mocode-ai 1.0.14 → 1.1.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/README.md CHANGED
@@ -72,7 +72,7 @@ MoCode isn't a chat box with a coat of paint — it's an agent that actually get
72
72
  - **Plan / Auto dual mode** — In `plan` mode the agent is read-only (reads code, queries indexes, searches — never writes to disk, runs commands, or spawns sub-agents) and produces a plan; `auto` mode unlocks the full toolset. The agent can switch between the two on its own — scope out an unfamiliar codebase first, then start making changes.
73
73
  - **Automatic context compression** — As the context window fills up, a three-tier compression kicks in (trim individual results → compact older tool results in place → summarize older turns), so long sessions never overflow. `/context` shows live token usage; `/compact` triggers manual compression (optionally with a focus hint to preserve what matters).
74
74
  - **Cross-session long-term memory** — The agent can save project architecture, conventions, and lessons learned as long-term memory, auto-loaded in future sessions. A background process periodically reflects on conversations to mine things worth remembering. Memories can be created, searched, updated, and forgotten, with recall-based decay.
75
- - **Project context (Snapshot + Skill)** — Two complementary systems help the agent understand your project: **Project Snapshot** automatically scans files and generates LLM-enhanced summaries (project description, tech stack, commands, module responsibilities, directory tree); **Project Skill** is a manually maintained knowledge base capturing design decisions, architectural insights, pitfalls, and conventions. Snapshot provides *what/where* (facts), Skill provides *why/how* (insights) no duplication, ~46% token savings.
75
+ - **Project context (`MOCODE.md`)** — A single project-level memory file at `MOCODE.md` captures both static facts (project description, commands, module list, directory tree) and human/AI-written insights (conventions, architectural decisions, pitfalls). Generate it once with `/init`, then keep it up to date by hand or by asking the agent to refresh it. Loaded automatically into the system prompt on every turn.
76
76
  - **Session notepad (notes.md)** — For complex multi-step tasks (≥3 file changes / ≥5 tool calls), the agent maintains a working notepad at `.mocode/sessions/<sessionId>/notes.md` (file-based, survives context compression). It can record intermediate findings, design decisions, open questions, and structured plans. A live progress chip in the TUI status bar shows `plan: [title] (3/7) ▸ [current step]` when a `## Plan:` section is present. The agent manages the file directly with write_file/edit_file/read_file.
77
77
  - **Interruptible and reversible** — Ctrl+C interrupts the current turn at any time (kills child processes recursively, rolls history back to before the turn started, leaves no half-finished tool calls). `/rollback` restores file changes from per-turn snapshots, with a per-file keep/undo choice — no git dependency required.
78
78
  - **Sandbox protection** — File reads/writes go through a sandbox that blocks out-of-bounds paths (`../../`, absolute paths outside the root, symlink escapes, etc.), so the agent never touches files outside your working directory.
@@ -89,7 +89,7 @@ MoCode isn't a chat box with a coat of paint — it's an agent that actually get
89
89
  ## Documentation
90
90
 
91
91
  - [中文使用指南](./docs/usage.md) — 菜单式快速上手、命令速查、模式、会话、项目上下文与排障。
92
- - [Project context](./docs/USAGE_SNAPSHOT_SKILL.md) — Snapshot and Project Skill reference.
92
+ - [Project context](./docs/usage.md#项目上下文) — `MOCODE.md` and Skills.
93
93
 
94
94
  ## Installation
95
95
 
@@ -235,8 +235,6 @@ The five `memory_*` tools are gated on `MEMORY_ENABLED=true` at startup; toggle
235
235
  | `/pet` | Toggle the optional desktop pet (floating window mirroring agent state) |
236
236
  | `/pet skin` | Pick a pet skin (↑↓ · Enter) |
237
237
  | `/pet quit` | Fully shut down the pet process (not just disconnect) |
238
- | `/snapshot_refresh` | Refresh project snapshot (re-scan files + regenerate LLM summary) |
239
- | `/snapshot` | Toggle project snapshot on/off |
240
238
 
241
239
  Type `/` to trigger the dropdown menu, keep typing to filter; Esc to cancel.
242
240
 
@@ -264,21 +262,6 @@ MoCode automatically scans the following directories for skills (each skill is a
264
262
 
265
263
  A skill's `description` is injected into the system prompt (progressive disclosure, tier 1); the model calls `use_skill` to load the full body (tier 2) only when the task is relevant. Use `/skills` to see discovered skills.
266
264
 
267
- ## Project Context (Snapshot + Skill)
268
-
269
- MoCode uses two complementary systems to help the agent understand your project:
270
-
271
- - **Project Snapshot** (automatic + LLM-enhanced, enabled by default): Scans your project files and generates a structured summary including project description, tech stack, key commands, module responsibilities, and directory tree. Stored in `.mocode/snapshot.json` and reused across sessions. Use `/snapshot` to toggle it and `/snapshot_refresh` after major changes.
272
- - **Project Skill** (manual + AI-assisted, disabled by default): A knowledge base for design decisions, architectural patterns, pitfalls, conventions, and workflow notes. Enable it with `/project_skill on` (or `MOCODE_PROJECT_SKILL=true`), generate an initial draft with `/project_skill init`, then refine `.mocode/project-skill.md`. The agent can update it through `project_skill_update` during conversations.
273
-
274
- **Complementary principle**: Snapshot provides *what/where* (facts: files, structure, commands), Skill provides *why/how* (insights: decisions, behaviors, gotchas). No duplication, ~46% token savings compared to the previous approach.
275
-
276
- Control via environment variables:
277
- - `MOCODE_PROJECT_SNAPSHOT=false` — disable snapshot
278
- - `MOCODE_PROJECT_SKILL=true` — enable Project Skill
279
-
280
- See [docs/USAGE_SNAPSHOT_SKILL.md](./docs/USAGE_SNAPSHOT_SKILL.md) for detailed usage.
281
-
282
265
  ## Working discipline (Build-and-Self-Verify)
283
266
 
284
267
  Every coding task runs through four sequential phases. Skipping or merging them is a failure mode — the system prompt injects this discipline on every turn (see `src/agent/work-discipline.ts`):
package/README.zh-CN.md CHANGED
@@ -88,7 +88,7 @@ mocode 不是一个套壳聊天框,而是一个能真正动手干活的 agent:
88
88
  ## 使用文档
89
89
 
90
90
  - [菜单式使用指南](./docs/usage.md) — 快速上手、命令速查、模式、会话、项目上下文与排障。
91
- - [项目上下文:SnapshotProject Skill](./docs/USAGE_SNAPSHOT_SKILL.md)
91
+ - [项目上下文:`MOCODE.md`Skills](./docs/usage.md#项目上下文)
92
92
 
93
93
  ## 安装
94
94
 
@@ -1,3 +1,3 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  // Mocode Work 的本地 Agent Host。stdout 仅输出 NDJSON 协议事件;诊断写 stderr。
3
3
  await import('../dist/host/stdio.js');
@@ -165,7 +165,7 @@ function readDiffContext(tc, parsed) {
165
165
  * - pruner 在每个 runAgentCore 实例化一次(本闭包持有),会话级状态。
166
166
  * - 开关关闭时 pruner 不创建(零开销、零行为变化)。
167
167
  * 出口再经 Lifecycle Engine 做引用追踪:LIVE→REFERENCED→OBSOLETE→STUB 四态。
168
- * - lifecycle 也在每个 runAgentCore 实例化一次,登记 grep/glob/codegraph 等 producer
168
+ * - lifecycle 也在每个 runAgentCore 实例化一次,登记 grep/glob/web_search/web_fetch 等 producer
169
169
  * 与 read/edit/write 的 consumer 关系;孤立+老化自动 STUB(观察类工具永不到 STUB)。
170
170
  * - 开关关闭时 lifecycle=null 完全跳过。 */
171
171
  /** RETRY-01: 把 thrash hint + 反思指针一次性拼到 output 尾部。
@@ -250,7 +250,8 @@ export async function runAgentCore(opts) {
250
250
  ? null
251
251
  : (opts.preCompletionChecklist ?? _checklistMiddleware.handler);
252
252
  const maxSteps = opts.maxSteps ?? config.maxSteps;
253
- // 中断还原:LLM 中途可能调 switch_mode 切了模式,abort 时连同模式一起还原回轮首。
253
+ // 中断还原:repl /plan / /auto / Shift+Tab 等用户面触发 setAgentMode 中途切了模式,
254
+ // abort 时连同模式一起还原回轮首。模型不再持有 switch_mode 工具,无法自切。
254
255
  const savedMode = getAgentMode();
255
256
  // 本轮计时:从入口到完毕(正常 return / 达上限),供 finally 打 ✻ Worked for 摘要行。
256
257
  const t0 = Date.now();
@@ -318,7 +319,7 @@ export async function runAgentCore(opts) {
318
319
  // 相关性裁剪 pruner:每个 runAgentCore 实例一个,纯静态、不调 LLM、自动判定 read_file 失效。
319
320
  // 开关关闭时为 null,所有 pushToolResult 调用走无 pruner 路径(零行为变化)。
320
321
  const relprune = config.contextRelprune ? createRelevancePruner() : null;
321
- // 观察者生命周期引擎:每个 runAgentCore 实例一个,纯静态、自动维护 grep/glob/codegraph
322
+ // 观察者生命周期引擎:每个 runAgentCore 实例一个,纯静态、自动维护 grep/glob/web_search/web_fetch
322
323
  // producer 与 read/edit/write 的 consumer 引用关系;孤立+老化的非观察类工具自动 STUB。
323
324
  // 开关关闭时为 null,所有 pushToolResult / mutation 调用走无 lifecycle 路径(零行为变化)。
324
325
  // 引擎需要从已有会话 history 恢复观察结果的年龄和 path 索引;不能只追踪本次
@@ -451,8 +452,26 @@ export async function runAgentCore(opts) {
451
452
  const modelStartedAt = Date.now();
452
453
  const provider = safeProviderId(requestBaseURL);
453
454
  emitTrace('model_start', { model: requestModel, provider });
455
+ const dynamicSystemSuffix = [
456
+ opts.dynamicSystemSuffix?.().trim() ?? '',
457
+ historyRebuilt
458
+ ? '## Post-compaction recovery\nContext was compacted before this request. Re-establish the current objective and unresolved work from retained evidence or the session note, avoid repeating completed investigation, and re-read exact file context before any dependent edit.'
459
+ : '',
460
+ ].filter(Boolean).join('\n\n');
461
+ const systemMessage = history[0];
462
+ const requestHistory = dynamicSystemSuffix
463
+ && systemMessage?.role === 'system'
464
+ && typeof systemMessage.content === 'string'
465
+ ? [
466
+ {
467
+ ...systemMessage,
468
+ content: `${systemMessage.content}\n\n${dynamicSystemSuffix}`,
469
+ },
470
+ ...history.slice(1),
471
+ ]
472
+ : history;
454
473
  try {
455
- result = await chat(history, {
474
+ result = await chat(requestHistory, {
456
475
  onText,
457
476
  onToolCall,
458
477
  onRetry: (retry) => emitTrace('model_retry', {
@@ -513,7 +532,7 @@ export async function runAgentCore(opts) {
513
532
  // 用本次实际发送的 tools 计算分母,再以 EWMA 更新 provider/model/tool-set 校准。
514
533
  // 只持久化比例与样本数;无 usage 或短 prompt 时保持既有值。
515
534
  if (result.usage?.promptTokens && result.usage.promptTokens > 100) {
516
- const estimated = estimatePromptTokens(history, activeTools);
535
+ const estimated = estimatePromptTokens(requestHistory, activeTools);
517
536
  const updated = updateTokenCalibration(requestBaseURL, requestModel, activeTools, estimated, result.usage.promptTokens);
518
537
  runtimeContextState.correction = updated.correction;
519
538
  runtimeContextState.calibrationSamples = updated.samples;
@@ -15,6 +15,7 @@ import { createPetHooks } from '../pet/state.js';
15
15
  import { t } from '../i18n/index.js';
16
16
  import { isToolErrorOutput } from '../tools/result.js';
17
17
  import { appendCurrentSessionTraceEvent } from '../session/index.js';
18
+ import { buildActiveNotesPlanReminder } from '../session/notes-plan.js';
18
19
  /** 当前 turn 的 batch id(runAgent 内闭包变量;一条 turn 一轮 tool batch 结束即清空)。 */
19
20
  let currentBatchId = null;
20
21
  let turnFileChanges = [];
@@ -280,6 +281,7 @@ onContextUpdate) {
280
281
  userInput,
281
282
  signal,
282
283
  onContextUpdate,
284
+ dynamicSystemSuffix: buildActiveNotesPlanReminder,
283
285
  hooks: combinedHooks,
284
286
  autoValidate: config.autoValidate,
285
287
  onTraceEvent: appendCurrentSessionTraceEvent,
@@ -2,19 +2,18 @@
2
2
  * agent 模式的共享状态(零依赖纯叶子)。
3
3
  *
4
4
  * 把 `agentMode` 从 repl 的模块变量提到这里,让三方都能用、且不破坏依赖单向:
5
- * - `tools/builtins/switch-mode.ts` 写它(setAgentMode)——LLM agent 循环里自切 plan↔auto。
5
+ * - `repl/index.ts` 读写它 + 注册 onModeChange 监听器( applyMode 重写 history[0] +
6
+ * refreshStatusBase 刷状态行 modeTag),并通过 /plan / /auto / Shift+Tab(c cycleMode) 触发切换。
6
7
  * - `agent/index.ts` 每步读它(getAgentMode)——决定 chat() 用全量 chatTools 还是 planChatTools 只读子集,
7
- * 以及串行分支的 plan 防御 backstop。这样 LLM 中途切模式后,下一次 chat() 立即看到新工具集。
8
- * - `repl/index.ts` 读写它 + 注册 onModeChange 监听器(做 applyMode 重写 history[0] + refreshStatusBase
9
- * 刷状态行 modeTag)。
8
+ * 以及串行分支的 plan 防御 backstop。这样切换模式后,下一次 chat() 立即看到新工具集。
9
+ * - 模型不再持有 switch_mode 工具(已砍):模式切换只能由用户面触发。
10
10
  *
11
- * 依赖方向无环:本模块不 import 任何业务模块。`agent/index → tools/registry → tools/builtins/switch-mode
12
- * → agent/mode` 链终点是本叶子,不回到 agent/index。`tools → agent/mode` 与既有 `tools → ui`(ask-human)、
13
- * `tools → rollback`(registry)同性质——都是引叶子。
11
+ * 依赖方向无环:本模块不 import 任何业务模块。
14
12
  *
15
- * listener 同步触发:setAgentMode 在变更模式后同步调 listener(无 async)。switch_mode 工具在 executeTool
16
- * 内调 setAgentMode → listener 同步 applyMode(重写 history[0])+ refreshStatusBase;execute 返回字符串后,
17
- * agent 串行分支继续,下一步 chat() 读到新模式 + 新系统提示,一致。
13
+ * listener 同步触发:setAgentMode 在变更模式后同步调 listener(无 async)。repl
14
+ * cycleMode / /plan / /auto 在 executeTool 路径之外调 setAgentMode → listener 同步
15
+ * applyMode(重写 history[0])+ refreshStatusBase;切换后下一步 chat() 读到新模式 +
16
+ * 新系统提示,一致。
18
17
  */
19
18
  let currentMode = 'auto';
20
19
  let listener = null;
@@ -20,18 +20,18 @@ import { summarizeToolCall, summarizeToolResult, truncateDisplay } from '../ui/r
20
20
  import { createContextState } from '../session/compact.js';
21
21
  import { inOverlay, mergeSubAgentChangeSet } from '../agents/coordinator.js';
22
22
  /** 子 agent 系统提示后缀:角色与约束。 */
23
- const SUBAGENT_SUFFIX = `
23
+ const SUBAGENT_SUFFIX = `
24
24
 
25
25
  ## ⛯ SUB-AGENT MODE (you are a sub-agent)
26
26
  You are a sub-agent spawned by the main agent to handle an isolated sub-task. You have your own conversation history (independent of the main thread).
27
- - Focus solely on the assigned sub-task. Do NOT attempt to call the "sub-agent" tool (no recursive spawning).
27
+ - Focus solely on the assigned sub-task. Do NOT attempt to call the "sub-agent" tool (no recursive spawning).
28
28
  - Use the tools available to you to complete the sub-task.
29
29
  - When done, your final text reply will be returned to the main agent as a summary — make it concise and actionable: what you did, key findings, files changed, and any issues. The main agent will decide the next step based on your summary.`;
30
- const SUBAGENT_ROLE = `## Sub-agent execution
31
- You are executing one delegated sub-task with the same engineering standards and capabilities as mocode.
32
- - Treat Task context as authoritative facts already established by the main agent; do not rediscover them without evidence they are stale.
33
- - Focus on the delegated scope, but continue until it is genuinely complete. Do not stop to save tokens.
34
- - Do not recursively call sub-agent. A write task runs in an isolated overlay; the coordinator merges and performs final unified verification.
30
+ const SUBAGENT_ROLE = `## Sub-agent execution
31
+ You are executing one delegated sub-task with the same engineering standards and capabilities as mocode.
32
+ - Treat Task context as authoritative facts already established by the main agent; do not rediscover them without evidence they are stale.
33
+ - Focus on the delegated scope, but continue until it is genuinely complete. Do not stop to save tokens.
34
+ - Do not recursively call sub-agent. A write task runs in an isolated overlay; the coordinator merges and performs final unified verification.
35
35
  - Return concise findings, changes, verification evidence, and blockers to the coordinator.`;
36
36
  /**
37
37
  * 派生一个子 agent 执行独立子任务。
@@ -66,7 +66,7 @@ export async function spawnAgent(opts) {
66
66
  let toolsOverride;
67
67
  const mode = opts.mode ?? 'read';
68
68
  const requested = opts.tools?.length ? new Set(opts.tools) : null;
69
- const readOnly = new Set(['read_file', 'glob', 'grep', 'codegraph', 'web_search', 'web_fetch', 'use_skill', 'memory_search', 'memory_list']);
69
+ const readOnly = new Set(['read_file', 'glob', 'grep', 'web_search', 'web_fetch', 'use_skill', 'memory_search', 'memory_list']);
70
70
  toolsOverride = chatTools.filter((tool) => tool.function.name !== 'sub-agent' &&
71
71
  (!requested || requested.has(tool.function.name)) &&
72
72
  (mode === 'write' || readOnly.has(tool.function.name)));
@@ -139,7 +139,7 @@ export async function spawnAgent(opts) {
139
139
  onToolOutcome: (tool, args) => {
140
140
  if (tool === 'read_file' && typeof args.path === 'string')
141
141
  readSet.add(args.path);
142
- else if (['glob', 'grep', 'codegraph'].includes(tool))
142
+ else if (['glob', 'grep'].includes(tool))
143
143
  readSet.add('workspace');
144
144
  },
145
145
  });
@@ -31,33 +31,30 @@ export function inferModelFamily(model) {
31
31
  }
32
32
  /**
33
33
  * 4 阶段核心纪律(英文)。4 个 model family 共用此文本,只在首句与标题
34
- * 标签上做轻量变体。长度 ~380 词,确保不显著抬升 token 预算。
34
+ * 标签上做轻量变体。保持短小,详细的完成检查由动态 checklist 按需注入。
35
35
  */
36
36
  const CORE_SECTION = `## Working discipline — coding tasks (Build-and-Self-Verify)
37
37
 
38
- Treat "verification" as a first-class part of the task, not an afterthought. Every coding task runs through four sequential phases; skipping or merging phases is a failure mode.
38
+ Treat "verification" as a first-class part of the task, not an afterthought. Use the smallest evidence-driven loop below.
39
39
 
40
40
  ### Phase 1 — Plan & Discover
41
- - Restate the goal in one sentence; identify the acceptance signal (test name, command output, file presence, behavior change).
42
- - Read the relevant code BEFORE writing anything; record assumptions you cannot verify (write them down, do not silently assume).
43
- - If the spec is ambiguous, surface the ambiguity to the user via \`ask_human\` before implementing — do not guess on irreversible choices (deletions, public API changes, schema/permission boundaries).
41
+ - State the goal and a concrete acceptance signal, then inspect the relevant code before changing it.
42
+ - Ask only when an unresolved choice is high-impact or user-owned; otherwise follow repository evidence and proceed.
44
43
 
45
44
  ### Phase 2 — Build
46
- - Make the smallest change that satisfies the spec. Do not bundle unrelated refactors.
47
- - If the project has tests, your change is incomplete without a test for the new/changed behavior. "Should" clauses in the goal are obligations, not aspirations.
48
- - After every mutation, re-read the relevant region (snapshot drift is real your memory of the file is stale after the previous edit).
45
+ - Make the smallest coherent change; avoid unrelated refactors.
46
+ - Add or update a focused test when behavior changes and the project has an applicable test suite.
47
+ - Re-read only when a dependent edit needs fresh exact content or state may be stale.
49
48
 
50
49
  ### Phase 3 — Verify
51
- - Run a real, executable verification: typecheck, the project's test command, a focused command that exercises the change, or a smoke script. Read the full output, not just the last line.
52
- - Compare the result to the SPEC, not to your own diff. A diff that "looks right" against itself is not evidence.
53
- - If the project has no test infra you can use, build the smallest possible reproducer (a script, a focused command) that exercises the change. "I read the code and it looks correct" is not verification.
50
+ - Run the smallest executable check that proves the requested behavior, then read its complete result.
51
+ - Compare evidence with the user's request, not merely with the diff.
54
52
 
55
53
  ### Phase 4 — Fix
56
- - Any failure go back to the spec, not to the diff. Re-derive what the spec requires; do not "tweak" the implementation to silence the failing test.
57
- - After a fix, re-run Phase 3 end-to-end. Do not declare done on a single passing run after multiple failed ones unless you understand and can name the root cause of every previous failure.
58
- - Cap blind retries: after three identical failed attempts on the same tool with the same arguments, change the approach (different tool, different invariant, or \`ask_human\`) instead of retrying.
54
+ - Diagnose the root cause, make a focused correction, and rerun the relevant check.
55
+ - After three identical failures, change the approach instead of repeating the same call.
59
56
 
60
- **Hard rule (non-negotiable):** "I read the code and it looks right" is not a completion signal. A task is complete only when an executable verification against the spec has actually run, its full output has been read, and the result matches the spec. Report this evidence explicitly in your final reply (which command, which output, which spec line it satisfied).`;
57
+ **Hard rule (non-negotiable):** "I read the code and it looks right" is not a completion signal. Report the verification performed, or state clearly why it could not be run.`;
61
58
  /**
62
59
  * 把核心段适配到指定 model family:只改首行(语序 / 强动词)与段标题
63
60
  * 末尾的 [model: X] 标签。Phase 内容保持原样,4 份共享同一份结构化文本。
@@ -67,21 +64,17 @@ function adapt(model, opener) {
67
64
  .replace('## Working discipline — coding tasks (Build-and-Self-Verify)', `## Working discipline — coding tasks (Build-and-Self-Verify) [model: ${model}]`)
68
65
  .replace('Treat "verification" as a first-class part of the task, not an afterthought.', opener);
69
66
  }
70
- /** ASK-01: 卡点白名单段。PROMPT-01 4 阶段纪律之后追加,告诉模型在哪些
71
- * 边界情形应当优先调 `ask_human`,而不是猜测。语种统一英文(与 PROMPT-01
72
- * 保持一致,避免多语种漂移);5 个固定条目,与 checklist 第 6 项耦合。
73
- */
67
+ /** ASK-01: only user-owned, high-impact choices should interrupt autonomous execution. */
74
68
  const ASK_WHITELIST_SECTION = `## When to ask instead of guess
75
69
 
76
- The following situations are not guessable. When you encounter any of them, call \`ask_human\` BEFORE writing code; do not silently pick one option and proceed.
70
+ Call \`ask_human\` before coding only when repository evidence cannot resolve a user-owned, high-impact choice:
71
+ 1. irreversible deletion, migration, security, permission, or external side effect;
72
+ 2. public API compatibility (keep, deprecate, rename, or remove);
73
+ 3. multiple reasonable options that materially change product behavior.
77
74
 
78
- 1. **Cross-package impact** the change touches public APIs, exports, or interfaces of other packages/modules; the user must confirm the blast radius.
79
- 2. **Naming conventions** — the project has no obvious style for this artifact (e.g. new file in a folder with no precedent); naming is cheap to fix and expensive to mass-rename later.
80
- 3. **Keep or remove old API** — the change deprecates, renames, or removes a function/type; the user must decide.
81
- 4. **Test expectations** — the spec says "should work" or "should handle" but does not pin down the input/output contract; ask for a concrete example or assertion.
82
- 5. **Implicit success criteria** — the user described intent but not the verification signal (which command, which output, which line of the spec). Without this, you cannot run Phase 3 honestly.
75
+ For naming, implementation detail, and verification commands, follow repository precedent and choose the safest reversible default. Disclose any consequential assumption.
83
76
 
84
- Budget: at most 2 \`ask_human\` calls per turn. If you would exceed the budget, prefer the safer default (e.g. "preserve old behavior" / "add a test, do not change behavior") and explicitly disclose the choice in your final reply — do not silently guess without disclosure. The disclosure is what the checklist item 6 is about.`;
77
+ Budget: at most 2 \`ask_human\` calls per turn. Beyond that, use the safest reversible default and disclose it in the final reply.`;
85
78
  /**
86
79
  * 拼出纪律段 + ASK-01 卡点白名单。返回完整段(两段用 \`\\n\\n\` 隔开);
87
80
  * 工厂之前只返回纪律段,ASK-01 落地后变成纪律 + 白名单两段;