@fission-ai/openspec 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/cli/index.js +2 -0
  2. package/dist/commands/config.d.ts +28 -0
  3. package/dist/commands/config.js +359 -5
  4. package/dist/core/available-tools.d.ts +16 -0
  5. package/dist/core/available-tools.js +30 -0
  6. package/dist/core/command-generation/adapters/index.d.ts +2 -0
  7. package/dist/core/command-generation/adapters/index.js +2 -0
  8. package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
  9. package/dist/core/command-generation/adapters/kiro.js +26 -0
  10. package/dist/core/command-generation/adapters/pi.d.ts +14 -0
  11. package/dist/core/command-generation/adapters/pi.js +41 -0
  12. package/dist/core/command-generation/registry.js +4 -0
  13. package/dist/core/completions/command-registry.js +5 -0
  14. package/dist/core/config-schema.d.ts +10 -0
  15. package/dist/core/config-schema.js +14 -1
  16. package/dist/core/config.js +2 -0
  17. package/dist/core/global-config.d.ts +5 -0
  18. package/dist/core/global-config.js +12 -2
  19. package/dist/core/init.d.ts +5 -0
  20. package/dist/core/init.js +205 -44
  21. package/dist/core/legacy-cleanup.js +1 -0
  22. package/dist/core/migration.d.ts +23 -0
  23. package/dist/core/migration.js +108 -0
  24. package/dist/core/profile-sync-drift.d.ts +38 -0
  25. package/dist/core/profile-sync-drift.js +200 -0
  26. package/dist/core/profiles.d.ts +26 -0
  27. package/dist/core/profiles.js +40 -0
  28. package/dist/core/shared/index.d.ts +1 -1
  29. package/dist/core/shared/index.js +1 -1
  30. package/dist/core/shared/skill-generation.d.ts +14 -7
  31. package/dist/core/shared/skill-generation.js +36 -20
  32. package/dist/core/shared/tool-detection.d.ts +8 -3
  33. package/dist/core/shared/tool-detection.js +18 -0
  34. package/dist/core/templates/index.d.ts +1 -1
  35. package/dist/core/templates/index.js +2 -2
  36. package/dist/core/templates/skill-templates.d.ts +15 -118
  37. package/dist/core/templates/skill-templates.js +14 -3424
  38. package/dist/core/templates/types.d.ts +19 -0
  39. package/dist/core/templates/types.js +5 -0
  40. package/dist/core/templates/workflows/apply-change.d.ts +10 -0
  41. package/dist/core/templates/workflows/apply-change.js +308 -0
  42. package/dist/core/templates/workflows/archive-change.d.ts +10 -0
  43. package/dist/core/templates/workflows/archive-change.js +271 -0
  44. package/dist/core/templates/workflows/bulk-archive-change.d.ts +10 -0
  45. package/dist/core/templates/workflows/bulk-archive-change.js +488 -0
  46. package/dist/core/templates/workflows/continue-change.d.ts +10 -0
  47. package/dist/core/templates/workflows/continue-change.js +232 -0
  48. package/dist/core/templates/workflows/explore.d.ts +10 -0
  49. package/dist/core/templates/workflows/explore.js +461 -0
  50. package/dist/core/templates/workflows/feedback.d.ts +9 -0
  51. package/dist/core/templates/workflows/feedback.js +108 -0
  52. package/dist/core/templates/workflows/ff-change.d.ts +10 -0
  53. package/dist/core/templates/workflows/ff-change.js +198 -0
  54. package/dist/core/templates/workflows/new-change.d.ts +10 -0
  55. package/dist/core/templates/workflows/new-change.js +143 -0
  56. package/dist/core/templates/workflows/onboard.d.ts +10 -0
  57. package/dist/core/templates/workflows/onboard.js +565 -0
  58. package/dist/core/templates/workflows/propose.d.ts +10 -0
  59. package/dist/core/templates/workflows/propose.js +216 -0
  60. package/dist/core/templates/workflows/sync-specs.d.ts +10 -0
  61. package/dist/core/templates/workflows/sync-specs.js +272 -0
  62. package/dist/core/templates/workflows/verify-change.d.ts +10 -0
  63. package/dist/core/templates/workflows/verify-change.js +332 -0
  64. package/dist/core/update.d.ts +36 -1
  65. package/dist/core/update.js +291 -65
  66. package/dist/prompts/searchable-multi-select.d.ts +3 -2
  67. package/dist/prompts/searchable-multi-select.js +22 -12
  68. package/package.json +1 -1
