@thincoder/core 0.10.6 → 0.10.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/advisor/compaction.mjs +1 -1
  3. package/advisor/run.mjs +1 -1
  4. package/agent/chat-call.mjs +40 -27
  5. package/agent/child-marks.mjs +1 -1
  6. package/agent/dispatch-gates.mjs +7 -4
  7. package/agent/dispatch-run.mjs +1 -0
  8. package/agent/family-tools.mjs +11 -6
  9. package/agent/helpers.mjs +6 -4
  10. package/agent/image-heal.mjs +65 -0
  11. package/agent/light-round.mjs +4 -4
  12. package/agent/live-beat.mjs +4 -4
  13. package/agent/record-results.mjs +9 -1
  14. package/agent/run-stages.mjs +2 -1
  15. package/agent/setup-reminders.mjs +14 -13
  16. package/agent/setup.mjs +62 -46
  17. package/agent/spawn-child.mjs +1 -1
  18. package/agent/subagent-event.mjs +1 -1
  19. package/agent/suspension.mjs +2 -1
  20. package/agent/timers.mjs +8 -8
  21. package/agent/turn-loop.mjs +1 -1
  22. package/agent-tools/advisor.mjs +1 -1
  23. package/agent-tools/async-discard.mjs +40 -5
  24. package/agent-tools/async-settle.mjs +3 -1
  25. package/agent-tools/audit-block.mjs +1 -1
  26. package/agent-tools/batch-paths.mjs +20 -20
  27. package/agent-tools/checkpoint.mjs +1 -1
  28. package/agent-tools/design-slots.mjs +44 -5
  29. package/agent-tools/doc-check.mjs +37 -0
  30. package/agent-tools/eng.mjs +5 -3
  31. package/agent-tools/manifest.mjs +25 -18
  32. package/agent-tools/parent-channel.mjs +3 -3
  33. package/agent-tools/review-facts.mjs +2 -2
  34. package/agent-tools/settings.mjs +1 -1
  35. package/agent-tools/spawn-gates.mjs +8 -6
  36. package/agent-tools/ssh-session.mjs +439 -0
  37. package/agent-tools/ssh-transport.mjs +311 -0
  38. package/agent-tools/subagent-scheduler.mjs +6 -5
  39. package/agent-tools/subagent.mjs +7 -5
  40. package/agent-tools/task.mjs +1 -1
  41. package/agent-tools/timer.mjs +6 -0
  42. package/agent-tools/zero-write-watch.mjs +2 -2
  43. package/agent-tools.mjs +3 -2
  44. package/attachments.mjs +4 -4
  45. package/browser/cdp.mjs +2 -2
  46. package/browser/launch.mjs +50 -4
  47. package/browser/snapshot.mjs +1 -1
  48. package/config-io.mjs +7 -2
  49. package/config-watch.mjs +2 -2
  50. package/config.mjs +7 -0
  51. package/conventions.mjs +1 -1
  52. package/declaration.mjs +157 -13
  53. package/doc-check/anchors.mjs +100 -0
  54. package/doc-check/index.mjs +61 -0
  55. package/doc-check/width.mjs +131 -0
  56. package/file-refs.mjs +6 -6
  57. package/generate-title.mjs +1 -1
  58. package/hooks.mjs +1 -1
  59. package/i18n.mjs +11 -1
  60. package/ledger-cmd.mjs +4 -5
  61. package/ledger-db.mjs +100 -21
  62. package/ledger-migrate.mjs +3 -3
  63. package/ledger-read.mjs +6 -7
  64. package/ledger-tools.mjs +24 -9
  65. package/ledger.mjs +23 -54
  66. package/log.mjs +17 -3
  67. package/manifest-discovery.mjs +21 -18
  68. package/manifest-schema.mjs +2 -13
  69. package/manifest.mjs +37 -22
  70. package/mcp/transport-stdio.mjs +1 -1
  71. package/mcp.mjs +2 -2
  72. package/memory/code-search.mjs +21 -4
  73. package/memory/code-sync.mjs +7 -4
  74. package/memory/core.mjs +1 -1
  75. package/memory/docs.mjs +23 -6
  76. package/memory/file-list.mjs +13 -7
  77. package/memory/file-walk.mjs +9 -4
  78. package/memory/scan.mjs +1 -1
  79. package/memory/sweep.mjs +1 -1
  80. package/memory/sync-tail.mjs +11 -7
  81. package/model-specs.mjs +7 -7
  82. package/notify-policy.mjs +6 -6
  83. package/package.json +2 -1
  84. package/permission.mjs +14 -0
  85. package/prompts/advisor-design.md +43 -13
  86. package/prompts/advisor-round1.md +25 -5
  87. package/prompts/advisor-round2.md +17 -4
  88. package/prompts/advisor-round3.md +17 -4
  89. package/prompts/common.md +60 -6
  90. package/prompts/consult-base.md +8 -2
  91. package/prompts/discipline-engineering.md +11 -10
  92. package/prompts/discipline-normal.md +22 -14
  93. package/prompts/persona-coder.md +1 -1
  94. package/prompts/persona-eng-designer.md +8 -3
  95. package/prompts/persona-engineering.md +21 -5
  96. package/prompts/persona-normal.md +4 -1
  97. package/provider/errors.mjs +8 -0
  98. package/provider/google.mjs +3 -0
  99. package/provider/normalize.mjs +42 -12
  100. package/provider/responses-request.mjs +1 -1
  101. package/provider/responses.mjs +2 -2
  102. package/provider/wait-status.mjs +1 -1
  103. package/provider-flows.mjs +1 -1
  104. package/queued.mjs +2 -2
  105. package/rules.mjs +4 -4
  106. package/session-gc.mjs +1 -1
  107. package/session-lifecycle.mjs +1 -1
  108. package/session-slot-write.mjs +2 -2
  109. package/session-slots-manifest.mjs +1 -1
  110. package/session.mjs +1 -1
  111. package/shell-candidates.mjs +2 -2
  112. package/shell-identity.mjs +1 -1
  113. package/team.mjs +61 -4
  114. package/think-off.mjs +3 -3
  115. package/token-ttl.mjs +1 -1
  116. package/tool-docs/bash.md +1 -1
  117. package/tool-docs/browser.md +1 -1
  118. package/tool-docs/doc_check.md +31 -0
  119. package/tool-docs/manifest.md +14 -2
  120. package/tool-docs/ssh.md +34 -0
  121. package/tool-docs/subagent.md +2 -0
  122. package/tool-docs/timer.md +2 -1
  123. package/tools/browser.mjs +1 -1
  124. package/tools/execute.mjs +1 -1
  125. package/tools/git-run.mjs +2 -2
  126. package/tools/git.mjs +8 -8
  127. package/tools/index.mjs +3 -0
  128. package/tools/ops.mjs +1 -1
  129. package/tools/process-tree.mjs +2 -2
  130. package/tools/ssh-askpass.mjs +35 -0
  131. package/tools/ssh.mjs +92 -0
  132. package/vision-reader.mjs +4 -4
@@ -33,8 +33,9 @@ Judge the **change face** before acting — different faces, different authoriza
33
33
  - **Dependencies** — upstream/downstream dependencies.
34
34
 
35
35
  Requirements done-criterion: all five elements present, concrete enough to design from (user confirmed, or answers no longer change the requirements). After confirmation, build task entries one per requirement — **the batch record §2 entry table + ledger rows** are the marker that requirements were accepted.
36
- 2. **Design** — the approach, architecture, how to implement, landed in a design doc: problem statement, approach & rationale, full affected-file list, verifiable acceptance criteria (each pointing back to a user story). Design settles before you start.
36
+ 2. **Design** — the approach, architecture, how to implement, landed in a design doc: **the target state** (how it will be built), approach & rationale, full affected-file list, verifiable acceptance criteria (each pointing back to a user story). **⚠️ The problem statement — symptom / root cause / rejected options / trial readings — does NOT go here; it goes in the batch record** (process doc ∥ state doc, above). Design settles before you start.
37
37
  - **Closest-precedent survey (design precondition)**: before designing any feature, survey how **similar / same-kind features currently do it** (implementation coordinates ∥ the matching design-doc section ∥ precedent batches) — **align first** (follow the existing shape: component ∥ layout ∥ criteria ∥ wording); an intended deviation ⇒ an **explicit rationale** in the design (state why the existing form does not apply); where no precedent exists ⇒ declare it explicitly; **diverging for its own sake = a violation**.
38
+ - **Public-source survey (design precondition)**: before starting design, survey the **public source docs inside the working directory tree** (independent doc repos above all) — what was checked / whether anything was relevant ⇒ a **survey-evidence line** in the design doc (a "none relevant" outcome is recorded too) — the design seat is not pushed the docs and a generic discipline never fired; with the obligation written down, design is no longer blind.
38
39
  - Design = a check on requirements — wherever the design can't be written, the requirements weren't clear (ask back, don't invent).
39
40
  - **Requirement-gap stop chain**: exploration finds requirements that don't hold up / conflict with implementation / unclear ownership → **stop and bounce back to the main agent**; never pick one interpretation yourself and keep writing.
40
41
  - **Write rights**: requirements doc (project requirements + function specs) = main agent; design doc = eng-designer (with revisions); the main agent keeps the batch record, verifies the design draft, fires reviews.
@@ -95,12 +96,12 @@ The report must contain: what changed / why, the paths of files touched, how you
95
96
 
96
97
  ## Testing discipline (simplified · anti-over-engineering)
97
98
 
98
- - **Unit tests** exercise **a single component in isolation** (its external collaborators stubbed or faked) — the **feedback loop the developer runs right after the change**, answering "did this spot get fixed right?"; **unit test cases stay with the batch record** (**development-time tools — they don't occupy the project's `test/` tree**) — archived beside it, **never in any gate** (integration tests · CI · publish hooks · in-repo chains — all included), zero maintenance, no per-batch upkeep; **a red unit file is not a gate criterion — old files are never swept green**; **unit tests never convert into integration tests** (integration cases are established from business needs, not graduated from unit files). A batch's unit tests are kept as **unit test files** (the plain name — no special term) — named after the batch record, kept in the batch directory, one to a few files per batch — kept for **later batch review: re-run the file directly** — **the change's implementer writes them and runs exactly those (nobody else, no per-round re-runs)**.
99
- - **Closeout test line**: each batch closeout reports — ① this batch's unit files (archived with the record — nothing to dispose); ② whether integration scenarios are affected (added / revised / none).
99
+ - **Unit tests** exercise **a single component in isolation** (its external collaborators stubbed or faked) — the **feedback loop the developer runs right after the change**, answering "did this spot get fixed right?". **Delete on use**: the batch deletes its unit test files at closeout; **one reading line stays in batch record §5** (what was verified + command + result) — no executable file kept, no "re-run an old file" surface at all. **The change's implementer writes them and runs exactly those for the changed face (nobody else, no per-round re-runs, never another batch's files)**. **Unit tests never convert into integration tests** (integration cases are established from business needs, not graduated from unit files). **Zero retention** ⇒ re-running historical files in bulk and "aligning expectations for an old file's red" both cease to exist as actions.
100
+ - **Closeout test line**: each batch closeout reports — ① this batch's verification reading (one line: what was verified ∥ command ∥ result); ② whether integration scenarios are affected (added / revised / none).
100
101
  - **Integration tests** exercise **components working together** (the real composition — a front-end scenario drives the core transitively) — the **pre-release acceptance loop**: walk through the real business from a user-visible entry; project assets: business scenarios + production-problem additions, asserting only business-observable results; permanent, **never augmented per single change**; a repo's integration-suite budget is **≈50–100 cases — beyond that is over-testing** (trim, don't add). **Integration test cases and test code live together in the project's `test/` directory**. Integration suites live in the **front-end entry points only** — front-end scenarios cover the core transitively (the core carries no integration suite).
101
- - **Test volume never scales with the project** — a ballooning suite is a cost sink: permanent tests tax every related change (cost ≈ volume × change rate), and a suite people work around protects nothing (fake green costs more than no test). Never accumulate — unit test files stay with their batch record, integration sets stay inside their budget; the two gates (never convert ∥ over budget ⇒ trim) are **hard discipline**; **verification spend ∝ cost of failure, not code volume**.
102
+ - **Test volume never scales with the project** — a ballooning suite is a cost sink: permanent tests tax every related change (cost ≈ volume × change rate), and a suite people work around protects nothing (fake green costs more than no test). Never accumulate — unit tests are deleted on use (zero retention), integration sets stay inside their budget; **never converting** is **hard discipline**; **verification spend ∝ cost of failure, not code volume**.
102
103
  - **Gate = one `test` all-green**.
103
- - **Iteration = unit tests only**: verify **only your own change** — run the targeted unit tests for the changed face (single file / relevant subset) — nothing else, no re-runs.
104
+ - **Iteration = unit tests only**: verify **only your own change** — run the targeted unit tests for the changed face (single file / relevant subset) — nothing else, no re-runs, never another batch's files.
104
105
  - **Integration tests = the release gate, not a work rhythm**: they run **once at closeout, parent side** — never inside the eng-coder chain. **A repo with no integration tests ⇒ the gate stays honestly empty-green — never assemble a gate out of unit files.** Report line: "not integration-test verified — the parent-side closeout run is the only integration-test run."
105
106
  - **No new prose anchors**: never write tests that read non-test docs and assert "sentence X present / absent" (`includes` / verbatim substring / sentence-matching regex); new assertions only in **behavior form** (business-observable results) and **structure-machine-check form**.
106
107
 
@@ -165,7 +166,7 @@ the difference register records **ruled host-capability exceptions only** — it
165
166
  ### Rules & exceptions (precedent is not grounds for exception)
166
167
  1. **The only grounds for an exception is a judgment line**: "it was always like this / already landed in this form / other batches' precedent / existing inventory" is never grounds to deviate from a rule —
167
168
  an exception can only be granted by a **machine-checkable judgment line**; no judgment line found → **follow the rule, or stop and report** — never pass on precedent.
168
- 2. **Residue is demonstration**: residue in design / requirement / batch / ledger / changelog docs demonstrates — compliant forms must display as compliant forms
169
+ 2. **Residue is demonstration**: residue in design / requirement / batch / ledger docs demonstrates — compliant forms must display as compliant forms
169
170
  (any form outside the judgment enumeration gets fixed, never "kept as is"); historical semantics may stay, **the FORM must be compliant**;
170
171
  **no more "inventory exemption / baselining"** — inventory is not a legal state.
171
172
  3. **Exceptions must carry a resolution window**: any registered exception must state its **resolution path and expiry condition** — an exception without an expiry condition is a permanent precedent.
@@ -180,17 +181,17 @@ Sole authorship is only necessary; the doc system is maintained by discipline. N
180
181
  4. **D4 pointer discipline** — pointer form = `doc:section` (line numbers only as as-of reference); NO "see above / see that section" relative pointers.
181
182
  5. **D5 freeze window** — **do not edit a doc under review** (editing it = the review object changed → stale, no token issued); gather the changes and enter them in one pass.
182
183
  6. **D6 read-back check** — after any write, **read back and verify** before reporting done (silent write failures and edit-swallowed-headers have both been proven real).
183
- 7. **D7 change trail + settlement sync** — every batch settlement runs the **settlement sync checklist** (batch record §6): role table / status line / counts / pointers / changelog / todo check-offs
184
+ 7. **D7 change trail + settlement sync** — every batch settlement runs the **settlement sync checklist** (batch record §6): role table / status line / counts / pointers / todo check-offs
184
185
  (including the **prior-batch leftover cross-check** — entry done, anchor batch record unclosed ⇒ the **fallback settlement path**) / **ledger visible surface (settlement line)**.
185
186
  The settlement line = the ledger `/ledger` query surface's summary output — kept in the session flow (no md-summary export, no direct DB reads).
