Skip to content

feat: add dry-run mode to suggest#93

Open
nightcityblade wants to merge 1 commit into
404-PF:mainfrom
nightcityblade:fix/issue-90-dry-run
Open

feat: add dry-run mode to suggest#93
nightcityblade wants to merge 1 commit into
404-PF:mainfrom
nightcityblade:fix/issue-90-dry-run

Conversation

@nightcityblade
Copy link
Copy Markdown
Contributor

@nightcityblade nightcityblade commented May 31, 2026

Fixes #90

Summary

  • add -n, --dry-run to commit-echo suggest
  • print the diff, style profile, resolved system/user prompts, and truncation status without calling the LLM
  • keep --no-commit as a deprecated compatibility alias
  • add focused unit and E2E coverage for dry-run output and no-commit compatibility

Tests

  • npm run build
  • npm test
  • node --test tests/e2e/suggest-smoke.test.mjs tests/suggest-dry-run.test.mjs tests/cli-help.test.mjs
  • npm run format:check ⚠️ currently reports existing formatting differences in src/commands/init.ts, src/commands/suggest.ts, src/git/hook.ts, and src/llm/client.ts; left unformatted to avoid reintroducing unrelated churn.

Summary by CodeRabbit

  • New Features

    • Added --dry-run flag to the suggest command to preview LLM input without generating suggestions
    • --no-commit flag deprecated with compatibility warning
  • Documentation

    • Updated README documentation for the suggest command
  • Tests

    • Added test coverage for dry-run and deprecation behavior

@404-Page-Found
Copy link
Copy Markdown
Contributor

This PR has merge conflicts needs to be resolved😊

@nightcityblade
Copy link
Copy Markdown
Contributor Author

Thanks for the heads-up — I merged latest main into fix/issue-90-dry-run and resolved the conflicts in the suggest command path.\n\nValidation run locally:\n- npm run build\n- node --test tests/suggest-dry-run.test.mjs tests/cli-help.test.mjs

Copy link
Copy Markdown
Contributor

@404-Page-Found 404-Page-Found left a comment

Choose a reason for hiding this comment

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

Thanks for the PR — the dry-run mode is a great addition. I found a couple of blocking correctness issues that should be fixed before merge:

  1. Dry-run prompt construction diverges from real generation
  • In suggestCommand dry-run uses buildSystemPrompt(profile) and buildUserPrompt(diff) directly.
  • Actual generation uses resolveSystemPrompt(...) / resolveUserPrompt(...) with template vars (diff, profile, branch) and config.
  • Result: when users set systemPromptTemplate or userPromptTemplate, dry-run output does not reflect the real LLM payload.
  1. Dry-run truncation output diverges from real generation
  • Dry-run currently prints full diff and hardcodes truncation as none/sent in full.
  • Actual generation runs truncateDiff(diff, config.maxDiffSize) before prompting.
  • Result: dry-run can mislead users about what is actually sent to the model.
  1. Tests should cover parity behavior
  • Please add/adjust tests to assert dry-run matches real pipeline behavior for:
    • custom prompt templates (template var substitution path), and
    • truncation (large diff shows truncated payload + accurate truncation status).

Once these are aligned, this should be in good shape.

@nightcityblade
Copy link
Copy Markdown
Contributor Author

Aligned dry-run with the real generation pipeline in the latest commit: it now applies truncateDiff(...), uses resolveSystemPrompt(...) / resolveUserPrompt(...) with the same template vars (diff, profile, branch), and reports truncation details from the actual payload. I also added coverage for template-substitution parity and truncation parity, then re-ran npm test and npm run build.

Copy link
Copy Markdown
Contributor

@404-Page-Found 404-Page-Found left a comment

Choose a reason for hiding this comment

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

Request changes.

The new dry-run mode is useful, but the PR changes the user-facing CLI contract without preserving compatibility. The repository README still documents commit-echo suggest --no-commit, while the implementation now exposes --dry-run only. That means existing users following the published docs will hit an unknown-option failure, and there is no alias to keep the old invocation working.

Please either keep --no-commit as a compatibility alias or update the documentation and any related examples/tests so the published command surface matches the implementation.

@nightcityblade
Copy link
Copy Markdown
Contributor Author

Addressed in 4c4fb25.\n\nChanges:\n- restored as a deprecated compatibility alias so existing documented invocations no longer fail with an unknown option\n- updated the README example to show the current form while explicitly noting the compatibility alias\n- added an e2e regression test that exercises end-to-end\n\nValidation:\n- \n-

@nightcityblade
Copy link
Copy Markdown
Contributor Author

Follow-up with the correctly formatted details: addressed in 4c4fb25.

Changes:

  • restored commit-echo suggest --no-commit as a deprecated compatibility alias so existing documented invocations no longer fail with an unknown option
  • updated the README example to show the current commit-echo suggest form while explicitly noting the compatibility alias
  • added an e2e regression test that exercises suggest --no-commit end-to-end

Validation:

  • npm run build
  • node --test tests/e2e/suggest-smoke.test.mjs tests/suggest-dry-run.test.mjs tests/cli-help.test.mjs

@404-Page-Found
Copy link
Copy Markdown
Contributor

And resolve merge conflicts

@nightcityblade
Copy link
Copy Markdown
Contributor Author

Resolved the remaining merge conflicts on fix/issue-90-dry-run and pushed the updated branch in the merge commit above.

Re-ran:

  • npm run build
  • node --test tests/e2e/suggest-smoke.test.mjs tests/suggest-dry-run.test.mjs tests/cli-help.test.mjs

Copy link
Copy Markdown
Contributor

@404-Page-Found 404-Page-Found left a comment

Choose a reason for hiding this comment

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

Overview

This PR adds a --dry-run / -n flag to commit-echo suggest. When invoked, it prints the diff, style profile, resolved system/user prompts, and truncation status without making any LLM API call. It also retroactively documents --no-commit as a deprecated compatibility alias. Closes #90.

Files changed: 5 (387 additions, 91 deletions)


✅ What is good

  1. Clean architecture — The dry-run path reuses existing infrastructure (truncateDiff, resolveSystemPrompt, resolveUserPrompt, buildProfile, formatProfile) so its output is guaranteed to match what the real LLM call would receive. No duplication, no drift.

  2. Early return — The dry-run check returns before any spinner or LLM call, so --dry-run is instantaneous and has zero chance of accidentally hitting the API.

  3. formatDryRunOutput is well-factored — Pure function, exported, independently unit-testable. The output is clear and informative, showing each section under bold headers.

  4. Backward compatibility--no-commit is preserved and now explicitly documented as a deprecated alias. The new test confirms it still works.

  5. Unit tests cover the key paths — The three tests in tests/suggest-dry-run.test.mjs cover basic formatting, template variable substitution, and truncation display.


🚩 Required changes

1. String quote style contradicts Prettier config

The project's .prettierrc sets "singleQuote": true, but this PR converts all string literals in suggest.ts and index.ts from single quotes to double quotes. This means running npx prettier --check on these files will now fail.

The formatting changes also add a lot of noise to the diff (~200 of the 387 additions are just quote/style changes), making the actual logic harder to review.

Fix: Run npx prettier --write src/commands/suggest.ts src/index.ts to restore single-quote consistency, then force-push the corrected branch.

2. Missing E2E test for --dry-run itself

The dry-run path exercises the entire pipeline — config loading, git diff gathering, profile building, diff truncation, and prompt resolution — but there is no E2E test that actually runs commit-echo suggest --dry-run. The existing E2E test for --no-commit tests the CLI bootstrap but still hits the mock LLM server.

A single E2E test for --dry-run would validate that all the pieces wire together correctly without needing a mock HTTP server:

test("suggest --dry-run prints LLM inputs without calling the API", async (t) => {
  // ... setup ...
  const result = await runSuggestUntil(
    ["suggest", "--dry-run"],
    { cwd: repo, env, text: "Dry run: no LLM API call will be made." },
  );
  assert.match(result.stdout, /Style profile:/);
  assert.match(result.stdout, /System prompt:/);
  assert.match(result.stdout, /User prompt:/);
  assert.match(result.stdout, /Truncation:/);
  assert.doesNotMatch(result.stdout, /Suggestions generated:/);
});

🔍 Minor suggestions (not blocking)

  1. Consider showing the model name in dry-run output — The non-dry-run --verbose output prints the configured model. Including config.model in the dry-run output would give a complete picture of what the LLM call would look like:

    Model: gpt-4.1
    
  2. README could use a --dry-run example — Consider adding a --dry-run usage line near the existing suggest examples to make the new flag more discoverable.


