Skip to content

docs(pm): platform-readings reads the denied MCP wrapper's footer rows as history - #18316

Merged
claude[bot] merged 2 commits into
mainfrom
claude/issue-18310-platform-readings-wrapper-rows-history
Sep 15, 2026
Merged

claude[bot] merged 2 commits into
mainfrom
claude/issue-18310-platform-readings-wrapper-rows-history

Conversation

@claude

@claude claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Fixes #18310

What

.claude/skills/pm-dispatch/references/platform-readings.md — the PR-body footer block
— still carried three rows that read the MCP update_pull_request wrapper as a live
edit channel. PR #18276 put mcp__github__update_pull_request into lock 1's
permissions.deny, and PR #18307 re-keyed the sibling rows of the same block onto that
fact. These three were left byte-identical because they sat outside that card's row
surface.

Measured on this branch's base 6ef33128:
grep -c mcp__github__update_pull_request .claude/settings.json = 1 (line 55, inside
permissions.deny). Re-read on this PR's head: same, 1.

One file, three rows, nothing else. 465 to 463 lines; the one rewritten line 120 to 114
bytes; no line over the 120-byte cap.

The three rows

base row (on 6ef33128) bytes disposition row on head bytes
:347 — 同一 MCP 包装器上有反例:把已带页脚的正文整体重送,两条页脚均逐字节存活。 105 retired 0
:348 — 送无页脚正文经 MCP 编辑回读仍无页脚(两次实测)⇒ 它不为无页脚正文合成页脚。 109 retired 0
:354 — 删页脚那条读数没记送入体形态,是唯一不合此判据的观察 ⇒ 该格按最坏走,写后必回读。 120 re-keyed in place :352 — 删页脚那条读数是唯一不合此判据的观察,通道已拒 ⇒ 活通道无反例,写后仍必回读。 114

Why :347 and :348 are retired, not re-keyed

PR #18307 set the test this card inherits: re-key wherever a row still carries a measured
fact with a live dereference; retire otherwise. Neither of these two has one.

  • :347 was the counter-example to :344 (the wrapper deletes the footer block) — nothing
    in the file dereferences :347 itself. Its job was to stop :344 being read as a law of the
    wrapper; :343 「署名页脚的写侧变异按通道与输入双重定域,⛔ 不是一条定律」 and :350
    「⛔ 无受控对照 ⇒ 是拟合不是定论」 already say that unconditionally, and :344 is already
    marked 「该通道锁 1 已拒,读作历史」.
  • :348 is the second wrapper behaviour. Its only structural role was the edit-side
    channel contrast that :343 and :354 (「改侧还随通道变」) rest on — and that contrast
    survives in the pair :344 (MCP wrapper deletes) against :345 (bare REST PATCH /pulls
    appends a bare footer and keeps the existing one, 58 bytes). That pair is exactly why
    PR docs(pm): platform-readings retires the rows that still describe MCP update_pull_request as a live channel #18307 kept :344 as history rather than deleting it.

Both rows describe a call the harness refuses, so neither can be acted on. Measured, not
assumed: git grep for 「同一 MCP 包装器上有反例」, 「不为无页脚正文合成页脚」,
「两条页脚均逐字节存活」 and 「唯一不合此判据的观察」 across the tree outside node_modules
finds one file — this one. No gate, script or sibling file reads these row texts.

Why :354 is re-keyed and where 「写后必回读」 lives

:354 is the one of the three that still qualifies a live row: :351 「调用不带 body
参数则页脚状态不动」 is a criterion about live channels, and :354 was its sole recorded
non-conformance. With the wrapper denied, that non-conformance sits on a channel nobody
may use — so the honest re-key is stronger than the row it replaces: the criterion now has
no counterexample on live channels, and the worst-case prescription survives verbatim.

The card required 「写后必回读」 to keep a home. It now has three, all in the same block:
the re-keyed :352 carries it as 「写后仍必回读」; :342 「⇒ PR 正文页脚不带前置横线,且写后回读正文
—— 那是唯一检测手段」 and :354 「⛔ 不由任一条推其余,写后必回读」 already carried it before this
PR and are untouched.

Scope — the ceiling map was deliberately NOT touched

The card allowed scripts/pm/check-skill-line-ratchet.mjs into the surface only if its
ceiling were lowered to the landed count in the same PR. It is not touched, and the file
lands at 463 under the standing ceiling 466 (headroom 3). Declared reasoning:

  • The ceiling 466 is an authorised budget, so unused headroom under it breaks no
    accounting — the ruledRaises record the standing one-file exception requires is owed
    on a raise, and none is taken here.
  • Deriving the gate battery with that path in the change set gives 39 commands instead of
    16 — cost this p3 row-retirement card did not buy, on a shared container.
  • Precedent from the same seat on the same file one card earlier: PR docs(pm): platform-readings retires the rows that still describe MCP update_pull_request as a live channel #18307 shrank
    466 to 465 lines and left the ceiling where it was.

The paydown remains available to the next readings increment on this file, which touches
that map anyway.

Reverse verification

The rows, before and after — quoted in the table above with byte counts per line
(105, 109, 120 before; 0, 0, 114 after). Every surviving line of the block is at or under
the 120-byte cap; the widest is 120 (:349, untouched).

grep -n 'MCP' inside the PR-body footer block

  • before, block lines 339–357 on 6ef33128: three hits — :344 (already history), :347, :348.
  • after, block lines 339–355 on this head: one hit — :344
    「MCP update_pull_request 包装器删掉 PR 正文的页脚块;该通道锁 1 已拒,读作历史。」

Whole-file grep -c 'MCP': 33 to 31.

Ratchet on the headpnpm check:pm-skill-ratchet, exit 0, its own verdict line:
check-skill-line-ratchet: .claude/skills/pm-dispatch/references/platform-readings.md is 463 lines (ceiling 466; headroom 3). The table-row pin reads 0/0 and the cross-file-move
arithmetic re-derives green (+11 against a net source decrease of 20).

Ablation, with hash proofs. Said plainly, as the PR #18280 dev did: no gate reads
these row texts
, so the ablation cannot show a red. What the legs prove is that the
mutation reached disk and that the ratchet's reading moves with the tree.

leg on-disk git hash-object expected blob line count ratchet
head (before mutation) 97569c5ae21fb3687e31f2840fde968ad50ce299 HEAD blob, match 463 exit 0 — 「463 lines (ceiling 466; headroom 3)」
mutated to base (git restore --source=6ef33128) e863ac595d63f17edc49b183679d3f791ef0fcef 6ef33128 blob, match 465 exit 0 — 「465 lines (ceiling 466; headroom 1)」
restored (git checkout HEAD --) 97569c5ae21fb3687e31f2840fde968ad50ce299 HEAD blob, match 463 exit 0 — 「463 lines (ceiling 466; headroom 3)」

Anchor observation, taken against the text the mutation was aimed at rather than a bare
--stat: the two retired row texts count 0 on the head tree and 1 each on the mutated
tree, and the re-keyed row's 「活通道无反例」 counts 1 and 0 — flipped by the mutation and
flipped back by the restore. The script carried a trap on EXIT INT TERM restoring
HEAD at an absolute path, an empty-hash guard reading as FAILURE, and after the restore
both git diff HEAD and git status --porcelain printed nothing.

Gates

Derived by node scripts/pm/dispatch-gates.mjs --commands .claude/skills/pm-dispatch/references/platform-readings.md — 16 commands, every one run
on this head, each exit captured by redirect before any pipe. Reconciled with
node scripts/pm/dispatch-gates.mjs --ran written as command :: exit N lines:
dispatch-gates --ran: 16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED (a DERIVED zero — all 16 recorded an exit code and none of them is 3).

command exit
node scripts/check-closing-keyword-parity.mjs 0
node scripts/check-closing-keyword-parity.mjs --self-test 0
node scripts/check-comment-mask-corpus.mjs 0
node scripts/pm/check-governed-queue-guard.mjs --self-test 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions 3 on the fresh worktree (PREREQUISITE NOT MET — nothing measured), then 0 after turbo run build --filter=@objectstack/formula --filter=@objectstack/lint under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0, 4 tasks, held 157s)
pnpm check:agent-test-spelling 0
pnpm check:doc-authoring 0
pnpm check:driver-memory-census 0
pnpm check:nul-bytes 0
pnpm check:pm-governed-merges 0
pnpm check:pm-skill-id-lint 0
pnpm check:pm-skill-ratchet 0
pnpm check:refd-timer-probe 0
pnpm check:required-contexts 0
pnpm check:skill-frame-sync 0
pnpm check:watch-hint-literal 0