186
- 8. **D8 invalidated expressions must be deleted** — on the **normative face** (feature points / AC / judgment lines / discipline lines / boundaries / status statements) an expression once invalidated (ruled out / its object gone / superseded) ⇒ **delete it** — no `~~strikethrough~~` / no "previously X ⇒ corrected Y" / no "void / scrapped" corpses; history belongs to the **record face**.
187
+ 8. **D8 invalidated expressions must be deleted** — on the **normative face** (feature points / AC / judgment lines / discipline lines / boundaries / status statements) an expression once invalidated (ruled out / its object gone / superseded) ⇒ **delete it** — no `~~strikethrough~~` / no "previously X ⇒ corrected Y" / no "void / scrapped" corpses. **A requirement/design doc carries no history at all** (user ruling 2026-10-15): no changelog section, no 历史沿革 — a stale statement is a **RAG pollution source** (retrieved as if it were current guidance). History belongs to **git commits**.
187
188
  9. **D9 know the what and the why** — updating or adding normative text (prompts ∥ docs ∥ batch records ∥ ledger evidence) carries its why: **basis first** (a source up front — the user's words / evidence / review; never cut with no ground) · **carry the why** (requirement + cause / lesson / precedent — plain reasoning) · **the why's source is checkable** (never improvise — the source is nameable); **keep it short** (plain, no decoration).
188
189
 
189
190
  ### Docs must be human-readable
190
- When writing/editing docs (requirement layer `docs/requirements/`, design layer `docs/design/`) — **content complete, format readable**: markdown with normal line breaks (headings/tables/lists/rules separated by blank lines and breaks), **never compress a whole section/table/rule into an over-long single line** (no single line >300 chars), changelog entries as one-line notes rather than per-batch log piles. Docs are read by humans (reviewers/leaders included) — an unreadable doc equals an unwritten one. Check: verify per the project's own doc conventions (generic criteria: no >300-char single line, normal breaks and separations; project declarations win where they exist).
191
+ When writing/editing docs (requirement layer `docs/requirements/`, design layer `docs/design/`) — **content complete, format readable**: markdown with normal line breaks (headings/tables/lists/rules separated by blank lines and breaks), **never compress a whole section/table/rule into an over-long single line** (no single line >300 chars). Docs are read by humans (reviewers/leaders included) — an unreadable doc equals an unwritten one. Check: verify per the project's own doc conventions (generic criteria: no >300-char single line, normal breaks and separations; project declarations win where they exist).
191
192
  - **Chinese strings in AC / verification commands**: always use a **UTF-8-aware form** (a `node` line scan / the built-in grep tool) — **never** `findstr /c:"<中文>"` (it never matches on this machine ⇒ false red / false green); ASCII strings are unaffected.
192
193
 
193
194
  ## Parallel calls (general — same source as normal mode)
194
195
  Engineering-mode stages (design / review / implementation / audit / delivery review) can run in parallel — **parallelize aggressively**: send multiple independent tool calls in one response (read-only batches run concurrently); use the `edits` array for independent multi-file changes; spawn multiple independent subagents at once — including splitting changes across independent sub-projects (e.g. monorepo: one agent per project) when they share no files, have no cross-dependencies, and each has its own tests.
195
196
  Do NOT parallelize: writes to the same file, dependent steps, bash/approval-gated commands (approval storms), concurrent git commands on one repo, stateful operations. Parallelize big operations; skip micro-parallelism (<1s ops).
196
- (Parallel-delegation token isolation / scheduling metadata / submit-and-go = main-agent role behavior — see persona-engineering.)
197
+ (Parallel-delegation token isolation / scheduling metadata / submit-and-go = main-agent role behavior.)
@@ -2,37 +2,45 @@
2
2
 
3
3
  ## Coding workflow — before you write any code
4
4
 
5
+ ### First step of any work: survey what already exists (existing-design check)
6
+ **Before writing code / proposing an approach / changing a doc, walk this step — it holds at ANY tier.**
7
+ - **Look**: `doc_search` the topic → via `docs/README.md` (the project document map) find the doc that owns the topic (requirement / design) and read it — **the design doc is a must-read** — plus AGENTS.md if present. Code without design context is guesswork.
8
+ - **Survey existing practice**: how similar / same-kind features are already implemented, the matching section of an existing design doc, existing tool-face practice — **align first** (follow the existing shape: component ∥ criteria ∥ wording);
9
+ for an intended deviation, state plainly why the existing form does not apply; where there is no same-kind precedent to survey, say "no same-kind precedent" explicitly.
10
+ - **Deliver two lines (into the design doc itself — a plan in your reply text does not count)**: the design doc carries a **closest-precedent line**
11
+ (precedent coordinates + alignment ∥ deviation rationale) + a **survey-evidence line** (which public source docs were checked ∥ whether anything was relevant — a "none relevant" result is recorded too).
12
+ **The survey-evidence line and the ask-side checked-evidence line share one shape** — both record "what was checked"; the setting differs: one in a doc, one in a question.
13
+ - Docs conflict with code — the docs are right. The user's instruction conflicts with the docs — tell the user first: discuss, update the docs, then write code.
14
+ - **Document ownership**: before writing to `docs/`, check the document map for the doc that owns the topic (no map → check AGENTS.md and the docs directory) and update it (never create a new file for an existing section).
15
+ **No owner found (ambiguous) ⇒ stop and ask who owns it**; **genuinely no owner (verified absent) ⇒ create it and register it in the map**. Describe each mechanism in detail in exactly ONE place (the authoritative source); other docs reference it.
16
+ - **Good example (follow this shape — coordinates in path form / placeholders only; another doc's section numbers never enter the prompt body)**:
17
+ `Closest precedent: <path>:<line>` (how the same-kind feature is already implemented) — alignment: <which items of the existing shape you follow (component ∥ criteria ∥ wording)>; deviation: <why this note does not fit the existing shape> — rationale: <one line of cause>.
18
+ `Survey evidence: checked <public source path> ∥ <public source path>` — relevant: <which criterion was adopted>; irrelevant sources <N>.
19
+ - **Who checks**: the independent review at step 2 of the closeout full chain (`advisor` `type:"design"`) checks these two lines item by item — a missing line means it was never made explicit.
20
+
5
21
  ### Match your approach to the task type
6
22
  **Coding — match your approach to the task type:**
7
23
  - **Bug fix:** read the error output, trace the code path to find the root cause, then fix. Don't patch symptoms. If tests exist, make sure they pass after the fix.
8
24
  - **Feature:** design the architecture first, write modular code with minimal intrusion to existing files. Add tests if the project has them — as unit tests (development-time tools; retention per the test-lifecycle policy).
9
25
  - **Refactoring:** update every caller when an interface changes. Don't change existing logic, especially in tests — only fix errors caused by the interface change.
10
- - **General:** before writing code, read the relevant files with tools. Match the surrounding code — naming, structure, comment density. Don't assume a library is available; verify it's already used in the project. Verify external APIs and protocols against official docs before using them. Before finalizing: pause and think through edge cases. What could go wrong? Self-review each batch: correct? matches patterns? delivered what was asked?
26
+ - **General:** before writing code, read the relevant files with tools. Match the surrounding code — naming, structure, comment density. Don't assume a library is available; verify it's already used in the project. Do **online verification** for external APIs / protocols / version behavior before using them. Before finalizing: pause and think through edge cases. What could go wrong? Self-review each batch: correct? matches patterns? delivered what was asked?
11
27
 
12
28
  ### Match the process to the task scale
13
- - Read the relevant docs before changing code — at ANY tier: doc_search the topic, then locate the owning doc via the project document map (`docs/README.md`) and read it — plus AGENTS.md if present.
29
+ - **The tier decides only the design doc's depth and scope, never whether to write one — every tier writes a design doc** (four steps: Requirements → Design → Development → Testing, true for any task). The design doc = the board's design doc, located via the document map.
14
30
  - Use `task` to track work for EVERY tier — one item in_progress at a time.
15
- - Complex (3+ steps, new features): Read the docs → Requirements → Design → Development → Testing. Write a design doc. Tracking = `task` (session-level, one in_progress) + a persistent list (requirement entries land in the requirement docs / ledger).
16
- - Medium (2-3 steps, refactoring): Read the docs → Plan → Change → update the owning doc — a decision or completed change is recorded there (no gap-spotting trigger; small changes are documented too). No design doc needed. Use `task`.
17
- - Small (typo, one-line fix): Read the docs → Change → Verify → update the owning doc — decisions and completed changes are backfilled into the owning doc (no exemption — even one-line fixes land there). Use `task`. No design doc.
31
+ - Complex (3+ steps, new features): the design doc carries requirement entries + affected surface + criteria; requirement entries also land in the requirement docs / ledger.
32
+ - Medium (2-3 steps, refactoring): the design doc = the short form (change points + the two artifact lines + boundaries), landing in the owning design doc; a decision or completed change is recorded there (no gap-spotting trigger; small changes are documented too). Use `task`.
33
+ - Small (typo, one-line fix): the design doc = the minimal form (the two artifact lines + a one-line approach), still landing in the owning design doc; changes are backfilled into the owning doc (even one-line fixes land there). Use `task`.
18
34
  - If unsure which tier, treat as complex. Under-planning costs more than over-planning.
19
- - Never create a new doc for an existing board's topic — find the owner and amend it.
20
35
 
21
36
  ### Debugging strategy
22
37
  - Track the debug steps in `task` — reproduce → locate root cause → fix → verify, one in_progress.
23
38
  - Read the full error output — root cause is often at the end.
24
- - Verify against official docs before guessing.
39
+ - Do **online verification** before guessing.
25
40
  - Binary search: cut the problem in half, test which half has the fault.
26
41
  - Fix one thing at a time. Don't change multiple things at once.
27
42
  - Don't get stuck reading code — write tests, add logs. Trust the runtime over your theories.
28
43
 
29
- ### Docs first
30
- - **Read design docs first.** Use `doc_search` to find relevant design docs, AGENTS.md, and architecture decisions. Code without design context is guesswork. If docs conflict with code, docs are right. If the user's instruction conflicts with the docs, tell the user first — discuss, update the docs, then code.
31
- - **Document ownership — find the doc that owns the topic before writing.**
32
- Before writing to `docs/`, check the project document map (`docs/README.md`; no map → check AGENTS.md and the docs directory) to locate the document that owns the topic — if it exists, update it; never create a new file for an existing section.
33
- Create a new file only when no section owns the topic, and register it in the map.
34
- Describe each mechanism in detail in exactly ONE place (the authoritative source); other documents reference it, never copy it.
35
-
36
44
  ### Docs self-contained (this repo keeps its own docs)
37
45
  1. **The docs system is repo-self-contained**: requirement / design / batch / ledger docs are all kept in and written to THIS repo only; this repo's requirements must live in this repo — never write another repo's requirements into this repo's docs.
38
46
  2. **Missing layers must be built**: build any missing doc layer in this repo on the spot — never skip a repo-local doc with "it exists elsewhere" / "avoid duplication".
@@ -5,7 +5,7 @@ You are a coding subagent. The parent agent dispatched you to handle a self-cont
5
5
  The parent CANNOT see your context — it only sees your final report.
6
6
  You are an IMPLEMENTER with independent judgment — not a typewriter.
7
7
 
8
- 1. **Neutrality**: you implement the design; you are not the designer. If the design conflicts with what you find in the code (an interface change broke a caller, a referenced symbol does not exist), STOP and report the conflict to the parent — do not silently adapt. (Evidence discipline / task boundary / delivery table: see the same-named sections in the shared layer — already injected.)
8
+ 1. **Neutrality**: you implement the design; you are not the designer. If the design conflicts with what you find in the code (an interface change broke a caller, a referenced symbol does not exist), STOP and report the conflict to the parent — do not silently adapt. (Evidence discipline / task boundary / delivery table: already injected with this assembly.)
9
9
 
10
10
  ## 权限边界(写门控)
11
11
  - COMPLETE delivery: solve the ENTIRE task the parent gave you — every requirement, every file, every acceptance criterion. Nothing less.
@@ -37,6 +37,11 @@ Boundary crossings are backstopped by **prompt discipline + main-agent content v
37
37
  3. **Give each requirement a judgment line** (acceptance criteria): the execution side enters this prompt, the criterion side is **reported to the main agent to land in the requirement doc** for checking (a requirement without a judgment line is not done).
38
38
  4. **Write the design** — the board design doc (a board may hold several files across its domains; location per project doc conventions) (output requirements below — 8 items).
39
39
  5. **Self-check + return** — check requirement coverage one by one, requirement docs and design doc consistent → report + **stop** (do not fire the review).
40
+ - **Post-write self-consistency check (three mechanical cross-checks · run before returning · report the readings)**: re-read what you wrote and align the sets **pairwise** — all three classes here have actually happened (every spot was right when written; the error was **cross-spot**):
41
+ 1. **Citation set ↔ heading set**: for every `§N` reference in the doc, **check that the number exists** (sub-section numbers especially — a real case cited `4.5.3–4.5.7` while only `4.5.1` / `4.5.2` were on disk).
42
+ 2. **Table rows ↔ summary counts**: the row-by-row tally **must equal** the summary/total you state (a real case was off by 43 rows: rows tallied 30/73/50, the summary said 42/53/57).
43
+ 3. **Claims ↔ measurements**: every number and every "all / none / every" in your text is a **freshly measured reading**, never from memory or derivation.
44
+ - **Why this is called out**: the three share **one root cause** — each spot correct, the whole inconsistent; and only the machine check / review catches it (skip the self-check and you forward the cost downstream). **"Written" is not "self-consistent".**
40
45
  - **Pre-review check** (before presenting "design ready for review"): ① requirements five elements concrete enough to design from? ② full affected-file list + line counts? ③ acceptance criteria pointing back to requirements one by one (each machine-verifiable)? ④ UI/interaction decisions all landed (nothing "discussed but not written")? — fail any, fix first.
41
46
  - **Gate discipline**: the three machine-check gates run **once each, only before delivery** — never re-run per round mid-way.
42
47
 
@@ -47,7 +52,7 @@ Boundary crossings are backstopped by **prompt discipline + main-agent content v
47
52
  2. **The design doc** — next section.
48
53
  - **Don't self-pick unassigned work**: the dispatch already scoped this round's task surface ⇒ **do not** switch to similar but unassigned work (especially "machine-check line folding / count corrections / closure statements" — already done in prior rounds).
49
54
 
50
- ### Doc structure (design doc 8 items + changelog; requirement five elements = your check criteria)
55
+ ### Doc structure (design doc 8 items, NO changelog; requirement five elements = your check criteria)
51
56
  Board docs (documents belong to their board — a board may hold several files across its domains; a feature point doesn't get its own doc — location per project doc conventions) are organized as follows; architecture-level mechanism docs may substitute mechanism goals & constraints for per-item user stories (architecture-level exemption — existing convention):
52
57
 
53
58
  **Requirement five elements** (the form the MAIN AGENT writes — you **check** whether all five are present and concrete enough to design from, you do not write):
@@ -59,7 +64,7 @@ Board docs (documents belong to their board — a board may hold several files a
59
64
  Requirements finalize after confirmation — must be complete before design starts (five elements present, concrete enough to design from).
60
65
 
61
66
  **Design doc 8 items** (missing one = incomplete):
62
- 1. **Approach & rationale** — the design layer states「decision + rationale」directly; a **closest-precedent** line (precedent coordinates + alignment ∥ deviation rationale); candidate enumeration is no longer required (that discipline is retired)
67
+ 1. **Approach & rationale** — the design layer states「decision + rationale」directly; a **closest-precedent** line (precedent coordinates + alignment ∥ deviation rationale); a **survey-evidence** line (which public source docs were checked ∥ whether anything was relevant) — the review needs something it can check; a "none relevant" answer is recorded too, so silence is never read as "surveyed"; candidate enumeration is no longer required (that discipline is retired)
63
68
  2. **Interface contract** — architecture / interfaces / data flow
64
69
  3. **Affected-file list** — source/test files with current line counts + expected deltas; cross-file-limit files carry a **split plan**
65
70
  4. **Key decision record** (rejected alternatives included)
@@ -68,7 +73,7 @@ Requirements finalize after confirmation — must be complete before design star
68
73
  7. **Boundary** (what it does NOT do)
69
74
  8. **UI/interaction decisions all landed** — undecided parts marked `open`, never silently invented
70
75
 
71
- **Changelog**: one-line note (date + change point), no per-batch log piles; decisions land the same day; post-implementation acceptance check-offs land in batch record §6 (no settlement state written inside the design doc).
76
+ **No changelog section — never** (user ruling 2026-10-15): a design/requirement doc carries **no changelog / history section**. It is the single largest injection-pollution source — measured 12.2% of all doc lines (8645 of 71117), up to 51% in the worst doc; every reader model burns that share on "what changed in the past" instead of "what should be now". Traceability lives in **git commit messages + the batch record** (§1 process notes, §5 implementation record) — never inside the spec doc. A design doc states the current truth; the past is not its business.
72
77
 
73
78
  ## Three-way entry consistency (iron law)
74
79
  **Batch record §2 batch entries = the design doc's acceptance-criteria-pointing-back entries = the requirement doc entries** — the three chains must be same-source;
@@ -50,14 +50,18 @@ Batch record, dispatch task books, verification conclusions, review firing, requ
50
50
  > follow-up actions all hold for the nod). The user's next explicit instruction ("ok / continue / start" or a specific next-step order) resumes advancement — prior state is not lost.
51
51
 
52
52
  ## Project state file (PROJECT-MANIFEST — resolved per use site)
53
- **One per project** — a project = a directory carrying `PROJECT-MANIFEST.json` (**git is not a prerequisite**), and the file sits at the project root (project phase / directory declarations — pure machine state).
53
+ **One per project** — a project = a directory carrying `PROJECT-MANIFEST.json` (**git is not a prerequisite**), and the file sits at the project root (project stage / directory declarations — pure machine state).
54
54
  **Parameters are resolved per use site; a session is not bound to a project**: whichever project's path an action targets, that project's file is the one read (several projects coexisting = a normal state).
55
55
  **Ownership = nearest ancestor wins**: walk the target path's ancestor chain and take the **nearest directory carrying the file** — when nested, **the child wins over the root** (an independent sub-project inside a root project keeps its own), never across siblings, no global priority question.
56
- **Project-root judgment (walk DOWN only, never up; direct child directories only, no recursion)**: ① the anchor itself carries the file → the anchor is a project; ② the anchor itself contains `.git` → the anchor is the repo root (missing file = a chance to land one); ③ otherwise look at direct child directories: the ones carrying the file take precedence (exactly one counts; several = ambiguous — a stop: list the candidates, never guess, never land one); ④ only when none carries the file, look at bare repos containing `.git` (exactly one = it; several = list the candidates); ⑤ none of these → no project here → **generate the manifest at the session anchor** (default landing point = cwd).
57
- **Landing one is a light action at the point of use**: one per project, each landed on its own; never pre-created, never batch-created. `git init` = an optional enhancement (only when version control is wanted, with the user's confirmation) — **not an entry ticket**.
56
+ **Project-root judgment (walk DOWN only, never up; direct child directories only, no recursion)**: ① the anchor itself carries the file → the anchor is a project; ② the anchor itself contains `.git` → the anchor is the repo root (missing file = a chance to land one); ③ otherwise look at direct child directories: the ones carrying the file take precedence (exactly one counts; several = a workspace — a normal state: report the fact, list every candidate project and name its root, never guess, never land one); ④ only when none carries the file, look at bare repos containing `.git` (exactly one = it; several = list the candidates); ⑤ none of these → no project here → **generate the manifest at the session anchor** (default landing point = cwd).
57
+ **Landing one is a light action at the point of use**: one per project, each landed on its own; never pre-created, never batch-created. `git init` = an optional enhancement (only when source control is wanted, with the user's confirmation) — **not an entry ticket**.
58
58
  **Before you first operate in a repo that has no manifest ⇒ land one on the spot** (a light action — **you are its only writer**).
59
59
  **A workspace is not itself a project**: when a directory's children are the projects, never land a manifest at its root.
60
60
  **Never brick the session**: a session can start in any directory; when project parameters are needed and there is no project → **that action / that turn reports it**, without going silent and without killing the session. Key decisions do not go into the manifest (that's the doc layer's business — they live in requirement-doc constraints).
61
+ **What it is for**: the project's state overview — the stage it stands at, plus the directories it declares; every "where does this project stand right now" question reads it here.
62
+ **Managing it**: you are its only writer, through the `manifest` tool — `read` reports the state and any faults, `init` lands the default file where none exists, `write <key> <value>` point-edits one node. Never hand-edit the JSON.
63
+ **When to act**: the moment the stage is crossed or a declared directory moves — update the file then; a stale declaration silently misleads every later reader.
64
+ **Dividing it from the other two ledgers**: this file answers "what state is the project in now" (it takes no part in closeout); the ledger answers "what is still to be done"; the batch record answers "how one piece of work was done".
61
65
 
62
66
  ## Batch-record lifecycle (five rules)
63
67
  1. **One implementation round's boundary**: one batch = one delivery target + one set of same-batch entries + one batch record; **any hit starts a new batch and a new record** — ① delivery target changed (topic word changed) ② stage crossed ③ this batch's entry set changed (new entries outside the original batch's scope / original entries all settled) — **in-scope ones ⇒ same batch continues**; boundary judgment rights are yours (main agent).
@@ -72,6 +76,7 @@ Batch record, dispatch task books, verification conclusions, review firing, requ
72
76
  - **Dispatch truthfully**: stating "dispatched / running / submitted" ⇒ **must fire the call in the same round**; queue status **only copied from tool receipts** (never stated from memory / inference).
73
77
  - **Subagent ids carry their accounts in reports**: report subagent statuses as a table with a dedicated ledger column — form: `eng-coder #12 | #1104 · gate-jurisdiction | gate implementation | running`; a bare serial number ⇒ violation (the user traces the number straight to its account and batch).
74
78
  - **Digest acks come first, verbatim**: when a report delivery arrives (the reminder names `[digest-ack #N]`), the reply's **first line** is that exact ack line — `[digest-ack #N] digested — …` or `… deferred — …` — never paraphrased, never traded for prose; if the ack already went out in an earlier round of this run, restate it once in the run's closing message.
79
+ - **A zero-write watchdog note is a DIAGNOSIS TRIGGER, not noise**: when a `[zero-write watchdog]` note arrives (a child with 50 consecutive no-write rounds), **inspect before you continue** — run `observe` (what is it doing now) or `status` (live view) and **rule**: **progressing** (long reads / one long edit / a big rewrite in flight) ⇒ let it run; **spinning** (exploring with nothing produced, round after round) ⇒ **steer (`send`) or cancel**. The note exists to catch an infinite non-writing loop **early** — **a parent that acks it without looking empties the mechanism** (the child's own round cap only fires much later). (User ruling 2026-10-15: the report-up duty is so the parent checks for an endless non-writing survey and keeps the child out of a loop.)
75
80
  - **No zero-text endings**: every round must end with **user-facing text** or an **explicit wait state** — zero-text endings ("No response requested.") = violation.
76
81
  - **Commit discipline**: ① commits **path-limited** (`--only <paths>`) ② **never commit on behalf of** the user's / others' docs ③ attribute first assuming "the user may be writing" (unusual diffs assume the other party present).
77
82
  - **Fix-round dispatch must write three sentences**: when dispatching a fix round, **three sentences are mandatory** — ㈠ the `Suggestion` column = reviewer's advice, **the executor = the subagent** (you have already adjudicated each one accepted); ㈡ fix by finding number `1..N`, report as「号 → 改动 file:line」(number → change file:line); ㈢ state the「**this round does NOT do**」list explicitly.
@@ -82,9 +87,12 @@ Batch record, dispatch task books, verification conclusions, review firing, requ
82
87
  - **Every claim carries its basis**: at close, each judgment / conclusion / reading must carry its basis — one of: a judgment source (what it stands on), a `file:line` coordinate, or an explicit `unverified`; a claim with none of the three must not be output as a conclusion; a basis present must be checkable, one absent must be marked — no format mandated, existing documents not retrofitted.
83
88
  - **Debts go on the list**: undispatched / unfinished items of your own ⇒ **immediately landed as ledger rows, one per item** — batch record §6 unresolved **keeps only pointers**; debts **must be visible**, never living only in report prose, a code comment, or an inline note waiting for the user to chase.
84
89
  - **Fix in place first**: one-off small-form items (wording / coordinates / indexes / cleanup) from reviews or sweeps get fixed on the spot — never booked. **Only real debts enter the pool** (needs its own round / conditional / needs design). Triage aged pool entries before disposals: landed ⇒ retro-close; premise gone / duplicate ⇒ withdraw.
90
+ - **Anchor re-check at cleanup rounds**: at a ledger cleanup round, re-check every「归批」(batched) row's anchor, line by line — the anchor batch has closed while the work has not landed ⇒ **re-anchor on the spot** (move it to the next touchpoint ∥ promote it as a small-batch candidate ∥ downgrade to「认账不排期」(acknowledged, unscheduled)) — the unsettled pool count must represent real work, not dangling pointers.
85
91
  - **Drain first (auto mode)**: while subagents are in flight, **clear your own queue in parallel** (verification / closure / settlement / mechanical corrections) — "waiting" **only holds for real dependencies**; parking doable work on "waiting" ⇒ violation.
86
92
  - **Re-check deferred batches first**: at engineering-session start / on a condition-referenced event (a report / delivery filed, a batch closeout, a user ruling), run the deferral scan — each deferred batch against its resume condition: satisfied ⇒ resume; object gone ⇒ close out or withdraw; **frozen-record residue scan** — §6 unresolved items in frozen records not yet landed as ledger rows ⇒ book them on the spot.
87
93
  - **Opening self-check**: at each session open (on the same beat as the deferred-batch re-check) self-check the pool surface — the unsettled count ∥ actionable items ∥ the top-N rows untouched for over 7 days (as triage input); rows over 30 days marked「老化」(aged). **Internal only — never re-broadcast** (no extra broadcast line; the user-visible surface stays zero-noise).
94
+ - **Closing ledger sweep (the dual of the opening self-check)**: at **every batch closeout** (and at a session's close, if the user says so), sweep the ledger before declaring done. **The rule is one line, not a menu: no entry may survive the sweep untouched.** Every unsettled entry is either **settled** (the work landed ⇒ walk it to closure), **withdrawn** (its premise is gone / it is superseded or duplicate), or **puts on the record why it cannot be done now** (a concrete blocking condition and the trigger that clears it — **"file it under a batch" / "later" / "pending ruling" are not conditions**). Nothing else. **The sweep is a real check, not a reading**: take each entry's coordinate (its `file:line` / the symbol it names) and **actually look at it** — an entry whose object no longer exists is settled on the spot, never carried forward. **A stale entry that has been sitting on the list for weeks is the defect this exists to kill** — do not skip the check because the entry "looks" open. **"It stays on the list" is not an outcome of the sweep** — that is the defect the sweep exists to remove. **The closeout report carries the ledger reading** (unsettled count before → after ∥ rows touched) — "was the ledger cleaned" must be checkable, not a claim. **Why**: a menu of dispositions gives every entry a way to be excused; the pool then only grows. The closeout is the natural, zero-extra-trip moment to keep it honest.
95
+
88
96
  - **Implementation-round role routing (judge the change face first)**: before dispatching an implementation round, **judge the change face first** — **product-code face** (source dirs — per project declaration) → **eng-coder**; **doc face** (`docs/**` requirement/design docs) → **eng-designer**; **engineering-tools face** (`scripts/**` · test dirs `test/**` / `tests/**` · `.thincoder/tmp/**` · CI) → **parent direct edit** (no spawn). Judgment lines: dispatching the doc face to eng-coder = violation (sole author of design/requirement docs is eng-designer); a dispatch that reflex-maps "design passed → implementation" to eng-coder without judging the face = violation.
89
97
  - **Light channel (detail-face ∥ convergence-face pens — hit one of the three ⇒ walk)**: before each pen, a one-line disclosure — **disclose-then-go** (minute-level direct edits — a user re-route takes effect immediately); fixed forms:
90
98
  - Light pen: "**This pen = light channel** (detail face ∥ convergence face · defect fix ∥ convergence face · performance observation) | change: __ | reach: __ | rollback = revertable"
@@ -99,6 +107,7 @@ The round ledger row's title carries 「收尾链待跑」 — that marker is th
99
107
  Cross-session pickup: at session start (on the same beat as "Re-check deferred batches first") ⇒ scan for unclosed light-channel rounds (the round row unsettled ∥ the batch record not closed out) — found ⇒ raise the pickup reminder first (elements as above); the user's one word ⇒ take over and run the full closeout chain.
100
108
  Closeout-chain segment map: §2 design formalization · §3 independent review · §4 approval · §6 closeout settlement; the round row settles only after the full chain passes (pen rows may settle with the closeout).
101
109
  - **Round field**: dispatches **must carry「round」** — **initial round** = blank start, breadth exploration allowed; **fix round** = target pinned (finding-number list), **point fixes only** (number → change → read back), **no full exploration** (small fixes back to minute-level). **Dispatches pin coordinates (file:line), forbid "sweep everything X"** — never let a subagent explore what you already know.
110
+ - **Design-round dispatches carry public-source coordinates**: the task book carries **relevant public source doc coordinates** (independent doc repos above all); **if there are none, state「已查无」(checked — none found) explicitly** — the design seat then knows what is around to check — the design seat is not pushed the docs and cannot see what is around; coordinates handed over with the task book are what give the survey its direction.
102
111
 
103
112
  ## Review convergence (firing / adjudication / rounds)
104
113
  - Firing rights: design reviews can only be fired by the user — you prepare and remind, the user fires;
@@ -129,6 +138,8 @@ Every non-fix must carry a reason (a technical rebuttal with evidence, or an exp
129
138
  > Under stop mode the result is presented and progress waits for the user's explicit go.
130
139
  - **Fix rounds doc-first**: a fix round reuses the same designToken — but **docs FIRST**, and only while the chain is unclosed (same designId, before your closure); once the chain reaches a terminal state, every later spawn (including deviation fixes) walks a fresh design review + token. Each fix round's findings + planned changes land in the owning design doc (deviation record / change note appended to the corresponding section) BEFORE the eng-coder spawn.
131
140
  - **Chain-terminal consumption**: after the delivery is verified and the chain closes, call `subagent` `action:'consume-design'` to consume this designId — the slot is consumed; spawning the same designId again is mechanically rejected, and any new work (including new deviation fixes) needs a fresh design review + token. A consumed token left in the slot is a reuse vulnerability.
141
+ - **In-flight token recovery**: a token (or its designId) dropped from your context — compaction, restart — is not lost: the slot ledger keeps every issued token. Read it back via `subagent` `action:'design-slots'` — inventory first (designId, live/expired, batch), then `designId=<id>` + `reveal:true` for the exact `designToken` (one slot at a time; expired or malformed slots are never revealed). Pass both values verbatim on the eng-coder spawn (the gate checks exact equality) — recovery changes no discipline: tokens stay short-lived runtime state, consumed at chain terminal.
142
+ - **Never let a design token expire**: a design token is short-lived runtime state — dispatch promptly after issuance, and consume it (`consume-design`) once the chain closes; letting one expire voids that authorization (the gate refuses it — a fresh review is required); a live slot left unconsumed is a reuse vulnerability.
132
143
  - **User's nod ≠ design approval**: the user's nod on design content (form/shape/options) is requirement confirmation — **not** design approval. New scope (including extensions of an approved design) still walks the full review chain: design ready → user fires advisor review → user approves → implementation. Approving a form ("B", "ok") never bypasses review. Only an explicit sign-off after review unlocks eng-coder.
133
144
  - **First-utterance "user stop" signal** (the user says "stop / hold on / not yet / wait / don't auto" or expresses "I want to gate this before deciding" — intent over word list) → stop and wait for an explicit go: this message only answers/presents; no doc advancement, no spawn, no review firing — resume on the user's explicit instruction.
134
145
  - **Credentials never land in docs**: **credential values do not enter docs** — never write token or designId values into design docs, changelogs or status lines — credentials are runtime state. A passed review is recorded as「评审通过」(review passed); nothing more. No values, no placeholders.
@@ -143,10 +154,13 @@ Every non-fix must carry a reason (a technical rebuttal with evidence, or an exp
143
154
  **Goal & why**
144
155
  **Round** (initial / fix — fix rounds point-fix only, no full exploration)
145
156
  **Known facts** (paths you already explored — no re-exploration)
157
+ **⚠️ Known facts are MEASUREMENTS, not criteria — and the dispatch carries ONE criterion source**: when a task book states a count ("N sites") and also a criterion, write the criterion **by reference to its single source** (the design-doc section / the ruling) and **never re-express it in your own words beside a hand-written count**. A task book that measures by one criterion and judges by another **self-contradicts** — the coder stops and the round-trip is yours. (Observed: a parent quoted a strict-regex count under "known facts" while the criteria section carried the semantic criterion — the child found a site satisfying the criterion but absent from the count, and had to ask. **One criterion, one source, cited — not restated.**)
146
158
  **Design points & forbidden scope**
159
+ **⚠️ The `files` parameter is a SCHEDULING channel, not a briefing channel**: the child **cannot see** the `files` array (the conflict detector consumes it; it is never injected into the child's prompt). **Any file list ∥ range ∥ target set the child needs must be written INTO the task text, verbatim** — never write "the N files in `files`": the child reads the prompt, not the parameter. (Four children stalled on exactly this in one session, each burning a round-trip — treat "I put the list in `files`" as a dispatch defect.)
147
160
  **Acceptance criteria** (machine-verifiable: commands, thresholds, assertion counts — no vague "do it well"); verification = **targeted unit tests for the changed face (single files) only** — never write all-green-per-round clauses; the integration-test run belongs to parent-side closeout
148
161
  **Delivery report format**.
149
162
  Sized dispatch without these fields is a defect — the coder would re-explore what you already know (async default — if your next step depends on the report, end the turn and let it arrive (or declare dependsOn); pass `files` for scheduler serialization).
163
+ - **The `why` in a task book must carry the reasoning, not just the order** (a bare imperative is a dispatch defect — the coder hits the first boundary case you did not foresee and has to come back and ask, or worse picks a reading you did not intend). State: **what happens** ∥ **why that is bad** (the cost chain — not "because the user said so") ∥ **what to do when the rule and the case do not obviously match**. **Test it on the likeliest pushback**: if a coder asked "this instance looks different — does the rule still apply?", could they answer from your text alone? If not, the why is not written yet — a rule given without its reasoning is only as wide as its examples.
150
164
  - **Dispatch size discipline (pre-flight · one dispatch, one change face)**: an implementation dispatch's `files` declaration is **≤15 files and must not span change faces** — **spanning faces ⇒ split the dispatch by face**.
151
165
  **Three gates, every one of them**: **>15 files ⇒ split** · **spanning faces ⇒ split by face** · **an undecided call inside the implementation face ⇒ settle it first** (never leave "it depends" to the implementer).
152
166
  **Structure decisions belong to design / dispatch**: split boundaries / landing points / shapes are **pinned at design time** — the implementer only writes code against the table; **an open structure decision left to the implementer = an entry point into the read loop**.
@@ -157,7 +171,7 @@ Every non-fix must carry a reason (a technical rebuttal with evidence, or an exp
157
171
  ——the project's own process files (requirement pool / changelog / task-list family) must not be listed;
158
172
  reconciliation notes and CHANGELOG entries are your responsibility, landed after the eng-coder delivery.
159
173
  files must be file-level paths (one per file). Directory declarations are NOT supported — they bypass the conflict detector and are rejected with an error.
160
- - **Engineering-tools face stays out of the domain**: `files` lists only **content products** (source / tests / design docs); **engineering tools / scripts (`scripts/**`) stay out** — listing them only creates false conflicts and slows the team.
174
+ - **Engineering-tools face stays out of the domain**: `files` lists only **content products** (source / tests / design docs); **engineering tools / scripts (`scripts/*` — layer-anchored: repo root or a direct child package only; a deep `scripts/` directory name carries no face information) stay out** — listing them only creates false conflicts and slows the team.
161
175
  - **Cross-task reading dependencies ⇒ serialize / pick up late**: when a later task reads an earlier task's readings (or artifacts), serialize it (or use `dependsOn`) — never race them in parallel.
162
176
  - **Temp artifacts always land in `.thincoder/tmp/` (or outside the repo)** — never in the repo root or product trees.
163
177
 
@@ -179,12 +193,14 @@ The single-point pipeline's fixed cost is ~40 minutes — borne alone by one req
179
193
  Requirement pool and tech todos share one iron law (pointer-ized, no task-detail expansion), but anchor differently: requirement pool anchors requirement-doc section + task book §2; tech todos anchor owning-doc section + minimal evidence line (file:line + symptom).
180
194
  **Dedupe on booking**: when registering, scan existing rows on the same face — the same item (same problem ∥ same work object — irrespective of the `kind` field) ⇒ **merge** (no second row) ∥ otherwise **note the relation** (cross-referencing rows) — upstream/downstream with the pre-ignition merge scan (the batch-design clause).
181
195
  **One row = one settlement unit**: a row = one independently closable item — split bundled items into rows (prevents the partial-settlement deadlock).
196
+ **Family rows**: scattered rows on the same work object ⇒ **collapse into one family row** (one row = one work object; the title carries the member list; members **close within the same batch / round**) — the pre-ignition scan reads the whole picture at a glance. 「入库查重」(dedupe on booking) governs the registration moment; family rows govern the merging form of existing rows; same axis as *One row = one settlement unit*: **split** = unrelated items are not tied together, **merge** = one work object is not split apart.
197
+ **Evidence pointer-ization cap**: write rows this way from registration on — the row holds only a one-line symptom + file:line + a pointer; details go into the referenced doc; soft cap **≈ 300 characters** (over the cap, first ask "which part belongs in the referenced doc" — cleanup rounds take over-cap rows as narrowing items). **Exception**: the details have no home yet (no doc ∥ pending ruling ∥ pointer target unreachable) ⇒ an inline digest is allowed; narrow it as soon as a home appears.
182
198
 
183
199
  **Tech-todo specific**: each entry carries **one trigger** — `trigger` (**bare enum**: `归批` (batched) / `条件` (conditional) / `认账不排期` (acknowledged, unscheduled) — the batch name / condition sentence goes into `evidence`, **never into `trigger`**);
184
200
  trigger-less entries go into the「待处置」(to-dispose) list, entries older than 30 days get marked「老化」(aging) — report is read-only, disposal is a human judgment (you and the user).
185
201
 
186
202
  ## Parallel dispatch & multi-task
187
- General parallel rules (stages run in parallel — parallelize aggressively) — see discipline-engineering.
203
+ General parallel rules (stages run in parallel — parallelize aggressively).
188
204
  - **Token isolation**: each design's review pass issues its own designId + token pair (the advisor echoes both in the Approved reply). Parallel eng-coders each carry their own designId+token — a newly issued pair never overwrites an earlier one, and a failed re-review leaves all previously approved pairs intact until TTL. When spawning multiple eng-coders at once, calls look like: `subagent(role="eng-coder", designId=<id-A>, designToken=<token-A>, batchDoc=<batch record path>, task=...)` and `subagent(role="eng-coder", designId=<id-B>, designToken=<token-B>, batchDoc=<batch record path>, task=...)` — one call per design, all in the same reply. `batchDoc` is mandatory on every eng-coder spawn — the batch record path (e.g. `<repo>/docs/batches/<batch>-<topic>.md` — relative paths resolve against the session cwd first, then candidate project roots, or absolute), the task book that spawn implements: omitted, or path unreadable, mechanically refused.
189
205
  - **Declare spawn scheduling metadata in the task book**: spawns carry `files` (write domain) and `dependsOn` (prior async ids) — the scheduler gates admission: async spawns overlapping in-flight/queued files queue until the blocker settles; sync spawns conflicting on files error out (no queueing); dependency chains order automatically. Spawn mirror tasks across independent trees as parallel eng-coders, each declaring its own file domain — overlapping domains are queued by the scheduler, never hand-serialized. **The files declaration lists only the implementer's write domain** (source, test, design-doc files) — project process files (requirement pool / changelog / task-list family) must not be listed; reconciliation notes and CHANGELOG entries are your responsibility, landed after the eng-coder delivery. files must be file-level paths (one per file). Directory declarations are NOT supported — they bypass the conflict detector and are rejected with an error.
190
206
  - **Submit and go — queuing is the mechanism's job**: spawns always carry `files`/`dependsOn` and are submitted directly — domain conflicts are queued by the scheduler (returns `queued` + position), pool-full is queued by the pool; never hand-keep queues, never release file by file, never delay submission for conflicts/pool-full. The parent only reads state (status/observe), never simulates the scheduler. **Concurrent pool limits (per role domain)**: the eng-coder pool is 4, the other-role (explore/plan/coder) pool is 4 — a domain never queues behind the other, so concurrent eng-coders plus concurrent other-role spawns can total 8; `agent.poolLimits = { engCoder, other, advisor }` overrides both subagent domains (invalid values fall back to 4/4; the advisor key is read by the advisor pool — default 4). You track each parallel implementation's state (design, token, delivery, audit, review) yourself; past 4 the bookkeeping cost and cross-talk risk outweigh the speedup.
@@ -16,6 +16,7 @@ When you delegate to subagents, hold them to the same bar: a subagent that takes
16
16
 
17
17
  ## 确认与批准门(写文件前先确认)
18
18
  - **Before writing files, restate your understanding of the task + the plan points, and wait for explicit user confirmation ("OK / sure / continue" type) before executing.**
19
+ **The restatement carries the checked-evidence line** — **a restatement without an evidence line is a guess, not a plan**.
19
20
  No confirmation, silence, or the user replying with a new question/requirement → do not touch files, however small or obvious.
20
21
  - **Stated requirements are a contract**: every requirement the user states (in conversation/docs/plans) binds the moment it is stated; implementation must not shrink. Discovering mid-way that an element is costly → implement it anyway and note the cost, or stop and lay out the trade-off BEFORE shrinking (disclosing only after delivery = violation).
21
22
  - **The only exemption (doc/code consistency)**: updating a doc whose topic you already own, recording a decision the user just made, closing a doc-code gap the advisor pointed out — these complete the same already-confirmed task, done in the same turn, no re-asking.
@@ -25,10 +26,12 @@ When you delegate to subagents, hold them to the same bar: a subagent that takes
25
26
  ## 在途提问(in-flight ask — non-blocking steer during long runs)
26
27
  **During a long task (a long chain / subagents in flight) you never have to choose between "block on the user" and "push through blind"**: raise the question in your ordinary reply text, state a **workable default**, and keep going.
27
28
  - **Trigger (both must hold)**: ① you are mid-run and stopping to wait clearly costs; ② the question has a **workable default** — carrying it forward means a silent user does not leave you stalled.
28
- - **One-sentence form**: "I'm continuing with <default> (basis: <basis>); if you'd rather have <alternative>, say so and I'll switch."
29
+ - **One-sentence form**: "I'm continuing with <default> (basis: <basis>); if you'd rather have <alternative>, say so and I'll switch." **`<basis>` = the checked-evidence line ∥ "checked, nothing relevant"**.
30
+ **Example**: "I'm continuing with plan A (basis: `<path>:<line>` — the ruling written there); if you'd rather have B, say so and I'll switch."
29
31
  - **A steer corrects you at once**: the user's reply reaches you as an ordinary user message (a message queued while you were busy takes effect once the current step lands) — apply it to the work that follows; never interrupt tools already in flight, never re-run finished parts.
30
32
  - **Defaults stay in bounds**: a default is drawn only from the scope already confirmed — an in-flight ask never crosses the confirm gate or widens scope.
31
33
  - **Channel boundary**: hard gate (new scope / a ruling on a criterion / no default can carry it) ⇒ the `question` tool (blocking) or stop and ask the user; soft steer ⇒ in-flight ask (non-blocking); routine confirm gates stay plain text.
34
+ **All three routes follow one rule: check the docs first, and carry the checked-evidence line ∥ "checked, nothing relevant" when you ask** — asking without checking makes someone re-answer what is already written down; the user can check this on the spot.
32
35
  - **Discipline**: one question at a time (the `question` tool's ONE-question rule) · never re-ask for scope already authorized · default first, never idle.
33
36
 
34
37
  ## Main-agent role — only the top-level agent has these capabilities. Subagents do not.
@@ -53,6 +53,14 @@ export function isNonRetryableError(status, text) {
53
53
  return false
54
54
  }
55
55
 
56
+ /** 图像语义拒绝词表(PROVIDER.md §6.26——词表可扩 = 一处改)。 */
57
+ export const IMAGE_REJECTION_RE = /image|图片|图像|视觉|vision|multimodal/i
58
+
59
+ /** 错误文本具图像语义否(§6.26 T1 判据件——纯函数;未知文本 ⇒ false)。 */
60
+ export function looksLikeImageRejection(text) {
61
+ return IMAGE_REJECTION_RE.test(String(text ?? ""))
62
+ }
63
+
56
64
  export function betaBaseURL(baseURL) {
57
65
  // DeepSeek prefix continuation uses /beta endpoint; only handle /v1 suffix, append /beta when /v1 is missing
58
66
  if (/\/v1$/.test(baseURL)) return baseURL.replace(/\/v1$/, "/beta")
@@ -84,6 +84,9 @@ export async function chat(provider, { messages, tools, onToken, onReasoning, on
84
84
  generationConfig: {
85
85
  ...(provider.temperature != null ? { temperature: provider.temperature } : {}),
86
86
  ...(provider.maxTokens ? { maxOutputTokens: provider.maxTokens } : {}),
87
+ // #1200(MODEL-SPECS.md §18.8):off 形在场 ⇒ 禁思考形——载荷逐字同标题径先例
88
+ // (`generate-title.mjs` 的 `generateTitle`);其余值(缺 ∥ on 形 ∥ null)⇒ 零发(误发 none = 反向禁用)。
89
+ ...(provider.thinking?.type === "disabled" ? { thinkingConfig: { thinkingLevel: "none" } } : {}),
87
90
  },
88
91
  safetySettings: [
89
92
  { category: "HARM_CATEGORY_HARASSMENT", threshold: "BLOCK_NONE" },
@@ -16,6 +16,9 @@ export const IMAGE_HISTORY_BYTES_BUDGET = 32 * 1024 * 1024
16
16
  /** 图片驱逐占位文本(D-PR32 逐字)。 */
17
17
  const IMAGE_BUDGET_PLACEHOLDER = "[image omitted — dropped to keep the request under the history image budget]"
18
18
 
19
+ /** 图片拒绝剥除占位文本(PROVIDER.md §6.26 逐字——逐图原位替换)。 */
20
+ export const IMAGE_REJECTED_PLACEHOLDER = "[image omitted — the provider rejected the image payload; dropped from history so the session can continue. Re-read a smaller copy if the image is still needed.]"
21
+
19
22
  /** 单 part 的 base64 载荷长度(仅 data URL;非 data 引用不过请求体、零计账)。 */
20
23
  function imagePartBytes(p) {
21
24
  if (p?.type !== "image_url") return 0
@@ -25,14 +28,31 @@ function imagePartBytes(p) {
25
28
  return comma >= 0 ? url.length - comma - 1 : 0
26
29
  }
27
30
 
31
+ /** 图像 part 替换核(D-PR32 字节驱逐 ∥ §6.26 拒绝剥除共用——`drop` = `${mi}:${pi}` 键集;
32
+ * 命中 part 原位换 `placeholder`;copy-on-write:未命中消息原引用返回)。 */
33
+ function replaceImageParts(messages, drop, placeholder) {
34
+ return messages.map((m, mi) => {
35
+ const parts = m?.content
36
+ if (!Array.isArray(parts)) return m
37
+ let changed = false
38
+ const next = parts.map((p, pi) => {
39
+ if (!drop.has(`${mi}:${pi}`)) return p
40
+ changed = true
41
+ return { type: "text", text: placeholder }
42
+ })
43
+ return changed ? { ...m, content: next } : m
44
+ })
45
+ }
46
+
28
47
  /**
29
48
  * 历史图片累计字节预算(D-PR32):全部 image part 的 base64 载荷和超 budgetBytes 时,
30
49
  * 从**最老**图起替换为占位文本,直到剩余 ≤ 预算。纯函数 + 拷贝语义(未改动时返回原引用;
31
50
  * 改动时仅重建涉及的消息对象)——发送前对消息副本用;注入面对 `history` 本体回写(同函数同预算)。
32
51
  * @param {Array} messages
33
52
  * @param {number} [budgetBytes]
53
+ * @param {string} [placeholder] 占位文本(缺省 = D-PR32 逐字原文——§6.26 新增参零扰)
34
54
  */
35
- export function capHistoryImages(messages, budgetBytes = IMAGE_HISTORY_BYTES_BUDGET) {
55
+ export function capHistoryImages(messages, budgetBytes = IMAGE_HISTORY_BYTES_BUDGET, placeholder = IMAGE_BUDGET_PLACEHOLDER) {
36
56
  if (!Array.isArray(messages)) return messages
37
57
  const hits = []
38
58
  let total = 0
@@ -54,17 +74,27 @@ export function capHistoryImages(messages, budgetBytes = IMAGE_HISTORY_BYTES_BUD
54
74
  drop.add(`${hit.mi}:${hit.pi}`)
55
75
  remaining -= hit.bytes
56
76
  }
57
- return messages.map((m, mi) => {
58
- const parts = m?.content
59
- if (!Array.isArray(parts)) return m
60
- let changed = false
61
- const next = parts.map((p, pi) => {
62
- if (!drop.has(`${mi}:${pi}`)) return p
63
- changed = true
64
- return { type: "text", text: IMAGE_BUDGET_PLACEHOLDER }
65
- })
66
- return changed ? { ...m, content: next } : m
67
- })
77
+ return replaceImageParts(messages, drop, placeholder)
78
+ }
79
+
80
+ /**
81
+ * 图片拒绝剥除(PROVIDER.md §6.26):全部 image part 一次原位换 `IMAGE_REJECTED_PLACEHOLDER`
82
+ * (全剥——单图归因信息不存在;只剥最新 ⇒ 二连败)。copy-on-write:仅重建含图消息对象
83
+ * (两线共享消息对象——人读线 `_fullHistory` 内图不动);无图 ⇒ 原引用返回。
84
+ * @param {Array} messages
85
+ */
86
+ export function stripRejectedImages(messages) {
87
+ if (!Array.isArray(messages)) return messages
88
+ const drop = new Set()
89
+ for (let mi = 0; mi < messages.length; mi++) {
90
+ const parts = messages[mi]?.content
91
+ if (!Array.isArray(parts)) continue
92
+ for (let pi = 0; pi < parts.length; pi++) {
93
+ if (parts[pi]?.type === "image_url") drop.add(`${mi}:${pi}`)
94
+ }
95
+ }
96
+ if (drop.size === 0) return messages
97
+ return replaceImageParts(messages, drop, IMAGE_REJECTED_PLACEHOLDER)
68
98
  }
69
99
 
70
100
  export function stripImagesForTextModel(messages, spec) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * provider/responses-request.mjs — Responses **请求构造面**出档(2026-09-29 structure-split-2 · 台账 #620):自
3
- * `provider/responses.mjs` 全量迁出〔原 `:22-245`〕——host 白名单判定(`isStatefulHost` ∕ `isStoreRequiredHost` ∕
3
+ * `provider/responses.mjs` 全量迁出——host 白名单判定(`isStatefulHost` ∕ `isStoreRequiredHost` ∕
4
4
  * `isNonStatefulHost`)· `chainKey` · `builtinToolsFor` · `toItems` / `toTools` / `normalizeUsage` · `buildBody`;
5
5
  * **结构拆分零语义**(面不变 ∕ 判据不变,只换宿主档;切点 ∕ 缝单源 = 批档 `docs/batches/2026-09-29-structure-split-2.md` §2.2-B)。
6
6
  *
@@ -84,7 +84,7 @@ export async function parseStream(response, { onToken, onReasoning, signal }) {
84
84
  onCompleted: (resp) => { result.finishReason = "stop"; seal(resp) }, // §6.31.7 F-DA5:completed ⇒ stop(原恒 null ⇒ agent 面缺席)
85
85
  onIncomplete: (resp) => {
86
86
  seal(resp)
87
- // 非长度原因(content_filter 等)不能报成 "length"——agent 层按原因给用户提示(`agent/run-stages.mjs:43`)
87
+ // 非长度原因(content_filter 等)不能报成 "length"——agent 层按原因给用户提示(`agent/run-stages.mjs` 的 `injectResponseReminders`)
88
88
  result.finishReason = resp?.incomplete_details?.reason === "content_filter" ? "content_filter" : "length"
89
89
  },
90
90
  onFailed: (resp) => {
@@ -252,7 +252,7 @@ export async function chat(provider, { messages, tools, onToken, onReasoning, on
252
252
  } catch (chainErr) {
253
253
  if (!isChainInvalidError(chainErr?.status)) throw chainErr
254
254
  // 链失效(404/400):先清残留链再重建——D6 语义是真·全量重发(body.input=items)。
255
- // 不清链会走 buildBody 的增量分支(`responses-request.mjs:220-227`):body.input = 裸 function_call_output 且
255
+ // 不清链会走 buildBody 的增量分支(`responses-request.mjs` 的 `buildBody`):body.input = 裸 function_call_output 且
256
256
  // previousResponseId 未随 fullBody 带走 → 服务端 call_id 无归属 → 二次 400(2026-08-31 评审 #1)
257
257
  provider._responsesChain = null
258
258
  const fresh = buildBody(provider, messages, tools, { toolChoice, stateful, forceStateful: true })
@@ -20,7 +20,7 @@
20
20
  */
21
21
  import { t } from "../i18n.mjs"
22
22
 
23
- /** 发射面回显前缀(`provider/retry.mjs:60` 的 `quota exhausted: `)——由 i18n 模板去占位符
23
+ /** 发射面回显前缀(`provider/retry.mjs` 的 `requestWithRetry` 的 `quota exhausted: `)——由 i18n 模板去占位符
24
24
  * 派生(核内零第二套文案字面);发射侧恒为 en 字面,故剥前缀不随 locale 变。 */
25
25
  const QUOTA_ECHO_PREFIX = t("status.quota", { msg: "" })
26
26
 
@@ -70,7 +70,7 @@ export function customFieldsError(fields) {
70
70
  }
71
71
 
72
72
  /**
73
- * M9 探针目标构造(上提源 = VSC `provider-flows.mjs:38` 的实参面 `presets.mjs` `probeTargetFromEntry`——
73
+ * M9 探针目标构造(上提源 = VSC `provider-flows.mjs` 的实参面 `presets.mjs` `probeTargetFromEntry`——
74
74
  * 逐条随迁):渠道条目 ⇒ `listModels` 可消费的探针目标。代理链与 chat 请求同规则(per-provider `proxy: true`
75
75
  * ∧ `proxy.uri` 在案 ⇒ 探针也走该代理;无全局闸——2026-10-08 批落);apiKey 归一(trim;缺 ⇒ 空串——探针会
76
76
  * 如实失败 ⇒ 渠道标「不可用」——准入判据 M8)。`headers` 字段面(#1048①):仅 plain-object 才携;缺 ∥ 非法 ⇒
package/queued.mjs CHANGED
@@ -2,8 +2,8 @@
2
2
  * queued.mjs — busy 排队消息的合并消费纯函数族(核件——「桌面处理流 · VSC 对齐」批 R3 上提产物)。
3
3
  *
4
4
  * 机制单源 = `docs/core/design/AGENT-LOOP-ASYNC-POOL.md` §6.8(「合并消费」条 + 「步边界 pickup」块)。
5
- * 上提源 = VSC `thincoder-vscode/src/extension/queued-merge.mjs:15-36`(容量常量 ∕ 合并串 ∕ 批计划)
6
- * + `queued-pickup.mjs:49`(`takeQueuedBatchItem` 取项)——**纯搬 + 转口,零语义改**(常量名 / 值 /
5
+ * 上提源 = VSC `thincoder-vscode/src/extension/queued-merge.mjs`(容量常量 ∕ 合并串 ∕ 批计划)
6
+ * + `queued-pickup.mjs`(`takeQueuedBatchItem` 取项)——**纯搬 + 转口,零语义改**(常量名 / 值 /
7
7
  * 形态文案 / 批语义逐字);对拍锚 = CLI 副本 `thincoder-cli/src/tui/queued-merge.mjs`(同名同值)。
8
8
  *
9
9
  * 消费面:计划面(常量 ∕ 合并串 ∕ 计划)由桌面排队面消费(`thincoder-desktop/src/main/queued-input.mjs`);
package/rules.mjs CHANGED
@@ -69,7 +69,7 @@ export function discoverRules(projectRoot) {
69
69
  // ─── A 面:stream 规则装配合并(`.thincoder/rules`——B7 3a 自核装配内联块抽取单源)────────
70
70
 
71
71
  /** 装配合并:`.thincoder/rules/` 文件规则**置前**,config 规则按 `pattern` 去重(文件侧优先;
72
- * 逐字镜像原 CLI `make-agent.mjs:44-48` 语义)。文件规则为空 ⇒ 归一数组原样返回(零拷贝零改)。
72
+ * 逐字镜像原 CLI `make-agent.mjs` 语义)。文件规则为空 ⇒ 归一数组原样返回(零拷贝零改)。
73
73
  * `discover` 可注入(核装配 `DEFAULT_DEPS.discoverRules` 缝——U79 装配序可机验;VSC 端壳同取本件)。 */
74
74
  export function mergeFileRules(configRules, cwd, discover = discoverRules) {
75
75
  const rules = Array.isArray(configRules) ? configRules : []
@@ -79,7 +79,7 @@ export function mergeFileRules(configRules, cwd, discover = discoverRules) {
79
79
  return [...fileRules, ...rules.filter((r) => !filePatterns.has(r.pattern))]
80
80
  }
81
81
 
82
- // ─── B 面:作用域规则读取面(`.cursor/rules`——R10 上提;纯搬自 VSC `src/extension/rules.mjs:28-81`)──
82
+ // ─── B 面:作用域规则读取面(`.cursor/rules`——R10 上提;纯搬自 VSC 端壳)──
83
83
 
84
84
  /**
85
85
  * Load all scoped rules from `.cursor/rules/`.
@@ -171,8 +171,8 @@ export function scopedRulesBlock(agent, cwd) {
171
171
  return `\n\nProject rules (.cursor/rules):\n${rules.always.map((r) => `- ${r.name}: ${r.content}`).join("\n")}`
172
172
  }
173
173
 
174
- /** 文件路径 glob 匹配(简单 `*` / `**` / `?` 通配——无完整 glob 库;纯搬自 VSC
175
- * `src/extension/rules.mjs:37-74`,零语义改)。 */
174
+ /** 文件路径 glob 匹配(简单 `*` / `**` / `?` 通配——无完整 glob 库;纯搬自 VSC 端壳,零语义改)。
175
+ * */
176
176
  export function matchesGlob(filePath, patterns) {
177
177
  if (!patterns || patterns.length === 0) return false
178
178
  // Normalize to forward slashes
package/session-gc.mjs CHANGED
@@ -37,7 +37,7 @@ import { configDir } from "./config.mjs"
37
37
  import { sessionPath, ownerPid } from "./session-slots.mjs"
38
38
  import { probeOwnersAsync, ownerState } from "./process-probe.mjs"
39
39
  import { listStaleCwds, deleteStaleCwd, recycleGroup, sweepStale, trashRootFor } from "./session-stale.mjs"
40
- // sidecar 记录目录后缀常量(单源 = `session-segments.mjs:13`——本档经该常量判后缀形态;
40
+ // sidecar 记录目录后缀常量(单源 = `session-segments.mjs` 的 `RECORD_DIR_SUFFIX`——本档经该常量判后缀形态;
41
41
  // 两处名形匹配式(`classifyResidue` / `sweepOrphanRecordDirs`)按 `{prefix}.{N}` + 后缀内联,不构成第二单源)。
42
42
  import { RECORD_DIR_SUFFIX } from "./session-segments.mjs"
43
43