docs(pm-skills): a repo with zero legacy statuses reads the combined-status endpoint as an empty-set default - #18775
Conversation
…status endpoint as an empty-set default
`GET /commits/{sha}/status` answers `state: "pending"` + `total_count: 0` on a
commit that carries no legacy commit statuses at all. That is the API's default
for an empty set, not a verdict about the gates, and it reads exactly like
"gates still running" — a seat that waits on it waits forever.
One row added beside the row that sends a reader to that endpoint, scoped to the
repos the trap is live in. Paid in the same file by retiring the footer-mechanism
preamble, whose whole content is held twelve rows later, more precisely.
Claude-Session: https://claude.ai/code/session_01Gqi43smmqjJ5sUrhfoPeKu
Co-authored-by: Claude <noreply@anthropic.com>
…mbined-status-pending-trap
Contract reviewServed-tier: Review of record on the PR thread (the queue guard's merge_group leg reads this thread and, since PR #18738, the card thread too). In-seat review of PR #18775 (#18733) by the dispatching ① Derived judgments
② Semver levelNone — no package is touched; ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #18733
Clause-②: noOne file:
.claude/skills/pm-dispatch/references/platform-readings.md, held at 466 / 466(ceiling 466, headroom 0; widest line in the file still 120 B at
:464, untouched). No ceilingraised, net line change 0: one row added, one row retired in the same file.
skip-changeset—.claude/**is shipped by no package'sfiles[], so nothing published moves.The trap
:28is the row that sends a reader toGET /commits/{sha}/status. On a commit that carries nolegacy commit statuses at all, that endpoint answers
state: "pending"withtotal_count: 0—the API's default for an empty set, not a verdict about anything. In a repo whose gates are all
check-runs the field is
pendingforever and means nothing, while reading exactly like "gates stillrunning": a seat that waits on it waits forever, and a seat that reads
pendingas not-yet-red canread a red PR as merely unfinished. The gate reading is
/commits/{sha}/check-runs.Measurements
Three
objectstack-ai/cloudheads — the card's table, verbatim (all fully green):objectstack-ai/cloud#231903c170eccompleted/success(2026-09-16T16:13:44Z)state: "pending",total_count: 0objectstack-ai/cloud#2320b4b1c5c4completed/success(2026-09-17T15:47:03Z)state: "pending",total_count: 0objectstack-ai/cloud#232123e928b7completed/success(2026-09-17T17:14:33Z)state: "pending",total_count: 0This repo, fetched through the REST proxy at 2026-09-17T19:57Z–19:59Z — measured here, ⛔ not
retyped from the card. Raw
state/total_counton both sides:/commits/{sha}/statusstatuses[]/commits/{sha}/check-runsd852dae1(PR #18750 head)state: "success",total_count: 1Vercel/successtotal_count: 40, 29completed/success+ 11completed/skipped702b4241(PR #18756 head)state: "success",total_count: 1Vercel/successtotal_count: 39, 28completed/success+ 11completed/skipped2f38ee0d(PR #18758 head)state: "success",total_count: 1Vercel/successtotal_count: 32, 24completed/success+ 8completed/skipped95e17452(maintip at branch point)state: "success",total_count: 1Vercel/successtotal_count: 59e2050cef(main)state: "success",total_count: 1Vercel/successtotal_count: 71bc2ec806(main)state: "success",total_count: 1Vercel/successtotal_count: 64The reading that scopes the row:
objectstack-ai/objectstackposts a legacyVercelstatus onevery commit, so the empty-set default never arises here. One further control makes that exact,
taken on this branch's own first commit
55c8e844at 19:59:48Z, seconds after the push and beforeany workflow had started:
/commits/{sha}/statusstatuses[]/commits/{sha}/check-runs55c8e844(this branch, pre-CI)state: "pending",total_count: 1Vercel/pendingtotal_count: 0This repo answers
pendingtoo — for the opposite reason. There,total_count: 1and a realVercelstatus genuinely in flight; in the card's three cloud heads,total_count: 0and no statusat all.
total_countis the discriminant,stateis not, which is why the row names bothfields rather than the word
pendingalone.⇒ the row is scoped 「零 legacy status 的仓」, ⛔ not 「所有仓」.
The row added —
:29, 118 BIt sits directly under
:28「unstable可源自 check-runs 看不见的 commit STATUS(如Vercel)⇒③ 另读
/commits/{sha}/status」, which names this repo's legacy status and points at the endpoint.The new row inherits that subject — the idiom the block already uses at
:30,:63,:65,:67—and states the condition under which the endpoint stops answering the question.
Against the card's proposed line, at the file's ≤ 120 B cap: 「那是空 legacy 集合的默认值」 is kept as
「空集默认值」 (「legacy」 already stands in the row's first clause), 「⛔ 不是门禁读数」 as
「⛔ 非门禁读数」, and 「门禁只认
/commits/{sha}/check-runs的completed/success」 as「门禁读 check-runs」. What changed on purpose is the scope: the card wrote 「在只有 check-runs 的
commit 上」, and the measurement above makes it a property of the repo, which is where the legacy
status is configured.
The payment —
:343retired, 85 Bbefore (
:343, pre-edit numbering):Why the tree no longer needs it as a separate line: it is a preamble that states the block's own
conclusion, which the same block states again at its end, more precisely. It carried two clauses,
and both are held:
:355「⇒ 形态随动作与送出体尾部变,改侧还随通道变」 — three loci named where the retired row named two, and:342「⇒ 失效既依拼写又依载体:评论里验过页脚对 PR 正文什么都没证明」 states the same localisation at the point of use:355「⛔ 不由任一条推其余,写后必回读」, and:351「⛔ 无受控对照(同通道只差该块两送)⇒ 是拟合不是定论,⛔ 不外推到别的动作」No fact leaves the corpus: every reading the block holds (
:340–:343,:344–:354) is untouched,and the row that generalises them — the one a reader reaches after the evidence rather than
before it — keeps the generalisation with the read-back prescription attached. The retired row is not
one of the nine PR #18689 adopted, not one of the three
配额rows #18744 names (:137,:145,:146), and not one of the four PR #18741 landed today (:47–:49,:163).The ratchet's standing one-file exception 「唯一例外:
platform-readings.md增量抬上限到落地行数,免决策卡,记
ruledRaises引常设裁决」 (scripts/pm/check-skill-line-ratchet.mjs) was not taken:a payment with zero fact loss was available, so the ceiling stays at 466 and no ruling is spent.
② re-read — CARRIED, no row, and a premise correction to the card
The card's ② says: "The existing entry says
/search/*is refused by the egress proxy. What it doesnot say is the shape of the refusal." On
mainthat sentence is false. Three consecutive rowssay exactly the shape (pre-edit numbering, the seat's
:209–:211):Mapped against the card's proposed addition, clause by clause: 「它的拒绝是成功形状的」 is
:209's 「403 体解析成净零」; 「回 JSON」 is:210's 「而那是合法 JSON」; 「total_count键缺失 ⇒.get()读成None、打印出来像 0」 is:211, which adds the measurement the card does nothave — 「与真空集只差一个字符,而请求根本没跑」.
The only residual is the card's prescription 「断言键在,⛔ 不断言值」, and that is precisely what
the open PR #18666 (for #18454, governed, awaiting the maintainer) lands on that same line. Its hunk
on this file is one line,
@@ -209,7 +209,7 @@:「缺键即拒绝」 is the assert-the-key prescription in the file's own voice, and 「判别式是状态码」 is
one notch sharper than the card asked for: it names the discriminant rather than the symptom. So the
residual is zero once #18666 lands, and the line a residual row would have to touch is #18666's own
hunk — a reserved line. ⇒ no row for ②, and the
search_issuesblock:192–:201is untouched.The card's own attribution note observes that the
domain:spec @ objectuiseat recorded the sameshape independently and argues that is the reason to put it in the shared table. It is in the shared
table; what the card measured is that a reader did not find it there.
Reserved rows — verified against the open PRs' hunks, by content
:10–:12([finding] the harness auto-mode classifier denies the protocol's landing command non-deterministically — 8 byte-identicalPUT …/ccr/auto_mergefrom one turn: 4 allowed / 4 denied under three reasons; and a hooks landing rotates every seat off shift before it can flip ready #18469 PR-A) — byte-identical before and after; the diff's two hunks are at:26–:32and
:341–:347, so these lines are in neither.:208–:212(PR docs(pm-dispatch): name the repository each cited instrument answers for #18666) — the only open PR touching this file, confirmed by reading all 26 openPRs' file lists at 2026-09-17T19:50Z; its hunk's changed line is the
total_countrow. The bandmoves by the insertion: on
mainthe changed line is:211and the hunk's full context windowis
:208–:214; on this head they are:212and:209–:215. Every byte in the band isunchanged, so docs(pm-dispatch): name the repository each cited instrument answers for #18666 still applies.
:431([finding] the harness auto-mode classifier denies the protocol's landing command non-deterministically — 8 byte-identicalPUT …/ccr/auto_mergefrom one turn: 4 allowed / 4 denied under three reasons; and a hooks landing rotates every seat off shift before it can flip ready #18469 PR-A) — this number was already stale before this diff. The row the card names,「harness 按内容拒写:同会话派发 PR 上 PASS 拒为
[Self-Approval]」, reads:432onmain, andread
:432at7636cd9b81^too, so PR docs(pm-skills): the undraft ccr route eats a GraphQL pool that /rate_limit cannot see #18741's body carried the off-by-one rather than the rowhaving moved.
:431is a different row (「分支删除被拒有第二形态:代理回 403」). After this diff the[Self-Approval]row is still at:432: the insertion at:29and the retirement at:344cancel across it.
Ratchet before / after
node scripts/pm/check-skill-line-ratchet.mjs, both pins, exit 0 on both sides:Widest line in the file, measured per row in bytes: 120 B at
:464on both sides, unchanged; norow exceeds 120 B on either side; the added row is 118 B.
Derived gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackfrom the worktree,no hand-fed path list — 18 families, all re-run at the final head
d6bc4775e5with$?capturedbefore any pipe:
Reconciled:
dispatch-gates.mjs --ranreads 「18 derived famil(ies) accounted for — 18 run, 0NOT-MEASURED (a DERIVED zero — all 18 recorded an exit code and none of them is 3)」.
On the first pass
check:doc-formula-expressionsexited 3 — PREREQUISITE NOT MET, its own text「Nothing was measured: this gate exited before running a single check」; its two declared
prerequisites were built under
scripts/pm/os-verify-lock.sh(VERDICT command-exit 0, held 158 s,waited 0 s) and it then exited 0, which is the reading recorded above.
Also run, outside the derived 18:
pnpm check:pm-settings-deny-rosterexit 0 — the derivation marksit 「roster under .claude, which one of your paths is in」, where silence is evidence in neither
direction. Repo-wide
pnpm lint(eslint . --no-inline-config): exit 0 atd6bc4775e5.Generated by Claude Code