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
6 changes: 4 additions & 2 deletions docs/branch-review-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie
| 2026-08-09 | claude/document-viewer-phase-3-bj5k5v | 156db63f1b60f09791e426b043ea90d427b789ab | post-#1772 test simplification: replace the viewer perf source-text grep with behavioural coverage; de-literalise rail window and keyboard label assertions | PR #1777 opened. Self-review of #1772's own tests against an excessive-strictness challenge. Finding: the client-performance-boundaries grep for resolveLiveCanvasWindow / resolveRenderAheadPages / liveCanvasLimit / requestIdleCallback was not merely brittle, it was INEFFECTIVE - replacing the budget call with a hardcoded 3 leaves every identifier in the file, so it stayed green while the viewer retained three full-zoom canvases (measured both ways). Replaced by a DOM case that binds the budget (VIEWER_MAX_ZOOM at dpr 3 gives ~16.8M backing px against the 24M budget, window collapses to 1) and fails on exactly that substitution. Also exported RAIL_IMAGE_WINDOW so the rail test derives its counts (verified by tuning 6->8: all 7 still pass), and relaxed the keyboard aria-label assertions from exact prose to the key names. Pre-existing greps for disableAutoFetch / canvas.width = 0 / pageToCleanup left alone deliberately - two are now redundant but they are another author's guard. | verify:pr-local (1 pre-existing root-only failure: pr-handoff-stop #291; 5872 passed), build OK 80s + client bundle secret check, eval:rag:offline 36 golden cases / 574 tests, lint + typecheck clean. Sabotage-verified in both directions. Browser gates unrunnable here (#279) - unchanged by this diff. |
| 2026-08-09 | claude/planning-build-intelligence-9ot0nm | 3df3cb3993f73cda4dbbc4ac7549f84b3c6ea7ed | Node 24.15 engine floor: engines.node, preinstall hook, check:runtime, session-start provisioning, codex-cloud assertion | Authored and handed off as PR #1771; closes #285; operationalRisk true, clinicalRisk/ragRanking false | test 5800 passed/1 pre-existing root-uid failure (pr-handoff-stop, confirmed on stashed clean tree); lint 0; typecheck 0; prettier --check . pass; check:runtime pass; check:codex-cloud pass; check:outstanding-issues pass; preinstall boundary proof 24.13/24.14.9 reject, 24.15/24.19 accept, 25.0.0 reject; contract test mutation-checked red |
| 2026-08-09 | pull/1771 | 466ec4216272c31c5f754db213dbdc529583b167 | PR 1771 runtime floor enforcement | P2: Cloud and Desktop setup paths remain major-only; do not merge until range-aware | static review; check:runtime PASS; check:codex-cloud PASS; ledger PASS; outstanding issues PASS; focused Vitest blocked by active Playwright lease |
| 2026-08-09 | PR #1782 / cursor/fix-document-open-scroll-e5bf | 5709f2cc7a954197e02107c96d7896d8d13445c3 | document-viewer open-at-top | ship: remove chunk mount scrollIntoView so document opens stay at overview top | document-viewer-shell.dom 7 pass; document-section-summary.dom 8 pass; verify:pr-local dry-run |
| 2026-08-09 | cursor/therapy-card-densify-e975 | 3db839a6bb1f5b45fc55bb732d21b30551a506b0 | therapy search ResultCard densify (gap, tags, favourite, actions, match cells) | pass — denser cards; band gap fixed; single-row prioritized tags; heart top-right; 3-col actions; summarised cells | unit 35/35; verify:pr-local pass; ensure visual phone+desktop pass |
| 2026-08-09 | claude/m3-token-debt-262-261 | c6e1fe7fc42ec6f286eb5a3d8f7ddad7dfad2724 | design-system contract: raw padding/radius/line-height ratchets + type-step selection gate (#262 parts 2/3); closed #218/#270 | Authored and self-verified; PR #1780 open, auto-merge deliberately not armed (gate change). Baseline additive: all 15 pre-existing metrics and every debtByPath entry byte-identical; 94/94 new findings verified present at their cited line. Mutation-tested both halves of part 3 and three failure modes of part 2. | check:design-system-contract, check:icon-scale, check:type-scale, check:outstanding-issues, vitest design-system-contract-utils (31 passed), format:check whole-tree, verify:cheap (exit 1 from 5 pre-existing failures, none in this diff; 3 cleared by merging main, remaining 2 byte-identical to origin/main) |
| 2026-08-09 | claude/documentviewer-nav-convergence-oddhjx | 1395d533cb13eadc705e47f76aa9f39a7a11c058 | DocumentViewer / in-page-nav convergence (#288): non-adoption decision recorded in docs/search-chrome-behaviour.md; merged duplicated visible-element predicate into resolveVisibleElement; new convergence guard test | Converged what was duplicated; DocumentReviewer header adoption declined on the merits with four blocking reasons recorded. No contract test edited. | verify:pr-local (546/547 files, 5883 tests pass; sole failure tests/pr-handoff-stop.test.ts reproduced on pristine origin/main), verify:phone-chrome (contracts 123 pass; focused Chromium 7 pass), contract set 12 files/151 tests pass, lint, typecheck, format |
| 2026-08-09 | claude/disabled-button-accessibility-piclvr | 722abdb780c715c0a89df268ed48f6c741ffd569 | disabled-placeholder buttons -> aria-disabled + inert handler (25 sites, 13 components); controlDisabled/therapy recipe aria-disabled styling; require-button-wiring redundantDisabledPair gate; wiring-conventions contract rewrite (settles #291) | authored — PR #1778 opened | lint (uncached, exit 0); typecheck; test 5878 passed/1 pre-existing root-env failure in pr-handoff-stop; build; check:rag:fixtures 36 golden cases; prettier --check clean; verify:ui not run (no browser in container) |
Expand All @@ -850,6 +850,8 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie
| 2026-08-09 | claude/m3-token-debt-262-261 | 7bac3bd762b381cb25c9b2a15ef3bb7223d15b16 | PR #1780 review-and-fix | fixed P2 ratchet bypasses (arbitrary-property classes, CSS-consumer exemption anti-rot, modern CSS zero units); Bugbot clean; merge-tree clean; required CI was green on prior tip | vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption fail→restore; verify:cheap PASS (549 files / 5933 tests); verify:pr-local stages PASS (test flake in design-system-adoption timed out once then 51/51 + full test 549/549 + check:rag:fixtures PASS); no provider gates |
| 2026-08-09 | cursor/dsm-search-header-fix-15d6 | df088c766f1761496189ec09146aa54c23b1c012 | dsm-search-header | pass: removed catalogue page strip; ribbon + category filter match target | vitest dsm-search-empty-state; npm test 5857 passed; lint; typecheck; ensure phone /dsm/search?q=Delirium |
| 2026-08-09 | claude/m3-token-debt-262-261 | fe75e6acade008e68f953e235cc035f2e5d9d216 | PR #1780 review-and-fix | fixed P2 ratchet bypasses; synced origin/main (#1775); Bugbot clean; merge-tree clean | vitest design-system-contract-utils 32/32; check:design-system-contract; mutation CSS-exemption; verify:cheap PASS 549/5933; verify:pr-local stages PASS after adoption flake retest; check:rag:fixtures PASS; no provider gates |
| 2026-08-09 | cursor/fix-document-open-scroll-e5bf (PR #1782) | 98029875db7d640d3e699829249bb33892296bff | PR #1782 unblock | before: static-pr+coverage failed on stale adoption-manifest (document-viewer-shell testFiles drift), merge-tree clean 0 behind, auto-merge armed, 1 advisory CodeRabbit waitFor thread; after: regenerated adoption-manifest, hardened scroll negative assertion, pre-commit+handoff adoption sync to prevent recurrence; CodeRabbit dispositioned as fixed by sync assert | check:design-system-adoption PASS; vitest design-system-adoption+document-viewer-shell+docs-inventory 63/63 PASS; format; no provider-backed checks |
| 2026-08-09 | cursor/therapy-card-densify-e975 | 52f07d49f89e6c786c624ccbd38ae552818a2071 | PR 1783 babysit | fixed review threads: TagRow +N clip, title/alias preview exclusion, preview field fallbacks; Copilot md grid kept; CI re-triggered after Copilot tip | npm test: 5958 passed / 4 skipped |
| 2026-08-09 | claude/in-page-nav-pr-3-i6gi8n | 6651feef4fab63f1181fba57908cb22e2932df3c | in-page-nav PR 3: convert /medications/[slug] (panel-swap) and /factsheets/[slug] (anchors) onto InPageNavHeader; record the differentials-presentations exception; delete orphaned SecondaryNavigation (#271) | converted 2 of 3 routes, 3rd recorded as a reasoned lasting exception; tocFor and SecondaryNavigation deleted; route-sections contract 7 -> 12 routes plus a panel-swap suite | verify:pr-local (1 pre-existing root-permission failure in pr-handoff-stop.test.ts, all else green); test 5932 passed; in-page-nav-route-sections 29 passed; verify:phone-chrome 3/4 stages (focused-browser blocked by #255 Chromium 1194 vs 1234); build + bundle-budget + rag:fixtures green; verify:ui not run (#255, delegated to CI) |
| 2026-08-09 | PR #1782 / cursor/fix-document-open-scroll-e5bf | 5709f2cc7a954197e02107c96d7896d8d13445c3 | document-viewer open-at-top | ship: remove chunk mount scrollIntoView so document opens stay at overview top | document-viewer-shell.dom 7 pass; document-section-summary.dom 8 pass; verify:pr-local dry-run |
| 2026-08-09 | cursor/fix-document-open-scroll-e5bf (PR #1782) | 98029875db7d640d3e699829249bb33892296bff | PR #1782 unblock | before: static-pr+coverage failed on stale adoption-manifest (document-viewer-shell testFiles drift), merge-tree clean 0 behind, auto-merge armed, 1 advisory CodeRabbit waitFor thread; after: regenerated adoption-manifest, hardened scroll negative assertion, pre-commit+handoff adoption sync to prevent recurrence; CodeRabbit dispositioned as fixed by sync assert | check:design-system-adoption PASS; vitest design-system-adoption+document-viewer-shell+docs-inventory 63/63 PASS; format; no provider-backed checks |
| 2026-08-09 | cursor/fix-document-open-scroll-e5bf (PR #1782) | 86698228533ebe10452c10c1bd7a3e1610d891ae | PR #1782 unblock | merged origin/main (behind-but-clean); fixed static-pr TS2322 on document-viewer-shell chunk fixture; fixed Production UI DSM compare remove stall via location.assign + DOM proof; prior adoption-manifest drift already fixed | tsc clean for changed files; vitest document-viewer-shell+dsm-compare-remove+design-system-adoption 59/59 PASS; check:design-system-adoption PASS; format; no provider-backed checks |
68 changes: 68 additions & 0 deletions src/components/therapy-compass/data/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,74 @@ export function summarise(text: string | null, sentences = 1): string {
return parts.slice(0, sentences).join(" ").trim();
}

/**
* True when a sentence is only a therapy-name restatement, or starts with that
* name before a word boundary (alias suffixes like `(CT)` / `, DT`, or prose
* such as "Behavioural activation is…"). Prefix-sharing words without a
* boundary ("Behavioural activationism") stay.
*/
function isExcludedTitleSentence(part: string, exclude: string): boolean {
if (!exclude) return false;
const normalized = part.toLowerCase().replace(/[.]+$/, "").trim();
if (!normalized) return false;
if (normalized === exclude) return true;
const escaped = exclude.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
return new RegExp(`^${escaped}\\b`).test(normalized);
}

/**
* Compact card copy: skip a leading sentence that merely restates the therapy
* name (common in clinicalSummary), then return up to `maxSentences` of the
* remainder. Empty when nothing useful remains.
*/
export function cardPreviewText(
text: string | null | undefined,
options: { exclude?: string | null; maxSentences?: number } = {},
): string {
if (!text) return "";
const maxSentences = options.maxSentences ?? 1;
const exclude = (options.exclude ?? "").trim().toLowerCase().replace(/[.]+$/, "");
const parts = text
.split(/(?<=\.)\s+/)
.map((part) => part.trim())
.filter(Boolean);

const useful = parts.filter((part) => !isExcludedTitleSentence(part, exclude));

return useful.slice(0, maxSentences).join(" ").trim();
}

/**
* Surface filter/query-relevant tags first so a one-row TagRow shows what
* matched the search rather than the catalogue's domain prefix.
*/
export function prioritiseTherapyTags(
tags: string[],
options: { query?: string; activeTags?: string[] } = {},
): string[] {
if (!tags.length) return tags;
const active = new Set((options.activeTags ?? []).map((tag) => tag.toLowerCase()));
const tokens = (options.query ?? "")
.toLowerCase()
.split(/[^a-z0-9/+-]+/)
.map((token) => token.trim())
.filter((token) => token.length >= 2);

const rank = (tag: string) => {
const lower = tag.toLowerCase();
if (active.has(lower)) return 0;
if (tokens.some((token) => lower === token || lower.includes(token) || token.includes(lower))) {
return 1;
}
return 2;
};

return tags
.map((tag, index) => ({ tag, index, rank: rank(tag) }))
.sort((a, b) => a.rank - b.rank || a.index - b.index)
.map((entry) => entry.tag);
}

export function reviewStatusMeta(status: string): { label: string; tone: "warning" | "success" | "neutral" } {
if (status === "reviewed") return { label: "Reviewed", tone: "success" };
if (status === "needs_review") return { label: "Needs source review", tone: "warning" };
Expand Down
4 changes: 2 additions & 2 deletions src/components/therapy-compass/screens/search-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function SearchScreen() {
const [filterOpen, setFilterOpen] = useState(false);

return (
<section data-screen-label="Search" className={pageContainer}>
<section data-screen-label="Search" className={`${pageContainer} space-y-2.5 sm:space-y-3`}>
<SearchResultsHeaderBand
modeId="therapy-compass"
query={q}
Expand All @@ -70,7 +70,7 @@ export function SearchScreen() {
/>
}
filterControls={
<div className="flex flex-wrap gap-2.5 mb-6">
<div className="mb-1 flex flex-wrap gap-2.5 sm:mb-2">
{QUICK_TAGS.map((tag) => {
const on = b.search.tags.includes(tag);
return (
Expand Down
Loading
Loading