diff --git a/package.json b/package.json index 89468c24..72a2c52d 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ "test:integration": "vitest run --config vitest.integration.config.ts", "test:integration:watch": "vitest --config vitest.integration.config.ts", "test:performance": "vitest run --config vitest.performance.config.mts", - "refresh-speckit": "node scripts/refresh-speckit.mjs" + "refresh-speckit": "node scripts/refresh-speckit.mjs", + "refresh-openspec": "node scripts/refresh-openspec.mjs" }, "build": { "npmRebuild": false, @@ -99,6 +100,10 @@ { "from": "src/prompts/speckit", "to": "prompts/speckit" + }, + { + "from": "src/prompts/openspec", + "to": "prompts/openspec" } ] }, @@ -127,6 +132,10 @@ { "from": "src/prompts/speckit", "to": "prompts/speckit" + }, + { + "from": "src/prompts/openspec", + "to": "prompts/openspec" } ] }, @@ -164,6 +173,10 @@ { "from": "src/prompts/speckit", "to": "prompts/speckit" + }, + { + "from": "src/prompts/openspec", + "to": "prompts/openspec" } ] }, diff --git a/scripts/refresh-openspec.mjs b/scripts/refresh-openspec.mjs new file mode 100644 index 00000000..2a3c9089 --- /dev/null +++ b/scripts/refresh-openspec.mjs @@ -0,0 +1,216 @@ +#!/usr/bin/env node +/** + * Refresh OpenSpec Prompts + * + * Fetches the latest OpenSpec prompts from GitHub by parsing AGENTS.md + * and extracts the three workflow stages (proposal, apply, archive). + * + * Unlike spec-kit which uses ZIP releases, OpenSpec bundles all workflow + * instructions in a single AGENTS.md file that we parse into sections. + * + * Usage: npm run refresh-openspec + */ + +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import https from 'https'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const OPENSPEC_DIR = path.join(__dirname, '..', 'src', 'prompts', 'openspec'); +const METADATA_PATH = path.join(OPENSPEC_DIR, 'metadata.json'); + +// GitHub OpenSpec repository info +const GITHUB_API = 'https://api.github.com'; +const REPO_OWNER = 'Fission-AI'; +const REPO_NAME = 'OpenSpec'; +const AGENTS_MD_URL = `https://raw.githubusercontent.com/${REPO_OWNER}/${REPO_NAME}/main/openspec/AGENTS.md`; + +// Commands to extract from AGENTS.md (we skip custom commands like 'help' and 'implement') +const UPSTREAM_COMMANDS = ['proposal', 'apply', 'archive']; + +// Section markers for parsing AGENTS.md +// Stage headers are formatted as: ### Stage N: Title +const SECTION_MARKERS = { + proposal: { + start: /^###\s*Stage\s*1[:\s]+Creating\s+Changes/i, + end: /^###\s*Stage\s*2[:\s]+/i, + }, + apply: { + start: /^###\s*Stage\s*2[:\s]+Implementing\s+Changes/i, + end: /^###\s*Stage\s*3[:\s]+/i, + }, + archive: { + start: /^###\s*Stage\s*3[:\s]+Archiving\s+Changes/i, + end: /^##[^#]/, // End at next level-2 heading or end of file + }, +}; + +/** + * Make an HTTPS GET request + */ +function httpsGet(url, options = {}) { + return new Promise((resolve, reject) => { + const headers = { + 'User-Agent': 'Maestro-OpenSpec-Refresher', + ...options.headers, + }; + + https.get(url, { headers }, (res) => { + // Handle redirects + if (res.statusCode === 301 || res.statusCode === 302) { + return resolve(httpsGet(res.headers.location, options)); + } + + if (res.statusCode !== 200) { + reject(new Error(`HTTP ${res.statusCode}: ${url}`)); + return; + } + + let data = ''; + res.on('data', chunk => data += chunk); + res.on('end', () => resolve({ data, headers: res.headers })); + res.on('error', reject); + }).on('error', reject); + }); +} + +/** + * Parse AGENTS.md and extract workflow sections as prompts + */ +function parseAgentsMd(content) { + const result = {}; + const lines = content.split('\n'); + + for (const [sectionId, markers] of Object.entries(SECTION_MARKERS)) { + let inSection = false; + let sectionLines = []; + + for (const line of lines) { + if (!inSection && markers.start.test(line)) { + inSection = true; + sectionLines.push(line); + continue; + } + + if (inSection) { + // Check if we've hit the end marker (next stage or next major section) + if (markers.end.test(line) && line.trim() !== '') { + // Don't include the end marker line, it belongs to the next section + break; + } + sectionLines.push(line); + } + } + + if (sectionLines.length > 0) { + // Clean up trailing empty lines + while (sectionLines.length > 0 && sectionLines[sectionLines.length - 1].trim() === '') { + sectionLines.pop(); + } + result[sectionId] = sectionLines.join('\n').trim(); + } + } + + return result; +} + +/** + * Get the latest commit SHA from the main branch + */ +async function getLatestCommitSha() { + try { + const url = `${GITHUB_API}/repos/${REPO_OWNER}/${REPO_NAME}/commits/main`; + const { data } = await httpsGet(url); + const commit = JSON.parse(data); + return commit.sha.substring(0, 7); + } catch (error) { + console.warn(' Warning: Could not fetch commit SHA, using "main"'); + return 'main'; + } +} + +/** + * Main refresh function + */ +async function refreshOpenSpec() { + console.log('šŸ”„ Refreshing OpenSpec prompts from GitHub...\n'); + + // Ensure openspec directory exists + if (!fs.existsSync(OPENSPEC_DIR)) { + console.error('āŒ OpenSpec directory not found:', OPENSPEC_DIR); + process.exit(1); + } + + try { + // Fetch AGENTS.md + console.log('šŸ“” Fetching AGENTS.md from OpenSpec repository...'); + const { data: agentsMdContent } = await httpsGet(AGENTS_MD_URL); + console.log(` Downloaded AGENTS.md (${agentsMdContent.length} bytes)`); + + // Parse sections + console.log('\nšŸ“¦ Parsing workflow sections...'); + const extractedPrompts = parseAgentsMd(agentsMdContent); + const extractedCount = Object.keys(extractedPrompts).length; + console.log(` Extracted ${extractedCount} sections from AGENTS.md`); + + if (extractedCount === 0) { + console.error('āŒ Failed to extract any sections from AGENTS.md'); + console.error(' Check that the section markers match the current format'); + process.exit(1); + } + + // Get commit SHA for version tracking + console.log('\nšŸ“‹ Getting version info...'); + const commitSha = await getLatestCommitSha(); + console.log(` Commit: ${commitSha}`); + + // Update prompt files + console.log('\nāœļø Updating prompt files...'); + let updatedCount = 0; + for (const commandName of UPSTREAM_COMMANDS) { + const content = extractedPrompts[commandName]; + if (!content) { + console.log(` ⚠ Missing: openspec.${commandName}.md (section not found)`); + continue; + } + + const promptFile = path.join(OPENSPEC_DIR, `openspec.${commandName}.md`); + const existingContent = fs.existsSync(promptFile) + ? fs.readFileSync(promptFile, 'utf8') + : ''; + + if (content !== existingContent) { + fs.writeFileSync(promptFile, content); + console.log(` āœ“ Updated: openspec.${commandName}.md`); + updatedCount++; + } else { + console.log(` - Unchanged: openspec.${commandName}.md`); + } + } + + // Update metadata + const metadata = { + lastRefreshed: new Date().toISOString(), + commitSha, + sourceVersion: '0.1.0', + sourceUrl: `https://github.com/${REPO_OWNER}/${REPO_NAME}`, + }; + + fs.writeFileSync(METADATA_PATH, JSON.stringify(metadata, null, 2)); + console.log('\nšŸ“„ Updated metadata.json'); + + // Summary + console.log('\nāœ… Refresh complete!'); + console.log(` Commit: ${commitSha}`); + console.log(` Updated: ${updatedCount} files`); + console.log(` Skipped: help, implement (custom Maestro prompts)`); + + } catch (error) { + console.error('\nāŒ Refresh failed:', error.message); + process.exit(1); + } +} + +// Run +refreshOpenSpec(); diff --git a/src/prompts/openspec/metadata.json b/src/prompts/openspec/metadata.json index fb37cd42..765495e7 100644 --- a/src/prompts/openspec/metadata.json +++ b/src/prompts/openspec/metadata.json @@ -1,6 +1,6 @@ { - "lastRefreshed": "2025-01-01T00:00:00Z", - "commitSha": "main", + "lastRefreshed": "2025-12-27T17:46:57.133Z", + "commitSha": "8dcd170", "sourceVersion": "0.1.0", "sourceUrl": "https://github.com/Fission-AI/OpenSpec" -} +} \ No newline at end of file diff --git a/src/prompts/openspec/openspec.apply.md b/src/prompts/openspec/openspec.apply.md index 011b3063..0a43fc8b 100644 --- a/src/prompts/openspec/openspec.apply.md +++ b/src/prompts/openspec/openspec.apply.md @@ -1,136 +1,9 @@ -# OpenSpec Apply - Stage 2: Implementing Changes - -You are helping the user implement an approved OpenSpec change proposal. This is Stage 2 of the OpenSpec workflow. - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). - -## Prerequisites - -**IMPORTANT: Do not start implementation until the proposal is reviewed and approved.** - -The approval gate ensures alignment between stakeholders before coding begins. If the proposal hasn't been approved yet, remind the user to get approval first. - -## Implementation Workflow - -### Step 1: Review the Proposal - -Read `proposal.md` to understand: -- **Why** - The problem or opportunity being addressed -- **What** - The specific changes being made -- **Impact** - Which specs, code, and systems are affected - -```bash -openspec show -``` - -### Step 2: Review Technical Decisions - -If `design.md` exists, review it for: -- Key architectural decisions -- Chosen approaches and trade-offs -- Migration plan (if applicable) -- Known risks to watch for - -### Step 3: Study the Tasks - -Read `tasks.md` for the implementation checklist: -- Tasks are numbered and ordered by dependency -- Each phase should be completed before moving to the next -- Tasks with `[P]` marker can run in parallel - -### Step 4: Execute Tasks Sequentially - -For each task in `tasks.md`: - -1. **Read the task description** carefully -2. **Implement the required changes** -3. **Verify the implementation** works as expected -4. **Test related functionality** to catch regressions -5. **Mark the task complete** by changing `- [ ]` to `- [x]` - -```markdown -# Before -- [ ] T001 Implement user authentication endpoint - -# After -- [x] T001 Implement user authentication endpoint -``` - -### Step 5: Confirm Completion - -Before marking the change as complete: - -1. **Verify every task** is checked (`- [x]`) -2. **Run validation** to ensure specs are consistent: - ```bash - openspec validate --strict - ``` -3. **Run project tests** to verify no regressions -4. **Review the spec deltas** match what was implemented - -## Implementation Guidelines - -### Following Task Order - -Tasks are dependency-ordered. Complete them in sequence unless marked with `[P]`: - -```markdown -- [x] T001 Setup database migration # Do first -- [x] T002 Create User model # Do second -- [x] T003 [P] Add unit tests # Can run parallel with T004 -- [x] T004 [P] Add integration tests # Can run parallel with T003 -- [x] T005 Update API documentation # Do after T003 & T004 -``` - -### Handling Blockers - -If you encounter a blocker: - -1. **Document the issue** in the task notes -2. **Ask clarifying questions** if requirements are unclear -3. **Update the proposal** if scope needs adjustment (requires re-approval) -4. **Don't skip tasks** - blockers should be resolved, not bypassed - -### Quality Checks - -For each task: - -- **Code quality** - Follow project conventions from `openspec/project.md` -- **Test coverage** - Add tests for new functionality -- **Documentation** - Update docs if behavior changes -- **Type safety** - Ensure type definitions are complete - -## Helpful Commands - -| Command | Purpose | -|---------|---------| -| `openspec show ` | Display full change details | -| `openspec validate --strict` | Validate change consistency | -| `openspec list` | View all active changes | -| `openspec diff ` | Show spec differences | - -## When Implementation is Complete - -Once all tasks are marked `[x]` and validation passes: - -1. **Commit your changes** with a descriptive message referencing the change-id -2. **Create a pull request** for review -3. **Wait for deployment** before proceeding to Stage 3 (Archive) - -```bash -git add . -git commit -m "feat: implement - " -``` - -## Key Principles - -- **Complete tasks in order** - Dependencies exist for a reason -- **Verify before marking done** - Each `[x]` represents tested, working code -- **Don't shortcut** - If something is unclear, ask rather than assume -- **Keep specs in sync** - Implemented behavior should match spec deltas +### Stage 2: Implementing Changes +Track these steps as TODOs and complete them one by one. +1. **Read proposal.md** - Understand what's being built +2. **Read design.md** (if exists) - Review technical decisions +3. **Read tasks.md** - Get implementation checklist +4. **Implement tasks sequentially** - Complete in order +5. **Confirm completion** - Ensure every item in `tasks.md` is finished before updating statuses +6. **Update checklist** - After all work is done, set every task to `- [x]` so the list reflects reality +7. **Approval gate** - Do not start implementation until the proposal is reviewed and approved \ No newline at end of file diff --git a/src/prompts/openspec/openspec.archive.md b/src/prompts/openspec/openspec.archive.md index 5de3eb24..760cd26f 100644 --- a/src/prompts/openspec/openspec.archive.md +++ b/src/prompts/openspec/openspec.archive.md @@ -1,162 +1,6 @@ -# OpenSpec Archive - Stage 3: Archiving Changes - -You are helping the user archive a completed OpenSpec change. This is Stage 3 of the OpenSpec workflow. - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). - -## Prerequisites - -**IMPORTANT: Archive only after deployment.** - -Stage 3 should be run after: -1. All tasks in `tasks.md` are marked complete (`- [x]`) -2. The code has been reviewed and merged -3. The changes have been deployed to production (or the target environment) - -## Archive Workflow - -### Step 1: Verify Completion - -Before archiving, confirm: - -```bash -# Check all tasks are complete -openspec show - -# Validate the change passes all checks -openspec validate --strict -``` - -### Step 2: Archive the Change - -Move the change directory to archive with a date prefix: - -```bash -openspec archive --yes -``` - -This command: -1. **Moves** `openspec/changes//` to `openspec/changes/archive/YYYY-MM-DD-/` -2. **Updates** `openspec/specs/` with any capability changes -3. **Validates** the archived change passes all checks - -### Step 3: Verify Archive Success - -After archiving: - -```bash -# Confirm change is no longer in active list -openspec list - -# Verify specs were updated correctly -openspec validate --strict -``` - -## Manual Archive Process - -If you need to archive manually (without the CLI): - -### 1. Create Archive Directory - -```bash -mkdir -p openspec/changes/archive/$(date +%Y-%m-%d)- -mv openspec/changes//* openspec/changes/archive/$(date +%Y-%m-%d)-/ -rmdir openspec/changes/ -``` - -### 2. Update Main Specs - -If the change modified existing specs, merge the deltas: - -1. **For ADDED requirements** - Copy to `openspec/specs//spec.md` -2. **For MODIFIED requirements** - Replace the original requirement with the modified version -3. **For REMOVED requirements** - Delete from `openspec/specs//spec.md` -4. **For RENAMED requirements** - Update the name in place - -### 3. Clean Up Spec Deltas - -The archived change should retain its spec deltas for historical reference, but the main `specs/` directory should now reflect the deployed state. - -## Archive Options - -```bash -# Standard archive (prompts for confirmation) -openspec archive - -# Skip confirmation prompt -openspec archive --yes -openspec archive -y - -# Skip spec updates (for tooling-only changes) -openspec archive --skip-specs -``` - -**Note:** Always pass the change-id explicitly. Don't rely on positional inference. - -## Validation After Archive - -Run comprehensive validation to confirm: - -```bash -openspec validate --strict -``` - -This validates: -- All archived changes pass validation -- Main specs are internally consistent -- No orphaned references exist - -## Common Issues - -### Spec Conflicts - -If archiving fails due to spec conflicts: - -1. **Review the conflict** - Check which requirements clash -2. **Resolve manually** - Edit `specs//spec.md` to resolve -3. **Re-run validation** - Ensure consistency after manual fixes -4. **Document resolution** - Note any manual interventions - -### Missing Archive Directory - -If the archive directory doesn't exist: - -```bash -mkdir -p openspec/changes/archive -``` - -### Partial Archive - -If archive was interrupted: - -1. **Check for duplicate files** in both `changes/` and `changes/archive/` -2. **Complete the move** manually if needed -3. **Run validation** to confirm state is correct - -## Post-Archive Checklist - -After successfully archiving: - -- [ ] Change is in `openspec/changes/archive/YYYY-MM-DD-/` -- [ ] Active change list (`openspec list`) no longer shows it -- [ ] Main specs reflect deployed state -- [ ] Validation passes (`openspec validate --strict`) -- [ ] Git commit includes the archive change - -```bash -git add . -git commit -m "chore: archive after deployment" -``` - -## Key Principles - -- **Archive promptly** - Don't let changes linger after deployment -- **Keep history** - Archived changes serve as documentation -- **Specs are truth** - After archiving, `specs/` represents deployed reality -- **Validate always** - Run validation before and after archiving +### Stage 3: Archiving Changes +After deployment, create separate PR to: +- Move `changes/[name]/` → `changes/archive/YYYY-MM-DD-[name]/` +- Update `specs/` if capabilities changed +- Use `openspec archive --skip-specs --yes` for tooling-only changes (always pass the change ID explicitly) +- Run `openspec validate --strict` to confirm the archived change passes checks \ No newline at end of file diff --git a/src/prompts/openspec/openspec.proposal.md b/src/prompts/openspec/openspec.proposal.md index 5726fcae..bd23c427 100644 --- a/src/prompts/openspec/openspec.proposal.md +++ b/src/prompts/openspec/openspec.proposal.md @@ -1,203 +1,31 @@ -# OpenSpec Proposal - Stage 1: Creating Changes - -You are helping the user create an OpenSpec change proposal. This is Stage 1 of the OpenSpec workflow. - -## User Input - -```text -$ARGUMENTS -``` - -You **MUST** consider the user input before proceeding (if not empty). - -## When to Create a Proposal - -Create a proposal when making substantial modifications: - -- Adding new features or functionality -- Implementing breaking changes (APIs, schemas) -- Changing architectural patterns -- Optimizing performance that affects behavior -- Updating security patterns - -**Skip proposal for:** bug fixes, typos, comments, non-breaking dependency updates, and configuration-only changes. - -## Stage 1 Workflow - -Follow these steps to create a complete change proposal: - -### Step 1: Review Existing Context - -Before creating a proposal: - -1. **Check `openspec/project.md`** for project conventions and context -2. **Run `openspec list`** to see active changes (avoid conflicts) -3. **Run `openspec list --specs`** to view existing capabilities -4. **Use `openspec show [spec]`** to review current specification state - -### Step 2: Choose a Unique Change-ID - -- Use **kebab-case** naming -- Use **verb-led** format: - - `add-` for new features - - `update-` for modifications - - `remove-` for deprecations - - `refactor-` for structural changes -- Ensure uniqueness (append `-2` or `-3` if needed) - -**Examples:** `add-user-authentication`, `update-api-v2-endpoints`, `remove-legacy-cache` - -### Step 3: Scaffold Directory Structure - -Create the following structure: - -``` -openspec/changes/[change-id]/ -ā”œā”€ā”€ proposal.md # What and why -ā”œā”€ā”€ tasks.md # Implementation checklist -ā”œā”€ā”€ design.md # Optional: technical decisions -└── specs/ # Spec deltas - └── [capability]/ - └── spec.md -``` - -### Step 4: Write proposal.md - -Create `proposal.md` with these sections: - -```markdown -# [Change Title] - -## Why - -1–2 sentences explaining the problem or opportunity this addresses. - -## What Changes - -- Bulleted list of modifications -- Mark breaking changes as **BREAKING** -- Be specific about affected components - -## Impact - -- List affected specs -- List affected code modules -- List affected external systems -``` - -### Step 5: Create Spec Deltas - -In `specs/[capability]/spec.md`, use operation headers: - -```markdown -## ADDED Requirements - -New, standalone capabilities that don't exist yet. - -### REQ-001: Requirement Title - -Description of the new requirement. - -#### Scenario: Success case -- **WHEN** specific conditions are met -- **THEN** expected outcome occurs - -## MODIFIED Requirements - -Changed behavior or scope of existing requirements. - -### REQ-002: Existing Requirement (Modified) - -Updated description reflecting new behavior. - -#### Scenario: Updated behavior -- **WHEN** new conditions apply -- **THEN** new outcome expected - -## REMOVED Requirements - -Deprecated features being removed. - -### REQ-003: Deprecated Feature - -**Reason:** Explain why this is being removed -**Migration:** Describe how users should migrate - -## RENAMED Requirements - -Name-only changes (no behavior change). - -### REQ-004: Old Name → New Name -``` - -**Critical Rules:** -- Include at least one `#### Scenario:` per requirement (use 4 hashtags) -- Use `**WHEN**` and `**THEN**` bullets within scenarios -- For MODIFIED requirements, copy the entire existing requirement block and edit it -- Header text must match exactly (whitespace-insensitive) when modifying - -### Step 6: Create tasks.md - -Create a structured implementation checklist: - -```markdown -# Implementation Tasks - -## Phase 1: Setup - -- [ ] T001 Initial setup task -- [ ] T002 Configuration task - -## Phase 2: Core Implementation - -- [ ] T003 Main feature implementation -- [ ] T004 Supporting functionality -- [ ] T005 Integration work - -## Phase 3: Testing & Documentation - -- [ ] T006 Add unit tests -- [ ] T007 Add integration tests -- [ ] T008 Update documentation -``` - -### Step 7: Optional - Create design.md - -Create `design.md` only when needed for: -- Cross-cutting changes affecting multiple systems -- New dependencies or external integrations -- Significant data model changes -- Security or performance complexity - -**design.md sections:** -- Context -- Goals / Non-Goals -- Key Decisions -- Risks & Trade-offs -- Migration Plan (if applicable) -- Open Questions - -### Step 8: Validate Before Sharing - -Always validate your proposal: - -```bash -openspec validate --strict -``` - -Fix all issues identified by validation. Use `openspec show --json --deltas-only` for debugging. - -## Key Principles - -- **Specs are truth** - The `specs/` directory reflects what is built -- **Changes are proposals** - The `changes/` directory contains planned modifications -- **Ask before ambiguity** - If the request is unclear, ask 1–2 clarifying questions before scaffolding - -## Helpful Commands - -| Command | Purpose | -|---------|---------| -| `openspec list` | View active changes | -| `openspec list --specs` | List existing capabilities | -| `openspec show [item]` | Display change or spec details | -| `openspec validate [item] --strict` | Comprehensive validation | +### Stage 1: Creating Changes +Create proposal when you need to: +- Add features or functionality +- Make breaking changes (API, schema) +- Change architecture or patterns +- Optimize performance (changes behavior) +- Update security patterns + +Triggers (examples): +- "Help me create a change proposal" +- "Help me plan a change" +- "Help me create a proposal" +- "I want to create a spec proposal" +- "I want to create a spec" + +Loose matching guidance: +- Contains one of: `proposal`, `change`, `spec` +- With one of: `create`, `plan`, `make`, `start`, `help` + +Skip proposal for: +- Bug fixes (restore intended behavior) +- Typos, formatting, comments +- Dependency updates (non-breaking) +- Configuration changes +- Tests for existing behavior + +**Workflow** +1. Review `openspec/project.md`, `openspec list`, and `openspec list --specs` to understand current context. +2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, optional `design.md`, and spec deltas under `openspec/changes//`. +3. Draft spec deltas using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement. +4. Run `openspec validate --strict` and resolve any issues before sharing the proposal. \ No newline at end of file