@ydtb/specsmd 0.1.22

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 (143) hide show
  1. package/README.md +322 -0
  2. package/bin/cli.js +21 -0
  3. package/flows/aidlc/README.md +372 -0
  4. package/flows/aidlc/agents/construction-agent.md +80 -0
  5. package/flows/aidlc/agents/inception-agent.md +97 -0
  6. package/flows/aidlc/agents/master-agent.md +61 -0
  7. package/flows/aidlc/agents/operations-agent.md +89 -0
  8. package/flows/aidlc/commands/construction-agent.md +67 -0
  9. package/flows/aidlc/commands/inception-agent.md +59 -0
  10. package/flows/aidlc/commands/master-agent.md +51 -0
  11. package/flows/aidlc/commands/operations-agent.md +81 -0
  12. package/flows/aidlc/context-config.yaml +67 -0
  13. package/flows/aidlc/memory-bank.yaml +105 -0
  14. package/flows/aidlc/quick-start.md +322 -0
  15. package/flows/aidlc/scripts/artifact-validator.cjs +594 -0
  16. package/flows/aidlc/scripts/bolt-complete.cjs +606 -0
  17. package/flows/aidlc/scripts/status-integrity.cjs +598 -0
  18. package/flows/aidlc/skills/construction/bolt-list.md +163 -0
  19. package/flows/aidlc/skills/construction/bolt-replan.md +345 -0
  20. package/flows/aidlc/skills/construction/bolt-start.md +442 -0
  21. package/flows/aidlc/skills/construction/bolt-status.md +185 -0
  22. package/flows/aidlc/skills/construction/navigator.md +196 -0
  23. package/flows/aidlc/skills/construction/prototype-apply.md +311 -0
  24. package/flows/aidlc/skills/inception/bolt-plan.md +372 -0
  25. package/flows/aidlc/skills/inception/context.md +171 -0
  26. package/flows/aidlc/skills/inception/intent-create.md +211 -0
  27. package/flows/aidlc/skills/inception/intent-list.md +124 -0
  28. package/flows/aidlc/skills/inception/navigator.md +207 -0
  29. package/flows/aidlc/skills/inception/requirements.md +227 -0
  30. package/flows/aidlc/skills/inception/review.md +248 -0
  31. package/flows/aidlc/skills/inception/story-create.md +304 -0
  32. package/flows/aidlc/skills/inception/units.md +278 -0
  33. package/flows/aidlc/skills/inception/vibe-to-spec.md +410 -0
  34. package/flows/aidlc/skills/master/analyze-context.md +239 -0
  35. package/flows/aidlc/skills/master/answer-question.md +141 -0
  36. package/flows/aidlc/skills/master/explain-flow.md +158 -0
  37. package/flows/aidlc/skills/master/project-init.md +281 -0
  38. package/flows/aidlc/skills/master/route-request.md +126 -0
  39. package/flows/aidlc/skills/operations/build.md +237 -0
  40. package/flows/aidlc/skills/operations/deploy.md +259 -0
  41. package/flows/aidlc/skills/operations/monitor.md +265 -0
  42. package/flows/aidlc/skills/operations/navigator.md +209 -0
  43. package/flows/aidlc/skills/operations/verify.md +224 -0
  44. package/flows/aidlc/templates/construction/bolt-template.md +226 -0
  45. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/adr-template.md +49 -0
  46. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/ddd-01-domain-model-template.md +55 -0
  47. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/ddd-02-technical-design-template.md +67 -0
  48. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/ddd-03-test-report-template.md +62 -0
  49. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt.md +590 -0
  50. package/flows/aidlc/templates/construction/bolt-types/simple-construction-bolt.md +347 -0
  51. package/flows/aidlc/templates/construction/bolt-types/spike-bolt.md +240 -0
  52. package/flows/aidlc/templates/construction/construction-log-template.md +129 -0
  53. package/flows/aidlc/templates/construction/standards/coding-standards.md +29 -0
  54. package/flows/aidlc/templates/construction/standards/system-architecture.md +22 -0
  55. package/flows/aidlc/templates/construction/standards/tech-stack.md +19 -0
  56. package/flows/aidlc/templates/inception/inception-log-template.md +134 -0
  57. package/flows/aidlc/templates/inception/project/README.md +55 -0
  58. package/flows/aidlc/templates/inception/requirements-template.md +144 -0
  59. package/flows/aidlc/templates/inception/stories-template.md +38 -0
  60. package/flows/aidlc/templates/inception/story-template.md +147 -0
  61. package/flows/aidlc/templates/inception/system-context-template.md +29 -0
  62. package/flows/aidlc/templates/inception/unit-brief-template.md +177 -0
  63. package/flows/aidlc/templates/inception/units-template.md +52 -0
  64. package/flows/aidlc/templates/standards/catalog.yaml +345 -0
  65. package/flows/aidlc/templates/standards/coding-standards.guide.md +553 -0
  66. package/flows/aidlc/templates/standards/data-stack.guide.md +162 -0
  67. package/flows/aidlc/templates/standards/decision-index-template.md +32 -0
  68. package/flows/aidlc/templates/standards/tech-stack.guide.md +280 -0
  69. package/flows/fire/README.md +19 -0
  70. package/flows/fire/agents/builder/agent.md +254 -0
  71. package/flows/fire/agents/builder/skills/code-review/SKILL.md +257 -0
  72. package/flows/fire/agents/builder/skills/code-review/references/auto-fix-rules.md +218 -0
  73. package/flows/fire/agents/builder/skills/code-review/references/review-categories.md +154 -0
  74. package/flows/fire/agents/builder/skills/code-review/templates/review-report.md.hbs +120 -0
  75. package/flows/fire/agents/builder/skills/commit-changes/SKILL.md +232 -0
  76. package/flows/fire/agents/builder/skills/commit-changes/scripts/commit-changes.cjs +447 -0
  77. package/flows/fire/agents/builder/skills/run-execute/SKILL.md +700 -0
  78. package/flows/fire/agents/builder/skills/run-execute/scripts/complete-run.cjs +748 -0
  79. package/flows/fire/agents/builder/skills/run-execute/scripts/init-run.cjs +457 -0
  80. package/flows/fire/agents/builder/skills/run-execute/scripts/update-phase.cjs +239 -0
  81. package/flows/fire/agents/builder/skills/run-execute/templates/plan.md.hbs +61 -0
  82. package/flows/fire/agents/builder/skills/run-execute/templates/test-report.md.hbs +81 -0
  83. package/flows/fire/agents/builder/skills/run-plan/SKILL.md +366 -0
  84. package/flows/fire/agents/builder/skills/run-status/SKILL.md +96 -0
  85. package/flows/fire/agents/builder/skills/walkthrough-generate/SKILL.md +181 -0
  86. package/flows/fire/agents/builder/skills/walkthrough-generate/templates/walkthrough.md.hbs +108 -0
  87. package/flows/fire/agents/orchestrator/agent.md +144 -0
  88. package/flows/fire/agents/orchestrator/skills/project-init/SKILL.md +226 -0
  89. package/flows/fire/agents/orchestrator/skills/project-init/templates/coding-standards.md.hbs +149 -0
  90. package/flows/fire/agents/orchestrator/skills/project-init/templates/constitution.md.hbs +43 -0
  91. package/flows/fire/agents/orchestrator/skills/project-init/templates/system-architecture.md.hbs +101 -0
  92. package/flows/fire/agents/orchestrator/skills/project-init/templates/tech-stack.md.hbs +136 -0
  93. package/flows/fire/agents/orchestrator/skills/project-init/templates/testing-standards.md.hbs +94 -0
  94. package/flows/fire/agents/orchestrator/skills/route/SKILL.md +146 -0
  95. package/flows/fire/agents/orchestrator/skills/status/SKILL.md +696 -0
  96. package/flows/fire/agents/planner/agent.md +143 -0
  97. package/flows/fire/agents/planner/skills/design-doc-generate/SKILL.md +156 -0
  98. package/flows/fire/agents/planner/skills/design-doc-generate/templates/design.md.hbs +124 -0
  99. package/flows/fire/agents/planner/skills/intent-capture/SKILL.md +125 -0
  100. package/flows/fire/agents/planner/skills/intent-capture/templates/brief.md.hbs +40 -0
  101. package/flows/fire/agents/planner/skills/work-item-decompose/SKILL.md +166 -0
  102. package/flows/fire/agents/planner/skills/work-item-decompose/templates/work-item.md.hbs +40 -0
  103. package/flows/fire/commands/fire-builder.md +56 -0
  104. package/flows/fire/commands/fire-planner.md +48 -0
  105. package/flows/fire/commands/fire.md +46 -0
  106. package/flows/fire/memory-bank.yaml +240 -0
  107. package/flows/fire/quick-start.md +146 -0
  108. package/flows/simple/README.md +190 -0
  109. package/flows/simple/agents/agent.md +404 -0
  110. package/flows/simple/commands/agent.md +60 -0
  111. package/flows/simple/context-config.yaml +34 -0
  112. package/flows/simple/memory-bank.yaml +66 -0
  113. package/flows/simple/quick-start.md +231 -0
  114. package/flows/simple/skills/design.md +96 -0
  115. package/flows/simple/skills/execute.md +190 -0
  116. package/flows/simple/skills/requirements.md +94 -0
  117. package/flows/simple/skills/tasks.md +136 -0
  118. package/flows/simple/templates/design-template.md +138 -0
  119. package/flows/simple/templates/requirements-template.md +85 -0
  120. package/flows/simple/templates/tasks-template.md +104 -0
  121. package/lib/InstallerFactory.js +36 -0
  122. package/lib/analytics/env-detector.js +92 -0
  123. package/lib/analytics/index.js +22 -0
  124. package/lib/analytics/machine-id.js +33 -0
  125. package/lib/analytics/tracker.js +232 -0
  126. package/lib/cli-utils.js +342 -0
  127. package/lib/constants.js +44 -0
  128. package/lib/installer.js +406 -0
  129. package/lib/installers/AntigravityInstaller.js +22 -0
  130. package/lib/installers/ClaudeInstaller.js +85 -0
  131. package/lib/installers/ClineInstaller.js +21 -0
  132. package/lib/installers/CodexInstaller.js +21 -0
  133. package/lib/installers/CopilotInstaller.js +113 -0
  134. package/lib/installers/CursorInstaller.js +63 -0
  135. package/lib/installers/GeminiInstaller.js +75 -0
  136. package/lib/installers/KiroInstaller.js +77 -0
  137. package/lib/installers/OpenCodeInstaller.js +30 -0
  138. package/lib/installers/RooInstaller.js +22 -0
  139. package/lib/installers/ToolInstaller.js +76 -0
  140. package/lib/installers/WindsurfInstaller.js +22 -0
  141. package/lib/markdown-validator.ts +175 -0
  142. package/lib/yaml-validator.ts +99 -0
  143. package/package.json +69 -0
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Analytics Tracker
3
+ *
4
+ * Mixpanel-based analytics for the specsmd installer.
5
+ * Tracks anonymous usage patterns while respecting privacy.
6
+ *
7
+ * Features:
8
+ * - Fire-and-forget event delivery (non-blocking)
9
+ * - Silent failures (never breaks installation)
10
+ * - Privacy-first (no PII, respects opt-out)
11
+ */
12
+
13
+ const crypto = require('crypto');
14
+ const { getMachineId } = require('./machine-id');
15
+ const { detectShell, isTelemetryDisabled } = require('./env-detector');
16
+
17
+ // Mixpanel project token
18
+ // This is safe to embed - analytics tokens are public by design
19
+ const MIXPANEL_TOKEN = 'f405d1fa631f91137f9bb8e0a0277653';
20
+
21
+ /**
22
+ * AnalyticsTracker - Singleton class for event tracking
23
+ */
24
+ class AnalyticsTracker {
25
+ constructor() {
26
+ this.mixpanel = null;
27
+ this.enabled = false;
28
+ this.machineId = null;
29
+ this.sessionId = null;
30
+ this.baseProperties = null;
31
+ this.initialized = false;
32
+ }
33
+
34
+ /**
35
+ * Initialize the analytics tracker
36
+ *
37
+ * @param {Object} options - Initialization options
38
+ * @param {boolean} options.noTelemetry - CLI flag to disable telemetry
39
+ * @returns {boolean} True if analytics is enabled
40
+ */
41
+ init(options = {}) {
42
+ if (this.initialized) {
43
+ return this.enabled;
44
+ }
45
+
46
+ this.initialized = true;
47
+
48
+ // Check if telemetry is disabled
49
+ if (isTelemetryDisabled({ noTelemetryFlag: options.noTelemetry })) {
50
+ this.enabled = false;
51
+ return false;
52
+ }
53
+
54
+ try {
55
+ // Lazy-load Mixpanel to avoid blocking if not needed
56
+ const Mixpanel = require('mixpanel');
57
+ this.mixpanel = Mixpanel.init(MIXPANEL_TOKEN, {
58
+ protocol: 'https',
59
+ host: 'api-eu.mixpanel.com', // EU endpoint for GDPR compliance
60
+ // Note: geolocate: true enables IP-based geolocation for analytics.
61
+ // This data is used solely for aggregate usage insights (e.g., country-level
62
+ // adoption patterns). No personal identifiers are collected. Users can
63
+ // opt out via the --no-telemetry flag or SPECSMD_NO_TELEMETRY env var.
64
+ geolocate: true
65
+ });
66
+
67
+ // Generate IDs
68
+ this.machineId = getMachineId();
69
+ this.sessionId = crypto.randomUUID();
70
+
71
+ // Build base properties included with every event
72
+ this.baseProperties = {
73
+ distinct_id: this.machineId,
74
+ session_id: this.sessionId,
75
+ $os: process.platform,
76
+ shell: detectShell(),
77
+ node_version: process.version,
78
+ specsmd_version: this._getVersion()
79
+ };
80
+
81
+ this.enabled = true;
82
+ return true;
83
+ } catch (error) {
84
+ // Silent failure - analytics should never break installation
85
+ this.enabled = false;
86
+ return false;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Get specsmd version from package.json
92
+ * @private
93
+ */
94
+ _getVersion() {
95
+ try {
96
+ const pkg = require('../../package.json');
97
+ return pkg.version || 'unknown';
98
+ } catch {
99
+ return 'unknown';
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Track an event (fire-and-forget)
105
+ * @private
106
+ *
107
+ * @param {string} eventName - Name of the event
108
+ * @param {Object} properties - Additional event properties
109
+ * @param {boolean} waitForDelivery - Wait for event to be sent
110
+ * @returns {Promise<void>} Resolves when event is sent (if waitForDelivery is true)
111
+ */
112
+ track(eventName, properties = {}, waitForDelivery = false) {
113
+ if (!this.enabled || !this.mixpanel) {
114
+ return waitForDelivery ? Promise.resolve() : undefined;
115
+ }
116
+
117
+ const eventData = {
118
+ ...this.baseProperties,
119
+ ...properties
120
+ };
121
+
122
+ if (waitForDelivery) {
123
+ return new Promise((resolve) => {
124
+ try {
125
+ this.mixpanel.track(eventName, eventData, () => {
126
+ // Resolve regardless of error - silent failure
127
+ resolve();
128
+ });
129
+ } catch {
130
+ resolve();
131
+ }
132
+ });
133
+ }
134
+
135
+ try {
136
+ this.mixpanel.track(eventName, eventData);
137
+ } catch {
138
+ // Silent failure
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Track installer_started event
144
+ * Called when the installer begins
145
+ * @returns {Promise<void>} Resolves when event is sent
146
+ */
147
+ trackInstallerStarted() {
148
+ // Wait for delivery - critical funnel event
149
+ return this.track('installer_started', {}, true);
150
+ }
151
+
152
+ /**
153
+ * Track ides_confirmed event
154
+ * Called after user confirms IDE/tool selection
155
+ *
156
+ * @param {string[]} ides - Array of selected IDE keys (e.g., ['claude-code', 'cursor'])
157
+ * @returns {Promise<void>} Resolves when event is sent
158
+ */
159
+ trackIdesConfirmed(ides) {
160
+ // Wait for delivery - critical funnel event
161
+ return this.track('ides_confirmed', {
162
+ ide_count: ides.length,
163
+ ides: ides
164
+ }, true);
165
+ }
166
+
167
+ /**
168
+ * Track flow_selected event
169
+ * Called after user selects an SDLC flow
170
+ *
171
+ * @param {string} flow - Flow key (e.g., 'aidlc', 'agile')
172
+ * @returns {Promise<void>} Resolves when event is sent
173
+ */
174
+ trackFlowSelected(flow) {
175
+ // Wait for delivery - critical funnel event
176
+ return this.track('flow_selected', {
177
+ flow: flow
178
+ }, true);
179
+ }
180
+
181
+ /**
182
+ * Track installation_completed event
183
+ * Called after successful installation for an IDE
184
+ *
185
+ * @param {string} ide - IDE key (e.g., 'claude-code')
186
+ * @param {string} flow - Flow key (e.g., 'aidlc')
187
+ * @param {number} durationMs - Installation duration in milliseconds
188
+ * @param {number} filesCreated - Number of files created
189
+ */
190
+ trackInstallationCompleted(ide, flow, durationMs, filesCreated) {
191
+ this.track('installation_completed', {
192
+ ide: ide,
193
+ flow: flow,
194
+ duration_ms: durationMs,
195
+ files_created: filesCreated
196
+ });
197
+ }
198
+
199
+ /**
200
+ * Track installation_failed event
201
+ * Called after failed installation for an IDE
202
+ *
203
+ * @param {string} ide - IDE key (e.g., 'claude-code')
204
+ * @param {string} errorCategory - Error category (e.g., 'file_permission', 'network', 'unknown')
205
+ * @param {string} [flow] - Flow key (optional, may not be selected yet)
206
+ */
207
+ trackInstallationFailed(ide, errorCategory, flow) {
208
+ const properties = {
209
+ ide: ide,
210
+ error_category: errorCategory
211
+ };
212
+
213
+ if (flow) {
214
+ properties.flow = flow;
215
+ }
216
+
217
+ this.track('installation_failed', properties);
218
+ }
219
+
220
+ /**
221
+ * Check if analytics is enabled
222
+ * @returns {boolean}
223
+ */
224
+ isEnabled() {
225
+ return this.enabled;
226
+ }
227
+ }
228
+
229
+ // Export singleton instance
230
+ const tracker = new AnalyticsTracker();
231
+
232
+ module.exports = tracker;
@@ -0,0 +1,342 @@
1
+ /**
2
+ * CLI Utilities for specsmd
3
+ */
4
+
5
+ const chalk = require('chalk');
6
+ const gradient = require('gradient-string');
7
+ const path = require('path');
8
+
9
+ const { THEME_COLORS } = require('./constants');
10
+
11
+ const THEME = THEME_COLORS;
12
+
13
+ // Create gradient for logo
14
+ const logoGradient = gradient([THEME.primary, THEME.secondary]);
15
+
16
+ // Pixel-art style logo (brick blocks with 3D effect)
17
+ const PIXEL_LOGO = `
18
+ ███████╗ ██████╗ ███████╗ ██████╗ ███████╗ ███╗ ███╗ ██████╗
19
+ ██╔════╝ ██╔══██╗ ██╔════╝ ██╔════╝ ██╔════╝ ████╗ ████║ ██╔══██╗
20
+ ███████╗ ██████╔╝ █████╗ ██║ ███████╗ ██╔████╔██║ ██║ ██║
21
+ ╚════██║ ██╔═══╝ ██╔══╝ ██║ ╚════██║ ██║╚██╔╝██║ ██║ ██║
22
+ ███████║ ██║ ███████╗ ╚██████╗ ███████║ ██╗ ██║ ╚═╝ ██║ ██████╔╝
23
+ ╚══════╝ ╚═╝ ╚══════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝
24
+ `;
25
+
26
+ // Theme chalk instances
27
+ const theme = {
28
+ primary: chalk.hex(THEME.primary),
29
+ secondary: chalk.hex(THEME.secondary),
30
+ success: chalk.hex(THEME.success),
31
+ error: chalk.hex(THEME.error),
32
+ warning: chalk.hex(THEME.warning),
33
+ info: chalk.hex(THEME.info),
34
+ dim: chalk.hex(THEME.dim)
35
+ };
36
+
37
+ // Box drawing characters (Unicode)
38
+ const BOX = {
39
+ topLeft: '╭',
40
+ topRight: '╮',
41
+ bottomLeft: '╰',
42
+ bottomRight: '╯',
43
+ horizontal: '─',
44
+ vertical: '│',
45
+ heavyHorizontal: '═',
46
+ heavyVertical: '║',
47
+ heavyTopLeft: '╔',
48
+ heavyTopRight: '╗',
49
+ heavyBottomLeft: '╚',
50
+ heavyBottomRight: '╝'
51
+ };
52
+
53
+ /**
54
+ * CLIUtils -
55
+ */
56
+ const CLIUtils = {
57
+ /**
58
+ * Get package version
59
+ */
60
+ getVersion() {
61
+ try {
62
+ const packageJson = require(path.join(__dirname, '..', 'package.json'));
63
+ return packageJson.version || 'Unknown';
64
+ } catch {
65
+ return 'Unknown';
66
+ }
67
+ },
68
+
69
+ /**
70
+ * Get terminal width (capped at 80)
71
+ */
72
+ getWidth() {
73
+ return Math.min(process.stdout.columns || 80, 80);
74
+ },
75
+
76
+ /**
77
+ * Display the specs.md logo with ASCII art
78
+ * @param {boolean} clearScreen - Whether to clear screen first
79
+ */
80
+ async displayLogo(clearScreen = true) {
81
+ if (clearScreen) {
82
+ console.clear();
83
+ }
84
+
85
+ const version = this.getVersion();
86
+
87
+ console.log('');
88
+ console.log(logoGradient(PIXEL_LOGO));
89
+
90
+ // Tagline with version
91
+ console.log(theme.primary(' AI-native development orchestration') + theme.primary.bold(` v${version}`) + theme.dim(' https://specs.md') + '\n');
92
+ },
93
+
94
+ /**
95
+ * Display the specsmd logo synchronously with ASCII art
96
+ * @param {boolean} clearScreen - Whether to clear screen first
97
+ */
98
+ displayLogoSync(clearScreen = true) {
99
+ if (clearScreen) {
100
+ console.clear();
101
+ }
102
+
103
+ const version = this.getVersion();
104
+
105
+ console.log('');
106
+ console.log(logoGradient(PIXEL_LOGO));
107
+
108
+ // Tagline with version
109
+ console.log(theme.primary(' AI-native development orchestration') + theme.primary.bold(` v${version}`) + theme.dim(' https://specs.md') + '\n');
110
+ },
111
+
112
+ /**
113
+ * Display the logo using pixel-art style (alternative/legacy method name)
114
+ * @param {boolean} clearScreen - Whether to clear screen first
115
+ */
116
+ displayFigletLogo(clearScreen = true) {
117
+ if (clearScreen) {
118
+ console.clear();
119
+ }
120
+
121
+ const version = this.getVersion();
122
+
123
+ console.log(logoGradient(PIXEL_LOGO));
124
+ console.log(theme.dim(' AI-native development orchestration') + theme.primary.bold(` v${version}`) + theme.dim(' https://specs.md') + '\n');
125
+ },
126
+
127
+ /**
128
+ * Display a section header with separator lines
129
+ * @param {string} title - Section title
130
+ * @param {string} subtitle - Optional subtitle
131
+ */
132
+ displaySection(title, subtitle = null) {
133
+ const width = this.getWidth();
134
+ const line = BOX.heavyHorizontal.repeat(width);
135
+
136
+ console.log('\n' + theme.primary(line));
137
+ console.log(theme.primary.bold(` ${title}`));
138
+ if (subtitle) {
139
+ console.log(theme.dim(` ${subtitle}`));
140
+ }
141
+ console.log(theme.primary(line) + '\n');
142
+ },
143
+
144
+ /**
145
+ * Display a header (lighter than section)
146
+ * @param {string} title - Header title
147
+ * @param {string} icon - Optional icon prefix
148
+ */
149
+ displayHeader(title, icon = '') {
150
+ const prefix = icon ? `${icon} ` : '';
151
+ console.log('\n' + theme.primary.bold(`${prefix}${title}`));
152
+ console.log(theme.dim(BOX.horizontal.repeat(title.length + prefix.length)) + '\n');
153
+ },
154
+
155
+ /**
156
+ * Display a boxed message
157
+ * @param {string} content - Box content
158
+ * @param {object} options - Box options
159
+ */
160
+ displayBox(content, options = {}) {
161
+ const {
162
+ title = null,
163
+ borderColor = 'primary',
164
+ padding = 1,
165
+ width = null
166
+ } = options;
167
+
168
+ const boxWidth = width || Math.min(this.getWidth() - 4, 76);
169
+ const innerWidth = boxWidth - 2;
170
+ const colorFn = theme[borderColor] || theme.primary;
171
+
172
+ // Top border
173
+ let topBorder;
174
+ if (title) {
175
+ const titleStr = ` ${title} `;
176
+ const remainingWidth = boxWidth - titleStr.length - 2;
177
+ const leftPad = Math.floor(remainingWidth / 2);
178
+ const rightPad = remainingWidth - leftPad;
179
+ topBorder = colorFn(BOX.topLeft + BOX.horizontal.repeat(leftPad) + titleStr + BOX.horizontal.repeat(rightPad) + BOX.topRight);
180
+ } else {
181
+ topBorder = colorFn(BOX.topLeft + BOX.horizontal.repeat(boxWidth - 2) + BOX.topRight);
182
+ }
183
+ console.log(topBorder);
184
+
185
+ // Padding top
186
+ for (let i = 0; i < padding; i++) {
187
+ console.log(colorFn(BOX.vertical) + ' '.repeat(innerWidth) + colorFn(BOX.vertical));
188
+ }
189
+
190
+ // Content lines
191
+ const lines = content.split('\n');
192
+ for (const line of lines) {
193
+ const stripped = line.replace(/\u001b\[[0-9;]*m/g, ''); // Strip ANSI codes for length calculation
194
+ const paddedLine = line + ' '.repeat(Math.max(0, innerWidth - stripped.length));
195
+ console.log(colorFn(BOX.vertical) + paddedLine.slice(0, innerWidth) + colorFn(BOX.vertical));
196
+ }
197
+
198
+ // Padding bottom
199
+ for (let i = 0; i < padding; i++) {
200
+ console.log(colorFn(BOX.vertical) + ' '.repeat(innerWidth) + colorFn(BOX.vertical));
201
+ }
202
+
203
+ // Bottom border
204
+ console.log(colorFn(BOX.bottomLeft + BOX.horizontal.repeat(boxWidth - 2) + BOX.bottomRight));
205
+ },
206
+
207
+ /**
208
+ * Display a success message in a green box
209
+ * @param {string} message - Success message
210
+ * @param {string} title - Optional title
211
+ */
212
+ displaySuccess(message, title = 'Success') {
213
+ console.log('');
214
+ this.displayBox(theme.success(message), {
215
+ title,
216
+ borderColor: 'success',
217
+ padding: 0
218
+ });
219
+ },
220
+
221
+ /**
222
+ * Display an error message in a red box
223
+ * @param {string} message - Error message
224
+ * @param {string} title - Optional title
225
+ */
226
+ displayError(message, title = 'Error') {
227
+ console.log('');
228
+ this.displayBox(theme.error(message), {
229
+ title,
230
+ borderColor: 'error',
231
+ padding: 0
232
+ });
233
+ },
234
+
235
+ /**
236
+ * Display a warning message in an amber box
237
+ * @param {string} message - Warning message
238
+ * @param {string} title - Optional title
239
+ */
240
+ displayWarning(message, title = 'Warning') {
241
+ console.log('');
242
+ this.displayBox(theme.warning(message), {
243
+ title,
244
+ borderColor: 'warning',
245
+ padding: 0
246
+ });
247
+ },
248
+
249
+ /**
250
+ * Display an info message in a blue box
251
+ * @param {string} message - Info message
252
+ * @param {string} title - Optional title
253
+ */
254
+ displayInfo(message, title = 'Info') {
255
+ console.log('');
256
+ this.displayBox(theme.info(message), {
257
+ title,
258
+ borderColor: 'info',
259
+ padding: 0
260
+ });
261
+ },
262
+
263
+ /**
264
+ * Display current step progress
265
+ * @param {number} current - Current step
266
+ * @param {number} total - Total steps
267
+ * @param {string} description - Step description
268
+ */
269
+ displayStep(current, total, description) {
270
+ const progress = theme.primary.bold(`[${current}/${total}]`);
271
+ console.log(`${progress} ${description}`);
272
+ },
273
+
274
+ /**
275
+ * Display a completion message
276
+ * @param {string} message - Completion message
277
+ */
278
+ displayComplete(message) {
279
+ this.displaySuccess(message, 'Complete');
280
+ },
281
+
282
+ /**
283
+ * Display a simple status line
284
+ * @param {string} icon - Status icon
285
+ * @param {string} message - Status message
286
+ * @param {string} color - Color name
287
+ */
288
+ displayStatus(icon, message, color = 'primary') {
289
+ const colorFn = theme[color] || theme.primary;
290
+ console.log(`${colorFn(icon)} ${message}`);
291
+ },
292
+
293
+ /**
294
+ * Display a list of items
295
+ * @param {string[]} items - List items
296
+ * @param {string} bullet - Bullet character
297
+ */
298
+ displayList(items, bullet = ' -') {
299
+ for (const item of items) {
300
+ console.log(theme.dim(bullet) + ' ' + item);
301
+ }
302
+ },
303
+
304
+ /**
305
+ * Display next steps
306
+ * @param {string[]} steps - Array of step descriptions
307
+ */
308
+ displayNextSteps(steps) {
309
+ console.log(theme.dim('\nNext steps:'));
310
+ steps.forEach((step, index) => {
311
+ console.log(theme.dim(` ${index + 1}. ${step}`));
312
+ });
313
+ console.log('');
314
+ },
315
+
316
+ /**
317
+ * Display a separator line
318
+ * @param {string} style - 'light' or 'heavy'
319
+ */
320
+ displaySeparator(style = 'light') {
321
+ const width = this.getWidth();
322
+ const char = style === 'heavy' ? BOX.heavyHorizontal : BOX.horizontal;
323
+ console.log(theme.dim(char.repeat(width)));
324
+ },
325
+
326
+ /**
327
+ * Theme colors for external use
328
+ */
329
+ theme,
330
+
331
+ /**
332
+ * Logo gradient for external use
333
+ */
334
+ logoGradient,
335
+
336
+ /**
337
+ * Box characters for external use
338
+ */
339
+ BOX
340
+ };
341
+
342
+ module.exports = CLIUtils;
@@ -0,0 +1,44 @@
1
+
2
+ // Theme Colors (dark red)
3
+ const THEME_COLORS = {
4
+ primary: '#A83232', // Dark brick red
5
+ secondary: '#C04545', // Medium red
6
+ accent: '#D85858', // Coral red
7
+ success: '#22c55e', // Green
8
+ error: '#ef4444', // Red
9
+ warning: '#f59e0b', // Amber
10
+ info: '#3b82f6', // Blue
11
+ dim: '#666666' // Gray shadow (visible on dark/light terminals)
12
+ };
13
+
14
+ const FLOWS = {
15
+ fire: {
16
+ name: 'FIRE',
17
+ description: 'Adaptive execution - Brownfield/monorepo ready, right-sizes rigor to complexity',
18
+ path: 'fire'
19
+ },
20
+ aidlc: {
21
+ name: 'AI-DLC',
22
+ description: 'Full methodology - Comprehensive traceability, DDD or Simple bolt types',
23
+ path: 'aidlc'
24
+ },
25
+ simple: {
26
+ name: 'Simple',
27
+ description: 'Spec generation only (Kiro style) - Creates requirement/design/task docs, no execution tracking',
28
+ path: 'simple'
29
+ }
30
+ };
31
+
32
+ const LINKS = {
33
+ website: 'https://specs.md',
34
+ flows: 'https://specs.md/architecture/flows',
35
+ ideExtension: 'https://specs.md/getting-started/ide-extension',
36
+ vscodeMarketplace: 'https://marketplace.visualstudio.com/items?itemName=fabriqaai.specsmd',
37
+ openVsx: 'https://open-vsx.org/extension/fabriqaai/specsmd'
38
+ };
39
+
40
+ module.exports = {
41
+ THEME_COLORS,
42
+ FLOWS,
43
+ LINKS
44
+ };