Supersedes 09-MVP-PLAN.md (kept as the record of the shipped v1 build). Vision: 00-VISION.md · Spec: 01-PRD.md. Phases ship as release trains (v2.0, v2.1, …); milestones within a phase are independently landable PRs. The changelog is the authoritative record of what shipped when; this document is the plan-shaped view of the same history, plus what comes next. The live position of the current train is BOARD.md.
A phase is a planned train of milestones, numbered continuously since the
v2 program began: Phase 1 shipped as v2.0, Phases 2–4 were planned as v2.1
through v3.0, and a milestone number like 2.3 means phase 2, milestone 3.
Delivery ran ahead of that ordering — voice, memory, and the companion landed
before Interviewer Assist, Tutor, and the second provider — so Phases 1–4 no
longer have sections of their own: their milestones live in the table below
with their fate, and the changelog holds the shipped record. The first phase
that is still a plan is Phase 5,
the v2.2 train. v2.1 also added a layer the original plan never named:
activities (the user says what a call is, the engine derives the mode —
one list, not two) and continuity (a Space is where a conversation is
kept; kept conversations ground the next one) — those rows carry a dash
instead of a milestone number.
✅ shipped · 🧪 shipped behind a Labs badge · ⬜ open.
| Milestone | Status |
|---|---|
| 1.1–1.4 One engine (schema, engine extraction, provider seam, rebrand) | ✅ v2.0 |
| 2.1 Meeting Copilot | 🧪 Labs (meeting.acceptance.test.ts gate) — graduation criteria scheduled: 5.5 |
| 2.2 Interviewer Assist | ⬜ later train |
| 2.3 Multi-provider v1 | ⬜ scheduled v2.2 (5.1) — seam ✅ since v2.0; Settings → Providers still says “Coming soon” |
| 3.1 Voice output | ✅ sentence-streamed TTS + barge-in; Realtime speech-to-speech ⬜ later train |
| 3.2 Tutor | ⬜ later train — subject ships meanwhile as a quiet ambient activity (meeting mode over your material) |
| 3.3 Summon anywhere | ✅ push-to-talk (Ctrl+Shift+T) + no-session quick ask |
| 4.1 Memory subsystem | ✅ review-first; v2.1 added lexical recall, fact supersession (Replace), and authoring |
| 4.2 Interjection policy engine | ✅ (companion.eval.test.ts gate) |
| 4.3 Companion | 🧪 Labs — game-buddy vision integration still ⬜ |
| 4.4 Cost governance v2 | ✅ session budgets + live meter; local-STT spike ⬜ (scheduled as a 5.x spike) |
| — Activities: one list, engine derives the mode (v2.1) | ✅ 18-ACTIVITIES.md |
| — Continuity: archives, save prompt, per-activity formats (v2.1) | ✅ 16-CONTINUITY.md |
| — One active profile, resolved in main (v2.1) | ✅ 19-ACTIVE-PROFILE.md |
| — Job-search quarantine made inert, tailoring re-homed to the Space (v2.1) | ✅ 20-QUARANTINE.md |
Phases 1–2 as originally drawn are complete in substance: the engine is one, the identity shift is public (README, media, and sample data lead with meetings, not interviews), and the copilots exist — with the single exception of the second provider, which is the oldest open promise in this document and therefore goes first in the next train.
Carried from v1: docs drive development; one session-log file per day; branch → PR, never commit to master; no version bump or changelog entry except when cutting a release; typecheck + build before committing.
Rules of the v2 era, all still in force:
npm run build clean, and the privacy hard test
(scripts/privacy-affinity/hardtest.js) passing. Interview mode is shipped
product; it never regresses in the name of generality.npm run db:generate) tested against a copy of a real
earlier database.The fifth phase of the v2 program, shipping as release v2.2.0 — the first phase that is entirely ahead of us (Phases 1–4 are accounted for in the status table above). Its live position is tracked on the board.
v2.1 made continuity and memory the core of the product. The next release hardens the promises that core rests on. The pitch is local-first, your data, grounded answers — and today that pitch has four soft spots: everything depends on one cloud vendor; memory can only be seeded one fact at a time; a local-first store has no backup or portability story; and the two flagship modes still wear Labs badges with no written way to take them off. Each milestone below closes one of those gaps. Breadth (new modes, new surfaces) deliberately waits — see Later trains.
chat and vision. Per-capability
provider/model selection in Settings → Providers; per-provider keys under
the same isolation rules as the OpenAI key (main-process only, encrypted at
rest, never sent to the renderer). Realtime STT and speech stay OpenAI-only
until a peer capability exists; PRD §6.7 degradation rules apply. Embedding-
provider switching ships only with the re-index flow — the
embeddingIdentity guard already refuses mixed vector spaces, so the flow
is a UX task, not a safety one.
Acceptance: a full meeting + interview session runs end-to-end with chat on
the second provider; capability gaps surface as clear UI states, never bare
errors; no key ever reaches the renderer.sourceKind: 'imported' is already reserved for exactly this
(14-MEMORY.md §6). The sensitive filter applies before
persistence, scope is chosen at import (Space or everywhere), and nothing
is recalled un-reviewed. Closes the “day one it knows nothing” gap from the
document side, as authoring closed it from the typing side.
Acceptance: pointing at a CV or a brief yields reviewable candidates;
rejecting the batch stores nothing; approving follows the existing
supersession rules (an imported fact can Replace a stale one).Train acceptance: parity gate passes; chat runs on the second provider end to end; a memory can arrive from a document, be exported, and be restored; the store is encrypted at rest; Meeting and Companion each have a written verdict.
In rough order of expected value to the daily cases (meetings, solo), which is the ordering rule 00-VISION.md sets:
kind='subject' Spaces exist and run today as a
quiet ambient activity; the upgrade is a real teach/quiz/drill dialogue loop
on the engine’s dialogue policy, migrating mock/sparring onto the same
loop and retiring their bespoke paths. Progress lands in Insights.realtime.ts.interviewer.ts and feedback.ts, adds the coverage tracker. Same
overlay, opposite chair. Worth revisiting the priority honestly: interviews
are one activity now, and this serves the least-daily one.Runs alongside every phase: tagline decision (still open, see
00-VISION.md §6), README/media refresh at each release
boundary (npm run media now rebuilds the whole set from the real app —
21-MEDIA.md), docs/*.md kept current with the code,
changelog entry per release train.
docs/*.md.