Skip to content

dispatch_workflow schema probe swallows the real payload, stalling epic continuation #1765

Closed

Description

@bradygaster

Blocks the last unproven hop of epic continuation. Everything before it now works; this is the final gap.

Live repro

Fixture repo bradygaster/aspiregregator-squad-e2e, worker run 32324473906.

The worker agent emitted two safe-output calls. From agent/safeoutputs.jsonl:

{"type":"dispatch_workflow"}
{"type":"dispatch_workflow","inputs":{"command":"implement","issue_number":"5"},"workflow_name":"squad"}

The first is an empty schema-discovery probe — the agent calling the tool with no arguments to learn its shape. The second is the fully correct payload.

gh-aw's safe-output collection is configured max: 1, and it keeps the first matching item, discarding the rest. So safe-outputs-items/safe-output-items.jsonl contained only:

{"type":"dispatch_workflow","timestamp":"2026-08-20T02:28:13.892Z"}

The real payload was thrown away. The router then received a dispatch with no command input and filed issue #12 "Squad workflow dispatch missing command" — which is #1752's safety net working exactly as designed, failing loudly instead of silently defaulting to cast.

What is NOT broken

The only defect is that the agent probes before committing.

The fix

gh-aw already defends against this pattern elsewhere. Its add_comment tool description opens with language to the effect of:

WRITE-ONCE: do NOT call this tool with empty or placeholder arguments to probe or discover its schema — if you are not ready to post a real comment, call noop instead.

dispatch_workflow carries no such warning.

Per the standing directive that all work stays in this repo, the deliverable is a workaround in our own prompt, not a change request elsewhere.

Target: workflows/squad-implement-worker.md, the ## Continue Parent Epic After Merge section (~L216–248, payload ~L232).

Add explicit WRITE-ONCE / never-probe language telling the agent to:

  • Call dispatch_workflow exactly once, only with a complete payload
  • Never call it with empty, partial, or placeholder arguments to probe the schema
  • Understand the schema is already in the prompt — there is nothing to discover
  • Call noop instead when there is no next wave to dispatch
  • Know the first call wins and later calls are silently discarded, so a probe destroys the real dispatch

Contract assertion

Add a test in test/gh-aw-quality.test.ts — there's an existing merge continuation dispatch contract describe block and an extractWorkflowDispatchInputs() helper to follow.

Make it contract-based, not a change-detector: assert the semantic guarantee (dispatch section warns against empty/probe calls and names noop as the alternative), not an exact sentence. A prior version of this file was criticized for being a change-detector that defended two bugs.

Verification

Re-run /squad implement on epic #5 in the fixture repo. Children #8 and #9 are still open and blocked, so a successful run should dispatch #8.

⚠️ Gotchas

  • Never put a ## heading inside a ## skill: block in workflows/squad.md — it closes implicitly at the next H2 and everything up to the next skill marker is silently discarded (~29 KB lost once, still compiled clean). Skills use #####.
  • Injection safety: the interpolation CI gate covers inputs.* only. comment.body / issue.body must stay un-interpolated — they're attacker-controlled and sanitized separately. Do not "fix" them.
  • ~16 local Vitest failures on Windows are a known baseline; CI is the arbiter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions