synarcx 0.2.0 → 0.3.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 (51) hide show
  1. package/README.md +237 -43
  2. package/dist/commands/config.js +7 -6
  3. package/dist/core/command-generation/adapters/bob.js +7 -20
  4. package/dist/core/command-generation/adapters/claude.js +9 -29
  5. package/dist/core/command-generation/adapters/cursor.js +9 -22
  6. package/dist/core/command-generation/adapters/pi.js +6 -19
  7. package/dist/core/command-generation/adapters/windsurf.js +9 -29
  8. package/dist/core/command-generation/yaml-utils.d.ts +3 -0
  9. package/dist/core/command-generation/yaml-utils.js +12 -0
  10. package/dist/core/completions/installers/bash-installer.d.ts +1 -0
  11. package/dist/core/completions/installers/bash-installer.js +14 -3
  12. package/dist/core/completions/installers/powershell-installer.d.ts +1 -0
  13. package/dist/core/completions/installers/powershell-installer.js +18 -10
  14. package/dist/core/config.js +0 -3
  15. package/dist/core/index.js +1 -1
  16. package/dist/core/init.d.ts +0 -2
  17. package/dist/core/init.js +27 -77
  18. package/dist/core/migration.js +1 -2
  19. package/dist/core/profile-sync-drift.d.ts +0 -7
  20. package/dist/core/profile-sync-drift.js +2 -17
  21. package/dist/core/profiles.d.ts +0 -11
  22. package/dist/core/profiles.js +1 -20
  23. package/dist/core/shared/artifact-cleanup.d.ts +5 -0
  24. package/dist/core/shared/artifact-cleanup.js +89 -0
  25. package/dist/core/shared/skill-generation.js +3 -3
  26. package/dist/core/shared/tool-detection.d.ts +4 -10
  27. package/dist/core/shared/tool-detection.js +3 -31
  28. package/dist/core/shared/workflow-registry.d.ts +40 -0
  29. package/dist/core/shared/workflow-registry.js +19 -0
  30. package/dist/core/templates/skill-templates.d.ts +1 -0
  31. package/dist/core/templates/skill-templates.js +1 -0
  32. package/dist/core/templates/types.d.ts +7 -0
  33. package/dist/core/templates/types.js +9 -1
  34. package/dist/core/templates/workflows/analyze.js +84 -84
  35. package/dist/core/templates/workflows/apply-change.js +291 -291
  36. package/dist/core/templates/workflows/archive-change.js +254 -254
  37. package/dist/core/templates/workflows/clarify.js +115 -93
  38. package/dist/core/templates/workflows/debug.js +100 -100
  39. package/dist/core/templates/workflows/explore.js +462 -462
  40. package/dist/core/templates/workflows/propose.js +199 -199
  41. package/dist/core/templates/workflows/quick.js +112 -112
  42. package/dist/core/templates/workflows/refactor.js +109 -109
  43. package/dist/core/templates/workflows/review.d.ts +4 -0
  44. package/dist/core/templates/workflows/review.js +293 -0
  45. package/dist/core/templates/workflows/sync.js +225 -148
  46. package/dist/core/update.d.ts +1 -21
  47. package/dist/core/update.js +18 -117
  48. package/dist/core/view.js +8 -8
  49. package/dist/core/workspace/open-surface.d.ts +2 -2
  50. package/dist/core/workspace/open-surface.js +13 -13
  51. package/package.json +84 -76
@@ -9,6 +9,7 @@ export declare class PowerShellInstaller {
9
9
  * Markers for PowerShell profile configuration management
10
10
  */
11
11
  private readonly PROFILE_MARKERS;
12
+ private readonly LEGACY_MARKERS;
12
13
  constructor(homeDir?: string);
13
14
  /**
14
15
  * Detect the encoding of a file by inspecting its BOM (Byte Order Mark).
@@ -11,6 +11,10 @@ export class PowerShellInstaller {
11
11
  * Markers for PowerShell profile configuration management
12
12
  */
13
13
  PROFILE_MARKERS = {
14
+ start: '# SYNARCX:START',
15
+ end: '# SYNARCX:END',
16
+ };
17
+ LEGACY_MARKERS = {
14
18
  start: '# OPENSPEC:START',
15
19
  end: '# OPENSPEC:END',
16
20
  };
@@ -107,7 +111,7 @@ export class PowerShellInstaller {
107
111
  getInstallationPath() {
108
112
  const profilePath = this.getProfilePath();
109
113
  const profileDir = path.dirname(profilePath);
110
- return path.join(profileDir, 'OpenSpecCompletion.ps1');
114
+ return path.join(profileDir, 'SynArcXCompletion.ps1');
111
115
  }
112
116
  /**
113
117
  * Backup an existing completion file if it exists
@@ -182,15 +186,15 @@ export class PowerShellInstaller {
182
186
  if (profileContent.includes(scriptLine)) {
183
187
  continue; // Already configured, skip
184
188
  }
185
- // Add OpenSpec completion configuration with markers
186
- const openspecBlock = [
189
+ // Add synarcx completion configuration with markers
190
+ const synarcxBlock = [
187
191
  '',
188
- '# OPENSPEC:START - synarcx completion (managed block, do not edit manually)',
192
+ this.PROFILE_MARKERS.start + ' - synarcx completion (managed block, do not edit manually)',
189
193
  scriptLine,
190
- '# OPENSPEC:END',
194
+ this.PROFILE_MARKERS.end,
191
195
  '',
192
196
  ].join('\n');
193
- const newContent = profileContent + openspecBlock;
197
+ const newContent = profileContent + synarcxBlock;
194
198
  await this.writeProfileFile(profilePath, newContent, fileEncoding, fileBom);
195
199
  anyConfigured = true;
196
200
  }
@@ -229,12 +233,16 @@ export class PowerShellInstaller {
229
233
  console.warn(`Warning: Could not read ${profilePath}: ${err?.message ?? String(err)}`);
230
234
  continue;
231
235
  }
232
- // Remove OPENSPEC:START -> OPENSPEC:END block
233
- const startMarker = '# OPENSPEC:START';
234
- const endMarker = '# OPENSPEC:END';
236
+ // Determine which markers to use (check new first, fall back to legacy)
237
+ const startMarker = profileContent.includes(this.PROFILE_MARKERS.start)
238
+ ? this.PROFILE_MARKERS.start
239
+ : this.LEGACY_MARKERS.start;
240
+ const endMarker = profileContent.includes(this.PROFILE_MARKERS.end)
241
+ ? this.PROFILE_MARKERS.end
242
+ : this.LEGACY_MARKERS.end;
235
243
  const startIndex = profileContent.indexOf(startMarker);
236
244
  if (startIndex === -1) {
237
- continue; // No OpenSpec block found
245
+ continue; // No synarcx block found
238
246
  }
239
247
  const endIndex = profileContent.indexOf(endMarker, startIndex);
240
248
  if (endIndex === -1) {
@@ -11,7 +11,6 @@ export const AI_TOOLS = [
11
11
  { name: 'Claude Code', value: 'claude', available: true, successLabel: 'Claude Code', skillsDir: '.claude', hasCommands: true },
12
12
  { name: 'Cline', value: 'cline', available: true, successLabel: 'Cline', skillsDir: '.cline' },
13
13
  { name: 'Codex', value: 'codex', available: true, successLabel: 'Codex', skillsDir: '.codex' },
14
- { name: 'ForgeCode', value: 'forgecode', available: true, successLabel: 'ForgeCode', skillsDir: '.forge' },
15
14
  { name: 'CodeBuddy Code (CLI)', value: 'codebuddy', available: true, successLabel: 'CodeBuddy Code', skillsDir: '.codebuddy' },
16
15
  { name: 'Continue', value: 'continue', available: true, successLabel: 'Continue (VS Code / JetBrains / Cli)', skillsDir: '.continue' },
17
16
  { name: 'CoStrict', value: 'costrict', available: true, successLabel: 'CoStrict', skillsDir: '.cospec' },
@@ -23,7 +22,6 @@ export const AI_TOOLS = [
23
22
  { name: 'iFlow', value: 'iflow', available: true, successLabel: 'iFlow', skillsDir: '.iflow' },
24
23
  { name: 'Junie', value: 'junie', available: true, successLabel: 'Junie', skillsDir: '.junie' },
25
24
  { name: 'Kilo Code', value: 'kilocode', available: true, successLabel: 'Kilo Code', skillsDir: '.kilocode' },
26
- { name: 'Kimi CLI', value: 'kimi', available: true, successLabel: 'Kimi CLI', skillsDir: '.kimi' },
27
25
  { name: 'Kiro', value: 'kiro', available: true, successLabel: 'Kiro', skillsDir: '.kiro' },
28
26
  { name: 'OpenCode', value: 'opencode', available: true, successLabel: 'OpenCode', skillsDir: '.opencode', hasCommands: true },
29
27
  { name: 'Pi', value: 'pi', available: true, successLabel: 'Pi', skillsDir: '.pi' },
@@ -31,7 +29,6 @@ export const AI_TOOLS = [
31
29
  { name: 'Lingma', value: 'lingma', available: true, successLabel: 'Lingma', skillsDir: '.lingma' },
32
30
  { name: 'Qwen Code', value: 'qwen', available: true, successLabel: 'Qwen Code', skillsDir: '.qwen' },
33
31
  { name: 'RooCode', value: 'roocode', available: true, successLabel: 'RooCode', skillsDir: '.roo' },
34
- { name: 'Trae', value: 'trae', available: true, successLabel: 'Trae', skillsDir: '.trae' },
35
32
  { name: 'Windsurf', value: 'windsurf', available: true, successLabel: 'Windsurf', skillsDir: '.windsurf' },
36
33
  { name: 'AGENTS.md (works with Amp, VS Code, …)', value: 'agents', available: false, successLabel: 'your AGENTS.md-compatible assistant' }
37
34
  ];
@@ -1,4 +1,4 @@
1
- // Core OpenSpec logic will be implemented here
1
+ // Core synarcx logic will be implemented here
2
2
  export { GLOBAL_CONFIG_DIR_NAME, GLOBAL_CONFIG_FILE_NAME, GLOBAL_DATA_DIR_NAME, getGlobalConfigDir, getGlobalConfigPath, getGlobalConfig, saveGlobalConfig, getGlobalDataDir } from './global-config.js';
3
3
  export * from './workspace/index.js';
4
4
  //# sourceMappingURL=index.js.map
@@ -30,8 +30,6 @@ export declare class InitCommand {
30
30
  private createConfig;
31
31
  private displaySuccessMessage;
32
32
  private startSpinner;
33
- private removeSkillDirs;
34
- private removeCommandFiles;
35
33
  }
36
34
  export {};
37
35
  //# sourceMappingURL=init.d.ts.map
package/dist/core/init.js CHANGED
@@ -19,31 +19,20 @@ import { generateCommands, CommandAdapterRegistry, } from './command-generation/
19
19
  import { detectLegacyArtifacts, cleanupLegacyArtifacts, formatCleanupSummary, formatDetectionSummary, } from './legacy-cleanup.js';
20
20
  import { getToolsWithSkillsDir, getToolStates, getSkillTemplates, getCommandContents, generateSkillContent, } from './shared/index.js';
21
21
  import { getGlobalConfig } from './global-config.js';
22
- import { getProfileWorkflows, ALL_WORKFLOWS } from './profiles.js';
22
+ import { getProfileWorkflows } from './profiles.js';
23
+ import { DEFAULT_SCHEMA } from './shared/workflow-registry.js';
24
+ import { removeSkillDirs, removeCommandFiles } from './shared/artifact-cleanup.js';
23
25
  import { getAvailableTools } from './available-tools.js';
24
26
  import { migrateIfNeeded } from './migration.js';
25
27
  const require = createRequire(import.meta.url);
26
- const { version: SYNC_VERSION } = require('../../package.json');
28
+ const { version: SYNARCX_VERSION } = require('../../package.json');
27
29
  // -----------------------------------------------------------------------------
28
30
  // Constants
29
31
  // -----------------------------------------------------------------------------
30
- const DEFAULT_SCHEMA = 'synarcx';
31
32
  const PROGRESS_SPINNER = {
32
33
  interval: 80,
33
34
  frames: ['░░░', '▒░░', '▒▒░', '▒▒▒', '▓▒▒', '▓▓▒', '▓▓▓', '▒▓▓', '░▒▓'],
34
35
  };
35
- const WORKFLOW_TO_SKILL_DIR = {
36
- 'explore': 'syn-explore',
37
- 'apply': 'syn-apply',
38
- 'archive': 'syn-archive',
39
- 'propose': 'syn-propose',
40
- 'sync': 'syn-sync',
41
- 'clarify': 'syn-clarify',
42
- 'analyze': 'syn-analyze',
43
- 'debug': 'syn-debug',
44
- 'refactor': 'syn-refactor',
45
- 'quick': 'syn-quick',
46
- };
47
36
  // -----------------------------------------------------------------------------
48
37
  // Init Command Class
49
38
  // -----------------------------------------------------------------------------
@@ -60,10 +49,10 @@ export class InitCommand {
60
49
  }
61
50
  async execute(targetPath) {
62
51
  const projectPath = path.resolve(targetPath);
63
- const openspecDir = SYNSPEC_DIR_NAME;
64
- const openspecPath = path.join(projectPath, openspecDir);
52
+ const synspecDir = SYNSPEC_DIR_NAME;
53
+ const synspecPath = path.join(projectPath, synspecDir);
65
54
  // Validation happens silently in the background
66
- const extendMode = await this.validate(projectPath, openspecPath);
55
+ const extendMode = await this.validate(projectPath, synspecPath);
67
56
  // Check for legacy artifacts and handle cleanup
68
57
  await this.handleLegacyCleanup(projectPath, extendMode);
69
58
  // Detect available tools in the project (task 7.1)
@@ -88,19 +77,19 @@ export class InitCommand {
88
77
  // Validate selected tools
89
78
  const validatedTools = this.validateTools(selectedToolIds, toolStates);
90
79
  // Create directory structure and config
91
- await this.createDirectoryStructure(openspecPath, extendMode);
80
+ await this.createDirectoryStructure(synspecPath, extendMode);
92
81
  // Generate skills and commands for each tool
93
82
  const results = await this.generateSkillsAndCommands(projectPath, validatedTools);
94
83
  // Create config.yaml if needed
95
- const configStatus = await this.createConfig(openspecPath, extendMode);
84
+ const configStatus = await this.createConfig(synspecPath, extendMode);
96
85
  // Display success message
97
86
  this.displaySuccessMessage(projectPath, validatedTools, results, configStatus);
98
87
  }
99
88
  // ═══════════════════════════════════════════════════════════
100
89
  // VALIDATION & SETUP
101
90
  // ═══════════════════════════════════════════════════════════
102
- async validate(projectPath, openspecPath) {
103
- const extendMode = await FileSystemUtils.directoryExists(openspecPath);
91
+ async validate(projectPath, synspecPath) {
92
+ const extendMode = await FileSystemUtils.directoryExists(synspecPath);
104
93
  // Check write permissions
105
94
  if (!(await FileSystemUtils.ensureWritePermissions(projectPath))) {
106
95
  throw new Error(`Insufficient permissions to write to ${projectPath}`);
@@ -139,7 +128,7 @@ export class InitCommand {
139
128
  const canPrompt = this.canPromptInteractively();
140
129
  if (this.force || !canPrompt) {
141
130
  // --force flag or non-interactive mode: proceed with cleanup automatically.
142
- // Legacy slash commands are 100% OpenSpec-managed, and config file cleanup
131
+ // Legacy slash commands are 100% synarcx-managed, and config file cleanup
143
132
  // only removes markers (never deletes files), so auto-cleanup is safe.
144
133
  await this.performLegacyCleanup(projectPath, detection);
145
134
  return;
@@ -316,14 +305,14 @@ export class InitCommand {
316
305
  // ═══════════════════════════════════════════════════════════
317
306
  // DIRECTORY STRUCTURE
318
307
  // ═══════════════════════════════════════════════════════════
319
- async createDirectoryStructure(openspecPath, extendMode) {
308
+ async createDirectoryStructure(synspecPath, extendMode) {
320
309
  if (extendMode) {
321
310
  // In extend mode, just ensure directories exist without spinner
322
311
  const directories = [
323
- openspecPath,
324
- path.join(openspecPath, 'specs'),
325
- path.join(openspecPath, 'changes'),
326
- path.join(openspecPath, 'changes', 'archive'),
312
+ synspecPath,
313
+ path.join(synspecPath, 'specs'),
314
+ path.join(synspecPath, 'changes'),
315
+ path.join(synspecPath, 'changes', 'archive'),
327
316
  ];
328
317
  for (const dir of directories) {
329
318
  await FileSystemUtils.createDirectory(dir);
@@ -332,10 +321,10 @@ export class InitCommand {
332
321
  }
333
322
  const spinner = this.startSpinner('Creating synarcx structure...');
334
323
  const directories = [
335
- openspecPath,
336
- path.join(openspecPath, 'specs'),
337
- path.join(openspecPath, 'changes'),
338
- path.join(openspecPath, 'changes', 'archive'),
324
+ synspecPath,
325
+ path.join(synspecPath, 'specs'),
326
+ path.join(synspecPath, 'changes'),
327
+ path.join(synspecPath, 'changes', 'archive'),
339
328
  ];
340
329
  for (const dir of directories) {
341
330
  await FileSystemUtils.createDirectory(dir);
@@ -383,14 +372,14 @@ export class InitCommand {
383
372
  // Generate SKILL.md content with YAML frontmatter including generatedBy
384
373
  // Use hyphen-based command references for tools where filename = command name
385
374
  const transformer = tool.value === 'pi' ? transformToHyphenCommands : undefined;
386
- const skillContent = generateSkillContent(template, SYNC_VERSION, transformer);
375
+ const skillContent = generateSkillContent(template, SYNARCX_VERSION, transformer);
387
376
  // Write the skill file
388
377
  await FileSystemUtils.writeFile(skillFile, skillContent);
389
378
  }
390
379
  }
391
380
  if (!generateSkillsForTool) {
392
381
  const skillsDir = path.join(projectPath, tool.skillsDir, 'skills');
393
- removedSkillCount += await this.removeSkillDirs(skillsDir);
382
+ removedSkillCount += await removeSkillDirs(skillsDir);
394
383
  }
395
384
  // Generate commands if delivery includes commands
396
385
  if (shouldGenerateCommands) {
@@ -407,7 +396,7 @@ export class InitCommand {
407
396
  }
408
397
  }
409
398
  if (!shouldGenerateCommands) {
410
- removedCommandCount += await this.removeCommandFiles(projectPath, tool.value);
399
+ removedCommandCount += await removeCommandFiles(projectPath, tool.value);
411
400
  }
412
401
  spinner.succeed(`Setup complete for ${tool.name}`);
413
402
  if (tool.wasConfigured) {
@@ -434,9 +423,9 @@ export class InitCommand {
434
423
  // ═══════════════════════════════════════════════════════════
435
424
  // CONFIG FILE
436
425
  // ═══════════════════════════════════════════════════════════
437
- async createConfig(openspecPath, extendMode) {
438
- const configPath = path.join(openspecPath, 'config.yaml');
439
- const configYmlPath = path.join(openspecPath, 'config.yml');
426
+ async createConfig(synspecPath, extendMode) {
427
+ const configPath = path.join(synspecPath, 'config.yaml');
428
+ const configYmlPath = path.join(synspecPath, 'config.yml');
440
429
  const configYamlExists = fs.existsSync(configPath);
441
430
  const configYmlExists = fs.existsSync(configYmlPath);
442
431
  if (configYamlExists || configYmlExists) {
@@ -544,44 +533,5 @@ export class InitCommand {
544
533
  spinner: PROGRESS_SPINNER,
545
534
  }).start();
546
535
  }
547
- async removeSkillDirs(skillsDir) {
548
- let removed = 0;
549
- for (const workflow of ALL_WORKFLOWS) {
550
- const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
551
- if (!dirName)
552
- continue;
553
- const skillDir = path.join(skillsDir, dirName);
554
- try {
555
- if (fs.existsSync(skillDir)) {
556
- await fs.promises.rm(skillDir, { recursive: true, force: true });
557
- removed++;
558
- }
559
- }
560
- catch {
561
- // Ignore errors
562
- }
563
- }
564
- return removed;
565
- }
566
- async removeCommandFiles(projectPath, toolId) {
567
- let removed = 0;
568
- const adapter = CommandAdapterRegistry.get(toolId);
569
- if (!adapter)
570
- return 0;
571
- for (const workflow of ALL_WORKFLOWS) {
572
- const cmdPath = adapter.getFilePath(workflow);
573
- const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
574
- try {
575
- if (fs.existsSync(fullPath)) {
576
- await fs.promises.unlink(fullPath);
577
- removed++;
578
- }
579
- }
580
- catch {
581
- // Ignore errors
582
- }
583
- }
584
- return removed;
585
- }
586
536
  }
587
537
  //# sourceMappingURL=init.js.map
@@ -6,8 +6,7 @@
6
6
  */
7
7
  import { getGlobalConfig, getGlobalConfigPath, saveGlobalConfig } from './global-config.js';
8
8
  import { CommandAdapterRegistry } from './command-generation/index.js';
9
- import { WORKFLOW_TO_SKILL_DIR } from './profile-sync-drift.js';
10
- import { ALL_WORKFLOWS } from './profiles.js';
9
+ import { ALL_WORKFLOWS, WORKFLOW_TO_SKILL_DIR } from './shared/workflow-registry.js';
11
10
  import path from 'path';
12
11
  import * as fs from 'fs';
13
12
  function scanInstalledWorkflowArtifacts(projectPath, tools) {
@@ -1,10 +1,4 @@
1
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
2
  /**
9
3
  * Checks whether a tool has at least one generated synarcx command file.
10
4
  */
@@ -34,5 +28,4 @@ export declare function getToolsNeedingProfileSync(projectPath: string, desiredW
34
28
  * Detects whether the current project has any profile/delivery drift.
35
29
  */
36
30
  export declare function hasProjectConfigDrift(projectPath: string, desiredWorkflows: readonly string[], delivery: Delivery): boolean;
37
- export {};
38
31
  //# sourceMappingURL=profile-sync-drift.d.ts.map
@@ -1,24 +1,9 @@
1
1
  import path from 'path';
2
2
  import * as fs from 'fs';
3
3
  import { AI_TOOLS } from './config.js';
4
- import { ALL_WORKFLOWS } from './profiles.js';
4
+ import { ALL_WORKFLOWS, WORKFLOW_TO_SKILL_DIR, COMMAND_IDS } from './shared/workflow-registry.js';
5
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': 'syn-explore',
12
- 'apply': 'syn-apply',
13
- 'archive': 'syn-archive',
14
- 'propose': 'syn-propose',
15
- 'sync': 'syn-sync',
16
- 'clarify': 'syn-clarify',
17
- 'analyze': 'syn-analyze',
18
- 'debug': 'syn-debug',
19
- 'refactor': 'syn-refactor',
20
- 'quick': 'syn-quick',
21
- };
6
+ import { getConfiguredTools } from './shared/index.js';
22
7
  function toKnownWorkflows(workflows) {
23
8
  return workflows.filter((workflow) => ALL_WORKFLOWS.includes(workflow));
24
9
  }
@@ -5,17 +5,6 @@
5
5
  * Profiles determine WHICH workflows; delivery (in global config) determines HOW.
6
6
  */
7
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 ["explore", "propose", "clarify", "analyze", "apply", "debug", "archive", "sync", "refactor", "quick"];
13
- /**
14
- * All available workflows in the system.
15
- */
16
- export declare const ALL_WORKFLOWS: readonly ["explore", "propose", "clarify", "analyze", "apply", "debug", "archive", "sync", "refactor", "quick"];
17
- export type WorkflowId = (typeof ALL_WORKFLOWS)[number];
18
- export type CoreWorkflowId = (typeof CORE_WORKFLOWS)[number];
19
8
  /**
20
9
  * Resolves which workflows should be active for a given profile configuration.
21
10
  *
@@ -4,26 +4,7 @@
4
4
  * Defines workflow profiles that control which workflows are installed.
5
5
  * Profiles determine WHICH workflows; delivery (in global config) determines HOW.
6
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 = ['explore', 'propose', 'clarify', 'analyze', 'apply', 'debug', 'archive', 'sync', 'refactor', 'quick'];
12
- /**
13
- * All available workflows in the system.
14
- */
15
- export const ALL_WORKFLOWS = [
16
- 'explore',
17
- 'propose',
18
- 'clarify',
19
- 'analyze',
20
- 'apply',
21
- 'debug',
22
- 'archive',
23
- 'sync',
24
- 'refactor',
25
- 'quick',
26
- ];
7
+ import { CORE_WORKFLOWS } from './shared/workflow-registry.js';
27
8
  /**
28
9
  * Resolves which workflows should be active for a given profile configuration.
29
10
  *
@@ -0,0 +1,5 @@
1
+ export declare function removeSkillDirs(skillsDir: string): Promise<number>;
2
+ export declare function removeUnselectedSkillDirs(skillsDir: string, desiredWorkflows: readonly string[]): Promise<number>;
3
+ export declare function removeCommandFiles(projectPath: string, toolId: string): Promise<number>;
4
+ export declare function removeUnselectedCommandFiles(projectPath: string, toolId: string, desiredWorkflows: readonly string[]): Promise<number>;
5
+ //# sourceMappingURL=artifact-cleanup.d.ts.map
@@ -0,0 +1,89 @@
1
+ import path from 'path';
2
+ import * as fs from 'fs';
3
+ import { ALL_WORKFLOWS, WORKFLOW_TO_SKILL_DIR } from './workflow-registry.js';
4
+ import { CommandAdapterRegistry } from '../command-generation/index.js';
5
+ export async function removeSkillDirs(skillsDir) {
6
+ let removed = 0;
7
+ for (const workflow of ALL_WORKFLOWS) {
8
+ const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
9
+ if (!dirName)
10
+ continue;
11
+ const skillDir = path.join(skillsDir, dirName);
12
+ try {
13
+ if (fs.existsSync(skillDir)) {
14
+ await fs.promises.rm(skillDir, { recursive: true, force: true });
15
+ removed++;
16
+ }
17
+ }
18
+ catch {
19
+ // Ignore errors
20
+ }
21
+ }
22
+ return removed;
23
+ }
24
+ export async function removeUnselectedSkillDirs(skillsDir, desiredWorkflows) {
25
+ const desiredSet = new Set(desiredWorkflows);
26
+ let removed = 0;
27
+ for (const workflow of ALL_WORKFLOWS) {
28
+ if (desiredSet.has(workflow))
29
+ continue;
30
+ const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
31
+ if (!dirName)
32
+ continue;
33
+ const skillDir = path.join(skillsDir, dirName);
34
+ try {
35
+ if (fs.existsSync(skillDir)) {
36
+ await fs.promises.rm(skillDir, { recursive: true, force: true });
37
+ removed++;
38
+ }
39
+ }
40
+ catch {
41
+ // Ignore errors
42
+ }
43
+ }
44
+ return removed;
45
+ }
46
+ export async function removeCommandFiles(projectPath, toolId) {
47
+ let removed = 0;
48
+ const adapter = CommandAdapterRegistry.get(toolId);
49
+ if (!adapter)
50
+ return 0;
51
+ for (const workflow of ALL_WORKFLOWS) {
52
+ const cmdPath = adapter.getFilePath(workflow);
53
+ const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
54
+ try {
55
+ if (fs.existsSync(fullPath)) {
56
+ await fs.promises.unlink(fullPath);
57
+ removed++;
58
+ }
59
+ }
60
+ catch {
61
+ // Ignore errors
62
+ }
63
+ }
64
+ return removed;
65
+ }
66
+ export async function removeUnselectedCommandFiles(projectPath, toolId, desiredWorkflows) {
67
+ let removed = 0;
68
+ const adapter = CommandAdapterRegistry.get(toolId);
69
+ if (!adapter)
70
+ return 0;
71
+ const desiredSet = new Set(desiredWorkflows);
72
+ for (const workflow of ALL_WORKFLOWS) {
73
+ if (desiredSet.has(workflow))
74
+ continue;
75
+ const cmdPath = adapter.getFilePath(workflow);
76
+ const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
77
+ try {
78
+ if (fs.existsSync(fullPath)) {
79
+ await fs.promises.unlink(fullPath);
80
+ removed++;
81
+ }
82
+ }
83
+ catch {
84
+ // Ignore errors
85
+ }
86
+ }
87
+ return removed;
88
+ }
89
+ //# sourceMappingURL=artifact-cleanup.js.map
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Shared utilities for generating skill and command files.
5
5
  */
6
- import { getSynExploreSkillTemplate, getSynApplySkillTemplate, getSynArchiveSkillTemplate, getSynProposeSkillTemplate, getSynSyncSkillTemplate, getSynClarifySkillTemplate, getSynAnalyzeSkillTemplate, getSynDebugSkillTemplate, getSynRefactorSkillTemplate, getSynQuickSkillTemplate, getSynExploreCommandTemplate, getSynApplyCommandTemplate, getSynArchiveCommandTemplate, getSynProposeCommandTemplate, getSynSyncCommandTemplate, getSynClarifyCommandTemplate, getSynAnalyzeCommandTemplate, getSynDebugCommandTemplate, getSynRefactorCommandTemplate, getSynQuickCommandTemplate, } from '../templates/skill-templates.js';
6
+ import { getSynExploreSkillTemplate, getSynApplySkillTemplate, getSynProposeSkillTemplate, getSynSyncSkillTemplate, getSynClarifySkillTemplate, getSynAnalyzeSkillTemplate, getSynDebugSkillTemplate, getSynRefactorSkillTemplate, getSynQuickSkillTemplate, getSynReviewSkillTemplate, getSynExploreCommandTemplate, getSynApplyCommandTemplate, getSynProposeCommandTemplate, getSynSyncCommandTemplate, getSynClarifyCommandTemplate, getSynAnalyzeCommandTemplate, getSynDebugCommandTemplate, getSynRefactorCommandTemplate, getSynQuickCommandTemplate, getSynReviewCommandTemplate, } from '../templates/skill-templates.js';
7
7
  /**
8
8
  * Gets skill templates with their directory names, optionally filtered by workflow IDs.
9
9
  *
@@ -13,7 +13,6 @@ export function getSkillTemplates(workflowFilter) {
13
13
  const all = [
14
14
  { template: getSynExploreSkillTemplate(), dirName: 'syn-explore', workflowId: 'explore' },
15
15
  { template: getSynApplySkillTemplate(), dirName: 'syn-apply', workflowId: 'apply' },
16
- { template: getSynArchiveSkillTemplate(), dirName: 'syn-archive', workflowId: 'archive' },
17
16
  { template: getSynProposeSkillTemplate(), dirName: 'syn-propose', workflowId: 'propose' },
18
17
  { template: getSynSyncSkillTemplate(), dirName: 'syn-sync', workflowId: 'sync' },
19
18
  { template: getSynClarifySkillTemplate(), dirName: 'syn-clarify', workflowId: 'clarify' },
@@ -21,6 +20,7 @@ export function getSkillTemplates(workflowFilter) {
21
20
  { template: getSynDebugSkillTemplate(), dirName: 'syn-debug', workflowId: 'debug' },
22
21
  { template: getSynRefactorSkillTemplate(), dirName: 'syn-refactor', workflowId: 'refactor' },
23
22
  { template: getSynQuickSkillTemplate(), dirName: 'syn-quick', workflowId: 'quick' },
23
+ { template: getSynReviewSkillTemplate(), dirName: 'syn-review', workflowId: 'review' },
24
24
  ];
25
25
  if (!workflowFilter)
26
26
  return all;
@@ -36,7 +36,6 @@ export function getCommandTemplates(workflowFilter) {
36
36
  const all = [
37
37
  { template: getSynExploreCommandTemplate(), id: 'explore' },
38
38
  { template: getSynApplyCommandTemplate(), id: 'apply' },
39
- { template: getSynArchiveCommandTemplate(), id: 'archive' },
40
39
  { template: getSynProposeCommandTemplate(), id: 'propose' },
41
40
  { template: getSynSyncCommandTemplate(), id: 'sync' },
42
41
  { template: getSynClarifyCommandTemplate(), id: 'clarify' },
@@ -44,6 +43,7 @@ export function getCommandTemplates(workflowFilter) {
44
43
  { template: getSynDebugCommandTemplate(), id: 'debug' },
45
44
  { template: getSynRefactorCommandTemplate(), id: 'refactor' },
46
45
  { template: getSynQuickCommandTemplate(), id: 'quick' },
46
+ { template: getSynReviewCommandTemplate(), id: 'review' },
47
47
  ];
48
48
  if (!workflowFilter)
49
49
  return all;
@@ -3,16 +3,10 @@
3
3
  *
4
4
  * Shared utilities for detecting tool configurations and version status.
5
5
  */
6
- /**
7
- * Names of skill directories created by synarcx init.
8
- */
9
- export declare const SKILL_NAMES: readonly ["syn-explore", "syn-apply", "syn-archive", "syn-propose", "syn-sync", "syn-clarify", "syn-analyze", "syn-debug", "syn-refactor", "syn-quick"];
10
- export type SkillName = (typeof SKILL_NAMES)[number];
11
- /**
12
- * IDs of command templates created by synarcx init.
13
- */
14
- export declare const COMMAND_IDS: readonly ["explore", "apply", "archive", "propose", "sync", "clarify", "analyze", "debug", "refactor", "quick"];
15
- export type CommandId = (typeof COMMAND_IDS)[number];
6
+ import { SKILL_NAMES, COMMAND_IDS } from './workflow-registry.js';
7
+ export type SkillName = string;
8
+ export type CommandId = string;
9
+ export { SKILL_NAMES, COMMAND_IDS };
16
10
  /**
17
11
  * Status of skill configuration for a tool.
18
12
  */
@@ -6,36 +6,8 @@
6
6
  import path from 'path';
7
7
  import * as fs from 'fs';
8
8
  import { AI_TOOLS } from '../config.js';
9
- /**
10
- * Names of skill directories created by synarcx init.
11
- */
12
- export const SKILL_NAMES = [
13
- 'syn-explore',
14
- 'syn-apply',
15
- 'syn-archive',
16
- 'syn-propose',
17
- 'syn-sync',
18
- 'syn-clarify',
19
- 'syn-analyze',
20
- 'syn-debug',
21
- 'syn-refactor',
22
- 'syn-quick',
23
- ];
24
- /**
25
- * IDs of command templates created by synarcx init.
26
- */
27
- export const COMMAND_IDS = [
28
- 'explore',
29
- 'apply',
30
- 'archive',
31
- 'propose',
32
- 'sync',
33
- 'clarify',
34
- 'analyze',
35
- 'debug',
36
- 'refactor',
37
- 'quick',
38
- ];
9
+ import { SKILL_NAMES, COMMAND_IDS } from './workflow-registry.js';
10
+ export { SKILL_NAMES, COMMAND_IDS };
39
11
  /**
40
12
  * Gets the list of tools with skillsDir configured.
41
13
  */
@@ -90,7 +62,7 @@ export function extractGeneratedByVersion(skillFilePath) {
90
62
  // ---
91
63
  // ...
92
64
  // metadata:
93
- // author: openspec
65
+ // author: synarcx
94
66
  // version: "1.0"
95
67
  // generatedBy: "0.23.0"
96
68
  // ---