Files
zooqueenandHanzo Dev af9a9a98fb chat: retire the dual-write seam, and stop claiming a Mongo we do not have
The Mongo->SQLite cutover finished. chat-docdb is deleted, MONGO_URI is unset,
and all 29 domains are served from the embedded SQLite file on the PVC. What was
left behind was scaffolding that reads as live.

- Remove the CHAT_STORE_DUALWRITE seam. Phase 4 is done: the flag is unset in
  the live container, and with it unset applySqliteOverrides never constructed a
  DualWriteModel anyway. The mirror existed to keep Mongo current as a rollback
  target and there is no Mongo to roll back to, so the escape hatch was already
  unusable. DualWriteModel + its spec, the export, the flag branch, and the
  stale comments in Role/Transaction/token/session all go.
- Drop `logger.info('Connected to MongoDB')`. It fired unconditionally one line
  after connectDb() logged that it was skipping Mongo, so the boot log asserted
  a connection that had just been declined.
- Retarget the authStore SQLite spec from DualWriteModel to DocModel rather than
  deleting it. It is the regression proof for the P1 that broke cold logins; the
  coverage is worth keeping, only the model shape changed.
- Rewrite the LLM.md store section, which still described Mongo as the live
  parallel store and told the reader that ripping it means data loss.

express-mongo-sanitize STAYS, and the comment above it now says why: the SQLite
engine still interprets $eq/$ne/$in/$or/$regex in filters and $set/$inc/$push in
updates, so a {"$ne": null} reaching a filter is operator injection against
SQLite exactly as it was against Mongo. The guard outlived the database it is
named for. mongoose, mongoMeili and keyvMongo also stay -- see LLM.md for why
each is a migration rather than a sweep.

Verified: data-schemas rollup build clean, DualWrite absent from the bundle,
createModels resolves flagged collections to DocModel and unflagged to mongoose.
Store suite is identical to origin/main (same 5 pre-existing meili failures,
minus exactly the 10 dual-write tests removed).

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 16:27:29 -07:00

65 lines
2.5 KiB
JavaScript

/**
* CI test runner for @hanzochat/data-schemas.
*
* The spec files listed in ISOLATED instantiate the native `better-sqlite3-*`
* driver. Jest gives every spec file its own JS module realm, but the native
* addon is process-cached per worker, so cross-file state corrupts sibling
* in-memory databases (driver-agnostic — reproduces with mainstream
* better-sqlite3 too; a compound `json_extract` UNIQUE stops firing). Production
* is unaffected: it runs one module realm with one shared handle for the process
* lifetime. The fix is strict one-file-per-process isolation for those specs
* only — NOT `--runInBand`/`--maxWorkers=1` (a single shared worker still
* corrupts). Everything else runs in the normal coverage pass.
*/
import { spawnSync } from 'node:child_process';
import { createRequire } from 'node:module';
import { dirname, join } from 'node:path';
const require = createRequire(import.meta.url);
const JEST = join(dirname(require.resolve('jest/package.json')), 'bin', 'jest.js');
/** Native-driver specs — each run in its own process. */
const ISOLATED = [
'src/stores/sqlite/DocModel.spec.ts',
'src/stores/sqlite/meili.sqlite.spec.ts',
'src/models/storeRegistry.spec.ts',
'src/models/plugins/tenantIsolation.coverage.spec.ts',
'src/methods/convoMessage.sqlite.spec.ts',
'src/methods/distinct.sqlite.spec.ts',
'src/methods/skill.harness.sqlite.spec.ts',
'src/methods/batch2.sqlite.spec.ts',
'src/methods/batch3.sqlite.spec.ts',
'src/methods/batch4.sqlite.spec.ts',
'src/methods/batch5.sqlite.spec.ts',
'src/methods/batch6.sqlite.spec.ts',
'src/methods/batch7.sqlite.spec.ts',
'src/methods/batch7b.sqlite.spec.ts',
'src/methods/batch8a.sqlite.spec.ts',
'src/methods/batch8b.sqlite.spec.ts',
'src/methods/authStore.sqlite.spec.ts',
];
const runJest = (args) =>
spawnSync(process.execPath, [JEST, '--ci', ...args], { stdio: 'inherit' }).status === 0;
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
let ok = true;
// 1) Normal coverage run for everything except the isolated set.
console.log(`\n[ci] coverage run (excluding ${ISOLATED.length} native-driver specs)`);
const ignore = ['/node_modules/', ...ISOLATED.map((f) => escapeRegExp(f) + '$')];
if (!runJest(['--coverage', '--testPathIgnorePatterns', ...ignore])) {
ok = false;
}
// 2) Each native-driver spec in its own process.
for (const file of ISOLATED) {
console.log(`\n[ci] isolated: ${file}`);
if (!runJest([file])) {
ok = false;
}
}
process.exit(ok ? 0 : 1);