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
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, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate } from '../core/templates/skill-templates.js';
import { getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate, getOpsxFfCommandTemplate } from '../core/templates/skill-templates.js';
import { FileSystemUtils } from '../utils/file-system.js';

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -796,17 +796,20 @@ async function artifactExperimentalSetupCommand(): Promise<void> {
const newChangeSkill = getNewChangeSkillTemplate();
const continueChangeSkill = getContinueChangeSkillTemplate();
const applyChangeSkill = getApplyChangeSkillTemplate();
const ffChangeSkill = getFfChangeSkillTemplate();

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

// Create skill directories and SKILL.md files
const skills = [
{ template: newChangeSkill, dirName: 'openspec-new-change' },
{ template: continueChangeSkill, dirName: 'openspec-continue-change' },
{ template: applyChangeSkill, dirName: 'openspec-apply-change' },
{ template: ffChangeSkill, dirName: 'openspec-ff-change' },
];

const createdSkillFiles: string[] = [];
Expand Down Expand Up @@ -834,6 +837,7 @@ ${template.instructions}
{ template: newCommand, fileName: 'new.md' },
{ template: continueCommand, fileName: 'continue.md' },
{ template: applyCommand, fileName: 'apply.md' },
{ template: ffCommand, fileName: 'ff.md' },
];

const createdCommandFiles: string[] = [];
Expand Down Expand Up @@ -889,6 +893,7 @@ ${template.content}
console.log(' • /opsx:new - Start a new change');
console.log(' • /opsx:continue - Create the next artifact');
console.log(' • /opsx:apply - Implement tasks');
console.log(' • /opsx:ff - Fast-forward: create all artifacts at once');
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
7 changes: 7 additions & 0 deletions src/core/artifact-graph/instruction-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ export interface ChangeStatus {
schemaName: string;
/** Whether all artifacts are complete */
isComplete: boolean;
/** Artifact IDs required before apply phase (from schema's apply.requires) */
applyRequires: string[];
/** Status of each artifact */
artifacts: ArtifactStatus[];
}
Expand Down Expand Up @@ -252,6 +254,10 @@ function getUnlockedArtifacts(graph: ArtifactGraph, artifactId: string): string[
* @returns Formatted change status
*/
export function formatChangeStatus(context: ChangeContext): ChangeStatus {
// Load schema to get apply phase configuration
const schema = resolveSchema(context.schemaName);
const applyRequires = schema.apply?.requires ?? schema.artifacts.map(a => a.id);

const artifacts = context.graph.getAllArtifacts();
const ready = new Set(context.graph.getNextArtifacts(context.completed));
const blocked = context.graph.getBlocked(context.completed);
Expand Down Expand Up @@ -290,6 +296,7 @@ export function formatChangeStatus(context: ChangeContext): ChangeStatus {
changeName: context.changeName,
schemaName: context.schemaName,
isComplete: context.graph.isComplete(context.completed),
applyRequires,
artifacts: artifactStatuses,
};
}
192 changes: 192 additions & 0 deletions src/core/templates/skill-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,101 @@ This skill supports the "actions on a change" model:
};
}

/**
* Template for openspec-ff-change skill
* Fast-forward through artifact creation
*/
export function getFfChangeSkillTemplate(): SkillTemplate {
return {
name: 'openspec-ff-change',
description: 'Fast-forward through OpenSpec artifact creation. Use when the user wants to quickly create all artifacts needed for implementation without stepping through each one individually.',
instructions: `Fast-forward through artifact creation - generate everything needed to start implementation in one go.

**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.

**Steps**

1. **If no clear input provided, ask what they want to build**

Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:
> "What change do you want to work on? Describe what you want to build or fix."

From their description, derive a kebab-case name (e.g., "add user authentication" → \`add-user-auth\`).

**IMPORTANT**: Do NOT proceed without understanding what the user wants to build.

2. **Create the change directory**
\`\`\`bash
openspec new change "<name>"
\`\`\`
This creates a scaffolded change at \`openspec/changes/<name>/\`.

3. **Get the artifact build order**
\`\`\`bash
openspec status --change "<name>" --json
\`\`\`
Parse the JSON to get:
- \`applyRequires\`: array of artifact IDs needed before implementation (e.g., \`["tasks"]\`)
- \`artifacts\`: list of all artifacts with their status and dependencies

4. **Create artifacts in sequence until apply-ready**

Use the **TodoWrite tool** to track progress through the artifacts.

Loop through artifacts in dependency order (artifacts with no pending dependencies first):

a. **For each artifact that is \`ready\` (dependencies satisfied)**:
- Get instructions:
\`\`\`bash
openspec instructions <artifact-id> --change "<name>" --json
\`\`\`
- The instructions JSON includes:
- \`template\`: The template content to use
- \`instruction\`: Schema-specific guidance for this artifact type
- \`outputPath\`: Where to write the artifact
- \`dependencies\`: Completed artifacts to read for context
- Read any completed dependency files for context
- Create the artifact file following the schema's \`instruction\`
- Show brief progress: "✓ Created <artifact-id>"

b. **Continue until all \`applyRequires\` artifacts are complete**
- After creating each artifact, re-run \`openspec status --change "<name>" --json\`
- Check if every artifact ID in \`applyRequires\` has \`status: "done"\` in the artifacts array
- Stop when all \`applyRequires\` artifacts are done

c. **If an artifact requires user input** (unclear context):
- Use **AskUserQuestion tool** to clarify
- Then continue with creation

5. **Show final status**
\`\`\`bash
openspec status --change "<name>"
\`\`\`

**Output**

After completing all artifacts, summarize:
- Change name and location
- List of artifacts created with brief descriptions
- What's ready: "All artifacts created! Ready for implementation."
- Prompt: "Run \`/opsx:apply\` or ask me to implement to start working on the tasks."

**Artifact Creation Guidelines**

- Follow the \`instruction\` field from \`openspec instructions\` for each artifact type
- The schema defines what each artifact should contain - follow it
- Read dependency artifacts for context before creating new ones
- Use the \`template\` as a starting point, filling in based on context

**Guardrails**
- Create ALL artifacts needed for implementation (as defined by schema's \`apply.requires\`)
- Always read dependency artifacts before creating a new one
- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum
- If a change with that name already exists, suggest continuing that change instead
- Verify each artifact file exists after writing before proceeding to next`
};
}

// -----------------------------------------------------------------------------
// Slash Command Templates
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -719,3 +814,100 @@ This skill supports the "actions on a change" model:
- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly`
};
}


/**
* Template for /opsx:ff slash command
*/
export function getOpsxFfCommandTemplate(): CommandTemplate {
return {
name: 'OPSX: Fast Forward',
description: 'Create a change and generate all artifacts needed for implementation in one go',
category: 'Workflow',
tags: ['workflow', 'artifacts', 'experimental'],
content: `Fast-forward through artifact creation - generate everything needed to start implementation.

**Input**: The argument after \`/opsx:ff\` is the change name (kebab-case), OR a description of what the user wants to build.

**Steps**

1. **If no input provided, ask what they want to build**

Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:
> "What change do you want to work on? Describe what you want to build or fix."

From their description, derive a kebab-case name (e.g., "add user authentication" → \`add-user-auth\`).

**IMPORTANT**: Do NOT proceed without understanding what the user wants to build.

2. **Create the change directory**
\`\`\`bash
openspec new change "<name>"
\`\`\`
This creates a scaffolded change at \`openspec/changes/<name>/\`.

3. **Get the artifact build order**
\`\`\`bash
openspec status --change "<name>" --json
\`\`\`
Parse the JSON to get:
- \`applyRequires\`: array of artifact IDs needed before implementation (e.g., \`["tasks"]\`)
- \`artifacts\`: list of all artifacts with their status and dependencies

4. **Create artifacts in sequence until apply-ready**

Use the **TodoWrite tool** to track progress through the artifacts.

Loop through artifacts in dependency order (artifacts with no pending dependencies first):

a. **For each artifact that is \`ready\` (dependencies satisfied)**:
- Get instructions:
\`\`\`bash
openspec instructions <artifact-id> --change "<name>" --json
\`\`\`
- The instructions JSON includes:
- \`template\`: The template content to use
- \`instruction\`: Schema-specific guidance for this artifact type
- \`outputPath\`: Where to write the artifact
- \`dependencies\`: Completed artifacts to read for context
- Read any completed dependency files for context
- Create the artifact file following the schema's \`instruction\`
- Show brief progress: "✓ Created <artifact-id>"

b. **Continue until all \`applyRequires\` artifacts are complete**
- After creating each artifact, re-run \`openspec status --change "<name>" --json\`
- Check if every artifact ID in \`applyRequires\` has \`status: "done"\` in the artifacts array
- Stop when all \`applyRequires\` artifacts are done

c. **If an artifact requires user input** (unclear context):
- Use **AskUserQuestion tool** to clarify
- Then continue with creation

5. **Show final status**
\`\`\`bash
openspec status --change "<name>"
\`\`\`

**Output**

After completing all artifacts, summarize:
- Change name and location
- List of artifacts created with brief descriptions
- What's ready: "All artifacts created! Ready for implementation."
- Prompt: "Run \`/opsx:apply\` to start implementing."

**Artifact Creation Guidelines**

- Follow the \`instruction\` field from \`openspec instructions\` for each artifact type
- The schema defines what each artifact should contain - follow it
- Read dependency artifacts for context before creating new ones
- Use the \`template\` as a starting point, filling in based on context

**Guardrails**
- Create ALL artifacts needed for implementation (as defined by schema's \`apply.requires\`)
- Always read dependency artifacts before creating a new one
- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum
- If a change with that name already exists, ask if user wants to continue it or create a new one
- Verify each artifact file exists after writing before proceeding to next`
};
}
Loading