thincoder 0.12.58 → 0.12.59
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/CHANGELOG.md +42 -1
- package/README.md +1 -1
- package/bin/thincoder.mjs +8 -0
- package/package.json +1 -1
- package/src/acp/bridge.mjs +132 -26
- package/src/advisor/messages.mjs +34 -1
- package/src/advisor/run.mjs +89 -51
- package/src/advisor.mjs +15 -7
- package/src/agent/dispatch.mjs +91 -14
- package/src/agent/helpers.mjs +35 -4
- package/src/agent/setup.mjs +90 -19
- package/src/agent/spawn-child.mjs +25 -0
- package/src/agent-tools/advisor.mjs +24 -2
- package/src/agent-tools/consult.mjs +37 -6
- package/src/agent-tools/eng.mjs +2 -1
- package/src/agent-tools/goal.mjs +11 -1
- package/src/agent-tools/read-history.mjs +160 -0
- package/src/agent-tools/settings.mjs +162 -0
- package/src/agent-tools/skill.mjs +2 -1
- package/src/agent-tools/subagent-actions.mjs +432 -0
- package/src/agent-tools/subagent-async.mjs +427 -0
- package/src/agent-tools/subagent-scheduler.mjs +319 -0
- package/src/agent-tools/subagent.mjs +467 -193
- package/src/agent-tools/task.mjs +4 -3
- package/src/agent-tools/timer.mjs +9 -4
- package/src/agent-tools/verify.mjs +161 -49
- package/src/agent-tools.mjs +1 -0
- package/src/agent.mjs +161 -125
- package/src/auto-think.mjs +14 -0
- package/src/cli/make-agent.mjs +2 -1
- package/src/cli/permission.mjs +8 -1
- package/src/config.mjs +5 -0
- package/src/context.mjs +87 -27
- package/src/distill.mjs +19 -1
- package/src/escape.mjs +6 -4
- package/src/log.mjs +195 -0
- package/src/memory/code-sync.mjs +1 -1
- package/src/memory/core.mjs +126 -0
- package/src/memory/docs.mjs +196 -87
- package/src/memory.mjs +1 -1
- package/src/model-specs.mjs +15 -1
- package/src/prompts/advisor-design.md +46 -0
- package/src/prompts/advisor-round1.md +49 -2
- package/src/prompts/advisor-round2.md +47 -0
- package/src/prompts/advisor-round3.md +47 -0
- package/src/prompts/coder.md +22 -0
- package/src/prompts/consult-base.md +13 -0
- package/src/prompts/discipline.md +10 -5
- package/src/prompts/eng-coder.md +2 -2
- package/src/prompts/engineering-sub.md +23 -1
- package/src/prompts/engineering.md +106 -56
- package/src/prompts/explore.md +1 -2
- package/src/prompts/main.md +11 -6
- package/src/prompts/methodology-template.md +14 -0
- package/src/prompts/system.md +4 -2
- package/src/provider/core.mjs +56 -2
- package/src/tools/apply_patch.md +3 -1
- package/src/tools/bash.md +1 -1
- package/src/tools/delete.md +1 -0
- package/src/tools/edit-batch.mjs +31 -43
- package/src/tools/edit-diff.mjs +265 -0
- package/src/tools/edit.md +10 -8
- package/src/tools/execute.md +7 -7
- package/src/tools/execute.mjs +24 -20
- package/src/tools/file.mjs +18 -68
- package/src/tools/file_ops.md +2 -1
- package/src/tools/get_current_time.md +3 -1
- package/src/tools/hashline_edit.md +2 -0
- package/src/tools/index.mjs +3 -2
- package/src/tools/insert_after.md +2 -1
- package/src/tools/lint.md +2 -0
- package/src/tools/lsp.md +4 -1
- package/src/tools/patch.mjs +84 -13
- package/src/tools/pdf-parse-text.mjs +497 -0
- package/src/tools/pdf-parse-xref.mjs +499 -0
- package/src/tools/pdf.mjs +155 -0
- package/src/tools/question.md +2 -1
- package/src/tools/read.md +1 -0
- package/src/tools/read_pdf.md +21 -0
- package/src/tools/repomap.mjs +1 -1
- package/src/tools/shared.mjs +4 -12
- package/src/tools/system.mjs +6 -21
- package/src/tools/tree.md +2 -1
- package/src/tools/web.mjs +5 -3
- package/src/tools/websearch.md +2 -1
- package/src/tools/write.md +2 -0
- package/src/traces/trace-store.mjs +224 -0
- package/src/tui/agent-turn.mjs +385 -22
- package/src/tui/clipboard.mjs +15 -4
- package/src/tui/cmd-config.mjs +29 -9
- package/src/tui/cmd-extract.mjs +1 -1
- package/src/tui/cmd-mcp.mjs +9 -0
- package/src/tui/cmd-think.mjs +1 -1
- package/src/tui/index.mjs +29 -95
- package/src/tui/interaction.mjs +13 -2
- package/src/tui/key-handler.mjs +105 -155
- package/src/tui/key-modes.mjs +215 -0
- package/src/tui/layout.mjs +22 -1
- package/src/tui/mouse.mjs +40 -0
- package/src/tui/pickers.mjs +11 -3
- package/src/tui/render-conversation.mjs +13 -161
- package/src/tui/render-frame.mjs +27 -10
- package/src/tui/render-loop.mjs +4 -1
- package/src/tui/render-segments.mjs +165 -0
- package/src/tui/startup.mjs +36 -0
- package/src/tui/subagent-blocks.mjs +322 -144
- package/src/tui/subagent-panel.mjs +88 -13
- package/src/tui/tool-args.mjs +10 -2
- package/src/tui/tool-events.mjs +132 -100
- package/src/tui/update-notice.mjs +72 -0
- package/src/tui/wizard.mjs +36 -6
- package/src/agent-tools/escalate.mjs +0 -179
- package/src/agent-tools/subagent-check.mjs +0 -107
- package/src/tools/exec-prelude.mjs +0 -84
package/src/memory/docs.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { join } from "node:path"
|
|
|
7
7
|
import { embed, cosine, toBlob, fromBlob } from "../embedding.mjs"
|
|
8
8
|
import { commitAndPush } from "../git/gitmem.mjs"
|
|
9
9
|
import { DOC_EXTS, SKIP_DIRS, MAX_DOC_FILE_BYTES } from "./schema.mjs"
|
|
10
|
-
import { buildFtsQuery, put, search, putMarkdown, deleteByUid, EMBED_TEXT_MAX_LEN } from "./core.mjs"
|
|
10
|
+
import { buildFtsQuery, put, search, putMarkdown, deleteByUid, matchMemoryRows, deleteWhere, clearPersonal, EMBED_TEXT_MAX_LEN } from "./core.mjs"
|
|
11
11
|
import { _upsertDocFile, yieldTick } from "./code-index.mjs"
|
|
12
12
|
import { markIndexedCommit, listProjectFiles } from "./code-sync.mjs"
|
|
13
13
|
|
|
@@ -164,7 +164,8 @@ export function docSearchTool(memory) {
|
|
|
164
164
|
return {
|
|
165
165
|
name: "doc_search",
|
|
166
166
|
description:
|
|
167
|
-
"Search the project's documentation (README, design docs, guides, markdown files) for relevant information. Use this to find design decisions, coding conventions, architecture docs, or project rules. Prefer this over code_search when you need to understand the project's intended design rather than existing implementation."
|
|
167
|
+
"Search the project's documentation (README, design docs, guides, markdown files) for relevant information. Use this to find design decisions, coding conventions, architecture docs, or project rules. Prefer this over code_search when you need to understand the project's intended design rather than existing implementation. " +
|
|
168
|
+
"Returns matching doc chunks: path, heading, line range, relevance score, content excerpt.",
|
|
168
169
|
parameters: {
|
|
169
170
|
type: "object",
|
|
170
171
|
properties: {
|
|
@@ -186,9 +187,45 @@ export function docSearchTool(memory) {
|
|
|
186
187
|
|
|
187
188
|
// ---------------------------------------------------------------- agent tools
|
|
188
189
|
|
|
190
|
+
/** §6 shared tool surface — action enum / parameter shapes / descriptions byte-identical
|
|
191
|
+
* with thincoder-vscode/src/memory.mjs (MEMORY.md §6 D-M1/F-M6); scope VALUES per end
|
|
192
|
+
* (VS Code has no team layer and rejects it with CLI guidance). */
|
|
193
|
+
const MEMORY_ACTIONS = ["search", "put", "list", "delete", "clear"]
|
|
194
|
+
const MEMORY_SCOPES = ["personal", "project", "team"]
|
|
195
|
+
const MEMORY_TOOL_DESCRIPTION =
|
|
196
|
+
"Manage long-term memory in ONE tool — the action parameter picks the operation:\n" +
|
|
197
|
+
"- search — find knowledge saved in previous sessions (query, optional scope/limit); results include every entry's id\n" +
|
|
198
|
+
"- put — save a piece of knowledge for future sessions (type: rule = coding standards, knowledge = project facts, decision = architecture decisions, pattern = debugging/workflow patterns; title/content/tags/scope)\n" +
|
|
199
|
+
"- list — inventory what memory holds: optional scope/type/keyword filters, limit default 50; one row per entry: id [type] title (date); a truncated list notes the full count\n" +
|
|
200
|
+
"- delete — SINGLE: {id, scope} deletes one entry by the id shown in put/search/list output. BATCH: {scope + type and/or keyword} deletes every matching entry in that scope — a call without confirm:true is refused and returns the count plus a preview (re-send with confirm:true to execute); scope-wide wipes without filters are refused on every layer\n" +
|
|
201
|
+
"- clear — {scope: \"personal\", confirm: true} wipes ALL personal memory entries. clear is personal-only: a missing scope or a project/team scope is refused (use delete batch filters on shared layers)\n" +
|
|
202
|
+
"Deleting project/team (CLI) entries removes the local markdown file and its index row — team deletion is local only and a later team sync may resurrect the file while the remote still has it.\n" +
|
|
203
|
+
"Save bugs, conventions, and preferences here — they persist across sessions."
|
|
204
|
+
|
|
205
|
+
function validateTypeFilter(type) {
|
|
206
|
+
if (type === undefined || type === null || type === "") return null
|
|
207
|
+
const t = String(type)
|
|
208
|
+
if (!["rule", "knowledge", "decision", "pattern"].includes(t)) throw new Error(`Invalid memory type "${t}"; expected one of: rule, knowledge, decision, pattern`)
|
|
209
|
+
return t
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function normalizeLimit(limit, dflt) {
|
|
213
|
+
const n = Number(limit)
|
|
214
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : dflt
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function fmtDate(ts) {
|
|
218
|
+
return ts ? new Date(ts).toISOString().slice(0, 10) : "?"
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const listRowLine = (r) => `${r.id} [${r.type}] ${r.title}(${fmtDate(r.ts)})`
|
|
222
|
+
|
|
189
223
|
/**
|
|
190
|
-
* Generate the
|
|
191
|
-
*
|
|
224
|
+
* Generate the memory agent tool — ONE `memory` tool with five actions (MEMORY.md §6 D-M1).
|
|
225
|
+
* search/list are read-only actions (planMode pass / no permission ask — dispatch classifies
|
|
226
|
+
* them action-level, same as subagent check/status); put keeps its side-effect permission
|
|
227
|
+
* gate; batch delete/clear gate on confirm:true + scope inside the tool (direct-delete
|
|
228
|
+
* ruling — the confirm parameter IS the gate) and stay non-readonly like the retired tools.
|
|
192
229
|
* opts: { cwd, projectDir, author, team: { dir, name } | null }
|
|
193
230
|
*/
|
|
194
231
|
export function memoryTools(memory, opts = {}) {
|
|
@@ -196,99 +233,171 @@ export function memoryTools(memory, opts = {}) {
|
|
|
196
233
|
const dirs = { project: projectDir, team: opts.team?.dir ?? null }
|
|
197
234
|
return [
|
|
198
235
|
{
|
|
199
|
-
name: "
|
|
200
|
-
description:
|
|
201
|
-
"Save a piece of knowledge to long-term memory. Use when you learn something worth remembering across sessions: a project convention, a debugging insight, an architecture decision. Types: rule (coding standards), knowledge (project facts), decision (architecture decisions), pattern (debugging/workflow patterns). Scopes: personal (default, private to you), project (shared via this repo's .thincoder/memory/), team (org-wide team repo, if configured).",
|
|
236
|
+
name: "memory",
|
|
237
|
+
description: MEMORY_TOOL_DESCRIPTION,
|
|
202
238
|
parameters: {
|
|
203
239
|
type: "object",
|
|
204
240
|
properties: {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
241
|
+
action: { type: "string", enum: MEMORY_ACTIONS, description: "Operation to run (required)" },
|
|
242
|
+
scope: { type: "string", enum: MEMORY_SCOPES, description: "Where the memory lives: personal (private), project (shared via this repo's .thincoder/memory/), team (CLI only). put defaults to personal; search/list search every layer when omitted; delete/clear require it" },
|
|
243
|
+
type: { type: "string", enum: ["rule", "knowledge", "decision", "pattern"], description: "Entry type: put = what to save; list/delete batch = filter by type" },
|
|
244
|
+
title: { type: "string", description: "put: short title" },
|
|
245
|
+
content: { type: "string", description: "put: full content to remember" },
|
|
246
|
+
tags: { type: "string", description: "put: space-separated tags" },
|
|
247
|
+
query: { type: "string", description: "search: natural-language query" },
|
|
248
|
+
keyword: { type: "string", description: "list/delete batch: filter matching title/content" },
|
|
249
|
+
id: { type: "string", description: "delete single: the entry id from put/search/list output" },
|
|
250
|
+
limit: { type: "number", description: "Max rows: list 50 by default, search 5 by default" },
|
|
251
|
+
confirm: { type: "boolean", description: "delete batch/clear: must be true — without it the tool refuses" },
|
|
210
252
|
},
|
|
211
|
-
required: ["
|
|
253
|
+
required: ["action"],
|
|
212
254
|
},
|
|
213
255
|
readonly: false,
|
|
214
256
|
async execute(args) {
|
|
215
|
-
const
|
|
216
|
-
if (
|
|
217
|
-
|
|
218
|
-
return `Saved to personal memory (id=personal:${id}): [${args.type}] ${args.title}`
|
|
219
|
-
}
|
|
220
|
-
if (scope === "project") {
|
|
221
|
-
if (!projectDir) throw new Error("project scope unavailable: no project directory configured")
|
|
222
|
-
const filename = await putMarkdown(memory, {
|
|
223
|
-
layer: "project",
|
|
224
|
-
dir: projectDir,
|
|
225
|
-
type: args.type,
|
|
226
|
-
title: args.title,
|
|
227
|
-
content: args.content,
|
|
228
|
-
tags: (args.tags ?? "").split(/\s+/).filter(Boolean),
|
|
229
|
-
author: opts.author ?? "unknown",
|
|
230
|
-
})
|
|
231
|
-
return `Saved to project memory (id=project:${projectDir}:${filename}): [${args.type}] ${args.title}`
|
|
257
|
+
const action = String(args?.action ?? "")
|
|
258
|
+
if (!MEMORY_ACTIONS.includes(action)) {
|
|
259
|
+
throw new Error(`memory: unknown action "${action}" — expected one of: ${MEMORY_ACTIONS.join("/")}`)
|
|
232
260
|
}
|
|
233
|
-
|
|
234
|
-
|
|
261
|
+
switch (action) {
|
|
262
|
+
case "search": return execSearch(memory, args)
|
|
263
|
+
case "put": return execPut(memory, args, opts, dirs)
|
|
264
|
+
case "list": return execList(memory, args, dirs)
|
|
265
|
+
case "delete": return execDelete(memory, args, dirs)
|
|
266
|
+
case "clear": return execClear(memory, args)
|
|
235
267
|
}
|
|
236
|
-
const filename = await putMarkdown(memory, {
|
|
237
|
-
layer: "team",
|
|
238
|
-
dir: opts.team.dir,
|
|
239
|
-
type: args.type,
|
|
240
|
-
title: args.title,
|
|
241
|
-
content: args.content,
|
|
242
|
-
tags: (args.tags ?? "").split(/\s+/).filter(Boolean),
|
|
243
|
-
author: opts.author ?? "unknown",
|
|
244
|
-
})
|
|
245
|
-
await commitAndPush(opts.team.dir, filename, `memory: [${args.type}] ${args.title}`)
|
|
246
|
-
return `Saved to team memory and pushed (id=team:${opts.team.dir}:${filename}): [${args.type}] ${args.title}`
|
|
247
|
-
},
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
name: "memory_search",
|
|
251
|
-
description:
|
|
252
|
-
"Search long-term memory across all layers (personal/project/team) for relevant knowledge saved in previous sessions. Use the same language as the memories being searched.",
|
|
253
|
-
parameters: {
|
|
254
|
-
type: "object",
|
|
255
|
-
properties: {
|
|
256
|
-
query: { type: "string", description: "Natural language search query" },
|
|
257
|
-
limit: { type: "number", description: "Max results (default 5)" },
|
|
258
|
-
},
|
|
259
|
-
required: ["query"],
|
|
260
|
-
},
|
|
261
|
-
readonly: true,
|
|
262
|
-
async execute(args) {
|
|
263
|
-
const results = await search(memory, args.query, { limit: args.limit ?? 5 })
|
|
264
|
-
if (results.length === 0) return "(no matching memories)"
|
|
265
|
-
return results.map((r) => `[${r.layer}][${r.type}] ${r.title} (id=${r.id})\n${r.content}`).join("\n\n")
|
|
266
|
-
},
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
name: "memory_delete",
|
|
270
|
-
description:
|
|
271
|
-
"Delete a memory entry by its id (as returned by memory_put / memory_search) and scope. " +
|
|
272
|
-
"Scope is required and must match the id prefix — this prevents accidental deletion in another scope. " +
|
|
273
|
-
"Returns the deleted entry's title and content so the deletion is auditable and recoverable.",
|
|
274
|
-
parameters: {
|
|
275
|
-
type: "object",
|
|
276
|
-
properties: {
|
|
277
|
-
id: { type: "string", description: "Entry id: personal:<n> / project:<origin>:<path> / team:<origin>:<path>" },
|
|
278
|
-
scope: { type: "string", enum: ["personal", "project", "team"], description: "Scope of the entry to delete (required)" },
|
|
279
|
-
},
|
|
280
|
-
required: ["id", "scope"],
|
|
281
|
-
},
|
|
282
|
-
readonly: false,
|
|
283
|
-
async execute(args) {
|
|
284
|
-
const uid = String(args.id)
|
|
285
|
-
const prefix = uid.split(":")[0]
|
|
286
|
-
const uidScope = prefix === "personal" || prefix === "project" || prefix === "team" ? prefix : /^\d+$/.test(prefix) ? "personal" : null
|
|
287
|
-
if (!uidScope) throw new Error(`invalid memory id: ${uid}`)
|
|
288
|
-
if (uidScope !== args.scope) throw new Error(`id prefix ${prefix}: 与 scope ${args.scope} 不匹配`)
|
|
289
|
-
const entry = await deleteByUid(memory, uid, { dirs })
|
|
290
|
-
return `Deleted ${entry.id}: ${entry.title}\n${(entry.content ?? "").slice(0, 500)}`
|
|
291
268
|
},
|
|
292
269
|
},
|
|
293
270
|
]
|
|
294
271
|
}
|
|
272
|
+
|
|
273
|
+
/** action search — the retired search tool surface (read-only, same output contract). */
|
|
274
|
+
async function execSearch(memory, args) {
|
|
275
|
+
const scope = args.scope
|
|
276
|
+
if (scope !== undefined && scope !== null && !MEMORY_SCOPES.includes(String(scope))) {
|
|
277
|
+
throw new Error(`memory search: invalid scope "${scope}"`)
|
|
278
|
+
}
|
|
279
|
+
const query = String(args.query ?? "").trim()
|
|
280
|
+
if (!query) return "(no matching memories)" // 空 query 短路——两端同语义(评审 code review #4)
|
|
281
|
+
const limit = normalizeLimit(args.limit, 5)
|
|
282
|
+
let results
|
|
283
|
+
if (!scope) {
|
|
284
|
+
results = await search(memory, query, { limit })
|
|
285
|
+
} else {
|
|
286
|
+
// scope filter: oversample then slice the requested layer (results keep global rank order).
|
|
287
|
+
// 窗口 = max(limit*4, 20) 是召回上限——大库 + 高 limit 时该层结果可能不足 limit(接受的取舍——评审 code review #3)
|
|
288
|
+
const wide = await search(memory, query, { limit: Math.max(limit * 4, 20) })
|
|
289
|
+
results = wide.filter((r) => r.layer === String(scope)).slice(0, limit)
|
|
290
|
+
}
|
|
291
|
+
if (results.length === 0) return "(no matching memories)"
|
|
292
|
+
return results.map((r) => `[${r.layer}][${r.type}] ${r.title} (id=${r.id})\n${r.content}`).join("\n\n")
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** action put — the retired put tool surface (side-effect gate, unchanged semantics). */
|
|
296
|
+
async function execPut(memory, args, opts, dirs) {
|
|
297
|
+
const scope = String(args.scope ?? "personal")
|
|
298
|
+
if (!MEMORY_SCOPES.includes(scope)) throw new Error(`memory put: invalid scope "${scope}"`)
|
|
299
|
+
if (scope === "personal") {
|
|
300
|
+
const id = await put(memory, { type: args.type, title: args.title, content: args.content, tags: args.tags ?? "" })
|
|
301
|
+
return `Saved to personal memory (id=personal:${id}): [${args.type}] ${args.title}`
|
|
302
|
+
}
|
|
303
|
+
if (scope === "project") {
|
|
304
|
+
if (!dirs.project) throw new Error("project scope unavailable: no project directory configured")
|
|
305
|
+
const filename = await putMarkdown(memory, {
|
|
306
|
+
layer: "project",
|
|
307
|
+
dir: dirs.project,
|
|
308
|
+
type: args.type,
|
|
309
|
+
title: args.title,
|
|
310
|
+
content: args.content,
|
|
311
|
+
tags: (args.tags ?? "").split(/\s+/).filter(Boolean),
|
|
312
|
+
author: opts.author ?? "unknown",
|
|
313
|
+
})
|
|
314
|
+
return `Saved to project memory (id=project:${dirs.project}:${filename}): [${args.type}] ${args.title}`
|
|
315
|
+
}
|
|
316
|
+
if (!dirs.team) {
|
|
317
|
+
throw new Error("team scope not configured: set memory.team in ~/.thincoder/config.json")
|
|
318
|
+
}
|
|
319
|
+
const filename = await putMarkdown(memory, {
|
|
320
|
+
layer: "team",
|
|
321
|
+
dir: dirs.team,
|
|
322
|
+
type: args.type,
|
|
323
|
+
title: args.title,
|
|
324
|
+
content: args.content,
|
|
325
|
+
tags: (args.tags ?? "").split(/\s+/).filter(Boolean),
|
|
326
|
+
author: opts.author ?? "unknown",
|
|
327
|
+
})
|
|
328
|
+
await commitAndPush(dirs.team, filename, `memory: [${args.type}] ${args.title}`)
|
|
329
|
+
return `Saved to team memory and pushed (id=team:${dirs.team}:${filename}): [${args.type}] ${args.title}`
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** action list — new inventory action (read-only): scope/type/keyword filters + limit truncation note. */
|
|
333
|
+
async function execList(memory, args, dirs) {
|
|
334
|
+
const scope = args.scope ?? null
|
|
335
|
+
if (scope && !MEMORY_SCOPES.includes(String(scope))) throw new Error(`memory list: invalid scope "${scope}"`)
|
|
336
|
+
const rows = await matchMemoryRows(memory, {
|
|
337
|
+
scope: scope ? String(scope) : null,
|
|
338
|
+
type: validateTypeFilter(args.type),
|
|
339
|
+
keyword: args.keyword ? String(args.keyword).trim() : null,
|
|
340
|
+
projectDir: dirs.project,
|
|
341
|
+
teamDir: dirs.team,
|
|
342
|
+
})
|
|
343
|
+
if (rows.length === 0) return "0 条匹配"
|
|
344
|
+
const limit = normalizeLimit(args.limit, 50)
|
|
345
|
+
const shown = rows.slice(0, limit)
|
|
346
|
+
const lines = shown.map(listRowLine)
|
|
347
|
+
if (rows.length > shown.length) lines.unshift(`${shown.length} 条——截断前 ${rows.length}`)
|
|
348
|
+
return lines.join("\n")
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** action delete — single ({ id, scope } — §0.1-era single-delete semantics) + batch (scope + type/keyword + confirm). */
|
|
352
|
+
async function execDelete(memory, args, dirs) {
|
|
353
|
+
const hasId = args.id !== undefined && args.id !== null && String(args.id) !== ""
|
|
354
|
+
if (hasId) return execDeleteSingle(memory, args, dirs)
|
|
355
|
+
// batch form
|
|
356
|
+
const scope = args.scope
|
|
357
|
+
if (!scope) throw new Error("batch delete requires scope plus type and/or keyword filter")
|
|
358
|
+
if (!MEMORY_SCOPES.includes(String(scope))) throw new Error(`memory delete: invalid scope "${scope}"`)
|
|
359
|
+
const type = validateTypeFilter(args.type)
|
|
360
|
+
const keyword = args.keyword ? String(args.keyword).trim() : null
|
|
361
|
+
if (!type && !keyword) {
|
|
362
|
+
throw new Error("batch delete requires type and/or keyword filter — a scope-wide wipe without filters is refused (personal full wipe is the clear action)")
|
|
363
|
+
}
|
|
364
|
+
if (scope === "project" && !dirs.project) throw new Error("project scope unavailable: no project directory configured")
|
|
365
|
+
if (scope === "team" && !dirs.team) throw new Error("team scope not configured: set memory.team in ~/.thincoder/config.json")
|
|
366
|
+
const filters = { scope: String(scope), type, keyword }
|
|
367
|
+
const rows = await matchMemoryRows(memory, { ...filters, projectDir: dirs.project, teamDir: dirs.team })
|
|
368
|
+
if (rows.length === 0) return "0 条匹配"
|
|
369
|
+
if (args.confirm !== true) {
|
|
370
|
+
const lines = [rows.length > 5 ? `将删 ${rows.length} 条:前 5 条预览` : `将删 ${rows.length} 条`]
|
|
371
|
+
lines.push(...rows.slice(0, 5).map(listRowLine))
|
|
372
|
+
if (rows.length > 5) lines.push(`5 条——截断前 ${rows.length}`)
|
|
373
|
+
lines.push("confirm:true required — re-send with it to execute the deletion")
|
|
374
|
+
return lines.join("\n")
|
|
375
|
+
}
|
|
376
|
+
const n = await deleteWhere(memory, filters, { dirs })
|
|
377
|
+
return `Deleted ${n} entries in scope ${scope}`
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** Single-entry delete — §0.1-era delete semantics (id + scope, NF2/NF3, direct-delete ruling). */
|
|
381
|
+
async function execDeleteSingle(memory, args, dirs) {
|
|
382
|
+
if (!args.scope) throw new Error("delete requires id + scope")
|
|
383
|
+
const uid = String(args.id)
|
|
384
|
+
const prefix = uid.split(":")[0]
|
|
385
|
+
const uidScope = prefix === "personal" || prefix === "project" || prefix === "team" ? prefix : /^\d+$/.test(prefix) ? "personal" : null
|
|
386
|
+
if (!uidScope) throw new Error(`invalid memory id: ${uid}`)
|
|
387
|
+
if (uidScope !== args.scope) throw new Error(`id prefix ${prefix}: 与 scope ${args.scope} 不匹配`)
|
|
388
|
+
const entry = await deleteByUid(memory, uid, { dirs })
|
|
389
|
+
return `Deleted ${entry.id}: ${entry.title}\n${(entry.content ?? "").slice(0, 500)}`
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/** action clear — personal-only full wipe (scope + confirm:true gates; project/team refused). */
|
|
393
|
+
function execClear(memory, args) {
|
|
394
|
+
const scope = args.scope
|
|
395
|
+
if (!scope) throw new Error('clear requires scope "personal" — pass scope: "personal" plus confirm: true')
|
|
396
|
+
if (String(scope) !== "personal") {
|
|
397
|
+
if (!MEMORY_SCOPES.includes(String(scope))) throw new Error(`memory clear: invalid scope "${scope}"`)
|
|
398
|
+
throw new Error("shared layers don't support clear — use delete with type/keyword batch filters instead")
|
|
399
|
+
}
|
|
400
|
+
if (args.confirm !== true) throw new Error("clear requires confirm:true — this wipes ALL personal memory")
|
|
401
|
+
const n = clearPersonal(memory)
|
|
402
|
+
return `Cleared personal memory (${n} entries deleted)`
|
|
403
|
+
}
|
package/src/memory.mjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
export { createMemory, migrate, segmentCJK, VALID_TYPES, SCHEMA_VERSION, CODE_EXTS, DOC_EXTS, SKIP_DIRS, BIG_FILE_LINES } from "./memory/schema.mjs"
|
|
8
8
|
|
|
9
9
|
// CRUD + search + ensureEmbeddings
|
|
10
|
-
export { put, search, ftsSearch, fetchEntry, ensureEmbeddings, putMarkdown, syncDir, indexMarkdownFile, list, remove, deleteByUid, buildFtsQuery } from "./memory/core.mjs"
|
|
10
|
+
export { put, search, ftsSearch, fetchEntry, ensureEmbeddings, putMarkdown, syncDir, indexMarkdownFile, list, remove, deleteByUid, matchMemoryRows, deleteWhere, clearPersonal, buildFtsQuery } from "./memory/core.mjs"
|
|
11
11
|
|
|
12
12
|
// code chunking + markdown chunking
|
|
13
13
|
export { detectLanguage, extractSymbols, extractPySymbols, chunkCode, extractLeadingDoc, yieldTick, _upsertCodeFile, chunkMarkdown, _upsertDocFile } from "./memory/code-index.mjs"
|
package/src/model-specs.mjs
CHANGED
|
@@ -88,7 +88,13 @@ const MODEL_SPECS = [
|
|
|
88
88
|
]
|
|
89
89
|
const DEFAULT_SPEC = { context: 128_000, maxOutput: 32_000, cacheMode: "none" }
|
|
90
90
|
|
|
91
|
-
/** Look up spec by model name prefix (case-insensitive), conservative default for unknown models
|
|
91
|
+
/** Look up spec by model name prefix (case-insensitive), conservative default for unknown models.
|
|
92
|
+
*
|
|
93
|
+
* Vendor-namespace prefix stripping (2026-09-04):第三方 token 市场(roapi/new-api/one-api/
|
|
94
|
+
* aiproxy 聚合网关)惯例在模型名前加厂商前缀(zhipu/glm-5.3、openai/gpt-4o)。完整名未命中
|
|
95
|
+
* 且含 "/" 时,剥掉第一个 "/" 前的 namespace 再按前缀匹配一次——ZHIPU/GLM-5.3 → glm-5.3 命中
|
|
96
|
+
* 真实规格,不再降级 128K 默认。kimi/kimi-k3 的显式 alias 行保留为文档锚(发送路径
|
|
97
|
+
* provider.core isRouter 依赖含 "/" 判定),通用机制已覆盖同类。 */
|
|
92
98
|
const warnedModels = new Set() // warn once per model name — specForModel is a hot path (every request)
|
|
93
99
|
// Pre-sorted once at module scope — specForModel runs on every request (agent, provider core,
|
|
94
100
|
// context, auto-think, TUI rendering); re-sorting per call was wasteful.
|
|
@@ -98,6 +104,14 @@ export function specForModel(model) {
|
|
|
98
104
|
for (const [prefix, spec] of SORTED_SPECS) {
|
|
99
105
|
if (m.startsWith(prefix.toLowerCase())) return spec
|
|
100
106
|
}
|
|
107
|
+
// Vendor-namespace strip: vendor/model — retry the prefix match on the bare model part.
|
|
108
|
+
const slash = m.indexOf("/")
|
|
109
|
+
if (slash > 0) {
|
|
110
|
+
const bare = m.slice(slash + 1)
|
|
111
|
+
for (const [prefix, spec] of SORTED_SPECS) {
|
|
112
|
+
if (bare.startsWith(prefix.toLowerCase())) return spec
|
|
113
|
+
}
|
|
114
|
+
}
|
|
101
115
|
// Unknown model: warn ONCE (not per request) so a typo'd ID or a missing alias surfaces
|
|
102
116
|
// instead of silently degrading to the 128K default (IK5VGJ).
|
|
103
117
|
if (m && !warnedModels.has(m)) {
|
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
You are an independent design reviewer for an engineering-mode project.
|
|
2
2
|
|
|
3
|
+
## Your role (identity — read before the criteria)
|
|
4
|
+
|
|
5
|
+
You are an INDEPENDENT REVIEWER — authority in judgment, not in decisions.
|
|
6
|
+
|
|
7
|
+
1. **Stance**: you judge the design/code on its own merits against the review
|
|
8
|
+
criteria. You are not the author, not the implementer, not the editor —
|
|
9
|
+
you FIND and REPORT; the parent agent (and the user) decides what changes.
|
|
10
|
+
Do NOT write replacement text or patch code in your findings — the
|
|
11
|
+
suggestion column stays advisory guidance (the parent agent decides
|
|
12
|
+
what changes; you evidence and recommend, you do not rewrite).
|
|
13
|
+
2. **Evidence discipline**: every factual/behavioral assertion you make MUST be
|
|
14
|
+
verified from the documents/files in scope (read them, cite file:line) —
|
|
15
|
+
or explicitly marked `unverified`. NEVER assert "Known behavior…",
|
|
16
|
+
"I'm confident…", or rely on remembered API semantics when the source is
|
|
17
|
+
readable in scope — a behavioral question is an EVIDENCE question, not a
|
|
18
|
+
reasoning question.
|
|
19
|
+
3. **Boundary**: your review target = the review-object declaration (type /
|
|
20
|
+
target / status / reason / exclude) + the documents in the review scope.
|
|
21
|
+
Do NOT expand it. With no object declaration (legacy calls) your target =
|
|
22
|
+
the review scope only. Findings that touch something outside this scope
|
|
23
|
+
(parent-side docs, other modules) go in a trailing "out-of-scope note" —
|
|
24
|
+
NO severity assigned to them.
|
|
25
|
+
4. **Neutrality**: no git diff, no conversation-history archaeology — the
|
|
26
|
+
state of the files/documents as you read them is the truth. Do not guess
|
|
27
|
+
author intent.
|
|
28
|
+
|
|
3
29
|
The agent has written a design document and is asking you to review it before any code is written.
|
|
4
30
|
|
|
5
31
|
## Review Criteria
|
|
@@ -50,3 +76,23 @@ Important:
|
|
|
50
76
|
- Review the design on its own merits — do NOT expect code to exist yet.
|
|
51
77
|
- Read the design document fully. Read METHODOLOGY.md to understand the project's standards.
|
|
52
78
|
- Do NOT run git diff or look for code changes — there are none at this stage.
|
|
79
|
+
|
|
80
|
+
## Judgment Rules (apply directly — do not re-derive)
|
|
81
|
+
|
|
82
|
+
Apply each rule to the extent it matches the review type: design review — doc-state rules (R1, R7a-e) apply; code review — all rules apply.
|
|
83
|
+
|
|
84
|
+
R1 Doc contradiction / state inconsistency → 🟡 (report-and-fix by the parent doc layer — NOT 🔴; exception: the same mechanism described differently in two places = Document ownership 🔴 — keep the advisor-design.md convention — do not downgrade)
|
|
85
|
+
R2 Implementation deviates from design (acceptance unmet / silent simplification) → 🔴 (must fix)
|
|
86
|
+
R3 Existing precedent ruling (debt like file size) → 🟡/🔵, do not escalate, do not re-litigate
|
|
87
|
+
R4 Fragile test (wall-clock / serialization-shape dependency) → 🔵 + suggest determinism
|
|
88
|
+
R5 Scope coordination (parent-side TODO) → 🟡 "coordination item" (not a defect)
|
|
89
|
+
R6 Test seam — when testing needs to mock an internal tool set / slow tools and the set is hard-coded inside the loop (not injectable): do NOT try real slow tools / FIFO / large files (non-deterministic) / onTool observation (insufficient) / mock-LLM-returning-real-tools (too fast) — the only path is a test seam (module-level setter or parameter override + `??` default fallback; default null → production behavior unchanged; restore in finally) — the generic rule applies to both ends; concrete symbol names live in design notes only (never in the generic prompt)
|
|
90
|
+
R7a Doc-state contradiction / cross-file lag → 🟡 report without editing (review is read-only; mechanism-level contradiction excluded — see R1 exception — = 🔴)
|
|
91
|
+
R7b Content contradiction → higher layer wins: Design (D) > Requirements (F) > records (TODO)
|
|
92
|
+
R7c Numeric drift / TODO unchecked / doc hygiene → 🔵
|
|
93
|
+
R7d Semantic dangling → 🟡 report the design gap (parent fixes)
|
|
94
|
+
R7e Never block "pass" due to doc-state contradiction — contradiction = 🟡 report-and-pass (except mechanism-level description mismatch — = 🔴 — must be resolved before pass)
|
|
95
|
+
|
|
96
|
+
Source: 7-round sample — verified judgments — continuously re-reviewed.
|
|
97
|
+
|
|
98
|
+
You have received the review-object declaration above — no need to infer the review target from the documents.
|
|
@@ -1,16 +1,43 @@
|
|
|
1
1
|
You are a code review advisor.
|
|
2
|
+
|
|
3
|
+
## Your role (identity — read before the criteria)
|
|
4
|
+
|
|
5
|
+
You are an INDEPENDENT REVIEWER — authority in judgment, not in decisions.
|
|
6
|
+
|
|
7
|
+
1. **Stance**: you judge the design/code on its own merits against the review
|
|
8
|
+
criteria. You are not the author, not the implementer, not the editor —
|
|
9
|
+
you FIND and REPORT; the parent agent (and the user) decides what changes.
|
|
10
|
+
Do NOT write replacement text or patch code in your findings — the
|
|
11
|
+
suggestion column stays advisory guidance (the parent agent decides
|
|
12
|
+
what changes; you evidence and recommend, you do not rewrite).
|
|
13
|
+
2. **Evidence discipline**: every factual/behavioral assertion you make MUST be
|
|
14
|
+
verified from the documents/files in scope (read them, cite file:line) —
|
|
15
|
+
or explicitly marked `unverified`. NEVER assert "Known behavior…",
|
|
16
|
+
"I'm confident…", or rely on remembered API semantics when the source is
|
|
17
|
+
readable in scope — a behavioral question is an EVIDENCE question, not a
|
|
18
|
+
reasoning question.
|
|
19
|
+
3. **Boundary**: your review target = the review-object declaration (type /
|
|
20
|
+
target / status / reason / exclude) + the documents in the review scope.
|
|
21
|
+
Do NOT expand it. With no object declaration (legacy calls) your target =
|
|
22
|
+
the review scope only. Findings that touch something outside this scope
|
|
23
|
+
(parent-side docs, other modules) go in a trailing "out-of-scope note" —
|
|
24
|
+
NO severity assigned to them.
|
|
25
|
+
4. **Neutrality**: no git diff, no conversation-history archaeology — the
|
|
26
|
+
state of the files/documents as you read them is the truth. Do not guess
|
|
27
|
+
author intent.
|
|
28
|
+
|
|
2
29
|
Perform a full-scope review of the specified files.
|
|
3
30
|
You have read-only tools to explore the codebase.
|
|
4
31
|
You have a budget of 20 tool rounds (chat turns) — plan your exploration accordingly. Hard mechanical cap: 100 rounds (the system stops you there if the review loops).
|
|
5
32
|
|
|
6
33
|
Review workflow:
|
|
7
|
-
1. The files to review are listed in the review scope
|
|
34
|
+
1. The files to review are listed in the review scope — **focus on the review scope**: read the review-target files (the delivery list) FIRST; read design documents only in the sections relevant to this implementation (do NOT read whole documents in full); do not read unrelated modules just to understand the implementation. The review scope defines exactly which files to inspect.
|
|
8
35
|
2. **READ THE PROJECT GUIDE FIRST** — the `## Project Guide (AGENTS.md)` section in the review context maps the project's structure.
|
|
9
36
|
- It tells you where the requirements/design documents live.
|
|
10
37
|
- Read whatever documents the guide names — no fixed file names are assumed.
|
|
11
38
|
- **The user's requirements live in those documents; the conversation background is only a supplement.**
|
|
12
39
|
- If the guide names none, judge from the conversation background and say so explicitly if requirements are unclear.
|
|
13
|
-
3. Read the specified files for full context. **Batch independent `read` calls in a SINGLE reply** — do not read files one at a time
|
|
40
|
+
3. Read the specified files for full context. **Batch independent `read` calls in a SINGLE reply** — do not read files one at a time; **multiple files read in one batch execute in PARALLEL (concurrent — do not wait serially)**. Each round-trip counts against your limit.
|
|
14
41
|
4. Produce your review table.
|
|
15
42
|
|
|
16
43
|
Budget rules:
|
|
@@ -45,3 +72,23 @@ Rules:
|
|
|
45
72
|
- Stop calling tools once you are ready to produce the review table.
|
|
46
73
|
- **Host verification**: every `file:line: content` reference in your table is mechanically checked against the CURRENT file state by the host — quote exactly what `read` returned; a mismatch marks the finding unverified.
|
|
47
74
|
- **Pass/fail**: if there are NO 🔴 (Critical) issues, the review passes. 🟡 (Advisory) and 🔵 (Style) findings do NOT block approval — list them in the table. If there is ANY 🔴 issue, list it and do not claim the review passed.
|
|
75
|
+
|
|
76
|
+
## Judgment Rules (apply directly — do not re-derive)
|
|
77
|
+
|
|
78
|
+
Apply each rule to the extent it matches the review type: design review — doc-state rules (R1, R7a-e) apply; code review — all rules apply.
|
|
79
|
+
|
|
80
|
+
R1 Doc contradiction / state inconsistency → 🟡 (report-and-fix by the parent doc layer — NOT 🔴; exception: the same mechanism described differently in two places = Document ownership 🔴 — keep the advisor-design.md convention — do not downgrade)
|
|
81
|
+
R2 Implementation deviates from design (acceptance unmet / silent simplification) → 🔴 (must fix)
|
|
82
|
+
R3 Existing precedent ruling (debt like file size) → 🟡/🔵, do not escalate, do not re-litigate
|
|
83
|
+
R4 Fragile test (wall-clock / serialization-shape dependency) → 🔵 + suggest determinism
|
|
84
|
+
R5 Scope coordination (parent-side TODO) → 🟡 "coordination item" (not a defect)
|
|
85
|
+
R6 Test seam — when testing needs to mock an internal tool set / slow tools and the set is hard-coded inside the loop (not injectable): do NOT try real slow tools / FIFO / large files (non-deterministic) / onTool observation (insufficient) / mock-LLM-returning-real-tools (too fast) — the only path is a test seam (module-level setter or parameter override + `??` default fallback; default null → production behavior unchanged; restore in finally) — the generic rule applies to both ends; concrete symbol names live in design notes only (never in the generic prompt)
|
|
86
|
+
R7a Doc-state contradiction / cross-file lag → 🟡 report without editing (review is read-only; mechanism-level contradiction excluded — see R1 exception — = 🔴)
|
|
87
|
+
R7b Content contradiction → higher layer wins: Design (D) > Requirements (F) > records (TODO)
|
|
88
|
+
R7c Numeric drift / TODO unchecked / doc hygiene → 🔵
|
|
89
|
+
R7d Semantic dangling → 🟡 report the design gap (parent fixes)
|
|
90
|
+
R7e Never block "pass" due to doc-state contradiction — contradiction = 🟡 report-and-pass (except mechanism-level description mismatch — = 🔴 — must be resolved before pass)
|
|
91
|
+
|
|
92
|
+
Source: 7-round sample — verified judgments — continuously re-reviewed.
|
|
93
|
+
|
|
94
|
+
You have received the review-object declaration above — no need to infer the review target from the documents.
|
|
@@ -1,4 +1,31 @@
|
|
|
1
1
|
You are an independent review advisor.
|
|
2
|
+
|
|
3
|
+
## Your role (identity — read before the criteria)
|
|
4
|
+
|
|
5
|
+
You are an INDEPENDENT REVIEWER — authority in judgment, not in decisions.
|
|
6
|
+
|
|
7
|
+
1. **Stance**: you judge the design/code on its own merits against the review
|
|
8
|
+
criteria. You are not the author, not the implementer, not the editor —
|
|
9
|
+
you FIND and REPORT; the parent agent (and the user) decides what changes.
|
|
10
|
+
Do NOT write replacement text or patch code in your findings — the
|
|
11
|
+
suggestion column stays advisory guidance (the parent agent decides
|
|
12
|
+
what changes; you evidence and recommend, you do not rewrite).
|
|
13
|
+
2. **Evidence discipline**: every factual/behavioral assertion you make MUST be
|
|
14
|
+
verified from the documents/files in scope (read them, cite file:line) —
|
|
15
|
+
or explicitly marked `unverified`. NEVER assert "Known behavior…",
|
|
16
|
+
"I'm confident…", or rely on remembered API semantics when the source is
|
|
17
|
+
readable in scope — a behavioral question is an EVIDENCE question, not a
|
|
18
|
+
reasoning question.
|
|
19
|
+
3. **Boundary**: your review target = the review-object declaration (type /
|
|
20
|
+
target / status / reason / exclude) + the documents in the review scope.
|
|
21
|
+
Do NOT expand it. With no object declaration (legacy calls) your target =
|
|
22
|
+
the review scope only. Findings that touch something outside this scope
|
|
23
|
+
(parent-side docs, other modules) go in a trailing "out-of-scope note" —
|
|
24
|
+
NO severity assigned to them.
|
|
25
|
+
4. **Neutrality**: no git diff, no conversation-history archaeology — the
|
|
26
|
+
state of the files/documents as you read them is the truth. Do not guess
|
|
27
|
+
author intent.
|
|
28
|
+
|
|
2
29
|
Verify the prior review output (provided in the review context).
|
|
3
30
|
You may note obvious new issues introduced by the fixes.
|
|
4
31
|
You have read-only tools to explore the codebase.
|
|
@@ -33,3 +60,23 @@ Rules:
|
|
|
33
60
|
| N | (new) | src/y.mjs | 🔴 | New: null check missing after fix | ... |
|
|
34
61
|
- If all 🔴 issues are resolved and remaining items are only 🟡/🔵, the review passes (🟡/🔵 do not block approval). If any 🔴 issue persists, do not claim it passed.
|
|
35
62
|
- Stop calling tools once you are ready to produce the review table.
|
|
63
|
+
|
|
64
|
+
## Judgment Rules (apply directly — do not re-derive)
|
|
65
|
+
|
|
66
|
+
Apply each rule to the extent it matches the review type: design review — doc-state rules (R1, R7a-e) apply; code review — all rules apply.
|
|
67
|
+
|
|
68
|
+
R1 Doc contradiction / state inconsistency → 🟡 (report-and-fix by the parent doc layer — NOT 🔴; exception: the same mechanism described differently in two places = Document ownership 🔴 — keep the advisor-design.md convention — do not downgrade)
|
|
69
|
+
R2 Implementation deviates from design (acceptance unmet / silent simplification) → 🔴 (must fix)
|
|
70
|
+
R3 Existing precedent ruling (debt like file size) → 🟡/🔵, do not escalate, do not re-litigate
|
|
71
|
+
R4 Fragile test (wall-clock / serialization-shape dependency) → 🔵 + suggest determinism
|
|
72
|
+
R5 Scope coordination (parent-side TODO) → 🟡 "coordination item" (not a defect)
|
|
73
|
+
R6 Test seam — when testing needs to mock an internal tool set / slow tools and the set is hard-coded inside the loop (not injectable): do NOT try real slow tools / FIFO / large files (non-deterministic) / onTool observation (insufficient) / mock-LLM-returning-real-tools (too fast) — the only path is a test seam (module-level setter or parameter override + `??` default fallback; default null → production behavior unchanged; restore in finally) — the generic rule applies to both ends; concrete symbol names live in design notes only (never in the generic prompt)
|
|
74
|
+
R7a Doc-state contradiction / cross-file lag → 🟡 report without editing (review is read-only; mechanism-level contradiction excluded — see R1 exception — = 🔴)
|
|
75
|
+
R7b Content contradiction → higher layer wins: Design (D) > Requirements (F) > records (TODO)
|
|
76
|
+
R7c Numeric drift / TODO unchecked / doc hygiene → 🔵
|
|
77
|
+
R7d Semantic dangling → 🟡 report the design gap (parent fixes)
|
|
78
|
+
R7e Never block "pass" due to doc-state contradiction — contradiction = 🟡 report-and-pass (except mechanism-level description mismatch — = 🔴 — must be resolved before pass)
|
|
79
|
+
|
|
80
|
+
Source: 7-round sample — verified judgments — continuously re-reviewed.
|
|
81
|
+
|
|
82
|
+
You have received the review-object declaration above — no need to infer the review target from the documents.
|
|
@@ -1,4 +1,31 @@
|
|
|
1
1
|
You are an independent review advisor.
|
|
2
|
+
|
|
3
|
+
## Your role (identity — read before the criteria)
|
|
4
|
+
|
|
5
|
+
You are an INDEPENDENT REVIEWER — authority in judgment, not in decisions.
|
|
6
|
+
|
|
7
|
+
1. **Stance**: you judge the design/code on its own merits against the review
|
|
8
|
+
criteria. You are not the author, not the implementer, not the editor —
|
|
9
|
+
you FIND and REPORT; the parent agent (and the user) decides what changes.
|
|
10
|
+
Do NOT write replacement text or patch code in your findings — the
|
|
11
|
+
suggestion column stays advisory guidance (the parent agent decides
|
|
12
|
+
what changes; you evidence and recommend, you do not rewrite).
|
|
13
|
+
2. **Evidence discipline**: every factual/behavioral assertion you make MUST be
|
|
14
|
+
verified from the documents/files in scope (read them, cite file:line) —
|
|
15
|
+
or explicitly marked `unverified`. NEVER assert "Known behavior…",
|
|
16
|
+
"I'm confident…", or rely on remembered API semantics when the source is
|
|
17
|
+
readable in scope — a behavioral question is an EVIDENCE question, not a
|
|
18
|
+
reasoning question.
|
|
19
|
+
3. **Boundary**: your review target = the review-object declaration (type /
|
|
20
|
+
target / status / reason / exclude) + the documents in the review scope.
|
|
21
|
+
Do NOT expand it. With no object declaration (legacy calls) your target =
|
|
22
|
+
the review scope only. Findings that touch something outside this scope
|
|
23
|
+
(parent-side docs, other modules) go in a trailing "out-of-scope note" —
|
|
24
|
+
NO severity assigned to them.
|
|
25
|
+
4. **Neutrality**: no git diff, no conversation-history archaeology — the
|
|
26
|
+
state of the files/documents as you read them is the truth. Do not guess
|
|
27
|
+
author intent.
|
|
28
|
+
|
|
2
29
|
Strictly verify only the prior review output (provided in the review context).
|
|
3
30
|
You have read-only tools to explore the codebase.
|
|
4
31
|
You have a budget of 15 tool rounds (chat turns). Hard mechanical cap: 100 rounds.
|
|
@@ -29,3 +56,23 @@ Rules:
|
|
|
29
56
|
| 1 | 3 | src/x.mjs | 🔴 | Unfixed | ... |
|
|
30
57
|
- If all 🔴 issues are resolved and remaining items are only 🟡/🔵, the review passes (🟡/🔵 do not block approval). If any 🔴 issue persists, do not claim it passed.
|
|
31
58
|
- Stop calling tools once you are ready to produce the review table.
|
|
59
|
+
|
|
60
|
+
## Judgment Rules (apply directly — do not re-derive)
|
|
61
|
+
|
|
62
|
+
Apply each rule to the extent it matches the review type: design review — doc-state rules (R1, R7a-e) apply; code review — all rules apply.
|
|
63
|
+
|
|
64
|
+
R1 Doc contradiction / state inconsistency → 🟡 (report-and-fix by the parent doc layer — NOT 🔴; exception: the same mechanism described differently in two places = Document ownership 🔴 — keep the advisor-design.md convention — do not downgrade)
|
|
65
|
+
R2 Implementation deviates from design (acceptance unmet / silent simplification) → 🔴 (must fix)
|
|
66
|
+
R3 Existing precedent ruling (debt like file size) → 🟡/🔵, do not escalate, do not re-litigate
|
|
67
|
+
R4 Fragile test (wall-clock / serialization-shape dependency) → 🔵 + suggest determinism
|
|
68
|
+
R5 Scope coordination (parent-side TODO) → 🟡 "coordination item" (not a defect)
|
|
69
|
+
R6 Test seam — when testing needs to mock an internal tool set / slow tools and the set is hard-coded inside the loop (not injectable): do NOT try real slow tools / FIFO / large files (non-deterministic) / onTool observation (insufficient) / mock-LLM-returning-real-tools (too fast) — the only path is a test seam (module-level setter or parameter override + `??` default fallback; default null → production behavior unchanged; restore in finally) — the generic rule applies to both ends; concrete symbol names live in design notes only (never in the generic prompt)
|
|
70
|
+
R7a Doc-state contradiction / cross-file lag → 🟡 report without editing (review is read-only; mechanism-level contradiction excluded — see R1 exception — = 🔴)
|
|
71
|
+
R7b Content contradiction → higher layer wins: Design (D) > Requirements (F) > records (TODO)
|
|
72
|
+
R7c Numeric drift / TODO unchecked / doc hygiene → 🔵
|
|
73
|
+
R7d Semantic dangling → 🟡 report the design gap (parent fixes)
|
|
74
|
+
R7e Never block "pass" due to doc-state contradiction — contradiction = 🟡 report-and-pass (except mechanism-level description mismatch — = 🔴 — must be resolved before pass)
|
|
75
|
+
|
|
76
|
+
Source: 7-round sample — verified judgments — continuously re-reviewed.
|
|
77
|
+
|
|
78
|
+
You have received the review-object declaration above — no need to infer the review target from the documents.
|