@x0rium/devkit-cli 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/advance.d.ts +9 -0
  2. package/dist/advance.d.ts.map +1 -0
  3. package/dist/advance.js +47 -0
  4. package/dist/advance.js.map +1 -0
  5. package/dist/constitution.d.ts +16 -0
  6. package/dist/constitution.d.ts.map +1 -0
  7. package/dist/constitution.js +186 -0
  8. package/dist/constitution.js.map +1 -0
  9. package/dist/coverage.d.ts +18 -0
  10. package/dist/coverage.d.ts.map +1 -0
  11. package/dist/coverage.js +167 -0
  12. package/dist/coverage.js.map +1 -0
  13. package/dist/dashboard.d.ts +2 -0
  14. package/dist/dashboard.d.ts.map +1 -0
  15. package/dist/dashboard.js +380 -0
  16. package/dist/dashboard.js.map +1 -0
  17. package/dist/detector.d.ts +3 -0
  18. package/dist/detector.d.ts.map +1 -0
  19. package/dist/detector.js +45 -0
  20. package/dist/detector.js.map +1 -0
  21. package/dist/escalate.d.ts +11 -0
  22. package/dist/escalate.d.ts.map +1 -0
  23. package/dist/escalate.js +133 -0
  24. package/dist/escalate.js.map +1 -0
  25. package/dist/gate.d.ts +15 -0
  26. package/dist/gate.d.ts.map +1 -0
  27. package/dist/gate.js +244 -0
  28. package/dist/gate.js.map +1 -0
  29. package/dist/impact.d.ts +17 -0
  30. package/dist/impact.d.ts.map +1 -0
  31. package/dist/impact.js +192 -0
  32. package/dist/impact.js.map +1 -0
  33. package/dist/index.d.ts +3 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +494 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/investigate.d.ts +21 -0
  38. package/dist/investigate.d.ts.map +1 -0
  39. package/dist/investigate.js +200 -0
  40. package/dist/investigate.js.map +1 -0
  41. package/dist/rfc.d.ts +21 -0
  42. package/dist/rfc.d.ts.map +1 -0
  43. package/dist/rfc.js +152 -0
  44. package/dist/rfc.js.map +1 -0
  45. package/dist/scaffold.d.ts +7 -0
  46. package/dist/scaffold.d.ts.map +1 -0
  47. package/dist/scaffold.js +54 -0
  48. package/dist/scaffold.js.map +1 -0
  49. package/dist/schemas.d.ts +11 -0
  50. package/dist/schemas.d.ts.map +1 -0
  51. package/dist/schemas.js +103 -0
  52. package/dist/schemas.js.map +1 -0
  53. package/dist/status.d.ts +13 -0
  54. package/dist/status.d.ts.map +1 -0
  55. package/dist/status.js +112 -0
  56. package/dist/status.js.map +1 -0
  57. package/dist/validator.d.ts +16 -0
  58. package/dist/validator.d.ts.map +1 -0
  59. package/dist/validator.js +185 -0
  60. package/dist/validator.js.map +1 -0
  61. package/dist/watch.d.ts +2 -0
  62. package/dist/watch.d.ts.map +1 -0
  63. package/dist/watch.js +48 -0
  64. package/dist/watch.js.map +1 -0
  65. package/package.json +47 -0
