Files
Maven/docs/plans/21-persisting-the-routing-trace.md
T
claude 7852aad60f every turn persists its decision record, and the reversal is written down (V-629)
internal/decision kept a 25-turn ring and persisted nothing, on the argument
that a turn record is read minutes later or never. The owner reversed that on
06-08-2026: the routing heads cannot be fitted or calibrated without real
utterances, and V-631 measured that 9 of the 31 modes have no seed example at
all. docs/plans/21-persisting-the-routing-trace.md carries the reversal, and
CLAUDE.md now says which of its own sentences stopped being true.

cmd/mavend/routingtrace.go is a second sink beside the ring, which did not move:
the ring is still what /trace reads and still what a test with no store gets. A
failed insert is logged and swallowed, because a trace must never change what he
hears. traceSink keeps a nil store out of the interface, since a typed nil
pointer there would pass the nil check and die on the first turn.

Four fields the ring never carried: which reach the turn arrived on, whether
stage 0 answered before the classifier was consulted, which encoder body was
live (the same EmbedderID string the vector marker uses), and what the action
stage actually did.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117tgnmbgZpHVV3XSNw8Qua
2026-08-06 19:13:20 +04:00

3.0 KiB

Plan: persist the routing trace

Owner's call, 06-08-2026. Vikunja #629, umbrella #628.

Verdict: the per-turn decision record is now written to the database. That reverses a written decision, which is the point of this file. It is not an incidental telemetry feature and must not be read as one.

Last verified: 06-08-2026 @ 799cf55

What the old decision said

internal/decision kept a 25-turn in-memory ring and persisted nothing. The argument was in CLAUDE.md and it was a good one. A turn record is read minutes after the turn or never, so a table that outlives the diagnosis buys nothing. His words did not belong in it.

Why it reversed

V-546 replaces the generative router with classification heads on e5-small. Fitting prototypes and calibrating a distance both need real utterances. V-631 measured how few there are. Nine of the 31 modes in internal/modes have no seed example at all, and they are exactly the nine with no deterministic matcher. The seed corpus cannot supply them. A seed row is a phrase someone wrote for a matcher, not a thing he said. The 202 generated contrast pairs were tried and cost four points of fixture accuracy.

So the choice was between no routing heads and a persisted trace. The owner chose the trace.

Retention, and why it is two answers

Raw trace: 14 days. routingTraceRetention in internal/store/routingtraces.go. That is the life of a diagnosis with room for a weekend. The bound is an age and not a row count. The useful question is what she did this week, and a busy Tuesday must not push last Friday out.

A correction: indefinite. The owner corrects a turn on /chat (V-630). The pair is then promoted out of the trace into a seed-shaped row and kept, because a label is not a transcript. What stays in routing_traces is the transcript. It expires on the same 14 days as every other row, corrected or not.

What keeps it safe

The utterance is stored in clear. A 384-dimension vector of a short sentence is substantially recoverable. Storing vectors instead would be a privacy claim we cannot support, and making it would be worse than staying silent.

  • Nothing here leaves the box. The rule that the owner's notes and facts are never search input covers this table too. No query source reads it, and no upstream engine can.
  • Retention is enforced on write. WriteRoutingTrace prunes every 64th row, which is hours at human rate.
  • Deletion already exists. Store.Wipe drops every table the database reports, so mavend -wipe -confirm-wipe covers this one with no list to edit.
  • The ring did not move. It is still what /trace reads and still what a test with no store gets. The table is a second sink beside it. A failed insert is logged and swallowed, because a trace must never change what he hears.

What is not decided

Whether some utterances must never be promoted into a durable label, no matter how badly they routed. That is a content rule and it belongs beside the personal boundary, not in the trace writer. Recorded here, left to the owner.