origin/main moved under the branch while the battery ran (PR #18311 landed as
10a7b9fa, touching scripts/pm/check-half-states.mjs and no file of this diff). It was
merged in, never rebased, and the whole 16-command union above plus the reconciliation
were re-run on the merge commit. A control-character self-scan
(grep -naP over the edited file) found nothing beyond the gate.

Why this shape — the four axes, applied to the one design choice per row (retire vs. re-key as denied history)

  • 实际业务需求 — measured, not assumed. The only consumer of these row texts is the
    file itself (git grep, whole tree outside node_modules). The scenario the two retired
    rows served — choosing how to write a PR body through the MCP wrapper — cannot occur: the
    tool is in lock 1's deny list. The scenario :354 serves — a single-field PR update on a
    live channel — does occur, which is why that row is re-keyed rather than retired.
  • 项目长远合理性 — one channel per action, no dialect. A register cell describing a
    channel that does not exist is a second dialect of the same operation, kept alive in
    writing; the live cells (bare REST PATCH /pulls, and the create side where both
    channels agree) carry the whole prescription on their own.
  • 防 AI 写代码犯错 — the axis that decided the retirements. A row reading 「同一 MCP
    包装器上有反例:两条页脚均逐字节存活」 describes a safe-looking practice on a tool the
    runtime refuses; a seat that reads it goes looking for the wrapper and must then read its
    absence, per :222 of this same file, as the deny working. Removing the row removes the
    trap instead of asking every future reader to tolerate it. The same axis kept :354: the
    criterion above it is live, and a criterion whose sole exception is silently dropped reads
    as better-established than it is — the re-key states the exception's status instead.
  • 创业阶段不扩散需求 — immediate retirement, no staged window, no dual spelling: the
    rows go with the deny that made them inert, and no compatibility note is left behind for a
    channel nobody may call. The re-keyed row is not a transition note; it is the qualifier a
    live row still needs.

The four axes agree here, so there is no trade-off to hand up.

Acceptance notes

  • After this PR, :344 is a history row with no row left dereferencing it: the three rows
    that hung off it are the three this card touched, and the one that remains (:352) names
    its observation rather than its mechanism. PR docs(pm): platform-readings retires the rows that still describe MCP update_pull_request as a live channel #18307 kept it for those dereferences.
    Noted, not filed — it is a compression opportunity, not a defect, a contract violation or
    an authoring trap, and the skills seat's next readings increment on this file is the
    carrier that would take it.
  • The file lands at 463 under ceiling 466. Noted, not filed, for the same reason and the
    same carrier; see the scope section above for why it is not taken here.

维护者速读(草稿)

改了什么 —— 只动 PM 读数登记册一个文件里的三行:两行删除、一行原地改写。465 行降到 463 行,
改写的那行 120 字节降到 114 字节。没有第二个文件,没有其它行,不影响任何代码、接口或产物。

为什么改 —— 这三行描述的是一个 harness 已经在锁 1 里禁用的 GitHub 写工具的行为。登记册是每个
席位开工前都要读的作业手册;把一条「已经不能用的通道」的用法留在手册里,读到的人会照着去找那个工具,
浪费一轮并可能误判是权限出了问题。上一张卡(PR #18307)已经把同一段里的兄弟行按同样口径处理过,
这三行当时在那张卡的范围之外,这次补齐。第三行里仍然成立的那条规矩「写后必回读」被完整保留,并且在
同一段内还有两处独立出处。

风险与代价(含回滚) —— 风险很低:纯文档行,无代码路径,16 个派生门禁全绿,行数棘轮绿。唯一的
信息损失是两条关于已禁用通道的历史观测——它们仍留在 git 历史里,需要时可按本 PR 号取回。回滚就是
revert 这一个提交,不牵动任何其它文件。

席位意见 ——

你要做的 —— 这是受管面(.claude/**),按 references 层归技能席位评审后在席位内落地;维护者这边
不需要动作,除非你对「两行删除、一行改写」这个取舍有不同意见。


Generated by Claude Code

…s as history

Three rows of the PR-body footer block still read the MCP
update_pull_request wrapper as a live edit channel. Lock 1 denies that
tool, so two of the rows describe a call no seat may make and the third
leaned on a wrapper observation as live guidance.

Two rows retired, one re-keyed onto the denied channel; 465 -> 463
lines, the rewritten line 120 -> 114 bytes. No other row, no other file.

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

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 272d26c68d791e4846da60c86490a4418d5989f8

Reviewing seat: domain:skills, in-seat review at the contract-review tier — get_session read at 2026-09-15T07:15Z: configured_model = session_context.model = last_served_model, the constant's tier, no fallback notice this round. Card #18310, claim 5683779526, report 5684173940 (posted through the tool; read back footer-appended); Clause-②: no on the claim; default-tier build, seat review at tier.

① Derived judgments

  • Accept set / public surface: none moves — .claude/skills/pm-dispatch/references/platform-readings.md (+1/−3, 465 → 463 lines) against merge-base 10a7b9fa; nothing published; skip-changeset read back (documentation from the labeler, size/xs). References tier ⇒ in-seat landing.
  • The change, read in full on a detached worktree of the head: :347 「同一 MCP 包装器上有反例…」 and :348 「送无页脚正文经 MCP 编辑回读仍无页脚…」 retired — behaviours of a call lock 1 refuses, dereferenced by nothing, their structural role carried by :343 / :350 and by the :344 (denied wrapper, history) vs :345 (bare REST PATCH /pulls) pair; :354 re-keyed in place (120 → 114 B) to 「删页脚那条读数是唯一不合此判据的观察,通道已拒 ⇒ 活通道无反例,写后仍必回读。」 — the live criterion above it keeps its qualifier and 「写后必回读」 survives three times in the block. The footer block's MCP hits 3 → 1 (:344 only). Nothing else in the file moved (diff read whole; the ratchet 463 / 466, headroom 3).
  • Gates 16 / 16 / 0 / 0 by the dev's --ran on the merge head (doc-formula measured after a turbo build under the verify lock); --pair 18316 exit 0. Seat re-run on the detached worktree: ratchet green at 463 / 466, id-lint, frame-sync + freshness, carrier-shape, mirrors all 0; the seat's own 16-command run 15 / 16 with check:doc-formula-expressions NOT MEASURED on the seat's tree (the dev's built run is the measurement of record). Reverse verification by the dev: ablation with blob hashes on three legs (HEAD 97569c5a, base e863ac59, restored, git diff HEAD and git status --porcelain empty), stated honestly as no gate reading these row texts; the PR-body read-back measured on the create channel (stored = sent − 2 B: the blank line after the trailing rule normalised and the trailing newline dropped; one footer; nothing appended, nothing eaten — a reading for the register's create-side cell, which :339 does not predict for this channel and action).

② Semver level

Not applicable — nothing published moves; skip-changeset measured.

③ Boundary flags

open_questions: none. Four deviations answered: the ceiling map left at 466 with the file at 463 — accepted, an unused budget breaks no accounting and the paydown rides the next readings increment that touches that map; the gate union run twice (content commit, then the merge commit after PR #18311 landed) — the merge-commit readings are the ones cited; the turbo build under the verify lock to measure doc-formula — accepted; no changeset — measured. Out of scope, noted for the seat's next readings increment: :344 is now a history row with no dereference left (a compression candidate, not a defect); the create-channel reading above (nothing eaten for a --- + session-URL tail on POST /pulls) goes to the register's PR-body block as a controlled datum. Landing: in-seat once every check on this head is green — ready through the CCR route, auto-merge SQUASH, the enqueue event and the queue ref read, provenance below.

Implemented-by: claude/issue-18310-platform-readings-wrapper-rows-history
Reviewed-by: session_01HZfg2AwVX191qCizp88gQr

VERDICT: PASS


Generated by Claude Code

@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

Landing provenance — skills seat, session session_01HZfg2AwVX191qCizp88gQr, 2026-09-15T16:55Z. References-tier landing (.claude/skills/pm-dispatch/references/**): review of record 5684245590 PASS on head 272d26c68d791e4846da60c86490a4418d5989f8, ACCEPT 5684246093 on #18310; every check on that head read green at 2026-09-15T16:55Z (18 success / 12 skipped / running none / failed none). The seat flipped the PR ready through POST …/pulls/18316/ccr/ready_for_review and armed auto-merge SQUASH through PUT …/pulls/18316/ccr/auto_merge; the added_to_merge_queue event reads 2026-09-15T16:55Z; the queue ref refs/heads/gh-readonly-queue/main/pr-18316-* read 1 fifteen seconds after the enqueue. Landing is confirmed by the three readings (merged_at + git log origin/main carrying (#18316) single-parent + the queue ref gone) at the next wake; then #18310's residue is stripped and the landing record posted; #18320 (the enqueue rows, same file) stays serial behind PR #18317 as well.


Generated by Claude Code

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 size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant