Skip to content
Internals — roadmap: describes planned work that may not match the current code.
Unverified: This page has not yet been anchored to automated code tests.

VoxDB Audit & Condensation — Implementation Plan

VoxDB Audit & Condensation — Implementation Plan

Section titled “VoxDB Audit & Condensation — Implementation Plan”

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Re-baseline vox-db’s schema down to the 116 tables with real callers (design §2.2), quarantine the 103 dormant/dead ones behind an opt-in Cargo feature (not delete — see design §3.2), resolve the two data-bearing exceptions and the “finished-but-unwired” subsystem clusters by hand rather than by default, and update or delete the tests that assert against now-quarantined tables (design §2.4’s own table lists 9 test functions across 7 files — local_tests.rs (3), schema/domains/history.rs, schema/mod.rs, tests/news_approval_tests.rs, tests/schema_contract_tests.rs, tests/ops_skill_tests.rs, toestub_store.rs; an earlier prose figure of “16 tests across 8 files” did not match that table and must not be used as a pass/fail target — see Task 1.2). Add a durable, re-runnable audit tool so this doesn’t silently drift back over time.

Declaration-mechanism note (Task 4 must account for this): the 219 live tables are declared through two different mechanisms, confirmed by re-querying .vox\store.db and cross-referencing every table name against source: 210 via literal CREATE TABLE DDL under crates/vox-db/src/schema/ (domain files, embedded .sql, and the DDL constants in schema/spec/mod.rs), and 4 more (provider_usage, attention_events, agent_trust_scores, handoff_payloads) via CollectionInfo entries in schema::spec::orchestrator_schema_digest(), backing schemaless tables created at runtime by crate::collection::Collection::ensure_table() rather than baseline DDL. The remaining 5 (archive_membership, chunk_members, context_window_items, context_windows, zstd_dictionaries) have no declaration anywhere in current source (confirmed via a repo-wide search, not just schema/) — they are pure leftover rows/tables from an already-removed feature. This means Task 4.1 (“move DDL to quarantine.rs”) applies as written to 99 of the 103 quarantine candidates; handoff_payloads needs its CollectionInfo entry removed/relocated instead of DDL text, and the 5 fully-orphaned tables need no schema-file change at all — only the DROP TABLE in Task 5. See design §2.1 for the full reconciliation.

Architecture: Nine sequential tasks. Task 1 makes the audit durable and re-runnable (VoxScript, not the throwaway Python used for investigation). Task 2 resolves the ambiguous cases before anything is quarantined, since those decisions change what Tasks 3-5 touch. Tasks 3-5 are the actual schema/test/migration surgery. Tasks 6-9 are cleanup, guardrails, and verification. Tasks 7-8 are opportunistic documentation-only additions that surfaced during the audit but are not part of the schema-condensation deliverable itself — they carry no dependency on Tasks 1-6 and can be dropped without affecting the rest of the plan if time is short.

  • Hard sequential spine: 0 (preflight) → 1 (census tool) → 2 (decisions) → ... → 9 (final verification). Task 0 must complete first (baseline must already be green) and Task 9 must run last (whole-workspace gates). Task 1’s outputs (table_usage_report.json, quarantine_test_findings.json) feed Task 2 directly — not parallelizable with it.
  • Task 2 is the hard gate: its outputs (the adjusted LIVE/DORMANT/DEAD split, and specifically whether history_entries, TOESTUB, Scientia, external-review, publication, MENS/training, and skill_executions stay live or get quarantined) determine which tables Tasks 3, 4, and 5 actually touch. None of 3/4/5 can start until 2.1-2.3 are resolved — their file scopes are undefined before that.
  • Task 4 → Task 5 must be sequential, not parallel: Task 5.1’s migration targets the version and table list Task 4.4 just finalized; running 5 concurrently with 4 risks targeting a BASELINE_VERSION or DROP list that hasn’t settled yet.
  • Task 3 and Task 4 are NOT safely parallel by default, despite touching “conceptually different” concerns (tests vs. DDL). schema/domains/history.rs plausibly holds both the history_entries DDL Task 4 moves and the test Task 3.3 disposes of in the same file; toestub_store.rs similarly couples Task 3.7’s test disposition to Task 4’s DDL move if the TOESTUB cluster is quarantined. Whether this collision is real depends entirely on Task 2’s decision (if history_entries stays live and TOESTUB has an active doc, there’s no overlap). Check file-overlap again after Task 2 concludes, before dispatching 3 and 4 in parallel — don’t assume disjointness from task numbering alone.
  • Task 6 touches a different crate (vox-db-types, read-mostly) and depends only on Task 2’s finalized DEAD list; it is file-disjoint from 3/4/5’s targets and can run in parallel with that cluster once Task 2 is done.
  • Tasks 7 and 8 are pure documentation, touch files unrelated to vox-db source, and depend on neither the census nor Task 2’s decisions — safe to hand off as background work at any point.
  • Steps too ambiguous for an unsupervised subagent without a clarifying question first: Task 2.1-2.3 (judgment calls that change downstream file scope), Task 3.7 (explicit “flag it rather than silently deleting” decision point), Task 8.1 (“skip rather than inventing new documentation” is itself a judgment call), Task 5.2 (must re-confirm the exact DROP list against Task 2’s final decisions before running any destructive-pattern migration test, even against a copy).

Tech Stack: Rust 2024, cargo, VoxScript (vox run), turso/SQLite, Markdown.

Spec: 2026-08-01-voxdb-audit-condensation-design.md

Authoritative ground truth (do NOT update from memory — re-read before editing):

  • crates/vox-db/src/schema/domains/*.rs (actual current DDL)
  • crates/vox-db/src/schema/manifest.rs (actual current BASELINE_VERSION)
  • crates/vox-db/Cargo.toml (actual current feature flags)
  • The design doc’s audit tables (§2.2-2.4) — but re-run Task 1’s tool rather than trusting the numbers if any schema file has changed since 2026-08-01

Project rules to honor (from CLAUDE.md / AGENTS.md):

  • Project automation MUST be .vox files via vox run, never .ps1/.sh/.py glue (Task 1).
  • archive/ and docs/src/archive/ are tombstoned — do NOT read or modify.
  • Use Edit/Write/Read/Glob/Grep tools, not cat/sed/awk/echo.
  • Auto-generated docs MUST be regenerated, never hand-edited.
  • Never cargo fmt --all on Windows — use vox run scripts/fmt.vox or cargo fmt -p vox-db.

  • Step 0.1: Confirm baseline build and tests are clean.

    Run:

    cargo build -p vox-db -p vox-db-types
    cargo test -p vox-db

    Expected: both clean. This is the reference point — if cargo test -p vox-db is already red before you start, stop and investigate that first; don’t let pre-existing failures get attributed to this work.

  • Step 0.2: Read the spec end-to-end. docs/src/architecture/2026-08-01-voxdb-audit-condensation-design.md, especially §2.3 (the two data-bearing exceptions) and §2.4 (the affected tests — read the table itself, not the “16 across 8” prose line above it; the table lists 9 functions across 7 files and is the one Task 1.2 must reproduce) before touching any code.


Task 1: Build the durable VoxScript audit tool

Section titled “Task 1: Build the durable VoxScript audit tool”

Why first: everything downstream depends on an accurate, re-runnable table census. The design doc’s numbers came from a one-off Python scratchpad script (not committed, not re-runnable by anyone else) — this task turns that into the real tool referenced by design §3.6, so the plan isn’t executing against a snapshot that may have already drifted.

  • 1.1a (RED, write first): Before writing any classification logic, create a small fixture set — a handful of throwaway .rs files (or an in-repo tests/fixtures/db_table_census/ directory) containing a few CREATE TABLE statements with known-correct LIVE/DORMANT/DEAD outcomes (e.g. one table referenced from a fixture file outside vox-db, one referenced only inside vox-db, one referenced nowhere). Write the test that asserts the classifier sorts these correctly, and run it — it must fail (no script exists yet). This is the driving test for 1.1, not a nice-to-have.

  • 1.1: Write scripts/db-table-census.vox. Port the classification logic from the investigation (walk .rs files under crates/, apps/, server/, tools/, tests/, examples/, scripts/, ci/; regex-match table names from sqlite_master against file contents; exclude codex_legacy.rs, circuit_breaker.rs, schema/manifest.rs from the “usage” signal per design §2.2 — document this exclusion list inline in the script with a comment explaining why each file is excluded, since it’s a hardcoded, non-structural signal that a future file of the same shape won’t automatically inherit; classify LIVE/DORMANT/DEAD by whether references exist outside vs. only inside vox-db/vox-db-types). Output: graphify-out/table_usage_report.json (table, rows, status, referencing files) plus a human-readable summary printed to stdout. Sensitive-table handling: for tables whose name matches a secrets/identity pattern (at minimum clavis_account_secrets, user_identities — grep the domain files for other candidates before finalizing the list), emit status and referencing-file-count only, never row content, and flag them in the summary as “sensitive — do not auto-quarantine without manual review” regardless of their computed LIVE/DORMANT/DEAD status (see Task 2.4 below). Make 1.1a’s fixture test pass (GREEN) before moving on.

    Run: vox run scripts/db-table-census.vox -- --db .vox/store.db

    Expected: 1.1a’s fixture test passes. Against the live workspace, this tool’s output is the authoritative count for Task 2 — it should closely match design §2.2’s 219/116/82/21 (confirmed by direct query against .vox\store.db and full cross-reference at the time the design doc was written), but treat any small drift as real workspace change since then, not a known reconciliation gap; a large drift (more than a handful of tables) means something about the classification logic itself needs re-checking before trusting it.

  • 1.2a (RED, write first): Create a synthetic fixture — a couple of fake #[test] functions in a throwaway file that reference known DEAD/DORMANT table names (from 1.1’s fixture, not the real schema) — with an asserted expected extraction (which functions, which files). Run it before the scanner exists; it must fail.

  • 1.2: Write scripts/db-test-census.vox. Same idea for design §2.4 — scan #[test]/#[tokio::test] function bodies for references to tables classified DEAD/DORMANT by 1.1’s output. Output: graphify-out/quarantine_test_findings.json. Make 1.2a’s fixture test pass (GREEN).

    Run: vox run scripts/db-test-census.vox

    Expected: 1.2a’s fixture test passes. Against the live workspace, cross-check the output against design §2.4’s table (9 functions / 7 files, not the doc’s “16 across 8” prose figure — see the Goal section above) as a sanity check, but the tool’s own output — not the design doc’s table — is what Task 3 actually works from, since the tool may find things the manual audit missed or vice versa.

  • 1.3: Commit both scripts and their outputs. These become the recurrence-prevention mechanism (design §3.6) — a future CI hook or periodic check can diff against graphify-out/table_usage_report.json to catch new tables added without a caller. Before committing table_usage_report.json and quarantine_test_findings.json, confirm they contain no row content for clavis_account_secrets/user_identities-class tables (status/counts only, per 1.1’s sensitive-table handling) — this report is meant to be periodically regenerated and re-committed, so this check applies every time it’s re-run, not just once. Wiring an actual CI gate is optional/future work and is not delivered by this plan — note explicitly in the commit/PR description that “recurrence prevention” currently means “a re-runnable tool exists,” not “drift is automatically caught”; nobody is yet obligated to re-run it before landing future schema changes.


Task 2: Resolve the ambiguous cases before quarantining anything

Section titled “Task 2: Resolve the ambiguous cases before quarantining anything”

Why before Tasks 3-5: whatever this task decides to keep live changes the DDL that stays in the default baseline and the tests that get UPDATE vs. left alone. Doing this first avoids quarantining something in Task 4 only to un-quarantine it in a follow-up PR.

  • 2.1: developer_journey_definitions (1 row, DEAD by code-reference). Do not start from crates/vox-db/src/codex_legacy.rs — that file is not where this row comes from. Instead read crates/vox-db/src/schema/domains/developer_journeys.rs (the CREATE TABLE DDL there carries an INSERT OR IGNORE seed row baked directly into the DDL string, which fires unconditionally every time baseline_sql() runs — i.e. on every fresh VoxDb::connect() — independent of any JSONL import path) and crates/vox-db/src/store/ops_developer_journeys.rs (confirm whether it reads developer_journey_definitions at all, or only developer_journey_steps). If confirmed to be a write-only schema-init seed with no reader anywhere: this is a distinct case from “generic incidental import residue” — treat it explicitly as a deterministic seed, not a legacy-import artifact, when writing the quarantine.rs comment (Task 4.1) and the DROP-migration exception list (Task 5.1), and proceed to quarantine as planned, excluded from the auto-DROP migration pending a one-time manual row export if the row has any value. If some real code path does read it that this re-check missed: pull it out of the DEAD list, treat as LIVE-adjacent, do not quarantine.

  • 2.2: history_entries (1 row, DORMANT, paired round-trip + schema tests). Read crates/vox-db/src/history_store.rs and both tests (local_tests.rs::history_entries_round_trip, schema/domains/history.rs::history_entries_schema_round_trip). Determine whether this is finished-but-simply-unwired functionality (recommended default: keep in the live baseline, not quarantine — a fully tested feature with real data is a poor quarantine candidate regardless of caller count) or genuinely abandoned. Record the decision and one-sentence rationale in this plan’s status callout when done.

  • 2.3: Cross-check subsystem clusters against other active-development docs. Design §2.2 enumerates 11 subsystem clusters, not 5 — check all of them, not just a subset, since an unchecked cluster is quarantined by default and a missed check is exactly how active WIP gets silently dropped: Scientia (11 tables), external review/CodeRabbit (6), Codex conversation graph (7), publication/scholarly (6), TOESTUB (4), MENS/training (4), skill ecosystem (2 — confirm against design §2.2 whether this is the same cluster as any “skill_executions”/“skill-execution” table referenced elsewhere in this plan; reconcile the naming before treating them as the same thing), news publishing (3), planning graph (3), gamification/vox-mesh trust (4), CI completion detector (2). Grep docs/src/architecture/ for recent design docs covering each (e.g. search for “scientia”, “external review”, “toestub”, “skill”, “mens”, “codex conversation”, “news publishing”, “planning graph”, “gamification”, “ci completion”). MENS/training in particular has multiple current, non-archived design docs in docs/src/architecture/ (e.g. mens-training-ssot, mens-training-pipeline-audit-and-improvement-plan, mesh-mens-distributed-training-and-execution-plan, voxmens- research/decision docs) — treat this as a strong signal the cluster is active, and confirm before quarantining any of its 4 tables.* For any cluster with an active/roadmap-status doc describing in-progress wiring, keep that cluster’s tables in the default baseline (do not quarantine) even though the code-usage census marked them DORMANT — quarantining active WIP just creates rework for whoever’s mid-flight on it. For clusters with no such doc, proceed with quarantine as planned.

    Record the final adjusted LIVE / DORMANT+DEAD split (starting point: 116/103, per Task 1.1’s confirmed output) after this step — this is the actual list Tasks 3-5 operate on, not the raw census from Task 1.

  • 2.4: Sensitive-table safeguard (independent of the code-reference census). For clavis_account_secrets, user_identities, and any other table Task 1.1 flags as sensitive: regardless of what the census computes (LIVE/DORMANT/DEAD) today or on any future re-run, require an explicit human confirmation step before such a table is ever added to a quarantine or DROP list — a mechanical “zero non-quarantine callers” signal is not sufficient on its own for tables of this kind, because a later refactor could remove their last outside-vox-db caller and let the same tooling reclassify them with no one noticing. Record this as a standing rule (e.g. a comment in scripts/db-table-census.vox and in this plan) rather than a one-time check, since Task 1’s tool is meant to be re-run indefinitely per design §3.6.


Work through the test functions from Task 1.2’s output (design §2.4’s table: 9 functions across 7 files — see the Goal-section note above; do not target “16 across 8”), using Task 2’s decisions to determine which tables are actually leaving the baseline.

Sequencing note (applies to every subtask below): editing an assertion list before Task 4 has removed any DDL is a no-op change from the test’s perspective — the quarantined tables still physically exist in the schema at that point, so “trim the list, run tests, see green” proves nothing (it was never red). The real red/green cycle for each test below happens in two passes:

  1. Now (Task 3): make the edit described in each subtask, but do not yet treat a passing cargo test -p vox-db as confirmation — the tables haven’t been removed yet, so this can only catch compile errors.
  2. After Task 4.3 removes the DDL, and again after 4.4 bumps the version: re-run cargo test -p vox-db. This is the actual red/green checkpoint — if you temporarily revert a given test’s Task-3 edit at that point and it now fails (compile error or assertion failure) against the post-quarantine schema, that confirms the edit was both necessary and targets the right table. Task 4’s “Run” block (below) has been updated to include this step explicitly; don’t skip it by treating Task 4’s plain cargo build as sufficient.
  • 3.1: local_tests.rs::baseline_schema_includes_chat_and_search_tables — UPDATE: remove any now-quarantined table names from its assertion list (subject to Task 2.3’s TOESTUB/chat-search cluster decision); keep it asserting the tables that remain live. Meaningfulness check: after trimming, confirm the test still asserts more than one or two tables — if Task 2.3 quarantined most of the groups this test originally checked, consider whether the remaining assertion is still worth keeping as a distinct test or should be folded elsewhere; a test that trivially passes on a single leftover table is low-signal.

  • 3.2: local_tests.rs::legacy_jsonl_roundtrips_gamification_and_coordination — UPDATE: remove distributed_locks (and any other now-quarantined table it iterates) from the roundtrip set it exercises. Verify post-Task-4.3 that this test would fail if you left distributed_locks in the iterated set (i.e. it’s actually exercising the removed table, not passing regardless).

  • 3.3: local_tests.rs::history_entries_round_trip and schema/domains/history.rs::history_entries_schema_round_trip — disposition per Task 2.2’s decision: if kept live, no change needed. If quarantined: move both tests behind the same decision (delete or mark #[ignore] with the rationale). Before deciding, verify post-Task-4.3 that these tests do in fact fail against the post-quarantine schema (compile error, since history.rs holds both the DDL Task 4 moves and this test — see the parallelism note above) — that failure is the red step confirming the disposition is necessary, not a guess.

  • 3.4: schema/mod.rs::chat_search_and_codex_in_fragments — UPDATE: trim to tables still in the default baseline after Task 2.3. Verify post-Task-4.3 the untrimmed version would fail (fragment no longer contains the quarantined table’s DDL) before finalizing the trim.

  • 3.5: tests/news_approval_tests.rs::mark_news_published_column_order_matches_github_twitter_oc... and tests/schema_contract_tests.rs::published_news_uses_news_id_primary_key — disposition per whether the publication/scholarly cluster was kept live in Task 2.3. Same post-4.3 red-check requirement as 3.3-3.4 if quarantined.

  • 3.6: tests/ops_skill_tests.rs::unpublish_skill_removes_row — this test only exercises skill_manifests (via publish_skill/unpublish_skill/get_skill_manifest, all of which issue statements against skill_manifests, not skill_executions) — its disposition should follow whatever Task 2.3 decided for the skill-manifests table, not skill_executions. If the intent was specifically to cover skill_executions, the correct target tests are list_skill_executions_returns_newest_first, list_skill_executions_limit_is_honoured, and list_skill_executions_empty_when_no_rows — in the same file, tests/ops_skill_tests.rs, not a different one — confirm against Task 1.2’s actual output (not this plan’s original assumption) which test(s) really reference skill_executions, and disposition those per whether the “skill ecosystem” cluster (design §2.2) was kept live in Task 2.3.

  • 3.7: toestub_store.rs::ensure_tables_is_idempotent_and_creates_usable_tables — first check whether toestub_store.rs’s public functions have any caller outside the module (if the whole module is unused, this is a larger dead-code question than one test — flag it rather than silently deleting the test and leaving dead production code behind; this is a decision point, not a scoped edit — surface it before proceeding rather than resolving it unsupervised). Disposition per Task 2.3.

    Run after all of 3.1-3.7 (first pass, DDL still present): cargo test -p vox-db Expected: clean, edits compile. This does not yet confirm the dispositions were correct — see the mandatory re-run after Task 4.3/4.4 below.


  • 4.1: Create crates/vox-db/src/schema/domains/quarantine.rs. For each table in the final quarantine list (Task 2.3’s output) that has literal CREATE TABLE DDL, move it there verbatim from its current domain file, with a comment noting status (DEAD/DORMANT), the ops-file trail from Task 1.1’s output (or “none” for DEAD), and subsystem cluster. Note: until 4.3 runs, the DDL now exists in both quarantine.rs and the original domain file — this is an expected transient duplicate-definition state, not yet a build error (nothing assembles quarantine.rs into baseline_sql() until 4.2), but don’t run a full schema-creation test between 4.1 and 4.3 or it will double-create tables. Two exceptions to the DDL-move pattern (see the “Declaration-mechanism note” in the Goal section, and design §2.1): if handoff_payloads ends up on the final quarantine list, its only declaration is a CollectionInfo entry in schema::spec::orchestrator_schema_digest() — remove or relocate that entry instead of moving DDL. archive_membership, chunk_members, context_window_items, context_windows, and zstd_dictionaries have no declaration anywhere in current source — skip them entirely in 4.1; they need no schema-file change, only the DROP TABLE in Task 5.

  • 4.2a (RED, write first): The real edit site for gating is crates/vox-db/src/schema/manifest.rs (lines ~52-175), not schema/domains/mod.rs — domains/mod.rs contains only pub mod ...; declarations with no fragment-assembly logic; the SCHEMA_FRAGMENTS const array and pub fn baseline_sql() that actually loop over fragments and build the DDL string live entirely in manifest.rs (re-exported via schema/mod.rs). Before touching manifest.rs, write a test that calls baseline_sql() with the quarantine feature off and asserts a quarantined table’s CREATE TABLE string/name is absent, plus a second variant of the same test (or a #[cfg(feature = "quarantine")]-gated one) asserting it’s present when built with --features quarantine. Run the feature-off variant now — it should fail (the DDL hasn’t moved/been gated yet), confirming this is a real red step and not a check of already-true behavior. A plain cargo build cannot substitute for this: build succeeding says nothing about whether the SQL string was actually excluded from the binary.

  • 4.2: Add a quarantine feature to crates/vox-db/Cargo.toml (default off — but do not copy the local feature as your “off by default” precedent: local is actually default = ["local"] in the current Cargo.toml; only replication is off-by-default. Model quarantine on replication, not local, and do not add quarantine to the default = [...] array). Wire manifest.rs so the quarantine fragment is only appended in baseline_sql() when the feature is enabled (there is no existing SQL-gating pattern in this crate to “mirror” — local/replication gate Rust connection/config code paths in config.rs, facade/connect.rs, pool.rs, store/open.rs, never a conditionally-included DDL fragment, so treat this as a new pattern for the crate, not a copy of an established one). Make 4.2a’s test pass (GREEN) for both feature configurations.

  • 4.3: Remove the quarantined tables’ DDL from their original domain files (this resolves 4.1’s transient duplicate-definition state).

    Run immediately after 4.3, before 4.4: cargo test -p vox-db Expected: this is the real red/green checkpoint for all of Task 3’s edits (see Task 3’s sequencing note) — the quarantined DDL is now actually gone from the default build, so a green result here means Task 3’s trimmed assertions are genuinely exercised, not vacuously passing. If anything fails here, it’s either a Task 3 edit that missed a table or a Task 4.1/4.3 DDL-move mistake — resolve before proceeding to 4.4.

  • 4.4: Bump BASELINE_VERSION 84 → 85 in schema/manifest.rs, with a one-line changelog comment matching the existing style (see lines 10-18 of that file).

    Run:

    cargo build -p vox-db
    cargo build -p vox-db --features quarantine
    cargo test -p vox-db
    cargo test -p vox-db --features quarantine
    cargo build --workspace

    Expected: all clean. The two plain cargo build legs alone are not sufficient — cargo test -p vox-db --features quarantine is required to actually exercise the quarantined DDL’s runtime behavior (a broken FK reference or DDL typo in the quarantined fragment could compile but fail to create a working schema, and cargo build would not catch that). The final cargo build --workspace leg exists specifically to catch Cargo feature unification: because this workspace uses resolver = "2", if any other crate in the workspace ever adds vox-db as a normal (non-dev) dependency with the quarantine feature enabled, that feature gets unified into every normal-dependency use of vox-db in the same build, including production binaries — cargo build -p vox-db --features quarantine run in isolation would never surface that. If this workspace-wide build ever picks up quarantined DDL unexpectedly, treat it as a build-graph bug and fix the offending crate’s Cargo.toml, the same class of issue as the recent vox-orchestrator-mcp wiremock/eval-gate fix.


Out of scope for this plan: design §3.5 (“Graduation path” — the procedure to revive a quarantined table later) has no corresponding task here and is not implemented by Tasks 1-9. If a quarantined table needs to come back, that’s a follow-up piece of work following design §3.5’s 4-step procedure (move DDL out of quarantine.rs, resolve test disposition, bump BASELINE_VERSION again, land the real caller) — not something this plan’s tasks produce automatically.

Blocker-level correction — read before implementing: the originally-described mechanism (“a Migration entry that runs SELECT COUNT(*) and aborts, else DROP TABLE, via migration.rs’s existing mechanism”) cannot work as stated. Migration is { version: i64, name: String, up_sql: String } with no callback/hook field, and apply_migrations executes up_sql via connection().execute_batch(...) — a flat batch with no host-language branching and no way to surface a query result back into Rust for a conditional decision. migration.rs’s own module doc says up_sql “must not contain row-returning statements (no standalone SELECT)” for exactly this reason. A SELECT COUNT(*)-then-branch cannot live inside up_sql. The safety rail has to be Rust-side orchestration that runs before apply_migrations is ever called for this migration, not inside it. Additionally, migration.rs’s own doc warns “use custom Migration rows only on ephemeral DBs, tests, or with a plan to re-baseline the file” — read that warning in full before writing 5.1.

Second blocker — version numbering: do not add this migration “at the next version” past BASELINE_VERSION. store/open.rs’s normal connect() path treats current_version > BASELINE_VERSION as a fatal, non-recoverable StoreError::LegacySchemaChain with no automatic recovery. Task 4.4 bumps BASELINE_VERSION to 85; if this migration lands at version 86, the instant it’s applied to any DB, that DB’s schema_version (86) exceeds BASELINE_VERSION (85) and every subsequent plain connect() on it fails forever. The migration that drops the quarantined tables for existing DBs must bring schema_version to exactly 85 — the same version fresh installs reach via baseline_sql() (which already excludes the quarantined DDL by construction) — not to some version beyond it. Coordinate the exact version number with whatever migration already exists (if any) that advances old DBs toward 84/85, so there is exactly one migration path to version 85, not two.

  • 5.1a (RED, write first, persisted in migration.rs’s existing test harness — not a one-time manual check): Write two failing tests before any implementation exists:

    • (a) Given a DB copy with a non-empty to-be-quarantined table, running the migration path aborts with the named error and leaves every table (including the non-empty one) intact, and schema_version does not advance. This must fail now because neither the pre-check function nor the migration exists yet.
    • (b) Given a DB copy where all to-be-quarantined tables are empty, running the migration path drops them and schema_version advances to 85. Also failing now for the same reason.

    Both tests must also cover the case where a quarantined table doesn’t exist at all in the DB copy (older baseline that predates that table) — assert this is treated as “0 rows, safe to skip,” not an unhandled SQLite “no such table” error. Recall from design §2.7 that at least ~19 other .vox/store.db copies exist across worktrees at potentially different baseline versions; if only the main checkout’s DB is available locally, simulate an older/partial schema for this case rather than skipping it.

  • 5.1: Implement the two-phase mechanism to make 5.1a green:

    • Phase 1 (Rust-side, runs before any migration is applied): a plain async function that opens a normal (non-batch) query connection, runs SELECT COUNT(*) FROM <table> for each quarantined table individually, treating a “no such table” error as count-0 (safe), and either aborts with a named error listing every non-empty table (no migration applied, DB untouched) or proceeds.
    • Phase 2 (the actual Migration entry, via the existing mechanism): only reached if Phase 1 passed — a plain, unconditional DROP TABLE IF EXISTS <table> batch for every table Phase 1 confirmed empty, at version 85 (see version-numbering note above).
    • Rollback/backup: Migration has no down_sql/reverse-migration field anywhere in the crate, so there is no automated rollback if something goes wrong after the DROP batch runs (partial batch failure, wrong table on the list, needing to undo after the fact). Document this explicitly in the migration’s code comment and require whatever invokes this migration in practice to keep (or instruct the user to keep) a copy of .vox/store.db taken immediately before the upgrade — do not silently rely on “it’s just a DROP, it’s fine.”
    • Abort-recovery path: because migrate() runs automatically on every local connect() (design §2.5), a Phase-1 abort will recur on every subsequent launch until the offending table’s rows are cleared or exported by hand. Add a clear-error message that names the exact table(s), states that the install is pinned below the new baseline until resolved, and points at a one-line remediation (export the row(s), then either delete them or move them to their new home, then retry). Do not leave this as “aborts with a clear error” with no further guidance — that leaves a real local install stuck with no stated recovery.
  • 5.2: Test the migration against a copy of the real audited DB (.vox/store.db from the main checkout) — never the live file directly. Confirm: (a) it drops all quarantined tables when run against a copy with the two exceptions from Task 2 already excluded from the DROP list, (b) it correctly refuses and names the table if you deliberately insert a row into a to-be-dropped table first. This is in addition to 5.1a’s persisted tests, not a replacement for them — 5.1a is the committed regression test for the safety rail; 5.2 is a one-time exploratory sanity check against real data. Re-confirm the exact DROP list against Task 2’s final decisions immediately before running this (per the parallelism note above, don’t run this from a stale table list). Also note: since this migration is only exercised here against a copy of the main checkout’s DB, and no other worktree’s .vox/store.db is tested, treat any other active worktree as untested until its own next normal vox invocation applies the migration — if that’s a concern, run this same procedure against one or two of the other known worktree DB copies as an extra check before considering the migration safe to rely on broadly. Stale/abandoned worktrees are handled by pruning (Task 8.1), not by this migration.

    Run:

    copy .vox\store.db .vox\store.db.test-copy

    then run the migration against the copy via migration.rs’s existing test harness (extend it with 5.1a’s two persisted tests rather than only doing this manually), and inspect the resulting table list.

    Expected: table count drops from 219 to the Task 2.3-adjusted LIVE count; schema_version reflects 85; no data loss on any table that had rows; a table missing from an older-baseline copy is handled per 5.1a, not treated as a hard failure.


Investigation performed against this worktree’s current source and graphify-out/table_usage_report.json (Task 1’s committed output — 219 tables total, 116 LIVE / 103 DORMANT+DEAD at the starting point). All reads/greps below were run directly against this worktree; no numbers were carried over from memory or the design doc without re-verifying against source.

2.1 developer_journey_definitions — QUARANTINE (deterministic-seed exception, not a legacy-import artifact)

Section titled “2.1 developer_journey_definitions — QUARANTINE (deterministic-seed exception, not a legacy-import artifact)”
  • Read crates/vox-db/src/schema/domains/developer_journeys.rs: the CREATE TABLE ... developer_journey_definitions DDL string contains an INSERT OR IGNORE INTO developer_journey_definitions (...) VALUES ('canonical_journey.v1.greenfield_vox_mens_devloop', ...) baked directly into the DDL constant SCHEMA_DEVELOPER_JOURNEYS, which fires unconditionally on every baseline_sql() run.
  • Read crates/vox-db/src/store/ops_developer_journeys.rs: its only function, list_developer_journey_steps, queries developer_journey_steps exclusively (SELECT step_json FROM developer_journey_steps WHERE journey_id = ?1 ...). It never references developer_journey_definitions.
  • Decision: confirmed write-only schema-init seed with no reader anywhere in the codebase. Proceed to quarantine as planned in Task 4/5, but the quarantine.rs comment and Task 5.1’s DROP-migration exception list must record this explicitly as “deterministic DDL-baked seed row, not legacy-import residue” and exclude it from the auto-DROP migration pending a one-time manual row export (per the plan’s original instruction) — no re-check needed at DROP time, this is settled.

2.2 history_entries — KEEP LIVE (finished, tested, simply unwired)

Section titled “2.2 history_entries — KEEP LIVE (finished, tested, simply unwired)”
  • Read crates/vox-db/src/history_store.rs (389 lines): a complete, production-quality CRUD module — add_entry, list_entries (by kind, with pagination), search_entries (LIKE search over redacted text), pin_entry, delete_entry, evict (per-kind eviction caps with pinned-row exemption), plus a HistoryCaps config struct with real defaults (clip=1000, command=500, chat=500). It has its own #[cfg(test)] mod tests with 3 passing-shaped unit tests (add_then_list_by_kind, evict_respects_caps_and_pins, search_redacted_text) exercising the real logic, including redaction integration.
  • Confirmed via grep: local_tests.rs::history_entries_round_trip and schema/domains/history.rs::history_entries_schema_round_trip both exist and exercise the table directly with INSERT/SELECT.
  • Grepped the workspace for callers of history_store::{add_entry,list_entries,search_entries,pin_entry,delete_entry} outside vox-db — none found, consistent with the DORMANT classification (no wired caller yet).
  • Decision: keep in the live baseline, not quarantine. Rationale (one sentence): this is complete, redaction-aware, cap-enforcing CRUD with its own passing unit tests and a real row of data — it reads as “built ahead of its UI/CLI wiring,” not abandoned scaffolding, and quarantining it would create needless rework the moment the History & Clip Manager UI lands (see project memory: project_history_clip_manager_design_2026_06_19.md records S1+S2 already done).

2.3 Subsystem cluster cross-check (all 11 clusters) — CORRECTED 2026-08-02

Section titled “2.3 Subsystem cluster cross-check (all 11 clusters) — CORRECTED 2026-08-02”

Correction note: an earlier pass of this section moved 21 tables to keep-live based on cluster-level doc activity (e.g. “Scientia has an approved finalization plan, therefore its scientia_* candidate tables stay live”). A spec-compliance review correctly flagged this as invalid: a doc about Scientia in general is not evidence that scientia_citations specifically is being implemented, and several of the reinstated tables (scientia_prereg, scientia_publication_attempts, scientia_citations, scholarly_publication_records, syndication_events) are classified DEAD — zero code references anywhere in the entire codebase, not even internal vox-db plumbing — which is strong evidence against active implementation regardless of what a roadmap doc says conceptually about the broader initiative. The table below is the corrected analysis (the original cluster-level reasoning was not preserved verbatim; this replaces it, it does not sit alongside it), applying a per-table bar throughout: a table only moves to keep-live if a doc names that exact table (not just the cluster/subsystem) or code shows real per-table work in progress, and DEAD status is treated as a disqualifier on its own regardless of cluster-level activity.

Method: grepped docs/src/architecture/*.md, docs/superpowers/plans/**/*.md, and docs/src/reference/*.md for each specific table’s exact name (not the cluster/topic keyword). (docs/src/archive/ is tombstoned per CLAUDE.md/AGENTS.md and was not used as evidence even though a few archived docs matched — an archived doc is not “current, active” work by definition.) Internal vox-db ops-file existence (the thing that makes a table DORMANT rather than DEAD) is not by itself counted as “real per-table work in progress” — it’s the baseline condition already reflected in the DORMANT/DEAD classification, not extra evidence of current activity.

#Cluster (design §2.2 count)Per-table evidence foundDecision
1Scientia research pipeline (11)Exact-name hits: scientia_discoveries — docs/superpowers/plans/scientia/2026-05-15-scientia-phase-A-signal-producers.md and 2026-06-05-p1-spec-compliant-nanopub-identity.md/p2-human-gated-review-backend.md cite it repeatedly as an existing table actively being extended/mirrored (human_gate_status vocabulary reused, scientia_finding_candidates built to mirror its shape) — status DORMANT (has internal ops code), not DEAD. scientia_producer_cursor — named exactly in docs/src/reference/scientia-ssot-handbook.md:79 (“resumable via scientia_producer_cursor”) describing a live, currently-documented resumability mechanism for automated discovery producers — status DORMANT. scientia_research_artifacts — named exactly in docs/src/architecture/vox-gui-scientia-coverage-audit-2026.md:50 (“durable artifacts in scientia_research_artifacts are never rendered”) — confirms the backend writes real durable data to it, just isn’t GUI-surfaced — status DORMANT. scientia_publication_queue — named exactly in the same audit doc (vox-gui-scientia-coverage-audit-2026.md:63, “the publication lifecycle board (scientia_publication_queue stages)”) — status DORMANT. No table-specific evidence found for scientia_feed_sources, scientia_provider_runs, scientia_training_pairs (DORMANT, but unnamed in any doc). scientia_prereg, scientia_publication_attempts, scientia_citations are DEAD — one doc (p1-spec-compliant-nanopub-identity.md) does name scientia_prereg as a schema “precedent,” but this describes its DDL shape as a template to mirror, not active work on the table itself, and it’s disqualified by DEAD status regardless.KEEP LIVE (4 of 11): scientia_discoveries, scientia_producer_cursor, scientia_research_artifacts, scientia_publication_queue. PROCEED TO QUARANTINE (7 of 11): scientia_feed_sources, scientia_prereg, scientia_provider_runs, scientia_publication_attempts, scientia_training_pairs, scientia_citations, plus whichever 1 table completes the design doc’s count of 11 (not identified by name-prefix matching).
2External review/CodeRabbit (6)No table-specific doc evidence found for any of external_review_comment_thread, external_review_finding_state_history, external_review_kpi_snapshot, external_review_outcome, external_status_snapshots, artifact_reviews/populi_reviews (DEAD).PROCEED TO QUARANTINE (unchanged from first pass — this cluster was never moved to keep-live).
3Codex conversation graph (7)No table-specific doc evidence found.PROCEED TO QUARANTINE (unchanged).
4Publication/scholarly (6)published_news — has two real referencing test files per design §2.4 (tests/news_approval_tests.rs::mark_news_published_column_order_matches_github_twitter_oc..., tests/schema_contract_tests.rs::published_news_uses_news_id_primary_key), both asserting against real column/PK structure — genuine, table-specific, code-level evidence, status DORMANT. No table-specific doc evidence found for publication_external_links, publication_external_revisions, publication_media_assets (all DORMANT but unnamed) — a reference doc mentions a publication-external-jobs-tick command and an “external-jobs dead-letter queue,” but that names an operator command, not confirmed to be either of these two tables specifically, so it doesn’t clear the bar. scholarly_publication_records, syndication_events are DEAD — disqualified regardless of cluster-level Scientia activity.KEEP LIVE (1 of 6): published_news. This resolves Task 3.5’s disposition: both cited tests need no change, the table stays live. PROCEED TO QUARANTINE (5 of 6): publication_external_links, publication_external_revisions, publication_media_assets, scholarly_publication_records, syndication_events.
5TOESTUB build cache (4)CORRECTED 2026-08-02 (caught during Task 3’s spec review, not the original 2.3 pass): the “zero external callers” claim above was wrong. crates/vox-db/src/lib.rs re-exports toestub_store::{add_suppression, get_file_cache_blocking, list_suppressions_blocking, load_baseline, load_latest_task_queue, save_baseline, save_task_queue, set_file_cache_blocking} at the crate root, and crates/vox-cli/src/commands/diagnostics/stub_check/mod.rs genuinely imports and calls add_suppression, load_baseline, load_latest_task_queue, save_baseline, save_task_queue as a live production CLI flow (--import-suppressions loads toestub.toml and calls add_suppression, which writes toestub_suppressions; load_baseline/save_baseline read/write toestub_baselines; load_latest_task_queue/save_task_queue read/write toestub_task_queue). This is genuine table-specific evidence for 3 of the 4 tables — real production code, not doc-topic adjacency. The original grep that found “no external caller” only checked for qualified toestub_store:: paths and missed the re-exported/unqualified imports — the same class of blind spot as the skill_executions wrapper-function case (design §2.4): the census tooling (and a plain grep) can miss usage that goes through a re-exported function whose name doesn’t contain the table name as a substring. get_file_cache_blocking/set_file_cache_blocking (backing toestub_file_cache) have no confirmed caller in crates/vox-cli/ — that one table’s disposition is unchanged.KEEP LIVE (3 of 4): toestub_suppressions, toestub_baselines, toestub_task_queue — real production callers via vox-cli’s stub-check diagnostics command. PROCEED TO QUARANTINE (1 of 4): toestub_file_cache — no confirmed caller found. Task 3.7’s original module-is-dead-code flag is withdrawn: toestub_store.rs has live callers and is not dead code; no follow-up needed on that front.
6MENS/training (4)No table-specific doc or code-level evidence found for any of mens_corpus_quality, grpo_training_run, local_train_log, training_throughput_profiles despite an extensive search of mens-training-ssot.md, mesh-mens-distributed-training-and-execution-plan-2026.md, mens-training-pipeline-audit-and-improvement-plan-2026-06-07.md, mens-corpus-audit-findings-2026.md, and the voxmens-* docs — none names any of these 4 tables by exact name. All 4 are DORMANT (real internal vox-db ops code exists in ops_mens_intelligence.rs/ops_mens_cloud.rs), but per the corrected bar that’s the baseline DORMANT condition, not extra evidence of current per-table work.PROCEED TO QUARANTINE (all 4), reversing the first pass’s cluster-level “strongest active-cluster signal” call. Flagged for human escalation rather than a unilateral call: this cluster has by far the most active-development documentation of all 11 (multiple current/approved docs, training_eligible: true), and it would not be surprising if one of these 4 tables is genuinely mid-flight without a doc naming it yet — recommend a direct question to the MENS/training owner before Task 4 quarantines these specifically, rather than treating “no doc found” as certain proof of inactivity.
7Skill ecosystem (2)No table-specific evidence for skill_executions/skill_reliability (unchanged from first pass).AMBIGUOUS, explicitly flagged — quarantine as default, not a silent pick (unchanged). Worth a direct question before Task 4.
8News publishing (3)No table-specific doc evidence for news_publish_approvals, news_publish_approvals_v2. (published_news is credited to cluster 4 above and kept live, not this cluster.)PROCEED TO QUARANTINE.
9Planning graph (3)No table-specific doc evidence for plan_node_attempts, plan_test_decisions, plan_versions.PROCEED TO QUARANTINE.
10Gamification/vox-mesh trust (4)No table-specific doc evidence for vox_kudos, vox_peer_reputation, victory_verdicts, node_trust_grants/node_identities/mesh_heartbeats (the topically-adjacent gamification-ludus-review-findings-2026.md doesn’t name any of them).PROCEED TO QUARANTINE (unchanged).
11CI completion detector (2)No table-specific doc evidence for ci_completion_detector_snapshot, ci_completion_finding.PROCEED TO QUARANTINE (unchanged).

Corrected adjusted split after 2.1-2.3 (updated 2026-08-02 for the TOESTUB correction found during Task 3’s review — see cluster 5 above):

  • Moved from quarantine-candidate back to keep-live: history_entries (2.2) + published_news (cluster 4) + scientia_discoveries, scientia_producer_cursor, scientia_research_artifacts, scientia_publication_queue (cluster 1) + toestub_suppressions, toestub_baselines, toestub_task_queue (cluster 5) = 9 tables total, each with genuine table-specific evidence cited above (not cluster-level inference).
  • developer_journey_definitions (2.1) stays a quarantine candidate (no count change) but with the deterministic-seed annotation carried into Task 4/5.
  • Corrected adjusted LIVE count: 116 + 9 = 125.
  • Corrected adjusted DORMANT+DEAD (quarantine) count: 103 − 9 = 94.
  • 125 + 94 = 219, consistent with Task 1’s total table count. This corrected split — not the first-pass 137/82, and not the intermediate 122/97 — is what Task 4 onward should operate against.
  • Methodology note for whoever re-runs scripts/db-table-census.vox in the future: the TOESTUB correction above reveals a structural limitation, not a one-off mistake — the census tool (and a plain grep) can only detect usage that contains the literal table name as a string. Usage that goes through a re-exported Rust function whose name doesn’t contain the table name (e.g. add_suppression writing toestub_suppressions) is invisible to it, same as the skill_executions wrapper-function case in design §2.4. Treat a DEAD/DORMANT verdict from the tool as “no literal-name reference found,” not “definitely unused” — for any table where the disposition materially matters, a targeted check for re-exported/wrapper-function usage (like this one) is worth doing before finalizing, not just trusting the tool’s status field.
  • Escalation recommended before Task 4 finalizes its list: the MENS/training cluster (4 tables) and the skill-ecosystem cluster (2 tables) are genuinely ambiguous under the corrected bar — high cluster-level activity or topical doc adjacency, but no per-table naming found, and (per the methodology note above) not yet checked for wrapper-function-mediated usage the way TOESTUB was. Both are defaulted to quarantine here per the “no clear evidence → don’t silently keep live” principle, but a direct human check-in (including a wrapper-function check, not just a doc/literal-name search) before Task 4 executes is recommended for these 6 tables specifically.

For clavis_account_secrets, user_identities, and any other table Task 1’s tool flags sensitive: true (per graphify-out/table_usage_report.json’s sensitive field): regardless of what any run of scripts/db-table-census.vox computes — LIVE, DORMANT, or DEAD, today or on any future re-run — such a table must never be added to a quarantine list or a DROP list without an explicit, separate human confirmation step. A “zero non-quarantine callers” signal from the mechanical census is not sufficient on its own for tables of this kind, because a later refactor could remove a sensitive table’s last outside-vox-db caller and let the tooling silently reclassify it. This is a standing rule, not a one-time check — it applies to every future re-run of the census tool per design §3.6, and should be encoded as a comment in scripts/db-table-census.vox and honored by whoever executes Tasks 4/5. Confirmed via graphify-out/table_usage_report.json: exactly two tables are currently flagged "sensitive":true — clavis_account_secrets (LIVE, 4 referencing files) and user_identities (LIVE, 4 referencing files). Both are already LIVE, so neither is at risk of quarantine today, but the standing rule above applies to them (and to any future table the tool flags sensitive) regardless.


Task 6: vox-db-types cleanup for DEAD tables only

Section titled “Task 6: vox-db-types cleanup for DEAD tables only”
  • 6.1 (green-before-red-analog: build green before deletion, delete, build still green after): For the final DEAD-table list from Task 2.3’s adjusted split (not a hardcoded “21 originally-DEAD” — Task 2.1/2.3 may have pulled tables out of or into that set, e.g. if developer_journey_definitions turns out not to be genuinely dead-adjacent), grep crates/vox-db-types/src/store_types/*.rs for any corresponding Rust struct. Design §2.2’s original census found zero references anywhere for true DEAD tables, so this should turn up nothing — treat any hit as a signal the census under-counted and re-run Task 1.1 rather than deleting a type that’s actually referenced somewhere the scan missed.
  • 6.2: If 6.1 confirms zero references for a struct: this task is subtractive only, so there’s no red test to write first — instead, confirm cargo build -p vox-db-types is green before deleting anything (establishing the pre-deletion baseline), delete the confirmed-dead struct(s), then run cargo build -p vox-db-types (and cargo build --workspace) again as the green checkpoint proving the deletion was safe. Do not stop at “grep found nothing” — that alone deletes nothing; the actual removal and this before/after build check are the deliverable of this task.

Task 7: Storage-boundary guardrail (documentation only)

Section titled “Task 7: Storage-boundary guardrail (documentation only)”
  • 7.1: Add a short note to docs/src/architecture/where-things-live.md (or create a small dedicated doc if that file isn’t the right home) documenting the threshold from design §3.7: embeddings.vector and any future large-BLOB columns move to file/object storage with a path+hash pointer once real row count or per-row size crosses a stated number. No code change.

Task 8: File-sprawl addendum (documentation only, low priority)

Section titled “Task 8: File-sprawl addendum (documentation only, low priority)”
  • 8.1: One-line addition to wherever the existing worktree-cleanup practice is documented (or your own habit, if it’s not written down anywhere yet — in that case, skip rather than inventing new documentation for it): stale worktree removal also reclaims its .vox/store.db.

  • 9.1: Full workspace build and vox-db test suite:
    cargo build --workspace
    cargo test -p vox-db
    cargo build -p vox-db --features quarantine
    cargo test -p vox-db --features quarantine
    Expected: all clean. (This repeats Task 4’s final “Run” block as a whole-workspace re-confirmation, including the --features quarantine test leg — not just the build legs.)
  • 9.2: Re-run vox run scripts/db-table-census.vox -- --db .vox/store.db (Task 1.1’s tool). Expected: LIVE count matches Task 2.3’s final adjusted number; DORMANT+DEAD count is 0 in the default (non-quarantine) baseline’s declared tables (quarantined tables now live only in quarantine.rs, outside the default baseline_sql() scan path).
  • 9.3: Confirm file-size impact. vox init does not create a .vox/store.db — it only scaffolds Vox.toml/src/main.vox/.vox_modules/ (crates/vox-cli/src/commands/init.rs’s run() calls scaffold_vox_project_at(), which never touches VoxDb). store.db is created lazily the first time something actually calls VoxDb::connect() — before running this step, identify which real command or test path first opens the store (e.g. a command that touches lock/sync/search state, or vox-db’s own connect-test harness against a fresh scratch path) and use that instead of vox init. Run it in a scratch directory and measure .vox/store.db’s size. Acceptance bar: don’t just check “smaller than 5.9MB” — that would pass on a marginal, buggy 1% reduction. Since the table-count reduction is now whatever Task 1.1/9.2 actually measured (not a fixed 219→116), compute the expected size reduction as roughly proportional to that ratio at this point in the plan (Task 9.2 has just re-run the census — use its LIVE count vs. the pre-condensation count) and confirm the measured size is in that ballpark, not merely “any amount smaller.”

Task 2 — SUPERSEDED 2026-08-02 by Task 1b (wrapper-call detection)

Section titled “Task 2 — SUPERSEDED 2026-08-02 by Task 1b (wrapper-call detection)”

Everything in the ## Task 2 Decisions section above (including its own two correction rounds) is now superseded. Task 4’s implementer, following this plan’s own instruction to sanity-check DORMANT tables for hidden wrapper-mediated callers before quarantining them, found the blind spot wasn’t limited to the one TOESTUB case Task 2/3 had already caught — roughly 40% of the quarantine-candidate list showed the same pattern. Rather than resolve that by hand table-by-table, Task 1b (4f5822e72e) added a second automated detection pass to scripts/db-table-census.vox that traces internal vox-db function calls, not just literal table-name strings, and re-ran it against the real DB.

New authoritative counts: 219 total = 170 LIVE / 25 DORMANT / 24 DEAD (was 116/82/21 from the literal-string-only pass; Task 2’s manually-corrected 125/94 is also superseded). 54 tables were promoted DORMANT→LIVE by the new pass alone — more than triple Task 2’s 9 manual corrections, all 9 of which the new pass also independently confirms via real code evidence except one (see below).

Reconciling with Task 2’s specific findings:

  • 8 of Task 2’s 9 keep-live corrections (history_entries, published_news, scientia_discoveries, scientia_producer_cursor, scientia_research_artifacts, toestub_suppressions, toestub_baselines, toestub_task_queue) are now independently confirmed by the automated wrapper-call pass with real cited call sites — no manual reasoning needed to trust them anymore.
  • scientia_publication_queue is the one exception: it remains DORMANT in the new automated report (graphify-out/table_usage_report.json) — the wrapper-call pass found no confirmed external caller for it. Task 2’s original keep-live call for this table was based on doc evidence (a specific audit doc naming it as “the publication lifecycle board… stages”), not code evidence, and the design’s evidentiary bar always allowed either kind. This table is carried forward as a manual keep-live exception on top of the automated list — the doc evidence hasn’t changed, only the automated tool’s (code-only) blind spot to it.
  • MENS/training cluster (mens_corpus_quality, grpo_training_run, local_train_log, training_throughput_profiles): Task 2 flagged this as ambiguous and recommended human escalation. Resolved — all 4 are now confirmed LIVE by the automated pass with real cited callers (e.g. vox-ml-cli calling query_corpus_quality_summary). No escalation needed.
  • Skill-ecosystem cluster (skill_executions, skill_reliability): Task 2 flagged this as ambiguous too. Resolved — both are confirmed to correctly stay quarantine-candidates, but on much stronger grounds than “no doc found”: skill_reliability’s only candidate wrapper functions were verified to query a different, already-consolidated table (reliability_scores) — a doc comment in ops_skills.rs explicitly says not to read the legacy skill_reliability table — so there was never a real candidate to begin with. skill_executions has a genuine wrapper function (list_skill_executions_by_skill) but zero callers anywhere outside vox-db, confirmed by direct search. No escalation needed.
  • developer_journey_definitions (2.1’s deterministic-seed exception): unaffected, still DEAD, same disposition (quarantine, with the deterministic-seed annotation, excluded from the auto-DROP pending manual row export).

Final quarantine list for Task 4 onward: the 25 DORMANT + 24 DEAD tables in graphify-out/table_usage_report.json, minus scientia_publication_queue (the one doc-evidence-only exception) = 48 tables. Final LIVE count: 170 + 1 = 171. 171 + 48 = 219, consistent with the total. This — not any earlier number in this document — is what Task 4 operates against.


Task 9 — Final Verification: DONE (2026-08-02)

Section titled “Task 9 — Final Verification: DONE (2026-08-02)”

All nine tasks (plus 1b, added mid-execution when Task 4’s sanity check found the wrapper-call blind spot was systemic) are complete, each independently spec- and code-quality-reviewed.

  • 9.1 (full build/test, both feature configs): cargo build --workspace clean (--exclude vox-gui, a pre-existing unrelated sidecar-binary build gotcha for fresh worktrees, not caused by this work). cargo test -p vox-db and cargo test -p vox-db --features quarantine both fully green — zero failures across every integration test binary. One test, guarded_connection_tests::concurrent_writes_through_shared_voxdb_all_succeed, is order-dependent/flaky and unrelated to this work (confirmed passing reliably in isolation).
  • 9.2 (re-run the census tool): Final run against the real main-checkout DB: 219 total = 171 LIVE / 48 quarantine-candidate (25 DORMANT + 24 DEAD). This re-run itself caught one more real bug: migration.rs’s QUARANTINE_DROP_TABLES const (added by Task 5) generically lists all 47 auto-dropped tables by name, which “laundered” every former-DEAD table into DORMANT the moment that file existed — the same failure mode codex_legacy.rs/circuit_breaker.rs/schema/manifest.rs were already excluded for, just introduced by this plan’s own Task 5 work. Fixed by adding migration.rs to the census tool’s exclusion list, with a new fixture case covering it. Confirmed the default (non-quarantine) schema’s CREATE TABLE declarations contain zero of the 48 quarantine-candidate tables (verified directly against crates/vox-db/src/schema/ excluding quarantine.rs, cross-checked against manifest.rs’s own baseline_sql() feature-gating tests).
  • 9.3 (file-size impact): vox init does not create a database file (confirmed, as anticipated) — used vox db status with VOX_DATA_DIR pointed at an isolated scratch directory instead, with a freshly-reinstalled vox binary built from this branch’s HEAD (2e6b629ac0) to avoid measuring a stale schema. Fresh file: 1.43MB (vox.db, schema v85), versus the original audit’s 5.93MB (.vox/store.db, schema v84, 219 tables) — a ~75% reduction, exceeding the naive proportional estimate (171/219 ≈ 78% of tables kept → ~78% of size expected) because quarantined tables carried disproportionately more indexes on average. Verified the fresh file’s actual table count directly: 168 tables created eagerly via baseline_sql(), plus 3 more (provider_usage, attention_events, agent_trust_scores) created lazily via the Collection API on first real use, not at connect time — 168 + 3 = 171, matching exactly. The real main-checkout .vox/store.db was confirmed untouched throughout (unchanged file timestamp) — all measurement was done against isolated scratch copies/directories, cleaned up afterward.

What shipped: schema re-baselined from 219 to 171 default tables; 48 tables quarantined behind an opt-in quarantine Cargo feature (not deleted — reversible); a migration path for existing database files to drop the quarantined 47 (developer_journey_definitions excluded, pending manual export) with transactional all-or-nothing safety; 4 dead Rust struct types removed; two durable, re-runnable, fixture-tested VoxScript audit tools (scripts/db-table-census.vox, scripts/db-test-census.vox) as the recurrence-prevention mechanism design §3.6 called for; two forward-looking documentation guardrails (storage-boundary threshold, worktree-cleanup addendum).

What’s explicitly NOT done (by design, matching the plan’s stated scope): no CI gate wired to the census tool (a re-runnable tool exists; nothing yet requires re-running it before landing new schema); design §3.5’s graduation path (reviving a quarantined table) has no automation, just a documented 4-step manual procedure; migrate_dropping_quarantine is not wired into any automatic connect()/upgrade flow — it’s an explicit opt-in function a future caller must invoke deliberately, with its own backup discipline.