Skip to content

docs(pm-skills): the multi-label page truncates into a false-empty lane, and the arming echo is not the landing method - #18713

Merged
os-justin merged 1 commit into
mainfrom
claude/issue-18461-list-issues-or-filter-and-arm-echo
Sep 17, 2026
Merged

os-justin merged 1 commit into
mainfrom
claude/issue-18461-list-issues-or-filter-and-arm-echo

Conversation

@os-justin

Copy link
Copy Markdown
Collaborator

Fixes #18461

Clause-②: no

One file: .claude/skills/pm-dispatch/references/platform-readings.md, held at 466 / 466 (headroom 0,
widest line 120 B). No ceiling raised. Net line change 0: one row rewritten in place, one row added, one
payment taken in the same file. skip-changeset — .claude/** is shipped by no package's files[], so
nothing published moves.

Reserved rows are untouched and verified by content: :10–:12 and :431 (#18469 PR-A's pending patch),
:209 (PR #18666's one-line change, awaiting the maintainer — it rides at :208 after the payment, byte
identical), and the nine rows PR #18689 adopted an hour before this branch (:28, :85, :249, :277–:278,
:291, :347, :357, :393, :410 — none appears in any hunk of this diff).

Row ② — rewritten in place at :50

Ruling reference: the maintainer's letter A on #18421, comment 5716260764 (2026-09-17T14:41Z, 「同意」).
Its operative conclusion is the one this row carries: auto_merge.merge_method is not a reading of what will
land
— the landing shape is the merge queue's to decide.

before (120 B, the falsified form):

- 挂上的 auto-merge 存的方法恒为 `merge`,不论请求了什么;REST `auto_merge.merge_method` 读回 `merge`。

after (117 B):

- auto-merge 回读 `merge_method` 不恒定:同 `SQUASH` 载荷 `merge`/`squash` 皆现,⛔ 非落地方法判据。

Why 「不恒定」 and not either constant. 「恒为 merge」 is falsified by this card's four PRs; 「恒为
squash」 is falsified by the same table's first row and by the ruling's own measurement. Same endpoint
(PUT .../pulls/{n}/ccr/auto_merge), same {"merge_method":"SQUASH"} payload:

PR echoed merge_method landed as
#18395 merge single-parent squash
#18392 squash single-parent squash
#18416 squash single-parent squash
#18445 squash single-parent squash

The #18421 ruling measured the same endpoint answering merge (both arming channels, MCP and CCR), and the
dispatching seat's own arms today echoed squash on PR #18689 / #18690 / #18700 and merge on earlier ones.
Four landings, two echoes, one landing shape ⇒ the echo varies and decides nothing. A row asserting either
constant would teach a seat to investigate a read-back that is simply not a signal.

Neighbours left as they are. :49 is about the bare PATCH draft bit — unrelated. :51
(「仓库 allow_merge_commit:false 时同样读回 merge」) does not restate 「恒」: it is one conditioned
measurement, and 「同样」 now attaches to merge, which the rewritten row names as one of the two observed
values. :53–:55 already carry the landing half (the branch rule decides; three carriers agreeing proves
nothing) and are untouched — the row above them no longer contradicts them.

Row ① — added at :272

after (118 B):

- 多标签页还静默截断:`totalCount` 231 而 `returned` 30,单标签同车道 24/24 ⇒ 求交读成空车道。

Placement — a declared deviation from the dispatch. The dispatch named the :247–:248 neighbourhood
(the MCP list_issues rows). The OR half of this reading is already in the file, in the 读数陷阱 cluster at
:269–:274: :269 「labels 数组是并集」, :270 「⛔ 永不读作交集」, :272 「失效全静默」, :273
「正确读法 = 整车道单标签一次读全加本地对 labels 求交」. Writing the new row at :247 would have put a second
home for the labels-OR fact six rows away from the first — the same duplication the dispatch forbids for row ②
(one row for one fact, never two). So the row is placed where the fact it compounds already lives: directly
between the silent-failure row :272 and the prescription :273, which it is the reason for. The fact
delivered is unchanged; only the address is.

What the row adds over :269–:274. Those rows carry the OR semantics and the prescription. They do not
carry the truncation, and the two compound: the returned page is a fraction of the set with nothing in the
response saying which fraction, so a local intersection taken over that page can return zero and read as
「本车道无活」. The measurement is inside the row: labels=["domain:cli","pm:queue"] answered totalCount=231
with returned=30, while the single-label query on the same lane in the same minute answered 24 / 24 —
complete, and intersectable. That is what makes :273 load-bearing rather than a style preference.

The payment — one dedup, :202+:203 become one row

payment before after fact lost
:202+:203 「换道:探针绿走 REST 列表端点 GET /repos/{o}/{r}/issues?state=open&labels=a,b&per_page=N。」 + 「它走 core 桶且 labels 是真 AND;⛔ 完整性自证靠 &page=N 加总数核对。」 「换道:探针绿走 REST 列表端点列卡,走 core 桶且 labels 真 AND;拼写与自证见 rest-channel.md。」 (118 B) the inline endpoint spelling and the &page=N-plus-total spelling — both held verbatim in rest-channel.md 〈读侧〉, which :137 already names as their single home (「逐操作通道归属、写侧配方与队列路由三读法见 rest-channel.md,⛔ 不在本表复述」). The two facts the row keeps inline are the ones a seat needs before it switches channel; labels being a true AND on REST is also stated in-file at :274, and the core bucket at :115 / :128.

Net: 3 lines changed, 466 in, 466 out.

Gate readings

node scripts/pm/check-governed-merges.mjs --test .claude/skills/pm-dispatch/references/platform-readings.md
exits 3 = GOVERNED (.claude/** ×1) — recorded as the verdict it is. This PR stays draft; no seat flips it
ready, enqueues it or arms auto-merge. The references tier applies: the skills seat's ## Contract review
record goes on this thread, and the seat lands it.

  • pnpm check:pm-skill-ratchet :: exit 0 — 「platform-readings.md is 466 lines (ceiling 466; headroom 0)」,
    「widest table row is 0 bytes (pin 0; headroom 0)」; no line over 120 B (awk 'length > 120' returns nothing).
  • pnpm check:skill-frame-sync :: exit 0 — 「the one declared copy of the decision frame is internally
    coherent … 4 axes … 74 markdown files scanned for undeclared copies」.
  • pnpm lint (repo-wide, eslint . --no-inline-config) :: exit 0.
  • grep -naP for control characters over the file: no hits. No tag-shaped fragment in either new row.

Derived gate list, with exit codes

Derived from the worktree with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack
(no hand-fed paths; change set 1 path vs merge base 72dd95fa5), every command run, each exit code captured by
redirect-then-$?:

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 0
pnpm check:agent-test-spelling                                      :: exit 0
pnpm check:doc-authoring                                            :: exit 0
pnpm check:driver-memory-census                                     :: exit 0
pnpm check:nul-bytes                                                :: exit 0
pnpm check:pm-governed-merges                                       :: exit 0
pnpm check:pm-half-states                                           :: exit 0
pnpm check:pm-skill-id-lint                                         :: exit 0
pnpm check:pm-skill-ratchet                                         :: exit 0
pnpm check:refd-timer-probe                                         :: exit 0
pnpm check:required-contexts                                        :: exit 0
pnpm check:skill-frame-sync                                         :: exit 0
pnpm check:watch-hint-literal                                       :: exit 0
pnpm check:pm-settings-deny-roster                                  :: exit 0   (outside the derivation; run
                                                                                 because its roster lives under
                                                                                 .claude, which this path is in)

check:doc-formula-expressions first exited 3 — PREREQUISITE NOT MET (@objectstack/formula and
@objectstack/lint not built, 「Nothing was measured」). It was re-run to a real verdict after
pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint through
scripts/pm/os-verify-lock.sh (VERDICT command-exit 0, held 1s, waited 0s); only the exit 0 is recorded above.

Reconciliation: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.txt →
「18 derived famil(ies) accounted for — 18 run, 0 NOT-MEASURED (a DERIVED zero — all 18 recorded an exit code
and none of them is 3)」. Outside that union: the 53 artifact-roster families, 11 wide-population families,
14 changeset-pending families and the CI-only families (--verify-required-set, check-half-states --provenance) — CI's, not this branch's, and named here so their absence is not read as a clearance.

Out of scope, reported not written

The card's third item — scripts/pm/check-expected-skips.mjs cannot run in a seat container
(ERR_MODULE_NOT_FOUND: Cannot find package 'yaml') — is not a references line and is not written here. In this
worktree, after pnpm install, yaml@2.9.0 is present; the crash is a property of the container the seat runs
it from, not of the script.

Generated by Claude Code


Generated by Claude Code

…ne, and the arming echo is not the landing method

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

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 0e783e659cd528508f55e3b3e7c06f906eccdad0

Review of record on the PR thread (the Governed Surface Guard's merge_group leg reads this thread alone — #18701). In-seat review of PR #18713 (#18461) by the dispatching domain:skills seat, 2026-09-17T16:28Z, read against the PR's diff, files and head on GitHub and a scratch worktree at the head — ⛔ not against the dev report (5717770330). Clause-②: no on the PR body and on the claim (5717478127); check-clause2-carriers --pair 18713 answers 0. Fact-layer landing: the one file is .claude/skills/pm-dispatch/references/platform-readings.md, so check-governed-merges --pr 18713 answers GOVERNED (exit 3, .claude/** ×1) and the seat lands it on this review of record — the references/** carve-out the SKILL names.

① Derived judgments

② Semver level

None — no package is touched; skip-changeset on the PR is correct for .claude/**.

③ Boundary flags

  • Dev's open_questions: none. Stop conditions: none fired. One declared placement deviation, accepted above.
  • Out-of-scope findings: (1) the yaml gap in a seat container — carried on [finding] platform-readings: the list_issues labels filter is OR and truncates (can read as an empty lane), and auto_merge's stored merge_method is not always merge #18461 itself, not a references line; (2) the PR-body create channel appended a 90-byte rule-plus-session-URL footer under a footerless-tail body — a confirming measurement of :348–:350 / :412, not a new fact.
  • Gates: 18 derived, 18 run, 0 NOT-MEASURED, all exit 0 per the report (doc-formula-expressions first PREREQUISITE, rebuilt through the verify lock and re-run at 0); seat-side on the head: ratchet 0, frame-sync 0, over-120 0, --pair 0, GOVERNED exit 3, harness CURRENT. CI on the head at review time: 13 success, 12 skipped, 4 in progress; the landing pre-check re-reads every run completed and none failure before the ready flip.
  • Writes: api_writes 3 (draft PR, skip-changeset via label-write read back, this report), mcp_calls 0, PR body written once at create — within budget.
  • Independence pair: mode:subagent build, in-seat review by the dispatching seat at CONTRACT_REVIEW_TIER — by design per contract-review.md, not SELF-REVIEW.

Implemented-by: claude/issue-18461-list-issues-or-filter-and-arm-echo
Reviewed-by: session_01Gqi43smmqjJ5sUrhfoPeKu

VERDICT: PASS


Generated by Claude Code

@os-justin
os-justin marked this pull request as ready for review September 17, 2026 16:38
@os-justin
os-justin added this pull request to the merge queue Sep 17, 2026
Merged via the queue into main with commit 080688b Sep 17, 2026
32 checks passed
@os-justin
os-justin deleted the claude/issue-18461-list-issues-or-filter-and-arm-echo branch September 17, 2026 17:02
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…_limit cannot see (objectstack-ai#18741)

Fixes objectstack-ai#18601

`Clause-②: no`

One file: `.claude/skills/pm-dispatch/references/platform-readings.md`,
held at **466 / 466**
(headroom 0, widest line in the file still 120 B at `:21`, untouched).
No ceiling raised, net line
change **0**: two rows rewritten in place, one row added, one dedup
taken in the same file.
`skip-changeset` — `.claude/**` is shipped by no package's `files[]`, so
nothing published moves.

Reserved rows are untouched, verified by content after the edit:
`:10`–`:12` and `:431` (objectstack-ai#18469
PR-A), PR objectstack-ai#18666's one line (now at `:209`, byte identical), `:51` (was
`:50`) and `:272` (PR
objectstack-ai#18713), and the nine rows PR objectstack-ai#18689 adopted (`:28`, `:86`, `:249`,
`:277`–`:278`, `:291`, `:347`,
`:357`, `:393`, `:410` — none appears in any hunk of this diff).

## What the card measured, and what the table now says

The seat's only undraft channel, `POST
.../pulls/{n}/ccr/ready_for_review`, draws on the **session
credential's hourly GraphQL quota** and answers **HTTP 429 with a
zero-byte write** when that quota
is spent — `GET /pulls/{n}` still read `draft: true`. In the same
minute, on the same credential,
`GET /rate_limit` reported `graphql` **10000 / 10000** and `core` 15000
/ 15000. So the table's
prescription 「graphql remaining < 1000 ⇒ 本轮走 git 加 REST」 reads an
instrument that cannot see
the pool that stops you, and a full reading is **not a pass** for the
undraft act.

The reading is **one session's, one hour**: this seat's own arms today
(four PRs) went through the
same ccr route without a 429. The row carries that by naming the pool as
会话凭据的 GraphQL 小时池
rather than generalising the trigger to the route as such.

## The undraft rows — `:47` rewritten, `:48` rewritten, `:49` added

**before** (`:47`, 97 B · `:48`, 118 B):

```text
- undraft 单通道:席位凭据走 `POST .../pulls/{n}/ccr/ready_for_review`;MCP 兜底已拒。
- 2026-09-12 两席实调:裸 GraphQL 会话内被拒,建议的 REST 正是 ccr 路 ⇒ 池 0 不再只能等重置。
```

**after** (`:47`, 115 B · `:48`, 116 B · `:49`, 104 B):

```text
- undraft 单通道:席位凭据走 `POST .../pulls/{n}/ccr/ready_for_review`;MCP 兜底与裸 GraphQL 均已拒。
- 2026-09-17 单席实测:该路吃会话凭据的 GraphQL 小时池,尽则 429 且零字节写入,`draft` 未动。
- 唯一可读信号是该 429 体自报的 `resets at` 时刻;体自带指令 ⛔ 重置前不重试。
```

`:48`'s facts are kept, not dropped. 「裸 GraphQL 会话内被拒」 folds into `:47`
as 「MCP 兜底与裸
GraphQL 均已拒」, and 「建议的 REST 正是 ccr 路」 is what `:47`'s main clause
already states — one
row for one fact. What is deleted is the tail 「⇒ 池 0 不再只能等重置」, and only
because today's
reading is its reverse: the ccr route itself draws on the pool, so a
spent pool is again a wait.
The routing rule is untouched — the seat still undrafts through this
route; there is no second one.

`:49` carries the 429's own two halves: the `resets at` instant is the
only readable signal that
exists before the act, and the refusal to retry is the body's own
instruction, attributed to it so
that no retry cadence is invented here.

## The prescription row — `:162` (now `:163`) rewritten in place

**before** (109 B):

```text
- 它答不了通道在不在,repo-scoped 探针另跑;graphql remaining < 1000 ⇒ 本轮走 git 加 REST。
```

**after** (118 B):

```text
- graphql remaining < 1000 ⇒ 本轮走 git 加 REST;⛔ 满余额不放行 undraft:同分钟满额而 ccr 路 429。
```

## The payment — one dedup, `:223` folded into `:94`

| payment | before | after | fact lost |
|---|---|---|---|
| `:162` first clause dropped (in-file duplicate), which paid for the
blind-spot clause in the same row | 「它答不了通道在不在,repo-scoped 探针另跑」 | —
(clause removed) | the point-of-use restatement beside `:161`. The fact
is held twice in the same section, 50+ rows earlier: `:106`
「开轮探一次…探针必须是一条真 repo-scoped 读」 and `:109` 「`/rate_limit` 照答 200,兼任不了探针」
|
| `:223` deleted, its one unique clause folded into `:94` (78 B → 103 B,
now `:95`), which paid for the new row `:49` | 「配额按账户计,不跨席共享:各席位跑在不同
GitHub 账户下。」 + 「配额池按身份计,换身份即清零燃烧,共享身份结构不变。」 | 「配额按账户计,不跨席共享:各席位跑在不同
GitHub 账户下;换身份即清零燃烧。」 | 「共享身份结构不变」 — held by `:96` 「所有 agent
共用一个身份只在席位内部成立」 and `:97` 「⛔ 不据限流报文里的 user ID 推池子跨席共用」 (post-edit
numbering). 「配额池按身份计」 is the same statement as the kept row's opening
clause |

Net: 5 lines changed, 466 in, 466 out.

## Why this row shape — the four axes

- **实际业务需求** — measured, not speculative: a green, reviewed,
clause-②-PASS undraft was stuck
27 minutes with no readable indicator before the act. Both edited sites
are points of use: a seat
reads `:47`–`:49` at the moment it undrafts, and `:163` at the start of
a round, when it budgets
the pool. Writing the fact at one site only would leave the other
reading exactly as it read this
  morning — which is how the seat got there.
- **项目长远合理性** — no workaround: no second channel is invented, no probe
is added, and the
correction is made where the falsified claim lives rather than appended
as a caveat. The stale
tail is removed instead of being qualified, so the table keeps one
statement per fact.
- **防 AI 写代码犯错** — the axis that decides the shape. The failure mode
here is a **tolerant
reading**: 10000 / 10000 looks like clearance, and the seat acts on it.
So the prescription row
itself carries the refusal (`⛔ 满余额不放行 undraft`) with its own evidence
(同分钟满额而 ccr 路
429) rather than a pointer to another row — a reader who never scrolls
to `:47` still cannot read
a full balance as a pass. Splitting the undraft fact across `:48` and
`:49` is what bought room
for the `resets at` instant; folding both into one row would have
dropped it, and it is the only
  signal a seat can act on.
- **创业阶段不扩散需求** — zero net lines, zero new surface, zero tooling. The
card's second
suggestion (make the 429's named wait a legal state in the landing flow)
is a `SKILL.md` /
lane-text matter and is deliberately NOT written here; it is raised in
the report's
  `open_questions` instead.

The alternative shape — both facts in one new row — was rejected on the
third axis: at ≤ 120 B one
row holds either the pool ownership or the instrument blind spot, not
both, and the half that would
have been dropped is the half a seat reads at round start.

## Gate readings

`node scripts/pm/check-governed-merges.mjs --test
.claude/skills/pm-dispatch/references/platform-readings.md`
exits **3 = GOVERNED** (`.claude/**`) — recorded as the verdict it is.
This PR stays draft; this
branch never flips ready and never arms auto-merge. The skills seat's
`## Contract review` record
goes on this thread, and the seat lands it.

- `pnpm check:pm-skill-ratchet` :: exit 0 — 「platform-readings.md is 466
lines (ceiling 466;
  headroom 0)」, 「widest table row is 0 bytes (pin 0; headroom 0)」.
- `pnpm check:skill-frame-sync` :: exit 0 — 「the one declared copy of
the decision frame is
internally coherent … 4 axes … 74 markdown files scanned for undeclared
copies」.
- `pnpm lint` (repo-wide, `eslint . --no-inline-config`) :: exit 0.
- Byte discipline: `LC_ALL=C awk 'length($0) > 120'` over the file
prints nothing; `grep -naP` for
control characters prints nothing; nothing tag-shaped is written in the
new rows.

### Derived gate list, with exit codes

Derived from the worktree with `node scripts/pm/dispatch-gates.mjs
--commands --repo objectstack-ai/objectstack`
(no hand-fed paths; change set 1 path vs merge base `080688b56`), every
command run, each exit code
captured by redirect-then-`$?`:

```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 0
pnpm check:agent-test-spelling                                      :: exit 0
pnpm check:doc-authoring                                            :: exit 0
pnpm check:driver-memory-census                                     :: exit 0
pnpm check:nul-bytes                                                :: exit 0
pnpm check:pm-governed-merges                                       :: exit 0
pnpm check:pm-half-states                                           :: exit 0
pnpm check:pm-skill-id-lint                                         :: exit 0
pnpm check:pm-skill-ratchet                                         :: exit 0
pnpm check:refd-timer-probe                                         :: exit 0
pnpm check:required-contexts                                        :: exit 0
pnpm check:skill-frame-sync                                         :: exit 0
pnpm check:watch-hint-literal                                       :: exit 0
pnpm check:pm-settings-deny-roster                                  :: exit 0   (outside the
                                                                                 derivation; run
                                                                                 because its roster
                                                                                 lives under .claude)
pnpm lint                                                           :: exit 0   (outside the
                                                                                 derivation)
```

`check:doc-formula-expressions` first exited **3 — PREREQUISITE NOT
MET** (`@objectstack/lint` not
built, 「Nothing was measured」), which is not a failed measurement. It
was re-run to a real verdict
after `pnpm exec turbo run build --filter=@objectstack/formula
--filter=@objectstack/lint` through
`scripts/pm/os-verify-lock.sh` (`VERDICT command-exit 0 · held the lock
167s · waited 0s`); only the
exit 0 is recorded above.

Reconciliation: `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --ran ran.txt`
→ 「18 derived famil(ies) accounted for — 18 run, 0 NOT-MEASURED (a
DERIVED zero — all 18 recorded
an exit code and none of them is 3)」. Outside that union and named so
their absence is not read as
clearance: the 53 artifact-roster families, the 11 wide-population
families, the 14
changeset-pending families and the CI-only families
(`--verify-required-set`, `check-half-states
--provenance`) — CI's, not this branch's.

## Acceptance notes

- Noted, not filed: nothing in this diff's neighbourhood is a defect of
its own except the item
raised in the report's `out_of_scope_findings` (three rows in the 配额
section rest on the same
rationale this card falsified — 「ccr 路是 REST ⇒ 不吃 GraphQL 池」 — and
correcting them needs a
measurement nobody has taken: whether a `/rate_limit`-red window
predicts a ccr 429 at all). That
one is filed rather than fixed here: the fix shape is not pinned, and
the dispatch scopes the
  routing and red-window scheduling rules out of this PR.

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

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
…t on the write-side footer cell (objectstack-ai#18837)

Fixes objectstack-ai#18622

`Clause-②: no`

Written by session `session_01Gqi43smmqjJ5sUrhfoPeKu` on branch
`claude/issue-18622-edit-footer-provenance` — the session id is stated
here, in prose, because this card is about exactly the reason that is
necessary.

This is a re-derivation against the tip plus **one row**, paid in place.
The cell has grown a lot since the card was filed at 09:27Z (PR objectstack-ai#18689,
objectstack-ai#18713, objectstack-ai#18741, objectstack-ai#18775, objectstack-ai#18808 all landed on this file today), and most
of what the card asked for is already carried.

## The carried-map — six readings against `origin/main` `ad1f94e8ec`

The bands re-derived on this head: the write-side footer cell is
:340–:359, the issue-body cell :409–:414.

| # | reading | verdict | carried by |
|:--|:--|:--|:--|
| a | `POST /pulls` stores the author's session-URL footer verbatim |
**CARRIED** | :350 「尾部已是该块则一字不追加,两通道各实测两向 ⇒ 建侧通道不是变量,判据是送出体尾部。」 read
with :348 「第四形:建 PR 两通道同判 —— 送出体尾部不是 `---` 加页脚块时,追加一条同形页脚。」 — 「同形」 is
what makes the stored block the author's, the session-URL spelling
included |
| b | `PATCH /pulls` appends the BARE form | **CARRIED** | :345 「裸 REST
`PATCH /pulls` 追加一个裸页脚并保留既有 session-URL 页脚,差恰 58 字节。」 and :346
「同路送无页脚正文存回恰一条(平台裸形)⇒ 该格处方是不送页脚,⛔ 不是不重送正文。」 |
| b′ | ⇒ so an edited body silently loses which session wrote it |
**RESIDUAL** — and, as the card states it, *falsified* on this tip |
nothing. See below |
| c | ⇒ durable attribution on an edited body lives in body PROSE, not
in the footer | **CARRIED — in the rule layer, by design** | `AGENTS.md`
:433 「Durable attribution lives in body prose or a comment.」 and
`.claude/agents/os-dev.md` :403 「耐久归属写进正文散文或评论,⛔ 不循环重贴页脚;完整读数住 AGENTS.md
同条。」 Nothing in :340–:359 / :409–:414 carries it, and nothing should |
| d | an issue-body `PATCH` synthesises one bare block on a block-less
body and re-anchors a bare-block tail to one | **CARRIED** | :412 「issue
正文 `PATCH` 识别按整块:送全块或不送页脚都存回恰一条,已有页脚归一末尾不复制。」 — both arms in one row;
with :411 for the create-side +58 and :413 for the rule-less
counter-case (total two) |
| e | a `PATCH` appends a bare block under a session-URL tail |
**CARRIED** | :345, verbatim above — the bare one is appended, the
session-URL one is kept, difference exactly 58 bytes |
| f | `POST /pulls` stores a session-URL tail byte-exact | **CARRIED** |
:350 for the 「一字不追加」 half. The trailing-newline trim reported beside it
in PR objectstack-ai#18786 (10841 sent / 10840 stored) is :356 「平台在尾部 `---`
前后正反两向归一空行:比对正文只按首个差异偏移,⛔ 不按长度。」 — which is precisely why the file
already refuses to let length be the verdict;
`trailing-newline-stripped` is a declared clean class in
`scripts/pm/post-stamped.mjs` |

### Why (c) is not written into the fact table

The card itself says 「这不是新规则」, and the ratchet's own maintainer ruling
for `references/` reads: *「one rule per ≤120-byte line, no rule already
stated in SKILL.md」*. `AGENTS.md` :433 already states the prescription,
and `.claude/agents/os-dev.md` :403 explicitly routes the full reading
to it — 「完整读数住 AGENTS.md 同条」. Writing 「耐久归属写正文散文」 into the fact table
would be a third copy of a rule that this corpus has deliberately given
exactly one home, the same content-ownership call the 2026-09-01 ruling
made for the red-window rule (「红窗规则由 `platform-readings.md` 配额段独家持有」).
So the new row **points** at `AGENTS.md` instead of restating it.

### Why (b′) is the residual, and why the card's own wording needed
correcting

The card reads 「一次正文编辑会静默丢掉「是哪个会话写的」」 — unconditionally. On this tip
that is **false as stated**, and :345 is what falsifies it: an
un-stripped `PATCH /pulls` **keeps** the existing session-URL block and
adds a bare one, +58 bytes — attribution intact, merely duplicated. The
loss happens on exactly one path: the one the cell itself prescribes at
:346–:347 (send no footer, strip *both* spellings). Then the stored
body's only attribution block is the platform's bare form, which carries
no session id.

A reader can get this wrong in both directions today: from :345 alone,
"my session-URL footer is preserved, attribution is safe"; from the card
alone, "any edit loses it". The residual sentence is the price tag on
the cell's own prescription, and nothing in the cell states it.

## The one row, and what paid for it

**Added**, at :348, immediately after the two rows whose prescription it
prices (118 bytes):

```
- ⇒ 代价是归属:裸形无 session id,按此剥净的 PR 正文不载明哪个会话写的;另置见 AGENTS.md。
```

**Retired**, the old :353 (114 bytes):

```
- 删页脚那条读数是唯一不合此判据的观察,通道已拒 ⇒ 活通道无反例,写后仍必回读。
```

Where its content survives, all of it inside the same cell:

| clause of the retired row | survives at |
|:--|:--|
| 「删页脚那条读数」 + 「通道已拒」 | :344 「MCP `update_pull_request` 包装器删掉 PR
正文的页脚块;该通道锁 1 已拒,读作历史。」 |
| 「活通道无反例」 | the same :344 — 「读作历史」 is what makes the single deleting
observation a dead-channel one |
| 「写后仍必回读」 | :355 「⇒ 形态随动作与送出体尾部变,改侧还随通道变;⛔ 不由任一条推其余,写后必回读。」 and :343 「⇒
PR 正文页脚不带前置横线,且写后回读正文 —— 那是唯一检测手段;评论两形皆可。」 |

⛔ No re-wrap was used as currency; ⛔ no ceiling was raised; net line
change is **zero**. Nothing outside the write-side footer cell was
touched — `git diff --stat` is `1 insertion(+), 1 deletion(-)`.

## Reserved bands — verified by content, md5 before and after

| band | content | md5 before | md5 after |
|:--|:--|:--|:--|
| :10–:12 | objectstack-ai#18469 PR-A (timeline `added_to_merge_queue` rows) |
`4b1a925b6f6004ebd8bf05ea4f477d24` | `4b1a925b6f6004ebd8bf05ea4f477d24`
|
| :29 | PR objectstack-ai#18775's zero-legacy-status row |
`9a1ac5fab8b1c0351d95472397eb1614` | `9a1ac5fab8b1c0351d95472397eb1614`
|
| :209–:215 | PR objectstack-ai#18666's band — its one hunk on this file, confirmed
from `/pulls/18666/files` (1/1, context :209–:215, changed line :212) |
`88505120d3f807422999b1e17e9e1266` | `88505120d3f807422999b1e17e9e1266`
|
| :432 | the `[Self-Approval]` row | `ed771ed2703b2ee5bcb02f29eddf4844`
| `ed771ed2703b2ee5bcb02f29eddf4844` |

All four byte-identical. Line numbers are unmoved too: the insert lands
at :348 and the retirement at the old :353, so every line from :354 on
keeps its number.

## The ratchet

```
before: .claude/skills/pm-dispatch/references/platform-readings.md is 466 lines (ceiling 466; headroom 0)
after : ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/platform-readings.md is 466 lines (ceiling 466; headroom 0)
        ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/platform-readings.md: widest table row is 0 bytes (pin 0; headroom 0)
node scripts/pm/check-skill-line-ratchet.mjs :: exit 0
```

## Derived gates

`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` from the worktree, no hand-fed path list.
Change set: 1 path,
`.claude/skills/pm-dispatch/references/platform-readings.md`, three-dot
against merge base `ad1f94e8e`. Every exit code captured
redirect-then-`$?`.

```
0  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  node scripts/pm/check-harness-current.mjs --self-test
0  pnpm --filter @objectstack/lint run check:doc-formula-expressions   (SECOND run — see below)
0  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-half-states
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
```

`check:doc-formula-expressions` answered **exit 3 PREREQUISITE NOT MET**
on its first run — 「the workspace package `@objectstack/formula` is not
built」, with `@objectstack/lint` unbuilt as a second unmet prerequisite.
Built under the shared verify lock (`bash scripts/pm/os-verify-lock.sh
-c "NODE_OPTIONS=--max-old-space-size=4096 pnpm
--workspace-concurrency=2 --filter '@objectstack/lint...' --filter
'@objectstack/formula...' build"`, `VERDICT command-exit 0 · held the
lock 152s · waited 0s`) and re-run: **the 0 above is that second run.**

Reconciliation, `--ran` with a code recorded per family:

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

One family was run beyond the derived union, because the derivation
marked its roster ⛔ *「roster under .claude, which one of your paths is
in」* and said the silence is not evidence in either direction:

```
0  pnpm check:pm-settings-deny-roster
```

Repo-wide, at the final commit `deaa1d0fd7`:

```
0  pnpm lint     (node --stack-size=4000 eslint . --no-inline-config)
```

Byte discipline: `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` over the
edited file returns no hits (exit 1), beyond `check:nul-bytes` above.

## Out of scope, noted here and reported to the seat

**To file (class a, a fact-table row a merged PR falsified).** :357
reads 「送全块即触发该归一 ⇒ `post-stamped` 的 `body` 档把这点空白判 `mutated`,净零字节良性告警。」
PR objectstack-ai#18786 (objectstack-ai#18693) landed at `94b3f37be3`, on this head: the body-mode
trailing-rule re-anchor is now its own declared clean class
`footer-re-anchored`, exit 0, printing `read-back: clean`, and
`body_mutated` is false. So that row is wrong on both the class word and
「告警」. It is a different reading in a different part of the cell, it
needs a fresh measurement rather than a mechanical rewrite, and this
card's dispatch bounds the diff to the residual — so it is reported, not
fixed here. Dedupe words: `post-stamped body mutated` ·
`footer-re-anchored` · `platform-readings 357` · `classifyReadBack
class` · 「净零字节良性告警」.

**Noted, not filed.** objectstack-ai#18686's create-side tension (:343's 「PR
正文页脚不带前置横线」 against :348's fourth form) was read and deliberately left
alone — it is the next card on this cell and its controlled comparison
was not run here. Successor: card objectstack-ai#18686, already open and queued behind
this one.

## Verification method note

This PR body was created with a tail of blank line + rule + the
session-URL footer block, which is :350's measured no-append shape on
the create side and `AGENTS.md`'s prescribed form — `AGENTS.md` wins
over :343 where the two differ, per its own precedence line. The body
was read back after the write.

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

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

Projects

None yet

2 participants