Skip to content

docs(pm): name the landing flow's wait state when the ccr undraft route answers 429 - #19717

Merged
huangyiirene merged 1 commit into
mainfrom
claude/issue-18743-undraft-429-named-wait-state
Sep 22, 2026
Merged

huangyiirene merged 1 commit into
mainfrom
claude/issue-18743-undraft-429-named-wait-state

Conversation

@huangyiirene

Copy link
Copy Markdown
Collaborator

Fixes #18743

What lands

One rule line in .claude/skills/pm-dispatch/references/landing-operations.md §B — the landing
flow's own state list — naming what an arming run IS when the ccr undraft route
(POST .../pulls/{n}/ccr/ready_for_review) answers 429. Before this, a seat that met that 429
held a fact (the body's resets at instant), a prohibition (never retry before the reset, never
busy-poll, never blind-retry) and no declared outcome, so its only exits were to report a
dated wait as a blocked landing or to invent a cadence — the thing the rules forbid.

Added at line 22, 120 bytes (the ratchet's per-line cap is 120, and a line of exactly 120 bytes passes — 34 lines of the
corpus already sit at exactly 120):

- undraft 撞 429 ⇒ 落地入等 `resets at` 态:该刻记卡,到点一次重试;⛔ 不报阻塞、不自定节奏。

It carries the three parts the card's contract asks for — the named wait on the instant, the
instant recorded on the card, one retry at it — plus both prohibitions (⛔ not a blocked landing,
⛔ no self-chosen cadence). The facts stay where they are: platform-readings.md is not edited.

Where it goes, and why there rather than the alternatives

Measured, not assumed. Three homes were on the table.

  1. Beside the arm act (chosen). The 429 is returned by the ready flip itself — zero bytes
    written, draft unmoved. So the line belongs in the block that performs the flip (the
    flip-定点 → 绿即转 ready + 挂 auto-merge → the no-busy-poll discipline). It sits immediately
    after the CI-webhook line so that the pair 绿即转 ready… ↔ CI success webhook 不可靠… stays
    intact, and so the new state reads as the permitted action under that line's ⛔ 不坐等 /
    ⛔ 不忙轮询: the wait is a 定点 the platform names, not one the seat picks.
  2. Beside the three-step enqueue check — rejected. That check is gated on
    ready + 全绿 ≠ 已入队. A 429 leaves the PR not ready at all, so that precondition is false
    and the three-step ladder never starts. Filing the state there would put it behind a door the
    429 can never open.
  3. rest-channel.md — rejected. That file is a per-operation channel table ("which route
    does this act take"), and it already carries the route. What is missing is not a route but a
    landing state, and the landing flow's state list is §B here.

How the line is paid: the retired duplicate

landing-operations.md is at ceiling 69 with headroom 0, so the line is paid in-file by retiring
one. Retired:

- ⛔ 不放宽其它任何 PR 的 queue-only 落地。

Two independent covers, both checkable:

  • It restates a rule that lives in SKILL.md. SKILL.md already states
    路径面干净的才转 ready → 入队;队列是唯一被认可的落地路径,⛔ 永不队列外合并。 — unconditional, and
    strictly stronger than "don't relax it for any other PR". This file's own ceiling convention,
    quoted in the ratchet's CEILINGS comment for the 80 → 69 lowering, is verbatim
    "no rule already stated in SKILL.md". So the line is a duplicate by the file's declared standard,
    not by my reading of it.
  • Inside this file it has no residual work. Its only possible job was bounding the two
    main-red exceptions directly above it, and both already carry their own bounds in their own
    text — 限 p0、机械、根因已核实的止血 PR and 仅限 main-red 修复. Nothing normative is lost with
    it gone.

Net: 69 lines before, 69 after. The ceiling is not raised and no cross-file move is declared.

Verification

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
(no paths — the script takes its own change set from the merge base), then reconciled with
--ran. Exit codes captured before any pipe, into a file.

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

The families the dispatch named, with the verdict each printed:

gate exit verdict line
pnpm check:pm-skill-ratchet 0 landing-operations.md is 69 lines (ceiling 69; headroom 0) · widest table row is 0 bytes (pin 0; headroom 0)
pnpm check:pm-skill-id-lint 0 30 file(s) clean (pattern /#[0-9]{3,}/g)
pnpm check:skill-frame-sync 0 the one declared copy of the decision frame is internally coherent · 77 md files scanned for undeclared copies
pnpm check:pm-governed-prose 0 2 instruction surface(s) name all 6 registered governed surfaces and claim no others
pnpm check:doc-authoring 0 403 files clean — no bare metadata literals
pnpm check:nul-bytes 0 scanned 9210 text file(s) … no raw ASCII control bytes

The other eleven derived families also exited 0: check:pm-governed-merges,
check:cross-package-test-inputs, check:driver-memory-census, check:agent-test-spelling,
check:gitlink-declared, check:refd-timer-probe, check:watch-hint-literal,
@objectstack/lint run check:doc-formula-expressions, check-closing-keyword-parity.mjs (both
with and without --self-test), check-comment-mask-corpus.mjs and
check-harness-current.mjs --self-test. Four of them first answered exit 3 in the fresh
worktree (prerequisite not met — no node_modules; one also needed
@objectstack/formula + @objectstack/lint built). Exit 3 is not a finding and was not recorded
as one: pnpm install and a locked
turbo run build --filter=@objectstack/formula --filter=@objectstack/lint cleared it and all four
were re-run to a real verdict. The build ran through scripts/pm/os-verify-lock.sh, which printed
VERDICT command-exit 0 · held the lock 177s · waited 0s.

Beyond the gate: a direct control-character sweep of the edited file,
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', exited 1 (no match).

No ablation or reverse-verification run is claimed here: the change is one line of governed prose
with no executable behaviour, so there is nothing whose removal a test could be shown to detect.
The ratchet is the instrument that would have caught a miscount, and it is green at 69/69.

Changeset

skip-changeset. Measured rather than asserted: .claude exists as exactly one directory in
the tree, at the repo root. The only package at the repo root is @objectstack/spec-monorepo,
which is private: true and declares no files[]. Of the 83 tracked package.json files, 70
declare a files[] and zero of their entries names .claude under any spelling; the
remaining 13 are all private: true. So nothing in this diff reaches a published tarball.

Acceptance notes

No out-of-scope cards are owed from this round. One boundary worth recording, deliberately not
filed:

  • SKILL.md and references/filing-gate.md each already carry a 429 rule (429 即停写 /
    收到 429 或次级限流 ⇒ 该席本 fire 停写). Those govern the write budget on the claude[bot]
    token, a different pool from the session credential's GraphQL hourly pool that the undraft
    route draws on, and they prescribe stopping writes — which is precisely what would push a
    seat toward reporting the landing as blocked. They are near neighbours of the gap this PR
    closes, not statements of it, and they are correct as written. An observation, so no card.

Generated by Claude Code

…s 429

The landing flow's state list had no legal state for a 429 on
POST .../pulls/{n}/ccr/ready_for_review. A seat that met it held a fact
(the body's `resets at` instant), a prohibition (never retry before the
reset, never busy-poll) and no declared outcome, so it could only report
a dated wait as a blocked landing or invent a cadence.

The new line sits beside the arm act it belongs to: the 429 is returned
BY the ready flip, zero bytes written and `draft` unmoved, so the PR
never reaches the ready + all-green precondition the three-step enqueue
check is gated on.

Paid in-file at 69/69 by retiring the queue-only restatement: its rule
is already stated in SKILL.md ("the queue is the only sanctioned landing
path, never merge outside the queue"), and inside this file its only
work was bounding the two main-red exceptions, both of which already
carry their own bounds.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wnstp2kTth7sGXfr8fXypc

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 1dda953eadb639ee6be47e2e136585e4bb0103ea

① Derived judgments

Rendered in-seat by the skills seat 1 session at the served tier the maintainer named on this date (the fable tier word at get_session → external_metadata.last_served_model; ruling record 5771798588; the constant on origin/main names it since PR #19684). The contract is the card's class-(b) reading — the landing flow has a fact (platform-readings.md :49 / :50 / :164: the ccr undraft route draws on the session credential's hourly GraphQL pool, answers 429 with a zero-byte write, the body's resets at is the only readable signal, ⛔ 重置前不重试) and a prohibition (no busy-polling, no blind retries) but no declared outcome for an arming run that meets the 429 — and the seat's dispatch: one rule line in landing-operations.md §B naming that state, paid in-file, ⛔ not SKILL.md, ⛔ not platform-readings.md.

  • (a) The diff is the one line and its payment — right, measured. git diff origin/main...1dda953ea is references/landing-operations.md +1 / −1, one commit on the branch, merge base a251aaa19 = origin/main at the seat's fetch. Added at :22, §B: 「- undraft 撞 429 ⇒ 落地入等 resets at 态:该刻记卡,到点一次重试;⛔ 不报阻塞、不自定节奏。」 — 120 bytes, at the ratchet's per-line cap (the cap admits a line whose length does not exceed it); all three parts of the state are in it: the named wait on the instant the 429 body names, the instant recorded on the card, one retry at it, ⛔ not a blocked landing, ⛔ no self-chosen cadence. Retired at old :50: 「- ⛔ 不放宽其它任何 PR 的 queue-only 落地。」. 69 / 69, headroom 0; the widest-table-row pin (0) untouched.
  • (b) Placement — argued and right. The 429 is returned by the ready flip itself, so the state sits in the arm-act block (:19–:21: the flip 定点, 「绿即转 ready + 挂 auto-merge」, the no-busy-poll discipline), directly after :21 so it reads as the permitted action under that line's ⛔ 不坐等 / ⛔ 不忙轮询 — the wait is a 定点 the platform names, not one the seat picks. The three-step enqueue check was measured out: it is gated on 「ready + 全绿 ≠ 已入队」, and a 429 leaves the PR not ready at all. rest-channel.md was measured out: a per-operation channel table that already carries the route; what was missing is a landing STATE.
  • (c) The retired line is a provable duplicate — right, with named covers. SKILL.md :637 states the rule unconditionally and more strongly (「路径面干净的才转 ready → 入队;队列是唯一被认可的落地路径,⛔ 永不队列外合并。」); this file's own ceiling convention, quoted in the ratchet's CEILINGS comment for the 80 → 69 lowering, is 「no rule already stated in SKILL.md」. Inside the file the line's only work was bounding the two main-red exceptions above it, and each carries its own bound in its own text (:49 「限 p0、机械、根因已核实的止血 PR」, :50 「仅限 main-red 修复」). Nothing normative is lost. The seat's three SEEN candidates were measured and rejected with reasons (the two 确认 MERGED lines are different rules; the two subscription lines each carry content the other lacks).
  • (d) Premise — re-measured on the base. grep -n '429\|resets at' over SKILL.md and references/*.md returns six rows, none naming a landing state for the undraft route: the three fact rows, an unrelated rate-limit-window row, and two WRITE-budget rules (SKILL.md :99, filing-gate.md :29 — the claude[bot] token's pool, a different pool and a different act, which prescribe stopping writes and would push a seat toward reporting the landing as blocked). The gap was real and unclosed.
  • (e) Gates — measured by this seat on a clean worktree at 1dda953ea after pnpm install --frozen-lockfile --offline. check:pm-skill-ratchet (69 / 69; widest table row 0 / 0), check:pm-skill-id-lint, check:skill-frame-sync, check:pm-governed-prose, check:doc-authoring, check:nul-bytes, check-skills-token-ratchet — all exit 0; no raw control byte; check-governed-merges.mjs --pr 19717 exit 3 — GOVERNED, Tier S, .claude/** ×1, 2 lines. The dev's 17-family derivation reconciled --ran 17 / 17 / 0 NOT-MEASURED (four first-pass exit 3 prerequisites cleared by install and a locked build, re-run to 0) reads as reported; check:pm-governed-prose is in the dispatch's list but not in the derivation (scored in the artifact-roster block) — run anyway, exit 0. CI at this head: 26 latest-per-name check runs, Lint & Repo Gates in progress at the seat's read, the rest success or skipped.

② Semver level

None — no release. .claude/** is in no package's files[] (the dev measured 70 declaring manifests, zero naming .claude); skip-changeset is the correct carrier, written through label-write.mjs with read-back; documentation and size/xs are the labelers'.

③ Boundary flags

  • Tier S — the seat readies and enqueues on all green and --pair 0.
  • Report on the card parses (os-dev-report first line); mcp_calls 0; three REST writes plus two pushes, as budgeted; the trailer pair model-free per check:commit-card-trailers; ⛔ no body PATCH by the dev, and none needed by the seat (references/** only — no 席位意见 slot owed).
  • Bookkeeping noted by the dev: the dispatch prose said 22 open PRs' file lists were read and the claim said 21 — the claim's number is the reading at claim time (21 open PRs at 10:18Z); the dispatch text was drafted from the 10:14Z scan of 22. The dev re-verified H4 independently for the increment. Recorded here.
  • Out of scope, noted, not filed: SKILL.md :99 and filing-gate.md :29 carry 429 rules for the WRITE budget on the other token — correct as written, near neighbours of this gap.

Implemented-by: claude/issue-18743-undraft-429-named-wait-state
Reviewed-by: session_01Wnstp2kTth7sGXfr8fXypc

VERDICT: PASS


Generated by Claude Code

@huangyiirene
huangyiirene marked this pull request as ready for review September 22, 2026 11:12
@huangyiirene
huangyiirene added this pull request to the merge queue Sep 22, 2026
Merged via the queue into main with commit ce95164 Sep 22, 2026
32 checks passed
@huangyiirene
huangyiirene deleted the claude/issue-18743-undraft-429-named-wait-state branch September 22, 2026 11:35
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