specsmd 0.1.1 → 0.1.3
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.
- package/flows/aidlc/skills/construction/bolt-start.md +106 -78
- package/flows/aidlc/skills/inception/bolt-plan.md +18 -5
- package/flows/aidlc/skills/inception/review.md +1 -1
- package/flows/aidlc/skills/inception/units.md +17 -13
- package/flows/aidlc/skills/operations/monitor.md +1 -1
- package/flows/aidlc/templates/construction/bolt-template.md +25 -4
- package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/ddd-01-domain-model-template.md +2 -2
- package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/ddd-02-technical-design-template.md +2 -2
- package/flows/aidlc/templates/construction/bolt-types/ddd-construction-bolt/ddd-03-test-report-template.md +2 -2
- package/flows/aidlc/templates/construction/bolt-types/simple-construction-bolt.md +5 -0
- package/flows/aidlc/templates/construction/construction-log-template.md +2 -2
- package/flows/aidlc/templates/inception/inception-log-template.md +1 -1
- package/flows/aidlc/templates/inception/requirements-template.md +1 -1
- package/flows/aidlc/templates/inception/stories-template.md +1 -1
- package/flows/aidlc/templates/inception/story-template.md +11 -11
- package/flows/aidlc/templates/inception/system-context-template.md +1 -1
- package/flows/aidlc/templates/inception/unit-brief-template.md +3 -3
- package/flows/aidlc/templates/inception/units-template.md +1 -1
- package/lib/analytics/tracker.js +40 -13
- package/lib/installer.js +19 -5
- package/package.json +2 -1
- package/scripts/artifact-validator.js +594 -0
- package/scripts/bolt-complete.js +606 -0
- package/scripts/status-integrity.js +598 -0
package/lib/analytics/tracker.js
CHANGED
|
@@ -56,7 +56,12 @@ class AnalyticsTracker {
|
|
|
56
56
|
const Mixpanel = require('mixpanel');
|
|
57
57
|
this.mixpanel = Mixpanel.init(MIXPANEL_TOKEN, {
|
|
58
58
|
protocol: 'https',
|
|
59
|
-
host: 'api-eu.mixpanel.com' // EU endpoint for GDPR compliance
|
|
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
|
|
60
65
|
});
|
|
61
66
|
|
|
62
67
|
// Generate IDs
|
|
@@ -101,18 +106,34 @@ class AnalyticsTracker {
|
|
|
101
106
|
*
|
|
102
107
|
* @param {string} eventName - Name of the event
|
|
103
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)
|
|
104
111
|
*/
|
|
105
|
-
track(eventName, properties = {}) {
|
|
112
|
+
track(eventName, properties = {}, waitForDelivery = false) {
|
|
106
113
|
if (!this.enabled || !this.mixpanel) {
|
|
107
|
-
return;
|
|
114
|
+
return waitForDelivery ? Promise.resolve() : undefined;
|
|
108
115
|
}
|
|
109
116
|
|
|
110
|
-
|
|
111
|
-
this.
|
|
112
|
-
|
|
113
|
-
|
|
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
|
+
}
|
|
114
132
|
});
|
|
115
|
-
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
this.mixpanel.track(eventName, eventData);
|
|
116
137
|
} catch {
|
|
117
138
|
// Silent failure
|
|
118
139
|
}
|
|
@@ -121,9 +142,11 @@ class AnalyticsTracker {
|
|
|
121
142
|
/**
|
|
122
143
|
* Track installer_started event
|
|
123
144
|
* Called when the installer begins
|
|
145
|
+
* @returns {Promise<void>} Resolves when event is sent
|
|
124
146
|
*/
|
|
125
147
|
trackInstallerStarted() {
|
|
126
|
-
|
|
148
|
+
// Wait for delivery - critical funnel event
|
|
149
|
+
return this.track('installer_started', {}, true);
|
|
127
150
|
}
|
|
128
151
|
|
|
129
152
|
/**
|
|
@@ -131,12 +154,14 @@ class AnalyticsTracker {
|
|
|
131
154
|
* Called after user confirms IDE/tool selection
|
|
132
155
|
*
|
|
133
156
|
* @param {string[]} ides - Array of selected IDE keys (e.g., ['claude-code', 'cursor'])
|
|
157
|
+
* @returns {Promise<void>} Resolves when event is sent
|
|
134
158
|
*/
|
|
135
159
|
trackIdesConfirmed(ides) {
|
|
136
|
-
|
|
160
|
+
// Wait for delivery - critical funnel event
|
|
161
|
+
return this.track('ides_confirmed', {
|
|
137
162
|
ide_count: ides.length,
|
|
138
163
|
ides: ides
|
|
139
|
-
});
|
|
164
|
+
}, true);
|
|
140
165
|
}
|
|
141
166
|
|
|
142
167
|
/**
|
|
@@ -144,11 +169,13 @@ class AnalyticsTracker {
|
|
|
144
169
|
* Called after user selects an SDLC flow
|
|
145
170
|
*
|
|
146
171
|
* @param {string} flow - Flow key (e.g., 'aidlc', 'agile')
|
|
172
|
+
* @returns {Promise<void>} Resolves when event is sent
|
|
147
173
|
*/
|
|
148
174
|
trackFlowSelected(flow) {
|
|
149
|
-
|
|
175
|
+
// Wait for delivery - critical funnel event
|
|
176
|
+
return this.track('flow_selected', {
|
|
150
177
|
flow: flow
|
|
151
|
-
});
|
|
178
|
+
}, true);
|
|
152
179
|
}
|
|
153
180
|
|
|
154
181
|
/**
|
package/lib/installer.js
CHANGED
|
@@ -70,7 +70,7 @@ async function detectTools() {
|
|
|
70
70
|
async function install() {
|
|
71
71
|
// Initialize analytics (respects opt-out env vars)
|
|
72
72
|
analytics.init();
|
|
73
|
-
analytics.trackInstallerStarted();
|
|
73
|
+
await analytics.trackInstallerStarted();
|
|
74
74
|
|
|
75
75
|
const installStartTime = Date.now();
|
|
76
76
|
|
|
@@ -119,8 +119,8 @@ async function install() {
|
|
|
119
119
|
process.exit(1);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
// Track IDE selection
|
|
123
|
-
analytics.trackIdesConfirmed(selectedToolKeys);
|
|
122
|
+
// Track IDE selection (await to ensure delivery before potential cancel)
|
|
123
|
+
await analytics.trackIdesConfirmed(selectedToolKeys);
|
|
124
124
|
|
|
125
125
|
// Step 3: Select Flow
|
|
126
126
|
console.log('');
|
|
@@ -143,8 +143,8 @@ async function install() {
|
|
|
143
143
|
process.exit(1);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
// Track flow selection
|
|
147
|
-
analytics.trackFlowSelected(selectedFlow);
|
|
146
|
+
// Track flow selection (await to ensure delivery before potential cancel)
|
|
147
|
+
await analytics.trackFlowSelected(selectedFlow);
|
|
148
148
|
|
|
149
149
|
// Step 4: Install flow files
|
|
150
150
|
console.log('');
|
|
@@ -250,6 +250,20 @@ async function installFlow(flowKey, toolKeys) {
|
|
|
250
250
|
|
|
251
251
|
CLIUtils.displayStatus('', 'Installed flow resources', 'success');
|
|
252
252
|
|
|
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
|
+
|
|
253
267
|
// NOTE: memory-bank/ is NOT created during installation
|
|
254
268
|
// It will be created when user runs project-init
|
|
255
269
|
// This allows us to detect if project is initialized by checking for memory-bank/standards/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specsmd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
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": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"bin/",
|
|
37
37
|
"flows/",
|
|
38
38
|
"lib/",
|
|
39
|
+
"scripts/",
|
|
39
40
|
"README.md"
|
|
40
41
|
],
|
|
41
42
|
"dependencies": {
|