Skip to content

feat(ztd-cli): add reusable ddl risk evaluation - #649

Merged
mk3008 merged 4 commits into
mainfrom
codex/648-independent-ddl-risk-evaluator
Mar 22, 2026
Merged

feat(ztd-cli): add reusable ddl risk evaluation#649
mk3008 merged 4 commits into
mainfrom
codex/648-independent-ddl-risk-evaluator

Conversation

@mk3008

@mk3008 mk3008 commented Mar 22, 2026

Copy link
Copy Markdown
Owner

Summary

This PR follows up on the structured ddl diff risks work by making the risk evaluator independently reusable and by adding a user-facing CLI entry for post-hoc migration risk analysis.

It keeps ddl diff as the generator-and-review flow, but separates the evaluator responsibility so we can analyze:

  • generated migration plans
  • generated migration SQL
  • hand-edited migration SQL after human review

What changed

  • extracted shared DDL diff contracts into a dedicated module
  • added independent evaluators:
    • analyzeMigrationPlanRisks(plan, summary?)
    • analyzeMigrationSqlRisks(sql)
  • updated ddl diff to use the extracted evaluator
  • added ztd ddl risk --file <migration.sql> so users can re-evaluate hand-edited migration SQL through the same risk contract
  • updated describe command support for the new ddl risk entry
  • updated tutorial / migration / agent-interface docs to explain the responsibility split:
    • ddl diff generates and evaluates from a diff
    • ddl risk evaluates migration SQL itself, including hand-edited scripts
  • added unit / CLI / docs regression coverage for the new entry

Why

Structured risks improved reviewability, but the evaluator still lived inside diff.ts, which made it harder to:

  • treat risk analysis as an independent responsibility
  • re-use the same contract from other entry points
  • re-evaluate migration SQL after manual edits

This PR makes that separation explicit and gives users a discoverable CLI path for post-hoc risk analysis.

Verification

  • pnpm --filter @rawsql-ts/ztd-cli build
  • pnpm --filter @rawsql-ts/ztd-cli test -- diff.unit.test.ts
  • pnpm --filter @rawsql-ts/ztd-cli test -- cliCommands.test.ts
  • pnpm --filter @rawsql-ts/ztd-cli test -- describe.cli.test.ts -u
  • pnpm --filter @rawsql-ts/ztd-cli test -- sqlFirstTutorial.docs.test.ts furtherReading.docs.test.ts
  • after merging latest main:
    • pnpm --filter @rawsql-ts/ztd-cli test -- diff.unit.test.ts cliCommands.test.ts describe.cli.test.ts
    • pnpm --filter @rawsql-ts/ztd-cli test -- furtherReading.docs.test.ts

Notes

  • I merged the latest main into this branch before opening the PR and resolved the one conflict in packages/ztd-cli/tests/diff.unit.test.ts.
  • There is an unrelated local package.json modification in the worktree, but it is not part of this PR.

Summary by CodeRabbit

  • New Features

    • Added a new CLI command to evaluate migration SQL files so hand-edited migrations can be re-assessed against the shared structured risk contract.
  • Documentation

    • Updated migration guides and tutorials to instruct rerunning risk evaluation after manual SQL edits and to capture that verification as evidence.
  • Refactor

    • Centralized risk analysis into reusable evaluators used for both generated plans and direct SQL evaluation.
  • Tests

    • Added unit and CLI tests covering the new command and both plan- and SQL-based risk evaluations.

@coderabbitai

coderabbitai Bot commented Mar 22, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8082f7b3-4460-4033-a038-e8c5450dafdd

📥 Commits

Reviewing files that changed from the base of the PR and between 05b1533 and 453e48b.

📒 Files selected for processing (4)
  • packages/ztd-cli/src/commands/ddl.ts
  • packages/ztd-cli/src/commands/ddlRiskEvaluator.ts
  • packages/ztd-cli/tests/cliCommands.test.ts
  • packages/ztd-cli/tests/diff.unit.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ztd-cli/tests/diff.unit.test.ts

📝 Walkthrough

Walkthrough

This PR extracts DDL diff risk analysis into reusable evaluators (plan-based and SQL-based), adds a new ddl risk CLI command to evaluate hand-edited migration SQL against the unified risk contract, and updates docs/tests to require/refer to re-running risk evaluation after manual SQL edits.

Changes

Cohort / File(s) Summary
Release & Documentation
\.changeset/kind-pets-shout.md, docs/dogfooding/ztd-migration-lifecycle.md, docs/guide/sql-first-end-to-end-tutorial.md, docs/guide/ztd-cli-agent-interface.md
Patch changeset added; docs updated to instruct running npx ztd ddl risk --file <migration.sql> after hand-editing generated SQL and to capture re-evaluation evidence in guides/checklists.
Risk Contracts & Evaluators
packages/ztd-cli/src/commands/ddlDiffContracts.ts, packages/ztd-cli/src/commands/ddlRiskEvaluator.ts
New DDL diff/risk types and a unified DdlDiffRisks contract. Added analyzeMigrationPlanRisks(plan, summary) and analyzeMigrationSqlRisks(sql) implementing plan- and SQL-based risk analysis, deduplication, and normalization.
CLI Command & Interface
packages/ztd-cli/src/commands/ddl.ts, packages/ztd-cli/src/commands/describe.ts
New ddl risk subcommand and descriptor: reads a migration SQL file, calls analyzeMigrationSqlRisks, emits JSON envelope or formatted text; --file and --json flags added to descriptor.
Refactored Risk Logic
packages/ztd-cli/src/commands/diff.ts
Replaced inline risk-building logic with calls to analyzeMigrationPlanRisks; removed in-file risk helpers/types and imported unified types/evaluator. groupSummaryByTable retained.
Tests & README Assertions
packages/ztd-cli/tests/cliCommands.test.ts, packages/ztd-cli/tests/diff.unit.test.ts, packages/ztd-cli/tests/furtherReading.docs.test.ts, packages/ztd-cli/tests/sqlFirstTutorial.docs.test.ts
Added tests for ddl risk help/JSON behavior, unit tests for both evaluators (plan and SQL variants), and updated doc-related tests to assert new CLI workflow references and reordered links.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI as "ztd ddl risk"
  participant FS as "Filesystem"
  participant Evaluator as "analyzeMigrationSqlRisks"
  participant Output as "Console / JSON"

  User->>CLI: run `ztd ddl risk --file tmp/users.diff.sql`
  CLI->>FS: read file `tmp/users.diff.sql`
  FS-->>CLI: return SQL text
  CLI->>Evaluator: analyzeMigrationSqlRisks(sql)
  Evaluator-->>CLI: return DdlDiffRisks (destructive/operational)
  CLI->>Output: emit JSON envelope or formatted risk lines
  Output-->>User: display results / write stdout
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 I nibble SQL lines with care,

Plan and text now both compare.
Hand-edited hops pass the test,
Risks exposed, each one addressed.
Hooray — safe migrations everywhere!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% 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 'feat(ztd-cli): add reusable ddl risk evaluation' clearly and specifically summarizes the main change: extracting DDL risk evaluation into a reusable module with new CLI command support.

✏️ 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 codex/648-independent-ddl-risk-evaluator

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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/ztd-cli/src/commands/ddl.ts`:
- Around line 172-178: Change the Commander option declaration for the "risk"
command from a requiredOption to an optional one so JSON payloads can supply the
file before runtime validation; specifically, update the chain that currently
calls requiredOption('--file', ...) to option('--file', ...), leaving the action
handler that constructs merged via parseJsonPayload(... ) and then calls
resolveRequiredProjectPath(merged.file, '--file') unchanged so that
resolveRequiredProjectPath enforces presence after merging JSON-provided values.

In `@packages/ztd-cli/src/commands/ddlRiskEvaluator.ts`:
- Around line 90-94: The current splitter (used to create statements from
normalized) only splits on /;\s*(?:\r?\n|$)/ which misses semicolon-separated
statements on the same line (e.g., "DROP...; CREATE...;"); change the split to
be formatting-independent by replacing that regex with a simple
semicolon+whitespace split such as .split(/;\s*/) when building statements from
normalized, keeping the subsequent .map(...).trim() and .filter(...) logic
intact (update the split call where statements is defined).
- Around line 100-155: The SQL analyzer never detects ADD/DROP CONSTRAINT or
constraint clauses in CREATE TABLEs; update the statement parsing loop to (1)
add regex checks for ALTER TABLE ... ADD CONSTRAINT and ALTER TABLE ... DROP
CONSTRAINT (use the same normalization helpers and call
createGuidedRisk/createDestructiveRisk as appropriate, e.g.,
createDestructiveRisk('drop_constraint',
`${normalizeQualifiedTarget(...)}.${constraintName}`) and
createGuidedRisk('add_constraint', ...)), and (2) when you handle
createTableMatch (the CREATE TABLE branch), inspect the full CREATE TABLE
statement body for inline CONSTRAINT definitions (or presence of ALTER ... ADD
CONSTRAINT in the same migration) and emit the same semantic constraint-change
risk (use the same risk kind used elsewhere, e.g.,
'semantic_constraint_change_effect' or a matching guided/destructive risk) so
rebuiltTables later will include constraint changes; use
normalizeQualifiedTarget and normalizeIdentifier to form targets.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a2d2d1e-8647-4a04-b077-7caf1ff057b3

📥 Commits

Reviewing files that changed from the base of the PR and between 620d175 and 05b1533.

⛔ Files ignored due to path filters (1)
  • packages/ztd-cli/tests/__snapshots__/describe.cli.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (13)
  • .changeset/kind-pets-shout.md
  • docs/dogfooding/ztd-migration-lifecycle.md
  • docs/guide/sql-first-end-to-end-tutorial.md
  • docs/guide/ztd-cli-agent-interface.md
  • packages/ztd-cli/src/commands/ddl.ts
  • packages/ztd-cli/src/commands/ddlDiffContracts.ts
  • packages/ztd-cli/src/commands/ddlRiskEvaluator.ts
  • packages/ztd-cli/src/commands/describe.ts
  • packages/ztd-cli/src/commands/diff.ts
  • packages/ztd-cli/tests/cliCommands.test.ts
  • packages/ztd-cli/tests/diff.unit.test.ts
  • packages/ztd-cli/tests/furtherReading.docs.test.ts
  • packages/ztd-cli/tests/sqlFirstTutorial.docs.test.ts

Comment thread packages/ztd-cli/src/commands/ddl.ts
Comment thread packages/ztd-cli/src/commands/ddlRiskEvaluator.ts
Comment thread packages/ztd-cli/src/commands/ddlRiskEvaluator.ts
@mk3008
mk3008 merged commit 0e5ae71 into main Mar 22, 2026
9 checks passed
@mk3008
mk3008 deleted the codex/648-independent-ddl-risk-evaluator branch March 22, 2026 11:56
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