Skip to content

docs(skills): bind three evidence controls onto the retirement playbook's liveness step - #17566

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-17553-retirement-evidence-controls
Sep 11, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-17553-retirement-evidence-controls

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes #17553

Two retirement rounds in one day rested on a "dead key" premise that measured
false. The retirement playbook's evidence step already bound the ledger side —
a dead verdict is an input, never a proof; the four-condition
live-elsewhere discipline; the fourteen-keys record — but it bound nothing
about the reading a seat offers for deadness. Three rules land beside those
bindings, in the file's own register and voice.

The three rules as landed

.claude/skills/spec-property-retirement/SKILL.md, appended to section 0's
pre-flight checklist immediately after the live-elsewhere item:

line rule
:59 - [ ] **零编写实例普查要并跑一个同族已知存活的键作对照**,两读数都报;同得零即没测出。
:60 - [ ] **拿 cross-repo 行当论据,就当刻重核路径与行号**:漂了读作重新取证,⛔ 不是 dead。
:61 - [ ] **「零编写实例」≠「没有代码读它」。** 前者答的是示例应用,后者才是退役的证据。

(The table renders the two inline code spans of :60 as plain words so the row
survives the body sanitizer; the file itself carries them as code spans.)

Why section 0 and not section 1. Section 0 is the pre-flight checklist —
「动手删之前:删除是正确的处置吗?」 — and every item in it is a question about
whether the disposition is right, answered in one or two lines. All three rules
are exactly that: tests a seat applies to its own evidence before it commits
to a removal. Section 1 ("裁判是构建,不是台账") argues one thesis in prose and
carries no checklist; three - [ ] **…** items appended there would have needed
a list of their own. The live-elsewhere item is the nearest neighbour by
subject, so they sit directly under it.

They sit beside the existing bindings, not on top of them: :55-:58 still
carries the four-condition cross-repo discipline and its elsewhere.mts /
README provenance, :65 still carries 「台账的 dead 裁定是删除的输入,不能
替代构建自己的证明」, and :71 still carries the fourteen-keys record.

Payment ledger — 337 lines in, 337 lines out

The ceiling is 337 with zero headroom, so each added line is bought by deleted
content, never by re-wrapping. Three lines added, three lines of content
deleted, all three inside the declared region.

deleted phrase the fact it carried where that fact still lives
live-elsewhere item: 「单读 dead 会批准一次删除,而它删掉的是姊妹仓某道门的输入。」 (88 B) a lone dead read would authorise a deletion; the casualty is a sibling repo's gate input both halves survive adjacent to it — the item's own 「姊妹仓真在强制执行的键 —— 永不是删除候选」 names the casualty, and section 1's opening 「台账的 dead 裁定是删除的输入,不能替代构建自己的证明」 (:65) states that a dead read alone is not authority
section 1: 「它是一条带时间戳的声明,」 (36 B) the ledger entry is a timestamped claim :56 「带日期的 verifiedAt、180 天过期」 and :70 「附真实证据与 verifiedAt」 — and the new :60 now turns on that clock explicitly
section 1: 「defineForm 往每个 *.form.ts 写 data: ...,metadata-protocol 把它喂给 metadata-admin 管线。」 (146 B) the write site and consumer chain of view.form.data narrative tail of the precedent. The precedent itself stays whole — 「view.form.data 挂在工作清单上是 dead…而删除打断了 gen:schema」 plus its correct response. :309 in the same file independently names 「一个 defineForm 会写的键」, and the very next sentence instructs the reader to put the chain in the ledger entry's own evidence string

Nothing outside the region moved: the four diff hunks span old lines 55-71
only, and the file is byte-identical elsewhere.

⚠️ A dispatch premise measured false, recorded rather than acted on. The
order said the 120-byte line cap does not bind this file because "7 lines
already exceed it". Measured: MAX_LINE_BYTES = 120 in
scripts/pm/check-skill-line-ratchet.mjs does cover this file, and the 7
over-120-byte lines are all structurally exempt classes — table rows at
:86-:88, :101, :126-:127 and a blockquote at :117. Every prose line in
the region is under 120 bytes today. The three new lines were therefore written
to 120 / 116 / 120 bytes, which satisfies both readings; no existing line was
reflowed. The order's other reading — "an over-wide line elsewhere in the same
region" as a payment source — has no referent: no line in :50-:72 exceeds 120
bytes.

The census control, re-measured on this branch

The card's decisive control, re-run once as the premise check, on
ad715aca (git grep -lE -- 'KEY:' examples apps | wc -l):

columns 31 files  ·  hiddenFields 0  ·  fieldOrder 0  ·  rowColor 1

Identical to the card's reading on 6e3462df47. hiddenFields is graded
live in packages/spec/liveness/view.json with a cross-repo evidence string
naming its own filter in objectui's ListView — indisputably live — and it
scores the same zero as fieldOrder. columns at 31 proves the instrument
works. The premise holds.

The one judgement, on the four axes

The judgement here is where the three rules sit and what pays for them.
实际业务需求: measured, not speculative — two dispatched rounds in one day
turned on exactly these three gaps, and the census control is one command whose
reading is reproduced above; the pre-flight checklist is where a seat actually
stands when it decides, so a rule placed there is read at the moment it binds.
项目长远合理性: the rules tighten the evidence contract at the point of
authorship rather than adding a consumer-side accommodation; no new gate, no new
ledger field, nothing to keep in sync. 防 AI 写代码犯错: this is the
AI-authoring axis at its sharpest — the failure mode is an agent reading a
cited path, finding it deleted, and inferring "dead", so :60 makes drift read
as 「重新取证」 and names the wrong inference explicitly (⛔ 不是 dead); a
census with no control is the same shape one layer down, and :59 refuses it.
创业阶段不扩散需求: paid entirely from inside the file at a flat 337 lines
with no ceiling raise and no new surface — three lines of protocol text against
a method that has already carried a maintainer's signature onto the deletion of
a working channel. The axes do not conflict here; the only tension is density,
and it is settled by the ledger above rather than by a budget increase.

Verification

Gate families derived from the final diff by
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack
(the script derives its own change set; 1 path, three-dot against merge base
ad715aca5). Every exit code captured before any pipe.

gate exit verdict line
pnpm check:pm-skill-ratchet (before edit) 0 ✓ check-skill-line-ratchet: .claude/skills/spec-property-retirement/SKILL.md is 337 lines (ceiling 337; headroom 0). · widest table row is 326 bytes (pin 326; headroom 0)
pnpm check:pm-skill-ratchet (after edit) 0 byte-identical to the two lines above — 337 / 337, 326 / 326
pnpm check:nul-bytes 0 check-nul-bytes: OK (scanned 8331 text file(s) ... no raw ASCII control bytes).
pnpm check:skill-frame-sync 0 ✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherent
pnpm check:pm-governed-merges 0 ✓ check-governed-merges --self-test: 317 assertions ...
node scripts/check-closing-keyword-parity.mjs 0 check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8338 tracked file(s), all registered).
node scripts/check-closing-keyword-parity.mjs --self-test 0 self-test pass
node scripts/check-ci-filter-parity.mjs 0 pass
node scripts/check-comment-mask-corpus.mjs 0 pass
node scripts/report-test-timings.mjs --self-test 0 pass
pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 first run exited 3 = PREREQUISITE NOT MET (「Nothing was measured」), not a finding; re-run green after turbo run build --filter=@objectstack/formula --filter=@objectstack/lint under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0 · held the lock 184s · waited 0s)
pnpm check:agent-test-spelling 0 pass
pnpm check:cross-package-test-inputs 0 pass
pnpm check:doc-authoring 0 pass
pnpm check:driver-memory-census 0 pass
pnpm check:refd-timer-probe 0 pass
pnpm check:required-contexts 0 pass
pnpm check:watch-hint-literal 0 pass

Reconciliation, exit codes recorded per family:
✓ dispatch-gates --ran: 17 derived famil(ies) accounted for — 17 run, 0 NOT-MEASURED (a DERIVED zero — all 17 recorded an exit code and none of them is 3).

Path face — node scripts/pm/check-governed-merges.mjs --branch claude/issue-17553-retirement-evidence-controls, exit 3:
⛔ GOVERNED — a human merge is the review record for this PR (#9495 regime).
.claude/** ×1. This PR stays draft; no seat flips it ready, enqueues it,
or arms auto-merge.

Two order-named checks that could not run as written, recorded rather than
skipped: node scripts/check-closing-keyword-parity.mjs --body — no such
flag exists
on this base (ad715aca); the script takes only the bare form,
--self-test and --list, and both runnable forms are green above.
pnpm check:pm-skill-id-lint — this file is not in its set: the gate scans
.claude/skills/pm-dispatch/** plus .claude/agents/os-dev.md and AGENTS.md
(SCAN_ROOT / EXTRA_FILES), and reports 27 file(s) clean on a tree that
does not include this one. That is why the file legitimately carries issue
numbers such as #3896; the three new lines carry none.

No changeset: the diff is .claude/** only, which ships in no package's
files[] — the skip-changeset fast track. Label applied.

Clause-②: no

Acceptance notes

维护者速读(草稿)

改了什么 —— 退役 playbook 的证据步(section 0 的动手前清单)多了三条规则:①
拿「本仓零编写实例」当死键证据时,必须同时跑一个同族已知存活的键作对照,两个读数
一起报;对照拿到同样的零,这次普查什么都没测出来。② 拿一条 cross-repo 台账行当删除
论据时,在引用当刻重核它引的路径与行号;漂了读作「重新取证」,不读作「dead」。③
「零编写实例」和「没有代码读它」是两件事,退役要的是后者。文件行数不变(337/337),三
行新规则由文件内部三处删减买单,删的每一处都在正文的付款表里点名,以及那条事实现在住
在哪儿。

为什么改 —— 同一天派出的两张退役卡,前提都实测为假:一张要删的键服务端在读,另一
张要删的键姊妹仓在用,而且第二张已经拿到维护者裁决。两轮都没造成损失,靠的是派发
词里的停止条件 —— 那是派发上的控制,不是方法上的。方法这一侧此前是无守卫的。

风险与代价(含回滚) —— 纯协议文本,没有代码、没有门禁、没有新面;唯一的代价是文
件密度:为了不抬 ceiling,section 1 里 view.form.data 那段先例的管道细节和两处重述被
删掉了,先例本身、它的教训与更正动作都完整保留。回滚成本为零 —— 单文件、单 commit,
git revert 即可,没有任何生成物或台账跟着动。

席位意见 ——

你要做的 —— 这是受管面(.claude/**),PR 保持 draft,由你人工合并;⛔ 没有任何
席位会翻 ready 或挂 auto-merge。要看的就一件事:三条规则是不是你要的说法,以及付款表里
删掉的三处你是否同意其中没有丢失事实。


Generated by Claude Code

…ok's liveness step

A "dead key" premise is only as good as the reading offered for it. The evidence
step bound a ledger `dead` verdict as an input rather than a proof, the
four-condition `live-elsewhere` discipline and the fourteen-keys record — but it
put no control on the census, did not require a cited `cross-repo` row to be
re-read at the moment it is used as an argument, and did not separate "nobody
authors it here" from "no code reads it".

Three rules land beside those bindings, at :59-:61:

- a zero-authored-instances census runs a known-live sibling key as its control
  and reports both readings; a control scoring the same zero measured nothing;
- a `cross-repo` row cited as an argument is re-verified at citation — path and
  lines — and drift reads as "re-cite", never as `dead`;
- "zero authored instances" is not "no code reads it"; a retirement needs the
  second.

Paid by density inside the file at 337/337 (ceiling unchanged): the lone-`dead`
restatement in the `live-elsewhere` item, the "timestamped claim" clause in §1,
and the `view.form.data` anecdote's plumbing tail. Every deleted fact still
lives in the file, named line by line in the PR body's payment ledger.

Claude-Session: https://claude.ai/code/session_01YKEjmbYNvYWJvWGSWx26zK
Co-authored-by: Claude <noreply@anthropic.com>
@os-litant os-litant added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 10, 2026 — with Claude
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 10, 2026

Copy link
Copy Markdown
Collaborator Author

维护者速读

改了什么 —— 退役 playbook(.claude/skills/spec-property-retirement/SKILL.md)section 0 的动手前清单多了三条规则(:59–:61):① 拿「本仓零编写实例」当死键证据时,必须并跑一个同族已知存活的键作对照,两个读数一起报——对照拿到同样的零,这次普查什么都没测出;② 拿一条 cross-repo 台账行当删除论据时,在引用当刻重核它引的路径与行号,漂了读作「重新取证」而不是「dead」;③ 「零编写实例」≠「没有代码读它」,退役要的是后者。文件仍 337/337 行、表行 326 pin 未动:三行由同一区域内三处删减买单(一句重述、一个「带时间戳的声明」从句、view.form.data 先例的管道细节),先例本身、教训与更正动作都在,verifiedAt 与 live-elsewhere 四条纪律原样保留。

为什么改 —— 同一天派出的两张退役卡前提都实测为假:#15180 要删的键服务端在读(分诊席独立复测后关 not planned);#15184 要删的键姊妹仓 ListView.tsx 在读,而且已经拿到您的裁决。两轮没造成损失,靠的只是派发词里的停止条件——那是派发上的控制,方法本身此前无守卫。对照实测:columns 31 个文件、已知存活的 hiddenFields 0、fieldOrder 0——存活键与目标键同得零,说明「本仓零编写实例」不是死键证据。

风险与代价(含回滚) —— 纯协议文本,无代码、无门禁、无发布面;棘轮两行读数本席在 head 48de3d86 上实测与 main 逐字相同;CI 18 过 / 11 跳 / 3 在跑,无失败。回滚 = revert 这一个 commit。

席位意见 —— 通过。三处删减本席逐句读过,没有事实离开文件而无家可归。受管面(.claude/**):本席不翻 ready、不入队、不批准。#15184 的裁决建立在假前提上,那张决策卡的处置仍在您的决策箱里,本 PR 不碰它。

你要做的 —— 一个动作:人工合并本 draft PR(付款表在 PR 正文;若您认为删掉的某句该留,评审里说一句)。

skills 席,session session_01YKEjmbYNvYWJvWGSWx26zK,2026-09-10T23:11Z。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 11, 2026 06:31
@os-zhuang
os-zhuang enabled auto-merge September 11, 2026 06:31
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 11, 2026
Merged via the queue into main with commit 1a08932 Sep 11, 2026
40 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-17553-retirement-evidence-controls branch September 11, 2026 07:15
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 17, 2026
… own subject or the zero is void (objectstack-ai#17837)

The zero-hit rule bound the control to HIT, not to be SCOPED to the
claim: a control can prove the instrument works while pointed at a
different corpus, path shape, module/package boundary or quoting, and
the zero then comes back as a reassuring negative that survives review
(three misses in one hotcrm shift, two more measured by the triage
seat). The rule now says the control shares the claim's own subject and
the target's failure mode (a phrase that wraps across lines needs a
control that wraps the same way), or the zero is VOID rather than
negative. Landed in all three carriers of the discipline in one PR, per
SKILL.md 「一条规则在本文与核心条款一处改动,另一处同 PR 同改」: `pm-dispatch/SKILL.md`
:161-:162, `references/core-rules.md` :45, and the dev-side reading in
`.claude/agents/os-dev.md` :54. Every file stays at its ratchet ceiling;
the payment is density inside the same section, itemised below. Not a
new gate.

Part of objectstack-ai#17569

## Acceptance notes

**Premises (re-taken on `origin/main` `0cd841a16` at 2026-09-12T10:03Z,
after `git fetch origin main`):**

1. SKILL.md :161 read 「- 零命中必须用确定存在的邻近词反查,否则零命中不成立。」 (78 bytes); file
812 lines, CEILINGS row 812, `MAX_LINE_BYTES = 120` — holds. The ratchet
script lives at `scripts/pm/check-skill-line-ratchet.mjs` (the dispatch
word spelled it without the `pm/` segment; same script).
2. core-rules.md :45 read 「- 零命中必须用确定存在的邻近词反查才成立;仓不可达时 ⛔ 不得当成查过且干净。」
(110 bytes); 151 lines at ceiling 151 — holds; it IS the rule's
core-rules mirror and is edited here.
3. os-dev.md :54 read 「 - 空结果要同会话一个已知必中的控制词答了命中才算读数。」 (83 bytes); 403
lines at ceiling 403 — holds.
4. SKILL.md :175 and core-rules.md :51 are the dedupe-control siblings —
left byte-identical (the new clause is general; no cross-reference
needed).
5. Open-PR scan re-taken at 2026-09-12T10:07Z over all 24 open PRs' file
lists (REST `pulls/{n}/files`): zero hits on the three files. Control,
same corpus and same regex family: 5 of those PRs touch `.claude/` paths
(objectstack-ai#17828 and objectstack-ai#17803 on `platform-readings.md`, objectstack-ai#17823 `rest-channel.md`,
objectstack-ai#17809 a hook, objectstack-ai#17515 `decision-analysis.md`) — the zero is scoped.
`origin/main` moved 3 commits (to `51b024a16`) during the run; none
touched the three files.
6. Sibling clause from PR objectstack-ai#17566 (spec-property-retirement SKILL.md :59)
read: 「零编写实例普查要并跑一个同族已知存活的键作对照,两读数都报;同得零即没测出。」 — the new wording keeps
that vocabulary (a control shares the claim's family/subject; a control
that measures nothing voids the reading) rather than introducing a
second idiom.
7. The card quotes a dispatch-template sentence 「pair every zero with a
control word that must hit」 as a second carrier inside SKILL.md. On
`origin/main` no such sentence exists (grep for `must hit`, `pair every
zero`, `control word` over `.claude/**` and `scripts/pm/**` returns
zero; control: `零命中` hits :161, :542, :724) — the template left in the
rules-only rewrite. No second carrier to edit.

**Edited lines and byte counts (each ≤ 120):**

| file | line | bytes | text |
|:--|:--|--:|:--|
| SKILL.md | :161 | 113 | 「- 零命中须用确定存在的邻近词反查;控制词须与主张同主体,否则该零作废,不是阴性。」 |
| SKILL.md | :162 (new) | 114 | 「- 同主体 =
同语料、同路径形、同包界、同引法、同失效形态:跨行短语配跨行控制词。」 |
| SKILL.md | :165 (merged) | 105 | 「- 时间戳形如 `YYYY-MM-DDThh:mmZ`,树读数另带
ref 或 tip;无时间戳的读数按未取处理。」 |
| core-rules.md | :44 | 112 | 「- 核验 main 用 fetch 后的 `origin/main`,⛔
不用共享检出树;仓不可达 ⛔ 不当查过且干净。」 |
| core-rules.md | :45 | 113 | 「-
零命中须用必中词反查,且与主张同语料/路径形/包界/引法/失效形态,否则该零作废。」 |
| os-dev.md | :54 | 113 | 「   - 空结果要同会话已知必中、与主张同主体同失效形态的控制词答了命中才算读数。」 |

**How density was paid (all inside the 平台读数纪律 section of each file):**

- SKILL.md 812/812: the clause takes two lines (:161-:162, +1); the two
timestamp lines (:164 「时间戳形如 …,树读数另带 ref 或 tip。」 and :165
「无时间戳的读数是格式错误不是现值,读者按未取处理。」) merged into one (−1). Dropped words:
「是格式错误不是现值,读者」 — the operative half 「按未取处理」 survives, matching
core-rules' own wording of that rule.
- core-rules.md 151/151: no two neighbouring lines in the section merge
under 120 bytes, so the clause is one line (:45) with the five sames
inline; the 仓不可达 half of the old :45 moved onto the `origin/main` line
(:44). Dropped words: 「确定存在的邻近」 → 「必中」, 「时」, 「不得当成」 → 「不当」, 「的工作树」 →
「树」, 「先」. The wrapped-phrase example is carried by SKILL.md only (terser
register).
- os-dev.md 403/403: one line, byte-for-byte replacement of :54 (83 →
113 bytes); the 范围 list is otherwise untouched.

**Frame block pin:** `sed -n '734,755p'
.claude/skills/pm-dispatch/SKILL.md | md5sum` =
`3327d02c56f8a0eca88569dad2270f32` before and after (net line count
above it is 0, so the block did not move).

**Gates (derived with `node scripts/pm/dispatch-gates.mjs --commands` in
the worktree, 18 commands; reconciliation via `--ran`: 「18 derived, 18
run, 0 NOT-MEASURED, 0 UNRUN」):** all 18 exit 0 at head `9e15e315f`.
`pnpm check:pm-skill-ratchet` verdict lines: 「SKILL.md is 812 lines
(ceiling 812; headroom 0)」 · 「core-rules.md is 151 lines (ceiling 151;
headroom 0)」 · 「os-dev.md is 403 lines (ceiling 403; headroom 0)」. `pnpm
check:skill-frame-sync`: 「the one declared copy of the decision frame is
internally coherent … 4 axes」. `pnpm check:nul-bytes`: 「OK (scanned 8465
text file(s) …; no raw ASCII control bytes)」.
`check:doc-formula-expressions` first answered exit 3 PREREQUISITE NOT
MET (`@objectstack/formula` and `@objectstack/lint` unbuilt) — not a
measurement; built both under the verify lock (VERDICT command-exit 0,
169 s) and re-ran: exit 0.

**Changeset:** `.claude/**` publishes nothing from any released package
(`node scripts/check-changeset-fixed.mjs` exit 0; no `files[]` of any
package covers `.claude/`) — `skip-changeset` applied by additive POST
and read back.

**Deferred rider (⛔ not in this PR):** the card's two
`references/platform-readings.md` rows (`git grep -- 'a/**/*.ext'` skips
files directly under `a/`; `grep -c $'\x00'` is not a NUL probe) wait on
that file's serial behind PR objectstack-ai#17828 and PR objectstack-ai#17803. objectstack-ai#17569 stays open for
the rider PR; hence `Part of`, not a closing keyword.

**Governed surface:** `.claude/**` — this PR stays a draft at the human
terminal; nothing here flips it ready or arms auto-merge.

## 维护者速读(草稿)

**改了什么:** 「零命中必须配控制词反查」这条规则,在三处载体(pm-dispatch SKILL.md、核心条款
core-rules.md、os-dev 开发 agent 定义)各加一句:控制词必须与主张同主体 ——
同语料、同路径形、同包界、同引法、同失效形态 —— 否则这个零作废,不算阴性读数。三个文件行数不变,各自仍顶着 ratchet 上限。

**为什么改:**
一个班次里三次「控制词命中了、零仍是假的」:控制词证明工具能用,却没证明工具对准了主张。旧文只要求控制词「命中」,不要求它「与主张同一件事」,于是错误读数反而带着安心感回来、过了复核。

**风险与代价(含回滚):** 纯文本规则,不加门禁、不加脚本;付费方式是同节内合并两行时间戳规则(SKILL.md)与把「仓不可达」半句挪到
origin/main 那一行(core-rules)。回滚 = revert 这一个 commit,无生成物、无依赖。

**席位意见:** (留空,席位定稿成评论)

**你要做的:** 读三处新句是否表达了你要的判据;确认后人工合并(governed surface)。rider
半张(platform-readings 两行)另开 PR,本 PR 不关卡。

---
_Generated by [Claude
Code](https://claude.ai/code/session_01MCLBsUgfykL74aU716rzVK)_

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation needs-user-decision size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants