@fitlab-ai/agent-infra 0.11.7 → 0.11.8

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 (95) hide show
  1. package/dist/bin/internal-cli.js +8 -2
  2. package/dist/lib/agent-clients/adapters/codex.js +1 -1
  3. package/dist/lib/agent-clients/config.js +11 -3
  4. package/dist/lib/defaults.json +6 -3
  5. package/dist/lib/internal/cli-route-inventory.js +3 -0
  6. package/dist/lib/internal/platform-pr-review.js +20 -3
  7. package/dist/lib/internal/task-operation-registry.js +3 -1
  8. package/dist/lib/internal/task-platform-recovery.js +56 -0
  9. package/dist/lib/merge.js +25 -5
  10. package/dist/lib/platform/completion-backfill.js +2 -1
  11. package/dist/lib/platform/in-label-sync.js +12 -1
  12. package/dist/lib/platform/issue-comments.js +58 -4
  13. package/dist/lib/platform/issues.js +105 -5
  14. package/dist/lib/platform/operation-coordinator.js +74 -0
  15. package/dist/lib/platform/pr-review.js +107 -1
  16. package/dist/lib/platform/pr-summary.js +79 -57
  17. package/dist/lib/platform/pull-requests.js +96 -4
  18. package/dist/lib/sandbox/commands/create.js +6 -3
  19. package/dist/lib/sandbox/commands/ls.js +4 -3
  20. package/dist/lib/sandbox/commands/rm.js +1 -1
  21. package/dist/lib/sandbox/config.js +22 -4
  22. package/dist/lib/sandbox/git-metadata.js +50 -0
  23. package/dist/lib/sandbox/index.js +1 -1
  24. package/dist/lib/sandbox/mounts.js +12 -0
  25. package/dist/lib/sandbox/recovery.js +11 -0
  26. package/dist/lib/sandbox/removal.js +58 -20
  27. package/dist/lib/sandbox/tools.js +29 -7
  28. package/dist/lib/task/activity-intent.js +4 -3
  29. package/dist/lib/task/create-service.js +5 -3
  30. package/dist/lib/task/create.js +22 -5
  31. package/dist/lib/task/finalization-artifacts.js +4 -1
  32. package/dist/lib/task/finalization.js +157 -24
  33. package/dist/lib/task/lifecycle.js +38 -2
  34. package/dist/lib/task/platform-operation-journal.js +152 -0
  35. package/dist/lib/task/platform-operation-recovery.js +459 -0
  36. package/dist/lib/task/workflow-warning-intents.js +7 -1
  37. package/dist/lifecycle-build-manifest.json +3 -3
  38. package/lib/agent-clients/adapters/codex.ts +1 -1
  39. package/lib/agent-clients/config.ts +9 -3
  40. package/lib/defaults.json +6 -3
  41. package/lib/internal/cli-route-inventory.ts +2 -0
  42. package/lib/internal/platform-pr-review.ts +14 -3
  43. package/lib/internal/task-operation-registry.ts +3 -1
  44. package/lib/internal/task-platform-recovery.ts +53 -0
  45. package/lib/merge.ts +26 -6
  46. package/lib/platform/completion-backfill.ts +2 -1
  47. package/lib/platform/in-label-sync.ts +12 -0
  48. package/lib/platform/issue-comments.ts +59 -3
  49. package/lib/platform/issues.ts +103 -5
  50. package/lib/platform/operation-coordinator.ts +96 -0
  51. package/lib/platform/pr-review.ts +113 -1
  52. package/lib/platform/pr-summary.ts +22 -1
  53. package/lib/platform/pull-requests.ts +105 -5
  54. package/lib/sandbox/commands/create.ts +7 -8
  55. package/lib/sandbox/commands/ls.ts +4 -3
  56. package/lib/sandbox/commands/rm.ts +1 -1
  57. package/lib/sandbox/config.ts +23 -5
  58. package/lib/sandbox/git-metadata.ts +66 -0
  59. package/lib/sandbox/index.ts +1 -1
  60. package/lib/sandbox/mounts.ts +14 -0
  61. package/lib/sandbox/recovery.ts +13 -0
  62. package/lib/sandbox/removal.ts +57 -19
  63. package/lib/sandbox/tool-types.ts +1 -1
  64. package/lib/sandbox/tools.ts +36 -7
  65. package/lib/task/activity-intent.ts +4 -3
  66. package/lib/task/create-service.ts +5 -3
  67. package/lib/task/create.ts +17 -5
  68. package/lib/task/finalization-artifacts.ts +4 -1
  69. package/lib/task/finalization.ts +154 -21
  70. package/lib/task/lifecycle.ts +35 -3
  71. package/lib/task/platform-operation-journal.ts +230 -0
  72. package/lib/task/platform-operation-recovery.ts +435 -0
  73. package/lib/task/workflow-warning-intents.ts +9 -1
  74. package/package.json +1 -1
  75. package/templates/.agents/README.en.md +19 -17
  76. package/templates/.agents/README.zh-CN.md +18 -16
  77. package/templates/.agents/rules/README.en.md +1 -1
  78. package/templates/.agents/rules/README.zh-CN.md +1 -1
  79. package/templates/.agents/rules/task-management.en.md +12 -0
  80. package/templates/.agents/rules/task-management.zh-CN.md +12 -0
  81. package/templates/.agents/skills/cancel-task/SKILL.en.md +4 -2
  82. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +4 -2
  83. package/templates/.agents/skills/code-task/SKILL.en.md +2 -2
  84. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -2
  85. package/templates/.agents/skills/complete-task/SKILL.en.md +2 -0
  86. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +2 -0
  87. package/templates/.agents/skills/plan-task/config/verify.en.json +1 -1
  88. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -1
  89. package/templates/.agents/skills/review-pr/SKILL.en.md +11 -11
  90. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +11 -11
  91. package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +3 -3
  92. package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +3 -3
  93. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -0
  94. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -0
  95. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +19 -6
@@ -250,7 +250,7 @@ ai agent-client configure
250
250
 
251
251
  TraeCode CLI 以 `.agents/skills/` 作为 Skill 的唯一权威源。agent-infra 仅在 `.traecli/commands/` 下生成轻量 slash-command 包装文件;每个包装文件读取对应的共享 Skill,并在该 Skill 声明参数时转发 `$ARGUMENTS`。它不会把 Skill 包镜像到 `.trae/skills/`;该目录继续由用户所有,仅用于有意添加的 Trae 专属覆盖。
252
252
 
253
- `agentClients` 是内建客户端状态的唯一配置来源。顶层数组必须按固定规范顺序包含全部五个内建客户端;`sandbox.tools` 只列出 `agent-infra` 和自定义工具等非客户端工具。旧 `tuis` 字段或 `sandbox.tools` 中的内建客户端 id 会被拒绝,配置不会被自动改写。
253
+ `agentClients` 是内建客户端状态的唯一配置来源。顶层数组必须按固定规范顺序包含全部五个内建客户端;`sandbox.tools.ids` 按顺序列出 `agent-infra` 和自定义工具等非客户端工具,`sandbox.tools.definitions` 用工具 ID 键控自定义工具定义。旧 `tuis` 字段或 `sandbox.tools.ids` 中的内建客户端 id 会被拒绝,配置不会被自动改写。
254
254
 
