Skip to content

fix(unfinished): fix mobile sizing on Unfinished page and its modals#210

Merged
tstapler merged 10 commits into
mainfrom
backlog/stapler-squad-fix-unfinished-page-mobile-sizing
Jul 24, 2026
Merged

fix(unfinished): fix mobile sizing on Unfinished page and its modals#210
tstapler merged 10 commits into
mainfrom
backlog/stapler-squad-fix-unfinished-page-mobile-sizing

Conversation

@tstapler

Copy link
Copy Markdown
Owner

Summary

The Unfinished page and its modal components had no mobile CSS treatment — no dvh/--viewport-height usage, no overflowX: hidden, and hover-only action buttons — unlike sibling pages already fixed in commit 759a1006.

What Changed

  • UnfinishedTab.css.ts: added overflowX: "hidden" to the page container to stop horizontal scroll at mobile widths.
  • WorktreeDiffModal.css.ts: maxHeight now uses calc(var(--viewport-height, 100dvh) - 4rem) instead of 100vh, plus a full-screen-sheet variant below the md (768px) breakpoint.
  • CommitPushModal.tsx: ported to createPortal(document.body), matching WorktreeDiffModal, so its fixed overlay can't be broken by a transformed ancestor.
  • CommitPushModal.css.ts: overlay/modal now scroll (overflowY: auto) with a dvh-based maxHeight, plus a full-screen-sheet variant below 768px, so Submit/Cancel stay reachable when the on-screen keyboard shrinks the viewport.
  • UnfinishedItem.css.ts: .actions now forces opacity: 1 under @media (hover: none) so Dismiss/Snooze are visible/tappable on touch devices without requiring hover.
  • UnfinishedItemDetail.css.ts / WorktreeDiffModal.css.ts: swapped two hardcoded zIndex numbers for the named zIndex.dropdown/zIndex.modal tokens per css-architecture.md.

All new rules are scoped inside @media (max-width: 768px) or @media (hover: none) blocks — the existing desktop (>=1024px) maxWidth: 960px, centering, and flexWrap rules are untouched.

Test plan

  • npx tsc --noEmit — no errors introduced in touched files
  • pnpm run lint:css (stylelint) — clean
  • npx --yes tsx scripts/check-theme-contrast.ts — all WCAG AA pairs pass across all 4 themes
  • npx jest --no-coverage --testPathPatterns="unfinished" — 234/236 suites pass (2 pre-existing unrelated failures in SessionDetail/BacklogEmptyState, not touched by this change)
  • Full Playwright e2e (navigation.spec.ts, the only spec hitting /unfinished) — could not run in the dev sandbox (no Chromium binary installed); needs a CI or local run with npx playwright install

Unfinished page and its component tree had no mobile CSS treatment,
unlike sibling pages fixed in 759a100. Adds overflowX:hidden to the
page container, converts WorktreeDiffModal/CommitPushModal to
dvh-based sizing with a full-screen-sheet variant below 768px, ports
CommitPushModal to createPortal so its fixed overlay can't be broken
by a transformed ancestor, and makes item-card Dismiss/Snooze buttons
visible via @media (hover: none) instead of hover-only. Also swaps two
hardcoded zIndex values for the named theme-contract tokens.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaXkDT9P1nSwknvACLd6Gi
@github-actions

Copy link
Copy Markdown
Contributor

✅ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 117 feature files to /tmp/tmp.vEIzDX6BXx/backend
Wrote 15 feature files to /tmp/tmp.vEIzDX6BXx/backend
Wrote 45 feature files to /tmp/tmp.vEIzDX6BXx/backend
Wrote 7 feature files to /tmp/tmp.vEIzDX6BXx/backend
Wrote 11 feature files to /tmp/tmp.vEIzDX6BXx/backend

=== Backend Registry Diff ===
Committed: 179  Generated: 179  Divergence: 0.0%
⚠️  111 feature(s) missing // +api: marker (markerFound: false)

✅ Registry validation passed. Divergence: 0.0%

Test Coverage: 18/179 features have testIds (10.1%)

Divergence > 2% blocks merges. Coverage reporting is advisory only.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

UX Analysis

Check Status Details
✅ Axe Core (WCAG 2.1 AA) success Critical/serious violations block merge
⚠️ Lighthouse Performance Score: unknown Warning if < 70 (non-blocking)
🤖 Claude UX Analysis Advisory See docs/qa/ for findings

Axe Core excludes terminal rendering areas (intentional design).
Lighthouse runs in desktop preset for this developer tool.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Go Benchmarks (Tier 1)

No baseline yet — will be established on next push to main.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Frontend Terminal Throughput

No baseline yet — will be established on next push to main.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

🎬 E2E Feature Demos

2 shard(s) recorded feature flows for this PR.

