Bug
PR #278 (ao/agent-orchestrator-2 → main) is CONFLICTING / DIRTY on GitHub. AO did detect it — the stored PR facts read mergeability: "conflicting":
GitHub: mergeable=CONFLICTING mergeStateStatus=DIRTY
AO /sessions/agent-orchestrator-2/pr → { "mergeability": "conflicting", "ci": "passing", "review": "approved", ... }
But AO never surfaces the conflict: no agent nudge, no user notification, and no attention status/badge. To the user it looks like AO "didn't detect it."
Source: local observation, PR #278 | Reported by: @aditi1178 | Analyzed against: 73649b0
Confidence: High
Reproduction
- Worker opens a PR, finishes its turn, and goes
waiting_input (needs_input).
- The base branch (
main) advances so the PR becomes CONFLICTING.
- The SCM observer detects it and stores
mergeability: conflicting.
- No nudge, no notification, no status change — the conflict is invisible unless you open the PR-facts panel and read a single mono row.
Root Cause
AO detects the conflict (data layer is correct), but all three surfacing paths are suppressed:
1. Agent nudge is gated off for waiting_input
backend/internal/lifecycle/reactions.go:65 short-circuits every PR reaction (CI-fail, review-feedback, AND merge-conflict) when the session is paused:
if rec.IsTerminated || rec.Activity.State == domain.ActivityWaitingInput {
return nil
}
The merge-conflict nudge (reactions.go:90-103, "Your PR has merge conflicts. Rebase onto the base branch and resolve them.") sits below that gate, so for a waiting_input session it never runs. PR #278's session is exactly waiting_input.
2. No user notification type for conflicts
notificationIntentForCurrentSCM (reactions.go:~196-214) only emits PRMerged, PRClosedUnmerged, and ReadyToMerge. There is no Conflicting notification — and ReadyToMerge is itself gated by the same waiting_input check (reactions.go:209). A conflict produces zero notifications.
3. No UI status/badge for conflicts
The frontend status model has no conflicting state:
frontend/src/renderer/types/workspace.ts:100 WorkerDisplayStatus = "working" | "needs_you" | "mergeable" | "ci_failed" | "done" — nothing for conflicts.
mergeability is rendered only as a buried mono row: frontend/src/renderer/components/SessionInspector.tsx:255 <Row k="Merge" v={prFacts.mergeability || "—"} mono />.
- Worse: a PR that is
approved + passing + conflicting maps to the mergeable / "Ready to merge" attention zone (workspace.ts:199-201) — actively misleading.
Compounding factor
This PR's session is also stuck in waiting_input with a dead runtime pane (see #290), so it can never leave waiting_input; even if the gate allowed the nudge, delivery to the dead pane would fail (see #265). But the surfacing gap is independent: a live waiting_input session with a freshly-conflicting PR is equally silent.
Fix
A merge conflict needs a path to the human even when the agent is paused. Options (not mutually exclusive):
- Lift merge-conflict (and CI-fail) above the
waiting_input gate in reactions.go, or carve an exception so authoritative PR problems still nudge/notify a waiting_input session.
- Add a
Conflicting notification type in notificationIntentForCurrentSCM so the user is told regardless of agent state.
- Add a
conflicting display status to the frontend status model so it lands in the "Needs you" attention zone instead of being invisible / mis-binned as "Ready to merge".
At minimum (1)+(3): surface conflicts as an attention item and stop a conflicting PR from showing as mergeable.
Impact
- A PR with merge conflicts silently sits as if fine (or even as "Ready to merge") — the user only discovers it by manually opening the PR on GitHub.
- Defeats the core promise that AO drives PRs to a mergeable state and flags what needs attention.
Related
- #290 — session stuck in
waiting_input with a dead pane (why this session can never leave the state that suppresses the nudge).
- #265 —
sendOnce blocked by a hung pane (nudge delivery path).
- #240 — PR surface mapping gaps.
Bug
PR #278 (
ao/agent-orchestrator-2→main) isCONFLICTING/DIRTYon GitHub. AO did detect it — the stored PR facts readmergeability: "conflicting":But AO never surfaces the conflict: no agent nudge, no user notification, and no attention status/badge. To the user it looks like AO "didn't detect it."
Source: local observation, PR #278 | Reported by: @aditi1178 | Analyzed against:
73649b0Confidence: High
Reproduction
waiting_input(needs_input).main) advances so the PR becomesCONFLICTING.mergeability: conflicting.Root Cause
AO detects the conflict (data layer is correct), but all three surfacing paths are suppressed:
1. Agent nudge is gated off for
waiting_inputbackend/internal/lifecycle/reactions.go:65short-circuits every PR reaction (CI-fail, review-feedback, AND merge-conflict) when the session is paused:The merge-conflict nudge (
reactions.go:90-103, "Your PR has merge conflicts. Rebase onto the base branch and resolve them.") sits below that gate, so for awaiting_inputsession it never runs. PR #278's session is exactlywaiting_input.2. No user notification type for conflicts
notificationIntentForCurrentSCM(reactions.go:~196-214) only emitsPRMerged,PRClosedUnmerged, andReadyToMerge. There is noConflictingnotification — andReadyToMergeis itself gated by the samewaiting_inputcheck (reactions.go:209). A conflict produces zero notifications.3. No UI status/badge for conflicts
The frontend status model has no
conflictingstate:frontend/src/renderer/types/workspace.ts:100WorkerDisplayStatus = "working" | "needs_you" | "mergeable" | "ci_failed" | "done"— nothing for conflicts.mergeabilityis rendered only as a buried mono row:frontend/src/renderer/components/SessionInspector.tsx:255<Row k="Merge" v={prFacts.mergeability || "—"} mono />.approved+passing+conflictingmaps to themergeable/ "Ready to merge" attention zone (workspace.ts:199-201) — actively misleading.Compounding factor
This PR's session is also stuck in
waiting_inputwith a dead runtime pane (see #290), so it can never leavewaiting_input; even if the gate allowed the nudge, delivery to the dead pane would fail (see #265). But the surfacing gap is independent: a livewaiting_inputsession with a freshly-conflicting PR is equally silent.Fix
A merge conflict needs a path to the human even when the agent is paused. Options (not mutually exclusive):
waiting_inputgate inreactions.go, or carve an exception so authoritative PR problems still nudge/notify awaiting_inputsession.Conflictingnotification type innotificationIntentForCurrentSCMso the user is told regardless of agent state.conflictingdisplay status to the frontend status model so it lands in the "Needs you" attention zone instead of being invisible / mis-binned as "Ready to merge".At minimum (1)+(3): surface conflicts as an attention item and stop a conflicting PR from showing as mergeable.
Impact
Related
waiting_inputwith a dead pane (why this session can never leave the state that suppresses the nudge).sendOnceblocked by a hung pane (nudge delivery path).