ADR-038: Ship v1.0 on ort 2.0.0-rc.12 with a tracked exit
Date: 2026-06-20 Status: Accepted Author: Rômulo Febasi
Scopes SYN-276 (#264). Companion to ADR-008 (embeddings/NER backend). The v1.0 milestone freezes the Synapse surface (schema / CLI / MCP); this ADR states what that “stable” claim does and does not cover for the transitive on-device inference stack.
Context
Synapse’s on-device embedding + NER runs on ONNX Runtime via the ort crate,
pinned to =2.0.0-rc.12 (a release candidate). This pin is transitive
and forced, not a free choice (Cargo.toml §inference, lines ~186-189):
fastembed 5.15(the embedding backend) pinsort = "=2.0.0-rc.12"exactly.- canonical
gline-rs(the NER crate) pinsort = "=2.0.0-rc.9", which conflicts; thekreuzberg-gliner-rsfork re-pins to rc.12 to align.
So the whole inference stack sits on rc.12, and ort cannot be moved to a final
release until both fastembed and the NER fork move first: Synapse cannot
unilaterally bump it. The stack is built, tested, and working on rc.12 (373 lib
tests green; cargo deny check clean: no advisory blocks it).
Tagging a release branded “stable” (v1.0) on an RC dependency is a real maturity question that should be decided explicitly rather than left as an undocumented pin.
Decision
Ship v1.0 on ort = 2.0.0-rc.12 (Option A), with a tracked exit.
- The v1.0 “stable” promise covers the Synapse public surface: the Markdown/frontmatter schema, the CLI, and the MCP tool surface: under semver (BR-11.2). It does not assert that the transitive ONNX Runtime is a final release; that is a documented caveat, not a broken promise.
- The exit criterion: when
fastembed(andkreuzberg-gliner-rs) publish versions depending onort 2.0.0final, adopt it in a 1.0.x patch: bump the three together, runcargo build --release --all-features && cargo test --all-features && cargo deny check, re-runsynapse-benchto confirm no embedding/NER regression, and ship. Until then, no action (the pin cannot move). - Do not bump
Cargo.toml/Cargo.lockspeculatively: a partial bump that desyncs fastembed and the NER fork breaks the build.
Consequences
- Improves: an honest, written posture instead of a silent RC pin; the “stable” claim is correctly scoped to the surface semver actually governs; no premature dependency churn on the inference path.
- Worsens / limits: v1.0 ships with an RC ONNX Runtime. If
ort 2.0.0final differs from rc.12 in a way that changes embedding/NER behavior, a 1.0.x patch is needed once upstream supports it, but the semantic models download on consent and the index is disposable, so any behavior change is reproducible and re-derivable (syn embed --all/syn reindex), never silent data loss. - Open: the bump is gated on upstream (
fastembed+ the NER fork adoptingort 2.0.0final). Track it with the dependency-health cadence; this ADR is the exit criterion of record.
Alternatives considered
- Option B: wait for
ort 2.0.0final before tagging v1.0. Rejected for now: adoption is not in Synapse’s hands (it requiresfastembed+ the NER fork to move first), and blocking the v1.0 tag on an upstream release with no committed date would hold the whole milestone hostage to a transitive pin. Revisit only if upstream ships final and the bump tests clean on all targets. - Swap the inference stack to a final-release ONNX binding now. Rejected: the backend choice (fastembed + BGE-M3 + GLiNER via the fork) is settled by ADR-008; replacing it to dodge an RC is a far larger, riskier change than the RC itself warrants for a single-user local-first tool.
- Pretend the RC is irrelevant and say nothing. Rejected; that is exactly the undocumented-pin the “never fake green / honesty” discipline forbids; a “stable” release should state what its stability covers.