Skip to content

fix(cockpit): use full task detail width by default - #976

Open
matgren wants to merge 3 commits into
mainfrom
cez/fe69813f
Open

matgren wants to merge 3 commits into
mainfrom
cez/fe69813f

Conversation

@matgren

@matgren matgren commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

🎯 What changes

Task detail pages no longer default to the old 820px reading column. The shared --measure token now defaults to full available width, so the run header, session transcript, and composer use the screen instead of leaving a large unused gutter on wide displays. Users who prefer the old reading measure can still choose Narrow in Settings → Appearance.

📋 Scope

This is limited to the cockpit appearance/layout path. The stored width enum remains narrow | wide for compatibility, but the default flips to wide; data-width="narrow" now opts into the 820px cap. The pre-paint localStorage mirror and Appearance settings copy were updated to match, and the existing preference round-trip tests now assert the new default.

💥 Compatibility

Existing wide preferences keep working as the broad mode. Migration 002 removes appearance.width: "narrow" from workspace state once, because older full-object writes persisted the default without proving that Narrow was chosen; users who want Narrow can select it again after upgrading. The rollback surface is the default only: switching the default back would return new/cleared cockpit state to the narrow column. The first load after upgrade can briefly paint the old narrow mirror before the migration response rewrites it.

🧪 Validation

  • npm run typecheck
  • TMPDIR=/tmp TMP=/tmp npm test
  • TMPDIR=/tmp TMP=/tmp npm run test:unit
  • TMPDIR=/tmp TMP=/tmp npm run build
  • TMPDIR=/tmp TMP=/tmp npm run test:package

The first plain npm test run failed because this Cezar task environment sets TMPDIR inside the repository, so tests that intentionally create non-git temp directories were still under a git checkout. Rerunning with temp fixtures outside the repo passed all 327 test files / 6196 tests.

@matgren matgren added review Ready for code review bug Something isn't working needs-qa Requires manual QA before merge priority-medium Ordinary bug or feature risk-medium Ordinary change with tests labels Sep 12, 2026
@matgren

matgren commented Sep 12, 2026

Copy link
Copy Markdown
Contributor Author

🤖 om-open-pr — 🏷️ label rationale

  • 🔍 review — ready for code review after the configured validation gate passed.
  • 🐛 bug — the task detail view wasted usable screen width by default on wide displays.
  • 🧪 needs-qa — the change affects visible cockpit layout and should be manually checked before merge.
  • 🔹 priority-medium — this is an ordinary user-facing cockpit fix, not an outage or release blocker.
  • 🟡 risk-medium — the change touches persisted Appearance defaults and shared layout tokens, but is covered by focused preference tests plus the full gate.

@github-actions

github-actions Bot commented Sep 12, 2026

Copy link
Copy Markdown

📦 npm preview published — 0.11.0-pr976.1524

Try this PR build (exact pinned version — copy-paste as-is):

npx cezar-cli@0.11.0-pr976.1524                                # cockpit at http://localhost:4321
npx cezar-cli@0.11.0-pr976.1524 run "…"                        # headless run
npx cezar-cli@0.11.0-pr976.1524 server-deploy --platform <id>  # roll a server to this exact build

Also tagged: npm install -g cezar-cli@pr-976 (moving tag for this PR).
Packages: cezar-cli@0.11.0-pr976.1524@open-mercato/cezar@0.11.0-pr976.1524@open-mercato/cezar-api-client@0.11.0-pr976.1524 (provenance attested).

@pat-lewczuk pat-lewczuk added the in-progress Cezar agent is actively working this issue label Sep 12, 2026
@pat-lewczuk pat-lewczuk self-assigned this Sep 12, 2026
@pat-lewczuk

Copy link
Copy Markdown
Collaborator

🤖 om-auto-review-pr started by @pat-lewczuk at 2026-09-12T17:05:59Z. Other auto-skills will skip this PR until the lock is released.

@pat-lewczuk pat-lewczuk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 om-auto-review-pr — Code review

Verdict: 🔴 CHANGES REQUESTED — 1 major, 1 minor, 3 nits. No blockers.

The change itself is clean, small and well-commented, and the token-level approach (one --measure lever, default = absence of the attribute) is exactly right. What it does not account for is that width: 'narrow' was persisted for users who never chose it — so the "full width by default" fix will not reach a large share of existing installs.


🔴 Major

1. Existing installs keep the 820px column, because narrow was persisted without ever being chosenpackages/web/src/lib/appearance.ts:35, packages/web/src/components/appearance-provider.tsx:73-80

AppearanceProvider.save() PUTs the full appearance object on every change (deliberately — the server merges shallowly, so a partial { accent } would drop density). Before this PR the default width was narrow, so:

  • Any user who ever changed Accent or Density has appearance.width: "narrow" written into ~/.cezar/ui-state.json — a value they never picked. The diff's own test shows it: settings.test.tsx:300 asserts a PUT of { accent: 'violet', density: 'compact', width: 'narrow' } from an accent+density interaction.
  • appearanceSchema (packages/cezar/src/server/server.ts:678) stores width verbatim, and normalizeWidth honors a stored narrow.

Net effect after this ships: every user who has ever opened Settings → Appearance and touched anything stays on the old 820px measure and never sees the fix. The PR body's compatibility note — "Existing narrow preferences remain honored" — reads as if those were deliberate choices; for this population they were not.

The PR is a bug fix whose whole point is the default. Please make this an explicit decision rather than an implicit one, either:

  • (a) add a workspace migration (packages/cezar/src/workspace/migrations.ts) that deletes appearance.width when it equals "narrow", accepting that the handful of users who genuinely chose Narrow get reset once and re-pick it — the migration framework is already the sanctioned reshaping path (BACKWARD_COMPATIBILITY.md §9) and is ordered/idempotent/non-blocking; or
  • (b) keep the current behavior and say so honestly in the PR body and the Width doc comment: "the new default only reaches installs that never wrote an appearance preference; everyone else opts in via Settings → Appearance."

Either is defensible — (a) delivers the fix, (b) is a smaller change. What is not fine is shipping it as if narrow on disk always meant intent.


🟡 Minor

2. :root[data-width='wide'] is unreachable, and its comment names a path that does not existpackages/web/src/styles/index.css:256-258

Nothing in the new code can stamp data-width="wide": applyAppearance() removes the attribute for the default (now wide), and the pre-paint script in index.html:39-40 only stamps narrow. The comment says the rule is kept "as a broad-mode alias for older mirrors that stamped it" — but older mirrors are read by the new pre-paint script, which never writes wide. The only path that could still stamp it is a stale cached index.html shell from before this change (the shell is served without an explicit Cache-Controlserver.ts:1407).

That is a legitimate reason to keep the rule, but the comment should name it (stale cached shell, not old mirrors) — or the rule should go. As written the next reader will delete it for the wrong reason or keep it for the wrong reason.


⚪ Nits

3. One-time narrow→full flash on the first load after upgradepackages/web/index.html:39

writeStoredAppearance() runs on every server response, so every existing browser currently holds cez-width: "narrow" in its localStorage mirror (written from the old default, even for users with no server-side preference). After upgrade, the new pre-paint script reads that mirror, stamps data-width="narrow", and the cockpit paints at 820px until the GET /api/v1/workspace/ui-state lands and the provider clears it. Self-healing — the mirror is rewritten to wide on that same load, so only the first load flashes. Worth a sentence in the PR body so it is not mistaken for a bug report later.

4. Stale spec.ai/specs/2026-07-27-publishable-react-components.md:708

The built-in --cezar-measure value is 820px for narrow and 1180px for wide.

wide is no longer 1180px. The --cezar-measure public token is not implemented yet, so nothing breaks — but the spec is now wrong about the value a future implementation would ship.

5. The wide enum value no longer means "wide"packages/web/src/lib/appearance.ts:31

Keeping the stored enum as narrow | wide while the UI says "Full" is the right compatibility call, and the type comment does explain it. Consider one more clause at the type site noting that wide is a legacy spelling for the uncapped mode, so nobody later "fixes" the label mismatch by renaming the persisted value.


✅ Validation gate

Run on the PR head (d452393) in an isolated worktree, TMPDIR outside the repo as the PR body advises:

Command Result
npm run typecheck ✅ pass
npm test ✅ pass — 327 files / 6196 tests
npm run test:unit ✅ pass — 36/36
npm run build ✅ pass — check:pack ok, 475 files
npm run test:package ✅ pass — 16/16

A first npm test run failed 3 files on waitFor timeouts (task-changes.test.tsx:187 and two others) while the machine was still loaded from npm ci; a clean re-run was fully green, and CI is green on the same SHA. Environmental flake, not a PR defect.

CI: all 3 checks passing (Unit, build, E2E, and package, Publish npm snapshot, license/cla). No merge conflicts; the branch is behind main but merges cleanly.

Not covered here: real-browser E2E — this is a visible layout change on a needs-qa PR, so the uncapped measure on a wide display still wants a manual look (especially the transcript line length on ultra-wide monitors, which is the readability cost the 820px measure was originally buying).


Checked and fine

  • max-width: none is valid for all 5 max-w-[var(--measure)] consumers (task-thread ×2, run-header, task-commits ×2); no calc() consumer needs a length.
  • Enum, schema, and /api/v1/workspace/ui-state round-trip are unchanged — additive-only contract honored, no BACKWARD_COMPATIBILITY.md surface broken.
  • Tests were updated alongside the behavior change and both applyAppearance branches stay covered.
  • No new dependencies, no any, no diff-level auto-detections triggered.

