Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions docs/architecture/rfcs/ledger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 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

- `<rfc-slug>/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 `<rfc-slug>/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.

`examples/docs-governance-smoke.py` checks the naming and the mirror pairing.
27 changes: 27 additions & 0 deletions docs/architecture/rfcs/ledger/README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# RFC 执行账本

每条一个文件。一条账本条目记录某次改动测到了什么、改了什么、以及明确没有确立
什么——就是过去追加到 RFC 附录 A 的那些内容。

## 为什么条目是文件

附录 A 是一个共享的追加簇。每个新增条目的分支都插在同一个位置,所以并发工作在
那里**必然**冲突:#4447 的修复轮里一个下午撞了八次,每次的解法都是"两侧不相交、
保留双方"。这是机械劳动,而且有真实的失败模式——一次粗心的解决就会静默丢掉一条
记录。

一条一个文件消除了这行共享。同一天新增条目的两个分支碰的是两个不同文件,无需
任何解决即可干净合并。

## 约定

- `<rfc-slug>/YYYY-MM-DD-slug.md` —— 每份 RFC 一个目录,目录名与其所属 RFC
文件名完全一致。有六份 RFC 带执行账本附录,所以条目必须写明它补的是哪一份。
- 文件名中的日期是**测量**当天,不是合并当天。
- 每条配一份中文镜像 `<rfc-slug>/YYYY-MM-DD-slug.zh-CN.md`,与 RFC 自身同一规则。
- 每个 RFC 的目录就是该 RFC 的索引。跨 RFC 不设枚举,因为索引行正是本目录要消除的那种
追加簇。
- 条目是只追加的历史。要更正一条写错的条目,用后续条目说明错在哪;不要重写别人
可能已经引用过的记录。

命名与镜像配对由 `examples/docs-governance-smoke.py` 校验。
Original file line number Diff line number Diff line change
@@ -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 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.
Original file line number Diff line number Diff line change
@@ -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 分支返工,而且什么问题都解决不了。

它没有做什么:它不会让账本条目变成可评审的证据——它们仍然是非规范的记录,记的是
某次改动测到了什么、以及明确没有确立什么。它也不把这些条目加进托管文档导航:导航
检查要求"每个导航条目都有文件",而不是"每个文件都有导航条目"。
16 changes: 16 additions & 0 deletions docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,22 @@ introduce a competing target state.

## Appendix A: Execution ledger (non-normative)

New entries are files, not sections here. Each one lives in
[`ledger/<rfc-slug>/`](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-17 — B3: the retirement metric separates readers from mentions

The six legacy should-run fields were budgeted by a token count: modules whose
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,19 @@ PR review 保留这些层级。普通改动记录检查范围和理由,无共

## 附录 A:执行账本(非规范)

新条目是文件,不再写在这一节里。每条放在
[`ledger/<rfc-slug>/`](ledger/README.zh-CN.md) 下,命名 `YYYY-MM-DD-slug.md` 并配
一份中文镜像;目录名即所属 RFC 文件名;跨 RFC 不设枚举——每个 RFC 的目录就是它的索引。

这个理由是实测的,不是风格偏好。本节过去是一个共享的追加簇:每个新增条目的分支
都插在同一位置,所以并发工作在这里**必然**冲突——#4447 的修复轮里一个下午撞了
八次,每次解法都是"两侧不相交、保留双方"。这是机械劳动,而它的失败模式是静默
的:一次粗心的解决就会丢掉一条没人会发现的记录。一条一个文件消除了这行共享,
命名与镜像配对由 `examples/docs-governance-smoke.py` 校验,约定不会退化回去。

下面的条目早于这次拆分,原地保留。它们是只追加的历史、从不编辑,所以从来不是
产生冲突的那一部分。

### 2026-09-17 — B3:退休指标把读者与提及分开

六个旧 should-run 字段此前按 token 计数计入预算:文本里出现该独立字段名的模块
Expand Down
49 changes: 49 additions & 0 deletions examples/docs-governance-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,54 @@ 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
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"
)
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]:
assert "\nnav:\n" in mkdocs_text or mkdocs_text.startswith("nav:\n"), mkdocs_text
nav_body = mkdocs_text.split("nav:", 1)[1]
Expand Down Expand Up @@ -853,6 +901,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

Expand Down
Loading