Skip to content

fix(cli): detect plan before impl commences#441

Open
calvinbrewer wants to merge 3 commits into
mainfrom
phased-plans
Open

fix(cli): detect plan before impl commences#441
calvinbrewer wants to merge 3 commits into
mainfrom
phased-plans

Conversation

@calvinbrewer
Copy link
Copy Markdown
Contributor

@calvinbrewer calvinbrewer commented May 11, 2026

Summary by CodeRabbit

  • Bug Fixes
    • Improved status command guidance: The stash status command now properly distinguishes between "no encryption rollout plan drafted yet" and "plan already drafted but not executed." When a plan exists, users are now directed to run stash impl to execute the drafted plan, rather than being directed to create a new plan first.

Review Change Stack

@calvinbrewer calvinbrewer requested a review from a team as a code owner May 11, 2026 19:44
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 11, 2026

🦋 Changeset detected

Latest commit: 5d8e699

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
stash Patch
@cipherstash/e2e Patch

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

📝 Walkthrough

Walkthrough

This PR adds a planExists field to the status command's quest log to distinguish between "no plan drafted yet" and "plan drafted but not executed." The status command now routes users to stash impl when a plan exists but no migrations have started, instead of always suggesting stash plan.

Changes

Status Command Plan Existence Tracking

Layer / File(s) Summary
Data Model
packages/cli/src/commands/status/quest.ts
QuestLog type adds planExists: boolean field. buildQuestLog input signature and return value updated to accept and propagate planExists.
Status Command Logic
packages/cli/src/commands/status/index.ts
buildLog forwards ProjectStatus.planExists to buildQuestLog. nextMoveHint branches on planExists when no quests exist: true routes to impl, false routes to plan.
Rendering
packages/cli/src/commands/status/render.ts
renderQuestLogTTY and renderQuestLogPlain conditionally render empty-state guidance: plan-drafted branches show .cipherstash/plan.md path and impl command; no-plan branches retain original guidance. renderQuestLogJSON includes planExists in output.
Tests
packages/cli/src/commands/status/__tests__/status.test.ts
All buildQuestLog(...) calls updated to pass planExists parameter. New test cases added for plan-drafted/no-quests scenario in TTY and plain renderers. renderQuestLogJSON and nextMoveHint tests extended to validate planExists field and routing.
Release Notes
.changeset/ten-deserts-hammer.md
Documents updated stash status behavior for plan-drafted-but-not-executed state.

Sequence Diagram

sequenceDiagram
    participant Status as statusCommand
    participant BuildLog as buildLog
    participant BuildQuest as buildQuestLog
    participant Render as renderQuestLog*
    participant ProjectStatus as ProjectStatus

    Status->>ProjectStatus: read planExists
    Status->>BuildLog: call with project state
    BuildLog->>ProjectStatus: extract planExists
    BuildLog->>BuildQuest: call with planExists
    BuildQuest->>BuildQuest: populate QuestLog.planExists
    BuildQuest-->>BuildLog: return QuestLog with planExists
    BuildLog->>Render: call with QuestLog
    Render->>Render: branch on planExists<br/>true: show impl + plan.md<br/>false: show plan guidance
    Render-->>Status: rendered output
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • cipherstash/stack#439: Also modifies CLI status/quest/render logic and tests to surface plan presence and route status output between impl and plan steps.

Suggested reviewers

  • auxesis

Poem

🐰 A plan was drafted, but not yet begun,
Now status sees this and points users to impl with great fun!
No more confusing suggestions to plan,
The quest log flows true with this boolean span! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: improving the detection of whether a plan file exists before the implementation phase commences, which is the core purpose of distinguishing plan-drafted vs non-existent states in the status command.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 phased-plans

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

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.

🧹 Nitpick comments (1)
packages/cli/src/commands/status/__tests__/status.test.ts (1)

408-410: ⚡ Quick win

Consider using a simpler assertion to avoid the ReDoS warning.

The RegExp is constructed from the CLI variable, which triggers a static analysis warning about potential ReDoS. While this is a false positive in the test context (CLI is a constant), you can eliminate the warning by using a simpler assertion approach.

🔧 Proposed refactor to avoid ReDoS warning
-    expect(out).not.toMatch(
-      new RegExp(`${CLI.replace(/ /g, '\\s')}\\s+plan\\b`),
-    )
+    // Ensure we don't suggest running plan when a plan already exists
+    expect(out).not.toContain(`${CLI} plan`)

This simpler check achieves the same goal (ensuring we don't suggest plan when a plan exists) while avoiding the regex complexity warning.

🤖 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/cli/src/commands/status/__tests__/status.test.ts` around lines 408 -
410, Replace the regex-based assertion that uses CLI with a simple substring
check to avoid the ReDoS warning: locate the assertion using
expect(out).not.toMatch(new RegExp(`${CLI.replace(/ /g, '\\s')}\\s+plan\\b`))
and change it to a plain string containment assertion such as
expect(out).not.toContain(`${CLI} plan`) (or use !out.includes(`${CLI} plan`))
to achieve the same negative check without constructing a RegExp from the CLI
variable.
🤖 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.

Nitpick comments:
In `@packages/cli/src/commands/status/__tests__/status.test.ts`:
- Around line 408-410: Replace the regex-based assertion that uses CLI with a
simple substring check to avoid the ReDoS warning: locate the assertion using
expect(out).not.toMatch(new RegExp(`${CLI.replace(/ /g, '\\s')}\\s+plan\\b`))
and change it to a plain string containment assertion such as
expect(out).not.toContain(`${CLI} plan`) (or use !out.includes(`${CLI} plan`))
to achieve the same negative check without constructing a RegExp from the CLI
variable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1044405f-14de-4e45-9fcb-a8ceb8a888aa

📥 Commits

Reviewing files that changed from the base of the PR and between 8721076 and 5d8e699.

📒 Files selected for processing (5)
  • .changeset/ten-deserts-hammer.md
  • packages/cli/src/commands/status/__tests__/status.test.ts
  • packages/cli/src/commands/status/index.ts
  • packages/cli/src/commands/status/quest.ts
  • packages/cli/src/commands/status/render.ts

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.

2 participants