@pat-lewczuk pat-lewczuk added changes-requested Reviewer requested changes and removed review Ready for code review labels Sep 12, 2026
@pat-lewczuk

Copy link
Copy Markdown
Collaborator

🤖 om-auto-review-pr — 🏷️ label rationale

  • 🔁 changes-requested (was review) — the review found one major: the new full-width default does not reach installs that already persisted width: "narrow" implicitly.
  • 🧪 needs-qa — kept; a visible layout change still wants a real-browser look before merge.
  • 🔹 priority-medium / 🟡 risk-medium — unchanged, both still fit a user-facing cockpit default flip covered by focused tests.

@pat-lewczuk pat-lewczuk assigned matgren and unassigned pat-lewczuk Sep 12, 2026
@pat-lewczuk

pat-lewczuk commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator

@matgren, the full-width default will not actually reach existing installs: AppearanceProvider.save() PUTs the whole appearance object, so every user who ever changed Accent or Density already has width: "narrow" persisted in ui-state.json without having chosen it — they stay on the old 820px column after this ships. Either add a workspace migration that clears appearance.width === "narrow", or state the limitation explicitly in the PR body and the Width doc comment. Details plus one minor and three nits in the review: #976 (review) — push the update and re-request review.

@pat-lewczuk pat-lewczuk removed the in-progress Cezar agent is actively working this issue label Sep 12, 2026
@pat-lewczuk

Copy link
Copy Markdown
Collaborator

🤖 om-auto-review-pr completed: CHANGES REQUESTED. Lock released.

Full validation gate green on d452393 (typecheck, 6196 unit/component tests, 36 node:test, build + check:pack, 16 package E2E); CI green; no conflicts. One major (persisted narrow blocks the new default from reaching existing installs), one minor, three nits — see the review.

autofix: skipped (not my PR — re-run with --autofix to fix it here).

@matgren matgren added the in-progress Cezar agent is actively working this issue label Sep 16, 2026
@matgren

matgren commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

🤖 om-pr-autopilot started by @matgren. Other auto-skills will skip this PR until the lock is released.

@matgren

matgren commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

QA Report

Result

PASS

PR #976 (d452393a3af0af405793a4c4781e8aa320ea2b31) was exercised in the local dry-run cockpit with agent-browser.

Environment

  • Base URL: http://127.0.0.1:57961
  • Viewports: 1280x577, 390x844
  • Browser: agent-browser 0.33.0
  • Mode: CEZ_DRY_RUN=1

Scenario

Step Result Evidence
Fresh Appearance defaults PASS Full selected, data-width absent, --measure: none; screenshot
Narrow and Full round-trip PASS Narrow uses 820px, Full clears the override; screenshot
Wide task detail PASS Task containers used available width with --measure: none; screenshot
Narrow task detail PASS Task containers capped at 820px; screenshot
Mobile task detail at 390x844 PASS No horizontal overflow; screenshot

Notes

This was an evidence-only run. The browser used a dry-run task fixture and the DOM measurements above; no source files were modified by QA and no qa-approved label was applied.

QA: PASS

Inline screenshots





@matgren

matgren commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

🧪 Follow-up: add a UI/integration test

Automate this verified scenario with om-integration-tests: boot with an empty workspace ui-state, open Settings > Appearance, assert Full is selected with no data-width and --measure none, select Narrow and assert 820px, return to Full, then open a task detail at desktop and 390x844 and assert no horizontal overflow. Clean up the dry-run task and isolated workspace after the run.

@matgren
matgren requested a review from pat-lewczuk September 16, 2026 08:29
@matgren

matgren commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

🤖 om-auto-review-pr taking over the chain lock — re-reviewing the pushed fix. The migration and documentation updates are on the latest head.

# Conflicts:
#	BACKWARD_COMPATIBILITY.md
@matgren

matgren commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

🤖 om-auto-fix-pr status for #976

✅ Fixed the persisted legacy appearance.width: "narrow" default with migration 002, preserving explicit user choices and unrelated appearance keys.
✅ Current head includes the latest main merge: a2d2d8f1fa0731194b8fcc9c8ea85b10c2d5512c.
✅ Focused regression suite: 271/271. GitHub CI: green (Unit, build, E2E, and package; CLA green).
✅ Browser QA evidence and follow-up scenario are already published on the PR.
⚠️ A broad local rerun showed 19 web-test timeouts, but the affected tests are outside the PR diff and the focused rerun passed; no unrelated fixes were added.
⏳ Remaining gates: external re-review by pat-lewczuk and the needs-qa approval.

@matgren matgren removed the in-progress Cezar agent is actively working this issue label Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working changes-requested Reviewer requested changes needs-qa Requires manual QA before merge priority-medium Ordinary bug or feature risk-medium Ordinary change with tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants