@hustle-together/api-dev-tools 3.1.0 → 3.3.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.
@@ -4,10 +4,47 @@
4
4
 
5
5
  **Purpose:** Orchestrates the complete API development workflow using interview-driven, research-first, test-first methodology with continuous verification loops.
6
6
 
7
+ ## ⚠️ CRITICAL: MANDATORY USER INTERACTION
8
+
9
+ **YOU MUST USE THE `AskUserQuestion` TOOL AT EVERY CHECKPOINT.**
10
+
11
+ This workflow requires REAL user input at each phase. You are **FORBIDDEN** from:
12
+ - Self-answering questions
13
+ - Assuming user responses
14
+ - Proceeding without explicit user confirmation
15
+ - Making decisions on behalf of the user
16
+
17
+ ### How to Ask Questions Correctly
18
+
19
+ At every `[Y/n]` or multiple-choice prompt in this workflow, you MUST call:
20
+
21
+ ```
22
+ AskUserQuestion({
23
+ questions: [{
24
+ question: "Your question here?",
25
+ header: "Phase",
26
+ options: ["Option A", "Option B", "Option C", "Type something else..."]
27
+ }]
28
+ })
29
+ ```
30
+
31
+ **WAIT for the user's response before proceeding.** The tool will pause execution until the user answers.
32
+
33
+ ### Violation Detection
34
+
35
+ The enforcement hooks will BLOCK your progress if:
36
+ - `user_question_asked` is false for any phase
37
+ - `user_confirmed`/`user_approved`/`user_completed` is false
38
+ - Questions were not asked via the AskUserQuestion tool
39
+
40
+ If you see "BLOCKED" messages, it means you skipped user interaction.
41
+
42
+ ---
43
+
7
44
  ## Key Principles
8
45
 
9
46
  1. **Loop Until Green** - Every verification phase loops back if not successful
10
- 2. **Continuous Interviews** - Checkpoints at EVERY phase transition
47
+ 2. **Continuous Interviews** - Checkpoints at EVERY phase transition (USE AskUserQuestion!)
11
48
  3. **Adaptive Research** - Propose searches based on context, not shotgun approach
12
49
  4. **Self-Documenting** - State file captures everything for re-grounding
13
50
  5. **Verify After Green** - Re-research docs to catch memory-based implementation errors
@@ -25,33 +62,49 @@
25
62
  │ • "[term] SDK" │
26
63
  │ • "[term] npm package" │
27
64
  │ │
28
- If multiple interpretations found, ask:
29
- ┌───────────────────────────────────────────────────────┐
30
- I found multiple things matching "[term]": │ │
31
- │ │ │ │
32
- [A] Option A - Description
33
- [B] Option B - Description
34
- │ │ [C] Both │ │
35
- [D] Something else: ____
36
- └───────────────────────────────────────────────────────┘
37
-
38
- ──── Loop back if ambiguous ────
65
+ ⚠️ REQUIRED: Use AskUserQuestion tool:
66
+
67
+ AskUserQuestion({
68
+ questions: [{
69
+ question: "I found multiple things matching
70
+ '[term]'. Which should we use?",
71
+ header: "Disambig",
72
+ options: [
73
+ "Option A - Description",
74
+ "Option B - Description",
75
+ "Both A and B",
76
+ │ "Something else (I'll describe)" │
77
+ │ ] │
78
+ │ }] │
79
+ │ }) │
80
+ │ │
81
+ │ WAIT for user response. Do NOT proceed without it. │
82
+ │ ──── Loop back if user selects "Something else" ──── │
39
83
  └───────────────────────────────────────────────────────────┘
40
84
  │ Clear
41
85
 
42
86
  ┌─ PHASE 1: SCOPE CONFIRMATION ─────────────────────────────┐
43
87
  │ │
44
- ┌───────────────────────────────────────────────────────┐
45
- SCOPE CONFIRMATION │ │
46
- │ │
47
- I understand you want: /api/v2/[endpoint] │ │
48
- Purpose: [inferred purpose] │ │
49
- │ External API: [service name] (URL)
50
- │ │
51
- Is this correct? [Y/n]
52
- Additional context? ____
53
- └───────────────────────────────────────────────────────┘
54
-
88
+ Present your understanding, then:
89
+
90
+ ⚠️ REQUIRED: Use AskUserQuestion tool:
91
+
92
+ AskUserQuestion({
93
+ questions: [{
94
+ question: "I understand you want /api/v2/[endpoint]
95
+ to [purpose]. Using [external API].
96
+ Is this correct?",
97
+ header: "Scope",
98
+ options: [
99
+ │ "Yes, proceed", │
100
+ │ "I have modifications to add", │
101
+ │ "No, let me clarify the purpose" │
102
+ │ ] │
103
+ │ }] │
104
+ │ }) │
105
+ │ │
106
+ │ WAIT for user response. Do NOT assume "yes". │
107
+ │ ──── Loop back if user has modifications ──── │
55
108
  └───────────────────────────────────────────────────────────┘
56
109
 
57
110
 
@@ -62,132 +115,178 @@
62
115
  │ • WebSearch: "[name] official documentation" │
63
116
  │ • WebSearch: "site:[domain] api reference" │
64
117
  │ │
65
- │ Present summary:
66
- ┌───────────────────────────────────────────────────────┐
67
- RESEARCH SUMMARY │
68
- │ │
69
- │ Source │ Found │ │
70
- │ │ ├────────────────┼────────────────────────────────────│ │
71
- Official docs │ [URL]
72
- API Reference │ ✓ REST v2
73
- │ │ │ Auth method │ ✓ Bearer token │ │
74
- │ │ │ NPM package │ ? Not found │ │
75
- │ │ │ │
76
- Proceed? [Y] / Search more? [n] ____
77
- └───────────────────────────────────────────────────────┘
78
-
118
+ │ Present summary table, then:
119
+
120
+ ⚠️ REQUIRED: Use AskUserQuestion tool:
121
+
122
+ AskUserQuestion({
123
+ questions: [{
124
+ question: "Research summary above. Found [N]
125
+ sources. Should I proceed or search
126
+ for more?",
127
+ header: "Research",
128
+ options: [
129
+ "Proceed to interview",
130
+ "Search more - I need [specific topic]",
131
+ "Search for something specific (I'll describe)"
132
+ │ ] │
133
+ │ }] │
134
+ │ }) │
135
+ │ │
136
+ │ WAIT for user response. Do NOT auto-proceed. │
79
137
  │ ──── Loop back if user wants more research ──── │
80
138
  └───────────────────────────────────────────────────────────┘
81
139
 
82
140
 
83
141
  ┌─ PHASE 3: INTERVIEW (Generated FROM Research) ────────────┐
84
142
  │ │
85
- Generate questions based on discovered parameters:
86
-
87
- ┌───────────────────────────────────────────────────────┐
88
- Based on research, [API] has N parameters:
89
- │ │
90
- 1. DOMAIN (required) - string
91
- │ → No question needed (always required)
92
- │ │ │ │
93
- 2. FORMAT: ["json", "svg", "png", "raw"]
94
- │ Q: Which formats do you need?
95
- │ │ [x] json [x] svg [x] png [ ] raw │ │
96
- │ │
97
- 3. QUALITY: 1-100 (continuous range) │ │
98
- Q: How should we TEST this? │ │
99
- │ [ ] All values (100 tests) │
100
- [x] Boundary (1, 50, 100) │ │
101
- │ [ ] Sample (1, 25, 50, 75, 100)
102
- [ ] Custom: ____ │ │
103
- │ │ │ │
104
- ... (continues for ALL discovered parameters)
105
- └───────────────────────────────────────────────────────┘
106
-
107
- Decisions are saved to state file for consistency.
143
+ For EACH parameter discovered in research, ask ONE
144
+ question at a time using AskUserQuestion:
145
+
146
+ ⚠️ REQUIRED: Use AskUserQuestion for EACH question:
147
+
148
+ // Question 1: Format preference
149
+ AskUserQuestion({
150
+ questions: [{
151
+ question: "Which response formats do you need?",
152
+ header: "Format",
153
+ multiSelect: true,
154
+ options: ["JSON", "SVG", "PNG", "All formats"]
155
+ }]
156
+ })
157
+ // WAIT for response, record in state, then next Q
158
+
159
+ // Question 2: Error handling
160
+ AskUserQuestion({
161
+ questions: [{
162
+ question: "How should errors be handled?",
163
+ header: "Errors",
164
+ options: [
165
+ "Throw exceptions",
166
+ │ "Return error objects", │
167
+ │ "Both (configurable)" │
168
+ │ ] │
169
+ │ }] │
170
+ │ }) │
171
+ │ // Continue for ALL parameters... │
172
+ │ │
173
+ │ After ALL questions answered: │
174
+ │ │
175
+ │ AskUserQuestion({ │
176
+ │ questions: [{ │
177
+ │ question: "Interview complete. Your decisions: │
178
+ │ [summary]. All correct?", │
179
+ │ header: "Confirm", │
180
+ │ options: [ │
181
+ │ "Yes, proceed to schema", │
182
+ │ "Change an answer", │
183
+ │ "Add another question" │
184
+ │ ] │
185
+ │ }] │
186
+ │ }) │
187
+ │ │
188
+ │ Decisions saved to state file for consistency. │
189
+ │ ──── Loop back if user wants to change answers ──── │
108
190
  └───────────────────────────────────────────────────────────┘
109
191
 
110
192
 
111
193
  ┌─ PHASE 4: DEEP RESEARCH (Adaptive) ───────────────────────┐
112
194
  │ │
113
- │ Based on interview answers, PROPOSE additional research:
114
- │ │
115
- │ ┌───────────────────────────────────────────────────────┐ │
116
- │ │ PROPOSED DEEP RESEARCH │ │
117
- │ │ │ │
118
- │ │ Based on your selections, I want to research: │ │
119
- │ │ │ │
120
- │ │ [x] Error response format (for error handling) │ │
121
- │ │ [x] Rate limiting behavior (short cache selected) │ │
122
- │ │ [ ] Webhook support (not selected) │ │
123
- │ │ [x] SVG optimization (SVG format selected) │ │
124
- │ │ │ │
125
- │ │ Approve these searches? [Y] │ │
126
- │ │ Add more: ____ │ │
127
- │ │ Skip and proceed: [n] │ │
128
- │ └───────────────────────────────────────────────────────┘ │
195
+ │ Based on interview answers, PROPOSE additional research.
129
196
  │ │
197
+ │ ⚠️ REQUIRED: Use AskUserQuestion tool: │
198
+ │ │
199
+ │ AskUserQuestion({ │
200
+ │ questions: [{ │
201
+ │ question: "Based on your interview answers, I │
202
+ │ want to research: [list]. Approve?", │
203
+ │ header: "Deep Research", │
204
+ │ options: [ │
205
+ │ "Yes, run these searches", │
206
+ │ "Add more - I also need [topic]", │
207
+ │ "Skip deep research, proceed to schema" │
208
+ │ ] │
209
+ │ }] │
210
+ │ }) │
211
+ │ │
212
+ │ WAIT for user response. Do NOT auto-approve. │
130
213
  │ KEY: Research is PROPOSED, not automatic shotgun. │
214
+ │ ──── Loop back if user wants to add topics ──── │
131
215
  └───────────────────────────────────────────────────────────┘
132
216
 
133
217
 
134
218
  ┌─ PHASE 5: SCHEMA DESIGN ──────────────────────────────────┐
135
219
  │ │
136
- │ Create Zod schema from research + interview:
137
- │ │
138
- ┌───────────────────────────────────────────────────────┐
139
- SCHEMA REVIEW │ │
140
- │ │
141
- │ const RequestSchema = z.object({
142
- │ domain: z.string().min(1),
143
- │ format: z.enum(["json", "svg", "png"]), │
144
- quality: z.number().min(1).max(100).default(80) │ │
145
- │ │ }); │ │
146
- │ │ │ │
147
- Schema matches interview answers? [Y/n]
148
- Missing fields? ____ │
149
- └───────────────────────────────────────────────────────┘
150
-
151
- ──── Loop back if schema wrong ────
220
+ │ Create Zod schema from research + interview, then:
221
+ │ │
222
+ ⚠️ REQUIRED: Use AskUserQuestion tool:
223
+
224
+ AskUserQuestion({
225
+ questions: [{
226
+ question: "Schema created based on your interview.
227
+ [show schema]. Does this match your
228
+ requirements?",
229
+ header: "Schema",
230
+ options: [
231
+ "Yes, schema looks correct",
232
+ "No, I need changes (I'll describe)",
233
+ "Let's redo the interview"
234
+ ]
235
+ }]
236
+ │ }) │
237
+ │ │
238
+ │ WAIT for user response. Do NOT assume approval. │
239
+ │ ──── Loop back if schema needs changes ──── │
152
240
  └───────────────────────────────────────────────────────────┘
153
241
 
154
242
 
155
243
  ┌─ PHASE 6: ENVIRONMENT CHECK ──────────────────────────────┐
156
244
  │ │
157
- ┌───────────────────────────────────────────────────────┐
158
- ENVIRONMENT CHECK │ │
159
- │ │
160
- │ │ │ Variable │ Status │ Source │ │
161
- │ │ ├──────────────────┼──────────┼──────────────────────│ │
162
- │ │ │ API_KEY │ ✓ Found │ .env.local │ │
163
- │ │ │ │
164
- │ │ Ready for testing? [Y/n] │ │
165
- │ └───────────────────────────────────────────────────────┘ │
245
+ Check required API keys, show status table, then:
246
+
247
+ ⚠️ REQUIRED: Use AskUserQuestion tool:
166
248
  │ │
249
+ │ AskUserQuestion({ │
250
+ │ questions: [{ │
251
+ │ question: "Environment check: [N] keys found, │
252
+ │ [M] missing. Ready to start TDD?", │
253
+ │ header: "Environment", │
254
+ │ options: [ │
255
+ │ "Yes, ready to write tests", │
256
+ │ "No, need to set up API keys first", │
257
+ │ "No, need to fix something else" │
258
+ │ ] │
259
+ │ }] │
260
+ │ }) │
261
+ │ │
262
+ │ WAIT for user response. Do NOT auto-proceed. │
167
263
  │ ──── Loop back if keys missing ──── │
168
264
  └───────────────────────────────────────────────────────────┘
169
265
 
170
266
 
171
267
  ┌─ PHASE 7: TDD RED (Write Failing Tests) ──────────────────┐
172
268
  │ │
173
- │ Generate test matrix from schema + interview decisions:
174
- │ │
175
- ┌───────────────────────────────────────────────────────┐
176
- TEST MATRIX REVIEW │ │
177
- │ │
178
- │ │ │ Parameter │ Valid Values │ Invalid Values │ │
179
- ├────────────┼────────────────────┼───────────────────│
180
- domain │ "x.com", "a.co" "", null │ │
181
- format │ "json", "svg" "gif", "webp" │ │
182
- │ │ quality │ 1, 50, 100 0, 101, -1 │ │
183
- │ │ │ │
184
- Total tests: 23 (pairwise reduction from 156)
185
- │ │
186
- Approve test matrix? [Y/n]
187
- Add test cases? ____ │ │
188
- └───────────────────────────────────────────────────────┘
189
-
269
+ │ Generate test matrix from schema + interview, then:
270
+ │ │
271
+ ⚠️ REQUIRED: Use AskUserQuestion tool:
272
+
273
+ AskUserQuestion({
274
+ questions: [{
275
+ question: "Test matrix: [N] test scenarios based
276
+ on your interview. Covers: [list].
277
+ Approve this test plan?",
278
+ header: "Tests",
279
+ options: [
280
+ "Yes, write these tests",
281
+ "Add more scenarios (I'll describe)",
282
+ "Change a scenario (I'll describe)"
283
+ ]
284
+ }]
285
+ })
286
+ │ │
287
+ │ WAIT for user response. Do NOT auto-approve. │
190
288
  │ HOOK: PreToolUse blocks Write if no research/interview │
