Skip to content

feat(task-board): put a code agent's PR on the board for review - #6344

Merged
guitavano merged 1 commit into
mainfrom
guitavano/code-agent-board-tools
Aug 21, 2026
Merged

feat(task-board): put a code agent's PR on the board for review#6344
guitavano merged 1 commit into
mainfrom
guitavano/code-agent-board-tools

Conversation

@guitavano

@guitavano guitavano commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

A GitHub-imported (or template-clone) coding agent had no way to record work for review after opening a PR. This does the board bookkeeping in code, triggered off the existing PR-open signal, so it's deterministic — with a single focused LLM call for the one judgement that isn't mechanical: is this work already tracked by a card?

Design chosen after discussion: not an always-on system-prompt instruction (the main loop skips it, and it taxes every turn of every coding agent), and not a blind auto-create (loses the dedup judgement). A code hook fires reliably and still delegates the create-vs-update decision to the model.

What changed

  • Reaction on PR-open. reactToPrOpenedForBoard is wired into the PR-open MCP hook (cluster-mcp-tool-hooks.ts onPrOpened). It no-ops for a run that already has a linked card (the Super Agent path — handled by advanceTaskBoardForRun/capturePrForRun), so it can't double up. For an ad-hoc chat with no card it: loads the org's open cards → one generateObject call on the cheap fast tier decides create vs update(taskId) → acts in code: create/update the card in review, link the PR and the thread, and post an optional reviewer note. Best-effort — it never throws into the run that opened the PR.
  • Split for testability. applyBoardDecision (no LLM) performs the storage writes and is covered by a real-Postgres integration test (create; update from an earlier lane; unknown-taskId → fallback create; never regress a done card). The LLM decision (decideBoardActionForPr) is best-effort and degrades to no-op without a model provider.
  • prUrl on CREATE/UPDATE. TASK_BOARD_ITEM_CREATE/UPDATE accept an optional prUrl to link a PR in one call (parsed before any write, so a bad/non-PR URL fails without orphaning a card). Used by the reaction and available for an explicit user request.
  • Scoped board tools at runtime. codeAgentBoardConnection grafts an in-memory SELF connection scoped to TASK_BOARD_ITEM_LIST/CREATE/UPDATE + COMMENT_CREATE onto agents with a checkout — for explicit user asks ("open a PR and put it in review"). Never REVIEW_DECISION/PROMOTE: an agent must not sign off on its own work. Nothing is persisted on the agent, so it covers existing and new agents with no backfill.

Why code, not prompt

  • Reliability — the org-tracking value depends on the card actually reflecting reality; a system-prompt instruction is best-effort per turn. A hook always fires.
  • Cost/latency — the instruction taxed every turn of every coding agent forever; the hook pays one cheap call only when a PR is actually opened.
  • Right trigger — hangs off the existing onPrOpened signal (a real PR was opened), not onThreadFinished (most threads finish without a PR).

Testing

  • Integration (real Postgres): pr-open-board-reaction.integration.test.ts — create / update / fallback / no-regress.
  • Unit: codeAgentBoardConnection inject/skip decision.
  • E2E: prUrl linking on create/update, and rejection of a non-PR URL.
  • bun run check (api/web/e2e), fmt, lint, knip clean.

Follow-up (not in this PR)

  • Tell the user in the chat. There's no SSE-aware "append assistant message" helper, and onPrOpened fires mid-run, so injecting a chat line ("Task created: …") is a separate, delicate change (best done at thread-finish). For now the new/updated card broadcasts live to the board and carries the agent's note as a comment.
  • In a plain chat the closesOwnReview guard doesn't apply, so an imported agent could move its own card in_review → done; left as-is since a human drives the chat.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the claude PR authored by a coding agent label Aug 20, 2026
A GitHub-imported (or template-clone) coding agent had no way to record
work for review after opening a PR. Do the board bookkeeping in code,
triggered off the existing PR-open signal, so it's deterministic — with a
single focused LLM call for the one judgement that isn't mechanical
(is this work already tracked?).

- New reaction reactToPrOpenedForBoard wired into the PR-open MCP hook
  (cluster-mcp-tool-hooks onPrOpened). No-ops for a run that already has a
  linked card (Super Agent), so it can't double up. For an ad-hoc chat with
  no card it: loads open cards → one generateObject "fast"-tier call decides
  create vs update(taskId) → acts in code (create/update the card in review,
  link the PR + thread, post an optional reviewer note). Best-effort; never
  throws into the run. applyBoardDecision is split out (no LLM) and covered by
  a real-Postgres integration test.
- TASK_BOARD_ITEM_CREATE/UPDATE accept an optional prUrl to link a PR in one
  call — used by the reaction and available for an explicit user request.
- Coding agents still get scoped board tools at runtime
  (codeAgentBoardConnection) for explicit asks; the always-on system-prompt
  instruction is dropped in favour of the deterministic hook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@guitavano
guitavano force-pushed the guitavano/code-agent-board-tools branch from 95a11e3 to 9d4a869 Compare August 20, 2026 17:38
@guitavano guitavano changed the title feat(task-board): let coding agents open a PR into review feat(task-board): put a code agent's PR on the board for review Aug 20, 2026
@guitavano
guitavano merged commit 3308bf8 into main Aug 21, 2026
35 of 37 checks passed
@guitavano
guitavano deleted the guitavano/code-agent-board-tools branch August 21, 2026 11:43
decocms Bot pushed a commit that referenced this pull request Aug 21, 2026
PR: #6344 feat(task-board): put a code agent's PR on the board for review
Bump type: minor

- decocms (apps/api/package.json): 4.253.4 -> 4.254.0
- @decocms/native (apps/native/package.json): 4.253.4 -> 4.254.0
- @decocms/e2e (packages/e2e/package.json): 1.43.3 -> 1.44.0

Deploy-Scope: server
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude PR authored by a coding agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant