Skip to content

[codex] Clinical KB cleanup readiness - #13

Merged
BigSimmo merged 4 commits into
mainfrom
codex/clinical-kb-cleanup-readiness
Jun 3, 2026
Merged

[codex] Clinical KB cleanup readiness#13
BigSimmo merged 4 commits into
mainfrom
codex/clinical-kb-cleanup-readiness

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Aligns Clinical KB local runtime policy with CI by pinning Node 22 in .nvmrc, .node-version, package.json, and lockfile metadata.
  • Extracts dashboard search retry/fallback/progress/answer-usability helpers into src/components/clinical-dashboard/search-utils.ts with focused unit coverage.
  • Stabilizes Chromium browser smoke expectations for local/demo document states and current dashboard labels.
  • Removes unused Next starter SVG assets from public/ after confirming no references remain.

Risk Notes

  • No Supabase schema, auth, storage, queue, import, enrichment, or cleanup scripts were run.
  • Main is treated as the protected/base branch despite no GitHub branch protection.
  • The worktree shows Git CRLF/index noise on untouched files locally, but git diff, git diff --cached, and untracked checks are clean.
  • The cleanup keeps the larger dashboard/RAG/document-viewer architecture work deferred.

Dependency Changes

  • Runtime policy only: Node 22.x and npm >=10 are declared.
  • No package version upgrades were made.
  • npm ls --depth=0 exits 0 but reports optional wasm/native packages as extraneous; this is carried as a local npm/platform quirk.
  • ESLint 10 remains deferred because the repo currently uses ESLint 9.39.4 with eslint-config-next@16.2.7.

Redundancy Removed

  • Deleted unused starter assets: public/file.svg, public/globe.svg, public/next.svg, public/vercel.svg, public/window.svg.

Verification Evidence

Local verification under Node 22:

  • fnm exec --using 22 cmd /c npm ci passed; 0 vulnerabilities.
  • fnm exec --using 22 cmd /c npm ls --depth=0 exited 0.
  • fnm exec --using 22 cmd /c npm audit --json passed with 0 vulnerabilities.
  • fnm exec --using 22 cmd /c npm run check:supabase-project passed for Clinical KB Database (sjrfecxgysukkwxsowpy).
  • fnm exec --using 22 cmd /c npm run format:check passed.
  • fnm exec --using 22 cmd /c npm run lint passed after one inspected timeout retry.
  • fnm exec --using 22 cmd /c npm run typecheck passed.
  • fnm exec --using 22 cmd /c npm run test passed: 39 files, 240 tests.
  • fnm exec --using 22 cmd /c npm run build passed.
  • git diff --check HEAD -- passed.
  • Branch diff secret pattern scan passed.

App/API/browser QA:

  • fnm exec --using 22 cmd /c npm run ensure started the guarded local server.
  • /api/local-project-id confirmed Clinical KB, project id clinical-kb:5b6a50f62d5b, safe local origin on http://localhost:4298.
  • In-app browser smoke loaded the dashboard, confirmed title Clinical KB, rendered clinical dashboard content, and observed 0 console errors.
  • fnm exec --using 22 cmd /c npm run test:e2e:chromium passed: 20/20.
  • Repo-owned dev server was stopped after QA and port 4298 no longer accepted connections.

Known Deferrals

  • ESLint 10 upgrade is deferred until framework/config compatibility is explicitly addressed.
  • Larger architecture splits for dashboard, RAG orchestration, document viewer, and oversized tests are deferred.
  • Demo/sample corpus cleanup beyond documented ownership is deferred.
  • Supabase data/queue/storage cleanup remains out of scope without separate approval.

