Context
The premise review of PR #15643 established that normal restore preserves stored vectors; it does not need an embedding-provider write canary. That correction exposes the actual restore precondition: the bundle's vectors must be complete and compatible with the destination collection before any destructive mutation.
Source inspection on dev shows that bundle-meta.json currently records bundle version, subsystem receipts, integrity, topology, and Neo version (ai/scripts/maintenance/backup.mjs:243-251) but no embedding contract. Both vector importers could truncate in replace mode before every row had been parsed and validated.
Truth-fold (post-review, two cycles): the original "hard model/strategy fingerprint incompatibility" premise is retired. No persisted write-time record of which provider/model embedded the stored rows exists in the substrate, so a backup-time config snapshot can never be presented as producer provenance, and a config-vs-config comparison must never hard-refuse a restore. Hard gates bind only to evidence the bundle itself proves; semantic-space provenance is classified as structured advisory residue for the orchestrator.
The Problem
A syntactically valid bundle can still contain a missing, non-finite, or wrong-dimension vector. Before this work, the restore driver could not compare the bundle's row-verifiable facts with the destination before mutation, and a late-row parse/vector failure could arrive after a replace-mode truncate. Provider readiness is not a substitute: a healthy provider neither proves that preserved vectors are compatible nor authorizes re-embedding.
The Architectural Reality
- Backup metadata is owned by
ai/scripts/maintenance/backup.mjs.
- Bundle admission is owned by
ai/scripts/maintenance/restore.mjs plus the importing DatabaseService boundaries.
- Row-verifiable facts (parseability, required IDs, vector presence/finiteness/dimension, exported counts) are the only hard-gate evidence a bundle carries.
- Semantic provenance (which provider/model produced the stored vectors) is unknown by construction until write-time provenance exists; restore admission classifies it, never asserts it.
- ADR 0025 keeps probes as evidence, never authority. ADR 0027 keeps re-embedding as an orchestrator-selected data-recovery action; restore admission must not trigger it implicitly.
The Fix
- Extend
bundle-meta.json with a versioned embedding block: schema version, vector dimension, per-actual-vector-collection exported counts (KB chunks, Memory Core memories, summaries — never null, never aggregate), and an explicitly advisory expectedConsumer (the backup host's active provider/model at backup time — expectation context, not producer evidence).
- A provider-free restore preflight streaming-validates every JSONL row (parseability, required ID, vector presence, finite values, expected dimension) and every declared count against the streamed totals, in both directions.
- Complete that preflight — and a full-source proof on every direct DatabaseService replace path — before any truncate or live collection write. Replace is all-or-nothing.
- Classify semantic provenance as structured advisories (
semantic-provenance-unverified always; consumer-expectation-mismatch additive on divergence) attached to the validation receipt and carried through the self-diagnostic probe. Never a hard refusal from config comparison, never a provider call.
- Keep re-embedding outside restore admission. If recovery needs new vectors, diagnostics/classification must select the ADR-0027 re-embed action.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
bundle-meta.json embedding block |
Backup orchestrator + export receipts |
Versioned dimension + per-collection non-null counts + advisory expectedConsumer |
Legacy metadata classifies semantic-provenance-unverified, never fabricated |
Backup/restore JSDoc |
Contract-shape specs |
validateBundle() / restore admission |
Restore driver |
Full streaming structural + vector validation + declared-vs-streamed count check before mutation |
Fail closed with a classified violation receipt; advisories ride the return |
Restore CLI help/JSDoc |
Corrupt-last-row, missing-ID, dimension, count, schema specs |
| DatabaseService import boundaries |
Full-source proof + per-batch vector invariant |
Accept only prevalidated compatible explicit vectors; replace is all-or-nothing |
Reject; zero truncate, zero writes |
Import JSDoc |
Corrupt-final-row zero-truncate/zero-write witnesses (KB + MC) |
| Advisory classification receipt |
meta.embeddingAdvisories + probe result |
Structured unknown-provenance baseline + optional mismatch, consumed by the orchestrator |
Log-only is never the sole channel |
JSDoc |
Advisory-shape specs (match, mismatch, legacy) |
Decision Record impact
Aligned-with ADR 0025 and ADR 0027. This adds evidence and admission checks; it does not grant probes action authority or move re-embedding out of orchestrator control.
Acceptance Criteria
Out of Scope
- Performing or scheduling re-embedding
- Choosing an autonomous recovery action
- Off-host bundle transport
- Write-time producer-provenance persistence (a separate future substrate; until it exists, provenance stays classified-unknown)
Avoided Traps
- Provider canary as compatibility proof — it proves neither vector completeness nor embedding-space identity.
- Validate while mutating — a late error after truncate is already data loss.
- Config snapshot as producer provenance — current config names the expected consumer, never which model embedded the stored rows.
Related
- #15639
- #15689
- PR #15690
- #11150 (closed production-scale restore hardening; did not add this contract)
- #15692 (bounded streaming importer), #15693 (orchestrator recovery receipt — the advisory consumer)
Live latest-open sweep: checked the latest 20 open issues at 2026-07-22T09:43:14Z; no equivalent found.
A2A in-flight claim sweep: checked the latest 30 messages across all read states immediately before creation; no overlapping lane claim found.
Origin Session ID: cb60301d-74a4-4024-b80d-2f7efdbf9cd1
Retrieval Hint: "restore bundle embedding compatibility metadata preflight before truncate preserved vectors"
Context
The premise review of PR
#15643established that normal restore preserves stored vectors; it does not need an embedding-provider write canary. That correction exposes the actual restore precondition: the bundle's vectors must be complete and compatible with the destination collection before any destructive mutation.Source inspection on
devshows thatbundle-meta.jsoncurrently records bundle version, subsystem receipts, integrity, topology, and Neo version (ai/scripts/maintenance/backup.mjs:243-251) but no embedding contract. Both vector importers could truncate in replace mode before every row had been parsed and validated.Truth-fold (post-review, two cycles): the original "hard model/strategy fingerprint incompatibility" premise is retired. No persisted write-time record of which provider/model embedded the stored rows exists in the substrate, so a backup-time config snapshot can never be presented as producer provenance, and a config-vs-config comparison must never hard-refuse a restore. Hard gates bind only to evidence the bundle itself proves; semantic-space provenance is classified as structured advisory residue for the orchestrator.
The Problem
A syntactically valid bundle can still contain a missing, non-finite, or wrong-dimension vector. Before this work, the restore driver could not compare the bundle's row-verifiable facts with the destination before mutation, and a late-row parse/vector failure could arrive after a replace-mode truncate. Provider readiness is not a substitute: a healthy provider neither proves that preserved vectors are compatible nor authorizes re-embedding.
The Architectural Reality
ai/scripts/maintenance/backup.mjs.ai/scripts/maintenance/restore.mjsplus the importing DatabaseService boundaries.The Fix
bundle-meta.jsonwith a versioned embedding block: schema version, vector dimension, per-actual-vector-collection exported counts (KB chunks, Memory Core memories, summaries — never null, never aggregate), and an explicitly advisoryexpectedConsumer(the backup host's active provider/model at backup time — expectation context, not producer evidence).semantic-provenance-unverifiedalways;consumer-expectation-mismatchadditive on divergence) attached to the validation receipt and carried through the self-diagnostic probe. Never a hard refusal from config comparison, never a provider call.Contract Ledger Matrix
bundle-meta.jsonembedding blocksemantic-provenance-unverified, never fabricatedvalidateBundle()/ restore admissionmeta.embeddingAdvisories+ probe resultDecision Record impact
Aligned-with ADR 0025 and ADR 0027. This adds evidence and admission checks; it does not grant probes action authority or move re-embedding out of orchestrator control.
Acceptance Criteria
semantic-provenance-unverifiedin all cases (match included); mismatch addsconsumer-expectation-mismatch; advisories ride the validation receipt and the self-diagnostic probe resultOut of Scope
Avoided Traps
Related
Origin Session ID: cb60301d-74a4-4024-b80d-2f7efdbf9cd1
Retrieval Hint: "restore bundle embedding compatibility metadata preflight before truncate preserved vectors"