Skip to content

Admin: staff pages for role holders only, one Renewals page, Sharing inside Requests - #3462

Merged
gitar-bot[bot] merged 16 commits into
mainfrom
claude/admin-role-access-k6ghqt
Oct 11, 2026
Merged

gitar-bot[bot] merged 16 commits into
mainfrom
claude/admin-role-access-k6ghqt

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

User description

Requested by Josh · project thread

Summary

Before: signed-out visitors saw Hospital and People and roles and hit a sign-in dead end; Workforce was an unguarded sample shown to every doctor; Renewals, Compliance and Documents listed the same requirements; Sharing said "Not live yet"; Numbers showed an empty Support card and repeated its On site items.

After: staff-only pages show only to role holders (or with example data switched on); Workforce redirects to Hospital, whose Medical Workforce section is the live version; Compliance is Renewals' "By group" view with its Export; Sharing is Requests' "Send a pack" view; Numbers drops the empty card and duplicate tiles; Day one check points to the real sharing switch in New job.

How: one gate change in use-work-frame-gate-open.ts, Admin menu entries in areas.ts, and the old Compliance, Sharing and Workforce routes become redirects (allowlisted in route reachability). Mode navigation gains an audience: "administrators" option, not yet applied: Therapy's Review tab stays visible until the owner's account carries the site administrator role, because hiding it now would hide it from the owner too. The Renewals and Requests merge was approved by Josh from real-app screenshots on 11 Oct 2026 (usefulness and layout audit, items 1 and 4).

Areas touched: Personal practice, App experience, Design system, Prototypes

Verification

  • Checks run: npm run test:focused on every changed file: Tests 2901 passed (2901); tests/mode-secondary-navigation.test.ts after the Review change: Tests 59 passed (59). ESLint on changed files and tsc --noEmit clean. Real-app screenshots at 320, 390 and 1440 px in container Chromium (focused visual check only; the browser suite is left to CI).

Risk and rollout

  • Risk: low. No database, role-policy or provider change; access is still checked on the server for every staff page. Signed-in readers without a role lose nothing they had: the hospital gates already closed for them before this change.
  • Rollback: revert this PR.
  • Provider or production effects: None.

Notes

  • Documents stays its own page for now: folding it into each renewal needs its records matched to renewal items.
  • Granting the first roles still needs Josh's own account marked as site administrator (a Supabase account setting, not in this PR).

🤖 Generated with Claude Code

https://claude.ai/code/session_01VRAKeUNKFmnQHMbMmnHWDW


CodeAnt-AI Description

Bring Admin renewals and sharing together, while limiting staff-page visibility

What Changed

  • Renewals now includes Soonest, By group (the former Compliance view), and Personal. Older Compliance links open By group, with the export still available.
  • Requests now includes Send a pack. Older Sharing links open that view, which explains that you save the pack or open an email draft and send it yourself.
  • Hospital and People and roles are hidden from menus for signed-out users and signed-in users without hospital roles; example data still opens them. Workforce links now lead to Hospital’s Medical Workforce section.
  • Help is labeled Numbers. The empty Support section and duplicate On site tiles are removed, and day-one sharing guidance points to the switch in New job.

Impact

✅ Renewals and compliance in one place
✅ Send-a-pack options alongside tracked requests
✅ Fewer dead-end visits to staff pages

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

…e, tidy Numbers

Hospital and People and roles no longer show to signed-out visitors (example data
switched on still opens them). Workforce redirects to Hospital, whose Medical
Workforce section is the live version. Sharing leaves Admin's menu while not live.
Therapy's Review tab shows only to the site administrator or on its own page.
Numbers drops the empty Support card and the duplicate On site tiles. Day one
check points to the real sharing switch in New job.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRAKeUNKFmnQHMbMmnHWDW
Compliance becomes Renewals' By group view (Soonest / By group / Personal), with
its Export and before-your-next-job list; /admin/compliance redirects there.
Renewals' at-a-glance counts become four compact tiles. Sharing becomes Requests'
"Send a pack" view and says plainly that you send it yourself; /admin/sharing
redirects there. Admin's menu drops Compliance and Export and leads with Requests.
Approved by Josh from real-app screenshots on 11 Oct 2026.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRAKeUNKFmnQHMbMmnHWDW
@supabase

supabase Bot commented Oct 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 ↗︎.

@BigSimmo BigSimmo self-assigned this Oct 11, 2026
@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 0cf51f80-7e6d-4fbd-912c-59fd7c531569

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@BigSimmo
BigSimmo marked this pull request as ready for review October 11, 2026 09:34
@codeant-ai

codeant-ai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Incremental review completed b5127e4 Oct 11, 2026 · 13:51 13:52
✅ Incremental review completed 619efb1 Oct 11, 2026 · 12:40 12:41
✅ Reviewed your PR 1f11df4 Oct 11, 2026 · 09:35 09:40

@codeant-ai

codeant-ai Bot commented Oct 11, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@greptile-apps greptile-apps 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.

BigSimmo has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-11T09:40:13.777026Z 1f11df4 Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Claude encountered an error after 2s —— View job


I'll analyze this and get back to you.

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Oct 11, 2026
…inistrator

Hiding it now would hide it from the owner as well, since no account carries the
site administrator role yet. The administrators audience stays ready to switch on.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRAKeUNKFmnQHMbMmnHWDW
@codeant-ai

codeant-ai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

🏁 CodeAnt Quality Gate Results

Commit: b5127e44
Scan Time: 2026-10-11 13:52:21 UTC

✅ Overall Status: PASSED

Quality Gate Details

Quality Gate Status Details
Secrets ✅ PASSED 0 secrets found
Duplicate Code ✅ PASSED 0.0% duplicated
SAST ✅ PASSED No security issues
Bugs ✅ PASSED Rating S: No bugs
IAC ✅ PASSED Rating S: No issues

View Full Results

@codspeed

codspeed Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ 2 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

✅ 8 untouched benchmarks


Comparing claude/admin-role-access-k6ghqt (b5127e4) with main (93e9ad6)

Open in CodSpeed

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Admin: gate staff pages to role holders, merge Renewals/Compliance and Requests/Sharing

🐞 Bug fix ✨ Enhancement 🕐 40+ Minutes

Grey Divider

AI Description

• Hides hospital-role Admin pages from signed-out visitors and non-role doctors instead of letting
 them hit a sign-in dead end.
• Retires the Workforce sample (redirects to Hospital) and hides Therapy's sign-off Review tab
 behind a new audience: "administrators" nav flag.
• Merges Compliance into Renewals as a new "By group" tab, and Sharing into Requests as a "Send a
 pack" tab; old routes redirect and are allowlisted in route reachability.
• Cleans up Numbers (Admin Help) page: drops the empty Support card and duplicate On-site glance
 tiles.
• Points Day one check's sharing signpost at the real New job sharing switch instead of the old
 Sharing page.
Diagram

graph TD
  Visitor["Visitor/Doctor"] --> Gate["useWorkFrameGateOpen"] --> Nav["Admin menu areas.ts"]
  Nav --> Renewals["Renewals page"] --> ByGroup["ComplianceByGroup view"]
  Nav --> Requests["Requests page"] --> SendPack["SharingBody view"]
  OldCompliance["/admin/compliance"] -.redirect.-> Renewals
  OldSharing["/admin/sharing"] -.redirect.-> Requests
  OldWorkforce["/admin/workforce"] -.redirect.-> Hospital["Hospital page"]
  Nav --> ReviewTab["Therapy Review tab"]
  AdminRole["Site administrator"] -.audience administrators.-> ReviewTab

  subgraph Legend
    direction LR
    _page["Page"] ~~~ _redir["Redirect"]
  end
Loading
High-Level Assessment

Reusing the existing view components (ComplianceByGroup, SharingBody) as embedded sub-views inside Renewals and Requests, with old routes kept as redirects, is the right low-risk approach: it avoids duplicating business logic, preserves bookmarks/search results via redirects, and keeps server-side role checks unchanged. No architecturally different approach offers meaningfully better tradeoffs here.

Files changed (30) +441 / -349

Enhancement (8) +260 / -171
mode-secondary-navigation.tsAdd administrators audience to secondary nav entries +17/-5

Add administrators audience to secondary nav entries

• Introduces an 'audience: 'administrators'' option alongside 'editors', filtered out of nav lists unless 'isAdministrator' is passed; used to hide Therapy's Review tab.

src/lib/mode-secondary-navigation.ts

registry-mode-nav.tsxHide administrator-only nav entries from non-administrators +5/-1

Hide administrator-only nav entries from non-administrators

• Reads the signed-in user's administrator status and filters secondary nav entries so an administrators-only tab shows only to the site administrator or when already active.

src/components/mode-nav/registry-mode-nav.tsx

admin-compliance-export-page.tsxBreadcrumb label updated to Renewals +1/-1

Breadcrumb label updated to Renewals

• Changes the breadcrumb home label from 'Compliance' to 'Renewals' to match the merged navigation.

src/components/admin/admin-compliance-export-page.tsx

admin-renewals-page.tsxAdd By group tab to Renewals, embedding ComplianceByGroup +26/-5

Add By group tab to Renewals, embedding ComplianceByGroup

• Adds a third 'By group' tab (Soonest/By group/Personal) that reuses 'ComplianceByGroup', supports '?view=group' deep links, and preserves the active view when opening item details.

src/components/admin/admin-renewals-page.tsx

sharing-page.tsxExtract SharingBody for embedding in Requests +68/-42

Extract SharingBody for embedding in Requests

• Splits Sharing into a reusable 'SharingBody' (with an 'embedded' mode that drops page chrome) and updates copy from 'Not live yet' to 'You send it yourself'.

src/components/work-screens/admin/sharing-page.tsx

requests-page.tsxAdd Send a pack tab embedding Sharing into Requests +123/-108

Add Send a pack tab embedding Sharing into Requests

• Adds a 'Send a pack' tab that renders the embedded 'SharingBody', supports landing via '#send' hash, and drops the standalone Sharing related-link row.

src/components/work-screens/admin/requests-page.tsx

page.tsxUpdate page metadata title to Numbers +1/-1

Update page metadata title to Numbers

• Changes the route's page title from 'Help' to 'Numbers' to match the renamed page.

src/app/(search-app)/admin/help/page.tsx

admin-work.module.cssRestyle Renewals glance tiles into a 4-column grid +19/-8

Restyle Renewals glance tiles into a 4-column grid

• Reworks the at-a-glance counts layout from a tall list into four compact, centered tiles for narrow screens.

src/components/admin/admin-work.module.css

Bug fix (3) +37 / -38
use-work-frame-gate-open.tsHospital-role gate no longer opens for signed-out visitors +3/-1

Hospital-role gate no longer opens for signed-out visitors

• Removes '!signedIn' from the hospital-role gate condition so hospital screens stay hidden from signed-out visitors unless example data is on.

src/components/work-frame/use-work-frame-gate-open.ts

admin-help-page.tsxDrop empty Support card and duplicate On-site glance tiles +25/-33

Drop empty Support card and duplicate On-site glance tiles

• Renames the page to 'Numbers', removes the Support section/chip when no rows exist, and removes the duplicate On-site glance tiles above the full list.

src/components/admin/admin-help-page.tsx

ready-for-day-one-page.tsxPoint sharing signpost at New job instead of old Sharing page +9/-4

Point sharing signpost at New job instead of old Sharing page

• Updates the Day one check's sharing notice copy and link to point to New job's sharing switch instead of the retired '/admin/sharing' page.

src/components/admin/ready/ready-for-day-one-page.tsx

Refactor (7) +99 / -100
areas.tsAdmin menu drops Compliance, Export, Sharing, Workforce entries +3/-20

Admin menu drops Compliance, Export, Sharing, Workforce entries

• Removes Compliance, Export, Sharing and Workforce items from the Admin menu, leading with Requests, since their routes now redirect into merged views.

src/lib/work-frame/areas.ts

page.tsxCompliance route redirects to Renewals By group +4/-9

Compliance route redirects to Renewals By group

• Replaces the standalone Compliance page with a redirect to 'ADMIN_PAGE_HREFS.compliance', now pointing at Renewals' By group view.

src/app/(search-app)/admin/compliance/page.tsx

page.tsxSharing route redirects to Requests Send a pack +4/-9

Sharing route redirects to Requests Send a pack

• Replaces the standalone Sharing page with a redirect to Requests' '#send' hash view.

src/app/(search-app)/admin/sharing/page.tsx

page.tsxWorkforce route redirects to Hospital +8/-16

Workforce route redirects to Hospital

• Retires the Workforce sample page in favor of a redirect to the Hospital hub, whose Medical Workforce section is the live equivalent.

src/app/(search-app)/admin/workforce/page.tsx

admin-compliance-page.tsxExtract ComplianceByGroup for reuse in Renewals +58/-40

Extract ComplianceByGroup for reuse in Renewals

• Splits the compliance view into a reusable 'ComplianceByGroup' component and keeps 'AdminCompliancePage' as a thin wrapper for its own route/tests.

src/components/admin/admin-compliance-page.tsx

pages.tsMerge Compliance/Export search keywords into Renewals and Requests +19/-3

Merge Compliance/Export search keywords into Renewals and Requests

• Folds the retired Compliance and Export search entries' keywords into 'admin:renewals' and adds sharing-related keywords to 'admin:admin-requests'.

src/lib/work-search/pages.ts

preview-role.tsPreview role screen updated from Workforce to Hospital +3/-3

Preview role screen updated from Workforce to Hospital

• Replaces the retired Workforce preview-role screen entry with a Hospital entry pointing at the Medical Workforce section.

src/lib/preview-role/preview-role.ts

Tests (8) +39 / -35
route-reachability.test.tsAllowlist redirected admin routes +12/-0

Allowlist redirected admin routes

• Adds '/admin/sharing', '/admin/compliance' and '/admin/workforce' to the reachability allowlist as documented redirects.

tests/route-reachability.test.ts

mode-secondary-navigation.test.tsTest administrator audience filtering and Therapy Review hiding +10/-2

Test administrator audience filtering and Therapy Review hiding

• Updates the editor-filter test to pass 'isAdministrator: true' and adds a case confirming Therapy's Review tab is hidden from non-administrators.

tests/mode-secondary-navigation.test.ts

admin-help-page.dom.test.tsxUpdate tests for dropped Support card and glance tiles +8/-25

Update tests for dropped Support card and glance tiles

• Replaces assertions expecting the Support empty state and On-site glance tiles with assertions that they are absent.

tests/admin-help-page.dom.test.tsx

admin-new-job-page.dom.test.tsxUpdate expected Compliance signpost href +1/-1

Update expected Compliance signpost href

• Updates the expected href for the paperwork signpost to the new Renewals By group URL.

tests/admin-new-job-page.dom.test.tsx

admin-starter-ready-pages.dom.test.tsxUpdate expected sharing link href on Day one check +1/-1

Update expected sharing link href on Day one check

• Updates the expected href of the sharing link to point at New job instead of the retired Sharing page.

tests/admin-starter-ready-pages.dom.test.tsx

on-call-routes.dom.test.tsxUpdate Renewals tab label expectations +2/-2

Update Renewals tab label expectations

• Updates assertions to expect the renamed 'Soonest' radio label instead of 'Checklist'.

tests/on-call-routes.dom.test.tsx

work-screens-admin-pages.dom.test.tsxUpdate Sharing page copy assertions +2/-2

Update Sharing page copy assertions

• Updates the expected 'Not live yet' text assertion to the new 'PsychSift never sends it for you' copy.

tests/work-screens-admin-pages.dom.test.tsx

work-search-smart.test.tsUpdate search result hrefs for merged Compliance +3/-2

Update search result hrefs for merged Compliance

• Updates expected search result hrefs for 'export' and 'fit test' queries to point at '/admin/renewals'.

tests/work-search-smart.test.ts

Documentation (2) +2 / -3
COMPONENTS.mdUpdate Sheet usage count in component inventory +1/-1

Update Sheet usage count in component inventory

• Decrements the generated usage count for the 'Sheet' component from 137 to 136.

docs/design-system/COMPONENTS.md

adoption-manifest.jsonRemove retired workforce-page entry from adoption manifest +1/-2

Remove retired workforce-page entry from adoption manifest

• Removes the deleted 'workforce-page.tsx' reference and clears a sanctioned-pattern entry in the generated manifest.

docs/design-system/adoption-manifest.json

Other (2) +4 / -2
page-hrefs.tsCompliance href now points at Renewals By group view +2/-1

Compliance href now points at Renewals By group view

• Changes the 'compliance' href constant to '/admin/renewals?view=group'.

src/lib/admin/page-hrefs.ts

hrefs.tsSharing href now points at Requests Send a pack view +2/-1

Sharing href now points at Requests Send a pack view

• Changes the 'sharing' href constant to '/admin/requests#send'.

src/lib/work-screens/admin/hrefs.ts

@qodo-code-review

Copy link
Copy Markdown
Contributor

Qodo Fixer

No findings are available for this PR yet. Findings appear here once Qodo has reviewed the PR.

@gitar-bot
gitar-bot Bot enabled auto-merge (squash) October 11, 2026 09:38
gitar-bot[bot]
gitar-bot Bot previously approved these changes Oct 11, 2026

@gitar-bot gitar-bot 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.

Gitar has auto-approved this PR (configure)

@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: 1f11df418c

ℹ️ 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/lib/mode-secondary-navigation.ts Resolved
@qodo-code-review

qodo-code-review Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

No findings for this group


Remediation recommended

No findings for this group


Informational

No findings for this group

Grey Divider


Resolved findings

1. Done switches back to Open ✗ Dismissed
Description
The viewParam !== seenView branch calls setChosenTab("open") when ?view=send disappears, even
when setTab("done") removed it after the reader selected Done. Starting from a Sharing link,
clicking Done triggers router.replace to the bare pathname, and the ensuing URL update replaces
the Done selection with Open.
Code

src/components/work-screens/admin/requests-page.tsx[142]

+    else if (seenView === "send") setChosenTab("open");
Relevance

●●● Strong

Accepted patterns prioritize fixing stale URL/local state transitions and adding regression coverage
for navigation changes.

PR-#3201
PR-#2184

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The Done chip calls setTab("done"), which removes ?view=send through router.replace; when
viewParam changes from send to null, the URL-sync branch calls setChosenTab("open") and
overrides the locally selected tab. The frontend-architecture-review skill warns against duplicating
URL state in local React state, and the new DOM test does not cover this click-and-navigation
sequence because it changes search parameters directly while its router replacement is a no-op.

src/components/work-screens/admin/requests-page.tsx[137-149]
tests/work-screens-admin-pages.dom.test.tsx[189-210]
src/components/work-screens/admin/requests-page.tsx[136-149]
src/components/work-screens/admin/requests-page.tsx[305-318]
tests/work-screens-admin-pages.dom.test.tsx[19-26]
Skill: frontend-architecture-review

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Leaving Send for Done removes `?view=send`, but URL synchronization then overrides the reader’s Done selection with Open.

## Fix Focus Areas
- src/components/work-screens/admin/requests-page.tsx[137-149]
- tests/work-screens-admin-pages.dom.test.tsx[189-210]

## Recommended Fix
Distinguish query removal initiated by a tab click from navigation to the plain Requests URL. Preserve the explicitly clicked Open or Done tab in the former case, while keeping Open as the default for a later visit to the plain URL. Add a test that starts at `?view=send`, clicks Done, applies the resulting router URL change, and confirms Done remains selected.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Sharing links miss their view ✓ Resolved
Description
AdminRequestsPage lets chosenTab override the URL’s #send hash, listens only for hashchange,
and does not update the hash when a tab is clicked. After a reader leaves Send for Open or Done,
refreshing the unchanged URL reopens Send, while navigating back to a Sharing link with Requests
still mounted may not select Send even if a hash-change event fires.
Code

src/components/work-screens/admin/requests-page.tsx[R141-143]

+  const landedOnSend = useSyncExternalStore(subscribeHash, readHashIsSend, () => false);
+  const [chosenTab, setTab] = useState<"open" | "done" | "send" | null>(null);
+  const tab = chosenTab ?? (landedOnSend ? "send" : "open");
Relevance

●●● Strong

Hash-driven navigation and stale state are established correctness concerns; the local tab state
clearly overrides linked URLs.

PR-#3201

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The Sharing destination uses #send, but Requests derives the linked view from a hashchange
listener while giving locally selected React state precedence over the hash. Its tab handlers change
only React state, so a tab click can leave #send in the URL, and subsequent navigation to that
hash cannot reliably restore the linked view.

src/components/work-screens/admin/requests-page.tsx[124-143]
src/lib/work-screens/admin/hrefs.ts[3-5]
src/lib/work-screens/admin/hrefs.ts[3-6]
src/components/work-screens/admin/requests-page.tsx[291-311]
Skill: frontend-architecture-review

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Send a pack deep link and the selected Requests tab can disagree after tab clicks or navigation while Requests remains mounted. A stale `#send` URL can reopen Send on refresh, while a Sharing link can fail to select it.

## Fix Focus Areas
- src/components/work-screens/admin/requests-page.tsx[124-143]
- src/components/work-screens/admin/requests-page.tsx[291-311]
- src/lib/work-screens/admin/hrefs.ts[3-5]

## Recommended Fix
Use router-observable URL state to select Send when the URL changes while Requests remains mounted, even after another tab has been chosen. Update or clear the hash when selecting another tab, preserve existing Sharing bookmarks, and add regression coverage for selecting Done before following a Sharing link, refreshing after a tab change, and same-page deep-link navigation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Old compliance links can regress silently ✓ Resolved
Description
The new browser scenario navigates directly to /admin/renewals?view=group instead of requesting
/admin/compliance, so it never exercises the redirect it claims to cover. A regression in the
retired route could leave existing bookmarks on the old page while this test still passes because
the destination view remains healthy.
Code

tests/ui-admin.spec.ts[R72-74]

+    await page.goto("/admin/renewals?view=group");
+    await expect(page.getByRole("radio", { name: "By group" })).toBeChecked();
+    await expect(visibleByTestId(page, "admin-compliance-group-registration")).toBeVisible();
Relevance

●●● Strong

Accepted precedents strengthen browser tests to exercise actual navigation and verify
redirect-preserved state, matching this legacy-route coverage gap.

PR-#3431
PR-#2455
PR-#2157

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test comments identify By group as the destination for the retired Compliance page, but the
added navigation uses the destination URL itself. The testing review skill requires frontend routes
and interactive flows to be covered by Playwright scenarios, so the legacy redirect remains
unverified.

tests/ui-admin.spec.ts[68-74]
Skill: testing-review

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The browser test validates the new Renewals query directly, but does not verify that the retired `/admin/compliance` address redirects to that view. Existing Compliance bookmarks could therefore break without this Playwright scenario failing.

### Fix Focus Areas
- tests/ui-admin.spec.ts[68-74]

### Recommended Fix
Navigate to `/admin/compliance` in the new browser scenario and assert that the final URL is `/admin/renewals?view=group` with the By group control checked and its content visible. Keep a separate direct-query assertion only if canonical query handling also needs coverage.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View resolved (6)
4. By-group renewals can regress unnoticed ✓ Resolved
Description
The browser scenario checks the renamed Soonest and Personal controls but never selects or validates
the newly added By group view. A broken tab, group rendering path, or route integration can
therefore pass the Playwright suite even though By group is the destination for the retired
Compliance page.
Code

tests/ui-on-call-boards.spec.ts[R952-954]

+  test("keeps Soonest and Personal tabs, and Personal holds only the reader's own renewals", async ({ page }) => {
    await openBoard(page, ROUTES.compliance);
-    await expect(page.getByRole("radio", { name: "Checklist" })).toBeVisible();
+    await expect(page.getByRole("radio", { name: "Soonest" })).toBeVisible();
Relevance

●●● Strong

Accepted coverage precedents require exercising non-default tabs and asserting their state or
resulting content.

PR-#2413
PR-#2455

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The testing-review skill requires frontend routes and interactive components to have Playwright
coverage. The changed browser assertions cover Soonest and Personal after the rename, but neither
changed scenario exercises the newly introduced By group tab; the cited test code demonstrates the
missing interaction.

tests/ui-on-call-boards.spec.ts[952-954]
tests/ui-admin.spec.ts[59-60]
Skill: testing-review

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The browser scenario was renamed from Checklist to Soonest but still omits the new By group workflow, so regressions in the merged Compliance destination can pass end-to-end verification.

## Fix Focus Areas
- tests/ui-on-call-boards.spec.ts[952-954]
- tests/ui-admin.spec.ts[59-60]

## Recommended Fix
Extend the relevant Playwright scenario to select the By group radio, assert that the grouped requirements content renders, and verify the old Compliance route reaches that view when applicable. Keep the Soonest and Personal assertions so all three Renewals views remain covered.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Renewals stays grouped after its link changes ✓ Resolved
Description
AdminRenewalsPage selects By group when view=group appears but does not reset the tab when that
parameter disappears. An in-place navigation from the old Compliance destination to
/admin/renewals therefore keeps showing By group even though the base Renewals link opens Soonest
on a fresh visit.
Code

src/components/admin/admin-renewals-page.tsx[R166-169]

+  if (viewParam !== seenView) {
+    setSeenView(viewParam);
+    if (viewParam === "group") setTab("group");
+  }
Relevance

●●● Strong

Accepted bug precedent favors synchronizing state when URL parameters change or disappear.

PR-#3201

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new synchronization sets tab only for the group parameter, while the rendered segmented
control and view use tab; the two destinations are defined as distinct URLs.

src/components/admin/admin-renewals-page.tsx[160-169]
src/components/admin/admin-renewals-page.tsx[469-479]
src/lib/admin/page-hrefs.ts[3-7]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Removing `view=group` during in-place navigation leaves Renewals on By group.
## Fix Focus Areas
- src/components/admin/admin-renewals-page.tsx[160-169]
## Recommended Fix
Handle transitions both into and out of the query-selected view while preserving deliberate tab selections when the URL has not changed. Test navigation between the grouped and base Renewals URLs without remounting.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Export searches miss the export action ✗ Dismissed
Description
KEYWORDS moves “export” and “spreadsheet” from the removed Export search entry to Renewals, whose
search result opens the base /admin/renewals URL. That URL starts on Soonest, while the
spreadsheet link is inside By group, so readers searching for Export no longer land on the export
page or the view containing its link.
Code

src/lib/work-search/pages.ts[R99-101]

+    "spreadsheet",
+    "csv",
+    "export",
Relevance

●●● Strong

Search results must land on content matching their keywords; prior search relevance findings were
accepted.

PR-#3295

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Search results inherit their href from frame entries; the Export entry was removed, the Renewals
href has no view parameter, and the export link renders only in the grouped component.

src/lib/work-search/pages.ts[84-104]
src/lib/work-search/pages.ts[134-177]
src/lib/admin/page-hrefs.ts[3-7]
src/components/admin/admin-renewals-page.tsx[474-479]
src/components/admin/admin-compliance-page.tsx[346-354]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Searching for Export now leads to Soonest rather than the spreadsheet action.
## Fix Focus Areas
- src/lib/work-search/pages.ts[85-104]
- src/lib/work-frame/areas.ts[1064-1070]
## Recommended Fix
Provide a searchable result that targets `/admin/compliance/export` directly, or at minimum target the grouped Renewals view for export-specific searches. Keep the general Renewals result for renewal queries.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Signed-out sharing lacks its own notice ✓ Resolved
Description
SharingBody suppresses its signed-out notice when embedded, but AdminRequestsPage supplies a
notice about keeping requests instead of sharing choices. A signed-out reader opening Send a pack
can use the sharing switches without the previous explanation that those choices are not saved.
Code

src/components/work-screens/admin/sharing-page.tsx[R295-298]

+      {page.signedOut && !embedded ? (
        <PaperworkSampleNotice what="sharing choices" testId="admin-sharing-signed-out" examples={page.examplesShown} />
      ) : null}
-      {page.demo ? <PaperworkDemoNotice testId="admin-sharing-demo" /> : null}
+      {page.demo && !embedded ? <PaperworkDemoNotice testId="admin-sharing-demo" /> : null}
Relevance

●●● Strong

Signed-out persistence explanations protect user expectations, matching prior acceptance of privacy
and persistence safeguards.

PR-#3206

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The embedded view removes the Sharing notice, while the parent notice explicitly names requests. The
removed notice is the component that explains signed-out changes are not saved.

src/components/work-screens/admin/requests-page.tsx[278-311]
src/components/work-screens/admin/sharing-page.tsx[289-298]
src/components/work-screens/admin/paperwork-shared.tsx[147-168]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Embedding Sharing removes the notice explaining what happens to signed-out sharing choices.
## Fix Focus Areas
- src/components/work-screens/admin/sharing-page.tsx[287-298]
- src/components/work-screens/admin/requests-page.tsx[278-311]
## Recommended Fix
Show a sharing-specific signed-out notice in Send a pack, either within `SharingBody` or by varying the parent notice with the selected tab. Avoid duplicating the general demo notice.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Old Sharing links can open the wrong tab ✓ Resolved
Description
ADMIN_WORK_SCREEN_HREFS.sharing and the /admin/sharing redirect now point to
/admin/requests#send, and AdminRequestsPage picks Send a pack only when it reads
window.location.hash === "#send". Next.js App Router has documented cases where a server redirect
followed during in-app navigation drops the fragment. When that happens, Documents' and Workforce's
Sharing links and preview-role's /admin/sharing entry open Requests on the Open tab instead of
Send a pack.
Code

src/lib/work-screens/admin/hrefs.ts[R4-5]

+  // Sharing is Requests' "Send a pack" view since 11 Oct 2026.
+  sharing: "/admin/requests#send",
Relevance

●● Moderate

The redirect-fragment risk is plausible and externally documented, but evidence is architectural
rather than repository-specific.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Two addresses lead to the Send a pack view: the redirect target and the href in the shared constant.
Both depend on the fragment arriving intact, and the page reads only the fragment to choose its tab.
Next.js issues report that fragments are stripped from redirect destinations during client
navigation. Renewals avoids this problem by using a query parameter (?view=group).

src/app/(search-app)/admin/sharing/page.tsx[1-8]
src/components/work-screens/admin/requests-page.tsx[124-143]
src/components/work-screens/admin/documents-page.tsx[340-346]
src/lib/preview-role/preview-role.ts[94-98]
🌐 Next.js issue: a redirect to /example?hello=world#hash drops the #hash. Comments also note that config redirects to /foo#bar end up at /foo when followed by fetch during client navigation.

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Send a pack tab in Requests is chosen from the `#send` fragment. Next.js can drop that fragment when it follows a redirect during in-app navigation, so old Sharing links open the Open tab.

## Fix Focus Areas
- src/lib/work-screens/admin/hrefs.ts[4-5]
- src/components/work-screens/admin/requests-page.tsx[124-143]

## Recommended Fix
Change `sharing` to `/admin/requests?view=send`. In `AdminRequestsPage`, read `useSearchParams().get("view") === "send"` to pick the initial tab, as Renewals does with `?view=group`, and handle later changes to the parameter the same way. Wrap the route in Suspense if needed. Optionally keep reading `#send` as a fallback.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Screens still send readers to a removed Compliance page ✓ Resolved
Description
The merged Requests suggestions keep the label count="From Compliance", and New job's signpost
count still ends "in Compliance" even though its link now opens Renewals' By group view. Compliance
no longer appears in the Admin menu, so readers are pointed to a page name they cannot find.
Code

src/components/work-screens/admin/requests-page.tsx[385]

+                  <WorkSectionLabel count="From Compliance">You may need more time</WorkSectionLabel>
Relevance

●●● Strong

Stale page terminology after navigation changes is a straightforward clarity defect aligned with
recent naming fixes.

PR-#3453

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR removes Compliance from the menu and renames the related links to "Renewals by group". Some
labels still use the old page name, and the updated New job test still expects "in Compliance".

src/lib/work-frame/areas.ts[1064-1070]
tests/admin-new-job-page.dom.test.tsx[277-282]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Some user-facing text still names "Compliance", which no longer appears in the Admin menu.

## Fix Focus Areas
- src/components/work-screens/admin/requests-page.tsx[385-385]
- src/components/admin/admin-new-job-page.tsx[165-185]
- tests/admin-new-job-page.dom.test.tsx[280-282]

## Recommended Fix
Change "From Compliance" to "From Renewals" and change "in Compliance" to "in Renewals". Update the test regex to match.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 9 rules
✅ Cross-repo context — repo relationships
✅ REVIEW.md
Review mode: Auto: 🚀 Fast: Localized test-only URL redirect assertion with minimal contained risk.

Grey Divider

Tip of the day
💡 Did you know, you can tweak Display settings with a live preview to see your comment before it ships

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/lib/work-search/pages.ts Resolved
Comment thread src/lib/work-screens/admin/hrefs.ts Resolved
@codeant-ai

codeant-ai Bot commented Oct 11, 2026

Copy link
Copy Markdown

CodeAnt Nitpicks

5 code suggestions

1. The font shorthand resets line-height to the inherited value, so the new 1.2 leading never applies and wrapped labels make these compact tiles taller.

Css layout issue · src/components/admin/admin-work.module.css:220


2. This opens New job at the page top, not the sharing switch, so users must search through the page to find the control.

Api mismatch · src/components/admin/ready/ready-for-day-one-page.tsx:267


3. In signed-out/demo mode, this view stores changes only in SharingBody state; switching to Open or Done unmounts it, so share toggles and recipient edits reset when reopened.

Possible bug · src/components/work-screens/admin/requests-page.tsx:310-312


4. The mode-pages sheet caller supplies only isEditor, so isAdministrator defaults to false and site administrators never see the new Review entry there.

Api mismatch · src/lib/mode-secondary-navigation.ts:388


5. These search terms open plain /admin/requests, whose default tab is Open, so searches for Sharing miss the Send a pack view.

Api mismatch · src/lib/work-search/pages.ts:104

@codeant-ai

codeant-ai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

CodeAnt PR Risk: Low Risk

  • The PR appears safe to merge; retired Admin pages redirect to their consolidated Renewals, Requests, or Hospital destinations.
  • Updated tests cover the new group and send views, legacy redirects, and the revised Help layout.

Assessed commit: b5127e44196e

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRAKeUNKFmnQHMbMmnHWDW
gitar-bot[bot]
gitar-bot Bot previously approved these changes Oct 11, 2026

@gitar-bot gitar-bot 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.

Gitar has auto-approved this PR (configure)

Comment thread tests/ui-admin.spec.ts Resolved
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit de7520e

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRAKeUNKFmnQHMbMmnHWDW
gitar-bot[bot]
gitar-bot Bot previously approved these changes Oct 11, 2026

@gitar-bot gitar-bot 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.

Gitar has auto-approved this PR (configure)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 859d652

Copy link
Copy Markdown
Owner Author

CodSpeed flags answer-ranking: rankAnswerEvidence 40 results as 22.8% slower on 859d652. I'm treating this as noise rather than something this PR caused:

  • Nothing in this PR touches answer ranking or anything it imports. The diff covers Admin pages, navigation and tests only.
  • Commit 859d652 changed one browser test file and no runtime code.
  • On the previous commits, the same CodSpeed comment showed no regression on this benchmark. CodSpeed also warns that this benchmark spends significant time in system calls, which it can't measure consistently.

I can't re-run a CodSpeed check from here. The owner can acknowledge the result on CodSpeed if it blocks the merge.


Generated by Claude Code

@codeant-ai codeant-ai Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Oct 11, 2026

Copy link
Copy Markdown
Owner Author

Unit coverage partition (1) failed on 619efb1 with one test: tests/challenger-m3-2-sql-and-lighthouse-stress.test.ts, "handles large SQL payload … in under 50ms". It took 105 ms against a 100 ms wall-clock limit.

This isn't from this PR:

There's no fix on main yet. A longer-term fix would be to loosen that timing limit under coverage, but that belongs in its own PR. I'll re-run the failed job once when the current run finishes.


Generated by Claude Code

BigSimmo and others added 2 commits October 11, 2026 20:56
The clinical side menu imported its counts loader from the module that
lazy-loads the side menus, closing an import cycle back to itself; the
loader now has its own module. The tablet rail test still expected Tools
and no Psychiatry after the More modes regroup.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRAKeUNKFmnQHMbMmnHWDW

BigSimmo commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner Author

Two checks went red on main at 4393497 (#3466, the new phone side menu), not from this PR: tests/architecture-boundaries.test.ts finds a new import cycle around the clinical side menu, and the tablet rail case in tests/ui-smoke.spec.ts:1506 still expects Tools and no Psychiatry. The dedicated fix is #3468 from the menu's owner, so the port I pushed (7592e47) is reverted in 6d39702 to avoid a collision. Once #3468 lands, main gets merged in here and CI re-runs.


Generated by Claude Code

gitar-bot[bot]
gitar-bot Bot previously approved these changes Oct 11, 2026

@gitar-bot gitar-bot 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.

Gitar has auto-approved this PR (configure)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRAKeUNKFmnQHMbMmnHWDW

@gitar-bot gitar-bot 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.

Gitar has auto-approved this PR (configure)

@qodo-code-review

qodo-code-review Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

No code changes since the last review — review skipped

Qodo Logo

@gitar-bot

gitar-bot Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor
Code Review ✅ Approved 1 closed / 1 findings

🟡 Medium risk · Staff-page menu gating could hide Hospital navigation from role holders if role detection fails; Compliance and Sharing URLs now redirect to merged screens.

Admin staff pages are now limited to role holders, with Renewals consolidating Compliance and Sharing moved inside Requests as a "Send a pack" view. The resolved finding: choosing Done from Send a pack no longer flips the tab back to Open, and a new test covers that ordering. No open issues found.

Auto-approved: No blocking issues found.
Please see Auto-approve Docs for details on setting custom approval criteria.

✅ 1 closed
✅ Bug: Choosing Done from Send a pack flips the tab back to Open

📄 src/components/work-screens/admin/requests-page.tsx:137-149 📄 tests/work-screens-admin-pages.dom.test.tsx:189-203
When the page was opened at ?view=send (Sharing's old address, or the Documents and Workforce links) and the reader taps Done, setTab("done") sets the tab and then calls router.replace(pathname). On the next render viewParam is null and seenView is still "send", so the render-time sync goes into else if (seenView === "send") setChosenTab("open") and replaces the reader's Done choice with Open. The new test misses this because it clears the param before it clicks Done. A fix is to remember the tab chosen during the replace and apply it when the URL catches up, or to only fall back to Open when the reader didn't start the change.

Review coverage

🤖 Auto-approval Approved

📋 Rules No rules evaluated

🧪 Functional validation Not enabled · Set up

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Counting what did not apply, without listing it.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔴 Large blast radius size:XL This PR changes 500-999 lines, ignoring generated files 🕐 40+ Minutes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants