Skip to content

v0.16.0 — synthesis lifecycle, provenance, and the embedder-identity gate

Choose a tag to compare

@spranab spranab released this 22 Aug 20:42
· 40 commits to main since this release
385de30

Behavior change: embedder identity is now checked (#117, #138)

Attaching an embedder whose declared fingerprint/digest contradicts the
store's recorded identity now raises instead of silently accepting. Measured
motivation: cosine distance between two unrelated embedding spaces still
returns a plausible number (0.595 in the incident that drove this) — results
look fine and are wrong. set_embedder(..., allow_unverified_embedder=True)
is the documented escape hatch.

And the gate knows when the record itself is wrong. A real production
store carried a meta identity row claiming potion-base-2M / dim 64 while
holding 384-dim MiniLM vectors — a provably false record, stamped by an
incidental embed() long ago. 0.16.0 refuses to brick such databases: when
the recorded dimension contradicts the width of the vectors actually stored,
the row is treated as evidence of nothing — the engine attaches, warns loudly
naming both dimensions, and adopt_embedder_identity ships as the honest
repair path (derive the digest by re-embedding stored text; never assert it).
"Cannot verify" and "verified mismatch" are distinct states; collapsing them
was the bug.

Synthesis lifecycle (schema v43 → v46)

Typed synthesis columns, the synthesis_dependencies table, evidence-versioned
lifecycle state, and the rollup-impression ledger with outcome finalization.
Migrations are idempotent and were verified on a copy of a live 5,751-row
production store before any deploy (43 → 46 clean, integrity ok).

Diagnosability: a failing open names its stage (#146, #147)

Every SQL call in the constructor is stage-tagged; the migration runner
attaches the exact statement it choked on. A truncated-SQL error that
previously read database error: incomplete input — naming nothing — now
reads database error at <stage>: ....

Fixes

  • search_entities clamp panic when limit > 10_000
  • Source filters now genuinely filter: recall no longer returns assistant
    turns under source=user (behavior change for callers who depended on it)
  • Version declarations unified across all four manifests, with a test so the
    wheel version can never again depend on which directory built it
  • recall_candidate_cap telemetry: the engine reports when a cap bounded a
    result rather than silently narrowing it

Verification

Dogfooded before tagging: deployed to a live production store (5,751 rows),
verify-on-copy first, schema 43 → 46 via lazy migration, integrity ok, reads
and writes exercised through the MCP surface. Six consecutive full-suite CI
runs with the new instrumentation, zero anomalies. Clean-venv wheel
verification: 48 Python files, all gate markers present by content, 13/13
identity-gate tests against the installed artifact.

Co-developed by Claude and Codex working as adversarial reviewers of each
other's changes; the embedder-gate fix in this release was reshaped twice by
that review loop before it shipped.