recordings shard 1
recordings shard 2

Demo preview opens directly in browser (single-file HTML). Raw WebM recordings in ZIP. Expires after 30 days.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

E2E RPC Latency

No baseline yet — will be established on next push to main.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

📊 Feature E2E Coverage

Feature coverage report unavailable

Run make e2e-report locally to view the full Allure report.

tstapler and others added 2 commits July 22, 2026 20:56
The suite couldn't execute at all until now (no Chromium in this
sandbox previously masked it): rpc() was missing the /api prefix every
RPC route requires, the pinned-repo fixture pointed at the bare repo
instead of the working clone (scanner needs a .git dir to resolve
`git worktree list`), and the hardcoded session title collided across
hook retries against the same long-lived test server. All three
predate this branch (authored 2026-04-30, commit 3296f2c).

With these fixed, the suite actually runs: the accessibility contrast
test and 7/11 core-mechanics tests (page load, empty state, filter
toggle, refresh RPC, item expand/collapse, nav badge, reattach
session) pass cleanly. The Commit & Push modal test failure confirms
the CommitPushModal portal migration works correctly (dialog opens
with proper aria-modal/aria-labelledby) — it fails only because its
locator is too broad and also matches an unrelated pre-existing
Notification Panel dialog. Remaining failures (Open Session fixture
mismatch, Dismiss button strict-mode violation from worktree
accumulation across sequential beforeAll runs) are pre-existing
test/fixture design issues unrelated to the CSS changes in this
branch.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaXkDT9P1nSwknvACLd6Gi
Pre-existing untracked bug docs from prior profiling/investigation
work in this shared worktree; committing so they aren't lost.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaXkDT9P1nSwknvACLd6Gi
@github-actions

Copy link
Copy Markdown
Contributor

✅ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 117 feature files to /tmp/tmp.qTZVlQimu5/backend
Wrote 15 feature files to /tmp/tmp.qTZVlQimu5/backend
Wrote 45 feature files to /tmp/tmp.qTZVlQimu5/backend
Wrote 7 feature files to /tmp/tmp.qTZVlQimu5/backend
Wrote 11 feature files to /tmp/tmp.qTZVlQimu5/backend

=== Backend Registry Diff ===
Committed: 179  Generated: 179  Divergence: 0.0%
⚠️  111 feature(s) missing // +api: marker (markerFound: false)

✅ Registry validation passed. Divergence: 0.0%

Test Coverage: 18/179 features have testIds (10.1%)

Divergence > 2% blocks merges. Coverage reporting is advisory only.

tstapler and others added 2 commits July 23, 2026 23:21
…no-op

Fixes three pre-existing e2e fixture/locator bugs blocking the suite: the
"Open Session" test asserted on a worktree that always had a matching
session (so it never showed that button), and the Commit & Push / Dismiss
tests used ambiguous role queries that also matched the always-present
Notification Panel dialog and the item card's own role="button" wrapper.

Also fixes a real scanner bug found while stabilizing the suite:
EnqueueRepo's 30s per-worktree TTL cache silently no-ops a manual
ScanUnfinishedWork RPC call (the Refresh button) if any worktree in that
repo was scanned recently, so repeated clicks did nothing. Periodic ticks
should respect the TTL; a user-initiated scan should not.

unfinished-work.spec.ts (11/11) and the /unfinished accessibility
contrast test now pass consistently across repeat runs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaXkDT9P1nSwknvACLd6Gi
@github-actions

Copy link
Copy Markdown
Contributor

✅ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 117 feature files to /tmp/tmp.breuwWHPkJ/backend
Wrote 15 feature files to /tmp/tmp.breuwWHPkJ/backend
Wrote 45 feature files to /tmp/tmp.breuwWHPkJ/backend
Wrote 7 feature files to /tmp/tmp.breuwWHPkJ/backend
Wrote 11 feature files to /tmp/tmp.breuwWHPkJ/backend

=== Backend Registry Diff ===
Committed: 179  Generated: 179  Divergence: 0.0%
⚠️  111 feature(s) missing // +api: marker (markerFound: false)

✅ Registry validation passed. Divergence: 0.0%

Test Coverage: 18/179 features have testIds (10.1%)

Divergence > 2% blocks merges. Coverage reporting is advisory only.

The Sources-link test added by the main merge (d475144) asserted
/settings/unfinished with no trailing slash, but next.config sets
trailingSlash: true, so the app always renders the URL with one — the
assertion failed on every run regardless of this branch's changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaXkDT9P1nSwknvACLd6Gi
@github-actions

Copy link
Copy Markdown
Contributor

✅ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 117 feature files to /tmp/tmp.zNH70CeS7V/backend
Wrote 15 feature files to /tmp/tmp.zNH70CeS7V/backend
Wrote 45 feature files to /tmp/tmp.zNH70CeS7V/backend
Wrote 7 feature files to /tmp/tmp.zNH70CeS7V/backend
Wrote 11 feature files to /tmp/tmp.zNH70CeS7V/backend

=== Backend Registry Diff ===
Committed: 179  Generated: 179  Divergence: 0.0%
⚠️  111 feature(s) missing // +api: marker (markerFound: false)

✅ Registry validation passed. Divergence: 0.0%

Test Coverage: 18/179 features have testIds (10.1%)

Divergence > 2% blocks merges. Coverage reporting is advisory only.

tstapler and others added 2 commits July 23, 2026 23:44
… enqueueRepo

The previous fix only bypassed the repo-level TTL gate in enqueueRepo,
so a forced (user-triggered) scan got enqueued but scanWorktree still
hit its own independent per-worktree cache and returned stale data —
the Refresh button appeared to work (a scanCompleted event fired) but
the underlying worktree state wasn't actually re-read. force now flows
through scanTask -> scanRepo -> scanWorktree, which skips the cache
read (and still refreshes it via the existing cache.Set on the OK path).

Adds a regression test that fails without this fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaXkDT9P1nSwknvACLd6Gi
Architecture review flagged that removing the TTL-based throttle for
forced scans (previous commit) meant a burst of triggers landing close
together — fsnotify + manual Refresh + periodic tick — could each
enqueue a redundant concurrent scanRepo for the same repo, since
nothing tracked "already queued/scanning" independent of the cache.

Adds Scanner.inFlight (sync.Map) so enqueueRepo skips re-queuing a repo
that's already queued or being scanned; the worker clears the entry
once scanRepo/publishResults finish, so the next trigger picks it back
up with current state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaXkDT9P1nSwknvACLd6Gi
@github-actions

Copy link
Copy Markdown
Contributor

✅ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 117 feature files to /tmp/tmp.ZWy3LUdtEp/backend
Wrote 15 feature files to /tmp/tmp.ZWy3LUdtEp/backend
Wrote 45 feature files to /tmp/tmp.ZWy3LUdtEp/backend
Wrote 7 feature files to /tmp/tmp.ZWy3LUdtEp/backend
Wrote 11 feature files to /tmp/tmp.ZWy3LUdtEp/backend

=== Backend Registry Diff ===
Committed: 179  Generated: 179  Divergence: 0.0%
⚠️  111 feature(s) missing // +api: marker (markerFound: false)

✅ Registry validation passed. Divergence: 0.0%

Test Coverage: 18/179 features have testIds (10.1%)

Divergence > 2% blocks merges. Coverage reporting is advisory only.

… /unfinished

The Playwright-managed ephemeral test server (tests/e2e/helpers/test-server.ts)
never set STAPLER_SQUAD_INSTANCE=e2e-local, so /api/debug/backlog/{seed,mutate}-*
(server/server.go) were never registered — in CI or locally. This silently
no-op'd every test that depends on them, including the "backlog live updates"
accessibility suite (10 tests were failing on createBacklogItemDirect: a JSON
parse error from the 404 HTML fallback) and, critically, the "stuck-item chips
pass Axe color-contrast on /unfinished" test: with seeding broken, zero stuck
items ever rendered, so the Axe scan had nothing to flag — a false-negative
that masked two real WCAG AA violations on /unfinished's StuckItemsSection
(added by the recent main merge) the whole time.

With seeding fixed, Axe correctly flags:
- chipActive: primary+textInverse = 4.43:1 (needs 4.5:1) in the clean theme.
  Fixed by using primaryActive+primaryText instead (6.29:1) — the existing
  "pressed state" token pair, so this only touches the affected chip, not
  primary's much broader usage across the app.
- stuckReason chip: success+successBg = 3.83:1. Fixed by nudging success
  from #10b981 to #34d399 (5.06:1) — a one-step-lighter shade of the same
  green, following this file's existing WCAG-nudge convention.

STAPLER_SQUAD_TEST_DIR (set via --test-dir) still takes priority in
config.GetConfigDirForDir, so this doesn't change data-directory isolation —
only the debug-handler gate and log prefix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaXkDT9P1nSwknvACLd6Gi
@github-actions

Copy link
Copy Markdown
Contributor

✅ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 117 feature files to /tmp/tmp.aarRW7afJO/backend
Wrote 15 feature files to /tmp/tmp.aarRW7afJO/backend
Wrote 45 feature files to /tmp/tmp.aarRW7afJO/backend
Wrote 7 feature files to /tmp/tmp.aarRW7afJO/backend
Wrote 11 feature files to /tmp/tmp.aarRW7afJO/backend

=== Backend Registry Diff ===
Committed: 179  Generated: 179  Divergence: 0.0%
⚠️  111 feature(s) missing // +api: marker (markerFound: false)

✅ Registry validation passed. Divergence: 0.0%

Test Coverage: 18/179 features have testIds (10.1%)

Divergence > 2% blocks merges. Coverage reporting is advisory only.

…-fix-unfinished-page-mobile-sizing

# Conflicts:
#	tests/e2e/helpers/test-server.ts
#	web-app/src/components/backlog-stuck/StuckItemsSection.css.ts
@github-actions

Copy link
Copy Markdown
Contributor

✅ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 117 feature files to /tmp/tmp.O5QLWQ9c3N/backend
Wrote 15 feature files to /tmp/tmp.O5QLWQ9c3N/backend
Wrote 45 feature files to /tmp/tmp.O5QLWQ9c3N/backend
Wrote 7 feature files to /tmp/tmp.O5QLWQ9c3N/backend
Wrote 11 feature files to /tmp/tmp.O5QLWQ9c3N/backend

=== Backend Registry Diff ===
Committed: 179  Generated: 179  Divergence: 0.0%
⚠️  111 feature(s) missing // +api: marker (markerFound: false)

✅ Registry validation passed. Divergence: 0.0%

Test Coverage: 18/179 features have testIds (10.1%)

Divergence > 2% blocks merges. Coverage reporting is advisory only.

tstapler added a commit that referenced this pull request Jul 24, 2026
…n backstop

Closes the confirmed PR-metadata capture gap (backlog item 12981e9d, PR #210):
an agent driving its own shipping via /backlog:ship -> gh pr create never
reported the resulting PR back to the item record, since only the system-
driven mechanical pushAndCreatePR path wrote pr_url/pr_number.

Epic 3.1: new report_pr_created MCP tool (role: work) verifies the reported
PR against GitHub (VerifyPRMatchesBranch, reusing GetPRForBranch's typed
ErrNoPR) before trusting it, then persists via the new primary-write
Storage.SetBacklogItemPRAndTransition and transitions review -> pr_pending.
Idempotent on a repeated call for the same PR.

Epic 3.2: reconcileOrphanedAgentPRs periodic detector backstops the case
where the agent crashes after gh pr create but before calling
report_pr_created — finds review-status items with no live session but a
real open GitHub PR for their branch, and self-heals via the same
SetBacklogItemPRAndTransition path. Deliberately not a new StuckReason per
ADR-001/plan.md's scope note (StuckReasonAbandonedReview already covers the
genuinely-no-PR case).

Frontend verified unchanged: PullRequestSection already renders pr_url/
pr_number correctly whenever item.status === "pr_pending", which both new
code paths now reliably reach.

project_plans/backlog-agent-communication/implementation/plan.md, Phase 3.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NnUqFpFJid7USqmi7CJQJ7
tstapler added a commit that referenced this pull request Jul 24, 2026
…n input

BUG-047: WriteToSession (web UI chat box) and the write_to_session/
run_command MCP tools appended "\n" after input instead of "\r", so
messages sent to a live raw-mode TUI session (the Claude Code CLI
itself) were written into the pane but never actually submitted --
they sit unactioned in the input buffer with no error surfaced to the
sender. TapEnter, the backlog nudge, the initial-prompt send, and the
autonomous driver's turn-submit keystroke all already correctly used
"\r" (one with a comment tracing the exact failure mode back to
BUG-031). Centralizes the convention into session.EnterKeySequence /
session.BuildSubmittableInput and switches all six call sites to it.

Found investigating why backlog item 12981e9d (PR #210) sat at
status=review for 2.5+ hours: its work session had already gotten the
PR fully green and ready to merge, and a human's "merge it" message
into the live pane silently failed to submit for exactly this reason.

Also files BUG-048 (open, not fixed here): a related but distinct gap
where a stuck review-role autonomous session's autonomous_stuck row
has no remediation/respawn path, unlike the work-role case.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NnUqFpFJid7USqmi7CJQJ7
@tstapler
tstapler merged commit 29eeacf into main Jul 24, 2026
23 checks passed
@tstapler
tstapler deleted the backlog/stapler-squad-fix-unfinished-page-mobile-sizing branch July 24, 2026 21:32
tstapler added a commit that referenced this pull request Jul 24, 2026
… branch

Merging PR #210's branch (created before BUG-018-024/027 were closed and
moved to docs/bugs/fixed/) reintroduced their pre-resolution copies into
docs/bugs/open/ as new files, since that branch's history predated the
deletion. The fixed/ versions are authoritative; removing the resurrected
open/ duplicates.
@tstapler
tstapler restored the backlog/stapler-squad-fix-unfinished-page-mobile-sizing branch July 24, 2026 22:09
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