@@ -0,0 +1,38 @@
1
+ import type { Delivery } from './global-config.js';
2
+ import { ALL_WORKFLOWS } from './profiles.js';
3
+ type WorkflowId = (typeof ALL_WORKFLOWS)[number];
4
+ /**
5
+ * Maps workflow IDs to their skill directory names.
6
+ */
7
+ export declare const WORKFLOW_TO_SKILL_DIR: Record<WorkflowId, string>;
8
+ /**
9
+ * Checks whether a tool has at least one generated OpenSpec command file.
10
+ */
11
+ export declare function toolHasAnyConfiguredCommand(projectPath: string, toolId: string): boolean;
12
+ /**
13
+ * Returns tools with at least one generated command file on disk.
14
+ */
15
+ export declare function getCommandConfiguredTools(projectPath: string): string[];
16
+ /**
17
+ * Returns tools that are configured via either skills or commands.
18
+ */
19
+ export declare function getConfiguredToolsForProfileSync(projectPath: string): string[];
20
+ /**
21
+ * Detects if a single tool has profile/delivery drift against the desired state.
22
+ *
23
+ * This function covers:
24
+ * - required artifacts missing for selected workflows
25
+ * - artifacts that should not exist for the selected delivery mode
26
+ * - artifacts for workflows that were deselected from the current profile
27
+ */
28
+ export declare function hasToolProfileOrDeliveryDrift(projectPath: string, toolId: string, desiredWorkflows: readonly string[], delivery: Delivery): boolean;
29
+ /**
30
+ * Returns configured tools that currently need a profile/delivery sync.
31
+ */
32
+ export declare function getToolsNeedingProfileSync(projectPath: string, desiredWorkflows: readonly string[], delivery: Delivery, configuredTools?: readonly string[]): string[];
33
+ /**
34
+ * Detects whether the current project has any profile/delivery drift.
35
+ */
36
+ export declare function hasProjectConfigDrift(projectPath: string, desiredWorkflows: readonly string[], delivery: Delivery): boolean;
37
+ export {};
38
+ //# sourceMappingURL=profile-sync-drift.d.ts.map
@@ -0,0 +1,200 @@
1
+ import path from 'path';
2
+ import * as fs from 'fs';
3
+ import { AI_TOOLS } from './config.js';
4
+ import { ALL_WORKFLOWS } from './profiles.js';
5
+ import { CommandAdapterRegistry } from './command-generation/index.js';
6
+ import { COMMAND_IDS, getConfiguredTools } from './shared/index.js';
7
+ /**
8
+ * Maps workflow IDs to their skill directory names.
9
+ */
10
+ export const WORKFLOW_TO_SKILL_DIR = {
11
+ 'explore': 'openspec-explore',
12
+ 'new': 'openspec-new-change',
13
+ 'continue': 'openspec-continue-change',
14
+ 'apply': 'openspec-apply-change',
15
+ 'ff': 'openspec-ff-change',
16
+ 'sync': 'openspec-sync-specs',
17
+ 'archive': 'openspec-archive-change',
18
+ 'bulk-archive': 'openspec-bulk-archive-change',
19
+ 'verify': 'openspec-verify-change',
20
+ 'onboard': 'openspec-onboard',
21
+ 'propose': 'openspec-propose',
22
+ };
23
+ function toKnownWorkflows(workflows) {
24
+ return workflows.filter((workflow) => ALL_WORKFLOWS.includes(workflow));
25
+ }
26
+ /**
27
+ * Checks whether a tool has at least one generated OpenSpec command file.
28
+ */
29
+ export function toolHasAnyConfiguredCommand(projectPath, toolId) {
30
+ const adapter = CommandAdapterRegistry.get(toolId);
31
+ if (!adapter)
32
+ return false;
33
+ for (const commandId of COMMAND_IDS) {
34
+ const cmdPath = adapter.getFilePath(commandId);
35
+ const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
36
+ if (fs.existsSync(fullPath)) {
37
+ return true;
38
+ }
39
+ }
40
+ return false;
41
+ }
42
+ /**
43
+ * Returns tools with at least one generated command file on disk.
44
+ */
45
+ export function getCommandConfiguredTools(projectPath) {
46
+ return AI_TOOLS
47
+ .filter((tool) => {
48
+ if (!tool.skillsDir)
49
+ return false;
50
+ const toolDir = path.join(projectPath, tool.skillsDir);
51
+ try {
52
+ return fs.statSync(toolDir).isDirectory();
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ })
58
+ .map((tool) => tool.value)
59
+ .filter((toolId) => toolHasAnyConfiguredCommand(projectPath, toolId));
60
+ }
61
+ /**
62
+ * Returns tools that are configured via either skills or commands.
63
+ */
64
+ export function getConfiguredToolsForProfileSync(projectPath) {
65
+ const skillConfigured = getConfiguredTools(projectPath);
66
+ const commandConfigured = getCommandConfiguredTools(projectPath);
67
+ return [...new Set([...skillConfigured, ...commandConfigured])];
68
+ }
69
+ /**
70
+ * Detects if a single tool has profile/delivery drift against the desired state.
71
+ *
72
+ * This function covers:
73
+ * - required artifacts missing for selected workflows
74
+ * - artifacts that should not exist for the selected delivery mode
75
+ * - artifacts for workflows that were deselected from the current profile
76
+ */
77
+ export function hasToolProfileOrDeliveryDrift(projectPath, toolId, desiredWorkflows, delivery) {
78
+ const tool = AI_TOOLS.find((t) => t.value === toolId);
79
+ if (!tool?.skillsDir)
80
+ return false;
81
+ const knownDesiredWorkflows = toKnownWorkflows(desiredWorkflows);
82
+ const desiredWorkflowSet = new Set(knownDesiredWorkflows);
83
+ const skillsDir = path.join(projectPath, tool.skillsDir, 'skills');
84
+ const adapter = CommandAdapterRegistry.get(toolId);
85
+ const shouldGenerateSkills = delivery !== 'commands';
86
+ const shouldGenerateCommands = delivery !== 'skills';
87
+ if (shouldGenerateSkills) {
88
+ for (const workflow of knownDesiredWorkflows) {
89
+ const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
90
+ const skillFile = path.join(skillsDir, dirName, 'SKILL.md');
91
+ if (!fs.existsSync(skillFile)) {
92
+ return true;
93
+ }
94
+ }
95
+ // Deselecting workflows in a profile should trigger sync.
96
+ for (const workflow of ALL_WORKFLOWS) {
97
+ if (desiredWorkflowSet.has(workflow))
98
+ continue;
99
+ const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
100
+ const skillDir = path.join(skillsDir, dirName);
101
+ if (fs.existsSync(skillDir)) {
102
+ return true;
103
+ }
104
+ }
105
+ }
106
+ else {
107
+ for (const workflow of ALL_WORKFLOWS) {
108
+ const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
109
+ const skillDir = path.join(skillsDir, dirName);
110
+ if (fs.existsSync(skillDir)) {
111
+ return true;
112
+ }
113
+ }
114
+ }
115
+ if (shouldGenerateCommands && adapter) {
116
+ for (const workflow of knownDesiredWorkflows) {
117
+ const cmdPath = adapter.getFilePath(workflow);
118
+ const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
119
+ if (!fs.existsSync(fullPath)) {
120
+ return true;
121
+ }
122
+ }
123
+ // Deselecting workflows in a profile should trigger sync.
124
+ for (const workflow of ALL_WORKFLOWS) {
125
+ if (desiredWorkflowSet.has(workflow))
126
+ continue;
127
+ const cmdPath = adapter.getFilePath(workflow);
128
+ const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
129
+ if (fs.existsSync(fullPath)) {
130
+ return true;
131
+ }
132
+ }
133
+ }
134
+ else if (!shouldGenerateCommands && adapter) {
135
+ for (const workflow of ALL_WORKFLOWS) {
136
+ const cmdPath = adapter.getFilePath(workflow);
137
+ const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
138
+ if (fs.existsSync(fullPath)) {
139
+ return true;
140
+ }
141
+ }
142
+ }
143
+ return false;
144
+ }
145
+ /**
146
+ * Returns configured tools that currently need a profile/delivery sync.
147
+ */
148
+ export function getToolsNeedingProfileSync(projectPath, desiredWorkflows, delivery, configuredTools) {
149
+ const tools = configuredTools ? [...new Set(configuredTools)] : getConfiguredToolsForProfileSync(projectPath);
150
+ return tools.filter((toolId) => hasToolProfileOrDeliveryDrift(projectPath, toolId, desiredWorkflows, delivery));
151
+ }
152
+ function getInstalledWorkflowsForTool(projectPath, toolId, options) {
153
+ const tool = AI_TOOLS.find((t) => t.value === toolId);
154
+ if (!tool?.skillsDir)
155
+ return [];
156
+ const installed = new Set();
157
+ const skillsDir = path.join(projectPath, tool.skillsDir, 'skills');
158
+ if (options.includeSkills) {
159
+ for (const workflow of ALL_WORKFLOWS) {
160
+ const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
161
+ const skillFile = path.join(skillsDir, dirName, 'SKILL.md');
162
+ if (fs.existsSync(skillFile)) {
163
+ installed.add(workflow);
164
+ }
165
+ }
166
+ }
167
+ if (options.includeCommands) {
168
+ const adapter = CommandAdapterRegistry.get(toolId);
169
+ if (adapter) {
170
+ for (const workflow of ALL_WORKFLOWS) {
171
+ const cmdPath = adapter.getFilePath(workflow);
172
+ const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
173
+ if (fs.existsSync(fullPath)) {
174
+ installed.add(workflow);
175
+ }
176
+ }
177
+ }
178
+ }
179
+ return [...installed];
180
+ }
181
+ /**
182
+ * Detects whether the current project has any profile/delivery drift.
183
+ */
184
+ export function hasProjectConfigDrift(projectPath, desiredWorkflows, delivery) {
185
+ const configuredTools = getConfiguredToolsForProfileSync(projectPath);
186
+ if (getToolsNeedingProfileSync(projectPath, desiredWorkflows, delivery, configuredTools).length > 0) {
187
+ return true;
188
+ }
189
+ const desiredSet = new Set(toKnownWorkflows(desiredWorkflows));
190
+ const includeSkills = delivery !== 'commands';
191
+ const includeCommands = delivery !== 'skills';
192
+ for (const toolId of configuredTools) {
193
+ const installed = getInstalledWorkflowsForTool(projectPath, toolId, { includeSkills, includeCommands });
194
+ if (installed.some((workflow) => !desiredSet.has(workflow))) {
195
+ return true;
196
+ }
197
+ }
198
+ return false;
199
+ }
200
+ //# sourceMappingURL=profile-sync-drift.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Profile System
3
+ *
4
+ * Defines workflow profiles that control which workflows are installed.
5
+ * Profiles determine WHICH workflows; delivery (in global config) determines HOW.
6
+ */
7
+ import type { Profile } from './global-config.js';
8
+ /**
9
+ * Core workflows included in the 'core' profile.
10
+ * These provide the streamlined experience for new users.
11
+ */
12
+ export declare const CORE_WORKFLOWS: readonly ["propose", "explore", "apply", "archive"];
13
+ /**
14
+ * All available workflows in the system.
15
+ */
16
+ export declare const ALL_WORKFLOWS: readonly ["propose", "explore", "new", "continue", "apply", "ff", "sync", "archive", "bulk-archive", "verify", "onboard"];
17
+ export type WorkflowId = (typeof ALL_WORKFLOWS)[number];
18
+ export type CoreWorkflowId = (typeof CORE_WORKFLOWS)[number];
19
+ /**
20
+ * Resolves which workflows should be active for a given profile configuration.
21
+ *
22
+ * - 'core' profile always returns CORE_WORKFLOWS
23
+ * - 'custom' profile returns the provided customWorkflows, or empty array if not provided
24
+ */
25
+ export declare function getProfileWorkflows(profile: Profile, customWorkflows?: string[]): readonly string[];
26
+ //# sourceMappingURL=profiles.d.ts.map
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Profile System
3
+ *
4
+ * Defines workflow profiles that control which workflows are installed.
5
+ * Profiles determine WHICH workflows; delivery (in global config) determines HOW.
6
+ */
7
+ /**
8
+ * Core workflows included in the 'core' profile.
9
+ * These provide the streamlined experience for new users.
10
+ */
11
+ export const CORE_WORKFLOWS = ['propose', 'explore', 'apply', 'archive'];
12
+ /**
13
+ * All available workflows in the system.
14
+ */
15
+ export const ALL_WORKFLOWS = [
16
+ 'propose',
17
+ 'explore',
18
+ 'new',
19
+ 'continue',
20
+ 'apply',
21
+ 'ff',
22
+ 'sync',
23
+ 'archive',
24
+ 'bulk-archive',
25
+ 'verify',
26
+ 'onboard',
27
+ ];
28
+ /**
29
+ * Resolves which workflows should be active for a given profile configuration.
30
+ *
31
+ * - 'core' profile always returns CORE_WORKFLOWS
32
+ * - 'custom' profile returns the provided customWorkflows, or empty array if not provided
33
+ */
34
+ export function getProfileWorkflows(profile, customWorkflows) {
35
+ if (profile === 'custom') {
36
+ return customWorkflows ?? [];
37
+ }
38
+ return CORE_WORKFLOWS;
39
+ }
40
+ //# sourceMappingURL=profiles.js.map
@@ -3,6 +3,6 @@
3
3
  *
4
4
  * Common code shared between init and update commands.
5
5
  */
6
- export { SKILL_NAMES, type SkillName, type ToolSkillStatus, type ToolVersionStatus, getToolsWithSkillsDir, getToolSkillStatus, getToolStates, extractGeneratedByVersion, getToolVersionStatus, getConfiguredTools, getAllToolVersionStatus, } from './tool-detection.js';
6
+ export { SKILL_NAMES, type SkillName, COMMAND_IDS, type CommandId, type ToolSkillStatus, type ToolVersionStatus, getToolsWithSkillsDir, getToolSkillStatus, getToolStates, extractGeneratedByVersion, getToolVersionStatus, getConfiguredTools, getAllToolVersionStatus, } from './tool-detection.js';
7
7
  export { type SkillTemplateEntry, type CommandTemplateEntry, getSkillTemplates, getCommandTemplates, getCommandContents, generateSkillContent, } from './skill-generation.js';
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -3,6 +3,6 @@
3
3
  *
4
4
  * Common code shared between init and update commands.
5
5
  */
6
- export { SKILL_NAMES, getToolsWithSkillsDir, getToolSkillStatus, getToolStates, extractGeneratedByVersion, getToolVersionStatus, getConfiguredTools, getAllToolVersionStatus, } from './tool-detection.js';
6
+ export { SKILL_NAMES, COMMAND_IDS, getToolsWithSkillsDir, getToolSkillStatus, getToolStates, extractGeneratedByVersion, getToolVersionStatus, getConfiguredTools, getAllToolVersionStatus, } from './tool-detection.js';
7
7
  export { getSkillTemplates, getCommandTemplates, getCommandContents, generateSkillContent, } from './skill-generation.js';
8
8
  //# sourceMappingURL=index.js.map
@@ -6,11 +6,12 @@
6
6
  import { getOpsxExploreCommandTemplate, type SkillTemplate } from '../templates/skill-templates.js';
7
7
  import type { CommandContent } from '../command-generation/index.js';
8
8
  /**
9
- * Skill template with directory name mapping.
9
+ * Skill template with directory name and workflow ID mapping.
10
10
  */
11
11
  export interface SkillTemplateEntry {
12
12
  template: SkillTemplate;
13
13
  dirName: string;
14
+ workflowId: string;
14
15
  }
15
16
  /**
16
17
  * Command template with ID mapping.
@@ -20,17 +21,23 @@ export interface CommandTemplateEntry {
20
21
  id: string;
21
22
  }
22
23
  /**
23
- * Gets all skill templates with their directory names.
24
+ * Gets skill templates with their directory names, optionally filtered by workflow IDs.
25
+ *
26
+ * @param workflowFilter - If provided, only return templates whose workflowId is in this array
24
27
  */
25
- export declare function getSkillTemplates(): SkillTemplateEntry[];
28
+ export declare function getSkillTemplates(workflowFilter?: readonly string[]): SkillTemplateEntry[];
26
29
  /**
27
- * Gets all command templates with their IDs.
30
+ * Gets command templates with their IDs, optionally filtered by workflow IDs.
31
+ *
32
+ * @param workflowFilter - If provided, only return templates whose id is in this array
28
33
  */
29
- export declare function getCommandTemplates(): CommandTemplateEntry[];
34
+ export declare function getCommandTemplates(workflowFilter?: readonly string[]): CommandTemplateEntry[];
30
35
  /**
31
- * Converts command templates to CommandContent array.
36
+ * Converts command templates to CommandContent array, optionally filtered by workflow IDs.
37
+ *
38
+ * @param workflowFilter - If provided, only return contents whose id is in this array
32
39
  */
33
- export declare function getCommandContents(): CommandContent[];
40
+ export declare function getCommandContents(workflowFilter?: readonly string[]): CommandContent[];
34
41
  /**
35
42
  * Generates skill file content with YAML frontmatter.
36
43
  *
@@ -3,29 +3,38 @@
3
3
  *
4
4
  * Shared utilities for generating skill and command files.
5
5
  */
6
- import { getExploreSkillTemplate, getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getSyncSpecsSkillTemplate, getArchiveChangeSkillTemplate, getBulkArchiveChangeSkillTemplate, getVerifyChangeSkillTemplate, getOnboardSkillTemplate, getOpsxExploreCommandTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate, getOpsxFfCommandTemplate, getOpsxSyncCommandTemplate, getOpsxArchiveCommandTemplate, getOpsxBulkArchiveCommandTemplate, getOpsxVerifyCommandTemplate, getOpsxOnboardCommandTemplate, } from '../templates/skill-templates.js';
6
+ import { getExploreSkillTemplate, getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getSyncSpecsSkillTemplate, getArchiveChangeSkillTemplate, getBulkArchiveChangeSkillTemplate, getVerifyChangeSkillTemplate, getOnboardSkillTemplate, getOpsxProposeSkillTemplate, getOpsxExploreCommandTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate, getOpsxFfCommandTemplate, getOpsxSyncCommandTemplate, getOpsxArchiveCommandTemplate, getOpsxBulkArchiveCommandTemplate, getOpsxVerifyCommandTemplate, getOpsxOnboardCommandTemplate, getOpsxProposeCommandTemplate, } from '../templates/skill-templates.js';
7
7
  /**
8
- * Gets all skill templates with their directory names.
8
+ * Gets skill templates with their directory names, optionally filtered by workflow IDs.
9
+ *
10
+ * @param workflowFilter - If provided, only return templates whose workflowId is in this array
9
11
  */
10
- export function getSkillTemplates() {
11
- return [
12
- { template: getExploreSkillTemplate(), dirName: 'openspec-explore' },
13
- { template: getNewChangeSkillTemplate(), dirName: 'openspec-new-change' },
14
- { template: getContinueChangeSkillTemplate(), dirName: 'openspec-continue-change' },
15
- { template: getApplyChangeSkillTemplate(), dirName: 'openspec-apply-change' },
16
- { template: getFfChangeSkillTemplate(), dirName: 'openspec-ff-change' },
17
- { template: getSyncSpecsSkillTemplate(), dirName: 'openspec-sync-specs' },
18
- { template: getArchiveChangeSkillTemplate(), dirName: 'openspec-archive-change' },
19
- { template: getBulkArchiveChangeSkillTemplate(), dirName: 'openspec-bulk-archive-change' },
20
- { template: getVerifyChangeSkillTemplate(), dirName: 'openspec-verify-change' },
21
- { template: getOnboardSkillTemplate(), dirName: 'openspec-onboard' },
12
+ export function getSkillTemplates(workflowFilter) {
13
+ const all = [
14
+ { template: getExploreSkillTemplate(), dirName: 'openspec-explore', workflowId: 'explore' },
15
+ { template: getNewChangeSkillTemplate(), dirName: 'openspec-new-change', workflowId: 'new' },
16
+ { template: getContinueChangeSkillTemplate(), dirName: 'openspec-continue-change', workflowId: 'continue' },
17
+ { template: getApplyChangeSkillTemplate(), dirName: 'openspec-apply-change', workflowId: 'apply' },
18
+ { template: getFfChangeSkillTemplate(), dirName: 'openspec-ff-change', workflowId: 'ff' },
19
+ { template: getSyncSpecsSkillTemplate(), dirName: 'openspec-sync-specs', workflowId: 'sync' },
20
+ { template: getArchiveChangeSkillTemplate(), dirName: 'openspec-archive-change', workflowId: 'archive' },
21
+ { template: getBulkArchiveChangeSkillTemplate(), dirName: 'openspec-bulk-archive-change', workflowId: 'bulk-archive' },
22
+ { template: getVerifyChangeSkillTemplate(), dirName: 'openspec-verify-change', workflowId: 'verify' },
23
+ { template: getOnboardSkillTemplate(), dirName: 'openspec-onboard', workflowId: 'onboard' },
24
+ { template: getOpsxProposeSkillTemplate(), dirName: 'openspec-propose', workflowId: 'propose' },
22
25
  ];
26
+ if (!workflowFilter)
27
+ return all;
28
+ const filterSet = new Set(workflowFilter);
29
+ return all.filter(entry => filterSet.has(entry.workflowId));
23
30
  }
24
31
  /**
25
- * Gets all command templates with their IDs.
32
+ * Gets command templates with their IDs, optionally filtered by workflow IDs.
33
+ *
34
+ * @param workflowFilter - If provided, only return templates whose id is in this array
26
35
  */
27
- export function getCommandTemplates() {
28
- return [
36
+ export function getCommandTemplates(workflowFilter) {
37
+ const all = [
29
38
  { template: getOpsxExploreCommandTemplate(), id: 'explore' },
30
39
  { template: getOpsxNewCommandTemplate(), id: 'new' },
31
40
  { template: getOpsxContinueCommandTemplate(), id: 'continue' },
@@ -36,13 +45,20 @@ export function getCommandTemplates() {
36
45
  { template: getOpsxBulkArchiveCommandTemplate(), id: 'bulk-archive' },
37
46
  { template: getOpsxVerifyCommandTemplate(), id: 'verify' },
38
47
  { template: getOpsxOnboardCommandTemplate(), id: 'onboard' },
48
+ { template: getOpsxProposeCommandTemplate(), id: 'propose' },
39
49
  ];
50
+ if (!workflowFilter)
51
+ return all;
52
+ const filterSet = new Set(workflowFilter);
53
+ return all.filter(entry => filterSet.has(entry.id));
40
54
  }
41
55
  /**
42
- * Converts command templates to CommandContent array.
56
+ * Converts command templates to CommandContent array, optionally filtered by workflow IDs.
57
+ *
58
+ * @param workflowFilter - If provided, only return contents whose id is in this array
43
59
  */
44
- export function getCommandContents() {
45
- const commandTemplates = getCommandTemplates();
60
+ export function getCommandContents(workflowFilter) {
61
+ const commandTemplates = getCommandTemplates(workflowFilter);
46
62
  return commandTemplates.map(({ template, id }) => ({
47
63
  id,
48
64
  name: template.name,
@@ -6,17 +6,22 @@
6
6
  /**
7
7
  * Names of skill directories created by openspec init.
8
8
  */
9
- export declare const SKILL_NAMES: readonly ["openspec-explore", "openspec-new-change", "openspec-continue-change", "openspec-apply-change", "openspec-ff-change", "openspec-sync-specs", "openspec-archive-change", "openspec-bulk-archive-change", "openspec-verify-change"];
9
+ export declare const SKILL_NAMES: readonly ["openspec-explore", "openspec-new-change", "openspec-continue-change", "openspec-apply-change", "openspec-ff-change", "openspec-sync-specs", "openspec-archive-change", "openspec-bulk-archive-change", "openspec-verify-change", "openspec-onboard", "openspec-propose"];
10
10
  export type SkillName = (typeof SKILL_NAMES)[number];
11
+ /**
12
+ * IDs of command templates created by openspec init.
13
+ */
14
+ export declare const COMMAND_IDS: readonly ["explore", "new", "continue", "apply", "ff", "sync", "archive", "bulk-archive", "verify", "onboard", "propose"];
15
+ export type CommandId = (typeof COMMAND_IDS)[number];
11
16
  /**
12
17
  * Status of skill configuration for a tool.
13
18
  */
14
19
  export interface ToolSkillStatus {
15
20
  /** Whether the tool has any skills configured */
16
21
  configured: boolean;
17
- /** Whether all 9 skills are configured */
22
+ /** Whether all skills are configured */
18
23
  fullyConfigured: boolean;
19
- /** Number of skills currently configured (0-9) */
24
+ /** Number of skills currently configured */
20
25
  skillCount: number;
21
26
  }
22
27
  /**
@@ -19,6 +19,24 @@ export const SKILL_NAMES = [
19
19
  'openspec-archive-change',
20
20
  'openspec-bulk-archive-change',
21
21
  'openspec-verify-change',
22
+ 'openspec-onboard',
23
+ 'openspec-propose',
24
+ ];
25
+ /**
26
+ * IDs of command templates created by openspec init.
27
+ */
28
+ export const COMMAND_IDS = [
29
+ 'explore',
30
+ 'new',
31
+ 'continue',
32
+ 'apply',
33
+ 'ff',
34
+ 'sync',
35
+ 'archive',
36
+ 'bulk-archive',
37
+ 'verify',
38
+ 'onboard',
39
+ 'propose',
22
40
  ];
23
41
  /**
24
42
  * Gets the list of tools with skillsDir configured.
@@ -4,5 +4,5 @@
4
4
  * The old config file templates (AGENTS.md, project.md, claude-template, etc.)
5
5
  * have been removed. The skill-based workflow uses skill-templates.ts directly.
6
6
  */
7
- export { getExploreSkillTemplate, getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getSyncSpecsSkillTemplate, getArchiveChangeSkillTemplate, getBulkArchiveChangeSkillTemplate, getVerifyChangeSkillTemplate, getOpsxExploreCommandTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate, getOpsxFfCommandTemplate, getOpsxSyncCommandTemplate, getOpsxArchiveCommandTemplate, getOpsxBulkArchiveCommandTemplate, getOpsxVerifyCommandTemplate, } from './skill-templates.js';
7
+ export * from './skill-templates.js';
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -4,6 +4,6 @@
4
4
  * The old config file templates (AGENTS.md, project.md, claude-template, etc.)
5
5
  * have been removed. The skill-based workflow uses skill-templates.ts directly.
6
6
  */
7
- // Re-export skill templates for convenience
8
- export { getExploreSkillTemplate, getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getSyncSpecsSkillTemplate, getArchiveChangeSkillTemplate, getBulkArchiveChangeSkillTemplate, getVerifyChangeSkillTemplate, getOpsxExploreCommandTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate, getOpsxFfCommandTemplate, getOpsxSyncCommandTemplate, getOpsxArchiveCommandTemplate, getOpsxBulkArchiveCommandTemplate, getOpsxVerifyCommandTemplate, } from './skill-templates.js';
7
+ // Re-export all skill templates and related types through the compatibility facade.
8
+ export * from './skill-templates.js';
9
9
  //# sourceMappingURL=index.js.map
@@ -1,122 +1,19 @@
1
1
  /**
2
2
  * Agent Skill Templates
3
3
  *
4
- * Templates for generating Agent Skills compatible with:
5
- * - Claude Code
6
- * - Cursor (Settings Rules → Import Settings)
7
- * - Windsurf
8
- * - Other Agent Skills-compatible editors
9
- */
10
- export interface SkillTemplate {
11
- name: string;
12
- description: string;
13
- instructions: string;
14
- license?: string;
15
- compatibility?: string;
16
- metadata?: Record<string, string>;
17
- }
18
- /**
19
- * Template for openspec-explore skill
20
- * Explore mode - adaptive thinking partner for exploring ideas and problems
21
- */
22
- export declare function getExploreSkillTemplate(): SkillTemplate;
23
- /**
24
- * Template for openspec-new-change skill
25
- * Based on /opsx:new command
26
- */
27
- export declare function getNewChangeSkillTemplate(): SkillTemplate;
28
- /**
29
- * Template for openspec-continue-change skill
30
- * Based on /opsx:continue command
31
- */
32
- export declare function getContinueChangeSkillTemplate(): SkillTemplate;
33
- /**
34
- * Template for openspec-apply-change skill
35
- * For implementing tasks from a completed (or in-progress) change
36
- */
37
- export declare function getApplyChangeSkillTemplate(): SkillTemplate;
38
- /**
39
- * Template for openspec-ff-change skill
40
- * Fast-forward through artifact creation
41
- */
42
- export declare function getFfChangeSkillTemplate(): SkillTemplate;
43
- /**
44
- * Template for openspec-sync-specs skill
45
- * For syncing delta specs from a change to main specs (agent-driven)
46
- */
47
- export declare function getSyncSpecsSkillTemplate(): SkillTemplate;
48
- /**
49
- * Template for openspec-onboard skill
50
- * Guided onboarding through the complete OpenSpec workflow
51
- */
52
- export declare function getOnboardSkillTemplate(): SkillTemplate;
53
- export interface CommandTemplate {
54
- name: string;
55
- description: string;
56
- category: string;
57
- tags: string[];
58
- content: string;
59
- }
60
- /**
61
- * Template for /opsx:explore slash command
62
- * Explore mode - adaptive thinking partner
63
- */
64
- export declare function getOpsxExploreCommandTemplate(): CommandTemplate;
65
- /**
66
- * Template for /opsx:new slash command
67
- */
68
- export declare function getOpsxNewCommandTemplate(): CommandTemplate;
69
- /**
70
- * Template for /opsx:continue slash command
71
- */
72
- export declare function getOpsxContinueCommandTemplate(): CommandTemplate;
73
- /**
74
- * Template for /opsx:apply slash command
75
- */
76
- export declare function getOpsxApplyCommandTemplate(): CommandTemplate;
77
- /**
78
- * Template for /opsx:ff slash command
79
- */
80
- export declare function getOpsxFfCommandTemplate(): CommandTemplate;
81
- /**
82
- * Template for openspec-archive-change skill
83
- * For archiving completed changes in the experimental workflow
84
- */
85
- export declare function getArchiveChangeSkillTemplate(): SkillTemplate;
86
- /**
87
- * Template for openspec-bulk-archive-change skill
88
- * For archiving multiple completed changes at once
89
- */
90
- export declare function getBulkArchiveChangeSkillTemplate(): SkillTemplate;
91
- /**
92
- * Template for /opsx:sync slash command
93
- */
94
- export declare function getOpsxSyncCommandTemplate(): CommandTemplate;
95
- /**
96
- * Template for openspec-verify-change skill
97
- * For verifying implementation matches change artifacts before archiving
98
- */
99
- export declare function getVerifyChangeSkillTemplate(): SkillTemplate;
100
- /**
101
- * Template for /opsx:archive slash command
102
- */
103
- export declare function getOpsxArchiveCommandTemplate(): CommandTemplate;
104
- /**
105
- * Template for /opsx:onboard slash command
106
- * Guided onboarding through the complete OpenSpec workflow
107
- */
108
- export declare function getOpsxOnboardCommandTemplate(): CommandTemplate;
109
- /**
110
- * Template for /opsx:bulk-archive slash command
111
- */
112
- export declare function getOpsxBulkArchiveCommandTemplate(): CommandTemplate;
113
- /**
114
- * Template for /opsx:verify slash command
115
- */
116
- export declare function getOpsxVerifyCommandTemplate(): CommandTemplate;
117
- /**
118
- * Template for feedback skill
119
- * For collecting and submitting user feedback with context enrichment
120
- */
121
- export declare function getFeedbackSkillTemplate(): SkillTemplate;
4
+ * Compatibility facade that re-exports split workflow template modules.
5
+ */
6
+ export type { SkillTemplate, CommandTemplate } from './types.js';
7
+ export { getExploreSkillTemplate, getOpsxExploreCommandTemplate } from './workflows/explore.js';
8
+ export { getNewChangeSkillTemplate, getOpsxNewCommandTemplate } from './workflows/new-change.js';
9
+ export { getContinueChangeSkillTemplate, getOpsxContinueCommandTemplate } from './workflows/continue-change.js';
10
+ export { getApplyChangeSkillTemplate, getOpsxApplyCommandTemplate } from './workflows/apply-change.js';
11
+ export { getFfChangeSkillTemplate, getOpsxFfCommandTemplate } from './workflows/ff-change.js';
12
+ export { getSyncSpecsSkillTemplate, getOpsxSyncCommandTemplate } from './workflows/sync-specs.js';
13
+ export { getArchiveChangeSkillTemplate, getOpsxArchiveCommandTemplate } from './workflows/archive-change.js';
14
+ export { getBulkArchiveChangeSkillTemplate, getOpsxBulkArchiveCommandTemplate } from './workflows/bulk-archive-change.js';
15
+ export { getVerifyChangeSkillTemplate, getOpsxVerifyCommandTemplate } from './workflows/verify-change.js';
16
+ export { getOnboardSkillTemplate, getOpsxOnboardCommandTemplate } from './workflows/onboard.js';
17
+ export { getOpsxProposeSkillTemplate, getOpsxProposeCommandTemplate } from './workflows/propose.js';
18
+ export { getFeedbackSkillTemplate } from './workflows/feedback.js';
122
19
  //# sourceMappingURL=skill-templates.d.ts.map