fix(auto-pr): detect catstack work from a session in another repo - #472
Merged
Conversation
repo_root() decided which repository it was looking at from the session's cwd
alone, so a session working in another repo that edits catstack through an
absolute path or a worktree got no reminder at all.
That is what happened today: engine/hooks/unverified-tag-ledger and install.sh
were written and committed from a session whose cwd was a different repo, the
Stop hook stayed silent every turn, and both PRs went up with no draft-pr
schema until the user noticed.
cwd stays the first check and is unchanged. When it does not resolve to
catstack, repo_root() now reads the file paths this session's tool calls named
and runs each through the same _accept_root() gate, so the fallback can only
ever widen detection and can never return a directory outside catstack.
Replayed against the real transcript of that session, cwd left as its own:
BEFORE repo_root -> None decide -> None
AFTER repo_root -> .../catstack/.worktrees/autopr-foreign
decide -> "catstack changes detected on branch ..."
30 tests pass, including a positive case (foreign cwd + a touched catstack
path fires), a negative case (touched paths outside catstack stay silent), an
unchanged-behaviour case for a cwd inside catstack, and an unreadable
transcript reporting on stderr rather than failing quietly.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u8S5ct3kFhosinSbybc7W
Change-Id: I77563afdcde6b7dde30dc046ff69ab637648d84f
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_94cd25ee-2aa3-4cdd-828f-376595bb7e92) |
Contributor
|
Queued — the merge queue status continues in this comment ↓. |
Owner
Author
|
@Mergifyio queue |
Contributor
Merge Queue Status
This pull request spent 2 minutes 34 seconds in the queue, with no time running CI. Waiting for
All conditions
ReasonPull request #472 has been merged manually at de78102 HintYou were too fast! Tick the box to put this pull request back in the merge queue (same as
|
5 tasks
Contributor
☑️ The pull request has been merged manuallyDetailsThe pull request has been merged manually at de78102 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The reminder to open a catstack PR only appears when the session is working
inside catstack.
It decides which repo it is looking at from the session's working directory. A
session sitting in another repo, editing catstack through a full path or a
worktree, gets nothing.
That happened today. A hook and an
install.shchange were written from asession working in another repo.
No reminder fired, and the PRs went up with no schema.
Now it also reads the file paths the session touched. If any live in catstack,
the reminder fires.
Review Claim
repo_root()falls back to the catstack paths this session's tool calls namedwhen the working directory belongs to another repository.
Review Lane
behavior
Review Unit
engine-runtime
Safety Invariant
The working-directory check runs first and is unchanged, so every session that
fired before still fires identically. The fallback only ever widens detection,
and
_accept_root()— the same function the working-directory path uses — stillgates every candidate, so no directory outside catstack can be returned. Reads
are the transcript file and read-only git; nothing writes.
Slice Rationale
This is one function's input, separable from everything else in the hook. The
diff-debounce, the once-per-diff marker, and the instruction text are untouched,
so a reviewer only has to agree that touched paths are a valid second signal for
which repo the session edited.
Non-goals
RELEVANT_PREFIXES, so the same paths count as relevant.CLAUDE.core.mdtriggers thePR skill on being asked, so agreeing to an agent's own offer ("yes") matches
no trigger. That is a prose change, filed separately.
Architecture
Before
graph TD A["Stop fires"] --> B["repo_root: read session cwd"] B --> C{"is cwd inside catstack?"} C -->|"yes"| D["check diff, remind once idle"] C -->|"no"| E["silent, even if catstack was edited"]After
graph TD A["Stop fires"] --> B["repo_root: read session cwd"] B --> C{"is cwd inside catstack?"} C -->|"yes"| D["check diff, remind once idle"] C -->|"no"| F["read paths this session's tools named"] F --> G{"any path inside catstack?"} G -->|"yes"| D G -->|"no"| E["silent"]Test Plan
Test Plan
cd engine/hooks/auto-pr && python3 -m unittest discover -s testspython3 engine/skills/make-pr/scripts/preflight.py --base origin/mainpython3 scripts/check_no_new_comments.pypython3 scripts/check_ecosystem_boundaries.pyReplayed against the real transcript of the session that missed it, cwd left as
that session's own (
empathy_ai):Suite and gates on this branch:
Fixture vs live: the before/after replay above is the real transcript, not a
fixture. The hook is installed on this machine as a symlink into the primary
checkout, so this branch's version has not itself run as the installed hook:
Revert Plan
Revert Plan
git revert <sha>