Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/cloud-profile/memory/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
- [Plain, brief communication style](communication-style-plain-and-brief.md) — answer first, numbered steps, no internal detail unless asked; saved in user-level CLAUDE.md
- [Ward Flow coordination state](ward-flow-coordination-state.md) — WA metro psychiatry patient flow: spec approved, Phase 1 executing, handoff lives in docs/ward-flow-phase-handoff.md
- [Ward Flow verification lessons](ward-flow-verification-lessons.md) — green tests missed a wrong value on every screen; verify claims, watch regression tests fail, look at the screen
- [Token usage hygiene](token-usage-hygiene.md) — no .claudeignore exists; grep before reading big dirs, delegate broad searches to Explore, don't shrink AGENTS.md
- [Token usage hygiene](token-usage-hygiene.md) — no .claudeignore exists; grep before reading big dirs, delegate broad searches to Explore, never drop a rule to save tokens (AGENTS.md is a deliberately small core plus docs/agents/ reference files)
- [Claude plugin native deps trap](claude-plugin-native-deps-trap.md) — `claude plugin install` skips npm deps; npm 11 blocks native builds; prove with stats+search, not the postinstall warning
14 changes: 10 additions & 4 deletions .claude/cloud-profile/memory/token-usage-hygiene.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ shape, so there was nothing to add there. [[dev-drive-project-location]] separat
of the repo's disk footprint — the same directory is the main _token_ risk for reads, not just disk space.

**How to apply:** Follow this automatically in every Database repo session; it needs no action or approval from
Josh each time. Do not shrink or restructure `AGENTS.md`/`CLAUDE.md` to save tokens even though they are large —
that size is deliberate (shared safety/process rules read by five different AI tooling systems, per the file's
own "AI tooling map"), and trimming it is a project decision for the team, not something to do unilaterally for
token savings.
Josh each time. Do not shrink `AGENTS.md`/`CLAUDE.md` by dropping or condensing rules to save tokens — those
rules are shared safety and process contracts read by five different AI tooling systems (per the file's own "AI
tooling map"), and cutting one is a project decision for the team, never something to do unilaterally for token
savings.

Their current shape is the result of one such project decision, taken deliberately in 2026-09: `AGENTS.md` is a
small always-loaded core — the boundaries that prevent irreversible harm, plus the sections a gate parses by
exact text — and an index. Every other rule keeps its heading there and its full text, verbatim, in a named file
under `docs/agents/`. So a large `AGENTS.md` is no longer the expected state, and a rule that is not in the core
has not been dropped; open the file the core names for it. Restoring the old single wall would undo that work.
1 change: 1 addition & 0 deletions .github/codex/prompts/run-pr-operator.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Read these files before acting:

- `AGENTS.md`
- `CLAUDE.md`
- `docs/agents/pull-request-workflow.md`
- `docs/codex-review-protocol.md`
- `.claude/skills/run-pr/SKILL.md`
- `.codex-run-pr/context.json`
Expand Down
590 changes: 49 additions & 541 deletions AGENTS.md

Large diffs are not rendered by default.

122 changes: 27 additions & 95 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ in it is already in force. This file is the **orientation layer** — what the s
it is laid out, how work flows through it. It deliberately does not restate AGENTS.md policy;
where the two ever disagree, **AGENTS.md wins**.

`AGENTS.md` is a small always-loaded core — the boundaries that prevent irreversible harm, plus
the sections a gate parses by exact text — and an index. Every other rule keeps its heading there
and its full text in a named file under `docs/agents/`. Read that file before acting in its area;
its rules are in force whether or not you have opened it.

| Need | Read |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Rules, gates, shortcuts, safety boundaries | `AGENTS.md` (auto-loaded) |
Expand All @@ -36,28 +41,16 @@ see the AI tooling map in `docs/agents-guide.md`.

## Highest-consequence rules

Full text and rationale in `AGENTS.md`. These are the ones most easily violated by accident:

- **Providers need explicit confirmation.** Never touch OpenAI, Supabase, GitHub/GitLab,
hosted CI, or any provider-backed workflow — including indirectly, via scripts, tests, or
release gates — without the user saying so. Prefer local/offline/mocked checks; report the
command and ask.
- **This is not the Next.js you know.** Next 16 has breaking changes versus most training
data. Read `node_modules/next/dist/docs/` before writing framework code.
- **RAG ranking surfaces are protected.** Flag the task _before_ editing anything under
`src/lib/rag/**`, clinical-search, retrieval-selection, ranking-config, answer-ranking,
the eval harness, or the golden fixture — even for a rename or a comment. Behaviour
changes need a live eval-canary pair. Read `docs/rag-behaviour/` first.
- **Supabase target is pinned.** Live project `Clinical KB Database`, ref
`sjrfecxgysukkwxsowpy`. The ref `qjgitjyhxrwxsrydablr` is stale — never use it. Migrations
target role `postgres`.
- **Check the review ledger before reviewing a branch or PR:**
`npm run ledger:lookup -- <ref> --scope "<scope>"`. Never scan or hand-write
`docs/branch-review-ledger.md`; it is a frozen historical table and new reviews use immutable records.
- **Never assume `localhost:3000`.** Use `npm run ensure` and the URL it prints.
- **Evidence is never compressed.** Paste the decisive line from a gate. Exit code 0 alone
is not proof — `verify:ui` can exit non-zero on lock-contention timeout rather than
soft-skipping green.
Full text and rationale in `AGENTS.md`, which now carries these boundaries in its core, ahead of
everything else: the provider confirmation boundary, Supabase project safety (merging a migration
reaches the live clinical database within seconds), RAG ranking protection, Railway project safety
and local server safety. The Next.js warning is the block at the top of `AGENTS.md`. Review-ledger
lookup before reviewing a branch or PR is in
[`docs/agents/codex-review-throttling.md`](docs/agents/codex-review-throttling.md), and the rule
that evidence is never compressed is in
[`docs/agents/external-skill-precedence.md`](docs/agents/external-skill-precedence.md).

Do not restate any of them here. A second copy is how these two files drift.

## Stack and runtime

Expand All @@ -80,55 +73,15 @@ dependencies. `npm install` also installs the repo's git hooks.
(`src/lib/demo-data.ts`, `public/demo-documents/`) via `isDemoMode()` in `src/lib/env.ts`.
Production never silently falls back — missing config fails loudly.

## Repository layout
## Repository layout and the two main flows

```
src/app/ Next.js App Router — (search-app) route group, api/, auth/, mockups/
src/components/ UI; clinical-dashboard/ is the shell, *-mockups.tsx are design scratch
src/lib/ ~200 modules — rag/, supabase/, validation/, observability/,
extractors/, webhooks/ are the extracted subdirectories
src/data/ Static clinical content (DSM, formulation, therapies indexes)
data/ Generated clinical snapshot exports loaded at runtime — regenerate, never hand-edit
supabase/ migrations/ (source of truth), schema.sql (mirror), functions/
worker/ Ingestion worker; worker/python/ is the OCR stack
scripts/ gates, eval, reindex, governance, dev — counted and mapped in docs/scripts-index.md
tests/ Vitest unit + Playwright E2E, side by side
docs/ Runbooks, governance, plans; docs/README.md categorises them
eslint-rules/ Repo-specific lint rules (see Conventions below)
mockups/ Notes for the design-scratch routes under src/app/mockups/
plugins/ plugins/clinical-kb/ Codex plugin manifest and workflow skill
.claude/ Claude Code agents, skills, hooks, settings
.agents/ Single-word skill catalogue (`npm run skills`)
.cursor/ Cursor project rules and local-agent configuration
.design-sync/ Generated design-system package metadata and validation notes
.githooks/ Installed by `npm install`; pre-push runs scripts/guard-push.mjs
.vscode/ Shared VS Code workspace recommendations and settings
```
The `src/` tree, the 15 app modes, and the two flows that matter — answer (read path) and
ingestion (write path) — are mapped in
[`docs/codebase-index.md`](docs/codebase-index.md), under "Orientation summary" and the detailed
sections that follow it. Start there for any real task.

Never commit: `.next/`, `node_modules/`, `coverage/`, `.env*`, `sample-documents/`, logs.

The product surface is **15 app modes** (`src/lib/app-modes.ts`) sharing one search shell:
answer, documents, services, forms, favourites, differentials, dsm, specifiers, formulation,
prescribing, tools, calculators, therapy-compass, factsheets, dictionary.

## The two flows that matter

**Answer (read path).** `/api/answer` → `src/lib/rag/rag.ts` orchestrates: hybrid retrieval
via Postgres RPCs (pgvector HNSW + tsvector/trigram) → `retrieval-selection` →
`answer-ranking` → routed OpenAI generation (fast vs strong) → `answer-verification` and
render policy → cited answer. If generation fails the quality gates it degrades to a
deterministic **source-only** answer that still cites real documents — that is expected
behaviour, not a bug. Responses cache in `rag_response_cache`.

**Ingestion (write path).** `/api/upload` → private `clinical-documents` bucket + a row in
`ingestion_jobs` → `worker/main.ts` (or the `indexing-v3-agent` Edge Function) claims the
job → extract (PDF/DOCX/XLSX/TXT) → OCR fallback → image captioning → chunking → OpenAI
embeddings → chunks, pages, images, embedding fields, index units, table facts → quality
gates in `document_index_quality`. Reindex commits atomically per generation
(`reindex-pipeline.ts`). Lifecycle detail: `docs/ingestion-state-machine.md`.

Both paths are owner-scoped: `owner-scope.ts`, `query-privacy.ts`, `authorization.ts`.

## Development workflow

```bash
Expand Down Expand Up @@ -166,38 +119,17 @@ applies; unknown non-document paths fail closed to heavy scope.

## Conventions the gates enforce

These fail builds, so they are worth knowing before you write code:

- **Button wiring.** Every `<button>` does something — handler, submit inside a form, or
navigation. A control unavailable for a stated reason uses `aria-disabled="true"` + an inert
handler + `title="… — coming soon"` + `sr-only` note; native `disabled` is for transient
inertness only, and the two attributes together fail lint. Enforced by
`eslint-rules/require-button-wiring.mjs`. Never blanket-disable the rule.
- **No orphan routes.** A new production page route needs an inbound link from real nav,
then `npm run sitemap:update`, a `docs/codebase-index.md` entry, and a reachability
assertion. Enforced by `tests/route-reachability.test.ts`.
- **Internal navigation** uses `<Link>` / `router.push` / server `redirect()` — never a raw
`<a href="/…">`. Build hrefs from `app-modes.ts`, `tools-catalog.ts`, `universal-search.ts`.
- **One search composer per page.** A page uses the shell/dashboard composer, an in-flow hero
composer, or the document-viewer composer — never two. Phone composers are edge-to-edge;
hidden chrome means zero reserve. Read `docs/search-chrome-behaviour.md` first.
These fail builds, so they are worth knowing before you write code. Button wiring, orphan routes,
internal navigation and the mockup exemptions are in
[`docs/agents/wiring-and-bundle-budget.md`](docs/agents/wiring-and-bundle-budget.md); the
one-composer rule is in `AGENTS.md` "Search chrome behaviour"; PR bodies as parsed input are in
[`docs/agents/external-skill-precedence.md`](docs/agents/external-skill-precedence.md). One
convention has no home in the rules layer and stays here:

- **Design tokens, not hex.** `eslint-rules/no-hardcoded-hex.mjs`, plus type-scale,
icon-scale, z-index-ladder, and lucide-icon-aria rules. Production tap targets are
`min-h-12` (48 px) — do **not** "fix" them down to `min-h-11` for a generic WCAG rule; that
reintroduces a known `ui-smoke` flake.
- **PR bodies are parsed input.** `scripts/pr-policy.mjs` hard-blocks merges when a
clinical-risk diff lacks a complete `## Clinical Governance Preflight` or a RAG-surface
diff lacks a satisfying `RAG impact:` line. Write those in full prose from
`.github/pull_request_template.md`, structure verbatim — paraphrasing silently fails.
- **Mockups are exempt from two gates, not all of them.** `src/app/mockups/**` and `*-mockups.tsx`
are design scratch and 404 in production, so they sit outside the **wiring** and **reachability**
gates — and nothing else. They are still compiled: they are typechecked like any source, and their
client chunks are still weighed by `check:bundle-budget` — but since 2026-08-09 against a separate
`mockups` scratch baseline (tolerance 25%), not the `production` one (tolerance 10%). That split
reconciled `/issues` `#013` and `#252`: the old single total charged design scratch against a
ceiling named as though it were production weight, which is how PR #1580 blocked at `+10.1%` for
chunks no user can load. See the "Bundle budget" section in `AGENTS.md`; a mockup-only PR can still
fail `Build`, just only on genuine runaway growth.

## Repo-specific tooling

Expand Down
65 changes: 59 additions & 6 deletions data/repo-awareness-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"version": "repo-awareness-snapshot-v1",
"captured_revision": {
"sha": "fad5e2698d964fa72208be23ee4b9bf125acafc7",
"committed_at": "2026-09-01T16:44:24Z"
"sha": "563896ea8b430830f0297e5f9ec6ae0644d88f99",
"committed_at": "2026-09-02T04:41:10+00:00"
},
"routes": {
"modes": [
Expand Down Expand Up @@ -1480,6 +1480,16 @@
"section": "root",
"catalogued": true
},
{
"path": "docs/agents/bug-hunter-shortcut.md",
"section": "agents",
"catalogued": false
},
{
"path": "docs/agents/claude-hook-scripts.md",
"section": "agents",
"catalogued": false
},
{
"path": "docs/agents/codex-cloud-environment.md",
"section": "agents",
Expand Down Expand Up @@ -1520,6 +1530,41 @@
"section": "agents",
"catalogued": false
},
{
"path": "docs/agents/dead-code-deletion.md",
"section": "agents",
"catalogued": false
},
{
"path": "docs/agents/external-skill-precedence.md",
"section": "agents",
"catalogued": false
},
{
"path": "docs/agents/pull-request-workflow.md",
"section": "agents",
"catalogued": false
},
{
"path": "docs/agents/repository-skills-and-issues.md",
"section": "agents",
"catalogued": false
},
{
"path": "docs/agents/upload-shortcut.md",
"section": "agents",
"catalogued": false
},
{
"path": "docs/agents/verification-gates.md",
"section": "agents",
"catalogued": false
},
{
"path": "docs/agents/wiring-and-bundle-budget.md",
"section": "agents",
"catalogued": false
},
{
"path": "docs/answer-page-redesign-handover.md",
"section": "root",
Expand Down Expand Up @@ -4367,9 +4412,9 @@
}
],
"counts": {
"documents": 566,
"documents": 575,
"catalogued": 111,
"uncatalogued": 455,
"uncatalogued": 464,
"sections": 21
}
},
Expand All @@ -4382,6 +4427,14 @@
},
"review_state": {
"records": [
{
"date": "2026-09-02",
"ref": "claude/instruction-tiering-n9vs14",
"head": "563896ea8b430830f0297e5f9ec6ae0644d88f99",
"scope": "Instruction tiering: AGENTS.md/CLAUDE.md always-loaded core plus docs/agents reference files",
"outcome": "No findings. Reorganisation only: all 662 non-blank AGENTS.md lines verified byte-identical across the post-change tree; the 48 removed CLAUDE.md lines are restatements whose canonical text was located in the rules layer. Gate-parsed sections quarantined in place; every heading retained as a pointer so external section-name references still resolve. Two guards repaired that the move would otherwise have weakened (docs/agents added to workflow scope maps and userFacingProductSurfaces).",
"checks": "verify:cheap (12050 passed; 2 pre-existing shallow-clone failures reproduced on unmodified origin/main); 10 doc-parsing test files 151 passed; check:gate-manifest; check:skills; docs:check-links; docs:check-scripts; check:repo-awareness-snapshot; check:migration-role; check:pr-policy; check:codex-cloud; ci-change-scope self-test; format:check; CI green (Static PR checks + PR required)"
},
{
"date": "2026-09-02",
"ref": "codex/smart-local-modes-20260901",
Expand Down Expand Up @@ -25680,8 +25733,8 @@
}
],
"counts": {
"records": 2662,
"refs": 1627
"records": 2663,
"refs": 1628
}
}
}
Loading
Loading