feat(web): land the remaining Clean and Cogent UI/UX work as one integration - #364
Merged
Merged
Conversation
Four registers in the one existing :root block, and the label, value, absence and caption rules repointed at them. Twenty-one cockpit and session label rules each spelled var(--ink3) in their own declaration block, so moving the label tier meant editing twenty-one rules by hand and hoping none of them was a value. Nothing changes colour: --ink-label and --ink-absence both resolve to --ink3 under the captain's ruling of 2026-09-17, --ink-value to --ink. An absence separates from its value on shape, never on tone. COUNTS and DELEGATION keep their own ink and gain a family swap plus a leading em dash from [data-next-absent]::before, stamped at emission because no selector can tell a null from a real 0. The three kinds of absence a reading paragraph can state carry data-absence and are told apart by a left rule: dim solid, bright solid, dotted, all three legible in greyscale. The briefing's emphasis is inverted back. FO INSPECTING returns to a mono chip at the label tier with a one-line gloss beside the heading, and the line saying whether the captain is needed takes the sentence tier at full ink. The evidence caption is suppressed when no task was observed, which is what leaves the label, value and caption in three distinct registers, and "captured" leaves the briefing on a two-verb rule that introduces no new absence phrase. All nine byte pins recomputed from the assets across three files. The absence side of every ternary is compared against its own value rather than asserted alone, which is the defect class that cost this milestone four review cycles. Implements DRC-4589 Implements DRC-4593 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
…rail card Three issues on one branch, because exactly one in-flight PR may touch cargento_runtime/web/ and all three do. DRC-4592 - make each tab name its own panel and carry a derived state cue. A lede per tab at the sentence tier, naming its own tab word, because three of five open onto a heading that does not repeat the label. A derived cue on the label in four states: a figure, a collection read and found empty, one nothing has published, and one whose context has not arrived. Course counts context.project.changes, Decisions the decision facts off the same semantic nextCockpitDecisionSummary selects, and Held to session.departures under the lane rule at nextCockpitDepartureLaneCount, which is now lifted out of nextCockpitDepartures so the section and the cue cannot disagree. Now and Console render no cue, and neither does Held to with the store off: those panels render no collection, which is not an absence to assert. Every read is guarded on the collection being an array first, because a length taken off a list declared on every row reports the schema (DRC-4559, the first Measured Invariant). Departure and revision are defined inline at first use; the reading definition renders only on the arms where NEXT_READING_OFFER does not. DRC-4598 - re-expose the timeline's own filter. nextCockpitTimeline stops passing mode:"decisions", controls:false and passes defaultMode instead, so an untouched tab renders what it rendered before and a reader who presses a button reaches the filtered activity view and the all-events view. One resolver, projectResolveGraphMode, is shared by the renderer and the cockpit heading, so the heading cannot say RECORDED DECISIONS over an all-events list. The mode mirrors to one cargento.next.graph.mode key and is read back on load. The dead nextCockpitProjectScope is deleted; nextCockpitProjectScopeKind survives. DRC-4597 - rebuild the scope rail card around the session title. Two lines: the title alone on line 1 at --fs-sm in --ink, clipped with the whole string in title=; harness, state, age and, on a twin row, the sid on line 2 at --fs-2xs. The builder takes a value and a meta rather than a label and a subtitle, because the project row and the session rows hold their value in opposite slots. The word SESSION moves into the accessible name and the round marker and connector rule carry the kind without it. Moving the sid off the title repairs the withheld-title marker, which the exact-match test missed on every twin row. The harness hoists into the heading when every row shares one. Both branches of every value-and-absence ternary resolve at one size. The cue's three state rules restate their size so the pair check can see them, and the rail's withheld rule supplies font-family only, leaving the one board-wide rule to own the colour. Implements DRC-4592, DRC-4598 and DRC-4597. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
…orce size DRC-4595. The Console panel spent its first 341px of 968 on setup prose for two capabilities a default run has switched off, and the one place on the page a person can write anything sat 86% of the way down, inside a section captioned "local only, nothing enforces these". Nothing leaves the page: the panel now emits the scope header, the project-scope prompt, the operations rail, then one disclosure holding the terminal surface, the observer-model controls and the status line. The summary reads the capability flags rather than whether those bodies came back non-empty, because both return "" on routes where the capability is on, and a capability that is on renders expanded and outside the disclosure. The steer composer is built once, in the project chrome, through the existing renderer rather than retyped markup, so it keeps data-next-steer-form, data-next-draft, data-next-controls-project, data-next-focus and the 500-character cap. The dead nextProjectControls is deleted: it had no caller in web/ and built a second composer, which made "renders once" unprovable. The correction no longer waits for the press, and the field was raised with the caveat so the warning is not drawn larger than the words it warns about. DRC-4596. The asset test measured the palette, which already passes on every pair, and measured size nowhere. It now enforces the label floor, the exact registry of sub-11px literals, and the sentence floor as a literal 15.0 with an exact inventory of what still sits below it, each demonstrated failing by a mutant applied to an in-process copy of the stylesheet. Its blind spot is stated rather than implied away: it reads one rule at a time, so a sentence whose size, family and line-height are composed across three rules is outside it, and two such sentences render today. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
Two issues on one branch, because exactly one in-flight PR may touch `cargento_runtime/web/`. DRC-4591 — a three-tier caveat rule. Every caveat rendered as one paragraph in the reading flow, and after DRC-4587 the caveat and the finding-label beside it carried the identical font shorthand, so size no longer separated them at all and the same sixty-nine words cost more vertical space than when the issue was filed. `nextCockpitWhy` puts the claim inline and the rest behind a summary, reusing `nextCockpitDisclosureAttr` so the existing restore lane reopens it after a redraw with no registration; Console reuses `projectDisclosure` for the same reason. Nothing is deleted: the one removal is the `two axes, read separately` aside, which said what the footer under the same cards already said, and its reason joins that footer. The rule is recorded as NUI-19, including why tier 3 ships no `docs/` href and no `DEC-N` token — an installed plugin has no `docs/` beside the page, and `RuntimeDecisionCitationsTest` reads the whole runtime tree rather than its comments. DRC-4594 — purpose and inputs before the caveats. A lede says what typing buys, worded to the default board because the unasked lane is off unless the reader started with `--unasked-readings`. The observed record moves from first to last, which overturns half of the placement constraint recorded at `nextCockpitHeldTo` deliberately: the sentence that was anchored to the record's old position is reworded in the same change rather than left claiming a position it no longer has. The re-entry paragraph becomes a primary action over two labelled rows with the platform explanation behind a disclosure, the count labels drop the quantity noun their new group heading supplies, and the `your words` sub-label goes — DRC-4587 set it at the same size as the label it restated, so it was a second label saying less. `PairedBranchRegisterTest` is new and was not in either estimate. A value and the absence that replaces it are chosen by a ternary and never render together, so no selector sweep and no walk of a populated board can see a mismatch; it resolves both branches through the cascade and compares them. It found one open instance on this base, filed as DRC-4607 and pinned in `KNOWN_OPEN` rather than fixed here, so a new violation fails the test and so does fixing that one without moving it off the list. All nine frontend byte figures recomputed from the assets across `test_next_page.py`, `test_next_flag.py` and `test_focus.py`. Implements DRC-4591, DRC-4594. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
The shipped skill body and the runtime module map both enumerated the tab in its old order, with the observed record beside the two fields rather than after the landing axes, and neither mentioned the lede. Both now read in render order, and the skill body says what tiering does for a reader: the claim stays on the page, the rest opens, and an opened one survives a redraw. NUI-19 is retoned to the repository's voice standard. The rule itself is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
This branch carried its own resolver, written when `css_cascade.py` was not yet on `main`. It is deleted rather than kept beside the merged one, which is strictly more capable: real specificity ahead of source order, an element-path walk that can resolve a branch declaring no size of its own, an error raised on a selector form it cannot express instead of a rule silently dropped, and a lookbehind that stops `font:10.5px/1.5` resolving as 0.5px. Two resolvers drift, and the weaker one produces plausible numbers, which is the failure this guard exists to stop. Two checks survive because the census above cannot make them. A tier-2 summary read against the body it hides is not a value/absence pair, and that test is scoped to DRC-4587's claim and says so; the summary is still the same trap one layer out, because it carries the only words a reader has for deciding whether to open the body. And the COUNTS row emitter is asserted at the source, in the shape `test_the_revision_slot_cannot_invert_because_one_class_carries_both` already uses: by the time a second class reaches the stylesheet, a CSS-only check is comparing two rules rather than noticing there is now a pair. `RAISED_ABSENCES` held one entry, `two axes, read separately`, and this branch deletes that span as a duplicate of the footer under the same cards. Removing it silently would have left the tuple empty and its loop green over nothing, so it is replaced by the landing card's own value and absence. It also did not fail when the class went: `resolve` walks up the path and inherits, so the absence still resolved to 15.0 off the section and compared equal to its value. That is the class's own second docstring failure, "one built a DOM the application never renders", reproduced in the test named for it. A path is only evidence while the emitter still builds it, and no resolver can tell you that it does, so `test_the_retired_axes_span_stays_retired` holds that half against both the emitter and the stylesheet. One inversion neither guard can see is recorded on the census docstring and tracked as DRC-4607: a value inheriting its size, drawn against an absence that declares a larger one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
Integration fix across DRC-4589, DRC-4592 and DRC-4597, none of which could see the others' trees. DRC-4597 moved `data-next-withheld` off a `<small>` and onto `span.next-cockpit-scope-title`. That class declares `color:var(--ink)` at (0,1,0) -- the same specificity as the bare `[data-next-withheld]` rule and later in the sheet -- so with DRC-4589's AC-3 having stripped the colour from the scope-rail override, a withheld title resolved to FULL ink and rendered byte-identical to a published one. That is the absence-outranks-its-value inversion this milestone exists to remove, and it was reachable only by resolving the pair: two separate rule-counting tests passed over it. The override is (0,2,0) and is now the only rule that can hold the title on the absence register, so it carries the colour again. AC-3's "exactly one rule colours a withheld value" was a count standing in for a property; the property is that every such rule resolves through the register, and that is what is asserted now. `WithheldTitleKeepsTheAbsenceInkTest` resolves both branches through `css_cascade` and was confirmed to fail when the declaration is removed. Two label rules added after DRC-4589 introduced the registers, by branches that never saw them, still spelled `var(--ink3)` beside `var(--fs-label)` in their own blocks. Repointed to `--ink-label`; no colour moves. The DRC-4596 registries and the sentence-tier count are recomputed from the merged sheet. The 70 the branch carried was read against the pre-squash DRC-4587 tree, which raised thirteen rules the narrower #361 that merged did not: main resolves 55 and the four branches here add seven, for 62. The sub-floor inventory is 33, unchanged from main, so nothing here pushed a rule below the floor. Each of the four below-floor absence rules was measured against the value it replaces and all four pairs resolve 12.5/12.5. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
…other Each of these passed on its own branch and fails only when the four are in one tree, which is the class of defect a per-branch merge cannot surface. DRC-4591's two COUNTS readers match `class="next-cockpit-count-value">`, with no room for an attribute. DRC-4589 then stamped `data-next-absent` on exactly the absent spans, so both readers silently dropped the two "not published" rows and asserted against three values where the render has five. Every other call site in this file already allows attributes; these two now match it. DRC-4597's own withheld-title test asserts the count of one that this issue's change refuted -- the attribute now sits on `span.next-cockpit-scope-title`, which declares `color:var(--ink)` at the same specificity and later in the sheet, so the rail override is load-bearing. It asserts the register on every colouring rule instead, and expects the override to carry it. DRC-4593's briefing-register test reads the size off a standalone `.next-cockpit-recovery strong` rule. That rule carries no size on this lineage: the narrower #361 that merged puts it on the head shared with `small`. Repointed, and the three registers still resolve distinct. The Now briefing's word cap read 101 against 100. Neither branch overran it alone: DRC-4593's authority gloss is thirteen words and DRC-4595's steer composer is twenty-six, and only the sum crosses. The composer is not briefing prose, though -- it is a sibling `<section>` DRC-4595 moved into the project chrome, and the mirror regex was anchored on the last `</section>` before the tabs nav, so it swallowed a control and charged its words to the briefing. The lookahead now stops at the briefing's own close. The cap is left at 100 deliberately: it states what the panel is for, and raising it to absorb a measurement error would retire the constraint without anyone deciding to. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
Every hand-counted figure in this section was taken against the pre-squash DRC-4587 tree, which raised thirteen rules the narrower change that merged did not. `main` said sixty-seven, forty-nine and eighteen; the branch that added the assertion said seventy, forty-seven and twenty-three. Measured on the merged sheet: sixty-two, forty-four and eighteen. Two independent counts, both confidently specific, both wrong, neither caught by review, which is why the paragraph now says the figures are written down only because `NextPageAssetContractTest` asserts them. The sub-floor inventory had the same defect in the other direction. Its four sub-group figures were right -- seven on `--fs-sm`, three on `--fs-body`, two on `--fs-summary`, seven literals -- but it omitted the `--fs-xs` group entirely, because on the tree it was written against those fourteen rules had already been raised. Thirty-three, not nineteen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
DRC-4592 and DRC-4597 each appended pairs to `AnAbsenceNeverOutranksTheValueItReplacesTest` when it was a flat table of CSS selector pairs. It was rewritten on the way in to resolve DOM paths through the cascade and narrowed to the absences raised to the sentence tier, which these three are not, so they no longer fit it and a textual merge would have dropped them silently. The property is true on the merged sheet -- the tab cue and both of its marks declare 11.0, and the scope title is 14.0 against an 11.5 caption -- so the guard is carried rather than discarded on the technicality that its old home changed shape. Confirmed failing: raising `.next-cockpit-tab-cue--pending` to `--fs-body` reds it at 13.0 against 11.0. An earlier mutant that inserted `font-size:14px` ahead of the existing `font:` shorthand did NOT red it, and correctly so -- the shorthand resets the size, so that mutant changed nothing a reader would see. A guard is only worth committing once something has been seen to break it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
sync-docs pass for the nine UI/UX entities. Each claim was read off the code rather than off the issue, and the four that were user-visible and undocumented are now in the shipped body. Console leads with the operations rail and keeps the startup capabilities in one disclosure, with a capability that is on rendered expanded and outside it. The tab strip names its own panel and carries a derived cue on the three tabs that have one, with the loading and unpublished marks called out as distinct from a zero. The scope rail leads with the session title over a harness, state and age caption, says so when a title was never published, and carries the session key only on rows that would otherwise render identically. The timeline filter is back, with its three modes remembered per session in the browser. The steer composer's move out of Tripwires is recorded where a reader would look for it, since the control did not change but its location did. COMPATIBILITY.md's docs-synced-through marker is deliberately untouched: this is a feature branch, and parallel branches cannot vouch for one another. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
gcko
added a commit
that referenced
this pull request
Sep 17, 2026
…e syntax The PR Workflow bullet said to always use explicit Closes #NNNN lines. Work here is tracked in Linear as DRC-NNNN, which is not a GitHub issue number, so Closes #4589 points at nothing today and will point at an unrelated issue once this repository's own numbering reaches it -- it currently has #221 and #25 and nothing else. The bullet predates the Linear move. Found by the integrator for PR #364, which correctly used the Implements [DRC-NNNN](url) form that #361 and #362 both use, and flagged that doing so contradicted this file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
Contributor
CoverageThreshold: |
Five findings from the implementers, each measured by them and re-measured here against the consolidated tree rather than taken on report. DRC-4589 showed its own `AnAbsentVariantBorrowsItsSizeFromTheValueItReplacesTest` does not subsume the delegation tuple I dropped: that class constrains the STAMPED variant and says nothing about the base rule it sits on, so raising `.next-delegation-withheld strong` to 40px against a 32px figure left it green. Its replacement is here and reds at 40px. DRC-4592 showed the same for the rail card: with its title/meta tuple dropped, redefining `--fs-2xs` above `--fs-sm` in `:root` survives every other check in the file, because the surviving assertions pin which token each half uses and cannot see the token move underneath them. Its four-line replacement reds on that mutation. DRC-4595 found a hole in its own sentence-tier count. A length passes a swap where one rule leaves the tier and another joins at 15px, and THIS INTEGRATION IS THAT SWAP: DRC-4589 moved `.next-cockpit-authority>span` off the tier and `>small` on. The oracle would have been green on the change that defeats it. It is a set now as well as a count, because two selectors are declared twice and a set alone loses that. DRC-4591 found a regression its own commit created: `.pc-substrate-steps` sat at 15.0 beside a 12.5 sentence in the same disclosure, because #361's review lowered the neighbour after the branch forked. Lowered to match. Nothing tested DRC-4589's trap 1, that a colour tidied into the authority override block would retire the captain-needed ink step by winning on source order. It is the hunk I resolved, so it is guarded here, and the guard was confirmed to fail when the colour is added. The design doc carries three changes. DRC-4589's correction, that a register makes a repoint safe and a removal dangerous, with its example rebased onto the merged tree: the competitor it names was deleted by DRC-4592, and the live instance is the rail card's own title rule winning on source order. The sentence-tier paragraph now reports the set rather than a capped/uncapped split that no test held. And main's refusal to state the sub-floor size is restored, rescoped to the true total, because the set that IS asserted counts what a per-rule census can see rather than what the page has. Byte pins and both DRC-4596 registries regenerated after the stylesheet edit. Every mutation check excluded the byte-pin oracle, which fires on any stylesheet edit at all and would have reported all five as killed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
gcko
added a commit
that referenced
this pull request
Sep 17, 2026
'Compare the set rather than its length' was recorded here as the fix for an oracle that passes a compensating swap. It is half of one. Two selectors in that census are declared twice, so the collection holds 61 entries across 60 distinct selectors and a set alone silently loses the duplicate. The set catches the swap; the count catches a duplicate appearing or vanishing. Either alone leaves a hole nobody looks for again once the first one is closed. Found by the integrator for PR #364, which implemented both rather than the set this file had recommended. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
…does DRC-4589 caught the paragraph claiming more than the code. It led with "resolve both through the cascade and compare them" and then listed two classes under it, but only one resolves: `AnAbsenceNeverRendersLargerThanItsValueTest` compares the size each rule declares for itself, deliberately, and its own docstring says so in as many words. A paragraph warning that a rule count is not a rendered colour should not itself describe a test by what the test beside it does. The two are now described separately, by what each answers. The cascade one holds the absences raised to the sentence tier. The declared-size one holds the pairs that are not raised, and fails loudly when a pair stops declaring a size rather than letting it inherit quietly. The delegation pair stays in the stamp class rather than moving to the declared-size class the taxonomy would put it in. DRC-4589 argued against its own placement and then gave the better reason to keep it: the test exists because the stamp assertions do not cover that pair, and a reader who opens that class and finds only stamp assertions is one step from concluding they suffice, which is what both of us concluded before measuring. Filing it correctly would hide the gap it was written to expose. Prose only. No byte pin moves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
`AnAbsenceNeverRendersLargerThanItsValueTest` is where DELEGATION's figure and the withheld string that replaces it belong by type: separate selectors, neither raised, both declaring literal sizes. It is not there, and the reason is only recorded in the class that does hold it, so a reader arriving by type finds an absence with no explanation. The pointer names the pair, says where it lives, and gives the reason: it sits beside the stamp assertions precisely to show they are not sufficient, because the stamp constrains only the absent variant and says nothing about the base rule it sits on. Measured at 40px against the 32px figure, where every stamp assertion stays green. Both readers are served now. The one who goes looking by type finds the pointer; the one who opens the stamp class and might conclude those assertions are enough finds the counter-example in front of them. That conclusion is not hypothetical: DRC-4589 and I both reached it before either of us measured. Docstring only. No assertion changes and no byte pin moves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
There was a problem hiding this comment.
🟡 Changes recommended
Several UI state paths remain inconsistent, and the byte/count evidence conflicts with the reviewed assertions.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Integrates the remaining Cargento cockpit UI/UX changes across styling, layout, state cues, caveats, and timeline filtering.
Changes:
- Adds role-based inks, absence markers, typography guards, and updated byte pins.
- Reworks cockpit tabs, scope cards, Console ordering, Held to, and steer controls.
- Updates design documentation and user-facing skill guidance.
Live browser walk was not completed in this environment.
File summaries
| File | Description |
|---|---|
docs/design-runtime-architecture.md |
Updates module ownership and cockpit ordering. |
docs/design-reader-state.md |
Documents timeline and disclosure persistence. |
docs/design-next-ui.md |
Records UI, typography, ink, and caveat decisions. |
CONTRIBUTING.md |
Adds ink-register guidance. |
cargento/skills/cargento/SKILL.md |
Updates user-facing cockpit behavior. |
cargento/skills/cargento/cargento_runtime/web/styles.css |
Implements visual roles, markers, and layout changes. |
cargento/skills/cargento/cargento_runtime/web/project.js |
Adds timeline mode persistence and disclosures. |
cargento/skills/cargento/cargento_runtime/web/next-delegation.js |
Adds absence stamps and relocates guardrails. |
cargento/skills/cargento/cargento_runtime/web/next-controls.js |
Moves and clarifies the steer composer. |
cargento/skills/cargento/cargento_runtime/web/next-cockpit.js |
Reworks cockpit rendering, cues, caveats, Console, and Held to. |
cargento/skills/cargento/tests/test_next_page.py |
Adds typography/ink contracts and updates pins. |
cargento/skills/cargento/tests/test_next_flag.py |
Updates assembled-page pin. |
cargento/skills/cargento/tests/test_next_delegation.py |
Tests absence rendering. |
cargento/skills/cargento/tests/test_next_controls.py |
Updates steer caveat assertions. |
cargento/skills/cargento/tests/test_focus.py |
Updates assembled digest. |
Review details
- Files reviewed: 15/16 changed files
- Comments generated: 8
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…t claims Six review findings triaged by execution rather than by reading. Two were refuted on their premise and four were real; the sweep that replaces the weakest criterion then found a fifth instance nobody had looked for. Refuted, no change made: - projectAction's graph-mode ternary drops `decisions`, but the function has no caller and the `data-calm` attribute it serves has no dispatcher in the bundle. The live Decisions button is rewritten to `data-next-cockpit-action="graph-mode"` and passes its argument through the validating projectSetGraphMode. Executed against the rendered cockpit: decisions -> all -> decisions, heading RECORDED DECISIONS. - The unknown HOW IT LANDED card renders a stated absence, not a blank slot. nextObservedPair falls back to the reason, so endText and claimText are never empty, and the pair separates on the `--absent` selector. The `data-next-absent` stamp is the figure-slot form of that ruling, which a sentence card is not. Fixed: - The re-entry disclosure said "Why a raise is unavailable" one line under "Its terminal can be raised". The label now travels with its branch. - The Decisions tab cue reported a context entry that had not arrived as "decisions not published" while the panel beside it said "Loading semantic context". `pending` existed and was reached only at session scope. - The Console setup summary told a reader whose server was started with both capabilities on that the terminal bridge and the observer model were off, because an unread capability collapsed into false. Both are three-state now. Measured on a fixture serving an enabled model and a registered terminal: unread read false/false where settled read true/true, and the terminal section sat inside the setup disclosure on that render. - Two sentences claimed the observed record is above them. DRC-4594 moved it last, and both are false by construction rather than on one fixture. Oracles, replacing four criteria that were verified over lists: - HeldToPositionalSentencesTest sweeps every positional sentence the bundle emits, reads the direction each one states, and compares rendered indices on the correct side. It found a third instance on its first run: the two settle cues say "the question above", and nextCockpitConflict draws them inside its own header, above the question. Both are corrected. A positional word is kept and required to be true rather than deleted, because a sweep with nothing to find passes forever. - The Held to lede is now measured against every absence element the tab renders, derived by the same convention, rather than four listed strings passed through a filter that dropped its own misses. - "two axes, read separately" is checked over every .py, .js, .css and .html under cargento_runtime rather than two files. - The caveat-survival set is derived from the merge base's own reading-why paragraphs, split into sentences because the tiering splits a paragraph. The revision and the extraction are recorded, and a test re-derives the list wherever the base blob is reachable. The absence register guard matched 8 of the 14 rules that carry an absence marker: four spell it with a single hyphen and all four spelled their ink var(--ink3) directly, so repointing --ink-absence would have left them behind. The sweep derives its subject now, the four rules are repointed, and two grouped selectors were split because each shared a rule with something that is not an absence. Byte pins regenerated from the assets. Full suite green: 3636 dashboard tests and 515 script tests, with coverage at 86.8% against a floor of 73. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
The three-state capability read in 8b9b57a keyed off the `loading` flag rather than the state beside it, and that is wrong for the arm that matters. `projectTerminalLookup` marks a REGISTERED terminal `{state:"registered", loading:true}` while it re-checks, and it re-checks whenever the payload revision advances -- which is every poll. A flag-based read therefore reported `null` on every poll of a working console, flipped the summary to "terminal bridge not read yet" and moved the live terminal section into the setup disclosure it had just left. Measured before and after: settled `{terminal:true}`, one revision later `{terminal:null}` with the terminal inside the disclosure; now `{terminal:true}` across the refresh with the section still outside it. `state` is the tri-state on its own -- `loading` only before any answer, then `registered` or `unavailable` -- so the flag plays no part in the decision. Found by re-reading the diff rather than by a suite, which is why it now has one. `ConsoleSetupNeverCallsAnUnreadCapabilityOffTest` pins all three states, asserts the refresh really is in flight before comparing, and was confirmed to fail on three mutants: the `loading` read this replaces, the original `Boolean()` pair, and a version that reports an unavailable terminal as unknown rather than off. Byte pins regenerated. Full suite green: 3639 dashboard tests, 515 script tests, coverage 86.8%. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
gcko
added a commit
that referenced
this pull request
Sep 17, 2026
Two rules from the review of PR #364. A defect needing two projects to be visible cannot be found by mutating a one-project fixture at any width or with any assertion. The milestone's worst defect was a localStorage key that collapsed across projects; both oracles passed and one seeded the collided key as its expected value. Ask whether the fixture holds two of the thing a criterion quantifies over before asking whether the assertion is strong enough. And a survivor has three explanations rather than two: the oracle is blind, the substitution never applied, or the run never loaded the test that kills it. Three findings were withdrawn on the third cause after re-running against the full selection -- the mirror of the no-op case recorded above. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
F1. The cue keyed off `entry.data`; the panel keyed off `entry.data` AND `entry.error`, and the poll's `.catch()` is the only writer of `error`. So a first fetch that FAILED left the panel saying "Semantic context unavailable." beside a cue reporting `pending`, glossed "decisions not loaded yet" -- a completed, failed read described as still in flight. The cue's own comment asserted the opposite. `nextCockpitTabCue` does not exist on origin/main; a54451d introduced it in this pull request, so this is a regression created here rather than one found in passing, and it is fixed rather than filed. Reproduced at BOTH scopes, which is one more than was reported: the focused arm had the same blind spot, and it differed a second way as well -- the panel also requires the PROJECT entry when a session is focused and the cue did not. Two conditions that must agree is the shape that produced both, so there is now one `nextCockpitContextRead` and neither caller re-derives the answer. The cue also takes its facts from that read at both scopes instead of from the `observation` argument. The two were the same object, measured `===`, so no board changes; what goes is the second read that let state and facts drift. A failed read gets its own cue state rather than borrowing one. It is not `pending`, which claims a read is still coming, and not `unobserved`, which claims nothing was published. The mark is the em dash this sheet already uses for a slot with no figure in it. The variant needed a rule of its own, and the obvious test does not prove it has one: pinning the emitted class name passes whether or not the sheet styles it, and measured, deleting the rule left the whole cockpit module green. Only the byte pins went red, and those fire on any stylesheet edit. `EveryTabCueVariantIsColouredByItsOwnRuleTest` derives the variants from the producer and resolves each through the cascade against the unstyled cue, so a state added with no rule reds instead of rendering an absence in the ink a real figure gets. Seven mutants run, all seven fail the suite: the cue ignoring `error`, the mark collapsing into `unobserved`, the panel dropping its failed arm, each of the two variant rules deleted, and a newly emitted variant with no rule. Two earlier mutants that appeared to survive were re-run after confirming the substitution had applied; both then failed. Byte pins regenerated. Full suite green: 3640 dashboard tests, 515 script tests, coverage 86.8%. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
…racles The blocker and every finding from the four verdicts, in one commit. M1. `projectSetGraphMode` keyed on the session, and `projectQuerySession` is "" at project scope for EVERY project, so one entry held every project's choice -- and this branch newly mirrors that map to `localStorage`, which turned a per-tab quirk into a persisted one. The scope is now the session when one is focused and the project otherwise, composed by ONE function the write and the read both call, because namespacing only the write passes half the criterion. `projectDisclosure` already composed that pair; this copies it rather than inventing a shape. The mirror is kept: it is a shipped capability and the criterion asks for the key by name. The fixture is the oracle here. Both of that issue's tests passed on a one-project board and one SEEDED the collided key as its expected value, so no stronger assertion at any width could have found this -- only a second project. The new test presses on one, opens the other untouched, presses there, and returns, because a fix that resolves the fallback from the wrong scope passes the first half alone. The context map. `nextCockpitContexts` has five reachable shapes, three writers, and only one writes `error`. The tab cue this branch adds keyed off `.data` alone and called a finished, failed read "decisions not loaded yet" beside a panel already saying "Semantic context unavailable." Both surfaces now resolve one classification, so they cannot describe a state differently. The fifth shape is the one neither independent enumeration had and the comparison between them found: the `.catch()` MERGES, carrying previous data into the new object, so a failure over loaded data is invisible to `.data`. It keeps its rows and claims nothing about staleness; whether the board should SAY the rows are stale is DRC-4613, not a sentence invented inside a fix commit. The comment that claimed the two "read one object under two names" -- true of the object, false of the field sets -- is replaced by what the function does. `projectTerminalLookup` preserved `registered` across a re-check and reset `unavailable` to `loading`, so a default bridge-off console flipped to "not read yet" on every poll. That is the third instance of this shape and it was inside the repair for the first. The pinning test drives it the way production does and samples on the render that STARTS the re-check: a sample taken four microtasks later passes on the broken code, which is why the first version of this test did. `.next-guardrail-copy small` rendered at 12.5px inside the compliant set, being declared at 15px in one grouped rule and 12.5px by the next at equal specificity. Taken structurally: the compliant set is resolved on ELEMENTS, and the sheet no longer declares a size it immediately overrides. The straddle census is pinned because straddling is the precondition even where it is benign, and the shipped defect was a member of it. `docs/design-next-ui.md` said a per-rule census "will understate the set". It can also overstate, by a different mechanism -- two rules at equal specificity rather than three composing -- and both are now written down, with the limit of the new guard stated rather than implied. Oracles, each with its own falsifier run: DRC-4597 AC-2's count is exercised across group sizes, since every fixture held exactly two sessions and a literal satisfied the derivation; DRC-4593 AC-4 asserts registers as well as pairs, and deliberately not three hexes, because label and caption share `--ink3` by a stated ruling; DRC-4595 AC-1 holds every part of the setup block behind the rail, not just the disclosure; DRC-4591 AC-7 runs on every tiered tab including the `pc-` surface that issue added; DRC-4591 AC-3 requires the disclosure to hide something; DRC-4594 AC-5 exercises all six branch combinations. Not closed, and not claimed: the element-resolved guard does NOT close DRC-4595's AC-5 hole. A rule reaching an element through ancestors the tier selector never names is still invisible, because the path is built from the selector rather than from the page. Widening it by hypothesising every DOM a rule could match was measured and abandoned at 8,873 false positives. All thirteen pins re-derived from the assets after the last edit. Suites green: 3652 dashboard, 515 scripts, coverage 86.8% against a floor of 73. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Jared Scott <jared.scott@variable.team>
…sweep
Four corrections to the previous commit, three of which make a repair stronger
rather than wider.
The mode key now carries the project AND the session, joined on a separator no
label can contain. Keying by the session alone was the collision; keying by the
project alone silently destroys the per-session distinction the resolver reads
at session scope, and that mutant passed every test the previous commit added.
It has one of its own now: three scopes in one project, each pressed to a
different mode, each read back after visiting the others.
`projectLoadGraphModes` validated values and not key shapes. A browser that has
already run this branch holds every project's choice under one empty key, so a
scheme where that key parsed as a real project would hand the old collision
straight to the new one. Unparseable shapes are dropped once at load rather
than defended against at each read site, and the separator is what makes the
shape decidable.
AC-4's storage test is rewritten against the two-project fixture rather than
patched. It seeded the collided key and asserted the first render took it --
the defect written down as the expected result -- and on a one-project board
that key reads as "project scope" rather than as "every project", so changing
the seed alone would have left a one-project fixture asserting a per-project
property.
AC-7 is derived over every `web/*.js` instead of rendered on a list of tabs.
Adding the Console surface to a fixture was the weaker repair: a second fixture
still cannot fail on the surface nobody thought to add, which is the argument
`js_literals` makes about itself and the reason AC-4's retired-span check walks
the runtime rather than naming files. The sweep asserts its file count, and its
one blind spot -- a template literal split at `${...}`, so an href composed
through a hole is out of reach -- is in the docstring rather than implied.
Four mutants, each with the substitution proved applied: the session-only key,
the project-only key, a read that resolves from the other scope, and a load
without the shape check. A `docs/` href planted in three different bundle files
reds the citation sweep from each.
What is NOT claimed. The cue and the panel agree across all five context
states and neither calls a finished read pending; the stale-plus-error state
renders its last known rows by the ruling in DRC-4613 and is separately
classified so that issue can act on it. They agree through one classifier, so
a future defect there is one condition wrong rather than two readers drifting
-- but agreement is not coverage, and DRC-4613 is open.
Still open and not closed by this commit: DRC-4595's AC-5 hole, since the
element-resolved guard builds its path from the selector rather than the page;
and DRC-4597's AC-6 live measurement, which needs a viewport this desk would
not give.
Pins re-derived from the assets after the last edit. Suites green: 3654
dashboard, 515 scripts, coverage 86.8%.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Jared Scott <jared.scott@variable.team>
…e six
Five items, all test and doc; no runtime file changes and no pin moves.
AC-3 had two halves and checked one. That the count rows stay OUT of the
disclosure was asserted; that the disclosure has anything IN it was not, so the
criterion's own empty-body falsifier passed. Removing `nextCockpitWhy`'s
empty-body return leaves 3652 behavioural tests green and draws exactly one
`<p class="next-cockpit-reading-why"></p>` in the re-entry block on the default
board -- a reachable arm emitting an empty sentence, seen by nothing. Both
shapes are now rejected across the whole tab.
AC-5's matrix had collapsed a second time, and in my own repair. The capability
stub returned `{content:"tmux"}`; `nextFocusCapability` requires
`typeof meta.getAttribute === "function"`, so it resolved to "" and all six
cases drew the capability-off branch -- one raise sentence, no disclosure, one
of three branches. Every per-case guard passed, because the anchor and both
rows render on every branch, which is why guarding each case cannot see six
copies of one. The stub is now `CockpitHeldReEntryTest.FOCUS_ON`'s, which
answers `getAttribute` as the page reads it, and the six are asserted to DIFFER:
three distinct raise claims, two distinct re-entry sentences, six distinct
pairs, and the disclosure present on exactly the two branches that have a limit
to explain.
`--ink-caption` doubles onto `--ink3` and `design-next-ui.md` recorded only
`--ink-label` and `--ink-absence`. The ruling cited for declining a
three-distinct-hexes assertion was therefore one role short of covering it.
Three of the four register names land on one hex; only `--ink-value` has an ink
to itself, and that is now written where a reader can re-read it rather than
rediscover it from a failing test.
`_below_floor` swallowed `UnsupportedSelectorError`. It now returns the skip
count and the test asserts it is zero -- 77 swept, 77 resolved, 0 skipped.
Recorded honestly as a TRIPWIRE and not a live guard: putting a sibling
combinator on a tier selector does not produce a skip, because `resolve` calls
`matches` over every rule and lets the error out, so the sweep raises before
the branch is reached. `_steps` is shared, so anything `path_for` refuses,
`matches` refuses too. The branch opens only if the resolver is later changed
to skip rules it cannot express, which is precisely the change that would open
the hole.
Mutants: removing the empty-body return reds AC-3; restoring the broken
capability stub reds AC-5 with `6 != 2`; moving the anchor last reds all six
branches. The skip counter has no falsifier and the docstring says why rather
than implying one.
Suites green: 3654 dashboard, 515 scripts, coverage 86.8%. Byte pins re-derived
and unchanged, since nothing in this commit touches an asset.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Jared Scott <jared.scott@variable.team>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements DRC-4589 — Split the three inks onto label, value and absence roles so a label stops sharing its ink with its own answer
Implements DRC-4593 — Invert the briefing's emphasis and let its all-absent grid collapse
Implements DRC-4591 — Adopt a three-tier caveat rule and put the long form behind redraw-safe disclosures
Implements DRC-4594 — Reorder Held to so its purpose and its inputs come before the caveats
Implements DRC-4592 — Make each tab name its own panel and carry a derived state cue
Implements DRC-4597 — Rebuild the scope rail card around the session title
Implements DRC-4598 — Re-expose the timeline's own filter instead of shipping one of its modes as a dead-end tab
Implements DRC-4595 — Put Console's operations first and lift the steer box out of TRIPWIRES
Implements DRC-4596 — Make the asset test enforce font size, not the contrast that already passes
The remaining Clean and Cogent UI/UX work, landed as one PR because all four branches rewrite
styles.cssand all four move the three frontend byte-pin oracles. Landing them separately would resolve the same conflict four times against a file moving underneath each resolution.Why one PR
AGENTS.md(Calibrating Effort) says the only constraint that genuinely forces a split is that exactly one PR may touchcargento_runtime/web/. Four branches wanted it. One integration resolves the conflict once with all four intents visible, which is what surfaced the defects below.What changed
:root, with label, value, absence and caption rules repointed. No colour moves.0.FO INSPECTINGis a mono chip at the label tier with a one-line gloss; the line saying whether the captain is needed takes the sentence tier.Held toreordered so purpose and inputs come before caveats.Three defects only the integration could find
Each passed on its own branch. None is findable by reading a single diff.
A withheld session title rendered in full ink, identical to a published one. DRC-4597 moved
data-next-withheldoff a<small>and ontospan.next-cockpit-scope-title, which declarescolor:var(--ink)at the same (0,1,0) specificity and later in the sheet. DRC-4589's AC-3 had stripped the colour from the scope-rail override on the reading that it was redundant. It is not: with it gone the title resolved to--ink— the absence-outranks-its-value inversion this milestone exists to remove. AC-3's "exactly one rule colours a withheld value" was a count standing in for a property, and two separate rule-counting tests passed over the defect because neither resolved the pair.WithheldTitleKeepsTheAbsenceInkTestresolves both branches throughcss_cascadeand was confirmed to fail when the declaration is removed. This reverses a captain's ruling made when the premise was different, and is the one thing here that most wants a second opinion.DRC-4591's two COUNTS readers stopped seeing half their rows. Their regex has no room for an attribute, and DRC-4589 then stamped
data-next-absenton exactly the absent spans, so both silently asserted against three values where the render has five.The Now briefing's word cap read 101 against 100. Neither branch overran it alone: the authority gloss is thirteen words and the steer composer twenty-six. The composer is not briefing prose, though, and the mirror regex was anchored on the last
</section>before the tabs nav, so it swallowed a control. The lookahead now stops at the briefing's own close. The cap stays at 100: raising it to absorb a measurement error would retire the constraint without anyone deciding to.Every count in this area was wrong
The sentence-tier figures were taken against the pre-squash DRC-4587 tree, which raised thirteen rules the narrower #361 that merged did not.
mainsaid sixty-seven, forty-nine and eighteen. The branch adding the assertion said seventy, forty-seven and twenty-three. Measured on the merged sheet: sixty-one, across sixty distinct selectors — two selectors are declared twice, which is whyNextPageAssetContractTestasserts both the set and the count rather than either alone. The capped-versus-uncapped split is deleted rather than recomputed: nothing asserts it, so it was precisely the un-held prose figuremainwas right to refuse. Two independent counts, both confidently specific, both wrong, neither caught by review. The sub-floor inventory had the same defect inverted: its four sub-group figures were right but it omitted the--fs-xsgroup entirely, because on its tree those fourteen had already been raised. Thirty-four, not nineteen — thirty-four rather than thirty-three because DRC-4591's.pc-substrate-stepsfix moved that rule below the floor.NextPageAssetContractTestnow asserts all of it.Review round two —
8b9b57a8Six code findings from Copilot, each triaged by execution rather than by reading, because this milestone has twice agreed with a finding's reasoning and then refuted it by running it.
Refuted, no change made.
projectAction's graph-mode ternary dropsdecisions, but the function has no caller and thedata-calmattribute it serves has no dispatcher in the bundle; the live button is rewritten todata-next-cockpit-action="graph-mode"and passes its argument through the validatingprojectSetGraphMode(measured:decisions → all → decisions). And the unknown HOW IT LANDED card renders a stated absence rather than a blank slot —nextObservedPairfalls back to the reason, soendText/claimTextare never empty.Fixed. The re-entry disclosure said "Why a raise is unavailable" one line under "Its terminal can be raised". The Decisions cue reported an unloaded context entry as "decisions not published" while the panel said "Loading semantic context" —
pendingexisted and was reached only at session scope. The Console setup summary told a reader whose server was started with both capabilities on that both were off, because an unread capability collapsed intofalse; measured on a fixture serving an enabled model and a registered terminal, unread readfalse/falsewhere settled readtrue/true, and the terminal section sat inside the setup disclosure on that render. Both fields are three-state now.Two sentences claimed the observed record is above them. DRC-4594 moved it last and reworded "the one sentence that was positionally anchored" — so it swept by known string and missed
NEXT_READING_OFFER, false on every render, andNEXT_READING_UNAUTHORIZED, false whenever it renders.Four criteria verified over lists are now derivations.
HeldToPositionalSentencesTestsweeps every positional sentence the bundle emits, reads each one's direction, and compares rendered indices on the correct side. It found a third instance on its first run: the two settle cues say "the question above", andnextCockpitConflictdraws them inside its own<header>, above the question. A positional word is kept and required to be true rather than deleted, because a sweep with nothing to find passes forever; four falsifiers were run against it and all four kill it. The Held to lede is measured against every absence element the tab renders;two axes, read separatelyis checked over every.py,.js,.cssand.htmlundercargento_runtimerather than two files; and the caveat-survival set is derived from the merge base's ownreading-whyparagraphs, with the revision and extraction recorded and re-derived by a test wherever the blob is reachable.The absence register guard matched 8 of the 14 rules that carry a marker. Four spell it with a single hyphen, and all four spelled their ink
var(--ink3)directly, so repointing--ink-absencewould have moved seven rules and left four behind. The sweep derives its subject now and the four are repointed; two grouped selectors were split because each shared a rule with something that is not an absence.One defect the fix introduced, caught by reading the diff —
2fa5a2f4The three-state capability read keyed off the
loadingflag rather than thestatebeside it.projectTerminalLookupmarks a registered terminal{state:"registered", loading:true}while it re-checks, and it re-checks whenever the payload revision advances — every poll. So the first draft reportednullon every poll of a working console, flipped the summary to "terminal bridge not read yet", and moved the live terminal back into the setup disclosure it had just left. Measured before and after: settled{terminal:true}, one revision later{terminal:null}with the terminal inside the disclosure; now{terminal:true}across the refresh with the section still outside it.No suite caught it, which is why it now has one.
ConsoleSetupNeverCallsAnUnreadCapabilityOffTestpins all three states, asserts the refresh really is in flight before comparing, and was confirmed to fail on three mutants: theloadingread, the originalBoolean()pair, and a version that reports an unavailable terminal as unknown rather than off.This is the reason there are two commits rather than the one intended. The head described below is
2fa5a2f4; the six review replies cite8b9b57a8, which is that head minus this fix.Post-verdict round — F1 from the DRC-4589/DRC-4593 reviewer —
9959f623nextCockpitTabCuekeyed offentry.data; the panel beside it keyed offentry.dataandentry.error, and the poll's.catch()is the only writer oferror. A first fetch that failed therefore left the panel saying "Semantic context unavailable." next to a cue reportingpending, glossed "decisions not loaded yet" — a completed, failed read described as still in flight. The function's own comment asserted the opposite.Fixed rather than filed because
nextCockpitTabCuedoes not exist onorigin/main—a54451d6introduced it in this PR, so it is a regression created here.Reproduced at both scopes, one more than reported, and the focused arm diverged a second way: the panel also requires the project entry when a session is focused, and the cue did not. Two conditions that must agree is the shape that produced both, so there is now one
nextCockpitContextReadand neither caller re-derives it. The cue takes its facts from that same read at both scopes instead of fromobservation— the two were the same object (measured===), so no board changes; what goes is the second read that let state and facts drift.A failed read gets its own cue state rather than borrowing one: not
pending, which claims a read is still coming, and notunobserved, which claims nothing was published. The mark is the em dash this sheet already uses for a slot with no figure in it.The obvious test for the new variant does not work, and that is worth recording. Pinning the emitted class name passes whether or not the sheet styles it — measured, deleting the
--unavailablerule left the entire cockpit module green, with only the byte pins red, and those fire on any stylesheet edit.EveryTabCueVariantIsColouredByItsOwnRuleTestderives the variants from the producer and resolves each through the cascade against the unstyled cue, so a state added with no rule reds instead of rendering an absence in the ink a real figure gets.Seven mutants run, all seven fail. Two that appeared to survive were re-run after confirming the substitution had applied; both then failed.
Post-verdict rounds —
26223372thenddd422bfM1's key now carries the project and the session. The session alone was the collision; the project alone silently destroys the per-session distinction the resolver reads at session scope, and that mutant passed every test the first post-verdict commit added — it has one of its own now.
projectLoadGraphModesvalidated values and not key shapes, so the legacy{"": "all"}a shipped browser already holds is dropped once at load rather than defended against at every read; the separator is what makes that shape decidable. AC-4's storage test is rewritten on the two-project fixture, not patched: it seeded the collided key and asserted the first render took it, and on a one-project board that key reads as "project scope" rather than "every project".The context map is separated across all five reachable shapes, cue and panel resolving one classification. The
.catch()merges rather than replaces, so a failure over loaded data is invisible to.dataalone; that state keeps its last known rows per DRC-4613 and is separately classified so the issue can act on it. Agreement is not coverage — the two agree, one condition governs both, and DRC-4613 is open.projectTerminalLookuppreserved only the affirmative answer, so a default bridge-off console flipped to "not read yet" every poll — the third instance of this shape, inside the repair for the first. Its test samples on the render that starts the re-check, because a sample four microtasks later passes on the broken code..next-guardrail-copy smallrendered at 12.5px inside the compliant set. Taken structurally: the compliant set is resolved on elements, and the straddle precondition is pinned as a census.Seven oracle repairs, each with its own falsifier. AC-7 is derived over every
web/*.jsrather than widened by one tab — a second fixture still cannot fail on the surface nobody thought to add.Two things this PR does NOT claim. The element-resolved guard does not close DRC-4595's AC-5 hole: it builds its path from the selector, not the page, and widening it by hypothesising every matching DOM was measured and abandoned at 8,873 false positives. DRC-4597's AC-6 is not re-measured at 980px — the viewport would not leave 1260 on this desk, and a figure taken there would be the error the reviewer was credited for refusing.
Final round —
c88cc110, test and docs onlyAC-3 had two halves and checked one. That the count rows stay out of the disclosure was asserted; that the disclosure has anything in it was not, so the criterion's own empty-body falsifier passed. Removing
nextCockpitWhy's empty-body return leaves 3652 behavioural tests green and draws exactly one<p class="next-cockpit-reading-why"></p>in the re-entry block — a reachable arm emitting an empty sentence.AC-5's matrix collapsed a second time, in my own repair. The capability stub returned
{content:"tmux"}andnextFocusCapabilityrequirestypeof meta.getAttribute === "function", so all six cases drew the capability-off branch: one raise sentence, no disclosure, one branch of three. Every per-case guard passed, because the anchor and both rows render on every branch — which is why guarding each case cannot see six copies of one. The six are now asserted to differ: three raise claims, two re-entry sentences, six distinct pairs.--ink-caption's doubling onto--ink3is now recorded indesign-next-ui.md; the ruling cited for declining a three-hexes assertion covered only--ink-labeland--ink-absence. And_below_floorreturns its skip count (77 swept / 77 resolved / 0 skipped) — recorded as a tripwire, not a live guard, becauseresolveraises on an unsupported rule before the skip branch is reachable.Evidence
Everything below is measured at
c88cc110, which is the head this describes.ruff check,ruff format --check,mypy --strict,lint_embedded.py,validate_plugins.py,bump_version.py --currentall clean. No version field moved.claude plugin validate --strictandagy plugin validateboth pass.965_309/e79d000c…,styles.css121_011/f1d8a9bc…,project.js111_842.test_next_page,test_next_flagandtest_focusall green.8b9b57a8and again on2fa5a2f4; this head re-runs them. Sub-floor census 35, up from 34 atb2675a2, because one grouped selector was split into two. Sentence tier unchanged at 61.docs/design-next-ui.mdsays 35.Review guidance
The six commits were cherry-picked, not merged. Three of the four branches were based on
2a07380, which is not the tree that merged: PR #362 landed as a squash of1d847b0, built on the squashed #361, while2a07380sits on the pre-squash DRC-4587 commits. The two differ by 399 insertions across seven paths includingstyles.cssand a whole file (tests/css_cascade.py) absent from2a07380. The resolution rule throughout was to takemain's line wherever the only difference was one of those superseded promotions, and apply only the delta each commit itself introduced. That is worth spot-checking; it is where a wrong call would hide.Three absence pairs that DRC-4592 and DRC-4597 appended to
AnAbsenceNeverOutranksTheValueItReplacesTestno longer fit it, sincemainrewrote that class to resolve DOM paths and narrowed it to sentence-tier absences. Rather than drop them, they are carried inAnAbsenceNeverRendersLargerThanItsValueTest. DRC-4589's delegation pair was dropped at first on the same reasoning and then restored verbatim, after its implementer showed by mutation that the stamp class does not subsume it: the stamp constrains only the absent variant and says nothing about the base rule, so the absence can be raised to any size with every stamp assertion green. Measured at 40px against the 32px figure.No
Closes #NNNNlines: DRC-NNNN are Linear issues, not GitHub ones, and GitHub issue #4589 does not exist in this repository. TheImplements [DRC-NNNN](…)form above matches #361 and #362.🤖 Generated with Claude Code