289
+ │ ──── Loop back if user wants changes ──── │
191
290
  └───────────────────────────────────────────────────────────┘
192
291
 
193
292
 
@@ -206,27 +305,27 @@
206
305
  ┌─ PHASE 9: VERIFY (Re-Research After Green) ───────────────┐
207
306
  │ │
208
307
  │ MANDATORY: Re-read original documentation. │
209
- │ Compare implementation to docs feature-by-feature:
210
- │ │
211
- ┌───────────────────────────────────────────────────────┐
212
- IMPLEMENTATION VERIFICATION │ │
213
- │ │
214
- │ │ │ Feature │ In Docs │ Implemented │ Status │ │
215
- ├───────────────┼─────────┼─────────────┼─────────────│
216
- domain param ✓ │ ✓ │ ✅ Match │ │
217
- format opts 4 │ 3 │ ⚠️ Missing │ │
218
- │ │ │ size max │ 4096 │ 2048 │ ⚠️ Wrong │ │
219
- │ │ webhook ✗ │ ℹ️ Optional │ │
220
- │ │
221
- DISCREPANCIES: 2 found │
222
- │ │
223
- │ Fix these gaps? [Y] → Returns to Phase 7 (Red)
224
- │ Skip (intentional)? [n] → Document as omissions
225
- └───────────────────────────────────────────────────────┘
226
- │ │
308
+ │ Compare implementation to docs, then:
309
+ │ │
310
+ ⚠️ REQUIRED: Use AskUserQuestion tool:
311
+
312
+ AskUserQuestion({
313
+ questions: [{
314
+ question: "Verification found [N] gap(s) between
315
+ docs and implementation: [list].
316
+ How should I proceed?",
317
+ header: "Verify",
318
+ options: [
319
+ "Fix gaps - loop back to Red phase",
320
+ "Skip - these are intentional omissions",
321
+ "Fix some, skip others (I'll specify)"
322
+ ]
323
+ }]
324
+ })
325
+ │ │
326
+ │ WAIT for user response. Do NOT auto-decide. │
227
327
  │ HOOK: PostToolUse triggers after test pass │
228
-
229
- │ ──── Loop back to Phase 7 if gaps need fixing ──── │
328
+ ──── Loop back to Phase 7 if user wants fixes ────
230
329
  └───────────────────────────────────────────────────────────┘
231
330
 
232
331
 
@@ -244,19 +343,26 @@
244
343
 
245
344
  ┌─ PHASE 11: DOCUMENTATION ─────────────────────────────────┐
246
345
  │ │
247
- ┌───────────────────────────────────────────────────────┐
248
- DOCUMENTATION REVIEW │ │
249
- │ │
250
- Files to update: │ │
251
- │ │
252
- [x] api-tests-manifest.json - Manifest entry
253
- [x] OpenAPI spec - Endpoint documented
254
- [x] .claude/research/[api]/CURRENT.md - Cached
255
- │ │ │ │
256
- │ Documentation complete? [Y/n]
257
- └───────────────────────────────────────────────────────┘
346
+ Update documentation files, then:
347
+
348
+ ⚠️ REQUIRED: Use AskUserQuestion tool:
349
+
350
+ AskUserQuestion({
351
+ questions: [{
352
+ question: "Documentation checklist: [list files].
353
+ All documentation complete?",
354
+ header: "Docs",
355
+ options: [
356
+ "Yes, all documentation is done",
357
+ │ "No, I need to add something (I'll describe)", │
358
+ │ "Skip docs for now (not recommended)" │
359
+ │ ] │
360
+ │ }] │
361
+ │ }) │
258
362
  │ │
