# TinyCortex Data-Format Parity Checklist (Phase 0.3)

**Status (2026-07-22):** The engine cutover and crate test port are complete.
The proposed pre-migration golden-fixture generator and differential
comparators 2–4 are deliberately **descoped**: there is no trustworthy
pre-cutover binary/fixture left to generate them from after cutover. Retained
gates are the security-critical `MemoryTaint` byte/serde pins, deterministic
chunk IDs, vector encoding/signature, content paths, schema composition,
idempotent reopen, and the host public-surface E2E suites.

**Purpose.** Existing user workspaces must open **unchanged** after every cutover flip.
This checklist enumerates every on-disk format shared between the host engine and TinyCortex,
records the audit result, and specifies the **golden-workspace parity harness** that gates W3, W5, W6.

**Hard rule (plan §0.3/§6):** any mismatch is fixed **upstream in tinycortex**, never papered over
with a host shim.

Anchors: historical audit host `7850cf363` · crate `d1a8c7be`; consolidation
base host `5b8a9f269` · reviewed crate `daaaf6ba` · migration branch `7b4b115`.

## Ownership tiers in the shared workspace (key finding)

A user workspace's `chunks.db` (and content vault) holds **two tiers**:

1. **Crate-owned substrate** — moves to TinyCortex, schema must match byte-for-byte:
   `vectors`, `kv_global`, `kv_namespace`, `store_meta`, `legacy_marker`, `mcp_writes`,
   `mem_tree_chunks`, `mem_tree_chunk_embeddings`, `mem_tree_chunk_reembed_skipped`,
   `mem_tree_summaries`, `mem_tree_summary_embeddings`, `mem_tree_summary_reembed_skipped`,
   `mem_tree_buffers`, `mem_tree_trees`, `mem_tree_score`, `mem_tree_entity_index`,
   `mem_tree_entity_edges`, `mem_tree_entity_hotness`, `mem_tree_ingested_sources`,
   `mem_tree_jobs` **(20 tables — exact name parity confirmed)**.

2. **Host-retained `UnifiedMemory` namespace-document tier** — stays host (the "namespace
   document/graph store" plan §1 keeps host), coexisting in the **same** DB file:
   `memory_docs`, `graph_global`, `graph_namespace`, `episodic_log` (+ `episodic_fts` virtual +
   `episodic_ai/ad/au` triggers), `event_log` (+ `event_fts` + `event_embeddings` +
   `event_ai/ad/au` triggers), `conversation_segments`, `segment_embeddings`, `vector_chunks`,
   `user_profile` **(10 tables + FTS + triggers)**.

   These live in `src/openhuman/memory_store/namespace_store/{init,fts5,events,segments,profile}.rs`.
   **The host continues creating/reading these in the same DB the crate now manages** —
   the crate's `chunks::with_connection` opens the shared handle; host `UnifiedMemory` schema
   init runs alongside the crate's. Parity requirement: crate schema init and host namespace-store
   init must **compose without collision** on both fresh and existing DBs.

## Parity results by format dimension

| # | Format | Result | Evidence |
| --- | --- | --- | --- |
| P1 | **Deterministic chunk ID** | ✅ **IDENTICAL** | `chunk_id()` = SHA-256 over `source_kind.as_str()` `\0` `source_id` `\0` `seq_in_source.to_be_bytes()` `\0` `content`, first 32 hex chars. Host `memory_store/chunks/types.rs:269` vs crate `chunks/types.rs:282` — byte-for-byte identical. |
| P2 | **Vector encoding (packed f32)** | ✅ **IDENTICAL** | `vec_to_bytes`: little-endian `f32::to_le_bytes`, 4 bytes/elem, no header. Host `vectors/store.rs:467` vs crate `store/vectors/store.rs:397` — identical. |
| P3 | **`vectors` table schema** | ✅ **IDENTICAL** | `(id TEXT, namespace TEXT, text TEXT, embedding BLOB, metadata TEXT DEFAULT '{}', created_at REAL, updated_at REAL, PRIMARY KEY(namespace,id))` + `idx_vectors_ns`. Identical. |
| P4 | **`mem_tree_jobs` (queue) columns** | ✅ **MATCH** | Both persist `(id, kind, payload_json, dedupe_key, status, attempts, max_attempts, available_at_ms, locked_until_ms, last_error, created_at_ms, started_at_ms, completed_at_ms)` (identical INSERT column list). Job **payload_json** shapes must also match — verify per `JobKind` in harness (P9). |
| P5 | **`mem_tree_chunks` base columns** | ✅ **MATCH (base)** ⚠️ **new-DB divergence** | Base 15 columns identical (`id…chunk_id`). **Divergence:** crate's `CREATE` inlines 3 legacy embedding columns (`model_signature TEXT, vector BLOB, dim INTEGER`) that the host **dropped** after migrating inline embeddings to the `mem_tree_chunk_embeddings` sidecar (host `chunks/store.rs:110` comment, #1574). **Existing DBs: compatible** — both run `CREATE TABLE IF NOT EXISTS` (no-op on existing) + `migrate_legacy_embeddings_to_sidecar` (crate `chunks/migrations.rs:23`). **Fresh DBs: crate adds 3 unused columns.** Risk: positional `INSERT`/`SELECT *`. **Action: harness asserts fresh-DB schema equality; if the 3 cols matter, drop them upstream.** |
| P6 | **Content vault paths** | ✅ **IDENTICAL sig** ⚠️ verify `sanitize_filename` | `chunk_rel_path(source_kind, source_id, chunk_id)` and `summary_rel_path(tree_kind, scope_slug, level, summary_id)` — identical signatures, same per-`source_kind` branching (`email` special-case). Host sanitizes chunk-id colons → `-` (`content/paths.rs:284`); crate uses `sanitize_filename` (`paths.rs:179`). **Action: harness asserts identical relative paths for a corpus of colon/unicode/long chunk-ids** (Windows-illegal chars are the risk). |
| P7 | **YAML frontmatter** | ✅ **MATCH** (verify key order) | Summary markdown frontmatter delimited by `---\n … ---\n` (crate `content/compose/summary.rs:76,127`; `split_front_matter` on `rposition(line=="---")`). **Action: harness asserts identical frontmatter key set + order + serialization** for chunk & summary markdown (byte-compare composed files). |
| P8 | **Entity markdown** | ⏳ harness | `entities/` registry markdown. Host `memory_entities` (0 external refs) ↔ crate `entities/`. Low risk (full port, no drift). Harness byte-compares entity files. |
| P9 | **Git diff-ledger layout** | ✅ git-backed both | Host migrated to git-backed ledger 06-25 (`040e6e20d`), captured in port (crate `diff/ledger.rs`, `diff.rs:98`). Verify `.git` repo layout + snapshot markdown + read-marker storage identical. Harness opens an existing diff repo with both. |
| P10 | **`store_meta` / embedding signature** | ✅ format | `format_embedding_signature` = `"provider={name};model={model};dims={dims}"` (crate `store/vectors/embedding.rs`). Host must produce the identical signature string from `Config` (W1 `embeddings.rs` seam) or re-embed churn triggers. **Action: seam test asserts signature string equality.** |
| P11 | **Remaining `mem_tree_*` column parity** | ⏳ harness | `mem_tree_summaries`, `mem_tree_buffers`, `mem_tree_trees`, `mem_tree_score`, `mem_tree_entity_index`, `mem_tree_entity_edges`, `mem_tree_entity_hotness`, `mem_tree_ingested_sources`, `mem_tree_chunk_embeddings`, reembed-skipped tables, `kv_*`, `mcp_writes`, `legacy_marker`. Spot-checks clean; full column+index+PK diff is automated in the harness. |
| P12 | **Host-retained tier coexistence** | ⏳ W3 gate | Crate schema init + host `unified` init must both run on the shared DB without `CREATE`/index collisions. Harness opens a real workspace, runs crate init then host init (and vice-versa), asserts full `sqlite_master` superset is preserved and no data dropped. |

Legend: ✅ audited-identical · ⚠️ divergence flagged · ⏳ deferred to harness (automated per-flip).

---

## The golden-workspace parity harness (design)

The built-in parity harness is the read-side comparator that gates each risky flip. It exists at
two layers.

### Layer 1 — schema/format asserters (host-side unit tests, cheap, run every PR)

Pure-function comparators (no disk), implemented in **`src/openhuman/tinycortex/parity.rs`**
(`#[cfg(test)]`). Status ✅ = landed & green; ⏳ = pending.

- ✅ **`chunk_id_matches_historical_golden` / `chunk_id_is_sensitive_to_every_field`** — golden +
  every-field sensitivity for the deterministic `chunk_id` (covers P1). *(After W3 both resolve to the
  crate; the golden vector stays as a regression pin.)*
- ✅ **`vector_encoding_is_le_packed_f32`** — `vec_to_bytes`/`bytes_to_vec` LE-packed-f32 round-trip
  + golden bytes (P2).
- ✅ **`chunk_rel_path_host_crate_byte_parity` / `summary_rel_path_host_crate_byte_parity`** —
  adversarial id corpus (colons, all Windows-illegal chars, unicode, >255 chars, gmail participant
  slugs, malformed email; every summary-id shape × 3 tree kinds × levels) → assert host
  `chunk_rel_path`/`summary_rel_path` **byte-equal** the crate's (P6). *(Landed; verified identical.)*
- ✅ **`embedding_signature_host_crate_byte_parity`** — assert host
  `embeddings::format_embedding_signature` == crate `store::vectors::format_embedding_signature` and
  both == the golden `provider={name};model={model};dims={dims}` over a provider corpus (P10). The
  seam's own `signature()` pass-through is separately pinned in `tinycortex/embeddings.rs`.
- ⏳ **`frontmatter_parity`** — compose a fixed chunk+summary → byte-compare markdown incl.
  frontmatter key order (P7). *(Not yet landed — needs the host/crate compose types aligned.)*

### Layer 2 — golden-workspace differential harness (the flip gate)

The core mechanism from plan §0.3: **one on-disk workspace, opened by both engines, outputs compared.**

> **Status (2026-07-10).** First cut landed as **`tests/memory_golden_parity_e2e.rs`** —
> comparator **1** (schema composition) and comparator **5** (idempotent re-open) are green:
> a real workspace is stood up through the host production surface (`memory::ops`), the crate
> substrate init is forced deterministically, and **all `*.db` files under the workspace are scanned
> path-agnostically** (union of tables). It asserts the crate chunk-DB substrate (15 `chunks/schema.rs`
> tables) and the host `UnifiedMemory` tier (10 tables) **coexist without collision** (P3/P5/P11/P12),
> and that re-running the flow adds/drops no tables (comparator 5). Still TODO: `vectors`/`store_meta`/
> `kv_*` (created by the chunk/embed pipeline, need a widened ingest flow), the seeded golden fixture +
> Comparators **2** (recall/retrieval snapshot), **3** (tree read), and **4**
> (byte-compare vault) were never landed before cutover and are now descoped by
> the decision above. Comparator 1 (schema composition) and comparator 5
> (idempotent reopen) remain active.

**Fixture decision.** Do not synthesize a fixture and label it “pre-migration”
after the fact. Compatibility is guarded by the retained format pins, schema
composition/idempotency test, and real host E2E fixtures. A future format
migration may add a versioned fixture captured before that migration starts.

**Comparators (read-only, both engines open the SAME copied workspace):**

1. **Schema snapshot** — dump `sqlite_master` (tables, indexes, triggers, `sql` text normalized) from
   the DB after each engine's `open`/init; assert the crate-owned 20-table set is identical and the
   host-retained 10-table tier is untouched (P3–P5, P11, P12).
2. **Recall/retrieval snapshot** — run a fixed query battery through the stable public surface
   (`openhuman::memory::` recall + `read_rpc` retrieval primitives) on pre- and post-migration builds;
   assert identical ordered hit ids + scores (within f64 epsilon) + `supporting_relations` (guards G2)
   + taint (guards the security seam).
3. **Tree read snapshot** — `read_tree` / `drill_down` / `cover_window` over the sealed tree; assert
   identical node structure + summary content.
4. **Byte-compare vault** — after a read-only open, assert **no content files changed** (a flip must
   not rewrite the vault) and, for a controlled re-ingest of one source, assert composed markdown is
   byte-identical.
5. **Idempotent re-open** — open → close → open with the post-migration build; assert no migration
   churn (no re-embed storm, no schema rewrite) on an already-current DB.

**Wiring.** Runs under `pnpm test:rust` (host-side, counts toward coverage) and as a dedicated
`tests/memory_golden_parity_e2e.rs`. The existing crate-level integration tests
(`tests/memory_roundtrip_e2e.rs`,
`tests/raw_coverage/memory_tree_sync_deep_raw_coverage_e2e.rs`) act as the
"public-surface still green" guard (plan §5.1); this harness adds the **differential** guard that a
flip preserves *existing* data, not just that the API still functions.

**Gate mapping:** Layer-1 asserters run every PR. Layer-2 golden harness is **green-before-merge** on
**W3** (store+chunks), **W5** (tree+retrieval+score), **W6** (ingest). W4 (queue) additionally asserts
job payload_json parity (P4/P9). Any red = upstream fix in tinycortex, re-bump submodule, re-run.

**W-SYNC gates (amendment 2026-07-09, plan §8):**
- **P13 sync-status parity** — `memory_sync_status_list` output (per-`source_kind` freshness rows)
  byte-equal pre/post flip on a golden workspace; asserter added to
  `src/openhuman/tinycortex/parity.rs`.
- **P14 Composio sync test pair** — the crate's mocked-HTTP provider suite
  (`vendor/tinycortex/tests/composio_sync_mock.rs`, wiremock, always-on) covers Gmail, Slack,
  GitHub, Notion, Linear, and ClickUp, including pagination/cursors, request budgets, retries,
  taint, idempotency, proxied envelopes, and secret redaction. The live `#[ignore]` test
  (`composio_sync_live.rs`, `COMPOSIO_API_KEY`) remains the manual direct-mode smoke gate.

### W8 test-ownership audit (2026-07-13)

Engine tests now run at their ownership boundary rather than through OpenHuman re-export shims:

- TinyCortex owns memory value/chunk/tree/queue/scoring behavior and the Composio sync pipelines.
  Duplicate engine assertions were removed from the pure `chunks::types`, `trees::types`,
  queue-backfill flag, retrieval-weight, and score re-export shims.
- OpenHuman retains tests that cross a product boundary: config and credential mapping,
  `SkillDocSink` persistence, event-bus subscribers, RPC envelopes, provider profile/task/catalog
  surfaces, agent-tool response post-processing, source registry side effects, and the
  security-critical `MemoryTaint` seam.
- OpenHuman CI now runs `cargo test --manifest-path vendor/tinycortex/Cargo.toml --features
  git-diff,sync,persona` when the submodule pointer changes and in the reusable full Rust suite. This is
  required because Cargo does not run dependency test targets while testing `openhuman`.

The focused local verification commands are:

```bash
cargo test --manifest-path vendor/tinycortex/Cargo.toml --features git-diff,sync,persona
cargo test --test raw_coverage_all memory_sync -- --test-threads=1
cargo test --test memory_sync_pipeline_e2e --test memory_artifacts_e2e \
  --test memory_golden_parity_e2e --test memory_roundtrip_e2e --test memory_sources_e2e
cargo test --test json_rpc_e2e json_rpc_memory
```

**W-EMB gate:** the existing **P10 `embedding_signature_parity`** asserter is the regression pin —
the tinyagents-backed provider stack must emit byte-identical
`provider={name};model={model};dims={dims}` signatures, or existing vector spaces split.

## Open divergences to resolve upstream before their flip

| Item | Flip gated | Resolution |
| --- | --- | --- |
| P5 `mem_tree_chunks` 3 legacy inline columns (fresh-DB) | W3 | Confirm no positional `INSERT`/`SELECT *`; if the columns are dead, drop them in a tinycortex PR so fresh DBs match. |
| P6 `sanitize_filename` vs host colon→`-` | W3 | Prove identical output on adversarial id corpus; align upstream if any diverge (Windows-illegal chars). |
| P7 frontmatter key **order** | W5/W6 | Byte-compare composed markdown; align serializer order upstream if diff. |
| G2 `supporting_relations` (graph_* host-retained vs crate derive-on-read) | W6/W7 | Recall snapshot (comparator 2) must match; else upstream relation persist. |

All other dimensions (P1–P4, P8–P12) audited compatible or covered by the automated harness.
