--- name: openspec-plan description: Syncs OpenSpec requirements into GSD's REQUIREMENTS.md (REQ-ID projection), maps OpenSpec tasks.md to the phase's PLAN.md files, and answers the plan:post agentVerdict gate (scenario coverage check). Runs as part of /gsd-plan-phase for any phase with an OPENSPEC-LINK.md. allowed-tools: Bash, Read, Write, Edit license: MIT metadata: author: openspec-gsd-integration version: "0.1.0" --- ## Purpose The one skill that keeps GSD's native requirement-coverage machinery (plan-checker Dimension 1, the `gap-analysis` capability) working unmodified on OpenSpec-sourced requirements, by keeping `.planning/REQUIREMENTS.md` a faithful, mechanical projection of `openspec/changes//specs/` — never hand-authored once this integration is active. ## Invocation conditions - Automatically as the `plan:post` gate's `agentVerdict` check (advisory scenario-coverage report). - Directly, to force a `REQUIREMENTS.md` re-sync without waiting for the next `/gsd-plan-phase` (e.g. after `openspec-repair` updated a spec). ## Required inputs - `.planning/phases/-/-OPENSPEC-LINK.md` (must exist — this skill does nothing for phases with no linked change). ## Files read - `openspec/changes//specs/**/spec.md` (or `openspec/specs/**/spec.md` post-archive) - `openspec/changes//tasks.md` - `.planning/phases/-/--PLAN.md` (all plans generated for the phase) - `.planning/openspec/id-registry.json` ## Files this skill may write - `.planning/REQUIREMENTS.md` — **only** the entries whose source is an OpenSpec requirement ID (tagged with a trailing `` comment so a human-authored requirement already in the file is never overwritten or reordered). - `.planning/openspec/id-registry.json` (delegates actual ID injection to `openspec-traceability`; this skill only reads the registry, it does not assign IDs itself — single-writer discipline). ## Algorithm 1. Read `OPENSPEC-LINK.md` for `change_id` and `requirement_ids`. If `ids_pending: true`, invoke `openspec-traceability` first (IDs must exist before a REQUIREMENTS.md sync — this skill never assigns IDs itself). 2. For each requirement ID, format an entry matching GSD's native `REQUIREMENTS.md` convention (`-: `), append/update it, and mark it with the `source: openspec:` trailing comment. 3. Diff against the previous sync: additions, modifications (requirement text changed upstream), and removals are each reported distinctly — a removal is never silent (see `openspec-drift` for the classification of an upstream requirement removal against in-flight work). 4. For the `tasks.md` → `PLAN.md` mapping: read `openspec/changes//tasks.md` checklist items and confirm each maps to at least one `PLAN.md` task (by requirement ID reference, per the `plan-pre-planner` fragment's instruction). Unmapped OpenSpec tasks are reported, not auto-created into plans — task decomposition remains the planner's job. 5. When invoked as the `plan:post` gate: emit the advisory report (`N/M scenarios covered`) and return — this path never writes files, only reports (the gate is non-blocking by design; `agentVerdict` checks cannot halt the loop, verified against the capability schema). ## Outputs - Updated `.planning/REQUIREMENTS.md` (OpenSpec-sourced entries only) - Advisory coverage report (when invoked as the `plan:post` gate) ## Failure states - `ids_pending` still true after delegating to `openspec-traceability` → stop, surface the spec files that need manual review (likely malformed headings). - An OpenSpec requirement was removed upstream while a `PLAN.md` already implements it → classify as `SPEC_CONFLICT`, hand to `openspec-repair`, do not silently delete the corresponding `REQUIREMENTS.md` line out from under in-flight work without flagging it. ## Guardrails - Never edits a `REQUIREMENTS.md` entry lacking the `source: openspec:` marker — those are human-authored and out of scope. - Never assigns stable IDs itself (single-writer: only `openspec-traceability` does). - The `plan:post` gate path never writes anything — advisory-only means read-only. ## Idempotency Re-running the sync with no upstream changes produces a zero-line diff. IDs are stable across reruns (delegated, cached in `id-registry.json`). ## Example ``` $ openspec-plan --sync --change add-health-check-endpoint [openspec-plan] REQUIREMENTS.md: +2 (HEALTH-01, HEALTH-02), 0 modified, 0 removed [openspec-plan] tasks.md: 4/4 tasks mapped to PLAN.md acceptance criteria ```