specsmd 0.0.0-dev.9 → 0.0.0-dev.90

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 (146) hide show
  1. package/README.md +190 -224
  2. package/bin/cli.js +28 -1
  3. package/flows/aidlc/commands/construction-agent.md +5 -1
  4. package/flows/aidlc/commands/inception-agent.md +4 -0
  5. package/flows/aidlc/commands/master-agent.md +4 -0
  6. package/flows/aidlc/commands/operations-agent.md +4 -0
  7. package/flows/aidlc/memory-bank.yaml +2 -1
  8. package/{scripts/artifact-validator.js → flows/aidlc/scripts/artifact-validator.cjs} +3 -3
  9. package/{scripts/bolt-complete.js → flows/aidlc/scripts/bolt-complete.cjs} +36 -5
  10. package/{scripts/status-integrity.js → flows/aidlc/scripts/status-integrity.cjs} +5 -5
  11. package/flows/aidlc/skills/construction/bolt-list.md +1 -1
  12. package/flows/aidlc/skills/construction/bolt-start.md +3 -3
  13. package/flows/aidlc/skills/construction/bolt-status.md +1 -1
  14. package/flows/aidlc/skills/construction/prototype-apply.md +311 -0
  15. package/flows/aidlc/skills/inception/vibe-to-spec.md +410 -0
  16. package/flows/aidlc/skills/master/analyze-context.md +1 -1
  17. package/flows/aidlc/templates/construction/bolt-template.md +2 -2
  18. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt.md +73 -11
  19. package/flows/aidlc/templates/standards/decision-index-template.md +32 -0
  20. package/flows/fire/README.md +19 -0
  21. package/flows/fire/agents/builder/agent.md +260 -0
  22. package/flows/fire/agents/builder/skills/code-review/SKILL.md +257 -0
  23. package/flows/fire/agents/builder/skills/code-review/references/auto-fix-rules.md +218 -0
  24. package/flows/fire/agents/builder/skills/code-review/references/review-categories.md +154 -0
  25. package/flows/fire/agents/builder/skills/code-review/templates/review-report.md.hbs +120 -0
  26. package/flows/fire/agents/builder/skills/run-execute/SKILL.md +714 -0
  27. package/flows/fire/agents/builder/skills/run-execute/scripts/complete-run.cjs +800 -0
  28. package/flows/fire/agents/builder/skills/run-execute/scripts/init-run.cjs +500 -0
  29. package/flows/fire/agents/builder/skills/run-execute/scripts/update-checkpoint.cjs +254 -0
  30. package/flows/fire/agents/builder/skills/run-execute/scripts/update-phase.cjs +250 -0
  31. package/flows/fire/agents/builder/skills/run-execute/templates/plan.md.hbs +61 -0
  32. package/flows/fire/agents/builder/skills/run-execute/templates/test-report.md.hbs +81 -0
  33. package/flows/fire/agents/builder/skills/run-plan/SKILL.md +378 -0
  34. package/flows/fire/agents/builder/skills/run-status/SKILL.md +96 -0
  35. package/flows/fire/agents/builder/skills/walkthrough-generate/SKILL.md +267 -0
  36. package/flows/fire/agents/builder/skills/walkthrough-generate/templates/walkthrough.md.hbs +176 -0
  37. package/flows/fire/agents/orchestrator/agent.md +144 -0
  38. package/flows/fire/agents/orchestrator/skills/project-init/SKILL.md +226 -0
  39. package/flows/fire/agents/orchestrator/skills/project-init/templates/coding-standards.md.hbs +149 -0
  40. package/flows/fire/agents/orchestrator/skills/project-init/templates/constitution.md.hbs +43 -0
  41. package/flows/fire/agents/orchestrator/skills/project-init/templates/system-architecture.md.hbs +101 -0
  42. package/flows/fire/agents/orchestrator/skills/project-init/templates/tech-stack.md.hbs +136 -0
  43. package/flows/fire/agents/orchestrator/skills/project-init/templates/testing-standards.md.hbs +94 -0
  44. package/flows/fire/agents/orchestrator/skills/route/SKILL.md +146 -0
  45. package/flows/fire/agents/orchestrator/skills/status/SKILL.md +696 -0
  46. package/flows/fire/agents/planner/agent.md +143 -0
  47. package/flows/fire/agents/planner/skills/design-doc-generate/SKILL.md +156 -0
  48. package/flows/fire/agents/planner/skills/design-doc-generate/templates/design.md.hbs +124 -0
  49. package/flows/fire/agents/planner/skills/intent-capture/SKILL.md +125 -0
  50. package/flows/fire/agents/planner/skills/intent-capture/templates/brief.md.hbs +40 -0
  51. package/flows/fire/agents/planner/skills/work-item-decompose/SKILL.md +166 -0
  52. package/flows/fire/agents/planner/skills/work-item-decompose/templates/work-item.md.hbs +40 -0
  53. package/flows/fire/commands/fire-builder.md +56 -0
  54. package/flows/fire/commands/fire-planner.md +48 -0
  55. package/flows/fire/commands/fire.md +46 -0
  56. package/flows/fire/memory-bank.yaml +240 -0
  57. package/flows/fire/quick-start.md +146 -0
  58. package/flows/ideation/README.md +35 -0
  59. package/flows/ideation/agents/orchestrator/agent.md +103 -0
  60. package/flows/ideation/agents/orchestrator/skills/flame/SKILL.md +132 -0
  61. package/flows/ideation/agents/orchestrator/skills/flame/references/evaluation-criteria.md +81 -0
  62. package/flows/ideation/agents/orchestrator/skills/flame/references/six-hats-method.md +87 -0
  63. package/flows/ideation/agents/orchestrator/skills/flame/templates/flame-report.md.hbs +81 -0
  64. package/flows/ideation/agents/orchestrator/skills/forge/SKILL.md +153 -0
  65. package/flows/ideation/agents/orchestrator/skills/forge/references/disney-method.md +94 -0
  66. package/flows/ideation/agents/orchestrator/skills/forge/references/pitch-framework.md +87 -0
  67. package/flows/ideation/agents/orchestrator/skills/forge/templates/concept-brief.md.hbs +83 -0
  68. package/flows/ideation/agents/orchestrator/skills/spark/SKILL.md +152 -0
  69. package/flows/ideation/agents/orchestrator/skills/spark/references/anti-bias.md +43 -0
  70. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/analogy.md +60 -0
  71. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/first-principles.md +56 -0
  72. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/index.yaml +76 -0
  73. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/inversion.md +52 -0
  74. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/questorming.md +57 -0
  75. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/random-word.md +35 -0
  76. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/scamper.md +67 -0
  77. package/flows/ideation/agents/orchestrator/skills/spark/references/techniques/what-if.md +55 -0
  78. package/flows/ideation/agents/orchestrator/skills/spark/templates/spark-bank.md.hbs +72 -0
  79. package/flows/ideation/commands/flame.md +43 -0
  80. package/flows/ideation/commands/forge.md +43 -0
  81. package/flows/ideation/commands/ideation.md +51 -0
  82. package/flows/ideation/commands/spark.md +43 -0
  83. package/flows/ideation/memory-bank.yaml +177 -0
  84. package/flows/ideation/quick-start.md +84 -0
  85. package/flows/ideation/shared/protocols/anti-bias.md +79 -0
  86. package/flows/ideation/shared/protocols/deep-thinking.md +92 -0
  87. package/flows/ideation/shared/protocols/diverge-converge.md +72 -0
  88. package/flows/ideation/shared/protocols/interaction-adaptation.md +88 -0
  89. package/flows/simple/README.md +190 -0
  90. package/flows/simple/agents/agent.md +404 -0
  91. package/flows/simple/commands/agent.md +60 -0
  92. package/flows/simple/context-config.yaml +34 -0
  93. package/flows/simple/memory-bank.yaml +66 -0
  94. package/flows/simple/quick-start.md +231 -0
  95. package/flows/simple/skills/design.md +96 -0
  96. package/flows/simple/skills/execute.md +190 -0
  97. package/flows/simple/skills/requirements.md +94 -0
  98. package/flows/simple/skills/tasks.md +136 -0
  99. package/flows/simple/templates/design-template.md +138 -0
  100. package/flows/simple/templates/requirements-template.md +85 -0
  101. package/flows/simple/templates/tasks-template.md +104 -0
  102. package/lib/analytics/tracker.js +6 -2
  103. package/lib/constants.js +25 -8
  104. package/lib/dashboard/aidlc/parser.js +581 -0
  105. package/lib/dashboard/fire/model.js +382 -0
  106. package/lib/dashboard/fire/parser.js +470 -0
  107. package/lib/dashboard/flow-detect.js +86 -0
  108. package/lib/dashboard/git/changes.js +362 -0
  109. package/lib/dashboard/git/worktrees.js +248 -0
  110. package/lib/dashboard/index.js +709 -0
  111. package/lib/dashboard/runtime/watch-runtime.js +122 -0
  112. package/lib/dashboard/simple/parser.js +293 -0
  113. package/lib/dashboard/tui/app.js +1675 -0
  114. package/lib/dashboard/tui/components/error-banner.js +35 -0
  115. package/lib/dashboard/tui/components/header.js +60 -0
  116. package/lib/dashboard/tui/components/help-footer.js +15 -0
  117. package/lib/dashboard/tui/components/stats-strip.js +35 -0
  118. package/lib/dashboard/tui/file-entries.js +383 -0
  119. package/lib/dashboard/tui/flow-builders.js +991 -0
  120. package/lib/dashboard/tui/git-builders.js +218 -0
  121. package/lib/dashboard/tui/helpers.js +236 -0
  122. package/lib/dashboard/tui/overlays.js +242 -0
  123. package/lib/dashboard/tui/preview.js +220 -0
  124. package/lib/dashboard/tui/renderer.js +76 -0
  125. package/lib/dashboard/tui/row-builders.js +797 -0
  126. package/lib/dashboard/tui/sections.js +45 -0
  127. package/lib/dashboard/tui/store.js +44 -0
  128. package/lib/dashboard/tui/views/overview-view.js +61 -0
  129. package/lib/dashboard/tui/views/runs-view.js +93 -0
  130. package/lib/dashboard/tui/worktree-builders.js +229 -0
  131. package/lib/dashboard/web/extension-adapter.js +726 -0
  132. package/lib/dashboard/web/public/app.js +9 -0
  133. package/lib/dashboard/web/public/index.html +14 -0
  134. package/lib/dashboard/web/public/styles.css +36 -0
  135. package/lib/dashboard/web/public/webview-bundle.js +7596 -0
  136. package/lib/dashboard/web/server.js +376 -0
  137. package/lib/dashboard/web/snapshot.js +299 -0
  138. package/lib/installer.js +19 -15
  139. package/lib/installers/CodexInstaller.js +72 -1
  140. package/lib/installers/KiroInstaller.js +55 -0
  141. package/lib/installers/OpenCodeInstaller.js +9 -1
  142. package/lib/installers/ToolInstaller.js +4 -1
  143. package/lib/installers/WindsurfInstaller.js +0 -54
  144. package/package.json +15 -55
  145. package/scripts/check-webview-bundle-sync.cjs +38 -0
  146. package/scripts/sync-webview-bundle.cjs +19 -0
package/lib/installer.js CHANGED
@@ -4,7 +4,7 @@ const prompts = require('prompts');
4
4
  const yaml = require('js-yaml');
5
5
  const CLIUtils = require('./cli-utils');
6
6
  const InstallerFactory = require('./InstallerFactory');
7
- const { FLOWS } = require('./constants');
7
+ const { FLOWS, LINKS } = require('./constants');
8
8
  const analytics = require('./analytics');
9
9
 
10
10
  // Use theme from CLIUtils for consistent styling
@@ -125,6 +125,7 @@ async function install() {
125
125
  // Step 3: Select Flow
126
126
  console.log('');
127
127
  CLIUtils.displayStep(3, 4, 'Select SDLC flow');
128
+ console.log(theme.dim(` Learn more about flows: ${LINKS.flows}\n`));
128
129
  const flowChoices = Object.entries(FLOWS).map(([key, flow]) => ({
129
130
  title: `${flow.name} - ${flow.description}${flow.message || ''}`,
130
131
  value: key,
@@ -171,6 +172,20 @@ async function install() {
171
172
  `Open ${selectedToolNames.join(' or ')} and run /specsmd-master-agent`
172
173
  ];
173
174
  CLIUtils.displayNextSteps(nextSteps);
175
+
176
+ // Display IDE extension info with brand colors
177
+ console.log('\n' + theme.primary('─'.repeat(72)));
178
+ console.log(CLIUtils.logoGradient(' ★ IDE Extension'));
179
+ console.log(theme.primary('─'.repeat(72)));
180
+ console.log('');
181
+ console.log(' ' + CLIUtils.logoGradient('Enhance your experience with the specsmd IDE extension!'));
182
+ console.log('');
183
+ console.log(` ${theme.primary('Learn more:')} ${LINKS.ideExtension}`);
184
+ console.log(` ${theme.primary('VS Code:')} ${LINKS.vscodeMarketplace}`);
185
+ console.log(` ${theme.primary('Cursor/Antigravity/Windsurf:')} ${LINKS.openVsx}`);
186
+ console.log('');
187
+ console.log(theme.primary('─'.repeat(72)) + '\n');
188
+ console.log('');
174
189
  } catch (error) {
175
190
  // Track installation failure
176
191
  const errorCategory = categorizeError(error);
@@ -229,6 +244,9 @@ async function installFlow(flowKey, toolKeys) {
229
244
  if (await fs.pathExists(path.join(flowPath, 'shared'))) {
230
245
  await fs.copy(path.join(flowPath, 'shared'), path.join(targetFlowDir, 'shared'));
231
246
  }
247
+ if (await fs.pathExists(path.join(flowPath, 'scripts'))) {
248
+ await fs.copy(path.join(flowPath, 'scripts'), path.join(targetFlowDir, 'scripts'));
249
+ }
232
250
 
233
251
  // Copy config files
234
252
  if (await fs.pathExists(path.join(flowPath, 'memory-bank.yaml'))) {
@@ -250,20 +268,6 @@ async function installFlow(flowKey, toolKeys) {
250
268
 
251
269
  CLIUtils.displayStatus('', 'Installed flow resources', 'success');
252
270
 
253
- // Step 2.5: Install local scripts for deterministic operations
254
- // These scripts are version-matched to the installed specsmd version
255
- const scriptsDir = path.join(specsmdDir, 'scripts');
256
- await fs.ensureDir(scriptsDir);
257
-
258
- const sourceScriptsDir = path.join(__dirname, '..', 'scripts');
259
- if (await fs.pathExists(sourceScriptsDir)) {
260
- await fs.copy(sourceScriptsDir, scriptsDir);
261
- CLIUtils.displayStatus('', 'Installed local scripts', 'success');
262
- }
263
-
264
- // Note: Scripts are invoked directly via relative path (e.g., node .specsmd/scripts/bolt-complete.js)
265
- // No npm scripts added to package.json to avoid dependency on package.json for execution
266
-
267
271
  // NOTE: memory-bank/ is NOT created during installation
268
272
  // It will be created when user runs project-init
269
273
  // This allows us to detect if project is initialized by checking for memory-bank/standards/
@@ -1,4 +1,8 @@
1
1
  const ToolInstaller = require('./ToolInstaller');
2
+ const fs = require('fs-extra');
3
+ const path = require('path');
4
+ const CLIUtils = require('../cli-utils');
5
+ const { theme } = CLIUtils;
2
6
 
3
7
  class CodexInstaller extends ToolInstaller {
4
8
  get key() {
@@ -10,12 +14,79 @@ class CodexInstaller extends ToolInstaller {
10
14
  }
11
15
 
12
16
  get commandsDir() {
13
- return '.codex';
17
+ return path.join('.codex', 'skills');
14
18
  }
15
19
 
16
20
  get detectPath() {
17
21
  return '.codex';
18
22
  }
23
+
24
+ async installCommands(flowPath, config) {
25
+ const targetSkillsDir = this.commandsDir;
26
+ console.log(theme.dim(` Installing skills to ${targetSkillsDir}/...`));
27
+ await fs.ensureDir(targetSkillsDir);
28
+
29
+ const commandsSourceDir = path.join(flowPath, 'commands');
30
+ if (!await fs.pathExists(commandsSourceDir)) {
31
+ console.log(theme.warning(` No commands folder found at ${commandsSourceDir}`));
32
+ return [];
33
+ }
34
+
35
+ const commandFiles = await fs.readdir(commandsSourceDir);
36
+ const installedFiles = [];
37
+
38
+ for (const cmdFile of commandFiles) {
39
+ if (!cmdFile.endsWith('.md')) continue;
40
+
41
+ try {
42
+ const sourcePath = path.join(commandsSourceDir, cmdFile);
43
+ const content = await fs.readFile(sourcePath, 'utf8');
44
+ const commandName = cmdFile.replace('.md', '');
45
+ const prefix = (config && config.command && config.command.prefix) ? `${config.command.prefix}-` : '';
46
+ const skillName = `specsmd-${prefix}${commandName}`;
47
+
48
+ const { description, body } = this.parseFrontmatter(content);
49
+
50
+ // Build SKILL.md with Codex frontmatter
51
+ const skillContent = [
52
+ '---',
53
+ `name: ${skillName}`,
54
+ `description: "${description || 'specsmd agent'}"`,
55
+ '---',
56
+ '',
57
+ body
58
+ ].join('\n');
59
+
60
+ // Write SKILL.md
61
+ const skillDir = path.join(targetSkillsDir, skillName);
62
+ await fs.ensureDir(skillDir);
63
+ await fs.writeFile(path.join(skillDir, 'SKILL.md'), skillContent, 'utf8');
64
+
65
+ installedFiles.push(skillName);
66
+ } catch (err) {
67
+ console.log(theme.warning(` Failed to install ${cmdFile}: ${err.message}`));
68
+ }
69
+ }
70
+
71
+ CLIUtils.displayStatus('', `Installed ${installedFiles.length} skills for ${this.name}`, 'success');
72
+ return installedFiles;
73
+ }
74
+
75
+ /**
76
+ * Parse YAML frontmatter from a markdown file
77
+ */
78
+ parseFrontmatter(content) {
79
+ const match = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
80
+ if (!match) return { description: '', body: content };
81
+
82
+ const frontmatter = match[1];
83
+ const body = match[2];
84
+ const descMatch = frontmatter.match(/description:\s*["']?(.+?)["']?\s*$/m);
85
+ return {
86
+ description: descMatch ? descMatch[1] : '',
87
+ body: body.trim()
88
+ };
89
+ }
19
90
  }
20
91
 
21
92
  module.exports = CodexInstaller;
@@ -1,5 +1,8 @@
1
1
  const ToolInstaller = require('./ToolInstaller');
2
2
  const path = require('path');
3
+ const fs = require('fs-extra');
4
+ const CLIUtils = require('../cli-utils');
5
+ const { theme } = CLIUtils;
3
6
 
4
7
  class KiroInstaller extends ToolInstaller {
5
8
  get key() {
@@ -17,6 +20,58 @@ class KiroInstaller extends ToolInstaller {
17
20
  get detectPath() {
18
21
  return '.kiro';
19
22
  }
23
+
24
+ /**
25
+ * Override to install commands and create specs symlink for simple flow
26
+ */
27
+ async installCommands(flowPath, config) {
28
+ // Install commands (default behavior)
29
+ const installedCommands = await super.installCommands(flowPath, config);
30
+
31
+ // For simple flow, create symlink to make specs visible in Kiro
32
+ if (flowPath.includes('simple')) {
33
+ await this.createSpecsSymlink();
34
+ }
35
+
36
+ return installedCommands;
37
+ }
38
+
39
+ /**
40
+ * Create symlink from .kiro/specs to specs/ for Kiro specifications compatibility
41
+ */
42
+ async createSpecsSymlink() {
43
+ const kiroSpecsPath = path.join('.kiro', 'specs');
44
+ const specsPath = 'specs';
45
+
46
+ // Check if .kiro/specs already exists
47
+ if (await fs.pathExists(kiroSpecsPath)) {
48
+ const stats = await fs.lstat(kiroSpecsPath);
49
+ if (stats.isSymbolicLink()) {
50
+ console.log(theme.dim(` .kiro/specs symlink already exists, skipping`));
51
+ } else {
52
+ console.log(theme.dim(` .kiro/specs already exists as folder, skipping symlink`));
53
+ }
54
+ return;
55
+ }
56
+
57
+ // Ensure specs folder exists
58
+ await fs.ensureDir(specsPath);
59
+
60
+ try {
61
+ // Create relative symlink from .kiro/specs -> ../specs
62
+ await fs.ensureSymlink(path.join('..', specsPath), kiroSpecsPath);
63
+ CLIUtils.displayStatus('', 'Created .kiro/specs symlink for Kiro compatibility', 'success');
64
+ } catch (err) {
65
+ // Handle specific error cases
66
+ if (err.code === 'EPERM' || err.code === 'EACCES') {
67
+ console.log(theme.warning(` Cannot create symlink (permission denied). On Windows, try running as Administrator.`));
68
+ } else if (err.code === 'EEXIST') {
69
+ console.log(theme.dim(` .kiro/specs already exists, skipping symlink`));
70
+ } else {
71
+ console.log(theme.warning(` Failed to create specs symlink: ${err.message}`));
72
+ }
73
+ }
74
+ }
20
75
  }
21
76
 
22
77
  module.exports = KiroInstaller;
@@ -11,12 +11,20 @@ class OpenCodeInstaller extends ToolInstaller {
11
11
  }
12
12
 
13
13
  get commandsDir() {
14
- return path.join('.opencode', 'agent');
14
+ return path.join('.opencode', 'command');
15
15
  }
16
16
 
17
17
  get detectPath() {
18
18
  return '.opencode';
19
19
  }
20
+
21
+ /**
22
+ * OpenCode requires 'agent: build' in command frontmatter.
23
+ * This inserts the line before the closing '---' of existing frontmatter.
24
+ */
25
+ transformContent(content) {
26
+ return content.replace(/^(---\n[\s\S]*?)(---)/, '$1agent: build\n$2');
27
+ }
20
28
  }
21
29
 
22
30
  module.exports = OpenCodeInstaller;
@@ -56,7 +56,10 @@ class ToolInstaller {
56
56
  const targetFileName = `specsmd-${prefix}${cmdFile}`;
57
57
  const targetPath = path.join(targetCommandsDir, targetFileName);
58
58
 
59
- const content = await fs.readFile(sourcePath, 'utf8');
59
+ let content = await fs.readFile(sourcePath, 'utf8');
60
+ if (this.transformContent) {
61
+ content = this.transformContent(content);
62
+ }
60
63
  await fs.outputFile(targetPath, content, 'utf8');
61
64
  installedFiles.push(targetFileName);
62
65
  } catch (err) {
@@ -1,8 +1,5 @@
1
1
  const ToolInstaller = require('./ToolInstaller');
2
- const fs = require('fs-extra');
3
2
  const path = require('path');
4
- const CLIUtils = require('../cli-utils');
5
- const { theme } = CLIUtils;
6
3
 
7
4
  class WindsurfInstaller extends ToolInstaller {
8
5
  get key() {
@@ -20,57 +17,6 @@ class WindsurfInstaller extends ToolInstaller {
20
17
  get detectPath() {
21
18
  return '.windsurf';
22
19
  }
23
-
24
- /**
25
- * Override to add frontmatter for Windsurf workflows
26
- */
27
- async installCommands(flowPath, config) {
28
- const targetCommandsDir = this.commandsDir;
29
- console.log(theme.dim(` Installing workflows to ${targetCommandsDir}/...`));
30
- await fs.ensureDir(targetCommandsDir);
31
-
32
- const commandsSourceDir = path.join(flowPath, 'commands');
33
-
34
- if (!await fs.pathExists(commandsSourceDir)) {
35
- console.log(theme.warning(` No commands folder found at ${commandsSourceDir}`));
36
- return [];
37
- }
38
-
39
- const commandFiles = await fs.readdir(commandsSourceDir);
40
- const installedFiles = [];
41
-
42
- for (const cmdFile of commandFiles) {
43
- if (cmdFile.endsWith('.md')) {
44
- const sourcePath = path.join(commandsSourceDir, cmdFile);
45
- const prefix = (config && config.command && config.command.prefix) ? `${config.command.prefix}-` : '';
46
-
47
- const targetFileName = `specsmd-${prefix}${cmdFile}`;
48
- const targetPath = path.join(targetCommandsDir, targetFileName);
49
-
50
- // Extract agent name from target filename (e.g., "specsmd-master-agent.md" -> "specsmd-master-agent")
51
- const agentName = targetFileName.replace(/\.md$/, '');
52
-
53
- // Read source content and add Windsurf frontmatter
54
- let content = await fs.readFile(sourcePath, 'utf8');
55
-
56
- // Add Windsurf-specific frontmatter if not present
57
- if (!content.startsWith('---')) {
58
- const frontmatter = `---
59
- description: ${agentName}
60
- ---
61
-
62
- `;
63
- content = frontmatter + content;
64
- }
65
-
66
- await fs.writeFile(targetPath, content);
67
- installedFiles.push(targetFileName);
68
- }
69
- }
70
-
71
- CLIUtils.displayStatus('', `Installed ${installedFiles.length} workflows for ${this.name}`, 'success');
72
- return installedFiles;
73
- }
74
20
  }
75
21
 
76
22
  module.exports = WindsurfInstaller;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specsmd",
3
- "version": "0.0.0-dev.9",
3
+ "version": "0.0.0-dev.90",
4
4
  "description": "Multi-agent orchestration system for AI-native software development. Delivers AI-DLC, Agile, and custom SDLC flows as markdown-based agent systems.",
5
5
  "main": "lib/installer.js",
6
6
  "bin": {
@@ -12,7 +12,10 @@
12
12
  "test:schema": "vitest run __tests__/unit/schema-validation/",
13
13
  "lint:md": "markdownlint 'flows/**/*.md' --config ../.markdownlint.yaml",
14
14
  "lint:md:fix": "markdownlint 'flows/**/*.md' --config ../.markdownlint.yaml --fix",
15
- "validate:all": "npm run test && npm run lint:md"
15
+ "sync:webview-bundle": "node scripts/sync-webview-bundle.cjs",
16
+ "check:webview-bundle": "node scripts/check-webview-bundle-sync.cjs",
17
+ "prepack": "npm run check:webview-bundle",
18
+ "validate:all": "npm run test && npm run lint:md && npm run check:webview-bundle"
16
19
  },
17
20
  "keywords": [
18
21
  "ai-dlc",
@@ -40,79 +43,36 @@
40
43
  "README.md"
41
44
  ],
42
45
  "dependencies": {
46
+ "@inkjs/ui": "^2.0.0",
43
47
  "chalk": "^4.1.2",
48
+ "chokidar": "^4.0.3",
44
49
  "commander": "^11.1.0",
45
50
  "figlet": "^1.9.4",
46
51
  "fs-extra": "^11.1.1",
47
52
  "gradient-string": "^2.0.2",
53
+ "ink": "^5.2.1",
48
54
  "js-yaml": "^4.1.0",
49
55
  "mixpanel": "^0.18.0",
50
56
  "oh-my-logo": "^0.4.0",
51
- "prompts": "^2.4.2"
57
+ "prompts": "^2.4.2",
58
+ "react": "^18.3.1",
59
+ "slice-ansi": "^4.0.0",
60
+ "string-width": "^4.2.3"
52
61
  },
53
62
  "engines": {
54
- "node": ">=14.0.0"
63
+ "node": ">=20.0.0"
55
64
  },
56
65
  "devDependencies": {
57
- "@semantic-release/git": "^10.0.1",
58
66
  "@types/js-yaml": "^4.0.9",
59
67
  "@types/node": "^24.10.2",
60
68
  "glob": "^13.0.0",
61
69
  "markdownlint": "^0.40.0",
62
70
  "markdownlint-cli": "^0.46.0",
63
71
  "remark-parse": "^11.0.0",
64
- "semantic-release": "^24.2.0",
65
72
  "typescript": "^5.9.3",
66
73
  "unified": "^11.0.5",
67
74
  "unist-util-visit": "^5.0.0",
68
- "vitest": "^4.0.15"
69
- },
70
- "release": {
71
- "branches": [
72
- "main"
73
- ],
74
- "plugins": [
75
- [
76
- "@semantic-release/commit-analyzer",
77
- {
78
- "releaseRules": [
79
- {
80
- "breaking": true,
81
- "release": "minor"
82
- },
83
- {
84
- "type": "feat",
85
- "release": "minor"
86
- },
87
- {
88
- "type": "fix",
89
- "release": "patch"
90
- },
91
- {
92
- "type": "perf",
93
- "release": "patch"
94
- }
95
- ]
96
- }
97
- ],
98
- "@semantic-release/release-notes-generator",
99
- "@semantic-release/npm",
100
- [
101
- "@semantic-release/github",
102
- {
103
- "successComment": false,
104
- "failComment": false
105
- }
106
- ],
107
- [
108
- "@semantic-release/git",
109
- {
110
- "assets": [
111
- "package.json"
112
- ],
113
- "message": "chore(release): ${nextRelease.version} [skip ci]"
114
- }
115
- ]
116
- ]
75
+ "vitest": "^4.0.15",
76
+ "yaml": "^2.8.2"
117
77
  }
118
78
  }
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const crypto = require('crypto');
6
+
7
+ const packageRoot = path.resolve(__dirname, '..');
8
+ const repoRoot = path.resolve(packageRoot, '..');
9
+ const extensionBundle = path.join(repoRoot, 'vs-code-extension', 'dist', 'webview', 'bundle.js');
10
+ const packagedBundle = path.join(packageRoot, 'lib', 'dashboard', 'web', 'public', 'webview-bundle.js');
11
+
12
+ function hashFile(filePath) {
13
+ return crypto.createHash('sha256').update(fs.readFileSync(filePath)).digest('hex');
14
+ }
15
+
16
+ if (!fs.existsSync(extensionBundle)) {
17
+ console.error(`Missing VS Code webview bundle: ${extensionBundle}`);
18
+ console.error('Run `npm run compile:webview` in vs-code-extension first.');
19
+ process.exit(1);
20
+ }
21
+
22
+ if (!fs.existsSync(packagedBundle)) {
23
+ console.error(`Missing packaged dashboard web bundle: ${packagedBundle}`);
24
+ process.exit(1);
25
+ }
26
+
27
+ const extensionHash = hashFile(extensionBundle);
28
+ const packagedHash = hashFile(packagedBundle);
29
+
30
+ if (extensionHash !== packagedHash) {
31
+ console.error('Dashboard web bundle is out of sync with the VS Code webview bundle.');
32
+ console.error(`extension: ${extensionHash}`);
33
+ console.error(`packaged: ${packagedHash}`);
34
+ console.error('Run `npm run sync:webview-bundle` from src/.');
35
+ process.exit(1);
36
+ }
37
+
38
+ console.log('Dashboard web bundle is synced with the VS Code webview bundle.');
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const packageRoot = path.resolve(__dirname, '..');
7
+ const repoRoot = path.resolve(packageRoot, '..');
8
+ const extensionBundle = path.join(repoRoot, 'vs-code-extension', 'dist', 'webview', 'bundle.js');
9
+ const packagedBundle = path.join(packageRoot, 'lib', 'dashboard', 'web', 'public', 'webview-bundle.js');
10
+
11
+ if (!fs.existsSync(extensionBundle)) {
12
+ console.error(`Missing VS Code webview bundle: ${extensionBundle}`);
13
+ console.error('Run `npm run compile:webview` in vs-code-extension first.');
14
+ process.exit(1);
15
+ }
16
+
17
+ fs.mkdirSync(path.dirname(packagedBundle), { recursive: true });
18
+ fs.copyFileSync(extensionBundle, packagedBundle);
19
+ console.log(`Synced ${path.relative(repoRoot, packagedBundle)} from ${path.relative(repoRoot, extensionBundle)}.`);