Skip to content

[P0] #404 — Execute the 15 canonical stages as individual tasks (not 8 mission bundles) - #413

Merged
richard-devbot merged 1 commit into
mainfrom
fix/404-15-stage-execution
Jul 20, 2026
Merged

[P0] #404 — Execute the 15 canonical stages as individual tasks (not 8 mission bundles)#413
richard-devbot merged 1 commit into
mainfrom
fix/404-15-stage-execution

Conversation

@richard-devbot

@richard-devbot richard-devbot commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Closes #404.

What

sdlc_plan now emits one task per canonical SDLC stage (15) instead of grouping them into 8 missions. Each stage becomes a first-class execution unit: its own builder contract, its own validator profile, its own approval gate, checkpoint, and memory episode. A single validator verdict can no longer mark three bundled stages PASS at once.

Why it matters

  • Validators are no longer shadowed. resolveValidatorProfile now receives a single stage, so 06-architecture and 13-compliance-checker get their own validators instead of losing to the security profile they used to share a mission bundle with.
  • Approvals, checkpoints, retries, and memory now attach at true stage boundaries.

How

  • lifecycleStages is generated from CANONICAL_SDLC_STAGES; MISSION_META holds the per-mission intent each stage inherits.
  • Missions survive as display-only grouping metadata on each task (mission_id / mission_title) so the dashboard can still swimlane by mission.
  • The 8 mission spec documents (product-brief.md, architecture.md, …) stay decoupled via missionSpecStages, so sdlc_spec / approvals / the release gate are unchanged.
  • requiredApprovalsForTask rekeyed off canonical stage order (the old lexicographic mission-id thresholds no longer bucket correctly), with a legacy fallback for non-canonical ids.
  • budgetEnvelopeForTask fallback divides the run budget across 15 stages.

Harness-agnostic by construction

This lives in the shared bridge implementation (bin/rstack-bridge.ts imports src/integrations/pi/rstack-sdlc.ts verbatim), so Pi, Claude Code, Tau, Operator, and Hermes all get it — a future adapter shells the same bridge. No tool names or param schemas changed, so bridge-conformance holds.

Tests

Fixtures updated to the 15-stage model; tests/helpers/claim.js added to target mid-pipeline stages. Full suite shows no regressions vs main baseline (the only failures are pre-existing Windows spawn npx ENOENT / EBUSY environmental issues that also fail on main).

Base: main. First in the Wave 1 stack (#404#405, #407).

Summary by CodeRabbit

  • New Features

    • SDLC plans now organize execution into 15 canonical stages, with clear stage ownership and mission grouping.
    • Mission briefs remain available as 8 separate planning documents.
    • Stage tasks now use consistent canonical IDs and routing, improving attribution and lifecycle tracking.
  • Improvements

    • Approval requirements now follow canonical stage order.
    • Validation, retry, rollback, and memory workflows consistently support canonical stages.
    • Fallback task cost estimates are distributed across all 15 stages for more accurate budgeting.

…8 bundles

sdlc_plan now emits one task per canonical SDLC stage (15) instead of grouping
them into 8 missions. Each stage becomes its own execution unit: its own
builder contract, its own validator profile (resolveValidatorProfile receives a
single stage, so architecture/compliance are no longer shadowed by the security
profile they used to share a bundle with), its own approval gate, checkpoint,
and memory episode. A single validator verdict can no longer mark three stages
PASS at once.

- lifecycleStages is generated from CANONICAL_SDLC_STAGES; MISSION_META carries
  the per-mission intent, inherited by each stage.
- Missions are retained as display-only grouping metadata on each task
  (mission_id/mission_title) so the dashboard can still swimlane by mission.
- The 8 mission spec documents (product-brief.md, architecture.md, ...) stay
  decoupled via missionSpecStages, so sdlc_spec / approvals / the release gate
  are unchanged.
- requiredApprovalsForTask rekeyed off canonical stage ORDER (the old
  lexicographic mission-id thresholds no longer bucket correctly), with a
  legacy fallback for non-canonical ids.
- budgetEnvelopeForTask fallback now divides the run budget across 15 stages.

Cross-harness by construction: this lives in the shared bridge implementation
(bin/rstack-bridge.ts imports it), so Pi, Claude Code, Tau, Operator, and
Hermes all get it. No tool names or param schemas changed — bridge conformance
holds. Tests updated (tests/helpers/claim.js added to target mid-pipeline
stages). No regressions vs baseline.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

SDLC planning now creates 15 canonical stage tasks, retains 8 mission-level specification briefs, aligns approval and budget calculations with canonical stages, and updates integration tests to claim and validate canonical task identifiers.

Changes

Canonical stage execution

Layer / File(s) Summary
Canonical stage planning
src/integrations/pi/rstack-sdlc.ts, tests/harness.test.js
Planning derives one task per canonical stage, assigns its stage agent, attaches mission metadata, and continues generating eight mission-level spec documents.
Stage policy and budget alignment
src/integrations/pi/rstack-sdlc.ts, src/core/profiles.js, tests/people-layer-approvals.test.js, tests/profiles.test.js
Approval ordering and fallback budget calculations use canonical stage semantics.
Canonical claim and validation coverage
tests/helpers/claim.js, tests/*
Regression tests claim canonical tasks and cover validation wiring, retries, attribution, memory, goal gates, validator profiles, rollback, and approval gates.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: richardsongunde

Sequence Diagram(s)

sequenceDiagram
  participant Planner
  participant CanonicalStages
  participant Tasks
  participant Validator
  Planner->>CanonicalStages: derive 15 execution stages
  CanonicalStages->>Tasks: create one task per stage
  Tasks->>Validator: claim canonical task
  Validator-->>Tasks: record stage validation and attribution
Loading

Poem

I’m a rabbit in the stage-task lane,
Fifteen hops replace the old terrain.
Eight briefs still bloom for mission view,
Canonical claims make paths come true.
Budgets, gates, and tests align—
Thump, thump, ship the pipeline fine!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: moving execution from 8 mission bundles to 15 canonical stage tasks.
Linked Issues check ✅ Passed The code and tests align with #404 by planning 15 canonical stage tasks, stage-specific validation, approvals, and budget fallbacks.
Out of Scope Changes check ✅ Passed The changes stay focused on the canonical-stage execution model and related test/helper updates, with no obvious unrelated additions.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/404-15-stage-execution

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
src/integrations/pi/rstack-sdlc.ts (1)

762-780: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hoist and guard codeIdx/archIdx against silent drift.

codeIdx/archIdx are recomputed via findIndex on every call and keyed off the literal strings "07-code"/"06-architecture". If those canonical ids are ever renamed, both lookups silently return -1, and idx >= -1 becomes always true — every canonical stage would require the full plan+requirements+architecture approval set with no error raised, unlike the fail-fast checks a few lines above for mission ownership (Lines 358-360). Consider hoisting these to module scope alongside a throw if either id is missing, for consistency with the existing fail-fast pattern.

♻️ Suggested refactor
+const CODE_STAGE_IDX = CANONICAL_SDLC_STAGES.findIndex((stage) => stage.id === "07-code");
+const ARCHITECTURE_STAGE_IDX = CANONICAL_SDLC_STAGES.findIndex((stage) => stage.id === "06-architecture");
+if (CODE_STAGE_IDX === -1 || ARCHITECTURE_STAGE_IDX === -1) {
+  throw new Error("requiredApprovalsForTask: expected canonical stages 07-code/06-architecture not found");
+}
+
 function requiredApprovalsForTask(taskId: string): string[] {
   const idx = CANONICAL_SDLC_STAGES.findIndex((stage) => stage.id === taskId);
   if (idx === -1) {
     if (taskId >= "004-implementation") return ["plan.md", "requirements.json", "architecture.md"];
     if (taskId >= "003-architecture") return ["plan.md", "requirements.json"];
     return ["plan.md"];
   }
-  const codeIdx = CANONICAL_SDLC_STAGES.findIndex((stage) => stage.id === "07-code");
-  const archIdx = CANONICAL_SDLC_STAGES.findIndex((stage) => stage.id === "06-architecture");
-  if (idx >= codeIdx) return ["plan.md", "requirements.json", "architecture.md"];
-  if (idx >= archIdx) return ["plan.md", "requirements.json"];
+  if (idx >= CODE_STAGE_IDX) return ["plan.md", "requirements.json", "architecture.md"];
+  if (idx >= ARCHITECTURE_STAGE_IDX) return ["plan.md", "requirements.json"];
   return ["plan.md"];
 }
🤖 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 `@src/integrations/pi/rstack-sdlc.ts` around lines 762 - 780, Hoist the
canonical stage indexes used by requiredApprovalsForTask into module scope
alongside the existing stage definitions, and fail fast if either the "07-code"
or "06-architecture" stage is missing instead of allowing -1 indexes. Update
requiredApprovalsForTask to reuse these validated constants while preserving its
approval thresholds and legacy-ID fallback behavior.
src/core/profiles.js (1)

159-161: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive the stage count instead of hardcoding 15.

The fallback divides by a literal 15, duplicating the canonical-stage count that CANONICAL_SDLC_STAGES.length already represents elsewhere (e.g. lifecycleStages in rstack-sdlc.ts, and the test assertion in tests/extension-stage-attribution.test.js). This reintroduces exactly the kind of count-drift risk #404 was meant to eliminate — if a canonical stage is added/removed, this fallback silently goes stale.

♻️ Suggested refactor
-  // `#404`: the run budget is now spread across the 15 canonical stage tasks
-  // (previously 8 bundled missions) when no per-stage budget is configured.
-  const fallback = Number(budgetPolicy.run_budget_usd || 0) / 15;
+  // `#404`: the run budget is spread across the canonical stage tasks
+  // (previously 8 bundled missions) when no per-stage budget is configured.
+  const fallback = Number(budgetPolicy.run_budget_usd || 0) / CANONICAL_SDLC_STAGES.length;

As per coding guidelines, "Keep shared classification and governance decisions centralized rather than duplicating logic across builders, validators, adapters, or UI paths."

🤖 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 `@src/core/profiles.js` around lines 159 - 161, Update the fallback calculation
in the relevant profile budget logic to divide by the existing canonical stage
count symbol, such as CANONICAL_SDLC_STAGES.length, instead of the literal 15.
Reuse the established shared stage definition and preserve the current
zero-budget behavior.

Source: Coding guidelines

tests/extension-validator-profile.test.js (1)

49-50: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove redundant directory creation.

The claimTaskForTest helper already ensures that the task's output directory is created recursively. The mkdirSync call here is redundant and can be safely removed.

♻️ Proposed refactor
   const outputDir = join(projectRoot, archTask.output_dir);
-  mkdirSync(outputDir, { recursive: true });
🤖 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 `@tests/extension-validator-profile.test.js` around lines 49 - 50, Remove the
redundant mkdirSync call in the test setup around outputDir, relying on
claimTaskForTest to create the task output directory recursively. Keep the
outputDir path calculation and subsequent test behavior unchanged.
🤖 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.

Nitpick comments:
In `@src/core/profiles.js`:
- Around line 159-161: Update the fallback calculation in the relevant profile
budget logic to divide by the existing canonical stage count symbol, such as
CANONICAL_SDLC_STAGES.length, instead of the literal 15. Reuse the established
shared stage definition and preserve the current zero-budget behavior.

In `@src/integrations/pi/rstack-sdlc.ts`:
- Around line 762-780: Hoist the canonical stage indexes used by
requiredApprovalsForTask into module scope alongside the existing stage
definitions, and fail fast if either the "07-code" or "06-architecture" stage is
missing instead of allowing -1 indexes. Update requiredApprovalsForTask to reuse
these validated constants while preserving its approval thresholds and legacy-ID
fallback behavior.

In `@tests/extension-validator-profile.test.js`:
- Around line 49-50: Remove the redundant mkdirSync call in the test setup
around outputDir, relying on claimTaskForTest to create the task output
directory recursively. Keep the outputDir path calculation and subsequent test
behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6ae4c98e-6aa0-4932-b0cb-b57998f7f0ca

📥 Commits

Reviewing files that changed from the base of the PR and between 0153c4d and edf4f0b.

📒 Files selected for processing (13)
  • src/core/profiles.js
  • src/integrations/pi/rstack-sdlc.ts
  • tests/environment-report.test.js
  • tests/extension-checkpoints.test.js
  • tests/extension-goal-gate.test.js
  • tests/extension-memory.test.js
  • tests/extension-retry-policy.test.js
  • tests/extension-stage-attribution.test.js
  • tests/extension-validator-profile.test.js
  • tests/harness.test.js
  • tests/helpers/claim.js
  • tests/people-layer-approvals.test.js
  • tests/profiles.test.js

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.

[P0-Architecture] 8-Mission Bundle vs 15-Stage Transactional Gap: one verdict marks 3 stages PASS, stage validators shadowed

2 participants