Give the stage 0 grammar set one home (V-693)
buildRouter held the real set and baselineGrammars in eval_test.go restated it by hand, in the daemon's order, with its own comment saying so. Three test files score against the fixture and nothing compared the two lists. They had already drifted: BareCaptureGrammar went into the daemon with V-557 and never into the fixture, so every routing measurement since has scored a set nobody runs. That is the failure CLAUDE.md warns about by name, and a diff test would have caught it one grammar late. The list moves to router.StageZeroGrammars in internal/router/stagezero.go, with the ordering comments, which are the load-bearing part. buildRouter and the fixture both call it. One list cannot drift from itself. Measured before and after on the 96-case fixture: classifier+onnx 72/96, 75.0% intent, 33.3% destination, identical either way, and the deterministic claim and reach hash ratchets do not move. So the missing grammar cost no measurable accuracy. That is the point rather than a reprieve: the fixture had been scoring the wrong set for four days and nothing could say so. The invariants caveat is deleted, both entries, since V-692 landed the other guard in the previous commit. The reasoning for both now sits in docs/routing.md beside the subsystem, which is where a fix's durable record belongs. Unrelated and pre-existing: TestONNXPersonalBoundary fails on "я рассказывал тебе про байкал?" (personal 0.9068, world 0.9413) at the merge base too.
This commit is contained in:
@@ -22,10 +22,12 @@ caveat is the pointer between them plus the trigger.
|
||||
|
||||
Every entry below came from the 2026-08-10 deep audit
|
||||
(`docs/evals/2026-08-10-repo-audit.md`), except the last, which came from wiring
|
||||
the gate the audit asked for. Three of the twenty findings are fixed and have no
|
||||
the gate the audit asked for. Five of the twenty findings are fixed and have no
|
||||
entry. The unauthenticated mavgpud proxy was V-673. The 20 reachable advisories
|
||||
in the toolchain and `x/text` were V-682. The missing analyzers were V-694, and
|
||||
what they now report is the baseline entry under V-701.
|
||||
what they now report is the baseline entry under V-701. The two unguarded
|
||||
invariants were V-692 and V-693, and their guards are described in
|
||||
`docs/routing.md`.
|
||||
|
||||
| limit | severity |
|
||||
| --- | --- |
|
||||
@@ -41,8 +43,6 @@ what they now report is the baseline entry under V-701.
|
||||
| [mavweb errors cannot be traced](transport.md#errors) | medium |
|
||||
| [Fact enrichment is a 20-call serial waterfall](workers.md#enrichment) | medium |
|
||||
| [A suppressed nudge is phrased anyway](workers.md#nudges) | medium |
|
||||
| [heads_path may equal model_path](invariants.md#heads) | medium |
|
||||
| [baselineGrammars is mirrored by hand](invariants.md#grammars) | medium |
|
||||
| [Committed absolute paths pin the build to this box](config.md#paths) | medium |
|
||||
| [The env example omits deployed variables](config.md#secrets) | medium |
|
||||
| [The analyzers pass against a baseline, not zero](dependencies.md#baseline) | medium |
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# Unguarded invariants
|
||||
|
||||
`CLAUDE.md` names these as load-bearing. Nothing enforces either one. A rule
|
||||
that lives only in prose gets broken by whoever did not read the prose. Both of
|
||||
these fail silently when broken.
|
||||
|
||||
`tokenizerRev` and `preRouteLadder` were checked and need nothing. The rev is
|
||||
baked into the embedder key, so a bump triggers re-embedding. A missing ladder
|
||||
rung is observable in the decision record.
|
||||
|
||||
## heads_path may equal model_path [#692] {#heads}
|
||||
|
||||
Costs: the routing heads then score with the same graph the resident e5-small
|
||||
uses, and recall degrades. There is no error and no log line, so it reads as
|
||||
ordinary drift rather than a misconfiguration.
|
||||
Revisit when: `deploy/mavend.json` is edited by hand, or a fine-tuned heads
|
||||
graph is swapped in.
|
||||
Workaround: check the two keys by eye. That is the whole guard today.
|
||||
|
||||
## baselineGrammars is mirrored by hand [#693] {#grammars}
|
||||
|
||||
Costs: the eval fixture restates the stage 0 rule set in the daemon's order,
|
||||
and its own comment says so. Three test files score against it. A grammar added
|
||||
to `buildRouter` alone means every routing measurement scores a set nobody
|
||||
runs. `CLAUDE.md` warns about this failure by name.
|
||||
Revisit when: the next stage 0 grammar is added. That is when it bites.
|
||||
Workaround: add to both lists, which is what the rule already says.
|
||||
+17
-5
@@ -1,6 +1,6 @@
|
||||
# Routing
|
||||
|
||||
*Last verified: 2026-08-09 @ 31b5093*
|
||||
*Last verified: 2026-08-11 @ 25ed201*
|
||||
|
||||
How an utterance becomes a `Decision`, why each stage exists, and what every
|
||||
stage has measured. `CLAUDE.md` carries the rules an agent must not break. This
|
||||
@@ -137,10 +137,15 @@ below.
|
||||
Go's `\b` is ASCII-only and never fires after a Cyrillic letter. A pattern needs
|
||||
an explicit `(\s|[?!.]|$)`.
|
||||
|
||||
`baselineGrammars` in `eval_test.go` mirrors `buildRouter` and has drifted before.
|
||||
`WorldQueryGrammars` was wired into the daemon by V-655 and not into the mirror,
|
||||
so the fixture scored a grammar set nobody runs. Fixed by V-659, worth 3 points
|
||||
of destination.
|
||||
The stage 0 set lives in `router.StageZeroGrammars` (`internal/router/stagezero.go`).
|
||||
Both `buildRouter` and the eval fixture call it. The daemon and the measurement
|
||||
cannot disagree about which rules exist, or in what order.
|
||||
|
||||
It was two lists until V-693 and it drifted twice. V-655 wired
|
||||
`WorldQueryGrammars` into the daemon and not into the fixture. That cost 3 points
|
||||
of destination and V-659 fixed it. `BareCaptureGrammar` then did the same thing,
|
||||
from V-557 until V-693 found it. That one moved no number, which is the point:
|
||||
the fixture had been scoring a set nobody ran and nothing said so.
|
||||
|
||||
### Praxis lifecycle rules
|
||||
|
||||
@@ -270,6 +275,13 @@ Three rules around it, each measured:
|
||||
means the heads are nil. The cascade is then byte-for-byte what shipped before
|
||||
them.
|
||||
|
||||
Pointing it at `model_path` is refused at config load (V-692). An unloadable
|
||||
weights file is not fatal, because the heads are an accelerator. A working file
|
||||
in the wrong role is a different thing. The heads then score with the graph the
|
||||
resident embedder scored with, and recall degrades with no log line. The check
|
||||
cleans and absolutises both paths, then compares them with `os.SameFile`, so a
|
||||
symlinked copy is caught too.
|
||||
|
||||
### The tokenizer bug the heads found
|
||||
|
||||
`encodeWord` in `onnxembedder.go` read every long word backwards until 2026-08-08.
|
||||
|
||||
Reference in New Issue
Block a user