pcblueprint — Session Runbook · 52 sessions across 4 repos · click any session card to get its prompt
🤝 Onboarding doc for a new Claude Code chat — open this if you're a fresh session picking up from 2026-04-25.
S00–S04e, S04g, S04h, S05a, S05b, S05c, and S06a are ✅ done (all R0). S04f is ⏸ deferred (post-S12 cleanup). The 2026-04-25 evening pivot reorganised the remaining work into five releases (R0 Foundation → R1 Private Archive Browser → R2 AI Chat → R3 Visual Identity → R4 Mobile + Offline) with a strict "default styling first, dazzle last" discipline — see the 🎯 Product re-focusing tile in the Changelog tab. Total: 52 sessions (was 55; dropped 9 Next.js+MUI scaffolding sessions, added 6 server-rendered HTML sessions). S06b is currently ⏳ waiting on Zepp/Strava credential resets; the rest of R0 (S06c/d/e/f, S16a/b) plus all of R1 (R1-01..R1-09) are pickable. Recommended next pickup: R1-01 (Auth core — first R1 session, gates the whole release).
C:\Users\apcan\Downloads\Blueprint Tasks\ (this runbook HTML)C:\Users\apcan\pcblueprint-api, C:\Users\apcan\pcblueprint-archive, C:\Users\apcan\pcblueprint-website, C:\Users\apcan\pcblueprint-sync.git fetch && git pull before starting a session — the local clones lag behind origin.C:\Users\apcan\.claude\projects\C--Users-apcan-Downloads-Blueprint-Tasks\memory\ — MEMORY.md is the index. Auto-loaded by Claude Code; read on session start for the most up-to-date conventions, gotchas, and cross-session decisions.gh CLI)C:\Program Files\GitHub CLI\gh.exe, authed as apcanario (HTTPS, token stored in keyring, scopes include repo + workflow).apcanario/pcblueprint-api, apcanario/pcblueprint-archive, apcanario/pcblueprint-website, apcanario/pcblueprint-sync.gh pr create → wait for Pedro's approval → gh pr merge <n> --squash --delete-branch.ssh apcanario@192.168.1.69 — keyless, ed25519 key already authorized (~/.ssh/id_ed25519 on this machine)./volume2/pcblueprint-archive (api reads/writes here via the bind mount at /data/archive). Owned node:node (set by the api entrypoint; see Dockerfile). Do not read from /volume1/pcblueprint-archive — orphan, slated for S04f deletion./volume2/docker/api/compose.yaml under the environment: key (no separate .env file on the api side). Contains API_KEY, GIT_AUTHOR_*. Never echo values to chat; reference by name only.http://localhost:3030 (host) → 3001 (container). Externally via the Cloudflare tunnel (see cloudflared container)./usr/local/bin/docker (not on apcanario's default PATH — always use the full path). apcanario is in the docker group and the socket (/var/run/docker.sock) is chgrp'd to docker with g+rw. Caveat: that socket perm reverts on NAS reboot — S06c makes it permanent via DSM Task Scheduler.ssh apcanario@192.168.1.69 "/usr/local/bin/docker exec -u node pcblueprint-api sh -c 'cd /data/archive && <git cmd>'". Git works because the Dockerfile sets safe.directory /data/archive and the entrypoint chowns the mount to node..git/config — S06c can switch to a credential helper)./volume2/docker/api/compose.yaml — api project. Runs pcblueprint-api + Watchtower + cloudflared. Auto-updates on new image push to ghcr.io/apcanario/pcblueprint-api:latest. Joined to the pcblueprint external network for inter-container DNS./volume2/docker/sync/compose.yaml — sync project (created in S06b). Runs pcblueprint-sync; image pulled from ghcr.io/apcanario/pcblueprint-sync:latest; joined to the same pcblueprint external network. Currently waiting on Zepp/Strava credentials before first docker compose up -d./volume2/docker/git-clone2/compose.yaml — git-clone2 project. Confirmed in S06a as a one-shot alpine/git clone; never ran past initial. Slated for deletion in S04f./volume2/docker/compose.yaml — orphan git-clone project. Clones to /volume1. Harmless but slated for deletion in S04f.package-lock.json. If npm install drifts it, git checkout -- package-lock.json. The drift is owned by S04h, not other sessions.git mv for moves. Don't boot the dev server — Pedro does runtime verification. Commit in small chunks.Companion to pcblueprint-checklist_<date>.html. The runbook is the how (per-session prompts, branching, PR flow); this doc is the what + why — the product we're building and how we'll know each piece is done.
A private, web-accessible system for one person (Pedro Canário) to store, browse, expand, and act on the full record of their life — biographical text, medical history, fitness data, journal entries, memoirs, and identity context — across phone and laptop, with archive-first persistence to a versioned git repository.
- WRITE — "log bp 118 over 76, pulse 62, left arm", "new memory tagged 'family' titled X", "upload this PDF as my latest blood test". Agent classifies intent, parses, dedupes against existing records, auto-tags from the canonical vocabulary, surfaces a confirm preview, then commits with links back to the saved file.
- QUERY — "any of dad's memoirs that mention me", "how did training load correlate with sleep last month", "is this blood test result normal compared to my history". Agent reads relevant archive files, cross-references, cites sources inline. Short structured answer for fact queries; prose only when the question is interpretive.
- EXPORT — "give me a PDF report of my HRV trends in April", "download all my 2024 medical files". Agent generates a deliverable (PDF / CSV / Markdown / .zip) following a universal filename convention.
| Repo | Role |
|---|---|
pcblueprint-archive |
Source of truth. Markdown + JSON files in lifecycle buckets (records/, writing/, source-files/, _legacy/, etc.). Every write is a git commit. |
pcblueprint-api |
Express/TypeScript api over the archive. Mounts at /health, /biography, /blueprint, /identity, /timeline, /search, /archive, /chat (planned). As of R1 (2026-04-25): also serves the user-facing HTML pages directly via EJS — no separate frontend until R3. |
pcblueprint-sync |
Docker cron worker. Pulls from Zepp + Strava, posts to api ingest endpoints. |
pcblueprint-meta |
Coordination repo (this PRD's home). Hosts the runbook HTML, helpers, and the GitHub Pages deploy of the runbook. New as of 2026-04-25. |
pcblueprint-website |
Originally: Next.js 16 (App Router) with MUI + Tailwind + Emotion. Status post-2026-04-25 release pivot: dormant until R3 (Visual Identity), at which point a Tailwind-vs-Next.js call gets made with real R1+R2 usage data informing the choice. |
52 sessions across 5 releases (R0–R4) — restructured 2026-04-25 from the prior 55-session flat list. R3 has no sessions yet (planned at R3 kickoff). EPIC 0 is the pre-runbook foundation; the historical EPIC 1–19 sections below remain for context, with dropped epics marked inline.
The chatbot is not conversational. It is a stateless natural-language task endpoint with three verbs (WRITE / QUERY / EXPORT — see North-star §2). Every interaction is one task; the agent's internal tool loop within a single request is unbounded (capped at 10 tool calls), but no state crosses requests.
records/, writing/, raw/, source-files/, sessions/; system buckets _legacy/, meta/, scripts/, claude-code-prompts/ are off-limits): classify intent → parse + extract → propose multi-domain split if applicable → call get_tag_vocabulary → run identity-based dedup (3-way: all-new / partial overlap silently merged / full duplicate escalated to user with side-by-side comparison) → surface confirm preview with editable per-domain fields → commit → return {saved_path, github_url, viewer_url, tags_applied}.web_search. Auto-save fresh inputs used in cross-reference (dedup contract still applies).<verb>-<scope>-<YYYY-MM-DD>.<ext>; simple PDF default, CSV as utility format (storage, not human-reading), .zip for source-file bundles (never .tar.gz).See memory chat_architecture_three_verbs.md for the full operational record.
The prior 55-session flat arc was "everything, everywhere, all at once": Next.js + MUI + Tailwind + Emotion + custom auth + mobile responsiveness all interleaved with no shippable intermediate before ~S20. The 2026-04-25 pivot replaces that with five releases under a strict "default styling first, dazzle last" discipline.
| Release | Goal | Sessions |
|---|---|---|
| R0 — Foundation (largely done) | Archive structure, API CRUD, sessions log, prod sync. | S00–S06f, S16a, S16b |
| R1 — Private Archive Browser | Read-only, server-rendered HTML directly from the API, default browser CSS only, real auth (Argon2id + Resend) from day one. No Next.js, no MUI, no Tailwind. | R1-01 (auth core, was S20a), R1-02 (auth UX, was S20b), R1-03 (auth hardening, was S20c), R1-04 (HTML rendering layer), R1-05 (index pages), R1-06 (detail pages), R1-07 (search/filter), R1-08 (public deploy, replaces S18a/b), R1-09 (observability minimum) |
| R2 — AI Chat over the archive | Stateless WRITE / QUERY / EXPORT command interface. Same default-CSS philosophy — <form> posting to /chat, results rendered server-side, vanilla-JS SSE. No React. |
S10a–d, S11a–c (rewritten — replace React panel with EJS), S12, S13a–b, S14a–c, S15a–b |
| R3 — Visual Identity (no sessions yet) | Branding, typography, color, charts. Tailwind-vs-Next.js call made here with real usage data informing the choice. | TBD — planned at R3 kickoff |
| R4 — Mobile + Offline (blocked on R3 planning) | Responsive 375px viewport, drawer, optional PWA install + offline-read. | S19a, S19b, S19c |
Sessions dropped (Next.js+MUI scaffolding superseded by R1-04..R1-07): EPIC 7 (S07a, S07b), EPIC 8 (S08a, S08b, S08c), EPIC 9 (S09a, S09b). Their per-EPIC sections below stay for historical record but are flagged DROPPED.
Sessions folded: EPIC 17 (S18a, S18b — original Vercel website deploy + DNS) → folded into R1-08 (single deploy of the API+HTML unit on Cloudflare tunnel or Fly.io).
Sessions moved: EPIC 19 (S20a–c — Auth Hardening) → pulled forward to R1 as R1-01..R1-03; archive is private from first public deploy, no APP_PASSWORD-only window.
Phase: Pre-S00 · Status: ✅ Shipped (manual, before formal sessions began) · Sessions: none — done by hand over weeks/months before the runbook existed
The entire foundation the runbook stands on: personal data gathered + curated, four GitHub repos created with initial code that builds, a Synology NAS configured as the production server, an end-to-end deploy chain wired up (cloudflared tunnel → api → archive → GitHub mirror), and Claude Code tooling installed with custom skills + MCP servers. None of S00–S20 would be runnable without this base.
Personal data gathered + curated (the actual content of the system, sourced over years):
intro 2014.md, pedro canario 2014.md, graça gomes 2014.md, francisco canario 2014.md, teresa faria 2014.md, rita canario 2014.md, domingos araujo 2014.md..idml) + ZIP bundle of family-book assets.biography-baseline.original.md, ~40KB) and biographical protocol (protocol.md, ~36KB).pedro_medical.md) plus 14 medical imaging PDFs — cardio ECGs, holters, MRIs, x-rays, ecographies, stress tests.pedro_blueprint.docx).pedro_journal.md) + Word source.Repo scaffolding — 4 GitHub repos created (pcblueprint-archive, pcblueprint-api, pcblueprint-website, pcblueprint-sync) with initial commits, package.json, tsconfig.json, Dockerfile + compose where applicable, GitHub Actions for image build/publish on pcblueprint-api, and initial README.md / CLAUDE.md / PRIVACY.md per repo.
Initial pcblueprint-api implementation (pre-S04 realign): Express + TypeScript, requireAuth Bearer middleware, full health endpoint surface (tracking, sports, medical, blood-pressure CRUD, ingest), biography read endpoints (protocol, chronology, journal, memories, identity, blueprint), schema/types, vitest infrastructure, gitService.commitArchive().
Initial pcblueprint-website: Next.js 16 (App Router) with all major routes already scaffolded — /sports, /sleep, /journal, /chronology, /medical, /memories, /protocol, /identity, /blueprint, /timeline, /search, /dashboard, /archive, /blood-pressure, /login. MUI + Tailwind + Emotion stack. Auth flow (APP_PASSWORD → JWT cookie). lib/api.ts Bearer-token client.
Initial pcblueprint-sync (PR #1 in that repo): custom Zepp HTTP client (email + password, no third-party dep), Strava OAuth v3 client, daily/nightly cron jobs (Zepp 11:00, Strava 03:00), structured logger with optional webhook alerting, Dockerfile + compose.
NAS production chain (Synology DS423+): DSM configured, SSH key-auth set up, Container Manager projects deployed: api stack (api container + cloudflared tunnel + Watchtower), git-clone and git-clone2 projects for archive seeding, ARCHIVE_PATH bind-mounted, GitHub PAT issued for container-side push/pull, Cloudflare tunnel routing public traffic to the api.
Claude Code tooling: custom domain skills (/biography, /medical, /activity, /sleep, /psychology, /schema), local MCP servers (knowledge-rag semantic search, strava-mcp OAuth, sleep-decoder), Stop hook validating schema.json on session end, GitHub Actions Claude Code review workflow (later removed in S04 cleanup once it became failure-noise), the runbook HTML itself with sessions S00–S12 sketched out.
The runbook starts at S00 (manual binary prep) on the assumption that the data, code, infrastructure, and tooling listed above already exist and work. The total invested effort here easily matches or exceeds the formal-session work that follows — every session depends on it. Documented retrospectively so future readers (or fresh Claude Code sessions) understand what they're standing on.
The 2026-04-25 prod reconciliation surfaced that several of the "✅ functional in concept" pieces above had latent gaps — the api had never successfully written to the archive (silent push failures), the NAS archive was 41 commits stale (no scheduled pull was actually running), the docker socket wasn't writable by apcanario. Those gaps are now closed (see Changelog and EPIC 6).
Phase: Prep · Status: ✅ Shipped · Sessions: S00
One-time clean-up of binary blobs and large originals before the main IA migration, so subsequent sessions don't churn on giant files.
Phase: Archive · Status: ✅ Shipped · Sessions: S01, S02a, S02b, S03a, S03b
The archive folder structure is reorganised into nine canonical lifecycle buckets (records/, writing/, source-files/, raw/, _legacy/, meta/, scripts/, sessions/, claude-code-prompts/) with a published spec at meta/ia-spec.md, so every future write knows exactly where it goes.
meta/ia-spec.md v1.2 approved and committed..en.md / .pt.md suffixes dropped — primary file is .md._legacy/2026-04-16/ retains pre-migration copies for reversibility.schema.json keys updated to new bucket paths (v1.3).meta/part2-manifest.json reflects new tree (v1.1.0)./sports duplication is intentional (Coros + Zepp = different schemas).S01 (IA spec + first migration), S02a (memories-wip + _legacy/ READMEs), S02b (source-files/ + binary recovery), S03a (health audit), S03b (schema.json + import scripts + manifest).
Phase: API — Realign · Status: ✅ Shipped · Sessions: S04a, S04b, S04c
Every api route reads/writes via a PATHS constant or path helper instead of hardcoded strings, so future archive moves require a one-line change in fileService.ts rather than a repo-wide grep.
PATHS const exported from src/services/fileService.ts covering every archive file the api touches.pathBloodPressureMonth, pathWorkoutStream, pathMedicalNote, pathBlueprintVersion./health/* routes adopt PATHS (S04b)./biography/, /blueprint, /identity/ routes adopt PATHS (S04c).PATHS constants and several hardcoded strings were not fully aligned with the post-S01 archive at the time S04c shipped — that gap was fixed retroactively on 2026-04-25 (see Changelog block "Prod reconciliation + path realign"). All routes now correctly point at the post-S01 tree.
Phase: Hardening / Backlog · Status: ✅ Mostly shipped (S04f deferred)
A grab-bag of cross-repo housekeeping: shared operating-rules doc, cleanup of orphaned NAS state, lockfile drift resolution, and bot reviews.
CLAUDE.md of all 4 repos.medical/notes audit (manual)./volume1/pcblueprint-archive (deferred to post-S12 cleanup).package-lock.json drift resolution + Node 22 pin via .nvmrc and engines.pnpm-lock.yaml removed; package-lock.json regenerated cleanly; future npm install produces no diff on Node 22./volume1/pcblueprint-archive deletion deferred — left for post-S12 sweep.Phase: API — CRUD Gaps · Status: ✅ Shipped · Sessions: S05a, S05b, S05c
Every biographical resource has a complete CRUD surface, so the website (and the future chat tools) can write any entity without dropping to filesystem tricks.
POST /biography/memories, PATCH/DELETE /biography/memories/:slug — slug-scoped.PATCH/DELETE /blueprint/:version — handles "delete current latest" by picking the previous version + setting identity_stale: true.GET/POST /biography/sessions — append-only AI session log; auto-incrementing session_number.POST/PATCH/DELETE /biography/chronology/events — slug = ${date}-${slugify(title)}; category enum; preserves the <!-- END OF CURRENT RECORD --> marker on POST.Phase: Prod Stability & API Sync · Status: 🟡 Planned (foundation work)
Production deploy is actually stable end-to-end: the api on the NAS bidirectionally syncs with GitHub, the sync worker is deployed and pulling Zepp/Strava data, infrastructure quirks (docker socket reset, PAT rotation) have permanent fixes, and the api exposes a manifest that the website can bind to.
git pull --rebase inside api container; commitArchive retries on non-FF).GET /archive/manifest reading meta/ia-spec.md for the website's docs sidebar).pcblueprint-sync/src/** matches post-S03 paths).pcblueprint-archive, the next NAS api write succeeds without merge-conflict (proven by 10-min cron pull).pcblueprint-sync container running on the NAS, registered with Watchtower; first scheduled cron tick (Zepp 11:00 / Strava 03:00) writes data to api ingest endpoints; archive shows API update: commits in git log.apcanario (Task Scheduler restores socket perms)..git/config.GET /archive/manifest returns { sections: [{ slug, label, description, routes, counts }], generated_at } matching meta/ia-spec.md.pcblueprint-sync write paths in code match the post-S03 archive tree (audited).Release pivot: superseded by R1-04 (API HTML rendering layer) + R1-05 (archive index pages). Original Next.js/MUI scaffolding no longer needed under the server-rendered approach. Section retained below for historical reference.
Phase: Website — Homepage · Status: 🟡 Planned · Sessions: S07a, S07b
Replace the current dashboard-first homepage with a chat-first homepage that has a centered chat panel, a collapsible sidebar with archive section tiles + today-snapshot, and preserves the existing dashboard at /today.
/today so my muscle memory still works./today renders the full pre-existing dashboard verbatim./ renders <HomeShell> with <ChatPanel> (stub) + collapsible left sidebar.app/api/chat/route.ts exists as a stub returning "Chat backend coming soon." (real wiring in S11a).Release pivot: superseded by R1-05 (archive index pages) + R1-06 (record detail pages). The "docs-shell + manifest sidebar + tiled landing" pattern collapses into plain semantic HTML lists rendered server-side; no React, no client-side data fetching. Section retained below for historical reference.
Phase: Website — Archive Docs · Status: 🟡 Planned · Sessions: S08a, S08b, S08c
A polished docs-site experience for browsing the archive: persistent collapsible sidebar, breadcrumbs, manifest-driven section list, tiled landing page, and consistent docs-shell wrapping for every existing sub-page.
app/archive/layout.tsx renders a sticky sidebar + breadcrumbs + content area on every /archive/* route.<ArchiveSidebar> renders from manifest data (S06e), not hardcoded.app/archive/page.tsx shows a tile per section with label, description, and record count./archive/<section> page is wrapped in the docs shell (no rebuilds, just wrapping).pnpm build green.Release pivot: the per-workout hero + HRZones + Splits + Pace/Effort cards depend on MUI X Charts and a styled component layer that are explicitly deferred to R3 (Visual Identity). For R1, activity records render via the same generic detail-page template (R1-06) as everything else — tabular data, no charts. Charts are reintroduced in R3 with whatever stack R3 picks. Section retained below for historical reference.
Phase: Website — Activity Detail · Status: 🟡 Planned · Sessions: S09a, S09b
The /sports/[id] page becomes a useful single-workout view: hero with map + headline stats, HR zone breakdown, splits table, pace zones, and an effort/relative-effort card.
<WorkoutMap> + distance, duration, avg HR, elevation, pace.<HRZones> 5-zone time-in-zone bar chart renders for any real workout (using existing MUI X Charts; no new chart libs).Phase: Chatbot — Backend · Status: 🟡 Planned · Sessions: S10a, S10b, S10c, S10d
A streaming stateless task endpoint on the api with a provider abstraction (so Anthropic/OpenAI/open-weight can swap), basic write tools (BP + journal) that set the response-shape contract, basic read tools (health + journal) plus get_tag_vocabulary, and a single cross-domain orchestrator (analyze_wellbeing).
POST /chat streams assistant text via SSE/chunked. Stateless body: { messages: [<single user turn>], file?: <multipart>, intent?: <hint> } — no session_id, no cross-request state.LLMProvider interface in src/chat/providers/index.ts; stub.ts deterministic provider for tests.CHAT_PROVIDER env var (default stub).log_blood_pressure, create_journal_entry — both end-to-end (chat → tool_call → archive commit). Each returns the standard response shape {saved_path, github_url, viewer_url, tags_applied} and implements identity-based dedup (3-way: all-new / partial-overlap silently merged / full duplicate escalated). Pattern used by every later write tool.query_health_window, query_journal, get_tag_vocabulary — return well-formed JSON; get_tag_vocabulary reads writing/identity/tags for canonical-tag lookups used by every WRITE flow.analyze_wellbeing(window_days) bundles journal + sleep + HRV + HR.Phase: Chatbot — Frontend · Status: 🟡 Planned · Sessions: S11a, S11b, S11c
The <ChatPanel> component becomes a command-bar + result-panel + deliverable-download slot (not a chat thread). Each task is a single round-trip: input → streaming agent response → final result with confirm flows for writes and download links for exports. No persistent conversation history.
/api/chat proxy (server-side bearer-token forwarding).<ToolCallCard> renders inline per tool call within the active task.query_health_window, entry list for query_journal)..zip / PDF download).Phase: Close-out · Status: 🟡 Planned
Final consistency pass across all four repos before declaring v1 shipped: README + CLAUDE.md fresh in every repo, session-log entries appended for every session that deferred them, branch hygiene confirmed.
/archive/manifest, /chat, and the post-S01 IA.pcblueprint-archive/sessions/session-log.{en,pt}.md for every session from S04a through the current point.Originally scoped to also backfill missing CHANGELOG entries — that work was done inline during the 2026-04-24/25 reconciliation, so S12 only needs to verify consistency, not create.
Phase: Chatbot — File Upload · Status: 🟡 Planned
Pedro can upload binary files (medical PDFs, photos, voice memos, IDML/Word originals) into the archive — via website drop-zones on each section page or via a chat tool that accepts file attachments. Files land in the right source-files/, writing/memories/drafts/, or _legacy/ bucket and a git commit lands within seconds.
/medical and have it filed under source-files/medical/ automatically..m4a to a chat message saying "save this as a new memoir draft" and have it land in writing/memories/drafts/.POST /upload/{bucket} accepts multipart with file + optional metadata; 50MB max; allowed types: pdf, png, jpg, jpeg, webp, heic, docx, idml, m4a, mp3, wav.source-files/{medical,sports,writing}, writing/memories/drafts, _legacy/2026-04-25.../, sanitise basename)./medical, /memories, /journal with bucket auto-selected by section./upload page for uncategorised files.attach_file({ filename, base64, bucket, metadata? }) works end-to-end.Phase: Chatbot — Tool Surface · Status: 🟡 Planned · Sessions: S14a, S14b, S14c
The chat can ingest into, query, and export every active user-data bucket in the archive. Cross-domain orchestrators support the questions that motivated this project ("dad's memories where I'm mentioned", "any chronology event near my hospitalization"). Deliverable-generation tools turn QUERY answers into downloadable PDF / CSV / Markdown / .zip artifacts.
Write tools (S14a) — covers all active user-data buckets, not just five examples:
writing/: append_memory({ slug?, name, body_markdown, tags?, author? }) (default author Pedro Canário); update_identity_context; add_identity_pattern.records/: add_blood_test, add_medical_note, add_medical_exam, add_medication, add_medical_flag, post_blueprint_version. (S10b already covers log_blood_pressure; S14a inherits its response-shape contract.)raw/: add_raw_record (generic raw-bucket write).sessions/: covered by existing POST /biography/sessions from S05b.add_tag_to_vocabulary (canonical-tag write).POST /biography/chronology/events from S05c.PATCH /identity/context, POST /identity/patterns, POST /identity/tags, write coverage for medical sub-resources (/health/medical/notes, /exams, /medications, /flags), POST /raw/....Read tools (S14b):
query_chronology({ from?, to?, category?, contains? }).query_memories({ author?, contains?, tags?, since? }).query_blueprint({ version? }).query_identity().query_medical({ contains?, since? }).web_search(query) — required by QUERY when comparing fresh inputs (blood tests, etc.) against medical reference values not embedded in source PDFs. Agent prefers PDF-embedded ranges first, falls back to web_search.Orchestrators (S14b):
cross_reference({ query, domains?, window? }) — single search across any combination of domains; returns grouped hits with snippets.timeline_summary({ from, to }) — chronology + journal + sessions + medical + sports merged + deduped.*Export tools (S14c) — new:*
export_to_pdf({ query, scope, options? }) — simple PDF (header: name + date + scope; body; page numbers; footer). Default minimal template; iterate when needed.export_to_csv({ query, scope }) — flat CSV, descriptive columns, ISO dates. Storage / downstream-tooling format, not for direct human reading.export_to_markdown({ query, scope }) — concatenated Markdown for printable docs.bundle_source_files({ query }) — .zip of selected source files with per-domain subdirs. Universal compatibility — never .tar.gz.generate_report({ template, scope }) — composite: data + simple chart(s) + commentary, rendered to PDF.<verb>-<scope>-<YYYY-MM-DD>.<ext> (e.g. report-hrv-2026-04.pdf, bundle-medical-2024.zip).<archive>/exports/<YYYY-MM>/ with TTL cleanup script (does not pollute user-data buckets).Each tool has a stub-provider canned phrase + vitest round-trip.
Phase: Chatbot — Real Provider · Status: 🟡 Planned
Anthropic's Claude replaces the deterministic stub provider. Default model is Haiku 4.5 (cheap + fast for simple tasks); router escalates to Sonnet 4.6 for hard cross-domain or interpretive queries. The system prompt encodes the stateless 3-verb router protocol (WRITE / QUERY / EXPORT) with full bucket knowledge, tool catalog, and citation conventions. A 3-layer cost ceiling makes runaway bills physically impossible. S15b replaces the original "conversation persistence" scope with a "Transaction Audit Log" — sqlite log of every chat task (verb, intent, tools called, result, tokens, cost) for debugging and accountability, not for chat-history continuity.
S15a — provider + system prompt:
src/chat/providers/anthropic.ts implements LLMProvider.generate streaming both content_block_delta and tool_use events.CHAT_PROVIDER=anthropic requires ANTHROPIC_API_KEY; default still stub for tests. - Per-request: max_tokens=1024 default, max-iterations cap (≤10 tool calls), hard timeout (~60s).
- App-level: monthly token-budget guard tracked in a small JSON/sqlite ledger; refuse new /chat with 429 at 100% of cap, warn at 80%.
- Vendor-level: prepaid credits + workspace spend limit set in the Anthropic console (outside the codebase).
/chat connection closes (no continuation).S15b — Transaction Audit Log (replaces original "Conversation Persistence" scope):
transactions(id, ts, verb, intent, tools_called, args, result_summary, error, tokens_in, tokens_out, cost_usd, model). Append-only, indexed by date + verb.<archive>/.chat/audit.db (gitignored)./chat request writes one row on completion (success or error).GET /chat/audit?from=&to=&verb= for ops visibility (no UI in this session).Phase: Production — Observability · Status: 🟡 Planned
Failures stop being silent. The api alerts on push/pull errors via the same webhook pattern the sync worker already uses. A /healthz endpoint exposes archive state for external monitoring. A nightly tarball lands in /volume2/backups/ for off-NAS recovery.
src/services/alert.ts shared by api + sync; payload shape { severity, source, message, details }.commitArchive() and the S06a archive puller call postAlert on failure.GET /healthz (no auth) returns { status, version, archive_head, last_commit_at }.tar -czf /volume2/backups/archive-YYYY-MM-DD.tar.gz (excluding .git/).pcblueprint-archive/CLAUDE.md.Release pivot: under R1, the archive HTML lives inside the API (server-rendered EJS), so deploying "the website" and "the API" is one operation, not two. S18a (Vercel website deploy) + S18b (DNS / custom domain) collapse into a single R1-08 (Public deploy — Cloudflare tunnel or Fly.io, with custom domain inline). Section retained below for the original framing.
Phase: Production — Public Deploy · Status: 🟡 Planned · Hard prereq: EPIC 19 (Auth Hardening)
The website is reachable from the public internet on a custom domain, served via Vercel, talking to the existing public api (Cloudflare tunnel). Pedro can hit it from cellular, log in, and use everything.
API_URL → cloudflared hostname, fresh COOKIE_SECRET, RESEND_API_KEY, etc.).APP_PASSWORD from .env.local. EPIC 19 must land first.Phase: Production — Mobile UX · Status: 🟡 Planned
Every page works comfortably at 375px iPhone width. Sidebar collapses into a drawer; charts and tables reflow; chat input is keyboard-aware.
/sports/[id], /blood-pressure, /sleep reflow responsively.<ResponsiveList>) below 768px.Release pivot: the original plan deferred auth to the very end of the arc (S20). The 2026-04-25 pivot pulls it forward — the archive is private from first public deploy, so auth gates everything before R1 ships. S20a→R1-01, S20b→R1-02, S20c→R1-03. Scope is unchanged; only the release tag and ID change. Section retained below for the original framing.
Phase: Production — Auth Hardening · Status: 🟡 Planned · Hard blocker: EPIC 17 (Public Deploy)
The single shared APP_PASSWORD is replaced with a real account: argon2id-hashed credentials in sqlite, proper session management, email-based password reset via Resend, an account settings UI, and optional TOTP 2FA. Schema is multi-user-ready even though only one user exists today.
Core (S20a):
users(id, email UNIQUE, password_hash, created_at, last_login_at, totp_secret nullable), sessions(id, user_id, created_at, expires_at, user_agent, ip), password_resets(token UNIQUE, user_id, expires_at).scripts/seed-user.ts bootstraps Pedro's account once./api/login: argon2id verify + httpOnly + secure + sameSite=Lax cookie + 30-day sliding expiration./api/logout: deletes session row, clears cookie./login + auth API routes checks session validity.Reset (S20b):
RESEND_API_KEY env./api/auth/request-reset always returns 200 (no enumeration)./reset-password?token=... page accepts new password; complete-reset endpoint invalidates token + all user sessions.Settings + 2FA (S20c):
/account page: change password, view + revoke active sessions, "sign out everywhere".These are intentionally NOT in the roadmap, even if related:
session_id, no cross-request memory, no chat threads, no cross-device sync of conversation state. An audit log of what the agent did is kept (S15b), but not what was said._legacy/, meta/, scripts/, claude-code-prompts/ are off-limits to chat WRITE. Schema-evolving changes belong in code PRs, not natural-language prompts.After S12 closes out the original 33-session arc, the recommended order for the new epics is:
S20 (Auth) ──┐
├─→ S18 (Public Deploy)
S19 (Mobile)─┘
S13 (Uploads) ──→ S14 (Tool surface) ──→ S15 (Real provider)
S16 (Observability) — can run any time after S06a/b
S20 + S19 are the hard blockers for going public; S13 → S14 → S15 unlocks the chat vision; S16 makes everything maintainable.
Last updated: 2026-04-25 (chat architecture pivot — see runbook 📒 Changelog). Companion runbook: pcblueprint-checklist_25 april.html.
📒 Out-of-scope work done outside the numbered sessions. Why this exists: the numbered sessions assume a working prod deploy + in-sync archive + stable infra. The 2026-04-25 reconciliation found those assumptions were not met, which triggered a cascade of unplanned fixes. Logging here so future sessions can see the full history. Going forward, entries include HH:MM alongside the date.
Increment: The auth UX is now complete end-to-end. The login page is a plain HTML form (view-source has zero JS) and the email value is preserved across a wrong-password retry. There's a "Forgot your password?" link, and the reset flow runs front-to-back: request → email (Resend in production, stdout in dev/test when RESEND_API_KEY is unset) → click → set new password → every session for that user dies the moment the reset commits, including any logged-in tab on a second browser. POST /auth/request-reset always returns 200 with the same body whether the email exists, doesn't exist, or is malformed — no enumeration via status, body, or branching.
Trade-offs accepted:
?flash=key query-string scheme with a small allow-list (reset, signed_out) — no cookie-backed flash bag, no enumeration via unknown keys (anything off the allow-list renders nothing).POST /auth/login kept its JSON contract for API/cron/legacy clients. The new POST /login is the urlencoded form-post entry; the two coexist and share the credential-check + session-create code path./auth/request-reset yet — that's R1-03's responsibility (along with TOTP enrolment and login-attempt throttling).PRs: pcblueprint-api#27 (squash-merged at f306d76) + pcblueprint-api#28 (docs-only CHANGELOG follow-up, awaiting approval).
Downstream-impact triage (from the closing api session, applied here):
R1-03 — TOTP + rate limiting: scope addition needed. R1-02 introduced two new public POST endpoints that are brute-force / abuse targets and need rate limiting alongside the existing POST /auth/login: (1) POST /login (the new urlencoded form-post — same brute-force surface as POST /auth/login, just a different URL), and (2) POST /auth/request-reset (rate-limit by IP and by destination email to prevent inbox flooding). R1-03's prompt currently mentions only POST /auth/login. Recommendation: update R1-03 prompt — extend the rate-limit list to all three. Also add the 2FA challenge step into the new POST /login handler, not just the legacy POST /auth/login.R1-05 — Archive index pages: no change. R1-04's reuse note still stands.R1-06 — Record detail pages: no change.R1-07 — Search + tag filter: no change.R1-08 — Public deploy: scope addition needed. R1-02 added two new env vars: RESEND_API_KEY (required in production for the reset flow to actually send email — without it the link only logs to stdout) and RESET_EMAIL_FROM (optional, default is a placeholder noreply@pcblueprint.local; should be a real verified Resend sender domain in production). R1-08 must wire both into compose.yaml on the NAS alongside the existing BUILD_VERSION and AUTH_DB_PATH notes. Recommendation: add a Resend bullet to R1-08 covering both env vars + the Resend domain-verification step.R1-09 — Observability: no change.Closing checklist split: the api session opened PR #28 with the ### Increment entry in pcblueprint-api/CHANGELOG.md (api-side step). This tile + the COMPLETED_SESSIONS bump + the recommended R1-03 / R1-08 prompt edits are the meta-side step. Third R1 session shipped — auth is done; the rest of R1 is content rendering + deploy.
Increment: Pedro now opens / in a browser and sees an auth-gated, server-rendered landing page listing the five archive buckets (records / writing / raw / source-files / sessions). Sign in via the new /login form (posts to the existing /auth/login over fetch, lands on / on success); the footer shows your email + BUILD_VERSION. The auth middleware was already redirecting browsers to /login; this session makes that destination exist. Stack stays minimal — EJS only, no express-ejs-layouts, no Tailwind, no MUI. One ~95-line stylesheet at /_/runbook.css.
Trade-offs accepted:
/auth/login contract untouched. A JS-free urlencoded form post is a follow-up if a no-JS fallback is wanted later./ currently fall through to the new HTML 404 when signed in — that's the intended end state until R1-05 lands the per-bucket index handlers. Anonymous visits still get the auth-gate redirect to /login.renderPage() two-pass helper (page → layout) instead of pulling in express-ejs-layouts. One less dep; same UX.PRs: pcblueprint-api#25 (squash-merged at 008d221) + pcblueprint-api#26 (docs-only CHANGELOG follow-up, awaiting approval).
Downstream-impact triage (from the closing api session, applied here):
R1-02 — Login Form + Password Reset: scope partially absorbed by R1-04. R1-04 already shipped a working GET /login rendering an EJS form with email + password fields posting to /auth/login. R1-02 should be re-scoped to focus on the password-reset flow (the actual unmet need): POST /auth/forgot (Resend email), GET /auth/reset/:token (renders reset form using renderPage()), POST /auth/reset/:token, plus form polish (server-side error rendering instead of inline JS, "forgot your password?" link on /login). Recommendation: update R1-02 prompt — narrow scope to reset + polish, since the form ships.R1-03 — Account Settings UI + 2FA + Rate Limiting: no scope change. R1-04 gave it the rendering scaffold (renderPage() + _layout.ejs nav slot). R1-03 just plugs settings views into the layout.R1-05 — Archive index pages (one route per top-level bucket): no scope change; one note. The bucket links and the EJS scaffold already exist on /; R1-05 only needs to add the route handlers + per-bucket index templates. Recommendation: add a "scaffold already exists — see src/views/render.ts + _layout.ejs" reuse note to the R1-05 prompt so it doesn't redo the layout work.R1-06 — Record detail pages: no scope change. Same scaffold reuse as R1-05.R1-08 — Public deploy: scope addition needed. R1-04 added a BUILD_VERSION env var (defaults to dev) shown in the rendered footer. R1-08 must wire BUILD_VERSION into compose.yaml on the NAS (probably from the GitHub Actions image tag or a build arg). Recommendation: add a BUILD_VERSION bullet to R1-08 alongside the existing AUTH_DB_PATH volume-mount note.R1-09 — Observability: no change.Closing checklist split: the api session opened PR #26 with the ### Increment entry in pcblueprint-api/CHANGELOG.md (api-side step). This tile + the COMPLETED_SESSIONS bump + the recommended R1-02 / R1-05 / R1-08 prompt edits are the meta-side step. Second R1 session shipped — the chain keeps moving.
Increment: Pedro now has real user accounts on pcblueprint-api. Argon2id password hashing, sqlite-backed sessions, HttpOnly + Secure + SameSite=Lax cookies with sliding 30-day expiry, and a global requireAuth middleware that gates every route except an explicit bypass list (/auth/login, /auth/logout, /login, /healthz, future reset routes). Seed via npm run db:seed.
Trade-offs accepted:
checkLegacyBearer inlined in requireAuth.ts) so the sync worker keeps ingesting without a flag day. Will be removed when sync also moves to cookie auth (post-R2 concern).per-route requireAuth deleted from all 16 protected route files in favour of one global gate — eliminates the "did I forget to wrap this route?" failure mode. Verified by 127/127 vitest green + tsc clean across 8 commits..data/auth.db path is configurable via AUTH_DB_PATH env var, but the NAS docker-compose volume mount is NOT yet wired. Persisting the db across container restarts is a deploy concern that R1-08 (Public deploy) must own — flagged in its triage update below.PRs: pcblueprint-api#23 (squash-merged at 4a55e92) + pcblueprint-api#24 (docs-only CHANGELOG follow-up).
Downstream-impact triage (from the closing api session, applied here):
R1-02 — Login form + reset: scope unchanged, now unblocked on the R1-01 prereq. The /login path is already in the global bypass list, and the password_resets table is already provisioned in the schema. R1-02 just adds the EJS view at GET /login + the email-driven reset routes (POST /auth/forgot, GET /auth/reset/:token, POST /auth/reset/:token). Recommendation: no change. (Still gated on R1-04 for the EJS rendering layer.)R1-03 — TOTP + rate limiting: the rate limiter must specifically wrap POST /auth/login — it's now public-by-bypass and is the obvious brute-force target. The users.totp_secret column is already provisioned. Recommendation: no prompt change needed — current wording already specifies the correct routes.R1-08 — Public deploy: scope addition needed. R1-01 made AUTH_DB_PATH configurable but did NOT touch docker-compose.yml on the NAS at /volume2/docker/api/compose.yaml. R1-08 must add a volume mount so .data/auth.db persists across container restarts. Recommendation: update R1-08 prompt — bullet added in this commit.R1-09 — Observability minimum: /healthz is already in the bypass list, so R1-09 just adds the handler. No change.src/middleware/auth.ts directly: that file no longer exists — its logic moved into src/middleware/requireAuth.ts as checkLegacyBearer. None of the remaining sessions reference it directly, but worth knowing.Closing checklist split: the api session opened PR #24 with the ### Increment entry in pcblueprint-api/CHANGELOG.md (api-side step). This tile + the COMPLETED_SESSIONS bump + the R1-08 prompt update are the meta-side step. First R1 session shipped — the chain is moving.
Caught a real bug just before starting R1-01. The S-META-02 rebrand renamed S20a/b/c → R1-01/02/03 and updated the session header + branch name, but didn't fix the prompt bodies. They still referenced Next.js concepts (/api/login page routes, Vercel Postgres, Next middleware, "every page" framing) that don't match R1's actual stack — under R1, the archive HTML lives in pcblueprint-api served via EJS, and auth has to live there too.
This was the kind of "downstream impact triage" step that should have happened in S-META-02's closing checklist; it slipped through. Caught now, fixed cleanly before the session starts.
What changed:
helpers/_rescope_r1_auth.js. Sentinel = string "R1 RESCOPE 2026-04-25" embedded in each rewritten prompt's RELEASE NOTE.pnpm add argon2 better-sqlite3 cookie-parser; auth DB at .data/auth.db; service in src/services/auth.ts; Express routes POST /auth/login + POST /auth/logout; middleware src/middleware/requireAuth.ts with bypass list and HTML/JSON content-type branching for redirect-vs-401; vitest tests in src/__tests__/. Curl-based manual smoke checklist included. Prereqs note updated to "no prereqs (R1-01 starts the R1 chain)".views/login.ejs, views/reset-request.ejs, views/reset-form.ejs, views/email/reset-email.ejs) instead of React pages. Express routes GET/POST /login, GET/POST /reset-password, POST /auth/request-reset, POST /auth/complete-reset. Resend integration unchanged. No-enumeration on /auth/request-reset preserved. Title updated to "Auth — Login Form + Password Reset (Resend)". Prereqs now R1-01 + R1-04 (R1-04 = the EJS rendering layer this session adds views into).views/account.ejs + intermediate 2FA login view. Express routes for change-password / session revoke / sign-out-everywhere / 2FA enroll-verify-disable / login-2fa second-step. Added rate limiting via express-rate-limit (10/min on login, 3/min on reset) — not in the original S20c scope but landed here since it's the same touch points. Title updated to "Auth — Account Settings UI + Optional 2FA + Rate Limiting".R1-01, R1-02, R1-03 entries' repos field flipped from ["website"] → ["api"]. Titles for R1-02/R1-03 updated. Branch names unchanged.Implication for the wider plan: the role of pcblueprint-website shrinks further. Under R1 it has zero sessions touching it (auth was the last website-resident work item). The repo stays dormant until R3 visual identity, when a "Tailwind on EJS" or "extract a Next.js frontend" call is made with real R1+R2 usage data informing the choice.
PRs: none — meta change. Single commit on pcblueprint-meta: helper + runbook HTML + prompts_line.txt mirror.
Impact on tasks: R1-01..R1-03 are now self-consistent and ready to start. Prereq rewrites also landed inline: R1-02 prereqs ["R1-01"] → ["R1-01", "R1-04"], R1-03 prereqs ["R1-01", "R1-02"] → ["R1-01", "R1-02", "R1-04"] — both depend on R1-04's EJS rendering layer for their views. The Next-ready widget will now correctly hold R1-02 / R1-03 back until R1-04 ships. No other sessions are affected — R1-04..R1-09 already pointed at pcblueprint-api from the start (they were defined fresh under R1, not rebranded from older S* sessions).
End of the four-session meta arc that promoted the runbook to its own repo, restructured the work into R0–R4 releases, and added a release-grouped UI on top. From this point forward, "next pickup" is unambiguous (Next-ready widget surfaces it; default is R1-01).
What shipped across S-META-01..04:
pcblueprint-meta repo created at github.com/apcanario/pcblueprint-meta; runbook deployed at apcanario.github.io/pcblueprint-meta via GitHub Pages workflow. Replaces the prior zip-and-transfer sync flow._restructure_releases.js: dropped 9 Next.js+MUI scaffolding sessions, renamed S20a–c→R1-01..03 (auth pulled forward), added R1-04..R1-09 with full prompts, retagged everything else, rewrote affected prereqs. PRD updated. Subtitle bumped 55→52.NEXT_RECOMMENDED.id = "S07a" cleared.helpers/prompts_line.txt mirror removed (canonical lives at repo root). This closing tile.Recommended next pickup: R1-01 — Auth core (Argon2id + sqlite sessions + JWT cookies). It's the start of R1, gates the whole release, and is the session the Next-ready widget surfaces by default. ~60 min, single repo (pcblueprint-website in the prompt — though the actual implementation may move to pcblueprint-api under the R1 server-rendered approach; flag at session-time if a re-scope is needed).
What's NOT done (deliberately deferred):
checkout@v4, upload-pages-artifact@v3, deploy-pages@v4). Node-24-compatible bumps to be revisited around May 2026 before the June 2026 forced cutover.PRs: none — three commits on pcblueprint-meta main: 21f0aee (initial), f6520e0 (S-META-02 restructure), 94f8cfd (S-META-03 UI), plus this S-META-04 commit. All deployed via the auto-Pages workflow.
Impact on tasks: none directly. Every numbered session retains its prompt content; only IDs / release tags / prereqs were rewritten. The R1-01..R1-09 prompts are fresh and ready to be picked up.
Executed S-META-02 — the structural rewrite of the runbook that implements the release plan landed earlier today (see the "🎯 Product re-focusing" tile below). One PR-style commit; runbook still loads cleanly; _extract.js works on every new ID.
What landed:
helpers/_restructure_releases.js. Re-running is a no-op (sentinel = presence of R1-01 in PROMPTS).SESSIONS array now carries a release: "R0" | "R1" | "R2" | "R4" field. R0=25 sessions (foundation, mostly done), R1=9, R2=15, R4=3. R3 sessions will be defined at R3 kickoff.SESSIONS + PROMPTS: S07a, S07b, S08a, S08b, S08c, S09a, S09b (Next.js+MUI scaffolding superseded by R1-04..R1-07), and S18a, S18b (folded into R1-08).waitingFor: "R3 visual identity sessions to be planned" so the Next-ready widget never surfaces them prematurely.history/PROJECT-PRD.md): added a "Release plan (2026-04-25 pivot)" section with the R0–R4 mapping table; marked EPIC 7/8/9 as ❌ DROPPED, EPIC 17 as 🔁 FOLDED → R1-08, EPIC 19 as 🔁 MOVED → R1-01..R1-03, all with one-line rationales. Re-rendered into the embedded 📋 PRD pane via _embed_prd.js.What's still on S-META queue: S-META-03 (release tabs in the 📌 Tasks pane + "Next ready" widget + recruiter-view rework to show release-level outcomes instead of the 52-row session grid) and S-META-04 (Pages action version bump + final polish).
PRs: none (runbook + helpers + PRD only — single commit on pcblueprint-meta main branch). The closing-checklist memo refers approximately to ~line 1986 in older prompts and ~line 2135 in newer ones; both are approximate (the line shifts with every completion). Future Claude sessions should grep for const COMPLETED_SESSIONS rather than chase the line number.
Impact on tasks: the largest structural rewrite the runbook has had. Every not-yet-done session was touched in some way (release tag, prereq update, or rename). All shipped sessions (S00–S06a) untouched. COMPLETED_SESSIONS array unchanged.
Why: Pedro flagged that the current 37-session arc is "everything, everywhere, all at once" — Next.js, MUI, Tailwind, Emotion, custom auth, mobile responsiveness, chat backend and frontend all interleaved with no shippable intermediate before ~S20. That's not an agile shape. It also risks a messy foundation: frontend choices made before the archive's display surface has been pressure-tested with real use; visual polish blocking functional access. The fix is to parcel work into deliverable releases with a strict "default styling first, dazzle last" discipline.
What changed:
<form> posting to /chat, results rendered server-side, vanilla-JS SSE for streaming. No React.Tasklist site → its own repo: the Blueprint Tasks/ folder gets promoted to a new GitHub repo pcblueprint-meta, replacing the manual zip-sync flow. Holds the runbook HTML, helpers, PROJECT-PRD source. Deployed via GitHub Pages so the recruiter view becomes a shareable URL instead of a file. Becomes the fourth pcblueprint repo (api, archive, sync, meta).
Runbook chaining work: sessions get a new release: 'R0'..'R4' field; UI groups by release with done/total counts per tab; new "Next ready" widget computes the highest-priority session whose prereqs are all merged and surfaces it as a one-click action. One-PR-per-session preserved — small reviewable commits remain non-negotiable per S01 rules; what disappears is the "what's next?" hunt, not the merge gate.
Execution sequence (meta-sessions, before R1-01 starts):
pcblueprint-meta repo (git init + README + Pages workflow + initial commit + push)._restructure_releases.js; run it to renumber sessions, add release field, drop S07a–S09b, add R1-04..R1-09 prompts, migrate COMPLETED_SESSIONS to new IDs.Plan record: full plan saved to ~/.claude/plans/ok-let-s-ask-some-fluttering-donut.md (approved 2026-04-25). PRD will be reorganized under R0–R4 headings as part of S-META-02; _embed_prd.js re-renders the embedded section automatically.
Impact on tasks: all not-done sessions are affected. The renumbering is the largest structural rewrite the runbook has had. The recruiter-readable framing improves substantially: a release-level outcome list is a stronger portfolio signal than a flat 55-row checklist.
Long working session. Three substantive workstreams progressed; one paused on external dependencies; the runbook itself was substantially redesigned. Logged here as a single index entry pointing at the per-workstream tiles below.
pcblueprint docker network, api stack rejoin, sync compose + env template). Final step (fill .env + docker compose up -d) paused on Zepp password reset + Strava email change. See "🚧 S06b in flight" tile below.Process notes (worth preserving):
DEFAULT_DONE hardcoded while clearing only localStorage) is a good example of where rapid execution outran the design — Pedro's catch saved a half-broken feature from shipping. The post-mortem fix simplified the model AND the standing rule. Net win.Open at end of day: S06b waiting on credentials. 34 other not-done sessions are picked-from-able. Recommended next pickup: S07a (~30m, unblocks the website + chatbot frontend chain).
docker compose up -d can run.pcblueprint-sync#5: GHA publish workflow mirroring pcblueprint-api's docker.yml exactly. Image now builds + pushes to ghcr.io/apcanario/pcblueprint-sync:latest on every merge to main, multi-arch.pcblueprint-sync#6: Missing package-lock.json — first build failed because the Dockerfile uses npm ci which requires one. Added.pcblueprint-sync#7: Removed dead getActivities() Zepp function that imported a never-defined ZeppActivity type — long-standing tsc failure that surfaced now that CI actually runs the build.pcblueprint-archive#11: Cross-repo lockfile audit during S06b found the same gap in archive's import scripts (loose reproducibility for the migration/import scripts). Fixed.pcblueprint; recreated pcblueprint-api stack joined to it (~5s Cloudflare 502 window during recreate); appended pcblueprint-sync to Watchtower's command: list; scaffolded /volume2/docker/sync/compose.yaml + .env template (mode 0600). API_TOKEN auto-pulled from /volume2/docker/api/compose.yaml via inline grep — never piped through chat./volume2/docker/sync/.env — ZEPP_EMAIL, ZEPP_PASSWORD, STRAVA_CLIENT_ID, STRAVA_CLIENT_SECRET, STRAVA_REFRESH_TOKEN (plus optional ALERT_WEBHOOK_URL). Pedro waiting on Zepp password reset email + Strava email change. Once received, fill the values and run cd /volume2/docker/sync && /usr/local/bin/docker compose -p pcblueprint-sync up -d.runbook_waiting_status.md.localStorage but left DEFAULT_DONE (the hardcoded baseline of completed sessions) intact. Result: clicking "Reset" still showed S00–S06a as done, defeating the purpose. Pedro caught this immediately.DEFAULT_DONE → COMPLETED_SESSIONS for semantic clarity ("what the project has shipped" vs "default state").localStorage["pcblueprint-runbook-recruiter-mode-v1"]. When set, loadState() returns {} — ignoring BOTH the project's completion record AND any in-flight UI toggles. Both are preserved (nothing destroyed) and re-apply when the flag is cleared.BACKUP_KEY + backup/restore-of-localStorage dance — unnecessary now that recruiter view is non-destructive. Removed the bootstrapInitialState() function — also unnecessary; COMPLETED_SESSIONS covers the same ground without re-seeding localStorage.DEFAULT_DONE AND the bootstrapInitialState seed. Now: just append the session id to COMPLETED_SESSIONS. Single location, no drift risk.helpers/_update_closing_checklist_to_v2.js. _append_closing_checklist.js + _patch_chat_architecture.js updated so any future prompt additions emit the v2 text.closing_checklist_rule.md updated to reflect the simpler protocol.<details> blocks no longer cut it. Needed a navigable, accessible, brand-consistent doc shell.<details> blocks. Header + tabs stay fixed; the active pane scrolls inside itself. URL-hash sync (#prd, #approach, etc.), arrow-key navigation, ARIA tablist roles.[data-anchor] elements, builds a sticky list, highlights the current section via IntersectionObserver, smooth-scrolls inside the pane on click.#0b0c14 → #dedede) replaces the prior near-neutral grays. Brand accents: salmon #cf2754 (notices, blockers, danger) and cyan-teal #0eb3c2 (active tab, ready badges, focus rings, sidebar highlights). Status pastels: mint, yellow, blue-gray. 17 unique hex values total, all on-theme.📘 Blueprint — Project Documentation as the title; pcblueprint — Session Runbook · 55 sessions across 4 repos demoted to subhead._embed_prd.js had a stale var(--surface, ...) reference (a variable that has never been defined in this stylesheet) — every PRD <pre> block was silently rendering on the hardcoded fallback. Now uses var(--bg-elevated). Other dead fallbacks (#2a2a2e, #6b6bff, #aaa) cleaned out for future palette changes.HH:MM alongside the date. Backfilling old entries with fake times was rejected as dishonest._embed_prd.js only. Lives in Blueprint Tasks/, which is the source of truth (Pedro syncs by zip-and-transfer between machines).data-anchor attribute..zip for source-files, never .tar.gz), and the 3-layer cost ceiling.session_id from request body; chat is a stateless task endpoint; added get_tag_vocabulary read tool; explicit response-shape contract {saved_path, github_url, viewer_url, tags_applied} for every write tool.web_search read tool. Likely api gaps to fill enumerated (identity context PATCH, patterns POST, tag vocabulary POST, raw record POST)._legacy/, meta/, scripts/, claude-code-prompts/)".S14c added to SESSIONS array + PROMPTS object. S15a's prereqs extended to include S14c. Subtitle + progress text bumped to 55 sessions. All applied via idempotent helper helpers/_patch_chat_architecture.js.chat_architecture_three_verbs.md.pcblueprint-archive from his laptop and the NAS clone catches up within ten minutes via a container-side cron — no more silently-rejected commitArchive() pushes after a manual edit. Real merge conflicts ping ALERT_WEBHOOK_URL instead of failing silently. PR pcblueprint-api#22.commitArchive() revealed the NAS archive was frozen 41 commits behind GitHub at pre-S01 state (commit 0c12945), and the api's PATHS constants still pointed at pre-S01 paths that no longer exist. Container had never successfully written to the archive.safe.directory + ownership entrypoint into the api Dockerfile, realigned every PATHS constant + hardcoded archive path across src/** for the post-S01 bucket tree (writing/, records/, etc.), updated tests. Verified end-to-end with a live POST that committed + pushed to GitHub.apcanario/pcblueprint-api#21 (realign + Dockerfile fix).S06a–S06d were inserted into the runbook to close remaining gaps (bidirectional sync, sync worker deploy, infra hardening, memoir endpoints). All downstream tasks now assume a working prod archive.pcblueprint-api#20, pcblueprint-archive#10, pcblueprint-sync#3.S12 — Cross-Repo Docs Sweep no longer has to backfill — scope reduces to verifying consistency across repos.docker compose up -d --build. Api has long since moved to image-based deploy via ghcr.io + Watchtower; sync should match./volume2/docker/sync/, fixed the stale pcblueprint.env reference.pcblueprint-sync#4.S06b.reorganize-archive-structure in archive) that had been abandoned on the remote.pcblueprint-sync locally for the first time.📐 A short, recruiter-readable framing of what this is, how to read it, and what it demonstrates. Five-minute version of the entire document.
pcblueprint is a private, web-accessible system for storing, browsing, expanding, and acting on a single person's full life record — biographical text, medical history, fitness data, journal entries, memoirs, identity context. The interface is a Next.js web app; the storage layer is markdown + JSON files in a versioned git repository; the agentic layer is a stateless natural-language interface that classifies user intent into one of three verbs (WRITE · QUERY · EXPORT) and dispatches to typed tools.
The "user" is one person — me. The system runs on a Synology NAS in my home, exposed publicly via a Cloudflare tunnel, with a continuous deploy chain (GitHub Actions → ghcr.io → Watchtower) that lets me ship code from my laptop and see it land in production in under five minutes.
This document is the project's outer shell. The runbook (📌 Tasks) lists every implementation session; the 📋 PRD captures the product reasoning; the 📒 Changelog records the iteration loop; the 🤝 Handoff is the operational onboarding for a fresh AI session. This 📐 Approach tab is the meta layer for an outside reader.
If you have 5 minutes:
If you have 15 minutes, add:
If you have 30+ minutes:
Skills the project surfaces by virtue of the work itself, not by claim:
records/, writing/, raw/, source-files/, _legacy/, etc.) was the foundation for everything downstream — paths, route helpers, type safety, deduplication contracts, the chat's WRITE-verb scope. Getting it right early saved a multi-session refactor later.Pedro Canário · Senior Director of UX Design by trade. This project is me treating AI orchestration as a UX problem: the prompts are the design system, the runbook is the product roadmap, and the agent is a teammate that needs onboarding, conventions, and feedback loops. What you see is what happens when a designer leans into the parts of engineering that are about clarity, sequencing, and protocol — and uses an AI senior engineer for the parts that aren't.
If you want to talk about this — building AI-orchestrated systems, designing for agentic interfaces, or hiring someone who can think across product · design · engineering — apcanario@gmail.com.