specsmd 0.1.0 → 0.1.1

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 (27) hide show
  1. package/README.md +20 -0
  2. package/flows/aidlc/skills/construction/bolt-list.md +14 -14
  3. package/flows/aidlc/skills/construction/bolt-replan.md +37 -35
  4. package/flows/aidlc/skills/construction/bolt-start.md +5 -5
  5. package/flows/aidlc/skills/construction/navigator.md +7 -7
  6. package/flows/aidlc/skills/inception/bolt-plan.md +49 -29
  7. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/adr-template.md +1 -1
  8. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/ddd-01-domain-model-template.md +1 -1
  9. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/ddd-02-technical-design-template.md +1 -1
  10. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/ddd-03-test-report-template.md +1 -1
  11. package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt.md +3 -3
  12. package/flows/aidlc/templates/construction/bolt-types/simple-construction-bolt.md +3 -3
  13. package/flows/aidlc/templates/construction/bolt-types/spike-bolt.md +2 -2
  14. package/flows/aidlc/templates/construction/construction-log-template.md +2 -2
  15. package/flows/aidlc/templates/inception/inception-log-template.md +2 -2
  16. package/flows/aidlc/templates/inception/requirements-template.md +2 -2
  17. package/flows/aidlc/templates/inception/stories-template.md +1 -1
  18. package/flows/aidlc/templates/inception/story-template.md +2 -2
  19. package/flows/aidlc/templates/inception/system-context-template.md +1 -1
  20. package/flows/aidlc/templates/inception/unit-brief-template.md +2 -2
  21. package/flows/aidlc/templates/inception/units-template.md +1 -1
  22. package/lib/analytics/env-detector.js +92 -0
  23. package/lib/analytics/index.js +22 -0
  24. package/lib/analytics/machine-id.js +33 -0
  25. package/lib/analytics/tracker.js +205 -0
  26. package/lib/installer.js +75 -1
  27. package/package.json +2 -1
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # specs.md
2
2
 
3
+ <p align="center">
4
+ <img src="images/specs_md_pixel_logo.png" alt="specs.md logo" width="400" />
5
+ </p>
6
+
3
7
  **AI-native software development with multi-agent orchestration.**
4
8
 
5
9
  specsmd implements the [AI-Driven Development Lifecycle (AI-DLC)](https://aws.amazon.com/blogs/devops/ai-driven-development-life-cycle/) methodology as a set of markdown-based agents that work with your favorite AI coding tools.
@@ -14,6 +18,22 @@ specsmd implements the [AI-Driven Development Lifecycle (AI-DLC)](https://aws.am
14
18
 
15
19
  ---
16
20
 
21
+ ## VS Code Extension
22
+
23
+ Track your AI-DLC progress with our sidebar extension for VS Code and compatible IDEs.
24
+
25
+ <p align="center">
26
+ <img src="vs-code-extension/resources/extension-preview.png" alt="VS Code Extension Preview" width="800" />
27
+ </p>
28
+
29
+ > **Note:** Works with any VS Code-based IDE including [Cursor](https://cursor.sh), [Google Antigravity](https://antigravity.google), [Windsurf](https://codeium.com/windsurf), and others.
30
+
31
+ **Install from:**
32
+ - [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=fabriqaai.specsmd)
33
+ - [GitHub Releases (VSIX)](https://github.com/fabriqaai/specs.md/releases)
34
+
35
+ ---
36
+
17
37
  ## Quick Start
18
38
 
19
39
  ### Prerequisites
@@ -73,20 +73,20 @@ Sort bolts by:
73
73
 
74
74
  ### Active Bolts
75
75
 
76
- - ⏳ **bolt-auth-2** (auth-service, {bolt-type}) - Stage: {current-stage}, 2/4 (50%) ← working
76
+ - ⏳ **002-auth-service** (auth-service, {bolt-type}) - Stage: {current-stage}, 2/4 (50%) ← working
77
77
 
78
78
  ### Planned Bolts
79
79
 
80
- - [ ] **bolt-auth-3** (auth-service) - Stories: 005-*, 006-* - Ready ✅
81
- - [ ] **bolt-payments-1** (payment-api) - Stories: 001-*, 002-*, 003-* - Ready ✅
80
+ - [ ] **003-auth-service** (auth-service) - Stories: 005-*, 006-* - Ready ✅
81
+ - [ ] **004-payment-api** (payment-api) - Stories: 001-*, 002-*, 003-* - Ready ✅
82
82
 
83
83
  ### Blocked Bolts
84
84
 
85
- - 🚫 **bolt-api-1** - Waiting for auth (since 2024-12-04)
85
+ - 🚫 **005-api-gateway** - Waiting for auth (since 2024-12-04)
86
86
 
87
87
  ### Completed Bolts
88
88
 
89
- - ✅ **bolt-auth-1** (auth-service) - Completed 2024-12-05 (4 hours)
89
+ - ✅ **001-auth-service** (auth-service) - Completed 2024-12-05 (4 hours)
90
90
 
91
91
  ### Summary
92
92
  - **Total**: {n} bolts
@@ -97,8 +97,8 @@ Sort bolts by:
97
97
 
98
98
  ### Actions
99
99
 
100
- 1 - **Continue active bolt**: Resume `bolt-auth-2`
101
- 2 - **Start planned bolt**: Begin `bolt-auth-3`
100
+ 1 - **Continue active bolt**: Resume `002-auth-service`
101
+ 2 - **Start planned bolt**: Begin `003-auth-service`
102
102
  3 - **View bolt status**: Check detailed status
103
103
  4 - **Plan new bolts**: Create additional bolts
104
104
 
@@ -112,14 +112,14 @@ Sort bolts by:
112
112
  ```markdown
113
113
  ## Bolts for Unit: {unit-name}
114
114
 
115
- - ✅ **bolt-{unit}-1** ({bolt-type}) - Completed 100% - Stories: 001-*, 002-*
116
- - ⏳ **bolt-{unit}-2** ({bolt-type}) - In progress 50% - Stories: 003-*, 004-* ← current
117
- - [ ] **bolt-{unit}-3** ({bolt-type}) - Planned 0% - Stories: 005-*
115
+ - ✅ **001-{unit-name}** ({bolt-type}) - Completed 100% - Stories: 001-*, 002-*
116
+ - ⏳ **002-{unit-name}** ({bolt-type}) - In progress 50% - Stories: 003-*, 004-* ← current
117
+ - [ ] **003-{unit-name}** ({bolt-type}) - Planned 0% - Stories: 005-*
118
118
 
119
119
  ### Quick Actions
120
120
 
121
- 1 - **Continue bolt-{unit}-2**: Resume current work
122
- 2 - **View bolt-{unit}-1 status**: Review completed bolt
121
+ 1 - **Continue 002-{unit-name}**: Resume current work
122
+ 2 - **View 001-{unit-name} status**: Review completed bolt
123
123
 
124
124
  **Type a number to continue.**
125
125
  ```
@@ -133,8 +133,8 @@ Sort bolts by:
133
133
  ```text
134
134
  ### Available Bolts
135
135
 
136
- 1 - bolt-{unit}-1 (planned) - Stories: 001-*, 002-*
137
- 2 - bolt-{unit}-2 (planned) - Stories: 003-*, 004-*
136
+ 1 - 001-{unit-name} (planned) - Stories: 001-*, 002-*
137
+ 2 - 002-{unit-name} (planned) - Stories: 003-*, 004-*
138
138
 
139
139
  Which bolt would you like to work on?
140
140
  ```
@@ -33,9 +33,9 @@ Replan bolts during Construction phase - add new bolts, split existing ones, or
33
33
  ```markdown
34
34
  ## Current Bolt Status: {unit-name}
35
35
 
36
- - ✅ **bolt-auth-service-1** ({bolt-type}): 001-user-signup, 002-user-login - completed - No dependencies
37
- - ⏳ **bolt-auth-service-2** ({bolt-type}): 003-password-reset, 004-email-verify - in-progress - requires bolt-1
38
- - [ ] **bolt-auth-service-3** ({bolt-type}): 005-mfa-setup - planned - requires bolt-2
36
+ - ✅ **001-auth-service** ({bolt-type}): 001-user-signup, 002-user-login - completed - No dependencies
37
+ - ⏳ **002-auth-service** ({bolt-type}): 003-password-reset, 004-email-verify - in-progress - requires 001-auth-service
38
+ - [ ] **003-auth-service** ({bolt-type}): 005-mfa-setup - planned - requires 002-auth-service
39
39
 
40
40
  ### Summary
41
41
 
@@ -86,8 +86,10 @@ Select an option (1-4):
86
86
  ```
87
87
 
88
88
  2. **Determine next bolt ID**:
89
- - Read existing bolts, find highest sequence number
90
- - Next bolt: `bolt-{unit}-{N+1}`
89
+ - List all directories in `memory-bank/bolts/`
90
+ - Extract the 3-digit prefix from each (e.g., `015` from `015-auth-service`)
91
+ - Find the highest number
92
+ - Next bolt: `{next-BBB}-{unit-name}` (e.g., if highest is `015`, next is `016-auth-service`)
91
93
 
92
94
  3. **Create new bolt(s)**:
93
95
  - Use template: `.specsmd/aidlc/templates/construction/bolt-template.md`
@@ -103,12 +105,12 @@ Select an option (1-4):
103
105
 
104
106
  Created 1 new bolt:
105
107
 
106
- - [ ] **bolt-auth-service-4** ({bolt-type}): 006-session-mgmt, 007-api-keys - requires bolt-3
108
+ - [ ] **004-auth-service** ({bolt-type}): 006-session-mgmt, 007-api-keys - requires 003-auth-service
107
109
 
108
110
  Updated dependency graph:
109
- bolt-1bolt-2bolt-3bolt-4 (NEW)
111
+ 001-auth-service002-auth-service003-auth-service004-auth-service (NEW)
110
112
 
111
- File created: `memory-bank/bolts/bolt-auth-service-4.md`
113
+ File created: `memory-bank/bolts/004-auth-service/bolt.md`
112
114
  ```
113
115
 
114
116
  ---
@@ -136,8 +138,8 @@ Select an option (1-4):
136
138
 
137
139
  Splittable bolts (planned or in-progress):
138
140
 
139
- - ⏳ **bolt-auth-service-2** ({bolt-type}): 003-password-reset, 004-email-verify, 005-mfa-setup - in-progress - ⚠️ Confirm to split
140
- - [ ] **bolt-auth-service-3** ({bolt-type}): 006-session-mgmt, 007-api-keys, 008-rate-limit - planned - ✅ Can split
141
+ - ⏳ **002-auth-service** ({bolt-type}): 003-password-reset, 004-email-verify, 005-mfa-setup - in-progress - ⚠️ Confirm to split
142
+ - [ ] **003-auth-service** ({bolt-type}): 006-session-mgmt, 007-api-keys, 008-rate-limit - planned - ✅ Can split
141
143
 
142
144
  Enter bolt ID to split:
143
145
  ```
@@ -145,21 +147,21 @@ Select an option (1-4):
145
147
  2. **Propose split**:
146
148
 
147
149
  ```markdown
148
- ## Split Proposal: bolt-auth-service-3
150
+ ## Split Proposal: 003-auth-service
149
151
 
150
152
  Current: 3 stories (006-session-mgmt, 007-api-keys, 008-rate-limit)
151
153
 
152
154
  Proposed split:
153
155
 
154
- - **bolt-auth-service-3a**: 006-session-mgmt - Core feature
155
- - **bolt-auth-service-3b**: 007-api-keys, 008-rate-limit - Related edge cases
156
+ - **003-auth-service**: 006-session-mgmt - Core feature
157
+ - **004-auth-service**: 007-api-keys, 008-rate-limit - Related edge cases
156
158
 
157
159
  Accept this split? (yes/no/customize)
158
160
  ```
159
161
 
160
162
  3. **Execute split**:
161
163
  - Archive or update original bolt file
162
- - Create new bolt files with `3a`, `3b` suffixes (or next sequence)
164
+ - Create new bolt files with next sequence number
163
165
  - Update dependencies on dependent bolts
164
166
  - Update `enables_bolts` on prerequisite bolts
165
167
 
@@ -168,17 +170,17 @@ Select an option (1-4):
168
170
  ```markdown
169
171
  ## Bolt Split Complete
170
172
 
171
- Original: bolt-auth-service-3 (archived)
173
+ Original: 003-auth-service (updated)
172
174
 
173
175
  Created:
174
176
 
175
- - [ ] **bolt-auth-service-3** ({bolt-type}): 006-session-mgmt - requires bolt-2
176
- - [ ] **bolt-auth-service-4** ({bolt-type}): 007-api-keys, 008-rate-limit - requires bolt-3
177
+ - [ ] **003-auth-service** ({bolt-type}): 006-session-mgmt - requires 002-auth-service
178
+ - [ ] **004-auth-service** ({bolt-type}): 007-api-keys, 008-rate-limit - requires 003-auth-service
177
179
 
178
180
  Updated files:
179
- - `memory-bank/bolts/bolt-auth-service-3.md` (updated)
180
- - `memory-bank/bolts/bolt-auth-service-4.md` (created)
181
- - `memory-bank/bolts/bolt-auth-service-2.md` (updated enables_bolts)
181
+ - `memory-bank/bolts/003-auth-service/bolt.md` (updated)
182
+ - `memory-bank/bolts/004-auth-service/bolt.md` (created)
183
+ - `memory-bank/bolts/002-auth-service/bolt.md` (updated enables_bolts)
182
184
  ```
183
185
 
184
186
  ---
@@ -204,21 +206,21 @@ Select an option (1-4):
204
206
  ```markdown
205
207
  ## Current Execution Order
206
208
 
207
- bolt-1 (completed) → bolt-2 (in-progress) → bolt-3 (planned) → bolt-4 (planned)
209
+ 001-auth-service (completed) → 002-auth-service (in-progress) → 003-auth-service (planned) → 004-auth-service (planned)
208
210
 
209
- - 1 - **bolt-auth-service-1**: completed - ❌ Cannot move
210
- - 2 - **bolt-auth-service-2**: in-progress - ⚠️ Will pause if moved
211
- - 3 - **bolt-auth-service-3**: planned - ✅ Can move
212
- - 4 - **bolt-auth-service-4**: planned - ✅ Can move
211
+ - 1 - **001-auth-service**: completed - ❌ Cannot move
212
+ - 2 - **002-auth-service**: in-progress - ⚠️ Will pause if moved
213
+ - 3 - **003-auth-service**: planned - ✅ Can move
214
+ - 4 - **004-auth-service**: planned - ✅ Can move
213
215
  ```
214
216
 
215
217
  2. **Get new order**:
216
218
 
217
219
  ```markdown
218
220
  Enter new order for planned bolts (comma-separated IDs):
219
- Example: bolt-auth-service-4, bolt-auth-service-3
221
+ Example: 004-auth-service, 003-auth-service
220
222
 
221
- This will execute bolt-4 before bolt-3.
223
+ This will execute 004-auth-service before 003-auth-service.
222
224
  ```
223
225
 
224
226
  3. **Validate dependencies**:
@@ -236,11 +238,11 @@ Select an option (1-4):
236
238
 
237
239
  New execution order:
238
240
 
239
- bolt-1 (completed) → bolt-2 (in-progress) → bolt-4 (planned) → bolt-3 (planned)
241
+ 001-auth-service (completed) → 002-auth-service (in-progress) → 004-auth-service (planned) → 003-auth-service (planned)
240
242
 
241
243
  Updated files:
242
- - `memory-bank/bolts/bolt-auth-service-3.md` (requires_bolts updated)
243
- - `memory-bank/bolts/bolt-auth-service-4.md` (requires_bolts updated)
244
+ - `memory-bank/bolts/003-auth-service/bolt.md` (requires_bolts updated)
245
+ - `memory-bank/bolts/004-auth-service/bolt.md` (requires_bolts updated)
244
246
  ```
245
247
 
246
248
  ---
@@ -253,10 +255,10 @@ When modifying bolts, always update dependencies:
253
255
 
254
256
  ```yaml
255
257
  ---
256
- id: bolt-auth-service-3
258
+ id: 003-auth-service
257
259
  type: ddd-construction-bolt
258
- requires_bolts: [bolt-auth-service-2]
259
- enables_bolts: [bolt-auth-service-4]
260
+ requires_bolts: [002-auth-service]
261
+ enables_bolts: [004-auth-service]
260
262
  requires_units: []
261
263
  complexity:
262
264
  avg_complexity: 2
@@ -314,12 +316,12 @@ Update Current Bolt Structure to reflect changes.
314
316
 
315
317
  ### Example
316
318
 
317
- After splitting bolt-2:
319
+ After splitting 002-auth-service:
318
320
 
319
321
  ```markdown
320
322
  ## Replanning History
321
323
 
322
- - **2025-12-07**: split - bolt-2bolt-2, bolt-3 - Scope too large - ✅ Approved
324
+ - **2025-12-07**: split - 002-auth-service002-auth-service, 003-auth-service - Scope too large - ✅ Approved
323
325
  ```
324
326
 
325
327
  ---
@@ -255,7 +255,7 @@ Status changes cascade upward: Bolt → Story → Unit → Intent.
255
255
  **On Bolt Completion** (after updating stories):
256
256
 
257
257
  1. **Check Unit Completion**:
258
- - Find all bolts for this unit: `memory-bank/bolts/bolt-{unit}-*/bolt.md`
258
+ - Find all bolts for this unit: scan `memory-bank/bolts/*/bolt.md` and match `unit: {unit-name}` in frontmatter
259
259
  - If ALL bolts have `status: complete` → update unit-brief to `status: complete`
260
260
 
261
261
  2. **Check Intent Completion**:
@@ -270,13 +270,13 @@ Unit: draft → stories-defined → in-progress → complete
270
270
  Story: draft → in-progress → complete
271
271
  ```
272
272
 
273
- **Example** (bolt-artifact-parser-1 completes):
273
+ **Example** (001-artifact-parser completes):
274
274
 
275
275
  ```text
276
276
  1. Stories updated: 001, 002, 003, 004 → complete
277
277
  2. Check unit bolts:
278
- - bolt-artifact-parser-1: complete ✓
279
- - bolt-artifact-parser-2: planned ✗
278
+ - 001-artifact-parser: complete ✓
279
+ - 005-artifact-parser: planned ✗
280
280
  → Unit stays in-progress (not all bolts complete)
281
281
  3. Intent stays construction (unit not complete)
282
282
  ```
@@ -286,7 +286,7 @@ Story: draft → in-progress → complete
286
286
  ```text
287
287
  1. Stories updated: 001, 002 → complete
288
288
  2. Check unit bolts:
289
- - bolt-file-watcher-1: complete ✓
289
+ - 003-file-watcher: complete ✓
290
290
  → Only bolt for unit, all complete!
291
291
  → Update unit-brief: status: complete
292
292
  3. Check intent units:
@@ -134,18 +134,18 @@ When user selects an option:
134
134
 
135
135
  ### Available Bolts
136
136
 
137
- - [ ] `bolt-auth-1` (auth-service, DDD) - planned
138
- - [ ] `bolt-auth-2` (auth-service, DDD) - planned
139
- - [ ] `bolt-api-1` (api-gateway, Simple) - planned
137
+ - [ ] `001-auth-service` (auth-service, DDD) - planned
138
+ - [ ] `002-auth-service` (auth-service, DDD) - planned
139
+ - [ ] `003-api-gateway` (api-gateway, Simple) - planned
140
140
 
141
141
  ### Quick Actions
142
142
 
143
- 1 - **Start bolt-auth-1**: Begin first bolt
143
+ 1 - **Start 001-auth-service**: Begin first bolt
144
144
  2 - **List all bolts**: View with details
145
145
  3 - **View bolt status**: Check specific bolt
146
146
 
147
147
  ### Suggested Next Step
148
- → Start construction with `bolt-auth-1`
148
+ → Start construction with `001-auth-service`
149
149
 
150
150
  **Type a number or enter a bolt ID.**
151
151
  ```
@@ -161,8 +161,8 @@ When user selects an option:
161
161
 
162
162
  All {n} bolts have been completed:
163
163
 
164
- - ✅ `bolt-{unit}-1` - Completed 2024-12-05 (3h)
165
- - ✅ `bolt-{unit}-2` - Completed 2024-12-06 (4h)
164
+ - ✅ `001-{unit-name}` - Completed 2024-12-05 (3h)
165
+ - ✅ `005-{unit-name}` - Completed 2024-12-06 (4h)
166
166
 
167
167
  ### Summary
168
168
  - Stories delivered: {n}
@@ -190,35 +190,51 @@ Establish execution order based on dependencies:
190
190
  1. **Read Path**: Check `schema.bolts` from `.specsmd/aidlc/memory-bank.yaml`
191
191
  *(Default: `memory-bank/bolts/{bolt-id}/`)*
192
192
 
193
- 2. **Create Directory + File Per Bolt**:
193
+ 2. **Determine Bolt ID**:
194
+ - List all directories in `memory-bank/bolts/`
195
+ - Extract the 3-digit prefix from each (e.g., `015` from `015-auth-service`)
196
+ - Find the highest number
197
+ - Next bolt uses the next available number (e.g., if highest is `015`, next is `016`)
198
+
199
+ **⚠️ CRITICAL**: The `{BBB}` prefix is a **GLOBAL** sequence across ALL bolts in `memory-bank/bolts/`, NOT per-unit.
200
+
201
+ 3. **Create Directory + File Per Bolt**:
194
202
  For EACH bolt in the plan:
195
- - Create directory: `memory-bank/bolts/bolt-{unit}-{N}/`
196
- - Create file inside: `memory-bank/bolts/bolt-{unit}-{N}/bolt.md`
203
+ - Create directory: `memory-bank/bolts/{BBB}-{unit-name}/`
204
+ - Create file inside: `memory-bank/bolts/{BBB}-{unit-name}/bolt.md`
197
205
  - Use template: `.specsmd/aidlc/templates/construction/bolt-template.md`
198
206
 
199
- **Example**: If planning 3 bolts for auth unit, CREATE THESE:
207
+ **Naming Convention** (from `memory-bank.yaml`):
208
+ - Format: `{BBB}-{unit-name}/` where BBB is a **GLOBAL** 3-digit sequence
209
+ - The number is global across ALL bolts in `memory-bank/bolts/` (not per-unit)
210
+ - Example sequence: `001-auth-service/`, `002-auth-service/`, `003-payment-service/`, `004-auth-service/`
211
+
212
+ **Example**: Planning bolts across multiple units (global numbering):
200
213
 
201
214
  ```text
202
- memory-bank/bolts/bolt-auth-1/bolt.md ← CREATE THIS DIRECTORY AND FILE
203
- memory-bank/bolts/bolt-auth-2/bolt.md CREATE THIS DIRECTORY AND FILE
204
- memory-bank/bolts/bolt-auth-3/bolt.md CREATE THIS DIRECTORY AND FILE
215
+ memory-bank/bolts/
216
+ ├── 001-auth-service/bolt.md First bolt ever created
217
+ ├── 002-auth-service/bolt.md Second bolt (same unit, continues sequence)
218
+ ├── 003-payment-service/bolt.md ← Third bolt (different unit)
219
+ ├── 004-auth-service/bolt.md ← Fourth bolt (back to auth-service)
220
+ └── 005-api-gateway/bolt.md ← Fifth bolt (another unit)
205
221
  ```
206
222
 
207
223
  **Stage artifacts will be added to same directory during construction:**
208
224
 
209
225
  ```text
210
- memory-bank/bolts/bolt-auth-1/
226
+ memory-bank/bolts/001-auth-service/
211
227
  ├── bolt.md ← You create this now
212
228
  └── {stage-artifacts} ← Created during construction (varies by bolt type)
213
229
  ```
214
230
 
215
231
  *Note: Artifact names depend on bolt type (e.g., DDD bolts create `ddd-01-domain-model.md`, simple bolts create `implementation-plan.md`).*
216
232
 
217
- 3. **Bolt File Structure** (CRITICAL: Include all dependencies in frontmatter):
233
+ 4. **Bolt File Structure** (CRITICAL: Include all dependencies in frontmatter):
218
234
 
219
235
  ```markdown
220
236
  ---
221
- id: bolt-{unit}-{sequence}
237
+ id: {BBB}-{unit-name}
222
238
  unit: {unit-name}
223
239
  intent: {intent-name}
224
240
  type: {bolt-type} # From unit-brief.md or default (ddd-construction-bolt, simple-construction-bolt)
@@ -227,8 +243,8 @@ Establish execution order based on dependencies:
227
243
  created: {date}
228
244
 
229
245
  # Dependency Tracking (REQUIRED)
230
- requires_bolts: [bolt-auth-1] # Bolts that must complete first
231
- enables_bolts: [bolt-auth-3, bolt-api-1] # Bolts that depend on this
246
+ requires_bolts: [001-auth-service] # Bolts that must complete first
247
+ enables_bolts: [003-auth-service, 001-api-service] # Bolts that depend on this
232
248
  requires_units: [auth-service] # Units that must be complete
233
249
  blocks: false # true if waiting on dependency
234
250
 
@@ -240,7 +256,7 @@ Establish execution order based on dependencies:
240
256
  testing_scope: 2 # 1=Unit, 2=Integration, 3=E2E
241
257
  ---
242
258
 
243
- ## Bolt: {bolt-id}
259
+ ## Bolt: {BBB}-{unit-name}
244
260
 
245
261
  ### Objective
246
262
  {What this bolt will accomplish}
@@ -257,19 +273,19 @@ Establish execution order based on dependencies:
257
273
 
258
274
  #### Bolt Dependencies (within intent)
259
275
 
260
- - **bolt-auth-1** (Required): Completed
261
- - **bolt-auth-2** (Optional): In Progress
276
+ - **001-auth-service** (Required): Completed
277
+ - **002-auth-service** (Optional): In Progress
262
278
 
263
279
  #### Unit Dependencies (cross-unit)
264
280
 
265
281
  - **auth-service**: Needs auth tokens - Completed
266
282
 
267
283
  #### Enables (other bolts waiting on this)
268
- - bolt-auth-3
269
- - bolt-api-1
284
+ - 003-auth-service
285
+ - 001-api-service
270
286
  ```
271
287
 
272
- ### 8. Validate Plan
288
+ ### 9. Validate Plan
273
289
 
274
290
  Check the plan against:
275
291
 
@@ -291,16 +307,20 @@ Check the plan against:
291
307
  **⚠️ YOU MUST CREATE THESE DIRECTORIES AND FILES:**
292
308
 
293
309
  ```text
294
- memory-bank/bolts/bolt-{unit}-1/bolt.md ← CREATE THIS DIRECTORY AND FILE
295
- memory-bank/bolts/bolt-{unit}-2/bolt.md ← CREATE THIS DIRECTORY AND FILE
296
- memory-bank/bolts/bolt-{unit}-3/bolt.md ← CREATE THIS DIRECTORY AND FILE
310
+ memory-bank/bolts/{BBB}-{unit-name}/bolt.md ← CREATE THIS DIRECTORY AND FILE
297
311
  ```
298
312
 
313
+ **Naming Convention** (from `memory-bank.yaml`):
314
+
315
+ - Format: `{BBB}-{unit-name}/` where BBB is a global 3-digit sequence
316
+ - Example: `001-auth-service/`, `002-auth-service/`, `016-analytics-tracker/`
317
+
299
318
  **⚠️ DO NOT CREATE:**
300
319
 
301
320
  - `bolt-plan.md` (summary doc)
302
321
  - `README.md` files
303
- - Flat files like `bolt-{unit}-1.md`
322
+ - Flat files like `001-auth-service.md` (must be in directory)
323
+ - Old format like `bolt-{unit}-1/` (incorrect)
304
324
 
305
325
  ### Summary (displayed to user)
306
326
 
@@ -309,17 +329,17 @@ memory-bank/bolts/bolt-{unit}-3/bolt.md ← CREATE THIS DIRECTORY AND FILE
309
329
 
310
330
  ### Bolts Created
311
331
 
312
- - [ ] **bolt-{unit}-1** ({bolt-type}): 001-user-signup, 002-user-login
313
- - [ ] **bolt-{unit}-2** ({bolt-type}): 003-password-reset, 004-email-verify
314
- - [ ] **bolt-{unit}-3** ({bolt-type}): 005-mfa-setup
332
+ - [ ] **001-auth-service** ({bolt-type}): 001-user-signup, 002-user-login
333
+ - [ ] **002-auth-service** ({bolt-type}): 003-password-reset, 004-email-verify
334
+ - [ ] **003-auth-service** ({bolt-type}): 005-mfa-setup
315
335
 
316
336
  ### Dependency Graph
317
- bolt-{unit}-1 ──► bolt-{unit}-2 ──► bolt-{unit}-3
337
+ 001-auth-service ──► 002-auth-service ──► 003-auth-service
318
338
 
319
339
  ### Directories Created
320
- ✅ `memory-bank/bolts/bolt-{unit}-1/bolt.md`
321
- ✅ `memory-bank/bolts/bolt-{unit}-2/bolt.md`
322
- ✅ `memory-bank/bolts/bolt-{unit}-3/bolt.md`
340
+ ✅ `memory-bank/bolts/001-auth-service/bolt.md`
341
+ ✅ `memory-bank/bolts/002-auth-service/bolt.md`
342
+ ✅ `memory-bank/bolts/003-auth-service/bolt.md`
323
343
 
324
344
  ### Total
325
345
  - {n} bolts created
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  bolt: {bolt-id}
3
- created: {timestamp}
3
+ created: {YYYY-MM-DDTHH:MM:SSZ}
4
4
  status: proposed | accepted | deprecated | superseded
5
5
  superseded_by: {adr-number if applicable}
6
6
  ---
@@ -3,7 +3,7 @@ unit: {unit-name}
3
3
  bolt: {bolt-id}
4
4
  stage: model
5
5
  status: complete
6
- updated: {date}
6
+ updated: {YYYY-MM-DDTHH:MM:SSZ}
7
7
  ---
8
8
 
9
9
  # Static Model - {Unit Name}
@@ -3,7 +3,7 @@ unit: {unit-name}
3
3
  bolt: {bolt-id}
4
4
  stage: design
5
5
  status: complete
6
- updated: {date}
6
+ updated: {YYYY-MM-DDTHH:MM:SSZ}
7
7
  ---
8
8
 
9
9
  # Technical Design - {Unit Name}
@@ -3,7 +3,7 @@ unit: {unit-name}
3
3
  bolt: {bolt-id}
4
4
  stage: test
5
5
  status: complete
6
- updated: {date}
6
+ updated: {YYYY-MM-DDTHH:MM:SSZ}
7
7
  ---
8
8
 
9
9
  # Test Report - {Unit Name}
@@ -109,7 +109,7 @@ This bolt type implements Domain-Driven Design (DDD) methodology through five se
109
109
  ---
110
110
  stage: model
111
111
  bolt: {bolt-id}
112
- created: {timestamp}
112
+ created: {YYYY-MM-DDTHH:MM:SSZ}
113
113
  ---
114
114
 
115
115
  ## Static Model: {unit-name}
@@ -189,7 +189,7 @@ created: {timestamp}
189
189
  ---
190
190
  stage: design
191
191
  bolt: {bolt-id}
192
- created: {timestamp}
192
+ created: {YYYY-MM-DDTHH:MM:SSZ}
193
193
  ---
194
194
 
195
195
  ## Technical Design: {unit-name}
@@ -440,7 +440,7 @@ tests/
440
440
  ---
441
441
  stage: test
442
442
  bolt: {bolt-id}
443
- created: {timestamp}
443
+ created: {YYYY-MM-DDTHH:MM:SSZ}
444
444
  ---
445
445
 
446
446
  ## Test Report: {unit-name}
@@ -107,7 +107,7 @@ This bolt type provides a lightweight construction process for work that doesn't
107
107
  ---
108
108
  stage: plan
109
109
  bolt: {bolt-id}
110
- created: {timestamp}
110
+ created: {YYYY-MM-DDTHH:MM:SSZ}
111
111
  ---
112
112
 
113
113
  ## Implementation Plan: {unit-name}
@@ -175,7 +175,7 @@ created: {timestamp}
175
175
  ---
176
176
  stage: implement
177
177
  bolt: {bolt-id}
178
- created: {timestamp}
178
+ created: {YYYY-MM-DDTHH:MM:SSZ}
179
179
  ---
180
180
 
181
181
  ## Implementation Walkthrough: {unit-name}
@@ -260,7 +260,7 @@ created: {timestamp}
260
260
  ---
261
261
  stage: test
262
262
  bolt: {bolt-id}
263
- created: {timestamp}
263
+ created: {YYYY-MM-DDTHH:MM:SSZ}
264
264
  ---
265
265
 
266
266
  ## Test Report: {unit-name}
@@ -80,7 +80,7 @@ This bolt type is for research and proof-of-concept work when there are unknowns
80
80
  ---
81
81
  stage: explore
82
82
  bolt: {bolt-id}
83
- created: {timestamp}
83
+ created: {YYYY-MM-DDTHH:MM:SSZ}
84
84
  time_box: {hours}
85
85
  ---
86
86
 
@@ -142,7 +142,7 @@ time_box: {hours}
142
142
  ---
143
143
  stage: document
144
144
  bolt: {bolt-id}
145
- created: {timestamp}
145
+ created: {YYYY-MM-DDTHH:MM:SSZ}
146
146
  ---
147
147
 
148
148
  ## Spike Report: {topic}
@@ -16,8 +16,8 @@ Use this template to track construction progress and replanning decisions for a
16
16
  ---
17
17
  unit: {unit-name}
18
18
  intent: {intent-name}
19
- created: {YYYY-MM-DD}
20
- last_updated: {YYYY-MM-DD}
19
+ created: {YYYY-MM-DDTHH:MM:SSZ}
20
+ last_updated: {YYYY-MM-DDTHH:MM:SSZ}
21
21
  ---
22
22
 
23
23
  # Construction Log: {unit-name}
@@ -15,8 +15,8 @@ Use this template to track inception progress and decisions for an intent.
15
15
  ```markdown
16
16
  ---
17
17
  intent: {intent-name}
18
- created: {YYYY-MM-DD}
19
- completed: {YYYY-MM-DD or null}
18
+ created: {YYYY-MM-DDTHH:MM:SSZ}
19
+ completed: {YYYY-MM-DDTHH:MM:SSZ or null}
20
20
  status: {in-progress | complete}
21
21
  ---
22
22
 
@@ -11,8 +11,8 @@ Use this template when documenting requirements for an intent.
11
11
  intent: {intent-name}
12
12
  phase: inception
13
13
  status: draft|in-progress|complete
14
- created: {YYYY-MM-DD}
15
- updated: {YYYY-MM-DD}
14
+ created: {YYYY-MM-DDTHH:MM:SSZ}
15
+ updated: {YYYY-MM-DDTHH:MM:SSZ}
16
16
  ---
17
17
  ```
18
18
 
@@ -2,7 +2,7 @@
2
2
  intent: {intent-name}
3
3
  phase: inception
4
4
  status: stories-created
5
- updated: {date}
5
+ updated: {YYYY-MM-DDTHH:MM:SSZ}
6
6
  ---
7
7
 
8
8
  # {Intent Name} - Stories
@@ -13,7 +13,7 @@ unit: {unit-name}
13
13
  intent: {intent-name}
14
14
  status: draft
15
15
  priority: must|should|could
16
- created: {YYYY-MM-DD}
16
+ created: {YYYY-MM-DDTHH:MM:SSZ}
17
17
  assigned_bolt: null
18
18
  implemented: false
19
19
  ---
@@ -96,7 +96,7 @@ unit: auth-service
96
96
  intent: user-authentication
97
97
  status: ready
98
98
  priority: must
99
- created: 2024-12-05
99
+ created: 2024-12-05T10:00:00Z
100
100
  assigned_bolt: bolt-auth-service-1
101
101
  implemented: false
102
102
  ---
@@ -2,7 +2,7 @@
2
2
  intent: {intent-name}
3
3
  phase: inception
4
4
  status: context-defined
5
- updated: {date}
5
+ updated: {YYYY-MM-DDTHH:MM:SSZ}
6
6
  ---
7
7
 
8
8
  # {Intent Name} - System Context
@@ -12,8 +12,8 @@ unit: {unit-name}
12
12
  intent: {intent-name}
13
13
  phase: inception
14
14
  status: draft|ready
15
- created: {YYYY-MM-DD}
16
- updated: {YYYY-MM-DD}
15
+ created: {YYYY-MM-DDTHH:MM:SSZ}
16
+ updated: {YYYY-MM-DDTHH:MM:SSZ}
17
17
  ---
18
18
  ```
19
19
 
@@ -2,7 +2,7 @@
2
2
  intent: {intent-name}
3
3
  phase: inception
4
4
  status: units-decomposed
5
- updated: {date}
5
+ updated: {YYYY-MM-DDTHH:MM:SSZ}
6
6
  ---
7
7
 
8
8
  # {Intent Name} - Unit Decomposition
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Environment Detection
3
+ *
4
+ * Detects shell environment and telemetry opt-out settings.
5
+ * Used to enrich analytics events and respect user privacy preferences.
6
+ */
7
+
8
+ /**
9
+ * Detect the user's shell/terminal environment
10
+ *
11
+ * @returns {string} Shell name (zsh, bash, powershell, cmd, fish, etc.) or 'unknown'
12
+ */
13
+ function detectShell() {
14
+ if (process.platform === 'win32') {
15
+ const comspec = (process.env.ComSpec || '').toLowerCase();
16
+ if (comspec.includes('powershell') || comspec.includes('pwsh')) {
17
+ return 'powershell';
18
+ }
19
+ if (comspec.includes('cmd')) {
20
+ return 'cmd';
21
+ }
22
+ return 'unknown';
23
+ }
24
+
25
+ // Unix-like systems (macOS, Linux)
26
+ const shell = process.env.SHELL || '';
27
+ const basename = shell.split('/').pop() || 'unknown';
28
+ return basename;
29
+ }
30
+
31
+ /**
32
+ * Check if telemetry is disabled via environment variables or CLI flag
33
+ *
34
+ * Respects:
35
+ * - SPECSMD_TELEMETRY_DISABLED=1
36
+ * - DO_NOT_TRACK=1
37
+ * - CI environments (CI, GITHUB_ACTIONS, GITLAB_CI, CIRCLECI, JENKINS_URL)
38
+ * - --no-telemetry CLI flag
39
+ *
40
+ * @param {Object} options - Optional overrides
41
+ * @param {boolean} options.noTelemetryFlag - CLI flag state
42
+ * @returns {boolean} True if telemetry should be disabled
43
+ */
44
+ function isTelemetryDisabled(options = {}) {
45
+ // Check CLI flag first (highest priority)
46
+ if (options.noTelemetryFlag === true) {
47
+ return true;
48
+ }
49
+
50
+ // Check process.argv for --no-telemetry flag
51
+ if (process.argv.includes('--no-telemetry')) {
52
+ return true;
53
+ }
54
+
55
+ // Check explicit opt-out environment variables
56
+ if (process.env.SPECSMD_TELEMETRY_DISABLED === '1') {
57
+ return true;
58
+ }
59
+
60
+ // Respect DO_NOT_TRACK standard (https://consoledonottrack.com/)
61
+ if (process.env.DO_NOT_TRACK === '1') {
62
+ return true;
63
+ }
64
+
65
+ // Auto-disable in CI environments
66
+ if (process.env.CI === 'true') {
67
+ return true;
68
+ }
69
+
70
+ if (process.env.GITHUB_ACTIONS === 'true') {
71
+ return true;
72
+ }
73
+
74
+ if (process.env.GITLAB_CI === 'true') {
75
+ return true;
76
+ }
77
+
78
+ if (process.env.CIRCLECI === 'true') {
79
+ return true;
80
+ }
81
+
82
+ if (process.env.JENKINS_URL !== undefined) {
83
+ return true;
84
+ }
85
+
86
+ return false;
87
+ }
88
+
89
+ module.exports = {
90
+ detectShell,
91
+ isTelemetryDisabled
92
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Analytics Module
3
+ *
4
+ * Exports the analytics tracker singleton for use throughout the installer.
5
+ *
6
+ * Usage:
7
+ * const analytics = require('./analytics');
8
+ *
9
+ * // Initialize at startup
10
+ * analytics.init();
11
+ *
12
+ * // Track events
13
+ * analytics.trackInstallerStarted();
14
+ * analytics.trackIdesConfirmed(['claude-code', 'cursor']);
15
+ * analytics.trackFlowSelected('aidlc');
16
+ * analytics.trackInstallationCompleted('claude-code', 'aidlc', 1500, 12);
17
+ * analytics.trackInstallationFailed('cursor', 'file_permission', 'aidlc');
18
+ */
19
+
20
+ const tracker = require('./tracker');
21
+
22
+ module.exports = tracker;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Machine ID Generation
3
+ *
4
+ * Generates a stable, anonymous machine identifier using a salted SHA-256 hash
5
+ * of the hostname. This ensures:
6
+ * - Same machine always produces same ID
7
+ * - Cannot reverse-lookup the hostname from the hash
8
+ * - No PII is stored or transmitted
9
+ */
10
+
11
+ const crypto = require('crypto');
12
+ const os = require('os');
13
+
14
+ // Constant salt prevents rainbow table attacks
15
+ // Do not change this value - it would break ID consistency
16
+ const SALT = 'specsmd-analytics-v1';
17
+
18
+ /**
19
+ * Generate a stable machine identifier
20
+ *
21
+ * @returns {string} SHA-256 hash of salted hostname (64 hex characters)
22
+ */
23
+ function getMachineId() {
24
+ const hostname = os.hostname();
25
+ return crypto
26
+ .createHash('sha256')
27
+ .update(SALT + hostname)
28
+ .digest('hex');
29
+ }
30
+
31
+ module.exports = {
32
+ getMachineId
33
+ };
@@ -0,0 +1,205 @@
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
+ });
61
+
62
+ // Generate IDs
63
+ this.machineId = getMachineId();
64
+ this.sessionId = crypto.randomUUID();
65
+
66
+ // Build base properties included with every event
67
+ this.baseProperties = {
68
+ distinct_id: this.machineId,
69
+ session_id: this.sessionId,
70
+ $os: process.platform,
71
+ shell: detectShell(),
72
+ node_version: process.version,
73
+ specsmd_version: this._getVersion()
74
+ };
75
+
76
+ this.enabled = true;
77
+ return true;
78
+ } catch (error) {
79
+ // Silent failure - analytics should never break installation
80
+ this.enabled = false;
81
+ return false;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Get specsmd version from package.json
87
+ * @private
88
+ */
89
+ _getVersion() {
90
+ try {
91
+ const pkg = require('../../package.json');
92
+ return pkg.version || 'unknown';
93
+ } catch {
94
+ return 'unknown';
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Track an event (fire-and-forget)
100
+ * @private
101
+ *
102
+ * @param {string} eventName - Name of the event
103
+ * @param {Object} properties - Additional event properties
104
+ */
105
+ track(eventName, properties = {}) {
106
+ if (!this.enabled || !this.mixpanel) {
107
+ return;
108
+ }
109
+
110
+ try {
111
+ this.mixpanel.track(eventName, {
112
+ ...this.baseProperties,
113
+ ...properties
114
+ });
115
+ // No await - fire and forget
116
+ } catch {
117
+ // Silent failure
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Track installer_started event
123
+ * Called when the installer begins
124
+ */
125
+ trackInstallerStarted() {
126
+ this.track('installer_started');
127
+ }
128
+
129
+ /**
130
+ * Track ides_confirmed event
131
+ * Called after user confirms IDE/tool selection
132
+ *
133
+ * @param {string[]} ides - Array of selected IDE keys (e.g., ['claude-code', 'cursor'])
134
+ */
135
+ trackIdesConfirmed(ides) {
136
+ this.track('ides_confirmed', {
137
+ ide_count: ides.length,
138
+ ides: ides
139
+ });
140
+ }
141
+
142
+ /**
143
+ * Track flow_selected event
144
+ * Called after user selects an SDLC flow
145
+ *
146
+ * @param {string} flow - Flow key (e.g., 'aidlc', 'agile')
147
+ */
148
+ trackFlowSelected(flow) {
149
+ this.track('flow_selected', {
150
+ flow: flow
151
+ });
152
+ }
153
+
154
+ /**
155
+ * Track installation_completed event
156
+ * Called after successful installation for an IDE
157
+ *
158
+ * @param {string} ide - IDE key (e.g., 'claude-code')
159
+ * @param {string} flow - Flow key (e.g., 'aidlc')
160
+ * @param {number} durationMs - Installation duration in milliseconds
161
+ * @param {number} filesCreated - Number of files created
162
+ */
163
+ trackInstallationCompleted(ide, flow, durationMs, filesCreated) {
164
+ this.track('installation_completed', {
165
+ ide: ide,
166
+ flow: flow,
167
+ duration_ms: durationMs,
168
+ files_created: filesCreated
169
+ });
170
+ }
171
+
172
+ /**
173
+ * Track installation_failed event
174
+ * Called after failed installation for an IDE
175
+ *
176
+ * @param {string} ide - IDE key (e.g., 'claude-code')
177
+ * @param {string} errorCategory - Error category (e.g., 'file_permission', 'network', 'unknown')
178
+ * @param {string} [flow] - Flow key (optional, may not be selected yet)
179
+ */
180
+ trackInstallationFailed(ide, errorCategory, flow) {
181
+ const properties = {
182
+ ide: ide,
183
+ error_category: errorCategory
184
+ };
185
+
186
+ if (flow) {
187
+ properties.flow = flow;
188
+ }
189
+
190
+ this.track('installation_failed', properties);
191
+ }
192
+
193
+ /**
194
+ * Check if analytics is enabled
195
+ * @returns {boolean}
196
+ */
197
+ isEnabled() {
198
+ return this.enabled;
199
+ }
200
+ }
201
+
202
+ // Export singleton instance
203
+ const tracker = new AnalyticsTracker();
204
+
205
+ module.exports = tracker;
package/lib/installer.js CHANGED
@@ -5,10 +5,56 @@ const yaml = require('js-yaml');
5
5
  const CLIUtils = require('./cli-utils');
6
6
  const InstallerFactory = require('./InstallerFactory');
7
7
  const { FLOWS } = require('./constants');
8
+ const analytics = require('./analytics');
8
9
 
9
10
  // Use theme from CLIUtils for consistent styling
10
11
  const { theme } = CLIUtils;
11
12
 
13
+ /**
14
+ * Categorize an error for analytics tracking
15
+ * @param {Error} error - The error to categorize
16
+ * @returns {string} Error category
17
+ */
18
+ function categorizeError(error) {
19
+ const message = (error.message || '').toLowerCase();
20
+
21
+ if (message.includes('permission') || message.includes('eacces')) {
22
+ return 'file_permission';
23
+ }
24
+ if (message.includes('enoent') || message.includes('not found')) {
25
+ return 'file_not_found';
26
+ }
27
+ if (message.includes('network') || message.includes('enotfound') || message.includes('timeout')) {
28
+ return 'network';
29
+ }
30
+ if (message.includes('enospc') || message.includes('disk')) {
31
+ return 'disk_space';
32
+ }
33
+ return 'unknown';
34
+ }
35
+
36
+ /**
37
+ * Count files in a directory recursively
38
+ * @param {string} dir - Directory path
39
+ * @returns {Promise<number>} File count
40
+ */
41
+ async function countFiles(dir) {
42
+ let count = 0;
43
+ try {
44
+ const entries = await fs.readdir(dir, { withFileTypes: true });
45
+ for (const entry of entries) {
46
+ if (entry.isDirectory()) {
47
+ count += await countFiles(path.join(dir, entry.name));
48
+ } else {
49
+ count++;
50
+ }
51
+ }
52
+ } catch {
53
+ // Ignore errors (directory might not exist)
54
+ }
55
+ return count;
56
+ }
57
+
12
58
  async function detectTools() {
13
59
  const detected = [];
14
60
  const installers = InstallerFactory.getInstallers();
@@ -22,6 +68,12 @@ async function detectTools() {
22
68
  }
23
69
 
24
70
  async function install() {
71
+ // Initialize analytics (respects opt-out env vars)
72
+ analytics.init();
73
+ analytics.trackInstallerStarted();
74
+
75
+ const installStartTime = Date.now();
76
+
25
77
  await CLIUtils.displayLogo();
26
78
  CLIUtils.displayHeader('Installation', '');
27
79
 
@@ -67,6 +119,9 @@ async function install() {
67
119
  process.exit(1);
68
120
  }
69
121
 
122
+ // Track IDE selection
123
+ analytics.trackIdesConfirmed(selectedToolKeys);
124
+
70
125
  // Step 3: Select Flow
71
126
  console.log('');
72
127
  CLIUtils.displayStep(3, 4, 'Select SDLC flow');
@@ -88,12 +143,21 @@ async function install() {
88
143
  process.exit(1);
89
144
  }
90
145
 
146
+ // Track flow selection
147
+ analytics.trackFlowSelected(selectedFlow);
148
+
91
149
  // Step 4: Install flow files
92
150
  console.log('');
93
151
  CLIUtils.displayStep(4, 4, `Installing ${FLOWS[selectedFlow].name} flow...`);
94
152
 
95
153
  try {
96
- await installFlow(selectedFlow, selectedToolKeys);
154
+ const filesCreated = await installFlow(selectedFlow, selectedToolKeys);
155
+
156
+ // Track successful installation for each tool
157
+ const durationMs = Date.now() - installStartTime;
158
+ for (const toolKey of selectedToolKeys) {
159
+ analytics.trackInstallationCompleted(toolKey, selectedFlow, durationMs, filesCreated);
160
+ }
97
161
 
98
162
  CLIUtils.displaySuccess(`${FLOWS[selectedFlow].name} flow installed successfully!`, 'Installation Complete');
99
163
 
@@ -108,6 +172,12 @@ async function install() {
108
172
  ];
109
173
  CLIUtils.displayNextSteps(nextSteps);
110
174
  } catch (error) {
175
+ // Track installation failure
176
+ const errorCategory = categorizeError(error);
177
+ for (const toolKey of selectedToolKeys) {
178
+ analytics.trackInstallationFailed(toolKey, errorCategory, selectedFlow);
179
+ }
180
+
111
181
  CLIUtils.displayError(`Installation failed: ${error.message}`);
112
182
  console.log(theme.dim('\nRolling back changes...'));
113
183
  await rollback(selectedFlow, selectedToolKeys);
@@ -199,6 +269,10 @@ async function installFlow(flowKey, toolKeys) {
199
269
  );
200
270
 
201
271
  CLIUtils.displayStatus('', 'Created installation manifest', 'success');
272
+
273
+ // Count files created for analytics
274
+ const filesCreated = await countFiles(specsmdDir);
275
+ return filesCreated;
202
276
  }
203
277
 
204
278
  async function rollback(flowKey, toolKeys) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specsmd",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
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": {
@@ -45,6 +45,7 @@
45
45
  "fs-extra": "^11.1.1",
46
46
  "gradient-string": "^2.0.2",
47
47
  "js-yaml": "^4.1.0",
48
+ "mixpanel": "^0.18.0",
48
49
  "oh-my-logo": "^0.4.0",
49
50
  "prompts": "^2.4.2"
50
51
  },