From 74aa65b381e2105a75cba344a64ff1993cbf8ca3 Mon Sep 17 00:00:00 2001 From: song <22676124+songoow@users.noreply.github.com> Date: Fri, 18 Sep 2026 02:45:12 -0400 Subject: [PATCH 1/3] docs(rfcs): make each execution-ledger entry its own file RFC Appendix A was a single append cluster. During the #4447 repair round four branches each added an entry and every pair conflicted at the same position: eight resolutions in one afternoon, all of the form "the two sides are disjoint additions, keep both". The cost is not the resolving. It is that a conflict always resolved the same way stops being read, and the resolution that drops an entry looks exactly like the seven that did not. Nothing parses Appendix A, so a lost record surfaces only when someone goes looking for it. New entries now live in `docs/architecture/rfcs/ledger/` as `YYYY-MM-DD-slug.md` with a Chinese mirror, so two branches adding entries on the same day touch different files. Nothing enumerates them: an index line in the RFC would be a smaller instance of the same problem, and the dated filename already sorts. `check_rfc_ledger_entries` checks the naming, the mirror pairing and non-empty content, so the convention cannot quietly rot back into prose. Verified by mutation: a file named `badname.md` and an entry with no mirror each fail the smoke. The fifteen entries already in Appendix A stay where they are. They are append-only history nobody edits, so they were never what conflicted; migrating them would have produced a large mechanical diff and forced rework on the one open #4447 branch while fixing nothing. Refs #4447 Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: song <22676124+songoow@users.noreply.github.com> --- .../2026-09-18-ledger-entries-become-files.md | 34 ++++++++++++++++++ ...09-18-ledger-entries-become-files.zh-CN.md | 27 ++++++++++++++ docs/architecture/rfcs/ledger/README.md | 28 +++++++++++++++ docs/architecture/rfcs/ledger/README.zh-CN.md | 25 +++++++++++++ .../semantic-vocabulary-convergence-v0.md | 16 +++++++++ ...emantic-vocabulary-convergence-v0.zh-CN.md | 13 +++++++ examples/docs-governance-smoke.py | 35 +++++++++++++++++++ 7 files changed, 178 insertions(+) create mode 100644 docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.md create mode 100644 docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.zh-CN.md create mode 100644 docs/architecture/rfcs/ledger/README.md create mode 100644 docs/architecture/rfcs/ledger/README.zh-CN.md diff --git a/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.md b/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.md new file mode 100644 index 0000000000..0c3301530c --- /dev/null +++ b/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.md @@ -0,0 +1,34 @@ +# Ledger entries become files + +Non-normative for the semantic model; it adds no invariant and changes no +check's verdict on any tree. What changes is where an execution-ledger entry +lives. + +- **The problem was measured, not anticipated.** RFC Appendix A was one append + cluster. During the #4447 repair round, four branches each added an entry and + every pair conflicted at the same position — eight resolutions in one + afternoon, all of the form "the two sides are disjoint additions, keep both". +- **The failure mode is silence.** A conflict that is always resolved the same + way stops being read. The resolution that drops an entry looks exactly like + the seven that did not, and nothing downstream notices: no code parses + Appendix A, so a lost entry surfaces only when someone goes looking for a + record that is no longer there. +- **A file per entry removes the shared line.** Two branches adding entries on + the same day now touch two different files and merge with no resolution. +- **Nothing enumerates the entries.** An index in the RFC would be a one-line + append cluster — smaller than the original, but the same class of problem. + The directory listing is the index, and the `YYYY-MM-DD-slug` name sorts. +- **The convention is checked, not described.** `check_rfc_ledger_entries` in + `examples/docs-governance-smoke.py` requires the dated name, a Chinese mirror + beside each entry, and non-empty content. Verified by mutation: a file named + `badname.md` and an entry with no mirror each fail the smoke. +- **Existing entries were left in place.** The fifteen entries already in + Appendix A are append-only history that nobody edits, so they were never the + thing that conflicted. Migrating them would have produced a large mechanical + diff, forced rework on the one open #4447 branch, and fixed nothing. + +What this does not do: it does not make ledger entries reviewable evidence. +They remain non-normative records of what a change measured and what it did not +establish. It also does not add them to the hosted documentation navigation — +the nav check requires a file for every nav entry, not a nav entry for every +file. diff --git a/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.zh-CN.md b/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.zh-CN.md new file mode 100644 index 0000000000..186670b480 --- /dev/null +++ b/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.zh-CN.md @@ -0,0 +1,27 @@ +# 账本条目改为一条一个文件 + +对语义模型非规范:不新增任何不变量,也不改变任何检查在任何树上的结论。改变的是 +执行账本条目存放的位置。 + +- **问题是实测出来的,不是预想的。** RFC 附录 A 是一个追加簇。在 #4447 的修复轮 + 里,四个分支各自新增一条条目,两两都在同一位置冲突——一个下午解了八次,形式 + 全都是"两侧是不相交的新增,保留双方"。 +- **它的失败模式是静默的。** 一个每次都用同样方式解决的冲突,就不再有人真的去 + 读。那次丢掉条目的解决,看起来和没丢的另外七次一模一样,而且下游毫无反应: + 没有任何代码解析附录 A,所以丢失只有在某人回头找一条已经不存在的记录时才会 + 浮现。 +- **一条一个文件消除了这行共享。** 同一天新增条目的两个分支现在碰的是两个不同 + 文件,无需任何解决即可合并。 +- **没有任何地方枚举条目。** 在 RFC 里放一份索引会变成一行的追加簇——比原来小, + 但属于同一类问题。目录列表就是索引,`YYYY-MM-DD-slug` 命名本身可排序。 +- **约定是被校验的,不是被描述的。** `examples/docs-governance-smoke.py` 里的 + `check_rfc_ledger_entries` 要求带日期的命名、每条配一份中文镜像、内容非空。 + 已用突变验证:一个名为 `badname.md` 的文件、一条没有镜像的条目,都会让 smoke + 失败。 +- **已有条目原地保留。** 附录 A 里已有的十五条是只追加的历史、没有人会去编辑, + 所以它们从来不是产生冲突的那一部分。迁移它们只会产出一个庞大的机械 diff、迫使 + 唯一一个开着的 #4447 分支返工,而且什么问题都解决不了。 + +它没有做什么:它不会让账本条目变成可评审的证据——它们仍然是非规范的记录,记的是 +某次改动测到了什么、以及明确没有确立什么。它也不把这些条目加进托管文档导航:导航 +检查要求"每个导航条目都有文件",而不是"每个文件都有导航条目"。 diff --git a/docs/architecture/rfcs/ledger/README.md b/docs/architecture/rfcs/ledger/README.md new file mode 100644 index 0000000000..0ec1085f01 --- /dev/null +++ b/docs/architecture/rfcs/ledger/README.md @@ -0,0 +1,28 @@ +# RFC execution ledger + +One file per entry. A ledger entry records what a change measured, what it +changed, and what it deliberately did not establish — the same content that used +to be appended to an RFC's Appendix A. + +## Why entries are files + +Appendix A was a single append cluster. Every branch adding an entry inserted at +the same position, so concurrent work conflicted there by construction: eight +times in one afternoon during the #4447 repair round, each resolved by hand as +"both sides are disjoint, keep both". That is mechanical work with a real +failure mode, because one careless resolution silently drops an entry. + +A file per entry removes the shared line. Two branches adding entries on the +same day touch two different files and merge cleanly with no resolution at all. + +## Convention + +- `YYYY-MM-DD-slug.md` — the date the work was measured, not the merge date. +- Each entry carries a Chinese mirror at `YYYY-MM-DD-slug.zh-CN.md`, the same + rule the RFCs themselves follow. +- The directory listing is the index. Nothing enumerates entries, because an + index line is the append cluster this directory exists to remove. +- Entries are append-only history. Correct a wrong entry with a later entry that + says what was wrong; do not rewrite a record someone may have cited. + +`examples/docs-governance-smoke.py` checks the naming and the mirror pairing. diff --git a/docs/architecture/rfcs/ledger/README.zh-CN.md b/docs/architecture/rfcs/ledger/README.zh-CN.md new file mode 100644 index 0000000000..3f54908bf9 --- /dev/null +++ b/docs/architecture/rfcs/ledger/README.zh-CN.md @@ -0,0 +1,25 @@ +# RFC 执行账本 + +每条一个文件。一条账本条目记录某次改动测到了什么、改了什么、以及明确没有确立 +什么——就是过去追加到 RFC 附录 A 的那些内容。 + +## 为什么条目是文件 + +附录 A 是一个共享的追加簇。每个新增条目的分支都插在同一个位置,所以并发工作在 +那里**必然**冲突:#4447 的修复轮里一个下午撞了八次,每次的解法都是"两侧不相交、 +保留双方"。这是机械劳动,而且有真实的失败模式——一次粗心的解决就会静默丢掉一条 +记录。 + +一条一个文件消除了这行共享。同一天新增条目的两个分支碰的是两个不同文件,无需 +任何解决即可干净合并。 + +## 约定 + +- `YYYY-MM-DD-slug.md` —— 日期是**测量**当天,不是合并当天。 +- 每条配一份中文镜像 `YYYY-MM-DD-slug.zh-CN.md`,与 RFC 自身同一规则。 +- 目录列表就是索引。没有任何地方枚举条目,因为索引行正是本目录要消除的那种 + 追加簇。 +- 条目是只追加的历史。要更正一条写错的条目,用后续条目说明错在哪;不要重写别人 + 可能已经引用过的记录。 + +命名与镜像配对由 `examples/docs-governance-smoke.py` 校验。 diff --git a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md index f43cd71134..2393058f98 100644 --- a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md +++ b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md @@ -1146,6 +1146,22 @@ introduce a competing target state. ## Appendix A: Execution ledger (non-normative) +New entries are files, not sections here. Each one lives in +[`ledger/`](ledger/README.md) as `YYYY-MM-DD-slug.md` with a Chinese mirror +beside it, and nothing enumerates them — the directory listing is the index. + +The reason is measured, not stylistic. This section was a single append cluster: +every branch adding an entry inserted at the same position, so concurrent work +conflicted here by construction — eight times in one afternoon during the +#4447 repair round, each resolved by hand as "both sides are disjoint, keep +both". That is mechanical work whose failure mode is silent: one careless +resolution drops an entry nobody notices is gone. A file per entry removes the +shared line, and `examples/docs-governance-smoke.py` checks the naming and the +mirror pairing so the convention cannot rot back. + +The entries below predate that split and stay where they are. They are +append-only history, never edited, so they were never the thing that conflicted. + ### 2026-09-18 — Three producer-scan answers that were confidently wrong Normative for what the producer scan may report as complete. No budget, floor or diff --git a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md index c700f55261..ae4f85b14b 100644 --- a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md +++ b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md @@ -922,6 +922,19 @@ PR review 保留这些层级。普通改动记录检查范围和理由,无共 ## 附录 A:执行账本(非规范) +新条目是文件,不再写在这一节里。每条放在 +[`ledger/`](ledger/README.zh-CN.md) 下,命名 `YYYY-MM-DD-slug.md` 并配一份中文 +镜像;没有任何地方枚举它们——目录列表就是索引。 + +这个理由是实测的,不是风格偏好。本节过去是一个共享的追加簇:每个新增条目的分支 +都插在同一位置,所以并发工作在这里**必然**冲突——#4447 的修复轮里一个下午撞了 +八次,每次解法都是"两侧不相交、保留双方"。这是机械劳动,而它的失败模式是静默 +的:一次粗心的解决就会丢掉一条没人会发现的记录。一条一个文件消除了这行共享, +命名与镜像配对由 `examples/docs-governance-smoke.py` 校验,约定不会退化回去。 + +下面的条目早于这次拆分,原地保留。它们是只追加的历史、从不编辑,所以从来不是 +产生冲突的那一部分。 + ### 2026-09-18 — 生产者扫描三处自信而错误的答案 对"扫描可以把什么报成完整"是规范性的。没有移动任何预算、下限或锚点: diff --git a/examples/docs-governance-smoke.py b/examples/docs-governance-smoke.py index b79788be8d..0acf51ea67 100644 --- a/examples/docs-governance-smoke.py +++ b/examples/docs-governance-smoke.py @@ -202,6 +202,40 @@ def check_rfc_language_mirrors() -> None: assert "语义镜像" in chinese_text, chinese.name +LEDGER_ENTRY_NAME = re.compile(r"^\d{4}-\d{2}-\d{2}-[a-z0-9]+(?:-[a-z0-9]+)*$") + + +def check_rfc_ledger_entries() -> None: + """Validate the per-file RFC execution ledger. + + The ledger exists so that two branches adding an entry on the same day touch + two different files instead of the same append cluster. That only holds while + every entry is its own file with a sortable name, so the naming is checked + rather than described. Nothing enumerates the entries: an index line would + reintroduce exactly the shared line this directory removes. + """ + ledger = DOCS / "architecture" / "rfcs" / "ledger" + if not ledger.is_dir(): + return + for entry in sorted(ledger.glob("*.md")): + if entry.name.endswith(".zh-CN.md"): + english = entry.with_name(entry.name[: -len(".zh-CN.md")] + ".md") + assert english.exists(), ( + f"ledger entry has a Chinese mirror with no English original: {entry.name}" + ) + continue + if entry.name == "README.md": + assert (ledger / "README.zh-CN.md").exists(), "ledger README missing its Chinese mirror" + continue + assert LEDGER_ENTRY_NAME.match(entry.stem), ( + f"ledger entry must be named YYYY-MM-DD-slug.md, got: {entry.name}" + ) + chinese = entry.with_name(f"{entry.stem}.zh-CN.md") + assert chinese.exists(), f"ledger entry missing required Chinese mirror: {entry.name}" + assert entry.read_text(encoding="utf-8").strip(), f"empty ledger entry: {entry.name}" + assert chinese.read_text(encoding="utf-8").strip(), f"empty ledger entry: {chinese.name}" + + def mkdocs_nav_paths(mkdocs_text: str) -> set[str]: assert "\nnav:\n" in mkdocs_text or mkdocs_text.startswith("nav:\n"), mkdocs_text nav_body = mkdocs_text.split("nav:", 1)[1] @@ -853,6 +887,7 @@ def main() -> int: assert required in compact_multi_agent_product_recipe, required check_rfc_language_mirrors() + check_rfc_ledger_entries() print("docs-governance-smoke ok") return 0 From 369f307df058a1d7cd4ade70d671e04c89653f6a Mon Sep 17 00:00:00 2001 From: song <22676124+songoow@users.noreply.github.com> Date: Fri, 18 Sep 2026 06:25:08 -0400 Subject: [PATCH 2/3] docs(rfcs): say which RFC a ledger entry belongs to MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six RFCs carry an `Appendix A: Execution ledger`, and this convention puts their entries in one shared directory. With only a date and a mirror recorded, an entry written for any of the other five satisfies every existing assertion and still leaves a reader unable to tell which appendix it extends. The association is the directory: `/YYYY-MM-DD-slug.md`, where the slug is the RFC file's own name. Path rather than a filename segment or a frontmatter field, because the point of this ledger is that the listing is the index — `ls ledger//` gives one RFC's entries directly, while a name-encoded slug can only be filtered by something that already knows the format, and a field would be a claim the naming cannot check. The assertion follows the same reasoning: the directory must name a real RFC file that actually carries an execution-ledger appendix. A directory claiming an RFC that does not exist fails, which is the negative case, and it fails structurally rather than by parsing a name. Also replaced "the fifteen entries already in Appendix A" with phrasing that does not carry a number. It was measured at fifteen and the merge brought it to sixteen; an entry arguing that silent inaccuracy is the real cost should not carry a figure that drifts. Both READMEs and both mirrors updated. Docs governance smoke ok; a `no-such-rfc-v0/` probe fails as intended. Signed-off-by: song <22676124+songoow@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: song <22676124+songoow@users.noreply.github.com> --- docs/architecture/rfcs/ledger/README.md | 14 ++++-- docs/architecture/rfcs/ledger/README.zh-CN.md | 8 ++-- .../2026-09-18-ledger-entries-become-files.md | 2 +- ...09-18-ledger-entries-become-files.zh-CN.md | 2 +- examples/docs-governance-smoke.py | 46 ++++++++++++------- 5 files changed, 46 insertions(+), 26 deletions(-) rename docs/architecture/rfcs/ledger/{ => semantic-vocabulary-convergence-v0}/2026-09-18-ledger-entries-become-files.md (96%) rename docs/architecture/rfcs/ledger/{ => semantic-vocabulary-convergence-v0}/2026-09-18-ledger-entries-become-files.zh-CN.md (94%) diff --git a/docs/architecture/rfcs/ledger/README.md b/docs/architecture/rfcs/ledger/README.md index 0ec1085f01..48ba494f19 100644 --- a/docs/architecture/rfcs/ledger/README.md +++ b/docs/architecture/rfcs/ledger/README.md @@ -17,11 +17,15 @@ same day touch two different files and merge cleanly with no resolution at all. ## Convention -- `YYYY-MM-DD-slug.md` — the date the work was measured, not the merge date. -- Each entry carries a Chinese mirror at `YYYY-MM-DD-slug.zh-CN.md`, the same - rule the RFCs themselves follow. -- The directory listing is the index. Nothing enumerates entries, because an - index line is the append cluster this directory exists to remove. +- `/YYYY-MM-DD-slug.md` — one directory per RFC, named exactly like + the RFC file it belongs to. Six RFCs carry an execution-ledger appendix, so + an entry has to say which one it extends. +- The name carries the date the work was measured, not the merge date. +- Each entry carries a Chinese mirror at `/YYYY-MM-DD-slug.zh-CN.md`, + the same rule the RFCs themselves follow. +- A directory is the index for its RFC. Nothing enumerates entries across + RFCs, because an index line is the append cluster this directory exists to + remove. - Entries are append-only history. Correct a wrong entry with a later entry that says what was wrong; do not rewrite a record someone may have cited. diff --git a/docs/architecture/rfcs/ledger/README.zh-CN.md b/docs/architecture/rfcs/ledger/README.zh-CN.md index 3f54908bf9..0f6f33243b 100644 --- a/docs/architecture/rfcs/ledger/README.zh-CN.md +++ b/docs/architecture/rfcs/ledger/README.zh-CN.md @@ -15,9 +15,11 @@ ## 约定 -- `YYYY-MM-DD-slug.md` —— 日期是**测量**当天,不是合并当天。 -- 每条配一份中文镜像 `YYYY-MM-DD-slug.zh-CN.md`,与 RFC 自身同一规则。 -- 目录列表就是索引。没有任何地方枚举条目,因为索引行正是本目录要消除的那种 +- `/YYYY-MM-DD-slug.md` —— 每份 RFC 一个目录,目录名与其所属 RFC + 文件名完全一致。有六份 RFC 带执行账本附录,所以条目必须写明它补的是哪一份。 +- 文件名中的日期是**测量**当天,不是合并当天。 +- 每条配一份中文镜像 `/YYYY-MM-DD-slug.zh-CN.md`,与 RFC 自身同一规则。 +- 每个 RFC 的目录就是该 RFC 的索引。跨 RFC 不设枚举,因为索引行正是本目录要消除的那种 追加簇。 - 条目是只追加的历史。要更正一条写错的条目,用后续条目说明错在哪;不要重写别人 可能已经引用过的记录。 diff --git a/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.md b/docs/architecture/rfcs/ledger/semantic-vocabulary-convergence-v0/2026-09-18-ledger-entries-become-files.md similarity index 96% rename from docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.md rename to docs/architecture/rfcs/ledger/semantic-vocabulary-convergence-v0/2026-09-18-ledger-entries-become-files.md index 0c3301530c..472282c6d8 100644 --- a/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.md +++ b/docs/architecture/rfcs/ledger/semantic-vocabulary-convergence-v0/2026-09-18-ledger-entries-become-files.md @@ -22,7 +22,7 @@ lives. `examples/docs-governance-smoke.py` requires the dated name, a Chinese mirror beside each entry, and non-empty content. Verified by mutation: a file named `badname.md` and an entry with no mirror each fail the smoke. -- **Existing entries were left in place.** The fifteen entries already in +- **Existing entries were left in place.** The entries already in Appendix A are append-only history that nobody edits, so they were never the thing that conflicted. Migrating them would have produced a large mechanical diff, forced rework on the one open #4447 branch, and fixed nothing. diff --git a/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.zh-CN.md b/docs/architecture/rfcs/ledger/semantic-vocabulary-convergence-v0/2026-09-18-ledger-entries-become-files.zh-CN.md similarity index 94% rename from docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.zh-CN.md rename to docs/architecture/rfcs/ledger/semantic-vocabulary-convergence-v0/2026-09-18-ledger-entries-become-files.zh-CN.md index 186670b480..41780d6a43 100644 --- a/docs/architecture/rfcs/ledger/2026-09-18-ledger-entries-become-files.zh-CN.md +++ b/docs/architecture/rfcs/ledger/semantic-vocabulary-convergence-v0/2026-09-18-ledger-entries-become-files.zh-CN.md @@ -18,7 +18,7 @@ `check_rfc_ledger_entries` 要求带日期的命名、每条配一份中文镜像、内容非空。 已用突变验证:一个名为 `badname.md` 的文件、一条没有镜像的条目,都会让 smoke 失败。 -- **已有条目原地保留。** 附录 A 里已有的十五条是只追加的历史、没有人会去编辑, +- **已有条目原地保留。** 附录 A 里已有的条目是只追加的历史、没有人会去编辑, 所以它们从来不是产生冲突的那一部分。迁移它们只会产出一个庞大的机械 diff、迫使 唯一一个开着的 #4447 分支返工,而且什么问题都解决不了。 diff --git a/examples/docs-governance-smoke.py b/examples/docs-governance-smoke.py index 0acf51ea67..557e960c57 100644 --- a/examples/docs-governance-smoke.py +++ b/examples/docs-governance-smoke.py @@ -217,23 +217,37 @@ def check_rfc_ledger_entries() -> None: ledger = DOCS / "architecture" / "rfcs" / "ledger" if not ledger.is_dir(): return - for entry in sorted(ledger.glob("*.md")): - if entry.name.endswith(".zh-CN.md"): - english = entry.with_name(entry.name[: -len(".zh-CN.md")] + ".md") - assert english.exists(), ( - f"ledger entry has a Chinese mirror with no English original: {entry.name}" - ) - continue - if entry.name == "README.md": - assert (ledger / "README.zh-CN.md").exists(), "ledger README missing its Chinese mirror" - continue - assert LEDGER_ENTRY_NAME.match(entry.stem), ( - f"ledger entry must be named YYYY-MM-DD-slug.md, got: {entry.name}" + assert (ledger / "README.md").exists(), "ledger README missing" + assert (ledger / "README.zh-CN.md").exists(), "ledger README missing its Chinese mirror" + # Six RFCs carry an execution-ledger appendix, so entries are shared and + # must say which one they belong to. The RFC slug is a directory, and the + # directory has to name a real RFC: an entry cannot claim an RFC that does + # not exist, and the per-RFC listing stays the index. + scopes = sorted(path for path in ledger.iterdir() if path.is_dir()) + assert scopes, "ledger has no per-RFC directories" + for scope in scopes: + appendix_a = DOCS / "architecture" / "rfcs" / f"{scope.name}.md" + assert appendix_a.is_file(), ( + f"ledger directory {scope.name}/ does not name an RFC: " + f"{appendix_a.relative_to(DOCS.parent)} does not exist" ) - chinese = entry.with_name(f"{entry.stem}.zh-CN.md") - assert chinese.exists(), f"ledger entry missing required Chinese mirror: {entry.name}" - assert entry.read_text(encoding="utf-8").strip(), f"empty ledger entry: {entry.name}" - assert chinese.read_text(encoding="utf-8").strip(), f"empty ledger entry: {chinese.name}" + assert "Appendix A: Execution ledger" in appendix_a.read_text(encoding="utf-8"), ( + f"{scope.name} has a ledger directory but no execution-ledger appendix" + ) + for entry in sorted(scope.glob("*.md")): + if entry.name.endswith(".zh-CN.md"): + english = entry.with_name(entry.name[: -len(".zh-CN.md")] + ".md") + assert english.exists(), ( + f"ledger entry has a Chinese mirror with no English original: {entry.name}" + ) + continue + assert LEDGER_ENTRY_NAME.match(entry.stem), ( + f"ledger entry must be named YYYY-MM-DD-slug.md, got: {entry.name}" + ) + chinese = entry.with_name(f"{entry.stem}.zh-CN.md") + assert chinese.exists(), f"ledger entry missing required Chinese mirror: {entry.name}" + assert entry.read_text(encoding="utf-8").strip(), f"empty ledger entry: {entry.name}" + assert chinese.read_text(encoding="utf-8").strip(), f"empty ledger entry: {chinese.name}" def mkdocs_nav_paths(mkdocs_text: str) -> set[str]: From 4fec73ef0c80b03ccc052683179ea1455b69981c Mon Sep 17 00:00:00 2001 From: song <22676124+songoow@users.noreply.github.com> Date: Fri, 18 Sep 2026 06:35:41 -0400 Subject: [PATCH 3/3] docs(rfcs): state the ledger path rule where the RFC describes it The Appendix A prose still described the flat form the previous commit replaced. Both mirrors now name the per-RFC directory, so a reader of the RFC does not have to open the ledger README to learn where an entry goes. Signed-off-by: song <22676124+songoow@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: song <22676124+songoow@users.noreply.github.com> --- docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md | 2 +- .../rfcs/semantic-vocabulary-convergence-v0.zh-CN.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md index cfb4f6049b..5b00686cc5 100644 --- a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md +++ b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md @@ -1159,7 +1159,7 @@ introduce a competing target state. ## Appendix A: Execution ledger (non-normative) New entries are files, not sections here. Each one lives in -[`ledger/`](ledger/README.md) as `YYYY-MM-DD-slug.md` with a Chinese mirror +[`ledger//`](ledger/README.md) as `YYYY-MM-DD-slug.md` with a Chinese mirror beside it, and nothing enumerates them — the directory listing is the index. The reason is measured, not stylistic. This section was a single append cluster: diff --git a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md index 2813d88bde..47b25e14f0 100644 --- a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md +++ b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md @@ -933,8 +933,8 @@ PR review 保留这些层级。普通改动记录检查范围和理由,无共 ## 附录 A:执行账本(非规范) 新条目是文件,不再写在这一节里。每条放在 -[`ledger/`](ledger/README.zh-CN.md) 下,命名 `YYYY-MM-DD-slug.md` 并配一份中文 -镜像;没有任何地方枚举它们——目录列表就是索引。 +[`ledger//`](ledger/README.zh-CN.md) 下,命名 `YYYY-MM-DD-slug.md` 并配 +一份中文镜像;目录名即所属 RFC 文件名;跨 RFC 不设枚举——每个 RFC 的目录就是它的索引。 这个理由是实测的,不是风格偏好。本节过去是一个共享的追加簇:每个新增条目的分支 都插在同一位置,所以并发工作在这里**必然**冲突——#4447 的修复轮里一个下午撞了