agentHost: stop a failed git probe from stalling Agent Merge - #331792
Merged
Benjamin Christopher Simmonds (benibenj) merged 2 commits intoAug 20, 2026
Merged
Conversation
A session with Agent Merge enabled could sit idle forever without ever
binding to its pull request, so review comments and CI failures never
reached it.
`_computeSessionGitState` treats every probe as independent and populates
fields best-effort. When `git status` failed -- most often a timeout under
load, which writes nothing to stderr and so logged nothing at all -- it
still returned an object, just without a branch. `_setSessionGitState`
replaces persisted git state wholesale, so that object overwrote the good
branch with `{"baseBranchName":"main"}`.
Nothing then repaired it. `AgentMergeController._evaluate` bails on a
missing branch before it reaches the refresh that would recompute it, and
the lazy refresh on subscribe only fires when git state is entirely
absent, so a partial state masked it. For a session held resident by Agent
Merge alone -- no client watching, no edits landing -- neither of the
remaining refresh triggers fires either, leaving it to re-read the same
stale state on the 10 minute backstop indefinitely.
- Return `undefined` from `_computeSessionGitState` when the status probe
fails, so callers keep the state they already had.
- Refresh git state in `_evaluate` before giving up on the branch, which
also recovers sessions already holding a branch-less state.
- Treat a branch-less state as missing in the subscribe-time refresh.
- Log git failures that produce no stderr, so a timed-out probe is no
longer invisible.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot started reviewing on behalf of
Benjamin Christopher Simmonds (benibenj)
August 20, 2026 13:03
View session
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Prevents Agent Merge from stalling indefinitely when persisted session git state loses its branch (e.g., after a failed git status probe), by avoiding persistence of misleading partial git state and adding a repair path that refreshes git state when a branch is missing.
Changes:
- Add a recovery path in
AgentMergeControllerthat refreshes session git state when no branch is available. - Make
AgentHostGitServicereturnundefined(instead of partial state) whengit statusfails, and improve logging for silent failures/timeouts. - Add/extend tests to cover the “probe fails → no git state persisted” behavior and the Agent Merge recovery behavior.
Show a summary per file
| File | Description |
|---|---|
| src/vs/platform/agentHost/test/node/agentMergeController.test.ts | Adds a regression test ensuring Agent Merge recovers when persisted git state is missing a branch. |
| src/vs/platform/agentHost/test/node/agentHostGitService.integrationTest.ts | Adds an integration test verifying that a failed status probe yields no git state (prevents persisting partial state). |
| src/vs/platform/agentHost/node/agentService.ts | Treats “git state with no branchName” as missing to trigger lazy git-state repair for watchers. |
| src/vs/platform/agentHost/node/agentMergeController.ts | Adds branch resolution + repair (_resolveCurrentBranch) to unblock Agent Merge when branch is missing. |
| src/vs/platform/agentHost/node/agentHostGitService.ts | Avoids returning/persisting partial git state when git status fails; improves failure logging in _runGit. |
Review details
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 5/5 changed files
- Comments generated: 2
- Review effort level: Lite
Dirk Bäumer (dbaeumer)
previously approved these changes
Aug 20, 2026
Addresses PR review feedback: keying the repair off a missing `branchName` alone also matched a detached HEAD, which reports no branch by design. Those sessions would have refreshed git state on every evaluation -- a periodic git call and log noise that could never produce a branch. `parseGitStatusV2` already recognises `(detached)`; it now reports that as `isDetachedHead` so the distinction survives into persisted session git state, and a shared `needsSessionGitStateRefresh` predicate keeps the Agent Merge and subscribe-time call sites in agreement about which states are worth recomputing. The controller additionally caps the repair at one attempt per runtime, so any other checkout that cannot report a branch costs a single git call rather than one per backstop, and logs a warning when a refresh still yields no branch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ben Villalobos (benvillalobos)
approved these changes
Aug 20, 2026
Benjamin Christopher Simmonds (benibenj)
merged commit Aug 20, 2026
56a267c
into
main
44 of 45 checks passed
Benjamin Christopher Simmonds (benibenj)
deleted the
benibenj/agents/agent-merge-issue-investigation
branch
August 20, 2026 20:12
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.
Fixes a class of bug where a session with Agent Merge enabled sits idle forever without ever binding to its pull request, so review comments and CI failures never reach it.
Found while investigating a real session (
copilotcli:/7535d422-…, PR #331760). Agent Merge was enabled and running — it had injected its autonomous configuration and the host was keeping the session resident for it:…but every evaluation died on the first check, exactly
backstopIntervalapart:Its
agentMerge.controllerstate had notarget, confirming it never got far enough to bind the PR — so it never subscribed to PR events, and a review comment and a failing check both went unnoticed.Root cause
The session's persisted git state had lost its branch, while the worktree itself was perfectly healthy:
_computeSessionGitStateruns its probes independently and fills fields best-effort.parseGitStatusV2always yieldsuncommittedChanges: 0for any non-empty output, so its absence meansgit statusitself returnedundefined. The repository root is cached, so the function still returned an object — just a branch-less one._setSessionGitStatereplaces persisted git state wholesale, so that object overwrote the good branch.The failure left no trace:
_runGitonly logged when stderr was non-empty, and a timeout kill produces none.Why it never recovered
Three separate paths that should have repaired it did not:
AgentMergeController._evaluatecallsattachSessionGitHubPullRequest(which begins withrefreshSessionGitState), but only after theif (!branchName) returnbail — so its own repair path was unreachable.undefined; a partial state counted as "already computed" and masked it.Changes
agentHostGitService— returnundefinedwhen the status probe fails, so callers keep the state they already had instead of persisting a misleading one.agentMergeController— refresh git state before giving up on the branch. This also recovers sessions already stuck in this state, which matters because the bad state is persisted.agentService— treat a branch-less state as missing in the subscribe-time refresh.agentHostGitService— log git failures that produce no stderr (warnfor timeouts/signals,tracefor the--quietprobes' expected non-zero exits), so this can't fail invisibly again.Validation
agentMergeController.test.tsgains a regression test that reproduces the stall. Reverting just the controller change makes it fail the same way the real session did:The git-probe change is covered by a new integration test, and was verified end to end against the compiled service: with the fix the degraded probe returns
undefinedand logsNot reporting session git state because git status failed; without it, it returns{}— the same shape as the corruption observed on disk.Full
agentHostunit suite: 5840 passing. The 11 failures are pre-existing and unrelated (sessionPermissions,agentHostDebugLogs,agentHostRequestService,copilotAgent,localAgentHostMetadata).