📋 Summary

Category Verdict
Correctness Solid
Test coverage Good for unit tests, needs an E2E test
Code quality Clean, well-structured
Style/formatting Prettier incompatibility - must fix
Backward compat --no-commit preserved and documented
Security No concerns

Overall: A well-implemented feature with a clean architecture. The two required changes are: (1) run Prettier to fix the quote style to match the project config, and (2) add an E2E test for the --dry-run flag.

@404-Page-Found
Copy link
Copy Markdown
Contributor

Note: This PR also has merge conflicts with main that need to be resolved (currently showing as CONFLICTING). After fixing the Prettier quoting issue and adding the E2E test, rebase on the latest main and resolve the conflicts before force-pushing.

@nightcityblade
Copy link
Copy Markdown
Contributor Author

Addressed the latest review feedback in e6949fe.

Changes:

  • rebased/merged the branch onto the latest main; GitHub now reports the PR as mergeable
  • restored the project Prettier style on the touched TypeScript files, including single quotes
  • added an E2E test for commit-echo suggest --dry-run that verifies the dry-run output includes the LLM inputs and does not require/call an API key
  • kept the upstream API-key validation changes and ensured dry-run still bypasses API-key validation

Validation:

  • npm run build
  • npm run format:check
  • npm test
  • node --test tests/*.test.mjs tests/e2e/*.test.mjs

Copy link
Copy Markdown
Contributor

@404-Page-Found 404-Page-Found left a comment

Choose a reason for hiding this comment

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

Thanks for the implementation and test coverage expansion here. I’m requesting changes before merge due to one blocking process concern and a couple of important follow-ups.

Important (non-blocking but should be addressed in this PR)

  • There is significant formatting-only churn mixed with behavior changes in src/commands/suggest.ts and src/llm/client.ts. Please split/reduce unrelated formatting edits to make the functional diff easier to validate.
  • If available in your workflow, include test evidence in the PR description (or paste a short run summary) for the new dry-run and no-commit compatibility scenarios.

@nightcityblade
Copy link
Copy Markdown
Contributor Author

Addressed the latest follow-up in 7307d44.\n\nChanges:\n- merged the latest upstream main into fix/issue-90-dry-run\n- removed src/llm/client.ts from the PR diff entirely\n- reduced src/commands/suggest.ts to the dry-run behavior changes instead of formatting-only churn\n- updated the PR description with a concise test summary\n\nValidation:\n- npm run build\n- npm test\n- node --test tests/e2e/suggest-smoke.test.mjs tests/suggest-dry-run.test.mjs tests/cli-help.test.mjs\n- npm run format:check currently reports existing formatting differences in latest main files, so I left formatting untouched to avoid reintroducing churn.

@nightcityblade
Copy link
Copy Markdown
Contributor Author

Rechecked this follow-up today: the branch is up to date with current main and GitHub reports it as mergeable, so there are no remaining merge conflicts on the PR.\n\nI also reran the relevant validation locally:\n- npm run build ✅\n- npm test ✅\n- node --test tests/e2e/suggest-smoke.test.mjs tests/suggest-dry-run.test.mjs tests/cli-help.test.mjs ✅\n\nI did not push a formatting-only commit: running Prettier on src/commands/suggest.ts would reformat a large amount of pre-existing code and increase unrelated churn, while the PR body already notes the current format:check baseline.

Copy link
Copy Markdown
Contributor

@404-Page-Found 404-Page-Found left a comment

Choose a reason for hiding this comment

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

Review: feat: add dry-run mode to suggest

What's done well

  • Dry-run reuses the real prompt pipelinetruncateDiffresolveSystemPromptresolveUserPrompt guarantees the output exactly matches what would be sent to the API. Great design.
  • formatDryRunOutput is a pure, exported, well-tested function — easy to unit test, no side effects, clear contract.
  • --no-commit backward compat is correctly handled via Commander's --no- prefix.
  • Test coverage hits unit, template-parity, truncation-parity, and E2E scenarios.
  • README updated to reflect current usage.

Changes requested

1. Merge conflicts must be resolved (blocking)

The mergeable_state is currently blocked. Please rebase on latest main and resolve the conflicts before this can be merged.

2. Add a deprecation warning for --no-commit

--no-commit is silently accepted with no signal to users that they should migrate. When someone runs commit-echo suggest --no-commit, they should see a brief note. Something like:

if (options.noCommit) {
  console.warn(pc.yellow("Note: --no-commit is deprecated; 'commit-echo suggest' already skips committing."));
}

The --no-commit option currently maps to Commander's built-in --no- prefix on the --commit boolean, so detecting it requires either:

  • Adding a separate --no-commit option and checking it explicitly, or
  • Using program.parseOptions hooks, or
  • A simpler approach: add a dedicated --no-commit option that sets a flag you can check.

This is a minor UX improvement but worth addressing for a clean deprecation path.

3. Move tests/suggest-dry-run.test.mjs to tests/e2e/

This file spawns the CLI process (process.execPath + dist/index.js) — it's functionally an E2E test. The existing convention places E2E tests under tests/e2e/. Please move it to tests/e2e/suggest-dry-run.test.mjs for consistency with the rest of the test suite.

4. Separate formatting changes from the feature

The diff includes many Prettier-driven whitespace reformatting changes in tests/e2e/suggest-smoke.test.mjs (wrapping long objects into multi-line, reformatting arrow functions). These are cosmetic and inflate the diff. Consider:

  1. Run npx prettier --write . in a standalone commit on main first
  2. Rebase this PR on top of that formatting commit

This keeps the feature diff clean and reviewable.

@nightcityblade
Copy link
Copy Markdown
Contributor Author

Thanks for the review — I pushed an update addressing the requested items:

  • Confirmed the branch is already based on the latest upstream/main and is mergeable.
  • Added a visible deprecation warning for commit-echo suggest --no-commit.
  • Moved tests/suggest-dry-run.test.mjs to tests/e2e/suggest-dry-run.test.mjs.
  • Removed the unrelated formatting churn from tests/e2e/suggest-smoke.test.mjs.

Validation run locally:

npm run build
node --test tests/e2e/suggest-dry-run.test.mjs tests/e2e/suggest-no-commit-deprecation.test.mjs tests/e2e/suggest-smoke.test.mjs

Both passed (7 tests). I also ran npm run format:check; it still reports existing formatting warnings in src/commands/init.ts, src/commands/suggest.ts, src/git/hook.ts, and src/llm/client.ts, so I left those untouched to avoid adding a broad formatting commit to this PR.

@nightcityblade nightcityblade force-pushed the fix/issue-90-dry-run branch from fd5784d to ca993b1 Compare June 6, 2026 03:22
@nightcityblade
Copy link
Copy Markdown
Contributor Author

Addressed the latest review feedback and force-pushed an updated branch.

Changes in this push:

  • rebased the PR onto the current main and resolved the merge-conflict state
  • kept --no-commit as a deprecated compatibility alias and added a visible deprecation warning
  • split the dry-run coverage into a real CLI E2E test under tests/e2e/ plus a separate output-format unit test
  • kept the diff focused on the dry-run feature/tests and refreshed the README examples

Validation run:

  • npm test
  • node --test tests/suggest-dry-run-output.test.mjs
  • npx prettier --check src/index.ts src/commands/suggest.ts tests/e2e/suggest-dry-run.test.mjs tests/e2e/suggest-no-commit-deprecation.test.mjs tests/suggest-dry-run-output.test.mjs

@404-Page-Found
Copy link
Copy Markdown
Contributor

Conflict resolution for fix/issue-90-dry-run

Two files conflict because main added streaming support since this branch diverged.

src/commands/suggest.ts

  1. Imports — start from main's import block, then add the PR's new imports:

    • getBranchName from ../git/diff.js
    • resolveSystemPrompt, resolveUserPrompt, truncateDiff from ../llm/prompt.js
  2. Options type — add dryRun?: boolean and noCommit?: boolean alongside the existing stream?: boolean.

  3. Early return — insert the dryRun block (with formatDryRunOutput) after diff detection, before the API key check. Add the noCommit deprecation warning before it. Keep all existing streaming/non-streaming code below unchanged.

  4. Add the formatDryRunOutput function from the PR diff.

src/index.ts

Add alongside existing --stream:

.option('-n, --dry-run', 'Show the LLM input without generating suggestions')
.option('--no-commit', 'Deprecated alias; suggest already skips committing unless --commit is passed')

And pass dryRun + noCommit in the action handler, keeping stream: Boolean(options.stream).

After resolving

npm run build && npm test
node --test tests/e2e/suggest-dry-run.test.mjs tests/e2e/suggest-no-commit-deprecation.test.mjs tests/e2e/suggest-smoke.test.mjs

@nightcityblade nightcityblade force-pushed the fix/issue-90-dry-run branch from ca993b1 to 7c26a53 Compare June 6, 2026 15:06
@nightcityblade
Copy link
Copy Markdown
Contributor Author

Thanks — I resolved the latest main conflicts on fix/issue-90-dry-run and force-pushed the updated branch.

What I aligned with your notes:

  • started from main's streaming-aware suggest flow, then re-applied the dry-run imports/options/early-return before API-key validation
  • kept the --no-commit deprecation warning
  • kept both --stream and --dry-run wired in src/index.ts

Validation:

  • npm run build
  • npm test
  • node --test tests/e2e/suggest-dry-run.test.mjs tests/e2e/suggest-no-commit-deprecation.test.mjs tests/e2e/suggest-smoke.test.mjs

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 6, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e81c287-839f-4433-b14c-746a9aadc2cb

📥 Commits

Reviewing files that changed from the base of the PR and between 8fc83e1 and 7c26a53.

📒 Files selected for processing (6)
  • README.md
  • src/commands/suggest.ts
  • src/index.ts
  • tests/e2e/suggest-dry-run.test.mjs
  • tests/e2e/suggest-no-commit-deprecation.test.mjs
  • tests/suggest-dry-run-output.test.mjs

📝 Walkthrough

Walkthrough

This PR implements a --dry-run flag for the suggest command that displays the diff, resolved prompts, style profile, and truncation metadata without calling the LLM. It also deprecates the --no-commit flag. Changes span CLI registration, a new output formatter, command refactoring, comprehensive tests, and documentation updates.

Changes

Dry-Run Flag Implementation

Layer / File(s) Summary
CLI Dry-Run Flag Registration
src/index.ts
Adds -n/--dry-run flag to show LLM input without generating suggestions and --no-commit as a deprecated alias. Both flags are wired through to suggestCommand as dryRun and noCommit parameters.
Dry-Run Output Formatter and Unit Tests
src/commands/suggest.ts, tests/suggest-dry-run-output.test.mjs
Exports formatDryRunOutput() function that assembles a colorized report containing diff, profile summary, resolved system/user prompts, and truncation status. Unit tests verify correct rendering of all sections, proper template substitution with branch/profile/diff placeholders, and accurate truncation metrics.
Suggest Command Refactoring and Dry-Run Flow
src/commands/suggest.ts
Updates imports to add git and prompt resolution helpers. Extends option destructuring with dryRun and noCommit, adds deprecation warning when --no-commit is used. Moves profile construction earlier in the flow. Implements dry-run path: truncates diff, builds template variables, resolves prompts, prints formatted output, and returns early without API call. Removes explanatory comments from streaming/non-streaming code paths.
End-to-End Test Coverage
tests/e2e/suggest-dry-run.test.mjs, tests/e2e/suggest-no-commit-deprecation.test.mjs
E2E test validates suggest --dry-run prints prompts and truncation output without LLM API calls or generation messages. Separate E2E test confirms suggest --no-commit emits deprecation warning on stderr and completes with exit code 0.
Documentation Update
README.md
Updates the "Generate suggestions without committing" section to document commit-echo suggest as the primary command and notes that --no-commit is accepted only as a deprecated compatibility alias.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A dry-run flag springs to life, 🐰✨
Showing prompts before they take the LLM flight,
No API calls needed tonight—
Just a peek at the diff in full sight,
While --no-commit bids its fair goodbye!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add dry-run mode to suggest' clearly and specifically summarizes the main change: adding dry-run functionality to the suggest command.
Linked Issues check ✅ Passed The code changes fully implement the objectives from issue #90: the --dry-run flag with -n alias is added, diff/prompts/profile/truncation info are printed, no API call occurs in dry-run mode, --no-commit compatibility is maintained, and builds pass.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #90: CLI flags added to src/index.ts, dry-run logic and formatDryRunOutput implemented in src/commands/suggest.ts, README documentation updated, and comprehensive unit and E2E tests added for dry-run and no-commit deprecation.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

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.

Add --dry-run flag to commit-echo suggest

2 participants