@@ -0,0 +1,380 @@
1
+ import { createServer } from 'node:http';
2
+ import { getStatus } from './status.js';
3
+ import { validateArtifacts } from './validator.js';
4
+ import { analyzeCoverage } from './coverage.js';
5
+ import { listRfcs } from './rfc.js';
6
+ import { listInvestigations } from './investigate.js';
7
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ export function startDashboard(cwd, port) {
10
+ const server = createServer((req, res) => {
11
+ if (req.url === '/api/data') {
12
+ res.writeHead(200, { 'Content-Type': 'application/json' });
13
+ res.end(JSON.stringify(collectData(cwd)));
14
+ return;
15
+ }
16
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
17
+ res.end(generateHtml());
18
+ });
19
+ server.listen(port, () => {
20
+ console.log(`\n🌐 Dashboard running at http://localhost:${port}\n`);
21
+ console.log(` Press Ctrl+C to stop.\n`);
22
+ });
23
+ }
24
+ function collectData(cwd) {
25
+ const status = getStatus(cwd);
26
+ const validation = validateArtifacts(cwd);
27
+ const coverage = analyzeCoverage(cwd);
28
+ const rfcs = listRfcs(cwd);
29
+ const investigations = listInvestigations(cwd);
30
+ // Count escalations
31
+ const escDir = join(cwd, '.devkit', 'qa', 'escalations');
32
+ let escalations = [];
33
+ if (existsSync(escDir)) {
34
+ escalations = readdirSync(escDir)
35
+ .filter(f => f.startsWith('ESC-'))
36
+ .map(f => {
37
+ const content = readFileSync(join(escDir, f), 'utf-8');
38
+ const levelMatch = content.match(/^ESCALATED_TO:\s*(.+)/m);
39
+ const statusMatch = content.match(/^STATUS:\s*(.+)/m);
40
+ return {
41
+ id: f.replace('.md', ''),
42
+ level: levelMatch?.[1]?.trim() ?? 'unknown',
43
+ status: statusMatch?.[1]?.trim() ?? 'unknown',
44
+ };
45
+ });
46
+ }
47
+ return {
48
+ status,
49
+ validation: {
50
+ total: validation.filesChecked,
51
+ errors: validation.errors.length,
52
+ errorList: validation.errors.slice(0, 10),
53
+ },
54
+ coverage: {
55
+ percentage: coverage.percentage,
56
+ covered: coverage.covered,
57
+ partial: coverage.partial,
58
+ uncovered: coverage.uncovered,
59
+ total: coverage.totalInvariants,
60
+ entries: coverage.entries,
61
+ },
62
+ rfcs,
63
+ investigations,
64
+ escalations,
65
+ };
66
+ }
67
+ function generateHtml() {
68
+ return `<!DOCTYPE html>
69
+ <html lang="en">
70
+ <head>
71
+ <meta charset="UTF-8">
72
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
73
+ <title>DevKit Dashboard</title>
74
+ <style>
75
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
76
+
77
+ :root {
78
+ --bg: #0a0a0f;
79
+ --surface: #12121a;
80
+ --surface2: #1a1a25;
81
+ --border: #2a2a3a;
82
+ --text: #e0e0e8;
83
+ --text-dim: #8888a0;
84
+ --accent: #6c5ce7;
85
+ --accent-glow: rgba(108, 92, 231, 0.15);
86
+ --green: #00cc88;
87
+ --yellow: #ffbe0b;
88
+ --red: #ff5555;
89
+ --blue: #4fc3f7;
90
+ }
91
+
92
+ * { margin: 0; padding: 0; box-sizing: border-box; }
93
+
94
+ body {
95
+ font-family: 'Inter', -apple-system, sans-serif;
96
+ background: var(--bg);
97
+ color: var(--text);
98
+ min-height: 100vh;
99
+ }
100
+
101
+ .header {
102
+ padding: 28px 40px;
103
+ border-bottom: 1px solid var(--border);
104
+ display: flex;
105
+ align-items: center;
106
+ gap: 16px;
107
+ background: linear-gradient(135deg, var(--surface) 0%, rgba(108, 92, 231, 0.05) 100%);
108
+ }
109
+
110
+ .header h1 {
111
+ font-size: 24px;
112
+ font-weight: 600;
113
+ background: linear-gradient(135deg, #6c5ce7, #a29bfe);
114
+ -webkit-background-clip: text;
115
+ -webkit-text-fill-color: transparent;
116
+ }
117
+
118
+ .header .version {
119
+ background: var(--accent-glow);
120
+ border: 1px solid rgba(108, 92, 231, 0.3);
121
+ padding: 2px 10px;
122
+ border-radius: 12px;
123
+ font-size: 12px;
124
+ color: #a29bfe;
125
+ }
126
+
127
+ .header .refresh {
128
+ margin-left: auto;
129
+ font-size: 13px;
130
+ color: var(--text-dim);
131
+ }
132
+
133
+ .grid {
134
+ display: grid;
135
+ grid-template-columns: 1fr 1fr 1fr;
136
+ gap: 20px;
137
+ padding: 28px 40px;
138
+ }
139
+
140
+ .card {
141
+ background: var(--surface);
142
+ border: 1px solid var(--border);
143
+ border-radius: 12px;
144
+ padding: 24px;
145
+ transition: border-color 0.2s;
146
+ }
147
+
148
+ .card:hover { border-color: rgba(108, 92, 231, 0.4); }
149
+
150
+ .card-title {
151
+ font-size: 11px;
152
+ text-transform: uppercase;
153
+ letter-spacing: 1.5px;
154
+ color: var(--text-dim);
155
+ margin-bottom: 16px;
156
+ font-weight: 600;
157
+ }
158
+
159
+ .card.wide { grid-column: span 2; }
160
+ .card.full { grid-column: span 3; }
161
+
162
+ /* Phase Progress */
163
+ .phases { display: flex; gap: 8px; align-items: center; }
164
+ .phase {
165
+ flex: 1;
166
+ text-align: center;
167
+ padding: 12px 8px;
168
+ border-radius: 8px;
169
+ font-size: 12px;
170
+ font-weight: 500;
171
+ position: relative;
172
+ }
173
+ .phase.done { background: rgba(0, 204, 136, 0.1); color: var(--green); border: 1px solid rgba(0, 204, 136, 0.2); }
174
+ .phase.current { background: var(--accent-glow); color: #a29bfe; border: 1px solid rgba(108, 92, 231, 0.4); animation: pulse 2s infinite; }
175
+ .phase.pending { background: var(--surface2); color: var(--text-dim); border: 1px solid var(--border); }
176
+ .phase-arrow { color: var(--text-dim); font-size: 18px; }
177
+
178
+ @keyframes pulse {
179
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0.3); }
180
+ 50% { box-shadow: 0 0 12px 4px rgba(108, 92, 231, 0.15); }
181
+ }
182
+
183
+ /* Stats */
184
+ .stats { display: flex; gap: 24px; }
185
+ .stat-value { font-size: 36px; font-weight: 700; }
186
+ .stat-label { font-size: 12px; color: var(--text-dim); margin-top: 4px; }
187
+ .stat-value.green { color: var(--green); }
188
+ .stat-value.yellow { color: var(--yellow); }
189
+ .stat-value.red { color: var(--red); }
190
+
191
+ /* Coverage Bar */
192
+ .coverage-bar-container { margin: 12px 0; }
193
+ .coverage-bar {
194
+ height: 8px;
195
+ background: var(--surface2);
196
+ border-radius: 4px;
197
+ overflow: hidden;
198
+ }
199
+ .coverage-fill {
200
+ height: 100%;
201
+ border-radius: 4px;
202
+ transition: width 0.5s ease;
203
+ }
204
+ .coverage-pct { font-size: 32px; font-weight: 700; margin-bottom: 4px; }
205
+
206
+ /* Items list */
207
+ .items { display: flex; flex-direction: column; gap: 8px; }
208
+ .item {
209
+ display: flex; align-items: center; gap: 10px;
210
+ padding: 10px 12px;
211
+ background: var(--surface2);
212
+ border-radius: 8px;
213
+ font-size: 13px;
214
+ }
215
+ .item-icon { font-size: 16px; }
216
+ .item-id { font-weight: 600; color: var(--blue); min-width: 60px; }
217
+ .item-text { flex: 1; color: var(--text); }
218
+ .item-status {
219
+ padding: 2px 8px; border-radius: 10px; font-size: 11px; font-weight: 500;
220
+ }
221
+ .item-status.open { background: rgba(255, 190, 11, 0.15); color: var(--yellow); }
222
+ .item-status.accepted, .item-status.resolved { background: rgba(0, 204, 136, 0.15); color: var(--green); }
223
+
224
+ /* Coverage entries */
225
+ .cov-entry {
226
+ display: flex; align-items: center; gap: 10px;
227
+ padding: 8px 12px;
228
+ background: var(--surface2);
229
+ border-radius: 8px;
230
+ font-size: 13px;
231
+ }
232
+ .cov-entry.covered { border-left: 3px solid var(--green); }
233
+ .cov-entry.partial { border-left: 3px solid var(--yellow); }
234
+ .cov-entry.uncovered { border-left: 3px solid var(--red); }
235
+ .cov-entry .tests { color: var(--text-dim); font-size: 11px; margin-left: auto; }
236
+
237
+ /* Validation errors */
238
+ .error-item {
239
+ padding: 10px 12px;
240
+ background: rgba(255, 85, 85, 0.05);
241
+ border-left: 3px solid var(--red);
242
+ border-radius: 0 8px 8px 0;
243
+ font-size: 13px;
244
+ margin-bottom: 6px;
245
+ }
246
+ .error-file { color: var(--blue); font-weight: 500; }
247
+ .error-msg { color: var(--text); margin-top: 4px; }
248
+ .error-fix { color: var(--green); font-size: 12px; margin-top: 2px; }
249
+
250
+ .empty { color: var(--text-dim); font-style: italic; font-size: 13px; }
251
+
252
+ /* Escalation flow */
253
+ .flow { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
254
+ .flow-node {
255
+ padding: 6px 14px; border-radius: 20px; font-size: 12px; font-weight: 500;
256
+ }
257
+ .flow-node.speckit { background: rgba(79, 195, 247, 0.15); color: var(--blue); }
258
+ .flow-node.archkit { background: rgba(108, 92, 231, 0.15); color: #a29bfe; }
259
+ .flow-node.productkit { background: rgba(255, 190, 11, 0.15); color: var(--yellow); }
260
+ .flow-node.researchkit { background: rgba(0, 204, 136, 0.15); color: var(--green); }
261
+ </style>
262
+ </head>
263
+ <body>
264
+ <div class="header">
265
+ <h1>⬡ DevKit Dashboard</h1>
266
+ <span class="version">v0.4.0</span>
267
+ <span class="refresh" id="refresh-time">Loading...</span>
268
+ </div>
269
+
270
+ <div class="grid" id="content">
271
+ <div class="card full" style="text-align:center; padding: 60px;">
272
+ <div style="font-size: 24px; margin-bottom: 12px;">⏳</div>
273
+ <div style="color: var(--text-dim);">Loading dashboard...</div>
274
+ </div>
275
+ </div>
276
+
277
+ <script>
278
+ async function loadData() {
279
+ const res = await fetch('/api/data');
280
+ const data = await res.json();
281
+ render(data);
282
+ }
283
+
284
+ function render(d) {
285
+ const s = d.status;
286
+ const phases = ['research', 'product', 'arch', 'spec', 'qa'];
287
+ const labels = { research: 'Research', product: 'Product', arch: 'Arch', spec: 'Spec', qa: 'QA' };
288
+
289
+ // Phase statuses — phaseProgress is a Record<phase, status>
290
+ const phaseMap = s ? (s.phaseProgress || {}) : {};
291
+
292
+ const phaseHtml = phases.map(p => {
293
+ const st = phaseMap[p] || 'pending';
294
+ const cls = st === 'done' ? 'done' : (s && s.phase === p) ? 'current' : 'pending';
295
+ const icon = st === 'done' ? '✅' : (s && s.phase === p) ? '◆' : '○';
296
+ return '<div class="phase ' + cls + '">' + icon + ' ' + labels[p] + 'Kit</div>';
297
+ }).join('<span class="phase-arrow">→</span>');
298
+
299
+ // Coverage color
300
+ const pct = d.coverage.percentage;
301
+ const covColor = pct >= 80 ? 'var(--green)' : pct >= 50 ? 'var(--yellow)' : 'var(--red)';
302
+
303
+ // Coverage entries
304
+ const covHtml = d.coverage.entries.map(e => {
305
+ const tests = e.coveredBy.length > 0 ? e.coveredBy.join(', ') : 'none';
306
+ return '<div class="cov-entry ' + e.status + '">' +
307
+ '<span>' + (e.status === 'covered' ? '✅' : e.status === 'partial' ? '🟡' : '❌') + '</span>' +
308
+ '<span>' + e.invariant + '</span>' +
309
+ '<span class="tests">' + tests + '</span></div>';
310
+ }).join('') || '<div class="empty">No invariants found</div>';
311
+
312
+ // RFCs
313
+ const rfcHtml = d.rfcs.map(r => {
314
+ const title = r.title.replace(r.id + ': ', '');
315
+ return '<div class="item"><span class="item-id">' + r.id + '</span>' +
316
+ '<span class="item-text">' + title + '</span>' +
317
+ '<span class="item-status ' + r.status + '">' + r.status + '</span></div>';
318
+ }).join('') || '<div class="empty">No RFCs created</div>';
319
+
320
+ // Investigations
321
+ const invHtml = d.investigations.map(i => {
322
+ const title = i.title.replace(i.id + ': ', '');
323
+ return '<div class="item"><span class="item-id">' + i.id + '</span>' +
324
+ '<span class="item-text">' + title + '</span>' +
325
+ '<span class="item-status ' + i.status + '">' + i.status + '</span></div>';
326
+ }).join('') || '<div class="empty">No investigations</div>';
327
+
328
+ // Escalations
329
+ const escHtml = d.escalations.map(e =>
330
+ '<div class="item"><span class="item-id">' + e.id + '</span>' +
331
+ '<span class="flow-node ' + e.level + '">' + e.level + '</span>' +
332
+ '<span class="item-status ' + e.status + '">' + e.status + '</span></div>'
333
+ ).join('') || '<div class="empty">No escalations</div>';
334
+
335
+ // Validation errors
336
+ const errHtml = d.validation.errorList.map(e =>
337
+ '<div class="error-item"><div class="error-file">' + e.file + ':' + e.line + '</div>' +
338
+ '<div class="error-msg">' + e.message + '</div>' +
339
+ '<div class="error-fix">Fix: ' + e.fix + '</div></div>'
340
+ ).join('') || '<div class="empty" style="color: var(--green);">✅ All artifacts valid</div>';
341
+
342
+ document.getElementById('content').innerHTML =
343
+ // Row 1: Phase progress
344
+ '<div class="card full"><div class="card-title">Phase Progress</div><div class="phases">' + phaseHtml + '</div></div>' +
345
+
346
+ // Row 2: Stats + Coverage + Validation
347
+ '<div class="card"><div class="card-title">Overview</div><div class="stats">' +
348
+ '<div><div class="stat-value green">' + d.coverage.covered + '</div><div class="stat-label">Covered</div></div>' +
349
+ '<div><div class="stat-value yellow">' + d.coverage.partial + '</div><div class="stat-label">Partial</div></div>' +
350
+ '<div><div class="stat-value red">' + d.coverage.uncovered + '</div><div class="stat-label">Uncovered</div></div>' +
351
+ '</div></div>' +
352
+
353
+ '<div class="card"><div class="card-title">Coverage</div>' +
354
+ '<div class="coverage-pct" style="color:' + covColor + '">' + pct + '%</div>' +
355
+ '<div class="coverage-bar-container"><div class="coverage-bar"><div class="coverage-fill" style="width:' + pct + '%; background:' + covColor + '"></div></div></div>' +
356
+ '<div class="stat-label">' + d.coverage.covered + ' of ' + d.coverage.total + ' invariants fully tested</div></div>' +
357
+
358
+ '<div class="card"><div class="card-title">Validation</div>' +
359
+ '<div class="stat-value ' + (d.validation.errors > 0 ? 'red' : 'green') + '">' + d.validation.errors + '</div>' +
360
+ '<div class="stat-label">errors in ' + d.validation.total + ' artifacts</div></div>' +
361
+
362
+ // Row 3: Coverage + Errors
363
+ '<div class="card wide"><div class="card-title">Invariant Coverage Map</div><div class="items">' + covHtml + '</div></div>' +
364
+ '<div class="card"><div class="card-title">Validation Errors</div>' + errHtml + '</div>' +
365
+
366
+ // Row 4: RFCs + Investigations + Escalations
367
+ '<div class="card"><div class="card-title">📋 RFCs</div><div class="items">' + rfcHtml + '</div></div>' +
368
+ '<div class="card"><div class="card-title">🔬 Investigations</div><div class="items">' + invHtml + '</div></div>' +
369
+ '<div class="card"><div class="card-title">🚨 Escalations</div><div class="items">' + escHtml + '</div></div>';
370
+
371
+ document.getElementById('refresh-time').textContent = 'Last: ' + new Date().toLocaleTimeString() + ' · Auto-refresh 5s';
372
+ }
373
+
374
+ loadData();
375
+ setInterval(loadData, 5000);
376
+ </script>
377
+ </body>
378
+ </html>`;
379
+ }
380
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type ProjectState = 'greenfield' | 'brownfield' | 'upgrade' | 'initialized';
2
+ export declare function detectProjectState(cwd: string): ProjectState;
3
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,aAAa,CAAC;AA6BnF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAiB5D"}
@@ -0,0 +1,45 @@
1
+ import { readdirSync, existsSync, statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ const CODE_EXTENSIONS = new Set([
4
+ '.ts', '.tsx', '.js', '.jsx', '.py', '.go', '.rs', '.java',
5
+ '.c', '.cpp', '.h', '.cs', '.rb', '.php', '.swift', '.kt',
6
+ ]);
7
+ function hasCodeFiles(dir) {
8
+ try {
9
+ const entries = readdirSync(dir, { withFileTypes: true });
10
+ for (const entry of entries) {
11
+ if (entry.name.startsWith('.'))
12
+ continue;
13
+ if (entry.name === 'node_modules')
14
+ continue;
15
+ if (entry.isFile()) {
16
+ const ext = entry.name.substring(entry.name.lastIndexOf('.'));
17
+ if (CODE_EXTENSIONS.has(ext))
18
+ return true;
19
+ }
20
+ if (entry.isDirectory()) {
21
+ if (hasCodeFiles(join(dir, entry.name)))
22
+ return true;
23
+ }
24
+ }
25
+ }
26
+ catch {
27
+ // Permission errors, etc.
28
+ }
29
+ return false;
30
+ }
31
+ export function detectProjectState(cwd) {
32
+ const devkitDir = join(cwd, '.devkit');
33
+ const specifyDir = join(cwd, '.specify');
34
+ if (existsSync(devkitDir) && statSync(devkitDir).isDirectory()) {
35
+ return 'initialized';
36
+ }
37
+ if (existsSync(specifyDir) && statSync(specifyDir).isDirectory()) {
38
+ return 'upgrade';
39
+ }
40
+ if (hasCodeFiles(cwd)) {
41
+ return 'brownfield';
42
+ }
43
+ return 'greenfield';
44
+ }
45
+ //# sourceMappingURL=detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.js","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC5B,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO;IAC1D,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK;CAC5D,CAAC,CAAC;AAEH,SAAS,YAAY,CAAC,GAAW;IAC7B,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YACzC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;gBAAE,SAAS;YAE5C,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBACjB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC9D,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;oBAAE,OAAO,IAAI,CAAC;YAC9C,CAAC;YAED,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACtB,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;oBAAE,OAAO,IAAI,CAAC;YACzD,CAAC;QACL,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,0BAA0B;IAC9B,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAEzC,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAC7D,OAAO,aAAa,CAAC;IACzB,CAAC;IAED,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/D,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,YAAY,CAAC;IACxB,CAAC;IAED,OAAO,YAAY,CAAC;AACxB,CAAC"}
@@ -0,0 +1,11 @@
1
+ export type EscalationLevel = 'speckit' | 'archkit' | 'productkit' | 'researchkit';
2
+ export interface EscalationResult {
3
+ created: boolean;
4
+ id: string;
5
+ path: string;
6
+ level: EscalationLevel;
7
+ reason: string;
8
+ error?: string;
9
+ }
10
+ export declare function createEscalation(cwd: string, description: string, forceLevel?: EscalationLevel): EscalationResult;
11
+ //# sourceMappingURL=escalate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escalate.d.ts","sourceRoot":"","sources":["../src/escalate.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,aAAa,CAAC;AAEnF,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAuDD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,gBAAgB,CAgGjH"}
@@ -0,0 +1,133 @@
1
+ import { writeFileSync, existsSync, readdirSync, mkdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ const LEVEL_DESCRIPTIONS = {
4
+ speckit: 'Code bug — code doesn\'t match spec. Fix in SpecKit.',
5
+ archkit: 'Invariant violation — system breaks an architectural guarantee. Investigation needed.',
6
+ productkit: 'UX problem — system works but user experience is wrong. Product investigation needed.',
7
+ researchkit: 'Assumption rejected — a research assumption proved false. Research revision needed.',
8
+ };
9
+ function detectEscalationLevel(cwd, description) {
10
+ const lower = description.toLowerCase();
11
+ // Check for UX-related keywords → ProductKit
12
+ const uxKeywords = ['ux', 'user experience', 'usability', 'confusing', 'unintuitive',
13
+ 'hard to use', 'awkward', 'too many', 'parameters', 'complicated', 'неудобно',
14
+ 'непонятно', 'слишком', 'пользователь не'];
15
+ for (const kw of uxKeywords) {
16
+ if (lower.includes(kw)) {
17
+ return { level: 'productkit', reason: `UX issue detected ("${kw}"). Escalating to ProductKit.` };
18
+ }
19
+ }
20
+ // Check for assumption/research keywords → ResearchKit
21
+ const researchKeywords = ['assumption', 'assumed', 'we thought', 'turns out',
22
+ 'wrong assumption', 'predicted', 'expected market', 'feasibility',
23
+ 'предполагали', 'оказалось'];
24
+ for (const kw of researchKeywords) {
25
+ if (lower.includes(kw)) {
26
+ return { level: 'researchkit', reason: `Research assumption challenged ("${kw}"). Escalating to ResearchKit.` };
27
+ }
28
+ }
29
+ // Check for invariant/architecture keywords → ArchKit
30
+ const archKeywords = ['invariant', 'guarantee', 'architecture', 'design flaw',
31
+ 'fundamental', 'race condition', 'data loss', 'security', 'performance',
32
+ 'инвариант', 'архитектур', 'гарантия'];
33
+ for (const kw of archKeywords) {
34
+ if (lower.includes(kw)) {
35
+ return { level: 'archkit', reason: `Architectural issue detected ("${kw}"). Escalating to ArchKit.` };
36
+ }
37
+ }
38
+ // Check for bug/library keywords → ArchKit investigation
39
+ const bugKeywords = ['bug in', 'library', 'doesn\'t support', 'benchmark',
40
+ 'unexpected behavior', 'limitation', 'баг', 'либа не'];
41
+ for (const kw of bugKeywords) {
42
+ if (lower.includes(kw)) {
43
+ return { level: 'archkit', reason: `Technical blocker detected ("${kw}"). Opening ArchKit investigation.` };
44
+ }
45
+ }
46
+ // Default: code bug → SpecKit
47
+ return { level: 'speckit', reason: 'No specific escalation trigger found. Treating as code bug (SpecKit fix).' };
48
+ }
49
+ export function createEscalation(cwd, description, forceLevel) {
50
+ const devkitDir = join(cwd, '.devkit');
51
+ const escalationsDir = join(devkitDir, 'qa', 'escalations');
52
+ if (!existsSync(devkitDir)) {
53
+ return {
54
+ created: false, id: '', path: '', level: 'speckit', reason: '',
55
+ error: '.devkit/ not found. Run "devkit init" first.',
56
+ };
57
+ }
58
+ mkdirSync(escalationsDir, { recursive: true });
59
+ // Detect level
60
+ const { level, reason } = forceLevel
61
+ ? { level: forceLevel, reason: `Manually escalated to ${forceLevel}.` }
62
+ : detectEscalationLevel(cwd, description);
63
+ // Generate ID
64
+ const existingFiles = existsSync(escalationsDir) ? readdirSync(escalationsDir).filter(f => f.startsWith('ESC-')) : [];
65
+ const nextNum = existingFiles.length + 1;
66
+ const id = `ESC-${nextNum.toString().padStart(3, '0')}`;
67
+ const filename = `${id}.md`;
68
+ const filePath = join(escalationsDir, filename);
69
+ const today = new Date().toISOString().split('T')[0];
70
+ const lines = [];
71
+ lines.push(`# ${id}: ${description}`);
72
+ lines.push('');
73
+ lines.push(`DATE: ${today}`);
74
+ lines.push('STATUS: open');
75
+ lines.push(`TRIGGERED_BY: ${description}`);
76
+ lines.push(`ESCALATED_TO: ${level}`);
77
+ lines.push(`REASON: ${reason}`);
78
+ lines.push('');
79
+ lines.push('## Analysis');
80
+ lines.push('');
81
+ switch (level) {
82
+ case 'speckit':
83
+ lines.push('**Type**: Code bug (code ≠ spec)');
84
+ lines.push('**Action**: Fix in SpecKit, no escalation needed.');
85
+ lines.push('');
86
+ lines.push('### What went wrong');
87
+ lines.push('');
88
+ lines.push('### Fix');
89
+ lines.push('');
90
+ break;
91
+ case 'archkit':
92
+ lines.push('**Type**: Invariant violation or technical blocker');
93
+ lines.push('**Action**: Open Investigation in ArchKit (`devkit investigate "..."`');
94
+ lines.push('');
95
+ lines.push('### Which invariant/assumption is broken');
96
+ lines.push('');
97
+ lines.push('### Proposed investigation');
98
+ lines.push('');
99
+ break;
100
+ case 'productkit':
101
+ lines.push('**Type**: UX invariant violation');
102
+ lines.push('**Action**: ProductKit investigation — review ux_invariants.md');
103
+ lines.push('');
104
+ lines.push('### Which UX invariant is violated');
105
+ lines.push('');
106
+ lines.push('### User impact');
107
+ lines.push('');
108
+ break;
109
+ case 'researchkit':
110
+ lines.push('**Type**: Research assumption rejected');
111
+ lines.push('**Action**: ResearchKit revision — update assumptions.md');
112
+ lines.push('');
113
+ lines.push('### Which assumption proved false');
114
+ lines.push('');
115
+ lines.push('### What we now know');
116
+ lines.push('');
117
+ break;
118
+ }
119
+ lines.push('## Resolution');
120
+ lines.push('RESOLVED_BY: ');
121
+ lines.push('DATE_RESOLVED: ');
122
+ lines.push('DECISION_CREATED: ');
123
+ lines.push('');
124
+ writeFileSync(filePath, lines.join('\n'), 'utf-8');
125
+ return {
126
+ created: true,
127
+ id,
128
+ path: `qa/escalations/${filename}`,
129
+ level,
130
+ reason,
131
+ };
132
+ }
133
+ //# sourceMappingURL=escalate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escalate.js","sourceRoot":"","sources":["../src/escalate.ts"],"names":[],"mappings":"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"}
package/dist/gate.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { Phase } from './status.js';
2
+ export interface GateCondition {
3
+ description: string;
4
+ satisfied: boolean;
5
+ detail?: string;
6
+ }
7
+ export interface GateResult {
8
+ allowed: boolean;
9
+ currentPhase: Phase;
10
+ nextPhase: Phase | 'production';
11
+ conditions: GateCondition[];
12
+ }
13
+ export declare function checkGate(cwd: string, currentPhase: Phase): GateResult;
14
+ export declare function formatGate(result: GateResult): string;
15
+ //# sourceMappingURL=gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC;IACpB,SAAS,EAAE,KAAK,GAAG,YAAY,CAAC;IAChC,UAAU,EAAE,aAAa,EAAE,CAAC;CAC/B;AAsND,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,GAAG,UAAU,CAqBtE;AAWD,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAyBrD"}