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
8 changes: 7 additions & 1 deletion data/outstanding-issues-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"p2": 49,
"p3": 31,
"queued": 7,
"pending": 84,
"pending": 85,
"resolved": 431
},
"queue": [
Expand Down Expand Up @@ -884,6 +884,12 @@
"summary": "#GQ5X8T: NOT REPRODUCED ON PINNED LINUX; WINDOWS-SPECIFIC CAUSE UNRESOLVED. Eleven retained PR #2313 ubuntu-24.04 Lighthouse artifacts used Lighthouse 12.8.2 and pinned HeadlessChrome/151.0.0.0. In the nine-run synchronized-baseline subset, mobile-root LCP was 2260.791-2300.923ms with median 2287.574ms versus 2274.017ms baseline (+13.557ms, +0.60%); TBT median was 430.602ms versus 436.600ms baseline (-1.37%); CLS was 0 throughout. Across all eleven heads LCP was 2221.675-2300.923ms, never reproducing the Windows 7422-8032ms state. The exact local 883f1007 control / 7cf37b53 treatment snapshots had identical lock hashes, but the local host stayed at 42.3-62.9% CPU and the control build hit the 10-minute Linux cap after compiling, before measurement; that attempt is environment-blocked and was not rerun. This excludes a repeatable cross-platform regression but cannot distinguish Windows host noise from a Windows-specific client regression. No product, budget, tolerance, request-count, or proven CLS change was made. Reopen if a pinned Linux exact-head run breaches repeatably or a synchronized quiet-host Windows control reproduces the slowdown. Evidence: docs/evidence/mobile-root-timing-control-2026-08-26.md.",
"created_at": "2026-08-26"
},
{
"request_id": "224cda1c-ae72-4921-b8aa-e6b3e315796a",
"action": "update",
"summary": "#ZBAC9D: detail → documents.owner_id is ON DELETE SET NULL (supabase/schema.sql) while a null owner independently means 'public corpus' in retrieval. CORRECTION (Codex on PR #2494): deleting an auth user does NOT silently republish private documents — documents_require_publication_approval (BEFORE INSERT OR UPDATE) runs guard_document_publication_transition, which rejects every non-null-to-null owner transition without matching publication evidence, so the user-delete transaction fails instead of orphaning/republishing. Distinguish blocked user deletion from any pre-existing orphan rows. RE-VERIFIED against main and the P2 -> P1 escalation still holds on the retrieval hazard, not on a live delete-to-publish path. (1) The retrieval path is NOT closed at any layer. public.retrieval_owner_matches still resolves the public sentinel to 'row_owner_id is null' with no public_corpus condition, and grep for 'public_corpus' returns ZERO occurrences across the entire retrieval chain: rag/rag-candidate-sources.ts, corpus-grounding.ts, deep-memory.ts, document-enrichment.ts, owner-scope.ts, clinical-search.ts and query-privacy.ts. Any ownerless row (pre-existing orphan or armed hole) is therefore retrievable as public corpus and citable in an answer to an anonymous query. (2) The helper written to close exactly this hazard is DEAD CODE. src/lib/documents/is-public-document.ts requires owner_id === null AND metadata.public_corpus === true, and tests/documents-is-public.test.ts:22 pins the precise case ('Orphaned after user delete' -> false), but grep across src/ and worker/ finds NO production caller outside its own module and the barrel re-export. Same shape as #A3AHCX. (3) The only genuinely closed application read path is the REST document read: withOwnerReadScope in src/lib/public-api-access.ts applies .is('owner_id', null).eq('metadata->>public_corpus','true'). NEXT, in order: (a) one read-only live count of documents where owner_id is null and metadata->>'public_corpus' is distinct from 'true' — this decides whether the hole is currently leaking or merely armed, and needs owner approval as a provider-backed read; (b) close the retrieval path, which is a genuine retrieval behaviour change on a protected RAG surface and so needs the RAG flag plus a live eval-canary pair; (c) add a database proof that deleting an owner of an unapproved private document fails and creates no ownerless indexed row, then in an approved production window change documents.owner_id to ON DELETE RESTRICT (or an explicit visibility column) and align the RPC predicate. Note the offline proof that no table whose null owner means public declares ON DELETE SET NULL cannot be added green today — it would fail on documents.owner_id, so it is the guard that accompanies (c), not a step that precedes it.; priority → P1; source → repo-wide audit at 3ed1932 (six domain reviewers); re-verified and expanded against main a633eb6e3 by the database coordination chat 2026-09-01; deletion-path correction per Codex review on PR #2494",
"created_at": "2026-09-01"
},
{
"request_id": "256a5104-df13-44d3-9734-645e08b2b0df",
"action": "cancel",
Expand Down
13 changes: 9 additions & 4 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": "612e9735c0096c046fad01a1b3a3b23482b3fc07",
"committed_at": "2026-09-01T17:10:51+08:00"
"sha": "bf4489206167d41e78e629e10194a3856616afea",
"committed_at": "2026-09-01T18:36:13+08:00"
},
"routes": {
"modes": [
Expand Down Expand Up @@ -573,6 +573,11 @@
"file": "src/app/mockups/development/page.tsx",
"area": "mockup"
},
{
"path": "/mockups/development/clinical-answer-failures",
"file": "src/app/mockups/development/clinical-answer-failures/page.tsx",
"area": "mockup"
},
{
"path": "/mockups/development/clinical-trust",
"file": "src/app/mockups/development/clinical-trust/page.tsx",
Expand Down Expand Up @@ -1420,9 +1425,9 @@
],
"counts": {
"modes": 15,
"pages": 198,
"pages": 199,
"product_pages": 63,
"mockup_pages": 135,
"mockup_pages": 136,
"redirects": 17,
"api": 60
}
Expand Down
1 change: 1 addition & 0 deletions docs/site-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -1199,6 +1199,7 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir
- `/mockups/caring-contacts/templates` - Route discovered from app directory Source: `src/app/mockups/caring-contacts/templates/page.tsx`.
- `/mockups/caring-contacts/templates/[pathwayId]` - Route discovered from app directory Source: `src/app/mockups/caring-contacts/templates/[pathwayId]/page.tsx`.
- `/mockups/development` - Route discovered from app directory Source: `src/app/mockups/development/page.tsx`.
- `/mockups/development/clinical-answer-failures` - Route discovered from app directory Source: `src/app/mockups/development/clinical-answer-failures/page.tsx`.
- `/mockups/development/clinical-trust` - Route discovered from app directory Source: `src/app/mockups/development/clinical-trust/page.tsx`.
- `/mockups/development/documentation` - Route discovered from app directory Source: `src/app/mockups/development/documentation/page.tsx`.
- `/mockups/development/ingestion` - Route discovered from app directory Source: `src/app/mockups/development/ingestion/page.tsx`.
Expand Down
124 changes: 124 additions & 0 deletions src/app/mockups/development/clinical-answer-failures/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import type { Metadata } from "next";

import { PanelPageShell } from "@/components/developer-area/hub/panel-page-shell";
import { CountTile, META_CLASS, PanelSection } from "@/components/developer-area/hub/panel-primitives";
import { referencedQuestionCount, resolveClinicalAnswerFailures } from "@/lib/developer-area/clinical-answer-failures";
import { loadLedgerSnapshot, resolveFreshness } from "@/lib/developer-area/ledger-snapshot";

export const metadata: Metadata = {
title: "Answer failures · Developer · PsychSift",
description: "Open ledger items that name one of the repository's clinical eval questions.",
};

export default function DeveloperClinicalAnswerFailuresPage() {
const snapshot = loadLedgerSnapshot();
const now = new Date();
const freshness = resolveFreshness(snapshot, now);
const failures = resolveClinicalAnswerFailures(snapshot);
const questions = referencedQuestionCount(failures);

return (
<PanelPageShell
testId="developer-clinical-answer-failures"
title="Answer failures"
freshness={freshness}
freshnessLabel="Ledger"
>
<div className="grid grid-cols-2 gap-3 sm:max-w-md">
<CountTile
testId="developer-clinical-answer-failures-count-items"
value={failures.length}
label={failures.length === 1 ? "open problem" : "open problems"}
/>
<CountTile
testId="developer-clinical-answer-failures-count-questions"
value={questions}
label={questions === 1 ? "question referenced" : "questions referenced"}
/>
</div>

{/*
* The scope caveat is page content, not a footnote, and it is deliberately
* above the list rather than below it. This page reports the intersection
* of two records — the task ledger and the eval case list — and that
* intersection is narrower than "clinical answer quality". Anyone reading
* an empty list here must not conclude the answer engine is well.
*/}
<p className={META_CLASS}>
Every open item in the task ledger that names one of the repository&rsquo;s clinical eval questions by its case
id. That is a narrower thing than a picture of answer quality: a recorded problem that does not name a case is
not listed here, and a question that is failing right now but that nobody has written up is not either. An empty
list means nothing is <em>recorded</em> against a named question, not that every question answers well.
</p>
{/*
* The correction from review of #2498, and the reason the questions below
* are labelled as referenced rather than affected. An item names a case for
* more than one reason: `#J8SJQ9` names the discharge-documentation case as
* the *contrast* that legitimately answers with a source pointer. Nothing in
* the text separates that from a case being reported broken, so the page
* asserts at the level it can stand behind -- the item -- and leaves the
* reader to open it.
*/}
<p className={META_CLASS}>
The questions under each item are the ones its text <em>names</em>, not a verdict on each question. An item may
name a question as the contrast that is behaving correctly, so read the item before concluding that a question
listed here answers badly.
</p>

<PanelSection
headingId="developer-clinical-answer-failures-heading"
heading={`Recorded problems naming a clinical question · ${failures.length}`}
>
{failures.length > 0 ? (
<ul className="grid gap-3">
{failures.map(({ item, cases }) => (
<li
key={item.id}
data-testid={`developer-clinical-answer-failure-${item.id}`}
className="grid gap-2 rounded-xl border border-[color:var(--border)] p-4"
>
<p className="text-sm font-extrabold leading-6 text-[color:var(--text-heading)]">{item.summary}</p>
<p className={META_CLASS}>
{item.id} · {item.priority} · recorded {item.added}
</p>
<p className="text-xs font-bold text-[color:var(--text-muted)]">Questions this item names</p>
<ul className="grid gap-1">
{cases.map((testCase) => (
<li key={testCase.id} className="text-sm leading-6 text-[color:var(--text)]">
{/*
* The question as a clinician would ask it, with the case
* id beside it rather than instead of it. The id is what
* makes the match verifiable; the question is what makes
* the entry mean anything to a reader.
*/}
&ldquo;{testCase.question}&rdquo;
<span className="block text-xs text-[color:var(--text-muted)]">{testCase.id}</span>
</li>
))}
</ul>
</li>
))}
</ul>
) : (
/*
* In words, never a blank container: an empty result and a failed load
* look identical otherwise, and here the difference matters more than
* usual because the empty state is the reassuring-looking one.
*/
<div
data-testid="developer-clinical-answer-failures-empty"
className="grid gap-2 rounded-xl border border-[color:var(--border)] p-4"
>
<p className="text-sm leading-6 text-[color:var(--text-heading)]">
No open ledger item names a clinical eval question.
</p>
<p className={META_CLASS}>
That is the ledger being quiet, not the answer engine being proven well. Answer quality itself is measured
by the eval runs, which this page does not read.
</p>
</div>
)}
</PanelSection>
</PanelPageShell>
);
}
22 changes: 22 additions & 0 deletions src/app/mockups/development/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { Metadata } from "next";
import Link from "next/link";
import { ShieldAlert } from "lucide-react";

import { DeveloperHubNavHeader } from "@/components/developer-area/developer-hub-nav-header";
import { EnvironmentStrip } from "@/components/developer-area/hub/environment-strip";
import { PanelCard } from "@/components/developer-area/hub/panel-card";
import { inPageAnchor } from "@/components/in-page-nav/in-page-nav-classes";
import { resolveClinicalAnswerFailures } from "@/lib/developer-area/clinical-answer-failures";
import { resolveHubEnvironmentFacts } from "@/lib/developer-area/environment-facts";
import { panelsInGroup, type HubPanelGroup } from "@/lib/developer-area/hub-panels";
import { loadLedgerSnapshot } from "@/lib/developer-area/ledger-snapshot";
Expand Down Expand Up @@ -52,6 +54,7 @@ const GROUPS: { id: HubPanelGroup; anchor: string; label: string }[] = [
export default async function DeveloperHubPage() {
const snapshot = loadLedgerSnapshot();
const environment = await resolveHubEnvironmentFacts();
const clinicalAnswerFailures = resolveClinicalAnswerFailures(snapshot);

return (
<>
Expand Down Expand Up @@ -113,6 +116,25 @@ export default async function DeveloperHubPage() {
</p>
) : null}

{/*
* Warning, not danger: these are recorded problems against named
* clinical questions, and today they are P2/P3 rather than blocking.
* Painting them the same red as the blocking band would teach the reader
* to discount both. The band exists at all because the same facts sit
* unread inside an 81-item ledger, which is the whole reason this panel
* was built.
*/}
{clinicalAnswerFailures.length > 0 ? (
<Link
href="/mockups/development/clinical-answer-failures"
data-testid="developer-hub-clinical-answer-failures-band"
className="rounded-xl border border-[color:var(--warning)]/40 bg-[color:var(--warning-soft)] px-4 py-3 text-sm text-[color:var(--text)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]"
>
{clinicalAnswerFailures.length} recorded {clinicalAnswerFailures.length === 1 ? "problem" : "problems"}{" "}
against a named clinical question.
</Link>
) : null}

{GROUPS.map((group) => {
const panels = panelsInGroup(group.id);
// An empty group must render no anchor at all. `useResolvedPageSections`
Expand Down
Loading
Loading