@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.
- package/abort-provenance.mjs +116 -0
- package/advisor/citations.mjs +139 -0
- package/advisor/compaction.mjs +174 -0
- package/advisor/convergence.mjs +80 -0
- package/advisor/history.mjs +77 -0
- package/advisor/loop.mjs +288 -0
- package/advisor/messages.mjs +299 -0
- package/advisor/notice.mjs +141 -0
- package/advisor/project-context.mjs +197 -0
- package/advisor/repos.mjs +150 -0
- package/advisor/run.mjs +190 -0
- package/advisor/truncate.mjs +57 -0
- package/advisor.mjs +281 -0
- package/agent/child-marks.mjs +24 -0
- package/agent/completion.mjs +145 -0
- package/agent/dispatch.mjs +493 -0
- package/agent/family-tools.mjs +174 -0
- package/agent/helpers.mjs +412 -0
- package/agent/post-turn.mjs +70 -0
- package/agent/record-results.mjs +174 -0
- package/agent/relay-prefix.mjs +39 -0
- package/agent/run-stages.mjs +244 -0
- package/agent/setup-reminders.mjs +199 -0
- package/agent/setup.mjs +234 -0
- package/agent/spawn-child.mjs +258 -0
- package/agent/suspension.mjs +240 -0
- package/agent/write-gate.mjs +87 -0
- package/agent-tools/advisor-async.mjs +481 -0
- package/agent-tools/advisor-settle.mjs +240 -0
- package/agent-tools/advisor.mjs +280 -0
- package/agent-tools/async-discard.mjs +143 -0
- package/agent-tools/async-settle.mjs +299 -0
- package/agent-tools/batch-segment.mjs +265 -0
- package/agent-tools/child-permission.mjs +45 -0
- package/agent-tools/consult.mjs +471 -0
- package/agent-tools/design-token.mjs +117 -0
- package/agent-tools/digest-budget.mjs +76 -0
- package/agent-tools/eng.mjs +102 -0
- package/agent-tools/escalate-async.mjs +302 -0
- package/agent-tools/goal.mjs +119 -0
- package/agent-tools/panel-blocks.mjs +24 -0
- package/agent-tools/parent-channel.mjs +231 -0
- package/agent-tools/plan.mjs +86 -0
- package/agent-tools/read-history.mjs +309 -0
- package/agent-tools/recent-changes.mjs +24 -0
- package/agent-tools/review-facts.mjs +31 -0
- package/agent-tools/settings.mjs +268 -0
- package/agent-tools/skill.mjs +63 -0
- package/agent-tools/spawn-gates.mjs +109 -0
- package/agent-tools/subagent-actions.mjs +496 -0
- package/agent-tools/subagent-async.mjs +456 -0
- package/agent-tools/subagent-panel.mjs +160 -0
- package/agent-tools/subagent-run.mjs +208 -0
- package/agent-tools/subagent-scheduler.mjs +446 -0
- package/agent-tools/subagent-spawn.mjs +478 -0
- package/agent-tools/subagent.mjs +419 -0
- package/agent-tools/task.mjs +87 -0
- package/agent-tools/timer.mjs +46 -0
- package/agent-tools/verify.mjs +295 -0
- package/agent-tools.mjs +23 -0
- package/agent.mjs +430 -0
- package/auto-think.mjs +115 -0
- package/compress-form.mjs +24 -0
- package/config-io.mjs +277 -0
- package/config-migrate.mjs +178 -0
- package/config-presets.mjs +49 -0
- package/config.mjs +419 -0
- package/context.mjs +495 -0
- package/conventions.mjs +223 -0
- package/embedding.mjs +120 -0
- package/escape.mjs +152 -0
- package/expand-home.mjs +16 -0
- package/explore-distill.mjs +152 -0
- package/generate-title.mjs +123 -0
- package/git/checkpoint.mjs +448 -0
- package/git/gitmem.mjs +100 -0
- package/history-window.mjs +179 -0
- package/hooks.mjs +108 -0
- package/i18n.mjs +106 -0
- package/index-bin.mjs +48 -0
- package/index-discover.mjs +176 -0
- package/ledger-cmd.mjs +209 -0
- package/ledger-db.mjs +86 -0
- package/ledger-surface.mjs +76 -0
- package/ledger.mjs +202 -0
- package/log.mjs +195 -0
- package/manifest.mjs +338 -0
- package/markdown.mjs +106 -0
- package/mcp/helpers.mjs +51 -0
- package/mcp/transport-http.mjs +248 -0
- package/mcp/transport-stdio.mjs +140 -0
- package/mcp/transport-ws.mjs +122 -0
- package/mcp.mjs +295 -0
- package/memory/code-index.mjs +219 -0
- package/memory/code-sync.mjs +427 -0
- package/memory/core.mjs +318 -0
- package/memory/delete.mjs +242 -0
- package/memory/docs.mjs +431 -0
- package/memory/file-walk.mjs +109 -0
- package/memory/origin.mjs +24 -0
- package/memory/scan.mjs +177 -0
- package/memory/schema.mjs +460 -0
- package/memory.mjs +21 -0
- package/model-ref.mjs +66 -0
- package/model-specs.mjs +277 -0
- package/package.json +32 -0
- package/peer-domains.mjs +265 -0
- package/peer-instances.mjs +178 -0
- package/permission.mjs +79 -0
- package/process-probe.mjs +315 -0
- package/prompt-files.mjs +113 -0
- package/prompt-overlays.mjs +78 -0
- package/prompts/advisor-design.md +43 -0
- package/prompts/advisor-round1.md +41 -0
- package/prompts/advisor-round2.md +46 -0
- package/prompts/advisor-round3.md +42 -0
- package/prompts/common.md +158 -0
- package/prompts/consult-base.md +19 -0
- package/prompts/discipline-engineering.md +123 -0
- package/prompts/discipline-normal.md +206 -0
- package/prompts/persona-coder.md +21 -0
- package/prompts/persona-eng-coder.md +41 -0
- package/prompts/persona-eng-designer.md +80 -0
- package/prompts/persona-engineering.md +160 -0
- package/prompts/persona-explore.md +15 -0
- package/prompts/persona-normal.md +35 -0
- package/prompts/persona-plan.md +27 -0
- package/provider/anthropic.mjs +225 -0
- package/provider/core.mjs +491 -0
- package/provider/errors.mjs +101 -0
- package/provider/google.mjs +257 -0
- package/provider/index.mjs +7 -0
- package/provider/list-models.mjs +163 -0
- package/provider/normalize.mjs +81 -0
- package/provider/rate.mjs +168 -0
- package/provider/responses.mjs +495 -0
- package/provider/retry.mjs +88 -0
- package/provider/sse.mjs +264 -0
- package/provider/wait-status.mjs +59 -0
- package/proxy.mjs +274 -0
- package/rules.mjs +53 -0
- package/session-gc.mjs +248 -0
- package/session-guard.mjs +59 -0
- package/session-lifecycle.mjs +305 -0
- package/session-migrate.mjs +48 -0
- package/session-rename.mjs +38 -0
- package/session-segments.mjs +99 -0
- package/session-slot-write.mjs +168 -0
- package/session-slots-manifest.mjs +264 -0
- package/session-slots.mjs +298 -0
- package/session-store.mjs +441 -0
- package/session.mjs +244 -0
- package/skills.mjs +234 -0
- package/text-budget.mjs +79 -0
- package/token-ttl.mjs +285 -0
- package/tool-docs/apply_patch.md +15 -0
- package/tool-docs/bash.md +38 -0
- package/tool-docs/delete.md +13 -0
- package/tool-docs/edit.md +30 -0
- package/tool-docs/execute.md +21 -0
- package/tool-docs/fetch.md +12 -0
- package/tool-docs/file_ops.md +17 -0
- package/tool-docs/get_current_time.md +8 -0
- package/tool-docs/git.md +54 -0
- package/tool-docs/glob.md +11 -0
- package/tool-docs/grep.md +19 -0
- package/tool-docs/hashline_edit.md +14 -0
- package/tool-docs/insert_after.md +15 -0
- package/tool-docs/lint.md +10 -0
- package/tool-docs/ls.md +12 -0
- package/tool-docs/lsp.md +10 -0
- package/tool-docs/process.md +10 -0
- package/tool-docs/question.md +16 -0
- package/tool-docs/read.md +20 -0
- package/tool-docs/read_image.md +8 -0
- package/tool-docs/tree.md +14 -0
- package/tool-docs/wait_for.md +22 -0
- package/tool-docs/websearch.md +16 -0
- package/tool-docs/write.md +11 -0
- package/tools/bash.mjs +276 -0
- package/tools/edit-batch.mjs +204 -0
- package/tools/edit-diff.mjs +388 -0
- package/tools/exec-run.mjs +43 -0
- package/tools/execute.mjs +243 -0
- package/tools/file.mjs +464 -0
- package/tools/git-checkpoint.mjs +143 -0
- package/tools/git-ext.mjs +173 -0
- package/tools/git.mjs +415 -0
- package/tools/glob-dialect.mjs +130 -0
- package/tools/index.mjs +76 -0
- package/tools/linter.mjs +120 -0
- package/tools/lsp.mjs +335 -0
- package/tools/ops.mjs +293 -0
- package/tools/patch.mjs +290 -0
- package/tools/question.mjs +26 -0
- package/tools/repomap.mjs +314 -0
- package/tools/search.mjs +248 -0
- package/tools/shared.mjs +467 -0
- package/tools/tree.mjs +81 -0
- package/tools/web.mjs +224 -0
- package/tools/write-path.mjs +191 -0
- package/traces/trace-store.mjs +303 -0
- 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
|
+
}
|
package/agent-tools.mjs
ADDED
|
@@ -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"
|