diff --git a/src/core/templates/workflows/archive-change.ts b/src/core/templates/workflows/archive-change.ts index 20f69c2bf..c1c40173c 100644 --- a/src/core/templates/workflows/archive-change.ts +++ b/src/core/templates/workflows/archive-change.ts @@ -64,8 +64,16 @@ ${STORE_SELECTION_GUIDANCE} - Determine what changes would be applied (adds, modifications, removals, renames) - Show a combined summary before prompting + **If a corresponding main spec does not exist yet:** + - Treat \`ADDED\` requirements as sync work that will create a new main spec + - Treat \`MODIFIED\` or \`RENAMED\` requirements as blocking errors because they cannot apply to a new spec + - Treat \`REMOVED\` requirements as ignored with a warning + - Do not skip sync just because the target main spec is missing + - If any blocking errors are present, do not offer "Archive without syncing" and do not proceed to archive until the delta spec is corrected + **Prompt options:** - If changes needed: "Sync now (recommended)", "Archive without syncing" + - If blocking errors exist: show the blocking errors and stop - If already synced: "Archive now", "Sync anyway", "Cancel" If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change ''. Delta spec analysis: "). Proceed to archive regardless of choice. @@ -182,8 +190,16 @@ ${STORE_SELECTION_GUIDANCE} - Determine what changes would be applied (adds, modifications, removals, renames) - Show a combined summary before prompting + **If a corresponding main spec does not exist yet:** + - Treat \`ADDED\` requirements as sync work that will create a new main spec + - Treat \`MODIFIED\` or \`RENAMED\` requirements as blocking errors because they cannot apply to a new spec + - Treat \`REMOVED\` requirements as ignored with a warning + - Do not skip sync just because the target main spec is missing + - If any blocking errors are present, do not offer "Archive without syncing" and do not proceed to archive until the delta spec is corrected + **Prompt options:** - If changes needed: "Sync now (recommended)", "Archive without syncing" + - If blocking errors exist: show the blocking errors and stop - If already synced: "Archive now", "Sync anyway", "Cancel" If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change ''. Delta spec analysis: "). Proceed to archive regardless of choice. diff --git a/test/core/templates/skill-templates-parity.test.ts b/test/core/templates/skill-templates-parity.test.ts index cc6ec7bc1..7d14a1c93 100644 --- a/test/core/templates/skill-templates-parity.test.ts +++ b/test/core/templates/skill-templates-parity.test.ts @@ -47,11 +47,11 @@ const EXPECTED_FUNCTION_HASHES: Record = { getOpsxContinueCommandTemplate: '418108b417107a87019d4020b26c105792d2ef0110fe6920445e255889216716', getOpsxApplyCommandTemplate: 'daeb507206707169de73c828e199648dde5732cbc17791ef2a027adffd028574', getOpsxFfCommandTemplate: '36973ae0dd00ab169fbaaa42bf565f97e1bc97cf63ae7c07307734cc1ca8c1fd', - getArchiveChangeSkillTemplate: 'c511a1c943bcfc5f9f3833b8c0ff284b22d34864a08f5f553cec471ee485d38f', + getArchiveChangeSkillTemplate: '698a1595d7bc58002075874bbc0db2c72915e5ae586c4f7e3d628b5e24de40d2', getBulkArchiveChangeSkillTemplate: '0f635913757ae3d1609e111f4a8f699443ca47cbaaf8a1b21eb652f7b96a1d13', getOpsxSyncCommandTemplate: '86cf706886d0f18069e2cfa16948b7357028fd348210efb58588c88c416d8622', getVerifyChangeSkillTemplate: 'd718c79aad649223a73fdb11036c93fb3842ac5a780f4934d50bfa03c9692683', - getOpsxArchiveCommandTemplate: '6985bddb310cb45b6b50350bfcebe31bf67146135ca0084c94930920280970a4', + getOpsxArchiveCommandTemplate: '56ec9f1fbd81daa19780e345a110e071768de8ee3239086ad660d2f551a0aa89', getOpsxOnboardCommandTemplate: '0673f34a0f81fd173bcfb8c3ac83e2b1c617f7b7564e24e5298d3bd5665a05a9', getOpsxBulkArchiveCommandTemplate: '9f444fc7b27a5b788077b5e3aa4f61af45aa8c8004ac8d899d204fa362ff89b7', getOpsxVerifyCommandTemplate: '011509480a20a60342c993906f0f9280c0e9ba5d019d335bdc1ef4d53213a5a8', @@ -67,7 +67,7 @@ const EXPECTED_GENERATED_SKILL_CONTENT_HASHES: Record = { 'openspec-apply-change': '54cffa61274c6a499d2b3775e9f6db29255fd8e5ad99d7352c1e3bbe2edb45ed', 'openspec-ff-change': 'cbb7844c130bd188319ff2b3f0c0320243b5ae5b588a0f816cd4e29408f25676', 'openspec-sync-specs': 'a81fd87f5e871874eab72e57c10a1949fde46d1d07d95f8ea3bc1a52b4e78c43', - 'openspec-archive-change': '833290ade47ddaed7f5e523d07437c7cef2497340021e944096bce449e290c22', + 'openspec-archive-change': '2ed1a381474add5637ce634488b89ddbe4f2fd0b8472f818f1599bcc259fd5d2', 'openspec-bulk-archive-change': '244b195e53d3f010a99892c1922c800fd8f02e7745d0f34ec18b5fe9b5548706', 'openspec-verify-change': '97d1eed5b900788706c28339e27c1d2d9c548626316253f43ebd00d8d52d02d6', 'openspec-onboard': 'd136b6ab7134d6bceeca73bc2f6037624506587e8df99059f77fe88874256ed1', @@ -191,4 +191,18 @@ describe('skill templates split parity', () => { expect(content, dirName).not.toContain('Workspace guard'); } }); + + it('teaches archive workflows how to assess delta specs for missing main specs', () => { + const skillInstructions = getArchiveChangeSkillTemplate().instructions; + const commandContent = getOpsxArchiveCommandTemplate().content; + + for (const content of [skillInstructions, commandContent]) { + expect(content).toContain('If a corresponding main spec does not exist yet'); + expect(content).toContain('`ADDED` requirements as sync work that will create a new main spec'); + expect(content).toContain('`MODIFIED` or `RENAMED` requirements as blocking errors'); + expect(content).toContain('Do not skip sync just because the target main spec is missing'); + expect(content).toContain('do not offer "Archive without syncing"'); + expect(content).toContain('If blocking errors exist: show the blocking errors and stop'); + } + }); });