Skip to content

feat(factsheets): add per-category counts; correct the eviction claim (PR D) - #1888

Merged
BigSimmo merged 5 commits into
mainfrom
claude/filter-contract-factsheets-pr-d
Aug 13, 2026
Merged

feat(factsheets): add per-category counts; correct the eviction claim (PR D)#1888
BigSimmo merged 5 commits into
mainfrom
claude/filter-contract-factsheets-pr-d

Conversation

@BigSimmo

Copy link
Copy Markdown
Owner

Summary

  • The correction, verified against the code before writing anything: an earlier rollout note said factsheets' category presets "replace the query" and must be evicted to the composer, the way formulation's Pattern group was evicted in PR feat(filters): make formulation a real facet surface #1858. That was false — searchHref(query, category) (src/components/factsheets/factsheets-search-page.tsx) preserves q and adds category. Factsheets never discarded the search; its category chips were never a navigate-kind contract violation, at either breakpoint. docs/filter-contract.md §1 corrected to say so plainly.
  • The design question the kickoff prompt asked me to answer before writing code: should the desktop category rail converge from real <Link> elements onto SegmentedControl, matching the four lens modes from PR feat(filters): adopt the lens contract across the four one-of-N modes #1857? Recommendation: no — keep the <Link> rail. Reasoning, recorded in full in docs/filter-contract.md §2: /factsheets/search is a genuine Next.js Server Component route — category is read from searchParams and filtered server-side before the client ever mounts (src/app/(search-app)/factsheets/search/page.tsx) — unlike every other lens mode, which filters an already-fetched client-side result set with useState. A real <a href> is the correct primitive for a server-driven route change (native prefetch, right-click/open-in-new-tab, works with zero JS), and SegmentedControl cannot render one. The back-button argument from the kickoff prompt turned out to be a wash (both <Link> and router.push push a history entry either way), but the hyperlink-semantics argument holds. This is recorded as a documented, narrow exception — not a precedent for any other mode to keep a bespoke rail.
  • Added per-query counts (option.hint) to both breakpoints from one shared categoryOptions array — the same "how many would I have if I picked this" predicate as the rest of the contract (§3), computed via the existing filterFactsheets(query, category) against the current query, not a static catalogue total (categoryCount, used on the factsheets home page's browse pills, answers a different question and was deliberately not reused here).
  • At 4 options this stays in §5's chips band — /issues #309's density decision does not bind here (confirmed: it doesn't, and is resolved anyway per the note below).

Verification

  • npm run verify:pr-local — full run, all green: 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, test, build, check:rag:fixtures.
  • npm run check:bundle-budget after a clean rm -rf .next && npm run build — production 1305.0 KiB gzip (baseline 1279.1 KiB, within the 10% tolerance), mockups 294.5 KiB gzip (baseline 267.5 KiB, within the 25% tolerance).
  • npm run verify:ui cannot run in this environment (/issues #255 — Playwright wants chromium-1234, only chromium-1194 installed). Proved UI directly: a Playwright script from the repo root with executablePath: "/opt/pw-browsers/chromium-1194/chrome-linux/chrome" against a real dev server — desktop rail renders a real <a href> with the correct aria-label="Medications (1)" for q=sertraline, clicking it preserves q and adds category, the phone sheet shows the same counts and preserves q on selection, 0px horizontal overflow at 1440/800/390/320. 11/11 checks passed.
  • Grepped for aria-label strings, not just component/testid names, per this rollout's own stated trap (it broke Playwright specs twice already in ui-formulation.spec.ts/ui-specifiers.spec.ts): found one real hit — tests/ui-smoke.spec.ts's existing factsheet test asserted getByRole("radio", { name: "All" }), which now reads "All (1)" for the q=sertraline query it uses. Updated and re-ran against a real production build via node scripts/run-playwright.mjs tests/ui-smoke.spec.ts --project=chromium --grep "factsheet search keeps query and category filters" with the same executable override — passes.
  • Full npx vitest run after merging origin/main in: Test Files 564 passed (564) / Tests 6159 passed | 4 skipped (6163).

Risk and rollout

  • Risk: low. Pure UI change to one already-correct filter surface plus a documentation correction; no data, API, auth, or Supabase surface touched. classifyPullRequestFiles returns clinicalRisk: false, operationalRisk: false, ragRanking: false for this diff.
  • Rollback: revert the single squash commit.
  • Provider or production effects: None.

Notes

  • /issues #170 (the rollout-tracking row) updated via npm run issues:update to correct its own prior "factsheets: evict category presets" claim and record current state across PR C (open, feat(services): adopt the filter contract with real facets (PR C) #1882) and this PR.
  • This branch was based on origin/main before PR C merged, so its copy of docs/filter-contract.md does not yet reflect PR C's services-specific edits (the density-tier §5 rewrite) or PR C's own correction to the services half of the navigate-kind paragraph in §1 — only this PR's factsheets-specific correction. Those will reconcile normally at merge time since PR C and this PR touch different paragraphs of the same file.

Generated by Claude Code

claude added 2 commits August 12, 2026 21:11
… (PR D)

The earlier rollout notes said factsheets' category presets replace
the query and must be evicted to the composer, the way formulation's
Pattern group was. That was wrong: searchHref(query, category)
preserves q and adds category, so factsheets never discarded the
search and its category chips were never a navigate-kind violation.
docs/filter-contract.md corrected to say so.

Kept the desktop rail as real <Link> elements rather than converging
it to SegmentedControl: /factsheets/search is a genuine Next.js
Server Component route (category read from searchParams, filtered
server-side), unlike every other lens mode's client-state-only rail,
so a real anchor is the correct primitive and SegmentedControl cannot
render one. Recorded as a documented exception in docs/filter-contract.md
§2, the same way §4 documents the scope-segment exclusions.

Added per-query counts (the same "how many would I have if I picked
this" predicate as the rest of the contract, not a static catalogue
total) to both the desktop rail and the phone sheet via one shared
options array. Updated the one existing Playwright assertion whose
accessible name changed as a result ("All" -> "All (1)").

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

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

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: 42 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: 22723c95-8c38-4e2c-a97b-25a91c7e674d

📥 Commits

Reviewing files that changed from the base of the PR and between 67db5a1 and 3749e14.

📒 Files selected for processing (2)
  • docs/branch-review-records/33f8fcf0543655449bf077fbb7595b849f39599f7d54238755ee9a649967f25a.record.md
  • docs/branch-review-records/770c855f8ddb79707f4ddb49b266ea1f4d27795aa33fcc02f099586e423c15b2.record.md

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

@supabase

supabase Bot commented Aug 12, 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 ↗︎.

@BigSimmo
BigSimmo enabled auto-merge August 12, 2026 21:23
@BigSimmo
BigSimmo disabled auto-merge August 12, 2026 21:25
@BigSimmo
BigSimmo enabled auto-merge August 12, 2026 21:25

Copy link
Copy Markdown
Owner Author

@claude This PR is currently mergeable_state: dirty against current main at head f8930c36d11a15820bd0a76aa6b4ff24928db224, with no unresolved review threads. Fetch current main and merge it into this PR branch without rebasing or force-pushing. Resolve only the merge conflicts, preserving the factsheets server-route hyperlink/count design and all newer main changes. Run conflict-adjacent format/typecheck plus focused factsheet filter/browser tests, push the merge-resolution commit, and report the pushed SHA and verification. Do not merge or close the PR, deploy, alter auto-merge, or broaden scope.

@github-actions

Copy link
Copy Markdown
Contributor

Hi @BigSimmo — thanks for the @claude mention.

Open this in Claude Code on the web to continue here: https://claude.ai/code

Context: BigSimmo/Database · #1888

Automated backlink from the Claude backlink workflow. Claude Code can pick up the mention and push a scoped fix to the branch.

@claude

claude Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 2s —— View job


I'll analyze this and get back to you.

@BigSimmo
BigSimmo disabled auto-merge August 12, 2026 21:50
@BigSimmo
BigSimmo enabled auto-merge August 12, 2026 21:53
@BigSimmo
BigSimmo disabled auto-merge August 12, 2026 22:05
@BigSimmo
BigSimmo enabled auto-merge August 12, 2026 22:07
@BigSimmo
BigSimmo disabled auto-merge August 12, 2026 22:49
@BigSimmo
BigSimmo enabled auto-merge (squash) August 12, 2026 23:07
@BigSimmo
BigSimmo disabled auto-merge August 12, 2026 23:17
@BigSimmo
BigSimmo enabled auto-merge August 12, 2026 23:37
@BigSimmo
BigSimmo disabled auto-merge August 12, 2026 23:51
@BigSimmo
BigSimmo enabled auto-merge August 13, 2026 00:07
@BigSimmo
BigSimmo disabled auto-merge August 13, 2026 00:17
@BigSimmo
BigSimmo enabled auto-merge August 13, 2026 00:37
@BigSimmo
BigSimmo disabled auto-merge August 13, 2026 01:07
@BigSimmo
BigSimmo enabled auto-merge August 13, 2026 01:37
@BigSimmo
BigSimmo disabled auto-merge August 13, 2026 01:59
@BigSimmo
BigSimmo enabled auto-merge (squash) August 13, 2026 02:07
Resolve PR #1888 against current main by retaining the newer factsheets filter implementation, contract, tests, and shared ledgers. Migrate the branch-added legacy review row and record the fresh adversarial review as immutable ledger entries.
@BigSimmo
BigSimmo merged commit 0709965 into main Aug 13, 2026
24 checks passed
@BigSimmo
BigSimmo deleted the claude/filter-contract-factsheets-pr-d branch August 13, 2026 02:42

Copy link
Copy Markdown
Owner Author

Final review-and-fix summary

Final state

  • Reviewed PR head: 3749e144f14c35936449391d3816e86ecefa52b6.
  • Base used for the required sync: main at 67db5a1d5ada98bbd22cc386ca6ea373b693107a.
  • Sync commit: 3749e144f14c35936449391d3816e86ecefa52b6, a true merge commit with first parent f8930c36d11a15820bd0a76aa6b4ff24928db224 and second parent 67db5a1d5ada98bbd22cc386ca6ea373b693107a; no rebase, force-push, history rewrite, deployment, release, or auto-merge change was performed.
  • The post-sync merge tree was clean and GitHub reported the PR mergeable against the current base.
  • The pre-existing auto-merge setting subsequently squashed the PR automatically at 0709965e66e04173ec0b0de1d121e85ac1ff7e04 on main at 2026-08-13 02:42:56 UTC. The squash commit has the reviewed tree e6a6225033ca008f94f76d93d78a54b29068028c.

Review outcome and conflict dispositions

  • Resolved the dirty merge state by retaining current main for all five conflicted PR files. Current main already had the newer shared counted SegmentedControl, selected zero-result/dead-end handling, dedicated factsheets DOM coverage, the updated filter contract, and broader UI-smoke changes. Restoring the PR's older raw-link rail or older test/docs versions would have regressed those newer contracts.
  • Final delta against the synced base was intentionally limited to two immutable ledger records:
  • No high-confidence PR-introduced P0, P1, or reproducible P2 defect remained after the current-main conflict resolution.
  • Pre-existing item left out of scope: the current-main wording of outstanding-issues row #170 remains a separate canonical-ledger tracking concern. The PR's proposed wording was itself stale relative to the newer implementation, so it was not copied into the shared queue during this conflict-only sync.

Adversarial review and comments

  • CodeRabbit did not provide an independent review because the repository review/spending limit was reached. A separate manual adversarial pass challenged correctness, regression risk, compatibility/accessibility, security/privacy, false positives, test coverage, and shared-ledger concurrency.
  • Result: no actionable P0-P2 finding. The final two-file record-only diff has no application, clinical, RAG/ranking, authentication, migration, payment, deployment, or provider-backed runtime surface.
  • Final inline review threads: 0; nothing remained to reply to or resolve.
  • Existing top-level CodeRabbit and Supabase comments were informational. The owner conflict-resolution request was satisfied.

Decisive verification

  • Proposed-tree falsification: comparing 67db5a1d5ada98bbd22cc386ca6ea373b693107a to 3749e144f14c35936449391d3816e86ecefa52b6 showed exactly two added immutable record files and no other tree delta.
  • Local structural check: both record filenames matched the SHA-256 of their exact UTF-8 row content; each record had six cells, a valid date, and a full 40-character reviewed HEAD.
  • No full repository checkout was available in this connector session, so no local npm command was represented as run. Exact-head hosted CI supplied the repository-native substitute evidence.

Exact-head required CI

For 3749e144f14c35936449391d3816e86ecefa52b6:

  • PR required: success.
  • Static PR checks: success, including runtime alignment, installed-lock parity, branch-review ledger integrity, outstanding-issues integrity, ledger write discipline, codebase-index coverage, docs inventory/scripts/links, changed-file formatting, and sitemap drift.
  • SAST: success (Semgrep ingestion gate and Semgrep).
  • Secret Scan: success (Gitleaks).
  • Missing required checks: none.
  • Pending required checks: none.
  • Failed required checks: none.
  • Unexpectedly skipped required checks: none.
  • Production UI critical, Production UI, Build, Unit coverage, migration replay, safety/config, typecheck, and lint were conditionally skipped because classification reduced the final PR delta to documentation review-record files; the required aggregate accepted that scope.

Advisory checks and residual risk

  • Advisory UI, visual baselines, Lighthouse budget, and release browser matrix were skipped as out of scope for the two-file documentation delta.
  • Supabase preview was ignored because no supabase/ file changed.
  • Residual risk is limited to the absence of a completed CodeRabbit pass and the pre-existing #170 tracking wording; neither affects the merged application tree.

The requested closing statement — “The PR was not merged. Final merge is left to the user.” — is no longer factually applicable. I did not manually merge or close the PR, but GitHub's pre-existing auto-merge merged it automatically after the required checks passed.

Copy link
Copy Markdown
Owner Author

@claude Please main-sync this PR from exact head f8930c36d11a15820bd0a76aa6b4ff24928db224: merge the latest main once (never rebase), resolve all conflicts minimally, commit and push. Do not merge/close the PR, force-push, alter auto-merge, or touch unrelated files.

The current PR delta appears to contain only immutable branch-review record files because the substantive Factsheets filter-count work has already converged elsewhere. Preserve current main entirely and retain only valid, non-duplicate immutable records that still truthfully describe this exact review. If the feature delta is empty after the merge, leave the PR open and report that fact rather than manufacturing changes or deleting history.

Run branch-review ledger integrity/dedupe/write-discipline and the smallest docs/format check. Report the new head, resulting changed-file delta, and exact outcomes.

@github-actions

Copy link
Copy Markdown
Contributor

Hi @BigSimmo — thanks for the @claude mention.

Open this in Claude Code on the web to continue here: https://claude.ai/code

Context: BigSimmo/Database · #1888

Automated backlink from the Claude backlink workflow. Claude Code can pick up the mention and push a scoped fix to the branch.

@claude

claude Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 2s —— View job


I'll analyze this and get back to you.

BigSimmo added a commit that referenced this pull request Aug 22, 2026
… drop an assertion I got wrong

The sort comment claimed a total order that the real corpus contradicts: 21
records share a date, ref and head, because one branch can be reviewed twice at
one commit under different scopes. Scope is now a fourth key, and the comment
states what actually carries determinism — a filename-sorted input and a stable
sort — rather than claiming the comparator does it alone.

Task 12's React key was heading for the same trap, identifying a row by fields
that are only incidentally unique. It now carries the index.

The corpus test gains power over scope and outcome, which it previously never
referenced at all.

Removed: an assertion I specified that refs never contain a space. The
implementer refused it with evidence and was right — 106 of the 454 refs
legitimately contain spaces, in forms like 'PR #1888 (claude/...)'. I verified
that against the corpus before accepting the refusal. The reasoning is recorded
in the plan so the idea is not retried.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

2 participants