255
255
  ### 取消 Agent Client 的副作用
256
256
 
@@ -258,7 +258,7 @@ TraeCode CLI 以 `.agents/skills/` 作为 Skill 的唯一权威源。agent-infra
258
258
 
259
259
  ### 与其他配置字段的关系
260
260
 
261
- - `sandbox.tools` 现在只列出 `agent-infra` 和自定义工具等非客户端工具。内建客户端的安装状态由 `agentClients[].installInSandbox` 表达。
261
+ - `sandbox.tools.ids` 只列出 `agent-infra` 和自定义工具等非客户端工具;自定义定义放在 `sandbox.tools.definitions`。内建客户端的安装状态由 `agentClients[].installInSandbox` 表达。
262
262
  - `agentClients` 与 `customTUIs`(见下)相互独立。即使自定义 TUI 目录落在已取消的内建客户端路径前缀下,其命令文件也会被保留。
263
263
 
264
264
  ## 自定义 TUI 配置
@@ -311,13 +311,13 @@ TraeCode CLI 以 `.agents/skills/` 作为 Skill 的唯一权威源。agent-infra
311
311
 
312
312
  ## 沙箱自定义工具(Sandbox Custom Tools)
313
313
 
314
- `customTUIs` 只负责生成 slash-command 文件,**不影响沙箱镜像**。如果要把一个非 npm 分发的 CLI 或工具(pip / cargo / curl 脚本 / 裸二进制)装进沙箱镜像、并 live-mount 它的凭证目录,需要在 `.agents/.airc.json` 的 `sandbox.customTools` 中声明。内建 Agent Client 按 `agentClients[].installInSandbox` 安装;`agent-infra` 仍是 `sandbox.tools` 中的非客户端条目,只提供沙箱内的 `ai` / `agent-infra` CLI。
314
+ `customTUIs` 只负责生成 slash-command 文件,**不影响沙箱镜像**。如果要把一个非 npm 分发的 CLI 或工具(pip / cargo / curl 脚本 / 裸二进制)装进沙箱镜像、并 live-mount 它的凭证目录,需要在 `.agents/.airc.json` 的 `sandbox.tools.definitions` 中按工具 ID 声明。内建 Agent Client 按 `agentClients[].installInSandbox` 安装;`agent-infra` 仍是 `sandbox.tools.ids` 中的非客户端条目,只提供沙箱内的 `ai` / `agent-infra` CLI。
315
315
 
316
316
  ### 必填字段
317
317
 
318
318
  | 字段 | 含义 |
319
319
  |------|------|
320
- | `id` | 小写 id,匹配 `^[a-z0-9][a-z0-9-]*$`;由 `sandbox.tools` 引用;不可与内建 id 冲突。 |
320
+ | 定义对象的键 | 小写工具 ID,匹配 `^[a-z0-9][a-z0-9-]*$`;`ids` 中选用的自定义工具必须有对应定义;未列入 `ids` 的定义可以保留为未启用工具;不可与内建 id 冲突。 |
321
321
  | `install` | 安装描述符。`{ "type": "npm", "cmd": "<npm 包规范>" }` 执行 `npm install -g <cmd>`;`{ "type": "shell", "cmd": "<shell>" }` 在镜像构建阶段以 `devuser` 执行 shell。`cmd` 必须非空。 |
322
322
 
323
323
  最小入口——把一个工具装进镜像所需的契约只有这两个字段:
@@ -325,13 +325,14 @@ TraeCode CLI 以 `.agents/skills/` 作为 Skill 的唯一权威源。agent-infra
325
325
  ```json
326
326
  {
327
327
  "sandbox": {
328
- "tools": ["my-shell-tool"],
329
- "customTools": [
330
- {
331
- "id": "my-shell-tool",
332
- "install": { "type": "shell", "cmd": "curl -fsSL https://example.com/install.sh | bash" }
328
+ "tools": {
329
+ "ids": ["my-shell-tool"],
330
+ "definitions": {
331
+ "my-shell-tool": {
332
+ "install": { "type": "shell", "cmd": "curl -fsSL https://example.com/install.sh | bash" }
333
+ }
333
334
  }
334
- ]
335
+ }
335
336
  }
336
337
  }
337
338
  ```
@@ -352,24 +353,25 @@ TraeCode CLI 以 `.agents/skills/` 作为 Skill 的唯一权威源。agent-infra
352
353
  | `hostLiveMounts` | (无) | 把宿主凭证(如 OAuth token)实时挂进容器,读写共享。 |
353
354
  | `postSetupCmds` | (无) | 首次安装完成后在容器内执行命令(如建符号链接)。 |
354
355
 
355
- > **`sandboxBase` 不由用户配置。** loader 永远使用 `~/.agent-infra/sandboxes/<id>`,这样 `ai sandbox rm` / `prune` 才能找到工具状态目录。`customTools` 条目里写的任何 `sandboxBase` 都会被静默忽略。
356
+ > **`sandboxBase` 不由用户配置。** loader 永远使用 `~/.agent-infra/sandboxes/<id>`,这样 `ai sandbox rm` / `prune` 才能找到工具状态目录。定义对象里写的任何 `sandboxBase` 都会被静默忽略。
356
357
 
357
358
  实际场景示例——`anthropic-claude` 作为用户自定义 id,二进制名是 `claude`,并把宿主凭证 live-mount 进来:
358
359
 
359
360
  ```json
360
361
  {
361
362
  "sandbox": {
362
- "tools": ["claude-code", "anthropic-claude"],
363
- "customTools": [
364
- {
365
- "id": "anthropic-claude",
363
+ "tools": {
364
+ "ids": ["anthropic-claude"],
365
+ "definitions": {
366
+ "anthropic-claude": {
366
367
  "install": { "type": "npm", "cmd": "@anthropic-ai/claude-code@stable" },
367
368
  "versionCmd": "claude --version",
368
369
  "hostLiveMounts": [
369
370
  { "hostPath": "~/.claude/.credentials.json", "containerSubpath": ".credentials.json" }
370
371
  ]
372
+ }
371
373
  }
372
- ]
374
+ }
373
375
  }
374
376
  }
375
377
  ```
@@ -29,7 +29,7 @@ so you can quickly find "which ones to read" without opening each file.
29
29
 
30
30
  ## Task Workflow
31
31
 
32
- - [`task-management.md`](task-management.md) — Task intent detection and workflow-command mapping.
32
+ - [`task-management.md`](task-management.md) — Task intent detection, workflow-command mapping, and skill blocking boundaries.
33
33
  - [`lifecycle-orchestration.md`](lifecycle-orchestration.md) — Fresh executor/reviewer, one-use receipt, pause/recovery, and safe endpoint rules for `run-task`.
34
34
  - [`review-handshake.md`](review-handshake.md) — Three-stage bidirectional review handshake: four-state disposition, symmetric evidence, disagreement ledger, convergence and post-review commit gate.
35
35
  - [`review-method.md`](review-method.md) — Shared three-stage review method: multi-pass review, risk lenses, traceability, and finding evidence.
@@ -28,7 +28,7 @@
28
28
 
29
29
  ## 任务工作流
30
30
 
31
- - [`task-management.md`](task-management.md) — 任务语义识别与工作流命令映射。
31
+ - [`task-management.md`](task-management.md) — 任务语义识别、工作流命令映射与技能阻塞边界。
32
32
  - [`lifecycle-orchestration.md`](lifecycle-orchestration.md) — `run-task` 的 fresh executor/reviewer、一次性 receipt、暂停恢复与安全终点规则。
33
33
  - [`review-handshake.md`](review-handshake.md) — 三阶段双向审查握手协议:四态处置、对称证据、分歧账本、收敛与 post-review commit 门禁。
34
34
  - [`review-method.md`](review-method.md) — 三阶段共享检视方法:多遍检视、风险镜头、追踪与 finding 证据契约。
@@ -36,6 +36,18 @@ The seven internal commands (`task-event` / `task-lifecycle` / `task-finalizatio
36
36
  - `task-verify` executes the typed catalog/check registry in-process; skills declare business events only.
37
37
  - Both entrypoints are read-only. Verification exits remain `0=pass`, `1=fail`, and `2=blocked`; network or platform blocking must never be downgraded to success.
38
38
 
39
+ ## Platform Results and Skill Blocking Boundaries
40
+
41
+ A `blocked` platform write means only that the operation is unfinished. Whether the skill stops depends on its delivery goal. The typed core handles write queuing, recovery, and idempotency; skills consume structured results and do not replay writes themselves.
42
+
43
+ - `import-issue`: stop importing when the source Issue cannot be read.
44
+ - `create-pr`: stop the creation flow when the PR was not created or its identity cannot be confirmed.
45
+ - `review-pr`: stop reviewing when the PR or reviewed head cannot be read. After local review is complete, record recoverable comment or formal Review write failures as the skill specifies without blocking the completed local review.
46
+ - `cancel-task`: apply the skill's full cancellation criteria; do not claim full cancellation when required Issue synchronization fails.
47
+ - `complete-task`: apply the skill's full completion criteria; resolve pending recoverable operations before archiving and do not claim completion while required remote facts remain unconfirmed.
48
+
49
+ Other skills continue past deferrable writes according to their local delivery goals. If `create-task` has created the local task but creation of the associated Issue fails, retain the local task and record the failure so independent subsequent work can continue.
50
+
39
51
  ## Required State Updates by Command
40
52
 
41
53
  - `create-task`: create `branch`, `workflow`, `status`, `created_at`, `updated_at`, `assigned_to`, `agent_infra_version`
@@ -36,6 +36,18 @@
36
36
  - `task-verify` 在进程内执行 typed catalog/check registry;SKILL 只声明业务事件,不传 task-dir、skill 名或特殊 check 序列。
37
37
  - 两个入口均保持只读;验证退出码固定为 `0=pass`、`1=fail`、`2=blocked`,网络或平台阻塞不得降格为成功。
38
38
 
39
+ ## 平台结果与技能阻塞边界
40
+
41
+ 平台写入返回 `blocked` 只表示该操作尚未完成;技能是否停止由当前技能的交付目标决定。平台写入的排队、恢复和幂等由 typed core 执行,技能只消费结构化结果,不自行重放。
42
+
43
+ - `import-issue`:源 Issue 读取失败时停止导入。
44
+ - `create-pr`:PR 未创建或无法确认其身份时停止创建流程。
45
+ - `review-pr`:PR 或被审 head 无法读取时停止审查;本地审查完成后,评论或正式 Review 写入失败按技能记录待恢复事实,不阻断已完成的本地审查。
46
+ - `cancel-task`:按技能的完整取消标准判断;必要的 Issue 同步失败时不得宣称取消全部完成。
47
+ - `complete-task`:按技能的完整完成标准判断;归档前收敛待恢复操作,必要的远端事实未确认时不得宣称任务完成。
48
+
49
+ 其他技能按各自的本地交付目标继续处理可延后写入。`create-task` 已在本地创建任务、但伴生 Issue 创建失败时,保留本地任务并记录失败,不停止后续可独立执行的工作。
50
+
39
51
  ## 常见命令的状态更新要求
40
52
 
41
53
  - `create-task`:创建 `branch`、`workflow`、`status`、`created_at`、`updated_at`、`assigned_to`、`agent_infra_version`
@@ -39,11 +39,13 @@ Check these directories in order:
39
39
 
40
40
  Handling rules:
41
41
  - If found in `active/` or `blocked/`: continue
42
- - If found only in `completed/`: inform the user the task is already moved and stop
42
+ - If found only in `completed/` with valid `cancelled_at` and `cancel_reason`, reuse the recorded reason, skip Steps 3-5, and continue at Step 6 to recover Issue closure and comments; stop for other completed tasks
43
43
  - If not found anywhere: prompt `Task {task-id} not found`
44
44
 
45
45
  ### 2. Choose the Cancellation Label
46
46
 
47
+ When retrying a completed task, use only the `cancel_reason` already recorded in `task.md`; do not replace it with new input.
48
+
47
49
  Infer the Issue closing label from the cancellation reason:
48
50
  - `status: superseded`: reason implies duplicate, replaced, merged into, or already covered by another Issue or PR
49
51
  - `status: invalid`: reason implies invalid report, no real problem, cannot reproduce, or no issue after investigation
@@ -76,7 +78,7 @@ Confirm the task directory was moved successfully.
76
78
 
77
79
  Check whether `task.md` contains a valid `platform_issue_identity`. If not, skip this step.
78
80
 
79
- If a valid `platform_issue_identity` exists:
81
+ If a valid `platform_issue_identity` exists, require `applied` / `no-op` without an error for every operation before declaring cancellation fully complete. On failure, retain the local terminal state and recovery record, then retry this skill for the same task after repair:
80
82
  - Run `agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --status {reason} --in-labels none --assignees none --milestone none --state closed --close-reason not_planned`
81
83
  - Write the cancellation body to a temporary file and run `agent-infra-internal platform-comment sync {task-id} --kind cancel --body-file {path} --agent {standard-agent-token}`
82
84
  - Run `agent-infra-internal platform-comment sync {task-id} --kind task --agent {standard-agent-token}`
@@ -38,11 +38,13 @@ description: >
38
38
 
39
39
  处理规则:
40
40
  - 如果在 `active/` 或 `blocked/` 中找到:继续
41
- - 如果只在 `completed/` 中找到:告知用户任务已转移,停止
41
+ - 如果只在 `completed/` 中找到且 `cancelled_at` 与 `cancel_reason` 有效:复用已记录的取消原因,跳过步骤 3-5,继续步骤 6 补齐 Issue 关闭与评论;其他 completed 任务停止
42
42
  - 如果都不存在:提示 `Task {task-id} not found`
43
43
 
44
44
  ### 2. 判断取消标签
45
45
 
46
+ 从 completed 任务重试时,只使用 `task.md` 已记录的 `cancel_reason`,不得采用本次输入改写取消原因。
47
+
46
48
  根据取消原因推断 Issue 关闭标签:
47
49
  - `status: superseded`:原因包含“重复”、“替代”、“合并到”、“已由 #123 / PR 替代”等语义
48
50
  - `status: invalid`:原因包含“误报”、“不存在”、“无法复现”、“排查后无问题”等语义
@@ -75,7 +77,7 @@ ls .agents/workspace/completed/{task-id}/task.md
75
77
 
76
78
  检查 `task.md` 中是否存在有效的 `platform_issue_identity`。如果没有,跳过此步骤。
77
79
 
78
- 如果存在有效的 `platform_issue_identity`:
80
+ 如果存在有效的 `platform_issue_identity`,以下操作均须取得 `applied` / `no-op` 且无错误后才能宣称取消全部完成;失败时保留本地终态和待恢复记录,修复后以同一任务重试本技能:
79
81
  - 调用 `agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --status {reason} --in-labels none --assignees none --milestone none --state closed --close-reason not_planned`
80
82
  - 将取消正文写入临时文件,调用 `agent-infra-internal platform-comment sync {task-id} --kind cancel --body-file {path} --agent {standard-agent-token}`
81
83
  - 调用 `agent-infra-internal platform-comment sync {task-id} --kind task --agent {standard-agent-token}`
@@ -118,7 +118,7 @@ When triaging a test failure or unexpected behavior, first read `.agents/rules/d
118
118
 
119
119
  After tests pass, call the shared commit core with `agent-infra-internal git-workflow commit --input {checkpoint-input}`. Pass `delivery: { "mode": "local" }`, explicit paths, expected HEAD/tree, task ref, agent, and the code round. This creates only a local checkpoint and does not contact a remote. The core writes a durable intent before committing and removes it after task-writer synchronization; do not emit `code.completed` if either checkpoint or task synchronization fails.
120
120
 
121
- After the checkpoint succeeds, when task.md has a `platform_issue_identity`, run `agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --in-labels from-diff --base {delivery-base-ref}`. The task-bound `delivery_base_ref` is the only source for Issue `in:` evidence; record a warning and stop this round without emitting `code.completed` if this sync fails.
121
+ After the checkpoint succeeds, when task.md has a `platform_issue_identity`, run `agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --in-labels from-diff --base {delivery-base-ref}`. The task-bound `delivery_base_ref` is the only source for Issue `in:` evidence; record a warning and continue the local code stage if this sync fails. `complete-task` restores and verifies this evidence before archiving.
122
122
 
123
123
  ### 9. Write the Code Report
124
124
 
@@ -154,7 +154,7 @@ Do not rescan or manually write digest data; the completion event must include `
154
154
 
155
155
  After requirement checkboxes are updated, run the initial event `agent-infra-internal task-event {task-id} code.completed --agent {standard-agent-token} --initiator {trigger-initiator} --request-id {request-id} --reason-code {reason-code} --artifact {code-artifact} --artifact-sha256 {artifact-sha256} --semantic-digest {semantic-digest} --files-modified {n} --tests-passed {n} {execution-flag}`; in fix mode add `--fix-for {review-artifact} --blockers {n} --major {n} --minor {n} --manual-validation {n} {execution-flag}` instead; in decision mode add `--implementation-input {input-id}` to the initial counts. The core atomically records the artifact link, stage, metadata, done log, and decision-input consumption.
156
156
 
157
- If task.md has a valid `platform_issue_identity`, read `.agents/rules/issue-sync.md`, then (status/comment failures follow the warning rules; an Issue `in:` evidence failure must not emit `code.completed`):
157
+ If task.md has a valid `platform_issue_identity`, read `.agents/rules/issue-sync.md`, then run these syncs. Record failures as warnings and continue the local workflow:
158
158
  - Run `agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --status in-progress`
159
159
  - Run `agent-infra-internal platform-comment sync {task-id} --kind task --agent {standard-agent-token}`
160
160
  - Run `agent-infra-internal platform-comment sync {task-id} --kind artifact --artifact {code-artifact} --agent {standard-agent-token}`
@@ -155,7 +155,7 @@ echo "$result"
155
155
 
156
156
  测试通过后,先创建报告并运行 `task-artifact {task-id} preflight --family code --artifact {code-artifact}`;preflight 失败只允许在同一受控 candidate 中修复并完整重跑,且不得产生 checkpoint、ledger、completed 或平台副作用。preflight 通过后,才通过 `agent-infra-internal git-workflow commit --input {checkpoint-input}` 调用共享 commit core,输入 `delivery: { "mode": "local" }`、明确 paths、expected HEAD/tree、task ref、agent 和 code round。该调用只创建本地 checkpoint,不访问远端;core 会在 commit 前写入 durable intent,并在 task writer 成功后清理 intent。checkpoint 失败或 task 状态未闭合时,不得发送 `code.completed`。
157
157
 
158
- checkpoint 成功后,若任务存在 `platform_issue_identity`,调用 `agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --in-labels from-diff --base {delivery-base-ref}`,由 task-bound `delivery_base_ref` 产生 Issue 的 `in:` target;该同步失败时记录 warning 并停止本轮,不发送 `code.completed`。
158
+ checkpoint 成功后,若任务存在 `platform_issue_identity`,调用 `agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --in-labels from-diff --base {delivery-base-ref}`,由 task-bound `delivery_base_ref` 产生 Issue 的 `in:` target;同步失败时记录 warning,继续完成本地代码阶段。`complete-task` 在归档前补齐并核验该证据。
159
159
 
160
160
  排查测试失败或行为不符合预期时,先读取 `.agents/rules/debugging-guide.md`,按其四阶段流程定位根因,禁止盲目改代码重试。
161
161
 
@@ -199,7 +199,7 @@ echo "$finalizer"
199
199
  - 修复模式:`agent-infra-internal task-event {task-id} code.completed --agent {standard-agent-token} --initiator {trigger-initiator} --request-id {request-id} --reason-code {reason-code} --artifact {code-artifact} --artifact-sha256 {artifact-sha256} --semantic-digest {semantic-digest} --fix-for {review-artifact} --blockers {n} --major {n} --minor {n} --manual-validation {n} {execution-flag}`
200
200
  - 裁决模式:`agent-infra-internal task-event {task-id} code.completed --agent {standard-agent-token} --initiator {trigger-initiator} --request-id {request-id} --reason-code {reason-code} --artifact {code-artifact} --artifact-sha256 {artifact-sha256} --semantic-digest {semantic-digest} --implementation-input {input-id} --files-modified {n} --tests-passed {n} {execution-flag}`
201
201
 
202
- 如果 task.md 中存在有效的 `platform_issue_identity`,执行以下同步操作(状态/评论失败按规则记录 warning;Issue `in:` evidence 同步失败不得发送 `code.completed`;边界见 `.agents/rules/issue-sync.md`):
202
+ 如果 task.md 中存在有效的 `platform_issue_identity`,执行以下同步操作(失败按规则记录 warning,继续本地流程;边界见 `.agents/rules/issue-sync.md`):
203
203
  - 调用 `agent-infra-internal platform-issue sync {task-id} --agent {standard-agent-token} --status in-progress`
204
204
  - 调用 `agent-infra-internal platform-comment sync {task-id} --kind task --agent {standard-agent-token}`
205
205
  - 调用 `agent-infra-internal platform-comment sync {task-id} --kind artifact --artifact {code-artifact} --agent {standard-agent-token}`
@@ -178,6 +178,8 @@ If a summary must mirror a human-decided `post-review-commit` exemption, make a
178
178
  agent-infra-internal task-finalization {task-id} complete --agent {standard-agent-token}
179
179
  ```
180
180
 
181
+ For an active task, finalization first recovers pending platform operations, then syncs and rereads Issue `in:` labels from `delivery_base_ref` together with requirements, Issue Type, and fields. If a required fact cannot be confirmed, the task stays active and completion is not committed.
182
+
181
183
  Finalization runs allowed artifact backfill -> lifecycle -> terminal task comment -> core verification -> warning task-comment update -> summary seal in a fixed order. Every backfill that actually runs must reach a successful terminal result before lifecycle starts; an ordinary replay with a complete receipt and no recovery fact does not rerun backfill, comments, verification, or summary. A completed recovery that may write a managed comment first persists a done summary as pending, then seals it only at the end. Summary seal always reads the durable staging record retained in the task directory; the platform entry point validates marker, owner, and digest, performs any required delete/recreate, and reads back final remote order. `result=completed` means the host safely completed the task from structured results and the receipt; if peripheral warnings or pending steps remain, return `result=completed_with_warnings`, warnings, and pending steps. Use `result=failed` or `result=blocked` only for hard or receipt/capability failures, then fix the cause and retry through the same entry point; do not claim completion or hand-repair partial state. A sandbox must not run `ls completed` or a local terminal verification against its historical mount to re-decide this result.
182
184
 
183
185
  ### 7. Handle Finalization Retries and Results
@@ -177,6 +177,8 @@ agent-infra-internal task-verify {task-id} complete-task.preflight --format text
177
177
  agent-infra-internal task-finalization {task-id} complete --agent {standard-agent-token}
178
178
  ```
179
179
 
180
+ active 任务的 finalization 先恢复账本中的待处理平台操作,并将 `delivery_base_ref` 对应的 Issue `in:` 标签与需求、Issue Type、字段一并同步及复读。任一必要事实无法确认时保持 active,不提交完成状态。
181
+
180
182
  finalization 按允许的 artifact backfill → lifecycle → task 评论 → core verification → warning task 评论更新 → summary seal 的固定顺序执行。每项实际运行的 backfill 必须取得成功终态,否则不得进入 lifecycle;完整 receipt 且无恢复事实的普通重入不执行 backfill、评论、验证或 summary。任何可能写入 managed comment 的 completed 恢复会先把 done summary 持久化为 pending,恢复末尾才重新 seal。summary seal 始终读取任务目录中保留的 durable staging record;平台入口负责校验 marker、owner 和 digest,必要时删除并重建摘要,再复读最终远端顺序。`result=completed` 即表示宿主已依据结构化结果和 receipt 安全完成;若还有外围 warning 或 pending step,返回 `result=completed_with_warnings`、warnings 和 pending steps。`result=failed` 或 `result=blocked` 仅用于硬失败或 receipt/capability 失败,修复原因后以同一入口重试,不得宣称完成或手工补写局部状态。沙箱不得从旧挂载执行 `ls completed` 或本地终态校验来重新裁决该结果。
181
183
 
182
184
  ### 7. 处理 finalization 重试与结果
@@ -20,7 +20,7 @@
20
20
  "schema": "plan"
21
21
  },
22
22
  "activity-log": {
23
- "expected_action_pattern": "(Plan Task|Technical Design) \\(Round \\d+\\)"
23
+ "expected_action_pattern": "((Plan Task|Technical Design) \\(Round \\d+\\)|Human Decision)"
24
24
  },
25
25
  "review-ledger": {
26
26
  "stage_scope": [
@@ -20,7 +20,7 @@
20
20
  "schema": "plan"
21
21
  },
22
22
  "activity-log": {
23
- "expected_action_pattern": "(Plan Task|Technical Design) \\(Round \\d+\\)"
23
+ "expected_action_pattern": "((Plan Task|Technical Design) \\(Round \\d+\\)|Human Decision)"
24
24
  },
25
25
  "review-ledger": {
26
26
  "stage_scope": [
@@ -81,7 +81,7 @@ agent-infra-internal task-activity {task-id} pr-review-start --agent {agent} \
81
81
  --artifact {pr-review-artifact} --head {head-sha}
82
82
  ```
83
83
 
84
- The one-shot path never calls `task-activity`. For a controlled failure after started where the formal Review is known not to have been published, first set the artifact status to `aborted`, then call `pr-review-terminate --outcome aborted --reason <single-line>` with the same artifact/head. If publication outcome is uncertain, leave the round open rather than guessing aborted.
84
+ The one-shot path never calls `task-activity`. If reading the PR, confirming the head, or completing the local review fails, set the artifact status to `aborted` and call `pr-review-terminate --outcome aborted --reason <single-line>` with the same artifact/head. A publication failure after the local review is complete records recovery evidence instead of aborting the review round.
85
85
 
86
86
  ### 2. Single decide: evidence enumeration + classification + risk + mode
87
87
 
@@ -99,7 +99,7 @@ Complete this round's artifact per `reference/report-template.md`; the task-anch
99
99
 
100
100
  ### 4. Sync the Issue artifact comments (task-anchored path)
101
101
 
102
- Sync the task comment, then the artifact comment, and capture a stable comment URL:
102
+ Attempt the task and artifact comment syncs in order. Record warnings and recovery evidence on failure, then continue the local review:
103
103
 
104
104
  ```bash
105
105
  agent-infra-internal platform-comment sync {task-id} --kind task --agent {agent}
@@ -116,11 +116,11 @@ Read the remote head again to confirm it did not drift during the review:
116
116
  agent-infra-internal platform-pr-review inspect --pr {pr-number} [--cwd <path>]
117
117
  ```
118
118
 
119
- If the head matches step 1, assemble the body (head SHA / conclusion / findings / receipt / Issue artifact link, **without a marker**) and publish the formal Review:
119
+ If the head matches step 1, assemble the body (head SHA / conclusion / findings / receipt / available Issue artifact link; use the artifact identity when its comment is pending, **without a marker**). Write the entire body to `pr-review-body.md` (Round 1) or `pr-review-body-r{N}.md` (later rounds) beside the current report, and bind `{review-body-file}` to its absolute path. The report's `Formal Review Body` section records only that filename. For a task-anchored review, use the file in the task directory; recovery rereads it by round and checks its digest. Then publish the formal Review:
120
120
 
121
121
  ```bash
122
122
  agent-infra-internal platform-pr-review publish --pr {pr-number} --scope {taskId|pr{pr-number}} --round {round} \
123
- --commit {head-sha} --event {COMMENT|APPROVE|REQUEST_CHANGES} --body-file {review-body.md} [--dry-run] [--cwd <path>]
123
+ --commit {head-sha} --event {COMMENT|APPROVE|REQUEST_CHANGES} --body-file {review-body-file} --artifact {pr-review-artifact} --agent {agent} [--dry-run] [--cwd <path>]
124
124
  ```
125
125
 
126
126
  `publish` generates and validates the marker (first line) in core and is idempotent per marker + commit (replay is a no-op; marker hit on a different commit fails stably). On head drift, first set the old artifact status to `superseded`, then close the old round:
@@ -131,11 +131,11 @@ agent-infra-internal task-activity {task-id} pr-review-terminate --agent {agent}
131
131
  --outcome superseded --reason "head changed before publish"
132
132
  ```
133
133
 
134
- After closure, re-run step 1 for the next canonical round; never start the new round first. If the remote outcome of `publish` is uncertain, keep the round open and recover through marker + commit idempotency on retry.
134
+ After closure, re-run step 1 for the next canonical round; never start the new round first. If `publish` has an uncertain outcome and a durable task journal entry exists, keep the operation pending and finish the local review round. Keep the round open when recovery evidence cannot be proven durable.
135
135
 
136
136
  ### 6. Write back the publication result and task state
137
137
 
138
- - **Task-anchored path**: after publish returns `applied` / `no-op`, write the Review ID/URL and matching Formal Review Status into the `pr-review-rN.md` "Publication Result" section, then close the Activity Log with the exact verdict/counts frozen in step 3:
138
+ - **Task-anchored path**: write the actual publication status in the `pr-review-rN.md` "Publication Result" section. Record the Review ID/URL for `applied` / `no-op`; for a failed write with a durable journal entry, record `blocked` / `failed`, the error code, and recovery action. Then close the local Activity Log with the verdict/counts frozen in step 3:
139
139
 
140
140
  ```bash
141
141
  agent-infra-internal task-activity {task-id} pr-review-complete --agent {agent} \
@@ -145,11 +145,11 @@ After closure, re-run step 1 for the next canonical round; never start the new r
145
145
 
146
146
  `task-activity` generates `Verdict: <result>, blockers: N, major: N, minor: N → {pr-review-artifact}` from the typed payload and atomically writes the Activity Log, `## Review Feedback` link, and version stamp through `writeTask`. It never changes `current_step` or puts receipt/head/Review URL into the NOTE.
147
147
 
148
- - **One-shot path (no task)**: write the Review ID/URL only into the `pr-review-rN.md` "Publication Result" section; do not call `task-activity`.
148
+ - **One-shot path (no task)**: record the actual publication status in the `pr-review-rN.md` "Publication Result" section. Record the Review ID/URL on success, or the error and lack of automatic recovery on failure. Do not call `task-activity`.
149
149
 
150
150
  ### 7. Re-sync after write-back (task-anchored path)
151
151
 
152
- Step 6 rewrote the local `pr-review-rN.md` "Publication Result" section and task.md (Activity Log), while step 4 synced the older snapshot. `verify_comment_content` / `verify_task_comment_content` compare full content, so you must re-sync first to align local and remote. Run in order:
152
+ Step 6 rewrote the local `pr-review-rN.md` "Publication Result" section and task.md (Activity Log), while step 4 synced the older snapshot. Attempt the syncs again in order; record failures as warnings for `complete-task` to restore before archiving:
153
153
 
154
154
  ```bash
155
155
  agent-infra-internal platform-comment sync {task-id} --kind task --agent {agent}
@@ -178,13 +178,13 @@ Exit code 0 passes; 1 means fix per the output and re-run; 2 means stop and ask
178
178
 
179
179
  ### 9. Inform the user
180
180
 
181
- Pick the single exit branch per `reference/output-guidance.md` (published / blocked-requires-link / one-shot), and read `.agents/rules/next-step-output.md` before rendering the next step.
181
+ Pick the single exit branch per `reference/output-guidance.md` (local review complete / blocked-requires-link / one-shot), and read `.agents/rules/next-step-output.md` before rendering the next step.
182
182
 
183
183
  ## Completion Checklist
184
184
 
185
185
  - [ ] Completed the evidence-graded PR review and produced `pr-review-rN.md`
186
- - [ ] Published the formal Review on the target PR, bound to the reviewed head SHA
187
- - [ ] Synced and re-synced the Issue artifact/task comments on the task-anchored path
186
+ - [ ] Published the formal Review, durably recorded its pending publication, or accurately recorded a one-shot publication failure
187
+ - [ ] Synced the Issue artifact/task comments or recorded their pending recovery on the task-anchored path
188
188
  - [ ] Ran the completion verification (`task-verify` or `verify-artifact`)
189
189
  - [ ] Updated task.md and appended the Activity Log entry (task-anchored path)
190
190
 
@@ -81,7 +81,7 @@ agent-infra-internal task-activity {task-id} pr-review-start --agent {agent} \
81
81
  --artifact {pr-review-artifact} --head {head-sha}
82
82
  ```
83
83
 
84
- 一次性路径不调用 `task-activity`。任意 started 后、正式 Review 明确尚未发布的受控失败,都先把 artifact 状态写为 `aborted`,再以同一 artifact/head 调用 `pr-review-terminate --outcome aborted --reason <single-line>`;发布结果不确定时保持 open,不臆断 aborted。
84
+ 一次性路径不调用 `task-activity`。读取 PR、确定 head 或本地审查失败时,先把 artifact 状态写为 `aborted`,再以同一 artifact/head 调用 `pr-review-terminate --outcome aborted --reason <single-line>`。本地审查结论完成后的发布失败记录恢复事实,不将审查轮次误判为 aborted。
85
85
 
86
86
  ### 2. 单次 decide:证据枚举 + 场景分类 + 风险分级 + 模式选择
87
87
 
@@ -99,7 +99,7 @@ agent-infra-internal pr-review-grade decide --input-file {decide-input.json} [--
99
99
 
100
100
  ### 4. 同步 Issue artifact 评论(任务锚定路径)
101
101
 
102
- 依次同步 task 评论与 artifact 评论,取得稳定 comment URL:
102
+ 依次尝试同步 task 评论与 artifact 评论;失败时记录 warning 和恢复事实,继续本地审查:
103
103
 
104
104
  ```bash
105
105
  agent-infra-internal platform-comment sync {task-id} --kind task --agent {agent}
@@ -116,11 +116,11 @@ agent-infra-internal platform-comment sync {task-id} --kind artifact --artifact
116
116
  agent-infra-internal platform-pr-review inspect --pr {pr-number} [--cwd <path>]
117
117
  ```
118
118
 
119
- 若 head 与步骤 1 记录一致,组装正文(head SHA / 结论 / finding / receipt / Issue artifact 链接,**不含 marker**),发布正式 Review:
119
+ 若 head 与步骤 1 记录一致,组装正文(head SHA / 结论 / finding / receipt / 已取得的 Issue artifact 链接;评论待恢复时写明 artifact 身份,**不含 marker**)。把完整正文写入与本轮报告同目录的 `pr-review-body.md`(Round 1)或 `pr-review-body-r{N}.md`(后续轮次),并将 `{review-body-file}` 绑定为该文件的绝对路径。本轮报告的「正式 Review 正文」段只记录该文件名。任务锚定路径必须使用任务目录中的该文件;失败恢复会按报告轮次重读该文件并核对正文摘要。然后发布正式 Review:
120
120
 
121
121
  ```bash
122
122
  agent-infra-internal platform-pr-review publish --pr {pr-number} --scope {taskId|pr{pr-number}} --round {round} \
123
- --commit {head-sha} --event {COMMENT|APPROVE|REQUEST_CHANGES} --body-file {review-body.md} [--dry-run] [--cwd <path>]
123
+ --commit {head-sha} --event {COMMENT|APPROVE|REQUEST_CHANGES} --body-file {review-body-file} --artifact {pr-review-artifact} --agent {agent} [--dry-run] [--cwd <path>]
124
124
  ```
125
125
 
126
126
  `publish` 由 core 生成并校验 marker(首行),按 marker + commit 幂等(重放 no-op;marker 命中但 commit 不一致稳定失败)。head 漂移时,先把旧 artifact 状态写为 `superseded`,再闭合旧轮:
@@ -131,11 +131,11 @@ agent-infra-internal task-activity {task-id} pr-review-terminate --agent {agent}
131
131
  --outcome superseded --reason "head changed before publish"
132
132
  ```
133
133
 
134
- 闭合成功后重新执行步骤 1,进入下一 canonical round;不得先写新轮 started。若 publish 调用的远端结果不确定,保留 open 并在重试时依赖 marker + commit 恢复。
134
+ 闭合成功后重新执行步骤 1,进入下一 canonical round;不得先写新轮 started。publish 结果不确定且已有任务账本记录时,保留待恢复操作并继续本地审查轮次;无法证明恢复事实已持久化时保持 open。
135
135
 
136
136
  ### 6. 回写发布结果与任务状态
137
137
 
138
- - **任务锚定路径**:publish 返回 `applied` / `no-op` 后,把 Review ID/URL 与同名正式 Review 状态写入 `pr-review-rN.md`「发布结果」段,再以步骤 3 冻结的同一组 verdict/counts 闭合活动日志:
138
+ - **任务锚定路径**:把 publish 的实际状态写入 `pr-review-rN.md`「发布结果」段。`applied` / `no-op` 时记录 Review ID/URL;写入失败且已有任务账本记录时写 `blocked` / `failed`、错误码和恢复动作。随后以步骤 3 冻结的同一组 verdict/counts 闭合本地活动日志:
139
139
 
140
140
  ```bash
141
141
  agent-infra-internal task-activity {task-id} pr-review-complete --agent {agent} \
@@ -145,11 +145,11 @@ agent-infra-internal task-activity {task-id} pr-review-terminate --agent {agent}
145
145
 
146
146
  `task-activity` 由 typed payload 生成 `Verdict: <结论>, blockers: N, major: N, minor: N → {pr-review-artifact}`,并经 `writeTask` 原子完成 Activity Log、`## 审查反馈` 链接与版本戳刷新;不改 `current_step`,也不把 receipt/head/Review URL 写入 NOTE。
147
147
 
148
- - **一次性路径(无任务)**:Review ID/URL 只写 `pr-review-rN.md`「发布结果」段,不调用 `task-activity`。
148
+ - **一次性路径(无任务)**:把实际发布状态写入 `pr-review-rN.md`「发布结果」段;成功时记录 Review ID/URL,失败时记录错误与不可自动恢复的限制。不调用 `task-activity`。
149
149
 
150
150
  ### 7. 发布后回写再同步(任务锚定路径)
151
151
 
152
- 步骤 6 已改写本地 `pr-review-rN.md`「发布结果」段与 task.md(活动日志),而步骤 4 同步的是旧快照。`verify_comment_content` / `verify_task_comment_content` 会全文比对,必须先再同步使本地与远端一致。依次调用:
152
+ 步骤 6 已改写本地 `pr-review-rN.md`「发布结果」段与 task.md(活动日志),而步骤 4 同步的是旧快照。依次尝试再同步;失败记录 warning,由 `complete-task` 在归档前补齐:
153
153
 
154
154
  ```bash
155
155
  agent-infra-internal platform-comment sync {task-id} --kind task --agent {agent}
@@ -178,13 +178,13 @@ agent-infra-internal platform-comment sync {task-id} --kind artifact --artifact
178
178
 
179
179
  ### 9. 告知用户
180
180
 
181
- 按 `reference/output-guidance.md` 选择唯一出口(正常发布 / 阻塞要求关联 / 一次性检视),渲染下一步前读取 `.agents/rules/next-step-output.md`。
181
+ 按 `reference/output-guidance.md` 选择唯一出口(本地审查完成 / 阻塞要求关联 / 一次性检视),渲染下一步前读取 `.agents/rules/next-step-output.md`。
182
182
 
183
183
  ## 完成检查清单
184
184
 
185
185
  - [ ] 已按证据分级完成 PR 审查并产出 `pr-review-rN.md`
186
- - [ ] 正式 Review 已发布到目标 PR,绑定被审 head SHA
187
- - [ ] 任务锚定路径的 Issue artifact/task 评论已同步并再同步
186
+ - [ ] 正式 Review 已发布、任务账本已记录待恢复操作,或一次性路径已如实记录发布失败
187
+ - [ ] 任务锚定路径的 Issue artifact/task 评论已同步,或失败已记录待恢复
188
188
  - [ ] 已完成校验(`task-verify` 或 `verify-artifact`)
189
189
  - [ ] 已更新 task.md 并追加 Activity Log(任务锚定路径)
190
190
 
@@ -6,13 +6,13 @@ Read this file and `.agents/rules/next-step-output.md` before presenting the fin
6
6
 
7
7
  | Exit | Trigger | Present |
8
8
  |------|---------|---------|
9
- | A Published | the formal Review was published (applied/no-op) and verification passed | conclusion, mode, reviewed head SHA, Review URL, receipt, next step |
9
+ | A Local review complete | the local review round closed and verification passed; formal publication succeeded or has a durable pending record | conclusion, mode, reviewed head SHA, actual publication status, Review URL or recovery action, receipt, next step |
10
10
  | B Blocked, requires linking | `resolve-host` returned none or ambiguous | linking guidance (create/link an Issue and task); do not auto-create an Issue; or explicitly choose the one-shot review |
11
- | C One-shot review | the user explicitly chose a "one-shot review" | non-recoverable notice, artifact directory `.agents/workspace/reviews/{pr-number}/`, Review URL |
11
+ | C One-shot review | the user explicitly chose a "one-shot review" | non-recoverable notice, artifact directory `.agents/workspace/reviews/{pr-number}/`, Review URL or publication failure |
12
12
 
13
13
  ## Presentation Requirements
14
14
 
15
- - On publish (exit A) report: review mode (verify/audit/reconstruct), evidence scenario (S1/S2/S3), reviewed head SHA, finding count, formal Review URL, receipt.
15
+ - On local completion (exit A), report the review mode (verify/audit/reconstruct), evidence scenario (S1/S2/S3), reviewed head SHA, finding count, formal publication status, Review URL or pending recovery operation, and receipt. Never claim a pending Review was published.
16
16
  - On block (exit B) provide concrete commands/steps to establish the link; if `resolve-host` returned `ambiguous`, list the candidate tasks and ask a human to pin the host.
17
17
  - On one-shot (exit C) state clearly `recoverable: false` and make no recovery promise.
18
18
  - Read `.agents/rules/next-step-output.md` before rendering the next step, and generate the "next step" command per its convention.
@@ -6,13 +6,13 @@
6
6
 
7
7
  | 出口 | 触发条件 | 呈现内容 |
8
8
  |------|----------|----------|
9
- | A 正常发布 | 正式 Review 已发布(applied/no-op)且校验通过 | 结论、模式、被审 head SHA、Review URL、receipt、下一步 |
9
+ | A 本地审查完成 | 本地审查轮次闭合且校验通过;正式 Review 已发布或有持久化待恢复记录 | 结论、模式、被审 head SHA、实际发布状态、Review URL 或恢复动作、receipt、下一步 |
10
10
  | B 阻塞要求关联 | `resolve-host` 返回 none 或 ambiguous | 关联指引(创建/关联 Issue 与 task),不自动创建 Issue;或显式选择一次性检视 |
11
- | C 一次性检视 | 用户显式选择「仅一次性检视」 | 不可恢复提示、产物目录 `.agents/workspace/reviews/{pr-number}/`、Review URL |
11
+ | C 一次性检视 | 用户显式选择「仅一次性检视」 | 不可恢复提示、产物目录 `.agents/workspace/reviews/{pr-number}/`、Review URL 或发布失败 |
12
12
 
13
13
  ## 呈现要求
14
14
 
15
- - 正常发布(出口 A)时报告:审查模式(verify/audit/reconstruct)、证据场景(S1/S2/S3)、被审 head SHA、finding 总数、正式 Review URL、receipt。
15
+ - 本地审查完成(出口 A)时报告:审查模式(verify/audit/reconstruct)、证据场景(S1/S2/S3)、被审 head SHA、finding 总数、正式 Review 发布状态、Review URL 或待恢复操作、receipt。待恢复时不得声称 Review 已发布。
16
16
  - 阻塞(出口 B)时给出建立关联的具体命令或步骤;如果 `resolve-host` 返回 ambiguous,列出候选任务并要求人工指定。
17
17
  - 一次性检视(出口 C)明确 `recoverable: false`,不承诺可恢复。
18
18
  - 渲染下一步前读取 `.agents/rules/next-step-output.md`,并按其中的「下一步」命令约定生成。
@@ -68,6 +68,10 @@ Land the following in order before the line-level findings, without impersonatin
68
68
 
69
69
  - **{title}**: {description} · `{file}:{line}` · Evidence: {evidence} · Impact: {impact} · Suggestion: {suggestion}
70
70
 
71
+ ## Formal Review Body
72
+
73
+ **Body file**: `pr-review-body.md` (Round 1) or `pr-review-body-r{N}.md` (later rounds), beside this report. The file contains the complete formal Review body without the platform marker. Publication and recovery read the same file by round and check its digest.
74
+
71
75
  ## Publication Result
72
76
 
73
77
  - **Formal Review Status**: {pending / applied / no-op / aborted / superseded / blocked / failed}
@@ -68,6 +68,10 @@
68
68
 
69
69
  - **{标题}**:{描述} · `{file}:{line}` · 证据:{evidence} · 影响:{impact} · 建议:{suggestion}
70
70
 
71
+ ## 正式 Review 正文
72
+
73
+ **正文文件**:`pr-review-body.md`(Round 1)或 `pr-review-body-r{N}.md`(后续轮次),与本报告同目录。文件保存不含平台 marker 的完整正式 Review 正文;发布与恢复按轮次读取同一文件并核对摘要。
74
+
71
75
  ## 发布结果
72
76
 
73
77
  - **正式 Review 状态**:{pending / applied / no-op / aborted / superseded / blocked / failed}
@@ -60,9 +60,12 @@ const DEFAULTS = {
60
60
  "runtimes": [
61
61
  "node22"
62
62
  ],
63
- "tools": [
64
- "agent-infra"
65
- ],
63
+ "tools": {
64
+ "ids": [
65
+ "agent-infra"
66
+ ],
67
+ "definitions": {}
68
+ },
66
69
  "refreshIntervalDays": 7,
67
70
  "dockerfile": null,
68
71
  "vm": {
@@ -334,10 +337,20 @@ function normalizeAgentClientConfig(cfg) {
334
337
  const sandbox = cfg.sandbox && typeof cfg.sandbox === 'object' && !Array.isArray(cfg.sandbox)
335
338
  ? cfg.sandbox
336
339
  : undefined;
337
- if (Array.isArray(sandbox?.tools)) {
338
- for (const [index, tool] of sandbox.tools.entries()) {
340
+ if (sandbox && own(sandbox, 'customTools')) {
341
+ return failure('INVALID_AGENT_CLIENTS', 'sandbox.customTools');
342
+ }
343
+ if (sandbox && own(sandbox, 'tools')) {
344
+ const tools = sandbox.tools;
345
+ if (!tools || typeof tools !== 'object' || Array.isArray(tools)) {
346
+ return failure('INVALID_AGENT_CLIENTS', 'sandbox.tools');
347
+ }
348
+ if (!Array.isArray(tools.ids)) {
349
+ return failure('INVALID_AGENT_CLIENTS', 'sandbox.tools.ids');
350
+ }
351
+ for (const [index, tool] of tools.ids.entries()) {
339
352
  if (AGENT_CLIENT_IDS.includes(tool)) {
340
- return failure('INVALID_AGENT_CLIENTS', `sandbox.tools[${index}]`);
353
+ return failure('INVALID_AGENT_CLIENTS', `sandbox.tools.ids[${index}]`);
341
354
  }
342
355
  }
343
356
  }