Repository navigation
Commit a85b5dc
docs(skills): reconcile the mutual-exclusion tail read against the comment count (#18950)
Fixes #18052
Clause-②: no
The `互斥最小尾页读法` recipe in `references/dispatch-runbook.md` consumes the
reported comment total as the page arithmetic's *input* and never
compares it against what the tail actually returns. A thread whose
newest records have been removed therefore reads as a thread that simply
ends there — the two are byte-identical — and the conclusion the recipe
licenses is `简报即最新事件 ⇒ 立即坐席`.
Read through the filer's own correction: the hazard is **durability**,
not pagination. A suspended account's comments are removed, the
`comments` count lags the removal and then **converges** on the
enumeration. So the count/enumeration mismatch is a *transient* flag — a
seat arriving after convergence sees no discrepancy at all, and the
record is simply gone.
That is why the vacancy cross-check below is **unconditional** rather
than gated on the mismatch.
## Before / after, with byte counts
Two lines change. Both land inside the recipe's own byte headroom under
the 120-byte line rule, so the file stays at its ceiling and **nothing
is retired**.
`.claude/skills/pm-dispatch/references/dispatch-runbook.md`
| line | before | after |
|:--|:--|:--|
| :60 | `- 互斥最小尾页读法:尾页配方只覆盖座位贴的两个读数。` — **75 B** | `-
互斥最小尾页读法:尾页配方只覆盖座位贴的两个读数,判空缺另对正文与标题。` — **106 B** |
| :63 | `- 尾页缺读数再回翻一页,⛔ 不读整线程。` — **55 B** | `- 尾页缺读数再回翻一页,⛔
不读整线程;返回数少于总数 ⇒ 记录可能已消失,报缺口。` — **113 B** |
Net: **+89 bytes, +0 lines**, widest line 113 B (cap 120).
### What paid for it: nothing, because no line was bought
The addition is authored into two lines that already carry this exact
subject, so the line count never moves. This is **not** re-wrap funding:
no line was merged, no line was freed, and no content left the corpus.
The distinction the ratchet draws is whether a fold *bought a line for
new content* — here no fold occurred and no line was bought.
Measured headroom in the recipe block before the edit (`120 − width`,
per line): :60 45 B · :61 6 B · :62 27 B · :63 65 B = **143 B of local
slack**, against the 89 B the two rules needed. The slack is in the very
lines the rules belong to, so the contract-review.md precedent —
"absorbing the addition without a new line means re-wrapping the whole
file" — does not apply: no unrelated line is touched.
Consequently **no retirement is claimed and no ceiling moves.** The PM's
candidate retirements were measured and refused:
- `:57` — `索引表 = 卡号加一行判决;后两段沿用 SKILL.md 轮次报告节的定义。` is **already a
pointer**, not a restatement; retiring it would delete the only signpost
to where `健康指标` / `接力清单` are defined.
- `:58`, `:59` — the brief's no-restatement rule and its 3000-character
hard budget appear nowhere else.
- `:64`–`:66` — a different topic (long-thread status outsourcing), and
their content survives nowhere else.
## Why no SKILL.md edit is required
`SKILL.md` `:86` reads `收班简报是前任不再写的显式声明,是释放标记不是锁:简报即最新事件 ⇒ 立即坐席。` — the
rule the card's bad reading ran through. It is **not weakened and not
edited**: its antecedent is `简报即最新事件`, which is a *reading*, and the
runbook recipe is how that reading is obtained. The new `:63` governs
when the antecedent may be treated as established; `:86` stays literally
true.
Likewise the enumeration rule at `SKILL.md` `:319` (`每条枚举比对返回数与
totalCount …点名缺口`) is **pointed at, not restated**: `:63` adopts its
verb `报缺口` rather than repeating the rule, which is the convention the
ratchet's own ceiling comment states ("no rule already stated in
SKILL.md").
## Why `正文与标题`, and not `assignee`
`platform-readings.md` `:135` is the measured reading:
`用户类写绑作者:封号则其评论与卡按作者 404,标签/状态/标题/正文存活。` It names **标签 / 状态 / 标题 / 正文**
as surviving — `assignee` is **not** in that list, and the filer
explicitly logged assignee degradation as *suggestive, not measured*. So
the cross-check names the two durable surfaces a vacancy judgement can
actually stand on. `seat-post-protocol.md` `:11` already makes 标题 the
assignee's cross-check, and `:47` already puts the handover ledger in
the body — the new clause joins those to the tail read without restating
either.
This also does not collide with `SKILL.md` `:280` (`⛔ 永不从贴的 updated_at
或标题推死活`): that governs `死活` (is the incumbent's session alive), judged
only by the incumbent's own output. `判空缺` is the state-board question,
which is exactly what `:11` cross-checks.
## Reader test, against the card's own numbers
An incoming seat reading seat post #6015's tail page at
2026-09-13T15:0xZ, with the new recipe:
> `872 reported, 816 returned ⇒ gap 56 ⇒ 记录可能已消失,报缺口` — and, because
`判空缺另对正文与标题` is unconditional, the body is read: it documents an
incumbent through R+219 ⇒ **NOT vacant**.
Under the recipe as it stood, the same seat read the newest visible
event as a 2026-09-11 stand-down brief and took a seat whose incumbent
had written to the board two hours earlier.
## `platform-readings.md`: measured, and deliberately NOT edited here
The durability facts the filer's correction names are **already in the
tree** (`:135`, `:168`, `:169`, `:170`, `:171`) and are not restated.
Three candidate facts were checked by `git grep`, each with a lit
control:
| candidate | probe | result | lit control |
|:--|:--|:--|:--|
| count **converges** after a removal | `git grep -n 收敛 --
references/platform-readings.md` | exit 1, **zero hits** | `计数` → **9
hits** in the same file |
| mismatch is a **transient** flag | `git grep -n 瞬态 --
…platform-readings.md` | 2 hits, both unrelated (`unstable` CI state; a
transient PR-files 404) | `截断` → **11 hits** |
| `updated_at` as the **discriminant** | `git grep -n updated_at --
…platform-readings.md` | **zero hits** in this file | same file lit
above |
⇒ the tree lacks them. But this file is at **466 / 466 with headroom
0**, and its own ceiling record states that line-neutral folding was
*measured* at zero available folds across its 333 adjacent rule pairs.
Raising a ceiling is on `SKILL.md` `:391`'s manual floor; the standing
one-file exception at `:393`–`:394` routes it through a `ruledRaises`
record in `scripts/pm/check-skill-line-ratchet.mjs` plus the **seat's**
ACCEPT verification — neither of which is this card's declared file
surface. The proposed row and its byte count are therefore reported for
the seat rather than taken here; see the dev report's `open_questions`.
Nothing in this PR depends on that row: the vacancy cross-check is
unconditional precisely so the guard does not rest on the transient
flag.
## Verification
Gate list derived from this worktree, not recalled: `node
scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` at `d7b97b712` → **17 commands**. All 17
run, exit codes captured with redirect-then-`$?` (never through a pipe),
then reconciled with `--ran`:
```
Run reconciliation — 17 derived, 17 run, 0 NOT-MEASURED, 0 UNRUN.
✓ 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).
```
`pnpm --filter @objectstack/lint run check:doc-formula-expressions`
first exited **3** — the gate's own PREREQUISITE-NOT-MET code, which its
output states measures nothing. The prerequisite was built under the
shared lock (`os-verify-lock: VERDICT command-exit 0 · held the lock
140s`) and the gate then exited **0**.
The ratchet's own verdict lines for both files:
```
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 241 lines (ceiling 241; headroom 0).
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md: widest table row is 0 bytes (pin 0; headroom 0).
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/platform-readings.md is 466 lines (ceiling 466; headroom 0).
```
Four gates beyond the derived 17 were also run, because the PM's
derivation for the sibling file named them and one roster gate keeps its
baseline under `.claude`, where the derivation warns its silence is
evidence in neither direction: `check:pm-governed-prose` **0** ·
`check:pm-half-states` **0** · `check:required-contexts` **0** ·
`check:pm-settings-deny-roster` **0**. Also `node
scripts/check-skills-token-ratchet.mjs` **0** (the `pnpm
check:skills-token-ratchet` spelling does not exist — command-not-found,
recorded as NOT MEASURED and re-run in the correct form rather than
reported as a failure).
Control-character self-scan beyond `check:nul-bytes`: `grep -naP
'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` over the changed file — exit 1,
clean.
`skip-changeset`: `.claude/**` is on the no-publish fast track — no
package `files[]` ships this path.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 7af6983 commit a85b5dc
1 file changed
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
60 | | - | |
| 60 | + | |
61 | 61 | | |
62 | 62 | | |
63 | | - | |
| 63 | + | |
64 | 64 | | |
65 | 65 | | |
66 | 66 | | |
| |||
0 commit comments