Problem
A session's "Pull requests" panel (desktop "About this work" sidebar) shows "No pull requests linked to this session." when the PR is opened in a different repository than the one the session was launched in.
Hit in practice: session 9a680e4ee5d847ea93b89a9c080dd762 was hosted in a kcap-server agent worktree, but the agent created its own kcap-cli worktree and opened kcap-cli#915 there. The PR body referenced both the Linear issue and a Closes #NNN GitHub issue, yet the panel stayed empty.
Cause
The panel is session-scoped. It reads GET /api/sessions/{id}/pull-requests, backed by the server's session_prs table. That table has exactly one writer: the RepositoryDetectedEvent handler, whose PR number comes from the watcher running argument-free gh pr view in the session's launch cwd.
src/Capacitor.Cli/PrDetection/PrDetector.cs — gh pr view --json number,title,url,headRefName in cwd, no --repo.
src/Capacitor.Cli/Commands/WatchCommand.cs — initial detect and the 60s re-probe, both in the session cwd.
src/Capacitor.Cli/RepositoryDetection.cs — ResolveAndDetectPrAsync.
In a kcap-server worktree that probe can only ever resolve a kcap-server PR for the worktree's branch. It cannot see a PR that lives in kcap-cli, so no session_prs row is written and the list comes back empty.
Every alternative path is repo-gated to the session's own repos:
- Transcript
gh pr create output URLs are dropped by the own-repo gate (WorkSignalParser.CollectUrls), because kcap-cli was never a detected repo for this session — and even if kept they would produce a work-item link, not a session_prs row.
- The desktop panel reads only
Kind == "issue" work-item links, never pr links, so a correlated work-item→PR link would not surface here either.
The PR body's issue references are irrelevant to this panel; linkage is purely "what gh pr view returned in the session cwd".
Suggested fix
The server already exposes POST /api/sessions/{id}/pull-requests (SessionHookHandlers.HandleLinkPullRequest) for exactly this — its doc comment names the "work spans repos" case — but nothing in the CLI or desktop app calls it (zero callers). Close the loop by having the kcap side assert the PR for whatever repo it actually landed in:
- A
kcap hook or MCP tool that, after a gh pr create, posts {owner, repo_name, pr_number, url, title, head_ref} to that endpoint for the PR's real repo, or
- Watcher-side discovery of PRs the agent opened in worktrees other than the session's launch cwd (scan the transcript for created-PR repos and probe each explicitly), preserving repo/host identity so an unrelated PR is never attached.
No schema change is needed; session_prs is already keyed (session_id, repo_hash, pr_number).
Related
Both are the same-repo cases; this issue is the distinct cross-repo one.
Problem
A session's "Pull requests" panel (desktop "About this work" sidebar) shows "No pull requests linked to this session." when the PR is opened in a different repository than the one the session was launched in.
Hit in practice: session
9a680e4ee5d847ea93b89a9c080dd762was hosted in a kcap-server agent worktree, but the agent created its own kcap-cli worktree and opened kcap-cli#915 there. The PR body referenced both the Linear issue and aCloses #NNNGitHub issue, yet the panel stayed empty.Cause
The panel is session-scoped. It reads
GET /api/sessions/{id}/pull-requests, backed by the server'ssession_prstable. That table has exactly one writer: theRepositoryDetectedEventhandler, whose PR number comes from the watcher running argument-freegh pr viewin the session's launch cwd.src/Capacitor.Cli/PrDetection/PrDetector.cs—gh pr view --json number,title,url,headRefNameincwd, no--repo.src/Capacitor.Cli/Commands/WatchCommand.cs— initial detect and the 60s re-probe, both in the session cwd.src/Capacitor.Cli/RepositoryDetection.cs—ResolveAndDetectPrAsync.In a kcap-server worktree that probe can only ever resolve a kcap-server PR for the worktree's branch. It cannot see a PR that lives in kcap-cli, so no
session_prsrow is written and the list comes back empty.Every alternative path is repo-gated to the session's own repos:
gh pr createoutput URLs are dropped by the own-repo gate (WorkSignalParser.CollectUrls), because kcap-cli was never a detected repo for this session — and even if kept they would produce a work-item link, not asession_prsrow.Kind == "issue"work-item links, neverprlinks, so a correlated work-item→PR link would not surface here either.The PR body's issue references are irrelevant to this panel; linkage is purely "what
gh pr viewreturned in the session cwd".Suggested fix
The server already exposes
POST /api/sessions/{id}/pull-requests(SessionHookHandlers.HandleLinkPullRequest) for exactly this — its doc comment names the "work spans repos" case — but nothing in the CLI or desktop app calls it (zero callers). Close the loop by having the kcap side assert the PR for whatever repo it actually landed in:kcaphook or MCP tool that, after agh pr create, posts{owner, repo_name, pr_number, url, title, head_ref}to that endpoint for the PR's real repo, orNo schema change is needed;
session_prsis already keyed(session_id, repo_hash, pr_number).Related
Both are the same-repo cases; this issue is the distinct cross-repo one.