Skip to content

feat(orch): worker-authored result handoff via report_result tool#18

Merged
nathanwhit merged 1 commit into
mainfrom
worker-report-result
Jun 15, 2026
Merged

feat(orch): worker-authored result handoff via report_result tool#18
nathanwhit merged 1 commit into
mainfrom
worker-report-result

Conversation

@nathanwhit

@nathanwhit nathanwhit commented Jun 15, 2026

Copy link
Copy Markdown
Owner

What

Workers now choose what gets relayed to their manager via a new report_result MCP tool, instead of the manager receiving a scrape of the worker's last TUI pane.

Why

A reviewer worker (real incident, manager 4fb7acff) produced a complete review — findings with file:line refs and the verification commands it ran — but the manager received only a teaser ("…I'm preparing the final review…") and then wasted a follow-up worker re-deriving the findings.

Root cause was the relay, not the agent:

  • The handoff summary was scraped from the visible Codex TUI pane (build logs, separators, footer, input prompt).
  • It was truncated at 2000 bytes. The pane's box-drawing separators are 3 bytes each, so only ~1050 characters survived. The findings began at character 1188 — sliced off. Head-anchored truncation also kept the build-log preamble and dropped the conclusion at the bottom of the pane.

Changes

  • report_result(summary, include_diff?, notes?) — worker-authored handoff stored in a new Session.HandoffSummary, preferred over the scraped LatestSummary everywhere a worker's result is surfaced (completion notification, manager context, supervisor snapshot).
    • include_diff captures git diff vs base (committed + uncommitted) from the worker's checkout, run on its own target, led by a --stat so a truncated diff still names files.
    • notes inlines referenced create_note bodies (shared-memory notes don't otherwise reach the manager).
  • Three role-scoped MCP surfaces, each exposing exactly its tools (tool defs factored into shared per-tool constructors):
    • manager — /mcp/, full surface
    • follow-up — /fmcp/: update_pr, comment_pr, create_note, ask_user, report_result
    • coding worker — /wmcp/: report_result, create_note, ask_user
  • Fixes latent over-permissioning: pr_followup/ci_followup workers previously shared the full manager surface, so they could spawn_session, publish_pr, mark_objective_done, or cancel_session — none of which a worker should do. They now get the scoped follow-up surface.
  • Forge.Diff method (GitForge runs git diff vs resolved base; Fake is seedable).
  • handoff_summary column + idempotent migration for existing DBs.
  • Worker + follow-up preambles now instruct calling report_result (with real findings, not a teaser) before the done marker.
  • Fallback scrape fixed: LatestSummary is now rune-safe and tail-anchored, so the conclusion survives even when a worker doesn't report.

Tests

report_result (summary / diff / notes / empty-diff / required-summary), relay preference order, tail-truncation rune-safety, GitForge.Diff, and a surface-scoping test asserting workers/follow-ups never see the manager-only tools. go vet, gofmt, and go test -race ./... all clean.

@nathanwhit nathanwhit force-pushed the worker-report-result branch from ee9d1fe to f69a75b Compare June 15, 2026 19:52
Workers now choose what gets relayed to the manager instead of leaving it to
a scrape of the last TUI pane. A new report_result MCP tool records an
authoritative HandoffSummary — the worker's findings/outcome, optionally its
diff vs base, and optionally inlined notes — which is preferred over the
scraped LatestSummary everywhere a worker's result is surfaced (completion
notification, manager context, supervisor snapshot).

Why: a reviewer worker produced a full review (findings with file:line refs),
but the manager received only a teaser. The handoff was scraped from the visible
Codex TUI pane and truncated at 2000 BYTES; the pane's box-drawing separators
(3 bytes each) meant only ~1050 characters survived, and head-anchored
truncation kept the build-log preamble while dropping the findings that started
at char 1188. The manager then wasted a follow-up worker re-deriving them.

Also fixes latent over-permissioning: pr_followup/ci_followup workers shared
the FULL manager MCP surface, so they could spawn_session, publish_pr,
mark_objective_done, or cancel_session — none of which a worker should do. Tools
are now split into three role-scoped surfaces.

- New Forge.Diff (GitForge runs git diff vs resolved base, led by --stat;
  Fake is seedable) so report_result can attach the worker's changes.
- Session.HandoffSummary column + idempotent migration for existing DBs.
- Three MCP surfaces, each exposing exactly its tools: manager (/mcp/, full),
  follow-up (/fmcp/: update_pr/comment_pr/create_note/ask_user/report_result),
  coding worker (/wmcp/: report_result/create_note/ask_user). Tool defs factored
  into shared per-tool constructors.
- Worker + follow-up preambles instruct calling report_result before the done
  marker.
- Fallback scrape (LatestSummary) is now rune-safe and tail-anchored, so the
  conclusion survives even when a worker doesn't report.

Tests: report_result summary/diff/notes/empty-diff/required-summary, relay
preference order, tail truncation, GitForge.Diff, and a surface-scoping test
asserting workers/follow-ups never see the manager-only tools. vet + gofmt +
-race clean.
@nathanwhit nathanwhit force-pushed the worker-report-result branch from f69a75b to 6d095ec Compare June 15, 2026 20:13
@nathanwhit nathanwhit merged commit c92cd7b into main Jun 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant