@thincoder/core 0.9.4 → 0.10.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 (221) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +1 -1
  3. package/abort-provenance.mjs +10 -10
  4. package/advisor/citations.mjs +5 -5
  5. package/advisor/compaction.mjs +16 -15
  6. package/advisor/loop.mjs +14 -14
  7. package/advisor/messages.mjs +6 -6
  8. package/advisor/project-context.mjs +5 -5
  9. package/advisor/repos.mjs +3 -3
  10. package/advisor/run.mjs +23 -13
  11. package/advisor.mjs +4 -4
  12. package/agent/assemble.mjs +111 -0
  13. package/agent/chat-call.mjs +68 -0
  14. package/agent/child-marks.mjs +2 -2
  15. package/agent/completion.mjs +9 -2
  16. package/agent/continue-decision.mjs +25 -0
  17. package/agent/dispatch-gates.mjs +140 -0
  18. package/agent/dispatch-run.mjs +167 -0
  19. package/agent/dispatch.mjs +55 -294
  20. package/agent/family-tools.mjs +11 -11
  21. package/agent/helpers.mjs +63 -3
  22. package/agent/live-beat.mjs +49 -0
  23. package/agent/post-turn.mjs +4 -8
  24. package/agent/record-results.mjs +23 -20
  25. package/agent/relay-prefix.mjs +2 -2
  26. package/agent/run-stages.mjs +19 -15
  27. package/agent/run-start.mjs +111 -0
  28. package/agent/setup-reminders.mjs +9 -9
  29. package/agent/setup.mjs +32 -4
  30. package/agent/spawn-child.mjs +9 -9
  31. package/agent/suspension.mjs +90 -30
  32. package/agent/timers.mjs +113 -0
  33. package/agent/turn-loop.mjs +244 -0
  34. package/agent/write-gate.mjs +103 -6
  35. package/agent-tools/advisor-async.mjs +11 -11
  36. package/agent-tools/advisor-settle.mjs +17 -17
  37. package/agent-tools/advisor.mjs +38 -43
  38. package/agent-tools/async-discard.mjs +44 -1
  39. package/agent-tools/async-settle.mjs +23 -20
  40. package/agent-tools/audit-block.mjs +7 -7
  41. package/agent-tools/bash-async.mjs +281 -0
  42. package/agent-tools/batch-lifecycle.mjs +65 -34
  43. package/agent-tools/batch-paths.mjs +186 -0
  44. package/agent-tools/batch-skeleton.mjs +19 -1
  45. package/agent-tools/batch.mjs +22 -119
  46. package/agent-tools/checkpoint.mjs +121 -0
  47. package/agent-tools/child-permission.mjs +5 -3
  48. package/agent-tools/consult.mjs +58 -58
  49. package/agent-tools/context.mjs +4 -20
  50. package/agent-tools/design-token.mjs +3 -3
  51. package/agent-tools/digest-budget.mjs +1 -1
  52. package/agent-tools/eng.mjs +5 -5
  53. package/agent-tools/escalate-async.mjs +18 -13
  54. package/agent-tools/goal.mjs +3 -10
  55. package/agent-tools/panel-blocks.mjs +3 -3
  56. package/agent-tools/parent-channel.mjs +3 -13
  57. package/agent-tools/plan.mjs +3 -4
  58. package/agent-tools/read-history.mjs +12 -28
  59. package/agent-tools/recent-changes.mjs +4 -5
  60. package/agent-tools/review-facts.mjs +1 -1
  61. package/agent-tools/settings.mjs +47 -20
  62. package/agent-tools/skill.mjs +3 -5
  63. package/agent-tools/spawn-gates.mjs +3 -3
  64. package/agent-tools/subagent-actions-query.mjs +270 -0
  65. package/agent-tools/subagent-actions.mjs +29 -273
  66. package/agent-tools/subagent-async.mjs +36 -31
  67. package/agent-tools/subagent-panel.mjs +38 -9
  68. package/agent-tools/subagent-run.mjs +44 -29
  69. package/agent-tools/subagent-scheduler.mjs +29 -28
  70. package/agent-tools/subagent-spawn.mjs +57 -25
  71. package/agent-tools/subagent.mjs +46 -66
  72. package/agent-tools/task.mjs +3 -9
  73. package/agent-tools/timer.mjs +12 -12
  74. package/agent-tools/verify.mjs +14 -13
  75. package/agent-tools.mjs +0 -1
  76. package/agent.mjs +20 -351
  77. package/attachments.mjs +125 -0
  78. package/auto-think.mjs +1 -1
  79. package/config-presets.mjs +12 -7
  80. package/config-watch.mjs +83 -0
  81. package/config.mjs +17 -4
  82. package/context-degrade.mjs +81 -0
  83. package/context-echo.mjs +88 -0
  84. package/context-push.mjs +51 -0
  85. package/context.mjs +8 -187
  86. package/conventions.mjs +110 -161
  87. package/declaration.mjs +194 -0
  88. package/embedding.mjs +3 -1
  89. package/env-ref.mjs +81 -0
  90. package/explore-distill.mjs +2 -3
  91. package/file-links.mjs +53 -0
  92. package/file-refs.mjs +103 -0
  93. package/generate-title.mjs +28 -4
  94. package/git/checkpoint.mjs +4 -8
  95. package/history-window.mjs +17 -2
  96. package/i18n.mjs +2 -0
  97. package/index-discover.mjs +7 -7
  98. package/ledger-cmd.mjs +34 -126
  99. package/ledger-db.mjs +35 -7
  100. package/ledger-migrate.mjs +299 -0
  101. package/ledger-tools.mjs +188 -0
  102. package/ledger.mjs +11 -5
  103. package/log.mjs +12 -7
  104. package/manifest-discovery.mjs +131 -0
  105. package/manifest-schema.mjs +166 -0
  106. package/manifest.mjs +18 -217
  107. package/mcp.mjs +4 -1
  108. package/memory/code-search.mjs +149 -0
  109. package/memory/code-sync.mjs +89 -230
  110. package/memory/core.mjs +47 -32
  111. package/memory/docs.mjs +63 -262
  112. package/memory/file-list.mjs +89 -0
  113. package/memory/file-walk.mjs +7 -4
  114. package/memory/memory-tool.mjs +229 -0
  115. package/memory/schema.mjs +18 -3
  116. package/memory/sweep.mjs +289 -0
  117. package/memory/sync-tail.mjs +81 -0
  118. package/memory-status.mjs +69 -0
  119. package/memory.mjs +3 -0
  120. package/model-specs.mjs +131 -66
  121. package/notify-policy.mjs +51 -0
  122. package/package.json +1 -1
  123. package/peer-claims.mjs +263 -0
  124. package/peer-domains.mjs +100 -71
  125. package/peer-instances.mjs +9 -10
  126. package/process-probe-exec.mjs +187 -0
  127. package/process-probe.mjs +27 -175
  128. package/prompt-overlays.mjs +11 -10
  129. package/prompts/advisor-design.md +2 -2
  130. package/prompts/advisor-round2.md +1 -1
  131. package/prompts/advisor-round3.md +1 -1
  132. package/prompts/common.md +19 -7
  133. package/prompts/discipline-engineering.md +57 -16
  134. package/prompts/discipline-normal.md +6 -3
  135. package/prompts/persona-coder.md +0 -1
  136. package/prompts/persona-eng-coder.md +1 -5
  137. package/prompts/persona-eng-designer.md +1 -2
  138. package/prompts/persona-engineering.md +41 -11
  139. package/prompts/persona-explore.md +0 -1
  140. package/prompts/persona-normal.md +10 -1
  141. package/prompts/persona-plan.md +3 -4
  142. package/prompts/subagent-base.md +14 -0
  143. package/provider/core.mjs +11 -48
  144. package/provider/list-models.mjs +3 -0
  145. package/provider/responses-request.mjs +237 -0
  146. package/provider/responses.mjs +6 -228
  147. package/provider-flows.mjs +248 -0
  148. package/queued.mjs +90 -0
  149. package/rules.mjs +209 -2
  150. package/session-gc.mjs +67 -6
  151. package/session-guard.mjs +27 -7
  152. package/session-lifecycle.mjs +90 -18
  153. package/session-rename.mjs +5 -1
  154. package/session-slot-claims.mjs +230 -0
  155. package/session-slot-scan.mjs +299 -0
  156. package/session-slot-verify.mjs +304 -0
  157. package/session-slot-write.mjs +74 -8
  158. package/session-slots-manifest.mjs +163 -236
  159. package/session-slots.mjs +99 -71
  160. package/session.mjs +30 -10
  161. package/shell-candidates.mjs +78 -0
  162. package/text-budget.mjs +2 -2
  163. package/think-off.mjs +49 -0
  164. package/token-ttl.mjs +15 -4
  165. package/tool-args.mjs +73 -0
  166. package/tool-docs/advisor.md +9 -0
  167. package/tool-docs/batch.md +1 -0
  168. package/tool-docs/code_search.md +1 -0
  169. package/tool-docs/consult_start.md +5 -0
  170. package/tool-docs/consult_stop.md +3 -0
  171. package/tool-docs/context.md +7 -0
  172. package/tool-docs/doc_search.md +1 -0
  173. package/tool-docs/edit.md +2 -13
  174. package/tool-docs/eng.md +1 -0
  175. package/tool-docs/execute.md +1 -9
  176. package/tool-docs/git.md +25 -51
  177. package/tool-docs/goal.md +6 -0
  178. package/tool-docs/ledger_add.md +1 -0
  179. package/tool-docs/ledger_close.md +1 -0
  180. package/tool-docs/ledger_count.md +1 -0
  181. package/tool-docs/ledger_query.md +1 -0
  182. package/tool-docs/ledger_update.md +1 -0
  183. package/tool-docs/main_history.md +1 -0
  184. package/tool-docs/memory.md +10 -0
  185. package/tool-docs/notify_parent.md +9 -0
  186. package/tool-docs/peer_instances.md +1 -0
  187. package/tool-docs/plan.md +5 -0
  188. package/tool-docs/process.md +7 -3
  189. package/tool-docs/question.md +1 -0
  190. package/tool-docs/read_history.md +7 -0
  191. package/tool-docs/recent_changes.md +1 -0
  192. package/tool-docs/repo_outline.md +1 -0
  193. package/tool-docs/settings.md +6 -0
  194. package/tool-docs/skill.md +5 -0
  195. package/tool-docs/subagent.md +31 -0
  196. package/tool-docs/task.md +7 -0
  197. package/tool-docs/timer.md +6 -0
  198. package/tool-docs/verify.md +1 -0
  199. package/tool-docs/wait_for.md +2 -1
  200. package/tools/bash.mjs +28 -4
  201. package/tools/edit-batch.mjs +10 -11
  202. package/tools/edit-diff.mjs +33 -25
  203. package/tools/exec-run.mjs +102 -4
  204. package/tools/execute.mjs +5 -2
  205. package/tools/file.mjs +11 -12
  206. package/tools/git-run.mjs +1 -1
  207. package/tools/git.mjs +0 -24
  208. package/tools/glob-dialect.mjs +3 -3
  209. package/tools/index.mjs +2 -1
  210. package/tools/linter.mjs +2 -1
  211. package/tools/node-child.mjs +21 -0
  212. package/tools/ops.mjs +50 -13
  213. package/tools/patch.mjs +4 -2
  214. package/tools/repomap.mjs +20 -9
  215. package/tools/search.mjs +2 -2
  216. package/tools/shared.mjs +9 -7
  217. package/tools/web.mjs +5 -2
  218. package/tools/write-path.mjs +1 -1
  219. package/traces/trace-store.mjs +17 -14
  220. package/vision-reader.mjs +76 -0
  221. package/agent-tools/batch-segment.mjs +0 -18
@@ -3,16 +3,17 @@
3
3
  * The agent calls this explicitly to get an independent review.
4
4
  * The top-level `type` is REQUIRED and must be exactly "code" or "design"
5
5
  * (F30 fail-closed — no silent default; ADVISOR-GUARDS.md §2.4).
6
- * §11.2 (R13 — async advisor): at depth 0 the review launches into the
6
+ * AGENT-LOOP-ASYNC-POOL.md §6.10 (R13 — async advisor): at depth 0 the review launches into the
7
7
  * background pool by DEFAULT (async:true / omitted; async:false forces the
8
8
  * blocking review); depth>0 (eng-coder self-review) stays synchronous always.
9
9
  */
10
10
  import { runAdvisorReview, advisorIncompleteMarker, ADVISOR_LAUNCH_REFUSAL_PREFIX } from "../advisor/run.mjs"
11
11
  import { resolveBatchDocPath } from "./batch.mjs"
12
12
  // M6(模块设计 §2.1 F3):评审对象来源读 manifest docRoot(声明面)——复用 M4 的
13
- // write-gate.mjs 单一权威源(KD-M6-1),替代 v1 的 loadConventions/isDocPath 分类;
13
+ // write-gate.mjs 单一权威源(KD-M6-1),替代 v1 的逐档分类面(isDocPath);
14
14
  // normAbs 同源 re-export(指针非副本)。不 import dispatch.mjs(簇间回边,环风险)。
15
- import { resolveReviewTargetPaths, normAbs } from "../agent/write-gate.mjs"
15
+ import { resolveReviewTargetPaths, resolveReviewRootsFor, normAbs } from "../agent/write-gate.mjs"
16
+ import { owningProject } from "../manifest-discovery.mjs"
16
17
  import { sep } from "node:path"
17
18
  import {
18
19
  generateDesignToken,
@@ -24,6 +25,8 @@ import {
24
25
  // F30/F31(2026-09-18 顾问面治理批):类型门判定 / 拒发串 / 对象标识行——单源 `advisor/notice.mjs`
25
26
  // (文案逐字 = ADVISOR-GUARDS.md §2.4 / §2.5);零计数载体(计数护栏随撤 cap 整体退场)。
26
27
  import { typeGateCriterion, buildTypeGateRefusal, scopeSummary, withIdentityLine } from "../advisor/notice.mjs"
28
+ // #15 描述外置:描述文本单点 = tool-docs/advisor.md(DESC 单解析面,缺档抛错语义不变)
29
+ import { DESC } from "../tools/shared.mjs"
27
30
 
28
31
  // Design-token utilities moved to advisor-async.mjs (the async settle shares
29
32
  // them — no wrapper↔runner module cycle); validateDesignToken stays exported
@@ -32,36 +35,14 @@ export { validateDesignToken } from "./advisor-async.mjs"
32
35
 
33
36
  export const advisorTool = {
34
37
  name: "advisor",
35
- description:
36
- "Run an independent review on your work. " +
37
- "type is REQUIRED — exactly one of the two legal values: type='design' reviews design / requirement documents before implementation (pass documents=[...] with the explicit list of doc paths; plus batchDoc when a batch record is in flight); type='code' reviews the code you changed after implementation (pass paths=[...] to scope files/directories — documents=[...] adds acceptance-criteria context). " +
38
- "A call without a type (or with a conflicting object.type) is refused — there is no default and no silent fallback. " +
39
- "The advisor is an independent read-only sub-agent that explores the codebase, " +
40
- "reads files, and traces callers via grep/lsp. " +
41
- "For code review: round 1 does a full review, round 2 verifies the agent's fix claims, " +
42
- "round 3+ strictly checks only the fix claims — convergence, not divergence. " +
43
- "For design review: single-pass review against methodology and requirements. " +
44
- "Review criteria come from .thincoder/advisor.md (if present) or sensible defaults. " +
45
- "After the review, you MUST produce a response table (see discipline rules for format). " +
46
- "If advisor says all clear, call verify. " +
47
- "Optionally pass object={type,target,status,reason,exclude} to anchor the review target " +
48
- " (the review-object declaration is mechanically injected into the review message); " +
49
- "absent → legacy behavior (no injection). " +
50
- "ASYNC: at depth 0 the review runs in the BACKGROUND by default " +
51
- "(async:true or omitted) — the call returns an ack immediately, the turn ends, and the report " +
52
- "arrives automatically in a digest turn when the review finishes; background reviews share one pool — " +
53
- "at most agent.poolLimits.advisor concurrent reviews (default 4 — configurable via /config 并发池 or " +
54
- "config.json; pool-full and same-scope refusals state the current limit) — launch reviews one at a time. " +
55
- "Inside a child (depth>0 — eng-coder self-review) " +
56
- "reviews are always synchronous; async:true is rejected there. " +
57
- "Returns the review report — the advisor's findings verdict: all-clear (call verify) or a findings list to fix.",
38
+ description: DESC("advisor"),
58
39
  parameters: {
59
40
  type: "object",
60
41
  properties: {
61
42
  type: { type: "string", enum: ["code", "design"], description: "Review type (required): 'design' for design doc review, 'code' for code review. Omitting it is refused — there is no default." },
62
43
  async: {
63
44
  type: "boolean",
64
- description: "Background review: default at depth 0 = true (async — ack now, report via digest); async:false forces the blocking review (mechanism parameter — top-level launches are async by default). depth>0 → always sync (async:true rejected).",
45
+ description: "Background review: default at depth 0 = true (ack now, report via digest); async:false forces the blocking review. depth>0 → always sync.",
65
46
  },
66
47
  object: {
67
48
  type: "object",
@@ -72,21 +53,21 @@ export const advisorTool = {
72
53
  reason: { type: "string", description: "Why this review runs: user-initiated / delivery verification" },
73
54
  exclude: { type: "string", description: "Explicit exclusion list — approved/implemented items NOT in this review" },
74
55
  },
75
- description: "Review-object declaration: mechanically injected at the start of the review user message so the advisor does not re-derive the review target. Absent → no injection (legacy behavior).",
56
+ description: "Review-object declaration — mechanically injected at the start of the review message. Absent → no injection (legacy behavior).",
76
57
  },
77
58
  paths: {
78
59
  type: "array",
79
60
  items: { type: "string" },
80
- description: "Code files or directories to review (for code review). Required unless documents is provided. The advisor reads the files/directories listed here — it has no git tool and never inspects diffs.",
61
+ description: "Code files or directories to review (for code review). Required unless documents is provided. The advisor reads exactly these — it has no git tool and never inspects diffs.",
81
62
  },
82
63
  documents: {
83
64
  type: "array",
84
65
  items: { type: "string" },
85
- description: "Explicit list of doc paths to review (design docs, requirements docs, referenced docs). The advisor reviews ONLY these — it does NOT scan git diff. Use for both design review and code review to pass the task's Docs involved list.",
66
+ description: "Doc paths to review (design / requirements / referenced docs). The advisor reviews ONLY these — no git diff scan. Use for both review types to pass the task's docs list.",
86
67
  },
87
68
  batchDoc: {
88
69
  type: "string",
89
- description: "Design review only: path to the batch record currently in flight. Validated WHENEVER passed (any review type) — a value that is not a readable file is refused with an error rather than ignored; for design reviews the reviewer then ALSO gets the `batch` write channel (transition alias `batch_segment`) to record its findings table + VERDICT + counts into §3. Omit when no batch record is in flight — the review then runs unchanged with no write channel (zero regression).",
70
+ description: "Design review only: the in-flight batch record path — validated whenever passed (unreadable ⇒ refused, not ignored); the reviewer then also gets the `batch` write channel to record its findings + verdict. Omit when no batch record is in flight (no write channel — zero regression).",
90
71
  },
91
72
  },
92
73
  required: ["type"],
@@ -96,7 +77,7 @@ export const advisorTool = {
96
77
  outputPanel: true,
97
78
  async execute(args, ctx) {
98
79
  const agent = ctx.agent
99
- // Review-object declaration (§18.8 D-OA3): the PARENT constructs it and the
80
+ // Review-object declaration (AGENT-LOOP-ASYNC-POOL.md §6.18 D-OA3): the PARENT constructs it and the
100
81
  // advisor tool passes it through — mechanical anchoring, not model inference.
101
82
  // Any non-object value (string/array/primitive, possibly from a malformed
102
83
  // tool call) degrades to null = no injection (legacy calls unchanged).
@@ -137,9 +118,23 @@ export const advisorTool = {
137
118
  // elsewhere declares them in PROJECT-MANIFEST.json docRoot).
138
119
  if (reviewType === "design" && documents) {
139
120
  const roots = resolveReviewTargetPaths(agent).map((r) => r.replace(/[\\/]/g, sep))
121
+ // 按用点解析(2026-09-21 之裁收口 · 台账 #828):逐文档按**其所属项目**(最近带档祖先)
122
+ // 的 docRoot 判定;无主档文档回退会话根集判定(原行为零变)。
123
+ const ownerRootsCache = new Map()
124
+ const ownRoots = (abs) => {
125
+ const owner = owningProject(abs)
126
+ if (!owner) return []
127
+ let r = ownerRootsCache.get(owner)
128
+ if (!r) {
129
+ r = resolveReviewRootsFor(owner).map((x) => x.replace(/[\\/]/g, sep))
130
+ ownerRootsCache.set(owner, r)
131
+ }
132
+ return r
133
+ }
140
134
  const invalidDocs = documents.filter((doc) => {
141
135
  const n = normAbs(doc, agent.cwd).replace(/[\\/]/g, sep)
142
- return !roots.some((r) => n === r || n.startsWith(r + sep))
136
+ const under = (r) => n === r || n.startsWith(r + sep)
137
+ return !roots.some(under) && !ownRoots(n).some(under)
143
138
  })
144
139
  if (invalidDocs.length > 0) {
145
140
  if (ctx._toolCallId !== undefined) (agent._advisorRefusals ??= new Set()).add(ctx._toolCallId)
@@ -150,7 +145,7 @@ export const advisorTool = {
150
145
  }
151
146
  }
152
147
 
153
- // §11.2 (R13 — ruling ②-3 A): async gate. Depth-0 defaults to the
148
+ // §6.10 (R13 — ruling ②-3 A): async gate. Depth-0 defaults to the
154
149
  // background pool; depth>0 (eng-coder internal self-review) is ALWAYS sync —
155
150
  // an explicit async:true there is rejected, the default never flips.
156
151
  // depth 显式校验(归一形态——判定单点:`depth` 取一次 + `asyncRequested` 显式布尔,
@@ -168,16 +163,16 @@ export const advisorTool = {
168
163
  }
169
164
  const isAsync = asyncRequested || (depth === 0 && args.async !== false)
170
165
 
171
- // Per-review instance resolution (§11.2 ③ — ruling ②-5 A): fix rounds
166
+ // Per-review instance resolution (§6.10 ③ — ruling ②-5 A): fix rounds
172
167
  // continue the same reviewId (design = the doc-set instance's designId —
173
168
  // slot/spawn continuity; code = the newest OPEN instance). The resolution
174
169
  // scopes agent._advisorRound/_lastAdvisorOutput so the message builder and
175
170
  // the run.mjs cap read THIS instance's round/prior (multi-review isolation).
176
171
  const resolved = resolveAdvisorLaunch(agent, reviewType, { documents })
177
- // §2.20.2 评审侧批次档门禁 + 实例键绑定(batch_segment 的唯一路径来源):
172
+ // BATCH-RECORD.md §4.2 评审侧批次档门禁 + 实例键绑定(评审实例的唯一路径来源):
178
173
  // 口径 = **「若传则须可读」**(空/不可读 → throw;不强制必传——无批次档的在途设计评审
179
174
  // 零回归,N5);绑定落在 resolved.run(评审实例键,与 reviewType/round/designId 同族)——
180
- // 并发设计评审各绑各档,不用单值会话态(§2.20.8 #6)。
175
+ // 并发设计评审各绑各档,不用单值会话态(BATCH-RECORD.md §4.7 #6)。
181
176
  if (args.batchDoc !== undefined && args.batchDoc !== null) {
182
177
  resolved.run.batchDoc = resolveBatchDocPath(agent.cwd, args.batchDoc)
183
178
  }
@@ -185,7 +180,7 @@ export const advisorTool = {
185
180
  // a clean pass; on pass it is slotted under the instance's designId at settle
186
181
  // (sync: right here; async: the settle callback — fix #2). A NEW instance
187
182
  // gets a fresh designId; a continued fix round keeps the original one — and a
188
- // same-scope re-review after a pass REUSES the session's id (F2h §29.1).
183
+ // same-scope re-review after a pass REUSES the session's id (F2h).
189
184
  const designToken = reviewType === "design" ? generateDesignToken(agent) : null
190
185
  const designId = reviewType === "design" ? resolved.designId : null
191
186
 
@@ -209,7 +204,7 @@ export const advisorTool = {
209
204
  if (ctx._toolCallId !== undefined) {
210
205
  (agent._advisorAsyncAcks ??= new Set()).add(ctx._toolCallId)
211
206
  }
212
- // E(F17/§14.14 E-3c):设计评审点火回执追加冻结句(代码评审 ack 零改)——窗口下界以
207
+ // E(F17/ADVISOR-GUARDS.md §5 E-3c):设计评审点火回执追加冻结句(代码评审 ack 零改)——窗口下界以
213
208
  // 可观察信号表达:报告送达 / 取消前,被审文档(含批次档)零写入。
214
209
  const freezeNote = reviewType === "design"
215
210
  ? ";D5 冻结窗口:被审文档(含批次档)在报告送达前零写入——在途写入会被拒绝,写入将使本轮结算为陈旧 (pass 不发 token)"
@@ -244,9 +239,9 @@ export const advisorTool = {
244
239
  batchDoc: resolved.run.batchDoc ?? null,
245
240
  }, designToken, documents, paths, reviewObject, designId)
246
241
 
247
- // B 启动拒绝(§14.4 #2——稳定前缀):拒发登记(同池满 / cap 款——不置 called、不耗轮次),
242
+ // B 启动拒绝(稳定前缀):拒发登记(同池满 / cap 款——不置 called、不耗轮次),
248
243
  // 可见报错照常返回(record-results 的 REFUSED 契约)。第 33 批:判定单点——同时供设计
249
- // 失败分类复用(launchRefused ⇒ neutral——无尝试发生,§17.3 #1)。
244
+ // 失败分类复用(launchRefused ⇒ neutral——无尝试发生;`ADVISOR-GUARDS.md` §7 失败结算表行 1)。
250
245
  const launchRefused = String(result).startsWith(ADVISOR_LAUNCH_REFUSAL_PREFIX)
251
246
  if (launchRefused && ctx._toolCallId !== undefined) {
252
247
  (agent._advisorRefusals ??= new Set()).add(ctx._toolCallId)
@@ -265,12 +260,12 @@ export const advisorTool = {
265
260
  const settled = settleDesignReview(agent, resolved.run, designToken, result, { incomplete })
266
261
  // 撤计数(2026-09-18 用户裁定):原同步面“分类落账”随会话级计数器整体退场(零载体——F28③);
267
262
  // 失败结论块由**结算出口**产出(异步结算 `settleAdvisorRun`——两轨共用,ADVISOR-GUARDS.md §7)。
268
- // F2e (§29.1): the sync prior mirror must not carry the raw echo the runner
263
+ // F2e: the sync prior mirror must not carry the raw echo the runner
269
264
  // stored — overwrite with the clean settled form (exact-suffix truncation).
270
265
  if (settled.passed) {
271
266
  agent._lastAdvisorOutput = stripApprovedSuffix(settled.output, resolved.run.approvedSuffix)
272
267
  } else if (incomplete) {
273
- // 未完成 ⇒ 同步 prior 镜像覆写为清洗后输出(防未注册 token 进 prior——§14.3)。
268
+ // 未完成 ⇒ 同步 prior 镜像覆写为清洗后输出(防未注册 token 进 prior——ADVISOR-GUARDS.md §1)。
274
269
  agent._lastAdvisorOutput = settled.output
275
270
  }
276
271
  return settled.output
@@ -13,6 +13,11 @@
13
13
  * - 保留 ⟺ 其余——存活条目(controller 未中止——报告沿自动通道到达)/ done-in-pool(回合尾
14
14
  * 收集 / 挂起 sweep 消化)/ cancelled(settle cancelled 分支收尾)。
15
15
  *
16
+ * #9 后台 bash 任务族(三族同面并入——D9-7 收尾档②):bg 条目的「已死」不由 controller 杀达
17
+ * ——其控制器链只作**判据**(杀 ⟺ 控制器已中止),杀树动作经本收尾面 `spec.dispose` 钩子落
18
+ * `bash-async.mjs` 杀单点(`killBgTree`);回合中断(Ctrl+I)经 `bindChildController`
19
+ * interrupt 豁免不中止控制器 ⇒ 本面零动作(F2 同款豁免——池保留)。
20
+ *
16
21
  * 判据口径(D-AD6):两接线点**均不传 `ctx`** ⇒ 实走 controller 支(`parentAborted(null, entry)`)
17
22
  * ——与对侧有效判据同判(对侧传入的 `ctx` 为死参);`ctx` 保留为签名备用面(直调用例 / 对侧收敛)。
18
23
  * 「controller 已中止 = 条目真死」由 `bindChildController` 单点保证(`async-settle.mjs:88-98`
@@ -36,6 +41,8 @@ import { carrierField, getAsyncPool, parentAborted, writeTombstone } from "./asy
36
41
  import { pushReal } from "../context.mjs"
37
42
  import { escapeXml } from "../agent/helpers.mjs"
38
43
  import { logEvent } from "../log.mjs"
44
+ // #9(后台 bash 任务族——收尾档②):杀单点(树杀)经 `bash-async.mjs` 落面。
45
+ import { killBgTree } from "./bash-async.mjs"
39
46
 
40
47
  /** 提醒模板(verbatim 同源 = 对侧 `async-discard.mjs:37-44`;测试断关键子串,不逐行断)。 */
41
48
  const subagentReminderText = (n, list) =>
@@ -47,6 +54,11 @@ const advisorReminderText = (n, list) =>
47
54
  `[System reminder: ${n} background advisor review(s) were discarded by the user's Stop — their reports will NOT arrive: ${list}.\n` +
48
55
  "No design token was issued for a discarded design review; launch the review again if it is still needed.]"
49
56
 
57
+ /** #9 后台 bash 任务族提醒模板(同族形态——报告不可达的可视化:进程已杀,全量 log 仍在盘上)。 */
58
+ const bgReminderText = (n, list) =>
59
+ `[System reminder: ${n} background bash task(s) were killed by the user's Stop — their processes are gone and no digest will arrive: ${list}. ` +
60
+ "Full output logs remain on disk (paths were given in the start ack).]"
61
+
50
62
  /** 列表词(wasStatus 数据源):queued → "(was queued — never started)";其余 "(was running)"。 */
51
63
  const wasPhrase = (wasStatus) => (wasStatus === "queued" ? " (was queued — never started)" : " (was running)")
52
64
 
@@ -87,6 +99,7 @@ function discardRole(parent, spec, ctx) {
87
99
  if (!discardable(entry, ctx)) continue
88
100
  out.discarded.push(spec.describe(entry))
89
101
  ids.add(String(entry.id))
102
+ spec.dispose?.(entry) // 族特有处置(#9 bg:杀树——判据成立即条目真死;其余族无此钩子)
90
103
  writeTombstone(parent, entry.id, "discarded", spec.roleOf(entry))
91
104
  removeFromPool(map, entry.id)
92
105
  }
@@ -94,7 +107,11 @@ function discardRole(parent, spec, ctx) {
94
107
  if (out.discarded.length === 0) return out // 零丢弃 = 零噪音(零注入 / 零事件)
95
108
  spec.pruneQueue?.(parent, ids)
96
109
  const list = out.discarded.map(spec.listPhrase).join(", ")
97
- pushReal(parent, { role: "user", content: spec.reminder(out.discarded.length, escapeXml(list)) })
110
+ // 注入面(#94 载体两形吸收):agent 形(run-stages ∕ 挂起中止接线点——`parent.history` 在)走
111
+ // `pushReal`(机器 + 人读双线);**history 数组本体形**(VSC 挂起载体——池挂数组)无注入目标 ⇒
112
+ // 跳过(与对侧 VSC copy 的 `parent?.history` 守卫同判;§6.20.1「carrier 形无注入目标」先例)
113
+ // ——墓碑与 `ev:discarded` 照发,仅模型可见提醒缺席(数组形无人读线可达面)。
114
+ if (parent?.history) pushReal(parent, { role: "user", content: spec.reminder(out.discarded.length, escapeXml(list)) })
98
115
  logEvent("ev:discarded", { n: out.discarded.length, ids: out.discarded.map((d) => `${d.role}#${d.id}`).join(", ") })
99
116
  return out
100
117
  }
@@ -120,6 +137,20 @@ const ADVISOR_SPEC = {
120
137
  pruneQueue: (parent, ids) => pruneQueue(parent, ids, "_asyncAdvisorQueue"),
121
138
  }
122
139
 
140
+ /** #9 后台 bash 任务族 spec(收尾档②):dispose = 杀树(杀单点 `killBgTree`)+ 标记 discarded
141
+ * (settle 面据此不注入——报告不可达);无队列面(超限 = 起跑显式拒,无排队语义)。 */
142
+ const BG_SPEC = {
143
+ pool: "bg",
144
+ describe: (entry) => ({ id: entry.id, role: "bg", command: entry.command }),
145
+ roleOf: () => "bg",
146
+ listPhrase: (d) => `bash#${d.id} (\`${d.command}\`)`,
147
+ reminder: bgReminderText,
148
+ dispose: (entry) => {
149
+ entry.discarded = true
150
+ killBgTree(entry)
151
+ },
152
+ }
153
+
123
154
  /**
124
155
  * 中止收尾(F1–F3):只清已死子代理条目——写 `discarded` 墓碑 + 出池 + 队列剔除 + 整批一次提醒。
125
156
  * @param parent agent 形态(载体双形经 `getAsyncPool` / `writeTombstone` 吸收)
@@ -141,3 +172,15 @@ export function discardAbortedPool(parent, ctx = null) {
141
172
  export function discardAbortedAdvisors(parent, ctx = null) {
142
173
  return discardRole(parent, ADVISOR_SPEC, ctx)
143
174
  }
175
+
176
+ /**
177
+ * 中止收尾(#9 后台 bash 任务族——收尾档②):只清已死条目——逐条**杀树**(判据成立 ⟺ 条目
178
+ * 控制器已中止;杀单点经 `killBgTree`)+ `discarded` 墓碑 + 出池 + 整批一次提醒;回合中断
179
+ * (Ctrl+I)不中止控制器 ⇒ 本面零动作(池保留——F2 同款豁免)。
180
+ * @param parent agent 形态
181
+ * @param ctx 判据 ctx(接线点不传——controller 支,同上)
182
+ * @returns {{discarded: Array<{id, role: "bg", command}>, kept: number}}
183
+ */
184
+ export function discardAbortedBgTasks(parent, ctx = null) {
185
+ return discardRole(parent, BG_SPEC, ctx)
186
+ }
@@ -43,7 +43,8 @@ import { refillAdvisorQueue } from "./advisor-async.mjs"
43
43
  /**
44
44
  * 载体字段读取吸收(#94——「VSC 的跨 runAgent 存活载体面按核内结构归一」):
45
45
  * §2.3 载体口径 = `_asyncSubagents` · `_asyncAdvisors` · `_consultSessions` ·
46
- * `_pendingAsyncResults` · `_suspended`(AGENT-LOOP.md §2.3 seam 表)。
46
+ * `_pendingAsyncResults` · `_suspended`(AGENT-LOOP.md §2.3 seam 表);#9 后台任务池
47
+ * `_bgTasks` 同列(写侧父字段 + 借用/别名 history——见 `bash-async.mjs` `ensureBgPool`)。
47
48
  * CLI 形:字段直接挂 agent(跨 run 存活);VSC 形:字段挂 depth-0 `history`
48
49
  * (agent per-run 重建——run 起始把 history 容器绑到 agent 字段,绑定不变式)。
49
50
  * 本函数吸收两形为同一读取:父对象字段优先,缺字段回退 `parent.history`。
@@ -91,7 +92,7 @@ export function tombstoneOf(parent, id) {
91
92
  /**
92
93
  * 条目 controller 链到基信号单点(#98 VSC 侧并入——interrupt 豁免面;原 subagent-run /
93
94
  * advisor-async / escalate-async / consult 四处逐字同构):
94
- * - 基信号**已 aborted** 且非 interrupt ⇒ 立即 abort(reason 逐跳保留——§20.3 站点 #10);
95
+ * - 基信号**已 aborted** 且非 interrupt ⇒ 立即 abort(reason 逐跳保留——AGENT-LOOP-SUBAGENT.md §6.12 站点 #10);
95
96
  * - interrupt aborted(Ctrl+I——中断消息注入后同回合续跑)⇒ **不逐链中止**(池保留;
96
97
  * 子代理 / 评审继续跑完,settle 照常注入——「Ctrl+I keeps the pool」意图对齐);
97
98
  * - 未来 abort ⇒ 非 interrupt 才逐链传播(Stop / 会话中止全停语义不变)。
@@ -111,11 +112,12 @@ export function bindChildController(ctrl, baseSignal) {
111
112
  // ─── D1 池 accessor(吸收双池)────────────────────────────────────────────────
112
113
 
113
114
  /** 池 accessor(D1):role "advisor" → `_asyncAdvisors`(独立评审池——无队列独立调度)·
114
- * role "consult" → `_consultSessions`(会话池)· 其余 → `_asyncSubagents`(子代理/飞刀
115
- * 共享槽位队列池)。载体经 `carrierField` 吸收(#94);未初始化返 null——调用方以
116
- * `?? new Map()` / 可选链处置。 */
115
+ * role "consult" → `_consultSessions`(会话池)· role "bg" → `_bgTasks`(#9 后台 bash
116
+ * 任务池)· 其余 → `_asyncSubagents`(子代理/飞刀共享槽位队列池)。载体经 `carrierField`
117
+ * 吸收(#94);未初始化返 null——调用方以 `?? new Map()` / 可选链处置。 */
117
118
  export function getAsyncPool(parent, role) {
118
- const field = role === "advisor" ? "_asyncAdvisors" : role === "consult" ? "_consultSessions" : "_asyncSubagents"
119
+ const field = role === "advisor" ? "_asyncAdvisors" : role === "consult" ? "_consultSessions"
120
+ : role === "bg" ? "_bgTasks" : "_asyncSubagents"
119
121
  return carrierField(parent, field) ?? null
120
122
  }
121
123
 
@@ -155,7 +157,7 @@ export function buildChildSignal(parent, ctx) {
155
157
  // ─── D3 settle 共享 helper ───────────────────────────────────────────────────
156
158
 
157
159
  /**
158
- * §23.3.1 消化窗口持有释放(TUI-OOM-ROOTCAUSE——D-SM2 表 2 候选 1):注入完成后置空条目
160
+ * AGENT-LOOP.md §6.15 消化窗口持有释放(TUI-OOM-ROOTCAUSE——D-SM2 表 2 候选 1):注入完成后置空条目
159
161
  * 对子代理对象的引用(`childAgent`/`report`——条目前此从不显式释放,挂起期 = 分钟级驻留)。
160
162
  * 幂等(重入不抛);池内/挂起未消化窗口语义零变(settle 时刻不释放——表 2 候选 2 否决:
161
163
  * status/observe 在窗口内仍读 child 摘要)。三消费点(回合尾收集 / run 起始 pending 注入 /
@@ -178,10 +180,10 @@ export function releaseSettledEntry(entry) {
178
180
  * ③ 分流:cancelled(出池 + cancelled 墓碑 + ⟦ev⟧stopped + 族提醒——不入 pending)→
179
181
  * parentAborted(守卫抑制——不落事件不入流——中止清池在回合尾/挂起中止统一做)→
180
182
  * settled(族 onAccounting hook 记账 → 挂起期(或 consult 族恒停靠)移交 pending
181
- * 单容器 + 出池 + ⟦ev⟧settled;回合内 ⟦ev⟧done 留池 done:true);
183
+ * 单容器 + 出池,非挂起期留池 done:true;两态一律 ⟦ev⟧settled——⟦ev⟧done = 消费面补发);
182
184
  * ④ 公共尾部:settleSeq 递增 + `_settle` 唤醒 waiter + 腾槽补位(subagent/escalate 族
183
185
  * 恒补——settle/cancel 释放槽 → maybeRefillAsync + refreshQueuedTokens——AGENT-LOOP.md
184
- * §10 "settle/cancel 释放槽后…启动到槽满";advisor 经 refillAdvisorQueue 补位
186
+ * AGENT-LOOP-SUBAGENT.md §6.9 "settle/cancel 释放槽后…启动到槽满";advisor 经 refillAdvisorQueue 补位
185
187
  * (ED-4——评审池有排队语义后不再豁免);consult(会话池)豁免)。
186
188
  * opts(设计签名 `{pool, onAccounting}` + 实现参数 ctx):
187
189
  * - pool:条目所在池 Map(出池 delete 目标;consult 传 null——会话池无条目)。
@@ -193,7 +195,7 @@ export function releaseSettledEntry(entry) {
193
195
  * 设计偏差注(advisor code review 发现——交付报告同步):设计 D3 把 maybeRefillAsync
194
196
  * 归入 onAccounting hook(仅 settled 分支执行)——running 取消的 cancelled 分支将不再
195
197
  * 补位(槽释放但 queued 头停滞——挂起会话无回合尾补位覆盖),违背既有不变式
196
- * (AGENT-LOOP.md §10 + subagent-scheduler maybeRefillAsync 文档 "called from every
198
+ * (AGENT-LOOP-SUBAGENT.md §6.9 + subagent-scheduler maybeRefillAsync 文档 "called from every
197
199
  * settle")与 VSC 镜像(无条件 refill)。修正:腾槽补位移入公共尾部(subagent/escalate
198
200
  * 族恒补——旧行为零回归;advisor/consult 豁免——同 VSC refill!==false 语义)。
199
201
  */
@@ -232,10 +234,10 @@ export function settleAsyncEntry(parent, entry, opts = {}) {
232
234
  }
233
235
  // ③ 分流
234
236
  if (entry.cancelled) {
235
- // §19.5 cancelled settle 分支(D-M6):不入 pending、不参与回合尾直注入——清池 +
237
+ // AGENT-LOOP-SUBAGENT.md §6.7.2 cancelled settle 分支(D-M6):不入 pending、不参与回合尾直注入——清池 +
236
238
  // 终态墓碑(dependsOn 取消语义)+ ⟦ev⟧stopped 冻结 + 族提醒(半成品警示对模型可见)。
237
239
  pool?.delete(String(entry.id))
238
- writeTombstone(parent, entry.id, "cancelled", role) // §20 D-SD5:单点写入(#94 载体吸收)
240
+ writeTombstone(parent, entry.id, "cancelled", role) // AGENT-LOOP-SUBAGENT.md §6.9 D-SD5:单点写入(#94 载体吸收)
239
241
  ctx?.callbacks?.onToken?.(`${entry.relayPrefix}⟦ev⟧stopped\x1e0\x1e0\x1estopped\x1e`)
240
242
  if (role === "advisor") {
241
243
  // ②-6b:评审取消——token 未签发提醒(settleAdvisorRun 不消费预算)。
@@ -249,7 +251,7 @@ export function settleAsyncEntry(parent, entry, opts = {}) {
249
251
  content: `[System reminder: async escalate #${entry.id} (${entry.tag}) cancelled by user — partial changes not merged/audited]`,
250
252
  })
251
253
  } else {
252
- // §20 D-SD5:running 依赖取消——提醒列出依赖者(供模型决策)。
254
+ // §6.9 D-SD5:running 依赖取消——提醒列出依赖者(供模型决策)。
253
255
  const dependents = dependentLabels(parent, String(entry.id))
254
256
  const autoNote = parent.autoApprove
255
257
  ? " — AUTO session: they auto-start on slot availability (round2 #3)"
@@ -263,23 +265,24 @@ export function settleAsyncEntry(parent, entry, opts = {}) {
263
265
  // 族记账 hook(advisor 陈旧判定/token D1 落盘;escalate 三分类 merge 决策;subagent/
264
266
  // escalate 腾槽补位)——可改写 entry.report(settle 分支输出——digest 原样进)。
265
267
  onAccounting?.(parent, entry)
266
- // 挂起分流(§17 D-S8 + D-S3 记账——以读取时刻为准):挂起期 settle → 移交 pending
267
- // 单容器(digest 注入)+ 出池 + ⟦ev⟧settled 驻留;回合内 → ⟦ev⟧done 立即冻结
268
- // (条目留池——done-in-pool 统一表示——回合尾 collectSettledAsync 注入)。
268
+ // 挂起分流(AGENT-LOOP-ASYNC-POOL.md §6.8 D-S8 + D-S3 记账——以读取时刻为准):挂起期 settle → 移交 pending
269
+ // 单容器(digest 注入)+ 出池;非挂起期 ⇒ 留池 done-in-pool(回合尾 collectSettledAsync 注入兜底 ∥
270
+ // 挂起会话 sweep 消费链照旧)。
269
271
  // consult 族恒停靠(settle 即出会话池入 pending——无 TUI 冻结事件——子块各自冻结)。
270
272
  if (suspended || role === "consult") {
271
273
  parkAsyncPending(parent, entry)
272
274
  pool?.delete(String(entry.id))
273
- ctx?.callbacks?.onToken?.(`${entry.relayPrefix}⟦ev⟧settled\x1e0\x1e0\x1esettled\x1e`)
274
- } else {
275
- ctx?.callbacks?.onToken?.(`${entry.relayPrefix}⟦ev⟧done\x1e0\x1e0\x1edone\x1e`)
276
275
  }
276
+ // 发射单点(块到达时点归位批 · #746|§6.8「settle 延迟冻结(两态统一)」):settle 一律 ⟦ev⟧settled
277
+ // (区块头恒中间态「done · awaiting digestion」驻留面板);⟦ev⟧done = 消费面补发(消费窗清单单源
278
+ // = §6.8)⇒ 冻结 ∥ 归档恒落消费时点——回合运行中零归档触发器(「S 不夹运行中回合」结构不变式)。
279
+ ctx?.callbacks?.onToken?.(`${entry.relayPrefix}⟦ev⟧settled\x1e0\x1e0\x1esettled\x1e`)
277
280
  }
278
281
  // ④ 公共尾部:settleSeq 递增 + _settle 唤醒(never rejects)+ 唤醒挂起驱动 waiter
279
282
  entry._settleSeq = (parent._asyncSettleSeq = (parent._asyncSettleSeq ?? 0) + 1)
280
283
  entry._settle?.()
281
284
  wakeAsyncWaiters(parent) // §6.27.12.4 ①:挂起驱动唤醒单点(settle 尾 / 上行 ask 入队尾两处调用)
282
- // §20 D-SD4 释放点:settle/cancel 释放槽 + 依赖终态转移 → 补位(依赖满足者/域冲突
285
+ // §6.9 D-SD4 释放点:settle/cancel 释放槽 + 依赖终态转移 → 补位(依赖满足者/域冲突
283
286
  // 解除者自动启动——槽 ≤4)→ 排队态面板刷新(等待块头标注随终态更新——dependency
284
287
  // cancelled / 位置前移)。subagent/escalate 族恒补(旧行为零回归——cancelled 分支
285
288
  // 同样补位);advisor(ED-4——独立评审池的排队语义)经 refillAdvisorQueue 补位;
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  /**
12
- * §18.7 D-TS5 (A2): mechanically summarize the parent spawn task book for the
12
+ * AGENT-LOOP-SUBAGENT.md §6.7.6 D-TS5 (A2): mechanically summarize the parent spawn task book for the
13
13
  * audit spawn — the three audit-relevant elements VERBATIM (design doc paths /
14
14
  * affected-file list / acceptance criteria); verbose context/background is
15
15
  * dropped (the auditor can read the design docs themselves — they stay
@@ -70,8 +70,8 @@ export function summarizeEngTaskBook(taskInput) {
70
70
  export function buildAuditBlock(ctx) {
71
71
  const touched = (ctx.agent._touchedFiles ?? []).map((f) => `- ${f}`).join("\n") || "- (none yet)"
72
72
  return `[Audit scope — mechanical context, independent of the eng-coder's self-report:]\n` +
73
- // §18.7 D-TS4 A1:审计指令模板(四类偏差 + 范围限制 + 校验清单格式)——审计语义
74
- // 不再靠模型自悟;范围限制是 §18.5 D-AG3 声明(下方 Zero-git scope authority)
73
+ // §6.7.6 D-TS4 A1:审计指令模板(四类偏差 + 范围限制 + 校验清单格式)——审计语义
74
+ // 不再靠模型自悟;范围限制是 §6.7.4 D-AG3 声明(下方 Zero-git scope authority)
75
75
  // 的同源一句指注,不重复声明。
76
76
  `[Audit instructions — mechanical template:]\n` +
77
77
  `You are auditing an eng-coder delivery against its approved design — audit for EXACTLY these four deviation categories:\n` +
@@ -83,21 +83,21 @@ export function buildAuditBlock(ctx) {
83
83
  `workspace changes not listed there are unrelated to this delivery and are NOT grounds for an out-of-list finding.\n` +
84
84
  `Scope discipline (F-TS6 A1): read ONLY the audited files and the design-doc sections relevant to this delivery — do NOT re-read whole documents.\n` +
85
85
  `Every deviation item MUST be fieldized: file:line + design reference (doc path + section/AC id) + severity + evidence (quoted code or doc text).\n` +
86
- // §18.7 D-TS5 A2:任务书从全量 verbatim 改机械摘要块(三要素逐字——排除冗长上下文)。
86
+ // §6.7.6 D-TS5 A2:任务书从全量 verbatim 改机械摘要块(三要素逐字——排除冗长上下文)。
87
87
  `[Parent spawn task book — mechanical summary: design docs + affected-file list + acceptance criteria verbatim; verbose context/background dropped — the design docs are still available for reading outside this input:]\n` +
88
88
  `${summarizeEngTaskBook(ctx.agent._engTaskInput)}\n` +
89
89
  `Files actually touched by the eng-coder (mechanical union — audit these against the file list):\n${touched}\n` +
90
90
  // §18.5 D-AG3(2026-09-04):审计零 git 范围权威声明——本审计任务零 git(不注入
91
- // git 上下文——§18.5 全角色零 git);_touchedFiles 为审计范围;工作区未列于
91
+ // git 上下文——§6.7.4 全角色零 git);_touchedFiles 为审计范围;工作区未列于
92
92
  // _touchedFiles 的改动与本任务无关,不作超清单依据(VS Code auditTaskBook 同款措辞)。
93
93
  "Zero-git scope authority: this audit task receives NO git context — nothing is injected. " +
94
94
  "The evidence base is the design documents, the current disk state (read/glob/grep), and the _touchedFiles list above. " +
95
95
  "Workspace changes NOT listed in _touchedFiles are unrelated to this delivery — they are NOT grounds for an out-of-file-list finding." +
96
- // §18.13 D-A1.2:审计预算句——A1 指令模板 + A2 摘要块之后、A3 报告模板之前(定序——评审 #7)。
96
+ // §6.7.6 D-A1.2:审计预算句——A1 指令模板 + A2 摘要块之后、A3 报告模板之前(定序——评审 #7)。
97
97
  // 逐字设计锚(D-A1.2 代码块):只读该读的——10 轮机械预算——超时报 PROBLEM 下结论。
98
98
  // 前导 \n 与 A3 同款块分隔约定(上一句 Zero-git 句末无换行——不触碰既有句)。
99
99
  `\n[Audit budget — mechanical]: read ONLY the touched files listed above and the design-doc sections the parent task book names (affected-files table, acceptance criteria, status line). Do NOT read whole documents. Budget = 10 tool rounds max — if you cannot conclude within it, report PROBLEM (inconclusive) rather than continuing to explore.\n` +
100
- // §18.7 D-TS6 A3:审计输出报告格式模板(三态——字段化行——不让模型自由发挥)。
100
+ // §6.7.6 D-TS6 A3:审计输出报告格式模板(三态——字段化行——不让模型自由发挥)。
101
101
  `\n[Audit report format — mechanical template:]\n` +
102
102
  `Report EXACTLY one of three states:\n` +
103
103
  `- CLEAN — no deviation across the four categories: reply the line "Four deviation categories: none found." (四类偏差均未发现);\n` +