-
Notifications
You must be signed in to change notification settings - Fork 1.9k
fix: fall back to repo default_branch instead of hardcoded "main" #1143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 The new test "prepare falls back to repository.default_branch when not 'main'" does not save/restore
CLAUDE_ARGS, unlike the adjacent test that explicitly manages it. If the preceding test fails at an assertion before itsdelete process.env.CLAUDE_ARGScleanup (line 104), the leaked value would flow intoprepareAgentModeand appear inclaudeArgsoutput — though the test assertions only coverbranchInfofields so they would still pass.Extended reasoning...
Analysis
The new test added at lines 113-163 of
test/modes/agent.test.tsdoes not save or restoreCLAUDE_ARGS, unlike the immediately preceding test "prepare passes through claude_args" which explicitly setsprocess.env.CLAUDE_ARGS = "--model claude-sonnet-4 --max-turns 10"and cleans it up withdelete process.env.CLAUDE_ARGSat the end of the test body.How the bug manifests
In
src/modes/agent/index.ts,CLAUDE_ARGSis read unconditionally:const userClaudeArgs = process.env.CLAUDE_ARGS || "";. This value flows into theclaudeArgsreturn field. If the preceding test fails mid-execution — for example, if one of itsexpect()assertions throws before reaching the cleanup block —CLAUDE_ARGSremains set in the process environment and is inherited by the new test.Why existing code doesn't prevent it
The test cleanup for
CLAUDE_ARGSin the preceding test is done inline in the test body (not inafterEach), so it is not guaranteed to run on failure. TheafterEachhook only restores spies, not environment variables. This is a gap that the new test inherits rather than defending against.Impact
If the leak occurs,
prepareAgentModewill include--model claude-sonnet-4 --max-turns 10in itsclaudeArgsoutput instead of an empty string. The new test only asserts onresult.branchInfo.baseBranchandresult.branchInfo.currentBranch, which are derived fromcontext.repository.default_branch— completely unaffected byCLAUDE_ARGS. So the test passes even with leaked state, silently masking the unexpected behavior. This is a test quality/robustness issue, not a correctness issue for production code.Addressing the refutation
The refutation correctly notes that (a) the prior test does clean up
CLAUDE_ARGSunder normal execution, and (b) the new test's assertions are unaffected byCLAUDE_ARGS. Both points are true. However, the fragility comes from the failure path: if the prior test throws before line 104, cleanup is skipped. The refutation does not address this failure-path scenario. The inconsistency with the surrounding cleanup pattern is also a readability/maintenance concern — future readers may not realize this test is not defensive against env leakage.Proof of fragility
Step-by-step: (1) Prior test sets
process.env.CLAUDE_ARGS = "--model claude-sonnet-4 --max-turns 10". (2) An assertion in the prior test fails, throwing beforedelete process.env.CLAUDE_ARGSat line 104. (3) The new test runs withCLAUDE_ARGSstill set. (4)prepareAgentModereadsCLAUDE_ARGSand buildsclaudeArgs = "--model claude-sonnet-4 --max-turns 10". (5) The new test assertionsexpect(result.branchInfo.baseBranch).toBe("develop")andexpect(result.branchInfo.currentBranch).toBe("develop")both pass sinceCLAUDE_ARGSdoes not affect branch info. (6) The test suite reports a passing test, but the behavior being tested has unexpected side effects that go undetected.Fix
Add
const originalClaudeArgs = process.env.CLAUDE_ARGS;before the test body and restore/delete it in the cleanup block alongside the other env var restorations, matching the pattern used in the same test forCLAUDE_BRANCH,GITHUB_HEAD_REF, andGITHUB_REF_NAME.