Owner's call. M1 is the turn path, M2 is memory he cannot correct, M3 is step-up. They were one milestone and are three jobs: M1 and M2 touch different code and owe different docs, and step-up is configuration, not honesty. Nine milestones now. Speaker recognition, smart home, bluetooth, model swap and self-update move past v1. Bluetooth was on the v1 list and comes off it: no bluez on the box. Their spec entries keep their DoD. --no-verify: committing on master by the owner's call this session. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 KiB
Roadmap: the order the spec gets built in
Last verified: 2026-08-15 @ 231248a
docs/spec.md says what every capability is for and what done means.
This file says which order they land in, and why that order and not another.
CLAUDE.md carries the rules.
The ordering rule
The audit ruled out a roadmap ordered by code work
(docs/evals/2026-08-13-capability-audit.md). None of the four broken
capabilities is a code defect. Weather has no configuration block. Nexus has no
data. The voice reach has no listener. Step-up has no WebAuthn credential.
So the order is by what would make her untrustworthy if it shipped later. A capability she does badly costs more than one she does not have. From the outside he cannot tell the difference. Honesty comes before reach, and reach comes before breadth.
Two rules bind every milestone.
A milestone closes its own documentation gaps. The spec found seventeen capabilities with no living doc. Those are not a milestone of their own. A capability does not ship out of a milestone until the doc its spec entry points at exists.
A milestone writes its own scenarios. Only five scenario files exist and 46 spec entries name one to write. The scenarios a milestone's DoD items cite are part of that milestone.
Honesty, in three milestones
She currently claims things that are not true. That is worse than a gap, because a gap is visible and a false claim is not. Nothing else is worth building on top of a turn that lies.
That is one theme and three separate jobs. M1 is the turn path. M2 is the memory he cannot correct. M3 is a configuration job that is not honesty at all. They are split because each is one session, and because M1 and M2 touch different code with different docs owed.
None of the three touches voice. A dishonest turn spoken aloud is still dishonest.
M1: The turn does not lie
Every item is on the path from utterance to reply, and each is a false statement rather than a missing one.
Lands: Route an utterance. Speak as herself. Answer from the world.
Gate:
- A question about what Maven remembers routes to query. Both audit probes pass.
- No masculine self-reference reaches the wire, checked on the outbound path and not only in the eval.
- A world answer that would invent content is refused instead of phrased. The audit's "почему небо голубое?" answer is the failing case.
Docs this milestone owes: none new. docs/routing.md, docs/language.md and
docs/world.md all exist and are corrected in place.
M2: Memory he can correct
The store is the other place she claims something untrue, and the only place he cannot fix it himself. It is separate from M1 because it is store and surface work, and because it owes the largest doc in the spec.
Lands: Facts. Notes.
Gate:
- No confirmation claims a write that did not happen. The audit's "я записала информацию о тебе" wrote nothing.
- A note can be deleted by voice and from the web UI (V-494).
- A question is not stored as a statement.
- A superseding fact retires the old value and both are readable.
Docs this milestone owes: the memory doc covering facts, notes, the supersede rule and the digestion worker's consolidation pass. It is the largest gap in the spec, and it is why this is its own milestone.
M3: Step-up is not fail-open
One bounded configuration-and-code job. It is not honesty and it does not belong inside M1. It is the audit's only high-severity item and it gates the act path, so it lands before anything reaches Hexis.
Lands: Passkey and step-up.
Gate:
- WebAuthn is configured and no step-up gate is fail-open, including
POST /api/chat(V-683). - Enrollment requires an existing credential once the first one exists. Anyone past the proxy can enroll today.
- Step-up is per-request, not process-global.
M4: The four broken, none of them code
Cheap, and it unblocks two later milestones. Nexus with entities is what makes the act path real. Weather is the capability he asked about first on the audit day.
Lands: Weather. Nexus. Hexis. The deployed stack.
Gate:
- A
weatherblock names a provider and a home city. The follow-up city parks as a clarify instead of dying with "Я тебя не разобрала". - Nexus has entities, so free text resolves to a canonical entity id.
- One act runs through Hexis against a real target, with confirmation binding capability id, target, arguments, requester and expiry.
- All five compose services run the current build. Three were four days stale during the audit.
Not here: smart home and bluetooth. Both are blocked on the host, not on Nexus.
M5: Voice is the spine
v1 is a voice assistant. Until a proactive message can reach him by speech, she is a web app he can talk at. He reaches her by speaking, which is a pull. She has no push.
Lands: Voice reach. Wake word to session. Hearing. Text to speech. Speech to text.
Gate:
- A proactive message reaches him by speech without him speaking first. Every proactive message during the audit fell through with "no live voice session".
- Waking her opens a session the proactive path can push into (V-515).
- A capture client runs on workpc and streams end to end from microphone to reply (V-514).
internal/ttsnormexpands times and dates intoEurope/Samaraphrasing.- The
mavsttdfloor arm is exercised on its own, not only behind the workstation.
The voice port stays on homesrv loopback and reaches workpc over ssh. This milestone does not LAN-bind it.
Docs this milestone owes: what holds a live voice session open. docs/protocol.md
documents the wire and nothing documents the listener.
M6: Proactive that arrives
Everything in this milestone exists and fails at the last step. The morning routine builds a plan and drops it. Reminders fire and one reach failure loops. Recurring is storage and delivery with no caller.
Lands: Reminders, including recurring. Morning routine. Interruption policy. Digest of held nudges. Tasks. RSS and news.
Gate:
- A recurring reminder is set by voice and states its schedule back: meetings,
pills, the dog, the vet, the kibble.
store.RemindercarriesCronand no caller incmd/mavendpasses one. - The morning plan reaches him inside its 08:00-11:00 window
Europe/Samara, and falls back to the non-voice reaches when no voice session exists (V-280). - The four presence-and-severity outcomes are written down before any of them changes (V-281).
- A failed delivery retries into another reach rather than once a minute until 03:05.
- One suppressed nudge is watched surfacing in a later digest, on the box (V-687).
Docs this milestone owes: the reminder lifecycle. Parking, firing, delivery, retry and cancellation span three packages with no written contract.
M7: Breadth she can already almost do
These have code and no path from an utterance. Each is one wiring job, not a design job. They come after the spine because none of them changes whether she is trustworthy or reachable.
Lands: Read an encyclopedia. Recall. See an image. Network scans. MCPs. Routine proposals. Memory evaluation.
Gate:
- A Russian question lands on the Russian book, an English one on the English book.
TestONNXPersonalBoundaryis green and a recall miss says she does not remember.- An image sent through Telegram gets a Russian description, and the vision call falls back silently when the workstation is down (V-667).
- A scan of the configured subnets is read back as prose.
- A configured MCP server's tools are callable through the act path, and only through the allowlist.
- The routine proposer's hand-written Russian verb list is replaced by
internal/lexiconor the embedder (V-606). - One memory evaluation run is observed and its notes read back (V-248).
M8: The product decision, then the deploy
Email and calendar are built and neither is in docker-compose.yml.
internal/email with mavmaild, internal/calendar with mavcaldav. Deploying
either before deciding what she does with his mail writes the decision by
accident. That is why they sit behind a milestone boundary rather than inside M7.
Lands: Email triage. Calendar management.
Gate:
- The owner has decided what triage means: read-only summary, task extraction, or reply drafting.
- Mail-derived candidates stay candidates until he accepts one (V-130).
- An event is created by voice with the slot asked for rather than guessed, times
in
Europe/Samara. - Both daemons are in compose, or their absence is deliberate and recorded.
M9: Design pass, then the undesigned seven
Seven v1 capabilities have no design. They keep a DoD in the spec so the gap stays visible, and each needs a design pass before any code. Every one of them assumes a turn that is honest, reachable and proactive. Each gets cheaper once M1 through M6 have landed, which is why they come last.
Lands: Web crawling. Summaries. Webhooks. Cron jobs. Desk notifications, outbound half. Learning the style. Learning from mistakes. Command chaining.
Two decisions this milestone opens with:
- Cron jobs against routines against recurring reminders. Three schedulers
must not exist.
internal/routinealready carries aCron, and M6 gives reminders one. What "cron jobs" adds beyond those two is undecided. - Which direction webhooks means. The only webhook in the tree is Telegram's own inbound intake. Inbound as an event source and outbound as a fourth reach are different capabilities.
Learning means behavioral, not weights. Stored outcomes: dismissed nudges, corrected phrasings, repaired routes. No adapter, no training set. Everything learned is readable on a page and deletable.
Deferred past v1
Owner's call, 2026-08-15. Four are audit rows the v1 list did not name. Bluetooth control was on that list and comes off it. No bluez exists on the box and the radio has no owner. Their spec entries stay, so the DoD is already written when one comes back.
| capability | why deferred |
|---|---|
| Speaker recognition | Nothing depends on it until someone other than him speaks to her (V-255). |
| Smart home | Blocked on the host, not on code (V-256). |
| Bluetooth control | No bluez on the box (V-257). |
| Model swap | The resident model being whatever the config says is an acceptable answer (V-250). |
| Self-update | mavupdate cannot reach the containerized socket, and a manual deploy works (V-477). |
What is not filed
Vikunja returned 503 across two sessions, so the following have no task id. Filing them is the first thing to do when it comes back.
- The capability audit itself. It is headed "unfiled".
- The remember-versus-query misroute. Two of seven audit probes.
- The masculine reply on the wire, caught live while the eval passed.
- Recurring reminders having no caller.
- The seventeen capabilities with no living doc.
- The 46 scenario files the spec names and does not have.