Skip to content

fix(dispatch): arm cascade on collapsed single-task (1-hop) closures (Gap B/#301) - #305

Merged
norrietaylor merged 1 commit into
mainfrom
fix/301-close-walk-collapsed-unit
Jun 19, 2026
Merged

fix(dispatch): arm cascade on collapsed single-task (1-hop) closures (Gap B/#301)#305
norrietaylor merged 1 commit into
mainfrom
fix/301-close-walk-collapsed-unit

Conversation

@norrietaylor

Copy link
Copy Markdown
Owner

Fixes #301.

Problem

The issues:closed cascade walk in sdd-route-dispatch hard-coded a 2-hop tree (Feature→Unit→task). An ADR-0028 collapsed single-task feature parents the task directly to the tracking issue (1 hop), so the GraphQL walk reaches the parentless tracker at walked===1 — failed both walked===2 arming gates, was mis-read as a Unit/tracker closure, and the cascade never re-armed (the tracking issue stalled, needing a manual /dispatch; observed on staging #52/#36). sdd-dispatch-compute already admits a direct ## Task child of the tracker — this aligns the close-walk with it.

Fix (surgical, additive, no recompile)

Three edits in .github/actions/sdd-route-dispatch/action.yml:

  1. Compute closedIsTask from the closed issue's ## Task body block (mirrors compute's isTask guard).
  2. In the partial-walk branch, when the walk terminated at a parentless tracker (stoppedBy==='none') and the closed issue is a genuine task, resolve the tracker (previously it only recorded depth and declined).
  3. Widen the arming gate walked===2walked∈{1,2}.

Safety: the tracker is resolved on the 1-hop path only when closedIsTask is true, so a genuine Unit closure (no ## Task block, also 1-hop to a parentless Feature) leaves the tracker null and still declines. The 2-hop Feature→Unit→task case is untouched (caps at walked===2). The sdd:dispatched precondition inside the gate is unchanged.

Composite action referenced @main by wrappers/sdd-dispatch.yml — not lock-embedded, no recompile.

Verification

YAML valid; embedded github-script JS clean (async-wrapped node --check); control flow traced against all four tree shapes (collapsed-task arms; Unit closure declines; 2-hop arms as before; no-parent declines).

🤖 Generated with Claude Code

…(Gap B)

The issues:closed cascade walk hard-coded a 2-hop tree (Feature→Unit→task), so
an ADR-0028 collapsed single-task feature — whose task is a DIRECT 1-hop child
of the tracking issue — was mis-classified as a Unit/tracker closure and the
cascade never re-armed (tracking issue stalled, needing a manual /dispatch).
sdd-dispatch-compute already admits a direct `## Task` child of the tracker;
this aligns the close-walk with that.

Three additive edits in sdd-route-dispatch: compute closedIsTask from the
closed issue's `## Task` body block; on a 1-hop walk that terminates at a
parentless tracker (stoppedBy==='none') AND a genuine task, resolve the tracker;
widen the arming gate from walked===2 to walked∈{1,2}. A genuine Unit closure
(no `## Task` block) leaves the tracker null and still declines; the 2-hop case
is untouched. Composite action — no lock recompile.

Fixes #301.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 95e0c0ae-7bbc-4e4b-ad9b-2edb5ecbd8a1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

In the sdd-route-dispatch composite action's issues.closed path, a TASK_BLOCK regex and closedIsTask boolean are introduced to distinguish genuine task closures from Unit/tracker closures. Tracker assignment after a parentless-ancestor GraphQL walk is now gated on closedIsTask. The cascade-arming depth guard is relaxed from walked === 2 to walked === 1 || walked === 2.

Changes

Task Classification and Cascade-Arming in issues.closed Route

Layer / File(s) Summary
TASK_BLOCK detection and conditional tracker assignment
.github/actions/sdd-route-dispatch/action.yml
Adds TASK_BLOCK regex and closedIsTask boolean derived from closedIssue.body. In the post-GraphQL partial-walk block, tracker is only assigned from the GraphQL result when gqlStoppedBy === 'none' and closedIsTask is true, implementing the ADR-0028 collapsed single-task one-hop path.
Cascade-arming guard broadened
.github/actions/sdd-route-dispatch/action.yml
Relaxes the cascade-arming condition from walked === 2 to walked === 1 || walked === 2, allowing cascade arming for one-hop walks in addition to two-hop walks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

  • norrietaylor/spectacles#149: Modifies the same issues.closed route-walk logic and tracker assignment via a walked === 2 gate; this PR extends and refines that handling with task-body classification and walked === 1 support.
  • norrietaylor/spectacles#277: Introduces the canonical TASK_BLOCK/isTask task-body detection pattern that this PR reuses for closedIsTask in the issues.closed dispatch path.

Poem

🐰 Hop, hop, one leap or two,
The rabbit checks the task block true.
If ## Task is in the body's art,
The tracker gets assigned its part.
One walk or two, the cascade arms—
No more strict gates, just open farms! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(dispatch): arm cascade on collapsed single-task (1-hop) closures (Gap B/#301)' directly describes the main fix in the changeset: enabling cascade re-arming for 1-hop collapsed single-task closures, which is the core purpose of this surgical bug fix.
Description check ✅ Passed The description comprehensively explains the problem (2-hop hard-coding), the fix (three specific edits), and safety considerations, all directly related to the changeset in the action.yml file.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/301-close-walk-collapsed-unit

Comment @coderabbitai help to get the list of available commands and usage tips.

@norrietaylor

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@norrietaylor
norrietaylor merged commit 73631a6 into main Jun 19, 2026
13 checks passed
@norrietaylor
norrietaylor deleted the fix/301-close-walk-collapsed-unit branch June 19, 2026 15:01
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.

Close-event cascade misses single-task (feature-parented) closures: hardcoded 2-hop walk vs ADR-0028

1 participant