inkcheck
inkcheck
面向 ink 故事的机械式 QA 工具。 编译检查、有界系统性分支探索、运行时错误复现路径,以及死内容检测——以独立 CLI 形式提供给作者和团队,并可选集成 CI 与 MCP。
智能体从这里开始 → SKILL.md —— 何时调用本工具、工作示例、MUST/MUST NOT 约定。家族契约:FAMILY.md。
inkcheck 是 QA 工具,不是写作工具。它不会生成、改写或发送任何一句散文。它的存在意义在于:让你写的故事可以被机械式地检查——用 ink 官方编译器编译、在明确限制内探索选择路径、并在玩家发现故障之前复现故障。
它使用 AI 吗?
不使用。inkcheck 本身不使用 AI、机器学习、LLM 或生成式模型来测试故事。它不会基于你的源码进行训练、推断散文改动、改写故事文本,也不会将故事内容发送给任何 AI 服务。
它的设计目标是让人类、CI 系统和可选的 AI 编码智能体都能驱动同一套机械式 QA 检查。实际的检查是确定性代码:官方 ink 编译器、ink 运行时、有界分支探索和结构化报告。
Related MCP server: RenForge MCP
两分钟上手
需要 Node.js 18 或更高版本:
npx -y inkcheck path/to/main.ink想在尝试自己的故事之前先看看失败路径报告?运行 两分钟合成演示。
产品承诺
Inkcheck 是面向 ink 故事的有界机械式 QA。它不证明大型故事中的每条路径都可用。它在明确限制内确定性地探索可达的故事状态,为发现的问题报告精确的复现路径,并说明覆盖为何是部分的、部分在哪里——让作者可以将其用作廉价、可重复的回归保险。
Inkcheck 不会证明大型交互式故事没有 bug。组合爆炸是真实存在的:循环、变量、随机性和宿主游戏代码可能产生比任何工具能穷尽访问的更多的可能状态。
承诺更窄也更有用:让机械式故事 QA 变得廉价、可重复、可操作。Inkcheck 在明确限制内遍历真实可达的选择状态,在运行不完整时明确告知,并将失败转化为修复后可再次运行的复现路径。如果今天发现了一条损坏的路径,明天同样的配置检查应该还能再次查找那条路径。
这是一个开源 QA 项目,因为这条边界很重要。如果报告过度声称、遗漏了明显模式、需要更好的遍历策略,或者在你能够安全分享的故事形态上失败,请提交 fixture 或 issue。路线图的目标是让部分覆盖更透明、更有价值,而不是假装部分覆盖变成了证明。
产品方向与自评分
Inkcheck 的未来价值计划来自一个可复现的混合方案:广泛的种子探测、系统化的局部检查、有界多样性搜索,以及针对门控、循环、断言和 storylet 资格条件的 Ink 感知专家。专家必须保持有界,并通过组合中新增的证据来争取更多工作,因为它们也可能成为预算陷阱。
同样的约定也适用于硬件。本地 CLI 和一次性 MCP 组合检查默认使用确定性的 1,024 状态实时试点,该试点保持小型、深度有界、作者前沿饱和的作业顺序执行,并且仅在开放且持续的前沿上激活有界工作器。每个试点状态都计入原始全局上限之下;搜索不会为了做决定而重启。匹配评估保留了精确证据,并将一次 5M 状态、深度 100 的 The Intercept 运行提升了 25.6%,而受限和托管作业则保留明确的顺序上限。参见并发评估。
维度 | 当前 | 10/10 方向 |
可操作、可重复的 QA | 8/10 | 在编辑/CI/智能体活动中保持稳定发现和精确重放 |
诚实的有界证据 | 8/10 | 事实、估计、限制、不确定性和证明始终分离 |
稳健的未知形态探索 | 6/10 | 广泛的跨家族价值,不依赖遍历或 fixture 过拟合 |
结构化专家优势 | 4/10 | 门控、循环、边界和枢纽由有界专家探针测试 |
每墙钟时间的随时价值 | 7/10 | 存在早期结果窗口和截止时间;首窗口大小调整仍固定 |
作者与智能体意图 | 8/10 | 安全不变量、目标、资源姿态和紧凑解释 |
已证实的泛化能力 | 4/10 | 预先声明的多项目语料库,包括真正的中/大型作品 |
这些是独立评分,不是平均值。高信任分无法抵消丢失的运行时错误。详细的产品与工程真相记分卡定义了每个 10/10 目标、当前证据、工程约束,以及每个史诗或发布时使用的重新评估协议。第一次完整的策略 v2 晋升评估将动态分配保持为实验性,而不是将混合证据变成发布声明。
Inkcheck 0.6 范围
Inkcheck 0.6 交付随时 QA 基础,但不声称拥有普遍更优的动态搜索策略。已建立的有界组合仍然是搜索默认。工作负载感知的并发可以在实时试点显示足够持续工作时左移结果;持久化活动可以返回、恢复并检查源绑定结果窗口;人类和智能体可以选择命名的时间/资源姿态;每个自动决策仍然可归因。长尾扩展、轮换和停止保持仅影子模式,因为三家族晋升门未能在足够广泛的范围内确立面向作者的价值,不足以使其上线。
这是一份已完成的发布契约,而不是声称更大的研究问题已解决。动态首窗口大小调整、紧凑大检查点、提供者归属成本、更广泛的智能体评估和有界专家探索器仍然是单独跟踪的路线图工作。未来的发布只有在检查过的证据通过相同的关键保留、重放、资源和诚实门之后,才可能替换固定组合。
Inkcheck 0.7:重要的规则
Inkcheck 0.7 使作者声明的不变量在托管检查器中与本地配置、CI 和 MCP 中一样成为一等公民。作者可以在 Web 流程中添加一条可选数值规则,例如 gold >= 0;该规则在运行前以通俗语言和生成的类型化配置显示,在普通有界 QA 期间被检查,如果违反则报告精确的重放见证。Web 流程检测声明的 Ink 变量以辅助选择,但服务器保持权威:未知变量、无效类型和不支持的语法在探索前即失败;临时规则配置随上传一起删除。智能体可以起草类型化规则提案,但不能静默授权。版本 0.7.2 还增加了私有 QA 证据锚点:已批准的运行时、断言或目标见证可以在编辑后无需再次搜索即可重新检查,而新的有界运行对于广泛验证仍然是必要的。
单独的断言导向专家保持选择加入和实验性。它不获得默认预算、不改变记分卡,也不声称更好的覆盖,直到通过其预注册的证据门。重要规则契约定义了两条边界。
智能体活动策略
MCP 智能体可以使用高级 quick、balanced、deep、overnight 或 campaign 模式启动持久化活动,而不是自行发明探索器权重。balanced 是新智能体的默认;fixed 保留显式的遗留控制。有界覆盖可以改变状态/窗口/时间/内存/磁盘/截止时间姿态、稀缺/均衡/丰富资源、首选价值(broad_qa、runtime_assertions、outcomes 或 approved_goals)、受保护的长尾工作,以及 ceilings 与 knee 停止。精确的基础窗口保持无断言/无目标且可恢复。受保护的长尾分配现在启动确定性的根启动组合子项,使用替代搜索种子和更深边界,同时保留精确的基础检查点。runtime_assertions 活动可以使用 add_assertions 添加已验证的断言窗口;approved_goals 活动可以使用 add_goal 添加已验证的目标。每个子项使用显式授权、保存单独的证据报告,并且仅获得活动新增的关键、意图、作者结或终止证据的信用。
第一次作者故事活动子项评估在 The Intercept 上发现了一个可信的陈旧变量审查线索和一个被拒绝的断言假设。其分阶段目标未命中,两个高预算子项在 5M 之前因内存停止,一个 500K 共享基础超过了持久检查点上限。这既是断言价值的希望,也是明确的警告:智能体编写的规则需要人工验证,专家需要探针到扩展的经济性,紧凑检查点是大型活动成为常规之前的必要条件。
匹配的独立长尾评估随后比较了增长中的共享前沿与受保护的根启动组合分区。在 5M Intercept 活动上,共享分支在 786,559 个总状态时因内存停止;九个独立子项以更低的峰值堆完成了全部 5M,并计入了 3,558 个活动新增终止变体,而共享分支为 407 个。它们没有发现新的关键问题、作者结或可见结局。这是资源高效多样性和可测量递减回报的证据,而不是普遍 QA 价值的声明。
随后的三家族 0.6 晋升门未晋升动态停止或扩展。Dog Ink Adventure 和 Heresy II 都在其 500K 基础产生可恢复检查点之前达到资源上限,因此没有长尾策略可以行动。在 The Intercept 上,独立分区以 1.40 GiB 峰值堆达到 4.66M 状态,而增长中的前沿在 787K 状态和 3.70 GiB 时停止;终止重发现从 34% 上升到 94%,没有新的关键问题、作者结或可见结果。Inkcheck 将这些建议保持为仅影子模式,并将动态首窗口大小调整视为更强的下一个产品需求。
每个结果窗口返回稳定的策略 ID、分配原因、测量的首选产出、吞吐量/资源证据、另一个窗口的不确定性标注经验范围、任何绑定约束,以及用于检查完整曲线或发现的报告 ID。紧凑检查还指明最新窗口的目的、分区和边际产出。knee 需要连续三个窗口没有首选产出,且不能消耗受保护探针。它仍然是对实际运行轨迹的有界观察,而不是声称故事已覆盖或后续发现不存在。参见活动策略契约和 MCP 结果窗口指南。
在独立子运行之后,紧凑决策还包含一个带版本的仅影子长尾建议:扩展同一家族、轮换到另一个分区,或在受保护下限之后停止。它使用所选偏好下的活动新值,报告每个状态和每秒的近期收益,对稀缺/均衡/充裕姿态要求逐步增加更多干探针,并暴露紧凑的选定值重新发现以及事实性的报告本地发现缺口。旧账本将这些信号标记为不可用。重新发现是与早期活动报告的身份重叠,而不是原始重复状态工作;扩大的缺口是观察结果,而非平台期证明。liveEffect: false 表示此证据尚不能改变分配。
人类无需学习其控制方式即可使用相同的持久策略:inkcheck campaign story.ink 运行均衡意图,而 --mode quick、deep 或 overnight 选择结果与时间姿态。它在工作进展时返回不可变的、绑定源的结果窗口,在截止时间或窗口间取消时保留最新的部分报告,并将技术状态/时间/内存/磁盘上限保留为专家覆盖项。结果窗口区分已花费的工作、可操作的收益、预测不确定性以及搜索是否可以继续。安静的发现间隔或观察到的拐点永远不会被描述为完整覆盖。
快速开始
需要 Node.js 18 或更高版本:
npx -y inkcheck path/to/main.ink无需全局安装。首次运行会下载固定的官方 ink 编译器,验证其 SHA-256 哈希,并在本地处理故事。
项目配置
当项目应为每个人类或代理会话使用相同的入口点和有界 CI 设置时,提交一个 inkcheck.yml:
schemaVersion: 1
entrypoint: story.ink
ci:
maxDepth: 100
maxStates: 1000000
goalMaxStates: 250000
seed: 1
storySeed: 1
search: portfolio
concurrency: auto
strict: true
assertions:
- id: gold_nonnegative
description: Gold never goes negative
when: always
condition:
left: { variable: gold }
operator: ">="
right: { literal: 0 }
goals:
- id: depleted_gold
description: Seek paths where the player runs out of gold
condition:
left: { variable: gold }
operator: "<="
right: { literal: 0 }运行 inkcheck validate-config 进行检查。从该目录开始,inkcheck 使用配置的入口点和默认值;显式 CLI 标志仍然优先。未知键会导致验证失败,因此不支持的对外行为和编辑策略字段不会显得已实现。已发布的契约是 config schema v1。
断言是类型化数据,绝不是 JavaScript 或任意 Ink 表达式。操作数是变量或标量字面量;比较使用 ==、!=、<、<=、> 或 >=,条件可以通过 all、any 和 not 组合。规则始终运行、在终止状态运行,或在进入命名结时运行。未知变量/结和无效的跨类型比较会在探索消耗其状态预算之前失败。违规总是导致 CI 失败,并包含观察到的值以及精确的索引重放见证。有界的干净运行仅表示“未观察到违规”;只有穷举运行才将该规则报告为已穷举验证。
目标使用相同的不可执行条件语法,但引导探索而不是使 CI 失败。一般探索始终获得完整的 maxStates 预算。在配置中设置 goalMaxStates 或在 CLI 上设置 --goal-states 以添加显式的确定性目标接近度切片;它默认为零,组合预算不得超过 100,000,000 个状态。当未请求额外切片时,目标仍会在普通探索期间被观察。达到的目标包含精确的选择索引;未达到则显示 not_reached_within_limits,除非穷举探索实际证明其不可达。报告分别暴露基线、目标和总预算,因此引导不能静默取代一般 QA 发现。参见 search experiments 中的比较证据。
对于后期复合依赖,用两个或更多有序的 stages 替换 condition。每个阶段使用相同的类型化语法。Inkcheck 寻找第一个未满足的累积里程碑,因此只有在状态也满足所有早期阶段的路径上才能到达后续阶段。未满足的先决条件使后续阶段保持 blocked_by_stage;它不会称它们为不可达。这第一个分阶段契约使用一个共享的额外目标预算,并从故事根确定性地重新开始,而不是序列化运行时检查点。
对于包含一个 .ink 文件的新项目,inkcheck init 会创建此配置。多文件项目必须使用 --entrypoint 指定根文件。inkcheck agent-kit --format codex 在需要时添加配置、固定的 GitHub Actions 示例、.inkcheck/ 工件忽略规则以及紧凑的版本匹配代理指令。这两个命令都是幂等的,并对每个目标进行预检;它们拒绝整个操作,而不是覆盖或部分修改现有的已编写文件。npm 工件还包含规范的 skills/inkcheck/SKILL.md、渐进式 Ink/工作流参考以及十个可执行的黄金练习。inkcheck capabilities --json 将此宣传为 features.bundledAgentSkill,并且仍然是已安装模式契约的权威。
--save-report 原子地将带版本的报告存储在 .inkcheck/reports/ 下,并返回其稳定的、由内容和入口点派生的 ID。后续会话可以使用 inkcheck artifacts list --json 和 inkcheck artifacts show <report-id> --json;重新打开时报告保存的证据相对于当前入口点是 current、stale 还是 path_changed。报告可能包含故事文本、变量和精确见证,因此代理工具包默认忽略它们。参见 local report artifacts 了解信任、隐私和兼容性契约。
长的基础共享运行也可以将精确的实时前沿本地持久化。以 --search=shared --no-min-repro --save-checkpoint 开始,然后稍后使用 inkcheck resume <checkpoint-id> --max-states N 继续;N 是更大的总授权,而不是额外的隐藏工作。inkcheck checkpoints list/show 报告有界元数据、持久压缩大小、存储编码和源新鲜度。新的检查点文件是流式 gzip 工件;旧的纯 schema-v1 JSON 仍然可读。检查点是私有的、原子的、绑定源/配置的、默认忽略的,并且有保留上限;它们可能包含已编写的文本和运行时状态。参见 local resumable checkpoints。共享遍历还暴露了一个有界的 resource/yield observability ledger,它将确定性逻辑核算与实时堆/RSS 观察分开。MCP 代理可以通过持久的 start_search / inspect_search / continue_search / cancel_search result windows 使用完全相同的基础。它们还可以使用 add_goal 进行显式的加法定向探针,该探针从故事根开始,并保持该精确的基础前沿不变。组合、共享变量、断言、定向前沿恢复和托管作业尚不使用此检查点契约。
托管检查器
该仓库现在包含一个自托管的 Web 界面,供不想使用终端的作者使用。托管模式临时上传授权的 .ink 源,提供 Quick(较早的 250K 状态结果)和 Balanced(更深的 1M 状态结果)意图,创建短期私有作业,流式传输实际工作、收益和不确定性信号,并在完成、取消或失败后删除临时作业目录。完成的托管检查返回绑定源的结果窗口身份和稳定的发现 ID。它不会公开报告,也不会在应用程序日志中保留故事文本。可选的第一方使用指标保留每日聚合计数以及保护隐私的近似每日唯一浏览器估计:不保留 IP、用户代理、浏览器令牌或访客配置文件。
本地 CLI 仍然是隐私优先选项,因为不会上传故事。参见 Hosted checker deployment 了解威胁模型、Docker 部署、操作限制以及当前低于 50 美元/月的预算。
它能捕获什么
编译错误和警告 — 损坏的转移、未解析的变量、松散结尾,带有文件和行号(通过 inklecate,官方编译器)
带有复现路径的运行时错误 — 触发除零、错误的外部调用或超出内容的确切选择序列,例如
repro: [Enter in darkness → Descend to the cellar]可能的非终止强制选择循环 — 当唯一可用的选择以相同的作者可见变量返回到相同的控制状态时,发出保守的审查警告;可选出口、随机行为、回合数、访问次数和 EXTERNAL 调用被有意排除
未访问的内容,已分类 — 在配置的限制内没有探索路径访问的结,每个结都通过入站转移扫描进行分类:“此处没有编写的转移点 — 可能是孤立内容”与“有入站转移 — 可能超出本次运行的限制”
不同的终止状态 — 带有到达每个状态的选择轨迹;不同的最终变量被保留为不同的结果
与替代方案对比
捕获语法错误 | 探索选择分支 | 发现未访问内容 | 崩溃的复现路径 | 在 CI 中运行 | |
| ✓ | — | — | — | ✓ |
手动试玩 | — | 仅你点击的内容 | 靠运气 | 如果你记得你的点击 | — |
Ink-Tester | ✓ | 随机重复运行 | 行覆盖 | 有限 | 手动/CLI |
inkcheck | ✓ | 系统化 + 种子随机,有界 | 结覆盖 | ✓ | ✓ |
编译器告诉你故事是有效的。点击浏览告诉你你碰巧点击的路径有效。Ink-Tester 重复采样随机通关并报告行级频率;而 inkcheck 则系统地遍历选择状态并返回简短的失败路径。关键区别在于可重复性:修复报告的路径后,相同的配置运行可以再次检查该路径。这些方法是互补的,尤其是对于具有随机性或引擎集成的故事。
示例
$ inkcheck examples/manor.ink
✓ compiled — 92 words, 7 knots, 6 choices
✓ explored 18050 states within limits (depth 100, 10000000 states, seed 1) — exhaustive (every reachable state visited) — 5 distinct terminal state(s)
terminal via [Enter in darkness → Search the study → Leave with your loot]: "You slip out the servant door, heavier by half a purse."
...
✗ 1 runtime error(s):
obj is null or undefined (at cellar.3)
repro: [Enter in darkness → Descend to the cellar] (found by dfs:last)
⚠ 1 knot(s) never visited on any explored path — unreached is not necessarily unreachable:
treasure_vault (manor.ink line 35) — no authored divert points here — possible orphan当运行被截断时,报告会指出实际限制它的界限 — 例如 ⚠ coverage is partial, not a proof — paths were cut at 30 choices deep; raise --max-depth to follow longer trails。深度和状态预算是不相关的轴:在 The Intercept 的本地运行中,将 --max-depth 从 30 提高到 100,在 1,000,000 状态预算下到达了更多后期故事内容,而 10 倍更大的预算在深度 30 时却没有。
编译或运行时错误时退出码非零。添加 --strict 也会在警告、未访问的结、截断或外部存根上失败,因此部分覆盖不能静默通过 CI。
故事不必很长就会超出默认预算。Inkle 发布的 The Intercept 被社区认为是一个相对较小的源文件,但 Inkcheck 在 5,000,000 个状态下仍报告其为部分覆盖:分支加上持久变量创建的可达状态图远大于可见选择数量所暗示的。耗尽是一个观察到的证明,而不是从源大小推断出的期望。有限值的故事原则上可能可穷举,但枚举不切实际;回合、随机或无界变量状态可能使语义图无界。有界运行在状态、深度、时间或内存中先到者处停止,并说明是哪一个。托管检查器将共享作业限制为 1,000,000 个状态;更大的作业(最高到 CLI 的 100M 上限)属于本地。参见 Performance and memory 了解规模指导。
在单次运行中,inkcheck 将其状态预算分配到互补的搜索遍(pass)上,而不是把一切都押在一种遍历顺序上。当前的 CLI 组合包括:最后选择优先、最先选择优先和由内向外(inside-out)的 DFS 切片;增加一个带种子的随机采样切片,用于变化确定性遍(deterministic passes)容易重复的早期选择前缀;增加一个前沿上限(frontier-capped)的多样性束(diversity beam),像 BFS 一样逐层推进,同时为每个变量签名谱系(variable-signature lineage)保留一个状态;然后保留一个小的广度优先切片以缩短复现路径。随机切片使用固定的默认种子,束(beam)根本不需要种子,因此运行在 CI 中保持可复现;每个报告的结局和运行时错误都会指明发现它的遍(和种子)。这通常能在相同的 --max-states 限制下发现更多结局和可达结(reachable knots),但它仍然是受限的 QA:截断的报告是有用的证据,而不是穷尽性的证明。
--search=shared 选择了一种实验性替代方案:深度、新颖性优先和带种子的视图从一个去重的前沿(deduplicated frontier)中提取,每个可达状态最多被扩展一次。当多种策略本来会重新发现同一状态时,这可以更高效地使用紧张的预算。JSON 遥测将待处理(pending)和活动(active)的检查点 JSON/变量、保留的见证祖先(witness ancestry)、去重和语义索引、前沿引用以及发现结果分开;它还报告已释放的祖先和陈旧视图压缩(stale-view compactions)。这些是确定性的、可核算的负载/结构估计,而不是精确的 V8 堆使用量。它还不是默认选项:某些早期选择结构可能仍然更青睐组合中独立的随机和束遍。
评估长期运行的共享作业的库使用者可以使用 exploreSharedResumable(...)。当预算剩余时,它返回一个绑定源(source-bound)、带版本号的 JSON 检查点,其中包含精确的实时基础共享前沿;后续调用会提高总授权(例如从 100k 提高到 1m)并继续,而不会重放前 100k。分割运行等价性已针对不间断运行进行了回归测试。这是一个引擎基础,还不是 CLI 持久化功能:检查点可能包含作者文本、变量、运行时状态和见证路径,而 schema v1 有意排除了断言、目标以及变量/目标感知的共享模式。参见 shared checkpoint schema v1。
--search=shared-variable 是一个更窄的实验,它将共享前沿选择的 12.5% 分配给通过不常见的变量快照或转换到达的状态。提升是有界的,深度、新颖性和带种子的视图仍然保持活动。它可能有助于机械驱动的故事图(storylet graphs),但并非在所有情况下都更好;已检入的 comparison table 同时包含收益和回退。
自适应组合(adaptive portfolio)仍然是通用默认选项。实验模式不会改变其权重或行为。Inkcheck 的 search strategy policy 定义了任何未来默认更改之前所需的基准广度和回归门禁。
有界搜索与随机采样
Inkcheck 并不是承诺访问非平凡故事中的每一个可能状态。分支、循环、变量、随机行为和宿主游戏集成可能使穷尽覆盖在物理上不切实际。它相对于随机采样的实际优势是可复现性:给定相同的故事和限制,inkcheck 系统地遍历选择图,为失败返回精确的选择路径,报告未访问结(unvisited-knot)线索,并明确说明运行何时是部分的。
随机采样仍然有用,特别是对于具有随机性或巨大状态空间的故事。将这两种方法视为互补:随机游玩可能偶然发现令人惊讶的路径,而 inkcheck 在声明的预算内提供确定性的、适合 CI 的证据。
在 The Intercept 的本地测试中,深度限制为 30,更高的预算发现了更多的终止状态,但仍然没有证明完全覆盖。计时来自一台本地开发机器,应视为规模证据,而不是通用基准:
状态预算 | 时间 | 不同的终止状态 | 运行时错误 | 未访问结 | 结果 |
50,000 | 9.4s | 7 | 0 | 9 | 截断 |
100,000 | 19.9s | 10 | 0 | 9 | 截断 |
500,000 | 100.2s | 17 | 0 | 8 | 截断 |
1,000,000 | 205.5s | 25 | 0 | 8 | 截断 |
这就是预期的解释:每次运行都测试真实可达的状态,并可能暴露真实的损坏路径,但截断的报告是关于访问了什么的证据,而不是关于一切是否可达或正确的证明。
性能与内存
默认预算是 10,000,000 个状态,上限是 100,000,000,因此了解大型运行的成本是值得的。两个资源限制了一次运行:时间和内存。小型或可穷尽的故事两者都不会触及——组合会在系统性遍证明可达空间完整的那一刻提前退出,因此 inkcheck small.ink 无论默认值如何,都会在其拥有的少量状态内完成。下面的数字只对大型、非穷尽的故事有意义。
时间大致随探索的状态数线性增长。在一台开发机器上,The Intercept 每百万状态运行约 200 秒(见上表),因此 10M 状态的运行需要几十分钟,100M 的运行需要数小时。本地 CLI 没有墙钟限制,因此对于 CI 或交互式使用,请将 --max-states 固定为你实际需要的覆盖范围,而不是依赖默认值——或者使用 --progress(在交互式终端中默认开启)运行默认值,以便你可以观察并中断。
内存是不同增长方式的各项之和,这也是上限很高而不是危险的原因:
增长的内容 | 扩展方式 | 备注 |
去重哈希集( | ~线性,每个不同状态约 200 字节 | 主导项。inkcheck 存储每个状态的哈希,而不是状态本身,这就是数百万状态可负担的原因。 |
DFS / 束前沿 | 平坦 | DFS 受深度限制;束有硬性前沿上限。两者都不会随预算增长。 |
随机采样 | 平坦(O(发现结果)) | 不保留去重结构。 |
BFS 复现缩短前沿 | 唯一的超线性风险 | 在深度大、循环少、分支多的故事上可能膨胀(一次研究运行排队了约 631K 个完整状态)。 |
实验性共享前沿 | 形状相关,可能线性 | 保留序列化的待处理检查点以及见证祖先。报告暴露组件高水位标记;可选的 |
由此得出两条实用经验法则:
预算堆,而不仅仅是状态。 作为最坏情况估计(无状态去重),每 10M 不同状态计划约 2 GB 堆。有循环的故事会大量去重并使用少得多的内存;低去重的故事接近最坏情况。因此,10M 状态运行的最坏情况(约 2 GB)接近 Node 的默认堆限制:循环密集的故事会远低于该限制,但大型低去重的故事即使在默认预算下也可能在完成前达到内存保护(memory guard)。100M 状态的运行超过正常的默认堆,除非你提高
--max-old-space-size,否则将在保护处停止。无论哪种方式,它都会以部分报告干净地停止——保护是使高上限可以安全指向的原因,而不是运行会完成的承诺。内存保护是真正的限制因素,而不是上限。 运行在 V8 堆的 85%(或你的
--max-memory)处干净地停止,并返回带有truncatedBy.memory的部分报告,而不是崩溃。因此设置--max-states 100000000并不鲁莽——在普通机器上,决定停止位置的是保护,而不是上限。要更进一步,给 Node 更多堆:NODE_OPTIONS=--max-old-space-size=8192 inkcheck big.ink --max-states 100000000。安全限制不是效率决策。 状态、时间和内存上限回答的是"这个作业可以走多远?"它们并不声称使用整台机器是有价值的,也不声称明显的平台期是完整的。0.6 研究路径测量组合新发现随时间的变化、吞吐量、恢复间隙、峰值 RSS 和保留前沿字节,以便未来的快速/平衡/深度策略可以选择有用的结果窗口,同时仍然保留长尾探测。固定限制仍然可用于 CI 和审计。
当一个故事太大而无法完成时,按影响顺序排列的杠杆:提高 --max-old-space-size(更多余量),传递 --no-min-repro(丢弃超线性 BFS 前沿),降低 --max-states(同时限制时间和内存),或者拆分故事并分别检查各部分。在实验性共享模式中,当待处理检查点队列本身需要更紧的界限时,设置 --max-frontier-memory 或 --max-frontier-states,并且只有在其报告显示有用证据继续到达时才提高该包络。每次运行后,nextRun 判定会指明限制性因素,以便你知道哪个杠杆适用。
已测量的 resource-safe deep-run evaluation 记录了保护在作者编写的 5M 上限作业上的行为,包括共享前沿待处理状态和序列化字节高水位证据。
MCP 服务器
用于处理 ink 故事的 AI 代理的工具:
工具或逻辑操作 | 功能 |
| 版本化模式、限制、搜索模式及显式功能可用性 |
| 仅源码项目映射:包含、形状、语义、外部项、knots、变量及静态条件门 |
| 结构化编译问题(严重性、文件、行) |
| 启动一个持久的精确共享搜索结果窗口并接收一个 bearer 能力 |
| 通过一个有界模式路由发现后搜索、活动、发现、重放、回归、断言、目标、取消及试玩操作 |
添加到 Claude Code:
claude mcp add inkcheck -- npx -y inkcheck mcp或添加到任何 MCP 客户端配置:
{
"mcpServers": {
"inkcheck": { "command": "npx", "args": ["-y", "inkcheck", "mcp"] }
}
}默认 MCP 配置文件暴露五个工具:inkcheck_capabilities、inspect_story、compile_story、start_search 和 inkcheck_workflow。这使新代理的引导上下文保持精简;capabilities 列出路由器的逻辑操作和请求字段。仅当客户端要求每个操作作为单独命名工具时,才设置 INKCHECK_MCP_PROFILE=full。
紧凑的代理循环是 inkcheck_capabilities -> inspect_story -> compile_story -> start_search -> 通过 inkcheck_workflow 路由发现/重放/回归操作 -> 修复 -> 编译并验证。结果窗口会话是默认的代理路径,因为它们持久、有界、分页且绑定源码。逻辑 start_campaign / continue_campaign 操作在相同的精确共享前沿上添加聚合策略和测量的支出/来源;普通 start_search / continue_search 保留显式的累积授权控制。调用是同步的,因此取消在返回的持久边界处是可信的,而不是窗口中途抢占。inspect_search 保持隐私最小化;add_goal 可以花费单独报告的定向预算而不削弱精确基础搜索,replay_witness 是返回一个当前转录、选择轨迹和变量状态的显式边界。对于运行时失败、断言违规和已批准的目标见证,在编辑前 pin_regression 并在之后 check_regression 无需另一次搜索运行即可重放一个精确的私有见证。pin 不是广泛的重新验证;在有意义的编辑后运行新的有界搜索。参见 QA 证据 pin、捆绑技能 和 MCP 结果窗口会话。
当作者或代理提出故事规则时,inkcheck_workflow 可以先运行 review_contract。该审查根据编译后的故事验证类型化断言和目标,盘点现有契约,要求作者批准,并默认推荐零定向预算的广泛 QA。它是只读的:不能编辑配置、花费搜索预算或静默提升目标探针。参见 代理定向 QA 契约。
CLI
inkcheck capabilities [--json]
inkcheck inspect <story.ink> [--json]
inkcheck <story.ink> [--max-depth N] [--max-states N] [--seed N] [--story-seed N] [--search=portfolio|shared|shared-variable] [--concurrency auto|N] [--max-frontier-states N] [--max-frontier-memory MB] [--auto] [--profile] [--next] [--no-min-repro] [--strict] [--save-report] [--save-checkpoint] [--progress=auto|human|ndjson|off] [--human|--json|--json-stream|--markdown]
inkcheck artifacts list [--json]
inkcheck artifacts show <report-id> [--json]
inkcheck artifacts findings <report-id> [--limit N] [--cursor C] [--json]
inkcheck artifacts finding <report-id> <finding-id> [--json]
inkcheck artifacts replay <report-id> <finding-id> [--json]
inkcheck artifacts delete <report-id> [--apply] [--json]
inkcheck artifacts prune --keep N [--apply] [--json]
inkcheck checkpoints list [--json]
inkcheck checkpoints show <checkpoint-id> [--json]
inkcheck resume <checkpoint-id> --max-states N [--json]
inkcheck mcp # start the MCP server on stdioinkcheck capabilities --json 让代理在依赖模式版本、限制、搜索模式和显式支持或不可用功能之前进行检查。inkcheck inspect story.ink --json 执行确定性的仅源码发现,无需编译或探索:它跟随项目本地包含并返回故事形状、语义、外部项、knots/函数、变量声明/读取/写入以及带事实赋值站点的静态条件门的有界映射。持久 MCP 会话可以将一个显式选择的受支持门转换为单独的 probe_gate 目标运行;该根启动的探针保留精确的基础前沿并报告见证或有界未命中。门检查和赋值站点是前提提示,绝不是可达性证明或对默认搜索分配的更改。参见 复合门检查契约 和 代理发现契约。
门探针评估协议 将普通共享搜索与同预算的显式探针在早期选择组合锁和可选的 500 万 The Intercept 单元上进行对比。它是关于进一步前提引导是否值得的证据,而不是覆盖或提升声明。
JSON 检查使用版本化的 报告模式。发现项具有稳定 ID 和规范化种类;结束和运行时错误见证同时携带人类可读的选择文本和从零开始的选择索引,因此重复标签可以通过 playtest_story 精确重放。信封记录 Inkcheck 版本、编译后的故事指纹、有效配置、绑定限制和仅观察的 shadowDecision,同时保留既定的 compile、stats、explore 和 nextRun 部分。
--concurrency auto 是本地组合的默认值。它设置四车道上限,而不是四个无条件工作线程:一个由内而外的 DFS 遍历最多运行 1,024 个状态,然后当故事耗尽、深度绑定、作者编写的 knots 已饱和、硬件只有一个核心或内存无法安全支持工作线程时,版本化分类器保持顺序执行。开放的持续前沿将该活动遍历保留在父进程中,而未触及的遍历在持久工作线程中开始。--concurrency 1 是硬性顺序退出选项;显式值 2-16 保留固定工作线程上限而不进行工作负载分类。共享搜索和附加目标运行自动保持顺序,除非显式请求了不兼容的固定值。
报告暴露 concurrencyMode、解析后的上限、激活策略/决策/原因、试点工作、有效工作线程、聚合堆计划和重复评估(生产策略为零)。工作线程失败保留最新完成的证据并报告 truncatedBy.worker;它绝不伪装成状态预算停止。托管部署传递自己的显式每作业上限,在生产容器上默认为一,真正的子取消清理临时上传。峰值 RSS 可能更高,因为 V8/运行时开销不是堆;分类器估计工作负载形状,而不是覆盖完整性。
MCP 默认使用 紧凑机器输出:检查上限为 16 KiB,编译、统计、一次性探索和结果窗口响应上限为 32 KiB。输出省略与有界搜索截断分开报告。完整的故事承载报告仅通过显式详情或下钻调用可用。
保存的报告支持有界发现下钻而无需加载完整报告。artifacts findings 默认返回最多 20 个隐私最小化摘要(最大 100)和报告绑定游标;摘要省略故事散文、变量、选择文本和见证路径。artifacts finding 获取一个完整的稳定发现。artifacts replay 重新编译保存的入口点并跟随该发现的索引选择及其保存的故事种子,但仅在工件新鲜度为 current 时;过期或移动的源码失败关闭。
报告存储是私有且有界的:一份报告最多可使用 256 MiB,一个项目中的所有报告最多可使用 1 GiB。超过任一上限的保存失败而不删除旧证据。artifacts delete 和 artifacts prune --keep N 默认预览,仅通过 --apply 变更;prune 为每个入口点保留最新的 N 份报告,每次调用最多删除 100 份。这种显式生命周期防止稳定报告 ID 仅仅因为另一个运行完成而消失。
维护者可以使用清单驱动的 影子策略评估器 跨独立预算运行比较影子建议。单独的 搜索提升基准 在检入的 20 家族语料库加上固定的同意安全作者项目层上运行匹配的基线/候选矩阵,报告资源观察和最差家族/项目损失,且从不宣布获胜者。第一次 作者项目评估 发现单元完成处具有同等性以及有意义的项目形状资源限制,而不是 policy-v2 优势。两个工具都不会将有界较大运行称为 oracle 或更改默认策略。
--max-depth 接受 1–1,000,--max-states 接受 1–100,000,000,默认预算为 10,000,000。这些硬性上限防止格式错误的自动化输入意外禁用探索边界。默认值刻意雄心勃勃,因为三件事使大预算安全而非鲁莽:完全可探索的故事在系统性遍历证明其穷尽时立即提前退出(因此小故事仍在少量状态内完成),内存保护在内存不足崩溃前干净停止,进度报告让你观察和中断长时间运行。因此,大型非穷尽故事将使用该预算——在 CI 中运行前参见 性能和内存,如果有限运行时比覆盖深度更重要,请在那里固定较小的 --max-states。
--max-states 是运行的总预算,而不是单个 DFS 遍历将花费所有状态的承诺。默认情况下,CLI 将该预算的大部分分配给选择树的三个互补 DFS 视图加上一个种子随机采样切片,并保留一个小广度优先切片用于更短的失败和结束重放路径。当广度优先缩短不如更广泛搜索重要时,使用 --no-min-repro 将该重放切片花费在 DFS 组合上。
--seed(默认 1)仅控制 Inkcheck 的随机采样搜索切片。--story-seed(默认 1)独立设置 Ink 的初始运行时 RNG 状态,用于 RANDOM() 和洗牌行为。两者都保持固定以获得可重复的 CI 和精确见证重放;更改 --seed 以采样不同的选择遍历,或故意更改 --story-seed 以执行另一个有效的故事随机性序列。作者编写的 SEED_RANDOM(...) 命令仍然生效,可以覆盖初始故事种子。Inkcheck 记录两个种子并在重放指令中携带 storySeed,但一次运行不会枚举每个可能的故事种子。每个发现的 foundBy 字段在 --json 输出中命名发现它的遍历,例如 dfs:last 或 random:seed=1。
--search=shared 选择实验性共享状态多前沿引擎;--search=portfolio 是未更改的默认值。共享模式对固定种子保持确定性,并仍然尊重深度、状态、内存、时间、进度和重放缩短控制。
--save-checkpoint 刻意比普通共享搜索更窄:它要求 --search=shared --no-min-repro 且同一命令中没有断言、目标、--auto、--next 或报告工件。当实时工作保留时,JSON 输出包含源码绑定的检查点 ID。inkcheck resume <id> --max-states N 要求源码和搜索绑定匹配,且 N 超过检查点先前的总授权;它自动保存下一代。完成和资源停止的搜索返回其报告而不发明可恢复的检查点。
--search=shared-variable 向共享搜索添加一个小变量稀有度前沿。它优先考虑观察到的罕见变量值并机械地更改;它不使用 AI、不理解故事含义或推断哪些值是可取的。
--max-frontier-states 和 --max-frontier-memory 是用于保留待处理检查点的可选共享搜索安全边界。两者均无默认值:Inkcheck 不会施加一个较低的通用前沿上限。如果显式边界生效,运行会保留其发现,报告 truncatedBy.frontier,并且不会将停止误标为状态预算耗尽。同样的控制也可通过 ci.maxFrontierStates / ci.maxFrontierMb 以及 MCP explore_story 输入使用。
--max-memory <mb> 限制整个运行在干净停止前可使用的堆内存上限。V8 堆内存不足中止无法事后捕获,因此 inkcheck 在探索期间监视内存,并在崩溃之前停止,保留迄今发现的所有内容,报告 truncatedBy.memory 并生成部分报告,而不是丢失整个运行。显式上限保留最多 25%(至多 1 GiB)用于最终结果构建和刷新;有界流同时报告完整边界和较低搜索水位线。默认上限为 V8 堆限制的 85%(该限制会遵循你设置的任何 NODE_OPTIONS=--max-old-space-size),因此大型运行在配置一般的硬件上会优雅降级而非崩溃;传入显式值可收紧或放宽该限制。内存停止时,nextRun 的判定为 investigate(提高 --max-old-space-size、降低 --max-states 或拆分故事)——绝不会是 broaden,因为更多预算只会更快撞墙。
--max-time <s> 是总墙钟时间对应项:截止时间在编译和源码扫描之前就开始计时,运行保留配额的 10%(最少 250 毫秒,最多 60 秒)用于合并保留的发现并刷新结果。探索以 truncatedBy.time 停止,而不是运行到状态预算。本地 CLI 没有默认时间限制。它适用于 CI 或任何需要有界运行时间但仍希望获得迄今发现的场景——与内存保护相同的优雅部分结果理念,应用于时间。托管 Web 检查器会自动设置此值,略低于其硬超时,因此缓慢的故事会返回部分报告而不是被终止。
--profile 打印故事的廉价静态形状概况——变量及其赋值位置、选择密度、最长 divert 路径——以及 inkcheck 会为该形状选择的深度限制和传递权重,而不运行任何探索。--auto 应用这些建议:当静态 divert 路径超出默认值时,它会提高 --max-depth(绝不会降低,且你的显式标志始终优先),并将概况的传递权重交给组合。对于主路径深达 40 个选择的故事,默认设置找不到任何内容,而 --auto 能到达结局并在约 111 个状态中证明故事穷尽。
交互式终端默认显示简洁的实时进度行:实际阶段、针对配置的工作预算探索的状态数、发现数和已用时间。--progress=human 为 CI 日志强制生成可读快照;--progress=ndjson 为代理和解析器写入带版本的事件;--progress=off 静默进度。这些百分比均不声称故事覆盖率。最终 stdout 报告仍具有权威性,进度从不包含故事散文、选择、变量或源码片段。
每份报告还携带一个 nextRun 判定——一个小的封闭词汇表(stop、deepen、broaden、reseed、investigate),由报告本身确定性计算得出,包含具体标志、引用其所用字段的理由以及有证据支持的预期收益。--next 会据此行动:检查后,inkcheck 应用推荐的升级并重新运行,最多三次,在 stop/investigate 判定、标志上限或升级运行未发现新内容(不动点)时停止。每次运行的轨迹会以 runs 形式出现在 --json 输出中;跳转叙述输出到 stderr,以保持机器输出干净。建议绝不会超过文档化的硬上限——当没有标志提升有证据支持时,判定降级为 investigate 并指向值得审查的节点。
GitHub Actions:
- uses: actions/setup-node@v4
with: { node-version: 22 }
- name: Check the story and publish a readable summary
shell: bash
run: |
set -o pipefail
npx -y inkcheck story/main.ink --strict --markdown --max-states 500000 | tee -a "$GITHUB_STEP_SUMMARY"该示例固定了 --max-states 500000,以便作业具有可预测的运行时间;默认预算为 10,000,000,大型非穷尽故事实际上会消耗该预算(参见性能与内存)。在 CI 中,当有界墙钟时间比最大覆盖率更重要时,请固定预算。
--strict 不仅会在警告和未访问节点时失败,还会在探索被截断或 EXTERNAL 函数必须被桩替换时失败。这防止部分检查被标记为绿色的“完整”徽章。
参见 InkJam QA 指南 获取面向作者的设置和报告解读帮助。
发现误导性结果?使用公共问题表单报告不正确或遗漏的结果、提供许可的最小夹具或请求可选的 QA 诊所检查。切勿将私有、受禁运或比赛限制的故事材料附加到公共问题中。
面向人类、CI 和代理
inkcheck 可由终端前的人类、CI 作业或可选的 AI 编码代理驱动。工具本身仍不使用 AI;代理只是 CLI 或 MCP 服务器的另一个调用者。
机器可读接口: 仓库根目录的
tool.json在一个文件中描述了 CLI 标志、MCP 工具、退出码以及--json/--json-stream输出形状。--json将整个报告作为单个 JSON 对象({ compile, stats, explore })输出到 stdout——解析该对象,而不是抓取美观输出。explore.passes保留有界的逐传递discoveryCurve(“此探索者发现了什么”)以及仅组合的portfolioMarginalCurve(“此探索者首先添加了什么”),区分精确终端、可见结果、运行时错误、断言、目标/阶段、节点和可比较的新颖性。摘要保留首次/最新发现状态和干差距事实,尽管进行了压缩。组合报告还包含按实际交错执行顺序的全程曲线;墙钟时间在进度事件中保持观察性。explore.schedule显示自适应轮次如何花费预算。带版本的shadowDecision显示未来随时策略会推荐什么及原因,包括受保护的逐传递下限和不确定性。它仅用于观察(applied: false):它不会改变今天的搜索,也不会声称有界覆盖是证明。--json-stream在保留发现时以 NDJSON 形式发出可重放的数值见证,然后发出有界的终端摘要,而不是物化完整的丰富报告或一个报告大小的 JSON 字符串。它目前要求--concurrency 1,支持一次探索运行(无--next或--profile),且不能与--save-report组合。保留的数值标签模式支持 InkBench 的中立评分,而不会将 oracle 变量暴露给搜索或流式输出每个普通结局。使用流进行长时间外部进程评估,其中部分证据必须跨越硬包装边界存活。参见有界证据流契约。--progress=ndjson在 stderr 上发出带版本的生命周期和工作进度事件,供代理或 CI 日志解析器使用。statesExplored / stateBudget是预算使用,而非故事覆盖率;最终 stdout 报告仍具有权威性。参见 NDJSON 进度契约。--human发出按错误、警告和注释分组的优先修复列表,包含可用的文件/行位置、运行时失败的选择路径以及每个发现的下一步。--markdown发出适合 GitHub Step Summary 的报告,供人类在 CI 中审查。确定性退出码:
0干净 ·1编译/运行时错误(或在--strict下,警告、未访问节点、截断或外部桩) ·2用法错误。基于退出码分支,不要 grep 文本。MCP:
claude mcp add inkcheck -- npx -y inkcheck mcp暴露紧凑的五工具代理配置文件。使用INKCHECK_MCP_PROFILE=full获取兼容性目录。循环: 编辑
.ink->compile_story->start_search-> 通过inkcheck_workflow路由下一个证据操作 -> 修复 -> 编译并验证。inkcheck 是对你生成或编辑的故事图的可重复机械检查;在返回之前使用它验证自己的工作。覆盖循环:
explore_story(以及 CLI--json)返回nextRun——根据其recommendation(stop/deepen/broaden/reseed/investigate)切换,并使用nextRun.flags重新运行,直到stop: true。或者让 CLI 驱动它:inkcheck story.ink --next。
仓库根目录的 llms.txt 是上述所有内容的紧凑、模型友好的摘要。
工作原理
编译使用
inklecate(官方编译器)——通过$INKLECATE_PATH查找,然后是PATH,首次运行时还会从固定的官方 ink 1.2.1 版本自动下载到~/.cache/inkcheck。下载的归档在解压前会对照固定的 SHA-256 哈希进行校验。故事使用-c编译,因此所有 knot 的访问都会被计数。探索在 inkjs(官方 JS 运行时移植版)中运行编译后的故事,复用池化的故事实例,使编译后的 JSON 每轮只解析一次,状态通过
LoadJson回退。Inkcheck 从--story-seed(默认 1)初始化故事随机性,然后在每个保存的分支中保留 Ink 的 RNG 状态;作者编写的SEED_RANDOM(...)在执行时仍然具有权威性。状态按内容哈希去重。INCLUDE会被跟随。CLI 使用有界、自适应的组合搜索。互补的遍历方式——最后选择优先、最先选择优先、由内向外 DFS、多样性优先的 beam 搜索,以及带种子的随机游走——在十个确定性轮次中交错运行。初始权重(大约 20/20/26/15/20%,或在
--auto下采用形状配置文件的建议)每轮都会重新分配,倾向于那些发现仍在增长的遍历方式,每个活跃遍历方式设有 8% 的小数下限。仅研究用的策略回放将该意图转化为可审计的累计整数服务,并将新近性归一化到各遍历方式观察到的执行窗口,而非全局状态计数。它需要三个窗口才能估计产出,信号在一个或两个测量窗口内未续期即过期,并且只允许针对续期的运行时/断言证据或明确的目标进展进行实验性分配叠加;广泛覆盖仍由既定调度器负责。生产调度器在完整推广语料通过之前保持不变。这些遍历方式是互补的:DFS 排序系统地穷尽子树,beam 搜索在硬前沿上限内将预算分散到可变状态谱系中,随机游走则对每个选择点重新掷骰,使早期选择组合得到采样而非重复。发现合并为一份报告,每条都标注了发现它的遍历方式,执行的调度出现在--json输出中。感知工作负载的
--concurrency auto是本地组合的默认设置。其实时的 1,024 状态由内向外 DFS 试点成为正常第一轮自适应的前缀,然后要么顺序继续,要么在有界持久工作进程中与未触及的遍历方式重叠。如果在该试点期间时间或内存受限——或截止时间在任何工作进程初始化之前到达——有效的试点结果将作为明确标记为资源截断的部分报告返回,绝不会被误标为状态预算耗尽。80 单元 100K 门保留了精确的发现、证明和自适应调度,仅两次开放前沿激活;匹配的 5M The Intercept 深度 30/深度 100 门保留了精确证据,拒绝了深度受限任务,并将持续任务从 657.7 秒改进到 489.0 秒。每个状态仍处于一个上限之内,重复的试点评估为零。显式1保留顺序执行;显式 2-16 上限保留固定并发。参见并发评估。实验性
--search=shared保持一个全局状态身份,并通过深度、新颖性和带种子的前沿视图暴露待处理工作。任何视图选择的状态只展开一次;展开的检查点 JSON 立即释放,紧凑的父链接仅在待处理后代需要精确重放路径时存活,过期的视图 ID 会定期压缩。报告暴露组件核算和可选的显式检查点信封。变量状态和变量转换的稀有性作为评估遥测记录。实验性
--search=shared-variable将每八个共享前沿选择中的一个替换为变量稀有性视图。其得分结合了目标变量快照的观测频率和该边上最罕见的变化;它不能消耗超过其固定份额,因此图新颖性、深度和带种子的探索仍然得到体现。一旦任何系统性遍历在未触及限制的情况下访问了每个可达状态,整个组合就会停止:任何进一步的状态都是冗余的。一个小的、可完全探索的故事在默认的 10,000,000 状态预算下仍然只在其实际拥有的少数几个状态中完成——当故事可穷尽时,大的默认值不产生任何成本。
beam 遍历具体回答了"beam 应该优化什么":幸存者按变量签名组轮询选择(多样性优先),组内按新颖性排序——新访问的 knot,然后是新的变量签名,再是新的可选选择集。它在没有种子的情况下是确定性的,并且每当它不得不剪枝一个可达状态时,它会将运行报告为截断,因此 beam 永远不会静默声称完全覆盖。
除非使用
--no-min-repro跳过,CLI 会保留约 10% 的请求--max-states预算用于广度优先的再现缩短切片。BFS 在可能的情况下通过更短的选择轨迹到达共享发现,并可能贡献额外的浅层发现。边界(
--max-depth、--max-states)控制最坏情况的组合爆炸;报告在截断时会明确说明。
覆盖限制
探索是有界的。截断的报告是关于已访问状态的证据,而不是关于整个故事的证明。
报告说明其运行所依据的限制(深度、状态预算、搜索种子和故事种子),并且在截断时说明是哪个限制实际切断了覆盖(
--json中的truncatedBy,包括memory),并针对应提高哪个标志给出针对性建议。会耗尽内存的大型运行会干净地停止并返回部分报告(
truncatedBy.memory)而不是崩溃——内存占用主要由去重哈希集(与不同状态数近似线性)以及深度循环较少的故事上的广度优先再现前沿主导,因此当故事太大无法完成时,--no-min-repro和更紧的--max-states是可用手段。小故事通常得到相反的保证:当系统性遍历在未触及限制的情况下访问了每个可达状态时,报告会说明(
exhaustive),采样切片预算耗尽不再算作截断。EXTERNAL函数被桩化为零,因为宿主游戏不可用。报告会点名每个桩;严格模式会失败而不是声称完全覆盖。随机行为对报告的故事种子是可重复的,但一次运行不会枚举每个可能的故事种子。当结果频率很重要时,应有意变化
--story-seed并保持人工试玩在循环中。未访问的 knot 可能是有意休眠的、由引擎进入的,或不可达的。入站 divert 分类将可能的孤立内容与可能受限制的内容区分开来,但它是审查提示,而非自动删除指令。
路线图
路线图由产品和工程真相记分卡管理。每个史诗都应改善测量价值,而不削弱有界覆盖的诚实性、关键证据保留、确定性重放或资源上限。
覆盖透明度:更清晰的截断、深度限制、已访问结局、跳过的搜索空间以及已探索和未探索内容的报告。
报告质量:更好的源位置、更短的再现路径、稳定的问题身份,以及更清晰的运行时错误、未访问 knot 和覆盖限制分组。
作者定义的故事断言:确定性项目规则,如"黄金永不为负"、"生命值永不超过最大值"或"结局前必须设置所需变量"。
目标导向的变量搜索:让作者和代理在保留受保护的一般搜索预算和精确的有界覆盖语言的同时寻求已批准的状态。
可选托管 AI 目标助手:一个一流的、明确启用的人类界面,帮助非技术作者提出变量目标和断言以供批准,然后将所有执行和验证委托给 Inkcheck 的确定性非 AI 引擎。提供商、同意、源共享、保留、成本和禁用控制必须明确;生成的规则永远不会被静默信任或应用。
再现持久化:记住已知的失败路径,并确保未来的运行即使遍历策略改进也持续检查它们。
紧凑的活动检查点:保留和恢复有用的大型故事前沿,而不让检查点工件主导内存或磁盘,并在序列化限制之前降级为不可变的部分报告。
公共兼容性夹具:用于回归测试、性能比较和建立信任的同意安全示例和合成边缘案例。
代理就绪:可执行的代理就绪基准固定了无隐藏提示协议、确定性运行时/断言夹具、引导/工具/参考/安全/证明目标、机器评分器,以及独立的工具/技能/模型/环境归因。来自不同代理实现的两个通过的观察运行仍然是发布门禁(#67)。
搜索推广机制:在任何实验性策略可以改变默认值之前,跨结构族、预算、深度和种子的广泛、预先声明的记分卡。
有界专家搜索:检测机械形状并为复合门、循环/计数器、storylet 资格、断言边界和行为前沿多样性派遣小型专家探针(#107-#112)。专家通过组合新增价值赢得扩展,并保留受保护的一般/长尾工作。
大型故事性能控制:快速、标准和深度检查预设,具有更清晰的时间/覆盖权衡。
结构 lint 检查:可选的缺失标签、不一致的标签模式或项目特定元数据约定检查。
许可证
MIT
Available Tools
5 toolscompile_storyA
Compile an .ink file with inklecate and return structured issues (errors, warnings, TODOs) with file and line numbers. The authoritative syntax/structure check — run this after any edit to an .ink file.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to the root .ink file | |
| detail | No | Response detail (default standard); full returns every compile issue | |
| findingLimit | No | Maximum compile issue summaries in standard detail (default 20) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses output format (structured issues with file/line numbers) but omits potential side effects, permission requirements, or error handling. Adequate but not comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences deliver purpose and usage concisely. No filler; each sentence adds critical information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers core purpose and usage. Lacks detail on output structure and parameter effects on results, but sufficient for a compile tool with clear return type.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline 3 applies. Description adds no extra meaning beyond schema for file, detail, or findingLimit parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it compiles .ink files with inklecate and returns structured issues. Distinguishes from siblings by calling itself 'authoritative syntax/structure check', differentiating from inspection or workflow tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises running after any .ink file edit, giving clear when-to-use context. Does not exclude alternatives or mention sibling tools, but usage direction is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inkcheck_capabilitiesA
Return Inkcheck's versioned schemas, limits, search modes, and explicit supported/unsupported feature flags. Call this before relying on optional functionality.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It implies a safe read operation but does not explicitly state non-destructiveness or other behavioral traits like rate limits or idempotency. The description is minimal but adequate for a simple introspection tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no wasted words. The key action and usage advice are front-loaded. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters, no output schema, and a simple purpose, the description fully covers what the tool returns and when to use it. No gaps remain for an agent to understand its role.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and schema description coverage is 100% (empty schema). Per guidelines, baseline is 4. The description does not need to add parameter info since none exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool returns 'Inkcheck's versioned schemas, limits, search modes, and explicit supported/unsupported feature flags'. The verb 'Return' and specific resource are precise. It effectively distinguishes from sibling tools which focus on story operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises 'Call this before relying on optional functionality', providing clear context for when to use. However, it does not mention when not to use or list alternatives explicitly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inkcheck_workflowC
Run one post-discovery Inkcheck operation through the compact agent surface. Call inkcheck_capabilities first for required/optional fields, then pass the exact operation and request object.
| Name | Required | Description | Default |
|---|---|---|---|
| request | Yes | Operation input fields listed by inkcheck_capabilities.mcp.workflowOperations | |
| operation | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does not disclose any behavioral traits such as mutability, idempotency, side effects, or error behavior, leaving the agent uninformed about consequences.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise with two front-loaded sentences. Every word adds value, no redundancy. It efficiently communicates the core purpose and a key usage instruction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of 13 enumerated operations and a nested request object, plus no output schema or annotations, the description is inadequate. It fails to explain return values, operation semantics, or error scenarios, leaving significant gaps for the agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50%, requiring compensation. The description merely reiterates 'pass the exact operation and request object' without adding meaning beyond the schema. It does not explain the purpose or constraints of the request object or operation enum values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool runs 'one post-discovery Inkcheck operation', providing a specific verb and resource. However, it does not explicitly distinguish from sibling tools like compile_story or inspect_story, though the unique operation set implies differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description instructs to call 'inkcheck_capabilities first for required/optional fields', which is a clear prerequisite. But it provides no when-to-use guidance, exclusions, or alternatives among sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspect_storyA
Inspect an Ink project from source without compiling or exploring it. Returns a bounded project map with includes, shape, semantics, externals, knots, variables, and the recommended next operation.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to the root .ink file | |
| limit | No | Section page size (default 50, max 100) | |
| cursor | No | Source-bound cursor returned by an earlier page of the same section | |
| section | No | Optional inventory section for stable paged drill-down; omit for the bounded overview |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden. It discloses that the tool is read-only ('without compiling or exploring') and lists the returned fields. It does not cover permissions or rate limits, but for a read-only inspection tool, the transparency is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: two sentences. The first clearly states the action and caveats, the second lists the return fields. No unnecessary words, and key info is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Considering the tool has 4 parameters with full schema descriptions, no output schema, and no annotations, the description explains the return value comprehensively (listing 7 components) and how to get an overview vs. drill-down. It is largely complete for the tool's purpose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (all 4 parameters have descriptions), so baseline is 3. The description adds value by relating the 'section' parameter to 'bounded overview', and implies that omitting section gives an overview. This extra context elevates the score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'inspect' and clearly identifies the resource as an 'Ink project from source'. It distinguishes itself from siblings like compile_story by explicitly stating 'without compiling or exploring it', making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool (for inspection before compiling/exploring) and mentions 'recommended next operation', but does not explicitly contrast with each sibling or state when not to use it. The guidance is clear but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_searchB
Start one durable exact shared-search result window. Returns an opaque bearer capability plus bounded findings and a source-bound checkpoint when work remains. This call runs synchronously until the window boundary; it does not create a background job.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to the root .ink file | |
| seed | No | Seed for the reproducible shared frontier (default 1) | |
| maxDepth | No | Max choices deep to explore (default 100) | |
| maxStates | No | Total state grant for the first window (default 1000000, max 5000000) | |
| storySeed | No | Initial Ink runtime RNG seed (default 1) | |
| findingLimit | No | Maximum privacy-minimal saved finding summaries to return (default 20) | |
| maxFrontierMb | No | Maximum pending checkpoint payload in MiB (default unlimited) | |
| maxFrontierStates | No | Maximum pending checkpoints retained (default unlimited) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must fully disclose behavioral traits. It states the return value (opaque bearer capability, bounded findings, checkpoint) and synchronous nature, but omits side effects, permissions, error conditions, or state changes. More detail is needed for safe invocation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise with two sentences, front-loaded with the core action and return values. Every sentence adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 8 parameters and no output schema, the description gives a high-level overview but lacks detail on return value structure, prerequisites (e.g., valid file), and workflow (e.g., how to use the returned capability). It is adequate but not complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the description adds no additional parameter meaning. Per guidelines, baseline is 3. The description does not explain parameter interplay or usage beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Start') and resource ('one durable exact shared-search result window'), distinguishing it from sibling tools that focus on compilation, capabilities, workflow, and inspection. The term 'shared-search' adds specificity but could be clearer.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies use for searching, but offers no explicit guidance on when to use this tool vs alternatives. It mentions synchronous execution but does not compare with sibling tools. The context is moderately clear for an agent to infer usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
7 tool updates
v0.6.0- Changed
compile_story2 fields changed- added
Input schema / properties / detailAdded value: +{ + "description": "Response detail (default standard); full returns every compile issue", + "enum": [ + "summary", + "standard", + "full" + ], + "type": "string" +} - added
Input schema / properties / findingLimitAdded value: +{ + "description": "Maximum compile issue summaries in standard detail (default 20)", + "maximum": 100, + "minimum": 1, + "type": "integer" +}
- Removed
explore_story - Added
inkcheck_workflow - Changed
inspect_story3 fields changed- added
Input schema / properties / cursorAdded value: +{ + "description": "Source-bound cursor returned by an earlier page of the same section", + "type": "string" +} - added
Input schema / properties / limitAdded value: +{ + "description": "Section page size (default 50, max 100)", + "maximum": 100, + "minimum": 1, + "type": "integer" +} - added
Input schema / properties / sectionAdded value: +{ + "description": "Optional inventory section for stable paged drill-down; omit for the bounded overview", + "enum": [ + "includes", + "externals", + "knots", + "variables" + ], + "type": "string" +}
- Removed
playtest_story - Added
start_search - Removed
story_stats
6 tool updates
v0.5.1- First observed
compile_story - First observed
explore_story - First observed
inkcheck_capabilities - First observed
inspect_story - First observed
playtest_story - First observed
story_stats
TDQS
Scored across 5 tools
Each tool has a clearly distinct purpose: compile checks syntax, inspect returns project map, capabilities lists version info, workflow runs operations, search initiates a search. No overlap or ambiguity.
Most tools follow a verb_noun pattern (compile_story, inspect_story, start_search). The 'inkcheck_' prefix on two tools (inkcheck_capabilities, inkcheck_workflow) is a minor inconsistency but still predictable.
Five tools is well-scoped for a schema/compilation server. Each tool provides a necessary operation without redundancy or bloat.
The tool set covers compilation, inspection, capabilities discovery, and search. A tool for managing or closing search results might be missing, but the core workflow is complete.
Maintenance
Related MCP Connectors
- mcpOAuthco.aistoryhub
Remote MCP server for AIStoryHub: stories, chapters, story bible, Voiceprints, AI generation.
Official remote MCP server for Archivist AI TTRPG campaign memory: characters, sessions, and more.
MCP Server for Slima - AI Writing IDE for Novel Authors with AI Beta Reader.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal E…
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server for automated Godot 4 game testing. Enables launching games, capturing errors, and verifying changes from Claude Code or any MCP client.1MIT
- AlicenseCqualityBmaintenanceAn MCP server for Ren'Py project tooling that enables AI agents to inspect game state, evaluate expressions, read/write variables, and capture screenshots from running Ren'Py games.54220 PyPI11MIT
- AlicenseNot gradedqualityDmaintenanceA universal AI-powered testing server built on the Model Context Protocol (MCP). Allows AI agents to inspect, execute, test, monitor, debug, and report on software projects.3GNU Lesser General Public v2.1 only
- AlicenseCqualityDmaintenance通用游戏叙事引擎 MCP,提供一致性校验、动态运行、Meta 伏笔、Playthrough 对比及 Ink/Yarn 导出等功能。68MIT