Skip to content

feat(mockups): three directions for the services filter surface - #1828

Merged
BigSimmo merged 13 commits into
mainfrom
claude/filter-popup-design-mockups-x6sbjv
Aug 12, 2026
Merged

feat(mockups): three directions for the services filter surface#1828
BigSimmo merged 13 commits into
mainfrom
claude/filter-popup-design-mockups-x6sbjv

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Summary

Adds /mockups/services-filter-refined — a design study for the sheet reached from the Filter control in the services results band, with three directions each shown at desktop and phone, plus a reproduction of what ships today with its defects annotated.

  • The finding that drove the study. The sheet is titled "Filter services" and nothing in it filters. Every chip calls applyServiceQuery() (services-navigator-page.tsx:604), which pushes a new route and replaces the query — so choosing "Crisis" while reading "16 services · lithium level timing" discards that search and its results. It is a preset switcher wearing a funnel icon. Secondary defects: no per-option counts, four unrelated categories flattened into one chip row, a dead band below the fold, "Done" as a low-emphasis outlined button doing the primary job, and a phone role="radiogroup" contradicting the desktop rail's aria-pressed toggles.
  • Direction A · Refine in place. Facet groups with live counts above a visually separated "Start a new search" block whose rows carry an outbound arrow. Expressible in the current ResultFilterSheet props — the unused ResultFilterOption.hint field (result-filter-control.tsx:39) already exists for counts. Upgrades all 7 modes at once; nothing forks.
  • Direction B · Presets and filters, split. Two tabs so the reader picks a verb before a value, plus a persistent active-filter pill row under the band that keeps the refinement legible after the sheet closes.
  • Direction C · Directory-grade refine. A persistent desktop rail instead of a popover, and a near-fullscreen phone sheet with find-a-filter, collapse-by-default groups and a live preview strip.
  • Counts are real, not placeholders. Computed live from the 219 services in data/services-snapshot.json via ~1KB of base64 facet bitmasks (OR within a group, AND across groups). Those CatalogServiceTags are already populated and entirely unused by the UI today. Verified against the snapshot: Crisis ∩ Regional WA = 12, of which 10 are High confidence and 9 are digital/phone.
  • Suppresses shared mockup chrome for this route in mockups-layout-client.tsx, records the study in mockups/README.md, and regenerates docs/site-map.md.

Data caveats recorded in the study itself: a "No cost" facet is not free (cost_funding is 87 distinct free-text values; ~69 of 219 match a free-ish pattern, so it is deliberately absent rather than faked); age_groups: mixed (202/219) and setting_flags: public (207/219) are omitted as facets because an option that never excludes anything is a row of dead pixels; and the radiogroup / aria-pressed disagreement must be resolved deliberately rather than inherited.

This is design scratch only — no production route, component or behaviour changes.

Verification

  • npm run verify:pr-local

Green through check:runtime, check:installed-lock-parity, format:changed, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, lint, typecheck. Then:

 Test Files  1 failed | 555 passed (556)
      Tests  1 failed | 6061 passed | 4 skipped (6066)

The single failure is pre-existing and environment-caused, not from this diff: tests/pr-handoff-stop.test.ts > emits handoff context only when the marker file exists chmods a git dir to 0o555 and expects the marker write to fail, but this container runs as uid 0, and root bypasses directory permissions on Linux. Confirmed by checking out pristine origin/main (046feb3) in a separate worktree and running the same file there — it fails identically, with none of this branch's changes present. The file is not in this diff.

The two steps verify:pr-local did not reach were then run directly:

Offline RAG fixture and manifest validation passed (36 golden cases, 23 suites).
Client bundle secret surface check passed.        # npm run build, exit 0
  • npm run check:bundle-budget — run after rm -rf .next && npm run build, since a cached .next makes this check report a false pass. A prior mockup route was deleted for failing exactly this gate.
production (what users download, 101 routes): 1291.0 KiB gzip — baseline 1279.1 KiB, within tolerance.
mockups (design scratch, 404s in production, 67 routes, 77 exclusive chunks): 279.6 KiB gzip — baseline 267.5 KiB, within tolerance.
  • UI verification not run in full: npm run verify:ui was not run because this adds only a design-scratch route that 404s in production and touches no production component or shared chrome. Proof was taken directly against the route instead — rendered at npm run ensure's URL, screenshotted at desktop 1280×900 and phone 390×844, and checked at the blocking 320px narrow breakpoint with 0px horizontal overflow.

Risk and rollout

  • Risk: None to production. src/app/mockups/** 404s in production via mockupsEnabled() (src/lib/env.ts:376) and is blocked again at the proxy (src/proxy.ts:129); robots.ts disallows it; eslint forbids production source importing *-mockups. The only shared file touched is mockups-layout-client.tsx, and the edit is one additional pathname branch that cannot affect other mockup routes.
  • Rollback: revert the commit, or delete the route directory and its component — nothing depends on them.
  • Provider or production effects: None. No OpenAI, Supabase, or hosted CI access; the facet counts come from a local JSON snapshot read at build time.

Notes

The mockups deliberately go no further than a study. Every direction here needs real filter state, URL round-tripping, and a services facet index modelled on buildSmartDocumentTagFacetIndex in src/lib/document-tags.ts before any of it could ship — services has no filter state today, because the chip is the query. Directions B and C also add a persistent row under the results band, which touches phone chrome reserve and would need docs/search-chrome-behaviour.md plus npm run verify:phone-chrome before being trusted.

No Clinical Governance Preflight or RAG impact: line: classifyPullRequestFiles returns clinicalRisk: false and operationalRisk: false for this diff, and it touches no RAG-ranking surface.


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added a services filter mockup page available at /mockups/services-filter-refined.
    • Showcases the current filter experience and three redesigned directions across desktop and phone layouts.
    • Includes multi-select filters, live facet counts, active-filter pills, presets, searchable groups, and shared preview state.
  • Documentation

    • Added setup details, design guidance, accessibility considerations, and known limitations for the mockup study.
    • Added the new mockup route to the site map.

The services filter sheet is titled "Filter services" and contains no
filter. Every chip calls applyServiceQuery(), which pushes a new route
and replaces the query, so choosing "Crisis" while reading "16 services
· lithium level timing" discards that search and its results. It is a
preset switcher wearing a funnel icon.

Adds /mockups/services-filter-refined: a reproduction of what ships
today with its defects annotated, then three directions, each at
desktop and phone.

- A · Refine in place — facet groups with live counts above a visually
  separated "Start a new search" block. Expressible in the current
  ResultFilterSheet props (the unused ResultFilterOption.hint field
  already exists for counts); upgrades all 7 modes, nothing forks.
- B · Presets and filters, split — two tabs so the reader picks a verb
  before a value, plus a persistent active-filter row under the band.
- C · Directory-grade refine — a persistent desktop rail instead of a
  popover, and a phone sheet with find-a-filter and collapsible groups.

Every count is real, computed live from the 219 services in
data/services-snapshot.json via ~1KB of base64 facet bitmasks (OR
within a group, AND across groups). Those tags are already populated
and entirely unused by the UI today.

Recorded caveats: cost_funding is 87 distinct free-text values so a
"No cost" facet needs normalising first and is deliberately absent
rather than faked; age_groups:mixed (202/219) and setting_flags:public
(207/219) are omitted because a facet that never excludes anything is
a row of dead pixels; and the phone radiogroup / desktop aria-pressed
disagreement must be resolved deliberately.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011btGFwWKYFWDs5McQkqz9J
@supabase

supabase Bot commented Aug 11, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

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: 53 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

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: CHILL

Plan: Pro

Run ID: 02f66096-33e5-4d4d-89b2-77ebbbae1ed4

📥 Commits

Reviewing files that changed from the base of the PR and between bff7050 and 5505f47.

📒 Files selected for processing (7)
  • docs/branch-review-ledger.md
  • docs/site-map.md
  • mockups/README.md
  • src/app/mockups/mockups-layout-client.tsx
  • src/app/mockups/services-filter-options/page.tsx
  • src/components/services-filter-options-mockups.tsx
  • src/components/services-filter-refined-mockups.tsx
📝 Walkthrough

Walkthrough

Added a runnable services filter mockup route. The page includes live facet counts, shared filter state, responsive previews, three redesign directions, route-specific mockup chrome handling, and supporting documentation.

Changes

Services filter mockup

Layer / File(s) Summary
Filter model and controls
src/components/services-filter-refined-mockups.tsx
Added facet metadata, bitmask operations, live counts, presets, and reusable multi-select filter controls for 219 services.
Current experience and redesign directions
src/components/services-filter-refined-mockups.tsx
Added the shipped filter-sheet reproduction and three responsive redesign directions with search, presets, active filters, counts, reset behavior, and commit states.
Shared previews and implementation notes
src/components/services-filter-refined-mockups.tsx
Added shared preview state, comparison rendering, filter anatomy documentation, and implementation notes.
Route wiring and study documentation
src/app/mockups/services-filter-refined/page.tsx, src/app/mockups/mockups-layout-client.tsx, docs/site-map.md, mockups/README.md, docs/branch-review-ledger.md
Added the mockup route, metadata, sitemap entry, route-specific shell exclusions, study documentation, and review record.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • BigSimmo/Database#1521: Both changes implement redesigned Services search and filter mockups with live facet behavior.
  • BigSimmo/Database#1548: Both changes cover mobile filter-sheet redesigns with multi-select controls and accessibility behavior.
  • BigSimmo/Database#1606: Both changes add mobile/service filtering mockup routes and suppress shared mockup chrome.

Suggested labels: codex

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: three services filter mockup directions.
Description check ✅ Passed The description includes the required summary, verification, risk, rollback, production effects, and notes, with clear explanations for conditional checks.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/filter-popup-design-mockups-x6sbjv

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

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011btGFwWKYFWDs5McQkqz9J

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b64f25597

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/components/services-filter-refined-mockups.tsx Outdated
Comment thread src/components/services-filter-refined-mockups.tsx Outdated
@BigSimmo

Copy link
Copy Markdown
Owner Author

@codex resolve actionable Codex review findings for this pull request and current head using the repository instructions. This is the pull request's single automatic repair pass: do not perform a fresh review, create new standalone findings, or request another review. Work only the existing unresolved Codex threads on the current head. The only repository destination is BigSimmo/Database, and the only branch destination is the pull request head branch claude/filter-popup-design-mockups-x6sbjv at starting commit 17ca6be; never publish fixes to a detached or synthetic work branch and never create a stacked pull request. Use the authenticated GitHub connector to commit each approved fix to BigSimmo/Database:claude/filter-popup-design-mockups-x6sbjv, then verify that the pull request head contains the published commit before reporting success. Always fix P0 and P1 findings. For P2 and lower findings, fix only clear, scoped, low-risk issues; otherwise disposition them with a concise reason. For a fixed thread, reply with as the first line and as the second line. For a no-code disposition, use followed by . These result markers authorize the workflow to close that exact thread only after it verifies a fixed commit is the pull request head; a local-only commit is not a fix. If publication or verification fails, do not use either result marker, do not claim success, and leave the thread open with the blocker. If human input or new authorization is required, do the same. Finish only after every actionable thread is fixed or dispositioned and closed, or explicitly left open for a human decision. Do not update the branch from main, address unrelated reviews, broaden scope, or create more than one scoped fix commit. Do not use external APIs, paid services, credentials, dependency changes, or broad refactors unless explicitly authorized. Add targeted tests where behavior changes and run the narrowest relevant validation.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: 17ca6be42e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/components/services-filter-refined-mockups.tsx (3)

554-561: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

text-white is a hardcoded design value.

Every other color in this file resolves through a var(--…) token. Line 560 uses the literal text-white for the commit button foreground. On the accent background this also fixes the foreground independently of theme, so a light-accent theme loses contrast.

Use the surface token that the checkbox indicator at Line 335 already pairs with --clinical-accent.

Guidelines require Tailwind 4 @theme tokens from src/app/globals.css rather than hardcoded design values.

♻️ Proposed fix
-          : "bg-[color:var(--clinical-accent)] text-white hover:brightness-110",
+          : "bg-[color:var(--clinical-accent)] text-[color:var(--surface)] hover:brightness-110",
🤖 Prompt for 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.

In `@src/components/services-filter-refined-mockups.tsx` around lines 554 - 561,
Replace the hardcoded text-white class in the commit button’s cn configuration
with the existing surface token used by the checkbox indicator alongside
--clinical-accent, using the corresponding Tailwind 4 `@theme` token from
globals.css so the foreground adapts to themed accent backgrounds.

Source: Coding guidelines


953-985: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

SegmentSwitch declares a tablist without the rest of the tab contract.

The container uses role="tablist" and the children use role="tab". Three pieces are missing: aria-controls on each tab, a matching role="tabpanel" on the rendered DirectionBBody output, and arrow-key navigation with roving tabindex. A screen reader announces "tab 1 of 2" and then finds no associated panel.

This matters more than usual here. The study argues that the shipped sheet mixes role="radiogroup" and aria-pressed for the same control, and the anatomy entry at Line 1422 promises "one contract at both widths". A comp that introduces its own incomplete role contract weakens that argument.

The simplest fix keeps the visual design and drops the tab roles, since the switch selects a body rather than paging through peer panels.

♻️ Option 1 — use a radiogroup contract, which matches "pick one of two modes"
     <div
-      role="tablist"
+      role="radiogroup"
       aria-label="Filter mode"
       className="inline-flex w-full rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-subtle)] p-1"
     >
       {segments.map((segment) => (
         <button
           key={segment.value}
           type="button"
-          role="tab"
-          aria-selected={value === segment.value}
+          role="radio"
+          aria-checked={value === segment.value}
           onClick={() => onChange(segment.value)}
♻️ Option 2 — complete the tab contract

Give each tab an id and aria-controls, then wrap the DirectionBBody output in a role="tabpanel" with the matching aria-labelledby, and add ArrowLeft/ArrowRight handling with roving tabindex.

🤖 Prompt for 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.

In `@src/components/services-filter-refined-mockups.tsx` around lines 953 - 985,
Update SegmentSwitch to remove the incomplete tablist/tab roles and use a
radiogroup-style contract for selecting one mode, preserving the existing visual
behavior and onChange flow. Align each option with the component’s established
single-choice accessibility pattern, such as the existing aria-pressed or
radiogroup semantics, without adding tab panels or keyboard-navigation logic.

232-243: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

skipGroup is never passed by any caller.

maskForSelection accepts skipGroup, but useFacetCounts at Lines 249 and 255 calls it with one argument only. The parameter is dead.

The parameter also hints at a counting strategy the code does not use. The anatomy entry at Line 1404 says counts are "computed against the other groups' selections", which describes the skipGroup approach. The implementation instead adds the candidate facet to the selection and recounts, which answers "what would I get if I added this?" — the question the same sentence ends with. Remove the parameter, or use it and align the prose.

🤖 Prompt for 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.

In `@src/components/services-filter-refined-mockups.tsx` around lines 232 - 243,
Remove the unused skipGroup parameter from maskForSelection and delete the
related group-skipping branch, updating both useFacetCounts call sites to match.
Keep the implementation and anatomy prose aligned with the existing
candidate-addition counting behavior rather than introducing the unused “other
groups” strategy.
🤖 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 `@src/components/services-filter-refined-mockups.tsx`:
- Around line 1226-1236: Fix the Direction C footer counts in the component’s
preview strip so facet values represent true subsets of the current selection,
not “if added” union counts. Add a helper alongside useFacetCounts that
intersects maskForSelection(selected) with DECODED[facetId] and returns its
popcount, then use it for the confidence:High and setting:digital_phone values
while preserving the existing total count and labels.
- Around line 456-487: Update ResultsPreview to render the “+ more” span only
when remaining is greater than 0; keep the existing count and SAMPLE_RESULTS
rendering behavior unchanged.

---

Nitpick comments:
In `@src/components/services-filter-refined-mockups.tsx`:
- Around line 554-561: Replace the hardcoded text-white class in the commit
button’s cn configuration with the existing surface token used by the checkbox
indicator alongside --clinical-accent, using the corresponding Tailwind 4 `@theme`
token from globals.css so the foreground adapts to themed accent backgrounds.
- Around line 953-985: Update SegmentSwitch to remove the incomplete tablist/tab
roles and use a radiogroup-style contract for selecting one mode, preserving the
existing visual behavior and onChange flow. Align each option with the
component’s established single-choice accessibility pattern, such as the
existing aria-pressed or radiogroup semantics, without adding tab panels or
keyboard-navigation logic.
- Around line 232-243: Remove the unused skipGroup parameter from
maskForSelection and delete the related group-skipping branch, updating both
useFacetCounts call sites to match. Keep the implementation and anatomy prose
aligned with the existing candidate-addition counting behavior rather than
introducing the unused “other groups” strategy.
🪄 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: CHILL

Plan: Pro

Run ID: ef55859b-a3d0-4cb7-9cc4-c5119b81e3bb

📥 Commits

Reviewing files that changed from the base of the PR and between 1e461d5 and bff7050.

📒 Files selected for processing (6)
  • docs/branch-review-ledger.md
  • docs/site-map.md
  • mockups/README.md
  • src/app/mockups/mockups-layout-client.tsx
  • src/app/mockups/services-filter-refined/page.tsx
  • src/components/services-filter-refined-mockups.tsx

Comment thread src/components/services-filter-refined-mockups.tsx Outdated
Comment thread src/components/services-filter-refined-mockups.tsx
@BigSimmo

Copy link
Copy Markdown
Owner Author

Babysit snapshot (@2026-08-12)

  • Head: bff7050134fa1b7c8e3a832b43d70502254b46ab (pushed)
  • Merge state: MERGEABLE (GitHub reports mergeable), mergeStateStatus: BLOCKED while required checks were re-running at capture time.
  • Base sync: merged origin/main once into branch before re-running checks.
  • Merge-tree vs origin/main: clean (no conflict markers).
  • Required checks: pass (Build, Unit coverage, Static PR checks, Semgrep, Semgrep ingestion gate, Safety and config checks, PR policy, PR mergeability, PR required, Production UI (1/2/3), Production UI critical, Advisory UI, Lighthouse budget, Change scope, Gitleaks).

Dispositions

  1. Line 257 / thread r3760481466 — Fixed

    • Thread asked: sibling facet counts should show post-toggle value.
    • Fix: useFacetCounts now computes each facet count from selected + facet (single candidate set) instead of other-group-only base.
    • Committed in: bff7050134fa1b7c8e3a832b43d70502254b46ab
  2. Line 462 / thread r3760481473 — Fixed

    • Thread asked: preview rows should reflect live filter outcome/total.
    • Fix: ResultsPreview now renders up to the compact/full viewport row budget constrained by count, shows explicit empty state at zero, and keeps + remaining consistent.
    • Committed in: bff7050134fa1b7c8e3a832b43d70502254b46ab

No new PR-policy or clinical/RAG text changes were needed (design-scratch route only).

@BigSimmo

Copy link
Copy Markdown
Owner Author

Codex babysit sweep (review-and-fix)

Snapshot

Findings and fixes

  • Unresolved actionable threads at final check: 0
  • Fixed
    • PR thread PRRT_kwDOSh5Fis6YXKwP (src/components/services-filter-refined-mockups.tsx:487) — guard “+ 0 more” render for small result sets.
    • PR thread PRRT_kwDOSh5Fis6YXKwg (src/components/services-filter-refined-mockups.tsx:1236) — show subset counts in Direction C preview strip using current-selection intersections.
  • Both were responded with codex-thread-result markers and threads resolved.

Checks on this head

  • PR policy: pending
  • PR mergeability: pending
  • Change scope: pending
  • Semgrep: pending
  • Semgrep ingestion gate: pending
  • GitGuardian Security Checks: pass
  • Supabase Preview / optional/dispatch checks: skipping

Local proof

  • npm run format attempted, but prettier is not installed in this checkout.
  • npm run format push guard failure was also surfaced on the first push attempt; resolved by formatting-adjusting the modified lines manually and amending the commit.
  • Push completed to claude/filter-popup-design-mockups-x6sbjv with one sync commit and fix commit.

Ledger

  • Appended review record:
    • review-and-fix outcome fixed at head 44206f8fd78495606c55a22336860e646e8a110b

Merge left to you.

@github-actions

Copy link
Copy Markdown
Contributor

CI triage

CI failed on this PR. Automated classification of the 2 failed job(s):

  • Production UI (3)needs investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • PR requiredneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.

Compared with main CI run #9764 (cancelled).

Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger.

@BigSimmo

Copy link
Copy Markdown
Owner Author

Babysit snapshot — scope babysit

  • PR number: 1828
  • Head: 44206f8fd78495606c55a22336860e646e8a110b
  • GitHub merge state: MERGEABLE, MERGE state BEHIND
  • Ledger status before this sweep: NOT REVIEWED at this HEAD and scope
  • Scope reviewed: all files in this branch diff

Merge-tree / scope check

  • git merge-tree between this head and its merge base is clean (no conflicts in changed files).
  • Merge-state blockers now: Production UI (3) failure + PR required wrapper failure.

Required checks on tip

  • Build: pass
  • Static PR checks: pass
  • Production UI (1): pass
  • Production UI (2): pass
  • Production UI (3): fail
  • PR required: fail
  • Semgrep: pass
  • Safety and config checks: pass
  • Policy: pass

Findings / dispositions

  • No new high-confidence P0/P1/P2 issues found in changed implementation code.
  • Production UI (3) fails at tests/ui-tools.spec.ts:2318 (differententials compare queue launches presentation comparison): expected URL /differentials/presentations/acute-confusion-encephalopathy but remained on /differentials/compare?ids=wernicke-encephalopathy.
  • Existing threads on this PR are resolved (including prior codex-thread-result status updates).

Action taken

  • Appended review ledger for this PR at scope babysit with outcome dispositioned and recorded check outcomes + blocker.
  • No code changes made in this sweep.

Next step

  • PR is blocked only by PR required because Production UI (3) fails on the shared route contract in CI, which appears pre-existing to the services filter mockup diff.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new design-scratch mockup route (/mockups/services-filter-refined) to study three alternative “services filter” sheet directions (desktop + phone), including live facet counts derived from a compact bitmask index, plus documentation/sitemap updates to record the study.

Changes:

  • Add ServicesFilterRefinedMockupsPage with three filter-surface directions and a “today” reproduction/annotation.
  • Add the /mockups/services-filter-refined route and suppress shared mockups chrome for it.
  • Document the study in mockups/README.md and regenerate docs/site-map.md.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/components/services-filter-refined-mockups.tsx New mockup page implementing the three design directions, including live facet-count recomputation.
src/app/mockups/services-filter-refined/page.tsx New mockup route entrypoint and metadata.
src/app/mockups/mockups-layout-client.tsx Suppress shared mockup chrome for the new route.
mockups/README.md Records the new services filter surface study and its rationale/caveats.
docs/site-map.md Adds the new mockup route to the generated site map.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/components/services-filter-refined-mockups.tsx
Comment thread src/components/services-filter-refined-mockups.tsx
@BigSimmo

Copy link
Copy Markdown
Owner Author

Babysit snapshot (scope: babysit)

  • PR head: b2d667f186daf91d628fdf2706f2ae533c67aec4
  • Mergeable: MERGEABLE; mergeStateStatus: BEHIND
  • Ahead/behind vs origin/main: 66/0
  • Merge-tree at this head is clean.
  • Required checks at current head are passing (PR required ✅).

Actionable issues reviewed and fixed

  1. decodeMask truncation/padding risk: added strict length guard and simplified copy loop so malformed facet masks now fail loudly (Expected ${MASK_LENGTH} bytes...).
  2. SegmentSwitch accessibility semantics: replaced tab roles with a labeled control group and aria-pressed button state to match non-tab segmented switch behavior.

Required checks run locally

  • npm exec eslint src/components/services-filter-refined-mockups.tsx
  • npm exec vitest run tests/search-refine-adaptive-mockups.dom.test.tsx

Thread dispositions

  • On decodeMask thread (src/components/services-filter-refined-mockups.tsx:193), disposition: fixed at this head.
  • On SegmentSwitch thread (src/components/services-filter-refined-mockups.tsx:968), disposition: fixed at this head.
<!-- codex-thread-disposition:resolved -->
status: fixed
result: fixed
commit: b2d667f186daf91d628fdf2706f2ae533c67aec4
notes: Added strict base64 mask length check and exact-length decode assignment.
<!-- codex-thread-disposition:resolved -->
status: fixed
result: fixed
commit: b2d667f186daf91d628fdf2706f2ae533c67aec4
notes: Replaced SegmentSwitch tab roles/selected semantics with labeled button group + aria-pressed states.

Residual risk

  • No new merge blockers introduced in this fix set.

Merge left to you.

@BigSimmo

Copy link
Copy Markdown
Owner Author

Babysit PR summary

  • Tip: claude/filter-popup-design-mockups-x6sbjv at a858ea905a4f80dbdb0bd6d678d810d92f88381a
  • Base: main
  • Sync state: performed one explicit git merge refs/remotes/origin/main cleanup sync (one sync for behind-pristine branch)
  • Merge-tree vs origin/main: clean
  • Mergeability: MERGEABLE, but mergeStateStatus currently BLOCKED while some checks are still in progress
  • Review-thread state: no unresolved threads after resolving
    • PRRT_kwDOSh5Fis6YampA
    • PRRT_kwDOSh5Fis6YampS
  • Fixes applied:
    • src/components/services-filter-refined-mockups.tsx
      • decodeMask() now enforces exact MASK_LENGTH and throws on mismatch
      • SegmentSwitch now uses aria-pressed button semantics instead of tab semantics without a tabpanel
  • Checks:
    • npx prettier --check src/components/services-filter-refined-mockups.tsx
    • Local lint/typecheck could not run in this worktree (@typescript/typescript6 / eslint toolchain missing; pre-commit reported blocked)
    • gh pr checks currently in progress/pending for Semgrep checks; PR policy, PR mergeability, GitGuardian, Gitleaks passed during this sweep
  • Residual risk:
    • No remaining actionable findings on this PR; merge left to user, with CI checks still completing.

@BigSimmo

Copy link
Copy Markdown
Owner Author

Review sweep complete for PR #1828 (HEAD a858ea9).

  • Snapshot: HEAD is current and clean (CLEAN, mergeable), behind/behind: main is currently ahead by 7 and this branch by 6 according to git rev-list --left-right; merge-tree is clean against refs/remotes/origin/main.
  • Required checks: CI required path is green on this head (PR required, Safety and config, Unit coverage, Build, and Production UI (1/2/3) all pass).
  • Review threads: 0 unresolved actionable threads.
  • Fixes vs disposition: no high-confidence new defects found; no fix applied in this pass.
  • Local proof: gh pr checks 1828, review-thread snapshot (0 unresolved), npm run ledger:lookup -- a858ea905a4f80dbdb0bd6d678d810d92f88381a --scope babysit-pr, and eslint checks for changed mockup files via shared root tooling.
  • Residual risks: PR body already documents a pre-existing environment-only pr-handoff-stop test expectation (UID permission behavior). No additional actionable regressions were reproducible from this review pass.

@BigSimmo

Copy link
Copy Markdown
Owner Author

babysit summary

  • PR: feat(mockups): three directions for the services filter surface #1828
  • Tip: �858ea905a4f80dbdb0bd6d678d810d92f88381a
  • Mergeability snapshot: mergeable=MERGEABLE, mergeStateStatus=CLEAN, compare vs main shows �head_by: 9, �ehind_by: 0 (status=ahead)
  • Required checks on this tip: all required checks are green in the latest run.
  • Thread status: current actionable threads reviewed; no unresolved actionable thread remains on this head (prior review findings are already marked resolved on current state).
  • Fixes/actions taken: no code changes were required to clear merge blockers or required checks for this PR.
  • Ledger: appended review record for scope �abysit with outcome clean.
  • Residual: this branch remains clean and requires only normal merge governance by the repo when selected for integration.

@BigSimmo

Copy link
Copy Markdown
Owner Author

Babysit review summary

  • Snapshot: reviewed at GitHub head a858ea905a4f80dbdb0bd6d678d810d92f88381a (branch claude/filter-popup-design-mockups-x6sbjv, base main).
  • Merge state: CLEAN; mergeable MERGEABLE with no open threads (6 threads found, all resolved).
  • Required checks: all required and supporting checks passed or were skipped per expected scope; PR required, PR mergeability, PR policy, Static PR checks, Unit coverage, Build, and Production UI (1/2/3) are pass.
  • Disposition: clean review; no actionable defects found and no fixes pushed in this pass.
  • Existing ledger entry exists for this head at scope babysit; no superseding record needed unless scope changed.

Round one offered three directions. Asked which to build, the answer was
a sequence rather than a winner, plus one bolder move flagged as a
product judgement. This draws those three threads so they can be
compared directly, at desktop and phone.

- 1 · Stop the bleed (ship first) — no filtering at all. The sheet is
  renamed to what it is, each shortcut shows the literal query it will
  run, and the current search sits at the top as the thing you are about
  to lose. Today that loss is invisible until it has happened. The
  footer commits to "Keep <query>" rather than "Done". No new state, no
  facets, no new component, and nothing that has to be unpicked later.
- 2 · The recommendation — direction A's multi-select facets with live
  counts and a committed "Show N services", plus direction B's
  persistent active-filter pill row. Phone shows the sheet open, desktop
  shows it closed, because the closed state is what the pill row exists
  for.
- 3 · Presets evicted (your call) — the sheet becomes purely a filter
  and the presets move to the composer as AnswerSuggestionChips, a
  production component whose own prop docs name composer rows as a use.
  Deletes sheet code rather than adding a surface; the risk is product,
  not engineering. Both surfaces are shown together because the sheet
  alone would flatter the option.

The facet engine, chips, band and sheet shell are imported from the
round-one study rather than copied, so the ~1KB bitmask table is not
duplicated and the two pages cannot drift to different numbers for the
same catalogue. That reuse is why the whole second study costs 7.1 KiB
gzip against the mockups budget where the first cost 12.1 KiB.

Adds an optional maxHeight to PhoneSheetShell so a study can leave the
surface behind the sheet visible when that surface is part of the
argument.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011btGFwWKYFWDs5McQkqz9J
claude added 2 commits August 12, 2026 06:12
…ps-x6sbjv' into claude/filter-popup-design-mockups-x6sbjv

# Conflicts:
#	src/components/services-filter-refined-mockups.tsx
@BigSimmo
BigSimmo enabled auto-merge August 12, 2026 06:55
@BigSimmo
BigSimmo merged commit a73dccf into main Aug 12, 2026
26 checks passed
@BigSimmo
BigSimmo deleted the claude/filter-popup-design-mockups-x6sbjv branch August 12, 2026 07:20
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.

3 participants