Browse Source

Merge remote-tracking branch 'origin/master' into worktree/schedule-conversational-after

Tianyi Cui 1 month ago
parent
commit
bef3fccbd8

+ 2 - 2
.agents/notes/implemented/process/2026-08-09-committed-artifact-citations.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-09-committed-artifact-citations.md
-2026-08-09-committed-artifact-citations.md: 31b2d52b423a080579b3ca95cf077859d0bf4c91
-2026-08-09-committed-artifact-citations.zh.md: b69bb8743d10e2d1e194905d6d0de2d3d3667b1d
+2026-08-09-committed-artifact-citations.md: 181378aab12a4423d9ac5216bac5304f3cfca11c
+2026-08-09-committed-artifact-citations.zh.md: 36f32bb1fd0d6991919959e1ebe6482bf7b19b32

+ 2 - 2
.agents/notes/implemented/process/2026-08-09-committed-artifact-citations.md

@@ -18,7 +18,7 @@ Durable prose — comments, JSDoc, docs, notes, test comments and titles — cit
 - Implemented notes state shipped reality: a "deferred to a later PR" claim whose target shipped names the shipped note instead.
 - Recorded fixtures, snapshots, and archived notes are exempt: recorded model output and sealed history keep their original voice. Inside a note's change-story sections, a historical stage name ("the first cut shipped X") is current-state-safe; indexical stamps ("this cut") stay banned everywhere.
 
-One repo-wide purge applied these rules across the prose surfaces, including the generator-owned templates (`scripts/gen-doc-graphs.ts`, `scripts/gen-tool-catalog.ts`, the typert generator's page notice) with regeneration, the type-equiv source JSDoc with page re-pastes, and the bilingual counterparts with pair re-records.
+One repo-wide purge applied these rules across the prose surfaces, including the generator-owned templates (`scripts/gen-doc-graphs.ts`, `scripts/gen-tool-catalog.ts`, the typert generator's page notice) with regeneration, the type-equiv source JSDoc with page re-pastes, and the bilingual counterparts with pair re-records. The [dsh-trim-cot-leakage skill](../../../skills/dsh-trim-cot-leakage/SKILL.md) operationalizes these rules: the audit taxonomy, the committed recall batteries, and few-shot calibration for the keep/delete boundary.
 
 ## Alternatives considered
 
@@ -28,7 +28,7 @@ One repo-wide purge applied these rules across the prose surfaces, including the
 
 ## Verification
 
-The audit's grep batteries (English and Chinese, comments and prose, `--hidden` for `.agents/`) return no design-ordinal citations outside recorded fixtures and archived notes; `verify-type-equiv`, the `gen-*` freshness checks, and `verify-translation-pairing` pin the regenerated and re-recorded surfaces. Coverage gap: no gate rejects a new ordinal citation — review owns the rule.
+The audit's grep batteries (English and Chinese, comments and prose, `--hidden` for `.agents/`) return no design-ordinal citations outside recorded fixtures, archived notes, and the trim skill's own calibration examples; `verify-type-equiv`, the `gen-*` freshness checks, and `verify-translation-pairing` pin the regenerated and re-recorded surfaces. Coverage gap: no gate rejects a new ordinal citation — review owns the rule.
 
 ## Consequences
 

+ 2 - 2
.agents/notes/implemented/process/2026-08-09-committed-artifact-citations.zh.md

@@ -18,7 +18,7 @@ Status: implemented
 - 已实现的 Agent Note 陈述已交付的现实:「推迟到后续 PR」的说法若其目标已经交付,就改为点名那篇已交付的 note。
 - 已录制的 fixture(测试前置数据)、快照与已归档的 Agent Note 不受此约束:已录制的模型输出与封存的历史保持原有行文。在 note 的变更故事段落内,历史阶段名称(「首版交付了 X」)属于安全的现状表述;指示性切次戳("this cut")在任何地方都仍被禁止。
 
-一次全仓库清理把这些规则应用到了各个行文表面,包括生成器持有的模板(`scripts/gen-doc-graphs.ts`、`scripts/gen-tool-catalog.ts`、typert 生成器的页面提示语,改后重新生成)、type-equiv 源码 JSDoc(改后把文档页重新粘贴)以及双语对侧文件(改后重新记录配对)。
+一次全仓库清理把这些规则应用到了各个行文表面,包括生成器持有的模板(`scripts/gen-doc-graphs.ts`、`scripts/gen-tool-catalog.ts`、typert 生成器的页面提示语,改后重新生成)、type-equiv 源码 JSDoc(改后把文档页重新粘贴)以及双语对侧文件(改后重新记录配对)。[dsh-trim-cot-leakage 技能](../../../skills/dsh-trim-cot-leakage/SKILL.md)把这些规则落地为可执行工作流:审计分类法、已提交的成批召回检索,以及校准保留/删除边界的少样本示例。
 
 ## 曾考虑的替代方案
 
@@ -28,7 +28,7 @@ Status: implemented
 
 ## 验证
 
-审计的成批 grep 检索(英文与中文、注释与行文、对 `.agents/` 加 `--hidden`)在已录制 fixture 与已归档 Agent Note 之外没有命中任何设计序号引用;`verify-type-equiv`、各 `gen-*` 新鲜度检查与 `verify-translation-pairing` 把重新生成与重新记录的表面固定下来。覆盖缺口:没有门禁会拒绝新的序号引用,这条规则由评审把关。
+审计的成批 grep 检索(英文与中文、注释与行文、对 `.agents/` 加 `--hidden`)在已录制 fixture、已归档 Agent Note 与该清理技能自带的校准示例之外没有命中任何设计序号引用;`verify-type-equiv`、各 `gen-*` 新鲜度检查与 `verify-translation-pairing` 把重新生成与重新记录的表面固定下来。覆盖缺口:没有门禁会拒绝新的序号引用,这条规则由评审把关。
 
 ## 后果
 

+ 5 - 6
.agents/skills/dsh-doc-standards/SKILL.md

@@ -37,12 +37,11 @@ Then check constraints that make placement expensive or wrong:
 After the structural pass, hunt the standard's slop checklist with the cheapest probes first. Verify and fetch the PR's live base, then run `pnpm --silent run change-scope --base <verified-base-ref>` to identify committed and dirty paths before applying semantic judgment. After a retarget or base merge, rerun the report and audit prose introduced by the new base.
 
 1. Measure: `pnpm run verify-doc-budgets --list`, then `git ls-files '*.md' ':(exclude)vendor/**' | xargs wc -w | sort -rn | head -30` to spot unbudgeted outliers.
-2. Hunt narrated history: `rg -n "no longer|used to|previously|was moved|renamed" --glob '*.md' --glob '*.ts' --glob '!vendor/**'` and keep only contrasts against a live alternative. Keep the vendor exclusion last so include globs cannot override it.
-3. Inspect long comments for reasoning transcripts: control-flow narration, test walkthroughs, proof of obvious branches, review findings, rejected local alternatives, and the same rationale repeated beside sibling methods. Preserve only a non-obvious contract or durable rationale; otherwise delete the comment.
-4. Hunt duplication by grepping distinctive phrases. Keep one home and replace other copies with links.
-5. Replace hand-written catalogs, test/status inventories, and JSDoc restatements with the authoritative tree, script, or generated reference.
-6. In `implemented/` Agent Notes, remove migration plans, acceptance-task checklists, and future-tense spec language. Keep concise verification contracts that identify the behaviors and tiers pinning the shipped decision, plus named coverage gaps.
-7. If removing prose changes a promised behavior rather than its explanation, use a proposed Agent Note first (follow [dsh-find-simplifications](../dsh-find-simplifications/SKILL.md)).
+2. Hunt reasoning-transcript leakage — narrated history, dead design-session citations, review choreography, control-flow narration, test walkthroughs — with [dsh-trim-cot-leakage](../dsh-trim-cot-leakage/SKILL.md), which owns the taxonomy, recall batteries, and the keep/delete boundary. Preserve only a non-obvious contract or durable rationale; the same rationale repeated beside sibling methods keeps one home.
+3. Hunt duplication by grepping distinctive phrases. Keep one home and replace other copies with links.
+4. Replace hand-written catalogs, test/status inventories, and JSDoc restatements with the authoritative tree, script, or generated reference.
+5. In `implemented/` Agent Notes, remove migration plans, acceptance-task checklists, and future-tense spec language. Keep concise verification contracts that identify the behaviors and tiers pinning the shipped decision, plus named coverage gaps.
+6. If removing prose changes a promised behavior rather than its explanation, use a proposed Agent Note first (follow [dsh-find-simplifications](../dsh-find-simplifications/SKILL.md)).
 
 Exclude `.agents/notes/archived/` from corpus audits and edits. Active prose may repair, redirect, or delete an inbound link, but never follow an archive-wide cleanup into the frozen target.
 

+ 1 - 1
.agents/skills/dsh-prose-standard/SKILL.md

@@ -5,7 +5,7 @@ description: Use when writing, reviewing, restoring, trimming, or auditing prose
 
 # DeepSeek Harness Prose Standard
 
-Write enough to preserve the contract, then remove reasoning transcripts, repetition, and decoration. This skill owns editorial judgment and required prose coverage; use [dsh-doc-standards](../dsh-doc-standards/SKILL.md) for placement, budgets, bilingual pairs, and documentation gates. It is guidance, not a script.
+Write enough to preserve the contract, then remove reasoning transcripts, repetition, and decoration. This skill owns editorial judgment and required prose coverage; use [dsh-doc-standards](../dsh-doc-standards/SKILL.md) for placement, budgets, bilingual pairs, and documentation gates, and [dsh-trim-cot-leakage](../dsh-trim-cot-leakage/SKILL.md) for hunting and fixing reasoning-transcript leakage. It is guidance, not a script.
 
 Comments describe non-obvious contracts or rationale that code cannot express; they do not restate what code already implies.
 

+ 45 - 0
.agents/skills/dsh-trim-cot-leakage/SKILL.md

@@ -0,0 +1,45 @@
+---
+name: dsh-trim-cot-leakage
+description: Use when auditing or fixing prose that reads like a leaked reasoning transcript — dead design-session citations such as (decision N), audit item codes, or §N of uncommitted drafts; change narration such as "used to", "no longer", "this cut"; stack or review vantage ("a later PR in this stack", "rejected in review"); reviewer-addressed justifications; control-flow narration; or hedged planning residue in comments, JSDoc, docs, or Agent Notes.
+---
+
+# Trimming Chain-of-Thought Leakage
+
+Chain-of-thought leakage is prose whose vantage is the authoring session rather than the repository: it cites artifacts only that session could see, narrates the change instead of the state, or argues with a reviewer who has left. The fix is never deletion alone — restate every factual clause so it stands at HEAD, then delete the transcript around it. **REQUIRED BACKGROUND:** [dsh-prose-standard](../dsh-prose-standard/SKILL.md) owns the complete-proposition rule this skill applies; the [committed-artifact-citations note](../../notes/implemented/process/2026-08-09-committed-artifact-citations.md) owns the citation rule's rationale. It is guidance, not a script.
+
+## The one test
+
+For every suspect passage ask: **could a reader at HEAD, with no access to any session transcript, PR thread, or uncommitted draft, resolve every reference and verify every claim?** If yes, it is not leakage, however historical it sounds. If no, restate the surviving facts from the repository's vantage and delete the rest.
+
+## Taxonomy
+
+1. **Dead design-session citations** — `(decision 7)`, `(audit C2)`, `design §4.7`, `plan §1.4`, phase labels (`T4`, `W3`, `P-I`), "the design ledger", "(B ruling)". If the decision has a committed owner, cite it by name and path; otherwise delete the citation and restate its factual clause to stand alone.
+2. **Stack and PR vantage** — "a later PR in this stack", "this PR adds", "the previous commit". State the shipped mechanism or the extension point; deferred work moves to a `TODO` marker or an issue reference.
+3. **Change narration and version stamps** — "used to", "no longer", "the old X", and indexical stamps ("v1", "this cut", "today", "now" contrasting with a past state). State the present behavior; a fixed regression becomes a present-tense counterfactual ("without X, Y happens"), never repo history ("used to Y").
+4. **Review choreography** — "Rejected in review:", "the reviewer confirmed", draft ordinals ("v5 of this note"), round attributions. Keep the surviving decision and rationale as plain fact; delete who said it when.
+5. **Reviewer-addressed justification** — "the cast is safe — it simply…", "this is correct because…". A comment arguing its own correctness addresses a reviewer, not a maintainer. State the invariant that makes the code safe, or delete the comment if the code shows it.
+6. **Restatement and derivation transcripts** — control-flow narration ("first we X, then we Y"), test walkthroughs, proofs of obvious branches. Delete; keep only a non-obvious contract or invariant.
+7. **Hedges and planning residue** — "probably fine for now", "should be enough", deferrals with no marker. Promote to `TODO`/`FIXME` or restate as the actual bound; delete the hedge.
+8. **Authoring-language slips** — untranslated working-language fragments (端, 设计稿, `---- 私有 ----` separators) in prose whose language is otherwise English, or the reverse in a zh counterpart. Translate or delete.
+
+## What is not leakage
+
+The citation boundary is where unaided passes fail in both directions — deleting durable references and keeping dead ones. Apply these keeps as written; [examples](references/examples.md) calibrates each:
+
+- **Issue references** — `#1470`, `TODO(name):`, "issue #N owns the follow-up" resolve at HEAD; keep them on any surface, including READMEs. Do not relocate them to Agent Notes.
+- **Merged-PR and issue citations inside Agent Notes and postmortems** — sanctioned evidence per the [documentation standard](../../../docs/AGENTS.md)'s change-story routing.
+- **Suppression justifications** — `oxlint-disable … -- reason`, coverage-ignore reasons, empty-catch explanations are required prose; fix a false reason, never delete it.
+- **Counterfactual-present regression pins** — "without X, Y happens", "a naive X would…".
+- **Measured bounds** — "(measured: 512 nests ≈ 0.15s)" calibrating a constant; the provenance word "measured" is load-bearing.
+- **Runtime old/new states** — "the old connection drains before the new one accepts" is runtime lifecycle, not change history.
+- **Historical stage names inside a note's change-story sections** — "the first cut shipped X" is current-state-safe there; indexical stamps ("this cut") stay banned everywhere.
+- **External references that resolve outside the repo by design** — standards sections (RFC 9110 §10.1.5), Figma frame names; the §-ban covers uncommitted internal drafts, not external standards or committed docs that own their §-numbering.
+- **Project voice and genre forms** — "we" as project voice; a note's Alternatives-considered section.
+
+## Workflow
+
+1. Scope and exclusions per [dsh-prose-standard](../dsh-prose-standard/SKILL.md): require an explicit scope; never touch `vendor/`, `.agents/notes/archived/`, or recorded fixtures and snapshots — recorded model output and sealed history keep their original voice.
+2. Audit read-only first: run the [recall batteries](references/recall-batteries.md) (with `--hidden` so `.agents/` is searched), then judge every hit semantically. The batteries are probes, not the definition — each review round of the original purge surfaced shapes the batteries missed, so also read the densest prose in scope (module JSDoc, READMEs, Agent Notes) without a pattern in hand.
+3. Fix owner-first per surface: generated catalogs → fix the source JSDoc or generator template, then regenerate; type-equivalence fences → fix the source JSDoc, then re-paste both bilingual pages (`verify-type-equiv` pins them); bilingual pairs → update the counterpart and re-record per [dsh-translate-docs](../dsh-translate-docs/SKILL.md); model-visible strings → wording is behavior, so flag for a snapshot-backed change instead of silently rewording.
+4. Before deleting anything, enumerate the passage's propositions (prose-standard) and check the [overcorrection traps](references/examples.md#overcorrection-traps): trims that flip an obligation into an endorsement, promote a hypothetical to a shipped feature, delete a true fact, or drop provenance.
+5. Verify: re-run the batteries expecting only sanctioned keeps and this skill's own references; confirm every remaining citation resolves at HEAD; run the gates for touched surfaces (`doc-sync` for docs, `verify-type-equiv`, `verify-translation-pairing`).

+ 253 - 0
.agents/skills/dsh-trim-cot-leakage/references/examples.md

@@ -0,0 +1,253 @@
+# Few-shot leakage examples
+
+Distilled from the 2026-08 repo-wide purge and its review rounds. Use them to identify the governing principle, not as text templates. This file deliberately quotes leaked shapes as calibration material — the [recall batteries](recall-batteries.md) exclude this directory, and its wording is not a license elsewhere.
+
+## Dead citations
+
+### Decision ordinal with a committed owner
+
+**Leaked:** "Slash input resolves against the visible catalog (decision 21)."
+
+**Fixed:** "Slash input resolves against the visible catalog — the plain-text-reference decision, owned by the web input-machine note."
+
+The ordinal resolves nowhere at HEAD; the decision's name and owning note path do. Name the owning note's path at least once per file; later mentions may use the searchable name alone.
+
+### Decision ordinal without an owner
+
+**Leaked:** "The registry rejects duplicate names (decision 7: names are flat, no namespacing)."
+
+**Fixed:** "The registry rejects duplicate names; names are flat, with no namespacing."
+
+No committed artifact owns "decision 7", so the citation is deleted — but its factual clause (flat names) is restated to stand alone, not deleted with it.
+
+### Audit item codes
+
+**Leaked:** "Rendering is pure: same snapshot, same string (audit R3)."
+
+**Fixed:** "Rendering is pure: same snapshot, same string."
+
+There is no audit document in the repo; the code is pure session shorthand carrying zero propositions.
+
+### Section numbers of uncommitted drafts
+
+**Leaked:** "Layering follows the design (v2 §3.2): `src/core/` is the pure core."
+
+**Fixed:** "Layering: `src/core/` is the pure core."
+
+`§N` of a draft nobody committed is unresolvable. Contrast: "escapes per RFC 9110 §10.1.5" stays — an external standard resolves outside the repo by design, and a committed doc that owns its §-numbering may be cited by section.
+
+### Plan-phase labels
+
+**Leaked:** "`src/client/` is the shell (T4); the P-I migration owns the adapters."
+
+**Fixed:** "`src/client/` is the shell; the adapters live in `src/client/adapters/`."
+
+Phase labels index a plan that never landed. Replace the label with what the phase produced.
+
+## Stack and PR vantage
+
+### Stack position in durable prose
+
+**Leaked:** "A future remote backend implements this interface (the sandbox backend is a later PR in this stack)."
+
+**Fixed:** "A remote backend can implement this interface without changing the render layer."
+
+Durable prose cannot see the stack. Keep the extension-point contract; the pending work's home is the PR itself, a `TODO`, or an issue.
+
+### "This PR" in a README
+
+**Leaked:** "This PR adds cursor-based pagination to the session list."
+
+**Fixed:** "The session list paginates by cursor."
+
+A README outlives every PR; state the mechanism as current fact.
+
+## Change narration and version stamps
+
+### War story with a PR number
+
+**Leaked:** "Colors used to come from `--widget-*` tokens, which nothing defined, so it always rendered the fallbacks; the alias tokens fixed that (PR #88)."
+
+**Fixed:** "Colors come from the alias tokens; an undefined token renders the fallbacks."
+
+Both live facts survive — the current mechanism and the standing failure behavior — restated in the present. The bug's biography belongs to the PR and its Agent Note.
+
+### Removal narration
+
+**Leaked:** "The `probe` field is gone with the removal cut; badges ride the generic projection pair now."
+
+**Fixed:** "Badges use the generic projection pair."
+
+Readers who never saw `probe` learn nothing from its absence. "Now" contrasting with a deleted past is a version stamp.
+
+### Fixed regression → counterfactual present
+
+**Leaked:** "This used to double-encode multibyte labels."
+
+**Fixed:** "Without the byte-length guard, multibyte labels double-encode."
+
+The regression pin survives as a present-tense counterfactual that names the guard; "used to" pins it to repo archaeology instead.
+
+### Indexical version stamps
+
+**Leaked:** "Batch rendering is synchronous this cut; the async path is roadmap work."
+
+**Fixed:** "Batch rendering is synchronous." (The deferral lives in `TODO(widget-batch):` at the call site.)
+
+"This cut" / "v1" / "today" go stale the moment they merge. A historical stage name inside an Agent Note's change-story section ("the first cut shipped X") is current-state-safe; the indexical form never is.
+
+## Review choreography
+
+### Review verdicts as prose
+
+**Leaked:** "Rejected in review: caching the resolved spec. We keep resolution per-call."
+
+**Fixed (in an Agent Note's Alternatives considered):** "**Caching the resolved spec.** Rejected: the spec depends on per-call cwd, so a cache keyed by request would serve stale roots."
+
+The alternatives-considered genre is the sanctioned home; the reviewer and the round are not part of the rationale.
+
+### Draft ordinals
+
+**Leaked:** "As of v5 of this note, the loader also validates manifests."
+
+**Fixed:** "The loader validates manifests."
+
+An implemented note states shipped reality; its own revision history lives in git.
+
+## Reviewer-addressed justification
+
+### Arguing a cast
+
+**Leaked:** "The cast is safe — the SDK constructed the object, it simply doesn't declare the optionals strictly enough."
+
+**Fixed:** "The SDK constructs this object with every optional populated; the declared type is looser than the runtime guarantee."
+
+State the invariant a maintainer must not break. "It simply…" is a voice answering an objection nobody at HEAD raised. If the invariant is visible in the code, delete the comment instead.
+
+### Appeal to review authority
+
+**Leaked:** "This is correct because the reviewer confirmed the wrapping order."
+
+**Fixed:** (deleted; the wrapping order is stated in the function's `@returns`.)
+
+Correctness claims cite invariants or tests, never people.
+
+## Restatement and derivation
+
+### Control-flow narration
+
+**Leaked:** "First we normalize the label, then we truncate it, then we wrap it."
+
+**Fixed:** (deleted.)
+
+The three lines below the comment say the same thing in code.
+
+### Test walkthrough
+
+**Leaked:** "This test creates a session, sends two messages, waits for the second reply, and then asserts the log has four entries."
+
+**Fixed:** "Two round-trips must produce exactly four log entries — the projection dedupes the shared prefix."
+
+Keep only the non-obvious assertion rationale; the walkthrough restates the test body.
+
+## Hedges and planning residue
+
+### Unmarked deferral
+
+**Leaked:** "Probably fine to render eagerly for now."
+
+**Fixed:** (deleted; the deferral already has its `TODO(widget-batch):` marker.)
+
+A hedge without an owner is planning residue. If no marker exists, write one (`TODO(name): coalesce per animation frame`) instead of keeping the hedge.
+
+### Vague sizing
+
+**Leaked:** "A 64 KiB buffer should be enough for most cases."
+
+**Fixed:** "64 KiB holds the largest observed frame (48 KiB) with headroom; a larger frame fails loudly in `decode`."
+
+Replace the hedge with the actual bound and the failure behavior when it is exceeded.
+
+## Authoring-language slips
+
+**Leaked:** "The renderer runs on the client 端; see the 设计稿 for spacing. ---- 私有 ----"
+
+**Fixed:** "The renderer runs on the client side; spacing follows the Figma frame `widget-badges`."
+
+Working-language fragments and session separators are transcription residue. The Figma frame name stays: external provenance that resolves outside the repo by design.
+
+## Keeps
+
+### Issue references are durable on every surface
+
+**Keep:** "The cap applies to the complete rendered value, wrappers included (issue #1470 owns the follow-up)."
+
+An unaided pass deleted this, reasoning that issue citations belong in Agent Notes. Wrong direction: issues resolve at HEAD from any surface, and "#N owns the follow-up" is the sanctioned home for deferred work in a README. What Agent Notes and postmortems additionally sanction is citing *merged PRs* as evidence.
+
+### Dead name-drops are not "naming the owner"
+
+**Delete:** "Badge renderer over the widget seam (see the widget-rendering RFC)."
+
+An unaided pass kept this as "naming the owning document by topic". The test is resolvability, not form: no committed file answers to "the widget-rendering RFC", so the pointer is dead. Retarget it to the committed owner if one exists; otherwise delete it.
+
+### Suppression justifications
+
+**Keep (after fixing):** `// oxlint-disable-next-line no-non-null-assertion -- the one-element literal guarantees index 0.`
+
+The justification clause is required prose. When the stated reason is false (the original said "the loop guard above proves a frame exists" with no loop in sight), fix the reason; never delete it.
+
+### Measured bounds
+
+**Keep:** "Depth cap (measured: 512 nests ≈ 0.15s synchronous; 4096 blocks the loop)."
+
+The measurement pins the constant against uninformed retuning, and "measured" is the provenance that distinguishes data from a guess.
+
+### Runtime old/new is not change history
+
+**Keep:** "The old connection drains before the new one accepts."
+
+"Old" and "new" here name two live runtime objects during handover, not repository states. The change-narration ban is about repo history, not lifecycle vocabulary.
+
+## Overcorrection traps
+
+Every trap below shipped in the original purge and was caught in review. Enumerate a passage's propositions before trimming it.
+
+### Flipping an obligation into an endorsement
+
+**Original:** "These direct registrations are exceptions pending migration to slots."
+
+**Overcorrected:** "These direct registrations are sanctioned exceptions."
+
+**Right:** "These direct registrations are exceptions pending migration to slots."
+
+"Pending migration" is an obligation; "sanctioned" blesses the status quo. The trim inverted the sentence's modality while shortening it.
+
+### Promoting a hypothetical to a shipped feature
+
+**Original:** "A future IPC-based shell subclasses the executor and overrides `spawn`."
+
+**Overcorrected:** "An IPC-based shell subclasses the executor and overrides `spawn`."
+
+**Right:** "A hypothetical IPC-based shell — no such shell exists — would subclass the executor and override `spawn`."
+
+Deleting the future-marker alone turns a design illustration into a claim that the class ships. Mark the hypothetical explicitly instead of just unmarking the future.
+
+### Deleting a true fact with the transcript around it
+
+**Original:** "The gate notice narrates the check order; the notice text is also what `verify-doc-typecheck` compiles against."
+
+**Overcorrected:** "…" (whole sentence deleted as narration.)
+
+**Right:** "The notice text is what `verify-doc-typecheck` compiles against."
+
+Half the sentence was narration; the other half was a load-bearing coupling. Delete clauses, not sentences, when propositions share a line.
+
+### Dropping provenance while keeping the number
+
+**Original:** "The 4 MiB ceiling is measured: the largest generated `py-types` module is 3.1 MiB."
+
+**Overcorrected:** "The ceiling is 4 MiB; the largest generated `py-types` module is 3.1 MiB."
+
+**Right:** keep "measured".
+
+Without "measured" the 3.1 MiB reads as a definition rather than an observation, and nobody re-measures before raising the ceiling.

+ 42 - 0
.agents/skills/dsh-trim-cot-leakage/references/recall-batteries.md

@@ -0,0 +1,42 @@
+# Recall batteries
+
+Probes for [the taxonomy](../SKILL.md#taxonomy), tuned during the 2026-08 purge. Every hit needs semantic judgment — the batteries over-match by design, and they under-match by nature: each review round of the purge found shapes no battery caught, so pair them with an unpatterned read of the densest prose in scope.
+
+## Invocation rules
+
+- Add `--hidden --glob '!.git/**'` so `.agents/` is searched; ripgrep skips dot-directories by default and the purge's biggest miss risk was Agent Notes.
+- Exclusions go last so a later include cannot re-admit them: `--glob '!vendor/**' --glob '!node_modules/**' --glob '!.agents/notes/archived/**' --glob '!.agents/skills/dsh-trim-cot-leakage/references/**'` (this directory quotes leaked shapes as calibration), plus recorded fixture and snapshot directories in scope.
+- A zero-hit pattern proves nothing until you have seen it match: test it against a known-positive string before trusting the negative.
+
+## English battery
+
+```sh
+rg -n --hidden '\(decision \d|\(audit [A-Z]\d|design §|plan §|design ledger|\(B ruling|\bP-I\b|\bW\d\b|\bT\d\b' ...
+rg -n --hidden 'this PR|this branch|this stack|later PR|previous commit|this commit' ...
+rg -n --hidden 'used to |no longer|previously|the old |was renamed|was moved' ...
+rg -n --hidden '\bv1\b|this cut|\bcut \d|\btoday\b|\bfor now\b|roadmap' ...
+rg -n --hidden -i 'rejected in review|review round|reviewer|as of v\d' ...
+rg -n --hidden 'probably |should be enough|should suffice|it simply|is safe —|is safe --' ...
+rg -n --hidden '§\d' ...
+```
+
+## Chinese battery
+
+```sh
+rg -n --hidden '设计稿|评审|上一?轮|旧版|老的|不再|以前|本版|遗留|私有' ...
+rg -n --hidden '(^|[^a-zA-Z])端([^a-zA-Z]|$)' --glob '*.md' ...
+```
+
+## Known false-positive families
+
+Judged and kept during the purge; expect them again:
+
+- **Instrumental "used to"** — "the key used to sign requests" is instrumental, not temporal. The temporal form has a subject state before it ("colors used to come from…").
+- **Runtime old/new** — "the old connection drains before the new one accepts" names live objects during handover, not repo states.
+- **"This PR" in process docs** — documentation *about* PR workflow ("the PR body should…", templates, this repo's process notes) legitimately says "PR"; the ban is on a doc adopting one PR's vantage about the code.
+- **`v1` as protocol or path segment** — `/v1/chat` endpoints and wire-format names are identifiers, not version stamps.
+- **`§N` with a committed owner** — external standards (RFC 9110 §10.1.5) and committed docs that own their §-numbering stay citable by section.
+- **Contrastive "actually" and noun "wait"** — ordinary English, not hedging.
+- **"Today" in generated timestamps and CLI output samples** — recorded output keeps its voice.
+- **本版本 in zh prose** — a legitimate rendering of "this release" in versioned-artifact contexts; the banned indexical is 本版 as a bare stamp mirroring "this cut".
+- **Alternatives-considered sections** — "rejected" inside an Agent Note's genre slot is the sanctioned home, not review choreography.

+ 9 - 8
scripts/project-doc-site.spec.ts

@@ -251,7 +251,7 @@ describe('rewriteMarkdown', () => {
 })
 
 describe('docsPages locale routes', () => {
-  it('publishes every route in both locales and selects paired sources', () => {
+  it('publishes every route in both locales and uses every available Chinese counterpart', () => {
     const byRoute = new Map(docsPages.map(page => [page.route, page]))
     for (const page of docsPages.filter(page => page.locale === 'root')) {
       const counterpart = byRoute.get(`en/${page.route}`)
@@ -265,6 +265,11 @@ describe('docsPages locale routes', () => {
       } else {
         expect(counterpart?.source).toBe(page.source)
         expect(counterpart?.contentLocale).toBe(page.contentLocale)
+        const chineseSource = page.source.replace(/\.md$/, '.zh.md')
+        expect(
+          existsSync(resolve(repositoryRoot, chineseSource)),
+          `${page.route} has a Chinese counterpart but projects English`,
+        ).toBe(false)
       }
     }
   })
@@ -282,20 +287,16 @@ describe('docsPages locale routes', () => {
     }
   })
 
-  it('projects translated subsystem pages while retaining explicit English fallbacks', () => {
+  it('projects every published subsystem page in Chinese', () => {
     const rootPages = docsPages.filter(page => (
       page.locale === 'root' && page.route.startsWith('reference/subsystems/')
     ))
     const translated = rootPages.filter(page => page.contentLocale === 'zh-CN')
     const fallbacks = rootPages.filter(page => page.contentLocale === 'en-US')
 
-    expect(translated).toHaveLength(39)
+    expect(translated).toHaveLength(42)
     expect(translated.every(page => page.source.endsWith('.zh.md'))).toBe(true)
-    expect(fallbacks.map(page => page.source).sort()).toEqual([
-      'docs/subsystems/commands.md',
-      'docs/subsystems/goal.md',
-      'docs/subsystems/pty.md',
-    ])
+    expect(fallbacks).toEqual([])
   })
 
   it('publishes the Cordis core API under matching locale structures', () => {

+ 8 - 12
website/docs.ts

@@ -226,7 +226,7 @@ const develop = pairedPages([
   },
 ])
 
-const cordisTutorial = mirroredPages(([
+const cordisTutorial = pairedPages(([
   ['index.md', 'Cordis 教程', 'Cordis tutorial'],
   ['01-first-plugin.md', '1. 第一个插件', '1. Your first plugin'],
   ['02-lifecycle-and-effects.md', '2. 生命周期与副作用', '2. Lifecycle and effects'],
@@ -235,10 +235,9 @@ const cordisTutorial = mirroredPages(([
   ['05-config.md', '5. 配置', '5. Configuration'],
   ['06-composition-and-hmr.md', '6. 组合与热重载', '6. Composition and HMR'],
   ['07-into-the-harness.md', '7. 进入 Harness', '7. Into the harness'],
-] as const).map(([file, rootLabel, enLabel], order): MirroredPage => ({
+] as const).map(([file, rootLabel, enLabel], order): PairedPage => ({
   source: `docs/cordis-tutorial/${file}`,
   route: `develop/cordis-tutorial/${file}`,
-  contentLocale: 'en-US',
   label: { root: rootLabel, en: enLabel },
   sidebar: { root: 'zh-develop', en: 'en-develop' },
   section: { root: 'Cordis 教程', en: 'Cordis tutorial' },
@@ -308,12 +307,11 @@ const subsystemsReference = pairedPages(([
 })))
 
 const reference = [
-  ...mirroredPages(([
+  ...pairedPages(([
     ['docs/architecture.md', 'reference/index.md', '架构', 'Architecture', 0],
-  ] as const).map(([source, route, rootLabel, enLabel, order]): MirroredPage => ({
+  ] as const).map(([source, route, rootLabel, enLabel, order]): PairedPage => ({
     source,
     route,
-    contentLocale: 'en-US',
     label: { root: rootLabel, en: enLabel },
     sidebar: { root: 'zh-reference', en: 'en-reference' },
     section: { root: '概念', en: 'Concepts' },
@@ -369,28 +367,26 @@ const reference = [
     section: { root: 'Cordis API', en: 'Cordis Core API' },
     order: order + 5,
   }))),
-  ...mirroredPages(([
+  ...pairedPages(([
     ['goal.md', '目标', 'Goals', 14],
     ['pty.md', 'PTY 会话', 'PTY sessions', 26],
     ['commands.md', '命令', 'Human commands', 38],
-  ] as const).map(([file, rootLabel, enLabel, order]): MirroredPage => ({
+  ] as const).map(([file, rootLabel, enLabel, order]): PairedPage => ({
     source: `docs/subsystems/${file}`,
     route: `reference/subsystems/${file}`,
-    contentLocale: 'en-US',
     label: { root: rootLabel, en: enLabel },
     sidebar: { root: 'zh-reference', en: 'en-reference' },
     section: { root: '子系统', en: 'Subsystems' },
     order,
   }))),
-  ...mirroredPages(([
+  ...pairedPages(([
     ['adding-a-package.md', '新增 Package', 'Adding a package'],
     ['adding-a-tool.md', '新增 Tool', 'Adding a tool'],
     ['adding-an-llm-adapter.md', '新增 LLM Adapter', 'Adding an LLM adapter'],
     ['extension-cookbook.md', '扩展模式', 'Extension patterns'],
-  ] as const).map(([file, rootLabel, enLabel], order): MirroredPage => ({
+  ] as const).map(([file, rootLabel, enLabel], order): PairedPage => ({
     source: `docs/cookbook/${file}`,
     route: `reference/cookbook/${file}`,
-    contentLocale: 'en-US',
     label: { root: rootLabel, en: enLabel },
     sidebar: { root: 'zh-reference', en: 'en-reference' },
     section: { root: '开发手册', en: 'Cookbook' },