Skip to content

Prior art: PR feedback routing, PR update, and task dispatch

State: open/active · Genre: research

What existing tools already do for Simple Dispatch’s three use cases: (1) route PR review feedback into the live agent session in that PR’s worktree, or open one; (2) keep PR branches up to date with guards; (3) dispatch ready tasks into sessions.

Examined 2026-09-26. Orca 1.4.211 was read through its installed CLI (--help, orca skills get, read-only list/show calls) and its bundled JS under /Applications/Orca.app/Contents/Resources/app.asar.unpacked/out/. Other tools were read from their GitHub repos (gh repo view, README, source tree) and official docs.

Markers:

  • V — verified in this session: run, or read in the repo or bundle directly.
  • D — read from vendor docs or a README by a research sub-agent; not re-read here.
  • I — inferred.

Release versions and dates come from gh repo view --json latestRelease on 2026-09-26 (V) unless marked otherwise.

  1. One open-source tool already does use case 1 end to end: Composio Agent Orchestrator (AO). ao session claim-pr binds a PR to a worker session. AO then polls the forge and sends failing checks, requested changes, unresolved comments and merge conflicts into that same session. It de-duplicates by content signature. It has a provider-neutral SCM port (GitHub and GitLab), a tmux runtime, and adapters for claude, codex and pi. Apache-2.0, Go, released today. It is the closest design to borrow from. V
  2. Orca orchestration is a good task-dispatch host (use case 3) but knows nothing about PRs. It gives Runs, Tasks, Dispatches, supervised workers, a durable mailbox, and idempotent mutations (--retry-request plus request-show). It is Orca-only: no tmux, no cmux. PR awareness in Orca lives elsewhere, in worktree metadata (linkedPR) and UI prompt builders. V
  3. Every cloud PR responder runs a fresh job per comment. claude-code-action, Copilot coding agent, Codex, Cursor Bugbot, Devin and Jules all start a new cloud VM or Actions runner per trigger. None can deliver into a local session that is already running. They answer a different question than use case 1. D
  4. No PR update tool has our two main guards. None switches rebase to merge when a PR has been reviewed, and none switches on a commit-count threshold. Renovate and Dependabot have the closest “someone else pushed, so stop” guard. Label-scoped overrides are common. Our pr_update design is not duplicated by anything surveyed. D
  5. bosun (virtengine/bosun) is active again upstream (v0.43.1, 2026-09-23), though the local install at /Users/sksizer2/bosun has been idle since 2026-02-26. It is a cloud-style control plane with SDK executors, not a live-terminal router. Its rebase notes are useful: a script switches to merge above 20 commits behind, and its failure catalog records a “rebase death spiral”. V

UC1 = route PR feedback, UC2 = update PR branches, UC3 = dispatch tasks. “Live local session” means it can deliver into an agent session already running on the user’s machine.

CandidateUC1UC2UC3Live local sessionForgesLicense / language
Orca orchestrationno (PR not modelled)noyesyes (Orca only)none in orchestrationproprietary app / TS
Composio Agent Orchestrator (AO)yes, automatic after claim-prroutes conflicts to agentyes (kanban, tracker)yes (tmux, PTY)GitHub, GitLabApache-2.0 / Go + TS
Supersetmanual (select diff lines, send)nopartial (Slack, Linear)yesGitHubElastic 2.0 / TS
cmuxno (PR status only)nonoyesGitHub (status)GPL-3.0+ / Swift
Conductorown diff UI, not GitHub threadsnot documentednoyesGitHubproprietary
vibe-kanbanown diff UI onlynoyes (kanban)yesGitHubApache-2.0 / Rust + TS
Emdashnonoyes (many trackers)yesGitHub, GitLab, Forgejo, …Apache-2.0 / TS
Claude Squadnononoyes (tmux)noneAGPL-3.0 / Go
ccmanagernononoyesnoneMIT / TS
SculptornononoyesGitHub (PR status)MIT / Python
container-usenononoMCP, containersnoneApache-2.0 / Go
uzinonomanual promptsyes (tmux)noneMIT / Go
Crystal → Nimbalystnonokanban (Nimbalyst)yesnoneMIT / TS
Terragonshut down——no (cloud)—Apache-2.0 snapshot
bosunyes, cloud-style workflowrebase with merge fallbackyesno (SDK executors)GitHub (I)Apache-2.0 / JS
claude-code-actionyes, per @claudenoissue → PRnoGitHub (+ community Gitea/Forgejo forks)MIT / TS
Copilot coding agentyes, per @copilotnoissue → PRnoGitHubproprietary
Codex cloud / codex-actionreview + @codex fixesnononoGitHubaction Apache-2.0
Cursor Bugbot / background agentreview + @cursor fixesnononoGitHub, GitLab, Bitbucket, Azureproprietary
Devinyes, on its own sessions’ PRsrebases its own stacksyesnoGitHubproprietary
Julesreview + repliesnoyes (action triggers)noGitHubaction MIT
OpenHands resolverissue/label drivennoissue → PRnoGitHubMIT / Python
Sweeppivoted to a JetBrains plugin—————
Renovate—yes (bot-owned branches)——GitHub, GitLab, Bitbucket, Azure, Gitea/ForgejoAGPL-3.0 / TS
Dependabot—yes (bot-owned branches)——GitHubcore MIT / Ruby
Mergify—yes (update, rebase, queue)——GitHubproprietary
GitHub “Update branch”—manual button——GitHubproprietary
Kodiak—yes (merge only)——GitHubAGPL-3.0 / Python
Aviator MergeQueue / av—yes (queue auto-update)——GitHub, GitLab, BitbucketSaaS / av MIT Go
Graphite gt—local restack——GitHubclosed binary
git-town—local sync——GitHub, GitLab, Gitea, Forgejo, BitbucketMIT / Go
spr, ghstack—local stack rewrite——GitHubMIT
ConceptWhat it isMarker
RunA durable namespace and coordinator inbox. The help text says it “never schedules or places workers”.V
TaskA unit of work with a spec, optional --deps (a DAG) and --parent. Status is one of pending, ready, dispatched, completed, failed, blocked.V
DispatchOne authoritative attempt at a Task. Lifecycle authority comes from the active Dispatch, not a pane or title.V
WorkerA supervised agent terminal started by worker-start. It gets an injected preamble with Task and Dispatch IDs.V
MessageTyped mail: status, dispatch, worker_done, merge_ready, escalation, handoff, decision_gate, question, heartbeat.V
GateA coordinator-owned decision that blocks a Task (gate-create/resolve/list).V
GroupCommandsNotes
Runsrun-create, run-use, run-current, run-list, run-showA coordinator terminal binds to one Run. V
Taskstask-create, task-list, task-update, dispatch-showtask-update sets status by hand; a valid worker_done settles the Task by itself. V
Workersworker-start, worker-show, worker-read, worker-list, worker-stop, worker-abandon, worker-release, worker-retainworker-start creates Task + Dispatch + worktree placement + agent terminal + prompt injection in one call. --worktree current|<selector>|new-child|new-top-level, --terminal <handle> reuses an existing agent terminal. --agent takes an Orca agent id such as claude, codex, cursor, opencode. V
Low-leveldispatch --task --to <handle> --injectInjects a Task into an operator-created terminal. The process stays unsupervised: stop and release do not close it. V
Messagessend, check, reply, inbox, asksend proves durable enqueue only; the wake or nudge is best-effort. check returns a FIFO batch of up to 50 and replays it until --ack. ask blocks a worker until the coordinator replies. V
Idempotency--retry-request <id> on every mutation, plus request-show --request <id>request-show answers completed, pending or absent for a mutation whose response was lost. absent does not prove nothing happened. V
Resetreset --all|--tasks|--messagesV

The CLI is an RPC client. Each handler in cli/handlers/orchestration/ calls a method such as orchestration.workerStart or orchestration.send on the running Orca runtime. cli/handlers/orchestration/mutation-request.js attaches the retry request id as orchestrationRequestId. V The server side is not in app.asar.unpacked, so its storage and wake mechanism were not read. I: it lives in the packed app.asar.

orca orchestration run-list on this machine shows only run_legacy_local (created 2026-08-25), and the inbox is empty. Orchestration is not in use here today. V

Not in the orchestration layer. No orchestration command, flag, or message type names a PR or a forge. V

Orca knows about PRs elsewhere:

WhereWhatMarker
orca worktree list --jsonEach worktree carries linkedPR, linkedIssue, linkedGitLabMR, linkedBitbucketPR, linkedAzureDevOpsPR, linkedGiteaPR, linkedLinearIssue. Two local worktrees have linkedPR set (2242, 2267).V
--worktree issue:<number> selectorWorker placement can target a worktree by linked GitHub issue.V
shared/hosted-review*.jsA provider-neutral “hosted review” record (state, checks, reviewDecision, mergeStateStatus, head SHA). Providers: github, gitlab, gitea, bitbucket, azure-devops.V
shared/pr-checks-fix-prompt.js, shared/source-control-conflict-prompts.js, shared/pr-comment-*.jsPrompt builders for “fix broken checks” and “resolve PR conflicts”, plus PR comment grouping and bot-author filtering (knows coderabbit, codex-connector, greptile, renovate and others).V
Who calls those buildersNot found in the unpacked main or CLI code. I: the renderer UI calls them, so they are user-clicked actions, not a watcher.I

orca automations create offers a cron trigger with --precheck <command>, --workspace (an existing worktree) and --reuse-session. I: a precheck script that exits non-zero when no new comments exist, plus --reuse-session, could approximate use case 1 inside Orca, one automation per worktree. Not tried.

Yes. Workers and handles are Orca terminals, and placement uses Orca worktree selectors. There is no tmux or cmux target. orca serve starts a headless Orca runtime without the desktop window, so Orca does not need its GUI, but it still needs Orca. V

Could Simple Dispatch use it as its host layer?

Section titled “Could Simple Dispatch use it as its host layer?”
NeedOrca orchestration fit
UC3 open a worktree + session for a taskGood. worker-start --spec … --worktree new-child --agent claude does it in one idempotent call and reports worker_done.
UC1 send into an existing sessionPartial. send --to dispatch:<id> only reaches supervised workers and needs the worker to check. A plain agent terminal needs orca terminal send instead.
Completion signalGood for supervised workers (worker_done with outcome). Not available for sessions the user started by hand.
tmux / other hostsNone. Simple Dispatch would still need its own tmux and terminal hosts.
Harness piNot in the documented --agent list. I: would need --terminal reuse or low-level dispatch --inject.

All run a fresh job per trigger. None can deliver into a live local session: the job has no process, socket or handle shared with the user’s terminal. D

ToolTriggerRuns inForgesStatus
anthropics/claude-code-action@claude in a PR or issue comment, assignment, or a workflow promptGitHub Actions runnerGitHub. Community Forgejo and Gitea forks exist.MIT, TS. v1.0.235, 2026-09-25 (V)
Copilot coding agent@copilot in a PR comment, issue assignmentEphemeral Actions container (self-hosted runners since 2025-10)GitHubProprietary
OpenAI Codex GitHub integration, openai/codex-action@codex review / @codex comment; Actions eventsOpenAI cloud; Actions runnerGitHubAction Apache-2.0, TS, tag v1.12 (V)
Cursor Bugbot / background agentsAutomatic per push, or @cursor / bugbot runCursor cloudGitHub, GitLab, Bitbucket, Azure DevOpsProprietary
DevinComments on PRs of its own sessions; /devin commandCognition cloud VMGitHubProprietary. Stacked PRs with auto-rebase of downstream PRs.
Google JulesActions triggers (cron, labels, PR events, CI failure)Google cloud VMGitHubAction MIT, v1.0.0, 2025-12-15 (V)
OpenHands resolverLabel or @openhands-agent mentionGitHub Action + sandboxGitHubMIT, Python. Standalone repo archived; now in OpenHands v1.24.0, 2026-09-25 (V)
Sweep———Pivoted to a JetBrains assistant. Repo last pushed 2025-09-18 (V)

Devin is the only one that keeps a session per PR and answers later comments on it. That session is in the cloud. D

ToolHost modelHarnessesWatches PRs?External APIRelease (V)
ComposioHQ/agent-orchestrator (AO)Local daemon + desktop app. Runtimes: tmux, PTY, ConPTY.~30 adapters incl. claudecode, codex, pi, opencode, cursor (V, backend/internal/adapters/agent/)Yes. See below.ao CLI, HTTP daemon (httpd)v0.13.1, 2026-09-26
superset-sh/supersetElectron app, worktrees, persistent terminalsClaude Code, Codex, other CLIsUser selects PR diff lines and sends them to a running or new session (V, README). Not automatic.CLI, SDK, MCP server (V, README)desktop-v1.30.2, 2026-09-22
manaflow-ai/cmuxNative macOS terminal (libghostty)Any terminal agentShows linked PR status. Open issues discuss a review-comment loop; not shipped as a documented feature. DCLI + socketv0.64.25, 2026-09-17
ConductormacOS desktop appClaude Code, Codex, CursorComments on diffs in its own UI; not confirmed to read GitHub threads. Dnone foundv0.87.5, 2026-09-25 (D)
BloopAI/vibe-kanbanLocal app, worktree per task~10 CLIsOwn diff comments only. DCLI, HTTP, MCPv0.1.44, 2026-04-24. Company shut down 2026-04; community-run.
generalaction/emdashElectron app, worktrees~9 CLIsNo. Imports tasks from Linear, GitHub, Jira, GitLab, Forgejo and others. D—v1.2.6, 2026-09-21
smtg-ai/claude-squadtmux + worktrees, TUIClaude, Codex, Gemini, Aider, OpenCode, AmpNononev1.0.20, 2026-08-20
kbwo/ccmanagerTUI, no tmux8 CLIs, shows idle/busy/waitingNononev4.4.3, 2026-09-13
imbue-ai/sculptorDesktop app, containersClaude Code, pi, terminal agentsPR status only. Dnonesculptor-v0.48.0, 2026-09-21
dagger/container-useMCP server, container + branch per agentAny MCP agentNoCLI, MCPv0.4.2, 2025-08-19
devflowinc/uzitmux + worktreesClaude, Codex, othersNoCLIv0.0.2, 2025-06-03; last push 2025-06-04 (stale)
stravu/crystal → NimbalystElectronClaude Code, CodexNo—v0.3.5, 2026-02-26 (deprecated)
terragon-labs/terragon-ossCloudClaude Code, Codex——Shut down; snapshot pushed 2026-02-10
virtengine/bosunDaemon + Telegram and web dashboard; SDK executorsCodex, Copilot, Claude, OpenCode SDKsYes, as workflows (PR digest from reviews, review comments and checks; CI-fail label; auto-merge with review gate)HTTP API, Telegramv0.43.1, 2026-09-23
  • ao session claim-pr <pr> binds a PR to a worker session. AO then “routes failing checks, requested changes, unresolved comments, and eligible merge conflicts to that session”. Delivery works for both its structured chat mode and its terminal mode. V (frontend/src/docs/content/guides/reactions.mdx)
  • It “stores or remembers signatures for observed feedback” and re-sends only when the content changes, not on every poll. V (same file)
  • Merge is always a manual ao pr merge. V
  • backend/internal/ports/scm_observations.go defines a provider-neutral SCMObservation with PR, CI, Review (decision plus normalized threads) and Mergeability sections, and an ETag guard for cheap polling. Adapters exist for scm/github, scm/gitlab and a scm/multi composite. V
  • It also has tracker/github and tracker/gitlab adapters for task intake, and a workspace/gitworktree adapter. V
  • No Forgejo or Gitea SCM adapter. V (source tree)
  • The README lists executor routing with failover, a “PR Watchdog” that merges passing PRs behind a review gate, a bosun-needs-fix label on CI failure, and intake from issues, comments, schedules and webhooks. V
  • workflow-templates/github.mjs builds a “prDigest” from PR body, files, comments, reviews, review comments and checks for a repair agent. V (code search)
  • git/fix-stuck-rebase.ps1 picks merge when more than 20 commits behind, rebase otherwise. V
  • _docs/VK_FAILURE_PATTERN_CATALOG.md “Category 8” records an agent run with 47 rebase attempts and 687 conflict lines, and lists detection strings for such loops. V
  • The local config at /Users/sksizer2/bosun/bosun.config.json targets sksizer/ontological with one Claude Code executor. Its logs stop on 2026-02-26. V
ToolMechanismGuardsTriggerForgesRelease (V)
RenovateRecreates its own commit on the base. rebaseWhen: auto|behind-base-branch|conflicted|automerging|neverStops touching a branch once anyone else pushes to it. Lockfile rebuilt on every recreate; lockFileMaintenance. rebaseLabel.Auto; checkbox or labelGitHub, GitLab, Bitbucket, Azure, Gitea/Forgejo44.115.10, 2026-09-26
DependabotRecreates its own commit. rebase-strategy: auto|disabled@dependabot rebase refuses if others pushed; recreate forces. Stops auto-rebase after 30 days.Auto; commentGitHubcore v0.397.0, 2026-09-21
Mergifyupdate merges base into head; rebase rebases. Queue update_method: merge|rebaseRefuses on conflicts, closed PRs, forks without edit rights. Its own pushes do not dismiss reviews.Rules, queue, @mergifyioGitHubSaaS
GitHub “Update branch”Button: merge or rebaseNoneManualGitHub—
KodiakGitHub update-branch API (merge)update.ignored_usernames, autoupdate_label, require_automerge_labelAuto or labelGitHubv0.59.1, 2026-03-13
AviatorQueue auto_update by rebase or merge; av sync locallabel, max_runs_for_update (throttles CI)Base push; CLIGitHub, GitLab, Bitbucketav v0.1.45, 2026-07-10
Graphite gt sync/restackLocal rebase of stacksNoneCLIGitHubclosed; npm v1.8.6, 2026-05-05 (D)
git-townsync-feature-strategy: merge|rebase|compressNone; --force-with-lease --force-if-includesCLIGit-only sync; propose for GitHub, GitLab, Gitea, Forgejo, Bitbucketv24.1.0, 2026-09-26
ejoffe/spr, ghstackRewrite PR branches from a local stackNone; single-owner assumptionCLIGitHubspr v0.17.6, 2026-04-22; ghstack v0.14.0, 2025-12-30
pr_update guardClosest prior art
guards.unpushed_local → skipRenovate and Dependabot stop when someone else pushed. Different check (remote, not local), same intent. D
guards.reviewed → mergeNone. Mergify protects reviews by exempting its own pushes from dismissal, but does not change strategy. D
guards.max_rebase_commits → mergeNone in these tools. bosun’s rescue script uses the same rule at 20 commits behind. V
overrides by label or base globCommon: Renovate labels, Mergify conditions, Kodiak and Aviator labels. D
lockfile_install, resolversOnly Renovate and Dependabot, and only because they rebuild their own commit. D
apply: false dry rungit-town and Graphite are explicit CLI actions; bots have no dry run. I

Agent Orchestrator as a backend for our own UI

Section titled “Agent Orchestrator as a backend for our own UI”

Examined 2026-09-26 at ComposioHQ/agent-orchestrator’s v0.13.1 tag (commit 460d9c45f, cut 2026-09-25T16:05Z).

SeamWhat it isUsable by us
Loopback HTTP daemonao start runs a Go daemon on 127.0.0.1:3001. The ao CLI is a thin client over it (V, docs/cli/README.md).Yes. This is the seam for our own UI.
OpenAPI specbackend/internal/httpd/apispec/openapi.yaml, OpenAPI 3.1, generated from Go code, 157 paths at the v0.13.1 tag (main HEAD had since added two more paths, V).Yes. A TS client can be generated from it.
Event streamGET /api/v1/events is server-sent events with replay via ?after=<seq> or Last-Event-ID (V). Also notifications/stream and per-session workspace/events.Yes. It covers live state for a TUI.
PR routessessions/{id}/pr/claim, sessions/{id}/auto-inject-review, sessions/{id}/auto-inject-ci, sessions/{id}/send, sessions/{id}/merge-policy, prs/{id}/merge, prs/{id}/resolve-comments (V).Yes. They cover use case 1.
Go packagesMost logic is under backend/internal/. Go does not allow importing internal/ packages from another module. Only backend/pkg/{contract,agentruntime,agentcreds} are public (V).No, not as a library. Reuse means a fork.
AuthLoopback requests carry no auth in the spec. A separate LAN listener uses a password with lockout (V, httpd/auth.go).Loopback only, same machine.

Limits for our design:

  • AO runs agents in its own sessions: tmux on macOS and Linux, since ao doctor checks for tmux (V), and ACP or Codex app-server chat drivers (V, adapters/chatdriver). It does not route into an Orca pane it did not start (I).
  • GitHub and GitLab; no Forgejo. api/v1/github/* and api/v1/gitlab/* both exist, and the spec’s provider/trackerProvider enums list both (V) — consistent with the scm/gitlab adapter noted above. No Forgejo or Gitea SCM adapter (V).
  • The API is large and versioned 0.1.0-route-shell (V). Expect churn.
DecisionWhatWhy
BorrowAO’s claim-then-route model: an explicit PR → session binding, then poll and deliver changed feedback.It is the one working design for UC1 against local sessions. Matches our planned session registry.
BorrowAO’s content-signature de-dup instead of a read cursor that advances on every classify.Solves our gap: pr classify advances its cursor even when delivery fails.
BorrowAO’s SCMObservation shape: PR, CI, Review threads and Mergeability as separate facts, plus ETag polling.Our first-match verdict hides co-occurring states; this keeps them all. Fits our Forge port.
BorrowOrca’s --retry-request + request-show for every mutating dispatch call.Makes sends and session opens safe to retry after a lost response.
IntegrateOrca orchestration as the Orca host for UC3 opens: worker-start with --worktree new-child, reading worker_done.Gives supervised completion and an idempotent open for free on Orca. Keep tmux and terminal as our own hosts.
IntegrateOrca worktree list --json linkedPR as one input to the worktree → PR map on Orca.Orca already records the link. Our registry stays the source of truth elsewhere.
Keep ourspr_update guards.Nothing surveyed has the reviewed → merge or commit-count guards. Add a loop cap on agent conflict resolution, per bosun’s catalog.
Do not useCloud responders (claude-code-action, Copilot, Codex, Bugbot, Devin, Jules) for UC1.They cannot reach a live local session. They could be an optional fallback when no session exists and the user opts in.
Do not adoptAO wholesale.It is Go plus a desktop app, has no Forgejo adapter, and brings its own task model and UI. Worth a hands-on trial before the loop is built, to confirm delivery behavior.
BuildHost send into a live session for tmux and terminal hosts; Forgejo forge adapter.No surveyed tool covers tmux + Forgejo + our task model together.
  • How AO delivers into a terminal-mode session (keystrokes, hooks, or ACP), and how it handles a busy agent. Not read.
  • Orca orchestration’s server code, storage and nudge mechanism. It is in the packed app.asar, which was out of scope.
  • Whether Orca’s PR prompt builders run only from UI clicks. Inferred, not traced.
  • Whether an Orca automation with --precheck and --reuse-session can deliver PR comments into a live session. Not tried; no mutating Orca calls were allowed.
  • Whether worker-start --terminal <handle> can adopt a session the user started by hand without disturbing it.
  • cmux’s review-comment loop: open issues only, so shipping status is unclear.
  • Conductor, Graphite and vibe-kanban release numbers come from vendor pages read by a sub-agent, not from gh.

← Back to Notes