diff --git a/.ralph/agent/memories.md b/.ralph/agent/memories.md index 6daae02..7123f74 100644 --- a/.ralph/agent/memories.md +++ b/.ralph/agent/memories.md @@ -2,6 +2,10 @@ ## Patterns +### mem-1771284742-cc7f +> Stage 1 canonical descriptive text foundation now exists in src/data/profile-content.ts with strict schema in src/types/profile-content.ts and typed selectors in src/lib/profile-content.ts; this is additive and preserves existing consumer behavior until migration checkpoints. + + ### mem-1771245168-48e8 > Canonical timeline data now lives in src/data/timeline.ts and legacy consultations/constellation exports are compatibility layers derived from it, removing duplicated date/year maintenance. @@ -30,6 +34,14 @@ ## Fixes +### mem-1771284167-9e36 +> failure: cmd=sed -n '1,260p' ralph/prompt.md, exit=2, error=No such file or directory, next=locate actual prompt path with rg --files and use correct casing/location + + +### mem-1771284072-053c +> failure: cmd=sed -n '1,260p' Ralph/PROMPT.md, exit=2, error=No such file or directory (path case mismatch), next=use lowercase path ralph/prompt.md + + ### mem-1771246458-9388 > failure: cmd=rg -n "--font-mono\b|font-mono-dashboard|font-geist-mono|timeline-intervention|chronology|pathway" src/index.css, exit=2, error=pattern beginning with -- parsed as flag, next=use rg -n -- '' diff --git a/.ralph/agent/scratchpad.md b/.ralph/agent/scratchpad.md new file mode 100644 index 0000000..df94d16 --- /dev/null +++ b/.ralph/agent/scratchpad.md @@ -0,0 +1,18 @@ +# Scratchpad + +## 2026-02-16T23:27:00Z — Planner Stage 1 framing +- Confirmed next unchecked rollout stage is Stage 1 in `Ralph/PROMPT.md`. +- Inventory completed across `src/data`, `src/components`, and search/chat builders. Major duplication centers are component literals (`PatientSummaryTile`, `Sidebar`) and builder-layer hardcoded text (`search.ts`, `llm.ts`) versus existing canonical domain data. +- Planned Stage 1 as schema + canonical module + typed access helpers + thin adapters only, with no component migration yet, to minimize regression risk. +- Confidence: 92/100. High confidence because scope is additive and preserves existing export contracts while preparing Stage 2/3 migrations. + +## 2026-02-16T23:33:00Z — Builder Stage 1 Checkpoint A complete +- Implemented additive canonical text foundation only (no consumer rewires): + - `src/types/profile-content.ts` defines typed schema for profile, sidebar copy, results, education entries, quick actions, and LLM prompt content. + - `src/data/profile-content.ts` is now the single editable canonical module seeded with current descriptive literals from `PatientSummaryTile`, `Sidebar`, `search.ts`, and `llm.ts`. + - `src/lib/profile-content.ts` adds typed selectors (`getProfileContent`, `getProfileSummaryText`, `getSidebarCopy`, `getSearchQuickActions`, `getLLMCopy`). +- Quality gates passed: + - `npm run lint` (warnings only, no errors) + - `npm run typecheck` + - `npm run build` +- Confidence: 91/100. Safe additive checkpoint with no runtime behavior changes. diff --git a/.ralph/agent/tasks.jsonl b/.ralph/agent/tasks.jsonl index af7bda4..0eb8323 100644 --- a/.ralph/agent/tasks.jsonl +++ b/.ralph/agent/tasks.jsonl @@ -33,3 +33,5 @@ {"id":"task-1771251477-81a2","title":"Visual: Entry animation reveal effects","description":"Role nodes scale from 0 with ease-out-back. New skill nodes scale from 0 with ease-out. Links draw on via stroke-dashoffset. Year indicator top-left monospace. Replace Phase 2 entry animation with timeline-driven animation.","status":"closed","priority":2,"blocked_by":[],"loop_id":"primary-20260216-135722","created":"2026-02-16T14:17:57.098724221+00:00","closed":"2026-02-16T14:31:18.740781337+00:00"} {"id":"task-1771251479-1473","title":"Integration: Wire animation to highlight system (Phase 4)","description":"Multiplicative opacity: animation(0/target) × highlight(1.0/0.15). Hover/tap pauses animation. Highlight only on revealed nodes. Resume 800ms after interaction ends. Explicit pause via button stays paused. Play/pause toggle bottom-right. Mobile accordion + keyboard nav + detail panel work during pause. prefers-reduced-motion shows final state.","status":"closed","priority":2,"blocked_by":[],"loop_id":"primary-20260216-135722","created":"2026-02-16T14:17:59.857204916+00:00","closed":"2026-02-16T14:31:18.838001047+00:00"} {"id":"task-1771251482-f0e9","title":"Accessibility: reduced-motion + play/pause button","description":"prefers-reduced-motion skips animation entirely, shows final state. Play/pause button with aria-label, subtle styling, larger touch target on mobile.","status":"closed","priority":2,"blocked_by":[],"loop_id":"primary-20260216-135722","created":"2026-02-16T14:18:02.061675075+00:00","closed":"2026-02-16T14:31:18.930889962+00:00"} +{"id":"task-1771284229-34e9","title":"Plan Stage 1 canonical content schema","description":"Planner hat: identify next unchecked stage and update .ralph/plan.md with scoped file-level migration plan","status":"closed","priority":1,"blocked_by":[],"loop_id":"primary-20260216-232330","created":"2026-02-16T23:23:49.734442590+00:00","closed":"2026-02-16T23:29:43.798920375+00:00"} +{"id":"task-1771284608-2942","title":"Stage1 Checkpoint A: add canonical profile content schema/module/helpers","description":"Create src/types/profile-content.ts, src/data/profile-content.ts, and src/lib/profile-content.ts with typed, centralized descriptive text and selectors; no consumer migration in this task.","status":"closed","priority":1,"blocked_by":[],"loop_id":"primary-20260216-232330","created":"2026-02-16T23:30:08.665923960+00:00","closed":"2026-02-16T23:32:25.469667619+00:00"} diff --git a/src/data/profile-content.ts b/src/data/profile-content.ts new file mode 100644 index 0000000..487b579 --- /dev/null +++ b/src/data/profile-content.ts @@ -0,0 +1,211 @@ +import type { ProfileContent } from '@/types/profile-content' + +export const profileContent = { + profile: { + patientSummaryNarrative: 'Healthcare leader combining clinical pharmacy expertise with proficiency in Python, SQL, and data analytics, self-taught over the past decade through a drive to find root causes in data and build the most efficient solutions to complex problems. Currently leading population health analytics for NHS Norfolk & Waveney ICB, serving a population of 1.2 million. Experienced in working with messy, real-world prescribing data at scale to deliver actionable insights, from financial scenario modelling and pharmaceutical rebate negotiation to algorithm design and population-level pathway development. Proven track record of identifying and prioritising efficiency programmes worth £14.6M+ through automated, data-driven analysis. Skilled at translating complex clinical, financial, and analytical requirements into clear recommendations for executive stakeholders.', + latestResults: { + title: 'LATEST RESULTS (CLICK TO VIEW FULL REFERENCE RANGE)', + rightText: 'Updated May 2025', + helperText: 'Select a metric to inspect methodology, impact, and outcomes.', + evidenceCta: 'Click to view evidence', + }, + sidebar: { + sectionTitle: 'Patient Data', + roleTitle: 'Pharmacy Data Technologist', + gphcLabel: 'GPhC No.', + educationLabel: 'Education', + locationLabel: 'Location', + phoneLabel: 'Phone', + emailLabel: 'Email', + registeredLabel: 'Registered', + navigationTitle: 'Navigation', + tagsTitle: 'Tags', + alertsTitle: 'Alerts / Highlights', + searchLabel: 'Search', + searchAriaLabel: 'Search. Press Control plus K', + searchShortcut: 'Ctrl+K', + menuLabel: 'Menu', + }, + }, + experienceEducation: { + educationEntries: [ + { + title: 'NHS Leadership Academy — Mary Seacole Programme', + subtitle: 'NHS Leadership Academy · 2018', + keywords: 'nhs leadership academy mary seacole programme 2018 qualification management', + }, + { + title: 'MPharm (Hons) — 2:1', + subtitle: 'University of East Anglia · 2011–2015', + keywords: 'mpharm hons 2:1 university east anglia uea 2011 2015 pharmacy degree', + }, + { + title: 'A-Levels', + subtitle: 'Highworth Grammar School · 2009–2011', + keywords: 'a-levels mathematics chemistry politics highworth grammar school 2009 2011', + }, + { + title: 'GPhC Registration', + subtitle: 'General Pharmaceutical Council · August 2016', + keywords: 'gphc registration general pharmaceutical council 2016 registered pharmacist', + }, + ], + }, + skillsNarrative: { + summary: 'Technical, domain, and leadership capabilities spanning data analysis, medicines optimisation, and executive communication with practical delivery across population-scale NHS prescribing programmes.', + }, + resultsNarrative: { + achievements: [ + { + title: '£14.6M Efficiency Savings Identified', + subtitle: 'Data-driven prescribing interventions', + keywords: '14.6m efficiency savings identified data-driven prescribing interventions money cost', + kpiId: 'savings', + }, + { + title: '£220M Budget Oversight', + subtitle: 'Full analytical accountability to ICB board', + keywords: '220m budget oversight analytical accountability icb board', + kpiId: 'budget', + }, + { + title: 'Power BI Dashboards for 200+ Users', + subtitle: 'Clinicians & commissioners across ICB', + keywords: 'power bi dashboards 200 users clinicians commissioners', + kpiId: 'years', + }, + { + title: '1.2M Population Served', + subtitle: 'Norfolk & Waveney Integrated Care System', + keywords: '1.2m population served norfolk waveney ics integrated care system', + kpiId: 'population', + }, + ], + }, + searchChat: { + quickActions: [ + { + title: 'Download CV', + subtitle: 'Export as PDF', + keywords: 'download cv export pdf resume', + type: 'download', + }, + { + title: 'Send Email', + subtitle: 'andy@charlwood.xyz', + keywords: 'send email contact andy charlwood', + type: 'link', + url: 'mailto:andy@charlwood.xyz', + }, + { + title: 'View LinkedIn', + subtitle: 'Professional profile', + keywords: 'view linkedin professional profile social', + type: 'link', + url: 'https://linkedin.com/in/andycharlwood', + }, + { + title: 'View Projects', + subtitle: 'GitHub & portfolio', + keywords: 'view projects github portfolio code repositories', + type: 'link', + url: 'https://github.com/andycharlwood', + }, + ], + llm: { + systemPrompt: `You are a helpful assistant on Andy Charlwood's portfolio website. Answer questions about Andy's professional background using ONLY the information below. + +## Profile +Andy Charlwood — MPharm, GPhC Registered Pharmacist. Norwich, UK. +Healthcare leader combining clinical pharmacy with Python, SQL, and data analytics (self-taught). Leading population health analytics for NHS Norfolk & Waveney ICB, serving 1.2M people. Specialises in prescribing data at scale — financial modelling, algorithm design, pathway development. Identified efficiency programmes worth £14.6M+ through automated analysis. + +## Employment Timeline (IMPORTANT) +- **NHS employment**: May 2022–present (all roles at NHS Norfolk & Waveney ICB). Total NHS service: ~4 years. +- **Private sector**: Nov 2017–May 2022 at Tesco PLC (community pharmacy). This was NOT NHS employment. +- GPhC registration (Aug 2016) is a professional licence, NOT an employer or NHS role. + +## Career History + +### [exp-interim-head-2025] Interim Head, Population Health & Data Analysis +NHS Norfolk & Waveney ICB | May–Nov 2025 +Led population health initiatives and data-driven medicines optimisation, reporting to Associate Director of Pharmacy with accountability to CMO. +- Identified £14.6M efficiency programme; achieved over-target performance by October 2025 +- Built Python switching algorithm: real-world GP prescribing data, 14,000 patients, £2.6M annual savings (£2M on target), compressed months into 3 days +- Novel GP payment system linking rewards to savings; 50% prescribing reduction within 2 months +- Presented to CMO bimonthly; led transformation to patient-level SQL analytics + +### [exp-deputy-head-2024] Deputy Head, Population Health & Data Analysis +NHS Norfolk & Waveney ICB | Jul 2024–Present (substantive role) +Data analytics strategy for medicines optimisation from real-world GP prescribing data. +- Managed £220M prescribing budget with forecasting models for proactive financial planning +- Created comprehensive dm+d medicines data table: standardised strengths, morphine equivalents, Anticholinergic Burden scoring — single source of truth for all medicines analytics +- Led DOAC switching financial modelling: interactive dashboard with rebate mechanics, patent expiry timelines +- Renegotiated pharmaceutical rebate terms ahead of patent expiry +- Tirzepatide commissioning (NICE TA1026): financial projections, cohort identification; authored executive paper advocating primary care model, driving system shift to GP-led delivery +- Built Python controlled drug monitoring: oral morphine equivalents across all opioid prescriptions, patient-level tracking, high-risk identification, diversion detection +- Improved team data fluency through training and self-serve tools + +### [exp-high-cost-drugs-2022] High-Cost Drugs & Interface Pharmacist +NHS Norfolk & Waveney ICB | May 2022–Jul 2024 +Led NICE TA implementation and high-cost drug pathways across the ICS. Pathways spanning: rheumatology, ophthalmology (wet AMD, DMO, RVO), dermatology, gastroenterology, neurology, migraine. +- Blueteq automation: 70% form reduction, 200 hours immediate savings, 7–8 hours ongoing weekly gains +- Integrated Blueteq with secondary care databases for accurate high-cost drug spend tracking +- Python Sankey chart tool for patient pathway visualisation and trust compliance auditing + +### [exp-pharmacy-manager-2017] Pharmacy Manager +Tesco PLC (private sector, NOT NHS) | Nov 2017–May 2022 +Community pharmacy with full operational autonomy (100-hour contract). LPC representative for Norfolk. +- Asthma screening process adopted nationally (~300 branches): reduced pharmacist time 60→6 hours/store/month, ~£1M revenue +- Leadership training: Created national induction training plan and eLearning modules for Tesco pharmacy staff +- Leadership development: Supervised two staff through NVQ3 to pharmacy technician registration; full HR responsibilities + +## Projects + +### [proj-inv-pharmetrics] PharMetrics Interactive Platform (2024, Live) +Real-time medicines expenditure dashboard for NHS decision-makers. Tech: Power BI, SQL, DAX. Tracks £220M prescribing budget. + +### [proj-inv-switching-algorithm] Patient Switching Algorithm (2025, Complete) +Python algorithm using GP prescribing data to auto-identify patients for cost-effective alternatives. Tech: Python, Pandas, SQL. 14,000 patients, £2.6M annual savings, novel GP payment system. + +### [proj-inv-blueteq-gen] Blueteq Generator (2023, Complete) +Automated Blueteq prior approval form creation. Tech: Python, SQL. 70% form reduction, 200 hours immediate savings, 7–8 hours ongoing weekly gains. + +### [proj-inv-cd-monitoring] CD Monitoring System (2024, Complete) +Controlled drug monitoring calculating oral morphine equivalents (OME) across all opioid prescriptions. Tech: Python, SQL. Patient-level tracking, high-risk identification, diversion detection. + +### [proj-inv-sankey-tool] Sankey Chart Analysis Tool (2023, Complete) +Patient journey visualisation through high-cost drug pathways. Tech: Python, Matplotlib, SQL. Trust compliance auditing. + +## Education + +### [edu-0] NHS Mary Seacole Programme (2018) +NHS Leadership Academy. Score: 78%. Covers change management, healthcare leadership, system-level thinking. + +### [edu-1] MPharm (Hons) 2:1 — University of East Anglia (2011–2015) +4-year integrated Master's degree. Research project on drug delivery and cocrystals: 75.1% (Distinction). + +### [edu-2] A-Levels — Highworth Grammar School (2009–2011) +Mathematics A*, Chemistry B, Politics C. + +### [edu-3] GPhC Registration — General Pharmaceutical Council (August 2016–Present) +Professional registration required to practise as a pharmacist in Great Britain. + +## Skills +Technical: [skill-data-analysis] Data Analysis (9yr, 95%), [skill-python] Python (6yr, 90%), [skill-sql] SQL (7yr, 88%), [skill-power-bi] Power BI (5yr, 92%), [skill-javascript-typescript] JavaScript/TypeScript (3yr, 70%), [skill-excel] Excel (9yr, 85%), [skill-algorithm-design] Algorithm Design (3yr, 82%), [skill-data-pipelines] Data Pipelines (2yr, 75%) +Domain: [skill-medicines-optimisation] Medicines Optimisation (9yr, 95%), [skill-population-health] Population Health (3yr, 90%), [skill-nice-ta] NICE TA Implementation (3yr, 92%), [skill-health-economics] Health Economics (3yr, 80%), [skill-clinical-pathways] Clinical Pathways (3yr, 88%), [skill-controlled-drugs] Controlled Drugs (1yr, 85%) +Leadership: [skill-budget-management] Budget Management (1yr, 90%), [skill-stakeholder-engagement] Stakeholder Engagement (3yr, 88%), [skill-pharma-negotiation] Pharmaceutical Negotiation (1yr, 82%), [skill-team-development] Team Development (8yr, 85%), [skill-change-management] Change Management (7yr, 80%), [skill-financial-modelling] Financial Modelling (1yr, 78%), [skill-executive-comms] Executive Communication (1yr, 85%) + +## Response Rules +1. Answer ONLY from the data above. If the answer is not in the data, say "I don't have that information" — never invent facts, roles, dates, achievements, URLs, or contact details. +2. Distinguish NHS employment (May 2022–present, ~4 years, all at Norfolk & Waveney ICB) from private sector (Tesco PLC, Nov 2017–May 2022, community pharmacy). Never conflate the two. GPhC registration is a professional licence, not NHS employment. +3. When asked broad questions about tools, skills, projects, or achievements across Andy's career, aggregate from ALL roles — do not limit your answer to one position. +4. Cite exact numbers, dates, percentages, and outcomes. Never say "approximately" or "around" when exact figures exist in the data. +5. For detailed or list-based questions, give a thorough answer covering all relevant items. For simple questions, be concise (2-4 sentences). + +## Item References +End your response with a single line listing relevant item IDs from the square-bracketed IDs above: +[ITEMS: exp-deputy-head-2024, skill-python] +Only include IDs that directly support your answer. Omit the line if none are relevant.`, + }, + }, +} as const satisfies ProfileContent diff --git a/src/lib/profile-content.ts b/src/lib/profile-content.ts new file mode 100644 index 0000000..be45245 --- /dev/null +++ b/src/lib/profile-content.ts @@ -0,0 +1,27 @@ +import { profileContent } from '@/data/profile-content' +import type { + LLMCopy, + ProfileContent, + QuickActionCopyEntry, + SidebarCopy, +} from '@/types/profile-content' + +export function getProfileContent(): ProfileContent { + return profileContent +} + +export function getProfileSummaryText(): string { + return profileContent.profile.patientSummaryNarrative +} + +export function getSidebarCopy(): SidebarCopy { + return profileContent.profile.sidebar +} + +export function getSearchQuickActions(): ReadonlyArray { + return profileContent.searchChat.quickActions +} + +export function getLLMCopy(): LLMCopy { + return profileContent.searchChat.llm +} diff --git a/src/types/profile-content.ts b/src/types/profile-content.ts new file mode 100644 index 0000000..7988744 --- /dev/null +++ b/src/types/profile-content.ts @@ -0,0 +1,68 @@ +export interface AchievementCopyEntry { + title: string + subtitle: string + keywords: string + kpiId: string +} + +export interface EducationCopyEntry { + title: string + subtitle: string + keywords: string +} + +export interface QuickActionCopyEntry { + title: string + subtitle: string + keywords: string + type: 'download' | 'link' + url?: string +} + +export interface SidebarCopy { + sectionTitle: string + roleTitle: string + gphcLabel: string + educationLabel: string + locationLabel: string + phoneLabel: string + emailLabel: string + registeredLabel: string + navigationTitle: string + tagsTitle: string + alertsTitle: string + searchLabel: string + searchAriaLabel: string + searchShortcut: string + menuLabel: string +} + +export interface LLMCopy { + systemPrompt: string +} + +export interface ProfileContent { + profile: { + patientSummaryNarrative: string + latestResults: { + title: string + rightText: string + helperText: string + evidenceCta: string + } + sidebar: SidebarCopy + } + experienceEducation: { + educationEntries: ReadonlyArray + } + skillsNarrative: { + summary: string + } + resultsNarrative: { + achievements: ReadonlyArray + } + searchChat: { + quickActions: ReadonlyArray + llm: LLMCopy + } +}