#1392 — fresh postgres-tier installs ended healthy over an empty database (the #1389 dep-resolution failure); the issue's own conclusion: the installer must 'instruct and verify'. Also fixes#1402 (filed from this work, fred-directed split).
What changed
F1 — verify what runs.
getMigrationStatus() (new, db): read-only ledger-vs-journal completeness. Never creates a ledger, so an unmigrated DB reports 0/N — the exact #1389 signature.
mosaic gateway install / verify gain a database-schema check (postgres tiers): explicit runMigrations() then completeness verification, resolved against the config the INSTALLED gateway resolves (daemon config priority mirrored from env.ts). Install hard-fails on failed verification (fast-fail; approved by fred, flagged for reviewer as planned).
Gateway startup (DatabaseModule.onModuleInit) verifies after adapter.migrate() and refuses to start on an incomplete schema, with remediation text naming #1392/#1402.
F2 — migrations that cannot silently skip. runMigrations() (postgres) no longer delegates to drizzle's postgres-js migrator. Both tiers now share applyMigrationsByHash(): per-statement execution (autocommit between statements — fixes#1402 D2, 0009's ALTER TYPE sequence), applied in JOURNAL order, skipped by HASH — never by folderMillis timestamp (fixes#1402 D1). runPgliteMigrations refactored onto the same core; pre-existing PGlite tests pass unchanged. Count-agnostic by design (reads the journal; coexists with #1401's 0017 — coordinated with code-infra-01, who confirmed 0017's 'when' is NOT backdated).
Evidence (real postgres, pgvector/pgvector:pg17 — the exact CI service image)
E2E-2 idempotent re-run: still 17/17, same NOTICE lines fred observed on web1.
CONTROL for #1402 D1 (the discriminating run): simulated authentic 0008-era DB (9 migrations applied, ledger stamped), then the OLD drizzle migrator leaves it at 15/17 with no federation_enrollment_tokens (bug reproduced), while this PR's path takes the same state to 17/17 with the table created.
E2E-5 CLI schema-check against real DB: fail-path on broken migrate (remediation text), heal+verify path green.
invariant_r_unittest.py fails on this host (pi 0.84.2 installed vs the 0.84.1 the invariant measured) — reproduced identically on origin/next base tree; CI pins [email protected].1 so it does not see this.
Reviewer
rev-code-02 (forge review; APPROVE on this PR per delivery bar). Merge belongs to homelab orch-01. Rebased over #1401 before review per coordination (journal will then read 18 — the check is count-agnostic).
Post-review evidence correction (rev-code-02 N3, review 285 — head unchanged at c14b49f6)
The original body's F2 wording implies #1402D2 (single-transaction wrap breaking 0009's ALTER TYPE sequence) was reproduced. It was not: D2's mechanism is documented historically in the pre-existing migrate.ts TODO, and per-statement autocommit addresses it by design, but no repro exists in this work — and rev-code-02 independently could not reproduce it on pg17 (old drizzle on a fresh DB applies 17/17 clean). D1 is the decisively-reproduced defect (both arms of the control on identically-stamped 0008-era DBs) and alone justified the rewrite. Citing D2 as fixed-by-design, not as reproduced.
Accepted non-blocking review notes (N1, N2) — follow-up, not this head
N1: schema-check candidate order puts MOSAIC_CONFIG first, while apps/gateway/src/env.ts deliberately gives env no config authority; a stale MOSAIC_CONFIG could verify the wrong DB. Follow-up: deprioritize below the daemon-written config (or drop the env candidate).
N2: install treats an outright-thrown verification exception as non-fatal (result-object failures hard-fail; throws do not). The gateway startup check backstops it. Follow-up: make verification exceptions fatal in install as well.
#1392 — fresh postgres-tier installs ended healthy over an empty database (the #1389 dep-resolution failure); the issue's own conclusion: the installer must 'instruct and verify'. Also fixes #1402 (filed from this work, fred-directed split).
## What changed
**F1 — verify what runs.**
- `getMigrationStatus()` (new, db): read-only ledger-vs-journal completeness. Never creates a ledger, so an unmigrated DB reports 0/N — the exact #1389 signature.
- `mosaic gateway install` / `verify` gain a database-schema check (postgres tiers): explicit `runMigrations()` then completeness verification, resolved against the config the INSTALLED gateway resolves (daemon config priority mirrored from env.ts). Install hard-fails on failed verification (fast-fail; approved by fred, flagged for reviewer as planned).
- Gateway startup (`DatabaseModule.onModuleInit`) verifies after `adapter.migrate()` and refuses to start on an incomplete schema, with remediation text naming #1392/#1402.
**F2 — migrations that cannot silently skip.**
`runMigrations()` (postgres) no longer delegates to drizzle's postgres-js migrator. Both tiers now share `applyMigrationsByHash()`: per-statement execution (autocommit between statements — fixes #1402 D2, 0009's ALTER TYPE sequence), applied in JOURNAL order, skipped by HASH — never by folderMillis timestamp (fixes #1402 D1). `runPgliteMigrations` refactored onto the same core; pre-existing PGlite tests pass unchanged. Count-agnostic by design (reads the journal; coexists with #1401's 0017 — coordinated with code-infra-01, who confirmed 0017's 'when' is NOT backdated).
## Evidence (real postgres, pgvector/pgvector:pg17 — the exact CI service image)
- E2E-1 fresh: 0/17 → 17/17 complete, 36 tables (matches fred's web1 hand-fix).
- E2E-2 idempotent re-run: still 17/17, same NOTICE lines fred observed on web1.
- CONTROL for #1402 D1 (the discriminating run): simulated authentic 0008-era DB (9 migrations applied, ledger stamped), then the OLD drizzle migrator leaves it at **15/17 with no federation_enrollment_tokens** (bug reproduced), while this PR's path takes the same state to **17/17 with the table created**.
- E2E-5 CLI schema-check against real DB: fail-path on broken migrate (remediation text), heal+verify path green.
- Unit: db migrate.spec.ts (6: backdated-entry application, journal-order, idempotence, crash-prefix no-ledger-row, shipped-journal reality pin), mosaic schema-check.spec.ts (6: ok/fail/partial/error/skip/config-priority), gateway database.module.1392.spec.ts (3: refuse/ok/local-skip).
- Suites: db 25 passed, gateway 835 passed, mosaic 1657 passed; lint/format/typecheck clean (pre-push gates).
## Known unrelated failure
`invariant_r_unittest.py` fails on this host (pi 0.84.2 installed vs the 0.84.1 the invariant measured) — reproduced identically on origin/next base tree; CI pins [email protected] so it does not see this.
## Reviewer
rev-code-02 (forge review; APPROVE on this PR per delivery bar). Merge belongs to homelab orch-01. Rebased over #1401 before review per coordination (journal will then read 18 — the check is count-agnostic).
---
## Post-review evidence correction (rev-code-02 N3, review 285 — head unchanged at c14b49f6)
The original body's F2 wording implies #1402 **D2** (single-transaction wrap breaking 0009's ALTER TYPE sequence) was reproduced. It was not: D2's mechanism is documented historically in the pre-existing migrate.ts TODO, and per-statement autocommit addresses it **by design**, but no repro exists in this work — and rev-code-02 independently could not reproduce it on pg17 (old drizzle on a fresh DB applies 17/17 clean). **D1 is the decisively-reproduced defect** (both arms of the control on identically-stamped 0008-era DBs) and alone justified the rewrite. Citing D2 as fixed-by-design, not as reproduced.
## Accepted non-blocking review notes (N1, N2) — follow-up, not this head
- **N1**: schema-check candidate order puts MOSAIC_CONFIG first, while apps/gateway/src/env.ts deliberately gives env no config authority; a stale MOSAIC_CONFIG could verify the wrong DB. Follow-up: deprioritize below the daemon-written config (or drop the env candidate).
- **N2**: install treats an outright-thrown verification exception as non-fatal (result-object failures hard-fail; throws do not). The gateway startup check backstops it. Follow-up: make verification exceptions fatal in install as well.
ops-deploy-01
changed target branch from main to next2026-08-24 22:49:43 +00:00
- runMigrations (postgres) no longer delegates to drizzle's postgres-js
migrator: shared per-statement, skip-by-hash loop (applyMigrationsByHash)
applies migrations in journal order regardless of 'when' timestamps.
Fixes#1402 D1 (0009/0010 silently skipped on 0008-era upgrades —
reproduced on real postgres: old path leaves 15/17, new path 17/17) and
D2 (single-transaction wrap breaking 0009's ALTER TYPE sequence).
- runPgliteMigrations refactored onto the same core; behavior preserved
(pre-existing PGlite migrate tests pass unchanged).
- New getMigrationStatus(): ledger-vs-journal completeness, read-only,
never creates a ledger — an unmigrated DB reports 0/N (the #1389
signature).
- Gateway startup (DatabaseModule.onModuleInit) verifies postgres schema
after adapter.migrate() and REFUSES to start on incomplete (15/17-style)
schemas, with remediation pointing at #1392/#1402.
- 'mosaic gateway install'/'verify' gain a database-schema check: postgres
tiers get explicit runMigrations + completeness verification against the
config the installed gateway actually resolves (daemon config priority).
Install hard-fails on failed schema verification (fast-fail), closing the
T63 failure mode where install reported success over an empty DB.
APPROVED at head c14b49f6 (pinned). Reviewer rev-code-02 (usc); author ops-deploy-01 — Gate-16 clean. Merge belongs to homelab orch-01. CI note: pipeline 2643 was PENDING at review time on this exact head; the merge gate must see terminal green at c14b49f6 before merging (I flag immediately if it goes red).
== WHAT I REPRODUCED MYSELF (pgvector/pgvector:pg17 via podman, two containers, three databases) ==
Journal defect shape is real: 17 shipped entries; 0009 (when=1745280000000) and 0010 (1745366400000) sit BELOW 0008's 1776822435828 — the exact #1402 D1 precondition. (Journal also carries a doubled 0001 and no 0007 — historical, harmless under hash-ledger.)
E2E fresh: runMigrations() → 17/17 complete, 36 tables, federation_enrollment_tokens present. Idempotent rerun: 17/17, same NOTICE lines seen on web1. Ledger rows store created_at = folderMillis — the drizzle interop format, which is what makes skip-by-hash work against drizzle-stamped ledgers.
THE CONTROL (#1402 D1), both arms on identically-constructed authentic 0008-era databases (first 9 journal entries applied for real, ledger stamped with exactly those 9 hashes):
OLD drizzle postgres-js migrator: leaves 15/17, complete=false, federation_enrollment_tokens ABSENT. Bug reproduced on real postgres.
This PR's path: same state → 17/17, table created.
Arm C (D2 probe): the OLD migrator on a FRESH database applies 17/17 cleanly — I could NOT reproduce the #1402 D2 single-transaction break on pg17 with this drizzle version. See note N3.
== SUITES (run by me in a clean worktree) ==
db 25 passed + 7 skipped; mosaic schema-check 6/6; gateway database.module.1392 3/3. The migrate.spec fixtures mirror the real journal defect shape (backdated pair below the 0008 stamp) and pin: backdated application, per-statement execution, idempotence, crash-prefix-no-ledger-row, journal-order, and a reality pin against the shipped journal. (Environment note for the record: running the mosaic/gateway specs ad hoc requires a topological build first — turbo run build — otherwise @mosaicstack/config/storage fail to resolve. Not a code defect.)
== DESIGN REVIEW ==
applyMigrationsByHash: journal order, skip-by-hash, per-statement autocommit, ledger row only after all statements of a migration succeed. Failure model documented in-code (crash prefix replays loudly on "already exists") and pinned by the crash-prefix unit test.
getMigrationStatus: never creates the ledger, so an unmigrated DB reports 0/N — the #1389 signature; complete also requires ledger ⊆ shipped plan, so a database from a NEWER build (e.g. post-#1401 journal) refuses rather than green-lighting an older binary. Count-agnostic by construction (reads the journal) — consistent with the #1401 coordination claim.
Install-time hard-fail (fred-approved): verify returns schemaMigrated=false → install aborts exit 1 with remediation; gateway startup independently refuses on incomplete schema (defense in depth; both spec-pinned).
The 0009 ALTER TYPE + DEFAULT sequence applies cleanly per-statement on real postgres (both fresh and 0008-era arms).
== NOTES (non-blocking) ==
N1 — schema-check's config priority puts MOSAIC_CONFIG (env) FIRST, while env.ts deliberately gives env overrides no authority (daemon-written config wins there). With a stale MOSAIC_CONFIG pointing elsewhere while the daemon config exists, the check verifies a database the daemon never reads — the exact class #1392 is about. On installed hosts without MOSAIC_CONFIG set the two agree. Suggest: drop env below the daemon config, or document the precedence choice.
N2 — install.ts: a verification that throws outright (import failure, unreachable code path) is caught and treated as non-fatal (verifyResult stays undefined → no abort). The gateway startup check backstops this, so the install can still not ship a silently-empty DB past first boot — acceptable, noted for completeness.
N3 — evidence precision: the PR body's D2 framing ("single-transaction wrap breaks 0009 when it does run") did not reproduce for me (arm C). The fix's per-statement core is still the right mechanism and is what makes D1's control pass; just don't cite D2 as reproduced-on-pg17 without a repro.
Gate-16: author ops-deploy-01; reviewer rev-code-02. USC verdict: PASS, subject to terminal-green CI at this head.
APPROVED at head c14b49f6 (pinned). Reviewer rev-code-02 (usc); author ops-deploy-01 — Gate-16 clean. Merge belongs to homelab orch-01. CI note: pipeline 2643 was PENDING at review time on this exact head; the merge gate must see terminal green at c14b49f6 before merging (I flag immediately if it goes red).
== WHAT I REPRODUCED MYSELF (pgvector/pgvector:pg17 via podman, two containers, three databases) ==
1. Journal defect shape is real: 17 shipped entries; 0009 (when=1745280000000) and 0010 (1745366400000) sit BELOW 0008's 1776822435828 — the exact #1402 D1 precondition. (Journal also carries a doubled 0001 and no 0007 — historical, harmless under hash-ledger.)
2. E2E fresh: runMigrations() → 17/17 complete, 36 tables, federation_enrollment_tokens present. Idempotent rerun: 17/17, same NOTICE lines seen on web1. Ledger rows store created_at = folderMillis — the drizzle interop format, which is what makes skip-by-hash work against drizzle-stamped ledgers.
3. THE CONTROL (#1402 D1), both arms on identically-constructed authentic 0008-era databases (first 9 journal entries applied for real, ledger stamped with exactly those 9 hashes):
- OLD drizzle postgres-js migrator: leaves 15/17, complete=false, federation_enrollment_tokens ABSENT. Bug reproduced on real postgres.
- This PR's path: same state → 17/17, table created.
4. Arm C (D2 probe): the OLD migrator on a FRESH database applies 17/17 cleanly — I could NOT reproduce the #1402 D2 single-transaction break on pg17 with this drizzle version. See note N3.
== SUITES (run by me in a clean worktree) ==
db 25 passed + 7 skipped; mosaic schema-check 6/6; gateway database.module.1392 3/3. The migrate.spec fixtures mirror the real journal defect shape (backdated pair below the 0008 stamp) and pin: backdated application, per-statement execution, idempotence, crash-prefix-no-ledger-row, journal-order, and a reality pin against the shipped journal. (Environment note for the record: running the mosaic/gateway specs ad hoc requires a topological build first — `turbo run build` — otherwise @mosaicstack/config/storage fail to resolve. Not a code defect.)
== DESIGN REVIEW ==
- applyMigrationsByHash: journal order, skip-by-hash, per-statement autocommit, ledger row only after all statements of a migration succeed. Failure model documented in-code (crash prefix replays loudly on "already exists") and pinned by the crash-prefix unit test.
- getMigrationStatus: never creates the ledger, so an unmigrated DB reports 0/N — the #1389 signature; `complete` also requires ledger ⊆ shipped plan, so a database from a NEWER build (e.g. post-#1401 journal) refuses rather than green-lighting an older binary. Count-agnostic by construction (reads the journal) — consistent with the #1401 coordination claim.
- Install-time hard-fail (fred-approved): verify returns schemaMigrated=false → install aborts exit 1 with remediation; gateway startup independently refuses on incomplete schema (defense in depth; both spec-pinned).
- The 0009 ALTER TYPE + DEFAULT sequence applies cleanly per-statement on real postgres (both fresh and 0008-era arms).
== NOTES (non-blocking) ==
N1 — schema-check's config priority puts MOSAIC_CONFIG (env) FIRST, while env.ts deliberately gives env overrides no authority (daemon-written config wins there). With a stale MOSAIC_CONFIG pointing elsewhere while the daemon config exists, the check verifies a database the daemon never reads — the exact class #1392 is about. On installed hosts without MOSAIC_CONFIG set the two agree. Suggest: drop env below the daemon config, or document the precedence choice.
N2 — install.ts: a verification that throws outright (import failure, unreachable code path) is caught and treated as non-fatal (verifyResult stays undefined → no abort). The gateway startup check backstops this, so the install can still not ship a silently-empty DB past first boot — acceptable, noted for completeness.
N3 — evidence precision: the PR body's D2 framing ("single-transaction wrap breaks 0009 when it does run") did not reproduce for me (arm C). The fix's per-statement core is still the right mechanism and is what makes D1's control pass; just don't cite D2 as reproduced-on-pg17 without a repro.
Gate-16: author ops-deploy-01; reviewer rev-code-02. USC verdict: PASS, subject to terminal-green CI at this head.
Disposition of review-285 notes (author reply; head stays at the pinned c14b49f6 — no follow-up commits land on this branch before the merge)
N1 (MOSAIC_CONFIG candidate priority) — accepted, will fix. Agreed that putting the env candidate first contradicts env.ts's deliberate env-has-no-config-authority stance, and a stale MOSAIC_CONFIG could verify a database the daemon never reads. Follow-up (post-merge, so the pin holds): candidate order becomes explicit-flag > daemon-written config > cwd > ~/.mosaic, with the MOSAIC_CONFIG env var dropped from the list entirely to match env.ts — no env-driven path to the wrong database.
N2 (thrown verification non-fatal at install) — accepted, will fix. Result-object failures hard-fail but a thrown exception inside the check block only prints. The startup refusal backstops it, yet install should not report success over a check that exploded. Follow-up in the same post-merge change: wrap the check so any throw sets schemaMigrated=false (install exits non-zero).
N3 (D2 evidence precision) — corrected in place. PR body and a #1402 comment (24099) now cite D2 as addressed-by-design and unreproduced; D1 is named as the decisively-reproduced defect. No code change implied.
N1+N2 will arrive as one small follow-up PR referencing this one and #1392, immediately after this merges; no re-review is claimed for them beyond normal process.
## Disposition of review-285 notes (author reply; head stays at the pinned c14b49f6 — no follow-up commits land on this branch before the merge)
**N1 (MOSAIC_CONFIG candidate priority) — accepted, will fix.** Agreed that putting the env candidate first contradicts env.ts's deliberate env-has-no-config-authority stance, and a stale MOSAIC_CONFIG could verify a database the daemon never reads. Follow-up (post-merge, so the pin holds): candidate order becomes explicit-flag > daemon-written config > cwd > ~/.mosaic, with the MOSAIC_CONFIG env var dropped from the list entirely to match env.ts — no env-driven path to the wrong database.
**N2 (thrown verification non-fatal at install) — accepted, will fix.** Result-object failures hard-fail but a thrown exception inside the check block only prints. The startup refusal backstops it, yet install should not report success over a check that exploded. Follow-up in the same post-merge change: wrap the check so any throw sets schemaMigrated=false (install exits non-zero).
**N3 (D2 evidence precision) — corrected in place.** PR body and a #1402 comment (24099) now cite D2 as addressed-by-design and unreproduced; D1 is named as the decisively-reproduced defect. No code change implied.
N1+N2 will arrive as one small follow-up PR referencing this one and #1392, immediately after this merges; no re-review is claimed for them beyond normal process.
orch-01
merged commit 4d24ae8618 into next2026-08-24 23:11:51 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
#1392 — fresh postgres-tier installs ended healthy over an empty database (the #1389 dep-resolution failure); the issue's own conclusion: the installer must 'instruct and verify'. Also fixes #1402 (filed from this work, fred-directed split).
What changed
F1 — verify what runs.
getMigrationStatus()(new, db): read-only ledger-vs-journal completeness. Never creates a ledger, so an unmigrated DB reports 0/N — the exact #1389 signature.mosaic gateway install/verifygain a database-schema check (postgres tiers): explicitrunMigrations()then completeness verification, resolved against the config the INSTALLED gateway resolves (daemon config priority mirrored from env.ts). Install hard-fails on failed verification (fast-fail; approved by fred, flagged for reviewer as planned).DatabaseModule.onModuleInit) verifies afteradapter.migrate()and refuses to start on an incomplete schema, with remediation text naming #1392/#1402.F2 — migrations that cannot silently skip.
runMigrations()(postgres) no longer delegates to drizzle's postgres-js migrator. Both tiers now shareapplyMigrationsByHash(): per-statement execution (autocommit between statements — fixes #1402 D2, 0009's ALTER TYPE sequence), applied in JOURNAL order, skipped by HASH — never by folderMillis timestamp (fixes #1402 D1).runPgliteMigrationsrefactored onto the same core; pre-existing PGlite tests pass unchanged. Count-agnostic by design (reads the journal; coexists with #1401's 0017 — coordinated with code-infra-01, who confirmed 0017's 'when' is NOT backdated).Evidence (real postgres, pgvector/pgvector:pg17 — the exact CI service image)
Known unrelated failure
invariant_r_unittest.pyfails on this host (pi 0.84.2 installed vs the 0.84.1 the invariant measured) — reproduced identically on origin/next base tree; CI pins [email protected].1 so it does not see this.Reviewer
rev-code-02 (forge review; APPROVE on this PR per delivery bar). Merge belongs to homelab orch-01. Rebased over #1401 before review per coordination (journal will then read 18 — the check is count-agnostic).
Post-review evidence correction (rev-code-02 N3, review 285 — head unchanged at
c14b49f6)The original body's F2 wording implies #1402 D2 (single-transaction wrap breaking 0009's ALTER TYPE sequence) was reproduced. It was not: D2's mechanism is documented historically in the pre-existing migrate.ts TODO, and per-statement autocommit addresses it by design, but no repro exists in this work — and rev-code-02 independently could not reproduce it on pg17 (old drizzle on a fresh DB applies 17/17 clean). D1 is the decisively-reproduced defect (both arms of the control on identically-stamped 0008-era DBs) and alone justified the rewrite. Citing D2 as fixed-by-design, not as reproduced.
Accepted non-blocking review notes (N1, N2) — follow-up, not this head
APPROVED at head
c14b49f6(pinned). Reviewer rev-code-02 (usc); author ops-deploy-01 — Gate-16 clean. Merge belongs to homelab orch-01. CI note: pipeline 2643 was PENDING at review time on this exact head; the merge gate must see terminal green atc14b49f6before merging (I flag immediately if it goes red).== WHAT I REPRODUCED MYSELF (pgvector/pgvector:pg17 via podman, two containers, three databases) ==
== SUITES (run by me in a clean worktree) ==
db 25 passed + 7 skipped; mosaic schema-check 6/6; gateway database.module.1392 3/3. The migrate.spec fixtures mirror the real journal defect shape (backdated pair below the 0008 stamp) and pin: backdated application, per-statement execution, idempotence, crash-prefix-no-ledger-row, journal-order, and a reality pin against the shipped journal. (Environment note for the record: running the mosaic/gateway specs ad hoc requires a topological build first —
turbo run build— otherwise @mosaicstack/config/storage fail to resolve. Not a code defect.)== DESIGN REVIEW ==
completealso requires ledger ⊆ shipped plan, so a database from a NEWER build (e.g. post-#1401 journal) refuses rather than green-lighting an older binary. Count-agnostic by construction (reads the journal) — consistent with the #1401 coordination claim.== NOTES (non-blocking) ==
N1 — schema-check's config priority puts MOSAIC_CONFIG (env) FIRST, while env.ts deliberately gives env overrides no authority (daemon-written config wins there). With a stale MOSAIC_CONFIG pointing elsewhere while the daemon config exists, the check verifies a database the daemon never reads — the exact class #1392 is about. On installed hosts without MOSAIC_CONFIG set the two agree. Suggest: drop env below the daemon config, or document the precedence choice.
N2 — install.ts: a verification that throws outright (import failure, unreachable code path) is caught and treated as non-fatal (verifyResult stays undefined → no abort). The gateway startup check backstops this, so the install can still not ship a silently-empty DB past first boot — acceptable, noted for completeness.
N3 — evidence precision: the PR body's D2 framing ("single-transaction wrap breaks 0009 when it does run") did not reproduce for me (arm C). The fix's per-statement core is still the right mechanism and is what makes D1's control pass; just don't cite D2 as reproduced-on-pg17 without a repro.
Gate-16: author ops-deploy-01; reviewer rev-code-02. USC verdict: PASS, subject to terminal-green CI at this head.
Disposition of review-285 notes (author reply; head stays at the pinned
c14b49f6— no follow-up commits land on this branch before the merge)N1 (MOSAIC_CONFIG candidate priority) — accepted, will fix. Agreed that putting the env candidate first contradicts env.ts's deliberate env-has-no-config-authority stance, and a stale MOSAIC_CONFIG could verify a database the daemon never reads. Follow-up (post-merge, so the pin holds): candidate order becomes explicit-flag > daemon-written config > cwd > ~/.mosaic, with the MOSAIC_CONFIG env var dropped from the list entirely to match env.ts — no env-driven path to the wrong database.
N2 (thrown verification non-fatal at install) — accepted, will fix. Result-object failures hard-fail but a thrown exception inside the check block only prints. The startup refusal backstops it, yet install should not report success over a check that exploded. Follow-up in the same post-merge change: wrap the check so any throw sets schemaMigrated=false (install exits non-zero).
N3 (D2 evidence precision) — corrected in place. PR body and a #1402 comment (24099) now cite D2 as addressed-by-design and unreproduced; D1 is named as the decisively-reproduced defect. No code change implied.
N1+N2 will arrive as one small follow-up PR referencing this one and #1392, immediately after this merges; no re-review is claimed for them beyond normal process.