@hustle-together/api-dev-tools 3.0.0 → 3.2.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.
- package/README.md +71 -0
- package/bin/cli.js +184 -14
- package/demo/audio/generate-all-narrations.js +124 -59
- package/demo/audio/generate-narration.js +120 -56
- package/demo/audio/narration-adam-timing.json +3086 -2077
- package/demo/audio/narration-adam.mp3 +0 -0
- package/demo/audio/narration-creature-timing.json +3094 -2085
- package/demo/audio/narration-creature.mp3 +0 -0
- package/demo/audio/narration-gaming-timing.json +3091 -2082
- package/demo/audio/narration-gaming.mp3 +0 -0
- package/demo/audio/narration-hope-timing.json +3072 -2063
- package/demo/audio/narration-hope.mp3 +0 -0
- package/demo/audio/narration-mark-timing.json +3090 -2081
- package/demo/audio/narration-mark.mp3 +0 -0
- package/demo/audio/voices-manifest.json +16 -16
- package/demo/workflow-demo.html +1528 -411
- package/hooks/api-workflow-check.py +2 -0
- package/hooks/enforce-deep-research.py +180 -0
- package/hooks/enforce-disambiguation.py +149 -0
- package/hooks/enforce-documentation.py +187 -0
- package/hooks/enforce-environment.py +249 -0
- package/hooks/enforce-interview.py +64 -1
- package/hooks/enforce-refactor.py +187 -0
- package/hooks/enforce-research.py +93 -46
- package/hooks/enforce-schema.py +186 -0
- package/hooks/enforce-scope.py +156 -0
- package/hooks/enforce-tdd-red.py +246 -0
- package/hooks/enforce-verify.py +186 -0
- package/hooks/verify-after-green.py +136 -6
- package/package.json +2 -1
- package/scripts/collect-test-results.ts +404 -0
- package/scripts/extract-parameters.ts +483 -0
- package/scripts/generate-test-manifest.ts +520 -0
- package/templates/CLAUDE-SECTION.md +84 -0
- package/templates/api-dev-state.json +45 -5
- package/templates/api-test/page.tsx +315 -0
- package/templates/api-test/test-structure/route.ts +269 -0
- package/templates/settings.json +36 -0
package/README.md
CHANGED
|
@@ -26,6 +26,22 @@ npx @hustle-together/api-dev-tools --scope=project
|
|
|
26
26
|
|
|
27
27
|
## What This Installs
|
|
28
28
|
|
|
29
|
+
```
|
|
30
|
+
.claude/
|
|
31
|
+
├── commands/ # Slash commands (*.md)
|
|
32
|
+
├── hooks/ # Enforcement hooks (*.py)
|
|
33
|
+
├── settings.json # Hook configuration
|
|
34
|
+
├── api-dev-state.json # Workflow state tracking
|
|
35
|
+
└── research/ # Cached research with freshness
|
|
36
|
+
|
|
37
|
+
scripts/
|
|
38
|
+
└── api-dev-tools/ # Manifest generation scripts (*.ts)
|
|
39
|
+
|
|
40
|
+
src/app/
|
|
41
|
+
├── api-test/ # Test UI page (if Next.js)
|
|
42
|
+
└── api/test-structure/# Parser API route (if Next.js)
|
|
43
|
+
```
|
|
44
|
+
|
|
29
45
|
### Slash Commands
|
|
30
46
|
|
|
31
47
|
Six powerful slash commands for Claude Code:
|
|
@@ -59,6 +75,20 @@ Python hooks that provide **real programmatic guarantees**:
|
|
|
59
75
|
- **`.claude/research/`** - Cached research with freshness tracking
|
|
60
76
|
- **`.claude/research/index.json`** - Research catalog with 7-day validity
|
|
61
77
|
|
|
78
|
+
### Manifest Generation Scripts (Programmatic, NO LLM)
|
|
79
|
+
|
|
80
|
+
Scripts that automatically generate documentation from test files:
|
|
81
|
+
|
|
82
|
+
| Script | Output | Purpose |
|
|
83
|
+
|--------|--------|---------|
|
|
84
|
+
| `generate-test-manifest.ts` | `api-tests-manifest.json` | Parses Vitest tests → full API manifest |
|
|
85
|
+
| `extract-parameters.ts` | `parameter-matrix.json` | Extracts Zod params → coverage matrix |
|
|
86
|
+
| `collect-test-results.ts` | `test-results.json` | Runs tests → results with pass/fail |
|
|
87
|
+
|
|
88
|
+
**Key principle:** Tests are the SOURCE OF TRUTH. Scripts parse source files programmatically. **NO LLM involvement** in manifest generation.
|
|
89
|
+
|
|
90
|
+
Scripts are triggered automatically after tests pass (Phase 8 → Phase 9) via `verify-after-green.py` hook.
|
|
91
|
+
|
|
62
92
|
## Complete Phase Flow (12 Phases)
|
|
63
93
|
|
|
64
94
|
```
|
|
@@ -115,6 +145,16 @@ Python hooks that provide **real programmatic guarantees**:
|
|
|
115
145
|
▼
|
|
116
146
|
┌─ PHASE 8: TDD GREEN ──────────────────────────┐
|
|
117
147
|
│ Minimal implementation to pass tests │
|
|
148
|
+
└───────────────────────────────────────────────┘
|
|
149
|
+
│
|
|
150
|
+
▼
|
|
151
|
+
┌─ MANIFEST GENERATION (Automatic) ─────────────┐
|
|
152
|
+
│ verify-after-green.py hook triggers: │
|
|
153
|
+
│ • generate-test-manifest.ts │
|
|
154
|
+
│ • extract-parameters.ts │
|
|
155
|
+
│ • collect-test-results.ts │
|
|
156
|
+
│ │
|
|
157
|
+
│ Output: api-tests-manifest.json (NO LLM) │
|
|
118
158
|
└───────────────────────────────────────────────┘
|
|
119
159
|
│
|
|
120
160
|
▼
|
|
@@ -302,6 +342,17 @@ Progress tracking. See [commands/api-status.md](commands/api-status.md).
|
|
|
302
342
|
"tdd_refactor": { "status": "complete" },
|
|
303
343
|
"documentation": { "status": "complete" }
|
|
304
344
|
},
|
|
345
|
+
"manifest_generation": {
|
|
346
|
+
"last_run": "2025-12-09T10:30:00.000Z",
|
|
347
|
+
"manifest_generated": true,
|
|
348
|
+
"parameters_extracted": true,
|
|
349
|
+
"test_results_collected": true,
|
|
350
|
+
"output_files": {
|
|
351
|
+
"manifest": "src/app/api-test/api-tests-manifest.json",
|
|
352
|
+
"parameters": "src/app/api-test/parameter-matrix.json",
|
|
353
|
+
"results": "src/app/api-test/test-results.json"
|
|
354
|
+
}
|
|
355
|
+
},
|
|
305
356
|
"reground_history": [
|
|
306
357
|
{ "turn": 7, "phase": "interview" },
|
|
307
358
|
{ "turn": 14, "phase": "tdd_red" }
|
|
@@ -351,6 +402,26 @@ Progress tracking. See [commands/api-status.md](commands/api-status.md).
|
|
|
351
402
|
└──────────────────────────────────────────────────────────┘
|
|
352
403
|
```
|
|
353
404
|
|
|
405
|
+
## Manual Script Usage
|
|
406
|
+
|
|
407
|
+
While scripts run automatically after tests pass, you can also run them manually:
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
# Generate manifest from test files
|
|
411
|
+
npx tsx scripts/api-dev-tools/generate-test-manifest.ts
|
|
412
|
+
|
|
413
|
+
# Extract parameters and calculate coverage
|
|
414
|
+
npx tsx scripts/api-dev-tools/extract-parameters.ts
|
|
415
|
+
|
|
416
|
+
# Collect test results (runs Vitest)
|
|
417
|
+
npx tsx scripts/api-dev-tools/collect-test-results.ts
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Output files are written to `src/app/api-test/`:
|
|
421
|
+
- `api-tests-manifest.json` - Complete API documentation
|
|
422
|
+
- `parameter-matrix.json` - Parameter coverage analysis
|
|
423
|
+
- `test-results.json` - Latest test run results
|
|
424
|
+
|
|
354
425
|
## Requirements
|
|
355
426
|
|
|
356
427
|
- **Node.js** 14.0.0 or higher
|
package/bin/cli.js
CHANGED
|
@@ -69,15 +69,29 @@ function verifyInstallation(claudeDir, hooksDir) {
|
|
|
69
69
|
{ path: path.join(claudeDir, 'research', 'index.json'), name: 'Research index' },
|
|
70
70
|
];
|
|
71
71
|
|
|
72
|
-
// Add hook checks if hooks directory exists (v3.0 has
|
|
72
|
+
// Add hook checks if hooks directory exists (v3.0 has 18 hooks for 100% phase enforcement with user checkpoints)
|
|
73
73
|
if (fs.existsSync(hooksDir)) {
|
|
74
74
|
checks.push(
|
|
75
|
-
|
|
76
|
-
{ path: path.join(hooksDir, 'track-tool-use.py'), name: 'track-tool-use.py' },
|
|
77
|
-
{ path: path.join(hooksDir, 'api-workflow-check.py'), name: 'api-workflow-check.py' },
|
|
75
|
+
// Core utility hooks (5)
|
|
78
76
|
{ path: path.join(hooksDir, 'session-startup.py'), name: 'session-startup.py' },
|
|
77
|
+
{ path: path.join(hooksDir, 'enforce-external-research.py'), name: 'enforce-external-research.py' },
|
|
78
|
+
{ path: path.join(hooksDir, 'track-tool-use.py'), name: 'track-tool-use.py' },
|
|
79
79
|
{ path: path.join(hooksDir, 'periodic-reground.py'), name: 'periodic-reground.py' },
|
|
80
|
-
{ path: path.join(hooksDir, '
|
|
80
|
+
{ path: path.join(hooksDir, 'api-workflow-check.py'), name: 'api-workflow-check.py' },
|
|
81
|
+
// Phase enforcement hooks with user checkpoints (12 - one per phase)
|
|
82
|
+
{ path: path.join(hooksDir, 'enforce-disambiguation.py'), name: 'enforce-disambiguation.py' },
|
|
83
|
+
{ path: path.join(hooksDir, 'enforce-scope.py'), name: 'enforce-scope.py' },
|
|
84
|
+
{ path: path.join(hooksDir, 'enforce-research.py'), name: 'enforce-research.py' },
|
|
85
|
+
{ path: path.join(hooksDir, 'enforce-interview.py'), name: 'enforce-interview.py' },
|
|
86
|
+
{ path: path.join(hooksDir, 'enforce-deep-research.py'), name: 'enforce-deep-research.py' },
|
|
87
|
+
{ path: path.join(hooksDir, 'enforce-schema.py'), name: 'enforce-schema.py' },
|
|
88
|
+
{ path: path.join(hooksDir, 'enforce-environment.py'), name: 'enforce-environment.py' },
|
|
89
|
+
{ path: path.join(hooksDir, 'enforce-tdd-red.py'), name: 'enforce-tdd-red.py' },
|
|
90
|
+
{ path: path.join(hooksDir, 'verify-implementation.py'), name: 'verify-implementation.py' },
|
|
91
|
+
{ path: path.join(hooksDir, 'verify-after-green.py'), name: 'verify-after-green.py' },
|
|
92
|
+
{ path: path.join(hooksDir, 'enforce-verify.py'), name: 'enforce-verify.py' },
|
|
93
|
+
{ path: path.join(hooksDir, 'enforce-refactor.py'), name: 'enforce-refactor.py' },
|
|
94
|
+
{ path: path.join(hooksDir, 'enforce-documentation.py'), name: 'enforce-documentation.py' }
|
|
81
95
|
);
|
|
82
96
|
}
|
|
83
97
|
|
|
@@ -267,6 +281,118 @@ function main() {
|
|
|
267
281
|
log(' ℹ️ Research index already exists (preserved)', 'blue');
|
|
268
282
|
}
|
|
269
283
|
|
|
284
|
+
// ========================================
|
|
285
|
+
// 4c. Install Test UI (Parser API + Page)
|
|
286
|
+
// ========================================
|
|
287
|
+
log('\n🧪 Setting up Test UI:', 'cyan');
|
|
288
|
+
|
|
289
|
+
const testUiSourceDir = path.join(sourceTemplatesDir, 'api-test');
|
|
290
|
+
const hasNextJs = fs.existsSync(path.join(targetDir, 'next.config.js')) ||
|
|
291
|
+
fs.existsSync(path.join(targetDir, 'next.config.mjs')) ||
|
|
292
|
+
fs.existsSync(path.join(targetDir, 'next.config.ts'));
|
|
293
|
+
|
|
294
|
+
if (!hasNextJs) {
|
|
295
|
+
log(' ⚠️ Next.js not detected - skipping Test UI installation', 'yellow');
|
|
296
|
+
log(' 💡 Test UI requires Next.js App Router', 'yellow');
|
|
297
|
+
} else if (fs.existsSync(testUiSourceDir)) {
|
|
298
|
+
// Detect App Router structure
|
|
299
|
+
const appDir = fs.existsSync(path.join(targetDir, 'src', 'app'))
|
|
300
|
+
? path.join(targetDir, 'src', 'app')
|
|
301
|
+
: fs.existsSync(path.join(targetDir, 'app'))
|
|
302
|
+
? path.join(targetDir, 'app')
|
|
303
|
+
: null;
|
|
304
|
+
|
|
305
|
+
if (!appDir) {
|
|
306
|
+
log(' ⚠️ App Router not detected - skipping Test UI installation', 'yellow');
|
|
307
|
+
log(' 💡 Test UI requires Next.js App Router (app/ or src/app/)', 'yellow');
|
|
308
|
+
} else {
|
|
309
|
+
// Install test-structure API route
|
|
310
|
+
const apiTestStructureDir = path.join(appDir, 'api', 'test-structure');
|
|
311
|
+
const apiTestStructureSource = path.join(testUiSourceDir, 'test-structure', 'route.ts');
|
|
312
|
+
const apiTestStructureDest = path.join(apiTestStructureDir, 'route.ts');
|
|
313
|
+
|
|
314
|
+
if (!fs.existsSync(apiTestStructureDir)) {
|
|
315
|
+
fs.mkdirSync(apiTestStructureDir, { recursive: true });
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (!fs.existsSync(apiTestStructureDest)) {
|
|
319
|
+
try {
|
|
320
|
+
fs.copyFileSync(apiTestStructureSource, apiTestStructureDest);
|
|
321
|
+
log(' ✅ Created /api/test-structure route (parses Vitest files)', 'green');
|
|
322
|
+
} catch (error) {
|
|
323
|
+
log(` ❌ Failed to create test-structure API: ${error.message}`, 'red');
|
|
324
|
+
}
|
|
325
|
+
} else {
|
|
326
|
+
log(' ℹ️ /api/test-structure already exists (preserved)', 'blue');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Install test UI page
|
|
330
|
+
const apiTestPageDir = path.join(appDir, 'api-test');
|
|
331
|
+
const apiTestPageSource = path.join(testUiSourceDir, 'page.tsx');
|
|
332
|
+
const apiTestPageDest = path.join(apiTestPageDir, 'page.tsx');
|
|
333
|
+
|
|
334
|
+
if (!fs.existsSync(apiTestPageDir)) {
|
|
335
|
+
fs.mkdirSync(apiTestPageDir, { recursive: true });
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (!fs.existsSync(apiTestPageDest)) {
|
|
339
|
+
try {
|
|
340
|
+
fs.copyFileSync(apiTestPageSource, apiTestPageDest);
|
|
341
|
+
log(' ✅ Created /api-test page (displays test structure)', 'green');
|
|
342
|
+
} catch (error) {
|
|
343
|
+
log(` ❌ Failed to create test UI page: ${error.message}`, 'red');
|
|
344
|
+
}
|
|
345
|
+
} else {
|
|
346
|
+
log(' ℹ️ /api-test page already exists (preserved)', 'blue');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
log(' 💡 Test UI available at http://localhost:3000/api-test', 'yellow');
|
|
350
|
+
}
|
|
351
|
+
} else {
|
|
352
|
+
log(' ⚠️ Test UI templates not found in package', 'yellow');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// ========================================
|
|
356
|
+
// 4d. Install Manifest Generation Scripts
|
|
357
|
+
// ========================================
|
|
358
|
+
log('\n📊 Setting up manifest generation scripts:', 'cyan');
|
|
359
|
+
|
|
360
|
+
const sourceScriptsDir = path.join(packageDir, 'scripts');
|
|
361
|
+
const targetScriptsDir = path.join(targetDir, 'scripts', 'api-dev-tools');
|
|
362
|
+
|
|
363
|
+
if (fs.existsSync(sourceScriptsDir)) {
|
|
364
|
+
if (!fs.existsSync(targetScriptsDir)) {
|
|
365
|
+
fs.mkdirSync(targetScriptsDir, { recursive: true });
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const scriptFiles = fs.readdirSync(sourceScriptsDir).filter(file =>
|
|
369
|
+
file.endsWith('.ts')
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
if (scriptFiles.length > 0) {
|
|
373
|
+
scriptFiles.forEach(file => {
|
|
374
|
+
const source = path.join(sourceScriptsDir, file);
|
|
375
|
+
const dest = path.join(targetScriptsDir, file);
|
|
376
|
+
|
|
377
|
+
try {
|
|
378
|
+
fs.copyFileSync(source, dest);
|
|
379
|
+
log(` ✅ ${file}`, 'green');
|
|
380
|
+
} catch (error) {
|
|
381
|
+
log(` ❌ Failed to copy ${file}: ${error.message}`, 'red');
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
log('\n Script purposes:', 'blue');
|
|
386
|
+
log(' • generate-test-manifest.ts - Parses tests → manifest (NO LLM)', 'blue');
|
|
387
|
+
log(' • extract-parameters.ts - Extracts Zod params → matrix', 'blue');
|
|
388
|
+
log(' • collect-test-results.ts - Runs Vitest → results JSON', 'blue');
|
|
389
|
+
log('\n 💡 Scripts run automatically after tests pass (Phase 8 → 9)', 'yellow');
|
|
390
|
+
log(' 💡 Manual: npx tsx scripts/api-dev-tools/generate-test-manifest.ts', 'yellow');
|
|
391
|
+
}
|
|
392
|
+
} else {
|
|
393
|
+
log(' ⚠️ Scripts directory not found in package', 'yellow');
|
|
394
|
+
}
|
|
395
|
+
|
|
270
396
|
// ========================================
|
|
271
397
|
// 5. Install MCP Servers via CLI (Context7, GitHub)
|
|
272
398
|
// ========================================
|
|
@@ -302,6 +428,42 @@ function main() {
|
|
|
302
428
|
log('\n ⚠️ GitHub MCP requires GITHUB_PERSONAL_ACCESS_TOKEN in env', 'yellow');
|
|
303
429
|
log(' 💡 Restart Claude Code for MCP tools to be available', 'yellow');
|
|
304
430
|
|
|
431
|
+
// ========================================
|
|
432
|
+
// 6. Update CLAUDE.md with workflow documentation
|
|
433
|
+
// ========================================
|
|
434
|
+
const claudeMdSection = path.join(sourceTemplatesDir, 'CLAUDE-SECTION.md');
|
|
435
|
+
const projectClaudeMd = path.join(targetDir, 'CLAUDE.md');
|
|
436
|
+
|
|
437
|
+
if (fs.existsSync(claudeMdSection)) {
|
|
438
|
+
log('\n📝 CLAUDE.md workflow documentation:', 'cyan');
|
|
439
|
+
|
|
440
|
+
const sectionContent = fs.readFileSync(claudeMdSection, 'utf8');
|
|
441
|
+
const sectionMarker = '## API Development Workflow (v3.0)';
|
|
442
|
+
|
|
443
|
+
if (fs.existsSync(projectClaudeMd)) {
|
|
444
|
+
const existingContent = fs.readFileSync(projectClaudeMd, 'utf8');
|
|
445
|
+
|
|
446
|
+
if (existingContent.includes(sectionMarker)) {
|
|
447
|
+
// Update existing section
|
|
448
|
+
const beforeSection = existingContent.split(sectionMarker)[0];
|
|
449
|
+
// Find the next ## heading or end of file
|
|
450
|
+
const afterMatch = existingContent.match(/## API Development Workflow[\s\S]*?((?=\n## )|$)/);
|
|
451
|
+
const afterSection = afterMatch ? existingContent.substring(existingContent.indexOf(afterMatch[0]) + afterMatch[0].length) : '';
|
|
452
|
+
|
|
453
|
+
fs.writeFileSync(projectClaudeMd, beforeSection + sectionContent + afterSection);
|
|
454
|
+
log(' ✅ Updated API Development Workflow section in CLAUDE.md', 'green');
|
|
455
|
+
} else {
|
|
456
|
+
// Append section
|
|
457
|
+
fs.appendFileSync(projectClaudeMd, '\n\n' + sectionContent);
|
|
458
|
+
log(' ✅ Added API Development Workflow section to CLAUDE.md', 'green');
|
|
459
|
+
}
|
|
460
|
+
} else {
|
|
461
|
+
// Create new CLAUDE.md with section
|
|
462
|
+
fs.writeFileSync(projectClaudeMd, '# Project Instructions\n\n' + sectionContent);
|
|
463
|
+
log(' ✅ Created CLAUDE.md with API Development Workflow section', 'green');
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
305
467
|
// ========================================
|
|
306
468
|
// Success Summary
|
|
307
469
|
// ========================================
|
|
@@ -311,25 +473,33 @@ function main() {
|
|
|
311
473
|
|
|
312
474
|
log('📋 What was installed:', 'bright');
|
|
313
475
|
log(' Commands: .claude/commands/*.md', 'blue');
|
|
314
|
-
log(' Hooks: .claude/hooks/*.py (
|
|
476
|
+
log(' Hooks: .claude/hooks/*.py (18 hooks for 100% enforcement + user checkpoints)', 'blue');
|
|
315
477
|
log(' Settings: .claude/settings.json', 'blue');
|
|
316
478
|
log(' State: .claude/api-dev-state.json', 'blue');
|
|
317
479
|
log(' Research: .claude/research/ (with freshness tracking)', 'blue');
|
|
480
|
+
log(' Scripts: scripts/api-dev-tools/*.ts (manifest generation)', 'blue');
|
|
318
481
|
log(' MCP: context7, github (via claude mcp add)', 'blue');
|
|
482
|
+
log(' Test UI: /api-test page + /api/test-structure API (if Next.js)', 'blue');
|
|
319
483
|
|
|
320
484
|
log('\n🆕 New in v3.0:', 'bright');
|
|
321
|
-
log(' •
|
|
322
|
-
log(' •
|
|
485
|
+
log(' • 12 phases, each with mandatory user checkpoint', 'cyan');
|
|
486
|
+
log(' • AskUserQuestion required at EVERY phase transition', 'cyan');
|
|
487
|
+
log(' • Loop-back support when user wants changes', 'cyan');
|
|
323
488
|
log(' • Adaptive research (propose-approve, not shotgun)', 'cyan');
|
|
324
|
-
log(' • Questions generated FROM research findings', 'cyan');
|
|
325
489
|
log(' • 7-turn re-grounding (prevents context dilution)', 'cyan');
|
|
326
490
|
log(' • Research freshness (7-day cache validity)', 'cyan');
|
|
327
491
|
|
|
328
|
-
log('\n🔒 Enforcement
|
|
329
|
-
log(' •
|
|
330
|
-
log(' •
|
|
331
|
-
log(' •
|
|
332
|
-
log(' •
|
|
492
|
+
log('\n🔒 User Checkpoint Enforcement:', 'bright');
|
|
493
|
+
log(' • Phase 0: "Which interpretation?" (disambiguation)', 'cyan');
|
|
494
|
+
log(' • Phase 1: "Scope correct?" (scope confirmation)', 'cyan');
|
|
495
|
+
log(' • Phase 2: "Proceed to interview?" (research summary)', 'cyan');
|
|
496
|
+
log(' • Phase 3: "Interview complete?" (all questions answered)', 'cyan');
|
|
497
|
+
log(' • Phase 4: "Approve searches?" (deep research proposal)', 'cyan');
|
|
498
|
+
log(' • Phase 5: "Schema matches interview?" (schema review)', 'cyan');
|
|
499
|
+
log(' • Phase 6: "Ready for testing?" (environment check)', 'cyan');
|
|
500
|
+
log(' • Phase 7: "Test plan looks good?" (test matrix)', 'cyan');
|
|
501
|
+
log(' • Phase 9: "Fix gaps?" (verification decision)', 'cyan');
|
|
502
|
+
log(' • Phase 11: "Documentation complete?" (final checklist)', 'cyan');
|
|
333
503
|
|
|
334
504
|
log('\n📚 Available Commands:', 'bright');
|
|
335
505
|
log(' /api-create [endpoint] - Complete 12-phase workflow', 'blue');
|
|
@@ -54,27 +54,25 @@ const VOICES = [
|
|
|
54
54
|
];
|
|
55
55
|
|
|
56
56
|
// The narration script with section markers and highlight triggers
|
|
57
|
+
// Format: [SECTION:id] marks a new section, [HIGHLIGHT:element-selector] marks what to highlight
|
|
57
58
|
const NARRATION_SCRIPT = `
|
|
58
59
|
[SECTION:intro]
|
|
59
|
-
Welcome to Hustle API Dev Tools.
|
|
60
|
+
Welcome to Hustle API Dev Tools, version three point oh.
|
|
60
61
|
|
|
61
62
|
[HIGHLIGHT:#hustleBrand]
|
|
62
|
-
This package enforces a structured workflow for AI-assisted API development.
|
|
63
|
+
This package enforces a structured, twelve-phase workflow for AI-assisted API development.
|
|
63
64
|
|
|
64
65
|
[HIGHLIGHT:[data-phase="research"]]
|
|
65
|
-
|
|
66
|
+
Research first. No assumptions. No training data. Real documentation from Context7 and web search.
|
|
66
67
|
|
|
67
68
|
[HIGHLIGHT:[data-phase="interview"]]
|
|
68
|
-
|
|
69
|
+
Interview second. The AI asks YOU questions with structured options based on what it actually found.
|
|
69
70
|
|
|
70
71
|
[HIGHLIGHT:[data-phase="test"]]
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
[HIGHLIGHT:[data-phase="code"]]
|
|
74
|
-
Only then do you write code. Minimal. Just enough to pass the tests.
|
|
72
|
+
Test before code. Red, green, refactor. No implementation without a failing test.
|
|
75
73
|
|
|
76
74
|
[HIGHLIGHT:[data-phase="docs"]]
|
|
77
|
-
|
|
75
|
+
Document everything. Every endpoint documented with real examples and schemas.
|
|
78
76
|
|
|
79
77
|
The philosophy is simple: Hustle together. Share resources. Build stronger.
|
|
80
78
|
|
|
@@ -83,72 +81,136 @@ The philosophy is simple: Hustle together. Share resources. Build stronger.
|
|
|
83
81
|
Let's talk about the problem. What goes wrong when AI builds APIs without structure?
|
|
84
82
|
|
|
85
83
|
[HIGHLIGHT:.gap-item:nth-child(1)]
|
|
86
|
-
Gap one: AI doesn't use your exact words. You say
|
|
84
|
+
Gap one: AI doesn't use your exact words. You say Brandfetch API but it searches for something else. Wrong library. Wrong documentation.
|
|
87
85
|
|
|
88
86
|
[HIGHLIGHT:.gap-item:nth-child(2)]
|
|
89
|
-
Gap two:
|
|
87
|
+
Gap two: Generic questions. Without research first, the AI asks template questions instead of specific ones based on actual API capabilities.
|
|
90
88
|
|
|
91
89
|
[HIGHLIGHT:.gap-item:nth-child(3)]
|
|
92
|
-
Gap three:
|
|
90
|
+
Gap three: Memory-based implementation. After research, the AI forgets what it learned and implements from training data instead.
|
|
93
91
|
|
|
94
92
|
[HIGHLIGHT:.gap-item:nth-child(4)]
|
|
95
|
-
Gap four:
|
|
93
|
+
Gap four: No verification after tests pass. The AI writes code that passes tests but doesn't match the actual documentation.
|
|
96
94
|
|
|
97
95
|
[HIGHLIGHT:.gap-item:nth-child(5)]
|
|
98
|
-
Gap five:
|
|
96
|
+
Gap five: Context dilution. After many turns, the AI forgets project structure, documentation locations, and workflow requirements.
|
|
99
97
|
|
|
100
|
-
These gaps compound.
|
|
98
|
+
These gaps compound. Version three solves all of them with loop-back architecture and continuous re-grounding.
|
|
101
99
|
|
|
102
100
|
[SECTION:solution]
|
|
103
101
|
[HIGHLIGHT:#solution h2]
|
|
104
102
|
The solution is enforcement. Python hooks that intercept every tool call.
|
|
105
103
|
|
|
106
|
-
[HIGHLIGHT:.
|
|
107
|
-
PreToolUse hooks run before Claude
|
|
104
|
+
[HIGHLIGHT:.hook-box:nth-child(1)]
|
|
105
|
+
PreToolUse hooks run before Claude writes any file. They inject interview decisions as reminders and block writes without research.
|
|
106
|
+
|
|
107
|
+
[HIGHLIGHT:.hook-box:nth-child(2)]
|
|
108
|
+
PostToolUse hooks track tool usage and trigger verification. After tests pass, they force Phase nine: re-read the documentation.
|
|
108
109
|
|
|
109
|
-
[HIGHLIGHT:.
|
|
110
|
-
|
|
110
|
+
[HIGHLIGHT:.hook-box:nth-child(3)]
|
|
111
|
+
The Stop hook blocks completion if any phase is incomplete. No more premature "done" declarations.
|
|
111
112
|
|
|
112
|
-
[HIGHLIGHT:.
|
|
113
|
-
|
|
113
|
+
[HIGHLIGHT:.hook-box:nth-child(4)]
|
|
114
|
+
SessionStart and periodic hooks re-inject context every seven turns to prevent dilution in long sessions.
|
|
114
115
|
|
|
115
116
|
This isn't about limiting AI. It's about holding it to the same standards we hold ourselves.
|
|
116
117
|
|
|
117
|
-
[SECTION:
|
|
118
|
-
[HIGHLIGHT:#
|
|
119
|
-
The workflow has
|
|
118
|
+
[SECTION:phases]
|
|
119
|
+
[HIGHLIGHT:#phases h2]
|
|
120
|
+
The workflow now has twelve phases. Two new ones in version three.
|
|
121
|
+
|
|
122
|
+
[HIGHLIGHT:[data-phase="0"]]
|
|
123
|
+
Phase zero: Disambiguation. When you say Vercel AI, do you mean the SDK or the Gateway? We clarify before researching.
|
|
124
|
+
|
|
125
|
+
[HIGHLIGHT:[data-phase="1"]]
|
|
126
|
+
Phase one: Scope. Confirm we understand what you want to build.
|
|
127
|
+
|
|
128
|
+
[HIGHLIGHT:[data-phase="2"]]
|
|
129
|
+
Phase two: Initial research. Context7 and web search. Find the real documentation.
|
|
130
|
+
|
|
131
|
+
[HIGHLIGHT:[data-phase="3"]]
|
|
132
|
+
Phase three: Interview. Questions generated FROM research findings. Not generic templates.
|
|
133
|
+
|
|
134
|
+
[HIGHLIGHT:[data-phase="4"]]
|
|
135
|
+
Phase four: Deep research. Based on your interview answers, we propose targeted follow-up searches. Adaptive, not shotgun.
|
|
136
|
+
|
|
137
|
+
[HIGHLIGHT:[data-phase="5"]]
|
|
138
|
+
Phase five: Schema. Define Zod schemas based on research plus interview decisions.
|
|
139
|
+
|
|
140
|
+
[HIGHLIGHT:[data-phase="6"]]
|
|
141
|
+
Phase six: Environment. Verify API keys exist before writing code.
|
|
142
|
+
|
|
143
|
+
[HIGHLIGHT:[data-phase="7"]]
|
|
144
|
+
Phase seven: TDD Red. Write failing tests. Define success before implementation.
|
|
145
|
+
|
|
146
|
+
[HIGHLIGHT:[data-phase="8"]]
|
|
147
|
+
Phase eight: TDD Green. Minimal code to pass tests. Interview decisions injected by hooks.
|
|
148
|
+
|
|
149
|
+
[HIGHLIGHT:[data-phase="9"]]
|
|
150
|
+
Phase nine: Verify. This is new. Re-read the original documentation and compare to implementation. Find gaps. Loop back if needed.
|
|
151
|
+
|
|
152
|
+
[HIGHLIGHT:[data-phase="10"]]
|
|
153
|
+
Phase ten: Refactor. Clean up code while tests stay green.
|
|
120
154
|
|
|
121
|
-
[HIGHLIGHT
|
|
122
|
-
Phase
|
|
155
|
+
[HIGHLIGHT:[data-phase="11"]]
|
|
156
|
+
Phase eleven: Documentation. Update OpenAPI spec and test manifest.
|
|
123
157
|
|
|
124
|
-
[HIGHLIGHT
|
|
125
|
-
Phase
|
|
158
|
+
[HIGHLIGHT:[data-phase="12"]]
|
|
159
|
+
Phase twelve: Complete. Final verification by the Stop hook.
|
|
126
160
|
|
|
127
|
-
|
|
128
|
-
Phase three: Interview. Ask the user questions with multiple choice options. What provider? What format? What error handling?
|
|
161
|
+
Every phase can loop back. If verification finds gaps, we return to Red and write tests for missing features.
|
|
129
162
|
|
|
130
|
-
[
|
|
131
|
-
|
|
163
|
+
[SECTION:demo]
|
|
164
|
+
[HIGHLIGHT:#demo h2]
|
|
165
|
+
Let's watch a real example. Creating a Brandfetch API endpoint.
|
|
132
166
|
|
|
133
|
-
[HIGHLIGHT
|
|
134
|
-
|
|
167
|
+
[HIGHLIGHT:[data-step="0"]]
|
|
168
|
+
The user types /api-create brandfetch. The twelve-phase workflow begins.
|
|
135
169
|
|
|
136
|
-
[HIGHLIGHT
|
|
137
|
-
|
|
170
|
+
[HIGHLIGHT:[data-step="1"]]
|
|
171
|
+
Claude confirms scope. We're building an endpoint to fetch brand assets by domain.
|
|
138
172
|
|
|
139
|
-
[HIGHLIGHT
|
|
140
|
-
|
|
173
|
+
[HIGHLIGHT:[data-step="2"]]
|
|
174
|
+
Initial research. Claude uses Context7 to find the SDK documentation. WebSearch finds rate limits and response formats.
|
|
141
175
|
|
|
142
|
-
[HIGHLIGHT
|
|
143
|
-
|
|
176
|
+
[HIGHLIGHT:[data-step="3"]]
|
|
177
|
+
Interview begins. But notice: the questions are specific to what Claude actually found. What's the primary purpose? Options come from the documentation.
|
|
144
178
|
|
|
145
|
-
[HIGHLIGHT
|
|
146
|
-
|
|
179
|
+
[HIGHLIGHT:[data-step="4"]]
|
|
180
|
+
User selects: Full brand kit with logos, colors, and fonts.
|
|
147
181
|
|
|
148
|
-
[HIGHLIGHT
|
|
149
|
-
|
|
182
|
+
[HIGHLIGHT:[data-step="5"]]
|
|
183
|
+
More questions. How should API keys be handled? User selects server environment variables only.
|
|
150
184
|
|
|
151
|
-
|
|
185
|
+
[HIGHLIGHT:[data-step="7"]]
|
|
186
|
+
Deep research. Based on your selections, Claude proposes specific searches for the full brand response format.
|
|
187
|
+
|
|
188
|
+
[HIGHLIGHT:[data-step="8"]]
|
|
189
|
+
Schema created. Zod types based on research plus interview decisions.
|
|
190
|
+
|
|
191
|
+
[HIGHLIGHT:[data-step="9"]]
|
|
192
|
+
Environment check. The hook verifies BRANDFETCH_API_KEY exists.
|
|
193
|
+
|
|
194
|
+
[HIGHLIGHT:[data-step="10"]]
|
|
195
|
+
TDD Red. Claude writes twelve failing test cases.
|
|
196
|
+
|
|
197
|
+
[HIGHLIGHT:[data-step="11"]]
|
|
198
|
+
TDD Green. Implementation begins. Watch the hook inject interview decisions.
|
|
199
|
+
|
|
200
|
+
[HIGHLIGHT:[data-step="12"]]
|
|
201
|
+
The hook reminds Claude: Remember user decisions. Purpose: full brand kit. API key handling: server only.
|
|
202
|
+
|
|
203
|
+
[HIGHLIGHT:[data-step="13"]]
|
|
204
|
+
Phase nine: Verify. Claude re-reads the Brandfetch documentation and compares to implementation. All features accounted for.
|
|
205
|
+
|
|
206
|
+
[HIGHLIGHT:[data-step="14"]]
|
|
207
|
+
Refactor. Code cleaned up. Tests still pass.
|
|
208
|
+
|
|
209
|
+
[HIGHLIGHT:[data-step="15"]]
|
|
210
|
+
Documentation updated. API test manifest and OpenAPI spec.
|
|
211
|
+
|
|
212
|
+
[HIGHLIGHT:[data-step="16"]]
|
|
213
|
+
Complete. All twelve phases verified. Four files created. Twelve tests passing.
|
|
152
214
|
|
|
153
215
|
[SECTION:installation]
|
|
154
216
|
[HIGHLIGHT:#installation h2]
|
|
@@ -157,33 +219,29 @@ Installation takes one command.
|
|
|
157
219
|
[HIGHLIGHT:.install-command]
|
|
158
220
|
Run npx @hustle-together/api-dev-tools. That's it.
|
|
159
221
|
|
|
160
|
-
The CLI copies slash commands
|
|
222
|
+
The CLI copies slash commands, Python hooks, and settings. It creates the research cache folder and updates your CLAUDE.md with workflow documentation.
|
|
161
223
|
|
|
162
|
-
|
|
224
|
+
Version three adds automatic CLAUDE.md updates so Claude understands the workflow in your project.
|
|
163
225
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
And it offers to add the Context7 MCP server for live documentation lookup.
|
|
167
|
-
|
|
168
|
-
Your project is now enforced. Every API you build follows the workflow.
|
|
226
|
+
Your project is now enforced. Every API follows the twelve-phase workflow.
|
|
169
227
|
|
|
170
228
|
[SECTION:credits]
|
|
171
229
|
[HIGHLIGHT:#credits h2]
|
|
172
230
|
This project builds on the work of others.
|
|
173
231
|
|
|
174
|
-
The TDD workflow
|
|
232
|
+
The TDD workflow is based on @wbern/claude-instructions by William Bernmalm.
|
|
175
233
|
|
|
176
|
-
|
|
234
|
+
Context7 provides live documentation lookup. Current docs, not stale training data.
|
|
177
235
|
|
|
178
|
-
And
|
|
236
|
+
And the interview methodology ensures questions come from research, not templates.
|
|
179
237
|
|
|
180
238
|
Thank you to the Claude Code community. Together, we're making AI development better.
|
|
181
239
|
|
|
182
240
|
[SECTION:outro]
|
|
183
241
|
[HIGHLIGHT:#intro]
|
|
184
|
-
Hustle API Dev Tools
|
|
242
|
+
Hustle API Dev Tools version three. Twelve phases. Loop-back architecture. Continuous verification.
|
|
185
243
|
|
|
186
|
-
|
|
244
|
+
Research first. Questions FROM findings. Verify after green. Document always.
|
|
187
245
|
|
|
188
246
|
Install it now with npx @hustle-together/api-dev-tools.
|
|
189
247
|
`.trim();
|
|
@@ -221,11 +279,18 @@ function parseMarkers(script) {
|
|
|
221
279
|
}
|
|
222
280
|
|
|
223
281
|
// Check for highlight marker
|
|
224
|
-
|
|
282
|
+
// Use a more robust regex that handles nested brackets like [data-phase="0"]
|
|
283
|
+
const highlightMatch = line.match(/\[HIGHLIGHT:(.+?)\]$/);
|
|
225
284
|
if (highlightMatch) {
|
|
285
|
+
// Extract the selector - handle double brackets for attribute selectors
|
|
286
|
+
let selector = highlightMatch[1];
|
|
287
|
+
// If selector starts with [ but doesn't end with ], add the closing bracket
|
|
288
|
+
if (selector.startsWith('[') && !selector.endsWith(']')) {
|
|
289
|
+
selector = selector + ']';
|
|
290
|
+
}
|
|
226
291
|
markers.push({
|
|
227
292
|
type: 'highlight',
|
|
228
|
-
selector:
|
|
293
|
+
selector: selector,
|
|
229
294
|
section: currentSection,
|
|
230
295
|
charPosition
|
|
231
296
|
});
|