From 5e86713c6b19c2f4b2e8775a83c7b4174f63f685 Mon Sep 17 00:00:00 2001 From: a-horde-o-bees Date: Tue, 28 Jul 2026 16:09:11 -0400 Subject: [PATCH] feat(config): add 'all' profile preset selecting every workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `openspec config profile` ships one preset (core), so selecting the full workflow set non-interactively requires hand-enumerating the twelve ids to `config set workflows` — where an unknown id stores without error and is silently dropped at render. ALL_WORKFLOWS already exists in core/profiles; this exposes it as `openspec config profile all` (profile=custom, delivery preserved), mirroring the core preset. The unknown-preset error now lists both presets; docs and a preset test added. Co-Authored-By: Claude Fable 5 --- docs/cli.md | 3 +++ src/commands/config.ts | 15 ++++++++++----- test/commands/config-profile.test.ts | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index 7bc8ff9f74..00e27216b2 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -1119,6 +1119,9 @@ openspec config profile # Fast preset: switch workflows to core (keeps delivery mode) openspec config profile core + +# Fast preset: select all workflows (keeps delivery mode) +openspec config profile all ``` `openspec config profile` starts with a current-state summary, then lets you choose: diff --git a/src/commands/config.ts b/src/commands/config.ts index e594583e7f..b23723002e 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -459,11 +459,16 @@ export function registerConfigCommand(program: Command): void { .command('profile [preset]') .description('Configure workflow profile (interactive picker or preset shortcut)') .action(async (preset?: string) => { - // Preset shortcut: `openspec config profile core` - if (preset === 'core') { + // Preset shortcuts: `openspec config profile core` / `openspec config profile all` + if (preset === 'core' || preset === 'all') { const config = getGlobalConfig(); - config.profile = 'core'; - config.workflows = [...CORE_WORKFLOWS]; + if (preset === 'core') { + config.profile = 'core'; + config.workflows = [...CORE_WORKFLOWS]; + } else { + config.profile = 'custom'; + config.workflows = [...ALL_WORKFLOWS]; + } // Preserve delivery setting saveGlobalConfig(config); printConfigProfileApplyGuidance(); @@ -471,7 +476,7 @@ export function registerConfigCommand(program: Command): void { } if (preset) { - console.error(`Error: Unknown profile preset "${preset}". Available presets: core`); + console.error(`Error: Unknown profile preset "${preset}". Available presets: core, all`); process.exitCode = 1; return; } diff --git a/test/commands/config-profile.test.ts b/test/commands/config-profile.test.ts index bb130a8f64..5e17e7ebca 100644 --- a/test/commands/config-profile.test.ts +++ b/test/commands/config-profile.test.ts @@ -432,6 +432,24 @@ describe('config profile interactive flow', () => { expect(confirm).not.toHaveBeenCalled(); }); + it('all preset should select every workflow and preserve delivery setting', async () => { + const { saveGlobalConfig, getGlobalConfig } = await import('../../src/core/global-config.js'); + const { ALL_WORKFLOWS } = await import('../../src/core/profiles.js'); + const { select, checkbox, confirm } = await getPromptMocks(); + + saveGlobalConfig({ featureFlags: {}, profile: 'core', delivery: 'skills', workflows: ['explore'] }); + + await runConfigCommand(['profile', 'all']); + + const config = getGlobalConfig(); + expect(config.profile).toBe('custom'); + expect(config.delivery).toBe('skills'); + expect(config.workflows).toEqual([...ALL_WORKFLOWS]); + expect(select).not.toHaveBeenCalled(); + expect(checkbox).not.toHaveBeenCalled(); + expect(confirm).not.toHaveBeenCalled(); + }); + it('Ctrl+C should cancel without stack trace and set interrupted exit code', async () => { const { select, checkbox, confirm } = await getPromptMocks(); const cancellationError = new Error('User force closed the prompt with SIGINT');