feat(sdd-dispatch): event-driven matrix dispatcher; remove daily cron (#81)#97
Conversation
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughAdds an event-driven sdd-dispatch orchestrator and supporting docs/specs; converts sdd-execute wrappers to named-task ChangesCascade Dispatch System
Estimated code review effort 🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/sdd-execute-opus.md:
- Around line 197-200: Update the wording so it accurately reflects the wrapper
concurrency behavior: replace "skipped" with wording that the second run is
queued (e.g., "the second is queued") or explicitly state that wrapper
concurrency (the concurrency group keyed on the task issue number) uses
cancel-in-progress: false and therefore will queue the duplicate trigger rather
than cancel it; reference the named task and noop emission when not eligible,
and keep mentions of the racing sources (stale `sdd-dispatch` cell and manual
`/execute`) intact.
In @.github/workflows/sdd-spec.lock.yml:
- Around line 708-709: The inlined interaction contract in the lock was only
partially updated (sentence changed to six agents) but the contract content
(command rows like /execute and missing /dispatch and cron behavior) remains out
of sync; regenerate/recompile the lock using the project's contract generation
tool so the inlined interaction contract is fully updated to the new cascade
model—ensure the contract includes the /dispatch row, the corrected /execute
timing/description, and the updated agent-count language before committing the
new lock.
In @.github/workflows/sdd-triage.lock.yml:
- Around line 1363-1365: Replace the expression-style boolean used for the draft
field with a literal boolean in the workflow source files: locate the draft: ${{
false }} occurrences in .github/workflows/sdd-triage.md (line ~34),
.github/workflows/sdd-spec.md (line ~34), and the three execute files
(sdd-execute-haiku.md, sdd-execute-opus.md, sdd-execute-sonnet.md at their draft
lines) and change each to draft: false so the workflow source uses a literal
boolean instead of expression syntax.
In `@docs/specs/01-spec-issue-native-sdd/01-spec-issue-native-sdd.md`:
- Around line 769-779: After adding "Unit 11: `sdd-dispatch` agent" update the
downstream unit-count references that are now stale: change occurrences of the
phrase "All ten demoable units" to reflect the new total (e.g., "All eleven
demoable units") and update the range "Units 2 to 10" to include Unit 11 (e.g.,
"Units 2 to 11"); search for the exact strings "All ten demoable units" and
"Units 2 to 10" in the document and revise them consistently wherever they
appear (also check any other numeric references or summaries that enumerate
units).
- Around line 802-807: Update R11.3 so the `max-parallel` expression uses the
same canonical JSON-parsed form as the proof contract: replace `${{
vars.SDD_DISPATCH_MAX_PARALLEL || 5 }}` with `${{
fromJSON(vars.SDD_DISPATCH_MAX_PARALLEL || '5') }}` (referencing the same
`SDD_DISPATCH_MAX_PARALLEL` repo variable and the `max-parallel` matrix setting)
to remove the ambiguity between the spec and the proof contract.
In `@wrappers/sdd-dispatch.yml`:
- Around line 353-373: The current in-flight PR detection only fetches the first
100 PRs via a single github.rest.pulls.list call, so tasks can be missed; change
the logic that builds inFlightFromPrs to iterate/paginate through all open PR
pages (using github.rest.pulls.list with page increments or octokit.paginate)
and process each PR exactly as done now (inspect pr.head.ref and pr.body for
sdd/NNN- and close/fix/resolve patterns) until no more pages remain so
inFlightFromPrs contains IDs from all open PRs.
- Around line 119-168: The current root-resolution block in the event handler
can treat a Unit closure (1 hop) as a task closure because it only checks for
cursor being a tracking issue; change the condition that treats cursor as the
tracking issue to also require walked === 2 so only true task closures (two
parent hops) trigger cascade logic. Update the conditional around the
tracking-check (currently using cursor && !cursor.parent_issue_url) to include a
walked === 2 check and adjust the related info log path if needed (e.g., log
when walked < 2 to indicate non-task closure); refer to the variables cursor,
walked, closedIssue, hasDispatched and the block that sets run/tracking/kind for
locating the change.
In `@wrappers/sdd-execute-opus.yml`:
- Around line 67-69: The concurrency.group currently calls
fromJSON(github.event.inputs.aw_context || '{}') which can crash workflow
evaluation on invalid JSON; change that expression to use try to guard parsing,
e.g. use fromJSON( (try(github.event.inputs.aw_context) || '{}') ) inside the
concurrency.group interpolation so malformed aw_context is ignored, and set
cancel-in-progress: true (replacing cancel-in-progress: false) to collapse
duplicate runs rather than queueing them; update the same pattern wherever
fromJSON(github.event.inputs.aw_context || '{}') appears (lines referenced by
the diff) and ensure the unique symbol concurrency.group and the
cancel-in-progress key are modified accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: d333b313-0da9-4659-b86d-5f2999613a07
📒 Files selected for processing (23)
.github/workflows/sdd-dispatch.lock.yml.github/workflows/sdd-dispatch.md.github/workflows/sdd-execute-haiku.lock.yml.github/workflows/sdd-execute-haiku.md.github/workflows/sdd-execute-opus.lock.yml.github/workflows/sdd-execute-opus.md.github/workflows/sdd-execute-sonnet.lock.yml.github/workflows/sdd-execute-sonnet.md.github/workflows/sdd-spec.lock.yml.github/workflows/sdd-spec.md.github/workflows/sdd-triage.lock.yml.github/workflows/sdd-triage.mddecisions/0011-dispatch-cascade.mddocs/sdd/index.mddocs/sdd/install.mddocs/specs/01-spec-issue-native-sdd/01-spec-issue-native-sdd.mdscripts/quick-setup.shshared/sdd-interaction.mdtemplates/.github/labels.ymlwrappers/sdd-dispatch.ymlwrappers/sdd-execute-haiku.ymlwrappers/sdd-execute-opus.ymlwrappers/sdd-execute-sonnet.yml
Address CodeRabbit review on #97: - Gate cascade root-resolution to walked === 2 so a Unit closure (1 hop) or a tracking-issue closure (0 hops) no longer fires the cascade. - Paginate github.rest.pulls.list so the in-flight detector sees every open PR, not just the first 100. - Flip cancel-in-progress to true on every sdd-execute-{tier} wrapper so a duplicate trigger actually collapses to one cell (the prose and the spec both say it should). Update the prose in each agent .md to match and document the fromJSON aw_context assumption in the wrapper comment. - Replace draft: ${{ false }} with draft: false in every workflow source to drop unneeded expression syntax. - Update stale unit-count phrasing in the spec doc after Unit 11 was added, and align R11.3's max-parallel expression with the proof contract's fromJSON form.
…#81) A new sdd-dispatch agent owns cascade execution. /dispatch on a tracking issue arms persistent matrix fan-out of sdd-execute runs across every ready task; the cascade re-fires on every task close until the tree is drained. Selection is graph-driven (every blocked-by reference resolves to a closed issue), not label-driven. Parallelism is bounded matrix fan-out, capped by SDD_DISPATCH_MAX_PARALLEL (default 5). The cascade marker sdd:dispatched coexists with the lifecycle label the same way needs-human does. The daily schedule cron is removed from every sdd-execute variant; execution is /approve -> /dispatch -> cascade-on-close. See ADR 0011.
Address CodeRabbit review on #97: - Gate cascade root-resolution to walked === 2 so a Unit closure (1 hop) or a tracking-issue closure (0 hops) no longer fires the cascade. - Paginate github.rest.pulls.list so the in-flight detector sees every open PR, not just the first 100. - Flip cancel-in-progress to true on every sdd-execute-{tier} wrapper so a duplicate trigger actually collapses to one cell (the prose and the spec both say it should). Update the prose in each agent .md to match and document the fromJSON aw_context assumption in the wrapper comment. - Replace draft: ${{ false }} with draft: false in every workflow source to drop unneeded expression syntax. - Update stale unit-count phrasing in the spec doc after Unit 11 was added, and align R11.3's max-parallel expression with the proof contract's fromJSON form.
53228ad to
8511dbd
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/sdd-triage.lock.yml (1)
411-440:⚠️ Potential issue | 🟠 Major | ⚡ Quick winDocument
/dispatchas the normal execution path here.This shared contract still frames
/executeas "ahead of the cron" and never adds/dispatch/sdd:dispatched. After this PR, that leaves the triage/execution prompts describing a startup path that no longer exists, so agents can point users at a daily schedule instead of the new event-driven cascade.Please update the source shared fragment to describe
/dispatchas the way to arm execution, keep/executeas the single-task override, and remove the cron wording before recompiling the lockfiles.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/sdd-triage.lock.yml around lines 411 - 440, Update the Comment-command vocabulary and related lifecycle text to make `/dispatch` the normal way to arm execution and introduce the `sdd:dispatched` lifecycle state; keep `/execute` documented as the single-task override (not the primary cron-trigger), and remove or replace any "ahead of the cron" phrasing. Specifically, edit the command table rows for `/dispatch` and `/execute` (and the surrounding explanatory paragraph) to state that `/dispatch` triggers the event-driven cascade and sets `sdd:dispatched`, while `/execute` only triggers `sdd-execute` for a single task; ensure references to `sdd:dispatched` are added where lifecycle transitions are described and delete mentions that execution is primarily driven by a cron before you recompile the lockfiles.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/sdd-execute-opus.md:
- Around line 167-177: Step 2 in the sdd-execute flow still contains the
lifecycle transition that moves the tracking issue from sdd:ready ->
sdd:in-progress; remove that transition so sdd-execute no longer mutates
feature-level state. Locate the Step 2 logic that references aw_context and the
sdd:ready -> sdd:in-progress transition inside the sdd-execute workflow and
delete or disable the code path that performs the state change, leaving only
selection of the candidate task (from aw_context) and downstream execution;
ensure /dispatch remains the sole owner of the lifecycle transition.
- Around line 175-202: Add back an in-flight guard: when evaluating the named
task's eligibility in the `/execute` manual path (the same block that checks
`model:opus`, `needs-human`, and `repo:`), also treat the `sdd:in-progress`
label as a disqualifier—emit `noop` and surface a message directing the human to
use `/revise` on the existing implementation PR instead of re-entering the task;
keep this check only for the manual `/execute` entry (the existing
`sdd-dispatch` behavior and concurrency wrapper remain unchanged).
---
Outside diff comments:
In @.github/workflows/sdd-triage.lock.yml:
- Around line 411-440: Update the Comment-command vocabulary and related
lifecycle text to make `/dispatch` the normal way to arm execution and introduce
the `sdd:dispatched` lifecycle state; keep `/execute` documented as the
single-task override (not the primary cron-trigger), and remove or replace any
"ahead of the cron" phrasing. Specifically, edit the command table rows for
`/dispatch` and `/execute` (and the surrounding explanatory paragraph) to state
that `/dispatch` triggers the event-driven cascade and sets `sdd:dispatched`,
while `/execute` only triggers `sdd-execute` for a single task; ensure
references to `sdd:dispatched` are added where lifecycle transitions are
described and delete mentions that execution is primarily driven by a cron
before you recompile the lockfiles.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 2c1a7f5e-34b7-4395-b534-5244c4239919
📒 Files selected for processing (27)
.github/workflows/sdd-dispatch.lock.yml.github/workflows/sdd-dispatch.md.github/workflows/sdd-execute-haiku.lock.yml.github/workflows/sdd-execute-haiku.md.github/workflows/sdd-execute-opus.lock.yml.github/workflows/sdd-execute-opus.md.github/workflows/sdd-execute-sonnet.lock.yml.github/workflows/sdd-execute-sonnet.md.github/workflows/sdd-review.lock.yml.github/workflows/sdd-spec.lock.yml.github/workflows/sdd-spec.md.github/workflows/sdd-triage.lock.yml.github/workflows/sdd-triage.md.github/workflows/sdd-validate.lock.ymldecisions/0011-dispatch-cascade.mddocs/sdd/index.mddocs/sdd/install.mddocs/specs/01-spec-issue-native-sdd/01-spec-issue-native-sdd.mdscripts/lifecycle-states.ymlscripts/quick-setup.shscripts/safe-output-allowlist-exceptions.ymlshared/sdd-interaction.mdtemplates/.github/labels.ymlwrappers/sdd-dispatch.ymlwrappers/sdd-execute-haiku.ymlwrappers/sdd-execute-opus.ymlwrappers/sdd-execute-sonnet.yml
✅ Files skipped from review due to trivial changes (3)
- docs/sdd/install.md
- .github/workflows/sdd-review.lock.yml
- decisions/0011-dispatch-cascade.md
Summary
A new
sdd-dispatchagent owns cascade execution./dispatchon a tracking issue arms persistent matrix fan-out ofsdd-executeruns across every ready task; the cascade re-fires on every task close until the tree is drained.blocked bylines, and admits a task only when every blocker is closed and the task is not in flight.sdd:readyis a UI hint, not the eligibility predicate.max-paralleldefaults to 5, overridable per repo viaSDD_DISPATCH_MAX_PARALLEL.sdd:dispatchedcascade marker on the tracking issue. While present, everyissues.closedevent on a task sub-issue re-fires the dispatcher. Removing the marker pauses the cascade; another/dispatchresumes.sdd-executevariants trigger only onworkflow_dispatch(from the dispatcher) andissue_comment(/execute). The pipeline is/approve->/dispatch-> cascade-on-close.Stack
This PR is stacked on #92 (
feat/79-plan-comment-before-tree). Base it againstfeat/79-plan-comment-before-tree, notmain. The #79 ADR is0010-plan-comment-before-tree.md; this PR adds0011-dispatch-cascade.md.Changes
.github/workflows/sdd-dispatch.md(+ compiled.lock.yml),wrappers/sdd-dispatch.yml. The wrapper carries the deterministic implementation (route, compute ready set, matrix fan-out, lifecycle, noop comment); the.mddocuments the contract.sdd-execute-{haiku,sonnet,opus}variants:schedule:cron removed from each wrapper; concurrency group keyed on the task issue number added;.mdtriggers prose reduced from six situations to five; tier gate updated to gate on every event (includingworkflow_dispatchcarryingaw_context).sdd:dispatchedintemplates/.github/labels.yml.SDD_DISPATCH_MAX_PARALLELdocumented indocs/sdd/install.mdand surfaced byscripts/quick-setup.sh.decisions/0011-dispatch-cascade.md.sdd-dispatchagent) appended; R6.1, R6.2, and the Unit 6 proof artifacts updated to reflect the cron removal and event-driven selection.docs/sdd/index.md(six agents; news_dispatchsubgraph; updated step table),shared/sdd-interaction.md(new/dispatchcommand;sdd:dispatchedas orthogonal cascade marker),scripts/quick-setup.sh(new wrapper in the install manifest; new variable surfaced inreport_configuration).Acceptance
sdd:readywith five independent open tasks, given/dispatchfrom a write-access author, opens five implementation PRs concurrently (bounded bySDD_DISPATCH_MAX_PARALLEL); the tracking issue moves tosdd:in-progressand gainssdd:dispatched.sdd:dispatchedtracking issue triggerssdd-dispatchand opens two new implementation PRs within seconds, with no/dispatchcomment needed./dispatchon a tracking issue insdd:specorsdd:triageposts one refusal comment naming the required state and emits noworkflow_dispatch;sdd:dispatchedis not applied.sdd:dispatchedby hand stops the cascade; a subsequent task close does not re-fire dispatch. A subsequent/dispatchresumes.sdd-dispatchremovessdd:dispatched.sdd-execute's completion path moves the tracking issue tosdd:done.grep -R "schedule:" .github/workflows/sdd-execute-*.md wrappers/sdd-execute-*.ymlreturns no lines./dispatchwhile the cascade is armed dispatches only tasks not already in flight; the concurrency group onsdd-execute-*prevents double-execution.scripts/quick-setup.sh --suite sdd --dry-runlistssdd-dispatch.ymland surfacesSDD_DISPATCH_MAX_PARALLELin its operator-supplied-config summary.References
decisions/0011-dispatch-cascade.md)sdd:readyset at task-creation)sdd:readypromotion gap; now no longer load-bearing for execution)Closes #81