From 1b67f3a8e146becfdc80f33b7e54e1c297f1496a Mon Sep 17 00:00:00 2001 From: song <22676124+songoow@users.noreply.github.com> Date: Thu, 17 Sep 2026 05:29:49 -0400 Subject: [PATCH] docs(semantics): name what measures each target surface, not a snapshot of it Section 11's target table gives a frozen baseline and an end state, and nothing says how a reader finds the current value. The first version of this PR filled that gap with a dated `Measured 2026-09-17` column. That was the wrong fix, for two reasons this rework removes. It was in the wrong place. The document map says Section 11 is the normative delivery plan and that "dated progress entries do not amend normative sections", and issue #4447 owns delivery status. A dated column inside the normative table, carrying a note claiming it is not normative, argues with the maintenance contract instead of following it. It was also redundant work with a failure mode. Eight of the ten surfaces are already printed by the drift smoke on every run -- `same_runtime_forks_semantic`, `multi_value_twins`, one `.py` / `.ts` pair per legacy field, `independently_maintained`. A hand-written column transcribes output a command already produces, goes stale on the next merge, and invites exactly the error the first version shipped: a merge-candidate count copied from a raw grouping without the registry filter the surrounding numbers carry. So the column now names the command and field that measure each surface, the way Section 9 names a test for each claim, and carries no values at all. A reader who wants the current state runs the command. Two surfaces honestly say no counter exists: the `effective_action` slot split is a Q6 decision, and merge candidates are only reachable through `merge_candidate_groups()` because no command prints them yet. Where a capability is not on `main`, the cell says which PR adds it rather than describing it as present. Dated values stay in issue #4447, which the RFC already designates as the owner of delivery status. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: song <22676124+songoow@users.noreply.github.com> --- .../semantic-vocabulary-convergence-v0.md | 36 ++++++++++++------- ...emantic-vocabulary-convergence-v0.zh-CN.md | 33 ++++++++++------- 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md index 864aa624c1..79e44bc64c 100644 --- a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md +++ b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md @@ -848,18 +848,30 @@ state at which this RFC is complete; each row is a registry budget or a vocabulary property the smoke can check. Rows marked *open* wait on a Section 12 decision and are the reason the plan is a skeleton until those are recorded. -| Surface | Baseline (`1dc6ad8d8`) | Target when this RFC closes | Reached by | -| --- | --- | --- | --- | -| `effective_action` values | 33 literals, no owner symbol | one enum owner; `skip`, `observe_replay`, `block_replay`, and the two `quota_action_selection_*` codes gone from the decision slot; 32 decision values after accounting for the five previously missed producers and retiring the synthetic operator_gate value | M1 | -| `effective_action` slots in one envelope | 3 vocabularies under one field name | 1, or a registered union if Q6 keeps the field | M1 (Q6) | -| Turn vocabularies | 3 sets, 28 values, 21 distinct, 7 redundant spellings | 3 sets kept; projection and decision table generated and checked; spellings unchanged unless Q10 sets a merge | M2 (Q2, Q10 *open*) | -| Same-runtime forks, semantic | 18 names | 0 | baseline PRs | -| Conflicting values, semantic | 2 names | 0 | baseline PRs | -| Multi-value forks | 4 (1 misclassified) | 0 after `scope` declares bounded-context names | M0.5 + baseline PRs | -| Multi-value twins | 19 | 0 | baseline PRs | -| Legacy should-run fields | 6 fields, 124 py / 10 ts module mentions | 0 fields | M3, identifier-counted | -| Merge-candidate groups | 32 unreviewed | every group classified; only `same_semantics` groups merged | classification PR, then per-group PRs | -| Control-plane py/ts twins | 43 | follows the TypeScript migration RFC; no target here | M4 | +| Surface | Baseline (`1dc6ad8d8`) | Measured by | Target when this RFC closes | Reached by | +| --- | --- | --- | --- | --- | +| `effective_action` values | 33 literals, no owner symbol | registry `vocabularies.effective_action.values`; `semantic-vocabulary-drift-smoke.py` fails on an unregistered literal | one enum owner; `skip`, `observe_replay`, `block_replay`, and the two `quota_action_selection_*` codes gone from the decision slot; 32 decision values after accounting for the five previously missed producers and retiring the synthetic operator_gate value | M1 | +| `effective_action` slots in one envelope | 3 vocabularies under one field name | no counter: the slot split is a Q6 decision, not a number. Read `relations.shared_field_names` | 1, or a registered union if Q6 keeps the field | M1 (Q6) | +| Turn vocabularies | 3 sets, 28 values, 21 distinct, 7 redundant spellings | registry `vocabularies`; spelling overlap is `relations.same_concept` | 3 sets kept; projection and decision table generated and checked; spellings unchanged unless Q10 sets a merge | M2 (Q2, Q10 *open*) | +| Same-runtime forks, semantic | 18 names | `semantic-vocabulary-drift-smoke.py`: `same_runtime_forks_semantic` | 0 | baseline PRs | +| Conflicting values, semantic | 2 names | `semantic-vocabulary-drift-smoke.py`: `conflicting_values_semantic` | 0 | baseline PRs | +| Multi-value forks | 4 (1 misclassified) | `semantic-vocabulary-drift-smoke.py`: `multi_value_forks` and `multi_value_forks_semantic`. Only the count is printed today; #4614 adds `divergent_value_sets` to name the surviving forks | 0 after `scope` declares bounded-context names | M0.5 + baseline PRs | +| Multi-value twins | 19 | `semantic-vocabulary-drift-smoke.py`: `multi_value_twins` | 0 | baseline PRs | +| Legacy should-run fields | 6 fields, 124 py / 10 ts module mentions | `semantic-vocabulary-drift-smoke.py`: one `.py` / `.ts` pair per field | 0 fields | M3, identifier-counted | +| Merge-candidate groups | 32 unreviewed | `merge_candidate_groups()` in `loopx/semantics/inventory.py`; no command prints it today, and #4630 adds the CLI line. Read the reviewable count, not the raw one -- a registered cross-runtime vocabulary owns both its Python and TypeScript symbols, so those pairs are required by I3 rather than debt | every group classified; only `same_semantics` groups merged | classification PR, then per-group PRs | +| Control-plane py/ts twins | 43 | `semantic-vocabulary-drift-smoke.py`: `independently_maintained` | follows the TypeScript migration RFC; no target here | M4 | + +*Measured by* names the command and field that print each surface today, the +way Section 9 names a test for each claim. It deliberately does not carry the +values: a transcribed number is stale on the next merge, and a reader who wants +the current state runs the command rather than trusting a date. Dated values +belong to the delivery tracker, issue #4447, which owns delivery status; this +table stays a contract about where the truth is measured. + +Read the reviewable merge-candidate count rather than the raw one. The raw +grouping pairs any two names carrying identical values, which includes the +Python and TypeScript symbols a registered cross-runtime vocabulary is required +by I3 to have. Treating those as debt is a measurement artifact, not drift. ### Two-track execution and enforcement lanes 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 10d9e81cb2..6358a78b10 100644 --- a/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md +++ b/docs/architecture/rfcs/semantic-vocabulary-convergence-v0.zh-CN.md @@ -697,18 +697,27 @@ TypeScript effective-action 绑定与[术语表](../../reference/glossary.md)通 注册表预算或 smoke 可检查的词表属性。标为*未决*的行等待第 12 节的决策,这也 是计划在那些决策记录之前只是骨架的原因。 -| 表面 | 基线(`1dc6ad8d8`) | 本 RFC 关闭时的目标 | 由谁达成 | -| --- | --- | --- | --- | -| `effective_action` 取值 | 33 个字面量,无 owner 符号 | 一个枚举 owner;`skip`、`observe_replay`、`block_replay` 与两个 `quota_action_selection_*` 码从判定槽位移出;计入五个此前漏记的生产值并移除合成 operator_gate 后,共 32 个决策值 | M1 | -| 同一 envelope 里的 `effective_action` 槽位 | 一个字段名下 3 套词表 | 1,或在 Q6 保留字段时为一个已注册并集 | M1(Q6) | -| Turn 词表 | 3 套、28 值、21 个不同值、7 个冗余拼法 | 保留 3 套;投影与决策表生成并校验;拼法不变,除非 Q10 决定合并 | M2(Q2、Q10 *未决*) | -| 同运行时分叉(语义) | 18 个名字 | 0 | 基线窄 PR | -| 冲突值(语义) | 2 个名字 | 0 | 基线窄 PR | -| 多值分叉 | 4(1 个误分类) | `scope` 声明有界上下文名字后为 0 | M0.5 + 基线窄 PR | -| 多值孪生 | 19 | 0 | 基线窄 PR | -| 旧 should-run 字段 | 6 个字段,124 py / 10 ts 模块提及 | 0 个字段 | M3,按标识符计数 | -| 合并候选组 | 32 组未评审 | 每组已分类;只合并 `same_semantics` 的组 | 分类表 PR,随后逐组 PR | -| 控制面 py/ts 孪生 | 43 | 跟随 TypeScript 迁移 RFC;本 RFC 不设目标 | M4 | +| 表面 | 基线(`1dc6ad8d8`) | 由什么度量 | 本 RFC 关闭时的目标 | 由谁达成 | +| --- | --- | --- | --- | --- | +| `effective_action` 取值 | 33 个字面量,无 owner 符号 | 注册表 `vocabularies.effective_action.values`;`semantic-vocabulary-drift-smoke.py` 在出现未注册字面量时失败 | 一个枚举 owner;`skip`、`observe_replay`、`block_replay` 与两个 `quota_action_selection_*` 码从判定槽位移出;计入五个此前漏记的生产值并移除合成 operator_gate 后,共 32 个决策值 | M1 | +| 同一 envelope 里的 `effective_action` 槽位 | 一个字段名下 3 套词表 | 无计数器:拆槽是 Q6 的决策而非一个数字。读 `relations.shared_field_names` | 1,或在 Q6 保留字段时为一个已注册并集 | M1(Q6) | +| Turn 词表 | 3 套、28 值、21 个不同值、7 个冗余拼法 | 注册表 `vocabularies`;拼法重叠见 `relations.same_concept` | 保留 3 套;投影与决策表生成并校验;拼法不变,除非 Q10 决定合并 | M2(Q2、Q10 *未决*) | +| 同运行时分叉(语义) | 18 个名字 | `semantic-vocabulary-drift-smoke.py`:`same_runtime_forks_semantic` | 0 | 基线窄 PR | +| 冲突值(语义) | 2 个名字 | `semantic-vocabulary-drift-smoke.py`:`conflicting_values_semantic` | 0 | 基线窄 PR | +| 多值分叉 | 4(1 个误分类) | `semantic-vocabulary-drift-smoke.py`:`multi_value_forks` 与 `multi_value_forks_semantic`。今天只打印计数;#4614 增加 `divergent_value_sets` 以按名字列出存活的分叉 | `scope` 声明有界上下文名字后为 0 | M0.5 + 基线窄 PR | +| 多值孪生 | 19 | `semantic-vocabulary-drift-smoke.py`:`multi_value_twins` | 0 | 基线窄 PR | +| 旧 should-run 字段 | 6 个字段,124 py / 10 ts 模块提及 | `semantic-vocabulary-drift-smoke.py`:每个字段一对 `<字段>.py` / `<字段>.ts` | 0 个字段 | M3,按标识符计数 | +| 合并候选组 | 32 组未评审 | `loopx/semantics/inventory.py` 的 `merge_candidate_groups()`;今天没有任何命令打印它,#4630 增加该 CLI 行。读可评审数而非原始数——注册的跨运行时词表本就同时拥有 Python 与 TypeScript 两个符号,这类配对是 I3 的要求而不是债务 | 每组已分类;只合并 `same_semantics` 的组 | 分类表 PR,随后逐组 PR | +| 控制面 py/ts 孪生 | 43 | `semantic-vocabulary-drift-smoke.py`:`independently_maintained` | 跟随 TypeScript 迁移 RFC;本 RFC 不设目标 | M4 | + +*由什么度量* 列点明今天打印每个表面的命令与字段,与第 9 节为每条断言点明一个 +测试的写法一致。它**刻意不携带数值**:誊抄来的数字在下一次合并时就过期,而想 +知道当前状态的读者应当去跑那条命令,而不是相信一个日期。带日期的数值归交付 +追踪(issue #4447,它拥有交付状态);本表保持为「真值在哪里被度量」的契约。 + +合并候选要读**可评审数**而非原始数。原始分组会把任意两个携带相同值集的名字配 +成一组,其中包含注册的跨运行时词表按 I3 **必须**同时拥有的 Python 与 TypeScript +两个符号。把它们当作债务是度量伪影,不是漂移。 ### 两条执行轨道与强制层级