mirror of
https://github.com/Fission-AI/OpenSpec.git
synced 2026-10-10 01:12:33 +08:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e40abe1f20 | ||
|
|
e752b3200f | ||
|
|
a59284839b | ||
|
|
fa824fac95 | ||
|
|
7bc54b2cd3 |
@@ -0,0 +1,86 @@
|
||||
# Technical Design
|
||||
|
||||
## Architecture Decisions
|
||||
|
||||
### Simplicity First
|
||||
- No version tracking - always update when commanded
|
||||
- Full replacement for OpenSpec-managed files only (e.g., `openspec/README.md`)
|
||||
- Marker-based updates for user-owned files (e.g., `CLAUDE.md`)
|
||||
- Templates bundled with package - no network required
|
||||
- Minimal error handling - only check prerequisites
|
||||
|
||||
### Template Strategy
|
||||
- Use existing template utilities
|
||||
- `readmeTemplate` from `src/core/templates/readme-template.ts` for `openspec/README.md`
|
||||
- `TemplateManager.getClaudeTemplate()` for `CLAUDE.md`
|
||||
- Directory name is fixed to `openspec` (from `OPENSPEC_DIR_NAME`)
|
||||
|
||||
### File Operations
|
||||
- Use async utilities for consistency
|
||||
- `FileSystemUtils.writeFile` for `openspec/README.md`
|
||||
- `FileSystemUtils.updateFileWithMarkers` for `CLAUDE.md`
|
||||
- No atomic operations needed - users have git
|
||||
- Check directory existence before proceeding
|
||||
|
||||
## Implementation
|
||||
|
||||
### Update Command (`src/core/update.ts`)
|
||||
```typescript
|
||||
export class UpdateCommand {
|
||||
async execute(projectPath: string): Promise<void> {
|
||||
const openspecDirName = OPENSPEC_DIR_NAME;
|
||||
const openspecPath = path.join(projectPath, openspecDirName);
|
||||
|
||||
// 1. Check openspec directory exists
|
||||
if (!await FileSystemUtils.directoryExists(openspecPath)) {
|
||||
throw new Error(`No OpenSpec directory found. Run 'openspec init' first.`);
|
||||
}
|
||||
|
||||
// 2. Update README.md (full replacement)
|
||||
const readmePath = path.join(openspecPath, 'README.md');
|
||||
await FileSystemUtils.writeFile(readmePath, readmeTemplate);
|
||||
|
||||
// 3. Update CLAUDE.md (marker-based)
|
||||
const claudePath = path.join(projectPath, 'CLAUDE.md');
|
||||
const claudeContent = TemplateManager.getClaudeTemplate();
|
||||
await FileSystemUtils.updateFileWithMarkers(
|
||||
claudePath,
|
||||
claudeContent,
|
||||
OPENSPEC_MARKERS.start,
|
||||
OPENSPEC_MARKERS.end
|
||||
);
|
||||
|
||||
// 4. Success message (ASCII-safe, checkmark optional by terminal)
|
||||
console.log('Updated OpenSpec instructions');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Why This Approach
|
||||
|
||||
### Benefits
|
||||
- **Dead simple**: ~40 lines of code total
|
||||
- **Fast**: No version checks, minimal parsing
|
||||
- **Predictable**: Same result every time; idempotent
|
||||
- **Maintainable**: Reuses existing utilities
|
||||
|
||||
### Trade-offs Accepted
|
||||
- No version tracking (unnecessary complexity)
|
||||
- Full overwrite only for OpenSpec-managed files
|
||||
- Marker-managed updates for user-owned files
|
||||
|
||||
## Error Handling
|
||||
|
||||
Only handle critical errors:
|
||||
- Missing `openspec` directory → throw error handled by CLI to present a friendly message
|
||||
- File write failures → let errors bubble up to CLI
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
Manual smoke tests are sufficient initially:
|
||||
1. Run `openspec init` in a test project
|
||||
2. Modify both files (including custom content around markers in `CLAUDE.md`)
|
||||
3. Run `openspec update`
|
||||
4. Verify `openspec/README.md` fully replaced; `CLAUDE.md` OpenSpec block updated without altering user content outside markers
|
||||
5. Run the command twice to verify idempotency and no duplicate markers
|
||||
6. Test with missing `openspec` directory (expect failure)
|
||||
@@ -0,0 +1,29 @@
|
||||
# Add Update Command
|
||||
|
||||
## Why
|
||||
|
||||
Users need a way to update their local OpenSpec instructions (README.md and CLAUDE.md) when the OpenSpec package releases new versions with improved AI agent instructions or structural conventions.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add new `openspec update` CLI command that updates OpenSpec instructions
|
||||
- Replace `openspec/README.md` with the latest template
|
||||
- Safe because this file is fully OpenSpec-managed
|
||||
- Update only the OpenSpec-managed block in `CLAUDE.md` using markers
|
||||
- Preserve all user content outside markers
|
||||
- If `CLAUDE.md` is missing, create it with the managed block
|
||||
- Display success message after update (ASCII-safe): "Updated OpenSpec instructions"
|
||||
- A leading checkmark MAY be shown when the terminal supports it
|
||||
- Operation is idempotent (re-running yields identical results)
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected specs: `cli-update` (new capability)
|
||||
- Affected code:
|
||||
- `src/core/update.ts` (new command class, mirrors `InitCommand` placement)
|
||||
- `src/cli/index.ts` (register new command)
|
||||
- Uses existing templates via `TemplateManager` and `readmeTemplate`
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- No `.openspec/config.json` is introduced by this change. The default directory name `openspec` is used.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Update Command Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
As a developer using OpenSpec, I want to update the OpenSpec instructions in my project when new versions are released, so that I can benefit from improvements to AI agent instructions.
|
||||
|
||||
## Core Requirements
|
||||
|
||||
### Update Behavior
|
||||
|
||||
The update command SHALL update OpenSpec instruction files to the latest templates.
|
||||
|
||||
WHEN a user runs `openspec update` THEN the command SHALL:
|
||||
- Check if the `openspec` directory exists
|
||||
- Replace `openspec/README.md` with the latest template (complete replacement)
|
||||
- Update the OpenSpec-managed block in `CLAUDE.md` using markers
|
||||
- Preserve user content outside markers
|
||||
- Create `CLAUDE.md` if missing
|
||||
- Display ASCII-safe success message: "Updated OpenSpec instructions"
|
||||
|
||||
### Prerequisites
|
||||
|
||||
The command SHALL require:
|
||||
- An existing `openspec` directory (created by `openspec init`)
|
||||
|
||||
IF the `openspec` directory does not exist THEN:
|
||||
- Display error: "No OpenSpec directory found. Run 'openspec init' first."
|
||||
- Exit with code 1
|
||||
|
||||
### File Handling
|
||||
|
||||
The update command SHALL:
|
||||
- Completely replace `openspec/README.md` with the latest template
|
||||
- Update only the OpenSpec-managed block in `CLAUDE.md` using markers
|
||||
- Use the default directory name `openspec`
|
||||
- Be idempotent (repeated runs have no additional effect)
|
||||
|
||||
## Edge Cases
|
||||
|
||||
### File Permissions
|
||||
IF file write fails THEN let the error bubble up naturally with file path.
|
||||
|
||||
### Missing CLAUDE.md
|
||||
IF CLAUDE.md doesn't exist THEN create it with the template content.
|
||||
|
||||
### Custom Directory Name
|
||||
Not supported in this change. The default directory name `openspec` SHALL be used.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
Users SHALL be able to:
|
||||
- Update OpenSpec instructions with a single command
|
||||
- Get the latest AI agent instructions
|
||||
- See clear confirmation of the update
|
||||
|
||||
The update process SHALL be:
|
||||
- Simple and fast (no version checking)
|
||||
- Predictable (same result every time)
|
||||
- Self-contained (no network required)
|
||||
@@ -0,0 +1,20 @@
|
||||
# Implementation Tasks
|
||||
|
||||
## 1. Update Command Implementation
|
||||
- [ ] 1.1 Create `src/core/update.ts` with `UpdateCommand` class
|
||||
- [ ] 1.2 Check if `openspec` directory exists (use `FileSystemUtils.directoryExists`)
|
||||
- [ ] 1.3 Write `readmeTemplate` to `openspec/README.md` using `FileSystemUtils.writeFile`
|
||||
- [ ] 1.4 Update `CLAUDE.md` using markers via `FileSystemUtils.updateFileWithMarkers` and `TemplateManager.getClaudeTemplate()`
|
||||
- [ ] 1.5 Display ASCII-safe success message: `Updated OpenSpec instructions`
|
||||
|
||||
## 2. CLI Integration
|
||||
- [ ] 2.1 Register `update` command in `src/cli/index.ts`
|
||||
- [ ] 2.2 Add command description: `Update OpenSpec instruction files`
|
||||
- [ ] 2.3 Handle errors with `ora().fail(...)` and exit code 1 (missing `openspec` directory, file write errors)
|
||||
|
||||
## 3. Testing
|
||||
- [ ] 3.1 Verify `openspec/README.md` is fully replaced with latest template
|
||||
- [ ] 3.2 Verify `CLAUDE.md` OpenSpec block updates without altering user content outside markers
|
||||
- [ ] 3.3 Verify idempotency (running twice yields identical files, no duplicate markers)
|
||||
- [ ] 3.4 Verify error when `openspec` directory is missing with friendly message
|
||||
- [ ] 3.5 Verify success message displays properly in ASCII-only terminals
|
||||
@@ -0,0 +1,148 @@
|
||||
# CLI Init Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
The `openspec init` command SHALL create a complete OpenSpec directory structure in any project, enabling immediate adoption of OpenSpec conventions with support for multiple AI coding assistants.
|
||||
|
||||
## Behavior
|
||||
|
||||
### Progress Indicators
|
||||
|
||||
WHEN executing initialization steps
|
||||
THEN validate environment silently in background (no output unless error)
|
||||
AND display progress with ora spinners:
|
||||
- Show spinner: "⠋ Creating OpenSpec structure..."
|
||||
- Then success: "✔ OpenSpec structure created"
|
||||
- Show spinner: "⠋ Configuring AI tools..."
|
||||
- Then success: "✔ AI tools configured"
|
||||
|
||||
### Directory Creation
|
||||
|
||||
WHEN `openspec init` is executed
|
||||
THEN create the following directory structure:
|
||||
```
|
||||
openspec/
|
||||
├── project.md
|
||||
├── README.md
|
||||
├── specs/
|
||||
└── changes/
|
||||
└── archive/
|
||||
```
|
||||
|
||||
### File Generation
|
||||
|
||||
The command SHALL generate:
|
||||
- `README.md` containing complete OpenSpec instructions for AI assistants
|
||||
- `project.md` with project context template
|
||||
|
||||
### AI Tool Configuration
|
||||
|
||||
WHEN run interactively
|
||||
THEN prompt user to select AI tools to configure:
|
||||
- Claude Code (updates/creates CLAUDE.md with OpenSpec markers)
|
||||
- Cursor (future)
|
||||
- Aider (future)
|
||||
|
||||
### AI Tool Configuration Details
|
||||
|
||||
WHEN Claude Code is selected
|
||||
THEN create or update `CLAUDE.md` in the project root directory (not inside openspec/)
|
||||
|
||||
WHEN CLAUDE.md does not exist
|
||||
THEN create new file with OpenSpec content wrapped in markers:
|
||||
```markdown
|
||||
<!-- OPENSPEC:START -->
|
||||
# OpenSpec Project
|
||||
|
||||
This document provides instructions for AI coding assistants on how to use OpenSpec conventions for spec-driven development. Follow these rules precisely when working on OpenSpec-enabled projects.
|
||||
|
||||
This project uses OpenSpec for spec-driven development. Specifications are the source of truth.
|
||||
|
||||
See @openspec/README.md for detailed conventions and guidelines.
|
||||
<!-- OPENSPEC:END -->
|
||||
```
|
||||
|
||||
WHEN CLAUDE.md already exists
|
||||
THEN preserve all existing content
|
||||
AND insert OpenSpec content at the beginning of the file using markers
|
||||
AND ensure markers don't duplicate if they already exist
|
||||
|
||||
The marker system SHALL:
|
||||
- Use `<!-- OPENSPEC:START -->` to mark the beginning of managed content
|
||||
- Use `<!-- OPENSPEC:END -->` to mark the end of managed content
|
||||
- Allow OpenSpec to update its content without affecting user customizations
|
||||
- Preserve all content outside the markers intact
|
||||
|
||||
WHY use markers:
|
||||
- Users may have existing CLAUDE.md instructions they want to keep
|
||||
- OpenSpec can update its instructions in future versions
|
||||
- Clear boundary between OpenSpec-managed and user-managed content
|
||||
|
||||
### Interactive Mode
|
||||
|
||||
WHEN run
|
||||
THEN prompt user with: "Which AI tool do you use?"
|
||||
AND show single-select menu with available tools:
|
||||
- Claude Code
|
||||
AND show disabled options as "coming soon" (not selectable):
|
||||
- Cursor (coming soon)
|
||||
- Aider (coming soon)
|
||||
- Continue (coming soon)
|
||||
|
||||
User navigation:
|
||||
- Use arrow keys to move between options
|
||||
- Press Enter to select the highlighted option
|
||||
|
||||
### Safety Checks
|
||||
|
||||
WHEN `openspec/` directory already exists
|
||||
THEN display error with ora fail indicator:
|
||||
"✖ Error: OpenSpec seems to already be initialized. Use 'openspec update' to update the structure."
|
||||
|
||||
WHEN checking initialization feasibility
|
||||
THEN verify write permissions in the target directory silently
|
||||
AND only display error if permissions are insufficient
|
||||
|
||||
### Success Output
|
||||
|
||||
WHEN initialization completes successfully
|
||||
THEN display actionable prompts for AI-driven workflow:
|
||||
```
|
||||
✔ OpenSpec initialized successfully!
|
||||
|
||||
Next steps - Copy these prompts to Claude:
|
||||
|
||||
────────────────────────────────────────────────────────────
|
||||
1. Populate your project context:
|
||||
"Please read openspec/project.md and help me fill it out
|
||||
with details about my project, tech stack, and conventions"
|
||||
|
||||
2. Create your first change proposal:
|
||||
"I want to add [YOUR FEATURE HERE]. Please create an
|
||||
OpenSpec change proposal for this feature"
|
||||
|
||||
3. Learn the OpenSpec workflow:
|
||||
"Please explain the OpenSpec workflow from openspec/README.md
|
||||
and how I should work with you on this project"
|
||||
────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
The prompts SHALL:
|
||||
- Be copy-pasteable for immediate use with AI tools
|
||||
- Guide users through the AI-driven workflow
|
||||
- Replace placeholder text ([YOUR FEATURE HERE]) with actual features
|
||||
|
||||
### Exit Codes
|
||||
|
||||
- 0: Success
|
||||
- 1: General error (including when OpenSpec directory already exists)
|
||||
- 2: Insufficient permissions (reserved for future use)
|
||||
- 3: User cancelled operation (reserved for future use)
|
||||
|
||||
## Why
|
||||
|
||||
Manual creation of OpenSpec structure is error-prone and creates adoption friction. A standardized init command ensures:
|
||||
- Consistent structure across all projects
|
||||
- Proper AI instruction files are always included
|
||||
- Quick onboarding for new projects
|
||||
- Clear conventions from the start
|
||||
Reference in New Issue
Block a user