Skip to content

feat(family-mongo): add live introspection and wire CLI commands#334

Merged
wmadden merged 38 commits intomainfrom
tml-2233-m4-online-cli-commands-live-introspection
Apr 14, 2026
Merged

feat(family-mongo): add live introspection and wire CLI commands#334
wmadden merged 38 commits intomainfrom
tml-2233-m4-online-cli-commands-live-introspection

Conversation

@wmadden
Copy link
Copy Markdown
Contributor

@wmadden wmadden commented Apr 13, 2026

closes TML-2233

Intent

Enable the MongoDB family to participate in all live-database CLI commands (db schema, db verify, db sign) by implementing live schema introspection, schema verification with strict mode, and marker-based contract signing. This is the foundation that the remaining M4 commands (db init, db update, migration status --db) will build on.

Change map

The story

  1. Live introspection: introspectSchema(db) reads a live MongoDB instance via listCollections and listIndexes, producing a MongoSchemaIR. It filters internal collections (_prisma_migrations, system.*, views) and the default _id index.

  2. Schema diffing: diffMongoSchemas(live, expected, strict) compares two MongoSchemaIR instances and produces a structured SchemaVerificationNode tree with SchemaIssue classifications. Strict mode escalates "extra" elements (collections, indexes, validators, options in the DB but not in the contract) from warn to fail, consistent with SQL family behavior.

  3. Family instance wiring: MongoControlFamilyInstance implements the full ControlFamilyInstance<'mongo', MongoSchemaIR> interface — verify (marker-only), schemaVerify (live diff), sign (CAS marker write), readMarker, introspect, and toSchemaView.

  4. CLI generalization: inspect-live-schema.ts is widened so non-SQL families pass their schema IR through directly (SQL continues through validatePrintableSqlSchemaIR). The InspectLiveSchemaResult.schema type becomes unknown. This is tracked as tech debt for full removal in TML-2251.

  5. CLI e2e tests: Three test files exercise the actual Commander command implementations for db schema, db verify, and db sign with a live mongodb-memory-server instance and fixture config.

Behavior changes & evidence

Compatibility / migration / risk

  • InspectLiveSchemaResult.schema widened to unknown: The only downstream consumer is contract-infer.ts (SQL-only), which now uses an explicit cast. No runtime behavior change.
  • No breaking changes to existing SQL paths: All SQL tests continue to pass unchanged.
  • familyId === 'sql' branch in framework code: This is an interim step. Full removal is tracked in TML-2251.

Follow-ups / open questions

  • TML-2251: Remove SQL-specific branching from inspect-live-schema.ts — migrate SQL to the family-agnostic path and remove the familyId === 'sql' conditional.
  • sign() method vs CLI db sign command: The family method is marker-only; the CLI command composes schemaVerify() + sign(). The M4 plan language should clarify this distinction.
  • Remaining M4 commands: db init, db update, migration status --db, and migration show are not yet implemented.

Non-goals / intentionally out of scope

  • contract infer for MongoDB: Would require Mongo-to-PSL reverse mapping.
  • Shared diffing between schema-verify and the planner: The planner diff (for migration planning) and the verify diff (for verification) solve overlapping problems but have different output requirements. Unifying them is a separate design decision.
  • Full removal of SQL coupling from framework CLI: Deferred to TML-2251.

Summary by CodeRabbit

  • New Features

    • Full MongoDB support: live DB introspection, canonical schema IR, human-readable schema view, schema diffing, and db schema / db sign / db verify CLI commands.
  • Bug Fixes

    • CLI now rejects non‑SQL targets early and returns clearer structured errors for unsupported targets.
    • Verification and error reporting use standardized codes for clearer diagnostics.
  • Refactor

    • More consistent, deterministic schema representation and view rendering.
  • Tests

    • Extensive unit, integration, and end‑to‑end coverage for Mongo flows and CLI JSON/plain outputs.
  • Chores

    • Documentation, rulecards, test fixtures, and package exports updated for Mongo tooling.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Implements runtime Mongo schema IR and visitor, live Mongo introspection, schema→view conversion, Mongo schema diffing, concrete Mongo control methods (verify/schemaVerify/sign/introspect) with marker persistence, CLI SQL-target/IR validation, and extensive unit and e2e tests and packaging/config updates.

Changes

Cohort / File(s) Summary
CLI & inspect
packages/1-framework/3-tooling/cli/src/commands/contract-infer.ts, packages/1-framework/3-tooling/cli/src/commands/inspect-live-schema.ts, packages/1-framework/3-tooling/cli/test/commands/inspect-live-schema.test.ts
contract-infer now rejects non-SQL targets early and validates/normalizes SQL schema IR; inspectLiveSchema changes schema typing to unknown and applies SQL-only validation; added non-SQL passthrough test.
Framework schema view & types
packages/1-framework/1-core/framework-components/src/control-schema-view.ts, .../control-capabilities.ts, .../control-instances.ts, .../control-migration-types.ts, .../control-result-types.ts, .../exports/control.ts
Replaced SchemaTreeNode interface with runtime SchemaTreeNode class + visitor API; tightened ControlFamilyInstance generics to require TSchemaIR; added verification code constants and updated related exports/type guards.
CLI control-api typing & tests
packages/1-framework/3-tooling/cli/src/control-api/..., .../client.ts, test updates under packages/1-framework/3-tooling/cli/test/*
Propagated ControlFamilyInstance<..., unknown> across control-api option types and updated tests/mocks to match new generic parameterization.
Mongo schema IR (runtime) & tooling
packages/2-mongo-family/3-tooling/mongo-schema-ir/src/schema-ir.ts, .../types.ts, .../visitor.ts, .../exports/index.ts, .../test/schema-ir.test.ts, .../README.md
Converted MongoSchemaIR from type to runtime class with sorted collections, lookup (collection(name)), collectionNames, visitor support; updated types, exports, tests, and README.
Mongo family core & view
packages/2-mongo-family/9-family/src/core/control-instance.ts, packages/2-mongo-family/9-family/src/core/schema-to-view.ts, packages/2-mongo-family/9-family/test/control.test.ts, packages/2-mongo-family/9-family/package.json
Implemented Mongo control instance methods (verify, schemaVerify, sign, introspect) wired to adapter, CAS marker flows, added mongoSchemaToView converter and tests; added runtime deps.
Schema diffing
packages/2-mongo-family/9-family/src/core/schema-diff.ts, packages/2-mongo-family/9-family/test/schema-diff.test.ts
Added diffMongoSchemas(live, expected, strict) with collection/index/validator/options comparators, issue reporting and aggregate counts; unit tests for strict vs lenient behaviors.
Mongo adapter introspection & control exports
packages/3-mongo-target/2-mongo-adapter/src/core/introspect-schema.ts, packages/3-mongo-target/2-mongo-adapter/src/exports/control.ts, packages/3-mongo-target/2-mongo-adapter/test/introspect-schema.test.ts
Added introspectSchema(db): MongoSchemaIR (filters system/_prisma_migrations/views, omits default _id index), re-exported it, and added integration tests against in-memory Mongo.
Target control / marker ledger
packages/3-mongo-target/1-mongo-target/src/core/marker-ledger.ts, packages/3-mongo-target/1-mongo-target/src/exports/control.ts
Reworked marker persistence to use Prisma Mongo query-AST executor helpers (aggregate/insert/findOneAndUpdate wrappers) and re-exported marker APIs via exports/control.
Mongo planner/runner & adapter updates
packages/3-mongo-target/2-mongo-adapter/src/core/contract-to-schema.ts, .../mongo-planner.ts, .../mongo-runner.ts, related tests
Switched planner/runner/tests to use MongoSchemaIR class accessors and arrays; runner derives profileHash from destination contract; imports updated to new control export surface.
Migration of tests & fixtures
many packages/*/test/*, test/integration/test/*, example tests and vitest configs
Extensive test updates to construct runtime SchemaTreeNode and MongoSchemaIR instances, add visitor methods, adapt timeouts to Mongo-memory-server, and add numerous unit/e2e integration suites and fixtures for Mongo CLI and control flows.
Package manifests & configs
various package.json, tsconfig, tsdown.config.ts, pnpm-workspace.yaml
Added/adjusted runtime and dev dependencies (Mongo packages, workspace catalog entries), exposed new control entry points, added build/export entries, and included tests in compilation where needed.
Docs & rules
.agents/rules/mongo-no-obsolete-commands.mdc, .agents/rules/mongodb-memory-server-setup.mdc, .cursor/rules/README.md
Added rulecards advocating aggregate over find/findOne, MMS setup guidance and checklist, and documented Mongo schema IR usage.
sequenceDiagram
    participant CLI as CLI
    participant Family as Mongo Family
    participant Adapter as Mongo Adapter
    participant DB as MongoDB
    participant Diff as Schema Diff

    CLI->>Family: verify(driver, contract, expectedTargetId)
    Family->>Adapter: introspectSchema(db)
    Adapter->>DB: listCollections(), listIndexes(), getOptions()
    DB-->>Adapter: collections metadata
    Adapter-->>Family: MongoSchemaIR
    Family->>Family: compute storage/profile hashes
    Family->>Adapter: readMarker / initMarker / updateMarker (CAS)
    Adapter->>DB: marker read/write commands
    DB-->>Adapter: marker result
    Family->>Diff: diffMongoSchemas(live, expected, strict)
    Diff-->>Family: root + issues + counts
    Family-->>CLI: Verify/Sign/SchemaVerify result (ok / error codes)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I hop through indexes, sniff each mapped key,
Markers are signed, and views bloom for me.
I compare live and contract, spot every drift,
Introspect, convert, then give schema a lift.
Hooray — carrots for CI, and tests in a heap!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding live introspection capabilities and wiring CLI commands for the MongoDB family.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tml-2233-m4-online-cli-commands-live-introspection

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 13, 2026

Open in StackBlitz

@prisma-next/mongo-runtime

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-runtime@334

@prisma-next/family-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/family-mongo@334

@prisma-next/sql-runtime

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-runtime@334

@prisma-next/family-sql

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/family-sql@334

@prisma-next/extension-paradedb

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-paradedb@334

@prisma-next/extension-pgvector

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-pgvector@334

@prisma-next/postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/postgres@334

@prisma-next/sql-orm-client

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-orm-client@334

@prisma-next/sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sqlite@334

@prisma-next/target-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-mongo@334

@prisma-next/adapter-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-mongo@334

@prisma-next/driver-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-mongo@334

@prisma-next/contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/contract@334

@prisma-next/utils

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/utils@334

@prisma-next/config

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/config@334

@prisma-next/errors

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/errors@334

@prisma-next/framework-components

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/framework-components@334

@prisma-next/operations

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/operations@334

@prisma-next/contract-authoring

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/contract-authoring@334

@prisma-next/ids

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/ids@334

@prisma-next/psl-parser

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/psl-parser@334

@prisma-next/psl-printer

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/psl-printer@334

@prisma-next/cli

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/cli@334

@prisma-next/emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/emitter@334

@prisma-next/migration-tools

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/migration-tools@334

@prisma-next/vite-plugin-contract-emit

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/vite-plugin-contract-emit@334

@prisma-next/runtime-executor

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/runtime-executor@334

@prisma-next/mongo-codec

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-codec@334

@prisma-next/mongo-contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract@334

@prisma-next/mongo-value

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-value@334

@prisma-next/mongo-contract-psl

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract-psl@334

@prisma-next/mongo-contract-ts

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract-ts@334

@prisma-next/mongo-emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-emitter@334

@prisma-next/mongo-schema-ir

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-schema-ir@334

@prisma-next/mongo-query-ast

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-query-ast@334

@prisma-next/mongo-orm

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-orm@334

@prisma-next/mongo-pipeline-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-pipeline-builder@334

@prisma-next/mongo-lowering

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-lowering@334

@prisma-next/mongo-wire

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-wire@334

@prisma-next/sql-contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract@334

@prisma-next/sql-errors

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-errors@334

@prisma-next/sql-operations

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-operations@334

@prisma-next/sql-schema-ir

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-schema-ir@334

@prisma-next/sql-contract-psl

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-psl@334

@prisma-next/sql-contract-ts

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-ts@334

@prisma-next/sql-contract-emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-emitter@334

@prisma-next/sql-lane-query-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-lane-query-builder@334

@prisma-next/sql-relational-core

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-relational-core@334

@prisma-next/sql-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-builder@334

@prisma-next/target-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-postgres@334

@prisma-next/target-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-sqlite@334

@prisma-next/adapter-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-postgres@334

@prisma-next/adapter-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-sqlite@334

@prisma-next/driver-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-postgres@334

@prisma-next/driver-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-sqlite@334

commit: 30a5699

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (4)
test/integration/test/cli.mongo-db-sign.e2e.test.ts (1)

11-12: Replace hardcoded startup timeout with shared timeouts helpers.

Using 60_000 directly in integration tests drifts from the shared timeout policy and makes suite-wide tuning harder.

As per coding guidelines: "Use shared timeout helpers from @prisma-next/test-utils in tests instead of hardcoded numeric timeout values."

Also applies to: 65-66, 72-76, 84-84, 93-93

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/integration/test/cli.mongo-db-sign.e2e.test.ts` around lines 11 - 12,
Replace hardcoded numeric timeouts in this test with the shared helpers from
`@prisma-next/test-utils`: remove MONGO_STARTUP_TIMEOUT and any other literal time
values (e.g., the values referenced near lines 65-66, 72-76, 84, 93) and
import/use the exported timeouts (e.g., timeouts.startup or the appropriate
named constants) so the test uses the centralized timeout policy; update any
uses of MONGO_STARTUP_TIMEOUT to the corresponding timeouts constant and adjust
imports to include the timeouts helper.
packages/2-mongo-family/9-family/test/schema-diff.test.ts (1)

25-30: Use ifDefined() instead of inline conditional spreads in the coll helper.

This helper currently uses inline conditional spreads twice, which diverges from the repo’s conditional-spread pattern.

♻️ Suggested refactor
+import { ifDefined } from '@prisma-next/utils/defined';

 function coll(
   name: string,
   opts?: {
     indexes?: MongoSchemaIndex[];
     validator?: MongoSchemaValidator;
     options?: MongoSchemaCollectionOptions;
   },
 ): MongoSchemaCollection {
   return new MongoSchemaCollection({
     name,
     indexes: opts?.indexes ?? [],
-    ...(opts?.validator ? { validator: opts.validator } : {}),
-    ...(opts?.options ? { options: opts.options } : {}),
+    ...ifDefined('validator', opts?.validator),
+    ...ifDefined('options', opts?.options),
   });
 }

As per coding guidelines: "Use ifDefined() from @prisma-next/utils/defined for conditional object spreads instead of inline conditional spread patterns."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/9-family/test/schema-diff.test.ts` around lines 25 -
30, The coll helper currently uses inline conditional spreads when building the
MongoSchemaCollection object; import ifDefined from "@prisma-next/utils/defined"
and replace the two inline spread expressions with conditional spreads using
ifDefined (e.g., ...ifDefined(opts?.validator, { validator: opts.validator })
and ...ifDefined(opts?.options, { options: opts.options })), keeping the
existing name and indexes fields (name, indexes: opts?.indexes ?? []), then pass
that resulting object into new MongoSchemaCollection.
test/integration/test/cli.mongo-db-schema.e2e.test.ts (1)

22-24: Use shared test timeout helpers instead of 60_000.

Please switch this suite to @prisma-next/test-utils timeout constants to keep timeout behavior consistent across integration tests.

As per coding guidelines: "Use shared timeout helpers from @prisma-next/test-utils in tests instead of hardcoded numeric timeout values."

Also applies to: 31-35, 43-43, 50-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/integration/test/cli.mongo-db-schema.e2e.test.ts` around lines 22 - 24,
Replace the hardcoded MONGO_STARTUP_TIMEOUT and all other numeric timeouts in
this test suite with the shared timeout helpers from `@prisma-next/test-utils`:
import the appropriate timeout constant(s) at the top of the file and use them
in place of MONGO_STARTUP_TIMEOUT (the const currently set to 60_000) and the
other numeric values referenced around the describe block and subsequent tests
(lines referenced in the review: 31–35, 43, 50–57). Specifically, remove the
local MONGO_STARTUP_TIMEOUT constant, add the import (e.g., import {
<sharedTimeoutConstant> } from '@prisma-next/test-utils'), and substitute that
shared constant into the describe({ timeout: ... }) and any test() or
before()/after() calls that currently use literal millisecond numbers so all
tests use the shared timeouts.
test/integration/test/mongo/db-schema.test.ts (1)

64-67: Use a single object matcher for related root fields.

Line 64 and Line 65 check related properties of the same object; prefer one matcher for this pattern (and apply similarly to Line 91-92 and Line 149-150).

♻️ Proposed refactor
-    expect(view.root.kind).toBe('root');
-    expect(view.root.id).toBe('mongo-schema');
+    expect(view.root).toMatchObject({
+      kind: 'root',
+      id: 'mongo-schema',
+    });
     expect(view.root.children).toHaveLength(2);

As per coding guidelines, "Prefer object matchers (toMatchObject) over multiple individual expect().toBe() calls when checking 2 or more related values in tests."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/integration/test/mongo/db-schema.test.ts` around lines 64 - 67, Replace
multiple expectations that assert related properties on the same object with a
single object matcher: instead of separate expect(view.root.kind).toBe('root')
and expect(view.root.id).toBe('mongo-schema'), use
expect(view.root).toMatchObject({ kind: 'root', id: 'mongo-schema' }) and leave
the children length assertion as-is
(expect(view.root.children).toHaveLength(2)); apply the same refactor to the
other paired assertions referenced (the checks at the later locations
corresponding to lines 91-92 and 149-150) by converting their paired property
assertions into single toMatchObject calls on the parent object.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/1-framework/3-tooling/cli/src/commands/contract-infer.ts`:
- Around line 61-63: The code blindly casts inspectResult.value.schema to
PslPrintableSqlSchemaIR and calls printPsl(), which can crash for non‑SQL IR;
instead, check the schema's family/kind before casting (e.g.,
inspectResult.value.schema.family === 'sql' or an equivalent discriminant), only
narrow to PslPrintableSqlSchemaIR when that check passes, and emit a clear CLI
error/exit if the schema is not SQL; update the logic around inspectResult,
schema, and the call site of printPsl() to use type guarding rather than an
unconditional cast and keep resolveContractInferOutputPath usage unchanged.

In `@packages/2-mongo-family/9-family/src/core/schema-diff.ts`:
- Around line 258-273: The branch handling extra validators (when
expected.validator is falsy and live.validator is truthy) currently returns a
verification node but does not add it to the issues array; update the block in
schema-diff.ts so it constructs the same verification object (using status
computed from strict, kind 'validator', code 'EXTRA_VALIDATOR', etc.), push that
object onto the issues array (the same array used by
extra_table/extra_index/extra_options handling), and then return it (or return
an array containing it) to keep behavior consistent with the other "extra_*"
branches; reference the symbols expected.validator, live.validator, strict,
issues, and the returned verification node when making the change.

In `@test/integration/test/cli.mongo-db-schema.e2e.test.ts`:
- Around line 83-90: Capture and assert the CLI process exit code when calling
executeCommand in this test (and the similar block at 122-129): store the
command result/exit code returned by executeCommand after calling
createDbSchemaCommand()/executeCommand (referencing createDbSchemaCommand,
executeCommand and testSetup) and add an assertion that the exit code equals the
expected value for each path (e.g., 0 for the successful case, the appropriate
non-zero code for failure cases) before restoring the original cwd.

In `@test/integration/test/cli.mongo-db-verify.e2e.test.ts`:
- Around line 97-108: The teardown can crash if beforeEach fails and
cleanupMocks remains undefined; initialize cleanupMocks defensively (e.g., set
cleanupMocks = () => {} at declaration) or guard the afterEach call so it only
invokes cleanupMocks if defined; locate the symbols cleanupMocks, beforeEach,
afterEach and setupCommandMocks in the test file and ensure cleanupMocks has a
safe default or add a null-check in afterEach before calling it.
- Line 11: Replace the hardcoded MONGO_STARTUP_TIMEOUT numeric constant with the
shared timeout helper from `@prisma-next/test-utils`: add the appropriate import
for the shared timeout (e.g., TEST_TIMEOUTS or DEFAULT_TEST_TIMEOUT) at the top
of the test file and replace the MONGO_STARTUP_TIMEOUT usage with that imported
constant (remove the MONGO_STARTUP_TIMEOUT declaration). Ensure the test now
references the shared symbol instead of the raw 60_000 value.

---

Nitpick comments:
In `@packages/2-mongo-family/9-family/test/schema-diff.test.ts`:
- Around line 25-30: The coll helper currently uses inline conditional spreads
when building the MongoSchemaCollection object; import ifDefined from
"@prisma-next/utils/defined" and replace the two inline spread expressions with
conditional spreads using ifDefined (e.g., ...ifDefined(opts?.validator, {
validator: opts.validator }) and ...ifDefined(opts?.options, { options:
opts.options })), keeping the existing name and indexes fields (name, indexes:
opts?.indexes ?? []), then pass that resulting object into new
MongoSchemaCollection.

In `@test/integration/test/cli.mongo-db-schema.e2e.test.ts`:
- Around line 22-24: Replace the hardcoded MONGO_STARTUP_TIMEOUT and all other
numeric timeouts in this test suite with the shared timeout helpers from
`@prisma-next/test-utils`: import the appropriate timeout constant(s) at the top
of the file and use them in place of MONGO_STARTUP_TIMEOUT (the const currently
set to 60_000) and the other numeric values referenced around the describe block
and subsequent tests (lines referenced in the review: 31–35, 43, 50–57).
Specifically, remove the local MONGO_STARTUP_TIMEOUT constant, add the import
(e.g., import { <sharedTimeoutConstant> } from '@prisma-next/test-utils'), and
substitute that shared constant into the describe({ timeout: ... }) and any
test() or before()/after() calls that currently use literal millisecond numbers
so all tests use the shared timeouts.

In `@test/integration/test/cli.mongo-db-sign.e2e.test.ts`:
- Around line 11-12: Replace hardcoded numeric timeouts in this test with the
shared helpers from `@prisma-next/test-utils`: remove MONGO_STARTUP_TIMEOUT and
any other literal time values (e.g., the values referenced near lines 65-66,
72-76, 84, 93) and import/use the exported timeouts (e.g., timeouts.startup or
the appropriate named constants) so the test uses the centralized timeout
policy; update any uses of MONGO_STARTUP_TIMEOUT to the corresponding timeouts
constant and adjust imports to include the timeouts helper.

In `@test/integration/test/mongo/db-schema.test.ts`:
- Around line 64-67: Replace multiple expectations that assert related
properties on the same object with a single object matcher: instead of separate
expect(view.root.kind).toBe('root') and
expect(view.root.id).toBe('mongo-schema'), use expect(view.root).toMatchObject({
kind: 'root', id: 'mongo-schema' }) and leave the children length assertion
as-is (expect(view.root.children).toHaveLength(2)); apply the same refactor to
the other paired assertions referenced (the checks at the later locations
corresponding to lines 91-92 and 149-150) by converting their paired property
assertions into single toMatchObject calls on the parent object.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 5f64525b-1d0a-428a-82ad-2f0217630622

📥 Commits

Reviewing files that changed from the base of the PR and between bb4a82e and 8f3041d.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • projects/mongo-schema-migrations/plans/m4-online-cli-commands-plan.md is excluded by !projects/**
📒 Files selected for processing (18)
  • packages/1-framework/3-tooling/cli/src/commands/contract-infer.ts
  • packages/1-framework/3-tooling/cli/src/commands/inspect-live-schema.ts
  • packages/1-framework/3-tooling/cli/test/commands/inspect-live-schema.test.ts
  • packages/2-mongo-family/9-family/package.json
  • packages/2-mongo-family/9-family/src/core/control-instance.ts
  • packages/2-mongo-family/9-family/src/core/schema-diff.ts
  • packages/2-mongo-family/9-family/test/control.test.ts
  • packages/2-mongo-family/9-family/test/schema-diff.test.ts
  • packages/3-mongo-target/2-mongo-adapter/src/core/introspect-schema.ts
  • packages/3-mongo-target/2-mongo-adapter/src/exports/control.ts
  • packages/3-mongo-target/2-mongo-adapter/test/introspect-schema.test.ts
  • test/integration/test/cli.mongo-db-schema.e2e.test.ts
  • test/integration/test/cli.mongo-db-sign.e2e.test.ts
  • test/integration/test/cli.mongo-db-verify.e2e.test.ts
  • test/integration/test/fixtures/cli/cli-e2e-test-app/fixtures/mongo-db-commands/prisma-next.config.with-db.ts
  • test/integration/test/fixtures/cli/cli-e2e-test-app/package.json
  • test/integration/test/mongo/db-schema.test.ts
  • test/integration/test/mongo/db-verify-sign.test.ts

wmadden added 16 commits April 13, 2026 10:45
Break down the implementation of Mongo live introspection and CLI
command wiring into 4 milestones with 20 tasks covering: introspect +
db schema, db verify + db sign, db init + db update, and migration
status/show. Introduces decoupled view interface design (prototype in
Mongo, extract later) and documents SQL coupling as tech debt.
Add introspectSchema() that reads collections, indexes, validators,
and collection options from a live MongoDB instance and produces a
MongoSchemaIR — symmetric to contractToMongoSchemaIR.

Filters out the default _id_ index, system collections, views, and
the _prisma_migrations collection.
Replace the introspect() stub with a real implementation that
delegates to introspectSchema(db). Fix method signatures on
verify/schemaVerify/sign stubs to match the ControlFamilyInstance
interface. Update MongoControlFamilyInstance to use the
MongoSchemaIR type parameter.
Map MongoSchemaIR to CoreSchemaView tree for CLI visualization.
Collections become collection nodes with index, validator, and
collection options as children. Implements SchemaViewCapable so
the CLI detects it via hasSchemaView().
Change InspectLiveSchemaResult.schema from PslPrintableSqlSchemaIR
to unknown. Only call validatePrintableSqlSchemaIR when the family
is SQL; for other families pass the raw schema IR through. This
unblocks db schema for MongoDB.
Verifies the full introspect -> toSchemaView -> tree output flow
against a real MongoMemoryReplSet. Covers collections with indexes,
validators, capped collections, empty databases, and JSON output.
Read the contract marker from MongoDB and compare storage/profile
hashes against the contract. Returns PN-RUN-3001 (missing marker),
PN-RUN-3002 (hash mismatch), PN-RUN-3003 (target mismatch), or
ok when the database matches the contract.
Introspect the live MongoDB, convert the contract to expected
MongoSchemaIR, and diff them to produce a SchemaVerificationNode
tree and SchemaIssue list. Detects missing/extra collections,
missing/extra indexes, validator mismatches, and collection options
drift. Strict mode reports extra elements as fail instead of warn.
Validate the contract, read the existing marker, and write/update
it via the adapter marker-ledger helpers. Uses compare-and-swap
(CAS) for atomic marker updates to prevent concurrent modification.
Returns created/updated/no-op status with previous hashes.
Cover all mode combinations: marker-only verify (missing, match,
hash mismatch, profile mismatch), schema verify (match, missing
index, extra index strict/non-strict, missing collection), and
sign (create, idempotent, update with CAS).
…f.ts

Move diffMongoSchemas and its helpers (diffIndexes, diffValidator,
diffOptions, buildIndexLookupKey, formatIndexName) into a dedicated
schema-diff.ts module. This reduces control-instance.ts from ~780 to
~420 lines and enables targeted unit testing of the diffing algorithm.

Also threads strict mode through diffValidator and diffOptions so
extra validators and extra options respect strict mode (fail instead
of warn), matching SQL behavior where strict mode applies to all
element types.
- Remove unused MIGRATIONS_COLLECTION and MARKER_ID constants
- Delegate readMarker() to the adapter instead of duplicating logic
- Remove redundant ?? undefined pattern in parseIndex
- Move target mismatch check before marker check in verify() so
  configuration errors surface independently of database state
…ent types

Tests cover: empty schemas, matching/missing/extra collections,
matching/missing/extra indexes, validator match/mismatch/missing/extra
(with validationLevel and validationAction variants), and options
match/mismatch/extra. Both strict and non-strict modes are exercised
for all "extra" element types.
Verify that non-SQL families (e.g. mongo) pass schema IR through
without validatePrintableSqlSchemaIR. Uses a mock config with
familyId "mongo" and asserts the raw schema IR is returned as-is.
Exercise the full CLI entry point for Mongo:
- db schema: JSON output with collections/indexes, tree output
- db verify: marker missing, matching marker+schema, schema-only
  (pass/fail), marker-only
- db sign: create marker, idempotent re-sign, update on hash change

Infrastructure: add Mongo workspace deps to cli-e2e-test-app fixture,
create mongo-db-commands fixture with Mongo family config. Contract
JSON is written directly to disk (no emit pipeline needed since
db verify/sign read contract.json from disk).
Replace non-null assertions with narrowed variable bindings to
satisfy biome noNonNullAssertion rule. Fix SchemaIssue type error
where expected was set to null instead of being omitted (expected
is string | undefined, not nullable).
@wmadden wmadden force-pushed the tml-2233-m4-online-cli-commands-live-introspection branch from 8f3041d to 33322e1 Compare April 13, 2026 07:45
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
packages/2-mongo-family/9-family/src/core/schema-diff.ts (1)

260-275: ⚠️ Potential issue | 🟡 Minor

Missing issue for extra validator.

When an extra validator is found (live has validator, expected doesn't), the code returns a verification node but doesn't push to the issues array. This is inconsistent with how extra_table (line 59-63), extra_index (lines 207-212), and extra_options (lines 343-348) are handled.

🐛 Proposed fix to add missing issue
   if (!expected.validator && live.validator) {
     const status = strict ? 'fail' : 'warn';
+    issues.push({
+      kind: 'extra_validator',
+      table: collName,
+      message: `Extra validator on collection "${collName}"`,
+    });
     return [
       {
         status,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/9-family/src/core/schema-diff.ts` around lines 260 -
275, The extra validator branch in schema-diff.ts currently returns a
verification node but does not append it to the issues array; update the block
that checks "if (!expected.validator && live.validator)" to both create the
verification node (with status set from strict, kind 'validator', code
'EXTRA_VALIDATOR', actual using canonicalize(live.validator.jsonSchema), etc.)
and push that node onto the issues array (same pattern used for extra_table,
extra_index, extra_options), then return the node (or the array) as currently
expected so behavior matches other "extra_*" handlers; reference the variables
expected.validator, live.validator, canonicalize, strict, and the issues array
when making the change.
🧹 Nitpick comments (5)
packages/1-framework/3-tooling/cli/src/commands/inspect-live-schema.ts (1)

129-130: Move family-specific schema validation behind the control adapter/family API.

Branching on config.family.familyId here leaks family-specific behavior into command orchestration. Prefer delegating this normalization/validation step to the family/control layer.

♻️ Suggested refactor direction
-    const schema =
-      config.family.familyId === 'sql' ? validatePrintableSqlSchemaIR(schemaIR) : schemaIR;
+    const schema = client.normalizeIntrospectedSchema(schemaIR);

As per coding guidelines, “Use adapters instead of branching on target. Reference .cursor/rules/no-target-branches.mdc for details.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/1-framework/3-tooling/cli/src/commands/inspect-live-schema.ts`
around lines 129 - 130, The code currently branches on config.family.familyId to
call validatePrintableSqlSchemaIR(schemaIR); move this family-specific
validation into the family/control adapter API instead of branching in
inspect-live-schema.ts. Replace the inline branch around
validatePrintableSqlSchemaIR and schemaIR with a single call to a
family-provided method (e.g., config.family.normalizeOrValidateSchema(schemaIR)
or via the control adapter), and implement the SQL-specific logic
(validatePrintableSqlSchemaIR) inside the SQL family adapter so
inspect-live-schema.ts no longer references config.family.familyId or
validatePrintableSqlSchemaIR directly.
packages/2-mongo-family/9-family/src/core/schema-diff.ts (1)

339-362: Missing handling for expected options without live options.

The diffOptions function handles:

  • Both undefined (line 339)
  • Live has options but expected doesn't (lines 341-362)
  • Both have options with deepEqual check (lines 364-378)
  • Options mismatch (lines 380-399)

However, it doesn't explicitly handle the case where expected.options exists but live.options is undefined (missing options). Currently this falls through to the deepEqual check which would compare undefined with an object, correctly producing a mismatch. This works but could be made more explicit with a dedicated MISSING_OPTIONS code for clarity and consistency with MISSING_VALIDATOR.

♻️ Optional refactor for explicit handling
   if (!live.options && !expected.options) return [];

+  if (expected.options && !live.options) {
+    issues.push({
+      kind: 'type_missing',
+      table: collName,
+      message: `Collection options missing on "${collName}"`,
+    });
+    return [
+      {
+        status: 'fail',
+        kind: 'options',
+        name: 'options',
+        contractPath: `storage.collections.${collName}.options`,
+        code: 'MISSING_OPTIONS',
+        message: 'Collection options missing',
+        expected: expected.options,
+        actual: null,
+        children: [],
+      },
+    ];
+  }
+
   if (!expected.options && live.options) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/9-family/src/core/schema-diff.ts` around lines 339 -
362, The diffOptions branch is missing explicit handling when expected.options
exists but live.options is undefined; update the diffOptions logic (around
collName, issues, strict) to add a branch for if (expected.options &&
!live.options) that pushes a type_mismatch issue with actual:
canonicalize(live.options) and returns an action object mirroring the
EXTRA_OPTIONS case but with code 'MISSING_OPTIONS', expected: expected.options,
actual: null, an appropriate message like 'Missing collection options found',
status set to 'fail' when strict else 'warn', and children: [] so it parallels
MISSING_VALIDATOR/EXTRA_OPTIONS handling.
packages/3-mongo-target/2-mongo-adapter/test/introspect-schema.test.ts (1)

13-16: Remove unused imports.

MongoInspectionExecutor, contractToMongoSchemaIR, and MongoMigrationRunner are imported but never used in this test file.

🧹 Proposed cleanup
-import { MongoInspectionExecutor } from '../src/core/command-executor';
-import { contractToMongoSchemaIR } from '../src/core/contract-to-schema';
 import { introspectSchema } from '../src/core/introspect-schema';
-import { MongoMigrationRunner } from '../src/core/mongo-runner';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/3-mongo-target/2-mongo-adapter/test/introspect-schema.test.ts`
around lines 13 - 16, Remove the unused imports from the test file: delete the
imports of MongoInspectionExecutor, contractToMongoSchemaIR, and
MongoMigrationRunner so only the used introspectSchema import remains; update
the import statement(s) in
packages/3-mongo-target/2-mongo-adapter/test/introspect-schema.test.ts to remove
references to those three symbols to avoid unused-import lint errors.
packages/3-mongo-target/2-mongo-adapter/src/core/introspect-schema.ts (2)

13-19: Consider type narrowing for index key direction.

The cast direction as MongoIndexKeyDirection assumes MongoDB always returns valid direction values. While this is generally true for indexes created through standard means, corrupted or manually manipulated metadata could contain unexpected values.

For defense-in-depth, consider validating the direction value:

🛡️ Suggested validation
 function parseIndexKeys(keySpec: Record<string, unknown>): MongoIndexKey[] {
   const keys: MongoIndexKey[] = [];
   for (const [field, direction] of Object.entries(keySpec)) {
-    keys.push({ field, direction: direction as MongoIndexKeyDirection });
+    // MongoDB index directions: 1, -1, 'text', '2dsphere', '2d', 'hashed'
+    const validDirections = [1, -1, 'text', '2dsphere', '2d', 'hashed'];
+    const dir = validDirections.includes(direction as MongoIndexKeyDirection)
+      ? (direction as MongoIndexKeyDirection)
+      : 1; // fallback to ascending
+    keys.push({ field, direction: dir });
   }
   return keys;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/3-mongo-target/2-mongo-adapter/src/core/introspect-schema.ts` around
lines 13 - 19, The parseIndexKeys function currently casts direction to
MongoIndexKeyDirection without validation; update parseIndexKeys to narrow and
validate the direction value from Object.entries(keySpec) before pushing: accept
known numeric directions (1, -1) and any project-specific string aliases (e.g.,
"asc"/"desc") mapping them to MongoIndexKeyDirection, otherwise either skip the
key or throw/log an error; reference parseIndexKeys, MongoIndexKey, and
MongoIndexKeyDirection so you can add a small guard (if/else or switch) that
converts/validates direction and only pushes a MongoIndexKey when the value is a
valid MongoIndexKeyDirection, providing a safe fallback behavior.

78-84: Consider using ifDefined() for conditional spreads.

The inline conditional spread pattern could be simplified using the ifDefined() helper from @prisma-next/utils/defined, which is the preferred pattern per coding guidelines.

♻️ Optional refactor
+import { ifDefined } from '@prisma-next/utils/defined';
+
 // In parseCollectionOptions:
-  return new MongoSchemaCollectionOptions({
-    ...(capped ? { capped: { size: size ?? 0, ...(max != null ? { max } : {}) } } : {}),
-    ...(timeseries ? { timeseries } : {}),
-    ...(collation ? { collation } : {}),
-    ...(changeStreamPreAndPostImages ? { changeStreamPreAndPostImages } : {}),
-    ...(clusteredIndex ? { clusteredIndex } : {}),
-  });
+  return new MongoSchemaCollectionOptions({
+    ...ifDefined(capped, () => ({ capped: { size: size ?? 0, ...ifDefined(max, () => ({ max })) } })),
+    ...ifDefined(timeseries, () => ({ timeseries })),
+    ...ifDefined(collation, () => ({ collation })),
+    ...ifDefined(changeStreamPreAndPostImages, () => ({ changeStreamPreAndPostImages })),
+    ...ifDefined(clusteredIndex, () => ({ clusteredIndex })),
+  });

As per coding guidelines: "Use ifDefined() from @prisma-next/utils/defined for conditional object spreads instead of inline conditional spread patterns"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/3-mongo-target/2-mongo-adapter/src/core/introspect-schema.ts` around
lines 78 - 84, Replace the inline conditional object spreads inside the
MongoSchemaCollectionOptions constructor with the ifDefined() helper from
`@prisma-next/utils/defined`: import ifDefined and wrap each optional property
(capped, timeseries, collation, changeStreamPreAndPostImages, clusteredIndex) so
you pass only defined values to the object passed to new
MongoSchemaCollectionOptions; ensure the capped object still builds size and max
correctly and use ifDefined(() => ({ capped: ... })) (or equivalent) for each
conditional to match existing shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/2-mongo-family/9-family/src/core/schema-diff.ts`:
- Around line 260-275: The extra validator branch in schema-diff.ts currently
returns a verification node but does not append it to the issues array; update
the block that checks "if (!expected.validator && live.validator)" to both
create the verification node (with status set from strict, kind 'validator',
code 'EXTRA_VALIDATOR', actual using canonicalize(live.validator.jsonSchema),
etc.) and push that node onto the issues array (same pattern used for
extra_table, extra_index, extra_options), then return the node (or the array) as
currently expected so behavior matches other "extra_*" handlers; reference the
variables expected.validator, live.validator, canonicalize, strict, and the
issues array when making the change.

---

Nitpick comments:
In `@packages/1-framework/3-tooling/cli/src/commands/inspect-live-schema.ts`:
- Around line 129-130: The code currently branches on config.family.familyId to
call validatePrintableSqlSchemaIR(schemaIR); move this family-specific
validation into the family/control adapter API instead of branching in
inspect-live-schema.ts. Replace the inline branch around
validatePrintableSqlSchemaIR and schemaIR with a single call to a
family-provided method (e.g., config.family.normalizeOrValidateSchema(schemaIR)
or via the control adapter), and implement the SQL-specific logic
(validatePrintableSqlSchemaIR) inside the SQL family adapter so
inspect-live-schema.ts no longer references config.family.familyId or
validatePrintableSqlSchemaIR directly.

In `@packages/2-mongo-family/9-family/src/core/schema-diff.ts`:
- Around line 339-362: The diffOptions branch is missing explicit handling when
expected.options exists but live.options is undefined; update the diffOptions
logic (around collName, issues, strict) to add a branch for if (expected.options
&& !live.options) that pushes a type_mismatch issue with actual:
canonicalize(live.options) and returns an action object mirroring the
EXTRA_OPTIONS case but with code 'MISSING_OPTIONS', expected: expected.options,
actual: null, an appropriate message like 'Missing collection options found',
status set to 'fail' when strict else 'warn', and children: [] so it parallels
MISSING_VALIDATOR/EXTRA_OPTIONS handling.

In `@packages/3-mongo-target/2-mongo-adapter/src/core/introspect-schema.ts`:
- Around line 13-19: The parseIndexKeys function currently casts direction to
MongoIndexKeyDirection without validation; update parseIndexKeys to narrow and
validate the direction value from Object.entries(keySpec) before pushing: accept
known numeric directions (1, -1) and any project-specific string aliases (e.g.,
"asc"/"desc") mapping them to MongoIndexKeyDirection, otherwise either skip the
key or throw/log an error; reference parseIndexKeys, MongoIndexKey, and
MongoIndexKeyDirection so you can add a small guard (if/else or switch) that
converts/validates direction and only pushes a MongoIndexKey when the value is a
valid MongoIndexKeyDirection, providing a safe fallback behavior.
- Around line 78-84: Replace the inline conditional object spreads inside the
MongoSchemaCollectionOptions constructor with the ifDefined() helper from
`@prisma-next/utils/defined`: import ifDefined and wrap each optional property
(capped, timeseries, collation, changeStreamPreAndPostImages, clusteredIndex) so
you pass only defined values to the object passed to new
MongoSchemaCollectionOptions; ensure the capped object still builds size and max
correctly and use ifDefined(() => ({ capped: ... })) (or equivalent) for each
conditional to match existing shape.

In `@packages/3-mongo-target/2-mongo-adapter/test/introspect-schema.test.ts`:
- Around line 13-16: Remove the unused imports from the test file: delete the
imports of MongoInspectionExecutor, contractToMongoSchemaIR, and
MongoMigrationRunner so only the used introspectSchema import remains; update
the import statement(s) in
packages/3-mongo-target/2-mongo-adapter/test/introspect-schema.test.ts to remove
references to those three symbols to avoid unused-import lint errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: f61d6259-44ef-4906-bc36-3c6f368595b5

📥 Commits

Reviewing files that changed from the base of the PR and between 8f3041d and 33322e1.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • projects/mongo-schema-migrations/plans/m4-online-cli-commands-plan.md is excluded by !projects/**
📒 Files selected for processing (18)
  • packages/1-framework/3-tooling/cli/src/commands/contract-infer.ts
  • packages/1-framework/3-tooling/cli/src/commands/inspect-live-schema.ts
  • packages/1-framework/3-tooling/cli/test/commands/inspect-live-schema.test.ts
  • packages/2-mongo-family/9-family/package.json
  • packages/2-mongo-family/9-family/src/core/control-instance.ts
  • packages/2-mongo-family/9-family/src/core/schema-diff.ts
  • packages/2-mongo-family/9-family/test/control.test.ts
  • packages/2-mongo-family/9-family/test/schema-diff.test.ts
  • packages/3-mongo-target/2-mongo-adapter/src/core/introspect-schema.ts
  • packages/3-mongo-target/2-mongo-adapter/src/exports/control.ts
  • packages/3-mongo-target/2-mongo-adapter/test/introspect-schema.test.ts
  • test/integration/test/cli.mongo-db-schema.e2e.test.ts
  • test/integration/test/cli.mongo-db-sign.e2e.test.ts
  • test/integration/test/cli.mongo-db-verify.e2e.test.ts
  • test/integration/test/fixtures/cli/cli-e2e-test-app/fixtures/mongo-db-commands/prisma-next.config.with-db.ts
  • test/integration/test/fixtures/cli/cli-e2e-test-app/package.json
  • test/integration/test/mongo/db-schema.test.ts
  • test/integration/test/mongo/db-verify-sign.test.ts
✅ Files skipped from review due to trivial changes (7)
  • packages/2-mongo-family/9-family/package.json
  • packages/1-framework/3-tooling/cli/test/commands/inspect-live-schema.test.ts
  • packages/3-mongo-target/2-mongo-adapter/src/exports/control.ts
  • test/integration/test/fixtures/cli/cli-e2e-test-app/fixtures/mongo-db-commands/prisma-next.config.with-db.ts
  • test/integration/test/mongo/db-schema.test.ts
  • test/integration/test/cli.mongo-db-verify.e2e.test.ts
  • packages/2-mongo-family/9-family/test/schema-diff.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/1-framework/3-tooling/cli/src/commands/contract-infer.ts
  • test/integration/test/fixtures/cli/cli-e2e-test-app/package.json
  • test/integration/test/cli.mongo-db-sign.e2e.test.ts
  • test/integration/test/cli.mongo-db-schema.e2e.test.ts
  • packages/2-mongo-family/9-family/src/core/control-instance.ts

wmadden added 9 commits April 13, 2026 12:49
The db schema command shows the live database schema, not the
contract. Both Mongo and SQL families had the root tree node
labeled "contract" — corrected to "database".
- Index directions: omit ascending (default), show desc/text/hashed/etc.
- Validator label: use explicit keys (level: strict, action: error)
- Validator subtree: expand jsonSchema properties as child nodes
  showing field name, bsonType, and (required) annotation
SchemaViewCapable<TSchemaIR = unknown> was always consumed as
SchemaViewCapable<unknown> since hasSchemaView never propagated
the concrete type. Remove the type param from SchemaViewCapable
and make hasSchemaView generic over ControlFamilyInstance so it
preserves TSchemaIR when narrowing.
…ror reporting

The Mongo planner was not including profileHash in the migration plan
destination, causing the runner to fall back to storageHash. This meant
the database marker profileHash was always set to storageHash after
migration, causing db verify to report a hash mismatch.

Additionally, the CLI db verify command only reported storageHash in
its error metadata for PN-RUN-3002, masking profileHash mismatches
and producing confusing output where expected/actual were identical.
Per ADR 004, profileHash is for capability profile drift and is
irrelevant to migration planning (which uses storageHash only).

Revert adding profileHash to the planner destination. Instead, the
runner reads profileHash from the destinationContract when writing
the marker. Remove the storageHash fallback that silently corrupted
the marker profileHash.

The sign method also no longer falls back — it reads profileHash
directly from the validated contract (which always has it).
MongoSchemaIR was the only plain interface in its own AST package —
it did not extend MongoSchemaNode, had no kind, no visitor dispatch,
no freeze, and used a Record instead of holding children as nodes.

Convert it to a class extending MongoSchemaNode with kind "schema",
sorted children array, visitor participation, and a collection(name)
lookup helper. Update all construction sites (introspectSchema,
contractToMongoSchemaIR) and consumers (diffMongoSchemas, toSchemaView,
MongoMigrationPlanner, and all tests) to use the class API.
The MongoSchemaIR → CoreSchemaView transformation is a substantial
piece of logic (~100 lines) that was embedded in the family instance
class. Extracting it to a dedicated module makes the transformation
independently testable and separates the labeling/ordering/expansion
concerns from the family instance lifecycle/orchestration.
SchemaTreeNode was a plain data interface that families constructed as
object literals. This promoted it to a concrete class with constructor
validation, Object.freeze() for immutability, and a visitor interface
(SchemaTreeVisitor<R>) with accept() method — following the same AST
pattern established by MongoSchemaNode. All family construction sites
(Mongo schema-to-view, SQL toSchemaView) and test fixtures now use
new SchemaTreeNode({...}) instead of object literals.
SchemaViewCapable<TSchemaIR> now flows the concrete schema IR type
through the interface, so families get compile-time verification that
their toSchemaView method signature matches the interface contract.
Both MongoControlFamilyInstance and SqlControlFamilyInstance now
explicitly extend SchemaViewCapable with their concrete IR type,
fixing the Liskov substitution violation where the concrete methods
narrowed the input type without declaring the interface.
wmadden added 10 commits April 13, 2026 14:34
Use ifDefined from @prisma-next/utils/defined instead of verbose
...(x ? { x } : {}) patterns in control-instance.ts and
schema-to-view.ts. Adds @prisma-next/utils as a dependency of
the mongo family package.
Define VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_HASH_MISMATCH,
VERIFY_CODE_TARGET_MISMATCH, and VERIFY_CODE_SCHEMA_FAILURE in
framework-components and use them in Mongo family, SQL family,
and CLI instead of inline string literals.
Defers F19 (raw driver calls + layer concern) to a follow-up
ticket. The refactoring requires adding RawFindOneCommand to the
query AST and extending the command executor.
Remove unused imports from test file and narrow CollectionInfo
options access to handle the union type correctly.
… aggregate

marker-ledger is deployment infrastructure state, not domain operation
bridging — it belongs in the driver layer. Also replaces the obsolete
findOne call with an aggregate pipeline ($match + $limit), consistent
with the modern MongoDB command surface.

Adapter re-exports from driver for backward compatibility. Runner tests
updated to mock the driver module. TML-2253 cancelled (no longer needed).
… calls

Use RawAggregateCommand, RawInsertOneCommand, and RawFindOneAndUpdateCommand
from @prisma-next/mongo-query-ast instead of calling db.collection() methods
directly. Small executor functions in the driver bridge AST commands to the
Db object.
marker-ledger is deployment infrastructure state — it belongs in
@prisma-next/target-mongo, not in the driver (connectivity/execution)
or adapter (domain bridging). Added control export to the target package.
All consumers updated to import from @prisma-next/target-mongo/control.
…e explicit type args

The default silently erased type safety. Framework-level consumers
now pass unknown explicitly; concrete families supply their IR type.
- Add missing issues.push() in extra validator branch of diffValidator
- Add extra_validator to SchemaIssue kind union
- Guard contract-infer to SQL families with structured error
- Replace hardcoded 60_000 timeouts with timeouts.spinUpDbServer
- Initialize cleanupMocks defensively in all e2e tests
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/1-framework/3-tooling/cli/test/output.test.ts (1)

1-1037: Consider splitting this test file.

At ~1037 lines, this file exceeds the 500-line guideline. Consider splitting by functionality (e.g., output.introspect.test.ts, output.schema-verify.test.ts, output.sign.test.ts) to improve navigability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/1-framework/3-tooling/cli/test/output.test.ts` around lines 1 -
1037, The test file is too large and should be split into focused test files to
improve navigability; create separate test files for introspection, schema
verification, and signing (e.g., tests that exercise
formatIntrospectOutput/formatIntrospectJson and createSchemaView; tests for
formatSchemaVerifyOutput/formatSchemaVerifyJson and
createVerificationNode/createResult; tests for formatSignOutput/formatSignJson
and createSignResult). Move any shared helpers (like parseGlobalFlags usage or
stripAnsi import) into a small shared test helper module if needed, update each
new test file to import only the functions it needs (formatIntrospectOutput,
formatIntrospectJson, formatSchemaVerifyOutput, formatSchemaVerifyJson,
formatSignOutput, formatSignJson, parseGlobalFlags, SchemaTreeNode), and ensure
each describe block from the original file is preserved in the appropriate new
file so tests and helper factory functions (createSchemaView, createResult,
createVerificationNode, createSignResult) remain available and referenced
correctly.
test/integration/test/cli.mongo-db-sign.e2e.test.ts (1)

48-56: Consider edge case handling in extractJson.

The current implementation finds the first { and last } in the output. This works for single JSON objects but could misbehave if:

  • CLI output contains multiple JSON objects
  • Braces appear in non-JSON output before/after the actual JSON

For CLI --json mode this is likely fine, but consider documenting this assumption or using a more robust approach if issues arise.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/integration/test/cli.mongo-db-sign.e2e.test.ts` around lines 48 - 56,
The extractJson function currently slices from the first '{' to the last '}',
which can break if there are multiple JSON objects or stray braces; update
extractJson to locate the first '{' then scan forward tracking brace depth
(increment on '{', decrement on '}') to find the matching closing brace and
parse only that balanced substring, throwing a clear error if no matching
closing brace is found; reference the extractJson function so you can replace
the current indexOf/lastIndexOf logic with this brace-counting loop to make the
extraction robust (or alternatively add a brief comment documenting the
single-JSON assumption if you choose not to change behavior).
packages/1-framework/3-tooling/cli/src/commands/db-verify.ts (1)

69-89: Potential logic issue: unreachable or confusing ternary condition.

When storageMatch is true (line 75 check passes, no early return), the code falls through to lines 83-89. At this point, if the verification code is VERIFY_CODE_HASH_MISMATCH but storageMatch is true, then profileMatch must be false (otherwise verification wouldn't have failed). The ternary profileMatch ? 'Contract hash does not match...' : 'Contract profileHash does not match...' at lines 84-86 will always take the false branch.

Consider simplifying:

Suggested simplification
       return errorHashMismatch({
-        why: profileMatch
-          ? 'Contract hash does not match database marker'
-          : 'Contract profileHash does not match database marker',
+        why: 'Contract profileHash does not match database marker',
         expected: verifyResult.contract.profileHash,
         ...ifDefined('actual', verifyResult.marker?.profileHash),
       });

Alternatively, if the generic message is intentional for edge cases (e.g., future mismatch types), add a comment explaining when profileMatch could be true here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/1-framework/3-tooling/cli/src/commands/db-verify.ts` around lines 69
- 89, The ternary using profileMatch inside the VERIFY_CODE_HASH_MISMATCH branch
is confusing/unreachable: after the storageMatch early return, profileMatch will
always be false here, so simplify the logic in the block that calls
errorHashMismatch for profile mismatches (the code that computes profileMatch
and returns errorHashMismatch) — replace the ternary with a single clear message
like "Contract profileHash does not match database marker" (and keep expected:
verifyResult.contract.profileHash and actual via ifDefined), or if you intend to
keep both messages for future cases, add a clear comment above profileMatch
explaining the edge-case when profileMatch could be true and why the ternary is
necessary; update the errorHashMismatch call accordingly to remove unreachable
branches.
packages/2-mongo-family/9-family/src/core/schema-to-view.ts (1)

44-52: Consider preserving explicit sparse: false in meta.

The expression index.sparse || undefined converts false to undefined, omitting sparse from meta when it's explicitly false. If distinguishing between "not sparse" and "sparse not specified" matters for debugging or display, consider:

-          ...ifDefined('sparse', index.sparse || undefined),
+          ...ifDefined('sparse', index.sparse),

However, if the intent is to only show non-default options, the current approach is acceptable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-mongo-family/9-family/src/core/schema-to-view.ts` around lines 44
- 52, The meta builder currently uses index.sparse || undefined which turns an
explicit false into undefined; update the meta population (in the block that
constructs meta for each index, referencing index and the helper ifDefined) to
use a nullish check (e.g., index.sparse ?? undefined) so that sparse: false is
preserved in meta rather than omitted.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/2-mongo-family/9-family/src/core/control-instance.ts`:
- Around line 204-228: contractProfileHash can be undefined but initMarker and
updateMarker require a non-optional profileHash; update the function signatures
for initMarker and updateMarker to accept profileHash?: string (and adjust any
internal logic to handle undefined), then update their type definitions/exports
and all call sites (including the calls in this file that pass
contractProfileHash and the updateMarker call that uses
existingMarker.storageHash) so the optional profileHash flows safely;
alternatively, if you prefer stricter validation instead, add a null check
before calling initMarker/updateMarker and throw or handle the missing
profileHash explicitly instead of passing undefined.

---

Nitpick comments:
In `@packages/1-framework/3-tooling/cli/src/commands/db-verify.ts`:
- Around line 69-89: The ternary using profileMatch inside the
VERIFY_CODE_HASH_MISMATCH branch is confusing/unreachable: after the
storageMatch early return, profileMatch will always be false here, so simplify
the logic in the block that calls errorHashMismatch for profile mismatches (the
code that computes profileMatch and returns errorHashMismatch) — replace the
ternary with a single clear message like "Contract profileHash does not match
database marker" (and keep expected: verifyResult.contract.profileHash and
actual via ifDefined), or if you intend to keep both messages for future cases,
add a clear comment above profileMatch explaining the edge-case when
profileMatch could be true and why the ternary is necessary; update the
errorHashMismatch call accordingly to remove unreachable branches.

In `@packages/1-framework/3-tooling/cli/test/output.test.ts`:
- Around line 1-1037: The test file is too large and should be split into
focused test files to improve navigability; create separate test files for
introspection, schema verification, and signing (e.g., tests that exercise
formatIntrospectOutput/formatIntrospectJson and createSchemaView; tests for
formatSchemaVerifyOutput/formatSchemaVerifyJson and
createVerificationNode/createResult; tests for formatSignOutput/formatSignJson
and createSignResult). Move any shared helpers (like parseGlobalFlags usage or
stripAnsi import) into a small shared test helper module if needed, update each
new test file to import only the functions it needs (formatIntrospectOutput,
formatIntrospectJson, formatSchemaVerifyOutput, formatSchemaVerifyJson,
formatSignOutput, formatSignJson, parseGlobalFlags, SchemaTreeNode), and ensure
each describe block from the original file is preserved in the appropriate new
file so tests and helper factory functions (createSchemaView, createResult,
createVerificationNode, createSignResult) remain available and referenced
correctly.

In `@packages/2-mongo-family/9-family/src/core/schema-to-view.ts`:
- Around line 44-52: The meta builder currently uses index.sparse || undefined
which turns an explicit false into undefined; update the meta population (in the
block that constructs meta for each index, referencing index and the helper
ifDefined) to use a nullish check (e.g., index.sparse ?? undefined) so that
sparse: false is preserved in meta rather than omitted.

In `@test/integration/test/cli.mongo-db-sign.e2e.test.ts`:
- Around line 48-56: The extractJson function currently slices from the first
'{' to the last '}', which can break if there are multiple JSON objects or stray
braces; update extractJson to locate the first '{' then scan forward tracking
brace depth (increment on '{', decrement on '}') to find the matching closing
brace and parse only that balanced substring, throwing a clear error if no
matching closing brace is found; reference the extractJson function so you can
replace the current indexOf/lastIndexOf logic with this brace-counting loop to
make the extraction robust (or alternatively add a brief comment documenting the
single-JSON assumption if you choose not to change behavior).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: a67ccf51-3165-4395-8f91-74849da425a0

📥 Commits

Reviewing files that changed from the base of the PR and between 33322e1 and fb2404d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (52)
  • .agents/rules/mongo-no-obsolete-commands.mdc
  • .cursor/rules/README.md
  • packages/1-framework/1-core/config/test/config-types.test-d.ts
  • packages/1-framework/1-core/config/test/config-validation.test.ts
  • packages/1-framework/1-core/framework-components/src/control-capabilities.ts
  • packages/1-framework/1-core/framework-components/src/control-instances.ts
  • packages/1-framework/1-core/framework-components/src/control-migration-types.ts
  • packages/1-framework/1-core/framework-components/src/control-result-types.ts
  • packages/1-framework/1-core/framework-components/src/control-schema-view.ts
  • packages/1-framework/1-core/framework-components/src/exports/control.ts
  • packages/1-framework/3-tooling/cli/src/commands/contract-infer.ts
  • packages/1-framework/3-tooling/cli/src/commands/db-verify.ts
  • packages/1-framework/3-tooling/cli/src/control-api/client.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/db-init.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/db-update.ts
  • packages/1-framework/3-tooling/cli/src/control-api/operations/migration-apply.ts
  • packages/1-framework/3-tooling/cli/test/control-api/client.test.ts
  • packages/1-framework/3-tooling/cli/test/control-api/db-update.test.ts
  • packages/1-framework/3-tooling/cli/test/control-api/progress.test.ts
  • packages/1-framework/3-tooling/cli/test/output.test.ts
  • packages/2-mongo-family/3-tooling/mongo-schema-ir/README.md
  • packages/2-mongo-family/3-tooling/mongo-schema-ir/src/exports/index.ts
  • packages/2-mongo-family/3-tooling/mongo-schema-ir/src/schema-ir.ts
  • packages/2-mongo-family/3-tooling/mongo-schema-ir/src/types.ts
  • packages/2-mongo-family/3-tooling/mongo-schema-ir/src/visitor.ts
  • packages/2-mongo-family/3-tooling/mongo-schema-ir/test/schema-ir.test.ts
  • packages/2-mongo-family/9-family/package.json
  • packages/2-mongo-family/9-family/src/core/control-instance.ts
  • packages/2-mongo-family/9-family/src/core/schema-diff.ts
  • packages/2-mongo-family/9-family/src/core/schema-to-view.ts
  • packages/2-mongo-family/9-family/test/control.test.ts
  • packages/2-mongo-family/9-family/test/schema-diff.test.ts
  • packages/2-sql/9-family/src/core/control-instance.ts
  • packages/3-mongo-target/1-mongo-target/package.json
  • packages/3-mongo-target/1-mongo-target/src/core/marker-ledger.ts
  • packages/3-mongo-target/1-mongo-target/src/exports/control.ts
  • packages/3-mongo-target/1-mongo-target/test/marker-ledger.test.ts
  • packages/3-mongo-target/1-mongo-target/tsconfig.json
  • packages/3-mongo-target/1-mongo-target/tsdown.config.ts
  • packages/3-mongo-target/2-mongo-adapter/package.json
  • packages/3-mongo-target/2-mongo-adapter/src/core/contract-to-schema.ts
  • packages/3-mongo-target/2-mongo-adapter/src/core/introspect-schema.ts
  • packages/3-mongo-target/2-mongo-adapter/src/core/mongo-planner.ts
  • packages/3-mongo-target/2-mongo-adapter/src/core/mongo-runner.ts
  • packages/3-mongo-target/2-mongo-adapter/src/exports/control.ts
  • packages/3-mongo-target/2-mongo-adapter/test/contract-to-schema.test.ts
  • packages/3-mongo-target/2-mongo-adapter/test/introspect-schema.test.ts
  • packages/3-mongo-target/2-mongo-adapter/test/mongo-planner.test.ts
  • packages/3-mongo-target/2-mongo-adapter/test/mongo-runner.test.ts
  • test/integration/test/cli.mongo-db-schema.e2e.test.ts
  • test/integration/test/cli.mongo-db-sign.e2e.test.ts
  • test/integration/test/cli.mongo-db-verify.e2e.test.ts
✅ Files skipped from review due to trivial changes (13)
  • packages/1-framework/1-core/config/test/config-validation.test.ts
  • packages/3-mongo-target/2-mongo-adapter/package.json
  • packages/3-mongo-target/1-mongo-target/tsconfig.json
  • packages/3-mongo-target/1-mongo-target/tsdown.config.ts
  • .cursor/rules/README.md
  • packages/3-mongo-target/1-mongo-target/src/exports/control.ts
  • packages/2-mongo-family/9-family/package.json
  • .agents/rules/mongo-no-obsolete-commands.mdc
  • packages/2-mongo-family/3-tooling/mongo-schema-ir/README.md
  • test/integration/test/cli.mongo-db-schema.e2e.test.ts
  • packages/3-mongo-target/2-mongo-adapter/src/core/introspect-schema.ts
  • packages/2-mongo-family/9-family/test/schema-diff.test.ts
  • test/integration/test/cli.mongo-db-verify.e2e.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/3-mongo-target/2-mongo-adapter/src/exports/control.ts

wmadden added 2 commits April 13, 2026 17:38
- Add explicit unknown to ControlFamilyInstance in control-capabilities.ts
  and control-descriptors.ts (missed in F11 commit)
- Replace non-null assertions with optional chaining in introspect-schema.ts
- Update e2e test assertion to match array-based MongoSchemaIR collections
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/integration/test/mongo/db-verify-sign.test.ts (1)

90-93: Prefer object matchers for grouped result assertions.

Several tests assert multiple related fields with separate toBe calls. Please switch these grouped checks to toMatchObject for consistency with repo test conventions.

♻️ Example refactor pattern
-      expect(result.ok).toBe(false);
-      expect(result.code).toBe('PN-RUN-3001');
+      expect(result).toMatchObject({
+        ok: false,
+        code: 'PN-RUN-3001',
+      });
       expect(result.summary).toContain('missing');
-      expect(result.ok).toBe(true);
-      expect(result.marker.created).toBe(true);
-      expect(result.marker.updated).toBe(false);
-      expect(result.contract.storageHash).toBe(baseContract.storage.storageHash);
+      expect(result).toMatchObject({
+        ok: true,
+        marker: { created: true, updated: false },
+        contract: { storageHash: baseContract.storage.storageHash },
+      });

As per coding guidelines, "Prefer object matchers (toMatchObject) over multiple individual expect().toBe() calls when checking 2 or more related values in tests."

Also applies to: 109-111, 127-129, 145-147, 164-166, 180-183, 199-201, 217-219, 231-233, 245-249, 266-269, 295-298

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/integration/test/mongo/db-verify-sign.test.ts` around lines 90 - 93,
Replace grouped individual assertions on the result object with an object
matcher: for the three assertions shown, collapse expect(result.ok).toBe(false)
and expect(result.code).toBe('PN-RUN-3001') into a single
expect(result).toMatchObject({ ok: false, code: 'PN-RUN-3001' }) and keep the
summary substring check (expect(result.summary).toContain('missing')) if still
needed; apply the same refactor for the other listed blocks (lines referencing
the same result variable) so any tests that assert two or more related fields
use toMatchObject rather than multiple expect(...).toBe() calls.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/1-framework/3-tooling/cli/src/commands/db-verify.ts`:
- Around line 70-89: storageMatch currently treats a missing marker.storageHash
as a mismatch; update the logic so you only return the specialized storage-hash
error when the marker actually contains storageHash. Concretely, change the
storage mismatch branch to check both that verifyResult.marker?.storageHash is
defined and that it differs from verifyResult.contract.storageHash (use the
existing storageMatch/profileMatch booleans or recompute as needed), e.g. only
call errorHashMismatch with the storage-specific message when
verifyResult.marker?.storageHash != null && !storageMatch; otherwise fall
through to the profile/hash handling and use errorHashMismatch for profileHash
or a generic contract/hash mismatch. Ensure you reference storageMatch,
profileMatch, verifyResult.marker?.storageHash, errorHashMismatch, and ifDefined
when making the change.

---

Nitpick comments:
In `@test/integration/test/mongo/db-verify-sign.test.ts`:
- Around line 90-93: Replace grouped individual assertions on the result object
with an object matcher: for the three assertions shown, collapse
expect(result.ok).toBe(false) and expect(result.code).toBe('PN-RUN-3001') into a
single expect(result).toMatchObject({ ok: false, code: 'PN-RUN-3001' }) and keep
the summary substring check (expect(result.summary).toContain('missing')) if
still needed; apply the same refactor for the other listed blocks (lines
referencing the same result variable) so any tests that assert two or more
related fields use toMatchObject rather than multiple expect(...).toBe() calls.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 5aff5408-8927-4dad-8ae9-ca0c25bc6a5f

📥 Commits

Reviewing files that changed from the base of the PR and between df67496 and 7a48bfa.

⛔ Files ignored due to path filters (1)
  • test/integration/test/__snapshots__/cli.db-introspect.e2e.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • packages/1-framework/3-tooling/cli/src/commands/db-verify.ts
  • test/integration/test/mongo/db-verify-sign.test.ts

@wmadden wmadden force-pushed the tml-2233-m4-online-cli-commands-live-introspection branch 5 times, most recently from 40c07a4 to cfa169e Compare April 13, 2026 18:23
Pin MMS to exact version 10.4.3 via pnpm catalog so all consumers
resolve the same binary. Add a dedicated spinUpMongoMemoryServer
timeout (60s base) to test-utils — if the beforeAll hook is killed
mid-download on CI, the partially-extracted binary corrupts the
shared MMS cache and causes SIGSEGV in every subsequent mongo test.

Migrate all 8 MMS consumers from inline versions to catalog:, all
mongo test timeouts from spinUpDbServer to spinUpMongoMemoryServer,
fix the orm package which had no vitest timeout config at all, and
add missing test coverage for the marker meta fallback branch.

Includes an agent rule (.agents/rules/mongodb-memory-server-setup.mdc)
documenting the version pinning, timeout, and new-package checklist.
@wmadden wmadden force-pushed the tml-2233-m4-online-cli-commands-live-introspection branch from b6e29a8 to 30a5699 Compare April 14, 2026 03:09
@wmadden wmadden merged commit ff06703 into main Apr 14, 2026
16 checks passed
@wmadden wmadden deleted the tml-2233-m4-online-cli-commands-live-introspection branch April 14, 2026 03:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant