Uh oh!
There was an error while loading. Please reload this page.
refs(pm-dispatch): bank five measured platform readings, paid for by same-file compression - #12659
Merged
Merged
Conversation
…ull_requests A leading `-` on a quoted phrase is silently dropped: `-"Part of"` and `"Part of"` return the same total_count and the same top hit, and 197 + 197 does not reconcile against the unfiltered 216 — so the two are not a partition of anything. The qualifier half of the same query keeps exact arithmetic (linked:issue 2903 + -linked:issue 216 = 3119), which is what makes the failure dangerous: one call returns correct arithmetic from the qualifiers and silent nonsense from the free text. The row carries the discipline that follows — any stratification built on a free-text term must run its complement and sum both against the unfiltered population. Paid for in the same file (line ratchet 314/314, headroom 0): - search_issues session-zeroing row 12 -> 10: dropped "不是工具/平台级" (survives as 故障是**会话级**), the perPage pointer (own row above), the "极易半途而废" aside (survives as the 226/100 specimen) and the undetermined-mechanism tail (survives as ⛔ 已推翻别再追). - 读数五坑 `gh` clause 7 -> 5: dropped the `command -v gh` exit-1 evidence (survives as **容器里没有 `gh`**) and the pipe-exit-code cross-reference (survives in os-dev.md's 门禁结果读法 clause). - auto-tier classifier row 5 -> 4: label-POST specimen compressed to 判定还跨天翻面, keeping the cross-day fact and dropping the anecdote. - quota-per-account row 7 -> 6: dropped 端点自身不计费 (survives at the 开轮先读配额 clause's "免费") and the used-10461/core-7 specimen (survives as the independent-pools reading in the 默认读序 row). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MnijPVVDakqK2J335JoJtq
…hat auto_merge is unstable The merge-queue rows recorded what cannot tell you a PR is enqueued (`auto_merge` reads back off, `merge_group` is a false negative off the queue front) and named the authoritative confirmation as a webhook — so a seat with a blind instrument and a ⛔ rule that depends on the reading it cannot make did the predictable thing and re-armed an already-enqueued PR. Per the filing seat's own correction, the webhook IS reachable from a subscribed session (measured within ~1s of the timeline event), so the row states the division rather than a gap: the timeline is the reading you make — queryable on demand, both directions from one call, and it separates "never enqueued" from "enqueued then ejected" — while the webhook is push-only corroboration that a fresh context or an unsubscribed seat cannot recover. `auto_merge` is upgraded from absent to UNSTABLE: the same PR read `set` and then `None` within a minute, so "not armed" is never a conclusion. Sits beside the just-landed mergeable_state / update_pull_request / draft-dequeue reshaping; none of those cuts is reopened. Paid for in the same file (line ratchet 314/314, headroom 0): - MCP read-side entity row 7 -> 5: dropped the write-side shape enumeration (survives in the 写侧实测行为 rows it pointed at) and the MCP-or-API attribution aside, keeping the & boundary. - REST-availability row 12 -> 11: shift matrix trimmed to the two readings that prove 门态逐容器变; the per-entry gh/rate_limit details survive at the 单调用凭据判别 clause and the 读数五坑 gh clause. - probe-branch row 8 -> 7: dropped the pre-claim-check restatement (survives as 失效方向是活卡被永久读成已被认领) and the undiagnosed-cause enumeration, keeping the boundary itself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MnijPVVDakqK2J335JoJtq
… a clean zero Unauthenticated REST from inside a session reaches repository-scoped paths only; anything under /search/ is refused by the proxy. The refusal body is valid JSON, so a caller reading total_count off it gets None and formats it as `total: None` — one character away from a real empty result set. A duplicate check that ran three such queries produced three clean-looking zeros, and the request never ran at all. The instrument for /search questions is the MCP search tools; repo-scoped enumeration is unaffected. Placed directly under the session-zeroing row so that row's "见下条" pointer resolves, and it carries the pairing the card asked for: run the positive control FIRST, because a zero that matches your expectations is the one you never re-check — here the control zeroing alongside the others is the only reason the artefact was caught. Paid for in the same file (line ratchet 314/314, headroom 0): - truncation-diagnosis row 12 -> 10: dropped the WebFetch restatement (the same instruction survives in the merged ⛔ 永不单凭 MCP 读判截断 clause), the three-seat observation anecdote, and the 0-span/10-tag control example (the 判据 itself survives verbatim). - sanitizer author-rule row 7 -> 6: the comment-exemption history compressed to ⛔ 评论不豁免 (the mechanism survives in the 评论 row below it). - sanitizer issue-body row 9 -> 7: merged the two fenced-behaviour readings into one dated clause, dropped the negative-lookbehind aside and the "同类标记在评论里存活" note whose rule survives as ⛔ 评论不豁免. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MnijPVVDakqK2J335JoJtq
… number `issue_read` with method `get_labels` and a PULL REQUEST number fails with a GraphQL resolution error — its query resolves the Issue type only, so the REST convention that a PR is also an issue does not carry over. Measured twice on different PRs by different dev runs in the same hour. Label read-backs on PRs are a mandated step, so every dev walks this path and re-derives the workaround alone; the row names the working read (`pull_request_read get`, whose response carries the labels array) and rules out the obvious fallback of spending a search-channel call to answer a single-PR question. The failure is loud, which is the good direction — the row exists to stop the re-derivation, not to prevent a wrong answer. Placed with the other label-semantics traps (`labels` OR-vs-AND, the whole-set replace) so the read-back rule and its instrument sit together. Paid for in the same file (line ratchet 314/314, headroom 0): - MCP-parameter row 10 -> 9: the OR-side evidence keeps the sharper of the two specimens (a two-label "intersection" wider than one of its own inputs) and drops the duplicate one. - list_issues-assignees row 3 -> 2: dropped the trailing ⛔ restatement, which repeats 清单只是候选名单 verbatim in imperative form. - MCP list/search row 3 -> 2: dropped the navigational pointer to the session-gate row printed directly above it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MnijPVVDakqK2J335JoJtq
…ndate re-derivation Two rows, both measured 2026-08-27. A dispatched subagent that terminates mid-edit because the account's model tier hit its limit is a THIRD death shape, and the fact table had no name for it: the host reports the limit, so it is neither an ordinary subagent death nor a maintainer abort — the dispatch is dead, the premise is intact, and re-dispatch is blocked on a resource rather than on anything about the card. Handling is dead-claim recovery plus worktree rescue, not premise re-verification and not an escalation. No pre-flight probe exists (quota state is observable only once a dev dies inside it), so the mitigation is dev-side WIP-committing, which the row says rather than implying. The second row is what keeps the lane moving. A mandated tier must not be downgraded because it is unavailable — that is the substitution the downgrade fuse refuses — but "this lane is fable-mandated" is usually recalled rather than derived, and the recalled version is too wide. Re-deriving with dispatch-gates --tier PER FILE SURFACE splits a blocked fold instead of stopping it (measured: SKILL.md and .claude/agents/** are mandated; scripts/pm/** and references/** carry no path mandate, turning a fully-blocked three-card fold into one blocked half and three runnable ones). The path line is a floor, never a clearance — content clauses are still judged separately. Paid for in the same file (line ratchet 314/314, headroom 0): - sanitizer comment row 8 -> 6: dropped the second-order anecdote (the card recording the incident truncating at the same point), the safe-authoring recipe (verbatim in the author-rule row above) and the "人看着像正常收尾" restatement; the truncation shape, the fuse and the worst-case boundary all stay. - silent-downgrade rows 9 -> 8: the host-fork row was entirely a modifier on the row above it, so it becomes that row's⚠️ clause; both host readings, both dates and the transcript fallback survive. - blocked-download row 3 -> 2: dropped the unverified-verdict anecdote and the zero-hit cross-reference; os-dev.md carries the same rule with the same evidence. - enable-sequence row 8 -> 7: dropped the stale-PR-reading specimen, whose fact (contradictory merged booleans) is the 二义读数 row's subject. - default-read-order row 8 -> 7: kept one of two specimens for independent metering. - git-first row 11 -> 10: dropped the container-has-no-gh duplicate (the 读数五坑 row asserts it) and the search/core independence duplicate (the default-read-order row above states it). - org-authorization row 3 -> 2: the valid-JSON-403 mechanism now lives in the session-proxy row, so this row cites it instead of restating it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MnijPVVDakqK2J335JoJtq
os-litant
marked this pull request as ready for review
August 27, 2026 04:16
os-zhuang
approved these changes
Aug 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#12486
Fixes#12534
Fixes#12604
Fixes#12628
Fixes#12640
Five measured platform facts become fact-table rows in
.claude/skills/pm-dispatch/references/platform-readings.md. That file is the onlysurface this PR touches.
Zero-headroom accounting. The line ratchet pins the file at 314 and it was sitting at
exactly 314, so every added line is paid for by compression inside the same file. No
row was re-wrapped to squeeze a line out — each cut removes content, and the ledger below
names where that content survives. Final state: 314/314, headroom 0; widest table row 0
bytes (pin 0).
Governed surface (
.claude/**, Markdown): stays draft for a maintainer merge. Nochangeset — this publishes nothing (
skip-changeset).The five rows
1 · A free-text negation is inert in
search_pull_requestsAPI 配额section, new row, 5 lines.A leading
-on a quoted phrase is silently dropped:-"Part of"and"Part of"returnthe same
total_count(197) and the same top hit, and 197 + 197 does not reconcile againstthe unfiltered 216 — so the two are not a partition of anything. The qualifier half of the
same query keeps exact arithmetic (
linked:issue2903 +-linked:issue216 = 3119). Onecall, correct arithmetic from the qualifiers, silent nonsense from the free text. The row
carries the discipline that follows: any stratification built on a free-text term must run
its complement and sum both against the unfiltered population; if they do not reconcile,
the text half is not filtering.
Placed after the two
search_issuesreliability rows, so the search instruments readtogether.
2 · The reachable positive enqueue instrument, and
auto_mergeas unstable队列成员资格与 auto-mergesection, existing timeline row 4 → 8 lines.The table named what cannot tell you a PR is enqueued and pointed at a webhook for the
positive answer — leaving a seat with a blind instrument and a ⛔ rule that depends on the
reading it cannot make, which is how an already-enqueued PR got re-armed.
Per the filing seat's own 2026-08-26 correction, the webhook is reachable from a
subscribed session (observed within ~1s of the timeline event), so the row states the
division rather than a gap:
added_to_merge_queue/removed_from_merge_queue) is the reading youmake — queryable on demand, both directions from one call, and it separates "never
enqueued" from "enqueued then ejected";
pull_request.enqueuedwebhook is push-only corroboration a fresh context or anunsubscribed seat cannot recover;
auto_mergeis upgraded from absent to UNSTABLE — the same PR readsetand thenNonewithin a minute, so "not armed" is never a conclusion from it.This sits beside the just-landed
mergeable_state/update_pull_request/draft-dequeue reshaping. None of that chain's cuts is reopened.
3 · The session proxy's
/search403 parses as a clean zeroAPI 配额section, new row, 5 lines.Unauthenticated REST from inside a session reaches repository-scoped paths only; anything
under
/search/is refused. The refusal body is valid JSON, so a caller readingtotal_countoff it getsNoneand printstotal: None— one character from a real emptyresult set. Three duplicate-check queries produced three clean-looking zeros and never ran.
The instrument for
/searchquestions is the MCP search tools; repo-scoped enumeration isunaffected.
Placed directly under the session-zeroing row so that row's
见下条pointer resolves, andcarrying the pairing the card asked for: run the positive control FIRST, because a zero
that matches your expectations is the one you never re-check.
4 · Tier-quota termination, and re-deriving the mandate per file surface
读数陷阱section, two new rows, 8 lines.A subagent that terminates mid-edit because the account's model tier hit its limit is a
third death shape the table had no name for: the host reports the limit, so it is
neither an ordinary subagent death nor a maintainer abort — the dispatch is dead, the
premise is intact, and re-dispatch is blocked on a resource. Handling is dead-claim
recovery plus worktree rescue, not premise re-verification and not an escalation. No
pre-flight probe exists, so the mitigation is dev-side WIP-committing.
The second row is what keeps a lane moving. A mandated tier must not be downgraded because
it is unavailable — but "this lane is fable-mandated" is usually recalled, and the
recalled version is too wide. Re-deriving with
dispatch-gates --tierper file surfacesplits a blocked fold instead of stopping it (measured:
SKILL.mdand.claude/agents/**are mandated;
scripts/pm/**andreferences/**carry no path mandate — a fully-blockedthree-card fold became one blocked half and three runnable ones). The path line is a
floor, never a clearance.
5 ·
issue_read get_labelscannot resolve a PR numberAPI 配额section, new row, 3 lines.get_labelsresolves the GraphQLIssuetype only, so a pull request number errors with"Could not resolve to an Issue" — the REST convention that a PR is also an issue does not
carry over. Measured twice, on different PRs, by different dev runs in the same hour. Label
read-backs on PRs are a mandated step, so every dev walks this path; the row names the
working read (
pull_request_read get, whose response carries the labels array) and rulesout spending a search-channel call on a single-PR question.
Placed with the other label-semantics traps so the read-back rule and its instrument sit
together.
Cut ledger — every cut, and where its content survives
search_issuessession-zeroing不是工具/平台级(survives as故障是会话级) · the perPage pointer (its own dedicated row above) ·极易半途而废(survives as the 226/100 specimen) · the undetermined-mechanism tail (survives as⛔ 已推翻别再追)读数五坑gh clausecommand -v ghexit-1 evidence (survives as容器里没有 gh) · the pipe-exit-code cross-reference (survives in os-dev.md's gate-reading clause)判定还跨天翻面— the cross-day fact is kept, the story is not端点自身不计费(survives at the开轮先读配额clause's免费) · the used-10461/core-7 specimen (survives as the independent-pools reading in the默认读序row)写侧实测行为rows it pointed at) · the MCP-or-API attribution aside; the&boundary is kept门态逐容器变; the per-entry details survive at the credential-discriminator clause and the gh clause判据is verbatim⛔ 评论不豁免(mechanism survives in the comment row below)同类标记在评论里存活(rule survives as⛔ 评论不豁免)人看着像正常收尾restatement; shape, fuse and worst-case boundary all kept二义读数row's own subject读数五坑row asserts it) · the search/core independence duplicate (the row directly above states it)list_issuesassignees清单只是候选名单in imperative formNet: +25 added / −25 paid, landing back at 314. Every figure in this table is read
back from
git diff -U0 d79c6025f..HEADhunk headers, not from notes taken while editing —that re-derivation caught one: the first commit's message records the gh clause as
7 -> 5; it is7 -> 6, as above. The commit is already pushed and this branch isnever force-pushed, so the correction lives here and in the dev report rather than in
rewritten history. The totals above are the diff's own.
Verification
Derived union, not recalled:
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackwith no paths, re-run after
git fetchso the stale-tree warning cleared. It reads thechange set from the merge base itself — exactly one path, this file. Eight families.
All runs below are at
887592d04, the branch head, which is also the merge commit thatbrings
origin/mainin.Verdict lines, quoted from the gates themselves (exit codes captured before any pipe):
check:doc-formula-expressionsfirst answered PREREQUISITE NOT MET (@objectstack/formulathen
@objectstack/lintnot built) — read as NOT MEASURED, not as red; both were built andthe gate then produced the verdict line above.
One family is not measurable here and CI owns it:
scripts/pm/check-governed-queue-guard.mjsreads
GITHUB_EVENT_PATHand refuses without a workflow event payload(
"could not look" must never exit 0 here). That is a declared CI-only input, not afinding.
Declared narrowing: the repo-wide
pnpm lintsweep was not run locally; the derivedunion above is the local scope, and CI runs the whole farm exactly once regardless.
Generated by Claude Code
Generated by Claude Code