diff --git a/src/core/templates/workflows/apply-change.ts b/src/core/templates/workflows/apply-change.ts index ec5b59ab1..fb96d9436 100644 --- a/src/core/templates/workflows/apply-change.ts +++ b/src/core/templates/workflows/apply-change.ts @@ -6,13 +6,33 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; -export function getApplyChangeSkillTemplate(): SkillTemplate { - return { - name: 'openspec-apply-change', - description: 'Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.', - instructions: `Implement tasks from an OpenSpec change. - -**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. +// ── Shared instruction body ─────────────────────────────────────────────────── +// Single source of truth for apply workflow instructions. +// Parameterized by mode so skill-friendly references and command-specific +// slash commands (/opsx:*) can differ without duplicating the entire body. +// See: https://github.com/Fission-AI/OpenSpec/issues/1139 +/** + * Returns the apply workflow instruction body for the given mode. + * Skill mode uses skill-friendly references (e.g. openspec-continue-change skill). + * Command mode uses slash command references (e.g. /opsx:continue, /opsx:archive). + */ +function getApplyInstructions(mode: 'skill' | 'command'): string { + const continueRef = mode === 'command' + ? '`/opsx:continue`' + : 'the openspec-continue-change skill'; + const archiveRef = mode === 'command' + ? 'You can archive this change with `/opsx:archive`.' + : 'Ready to archive this change.'; + const inputExample = mode === 'command' + ? ' (e.g., `/opsx:apply add-auth`)' + : ''; + const overrideExample = mode === 'command' + ? ' (e.g., `/opsx:apply `)' + : ''; + + return `Implement tasks from an OpenSpec change. + +**Input**: Optionally specify a change name${inputExample}. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. **Steps** @@ -23,7 +43,7 @@ export function getApplyChangeSkillTemplate(): SkillTemplate { - Auto-select if only one active change exists - If ambiguous, run \`openspec list --json\` to get available changes and use the **AskUserQuestion tool** to let the user select - Always announce: "Using change: " and how to override (e.g., \`/opsx:apply \`). + Always announce: "Using change: " and how to override${overrideExample}. 2. **Check status to understand the schema** \`\`\`bash @@ -47,7 +67,7 @@ export function getApplyChangeSkillTemplate(): SkillTemplate { - Dynamic instruction based on current state **Handle states:** - - If \`state: "blocked"\` (missing artifacts): show message, suggest using openspec-continue-change + - If \`state: "blocked"\` (missing artifacts): show message, suggest using ${continueRef} - If \`state: "all_done"\`: congratulate, suggest archive - Otherwise: proceed to implementation @@ -119,7 +139,7 @@ Working on task 4/7: - [x] Task 2 ... -All tasks complete! Ready to archive this change. +${archiveRef} \`\`\` **Output On Pause (Issue Encountered)** @@ -157,166 +177,34 @@ What would you like to do? This skill supports the "actions on a change" model: - **Can be invoked anytime**: Before all artifacts are done (if tasks exist), after partial implementation, interleaved with other actions -- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly`, +- **Allows artifact updates**: If implementation reveals design issues, suggest updating artifacts - not phase-locked, work fluidly`; +} + +/** + * Returns the skill template for the apply-change workflow. + * Used by skills-only tools (e.g. Antigravity) via SKILL.md discovery. + */ +export function getApplyChangeSkillTemplate(): SkillTemplate { + return { + name: 'openspec-apply-change', + description: 'Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.', + instructions: getApplyInstructions('skill'), license: 'MIT', compatibility: 'Requires openspec CLI.', metadata: { author: 'openspec', version: '1.0' }, }; } +/** + * Returns the command template for the opsx apply workflow. + * Used by Claude Code and other command-enabled tools via /opsx:apply. + */ export function getOpsxApplyCommandTemplate(): CommandTemplate { return { name: 'OPSX: Apply', description: 'Implement tasks from an OpenSpec change (Experimental)', category: 'Workflow', tags: ['workflow', 'artifacts', 'experimental'], - content: `Implement tasks from an OpenSpec change. - -**Input**: Optionally specify a change name (e.g., \`/opsx:apply add-auth\`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. - -**Steps** - -1. **Select the change** - - If a name is provided, use it. Otherwise: - - Infer from conversation context if the user mentioned a change - - Auto-select if only one active change exists - - If ambiguous, run \`openspec list --json\` to get available changes and use the **AskUserQuestion tool** to let the user select - - Always announce: "Using change: " and how to override (e.g., \`/opsx:apply \`). - -2. **Check status to understand the schema** - \`\`\`bash - openspec status --change "" --json - \`\`\` - Parse the JSON to understand: - - \`schemaName\`: The workflow being used (e.g., "spec-driven") - - \`planningHome\`, \`changeRoot\`, and \`actionContext\`: planning scope and edit constraints - - Which artifact contains the tasks (typically "tasks" for spec-driven, check status for others) - -3. **Get apply instructions** - - \`\`\`bash - openspec instructions apply --change "" --json - \`\`\` - - This returns: - - \`contextFiles\`: artifact ID -> array of concrete file paths (varies by schema) - - Progress (total, complete, remaining) - - Task list with status - - Dynamic instruction based on current state - - **Handle states:** - - If \`state: "blocked"\` (missing artifacts): show message, suggest using \`/opsx:continue\` - - If \`state: "all_done"\`: congratulate, suggest archive - - Otherwise: proceed to implementation - - **Workspace guard:** If status JSON reports \`actionContext.mode: "workspace-planning"\` and \`allowedEditRoots\` is empty, explain that full workspace apply is not supported in this slice. Treat linked repos and folders as read-only context, ask the user to select an affected area through an explicit implementation workflow, and STOP before editing files. - -4. **Read context files** - - Read every file path listed under \`contextFiles\` from the apply instructions output. - The files depend on the schema being used: - - **spec-driven**: proposal, specs, design, tasks - - Other schemas: follow the contextFiles from CLI output - -5. **Show current progress** - - Display: - - Schema being used - - Progress: "N/M tasks complete" - - Remaining tasks overview - - Dynamic instruction from CLI - -6. **Implement tasks (loop until done or blocked)** - - For each pending task: - - Show which task is being worked on - - Make the code changes required - - Keep changes minimal and focused - - Mark task complete in the tasks file: \`- [ ]\` → \`- [x]\` - - Continue to next task - - **Pause if:** - - Task is unclear → ask for clarification - - Implementation reveals a design issue → suggest updating artifacts - - Error or blocker encountered → report and wait for guidance - - User interrupts - -7. **On completion or pause, show status** - - Display: - - Tasks completed this session - - Overall progress: "N/M tasks complete" - - If all done: suggest archive - - If paused: explain why and wait for guidance - -**Output During Implementation** - -\`\`\` -## Implementing: (schema: ) - -Working on task 3/7: -[...implementation happening...] -✓ Task complete - -Working on task 4/7: -[...implementation happening...] -✓ Task complete -\`\`\` - -**Output On Completion** - -\`\`\` -## Implementation Complete - -**Change:** -**Schema:** -**Progress:** 7/7 tasks complete ✓ - -### Completed This Session -- [x] Task 1 -- [x] Task 2 -... - -All tasks complete! You can archive this change with \`/opsx:archive\`. -\`\`\` - -**Output On Pause (Issue Encountered)** - -\`\`\` -## Implementation Paused - -**Change:** -**Schema:** -**Progress:** 4/7 tasks complete - -### Issue Encountered - - -**Options:** -1.