Skip to content

Commit cac5404

Browse files
authored
feat: add Agent Skills for experimental artifact workflow (#424)
* feat: add Agent Skills for experimental artifact workflow Implements Task #3 from the experimental release plan: - Create skill templates for openspec-new-change and openspec-continue-change - Add artifact-experimental-setup CLI command - Generate Agent Skills in .claude/skills/ directory - Support cross-editor compatibility (Claude Code, Cursor, Windsurf) Skills follow the Agent Skills specification and provide: - Natural language invocation by AI assistants - Step-by-step artifact creation workflow - Dependency-driven change management * fix: update GitHub issues URL to correct repository Replace placeholder `https://github.com/your-org/openspec/issues` with correct URL `https://github.com/Fission-AI/OpenSpec/issues` in: - docs/experimental-release-plan.md - src/commands/artifact-workflow.ts Verified against package.json repository.url field. * feat: add openspec-apply-change skill for task implementation Add the apply skill to guide agents through implementing tasks from an OpenSpec change: - Add `openspec instructions apply` CLI command that parses tasks.md and returns context files, progress tracking, and dynamic instructions - Add `getApplyChangeSkillTemplate()` to skill-templates.ts with full workflow guidance for implementing tasks - Update artifact-experimental-setup to generate all three skills: openspec-new-change, openspec-continue-change, openspec-apply-change The apply skill supports the fluid "actions on a change" model: - Can be invoked anytime (if tasks.md exists) - Handles blocked/ready/all_done states - Guides agents to pause on issues and suggest artifact updates - Tracks progress via task checkboxes * docs: mark apply skill implementation steps as complete * feat: add Capabilities section to proposal template Enrich the proposal template to explicitly capture capability discovery: - Add "Capabilities" section with "New Capabilities" and "Modified Capabilities" subsections to proposal template - Update proposal instruction in schema.yaml to guide agents on researching existing specs and listing capabilities - Update skill instructions with detailed guidance for the Capabilities section This creates a clear contract between proposal and specs phases - each capability listed in the proposal will need a corresponding spec file. * feat: remove redundant `openspec next` command The `next` command was redundant with `status` - both show which artifacts are ready to create. The status command provides more context (done/ready/blocked) and is the single source of truth for artifact state. Changes: - Remove nextCommand function and CLI registration from artifact-workflow.ts - Update skill templates to use status instead of next - Update docs and specs to reflect removal - Add REMOVED Requirements section to cli-artifact-workflow spec - Remove 7 tests for the next command Migration: Use `openspec status --change <id> --json` and filter artifacts with `status: "ready"` to find artifacts that can be created next. * docs: clarify kebab-case naming in proposal template Update HTML comments in the Capabilities section to explicitly instruct using kebab-case identifiers with examples (user-auth, data-export, api-rate-limiting). * feat: add change proposals for per-change schema metadata Add two related change proposals for enabling schema selection in the experimental artifact workflow: 1. add-per-change-schema-metadata: Store schema choice in .openspec.yaml per change, enabling auto-detection in workflow commands. Includes Zod schema design and delta specs for cli-artifact-workflow. 2. add-agent-schema-selection: Follow-up to update agent skills to support dynamic schema selection (depends on metadata change). Also includes: - Example .openspec.yaml in add-frontmatter-to-openspec-artifact-files - Clarify "Modified Capabilities" guidance in proposal template * remove test change * feat: fix design.md as optional, update docs, add schema-aware apply proposal Changes: - Fix generateApplyInstructions to treat design.md as optional (not required) - Update experimental-release-plan.md CLI output to match implementation - Add openspec-apply-change skill to docs (was missing) - Fix test flow numbering after adding apply skill verification step - Add change proposal for making apply instructions schema-aware The schema-aware proposal introduces an `implementation` block in schema.yaml to define when a change becomes implementable and how to track progress.
1 parent c47cdaa commit cac5404

File tree

16 files changed

+2137
-176
lines changed

16 files changed

+2137
-176
lines changed

docs/experimental-release-plan.md

Lines changed: 926 additions & 0 deletions
Large diffs are not rendered by default.

docs/schema-workflow-gaps.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,7 @@ openspec new change add-auth --schema tdd
210210
# Auto-reads schema from change.yaml — no --schema needed
211211
openspec status --change add-auth
212212
# Output: "Change: add-auth (schema: tdd)"
213-
214-
openspec next --change add-auth
215-
# Knows to use TDD artifacts
213+
# Shows which artifacts are ready/blocked/done
216214

217215
# Explicit override still works (with informational message)
218216
openspec status --change add-auth --schema spec-driven
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
## Why
2+
3+
With per-change schema metadata in place (see `add-per-change-schema-metadata`), agents can now create changes with different workflow schemas. However, the agent skills are still hardcoded to `spec-driven` artifacts and don't offer schema selection to users.
4+
5+
## What Changes
6+
7+
**Scope: Experimental artifact workflow agent skills**
8+
9+
**Depends on:** `add-per-change-schema-metadata` (must be implemented first)
10+
11+
- Update `openspec-new-change` skill to prompt user for schema selection
12+
- Update `openspec-continue-change` skill to work with any schema's artifacts
13+
- Update `openspec-apply-change` skill to handle schema-specific task structures
14+
- Add schema descriptions to help users choose appropriate workflow
15+
16+
## Capabilities
17+
18+
### Modified Capabilities
19+
- `cli-artifact-workflow`: Agent skills support dynamic schema selection
20+
21+
## Impact
22+
23+
- **Affected code**: `src/core/templates/skill-templates.ts`
24+
- **User experience**: Users can choose TDD, spec-driven, or future workflows when starting a change
25+
- **Agent behavior**: Skills read artifact list from schema rather than hardcoding
26+
- **Backward compatible**: Default remains `spec-driven` if user doesn't choose
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## Prerequisites
2+
3+
- [ ] 0.1 Implement `add-per-change-schema-metadata` change first
4+
5+
## 1. Schema Discovery
6+
7+
- [ ] 1.1 Add CLI command or helper to list schemas with descriptions (for agent use)
8+
- [ ] 1.2 Ensure `openspec templates --schema <name>` returns artifact list for any schema
9+
10+
## 2. Update New Change Skill
11+
12+
- [ ] 2.1 Add schema selection prompt using AskUserQuestion tool
13+
- [ ] 2.2 Present available schemas with descriptions (spec-driven, tdd, etc.)
14+
- [ ] 2.3 Pass selected schema to `openspec new change --schema <name>`
15+
- [ ] 2.4 Update output to show which schema/workflow was selected
16+
17+
## 3. Update Continue Change Skill
18+
19+
- [ ] 3.1 Remove hardcoded artifact references (proposal, specs, design, tasks)
20+
- [ ] 3.2 Read artifact list dynamically from `openspec status --json`
21+
- [ ] 3.3 Adjust artifact creation guidelines to be schema-agnostic
22+
- [ ] 3.4 Handle schema-specific artifact types (e.g., TDD's `tests` artifact)
23+
24+
## 4. Update Apply Change Skill
25+
26+
- [ ] 4.1 Make task detection work with different schema structures
27+
- [ ] 4.2 Adjust context file reading for schema-specific artifacts
28+
29+
## 5. Documentation
30+
31+
- [ ] 5.1 Add schema descriptions to help text or skill instructions
32+
- [ ] 5.2 Document when to use each schema (TDD for bug fixes, spec-driven for features, etc.)
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
## Context
2+
3+
The experimental artifact workflow supports multiple schemas (`spec-driven`, `tdd`), but schema selection must be passed on every command. This creates friction for agents and users.
4+
5+
We need a lightweight metadata file to persist the schema choice per change.
6+
7+
## Goals / Non-Goals
8+
9+
**Goals:**
10+
- Store schema choice once at change creation
11+
- Auto-detect schema in experimental workflow commands
12+
- Maintain backward compatibility (no metadata = default)
13+
- Validate metadata with Zod schema
14+
15+
**Non-Goals:**
16+
- Migrate existing changes (they use default)
17+
- Extend to legacy commands
18+
- Store additional metadata beyond schema (keep minimal for now)
19+
20+
## Decisions
21+
22+
### Decision: Zod Schema Design
23+
24+
The metadata file (`.openspec.yaml`) will be validated with this Zod schema:
25+
26+
```typescript
27+
// src/core/artifact-graph/types.ts (or new metadata.ts)
28+
29+
import { z } from 'zod';
30+
import { listSchemas } from './resolver.js';
31+
32+
/**
33+
* Schema for per-change metadata stored in .openspec.yaml
34+
*/
35+
export const ChangeMetadataSchema = z.object({
36+
// Required: which workflow schema this change uses
37+
schema: z.string().min(1, { message: 'schema is required' }).refine(
38+
(val) => listSchemas().includes(val),
39+
(val) => ({ message: `Unknown schema '${val}'. Available: ${listSchemas().join(', ')}` })
40+
),
41+
42+
// Optional: creation timestamp (ISO date string)
43+
created: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, {
44+
message: 'created must be YYYY-MM-DD format'
45+
}).optional(),
46+
});
47+
48+
export type ChangeMetadata = z.infer<typeof ChangeMetadataSchema>;
49+
```
50+
51+
**Rationale:**
52+
- `schema` is required and validated against available schemas at parse time
53+
- `created` is optional, ISO date format for consistency
54+
- Minimal fields - can extend later without breaking existing files
55+
- Follows existing codebase pattern (see `ArtifactSchema`, `SchemaYamlSchema`)
56+
57+
### Decision: File Location and Format
58+
59+
**Location:** `openspec/changes/<name>/.openspec.yaml`
60+
61+
**Format:**
62+
```yaml
63+
schema: tdd
64+
created: 2025-01-05
65+
```
66+
67+
**Alternatives considered:**
68+
- `change.yaml` - less hidden, but clutters directory
69+
- Frontmatter in `proposal.md` - couples to proposal existence
70+
- `openspec.json` - YAML matches existing schema files
71+
72+
### Decision: Read/Write Functions
73+
74+
```typescript
75+
// src/utils/change-metadata.ts
76+
77+
import * as fs from 'node:fs';
78+
import * as path from 'node:path';
79+
import * as yaml from 'yaml';
80+
import { ChangeMetadataSchema, type ChangeMetadata } from '../core/artifact-graph/types.js';
81+
82+
const METADATA_FILENAME = '.openspec.yaml';
83+
84+
export function writeChangeMetadata(
85+
changeDir: string,
86+
metadata: ChangeMetadata
87+
): void {
88+
// Validate before writing
89+
const validated = ChangeMetadataSchema.parse(metadata);
90+
const content = yaml.stringify(validated);
91+
fs.writeFileSync(path.join(changeDir, METADATA_FILENAME), content);
92+
}
93+
94+
export function readChangeMetadata(
95+
changeDir: string
96+
): ChangeMetadata | null {
97+
const metaPath = path.join(changeDir, METADATA_FILENAME);
98+
99+
if (!fs.existsSync(metaPath)) {
100+
return null;
101+
}
102+
103+
const content = fs.readFileSync(metaPath, 'utf-8');
104+
const parsed = yaml.parse(content);
105+
106+
// Validate and return (throws ZodError if invalid)
107+
return ChangeMetadataSchema.parse(parsed);
108+
}
109+
```
110+
111+
### Decision: Schema Resolution Order
112+
113+
When determining which schema to use:
114+
115+
1. **Explicit `--schema` flag** (highest priority - user override)
116+
2. **`.openspec.yaml` metadata** (persisted choice)
117+
3. **Default `spec-driven`** (fallback)
118+
119+
```typescript
120+
function resolveSchemaForChange(
121+
changeDir: string,
122+
explicitSchema?: string
123+
): string {
124+
if (explicitSchema) return explicitSchema;
125+
126+
const metadata = readChangeMetadata(changeDir);
127+
if (metadata?.schema) return metadata.schema;
128+
129+
return 'spec-driven';
130+
}
131+
```
132+
133+
## Risks / Trade-offs
134+
135+
- **Extra file per change** → Minimal overhead, hidden file
136+
- **YAML parsing dependency** → Already using `yaml` package for schema files
137+
- **Schema validation at read time** → Fail fast with clear error if corrupted
138+
139+
## Migration Plan
140+
141+
No migration needed:
142+
- Existing changes without `.openspec.yaml` continue to work (use default)
143+
- New changes created with `openspec new change --schema X` get metadata file
144+
145+
## Open Questions
146+
147+
- Should `openspec new change` prompt for schema interactively if not specified? (Leaning no - default is fine)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## Why
2+
3+
Currently, the schema (workflow type) must be passed via `--schema` flag on every experimental workflow command. This is repetitive and error-prone. Agents have no way to know which schema a change uses, so they default to `spec-driven` and cannot leverage alternative workflows like `tdd`.
4+
5+
## What Changes
6+
7+
**Scope: Experimental artifact workflow only** (`openspec new change`, `openspec status`, `openspec instructions`, `openspec templates`)
8+
9+
- Store schema choice in `.openspec.yaml` metadata file when creating a change via `openspec new change`
10+
- Auto-detect schema from metadata in experimental workflow commands
11+
- Make `--schema` flag optional (override only, metadata takes precedence)
12+
- Add `--schema` option to `openspec new change` command
13+
14+
**Not affected**: Legacy commands (`openspec validate`, `openspec archive`, `openspec list`, `openspec show`)
15+
16+
## Capabilities
17+
18+
### New Capabilities
19+
- `change-metadata`: Reading/writing per-change metadata files
20+
21+
### Modified Capabilities
22+
- `cli-artifact-workflow`: Commands auto-detect schema from change metadata
23+
24+
## Impact
25+
26+
- **Affected code**: `src/utils/change-utils.ts`, `src/core/artifact-graph/instruction-loader.ts`, `src/commands/artifact-workflow.ts`
27+
- **Agent skills**: Can be simplified - no longer need to pass schema explicitly
28+
- **Backward compatible**: Changes without `.openspec.yaml` fall back to `spec-driven` default
29+
- **Isolation**: All changes contained within experimental workflow code; legacy commands untouched
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
## ADDED Requirements
2+
3+
### Requirement: Change Metadata
4+
5+
The system SHALL store and validate per-change metadata in `.openspec.yaml` files using a Zod schema.
6+
7+
#### Scenario: Metadata file created with new change
8+
9+
- **WHEN** user runs `openspec new change add-feature --schema tdd`
10+
- **THEN** the system creates `.openspec.yaml` in the change directory
11+
- **AND** the file contains `schema: tdd` and `created: <YYYY-MM-DD>`
12+
13+
#### Scenario: Metadata validated on read
14+
15+
- **WHEN** the system reads `.openspec.yaml`
16+
- **AND** the `schema` field references an unknown schema
17+
- **THEN** the system displays a validation error listing available schemas
18+
19+
#### Scenario: Metadata schema validation
20+
21+
- **WHEN** `.openspec.yaml` contains invalid YAML or missing required fields
22+
- **THEN** the system displays a Zod validation error with details
23+
24+
#### Scenario: Missing metadata file
25+
26+
- **WHEN** a change directory has no `.openspec.yaml` file
27+
- **THEN** the system falls back to the default schema (`spec-driven`)
28+
29+
## MODIFIED Requirements
30+
31+
### Requirement: New Change Command
32+
33+
The system SHALL create new change directories with validation and optional schema metadata.
34+
35+
#### Scenario: Create valid change
36+
37+
- **WHEN** user runs `openspec new change add-feature`
38+
- **THEN** the system creates `openspec/changes/add-feature/` directory
39+
- **AND** creates `.openspec.yaml` with `schema: spec-driven` (default)
40+
41+
#### Scenario: Create change with schema
42+
43+
- **WHEN** user runs `openspec new change add-feature --schema tdd`
44+
- **THEN** the system creates `openspec/changes/add-feature/` directory
45+
- **AND** creates `.openspec.yaml` with `schema: tdd`
46+
47+
#### Scenario: Invalid schema on create
48+
49+
- **WHEN** user runs `openspec new change add-feature --schema unknown`
50+
- **THEN** the system displays an error listing available schemas
51+
- **AND** does not create the change directory
52+
53+
#### Scenario: Invalid change name
54+
55+
- **WHEN** user runs `openspec new change "Add Feature"` with invalid name
56+
- **THEN** the system displays validation error with guidance
57+
58+
#### Scenario: Duplicate change name
59+
60+
- **WHEN** user runs `openspec new change existing-change` for an existing change
61+
- **THEN** the system displays an error indicating the change already exists
62+
63+
#### Scenario: Create with description
64+
65+
- **WHEN** user runs `openspec new change add-feature --description "Add new feature"`
66+
- **THEN** the system creates the change directory with description in README.md
67+
68+
### Requirement: Schema Selection
69+
70+
The system SHALL support custom schema selection for workflow commands, with automatic detection from change metadata.
71+
72+
#### Scenario: Schema auto-detected from metadata
73+
74+
- **WHEN** user runs `openspec status --change <id>` without `--schema`
75+
- **AND** the change has `.openspec.yaml` with `schema: tdd`
76+
- **THEN** the system uses the `tdd` schema
77+
78+
#### Scenario: Explicit schema overrides metadata
79+
80+
- **WHEN** user runs `openspec status --change <id> --schema spec-driven`
81+
- **AND** the change has `.openspec.yaml` with `schema: tdd`
82+
- **THEN** the system uses `spec-driven` (explicit flag wins)
83+
84+
#### Scenario: Default schema fallback
85+
86+
- **WHEN** user runs workflow commands without `--schema`
87+
- **AND** the change has no `.openspec.yaml` file
88+
- **THEN** the system uses the "spec-driven" schema
89+
90+
#### Scenario: Custom schema via flag
91+
92+
- **WHEN** user runs `openspec status --change <id> --schema tdd`
93+
- **THEN** the system uses the specified schema for artifact graph
94+
95+
#### Scenario: Unknown schema
96+
97+
- **WHEN** user specifies an unknown schema
98+
- **THEN** the system displays an error listing available schemas
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## 1. Zod Schema and Types
2+
3+
- [ ] 1.1 Add `ChangeMetadataSchema` Zod schema to `src/core/artifact-graph/types.ts`
4+
- [ ] 1.2 Export `ChangeMetadata` type inferred from schema
5+
6+
## 2. Core Metadata Functions
7+
8+
- [ ] 2.1 Create `src/utils/change-metadata.ts` with `writeChangeMetadata()` function
9+
- [ ] 2.2 Add `readChangeMetadata()` function with Zod validation
10+
- [ ] 2.3 Update `createChange()` to accept optional `schema` param and write metadata
11+
12+
## 3. Auto-Detection in Instruction Loader
13+
14+
- [ ] 3.1 Modify `loadChangeContext()` to read schema from `.openspec.yaml`
15+
- [ ] 3.2 Make `schemaName` parameter optional (fall back to metadata, then default)
16+
17+
## 4. CLI Updates
18+
19+
- [ ] 4.1 Add `--schema <name>` option to `openspec new change` command
20+
- [ ] 4.2 Verify existing commands (`status`, `instructions`) work with auto-detection
21+
22+
## 5. Tests
23+
24+
- [ ] 5.1 Test `ChangeMetadataSchema` validates correctly (valid/invalid cases)
25+
- [ ] 5.2 Test `writeChangeMetadata()` creates valid YAML
26+
- [ ] 5.3 Test `readChangeMetadata()` parses and validates schema
27+
- [ ] 5.4 Test `loadChangeContext()` auto-detects schema from metadata
28+
- [ ] 5.5 Test fallback to default when no metadata exists
29+
- [ ] 5.6 Test `--schema` flag overrides metadata

0 commit comments

Comments
 (0)