From 4cc6fe64313f49ddb8b6f5cfbd704411132efc69 Mon Sep 17 00:00:00 2001 From: hutiefang Date: Mon, 22 Jun 2026 03:10:42 +0800 Subject: [PATCH] Fix archive guidance for greenfield specs --- .../templates/workflows/archive-change.ts | 4 ++++ .../templates/skill-templates-parity.test.ts | 20 ++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/core/templates/workflows/archive-change.ts b/src/core/templates/workflows/archive-change.ts index 41619c2b3..ef5d95e61 100644 --- a/src/core/templates/workflows/archive-change.ts +++ b/src/core/templates/workflows/archive-change.ts @@ -60,6 +60,8 @@ export function getArchiveChangeSkillTemplate(): SkillTemplate { **If delta specs exist:** - Compare each delta spec with its corresponding main spec at \`openspec/specs//spec.md\` + - If the main spec does not exist, treat the delta as an unsynced greenfield capability and create a new main spec from ADDED requirements during sync + - Do not treat a missing main spec as already synced or skip it because no existing capability was found - Determine what changes would be applied (adds, modifications, removals, renames) - Show a combined summary before prompting @@ -178,6 +180,8 @@ export function getOpsxArchiveCommandTemplate(): CommandTemplate { **If delta specs exist:** - Compare each delta spec with its corresponding main spec at \`openspec/specs//spec.md\` + - If the main spec does not exist, treat the delta as an unsynced greenfield capability and create a new main spec from ADDED requirements during sync + - Do not treat a missing main spec as already synced or skip it because no existing capability was found - Determine what changes would be applied (adds, modifications, removals, renames) - Show a combined summary before prompting diff --git a/test/core/templates/skill-templates-parity.test.ts b/test/core/templates/skill-templates-parity.test.ts index f851082e5..cc19df0a5 100644 --- a/test/core/templates/skill-templates-parity.test.ts +++ b/test/core/templates/skill-templates-parity.test.ts @@ -42,11 +42,11 @@ const EXPECTED_FUNCTION_HASHES: Record = { getOpsxContinueCommandTemplate: '62f8863edda2bfe4e210f8bc3095fd4369aaaaf7772a5cba9602d0f0bca1d0c9', getOpsxApplyCommandTemplate: '812feefd32a4d9d468e03e456d06e3d2d08d1118d29cce4911f0be59cdd30bfc', getOpsxFfCommandTemplate: 'f775b242bcfd56594c431c7f31a0129208a1bacfdb2427074d412543072ef7ca', - getArchiveChangeSkillTemplate: 'bdf022ae2cdef1feef4d641a068bef3a7fc5d98a323f7ce9f77ac578fe8d20c6', + getArchiveChangeSkillTemplate: '8e90a6c2e4c85795aec5443da2653bb898cdb7b97b907a7ad778e05e258b450a', getBulkArchiveChangeSkillTemplate: 'fdb1715804e86de85be96222b8efeb9d5b350c6d5c19e343e244655deff8e62b', getOpsxSyncCommandTemplate: '4c8118afaea79ff4fed3d946c88e6a7abbba904a5fbf643e4372da1e3735a467', getVerifyChangeSkillTemplate: '3c5dda8b49ba00f50b5bae7f04763dd00cc00a05e5f1d8a2068ad7fb701d8165', - getOpsxArchiveCommandTemplate: '5181ec2f59c9f0f3376e61d952ed4be976cbd01595b6b0d5e67466c8bd6bac6d', + getOpsxArchiveCommandTemplate: '3ab4cae110580001dbf9f7adc20be7286b4eefb7be27452cb1af6ea461ec77a0', getOpsxOnboardCommandTemplate: '57c1f3e2590bda8f47818bab1d528456c1b8a9a7501f63ab9e2115e0cfaf6f35', getOpsxBulkArchiveCommandTemplate: 'b76c421023ccb5a12867c349f27cdb186234b692c1811980fb94127567bdabda', getOpsxVerifyCommandTemplate: '9a7a3f9e5bc3d0c0878b1a4493efbbb38729597d9b9be78f63284cc2da7c20c3', @@ -62,7 +62,7 @@ const EXPECTED_GENERATED_SKILL_CONTENT_HASHES: Record = { 'openspec-apply-change': 'd849442efd925b9247651e254a5cd696945321610cca5a9432ad420430554548', 'openspec-ff-change': '9d9b1995b6f4adb3da570676f7d11fee4cd1cf6c5df8ec83c033e02783a544df', 'openspec-sync-specs': '2e0f67ec6fadffc6107b4b1a28eef23a99a6649e5fae706897ea1dd9deb852a8', - 'openspec-archive-change': '8d14af2c8b2e4358308ac9fc14f75db42a4b41a07e175825035852a82479793e', + 'openspec-archive-change': '3ef758165e25eaf6758b46f3a7c735627548fbd67a5a3dd2acb8a93628bb44ef', 'openspec-bulk-archive-change': '16207683996b1952559cd4e33463f28fb097761f2c5d912107733d01a90d3f2f', 'openspec-verify-change': 'a2acecd0c2b4e57080a314e5e7a093e0688293c37e446eb45d378f5050058550', 'openspec-onboard': 'b924ea3c97543ebb7ee82c5f194afe7ce87a521c32b85616f445240ab33a02ab', @@ -169,4 +169,18 @@ describe('skill templates split parity', () => { expect(content, dirName).not.toContain('mv openspec/changes'); } }); + + it('instructs archive workflows to create missing main specs for greenfield changes', () => { + const archiveSkill = generateSkillContent(getArchiveChangeSkillTemplate(), 'PARITY-BASELINE'); + const archiveCommand = getOpsxArchiveCommandTemplate().content; + + for (const [name, content] of [ + ['openspec-archive-change', archiveSkill], + ['opsx-archive-command', archiveCommand], + ] as const) { + expect(content, name).toContain('If the main spec does not exist'); + expect(content, name).toContain('create a new main spec'); + expect(content, name).toContain('Do not treat a missing main spec as already synced'); + } + }); });