diff --git a/docs/audit/primary-checkout-reconciliation-2026-07-24.md b/docs/audit/primary-checkout-reconciliation-2026-07-24.md new file mode 100644 index 000000000..baf3c5340 --- /dev/null +++ b/docs/audit/primary-checkout-reconciliation-2026-07-24.md @@ -0,0 +1,117 @@ +# Primary checkout reconciliation — 2026-07-24 + +## Scope and decision rule + +This record covers the dirty primary checkout and the final cloud-chat salvage wave. The canonical +integration base was freshly fetched `origin/main`; the dirty primary checkout was never used as a +merge base. Content was included only when it had a current-main reproducer or exact content proof, +was isolated into a coherent PR, and passed its proportionate local and hosted gates. + +No branch, commit, uncommitted source file, or secret-bearing worktree was discarded. Rejected and +deferred material remains recoverable from local archive refs and verified bundles. + +## Preservation proof + +| Snapshot | Archive ref / commit | Evidence | Disposition | +| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | +| Primary wave 1 | Checkpoint commit `faa50e6e3d245b3bf82aa2446f26a64a8f00f430` (the original archive branch later advanced to the wave-2 child) | 102 legitimate paths checkpointed; 23 exact current-main duplicates, 48 local-only paths, 31 divergent paths, 12 paths containing conflict markers | Classified file-by-file; never replayed as one patch | +| Primary wave 2 | `archive/pre-reconcile/primary-dirty-wave2-20260724-164509` and `archive/pre-reconcile/primary-dirty-20260724-153023` at `ffb66e26bde09f97b697b53a8a37ec687688b7d0` | Preserved an interrupted merge: 62 changed paths versus wave 1, of which 33 matched current main and 29 were merge-resolution-unique; 21 paths contained conflict markers | Archive-only merge artifact; not an independent implementation | + +The first verified bundle is external to the repository: + +- `C:\Dev\Apps\Database-pre-reconciliation-20260724-153023.bundle` +- Size: 79,853,865 bytes. +- SHA-256: `56091EDC0570FAECD38847ABC79A7A6D46E0ECBDAC3FCACB9C012BBAF35979B1`. +- `git bundle verify` passed and reported complete history with 458 refs. +- Earlier July 19 and July 23 bundles remain independent and were not replaced. + +The untracked `debug-f29a16.log` was deliberately excluded from Git and bundles. It is ordinary +machine-local debug output, not source. The final external reconciliation manifest records its +preserved destination and hash after primary synchronization. + +A high-signal secret scan found no newly added credential or private key in either snapshot. One +key-like match was a historical GitHub branch name in `docs/branch-review-ledger.md`; it was verified +against GitHub metadata without printing or retaining a secret value. + +## Landed content + +| PR | Result | Behaviour boundary | +| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| #1125 / merge `1cb3ff8941f66194dccb3de341b2d0325f5e62b3` | #061 fails closed when source relevance metadata is absent | Presentation policy only; no retrieval, ranking, generation, provider, or data change | +| #1143 / merge `9d1d38e7e81445011fde44fe91ca50c48b3baf40` | #052 atomically prevents reindex work from overlapping active enrichment | Transactional, owner-scoped RPC with disposable PostgreSQL/Docker replay and schema/drift proof | +| #1152 / merge `1c30a9d3e923d64ddc07f1e194cb9bdd6851b982` | #062 surfaces aged queued uploads without jobs and provides guarded recovery | Scheduled monitoring alerts only; recovery remains dry-run and confirmation-first | +| #1163 / merge `2f407e8facc800c6f00761c682b292debb8a97aa` | Invalid summary-mode requests fail closed and selected-document scope is enforced | API contract only; no retrieval behaviour change | +| #1161 / merge `7a81cfaa9064d7e1c4d50488e2dfa0926887a0e9` | Deterministic in-app back navigation, dirty safety-plan confirmation, mode-aware privacy return, and Sheet teardown hardening | UI/navigation/focus only; protected browser checks passed | +| #1164 / merge `3f4e24948ef0a9022d2a12108af61de29d69612b` | Trusted PR policy now also runs for `release/**` targets | Workflow trigger coverage only | + +Each merge was made through protected main only after required hosted checks passed and actionable +review threads reached zero. The reviewed head was then proved ancestral to fetched `origin/main`, +and the merge tree was compared with the intended fetched main tree before starting the next PR. + +## Already represented or superseded + +- Current main already contained the Next.js 16.2.11 security update from PR #1091; dependency and + lockfile hunks from the dirty snapshot were not replayed. +- Action pinning, service-worker isolation, existing upload budgets, active indexing-agent safety, + and several browser expectations were duplicates or weaker variants of current-main controls. +- 23 wave-1 paths and 33 wave-2 paths were exact current-main content at their comparison points. +- The old back-navigation PR #1121 was rebuilt cleanly as #1161. Draft #1151's browser-history + design was rejected because an external or unrelated history entry can eject a deep-linked user. + +## Explicitly rejected content + +The following material is preserved but must not be ported wholesale: + +- Removing `.npmrc` `allow-scripts=true`; npm 11 recognises the supported `allowScripts` policy and + the archive change weakens rather than repairs the control. +- Favourites changes that replace the accessible disabled-placeholder convention with unwired + affordances, and differential/home changes that regress current map, related-link, or placeholder + behaviour. +- A layout font import through the internal `next/dist/next-devtools` path and a hydration test that + references a non-existent specification. +- The unregistered prompt-perfector skill and its unsupported workspace semantics. +- Conflict-corrupted audit-plan, service catalogue, source/evidence, settings, upload, answer, and + private-route hunks from either primary snapshot. +- Search-chrome changes that restore `router.back()`, answer-render changes that undo #061's + fail-closed policy, and safety/privacy changes that reintroduce patient identifiers or undo #060. +- Source-authority changes that infer authority from user-controlled upload identity or remove + current governance safeguards. +- Ingestion/reindex changes that bypass #052's atomic RPC, and stale atomic-upload/schema hunks now + superseded by #062 and current migrations. +- Broad PDF crop retention, arbitrary padding/thresholds, storage expansion, or extraction timeout + increases without a real current-main malformed-asset reproducer. +- The old 31-file non-RAG salvage patch, stale browser expectations, score-spreading/comparator + changes, bulk alias widening, semantic-reranking enablement, or any protected RAG patch without a + separate current-main reproducer and the repository's canary safeguards. +- Wave 2's 29 merge-resolution-unique paths as a group: they are products of an interrupted merge, + not a coherent reviewed implementation, and 21 files still contain conflict markers. + +## Deferred, not lost + +- #075 records the valid part of mixed PR #1132: source-label enumeration can silently truncate at + the Supabase 1,000-row response cap. It requires an isolated bounded-pagination reproducer and PR; + the mixed dependency/PDF/Sheet/search patch must not merge. +- #076 records the only safe next step for PR #1129: reproduce malformed fallback PDF assets with a + real fixture before changing image retention, crop geometry, storage, or time budgets. +- Active Cursor/Codex/Claude/Antigravity and secret-bearing worktrees remain registered and + untouched. Reconciliation completion does not imply ownership or deletion authority for those + independent tasks. +- Provider-backed rollout debt remains governed by `docs/outstanding-issues.md`. No live RAG, + OpenAI, Supabase data mutation, Railway mutation, or production migration was required for this + final salvage wave, and no RAG evaluation budget was spent. + +## Final synchronization contract + +After this record lands, the operator sequence is: + +1. Create and verify a final `--all` Git bundle containing the archive refs and merged refs. +2. Preserve the excluded debug log outside the repository. +3. Fetch `origin`, switch the primary checkout to `main`, and use `git merge --ff-only` only. +4. Prove `main == origin/main`, `git diff --quiet main origin/main`, a clean primary status, and no + active Git operation markers. +5. Retain active or secret-bearing worktrees; remove only task-owned clean worktrees whose heads are + merged and present in the verified bundle. + +The dated external manifest carries the final bundle hash, final main SHA, primary status, and +worktree cleanup evidence so this repository record never claims a synchronization step before it +has actually occurred. diff --git a/docs/outstanding-issues.md b/docs/outstanding-issues.md index ca1982cbc..4502f1425 100644 --- a/docs/outstanding-issues.md +++ b/docs/outstanding-issues.md @@ -53,7 +53,7 @@ removed after current-main verification; it is not missing recommended work. | 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. | | 2 | `#053` | A1 | Operator — legal/privacy | Start now; finish before real patient use/privacy-approved release | 4–8 hours internal; 1–6 weeks elapsed | Execute DPAs; decide ZDR/residency; obtain cache behavior in writing; review subprocessors; obtain APP 8 and APP 5/1 counsel sign-off. Do not change public copy before approval. | | 3 | `#067` | A3 | High — test reliability | Next flake-hardening window | 1–2 hours | Reproduce the load-sensitive reconciliation-preflight subprocess timeout, instrument its lifecycle, and make the smallest deterministic harness fix. Do not raise the global timeout or bypass the shared heavy-test lock without causal proof. | -| 4 | `#030` | A2 | High — evaluation semantics | Decision-ready | 2–4 hours | Require distinct source identities for distinct comparison slots. Run focused matching tests, typecheck, and `verify:cheap`; stop without changing strict aliases, retrieval, or ranking. | +| 4 | `#030`, `#075` | A2 | High — search correctness | Decision-ready | 2–4 hours each | Handle as separate PRs: #030 requires distinct source identities; #075 reproduces more than 1,000 labels and adds bounded pagination. Run focused contracts and `verify:cheap`; stop before alias, retrieval, or ranking changes without protected evidence. | | 5 | `#069` | A3 | Specialist — retrieval latency | After hosted apply of PR #1133 migrations; approval-gated live profile | 30–60 min | Operator applies `20260724120000`/`20260724130000`/`20260724130100`, then re-profiles `match_document_table_facts_text` (~70ms-class plans). Stop without mutating ranking or unpaid evals. Cloud agent blocked: no DB URL / MCP auth; live profile hit Unregistered API key. | | 6 | `#019` | A2 | Specialist — RAG answer pipeline | Local reproducer now; behavior change after `#051`/`#023` | 0.5–1 day reproducer | Reproduce admission-source loss in the fallback layer using PR #1096’s source shape. Any behavior change needs protected review and an approved baseline/post canary; stop if independently non-reproducible. | | 7 | `#054` | A2 | Standard locally; Operator hosted | Local safety identifier now; hosted next approved window | 15–30 min local; 1–2 hours hosted | Presence-check and fill confirmed secret/config gaps with distinct per-environment values. Never record values. Require clean readiness/secret checks; stop on ambiguous environment or project identity. | @@ -84,7 +84,7 @@ removed after current-main verification; it is not missing recommended work. | 32 | `#063` | A3 | High — product architecture + privacy | Only when the product owner wants to evaluate the feature | 0.5–1 day | Write a product/privacy/persistence brief for “Current Clinical Work” before storage or UI implementation. Stop if demand or safe persistence cannot be established. | | 33 | `#065` | A2 | High — document-viewer UI | Only when the user explicitly resumes the paused task | 0.5–1.5 days | Finish the compact source-text accordion, citation/search auto-open, print restoration, and 320/390/1280 px coverage. Keep the preserved branch untouched until explicit resume; no provider calls. | - + ## Open items @@ -138,6 +138,8 @@ removed after current-main verification; it is not missing recommended work. | #039 | P3 | rec | Consolidate catalogue toolbar patterns | Catalogue/search pages have independently evolved filter, sort, result-count and mobile toolbar behavior. Inventory the existing implementations and converge only the repeated interaction contract; do not flatten mode-specific search semantics. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | | #040 | P3 | rec | Add targeted visual-regression baselines | Keep a small approved baseline set for high-value desktop/mobile surfaces and accessibility modes instead of screenshotting every route. Start with account/settings, document viewer, mode homes and bottom-composer interactions; define an intentional-update workflow before enabling blocking comparisons. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | | #041 | P3 | rec | Extend the existing Factsheets reading model | Do not add a second patient-facing Factsheets mode. Future patient-content work should extend the existing Easy Read/Standard presentation and its accessibility/content contracts. Revisit only with a concrete user need and source-governance plan. | design audit reconciliation; session 2026-07-22 | 2026-07-22 | +| #075 | P2 | issue | Search-scope label enumeration can truncate after 1,000 rows | **Outcome:** every owner-visible source label can participate in scoped search without silently dropping rows at the Supabase response cap. **Next:** reproduce on current `main` with more than 1,000 distinct labels, then add bounded deterministic pagination and a focused multi-page regression. **Verify:** search-scope unit/API contracts, offline RAG contracts, `verify:cheap`, and production-readiness. **Stop:** do not replay mixed PR #1132, widen aliases, change ranking, or run a live canary unless the isolated fix demonstrably changes protected retrieval behaviour. | PR #1132 (`src/lib/search-scope.ts`, `tests/search-scope.test.ts`); primary reconciliation 2026-07-24 | 2026-07-24 | +| #076 | P3 | task | Reproduce malformed fallback PDF image/table crops | **Outcome:** a real current-main fixture proves whether fallback images or table crops are malformed before retention/storage behaviour changes. **Next:** capture one minimal authorised fixture, identify the exact extraction stage and expected geometry, and add a red Python/DOM regression. **Success:** the smallest fix preserves valid assets within existing count/byte budgets and signed-image privacy boundaries. **Stop:** do not merge broad PR #1129, arbitrary crop thresholds/padding, storage expansion, or timeout increases without the reproducer and budget evidence. | PR #1129; `worker/python/extract_pdf_assets.py`; `src/lib/image-filtering.ts`; primary reconciliation 2026-07-24 | 2026-07-24 | ## Resolved / archive