diff --git a/.changeset/quick-hawks-bark.md b/.changeset/quick-hawks-bark.md new file mode 100644 index 000000000..ec7a8af7f --- /dev/null +++ b/.changeset/quick-hawks-bark.md @@ -0,0 +1,5 @@ +--- +type: Added +pr: 2422 +--- +**`` task element (Design by Contract)** — plans may now declare a runnable/checkable fact a task assumes (env var set, prior-phase artifact present, external-setup done) that plan ordering does not guarantee; the executor asserts it before running the task and halts with a checkpoint on unmet instead of building on a broken assumption. Plans that omit `` behave exactly as today. (#1949) diff --git a/CONTEXT.md b/CONTEXT.md index 7b1dd2500..9933d3381 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -362,7 +362,10 @@ Phase 1 deliverable under `--mvp` on a new project — the Phase-1 whole-applica Single-feature task that moves one user capability from open-to-close (happy path) end-to-end. Contrast with the horizontal layer (all models, then all APIs, then all UI). The default planning unit under tracer-first decomposition (the leading task is a Tracer Bullet); SPIDR Splitting axes (Spike, Paths, Interfaces, Data, Rules) are the canonical decomposition tools when a slice is too large for one phase. ### Tracer Bullet -The default GSD decomposition lead: a **permanent, production-quality, minimal end-to-end slice** that wires one path through every layer a phase touches and becomes part of the skeleton of the final system — written for keeps, not thrown away. Contrast with a **prototype** (throwaway reconnaissance code, deleted once its lesson is learned): a tracer's *functionality* gaps are acceptable but its *architectural* gaps are not; stubs are allowed only where they can later be filled without an architectural change. GSD ships tracers, never prototypes — which is why `gsd-planner` LEADS every plan with a `type="tracer"` task (default; `--no-tracer` / `TRACER_MODE=false` opts back into horizontal layers) and `gsd-executor` runs an early integration feedback gate on the tracer's `` before expansion tasks (autonomous: halt-on-fail; interactive: `checkpoint:human-verify`). Origin: *The Pragmatic Programmer* "Tracer Bullets" (#1945); the Walking Skeleton is the Phase-1 whole-application special case. See Vertical Slice, MVP Mode, Walking Skeleton. +The default GSD decomposition lead: a **permanent, production-quality, minimal end-to-end slice** that wires one path through every layer a phase touches and becomes part of the skeleton of the final system — written for keeps, not thrown away. Contrast with a **prototype** (throwaway reconnaissance code, deleted once its lesson is learned): a tracer's *functionality* gaps are acceptable but its *architectural* gaps are not; stubs are allowed only where they can later be filled without an architectural change. GSD ships tracers, never prototypes — which is why `gsd-planner` LEADS every plan with a `type="tracer"` task (default; `--no-tracer` / `TRACER_MODE=false` opts back into horizontal layers) and `gsd-executor` runs an early integration feedback gate on the tracer's `` before expansion tasks (autonomous: halt-on-fail; interactive: `checkpoint:human-verify`). Origin: *The Pragmatic Programmer* "Tracer Bullets" (#1945); the Walking Skeleton is the Phase-1 whole-application special case. See Vertical Slice, MVP Mode, Walking Skeleton, Precondition. + +### Precondition +The front-of-task side of the GSD plan contract (issue #1949, *The Pragmatic Programmer* Topic 23 — Design by Contract). An optional `` element on `` stating, in a single line of runnable/checkable prose, what must already be true for the task to begin safely — e.g. "`OPENAI_API_KEY` is set", "`dist/schema.json` from Phase 02 exists", "server responds to GET /health". `gsd-executor` evaluates it before any other task work, using **read-only checks only** (file existence, env var presence with no value output, idempotent `GET /health`-style pings — no writes, no network POSTs, no secret emission; if a side-effecting check seems required, the executor halts and surfaces a checkpoint rather than running it): met-or-absent is a no-op (back-compat for every existing plan); unmet returns a `checkpoint:human-verify` with no partial commit, and is NEVER auto-approved under `AUTO_CFG=true` (a missing prerequisite is a fact the executor cannot establish on its own, not a verification step). `gsd-planner` emits `` in exactly three cases — `user_setup` consumption, prior-phase artifact dependency, or env-var/runtime-config dependency — when the assumption is not already guaranteed by `depends_on` ordering. Closes the contract triad whose other two sides are postconditions (``/``/``) and invariants (`must_haves.truths`). The structural validator (`cmdVerifyPlanStructure`) does not reject unknown optional tags, so adding `` passes plan-structure validation unchanged. Canonical schema reference: `docs/reference/plan-md.md` → Preconditions; emission rules + anti-patterns: `gsd-core/references/planner-preconditions.md`. The architectural-end companion is the Tracer Bullet (#1945); together they close both ends of the "outrunning your headlights" failure mode. See Tracer Bullet. ### Behavior-Adding Task Predicate over a PLAN.md task: `tdd="true"` frontmatter AND `` block names a user-visible outcome AND `` includes at least one non-`*.md` / non-`*.json` / non-`*.test.*` source file. Pure doc/config/test-only tasks are exempt. The MVP+TDD Gate (in `references/execute-mvp-tdd.md`) only halts execution on this predicate; the gsd-executor agent applies all three checks at runtime. Currently a prose-only specification — no shared utility. diff --git a/agents/gsd-executor.md b/agents/gsd-executor.md index 3e2db5fe2..78cac9406 100644 --- a/agents/gsd-executor.md +++ b/agents/gsd-executor.md @@ -144,6 +144,10 @@ At execution decision points, apply structured reasoning: For each task: +0. **Precondition check (before any other task work):** If the task carries a `` element, evaluate that single prose line first — it names a runnable/checkable fact the task assumes (env var set, prior-phase artifact present, server responding to `/health`, `user_setup` step done). Verify with **read-only checks only** — file existence, env var presence (no value output), idempotent `GET /health`-style pings. Do NOT run commands with side effects (writes, network POSTs, secret emission) as the check; if a side-effecting check seems required, halt and surface via checkpoint instead. + - **Met OR absent:** continue with no visible change to execution flow. The precondition is a no-op for the rest of the task loop. + - **Unmet:** STOP — return a `checkpoint:human-verify` (use `checkpoint_return_format`) with `**Blocked by:** Precondition not met: `. Do NOT partial-commit the task. Unmet preconditions are NEVER auto-approved, even under `AUTO_CFG=true` — a missing prerequisite is not a verification step a human can rubber-stamp; it is a fact the executor cannot establish on its own. The human either satisfies the precondition (sets the env var, completes the `user_setup` step, regenerates the artifact) or reruns `/gsd:plan-phase` to restructure. + 1. **If `type="auto"`:** - Check for `tdd="true"` → follow TDD execution flow - Execute task, apply deviation rules as needed diff --git a/agents/gsd-planner.md b/agents/gsd-planner.md index 50881ec67..e5b2a51ad 100644 --- a/agents/gsd-planner.md +++ b/agents/gsd-planner.md @@ -193,23 +193,19 @@ Every task has four required fields: **Grep gate hygiene:** `grep -c` counts comments, so header prose can be self-invalidating. Use `grep -v '^#' | grep -c token`. Bare `== 0` gates on unfiltered files are forbidden. -**Comment-text discipline (HARD GATE, #429):** A literal an acceptance criterion negative-greps for (`grep -c 'LIT' file == 0`) must NOT appear verbatim in any `` body — JSDoc samples, head-comment references, or "what NOT to do" snippets echo into the written file and trip the executor's commit-time gate. `validate_plan` (`verify.plan-structure`) fails plan creation on violation. Rephrase the literal by concept, or — when it must legitimately appear — add an allowlist marker on its own line: - -`` - -Full rules + worked examples: @gsd-core/references/planner-antipatterns.md ("Comment-Text Discipline"). +**Comment-text discipline (HARD GATE, #429):** A literal an acceptance criterion negative-greps for must NOT appear verbatim in any `` body. Full rules + `` allowlist + worked examples: @gsd-core/references/planner-antipatterns.md ("Comment-Text Discipline"). -**Region-scoped negative gates (WARN, #968):** Region-scope a file-wide negative grep when a sibling task needs that construct elsewhere in the same file; `validate_plan` WARNS. See: @gsd-core/references/planner-antipatterns.md ("Region-Scoped Negative Gates"). - -**Verify-gate hygiene (#1478/#1479):** See @gsd-core/references/planner-antipatterns.md. +**Region-scoped negative gates (WARN, #968)** and **Verify-gate hygiene (#1478/#1479):** @gsd-core/references/planner-antipatterns.md. **:** Acceptance criteria - measurable state of completion. - Good: "Valid credentials return 200 + JWT cookie, invalid credentials return 401" - Bad: "Authentication is complete" +**** (optional, one prose line): a runnable/checkable fact the task assumes that plan ordering does not guarantee — external setup (`user_setup`), a prior-phase artifact, or an env var. The executor asserts it before running the task and halts on unmet. Emission rules + the contract triad (precondition ↔ ``/`` ↔ `must_haves.truths`): @~/.claude/gsd-core/references/planner-preconditions.md. + See @~/.claude/gsd-core/references/planner-guidance.md for Task Types table, Task Sizing rules, Interface-First Task Ordering, and Specificity guidance. ## TDD Detection diff --git a/docs/INVENTORY-MANIFEST.json b/docs/INVENTORY-MANIFEST.json index 31a3c753b..d445161cd 100644 --- a/docs/INVENTORY-MANIFEST.json +++ b/docs/INVENTORY-MANIFEST.json @@ -254,6 +254,7 @@ "planner-interface-context.md", "planner-load-graph-context.md", "planner-mvp-mode.md", + "planner-preconditions.md", "planner-reviews.md", "planner-revision.md", "planner-source-audit.md", diff --git a/docs/INVENTORY.md b/docs/INVENTORY.md index 8de2825bc..d6d2990cb 100644 --- a/docs/INVENTORY.md +++ b/docs/INVENTORY.md @@ -385,6 +385,7 @@ The `gsd-planner` agent is decomposed into a core agent plus reference modules t | `planner-revision.md` | Plan revision patterns for iterative refinement. | | `planner-source-audit.md` | Planner source-audit and authority-limit rules. | | `planner-mvp-mode.md` | Vertical-slice planning rules for MVP mode. | +| `planner-preconditions.md` | Emission rules for the optional `` task element (issue #1949, Design by Contract): when to emit, the three cases (user_setup / prior-phase artifact / env-var), format, anti-patterns, and the contract triad mapping. | | `planner-human-verify-mode.md` | Rules for `workflow.human_verify_mode = end-of-phase`: suppress `checkpoint:human-verify` task emission and route deferred items via ``. | | `planner-graphify-auto-update.md` | How `load_graph_context` surfaces `.last-build-status.json` auto-update state (running / failed / stale head) alongside the existing staleness annotation. Opt-in via `graphify.auto_update` (#3347). | | `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. | diff --git a/docs/reference/plan-md.md b/docs/reference/plan-md.md index 079e3a6f4..10b707d2f 100644 --- a/docs/reference/plan-md.md +++ b/docs/reference/plan-md.md @@ -160,7 +160,34 @@ References source files the executor needs to read. Includes project-level plann ### `` -Contains one or more `` elements. Every task element must carry ``, ``, ``, ``, ``, ``, and `` for `type="auto"` and `type="tracer"` tasks. +Contains one or more `` elements. Every task element must carry ``, ``, ``, ``, ``, ``, and `` for `type="auto"` and `type="tracer"` tasks. An optional `` element (see [Preconditions](#preconditions)) may sit between `` and ``. + +--- + +## Preconditions + +`` is an **optional** element on `` (issue #1949, *The Pragmatic Programmer* Topic 23 — Design by Contract). It states, in a single line of runnable/checkable prose, what must already be true for the task to begin safely. It closes the front-of-task side of the contract triad — preconditions (before) ↔ postconditions (``/``/``, after) ↔ invariants (`must_haves.truths`, across the whole plan). + +```xml + + Add /reveal endpoint handler + server bootstraps and responds to GET /health (from the tracer slice) + server/reveal.ts + … + curl /reveal?path=… opens the OS file manager + Endpoint committed and manually verified + +``` + +**Optional and back-compat:** a plan that omits `` on every task behaves exactly as today — the executor skips the check with no visible change. Adding `` to a task tells the executor to assert it before any other task work (read-only checks only: file existence, env var presence, idempotent health pings; no side-effecting checks — halt and surface a checkpoint if one seems required) and halt (returning a `checkpoint:human-verify`, no partial commit) on an unmet precondition. Plans that include `` pass `verify plan-structure` unchanged — the structural validator checks for the presence of required tags and does not reject unknown optional tags. + +**Emission cases** (planner-side): emit `` only when a task relies on state the plan's own `depends_on` ordering does not already guarantee. Three cases cover every legitimate use: + +1. **External service setup** (`user_setup` frontmatter) — the consuming task ties a specific setup step to itself so the executor halts if the setup was skipped. +2. **Prior-phase artifact dependency** — a generated schema, a migration's dist output, a contract file from an earlier phase. Cross-phase `depends_on` does not cross phase boundaries, so `` is the explicit pointer. +3. **Environment variable / runtime configuration** — a tool, API, or script the task invokes requires an env var or runtime config that exists *now*, not at plan time. + +Full emission rules, anti-patterns ("the system is ready" is not checkable; do not use `` for intra-plan sequencing — that is what `depends_on` is for), and the contract triad mapping: see `gsd-core/references/planner-preconditions.md`. --- diff --git a/gsd-core/references/planner-preconditions.md b/gsd-core/references/planner-preconditions.md new file mode 100644 index 000000000..92cbafd99 --- /dev/null +++ b/gsd-core/references/planner-preconditions.md @@ -0,0 +1,156 @@ +# Planner Preconditions — `` Element + +> Progressive-disclosure reference for `agents/gsd-planner.md`. The planner agent +> reads this file when it needs the full emission rules for the `` +> task element (issue #1949, *The Pragmatic Programmer* Topic 23 — Design by +> Contract). The slim pointer in `agents/gsd-planner.md` → `` +> routes here; the canonical schema row lives in `docs/reference/plan-md.md`. + +## The contract triad + +Every task in a PLAN.md participates in a three-sided contract: + +| Contract side | GSD element | When it binds | +|---|---|---| +| **Precondition** | `` (optional element on ``) | Before the task begins. What must already be true for the task to run safely. | +| **Postcondition** | `` + `` + `` | After the task ends. What the task guarantees on return. | +| **Invariant** | `must_haves.truths` (plan frontmatter) | Across the whole plan/phase. What always holds. | + +GSD already models postconditions and invariants well. `` closes +the missing side: it states, in runnable/checkable terms, what must be true +*before* a task begins — so an autonomous executor stops the instant an +assumption is false, instead of building ten atomic commits on top of a +migration that never ran. + +This is the front-of-task companion to the tracer-bullet proposal (#1945): +tracers prove the *architecture* end-to-end before expansion; preconditions prove +each expansion task's *assumptions* before it runs. Together they close both ends +of the "outrunning your headlights" failure mode. + +## When to emit `` + +Emit `` ONLY when a task relies on state the plan's own `depends_on` +ordering does not already guarantee. Three cases cover every legitimate use; if +the task's prerequisite is intra-plan sequencing, use `depends_on`, NOT +``. + +### Case 1 — External service setup (`user_setup`) + +The task depends on an external service the developer must set up (account +creation, secret retrieval, dashboard configuration, billing activation). The +`user_setup` frontmatter field already enumerates these steps; `` +on the consuming task ties a specific setup step to a specific task so the +executor halts if the setup was skipped. + +```xml + + Send welcome email via SendGrid + SENDGRID_API_KEY is set (user_setup step 1 complete) + src/email/welcome.ts + ... + ... + Welcome email dispatched for a test user + +``` + +### Case 2 — Prior-phase artifact dependency + +The task consumes an artifact a prior phase promised (a generated schema, a +migration's dist output, a contract file). Cross-phase `depends_on` does not +cross phase boundaries, so a `` is the explicit pointer. + +```xml + + Generate TypeScript client from schema + dist/schema.json from Phase 02 exists and is non-empty + src/client/generated.ts + ... + ... + Client generated and compiles + +``` + +### Case 3 — Environment variable / runtime configuration + +The task shells out to a tool, hits an API, or runs a script that requires an +environment variable or runtime config that exists *now* (not at plan time). + +```xml + + Add /reveal endpoint handler + server bootstraps and responds to GET /health (from the tracer slice) + server/reveal.ts + ... + curl /reveal?path=... opens the OS file manager + Endpoint committed and manually verified + +``` + +## Format + +`` is a single line of prose inside the `` element, placed right after `` and before ``. It is **prose, not a structured block** — concrete enough that the executor agent can run a read-only check (file existence, env var presence, idempotent `GET /health`-style ping), prose enough not to require a parser extension. The executor MUST verify with read-only checks only: no writes, no network POSTs, no secret emission. If a side-effecting check seems required, the executor halts and surfaces a checkpoint rather than running it. + +```xml + + ... + ... + ... + ... + ... + ... + +``` + +## What NOT to put in a `` + +- **Vague readiness checks.** "The system is ready" is not checkable. Name the + concrete signal: a `curl` response, a file path, an env var name. +- **Intra-plan ordering.** "Task 1 has completed" — that is what `depends_on` + is for. Reserve `` for state the plan's wave/dependency graph + cannot express. +- **Implementation choices.** "We have chosen library X" — that belongs in the + `` body or a `## Decisions` row, not a runtime fact. +- **Things the task itself creates.** A precondition names a fact the task + *assumes*; if the task produces it, it is a postcondition (``). + +## Executor behavior (assertion contract) + +The executor agent reads `` before any other task work: + +| State | Executor behavior | +|---|---| +| **Absent** | No visible change — execute the task exactly as today. Back-compat for every existing plan. | +| **Met** | No visible change — proceed with the task. The precondition is logged in the SUMMARY only if it was non-trivial to verify. | +| **Unmet** | STOP — return a `checkpoint:human-verify` (use `checkpoint_return_format`) with `**Blocked by:** Precondition not met: `. Do NOT partial-commit the task. Unmet preconditions are NEVER auto-approved — a missing prerequisite is not a verification step a human can rubber-stamp, it is a fact the executor cannot establish on its own. | + +## Plan-structure validation + +`cmdVerifyPlanStructure` checks for the presence of required tags (``, +``, etc.) and warns on missing recommended tags (``, ``, +``). It does **not** reject unknown optional tags, so adding +`` to a plan passes validation unchanged. A future ADR may add +structured validation if drift emerges; v1 ships prose-only to keep the surface +minimal (Hyrum's Law: the smaller the observable surface, the less the system +depends on by accident). + +## Out of scope + +The following are explicitly NOT part of v1: + +- **Structured precondition DSL** (e.g. ``). + Prose-first keeps complexity flat; structured validation can land in a later + PR if prose proves insufficient. +- **Automatic precondition emission for every task.** The three cases above are + a hard ceiling (Zawinski's Law guard). Most tasks do not need a precondition. +- **Cross-task preconditions.** A precondition binds one task to one fact. Use + `depends_on` or a parent plan's `must_haves` for multi-task contracts. + +## See also + +- *The Pragmatic Programmer*, Topic 23 — "Design by Contract" (Hunt & Thomas). +- `docs/reference/plan-md.md` — canonical PLAN.md schema reference (where + `` appears in the task-element table). +- Tracer-bullet proposal (#1945) — the architectural-end companion to this + front-of-task contract. +- `agents/gsd-executor.md` → `` → precondition check step — the + assertion surface that consumes what this reference defines. diff --git a/tests/agent-size-baseline.json b/tests/agent-size-baseline.json index 11212ff5e..b0b2e09e7 100644 --- a/tests/agent-size-baseline.json +++ b/tests/agent-size-baseline.json @@ -14,7 +14,7 @@ "gsd-domain-researcher.md": 7032, "gsd-eval-auditor.md": 12496, "gsd-eval-planner.md": 7008, - "gsd-executor.md": 45338, + "gsd-executor.md": 46644, "gsd-framework-selector.md": 6778, "gsd-integration-checker.md": 15238, "gsd-intel-updater.md": 18166, @@ -23,7 +23,7 @@ "gsd-pattern-mapper.md": 12487, "gsd-phase-researcher.md": 40866, "gsd-plan-checker.md": 44780, - "gsd-planner.md": 49314, + "gsd-planner.md": 49172, "gsd-project-researcher.md": 22242, "gsd-research-synthesizer.md": 13847, "gsd-roadmapper.md": 22273, diff --git a/tests/fixtures/golden-install-parity/antigravity.json b/tests/fixtures/golden-install-parity/antigravity.json index baeb46666..8097d04ea 100644 --- a/tests/fixtures/golden-install-parity/antigravity.json +++ b/tests/fixtures/golden-install-parity/antigravity.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "1db46cac3f4d9889", "agents/gsd-eval-auditor.md": "1b8391f1aafb067f", "agents/gsd-eval-planner.md": "3d10fd11147f6857", - "agents/gsd-executor.md": "5dc97b2515b36731", + "agents/gsd-executor.md": "152955064cf4c9d2", "agents/gsd-framework-selector.md": "daa62c79619c76bf", "agents/gsd-integration-checker.md": "0643cd2d779b131c", "agents/gsd-intel-updater.md": "26c1f1e028c6346a", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "e62ee90d39084802", "agents/gsd-phase-researcher.md": "cff1196c8e8bb4fa", "agents/gsd-plan-checker.md": "dd1e7cdc837d8f3e", - "agents/gsd-planner.md": "c5de6bb9b277e4d4", + "agents/gsd-planner.md": "6a442501f9d4caa8", "agents/gsd-project-researcher.md": "85de7f562872ee9b", "agents/gsd-research-synthesizer.md": "18a2e1b30ff7ae3a", "agents/gsd-roadmapper.md": "7a8465ac6d4dd29e", @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "90cb2ecd1f3eb4d8", "gsd-core/references/planner-mvp-mode.md": "cdac9dde7cd8fa84", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/augment.json b/tests/fixtures/golden-install-parity/augment.json index eaab16494..364625d6f 100644 --- a/tests/fixtures/golden-install-parity/augment.json +++ b/tests/fixtures/golden-install-parity/augment.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "671c9ea949889c4a", "agents/gsd-eval-auditor.md": "fcaec7b00f94c435", "agents/gsd-eval-planner.md": "a4a5b4b3f7828ba3", - "agents/gsd-executor.md": "2df526331a77b2aa", + "agents/gsd-executor.md": "47c648f6622e939f", "agents/gsd-framework-selector.md": "4b77eebbe9288d80", "agents/gsd-integration-checker.md": "fa53e2d78be1de74", "agents/gsd-intel-updater.md": "fa40e685d7441ace", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "43c6021cf7caabfa", "agents/gsd-phase-researcher.md": "f1f6fd6a3e67c7a8", "agents/gsd-plan-checker.md": "bf1a4e636f2390de", - "agents/gsd-planner.md": "4614c9f6250d08d4", + "agents/gsd-planner.md": "55cc953c6a52ae05", "agents/gsd-project-researcher.md": "4531b7cc8f5e5f7d", "agents/gsd-research-synthesizer.md": "4a4f68e6c75b133a", "agents/gsd-roadmapper.md": "bb2f57695dbab32c", @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "ca7a7af3f35ae61b", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "dda0193a0fbd4947", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/claude-local.json b/tests/fixtures/golden-install-parity/claude-local.json index db988733b..311b0e65c 100644 --- a/tests/fixtures/golden-install-parity/claude-local.json +++ b/tests/fixtures/golden-install-parity/claude-local.json @@ -15,7 +15,7 @@ "agents/gsd-domain-researcher.md": "f1e03df842ddfb95", "agents/gsd-eval-auditor.md": "d0f45fff7370bb0b", "agents/gsd-eval-planner.md": "9cc049b82897daa4", - "agents/gsd-executor.md": "e96f3cbde4428497", + "agents/gsd-executor.md": "3c8d4fd1c29542bb", "agents/gsd-framework-selector.md": "85005d716f9d98f7", "agents/gsd-integration-checker.md": "17a8ee731986564d", "agents/gsd-intel-updater.md": "4953a465db9dadc1", @@ -24,7 +24,7 @@ "agents/gsd-pattern-mapper.md": "b45b5e106775bec1", "agents/gsd-phase-researcher.md": "4772d9eada32e8bd", "agents/gsd-plan-checker.md": "75851b147f35354a", - "agents/gsd-planner.md": "a5cdb261a6ccbb96", + "agents/gsd-planner.md": "4636f48b1b7ca1f6", "agents/gsd-project-researcher.md": "d7f355894519f9fe", "agents/gsd-research-synthesizer.md": "1c738df9932d325a", "agents/gsd-roadmapper.md": "453e9471ad27c7ea", @@ -185,6 +185,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "add55e135dd968da", "gsd-core/references/planner-mvp-mode.md": "98bcd2020c30cbd2", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/claude.json b/tests/fixtures/golden-install-parity/claude.json index af6265f3f..5f7be45b6 100644 --- a/tests/fixtures/golden-install-parity/claude.json +++ b/tests/fixtures/golden-install-parity/claude.json @@ -15,7 +15,7 @@ "agents/gsd-domain-researcher.md": "5f7d366251b957fe", "agents/gsd-eval-auditor.md": "fea2759beff0a642", "agents/gsd-eval-planner.md": "112f6730f23854e3", - "agents/gsd-executor.md": "e44ea5156ca2a42d", + "agents/gsd-executor.md": "e63187a0bbff74eb", "agents/gsd-framework-selector.md": "c350ee693cb1aa4e", "agents/gsd-integration-checker.md": "c8b4e65dee89c8ea", "agents/gsd-intel-updater.md": "5b41e05f90ce89d9", @@ -24,7 +24,7 @@ "agents/gsd-pattern-mapper.md": "b45b5e106775bec1", "agents/gsd-phase-researcher.md": "85217c69c1ed2ac6", "agents/gsd-plan-checker.md": "c70134c61b969589", - "agents/gsd-planner.md": "c07a226ddd579839", + "agents/gsd-planner.md": "3098091aa1f0756d", "agents/gsd-project-researcher.md": "f468e96f8339d1e0", "agents/gsd-research-synthesizer.md": "7be02e47f4fd901b", "agents/gsd-roadmapper.md": "8a7f1f1256a6aed5", @@ -114,6 +114,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "ca7a7af3f35ae61b", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/cline.json b/tests/fixtures/golden-install-parity/cline.json index 351f1e12b..84ac13c4e 100644 --- a/tests/fixtures/golden-install-parity/cline.json +++ b/tests/fixtures/golden-install-parity/cline.json @@ -19,7 +19,7 @@ "agents/gsd-domain-researcher.md": "0fecdaea86466a56", "agents/gsd-eval-auditor.md": "36c44303085df2f8", "agents/gsd-eval-planner.md": "3ddea88a69b4da3f", - "agents/gsd-executor.md": "9b51734f64049fda", + "agents/gsd-executor.md": "343f7d59b160d74a", "agents/gsd-framework-selector.md": "564669d479433f15", "agents/gsd-integration-checker.md": "1bbbdd3d420b994e", "agents/gsd-intel-updater.md": "42c40fffbc720d0b", @@ -28,7 +28,7 @@ "agents/gsd-pattern-mapper.md": "b526065fd2efa19c", "agents/gsd-phase-researcher.md": "c507db2ba66038f4", "agents/gsd-plan-checker.md": "a609245dbdc4ef2b", - "agents/gsd-planner.md": "2fa5c5d4529ef651", + "agents/gsd-planner.md": "c2ab476257cd07cf", "agents/gsd-project-researcher.md": "049f816c6caa4316", "agents/gsd-research-synthesizer.md": "2f7dcbff50371d4c", "agents/gsd-roadmapper.md": "bbb23d3097911516", @@ -118,6 +118,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "e469016f2d51b5bc", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "dda0193a0fbd4947", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/codebuddy.json b/tests/fixtures/golden-install-parity/codebuddy.json index 301779bca..380fcc5cd 100644 --- a/tests/fixtures/golden-install-parity/codebuddy.json +++ b/tests/fixtures/golden-install-parity/codebuddy.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "1c1a800108a2b225", "agents/gsd-eval-auditor.md": "99012004b14ea602", "agents/gsd-eval-planner.md": "4ebdd7fe9cbb0cfe", - "agents/gsd-executor.md": "4f4bbb77be53a135", + "agents/gsd-executor.md": "44149e405a126f90", "agents/gsd-framework-selector.md": "7726fccc86bfeb50", "agents/gsd-integration-checker.md": "2d8339790bbb2dc3", "agents/gsd-intel-updater.md": "c51339956197cbd3", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "92cfa2e6c2a06bf3", "agents/gsd-phase-researcher.md": "6338474da1a5d65e", "agents/gsd-plan-checker.md": "e704c083b02e8c35", - "agents/gsd-planner.md": "1ade235391742f7e", + "agents/gsd-planner.md": "8e3e314f962711cd", "agents/gsd-project-researcher.md": "e43c59f7f1f2f37a", "agents/gsd-research-synthesizer.md": "87955470c3c129b2", "agents/gsd-roadmapper.md": "20b69eff61a7a9fa", @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "ca7a7af3f35ae61b", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "dda0193a0fbd4947", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/codex.json b/tests/fixtures/golden-install-parity/codex.json index a590c9f8f..e4be6d98f 100644 --- a/tests/fixtures/golden-install-parity/codex.json +++ b/tests/fixtures/golden-install-parity/codex.json @@ -102,8 +102,8 @@ "agents/gsd-eval-auditor.toml": "9b81d61b3c5f722d", "agents/gsd-eval-planner.md": "73f2ad2ff2797a51", "agents/gsd-eval-planner.toml": "09468ad1a34ac468", - "agents/gsd-executor.md": "895482e838b13815", - "agents/gsd-executor.toml": "a95f6ad24154e646", + "agents/gsd-executor.md": "ed8080096522f7ec", + "agents/gsd-executor.toml": "126d79d90e2fdf4f", "agents/gsd-framework-selector.md": "ebae32430887d2e0", "agents/gsd-framework-selector.toml": "637e4e021b7ec380", "agents/gsd-integration-checker.md": "9cc875676cf7d741", @@ -120,8 +120,8 @@ "agents/gsd-phase-researcher.toml": "44a3d510cd0ce3bd", "agents/gsd-plan-checker.md": "e7f02c10ea788aee", "agents/gsd-plan-checker.toml": "6f8ceb421d0ad721", - "agents/gsd-planner.md": "7d48d3a81760af05", - "agents/gsd-planner.toml": "2527d19b0c47ec66", + "agents/gsd-planner.md": "cb3ff2ef2c58617c", + "agents/gsd-planner.toml": "ac51638704036f71", "agents/gsd-project-researcher.md": "959f2e57c3d69ed8", "agents/gsd-project-researcher.toml": "f395e8e8c4baf1ed", "agents/gsd-research-synthesizer.md": "497f85adf53259ef", @@ -221,6 +221,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "ca7a7af3f35ae61b", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "7889bfa28e82156b", "gsd-core/references/planner-revision.md": "2ebf1a714d1ec4bf", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/copilot.json b/tests/fixtures/golden-install-parity/copilot.json index 7f22b3a69..d0e7cc629 100644 --- a/tests/fixtures/golden-install-parity/copilot.json +++ b/tests/fixtures/golden-install-parity/copilot.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.agent.md": "d603239b3e9fe428", "agents/gsd-eval-auditor.agent.md": "3c03009564de55c8", "agents/gsd-eval-planner.agent.md": "14751876fc2b5f16", - "agents/gsd-executor.agent.md": "761523a925bd2649", + "agents/gsd-executor.agent.md": "e75e46a35b7b260a", "agents/gsd-framework-selector.agent.md": "cafeec0b3489be45", "agents/gsd-integration-checker.agent.md": "30439b804927acc7", "agents/gsd-intel-updater.agent.md": "238c1a886f35a25c", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.agent.md": "b1f488b0fa6a2395", "agents/gsd-phase-researcher.agent.md": "03cfb510a766fe93", "agents/gsd-plan-checker.agent.md": "c50a5b008ddcbfad", - "agents/gsd-planner.agent.md": "2664dc34defa7580", + "agents/gsd-planner.agent.md": "8f5f400efea5e446", "agents/gsd-project-researcher.agent.md": "d73bdbe986ffa8a6", "agents/gsd-research-synthesizer.agent.md": "f03eed4aa89e47c5", "agents/gsd-roadmapper.agent.md": "322048cf8ddcb4e5", @@ -116,6 +116,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "641b6c1ce4dd0c8c", "gsd-core/references/planner-mvp-mode.md": "355d8a9ff2b2b67e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/cursor.json b/tests/fixtures/golden-install-parity/cursor.json index 730759255..cced95471 100644 --- a/tests/fixtures/golden-install-parity/cursor.json +++ b/tests/fixtures/golden-install-parity/cursor.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "56395dbdabf076f6", "agents/gsd-eval-auditor.md": "ad2840fd5cd76172", "agents/gsd-eval-planner.md": "2049dac060d00eda", - "agents/gsd-executor.md": "68796b76140841c2", + "agents/gsd-executor.md": "e3d78836e115b18c", "agents/gsd-framework-selector.md": "4b77eebbe9288d80", "agents/gsd-integration-checker.md": "5da30584d06b878c", "agents/gsd-intel-updater.md": "b8971c5d96e63b38", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "1229c215677f740d", "agents/gsd-phase-researcher.md": "982d59921bed463d", "agents/gsd-plan-checker.md": "ba51999876d40cf2", - "agents/gsd-planner.md": "1feec75fe52b56bd", + "agents/gsd-planner.md": "c788d7fb84cf5433", "agents/gsd-project-researcher.md": "beeac940d3a10e76", "agents/gsd-research-synthesizer.md": "6315f016d55176f4", "agents/gsd-roadmapper.md": "d28e7d4bac46dde2", @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "ca7a7af3f35ae61b", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/hermes.json b/tests/fixtures/golden-install-parity/hermes.json index c9eb14893..985d27178 100644 --- a/tests/fixtures/golden-install-parity/hermes.json +++ b/tests/fixtures/golden-install-parity/hermes.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "412cdbb05ba252ea", "agents/gsd-eval-auditor.md": "4ffb265063c318e5", "agents/gsd-eval-planner.md": "03448fc9c5774b56", - "agents/gsd-executor.md": "c1f807f853dc53d7", + "agents/gsd-executor.md": "b70c976372c77dc1", "agents/gsd-framework-selector.md": "ea9981d65d6b3429", "agents/gsd-integration-checker.md": "35b4f2969d279871", "agents/gsd-intel-updater.md": "5fe5edfae2719cb8", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "cea092600aeb3978", "agents/gsd-phase-researcher.md": "2bd0402f33d757ca", "agents/gsd-plan-checker.md": "4b4e2b475bf5b5c3", - "agents/gsd-planner.md": "a48726410b038084", + "agents/gsd-planner.md": "d5fa8236f975aacd", "agents/gsd-project-researcher.md": "425a7df7f37a5c06", "agents/gsd-research-synthesizer.md": "9d31c87fc2c87ffa", "agents/gsd-roadmapper.md": "64dce5d5f9fa5654", @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "8f598e08696843c0", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/kilo.json b/tests/fixtures/golden-install-parity/kilo.json index 6c47ac40b..9583bb9e3 100644 --- a/tests/fixtures/golden-install-parity/kilo.json +++ b/tests/fixtures/golden-install-parity/kilo.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "a3874d80bcbc7380", "agents/gsd-eval-auditor.md": "630d4cd3bd6ea195", "agents/gsd-eval-planner.md": "3db12cde12aeb2c1", - "agents/gsd-executor.md": "c53d111b0c795f7c", + "agents/gsd-executor.md": "73278ea652cac62f", "agents/gsd-framework-selector.md": "ad5f2c6b9bec6270", "agents/gsd-integration-checker.md": "c503e2f4a3d8ec05", "agents/gsd-intel-updater.md": "231393da62a45b2e", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "6a5408fd11d70391", "agents/gsd-phase-researcher.md": "94818f28c498bb26", "agents/gsd-plan-checker.md": "56164206242c8caf", - "agents/gsd-planner.md": "1fbe1f6e9c3b74f0", + "agents/gsd-planner.md": "13c4b6db72b6bbb3", "agents/gsd-project-researcher.md": "60573a38d3dfd9fe", "agents/gsd-research-synthesizer.md": "1f7cd286c5783c86", "agents/gsd-roadmapper.md": "277e0a3252553ab7", @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "ca7a7af3f35ae61b", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/kimi.json b/tests/fixtures/golden-install-parity/kimi.json index 3e490e8ca..09e5b64f5 100644 --- a/tests/fixtures/golden-install-parity/kimi.json +++ b/tests/fixtures/golden-install-parity/kimi.json @@ -61,7 +61,7 @@ "agents/subagents/gsd-eval-auditor.yaml": "e3d868bd5fefe938", "agents/subagents/gsd-eval-planner.md": "70f8c5727bfb9876", "agents/subagents/gsd-eval-planner.yaml": "df8499f7af297ec2", - "agents/subagents/gsd-executor.md": "948d122c6607e343", + "agents/subagents/gsd-executor.md": "20cf0b2aa886d35c", "agents/subagents/gsd-executor.yaml": "e29422986636fd64", "agents/subagents/gsd-framework-selector.md": "a15b7aa1e0576e16", "agents/subagents/gsd-framework-selector.yaml": "fb52c31cde27b0e3", @@ -79,7 +79,7 @@ "agents/subagents/gsd-phase-researcher.yaml": "7633c8e82617e7cc", "agents/subagents/gsd-plan-checker.md": "bd302afc01ed40f0", "agents/subagents/gsd-plan-checker.yaml": "8295181071121db8", - "agents/subagents/gsd-planner.md": "aaaac708b1cf2939", + "agents/subagents/gsd-planner.md": "d29376ff9f57cc60", "agents/subagents/gsd-planner.yaml": "2e83ee194bcd7fbd", "agents/subagents/gsd-project-researcher.md": "39bc2ec5a8b18283", "agents/subagents/gsd-project-researcher.yaml": "ce12586b0347e2dc", @@ -179,6 +179,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "ca7a7af3f35ae61b", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "dda0193a0fbd4947", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/opencode.json b/tests/fixtures/golden-install-parity/opencode.json index d3e63a042..996dd209d 100644 --- a/tests/fixtures/golden-install-parity/opencode.json +++ b/tests/fixtures/golden-install-parity/opencode.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "71250e759ca9e723", "agents/gsd-eval-auditor.md": "c88890105f32ace6", "agents/gsd-eval-planner.md": "60bddb70a937f796", - "agents/gsd-executor.md": "4f180ee85214abe8", + "agents/gsd-executor.md": "84c0a7dc19ddb6c5", "agents/gsd-framework-selector.md": "1c0a10355e787675", "agents/gsd-integration-checker.md": "a9de5928e5a5c649", "agents/gsd-intel-updater.md": "493e07482fa6198a", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "7c6d1d9817a9c1e7", "agents/gsd-phase-researcher.md": "9874110700b41f48", "agents/gsd-plan-checker.md": "28ca3dc43669894f", - "agents/gsd-planner.md": "4e568338c7ee6b80", + "agents/gsd-planner.md": "87d1aa910eb02ad5", "agents/gsd-project-researcher.md": "dae210ae0b3c6e2b", "agents/gsd-research-synthesizer.md": "e02c6ad5d1b74171", "agents/gsd-roadmapper.md": "1658a40b20d8b575", @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "97f6e67b56c072c1", "gsd-core/references/planner-mvp-mode.md": "35d30284ea9110c0", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/pi.json b/tests/fixtures/golden-install-parity/pi.json index b87f500f2..30bf878f2 100644 --- a/tests/fixtures/golden-install-parity/pi.json +++ b/tests/fixtures/golden-install-parity/pi.json @@ -82,6 +82,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "ca7a7af3f35ae61b", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "dda0193a0fbd4947", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/qwen.json b/tests/fixtures/golden-install-parity/qwen.json index 3217ff6d3..1514e33cf 100644 --- a/tests/fixtures/golden-install-parity/qwen.json +++ b/tests/fixtures/golden-install-parity/qwen.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "bd054bb27beed2a7", "agents/gsd-eval-auditor.md": "57cc7458ab5de6b7", "agents/gsd-eval-planner.md": "01b665728dde4ccf", - "agents/gsd-executor.md": "988960899bd49c68", + "agents/gsd-executor.md": "6dcccfef842a49ac", "agents/gsd-framework-selector.md": "82ba6abea84226b7", "agents/gsd-integration-checker.md": "90835dbc7dfa1691", "agents/gsd-intel-updater.md": "3cc4f6ddd04676ec", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "83c66c7722e8b165", "agents/gsd-phase-researcher.md": "284e55a86ae46d7f", "agents/gsd-plan-checker.md": "c8a8fcc8ed38eff0", - "agents/gsd-planner.md": "75989c686d191143", + "agents/gsd-planner.md": "f0a5bede90f23be4", "agents/gsd-project-researcher.md": "b5baac64a15c85e2", "agents/gsd-research-synthesizer.md": "6cd9b501dc97bd50", "agents/gsd-roadmapper.md": "c357a77ab919e9e5", @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "3f6f5ee62d86f72d", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/trae.json b/tests/fixtures/golden-install-parity/trae.json index b32df012d..2734968b7 100644 --- a/tests/fixtures/golden-install-parity/trae.json +++ b/tests/fixtures/golden-install-parity/trae.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "b80f76874c04e515", "agents/gsd-eval-auditor.md": "470bf16303ec4d2e", "agents/gsd-eval-planner.md": "22334fde85723c9d", - "agents/gsd-executor.md": "2e92d53ec70b614f", + "agents/gsd-executor.md": "b3baa767abac0593", "agents/gsd-framework-selector.md": "7726fccc86bfeb50", "agents/gsd-integration-checker.md": "7cd2072984411c7f", "agents/gsd-intel-updater.md": "83de6ba9172891c3", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "b5d7a4abb1baecb9", "agents/gsd-phase-researcher.md": "2256f1f82212c757", "agents/gsd-plan-checker.md": "523119bd5d6599fe", - "agents/gsd-planner.md": "3cbce9388340c855", + "agents/gsd-planner.md": "fb330c599b9c1dac", "agents/gsd-project-researcher.md": "ddf7794e81300032", "agents/gsd-research-synthesizer.md": "a124b00271748d07", "agents/gsd-roadmapper.md": "493ef92b42b12cf4", @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "9a9383599893ea7e", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/windsurf.json b/tests/fixtures/golden-install-parity/windsurf.json index 63727749a..4aa8487a5 100644 --- a/tests/fixtures/golden-install-parity/windsurf.json +++ b/tests/fixtures/golden-install-parity/windsurf.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "56395dbdabf076f6", "agents/gsd-eval-auditor.md": "fb64fc5acf359747", "agents/gsd-eval-planner.md": "2049dac060d00eda", - "agents/gsd-executor.md": "5d56ba16562745d0", + "agents/gsd-executor.md": "45c4632bc67a12a2", "agents/gsd-framework-selector.md": "4b77eebbe9288d80", "agents/gsd-integration-checker.md": "4ffb37fb230c2b90", "agents/gsd-intel-updater.md": "a81d77c143c02108", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "ada0c169daa2f0ec", "agents/gsd-phase-researcher.md": "2a45ebde829555ec", "agents/gsd-plan-checker.md": "33fbf70b7b24eb1e", - "agents/gsd-planner.md": "c4072a4678c17485", + "agents/gsd-planner.md": "61ac0bd59b5b836a", "agents/gsd-project-researcher.md": "f6697b316b5995ba", "agents/gsd-research-synthesizer.md": "04036f38c1d373ea", "agents/gsd-roadmapper.md": "fb62e1e3de84b5f9", @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "18d50b6d12db830e", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "da39eace09a10743", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/golden-install-parity/zcode.json b/tests/fixtures/golden-install-parity/zcode.json index 056cd7184..5e498dae7 100644 --- a/tests/fixtures/golden-install-parity/zcode.json +++ b/tests/fixtures/golden-install-parity/zcode.json @@ -16,7 +16,7 @@ "agents/gsd-domain-researcher.md": "049f588663814fa2", "agents/gsd-eval-auditor.md": "54870d3b07433525", "agents/gsd-eval-planner.md": "552e9fa164c51ce8", - "agents/gsd-executor.md": "b49a6d92b2cd9831", + "agents/gsd-executor.md": "59fbb1e047b9a7c4", "agents/gsd-framework-selector.md": "8a795f230436ad2e", "agents/gsd-integration-checker.md": "c1760a0bbd4f7bf5", "agents/gsd-intel-updater.md": "944f1d903e2e9e09", @@ -25,7 +25,7 @@ "agents/gsd-pattern-mapper.md": "68ecefd60811a669", "agents/gsd-phase-researcher.md": "2235f61764d8e969", "agents/gsd-plan-checker.md": "bb38f345d3d41edc", - "agents/gsd-planner.md": "e76def94ab518216", + "agents/gsd-planner.md": "42f6e9832d5c2edc", "agents/gsd-project-researcher.md": "f572892f138734ff", "agents/gsd-research-synthesizer.md": "29949bf3f049a8f1", "agents/gsd-roadmapper.md": "840ac933e3b094f9", @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md": "b28fa3da6ae739a8", "gsd-core/references/planner-load-graph-context.md": "ca7a7af3f35ae61b", "gsd-core/references/planner-mvp-mode.md": "cfd535c9c545e73e", + "gsd-core/references/planner-preconditions.md": "4511829607ec9107", "gsd-core/references/planner-reviews.md": "dda0193a0fbd4947", "gsd-core/references/planner-revision.md": "86ba8a511f081f05", "gsd-core/references/planner-source-audit.md": "7de5bdb07232ce0b", diff --git a/tests/fixtures/install-tree/antigravity.json b/tests/fixtures/install-tree/antigravity.json index 310ffad32..18cf446a0 100644 --- a/tests/fixtures/install-tree/antigravity.json +++ b/tests/fixtures/install-tree/antigravity.json @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/augment.json b/tests/fixtures/install-tree/augment.json index a4b2e7922..de408512c 100644 --- a/tests/fixtures/install-tree/augment.json +++ b/tests/fixtures/install-tree/augment.json @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/claude-local.json b/tests/fixtures/install-tree/claude-local.json index 2f060468e..abd55e82d 100644 --- a/tests/fixtures/install-tree/claude-local.json +++ b/tests/fixtures/install-tree/claude-local.json @@ -185,6 +185,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/claude.json b/tests/fixtures/install-tree/claude.json index f0920a02e..39b9c7780 100644 --- a/tests/fixtures/install-tree/claude.json +++ b/tests/fixtures/install-tree/claude.json @@ -114,6 +114,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/cline.json b/tests/fixtures/install-tree/cline.json index be4c9c39e..36a075671 100644 --- a/tests/fixtures/install-tree/cline.json +++ b/tests/fixtures/install-tree/cline.json @@ -118,6 +118,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/codebuddy.json b/tests/fixtures/install-tree/codebuddy.json index fd8ed7e53..d4f673042 100644 --- a/tests/fixtures/install-tree/codebuddy.json +++ b/tests/fixtures/install-tree/codebuddy.json @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/codex.json b/tests/fixtures/install-tree/codex.json index d6f76ea04..cc170128b 100644 --- a/tests/fixtures/install-tree/codex.json +++ b/tests/fixtures/install-tree/codex.json @@ -221,6 +221,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/copilot.json b/tests/fixtures/install-tree/copilot.json index d7f1e3824..6b5df9763 100644 --- a/tests/fixtures/install-tree/copilot.json +++ b/tests/fixtures/install-tree/copilot.json @@ -116,6 +116,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/cursor.json b/tests/fixtures/install-tree/cursor.json index 2e3fa2eb1..a30363bca 100644 --- a/tests/fixtures/install-tree/cursor.json +++ b/tests/fixtures/install-tree/cursor.json @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/hermes.json b/tests/fixtures/install-tree/hermes.json index 58acc1d33..925431378 100644 --- a/tests/fixtures/install-tree/hermes.json +++ b/tests/fixtures/install-tree/hermes.json @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/kilo.json b/tests/fixtures/install-tree/kilo.json index 19c0fbe5d..4521e6168 100644 --- a/tests/fixtures/install-tree/kilo.json +++ b/tests/fixtures/install-tree/kilo.json @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/kimi.json b/tests/fixtures/install-tree/kimi.json index 100fc69eb..9f2615ec9 100644 --- a/tests/fixtures/install-tree/kimi.json +++ b/tests/fixtures/install-tree/kimi.json @@ -179,6 +179,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/opencode.json b/tests/fixtures/install-tree/opencode.json index ca22c4048..330121e16 100644 --- a/tests/fixtures/install-tree/opencode.json +++ b/tests/fixtures/install-tree/opencode.json @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/pi.json b/tests/fixtures/install-tree/pi.json index 677542e14..4baae4984 100644 --- a/tests/fixtures/install-tree/pi.json +++ b/tests/fixtures/install-tree/pi.json @@ -82,6 +82,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/qwen.json b/tests/fixtures/install-tree/qwen.json index 4a6132ada..041cd1410 100644 --- a/tests/fixtures/install-tree/qwen.json +++ b/tests/fixtures/install-tree/qwen.json @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/trae.json b/tests/fixtures/install-tree/trae.json index 3bff0d1ff..b48ca07e4 100644 --- a/tests/fixtures/install-tree/trae.json +++ b/tests/fixtures/install-tree/trae.json @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/windsurf.json b/tests/fixtures/install-tree/windsurf.json index e73fbe5cd..0054b2e3c 100644 --- a/tests/fixtures/install-tree/windsurf.json +++ b/tests/fixtures/install-tree/windsurf.json @@ -115,6 +115,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/fixtures/install-tree/zcode.json b/tests/fixtures/install-tree/zcode.json index ad72e0ff6..fa6044c57 100644 --- a/tests/fixtures/install-tree/zcode.json +++ b/tests/fixtures/install-tree/zcode.json @@ -186,6 +186,7 @@ "gsd-core/references/planner-interface-context.md", "gsd-core/references/planner-load-graph-context.md", "gsd-core/references/planner-mvp-mode.md", + "gsd-core/references/planner-preconditions.md", "gsd-core/references/planner-reviews.md", "gsd-core/references/planner-revision.md", "gsd-core/references/planner-source-audit.md", diff --git a/tests/precondition-element.test.cjs b/tests/precondition-element.test.cjs new file mode 100644 index 000000000..b1b6c2992 --- /dev/null +++ b/tests/precondition-element.test.cjs @@ -0,0 +1,233 @@ +// allow-test-rule: source-text-is-the-product [#1949] +// Agent .md, reference .md, and docs/reference/*.md files — their text IS what the +// runtime loads. Per CONTRIBUTING.md exception matrix, asserting these files +// document the contract tests the deployed surface, not derived +// behavior. The behavioral test (cmdVerifyPlanStructure) asserts the validator +// stays additive. Issue #1949. + +'use strict'; + +const { describe, test } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const { runGsdTools, createTempProject, cleanup } = require('./helpers.cjs'); + +const ROOT = path.resolve(__dirname, '..'); +const PLANNER = path.join(ROOT, 'agents', 'gsd-planner.md'); +const EXECUTOR = path.join(ROOT, 'agents', 'gsd-executor.md'); +const PLAN_MD_DOC = path.join(ROOT, 'docs', 'reference', 'plan-md.md'); +const PRECONDITIONS_REF = path.join(ROOT, 'gsd-core', 'references', 'planner-preconditions.md'); + +function read(rel) { + return fs.readFileSync(rel, 'utf-8').replace(/\r\n/g, '\n').replace(/\r/g, '\n'); +} + +// ─── Schema documentation (docs/reference/plan-md.md) ──────────────────────── + +describe('issue #1949: plan-md.md documents ', () => { + test('plan-md.md mentions as an optional task element', () => { + const doc = read(PLAN_MD_DOC); + assert.match( + doc, + //, + 'docs/reference/plan-md.md must document the element' + ); + }); + + test('plan-md.md states is optional and does not break plans that omit it', () => { + const doc = read(PLAN_MD_DOC); + assert.ok( + /optional/.test(doc) && /precondition/.test(doc), + 'plan-md.md must describe as optional' + ); + }); +}); + +// ─── Planner emission contract (agents/gsd-planner.md) ────────────────────── + +describe('issue #1949: gsd-planner.md declares emission', () => { + test('planner references the precondition reference file', () => { + const planner = read(PLANNER); + assert.ok( + planner.includes('planner-preconditions.md'), + 'gsd-planner.md must @-reference planner-preconditions.md (progressive disclosure)' + ); + }); + + test('planner is under the 49152-char cap after adding content', () => { + const planner = read(PLANNER); + assert.ok( + planner.length < 49152, + `gsd-planner.md is ${planner.length} chars, must be < 49152 (LF-normalized)` + ); + }); +}); + +// ─── Planner-preconditions reference file (progressive disclosure) ─────────── + +describe('issue #1949: planner-preconditions.md exists with the three emission cases', () => { + test('reference file exists', () => { + assert.ok(fs.existsSync(PRECONDITIONS_REF), `Missing: ${PRECONDITIONS_REF}`); + }); + + test('reference documents the user_setup emission case', () => { + const ref = read(PRECONDITIONS_REF); + assert.ok( + /user_setup/.test(ref) || /external service setup/i.test(ref), + 'planner-preconditions.md must document the user_setup / external-setup emission case' + ); + }); + + test('reference documents the prior-phase artifact emission case', () => { + const ref = read(PRECONDITIONS_REF); + assert.ok( + /prior.?phase artifact/i.test(ref) || /artifact from (a )?prior/i.test(ref), + 'planner-preconditions.md must document the prior-phase-artifact emission case' + ); + }); + + test('reference documents the env-var emission case', () => { + const ref = read(PRECONDITIONS_REF); + assert.ok( + /env(ironment)? var/i.test(ref), + 'planner-preconditions.md must document the env-var emission case' + ); + }); + + test('reference maps the contract triad (precondition / postcondition / invariant)', () => { + const ref = read(PRECONDITIONS_REF); + assert.ok( + /postcondition||/.test(ref), + 'planner-preconditions.md must map to existing postconditions (/)' + ); + }); +}); + +// ─── Executor assertion contract (agents/gsd-executor.md) ──────────────────── + +describe('issue #1949: gsd-executor.md asserts before task execution', () => { + test('executor mentions ', () => { + const exec = read(EXECUTOR); + assert.match( + exec, + //, + 'gsd-executor.md must reference ' + ); + }); + + test('executor routes an unmet precondition through checkpoint machinery (halt, no partial commit)', () => { + const exec = read(EXECUTOR); + assert.ok( + /precondition/i.test(exec) && /checkpoint/.test(exec), + 'gsd-executor.md must route unmet through checkpoint machinery' + ); + }); + + test('executor treats a met/absent precondition as a no-op (does not change flow)', () => { + const exec = read(EXECUTOR); + assert.ok( + /no.op|no visible change|continue/i.test(exec), + 'gsd-executor.md must state that a met or absent precondition produces no visible change' + ); + }); + + test('executor is under the 49152-char cap after adding content', () => { + const exec = read(EXECUTOR); + assert.ok( + exec.length < 49152, + `gsd-executor.md is ${exec.length} chars, must be < 49152 (LF-normalized)` + ); + }); +}); + +// ─── Behavioral test: validator stays additive (cmdVerifyPlanStructure) ────── +// +// `cmdVerifyPlanStructure` checks for PRESENCE of required tags. It must not +// reject unknown optional tags. This is the "does not break plans that omit it" +// plus "does not break plans that include it" guarantee from acceptance #1. +// Pattern mirrors tests/tracer-bullet.test.cjs (companion feature #1945). + +function planWith({ precondition = null } = {}) { + const lines = [ + '', + ' Task 1: Test', + ]; + if (precondition !== null) { + lines.push(` ${precondition}`); + } + lines.push( + ' src/x.ts', + ' Do the thing.', + ' echo ok', + ' Done', + '', + '', + ); + return [ + '---', + 'phase: 01-test', + 'plan: 01', + 'type: execute', + 'wave: 1', + 'depends_on: []', + 'files_modified: [src/x.ts]', + 'autonomous: true', + 'must_haves:', + ' truths:', + ' - "something is true"', + '---', + '', + '', + '', + ...lines, + '', + ].join('\n'); +} + +function verifyPlan(tmpDir, content) { + const rel = path.join('.planning', 'phases', '01-test', '01-01-PLAN.md'); + fs.mkdirSync(path.join(tmpDir, '.planning', 'phases', '01-test'), { recursive: true }); + fs.writeFileSync(path.join(tmpDir, rel), content); + const result = runGsdTools(`verify plan-structure ${rel}`, tmpDir); + assert.ok(result.success, `verify plan-structure failed to run: ${result.error}`); + return JSON.parse(result.output); +} + +describe('issue #1949: cmdVerifyPlanStructure accepts (additive)', () => { + test('plan with passes structural validation', (t) => { + const tmp = createTempProject(); + t.after(() => cleanup(tmp)); + + const out = verifyPlan(tmp, planWith({ precondition: 'OPENAI_API_KEY is set in the environment' })); + assert.strictEqual(out.valid, true, `plan with must be valid, errors: ${JSON.stringify(out.errors)}`); + assert.deepStrictEqual(out.errors, [], 'no validation path may reject a task'); + assert.ok( + !(out.warnings || []).some((w) => /precondition/i.test(w)), + 'nothing may flag the element specifically', + ); + }); + + test('plan without still passes structural validation (back-compat)', (t) => { + const tmp = createTempProject(); + t.after(() => cleanup(tmp)); + + const out = verifyPlan(tmp, planWith({ precondition: null })); + assert.strictEqual(out.valid, true, `plan without must be valid (back-compat), errors: ${JSON.stringify(out.errors)}`); + }); +}); + +// ─── Parity: docs/reference/plan-md.md and planner-preconditions.md agree ──── +// +// DEFECT.GENERATIVE-FIX-DIVERGENCE: two surfaces describing the same schema +// must agree on the canonical tag spelling. This is the parity guard against +// silent drift. + +describe('issue #1949: parity between plan-md.md and planner-preconditions.md', () => { + test('both surfaces spell the canonical tag ', () => { + const doc = read(PLAN_MD_DOC); + const ref = read(PRECONDITIONS_REF); + assert.ok(doc.includes(''), 'plan-md.md must spell '); + assert.ok(ref.includes(''), 'planner-preconditions.md must spell '); + }); +});