# ONNX vendor-capture immunity — why the engine is not a trust dependency

**What this is:** the rationale for why arborist is *structurally*
immune to ONNX-format and ONNX-Runtime vendor capture — and why that
immunity was a free side-effect of a discipline adopted for honesty,
not for procurement reasons. Not a ticket; a positioning/architecture
reference. Public-domain intellectual capital: the argument is
reproducible and inheritable by any fork or downstream client that
keeps the same cage. The headline: **arborist puts zero neural
inference in its proof path, so whichever vendor owns the inference
engine owns none of arborist's trust boundary.**

---

## 1. The capture vector, stated honestly

ONNX is an open model-exchange format; ONNX Runtime (ORT) is its
dominant engine. Both are governed and overwhelmingly resourced by
Microsoft. The systems-programming critique that motivated this note
(ORT's ~2,500-line, many-flag, many-execution-provider build) is real,
but it is the *small* version of the risk. The large version is the
trust one:

> Any system that places a neural model — its embedder, its NLI head,
> its reranker, its LLM — *inside* the chain of custody for its
> answers inherits that model's runtime, and therefore that runtime's
> vendor. The vendor's roadmap, deprecation policy, license drift,
> build complexity, and execution-provider politics all become load-
> bearing for *your* correctness guarantee.

This is the same defect class as a logged secret or a leaked context:
a dependency that should have stayed at the edge has reached into the
core. The fix is not "pick a better engine." The fix is **not putting
the engine in the core at all.**

## 2. Where models are, and are not, in arborist

| layer | what runs there | model? | vendor-exposed? |
|---|---|---|---|
| Merkle commit (`merkle.py`) | SHA-256, fixed combine conventions | no | no |
| Content store / cache key (`store.py`, `qa/keys.py`) | canonical encodings, 8-dim key | no | no |
| Verifier (`qa/verify.py`) | byte-identical lexical matching (quote / span / entity / paraphrase) | **no** | **no** |
| Audit chain (`audit_events`) | `sha256(prev ‖ canonical(body))` | no | no |
| NLI shadow (`qa/nli/shadow.py`) | entailment contradiction veto | yes | yes — but **sidecar** |
| Relevance shadow (`qa/relevance/shadow.py`) | cross-encoder aboutness | yes | yes — but **sidecar** |
| MT edges (`qa/mt/translator.py`) | opus-mt query/display translation | yes | yes — but **display-only** |

Everything above the rule is the proof path: deterministic, hash-
anchored, model-free, reproducible from `python + sqlite3` alone.
Everything below is a sidecar that is **demote-only, never an
`audit_mode` input, never writes `providence_cache` / `audit_events` /
`run_dag_root`** (the #000049 model-in-proof-path cage; the
verifier-stays-binary and "no soft signal in the hard chain" rules in
CLAUDE.md). A model in arborist can only ever *lower* confidence as an
advisory signal — it can never mint, promote, or sign a result.

## 3. The immunity, precisely

Because no model output is an input to any commitment, proof, cache
key, or audit row:

- **The inference engine is interchangeable.** arborist already swaps
  it silently: `qa/nli/shadow.py` prefers an `optimum.onnxruntime`
  int8 graph if one exists, picks `CUDAExecutionProvider` /
  `CPUExecutionProvider`, and **falls through to the plain
  `transformers` + `torch` path on any failure** — with no effect on
  any hash. ORT is an *accelerator*, not an authority.
- **A hostile vendor pivot is bounded and cheap.** If Microsoft
  deprecated ORT, relicensed it, fragmented the ONNX opset, or its
  build complexity became untenable, the blast radius is: re-export
  the *pinned* checkpoint to whatever engine survives (torch always
  works; tinygrad's ONNX frontend is a candidate — #000049 §7). The
  checkpoint is already version-pinned in the NLI manifest; nothing
  in the proof path observes the swap. Cost is hours of producer-box
  work, not a correctness migration.
- **Cache validity is engine-independent.** A record's
  `falsification_state` and `audit_mode` were decided by the
  deterministic verifier. Re-running tomorrow on a different engine
  cannot change a prior STRICT/HYBRID/UNGROUNDED verdict, because the
  engine never produced it. (Contrast: a system whose answer is
  graded by an LLM must re-grade — and silently re-trust — on every
  model or runtime change.)

The one place a model could ever touch authority is the deliberately-
unwired Phase-3 demotion hook in #000049. Even there the design
forces the exposure to be *named*: if NLI is ever allowed to demote
`audit_mode`, `nli_policy_hash` (model + k + agg + guard + θ) folds
into `governance_policy_hash`, so the model's identity becomes a
first-class, cache-partitioning, audited policy input — capture made
visible and versioned, never silent.

## 4. This was free — and that is the point

We did not design the cage to dodge Microsoft. We designed it because
a model in the proof path is a honesty defect: a false-positive STRICT
is corruption, and a model that can promote will eventually hallucinate
a promotion. The deletion-first guardrails (delete the part: the model
does not get to be in the hard chain) were adopted for *truth*.

Vendor-capture immunity fell out for free. That is the recurring shape
of the right architectural call: a discipline taken for one good
reason pays a second, unbid dividend. A system built to never lie about
grounding turns out to also be a system no inference-engine vendor can
hold hostage.

## 5. Why this is published intellectual capital

Per the Prime Mission, this argument is a gift to the ecosystem, not a
moat. Any RAG / retrieval / agent system can adopt the same split:
deterministic verifier in the proof path, models as demote-only
sidecars on a producer box, engine identity versioned into a policy
hash only if it is ever allowed to touch authority. A fork that keeps
the cage inherits the immunity verbatim — no license, no dependency,
no permission required. The cage *is* the gift.

See also: `docs/lexical-first-rationale.md` (the cost-asymmetry
sibling — why the cheap deterministic path is the default),
`docs/soft-hash-channel-analysis.md` (soft-vs-hard channel threat
model), and ticket #000049 §7 (the NLI cage, shadow path, and the
tinygrad/ORT engine-swap bench).
