Skip to content

finding(pm): pm:queue 半态「已判未转」——两条可机判的 H 规则,加 #11086 的一条输入 #11179

Closed

Description

@os-zhuang

Finding,只记录不认领(维护者 2026-08-23 口头采纳立卡建议;记录席位 session 757f0dc0-5dae-51d7-9053-c15c57ebfe3b)。

事故

另一 PM 席位把 #10534 / #10746 / #10556 挂在 pm:queue 长期不处理。维护者点破后,该席位自查结论:技能原文清楚,是执行没跟上,至少四处违规——

技能原文 实际做的
「挂 needs-user-decision、退出活动队列」 贴了分析,留在 pm:queue
「状态转换同笔……永不留挂」 正是留挂
前提刷新:「零命中/变形的就地改写或撤卡」 只加注解,没改也没撤
pm:queue 定义「无可问之事」 #10556 带两个未决设计问题入队

外加 #10534 咬到的鲜度门:「录前重读晚于正文最后编辑的评论,有修正的先调和正文」没执行。

判读

四条违规同一签名:判断做了(有分析产出),状态写入没做(纯开销的那半)。长上下文席位注意力衰减最先丢的就是两段式义务的后半段——这不是"技能写得不清楚",是散文规则在长会话里的可预测衰减。本仓已有的结论一贯如此:活下来的规则都是有门的规则(worktree/stash hooks、check-half-states.mjs、各 ratchet)。

提案:进 scripts/pm/check-half-states.mjs 的两条新 H 规则

  1. 矛盾态:卡同时挂 pm:queue 与 needs-user-decision(或等价未决标记)= 红。pm:queue 的定义就是「无可问之事」,共现即违反定义,机器可判。
  2. 腐烂告警:pm:queue 卡零活动超过 N 天 = 点名,不判对错,只逼出一次显式转换(派发 / 转 needs-user-decision / 撤卡 / 改写)。

第三条(鲜度门)机判不了意图但可判事实:结论型评论时间戳早于卡正文最后编辑时间戳 → 提示需重新调和;可作 warning 级,不作 red。

不做的事

不往 .claude/skills/pm-dispatch/SKILL.md 加散文(682/682 零余量,且散文正是刚失效的手段)。「散文规则 → 机器门」的整体审视喂进已裁决待触发的 #11086 全文重构轮,本卡只落上面可机判的规则。

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    domain:skillsDomain lane — seat card indexed by label:pm:seat
    on Aug 24, 2026
  2. os-zhuang commented on Aug 24, 2026

    @os-zhuang
    ContributorAuthor

    Promoted to pm:queue + scope expanded with today's measured instances (skills seat, session 5213b871-5164-5bc3-8874-28b336bbcd40, self-triaged under the skills-lane exception; authorization: maintainer 2026-08-24, live PM chat — the half-state batch report plus verbatim 「以上问题要排查skills原因」).

    The maintainer's sweep surfaced four half-state CLASSES in one afternoon. Each has a protocol root cause, and this card is the vehicle for the machine-checkable rules that close them:

    1. Dual-hang pm:queue+pm:blocked (Retire the nine dead members of the plugin-manifest contributes block (events/menus/themes/translations/actions/drivers/fieldTypes/functions/commands) — tombstone route, kinds survives #10724, sat 3 days) — the unlock/park transitions are two independent label writes with no exclusivity invariant. Rule: the pm-state labels (pm:queue/pm:dispatched/pm:blocked/pm:on-hold) are MUTUALLY EXCLUSIVE; a patrol row flags any card carrying two, and every transition in the skill text is worded as replace-not-add.
    2. Assigned-but-pm:queue (7 instances: [Epic] Migrate SCIM from @better-auth/scim 1.7.0-rc.1 to stable 1.7.x — seven-model provision, sys_scim_provider disposition, token reissue coordination, net-new Setup surface #11632, pm-dispatch: unlock scan must distinguish "upstream merged" from "consumer can install" — release-gated cross-repo unblocks go pm:on-hold with a Restart-when, not back to queue #11498-post-close, objectui bug(platform-objects): 超预算后台 seed 时,空库自证仍可能签在尾部数据落定之前 —— 首启一次启动两套契约 #4795/fix(sharing)!: give the share-management surface the authorization layer it never had (ADR-0111 P0, #3902) #3965/fix(plugin-sharing): 记录删除后 sys_share_link 令牌立即失效 —— resolve 存在性校验 + 删除级联 (#5190) #5214/fix(plugin-auth): 每号码 OTP 发送预算改用惰性解析的共享计数存储 —— 多节点下不再按节点数倍增 (#4790) #4806/✅ spec 双源清账主单:基线 52 → 0(2026-08-03 收官)—— #4446 gate 落地后的偿还 worklist #4535) — three distinct sub-causes, measured today: (a) an epic owner decomposing without flipping ([Epic] Migrate SCIM from @better-auth/scim 1.7.0-rc.1 to stable 1.7.x — seven-model provision, sys_scim_provider disposition, token reissue coordination, net-new Setup surface #11632); (b) assignee residue from the 2026-08-24 identity incident and from filer self-assign, with the claim protocol saying "comments are the arbiter" but NOTHING instructing residue cleanup; (c) decision-shaped cards mislabeled pm:queue when their own bodies demand a ruling (bug(platform-objects): 超预算后台 seed 时,空库自证仍可能签在尾部数据落定之前 —— 首启一次启动两套契约 #4795 「需裁决」, fix(plugin-auth): 每号码 OTP 发送预算改用惰性解析的共享计数存储 —— 多节点下不再按节点数倍增 (#4790) #4806 「本条不带 pm:queue 的原因」 — the card text and the label directly contradicting). Rules: assignee⊕pm:queue is a flagged pair unless a fresh claim comment exists; first-touch grading must check label-vs-body-disposition agreement.
    3. needs:contract-review lingering after PASS ([Decision] Does react-blocks.ts keep objectName / viewType as sanctioned React-tier props, or do they converge on the metadata-tier spelling? — the carrier objectui#2890's last phase has never had #11284 card-side, this seat's own miss today: verdict posted, PR cleared, card write skipped) — the dual-carrier clear is two writes with read-back required per carrier, but the checklist doesn't enumerate the carriers as a PAIRED postcondition. Rule for references/contract-review.md: a PASS is complete only when BOTH carriers read back clear in the same stroke; a patrol row flags a card whose latest review comment says PASS while the label survives on either carrier. Companion rule: needs:contract-review on a card with NO open PR carrier (Should a definition-level input-schema refusal be non-retryable? #9889's parity floor makes a flow burn its whole retry budget on a verdict that cannot change #10025, standing noise for days) is premature — the gate label hangs at PR-open time, not at ruling-request time.
    4. Stale pm:blocking derivations (A failing turbo run test task can land in Test Core with ZERO captured output, and the completeness guard's green does not cover a package that printed nothing #10032 pointing at a 404'd dependent; Migrate the release toolchain to @changesets/cli v3 — one atomic PR carrying the bump, the pre-mode restructure, and the gates that model v2's semantics #9465 with all dependents closed) — H14 derives additively but never retires. Rule: the derivation is a two-way sync — recompute the dependent set each patrol and STRIP when it is empty or every named dependent is closed/404.

    The original card's two H-rules plus these four make one coherent deliverable: a scripts/pm/ patrol extension (report-only first, per the H21 precedent) + the matching one-line transition wordings in the skill text. Governed surface ⇒ draft PR, human merge; the patrol script half is ungoverned.


    Generated by Claude Code

  3. added
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    pm:queueReady for the PM dispatch loop
    on Aug 24, 2026
  4. self-assigned this
    on Aug 24, 2026
  5. os-zhuang commented on Aug 24, 2026

    @os-zhuang
    ContributorAuthor

    Claim (twin of the fold claim on #11747, same stroke): skills seat dispatch, session session_01RMTpSRF5CjMmQBFfPtPCwJ, branch claude/issue-11747-unlock-scan-overhaul — FOLDED into #11747's patrol PR per that charter's deliverable 4 (one patrol PR, two rule families, separately named acceptance). This card's H-rules (the queue↔dispatched half-state machine-judgeable rows, plus the #11086 input) land as their own rule family in that PR; this card closes via its own Fixes line there.


    Generated by Claude Code

  6. os-zhuang commented on Aug 24, 2026

    @os-zhuang
    ContributorAuthor

    Unfolded from #11747 (skills seat, session session_01RMTpSRF5CjMmQBFfPtPCwJ, superseding the fold claim above — ruling recorded on #11747 comment thread): the fold's one-file-surface rationale died with #11747's re-charter, and this card's rules do not depend on that diagnosis. Re-dispatching STANDALONE.


    Generated by Claude Code

  7. os-zhuang commented on Aug 24, 2026

    @os-zhuang
    ContributorAuthor

    os-dev-report

    {
      "issue": 11179,
      "status": "done",
      "branch": "claude/issue-11179-half-state-rules",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/11884",
      "premise_still_valid": true,
      "summary": "Inventory re-verified against origin/main (4019e16c) FIRST, as ordered; the re-dispatch's corrected inventory holds and two more families collapse under it. LANDED (one file, scripts/pm/check-half-states.mjs): H29, the GENERAL pm-state ONE-OF — H3 and H25 each pin one carrier, leaving 11 of the vocabulary's 15 pairs with no reader, including both pairs this card was filed on; it reports only the pairs no other row owns (H3's pair and every awaiting pair excluded, each pinned silent-here + fires-there), names both CLAIMS rather than both labels, and derives its vocabulary from H25's list so the two cannot drift. H30, pm:queue rot at a 3-day horizon derived from a live measurement rather than copied from H11 (see tests). H31, the contract-review dual-carrier comparison, both directions, free (the open-PR listing and prDeliversCard are already in hand). All three report-only; no label is ever written from the script. NOT LANDED, each with evidence: (a) H14's strip-when-empty is ALREADY SHIPPED — its stale direction is `carries && dependents.length === 0` and buildBlockingIndex is built from the OPEN listing, so a closed-or-404 dependent contributes no edge and lands in that branch by construction; the shipped row is better calibrated than the proposal (suspended on an incomplete index, states its repo-local boundary). (b) The FRESHNESS row is not machine-judgeable on this transport and the file already says so: an issue's body-edit time is on no REST payload at all (GraphQL userContentEdits only; the timeline does not carry it), and the one proxy in reach, updated_at, bumps when a comment is POSTED — so the check would read nothing while looking like it read. No code written on a guess; it comes back as open question 1. (c) The companion 'gate label on a card with no PR carrier is premature' rule is REFUSED — references/contract-review.md makes card-side-first the prescribed sequence, so that row would report correct behaviour as a defect; live card #10025 is pinned as a CLEAN case for it. Also NOT touched: references/state-machine.md, zero lines — it is at ceiling 43/43 and every line still consolidatable sits inside PR #11874's in-flight hunks, so paying for a row there would have guaranteed the conflict this dispatch said to avoid (argued in the PR body; the file already names check-half-states.mjs as the enforcement authority).",
      "tests": "All at branch head `b83214bf` — the gate union below was run on that same tree (`git rev-parse --short HEAD` = b83214bf), and no commit followed it. Exit codes captured before any pipe (redirect-then-capture) throughout; every result quotes the gate's OWN verdict line, never a bare $?. SELF-TEST: `bash scripts/pm/os-verify-lock.sh -c 'node scripts/pm/check-half-states.mjs --self-test'` => its own lines '✓ check-half-states self-test: 1149 cases pass.' and 'os-verify-lock: VERDICT command-exit 0 · held the lock 0s · waited 0s' — 1058 -> 1149, +91 cases. LIVE-BOARD MEASUREMENT behind H30's horizon (read-only, MCP list_issues over all 40 open pm:queue cards, 2026-08-24T22:40Z): idle >1d 17 · >2d 10 · >3d 8 · >4d 4 · >5d 3 · >7d 0. H11's 7d would fire on NOTHING (a check that cannot fail — the shape this file exists to catch); 1d reports 43% of the queue, i.e. depth not rot; 3d names 8 of 40 and still exceeds the measured 3-day dual-hang. Five of those live rows are pinned as fixtures (#9997/#7251/#10735 fire, #11150/#11852 clean). LIVE SPECIMENS pinned for the other two rows: #11534 (needs-user-decision + pm:blocked) for H29 — a THIRD pair, in a third direction, which is the argument for asking the invariant rather than pinning pairs; and card #11427 gated while its delivering draft PR #11844 carries documentation/size/l/dependencies/tests/tooling and NOT the gate, for H31. ABLATIONS — three, each anchored on the exact text intended to change, each in a script carrying an EXIT/INT/TERM trap that restores the file, each with the mutation PROVEN ON DISK by grepping the injected AND the deleted text separately (never an editor exit code, never a bare `git diff --stat`), and each restore verified byte-identical with `cmp` against the pre-mutation copy plus a residual-marker count of 0. No build/dist leg applies: a plain .mjs the self-test imports from source, so there is nothing to rebuild and nothing to preflight in a dist/. (1) H29's pair collection neutered ('if (pairs.length === 0) return null;' -> 'if (true) return null;'): injected 1 / deleted 0 on disk, MUTATED-EXIT=1, verdict '✗ check-half-states self-test: 15 of 1149 case(s) failed.' — RED, as predicted. (3) H31's bare-carrier filter neutered (barePrs -> []): injected 1 / deleted 0, MUTATED-EXIT=1, '✗ … 11 of 1149 case(s) failed.' — RED. ⚠️ (2) H31's card-side-first early return removed ('delivering.length === 0' -> 'if (false)'): injected 1, MUTATED-EXIT=0 — GREEN, and reported as OBSERVED rather than templated. It is a real measurement, not a failed run: both reporting branches independently require a non-empty PR set, so that silence is over-determined and the early return is documentary rather than load-bearing today. The line stays (it states the protocol rule where a future third branch would otherwise violate it) and ablation 3 was run against a predicate that IS load-bearing. ⚠️ ONE HONEST CORRECTION TO MY OWN PROOF: ablation 2's first on-disk 'deleted' count reported 1 after a successful mutation, because H8 carries the byte-identical line 'if (delivering.length === 0) return null;' — that grep was not anchored tightly enough to be evidence. What actually proved uniqueness was the mutation script's own `assert s.count(old) == 1` against the full line INCLUDING its trailing comment; ablation 3's proof is anchored on text unique to its target. ASSERTION SHAPE: the observation recorded on #11874's report is honoured — every message assertion in the new blocks goes through a helper that checks `typeof` FIRST and returns a describing string, so a null-return regression fails as named cases ('got \"NO MESSAGE (null)\", want true' on 20 of the 26 failing rows across ablations 1 and 3) instead of crashing at the first assertion. The existing H26 block was NOT restructured, per the dispatch. COMPOSITION, MEASURED not asserted: `git merge-tree` of this branch against origin/claude/issue-11747-unlock-scan-overhaul reports 0 conflict markers, and against the current origin/main (e75e3438, three commits past the derivation base, none touching this file) likewise 0.",
      "gates": "Derived with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` (NO path args — the script took its own change set from the merge base), exit captured directly = 0. Its own lines: \"gate list derived from the tree of 'objectstack-ai/objectstack' at commit b83214bf\" / \"--repo 'objectstack-ai/objectstack' checked against this checkout's 'origin' remote — it holds.\" / \"change set derived from git — 1 path(s) vs merge base 4019e16cd of 'origin/main' and HEAD (committed 1, working tree 0, untracked 0; three-dot semantics)\", naming exactly scripts/pm/check-half-states.mjs. 11 families matched out of 157 discovered; 10 are locally runnable and ALL 10 are green at b83214bf. Each family's own verdict line: check:pm-half-states => '✓ check-half-states self-test: 1149 cases pass.'; check:agent-test-spelling => '✓ check-agent-test-spelling: 0 violations — 357 file(s) · 3459 bare -- token(s) · 1109 launcher-rooted run(s) · 8 separator(s) JUDGED'; check:cross-package-test-inputs and its node form => 'OK: 16 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.'; check:entry-guard => '✓ check:entry-guard: 148 scripts/ file(s) — every entry guard goes through invoked-as.mjs; 105 export bindings, 95 of them inert on import'; check:parse-guard => '✓ check:parse-guard: 147 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.'; check:partof-closing-keyword => '✓ check-partof-closing-keyword self-test: 28 cases pass.'; check-closing-keyword-parity => 'check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 6619 tracked file(s), all registered).'; check:pnpm-filter-targets => '✓ check:pnpm-filter-targets: 135/168 --filter occurrence(s) across 26 file(s) resolve against 78 workspace package(s)'. The 11th matched row is `node scripts/pm/check-half-states.mjs` under half-state-patrol.yml — the LIVE network sweep, not a local gate; its offline half is check:pm-half-states above. Invoking scripts/check-partof-closing-keyword.mjs directly first printed its own 'check:partof-closing-keyword: NOT WIRED — neither PR_BODY nor PR_NUMBER is set … This is a wiring or usage failure, NOT a verdict' — NOT a finding, and it is green when handed the real body: '✓ check:partof-closing-keyword: this PR carries no Part-of/closing-keyword contradiction.' check:nul-bytes was run on the standing clause even though the derivation did not name it => 'check-nul-bytes: OK (scanned 6614 text file(s) -- 6614 tracked, 0 untracked-not-ignored; skipped 5 binary; no raw ASCII control bytes).' plus a manual control-byte scan of the PR body (no match). The body's closing-keyword parse, run through the file's own closingKeywordTargets, returns exactly one target: [['11179','Fixes']]. `skip-changeset` written through the ADDITIVE endpoint (POST /issues/11884/labels => HTTP 200) and READ BACK after the bots settled: ['size/l','skip-changeset'] — it survived the size-labeler's group PUT. PR body read back byte-checked: draft true, session-URL footer intact, no sanitizer mangling.",
      "deviations": "Four, all declared, none silent. (1) NO REPO-WIDE `pnpm lint` RUN — a DECLARED NARROWING, not a measured one: the derivation placed 11 families for this path and every locally runnable one was run, but I did not additionally run the whole-repo eslint pass and I am NOT claiming the three-part narrowing proof. CI runs the farm regardless; PM reviews CI convergence. (2) NO `references/state-machine.md` EDIT AT ALL, and no header-catalogue entry inside the script. Both are ceiling/anchor decisions argued in the PR body rather than omissions: the doc file is at 43/43 and every consolidatable line sits inside #11874's in-flight hunks, and the script's catalogue anchor is where #11874's H28 entry goes. The catalogue skip follows the existing precedent that H21, H22 and H23 have no entry either; every new row carries its full rationale at the predicate site as H24–H27 do. If the reviewer wants the doc rows anyway, they should land AFTER #11874 merges, as a follow-up that can pay from a purse that is no longer contested. (3) Ablation 2 came out GREEN and is reported as observed rather than forced into the template, with the over-determination explained and a third ablation run against a load-bearing predicate — see `tests`. (4) `pnpm install --frozen-lockfile` was run in the fresh worktree (needed by check-closing-keyword-parity's `yaml` dependency); the gate said in its own text that it had measured nothing, so it was never read as a finding. Heavy work serialized through scripts/pm/os-verify-lock.sh (longest hold 22s). CI convergence is NOT awaited, per the standing contract. Governed surface: draft only, NOT flipped ready, auto-merge not armed, no board write on any card — no assignee touched, no label written anywhere except the PR's own skip-changeset and this report comment. Worktree removed without --force after `rm -rf node_modules`.",
      "open_questions": [
        {
          "question": "The freshness family (this card's third proposed rule) cannot be judged on this file's transport: an issue's BODY-EDIT time is on no REST payload — the issues API carries created_at/updated_at only, body edit history lives behind GraphQL userContentEdits, and the timeline endpoint does not record body edits. The file already carries this measurement in the `Blocked-by:` channel's 'Stated boundary' note, where the same cut-off was refused for the same reason. What should the freshness duty become?",
          "options": [
            "A. Record the measurement and leave freshness with the SEAT protocol (the read-closure rule 「只读晚于正文最后编辑时间的评论」 stays a human/seat duty, unmechanized), with no patrol row. Zero code, zero cost, and it is honest about what this transport can see.",
            "B. Move ONE row of this file onto GraphQL to read `userContentEdits` for the candidate cards. It would make the fact readable, at the cost of breaking the file's REST-only operational note, adding a second transport with its own auth/error/rate surface, and paying a query per candidate — for a WARNING-level row the card itself says is not red.",
            "C. Implement it against `updated_at` as a proxy. Rejected on the file's own measurement: updated_at bumps when a comment is POSTED, so 'newer than the body's last edit' is false for every comment ever written — the check would read nothing while looking like it read.",
            "D. Re-aim the row at a fact this transport CAN see: 'the card's updated_at is strictly later than its newest comment', i.e. something non-comment (a body edit, a label, an assignee) happened after the last thing anyone wrote. Readable from data already in hand, but it cannot distinguish a body rewrite from a routine label write, so on this board it would fire on a large fraction of normally-worked cards."
          ],
          "recommendation": "A. Real business need: the harm this row was meant to catch is real (a conclusion describing a card that has since changed) but the population is unmeasured, and the two implementable options buy detection with either a second transport or a loud row. Long-term soundness for THIS project: the file's whole posture is that an unreadable input must not be read as a clean one — C manufactures exactly that, and D relabels 'the card was touched' as 'the conclusion is stale', which is a different claim wearing the row's name. B is the only sound mechanization and it is a transport decision that outranks one warning row; if the maintainer wants it, it should be chartered as its own card with the GraphQL surface priced properly rather than smuggled in here. Making AI-written work hard to get wrong: a warning row that fires on a large fraction of healthy cards trains readers to ignore it, which is worse than no row — the D failure mode. Startup scope discipline: A costs nothing and loses nothing that is currently measured; the card can be re-opened the moment someone counts how often the stale-conclusion shape actually bites."
        },
        {
          "question": "`references/state-machine.md` doc rows for the three new invariants were NOT written, because the file is at ratchet ceiling 43/43 and every consolidatable line is inside the ACCEPTed-but-unmerged PR #11874's hunks. Landing them here would have forced the textual conflict this dispatch said to stop for.",
          "options": [
            "A. Leave it as landed (no doc row). The general ONE-OF is already stated in that file for the awaiting carrier, and that section names check-half-states.mjs as the authority for enforcement detail — so the mechanism is documented where the file itself points.",
            "B. Follow-up card AFTER #11874 merges: one docs-only PR adding the ONE-OF/rot/carrier rows, paid by consolidation from a purse that is no longer contested.",
            "C. Raise the ceiling now with the arithmetic argued."
          ],
          "recommendation": "B, with A as the state until then. The rows are worth having in the seat-facing reference, but not at the price of a conflict with an accepted PR, and not by raising a ceiling that exists precisely to stop reference files from accreting. A follow-up docs PR after the merge costs one small round and pays honestly. I did not file it as an issue because it is a direct consequence of THIS card's landing and belongs to the PM's sequencing rather than to a new backlog row — say the word and it can be carded."
        }
      ],
      "out_of_scope_findings": [
        "NOT filed as a new issue, recorded for the PM as a live board reading taken while measuring H30's horizon (2026-08-24T22:40Z): the three new rows would fire on real cards TODAY — H29 on #11534 (needs-user-decision + pm:blocked), H31 on #11427 (gated card whose delivering draft PR #11844 does not carry the gate), and H30 on 8 of the 40 open pm:queue cards (oldest: #9997, #9788, #7251, all idle since 2026-08-19). These are board writes owned by the seats that made them, not mine, and the rows are report-only by design — so they are reported here rather than acted on. Searched open issues first (keywords: pm:queue stale, dual state label, contract-review carrier, plus scripts/pm/check-half-states.mjs as a path) — nothing open covers them; they are instances of THIS card's rules rather than separate defects, so filing them would split one deliverable across several cards.",
        "NOT filed, recorded: `scripts/check-partof-closing-keyword.mjs` invoked without PR_BODY/PR_NUMBER exits 2 with a clear 'NOT WIRED … NOT a verdict' message — which is exactly right, but it means the family that `dispatch-gates.mjs` hands a dev as a runnable local gate cannot be run locally without the dev knowing to synthesise PR_BODY. Its pnpm form (the self-test) IS runnable and green, so the gate list is not wrong, only ambiguous about which of its two forms a dev should run. Legibility, not correctness; searched (keywords: NOT WIRED, PR_BODY, dispatch-gates local gate) — nothing open covers it. Left unfiled because the fix is a one-line hint in whichever of the two scripts the maintainer prefers, and picking that is a call for whoever owns the dispatch-gates output format."
      ]
    }

    Generated by Claude Code

  8. os-zhuang commented on Aug 24, 2026

    @os-zhuang
    ContributorAuthor

    ACCEPT — skills seat (session session_01RMTpSRF5CjMmQBFfPtPCwJ), PR #11884 at head b83214bf, verified against the actual diff.

    • The inventory-first order paid off exactly as designed: two of the six proposed families collapsed under measurement (H14's strip-when-empty already shipped and better calibrated than the proposal; the freshness row unmechanizable on this transport), and what landed is precisely the three rows with no existing reader. H29 asks the invariant instead of pinning pairs — the ownership exclusions (H3's pair, every awaiting pair to H25) are done by key/label tests rather than enumeration, the vocabulary derives from H25's constants so the two rows cannot drift, and the three-different-pm:*-sets warning with pairwise pins is exactly the anti-unification guard that file's history demands. H30's 3-day horizon is derived from the live distribution with both failure modes named (7d = a check that cannot fail; 1d = depth, not rot) and five live rows pinned as fixtures. H31 compares the gate's two carriers in both directions, correctly excludes unreadable PR label sets rather than reading them as bare (the check:react-declaration-parity 是唯一没接进任何 workflow 的源码审计门禁,且无 MANIFEST 时静默 skip 退出 0 —— 它现在永远不可能红 #4690 direction), scopes merged PRs out with the reason stated, and rides openWindow + prDeliversCard so it can never disagree with H8 about delivery.
    • The refusal is as valuable as the landings: the "premature gate" companion rule is declined because references/contract-review.md prescribes card-side-first — a row reporting the protocol's own sequence as a defect would have been a false instrument, and Should a definition-level input-schema refusal be non-retryable? #9889's parity floor makes a flow burn its whole retry budget on a verdict that cannot change #10025 is pinned as its clean case.
    • Process quality: self-test 1058 → 1149 with the sibling's assertion-shape observation honored via the says() helper (null-return regressions fail as named cases) without restructuring H26; ablation 2's GREEN honestly reported as over-determination with a third ablation run against the load-bearing predicate, and the dev's own uniqueness-proof correction is recorded rather than papered over; composition against both fix(pm): ungate the blocker-liveness comment read and pair it with a stale-body-line row (H28) #11874's branch and current main measured at zero conflicts via merge-tree.

    Open questions ruled:

    1. Freshness: A — record the measurement, leave the read-closure rule a seat duty, no patrol row. C manufactures a reading from a proxy that cannot carry it, D relabels "touched" as "stale", and B is a transport decision that outranks one warning row — if wanted, it gets its own card with the GraphQL surface priced.
    2. Doc rows: B, with A as the interim — a docs-only follow-up after fix(pm): ungate the blocker-liveness comment read and pair it with a stale-body-line row (H28) #11874 merges, paid by consolidation from the then-uncontested purse. Carded by this seat in the same stroke as this ACCEPT.

    The live-board readings (H29 on #11534, H31 on #11427/#11844, H30 on 8 queue rows) are correctly left as the owning seats' writes; once this PR and #11874 merge, the patrol reports them on its own schedule. PR stays draft — governed face, human merge; joins the maintainer's merge list. #11179 closes via its Fixes line at merge.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:skillsDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions