@thincoder/core 0.9.5 → 0.10.2

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 (216) hide show
  1. package/CHANGELOG.md +49 -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 +12 -12
  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 +22 -12
  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 +54 -296
  20. package/agent/family-tools.mjs +5 -5
  21. package/agent/helpers.mjs +53 -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 +15 -11
  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 +89 -29
  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 +9 -9
  36. package/agent-tools/advisor-settle.mjs +12 -12
  37. package/agent-tools/advisor.mjs +36 -41
  38. package/agent-tools/async-discard.mjs +44 -1
  39. package/agent-tools/async-settle.mjs +21 -18
  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 +57 -18
  43. package/agent-tools/batch-paths.mjs +52 -8
  44. package/agent-tools/batch-skeleton.mjs +19 -1
  45. package/agent-tools/batch.mjs +12 -65
  46. package/agent-tools/checkpoint.mjs +121 -0
  47. package/agent-tools/child-permission.mjs +5 -3
  48. package/agent-tools/consult.mjs +56 -56
  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 +16 -11
  54. package/agent-tools/goal.mjs +3 -10
  55. package/agent-tools/panel-blocks.mjs +2 -2
  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 +21 -265
  66. package/agent-tools/subagent-async.mjs +25 -20
  67. package/agent-tools/subagent-panel.mjs +33 -4
  68. package/agent-tools/subagent-run.mjs +36 -21
  69. package/agent-tools/subagent-scheduler.mjs +28 -27
  70. package/agent-tools/subagent-spawn.mjs +45 -14
  71. package/agent-tools/subagent.mjs +33 -53
  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 +18 -355
  77. package/attachments.mjs +125 -0
  78. package/auto-think.mjs +1 -1
  79. package/config-presets.mjs +11 -6
  80. package/config-watch.mjs +83 -0
  81. package/config.mjs +29 -12
  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/history-window.mjs +17 -2
  95. package/i18n.mjs +2 -0
  96. package/index-discover.mjs +7 -7
  97. package/ledger-cmd.mjs +34 -126
  98. package/ledger-db.mjs +10 -2
  99. package/ledger-tools.mjs +188 -0
  100. package/ledger.mjs +9 -4
  101. package/log.mjs +12 -7
  102. package/manifest-discovery.mjs +131 -0
  103. package/manifest-schema.mjs +166 -0
  104. package/manifest.mjs +18 -217
  105. package/mcp.mjs +4 -1
  106. package/memory/code-search.mjs +149 -0
  107. package/memory/code-sync.mjs +89 -230
  108. package/memory/core.mjs +47 -32
  109. package/memory/docs.mjs +63 -262
  110. package/memory/file-list.mjs +89 -0
  111. package/memory/file-walk.mjs +7 -4
  112. package/memory/memory-tool.mjs +229 -0
  113. package/memory/schema.mjs +18 -3
  114. package/memory/sweep.mjs +289 -0
  115. package/memory/sync-tail.mjs +81 -0
  116. package/memory-status.mjs +69 -0
  117. package/memory.mjs +3 -0
  118. package/model-ref.mjs +96 -3
  119. package/model-specs.mjs +16 -7
  120. package/notify-policy.mjs +51 -0
  121. package/package.json +1 -1
  122. package/peer-claims.mjs +2 -2
  123. package/peer-domains.mjs +7 -11
  124. package/peer-instances.mjs +9 -10
  125. package/process-probe-exec.mjs +187 -0
  126. package/process-probe.mjs +27 -175
  127. package/prompt-overlays.mjs +11 -10
  128. package/prompts/advisor-design.md +2 -2
  129. package/prompts/advisor-round2.md +1 -1
  130. package/prompts/advisor-round3.md +1 -1
  131. package/prompts/common.md +16 -8
  132. package/prompts/discipline-engineering.md +57 -16
  133. package/prompts/discipline-normal.md +6 -3
  134. package/prompts/persona-coder.md +0 -1
  135. package/prompts/persona-eng-coder.md +1 -5
  136. package/prompts/persona-eng-designer.md +2 -3
  137. package/prompts/persona-engineering.md +32 -11
  138. package/prompts/persona-explore.md +0 -1
  139. package/prompts/persona-normal.md +1 -1
  140. package/prompts/persona-plan.md +3 -4
  141. package/prompts/subagent-base.md +14 -0
  142. package/provider/core.mjs +11 -48
  143. package/provider/list-models.mjs +3 -0
  144. package/provider/responses-request.mjs +237 -0
  145. package/provider/responses.mjs +6 -228
  146. package/provider-flows.mjs +248 -0
  147. package/queued.mjs +90 -0
  148. package/rules.mjs +209 -2
  149. package/session-guard.mjs +27 -7
  150. package/session-lifecycle.mjs +108 -27
  151. package/session-rename.mjs +5 -1
  152. package/session-slot-claims.mjs +230 -0
  153. package/session-slot-scan.mjs +299 -0
  154. package/session-slot-verify.mjs +304 -0
  155. package/session-slot-write.mjs +74 -8
  156. package/session-slots-manifest.mjs +163 -241
  157. package/session-slots.mjs +99 -71
  158. package/session.mjs +30 -10
  159. package/shell-candidates.mjs +78 -0
  160. package/text-budget.mjs +2 -2
  161. package/think-off.mjs +49 -0
  162. package/token-ttl.mjs +15 -4
  163. package/tool-args.mjs +73 -0
  164. package/tool-docs/advisor.md +9 -0
  165. package/tool-docs/batch.md +1 -0
  166. package/tool-docs/code_search.md +1 -0
  167. package/tool-docs/consult_start.md +5 -0
  168. package/tool-docs/consult_stop.md +3 -0
  169. package/tool-docs/context.md +7 -0
  170. package/tool-docs/doc_search.md +1 -0
  171. package/tool-docs/edit.md +2 -13
  172. package/tool-docs/eng.md +1 -0
  173. package/tool-docs/execute.md +1 -9
  174. package/tool-docs/git.md +25 -51
  175. package/tool-docs/goal.md +6 -0
  176. package/tool-docs/ledger_add.md +1 -0
  177. package/tool-docs/ledger_close.md +1 -0
  178. package/tool-docs/ledger_count.md +1 -0
  179. package/tool-docs/ledger_query.md +1 -0
  180. package/tool-docs/ledger_update.md +1 -0
  181. package/tool-docs/main_history.md +1 -0
  182. package/tool-docs/memory.md +10 -0
  183. package/tool-docs/notify_parent.md +9 -0
  184. package/tool-docs/peer_instances.md +1 -0
  185. package/tool-docs/plan.md +5 -0
  186. package/tool-docs/process.md +7 -3
  187. package/tool-docs/read_history.md +7 -0
  188. package/tool-docs/recent_changes.md +1 -0
  189. package/tool-docs/repo_outline.md +1 -0
  190. package/tool-docs/settings.md +6 -0
  191. package/tool-docs/skill.md +5 -0
  192. package/tool-docs/subagent.md +31 -0
  193. package/tool-docs/task.md +7 -0
  194. package/tool-docs/timer.md +6 -0
  195. package/tool-docs/verify.md +1 -0
  196. package/tool-docs/wait_for.md +2 -1
  197. package/tools/bash.mjs +28 -4
  198. package/tools/edit-batch.mjs +4 -4
  199. package/tools/edit-diff.mjs +4 -23
  200. package/tools/exec-run.mjs +102 -4
  201. package/tools/execute.mjs +5 -2
  202. package/tools/file.mjs +4 -9
  203. package/tools/git-run.mjs +1 -1
  204. package/tools/git.mjs +0 -24
  205. package/tools/index.mjs +2 -1
  206. package/tools/linter.mjs +2 -1
  207. package/tools/node-child.mjs +21 -0
  208. package/tools/ops.mjs +50 -13
  209. package/tools/patch.mjs +4 -2
  210. package/tools/repomap.mjs +20 -9
  211. package/tools/shared.mjs +8 -6
  212. package/tools/web.mjs +5 -2
  213. package/tools/write-path.mjs +1 -1
  214. package/traces/trace-store.mjs +17 -14
  215. package/vision-reader.mjs +76 -0
  216. package/agent-tools/batch-segment.mjs +0 -18
package/CHANGELOG.md CHANGED
@@ -3,6 +3,55 @@
3
3
  All notable changes to the core package are documented here.
4
4
  Format: Keep a Changelog · 中文 · 号在发布时定(CalVer——见 `docs/RELEASE.md` §4)。
5
5
 
6
+ ## [0.10.2] — 2026-10-03
7
+
8
+ > 0.10.1 → 0.10.2(月内 +1——发布时定号)
9
+
10
+ ### Added
11
+
12
+ - **统一 provider 解析(#841 · 三端归一)**:核导出 `resolveProviderPlan`(回退链 = 槽渠道(持 key)→ `defaultModel` 渠道 → 首个持 key 渠道;模型面 = 槽模型 → `defaultModel`(同渠道)→ 渠道单值 → `null`;三态 = `ok` ∕ `fallback` ∕ `invalid` + `reason`)与 `resolveChannelModel`(单值转口面)。
13
+ - **`providerState` ∕ `providerStateReason` 两键**:`loadConfig()` 落(`provider` = 解析入选渠道)+ 槽面 key 门(`applySession`——槽无 key ⇒ 跳过且不写槽)。
14
+
15
+ ### Changed
16
+
17
+ - **「无效」语义收窄**:仅「无 provider ∥ 无 key」为 `invalid`(不可运行 ⇒ 引导配置);「可运行而无有效 `defaultModel`」为 `fallback`(**可运行 + 必明示**——不再当无效拦下)。
18
+
19
+ ## [0.10.1] — 2026-10-03
20
+
21
+ > 0.9.5 → 0.10.1(月切换——十月首发,发布时定号)
22
+
23
+ ### Added
24
+
25
+ - **公开仓读取(declared sources)**:可把外部公开仓声明为「公开源」——检索 ∕ 引用 ∕ 提示词面一体支持(多仓工作区的只读面)+ 四条提示面词句与机检。
26
+ - **会话锚解析(session-anchor)**:`projectRootView` 三态(ok ∕ ambiguous ∕ none)+ 歧义保护贯通台账 ∕ 批档 ∕ 写门——多清单工作区不再猜锚。
27
+ - **多仓操作机制(六提示面 · 中英)**:仓 = 一个 git 仓;一档一仓;子代理只写本仓;跨仓任务分仓记录;发现物报告路由。
28
+ - **工程纪律面**:轻通道三判据 + 一句边界(四面)∥ 命名纪律(禁生造词)∥ 单测 ∕ 集成锚定与「单测永不升集成」∥ 反膨胀判断 ∥ fix-in-place 与追认核销。
29
+ - **`pushRecord` 缝(#726)**:人工可读行的记录追加面。
30
+ - **settle 事件归一(#746)**:done 仅在消费时落——子代理块不再中途拼接。
31
+ - **heap 快照采集运行期开关**(默认关);**桌面 digest 持久化(#719)**:traces 与归档子代理块跨重载 ∕ 重挂 ∕ 换会话存活。
32
+ - **桌面聊天面板(A+B)+ e2e 骨架** ∥ **turn-cap 续跑(F8 ∕ F9)+ slot-end 参数 + config 镜像** ∥ **空闲唤醒 p2 核**(opt-in 注入 + 中止适配——timer-wake #443 ∕ #444)∥ **子代理升级 canonical 重写 + subagent-base 单源层**(18 处去重——#442)。
33
+ - **R8 台账刷新(核面)** + config-watch 升级 + 热重载 + L2 明细行;channels 23(13 档)。
34
+ - **parity B1–B10 波 + 走查轮**:滚动退出 ∕ 挂起队列 ∕ 状态栏 ∕ 渲染性能 ∕ execute 修复 ∕ i18n ∕ 设置 ∕ 复制 ∕ 卡顿指示 ∕ 发送忙碌队列。
35
+ - **`PROJECT-MANIFEST.json` 接管声明面**:codePaths ∕ index ∕ advisor 三键入驻(旧 `conventions.json` 退役);**eng 写门豁免 aux 路径**(test/tests/scripts、.thincoder/tmp)。
36
+
37
+ ### Changed
38
+
39
+ - **测试面重整**:全仓旧套件退役(五包——runner 骨架保留,空 = 绿);开发期测试件 36 档退役(-213 例)+ 锁型测试件 10 档退役(-87 例);单测 = 批内件(随批档,可复跑)。
40
+ - **规则上收(R10)**:薄壳规则纯搬迁入核(字节一致探针);VSC 壳重指向。
41
+ - **提示词面**:EN 面 parity 收正(#721)∥ `batch_segment` 过渡别名退役 ∥ 模式口径收正(文档系统模式无关)∥ 轻通道收口(#725——提醒点 + 跨会话承接)。
42
+
43
+ ### Fixed
44
+
45
+ - **批档 CRLF 容忍 + CLI 粘贴生命周期(#732 ∕ #733)**;**VSC 粘贴临时件写时清扫(#735——有界临时目录)**。
46
+ - **会话台账可靠性核**:懒校验 + 写安全 + 空值 ∕ `—` 显示;**会话列表按磁盘槽扫描**(resume 门 + 18 例)。
47
+ - **manifest 写守卫**:不可信 base 拒写(G1–G11);**台账工具参数守卫** + 写门 null ∕ empty `task_book`(AC-M2-15)。
48
+ - **项目相对守卫面 + 台账读守卫**(ledger-tools 拆分);**`ledger_close` 追认核销路径**。
49
+ - **桌面残项**:恢复态播种 ∥ user-block md 深度 ∥ 事件拆分。
50
+
51
+ ### Removed
52
+
53
+ - **`conventions.json` 退役**(`PROJECT-MANIFEST.json` 单源);旧测试套件族(锁型 ∕ 开发期——见 Changed)。
54
+
6
55
  ## [0.9.5] — 2026-09-25
7
56
 
8
57
  > 0.9.4 → 0.9.5(月内序号——发布时定号)
package/README.md CHANGED
@@ -82,7 +82,7 @@ Per-release notes and artifacts: `CHANGELOG.md` in this package and the [GitHub
82
82
  The core lives in `thincoder-core/` of the ThinCoder repository; bug reports and questions go to the
83
83
  repository issue tracker. Two conventions shape every change: pure ESM `.mjs` with no build step, and
84
84
  zero third-party dependencies — if the Node.js standard library can do it, no third-party package is
85
- allowed. `npm test` runs the offline unit suite; it runs again on release through `prepublishOnly`.
85
+ allowed. `npm test` runs the repo suite entry (`node test/run.mjs`); after the 2026-09-28 full reset the suite manifest is empty (zero tests = green — collection self-checks still run). Unit tests live as batch-local files under `docs/batches/` in the repository — current state: `docs/core/design/TESTING.md` §2.3. It runs again on release through `prepublishOnly`.
86
86
  Mechanism design documents live in the repository under `docs/core/design/`.
87
87
 
88
88
  ## License
@@ -1,8 +1,8 @@
1
1
  /**
2
- * abort-provenance.mjs — abort 来源标注词汇表(单一权威源——AGENT-LOOP.md §20.3 第 1/2 条)
2
+ * abort-provenance.mjs — abort 来源标注词汇表(单一权威源——AGENT-LOOP-SUBAGENT.md §6.12)
3
3
  *
4
4
  * 子代理 / 评审 / 会诊死亡的可诊断性:产生点标注结构化来源(`err.abortInfo`)→
5
- * controller 链 hop 逐跳保 reason(§20.3 第 4 条 #10)→ 结算 / 报告面用 `deathLine`
5
+ * controller 链 hop 逐跳保 reason(AGENT-LOOP-SUBAGENT.md §6.12 形态④ #10)→ 结算 / 报告面用 `deathLine`
6
6
  * 合成死亡行(原 message 前缀逐字保留 + 来源后缀)。
7
7
  *
8
8
  * 纯函数、零 import——任意层可引、无环(provider / proxy / agent / settle 族共用)。
@@ -12,11 +12,11 @@
12
12
  * - layer(3 值):`provider` / `agent` / `settle`;未标注错误回落 `unrecorded`(合成器 token)。
13
13
  */
14
14
 
15
- /** trigger 枚举权威(测试锁计数 5——AGENT-LOOP.md §20.3 第 1 条表)。 */
15
+ /** trigger 枚举权威(测试锁计数 5——AGENT-LOOP-SUBAGENT.md §6.12 trigger 表)。 */
16
16
  export const TRIGGERS = ["user", "timeout", "cancel", "stop", "unknown"]
17
17
 
18
18
  /**
19
- * trigger 判定(判据序 = §20.3 第 1 条表;signal.reason 四形态:
19
+ * trigger 判定(判据序 = AGENT-LOOP-SUBAGENT.md §6.12 第 1 条表;signal.reason 四形态:
20
20
  * ① `{interrupt:true(,message)}`(既有 user 面)② `TimeoutError`(原生——timeout 面)
21
21
  * ③ `{abortTrigger:"cancel"|"stop"|"timeout"(,abortDetail)}`(新增——程序性中止)
22
22
  * ④ 缺失 / 无已知键(→ unknown——诊断告警态,不得静默)。
@@ -65,17 +65,17 @@ export function annotateAbort(err, signal, layer, detail) {
65
65
  return err
66
66
  }
67
67
 
68
- /** 死亡行长度上限(AGENT-LOOP.md §20.3 第 3 条——超长优先截 detail)。 */
68
+ /** 死亡行长度上限(AGENT-LOOP-SUBAGENT.md §6.12 死亡行形态——超长优先截 detail)。 */
69
69
  const MAX_LEN = 300
70
- /** unknown 形态 detail token(§20.3 第 3 条逐字)。 */
70
+ /** unknown 形态 detail token(AGENT-LOOP-SUBAGENT.md §6.12 逐字)。 */
71
71
  const NO_REASON = "no reason on signal"
72
72
  /** 未标注回落 token(layer / detail 两面兜底)。 */
73
73
  const UNRECORDED = "unrecorded"
74
74
 
75
- /** 信号域 detail 回落(§20.3 第 1 条形态③——`abortDetail` 载站点名;错误未标注时仍可辨发起动作)。 */
75
+ /** 信号域 detail 回落(AGENT-LOOP-SUBAGENT.md §6.12 形态③——`abortDetail` 载站点名;错误未标注时仍可辨发起动作)。 */
76
76
  const detailOf = (signal) => (typeof signal?.reason?.abortDetail === "string" ? signal.reason.abortDetail : null)
77
77
 
78
- /** 求值链(§20.3 第 1 条:err.abortInfo → triggerOf(signal) → err.name 兜底)。 */
78
+ /** 求值链(§6.12 第 1 条:err.abortInfo → triggerOf(signal) → err.name 兜底)。 */
79
79
  function resolveAbort(err, signal) {
80
80
  const info = err?.abortInfo
81
81
  if (info?.trigger) return { trigger: info.trigger, layer: info.layer ?? UNRECORDED, detail: info.detail || null }
@@ -93,7 +93,7 @@ function clipDetail(detail, budget) {
93
93
  }
94
94
 
95
95
  /**
96
- * 死亡行合成器(§20.3 第 3 条——报告面单点):
96
+ * 死亡行合成器(§6.12 第 3 条——报告面单点):
97
97
  * `<原 message>[ ← cause: <cause.message>][ · abort(<trigger>@<layer>:<detail>)]`
98
98
  * - 原 message 前缀逐字保留(既有前缀 / 包含断言零回归);
99
99
  * - 后缀出现条件 = `err.abortInfo` 存在 ∨ `signal?.aborted` ∨ `err.name ∈ {AbortError, TimeoutError}`;
@@ -108,7 +108,7 @@ export function deathLine(err, signal) {
108
108
  if (abortish) {
109
109
  const { trigger, layer, detail } = resolveAbort(err, signal)
110
110
  const head = `${line} · abort(${trigger}@${layer}:`
111
- // unknown 形态逐字用告警 token(§20.3 第 3 条——站点 detail 不进告警行);非串 detail 归一化
111
+ // unknown 形态逐字用告警 token(§6.12 第 3 条——站点 detail 不进告警行);非串 detail 归一化
112
112
  const text = trigger === "unknown" ? NO_REASON : (detail == null ? UNRECORDED : String(detail))
113
113
  line = `${head}${clipDetail(text, MAX_LEN - head.length - 1)})`
114
114
  }
@@ -5,7 +5,7 @@
5
5
  * checked against the CURRENT disk state; mismatches mark the finding
6
6
  * unverified and cannot support a push-back.
7
7
  *
8
- * 第 11 批(C / F14 / §14.5):解析候选 = cwd + **评审对象声明范围派生根**(声明仓根 /
8
+ * 第 11 批(C / F14 / `ADVISOR-GUARDS.md §3`):解析候选 = cwd + **评审对象声明范围派生根**(声明仓根 /
9
9
  * 声明文件目录 / 声明目录——纯路径派生,零扫描、零 git);命中判据三条件全中(围栏内 ∧
10
10
  * 可读 ∧ 目标行含引文内容)⇒ 零新增假命中。失败原因三分(file unreadable /
11
11
  * content mismatch @ path / path traversal)——父侧不再人肉复核。
@@ -30,7 +30,7 @@ export function extractCitations(text) {
30
30
  return out
31
31
  }
32
32
 
33
- /** 候选解析根(§14.5——纯路径派生,候选顺序 = cwd → 各声明路径的派生根):
33
+ /** 候选解析根(`ADVISOR-GUARDS.md §3`——纯路径派生,候选顺序 = cwd → 各声明路径的派生根):
34
34
  * 声明仓根(`cwd/<segs[0]>`)与 声明文件目录 / 声明目录本身。声明在 cwd 之外 → 不派生
35
35
  * (relative 越出 cwd 或跨盘符——候选与声明脱节即假命中面)。 */
36
36
  function citationRoots(cwd, scope) {
@@ -50,7 +50,7 @@ function citationRoots(cwd, scope) {
50
50
  return roots
51
51
  }
52
52
 
53
- /** 单引文解析(§14.5):按候选顺序试 `resolve(root, file)`;三条件全中才算命中。
53
+ /** 单引文解析(`ADVISOR-GUARDS.md §3`):按候选顺序试 `resolve(root, file)`;三条件全中才算命中。
54
54
  * @returns {{matched: true, root: string, resolved: string}|{matched: false, reason: string}} */
55
55
  function resolveCitation(citation, roots, base) {
56
56
  const fence = base + sep
@@ -104,7 +104,7 @@ export function verifyCitations(text, cwd, opts = {}) {
104
104
  for (const c of citations) {
105
105
  const r = resolveCitation(c, roots, base)
106
106
  if (r.matched) {
107
- // 命中根记录(§14.5):经派生根解析(非 cwd 直解)的命中在报告中注明解析路径。
107
+ // 命中根记录(`ADVISOR-GUARDS.md §3`):经派生根解析(非 cwd 直解)的命中在报告中注明解析路径。
108
108
  matched.push(r.root === base ? c : { ...c, root: r.root, resolved: r.resolved })
109
109
  } else {
110
110
  failed.push({ ...c, reason: r.reason })
@@ -122,7 +122,7 @@ export function appendCitationReport(text, cwd, opts = {}) {
122
122
  "---",
123
123
  `[host-verified] ${matched.length}/${total} citations match current file state.`,
124
124
  ]
125
- // 命中根透明(F14/§14.5):经声明范围派生根解析的命中逐条注明解析路径(cwd 直解的不列
125
+ // 命中根透明(F14/`ADVISOR-GUARDS.md §3`):经声明范围派生根解析的命中逐条注明解析路径(cwd 直解的不列
126
126
  // ——零噪音;列的正是修复前会被误报为 unreadable 的裸路径引用)。
127
127
  const derived = matched.filter((c) => c.resolved)
128
128
  if (derived.length > 0) {
@@ -4,13 +4,13 @@
4
4
  * limits + the terminal-state guards + the review-text assembler.
5
5
  *
6
6
  * estimateTokens / compactMessages moved VERBATIM (the only edit is the `pinned`
7
- * re-attach — F13/§14.4 #3); renderTimeline moved verbatim too, so the tail
7
+ * re-attach — F13/`ADVISOR-GUARDS.md §2` #3); renderTimeline moved verbatim too, so the tail
8
8
  * GENERATOR and the tail CLASSIFIER stay in one file with the assembler they
9
- * feed (§14.3 谓词 ↔ §14.6 结构化尾——同族单源)。拆分线 = 行数硬帽实测(见批次档 §5)。
9
+ * feed (`ADVISOR-GUARDS.md §1` 谓词 ↔ §4 结构化尾——同族单源)。拆分线 = 行数硬帽实测(见批次档 §5)。
10
10
  */
11
11
 
12
12
  import { providerSpec } from "../config.mjs" // 第 25 批:预算派生(与 loop.mjs:11 同源导入)
13
- // B4(群 B 批,CLI §18.3——F32):CJK 加权单源(provider/rate.mjs 叶子向无环)
13
+ // B4(群 B 批,ADVISOR-GUARDS.md §9——F32):CJK 加权单源(provider/rate.mjs 叶子向无环)
14
14
  import { estimateText } from "../provider/rate.mjs"
15
15
 
16
16
  export const MAX_ADVISOR_TURNS = 100
@@ -22,7 +22,7 @@ export const MAX_ADVISOR_TURNS = 100
22
22
  // Context window limits
23
23
  // 上下文预算(第 25 批——120K 硬编码退场):预算跟随评审模型窗口(providerSpec:
24
24
  // 模型规格表 × provider 级 context 覆盖)。头寸用途 = chars/4 估算误差 + 响应/协议开销
25
- // (内存不构成约束——设计 §16.4);判死线仍是宿主机自限线,服务端窗口约束不变。
25
+ // (内存不构成约束——`ADVISOR-GUARDS.md §8`);判死线仍是宿主机自限线,服务端窗口约束不变。
26
26
  export const CONTEXT_LIMIT_RATIO = 0.8 // 判死线 = 窗口 × 0.8
27
27
  const COMPACT_TRIGGER_RATIO = 0.8 // 压缩触发 = 判死线 × 0.8(既有关系零改)
28
28
 
@@ -37,7 +37,7 @@ export const REVIEW_TIMEOUT_MS = 600_000 // whole review timeout (10 minutes)
37
37
  export const MAX_RESULT_CHARS = 64 * 1024 // tool result truncation (line-aware; 64K, aligned with main offload limit)
38
38
  const MAX_KEY_FILES_IN_COMPACTION = 5 // files named in the compaction summary
39
39
 
40
- /** Estimate token count from messages(B4——群 B 批 CLI §18.3:扁平 chars/4 改 `estimateText`
40
+ /** Estimate token count from messages(B4——群 B 批 ADVISOR-GUARDS.md §9:扁平 chars/4 改 `estimateText`
41
41
  * 加权式——ASCII/4 + 非 ASCII/1;纯 ASCII 与旧式逐值相等;CJK 低估 ~3-4× 修正;
42
42
  * walker(content / tool_calls 两源)与计数口径零改)。 */
43
43
  export function estimateTokens(messages) {
@@ -71,7 +71,7 @@ export function compactMessages(messages, pinned = null) {
71
71
  const filesPart = keyFiles.length > 0 ? ` Key files examined: ${keyFiles.join(", ")}` : ""
72
72
  const summary = `Earlier exploration: ${toolCount} tool calls completed.${filesPart}`
73
73
 
74
- // F13(第 11 批 §14.4 #3):压缩丢掉的正是**首条 user 消息**(评审简报,含 token)——
74
+ // F13(第 11 批 · `ADVISOR-GUARDS.md §2` #3):压缩丢掉的正是**首条 user 消息**(评审简报,含 token)——
75
75
  // pinned 由评审参数构建(非模型输出),在本次压缩动作内作为一条 user 消息重挂(幂等可读:
76
76
  // 重复压缩允许重复挂回,不做存在性判定)。
77
77
  const pin = pinned ? [{ role: "user", content: pinned }] : []
@@ -83,10 +83,10 @@ export function compactMessages(messages, pinned = null) {
83
83
  }
84
84
 
85
85
  // ─────────────────────────────────────────────────────────────────────────────
86
- // 不完整判定族(A / F16 共用单谓词——§14.3;六 kind = 宿主尾族)
86
+ // 不完整判定族(A / F16 共用单谓词——`ADVISOR-GUARDS.md §1`;六 kind = 宿主尾族)
87
87
  // ─────────────────────────────────────────────────────────────────────────────
88
88
 
89
- /** 宿主尾族六 kind 的块首行逐字前缀(§14.3 表)。变量段(token 数 / 秒数 / 工具轮数)
89
+ /** 宿主尾族六 kind 的块首行逐字前缀(`ADVISOR-GUARDS.md §1` 表)。变量段(token 数 / 秒数 / 工具轮数)
90
90
  * 不入前缀——取各尾的固定字面部分;`review_failed` = run.mjs catch 的字符串 resolve
91
91
  * 形态(不 throw),其余五条 = renderTimeline 尾(loop.mjs)。 */
92
92
  const ADVISOR_INCOMPLETE_PREFIXES = [
@@ -100,7 +100,7 @@ const ADVISOR_INCOMPLETE_PREFIXES = [
100
100
 
101
101
  /** 单谓词(三消费点同源:design 结算 / code 完成守卫 / 报告提示)——**块首行扫描**(按空行
102
102
  * 分块,逐块取首行 trim 后测前缀;时间线与尾以空行相接,六条尾均以块首行形态落地)。
103
- * 负向精度(§14.3 修正轮):引文中同串的**非块首形态**(围栏内行 / 表格行 / 引用行)不判
103
+ * 负向精度(`ADVISOR-GUARDS.md §1` 修正轮):引文中同串的**非块首形态**(围栏内行 / 表格行 / 引用行)不判
104
104
  * incomplete;块首裸行引用同串的残余误报方向安全(fail-closed——多付一轮重跑,如实登记)。
105
105
  * @returns {string|null} kind 或 null */
106
106
  export function advisorIncompleteMarker(text) {
@@ -116,7 +116,7 @@ export function advisorIncompleteMarker(text) {
116
116
  }
117
117
 
118
118
  // ─────────────────────────────────────────────────────────────────────────────
119
- // 预算提示 + 结构化超时尾(D / F15——§14.6 #2/#3)
119
+ // 预算提示 + 结构化超时尾(D / F15——`ADVISOR-GUARDS.md §4` #2/#3)
120
120
  // ─────────────────────────────────────────────────────────────────────────────
121
121
 
122
122
  /** 0.75 一次性预算提示判定(纯函数——阈值两侧可机测;每场评审至多一次)。 */
@@ -124,14 +124,14 @@ export function shouldBudgetNudge(elapsedMs, budgetMs, nudged) {
124
124
  return !nudged && Number.isFinite(budgetMs) && budgetMs > 0 && elapsedMs >= budgetMs * 0.75
125
125
  }
126
126
 
127
- /** 预算提示文案(逐字——§14.6 #2;由循环注入一条 user 消息)。 */
127
+ /** 预算提示文案(逐字——`ADVISOR-GUARDS.md §4` #2;由循环注入一条 user 消息)。 */
128
128
  export function budgetNudgeText(elapsedMs, budgetMs) {
129
129
  const secs = (ms) => Math.round(ms / 100) / 10
130
130
  const pct = Math.round((elapsedMs / budgetMs) * 100)
131
131
  return `⏳ review budget: ~${pct}% consumed (${secs(elapsedMs)}s of ${secs(budgetMs)}s). Converge now: emit your findings table for the evidence you have verified, mark anything you could not verify explicitly as \`unverified\` (unverified evidence must not support a pass), and emit your verdict line.`
132
132
  }
133
133
 
134
- /** 结构化超时尾(§14.6 #3):族前缀 `Advisor: review timeout after {S}s.` 逐字保持
134
+ /** 结构化超时尾(`ADVISOR-GUARDS.md §4` #3):族前缀 `Advisor: review timeout after {S}s.` 逐字保持
135
135
  * (判定族字面依赖);其后 = 机读统计(rounds / tool calls / review text produced)
136
136
  * + 可执行恢复指引(narrower scope / 调预算)。 */
137
137
  export function timeoutTail(timeoutMs, rounds, toolCalls, producedText) {
@@ -154,9 +154,10 @@ export const ADVISOR_THINKING_PLACEHOLDER = "\n[thinking…]\n"
154
154
 
155
155
  /**
156
156
  * Tool-call progress line summary delegates to the single source describeToolArgs
157
- * (../tui/tool-args.mjs) — the same function main-agent tool blocks and subagent
158
- * blocks use. 2026-08-31: replaced the local picker (action/path/pattern/command-only)
159
- * so advisor progress lines show the quoted-path forms everywhere else.
157
+ * (../tool-args.mjs — B7 1a 上提核件单源;CLI `tui/tool-args.mjs` = 核件同名转口) — the same
158
+ * function main-agent tool blocks and subagent blocks use. 2026-08-31: replaced the local
159
+ * picker (action/path/pattern/command-only) so advisor progress lines show the quoted-path
160
+ * forms everywhere else.
160
161
  */
161
162
  /**
162
163
  * Render the ordered review timeline — thinking / tool progress / final text
package/advisor/loop.mjs CHANGED
@@ -3,7 +3,7 @@
3
3
  * review timeline (split out of advisor/run.mjs, 第 11 批 — run.mjs was 498/500
4
4
  * 硬帽;拆分保持既有 import 面:run.mjs 继续 re-export 本文件导出)。
5
5
  *
6
- * 第 11 批(F15/§14.6):每次 chat 调用携带硬墙信号(`AbortSignal.any([signal,
6
+ * 第 11 批(F15/`ADVISOR-GUARDS.md §4`):每次 chat 调用携带硬墙信号(`AbortSignal.any([signal,
7
7
  * AbortSignal.timeout(remaining)])`;墙判定绑信号状态——抛错 / partial 两形态同判),
8
8
  * 并按 0.75 一次性预算提示 + 结构化超时尾收尾;守卫与限额函数在 compaction.mjs。
9
9
  */
@@ -56,7 +56,7 @@ export { advisorToolsFor, advisorToolsFor as _advisorToolsFor }
56
56
  * the panel keeps moving while the advisor explores — otherwise the panel sits
57
57
  * frozen through every tool-call phase and the review appears to have stalled.
58
58
  *
59
- * @param {string|null} [pinned] — 第 11 批:压缩定锚简报(评审参数构建——F13/§14.4 #3)。
59
+ * @param {string|null} [pinned] — 第 11 批:压缩定锚简报(评审参数构建——F13/`ADVISOR-GUARDS.md §2` #3)。
60
60
  * @param {{now?: Function, chat?: Function, describeArgs?: Function}} [seams] — 测试缝 + ④ 端差注入点
61
61
  * (默认 Date.now / chat / 无进度行——生产调用不传时进度行由端装配层补齐)。
62
62
  */
@@ -64,7 +64,7 @@ async function runAdvisorToolLoop(provider, messages, onOutput, signal, agent, c
64
64
  const now = seams.now ?? Date.now
65
65
  const chatCall = seams.chat ?? chat
66
66
  // ④ 端差注入点(CORE-UNIFICATION §2.5 #109「进度行按端注入」):工具进度行的参数摘要
67
- // 是**展示面**(CLI = `tui/tool-args.mjs` 的 `describeToolArgs`;VSC = 卡片头),不进核。
67
+ // 是**展示面**(单源 = 核 `tool-args.mjs` `describeToolArgs`(B7 1a);CLI 取核件转口,VSC = 卡片头),不进核。
68
68
  // 未注入 ⇒ 不发进度行(核内零端名分支——契约 5 / 10)。端在装配层传入自己的格式化器。
69
69
  const describeArgs = seams.describeArgs ?? (() => "")
70
70
  // 第 11 批硬墙 / 预算 / 尾:实现注解见下方各点;守卫函数与 renderTimeline 在 compaction.mjs。
@@ -91,7 +91,7 @@ async function runAdvisorToolLoop(provider, messages, onOutput, signal, agent, c
91
91
  let reviewTextProduced = false
92
92
  let budgetNudged = false
93
93
  const startTime = now()
94
- // 第 25 批(§16.3):上下文预算跟随评审模型窗口——`providerSpec`(模型规格表 × provider 级
94
+ // 第 25 批(`ADVISOR-GUARDS.md §8`):上下文预算跟随评审模型窗口——`providerSpec`(模型规格表 × provider 级
95
95
  // context 覆盖)派生;函数体内、while 轮次外一次性(provider 全场不变),两档消费见下守卫。
96
96
  const budget = advisorContextBudget(provider)
97
97
 
@@ -106,11 +106,11 @@ async function runAdvisorToolLoop(provider, messages, onOutput, signal, agent, c
106
106
  const timeoutMs = (Number.isFinite(cfg) && cfg > 0) ? cfg : REVIEW_TIMEOUT_MS
107
107
  const elapsed = now() - startTime
108
108
  const remaining = timeoutMs - elapsed
109
- // 硬墙(§14.6 #1):预算用尽 → 结构化超时尾(首行 = 判定族 timeout 前缀)。
109
+ // 硬墙(`ADVISOR-GUARDS.md §4` #1):预算用尽 → 结构化超时尾(首行 = 判定族 timeout 前缀)。
110
110
  if (remaining <= 0) {
111
111
  return renderTimeline(timeline, timeoutTail(timeoutMs, turns, toolCallCount, reviewTextProduced))
112
112
  }
113
- // 0.75 一次性预算提示(§14.6 #2——同一检查点、每场评审至多一次):注入一条 user 消息
113
+ // 0.75 一次性预算提示(`ADVISOR-GUARDS.md §4` #2——同一检查点、每场评审至多一次):注入一条 user 消息
114
114
  // 促模型在墙前收敛产出(不改语义判据、不碰提示词面)。
115
115
  if (shouldBudgetNudge(elapsed, timeoutMs, budgetNudged)) {
116
116
  budgetNudged = true
@@ -143,9 +143,9 @@ async function runAdvisorToolLoop(provider, messages, onOutput, signal, agent, c
143
143
  // reasoning continues right where the placeholder sits.
144
144
  onOutput?.({ kind: "think", text: ADVISOR_THINKING_PLACEHOLDER })
145
145
 
146
- // 硬墙(§14.6 #1):单次请求信号 = 用户信号 × 本调用 deadline(remaining)。复合信号
146
+ // 硬墙(`ADVISOR-GUARDS.md §4` #1):单次请求信号 = 用户信号 × 本调用 deadline(remaining)。复合信号
147
147
  // 无条件传入(上层检查与本调用之间的中止仍必须取消请求——已 aborted 的 composite 使请求
148
- // 立即失败);此处改正了原指向 provider/core.mjs 组合 AbortSignal 的陈旧注释(§14.10 #3)。
148
+ // 立即失败);此处改正了原指向 provider/core.mjs 组合 AbortSignal 的陈旧注释。
149
149
  const callSignal = signal
150
150
  ? AbortSignal.any([signal, AbortSignal.timeout(remaining)])
151
151
  : AbortSignal.timeout(remaining)
@@ -158,7 +158,7 @@ async function runAdvisorToolLoop(provider, messages, onOutput, signal, agent, c
158
158
  onToken: (t) => { if (String(t ?? "").trim()) reviewTextProduced = true; onText(t) },
159
159
  onReasoning: onThink,
160
160
  // LOGGING(vscode advisor/run.mjs parity——按 stage 可 grep)
161
- // §18.6 D-TR4:轨迹元数据增补——kind=advisor(评审独立于子代理——T-TR2);role
161
+ // TRACES.md §6.1 D-TR4:轨迹元数据增补——kind=advisor(评审独立于子代理——T-TR2);role
162
162
  // 透出调用方角色(eng-coder 内嵌评审时为 "eng-coder");session/cwd 供轨迹对回;
163
163
  // traces 开关沿 agent.config(D-TR6)。
164
164
  logCtx: {
@@ -171,7 +171,7 @@ async function runAdvisorToolLoop(provider, messages, onOutput, signal, agent, c
171
171
  },
172
172
  })
173
173
  } catch (e) {
174
- // 墙判定绑信号状态(§14.6 #1——非异常名):① 用户信号已中止 ⇒ 原样上抛(中断语义
174
+ // 墙判定绑信号状态(`ADVISOR-GUARDS.md §4` #1——非异常名):① 用户信号已中止 ⇒ 原样上抛(中断语义
175
175
  // 零变);② 复合信号已中止(墙触发)而用户信号未中止 ⇒ 结构化超时尾(形态①:抛错;
176
176
  // AbortError / TimeoutError 两名兜底——AbortSignal.timeout 的 reason 是 TimeoutError
177
177
  // DOMException);③ 其余错误原样上抛(runAdvisorReview 的失败分类不变)。
@@ -182,7 +182,7 @@ async function runAdvisorToolLoop(provider, messages, onOutput, signal, agent, c
182
182
  throw e
183
183
  }
184
184
  if (signal?.aborted) return renderTimeline(timeline, "Advisor: interrupted.")
185
- // 形态②(§14.6 #1):不抛错而返回 partial(流已有内容时中断以 partial:true 透传)——
185
+ // 形态②(`ADVISOR-GUARDS.md §4` #1):不抛错而返回 partial(流已有内容时中断以 partial:true 透传)——
186
186
  // 不得按普通结果收尾:墙触发(复合信号已中止)同判。
187
187
  if (callSignal.aborted && response?.partial) {
188
188
  return renderTimeline(timeline, timeoutTail(timeoutMs, turns, toolCallCount, reviewTextProduced))
@@ -204,7 +204,7 @@ async function runAdvisorToolLoop(provider, messages, onOutput, signal, agent, c
204
204
  // Mirrors the main agent's push (agent.mjs).
205
205
  messages.push(assistantToolCallMessage(response, providerSpec(provider)))
206
206
 
207
- // B1 (AGENT-LOOP.md §18.7 D-TS7): the SAME LLM reply's multiple read-only
207
+ // B1: the SAME LLM reply's multiple read-only
208
208
  // tool calls run in PARALLEL (Promise.all) — results are backfilled in
209
209
  // toolCalls order (Promise.all preserves the input order → tool_call_id
210
210
  // never mismatches); each tool's timeout/error is captured independently
@@ -15,8 +15,8 @@ import { injectProjectGuide, injectDocumentMap, injectProjectStandards, NO_GIT_N
15
15
  export { findProjectRoot, injectProjectGuide } from "./project-context.mjs"
16
16
 
17
17
  /**
18
- * Build the mechanical review-object declaration block (AGENT-LOOP.md §18.8
19
- * D-OA2 — English anchored form). Injected at the START of the review user
18
+ * Build the mechanical review-object declaration block (AGENT-LOOP-ASYNC-POOL.md §6.18
19
+ * — English anchored form). Injected at the START of the review user
20
20
  * message every round: round 1 (design + code), the legacy convergence path,
21
21
  * and the round-2+ follow-up (see buildAdvisorFollowUp) — the reviewer must
22
22
  * not re-derive "who is being reviewed / why" from the documents (T-OA2:
@@ -39,7 +39,7 @@ export function buildObjectDeclarationBlock(object = null) {
39
39
  }
40
40
 
41
41
  /**
42
- * Approval-signal block for design reviews (round 1 and round 2+ — §11.2 D-24b:
42
+ * Approval-signal block for design reviews (round 1 and round 2+ — AGENT-LOOP-ASYNC-POOL.md §6.10 D-24b:
43
43
  * an async fix-round continuation must be able to re-approve, so the token is
44
44
  * injected into EVERY design round; the reviewer echoes it only on a clean pass).
45
45
  * §29.1 F2a (2026-09-07): BOTH values are injected — the token AND the designId
@@ -67,17 +67,17 @@ export function buildDesignApprovalBlock(designToken, designId) {
67
67
  * When set, the review input is built from this list ONLY — no git-diff change-set collection.
68
68
  * When absent, the legacy git-diff-based scope is kept (backward compatible).
69
69
  * @param {string[]|null} [paths] — code review only: explicit list of file/dir paths to review (deduped; shown under Review Scope)
70
- * @param {Object|null} [object] — review-object declaration (§18.8 D-OA1/D-OA3):
70
+ * @param {Object|null} [object] — review-object declaration (AGENT-LOOP-ASYNC-POOL.md §6.18 D-OA1/D-OA3):
71
71
  * { type, target, status, reason, exclude } — mechanically injected at the
72
72
  * start of the user message; absent → no injection (legacy calls unchanged).
73
- * @param {string|null} [designId] — §29.1 F2a: injected next to the token in the
73
+ * @param {string|null} [designId] — F2a: injected next to the token in the
74
74
  * Approval Signal (both values — the reviewer copies both verbatim); null →
75
75
  * token-only degradation (legacy direct callers).
76
76
  * @returns {string} the user message
77
77
  */
78
78
  export function buildAdvisorUserMessage(agent, prior, reviewType, designToken = null, documents = null, paths = null, object = null, designId = null) {
79
79
  const body = buildAdvisorUserMessageInner(agent, prior, reviewType, designToken, documents, paths, object, designId)
80
- // B 构建自愈(F12/§14.4 #1):design + token 且输出不含逐字信号 ⇒ 尾包补齐 Approval Signal。
80
+ // B 构建自愈(F12/`ADVISOR-GUARDS.md §2` #1):design + token 且输出不含逐字信号 ⇒ 尾包补齐 Approval Signal。
81
81
  // 覆盖所有出口(含 code 形态分支降级态与 legacy 收敛分支)——既有分支语义零改:已在分支内
82
82
  // 注入过的路径因 `[DESIGN-TOKEN:{token}` 逐字在场而不重复追加(幂等)。
83
83
  if (reviewType !== "design" || !designToken) return body
@@ -13,12 +13,12 @@
13
13
  * dimension it could no longer check (silent failure, the worst class: invisible
14
14
  * and unfixable by the user). Missing pieces now say so, and the reviewer is told
15
15
  * to state the limitation in its findings. Projects can point at their own files
16
- * through `.thincoder/conventions.json` (advisor.docMap / advisor.standardsDoc).
16
+ * through the project manifest (advisor.docMap / advisor.standardsDoc).
17
17
  */
18
18
  import { readFileSync, existsSync } from "node:fs"
19
19
  import { resolve, join, relative, dirname, sep } from "node:path"
20
20
  import { providerSpec } from "../config.mjs"
21
- import { loadConventions } from "../conventions.mjs"
21
+ import { loadProjectDeclaration } from "../conventions.mjs"
22
22
 
23
23
  /** Project guide (AGENTS.md) injection budget — decision 2026-08-08:
24
24
  * NO fixed truncation; long-context models (1M+) get up to 5% of their context
@@ -109,7 +109,7 @@ export function injectProjectGuide(agent, parts, scopeFiles = []) {
109
109
  // readFileSync succeeded — compute the budget OUTSIDE the try so a spec
110
110
  // lookup failure can never masquerade as "no AGENTS.md".
111
111
  // providerSpec: the project-guide budget follows the provider-level context
112
- // override (PROVIDER.md §15 — advisor messages budget is context-based).
112
+ // override (`ADVISOR-GUARDS.md §8` — advisor messages budget is context-based).
113
113
  // 字段名归一:解析后的 provider 挂点两端其一(`provider` 本体字段 / `_provider` 运载字段)
114
114
  // ——取在场者,两形态同语义(都指本回合生效的 provider 对象)。
115
115
  const resolvedProvider = agent.provider ?? agent._provider
@@ -136,7 +136,7 @@ export function injectProjectGuide(agent, parts, scopeFiles = []) {
136
136
  */
137
137
  export function injectDocumentMap(agent, parts, root) {
138
138
  const base = root ?? agent.cwd
139
- const conv = loadConventions(agent.cwd)
139
+ const conv = loadProjectDeclaration(agent.cwd)
140
140
  let mapPath = null
141
141
  if (conv.advisor.docMap) {
142
142
  const declared = resolve(base, conv.advisor.docMap)
@@ -174,7 +174,7 @@ export function injectDocumentMap(agent, parts, root) {
174
174
  */
175
175
  export function injectProjectStandards(agent, parts, root) {
176
176
  const base = root ?? agent.cwd
177
- const conv = loadConventions(agent.cwd)
177
+ const conv = loadProjectDeclaration(agent.cwd)
178
178
  const declared = conv.advisor.standardsDoc ? resolve(base, conv.advisor.standardsDoc) : null
179
179
  parts.push("## Project Standards")
180
180
  let text = null
package/advisor/repos.mjs CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { execFileSync } from "node:child_process"
6
6
  import { dirname, basename, resolve } from "node:path"
7
- import { loadConventions, isCodePath } from "../conventions.mjs"
7
+ import { loadProjectDeclaration, isCodePath } from "../conventions.mjs"
8
8
 
9
9
  const GIT_TIMEOUT = 5_000
10
10
  const MAX_EMBEDDED_DIFF = 50_000
@@ -118,7 +118,7 @@ export function collectChangedFiles(repos, cwd) {
118
118
  export function hasCodeMutations({ _touchedFiles, _mutatedThisRun, cwd }) {
119
119
  const files = _touchedFiles ?? []
120
120
  if (files.length === 0) return _mutatedThisRun
121
- const conv = loadConventions(cwd)
121
+ const conv = loadProjectDeclaration(cwd)
122
122
  return files.some((p) => isCodePath(p, conv))
123
123
  }
124
124
 
@@ -126,7 +126,7 @@ export function hasCodeMutations({ _touchedFiles, _mutatedThisRun, cwd }) {
126
126
  * Anything inside a code segment (incl. src/prompts/*.md) counts as product code —
127
127
  * the same authority the design gate uses. Paths here are repo-relative. */
128
128
  export function isDocOnlyChange(repos, cwd) {
129
- const conv = loadConventions(cwd)
129
+ const conv = loadProjectDeclaration(cwd)
130
130
  const targets = repos.length > 0 ? repos : [cwd]
131
131
  let sawChanges = false
132
132
  for (const repo of targets) {
package/advisor/run.mjs CHANGED
@@ -9,7 +9,7 @@ import { prepareAdvisorMessages } from "../advisor.mjs"
9
9
  import { buildObjectDeclarationBlock, buildDesignApprovalBlock } from "./messages.mjs"
10
10
  import { appendCitationReport } from "./citations.mjs"
11
11
  import { runAdvisorToolLoop } from "./loop.mjs"
12
- import { advisorIncompleteMarker, estimateTokens } from "./compaction.mjs"
12
+ import { estimateTokens } from "./compaction.mjs"
13
13
  import { batchDocForReview } from "../agent-tools/batch.mjs"
14
14
 
15
15
  // 拆分后 import 面(既有导出名逐一保面——re-export;谓词为本批新增)。
@@ -18,7 +18,7 @@ export { advisorToolsFor, advisorToolsFor as _advisorToolsFor } from "./loop.mjs
18
18
  export { runAdvisorToolLoop as _runAdvisorToolLoop } from "./loop.mjs"
19
19
  export { advisorIncompleteMarker } from "./compaction.mjs"
20
20
 
21
- /** B 启动拒绝前缀(§14.4 #2)——稳定契约单源(三消费点同串):run.mjs 生成;同步工具面
21
+ /** B 启动拒绝前缀(`ADVISOR-GUARDS.md §2` #2)——稳定契约单源(三消费点同串):run.mjs 生成;同步工具面
22
22
  * 据此登记 `_advisorRefusals`;异步结算面据此不置 `_calledAdvisorThisRun`。 */
23
23
  export const ADVISOR_LAUNCH_REFUSAL_PREFIX = "Advisor: design review launch refused"
24
24
 
@@ -36,7 +36,14 @@ export function resolveAdvisorProvider(agent) {
36
36
  // 单值);渠道无默认模型 → 父 provider 兜底(与 subagent F-2c 同构)——绝不产出静默
37
37
  // undefined-model 请求(最极端两者皆无 → chat 前 assertProviderModel fail-fast)。
38
38
  const result = cfg.model ? { ...provider, model: cfg.model } : { ...provider, model: provider.model ?? agent.provider?.model }
39
- if (cfg.thinking === null || cfg.thinking === false) result.thinking = undefined // explicitly off
39
+ // 台账 #329 / `MODEL-SPECS.md §15.4-3`:off 形须**活着到达载荷层**——载荷层 off 门首款 = `provider.thinking === null`
40
+ // (`thincoder-core/provider/core.mjs:213-219`);归一为 `undefined` 会让该门永不开(effort 族 advisor
41
+ // 关思考静默失效)。显式 off 同清**继承档**(渠条目自带 / 主 provider 的 `reasoningEffort` 不得随行——
42
+ // 随行则显式档支先命中、off 意图作废)。`false`(非法原值)仍归一 `undefined`(零变)。
43
+ if (cfg.thinking === null) {
44
+ result.thinking = null
45
+ delete result.reasoningEffort
46
+ } else if (cfg.thinking === false) result.thinking = undefined // invalid raw value — normalized
40
47
  else if (cfg.thinking !== undefined) result.thinking = cfg.thinking
41
48
  if (cfg.reasoningEffort !== undefined) result.reasoningEffort = cfg.reasoningEffort
42
49
  return result
@@ -47,9 +54,12 @@ export function resolveAdvisorProvider(agent) {
47
54
  }
48
55
  const provider = { ...agent.provider }
49
56
  if (cfg?.model) provider.model = cfg.model
50
- // thinking off: null AND false both mean "explicitly off" — a raw `false`
57
+ // thinking off: null = NF1 显式 off 标记(保形——同自定义渠道分支;`MODEL-SPECS.md §15.4-3`),a raw `false`
51
58
  // value is invalid for providers that expect undefined or an object.
52
- if (cfg?.thinking === null || cfg?.thinking === false) provider.thinking = undefined
59
+ if (cfg?.thinking === null) {
60
+ provider.thinking = null
61
+ delete provider.reasoningEffort // 继承档(主 provider)不得随显式 off 同行
62
+ } else if (cfg?.thinking === false) provider.thinking = undefined
53
63
  else if (cfg?.thinking !== undefined) provider.thinking = cfg.thinking
54
64
  if (cfg?.reasoningEffort !== undefined) provider.reasoningEffort = cfg.reasoningEffort
55
65
  return provider
@@ -62,9 +72,9 @@ export function looksLikeReviewOutput(text) {
62
72
  }
63
73
 
64
74
  /**
65
- * 压缩定锚简报(F13/§14.4 #3)——**由评审参数构建**(非模型输出):对象声明 / 文档清单 /
75
+ * 压缩定锚简报(F13/`ADVISOR-GUARDS.md §2` #3)——**由评审参数构建**(非模型输出):对象声明 / 文档清单 /
66
76
  * Approval Signal 三锚;重内容(项目指南 / 方法论 / 文档地图)不入 pin(压缩的意义所在)。
67
- * 形态逐字见设计 §14.4 #3(首行为机械化重挂说明)。
77
+ * 形态逐字见 `ADVISOR-GUARDS.md §2` #3(首行为机械化重挂说明)。
68
78
  */
69
79
  function buildPinnedBrief(reviewType, documents, object, designToken, designId) {
70
80
  const docList = Array.isArray(documents) ? documents.filter((d) => typeof d === "string" && d.trim()) : []
@@ -84,8 +94,8 @@ function buildPinnedBrief(reviewType, documents, object, designToken, designId)
84
94
  * @param {string|null} [designToken] — injected into the design-review prompt; the advisor echoes it only on approval.
85
95
  * @param {string[]|null} [documents] — design review only: explicit list of doc paths to review; passed through to the message builder.
86
96
  * @param {string[]|null} [paths] — code review only: explicit list of file/dir paths to review.
87
- * @param {Object|null} [object] — review-object declaration (§18.8 D-OA1/D-OA3): { type, target, status, reason, exclude }; absent → legacy behavior (no injection).
88
- * @param {string|null} [designId] — §29.1 F2a: injected next to the design token in
97
+ * @param {Object|null} [object] — review-object declaration (AGENT-LOOP-ASYNC-POOL.md §6.18 D-OA1/D-OA3): { type, target, status, reason, exclude }; absent → legacy behavior (no injection).
98
+ * @param {string|null} [designId] — F2a: injected next to the design token in
89
99
  * the Approval Signal (passed through to the message builders).
90
100
  */
91
101
  export async function runAdvisorReview(agent, reviewType, callbacks, designToken = null, documents = null, paths = null, object = null, designId = null) {
@@ -106,7 +116,7 @@ export async function runAdvisorReview(agent, reviewType, callbacks, designToken
106
116
 
107
117
  const messages = prepareAdvisorMessages(agent, reviewType, designToken, documents, paths, null, object, designId)
108
118
 
109
- // B 启动断言(fail-closed——§14.4 #2):设计评审请求内**必须**携带与本次签发 token 精确
119
+ // B 启动断言(fail-closed——`ADVISOR-GUARDS.md §2` #2):设计评审请求内**必须**携带与本次签发 token 精确
110
120
  // 对应的 Approval Signal——构建面补不上就拒绝启动(不发"请回显一个不存在的 token"的请求)。
111
121
  // 拒绝报告前缀 `Advisor: design review launch refused` = 稳定契约(同步工具面据此登记
112
122
  // _advisorRefusals;异步结算面据此不置 _calledAdvisorThisRun)。工具路径恒签发 token ⇒
@@ -126,7 +136,7 @@ export async function runAdvisorReview(agent, reviewType, callbacks, designToken
126
136
  // callbacks.batchDoc(即 resolved.run 的实例绑定);异步路径 = 本实例在跑池条目的
127
137
  // run.batchDoc(同文档集实例键——各评审各取各档,不用单值会话态)。
128
138
  const boundBatchDoc = reviewType === "design" ? batchDocForReview(agent, documents, callbacks) : null
129
- // F13/§14.4 #3:压缩定锚简报(评审参数构建——压缩触发时由 compaction 重挂)。
139
+ // F13/`ADVISOR-GUARDS.md §2` #3:压缩定锚简报(评审参数构建——压缩触发时由 compaction 重挂)。
130
140
  const pinned = buildPinnedBrief(reviewType, documents, object, designToken, designId)
131
141
 
132
142
  try {
@@ -138,7 +148,7 @@ export async function runAdvisorReview(agent, reviewType, callbacks, designToken
138
148
  // the prior table instead of re-reading (three consecutive false reports
139
149
  // cited pre-fix line content). Unverified citations must not support a
140
150
  // push-back; the parent agent sees the verification report.
141
- // F14/§14.5:解析候选 = cwd + 评审对象声明范围派生根(scope = documents + paths)。
151
+ // F14/`ADVISOR-GUARDS.md §3`:解析候选 = cwd + 评审对象声明范围派生根(scope = documents + paths)。
142
152
  let final = result
143
153
  if (!result.trimStart().startsWith("Advisor:")) {
144
154
  final = appendCitationReport(result, advisorCwd, { scope: [...(documents ?? []), ...(paths ?? [])] })