Reference-count the process-global ONNX Runtime across embedder and routing-head sessions, make close idempotent, and require named proof that both aggregate routing gates executed rather than self-skipped (V-716). Owner explicitly requested direct commits to master.
12 KiB
Maven completion journal
This journal tracks the autonomous completion goal started on 2026-08-13. It is an operational index, not a substitute for living subsystem documentation, dated evaluations, Vikunja tasks, or focused caveat entries.
2026-08-13 — baseline and backlog reconstruction
Goal: make Maven usable end to end with every current and planned feature wired, tested, and polished. Completion requires clean automated gates and successful sessions across local, degraded-ecosystem, and integrated modes.
Initial observations:
HEADis2cf8b7e, identical to both local and remotemaster, while the checked-out branch is the staletask/704-...branch.- The worktree already contained staged documentation/evaluation changes,
staged transcript deletions, an unstaged
deploy/mavwaked.servicechange, and untrackeddeploy/asoundrc. These are pre-existing work and are being preserved and validated before any commit. - The repository has no prior goal journal. Durable subsystem facts continue
to belong under
docs/; unresolved limits continue to belong underdocs/caveats/with a task and revisit trigger.
Work streams started:
- Vikunja project 2: inventory every open task and recover acceptance criteria.
- Repository: compare feature plans, caveats, routing/ecosystem contracts, and implementation.
- Verification: run build, race tests, simulator, analyzer gates, and inspect skipped hardware/model evaluations separately.
- Runtime: exercise the web, IPC, voice, model, and sibling-service paths with real local dependencies where available and explicit degraded-mode probes otherwise.
References: docs/workflow.md, docs/qa.md, docs/ecosystem.md,
docs/routing.md, docs/caveats/CLAUDE.md, and Vikunja Maven project 2.
Backlog correction
The first Vikunja page was accidentally read without a done: false filter and
mixed closed history into the working set. Re-querying all pages strictly open
produced 127 records: 89 implementation-open, 20 shipped-but-QA-open, 12
external/owner gates, and 6 duplicate or stale-open records. Closed tasks are
used only as commit provenance; they are not work to redo. V-704 was the only
open hanging task and was closed after its measured correction landed.
Model-aware baseline
The ordinary make test passed but does not set MAVEN_ONNX_LIB, so model-aware
tests can self-skip. The explicit ONNX boundary gate exposed V-702/V-703: the
held-out я рассказывал тебе про байкал? was the sole miss at 28/29. A
three-neighbour class score fixed the semantic collision without adding a word
pattern or copying the held-out sentence. Boundary is now 29/29 and the adjacent
topic gate remains 43/43. Measurement:
docs/evals/2026-08-13-personal-boundary-neighbourhood.md.
That narrow result was not accepted as the completion gate. A second agent wrote a balanced 72-case RU/EN matrix across remembered speech, possession, narrative, proper nouns, personal preambles, and advice/current questions. It contains no production seeds and no Baikal paraphrase. The top-three candidate scores only 61/72 (84.7%); top-two reaches 62/72, one-neighbour 56/72, and a whole-class centroid 54/72. V-702 therefore remains open while a principled classifier is developed against the independent matrix. The 29/29 measurement describes the narrow regression set, not general boundary quality.
Live delivery incident
The five-service compose stack was running, but a due reminder was being re-phrased and retried through ntfy every tick. The sink returned HTTP 403 each time. Only secret names were inspected: the configured ntfy and workstation token variables were absent from the deployed environment file; no secret values were read into this journal. The durable outbox records each failed attempt, but the retry path has no backoff or alternate channel and spends the resident model again before every failure. This is active V-651 behavior, with the repeated-phrasing shape related to V-687.
V-715 now owns the incident acceptance criteria. In the working tree, phrases, collapsed-group identity, attempts, and next-attempt time are durable; definite failure backs off from one minute to a capped hour; retries and restarts reuse the exact phrase; and away delivery tries ntfy then Telegram, stopping at the first success. The committed deployment explicitly disables the uncredentialed ntfy block. Independent review added a real occurrence key for collapsed bundles, suppresses crash-ambiguous attempts from automatic replay, classifies HTTP 401/403 as permanent, blocks permanently unreachable reminders visibly, and commits the successful outbox result plus every collapsed original in one SQLite transaction. The store, delivery, IPC, loop, config, and mavweb race suites pass. A live rebuild and one-time delivery of the existing backlog are still required before V-715 is closed.
Explicit integration enablement
V-691's deployment boundary was audited against every ${VAR} reference. The
canonical deploy/telegram.env.example now names Telegram, ntfy, workstation
model, workstation STT, Home Assistant, ambient, CW2, and database-key inputs.
Enabled Telegram, ntfy, ambient, non-loopback workstation model, and
non-loopback workstation STT paths refuse missing credentials; each arm has an
explicit disabled state. The live config disables the currently uncredentialed
ntfy and workstation-model arms while retaining the separately credentialed
STT arm. CW2 also refuses a non-loopback bind without its token.
Focused Go race suites, the Python CW2 startup contract, deploy-config drift
test, secret-expanded config validation (values not printed), and
docker compose config --quiet pass. The workpc is unreachable from this host,
so installing the updated CW2 script there remains an external deployment step;
the affected model arm is explicitly dark rather than ambiguously half-live.
Traceable web failures
V-689 gives every mavweb response a server-generated request ID and routes
every handler failure through one sanitized problem envelope. Stable error
codes and the request ID reach the browser; the wrapped internal error reaches
only the server log beside the same ID. Degraded inline panels use stable public
text rather than backend paths or tokens, and direct ecosystem reads propagate
the web request ID as their correlation ID. An AST guard prevents new production
handlers from bypassing the contract with http.Error. The full mavweb race
suite passes, including disclosure, untrusted-ID, log-join, and propagation
tests.
Bounded external responses
Three audit defects were repaired and committed directly to master:
- V-608 (
d7e8804): llama completion responses are capped at 1 MiB, including the LAN workstation seam. - V-675 (
459fe7a): remote STT requires nonblank text and an explicit finite confidence in[0,1], caps JSON at 64 KiB, and falls back to mavsttd on a malformed HTTP 200. - V-676 (
7d0250a): Open-Meteo geocoding and forecasts are bounded, required fields are nullable/validated, and coordinates/weather values are range checked so{}cannot become plausible zero-degree weather.
Each focused race suite passed and each task was closed only after the commit.
Transport shutdown
V-679 (de61b75) adds the listener's done channel to TCP Accept. A
concurrent-close test holds a silent peer in handshake and proves an in-flight
accept returns net.ErrClosed; the race test passed twenty consecutive runs.
V-688 (80b6068, caveat retirement a0e6643) bounds the browser push-to-talk
body at ten minutes of mono PCM and configures header, idle, and read limits on
the web server. The unused /ws handler was removed instead of retaining a
second unauthenticated streaming transport with no browser caller. Focused race
tests prove the exact-size request succeeds and an oversized request returns
HTTP 413.
Conversation continuity
V-542 (da9114b) repairs the five-turn monitor conversation without changing
single-turn intent classification. Exact user utterances are now persisted
separately from normalized intent slots and retained in chronological order.
An anaphoric query with live transcript context reaches the chat path, while
non-anaphoric sources are unchanged and acts stay fail-closed. An explicit
conversation opener extends the session lifetime through later fact/query/chat
routes without suppressing the grounded fact write.
The deterministic scenario now names the monitor in all four contextual
replies, proves that the original raw turn reached PhraseChat four times,
stores the fact once, and produces zero unsolicited sends across five turns and
one tick. Focused race tests passed for cmd/mavend, internal/dialogue,
internal/router, and internal/lexicon. Measurement:
docs/evals/2026-08-13-conversation-continuity.md.
Personal-data boundary
V-702 replaces the narrow nearest-neighbour privacy gate with a frozen, class-balanced logistic head over multilingual-e5-small. It introduces no lexical exception and leaves the decision threshold at 0.5. Historical regressions score 29/29 and the balanced 72-case RU/EN fixture scores 72/72.
The first 24-case challenge found one private-configuration miss. That result
was treated as model-selection data rather than advertised as independent
proof. Shrinkage LDA and an LDA/logistic ensemble repaired it but regressed the
72-case gate, so both were rejected. Increasing the logistic L2 coefficient
from 0.0001 to 0.0003 repairs the miss while improving four-fold corpus
cross-validation from 97/104 to 99/104 and whole-shape holdout from 91/104 to
92/104. A fresh 24-case challenge written only after that head was frozen scores
24/24 at minimum signed probability margin +0.1718. The original challenge is
also 24/24 but its +0.0001 edge remains documented as a regression, not fresh
evidence. Full measurement:
docs/evals/2026-08-13-personal-boundary-linear-head.md.
During the audit, running multiple ONNX-backed tests in one go test process
showed that only the first initializes; later tests self-skip because the
runtime is process-global. All V-702 figures were therefore rerun in separate
processes. V-716 tracks fixing that harness gap rather than hiding it in this
feature.
Forced dialogue and repair state
V-573 closes all four repair seams exposed by the dialogue contract: a correction wins before a parked clarify answer; a repaired decision is checked for required slots before acting; a request completed through clarification is correctable; and declined or stale repairs do not prematurely spend the repair pointer. Same-intent corrections are handled explicitly without redoing the action, so their prose cannot route fresh and overwrite the retained pointer.
The independent state audit found two deeper stack losses. A handled repair could leave an older question silently parked with its old TTL, and a repaired request needing clarification could overwrite—or, on completion, delete—the older flow. Repairs now suspend and audibly resume live questions, repaired questions push onto the bounded dialogue stack, and completion/cancellation pops only the active top before resuming the flow underneath.
MAVEN_DIALOGUE_NO_SKIP=1 go test -race ./cmd/mavend -run '^TestDialogueTraces$' -count=1 passes all 22 traces. The complete forced
cmd/mavend race suite passes in 208.031s. The integrated race command over
cmd/mavend, internal/dialogue, and all internal/router packages also
passes (162.310s for mavend; every package green). Focused structural
possession, repair-pointer, nested-stack, and repaired-clarify tests pass under
the race detector.
ONNX test/runtime lifecycle
V-716 found that each embedder constructor tried to initialize ONNX Runtime,
while Close destroyed only its session. In one package process the first
model-aware test ran and later tests converted “already initialized” into a
green skip. The router now owns the process-global environment through
reference-counted leases held by each embedder and routing-head session; the
last owned lease performs cleanup, and close is idempotent.
The router and mavend test packages hold a lease across their model gates.
make eval-router additionally requires proof that both named aggregate gates
actually executed. In one process the classifier baseline scored 72/96 and the
routing heads 93/96; destination was 11/33 and 25/33 respectively, and ecosystem
reach remained 28/30. The lifecycle reacquire test, focused race suite, full
aggregate command, and portable no-runtime packages all pass. Measurement:
docs/evals/2026-08-13-onnx-runtime-lifecycle.md.