fix: Apply audit system remediation and address all outstanding issues - #1261
fix: Apply audit system remediation and address all outstanding issues#1261BigSimmo wants to merge 2 commits into
Conversation
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
📝 WalkthroughWalkthroughThe PR adds three GitHub Actions workflows, updates bundle-budget data and action-pin discovery, repairs upload and RAG paths, changes dashboard and service UI behavior, refreshes skill configuration and tests, and cleans up repository, issue-tracking, and public documentation. ChangesCI and validation automation
Application and RAG behavior
Dashboard and service interface updates
Skills and documentation content
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve 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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b4dae84690
ℹ️ 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".
| } | ||
|
|
||
| export function shouldShortCircuitUnsupportedSearch(query: string, analysis: ClinicalQueryAnalysis) { | ||
| if (analysis.corpusGrounding === "out_of_corpus") return true; |
There was a problem hiding this comment.
Keep mixed in-corpus clinical queries retrievable
When an unsupported-soft-tail query combines a known topic with any normalized qualifier absent from the corpus (for example, “bipolar management for a FIFO worker”), classifyCorpusGroundingFromStats returns out_of_corpus if even one term is absent, and this unconditional return bypasses the clinical-term safeguard below. With no alias or typo correction for the legitimate qualifier, rag.ts:2369-2402 returns zero results despite matching bipolar sources. Preserve retrieval when corpus anchors exist, add a mixed present/absent-term regression case, and validate the protected behavior with the required canary pair.
AGENTS.md reference: AGENTS.md:L256-L259
Useful? React with 👍 / 👎.
| - name: Setup UI e2e environment | ||
| uses: ./.github/actions/setup-ui-e2e | ||
|
|
||
| - name: Run Playwright suite | ||
| run: node scripts/run-playwright.mjs --project=${{ matrix.project }} |
There was a problem hiding this comment.
Install browsers before running cross-browser jobs
On a fresh runner or browser-cache miss, the Firefox and WebKit matrix entries fail before executing tests: the inspected .github/actions/setup-ui-e2e/action.yml:12-28 caches and installs only Chromium (playwright install ... chromium), while this workflow requests all three projects. Install the selected matrix browser—or use a setup action that installs the full set—before invoking run-playwright.mjs; an empty ~/.cache/ms-playwright run is the smallest proof.
Useful? React with 👍 / 👎.
| alternates: { | ||
| canonical: "/", | ||
| }, |
There was a problem hiding this comment.
Do not inherit the home canonical on every route
Because this metadata is defined in the root layout and nearly all child routes only override fields such as title, pages including /tools, /privacy, and document/detail routes inherit a canonical URL of /. Their rendered metadata therefore identifies the homepage as canonical, causing distinct production pages to be treated as duplicate versions of the home page. Omit the root canonical or generate a route-specific canonical; rendering any non-root page and inspecting its canonical link is a focused regression proof.
Useful? React with 👍 / 👎.
|
|
||
| | Order | ID(s) | Acuity | Capability | When | Estimate | Outcome, gate, verification, and stopping condition | |
There was a problem hiding this comment.
Retain only one issues priority table
Resolving the conflict marker to a blank line leaves both sides of the priority-table conflict in the document: the first table ends with issues:next-id=064, then a second, conflicting ordered plan begins here and later uses next-id=070. The stale table still schedules already-resolved items such as #060–#062, so operators can follow contradictory priorities. Keep only the current table and its matching next-ID marker.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 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 @.github/workflows/bundle-size.yml:
- Around line 6-12: Update the path filters in the bundle-size workflow to also
trigger when the bundle-budget checker under scripts, the local setup action
under .github/actions/setup-node-cached, or this workflow itself changes.
Preserve the existing source, public, package, Next.js, and budget configuration
paths while using the documented project and provider safety boundaries.
In `@docs/audit/repo-wide-review-remediation-plan-2026-07-23.md`:
- Line 264: Update the remediation plan so the composite-action self-test is
listed as an unconditional Batch 2 requirement rather than under the
approval-only section. Remove the malformed “Ask before running any of these:
3.” entry and keep the approval-only section limited to provider-backed
commands.
- Line 120: Complete the action-pin discovery checklist in item 2 by adding the
required .yml and .yaml patterns after “extend discovery to include:”, or remove
the incomplete duplicate block if those details are already documented
elsewhere. Keep item 3 focused solely on reading the installed Next guide before
framework changes.
In `@docs/outstanding-issues.md`:
- Around line 87-91: Make docs/outstanding-issues.md contain one authoritative
issue ledger: remove the duplicate stale queue/open-items snapshot and its
conflicting issues:next-id marker, retain the current queue and open-items table
with a single next-id marker, and preserve the archive’s resolved status for
`#052`, `#060`, `#061`, and `#062` so completed work cannot be reintroduced.
In `@public/llms.txt`:
- Around line 1-3: Update the public Clinical KB documentation in llms.txt to
remove the API discovery section and any invitation to inspect the source code
for endpoints. Keep the document limited to the private knowledge-base
description unless an explicitly supported authenticated API contract with AUTH
and PHI boundaries is already defined.
In `@src/app/globals.css`:
- Line 474: Update the text-rendering declaration in the global stylesheet to
use the lowercase optimizelegibility value required by the configured Stylelint
value-keyword-case rule.
- Around line 430-526: Move the iOS form-control font-floor rules and shared
focus-ring selectors out of `@layer` base so they remain unlayered or are emitted
after Tailwind utilities. Preserve the existing selectors, 16px mobile minimum,
and single-owner focus styling so text-* and focus utilities cannot override
them.
In `@src/app/layout.tsx`:
- Around line 33-35: Remove the alternates.canonical configuration from the root
layout metadata. Define canonical "/" only in the home route’s metadata so child
routes do not inherit it unintentionally.
🪄 Autofix (Beta)
❌ Autofix failed (check again to retry)
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 Plus
Run ID: 1dc13a23-51de-4df2-9c17-1ab57f55ba69
📒 Files selected for processing (31)
.agents/skills/catalog.json.agents/skills/prompt-perfector/agents/openai.yaml.github/workflows/bundle-size.yml.github/workflows/nightly-drift.yml.github/workflows/playwright.ymlbundle-budget.jsondocs/audit/repo-wide-review-remediation-plan-2026-07-23.mddocs/outstanding-issues.mddocs/search-chrome-behaviour.mdpublic/llms.txtscripts/check-github-action-pins.mjssrc/app/api/answer/route.tssrc/app/api/upload/route.tssrc/app/globals.csssrc/app/layout.tsxsrc/components/ClinicalDashboard.tsxsrc/components/clinical-dashboard/answer-status.tsxsrc/components/clinical-dashboard/evidence-panels.tsxsrc/components/clinical-dashboard/settings-dialog.tsxsrc/components/mode-home-template.tsxsrc/components/services/service-detail-page.tsxsrc/components/services/services-navigator-page.tsxsrc/lib/rag/rag-query-guard.tssrc/lib/service-catalog-mapper.tstests/database-skills.test.tstests/privacy-ui.test.tstests/private-access-routes.test.tstests/reconciliation-preflight.test.tstests/ui-tools.spec.tstests/visual-evidence-tabs.dom.test.tsxworker/main.ts
💤 Files with no reviewable changes (8)
- src/components/services/services-navigator-page.tsx
- src/lib/service-catalog-mapper.ts
- src/components/services/service-detail-page.tsx
- src/components/clinical-dashboard/settings-dialog.tsx
- src/components/clinical-dashboard/answer-status.tsx
- src/components/clinical-dashboard/evidence-panels.tsx
- tests/visual-evidence-tabs.dom.test.tsx
- tests/private-access-routes.test.ts
| paths: | ||
| - "src/**" | ||
| - "public/**" | ||
| - "package.json" | ||
| - "package-lock.json" | ||
| - "next.config.ts" | ||
| - "bundle-budget.json" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Trigger the audit when its own implementation changes.
Changes to the bundle-budget checker, local setup action, or this workflow do not match these paths, so the guard can be modified without running. Include the relevant scripts/**, .github/actions/setup-node-cached/**, and workflow path. As per coding guidelines, CI workflows must use documented project and provider safety boundaries.
🤖 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 @.github/workflows/bundle-size.yml around lines 6 - 12, Update the path
filters in the bundle-size workflow to also trigger when the bundle-budget
checker under scripts, the local setup action under
.github/actions/setup-node-cached, or this workflow itself changes. Preserve the
existing source, public, package, Next.js, and budget configuration paths while
using the documented project and provider safety boundaries.
Source: Coding guidelines
| ======= | ||
| >>>>>>> theirs | ||
| 5. Before any Next/framework code change, read the relevant installed guide in `node_modules/next/dist/docs/`. | ||
| 3. Before any Next/framework code change, read the relevant installed guide in `node_modules/next/dist/docs/`. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Restore the missing action-pin discovery details.
The preceding item ends with “extend discovery to include:” but item 3 starts immediately, so this checklist omits the required .yml/.yaml patterns. Add those bullets under item 2 or remove this incomplete duplicate block.
🤖 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 `@docs/audit/repo-wide-review-remediation-plan-2026-07-23.md` at line 120,
Complete the action-pin discovery checklist in item 2 by adding the required
.yml and .yaml patterns after “extend discovery to include:”, or remove the
incomplete duplicate block if those details are already documented elsewhere.
Keep item 3 focused solely on reading the installed Next guide before framework
changes.
| ======= | ||
| >>>>>>> theirs | ||
| 3. Add a self-test that would fail if an unpinned external `uses:` in a composite action is ignored. | ||
| Ask before running any of these: 3. Add a self-test that would fail if an unpinned external `uses:` in a composite action is ignored. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Move the composite-action self-test out of the approval-only section.
This line is malformed as Ask before running any of these: 3. and incorrectly makes adding the self-test approval-gated. Keep the self-test as an unconditional Batch 2 requirement, reserving this section for provider-backed commands.
🤖 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 `@docs/audit/repo-wide-review-remediation-plan-2026-07-23.md` at line 264,
Update the remediation plan so the composite-action self-test is listed as an
unconditional Batch 2 requirement rather than under the approval-only section.
Remove the malformed “Ask before running any of these: 3.” entry and keep the
approval-only section limited to provider-backed commands.
| <!-- issues:next-id=064 --> | ||
| ======= | ||
|
|
||
| | Order | ID(s) | Acuity | Capability | When | Estimate | Outcome, gate, verification, and stopping condition | | ||
| | ----: | ---------------------- | -------- | ------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| | 1 | `#059` | A1 | Operator security + independent reviewer | Immediate approved security window | 1–3 hours plus verification | Verify every reported exposed credential (GitHub, OpenAI, Supabase service role/database, E2E) is retired; rotate anything still valid and update only intended secret stores. Never record values; stop before provider action without approval. | |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Keep one authoritative issue-ledger snapshot.
This change leaves duplicate queue/open-item tables and conflicting issues:next-id markers: 064 here and 070 at Line 124. The later open-items copy still lists #052, #060, #061, and #062 as open even though the archive marks them resolved at Lines 231-234. /issues can therefore read or mutate stale data, resurrect completed work, or allocate incorrect IDs. Remove the stale snapshot and retain one queue, one open-items table, and one next-id marker.
As per coding guidelines, docs/outstanding-issues.md is the single durable ledger, and completed or duplicate work must not be restored.
Also applies to: 124-137, 230-234
🤖 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 `@docs/outstanding-issues.md` around lines 87 - 91, Make
docs/outstanding-issues.md contain one authoritative issue ledger: remove the
duplicate stale queue/open-items snapshot and its conflicting issues:next-id
marker, retain the current queue and open-items table with a single next-id
marker, and preserve the archive’s resolved status for `#052`, `#060`, `#061`, and
`#062` so completed work cannot be reintroduced.
Source: Coding guidelines
| # Clinical KB | ||
|
|
||
| Purpose: Clinical Guide is a local clinical knowledge-base interface for searching indexed source documents, reviewing evidence, and drafting source-backed clinical answers. | ||
| > Private medical guideline RAG knowledge base. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== locate llms.txt and route docs/config ==="
fd -a 'llms\.txt$|routes|app|pages|router|middleware' . | sed 's#^\./##' | head -100
echo
echo "=== public/llms.txt ==="
if [ -f public/llms.txt ]; then
cat -n public/llms.txt
else
echo "public/llms.txt not found"
fi
echo
echo "=== Next docs availability ==="
fd -a 'docs' . | head -50
echo
echo "=== search API/security docs references in repo ==="
rg -n "API|LLM|private|PHI|medical|authorization|authentication|routing|routes" -S . --glob '!node_modules' --glob '!*.lock' --glob '!!.gitignore' | head -200Repository: BigSimmo/Database
Length of output: 50373
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== src/app ==="
fd -a . src/app | sed 's#^\./##' | sort | head -120
echo
echo "=== API route files ==="
fd -a 'route\.(ts|tsx|json)$' src/api src/app 2>/dev/null | sed 's#^\./##' | sort | head -200
echo
echo "=== private access tests ==="
cat -n tests/private-access-routes.test.ts | sed -n '1,220p'
echo
echo "=== app routing/security relevant source ==="
rg -n "notFound|forbidden|redirect|middleware|headers|authorization|auth|middleware\.ts|next/server|LLM|api|/api" src tests scripts docs --glob '!node_modules' --glob '!*.lock' | head -300
echo
echo "=== llms plus security boundary refs ==="
rg -n "secure|private|Clinical KB|authorized|authentication|authorization|auth|PHI|medical|endpoint|API|routes" public/llms.txt SECURITY.md docs public -S --glob '!node_modules' --glob '!*.lock' | head -200Repository: BigSimmo/Database
Length of output: 50373
Remove the unsupported API discovery from public/llms.txt.
public/llms.txt publicly invites agents to the Clinical KB’s API endpoints while the app is documented as private and the src/app/api surface includes authenticated management/route endpoints. “Refer to the source codebase” lets public consumers discover non-public APIs; either publish only the intended authenticated API contract with AUTH/PHI usage boundaries or remove the API section.
🤖 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 `@public/llms.txt` around lines 1 - 3, Update the public Clinical KB
documentation in llms.txt to remove the API discovery section and any invitation
to inspect the source code for endpoints. Keep the document limited to the
private knowledge-base description unless an explicitly supported authenticated
API contract with AUTH and PHI boundaries is already defined.
| @layer base { | ||
| /* Reset and base document styles */ | ||
| * { | ||
| box-sizing: border-box; | ||
| } | ||
|
|
||
| html { | ||
| min-width: 320px; | ||
| min-height: 100%; | ||
| min-height: 100svh; | ||
| min-height: 100dvh; | ||
| background-color: var(--background); | ||
| overflow-x: clip; | ||
| overscroll-behavior-x: none; | ||
| scroll-padding-top: calc(4rem + env(safe-area-inset-top)); | ||
| } | ||
| html { | ||
| min-width: 320px; | ||
| min-height: 100%; | ||
| min-height: 100svh; | ||
| min-height: 100dvh; | ||
| background-color: var(--background); | ||
| overflow-x: clip; | ||
| overscroll-behavior-x: none; | ||
| scroll-padding-top: calc(4rem + env(safe-area-inset-top)); | ||
| } | ||
|
|
||
| /* | ||
| * Interface density scales the rem baseline so every rem-based size shifts | ||
| * together. "Comfortable" is the browser default (16px) and sets no attribute, | ||
| * so the untouched default experience is unchanged. The attribute is applied on | ||
| * <html> before first paint (layout.tsx inline script) and kept in sync by | ||
| * useAppPreferences. The unlayered 16px mobile input floor above still wins for | ||
| * form controls so iOS never zooms. | ||
| */ | ||
| html[data-density="compact"] { | ||
| font-size: 15px; | ||
| } | ||
| /* | ||
| * Interface density scales the rem baseline so every rem-based size shifts | ||
| * together. "Comfortable" is the browser default (16px) and sets no attribute, | ||
| * so the untouched default experience is unchanged. The attribute is applied on | ||
| * <html> before first paint (layout.tsx inline script) and kept in sync by | ||
| * useAppPreferences. The unlayered 16px mobile input floor above still wins for | ||
| * form controls so iOS never zooms. | ||
| */ | ||
| html[data-density="compact"] { | ||
| font-size: 15px; | ||
| } | ||
|
|
||
| html[data-density="spacious"] { | ||
| font-size: 17px; | ||
| } | ||
| html[data-density="spacious"] { | ||
| font-size: 17px; | ||
| } | ||
|
|
||
| body { | ||
| min-height: 100%; | ||
| min-height: 100svh; | ||
| min-height: 100dvh; | ||
| background: var(--background); | ||
| color: var(--text); | ||
| font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif; | ||
| font-feature-settings: | ||
| "liga" 1, | ||
| "calt" 1, | ||
| "ss01" 1; | ||
| text-rendering: optimizeLegibility; | ||
| overflow-x: clip; | ||
| overscroll-behavior-x: none; | ||
| } | ||
| body { | ||
| min-height: 100%; | ||
| min-height: 100svh; | ||
| min-height: 100dvh; | ||
| background: var(--background); | ||
| color: var(--text); | ||
| font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif; | ||
| font-feature-settings: | ||
| "liga" 1, | ||
| "calt" 1, | ||
| "ss01" 1; | ||
| text-rendering: optimizeLegibility; | ||
| overflow-x: clip; | ||
| overscroll-behavior-x: none; | ||
| } | ||
|
|
||
| /* Interactive element defaults */ | ||
| button, | ||
| input, | ||
| textarea, | ||
| select { | ||
| font: inherit; | ||
| } | ||
|
|
||
| /* Interactive element defaults */ | ||
| button, | ||
| input, | ||
| textarea, | ||
| select { | ||
| font: inherit; | ||
| } | ||
| /* | ||
| * iOS Safari zooms the viewport when a focused form control renders below 16px. | ||
| * This rule is intentionally unlayered so it wins over Tailwind's layered | ||
| * text-* utilities, giving every control a 16px floor on small screens | ||
| * (search field, scope filter, PDF page input) without per-call-site edits. | ||
| */ | ||
| @media (max-width: 640px) { | ||
| input, | ||
| select, | ||
| textarea { | ||
| font-size: 16px; | ||
| } | ||
| } | ||
|
|
||
| /* | ||
| * iOS Safari zooms the viewport when a focused form control renders below 16px. | ||
| * This rule is intentionally unlayered so it wins over Tailwind's layered | ||
| * text-* utilities, giving every control a 16px floor on small screens | ||
| * (search field, scope filter, PDF page input) without per-call-site edits. | ||
| */ | ||
| @media (max-width: 640px) { | ||
| button, | ||
| a, | ||
| summary, | ||
| input, | ||
| select, | ||
| textarea { | ||
| font-size: 16px; | ||
| textarea, | ||
| select { | ||
| outline: none; | ||
| touch-action: manipulation; | ||
| -webkit-tap-highlight-color: transparent; | ||
| } | ||
| } | ||
|
|
||
| button, | ||
| a, | ||
| summary, | ||
| input, | ||
| textarea, | ||
| select { | ||
| outline: none; | ||
| touch-action: manipulation; | ||
| -webkit-tap-highlight-color: transparent; | ||
| } | ||
|
|
||
| /* One focus owner per interaction. Buttons and links use a single external | ||
| outline; form fields draw the same outline inside their own box so scroll | ||
| containers and sheets cannot clip it at an edge. Keeping these unlayered is | ||
| intentional: it prevents component-level `focus:ring-*` utilities from | ||
| stacking a second halo on top of the shared treatment. */ | ||
| :where(button, a, summary, input[type="checkbox"], input[type="radio"], input[type="range"]):focus-visible { | ||
| outline: 2px solid var(--focus); | ||
| outline-offset: 2px; | ||
| } | ||
| /* One focus owner per interaction. Buttons and links use a single external | ||
| outline; form fields draw the same outline inside their own box so scroll | ||
| containers and sheets cannot clip it at an edge. Keeping these unlayered is | ||
| intentional: it prevents component-level `focus:ring-*` utilities from | ||
| stacking a second halo on top of the shared treatment. */ | ||
| :where(button, a, summary, input[type="checkbox"], input[type="radio"], input[type="range"]):focus-visible { | ||
| outline: 2px solid var(--focus); | ||
| outline-offset: 2px; | ||
| } | ||
|
|
||
| :where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]), textarea, select):focus-visible { | ||
| box-shadow: var(--shadow-inset); | ||
| outline: 2px solid var(--focus); | ||
| outline-offset: -2px; | ||
| } | ||
| :where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]), textarea, select):focus-visible { | ||
| box-shadow: var(--shadow-inset); | ||
| outline: 2px solid var(--focus); | ||
| outline-offset: -2px; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "## files"
git ls-files | rg '(^|/)(globals\.css|tailwind\.config\.(js|cjs|mjs|ts)|package\.json|postcss\.config\.(js|cjs|mjs|ts)|(\.stylelintrc.*|stylelint\.config\..*))$' || true
echo
echo "## globals relevant"
sed -n '1,90p' src/app/globals.css
echo
sed -n '420,5400p' src/app/globals.css | sed -n '1,120p'
echo
echo "## tailwind config snippets"
for f in $(git ls-files | rg '(^|/)tailwind\.config\.(js|cjs|mjs|ts)$'); do
echo "--- $f"
sed -n '1,220p' "$f"
done
echo "## next docs if present"
find node_modules/next/dist/docs -maxdepth 3 -type f 2>/dev/null | sed -n '1,80p' || true
echo "## search layer declarations"
rg -n '@(layer|import)\s+["'\'']tailwind|`@tailwind`|`@layer`\s+(base|components|utilities|utilities-base)?|utilities-base' src -S || trueRepository: BigSimmo/Database
Length of output: 15113
🌐 Web query:
Tailwind CSS v4 @import "@tailwindcss/base" @layerutilities priority CSS layers@tailwindcss/utilities``
💡 Result:
In Tailwind CSS v4, the architecture has shifted from hijacking CSS layers to using native CSS Cascade Layers [1][2]. This change fundamentally alters how Tailwind's internal styles and your custom CSS interact, placing high importance on layer order and declaration [1][3]. Core Concepts and Priority 1. Native Cascade Layers: Tailwind v4 defines layers such as theme, base, components, and utilities [4][2]. According to CSS standards, layers are ordered at declaration, and later layers take precedence over earlier ones, regardless of selector specificity [3]. 2. Unlayered CSS: Rules not placed in a layer are considered "unlayered" and have higher precedence than any styles placed inside a layer [5][6]. To ensure your custom styles can be overridden by Tailwind utilities, you should place your custom styles into a layer (e.g., @layer base or @layer components) rather than writing them as unlayered CSS [3][6]. 3. The @utility API: In v4, custom utilities should be defined using the @utility directive rather than @layer utilities [1]. The @utility API is designed to integrate seamlessly with Tailwind's utility generation, ensuring they are treated correctly within the framework's internal layer structure [1][7]. Working with @import When you use @import "tailwindcss";, Tailwind automatically configures the necessary layers for you [8][1]. If you need to customize or split these imports, you can import specific sub-modules into named layers to maintain control [9][10]: @layer theme, base, components, utilities; @import "tailwindcss/theme" layer(theme); @import "tailwindcss/preflight" layer(base); @import "tailwindcss/utilities" layer(utilities); Best Practices - Use @utility for Custom Utilities: Avoid manually adding classes to the utilities layer via @layer utilities; instead, use the @utility directive [1]. This allows Tailwind to intelligently sort these utilities based on the number of properties they define, providing better control over precedence [1][7]. - Managing Conflicts: If you have external styles that override Tailwind, ensure you place those styles into a named layer [5][6]. If a specific utility needs to win, you can continue to use the!important flag, which remains a standard tool for breaking layer priority in CSS [11][12]. - Precedence: Remember that the source order of @layer declarations defines the priority: @layer theme, base, components, utilities; In this declaration, utilities is the highest priority layer [11][3]. If you define custom styles in a layer declared after utilities, they will override Tailwind's utilities [11].
Citations:
- 1: https://tailwindcss.com/docs/upgrade-guide
- 2: https://tailwindcss.com/blog/tailwindcss-v4
- 3: https://danholloran.me/posts/css-cascade-layers-taking-control-of-specificity
- 4: v3→v4 upgrade: gradient buttons broken when using @import 'tailwindcss' (unlayered preflight overrides bg-linear-to-* utilities) tailwindlabs/tailwindcss#19979
- 5: [v4] Will there be a way to opt out of native cascade layers? tailwindlabs/tailwindcss#13188
- 6: [v4] Utility classes are less specific than other classes tailwindlabs/tailwindcss#17202
- 7: [v4] @utility with custom layer tailwindlabs/tailwindcss#14363
- 8: https://tailwindcss.com/docs/functions-and-directives
- 9: `@layer base` is used but no matching `@tailwind base` directive is present. tailwindlabs/tailwindcss#18123
- 10: https://tailwindcss.com/blog/tailwindcss-v4-alpha
- 11: https://css-tricks.com/using-css-cascade-layers-with-tailwind-utilities/
- 12: https://tailwindcss.com/docs/styling-with-utility-classes
Keep the control overrides outside @layer base.
@layer rules are lower priority than Tailwind’s utilities layer, so these rules are overridden by text-*, outline-ring-*, and focus utilities. This breaks the intended iOS 16px font floor and shared focus-ring contract; leave the controls overrides unlayered or place them after Tailwind utility output.
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 474-474: Expected "optimizeLegibility" to be "optimizelegibility" (value-keyword-case)
(value-keyword-case)
🤖 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/app/globals.css` around lines 430 - 526, Move the iOS form-control
font-floor rules and shared focus-ring selectors out of `@layer` base so they
remain unlayered or are emitted after Tailwind utilities. Preserve the existing
selectors, 16px mobile minimum, and single-owner focus styling so text-* and
focus utilities cannot override them.
| "liga" 1, | ||
| "calt" 1, | ||
| "ss01" 1; | ||
| text-rendering: optimizeLegibility; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the failing Stylelint value casing.
optimizeLegibility violates the configured value-keyword-case rule; use optimizelegibility.
🧰 Tools
🪛 Stylelint (17.14.0)
[error] 474-474: Expected "optimizeLegibility" to be "optimizelegibility" (value-keyword-case)
(value-keyword-case)
🤖 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/app/globals.css` at line 474, Update the text-rendering declaration in
the global stylesheet to use the lowercase optimizelegibility value required by
the configured Stylelint value-keyword-case rule.
Source: Linters/SAST tools
| alternates: { | ||
| canonical: "/", | ||
| }, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect whether every App Router route overrides the root canonical.
rg -n --glob '*.{ts,tsx}' \
'alternates\s*:|canonical\s*:' \
src/appRepository: BigSimmo/Database
Length of output: 235
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and inspect the root layout metadata, App Router route metadata files, and Next docs around metadata inheritance.
printf '--- src/app/layout.tsx ---\n'
sed -n '1,90p' src/app/layout.tsx
printf '\n--- route-level metadata files ---\n'
git ls-files 'src/app/**/*.{ts,tsx}' | while read -r f; do
echo "===== $f ====="
sed -n '1,80p' "$f" | rg -n 'export async function generateMetadata|alternates|canonical|metadata' -C 4 || true
done
printf '\n--- Next docs candidates ---\n'
find node_modules/next/dist/docs -path '*metadata*' -maxdepth 3 2>/dev/null | head -50 || true
printf '\n--- docs references to metadata inheritance/alternates ---\n'
rg -n --glob '*.{md,mdx,jsx,tsx,js,ts}' \
'metadata inheritance|alternate|canonical|generateMetadata|layout|route' \
node_modules/next/dist/docs 2>/dev/null | head -200 || trueRepository: BigSimmo/Database
Length of output: 246
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- src/app/layout.tsx ---'
sed -n '1,120p' src/app/layout.tsx
echo
echo '--- route/generateMetadata metadata occurrences ---'
rg -n --glob '*.{ts,tsx}' \
'generateMetadata|metadata\s*=|\balternates\s*:[^}]*canonical\s*:' \
src/app || true
echo
echo '--- Next docs metadata references ---'
if [ -d node_modules/next/dist/docs ]; then
rg -n --glob '*.{md,mdx,jsx,tsx,js,ts}' \
'metadata inheritance|alternate|canonical|generateMetadata|layout|route segment|segment.*metadata' \
node_modules/next/dist/docs 2>/dev/null | head -120 || true
else
echo 'node_modules/next/dist/docs not present'
fiRepository: BigSimmo/Database
Length of output: 34143
🌐 Web query:
Next.js app router generateMetadata route segments metadata are merged inheritance documentation
💡 Result:
In the Next.js App Router, metadata inheritance and merging follow a hierarchical evaluation process [1][2]. Evaluation Order Metadata is evaluated from the root segment down to the segment closest to the final page.js segment [1][2]. Merging Behavior Metadata objects exported from multiple segments in the same route are shallowly merged together [1][2]. If a child segment defines a field that already exists in a parent segment, the child's value will override the parent's value [1]. This can result in the loss of nested data if not handled carefully [1]. For example, if a parent layout defines an openGraph object and a child page defines its own openGraph object, the child's openGraph object will completely replace the parent's, rather than merging nested properties like description [1]. Inheritance via generateMetadata To manage inheritance and preserve parent values when using the generateMetadata function, you can utilize the parent parameter, which is a promise that resolves to the metadata of the parent segments [3][4][2]. This allows you to selectively override or extend parent metadata [5]. Example: Extending Parent Metadata async function generateMetadata({ params }, parent) { const previousImages = (await parent).openGraph?.images || [] return { openGraph: { images: ['/new-image.png',...previousImages], }, } } Key Considerations 1. Shallow Merging: Next.js performs shallow merging by default [1][2]. If you need to preserve nested structures, you must manually spread the parent's data as shown above [1][5]. 2. File-based Metadata: Special files (like opengraph-image.png) have the highest priority and will override any metadata defined in the metadata object or generateMetadata function [3][4]. 3. Exclusivity: You cannot export both a static metadata object and a generateMetadata function from the same route segment [3][4][2]. 4. Server Components: Both metadata object and generateMetadata are only supported in Server Components [3][4][2].
Citations:
- 1: https://en.nextjs.im/docs/app/api-reference/functions/generate-metadata/
- 2: https://nextjs.org/docs/15/app/api-reference/functions/generate-metadata
- 3: https://nextjs.org/docs/app/api-reference/functions/generate-metadata
- 4: https://www.nazarboyko.com/articles/nextjs-seo-metadata-sitemaps-open-graph-structured-data
- 5: Open graph properties are not inherited in children routes metadata vercel/next.js#58189
Set the canonical at the home route instead of the root layout.
In the App Router, metadata is shallow-merged from parent layouts, so this root-layout canonical is inherited by child routes unless they override alternates.canonical. As written, routes without their own override will emit / as their canonical.
🤖 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/app/layout.tsx` around lines 33 - 35, Remove the alternates.canonical
configuration from the root layout metadata. Define canonical "/" only in the
home route’s metadata so child routes do not inherit it unintentionally.
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. ❌ Cannot run autofix: This PR has merge conflicts. Please resolve the conflicts with the base branch and try again. Alternatively, use |
|
Closing without merge after the 2026-07-27 open-PR review + Bugbot sweep. Why: Same unsafe dirty-checkpoint lineage as previously closed #1255/#1253 ( Do not sync this tip onto main. If any non-RAG workflow bits are still wanted, open a fresh PR from current |
This PR addresses the recent audit recommendations and fixes all remaining regressions, specifically:
ag-query-guard.ts\ to properly integrate \corpusGrounding\ categorization before LLM invocation, ensuring deterministic out-of-corpus query behavior.
Summary by CodeRabbit
New Features
Bug Fixes
Chores