The manifest excluded docs/tool-catalog/ and docs/persistence-catalog/ as
directories; the trailing slash is a deliberate path boundary, so the
flattened single files no longer matched and lost their generated-doc
classification — the gate would have accepted a hand-added .zh.md twin it
must reject. The entries now name the files.
Review findings on the config catalog:
The transitive-paste closure deduplicated by bare name, so two DIFFERENT
package-local declarations sharing a name would silently collapse to the
first one pasted — and a reference satisfied by the wrong declaration is a
wrong catalog, not just a thin one. Every resolution is now identity-checked
by source pointer: reaching the same declaration again is benign, while a
name that resolves to two distinct declarations, to conflicting imports, or
to a declaration in one file and an import in another is a violation — a
verbatim fence has a single flat namespace, so the fix is a rename at the
source. A spec case pins the two-declarations collision.
docs/config-catalog.md also joins the translation-pairing exclusions: it is
a generated English-only doc, and without the entry the gate would accept a
hand-added .zh.md twin it must reject.
Human-annotated gold pairs land as docs/i18n/style-samples.md (bilingual
by construction, excluded from pairing) and outrank prose tone rules.
translation-rules gains a Voice section; shape stays gate-owned so the
writer optimizes for natural Chinese. The skill's translate step becomes
two passes: native-author writing, then clause-level fidelity check.
Terminology rulings: hash -> 哈希 (blob 哈希/提交哈希), HMR and fiber
confirmed as tabled.
docs/persistence-catalog/log-events.md enumerates every SessionEventMap
member — the owning dsh-session vocabulary plus the dsh-compact and
dsh-hook-protocol declaration merges — with payload, surface/log-only badge,
JSDoc prose, and declaration site. scripts/gen-persistence-catalog.ts is a
pure AST pass in the gen-cordis-catalog mold: verify-persistence-catalog
(--check) joins doc-sync, so a stale committed catalog fails pre-push and CI.
The walk enforces JSDoc completeness (every member needs description prose;
@mode is rejected as a category error — log events do not dispatch on the
cordis bus), derives the surface badge from the SurfaceEventType union with a
stale-member cross-check, and hard-errors on duplicate declarations. Payloads
render through the TypeScript printer so newline-separated multi-line type
literals still emit valid one-line fragments.
Documented the five previously JSDoc-less core events (turn/step boundaries,
tool/call), removed the two stray @mode tags on the hook/* merges, and
replaced the hand-restated event enumerations (session.md hook/* table,
compact README table, hook-protocol README bullets, session README name-list
— whose merge note had already drifted) with links to the catalog. RFC:
docs/rfc/implemented/process/2026-07-04-persistence-log-catalog.md.
New docs must not enlarge the translation backlog: any date-named
document (yyyy-mm-dd-*.md, i.e. an RFC) dated on/after the manifest's
requiredSince cutoff must merge with its complete pair, independent of
the required back-catalog list. Cutoff ships at 2026-07-05, so the
existing 2026-07-04 RFC wave is grandfathered into the batch backlog
and everything after is bilingual from birth.
The date comes from the filename, deliberately: it is deterministic
from tree content alone — no git history (shallow CI checkouts hold),
no PR base ref — matching the gate's pure-content design. A proposal
dated before the cutoff that merges later escapes the rule; that is
the graceful grandfathering of in-flight work, not a hole.
--list marks such files (required by date); contract and RFC updated
in both languages and the pairs re-recorded.
Redesign per review: neither language is canonical. A pair is three
sibling files — foo.md, foo.zh.md, foo.i18n.yaml — and either language
may be authored first (a Chinese-first RFC is as legitimate as an
English-first one). The sidecar record holds the FULL git blob hash of
both sides as of the last confirmed-consistent state, replacing the
in-file one-directional fingerprint; editing either side without
re-confirming the pair goes red. New --write mode re-records a pair
after both sides are brought in line, making the confirmation a
reviewable yaml diff. Pairs merge whole (completeness enforced).
- gate rewritten around pair anchors (union of .zh.md and .i18n.yaml
remnants) so half-deleted pairs are caught from either side; red/green
proven for en-only edit, zh-only edit, missing record, and a record
for an excluded file
- verify-rfc-classification now skips .zh.md counterparts (same RFC,
indexed via its English filename; the pairing gate owns consistency)
- docs/i18n/README.md + translation-rules.md reframed bidirectionally
(terminology table binds both directions; typography section governs
the Chinese side); zh counterparts updated; skill workflow updated
- RFC amended to the shipped design, records the English-canonical
in-file-fingerprint model as considered-and-revised; RFC translated
(docs/rfc/.../2026-07-02-bilingual-docs-and-pairing-gate.zh.md) and
added to the required frontier
- generated docs stay excluded with the follow-up recorded: teach the
generators to emit Chinese, then de-list
First backlog item translated with the dsh-translate-docs skill: full-file
translation, terminology per docs/i18n/terminology.md, structure locked to
the source (11 headings, 10 byte-identical code blocks), fingerprinted and
added to the manifest's required list.
Establish EN->ZH bilingual documentation for the README and docs tree:
- docs/i18n/README.md — the pairing contract: sibling foo.md <-> foo.zh.md,
English canonical, blob-hash source fingerprints, language switchers,
scope/exclusions, and a manifest-driven rollout ratchet.
- docs/i18n/translation-rules.md — how to translate: faithfulness, structure
preservation, terminology discipline over docs/i18n/terminology.md, and
typography rules grounded in MDN/K8s/Vue/clreq conventions.
- .agents/skills/dsh-translate-docs — the committed agent workflow, following
the dsh-code-review pattern of deferring to docs as sources of truth.
- scripts/verify-translation-pairing.ts + manifest — a doc-sync gate: required
pairs exist; every existing .zh.md is fresh (fingerprint = current source
blob), switcher-linked, structure-matched, and non-orphaned; excluded
(generated) docs stay unpaired. --list prints the translation work list.
- RFC (implemented/process) recording the decision and the alternatives.
- Dogfood: README.zh.md and the two i18n docs translated under their own rules.
Gates: doc-sync green including the new gate; red/green proven for stale
fingerprint, orphan, and excluded-file violations.