Skip to content

fix(spec-stop-guard): ignore active plan outside current project#156

Closed
presempathy-awb wants to merge 1 commit into
maxritter:mainfrom
presempathy-awb:fix/spec-stop-guard-cross-session-bleed
Closed

fix(spec-stop-guard): ignore active plan outside current project#156
presempathy-awb wants to merge 1 commit into
maxritter:mainfrom
presempathy-awb:fix/spec-stop-guard-cross-session-bleed

Conversation

@presempathy-awb
Copy link
Copy Markdown
Contributor

@presempathy-awb presempathy-awb commented May 31, 2026

Problem

When PILOT_SESSION_ID is unset, the session-scoped active_plan.json collapses to the shared default file. A /spec plan registered by another repo's session then leaks into an unrelated repo's session through that shared file, and spec_stop_guard.py blocks stops on a plan that has nothing to do with the current project.

Observed: a COMPLETE plan in repo A blocked every stop in an unrelated repo B's session ("you cannot stop…"), with no clean way to clear it short of hand-editing the shared state.

Fix

Scope the guard to plans that actually live inside the current project root:

  • _current_project_root() resolves CLAUDE_PROJECT_ROOT → git root → cwd.
  • _plan_in_current_project() returns False when the registered plan path is outside that root, so find_active_plan() returns (None, None) and the guard stays out of the way.
  • Fails open: if the project root can't be determined it returns True (legacy behaviour), so legitimate same-project guarding is never weakened.

Tests

Two new tests in TestSessionScopedPlanDetection:

  • test_ignores_plan_outside_current_project — reproduces the bleed: a foreign-project plan must not block.
  • test_blocks_absolute_plan_inside_current_project — guards against over-suppression: an absolute plan path inside the current project still blocks.

42 passed locally (pytest pilot/hooks/tests/test_spec_stop_guard.py).

Notes

Additive and non-breaking — no change to behaviour when a single session/project is involved. Surfaced while running /spec in one repo with a stale COMPLETE plan registered from another.


Summary by cubic

Prevented cross-session bleed in spec_stop_guard so a plan from another repo no longer blocks stops when PILOT_SESSION_ID is unset. The guard now only applies to plans inside the current project.

  • Bug Fixes
    • Scope active plan checks to the current project root: CLAUDE_PROJECT_ROOT → git root → cwd.
    • Fail open if the root can’t be determined to preserve same-project guarding.
    • Added tests to ensure foreign-project plans are ignored and in-project plans still block.

Written for commit 94874e7. Summary will update on new commits.

Review in cubic

When PILOT_SESSION_ID is unset, the session-scoped active_plan.json
collapses to the shared "default" file. A /spec plan registered by
another repo's session (e.g. a COMPLETE plan in repo A) then leaks into
an unrelated repo B's session and blocks its stops — the guard fires on
a plan that has nothing to do with the current project.

Scope the guard to plans that actually live inside the current project
root (CLAUDE_PROJECT_ROOT, else git root, else cwd). Fails open
(returns True -> legacy behaviour) when the root can't be determined, so
legitimate same-project guarding is never weakened.

Adds two tests: a foreign-project plan must not block; an absolute plan
path inside the current project still blocks.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 31, 2026

@presempathy-awb is attempting to deploy a commit to the Max Ritter Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (2)
  • pilot/hooks/spec_stop_guard.py is excluded by !pilot/**
  • pilot/hooks/tests/test_spec_stop_guard.py is excluded by !pilot/**

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 65c3946b-0c76-4ef7-9022-0913566fea48

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

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

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

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

Tip: cubic could auto-approve low-risk PRs like this, if it thinks it's safe to merge. Learn more

Re-trigger cubic

@maxritter maxritter self-assigned this Jun 1, 2026
@maxritter
Copy link
Copy Markdown
Owner

@presempathy-awb Thanks for your contribution, this has been applied in version 9.2.0. I hope you enjoy using Pilot Shell :)

@maxritter maxritter closed this Jun 1, 2026
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