Skip to content

docs(pm-dispatch): split the PR-body signature prescription per action, with the create-side contrast taken on this body - #18961

Merged
os-elon-musk merged 4 commits into
mainfrom
claude/issue-18686-pr-body-footer-forms
Sep 18, 2026
Merged

os-elon-musk merged 4 commits into
mainfrom
claude/issue-18686-pr-body-footer-forms

Conversation

@os-elon-musk

Copy link
Copy Markdown
Collaborator

Fixes #18686

Clause-②: no

Governed fact layer only: .claude/skills/pm-dispatch/references/platform-readings.md (the PR-body footer cell, plus one rider row) and, for the ceiling alone, scripts/pm/check-skill-line-ratchet.mjs. No SKILL.md edit, no other file. skip-changeset: nothing published moves — .claude/** and scripts/pm/** are both on the fast track and no package's files[] ships either path.

THIS BODY IS THE INSTRUMENT, not a description of one

The card's named unknown is the missing half of the controlled contrast that platform-readings.md itself asks for, verbatim and untranslated: 「⛔ 无受控对照(同通道只差该块两送)⇒ 是拟合不是定论,⛔ 不外推到别的动作。」 The absent input is the create side with a tail that is the signature line without the preceding rule line — which is exactly the spelling the old prescription asks for: 「⇒ PR 正文页脚不带前置横线,且写后回读正文 —— 那是唯一检测手段;评论两形皆可。」

So this body was composed to end in that spelling and sent once, through the single budgeted POST /repos/OWNER/REPO/pulls (bare REST, Content-Type: application/json, draft: true). The sent tail was, byte for byte:

  1. the last prose line of the Acceptance notes section;
  2. one blank line;
  3. no rule line — that is the whole point of the send;
  4. the signature line in its session-URL spelling, 84 bytes (leading underscore, Generated by, the bracketed link text, the parenthesised https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF URL, trailing underscore);
  5. no trailing newline.

Read it back and count:

curl -sS -H "Authorization: Bearer $GITHUB_TOKEN" -H "Accept: application/vnd.github+json" \
  https://api.github.com/repos/objectstack-ai/objectstack/pulls/PR-NUMBER --output /tmp/pr.json; EXIT=$?
node -e 'const b=JSON.parse(require("fs").readFileSync("/tmp/pr.json","utf8")).body;
  console.log("stored bytes", Buffer.byteLength(b,"utf8"));
  console.log("signature lines", (b.match(/^_Generated by /gm)||[]).length);
  console.log("tail", JSON.stringify(b.slice(-200)));'

⭐ The stored tail and the signature count are not quoted in this body, and that is deliberate rather than an omission: this body is the probe, so its stored form is the reading, and ⛔ it is never PATCHed afterwards — the patch cell appends unconditionally (table below), so a tidy-up would destroy the very evidence it tidied. Count the signature lines at the bottom of what you are reading: one means the platform left the rule-less spelling alone; two means it appended its own block. The exact byte readings live in the os-dev-report comment on #18686 and in this round's report.

Pre-registered rows — so the landed row cannot be fitted to the outcome

The row that states the create-side cell is written before the read-back, one text per outcome, and the commit that follows this body carries whichever the read-back supports. Both are inside the 120-byte line cap.

If the append fired (two signature lines):

where bytes text
rewrite of the 拟合 caveat row 109 - 受控对照已补齐:同通道同动作只差该块两送,尾部为无横线页脚时照追加成两条。
new row after it 103 - ⇒ 判据确认是送出体尾部;⛔ 未控:MCP 建侧该输入、评论侧与改侧其余输入。
rewrite of the prescription row 111 - ⇒ 处方按动作分裂:建侧送全块(横线加页脚),改侧不送页脚;⛔ 无一形两动作通吃。

If it did not fire (one signature line, stored byte-identical but for the known trailing-newline strip):

where bytes text
rewrite of the 拟合 caveat row 106 - 受控对照已补齐:同通道同动作只差该块两送,尾部为无横线页脚时一字不追加。
new row after it 105 - ⇒ 判据不是整块而是尾部有无页脚行;第四形条件须按此收窄,⛔ 不按整块判。
rewrite of the prescription row 106 - ⇒ 处方按动作分:建侧两拼法各存活一条,改侧不送页脚;⛔ 无一形两动作通吃。

Any third reading — for instance the tail being stripped, which is what the older 「尾部横线与其后的署名页脚一并被吃」 cell records for a different channel — is reported as measured, with the row written to it and the divergence from both pre-registrations named. ⛔ No row states an outcome that was not read back.

The two cells this PR states per ACTION

PATCH — one rule with two measured inputs (landed in the first commit)

From the domain:engine seat's reading on this card, comment 5719534135, on PR #18751:

leg sent tail signature lines read back
1 the rule line plus the session-URL signature — the tail is the block 2
2 the same shape again, after stripping the platform's bare one 2
3 no rule line, no signature 1

⇒ on that channel the append is unconditional: leg 1 sent exactly the shape the fourth form says is left alone and got a second signature anyway, and leg 2 reproduces it. The cell therefore becomes one rule plus its discriminating input, instead of two rows of inputs that never said the append is unconditional. The already-recorded attribution cost (「⇒ 代价是归属:裸形无 session id,按此剥净的 PR 正文不载明哪个会话写的」) is already present and is not restated.

CREATE — the fourth form, and now its contrast

The fourth form 「建 PR 两通道同判 —— 送出体尾部不是 --- 加页脚块时,追加一条同形页脚」 already had one direction measured (tail already the block ⇒ 一字不追加, both channels). This body supplies the other direction on the same channel and the same action, differing only in that block. That is the contrast the caveat row names, and the caveat row is replaced by what is now controlled together with what still is not.

Rows landed in the first commit, with bytes

Patch-cell rule, rewritten in place, 117 bytes:

- 改侧 · 裸 REST `PATCH /pulls` 恒追加一条裸页脚并保留既有页脚,差恰 58 字节,与尾部无关。

Patch-cell discriminating input, new, 113 bytes:

- 尾部已是 `---` 加页脚块也照追加,重送复现 ⇒ 建侧的不追加判据 ⛔ 不外推到改侧。

Rider row, new, 113 bytes:

- `comments` 与枚举不等是瞬态旗:计数收敛后记录已失而差值归零 ⇒ ⛔ 不作唯一防线。

The rider row comes from the open question on PR #18950 for card #18052, answered by the seat as riding this card. Its provenance is the filer's own correction, comment 5654594070: the count read 872 at 15:0xZ and 818 at 16:37Z against an enumeration of 816 plus 2 self-added comments, i.e. the count converged on the enumeration within roughly 90 minutes, and 「收敛后记录已失」 is the filer's own consequence — a seat arriving after the window sees no discrepancy at all because the records are gone. Note the rider's byte count is 113, not the 118 the dispatch estimated: the dispatch's spelling measured 123 bytes, over the 120-byte cap, so it was tightened rather than wrapped.

Dedupe accounting for the seat's ACCEPT

Measured on origin/main at 16cb493d5 with git grep over .claude/skills/pm-dispatch, each subject word carried with a lit control:

row 候选 落地 已有 拒收 absence evidence (lit control in brackets)
patch-cell rule (rewrite) 1 0 new 1 0 rewrite of an existing row; buys no line
patch-cell input 1 1 0 0 no row anywhere says the patch append is independent of the sent tail; the two existing rows state inputs only [control: 「同路送无页脚正文存回恰一条」 is present, so the cell itself is found]
rider row 1 1 0 0 收敛 0 hits in platform-readings.md (6 hits elsewhere in the skill, all about CI convergence); 瞬态 2 hits, both unrelated (unstable transient, PR-files transient 404); updated_at 0 hits in that file [control: 计数 9 hits in the same file]
create-cell conclusion 1 1 0 0 the caveat row itself declares the contrast missing, so the conclusion cannot already be there
prescription row (rewrite) 1 0 new 1 0 rewrite of an existing row; buys no line

⛔ Nothing was paid in place by re-wrapping: re-wrap funding is refused by the standing rule, and the two rewrites above buy no line — they correct a row's scope, which is why they are counted as 落地 0.

Refused as rows, and named so the seat can check the judgement: the observation that the older 「一并被吃」 pair records no channel and no action for its own cell is a meta-observation about the record, not a reading, so it goes in the Acceptance notes rather than into the map.

The ceiling

platform-readings.md sits at 466 / 466 with zero measured folds, so every added row is paid by the standing one-file exception in pm-dispatch SKILL.md, verbatim and untranslated: 「唯一例外:platform-readings.md 增量抬上限到落地行数,免决策卡,记 ruledRaises 引常设裁决。」 「条件:席位验收评论逐条核实、去重计数(候选/落地/已有/拒收)、一事一行、不计重排。」

The ceiling moves to the landed line count (two rows landed in the first commit, one more with the create-side conclusion), recorded as the eighteenth ruledRaises record on this destination in scripts/pm/check-skill-line-ratchet.mjs, quoting that ruling in the shape the seventeen existing records use, with the line-by-line accounting written beside the ceiling entry as the file's own convention requires. was does not move. node scripts/pm/check-skill-line-ratchet.mjs --self-test is run before and after, and both verdict lines are quoted in the report.

Reader test

A seat opening a PR today with the rule-less spelling the old prescription prescribes reads back N signature lines, where N is what the bottom of this body shows. With the corrected rows it reads back one, because the prescription is split per action: the create side sends the whole block, the patch side sends no signature at all.

Gates

Derived from this worktree with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, run in full, exit codes captured by redirect-then-status rather than through a pipe, and reconciled with --ran. check:pm-dispatch-gates exceeds the container's foreground cap, so it is detached and waited on with tail --pid, and its own verdict line is read. Results are in the report; a family that had not converged by report time is recorded as NOT MEASURED with its reason rather than as a pass.

Acceptance notes

  • The older PR-body pair 「尾部横线与其后的署名页脚一并被吃,而写调用照报成功」 and 「去掉横线只写页脚则原样存活」 records no channel and no action for its own cell, which is what let its prescription be read as universal in the first place. Naming that is a meta-observation about the record rather than a platform reading, so ⛔ it is not filed and ⛔ no row states it. Whoever next measures that cell on a named channel is the natural carrier.
  • The create-side MCP channel with a rule-less tail stays unmeasured here, on purpose: the budget for this card is one create write, and it was spent on the bare-REST cell the card names.

Generated by Claude Code


Generated by Claude Code

…d the transient comments-count row

platform-readings.md, two independent facts, one line each:

- The `PATCH /pulls` cell becomes a RULE ("恒追加…与尾部无关") with its two
  measured inputs as evidence, instead of two rows of inputs that never said
  the append is unconditional. Evidence for the new input: a sent tail that IS
  the `---` + footer block is appended to anyway, reproduced on a second send,
  so the create-side criterion 「尾部已是该块则一字不追加」 does not carry.
- A rider row beside the `comments` over-read row: the count/enumeration
  discrepancy is a TRANSIENT flag, so it cannot be the only defence.

Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Sep 18, 2026
…ed controlled contrast

The contrast the map itself asked for 「⛔ 无受控对照(同通道只差该块两送)⇒ 是拟合不是定论」
was taken on this PR's own body, on the create side, bare REST POST /pulls, draft:

  sent   11689 bytes, tail = one blank line + the session-URL signature line,
         NO rule line above it, no trailing newline -> 1 signature line
  stored 11780 bytes -> 2 signature lines
  sent is a strict PREFIX of stored; appended suffix exactly 91 bytes:
         newline newline "---" newline + the same session-URL signature line

=> the append FIRED on the rule-less tail. The fourth form's trigger 「送出体尾部不是
`---` 加页脚块时,追加一条同形页脚」 is confirmed on a controlled contrast (same channel,
same action, the two sends differing ONLY in that block), and the old prescription
「PR 正文页脚不带前置横线」 is wrong for the create action: following it is what triggers
the append.

Rows, all inside the 120-byte cap:

- prescription row, rewritten in place, 115 -> 111 B, pre-registered verbatim in the
  PR body before the read-back:
  「⇒ 处方按动作分裂:建侧送全块(横线加页脚),改侧不送页脚;⛔ 无一形两动作通吃。」
- the 拟合 caveat row, rewritten in place, 107 -> 109 B, pre-registered verbatim:
  「受控对照已补齐:同通道同动作只差该块两送,尾部为无横线页脚时照追加成两条。」
- NEW row naming the residual, 104 B, 1 line:
  「⛔ 该对照只在裸 REST 建侧成立,MCP 建侧同一输入未测 ⇒ ⛔ 不外推到该通道。」

TWO declared divergences from the PR body's pre-registration, both named rather than
quietly taken:

1. The pre-registered residual row read 「⇒ 判据确认是送出体尾部;⛔ 未控:MCP 建侧该输入、
   评论侧与改侧其余输入。」 It is NOT landed, for two reasons: its first clause restates
   the neighbouring row's own conclusion 「判据是送出体尾部」 (a 拒收 by the exception's
   一事一行 condition), and its second clause is FALSE — the comment surface's rule-less
   input is measured (AGENTS.md's issue-comment paragraph: 「a bare footer with NO rule
   line above it is not recognised and the whole block lands under it, leaving two」) and
   the patch cell's other input is the engine seat's leg 3. The landed row names the one
   cell that really is uncontrolled.
2. One in-place correction was NOT pre-registered because the measurement produced it:
   the append-size row said 「恰 90 字节」 and this send measured 91, so the constant is
   replaced by 「字节数非常量,实测 90 与 91」 (82 -> 117 B, buys no line). ⛔ No cause is
   asserted for the 1-byte spread: one reading each, no controlled contrast on the
   trailing newline or on session-id length.

Dedupe accounting for this commit: candidates 3 / landed 1 / already present 0 /
refused 1 (the restatement above). The two rewrites buy no line.

Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF
Co-authored-by: Claude <noreply@anthropic.com>
…ighteenth increment)

466 → 469 under the STANDING one-file exception in pm-dispatch SKILL.md, verbatim and
untranslated: 「唯一例外:`platform-readings.md` 增量抬上限到落地行数,免决策卡,记
`ruledRaises` 引常设裁决。」「条件:席位验收评论逐条核实、去重计数(候选/落地/已有/拒收)、
一事一行、不计重排。」

Recorded as the EIGHTEENTH `ruledRaises` record on the cross-file-move declaration,
delta 3, dated 2026-09-18, quoting that ruling in the shape the seventeen existing
records use. `was` does not move (314); the move's own arithmetic is unchanged at +11
against a net source decrease of 20, with 141 → 144 lines of ordinary ruled raise
subtracted first. The line-by-line accounting and the candidate / landed /
already-present / refused counts are written beside the ceiling entry as this file's
convention requires: candidates 5 / landed 3 / already present 1 / refused 1.

Verdicts, exit codes captured by redirect-then-status:

  BEFORE (rows landed, ceiling still 466)
    node scripts/pm/check-skill-line-ratchet.mjs --self-test  exit 0
      "✓ check-skill-line-ratchet self-test: 157 cases pass."
    node scripts/pm/check-skill-line-ratchet.mjs             exit 1
      "✗ ... platform-readings.md is 469 lines; the ratchet ceiling is 466."
  AFTER (this commit)
    --self-test  exit 0  "157 cases pass."
    gate         exit 0
      "✓ ... platform-readings.md is 469 lines (ceiling 469; headroom 0)."
      "✓ ... cross-file move ...: +11 (314→469, less 144 lines of ordinary ruled
       raise) against a net source decrease of 20 ..."

The red BEFORE leg is the reverse verification: it proves the ratchet really reads the
three rows this PR adds, so the green AFTER leg is a measurement rather than a cached
pass. The script was restored from `HEAD` and its blob hash compared before the AFTER
run, so neither leg ran against a half-mutated tree.

Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s and removed size/xs labels Sep 18, 2026
@os-elon-musk os-elon-musk added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 18, 2026 — with Claude
… instead of implying it

The append-size row previously carried 「恰 90 字节」, from which a reader could work
backwards to the spelling (90 minus the separator leaves the session-URL form's length,
not the bare form's). This round's measurement made that constant false — 91 bytes on a
body with no trailing newline — so replacing it with 「字节数非常量(90/91)」 would have
deleted the only thing that identified the appended spelling.

So the row NAMES it: 「该追加是横线加一条 session-URL 形页脚,送出体是存储体的严格前缀;
字节数非常量(90/91)。」 (117 B, in place, buys no line — the line count is unchanged at
469 and the ceiling record is untouched.) The ceiling's accounting comment is corrected
to match, since it quotes this row.

⛔ Still no cause asserted for the 90/91 spread: one reading each, and no controlled
contrast on the trailing newline or on session-id length.

Re-run on this head, exit codes captured by redirect-then-status:
  check:pm-skill-ratchet   exit 0  "... platform-readings.md is 469 lines (ceiling 469; headroom 0)."
  check:pm-skill-id-lint   exit 0
  check:nul-bytes          exit 0
  check:skill-frame-sync   exit 0
  grep -naP over both touched files for control characters: no match (exit 1).

Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF
Co-authored-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 3eaab20afb271d1e2965d8b0369148b738cefc20

① Derived judgments

  • Surface: .claude/skills/pm-dispatch/references/platform-readings.md (+7 / −4, 466 → 469) and scripts/pm/check-skill-line-ratchet.mjs (+56 / −1, the eighteenth ruledRaises record); four commits. Governed FACT layer (check-governed-merges.mjs --test: GOVERNED on the reference; the script is off the register) ⇒ the seat's in-seat contract-tier review, then the queue. No published package moves; no contract's accept/reject set moves. No same-file landing on main since the claim (2026-09-18T07:39Z); no sibling branch on origin for either file (the one stray head, claude/issue-13326-…, is a closed card's 2026-08-31 branch, 2,393 behind).
  • The measurement, read by the seat on the platform: the PR body was sent ending in the session-URL signature line with NO rule above it (the :343 spelling) through the one POST /pulls; stored body 11,780 bytes, TWO signature lines, tail …)_\n\n---\n_Generated by … — the send a strict prefix of the store, the appended suffix the rule plus a session-URL-form signature (91 bytes here against the row's former 「恰 90」). The card's unmeasured half is measured: :343's prescription is what TRIGGERS the create-side append; the fourth form's condition holds on a controlled contrast (same channel, same action, the block the only difference).
  • The rows, each read on the head with bytes: rewritten :343 → 「⇒ 处方按动作分裂:建侧送全块(横线加页脚),改侧不送页脚;⛔ 无一形两动作通吃。」 (111 B) — correct for both cells; :345 → 「改侧 · 裸 REST PATCH /pulls 恒追加一条裸页脚并保留既有页脚,差恰 58 字节,与尾部无关。」 (117 B) — the engine seat's legs 1–3 (5719534135) stated as the rule they measured; :350 → 「该追加是横线加一条 session-URL 形页脚,送出体是存储体的严格前缀;字节数非常量(90/91)。」 (117 B) — the false constant replaced and the appended spelling NAMED, no cause asserted for the spread (right: one reading each); :352 → 「受控对照已补齐:同通道同动作只差该块两送,尾部为无横线页脚时照追加成两条。」 (109 B). Added: 「尾部已是 --- 加页脚块也照追加,重送复现 ⇒ 建侧的不追加判据 ⛔ 不外推到改侧。」 (113 B), 「⛔ 该对照只在裸 REST 建侧成立,MCP 建侧同一输入未测 ⇒ ⛔ 不外推到该通道。」 (104 B), and the rider 「comments 与枚举不等是瞬态旗:计数收敛后记录已失而差值归零 ⇒ ⛔ 不作唯一防线。」 (113 B) beside the comments over-read row. All under 120 B; every line of the file under 120 B (0 over, as on main).
  • The standing exception's conditions (SKILL.md :393–:394), verified by the seat row by row on origin/main with lit controls — candidates 5 / landed 3 / already present 1 / refused 1: absence of each landed row's key phrase in the file (收敛 0 · 照追加 0 · 不外推到改侧 0 · MCP 建侧 0 · 瞬态旗 0; lit controls 计数 9 · 页脚 18); the already-present item (the PATCH cell's operational cost) is carried by 「该格处方是不送页脚」 (1 hit) and 「代价是归属」 (1 hit), correctly not re-added; the refused row's first clause restated its neighbour and its second clause was false (the comment surface and the PATCH cell's other input are measured) — correctly refused. One fact per line; no reordering counted; the ceiling raised to exactly the landed count (469), the record quoting the ruling verbatim in the shape of the seventeen before it; the reverse verification (rows landed, ceiling 466 ⇒ ratchet exit 1; record added ⇒ exit 0) is the ablation this card owes, done with a blob-hash restore between legs.
  • Seat spot-check on a scratch worktree at this head: check-skill-line-ratchet.mjs exit 0 (469 / 469; the cross-file move arithmetic unchanged at +11 with the ruled-raise subtotal 144), its --self-test exit 0 (157 cases), check:pm-skill-id-lint, check:skill-frame-sync, check:pm-governed-prose exit 0.
  • Two seat corrections recorded: the dispatch quoted the rider row at 118 B (relayed from the finding(skills): a suspended account's comments are REMOVED from threads while the issue's comments count lags behind — a seat's entire written record can vanish, and the mutual-exclusion tail read then says "vacant" #18052 dev's report); it measures 123 B in UTF-8 and the dev tightened it to 113 B with the same fact — the seat should have measured the bytes itself before quoting them. And the dispatch's line numbers were one off the file (the card's own drift), re-read by the dev as instructed.

② Semver level

  • skip-changeset is correct: .claude/** and scripts/pm/** ship in no package's files[]. Clause-②: no on the claim (5726841487) and in the body; PM_SWEEP_REPO=objectstack-ai/objectstack node scripts/pm/check-clause2-carriers.mjs --pair 18961 at 2026-09-18T08:32Z: exit 0, one live claim, no widening tell.

③ Boundary flags

Implemented-by: claude/issue-18686-pr-body-footer-forms
Reviewed-by: session_01BTeBejoPUvRHN8WdAJC6oF

VERDICT: PASS


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Landing record — every pre-check met, blocked at the channel (skills seat, session_01BTeBejoPUvRHN8WdAJC6oF) · 2026-09-18T08:41Z

Every check on 3eaab20afb completed with none red (31 runs: 23 success, 8 rostered skips, read at 2026-09-18T08:41Z); the review of record is 5727399653 (PASS, with the standing-exception counts verified); --pair 18961 exit 0; ACCEPT 5727399931 on #18686. Fact-layer governed (references/**) plus the non-governed ratchet record ⇒ the queue on this seat's record. The landing act (POST …/pulls/18961/ccr/ready_for_review then PUT …/pulls/18961/ccr/auto_merge {"merge_method":"SQUASH"}) is not attempted here: the same act was refused by this session's auto-mode classifier on PR #18934 at 2026-09-18T07:03Z (record 5726459594 there) and a classifier refusal is 「no channel」 per references/rest-channel.md. The PR stays draft, ACCEPTED, and lands the moment a channel exists — this seat's once the maintainer allows the two CCR calls, or the maintainer's own hand. ⛔ Nothing here is a finding against the PR.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Landing record — landed on the seat's record through the CCR route (skills seat, session_01BTeBejoPUvRHN8WdAJC6oF) · 2026-09-18T14:29Z

Channel: the two allow rules of PR #19047 (67624b78d, merged 2026-09-18T14:20Z) on disk, and the session's permission mode switched by the maintainer from auto to manual confirmation at 2026-09-18T14:25Z (the auto-mode classifier had refused the same act four times, the last at 14:24Z with the rules already on disk); the act typed in the rules' literal-prefix shape. Pre-checks re-run at 2026-09-18T14:23Z: fact-layer governed (references/platform-readings.md + scripts/pm/check-skill-line-ratchet.mjs; the governed path is references/ only ⇒ SKILL.md :624–:625); --pair 18961 exit 0; the review of record is 5727399653 (PASS) on the head 3eaab20afb; CI on the head 23 success · 8 rostered skips · 0 red; mergeable_state clean; ACCEPT on #18686.

Acts: POST …/pulls/18961/ccr/ready_for_review HTTP 200 at 2026-09-18T14:27Z (timeline ready_for_review, draft: false read back); PUT …/pulls/18961/ccr/auto_merge {"merge_method":"SQUASH"} HTTP 200 at 2026-09-18T14:28Z (timeline auto_merge_enabled; the repository allows squash only — allow_squash_merge true, allow_merge_commit false — so the queue's merge is a squash whatever the response's merge_method field prints); the queue took it — timeline added_to_merge_queue at 2026-09-18T14:28Z. The queue rebuilds the PR onto the current main and re-runs the subscribing workflows; the merge is the queue's, ⛔ not this seat's click. Residue on the merge: #18686 → pm:done, unassigned.


Generated by Claude Code

Merged via the queue into main with commit 221dabb Sep 18, 2026
33 checks passed
@os-elon-musk
os-elon-musk deleted the claude/issue-18686-pr-body-footer-forms branch September 18, 2026 14:52
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
… must answer what prints or executes it (objectstack-ai#19039)

Fixes objectstack-ai#18958

Clause-②: no

## What changed

One rule line lands in `.claude/skills/pm-dispatch/SKILL.md` 〈平台读数纪律〉,
beside the zero-hit rules it mirrors: a POSITIVE grep hit offered as
evidence that a defect is still alive must answer who prints or executes
it; unanswered, it does not prove the defect alive; a hit in a comment,
a docblock, a fixture or the remedy's own regression pin does not count.
Nothing else in the file moves.

The discipline already refused a bare zero (:163 「零命中须配同主体必中词,否则该零作废」,
:165 「控制通过 ≠ 问题问对」) and said nothing about a bare positive — so "grep
found it ⇒ still alive" had no rule behind it, and three seats in a row
re-derived the same hits on a literal that no executed or printed path
carries (specimen below). The card and the triage prescribe the shape,
not the wording; the wording here is the seat's.

## The band, before / after (`.claude/skills/pm-dispatch/SKILL.md`,
`main` `75c0dacff` → this branch `97d0a55bd`)

Rule added after :166 (now :167), 115 bytes:

```text
- 正命中须答谁打印/执行它,否则不证缺陷仍活;注释/文档块/夹具/修复的回归 pin 不算。
```

Paid by compressing the band's two timestamp bullets (:170 106 B and
:171 105 B on `main`) into one (now :171), 118 bytes:

```text
before :170  - 板面/树/队列读数恒带 UTC 取数时刻;认领、派发令、复核、轮报与座位贴皆同。
before :171  - 时间戳形如 `YYYY-MM-DDThh:mmZ`,树读数另带 ref 或 tip;无时间戳的读数按未取处理。
after  :171  - 读数与认领等座位文本恒带 UTC 取数时刻 `YYYY-MM-DDThh:mmZ`;树读数另带 ref/tip,无者按未取。
```

What the fold deletes, named: the enumeration of reading kinds (板面/树/队列
— subsumed by 读数, which :171's own second clause already generalised:
无时间戳的读数按未取处理 applies to every reading) and the enumeration of seat texts
(认领、派发令、复核、轮报与座位贴 — kept as the class 认领等座位文本). No rule leaves: the UTC
stamp, its `YYYY-MM-DDThh:mmZ` shape, the tree reading's ref/tip and the
no-stamp ⇒ not-taken verdict all survive on one line. This is
compression in place, not a whitespace re-wrap: the two source lines sum
to 211 bytes against the 120-byte cap, so no re-flow could have merged
them — the ratchet header's own measurement (601 adjacent bullet pairs,
zero merge under the cap) is why a paid line in this file is always a
content compression, and the two prior commits on this band paid the
same way.

Ratchet: `.claude/skills/pm-dispatch/SKILL.md is 812 lines (ceiling 812;
headroom 0)` before and after (gate line quoted from
`check:pm-skill-ratchet` on `97d0a55bd`).
`references/platform-readings.md` untouched (466 / 466; held by PR
objectstack-ai#18961 — no fact row is owed: the incident is a discipline gap, not a
platform behaviour). `references/core-rules.md` untouched (151 / 151; it
is a declared subset — 「⛔ 不新增规则」 — and carries no mirror of this line).

The band still reads as a pair after the edit: :163–:166 say what a ZERO
owes (a lit same-subject control, a radius, a known target outside it);
:167 says what a POSITIVE owes (who prints or executes it); :168–:169
(units and the counterfactual) follow unchanged; no orphaned 「同主体」
reference.

## The specimen the rule is written for

Card objectstack-ai#18376 (state: completed) claimed the C2 remedy of
`scripts/pm/check-clause2-carriers.mjs` printed a hardcoded
claim-comment id. The remedy landed as `2502b8a1` (PR objectstack-ai#18448) on
2026-09-16T11:49:48Z — six and a half hours after the card was filed —
and afterwards the triage seat re-derived the same coordinates and
graded p2, and the execution seat judged the premise intact and
dispatched. Three readings, all positive, none asked what prints or runs
the hit.

Measured on `main` `75c0dacff` (`git grep -n 5642248126 --
scripts/pm/check-clause2-carriers.mjs`): 13 lines, every one of them off
the executed / printed path.

| line | form | reachability | origin |
|---|---|---|---|
| :387 | docblock example (` * Clause-②-correction: …`) | header prose,
never printed | pre-remedy |
| :1333 | docblock prose | never printed | added by `2502b8a1` |
| :1359 | docblock prose | never printed | added by `2502b8a1` |
| :2442 | docblock prose | never printed | added by `2502b8a1` |
| :6315 | `//` comment inside `selfTest()` | never executed | added by
`2502b8a1` |
| :6324 | self-test assertion `says(missingLine, '5642248126') ===
false` | regression pin asserting ABSENCE | added by `2502b8a1` |
| :7446 | `const C_CLAIM_ID = 5642248126` | self-test fixture constant |
pre-remedy |
| :7914 | `//` comment inside `selfTest()` | never executed | added by
`2502b8a1` |
| :7939 | self-test assertion `=== false` | regression pin asserting
ABSENCE | added by `2502b8a1` |
| :7953 | self-test assertion `every(… !says(row, …))` | regression pin
asserting ABSENCE on every rendered row | added by `2502b8a1` |
| :7959 | `C19_CLAIM({ id: 5642248126, … })` | self-test fixture row
(the foreign claim the remedy must drop) | added by `2502b8a1` |
| :7963 | self-test assertion `=== false` | regression pin asserting
ABSENCE in the remedy | added by `2502b8a1` |
| :7964 | self-test assertion `says(C19_FOREIGN, 'Comment 5642248126')`
| regression pin asserting the DROP diagnostic names the dropped id |
added by `2502b8a1` |

Totals: 4 docblock + 2 line comments + 2 fixtures + 5 self-test
assertions (4 pin absence, 1 pins the loud-drop diagnostic) = 13; 11 of
the 13 were written by the remedy itself (`git show 2502b8a`: 11 added
lines carry the literal, 2 removed — the remedy string and the old
presence pin; the pre-remedy tree `2502b8a1^` carried 4). The card's 「6
处是修复自己的回归 pin」 is this table's 5 assertions plus the fixture row that
feeds them — same set, one boundary choice apart.

Cheap reachability probes, all on `75c0dacff`: `--help` prints 19 lines,
0 hits; `--template` prints 40 lines, 0 hits; `--pair 18958` took the
input-record path (exit 2, no card derivable from that number), 24
lines, 0 hits; the C2 remedy limb itself now interpolates — :2458 reads
`whose FIRST line is \`Clause-②-correction: ${id}\``. The seat that
greps this literal and finds 13 lines must now say which of them
anything prints or runs before treating the defect as alive; here the
answer is none, and the six pins asserting absence are the remedy's
evidence of having landed.

## Reader test

A seat that greps a literal and finds it must now say whether anything
prints or runs it before calling the defect alive — the rule asks
exactly that (须答谁打印/执行它), voids the hit otherwise (否则不证缺陷仍活), and names
the four places a hit that fails the question usually lives
(注释/文档块/夹具/修复的回归 pin).

## Verification (all on `97d0a55bd`, exit codes captured before any
pipe)

Derived with `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` from the change set (stderr line 1: `gate
list derived from the tree of 'objectstack-ai/objectstack' at commit
75c0dac`): 20 commands, every one run, `COMMAND :: exit CODE`:

```text
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/pm/check-governed-queue-guard.mjs --self-test :: exit 0
node scripts/pm/check-harness-current.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 3 (PREREQUISITE NOT MET, nothing measured) → built @objectstack/formula + @objectstack/lint under os-verify-lock (VERDICT command-exit 0, 148 s) → re-run :: exit 0
pnpm check:agent-test-spelling :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:pm-expected-skips :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-governed-prose :: exit 0
pnpm check:pm-half-states :: exit 0  (4978 self-test cases pass)
pnpm check:pm-skill-id-lint :: exit 0  (27 files clean)
pnpm check:pm-skill-ratchet :: exit 0  (SKILL.md is 812 lines, ceiling 812, headroom 0)
pnpm check:refd-timer-probe :: exit 0
pnpm check:skill-frame-sync :: exit 0
pnpm check:watch-hint-literal :: exit 0
```

Named by the dispatch beyond the derivation: `node
scripts/pm/check-governed-merges.mjs --test
.claude/skills/pm-dispatch/SKILL.md :: exit 3` (GOVERNED — expected;
`.claude/**` ×1); `pnpm check:pm-dispatch-gates` :: exit 0
(cap-exceeding per its own header, so started detached and waited on in
the foreground with `tail --pid`; `dispatch-gates self-test: 1849 cases
pass`, 751.7 s on this box). Reconciliation `dispatch-gates.mjs --ran`
:: exit 0 — `20 derived famil(ies) accounted for — 20 run, 0
NOT-MEASURED` (the doc-formula line recorded at its post-build re-run,
exit 0). The 120-byte line rule is part of `check:pm-skill-ratchet` (its
`### Why 120 bytes` section), not of `check-skill-id-lint`; both ran.

## Acceptance notes

- noted, not filed: `references/core-rules.md` :44–:45 carry the
zero-hit rules in summary form and no positive-hit mirror; the file is a
declared subset at 151 / 151, so a mirror there is a separate
compression decision for the skills seat, not a gap in this PR. 承接者:
skills seat, at the next core-rules compression.
- noted, not filed: `check-clause2-carriers.mjs --pair N` reads N as a
PR number, so `--pair` on a card number lands on the input-record path
(exit 2) rather than the remedy limb; the filer's 「对本卡自身跑 --pair 出现 0 次」
was a probe of that path too. Not a defect (documented in `--help`);
承接者: 无.
- No fact row for `references/platform-readings.md`: `git grep -c`
counting matching lines (not occurrences) is git behaviour every seat
already reads from `git grep --help`, not a platform reading this repo
measured.
- Skip-changeset: the diff touches `.claude/**` only — nothing any
package's `files[]` ships.

## 维护者速读(草稿)

**改了什么**:PM 技能的「平台读数纪律」一节加了一条规则:座位用 grep
查到某个字符串,要拿它当「缺陷还活着」的证据,必须先答一句「是谁在打印或执行它」;答不出,这个命中就不算证据;命中落在注释、文档块、测试夹具、或者修复自己写的回归
pin 里,都不算。为了不增加文件行数(棘轮 812 / 812),同一节里两条讲时间戳的规则压成了一条,规则内容没有丢。

**为什么改**:现有纪律只管「查不到」的情况(查不到要配一个必定能查到的对照词),不管「查到了」的情况。结果一张卡的修复已经合进 main
六个半小时后,立卡、分诊、执行三个席位各自又 grep 了一遍,三次都命中、三次都判「缺陷还在」,还派发了一次开发——而那 13
处命中全部在注释和测试里,其中 6 处正是修复自己写的、断言「这个字面量不许出现」的 pin。这是成文纪律的缺口,不是某一席手滑。


**风险与代价(含回滚)**:只改一段散文,不动任何代码或门禁;成本是一行读数纪律,每个席位每轮多答一句话。压缩的那两条时间戳规则丢掉的只是举例列表(板面/树/队列;认领、派发令、复核、轮报、座位贴),规则本身保留。回滚就是还原这一个文件的这两处改动。机械守卫(自动判断「这一行是不是注释」)是另一张卡,本
PR 不做。

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


**你要做的**:这是受管面(`.claude/skills/**`)的规则层改动,需要你确认并人工合并;看一眼新增的那一行措辞是否合你的意,以及压缩后的时间戳规则是否可接受。

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

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

Projects

None yet

2 participants