@BigSimmo
BigSimmo merged commit c44c5ce into main Jun 3, 2026
4 checks passed
@BigSimmo
BigSimmo deleted the codex/clinical-kb-cleanup-readiness branch June 3, 2026 19:43
BigSimmo added a commit that referenced this pull request Jul 22, 2026
cursor Bot pushed a commit that referenced this pull request Jul 28, 2026
Per /issues done: remove #12 from the recommended execution queue
composite (#13/#16 remain) and drop the Before #12 sequencing hint
on #17. #12 stays in Resolved/archive with the shipped outcome.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
BigSimmo pushed a commit that referenced this pull request Jul 30, 2026
Fourth genuine conflict on docs/outstanding-issues.md, confirmed with
git merge-tree before acting. Main's #1470 rewrote #13 as
measurement-gated while this branch changed #17, #105 and added #147.
Verified by hash that main touched neither #17 nor #105 — both are
byte-identical at the merge base and at origin/main — so those rows take
this branch's version and #13 takes main's, rather than either side
winning wholesale.

Also de-duplicated against main's new #118, which already owns adopting
the Lighthouse baseline and flipping enforce. #147's gate paragraph now
cross-references it instead of restating it, and contributes the
constraint #118 was missing: pinning a baseline today would bake CLS
0.363 on /dsm in as the accepted value, so the CLS fixes must land first
or the gate ratifies the breach.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01361jh3eYVjJCzXWjAhdZiF
cursor Bot pushed a commit that referenced this pull request Aug 5, 2026
* fix(gates): catch lint and type errors before push, not in CI

Two open PRs burned full CI cycles this week on defects a single local
command would have caught: #1606 on a react-hooks/set-state-in-effect lint
error, #1618 on a TS2339 for `mode.devOnly` (a union member that lacks the
property, where app-modes.ts already exports the correct `"devOnly" in mode`
guard). Neither lint nor typecheck was in the pre-push path.

Typecheck could not simply be added, because it was already unusable
(outstanding-issues #210). tsconfig.json's `include` carries
`.next/types/**/*.ts` and `.next/dev/types/**/*.ts` — gitignored build
artifacts — so deleting a page leaves the stale generated validator importing
a removed module. Reproduced rather than inferred: a planted
`.next/dev/types/validator.ts` referencing a removed mockup page yields
`error TS2307: Cannot find module .../mockups/deleted-mockup-route/page.js`,
base config exit 2, source-only config exit 0. Full source typecheck is clean
(71s cold, 8.8s warm). Red locally and green in CI is how the gate got
abandoned, which is how the real type error then reached CI.

- tsconfig.typecheck.json + `typecheck:source`: identical compiler options,
  minus the `.next` globs, with a separate tsbuildinfo so the two incremental
  caches cannot invalidate each other. Route-signature validation is not lost;
  `next build` still covers it in CI.
- guard-push.mjs gains a fourth guard running eslint over the pushed files and
  this typecheck. Verified to reproduce both defects above with CI-identical
  messages. Scoped to the lint roots and to pushes that touch TS, skips loudly
  when node_modules is absent rather than pushing people to
  GUARD_PUSH_DISABLE=1, and overridable with SKIP_STATIC_GUARD=1.

Also corrects a doc claim that made #1580 surprising: "mockups are exempt"
was being read as blanket. Mockups are exempt from the wiring and reachability
gates and nothing else — they are still typechecked, and their client chunks
still count toward check:bundle-budget, which totals every built chunk rather
than the initial production bundle. That the budget's scope contradicts
ledger #13's "not an initial production bundle" position is a real unmade
decision, now recorded as #237 rather than papered over.

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

* docs(issues): capture the phone Category soft-menu fix salvaged from PR #1606

#1606 is closed, but it carried the one fix nothing else in the queue provides:
MobileResultFilterControl's native <select> paints a harsh system-blue highlight
on phones, and #1615 keeps that native select (its change is the iOS 16px
anti-zoom rule). So the fix does not survive #1615 landing.

Records it as #238 with the two defects the redo must not repeat: the unresolved
keyboard trap on disabled options, and the set-state-in-effect lint error that
PR #1620's new pre-push guard would now catch.

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

* issues: capture #239 stale Cloud acceptance pin on PR #1617, #240 remote-container browser gate drift

* Tighten guard coordinator test

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>

* fix(gates): shared source-typecheck lease and safer static pre-push

Treat typecheck:source:internal as a shared read-only coordinator lease with
a distinct per-worktree buildinfo file, drop the pinned in-repo cache path,
and harden staticGuard: acquire a short exclusive lease (fail-open when busy),
use a private eslint cache, escalate lint on eslint policy changes, fail closed
when the push tip is not HEAD, cover eslint-rules, and add Vitest coverage.
Align hook/docs wording with the fourth guard and point CLAUDE.md at #252.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>

