feat: add dispatch_result source_id propagation and wire pipeline chaining workflows#702
Conversation
|
This change is part of the following stack: Change managed by git-spice. |
geoffjay
left a comment
There was a problem hiding this comment.
Review: dispatch_result source_id propagation + pipeline chaining workflows
The Rust core work is clean and well-tested. The source_id propagation through BusyState → DispatchCompleted → EventStrategy.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 hastriaged, 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: trueWithout 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:
- Any dispatch completes → chain fires → applies
enrich-agentto{{original_source_id}} - Enricher completes → removes
enrich-agent→ chain fires again → re-appliesenrich-agent - 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
Nonewhen 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_idis initialized toNone, set at dispatch start (runner.rs:301), and cleared in both the error path (runner.rs:309) andnotify_complete(runner.rs:317). No leak.mod.rscapturessource_idfromBusyStatebefore callingnotify_complete(which clears it), then passes the captured value toDispatchCompleted. Ordering is correct.strategy.rsusessource_id.as_deref()correctly (no unnecessary clone).build_dispatch_taskonly insertsoriginal_source_idwhenSome— absent key renders as unchanged placeholder, as confirmed bytest_render_dispatch_result_without_original_source_id. ✓- All existing
DispatchCompletedmatch arms updated acrossevents.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.
… (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.
feat: add dispatch_result source_id propagation and wire pipeline chaining workflows
feat(scheduler): propagate source_id through DispatchCompleted event for workflow chaining
source_id: Option<String>toSystemEvent::DispatchCompletedsochained workflows can reference the originating GitHub issue or PR number
active_source_id: Option<String>toBusyStateand populate italongside
active_dispatch_idindispatch_tasksandtrigger_workflowsource_idfromBusyStatewhen publishingDispatchCompletedinnotify_task_completeoriginal_source_idmetadata key inbuild_dispatch_taskso chainedprompt templates can use
{{original_source_id}}source_workflow_id,dispatch_id,status,timestamp, andoriginal_source_idtoKNOWN_VARIABLESin template.rs to eliminatevalidation warnings for dispatch_result workflows
.agentd/workflows/triage-enrich-chain.ymlandreview-merge-chain.ymlas ready-to-deploy pipeline chaining examplesdocs/public/event-triggers.mdanddocs/public/templates.mdwithoriginal_source_id, YAML chaining examples, and updated system event docsCloses #641
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com