Skip to content

docs: record phase 6 re-audit - #100

Merged
BigSimmo merged 1 commit into
mainfrom
codex/phase-6-reaudit
Jun 29, 2026
Merged

docs: record phase 6 re-audit#100
BigSimmo merged 1 commit into
mainfrom
codex/phase-6-reaudit

Conversation

@BigSimmo

Copy link
Copy Markdown
Owner

Summary

  • Records the Phase 6 re-audit after the M2 merge and live Supabase migration.
  • Captures current clinical/security-sensitive path status, lower-confidence batch decision criteria, and remaining DocumentViewer follow-up rules.
  • Tightens the DocumentViewer indexed-source hit controls to compact icon controls while preserving accessible names and keyboard behavior.

Verification

  • npm run test -- tests/private-access-routes.test.ts tests/source-governance.test.ts tests/source-text-sanitizer.test.ts - 77 passed
  • npm run test:e2e:chromium -- tests/ui-smoke.spec.ts -g "search regressions avoid fetch errors and open viewer hits" - 1 passed
  • npm run verify:cheap - runtime, lint, typecheck, 583 Vitest tests passed
  • npm run verify:ui - 35 Chromium Playwright tests passed
  • npm run verify:release before release or handoff confidence claims
  • npm run format:check
  • npm run check:production-readiness - passed with expected local env warnings only
  • npm run check:supabase-project - passed against Clinical KB Database (sjrfecxgysukkwxsowpy)
  • npm run check:indexing - passed; 2065/2065 indexed, 0 failed jobs, 0 missing embeddings, 0 mixed-generation documents
  • npm run reindex:health - passed
  • npm run reindex:cleanup-staged - dry run found 0 eligible documents and 0 artifact rows

Clinical Governance Preflight

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy)
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed

Notes

  • This PR does not include dependency changes or M2 implementation changes.
  • Unrelated local work in scripts/classify-documents.ts was left unstaged and is not part of this PR.
  • npm run check:indexing needed a longer local timeout when run alone; it passed in 369s.

@BigSimmo
BigSimmo merged commit aa1b4ce into mainJun 29, 2026
6 checks passed
@BigSimmo
BigSimmo deleted the codex/phase-6-reaudit branch June 29, 2026 04:29
BigSimmo pushed a commit that referenced this pull request Jul 30, 2026
Addresses the Codex P2 on this PR and fixes my own mistake in the first attempt.
The correction itself is unchanged in substance: `documents_status_id_idx` is
canary-gated, not ordering-safe, because `rag-candidate-sources.ts:482` pairs
`.eq("status","indexed")` with an unordered `.limit(12)` and `(status, id)`
serves that equality. The reasoning stays in the runbook, which is the
authority; the ledger row now just points at it.
What changed is the shape. My first version added prose to #102's Detail cell,
which is the widest cell in that column — so Prettier repadded every row and the
diff became 63 insertions / 63 deletions. Row #133 records that this exact
whole-table behaviour has already caused mechanical conflicts that silently
stopped all CI, and it is very likely how the original correction was lost
between #1423 and main in the first place.
Three attempts established the rule empirically, since my first two hypotheses
were both wrong: growing the cell reflows (68 lines), *shrinking* it also
reflows (68 lines, because the column width tracks this cell), and trailing
whitespace padding does not help because Prettier trims it. The replacement is
therefore exactly the same length as the text it replaces — 97 characters — and
the diff is now 1 insertion / 1 deletion with Prettier reporting the file
unchanged.
Verified on an untouched row: before this, #100's Detail cell lost exactly one
padding space (3533 -> 3532 chars), which is what proved the column width, not
my cell's content, was driving the churn.
Gates: outstanding-issues guard 137 rows / unique ids; branch-review-ledger 117
live + 1206 archived, no duplicates; prettier clean. No SQL applied.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01361jh3eYVjJCzXWjAhdZiF
BigSimmo added a commit that referenced this pull request Jul 30, 2026
…#1440)
* docs(issues): re-apply #102's canary-gated correction lost to a merge
Codex raised this as a P2 on PR #1423: with the runbook corrected, ledger #102
still told an operator the `(status,id)` use was ordering-safe, so the two
operator entry points contradicted each other. A reply on that thread claimed
the fix landed in 2bdc245. It did not reach `main`.
Verified by content rather than by SHA, which matters here: #1423 was
squash-merged, so `git merge-base --is-ancestor` returns NO for every original
commit and proves nothing either way. Reading `docs/outstanding-issues.md` at
`origin/main` (0310c6a) shows the retracted sentence still present, while the
runbook correction and the test change from the same PR both landed.
Most likely cause, and it is a documented hazard: #1428 ("archive five
completed ledger rows") touched this same file on `main`, and #112 records that
`docs/outstanding-issues.md` conflicts present as ordinary content conflicts a
hurried resolution can settle by dropping one side. Union merge has since been
added to this file, but it would not have saved this case — both sides edited
the same sentence.
The row now mirrors the runbook's classification and names the runbook as the
authority if the two ever diverge again, so a future reader has a tie-breaker
rather than two equal-looking claims.
Gates: verify:cheap exit 0, Test Files 434 passed (434), Tests 4563 passed | 4
skipped. Outstanding-issues guard, branch-review-ledger guard, docs:check-links,
docs:check-scripts, prettier all pass. No SQL applied; no index created.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01361jh3eYVjJCzXWjAhdZiF
* docs(issues): correct #102 within the existing table width
Addresses the Codex P2 on this PR and fixes my own mistake in the first attempt.
The correction itself is unchanged in substance: `documents_status_id_idx` is
canary-gated, not ordering-safe, because `rag-candidate-sources.ts:482` pairs
`.eq("status","indexed")` with an unordered `.limit(12)` and `(status, id)`
serves that equality. The reasoning stays in the runbook, which is the
authority; the ledger row now just points at it.
What changed is the shape. My first version added prose to #102's Detail cell,
which is the widest cell in that column — so Prettier repadded every row and the
diff became 63 insertions / 63 deletions. Row #133 records that this exact
whole-table behaviour has already caused mechanical conflicts that silently
stopped all CI, and it is very likely how the original correction was lost
between #1423 and main in the first place.
Three attempts established the rule empirically, since my first two hypotheses
were both wrong: growing the cell reflows (68 lines), *shrinking* it also
reflows (68 lines, because the column width tracks this cell), and trailing
whitespace padding does not help because Prettier trims it. The replacement is
therefore exactly the same length as the text it replaces — 97 characters — and
the diff is now 1 insertion / 1 deletion with Prettier reporting the file
unchanged.
Verified on an untouched row: before this, #100's Detail cell lost exactly one
padding space (3533 -> 3532 chars), which is what proved the column width, not
my cell's content, was driving the churn.
Gates: outstanding-issues guard 137 rows / unique ids; branch-review-ledger 117
live + 1206 archived, no duplicates; prettier clean. No SQL applied.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01361jh3eYVjJCzXWjAhdZiF
* docs: record issue correction review
---------
Co-authored-by: Claude <noreply@anthropic.com>
BigSimmo pushed a commit that referenced this pull request Aug 13, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBdo125Dh3idPcF7CmCCmG
BigSimmo pushed a commit that referenced this pull request Aug 13, 2026
… preview
Incremental verified delivery per docs/verified-answer-incremental-delivery-design.md:
- answer-stream-contract: VerifiedUnit types and isDeliverableVerifiedUnit
(schema version, kind allowlist, strictly-increasing sequence, bounded JSON
size); the token/revising SSE event names remain excluded.
- answer-preview: buildEvidencePreviewUnit reuses the production danger-level
source-governance refusal and the exact route-boundary source trim; any
danger warning suppresses the preview entirely (stricter than the final
response, whose refusal only fires on grounded supported answers).
- answer-progress-public: optional verifiedUnit passthrough, dropped (never
repaired) when validation fails; old clients ignore the field.
- rag.ts: the retrieved progress event carries the preview only when
RAG_INCREMENTAL_EVIDENCE_PREVIEW=true (new env flag, default false in
env.ts and .env.example). No new SSE event name; Phase 2 per-section
generation is not attempted (provider-gated by design).
- tests/answer-incremental-delivery.test.ts: Phase 0 offline contract proof —
schema/sequence validation, token/revising rejection, governance refusal
emitting zero units, owner-boundary trimming, byte-identical preview/final
reconciliation at the trim layer, flag-off default.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBdo125Dh3idPcF7CmCCmG
BigSimmo pushed a commit that referenced this pull request Aug 27, 2026
… panel
Direction B from /mockups/answer-loading-redesign, applied to the live surface
after the clinical owner chose it (2026-08-27).
`AnswerProgressStepper` is gone. It was a filled accent panel carrying a 36px
icon tile, a five-circle stepper with connecting rails, a scrolling ECG trace, a
per-second elapsed counter and a Processing details disclosure — roughly 210px
of the loudest chrome in the product, occupying the answer's own position for
the four to twelve seconds before every answer, on a surface that PRs #2386 and
#2388 had just spent their whole argument quietening. It narrated the
orchestrator's five stages, which the reader is not operating, and it never
showed a single source.
`AnswerProgress` replaces it with one status line plus the arriving source rail.
The rail is the substantive half. The evidence preview already crossed the
stream boundary before the prose — trimmed, owner-scoped, governed, consumed by
the client — and was being rendered as a SECOND full panel below the stepper,
with its own icon tile, heading and three-column card grid. Two loud blocks in
the answer's position, both removed when the answer arrived. It is now a
horizontal rail of small cards drawn to look like the source rail the arrived
answer renders, mounted inside AnswerProgress rather than beside it, so nothing
is removed and nothing jumps when the answer lands.
Cards carry a dot, not a number. The preview is the top slice of retrieval in
retrieval order; the final list is rebuilt from what the answer cites and
re-capped by trust. A number assigned during the wait can point at a different
document once the answer lands, which is the precise failure the citation design
exists to prevent. Pinned by a DOM test, and stated in the rail's accessible
name for a reader who never sees the dot.
Checked while building, not assumed: `isDeliverableVerifiedUnit` pins
evidence_preview to sequence 0 and rejects a repeat, so the preview crosses once,
complete — it cannot accrue card by card. And it is gated behind
NEXT_PUBLIC_RAG_INCREMENTAL_EVIDENCE_PREVIEW_RENDER (#100 Phase 1), off by
default, so today the line carries the accrual alone via resultCount and the rail
is simply absent rather than a placeholder.
Improvements beyond the mockup:
- Retrieval counts passages and selection counts sources, never one noun for
both. Collapsing them is how a reader believes two dozen documents are behind
an answer that cites three. Pinned in tests/answer-progress.test.ts.
- `fallback` says "Assembling the answer from the sources directly" while it is
happening. Twenty of thirty answers in the 2026-08-18 blinded read were
source_only; the wait is the honest place to set that expectation.
- Processing details became "How this answer was built", shown only after a
retrying/fallback/cached run. The old disclosure held the same five stages for
every question, which is why nobody opened it.
- The elapsed counter is gone. In its place one threshold at 10s appends
"taking longer than usual" and does not tick. Nothing can be done with the
number while the search is healthy; re-drawing it every second in the position
the eye rests on is what made the wait the subject.
- SearchProgressBanner (library/document modes) loses its filled accent band and
spinning Loader2 for the same line. Fill is how this app marks a hazard.
- AnswerSkeleton drops its own status line. Found in the browser, not in a test:
it renders in the answer's body slot directly under AnswerProgress, so the
screen showed "Writing the answer…" above "Reading your question…". There is
now exactly one place that says what is happening.
- The completion dot is not green. A status hue that nothing else on the element
repeats is a colour-only signal, and it was redundant beside a line already
reading "Answer ready in 3s". Caught by check:design-system-contract.
Motion. The ECG trace, its two animation tokens, its keyframes and its
compositor rules are deleted; the indicator is a 5px dot breathing on opacity.
That choice is what holds the contract ui-phone-motion.spec.ts exists for, after
Reduce Motion set the trace to opacity 0 and left a dead panel on a physical
iPhone: a stopped dot is a complete, correct bullet, where a stopped spinner is a
fragment of a circle. The animation stays in globals.css rather than a
motion-safe: utility because html[data-motion="full"] must be able to opt back in
over the OS, which a Tailwind media variant cannot express.
tests/answer-activity-trace-css.test.ts pinned the deleted component, so it is
replaced by tests/answer-progress-indicator-css.test.ts carrying the same
regression forward against the dot — including an assertion that the trace stays
deleted, since a partial revival is how the original defect shipped.
docs/search-chrome-behaviour.md's physical-iPhone rubric named the ECG strip by
class and would have sent a tester hunting for markup that no longer exists;
docs/design-system/COMPONENTS.md named the component in its live-region adoption
note. Both updated — the second found by check:dead-code-candidate, which is the
gate doing its job.
Verified: verify:cheap exit 0 — 37 gates enforced, design-system contract passed
(1021 production files, no ratchet moved), 886 test files / 10733 tests passed;
Playwright chromium answer-progress-ui-smoke + ui-phone-motion 9 passed,
ui-universal-search 20 passed; driven in a real browser at 390px through
scoping → retrieving → retrieved(24) → ranking(4 AU, 2 WA) → generating and past
the 10s threshold, and again with the preview flag on to confirm six real cards
render, link to /documents/<id>?page=&chunk=, and carry no numbers.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012kHT2YKCNnUrVckTaJW6ga
Sign up for freeto 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

@BigSimmo