From f4e1e39a25b4816a27f402fb895f24c3c7fdee25 Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Sun, 18 Jan 2026 18:08:10 -0800 Subject: [PATCH 1/4] opsx: infer change for apply --- docs/experimental-workflow.md | 2 +- src/core/templates/skill-templates.ts | 40 +++++++++++++++------------ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/docs/experimental-workflow.md b/docs/experimental-workflow.md index 98263b065d..78e6c95335 100644 --- a/docs/experimental-workflow.md +++ b/docs/experimental-workflow.md @@ -119,7 +119,7 @@ Creates all planning artifacts at once. Use when you have a clear picture of wha ``` /opsx:apply ``` -Works through tasks, checking them off as you go. **Key difference:** if you discover issues during implementation, you can update your specs, design, or tasks — then continue. No phase gates. +Works through tasks, checking them off as you go. **Key difference:** if you discover issues during implementation, you can update your specs, design, or tasks — then continue. No phase gates. If you're juggling multiple changes, you can run `/opsx:apply `; otherwise it should infer from the conversation (falling back to the most recently modified change). ### Finish up ``` diff --git a/src/core/templates/skill-templates.ts b/src/core/templates/skill-templates.ts index cd67b634eb..515cb8611e 100644 --- a/src/core/templates/skill-templates.ts +++ b/src/core/templates/skill-templates.ts @@ -499,19 +499,21 @@ export function getApplyChangeSkillTemplate(): SkillTemplate { 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, MUST prompt for available changes. +**Input**: Optionally specify a change name. If omitted, infer the intended change from the conversation; if still ambiguous, default to the most recently modified change (and clearly announce which change you're using). **Steps** -1. **If no change name provided, prompt for selection** +1. **Resolve the target change (infer → fallback)** - Run \`openspec list --json\` to get available changes. Use the **AskUserQuestion tool** to let the user select. + If the user already mentioned a change name in the conversation, use it (validate it exists via \`openspec list --json\` or \`openspec status --change "" --json\`). - Show changes that are implementation-ready (have tasks artifact). - Include the schema used for each change if available. - Mark changes with incomplete tasks as "(In Progress)". + If no change name is mentioned: + - Run \`openspec list --json\` to get active changes (sorted by most recently modified) + - Select the best default: + - Prefer the most recently modified change that is not blocked for apply (you can probe candidates with \`openspec instructions apply --change "" --json\`) + - If every change is blocked, use the most recently modified change anyway and explain what's missing and how to unblock it (usually \`/opsx:continue\`) - **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. + **IMPORTANT**: Do not silently pick a change. Always state: "Using change: " and how to override (e.g., \`/opsx:apply \` or "Use change "). 2. **Check status to understand the schema** \`\`\`bash @@ -1154,7 +1156,7 @@ export function getOpsxContinueCommandTemplate(): CommandTemplate { tags: ['workflow', 'artifacts', 'experimental'], content: `Continue working on a change by creating the next artifact. -**Input**: Optionally specify \`--change \` after \`/opsx:continue\`. If omitted, MUST prompt for available changes. +**Input**: Optionally specify a change name after \`/opsx:continue\` (e.g., \`/opsx:continue add-auth\`). If omitted, MUST prompt for available changes. **Steps** @@ -1269,19 +1271,21 @@ export function getOpsxApplyCommandTemplate(): CommandTemplate { tags: ['workflow', 'artifacts', 'experimental'], content: `Implement tasks from an OpenSpec change. -**Input**: Optionally specify \`--change \` after \`/opsx:apply\`. If omitted, MUST prompt for available changes. +**Input**: Optionally specify a change name after \`/opsx:apply\` (e.g., \`/opsx:apply add-auth\`). If omitted, infer the intended change from the conversation; if still ambiguous, default to the most recently modified change (and clearly announce which change you're using). **Steps** -1. **If no change name provided, prompt for selection** +1. **Resolve the target change (infer → fallback)** - Run \`openspec list --json\` to get available changes. Use the **AskUserQuestion tool** to let the user select. + If the user already mentioned a change name in the conversation, use it (validate it exists via \`openspec list --json\` or \`openspec status --change "" --json\`). - Show changes that are implementation-ready (have tasks artifact). - Include the schema used for each change if available. - Mark changes with incomplete tasks as "(In Progress)". + If no change name is mentioned: + - Run \`openspec list --json\` to get active changes (sorted by most recently modified) + - Select the best default: + - Prefer the most recently modified change that is not blocked for apply (you can probe candidates with \`openspec instructions apply --change "" --json\`) + - If every change is blocked, use the most recently modified change anyway and explain what's missing and how to unblock it (usually \`/opsx:continue\`) - **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose. + **IMPORTANT**: Do not silently pick a change. Always state: "Using change: " and how to override (e.g., \`/opsx:apply \` or "Use change "). 2. **Check status to understand the schema** \`\`\`bash @@ -1659,7 +1663,7 @@ export function getOpsxSyncCommandTemplate(): CommandTemplate { This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement). -**Input**: Optionally specify \`--change \` after \`/opsx:sync\`. If omitted, MUST prompt for available changes. +**Input**: Optionally specify a change name after \`/opsx:sync\` (e.g., \`/opsx:sync add-auth\`). If omitted, MUST prompt for available changes. **Steps** @@ -1964,7 +1968,7 @@ export function getOpsxArchiveCommandTemplate(): CommandTemplate { tags: ['workflow', 'archive', 'experimental'], content: `Archive a completed change in the experimental workflow. -**Input**: Optionally specify \`--change \` after \`/opsx:archive\`. If omitted, MUST prompt for available changes. +**Input**: Optionally specify a change name after \`/opsx:archive\` (e.g., \`/opsx:archive add-auth\`). If omitted, MUST prompt for available changes. **Steps** @@ -2144,7 +2148,7 @@ export function getOpsxVerifyCommandTemplate(): CommandTemplate { tags: ['workflow', 'verify', 'experimental'], content: `Verify that an implementation matches the change artifacts (specs, tasks, design). -**Input**: Optionally specify \`--change \` after \`/opsx:verify\`. If omitted, MUST prompt for available changes. +**Input**: Optionally specify a change name after \`/opsx:verify\` (e.g., \`/opsx:verify add-auth\`). If omitted, MUST prompt for available changes. **Steps** From a3ab03212313b99d393ffd4ac9d1e97fa44bd95a Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Sun, 18 Jan 2026 18:14:28 -0800 Subject: [PATCH 2/4] opsx: prompt when apply ambiguous --- docs/experimental-workflow.md | 2 +- src/core/templates/skill-templates.ts | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/experimental-workflow.md b/docs/experimental-workflow.md index 78e6c95335..538b2d1ac6 100644 --- a/docs/experimental-workflow.md +++ b/docs/experimental-workflow.md @@ -119,7 +119,7 @@ Creates all planning artifacts at once. Use when you have a clear picture of wha ``` /opsx:apply ``` -Works through tasks, checking them off as you go. **Key difference:** if you discover issues during implementation, you can update your specs, design, or tasks — then continue. No phase gates. If you're juggling multiple changes, you can run `/opsx:apply `; otherwise it should infer from the conversation (falling back to the most recently modified change). +Works through tasks, checking them off as you go. **Key difference:** if you discover issues during implementation, you can update your specs, design, or tasks — then continue. No phase gates. If you're juggling multiple changes, you can run `/opsx:apply `; otherwise it should infer from the conversation and prompt you to choose if it can’t tell. ### Finish up ``` diff --git a/src/core/templates/skill-templates.ts b/src/core/templates/skill-templates.ts index 515cb8611e..7cf58abac9 100644 --- a/src/core/templates/skill-templates.ts +++ b/src/core/templates/skill-templates.ts @@ -499,19 +499,20 @@ export function getApplyChangeSkillTemplate(): SkillTemplate { 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, infer the intended change from the conversation; if still ambiguous, default to the most recently modified change (and clearly announce which change you're using). +**Input**: Optionally specify a change name. If omitted, infer the intended change from the conversation; if ambiguous, prompt the user to choose (do not guess). **Steps** -1. **Resolve the target change (infer → fallback)** +1. **Resolve the target change (infer → prompt)** If the user already mentioned a change name in the conversation, use it (validate it exists via \`openspec list --json\` or \`openspec status --change "" --json\`). If no change name is mentioned: - - Run \`openspec list --json\` to get active changes (sorted by most recently modified) - - Select the best default: - - Prefer the most recently modified change that is not blocked for apply (you can probe candidates with \`openspec instructions apply --change "" --json\`) - - If every change is blocked, use the most recently modified change anyway and explain what's missing and how to unblock it (usually \`/opsx:continue\`) + - Run \`openspec list --json\` to get active changes + - If there is exactly ONE active change, use it + - Otherwise, prompt the user to choose which change to apply (do not guess) + - Present the top 3-4 most recently modified changes as options (include task progress if available) + - Mark the most recently modified as "(Recommended)" but still require user confirmation **IMPORTANT**: Do not silently pick a change. Always state: "Using change: " and how to override (e.g., \`/opsx:apply \` or "Use change "). @@ -1271,19 +1272,20 @@ export function getOpsxApplyCommandTemplate(): CommandTemplate { tags: ['workflow', 'artifacts', 'experimental'], content: `Implement tasks from an OpenSpec change. -**Input**: Optionally specify a change name after \`/opsx:apply\` (e.g., \`/opsx:apply add-auth\`). If omitted, infer the intended change from the conversation; if still ambiguous, default to the most recently modified change (and clearly announce which change you're using). +**Input**: Optionally specify a change name after \`/opsx:apply\` (e.g., \`/opsx:apply add-auth\`). If omitted, infer the intended change from the conversation; if ambiguous, prompt the user to choose (do not guess). **Steps** -1. **Resolve the target change (infer → fallback)** +1. **Resolve the target change (infer → prompt)** If the user already mentioned a change name in the conversation, use it (validate it exists via \`openspec list --json\` or \`openspec status --change "" --json\`). If no change name is mentioned: - - Run \`openspec list --json\` to get active changes (sorted by most recently modified) - - Select the best default: - - Prefer the most recently modified change that is not blocked for apply (you can probe candidates with \`openspec instructions apply --change "" --json\`) - - If every change is blocked, use the most recently modified change anyway and explain what's missing and how to unblock it (usually \`/opsx:continue\`) + - Run \`openspec list --json\` to get active changes + - If there is exactly ONE active change, use it + - Otherwise, prompt the user to choose which change to apply (do not guess) + - Present the top 3-4 most recently modified changes as options (include task progress if available) + - Mark the most recently modified as "(Recommended)" but still require user confirmation **IMPORTANT**: Do not silently pick a change. Always state: "Using change: " and how to override (e.g., \`/opsx:apply \` or "Use change "). From 028afd912d8bb551286a097da2e5b4fd1246861f Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Sun, 18 Jan 2026 19:07:31 -0800 Subject: [PATCH 3/4] opsx: use AskUserQuestion when ambiguous --- src/core/templates/skill-templates.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/templates/skill-templates.ts b/src/core/templates/skill-templates.ts index 7cf58abac9..94a468c3c0 100644 --- a/src/core/templates/skill-templates.ts +++ b/src/core/templates/skill-templates.ts @@ -510,7 +510,7 @@ export function getApplyChangeSkillTemplate(): SkillTemplate { If no change name is mentioned: - Run \`openspec list --json\` to get active changes - If there is exactly ONE active change, use it - - Otherwise, prompt the user to choose which change to apply (do not guess) + - Otherwise, prompt the user to choose which change to apply (do not guess). Use the **AskUserQuestion tool** to let the user select. - Present the top 3-4 most recently modified changes as options (include task progress if available) - Mark the most recently modified as "(Recommended)" but still require user confirmation @@ -1283,7 +1283,7 @@ export function getOpsxApplyCommandTemplate(): CommandTemplate { If no change name is mentioned: - Run \`openspec list --json\` to get active changes - If there is exactly ONE active change, use it - - Otherwise, prompt the user to choose which change to apply (do not guess) + - Otherwise, prompt the user to choose which change to apply (do not guess). Use the **AskUserQuestion tool** to let the user select. - Present the top 3-4 most recently modified changes as options (include task progress if available) - Mark the most recently modified as "(Recommended)" but still require user confirmation From e2b5142137f2c8143c89817e2fb6dc475506c34b Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Sun, 18 Jan 2026 19:23:13 -0800 Subject: [PATCH 4/4] Simplify opsx:apply change selection instructions Update all change selection instructions across all opsx commands (apply, continue, sync, archive, verify, ff) to use consistent wording: "If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes." For apply specifically, also simplifies Step 1 from ~180 to ~60 words while preserving the same behavior: infer from conversation, auto-select if single change, prompt via AskUserQuestion if ambiguous, always announce. Removes micromanagement details (validation commands, recommendation markers, presentation specifics) and trusts the LLM to figure out reasonable defaults. --- src/core/templates/skill-templates.ts | 52 ++++++++++++--------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/src/core/templates/skill-templates.ts b/src/core/templates/skill-templates.ts index 94a468c3c0..a54dee8f86 100644 --- a/src/core/templates/skill-templates.ts +++ b/src/core/templates/skill-templates.ts @@ -385,7 +385,7 @@ export function getContinueChangeSkillTemplate(): SkillTemplate { description: 'Continue working on an OpenSpec change by creating the next artifact. Use when the user wants to progress their change, create the next artifact, or continue their workflow.', instructions: `Continue working on a change by creating the next artifact. -**Input**: Optionally specify a change name. If omitted, MUST prompt for available changes. +**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. **Steps** @@ -499,22 +499,18 @@ export function getApplyChangeSkillTemplate(): SkillTemplate { 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, infer the intended change from the conversation; if ambiguous, prompt the user to choose (do not guess). +**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. **Steps** -1. **Resolve the target change (infer → prompt)** +1. **Select the change** - If the user already mentioned a change name in the conversation, use it (validate it exists via \`openspec list --json\` or \`openspec status --change "" --json\`). + 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 - If no change name is mentioned: - - Run \`openspec list --json\` to get active changes - - If there is exactly ONE active change, use it - - Otherwise, prompt the user to choose which change to apply (do not guess). Use the **AskUserQuestion tool** to let the user select. - - Present the top 3-4 most recently modified changes as options (include task progress if available) - - Mark the most recently modified as "(Recommended)" but still require user confirmation - - **IMPORTANT**: Do not silently pick a change. Always state: "Using change: " and how to override (e.g., \`/opsx:apply \` or "Use change "). + Always announce: "Using change: " and how to override (e.g., \`/opsx:apply \`). 2. **Check status to understand the schema** \`\`\`bash @@ -757,7 +753,7 @@ export function getSyncSpecsSkillTemplate(): SkillTemplate { This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement). -**Input**: Optionally specify a change name. If omitted, MUST prompt for available changes. +**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. **Steps** @@ -1157,7 +1153,7 @@ export function getOpsxContinueCommandTemplate(): CommandTemplate { tags: ['workflow', 'artifacts', 'experimental'], content: `Continue working on a change by creating the next artifact. -**Input**: Optionally specify a change name after \`/opsx:continue\` (e.g., \`/opsx:continue add-auth\`). If omitted, MUST prompt for available changes. +**Input**: Optionally specify a change name after \`/opsx:continue\` (e.g., \`/opsx:continue add-auth\`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. **Steps** @@ -1272,22 +1268,18 @@ export function getOpsxApplyCommandTemplate(): CommandTemplate { tags: ['workflow', 'artifacts', 'experimental'], content: `Implement tasks from an OpenSpec change. -**Input**: Optionally specify a change name after \`/opsx:apply\` (e.g., \`/opsx:apply add-auth\`). If omitted, infer the intended change from the conversation; if ambiguous, prompt the user to choose (do not guess). +**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. **Resolve the target change (infer → prompt)** - - If the user already mentioned a change name in the conversation, use it (validate it exists via \`openspec list --json\` or \`openspec status --change "" --json\`). +1. **Select the change** - If no change name is mentioned: - - Run \`openspec list --json\` to get active changes - - If there is exactly ONE active change, use it - - Otherwise, prompt the user to choose which change to apply (do not guess). Use the **AskUserQuestion tool** to let the user select. - - Present the top 3-4 most recently modified changes as options (include task progress if available) - - Mark the most recently modified as "(Recommended)" but still require user confirmation + 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 - **IMPORTANT**: Do not silently pick a change. Always state: "Using change: " and how to override (e.g., \`/opsx:apply \` or "Use change "). + Always announce: "Using change: " and how to override (e.g., \`/opsx:apply \`). 2. **Check status to understand the schema** \`\`\`bash @@ -1530,7 +1522,7 @@ export function getArchiveChangeSkillTemplate(): SkillTemplate { description: 'Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.', instructions: `Archive a completed change in the experimental workflow. -**Input**: Optionally specify a change name. If omitted, MUST prompt for available changes. +**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. **Steps** @@ -1665,7 +1657,7 @@ export function getOpsxSyncCommandTemplate(): CommandTemplate { This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement). -**Input**: Optionally specify a change name after \`/opsx:sync\` (e.g., \`/opsx:sync add-auth\`). If omitted, MUST prompt for available changes. +**Input**: Optionally specify a change name after \`/opsx:sync\` (e.g., \`/opsx:sync add-auth\`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. **Steps** @@ -1801,7 +1793,7 @@ export function getVerifyChangeSkillTemplate(): SkillTemplate { description: 'Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving.', instructions: `Verify that an implementation matches the change artifacts (specs, tasks, design). -**Input**: Optionally specify a change name. If omitted, MUST prompt for available changes. +**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. **Steps** @@ -1970,7 +1962,7 @@ export function getOpsxArchiveCommandTemplate(): CommandTemplate { tags: ['workflow', 'archive', 'experimental'], content: `Archive a completed change in the experimental workflow. -**Input**: Optionally specify a change name after \`/opsx:archive\` (e.g., \`/opsx:archive add-auth\`). If omitted, MUST prompt for available changes. +**Input**: Optionally specify a change name after \`/opsx:archive\` (e.g., \`/opsx:archive add-auth\`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. **Steps** @@ -2150,7 +2142,7 @@ export function getOpsxVerifyCommandTemplate(): CommandTemplate { tags: ['workflow', 'verify', 'experimental'], content: `Verify that an implementation matches the change artifacts (specs, tasks, design). -**Input**: Optionally specify a change name after \`/opsx:verify\` (e.g., \`/opsx:verify add-auth\`). If omitted, MUST prompt for available changes. +**Input**: Optionally specify a change name after \`/opsx:verify\` (e.g., \`/opsx:verify add-auth\`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes. **Steps**