# maven — feature ranking

> **Archived 2026-08-02 (V-447).** The mandatory and easy tiers are now Vikunja tasks
> 449-458. Two of those closed immediately, because the ranking was stale. Quiet hours
> (V-450) ship as `QuietHoursConfig` plus the care gate in `internal/loop/loop.go`.
> Schema migrations (V-451) ship as `internal/store/migrations.go` on `PRAGMA
> user_version`. The doable and epic tiers stay here because they are reasoning. Some of
> them exist only to record why something is not worth doing yet. Read this for the why,
> not as a work queue, and check the code before believing a gap.

> dated 2026-07-03. companion to `docs/design.md` (folded from the former `maven.md`). ranks everything discussed post-repo-state against the infra blockers, not a replacement for the build order.

---

## what already shipped (checked against the code, 2026-08-02)

One month old and already wrong in ten places. Everything below is marked
built after reading the code, not the board. Read the tiers underneath with this list in
hand.

Infra 1 and 2, the two the ranking says block every feature, are both done. sqlcipher
at-rest ships as `Store.enc` plus `OpenEncrypted`, a tmpfs working copy re-encrypted on
`Close`, keyed from `db_key_env` in `deploy/mavend.json`. mavweb and mavcaldav are no
longer at zero coverage: seven test files under `cmd/mavweb`, including
`credentials_test.go` and `passkey_prf_test.go`, and two under `cmd/mavcaldav`. Infra 3
is stale in the other direction. There are still no systemd units, but the deploy is
`deploy/ecosystem/docker-compose.yml`, not scripts and tmux.

Doable tier, built: rule trace and explanation as `/trace` plus `internal/loop/explain.go`.
Recurring reminders as the cron column, `NextFireTs` and `RescheduleReminder`
(`internal/store/reminders.go:206`), so "fires once right now" is wrong. Stale-reminder
burst collapse as `collapseReminders` (`internal/loop/gather.go:209`). Revert as
`VoidLatestFact` (`internal/store/facts.go:300`). Digest mode as `internal/store/digest.go`.
Testing infra as the simulator and the eval lab (V-284, V-278). Passkey persistence as the
JSON-backed `credentialStore` in `cmd/mavweb/credentials.go`. Most integrations shipped as
their own QA tasks (V-246 mail, V-256 smarthome, V-258 rss, V-259 crawler).

Doable tier, still open: correx, systemd units, memory decay and duplicate detection
(nothing in `internal/memory` touches it), backup automation, import and export, barge-in.

Epic tier, unbuilt as ranked. `event.Bus` exists (`cmd/mavend/intake.go:57`) but it is the
intake journal from V-283, not the rewrite of facts into projections that this tier means.

---

## infra — blocks everything below, in order

1. **sqlcipher at-rest** — auth chapter (cold-start = layer-3, key-in-core-only) is fiction without it. plain sqlite on disk right now, anyone with disk access reads everything.
2. **mavweb / mavcaldav tests** — zero coverage. mavweb carries passkey HTTP flow + the tools-enable surface, i.e. the actual privilege-escalation gate. webauthn crypto is tested; the handlers wiring it up aren't.
3. **systemd units** — core/module isolation ("crash-independent, key-free modules") is currently a claim, not enforced. still scripts+tmux.
4. **go.mod tidy** — trivial, do whenever.

nothing feature-level below should land before 1–2 are done. 3–4 can interleave.

---

## features, ranked

### mandatory
things that block correctness or safety of stuff already shipped — not new capability, just closing gaps in existing design.

- **destructive-confirm policy** — open question in `docs/design.md` § open questions, blocks correx and any new tool domain from having a coherent risk tier
- **quiet-hours definition** — open question, blocks proactive delivery being trustworthy
- **schema migrations** — sqlcipher rollout alone forces a schema touch. want this mechanism before that, not after.

### easy
cheap, no dependencies, no new invariants.

- **grocery / `list_items` table** — fourth append-only shape (item, status, list-tag), no predicate touches it, multi-adder just works for free
- **go.mod tidy**
- **capability model** (deepseek) — `homelab.docker.restart` instead of flat `tool→enabled`. cheap now, expensive to retrofit once tools surface passes ~15 entries. time-sensitive, not urgent.
- **conversation repair** — already free: `docs/design.md` has "misroute correction = new centroid example," this is just naming the existing mechanism as a feature
- **command history** — read-only query over existing facts, no new mechanism
- **clarification templates** — canned phrasing for the router's existing confidence-gate fallback, phraser-lane only
- **pronunciation dictionary** — tts config, no architecture

### doable
real work, scope is clear, no new invariant needed — reuses proposed→enabled / gate / append-only patterns already pinned.

