jettypod 4.4.116 → 4.4.120
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/.env +7 -0
- package/apps/dashboard/app/api/claude/[workItemId]/message/route.ts +124 -48
- package/apps/dashboard/app/api/claude/[workItemId]/route.ts +171 -58
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +161 -10
- package/apps/dashboard/app/api/tests/run/stream/route.ts +13 -1
- package/apps/dashboard/app/api/usage/route.ts +17 -0
- package/apps/dashboard/app/api/work/[id]/route.ts +35 -0
- package/apps/dashboard/app/api/work/[id]/status/route.ts +43 -1
- package/apps/dashboard/app/connect-claude/page.tsx +24 -0
- package/apps/dashboard/app/decision/[id]/page.tsx +14 -14
- package/apps/dashboard/app/demo/gates/page.tsx +42 -42
- package/apps/dashboard/app/design-system/page.tsx +868 -0
- package/apps/dashboard/app/globals.css +6 -2
- package/apps/dashboard/app/install-claude/page.tsx +9 -7
- package/apps/dashboard/app/layout.tsx +17 -5
- package/apps/dashboard/app/login/page.tsx +250 -0
- package/apps/dashboard/app/page.tsx +11 -9
- package/apps/dashboard/app/settings/page.tsx +4 -2
- package/apps/dashboard/app/signup/page.tsx +245 -0
- package/apps/dashboard/app/subscribe/page.tsx +11 -0
- package/apps/dashboard/app/welcome/page.tsx +24 -1
- package/apps/dashboard/app/work/[id]/page.tsx +34 -50
- package/apps/dashboard/components/AppShell.tsx +95 -55
- package/apps/dashboard/components/CardMenu.tsx +56 -13
- package/apps/dashboard/components/ClaudePanel.tsx +301 -582
- package/apps/dashboard/components/ClaudePanelInput.tsx +23 -14
- package/apps/dashboard/components/ConnectClaudeScreen.tsx +210 -0
- package/apps/dashboard/components/CopyableId.tsx +3 -3
- package/apps/dashboard/components/DetailReviewActions.tsx +109 -0
- package/apps/dashboard/components/DragContext.tsx +75 -65
- package/apps/dashboard/components/DraggableCard.tsx +6 -46
- package/apps/dashboard/components/DropZone.tsx +2 -2
- package/apps/dashboard/components/EditableDetailDescription.tsx +1 -1
- package/apps/dashboard/components/EditableTitle.tsx +26 -6
- package/apps/dashboard/components/ElapsedTimer.tsx +54 -0
- package/apps/dashboard/components/EpicGroup.tsx +329 -0
- package/apps/dashboard/components/GateCard.tsx +100 -16
- package/apps/dashboard/components/GateChoiceCard.tsx +15 -17
- package/apps/dashboard/components/InstallClaudeScreen.tsx +140 -51
- package/apps/dashboard/components/JettyLoader.tsx +38 -0
- package/apps/dashboard/components/KanbanBoard.tsx +147 -766
- package/apps/dashboard/components/KanbanCard.tsx +506 -0
- package/apps/dashboard/components/LazyMarkdown.tsx +12 -0
- package/apps/dashboard/components/MainNav.tsx +20 -54
- package/apps/dashboard/components/MessageBlock.tsx +391 -0
- package/apps/dashboard/components/ModeStartCard.tsx +15 -15
- package/apps/dashboard/components/OnboardingWelcome.tsx +214 -0
- package/apps/dashboard/components/PlaceholderCard.tsx +11 -21
- package/apps/dashboard/components/ProjectSwitcher.tsx +36 -8
- package/apps/dashboard/components/PrototypeTimeline.tsx +25 -25
- package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +265 -301
- package/apps/dashboard/components/RealTimeTestsWrapper.tsx +97 -74
- package/apps/dashboard/components/ReviewFooter.tsx +141 -0
- package/apps/dashboard/components/SessionList.tsx +19 -18
- package/apps/dashboard/components/SubscribeContent.tsx +206 -0
- package/apps/dashboard/components/TestTree.tsx +15 -14
- package/apps/dashboard/components/TipCard.tsx +177 -0
- package/apps/dashboard/components/Toast.tsx +5 -5
- package/apps/dashboard/components/TypeIcon.tsx +56 -0
- package/apps/dashboard/components/UpgradeBanner.tsx +30 -0
- package/apps/dashboard/components/WaveCompletionAnimation.tsx +61 -62
- package/apps/dashboard/components/WelcomeScreen.tsx +25 -27
- package/apps/dashboard/components/WorkItemHeader.tsx +4 -4
- package/apps/dashboard/components/WorkItemTree.tsx +9 -28
- package/apps/dashboard/components/settings/AccountSection.tsx +169 -0
- package/apps/dashboard/components/settings/EnvVarsSection.tsx +54 -79
- package/apps/dashboard/components/settings/GeneralSection.tsx +26 -31
- package/apps/dashboard/components/settings/SettingsLayout.tsx +4 -4
- package/apps/dashboard/components/ui/Button.tsx +104 -0
- package/apps/dashboard/components/ui/Input.tsx +78 -0
- package/apps/dashboard/contexts/ClaudeSessionContext.tsx +408 -105
- package/apps/dashboard/contexts/ConnectionStatusContext.tsx +25 -4
- package/apps/dashboard/contexts/UsageContext.tsx +155 -0
- package/apps/dashboard/contexts/usageHelpers.js +9 -0
- package/apps/dashboard/electron/ipc-handlers.js +281 -88
- package/apps/dashboard/electron/main.js +691 -131
- package/apps/dashboard/electron/preload.js +25 -4
- package/apps/dashboard/electron/session-manager.js +163 -0
- package/apps/dashboard/electron-builder.config.js +3 -5
- package/apps/dashboard/hooks/useKanbanAnimation.ts +29 -0
- package/apps/dashboard/hooks/useKanbanUndo.ts +83 -0
- package/apps/dashboard/lib/backlog-parser.ts +50 -0
- package/apps/dashboard/lib/claude-process-manager.ts +50 -11
- package/apps/dashboard/lib/constants.ts +43 -0
- package/apps/dashboard/lib/db-bridge.ts +33 -0
- package/apps/dashboard/lib/db.ts +136 -20
- package/apps/dashboard/lib/kanban-utils.ts +70 -0
- package/apps/dashboard/lib/run-migrations.js +27 -2
- package/apps/dashboard/lib/session-state-machine.ts +3 -0
- package/apps/dashboard/lib/session-stream-manager.ts +144 -38
- package/apps/dashboard/lib/shadows.ts +7 -0
- package/apps/dashboard/lib/tests.ts +3 -1
- package/apps/dashboard/lib/utils.ts +6 -0
- package/apps/dashboard/next.config.js +35 -14
- package/apps/dashboard/package.json +6 -3
- package/apps/dashboard/public/bug-icon.svg +9 -0
- package/apps/dashboard/public/buoy-icon.svg +9 -0
- package/apps/dashboard/public/fonts/Satoshi-Variable.woff2 +0 -0
- package/apps/dashboard/public/fonts/Satoshi-VariableItalic.woff2 +0 -0
- package/apps/dashboard/public/in-flight-seagull.svg +9 -0
- package/apps/dashboard/public/jetty-icon-loading-alt.svg +11 -0
- package/apps/dashboard/public/jetty-icon-loading.svg +11 -0
- package/apps/dashboard/public/jettypod_logo.png +0 -0
- package/apps/dashboard/public/pier-icon.svg +14 -0
- package/apps/dashboard/public/star-icon.svg +9 -0
- package/apps/dashboard/public/wrench-icon.svg +9 -0
- package/apps/dashboard/scripts/upload-to-r2.js +89 -0
- package/apps/dashboard/scripts/ws-server.js +191 -0
- package/apps/dashboard/tsconfig.tsbuildinfo +1 -0
- package/apps/update-server/package.json +16 -0
- package/apps/update-server/schema.sql +31 -0
- package/apps/update-server/src/index.ts +1085 -0
- package/apps/update-server/tsconfig.json +16 -0
- package/apps/update-server/wrangler.toml +35 -0
- package/cucumber.js +9 -3
- package/docs/COMMAND_REFERENCE.md +34 -0
- package/hooks/post-checkout +32 -75
- package/hooks/post-merge +111 -10
- package/jest.setup.js +1 -0
- package/jettypod.js +54 -116
- package/lib/chore-taxonomy.js +33 -10
- package/lib/database.js +36 -16
- package/lib/db-watcher.js +1 -1
- package/lib/git-hooks/pre-commit +1 -1
- package/lib/jettypod-backup.js +27 -4
- package/lib/migrations/027-plan-at-creation-column.js +33 -0
- package/lib/migrations/028-ready-for-review-column.js +27 -0
- package/lib/migrations/029-remove-autoincrement.js +307 -0
- package/lib/migrations/029-rename-corrupted-to-cleaned.js +149 -0
- package/lib/migrations/index.js +47 -4
- package/lib/schema.js +13 -6
- package/lib/seed-onboarding.js +101 -69
- package/lib/update-command/index.js +9 -175
- package/lib/work-commands/index.js +129 -16
- package/lib/work-tracking/index.js +86 -46
- package/lib/worktree-diagnostics.js +16 -16
- package/lib/worktree-facade.js +1 -1
- package/lib/worktree-manager.js +8 -8
- package/lib/worktree-reconciler.js +5 -5
- package/package.json +9 -2
- package/scripts/ndjson-to-cucumber-json.js +152 -0
- package/scripts/postinstall.js +25 -0
- package/skills-templates/bug-mode/SKILL.md +39 -28
- package/skills-templates/bug-planning/SKILL.md +25 -29
- package/skills-templates/chore-mode/SKILL.md +131 -68
- package/skills-templates/chore-mode/verification.js +51 -10
- package/skills-templates/chore-planning/SKILL.md +47 -18
- package/skills-templates/epic-planning/SKILL.md +68 -48
- package/skills-templates/external-transition/SKILL.md +47 -47
- package/skills-templates/feature-planning/SKILL.md +83 -73
- package/skills-templates/production-mode/SKILL.md +49 -49
- package/skills-templates/request-routing/SKILL.md +27 -14
- package/skills-templates/simple-improvement/SKILL.md +68 -44
- package/skills-templates/speed-mode/SKILL.md +209 -128
- package/skills-templates/stable-mode/SKILL.md +105 -94
- package/templates/bdd-guidance.md +139 -0
- package/templates/bdd-scaffolding/wait.js +18 -0
- package/templates/bdd-scaffolding/world.js +19 -0
- package/.jettypod-backup/work.db +0 -0
- package/apps/dashboard/app/access-code/page.tsx +0 -110
- package/lib/discovery-checkpoint.js +0 -123
- package/skills-templates/project-discovery/SKILL.md +0 -372
|
@@ -18,7 +18,7 @@ description: Guide implementation of stable mode chores with comprehensive testi
|
|
|
18
18
|
└─────────────────────────────────────────────────────────────────────┘
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## CRITICAL HANDOFF REQUIREMENT
|
|
22
22
|
|
|
23
23
|
**After completing ALL stable mode chores:**
|
|
24
24
|
|
|
@@ -30,7 +30,7 @@ description: Guide implementation of stable mode chores with comprehensive testi
|
|
|
30
30
|
1. Set feature mode to production
|
|
31
31
|
2. **IMMEDIATELY invoke production-mode using the Skill tool**
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
**STOP GATE:** For external projects, DO NOT end this skill without invoking production-mode. Stable mode makes it robust - production mode makes it ready for real users at scale.
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
@@ -40,7 +40,7 @@ Guides Claude Code through stable mode implementation with comprehensive testing
|
|
|
40
40
|
|
|
41
41
|
When this skill is activated, you are helping implement a stable mode chore to add comprehensive testing and error handling. Follow this structured approach:
|
|
42
42
|
|
|
43
|
-
##
|
|
43
|
+
## Critical Context
|
|
44
44
|
|
|
45
45
|
**You are working in an isolated git worktree:**
|
|
46
46
|
- `work start [chore-id]` created a dedicated worktree for this chore
|
|
@@ -52,7 +52,7 @@ When this skill is activated, you are helping implement a stable mode chore to a
|
|
|
52
52
|
|
|
53
53
|
---
|
|
54
54
|
|
|
55
|
-
##
|
|
55
|
+
## SHELL CWD RECOVERY
|
|
56
56
|
|
|
57
57
|
**If ALL bash commands start failing with "Error: Exit code 1" and no output:**
|
|
58
58
|
|
|
@@ -68,7 +68,7 @@ Your shell's working directory was likely inside a worktree that was deleted. Th
|
|
|
68
68
|
|
|
69
69
|
---
|
|
70
70
|
|
|
71
|
-
##
|
|
71
|
+
## PRE-FLIGHT VALIDATION (REQUIRED)
|
|
72
72
|
|
|
73
73
|
**Before proceeding with ANY implementation, you MUST validate the worktree exists.**
|
|
74
74
|
|
|
@@ -82,17 +82,17 @@ sqlite3 .jettypod/work.db "SELECT wi.id, wi.title, wi.status, wt.worktree_path,
|
|
|
82
82
|
|
|
83
83
|
| worktree_path | What it means | Action |
|
|
84
84
|
|---------------|---------------|--------|
|
|
85
|
-
| **Has a path** (e.g., `/path/to/.jettypod-work/...`) |
|
|
86
|
-
| **NULL or empty** |
|
|
87
|
-
| **No rows returned** |
|
|
85
|
+
| **Has a path** (e.g., `/path/to/.jettypod-work/...`) | Worktree exists, ready to proceed | Continue to Step 0 |
|
|
86
|
+
| **NULL or empty** | `work start` was not called | **STOP - run `jettypod work start [chore-id]` first** |
|
|
87
|
+
| **No rows returned** | No chore is in progress | **STOP - verify the chore exists and run `work start`** |
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
**STOP GATE:** If `worktree_path` is NULL or no rows returned, you MUST run `jettypod work start [chore-id]` before continuing. DO NOT proceed without a valid worktree.
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
**FORBIDDEN: Manual Git Worktree Commands**
|
|
92
92
|
```
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
git worktree add ...
|
|
94
|
+
git checkout -b feature/...
|
|
95
|
+
git branch feature/...
|
|
96
96
|
```
|
|
97
97
|
**ALWAYS use `jettypod work start`** - it handles branch naming, path conventions, database tracking, and cleanup. Manual git commands will create orphaned worktrees that break the merge workflow.
|
|
98
98
|
|
|
@@ -109,7 +109,7 @@ sqlite3 .jettypod/work.db "SELECT wi.id, wi.title, wi.status, wt.worktree_path,
|
|
|
109
109
|
|
|
110
110
|
---
|
|
111
111
|
|
|
112
|
-
##
|
|
112
|
+
## WORKTREE PATH LOCK
|
|
113
113
|
|
|
114
114
|
**After pre-flight validation passes, capture and lock the worktree path:**
|
|
115
115
|
|
|
@@ -119,7 +119,7 @@ From the pre-flight query output, extract and store:
|
|
|
119
119
|
**Display:**
|
|
120
120
|
|
|
121
121
|
```
|
|
122
|
-
|
|
122
|
+
WORKTREE LOCK ACTIVE
|
|
123
123
|
Path: ${WORKTREE_PATH}
|
|
124
124
|
|
|
125
125
|
All file writes will use this path.
|
|
@@ -154,7 +154,7 @@ jettypod ui gate worktree-started --data='{"path":"${WORKTREE_PATH}"}'
|
|
|
154
154
|
**User Profile:** May not know how to code - Claude Code does the implementation autonomously.
|
|
155
155
|
|
|
156
156
|
<details>
|
|
157
|
-
<summary><strong
|
|
157
|
+
<summary><strong>What Stable Mode Includes (click to expand)</strong></summary>
|
|
158
158
|
|
|
159
159
|
**Stable Mode is NOT just error handling. It includes:**
|
|
160
160
|
|
|
@@ -194,7 +194,7 @@ jettypod ui gate worktree-started --data='{"path":"${WORKTREE_PATH}"}'
|
|
|
194
194
|
|
|
195
195
|
---
|
|
196
196
|
|
|
197
|
-
##
|
|
197
|
+
## Unit Testing in Stable Mode - True TDD
|
|
198
198
|
|
|
199
199
|
**Unit tests are written DURING implementation, not after.**
|
|
200
200
|
|
|
@@ -214,10 +214,10 @@ jettypod ui gate worktree-started --data='{"path":"${WORKTREE_PATH}"}'
|
|
|
214
214
|
- State consistency (transaction rollback, cleanup on failure)
|
|
215
215
|
|
|
216
216
|
<details>
|
|
217
|
-
<summary><strong
|
|
217
|
+
<summary><strong>Unit Test Examples (click to expand)</strong></summary>
|
|
218
218
|
|
|
219
219
|
```javascript
|
|
220
|
-
//
|
|
220
|
+
// Stable mode unit tests (error paths and edge cases)
|
|
221
221
|
test('createUser throws ValidationError for null email', () => {
|
|
222
222
|
expect(() => createUser('John', null)).toThrow(ValidationError);
|
|
223
223
|
expect(() => createUser('John', null)).toThrow('Email is required');
|
|
@@ -266,7 +266,7 @@ test('getUserById returns null for non-existent user', () => {
|
|
|
266
266
|
sqlite3 .jettypod/work.db "SELECT wi.id, wi.title, wi.parent_id, parent.title as parent_title, parent.scenario_file, wt.worktree_path, wt.branch_name FROM work_items wi LEFT JOIN work_items parent ON wi.parent_id = parent.id LEFT JOIN worktrees wt ON wi.id = wt.work_item_id WHERE wi.status = 'in_progress' AND wi.type = 'chore'"
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
-
|
|
269
|
+
**WORKFLOW INTEGRATION: Start workflow tracking**
|
|
270
270
|
|
|
271
271
|
After getting the work context, register this skill execution:
|
|
272
272
|
|
|
@@ -280,7 +280,7 @@ This validates that `speed_mode_complete` gate is passed and creates an executio
|
|
|
280
280
|
|
|
281
281
|
```
|
|
282
282
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
283
|
-
|
|
283
|
+
STABLE MODE: Implementing Chore #[id]
|
|
284
284
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
285
285
|
|
|
286
286
|
Chore: [title]
|
|
@@ -299,11 +299,11 @@ Analyzing stable mode BDD scenarios to determine what error handling and validat
|
|
|
299
299
|
|
|
300
300
|
**CRITICAL:** Claude Code executes this autonomously - no user permission needed.
|
|
301
301
|
|
|
302
|
-
|
|
302
|
+
**FORBIDDEN: Writing Files at This Step**
|
|
303
303
|
```
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
304
|
+
Write tool to any path
|
|
305
|
+
Edit tool to any path
|
|
306
|
+
Any file creation or modification
|
|
307
307
|
```
|
|
308
308
|
**This is an ANALYSIS step.** File writes happen in Step 5.
|
|
309
309
|
|
|
@@ -331,15 +331,15 @@ sqlite3 .jettypod/work.db "SELECT wi.id, wi.title, wi.description, wi.parent_id,
|
|
|
331
331
|
4. If no match found, list available scenarios and ask which one to implement
|
|
332
332
|
|
|
333
333
|
**Handle errors gracefully:**
|
|
334
|
-
- If no current work: "
|
|
335
|
-
- If no parent feature: "
|
|
336
|
-
- If no scenario_file: "
|
|
334
|
+
- If no current work: "No current work found. Run: jettypod work start <chore-id>"
|
|
335
|
+
- If no parent feature: "Current work has no parent feature."
|
|
336
|
+
- If no scenario_file: "Feature has no scenario_file."
|
|
337
337
|
- If can't match chore to scenario: List available scenarios and ask user
|
|
338
338
|
|
|
339
339
|
**Display to user:**
|
|
340
340
|
|
|
341
341
|
```
|
|
342
|
-
|
|
342
|
+
Stable Mode: [Feature Name]
|
|
343
343
|
|
|
344
344
|
Target Scenario:
|
|
345
345
|
[Scenario title]
|
|
@@ -364,11 +364,11 @@ Now reviewing speed mode implementation...
|
|
|
364
364
|
|
|
365
365
|
**CRITICAL:** Claude Code executes this autonomously - no user permission needed.
|
|
366
366
|
|
|
367
|
-
|
|
367
|
+
**FORBIDDEN: Writing Files at This Step**
|
|
368
368
|
```
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
369
|
+
Write tool to any path
|
|
370
|
+
Edit tool to any path
|
|
371
|
+
Any file creation or modification
|
|
372
372
|
```
|
|
373
373
|
**This is an ANALYSIS step.** File writes happen in Step 5.
|
|
374
374
|
|
|
@@ -399,14 +399,14 @@ Then use the Read tool to examine the implementation files.
|
|
|
399
399
|
**Display analysis:**
|
|
400
400
|
|
|
401
401
|
```
|
|
402
|
-
|
|
402
|
+
Code Analysis Complete
|
|
403
403
|
|
|
404
404
|
Current Implementation:
|
|
405
405
|
• Files: [list]
|
|
406
|
-
• Success scenarios:
|
|
407
|
-
• Error handling:
|
|
408
|
-
• Validation:
|
|
409
|
-
• Edge cases:
|
|
406
|
+
• Success scenarios: Working (from speed mode)
|
|
407
|
+
• Error handling: Missing [specific gaps]
|
|
408
|
+
• Validation: Missing [specific gaps]
|
|
409
|
+
• Edge cases: Not handled [specific gaps]
|
|
410
410
|
|
|
411
411
|
To pass the target scenario, I need to:
|
|
412
412
|
1. [Specific change]
|
|
@@ -416,7 +416,7 @@ To pass the target scenario, I need to:
|
|
|
416
416
|
Now proposing comprehensive implementation...
|
|
417
417
|
```
|
|
418
418
|
|
|
419
|
-
|
|
419
|
+
**WORKFLOW CHECKPOINT: Code analysis complete**
|
|
420
420
|
|
|
421
421
|
```bash
|
|
422
422
|
jettypod workflow checkpoint <feature-id> --step=2
|
|
@@ -424,11 +424,11 @@ jettypod workflow checkpoint <feature-id> --step=2
|
|
|
424
424
|
|
|
425
425
|
### Step 3: Decide if Confirmation Needed
|
|
426
426
|
|
|
427
|
-
|
|
427
|
+
**FORBIDDEN: Writing Files at This Step**
|
|
428
428
|
```
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
429
|
+
Write tool to any path
|
|
430
|
+
Edit tool to any path
|
|
431
|
+
Any file creation or modification
|
|
432
432
|
```
|
|
433
433
|
**This is a DECISION step.** File writes happen in Step 5.
|
|
434
434
|
|
|
@@ -448,20 +448,20 @@ jettypod workflow checkpoint <feature-id> --step=2
|
|
|
448
448
|
|
|
449
449
|
### Step 3A: Propose Implementation Approach (Conditional)
|
|
450
450
|
|
|
451
|
-
|
|
451
|
+
**ASYNC BOUNDARY - Only execute this if confirmation needed**
|
|
452
452
|
|
|
453
|
-
|
|
453
|
+
**FORBIDDEN: Writing Files at This Step**
|
|
454
454
|
```
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
455
|
+
Write tool to any path
|
|
456
|
+
Edit tool to any path
|
|
457
|
+
Any file creation or modification
|
|
458
458
|
```
|
|
459
459
|
**This is a PROPOSAL step.** File writes happen in Step 5.
|
|
460
460
|
|
|
461
461
|
**Present your analysis and proposal to the user:**
|
|
462
462
|
|
|
463
463
|
```
|
|
464
|
-
|
|
464
|
+
Implementation Proposal
|
|
465
465
|
|
|
466
466
|
I see multiple ways to approach this error handling. Here's what I'm thinking:
|
|
467
467
|
|
|
@@ -476,7 +476,7 @@ I see multiple ways to approach this error handling. Here's what I'm thinking:
|
|
|
476
476
|
Sound good, or would you prefer a different approach?
|
|
477
477
|
```
|
|
478
478
|
|
|
479
|
-
|
|
479
|
+
**WAIT for user confirmation or adjustments.**
|
|
480
480
|
|
|
481
481
|
If user adjusts: revise proposal and confirm again before proceeding.
|
|
482
482
|
|
|
@@ -484,6 +484,16 @@ If user adjusts: revise proposal and confirm again before proceeding.
|
|
|
484
484
|
|
|
485
485
|
---
|
|
486
486
|
|
|
487
|
+
### BDD Step Definition Constraints (ENFORCED)
|
|
488
|
+
|
|
489
|
+
Before writing any step definitions, read `templates/bdd-guidance.md`. BANNED in step defs: `setTimeout`/`sleep`, module-level `let`/`var`, raw SQL, assertions in Given/When, loops/branching, self-fulfilling mocks (setting state then asserting it). Steps must be 1-5 lines calling one helper via Cucumber World (`this`). Read `features/support/helpers/` and reuse before creating.
|
|
490
|
+
|
|
491
|
+
**Scaffolding:** If `features/support/helpers/` does not exist in the project, scaffold it before writing step definitions. Copy `templates/bdd-scaffolding/wait.js` to `features/support/helpers/wait.js` and `templates/bdd-scaffolding/world.js` to `features/support/world.js`.
|
|
492
|
+
|
|
493
|
+
**Helper Reuse:** Before writing step definitions, glob `features/support/helpers/**/*.js` and read each file. Import and call existing helpers in your steps — never duplicate functionality that already exists.
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
487
497
|
### Step 4: Establish RED Baseline
|
|
488
498
|
|
|
489
499
|
**CRITICAL:** After user confirms (or skips confirmation), execute autonomously - no permission needed for code changes.
|
|
@@ -528,25 +538,25 @@ Parse the output to identify:
|
|
|
528
538
|
|
|
529
539
|
**Display RED baseline:**
|
|
530
540
|
```
|
|
531
|
-
|
|
541
|
+
Establishing RED baseline...
|
|
532
542
|
|
|
533
543
|
RED Baseline: 3 of 11 steps failing (stable mode scenarios)
|
|
534
544
|
|
|
535
545
|
Failing steps:
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
546
|
+
Then it should throw a validation error
|
|
547
|
+
And the error message should be "Email is required"
|
|
548
|
+
When I provide an empty string as input
|
|
539
549
|
|
|
540
550
|
First error:
|
|
541
551
|
Step: Then it should throw a validation error
|
|
542
552
|
Error: Error: Expected function to throw but it didn't
|
|
543
553
|
|
|
544
|
-
|
|
554
|
+
Goal: Make all stable mode scenarios pass
|
|
545
555
|
|
|
546
556
|
Now implementing...
|
|
547
557
|
```
|
|
548
558
|
|
|
549
|
-
|
|
559
|
+
**WORKFLOW CHECKPOINT: RED baseline established**
|
|
550
560
|
|
|
551
561
|
```bash
|
|
552
562
|
jettypod workflow checkpoint <feature-id> --step=4
|
|
@@ -556,9 +566,9 @@ jettypod workflow checkpoint <feature-id> --step=4
|
|
|
556
566
|
|
|
557
567
|
### Step 5: RED→GREEN→REFACTOR Loop
|
|
558
568
|
|
|
559
|
-
|
|
569
|
+
**WORKTREE PATH REQUIRED:** All file writes MUST use the `WORKTREE_PATH` captured after pre-flight validation.
|
|
560
570
|
|
|
561
|
-
|
|
571
|
+
**NOW you may write files** - worktree is locked, approach is confirmed.
|
|
562
572
|
|
|
563
573
|
**Emit gate signal:**
|
|
564
574
|
|
|
@@ -581,23 +591,23 @@ jettypod ui gate implementing --data='{"description":"[stable mode error handlin
|
|
|
581
591
|
**Show progress each iteration:**
|
|
582
592
|
```
|
|
583
593
|
━━━ Iteration 3/10 ━━━
|
|
584
|
-
|
|
594
|
+
Unit test: test/user.test.js - validates email format
|
|
585
595
|
RED: Test fails - no validation exists yet
|
|
586
|
-
|
|
596
|
+
Implementation: src/user.js - added email format validation
|
|
587
597
|
GREEN: Unit test passes
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
598
|
+
Running BDD scenarios...
|
|
599
|
+
Progress: 9/11 BDD steps passing
|
|
600
|
+
Newly passing: Then it should throw a validation error
|
|
601
|
+
Next failure: And the error message should be user-friendly
|
|
592
602
|
BDD step: Then the error message should be "Email format is invalid"
|
|
593
603
|
```
|
|
594
604
|
|
|
595
605
|
**When GREEN achieved:**
|
|
596
606
|
```
|
|
597
|
-
|
|
607
|
+
GREEN: All stable mode scenarios passing!
|
|
598
608
|
```
|
|
599
609
|
|
|
600
|
-
|
|
610
|
+
**WORKFLOW CHECKPOINT: GREEN achieved**
|
|
601
611
|
|
|
602
612
|
```bash
|
|
603
613
|
jettypod workflow checkpoint <feature-id> --step=5
|
|
@@ -612,7 +622,7 @@ jettypod workflow checkpoint <feature-id> --step=5
|
|
|
612
622
|
**Re-run tests after refactor** to ensure nothing broke.
|
|
613
623
|
|
|
614
624
|
<details>
|
|
615
|
-
<summary><strong
|
|
625
|
+
<summary><strong>TDD Loop Guidelines (click to expand)</strong></summary>
|
|
616
626
|
|
|
617
627
|
**Iteration strategy:**
|
|
618
628
|
- Start with first failing stable mode step
|
|
@@ -632,6 +642,8 @@ jettypod workflow checkpoint <feature-id> --step=5
|
|
|
632
642
|
|
|
633
643
|
</details>
|
|
634
644
|
|
|
645
|
+
**Quality Gate:** Before committing, review every `.steps.js` file you wrote or modified. Check for banlist violations: `setTimeout`/`sleep`, module-level `let`/`var`, raw SQL, assertions in Given/When, self-fulfilling mocks, steps longer than 5 lines. Fix violations before proceeding.
|
|
646
|
+
|
|
635
647
|
---
|
|
636
648
|
|
|
637
649
|
### Step 6: Route After Chore Completion
|
|
@@ -654,10 +666,10 @@ sqlite3 .jettypod/work.db "SELECT id, title FROM work_items WHERE parent_id = <f
|
|
|
654
666
|
|
|
655
667
|
```
|
|
656
668
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
657
|
-
|
|
669
|
+
Stable Mode Chore Complete
|
|
658
670
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
659
671
|
|
|
660
|
-
|
|
672
|
+
Error handling and validation scenarios pass for this chore
|
|
661
673
|
|
|
662
674
|
More stable mode chores remain. Starting next chore:
|
|
663
675
|
#[next-chore-id]: [next-chore-title]
|
|
@@ -699,7 +711,7 @@ If the query returns no remaining chores, proceed to Step 7.
|
|
|
699
711
|
|
|
700
712
|
### Step 7: Complete Feature or Transition to Production Mode
|
|
701
713
|
|
|
702
|
-
|
|
714
|
+
**CRITICAL: This step ONLY runs after ALL stable chores are complete.**
|
|
703
715
|
|
|
704
716
|
**First, merge the final stable chore:**
|
|
705
717
|
|
|
@@ -741,27 +753,26 @@ sqlite3 .jettypod/work.db "SELECT project_state FROM project_config WHERE id = 1
|
|
|
741
753
|
|
|
742
754
|
**If project_state = 'internal':**
|
|
743
755
|
|
|
744
|
-
|
|
745
|
-
jettypod work status <feature-id> done
|
|
746
|
-
```
|
|
756
|
+
**The merge command automatically sets the feature as ready for review.**
|
|
757
|
+
It will appear with accept/reject buttons on the kanban board. Do NOT call `jettypod work status <feature-id> done` — that bypasses the review gate.
|
|
747
758
|
|
|
748
759
|
**Display:**
|
|
749
760
|
|
|
750
761
|
```
|
|
751
762
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
752
|
-
|
|
763
|
+
FEATURE COMPLETE!
|
|
753
764
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
754
765
|
|
|
755
766
|
Feature: #[id] [Feature Title]
|
|
756
|
-
Status:
|
|
767
|
+
Status: DONE
|
|
757
768
|
|
|
758
769
|
What we accomplished:
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
770
|
+
All BDD scenarios passing (success + error handling + edge cases)
|
|
771
|
+
Comprehensive error handling and validation
|
|
772
|
+
Input validation and edge case coverage
|
|
773
|
+
State consistency and data integrity
|
|
763
774
|
|
|
764
|
-
|
|
775
|
+
INTERNAL PROJECT - STABLE MODE IS COMPLETE
|
|
765
776
|
|
|
766
777
|
This is an internal project - stable mode is the end state.
|
|
767
778
|
Feature is complete and ready to use!
|
|
@@ -770,7 +781,7 @@ Note: If you later transition to external (accepting real users),
|
|
|
770
781
|
run the external-transition skill to generate production chores.
|
|
771
782
|
```
|
|
772
783
|
|
|
773
|
-
|
|
784
|
+
**WORKFLOW INTEGRATION: Complete workflow (internal project)**
|
|
774
785
|
|
|
775
786
|
```bash
|
|
776
787
|
jettypod workflow complete stable-mode <feature-id>
|
|
@@ -792,7 +803,7 @@ This marks the `stable_mode_complete` gate as passed. For internal projects, thi
|
|
|
792
803
|
|
|
793
804
|
**If project_state = 'external':**
|
|
794
805
|
|
|
795
|
-
|
|
806
|
+
**CRITICAL HANDOFF - You MUST invoke production-mode using the Skill tool.**
|
|
796
807
|
|
|
797
808
|
**Set feature mode to production:**
|
|
798
809
|
|
|
@@ -804,21 +815,21 @@ jettypod work set-mode <feature-id> production
|
|
|
804
815
|
|
|
805
816
|
```
|
|
806
817
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
807
|
-
|
|
818
|
+
Stable Mode Complete! Transitioning to Production Mode
|
|
808
819
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
809
820
|
|
|
810
|
-
|
|
821
|
+
CRITICAL: This is an EXTERNAL project.
|
|
811
822
|
Stable mode makes it robust - production mode makes it ready for real users.
|
|
812
823
|
|
|
813
824
|
What we accomplished:
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
825
|
+
All BDD scenarios passing (success + error handling + edge cases)
|
|
826
|
+
Comprehensive error handling and validation
|
|
827
|
+
Feature stable and ready for production hardening
|
|
817
828
|
|
|
818
|
-
|
|
829
|
+
Now invoking production-mode skill...
|
|
819
830
|
```
|
|
820
831
|
|
|
821
|
-
|
|
832
|
+
**WORKFLOW INTEGRATION: Complete workflow (external project)**
|
|
822
833
|
|
|
823
834
|
```bash
|
|
824
835
|
jettypod workflow complete stable-mode <feature-id>
|
|
@@ -854,7 +865,7 @@ Before ending stable-mode skill, ensure:
|
|
|
854
865
|
- [ ] Integration scenario still passes (feature remains reachable after error handling added)
|
|
855
866
|
- [ ] Final chore merged to main
|
|
856
867
|
- [ ] Project state checked (internal vs external)
|
|
857
|
-
- [ ] **INTERNAL:** Feature
|
|
868
|
+
- [ ] **INTERNAL:** Feature merged (review gate set automatically by merge command)
|
|
858
869
|
- [ ] **EXTERNAL:** Feature mode set to production AND production-mode skill invoked
|
|
859
870
|
|
|
860
871
|
---
|
|
@@ -878,17 +889,17 @@ jettypod work start <chore-id> # Create worktree and start chore
|
|
|
878
889
|
|
|
879
890
|
**Set feature status/mode:**
|
|
880
891
|
```bash
|
|
881
|
-
|
|
882
|
-
jettypod work set-mode <feature-id> production # Set feature to production mode
|
|
892
|
+
# Do NOT call `work status done` — merge sets the review gate automatically
|
|
893
|
+
jettypod work set-mode <feature-id> production # Set feature to production mode (external only)
|
|
883
894
|
```
|
|
884
895
|
|
|
885
|
-
|
|
896
|
+
**DO NOT use these to complete chores:**
|
|
886
897
|
- `jettypod work status <chore-id> done`
|
|
887
898
|
- `jettypod work complete <id>`
|
|
888
899
|
|
|
889
900
|
---
|
|
890
901
|
|
|
891
|
-
##
|
|
902
|
+
## Important: Sequential Workflow
|
|
892
903
|
|
|
893
904
|
**Stable mode chores MUST be completed sequentially, not in parallel.**
|
|
894
905
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# BDD Reference for Skills
|
|
2
|
+
|
|
3
|
+
Read this before writing scenarios or step definitions. Every rule here is enforced — not advisory.
|
|
4
|
+
|
|
5
|
+
## Scenario Formulation
|
|
6
|
+
|
|
7
|
+
**Feature files describe "what" and "why." Step definitions implement "how."**
|
|
8
|
+
|
|
9
|
+
Each scenario: one behavior, one reason to fail.
|
|
10
|
+
|
|
11
|
+
### Rules
|
|
12
|
+
|
|
13
|
+
- **Declarative** — describe intent, not UI clicks. "When the user retries payment" not "When I click the third button."
|
|
14
|
+
- **Stable** — no brittle details (pixel positions, timing, CSS selectors).
|
|
15
|
+
- **Deterministic** — use factories with known data. Never depend on ambient/existing data.
|
|
16
|
+
- **No implementation leakage** — no "Given the database has..." in feature files. Use intentful language: "Given a user with an unpaid invoice."
|
|
17
|
+
|
|
18
|
+
### Good
|
|
19
|
+
|
|
20
|
+
```gherkin
|
|
21
|
+
Scenario: User can retry a failed payment
|
|
22
|
+
Given a user with an unpaid invoice
|
|
23
|
+
And the payment processor returns "insufficient_funds"
|
|
24
|
+
When the user retries payment with a different card
|
|
25
|
+
Then the invoice is marked as paid
|
|
26
|
+
And the user sees a receipt
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Bad
|
|
30
|
+
|
|
31
|
+
```gherkin
|
|
32
|
+
Scenario: Pay invoice
|
|
33
|
+
Given I click the "Billing" tab
|
|
34
|
+
And I wait 2 seconds
|
|
35
|
+
And I click the third button on the page
|
|
36
|
+
When I type "4111111111111111" into the card field
|
|
37
|
+
Then I should see "Success"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Step Definition Banlist
|
|
41
|
+
|
|
42
|
+
These are BANNED in step definitions. Not "avoid" — banned.
|
|
43
|
+
|
|
44
|
+
| Banned | Use instead |
|
|
45
|
+
|--------|-------------|
|
|
46
|
+
| `setTimeout`, `sleep`, fixed waits | `waitFor(() => condition, { timeout })` polling utility |
|
|
47
|
+
| Module-level `let`/`var` state | Cucumber World (`this`) for per-scenario state |
|
|
48
|
+
| Raw SQL (`db.run`, `db.get`) | Helper methods in `features/support/helpers/` |
|
|
49
|
+
| Loops and branching logic | One intentful helper call per step |
|
|
50
|
+
| Assertions in Given/When steps | Assertions belong in Then steps only |
|
|
51
|
+
| Inline selectors/click chains | Page objects or screen models |
|
|
52
|
+
| Setting mock state then asserting it | Tests must exercise real production code |
|
|
53
|
+
|
|
54
|
+
### Thin Step Pattern
|
|
55
|
+
|
|
56
|
+
Steps do three things: parse parameters, call one helper, assert outcome.
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
// GOOD — thin step, calls helper
|
|
60
|
+
When('the user retries payment with a different card', async function () {
|
|
61
|
+
await this.billing.retryPaymentWith(this.validCard);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// BAD — inline implementation
|
|
65
|
+
When('the user retries payment with a different card', async function () {
|
|
66
|
+
await page.click('#billing-tab');
|
|
67
|
+
await page.waitForSelector('.invoice-list');
|
|
68
|
+
await page.click('.invoice:first-child .retry-btn');
|
|
69
|
+
await page.fill('#card-number', '4242424242424242');
|
|
70
|
+
await page.click('#submit');
|
|
71
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Helper Layer Architecture
|
|
76
|
+
|
|
77
|
+
Step definitions must not contain domain logic, SQL, or UI interaction directly. Use this layering:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
Feature files (behavior — Gherkin)
|
|
81
|
+
└─ Step definitions (glue — thin, 1-5 lines)
|
|
82
|
+
└─ Helpers (features/support/helpers/)
|
|
83
|
+
├─ Domain helpers (intentful operations)
|
|
84
|
+
├─ API client
|
|
85
|
+
├─ DB helpers (encapsulated queries)
|
|
86
|
+
└─ Wait utilities (polling, not sleeping)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Dependency rules:**
|
|
90
|
+
- Step defs call helpers. Never call drivers directly.
|
|
91
|
+
- Helpers call drivers (DB, API, UI).
|
|
92
|
+
- Feature files know nothing about implementation.
|
|
93
|
+
|
|
94
|
+
**Before writing step definitions:** Read `features/support/helpers/` for existing helpers. Reuse before creating new ones.
|
|
95
|
+
|
|
96
|
+
## Async & External Dependencies
|
|
97
|
+
|
|
98
|
+
**Async:** Poll with timeout, never sleep.
|
|
99
|
+
```js
|
|
100
|
+
await waitFor(() => order.status === 'COMPLETED', { timeout: 10_000 });
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**External services:** Stub at the boundary for most tests. Use fakes (in-memory implementations) over mocks. Mocks test call patterns ("did we call X?"); fakes test outcomes ("did the user get the result?").
|
|
104
|
+
|
|
105
|
+
**Auth flows:** Use test shortcuts (token minting, session injection). Don't make every scenario pay the login tax.
|
|
106
|
+
|
|
107
|
+
## Test Doubles
|
|
108
|
+
|
|
109
|
+
Prefer stubs/fakes for BDD. They support behavior assertions without coupling to implementation.
|
|
110
|
+
|
|
111
|
+
Use mocks only when verifying a side effect IS the scenario's purpose (e.g., "audit event was emitted").
|
|
112
|
+
|
|
113
|
+
**BDD asserts outcomes, not internal choreography.**
|
|
114
|
+
|
|
115
|
+
## Data Setup
|
|
116
|
+
|
|
117
|
+
Use intentful factories:
|
|
118
|
+
```js
|
|
119
|
+
// GOOD
|
|
120
|
+
await this.fixtures.createUserWithUnpaidInvoice();
|
|
121
|
+
|
|
122
|
+
// BAD — implementation leakage
|
|
123
|
+
await db.run('INSERT INTO users...');
|
|
124
|
+
await db.run('INSERT INTO invoices...');
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Freeze time and seed randomness. Assert on meaning ("receipt exists") not raw IDs.
|
|
128
|
+
|
|
129
|
+
## Quality Checklist
|
|
130
|
+
|
|
131
|
+
After writing tests, verify:
|
|
132
|
+
|
|
133
|
+
- [ ] Steps are 1-5 lines, each calling one helper
|
|
134
|
+
- [ ] No `setTimeout` or `sleep` anywhere in step definitions
|
|
135
|
+
- [ ] State stored on `this` (Cucumber World), not module-level variables
|
|
136
|
+
- [ ] No raw SQL in step definitions
|
|
137
|
+
- [ ] Assertions only in Then steps
|
|
138
|
+
- [ ] Tests exercise real production code (not asserting mock state you just set)
|
|
139
|
+
- [ ] Existing helpers reused, not duplicated
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Poll a condition function until it returns true, with timeout.
|
|
3
|
+
* Use this instead of setTimeout/sleep in step definitions.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* const { waitFor } = require('../helpers/wait');
|
|
7
|
+
* await waitFor(() => order.status === 'COMPLETED', { timeout: 10000 });
|
|
8
|
+
*/
|
|
9
|
+
async function waitFor(conditionFn, { timeout = 5000, interval = 100 } = {}) {
|
|
10
|
+
const start = Date.now();
|
|
11
|
+
while (Date.now() - start < timeout) {
|
|
12
|
+
if (await conditionFn()) return;
|
|
13
|
+
await new Promise(r => setTimeout(r, interval));
|
|
14
|
+
}
|
|
15
|
+
throw new Error(`waitFor timed out after ${timeout}ms`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = { waitFor };
|