Verification — production deploy now ships migrations and fails loudly otherwise

Implementation commit: 5f4087b2b2504a099c73c32536babfebf61f87ea on branch feature/fix-migrations-in-dist.

Build-time evidence

npm run build happy path

$ rm -rf dist && npm run build

> colibri@0.0.1 build
> tsc

> colibri@0.0.1 postbuild
> node scripts/copy-migrations.mjs

copy-migrations: copied 6 migration(s) ...src/db/migrations -> ...dist/db/migrations

dist/db/migrations/ contents

$ ls dist/db/migrations/
001_init.sql
002_tasks.sql
003_thought_records.sql
004_skills.sql
005_retention.sql
006_eta.sql

All 6 expected migrations present.

Byte-identical copy

$ diff -r src/db/migrations dist/db/migrations
$ echo $?
0

No diff — src and dist migration directories are byte-identical.

Runtime evidence

Lint

$ npm run lint

> colibri@0.0.1 lint
> eslint src

$ echo $?
0

Clean.

Full test suite

$ npm test
...
Test Suites: 1 failed, 29 passed, 30 total
Tests:       1 failed, 1357 passed, 1358 total

1357 of 1358 passing. Net +1 test vs the pre-task baseline (1357 = 1356 prior + new prod-mode test). The single failure is the pre-existing flake startup — subprocess smoke › tsx src/server.ts boots and logs [Startup] Phase 1 documented in MEMORY.md (“predates Wave H; all 4 R77 executors hit it once, always green on rerun”).

Verified flake on isolated rerun:

$ npm test -- --testPathPattern='startup'
...
Test Suites: 1 passed, 1 total
Tests:       40 passed, 40 total

40/40 on the startup file in isolation — the flake is environmental, not a regression of this task.

New test in isolation

$ npm test -- --testPathPattern='db-init' --testNamePattern='NODE_ENV=production'
...
Test Suites: 1 passed, 1 total
Tests:       29 skipped, 1 passed, 30 total

The new test 'throws under NODE_ENV=production when migrations directory is missing' passes deterministically.

Coverage on src/db/index.ts

File          | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
index.ts      |     100 |    95.65 |     100 |     100 | 299

Statement / function / line coverage stays at 100%. Branch coverage moved from 95% (pre-task) to 95.65% — the new prod-mode guard is exercised on both arms (migrations.length === 0 true + false in covered tests; NODE_ENV === 'production' true in the new test, false in the existing missing-directory test).

Contract assertions verified

Build-time

Assertion Expected Actual Pass?
npm run build exit code on a clean tree 0 0
ls dist/db/migrations/*.sql \| wc -l 6 6
diff -r src/db/migrations dist/db/migrations empty empty
Build fails when src/db/migrations/ is missing non-zero (verified by reading scripts/copy-migrations.mjs:24-27)
Build fails when source dir contains zero .sql non-zero (verified by reading scripts/copy-migrations.mjs:30-33)

Runtime guard

Step Expected Actual Pass?
process.env.NODE_ENV = 'production' + empty migrations + initDb(p) throws throws via the new test
Error contains migrations directory not found required regex matches /migrations directory not found.../is
Error contains dist/db/migrations required included in regex
Error contains npm run build required included in regex
getDb() after failed init throws Database not initialized required second expect in the new test
Existing test at db-init.test.ts:428 still green required covered in full suite (1357/1358)
tsx dev path unaffected required NODE_ENV !== 'production' guard predicate, no tsx run touched

Header comment update

Assertion Expected Actual Pass?
Known limitation substring removed true confirmed via grep -n "Known limitation" src/db/index.ts returns nothing
New paragraph mentions scripts/copy-migrations.mjs and the runtime guard true lines 41-47 of the post-impl file include both

Manual cross-check

$ grep -nF "Known limitation" src/db/index.ts
$ grep -nF "scripts/copy-migrations.mjs" src/db/index.ts
42: * so `scripts/copy-migrations.mjs` runs as `npm postbuild` and copies
$ grep -nF "migrations directory not found" src/db/index.ts
269:      'Database boot aborted: migrations directory not found or empty ' +

Header comment + runtime guard both wired correctly.

Files changed in this task

File Status LOC delta
scripts/copy-migrations.mjs new +37
package.json modified (added postbuild) +1
src/db/index.ts modified (header comment + runtime guard) +14 / -7
src/__tests__/db-init.test.ts modified (new test) +24
docs/audits/fix-migrations-in-dist-audit.md new +106
docs/contracts/fix-migrations-in-dist-contract.md new +81
docs/packets/fix-migrations-in-dist-packet.md new +179
docs/verification/fix-migrations-in-dist-verification.md new (this file)

Five-step chain commits on branch feature/fix-migrations-in-dist:

  1. dd116ec4 — audit(fix-migrations-in-dist): inventory surface
  2. c26821d9 — contract(fix-migrations-in-dist): behavioral contract
  3. 8adf31a1 — packet(fix-migrations-in-dist): execution plan
  4. 5f4087b2 — feat(fix-migrations-in-dist): copy SQL migrations into dist + prod boot guard
  5. (this verification commit)

Acceptance criteria — round-trip

# Criterion Status
1 npm run build produces dist/db/migrations/*.sql with all 6 migrations
2 Runtime guard fails boot loudly under prod when migrations are empty (mentions “migrations directory not found” + build step)
3 tsx dev path unaffected; tests still run
4 New test asserts the prod-mode failure with the expected message
5 All existing tests still pass: build && lint && test ✓ (1357/1358; the 1 fail is the pre-existing startup-subprocess flake)
6 Header comment in src/db/index.ts:41-44 reflects the resolved limitation

All six acceptance criteria satisfied. No blockers.


Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.