* fix(gates): keep tsBuildInfoFile when run-heavy has no npm_execpath

Pre-push invokes run-heavy via plain node, so the npm_execpath spawn path
was skipped and the fallback dropped effectiveForwarded — undoing the
per-worktree buildinfo injection. Also warn when staticGuard passes on a
dirty working tree.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>

* docs: refresh scripts-index for lint:changed:internal

Keep docs:check-inventory green after adding the pre-push eslint wrapper
script to package.json.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>

* fix(gates): address Devin findings on static pre-push guard

- Treat "Database focused-test capacity is full" as coordinator busy so
  shared typecheck slot exhaustion fails open instead of faking a type error.
- Skip source typecheck when every changed .ts path is excluded by
  tsconfig.typecheck.json (edge functions, archive, scratch, worktrees).
- Restore check-github-shell-access.mjs (and its Role notes) in the scripts index.

* chore(ledger): record PR #1620 babysit

* fix(gates): emit structured heavy-run admission-busy signal

Prefer exit 75 + DATABASE_HEAVY_RUN_ADMISSION_BUSY over prose matching so
tsc/eslint output that quotes busy strings cannot false-pass the static guard.

* fix(gates): tip-check only when static work runs; isolate typecheck cache

Addresses follow-up Devin on PR #1620:
- Reorder staticGuard so tip-vs-HEAD fails closed only when lint/typecheck
  will actually read the working tree; ignore tag refs in the tip check.
- Pin a distinct tsBuildInfoFile on tsconfig.typecheck.json so direct tsc
  does not collide with the base config cache (run-heavy still overrides).

* fix(gates): keep lint failures when typecheck admission is busy

Addresses Devin on PR #1620 — a prior eslint failure must still block the
push if the follow-up source typecheck cannot get a coordinator slot.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
BigSimmo pushed a commit that referenced this pull request Aug 9, 2026
check:bundle-budget totals every built chunk, mockups included, and main
sits at ~+9.4% against a 10% tolerance. The study's two scratch chunks
(~9.8 KiB gzip) alone took the repo to +10.1% and failed Build — the
same failure PR #1580 hit, at the same number.

Measured on this branch: main alone 308 chunks / 1538.9 KiB (+9.42%,
passing); with the study 310 / 1548.7 KiB (+10.1%, failing); without it
309 / 1542.4 KiB (+9.67%, passing). The implementation itself adds no
new route chunk — it edits existing components.

Direction 02 has shipped, so the runnable route had already served its
purpose. A design-scratch route that 404s in production is the wrong
thing to spend the last of that headroom on, and raising the baseline
would have settled the open #13/#252 question — whether scratch should
count toward this budget at all — by default, in the direction of "raise
the ceiling". mockups/README.md keeps the three directions and says why
the route went, so the alternatives stay recoverable from history.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBAt8pJVz2TxMEUJeWEdUy
BigSimmo added a commit that referenced this pull request Aug 9, 2026
…tes, and pin the factsheet heading census (#1779)

* test(factsheets): census every h1 in the factsheet detail document

The hero <h1> and the portaled print sheet's <h1> are correct and mutually
exclusive by construction: on screen `.factsheet-print-sheet { display: none }`
removes the print subtree, and in print
`html.factsheets-printing body > *:not(.factsheet-print-portal)` removes the
shell that owns the hero. Neither state exposes two headings to the
accessibility tree, and the printed PDF is a separate document whose section
headings are already <h2>, so demoting its title would leave it with no
top-level heading.

The real gap was that the existing assertion was scoped to the page testid, so
the document-level invariant was asserted nowhere and a stray third <h1> would
not have been caught. Pin the census instead: exactly two, one per container,
both carrying the title, plus a non-empty <h2> outline in the print sheet.
jsdom applies no stylesheet, so a census is the right guard rather than a
visibility assertion.

FactsheetPrintSheet stays in factsheet-detail-page.tsx —
design-system-contract-utils.mjs scopes its raw-colour exemption to the literal
factsheet-print-sheet marker and fails closed if it moves.

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

* docs(testing): record the verified recipe for restoring local browser gates

The remote/Cloud drift note said to delegate browser proof to CI and left the
impression that local gates were unrecoverable. They are recoverable; the
blocker was two separate image faults, and the second is why the obvious fix
looks impossible.

The baked node_modules is stale or incomplete — containers have shipped none at
all, and earlier ones reported playwright 1.62.0 against a locked 1.62.1 with
tailwind-merge absent entirely, which is an incomplete install rather than a
version skew, so the lockfile pin was never wrong. And npm ci cannot repair it
because jsdom@30.0.1 requires node ^22.22.2 || ^24.15.0 || >=26.0.0 while images
have shipped v24.13.0, so the install dies on EBADENGINE under engine-strict.

Installing Node 24.19.0 clears that, npm ci then exits 0 and parity reports all
seven pinned packages, and `npx playwright install` supplies Chromium 1234
(images ship only 1194). Verified end to end this session, launch included.

Keeps the existing Stop intact and makes it cheap to honour: install the
matching revision rather than forcing a run against 1194.

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

* fix(bundle-budget): split production weight from mockup scratch

One number could not honestly answer two questions. totalGzipBytes summed every
built client chunk, including src/app/mockups/** design scratch that 404s in
production, against a ceiling named as though it were production weight. #13
held that mockup chunks are not a production bundle; this gate charged them
anyway, which is how PR #1580 blocked at +10.1% for chunks no user can load.
#252 recorded the contradiction and left the metric undecided.

Measured on a clean build of main at af85cbc, the blur had become the whole
signal: 1546.5 KiB total was +9.96% of the 1406.4 KiB baseline — 576 bytes from
failing Build — while production-only was 1279.1 KiB, 9.06% BELOW that same
baseline. Every byte of the apparent regression was design scratch (267.5 KiB
across 76 chunks over 66 mockup routes) and production had actually shrunk.
latency-audit-2026-07-28 corroborates: 1,309,274 bytes then against 1,309,772
production-only now, flat to +0.04%, so the 2026-08-04 bump to 1,440,201 had
absorbed mockup growth as production growth. Raising the ceiling again would
have hidden that permanently, so this splits rather than ratchets.

production (10%) covers every chunk a non-mockup route reaches plus chunks no
manifest claims — framework, polyfills, runtime. mockups (25%) covers chunks
reachable only from /mockups/**, as a runaway detector rather than a
per-mockup gate; a ceiling tight enough to fire on the next mockup would just
be --update'd reflexively. A chunk shared by both counts as production because
it would be built either way.

Attribution reads the per-route *_client-reference-manifest.js files under
.next/server/app, since Next 16 webpack emits no app-build-manifest.json, and
fails closed when that tree is missing or resolves no routes so the buckets can
never silently collapse. Both fail paths proven against the real build.

Also captures #296: pr-handoff-stop.test.ts fails in any root container because
it chmods a fixture dir to force a write failure and root ignores permission
bits — pre-existing, reproduced on clean af85cbc.

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

* fix(bundle-budget): fail closed on bad manifests and zero baselines

Review feedback on PR #1779: treat unparseable route manifests as fatal
attribution errors instead of counting them as resolved empty routes, and
handle a zero mockup/production baseline without NaN percentage math.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
BigSimmo pushed a commit that referenced this pull request Aug 13, 2026
…ion design

Cancels the original request and re-files it, using the inbox's own supersede
mechanism rather than editing an immutable request.

The original said 'drop the Outcome column (or replace each cell with a
pointer)'. Building it on 2026-08-13 established that dropping the column is
wrong and that two other constraints are load-bearing, none of which are
visible from reading the code:

  - The rewrite cannot be a direct edit, and cannot even be code-only. It has
    to run inside applyRequestBatch — the function check-ledger-write-discipline
    imports — and land in the same commit as a reconcile, or the checker
    computes normalise(base) against an un-normalised canonical and fails every
    PR.
  - Dropping the column makes the queue vanish from /issues, because
    issues-report skips any queue row whose cells.length !== 7.
  - Composite ID(s) rows must keep their prose. Derivation deliberately skips
    them, so they still fall back to the Outcome cell; blanking it leaves them
    with nothing. Found by running it: order 17 (#13, #16) rendered empty.

Recording these now because rediscovering them costs another build-and-revert
cycle, which is what this session just spent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DuYJz8hauCsCdx8r4fXiZU
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant