You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The SCM observer looks up a session's PR by the branch name stored in the session's DB metadata at spawn time (sessions.branch). If the worker agent renames/checks out a different local branch and opens its PR from that branch instead, AO never discovers the PR — the session's branch column is never updated after spawn, so the lookup always queries the wrong (original) branch name.
Source: Discovered while triaging #251 (PR hydration bug) | Reported by: Aditi Chauhan Analyzed against:96d1649 Confidence: High
Reproduction
Spawn a worker session (e.g. agent-orchestrator-3); AO assigns the default branch ao/agent-orchestrator-3 and stores it in sessions.branch.
Inside the worker's worktree, the agent runs git checkout -b fix/some-other-name and pushes/opens a PR from that branch instead (observed live: PR #279, head=fix/251-pr-details-not-populated, for session agent-orchestrator-3).
GET /api/v1/sessions/agent-orchestrator-3/pr returns {"prs": []} even though the PR is OPEN on GitHub and clearly tied to that session's work.
Daemon log confirms the lookup target: scm observer: no PR detected for branch session=agent-orchestrator-3 branch=ao/agent-orchestrator-3 — querying the stale branch name, not fix/251-pr-details-not-populated.
Root Cause
backend/internal/session_manager/manager.go sets domain.SessionMetadata.Branch only at spawn (line 217) and restore (line 508) — there is no code path anywhere in backend/internal that updates sessions.branch afterward (confirmed via grep -rn "Metadata.Branch\s*=", only those two spawn/restore sites).
backend/internal/observe/scm/observer.go line 419-420 reads sess.Metadata.Branch as the sole input to DetectPRByBranch (line 526), which queries the provider (GitHub) for an open PR matching that exact branch name.
Nothing prevents (or detects) the spawned agent from running git checkout -b <new-name> inside its own worktree and pushing/opening a PR from a different branch than the one AO recorded. Once that happens, the stored branch and the actual branch permanently diverge, and the observer's per-branch lookup can never find the real PR — it's not a transient miss, it never self-heals.
This silently breaks every downstream feature that depends on PR detection: Session Inspector Summary tab, the kanban Board's PR badge, the /prs page, and any CI/review reaction nudges gated on PR state (e.g. #243, #265).
Fix
Two complementary angles:
Detect drift: when the workspace adapter or agent hooks observe the worktree's actual current branch differs from sessions.branch, update the stored value (or at minimum log/flag it) so the SCM observer's lookup target stays accurate.
Fallback lookup:DetectPRByBranch could fall back to detecting an open PR by HEAD commit SHA or by querying "PRs from this fork/repo with any head branch authored after sessions.created_at" rather than relying solely on an exact, immutable branch-name match — though this is a heavier change and may belong in a separate design discussion.
(1) is the minimal, low-risk fix; (2) is a more robust but bigger lift — flagging both rather than guessing further without maintainer input on which direction is preferred.
Impact
PR state (CI, mergeability, review) silently never surfaces for any session whose agent diverges from its assigned branch — no error, just permanently stale "no PR yet" everywhere in the UI.
Affects reaction/nudge logic gated on PR observation (see related issues below) — a worker could sit stalled waiting for a nudge that never fires because the PR is invisible.
Bug
The SCM observer looks up a session's PR by the branch name stored in the session's DB metadata at spawn time (
sessions.branch). If the worker agent renames/checks out a different local branch and opens its PR from that branch instead, AO never discovers the PR — the session'sbranchcolumn is never updated after spawn, so the lookup always queries the wrong (original) branch name.Source: Discovered while triaging #251 (PR hydration bug) | Reported by: Aditi Chauhan
Analyzed against:
96d1649Confidence: High
Reproduction
agent-orchestrator-3); AO assigns the default branchao/agent-orchestrator-3and stores it insessions.branch.git checkout -b fix/some-other-nameand pushes/opens a PR from that branch instead (observed live: PR #279, head=fix/251-pr-details-not-populated, for sessionagent-orchestrator-3).GET /api/v1/sessions/agent-orchestrator-3/prreturns{"prs": []}even though the PR is OPEN on GitHub and clearly tied to that session's work.scm observer: no PR detected for branch session=agent-orchestrator-3 branch=ao/agent-orchestrator-3— querying the stale branch name, notfix/251-pr-details-not-populated.Root Cause
backend/internal/session_manager/manager.gosetsdomain.SessionMetadata.Branchonly at spawn (line 217) and restore (line 508) — there is no code path anywhere inbackend/internalthat updatessessions.branchafterward (confirmed viagrep -rn "Metadata.Branch\s*=", only those two spawn/restore sites).backend/internal/observe/scm/observer.goline 419-420 readssess.Metadata.Branchas the sole input toDetectPRByBranch(line 526), which queries the provider (GitHub) for an open PR matching that exact branch name.git checkout -b <new-name>inside its own worktree and pushing/opening a PR from a different branch than the one AO recorded. Once that happens, the stored branch and the actual branch permanently diverge, and the observer's per-branch lookup can never find the real PR — it's not a transient miss, it never self-heals./prspage, and any CI/review reaction nudges gated on PR state (e.g. #243, #265).Fix
Two complementary angles:
sessions.branch, update the stored value (or at minimum log/flag it) so the SCM observer's lookup target stays accurate.DetectPRByBranchcould fall back to detecting an open PR by HEAD commit SHA or by querying "PRs from this fork/repo with any head branch authored aftersessions.created_at" rather than relying solely on an exact, immutable branch-name match — though this is a heavier change and may belong in a separate design discussion.(1) is the minimal, low-risk fix; (2) is a more robust but bigger lift — flagging both rather than guessing further without maintainer input on which direction is preferred.
Impact
Related
ao session get(would also be affected by this gap)