Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions openspec/changes/opsx-archive-command/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-01-07
84 changes: 84 additions & 0 deletions openspec/changes/opsx-archive-command/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
## Context

The experimental workflow (OPSX) provides a complete lifecycle for creating changes:
- `/opsx:new` - Scaffold a new change with schema
- `/opsx:continue` - Create next artifact
- `/opsx:ff` - Fast-forward all artifacts
- `/opsx:apply` - Implement tasks
- `/opsx:sync` - Sync delta specs to main

The missing piece is archiving. The existing `openspec archive` command works but:
1. Applies specs programmatically (not agent-driven)
2. Doesn't use the artifact graph for completion checking
3. Doesn't integrate with the OPSX workflow philosophy

## Goals / Non-Goals

**Goals:**
- Add `/opsx:archive` skill to complete the OPSX workflow lifecycle
- Use artifact graph for schema-aware completion checking
- Integrate with `/opsx:sync` for agent-driven spec syncing
- Preserve `.openspec.yaml` schema metadata in archive

**Non-Goals:**
- Replacing the existing `openspec archive` CLI command
- Changing how specs are applied in the CLI command
- Modifying the artifact graph or schema system

## Decisions

### Decision 1: Skill-only implementation (no new CLI command)

The `/opsx:archive` will be a slash command/skill only, not a new CLI command.

**Rationale**: The existing `openspec archive` CLI command already handles the core archive functionality (moving to archive folder, date prefixing). The OPSX version just needs different pre-archive checks and optional sync prompting, which are agent behaviors better suited to a skill.

**Alternatives considered**:
- Adding flags to `openspec archive` (e.g., `--experimental`) - Rejected: adds complexity to CLI, harder to maintain two code paths
- New CLI command `openspec archive-experimental` - Rejected: unnecessary duplication, agent skills are the OPSX pattern

### Decision 2: Prompt for sync before archive

The skill will check for unsynced delta specs and prompt the user before archiving.

**Rationale**: The OPSX philosophy is agent-driven intelligent merging via `/opsx:sync`. Rather than programmatically applying specs like the regular archive command, we prompt the user to sync first if needed. This maintains workflow flexibility (user can decline and just archive).

**Flow**:
1. Check if `specs/` directory exists in the change
2. If yes, ask: "This change has delta specs. Would you like to sync them to main specs before archiving?"
3. If user says yes, execute `/opsx:sync` logic
4. Proceed with archive regardless of answer

### Decision 3: Use artifact graph for completion checking

The skill will use `openspec status --change "<name>" --json` to check artifact completion instead of just validating proposal.md and specs.

**Rationale**: The experimental workflow is schema-aware. Different schemas have different required artifacts. The artifact graph knows which artifacts are complete/incomplete for the current schema.

**Behavior**:
- Show warning if any artifacts are not `done`
- Don't block archive (user may have valid reasons to archive early)
- List incomplete artifacts so user can make informed decision

### Decision 4: Reuse tasks.md completion check from regular archive

The skill will parse tasks.md and warn about incomplete tasks, same as regular archive.

**Rationale**: Task completion checking is valuable regardless of workflow. The logic is simple (count `- [ ]` vs `- [x]`) and doesn't need special OPSX handling.

### Decision 5: Move change to archive/ with date prefix

Same archive behavior as regular command: move to `openspec/changes/archive/YYYY-MM-DD-<name>/`.

**Rationale**: Consistency with existing archive convention. The `.openspec.yaml` file moves with the change, preserving schema metadata.

## Risks / Trade-offs

**Risk**: Users confused about when to use `/opsx:archive` vs `openspec archive`
→ **Mitigation**: Documentation should clarify: use `/opsx:archive` if you've been using the OPSX workflow, use `openspec archive` otherwise. Both produce the same archived result.

**Risk**: Incomplete sync if user declines and has delta specs
→ **Mitigation**: The prompt is informational; user has full control. They may want to archive without syncing (e.g., abandoned change). Log a note in output.

**Trade-off**: No programmatic spec application in OPSX archive
→ **Accepted**: This is intentional. OPSX philosophy is agent-driven merging. If user wants programmatic application, use `openspec archive` instead.
28 changes: 28 additions & 0 deletions openspec/changes/opsx-archive-command/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Why

The experimental workflow (OPSX) provides a schema-driven, artifact-by-artifact approach to creating changes with `/opsx:new`, `/opsx:continue`, `/opsx:ff`, `/opsx:apply`, and `/opsx:sync`. However, there's no corresponding archive command to finalize and archive completed changes. Users must currently fall back to the regular `openspec archive` command, which doesn't integrate with the OPSX philosophy of agent-driven spec syncing and schema-aware artifact tracking.

## What Changes

- Add `/opsx:archive` slash command for archiving changes in the experimental workflow
- Use artifact graph to check completion status (schema-aware) instead of just validating proposal + specs
- Prompt for `/opsx:sync` before archiving instead of programmatically applying specs
- Preserve `.openspec.yaml` schema metadata when moving to archive
- Integrate with existing OPSX commands for a cohesive workflow

## Capabilities

### New Capabilities

- `opsx-archive-skill`: Slash command and skill for archiving completed changes in the experimental workflow. Checks artifact completion via artifact graph, verifies task completion, optionally syncs specs via `/opsx:sync`, and moves the change to `archive/YYYY-MM-DD-<name>/`.

### Modified Capabilities

(none - this is a new skill that doesn't modify existing specs)

## Impact

- New file: `.claude/commands/opsx/archive.md`
- New skill definition (generated via `openspec artifact-experimental-setup`)
- No changes to existing archive command or other OPSX commands
- Completes the OPSX command suite for full lifecycle management
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
## ADDED Requirements

### Requirement: OPSX Archive Skill

The system SHALL provide an `/opsx:archive` skill that archives completed changes in the experimental workflow.

#### Scenario: Archive a change with all artifacts complete

- **WHEN** agent executes `/opsx:archive` with a change name
- **AND** all artifacts in the schema are complete
- **AND** all tasks are complete
- **THEN** the agent moves the change to `openspec/changes/archive/YYYY-MM-DD-<name>/`
- **AND** displays success message with archived location

#### Scenario: Change selection prompt

- **WHEN** agent executes `/opsx:archive` without specifying a change
- **THEN** the agent prompts user to select from available changes
- **AND** shows only active changes (excludes archive/)

### Requirement: Artifact Completion Check

The skill SHALL check artifact completion status using the artifact graph before archiving.

#### Scenario: Incomplete artifacts warning

- **WHEN** agent checks artifact status
- **AND** one or more artifacts have status other than `done`
- **THEN** display warning listing incomplete artifacts
- **AND** prompt user for confirmation to continue
- **AND** proceed if user confirms

#### Scenario: All artifacts complete

- **WHEN** agent checks artifact status
- **AND** all artifacts have status `done`
- **THEN** proceed without warning

### Requirement: Task Completion Check

The skill SHALL check task completion status from tasks.md before archiving.

#### Scenario: Incomplete tasks found

- **WHEN** agent reads tasks.md
- **AND** incomplete tasks are found (marked with `- [ ]`)
- **THEN** display warning showing count of incomplete tasks
- **AND** prompt user for confirmation to continue
- **AND** proceed if user confirms

#### Scenario: All tasks complete

- **WHEN** agent reads tasks.md
- **AND** all tasks are complete (marked with `- [x]`)
- **THEN** proceed without task-related warning

#### Scenario: No tasks file

- **WHEN** tasks.md does not exist
- **THEN** proceed without task-related warning

### Requirement: Spec Sync Prompt

The skill SHALL prompt to sync delta specs before archiving if specs exist.

#### Scenario: Delta specs exist

- **WHEN** agent checks for delta specs
- **AND** `specs/` directory exists in the change with spec files
- **THEN** prompt user: "This change has delta specs. Would you like to sync them to main specs before archiving?"
- **AND** if user confirms, execute `/opsx:sync` logic
- **AND** proceed with archive regardless of sync choice

#### Scenario: No delta specs

- **WHEN** agent checks for delta specs
- **AND** no `specs/` directory or no spec files exist
- **THEN** proceed without sync prompt

### Requirement: Archive Process

The skill SHALL move the change to the archive folder with date prefix.

#### Scenario: Successful archive

- **WHEN** archiving a change
- **THEN** create `archive/` directory if it doesn't exist
- **AND** generate target name as `YYYY-MM-DD-<change-name>` using current date
- **AND** move entire change directory to archive location
- **AND** preserve `.openspec.yaml` file in archived change

#### Scenario: Archive already exists

- **WHEN** target archive directory already exists
- **THEN** fail with error message
- **AND** suggest renaming existing archive or using different date

### Requirement: Skill Output

The skill SHALL provide clear feedback about the archive operation.

#### Scenario: Archive complete with sync

- **WHEN** archive completes after syncing specs
- **THEN** display summary:
- Specs synced (from `/opsx:sync` output)
- Change archived to location
- Schema that was used

#### Scenario: Archive complete without sync

- **WHEN** archive completes without syncing specs
- **THEN** display summary:
- Note that specs were not synced (if applicable)
- Change archived to location
- Schema that was used

#### Scenario: Archive complete with warnings

- **WHEN** archive completes with incomplete artifacts or tasks
- **THEN** include note about what was incomplete
- **AND** suggest reviewing if archive was intentional
23 changes: 23 additions & 0 deletions openspec/changes/opsx-archive-command/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## 1. Create Slash Command

- [x] 1.1 Create `.claude/commands/opsx/archive.md` with skill definition
- [x] 1.2 Add YAML frontmatter (name, description, category, tags)
- [x] 1.3 Implement change selection logic (prompt if not provided)
- [x] 1.4 Implement artifact completion check using `openspec status --json`
- [x] 1.5 Implement task completion check (parse tasks.md for `- [ ]`)
- [x] 1.6 Implement spec sync prompt (check for specs/ directory, offer `/opsx:sync`)
- [x] 1.7 Implement archive process (move to archive/YYYY-MM-DD-<name>/)
- [x] 1.8 Add output formatting for success/warning cases

## 2. Regenerate Skills

- [x] 2.1 Run `openspec artifact-experimental-setup` to regenerate skills
- [x] 2.2 Verify skill appears in `.claude/skills/` directory

## 3. Testing

- [x] 3.1 Test `/opsx:archive` with a complete change (all artifacts, all tasks done)
- [x] 3.2 Test `/opsx:archive` with incomplete artifacts (verify warning shown)
- [x] 3.3 Test `/opsx:archive` with incomplete tasks (verify warning shown)
- [x] 3.4 Test `/opsx:archive` with delta specs (verify sync prompt shown)
- [x] 3.5 Test `/opsx:archive` without change name (verify selection prompt)
7 changes: 6 additions & 1 deletion src/commands/artifact-workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
type SchemaInfo,
} from '../core/artifact-graph/index.js';
import { createChange, validateChangeName } from '../utils/change-utils.js';
import { getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getSyncSpecsSkillTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate, getOpsxFfCommandTemplate, getOpsxSyncCommandTemplate } from '../core/templates/skill-templates.js';
import { getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getSyncSpecsSkillTemplate, getArchiveChangeSkillTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate, getOpsxFfCommandTemplate, getOpsxSyncCommandTemplate, getOpsxArchiveCommandTemplate } from '../core/templates/skill-templates.js';
import { FileSystemUtils } from '../utils/file-system.js';

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -798,13 +798,15 @@ async function artifactExperimentalSetupCommand(): Promise<void> {
const applyChangeSkill = getApplyChangeSkillTemplate();
const ffChangeSkill = getFfChangeSkillTemplate();
const syncSpecsSkill = getSyncSpecsSkillTemplate();
const archiveChangeSkill = getArchiveChangeSkillTemplate();

// Get command templates
const newCommand = getOpsxNewCommandTemplate();
const continueCommand = getOpsxContinueCommandTemplate();
const applyCommand = getOpsxApplyCommandTemplate();
const ffCommand = getOpsxFfCommandTemplate();
const syncCommand = getOpsxSyncCommandTemplate();
const archiveCommand = getOpsxArchiveCommandTemplate();

// Create skill directories and SKILL.md files
const skills = [
Expand All @@ -813,6 +815,7 @@ async function artifactExperimentalSetupCommand(): Promise<void> {
{ template: applyChangeSkill, dirName: 'openspec-apply-change' },
{ template: ffChangeSkill, dirName: 'openspec-ff-change' },
{ template: syncSpecsSkill, dirName: 'openspec-sync-specs' },
{ template: archiveChangeSkill, dirName: 'openspec-archive-change' },
];

const createdSkillFiles: string[] = [];
Expand Down Expand Up @@ -842,6 +845,7 @@ ${template.instructions}
{ template: applyCommand, fileName: 'apply.md' },
{ template: ffCommand, fileName: 'ff.md' },
{ template: syncCommand, fileName: 'sync.md' },
{ template: archiveCommand, fileName: 'archive.md' },
];

const createdCommandFiles: string[] = [];
Expand Down Expand Up @@ -899,6 +903,7 @@ ${template.content}
console.log(' • /opsx:apply - Implement tasks');
console.log(' • /opsx:ff - Fast-forward: create all artifacts at once');
console.log(' • /opsx:sync - Sync delta specs to main specs');
console.log(' • /opsx:archive - Archive a completed change');
console.log();
console.log(chalk.yellow('💡 This is an experimental feature.'));
console.log(' Feedback welcome at: https://github.com/Fission-AI/OpenSpec/issues');
Expand Down
Loading
Loading