Skip to content

feat(sdd-triage): defer sub-issue creation until /approve (#79)#92

Merged
norrietaylor merged 5 commits into
mainfrom
feat/79-plan-comment-before-tree
May 20, 2026
Merged

feat(sdd-triage): defer sub-issue creation until /approve (#79)#92
norrietaylor merged 5 commits into
mainfrom
feat/79-plan-comment-before-tree

Conversation

@norrietaylor
Copy link
Copy Markdown
Owner

@norrietaylor norrietaylor commented May 20, 2026

Summary

  • Phase B posts the proposed plan as one comment on the tracking issue (carrying the <!-- sdd-triage:plan --> sentinel) and creates no sub-issues. /approve is now the single gate at which structure is committed to the tree.
  • Phase C, on /approve, creates the Unit sub-issues and the implementation task sub-issues together, materializing exactly what the plan comment shows. Cycle and spec-requirement-coverage checks run before any create-issue is emitted, so a hand-off never leaves an orphan tree.
  • Adds ADR 0010 recording the new gate semantics plus the post-approve /revise rules (set-difference reconciliation; refuse while any task is in flight).

Closes #79.

Changes

  • .github/workflows/sdd-triage.md — rewrite §5 (phase B is now plan-comment only), rewrite §6 (phase C creates Units and tasks; checks run before any create-issue), update §7 (no extra cycle gate), add §9 (post-approve /revise reconcile + in-flight refusal). New safe-outputs: hide-comment (max 5) for collapsing prior plan comments as OUTDATED, close-issue target: '*' (max 30) for reconciliation closes. create-issue cap raised from 20 to 30 to cover Units alongside sub-tasks in one phase-C run.
  • .github/workflows/sdd-triage.lock.yml — regenerated by gh aw compile.
  • decisions/0010-plan-comment-before-tree.md — new ADR.
  • docs/specs/01-spec-issue-native-sdd/01-spec-issue-native-sdd.md — rewrites R5.4 / R5.5; updates the triage acceptance tests at L500–L502; updates the design-notes paragraph framing the three phases; small wording fix in the introduction and Unit 5 purpose.
  • shared/sdd-interaction.md — restates the /approve row, the "merging the architecture PR…" sentence, and the phase-coverage line.
  • docs/sdd/index.md — Mermaid nodes a_units and a_tasks retitled; step table rows 5 and 6 retitled; adds a one-paragraph rationale under the table.
  • templates/.github/ISSUE_TEMPLATE/feature.md, templates/.github/ISSUE_TEMPLATE/bug.md — restate /approve and the "merging the architecture PR" sentence so the user-facing copy matches.

Acceptance

Quoting the non-obvious rules verbatim from the issue and ADR 0010:

Post-approve /revise reconciliation (no task in flight):

Re-run phase B (edits the plan comment) and phase C (reconcile the tree — close Units/tasks no longer in the plan, open new ones, leave intersecting items alone). Reconciliation must be idempotent on re-run.

In-flight refusal:

After /approve, any task is in sdd:in-progress or has an open implementation PR: refuse with one comment naming the in-flight task(s) and pointing to the per-PR /revise loop.

The in-progress test: any open task sub-issue under the tracking issue carries sdd:in-progress, or any task sub-issue has an open linked implementation PR. Either refuses.

Verifiable behaviors (see ADR 0010 § Verification and sdd-triage.md § Verification):

  • Merging the architecture PR produces zero new sub-issues and one plan comment on the tracking issue.
  • /revise <note> between merge and /approve posts a new plan comment and hides the prior one as OUTDATED. No sub-issues created.
  • /approve from a write-access author creates Units (parent = tracking issue) and tasks (parent = Unit) in one phase. Tracking issue moves sdd:triagesdd:ready; unblocked tasks carry sdd:ready at creation.
  • A cycle or an unmapped requirement at phase C produces a needs-human comment and zero create-issue safe-outputs.
  • A post-approve /revise with no task in flight reconciles the tree set-difference-wise; a re-run with the same note emits no tree safe-outputs (idempotent).
  • A post-approve /revise while any task carries sdd:in-progress or has an open linked implementation PR posts one refusal comment and emits noop; the plan and tree are not changed; needs-human is not applied.

References

Open implementation note

gh-aw has no update-comment safe-output today, so "edit the plan comment in place" is rendered as: add-comment posts the revised plan + hide-comment collapses the prior plan comment as OUTDATED. A reader sees one active plan and GitHub's edit log preserves history. If update-comment is added later, the agent can switch to literal in-place edits without changing the gate semantics. This is called out in ADR 0010's Consequences.

Phase B now posts the proposed plan as a single comment on the tracking
issue and creates no sub-issues. Phase C, on /approve, materializes the
plan by creating both Unit and task sub-issues together (ADR 0010). The
cycle and requirement-coverage checks run before any create-issue fires,
so a hand-off never leaves an orphan tree.

Adds ADR 0010, which also records the post-approve /revise reconciliation
rule (close items dropped from the revised plan, create items added,
leave intersections alone; refuse while any task is sdd:in-progress or
has an open implementation PR). Updates the spec (R5.4 / R5.5 and the
triage acceptance tests), shared/sdd-interaction.md, docs/sdd/index.md
(diagram and step table), and the bug/feature issue templates to match.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Review Change Stack

Warning

Rate limit exceeded

@norrietaylor has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 50 seconds before requesting another review.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2741d5f0-ed07-41c7-a3e6-1baaddbf49c3

📥 Commits

Reviewing files that changed from the base of the PR and between 49c7237 and ad750fb.

📒 Files selected for processing (1)
  • decisions/0010-plan-comment-before-tree.md
📝 Walkthrough

Walkthrough

Implements ADR 0010: Phase B posts one sentinel plan comment (no sub-issues); Phase C (/approve) runs pre-create checks then materializes Unit and task sub-issues to match the plan; Phase 9 reconciles or refuses post-approve /revise. Documentation, specs, templates, and Safe Outputs schema updated.

Changes

Plan-comment-before-tree gate restructuring

Layer / File(s) Summary
ADR 0010 decision gate and semantic contract
decisions/0010-plan-comment-before-tree.md
Introduces ADR 0010: phase B posts a single proposed plan comment; phase C on /approve validates and materializes the full Unit/task tree; /revise before approval re-posts/hides prior plans; post-approve /revise reconciles idempotently or refuses if work is in-flight.
Workflow core: Phase B/C procedures and triggers
.github/workflows/sdd-triage.lock.yml, .github/workflows/sdd-triage.md
Phase B composes/posts one dependency-ordered sentinel plan comment and runs cycle gating before posting. Phase C locates the active plan comment, re-runs cycle/coverage checks before any create-issue, then creates Unit issues (parent=tracking issue) and task issues (parent=Unit) with bodies matching the plan preview. Trigger routing for arch/<slug>, /approve, and /revise updated.
Phase 9 post-approve /revise reconciliation
.github/workflows/sdd-triage.lock.yml, .github/workflows/sdd-triage.md
Adds Phase 9: if no sdd:in-progress task or open implementation PR, re-run Phase B, hide prior plan comments as OUTDATED, idempotently close dropped Unit/task issues (close-issue(state-reason: not_planned)) and create missing items; otherwise refuse /revise with a single comment and make no tree edits.
Safe Outputs config and validation schema
.github/workflows/sdd-triage.lock.yml
Raises create_issue cap to 30, adds close_issue(max:30, target:"*"), sets hide_comment(max:30), and extends Safe Outputs validation schema for close_issue and hide_comment (including reason enum with OUTDATED).
Specification and documentation alignment
docs/specs/01-spec-issue-native-sdd/01-spec-issue-native-sdd.md, docs/sdd/index.md, shared/sdd-interaction.md, templates/.github/ISSUE_TEMPLATE/*
Updates spec, pipeline docs, interaction contract, and issue templates to reflect plan-comment Phase B and approval-gated Phase C; updates Mermaid diagram to insert /approve, rewrites /approve and /revise command descriptions, and updates proof-artifact expectations (one plan comment on merge; Units+tasks on /approve).

Sequence Diagram (high-level)

sequenceDiagram
  participant ArchPR as Architecture PR
  participant Triage as sdd-triage Agent
  participant Tracking as Tracking Issue
  participant Human as Human Reviewer
  ArchPR->>Triage: merge (arch/<slug>)
  Triage->>Tracking: post plan comment <!-- sdd-triage:plan -->
  Human->>Tracking: /revise or /approve
  alt revise before approve
    Triage->>Tracking: post new plan, hide prior as OUTDATED
  else approve
    Triage->>Triage: validate cycle & coverage
    Triage->>Tracking: create-issue Unit(s)
    Triage->>Tracking: create-issue Task(s) (parent=Unit)
    Triage->>Tracking: label sdd:ready (where unblocked)
  end
Loading

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues:

  • #83: overlaps on safe-output allowlists and workflow frontmatter that this PR updates.
  • #82: overlaps on plan-comment vs /approve materialization semantics.
  • #81: related to downstream dispatch/sdd:ready handoff that consumes this workflow's /approve behavior.

Possibly related PRs:

"A rabbit hops through the phase gate,
Plans tucked safe where humans wait—
Post /approve, the branches grow,
/revise hides what once we'd know,
ADR 0010 sets the date. 🐇🌿"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: deferring sub-issue creation until the /approve command is given, making Phase B plan-comment-only.
Description check ✅ Passed The description comprehensively explains the Phase B/C changes, acceptance criteria, and rationale, all directly related to the changeset.
Linked Issues check ✅ Passed The PR fully addresses all coding and workflow objectives from issue #79: Phase B posts plan comments only, Phase C creates Units+tasks together, pre-create checks prevent orphan trees, and ADR 0010 documents the new gate semantics and post-approve reconciliation rules.
Out of Scope Changes check ✅ Passed All changes are in scope: workflow logic, spec, diagrams, templates, and ADR 0010 are all required updates to implement the deferred sub-issue creation pattern. No unrelated refactoring or scope creep is present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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

@norrietaylor norrietaylor marked this pull request as ready for review May 20, 2026 20:41
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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-triage.lock.yml:
- Around line 884-885: The compiled prompt is losing the sentinel literal `<!--
sdd-triage:plan -->` (leaving empty backticks) during lock-file generation;
update the lock-file generation/compilation routine (e.g., functions like
compilePrompt or generateCompiledPrompt / generate_lockfile) to preserve or
explicitly inject the sentinel into the compiled prompt code-fence so the exact
string `<!-- sdd-triage:plan -->` appears (not empty backticks), and add a
unit/integration check that the compiled output contains that literal to prevent
regressions.

In @.github/workflows/sdd-triage.md:
- Around line 42-43: The workflow sets hide-comment.max = 5 which conflicts with
the steps that must "hide every prior plan comment" after repeated /revise runs;
update the hide-comment configuration (the hide-comment and hide-comment.max
setting) to remove the fixed cap (or set it to an unlimited value such as 0 or
"all") so it can hide every prior plan comment as required by the plan-comment
hiding logic referenced by the /revise flows and the
hide-every-prior-plan-comment steps.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 80c31ac6-65c1-41bb-9f37-0d74b75774f8

📥 Commits

Reviewing files that changed from the base of the PR and between 77a18da and 7abb5b1.

📒 Files selected for processing (8)
  • .github/workflows/sdd-triage.lock.yml
  • .github/workflows/sdd-triage.md
  • decisions/0010-plan-comment-before-tree.md
  • docs/sdd/index.md
  • docs/specs/01-spec-issue-native-sdd/01-spec-issue-native-sdd.md
  • shared/sdd-interaction.md
  • templates/.github/ISSUE_TEMPLATE/bug.md
  • templates/.github/ISSUE_TEMPLATE/feature.md

Comment thread .github/workflows/sdd-triage.lock.yml Outdated
Comment thread .github/workflows/sdd-triage.md Outdated
…se runs

Phase B (lines 295-297) and the post-approve /revise reconcile (lines 449-451)
both require hiding **every** prior plan comment as OUTDATED. The previous cap
of 5 meant that after enough /revise iterations the agent could no longer
satisfy that invariant in one run, leaving stale active plan comments alongside
the latest one.

Match the close-issue / create-issue cap of 30, which is the practical ceiling
on tree size and therefore on revisable-plan history per tracking issue.
gh aw's markdown→YAML compiler strips HTML comments even inside inline code
spans, so the literal `<!-- sdd-triage:plan -->` was dropping out of the
compiled prompt, leaving empty backticks at every reference site. The agent
prompt no longer named the exact string it must write into plan comments or
match against on `/revise` and `/approve`.

Backslash-escape the bang (`<\!-- sdd-triage:plan -->`) at every prompt site so
the compiler preserves the literal, and add a short parenthetical at each site
clarifying that the backslash is a prompt-escape only — the actual sentinel
posted to GitHub is the un-escaped HTML comment.
@norrietaylor
Copy link
Copy Markdown
Owner Author

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Review triggered.

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
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Review triggered.

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
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Review triggered.

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
Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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.md (1)

219-220: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Phase A PR-body guidance still describes old Phase B behavior.

This line says phase B creates Unit sub-issues, which contradicts ADR 0010 behavior defined elsewhere in this same workflow (phase B is plan-comment-only).

Suggested fix
- request advances the tracking issue to phase B, where one Unit sub-issue per
- demoable unit is created.
+ request advances the tracking issue to phase B, where one sentinel plan
+ comment is posted and no sub-issues are created.
🤖 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.md around lines 219 - 220, Update the Phase A
PR-body guidance text that currently states "request advances the tracking issue
to phase B, where one Unit sub-issue per demoable unit is created" to match ADR
0010 and the workflow's actual behavior: change the wording to say that
advancing to Phase B only posts the plan comment (plan-comment-only) and does
not create Unit sub-issues, and ensure any mention of "Phase B" in the same file
(and related rules in this workflow) uses the same language so the guidance is
consistent with ADR 0010.
🧹 Nitpick comments (1)
.github/workflows/sdd-triage.lock.yml (1)

1372-1374: 💤 Low value

Static analysis: ${{ false }} could be simplified.

The zizmor tool flags "draft":"${{ false }}" as obfuscated since it could be replaced with the literal false. However, this is auto-generated code from gh aw compile, and the pattern may be intentional for template consistency. Consider updating the compiler if this pattern is undesirable.

🤖 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 1372 - 1374, The safe
outputs JSON contains the stringified template expression `"draft":"${{ false
}}"` under the create_pull_request object; replace that with a real JSON boolean
(`"draft": false`) so the value is not an obfuscated string. Fix this in the
generator that emits the here-doc (the GH_AW_SAFE_OUTPUTS_CONFIG... block from
gh aw compile) to output a boolean for create_pull_request.draft (or add a
post-process step that replaces the exact token `"draft":"${{ false }}"` with
`"draft": false`).
🤖 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 `@decisions/0010-plan-comment-before-tree.md`:
- Around line 166-168: The ADR currently states the `hide-comment` safe-output
is capped at 5 but the workflow and `/revise` flow expect and use a cap of 30;
update the document text so the `hide-comment` cap matches the implemented
contract (change "capped at 5 per run" to "capped at 30 per run") and, if
relevant, add a short note referencing the workflow behavior that hides all
prior plan comments during repeated `/revise` runs; ensure you update the line
describing `hide-comment` (the sentence that currently reads "`sdd-triage`
declares two additional safe-outputs: `hide-comment` (capped at 5 per run)...")
to reflect the new cap.

---

Outside diff comments:
In @.github/workflows/sdd-triage.md:
- Around line 219-220: Update the Phase A PR-body guidance text that currently
states "request advances the tracking issue to phase B, where one Unit sub-issue
per demoable unit is created" to match ADR 0010 and the workflow's actual
behavior: change the wording to say that advancing to Phase B only posts the
plan comment (plan-comment-only) and does not create Unit sub-issues, and ensure
any mention of "Phase B" in the same file (and related rules in this workflow)
uses the same language so the guidance is consistent with ADR 0010.

---

Nitpick comments:
In @.github/workflows/sdd-triage.lock.yml:
- Around line 1372-1374: The safe outputs JSON contains the stringified template
expression `"draft":"${{ false }}"` under the create_pull_request object;
replace that with a real JSON boolean (`"draft": false`) so the value is not an
obfuscated string. Fix this in the generator that emits the here-doc (the
GH_AW_SAFE_OUTPUTS_CONFIG... block from gh aw compile) to output a boolean for
create_pull_request.draft (or add a post-process step that replaces the exact
token `"draft":"${{ false }}"` with `"draft": false`).
🪄 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: ede348b2-d51f-41f9-986f-9f9c9d5a2af6

📥 Commits

Reviewing files that changed from the base of the PR and between 77a18da and 49c7237.

📒 Files selected for processing (8)
  • .github/workflows/sdd-triage.lock.yml
  • .github/workflows/sdd-triage.md
  • decisions/0010-plan-comment-before-tree.md
  • docs/sdd/index.md
  • docs/specs/01-spec-issue-native-sdd/01-spec-issue-native-sdd.md
  • shared/sdd-interaction.md
  • templates/.github/ISSUE_TEMPLATE/bug.md
  • templates/.github/ISSUE_TEMPLATE/feature.md

Comment thread decisions/0010-plan-comment-before-tree.md Outdated
@norrietaylor
Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

✅ Actions performed

Full review triggered.

@norrietaylor norrietaylor merged commit c71c17a into main May 20, 2026
8 of 9 checks passed
@norrietaylor norrietaylor deleted the feat/79-plan-comment-before-tree branch May 20, 2026 22:20
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.

sdd-triage: defer all sub-issue creation until /approve; phase B posts the plan as a comment only

1 participant