@abelxiaoxing/cadence 1.6.0 → 1.8.0

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 (45) hide show
  1. package/README.md +25 -4
  2. package/config/.env.example +6 -0
  3. package/config/plan-draft.example.json +3 -0
  4. package/config/plan-draft.multiple-tasks.example.json +30 -0
  5. package/package.json +1 -1
  6. package/prompts/abel-design.md +33 -3
  7. package/prompts/abel-implement.md +36 -4
  8. package/src/apply-transaction.ts +28 -8
  9. package/src/build-windows-job.mjs +95 -0
  10. package/src/candidate-workspace.ts +6 -0
  11. package/src/change-verification.ts +764 -67
  12. package/src/contracts.ts +8 -0
  13. package/src/delivery-compiler.ts +452 -9
  14. package/src/design-control.ts +2 -2
  15. package/src/design-diagnostics.ts +6 -4
  16. package/src/durable-contracts.ts +21 -3
  17. package/src/durable-workflow.ts +55 -40
  18. package/src/execution-profile.ts +28 -2
  19. package/src/execution-retention.ts +77 -0
  20. package/src/implement-continuation.ts +559 -0
  21. package/src/implement-graph.ts +114 -0
  22. package/src/implement-plan.ts +2 -0
  23. package/src/index.ts +151 -1
  24. package/src/isolation-backend.ts +2 -1
  25. package/src/operator-cli.mjs +664 -104
  26. package/src/operator-tools.ts +7 -1
  27. package/src/package-state.ts +11 -0
  28. package/src/package-verification.ts +66 -18
  29. package/src/package-workflow.ts +6 -0
  30. package/src/phase-execution.ts +18 -7
  31. package/src/plan-draft-summary.ts +385 -7
  32. package/src/plan-draft.ts +9 -0
  33. package/src/remove-path.ts +32 -0
  34. package/src/subagent-activity.ts +3 -1
  35. package/src/verification-capability.ts +18 -6
  36. package/src/verification-environment-io.ts +123 -14
  37. package/src/verification-environment.ts +50 -3
  38. package/src/windows-job-backend.ts +419 -0
  39. package/src/windows-job.c +149 -0
  40. package/src/workflow-policy.ts +296 -5
  41. package/src/workflow-recovery-policy.ts +2 -0
  42. package/src/workflow-state-machine.ts +314 -80
  43. package/src/workflow-status.ts +251 -59
  44. package/src/workspace-io-entry.mjs +2 -2
  45. package/src/workspace-io-worker.mjs +207 -110
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  1. 安装 Node.js >=22.13、Git、Pi,以及 `@fission-ai/openspec@1.5.0`。
12
12
  2. 在 Pi 中安装:`pi install npm:@abelxiaoxing/cadence`。
13
- 3. 默认 Implement 需要可用的 Linux Bubblewrap;Windows 请使用 WSL。
13
+ 3. 默认 Implement 使用 Linux Bubblewrap;Windows x64 可信项目可显式选择 `host-trusted`,构建与验收见 [Windows 原生执行](docs/windows-host-trusted.md)。
14
14
  4. 首次进入项目先运行 `/abel-init`,然后 `/abel-design <需求>`,确认集中呈现的目标与方案,设计完成后运行 `/abel-implement <change>`。
15
15
  5. 暂停时先查看原因和建议,不要靠反复 resume 或重启“碰运气”;未完成的工作会保留。
16
16
 
@@ -50,7 +50,9 @@ export ABEL_VERIFICATION_TIMEOUT_MS=900000
50
50
  可信模式仍在独立候选目录执行,并复制依赖以避免普通缓存写入修改 consumer 的依赖,但**不是沙箱**:测试可访问宿主文件、网络及显式继承的环境变量,产生的外部副作用不能回滚。
51
51
  HOME、临时目录和报告仍独立;PATH 复用宿主,仓库内 workspace 链接映射到候选代码。
52
52
  该模式仍要求 Linux Bubblewrap 的 PID namespace 管理后代进程(包括 detached 后代),但不隔离宿主文件和网络;缺少该能力时暂停,不回退到普通进程组。
53
- 原生 macOS/Windows 不提供此执行模式,Windows 可使用 WSL。
53
+ `local-trusted` 仅用于 Linux。
54
+ Windows x64 使用独立的 `host-trusted` 后端,见 [配置、构建与验收说明](docs/windows-host-trusted.md);macOS 暂不支持。
55
+ 包含原生 helper 的 Windows x64 安装包在 [GitHub Release](https://github.com/abelxiaoxing/cadence/releases/tag/v1.8.0) 下载;npm 通用包可显式构建 helper 后配置使用。
54
56
  依赖副本准备、替换与清理在 I/O Worker 中执行,复制支持取消并等待线程退出;大型依赖复制仍有额外成本;需要安装新依赖、宿主浏览器缓存或服务启动编排时仍需配置/准备,不会自动下载。
55
57
 
56
58
  可选宿主参数还包括 `ABEL_BWRAP_PATH`、`ABEL_FIRST_PROGRESS_MS` 和 `ABEL_STREAM_IDLE_MS`。
@@ -150,6 +152,18 @@ artifact、stale candidate 与 verification 纠错会将具体失败码、修复
150
152
  自动恢复预算以验证义务和阶段为依据,使用独立 SQLite 事实保存;普通 `resume`、重启、回滚、换路由、任务重命名和合同改写都不能重置额度。
151
153
  执行前持久化预留工作额度;内部修复也计入同一 run 的有限资源预算。
152
154
  系统保留 baseline 和 phase facts,并明确区分缺少能力、缺少决定与恢复额度耗尽。
155
+ 任务 `baselineVerification` 只读取 run 的原始不可变快照;只有 affected 输入均为原始安全普通文件时,编译器才允许省略并推导它。
156
+ 新增 Red 测试仍完整参与阶段、affected、累计和最终验收。
157
+ 独立任务共享四个执行槽位,单个任务结算后立即补位;其他 run 释放容量也会唤醒排队工作。
158
+ 局部 baseline 或能力缺失只阻塞相关任务及依赖者,完整验收和事务 apply 保留全局屏障。
159
+ Design 的 `summary.parallelism` 展示最多四项互不冲突的初始任务组、明确标为后续兼容关系的任务对、producer 等待、串行原因和全局验证屏障。
160
+ 初始组假设共享槽位可用;实际运行仍检查容量、能力和 currentness。
161
+ `summary.implementation` 同时展示已接受的验收/限制 ID、技术修订可用的写入范围、依赖与验证模式,让 Design 能检查后续修复是否有足够权限;摘要本身不授予权限,也不宣称运行环境已就绪。
162
+ Design 集中解决用户决策和已知的外部前提,按受影响模块及必要集成修复确定政策范围,按精确文件划分初始任务。
163
+ Implement 以已接受目标为持续执行目标:父代理负责范围内的推荐决策、拆分、修复、重新编译和继续执行;调度器持续填充四个共享槽位。
164
+ 父代理在仍有可执行后续动作时提前结束回合,宿主会重新读取同一 change 的本地状态,并接续同阶段工作,不需要用户再次发送“继续”。
165
+ 取消、退出、模型中断、待处理用户消息和无进展保护会阻止自动接续;接续不扩大授权、不重置恢复额度,也不将缺少凭据或服务的外部阻塞伪报为完成。
166
+ 进程中断后的 run 在用户再次显式调用 Implement 时提供同一 run 的恢复动作;已有 apply journal 的结算不消耗 Worker 额度,仍由引擎控制。
153
167
  Worker 可读取同一任务各阶段已批准路径的并集,并按需申请 sealed roots 内的普通文件读取;新增读取会绑定合并与最终应用的 currentness,写入和删除仍限于当前阶段;超大补丁先自动尝试紧凑的完整提交,不能完整提交时保留进度,绝不接受部分补丁。
154
168
  Design 对明确需求尽量只进行一轮集中决策:先调查仓库约定,再一起呈现目标、关键技术取舍、推荐默认值及编译授权;编译器在记录有效计划时原子生成 Gate B 证明,无需第二次用户确认。
155
169
  相同计划重编译和仅修改决策引用不会重开 Gate。
@@ -165,7 +179,10 @@ Gate A/B 收据只有一套 canonical 结构,并在 Implement admission 时同
165
179
  Design 完成主要决策后,Implement 中的新实施选择默认由父模型采用推荐方案,记录后继续执行;不再默认向用户追问。
166
180
  状态一次返回完整 `blockers`、稳定的 `decisionBatch`,并明确由父模型负责执行自动 `continuation`。
167
181
  父模型通过当前 Implement 内的 `action: "amend"` 修订同一 change、自动生成计划证明,再由普通 resume 发现并验证新交付;无需切换命令、重新确认或手动传递收据。
168
- 交付校验失败和任务过大也能进入该修订通道,不必伪装成用户决策。
182
+ 父控制面从原始快照证明的 baseline 输入缺陷和任务过大可以进入该修订通道,不必伪装成用户决策。
183
+ 单独的错误码、hash/receipt 异常、不安全路径和未知错误不授予修订权限。
184
+ 相同 baseline 合同、输入和环境下的失败会持久保留,重复 resume 不再执行相同失败检查或启动 Worker;可观测前提变化后才在原预算内恢复。
185
+ baseline 专属修订保留兼容的已提交阶段、任务成果与原 run。
169
186
  修订有独立的持久化预算:每个 run 最多 64 次变更尝试,失败也计数,成功操作重放和只读检查不计数。
170
187
  自动修订保留 Design 目标、明确限制与验收标准;Worker 仍必须等待新计划通过完整校验才能使用新权限。
171
188
  新证明尚未就绪时,`resume` 只列为条件命令;证明就绪后可直接恢复,由控制层读取版本和哈希。
@@ -324,7 +341,9 @@ inspection 不可用时不再级联误报 traceability 输入缺失,且绝不
324
341
  CLI 的其他版本必须满足相同 JSON 协议;新增支持版本应加入契约测试。
325
342
 
326
343
  **此矩阵不代表原生 Implement 隔离已全平台可用。**
327
- 默认隔离后端仍为 Linux Bubblewrap;Windows/macOS 的原生隔离、ACL 与完整文件应用语义需要单独实现和验收,缺少隔离能力时保持暂停,不降级为主工作区直接执行。
344
+ 默认隔离后端仍为 Linux Bubblewrap。
345
+ Windows x64 的显式 `host-trusted` 使用 Job Object 管理验证进程,不提供文件或网络安全隔离;真实原生支持以 Windows CI 验收结果为准。
346
+ 缺少所选后端时保持暂停。
328
347
 
329
348
  目录持久化在 Windows 上单独处理:仅当已打开的目录句柄执行 `fsync` 返回 `EPERM` 时,标记为不支持目录刷新屏障。
330
349
  普通文件仍须在发布前成功 `fsync`;目录打开/关闭、权限、其他 I/O 及 POSIX 目录刷新错误不会被忽略。
@@ -463,6 +482,8 @@ Vitest 的 JSON 报告与普通 stdout/stderr 分离,日志超过捕获预算
463
482
 
464
483
  自动纠错耗尽后,普通 resume、rebind 和重启不充值。
465
484
  父代理可使用 status 返回的 `recovery.additionalAttempt`,作为 resume 的 `recovery` 字段明确追加一次尝试;失败后再次暂停,历史消耗保持。
485
+ `continuation.kind: "inspect-recovery"` 将已知故障交给父代理调查并选择具体修复策略;它是指导信息,不是新的 dispatch action。
486
+ 纠错耗尽时,`conditionalCommands` 明确给出需要原样携带恢复凭据的 resume 条件;有证据支持的计划调整仍需经过同一 change 的编译和验证。
466
487
  累计工作额度按成功接纳过的最大阶段数增长,任务重命名、重复编译及缩小后恢复原规模不增加额度。
467
488
  宿主可在启动前设置 `ABEL_WORK_MAX_UNITS`(默认 512)和 `ABEL_VERIFICATION_MAX_REPORT_BYTES`(默认 67108864);Worker 不能调整这些资源设置。
468
489
  前者在 run 中固定,后者用于每次独立报告的有界读取。
@@ -19,3 +19,9 @@ GROK_API_KEY=
19
19
  # TAVILY_ENABLED=true
20
20
  # TAVILY_API_URL=https://api.tavily.com
21
21
  # TAVILY_API_KEY=
22
+
23
+ # Explicit Windows x64 trusted host verification (not a filesystem/network sandbox).
24
+ # ABEL_EXECUTION_MODE=host-trusted
25
+ # ABEL_WINDOWS_JOB_HELPER=C:\CadenceNative\windows-job.exe
26
+ # ABEL_VERIFICATION_TIMEOUT_MS=600000
27
+ # ABEL_VERIFICATION_ENV=DATABASE_URL,NODE_ENV
@@ -57,6 +57,9 @@
57
57
  }
58
58
  }
59
59
  },
60
+ "baselineVerification": {
61
+ "use": "add-test"
62
+ },
60
63
  "affectedVerification": {
61
64
  "use": "add-test"
62
65
  },
@@ -93,6 +93,9 @@
93
93
  }
94
94
  }
95
95
  },
96
+ "baselineVerification": {
97
+ "use": "add-test"
98
+ },
96
99
  "affectedVerification": {
97
100
  "use": "add-test"
98
101
  },
@@ -196,6 +199,33 @@
196
199
  }
197
200
  }
198
201
  },
202
+ "baselineVerification": {
203
+ "kind": "steps",
204
+ "id": "double-affectedVerification",
205
+ "classification": "expected-green",
206
+ "steps": [
207
+ {
208
+ "kind": "static-check",
209
+ "id": "double-green-add-affectedVerification",
210
+ "runner": {
211
+ "kind": "node",
212
+ "script": "test/add.test.mjs"
213
+ },
214
+ "args": [],
215
+ "classification": "expected-green"
216
+ },
217
+ {
218
+ "kind": "static-check",
219
+ "id": "double-green-own-affectedVerification",
220
+ "runner": {
221
+ "kind": "node",
222
+ "script": "test/double.test.mjs"
223
+ },
224
+ "args": [],
225
+ "classification": "expected-green"
226
+ }
227
+ ]
228
+ },
199
229
  "affectedVerification": {
200
230
  "kind": "steps",
201
231
  "id": "double-affectedVerification",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abelxiaoxing/cadence",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "description": "Four explicit Abel workflow prompts with stage-isolated design and diagnosis, durable resumable implementation, and three package-owned professional Agents.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -144,6 +144,14 @@ Design settles the goal, main decisions, explicit constraints, and non-goals.
144
144
  Make the implementation delegation clear in the accepted proposal: the parent will choose its recommended solution for later implementation choices within those constraints, record material decisions, and continue to verified results without another selection or confirmation round.
145
145
  Do not ask the user to approve this delegation separately or attempt to enumerate every future implementation detail.
146
146
 
147
+ Design owns the user decision boundary for this change.
148
+ Discuss the outcome and real constraints here, including likely repair scope, dependency choices, environment prerequisites that require the operator, and any irreversible operation.
149
+ Treat the task DAG as the initial execution strategy: the parent may revise its technical decomposition, supply context, repair failures, and recompile within the accepted contract during Implement.
150
+ Do not make incidental file lists or a guessed decomposition into product constraints.
151
+ Choose `policy.writeRoots` to cover the affected modules, their regression tests, and necessary integration repairs justified by repository evidence; keep initial phase writes precise.
152
+ An explicit user authorization for repository-wide work may be represented by `"."`; never infer it from convenience, and still name any authorized AGENTS target exactly.
153
+ Set dependency and verification-mode policy from the accepted choices, so known requirements do not become authorization requests during execution.
154
+
147
155
  ## Structured authority for new work
148
156
 
149
157
  Use a structured `ChangeContract` as the Gate A `contract` for new designs: `goal`, `acceptance` (stable `id`, accepted `statement`, complete structured `verification`), `constraints` (stable `id` and `statement`), and `policy` (`writeRoots`, allowed dependency names in `dependencies`, and `verificationModes`).
@@ -235,7 +243,7 @@ Each task must seal:
235
243
  - stable id, objective, exact dependencies and edge reasons;
236
244
  - exact phase-local read/write/delete paths and output producers;
237
245
  - Red, Green, optional Refactor structured verification and exact verification inputs;
238
- - task-affected and repair verification contracts;
246
+ - an original-revision `baselineVerification`, task-affected and repair verification contracts;
239
247
  - conflicts, resources, verification locks, dependency changes, impact closure, and existing-test evidence;
240
248
  - AGENTS impact/target and managed-only ownership;
241
249
  - precise context sufficient for a fresh Worker without a conversation transcript.
@@ -244,6 +252,25 @@ Seal the supporting repository files needed by the whole task, including callers
244
252
  Writes and deletes remain phase-local.
245
253
  This task-wide read authority is part of the proposal, not an ad hoc escalation during Implement.
246
254
  Keep tasks small enough for one complete patch using compact exact replacements, and separate independent outputs during planning.
255
+ Give each dependency its reason in task context: a consumed producer output, an unresolved shared interface, or a concrete resource constraint.
256
+ Use `summary.parallelism.initiallyRunnableGroup` to inspect the bounded, conflict-free initial group, assuming shared slots are available.
257
+ The labelled static pairs describe eventual compatibility; inspect producer waits, all serialization causes, and global verification barriers before claiming concurrency.
258
+ Runtime capacity and capabilities still require Implement admission.
259
+ Keep reads precise so unrelated module tasks can run concurrently; shared interface or manifest changes need one explicit owner and dependent consumers.
260
+
261
+ For work spanning independent modules, plan independent tasks that can fill the four shared Worker slots, followed by dependent integration where necessary.
262
+ Do not chain tasks merely to prescribe an order or put every task behind the same resource label.
263
+ Do not split a small task solely to increase Worker count.
264
+ Use `summary.implementation` to inspect the accepted amendment policy and stable acceptance/constraint IDs alongside the initial phase permissions.
265
+ Its `review-only` authority and `runtimePrerequisites: "not-assessed"` are explicit: it neither grants broader scope nor certifies a working environment.
266
+ Before finalizing, resolve known missing runners, supported execution profile, required services, and credentials with the user in Design when repository evidence cannot resolve them.
267
+ Record the observed prerequisites and recovery approach in `design.md`; retain the existing prohibition on executing product tests during Design.
268
+ Do not describe a known unavailable prerequisite as ready for unattended execution.
269
+
270
+ Task `baselineVerification` may be omitted only when every affected input is a safe regular file in the original snapshot; the compiler then projects that exact affected contract.
271
+ For a new Red test, declare its output and keep it in the phase, affected, repair, cumulative and post-apply contracts.
272
+ Bind the original baseline to executable existing regression coverage or an existing full suite, without creating that future test in the baseline or dropping acceptance.
273
+ An existing file which is also a future modification output remains readable at its original bytes for baseline verification.
247
274
 
248
275
  Impact closure must name affected existing tests and fixtures; a suite made only from newly added tests is insufficient.
249
276
  In `impactClosure.relatedTests`, `current-task` means this task edits that test: its path must appear in a phase's `write` set.
@@ -277,7 +304,7 @@ Do not hand-assemble canonical plan bytes, hashes, generated task Markdown, or r
277
304
  The canonical `ImplementPlan` contains:
278
305
 
279
306
  - tasks and regular-file outputs;
280
- - target/affected/full-suite baselines and normalized failure identity policy;
307
+ - target-contract identities, task original-baseline contracts, full-suite baseline and normalized failure identity policy;
281
308
  - change-level affected, full-suite, and post-apply verification;
282
309
  - an explicit `artifactCorrection.maxAttempts` of 2-3 attempts for a verification obligation and phase, including the initial attempt; operation ids, rollback lineage, route changes, task renaming, and rewording do not replenish it;
283
310
  - bounded in-boundary repair policy and attribution classes `pre-existing | introduced | unresolved | environment`;
@@ -286,7 +313,10 @@ The canonical `ImplementPlan` contains:
286
313
 
287
314
  Use the code-owned readiness proof to require an executable static closure with no diagnostics.
288
315
  A write set grants authority but never proves that an output exists.
289
- Every absent future input must be a unique declared output from a transitive dependency.
316
+ Every absent future input must be a unique declared output available at its consumer's phase: the same task's current/prior phase, or a completed transitive dependency.
317
+ Affected/repair consume final task outputs; cumulative and post-apply consume outputs at their global barriers.
318
+ A deletion must have a causally later rewrite before consumption.
319
+ Original baseline contracts cannot consume future outputs.
290
320
 
291
321
  ## Gate B and trusted delivery
292
322
 
@@ -40,6 +40,16 @@ Do not end the turn merely because a control call returns a nonterminal state.
40
40
  Follow its parent-owned continuation until verified completion or a concrete blocker that cannot be resolved within available capabilities and budgets.
41
41
  Keep routine decisions and repairs internal; give brief progress updates during sustained work and include material implementation choices in the final result.
42
42
 
43
+ Treat the accepted goal as active work until the control plane proves completion.
44
+ An internal pause is a checkpoint for the parent to investigate, repair, or replan, not the end of the user's request.
45
+ Design owns product decisions; Implement owns execution and chooses compliant technical solutions without handing those choices back to the user.
46
+ Use all available independent Worker slots through the engine's DAG scheduler; do not replace it with serial manual task calls or launch Workers outside the admitted graph.
47
+ If the parent ends a turn while an actionable continuation remains, the host can schedule another same-stage parent turn after rereading local status.
48
+ That continuation is internal workflow guidance, not a new user request or additional approval.
49
+ Follow its current control-plane evidence; never replay an old command solely because it appeared in an earlier reminder.
50
+ Repeated status reads and identical failed operations are not progress: change the recovery strategy, gather concrete evidence, or preserve the run with the specific remaining external condition.
51
+ Explicit cancellation, stage exit, or an interrupted model turn stops automatic continuation.
52
+
43
53
  ## Trusted admission
44
54
 
45
55
  Before the first Worker launch, load the current `ready.yaml` and referenced canonical `implement-plan.json`; verify both current owner-private Gate proofs and the finalization fact binding the exact delivery revision, receipt hash, and canonical plan hash, plus the Gate A binding, raw and canonical hashes, OpenSpec strict/planning status, Requirement → Scenario → Verification → Task traceability, capability closure, exact path/output contracts, repair policy, tracking contract, and sealed AGENTS operations.
@@ -79,8 +89,12 @@ Discovery never admits the delivery: `resume` still performs the full artifact,
79
89
 
80
90
  ## Execution and verification
81
91
 
82
- Before any candidate, the engine records target-contract, task-affected, and full-suite baselines with normalized failure identities.
92
+ Before a task's candidate, the engine records that task's explicit original-baseline contract and the global full-suite baseline with normalized failure identities.
93
+ Task baselines are collected on demand and cached by contract, original revision, owner and environment; a local unavailable baseline does not require unrelated tasks to stop.
94
+ The immutable original snapshot remains the source after amendments.
95
+ Later main-workspace additions cannot repair its missing inputs.
83
96
  A pre-existing failure remains separate and never satisfies Red or becomes evidence that this change caused it.
97
+ Only comparable verification obligations can reuse failure attribution; new tests remain part of affected, cumulative and final acceptance.
84
98
 
85
99
  For each ready behavior task the engine runs:
86
100
 
@@ -90,6 +104,9 @@ For each ready behavior task the engine runs:
90
104
  4. Parent-owned task completion and exactly one `tasks.md` checkbox update in the private cumulative revision.
91
105
 
92
106
  Independent tasks may merge only after currentness and declared conflict checks.
107
+ The engine shares four execution slots across runs and refills them after individual task settlement, including capacity released by another run.
108
+ Dependencies consume only completed producer tasks and valid outputs.
109
+ Cancellation and close wait for every launched operation to settle before resources are released.
93
110
  Conflicting tasks remain durably queued without spending a Worker attempt.
94
111
  Workers make one atomic structured-patch submission whose operations stay within their approved write/delete sets; unused authorized paths need not be touched.
95
112
  The trusted submit tool validates exact replacements and file operations, generates the unified diff, and owns internal chunking, hashes, byte limits, and sealing; Workers never hand-author hunk ranges or write the workspace, AGENTS, task state, or the main repository.
@@ -111,10 +128,13 @@ Ordinary failures stay inside this Implement run:
111
128
  A run shares one cumulative work budget: 24 plus three units per largest admitted phase count, bounded by the host limit captured at run start (default 512).
112
129
  Recompiling, renaming or returning to a previous plan size never adds credit; a genuinely larger admitted decomposition may increase capacity without refunding consumption.
113
130
  Execution reserves work durably before launch, including nested repair proposals; restart and post-launch cancellation do not refund consumed work.
114
- - `environment` or `verification-adapter`: the executor pauses without speculative edits.
131
+ - `environment` or `verification-adapter`: the affected task pauses while safe independent work continues; required global verification remains a completion barrier.
115
132
  The parent inspects local diagnostics and restores available prerequisites using existing authorized capabilities, then resumes; baseline facts and completed phases are reused.
116
133
  Do not request user input for a prerequisite the parent can restore.
117
134
  Missing external credentials or unavailable services are reported only after local alternatives have been checked.
135
+ A retained baseline prerequisite identifies its owner, original revision, input/producer or capability, and minimum recovery condition.
136
+ Repeating resume with the same failure prerequisites does not repeat the failed verification or launch a Worker.
137
+ A changed observable environment or valid revised contract permits bounded recovery within the retained budgets.
118
138
  - `pre-existing`: keep as baseline evidence.
119
139
  It does not authorize a code change and does not fail completion unless the change worsens it.
120
140
  - `introduced` in a task-affected contract: reopen the owning task as `repairable`, perform the minimum bounded repair inside its approved paths, record `repair-verified`, and re-run attribution automatically.
@@ -141,6 +161,12 @@ A rebind may repair endpoint configuration but does not grant a new incident bud
141
161
  If a revised delivery already exists, local status also discovers its exact revision/hash for an exhausted run; resume with `availableDelivery` without asking the user to copy receipt data.
142
162
  When `recovery.additionalAttempt` is present, the parent may make a concrete decision to retry once within remaining work capacity.
143
163
  Copy that object into an ordinary resume request's optional `recovery` field; do not invent incident keys or failure sequences.
164
+ When `continuation.kind` is `inspect-recovery`, use its bounded diagnostic and recommendation to choose the next recovery strategy before issuing another execution command.
165
+ This object has no dispatch `action` or `command`; never submit it as tool arguments.
166
+ For an exhausted incident, `conditionalCommands` supplies a resume conditional on the exact retained recovery grant even though ordinary unqualified resume is unavailable.
167
+ An evidence-bound correction batch may also permit revising the task decomposition or context within the accepted contract.
168
+ Choose a concrete correction from the retained failure, preserve completed work, and resume only after the relevant prerequisites or compiled delivery are valid.
169
+ For a capability or route investigation, use the available parent tools to establish what changed before resuming; do not repeatedly probe an unchanged prerequisite.
144
170
  The default reason is `parent-directed-retry`; `route-changed` and `context-extended` additionally require control-plane evidence.
145
171
  This consumes one launch without resetting automatic correction history; another failure pauses again.
146
172
  Do not turn the availability of this option into an unconditional retry loop or another user approval round.
@@ -159,14 +185,17 @@ The parent resolves new implementation choices with its recommended option under
159
185
  `approval-needed` is an internal requirement to compile updated authority before a Worker continues, not a request for user input.
160
186
  `decisionBatch.resolution` identifies the parent as decision owner and `continuation` identifies the automatic next action.
161
187
  Follow it in this turn.
162
- `owner` and `automatic` are status metadata, not tool arguments.
188
+ `owner`, `automatic`, `kind`, `reason`, and `metadata` are status guidance, not tool arguments.
163
189
  For amendment use the exact `decisionBatch.continuation` envelope plus `request`; for resume send the closed command envelope with a new operationId.
164
190
  A changed batch must cite the new evidence; never ask separately for each task's copy of the same decision.
165
191
  Retain the Implement stage and original run.
166
192
  `decisionBatch.continuation` supplies the exact `action: "amend"`, change, and batchId for the narrow private artifact revision channel.
167
193
  After selecting the recommended solution, use that envelope with a `request` containing the existing closed Design artifact operations: start the same change, retain inherited decisions, record the parent-selected changes, write the required change artifacts, compile, and finalize.
168
194
  This is implementation delegation from the accepted Design, not a fabricated new user answer.
169
- The same channel is available for the allowlisted `delivery-invalid`, `needs-task-split`, and `task-split-needed` technical pauses; these do not need a user decision or a fabricated approval-needed classification.
195
+ The same channel is available for `needs-task-split`, `task-split-needed`, and original-baseline defects proven by parent-owned prerequisite evidence and included in the current batch.
196
+ A bare `delivery-invalid` or `input-missing` code supplies no amendment authority.
197
+ Unsafe paths, unknown errors, receipt/hash and currentness failures require restoration of trusted prerequisites.
198
+ Baseline-only amendments retain compatible committed phases and task evidence, and invalidate only incompatible baseline/attribution evidence; they preserve the run and budgets.
170
199
  Each run permits 64 mutating amendment attempts in a dedicated persistent budget.
171
200
  Failed writes/compilations consume that budget, successful operation replay is free, and restart or a new batch does not replenish it.
172
201
  Read-only status/preflight does not consume it.
@@ -183,11 +212,14 @@ This channel does not activate Design, admit evidence packets, allow a different
183
212
  Keep the approved goal and explicit constraints stable.
184
213
  Automatic amendments retain Gate A and the structured ChangeContract.
185
214
  They cannot renew Gate A, replace behavior decisions, or rewrite proposal/spec artifacts.
215
+ Even when a Worker classifies its preferred option as requiring Gate A, choose an alternative that satisfies the existing accepted behavior; the batch does not authorize renewing that Gate.
186
216
  Resolve implementation gaps within the accepted goal, constraints and policy; when no conforming solution exists, report that concrete contract blocker and preserve progress rather than repeatedly attempting an invalid amendment.
187
217
  Never weaken acceptance criteria just to obtain a passing result.
188
218
  The compiler supplies Gate B automatically.
189
219
  Finish all known items in the batch before finalizing, then issue ordinary resume.
190
220
  Local delivery discovery supplies the newer verified revision/hash; do not ask the user to copy receipts or switch commands.
221
+ After an explicit Implement invocation for a process-interrupted run, follow the returned `resume-interrupted-operation` or `settle-apply-recovery` continuation using the ordinary closed resume command.
222
+ Apply-journal settlement does not spend Worker work units; its continuation may remain available after those units are exhausted, and the engine still controls settlement before any further execution.
191
223
  An unchanged resume cannot bypass a pending decision, and stale batch ids or unrelated revision runIds are rejected.
192
224
  The user may explicitly choose a full Design discussion, but it is not the recovery instruction for an Implement blocker.
193
225
  A generated artifact defect, endpoint outage, stale snapshot, environment failure, pre-existing failure, introduced in-boundary repair, approved documentation/test edit, or approved AGENTS checkpoint is never `approval-needed`.
@@ -13,7 +13,6 @@ import {
13
13
  realpathSync,
14
14
  renameSync,
15
15
  rmdirSync,
16
- rmSync,
17
16
  unlinkSync,
18
17
  writeFileSync,
19
18
  } from "node:fs";
@@ -24,6 +23,8 @@ import type { ArtifactStore } from "./artifact-store.ts";
24
23
  import { compareCanonicalStrings } from "./canonical.ts";
25
24
  import { isValidRelativePath } from "./contracts.ts";
26
25
  import { syncDirectory } from "./directory-sync.ts";
26
+ import { isExecutionRetained } from "./execution-retention.ts";
27
+ import { removePathSync } from "./remove-path.ts";
27
28
  import { observeSafePath } from "./safe-path.ts";
28
29
  import { configureSqlite, ensureSqliteSchema } from "./sqlite-schema.ts";
29
30
  import { APPLY_SCHEMA } from "./storage-schema.ts";
@@ -161,6 +162,8 @@ export interface ApplyTransactionHooks {
161
162
  path: string;
162
163
  index: number;
163
164
  }) => void | Promise<void>;
165
+ /** Production executors settle their process scope before cancellation returns. */
166
+ awaitPostApplySettlement?: boolean;
164
167
  postApply?: (input: {
165
168
  transactionId: string;
166
169
  root: string;
@@ -412,10 +415,10 @@ function writeExclusiveFile(
412
415
  syncDirectory(directory);
413
416
  return true;
414
417
  } catch (error) {
415
- rmSync(temporary, { force: true });
418
+ removePathSync(temporary, { force: true });
416
419
  throw error;
417
420
  } finally {
418
- rmSync(temporary, { force: true });
421
+ removePathSync(temporary, { force: true });
419
422
  }
420
423
  }
421
424
 
@@ -587,7 +590,8 @@ export async function verifyCumulativeRevision(
587
590
  verificationId: input.verificationId,
588
591
  };
589
592
  } finally {
590
- rmSync(temporary, { recursive: true, force: true });
593
+ if (!isExecutionRetained(temporary))
594
+ removePathSync(temporary, { recursive: true, force: true });
591
595
  }
592
596
  }
593
597
 
@@ -1247,11 +1251,13 @@ export class ApplyTransaction {
1247
1251
  }),
1248
1252
  );
1249
1253
  void execution.catch(() => undefined);
1250
- postApply = signal
1251
- ? await raceWithAbort(execution, signal)
1252
- : await execution;
1254
+ postApply =
1255
+ signal && !this.#hooks.awaitPostApplySettlement
1256
+ ? await raceWithAbort(execution, signal)
1257
+ : await execution;
1253
1258
  } finally {
1254
- rmSync(isolatedRoot, { recursive: true, force: true });
1259
+ if (!isExecutionRetained(isolatedRoot))
1260
+ removePathSync(isolatedRoot, { recursive: true, force: true });
1255
1261
  }
1256
1262
  }
1257
1263
  } catch (error) {
@@ -1260,6 +1266,13 @@ export class ApplyTransaction {
1260
1266
  if (settled) return settled;
1261
1267
  if (!journal.pendingIntent && !signal?.aborted) throw error;
1262
1268
  }
1269
+ if (isExecutionRetained(this.root)) {
1270
+ journal = this.#load(transactionId);
1271
+ journal.state = "recovering";
1272
+ journal.code = "isolation-termination-unconfirmed";
1273
+ this.#save(journal);
1274
+ return { ok: false, transactionId, state: "paused", code: journal.code };
1275
+ }
1263
1276
  journal = this.#load(transactionId);
1264
1277
  const settled = this.#settledOutcome(journal);
1265
1278
  if (settled) return settled;
@@ -1350,6 +1363,13 @@ export class ApplyTransaction {
1350
1363
  ): Promise<ApplyTransactionOutcome> {
1351
1364
  const existing = this.#active.get(transactionId);
1352
1365
  if (existing) return existing.promise;
1366
+ if (isExecutionRetained(this.root))
1367
+ return Promise.resolve({
1368
+ ok: false,
1369
+ transactionId,
1370
+ state: "paused",
1371
+ code: "isolation-termination-unconfirmed",
1372
+ });
1353
1373
  const controller = new AbortController();
1354
1374
  const forwardAbort = () => {
1355
1375
  if (!controller.signal.aborted) {
@@ -0,0 +1,95 @@
1
+ // Explicit operator/release build only. Never invoked on import, install or verification.
2
+ import { spawnSync } from "node:child_process";
3
+ import { createHash } from "node:crypto";
4
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ function main() {
9
+ const args = process.argv.slice(2);
10
+ if (
11
+ process.platform !== "win32" ||
12
+ process.arch !== "x64" ||
13
+ args.length !== 2 ||
14
+ args[0] !== "--output"
15
+ )
16
+ throw new Error(
17
+ "Windows x64 required; usage: node build-windows-job.mjs --output <directory>",
18
+ );
19
+ const output = path.resolve(args[1]);
20
+ const compiler = path.join(
21
+ process.env.VCToolsInstallDir ?? "",
22
+ "bin/Hostx64/x64/cl.exe",
23
+ );
24
+ if (!path.isAbsolute(compiler))
25
+ throw new Error(
26
+ "Select the installed MSVC x64 developer environment first",
27
+ );
28
+ const sdkVersion = process.env.WindowsSDKVersion?.replace(/[\\/]+$/u, "");
29
+ if (!sdkVersion || !/^10\.0\.\d+\.0$/u.test(sdkVersion))
30
+ throw new Error("Windows 10 SDK required");
31
+ const version = spawnSync(compiler, [], {
32
+ shell: false,
33
+ encoding: "utf8",
34
+ timeout: 10000,
35
+ maxBuffer: 16384,
36
+ });
37
+ const compilerVersion =
38
+ `${version.stdout ?? ""}${version.stderr ?? ""}`.match(
39
+ /19\.(?:3\d|4\d)\.\d+/u,
40
+ )?.[0];
41
+ if (!compilerVersion) throw new Error("MSVC 19.3x/19.4x required");
42
+ mkdirSync(output, { recursive: true });
43
+ const source = fileURLToPath(new URL("./windows-job.c", import.meta.url));
44
+ const helper = path.join(output, "windows-job.exe");
45
+ rmSync(`${helper}.json`, { force: true });
46
+ rmSync(helper, { force: true });
47
+ const result = spawnSync(
48
+ compiler,
49
+ [
50
+ "/nologo",
51
+ "/W4",
52
+ "/WX",
53
+ "/O2",
54
+ "/MT",
55
+ "/utf-8",
56
+ "/DUNICODE",
57
+ "/D_UNICODE",
58
+ source,
59
+ `/Fe:${helper}`,
60
+ `/Fo:${path.join(output, "windows-job.obj")}`,
61
+ ],
62
+ {
63
+ shell: false,
64
+ cwd: output,
65
+ encoding: "utf8",
66
+ timeout: 60000,
67
+ maxBuffer: 65536,
68
+ },
69
+ );
70
+ writeFileSync(
71
+ path.join(output, "build.log"),
72
+ `${result.stdout ?? ""}${result.stderr ?? ""}`,
73
+ );
74
+ if (result.error || result.status !== 0)
75
+ throw new Error("Native build failed; inspect build.log");
76
+ const hash = (file) =>
77
+ createHash("sha256").update(readFileSync(file)).digest("hex");
78
+ writeFileSync(
79
+ `${helper}.json`,
80
+ `${JSON.stringify({ version: 2, arch: "x64", sourceSha256: hash(source), helperSha256: hash(helper), compilerSha256: hash(compiler), compilerVersion, sdkVersion }, null, 2)}\n`,
81
+ { flag: "wx" },
82
+ );
83
+ console.log(`Built ${helper}`);
84
+ }
85
+ if (
86
+ process.argv[1] &&
87
+ path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)
88
+ ) {
89
+ try {
90
+ main();
91
+ } catch (error) {
92
+ console.error(error.message);
93
+ process.exitCode = 1;
94
+ }
95
+ }
@@ -21,6 +21,12 @@ export function runGitApply(
21
21
  const child = spawn(
22
22
  "git",
23
23
  [
24
+ // Candidate patches bind exact bytes, independent of host checkout
25
+ // preferences. Git's Windows autocrlf default must not rewrite them.
26
+ "-c",
27
+ "core.autocrlf=false",
28
+ "-c",
29
+ "core.eol=lf",
24
30
  "apply",
25
31
  ...(checkOnly ? ["--check"] : []),
26
32
  "--recount",