# ONNX aggregate gate lifecycle — 2026-08-13

Vikunja: V-716.

## Finding

`router.NewONNXEmbedder` initialized `onnxruntime_go` unconditionally. Its
`Close` method destroyed the model session but left the package-global runtime
environment alive. In one Go process the first `TestONNX*` therefore ran and
every later constructor returned `The onnxruntime has already been initialized`.
Those tests converted the constructor error into `t.Skip`, so the aggregate
package still reported `PASS`.

Reproduction before the fix:

```text
TestONNXBaseline     PASS  classifier+onnx 72/96
TestONNXRoutingHeads SKIP  onnx: init environment: already initialized
package              PASS
```

## Contract

The router now owns ONNX Runtime through reference-counted leases. Every model
session holds one lease; routing heads hold their own, so daemon shutdown order
cannot unload the library underneath a live graph. The last lease destroys an
environment Maven initialized. Package `TestMain` holds one extra lease across
all model-aware tests in `internal/router/eval` and `cmd/mavend`.

The aggregate router command additionally requires two named gates to record
execution only after all of their model dependencies loaded. A second-test
skip can no longer satisfy the command.

## Measurement

Runtime and model:

```text
deps/onnxruntime-linux-x64-1.26.0/lib/libonnxruntime.so.1.26.0
models/embedder/multilingual-e5-small/model_quantized.onnx
models/embedder/router-heads/router_heads.onnx
```

Focused aggregate, one process:

```text
TestONNXBaseline     PASS  72/96 full (75.0%), destination 11/33
TestONNXRoutingHeads PASS  93/96 full (96.9%), destination 25/33
ONNX aggregate proof: verified 2 required model gates:
  [TestONNXBaseline TestONNXRoutingHeads]
```

The separate lifecycle test released the last lease and successfully acquired
the runtime again. A second same-process package run also executed all three
selected mavend gates without a skip:

```text
TestONNXPersonalBoundary         PASS  29/29
TestONNXPersonalBoundaryFourFold PASS  99/104
TestONNXTopics                   PASS  43/43
```

Finally, `make eval-router` completed the full package. In addition to the two
required proof gates, `TestONNXClaimConfidenceDistribution` and
`TestReachBaselineONNX` executed; ecosystem reach remained 28/30.