- **correx integration** — mechanism already sketched (task queue → correx → diff/PR → gated merge, same authority tier as any module, zero key access). stalls on destructive-confirm policy + mavweb hardening first.
- **systemd units** (infra, feature-adjacent)
- **passkey persistence past restart** — bounded fix, matters more once cold-start unlock routes through the passkey-authed page (otherwise chicken/egg: box reboots locked, unlock needs passkey, passkey needs re-enroll)
- **confidence propagation** — flagged independently by deepseek + chatgpt, never tiered until now. touches store schema (confidence riding along derived facts, not just source facts)
- **rule trace / explanation engine / presence debugger** — one feature, not three. "why did/didn't you nudge me" over existing predicate evals. worth doing before mandatory rules multiply
- **recurring reminders** — real gap, reminders only fire once right now. "trash every tuesday" isn't representable yet
- **stale-reminder burst collapse** — NOT a recovery bug: recovery already works. `DueReminders` is `status='pending' AND fire_ts <= now` with no lower bound, and the gatherer calls it every tick (`gather.go:139`), so on the first boot tick every reminder that came due while the daemon was down is still pending and fires. The only real gap is cosmetic: a pile of stale reminders all firing at once on boot could spam. Doable-tier polish (collapse/digest the boot burst), not mandatory. (was mis-filed as "missed-reminder recovery, one-shot, nothing catches up" — that premise was wrong)
- **revert** (was "undo") — not a new mechanism, just a wrapper: void the latest row instead of hard delete. append-only already supports it
- **notification batching / digest mode** — layer over existing sev routing, morning/evening rollup instead of per-event
- **memory decay / duplicate / conflict detection** — chroma-side hygiene, no predicate touches it, low-risk to add
- **backup/restore automation** — spec already says "backup is `cp`," this just scripts it properly
- **import/export, config versioning** — easy-adjacent, mostly plumbing
- **barge-in (interrupt tts)** — audio-stack level UX gap, not architecture-level
- **most integrations** (email, rss, github, media players, package/update monitoring, docker/k8s status) — just allowlist entries, capability-gated same as everything else. volume, not novelty
- **testing infra** (state snapshots, fake clock, replay, regression suite for rules) — should slot in right after mavweb tests. unit-testable predicates are wasted without the harness
- **timeline viewer / performance metrics / admin dashboard** — UI on top of data that already exists. doable once mavweb has tests, not before

### epic
real forks of the project. need their own design pass, not a bolt-on.

- **multi-user / namespace (gf)** — presence, delivery, `nudges` restraint memory all assume a single subject end to end. touching all three, not a tag column. waits on deepseek's multi-user approach review + sqlcipher (namespacing means nothing if disk read = everything).
- **self-update via correx** — needs task-queue location decided (own db, isolated from core's key-holding store) and correx already stable before it's worth the authority jump.
- **event bus** (deepseek) — facts stop being writes, become projections over immutable events. rewrite, not addition.
- **goal management** (deepseek) — new long-lived object (`Goal`), new relations to reminders/notes/observations. genuinely new subsystem, not an extension of existing three.
- **dependency graph between facts/rules/goals** — needs the goal object to exist first
- **plugin api** — third-party capability-injection point, worse than a single tool gap. needs its own auth-tier conversation before it's even a candidate
- **speaker adaptation / wake-word personalization** — depends on multi-user existing first, same per-subject problem
- **multi-device audio routing** — same shape as multi-user: presence/delivery need to know *which* device, not just *if present*. new dimension.
- **hot-reloadable rules** — mild tension with "rules as code, not a DSL." reload-without-redeploy touches core's minimalism principle, needs a real look, not a free yes
- **mobile offline mode** — router/stt/tts assume homesrv reachable over wg. real offline means shipping a model subset onto the phone
- **wearable integration** — new presence signal (weight/τ pair) + new delivery channel
- **location-aware automations** — needs a location fact type that doesn't exist yet, and gps is a much bigger privacy jump than wg handshake

### rejected
explicitly not doing these, noted so they don't get re-proposed later.

- **federated assistants** — multiple maven instances talking over network is "phones home" with extra steps

---

## open dependency notes

- correx and multi-user both stall on **destructive-confirm policy** — worth pinning that one first since two epics share the block
- capability model's "easy" rating has a shelf life — same shape as the sqlcipher-before-cold-start window: cheap today, not cheap forever
- rule trace / explanation / presence debugger got proposed three times under three names across the source lists — same feature, collapse it
- schema migrations moved from "doable" to "mandatory" — sqlcipher forces the first real migration, want the mechanism before that lands, not built ad hoc during it
