Skip to content

[Phase 2] Adversarial plan-critic pass against the fixed rubric #603

Closed

Description

@github-actions

Story

As a maintainer relying on the planner's output,
I want a single bounded critic pass that reviews Bob's draft plan.json against the fixed rubric, emits structured findings, and has Bob revise once before apply-plan.sh,
so that semantic defects a structural validator can't catch (contested ACs, missing success metric or cost cap, reward-hacking) are caught before the epic materializes.

Acceptance Criteria

  1. After Bob writes the draft plan.json and it passes validate-plan.py, a bounded critic pass reviews it against the fixed rubric from prompts/bmad/scrum-master.md (the same checks defined in story 2) and emits structured findings as JSON ({check, story_id?, severity, finding}).
  2. The pass is a SINGLE review plus ONE revise — no loop. It is implemented as one bounded step (a second claude-code-action step in initiative-planner.yml OR a second turn in Bob's prompt — the choice is made and documented; see open_questions).
  3. Findings Bob can resolve are folded back into plan.json (which is re-validated); findings he cannot resolve become open_questions carrying affected_story_ids, so they gate per the open-questions-as-gate mechanism.
  4. The Initiative: Eval-gated, human-reviewed self-improving skills (SkillOpt-style) #581 plan is captured as a static regression fixture and a test asserts the critic surfaces the six known hand-review findings (contested-AC, no success metric, no cost cap, reward-hacking/overfitting, untracked prereq, reviewability).
  5. The critic adds at most one extra LLM pass; the human initiative:auto gate remains the final say.

Tasks / Subtasks

Dev Notes

Project Structure Notes

Spans the workflow (new bounded step/turn), the prompt (rubric reuse), and a small findings helper + a tests/fixtures regression case. Depends on the rubric (story 2) and the open-questions gate schema (story 3) being in place so findings have a defined home.

References

  • prompts/bmad/scrum-master.md
  • .github/workflows/initiative-planner.yml#L88-L176
  • scripts/initiative-planner/validate-plan.py
  • tests/fixtures

Likely target surface

  • .github/workflows/initiative-planner.yml
  • prompts/bmad/scrum-master.md
  • scripts/initiative-planner/
  • tests/test_initiative_planner.bats

Story prepared by the BMAD Scrum Master (Bob) for epic #597. Status: ready-for-dev.

Activity

  1. don-petry commented on Jun 17, 2026

    @don-petry
    Collaborator

    Dev-Lead Implementation Plan

    Issue: #603 — [Phase 2] Adversarial plan-critic pass against the fixed rubric

    Scope

    Wire a single bounded adversarial critic pass into the initiative-planner that scores Bob's draft plan.json against the fixed six-check rubric in prompts/bmad/scrum-master.md (consumed verbatim — no forked rubric), emits structured JSON findings, and has Bob revise exactly once: resolvable findings fold back into plan.json (re-validated), unresolved ones become open_questions carrying affected_story_ids so they gate per #682.

    Wiring decision (AC #2 — documented)

    Second turn in Bob's prompt, inside the existing single claude-code-action step — not a second action step. Rationale: keeps the critic to one extra reasoning pass in the existing LLM invocation (AC #5), needs no extra engine wiring, and the plan → critique → revise → validate → apply sequence is one bounded session with no self-reflection loop (per discussion #593).

    Implementation Checklist

    • prompts/plan-review.md: align the critic to the six scrum-master.md checks (single source; drop the divergent fork); define findings shape {check, story_id?, severity, finding}.
    • scripts/initiative-planner/plan.schema.json: add affected_story_ids to the open_questions object.
    • scripts/initiative-planner/validate-plan.py: validate affected_story_ids reference real story ids.
    • scripts/initiative-planner/route-findings.sh: deterministic helper that folds unresolved findings into open_questions {question, affected_story_ids, blocking}.
    • .github/workflows/initiative-planner.yml: add the bounded critic turn (single review + one revise) to Bob's prompt; document the choice.
    • tests/fixtures/initiative-planner/plan-581.json + plan-581.expected-findings.json: the Initiative: Eval-gated, human-reviewed self-improving skills (SkillOpt-style) #581 plan as a static regression fixture.
    • Register the new bats file in .github/workflows/lint.yml (repo-specific bats list, per AGENTS.md).

    Tests to Write

    • tests/test_plan_critic.bats: fixture passes validate-plan.py (structural validator can't catch the six semantic defects); rubric in scrum-master.md enumerates the six checks; plan-review.md references scrum-master.md (no fork); expected-findings cover all six checks (contested-AC, success-metric, cost-cap, reward-hacking/overfitting, untracked-prereq, reviewability); route-findings.sh routes unresolved findings into open_questions with affected_story_ids and the result re-validates; major/critical → blocking:true gates apply-plan.
    • Extend tests/test_initiative_planner.bats: validate-plan accepts/validates affected_story_ids.

    Test Command

    scripts/run-bats.sh tests/test_plan_critic.bats tests/test_initiative_planner.bats tests/test_plan_review.bats and bash .dev-lead/scripts/dev-lead-lint.sh

  2. don-petry commented on Jun 17, 2026

    @don-petry
    Collaborator

    Dev-Lead: Implementation Complete

    Plan Execution

    Wiring decision (AC #2, documented)

    Second turn in Bob's prompt, inside the existing single claude-code-action step — not a second action step. It keeps the critic to one extra reasoning pass in the existing LLM invocation, needs no extra engine wiring, and runs plan → critique → revise → re-validate → apply as one bounded session with no self-reflection loop (per #593).

    Note on the regression test (AC #4)

    The LLM critic can't run deterministically in CI, so the test locks the regression contract: the #581 fixture is structurally valid (proving the structural validator can't catch the six semantic defects), the rubric is single-sourced and enumerates the six checks, the golden findings cover all six (contested_ac, success_metric, cost_cap, eval_safeguards, untracked_prereq, reviewability), and route-findings.sh folds them into the gating open_questions shape. The fixture is a faithful capture of the #581 plan's structure (discussion #572 / epic #581) exhibiting each of the six known defects.

    Test Results

    tests/test_plan_critic.bats ......... 22/22 passing
    Full lint.yml bats list ............. 469/469 passing (no regressions)
    dev-lead-lint (shellcheck + agent frontmatter) ... all checks passed
    shellcheck route-findings.sh / post-plan-findings.sh ... clean
    YAML/JSON parse (workflow, schema, fixtures) ... OK
    

    Files Changed

    • prompts/plan-review.md: rewritten to consume the scrum-master.md rubric verbatim + new findings shape.
    • .github/workflows/initiative-planner.yml: added the bounded plan-critic turn (critique → revise once → re-validate) to Bob's prompt.
    • .github/workflows/lint.yml: registered tests/test_plan_critic.bats.
    • scripts/initiative-planner/plan.schema.json: open_questions.affected_story_ids.
    • scripts/initiative-planner/validate-plan.py: validate affected_story_ids refs.
    • scripts/initiative-planner/route-findings.sh: new deterministic routing helper.
    • scripts/post-plan-findings.sh: header comment updated to the new findings shape (channel is field-name agnostic).
    • tests/test_plan_critic.bats, tests/fixtures/initiative-planner/plan-581.json, tests/fixtures/initiative-planner/plan-581.expected-findings.json: new regression test + fixtures.

    Notes

  3. added a commit that references this issue on Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    dev-leadFor dev-lead agent pickupinitiativeEpic / initiative tracking issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions