@hustle-together/api-dev-tools 2.0.7 → 3.1.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 +343 -467
- package/bin/cli.js +229 -15
- package/commands/README.md +124 -251
- package/commands/api-create.md +318 -136
- package/commands/api-interview.md +252 -256
- package/commands/api-research.md +209 -234
- package/commands/api-verify.md +231 -0
- package/demo/audio/generate-all-narrations.js +581 -0
- package/demo/audio/generate-narration.js +120 -56
- package/demo/audio/generate-voice-previews.js +140 -0
- package/demo/audio/narration-adam-timing.json +4675 -0
- package/demo/audio/narration-adam.mp3 +0 -0
- package/demo/audio/narration-creature-timing.json +4675 -0
- package/demo/audio/narration-creature.mp3 +0 -0
- package/demo/audio/narration-gaming-timing.json +4675 -0
- package/demo/audio/narration-gaming.mp3 +0 -0
- package/demo/audio/narration-hope-timing.json +4675 -0
- package/demo/audio/narration-hope.mp3 +0 -0
- package/demo/audio/narration-mark-timing.json +4675 -0
- package/demo/audio/narration-mark.mp3 +0 -0
- package/demo/audio/previews/manifest.json +30 -0
- package/demo/audio/previews/preview-creature.mp3 +0 -0
- package/demo/audio/previews/preview-gaming.mp3 +0 -0
- package/demo/audio/previews/preview-hope.mp3 +0 -0
- package/demo/audio/previews/preview-mark.mp3 +0 -0
- package/demo/audio/voices-manifest.json +50 -0
- package/demo/hustle-together/blog/gemini-vs-claude-widgets.html +30 -28
- package/demo/hustle-together/blog/interview-driven-api-development.html +37 -23
- package/demo/hustle-together/index.html +142 -109
- package/demo/workflow-demo.html +2618 -1036
- 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-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/periodic-reground.py +154 -0
- package/hooks/session-startup.py +151 -0
- package/hooks/track-tool-use.py +109 -17
- package/hooks/verify-after-green.py +282 -0
- package/package.json +3 -2
- 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 +83 -8
- package/templates/api-test/page.tsx +315 -0
- package/templates/api-test/test-structure/route.ts +269 -0
- package/templates/research-index.json +6 -0
- package/templates/settings.json +59 -0
|
Binary file
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generated": "2025-12-08T06:50:32.727Z",
|
|
3
|
+
"text": "Welcome to Hustle API Dev Tools. Build APIs the right way. Research first. Interview second. Test before code. Document everything.",
|
|
4
|
+
"voices": [
|
|
5
|
+
{
|
|
6
|
+
"voice": "Mark",
|
|
7
|
+
"id": "UgBBYS2sOqTuMpoF3BR0",
|
|
8
|
+
"file": "preview-mark.mp3",
|
|
9
|
+
"size": 164302
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"voice": "Hope",
|
|
13
|
+
"id": "tnSpp4vdxKPjI9w0GnoV",
|
|
14
|
+
"file": "preview-hope.mp3",
|
|
15
|
+
"size": 135881
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"voice": "Creature",
|
|
19
|
+
"id": "Z7RrOqZFTyLpIlzCgfsp",
|
|
20
|
+
"file": "preview-creature.mp3",
|
|
21
|
+
"size": 288018
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"voice": "Gaming",
|
|
25
|
+
"id": "YOq2y2Up4RgXP2HyXjE5",
|
|
26
|
+
"file": "preview-gaming.mp3",
|
|
27
|
+
"size": 329814
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generated": "2025-12-09T04:43:32.000Z",
|
|
3
|
+
"voices": [
|
|
4
|
+
{
|
|
5
|
+
"voice": "Adam",
|
|
6
|
+
"name": "adam",
|
|
7
|
+
"audioFile": "narration-adam.mp3",
|
|
8
|
+
"timingFile": "narration-adam-timing.json",
|
|
9
|
+
"duration": 507.543,
|
|
10
|
+
"wordCount": 875,
|
|
11
|
+
"audioSize": 8121409
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"voice": "Mark",
|
|
15
|
+
"name": "mark",
|
|
16
|
+
"audioFile": "narration-mark.mp3",
|
|
17
|
+
"timingFile": "narration-mark-timing.json",
|
|
18
|
+
"duration": 440.671,
|
|
19
|
+
"wordCount": 875,
|
|
20
|
+
"audioSize": 7051434
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"voice": "Hope",
|
|
24
|
+
"name": "hope",
|
|
25
|
+
"audioFile": "narration-hope.mp3",
|
|
26
|
+
"timingFile": "narration-hope-timing.json",
|
|
27
|
+
"duration": 407.181,
|
|
28
|
+
"wordCount": 875,
|
|
29
|
+
"audioSize": 6515610
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"voice": "Creature",
|
|
33
|
+
"name": "creature",
|
|
34
|
+
"audioFile": "narration-creature.mp3",
|
|
35
|
+
"timingFile": "narration-creature-timing.json",
|
|
36
|
+
"duration": 620.62,
|
|
37
|
+
"wordCount": 875,
|
|
38
|
+
"audioSize": 9930755
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"voice": "Gaming",
|
|
42
|
+
"name": "gaming",
|
|
43
|
+
"audioFile": "narration-gaming.mp3",
|
|
44
|
+
"timingFile": "narration-gaming-timing.json",
|
|
45
|
+
"duration": 845.811,
|
|
46
|
+
"wordCount": 875,
|
|
47
|
+
"audioSize": 13533563
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
@@ -13,15 +13,17 @@
|
|
|
13
13
|
|
|
14
14
|
:root {
|
|
15
15
|
--bg: #0a0a0a;
|
|
16
|
-
--bg-secondary: #
|
|
16
|
+
--bg-secondary: #121212;
|
|
17
17
|
--bg-tertiary: #1a1a1a;
|
|
18
|
-
--text: #
|
|
19
|
-
--text-muted: #
|
|
20
|
-
--text-dim: #
|
|
18
|
+
--text: #e8e8e8;
|
|
19
|
+
--text-muted: #999;
|
|
20
|
+
--text-dim: #555;
|
|
21
21
|
--accent: #fff;
|
|
22
22
|
--accent-red: #BA0C2F;
|
|
23
23
|
--accent-red-glow: rgba(186, 12, 47, 0.4);
|
|
24
24
|
--border: #333;
|
|
25
|
+
--border-strong: #444;
|
|
26
|
+
--bg-card: #1a1a1a;
|
|
25
27
|
--glow: rgba(255, 255, 255, 0.3);
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -57,7 +59,7 @@
|
|
|
57
59
|
justify-content: space-between;
|
|
58
60
|
align-items: center;
|
|
59
61
|
background: var(--bg);
|
|
60
|
-
border-bottom:
|
|
62
|
+
border-bottom: 2px solid var(--border);
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
.logo {
|
|
@@ -100,7 +102,7 @@
|
|
|
100
102
|
|
|
101
103
|
.theme-toggle {
|
|
102
104
|
background: transparent;
|
|
103
|
-
border:
|
|
105
|
+
border: 2px solid var(--border);
|
|
104
106
|
color: var(--text);
|
|
105
107
|
padding: 6px 12px;
|
|
106
108
|
cursor: pointer;
|
|
@@ -164,7 +166,7 @@
|
|
|
164
166
|
|
|
165
167
|
.audio-player {
|
|
166
168
|
background: var(--bg-secondary);
|
|
167
|
-
border:
|
|
169
|
+
border: 2px solid var(--border);
|
|
168
170
|
padding: 25px;
|
|
169
171
|
margin: 40px 0;
|
|
170
172
|
opacity: 0;
|
|
@@ -236,7 +238,7 @@
|
|
|
236
238
|
|
|
237
239
|
.comparison-table {
|
|
238
240
|
margin: 40px 0;
|
|
239
|
-
border:
|
|
241
|
+
border: 2px solid var(--border);
|
|
240
242
|
opacity: 0;
|
|
241
243
|
}
|
|
242
244
|
|
|
@@ -244,7 +246,7 @@
|
|
|
244
246
|
display: grid;
|
|
245
247
|
grid-template-columns: 1fr 1fr 1fr;
|
|
246
248
|
background: var(--bg-secondary);
|
|
247
|
-
border-bottom:
|
|
249
|
+
border-bottom: 2px solid var(--border);
|
|
248
250
|
}
|
|
249
251
|
|
|
250
252
|
.comparison-header div {
|
|
@@ -256,13 +258,13 @@
|
|
|
256
258
|
}
|
|
257
259
|
|
|
258
260
|
.comparison-header div:not(:last-child) {
|
|
259
|
-
border-right:
|
|
261
|
+
border-right: 2px solid var(--border);
|
|
260
262
|
}
|
|
261
263
|
|
|
262
264
|
.comparison-row {
|
|
263
265
|
display: grid;
|
|
264
266
|
grid-template-columns: 1fr 1fr 1fr;
|
|
265
|
-
border-bottom:
|
|
267
|
+
border-bottom: 2px solid var(--border);
|
|
266
268
|
}
|
|
267
269
|
|
|
268
270
|
.comparison-row:last-child { border-bottom: none; }
|
|
@@ -274,7 +276,7 @@
|
|
|
274
276
|
}
|
|
275
277
|
|
|
276
278
|
.comparison-row div:not(:last-child) {
|
|
277
|
-
border-right:
|
|
279
|
+
border-right: 2px solid var(--border);
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
.comparison-row div:first-child {
|
|
@@ -286,7 +288,7 @@
|
|
|
286
288
|
|
|
287
289
|
.featured-media {
|
|
288
290
|
margin: 40px 0;
|
|
289
|
-
border:
|
|
291
|
+
border: 2px solid var(--border);
|
|
290
292
|
opacity: 0;
|
|
291
293
|
}
|
|
292
294
|
|
|
@@ -313,7 +315,7 @@
|
|
|
313
315
|
padding: 15px;
|
|
314
316
|
font-size: 0.8rem;
|
|
315
317
|
color: var(--text-muted);
|
|
316
|
-
border-top:
|
|
318
|
+
border-top: 2px solid var(--border);
|
|
317
319
|
}
|
|
318
320
|
|
|
319
321
|
.article-content { opacity: 0; }
|
|
@@ -337,13 +339,13 @@
|
|
|
337
339
|
.article-content code {
|
|
338
340
|
background: var(--bg-secondary);
|
|
339
341
|
padding: 2px 8px;
|
|
340
|
-
border:
|
|
342
|
+
border: 2px solid var(--border);
|
|
341
343
|
font-size: 0.9em;
|
|
342
344
|
}
|
|
343
345
|
|
|
344
346
|
.article-content pre {
|
|
345
347
|
background: var(--bg-secondary);
|
|
346
|
-
border:
|
|
348
|
+
border: 2px solid var(--border);
|
|
347
349
|
padding: 20px;
|
|
348
350
|
margin: 25px 0;
|
|
349
351
|
overflow-x: auto;
|
|
@@ -361,7 +363,7 @@
|
|
|
361
363
|
|
|
362
364
|
.callout {
|
|
363
365
|
background: var(--bg-secondary);
|
|
364
|
-
border:
|
|
366
|
+
border: 2px solid var(--border);
|
|
365
367
|
border-left: 3px solid var(--text);
|
|
366
368
|
padding: 25px;
|
|
367
369
|
margin: 30px 0;
|
|
@@ -390,14 +392,14 @@
|
|
|
390
392
|
|
|
391
393
|
.ai-chat {
|
|
392
394
|
background: var(--bg-secondary);
|
|
393
|
-
border:
|
|
395
|
+
border: 2px solid var(--border);
|
|
394
396
|
margin: 50px 0;
|
|
395
397
|
opacity: 0;
|
|
396
398
|
}
|
|
397
399
|
|
|
398
400
|
.ai-chat-header {
|
|
399
401
|
padding: 20px;
|
|
400
|
-
border-bottom:
|
|
402
|
+
border-bottom: 2px solid var(--border);
|
|
401
403
|
display: flex;
|
|
402
404
|
align-items: center;
|
|
403
405
|
gap: 15px;
|
|
@@ -432,7 +434,7 @@
|
|
|
432
434
|
.chat-avatar {
|
|
433
435
|
width: 30px;
|
|
434
436
|
height: 30px;
|
|
435
|
-
border:
|
|
437
|
+
border: 2px solid var(--border);
|
|
436
438
|
display: flex;
|
|
437
439
|
align-items: center;
|
|
438
440
|
justify-content: center;
|
|
@@ -442,7 +444,7 @@
|
|
|
442
444
|
|
|
443
445
|
.chat-bubble {
|
|
444
446
|
background: var(--bg-tertiary);
|
|
445
|
-
border:
|
|
447
|
+
border: 2px solid var(--border);
|
|
446
448
|
padding: 12px 16px;
|
|
447
449
|
max-width: 80%;
|
|
448
450
|
font-size: 0.9rem;
|
|
@@ -465,7 +467,7 @@
|
|
|
465
467
|
|
|
466
468
|
.quick-btn {
|
|
467
469
|
background: transparent;
|
|
468
|
-
border:
|
|
470
|
+
border: 2px solid var(--border);
|
|
469
471
|
color: var(--text);
|
|
470
472
|
padding: 8px 16px;
|
|
471
473
|
font-family: inherit;
|
|
@@ -480,13 +482,13 @@
|
|
|
480
482
|
display: flex;
|
|
481
483
|
gap: 10px;
|
|
482
484
|
padding: 15px 20px;
|
|
483
|
-
border-top:
|
|
485
|
+
border-top: 2px solid var(--border);
|
|
484
486
|
}
|
|
485
487
|
|
|
486
488
|
.ai-chat-input input {
|
|
487
489
|
flex: 1;
|
|
488
490
|
background: transparent;
|
|
489
|
-
border:
|
|
491
|
+
border: 2px solid var(--border);
|
|
490
492
|
color: var(--text);
|
|
491
493
|
padding: 12px 15px;
|
|
492
494
|
font-family: inherit;
|
|
@@ -509,7 +511,7 @@
|
|
|
509
511
|
|
|
510
512
|
.feedback-section {
|
|
511
513
|
background: var(--bg-secondary);
|
|
512
|
-
border:
|
|
514
|
+
border: 2px solid var(--border);
|
|
513
515
|
padding: 30px;
|
|
514
516
|
margin: 50px 0;
|
|
515
517
|
text-align: center;
|
|
@@ -562,7 +564,7 @@
|
|
|
562
564
|
}
|
|
563
565
|
|
|
564
566
|
.related-card {
|
|
565
|
-
border:
|
|
567
|
+
border: 2px solid var(--border);
|
|
566
568
|
padding: 25px;
|
|
567
569
|
text-decoration: none;
|
|
568
570
|
color: var(--text);
|
|
@@ -588,7 +590,7 @@
|
|
|
588
590
|
}
|
|
589
591
|
|
|
590
592
|
footer {
|
|
591
|
-
border-top:
|
|
593
|
+
border-top: 2px solid var(--border);
|
|
592
594
|
padding: 40px;
|
|
593
595
|
text-align: center;
|
|
594
596
|
margin-top: 60px;
|
|
@@ -623,7 +625,7 @@
|
|
|
623
625
|
.article-title { font-size: 2rem; }
|
|
624
626
|
.comparison-header, .comparison-row { grid-template-columns: 1fr; }
|
|
625
627
|
.comparison-header div:not(:last-child),
|
|
626
|
-
.comparison-row div:not(:last-child) { border-right: none; border-bottom:
|
|
628
|
+
.comparison-row div:not(:last-child) { border-right: none; border-bottom: 2px solid var(--border); }
|
|
627
629
|
.related-grid { grid-template-columns: 1fr; }
|
|
628
630
|
nav { padding: 15px 20px; }
|
|
629
631
|
.nav-links { display: none; }
|
|
@@ -17,31 +17,35 @@
|
|
|
17
17
|
|
|
18
18
|
:root {
|
|
19
19
|
--bg: #0a0a0a;
|
|
20
|
-
--bg-secondary: #
|
|
20
|
+
--bg-secondary: #121212;
|
|
21
21
|
--bg-tertiary: #1a1a1a;
|
|
22
|
-
--
|
|
23
|
-
--text
|
|
24
|
-
--text-
|
|
22
|
+
--bg-card: #1a1a1a;
|
|
23
|
+
--text: #e8e8e8;
|
|
24
|
+
--text-muted: #999;
|
|
25
|
+
--text-dim: #555;
|
|
25
26
|
--accent: #fff;
|
|
26
27
|
--accent-red: #BA0C2F;
|
|
27
28
|
--accent-red-glow: rgba(186, 12, 47, 0.4);
|
|
28
29
|
--border: #333;
|
|
30
|
+
--border-strong: #444;
|
|
29
31
|
--glow: rgba(255, 255, 255, 0.3);
|
|
30
32
|
--success: #4ade80;
|
|
31
33
|
--warning: #fbbf24;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
[data-theme="light"] {
|
|
35
|
-
--bg: #
|
|
37
|
+
--bg: #f0f0f0;
|
|
36
38
|
--bg-secondary: #fff;
|
|
37
|
-
--bg-tertiary: #
|
|
39
|
+
--bg-tertiary: #f5f5f5;
|
|
40
|
+
--bg-card: #fafafa;
|
|
38
41
|
--text: #1a1a1a;
|
|
39
42
|
--text-muted: #666;
|
|
40
43
|
--text-dim: #aaa;
|
|
41
44
|
--accent: #000;
|
|
42
45
|
--accent-red: #BA0C2F;
|
|
43
46
|
--accent-red-glow: rgba(186, 12, 47, 0.3);
|
|
44
|
-
--border: #
|
|
47
|
+
--border: #ddd;
|
|
48
|
+
--border-strong: #ccc;
|
|
45
49
|
--glow: rgba(0, 0, 0, 0.15);
|
|
46
50
|
}
|
|
47
51
|
|
|
@@ -53,19 +57,19 @@
|
|
|
53
57
|
overflow-x: hidden;
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
/* Navigation */
|
|
60
|
+
/* Navigation - boxy style */
|
|
57
61
|
nav {
|
|
58
62
|
position: fixed;
|
|
59
63
|
top: 0;
|
|
60
64
|
left: 0;
|
|
61
65
|
right: 0;
|
|
62
66
|
z-index: 1000;
|
|
63
|
-
padding:
|
|
67
|
+
padding: 15px 40px;
|
|
64
68
|
display: flex;
|
|
65
69
|
justify-content: space-between;
|
|
66
70
|
align-items: center;
|
|
67
71
|
background: var(--bg);
|
|
68
|
-
border-bottom:
|
|
72
|
+
border-bottom: 2px solid var(--border);
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
.logo {
|
|
@@ -81,13 +85,16 @@
|
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
.logo-icon {
|
|
84
|
-
width:
|
|
85
|
-
height:
|
|
86
|
-
border: 2px solid var(--
|
|
88
|
+
width: 30px;
|
|
89
|
+
height: 30px;
|
|
90
|
+
border: 2px solid var(--accent-red);
|
|
91
|
+
background: var(--accent-red);
|
|
92
|
+
color: #fff;
|
|
87
93
|
display: flex;
|
|
88
94
|
align-items: center;
|
|
89
95
|
justify-content: center;
|
|
90
|
-
font-size: 0.
|
|
96
|
+
font-size: 0.75rem;
|
|
97
|
+
font-weight: bold;
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
.nav-links {
|
|
@@ -99,29 +106,36 @@
|
|
|
99
106
|
.nav-links a {
|
|
100
107
|
color: var(--text-muted);
|
|
101
108
|
text-decoration: none;
|
|
102
|
-
font-size: 0.
|
|
109
|
+
font-size: 0.75rem;
|
|
103
110
|
letter-spacing: 1px;
|
|
104
|
-
|
|
111
|
+
text-transform: uppercase;
|
|
112
|
+
padding: 8px 12px;
|
|
113
|
+
border: 2px solid transparent;
|
|
114
|
+
transition: all 0.2s;
|
|
105
115
|
}
|
|
106
116
|
|
|
107
117
|
.nav-links a:hover {
|
|
108
118
|
color: var(--accent-red);
|
|
119
|
+
border-color: var(--accent-red);
|
|
109
120
|
}
|
|
110
121
|
|
|
111
122
|
.theme-toggle {
|
|
112
|
-
background:
|
|
113
|
-
border:
|
|
123
|
+
background: var(--bg-card);
|
|
124
|
+
border: 2px solid var(--border);
|
|
114
125
|
color: var(--text);
|
|
115
|
-
padding:
|
|
126
|
+
padding: 8px 14px;
|
|
116
127
|
cursor: pointer;
|
|
117
128
|
font-family: inherit;
|
|
118
|
-
font-size: 0.
|
|
119
|
-
|
|
129
|
+
font-size: 0.7rem;
|
|
130
|
+
text-transform: uppercase;
|
|
131
|
+
letter-spacing: 1px;
|
|
132
|
+
transition: all 0.2s;
|
|
120
133
|
}
|
|
121
134
|
|
|
122
135
|
.theme-toggle:hover {
|
|
123
|
-
background: var(--
|
|
124
|
-
color:
|
|
136
|
+
background: var(--accent-red);
|
|
137
|
+
color: #fff;
|
|
138
|
+
border-color: var(--accent-red);
|
|
125
139
|
}
|
|
126
140
|
|
|
127
141
|
/* Main Content */
|