From 32709176c5f77b294cfa3b47127561ee01cb3536 Mon Sep 17 00:00:00 2001 From: Clay Good Date: Fri, 14 Aug 2026 16:03:36 -0500 Subject: [PATCH 1/2] fix(skills): scope activation to OpenSpec projects --- skills/openspec-apply-change/SKILL.md | 2 +- skills/openspec-archive-change/SKILL.md | 2 +- skills/openspec-bulk-archive-change/SKILL.md | 2 +- skills/openspec-continue-change/SKILL.md | 2 +- skills/openspec-explore/SKILL.md | 2 +- skills/openspec-ff-change/SKILL.md | 2 +- skills/openspec-new-change/SKILL.md | 2 +- skills/openspec-onboard/SKILL.md | 2 +- skills/openspec-propose/SKILL.md | 2 +- skills/openspec-sync-specs/SKILL.md | 2 +- skills/openspec-update-change/SKILL.md | 2 +- skills/openspec-verify-change/SKILL.md | 2 +- src/core/templates/workflows/apply-change.ts | 2 +- .../templates/workflows/archive-change.ts | 2 +- .../workflows/bulk-archive-change.ts | 2 +- .../templates/workflows/continue-change.ts | 2 +- src/core/templates/workflows/explore.ts | 2 +- src/core/templates/workflows/ff-change.ts | 2 +- src/core/templates/workflows/new-change.ts | 2 +- src/core/templates/workflows/onboard.ts | 2 +- src/core/templates/workflows/propose.ts | 2 +- src/core/templates/workflows/sync-specs.ts | 2 +- src/core/templates/workflows/update-change.ts | 2 +- src/core/templates/workflows/verify-change.ts | 2 +- .../templates/skill-templates-parity.test.ts | 56 +++++++++++-------- 25 files changed, 56 insertions(+), 48 deletions(-) diff --git a/skills/openspec-apply-change/SKILL.md b/skills/openspec-apply-change/SKILL.md index 098f63fecb..24219c56cb 100644 --- a/skills/openspec-apply-change/SKILL.md +++ b/skills/openspec-apply-change/SKILL.md @@ -1,6 +1,6 @@ --- 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. +description: Implement tasks from an OpenSpec change. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-archive-change/SKILL.md b/skills/openspec-archive-change/SKILL.md index 5f34ed53a7..e74c86296d 100644 --- a/skills/openspec-archive-change/SKILL.md +++ b/skills/openspec-archive-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-archive-change -description: Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete. +description: Archive a completed change in the experimental workflow. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-bulk-archive-change/SKILL.md b/skills/openspec-bulk-archive-change/SKILL.md index 252e1dd155..24c8874b21 100644 --- a/skills/openspec-bulk-archive-change/SKILL.md +++ b/skills/openspec-bulk-archive-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-bulk-archive-change -description: Archive multiple completed changes at once. Use when archiving several parallel changes. +description: Archive multiple completed changes at once. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-continue-change/SKILL.md b/skills/openspec-continue-change/SKILL.md index 5991b06891..86860f1087 100644 --- a/skills/openspec-continue-change/SKILL.md +++ b/skills/openspec-continue-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-continue-change -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. +description: Continue working on an OpenSpec change by creating the next artifact. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-explore/SKILL.md b/skills/openspec-explore/SKILL.md index 327c261489..43d7ff8f36 100644 --- a/skills/openspec-explore/SKILL.md +++ b/skills/openspec-explore/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-explore -description: Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change. +description: Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-ff-change/SKILL.md b/skills/openspec-ff-change/SKILL.md index c63aeee13b..bc536fac84 100644 --- a/skills/openspec-ff-change/SKILL.md +++ b/skills/openspec-ff-change/SKILL.md @@ -1,6 +1,6 @@ --- 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. +description: Fast-forward through OpenSpec artifact creation. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-new-change/SKILL.md b/skills/openspec-new-change/SKILL.md index 9aea11d391..3d4a592a93 100644 --- a/skills/openspec-new-change/SKILL.md +++ b/skills/openspec-new-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-new-change -description: Start a new OpenSpec change using the experimental artifact workflow. Use when the user wants to create a new feature, fix, or modification with a structured step-by-step approach. +description: Start a new OpenSpec change using the experimental artifact workflow. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-onboard/SKILL.md b/skills/openspec-onboard/SKILL.md index 5619596ea1..016252e0cb 100644 --- a/skills/openspec-onboard/SKILL.md +++ b/skills/openspec-onboard/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-onboard -description: Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work. +description: Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-propose/SKILL.md b/skills/openspec-propose/SKILL.md index ccf7b22334..64487cd95b 100644 --- a/skills/openspec-propose/SKILL.md +++ b/skills/openspec-propose/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-propose -description: Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation. +description: Propose a new change with all artifacts generated in one step. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-sync-specs/SKILL.md b/skills/openspec-sync-specs/SKILL.md index d12d56b857..5cdd06317a 100644 --- a/skills/openspec-sync-specs/SKILL.md +++ b/skills/openspec-sync-specs/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-sync-specs -description: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change. +description: Sync delta specs from a change to main specs. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-update-change/SKILL.md b/skills/openspec-update-change/SKILL.md index 24c9f88367..2f2db68441 100644 --- a/skills/openspec-update-change/SKILL.md +++ b/skills/openspec-update-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-update-change -description: Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use when the user wants to revise a change's plan, fold new decisions into it, or reconcile its artifacts after an edit. Never edits code. +description: Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. Never edits code. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/skills/openspec-verify-change/SKILL.md b/skills/openspec-verify-change/SKILL.md index 2165a6a910..262d898a40 100644 --- a/skills/openspec-verify-change/SKILL.md +++ b/skills/openspec-verify-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-verify-change -description: Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving. +description: Verify implementation matches change artifacts. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. diff --git a/src/core/templates/workflows/apply-change.ts b/src/core/templates/workflows/apply-change.ts index d7ebe2f4eb..eed7370f33 100644 --- a/src/core/templates/workflows/apply-change.ts +++ b/src/core/templates/workflows/apply-change.ts @@ -198,7 +198,7 @@ This skill supports the "actions on a change" model: 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.', + description: 'Implement tasks from an OpenSpec change. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: getApplyInstructions(), license: 'MIT', compatibility: 'Requires openspec CLI.', diff --git a/src/core/templates/workflows/archive-change.ts b/src/core/templates/workflows/archive-change.ts index 2dae74d436..26cac00145 100644 --- a/src/core/templates/workflows/archive-change.ts +++ b/src/core/templates/workflows/archive-change.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getArchiveChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-archive-change', - description: 'Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.', + description: 'Archive a completed change in the experimental workflow. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: `Archive a completed change in the experimental workflow. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/bulk-archive-change.ts b/src/core/templates/workflows/bulk-archive-change.ts index cacede2543..cff97f30b0 100644 --- a/src/core/templates/workflows/bulk-archive-change.ts +++ b/src/core/templates/workflows/bulk-archive-change.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getBulkArchiveChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-bulk-archive-change', - description: 'Archive multiple completed changes at once. Use when archiving several parallel changes.', + description: 'Archive multiple completed changes at once. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: `Archive multiple completed changes in a single operation. This skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented. diff --git a/src/core/templates/workflows/continue-change.ts b/src/core/templates/workflows/continue-change.ts index 14b3109e43..b99ae7c857 100644 --- a/src/core/templates/workflows/continue-change.ts +++ b/src/core/templates/workflows/continue-change.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getContinueChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-continue-change', - 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.', + description: 'Continue working on an OpenSpec change by creating the next artifact. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: `Continue working on a change by creating the next artifact. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/explore.ts b/src/core/templates/workflows/explore.ts index 211de65646..74e7a39efd 100644 --- a/src/core/templates/workflows/explore.ts +++ b/src/core/templates/workflows/explore.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getExploreSkillTemplate(): SkillTemplate { return { name: 'openspec-explore', - description: 'Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.', + description: 'Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: `Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes. **IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing. For a new change, scaffold it first as described below. diff --git a/src/core/templates/workflows/ff-change.ts b/src/core/templates/workflows/ff-change.ts index 1a3f036ba2..cec07e1b37 100644 --- a/src/core/templates/workflows/ff-change.ts +++ b/src/core/templates/workflows/ff-change.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; 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.', + description: 'Fast-forward through OpenSpec artifact creation. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: `Fast-forward through artifact creation - generate everything needed to start implementation in one go. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/new-change.ts b/src/core/templates/workflows/new-change.ts index e45858abbc..5355a9d43d 100644 --- a/src/core/templates/workflows/new-change.ts +++ b/src/core/templates/workflows/new-change.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getNewChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-new-change', - description: 'Start a new OpenSpec change using the experimental artifact workflow. Use when the user wants to create a new feature, fix, or modification with a structured step-by-step approach.', + description: 'Start a new OpenSpec change using the experimental artifact workflow. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: `Start a new change using the experimental artifact-driven approach. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/onboard.ts b/src/core/templates/workflows/onboard.ts index 743c71ff8d..c755305128 100644 --- a/src/core/templates/workflows/onboard.ts +++ b/src/core/templates/workflows/onboard.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getOnboardSkillTemplate(): SkillTemplate { return { name: 'openspec-onboard', - description: 'Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work.', + description: 'Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: getOnboardInstructions(), license: 'MIT', compatibility: 'Requires openspec CLI.', diff --git a/src/core/templates/workflows/propose.ts b/src/core/templates/workflows/propose.ts index 8e700c703d..36e04fbcc0 100644 --- a/src/core/templates/workflows/propose.ts +++ b/src/core/templates/workflows/propose.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getOpsxProposeSkillTemplate(): SkillTemplate { return { name: 'openspec-propose', - description: 'Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.', + description: 'Propose a new change with all artifacts generated in one step. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: `Propose a new change - create the change and generate all artifacts in one step. **Planning boundary**: This workflow creates planning artifacts only. The user request that selected or triggered this workflow authorizes planning only, even if it asks to build or fix something. Do not edit project code. After the planning artifacts are complete, stop. Do not start implementation in the same response, even if the initial request asks for it. Wait for a new user request after the artifacts are presented; then start the apply workflow. diff --git a/src/core/templates/workflows/sync-specs.ts b/src/core/templates/workflows/sync-specs.ts index bedbaa7164..3e41ad1053 100644 --- a/src/core/templates/workflows/sync-specs.ts +++ b/src/core/templates/workflows/sync-specs.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getSyncSpecsSkillTemplate(): SkillTemplate { return { name: 'openspec-sync-specs', - description: 'Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change.', + description: 'Sync delta specs from a change to main specs. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: `Sync delta specs from a change to main specs. 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). diff --git a/src/core/templates/workflows/update-change.ts b/src/core/templates/workflows/update-change.ts index 7700cd8d7e..b98c4a6f4f 100644 --- a/src/core/templates/workflows/update-change.ts +++ b/src/core/templates/workflows/update-change.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getUpdateChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-update-change', - description: "Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use when the user wants to revise a change's plan, fold new decisions into it, or reconcile its artifacts after an edit. Never edits code.", + description: "Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. Never edits code.", instructions: `Revise a change's existing planning artifacts and keep them coherent. Never edit code. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/verify-change.ts b/src/core/templates/workflows/verify-change.ts index 1aa540c76b..d79528a9af 100644 --- a/src/core/templates/workflows/verify-change.ts +++ b/src/core/templates/workflows/verify-change.ts @@ -10,7 +10,7 @@ import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; export function getVerifyChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-verify-change', - description: 'Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving.', + description: 'Verify implementation matches change artifacts. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', instructions: `Verify that an implementation matches the change artifacts (specs, tasks, design). ${STORE_SELECTION_GUIDANCE} diff --git a/test/core/templates/skill-templates-parity.test.ts b/test/core/templates/skill-templates-parity.test.ts index decad7b0b5..531e220be6 100644 --- a/test/core/templates/skill-templates-parity.test.ts +++ b/test/core/templates/skill-templates-parity.test.ts @@ -38,46 +38,46 @@ import { import { STORE_SELECTION_GUIDANCE } from '../../../src/core/templates/workflows/store-selection.js'; const EXPECTED_FUNCTION_HASHES: Record = { - getExploreSkillTemplate: '3efc37cddf342318ac37be7bb4ff5915f454b4c5bb127294ebdc7534ee21aa23', - getNewChangeSkillTemplate: 'eabd1e895c5881dcb17dcbaa3fb26098dd59e8eacb318e400820b4dc811ef781', - getContinueChangeSkillTemplate: '012136f6411a99c8fa228e2f9444cb64b0a89e0f56fdeac2fe03b2f5bee0c5d7', - getApplyChangeSkillTemplate: 'd1e7d5ceb85193c0964057dbb88e9651526754bd33f84020e2440ff0621d5dbb', - getFfChangeSkillTemplate: '5501740e7ec36ab23ab8c3a0d6dd0655a5e2f35433c7b90e82904fef5e7a326a', - getSyncSpecsSkillTemplate: 'b099e2ff31859c9b10d928066e662524f9aad9ecf2be12fceacb732d718c4146', - getOnboardSkillTemplate: '29b1d825179cff92fbc7b790694c1baef138575ea3de56848715e27d7e367946', + getExploreSkillTemplate: 'c61e7251e313d68222e70d2966d50fcee6d39a47dbbe52e0eaed17b6bf36b585', + getNewChangeSkillTemplate: '829edf1037bd719517a4124b107df9637106f44012d995068c11bc443a5c475b', + getContinueChangeSkillTemplate: 'd01590eabfcd84fa69b33557f573ff6c1eef620651681ac8365faf0fd6a4ccaa', + getApplyChangeSkillTemplate: '8fb8e88ccea63158926aba85e2ffd9f784f068a5891bf9dadb9156af1a04448b', + getFfChangeSkillTemplate: '1f1c4061deecad1ac2e793f88fa8e164b2a7ade4b44376285da499e31208c8b7', + getSyncSpecsSkillTemplate: '444b21825cbe95152b0f7532578be23c8a78718bca88cb1bc53e086f2fbce08f', + getOnboardSkillTemplate: '4a711c994aa820ac6f208485739c71993df19d8de049ebf3d73a4354468b2c08', getOpsxExploreCommandTemplate: 'd2f70d11588f902c15c1e5ce9908cc4124c6b82fe78dc766ac5c3599c9e2a6f1', getOpsxNewCommandTemplate: 'f2d30e569798a4c92ba932859d6ba4e0ad10e18feccbade1cfee0957597b3463', getOpsxContinueCommandTemplate: 'e50e50266efa1b8e64ff9b6274ee8254f0a240d6adc1b862d126e2f1c9d3a559', getOpsxApplyCommandTemplate: 'e3579ac78f2e2c75fa3d3a7ac7dc3e49c395e96f7323398f0f041d94f8de9bb0', getOpsxFfCommandTemplate: 'e603bc0996604e6c17a3140943ea642a32d0fc65565e25424bf956e124c55772', - getArchiveChangeSkillTemplate: '56bfada1a5f35a127791b70de9d428a75b5aedd1584d6c9803a1ecb1fd1b4a23', - getBulkArchiveChangeSkillTemplate: '93875998cade5322d95b43299fba794bc1da754e917dd63a770406386a6d295d', + getArchiveChangeSkillTemplate: '94208d8e5be24e4040b57ea40c67c4de4e1e39bcf055cc7e9073bceba37744d7', + getBulkArchiveChangeSkillTemplate: 'dd4769a6dc69670bc51edf3f2c399d6cc0cb8bb4775752e7ddf64e3b08e74cf2', getOpsxSyncCommandTemplate: '0d2427efb79986e8fff3f96bd075a739c80d45eb29159fae717e950030da8202', - getVerifyChangeSkillTemplate: '223b7ffd99299a7d430e13092b9a0a3421b39f0d3217232f46c39d79b5f619ff', + getVerifyChangeSkillTemplate: 'd0cf3940d9e749c9c13b95f2d9c6613c339f7bfd1f4f7738fea4e85e2399fcca', getOpsxArchiveCommandTemplate: '9f973c819b11620985b03322945f0e0a92a02a2ef455b94e74482f5e6292ac5d', getOpsxOnboardCommandTemplate: '7e251da66e2fdf539a09326463ee3ed0d01fe665ecb1d8f36f941fed00a01891', getOpsxBulkArchiveCommandTemplate: '9fa8cdebe2f5667ebfc37bdc023396762c59d5b038c771dac2d8fd2c19e2627b', getOpsxVerifyCommandTemplate: '1efcf7eff0671f48e9d9420f50865c563dd3079ee60f8c380bb7a90dd0102696', - getOpsxProposeSkillTemplate: '24623c066f97e34b957d448d1f9a9e8b8a13da3dfce45d45671f6226a2534848', + getOpsxProposeSkillTemplate: 'ecfc721940b6d723eaf7efdf02f582ed457aaa6b0793b31c2bb4ba1b30084f36', getOpsxProposeCommandTemplate: 'e67ba591efb0fecacb2229d06dfa84af18b825fab8a7b01377279e4f09a06ce4', getFeedbackSkillTemplate: 'd7d83c5f7fc2b92fe8f4588a5bf2d9cb315e4c73ec19bcd5ef28270906319a0d', - getUpdateChangeSkillTemplate: '7dc8abc6f64c58bf34d7581ed4ab095a3b7a53cb372349bee2d840db58622819', + getUpdateChangeSkillTemplate: '991a4eb0f05425f2a68540355c9e2b59037056c2043597a22ce618ce2b9b7b3c', getOpsxUpdateCommandTemplate: 'e2388521b22f92f74561df9a0c2f98e1fa4d265af93b5ba26f42fb47a6c5bfed', }; const EXPECTED_GENERATED_SKILL_CONTENT_HASHES: Record = { - 'openspec-explore': '4d9736372cc1faf8a5d8a66395a95bf77b9f3fcd2cda40411ad1db6927e8066a', - 'openspec-new-change': 'ec4529beef978e34634a6f7286fab55d68fad8fb374dceb45691d52caab33fbb', - 'openspec-continue-change': 'bb6194a16c54891cdb253678e8f70ce53b2af86735243980f366ce551d37e42e', - 'openspec-apply-change': '81ea96d9fa6ec8536cd23c1fe561ed28e1cc1cad0a8ceb700588e08974cc0e49', - 'openspec-ff-change': '217c78da2b6e8358f609ac57dcd02266aaec3354ce26dc6ec2fc9c2174673ab4', - 'openspec-sync-specs': 'd933d8856584d6c1253de91e652e7aee9e85c77ad4d3531f6476f79d84e6e5e8', - 'openspec-archive-change': '7c65053d674ba4e1e20e2bf73ba7e5a7f94baef2eaa9b33cee48d4cadea51b7a', - 'openspec-bulk-archive-change': '2039b9ecf6e64339dffe0e16272507a386d9fe326f419ff758315aa736fdd96c', - 'openspec-verify-change': 'af9be013dcbe8c6d8f6d9ab10c893fbd03f4c62933c384d82f63894dd0ceb84f', - 'openspec-onboard': 'd53403b4910ab64307862ccf97e70bd8f7174ee44508088fb239c880f0939331', - 'openspec-propose': '25d08ed4f031770cea219604167d76bca9f3e89fe0c2f545263674482c6f13f0', - 'openspec-update-change': '586547406aca94422dfeb3ffedce6c01049429b743f57ce829baa79ebc714d51', + 'openspec-explore': 'b51f5063a4313f615652aa2b4c88759f49554e4ae584adc8ff12ece608ae80de', + 'openspec-new-change': '63dd689371fe30a8a19085ee3e4dca52cb418cbbad5ba9e3cee2d40a2998d19a', + 'openspec-continue-change': '5451ae883a280e1217d5b56ff5d2468a281b594a4742b64d6c56ac9df51372cd', + 'openspec-apply-change': 'fe76ede7c14393c79c64a15a900ff289fea2c6c0bb10c728b8a48cc07364c005', + 'openspec-ff-change': 'a4c4da88acae366e5d46617693236a380e8827049190a5b07e5fca433764c08c', + 'openspec-sync-specs': '92f0984fa9d57f77e262689535e2596a522db978c4a5c37a847a8502382c5262', + 'openspec-archive-change': 'a5617dd3d00b5e4eb83876a12efa18c27064a42b1b39b3589706d90f405ceacc', + 'openspec-bulk-archive-change': '9ce1be8e0bf77bd73fd89fad32b2b15b7977815d9bb6549ea1a65f34e6e3177b', + 'openspec-verify-change': 'e70859266672e85bc3e4e5c269a96d188ac365bd2aa44f78ea5da6d9bf47abbe', + 'openspec-onboard': 'e57196225937e7366e804fffeb1807d3baeee9b0fe9e5ba2072e8b2f253dff79', + 'openspec-propose': '77d60ca63550c7906667d5762a6c0b6a94b5e6c4a4555301f7734c477f2e86f9', + 'openspec-update-change': '36889dbf929c6b43e9f8ddd27eafaa7e83ff9496ac3938e67a8f9c311cc4c632', }; // Intentionally excludes getFeedbackSkillTemplate: this list only models templates @@ -195,6 +195,14 @@ describe('skill templates split parity', () => { } }); + it('scopes automatic skill selection to OpenSpec work (#1645)', () => { + for (const { template, dirName } of getSkillTemplates()) { + expect(template.description, dirName).toContain( + 'Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.' + ); + } + }); + it('teaches store selection in every deployed opsx command template', () => { for (const entry of getCommandContents()) { expect(entry.body, entry.id).toContain(STORE_SELECTION_GUIDANCE); From 5dcd1c26c753331922c6df1decb21685fd0caafa Mon Sep 17 00:00:00 2001 From: Clay Good Date: Fri, 14 Aug 2026 16:26:57 -0500 Subject: [PATCH 2/2] fix(skills): harden OpenSpec activation guards --- skills/openspec-apply-change/SKILL.md | 4 +- skills/openspec-archive-change/SKILL.md | 4 +- skills/openspec-bulk-archive-change/SKILL.md | 4 +- skills/openspec-continue-change/SKILL.md | 4 +- skills/openspec-explore/SKILL.md | 4 +- skills/openspec-ff-change/SKILL.md | 4 +- skills/openspec-new-change/SKILL.md | 4 +- skills/openspec-onboard/SKILL.md | 4 +- skills/openspec-propose/SKILL.md | 4 +- skills/openspec-sync-specs/SKILL.md | 4 +- skills/openspec-update-change/SKILL.md | 4 +- skills/openspec-verify-change/SKILL.md | 4 +- src/core/templates/workflows/apply-change.ts | 5 +- .../templates/workflows/archive-change.ts | 5 +- .../workflows/bulk-archive-change.ts | 5 +- .../templates/workflows/continue-change.ts | 5 +- src/core/templates/workflows/explore.ts | 5 +- src/core/templates/workflows/ff-change.ts | 5 +- src/core/templates/workflows/new-change.ts | 5 +- src/core/templates/workflows/onboard.ts | 5 +- src/core/templates/workflows/propose.ts | 5 +- .../templates/workflows/skill-activation.ts | 7 ++ src/core/templates/workflows/sync-specs.ts | 5 +- src/core/templates/workflows/update-change.ts | 5 +- src/core/templates/workflows/verify-change.ts | 5 +- .../templates/skill-templates-parity.test.ts | 72 ++++++++++--------- 26 files changed, 118 insertions(+), 69 deletions(-) create mode 100644 src/core/templates/workflows/skill-activation.ts diff --git a/skills/openspec-apply-change/SKILL.md b/skills/openspec-apply-change/SKILL.md index 24219c56cb..01b9419d82 100644 --- a/skills/openspec-apply-change/SKILL.md +++ b/skills/openspec-apply-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-apply-change -description: Implement tasks from an OpenSpec change. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Implement tasks from an OpenSpec change. **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. diff --git a/skills/openspec-archive-change/SKILL.md b/skills/openspec-archive-change/SKILL.md index e74c86296d..031a83fdaf 100644 --- a/skills/openspec-archive-change/SKILL.md +++ b/skills/openspec-archive-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-archive-change -description: Archive a completed change in the experimental workflow. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Archive a completed change in the experimental workflow. **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. diff --git a/skills/openspec-bulk-archive-change/SKILL.md b/skills/openspec-bulk-archive-change/SKILL.md index 24c8874b21..6211d7d102 100644 --- a/skills/openspec-bulk-archive-change/SKILL.md +++ b/skills/openspec-bulk-archive-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-bulk-archive-change -description: Archive multiple completed changes at once. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Archive multiple completed changes at once. Use when archiving several parallel changes. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Archive multiple completed changes in a single operation. This skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented. diff --git a/skills/openspec-continue-change/SKILL.md b/skills/openspec-continue-change/SKILL.md index 86860f1087..5806c4e9b4 100644 --- a/skills/openspec-continue-change/SKILL.md +++ b/skills/openspec-continue-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-continue-change -description: Continue working on an OpenSpec change by creating the next artifact. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. 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. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Continue working on a change by creating the next artifact. **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. diff --git a/skills/openspec-explore/SKILL.md b/skills/openspec-explore/SKILL.md index 43d7ff8f36..019c119bb3 100644 --- a/skills/openspec-explore/SKILL.md +++ b/skills/openspec-explore/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-explore -description: Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes. **IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing. For a new change, scaffold it first as described below. diff --git a/skills/openspec-ff-change/SKILL.md b/skills/openspec-ff-change/SKILL.md index bc536fac84..2458e021a6 100644 --- a/skills/openspec-ff-change/SKILL.md +++ b/skills/openspec-ff-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-ff-change -description: Fast-forward through OpenSpec artifact creation. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. 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. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Fast-forward through artifact creation - generate everything needed to start implementation in one go. **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. diff --git a/skills/openspec-new-change/SKILL.md b/skills/openspec-new-change/SKILL.md index 3d4a592a93..a11073d8ab 100644 --- a/skills/openspec-new-change/SKILL.md +++ b/skills/openspec-new-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-new-change -description: Start a new OpenSpec change using the experimental artifact workflow. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Start a new OpenSpec change using the experimental artifact workflow. Use when the user wants to create a new feature, fix, or modification with a structured step-by-step approach. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Start a new change using the experimental artifact-driven approach. **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. diff --git a/skills/openspec-onboard/SKILL.md b/skills/openspec-onboard/SKILL.md index 016252e0cb..21973571a0 100644 --- a/skills/openspec-onboard/SKILL.md +++ b/skills/openspec-onboard/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-onboard -description: Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Guide the user through their first complete OpenSpec workflow cycle. This is a teaching experience—you'll do real work in their codebase while explaining each step. **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. diff --git a/skills/openspec-propose/SKILL.md b/skills/openspec-propose/SKILL.md index 64487cd95b..0b787c9c1a 100644 --- a/skills/openspec-propose/SKILL.md +++ b/skills/openspec-propose/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-propose -description: Propose a new change with all artifacts generated in one step. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Propose a new change - create the change and generate all artifacts in one step. **Planning boundary**: This workflow creates planning artifacts only. The user request that selected or triggered this workflow authorizes planning only, even if it asks to build or fix something. Do not edit project code. After the planning artifacts are complete, stop. Do not start implementation in the same response, even if the initial request asks for it. Wait for a new user request after the artifacts are presented; then start the apply workflow. diff --git a/skills/openspec-sync-specs/SKILL.md b/skills/openspec-sync-specs/SKILL.md index 5cdd06317a..2288aaac74 100644 --- a/skills/openspec-sync-specs/SKILL.md +++ b/skills/openspec-sync-specs/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-sync-specs -description: Sync delta specs from a change to main specs. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Sync delta specs from a change to main specs. 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). diff --git a/skills/openspec-update-change/SKILL.md b/skills/openspec-update-change/SKILL.md index 2f2db68441..60feff053c 100644 --- a/skills/openspec-update-change/SKILL.md +++ b/skills/openspec-update-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-update-change -description: Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. Never edits code. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use when the user wants to revise a change's plan, fold new decisions into it, or reconcile its artifacts after an edit. Never edits code. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Revise a change's existing planning artifacts and keep them coherent. Never edit code. **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. diff --git a/skills/openspec-verify-change/SKILL.md b/skills/openspec-verify-change/SKILL.md index 262d898a40..9d6659e494 100644 --- a/skills/openspec-verify-change/SKILL.md +++ b/skills/openspec-verify-change/SKILL.md @@ -1,6 +1,6 @@ --- name: openspec-verify-change -description: Verify implementation matches change artifacts. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. +description: Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving. allowed-tools: Bash(openspec:*) license: MIT compatibility: Requires openspec CLI. @@ -9,6 +9,8 @@ metadata: version: "1.0" --- +**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an `openspec/` directory; `openspec context --json` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally. + Verify that an implementation matches the change artifacts (specs, tasks, design). **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store ` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`, `schemas`, `view`). Once selected, treat `--store ` as sticky for the rest of the workflow. Every unscoped example of those commands below is shorthand: before running it, append the flag. For example, run `openspec status --change "" --json --store ""`, not the unscoped form shown below. Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root. diff --git a/src/core/templates/workflows/apply-change.ts b/src/core/templates/workflows/apply-change.ts index eed7370f33..2daf450dbb 100644 --- a/src/core/templates/workflows/apply-change.ts +++ b/src/core/templates/workflows/apply-change.ts @@ -6,6 +6,7 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; /** * The apply workflow instructions, authored once and rendered by both the @@ -198,8 +199,8 @@ This skill supports the "actions on a change" model: export function getApplyChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-apply-change', - description: 'Implement tasks from an OpenSpec change. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: getApplyInstructions(), + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.', + instructions: `${SKILL_ACTIVATION_GUARD}\n\n${getApplyInstructions()}`, license: 'MIT', compatibility: 'Requires openspec CLI.', metadata: { author: 'openspec', version: '1.0' }, diff --git a/src/core/templates/workflows/archive-change.ts b/src/core/templates/workflows/archive-change.ts index 26cac00145..2be6d03ad0 100644 --- a/src/core/templates/workflows/archive-change.ts +++ b/src/core/templates/workflows/archive-change.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getArchiveChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-archive-change', - description: 'Archive a completed change in the experimental workflow. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: `Archive a completed change in the experimental workflow. + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.', + instructions: `${SKILL_ACTIVATION_GUARD}\n\nArchive a completed change in the experimental workflow. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/bulk-archive-change.ts b/src/core/templates/workflows/bulk-archive-change.ts index cff97f30b0..f7dff0f657 100644 --- a/src/core/templates/workflows/bulk-archive-change.ts +++ b/src/core/templates/workflows/bulk-archive-change.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getBulkArchiveChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-bulk-archive-change', - description: 'Archive multiple completed changes at once. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: `Archive multiple completed changes in a single operation. + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Archive multiple completed changes at once. Use when archiving several parallel changes.', + instructions: `${SKILL_ACTIVATION_GUARD}\n\nArchive multiple completed changes in a single operation. This skill allows you to batch-archive changes, handling spec conflicts intelligently by checking the codebase to determine what's actually implemented. diff --git a/src/core/templates/workflows/continue-change.ts b/src/core/templates/workflows/continue-change.ts index b99ae7c857..4f338fc871 100644 --- a/src/core/templates/workflows/continue-change.ts +++ b/src/core/templates/workflows/continue-change.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getContinueChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-continue-change', - description: 'Continue working on an OpenSpec change by creating the next artifact. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: `Continue working on a change by creating the next artifact. + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. 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: `${SKILL_ACTIVATION_GUARD}\n\nContinue working on a change by creating the next artifact. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/explore.ts b/src/core/templates/workflows/explore.ts index 74e7a39efd..68422c1c5e 100644 --- a/src/core/templates/workflows/explore.ts +++ b/src/core/templates/workflows/explore.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getExploreSkillTemplate(): SkillTemplate { return { name: 'openspec-explore', - description: 'Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: `Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes. + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.', + instructions: `${SKILL_ACTIVATION_GUARD}\n\nEnter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes. **IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing. For a new change, scaffold it first as described below. diff --git a/src/core/templates/workflows/ff-change.ts b/src/core/templates/workflows/ff-change.ts index cec07e1b37..c4c550959d 100644 --- a/src/core/templates/workflows/ff-change.ts +++ b/src/core/templates/workflows/ff-change.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getFfChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-ff-change', - description: 'Fast-forward through OpenSpec artifact creation. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: `Fast-forward through artifact creation - generate everything needed to start implementation in one go. + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. 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: `${SKILL_ACTIVATION_GUARD}\n\nFast-forward through artifact creation - generate everything needed to start implementation in one go. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/new-change.ts b/src/core/templates/workflows/new-change.ts index 5355a9d43d..97fb61b4d9 100644 --- a/src/core/templates/workflows/new-change.ts +++ b/src/core/templates/workflows/new-change.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getNewChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-new-change', - description: 'Start a new OpenSpec change using the experimental artifact workflow. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: `Start a new change using the experimental artifact-driven approach. + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Start a new OpenSpec change using the experimental artifact workflow. Use when the user wants to create a new feature, fix, or modification with a structured step-by-step approach.', + instructions: `${SKILL_ACTIVATION_GUARD}\n\nStart a new change using the experimental artifact-driven approach. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/onboard.ts b/src/core/templates/workflows/onboard.ts index c755305128..2a973625f7 100644 --- a/src/core/templates/workflows/onboard.ts +++ b/src/core/templates/workflows/onboard.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getOnboardSkillTemplate(): SkillTemplate { return { name: 'openspec-onboard', - description: 'Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: getOnboardInstructions(), + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Guided onboarding for OpenSpec - walk through a complete workflow cycle with narration and real codebase work.', + instructions: `${SKILL_ACTIVATION_GUARD}\n\n${getOnboardInstructions()}`, license: 'MIT', compatibility: 'Requires openspec CLI.', metadata: { author: 'openspec', version: '1.0' }, diff --git a/src/core/templates/workflows/propose.ts b/src/core/templates/workflows/propose.ts index 36e04fbcc0..6c2eda71a8 100644 --- a/src/core/templates/workflows/propose.ts +++ b/src/core/templates/workflows/propose.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getOpsxProposeSkillTemplate(): SkillTemplate { return { name: 'openspec-propose', - description: 'Propose a new change with all artifacts generated in one step. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: `Propose a new change - create the change and generate all artifacts in one step. + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.', + instructions: `${SKILL_ACTIVATION_GUARD}\n\nPropose a new change - create the change and generate all artifacts in one step. **Planning boundary**: This workflow creates planning artifacts only. The user request that selected or triggered this workflow authorizes planning only, even if it asks to build or fix something. Do not edit project code. After the planning artifacts are complete, stop. Do not start implementation in the same response, even if the initial request asks for it. Wait for a new user request after the artifacts are presented; then start the apply workflow. diff --git a/src/core/templates/workflows/skill-activation.ts b/src/core/templates/workflows/skill-activation.ts new file mode 100644 index 0000000000..e96cd863c1 --- /dev/null +++ b/src/core/templates/workflows/skill-activation.ts @@ -0,0 +1,7 @@ +/** + * Defense-in-depth for model-selected skills. + * + * Slash commands are explicit invocations, so this guidance is intentionally + * added only to skill templates. + */ +export const SKILL_ACTIVATION_GUARD = `**Activation check:** Use this skill only for OpenSpec work. Before continuing, confirm at least one of these conditions: the current project has an \`openspec/\` directory; \`openspec context --json\` resolves a configured OpenSpec store; the user selected a registered OpenSpec store; or the user explicitly invoked this skill or asked to use OpenSpec. If none applies, stop using this skill and continue with the user's request normally.`; diff --git a/src/core/templates/workflows/sync-specs.ts b/src/core/templates/workflows/sync-specs.ts index 3e41ad1053..a11c26224b 100644 --- a/src/core/templates/workflows/sync-specs.ts +++ b/src/core/templates/workflows/sync-specs.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getSyncSpecsSkillTemplate(): SkillTemplate { return { name: 'openspec-sync-specs', - description: 'Sync delta specs from a change to main specs. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: `Sync delta specs from a change to main specs. + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change.', + instructions: `${SKILL_ACTIVATION_GUARD}\n\nSync delta specs from a change to main specs. 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). diff --git a/src/core/templates/workflows/update-change.ts b/src/core/templates/workflows/update-change.ts index b98c4a6f4f..42ee68e3cf 100644 --- a/src/core/templates/workflows/update-change.ts +++ b/src/core/templates/workflows/update-change.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getUpdateChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-update-change', - description: "Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec. Never edits code.", - instructions: `Revise a change's existing planning artifacts and keep them coherent. Never edit code. + description: "Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use when the user wants to revise a change's plan, fold new decisions into it, or reconcile its artifacts after an edit. Never edits code.", + instructions: `${SKILL_ACTIVATION_GUARD}\n\nRevise a change's existing planning artifacts and keep them coherent. Never edit code. ${STORE_SELECTION_GUIDANCE} diff --git a/src/core/templates/workflows/verify-change.ts b/src/core/templates/workflows/verify-change.ts index d79528a9af..0b472d5f2b 100644 --- a/src/core/templates/workflows/verify-change.ts +++ b/src/core/templates/workflows/verify-change.ts @@ -6,12 +6,13 @@ */ import type { SkillTemplate, CommandTemplate } from '../types.js'; import { STORE_SELECTION_GUIDANCE } from './store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from './skill-activation.js'; export function getVerifyChangeSkillTemplate(): SkillTemplate { return { name: 'openspec-verify-change', - description: 'Verify implementation matches change artifacts. Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.', - instructions: `Verify that an implementation matches the change artifacts (specs, tasks, design). + description: 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec. Verify implementation matches change artifacts. Use when the user wants to validate that implementation is complete, correct, and coherent before archiving.', + instructions: `${SKILL_ACTIVATION_GUARD}\n\nVerify that an implementation matches the change artifacts (specs, tasks, design). ${STORE_SELECTION_GUIDANCE} diff --git a/test/core/templates/skill-templates-parity.test.ts b/test/core/templates/skill-templates-parity.test.ts index 531e220be6..f102ab27f7 100644 --- a/test/core/templates/skill-templates-parity.test.ts +++ b/test/core/templates/skill-templates-parity.test.ts @@ -36,48 +36,51 @@ import { getSkillTemplates, } from '../../../src/core/shared/skill-generation.js'; import { STORE_SELECTION_GUIDANCE } from '../../../src/core/templates/workflows/store-selection.js'; +import { SKILL_ACTIVATION_GUARD } from '../../../src/core/templates/workflows/skill-activation.js'; + +const SKILL_SCOPE = 'Use only for OpenSpec work when the current project has an openspec/ directory, a configured or user-selected OpenSpec store applies, or the user explicitly invokes this skill or asks to use OpenSpec.'; const EXPECTED_FUNCTION_HASHES: Record = { - getExploreSkillTemplate: 'c61e7251e313d68222e70d2966d50fcee6d39a47dbbe52e0eaed17b6bf36b585', - getNewChangeSkillTemplate: '829edf1037bd719517a4124b107df9637106f44012d995068c11bc443a5c475b', - getContinueChangeSkillTemplate: 'd01590eabfcd84fa69b33557f573ff6c1eef620651681ac8365faf0fd6a4ccaa', - getApplyChangeSkillTemplate: '8fb8e88ccea63158926aba85e2ffd9f784f068a5891bf9dadb9156af1a04448b', - getFfChangeSkillTemplate: '1f1c4061deecad1ac2e793f88fa8e164b2a7ade4b44376285da499e31208c8b7', - getSyncSpecsSkillTemplate: '444b21825cbe95152b0f7532578be23c8a78718bca88cb1bc53e086f2fbce08f', - getOnboardSkillTemplate: '4a711c994aa820ac6f208485739c71993df19d8de049ebf3d73a4354468b2c08', + getExploreSkillTemplate: '222fe6a6b51eedf3d1a27d0e412e7474b616493dc60bfee162e1c98a3a22486a', + getNewChangeSkillTemplate: 'caf34369b38944f4e9d081bcddb0219a23d649f4d1dce3c92a2dd82c6c5f8295', + getContinueChangeSkillTemplate: '9959203b4599f7468914f36ec5e901bf4c955aa12d8c1b4ac69086647b13e921', + getApplyChangeSkillTemplate: '167730cb5d38a7156515479a5beb3b6a645afc12b2c858cb6ea7005150d8513c', + getFfChangeSkillTemplate: '2a4178b35537c7f866d746bd321d22dbbef4486b91335323ba8fe4fb0b48cf82', + getSyncSpecsSkillTemplate: '1feae15703193855a800c581a76e4ebf60928681bc00601ae6bfdaf93f292ba2', + getOnboardSkillTemplate: '3655431ead4b02b2ac22873e44f2f840f7a7b5139c168401a382a2a58b74d422', getOpsxExploreCommandTemplate: 'd2f70d11588f902c15c1e5ce9908cc4124c6b82fe78dc766ac5c3599c9e2a6f1', getOpsxNewCommandTemplate: 'f2d30e569798a4c92ba932859d6ba4e0ad10e18feccbade1cfee0957597b3463', getOpsxContinueCommandTemplate: 'e50e50266efa1b8e64ff9b6274ee8254f0a240d6adc1b862d126e2f1c9d3a559', getOpsxApplyCommandTemplate: 'e3579ac78f2e2c75fa3d3a7ac7dc3e49c395e96f7323398f0f041d94f8de9bb0', getOpsxFfCommandTemplate: 'e603bc0996604e6c17a3140943ea642a32d0fc65565e25424bf956e124c55772', - getArchiveChangeSkillTemplate: '94208d8e5be24e4040b57ea40c67c4de4e1e39bcf055cc7e9073bceba37744d7', - getBulkArchiveChangeSkillTemplate: 'dd4769a6dc69670bc51edf3f2c399d6cc0cb8bb4775752e7ddf64e3b08e74cf2', + getArchiveChangeSkillTemplate: 'a2861f9498ebdf6c89cb03a7a213d4191e6fef6dd71c29c25802da660863f8f9', + getBulkArchiveChangeSkillTemplate: '4e5194e8e671793c862a0b5694cf973cb5f1a54764284729d58892e8dfc69a81', getOpsxSyncCommandTemplate: '0d2427efb79986e8fff3f96bd075a739c80d45eb29159fae717e950030da8202', - getVerifyChangeSkillTemplate: 'd0cf3940d9e749c9c13b95f2d9c6613c339f7bfd1f4f7738fea4e85e2399fcca', + getVerifyChangeSkillTemplate: 'd26e4ebaf558e908854e2c69229bce27325cde9a683c532d596157a7722800d0', getOpsxArchiveCommandTemplate: '9f973c819b11620985b03322945f0e0a92a02a2ef455b94e74482f5e6292ac5d', getOpsxOnboardCommandTemplate: '7e251da66e2fdf539a09326463ee3ed0d01fe665ecb1d8f36f941fed00a01891', getOpsxBulkArchiveCommandTemplate: '9fa8cdebe2f5667ebfc37bdc023396762c59d5b038c771dac2d8fd2c19e2627b', getOpsxVerifyCommandTemplate: '1efcf7eff0671f48e9d9420f50865c563dd3079ee60f8c380bb7a90dd0102696', - getOpsxProposeSkillTemplate: 'ecfc721940b6d723eaf7efdf02f582ed457aaa6b0793b31c2bb4ba1b30084f36', + getOpsxProposeSkillTemplate: '0c10bcc397ea0666ce776d2a440433840ca6defd94d7ef9a7368234a11ae7851', getOpsxProposeCommandTemplate: 'e67ba591efb0fecacb2229d06dfa84af18b825fab8a7b01377279e4f09a06ce4', getFeedbackSkillTemplate: 'd7d83c5f7fc2b92fe8f4588a5bf2d9cb315e4c73ec19bcd5ef28270906319a0d', - getUpdateChangeSkillTemplate: '991a4eb0f05425f2a68540355c9e2b59037056c2043597a22ce618ce2b9b7b3c', + getUpdateChangeSkillTemplate: '30f35f4ff4916e2439fb76cdf24a331e6a2748813a5a3fae429c21c3fca5a1ed', getOpsxUpdateCommandTemplate: 'e2388521b22f92f74561df9a0c2f98e1fa4d265af93b5ba26f42fb47a6c5bfed', }; const EXPECTED_GENERATED_SKILL_CONTENT_HASHES: Record = { - 'openspec-explore': 'b51f5063a4313f615652aa2b4c88759f49554e4ae584adc8ff12ece608ae80de', - 'openspec-new-change': '63dd689371fe30a8a19085ee3e4dca52cb418cbbad5ba9e3cee2d40a2998d19a', - 'openspec-continue-change': '5451ae883a280e1217d5b56ff5d2468a281b594a4742b64d6c56ac9df51372cd', - 'openspec-apply-change': 'fe76ede7c14393c79c64a15a900ff289fea2c6c0bb10c728b8a48cc07364c005', - 'openspec-ff-change': 'a4c4da88acae366e5d46617693236a380e8827049190a5b07e5fca433764c08c', - 'openspec-sync-specs': '92f0984fa9d57f77e262689535e2596a522db978c4a5c37a847a8502382c5262', - 'openspec-archive-change': 'a5617dd3d00b5e4eb83876a12efa18c27064a42b1b39b3589706d90f405ceacc', - 'openspec-bulk-archive-change': '9ce1be8e0bf77bd73fd89fad32b2b15b7977815d9bb6549ea1a65f34e6e3177b', - 'openspec-verify-change': 'e70859266672e85bc3e4e5c269a96d188ac365bd2aa44f78ea5da6d9bf47abbe', - 'openspec-onboard': 'e57196225937e7366e804fffeb1807d3baeee9b0fe9e5ba2072e8b2f253dff79', - 'openspec-propose': '77d60ca63550c7906667d5762a6c0b6a94b5e6c4a4555301f7734c477f2e86f9', - 'openspec-update-change': '36889dbf929c6b43e9f8ddd27eafaa7e83ff9496ac3938e67a8f9c311cc4c632', + 'openspec-explore': '8b2c80cceaf582803be104eca9499ba4562f60c2f9074485ab95982e5a915a58', + 'openspec-new-change': '23e71f0704ed576ec35ef7da1e2984906835b80f475e726b72cf8a3ca42d2993', + 'openspec-continue-change': '5d7cf4e0c184e912b121013541ae762b2b05eb6dbcc5a662312ebf17467086ca', + 'openspec-apply-change': '7f9720132853e8dc14b10f474a614d287957ceb3e5184308de75e4cecc4fd654', + 'openspec-ff-change': '8947acac81420afeb4d6d8720157d2ab1d942745b9b691d686ad0f1546d2467f', + 'openspec-sync-specs': 'eb5992a2760b543042ebc24917d689ff5a7444dc676d5530ad564de995cd29fc', + 'openspec-archive-change': '5f5465d67714d36a5cf9c0dcac10c5d89f8e55295c1b1f3646e5b5aa8923a85e', + 'openspec-bulk-archive-change': '46b3d9a5a7fd9ac0915460deb4b83bac6684b604277e0dcb67e62f38ac450fe2', + 'openspec-verify-change': '83b3b68cc638ec0aec4c4c042b6c0456c12c2aa421182c963f6b785a1e70d9a7', + 'openspec-onboard': '98da412b94e5464b40d994dc9d9bf1bfcbafe4b3bc775acab6d6624bf4fcfa1a', + 'openspec-propose': '728af8662d8defefa62a19a0518c295f267f212ac1f651b856ed50a2c89d88fa', + 'openspec-update-change': '6217074f930457fc6e6c4302142c2c1c033f7333d0857c8b44c6e23cebe22a82', }; // Intentionally excludes getFeedbackSkillTemplate: this list only models templates @@ -197,9 +200,14 @@ describe('skill templates split parity', () => { it('scopes automatic skill selection to OpenSpec work (#1645)', () => { for (const { template, dirName } of getSkillTemplates()) { - expect(template.description, dirName).toContain( - 'Use only when the current project has an openspec/ directory or the user explicitly asks to use OpenSpec.' - ); + expect(template.description.startsWith(SKILL_SCOPE), dirName).toBe(true); + expect(template.instructions.startsWith(SKILL_ACTIVATION_GUARD), dirName).toBe(true); + } + }); + + it('does not gate explicitly invoked opsx commands', () => { + for (const entry of getCommandContents()) { + expect(entry.body, entry.id).not.toContain(SKILL_ACTIVATION_GUARD); } }); @@ -962,14 +970,12 @@ describe('skill templates split parity', () => { describe('apply skill/command shared instruction core', () => { // The apply skill and command are intentionally distinct surfaces, but they - // differ only in how they are invoked — the generation transformers rewrite - // the canonical `/opsx:` tokens per surface downstream (asserted in - // test/utils/command-references.test.ts). The instruction text itself is - // shared, so this pins the contract: both surfaces render the one canonical - // core and cannot silently drift apart at the template level. + // differ only in skill activation and invocation syntax. The generation + // transformers rewrite canonical `/opsx:` tokens downstream (asserted in + // test/utils/command-references.test.ts); this pins the remaining shared core. it('renders both apply surfaces from the shared instruction core', () => { const core = getApplyInstructions(); - expect(getApplyChangeSkillTemplate().instructions).toBe(core); + expect(getApplyChangeSkillTemplate().instructions).toBe(`${SKILL_ACTIVATION_GUARD}\n\n${core}`); expect(getOpsxApplyCommandTemplate().content).toBe(core); }); });