Skip to content

test(account): gate the faulted crew's worst case, and stop paying 88px for it - #173

Merged
guarzo merged 2 commits into
mainfrom
worktree-manifest-faulted-width
Aug 7, 2026
Merged

test(account): gate the faulted crew's worst case, and stop paying 88px for it#173
guarzo merged 2 commits into
mainfrom
worktree-manifest-faulted-width

Conversation

@guarzo

@guarzo guarzo commented Aug 7, 2026

Copy link
Copy Markdown
Owner

What

The account manifest's horizontal-scroll gate only ever measured a healthy crew. showStatusColumn (src/app/account/page.tsx) is exception-only, so on an all-ok seed the widest column in the manifest is not in the DOM at all — the assertion passed because the thing it was budgeting for wasn't rendered.

This adds a gate that seeds a faulted crew, then removes 17px the faulted layout was paying for nothing.

The gate fails against main

Proven before any production code changed, and again against fully-reverted source:

Expected: < 232
Received:   240.21875

Which fault, and why it matters

The STATUS column is content-sized, so "a faulted crew" is a range, not a width. Measured at 320px across every code contactStateToken can render:

result chip scroll before after
label_mismatch "label wrong" 293 275
missing_label "label needed" 300 283
token_invalid "token invalid" 308 291
missing_scope "scope missing" 308 291
needs_reauth "re-auth needed" 316 299

The gate seeds needs_reauth, the widest member-fixable result. A missing_label seed passes at 283px and says nothing about the 299px a needs_reauth member actually gets — that would have been the same class of bug as the one being fixed.

The 17px

The alignment (every token starting at the same x) was bought by min-width: 5.5rem — a flat 88px — on each label. The widest of the three labels, "standings", measures 71px. A two-column grid over display: contents lines sizes that column to content and takes 17px off every faulted state uniformly.

What this does NOT claim

The common case clears one region-width (286px at 320px). The worst member-fixable case does notneeds_reauth still forces 299px. The remaining 13px is the difference between "re-auth needed" and "label needed": content, not layout. Both the CSS rule and the test say so explicitly rather than implying the gap was closed. Shortening that copy is a real lever, deliberately not taken here — the same strings render on the admin members drawer.

Also noted, not gated: an unrecognized result code falls through to result.replace(/_/g, " ") inside a nowrap chip in a content-sized column, which is unbounded. That's an error path.

Regression caught during review

The grid introduced one. justify-items defaults to stretch, and a grid item stretches to its track — so the bordered re-authorize control grew to whatever the standings chip beside it measured: 168px next to "token refresh failed", 199px next to an unrecognized code. .stack never did this (a flex item doesn't stretch along the main axis). justify-items: start restores its own 112.6px and leaves every measured width and scroll figure unchanged. The gate now asserts it.

Constraints respected

  • Name and location stay on separate lines (the one-line layout was measured and rejected).
  • No reveal-on-hover/focus in a <td> — no actions changed.
  • .char__location untouched, so the admin members drawer is unaffected.
  • Row heights unchanged (row-gap is still --s-2); all three fold-count tests and the 63px density budget still pass.
  • .status-line / .status-lines have exactly one consumer, so display: contents can't leak.

Verification

check result
npx playwright test e2e/account.spec.ts 41 passed
npm test 83 files / 1290 tests passed
npm run test:e2e 281 passed (4.4m)
npm run typecheck clean
npm run lint clean
npm run format:check clean
npm run build succeeded

The helper now takes the ContactSyncResult union rather than string, so a typo'd seed is a compile error, and it asserts rowCount — a seed that faults nobody would otherwise leave the STATUS column out of the DOM and pass the width budget for exactly the reason the budget exists to rule out.

Summary by CodeRabbit

  • Bug Fixes
    • Improved account status displays for narrow screens, including 320px layouts.
    • Status labels and values now align consistently across entries.
    • Faulted accounts clearly show re-authorization requirements and controls.
    • Adjusted status and control sizing to reduce unnecessary horizontal scrolling and keep affected rows readable.

…px for it

The manifest's horizontal-scroll gate only ever measured a healthy crew, and
`showStatusColumn` is exception-only — so the widest column in the manifest was
not in the DOM when the test ran. The member who has to reach STATUS and ACTIONS
is the member with a fault, and that layout was unmeasured.

Adds a gate that seeds one. It fails against main at 240.2px on the STATUS cell
(budget 232) and was proven to before any production code changed.

The column is content-sized, so "a faulted crew" is a range, not a width. Seeded
`needs_reauth` — the widest member-fixable result — after measuring all of them;
a `missing_label` seed passes at 283px and says nothing about the 299px a
`needs_reauth` member is served.

The 88px `min-width` gutter on the labels bought an alignment the widest label
(71px "standings") never needed. A two-column grid over `display: contents`
lines sizes it to content and takes 17px off every faulted state uniformly:

  label_mismatch  293 -> 275    missing_scope  308 -> 291
  missing_label   300 -> 283    needs_reauth   316 -> 299
  token_invalid   308 -> 291

The common case now clears one region-width (286px at 320px); the worst
member-fixable one does not. 299px is still over, the remaining 13px is copy
rather than layout, and both the rule and the gate say so rather than implying
the gap was closed.

Also fixes a regression the grid introduced: `justify-items` defaults to
`stretch`, which sized the bordered `re-authorize` control to the standings chip
beside it (168px next to "token refresh failed", 199px next to an unrecognized
code). `.stack` never did that. `start` restores its own 112.6px and leaves
every measured width unchanged.
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 37 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1c2712f2-d0a0-4a49-8108-ee56fa72a0d9

📥 Commits

Reviewing files that changed from the base of the PR and between 8981841 and f7d8876.

📒 Files selected for processing (1)
  • e2e/account.spec.ts
📝 Walkthrough

Walkthrough

The account status cell now uses a shared grid for labels and values. End-to-end coverage seeds faulted contact-sync results and verifies the 320px layout, status controls, row placement, and horizontal overflow limits.

Changes

Account status layout

Layer / File(s) Summary
Shared status grid
src/app/account/page.tsx:667, src/app/globals.css:1654-1747
The STATUS wrapper now uses status-lines. Status entries participate in a shared content-sized grid. Fixed label width and flex-shrink rules were removed.
Faulted account geometry validation
e2e/account.spec.ts:13, e2e/account.spec.ts:125-158, e2e/account.spec.ts:1106-1257
The test helper updates selected contact-sync results and verifies the affected row count. The geometry test checks needs_reauth labels, controls, row placement, cell widths, and horizontal overflow at 320px.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • guarzo/authGD#2: Implements the contact synchronization job that produces the tested results.
  • guarzo/authGD#71: Provides related account contact-status UI behavior.
  • guarzo/authGD#128: Covers related /account status and re-authorization behavior.

Poem

Status lines join in a measured array,
Faulted contacts now show what they say.
At three-twenty, rows hold their place,
Re-auth controls fit with grace.
Grid and tests keep overflow at bay.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title uses the required Conventional Commit form and describes the test coverage and reduced faulted-layout width.
Description check ✅ Passed The description explains the change, rationale, measurements, constraints, regression, and verification results, but omits the template's dedicated sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/account.spec.ts`:
- Around line 125-156: Update faultContacts to accept the seeded account ID and
constrain its character subquery with character.accountId in addition to the
names filter. Update faultOneAlt and its invocation around the referenced test
flow to pass the same account-scoped API, using acc.id, while preserving the
row-count assertion.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 717b73c8-f7d7-442e-8b5f-fff85985f71f

📥 Commits

Reviewing files that changed from the base of the PR and between 17d2fa1 and 8981841.

📒 Files selected for processing (3)
  • e2e/account.spec.ts
  • src/app/account/page.tsx
  • src/app/globals.css

Comment thread e2e/account.spec.ts
@guarzo
guarzo enabled auto-merge (squash) August 7, 2026 21:39
@guarzo
guarzo merged commit 32b8100 into main Aug 7, 2026
7 checks passed
guarzo added a commit that referenced this pull request Aug 7, 2026
… 3) (#174)

* feat(account): report the healthy verdict as a green chip with a count

* feat(account): let the crew manifest opt out of the narrow page cap

* feat(account): move remediation detail into a sub-row under its character

* fix(account): cancel the drawer row's dead margin and raise the fold floor

.table-notes used to cancel .table-note's own bottom margin for the last
child; deleting that container without a replacement left every drawer
row with s-4 of dead space under a row whose whole point is minimal
height. Adds .drawer-row .table-note { margin-bottom: 0 } and re-measures
the sub-row (37px at 1440/1280, 57px at 390, not the flat 53px the prior
comment claimed).

Waits on document.fonts.ready before the fold measurement, which removed
the run-to-run variance that made FAULTED_FOLD_TARGETS unraisable; raises
the floor to the now-stable observed minimum (7/6/5, five consecutive
runs each viewport) per Step 11's instruction to raise rather than leave
a floor below the truth.

Also re-indents two comment bodies whose opening `{/*` moved during the
prior commit's reindent but whose body lines did not follow, and updates
.table-note's docblock now that it also renders inside a table row.

* fix(ui): stop the row-hover tint painting over drawer rows

* fix(account): reconcile the remedy sub-row with #173's faulted layout

The branch was cut before round 2 landed and #173 reworked the same
faulted-crew layout. Rebasing onto it exposed three real interactions,
none of which the pre-rebase measurements could have seen.

#173's 320px gate counted `re-authorize` links across the whole manifest
and asserted 1. Task 3 moved the remedy prose inside the manifest, and
each contacts-faulted row's `ContactRemedy` carries its own link when the
token is valid — so the honest count is 3. Scoped the existing assertion
to `.status-line`, which is the cell the width measurement is of, and
pinned the other two on the drawer rows rather than dropping them: a
change that stops rendering them should fail here, not quietly loosen the
line above. The 320px width budget itself is unaffected — a spanning
sub-row adds no horizontal cost, and the gate still passes.

Re-measured the fold on the new base: 7/6/5, identical across three runs
and unchanged from the pre-rebase measurement. #173's -17px per faulted
state is real but two faulted rows do not add up to a 63px character row,
so the floor stands.

Re-measured the sub-row: a flat 37px at 1440, 1280 and 390 alike, where
it was 37/37/57 before. At 390 the table sits in a horizontal scroller,
and #173's wider table gives the sub-row enough span that the prose stops
wrapping. Corrected the comment, which claimed the wrap it no longer has.

* fix(account): restore the character name to the remedy sub-row for AT

The sub-row's prose lost its `{name}:` prefix when it moved under the
character it describes, correct for sighted users since the row above
already carries the name — but the table has no `<th scope="row">`, so a
screen reader in table mode gets a spanning cell naming no one, and in
links mode gets N identical "re-authorize" links. Restore the name as a
visually-hidden prefix and pin it with a Playwright assertion.

* test(account): wait on fonts before measuring the healthy fold

The faulted fold test already waited on `document.fonts.ready` before
measuring row geometry (a font swap moves the row height the gate counts
against the fold); the healthy fold test did not, leaving its 390x844
floor of 4 unmeasured against the actual layout. Adding the wait and
measuring 3 runs at each viewport gives a stable 8/6/5 with no
run-to-run variance, so raise the 390x844 floor from 4 to 5.

* docs(account): point the sweep note at the remedy sub-row, not the deleted block

The "prose out of the table cells" bullet still cited the contactRemedies
block below the Scroller, which this branch deleted — as written it read
as a directive to revert the sub-row design it now describes elsewhere.
Update the citation to the sub-row (page.tsx:830-853) and its measurement,
keeping the real prohibition against folding the remedy back into the cell
intact.

* docs(account): fix the second stale reference to the deleted remedy block

The re-review caught one bad line range in the bullet rewritten last
commit (830-853 ends mid-props; the block runs to 863). Checking it
turned up finding 6, which the rewrite missed: it cited the deleted
566-586 block and closed by saying the prose "should stay exactly
where it is" -- a directive against the change this branch just made,
in the only tracked doc on this area now that the round-3 spec sits
under gitignored docs/superpowers/.

Finding 6 itself stays open: aria-describedby is still on the <td> and
is still unreliably surfaced. Only its stale structure references are
corrected, plus a note that the sub-row's new visually-hidden name
prefix makes the character recoverable when the description is dropped
-- which softens the finding's cost but does not close it.
guarzo added a commit that referenced this pull request Aug 8, 2026
Sweep item #6 put one paragraph per non-main character under the crew
manifest, explaining what pressing "make main" would do to the account's
tier. But `previewMainChange` has only three outcomes, so the text has
only three possible values — on a real 13-character account it rendered
as thirteen paragraphs, eleven of them byte-identical after the name
prefix. The comment claiming "up to nine of them can apply at once"
understated it; the real ceiling is the crew size.

Collapsing the duplicates was the obvious fix and the wrong one. The
sentence is noise on a row nobody is acting on: it describes a
hypothetical press of a button the member is not pressing, on a
character that is not their main, and it landed directly on top of three
rounds of density work (#169, #173, #174) whose whole point was
reclaiming fold space.

So the feature comes out rather than getting reformatted — including the
per-page `getMainChangeContext` query that only ever backed it, which
takes /account's parallel read burst from four connections back to
three, and `previewMainChange` in core, whose only consumer this was.
`decideTier`, which the membership job actually runs on, is untouched.

The e2e assertion that scoped to the removed `.table-notes` container
would have passed vacuously afterwards; it now counts the contact-remedy
element directly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant