@thincoder/core 0.9.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 (203) hide show
  1. package/abort-provenance.mjs +116 -0
  2. package/advisor/citations.mjs +139 -0
  3. package/advisor/compaction.mjs +174 -0
  4. package/advisor/convergence.mjs +80 -0
  5. package/advisor/history.mjs +77 -0
  6. package/advisor/loop.mjs +288 -0
  7. package/advisor/messages.mjs +299 -0
  8. package/advisor/notice.mjs +141 -0
  9. package/advisor/project-context.mjs +197 -0
  10. package/advisor/repos.mjs +150 -0
  11. package/advisor/run.mjs +190 -0
  12. package/advisor/truncate.mjs +57 -0
  13. package/advisor.mjs +281 -0
  14. package/agent/child-marks.mjs +24 -0
  15. package/agent/completion.mjs +145 -0
  16. package/agent/dispatch.mjs +493 -0
  17. package/agent/family-tools.mjs +174 -0
  18. package/agent/helpers.mjs +412 -0
  19. package/agent/post-turn.mjs +70 -0
  20. package/agent/record-results.mjs +174 -0
  21. package/agent/relay-prefix.mjs +39 -0
  22. package/agent/run-stages.mjs +244 -0
  23. package/agent/setup-reminders.mjs +199 -0
  24. package/agent/setup.mjs +234 -0
  25. package/agent/spawn-child.mjs +258 -0
  26. package/agent/suspension.mjs +240 -0
  27. package/agent/write-gate.mjs +87 -0
  28. package/agent-tools/advisor-async.mjs +481 -0
  29. package/agent-tools/advisor-settle.mjs +240 -0
  30. package/agent-tools/advisor.mjs +280 -0
  31. package/agent-tools/async-discard.mjs +143 -0
  32. package/agent-tools/async-settle.mjs +299 -0
  33. package/agent-tools/batch-segment.mjs +265 -0
  34. package/agent-tools/child-permission.mjs +45 -0
  35. package/agent-tools/consult.mjs +471 -0
  36. package/agent-tools/design-token.mjs +117 -0
  37. package/agent-tools/digest-budget.mjs +76 -0
  38. package/agent-tools/eng.mjs +102 -0
  39. package/agent-tools/escalate-async.mjs +302 -0
  40. package/agent-tools/goal.mjs +119 -0
  41. package/agent-tools/panel-blocks.mjs +24 -0
  42. package/agent-tools/parent-channel.mjs +231 -0
  43. package/agent-tools/plan.mjs +86 -0
  44. package/agent-tools/read-history.mjs +309 -0
  45. package/agent-tools/recent-changes.mjs +24 -0
  46. package/agent-tools/review-facts.mjs +31 -0
  47. package/agent-tools/settings.mjs +268 -0
  48. package/agent-tools/skill.mjs +63 -0
  49. package/agent-tools/spawn-gates.mjs +109 -0
  50. package/agent-tools/subagent-actions.mjs +496 -0
  51. package/agent-tools/subagent-async.mjs +456 -0
  52. package/agent-tools/subagent-panel.mjs +160 -0
  53. package/agent-tools/subagent-run.mjs +208 -0
  54. package/agent-tools/subagent-scheduler.mjs +446 -0
  55. package/agent-tools/subagent-spawn.mjs +478 -0
  56. package/agent-tools/subagent.mjs +419 -0
  57. package/agent-tools/task.mjs +87 -0
  58. package/agent-tools/timer.mjs +46 -0
  59. package/agent-tools/verify.mjs +295 -0
  60. package/agent-tools.mjs +23 -0
  61. package/agent.mjs +430 -0
  62. package/auto-think.mjs +115 -0
  63. package/compress-form.mjs +24 -0
  64. package/config-io.mjs +277 -0
  65. package/config-migrate.mjs +178 -0
  66. package/config-presets.mjs +49 -0
  67. package/config.mjs +419 -0
  68. package/context.mjs +495 -0
  69. package/conventions.mjs +223 -0
  70. package/embedding.mjs +120 -0
  71. package/escape.mjs +152 -0
  72. package/expand-home.mjs +16 -0
  73. package/explore-distill.mjs +152 -0
  74. package/generate-title.mjs +123 -0
  75. package/git/checkpoint.mjs +448 -0
  76. package/git/gitmem.mjs +100 -0
  77. package/history-window.mjs +179 -0
  78. package/hooks.mjs +108 -0
  79. package/i18n.mjs +106 -0
  80. package/index-bin.mjs +48 -0
  81. package/index-discover.mjs +176 -0
  82. package/ledger-cmd.mjs +209 -0
  83. package/ledger-db.mjs +86 -0
  84. package/ledger-surface.mjs +76 -0
  85. package/ledger.mjs +202 -0
  86. package/log.mjs +195 -0
  87. package/manifest.mjs +338 -0
  88. package/markdown.mjs +106 -0
  89. package/mcp/helpers.mjs +51 -0
  90. package/mcp/transport-http.mjs +248 -0
  91. package/mcp/transport-stdio.mjs +140 -0
  92. package/mcp/transport-ws.mjs +122 -0
  93. package/mcp.mjs +295 -0
  94. package/memory/code-index.mjs +219 -0
  95. package/memory/code-sync.mjs +427 -0
  96. package/memory/core.mjs +318 -0
  97. package/memory/delete.mjs +242 -0
  98. package/memory/docs.mjs +431 -0
  99. package/memory/file-walk.mjs +109 -0
  100. package/memory/origin.mjs +24 -0
  101. package/memory/scan.mjs +177 -0
  102. package/memory/schema.mjs +460 -0
  103. package/memory.mjs +21 -0
  104. package/model-ref.mjs +66 -0
  105. package/model-specs.mjs +277 -0
  106. package/package.json +32 -0
  107. package/peer-domains.mjs +265 -0
  108. package/peer-instances.mjs +178 -0
  109. package/permission.mjs +79 -0
  110. package/process-probe.mjs +315 -0
  111. package/prompt-files.mjs +113 -0
  112. package/prompt-overlays.mjs +78 -0
  113. package/prompts/advisor-design.md +43 -0
  114. package/prompts/advisor-round1.md +41 -0
  115. package/prompts/advisor-round2.md +46 -0
  116. package/prompts/advisor-round3.md +42 -0
  117. package/prompts/common.md +158 -0
  118. package/prompts/consult-base.md +19 -0
  119. package/prompts/discipline-engineering.md +123 -0
  120. package/prompts/discipline-normal.md +206 -0
  121. package/prompts/persona-coder.md +21 -0
  122. package/prompts/persona-eng-coder.md +41 -0
  123. package/prompts/persona-eng-designer.md +80 -0
  124. package/prompts/persona-engineering.md +160 -0
  125. package/prompts/persona-explore.md +15 -0
  126. package/prompts/persona-normal.md +35 -0
  127. package/prompts/persona-plan.md +27 -0
  128. package/provider/anthropic.mjs +225 -0
  129. package/provider/core.mjs +491 -0
  130. package/provider/errors.mjs +101 -0
  131. package/provider/google.mjs +257 -0
  132. package/provider/index.mjs +7 -0
  133. package/provider/list-models.mjs +163 -0
  134. package/provider/normalize.mjs +81 -0
  135. package/provider/rate.mjs +168 -0
  136. package/provider/responses.mjs +495 -0
  137. package/provider/retry.mjs +88 -0
  138. package/provider/sse.mjs +264 -0
  139. package/provider/wait-status.mjs +59 -0
  140. package/proxy.mjs +274 -0
  141. package/rules.mjs +53 -0
  142. package/session-gc.mjs +248 -0
  143. package/session-guard.mjs +59 -0
  144. package/session-lifecycle.mjs +305 -0
  145. package/session-migrate.mjs +48 -0
  146. package/session-rename.mjs +38 -0
  147. package/session-segments.mjs +99 -0
  148. package/session-slot-write.mjs +168 -0
  149. package/session-slots-manifest.mjs +264 -0
  150. package/session-slots.mjs +298 -0
  151. package/session-store.mjs +441 -0
  152. package/session.mjs +244 -0
  153. package/skills.mjs +234 -0
  154. package/text-budget.mjs +79 -0
  155. package/token-ttl.mjs +285 -0
  156. package/tool-docs/apply_patch.md +15 -0
  157. package/tool-docs/bash.md +38 -0
  158. package/tool-docs/delete.md +13 -0
  159. package/tool-docs/edit.md +30 -0
  160. package/tool-docs/execute.md +21 -0
  161. package/tool-docs/fetch.md +12 -0
  162. package/tool-docs/file_ops.md +17 -0
  163. package/tool-docs/get_current_time.md +8 -0
  164. package/tool-docs/git.md +54 -0
  165. package/tool-docs/glob.md +11 -0
  166. package/tool-docs/grep.md +19 -0
  167. package/tool-docs/hashline_edit.md +14 -0
  168. package/tool-docs/insert_after.md +15 -0
  169. package/tool-docs/lint.md +10 -0
  170. package/tool-docs/ls.md +12 -0
  171. package/tool-docs/lsp.md +10 -0
  172. package/tool-docs/process.md +10 -0
  173. package/tool-docs/question.md +16 -0
  174. package/tool-docs/read.md +20 -0
  175. package/tool-docs/read_image.md +8 -0
  176. package/tool-docs/tree.md +14 -0
  177. package/tool-docs/wait_for.md +22 -0
  178. package/tool-docs/websearch.md +16 -0
  179. package/tool-docs/write.md +11 -0
  180. package/tools/bash.mjs +276 -0
  181. package/tools/edit-batch.mjs +204 -0
  182. package/tools/edit-diff.mjs +388 -0
  183. package/tools/exec-run.mjs +43 -0
  184. package/tools/execute.mjs +243 -0
  185. package/tools/file.mjs +464 -0
  186. package/tools/git-checkpoint.mjs +143 -0
  187. package/tools/git-ext.mjs +173 -0
  188. package/tools/git.mjs +415 -0
  189. package/tools/glob-dialect.mjs +130 -0
  190. package/tools/index.mjs +76 -0
  191. package/tools/linter.mjs +120 -0
  192. package/tools/lsp.mjs +335 -0
  193. package/tools/ops.mjs +293 -0
  194. package/tools/patch.mjs +290 -0
  195. package/tools/question.mjs +26 -0
  196. package/tools/repomap.mjs +314 -0
  197. package/tools/search.mjs +248 -0
  198. package/tools/shared.mjs +467 -0
  199. package/tools/tree.mjs +81 -0
  200. package/tools/web.mjs +224 -0
  201. package/tools/write-path.mjs +191 -0
  202. package/traces/trace-store.mjs +303 -0
  203. package/undo-stack.mjs +47 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * verify.mjs — verify tool: generic pre-completion verification gate (VERIFY-REDESIGN.md).
3
+ * Verify is language/framework/project agnostic: it does NOT hardcode any project's
4
+ * module→test mapping, does NOT auto-run any test/verification command, and does NOT
5
+ * require a test for every change. The model DECLARES its verification status via the
6
+ * `verification` argument (whether it already ran the project's verification and the
7
+ * result); verify makes a mechanical gate decision on that declaration. Which
8
+ * verification to run is described in natural language in each project's AGENTS.md —
9
+ * verify never parses or executes it. Retained mechanical checks: doc-only fast path,
10
+ * an advisory (non-gating) node --check hint, git diff report, and — on the code
11
+ * path (doc-only changes return early) — the task list and self-review checklist.
12
+ */
13
+
14
+ import { isCodePath, isDocPath, loadConventions } from "../conventions.mjs"
15
+ // #96(信息段与执行方式按端注入——CORE-UNIFICATION §2.13.4):git / node --check 执行
16
+ // 全部经核内执行面单点(默认径 = execFileSync 等价——CLI 语义零行为变;端侧 injected ⇒
17
+ // 可中断执行器);编辑器诊断段经 `configureVerifyDiagnostics` 注入(缺省不注入)。
18
+ import { runCommand } from "../tools/exec-run.mjs"
19
+ import { existsSync } from "node:fs"
20
+ import { resolve } from "node:path"
21
+
22
+ // ─── 信息段注入缝(#96——「信息段与执行方式按端注入」的信息段面)──────────────────────
23
+ /**
24
+ * 报告附加段注入位(**缺省不覆盖** = 不注入——CLI 报告逐字不变,零行为变;端装配层可覆盖
25
+ * 为本端信息段(如编辑器诊断)。核内零端名分支(契约 5——本档只认 `section` 函数名)。
26
+ * 契约:`section(ctx, codeFiles) → string | string[] | null | Promise<同>`——非空字符串 /
27
+ * 非空数组 = 追加到报告(advisory——不进门禁);null / 空 ⇒ 跳过。
28
+ */
29
+ let injectedDiagnostics = null
30
+ export function configureVerifyDiagnostics(impl) {
31
+ injectedDiagnostics = impl && typeof impl.section === "function" ? impl.section : null
32
+ }
33
+ /** 撤销注入(测试与端装配生命周期用——缺省态 = 不注入)。 */
34
+ export function resetVerifyDiagnostics() { injectedDiagnostics = null }
35
+
36
+ /**
37
+ * §18.12 D-VR1 path normalization — mirrors the §20.5 file-domain handling:
38
+ * resolved to an absolute path with forward slashes; dedup uses the win32
39
+ * lowercase comparison key (changedFileKey) so "D:/x/src/a.mjs" and
40
+ * "d:\\x\SRC\a.mjs" count as the same file.
41
+ */
42
+ function normalizeChangedPath(p, base) {
43
+ return resolve(base, p).replace(/\\/g, "/")
44
+ }
45
+
46
+ /** Win32 comparison key: case-insensitive drives/folders (same file). */
47
+ function changedFileKey(p) {
48
+ return process.platform === "win32" ? p.toLowerCase() : p
49
+ }
50
+
51
+ /**
52
+ * D-V3 block guidance — a block message must not just say "not verified": it lists
53
+ * the changed code files and points to the project's AGENTS.md natural-language
54
+ * description of how to verify, so the model knows what to run/add.
55
+ */
56
+ function appendBlockGuidance(lines, codeFiles) {
57
+ lines.push("")
58
+ lines.push("Changed code file(s):")
59
+ for (const f of codeFiles) lines.push(` ${f}`)
60
+ lines.push("")
61
+ lines.push("verify does not run commands for you — decide and run the project's verification yourself.")
62
+ lines.push("Reference the verification approach declared in the project's AGENTS.md (natural language, e.g. \"tests run with npm test\" / \"no automated tests — rely on manual review\") to decide what to run, then call verify again declaring the outcome via verification.status.")
63
+ }
64
+
65
+ /**
66
+ * verify tool: generic pre-completion verification gate. Flow:
67
+ * 0. Doc-only fast path — all changed files are docs: short report, no verification needed.
68
+ * 1. git diff --stat — changed file list (_touchedFiles ∪ git diff)
69
+ * 2. Advisory syntax hint (D-V5) — node --check changed .js/.mjs when node exists; SOFT, not gating.
70
+ * 3. Verification gate (D-V1/D-V2) — requires the model to DECLARE verification.status:
71
+ * passed → allowed; failed → blocked; skipped → allowed but needs a summary reason.
72
+ * 4. Task list + self-review checklist.
73
+ * Agent must not say "done" before verify passes.
74
+ */
75
+ export const verifyTool = {
76
+ name: "verify",
77
+ description:
78
+ "Generic pre-completion verification gate — language/framework/project agnostic. verify does NOT run any test/verification command for you and does NOT require a test per change. You DECLARE your verification status via the verification argument: { status: 'passed' | 'failed' | 'skipped', command?, summary? }. 'passed' → allowed; 'failed' → blocked (cannot claim done); 'skipped' → allowed but requires a summary reason. Whether/how to verify is described in natural language in the project's AGENTS.md and is decided + executed by you — verify only mechanically gates on your declaration. Also reports changed files (git diff), an advisory node --check hint on changed .js/.mjs (not gating), the task list, and a self-review checklist. Call this BEFORE declaring a coding task complete — do not say 'done' until verify passes.",
79
+ parameters: {
80
+ type: "object",
81
+ properties: {
82
+ verification: {
83
+ type: "object",
84
+ description: "The model's declaration of whether it already ran the project's verification and its outcome. verify does not execute the command — it is self-reported evidence.",
85
+ properties: {
86
+ status: { type: "string", enum: ["passed", "failed", "skipped"], description: "The verification outcome you declare: 'passed' → allowed; 'failed' → blocked; 'skipped' → allowed but requires a summary reason." },
87
+ command: { type: "string", description: "Optional: the verification command you ran (self-reported — verify does not execute it)." },
88
+ summary: { type: "string", description: "Optional: summary/result of the verification. Required when status='skipped' — a concrete reason (e.g. \"project has no automated tests — verified by manual review\")." },
89
+ },
90
+ required: ["status"],
91
+ },
92
+ workdir: { type: "string", description: "Optional: run verify in this subdirectory (relative to cwd or absolute) — for monorepos" },
93
+ },
94
+ },
95
+ readonly: true,
96
+ async execute(args, ctx) {
97
+ const cwd = ctx.agent.cwd
98
+ // Changed-file resolution (§18.12 D-VR3): _touchedFiles (per-run bookkeeping,
99
+ // absolute paths) ∪ git diff fallback — git is tried at testCwd
100
+ // (workdir-resolved) first, then at ctx.agent.cwd; first success wins.
101
+ // git-diff paths are repo-root-relative — resolved against the discovered
102
+ // git root, then normalized (absolute, forward slashes, win32 key).
103
+ const testCwd = args.workdir ? resolve(cwd, args.workdir) : cwd
104
+ const lines = []
105
+ lines.push("=== VERIFICATION REPORT ===")
106
+ lines.push("")
107
+
108
+ // 1. Changed files — _touchedFiles ∪ git diff (§18.12 D-VR1)
109
+ let gitOk = false
110
+ let gitStat = ""
111
+ let gitFiles = []
112
+ for (const gitCwd of new Set([testCwd, cwd])) {
113
+ try {
114
+ // Anchor the repo root FIRST (also proves git works here) — diff paths
115
+ // are repo-root-relative, so both diff calls run at the root.
116
+ const gitRoot = (await runCommand("git", ["rev-parse", "--show-toplevel"], { cwd: gitCwd, timeout: 5000, signal: ctx.signal })).trim() || gitCwd
117
+ const diff = await runCommand("git", ["diff", "--stat"], { cwd: gitRoot, timeout: 5000, signal: ctx.signal })
118
+ const nameOnly = await runCommand("git", ["diff", "--name-only"], { cwd: gitRoot, timeout: 5000, signal: ctx.signal })
119
+ gitOk = true
120
+ gitStat = diff.trim()
121
+ gitFiles = nameOnly.trim().split("\n").filter(Boolean).map((p) => normalizeChangedPath(p, gitRoot))
122
+ break
123
+ } catch { /* git unavailable here — try the next cwd in the chain */ }
124
+ }
125
+ if (gitOk && gitStat) {
126
+ lines.push("Changed files (git diff --stat):")
127
+ lines.push(gitStat)
128
+ } else if (gitOk) {
129
+ lines.push("Changed files: (none — no uncommitted changes)")
130
+ } else {
131
+ lines.push("Changed files: (not a git repo or git unavailable)")
132
+ }
133
+ // _touchedFiles: files written by the tools this run — captured regardless
134
+ // of git state (§18.12 F-VR1: subagent cwd ≠ git root must still locate).
135
+ const touchedFiles = (ctx.agent._touchedFiles ?? []).map((p) => normalizeChangedPath(p, cwd))
136
+ const gitKeys = new Set(gitFiles.map(changedFileKey))
137
+ const touchedOnly = touchedFiles.filter((p) => !gitKeys.has(changedFileKey(p)))
138
+ if (touchedOnly.length > 0) {
139
+ lines.push("")
140
+ lines.push("Changed files (this run — _touchedFiles):")
141
+ for (const f of touchedOnly) lines.push(` ${f}`)
142
+ }
143
+ // Union, deduped by comparison key (win32 case-insensitive).
144
+ const changedKeys = new Set()
145
+ const changedFiles = [...touchedFiles, ...gitFiles].filter((p) => {
146
+ const k = changedFileKey(p)
147
+ if (changedKeys.has(k)) return false
148
+ changedKeys.add(k)
149
+ return true
150
+ })
151
+
152
+ // D-V11 G10 (doc-only/empty change set must not swallow an explicit failed):
153
+ // an explicit verification.status='failed' is ALWAYS respected — never
154
+ // overridden to pass by the doc-only fast path or the no-code-changed path
155
+ // below (D-V5 exception, review #6). Aligns CLI with VS Code (T-V8). Lists
156
+ // the changed files + points at AGENTS.md (D-V3 guidance).
157
+ if (args.verification?.status === "failed") {
158
+ lines.push("")
159
+ lines.push("VERIFY BLOCKED: you declared verification failed (verification.status = 'failed').")
160
+ lines.push("Do not say 'done' while verification fails — fix the issue, re-run the project's verification, then call verify again declaring the outcome.")
161
+ lines.push("")
162
+ lines.push("Changed file(s):")
163
+ for (const f of changedFiles) lines.push(` ${f}`)
164
+ lines.push("")
165
+ lines.push("verify does not run commands for you — decide and run the project's verification yourself.")
166
+ lines.push("Reference the verification approach declared in the project's AGENTS.md (natural language, e.g. \"tests run with npm test\" / \"no automated tests — rely on manual review\") to decide what to run, then call verify again declaring the outcome via verification.status.")
167
+ ctx.agent._verifyPassed = false
168
+ return lines.join("\n")
169
+ }
170
+
171
+ // 1b. Doc-only fast path: every changed file is documentation (docs/, *.md,
172
+ // LICENSE…) — syntax checks and a verification declaration are meaningless
173
+ // for doc changes, and the task list/self-review checklist add nothing either.
174
+ // Paths inside a declared code segment (default: src — incl. prompts/*.md) are
175
+ // product code — excluded from the fast path, consistent with the design gate.
176
+ // The project's own layout is declarable (.thincoder/conventions.json).
177
+ // Empty list (no changes / git unavailable)
178
+ // intentionally falls through to the normal path below.
179
+ const conv = loadConventions(cwd)
180
+ if (changedFiles.length > 0 && changedFiles.every((f) => isDocPath(f, conv))) {
181
+ lines.push("")
182
+ lines.push("Documentation-only changes — skipping syntax checks and tests.")
183
+ ctx.agent._verifyPassed = true
184
+ return lines.join("\n")
185
+ }
186
+
187
+ // Code files needing verification: anything the shared classifier calls product
188
+ // code (D-V1 — these require a verification declaration). Temp scratch files are
189
+ // neither code nor docs and fall out of this list (a throwaway diagnostic script
190
+ // is not a code change — no declaration is demanded for it).
191
+ const codeFiles = changedFiles.filter((f) => isCodePath(f, conv))
192
+
193
+ // 2. Advisory syntax hint (D-V5) — node --check on changed .js/.mjs when node
194
+ // exists. SOFT hint only — it does NOT gate done (no language-specific
195
+ // enforcement; a non-JS project or a missing node simply skips silently).
196
+ const jsFiles = codeFiles.filter((f) => /\.(m?js)$/i.test(f) && existsSync(f))
197
+ if (jsFiles.length > 0) {
198
+ lines.push("")
199
+ lines.push("Advisory syntax hint (node --check — does not gate):")
200
+ for (const f of jsFiles) {
201
+ try {
202
+ await runCommand("node", ["--check", f], { timeout: 10000, signal: ctx.signal })
203
+ lines.push(` ✓ ${f}`)
204
+ } catch (e) {
205
+ const errOutput = (e.stderr || e.stdout || e.message || "").toString()
206
+ const errMsg = errOutput.split("\n").slice(0, 3).join("\n")
207
+ lines.push(` ⚠ ${f} — node --check flagged it`)
208
+ lines.push(` ${errMsg.replace(/\n/g, "\n ")}`)
209
+ }
210
+ }
211
+ }
212
+
213
+ // 2b. 端注入报告段(#96 信息段面):缺省不注入 ⇒ 报告零变化;注入 ⇒ 追加(advisory——
214
+ // 不进门禁)。位置 = 语法提示之后、门禁段之前(与语法提示同属建议信息面)。
215
+ if (injectedDiagnostics) {
216
+ const extra = await injectedDiagnostics(ctx, codeFiles)
217
+ if (Array.isArray(extra)) { if (extra.length) lines.push(...extra.map(String)) }
218
+ else if (typeof extra === "string" && extra) lines.push(extra)
219
+ }
220
+
221
+ // 3. Verification gate (D-V1/D-V2): the model declares its verification status.
222
+ if (codeFiles.length === 0) {
223
+ // No code changed (empty change set / only temp/non-code files) — nothing to verify.
224
+ lines.push("")
225
+ lines.push("No code files changed — nothing to verify.")
226
+ ctx.agent._verifyPassed = true
227
+ } else {
228
+ const v = args.verification ?? {}
229
+ const status = v?.status
230
+ if (!status) {
231
+ lines.push("")
232
+ lines.push("VERIFY BLOCKED: no verification status was declared.")
233
+ lines.push("These code changes must be verified before you say 'done' — declare whether you ran the project's verification and its result.")
234
+ appendBlockGuidance(lines, codeFiles)
235
+ ctx.agent._verifyPassed = false
236
+ } else if (status === "passed") {
237
+ lines.push("")
238
+ lines.push("Verification declared passed.")
239
+ if (v.command) lines.push(` command: ${v.command}`)
240
+ if (v.summary) lines.push(` summary: ${v.summary}`)
241
+ ctx.agent._verifyPassed = true
242
+ } else if (status === "skipped") {
243
+ const reason = (v.summary ?? "").trim()
244
+ if (reason) {
245
+ lines.push("")
246
+ lines.push(`Verification skipped with reason: ${reason}`)
247
+ ctx.agent._verifyPassed = true
248
+ } else {
249
+ lines.push("")
250
+ lines.push("VERIFY BLOCKED: verification skipped with no summary reason — an empty skip is not allowed.")
251
+ lines.push("Give a concrete reason in verification.summary (e.g. \"project has no automated tests — verified by manual review\"), or run the project's verification and declare its result.")
252
+ appendBlockGuidance(lines, codeFiles)
253
+ ctx.agent._verifyPassed = false
254
+ }
255
+ } else {
256
+ // Unknown status value — defensive (schema enum normally rejects it first).
257
+ lines.push("")
258
+ lines.push(`VERIFY BLOCKED: unknown verification.status ${JSON.stringify(status)} — use 'passed' | 'failed' | 'skipped'.`)
259
+ appendBlockGuidance(lines, codeFiles)
260
+ ctx.agent._verifyPassed = false
261
+ }
262
+ }
263
+
264
+ // 4. Task list
265
+ lines.push("")
266
+ if (ctx.agent.tasks.length === 0) {
267
+ lines.push("Task list: (no tasks tracked)")
268
+ } else {
269
+ const done = ctx.agent.tasks.filter((t) => t.status === "done").length
270
+ const total = ctx.agent.tasks.length
271
+ const open = ctx.agent.tasks.filter((t) => t.status !== "done")
272
+ lines.push(`Task list: ${done}/${total} done`)
273
+ for (const t of ctx.agent.tasks) {
274
+ const mark = t.status === "done" ? "✓" : t.status === "in_progress" ? "▶" : "○"
275
+ lines.push(` ${mark} [${t.status}] ${t.title}`)
276
+ }
277
+ if (open.length > 0) {
278
+ lines.push("")
279
+ lines.push(`WARNING: ${open.length} task(s) still open. Complete them or explain why they can be left undone.`)
280
+ }
281
+ }
282
+
283
+ // 5. Checklist
284
+ lines.push("")
285
+ lines.push("Self-review checklist:")
286
+ lines.push("- [ ] Did I run the project's verification (per its AGENTS.md) and does it pass, or did I declare a concrete skip reason?")
287
+ lines.push("- [ ] Did I read every file I changed to catch leftover debug code or stale comments?")
288
+ lines.push("- [ ] Do comments and docstrings match what the code actually does?")
289
+ lines.push("- [ ] Did I remove placeholder code, TODO stubs, or commented-out experiment blocks?")
290
+ lines.push("- [ ] If I used a subagent, did I verify its report against the actual files it touched?")
291
+ lines.push("- [ ] Are all task items genuinely done (not just marked done to finish early)?")
292
+
293
+ return lines.join("\n")
294
+ },
295
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * agent-tools.mjs — self-discipline tool index
3
+ * Loaded from agent.mjs via dynamic import to avoid ESM circular dependencies.
4
+ * Each tool implementation lives in the agent-tools/ subdirectory.
5
+ */
6
+ export { planTool } from "./agent-tools/plan.mjs"
7
+ export { subagentTool } from "./agent-tools/subagent.mjs"
8
+ export { taskTool } from "./agent-tools/task.mjs"
9
+ export { skillTool } from "./agent-tools/skill.mjs"
10
+ export { goalTool } from "./agent-tools/goal.mjs"
11
+ export { verifyTool } from "./agent-tools/verify.mjs"
12
+ export { recentChangesTool } from "./agent-tools/recent-changes.mjs"
13
+ export { timerTool } from "./agent-tools/timer.mjs"
14
+ export { advisorTool } from "./agent-tools/advisor.mjs"
15
+ export { engTool } from "./agent-tools/eng.mjs"
16
+ export { readHistoryTool } from "./agent-tools/read-history.mjs"
17
+ export { batchSegmentTool } from "./agent-tools/batch-segment.mjs"
18
+ // CORE-UNIFICATION TOOLS #83(统一登记册——VSC `agent-tools/index.mjs:15` 含 consult 家族;
19
+ // CLI 原把 consult 另挂 `agent/setup.mjs:173` ⇒ 归位:登记册即单一来源,装配方只读本档)。
20
+ export { consultStartTool, consultStopTool } from "./agent-tools/consult.mjs"
21
+ // SUBAGENT-UPSTREAM-CHANNEL(AGENT-LOOP-SUBAGENT.md §6.27.4 装配接线):子代理上行通道工具
22
+ // (depth>0 段装配——`agent/family-tools.mjs`;depth-0 / consult 不装配)。
23
+ export { parentChannelTool } from "./agent-tools/parent-channel.mjs"