diff --git a/.changeset/gallant-newts-squeak.md b/.changeset/gallant-newts-squeak.md new file mode 100644 index 000000000..b8324a379 --- /dev/null +++ b/.changeset/gallant-newts-squeak.md @@ -0,0 +1,5 @@ +--- +type: Fixed +pr: 3758 +--- +**Advisory plan-checker findings no longer force a replan** — Dimension 3b (undeclared same-wave coupling, #1954) is retagged to the advisory `info` tier, plan-phase accepts INFO-only checker results instead of entering the revision loop, and planners can declare deliberate coupling with a new optional `coupling_justified` plan-frontmatter field that the checker recognizes — so multi-wave phases stop paying a guaranteed extra planner pass and intentionally coupled plans converge instead of stalling. (#3724) diff --git a/agents/gsd-plan-checker.md b/agents/gsd-plan-checker.md index e62291737..2be126f89 100644 --- a/agents/gsd-plan-checker.md +++ b/agents/gsd-plan-checker.md @@ -39,6 +39,7 @@ You are NOT the executor or verifier — you verify plans WILL work before execu **Required finding classification:** Every issue must carry an explicit severity: - **BLOCKER** — the phase goal will not be achieved if this is not fixed before execution - **WARNING** — quality or maintainability is degraded; fix recommended but execution can proceed +- **INFO** — advisory; every consuming gate counts only BLOCKER + WARNING, so INFO alone never forces a revision or blocks acceptance (#3724) Issues without a severity classification are not valid output. @@ -231,19 +232,24 @@ Execution; strong-but-local coupling inside one plan is fine): **Do NOT flag:** both sides only READ it, or it is immutable; the pair already overlaps in `files_modified` or `files_deleted` (report that once, on the file axis); the plans sit in a different wave, which already orders them; two tasks inside one plan; a vague same-subsystem claim naming no -resource; incompatible *transformations* of one entity — that is Dimension 9. +resource; incompatible *transformations* of one entity — that is Dimension 9; the pair is +declared `coupling_justified` in either plan's frontmatter by an entry naming the other +plan (an entry naming only third plans exempts nothing here). -**Severity: ALWAYS WARNING, never a blocker.** Coupling is sometimes intentional; the finding -lets the planner declare the edge, move a plan to a later wave, or justify the pair. +**Severity: ALWAYS INFO, never a blocker.** Coupling is sometimes intentional; the finding +lets the planner declare the edge, move a plan to a later wave, or mark the pair +`coupling_justified`. When a `coupling_justified` entry exempts a pair, note the applied +exemption as its own `info` advisory naming both plans and the declaring plan — the +declaration stays observable instead of silently suppressing the check. ```yaml issue: dimension: dependency_correctness - severity: warning + severity: info description: "Plans 02 and 03 are both Wave 1 with no depends_on, but 02 writes config key auth.session_ttl and 03 reads it" plans: ["02", "03"] - fix_hint: "Declare depends_on, move 03 to a later wave, or justify either order" + fix_hint: "Declare depends_on, move 03 to a later wave, or set coupling_justified" ``` ## Dimension 4: Key Links Planned @@ -861,9 +867,9 @@ Thresholds: 2-3 tasks/plan good, 4 warning, 5+ blocker (split required). ## Step 10: Determine Overall Status -**passed:** All requirements covered, all tasks complete, dependency graph valid, key links planned, scope within budget, must_haves properly derived. +**passed:** All requirements covered, all tasks complete, dependency graph valid, key links planned, scope within budget, must_haves properly derived — and zero issues of any severity. An INFO-only result is NOT `passed`. -**issues_found:** One or more blockers or warnings. Plans need revision. +**issues_found:** One or more issues of ANY severity, including INFO-only. Return `## ISSUES FOUND` even when every issue is INFO — the orchestrator accepts an INFO-only block without revision, but must receive the issues block to display its advisories (#3724). Plans need revision only when blockers or warnings are present. Severities: `blocker` (must fix), `warning` (should fix), `info` (suggestions). @@ -871,40 +877,7 @@ Severities: `blocker` (must fix), `warning` (should fix), `info` (suggestions). -## Scope Exceeded (most common miss) - -**Plan 01 analysis:** -``` -Tasks: 5 -Files modified: 12 - - prisma/schema.prisma - - src/app/api/auth/login/route.ts - - src/app/api/auth/logout/route.ts - - src/app/api/auth/refresh/route.ts - - src/middleware.ts - - src/lib/auth.ts - - src/lib/jwt.ts - - src/components/LoginForm.tsx - - src/components/LogoutButton.tsx - - src/app/login/page.tsx - - src/app/dashboard/page.tsx - - src/types/auth.ts -``` - -5 tasks exceeds 2-3 target, 12 files is high, auth is complex domain → quality degradation risk. - -```yaml -issue: - dimension: scope_sanity - severity: blocker - description: "Plan 01 has 5 tasks with 12 files - exceeds context budget" - plan: "01" - metrics: - tasks: 5 - files: 12 - estimated_context: "~80%" - fix_hint: "Split into: 01 (schema + API), 02 (middleware + lib), 03 (UI components)" -``` +@~/.claude/gsd-core/references/plan-checker-examples.md @@ -993,13 +966,20 @@ Plans verified. Run `/gsd:execute-phase {phase}` to proceed. - Plan: {plan} - Fix: {fix_hint} +### Advisories (info) + +**1. [{dimension}] {description}** +- Plan: {plan} +- Fix: {fix_hint} + ### Structured Issues (YAML issues list using format from Issue Format above) ### Recommendation -{N} blocker(s) require revision. Returning to planner with feedback. +{N} blocker(s), {M} warning(s) require revision. Returning to planner with feedback. +(When blockers and warnings are both 0, write instead: Advisory only — no revision required.) ``` diff --git a/agents/gsd-planner.md b/agents/gsd-planner.md index 609e81b7a..f09cfc85c 100644 --- a/agents/gsd-planner.md +++ b/agents/gsd-planner.md @@ -754,6 +754,8 @@ for each plan B in plan_order: ``` **Rule:** Same-wave plans must have zero `files_modified`/`files_deleted` overlap. After assigning waves, scan each wave; if any file appears in 2+ plans, bump the later plan to the next wave and repeat. + +Non-file coupling: @~/.claude/gsd-core/references/planner-coupling.md diff --git a/docs/INVENTORY-MANIFEST.json b/docs/INVENTORY-MANIFEST.json index 1752f2bdf..cc567c85d 100644 --- a/docs/INVENTORY-MANIFEST.json +++ b/docs/INVENTORY-MANIFEST.json @@ -251,8 +251,10 @@ "nyquist-compliance.md", "offer-next.md", "phase-argument-parsing.md", + "plan-checker-examples.md", "planner-antipatterns.md", "planner-chunked.md", + "planner-coupling.md", "planner-failing-direction.md", "planner-gap-closure.md", "planner-graphify-auto-update.md", diff --git a/docs/INVENTORY.md b/docs/INVENTORY.md index c16fb471d..8a36ccd6c 100644 --- a/docs/INVENTORY.md +++ b/docs/INVENTORY.md @@ -379,6 +379,7 @@ Full roster at `gsd-core/references/*.md`. References are shared knowledge docum | `api-coverage.md` | API-coverage gate reference (full-coverage-by-default) for the `ai-integration` capability's `verify:pre` blocking gate (#1562) — matrix format, trigger, tuning, detector CLI, and the seal-time outcome table naming every pass/block arm including `scope_unavailable` (#3909). | | `ai-frameworks.md` | AI framework decision-matrix reference for `gsd-framework-selector`. | | `executor-examples.md` | Worked examples for the gsd-executor agent. | +| `plan-checker-examples.md` | Worked example for the gsd-plan-checker agent (Scope Exceeded), moved out of the inline `` block to keep worked examples structurally separate from the agent contract, matching the other agents' reference layout. `@`-inlined at load (eager), so this costs ~0.6 KB of runtime context versus keeping it inline — a readability trade, not a size-cap remedy (#3724). | | `doc-conflict-engine.md` | Shared conflict-detection contract for ingest/import workflows. | | `execute-mvp-tdd.md` | Runtime gate semantics for execute-phase under MVP+TDD — pre-task failing-test verification, end-of-phase blocking review. | | `mvp-concepts.md` | Cross-reference index for the six MVP-related reference files; maps each file to its purpose and which workflow loads it. | @@ -428,6 +429,7 @@ The `gsd-planner` agent is decomposed into a core agent plus reference modules t | `planner-interface-context.md` | Interface context rules for executors — how to extract key interfaces/types/exports from existing code and document new interfaces that downstream plans will consume. | | `planner-load-graph-context.md` | Planner's load_graph_context step: knowledge-graph freshness + dependency-context query via the gsd_run launcher (extracted from gsd-planner.md). | | `planner-verify-command-grounding.md` | Verify Command Grounding rules (#2401): inherit `prior_verify_commands` verbatim when the story repeats, prefer `npm --prefix run