tooling(pm): the partial-dispatch landing is a release — one SKILL.md rule, one report-only sweep row (H49) - #16040
Conversation
… rule, one report-only sweep row (H49) SKILL.md (認领 family, line-neutral 811/811): a PR that lands ONE item of a card carries `Refs #N (item k)` and never `Fixes`; its landing releases the card in the landed form — same write back to `pm:queue` (+ `pm:retriage` when a remaining item needs a re-lane or a split), assignee cleared, a `Release:` line naming the landed item and where the remaining items go; the remainder is re-claimed from the queue. Paid for by two folds in the 状态模型 prose (not-planned closure; the pin-consumer exemption). check-half-states.mjs: H49 (band `state`, report-only) — an open `pm:dispatched` + assigned card whose newest `Refs`-linked PR is MERGED while no `Release:` or `Claim:` on the thread is newer than that merge. `refsTargets` joins H7's extractors with H7's strictness; the PR side is H8's merged window plus the open listing; the thread is H2's read. Coverage pair, summary clause, registry band, 108 self-test cases (2427 → 2535, none dropped). Tidiness, same file: H24's remedy and H47's two legs now read `RELEASE_ACT_RULE`; the two docblocks that cited SKILL.md line numbers keep their quotes and drop the numbers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
|
ACCEPT — lands #16003 as ruled. Governed (mixed diff, What the seat verified, at head
Open question answered: A. The ruling asked for H7's strictness, and a lowercase Follow-ups graded: #16036 (H8's branch-name fallback reads a merged Implemented-by: os-dev executor, flight #16003, branch Generated by Claude Code |
维护者速读改了什么:PM 手册补两行规则:一张卡只落其中一项时,PR 写 为什么改:spec 席位交班实测:一天里两个席位各自即兴处理「只落了一项」的卡,其中一次把整张卡停在一个只有一项依赖的决定后面,余项白等。规则本身就是已落地的释放动作,只是没人写下「合入一项也算离手」。 风险与代价(含回滚):纯规则文字 + 一条报告态巡查行,不新增任何 API 读取;40 个派生门禁全绿,巡查自测 2427 → 2535,两块板实测 0 条新报告(今日没有卡处于这种形状,不是没读到)。与同在等你的 PR #15946 同改一个文件但不同区域,merge-tree 证明无冲突。回滚 = revert 一个 commit。 席位意见:建议批准。四轴:业务——实测两次即兴处理、一次处理错;长远——复用已落地的释放动作,不新造机制;防 AI 错——把「合入一项」这个以前无规则的时刻变成有明确写法、且机器能看见没照做的卡;创业阶段——不加行、不加抓取。 你要做的:批准并入队,或人工直合。一字:是/否。 Generated by Claude Code |
Fixes #16003
Two files, nothing else:
.claude/skills/pm-dispatch/SKILL.md(one rule, two lines, line-neutral) andscripts/pm/check-half-states.mjs(one report-only row, H49, plus the two tidiness items from #15899's flight). Governed (.claude/**hit): draft, human merge,skip-changeset— this diff publishes nothing from any package.The rule (SKILL.md, 认领 family, beside the release line)
A dispatch may cover ONE item of a card whose other items belong to another lane or a governed surface. Before today the state model had no transition for the moment that PR lands: the card stays open,
pm:dispatched, assigned, with no dev — and two seats improvised the exit in one shift, one of them parking a whole card behind a decision only one item depended on. The rule, quoted unbroken:Rules-only register, 111 and 118 bytes. Paid for by two folds in the 状态模型 prose, both semantically one rule already: the not-planned closure pair (「无机制可唤醒的卡 ⛔ 不 hold…;重开免费,维护者可否决」, 119 bytes) and the unreleased-upstream hold pair (「该 hold 评论预写唤醒后的派发形状;pin 消费的仓不适用…」, 120 bytes). No table row touched; the four-axis frame block and the 升级与决策 section are untouched.
Same-file caution, proved. PR #15946 (
3ba4752b31,claude/issue-15929-governing-text-step) edits SKILL.md at 712–733. This branch's hunks sit at 130, 146 and 466. Fetched into a ref this session owns and merged in memory at head023dd73f3e:One line of output — the merged tree's id — and no conflicting path listed.
The row (check-half-states.mjs, H49, band
state, report-only)An OPEN card carrying
pm:dispatchedwith a non-empty assignee (and nopm:queue) whose newestRefs-linked PR is MERGED while noRelease:orClaim:comment on the card is newer than that merge — a partial dispatch landed and the card still reads TAKEN; the release is owed. The finding names the PR and the item (Refs #N (item k); a bareRefs #Nfires too and says no item is named), quotes the partial-landing line andRELEASE_ACT_RULEunbroken, and states the remedy as one write:pm:dispatchedtopm:queue(addingpm:retriagewhen a remaining item needs a re-lane or a split), assignee cleared, theRelease:line naming the landed item and where the remaining items go; the remainder re-dispatched from the queue as a fresh claim.refsTargetsjoins H7'spartOfTargets/closingKeywordTargets, with H7's strictness: word-bound, whitespace then#, no colon, code-stripped on the body surface, fresh regex per call,Ref/Referencesdeliberately not read. It captures the(item k)annotation only when it directly follows the number.refsOnlyLinksForcounts a PR as aRefslink only when its body does NOT also deliver the card (Part of, closing keyword) — those are H8's, bound per card number as H7 binds.RefsPR on the card is the newest word and the row declines.latestMarkedComment— H47's resolution, reused. A marker whose stamp does not parse cannot be placed against a merge, so the row declines rather than accuse.commentCache, which H2's claim read fills for exactly this population (an assigned pm-tracked card), so the coverage pairpartialCandidates/partialJudgedis complete by construction; a shortfall is a thread H2 could not read.Refs-only merged PR whose head is not named for the card, H8 is silent and H49 fires (the gap this row closes). On a head named for the card both fire; after aClaim:newer than the merge H49 stands down while H8 cannot read the thread — filed as check-half-states: H8's branch-name fallback reads a mergedRefs #N (item k)PR on a card-named branch as a full delivery, so it prescribes droppingpm:dispatchedon a lawfully re-dispatched remainder #16036, not addressed here.The two tidiness items (same file)
RELEASE_ACT_RULE.selfTest's independentRELEASE_RULE_LINEstill pins all three (the existing unbroken-quote cases pass unchanged).RELEASE_COMMENT_MARKERdocblock and the H47 section comment, both 465 and 493) keep their quoted text and drop the numbers. Three citations of the same class elsewhere in the file were left alone per the ruling and are [finding] check-half-states.mjs still cites SKILL.md by line number in three places (headerline 109/line 465, selfTestline 465) after the two ruled docblocks dropped theirs #16037 (not addressed here).Verification — all readings at head
023dd73f3eSelf-test.
node scripts/pm/check-half-states.mjs --self-test: 2427 → 2535 cases pass. Case-name sets diffed: 0 names left, 108 arrived, none dropped. The self-test's ownPARTIAL_RULE_LINEis an independent transcription of the SKILL.md line, compared against the row's output rather than against the constant it pins.Ablation, on a throwaway copy placed in
scripts/pm/so every sibling resolves (the control proves the governed register loads), copy blob proved equal to the HEAD blob before each leg, each mutation confirmed on disk by grep counts of the injected marker and the deleted text, restore proved by blob hash:b5b98548ae…= HEAD blob)h49PartialLandingUnreleasedreturns null after its population check (marker 1 on the copy, 0 in the tree)findings.push([issue, 'H49', owed])line replaced (deleted text 0, marker 1)summaryClauseinvariants + 5 H49 summary casesTree file blob identical before and after the whole run (
b5b98548ae906e97327a191e6a799b45bd4eab49),git diff HEADempty, no copy left behind. No rebuild leg applies: node loads this.mjssource directly.Live sweeps, read-only, before (the merge-base blob
3161d0b325…extracted and hash-checked) and after, both boards:Per-family: objectstack H2 22 → 23 and H24 1 → 3; objectui H20 0 → 1 and H44 15 → 14 — drift between two sweeps minutes apart on live boards worked by parallel seats; every other family identical, H49 contributing nothing to either side. Zero is the expected reading, not a quiet row: no
pm:dispatched+ assigned card on either board has a mergedRefs-only PR inside H8's 8-day window that no laterClaim:orRelease:answers — and the coverage pair says every candidate had its thread in hand, as the docblock predicts from H2's read. The self-test carries the shapes.Gates.
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackwith no paths (the changed set derived by the tool from the merge base): 40 commands, identical to the explicit two-path derivation. All 40 run, every exit code captured before any pipe;--ranreconciles:40 derived, 40 run, 0 NOT-MEASURED, 0 UNRUN.check:pm-dispatch-gateswas run detached per its header and read to completion (1511 cases pass).check:doc-formula-expressionsfirst answered exit 3 PREREQUISITE NOT MET (@objectstack/formulanot built in a fresh worktree); after building@objectstack/formula...and@objectstack/lint...through the shared lock it ran and passed — measured, not skipped.check-skill-line-ratchet: self-test 155 cases; liveSKILL.md is 811 lines (ceiling 811; headroom 0),widest table row is 342 bytes (pin 342; headroom 0).check-skill-id-lint: 24 files clean.check-skill-frame-sync: 4 axes, binding sentence in both copies.check-governed-prose: 2 surfaces name all 5 registered governed surfaces.check-half-states --self-test: 2535 (2427 before, no case dropped).check-governed-merges --teston the file list: exit 3 GOVERNED —.claude/** ×1.pnpm lintthroughscripts/pm/os-verify-lock.shon slotissue-16003:VERDICT command-exit 0(57s hold). Not a narrowed run — the full farm.维护者速读(草稿)
一句话:给「一张卡只落了一项」这件事补一条状态转换规则,并让巡查机器能看见没走这条规则的卡。
业务背景:并行开发常常只做卡上的一项——其余项属于别的车道或受管面。以前 PR 合入后,卡仍然显示「已派发、有人认领」,但实际上没有人在做;同一天两个席位各自即兴处理,其中一次把整张卡停在一个只有一项依赖的决定后面,剩余项白等。
规则内容:只落一项的 PR 写
Refs #N (item k)、不写Fixes(GitHub 就不会关卡);合入即释放——同一笔写入把卡放回队列、清掉 assignee、留一行Release:点名已落项和余项去向;余项需要换车道或拆卡时加pm:retriage交分诊;余项从队列重新认领。文字与既有释放规则并列,行数不增。机器侧:巡查脚本新增一行只报告、不改标签的 H49——卡还显示「已派发、有人」,而它最新的
RefsPR 已合入、线程上没有更新的Release:或Claim:,就点名 PR 和已落项,提示欠一次释放。不新增任何 API 读取;今天两块板都读作 0 行,是因为还没有卡处于这种形状,不是没读到。风险与代价:规则文字压在既有行数上限内,靠折叠两行状态模型散文换来;巡查行是报告态,误报只会多一条提示、不会写标签。已顺手发现 H8 对同名分支上的
RefsPR 会再报一次(#16036,未在本 PR 处理)。席位意见:(留空)
🤖 Generated with Claude Code
https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
Generated by Claude Code
Generated by Claude Code