Repository navigation
pm-dispatch(sign-off): a seat going off shift hands every unlanded claimed card back to pm:queue in one stroke; a needs_decision card goes to the decision box; stay-behind narrows to ACCEPTed PRs waiting on the queue or a human - #27371
Conversation
… back to pm:queue Stay-behind stops being the default at shift end. The default is the hand-back stroke of the handover checklist's step 2 (Release: with Resume-from:, the assignee cleared, back to pm:queue); a needs_decision card goes to the decision box instead. Stay-behind narrows to ACCEPTed PRs waiting on the merge queue or a human approval, and the sign-off sequence runs whatever words the maintainer used to end the shift. Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg Co-authored-by: Claude <noreply@anthropic.com>
…hat waits; a held needs_decision card is refused by name The sign-off hand-back rule narrows the declared stay-behind: (a) now reports a declared tail only when an open pull delivering the card carries an ACCEPT as its newest seat record and waits on the merge queue (timeline), armed auto-merge, or a human approval (the PR's needs-user-decision label). A card whose dev's newest os-dev-report, newer than the claim, says needs_decision while the card is not in the decision box is refused as [needs-decision-unreleased], with the decision box as the remedy rather than pm:queue. Readers are imported from their owners (check-half-states, seat-record, the queue guard). Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg Co-authored-by: Claude <noreply@anthropic.com>
|
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg Contract-review-claim: session_01QSeKYmhU5KEj1nukYhp1Tg · head d457c56 · 2026-10-29T04:05Z |
|
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg Contract reviewServed-tier: Claim line 6487607811 on this head (2026-10-29T04:07Z); no earlier record or claim on it. Read at 2026-10-29T04:07Z by the ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: PASS |
|
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg 维护者速读 — 席位终稿 · PR #27371 · head
|
Fixes #27359
Clause-②: no
Metadata-protocol: none
维护者速读
pm:queue(Release:+Resume-from:+ 清 assignee);dev 报了needs_decision的卡改进决策箱;留守只剩已 ACCEPT、正在等合并队列或等人批的 PR。check-handover.mjs同步收窄:声明留守的卡必须有已 ACCEPT 且在等的 PR,dev 报needs_decision却还挂pm:dispatched的卡点名拒收。pm:dispatched没人跑,其中一张的待裁问题根本没到你手里,别的席位只能强制接管。scripts/pm/check-handover.mjs的handoverVerdict与acceptedPullWait(收窄逻辑);seat-post-protocol.md〈活性、写侧刷新与收班〉新第 35–36 行与〈交接收尾清单〉第 2 步;seat-lifecycle.md第 40、43 行。node scripts/pm/check-handover.mjs --self-test,应看到✓ check-handover self-test: 66 cases pass。.claude/**为 Tier S,席位达档复核后落地)。What changes
The maintainer's rule, verbatim: 「下班时卡片应该交回队列,这个应该立卡更新 skills」. The card's items 1–4 are the spec.
Protocol text (both files stay at their line ceilings, every line at most 120 bytes):
check-handover.mjs退出 0 → 刷正文与标题 → 简报最终一笔。Release:与清 assignee 同笔释放,转成真实状态。Release:+Resume-from:+清 assignee 交回pm:queue;needs_decision进决策箱。Bytes are the full source line, list marker included (the gate's measure); the table shows the text after the marker. Line counts: seat-post-protocol.md 88 → 88 (ceiling 88), seat-lifecycle.md 96 → 96 (ceiling 96). The new L36 is paid by deleting old L40, whose content moved into L35/L36. One clause leaves old L38: 「继任的释放判据 = 简报在」. Its home is seat-lifecycle.md 〈开轮互斥〉: 「收班简报是前任不再写的显式声明,是释放标记不是锁:简报即最新事件 ⇒ 立即坐席。」
Release:,Resume-from:, the assignee cleared, and the card back topm:queue.needs_decisioncard goes to the decision box, ⛔ notpm:queue): checklist step 2, and the new check below.check-handover.mjsrun are the last acts, whatever words end the shift): L39.scripts/pm/check-handover.mjs(a local refusal tool; no workflow runs it):[needs-decision-unreleased]. A held card is refused by this name when its newestos-dev-reportis newer than the claim and declares"status": "needs_decision", and the card is notneeds-user-decision. The remedy names the decision box, ⛔ notpm:queue. It is refused even when the card is declared as a stay-behind.--stay-behindand declared on the vacant body is reported as[stay-behind]only when an open pull that delivers it meets two conditions. First, the pull's newest## 席位核对record is an ACCEPT. Second, the pull waits: it is in the merge queue (newest queue event on its timeline is the add), auto-merge is armed, or it awaits a human approval (needs-user-decisionon the pull). Otherwise the card stays[claim-unreleased], and the refusal names the failed condition for each pull.latestDevReport/devReportPayloadCandidates/deliveryEvidencecome fromcheck-half-states.mjs,SEAT_RECORD_MARKER/seatRecordAcceptsfromseat-record.mjs, andenqueuerFromTimelinefromcheck-governed-queue-guard.mjs. The only new reading is the report'sstatusfield.auto_mergedid not answer. Every request is a GET.Tests
node scripts/pm/check-handover.mjs --self-test: 46 → 66 cases, all pass (handshake intact). Changed rows: ARM 1 now requires a waiting ACCEPTed pull, and the decision-not-excused row uses a waiting tail so it still isolates the decision refusal. New rows cover the narrowing (not-waiting, unread), (a′) (measured shape, older-than-claim, newest-decides, already-in-inbox, refused-by-name),acceptedPullWait(queue, approval label, armed, needs-timeline, dequeued, no-accept, REWORK-after-ACCEPT, ACCEPT-after-REWORK), the shortfall text, delivery evidence, and two structural pins.Ablation, four legs through scripts/ablation-replace.mjs, each restored and hash-proven (HEAD d457c56, blob 2557438f5d42)
else if (twice && h.wait)changed toelse if (twice). 2 of 66 failed:SIGN-OFF NARROWING,absence never reads as waiting.needs_decisionstatus test changed toreturn null. 1 of 66 failed:(a′) THE MEASURED SHAPE.a REWORK newer than the ACCEPT, is no ACCEPT.if (true). 1 of 66 failed:the newest queue event is a removal, or there is none.git diff HEADis empty. The unmutated control run: 66 cases pass.Live reads (GET only, this container)
--probe: transport prerequisite met.domain:serverseat (session_01R1q2xdtYgU6FKrZ7LgjPCC,os-sales, since 2026-10-27): exit 0, clear. The measured instance has moved on. validate/lint/build refuse a lookup or record_change trigger to an object provided by a package in manifest.dependencies — the publish gate already resolves that closure #25805 is nowneeds-user-decision, and test budget (domain:cli): 119 test file(s) over 10 s of wall in the hourly full battery (Part of #23151) #23181's newest claim names another session, so it is listed, not refused.--stay-behind=#27359and a vacant probe body: exit 2. pm-dispatch(sign-off): a seat going off shift hands every unlanded claimed card back to pm:queue, instead of keeping it as stay-behind #27359 was refused with "declared a stay-behind on both, but no open pull request delivers it". Coverage:(c) 1 declared stay-behind card(s): 14 open pull(s) listed.Acceptance notes
落地中的评审链载体leaves the stay-behind write surface. Card item 3 narrows stay-behind to ACCEPTed PRs only.pm:queue, or the decision box forneeds_decision. Step 4 still carriespm:blocked+Blocked-by:/Restart-when:for ledger obligations.pm:queuewhile its dev's question is open leaves that population, and H52 (open questions unrouted) still reports it.enqueuerFromTimeline. An add event whose actor has no login reads as not queued, which is the refusing direction.(c)between(a)and(b), because the stay-behind reads follow the held-card reads. Cosmetic only.os-dev.mdon main still says to send one.Verification
Final head
d457c56d. Derivation:node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackgives 36 commands. All 36 exited 0 locally.check:doc-formula-expressionsfirst exited 3 (PREREQUISITE NOT MET:@objectstack/lintwas not built). It exited 0 afterturbo run build --filter=@objectstack/formula --filter=@objectstack/lintunder the verify lock.--ranreconciliation:36 derived famil(ies) accounted for — 36 run, 0 NOT-MEASURED (a DERIVED zero — all 36 recorded an exit code and none of them is 3).Gate readings
pnpm check:pm-skill-ratchet: seat-post-protocol.md is 88 lines (ceiling 88; headroom 0). seat-lifecycle.md is 96 lines (ceiling 96; headroom 0). Self-test: 164 cases pass.pnpm check:pm-skill-id-lint: 105 file(s) clean.pnpm check:pm-post-stamped: 735 cases pass across 26 batteries. Its self-test readscheck-handover.mjs'scarriesFacetMarker, which is unchanged.pnpm check:doc-authoring,pnpm check:nul-bytes,node scripts/check-self-test-wired.mjs(+--self-test),pnpm check:pm-governed-merges,pnpm check:skill-frame-sync, and the remaining 26 derived commands: exit 0.pnpm exec eslint --no-inline-config scripts/pm/check-handover.mjs: exit 0.check:pm-governed-proseandcheck:pm-half-statesare not derived for this diff, so they did not run locally; CI runs the lint farm.Generated by Claude Code