Skip to content

fix(pm): check-prior-rulings parses the ## Decision shape and names the corpus repo - #19353

Merged
os-steve merged 3 commits into
mainfrom
claude/issue-19132-prior-rulings-objectui-corpus
Sep 20, 2026
Merged

os-steve merged 3 commits into
mainfrom
claude/issue-19132-prior-rulings-objectui-corpus

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes #19132

Clause-②: no

Run from an objectui checkout, scripts/pm/check-prior-rulings.mjs refused — docs/adr parsed to zero decision units — so every objectui decision card was entitled to exactly one paste line, Prior rulings read: unresolved, and could never cite a prior ruling. Both halves of the lane direction (comment 5738994087) land here.

Measured first — the structural difference between the two corpora

The direction required the measurement before any widening. Taken this act at objectui@0c2eb5e and objectstack@13d5294.

What counted as a decision unit before this PR

Two shapes, both keyed on a D-number: a level-3/4 heading (### D8 — One predicate, computed once) and a decision bullet (- **D4** — A tenancy kernel service…) with the separator rule that rejects prose about a decision. Nothing else was a unit.

Which marker objectui's ten files use

file **Status**: line D-number units ## Decision anchor units (before → after)
0001-master-detail-subform.md yes 0 ## Decision 0 → 5
0034-unified-runtime-metadata-persistence.md yes 0 — none — 0 → 0
0036-field-conditional-rules.md yes 0 — none — 0 → 0
0053-list-view-navigation-modes.md yes 0 ## Decision detail 0 → 7
0054-ui-testability-contract.md yes 0 ## Decision detail 0 → 7
0055-parameterized-bare-data-surface.md yes 0 — none — 0 → 0
0056-permission-editing-studio.md yes 0 ## Decision 0 → 6
0057-console-ai-chat-one-conversation-docked.md yes 0 ## Decision 0 → 6
0058-cascading-select-options.md yes 0 ## Decision: per-option … 0 → 5
0059-action-params-shared-field-widgets.md yes 0 ## Decision 0 → 5
total (10 files) 10 of 10 0 7 of 10 0 → 41

The dispatch's mechanism assumption 2 is REFUTED on its status half. It read: no numbered D-units and 「as far as the seat can see」 no **Status**: line. The D-number half holds — zero across all ten. The status half does not: all ten carry a **Status**: line, in spellings this file already supports (**Status**: Accepted — implementing (2026-06-05), **Status**: Proposed (2026-06-22), …). So extractStatusLine and the positional classifyStatus needed no change at all, and objectui units arrive correctly classified. One measured consequence: 0034's **Status**: Implemented (2026-06-06) carries no word in STATUS_WORDS, so it classifies unknown — the intended loud bucket, not a regression.

The whole structural difference is therefore the decision unit, and nothing else. objectui's decisions live under a level-2 ## Decision / ## Decision detail / ## Decisions / ## Decision: TITLE section whose parts are level-3 headings (### C1 — Idempotent, direct triggers) or numbered bold items (1. **Two orthogonal fields, no mode discriminator.**).

The same blind spot is 57% of THIS repo

corpus ADR files files with zero D-number units of those, carrying a ## Decision anchor
objectstack docs/adr 139 79 59
objectui docs/adr 10 10 7

This is not a foreign dialect the reader is being taught to tolerate — it is a shape the reader was already blind to in the corpus it was written for.

The fix

Half ① — the line names the repository whose docs/adr was read

Derived from this checkout's origin, never PM_SWEEP_REPO: the corpus is a property of the working directory, and the two diverge in exactly the case the card names. Named in both arms, so the wrong-corpus case is visible in the line itself:

Prior rulings read: gate,required,spec,shape → 11 hits; ADR-0001 Decision §1; thread: not read (no --card); repo: objectstack-ai/objectui
Prior rulings read: unresolved (repo: objectstack-ai/fakerepo)

The refusal headline names it too (docs/adr in objectstack-ai/fakerepo parsed to zero decision units), and with --card the report says WRONG CORPUS outright when the board and the corpus disagree — the card's second reading, the one six objectui cards were corrected in place for.

⛔ Still no --repo flag: the corpus is reported, never redirected. An unresolvable origin prints repo: unknown rather than dropping the clause, because a line that omits the repo reads like one that agrees with the board.

The paste line stays additive: references/decision-analysis.md pins the terms / hits / named / thread field order, and the repo clause is appended after it, so the documented order and the literal ^Prior rulings read: grep are both unchanged.

Half ② — a THIRD shape, scoped as a FALLBACK

It runs only on a file the two D-shapes parsed to zero units. That is what keeps it from being a widening: the 53 D-carrying objectstack ADRs that also head a ## Decision section are untouched, so a heading that merely contains their D-units can never double-count them.

Prose is refused by three guards, each pinned:

  1. the structural level-2 anchor — a heading whose title opens with Decision/Decisions, never a sentence that mentions one;
  2. the section-lead unit needs a non-empty first paragraph, so a bare ## Decision with nothing under it yields 0 — and an empty docs/adr still exits 3, the control kept;
  3. the file must carry an ADR number, and a file that already speaks D-units is never re-read.

A structural part carries its own line instead of needing a following paragraph, because a one-line item says everything on it (ADR-0050's 1. **FormView.type = layout only**: … would otherwise be dropped).

Unit ids are positional (Decision §1, Decision §2, …): this shape has no D-number to be an identity, so the author's own label (C1 — …) rides in the heading beside it, and a bare ## Decision takes the ADR's H1 so its lead unit is never nameless.

Before / after, both checkouts, with exit codes

run — --terms gate,required,spec,shape before after
cwd = /home/user/objectui (0c2eb5e) exit 3docs/adr parsed to zero decision units exit 0 — 41 units, 11 hits, line resolved
cwd = objectstack exit 0 — 465 units, 117 hits exit 0 — 758 units, 180 hits
empty docs/adr fixture (control) exit 3 exit 3 — and now names the repo

The no-double-count invariant, measured rather than argued. Every docs/adr/*.md in both repos parsed with the origin/main parser and this one, comparing unit id, line and text:

corpus files units before → after files changed of those, changed from a non-zero count
objectstack 139 465 → 758 59 0
objectui 10 0 → 41 7 0

Every changed file went 0 → N. No file that already had units moved by a single unit, so no existing rank moved under them.

Pins added — self-test 143 → 155 cases (pnpm check:pm-prior-rulings)

Pins from both sides, as the direction required:

  • objectui's real structure (a ## Decision detail of numbered bold items) → 2 units, ADR id from the filename, accepted from the status line objectui does carry, the item body present in the unit text so a term can match it, and the following ## Consequences contributing nothing;
  • ## Decision with an empty body0 units;
  • a sentence mentioning a decision under ## Context0 units;
  • a file that has a D1 heading and a ## Decision section → D1 only, ⛔ no double count;
  • a path with no ADR number → 0 units, anchor or not;
  • the repo clause in the resolved line, in the refusal, and its unknown fallback.

The pre-existing fixture ranks are unmoved: the #16934 fixture still surfaces ADR-0131 D8 at rank 1, the superseded ADR is still found-but-unnamed, the substring-noise control still holds, and the fixture corpus still parses to exactly 6 units — it carries no ## Decision section, so the fallback never fires on it. Seven paste-line pins were updated for the appended repo clause; each is the same assertion with ; repo: unknown added.

Gates

30 of 30 derived families run at head 8ba9049, each exit code captured before any pipe; dispatch-gates --ran reconciles 30 derived / 30 run / 0 NOT-MEASURED — a DERIVED zero (every family recorded a code and none is 3). Derivation asserted with --repo objectstack-ai/objectstack.

origin/main moved to 2277d1f while the battery ran (check:pm-dispatch-gates alone took 1047 s on a box running three copies of it for three parallel agents), so the family list is current as of merge-base 13d5294; CI and the merge queue are the authority past that point.

Acceptance notes


Generated by Claude Code

os-steve and others added 3 commits September 20, 2026 10:36
… the corpus repo

`docs/adr` parsed to zero decision units in an objectui checkout, so every
objectui decision card was entitled to `Prior rulings read: unresolved` and
could never cite a prior ruling.

Measured first, per the lane direction. objectui's ten ADRs carry zero `D<n>`
headings and zero decision bullets; the same census over this repo's own 139
ADRs finds 79 with zero D-units, 59 of them heading a `## Decision` section --
57% of the objectstack corpus was in the same blind spot.

Half (2): a THIRD decision shape, scoped as a FALLBACK -- it runs only on a
file the two D-shapes parsed to zero units, so the 53 D-carrying ADRs that also
head a `## Decision` section cannot double-count. Measured: 0 of 139 objectstack
files that already had units changed; 59 went 0 -> N (465 -> 758 units), and
objectui goes 0 -> 41 units across 7 of its 10 files. Prose is refused by
requiring the structural level-2 anchor and, for the section-lead unit, a
non-empty first paragraph; an empty `docs/adr` still exits 3.

Half (1): both the resolved paste line and the refusal now name the repository
whose `docs/adr` was read, derived from this checkout's `origin`, so the
wrong-corpus case is visible in the line itself. The report also says WRONG
CORPUS outright when `--card` names a board the corpus does not come from.

Claude-Session: https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi
Co-authored-by: Claude <noreply@anthropic.com>

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 8ba90491fbce3b58b158fbff752649e654d3c42b

① Derived judgments

  • Published accept set / public surface: none moves — one report-only PM reader (scripts/pm/check-prior-rulings.mjs, +141 / −22, net +119 against the ≤ +120 budget); no published package, no schema, no error code, no new flag (⛔ no --repo: the corpus is reported, never redirected). check-widening-tells --declaration no on the diff: 1 file NOT MEASURED (no declared surface covers scripts/pm/**) — the no stands on the seat's reading of the diff, ⛔ not on that exit. check-governed-merges --pr 19353: 0 of 1 paths on the register — NOT governed. Judged correct.
  • Half ① (the line names the corpus): readCorpusRepo() derives owner/name from THIS checkout's origin, never PM_SWEEP_REPO; named in BOTH arms (unresolved (repo: …) and the trailing ; repo: … clause), unknown on an unresolvable origin rather than a dropped clause; the refusal headline and the --card report (⚠️ WRONG CORPUS when board ≠ corpus) carry it too. The clause is APPENDED after the pinned terms / hits / named / thread order, so the literal ^Prior rulings read: grep is unchanged. Cross-file reader checked in seat: check-half-states.mjs H62 priorRulingsReading (origin/main) reads Prior rulings read: unresolved (repo: objectstack-ai/objectui) as unresolved (its test is ^unresolved\b) and the resolved shape with the clause as present — probed live on five lines; its H62 ↔ writer SOURCE pin (includes('Prior rulings read: unresolved')) still holds on this head. Judged correct.
  • Half ② (a third decision shape, as a FALLBACK): parseAdrDecisionSectionUnits runs only when the two D-shapes parsed a file to zero units, so the 53 D-carrying objectstack ADRs that also head a ## Decision section cannot double-count (the dev's before/after census: 0 of 139 objectstack / 0 of 10 objectui files with an existing non-zero count changed; every change is 0 → N). Three prose guards pinned: a level-2 anchor whose title opens with Decision, a non-empty lead paragraph (a bare anchor yields 0, so an empty docs/adr still exits 3 — the card's control kept), and an ADR-numbered path. The dispatch's mechanism assumption 2 was REFUTED on its status half by measurement (all ten objectui ADRs carry **Status**:), so classifyStatus / extractStatusLine are untouched — the correct consequence of the lane direction's 「measure before widening」, ⛔ not a deviation. Judged correct.
  • Evidence, seat-run on this head in a detached worktree: --self-test exit 0, 155 cases (143 → 155; the fallback battery with its empty-anchor / prose-sentence / already-carries-a-D-unit / non-ADR-path controls, and the repo clause in both arms); objectstack control --terms gate,required,spec,shape exit 0 (180 candidates on origin/main 2277d1f); the card's case reproduced both ways from a /home/user/objectui checkout (origin/main 205b973): the origin/main parser exits 3 (docs/adr parsed to zero decision units), this head exits 0 with 11 hits and the line ending ; repo: objectstack-ai/objectui. origin/main has not touched the file since merge-base 13d5294 (0 commits); mergeable: true.

② Semver level

None — nothing published; skip-changeset on the PR is the correct declaration. Judged correct.

③ Boundary flags

open_questions empty. Three noted, not filed items read and accepted with their carriers (the duplicate origin-URL parse vs localCheckoutServes in check-half-states.mjs — a file outside this surface under a Clause-②: no claim; **Status**: Implemented classifying unknown, the designed loud bucket; 20 objectstack ADRs with neither shape — a fourth shape the direction does not authorize). Two seat readings beyond the dev's: (a) ADR_DECISION_SECTION_RE accepts ANY level-2 title opening with Decision (a MADR-style ## Decision Drivers would anchor), broader than the four spellings its docblock names — measured harmless today: the seat's census of both corpora at origin/main finds 11 objectstack spellings and 3 objectui spellings, every one a decision section; carrier: whoever next widens the shape. (b) references/decision-analysis.md :45 documents the line without the trailing repo: clause — the documented shape is now a strict prefix of the real one; H62 tolerates it and the order is unchanged, so this is a one-line Tier S doc follow-up on the seat's ledger, ⛔ not this PR's (its surface is the script only).

Implemented-by: claude/issue-19132-prior-rulings-objectui-corpus
Reviewed-by: session_017ETYWqMQD4qMtZzAGovWNi

VERDICT: PASS


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review September 20, 2026 14:02
@os-steve
os-steve added this pull request to the merge queue Sep 20, 2026
Merged via the queue into main with commit 3270826 Sep 20, 2026
37 checks passed
@os-steve
os-steve deleted the claude/issue-19132-prior-rulings-objectui-corpus branch September 20, 2026 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

check-prior-rulings: objectui’s 10 ADRs parse to zero decision units, so every objectui decision card is stuck on Prior rulings read: unresolved

2 participants