diff --git a/AGENTS.md b/AGENTS.md index 944ed46..1901f9c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,7 +18,7 @@ live in sibling repos next to this one. Division of labour: Nexus identifies, Praxis observes, Hexis acts, Maven understands and coordinates. Maven is not the source of truth for any of the three. The full -contract is `MAVEN_ECOSYSTEM_ARCHITECTURE.md`, and the constraints that bite during +contract is `docs/ecosystem.md`, and the constraints that bite during implementation are summarised in `CLAUDE.md`. Where things are in this repo: diff --git a/CLAUDE.md b/CLAUDE.md index 5c2ce01..89474cf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,7 +10,7 @@ compose passes `/dev/dri` + the render gid) — the resident model stays ≤1.7B **Resident model:** currently **Qwen3-1.7B** (`UD-Q4_K_XL`), stock — not yet the CPT'd one. It replaced Qwen3.5-0.8B on 2026-07-31 because it measured better on both fixtures we have: 67.5% vs 59.7% intent-only on the 77-case RU routing fixture, and 20/27 vs 11-17/27 on the -talk fixture. See `MODEL-BAKEOFF-31-07-2026.md`. It is a Thinking variant, so `n_ctx` is 4096 +talk fixture. See `docs/evals/2026-07-31-model-bakeoff.md`. It is a Thinking variant, so `n_ctx` is 4096 — reasoning tokens need the room, and 4096 is what the scores above were measured at. The **target** is still the locally CPT'd **Qwen3-1.7B** (Vikunja #122, training in flight). @@ -25,7 +25,7 @@ Spanish. Their strong published IFEval/BFCL numbers are English-only. Model file `models/llm/`, so the LFM2.5 gguf sitting there is not loaded by anything. Swapping the resident model is a one-line change to `phraser.model_path` in `deploy/mavend.json`. -See `REARCH.md` for the target architecture, `DESIGN.md` for the folded design spec, and +See `docs/rearchitecture.md` for the target architecture, `docs/design.md` for the folded design spec, and `AGENTS.md` for local-preview + model-download recipes. ## Build & test @@ -72,7 +72,7 @@ protocol; the config in `deploy/mavend.json` (with `${VAR}` env expansion from g Maven is one of four services. It owns conversation and personal memory. It does not own identity, operational state, or execution. Full contract in -`MAVEN_ECOSYSTEM_ARCHITECTURE.md`. +`docs/ecosystem.md`. ```text Nexus identifies. Praxis observes. Hexis acts. Maven understands and coordinates. @@ -113,7 +113,7 @@ Every cross-service call carries a correlation id minted once per action on in deploy** — this section used to say it was wired `nil`, which stopped being true on 2026-07-31. -- **LLM router (the intended design, REARCH.md):** the resident Qwen3-1.7B (`llmrouter.go`) +- **LLM router (the intended design, docs/rearchitecture.md):** the resident Qwen3-1.7B (`llmrouter.go`) emits GBNF-constrained structured JSON, and the SAME model phrases replies. Embedder is demoted from a routing gate to a RAG hint. Wired at `voice.go:214` via `pickLLMRouter(cfg.Voice.UseLLMRouter(), llmClient)`; the flag is `voice.llm_router` @@ -127,11 +127,11 @@ on in deploy** — this section used to say it was wired `nil`, which stopped be Cascade order: `stage0.go` exact-match fast-path → LLM router (when non-nil) → classifier fallback. Any LLM error falls through to the classifier so a turn never breaks on the model. -Measured on the 77-case RU fixture (`MODEL-BAKEOFF-31-07-2026.md`): the classifier scores +Measured on the 77-case RU fixture (`docs/evals/2026-07-31-model-bakeoff.md`): the classifier scores 36.8% full accuracy at p50 31ms; Qwen3-1.7B scores 67.5% intent-only / 72.7% through the cascade at p50 ≈825ms. Accuracy roughly doubled, latency is ~27× worse, and that trade was accepted deliberately. **The ≈2.7s figure that stood here until 2026-08-02 was contention, -not the model.** See `ROUTING-EVAL-31-07-2026.md` line 61, which measures the LLM router at +not the model.** See `docs/evals/2026-07-31-routing.md` line 61, which measures the LLM router at p50 825ms / p95 1.2s / max 3.0s and the full cascade at p50 0.80-1.04s. Do not plan latency work off the bakeoff table. `Confidence: 1.0` used to be hardcoded in `llmrouter.go`, so the LLM path could never ask for clarification (6/6 refusal cases missed on the fixture) — Vikunja diff --git a/Makefile b/Makefile index c3e8d7b..1721e39 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ deps-go: done $(GO) version -# fmt-check fails if any file needs gofmt. DESIGN.md has always said `make +# fmt-check fails if any file needs gofmt. docs/design.md has always said `make # test` gates on gofmt and vet; it did not, so nine files quietly drifted. # Run `gofmt -w` on whatever this prints. fmt-check: @@ -191,7 +191,7 @@ deps-piper: # multilingual-e5-small: an asymmetric retrieval model. It is trained to match # a short question against a longer passage, which is what note recall is. # The quantized file is the one we download, deploy and measure — see -# RECALL-EVAL-31-07-2026.md. +# docs/evals/2026-07-31-recall.md. EMBEDDER_DIR := $(shell pwd)/models/embedder/multilingual-e5-small EMBEDDER_MODEL_URL := https://huggingface.co/Xenova/multilingual-e5-small/resolve/main/onnx/model_quantized.onnx EMBEDDER_TOKENIZER_URL := https://huggingface.co/Xenova/multilingual-e5-small/resolve/main/tokenizer.json diff --git a/PROGRESS.md b/PROGRESS.md index 97960fe..b3a11af 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -74,7 +74,7 @@ full-weight checkpoint at step 1000/8077; evaluation and Qwen3 SFT tooling are tracked in `docs/plans/2026-07-18-qwen3-resident-training-eval.md`. Consolidated status. The reactive↔proactive core is closed and testable through -the web PWA. The former SPEC's open items 1–7 (now `DESIGN.md` § execution ledger) are landed (protocol doc, away-channel +the web PWA. The former SPEC's open items 1–7 (now `docs/design.md` § execution ledger) are landed (protocol doc, away-channel fallthrough, CalDAV poller, quiet-hours schedule, tools enable/disable, note RAG, passkey step-up); item 8 (multi-user) is deliberately deferred — see the tail. The two big infra gaps from the jul5 revision are closed on `overnight-jul5`: @@ -145,7 +145,7 @@ tests, `-race` in `make test`. time window (`voice.quiet_hours`, HH:MM, midnight-crossing handled) now sets it on each tick — in addition to the "тихий режим" voice toggle. Both activate quiet. - **Client protocol (SPEC item 1):** the voice wire format (length-prefixed JSON - frames) is published in `PROTOCOL.md`, generated from `internal/voice/wire.go` + frames) is published in `docs/protocol.md`, generated from `internal/voice/wire.go` so third-party clients don't need the Go source. - **Passkey step-up (SPEC item 7):** `internal/webauthn` does real WebAuthn — ES256/P-256 register + assert, ecdsa signature verification, rpIdHash + UP/UV @@ -463,6 +463,6 @@ Not neglect — the one item where doing nothing now beats doing something: - **The hard part is speaker attribution, and it needs the second voice.** A voice-print discriminator (kami vs gf vs unknown) can't be trained or tuned with one voice in the house. Plumbing before the model is pipe with no water. -- **It's fenced deliberately** (`DO NOT TOUCH THIS PHASE` in `DESIGN.md` § Users) so an +- **It's fenced deliberately** (`DO NOT TOUCH THIS PHASE` in `docs/design.md` § Users) so an autonomous agent doesn't add `user_id` columns while touching the store and commit us to a schema before the constraints that shape it exist. diff --git a/cmd/mavenclient/main.go b/cmd/mavenclient/main.go index e711404..6427f0c 100644 --- a/cmd/mavenclient/main.go +++ b/cmd/mavenclient/main.go @@ -1,6 +1,6 @@ // Package main is mavenclient — maven's reference client. // -// Per DESIGN.md § Voice pipeline (STT / TTS): capture lives on the client; +// Per docs/design.md § Voice pipeline (STT / TTS): capture lives on the client; // the server transcribes + synthesises on demand. The PC client runs the // wake-word / VAD gate (cmd/mavwaked) and ships ONE clean audio blob per // utterance on activation. The server never owns a mic. diff --git a/cmd/mavweb/main.go b/cmd/mavweb/main.go index b39823e..2f00dff 100644 --- a/cmd/mavweb/main.go +++ b/cmd/mavweb/main.go @@ -512,7 +512,7 @@ func main() { // /tools — the authed enable surface. maven proposes acts she can't run; // this page is where a human reviews and enables them (proposed→enabled). - // Enabling is the boundary-moving act (DESIGN.md § Tool registration — + // Enabling is the boundary-moving act (docs/design.md § Tool registration — // drafting is suggest, enabling is act), so it lives ONLY here, // behind wg+nginx+auth — never the voice/chat path. mux.HandleFunc("/tools", func(w http.ResponseWriter, r *http.Request) { diff --git a/REVIEW-30-07-2026.md b/docs/archive/2026-07-30-senior-review.md similarity index 93% rename from REVIEW-30-07-2026.md rename to docs/archive/2026-07-30-senior-review.md index 3c868e6..e60a5a5 100644 --- a/REVIEW-30-07-2026.md +++ b/docs/archive/2026-07-30-senior-review.md @@ -30,7 +30,7 @@ critical workflows: voice turn (mic→STT→route→tool/reply→TTS); proactive (/dash /chat /tools /ecosystem) current state: all 34 test packages pass; vet clean; `make test` still exits 1 (finding 2) -known failures: weak RU query routing — REARCH.md names the cause; the named fix +known failures: weak RU query routing — docs/rearchitecture.md names the cause; the named fix is wired `nil` maintenance burden: 4,518 lines of root markdown vs 33,319 lines of Go; 15 top-level .md files, 3 of them dated session logs; several contradict @@ -47,11 +47,11 @@ what's obsolete: llmrouter.go (built, tested, never wired); classifier seed-p ``` **Classification: healthy + misaligned.** Not fragile, not overbuilt, not abandoned. The -architecture in `REARCH.md` is sound and mostly *built* — it just is not *connected*. +architecture in `docs/rearchitecture.md` is sound and mostly *built* — it just is not *connected*. ## what it should become -The thing `REARCH.md` already describes, with the switch flipped and the drift removed: +The thing `docs/rearchitecture.md` already describes, with the switch flipped and the drift removed: one resident small model doing both routing and phrasing, classifier demoted from the live path to the failure floor, embedder demoted to RAG hint. No new architecture is needed. **The gap is a config/wiring decision plus doc convergence, not a redesign.** @@ -65,19 +65,19 @@ path to the failure floor, embedder demoted to RAG hint. No new architecture is `architecture` / `repair` **problem:** The most load-bearing design decision in the project is stated four different, -incompatible ways, and the code path `REARCH.md` calls "the linchpin" is disabled. +incompatible ways, and the code path `docs/rearchitecture.md` calls "the linchpin" is disabled. **evidence** (all confirmed): - `cmd/mavend/voice.go:211` — `rtr := buildRouter(emb, matcher, threshold, nil) // LLM router disabled`, with comment *"the classifier handles routing reliably."* -- `REARCH.md:11` says the same classifier is *"the structural cause of 'she messes up +- `docs/rearchitecture.md:11` says the same classifier is *"the structural cause of 'she messes up queries.'"* **The code comment and the design doc make opposite claims about the same component.** - `internal/router/llmrouter.go` (139 lines) + `llmrouter_test.go` — fully built and tested, zero non-test callers. -- Model identity, four ways: docs say **Qwen3-1.7B** (`CLAUDE.md:6`, `REARCH.md:15`, - `SPEC.md:46`, `AGENTS.md:79`, `MAVEN_ECOSYSTEM_ARCHITECTURE.md:72`); +- Model identity, four ways: docs say **Qwen3-1.7B** (`CLAUDE.md:6`, `docs/rearchitecture.md:15`, + `SPEC.md:46`, `AGENTS.md:79`, `docs/ecosystem.md:72`); `deploy/mavend.json:9` says **Qwen3.5-2B-UD-Q4_K_XL**; `models/llm/` on disk holds **LFM2.5-1.2B-Thinking**; code comments in 5 files still say **LFM**. - `deploy/mavend.json:11` sets `"n_gpu_layers": 99` while `CLAUDE.md:4` states the target @@ -100,7 +100,7 @@ match. Delete nothing from `internal/router` yet — the classifier is the fallb reconciliation, not a refactor. **Do not rewrite the router.** **alternatives:** Delete `llmrouter.go` and commit to the classifier — only defensible if -the eval harness shows the classifier is actually adequate, which contradicts `REARCH.md`. +the eval harness shows the classifier is actually adequate, which contradicts `docs/rearchitecture.md`. **risk:** Low-moderate. LLM route failures already fall through to the classifier (`router.go:88-96`), so a bad model cannot break a turn. The real risk is CPU latency. @@ -228,21 +228,21 @@ after finding 1, not before** — and skip it if it stays purely cosmetic. **problem:** 15 root markdown files, 4,518 lines, several stale or superseded, at least three pairs contradicting each other. -**evidence:** `ROADMAP.md` (759) + `MAVEN_ECOSYSTEM_ARCHITECTURE.md` (884) + +**evidence:** `ROADMAP.md` (759) + `docs/ecosystem.md` (884) + `PROGRESS.md` (456) + `maven.md` (413) + `20-07-2026-BACKLOG.md` (396) + `SESSION-05-07-2026.md` + `SESSION-06-07-2026.md` (477 combined) + `PLANS.md` (25) + -`START.md` + `SPEC.md` + `PROTOCOL.md`. `PROGRESS.md:61` annotates its own staleness: -*"Older LFM references below describe the currently deployed..."*. `REARCH.md` announces it +`docs/operations.md` + `SPEC.md` + `docs/protocol.md`. `PROGRESS.md:61` annotates its own staleness: +*"Older LFM references below describe the currently deployed..."*. `docs/rearchitecture.md` announces it "supersedes" a model still described as current elsewhere. **impact:** The doc set is the reason finding 1 exists. When five documents describe the architecture, the code becomes the only trustworthy one — which defeats the purpose of having them. -**recommended action:** Keep `CLAUDE.md` (agent contract), `REARCH.md` (target -architecture), `AGENTS.md` (recipes), `PROTOCOL.md` (wire format), +**recommended action:** Keep `CLAUDE.md` (agent contract), `docs/rearchitecture.md` (target +architecture), `AGENTS.md` (recipes), `docs/protocol.md` (wire format), `20-07-2026-BACKLOG.md` (live queue). Delete the two `SESSION-*.md` and `PLANS.md` — git -history holds them. Fold `SPEC.md` + `maven.md` + `ROADMAP.md` into one `DESIGN.md` and +history holds them. Fold `SPEC.md` + `maven.md` + `ROADMAP.md` into one `docs/design.md` and mark superseded sections instead of leaving them to read as current. Target ~1,500 lines. --- @@ -320,7 +320,7 @@ expected maintenance gain: none over the incremental path suggesting Vulkan offload is intended and working — but `CLAUDE.md` says CPU-only. Likely the doc is stale, not the config; unverified. - **Whether the classifier is genuinely adequate.** `voice.go:211` asserts it is; - `REARCH.md` asserts it is not. Both are claims, neither is measured. The uncommitted eval + `docs/rearchitecture.md` asserts it is not. Both are claims, neither is measured. The uncommitted eval harness is the instrument to settle it — resolve before flipping the router, not after. - **Whether wg+nginx+auth actually fronts 9201 in production.** Not in this repo. If it does, finding 3 drops from "unauthenticated RCE" to "the control is not reproducible from @@ -350,7 +350,7 @@ Key claims independently re-verified against the working tree; the verdict stand over WireGuard on homesrv, this is hygiene, not an emergency — but the loopback bind and startup warning are cheap insurance either way, so do them regardless. - Finding 1's "flip the router" step should be gated harder on measurement. - `REARCH.md`'s claim that the classifier causes weak RU queries is itself unmeasured — + `docs/rearchitecture.md`'s claim that the classifier causes weak RU queries is itself unmeasured — the review admits this under uncertainties, but the "repair now" ordering buries it. Run `eval_scenarios_test.go` against both paths **before** deciding to flip, not after. A 2B model on CPU may add enough latency that the classifier wins in practice diff --git a/DESIGN.md b/docs/design.md similarity index 98% rename from DESIGN.md rename to docs/design.md index 611f00c..d3510c0 100644 --- a/DESIGN.md +++ b/docs/design.md @@ -1,10 +1,12 @@ # Maven — Design +*Last verified: 2026-08-02 @ 7079a24. Living doc: correct it in place, do not append.* + > Folded 2026-07-30 from `SPEC.md` (north star, 2026-07-03), `maven.md` > (consolidated decisions, 2026-06-30) and `ROADMAP.md` (execution plan, > 2026-07-06). Those three files are gone; git history holds them. > This is the single design document: principles, target state, and the -> execution ledger. `REARCH.md` remains authoritative wherever it disagrees +> execution ledger. `docs/rearchitecture.md` remains authoritative wherever it disagrees > with anything here. Everything the three sources asserted that is no longer > the intended design is preserved under **§ Superseded** — do not read that > section as current. @@ -160,7 +162,7 @@ presence_state ( last_bucket, last_score, updated_ts ) ``` Facts additionally carry `Subject`/`EntityID`/`ResolutionState` for -entity-aware resolution against Nexus (see `MAVEN_ECOSYSTEM_ARCHITECTURE.md`). +entity-aware resolution against Nexus (see `docs/ecosystem.md`). ### Trigger model @@ -196,7 +198,7 @@ INTO the gate as an env predicate, not the LLM's job. ## Reactive path — routing -**Target design: LLM-as-router** (see `REARCH.md` and `CLAUDE.md`). One +**Target design: LLM-as-router** (see `docs/rearchitecture.md` and `CLAUDE.md`). One resident model emits GBNF-constrained structured JSON, and the same model phrases replies; the embedder is a RAG hint, not a routing gate. The committed default today is the classifier/embedder cascade, which is an @@ -655,7 +657,7 @@ daemon. The voice wire protocol (length-prefixed JSON frames over TCP) is designed for **multiple client implementations**. The reference PWA at `cmd/mavweb` is one client; any app (phone, desktop CLI, smartwatch) can implement the same frame -protocol. The published spec is `PROTOCOL.md` — **generated from +protocol. The published spec is `docs/protocol.md` — **generated from `internal/voice/wire.go`**, not composed freehand, so it can't drift from code. It covers transport (4-byte big-endian length prefix), methods (`PushToTalk`, `Pong`), push kinds (`AudioNudge`), surface identity @@ -755,7 +757,7 @@ Kept for provenance. **None of this is the current or intended design.** stay deterministic — "classifier owns the route, the SLM stays in its phrasing lane" — with an embedding + nearest-centroid stage 1 over ~10 examples per intent, and misroutes appended as new centroid examples. - *Replaced by* LLM-as-router (`REARCH.md`): one resident model emits + *Replaced by* LLM-as-router (`docs/rearchitecture.md`): one resident model emits GBNF-constrained JSON and also phrases replies; the embedder is demoted to a RAG hint. *Landed 2026-07-31:* the LLM router is on by default and set `true` in `deploy/mavend.json`. The classifier cascade stays as the failure @@ -774,7 +776,7 @@ Kept for provenance. **None of this is the current or intended design.** *Resolved 2026-07-30 (#318), revised 2026-07-31:* the resident checkpoint is stock **Qwen3-1.7B** (`UD-Q4_K_XL`, `n_ctx` 4096), which replaced Qwen3.5-0.8B after measuring better on both fixtures - (`MODEL-BAKEOFF-31-07-2026.md`). The CPT'd **Qwen3-1.7B** remains the target + (`docs/evals/2026-07-31-model-bakeoff.md`). The CPT'd **Qwen3-1.7B** remains the target (#122); what stock gets wrong is the persona, not the Russian. Note the resident model is no longer described as untrained — the target is trained end-to-end, which is the substantive change from the old claim. diff --git a/PLAN-DETERMINISM-02-08-2026.md b/docs/determinism.md similarity index 98% rename from PLAN-DETERMINISM-02-08-2026.md rename to docs/determinism.md index 4810882..08bf853 100644 --- a/PLAN-DETERMINISM-02-08-2026.md +++ b/docs/determinism.md @@ -1,5 +1,7 @@ # Deterministic logic around a small model +*Last verified: 2026-08-02 @ 7079a24. Living doc: correct it in place, do not append.* + Written 2026-08-02. Branch `fix/integrated`. ## The question @@ -268,7 +270,7 @@ rebuilt `mavend` wires it. "кто написал войну и мир?" now rou that turn left unsettled. - **The turn was slow, and nobody knows yet whether that is real.** Route 7s, - search 1s, phrasing 15s. The p50 in `ROUTING-EVAL-31-07-2026.md` is 825ms. It + search 1s, phrasing 15s. The p50 in `docs/evals/2026-07-31-routing.md` is 825ms. It was the first turn after a cold start with the model still warming, so it proves nothing either way. Re-run the same question warm before treating it as a regression. Do not plan latency work off this number. diff --git a/MAVEN_ECOSYSTEM_ARCHITECTURE.md b/docs/ecosystem.md similarity index 99% rename from MAVEN_ECOSYSTEM_ARCHITECTURE.md rename to docs/ecosystem.md index 0d4a60a..9b6bd7d 100644 --- a/MAVEN_ECOSYSTEM_ARCHITECTURE.md +++ b/docs/ecosystem.md @@ -1,5 +1,7 @@ # Maven Ecosystem Architecture +*Last verified: 2026-08-02 @ 7079a24. Living doc: correct it in place, do not append.* + ## 1. Purpose This document defines Maven's role in the local ecosystem formed by: diff --git a/MODEL-BAKEOFF-31-07-2026.md b/docs/evals/2026-07-31-model-bakeoff.md similarity index 96% rename from MODEL-BAKEOFF-31-07-2026.md rename to docs/evals/2026-07-31-model-bakeoff.md index ecf897d..4f5fc3e 100644 --- a/MODEL-BAKEOFF-31-07-2026.md +++ b/docs/evals/2026-07-31-model-bakeoff.md @@ -16,7 +16,7 @@ with Qwen3-1.7B. Settles Vikunja **#278 / #250**. -- Same fixture and scorer as `ROUTING-EVAL-31-07-2026.md`: `internal/router/eval/` +- Same fixture and scorer as `docs/evals/2026-07-31-routing.md`: `internal/router/eval/` (`ru_routing_v1.json`, 76 held-out cases). - Reproduce: `MAVEN_LLM_URL=http://127.0.0.1: make eval-router` (`TestLLMRouterBaseline`). (This line used to say there is no `make eval-models` target. @@ -148,7 +148,7 @@ Qwen3-1.7B wins every column, including against a model 20% larger than it. | ontopic | 16, 19, 19 | **22, 23, 23** | | canned fallbacks | 8, 5, 6 | **0, 2, 0** | -This also fills the row `TALK-EVAL-31-07-2026.md` had to void for contamination: +This also fills the row `docs/evals/2026-07-31-talk.md` had to void for contamination: **600ch/1024tok on Qwen3.5-0.8B scores 13, 11, 8.** `address` is the headline. It sat at 18-22 of 27 on the 0.8B no matter how the prompt @@ -164,7 +164,7 @@ The 1.7B does that 0-2 times. > **Stale, corrected 2026-08-02.** The p50 figures in this table are contention on a > shared llama-server, not the model's cost. The router measures p50 825ms / p95 1.2s / -> max 3.0s in `ROUTING-EVAL-31-07-2026.md`, which says so at line 61. Read this table for +> max 3.0s in `docs/evals/2026-07-31-routing.md`, which says so at line 61. Read this table for > the shape of the tail only. Take absolute latency from the routing eval. | | p50 | p95 | @@ -220,11 +220,11 @@ swapped again when the CPT lands. behind `voice.llm_router`, the default is on, and `deploy/mavend.json` sets it `true`. These numbers are the production path now. **Corrected 2026-08-02: the p50 ≈2.7s in the latency table above WAS a bench artifact.** It is contention on the shared llama-server, - not the model. `ROUTING-EVAL-31-07-2026.md` line 61 says so, and measures the router at + not the model. `docs/evals/2026-07-31-routing.md` line 61 says so, and measures the router at p50 825ms / p95 1.2s / max 3.0s. Cite that file for latency, not this one. - ~~`/mnt/hdd1/llms/LFM2.5/Qwen3-1.7B-UD-Q4_K_XL.gguf` is a 293 MB truncated download in the wrong directory.~~ **Deleted 2026-07-31.** The good 1.13 GB copy in `qwen3/` is what `deploy/mavend.json` loads. - Harness: `scratchpad/bakeoff.sh`, one server at a time, health-checked before each run, `/v1/models` recorded per run. Never run two LLM consumers at once — see the - contamination note in `TALK-EVAL-31-07-2026.md`. + contamination note in `docs/evals/2026-07-31-talk.md`. diff --git a/PHRASING-EVAL-31-07-2026.md b/docs/evals/2026-07-31-phrasing.md similarity index 99% rename from PHRASING-EVAL-31-07-2026.md rename to docs/evals/2026-07-31-phrasing.md index 0573665..e64e1ab 100644 --- a/PHRASING-EVAL-31-07-2026.md +++ b/docs/evals/2026-07-31-phrasing.md @@ -1,7 +1,7 @@ # Phrasing evaluation — 31-07-2026 How Maven words a nudge, measured instead of argued. Counterpart to -`ROUTING-EVAL-31-07-2026.md`. +`docs/evals/2026-07-31-routing.md`. - Fixture + scorer: `internal/phraser/eval/` (`nudges_v1.json`, 15 cases; `eval.go`, `checks.go`) - Reproduce: `MAVEN_LLM_URL=http://127.0.0.1:18099 make eval-phrasing` diff --git a/RECALL-EVAL-31-07-2026.md b/docs/evals/2026-07-31-recall.md similarity index 99% rename from RECALL-EVAL-31-07-2026.md rename to docs/evals/2026-07-31-recall.md index ead570c..6c82e56 100644 --- a/RECALL-EVAL-31-07-2026.md +++ b/docs/evals/2026-07-31-recall.md @@ -65,7 +65,7 @@ prefixes) is the targeted fix, and it would move findings 1 and 2 together. Sepa `model_quantized.onnx` — not the same file. `hard` cases score **2/11**: every one is a query where the operator did not reuse his own words. -That is the normal case weeks later, and exactly what DESIGN.md's "recall when relevant" promises. +That is the normal case weeks later, and exactly what docs/design.md's "recall when relevant" promises. ### 4. The memory-store recall branch is dead for notes diff --git a/ROUTING-EVAL-31-07-2026.md b/docs/evals/2026-07-31-routing.md similarity index 99% rename from ROUTING-EVAL-31-07-2026.md rename to docs/evals/2026-07-31-routing.md index 1ddef82..9144f51 100644 --- a/ROUTING-EVAL-31-07-2026.md +++ b/docs/evals/2026-07-31-routing.md @@ -177,7 +177,7 @@ was silent ("не знаю" to "который час") while the one it introdu ### 1. The resident model does route better — 50.0% vs 36.8% -REARCH.md's premise holds; `voice.go:211`'s comment does not. **But the classifier is only +docs/rearchitecture.md's premise holds; `voice.go:211`'s comment does not. **But the classifier is only ~37% correct on held-out utterances, and the model only ~50%.** Neither is "reliable". The gap between them is real but both are far from a system you would describe as working. diff --git a/TALK-EVAL-31-07-2026.md b/docs/evals/2026-07-31-talk.md similarity index 99% rename from TALK-EVAL-31-07-2026.md rename to docs/evals/2026-07-31-talk.md index 65cad81..58561c2 100644 --- a/TALK-EVAL-31-07-2026.md +++ b/docs/evals/2026-07-31-talk.md @@ -141,7 +141,7 @@ a model check, which catches a dead server but not a loaded one. measured) on this fixture and the router fixture. Not the 4B — too big for this box, owner's call. - Newer sub-500M candidates (LFM2.5 200M/300M) are worth a run for routing. - Note `MODEL-BAKEOFF-31-07-2026.md` found LFM2.5-**1.2B** worse than + Note `docs/evals/2026-07-31-model-bakeoff.md` found LFM2.5-**1.2B** worse than Qwen3.5-0.8B at Russian routing and 2.4× slower — but those are a different, older generation, so that result does not predict the small ones. - Fix `chat-how-are-you`'s `want_any`, and re-baseline once, so `ontopic` diff --git a/START.md b/docs/operations.md similarity index 98% rename from START.md rename to docs/operations.md index 74cf6a7..004f54d 100644 --- a/START.md +++ b/docs/operations.md @@ -1,5 +1,7 @@ # Start Commands +*Last verified: 2026-08-02 @ 7079a24. Living doc: correct it in place, do not append.* + All commands assume `ROOT=/home/kami/apps/Maven` and the local Go toolchain at `$ROOT/deps/go/go/bin/go`. ## Prerequisites diff --git a/docs/plans/2026-07-10-router-lfm-foundation.md b/docs/plans/2026-07-10-router-lfm-foundation.md index 30a0220..af78fce 100644 --- a/docs/plans/2026-07-10-router-lfm-foundation.md +++ b/docs/plans/2026-07-10-router-lfm-foundation.md @@ -6,7 +6,7 @@ > use the embedded LFM model paths or old single-object examples as current ops > guidance; see `2026-07-18-qwen3-resident-training-eval.md`. -> Scope from `REARCH.md`. Make Maven trustworthy: the LFM becomes the router +> Scope from `docs/rearchitecture.md`. Make Maven trustworthy: the LFM becomes the router > (fixes "messes up queries" / "doesn't take notes"), the engine actually runs > (fixes stub replies), dates stop being read as "number dot number dot number", > and telegram becomes a reach channel. NOT in scope: on-demand 4B reasoner, @@ -693,7 +693,7 @@ ssh kami@192.168.1.104 'curl -s localhost:9201/api/chat -d "{\"text\":\"запо 4. `docker compose up -d mavend && docker logs -f maven-mavend-1` — confirm the phraser spawns and no `phraser: NewStub` path. Run the two verify curls. 5. Update `AGENTS.md`: LFM model download + note that routing is now LFM-first - with classifier fallback (`REARCH.md` is the design of record). + with classifier fallback (`docs/rearchitecture.md` is the design of record). --- diff --git a/PROTOCOL.md b/docs/protocol.md similarity index 98% rename from PROTOCOL.md rename to docs/protocol.md index b2f9b59..56dbe9f 100644 --- a/PROTOCOL.md +++ b/docs/protocol.md @@ -1,5 +1,7 @@ # Maven Voice Protocol +*Last verified: 2026-08-02 @ 7079a24. Living doc: correct it in place, do not append.* + > Auto-generated from `internal/voice/wire.go`, `internal/voice/errors.go`, > `internal/voice/frame.go`, `internal/voice/client.go`. If this file and > those files disagree, the code wins. diff --git a/QA-PLAN.md b/docs/qa.md similarity index 99% rename from QA-PLAN.md rename to docs/qa.md index e7dea73..8d04217 100644 --- a/QA-PLAN.md +++ b/docs/qa.md @@ -1,5 +1,7 @@ # QA plan: checking Maven properly +*Last verified: 2026-08-02 @ 7079a24. Living doc: correct it in place, do not append.* + Written 2026-08-01, after the 35-PR stack landed and the box came back up. 44 of the 50 open Vikunja tasks are `QA:` tasks. They are verification work, not diff --git a/REARCH.md b/docs/rearchitecture.md similarity index 98% rename from REARCH.md rename to docs/rearchitecture.md index 36e110e..130951b 100644 --- a/REARCH.md +++ b/docs/rearchitecture.md @@ -1,5 +1,7 @@ # Maven — Re-architecture (Qwen3 resident model, revised 2026-07-18) +*Last verified: 2026-08-02 @ 7079a24. Living doc: correct it in place, do not append.* + > Supersedes the classifier-first routing model. Agreed in a design session > after diagnosing that homesrv deploys with a **stub phraser** (no LLM > running) and an embedder-classifier that routes by nearest-neighbor between diff --git a/internal/auth/tier.go b/internal/auth/tier.go index 4c5589b..f7d0aff 100644 --- a/internal/auth/tier.go +++ b/internal/auth/tier.go @@ -1,7 +1,7 @@ // Package auth is maven's authority layer — the 4-layer cascade and the // "surface caps authority" invariant. // -// Spec contract (from DESIGN.md § Auth): +// Spec contract (from docs/design.md § Auth): // // a cascade, not a pick-one — each layer answers a different question: // diff --git a/internal/config/config.go b/internal/config/config.go index a55dc13..a95bf77 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -649,7 +649,7 @@ type VoiceConfig struct { // LLMRouter — route with the resident model instead of the embedding // classifier. On by default since Vikunja #320. // - // Measured on the held-out fixture (ROUTING-EVAL-31-07-2026.md): 63.2% of + // Measured on the held-out fixture (docs/evals/2026-07-31-routing.md): 63.2% of // intents right against the classifier's 50.0%, and no route errors. It // costs about 1s per turn instead of 30ms. // diff --git a/internal/delivery/channel.go b/internal/delivery/channel.go index aa54c12..8da5d20 100644 --- a/internal/delivery/channel.go +++ b/internal/delivery/channel.go @@ -1,6 +1,6 @@ // Package delivery is maven's channel-routing + dispatch layer. // -// Spec contract (from DESIGN.md § Delivery / channel routing): +// Spec contract (from docs/design.md § Delivery / channel routing): // // - routing = f(severity, presence). presence decides REACHABILITY; severity // decides INSISTENCE. need both. diff --git a/internal/delivery/routing_table_test.go b/internal/delivery/routing_table_test.go index a008880..404cf26 100644 --- a/internal/delivery/routing_table_test.go +++ b/internal/delivery/routing_table_test.go @@ -9,7 +9,7 @@ import ( "github.com/kami/maven/internal/store" ) -// This file walks every cell of the DESIGN.md § "Delivery / channel routing" +// This file walks every cell of the docs/design.md § "Delivery / channel routing" // table, once as the pure table and once through the dispatcher, so a change // to either side has to break a named cell. // @@ -205,7 +205,7 @@ func TestAwayChannelsGetMinimalBody(t *testing.T) { // An empty Summary no longer means "send the whole body" — it means a short // generic line — so the old expectation here was wrong as well as duplicated. -// TestCareAwayDropIsRecorded — DESIGN.md's drop is a decision ("a missed water +// TestCareAwayDropIsRecorded — docs/design.md's drop is a decision ("a missed water // nudge is noise, a missed backup failure isn't"), so it should be visible // rather than vanish. Today drop is a bare `continue`: no nudge row, no outbox // attempt, no log — nothing an operator can see afterwards. now it leaves a diff --git a/internal/kiwix/rewrite.go b/internal/kiwix/rewrite.go index 408d608..7986538 100644 --- a/internal/kiwix/rewrite.go +++ b/internal/kiwix/rewrite.go @@ -31,7 +31,7 @@ type Completer interface { // or reply in Russian. // // Why the JSON wrapper: this model always thinks out loud and this llama-server -// build ignores the thinking switch (see ROUTING-EVAL-31-07-2026.md). A bare +// build ignores the thinking switch (see docs/evals/2026-07-31-routing.md). A bare // word-list grammar just captured the reasoning — every case came back as // "Let me analyze this request carefully". Demanding JSON, like routeGrammar and // responseGrammar already do, gives the reasoning nowhere to go. diff --git a/internal/loop/gate_test.go b/internal/loop/gate_test.go index 8c66f45..eb613d4 100644 --- a/internal/loop/gate_test.go +++ b/internal/loop/gate_test.go @@ -10,12 +10,12 @@ import ( // Tests for the universal restraint gate. // -// DESIGN.md § Trigger model: "the gate is universal, applied by the loop, never +// docs/design.md § Trigger model: "the gate is universal, applied by the loop, never // per-rule — quiet-hours, presence, cooldown, snooze, calendar-busy all live in // one fires()." These tests pin the CONSERVATIVE side of that: the cases where // Maven must stay quiet. They exist so nobody loosens the gate by accident. // -// Where the code does not yet do what DESIGN.md promises, the test is written to +// Where the code does not yet do what docs/design.md promises, the test is written to // show the gap and then skipped, with the file and line to fix. Behaviour is not // changed to make a test pass. @@ -54,7 +54,7 @@ func TestGateQuietHoursSuppressesCareOnly(t *testing.T) { // ---------------------------- presence --------------------------------------- -// DESIGN.md § Delivery: "sev <= 2 drops on away, sev >= 3 holds: a missed water +// docs/design.md § Delivery: "sev <= 2 drops on away, sev >= 3 holds: a missed water // nudge is noise, a missed backup failure isn't." func TestGateAwayDropsCareHoldsOps(t *testing.T) { cases := []struct { @@ -250,7 +250,7 @@ func TestTickOrderOfRulesDoesNotMatter(t *testing.T) { // ---------------------------- reminders bypass the gate ---------------------- -// DESIGN.md § User reminders: "bypasses the restraint gate — 'wake me 7' fires +// docs/design.md § User reminders: "bypasses the restraint gate — 'wake me 7' fires // in quiet hours; that's the point." Every suppressor set at once, and the // reminder still comes through. func TestRemindersBypassEverySuppressor(t *testing.T) { @@ -269,7 +269,7 @@ func TestRemindersBypassEverySuppressor(t *testing.T) { } } -// GAP — DESIGN.md § User reminders ends "Snooze still applies." RemindDecisions +// GAP — docs/design.md § User reminders ends "Snooze still applies." RemindDecisions // passes every due reminder straight through with no snooze check, so a snoozed // reminder fires anyway. The test below is what the contract asks for. func TestRemindersStillHonourSnooze(t *testing.T) { diff --git a/internal/loop/rules_test.go b/internal/loop/rules_test.go index af765a6..3bec077 100644 --- a/internal/loop/rules_test.go +++ b/internal/loop/rules_test.go @@ -18,7 +18,7 @@ import ( // - does it stay quiet when it should? // - is it silent when the key it needs has no data at all? // -// The last one is load-bearing. DESIGN.md: "since(key)==null → don't fire. +// The last one is load-bearing. docs/design.md: "since(key)==null → don't fire. // Silence on no-data is 'shuts up when uncertain'." // stateWith builds a snapshot at refTime() holding just the given facts. @@ -179,7 +179,7 @@ func TestCareRulePredicates(t *testing.T) { // ---------------------------- ops rules -------------------------------------- -// The two ops rules match on a value AND on which poller wrote it. DESIGN.md: +// The two ops rules match on a value AND on which poller wrote it. docs/design.md: // "a compromised poller must not be able to forge a trigger." Half of this // table is forgery attempts; all of them must be refused. func TestOpsRulePredicates(t *testing.T) { @@ -331,7 +331,7 @@ func TestNoDefaultRuleFiresOnEmptyState(t *testing.T) { } } -// Severities are the delivery contract (DESIGN.md § Delivery / channel +// Severities are the delivery contract (docs/design.md § Delivery / channel // routing): care is sev1-2 and drops when away, ops is sev3-4 and holds. Pin // them so a change to a rule's insistence has to be deliberate. func TestDefaultRuleSeverities(t *testing.T) { @@ -356,7 +356,7 @@ func TestDefaultRuleSeverities(t *testing.T) { } } -// Cooldown bounds keep the feedback tuner honest — DESIGN.md wants +// Cooldown bounds keep the feedback tuner honest — docs/design.md wants // `cooldown in [min,max]` "so a weird week can't mutate Maven silent or // stalker". A base outside its own envelope would make that meaningless. func TestDefaultRuleCooldownsAreBounded(t *testing.T) { diff --git a/internal/memory/recalleval/ru_recall_v1.json b/internal/memory/recalleval/ru_recall_v1.json index 7659680..f5f9c7d 100644 --- a/internal/memory/recalleval/ru_recall_v1.json +++ b/internal/memory/recalleval/ru_recall_v1.json @@ -41,7 +41,7 @@ "tags": ["preference", "homelab", "paraphrase", "hard"], "query": "когда запускать резервное копирование", "want": "n1", - "note": "The DESIGN.md preference-seam example, phrased as the operator would ask it later.", + "note": "The docs/design.md preference-seam example, phrased as the operator would ask it later.", "notes": [ {"id": "n1", "text": "бэкапы лучше делать ночью в три часа", "kind": "note"}, {"id": "n2", "text": "обновления ставлю по субботам", "kind": "note"}, diff --git a/internal/phraser/eval/checks.go b/internal/phraser/eval/checks.go index 29a198b..4fffc46 100644 --- a/internal/phraser/eval/checks.go +++ b/internal/phraser/eval/checks.go @@ -15,7 +15,7 @@ const ( CheckLang = "lang" // the operator's language, not the prompt's CheckLength = "length" // a nudge is one sentence, not a paragraph CheckFeminine = "feminine" // her self-reference is feminine (hard constraint) - CheckCringe = "cringe" // DESIGN.md § Non-goals, "not a relationship" + CheckCringe = "cringe" // docs/design.md § Non-goals, "not a relationship" CheckOnTopic = "ontopic" // says the thing the rule is about // CheckHisGender — the other half of the persona rule: SHE is feminine, HE @@ -105,7 +105,7 @@ func checkLength(body string) Result { // --- feminine self-reference --------------------------------------------- // -// The hard constraint (CLAUDE.md, DESIGN.md § Identity): Maven's Russian +// The hard constraint (CLAUDE.md, docs/design.md § Identity): Maven's Russian // self-reference is feminine. The operator is male, so second-person forms // addressed to him are MASCULINE and must not be flagged — "ты не пил воду" is // correct, "я напомнил" is not. Both directions matter, which is why this is a @@ -497,7 +497,7 @@ func isLatinWord(w string) bool { // --- the cringe checks --------------------------------------------------- // -// "Think Jarvis without the cringe part". DESIGN.md § Non-goals: "Not a +// "Think Jarvis without the cringe part". docs/design.md § Non-goals: "Not a // relationship — mom-tone is a function that makes nudges land, not emotional // company. Names the drift a warm small model falls into." Each pattern below // is one shape of that drift. They are deliberately specific: a check that diff --git a/internal/phraser/eval/eval.go b/internal/phraser/eval/eval.go index f199ebb..3b79797 100644 --- a/internal/phraser/eval/eval.go +++ b/internal/phraser/eval/eval.go @@ -11,7 +11,7 @@ // length test that a human can read and disagree with. A score here is a claim // about measurable properties, not about whether a sentence is good. // -// DESIGN.md § "Rules decide, LLM phrases" is why there is no send/veto signal +// docs/design.md § "Rules decide, LLM phrases" is why there is no send/veto signal // anywhere in this package: the rule already decided she speaks. The phraser // only words it, so a nudge the model refuses to write is a failure, never a // legitimate outcome. @@ -38,7 +38,7 @@ var fixtureJSON []byte const SchemaVersion = 1 // Case — one nudge situation, as a real tick would present it. The fields are -// the (rule, severity, context) input DESIGN.md names, flattened to JSON. +// the (rule, severity, context) input docs/design.md names, flattened to JSON. // // WantAny is the on-topic contract: at least one of these lowercased fragments // must appear in the message. A water nudge that never mentions water is a diff --git a/internal/phraser/llmphraser.go b/internal/phraser/llmphraser.go index fd34770..ba690b1 100644 --- a/internal/phraser/llmphraser.go +++ b/internal/phraser/llmphraser.go @@ -692,7 +692,7 @@ func (p *LLMPhraser) chatWithSystem(ctx context.Context, system, user string, ma // Written as filled-in examples, not as a schema with "..." in it. A 0.8B // copies whatever sits in the response slot, so a literal placeholder there // teaches it to answer with the placeholder. Measured: 7/15 nudges came back -// as "..." before this. See PHRASING-EVAL-31-07-2026.md. +// as "..." before this. See docs/evals/2026-07-31-phrasing.md. // // Russian only, feminine self-reference, second person masculine (the owner is // a man). She talks TO him, informally, singular — never "вы", never "он". diff --git a/internal/phraser/phraser.go b/internal/phraser/phraser.go index a15f7bb..79488d2 100644 --- a/internal/phraser/phraser.go +++ b/internal/phraser/phraser.go @@ -1,9 +1,9 @@ // Package phraser is maven's "rules decide, llm phrases" seam — the layer // that turns a loop decision into the body + summary the delivery module ships. // -// Per DESIGN.md § Resident language model: the phraser is the resident model +// Per docs/design.md § Resident language model: the phraser is the resident model // (Qwen3-1.7B — RU continued pretraining plus joint persona/router SFT, not a -// sub-1b prompted-only model as the retired spec claimed; see DESIGN.md +// sub-1b prompted-only model as the retired spec claimed; see docs/design.md // § Superseded, "small-model phrasing claim"). It takes // (rule, severity, context) and produces Body (full voice message, local — no // shoulder-surf concern beyond who's in the room) + Summary (minimal body for diff --git a/internal/router/eval/llmrouter_test.go b/internal/router/eval/llmrouter_test.go index 12a8e76..fe5cc43 100644 --- a/internal/router/eval/llmrouter_test.go +++ b/internal/router/eval/llmrouter_test.go @@ -39,7 +39,7 @@ import ( // Re-measured with everything else held equal, thinking off scores exactly the // same, case for case — and a direct probe shows this llama-server build ignores // enable_thinking / reasoning_budget for this model anyway, so there was nothing -// to turn off. Full write-up in ROUTING-EVAL-31-07-2026.md (Vikunja #376). +// to turn off. Full write-up in docs/evals/2026-07-31-routing.md (Vikunja #376). func TestLLMRouterBaseline(t *testing.T) { base := os.Getenv("MAVEN_LLM_URL") if base == "" { diff --git a/internal/router/intent.go b/internal/router/intent.go index 758c042..df15fea 100644 --- a/internal/router/intent.go +++ b/internal/router/intent.go @@ -1,13 +1,13 @@ // Package router is maven's reactive path — the cascade that turns a free-form // utterance into a deterministic Decision. // -// Spec contract (from DESIGN.md § Reactive path — routing): +// Spec contract (from docs/design.md § Reactive path — routing): // // - the TARGET design is LLM-as-router: the resident model (Qwen3-1.7B) // emits GBNF-constrained structured JSON for the route, and the same // model phrases replies; the embedder is a RAG hint, not a routing gate. // the classifier/embedder cascade below is the committed default today, -// but it is an interim stopgap (DESIGN.md § Superseded, "classifier-owns- +// but it is an interim stopgap (docs/design.md § Superseded, "classifier-owns- // the-route") and the known cause of weak RU query handling — not a // design to extend. // - a CASCADE, not one decider — layers: @@ -35,7 +35,7 @@ package router import "time" -// Intent — the seven save-where labels from DESIGN.md's routing table. The +// Intent — the seven save-where labels from docs/design.md's routing table. The // discriminator is "does the loop evaluate a predicate against it?": // // - act: command now, not stored (function call into the allowlist) diff --git a/internal/stt/stt.go b/internal/stt/stt.go index 615a1d1..3a26d81 100644 --- a/internal/stt/stt.go +++ b/internal/stt/stt.go @@ -18,9 +18,9 @@ // returns a canned string the router + action path operate on); with a // worker socket configured, it wires Remote. // -// Per DESIGN.md § Voice pipeline (STT / TTS): whisper.cpp (CGo, Vulkan) in +// Per docs/design.md § Voice pipeline (STT / TTS): whisper.cpp (CGo, Vulkan) in // cmd/mavsttd is the production stt — the older faster-whisper/vosk picks are -// retired (DESIGN.md § Superseded, "named STT/TTS model picks"). The +// retired (docs/design.md § Superseded, "named STT/TTS model picks"). The // server-side stt module is the heavy multilingual path; the client's // wake-word + stage-0 command grammar (cmd/mavwaked) hits the router directly // and never crosses this seam. Today's Remote + Stub both return plain text diff --git a/internal/tool/tool.go b/internal/tool/tool.go index 4a1b017..d948d58 100644 --- a/internal/tool/tool.go +++ b/internal/tool/tool.go @@ -2,7 +2,7 @@ // store's allowlist, and drafts 'proposed' scaffolds for acts that aren't on // it yet. // -// Boundary discipline (DESIGN.md § "Tool registration — drafting is suggest, +// Boundary discipline (docs/design.md § "Tool registration — drafting is suggest, // enabling is act"): // // - The store is the allowlist. Only status='enabled' rows run. A verb not @@ -26,7 +26,7 @@ // - Destructive tools don't run on first hearing: Exec returns ErrNeedsConfirm // and the handler runs a confirm turn ("выполнить X? да/нет"); only a // confirmed re-Exec runs them. A gate assumes a fully-formed action, which -// an enabled+matched act is (DESIGN.md § "Confirmation is not one +// an enabled+matched act is (docs/design.md § "Confirmation is not one // mechanism"). package tool diff --git a/internal/tts/tts.go b/internal/tts/tts.go index 31019fb..4fae0ab 100644 --- a/internal/tts/tts.go +++ b/internal/tts/tts.go @@ -5,9 +5,9 @@ // PCM, headerless per the audio package; the voice sink + reference client // wrap it in a WAV at the disk edge. // -// Per DESIGN.md § Voice pipeline (STT / TTS): piper is the production tts +// Per docs/design.md § Voice pipeline (STT / TTS): piper is the production tts // (subprocess + espeak-ng, CPU-only on the ryzen box, driven by cmd/mavttsd); -// the older silero pick is retired (DESIGN.md § Superseded, "named STT/TTS +// the older silero pick is retired (docs/design.md § Superseded, "named STT/TTS // model picks"). A different voice is a model-file swap, not a code change. // The daemon wires one impl — Remote pointing at the worker socket if // configured, Stub otherwise. diff --git a/maven-feature-ranking.md b/maven-feature-ranking.md index 5c2ae35..ec83127 100644 --- a/maven-feature-ranking.md +++ b/maven-feature-ranking.md @@ -1,6 +1,6 @@ # maven — feature ranking -> dated 2026-07-03. companion to `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. +> 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. --- @@ -20,7 +20,7 @@ nothing feature-level below should land before 1–2 are done. 3–4 can interle ### 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 `DESIGN.md` § open questions, blocks correx and any new tool domain from having a coherent risk tier +- **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. @@ -30,7 +30,7 @@ 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: `DESIGN.md` has "misroute correction = new centroid example," this is just naming the existing mechanism as a feature +- **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