feat(pm): the Prior rulings read: line covers the card’s own thread — tool corpus half and charter :339 in one batch - #19021
Conversation
… half The `Prior rulings read:` line answered for three tree corpora (docs/adr, AGENTS.md, packages/spec/src) and not for the cheapest ruling there is: the one already written on the card being checked. Measured on one card, a director-seat ruling was followed four days later by a retriage that moved the card back into the decision box without citing it, the maintainer ruled again with a different prescription, and a dispatch round ended with zero diff between the two. Run on that card, this file could not have said so. So the card's own thread is the fourth corpus. A ruling comment is recognised by the SHAPE of its first content line — the charter's `Ruling: batch #n item k …`, the pre-charter `## Ruling recorded — …` heading, and a director `Ruling addendum` — measured over 1,100 comments in two windows of the live board; not by author (the director seat wrote as three logins in five days) and not by a quoted 「同意」 (63 of 500 recent comments carry one). Two measured near-misses are pinned OUT and listed uncounted. The line gains a `thread:` clause that spells `none` (read, no ruling), `not read (no --card)` (a --terms-only run) and the whole-line `unresolved` (a thread that could not be read, exit 3) apart. The read is one paged GET walked by page number to a short page, bounded, with pages, bytes and wall time measured and printed: the incident card is one page and ~0.35 s; the longest thread on the board (962 comments) is ten pages and ~4.4 s. Every `--card` run rides the file's existing proxy re-exec. The self-test gains the thread fixtures (shapes, near-misses, an offline paged board with a refusal, a bound and a network failure): 99 → 144 cases. Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF Co-authored-by: Claude <noreply@anthropic.com>
…n rulings SKILL.md :339 required a direction found on an already-ruled card to be answered by a tool whose corpora held no card thread; the requirement and the tool now change in one batch. :339 is rewritten in place (net 0, 120 bytes): the three places a direction may already be ruled are `ADR/本卡裁决/ 不可重裁规则`, which is exactly what the tool's line now covers. decision-analysis.md :45 states the same line shape for a human and gains the `thread:` clause, also in place at the byte cap; both files stay at their ceilings (812 / 812, 50 / 50). Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
维护者速读(终稿)· skills 席 · 2026-09-18T12:03Z这个 PR 做什么:PM 循环在呈报决策卡前要机械查一遍「有没有已经裁过的」。查重工具 代价,实测:每次查重多一次分页读线程 —— 事故卡 #17518 是 1 页、0.35 秒;板上最长的线程(962 条评论)10 页、4.4 秒。 验收:复核记录 5729706403(PASS)、ACCEPT 5729706770;自测 99 → 144;派生门禁 40 / 40 绿;在 head 上实跑 #17518 读出三条裁决(含 hotlong 今天 11:42Z 新裁的一条),最早的在前。 请您做的一件事:受管文本( Generated by Claude Code |
Fixes #18993
Clause-②: no
scripts/pm/check-prior-rulings.mjsanswered thePrior rulings read:line out of three tree corpora (docs/adr/**,AGENTS.md,packages/spec/src/**) whileSKILL.md:339required it to cover 「已裁卡」 — a card's own thread, where the cheapest ruling lives, was in no corpus. Measured consequence on #17518: a director-seat ruling (5651572469, 2026-09-13) was followed by a retriage that re-presented the card as unruled, a second maintainer ruling with a different prescription (5716259259, 2026-09-17), and a dispatch round that ended with zero diff. This PR makes the card's own thread a corpus half of the tool and rewrites the charter line in the same batch, so the requirement and the tool never diverge again.What changed
scripts/pm/check-prior-rulings.mjs(report-only, no write path, unchanged exit register)--cardrun now reads the card's comment thread over the board route the file already uses (its own proxy re-exec guard, taken once, never on--self-test), one pagedGET …/issues/{n}/comments?per_page=100&page=Pwalked by page number to a short page, bounded atMAX_THREAD_PAGES(50), reconciled against the card'scommentsfield.Ruling: batch #n item k …(ruling-line), the pre-charter## Ruling recorded — …heading (ruling-recorded, the shape 5651572469 is written in), andRuling addendum …(ruling-addendum). Every hit prints its id, author, timestamp and shape.**Ruling C landing step** — …,## Ruling A's patch is falsified …).thread:clause with three spellings kept apart:thread: 2 ruling(s) (id, id);thread: none(read, no ruling);thread: not read (no --card)(a--terms-only run). A thread that could not be read is the WHOLE lineunresolved, exit 3, exactly as an unreadable corpus — nevernone.none/not read/unresolved, and an offline paged board: two pages, one page, a 403, no token, the page bound, a network failure, a malformed page; plus a structural pin that noLinkheader is followed).check-half-states.mjs's source-text pin on the line's writer (H62) still holds: 4963 cases pass..claude/skills/pm-dispatch/SKILL.md:339 — rewritten in place, net 0, 120 bytes → 120 bytes, 812 / 812 lines before and after:The three places a direction may already be ruled now read exactly as the tool's line covers them: an ADR, a ruling on this card, a non-re-rulable rule.
.claude/skills/pm-dispatch/references/decision-analysis.md:45 — the human-facing statement of the same line shape (the tool'sformatPasteLinedocblock names it as the twin), rewritten in place, 113 → 120 bytes, 50 / 50 lines:(The file spells the placeholders in angle brackets; they are written as capitals here because the platform mutates angle-bracket fragments in a body.)
This file was not in the dispatch's named surface; it is included because it states the line's shape and would otherwise be the next 「a requirement and a tool that cannot answer it」 pair. No open PR touches it (file lists of the 14 skills-lane PRs read 2026-09-18T11:3xZ).
Hypotheses measured
## Ruling recorded — …22 (os-tesla 19, claude[bot] 3),Ruling: …4 (os-tesla 2, claude[bot] 2); 2026-09-18T04Z–11Z (500):Ruling: …26 (hotlong 26),Ruling addendum2 (hotlong). The charter line (director.md: 「裁决评论首行固定一条:Ruling: batch #N item K · letter X · maintainer 「VERBATIM」 UTC」 — placeholders capitalised here, the file spells them in angle brackets) landed 32a3214 2026-09-13T11:27Z; the heading shape is the same seat's earlier spelling. The fallback the dispatch named — 「every comment by aGOVERNED_APPROVERSlogin」 — is falsified: it would have missed every 2026-09-13 ruling, 5651572469 included. A quoted 「同意」/「agreed」 predicate hits 63 of 500 recent comments (claims, ledgers, dev reports) and names nothing.fetchon the re-exec'd route, pages serial, 2026-09-18T11:3xZ):curlon the same pages reads ~10% more bytes (156,874 on #17518): GitHub pretty-prints for acurl/*User-Agent and minifies for any other, measured directly; the tool reports what its own route pays. The fixed cost per dedupe on the incident card is one page and about a third of a second.--card 17518through the proxy (exit 0 both):and the report's thread block:
--terms single,posture,tenant(no card): exit 0, line ends; thread: not read (no --card).Gates
Derived with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackfrom the worktree (three-dot change set: the three files above): 40 families, every one run, exit codes captured redirect-then-$?, reconciled with--ran(40 derived, 40 runafter the one PREREQUISITE NOT MET was cleared by its declared build:check:doc-formula-expressionsexited 3 for an unbuilt@objectstack/formula; built under the verify lock, re-run, exit 0).check:pm-dispatch-gatesexceeds the foreground cap and ran detached (tail --pid): 779 s,1849 cases pass, exit 0. Also:node scripts/pm/check-prior-rulings.mjs --self-test144 pass;check:pm-skill-ratchet✓ (812 / 812, 50 / 50, widest rows unchanged);check:pm-skill-id-lint✓ 27 files clean;check:nul-bytes✓;check-governed-merges.mjs --testover the three paths: GOVERNED (2 of 3 on the register — expected,.claude/**); eslint on the edited script: 1 file, 0 errors, 0 warnings (--no-inline-config, the root flat config's**/*.mjsblock; no type-aware rules, so the diff moves no untouched file's verdict). Readings taken atcba931995, the branch head. The same derivation from a throwaway worktree atorigin/main64de4c5 (five commits past this branch's base, four of them touching family-defining files) yields the identical 40 families — none new, none gone. This branch is deliberately not merged withmainhere: the incoming range carries fourmerge=os-regenartifacts whose driver debt would hold the push on a PR that touches no spec file; the seat'supdate-branchis the right instrument if a refresh is wanted before landing.No published package moves (
scripts/pm/**and.claude/**ship in nofiles[]):skip-changeset.Acceptance notes
--self-testsection's floor rule is stated for writing a new one); the 2026-09 self-test shape census owns that class — carrier: whoever works that census; not this card.readCardstill uses the globalfetchwhilereadThreadtakes an injectable one; symmetry only, no behaviour — carrier: none.check-single-claim-paths.mjs's proxy re-exec; #18844's triage named no sibling, and the second PR closed as superseded #18963 / PR skills(pm-dispatch): dedupe at grading by file/mechanism over the open board of both repos — same finding ⇒duplicate_of, never a second dispatch #18981 (grading-time dedupe by file) — same class, different mechanism; [finding] two cards on one file, one defect, graded two days apart into two lanes and both dispatched — #18314 (spec, 2026-09-15) and #18844 (skills, 2026-09-17) each produced a PR forcheck-single-claim-paths.mjs's proxy re-exec; #18844's triage named no sibling, and the second PR closed as superseded #18963 is not addressed here.维护者速读(草稿)
改了什么:查重工具
check-prior-rulings.mjs多读一处 —— 被查那张卡自己评论线上的裁决评论;贴进卡面的那一行Prior rulings read:多出一段thread: …,写明本卡已有几条裁决、评论 id 是哪几条;读不到线程时整行仍写unresolved,绝不写成「没有」。章程SKILL.md:339与decision-analysis.md:45各原位改一行,行数不变,同一批落地。为什么改:#17518 上四天内出现两条互相矛盾的维护者裁决,一整轮派发白跑 —— 原因是重新分诊的席位没看到卡上四天前的那条裁决,而工具即使跑了也查不到:卡的评论线不在它任何语料里。这次把「已裁卡」这半边做成机械面,并把章程那句话改成工具真能答的范围。
风险与代价(含回滚):每次查重固定多一次线程读取 —— 事故卡 1 页、约 0.35 秒;全板最长线程(962 条评论)10 页、约 4.4 秒,已实测。识别靠裁决评论首行的固定写法(三种实测形态),不靠作者身份;写法漂移会以「近似项」在报告里显形而不是静默漏掉。回滚 = revert 本 PR 三个文件,无发布物、无数据迁移。
席位意见:(留空)
你要做的:确认三种裁决写法的识别边界可接受;若同意,按受管面流程合并。
Generated by Claude Code