diff --git a/src/core/templates/skill-templates.ts b/src/core/templates/skill-templates.ts index 598fcc4465..041c0331c7 100644 --- a/src/core/templates/skill-templates.ts +++ b/src/core/templates/skill-templates.ts @@ -9,7 +9,7 @@ export type { SkillTemplate, CommandTemplate } from './types.js'; export { getExploreSkillTemplate, getOpsxExploreCommandTemplate } from './workflows/explore.js'; export { getNewChangeSkillTemplate, getOpsxNewCommandTemplate } from './workflows/new-change.js'; export { getContinueChangeSkillTemplate, getOpsxContinueCommandTemplate } from './workflows/continue-change.js'; -export { getApplyChangeSkillTemplate, getOpsxApplyCommandTemplate } from './workflows/apply-change.js'; +export { getApplyInstructions, getApplyChangeSkillTemplate, getOpsxApplyCommandTemplate } from './workflows/apply-change.js'; export { getUpdateChangeSkillTemplate, getOpsxUpdateCommandTemplate } from './workflows/update-change.js'; export { getFfChangeSkillTemplate, getOpsxFfCommandTemplate } from './workflows/ff-change.js'; export { getSyncSpecsSkillTemplate, getOpsxSyncCommandTemplate } from './workflows/sync-specs.js'; diff --git a/src/core/templates/workflows/apply-change.ts b/src/core/templates/workflows/apply-change.ts index 393e83e237..931f6e7b68 100644 --- a/src/core/templates/workflows/apply-change.ts +++ b/src/core/templates/workflows/apply-change.ts @@ -7,11 +7,17 @@ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.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. +/** + * The apply workflow instructions, authored once and rendered by both the + * skill and command surfaces. The surfaces are intentionally distinct, but + * they differ only in how they are invoked — the generation transformers + * rewrite the canonical `/opsx:` tokens per surface downstream (see + * command-references.ts). The instruction text itself is shared, so the two + * cannot silently drift. Should a surface ever need genuinely different + * wording, add a parameter here and pass it from that surface's template. + */ +export function getApplyInstructions(): string { + return `Implement tasks from an OpenSpec change. ${STORE_SELECTION_GUIDANCE} @@ -183,7 +189,14 @@ 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`; +} + +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(), license: 'MIT', compatibility: 'Requires openspec CLI.', metadata: { author: 'openspec', version: '1.0' }, @@ -196,178 +209,6 @@ export function getOpsxApplyCommandTemplate(): CommandTemplate { description: 'Implement tasks from an OpenSpec change (Experimental)', category: 'Workflow', tags: ['workflow', 'artifacts', 'experimental'], - content: `Implement tasks from an OpenSpec change. - -${STORE_SELECTION_GUIDANCE} - -**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 ask the user to select one - - 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 - - Optional \`context\`: current required project instruction input from the selected root - - Optional \`operationGuidance\`: current advisory guidance for apply - - **Handle states:** - - If \`state: "blocked"\` (missing artifacts): show message, suggest using \`/opsx:continue\` (if it is not installed, run \`openspec status --change "" --json\` to see the next artifact and \`openspec instructions --change "" --json\` for how to create it) - - If \`state: "all_done"\`: congratulate, suggest archive - - Otherwise: proceed to implementation - - Treat \`context\` as a required prompt-level input. Read and consider it, and - apply relevant project facts, conventions, and constraints while implementing. - Treat \`operationGuidance\` as optional additive advice. Read and consider every - entry, and follow entries that are applicable and compatible with the built-in - workflow. - - Keep both fields separate from CLI-returned state, missing artifacts, tasks, - progress, \`contextFiles\`, and the built-in \`instruction\`. They are not - evidence of task completion, do not replace the built-in instruction, and do - not permit bypassing a blocked state. If context conflicts with the built-in - instruction, an explicit user choice, or a CLI-controlled value, report the - conflict and preserve the controlling value. If guidance is inapplicable or - conflicts with those controlling inputs, do not follow it and explain why. - These are prompt-level behavior contracts, not enforceable checks. - -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 - - Do not copy \`context\` or \`operationGuidance\` verbatim into implementation - files or planning artifacts unless the user separately asks for that content. - -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.