diff --git a/README.md b/README.md index bb398c6b68..8c18ed00e8 100644 --- a/README.md +++ b/README.md @@ -213,7 +213,9 @@ The Pi package loads the Superpowers skills and a small extension that injects t 6. **requesting-code-review** - Activates between tasks. Reviews against plan, reports issues by severity. Critical issues block progress. -7. **finishing-a-development-branch** - Activates when tasks complete. Verifies tests, presents options (merge/PR/keep/discard), cleans up worktree. +7. **sync-requirements** - Activates when tasks complete and durable requirements should be preserved. Merges specs, plans, commits, reports, and session-only user requirements into `docs/req//req.md`. + +8. **finishing-a-development-branch** - Activates when tasks complete. Verifies tests, offers requirement sync, presents options (merge/PR/keep/discard), cleans up worktree. **The agent checks for relevant skills before any task.** Mandatory workflows, not suggestions. @@ -237,6 +239,7 @@ The Pi package loads the Superpowers skills and a small extension that injects t - **receiving-code-review** - Responding to feedback - **using-git-worktrees** - Parallel development branches - **finishing-a-development-branch** - Merge/PR decision workflow +- **sync-requirements** - Durable requirements sync into `docs/req//req.md` - **subagent-driven-development** - Fast iteration with two-stage review (spec compliance, then code quality) **Meta** diff --git a/docs/req/sync-requirements/req.md b/docs/req/sync-requirements/req.md new file mode 100644 index 0000000000..269850a407 --- /dev/null +++ b/docs/req/sync-requirements/req.md @@ -0,0 +1,124 @@ +# sync-requirements Requirements + +## Purpose +Preserve durable requirements learned during Superpowers-driven work by merging dated design specs, implementation plans, branch evidence, and session-only user requests into long-lived PRD-style requirements documents. + +## Requirements + +### Requirement: Durable Requirements Storage +The system SHALL store long-lived module requirements in `docs/req//req.md`. + +#### Scenario: Creating a module requirements document +- **WHEN** durable requirements for a module do not yet have a req document +- **THEN** the agent creates `docs/req//req.md` +- **AND** the document uses `# Requirements`, `## Purpose`, and `## Requirements` sections + +#### Scenario: Preserving dated execution artifacts +- **WHEN** syncing durable requirements from Superpowers work +- **THEN** the agent SHALL keep dated brainstorming specs under `docs/superpowers/specs/` +- **AND** the agent SHALL keep dated implementation plans under `docs/superpowers/plans/` +- **BUT** the agent MUST NOT rewrite or archive those dated artifacts as part of requirements sync + +### Requirement: Requirement Authoring Convention +The system SHALL define a reusable authoring convention for PRD-style requirements documents. + +#### Scenario: Writing normative requirements +- **WHEN** the agent writes a requirement body +- **THEN** the requirement uses `SHALL` or `MUST` for required behavior +- **AND** the requirement uses `SHALL NOT` or `MUST NOT` for prohibited behavior +- **BUT** the requirement MUST NOT use weak substitutes such as "should avoid" or "does not usually" + +#### Scenario: Writing verifiable scenarios +- **WHEN** the agent documents a concrete behavior or use case +- **THEN** it uses a `#### Scenario: ` heading +- **AND** scenario steps use `**WHEN**` and `**THEN**` at minimum +- **AND** `**GIVEN**` is used only when an initial state matters +- **AND** `**AND**` is used for additional conditions or outcomes +- **AND** `**BUT**` is used only for prohibited behavior, exceptions, or negative expectations + +### Requirement: Requirements Sync Skill +The system SHALL provide a `sync-requirements` skill that owns durable requirements synchronization. + +#### Scenario: Resolving sync context +- **WHEN** the agent starts requirements sync +- **THEN** it looks for referenced or recently created design specs under `docs/superpowers/specs/` +- **AND** it looks for referenced or recently created plans under `docs/superpowers/plans/` +- **AND** it considers branch commits, task reports, progress ledgers, final summaries, and active-session user requirements +- **BUT** it MUST NOT invent a work context when the relevant artifacts cannot be inferred uniquely + +#### Scenario: Capturing session-only requirements +- **WHEN** the user adds or changes requirements after the original spec or plan +- **THEN** the sync workflow includes those session-only user requirements in the durable requirements analysis +- **AND** later explicit user messages supersede conflicting earlier spec or plan text + +#### Scenario: Skipping non-durable details +- **WHEN** extracting durable requirements from a session or branch +- **THEN** the agent skips transient test failures, debugging dead ends, local command output, implementation accidents, and branch management choices +- **BUT** the agent SHALL preserve one of those details if the user explicitly changed the intended durable behavior + +### Requirement: Convention-Aware Merge +The system SHALL merge requirements by intent rather than copying dated artifacts verbatim. + +#### Scenario: Updating target req documents +- **WHEN** a durable behavior is new +- **THEN** the sync workflow adds a new `### Requirement:` block +- **AND** additional examples or edge cases become new `#### Scenario:` entries under an existing requirement +- **AND** changed behavior updates the existing requirement or scenario while preserving unrelated content + +#### Scenario: Preserving existing requirements +- **WHEN** the target req document contains requirements not mentioned by the current work +- **THEN** the sync workflow preserves that existing content +- **BUT** it SHALL remove behavior only when the current work explicitly deprecates it + +#### Scenario: Idempotent sync +- **WHEN** the sync workflow runs more than once for the same durable requirements +- **THEN** it reports requirements or scenarios that are already synchronized +- **BUT** it MUST NOT duplicate equivalent requirements or scenarios + +### Requirement: Ambiguity and Failure Handling +The system SHALL stop or ask when safe requirements sync cannot be completed confidently. + +#### Scenario: No reliable sync context +- **WHEN** no design spec, plan, commits, or session requirements can be identified +- **THEN** the agent reports that there is nothing reliable to sync +- **AND** it returns to the caller without editing req documents + +#### Scenario: Ambiguous module selection +- **WHEN** multiple target modules are plausible +- **THEN** the agent asks one multiple-choice question that lists plausible module names and their rationale +- **BUT** the agent MUST NOT silently choose a module in ambiguous cases + +#### Scenario: Existing requirement conflict +- **WHEN** a target module requirements document contains ambiguous or contradictory existing requirements +- **THEN** the agent asks the user before editing those requirements + +#### Scenario: File write failure +- **WHEN** writing a req document fails +- **THEN** the agent stops and reports the exact path and failure + +### Requirement: Finishing Workflow Prompt +The system SHALL offer requirements sync before completing a development branch. + +#### Scenario: Completed implementation reaches branch finishing +- **WHEN** implementation tasks are complete and verification has passed +- **THEN** `finishing-a-development-branch` asks whether to sync durable requirements into `docs/req//req.md` +- **AND** the prompt includes options to sync now, skip sync and continue finishing, or cancel finishing +- **AND** choosing sync delegates to `sync-requirements` +- **BUT** `finishing-a-development-branch` MUST NOT inline the requirements merge algorithm + +#### Scenario: User cancels finishing during sync prompt +- **WHEN** the user chooses to cancel finishing from the requirement sync prompt +- **THEN** the agent stops before presenting merge, PR, keep, or discard options + +### Requirement: Static Workflow Verification +The system SHALL include static regression coverage for the requirements sync workflow. + +#### Scenario: Verifying sync-requirements invariants +- **WHEN** the static skill test runs +- **THEN** it verifies the `sync-requirements` skill name, canonical req path, dated spec and plan inputs, session-only requirement handling, idempotency, OpenSpec independence, and requirement authoring conventions +- **AND** it verifies `SHALL NOT`, `MUST NOT`, and `**BUT**` support + +#### Scenario: Verifying finishing and README integration +- **WHEN** the static skill test runs +- **THEN** it verifies the finishing workflow prompts for requirements sync after tests pass and before environment detection +- **AND** it verifies README documents `sync-requirements` before `finishing-a-development-branch` in the basic workflow diff --git a/docs/superpowers/plans/2026-06-20-sync-requirements.md b/docs/superpowers/plans/2026-06-20-sync-requirements.md new file mode 100644 index 0000000000..31b4bb314e --- /dev/null +++ b/docs/superpowers/plans/2026-06-20-sync-requirements.md @@ -0,0 +1,823 @@ +# Sync Requirements Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add a `sync-requirements` skill that lets completed Superpowers work update durable PRD-style requirements documents at `docs/req//req.md`. + +**Architecture:** This is a behavior-shaping skill change, so the implementation is documentation plus static workflow checks. A new `sync-requirements` skill owns context resolution, durable requirement extraction, module selection, convention-aware merging, and reporting. `finishing-a-development-branch` only prompts after tests pass and delegates the merge workflow to the new skill. + +**Tech Stack:** Markdown skill files, bash static regression tests, existing `tests/claude-code/run-skill-tests.sh` runner, repository README workflow docs. + +## Global Constraints + +- Main requirements documents live at `docs/req//req.md`. +- The new skill name is exactly `sync-requirements`. +- Dated brainstorming specs remain under `docs/superpowers/specs/`; dated writing plans remain under `docs/superpowers/plans/`. +- The sync workflow must consider active-session user requirements that were added after the original spec or plan. +- Requirement authoring conventions must include `SHALL`, `MUST`, `SHALL NOT`, `MUST NOT`, `### Requirement:`, `#### Scenario:`, and scenario bullets using `**GIVEN**`, `**WHEN**`, `**THEN**`, `**AND**`, and `**BUT**`. +- `**BUT**` is only for prohibited behavior, exceptions, or negative expectations. +- Do not add runtime dependencies or require OpenSpec CLI. +- Do not archive or rewrite dated design specs or implementation plans. +- Use PowerShell-safe command chaining when running commands on Windows; do not use `&&`. + +--- + +## File Structure + +- Create `skills/sync-requirements/SKILL.md`: the new skill. It contains the full workflow and authoring conventions. +- Create `tests/claude-code/test-sync-requirements-skill.sh`: static regression test for the skill, finishing-flow prompt, and README workflow docs. +- Modify `tests/claude-code/run-skill-tests.sh`: include the new static test in the fast skill test suite. +- Modify `skills/finishing-a-development-branch/SKILL.md`: add a requirement-sync prompt after test verification and before environment detection. +- Modify `README.md`: document `sync-requirements` in the basic workflow and skills list. + +## Task 1: Add `sync-requirements` Skill With Static Guards + +**Files:** +- Create: `skills/sync-requirements/SKILL.md` +- Create: `tests/claude-code/test-sync-requirements-skill.sh` +- Modify: `tests/claude-code/run-skill-tests.sh` + +**Interfaces:** +- Produces: `skills/sync-requirements/SKILL.md` with frontmatter `name: sync-requirements`. +- Produces: `tests/claude-code/test-sync-requirements-skill.sh`, a bash test that later tasks will extend. +- Consumes: Existing static test style from `tests/claude-code/test-worktree-path-policy.sh`. + +- [ ] **Step 1: Write the failing static test for the new skill** + +Create `tests/claude-code/test-sync-requirements-skill.sh` with this content: + +```bash +#!/usr/bin/env bash +# Regression check: sync-requirements owns durable requirements sync. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +SYNC_SKILL="$REPO_ROOT/skills/sync-requirements/SKILL.md" +FINISHING_SKILL="$REPO_ROOT/skills/finishing-a-development-branch/SKILL.md" +README_FILE="$REPO_ROOT/README.md" + +failures=0 + +assert_file_exists() { + local file="$1" + local label="$2" + + if [ -f "$file" ]; then + echo " [PASS] $label" + else + echo " [FAIL] $label" + echo " Missing file: $file" + failures=$((failures + 1)) + fi +} + +assert_contains() { + local file="$1" + local pattern="$2" + local label="$3" + + if grep -Fq "$pattern" "$file"; then + echo " [PASS] $label" + else + echo " [FAIL] $label" + echo " Expected to find: $pattern" + echo " In file: $file" + failures=$((failures + 1)) + fi +} + +assert_order() { + local file="$1" + local first="$2" + local second="$3" + local label="$4" + local first_line + local second_line + + first_line=$(grep -Fn "$first" "$file" | head -1 | cut -d: -f1 || true) + second_line=$(grep -Fn "$second" "$file" | head -1 | cut -d: -f1 || true) + + if [ -n "$first_line" ] && [ -n "$second_line" ] && [ "$first_line" -lt "$second_line" ]; then + echo " [PASS] $label" + else + echo " [FAIL] $label" + echo " Expected '$first' before '$second'" + echo " In file: $file" + failures=$((failures + 1)) + fi +} + +echo "=== Sync Requirements Skill Test ===" +echo "" + +assert_file_exists "$SYNC_SKILL" "sync-requirements skill exists" + +if [ -f "$SYNC_SKILL" ]; then + assert_contains "$SYNC_SKILL" "name: sync-requirements" "skill frontmatter uses exact name" + assert_contains "$SYNC_SKILL" "description: Use when" "skill frontmatter has trigger description" + assert_contains "$SYNC_SKILL" 'docs/req//req.md' "skill documents canonical req path" + assert_contains "$SYNC_SKILL" 'docs/superpowers/specs/' "skill keeps dated brainstorming specs as inputs" + assert_contains "$SYNC_SKILL" 'docs/superpowers/plans/' "skill keeps dated writing plans as inputs" + assert_contains "$SYNC_SKILL" 'session-only user requirements' "skill considers session-only requirements" + assert_contains "$SYNC_SKILL" 'SHALL NOT' "skill supports SHALL NOT" + assert_contains "$SYNC_SKILL" 'MUST NOT' "skill supports MUST NOT" + assert_contains "$SYNC_SKILL" '**BUT**' "skill supports BUT scenario steps" + assert_contains "$SYNC_SKILL" 'prohibited behavior, exceptions, or negative expectations' "skill constrains BUT semantics" + assert_contains "$SYNC_SKILL" '### Requirement:' "skill documents requirement heading format" + assert_contains "$SYNC_SKILL" '#### Scenario:' "skill documents scenario heading format" + assert_contains "$SYNC_SKILL" 'idempotent' "skill requires idempotent sync" + assert_contains "$SYNC_SKILL" 'Do not require the OpenSpec CLI' "skill avoids OpenSpec runtime dependency" + assert_order "$SYNC_SKILL" 'Resolve Work Context' 'Extract Durable Requirements' "skill resolves context before extraction" + assert_order "$SYNC_SKILL" 'Extract Durable Requirements' 'Select Target Modules' "skill extracts before module selection" + assert_order "$SYNC_SKILL" 'Select Target Modules' 'Merge Intelligently' "skill selects modules before merge" +fi + +echo "" + +if [ "$failures" -gt 0 ]; then + echo "STATUS: FAILED ($failures failures)" + exit 1 +fi + +echo "STATUS: PASSED" +``` + +- [ ] **Step 2: Run the test and verify it fails** + +Run: + +```bash +bash tests/claude-code/test-sync-requirements-skill.sh +``` + +Expected: FAIL with at least: + +```text +[FAIL] sync-requirements skill exists +STATUS: FAILED +``` + +- [ ] **Step 3: Create the minimal `sync-requirements` skill** + +Create `skills/sync-requirements/SKILL.md` with this content: + +````markdown +--- +name: sync-requirements +description: Use when implementation work is complete or durable requirements need to be merged from specs, plans, commits, reports, or session discussion into long-lived requirements documents +--- + +# Sync Requirements + +## Overview + +Merge durable requirements learned during Superpowers-driven work into +PRD-style module requirements documents. + +**Core principle:** dated specs and plans are execution artifacts; durable +requirements belong in `docs/req//req.md`. + +**Announce at start:** "I'm using the sync-requirements skill to update durable requirements." + +## When to Use + +Use this skill when: + +- Implementation work is complete and requirements may need to be preserved. +- A user asks to merge a brainstorming spec or writing plan into long-lived requirements. +- A session included user-requested behavior changes after the original spec or plan. +- You need to update `docs/req//req.md` without archiving or rewriting dated artifacts. + +Do not use this skill for: + +- Temporary notes, command output, or debugging traces. +- Pure implementation details that belong in design docs, plans, or code comments. +- OpenSpec project state under `openspec/`; do not require the OpenSpec CLI. + +## Requirements Document Convention + +Main requirements documents live at: + +```text +docs/req//req.md +``` + +Use stable, lowercase, hyphen-separated module names. + +Each req document uses this structure: + +```markdown +# Requirements + +## Purpose +One short paragraph explaining what durable capability this module describes. + +## Requirements + +### Requirement: +The system SHALL describe one durable behavior, constraint, or user-visible rule. + +#### Scenario: +- **GIVEN** an initial state, when the state matters +- **WHEN** a condition, trigger, or user action occurs +- **THEN** an observable result is required +- **AND** an additional condition or outcome also applies +- **BUT** a prohibited behavior, exception, or negative expectation must hold +``` + +Requirement bodies use normative language: + +- Use **SHALL** or **MUST** for required behavior. +- Use **SHALL NOT** or **MUST NOT** for prohibited behavior. +- Do not use weak substitutes such as "should avoid" or "does not usually". +- Every requirement must have at least one `#### Scenario:` block. +- Scenario steps use **WHEN** and **THEN** at minimum. +- Use **GIVEN** only when an initial state matters. +- Use **AND** for additional conditions or outcomes. +- Use **BUT** only for prohibited behavior, exceptions, or negative expectations. + +## Workflow + +### 1. Resolve Work Context + +Identify the work to sync. Look for: + +- A referenced or recently created design spec under `docs/superpowers/specs/`. +- A referenced or recently created plan under `docs/superpowers/plans/`. +- Current branch commits, task reports, progress ledgers, and final summaries. +- Session-only user requirements added after the original spec or plan. + +If the relevant spec or plan cannot be inferred uniquely, ask the user to choose +from candidate files. Do not invent a context. + +### 2. Extract Durable Requirements + +Read the available design spec and plan, then review the active session for +additional user requirements. + +Extract durable product, workflow, behavior, and constraint requirements. + +Skip: + +- Transient test failures. +- Debugging dead ends. +- Local command output. +- Implementation accidents. +- Branch management choices. + +Keep a requirement from those skipped categories only when the user explicitly +changed the intended durable behavior. + +When a later user message conflicts with the original spec or plan, the later +explicit user message wins. Mention that replacement in the sync summary. + +### 3. Select Target Modules + +Map each durable requirement to one or more module req documents under +`docs/req//req.md`. + +If the target req document does not exist, create it with `# Requirements`, +`## Purpose`, and `## Requirements`. + +If the module boundary is unclear, ask one multiple-choice question showing the +plausible module names and why each is plausible. + +### 4. Merge Intelligently + +Apply requirements by intent rather than copying artifact text: + +- New durable behavior becomes a new `### Requirement`. +- Additional examples or edge cases become new `#### Scenario` entries under an existing requirement. +- Changed behavior updates the existing requirement or scenario while preserving unrelated content. +- Removed behavior is deleted only when the current work explicitly deprecated it. +- Renames update headings while preserving scenarios that still apply. + +The operation must be idempotent. If the target req document already states the +same requirement or scenario, report that it is already synchronized instead of +duplicating it. + +### 5. Report Results + +After syncing, report: + +- Which module requirements documents were created or modified. +- Which requirements or scenarios were added, modified, removed, or already in sync. +- Which session-only user requirements were captured. +- Which candidate details were skipped as temporary or non-durable. + +## Guardrails + +- Do not require the OpenSpec CLI. +- Do not create an `openspec/` directory. +- Do not archive or rewrite dated specs in `docs/superpowers/specs/`. +- Do not archive or rewrite dated plans in `docs/superpowers/plans/`. +- Do not silently edit requirements if module selection is ambiguous. +- Preserve existing req document content not mentioned by the current work. +```` + +- [ ] **Step 4: Run the focused test and verify it passes** + +Run: + +```bash +bash tests/claude-code/test-sync-requirements-skill.sh +``` + +Expected: + +```text +STATUS: PASSED +``` + +- [ ] **Step 5: Wire the test into the fast skill test runner** + +In `tests/claude-code/run-skill-tests.sh`, change the fast test list from: + +```bash +tests=( + "test-worktree-path-policy.sh" + "test-sdd-workspace.sh" + "test-subagent-driven-development.sh" +) +``` + +to: + +```bash +tests=( + "test-worktree-path-policy.sh" + "test-sync-requirements-skill.sh" + "test-sdd-workspace.sh" + "test-subagent-driven-development.sh" +) +``` + +- [ ] **Step 6: Run the new test through the runner** + +Run: + +```bash +bash tests/claude-code/run-skill-tests.sh --test test-sync-requirements-skill.sh +``` + +Expected: + +```text +Running: test-sync-requirements-skill.sh +[PASS] +STATUS: PASSED +``` + +- [ ] **Step 7: Commit Task 1** + +Run: + +```bash +git add skills/sync-requirements/SKILL.md tests/claude-code/test-sync-requirements-skill.sh tests/claude-code/run-skill-tests.sh +git commit -m "feat: add sync-requirements skill" +``` + +## Task 2: Add Requirement Sync Prompt to Branch Finishing + +**Files:** +- Modify: `tests/claude-code/test-sync-requirements-skill.sh` +- Modify: `skills/finishing-a-development-branch/SKILL.md` + +**Interfaces:** +- Consumes: `sync-requirements` skill from Task 1. +- Produces: Finishing workflow step that prompts after tests pass and before environment detection. + +- [ ] **Step 1: Extend the static test for finishing workflow integration** + +Replace `tests/claude-code/test-sync-requirements-skill.sh` with this content: + +```bash +#!/usr/bin/env bash +# Regression check: sync-requirements owns durable requirements sync. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +SYNC_SKILL="$REPO_ROOT/skills/sync-requirements/SKILL.md" +FINISHING_SKILL="$REPO_ROOT/skills/finishing-a-development-branch/SKILL.md" +README_FILE="$REPO_ROOT/README.md" + +failures=0 + +assert_file_exists() { + local file="$1" + local label="$2" + + if [ -f "$file" ]; then + echo " [PASS] $label" + else + echo " [FAIL] $label" + echo " Missing file: $file" + failures=$((failures + 1)) + fi +} + +assert_contains() { + local file="$1" + local pattern="$2" + local label="$3" + + if grep -Fq "$pattern" "$file"; then + echo " [PASS] $label" + else + echo " [FAIL] $label" + echo " Expected to find: $pattern" + echo " In file: $file" + failures=$((failures + 1)) + fi +} + +assert_order() { + local file="$1" + local first="$2" + local second="$3" + local label="$4" + local first_line + local second_line + + first_line=$(grep -Fn "$first" "$file" | head -1 | cut -d: -f1 || true) + second_line=$(grep -Fn "$second" "$file" | head -1 | cut -d: -f1 || true) + + if [ -n "$first_line" ] && [ -n "$second_line" ] && [ "$first_line" -lt "$second_line" ]; then + echo " [PASS] $label" + else + echo " [FAIL] $label" + echo " Expected '$first' before '$second'" + echo " In file: $file" + failures=$((failures + 1)) + fi +} + +echo "=== Sync Requirements Skill Test ===" +echo "" + +assert_file_exists "$SYNC_SKILL" "sync-requirements skill exists" + +if [ -f "$SYNC_SKILL" ]; then + assert_contains "$SYNC_SKILL" "name: sync-requirements" "skill frontmatter uses exact name" + assert_contains "$SYNC_SKILL" "description: Use when" "skill frontmatter has trigger description" + assert_contains "$SYNC_SKILL" 'docs/req//req.md' "skill documents canonical req path" + assert_contains "$SYNC_SKILL" 'docs/superpowers/specs/' "skill keeps dated brainstorming specs as inputs" + assert_contains "$SYNC_SKILL" 'docs/superpowers/plans/' "skill keeps dated writing plans as inputs" + assert_contains "$SYNC_SKILL" 'session-only user requirements' "skill considers session-only requirements" + assert_contains "$SYNC_SKILL" 'SHALL NOT' "skill supports SHALL NOT" + assert_contains "$SYNC_SKILL" 'MUST NOT' "skill supports MUST NOT" + assert_contains "$SYNC_SKILL" '**BUT**' "skill supports BUT scenario steps" + assert_contains "$SYNC_SKILL" 'prohibited behavior, exceptions, or negative expectations' "skill constrains BUT semantics" + assert_contains "$SYNC_SKILL" '### Requirement:' "skill documents requirement heading format" + assert_contains "$SYNC_SKILL" '#### Scenario:' "skill documents scenario heading format" + assert_contains "$SYNC_SKILL" 'idempotent' "skill requires idempotent sync" + assert_contains "$SYNC_SKILL" 'Do not require the OpenSpec CLI' "skill avoids OpenSpec runtime dependency" + assert_order "$SYNC_SKILL" 'Resolve Work Context' 'Extract Durable Requirements' "skill resolves context before extraction" + assert_order "$SYNC_SKILL" 'Extract Durable Requirements' 'Select Target Modules' "skill extracts before module selection" + assert_order "$SYNC_SKILL" 'Select Target Modules' 'Merge Intelligently' "skill selects modules before merge" +fi + +assert_contains "$FINISHING_SKILL" '### Step 1.5: Requirement Sync Prompt' "finishing skill has requirement sync step" +assert_contains "$FINISHING_SKILL" 'Sync requirements now (recommended)' "finishing prompt includes recommended sync option" +assert_contains "$FINISHING_SKILL" 'Skip sync and continue finishing' "finishing prompt includes skip option" +assert_contains "$FINISHING_SKILL" 'Cancel finishing' "finishing prompt includes cancel option" +assert_contains "$FINISHING_SKILL" 'sync-requirements' "finishing skill delegates to sync-requirements" +assert_contains "$FINISHING_SKILL" 'docs/req//req.md' "finishing prompt names req path" +assert_order "$FINISHING_SKILL" '**If tests pass:** Continue to Step 1.5.' '### Step 1.5: Requirement Sync Prompt' "finishing enters sync prompt after tests pass" +assert_order "$FINISHING_SKILL" '### Step 1.5: Requirement Sync Prompt' '### Step 2: Detect Environment' "sync prompt happens before environment detection" + +echo "" + +if [ "$failures" -gt 0 ]; then + echo "STATUS: FAILED ($failures failures)" + exit 1 +fi + +echo "STATUS: PASSED" +``` + +- [ ] **Step 2: Run the test and verify the finishing assertions fail** + +Run: + +```bash +bash tests/claude-code/test-sync-requirements-skill.sh +``` + +Expected: FAIL with at least: + +```text +[FAIL] finishing skill has requirement sync step +STATUS: FAILED +``` + +- [ ] **Step 3: Update the finishing workflow core principle** + +In `skills/finishing-a-development-branch/SKILL.md`, replace: + +```markdown +**Core principle:** Verify tests → Detect environment → Present options → Execute choice → Clean up. +``` + +with: + +```markdown +**Core principle:** Verify tests → Offer requirements sync → Detect environment → Present options → Execute choice → Clean up. +``` + +- [ ] **Step 4: Route test success to the new Step 1.5** + +In `skills/finishing-a-development-branch/SKILL.md`, replace: + +```markdown +**If tests pass:** Continue to Step 2. +``` + +with: + +```markdown +**If tests pass:** Continue to Step 1.5. +``` + +- [ ] **Step 5: Add Step 1.5 before environment detection** + +Insert this section immediately before the existing `### Step 2: Detect Environment` heading: + +````markdown +### Step 1.5: Requirement Sync Prompt + +Before finishing the branch, offer to sync durable requirements learned during +the session into `docs/req//req.md`. + +Present exactly these 3 options: + +``` +Requirements may have changed during this session. Would you like to sync the +durable requirements into docs/req//req.md before finishing? + +1. Sync requirements now (recommended) +2. Skip sync and continue finishing +3. Cancel finishing + +Which option? +``` + +**If user chooses 1:** Announce: "I'm using the sync-requirements skill to update durable requirements." Use `sync-requirements`, then return to Step 2. + +**If user chooses 2:** Continue to Step 2. + +**If user chooses 3:** Stop. Do not present merge, PR, keep, or discard options. + +**Do not inline the merge algorithm here.** This skill only prompts; `sync-requirements` owns context resolution, durable requirement extraction, module selection, merging, and reporting. + +```` + +- [ ] **Step 6: Update finishing quick reference and red flags** + +In `skills/finishing-a-development-branch/SKILL.md`, under `## Common Mistakes`, add this section before `**Open-ended questions**`: + +```markdown +**Skipping requirement sync prompt** +- **Problem:** Durable requirements learned during implementation disappear after branch completion +- **Fix:** Always offer Step 1.5 after tests pass and before branch finishing choices +``` + +In the `Always:` list under `## Red Flags`, insert this bullet after `Verify tests before offering options`: + +```markdown +- Offer requirements sync after tests pass +``` + +- [ ] **Step 7: Run the focused test and verify it passes** + +Run: + +```bash +bash tests/claude-code/test-sync-requirements-skill.sh +``` + +Expected: + +```text +STATUS: PASSED +``` + +- [ ] **Step 8: Commit Task 2** + +Run: + +```bash +git add tests/claude-code/test-sync-requirements-skill.sh skills/finishing-a-development-branch/SKILL.md +git commit -m "feat: prompt for requirements sync when finishing" +``` + +## Task 3: Document the Workflow in README + +**Files:** +- Modify: `tests/claude-code/test-sync-requirements-skill.sh` +- Modify: `README.md` + +**Interfaces:** +- Consumes: `sync-requirements` skill and finishing prompt from Tasks 1 and 2. +- Produces: README workflow docs that mention the new skill in the basic workflow and skills library. + +- [ ] **Step 1: Extend the static test for README documentation** + +In `tests/claude-code/test-sync-requirements-skill.sh`, add these assertions after the finishing assertions and before `echo ""`: + +```bash +assert_contains "$README_FILE" '**sync-requirements**' "README lists sync-requirements" +assert_contains "$README_FILE" 'docs/req//req.md' "README documents req path" +assert_order "$README_FILE" '**requesting-code-review**' '**sync-requirements**' "README places sync before finishing in workflow" +assert_order "$README_FILE" '**sync-requirements**' '**finishing-a-development-branch**' "README places finishing after sync" +``` + +- [ ] **Step 2: Run the test and verify README assertions fail** + +Run: + +```bash +bash tests/claude-code/test-sync-requirements-skill.sh +``` + +Expected: FAIL with at least: + +```text +[FAIL] README lists sync-requirements +STATUS: FAILED +``` + +- [ ] **Step 3: Update the README basic workflow** + +In `README.md`, replace the current workflow ending: + +```markdown +6. **requesting-code-review** - Activates between tasks. Reviews against plan, reports issues by severity. Critical issues block progress. + +7. **finishing-a-development-branch** - Activates when tasks complete. Verifies tests, presents options (merge/PR/keep/discard), cleans up worktree. +``` + +with: + +```markdown +6. **requesting-code-review** - Activates between tasks. Reviews against plan, reports issues by severity. Critical issues block progress. + +7. **sync-requirements** - Activates when tasks complete and durable requirements should be preserved. Merges specs, plans, commits, reports, and session-only user requirements into `docs/req//req.md`. + +8. **finishing-a-development-branch** - Activates when tasks complete. Verifies tests, offers requirement sync, presents options (merge/PR/keep/discard), cleans up worktree. +``` + +- [ ] **Step 4: Update the README skills list** + +In the `**Collaboration**` section of `README.md`, replace: + +```markdown +- **finishing-a-development-branch** - Merge/PR decision workflow +- **subagent-driven-development** - Fast iteration with two-stage review (spec compliance, then code quality) +``` + +with: + +```markdown +- **finishing-a-development-branch** - Merge/PR decision workflow +- **sync-requirements** - Durable requirements sync into `docs/req//req.md` +- **subagent-driven-development** - Fast iteration with two-stage review (spec compliance, then code quality) +``` + +- [ ] **Step 5: Run the focused test and verify it passes** + +Run: + +```bash +bash tests/claude-code/test-sync-requirements-skill.sh +``` + +Expected: + +```text +STATUS: PASSED +``` + +- [ ] **Step 6: Run the fast skill test runner for the new test** + +Run: + +```bash +bash tests/claude-code/run-skill-tests.sh --test test-sync-requirements-skill.sh +``` + +Expected: + +```text +Running: test-sync-requirements-skill.sh +[PASS] +STATUS: PASSED +``` + +- [ ] **Step 7: Commit Task 3** + +Run: + +```bash +git add tests/claude-code/test-sync-requirements-skill.sh README.md +git commit -m "docs: document requirements sync workflow" +``` + +## Task 4: Final Verification + +**Files:** +- Verify: `skills/sync-requirements/SKILL.md` +- Verify: `skills/finishing-a-development-branch/SKILL.md` +- Verify: `README.md` +- Verify: `tests/claude-code/test-sync-requirements-skill.sh` +- Verify: `tests/claude-code/run-skill-tests.sh` + +**Interfaces:** +- Consumes: all outputs from Tasks 1-3. +- Produces: verification evidence and final commit only if a fix is needed. + +- [ ] **Step 1: Run the focused static test** + +Run: + +```bash +bash tests/claude-code/test-sync-requirements-skill.sh +``` + +Expected: + +```text +STATUS: PASSED +``` + +- [ ] **Step 2: Run the fast skill test entry for the new test** + +Run: + +```bash +bash tests/claude-code/run-skill-tests.sh --test test-sync-requirements-skill.sh +``` + +Expected: + +```text +Running: test-sync-requirements-skill.sh +[PASS] +STATUS: PASSED +``` + +- [ ] **Step 3: Check for forbidden stale paths and missing syntax** + +Run: + +```bash +grep -R "docs/specs//spec.md" skills/sync-requirements skills/finishing-a-development-branch/SKILL.md README.md tests/claude-code/test-sync-requirements-skill.sh +``` + +Expected: command exits non-zero with no matches. + +Run: + +```bash +grep -R "SHALL NOT\|MUST NOT\|\*\*BUT\*\*" skills/sync-requirements/SKILL.md tests/claude-code/test-sync-requirements-skill.sh +``` + +Expected: command exits zero and prints matches from both files. + +- [ ] **Step 4: Inspect git diff** + +Run: + +```bash +git diff --stat +git diff -- skills/sync-requirements/SKILL.md skills/finishing-a-development-branch/SKILL.md README.md tests/claude-code/test-sync-requirements-skill.sh tests/claude-code/run-skill-tests.sh +``` + +Expected: + +```text +skills/sync-requirements/SKILL.md +skills/finishing-a-development-branch/SKILL.md +README.md +tests/claude-code/test-sync-requirements-skill.sh +tests/claude-code/run-skill-tests.sh +``` + +The diff should show no edits to `docs/superpowers/specs/` or `docs/superpowers/plans/` beyond the already committed design and this implementation plan. + +- [ ] **Step 5: Commit final verification fix only if needed** + +If Step 1-4 expose a missing wording or test assertion, fix it and run: + +```bash +git add skills/sync-requirements/SKILL.md skills/finishing-a-development-branch/SKILL.md README.md tests/claude-code/test-sync-requirements-skill.sh tests/claude-code/run-skill-tests.sh +git commit -m "fix: tighten requirements sync workflow checks" +``` + +Expected: only run this commit if there was a verification fix. If no fix was needed, do not create an empty commit. diff --git a/docs/superpowers/specs/2026-06-19-sync-requirements-design.md b/docs/superpowers/specs/2026-06-19-sync-requirements-design.md new file mode 100644 index 0000000000..409a23a768 --- /dev/null +++ b/docs/superpowers/specs/2026-06-19-sync-requirements-design.md @@ -0,0 +1,248 @@ +# Sync Requirements Design + +## Problem + +Superpowers currently treats brainstorming specs and writing-plans documents as +dated execution artifacts. They are useful while a task is being designed and +implemented, but once the work completes, the durable requirements learned during +the session are not folded into a long-lived module requirements document. This +makes it easy for future agents to miss decisions that were made during +implementation, especially when the user added requirements after the original +spec and plan were written. + +OpenSpec has a similar artifact lifecycle, but its sync workflow gives agents a +way to merge change-local specs into long-lived module requirements documents. +Superpowers should gain the same durable knowledge path without adopting +OpenSpec's CLI or directory layout wholesale. + +## Goals + +- Add a new Superpowers skill named `sync-requirements`. +- Store long-lived module requirements in `docs/req//req.md`. +- Keep existing brainstorming specs in `docs/superpowers/specs/` and writing + plans in `docs/superpowers/plans/` as dated historical artifacts. +- Prompt users to sync requirements after implementation tasks complete, before + branch finishing choices such as merge or PR. +- Include requirements that appeared in the session after the original spec and + plan, so user-requested scope changes are not lost. +- Make sync idempotent: running it twice should not duplicate requirements or + scenarios. + +## Non-Goals + +- Do not replace or rewrite dated design specs and implementation plans. +- Do not require the OpenSpec CLI or create an `openspec/` directory. +- Do not silently edit main requirements documents without user confirmation in + the finishing workflow. +- Do not archive old design specs or plans as part of this feature. +- Do not add third-party dependencies. + +## Architecture + +Add a focused skill at `skills/sync-requirements/SKILL.md`. The skill is the only +place that performs requirement discovery, module selection, intelligent merging, +and final reporting. + +Update `skills/finishing-a-development-branch/SKILL.md` so that, after tests +pass and before the merge/PR/keep/discard menu, it runs a requirement sync prompt. +That prompt should explain that the session may contain durable requirements not +captured in the original spec or plan and ask whether to run +`sync-requirements`. + +The finishing skill should stay lightweight. It should not inline the merge +algorithm; it only detects whether this work likely has syncable artifacts and +presents the choice. If the user chooses to sync, the agent invokes or follows +`sync-requirements`, then returns to the normal branch-finishing menu. + +## Main Requirements Document Format + +Main requirements documents live under module directories: + +```text +docs/req//req.md +``` + +Each req document uses a PRD-style requirements format, closer to a traditional +software requirements specification than an implementation design artifact: + +```markdown +# requirements-sync Requirements + +## Purpose +Captures how completed Superpowers work updates durable module requirements. + +## Requirements + +### Requirement: Requirement Sync Prompt +The system SHALL ask whether to sync durable requirements before finishing a +completed branch. + +#### Scenario: Completed implementation has syncable requirements +- **WHEN** implementation tasks are complete and verification has passed +- **THEN** the agent offers to sync requirements before presenting branch completion choices +- **BUT** the agent MUST NOT add transient command output to the requirements document +``` + +Module names should be stable, lowercase, and hyphen-separated. The sync skill +may infer a module from the work, but if multiple modules are plausible or the +work spans more than one module, it must ask the user rather than guessing. + +## Requirements Control Model + +OpenSpec does not rely on templates alone to control final spec output. Its +templates provide a starting shape, while schema instructions, conventions, +parsers, validators, and workflow skills together define what good output means. +Superpowers should copy that layered control model for requirements documents. + +The `sync-requirements` feature should therefore include: + +- A reusable authoring convention for `docs/req//req.md`, covering + Purpose, Requirements, SHALL/MUST and SHALL NOT/MUST NOT language, + `### Requirement:` headings, `#### Scenario:` headings, and scenario bullets + using **GIVEN** when useful, **WHEN**, **THEN**, **AND** for additional + conditions or outcomes, and **BUT** for prohibited behavior or negative + expectations. +- A skill workflow that tells the agent how to extract, classify, merge, and + report requirements. The example req skeleton is not enough. +- Static validation or tests that check structural invariants in the skill and + docs: the canonical path, requirement/scenario heading formats, normative + SHALL/MUST/SHALL NOT/MUST NOT language, and the instruction to consider + session-only user requirements. +- Finishing-flow integration that prompts for sync but delegates the actual + convention-aware merge to `sync-requirements`. + +This keeps the implementation from becoming a template-only generator. The +template-like example is documentation; the behavior is controlled by the skill +instructions and testable conventions. + +## `sync-requirements` Workflow + +### 1. Resolve Work Context + +The skill first identifies the current work. It should look for: + +- A referenced or recently created design spec under `docs/superpowers/specs/`. +- A referenced or recently created implementation plan under + `docs/superpowers/plans/`. +- Current branch commits, task reports, progress ledgers, and final summaries + when those are available in the session or workspace. +- User messages in the active session that changed requirements after the + original spec or plan. + +If the relevant design spec or plan cannot be inferred uniquely, the skill must +ask the user to choose from candidate files. It must not invent a context. + +### 2. Extract Durable Requirements + +The skill reads the available design spec and plan, then reviews the active +session for additional user requirements. It should extract durable product, +workflow, behavior, and constraint requirements. + +It should ignore temporary execution details such as transient test failures, +debugging dead ends, local command output, implementation accidents, and branch +management choices unless they changed the intended behavior. + +When user messages conflict with the original spec or plan, the later explicit +user message wins. The sync summary should mention that the newer requirement +superseded the older artifact. + +### 3. Select Target Modules + +The skill maps each durable requirement to one or more module requirements +documents under `docs/req//req.md`. + +If the target req document does not exist, the skill creates it with a clear +Purpose and Requirements section. If a requirement belongs in an existing module +requirements document, the skill reads that document before editing it. + +If the module boundary is unclear, the skill asks a single multiple-choice +question showing the plausible module names and their rationale. + +### 4. Merge Intelligently + +The skill applies requirements by intent rather than copying artifact text. + +- New durable behavior becomes a new `### Requirement`. +- Additional examples or edge cases become new `#### Scenario` entries under an + existing requirement. +- Changed behavior updates the existing requirement or scenario while preserving + unrelated content. +- Removed behavior is deleted only when the current work explicitly deprecated + it. +- Renames update headings while preserving existing scenarios that still apply. +- Scenario steps use **WHEN** and **THEN** at minimum, **GIVEN** only when an + initial state matters, **AND** for extra conditions or outcomes, and **BUT** + only for prohibited behavior, exceptions, or negative expectations. +- Normative requirement language includes **SHALL**, **MUST**, **SHALL NOT**, and + **MUST NOT**. Negative requirements should use SHALL NOT/MUST NOT rather than + weaker prose such as "should avoid" or "does not usually". + +The merge must be idempotent. If the target req document already states the same +requirement or scenario, the skill reports that it was already synchronized +instead of duplicating it. + +### 5. Report Results + +After syncing, the skill reports: + +- Which module requirements documents were created or modified. +- Which requirements or scenarios were added, modified, removed, or already in + sync. +- Which session-only user requirements were captured. +- Which candidate details were skipped as temporary or non-durable. + +## Finishing Workflow Integration + +`finishing-a-development-branch` gains a step after test verification and before +environment/base-branch detection: + +```text +Requirements may have changed during this session. Would you like to sync the +durable requirements into docs/req//req.md before finishing? + +1. Sync requirements now (recommended) +2. Skip sync and continue finishing +3. Cancel finishing + +Which option? +``` + +If the user chooses sync, the agent runs `sync-requirements` and then resumes the +existing finishing flow. If the user skips, the finishing flow continues +unchanged. If the user cancels, no merge/PR/cleanup option is presented. + +## Error Handling + +- If no design spec, plan, commits, or session requirements can be identified, + report that there is nothing reliable to sync and return to the caller. +- If a target module requirements document contains ambiguous or contradictory + existing requirements, ask the user before editing. +- If file writes fail, stop and report the exact path and failure. +- If the user declines sync, do not treat it as an error. + +## Testing + +This change is behavior-shaping skill content, so tests should focus on static +and workflow-level verification: + +- Verify `skills/sync-requirements/SKILL.md` exists with the expected name and + trigger description. +- Verify the skill documents `docs/req//req.md` as the main requirements + document path. +- Verify the skill requires session-added user requirements to be considered. +- Verify the skill defines requirement authoring conventions beyond a file + template, including SHALL/MUST/SHALL NOT/MUST NOT, requirement headings, + scenario headings, and GIVEN/WHEN/THEN/AND/BUT usage. +- Verify `finishing-a-development-branch` prompts for requirement sync before its + existing branch completion options. +- Verify README workflow documentation includes the new requirement sync step. + +No runtime OpenSpec dependency is required. + +## Open Questions Resolved + +- Main requirements document path: `docs/req//req.md`. +- New skill name: `sync-requirements`. +- Dated brainstorming specs and writing plans remain in their current locations. +- Session-only requirements are part of the sync input and should be summarized + explicitly. diff --git a/skills/finishing-a-development-branch/SKILL.md b/skills/finishing-a-development-branch/SKILL.md index 7f5337aaf9..0a2c652d79 100644 --- a/skills/finishing-a-development-branch/SKILL.md +++ b/skills/finishing-a-development-branch/SKILL.md @@ -9,7 +9,7 @@ description: Use when implementation is complete, all tests pass, and you need t Guide completion of development work by presenting clear options and handling chosen workflow. -**Core principle:** Verify tests → Detect environment → Present options → Execute choice → Clean up. +**Core principle:** Verify tests → Offer requirements sync → Detect environment → Present options → Execute choice → Clean up. **Announce at start:** "I'm using the finishing-a-development-branch skill to complete this work." @@ -35,7 +35,33 @@ Cannot proceed with merge/PR until tests pass. Stop. Don't proceed to Step 2. -**If tests pass:** Continue to Step 2. +**If tests pass:** Continue to Step 1.5. + +### Step 1.5: Requirement Sync Prompt + +Before finishing the branch, offer to sync durable requirements learned during +the session into `docs/req//req.md`. + +Present exactly these 3 options: + +``` +Requirements may have changed during this session. Would you like to sync the +durable requirements into docs/req//req.md before finishing? + +1. Sync requirements now (recommended) +2. Skip sync and continue finishing +3. Cancel finishing + +Which option? +``` + +**If user chooses 1:** Announce: "I'm using the sync-requirements skill to update durable requirements." Use `sync-requirements`, then return to Step 2. + +**If user chooses 2:** Continue to Step 2. + +**If user chooses 3:** Stop. Do not present merge, PR, keep, or discard options. + +**Do not inline the merge algorithm here.** This skill only prompts; `sync-requirements` owns context resolution, durable requirement extraction, module selection, merging, and reporting. ### Step 2: Detect Environment @@ -196,6 +222,10 @@ git worktree prune # Self-healing: clean up any stale registrations - **Problem:** Merge broken code, create failing PR - **Fix:** Always verify tests before offering options +**Skipping requirement sync prompt** +- **Problem:** Durable requirements learned during implementation disappear after branch completion +- **Fix:** Always offer Step 1.5 after tests pass and before branch finishing choices + **Open-ended questions** - **Problem:** "What should I do next?" is ambiguous - **Fix:** Present exactly 4 structured options (or 3 for detached HEAD) @@ -233,6 +263,7 @@ git worktree prune # Self-healing: clean up any stale registrations **Always:** - Verify tests before offering options +- Offer requirements sync after tests pass - Detect environment before presenting menu - Present exactly 4 options (or 3 for detached HEAD) - Get typed confirmation for Option 4 diff --git a/skills/sync-requirements/SKILL.md b/skills/sync-requirements/SKILL.md new file mode 100644 index 0000000000..56ed8ad7fa --- /dev/null +++ b/skills/sync-requirements/SKILL.md @@ -0,0 +1,159 @@ +--- +name: sync-requirements +description: Use when implementation work is complete or durable requirements need to be merged from specs, plans, commits, reports, or session discussion into long-lived requirements documents +--- + +# Sync Requirements + +## Overview + +Merge durable requirements learned during Superpowers-driven work into +PRD-style module requirements documents. + +**Core principle:** dated specs and plans are execution artifacts; durable +requirements belong in `docs/req//req.md`. + +**Announce at start:** "I'm using the sync-requirements skill to update durable requirements." + +## When to Use + +Use this skill when: + +- Implementation work is complete and requirements may need to be preserved. +- A user asks to merge a brainstorming spec or writing plan into long-lived requirements. +- A session included user-requested behavior changes after the original spec or plan. +- You need to update `docs/req//req.md` without archiving or rewriting dated artifacts. + +Do not use this skill for: + +- Temporary notes, command output, or debugging traces. +- Pure implementation details that belong in design docs, plans, or code comments. +- OpenSpec project state under `openspec/`; do not require the OpenSpec CLI. + +## Requirements Document Convention + +Main requirements documents live at: + +```text +docs/req//req.md +``` + +Use stable, lowercase, hyphen-separated module names. + +Each req document uses this structure: + +```markdown +# Requirements + +## Purpose +One short paragraph explaining what durable capability this module describes. + +## Requirements + +### Requirement: +The system SHALL describe one durable behavior, constraint, or user-visible rule. + +#### Scenario: +- **GIVEN** an initial state, when the state matters +- **WHEN** a condition, trigger, or user action occurs +- **THEN** an observable result is required +- **AND** an additional condition or outcome also applies +- **BUT** a prohibited behavior, exception, or negative expectation must hold +``` + +Requirement bodies use normative language: + +- Use **SHALL** or **MUST** for required behavior. +- Use **SHALL NOT** or **MUST NOT** for prohibited behavior. +- Do not use weak substitutes such as "should avoid" or "does not usually". +- Every requirement must have at least one `#### Scenario:` block. +- Scenario steps use **WHEN** and **THEN** at minimum. +- Use **GIVEN** only when an initial state matters. +- Use **AND** for additional conditions or outcomes. +- Use **BUT** only for prohibited behavior, exceptions, or negative expectations. + +## Workflow + +### 1. Resolve Work Context + +Identify the work to sync. Look for: + +- A referenced or recently created design spec under `docs/superpowers/specs/`. +- A referenced or recently created plan under `docs/superpowers/plans/`. +- Current branch commits, task reports, progress ledgers, and final summaries. +- Session-only user requirements added after the original spec or plan. + +If the relevant spec or plan cannot be inferred uniquely, ask the user to choose +from candidate files. Do not invent a context. + +### 2. Extract Durable Requirements + +Read the available design spec and plan, then review the active session for +additional user requirements. + +Extract durable product, workflow, behavior, and constraint requirements. + +Skip: + +- Transient test failures. +- Debugging dead ends. +- Local command output. +- Implementation accidents. +- Branch management choices. + +Keep a requirement from those skipped categories only when the user explicitly +changed the intended durable behavior. + +When a later user message conflicts with the original spec or plan, the later +explicit user message wins. Mention that replacement in the sync summary. + +### 3. Select Target Modules + +Map each durable requirement to one or more module req documents under +`docs/req//req.md`. + +If the target req document does not exist, create it with `# Requirements`, +`## Purpose`, and `## Requirements`. + +If the module boundary is unclear, ask one multiple-choice question showing the +plausible module names and why each is plausible. + +### 4. Merge Intelligently + +Apply requirements by intent rather than copying artifact text: + +- New durable behavior becomes a new `### Requirement`. +- Additional examples or edge cases become new `#### Scenario` entries under an existing requirement. +- Changed behavior updates the existing requirement or scenario while preserving unrelated content. +- Removed behavior is deleted only when the current work explicitly deprecated it. +- Renames update headings while preserving scenarios that still apply. + +The operation must be idempotent. If the target req document already states the +same requirement or scenario, report that it is already synchronized instead of +duplicating it. + +### 5. Report Results + +After syncing, report: + +- Which module requirements documents were created or modified. +- Which requirements or scenarios were added, modified, removed, or already in sync. +- Which session-only user requirements were captured. +- Which candidate details were skipped as temporary or non-durable. + +## Error Handling + +- If no design spec, plan, commits, or session requirements can be identified, + report that there is nothing reliable to sync and return to the caller. +- If a target module requirements document contains ambiguous or contradictory + existing requirements, ask the user before editing. +- If file writes fail, stop and report the exact path and failure. + +## Guardrails + +- Do not require the OpenSpec CLI. +- Do not create an `openspec/` directory. +- Do not archive or rewrite dated specs in `docs/superpowers/specs/`. +- Do not archive or rewrite dated plans in `docs/superpowers/plans/`. +- Do not silently edit requirements if module selection is ambiguous. +- Preserve existing req document content not mentioned by the current work. diff --git a/tests/claude-code/run-skill-tests.sh b/tests/claude-code/run-skill-tests.sh index c94cfec9e0..04fd46a3f9 100755 --- a/tests/claude-code/run-skill-tests.sh +++ b/tests/claude-code/run-skill-tests.sh @@ -74,6 +74,7 @@ done # List of skill tests to run (fast unit tests) tests=( "test-worktree-path-policy.sh" + "test-sync-requirements-skill.sh" "test-sdd-workspace.sh" "test-subagent-driven-development.sh" ) diff --git a/tests/claude-code/test-sync-requirements-skill.sh b/tests/claude-code/test-sync-requirements-skill.sh new file mode 100755 index 0000000000..ce951d59d4 --- /dev/null +++ b/tests/claude-code/test-sync-requirements-skill.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# Regression check: sync-requirements owns durable requirements sync. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +SYNC_SKILL="$REPO_ROOT/skills/sync-requirements/SKILL.md" +FINISHING_SKILL="$REPO_ROOT/skills/finishing-a-development-branch/SKILL.md" +README_FILE="$REPO_ROOT/README.md" + +failures=0 + +assert_file_exists() { + local file="$1" + local label="$2" + + if [ -f "$file" ]; then + echo " [PASS] $label" + else + echo " [FAIL] $label" + echo " Missing file: $file" + failures=$((failures + 1)) + fi +} + +assert_contains() { + local file="$1" + local pattern="$2" + local label="$3" + + if grep -Fq "$pattern" "$file"; then + echo " [PASS] $label" + else + echo " [FAIL] $label" + echo " Expected to find: $pattern" + echo " In file: $file" + failures=$((failures + 1)) + fi +} + +assert_order() { + local file="$1" + local first="$2" + local second="$3" + local label="$4" + local first_line + local second_line + + first_line=$(grep -Fn "$first" "$file" | head -1 | cut -d: -f1 || true) + second_line=$(grep -Fn "$second" "$file" | head -1 | cut -d: -f1 || true) + + if [ -n "$first_line" ] && [ -n "$second_line" ] && [ "$first_line" -lt "$second_line" ]; then + echo " [PASS] $label" + else + echo " [FAIL] $label" + echo " Expected '$first' before '$second'" + echo " In file: $file" + failures=$((failures + 1)) + fi +} + +echo "=== Sync Requirements Skill Test ===" +echo "" + +assert_file_exists "$SYNC_SKILL" "sync-requirements skill exists" + +if [ -f "$SYNC_SKILL" ]; then + assert_contains "$SYNC_SKILL" "name: sync-requirements" "skill frontmatter uses exact name" + assert_contains "$SYNC_SKILL" "description: Use when" "skill frontmatter has trigger description" + assert_contains "$SYNC_SKILL" 'docs/req//req.md' "skill documents canonical req path" + assert_contains "$SYNC_SKILL" 'docs/superpowers/specs/' "skill keeps dated brainstorming specs as inputs" + assert_contains "$SYNC_SKILL" 'docs/superpowers/plans/' "skill keeps dated writing plans as inputs" + assert_contains "$SYNC_SKILL" 'session-only user requirements' "skill considers session-only requirements" + assert_contains "$SYNC_SKILL" 'SHALL NOT' "skill supports SHALL NOT" + assert_contains "$SYNC_SKILL" 'MUST NOT' "skill supports MUST NOT" + assert_contains "$SYNC_SKILL" '**BUT**' "skill supports BUT scenario steps" + assert_contains "$SYNC_SKILL" 'prohibited behavior, exceptions, or negative expectations' "skill constrains BUT semantics" + assert_contains "$SYNC_SKILL" '### Requirement:' "skill documents requirement heading format" + assert_contains "$SYNC_SKILL" '#### Scenario:' "skill documents scenario heading format" + assert_contains "$SYNC_SKILL" 'idempotent' "skill requires idempotent sync" + assert_contains "$SYNC_SKILL" 'Do not require the OpenSpec CLI' "skill avoids OpenSpec runtime dependency" + assert_order "$SYNC_SKILL" 'Resolve Work Context' 'Extract Durable Requirements' "skill resolves context before extraction" + assert_order "$SYNC_SKILL" 'Extract Durable Requirements' 'Select Target Modules' "skill extracts before module selection" + assert_order "$SYNC_SKILL" 'Select Target Modules' 'Merge Intelligently' "skill selects modules before merge" +fi + +assert_contains "$FINISHING_SKILL" '### Step 1.5: Requirement Sync Prompt' "finishing skill has requirement sync step" +assert_contains "$FINISHING_SKILL" 'Sync requirements now (recommended)' "finishing prompt includes recommended sync option" +assert_contains "$FINISHING_SKILL" 'Skip sync and continue finishing' "finishing prompt includes skip option" +assert_contains "$FINISHING_SKILL" 'Cancel finishing' "finishing prompt includes cancel option" +assert_contains "$FINISHING_SKILL" 'sync-requirements' "finishing skill delegates to sync-requirements" +assert_contains "$FINISHING_SKILL" 'docs/req//req.md' "finishing prompt names req path" +assert_order "$FINISHING_SKILL" '**If tests pass:** Continue to Step 1.5.' '### Step 1.5: Requirement Sync Prompt' "finishing enters sync prompt after tests pass" +assert_order "$FINISHING_SKILL" '### Step 1.5: Requirement Sync Prompt' '### Step 2: Detect Environment' "sync prompt happens before environment detection" + +assert_contains "$README_FILE" '**sync-requirements**' "README lists sync-requirements" +assert_contains "$README_FILE" 'docs/req//req.md' "README documents req path" +assert_order "$README_FILE" '**requesting-code-review**' '**sync-requirements**' "README places sync before finishing in workflow" +assert_order "$README_FILE" '**sync-requirements**' '**finishing-a-development-branch**' "README places finishing after sync" + +echo "" + +if [ "$failures" -gt 0 ]; then + echo "STATUS: FAILED ($failures failures)" + exit 1 +fi + +echo "STATUS: PASSED"