MAESTRO: feat(openspec): add GitHub refresh script and npm command

- Create scripts/refresh-openspec.mjs for build-time prompt updates
- Add refresh-openspec npm script to package.json
- Add extraResources for openspec prompts in all platform builds
- Update bundled prompts with latest from OpenSpec repository
This commit is contained in:
Pedram Amini
2025-12-27 11:48:01 -06:00
parent f014ae79eb
commit 282d87b0fb
6 changed files with 279 additions and 505 deletions

View File

@@ -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"
}
]
},

View File

@@ -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();

View File

@@ -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"
}

View File

@@ -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 <change-id>
```
### 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 <change-id> --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 <change-id>` | Display full change details |
| `openspec validate <change-id> --strict` | Validate change consistency |
| `openspec list` | View all active changes |
| `openspec diff <change-id>` | 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 <change-id> - <brief description>"
```
## 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

View File

@@ -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 <change-id>
# Validate the change passes all checks
openspec validate <change-id> --strict
```
### Step 2: Archive the Change
Move the change directory to archive with a date prefix:
```bash
openspec archive <change-id> --yes
```
This command:
1. **Moves** `openspec/changes/<change-id>/` to `openspec/changes/archive/YYYY-MM-DD-<change-id>/`
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)-<change-id>
mv openspec/changes/<change-id>/* openspec/changes/archive/$(date +%Y-%m-%d)-<change-id>/
rmdir openspec/changes/<change-id>
```
### 2. Update Main Specs
If the change modified existing specs, merge the deltas:
1. **For ADDED requirements** - Copy to `openspec/specs/<capability>/spec.md`
2. **For MODIFIED requirements** - Replace the original requirement with the modified version
3. **For REMOVED requirements** - Delete from `openspec/specs/<capability>/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 <change-id>
# Skip confirmation prompt
openspec archive <change-id> --yes
openspec archive <change-id> -y
# Skip spec updates (for tooling-only changes)
openspec archive <change-id> --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/<capability>/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-<change-id>/`
- [ ] 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 <change-id> 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 <change-id> --skip-specs --yes` for tooling-only changes (always pass the change ID explicitly)
- Run `openspec validate --strict` to confirm the archived change passes checks

View File

@@ -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
12 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 <change-id> --strict
```
Fix all issues identified by validation. Use `openspec show <change-id> --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 12 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/<id>/`.
3. Draft spec deltas using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement.
4. Run `openspec validate <id> --strict` and resolve any issues before sharing the proposal.