363
+ │ WAIT for user response. Do NOT auto-complete. │
259
364
  │ HOOK: Stop hook blocks if docs incomplete │
365
+ │ ──── Loop back if user needs to add docs ──── │
260
366
  └───────────────────────────────────────────────────────────┘
261
367
 
262
368
 
@@ -259,9 +259,72 @@ Reset the interview and ask with options based on research."""
259
259
  }))
260
260
  sys.exit(0)
261
261
 
262
- # All checks passed - inject interview decisions as context reminder
262
+ # Check 6: FINAL USER CONFIRMATION - must confirm interview is complete
263
+ user_question_asked_final = interview.get("user_question_asked", False)
264
+ user_completed = interview.get("user_completed", False)
263
265
  decisions = interview.get("decisions", {})
264
266
 
267
+ if not user_completed or not user_question_asked_final:
268
+ decision_summary = _build_decision_summary(decisions)
269
+ missing = []
270
+ if not user_question_asked_final:
271
+ missing.append("Final confirmation question (AskUserQuestion not used)")
272
+ if not user_completed:
273
+ missing.append("User hasn't confirmed interview complete")
274
+
275
+ print(json.dumps({
276
+ "permissionDecision": "deny",
277
+ "reason": f"""❌ BLOCKED: Interview needs FINAL USER CONFIRMATION.
278
+
279
+ Questions asked: {len(questions)}
280
+ Structured questions: {actual_structured}
281
+ User final confirmation: {user_completed}
282
+
283
+ MISSING:
284
+ {chr(10).join(f" • {m}" for m in missing)}
285
+
286
+ ═══════════════════════════════════════════════════════════
287
+ ⚠️ GET USER CONFIRMATION BEFORE PROCEEDING
288
+ ═══════════════════════════════════════════════════════════
289
+
290
+ REQUIRED STEPS:
291
+
292
+ 1. SHOW interview summary to user:
293
+ ┌───────────────────────────────────────────────────────┐
294
+ │ INTERVIEW COMPLETE │
295
+ │ │
296
+ │ Your decisions: │
297
+ {chr(10).join(f" │ • {line:<49} │" for line in decision_summary.split(chr(10))[:8]) if decision_summary else " │ (no decisions recorded yet) │"}
298
+ │ │
299
+ │ These will guide the schema, tests, and implementation│
300
+ │ │
301
+ │ All correct? [Y] │
302
+ │ Change an answer? [n] ____ │
303
+ └───────────────────────────────────────────────────────┘
304
+
305
+ 2. USE AskUserQuestion:
306
+ question: "Interview decisions correct? Ready to proceed?"
307
+ options: [
308
+ {{"value": "confirm", "label": "Yes, proceed to schema creation"}},
309
+ {{"value": "change", "label": "No, I want to change [which question]"}},
310
+ {{"value": "add", "label": "Add another question about [topic]"}}
311
+ ]
312
+
313
+ 3. If user says "change" or "add":
314
+ • Ask which question/topic
315
+ • Re-ask with AskUserQuestion
316
+ • Update decisions
317
+ • LOOP BACK and show updated summary
318
+
319
+ 4. If user says "confirm":
320
+ • Set interview.user_question_asked = true
321
+ • Set interview.user_completed = true
322
+ • Set interview.status = "complete"
323
+
324
+ WHY: User must approve their decisions before they drive implementation."""
325
+ }))
326
+ sys.exit(0)
327
+
265
328
  if decisions:
266
329
  # Build a reminder of what the user decided
267
330
  decision_summary = _build_decision_summary(decisions)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hustle-together/api-dev-tools",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "Interview-driven, research-first API development workflow with continuous verification loops for Claude Code",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {