From 71ee564ed78899ae0a8a0e7a486d659b89a4bf15 Mon Sep 17 00:00:00 2001 From: galuis116 Date: Fri, 24 Jul 2026 11:19:35 -0300 Subject: [PATCH] fix(miner): add orb-export to the doctor and migrate store lists (#8318) status.ts's storeIntegrityChecks and migrate-cli.ts's STORES are both meant to enumerate every durable local SQLite store in the package -- each file's own comment says to keep it in sync with the other. Both listed the same sixteen stores, but orb-export.sqlite3 (the opt-in Orb telemetry export's per-instance HMAC secret and export cursor, #4277/#5681) was never added when it shipped. The effect: a corrupted orb-export.sqlite3 was invisible to `loopover-miner doctor`'s per-store integrity sweep, and `loopover-miner migrate` never brought it up to date, unlike every other store the package ships. Same gap class already fixed for policy-doc-cache (#7238), ranked-candidates + deny-hook-synthesis (#8008/#8036), and four earlier omissions (#6768). Adds the store to both lists using each list's existing entry shape (no restructuring): ["orb-export", resolveOrbExportDbPath(env)] in status.ts and { name, resolveDbPath, open } in migrate-cli.ts. Both resolver/opener signatures already match the sibling entries, so no casts are needed. Updates the two tests that pin the lists exactly -- the migrate test's store-name array (now seventeen, same order) and the doctor test's store-integrity check names -- and adds a #8318 regression assertion beside the existing #6768/#8008 ones. --- packages/loopover-miner/lib/migrate-cli.ts | 4 ++++ packages/loopover-miner/lib/status.ts | 4 ++++ test/unit/miner-migrate-cli.test.ts | 6 +++++- test/unit/miner-status.test.ts | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/loopover-miner/lib/migrate-cli.ts b/packages/loopover-miner/lib/migrate-cli.ts index a8fffcc9c4..69797069ce 100644 --- a/packages/loopover-miner/lib/migrate-cli.ts +++ b/packages/loopover-miner/lib/migrate-cli.ts @@ -27,6 +27,7 @@ import { initPolicyVerdictCacheStore, resolvePolicyVerdictCacheDbPath } from "./ import { initPolicyDocCacheStore, resolvePolicyDocCacheDbPath } from "./policy-doc-cache.js"; import { initRankedCandidatesStore, resolveRankedCandidatesDbPath } from "./ranked-candidates.js"; import { initDenyHookSynthesisStore, resolveDenyHookSynthesisDbPath } from "./deny-hook-synthesis.js"; +import { openOrbExportStore, resolveOrbExportDbPath } from "./orb-export.js"; const MIGRATE_USAGE = "Usage: loopover-miner migrate [--json]"; @@ -80,6 +81,9 @@ const STORES: MigrateStoreDescriptor[] = [ { name: "policy-doc-cache", resolveDbPath: resolvePolicyDocCacheDbPath, open: initPolicyDocCacheStore }, { name: "ranked-candidates", resolveDbPath: resolveRankedCandidatesDbPath, open: initRankedCandidatesStore }, { name: "deny-hook-synthesis", resolveDbPath: resolveDenyHookSynthesisDbPath, open: initDenyHookSynthesisStore }, + // #8318: orb-export.sqlite3 (the opt-in Orb telemetry export's HMAC secret + cursor, #4277/#5681) is a + // durable local store like every entry above, but was never added when it shipped. + { name: "orb-export", resolveDbPath: resolveOrbExportDbPath, open: openOrbExportStore }, ]; /** Read a store file's stamped schema version without ever creating it -- matches checkStoreIntegrity's diff --git a/packages/loopover-miner/lib/status.ts b/packages/loopover-miner/lib/status.ts index 6b32fd91b1..d2e9f0b126 100644 --- a/packages/loopover-miner/lib/status.ts +++ b/packages/loopover-miner/lib/status.ts @@ -31,6 +31,7 @@ import { resolvePolicyVerdictCacheDbPath } from "./policy-verdict-cache.js"; import { resolvePolicyDocCacheDbPath } from "./policy-doc-cache.js"; import { resolveRankedCandidatesDbPath } from "./ranked-candidates.js"; import { resolveDenyHookSynthesisDbPath } from "./deny-hook-synthesis.js"; +import { resolveOrbExportDbPath } from "./orb-export.js"; // Slim laptop-mode CLI commands (#2288): `status` (what's installed + where local state lives) and `doctor` (is // this laptop set up correctly). Both are read-only and 100% local — no repo-scanning, no coding-agent invocation, @@ -381,6 +382,9 @@ function storeIntegrityChecks(env: Record): DoctorCh ["policy-doc-cache", resolvePolicyDocCacheDbPath(env)], ["ranked-candidates", resolveRankedCandidatesDbPath(env)], ["deny-hook-synthesis", resolveDenyHookSynthesisDbPath(env)], + // #8318: orb-export.sqlite3 (the opt-in Orb telemetry export's HMAC secret + cursor, #4277/#5681) is a + // durable local store like every entry above, but was never added when it shipped. + ["orb-export", resolveOrbExportDbPath(env)], ]; return stores.map(([name, dbPath]) => checkStoreIntegrity(`store-integrity:${name}`, dbPath)); } diff --git a/test/unit/miner-migrate-cli.test.ts b/test/unit/miner-migrate-cli.test.ts index 2b5b57341a..87918f120f 100644 --- a/test/unit/miner-migrate-cli.test.ts +++ b/test/unit/miner-migrate-cli.test.ts @@ -34,6 +34,7 @@ const STORE_NAMES = [ "policy-doc-cache", "ranked-candidates", "deny-hook-synthesis", + "orb-export", ]; afterEach(() => { @@ -42,7 +43,7 @@ afterEach(() => { }); describe("loopover-miner migrate (#4871)", () => { - it("covers the exact same sixteen stores doctor's store-integrity sweep covers, in the same order, and skips every one when nothing has been created yet", () => { + it("covers the exact same seventeen stores doctor's store-integrity sweep covers, in the same order, and skips every one when nothing has been created yet", () => { const env = tempEnv(); const results = runMigrateChecks(env); @@ -51,6 +52,9 @@ describe("loopover-miner migrate (#4871)", () => { expect(STORE_NAMES).toEqual(expect.arrayContaining(["governor-state", "attempt-log", "replay-snapshot", "worktree-allocator"])); // REGRESSION (#8008): ranked-candidates and deny-hook-synthesis were likewise omitted from both lists. expect(STORE_NAMES).toEqual(expect.arrayContaining(["ranked-candidates", "deny-hook-synthesis"])); + // REGRESSION (#8318): orb-export.sqlite3 (the opt-in Orb telemetry export's HMAC secret + cursor) was + // never added to either list when it shipped, so a corrupted store was invisible to doctor and migrate. + expect(STORE_NAMES).toEqual(expect.arrayContaining(["orb-export"])); for (const result of results) { expect(result.ok).toBe(true); expect(result.status).toBe("skipped"); diff --git a/test/unit/miner-status.test.ts b/test/unit/miner-status.test.ts index 2af943679d..b60a27016e 100644 --- a/test/unit/miner-status.test.ts +++ b/test/unit/miner-status.test.ts @@ -145,6 +145,7 @@ describe("loopover-miner status/doctor (#2288)", () => { "store-integrity:policy-doc-cache", "store-integrity:ranked-candidates", "store-integrity:deny-hook-synthesis", + "store-integrity:orb-export", ]); // REGRESSION (#6768): doctor previously omitted these four durable local stores from the integrity sweep. expect(checks.map((check) => check.name)).toEqual(