feat(cli, wizard): support plan mode in wizard#435
Conversation
🦋 Changeset detectedLatest commit: 1a97d40 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughThis PR introduces plan-mode support to the Stash wizard CLI. The wizard now accepts a ChangesPlan Mode Support
Sequence DiagramsequenceDiagram
participant User
participant CLI as stash CLI
participant WizardBin as wizard binary
participant Gather as gatherContext()
participant Agent as Agent / LLM
participant Gateway as Gateway API
participant Finalize as finalize()
User->>CLI: stash plan (or stash impl)
CLI->>CLI: Determine mode: 'plan' or 'implement'
CLI->>WizardBin: Spawn with --mode <plan|implement>
WizardBin->>WizardBin: parseArgs() → mode
WizardBin->>Gather: gatherContext({..., mode})
alt plan mode
Gather->>Gather: Skip column selection (empty list)
Gather-->>WizardBin: GatheredContext
else implement mode
Gather->>Gather: Prompt & select columns
Gather-->>WizardBin: GatheredContext
end
WizardBin->>Agent: Initialize agent
WizardBin->>Gateway: fetchIntegrationPrompt({..., mode})
Gateway-->>WizardBin: Prompt (plan-specific or impl-specific)
WizardBin->>Agent: Execute agent with prompt
alt plan mode
Agent-->>WizardBin: Agent result
WizardBin->>WizardBin: Write .cipherstash/plan.md
WizardBin->>Finalize: finalize()
else implement mode
WizardBin->>WizardBin: Start call-site scan (background)
Agent-->>WizardBin: Agent result
WizardBin->>WizardBin: Run post-agent steps
WizardBin->>WizardBin: Await scan result
WizardBin->>Finalize: finalize()
end
Finalize->>Finalize: Install Claude skills
Finalize->>Finalize: Record completion telemetry
Finalize->>Finalize: Flush changelog
Finalize-->>WizardBin: Done
WizardBin-->>User: Output outro + next steps
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/wizard/src/lib/gather.ts (1)
9-16: 💤 Low valueMinor: two separate
importblocks fromnode:fscould be merged.
closeSyncis imported in its own statement (Line 16) separate from the five othernode:fsimports (Lines 9–15). No functional impact, but a single block is conventional.♻️ Proposed merge
import { existsSync, openSync, readFileSync, readSync, readdirSync, + closeSync, } from 'node:fs' -import { closeSync } from 'node:fs'🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/wizard/src/lib/gather.ts` around lines 9 - 16, Merge the two separate node:fs import statements into one by combining existsSync, openSync, readFileSync, readSync, readdirSync and closeSync into a single import declaration; locate the imports at the top of the file where existsSync, openSync, readFileSync, readSync, readdirSync and closeSync are currently imported separately and consolidate them into one import from 'node:fs' to follow convention and reduce redundancy.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/wizard/src/bin/parse-args.ts`:
- Around line 36-46: The space-separated --mode branch in parse-args.ts
currently skips setting modeError when --mode is the last argument; update the
if (arg === '--mode' && i + 1 < args.length) branch so that when i + 1 >=
args.length you set modeError to a clear message (e.g., "Missing value for
--mode; expected 'plan' or 'implement'") instead of silently falling through;
keep the existing validation for next === 'plan' || 'implement' and increment i
when you consume the value, and ensure mode remains unchanged when modeError is
set.
---
Nitpick comments:
In `@packages/wizard/src/lib/gather.ts`:
- Around line 9-16: Merge the two separate node:fs import statements into one by
combining existsSync, openSync, readFileSync, readSync, readdirSync and
closeSync into a single import declaration; locate the imports at the top of the
file where existsSync, openSync, readFileSync, readSync, readdirSync and
closeSync are currently imported separately and consolidate them into one import
from 'node:fs' to follow convention and reduce redundancy.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 469af2af-53e6-4dab-b600-716d4dd3bfff
📒 Files selected for processing (18)
.changeset/wizard-plan-mode.mdpackages/cli/src/commands/impl/__tests__/how-to-proceed.test.tspackages/cli/src/commands/impl/steps/handoff-wizard.tspackages/cli/src/commands/impl/steps/how-to-proceed.tspackages/wizard/src/__tests__/parse-args.test.tspackages/wizard/src/agent/__tests__/interface.test.tspackages/wizard/src/agent/fetch-prompt.tspackages/wizard/src/agent/hooks.tspackages/wizard/src/agent/interface.tspackages/wizard/src/bin/parse-args.tspackages/wizard/src/bin/wizard.tspackages/wizard/src/lib/detect.tspackages/wizard/src/lib/format.tspackages/wizard/src/lib/gather.tspackages/wizard/src/lib/prerequisites.tspackages/wizard/src/lib/types.tspackages/wizard/src/run.tsskills/stash-cli/SKILL.md
| if (arg === '--mode' && i + 1 < args.length) { | ||
| const next = args[i + 1] ?? '' | ||
| if (next === 'plan' || next === 'implement') { | ||
| mode = next | ||
| i++ | ||
| } else { | ||
| modeError = `Unknown --mode value: ${next}. Expected 'plan' or 'implement'.` | ||
| break | ||
| } | ||
| continue | ||
| } |
There was a problem hiding this comment.
--mode with no trailing value is silently ignored instead of producing a modeError.
When --mode appears as the final argument, i + 1 < args.length is false and the entire branch is skipped — leaving mode as 'implement' with no diagnostic. The --mode= form correctly surfaces an error for a missing/invalid value; the space-separated form should behave consistently.
🛡️ Proposed fix
- if (arg === '--mode' && i + 1 < args.length) {
- const next = args[i + 1] ?? ''
+ if (arg === '--mode') {
+ if (i + 1 >= args.length) {
+ modeError = `--mode requires a value. Expected 'plan' or 'implement'.`
+ break
+ }
+ const next = args[i + 1]
if (next === 'plan' || next === 'implement') {
mode = next
i++
} else {
modeError = `Unknown --mode value: ${next}. Expected 'plan' or 'implement'.`
break
}
continue
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (arg === '--mode' && i + 1 < args.length) { | |
| const next = args[i + 1] ?? '' | |
| if (next === 'plan' || next === 'implement') { | |
| mode = next | |
| i++ | |
| } else { | |
| modeError = `Unknown --mode value: ${next}. Expected 'plan' or 'implement'.` | |
| break | |
| } | |
| continue | |
| } | |
| if (arg === '--mode') { | |
| if (i + 1 >= args.length) { | |
| modeError = `--mode requires a value. Expected 'plan' or 'implement'.` | |
| break | |
| } | |
| const next = args[i + 1] | |
| if (next === 'plan' || next === 'implement') { | |
| mode = next | |
| i++ | |
| } else { | |
| modeError = `Unknown --mode value: ${next}. Expected 'plan' or 'implement'.` | |
| break | |
| } | |
| continue | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/wizard/src/bin/parse-args.ts` around lines 36 - 46, The
space-separated --mode branch in parse-args.ts currently skips setting modeError
when --mode is the last argument; update the if (arg === '--mode' && i + 1 <
args.length) branch so that when i + 1 >= args.length you set modeError to a
clear message (e.g., "Missing value for --mode; expected 'plan' or 'implement'")
instead of silently falling through; keep the existing validation for next ===
'plan' || 'implement' and increment i when you consume the value, and ensure
mode remains unchanged when modeError is set.
Summary by CodeRabbit
New Features
--plan/--implement/--mode <plan|implement>CLI flags to the wizard for toggling between planning and implementation workflows..cipherstash/plan.mddeliverable and skips column selection and post-implementation steps.Improvements
stash planvsstash impl).Documentation
stash init → stash plan → stash impl → stash statuslifecycle workflow.