Skip to content

feat: add dispatch_result source_id propagation and wire pipeline chaining workflows#702

Merged
geoffjay merged 2 commits intofeature/autonomous-pipelinefrom
issue-641
Mar 23, 2026
Merged

feat: add dispatch_result source_id propagation and wire pipeline chaining workflows#702
geoffjay merged 2 commits intofeature/autonomous-pipelinefrom
issue-641

Conversation

@geoffjay
Copy link
Owner

feat: add dispatch_result source_id propagation and wire pipeline chaining workflows

feat(scheduler): propagate source_id through DispatchCompleted event for workflow chaining

  • Add source_id: Option<String> to SystemEvent::DispatchCompleted so
    chained workflows can reference the originating GitHub issue or PR number
  • Add active_source_id: Option<String> to BusyState and populate it
    alongside active_dispatch_id in dispatch_tasks and trigger_workflow
  • Pass source_id from BusyState when publishing DispatchCompleted in
    notify_task_complete
  • Add original_source_id metadata key in build_dispatch_task so chained
    prompt templates can use {{original_source_id}}
  • Add source_workflow_id, dispatch_id, status, timestamp, and
    original_source_id to KNOWN_VARIABLES in template.rs to eliminate
    validation warnings for dispatch_result workflows
  • Add .agentd/workflows/triage-enrich-chain.yml and
    review-merge-chain.yml as ready-to-deploy pipeline chaining examples
  • Update docs/public/event-triggers.md and docs/public/templates.md with
    original_source_id, YAML chaining examples, and updated system event docs

Closes #641

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

@geoffjay geoffjay added the review-agent Used to invoke a review by an agent tracking this label label Mar 22, 2026
@geoffjay
Copy link
Owner Author

geoffjay commented Mar 22, 2026

This change is part of the following stack:

Change managed by git-spice.

Copy link
Owner Author

@geoffjay geoffjay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: dispatch_result source_id propagation + pipeline chaining workflows

The Rust core work is clean and well-tested. The source_id propagation through BusyStateDispatchCompletedEventStrategy.build_dispatch_task → task metadata is correct end-to-end. Lock ordering is safe (read guard dropped before notify_complete re-acquires). Test coverage is thorough — both the Some and None paths are exercised across events.rs, strategy.rs, and template.rs. Two issues in the YAML chain files need to be fixed before this merges.


Blocking: triage-enrich-chain.yml Step 1 stop guard is always true

Step 1 says:

If the issue is closed, already has enrich-agent, or already has triaged, stop here — no action needed.

After triage completes the issue will always have the triaged label — that is the state the triage-worker just applied. This guard makes the chain a permanent no-op: it triggers on every triage completion, checks the issue state, finds triaged, and immediately stops without ever applying enrich-agent.

Fix: remove triaged from the stop conditions. The relevant guards are:

  • Issue is closed → stop (nothing to dispatch)
  • Already has enrich-agent → stop (already dispatched, dedup)
  • Already has a downstream agent label (agent, work-agent) → stop (enrichment has been superseded)

The triaged label should be absent from the stop list; its presence is the signal that enrichment is appropriate.


Blocking: Both chain workflows deploy as enabled: true with no source_workflow_id filter

Both triage-enrich-chain.yml and review-merge-chain.yml ship with:

source:
  type: dispatch_result
  # source_workflow_id: "<…UUID…>"  # uncomment and fill in after deployment
  status: completed

enabled: true

Without source_workflow_id, each workflow fires on every successful dispatch completion across the entire deployment — including completions from other chain workflows themselves. For triage-enrich-chain, this means:

  1. Any dispatch completes → chain fires → applies enrich-agent to {{original_source_id}}
  2. Enricher completes → removes enrich-agent → chain fires again → re-applies enrich-agent
  3. Loop continues indefinitely until a human removes the label

review-merge-chain is more self-limiting (the merge-ready guard stops it after the first application), but it would still fire and check the GitHub API on every dispatch completion in the system, which is noisy and wasteful.

Fix: set enabled: false in both YAML files. The header comments already explain the post-deployment patch procedure; defaulting to disabled ensures the chain only activates after the operator has wired source_workflow_id correctly. The agent apply .agentd/ docs note should also mention that chain workflows require a post-deploy configuration step before enabling.


Non-blocking: source_id in DispatchCompleted is never None in normal operation

The doc comment on the new source_id field reads:

It is None when the dispatch originated from a trigger type that does not carry a task-level source identifier (rare).

In practice, active_source_id is set to Some(task.source_id.clone()) for every dispatch type — including cron (where task.source_id is a synthetic "cron:{fire_time}" string) and dispatch_result chains (where it is "event:dispatch:{uuid}:{timestamp}"). The field will only ever be None in the window between WorkflowRunner construction and the first dispatch, which is never observable externally.

The consequence is that {{original_source_id}} in a chain workflow triggered by a cron dispatch will be the cron synthetic ID, not None — a chain without source_workflow_id scoping would attempt gh issue view "cron:…" and fail. The documentation should note that original_source_id is the raw task.source_id of the parent dispatch and may be a synthetic value for schedule-based upstreams, not just a GitHub identifier.


Rust correctness ✓

  • BusyState.active_source_id is initialized to None, set at dispatch start (runner.rs:301), and cleared in both the error path (runner.rs:309) and notify_complete (runner.rs:317). No leak.
  • mod.rs captures source_id from BusyState before calling notify_complete (which clears it), then passes the captured value to DispatchCompleted. Ordering is correct.
  • strategy.rs uses source_id.as_deref() correctly (no unnecessary clone).
  • build_dispatch_task only inserts original_source_id when Some — absent key renders as unchanged placeholder, as confirmed by test_render_dispatch_result_without_original_source_id. ✓
  • All existing DispatchCompleted match arms updated across events.rs, mod.rs, strategy.rs. No exhaustiveness gaps.

Documentation ✓

event-triggers.md and templates.md changes are accurate. The "API-only" note correctly updated to reflect YAML support. The post-deployment UUID patching workflow is clearly documented.


Stack note: issue-641 (#702) is stacked directly on feature/autonomous-pipeline — no parent PRs pending. Once the two YAML fixes are in, this is ready to merge.

Summary: Fix the triaged guard in triage-enrich-chain.yml Step 1 and default both chain workflows to enabled: false. Everything else — the Rust core, tests, and documentation — is solid.

@geoffjay geoffjay added needs-rework PR has review feedback that must be addressed before merging and removed review-agent Used to invoke a review by an agent tracking this label labels Mar 22, 2026
… (address review feedback)

- Fix triage-enrich-chain.yml: remove `triaged` from stop conditions;
  its presence is the signal enrichment should proceed, not a reason to
  stop. Updated stop conditions: closed, already has `enrich-agent`, or
  already has a downstream agent label (`agent`, `work-agent`).
- Set enabled: false on both chain workflows (triage-enrich-chain and
  review-merge-chain) to prevent feedback loops and noisy firing before
  source_workflow_id is configured post-deployment.
- Add IMPORTANT header comments to both chain workflows explaining why
  they ship disabled and what the operator must do before enabling.
@geoffjay geoffjay added the review-agent Used to invoke a review by an agent tracking this label label Mar 23, 2026
@geoffjay geoffjay merged commit fcce6e7 into feature/autonomous-pipeline Mar 23, 2026
@geoffjay geoffjay deleted the issue-641 branch March 23, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-rework PR has review feedback that must be addressed before merging review-agent Used to invoke a review by an agent tracking this label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant