Repository navigation
fix(pm): H4 prose and the pm:blocked readings release a PR target on merge, never on close - #28031
Conversation
…merge, never on close After the unlock sweep learned that a `Blocked-by:` line can name a PR and that the PR releases on merged, three readers still spoke of a PR target as "closed": - `proseBlockerClause` (the H4 prose half) bucketed every `closed` candidate as a satisfied condition and told the seat a card parked on an abandoned (closed, unmerged) PR was due back in `pm:queue`. The resolver already marks such a row `unmerged: true`; the clause now keeps it in its own bucket, renders it `CLOSED UNMERGED`, never counts it among the expired, and says the target wants re-pointing. Nine pins cover a merged PR (released), an abandoned PR (withholds, no "due back"), and the mixed readings. - The pm-dispatch SKILL.md `pm:blocked` row said a target releases when #N closes; it now says a PR target releases on merge and a closed-unmerged one does not release (line-neutral, row at its byte ceiling). - platform-readings.md named `issue_read` + `merged_at` for the merge reading; the MCP issue read cannot tell a merge from an abandonment, so the line now names `pull_request_read` or the REST read (line-neutral). Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4d17R6AtQwLrxguoYs1
|
domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS Contract-review-claim: session_016WV4d1QkPVVzNz3FJqb2iS · head 45763c7 · 2026-10-30T09:21Z |
|
domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS Contract reviewServed-tier: ① Derived judgmentsBase is
② Semver levelNo published package is touched ( ③ Boundary flags
④ Design judgmentRules face, per
Implemented-by: VERDICT: PASS Must-fix: none. Should-fix:
|
|
domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS 维护者速读
席位意见:ACCEPT。契约复核 PASS,没有 must-fix。复核亲自做了两条消融,都按预期变红,复原后 diff 为空:
should-fix 1、2、4、5 都只是措辞,不影响判定,转到跟进卡 #28033。这四处还把 PR 目标说成「关闭」:
should-fix 3(给 席位核对
|
Requested by Elon · project thread
Fixes #27989
Clause-②: no
Metadata-protocol: none
维护者速读
Blocked-by:目标是 PR 时,三处读器从「关闭即放」改为「合并才放」:H4 散文半边把「关而未合并」单独成桶、渲染CLOSED UNMERGED、不再说「due back in pm:queue」;SKILL.md 的pm:blocked行改为「关单(PR 则合并,关而未合并不放)时放回」;platform-readings.md 改为 PR 判合并走pull_request_read/REST,不再点名issue_read。unmerged: true,但 H4 散文子句仍按state === 'closed'分桶,把卡在废弃 PR 上的卡报成「条件已满足、该回队」;MCPissue_read实测分不出合并与废弃(记录 6516593752)。scripts/pm/check-half-states.mjsproseBlockerClause(新 docblock 段落与abandoned桶)→ 9 个H4 prose PR:钉子 → 两行规则文本 diff。node scripts/pm/check-half-states.mjs --self-test && pnpm check:pm-skill-ratchet && pnpm check:pm-skill-id-lint,预期全绿。GOVERNED_SURFACES登记为准(--branch预读:Tier S,.claude/**×2),席位落地。What changes
After the unlock sweep learned that a
Blocked-by:line can name a PR, and that a PR target releases on merged, three readers still spoke of a PR target as "closed". Card items 1–3; items 4 and 5 are read below.Item 1 —
proseBlockerClause(H4 prose half),scripts/pm/check-half-states.mjs. The resolverblockerResolutionFromRowalready keepsstate: 'closed'for an abandoned PR and marks itunmerged: true, but the clause bucketed everyclosedrow as a satisfied condition and told the seat the card was "due back inpm:queue" — for a prose-named PR that closed without merging, a release that never happened. Now:namedProseCandidatesrenders such a row as`#N` CLOSED UNMERGED (closed_at).abandonedbucket. A merged PR (closed, no mark) still reads "ALREADY CLOSED … due back inpm:queue" — the released direction is unchanged. All-abandoned reads "closed UNMERGED — an abandoned attempt releases nothing … the block still stands; the target wants re-pointing". Mixed readings count only merges/issue closes as expired, and an abandoned close beside an open target no longer claims "They all still read OPEN".H4 prose PR:pins drive the measuredGET /issues/Nshapes (fix(rest): a refused xlsx export answers the 400 envelope, not a 200 workbook stream #27888 merged, pm:mailbox — sunhaolin #27296 closed unmerged, the same rows H19's battery pins) through the sweep's own projection into the clause. Report-only: H4 writes no label, and the clause still ends with "fix it by writing theBlocked-by: #Nline".Item 2 —
.claude/skills/pm-dispatch/SKILL.md, thepm:blockedstatus row. 「#N 关闭时由解锁扫描或scheduled-full-run-card.yml刷新放回」 → 「#N 关单(PR 则合并,关而未合并不放)时由解锁扫描或scheduled-full-run-card.yml放回」, agreeing withstate-machine.md「合并才放,关而未合并 ⛔ 不放」. In-row, 319 lines kept. The row sits at the file'sMAX_TABLE_ROW_BYTESceiling (341), so three words were tightened in the same row to pay for the new clause: 「刷新放回」→「放回」, 「工已完、PR 被外部门禁卡住的」→「工已完而被门禁卡住的」, 「正文或线程行首」→「双通道行首」 (the term the hold/blocked line below already uses), 「挂本态直至其」→「直至其」. No rule was dropped.Item 3 —
.claude/skills/pm-dispatch/references/platform-readings.md. The unlock-scan line namedissue_read+merged_at; measurement 6516593752 shows MCPissue_readon a PR number answersstate: "closed"with nopull_requestkey, so it cannot tell a merge from an abandonment. The line now reads 「解锁扫描list_issues列卡、逐目标直读,⛔ 不加常设评论读;PR 合并走pull_request_read/REST。」 — exactly 120 bytes, theMAX_LINE_BYTESceiling, which is why the REST read is named without itsmerged_atfield andissue_readis excluded by omission rather than by a ⛔ clause. 458 lines kept.Item 4 — read, not edited. Triage 6516946612 rules: no new gate; triage's
unlockscan already lists a closed-unmerged PR target as not released; at most thepm:blockedrow says so. The row now says 「关而未合并不放」;state-machine.mdis untouched and H26 is not extended.Item 5 — H28 wording. Not touched: the diff does not reach H28.
Verification
node scripts/pm/check-half-states.mjs --self-test→ 5098 cases pass (was 5089).git diffempty): (A) theclosedbucket counts unmerged rows again → 6 of the new pins red; (B) the render drops theUNMERGEDword → 1 red; (C) the all-abandoned branch removed → 1 red. The two merged-PR pins pin the direction that was already right and are not reachable by an ablation of this diff.pnpm check:pm-skill-id-lint→ 105 files clean.pnpm check:pm-skill-ratchet→ green (SKILL.md row 341/341, platform-readings line 120/120).node scripts/check-skills-token-ratchet.mjs→ green.node scripts/pm/dispatch-gates.mjs --commands --changed: 58 commands, all run serially on the committed head 45763c7 in a fresh worktree afterpnpm install --frozen-lockfile --ignore-scriptsand the@objectstack/lint...build, each exit code captured before any pipe; all 58 exit 0;dispatch-gates --ranreconciliation: 58 derived, 58 run, 0 NOT-MEASURED, 0 UNRUN (exit 0); the derivation recomputed after the commit is the same 58.node scripts/pm/check-governed-merges.mjs --branch claude/project-thread-vo8914→ governed.claude/**×2, Tier S;scripts/pm/check-half-states.mjsnot on the register.pr_create不请不派」; the hand-off is the seat's after ACCEPT.Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses on the touched script.main, one pull request.skip-changeset)packages/spectouched: its generated artifacts are regenerated and committed. (not touched)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4d17R6AtQwLrxguoYs1