@abelxiaoxing/cadence 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +58 -4
  2. package/agents/design-explorer.md +17 -11
  3. package/agents/diagnosis-worker.md +9 -1
  4. package/agents/implementation-worker.md +3 -1
  5. package/config/plan-draft.example.json +122 -0
  6. package/config/plan-draft.multiple-tasks.example.json +345 -0
  7. package/package.json +5 -3
  8. package/prompts/abel-design.md +93 -44
  9. package/src/activity-contracts.ts +82 -0
  10. package/src/candidate-artifact.ts +143 -0
  11. package/src/candidate-patch.ts +31 -11
  12. package/src/candidate-workspace.ts +74 -0
  13. package/src/change-contract-schema.ts +191 -0
  14. package/src/change-contract.ts +5 -0
  15. package/src/change-verification.ts +896 -0
  16. package/src/child-model.ts +129 -0
  17. package/src/child-session.ts +293 -326
  18. package/src/contracts.ts +184 -76
  19. package/src/delivery-compiler.ts +103 -120
  20. package/src/delivery-revision.ts +42 -0
  21. package/src/design-control.ts +113 -4
  22. package/src/design-diagnostics.ts +150 -0
  23. package/src/durable-contracts.ts +210 -0
  24. package/src/durable-workflow.ts +148 -3570
  25. package/src/evidence-draft.ts +122 -0
  26. package/src/implement-graph.ts +3 -0
  27. package/src/implement-plan.ts +70 -0
  28. package/src/index.ts +59 -522
  29. package/src/model-source.ts +22 -0
  30. package/src/package-candidate.ts +224 -0
  31. package/src/package-workflow.ts +253 -0
  32. package/src/packet-runtime.ts +27 -48
  33. package/src/parent-provider.ts +86 -198
  34. package/src/phase-execution.ts +2248 -0
  35. package/src/pi-adapter.ts +19 -0
  36. package/src/plan-draft-summary.ts +146 -0
  37. package/src/plan-draft.ts +493 -0
  38. package/src/subagent-activity.ts +32 -66
  39. package/src/submit-tool.ts +20 -59
  40. package/src/transport-budget.ts +32 -0
  41. package/src/worker-broker.ts +37 -57
  42. package/src/workflow-policy.ts +14 -53
  43. package/src/workflow-recovery-policy.ts +95 -0
  44. package/src/workflow-scheduling.ts +105 -0
  45. package/src/workflow-state-machine.ts +105 -497
  46. package/src/workflow-status.ts +384 -0
  47. package/src/workspace-io-worker.mjs +7 -0
  48. package/src/empty-resource-loader.ts +0 -38
  49. package/src/parent-payload-bridge.ts +0 -523
package/README.md CHANGED
@@ -26,6 +26,14 @@ Implement 只暴露 `start`、`status`、`resume`、`rebind`、`cancel` 和 `dis
26
26
  Design 从第一步起统一使用 `action: "design"`:新需求通过 `start(requirement)` 进入,已有 change 通过 `start(change)` 进入,后续只携带返回的 `runId`。
27
27
  需求、决策合同与 Gate A 合同由控制面规范化并计算哈希,调用方无需 SHA-256 工具;Gate B 自动绑定当前已编译 canonical plan,原始瞬时文本不会写入 durable journal。
28
28
  `validate-plan-draft` 可在 `compile-plan` 前只读运行同一套编译检查,并以结构化 `taskId` / phase / field / verification 诊断定位问题;Design finalization 的安全诊断码也会进入错误详情与可展开 TUI,而不再只显示统一失败标题。
29
+ 随包提供的 [单任务计划示例](config/plan-draft.example.json) 展示精简 PlanDraft 和结构化 Gate A 合同;按实际仓库替换示例中的路径、证据与验证命令。
30
+ 草稿可省略 `tracking`、阶段 `verificationInputs` 和现有测试的 `disposition`,编译器按任务、验证契约和已声明产物生成这些机械字段;已批准的 `changeContract` 由控制面继承,无需重复填写。
31
+ 原子验证命令可放在 `verificationDefinitions` 中,用 `{ "use": "name" }` 在各验证义务引用;Red 的 `expectedFailure` 仍需明确填写。
32
+ 内联原子验证也可省略 `id` / `classification`;任务公共 `read` 与阶段读取合并,固定 baseline/repair 保护字段由编译器补齐,恢复次数和 AGENTS 影响仍需作者明确选择。
33
+ [多任务示例](config/plan-draft.multiple-tasks.example.json) 保留显式依赖和产物 producer;ordered steps 仍使用完整内联合同。
34
+ `validate-plan-draft` 返回有界的最终权限、验证用途、恢复次数和实际派生来源摘要;摘要不充当批准或封存证明。
35
+ 推导有歧义时拒绝编译,显式错误仍会报错;代码不会据此扩大路径、依赖或产物权限,封存计划保持完整、严格的结构。
36
+ 预检集中返回不同任务的独立结构错误,并提供字段位置、期望/实际路径和修正提示;工具反馈与 TUI 共用有界脱敏投影。
29
37
  Design status 将可调用的 `legalOperations` 与顶层 `packetActions` 分开;显式退出只能发送 `{"action":"finish"}`,不能伪装成 `operation: "finish"`。
30
38
 
31
39
  普通 artifact、错误 Red、transport、environment、stale、conflict、baseline 与验证失败都留在同一 Implement run 中恢复。
@@ -56,9 +64,9 @@ Design 完成主要决策后,Implement 中的新实施选择默认由父模型
56
64
  增量修订或用户主动选择的 Design 完成后,新的 Implement 上下文都能本地发现并校验交付,继续同一 run。
57
65
 
58
66
  交互式 TUI、print、JSON 和 RPC 都保留 durable semantic state;父模型有自动继续动作时,TUI 显示 recovering,不把内部待编译状态显示成用户待确认,也不提示用户手动 resume。
59
- queued、connecting、waiting-first-response、running、validating、retrying、verifying、paused、approval-needed、applying 和 recovering 都不是完成;operation-cancelled 表示本次操作取消但 run 仍可恢复,discarded 与 rejected 是非成功终态。
67
+ queued、preparing、waiting-first-response、running、validating、retrying、verifying、paused、approval-needed、applying 和 recovering 都不是完成;operation-cancelled 表示本次操作取消但 run 仍可恢复,discarded 与 rejected 是非成功终态。
60
68
  只有最终 apply 与 post-apply verification 提交后的 `completed` 才显示成功。
61
- Design finalization、Implement 终态、Diagnose/显式 `finish` 或 session shutdown 会清除 active stage 与 parent bridge;Design 还会恢复进入前的精确父工具集合,其他阶段只撤下 `abel_dispatch`。
69
+ Design finalization、Implement 终态、Diagnose/显式 `finish` 或 session shutdown 会清除 active stage 与私有子执行状态;Design 还会恢复进入前的精确父工具集合,其他阶段只撤下 `abel_dispatch`。
62
70
  Gate 等待和可恢复暂停保持激活以接收直接后续操作。
63
71
 
64
72
  私有 journal、artifact 与 change workspace 位于 consumer repository 之外的 owner-private state root。
@@ -69,8 +77,15 @@ Gate 等待和可恢复暂停保持激活以接收直接后续操作。
69
77
 
70
78
  扩展入口负责宿主生命周期与服务装配,交付加载和验证适配器分别由独立模块负责。
71
79
  工作流入口保留原有导出,状态机仍是唯一状态转换权威;执行服务通过类型化接口返回事实。
80
+ 状态机读取运行与预算事实,独立的 `workflow-status.ts` 纯函数生成状态、阻塞批次及继续动作,不访问存储或启动执行。
81
+ 普通阶段和修复阶段共用 `candidate-artifact.ts` 校验、封存候选;恢复旧候选仍按当前批准路径检查,调用方分别处理普通越界和修复权限扩展。
72
82
  测试检查模块依赖无环,以及子会话无法导入主工作区应用和 run 状态权限。
73
83
 
84
+ Implement 父模型属于受信任的宿主编排层,保留原有工具以调查和修复已授权的环境问题;产品修改应通过控制面完成。
85
+ 子 Worker 和控制面执行路径有代码边界;父模型直接使用宿主工具不经过这些路径,阶段指令约束其行为。
86
+ 只有 Design 会收紧父工具。
87
+ 结构化验收固定验证义务,目标是否被充分覆盖仍取决于验收测试的质量。
88
+
74
89
  新身份统一采用 UTF-16 码元排序,不依赖宿主语言环境。
75
90
  旧 workspace manifest 按已保存的条目顺序验证原身份;已绑定批准证明的历史交付可保留原有集合顺序,仍需验证原始字节哈希和私有批准事实。
76
91
  普通交付解析保持严格规范化。
@@ -117,7 +132,8 @@ npm install -g @abelxiaoxing/cadence
117
132
  - **本地包目录(local package directory)** — 将 Pi 指向本仓库的绝对路径或相对路径(absolute or relative path,例如 `./cadence`),Pi 发现同样的资源。
118
133
  - **已安装 tarball 目录(installed tarball directory)** — 运行 `bun pm pack --destination <tmp>` 生成真实 tarball(.tgz),安装或解压到隔离目录后指向该目录;tarball 文件本身永远不会被当作本地包传给 Pi。
119
134
 
120
- 本包要求 Node.js `>=22.13.0`,以使用稳定可用的内置 `node:sqlite`;不从参考仓库源安装,也不维护 Pi 主机版本兼容矩阵。
135
+ 本包要求 Node.js `>=22.13.0`,以使用稳定可用的内置 `node:sqlite`;不从参考仓库源安装。
136
+ Pi 相关 peer 依赖使用 `*`,不限制宿主 Pi 的版本;开发依赖的固定版本仅用于仓库构建与测试。
121
137
 
122
138
  ## OpenSpec 启动与平台范围
123
139
 
@@ -169,6 +185,20 @@ bun run test:target test/openspec-cli.test.ts test/design-delivery.integration.t
169
185
  inherited route 声明的能力会与当前父模型真实能力取交集,不能通过夸大的配置绕过 admission。
170
186
  Implement 保留 16,000 context / 8,000 output 的最低容量要求;任务复杂度估算只影响自动选择的优先级,满足最低要求的 route 仍可作为 fallback 或显式 rebind。
171
187
  transport 与 malformed structural result 都只在声明的 route 集合内做有界 failover;优先选择达到容量估算的 route,同一优先级保持声明顺序,只有一个 route 时会原地重试一次。
188
+
189
+ 子任务由 Cadence 自己维护模型/工具循环,通过 `pi-ai` 公开接口请求完整响应,不创建 Pi `AgentSession`、覆盖 Agent 钩子或扫描宿主事件历史决定终止。
190
+ 模型流事件只用于进度与完整响应适配;只有正常完整响应的工具调用可以执行,错误、截断或取消不得提交产物。
191
+ 继承路由快照当前有效 Provider、模型及每次 attempt 新鲜解析的认证,不修改父 Provider 注册表,也不要求父请求预热。
192
+ Provider 自身的流式实现和模型配置仍然生效;宿主 session 的 `before_provider_request`/`onPayload` 不会自动移植到子任务。
193
+ 需要通用请求定制时,应使用明确配置的 Provider 实现或 custom route;子请求使用自己的 `low` reasoning 请求,最终由模型映射解释。
194
+ 输出上限沿用声明的模型/Provider 合同,不再隐式删除 Responses 的 `max_output_tokens`。
195
+
196
+ 子 Agent 的 evidence 提交使用精简草稿:工具绑定省略的身份,补齐未提供的提示性字段,然后按严格内部结果合同校验。
197
+ 引用、约束、风险和未决问题仍须显式提供;省略提示不等于已验证的“没有影响”,也不增加授权。
198
+ 一次被拒绝的提交可在原会话纠正一次;只有正常以文字结束且从未提交时,才额外提示补交一次。
199
+ 补交沿用原工具权限、总时限、取消和用量统计,不重新调查,不把文字直接当作交付;传输错误、截断和取消不触发补交。
200
+ 合法提交可附带简短文字,但接受后不得重复提交或覆盖结果。
201
+
172
202
  相同 pause 的安全指纹与重复计数通过 `status` 暴露,凭据、URL 和原始输出仍保持私有。
173
203
  `rebind` 只能选择已获 policy 授权且能力匹配的 route,不会扩大任务边界。
174
204
 
@@ -287,7 +317,7 @@ Vitest 的 JSON 报告与普通 stdout/stderr 分离,日志超过捕获预算
287
317
 
288
318
  ```sh
289
319
  bun run eval:workflow
290
- bun run eval:workflow --live --scenario small-fix --output /tmp/cadence-evaluation.json
320
+ bun run eval:workflow --live --scenario small-fix --output /tmp/cadence-evaluation.json --progress-output /tmp/cadence-progress.json
291
321
  bun run eval:workflow --live --scenario multiple-tasks
292
322
  bun run eval:workflow --live --scenario restart-recovery
293
323
  bun run eval:workflow --live --scenario missing-capability
@@ -295,6 +325,30 @@ bun run eval:workflow --live --scenario missing-capability
295
325
 
296
326
  `--live` 使用 Pi 当前配置的模型,也可传 `--model provider/model`;需要可用的 Provider、OpenSpec 和 Linux Bubblewrap。
297
327
  报告记录完成状态、用户介入、重复修订、耗时及宿主报告的 token/成本;最终行为另由隔离 oracle 检查。
328
+ `trace` 提供有界的工具/操作计数、安全错误分类、阶段里程碑、重复提交、工具活动区间并集和消息 usage;截止时冻结快照,未到达的里程碑为 null。
329
+ 非工具时间不是纯模型计算时间。
330
+ `configurations` 记录实际模型、reasoning 和非秘密路由指纹,`sourceSha256` / `sourceUnchanged` 标识工作树版本和运行期间是否变化。
331
+ 可选 `--progress-output` 每 15 秒写一份有界进度快照;无原始参数、提示或响应正文。
332
+ 源码读取统计只覆盖明确的成功 read,未分类访问不能当作零。
333
+ `modelFailureDiagnostics` 最多保留 16 条脱敏错误分类及可从 SDK 错误文字识别的 HTTP 状态;无法识别时明确记录 `unclassified` / `null`。
334
+ `autoRetries` 与 `retryDelayMs` 单独记录宿主自动重试次数和计划退避时间,避免把同一请求的多次失败误读为独立故障。
298
335
  模型服务不可用、阶段停滞、取消与 Design 完成都不会被计为 Implement 成功。
299
336
  缺少能力的场景用于观察保留状态,不能把任意停滞当作正确恢复。
300
337
  无原始对话落盘。
338
+
339
+ ## 内部架构与请求预算
340
+
341
+ `PlanDraft` 只表示作者输入,`ImplementPlan` 独立定义完整执行合同;命名引用和默认值仅在编译入口展开,旧封存计划不被重写。
342
+ PlanDraft 的命名或内联 package-script 可以省略 `command`,编译器从 manifest 绑定脚本原文后生成身份;显式不匹配仍拒绝,Gate A 的完整验证合同不被替换。
343
+ 作者在 `tasks.md` 保留任务 checkbox、目标和精确 Scenario 归属;`compile-plan` 生成独立的验证 ID 绑定区域,保留作者正文,并在两份文件安装成功后记录编译。
344
+ 旧封存交付仍可读取;缺失作者证据或篡改绑定不能通过追溯检查。
345
+ `workflow-state-machine` 继续独占 run/task 状态转换与预算事务;调度、恢复策略和交付差异比较使用只接受事实的内部函数。
346
+ `durable-workflow` 管理资源生命周期和交付重放,`phase-execution` 执行候选阶段,`change-verification` 管理基线及变更验证;阶段服务没有主工作区 apply 能力。
347
+ Pi 入口负责激活、工具交互、模型能力投影和展示;`package-workflow` 组合控制服务,`package-candidate` 执行受限候选请求,核心不接收 Pi 会话事件或完整宿主上下文。
348
+
349
+ 每次模型请求独立计时:90 秒内没有非空文本、思考或工具参数增量时返回 `first-progress-timeout`;已有进展后空闲 180 秒返回 `stream-idle-timeout`。
350
+ HTTP 响应头用于观察,不刷新进展预算;完整终态可直接结束请求,本地工具执行间隙不计入流空闲,下一轮重新计时。
351
+ Broker 保留每 attempt 20 分钟总上限和原有有限重试;该上限不代表跨重试的 workflow 总时限。
352
+ 新请求不再发出 `connect-timeout`,也不声称观测到了 TCP/TLS 建连;旧超时事实和 `connecting` 展示仍可读取。
353
+ 子执行器限制为 64 轮、4 MiB 序列化上下文,不自动压缩或静默截断证据;达到限制返回执行限制失败,候选任务暂停并要求拆分,不作为端点故障重试。
354
+ 取消后的用量结算最多等待 250 ms,迟到结果不能进入候选提交或主工作区应用。
@@ -5,18 +5,24 @@ You are a package-owned read-only professional Agent for the `abel-design` stage
5
5
  You explore the repository ONLY through the scoped `read`, `grep`, `find`, and `ls` tools.
6
6
  You have no shell, edit, Git, network, or validation capability, and you never create or modify files.
7
7
 
8
- Call `abel_submit_result` exactly once with one structured object.
9
- Do not emit a second submit, prose, or fields outside the declared Design evidence schema.
10
- The object contains the matching `id`, `role: "design-explorer"`, `kind: "evidence"`, and:
8
+ Submit one accepted final result through `abel_submit_result`; brief accompanying text is harmless.
9
+ If the tool rejects your submission, use its error to correct once in this same disposable session.
10
+ A second rejected structural submission ends the session.
11
+ Never submit again after acceptance.
11
12
 
12
- - `packet_id` (exactly equal to the request id), `module_name`, `scope`, and
13
- `files_read`;
14
- - `evidence`, where every item has `claim`, `path`, `line_start`, and
15
- `line_end`;
16
- - `existing_structures`, `existing_conventions`, `constraints_discovered`,
17
- `open_questions`, and `dependencies`;
18
- - `write_set_hints`, `validation_hints`, `agents_impact_hints`, `risks`, and
19
- `success_criteria_hints`.
13
+ Required draft fields:
14
+
15
+ - `module_name`: a canonical workspace-relative module path or slug;
16
+ - `scope` and `files_read`: unique workspace-relative paths, with nonempty scope;
17
+ - `evidence`: cited claims with `claim`, `path`, positive `line_start`, and inclusive `line_end >= line_start`;
18
+ - `constraints_discovered`, `open_questions`, and `risks`: explicit arrays (use `[]` only when there are none).
19
+
20
+ Omit `id`, `packet_id`, `role`, and `kind`: the trusted tool binds them to this packet.
21
+ If supplied, they must match the declared identity.
22
+ Optional advisory arrays are `existing_structures`, `existing_conventions`, `dependencies`, `write_set_hints`, `validation_hints`, `agents_impact_hints`, and `success_criteria_hints`.
23
+ Omission means no advisory information supplied, not a verified absence or authorization.
24
+ Do not invent evidence or drop unresolved questions to satisfy the format.
25
+ Do not add undeclared fields.
20
26
 
21
27
  You never return raw transcripts, hidden reasoning, or tool-call history.
22
28
  A packet is complete only when every claim is cited and every blocking question is explicit.
@@ -6,8 +6,16 @@ You collect evidence and falsify candidate root causes ONLY through the scoped `
6
6
  You never write, execute commands, or run validation.
7
7
  The fixed algorithm order is reproduce, falsify, failing-regression, then minimum-repair.
8
8
 
9
- An evidence packet submits exactly one compact structured evidence object through `abel_submit_result` with the reported symptoms, candidate causes, confirming or refuting citations, and a supported root-cause conclusion or an explicit evidence gap.
9
+ An evidence packet submits one accepted compact structured evidence object through `abel_submit_result` with the reported symptoms, candidate causes, confirming or refuting citations, and a supported root-cause conclusion or an explicit evidence gap.
10
10
  Only the parent may claim that command-based reproduction succeeded.
11
+ For evidence, omit `id`, `role`, and `kind`; the tool binds them.
12
+ Keep `conclusions`, `citations`, `constraints`, `risks`, and `blockingQuestions` explicit.
13
+ `dependencies` and `hints` may be omitted when no advisory information is supplied.
14
+ If supplying hints, use `writeSet`, `verification`, and `agentsImpact` (`none`, `update-existing`, `create-index`, or `remove-index`).
15
+ Omission never proves the absence of an impact.
16
+ After a rejected evidence or patch submission, use the error to correct once in this same disposable session.
17
+ A second rejected structural submission ends the session.
18
+ Never submit again after acceptance.
11
19
 
12
20
  A candidate packet submits one complete structured patch: either the failing regression or, after the parent has verified that regression, the minimum repair.
13
21
  Use ordered `replace`, `rewrite`, `create`, and `delete` operations inside the approved write set.
@@ -8,7 +8,7 @@ You never write the workspace, run validation, or execute commands.
8
8
  Your output is one complete structured patch delivered through `abel_submit_result`:
9
9
 
10
10
  - copy the attempt-bound `candidateId` from the phase contract;
11
- - submit exactly one `candidate-patch` call containing that `candidateId` and
11
+ - submit one accepted `candidate-patch` call containing that `candidateId` and
12
12
  an ordered `operations` array;
13
13
  - use `replace` with exact uniquely occurring `oldText` and the intended
14
14
  `newText` for compact edits, `rewrite` for a complete existing-file body,
@@ -32,6 +32,8 @@ Your output is one complete structured patch delivered through `abel_submit_resu
32
32
 
33
33
  If the submit tool rejects malformed operations, use its concrete error to correct the submission once in this same disposable session; a second rejected structural submission ends the session.
34
34
 
35
+ Never submit again after acceptance; brief accompanying text is harmless.
36
+
35
37
  If the configured candidate limit is exceeded, the submit tool returns terminal typed `result-limit` with `limitBytes`; never continue with a partial or truncated patch.
36
38
  The parent alone reviews, applies, and validates the generated diff.
37
39
  You report candidate facts only and never claim execution success, select parent recovery, choose a workflow stage, or control the task DAG.
@@ -0,0 +1,122 @@
1
+ {
2
+ "changeContract": {
3
+ "goal": "Fix integer addition while preserving the existing zero case",
4
+ "acceptance": [
5
+ {
6
+ "id": "integer-addition",
7
+ "statement": "add(2, 3) returns 5 and add(0, 0) remains 0",
8
+ "verification": {
9
+ "kind": "static-check",
10
+ "id": "add-acceptance",
11
+ "runner": {
12
+ "kind": "node",
13
+ "script": "test/add.test.mjs"
14
+ },
15
+ "args": [],
16
+ "classification": "expected-green"
17
+ }
18
+ }
19
+ ],
20
+ "constraints": [
21
+ {
22
+ "id": "no-dependencies",
23
+ "statement": "Keep the existing function signature and add no dependencies"
24
+ }
25
+ ],
26
+ "policy": {
27
+ "writeRoots": ["src/add.mjs", "test/add.test.mjs"],
28
+ "dependencies": [],
29
+ "verificationModes": ["behavior"]
30
+ }
31
+ },
32
+ "changeId": "fix-integer-addition",
33
+ "tasks": [
34
+ {
35
+ "taskId": "fix-add",
36
+ "dependsOn": [],
37
+ "objective": "Preserve the existing zero assertion; add a failing positive-integer assertion with [ADD:positive-integers], then fix addition",
38
+ "context": {
39
+ "agents": "No AGENTS.md in this example consumer; use the actual repository instructions when adapting",
40
+ "contract": "Gate A integer-addition acceptance; only src/add.mjs and test/add.test.mjs may change"
41
+ },
42
+ "roots": ["."],
43
+ "phases": {
44
+ "red": {
45
+ "write": ["test/add.test.mjs"],
46
+ "delete": [],
47
+ "verification": {
48
+ "use": "add-test",
49
+ "expectedFailure": "[ADD:positive-integers]"
50
+ }
51
+ },
52
+ "green": {
53
+ "write": ["src/add.mjs"],
54
+ "delete": [],
55
+ "verification": {
56
+ "use": "add-test"
57
+ }
58
+ }
59
+ },
60
+ "affectedVerification": {
61
+ "use": "add-test"
62
+ },
63
+ "repairVerification": {
64
+ "use": "add-test"
65
+ },
66
+ "scheduling": {
67
+ "conflicts": [],
68
+ "resources": []
69
+ },
70
+ "agents": {
71
+ "impact": "none"
72
+ },
73
+ "approvedDependencies": [],
74
+ "impactClosure": {
75
+ "changedSurfaces": ["none"],
76
+ "searchEvidence": [
77
+ "Example consumer: src/add.mjs exports add; test/add.test.mjs is its only caller and existing test"
78
+ ],
79
+ "relatedTests": [
80
+ {
81
+ "path": "test/add.test.mjs",
82
+ "evidence": "Existing add(0, 0) assertion passes; preserve it while adding the positive-integer regression"
83
+ }
84
+ ],
85
+ "affectedSuite": ["test/add.test.mjs"]
86
+ },
87
+ "read": ["package.json", "src/add.mjs", "test/add.test.mjs"]
88
+ }
89
+ ],
90
+ "outputs": [],
91
+ "verification": {
92
+ "baseline": {
93
+ "fullSuite": {
94
+ "use": "add-test"
95
+ }
96
+ },
97
+ "change": {
98
+ "fullSuite": {
99
+ "use": "add-test"
100
+ },
101
+ "postApply": {
102
+ "use": "add-test"
103
+ }
104
+ },
105
+ "artifactCorrection": {
106
+ "maxAttempts": 2
107
+ },
108
+ "repair": {
109
+ "maxAttempts": 1
110
+ }
111
+ },
112
+ "verificationDefinitions": {
113
+ "add-test": {
114
+ "kind": "static-check",
115
+ "runner": {
116
+ "kind": "node",
117
+ "script": "test/add.test.mjs"
118
+ },
119
+ "args": []
120
+ }
121
+ }
122
+ }
@@ -0,0 +1,345 @@
1
+ {
2
+ "changeContract": {
3
+ "goal": "Fix integer addition and doubling through add",
4
+ "acceptance": [
5
+ {
6
+ "id": "integer-addition",
7
+ "statement": "add(2, 3) returns 5 and add(0, 0) remains 0",
8
+ "verification": {
9
+ "kind": "static-check",
10
+ "id": "add-acceptance",
11
+ "runner": {
12
+ "kind": "node",
13
+ "script": "test/add.test.mjs"
14
+ },
15
+ "args": [],
16
+ "classification": "expected-green"
17
+ }
18
+ },
19
+ {
20
+ "id": "integer-double",
21
+ "statement": "double(3) returns 6 via add(3, 3)",
22
+ "verification": {
23
+ "kind": "steps",
24
+ "id": "double-green",
25
+ "classification": "expected-green",
26
+ "steps": [
27
+ {
28
+ "kind": "static-check",
29
+ "id": "double-green-add",
30
+ "runner": {
31
+ "kind": "node",
32
+ "script": "test/add.test.mjs"
33
+ },
34
+ "args": [],
35
+ "classification": "expected-green"
36
+ },
37
+ {
38
+ "kind": "static-check",
39
+ "id": "double-green-own",
40
+ "runner": {
41
+ "kind": "node",
42
+ "script": "test/double.test.mjs"
43
+ },
44
+ "args": [],
45
+ "classification": "expected-green"
46
+ }
47
+ ]
48
+ }
49
+ }
50
+ ],
51
+ "constraints": [
52
+ {
53
+ "id": "no-dependencies",
54
+ "statement": "Keep the existing function signature and add no dependencies"
55
+ }
56
+ ],
57
+ "policy": {
58
+ "writeRoots": [
59
+ "src/add.mjs",
60
+ "test/add.test.mjs",
61
+ "src/double.mjs",
62
+ "test/double.test.mjs"
63
+ ],
64
+ "dependencies": [],
65
+ "verificationModes": ["behavior"]
66
+ }
67
+ },
68
+ "changeId": "fix-add-and-double",
69
+ "tasks": [
70
+ {
71
+ "taskId": "fix-add",
72
+ "dependsOn": [],
73
+ "objective": "Preserve the existing zero assertion; add a failing positive-integer assertion with [ADD:positive-integers], then fix addition",
74
+ "context": {
75
+ "agents": "No AGENTS.md in this example consumer; use the actual repository instructions when adapting",
76
+ "contract": "Gate A integer-addition acceptance; only src/add.mjs and test/add.test.mjs may change"
77
+ },
78
+ "roots": ["."],
79
+ "phases": {
80
+ "red": {
81
+ "write": ["test/add.test.mjs"],
82
+ "delete": [],
83
+ "verification": {
84
+ "use": "add-test",
85
+ "expectedFailure": "[ADD:positive-integers]"
86
+ }
87
+ },
88
+ "green": {
89
+ "write": ["src/add.mjs"],
90
+ "delete": [],
91
+ "verification": {
92
+ "use": "add-test"
93
+ }
94
+ }
95
+ },
96
+ "affectedVerification": {
97
+ "use": "add-test"
98
+ },
99
+ "repairVerification": {
100
+ "use": "add-test"
101
+ },
102
+ "scheduling": {
103
+ "conflicts": [],
104
+ "resources": []
105
+ },
106
+ "agents": {
107
+ "impact": "none"
108
+ },
109
+ "approvedDependencies": [],
110
+ "impactClosure": {
111
+ "changedSurfaces": ["none"],
112
+ "searchEvidence": [
113
+ "Example consumer: src/add.mjs exports add; test/add.test.mjs is its only caller and existing test"
114
+ ],
115
+ "relatedTests": [
116
+ {
117
+ "path": "test/add.test.mjs",
118
+ "evidence": "Existing add(0, 0) assertion passes; preserve it while adding the positive-integer regression"
119
+ }
120
+ ],
121
+ "affectedSuite": ["test/add.test.mjs"]
122
+ },
123
+ "read": ["package.json", "src/add.mjs", "test/add.test.mjs"]
124
+ },
125
+ {
126
+ "taskId": "fix-double",
127
+ "dependsOn": ["fix-add"],
128
+ "objective": "Keep double(0) passing; add the [DOUBLE:positive-integers] failure then use add(value, value)",
129
+ "context": {
130
+ "agents": "No AGENTS.md in this example consumer; use the actual repository instructions when adapting",
131
+ "contract": "Gate A integer-double acceptance; depends on corrected addition"
132
+ },
133
+ "roots": ["."],
134
+ "phases": {
135
+ "red": {
136
+ "write": ["test/double.test.mjs"],
137
+ "delete": [],
138
+ "verification": {
139
+ "kind": "steps",
140
+ "id": "double-red",
141
+ "classification": "expected-red",
142
+ "steps": [
143
+ {
144
+ "kind": "static-check",
145
+ "id": "double-red-add",
146
+ "runner": {
147
+ "kind": "node",
148
+ "script": "test/add.test.mjs"
149
+ },
150
+ "args": [],
151
+ "classification": "expected-green"
152
+ },
153
+ {
154
+ "kind": "static-check",
155
+ "id": "double-red-own",
156
+ "runner": {
157
+ "kind": "node",
158
+ "script": "test/double.test.mjs"
159
+ },
160
+ "args": [],
161
+ "classification": "expected-red",
162
+ "expectedFailure": "[DOUBLE:positive-integers]"
163
+ }
164
+ ]
165
+ }
166
+ },
167
+ "green": {
168
+ "write": ["src/double.mjs"],
169
+ "delete": [],
170
+ "verification": {
171
+ "kind": "steps",
172
+ "id": "double-green",
173
+ "classification": "expected-green",
174
+ "steps": [
175
+ {
176
+ "kind": "static-check",
177
+ "id": "double-green-add",
178
+ "runner": {
179
+ "kind": "node",
180
+ "script": "test/add.test.mjs"
181
+ },
182
+ "args": [],
183
+ "classification": "expected-green"
184
+ },
185
+ {
186
+ "kind": "static-check",
187
+ "id": "double-green-own",
188
+ "runner": {
189
+ "kind": "node",
190
+ "script": "test/double.test.mjs"
191
+ },
192
+ "args": [],
193
+ "classification": "expected-green"
194
+ }
195
+ ]
196
+ }
197
+ }
198
+ },
199
+ "affectedVerification": {
200
+ "kind": "steps",
201
+ "id": "double-affectedVerification",
202
+ "classification": "expected-green",
203
+ "steps": [
204
+ {
205
+ "kind": "static-check",
206
+ "id": "double-green-add-affectedVerification",
207
+ "runner": {
208
+ "kind": "node",
209
+ "script": "test/add.test.mjs"
210
+ },
211
+ "args": [],
212
+ "classification": "expected-green"
213
+ },
214
+ {
215
+ "kind": "static-check",
216
+ "id": "double-green-own-affectedVerification",
217
+ "runner": {
218
+ "kind": "node",
219
+ "script": "test/double.test.mjs"
220
+ },
221
+ "args": [],
222
+ "classification": "expected-green"
223
+ }
224
+ ]
225
+ },
226
+ "repairVerification": {
227
+ "kind": "steps",
228
+ "id": "double-repairVerification",
229
+ "classification": "expected-green",
230
+ "steps": [
231
+ {
232
+ "kind": "static-check",
233
+ "id": "double-green-add-repairVerification",
234
+ "runner": {
235
+ "kind": "node",
236
+ "script": "test/add.test.mjs"
237
+ },
238
+ "args": [],
239
+ "classification": "expected-green"
240
+ },
241
+ {
242
+ "kind": "static-check",
243
+ "id": "double-green-own-repairVerification",
244
+ "runner": {
245
+ "kind": "node",
246
+ "script": "test/double.test.mjs"
247
+ },
248
+ "args": [],
249
+ "classification": "expected-green"
250
+ }
251
+ ]
252
+ },
253
+ "scheduling": {
254
+ "conflicts": [],
255
+ "resources": []
256
+ },
257
+ "agents": {
258
+ "impact": "none"
259
+ },
260
+ "approvedDependencies": [],
261
+ "impactClosure": {
262
+ "changedSurfaces": ["none"],
263
+ "searchEvidence": [
264
+ "Example consumer: double imports add; each has an existing zero assertion; all.test.mjs imports both test files"
265
+ ],
266
+ "relatedTests": [
267
+ {
268
+ "path": "test/add.test.mjs",
269
+ "evidence": "Producer task owns the addition regression, checked before the double regression"
270
+ },
271
+ {
272
+ "path": "test/double.test.mjs",
273
+ "evidence": "Preserve the existing double(0) assertion while adding double(3)"
274
+ }
275
+ ],
276
+ "affectedSuite": ["test/add.test.mjs", "test/double.test.mjs"]
277
+ },
278
+ "read": [
279
+ "package.json",
280
+ "src/add.mjs",
281
+ "test/add.test.mjs",
282
+ "src/double.mjs",
283
+ "test/double.test.mjs"
284
+ ]
285
+ }
286
+ ],
287
+ "outputs": [
288
+ {
289
+ "id": "add-regression",
290
+ "path": "test/add.test.mjs",
291
+ "producer": {
292
+ "taskId": "fix-add",
293
+ "phase": "red"
294
+ },
295
+ "postcondition": "regular-file"
296
+ }
297
+ ],
298
+ "verification": {
299
+ "baseline": {
300
+ "fullSuite": {
301
+ "use": "full-suite"
302
+ }
303
+ },
304
+ "change": {
305
+ "fullSuite": {
306
+ "use": "full-suite"
307
+ },
308
+ "postApply": {
309
+ "use": "full-suite"
310
+ }
311
+ },
312
+ "artifactCorrection": {
313
+ "maxAttempts": 2
314
+ },
315
+ "repair": {
316
+ "maxAttempts": 1
317
+ }
318
+ },
319
+ "verificationDefinitions": {
320
+ "add-test": {
321
+ "kind": "static-check",
322
+ "runner": {
323
+ "kind": "node",
324
+ "script": "test/add.test.mjs"
325
+ },
326
+ "args": []
327
+ },
328
+ "full-suite": {
329
+ "kind": "static-check",
330
+ "runner": {
331
+ "kind": "node",
332
+ "script": "test/all.test.mjs"
333
+ },
334
+ "args": []
335
+ },
336
+ "double-test": {
337
+ "kind": "static-check",
338
+ "runner": {
339
+ "kind": "node",
340
+ "script": "test/double.test.mjs"
341
+ },
342
+ "args": []
343
+ }
344
+ }
345
+ }