jettypod 4.1.2 โ†’ 4.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/.nvmrc +1 -0
  2. package/docs/COMPLETE-TESTING-STRATEGY.md +970 -0
  3. package/docs/DECISIONS.md +10 -12
  4. package/docs/NODE_VERSION.md +83 -0
  5. package/docs/TDD-INFRASTRUCTURE-STRATEGY.md +1374 -0
  6. package/docs/TESTING-FOR-NON-ENGINEERS.md +1588 -0
  7. package/docs/TESTING-STRATEGY-AUDIT.md +698 -0
  8. package/hooks/post-checkout +17 -0
  9. package/hooks/post-merge +17 -0
  10. package/hooks/pre-commit +30 -0
  11. package/jettypod.js +259 -120
  12. package/lib/coverage-tracker.js +218 -0
  13. package/lib/database.js +2 -0
  14. package/lib/db-export.js +192 -0
  15. package/lib/db-import.js +193 -0
  16. package/lib/external-transition-handler.js +32 -0
  17. package/lib/git-hook-helpers.js +174 -0
  18. package/lib/git-root.js +90 -0
  19. package/lib/infrastructure-chore-generator.js +45 -0
  20. package/lib/install-hooks.js +52 -0
  21. package/lib/jettypod-backup.js +238 -0
  22. package/lib/merge-lock.js +193 -0
  23. package/lib/migrations/012-add-worktree-path.js +38 -0
  24. package/lib/migrations/013-worktrees-table.js +86 -0
  25. package/lib/migrations/014-migrate-worktree-data.js +161 -0
  26. package/lib/migrations/015-merge-locks-table.js +67 -0
  27. package/lib/pattern-finder.js +152 -0
  28. package/lib/process-manager.js +140 -0
  29. package/lib/production-standards-reader.js +13 -2
  30. package/lib/production-standards-writer.js +85 -0
  31. package/lib/skills/feature-planning/dry-run-validator.js +135 -0
  32. package/lib/skills/feature-planning/validation-formatter.js +160 -0
  33. package/lib/smart-conflict-detection.js +168 -0
  34. package/lib/smart-fetch-rebase.js +614 -0
  35. package/lib/step-definition-parser.js +76 -0
  36. package/lib/unit-test-generator.js +232 -0
  37. package/lib/verification-command-generator.js +66 -0
  38. package/lib/worktree-diagnostics.js +413 -0
  39. package/lib/worktree-facade.js +174 -0
  40. package/lib/worktree-manager.js +636 -0
  41. package/lib/worktree-reconciler.js +429 -0
  42. package/package.json +30 -3
  43. package/skills-templates/external-transition/SKILL.md +34 -3
  44. package/skills-templates/feature-planning/SKILL.md +190 -24
  45. package/skills-templates/production-mode/SKILL.md +127 -9
  46. package/skills-templates/speed-mode/SKILL.md +454 -51
  47. package/skills-templates/stable-mode/SKILL.md +285 -76
  48. package/.claude/PROTECT_SKILLS.md +0 -28
  49. package/.claude/settings.json +0 -24
  50. package/.claude/settings.local.json +0 -16
  51. package/.claude/skills/epic-planning/SKILL.md +0 -297
  52. package/.claude/skills/external-transition/SKILL.md +0 -384
  53. package/.claude/skills/feature-planning/SKILL.md +0 -464
  54. package/.claude/skills/production-mode/SKILL.md +0 -369
  55. package/.claude/skills/speed-mode/SKILL.md +0 -481
  56. package/.claude/skills/stable-mode/SKILL.md +0 -713
  57. package/.claude/skills.backup-2025-11-10T23-33-09-368Z/epic-planning/SKILL.md +0 -297
  58. package/.claude/skills.backup-2025-11-10T23-33-09-368Z/feature-planning/SKILL.md +0 -464
  59. package/.claude/skills.backup-2025-11-10T23-33-09-368Z/speed-mode/SKILL.md +0 -467
  60. package/.claude/skills.backup-2025-11-10T23-33-09-368Z/stable-mode/SKILL.md +0 -673
  61. package/.claude/skills.backup-2025-11-11T16-15-10-070Z/epic-discover/SKILL.md +0 -297
  62. package/.claude/skills.backup-2025-11-11T16-42-43-212Z/epic-planning/SKILL.md +0 -297
  63. package/.claude/skills.backup-2025-11-11T16-42-43-212Z/feature-planning/SKILL.md +0 -464
  64. package/.claude/skills.backup-2025-11-11T16-42-43-212Z/speed-mode/SKILL.md +0 -467
  65. package/.claude/skills.backup-2025-11-11T16-42-43-212Z/stable-mode/SKILL.md +0 -673
  66. package/.claude/skills.backup-2025-11-11T17-06-09-783Z/epic-planning/SKILL.md +0 -297
  67. package/.claude/skills.backup-2025-11-11T17-06-09-783Z/feature-planning/SKILL.md +0 -464
  68. package/.claude/skills.backup-2025-11-11T17-06-09-783Z/speed-mode/SKILL.md +0 -467
  69. package/.claude/skills.backup-2025-11-11T17-06-09-783Z/stable-mode/SKILL.md +0 -673
  70. package/.devpod/current-work.json +0 -10
  71. package/.devpod/work.db +0 -0
  72. package/.github/workflows/test-safety.yml +0 -85
  73. package/.jettypod/config.json +0 -5
  74. package/.jettypod/current-work.json +0 -10
  75. package/.jettypod/hooks/README.md +0 -77
  76. package/.jettypod/hooks/protect-claude-md.js +0 -338
  77. package/.jettypod/test-work.db +0 -0
  78. package/.jettypod/work.db +0 -0
  79. package/CLAUDE.md +0 -49
  80. package/SPEED-STABLE-AUDIT.md +0 -853
  81. package/SYSTEM-BEHAVIOR.md +0 -2199
  82. package/TEST_SAFETY_AUDIT.md +0 -314
  83. package/TEST_SAFETY_IMPLEMENTATION.md +0 -97
  84. package/cucumber-report.html +0 -45
  85. package/dist/devpod-linux +0 -0
  86. package/dist/devpod-macos +0 -0
  87. package/dist/devpod-win.exe +0 -0
  88. package/docs/features/jettypod-standards-explained.md +0 -543
  89. package/docs/features/standards-inventory.md +0 -257
  90. package/features/auto-generate-production-chores.feature +0 -13
  91. package/features/backlog-command.feature +0 -26
  92. package/features/backlog-filtering-production.feature +0 -10
  93. package/features/claude-md-protection/steps.js +0 -498
  94. package/features/decisions/index.js +0 -490
  95. package/features/decisions/index.test.js +0 -208
  96. package/features/fix-text-wrapping.feature +0 -42
  97. package/features/git-hooks/git-hooks.feature +0 -30
  98. package/features/git-hooks/index.js +0 -93
  99. package/features/git-hooks/index.test.js +0 -137
  100. package/features/git-hooks/post-commit +0 -56
  101. package/features/git-hooks/post-merge +0 -47
  102. package/features/git-hooks/pre-commit +0 -28
  103. package/features/git-hooks/simple-steps.js +0 -53
  104. package/features/git-hooks/simple-test.feature +0 -10
  105. package/features/git-hooks/steps.js +0 -196
  106. package/features/jettypod-update-command.feature +0 -46
  107. package/features/mode-prompts/index.js +0 -95
  108. package/features/mode-prompts/simple-steps.js +0 -44
  109. package/features/mode-prompts/simple-test.feature +0 -9
  110. package/features/mode-prompts/validation.test.js +0 -120
  111. package/features/multiple-claude-instances.feature +0 -121
  112. package/features/production-mode-skill.feature +0 -121
  113. package/features/refactor-mode/steps.js +0 -217
  114. package/features/refactor-mode.feature +0 -49
  115. package/features/simplify-external-transition.feature +0 -166
  116. package/features/skills-update/index.test.js +0 -216
  117. package/features/step_definitions/backlog-command.steps.js +0 -37
  118. package/features/step_definitions/fix-text-wrapping.steps.js +0 -271
  119. package/features/step_definitions/multiple-claude-instances.steps.js +0 -621
  120. package/features/step_definitions/production-mode-skill.steps.js +0 -862
  121. package/features/step_definitions/simplify-external-transition.steps.js +0 -370
  122. package/features/step_definitions/terminal-logo.steps.js +0 -145
  123. package/features/step_definitions/update-command.steps.js +0 -183
  124. package/features/support/hooks.js +0 -9
  125. package/features/terminal-logo/index.js +0 -39
  126. package/features/terminal-logo/terminal-logo.feature +0 -30
  127. package/features/update-command/index.js +0 -181
  128. package/features/update-command/index.test.js +0 -225
  129. package/features/work-commands/bug-workflow-display.feature +0 -22
  130. package/features/work-commands/index.js +0 -498
  131. package/features/work-commands/simple-steps.js +0 -69
  132. package/features/work-commands/stable-tests.feature +0 -57
  133. package/features/work-commands/steps.js +0 -1174
  134. package/features/work-commands/validation.test.js +0 -88
  135. package/features/work-commands/work-commands.feature +0 -13
  136. package/features/work-tracking/discovery-validation.test.js +0 -228
  137. package/features/work-tracking/index.js +0 -1921
  138. package/features/work-tracking/mode-required.feature +0 -112
  139. package/features/work-tracking/phase-tracking.test.js +0 -482
  140. package/features/work-tracking/prototype-tracking.test.js +0 -485
  141. package/features/work-tracking/tree-view.test.js +0 -310
  142. package/features/work-tracking/work-set-mode.feature +0 -71
  143. package/features/work-tracking/work-start-mode.feature +0 -88
  144. package/full-test.txt +0 -0
  145. package/lib/bug-workflow.test.js +0 -177
  146. package/lib/claudemd.test.js +0 -195
  147. package/lib/config.test.js +0 -511
  148. package/lib/constants.test.js +0 -164
  149. package/lib/current-work.test.js +0 -146
  150. package/lib/database-project-config.test.js +0 -111
  151. package/lib/database.test.js +0 -106
  152. package/lib/decisions-generator.test.js +0 -457
  153. package/lib/decisions-helpers.test.js +0 -310
  154. package/lib/git-coordinator.js +0 -167
  155. package/lib/git.test.js +0 -145
  156. package/lib/migrations/002-default-work-item-modes.test.js +0 -351
  157. package/lib/production-chore-generator.test.js +0 -432
  158. package/lib/production-context-detector.test.js +0 -277
  159. package/lib/production-scenario-appender.test.js +0 -235
  160. package/lib/production-scenario-validator.test.js +0 -246
  161. package/lib/production-standards-reader.test.js +0 -270
  162. package/lib/project-state.test.js +0 -92
  163. package/lib/push-queue.js +0 -417
  164. package/lib/queue-processor.js +0 -74
  165. package/lib/test-helpers.js +0 -202
  166. package/lib/test-helpers.test.js +0 -255
  167. package/prototypes/2025-01-11-production-mode-autonomous.js +0 -119
  168. package/prototypes/2025-01-11-production-mode-collaborative.js +0 -166
  169. package/prototypes/2025-01-11-production-mode-guided.js +0 -217
  170. package/prototypes/2025-01-11-production-mode-smart-context.js +0 -347
  171. package/prototypes/2025-01-11-production-standards-example.md +0 -204
  172. package/prototypes/2025-11-10-backlog-filtering-tree-aware.js +0 -242
  173. package/prototypes/test/index.html +0 -1
  174. package/setup-dist-repo.sh +0 -68
  175. package/test-production-standards-engine.js +0 -130
  176. package/test-results.json +0 -2195
  177. package/test-safety-check.sh +0 -80
  178. package/work-item-tracking-plan.md +0 -199
  179. /package/{.jettypod/devpod.db โ†’ jettypod.db} +0 -0
@@ -0,0 +1,1588 @@
1
+ # Testing Strategy for Non-Engineers: JettyPod Methodology
2
+
3
+ **Date**: 2025-11-14
4
+ **Audience**: Non-engineers building software with AI + JettyPod
5
+ **Purpose**: Tests as documentation, AI guidance, and quality assurance
6
+ **Coverage Target**: 100% (tests replace traditional documentation)
7
+
8
+ ---
9
+
10
+ ## Philosophy: Tests Are Your Documentation
11
+
12
+ ### Why 100% Coverage Makes Sense Here
13
+
14
+ **Traditional software development:**
15
+ - Tests = quality assurance
16
+ - Docs = separate markdown files
17
+ - 80% coverage = good enough
18
+
19
+ **JettyPod methodology:**
20
+ - Tests = documentation + quality + AI guidance
21
+ - No separate docs (except work item notes)
22
+ - 100% coverage = necessary for AI to understand system
23
+
24
+ ### What This Means
25
+
26
+ **Every piece of functionality has:**
27
+ 1. BDD scenario (readable by humans)
28
+ 2. Step definitions (executable by AI)
29
+ 3. Unit tests (detailed documentation of behavior)
30
+
31
+ **AI assistants read tests to understand:**
32
+ - How does login work? โ†’ Read `features/login.feature`
33
+ - What validation exists? โ†’ Read `lib/validators.test.js`
34
+ - What errors are handled? โ†’ Read error scenarios in BDD
35
+
36
+ **Users read tests to understand:**
37
+ - What does this feature do? โ†’ Read BDD scenario
38
+ - How do I use this? โ†’ Read Given/When/Then steps
39
+ - What can go wrong? โ†’ Read error scenarios
40
+
41
+ ---
42
+
43
+ ## Test Types in JettyPod
44
+
45
+ ### 1. BDD Scenarios (Primary Documentation)
46
+
47
+ **Purpose**: Human-readable documentation of features
48
+
49
+ **Written in**: Plain English (Gherkin syntax)
50
+
51
+ **Example:**
52
+ ```gherkin
53
+ Feature: User Login
54
+ As a user
55
+ I want to log in with email and password
56
+ So that I can access my account
57
+
58
+ Scenario: Successful login
59
+ Given I am on the login page
60
+ And I have an account with email "user@example.com"
61
+ When I enter my email and password
62
+ And I click the "Login" button
63
+ Then I am redirected to the dashboard
64
+ And I see a welcome message "Welcome back!"
65
+
66
+ Scenario: Login with wrong password
67
+ Given I am on the login page
68
+ And I have an account with email "user@example.com"
69
+ When I enter my email and wrong password
70
+ And I click the "Login" button
71
+ Then I remain on the login page
72
+ And I see an error message "Invalid password"
73
+ And my password field is cleared
74
+
75
+ Scenario: Login with unregistered email
76
+ Given I am on the login page
77
+ When I enter email "unknown@example.com" and any password
78
+ And I click the "Login" button
79
+ Then I see an error message "No account found with that email"
80
+ And I see a link to "Create an account"
81
+ ```
82
+
83
+ **Who reads this:**
84
+ - โœ… Users (understand what feature does)
85
+ - โœ… AI assistants (understand behavior to implement)
86
+ - โœ… Future developers (onboarding)
87
+
88
+ ---
89
+
90
+ ### 2. Step Definitions (AI Implementation Guide)
91
+
92
+ **Purpose**: Executable code that AI can reference
93
+
94
+ **Written in**: JavaScript (with detailed comments)
95
+
96
+ **Example:**
97
+ ```javascript
98
+ // features/step_definitions/login.steps.js
99
+
100
+ const { Given, When, Then } = require('@cucumber/cucumber');
101
+
102
+ /**
103
+ * Sets up a user account for testing login
104
+ * Creates user in test database with hashed password
105
+ */
106
+ Given('I have an account with email {string}', async function(email) {
107
+ // AI reads this to understand user creation flow
108
+ const hashedPassword = await hashPassword('correct-password');
109
+
110
+ this.testUser = await createUser({
111
+ email: email,
112
+ password: hashedPassword,
113
+ name: 'Test User'
114
+ });
115
+
116
+ // Track for cleanup
117
+ this.createdUsers.push(this.testUser.id);
118
+ });
119
+
120
+ /**
121
+ * Simulates user entering credentials in login form
122
+ * Sets form values without actually rendering UI
123
+ */
124
+ When('I enter my email and password', async function() {
125
+ // AI reads this to understand login form structure
126
+ this.loginForm = {
127
+ email: this.testUser.email,
128
+ password: 'correct-password',
129
+ rememberMe: false
130
+ };
131
+ });
132
+
133
+ /**
134
+ * Executes login logic and captures result
135
+ * This is the core login implementation
136
+ */
137
+ When('I click the {string} button', async function(buttonText) {
138
+ if (buttonText === 'Login') {
139
+ // AI reads this to understand login flow
140
+ try {
141
+ this.loginResult = await login(
142
+ this.loginForm.email,
143
+ this.loginForm.password
144
+ );
145
+
146
+ // Store session for subsequent steps
147
+ this.session = this.loginResult.session;
148
+ } catch (error) {
149
+ this.loginError = error;
150
+ }
151
+ }
152
+ });
153
+
154
+ /**
155
+ * Verifies successful login redirects to dashboard
156
+ * Confirms session is established
157
+ */
158
+ Then('I am redirected to the dashboard', function() {
159
+ // AI reads this to understand success criteria
160
+ expect(this.loginResult.redirectTo).toBe('/dashboard');
161
+ expect(this.session).toBeDefined();
162
+ expect(this.session.userId).toBe(this.testUser.id);
163
+ });
164
+ ```
165
+
166
+ **Who reads this:**
167
+ - โœ… AI assistants (detailed implementation guidance)
168
+ - โœ… Advanced users (debugging)
169
+ - โš ๏ธ Non-technical users (too complex)
170
+
171
+ ---
172
+
173
+ ### 3. Unit Tests (Detailed Behavior Documentation)
174
+
175
+ **Purpose**: Document edge cases and implementation details
176
+
177
+ **Written in**: JavaScript (with descriptive test names)
178
+
179
+ **Example:**
180
+ ```javascript
181
+ // lib/auth.test.js
182
+
183
+ describe('login(email, password)', () => {
184
+ describe('successful login', () => {
185
+ it('returns user data when credentials are correct', async () => {
186
+ const user = await createTestUser('user@example.com', 'password123');
187
+
188
+ const result = await login('user@example.com', 'password123');
189
+
190
+ expect(result.success).toBe(true);
191
+ expect(result.user.email).toBe('user@example.com');
192
+ expect(result.session).toBeDefined();
193
+ });
194
+
195
+ it('creates a session that expires in 24 hours', async () => {
196
+ const user = await createTestUser('user@example.com', 'password123');
197
+
198
+ const result = await login('user@example.com', 'password123');
199
+
200
+ const expiresAt = new Date(result.session.expiresAt);
201
+ const expectedExpiry = new Date(Date.now() + 24 * 60 * 60 * 1000);
202
+
203
+ expect(expiresAt.getTime()).toBeCloseTo(expectedExpiry.getTime(), -3);
204
+ });
205
+
206
+ it('updates last_login timestamp on user record', async () => {
207
+ const user = await createTestUser('user@example.com', 'password123');
208
+
209
+ await login('user@example.com', 'password123');
210
+
211
+ const updatedUser = await getUserById(user.id);
212
+ expect(updatedUser.lastLogin).toBeDefined();
213
+ expect(new Date(updatedUser.lastLogin).getTime())
214
+ .toBeCloseTo(Date.now(), -3);
215
+ });
216
+ });
217
+
218
+ describe('failed login attempts', () => {
219
+ it('returns error when email does not exist', async () => {
220
+ const result = await login('unknown@example.com', 'password123');
221
+
222
+ expect(result.success).toBe(false);
223
+ expect(result.error).toBe('No account found with that email');
224
+ });
225
+
226
+ it('returns error when password is incorrect', async () => {
227
+ await createTestUser('user@example.com', 'correct-password');
228
+
229
+ const result = await login('user@example.com', 'wrong-password');
230
+
231
+ expect(result.success).toBe(false);
232
+ expect(result.error).toBe('Invalid password');
233
+ });
234
+
235
+ it('does not reveal whether email exists (security)', async () => {
236
+ // Test that error messages don't leak information
237
+ const noEmailResult = await login('unknown@example.com', 'password');
238
+ const wrongPassResult = await login('real@example.com', 'wrong');
239
+
240
+ // Both should have similar response structure
241
+ expect(noEmailResult.error).toContain('Invalid');
242
+ expect(wrongPassResult.error).toContain('Invalid');
243
+ });
244
+
245
+ it('increments failed login counter on wrong password', async () => {
246
+ const user = await createTestUser('user@example.com', 'correct');
247
+
248
+ await login('user@example.com', 'wrong');
249
+ await login('user@example.com', 'wrong');
250
+
251
+ const updatedUser = await getUserById(user.id);
252
+ expect(updatedUser.failedLoginAttempts).toBe(2);
253
+ });
254
+
255
+ it('locks account after 5 failed attempts', async () => {
256
+ const user = await createTestUser('user@example.com', 'correct');
257
+
258
+ // Fail 5 times
259
+ for (let i = 0; i < 5; i++) {
260
+ await login('user@example.com', 'wrong');
261
+ }
262
+
263
+ // 6th attempt should be blocked
264
+ const result = await login('user@example.com', 'correct');
265
+ expect(result.success).toBe(false);
266
+ expect(result.error).toBe('Account locked due to too many failed attempts');
267
+ });
268
+ });
269
+
270
+ describe('edge cases', () => {
271
+ it('handles null email', async () => {
272
+ const result = await login(null, 'password');
273
+
274
+ expect(result.success).toBe(false);
275
+ expect(result.error).toContain('Email is required');
276
+ });
277
+
278
+ it('handles empty password', async () => {
279
+ const result = await login('user@example.com', '');
280
+
281
+ expect(result.success).toBe(false);
282
+ expect(result.error).toContain('Password is required');
283
+ });
284
+
285
+ it('handles extremely long email (buffer overflow test)', async () => {
286
+ const longEmail = 'a'.repeat(10000) + '@example.com';
287
+
288
+ const result = await login(longEmail, 'password');
289
+
290
+ expect(result.success).toBe(false);
291
+ expect(result.error).toContain('Email too long');
292
+ });
293
+
294
+ it('handles SQL injection attempt in email', async () => {
295
+ const maliciousEmail = "'; DROP TABLE users; --";
296
+
297
+ const result = await login(maliciousEmail, 'password');
298
+
299
+ // Should not crash or execute SQL
300
+ expect(result.success).toBe(false);
301
+ expect(result.error).toBeDefined();
302
+ });
303
+ });
304
+ });
305
+ ```
306
+
307
+ **Who reads this:**
308
+ - โœ… AI assistants (understand edge cases and security)
309
+ - โœ… Advanced users (detailed behavior)
310
+ - โŒ Non-technical users (too detailed)
311
+
312
+ ---
313
+
314
+ ## JettyPod's Role in Testing
315
+
316
+ ### What JettyPod Provides Automatically
317
+
318
+ **1. Test Infrastructure Setup**
319
+
320
+ When user runs `jettypod init`:
321
+ ```javascript
322
+ // JettyPod creates:
323
+ project/
324
+ โ”œโ”€โ”€ features/ โ† BDD scenarios directory
325
+ โ”‚ โ”œโ”€โ”€ support/
326
+ โ”‚ โ”‚ โ”œโ”€โ”€ hooks.js โ† Cleanup patterns
327
+ โ”‚ โ”‚ โ””โ”€โ”€ world.js โ† Shared test context
328
+ โ”‚ โ””โ”€โ”€ step_definitions/ โ† Step implementations
329
+ โ”œโ”€โ”€ test/ โ† Unit tests directory
330
+ โ”œโ”€โ”€ .git/hooks/ โ† Smart git hooks
331
+ โ”‚ โ”œโ”€โ”€ pre-commit
332
+ โ”‚ โ”œโ”€โ”€ pre-push
333
+ โ”‚ โ””โ”€โ”€ post-merge
334
+ โ”œโ”€โ”€ jest.config.js โ† Jest configuration
335
+ โ”œโ”€โ”€ cucumber.js โ† Cucumber configuration
336
+ โ””โ”€โ”€ .jettypod/
337
+ โ”œโ”€โ”€ test-config.json โ† Testing strategy config
338
+ โ””โ”€โ”€ coverage-targets.json โ† Coverage requirements
339
+ ```
340
+
341
+ **2. Test Templates**
342
+
343
+ JettyPod provides templates for common patterns:
344
+ ```javascript
345
+ // .jettypod/templates/bdd-scenario.template
346
+ Feature: {{featureName}}
347
+ {{featureDescription}}
348
+
349
+ Scenario: {{happyPathScenario}}
350
+ Given {{initialState}}
351
+ When {{userAction}}
352
+ Then {{expectedOutcome}}
353
+ ```
354
+
355
+ **3. Git Hooks (Context-Aware)**
356
+
357
+ JettyPod installs smart hooks that understand workflow phase:
358
+ ```javascript
359
+ // .git/hooks/pre-commit (installed by JettyPod)
360
+ #!/usr/bin/env node
361
+
362
+ const { getCurrentWork } = require('.jettypod/current-work');
363
+
364
+ const currentWork = getCurrentWork();
365
+ const mode = currentWork?.mode; // speed, stable, production
366
+
367
+ if (mode === 'speed') {
368
+ // Speed mode: Fast smoke test only
369
+ console.log('๐Ÿš€ Speed mode: Running quick validation...');
370
+ execSync('npm run test:smoke', { stdio: 'inherit' });
371
+
372
+ } else if (mode === 'stable') {
373
+ // Stable mode: Run tests for current feature
374
+ console.log('๐Ÿงช Stable mode: Running feature tests...');
375
+ const featureFile = getFeatureFile(currentWork.parent_id);
376
+ execSync(`npx cucumber-js ${featureFile}`, { stdio: 'inherit' });
377
+
378
+ } else if (mode === 'production') {
379
+ // Production mode: Comprehensive validation
380
+ console.log('๐Ÿ›ก๏ธ Production mode: Running full test suite...');
381
+ execSync('npm test', { stdio: 'inherit' });
382
+ }
383
+ ```
384
+
385
+ ---
386
+
387
+ ## Testing in Each Workflow Phase
388
+
389
+ ### Feature-Planning Phase
390
+
391
+ **JettyPod's Role:**
392
+
393
+ 1. **Guides user to write BDD scenarios**
394
+ ```
395
+ Claude (via skill): "Let's write scenarios for your login feature.
396
+
397
+ I'll help you write them in plain English. Here's the template:
398
+
399
+ Feature: What this feature does
400
+
401
+ Scenario: What happens in the happy path
402
+ Given [starting situation]
403
+ When [user takes action]
404
+ Then [what they see/experience]
405
+
406
+ Let's start with the happy path. When a user successfully logs in,
407
+ what should happen?"
408
+
409
+ User: "They should see their dashboard with a welcome message"
410
+
411
+ Claude: "Great! Here's the scenario:
412
+
413
+ Scenario: User logs in successfully
414
+ Given I am registered with email 'user@example.com'
415
+ When I enter my email and password
416
+ And I click 'Login'
417
+ Then I am redirected to my dashboard
418
+ And I see 'Welcome back!'
419
+
420
+ Does this capture it? Any other details?"
421
+ ```
422
+
423
+ 2. **Generates step definitions automatically**
424
+ ```javascript
425
+ // JettyPod auto-generates:
426
+ Given('I am registered with email {string}', async function(email) {
427
+ // TODO: Implement user creation
428
+ this.testUser = await createUser({ email });
429
+ });
430
+
431
+ When('I enter my email and password', async function() {
432
+ // TODO: Implement form interaction
433
+ this.loginData = {
434
+ email: this.testUser.email,
435
+ password: 'test-password'
436
+ };
437
+ });
438
+
439
+ Then('I am redirected to my dashboard', function() {
440
+ // TODO: Implement redirect check
441
+ expect(this.response.redirect).toBe('/dashboard');
442
+ });
443
+ ```
444
+
445
+ 3. **Validates test infrastructure**
446
+ ```bash
447
+ # JettyPod runs automatically:
448
+ npx cucumber-js --dry-run features/login.feature
449
+
450
+ # Output:
451
+ โœ… 3 scenarios (3 undefined)
452
+ โœ… 12 steps (12 undefined)
453
+ โš ๏ธ You need to implement these step definitions
454
+ ```
455
+
456
+ **User Experience:**
457
+ ```
458
+ You: "I want to add a login feature"
459
+
460
+ Claude: "Let's plan it! First, how should login work?"
461
+
462
+ You: "User enters email and password, clicks login, goes to dashboard"
463
+
464
+ Claude: "Perfect! I've created the BDD scenario in features/login.feature.
465
+ Let me show you:
466
+
467
+ Feature: User Login
468
+ Scenario: User logs in successfully
469
+ Given I am on the login page
470
+ When I enter valid credentials
471
+ Then I am redirected to dashboard
472
+
473
+ โœ… Scenario created
474
+ โœ… Step definitions scaffolded
475
+ ๐Ÿ”„ Ready for speed mode implementation
476
+
477
+ Next: jettypod work start [chore-id]"
478
+ ```
479
+
480
+ ---
481
+
482
+ ### Speed-Mode Phase
483
+
484
+ **JettyPod's Role:**
485
+
486
+ 1. **Guides implementation with TDD**
487
+ ```
488
+ Claude: "Let's implement the login feature. I'll use TDD:
489
+
490
+ Step 1: Make the first scenario step pass
491
+ Given I am on the login page
492
+
493
+ I need to implement:
494
+ - Login page route
495
+ - Basic form rendering
496
+
497
+ Writing the step definition first..."
498
+
499
+ [Claude writes step definition]
500
+
501
+ Claude: "Now implementing the route and form...
502
+
503
+ [Claude writes code]
504
+
505
+ Running test: npx cucumber-js features/login.feature
506
+
507
+ โœ… Step 1 passing
508
+ ๐Ÿ”„ Moving to Step 2: 'When I enter valid credentials'..."
509
+ ```
510
+
511
+ 2. **Runs tests continuously**
512
+ ```javascript
513
+ // Inside speed-mode skill loop:
514
+ while (!scenarioPasses) {
515
+ // 1. Implement next piece
516
+ await implementNextStep();
517
+
518
+ // 2. Run BDD test
519
+ const result = execSync(`npx cucumber-js ${featureFile}`);
520
+
521
+ // 3. Show progress to user
522
+ console.log(`
523
+ Progress:
524
+ โœ… Given I am on the login page
525
+ โœ… When I enter valid credentials
526
+ ๐Ÿ”„ Then I am redirected to dashboard (working on this)
527
+ `);
528
+
529
+ // 4. Iterate until passing
530
+ if (allStepsPass(result)) {
531
+ scenarioPasses = true;
532
+ }
533
+ }
534
+ ```
535
+
536
+ 3. **Generates unit tests for new functions**
537
+ ```javascript
538
+ // Claude (via skill): "I created a validateEmail() function.
539
+ // Let me write unit tests to document its behavior..."
540
+
541
+ describe('validateEmail', () => {
542
+ it('accepts valid email addresses', () => {
543
+ expect(validateEmail('user@example.com')).toBe(true);
544
+ });
545
+
546
+ it('rejects emails without @', () => {
547
+ expect(validateEmail('userexample.com')).toBe(false);
548
+ });
549
+
550
+ // etc...
551
+ });
552
+ ```
553
+
554
+ **User Experience:**
555
+ ```
556
+ You: "Start implementing login"
557
+
558
+ Claude: "I'll implement the login feature to pass the scenario we wrote.
559
+
560
+ ๐Ÿ”„ Iteration 1:
561
+ โœ๏ธ Creating login form component...
562
+ ๐Ÿงช Testing... 1 of 3 steps passing
563
+
564
+ ๐Ÿ”„ Iteration 2:
565
+ โœ๏ธ Adding authentication logic...
566
+ ๐Ÿงช Testing... 2 of 3 steps passing
567
+
568
+ ๐Ÿ”„ Iteration 3:
569
+ โœ๏ธ Adding dashboard redirect...
570
+ ๐Ÿงช Testing... โœ… All steps passing!
571
+
572
+ โœ… Login feature works (happy path)
573
+
574
+ Next: Should I create stable mode chores to add error handling?"
575
+ ```
576
+
577
+ ---
578
+
579
+ ### Stable-Mode Phase
580
+
581
+ **JettyPod's Role:**
582
+
583
+ 1. **Guides user to identify error scenarios**
584
+ ```
585
+ Claude: "The happy path works! Now let's think about what can go wrong.
586
+
587
+ What should happen if:
588
+ 1. User enters wrong password?
589
+ 2. User's email doesn't exist?
590
+ 3. User is already logged in?
591
+ 4. Login fails due to server error?
592
+
593
+ For each one, we'll:
594
+ - Add a BDD scenario (human-readable)
595
+ - Implement error handling (code)
596
+ - Add unit tests (edge cases)
597
+
598
+ Let's start with #1: Wrong password..."
599
+ ```
600
+
601
+ 2. **Adds error scenarios to feature file**
602
+ ```gherkin
603
+ # JettyPod appends to features/login.feature:
604
+
605
+ Scenario: Login with wrong password
606
+ Given I am registered with email 'user@example.com'
607
+ When I enter my email and wrong password
608
+ And I click 'Login'
609
+ Then I remain on the login page
610
+ And I see error "Invalid password"
611
+ And my password field is cleared
612
+
613
+ Scenario: Login with unregistered email
614
+ Given no user exists with email 'unknown@example.com'
615
+ When I enter email 'unknown@example.com' and any password
616
+ And I click 'Login'
617
+ Then I see error "No account found"
618
+ And I see a link to "Create account"
619
+ ```
620
+
621
+ 3. **Implements error handling with tests first**
622
+ ```javascript
623
+ // TDD cycle for error handling:
624
+
625
+ // 1. RED: Add test for error case
626
+ it('returns error when password is wrong', async () => {
627
+ await createUser('user@example.com', 'correct-password');
628
+
629
+ const result = await login('user@example.com', 'wrong-password');
630
+
631
+ expect(result.success).toBe(false);
632
+ expect(result.error).toBe('Invalid password');
633
+ });
634
+
635
+ // 2. GREEN: Implement error handling
636
+ async function login(email, password) {
637
+ const user = await findUser(email);
638
+
639
+ if (!user) {
640
+ return { success: false, error: 'No account found' };
641
+ }
642
+
643
+ const validPassword = await verifyPassword(password, user.passwordHash);
644
+
645
+ if (!validPassword) {
646
+ return { success: false, error: 'Invalid password' };
647
+ }
648
+
649
+ return { success: true, session: createSession(user) };
650
+ }
651
+
652
+ // 3. REFACTOR: Extract validation
653
+ ```
654
+
655
+ 4. **Tracks coverage and gaps**
656
+ ```javascript
657
+ // JettyPod runs coverage after each iteration:
658
+ npx jest --coverage
659
+
660
+ // Shows user:
661
+ File | % Stmts | % Branch | % Funcs | % Lines |
662
+ lib/auth.js | 95.2 | 89.5 | 100 | 94.8 |
663
+
664
+ Uncovered lines:
665
+ auth.js:45-47 (rare edge case: database connection lost)
666
+
667
+ Claude: "We have 95% coverage. The uncovered lines handle database
668
+ connection loss. Should we test that edge case or is it handled elsewhere?"
669
+ ```
670
+
671
+ **User Experience:**
672
+ ```
673
+ You: "Add error handling to login"
674
+
675
+ Claude: "Let's think about what can go wrong:
676
+ 1. Wrong password
677
+ 2. Email doesn't exist
678
+ 3. Account locked
679
+ 4. Server error
680
+
681
+ I'll add scenarios for each and implement error handling.
682
+
683
+ ๐Ÿ”„ Adding 'Wrong password' scenario...
684
+ โœ๏ธ Writing BDD scenario
685
+ โœ๏ธ Writing unit tests (TDD)
686
+ โœ๏ธ Implementing error handling
687
+ ๐Ÿงช Testing... โœ… Scenario passes
688
+
689
+ ๐Ÿ”„ Adding 'Email doesn't exist' scenario...
690
+ [repeat]
691
+
692
+ โœ… All error scenarios pass
693
+ ๐Ÿ“Š Coverage: 98% (2 lines in rare edge case not covered)
694
+
695
+ Login feature is now robust with error handling!"
696
+ ```
697
+
698
+ ---
699
+
700
+ ### Production-Mode Phase
701
+
702
+ **JettyPod's Role:**
703
+
704
+ 1. **Adds security/performance/scale scenarios**
705
+ ```gherkin
706
+ # JettyPod appends production scenarios:
707
+
708
+ @production @security
709
+ Scenario: Login is protected against brute force attacks
710
+ Given I have an account with email 'user@example.com'
711
+ When I attempt to login with wrong password 10 times
712
+ Then my account is temporarily locked
713
+ And I see "Too many failed attempts. Try again in 15 minutes"
714
+
715
+ @production @performance
716
+ Scenario: Login completes within 200ms
717
+ Given I have an account
718
+ When I login with valid credentials
719
+ Then the response time is under 200ms
720
+ And the session is created
721
+
722
+ @production @security
723
+ Scenario: Login protects against SQL injection
724
+ When I attempt to login with email "'; DROP TABLE users; --"
725
+ Then no SQL is executed
726
+ And I see "Invalid email format"
727
+ ```
728
+
729
+ 2. **Implements production hardening**
730
+ ```javascript
731
+ // Claude adds:
732
+ // - Rate limiting
733
+ // - Brute force protection
734
+ // - SQL injection prevention
735
+ // - XSS prevention
736
+ // - Performance monitoring
737
+
738
+ async function login(email, password) {
739
+ // Production: Rate limiting
740
+ await checkRateLimit(email);
741
+
742
+ // Production: Input sanitization
743
+ const sanitizedEmail = sanitizeInput(email);
744
+
745
+ // Production: SQL injection prevention (parameterized queries)
746
+ const user = await db.query(
747
+ 'SELECT * FROM users WHERE email = $1',
748
+ [sanitizedEmail]
749
+ );
750
+
751
+ // Production: Timing attack prevention
752
+ await constantTimeCompare(password, user.passwordHash);
753
+
754
+ // Production: Brute force protection
755
+ await checkFailedAttempts(user);
756
+
757
+ // Rest of logic...
758
+ }
759
+ ```
760
+
761
+ 3. **Validates all scenarios still pass**
762
+ ```bash
763
+ # JettyPod runs full suite:
764
+ npx cucumber-js --tags "not @wip"
765
+
766
+ # Output:
767
+ โœ… 15 scenarios (15 passed)
768
+ โœ… 87 steps (87 passed)
769
+ ๐Ÿ“Š Coverage: 100%
770
+
771
+ Production scenarios:
772
+ โœ… Brute force protection
773
+ โœ… SQL injection prevention
774
+ โœ… Performance under 200ms
775
+ โœ… XSS prevention
776
+ โœ… Rate limiting
777
+ ```
778
+
779
+ **User Experience:**
780
+ ```
781
+ You: "Make login production-ready"
782
+
783
+ Claude: "I'll harden login for production with:
784
+ 1. Security (brute force, injection protection)
785
+ 2. Performance (response time under 200ms)
786
+ 3. Monitoring (error tracking, metrics)
787
+
788
+ ๐Ÿ”„ Adding security scenarios...
789
+ โœ๏ธ Rate limiting
790
+ โœ๏ธ Brute force protection
791
+ ๐Ÿงช Testing... โœ… Security tests pass
792
+
793
+ ๐Ÿ”„ Adding performance scenarios...
794
+ โœ๏ธ Response time monitoring
795
+ โœ๏ธ Database query optimization
796
+ ๐Ÿงช Testing... โœ… Performance tests pass (avg 145ms)
797
+
798
+ โœ… Login is production-ready!
799
+ ๐Ÿ“Š Coverage: 100%
800
+ ๐Ÿ›ก๏ธ All security tests pass
801
+ โšก Performance: 145ms avg (target: 200ms)
802
+
803
+ Login feature is complete and ready for real users."
804
+ ```
805
+
806
+ ---
807
+
808
+ ## The Complete Testing Experience
809
+
810
+ ### From User's Perspective
811
+
812
+ **Day 1: Feature Planning**
813
+ ```
814
+ You: "I want users to be able to log in"
815
+
816
+ JettyPod: "Let's write scenarios describing how login should work."
817
+
818
+ [Collaborative scenario writing in plain English]
819
+
820
+ โœ… Scenarios written (readable documentation)
821
+ โœ… Test infrastructure ready
822
+ ๐ŸŽฏ Ready to implement
823
+ ```
824
+
825
+ **Day 2-3: Speed Mode**
826
+ ```
827
+ You: "Build the login feature"
828
+
829
+ JettyPod: "I'll implement it step by step, running tests as I go."
830
+
831
+ [TDD implementation with continuous feedback]
832
+
833
+ โœ… Happy path works
834
+ ๐Ÿ“– Tests document how login works
835
+ ๐Ÿ”„ Ready for error handling
836
+ ```
837
+
838
+ **Day 4-5: Stable Mode**
839
+ ```
840
+ You: "Add error handling"
841
+
842
+ JettyPod: "Let's think about what can go wrong and handle each case."
843
+
844
+ [Error scenarios + TDD implementation]
845
+
846
+ โœ… All error cases handled
847
+ ๐Ÿ“– Tests document all edge cases
848
+ ๐Ÿ›ก๏ธ Ready for production hardening
849
+ ```
850
+
851
+ **Day 6: Production Mode**
852
+ ```
853
+ You: "Make it production-ready"
854
+
855
+ JettyPod: "I'll add security, performance, and monitoring."
856
+
857
+ [Production scenarios + hardening]
858
+
859
+ โœ… Production-ready
860
+ ๐Ÿ“– Tests document security measures
861
+ ๐Ÿš€ Ready to deploy
862
+ ```
863
+
864
+ ---
865
+
866
+ ## Coverage: Why 100% Makes Sense
867
+
868
+ ### Traditional Software: 80% Coverage Goal
869
+
870
+ **Why 80% is common:**
871
+ - Diminishing returns on last 20%
872
+ - Some code is hard to test (UI, third-party integration)
873
+ - Docs explain the system
874
+ - Developers understand the codebase
875
+
876
+ **What 80% means:**
877
+ - Core logic: 100% covered
878
+ - Edge cases: Mostly covered
879
+ - Trivial code: Not covered
880
+ - Acceptable because docs supplement tests
881
+
882
+ ### JettyPod Methodology: 100% Coverage Goal
883
+
884
+ **Why 100% makes sense here:**
885
+ - Tests ARE the documentation (no separate docs)
886
+ - AI needs complete understanding of system
887
+ - Non-engineers read tests to understand features
888
+ - Tests explain every edge case and error condition
889
+
890
+ **What 100% means:**
891
+ - Every function has unit tests documenting behavior
892
+ - Every user workflow has BDD scenario
893
+ - Every error condition has test explaining how it's handled
894
+ - Every edge case is documented via test
895
+
896
+ **The uncovered 0%:**
897
+ ```javascript
898
+ // Even trivial code gets documented via tests:
899
+
900
+ // lib/formatters.js
901
+ function capitalize(str) {
902
+ return str.charAt(0).toUpperCase() + str.slice(1);
903
+ }
904
+
905
+ // lib/formatters.test.js
906
+ describe('capitalize', () => {
907
+ it('capitalizes first letter of a word', () => {
908
+ expect(capitalize('hello')).toBe('Hello');
909
+ });
910
+
911
+ it('leaves already capitalized words unchanged', () => {
912
+ expect(capitalize('Hello')).toBe('Hello');
913
+ });
914
+
915
+ it('handles empty string', () => {
916
+ expect(capitalize('')).toBe('');
917
+ });
918
+
919
+ it('handles single character', () => {
920
+ expect(capitalize('a')).toBe('A');
921
+ });
922
+ });
923
+ ```
924
+
925
+ **Why test trivial code?**
926
+ - AI reads these tests to understand string formatting
927
+ - Non-engineers see examples of edge cases
928
+ - Future changes won't break assumptions
929
+ - Tests are the documentation
930
+
931
+ ---
932
+
933
+ ## How AI Uses Tests
934
+
935
+ ### AI Reading Tests as Documentation
936
+
937
+ **Scenario: User asks AI to add password reset**
938
+
939
+ ```
940
+ User: "Add a password reset feature"
941
+
942
+ AI (Claude): "Let me understand how authentication works first..."
943
+
944
+ [AI reads features/login.feature]
945
+
946
+ AI: "I see login uses email and password. Let me check password storage..."
947
+
948
+ [AI reads lib/auth.test.js]
949
+
950
+ AI: "I understand:
951
+ - Passwords are hashed with bcrypt
952
+ - Failed attempts are tracked
953
+ - Account lockout after 5 attempts
954
+ - Sessions expire after 24 hours
955
+
956
+ For password reset, I should:
957
+ 1. Generate reset token (similar to session token)
958
+ 2. Send email with reset link
959
+ 3. Verify token on reset page
960
+ 4. Allow new password (hash with bcrypt like login)
961
+ 5. Clear failed attempts on successful reset
962
+
963
+ Let me write the scenarios first..."
964
+ ```
965
+
966
+ **Without tests as documentation:**
967
+ ```
968
+ AI: "I'll add password reset functionality."
969
+ [Makes assumptions, might conflict with existing auth logic]
970
+ ```
971
+
972
+ **With tests as documentation:**
973
+ ```
974
+ AI: "Based on the auth tests, I'll integrate password reset properly:
975
+ - Use same hashing as login (bcrypt with cost 10)
976
+ - Clear failed attempts on reset (prevents lockout)
977
+ - Generate token with 1-hour expiry (like sessions but shorter)
978
+
979
+ Let me write scenarios that explain the reset flow..."
980
+ ```
981
+
982
+ ---
983
+
984
+ ## JettyPod's Testing Automation
985
+
986
+ ### What JettyPod Does Automatically
987
+
988
+ **1. Test Infrastructure Setup**
989
+ ```javascript
990
+ // When user runs: jettypod init
991
+
992
+ async function initializeProject() {
993
+ // Create test directories
994
+ fs.mkdirSync('features', { recursive: true });
995
+ fs.mkdirSync('features/step_definitions', { recursive: true });
996
+ fs.mkdirSync('features/support', { recursive: true });
997
+ fs.mkdirSync('test', { recursive: true });
998
+
999
+ // Install test dependencies
1000
+ execSync('npm install --save-dev jest @cucumber/cucumber chai');
1001
+
1002
+ // Create configuration files
1003
+ createJestConfig();
1004
+ createCucumberConfig();
1005
+
1006
+ // Create support files with safety patterns
1007
+ createHooksFile(); // Before/After cleanup
1008
+ createWorldFile(); // Shared test context
1009
+
1010
+ // Install git hooks
1011
+ installSmartGitHooks();
1012
+
1013
+ console.log('โœ… Test infrastructure ready');
1014
+ console.log('๐Ÿ“– Tests will serve as your documentation');
1015
+ console.log('๐Ÿค– AI will read tests to understand your system');
1016
+ }
1017
+ ```
1018
+
1019
+ **2. Scenario Generation**
1020
+ ```javascript
1021
+ // In feature-planning skill:
1022
+
1023
+ async function generateScenarios(featureDescription) {
1024
+ // Use AI to generate scenarios from user's description
1025
+ const scenarios = await aiGenerateScenarios({
1026
+ feature: featureDescription,
1027
+ context: readExistingScenarios(), // Learn from existing patterns
1028
+ style: 'non-technical' // Plain English
1029
+ });
1030
+
1031
+ // Write to feature file
1032
+ const featureFile = `features/${slugify(featureDescription)}.feature`;
1033
+ fs.writeFileSync(featureFile, scenarios);
1034
+
1035
+ // Generate step definitions
1036
+ const steps = extractSteps(scenarios);
1037
+ const stepDefinitions = generateStepDefinitions(steps);
1038
+
1039
+ const stepsFile = `features/step_definitions/${slugify(featureDescription)}.steps.js`;
1040
+ fs.writeFileSync(stepsFile, stepDefinitions);
1041
+
1042
+ // Validate infrastructure
1043
+ execSync(`npx cucumber-js --dry-run ${featureFile}`);
1044
+
1045
+ console.log('โœ… Scenarios created and validated');
1046
+ }
1047
+ ```
1048
+
1049
+ **3. Test Execution During Implementation**
1050
+ ```javascript
1051
+ // In speed-mode skill:
1052
+
1053
+ async function implementFeature(featureId) {
1054
+ const feature = getFeature(featureId);
1055
+ const scenarios = readScenarios(feature.scenarioFile);
1056
+
1057
+ for (const scenario of scenarios) {
1058
+ console.log(`\n๐Ÿ”„ Implementing: ${scenario.title}`);
1059
+
1060
+ // TDD loop
1061
+ let passing = false;
1062
+ let iteration = 0;
1063
+
1064
+ while (!passing && iteration < 10) {
1065
+ iteration++;
1066
+
1067
+ // 1. Implement next piece
1068
+ await aiImplementNextStep(scenario, iteration);
1069
+
1070
+ // 2. Run tests
1071
+ console.log('๐Ÿงช Running tests...');
1072
+ const result = execSync(
1073
+ `npx cucumber-js ${feature.scenarioFile}`,
1074
+ { encoding: 'utf-8' }
1075
+ );
1076
+
1077
+ // 3. Check progress
1078
+ const progress = parseTestProgress(result);
1079
+ console.log(`
1080
+ Progress (${progress.passed}/${progress.total} steps):
1081
+ ${formatProgressSteps(progress)}
1082
+ `);
1083
+
1084
+ // 4. Check if scenario passes
1085
+ if (progress.passed === progress.total) {
1086
+ console.log('โœ… Scenario passes!');
1087
+ passing = true;
1088
+ } else {
1089
+ console.log('๐Ÿ”„ Iterating...');
1090
+ }
1091
+ }
1092
+ }
1093
+
1094
+ // Generate unit tests for any new functions
1095
+ await generateUnitTestsForNewCode();
1096
+
1097
+ console.log('\nโœ… Feature implementation complete');
1098
+ console.log('๐Ÿ“– All scenarios pass (tests document behavior)');
1099
+ console.log('๐Ÿ“Š Running coverage...');
1100
+
1101
+ const coverage = execSync('npx jest --coverage', { encoding: 'utf-8' });
1102
+ console.log(coverage);
1103
+ }
1104
+ ```
1105
+
1106
+ **4. Coverage Tracking**
1107
+ ```javascript
1108
+ // After each phase:
1109
+
1110
+ function checkCoverage(phase) {
1111
+ const coverage = getCoverageReport();
1112
+ const target = getCoverageTarget(phase);
1113
+
1114
+ console.log(`\n๐Ÿ“Š Coverage Report (${phase}):`);
1115
+ console.log(`Current: ${coverage.lines}%`);
1116
+ console.log(`Target: ${target.lines}%`);
1117
+
1118
+ if (coverage.lines < target.lines) {
1119
+ console.log(`\nโš ๏ธ Coverage below target`);
1120
+ console.log(`Missing coverage in:`);
1121
+
1122
+ // Show which files need more tests
1123
+ const gaps = findCoverageGaps(coverage);
1124
+ gaps.forEach(gap => {
1125
+ console.log(` - ${gap.file}: ${gap.uncoveredLines.length} uncovered lines`);
1126
+ });
1127
+
1128
+ console.log(`\nShould I write tests to cover these gaps?`);
1129
+ } else {
1130
+ console.log(`\nโœ… Coverage target met!`);
1131
+ }
1132
+ }
1133
+ ```
1134
+
1135
+ **5. Documentation Generation from Tests**
1136
+ ```javascript
1137
+ // JettyPod generates human-readable docs from tests:
1138
+
1139
+ function generateDocumentation() {
1140
+ console.log('๐Ÿ“š Generating documentation from tests...');
1141
+
1142
+ // Parse BDD scenarios
1143
+ const features = parseAllFeatures();
1144
+
1145
+ // Generate markdown documentation
1146
+ const docs = [];
1147
+
1148
+ features.forEach(feature => {
1149
+ docs.push(`# ${feature.title}\n`);
1150
+ docs.push(`${feature.description}\n\n`);
1151
+
1152
+ feature.scenarios.forEach(scenario => {
1153
+ docs.push(`## ${scenario.title}\n\n`);
1154
+ docs.push('**What happens:**\n');
1155
+
1156
+ scenario.steps.forEach(step => {
1157
+ docs.push(`- ${step.type} ${step.text}\n`);
1158
+ });
1159
+
1160
+ docs.push('\n');
1161
+ });
1162
+ });
1163
+
1164
+ fs.writeFileSync('FEATURES.md', docs.join(''));
1165
+
1166
+ console.log('โœ… Documentation generated from tests');
1167
+ console.log('๐Ÿ“– See FEATURES.md for human-readable feature list');
1168
+ }
1169
+ ```
1170
+
1171
+ ---
1172
+
1173
+ ## Test Execution Optimization
1174
+
1175
+ ### The Performance Problem (Solved)
1176
+
1177
+ **Initial implementation challenge:**
1178
+ - Test execution was slow during TDD iterations
1179
+ - Running entire feature files when only testing single scenarios
1180
+ - 5-10 minute iteration cycles
1181
+ - Poor developer experience
1182
+
1183
+ **Root cause:**
1184
+ ```javascript
1185
+ // Original approach: Run entire feature file every iteration
1186
+ const result = execSync(`npm run test:bdd -- ${featureFile}`);
1187
+ // Problem: Tests ALL scenarios when we only care about one
1188
+ ```
1189
+
1190
+ **Solution: Scenario-specific execution:**
1191
+ ```javascript
1192
+ // Optimized: Run only the target scenario during iteration
1193
+ const happyPathLine = getFirstScenarioLine(featureFile);
1194
+ const result = runBddScenarioWithTimeout(featureFile, happyPathLine);
1195
+ // Result: 20-30x faster (10-30 seconds vs 5-10 minutes)
1196
+ ```
1197
+
1198
+ ### How It Works: Context-Aware Testing
1199
+
1200
+ **During iteration (speed/stable/production modes):**
1201
+ - Run ONLY the target scenario being implemented
1202
+ - Fast feedback loop (10-30 seconds)
1203
+ - Focus on the specific functionality being built
1204
+
1205
+ **After GREEN is achieved:**
1206
+ - Run full feature file for regression detection
1207
+ - Ensures new code doesn't break existing scenarios
1208
+ - Comprehensive validation before marking work complete
1209
+
1210
+ **On git commit (pre-commit hook):**
1211
+ - Context-aware test execution based on workflow phase
1212
+ - Speed mode: Happy path only (10-30 seconds)
1213
+ - Stable mode: All current feature scenarios (30-60 seconds)
1214
+ - Production mode: Full test suite (1-2 minutes)
1215
+
1216
+ ### Test Execution Functions
1217
+
1218
+ **1. runBddScenarioWithTimeout()**
1219
+ ```javascript
1220
+ // Run a specific scenario by line number
1221
+ const result = await runBddScenarioWithTimeout(
1222
+ 'features/login.feature',
1223
+ 13, // Line number of "Scenario:" keyword
1224
+ 60000 // 60-second timeout
1225
+ );
1226
+
1227
+ // Or by scenario name
1228
+ const result = await runBddScenarioWithTimeout(
1229
+ 'features/login.feature',
1230
+ 'User logs in successfully', // Scenario name
1231
+ 60000
1232
+ );
1233
+ ```
1234
+
1235
+ **2. runBddTestWithTimeout()**
1236
+ ```javascript
1237
+ // Run entire feature file (for full verification)
1238
+ const result = await runBddTestWithTimeout(
1239
+ 'features/login.feature',
1240
+ 120000 // 120-second timeout
1241
+ );
1242
+ ```
1243
+
1244
+ **3. Timeout Protection**
1245
+ ```javascript
1246
+ // All test execution protected by timeout with graceful termination
1247
+ if (result.timedOut) {
1248
+ console.log('โš ๏ธ Tests timed out - may have infinite loop');
1249
+ // Continue implementation, don't block
1250
+ }
1251
+ ```
1252
+
1253
+ ### Performance Comparison
1254
+
1255
+ **Before optimization:**
1256
+ ```
1257
+ Speed mode iteration:
1258
+ ๐Ÿ”„ Iteration 1: Running tests... 5-10 minutes
1259
+ ๐Ÿ”„ Iteration 2: Running tests... 5-10 minutes
1260
+ ๐Ÿ”„ Iteration 3: Running tests... 5-10 minutes
1261
+ Total: 15-30 minutes for 3 iterations
1262
+ ```
1263
+
1264
+ **After optimization:**
1265
+ ```
1266
+ Speed mode iteration:
1267
+ ๐Ÿ”„ Iteration 1: Running target scenario... 10-30 seconds
1268
+ ๐Ÿ”„ Iteration 2: Running target scenario... 10-30 seconds
1269
+ ๐Ÿ”„ Iteration 3: Running target scenario... 10-30 seconds
1270
+ โœ… GREEN: Running full verification... 1-2 minutes
1271
+ Total: 2-3 minutes for 3 iterations + verification
1272
+ ```
1273
+
1274
+ **20-30x speedup in iteration cycles**
1275
+
1276
+ ### Pre-commit Hook Intelligence
1277
+
1278
+ **Context detection:**
1279
+ ```javascript
1280
+ // Reads CLAUDE.md and database to determine current work
1281
+ const context = detectWorkContext();
1282
+ // Returns: {mode: 'speed'|'stable'|'production', feature_id, scenario_file}
1283
+ ```
1284
+
1285
+ **Adaptive test execution:**
1286
+ ```javascript
1287
+ switch (context.mode) {
1288
+ case 'speed':
1289
+ // Fast smoke test: Happy path scenario only
1290
+ const happyPathLine = getFirstScenarioLine(context.scenario_file);
1291
+ result = runBddScenarioWithTimeout(context.scenario_file, happyPathLine, 30000);
1292
+ break;
1293
+
1294
+ case 'stable':
1295
+ // Feature-specific: All scenarios in current feature
1296
+ result = runBddTestWithTimeout(context.scenario_file, 60000);
1297
+ break;
1298
+
1299
+ case 'production':
1300
+ // Comprehensive: Entire test suite
1301
+ result = runBddTestWithTimeout(context.scenario_file, 120000);
1302
+ break;
1303
+ }
1304
+ ```
1305
+
1306
+ **Non-blocking failures:**
1307
+ - Infrastructure failures allow commit to proceed
1308
+ - Test failures block commit (as expected)
1309
+ - Prevents git hook issues from blocking development
1310
+
1311
+ ### Automatic Unit Test Generation
1312
+
1313
+ **Problem solved:**
1314
+ - "I'll add tests later" syndrome
1315
+ - Missing unit test coverage
1316
+ - Inconsistent test patterns
1317
+
1318
+ **Three-phase approach:**
1319
+
1320
+ **Phase 1: Feature Planning (Scaffolding)**
1321
+ ```javascript
1322
+ // After BDD validation passes, scaffold empty test files
1323
+ const { scaffoldUnitTestFile } = require('../../lib/unit-test-generator');
1324
+
1325
+ for (const implementationFile of inferredFiles) {
1326
+ if (implementationFile.endsWith('.js') && !implementationFile.includes('test')) {
1327
+ const testFile = scaffoldUnitTestFile(implementationFile);
1328
+ console.log(` โœ… Created ${testFile}`);
1329
+ }
1330
+ }
1331
+ ```
1332
+
1333
+ **Phase 2: Speed Mode (Generation)**
1334
+ ```javascript
1335
+ // After GREEN achieved, generate tests for new functions
1336
+ const { generateTestsAfterGreen } = require('../../lib/unit-test-generator');
1337
+
1338
+ for (const modifiedFile of getModifiedFiles()) {
1339
+ const result = generateTestsAfterGreen(modifiedFile);
1340
+
1341
+ if (result.functionsAdded > 0) {
1342
+ console.log(` โœ… Generated tests for ${result.functionsAdded} functions`);
1343
+ console.log(` ${result.testFile}`);
1344
+ }
1345
+ }
1346
+ ```
1347
+
1348
+ **Phase 3: Stable Mode (Edge Cases)**
1349
+ ```javascript
1350
+ // Human review and enhancement of generated tests
1351
+ // Add edge case tests, error condition tests, security tests
1352
+ // Fill in TODO placeholders with actual assertions
1353
+ ```
1354
+
1355
+ ### Coverage Tracking
1356
+
1357
+ **After stable mode completion:**
1358
+ ```javascript
1359
+ const { trackFeatureCoverage } = require('../../lib/coverage-tracker');
1360
+
1361
+ const coverageResult = trackFeatureCoverage(implementationFiles, {
1362
+ coverageThreshold: 80,
1363
+ verbose: false
1364
+ });
1365
+
1366
+ console.log(coverageResult.report);
1367
+ // Output:
1368
+ // ๐Ÿ“Š Unit Test Coverage Report
1369
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
1370
+ // Statements: โœ… 85.23%
1371
+ // Branches: โœ… 82.15%
1372
+ // Functions: โœ… 88.50%
1373
+ // Lines: โœ… 84.90%
1374
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
1375
+ // โœ… All coverage metrics meet 80% threshold
1376
+ ```
1377
+
1378
+ **What it does:**
1379
+ - Identifies test files for modified implementation files
1380
+ - Runs Jest with coverage for those specific tests
1381
+ - Reports coverage metrics with threshold comparison
1382
+ - Highlights gaps needing additional tests
1383
+
1384
+ ### The Complete Optimized Experience
1385
+
1386
+ **Feature planning:**
1387
+ ```
1388
+ You: "Add login feature"
1389
+ Claude: "Writing scenarios..."
1390
+ โœ… Scenarios validated (dry-run: 10 seconds)
1391
+ โœ… Test files scaffolded
1392
+ ```
1393
+
1394
+ **Speed mode (optimized):**
1395
+ ```
1396
+ ๐Ÿ”„ Iteration 1: Implementing first step...
1397
+ ๐Ÿงช Running happy path scenario... 15 seconds
1398
+ ๐Ÿ“Š 1 of 3 steps passing
1399
+
1400
+ ๐Ÿ”„ Iteration 2: Implementing auth logic...
1401
+ ๐Ÿงช Running happy path scenario... 12 seconds
1402
+ ๐Ÿ“Š 2 of 3 steps passing
1403
+
1404
+ ๐Ÿ”„ Iteration 3: Adding redirect...
1405
+ ๐Ÿงช Running happy path scenario... 10 seconds
1406
+ โœ… Happy path passes!
1407
+
1408
+ ๐Ÿ” Running full verification... 45 seconds
1409
+ โœ… All scenarios passing
1410
+
1411
+ ๐Ÿ“ Generating unit tests... 5 seconds
1412
+ โœ… Generated tests for 4 functions
1413
+
1414
+ Total time: ~1.5 minutes (vs 15-30 minutes before)
1415
+ ```
1416
+
1417
+ **Stable mode (optimized):**
1418
+ ```
1419
+ ๐Ÿ”„ Iteration 1: Adding error handling...
1420
+ ๐Ÿงช Running error scenario... 18 seconds
1421
+ ๐Ÿ“Š Target scenario passing
1422
+
1423
+ ๐Ÿ” Running full verification... 45 seconds
1424
+ โœ… All scenarios still passing (no regressions)
1425
+
1426
+ ๐Ÿ“Š Running coverage... 10 seconds
1427
+ โœ… 85% coverage
1428
+
1429
+ Total time per chore: ~1.2 minutes
1430
+ ```
1431
+
1432
+ **Git commit (optimized):**
1433
+ ```
1434
+ git commit -m "feat: Add login validation"
1435
+
1436
+ ๐Ÿงช Pre-commit: Speed mode context detected
1437
+ Running happy path scenario... 12 seconds
1438
+ โœ… Tests pass
1439
+
1440
+ โœ… Commit allowed
1441
+ ```
1442
+
1443
+ ---
1444
+
1445
+ ## Configuration: Test Strategy Settings
1446
+
1447
+ ### .jettypod/test-config.json
1448
+
1449
+ ```json
1450
+ {
1451
+ "coverage": {
1452
+ "target": 100,
1453
+ "enforce": true,
1454
+ "excludePatterns": [
1455
+ "**/node_modules/**",
1456
+ "**/test/**",
1457
+ "**/*.test.js",
1458
+ "**/*.spec.js"
1459
+ ]
1460
+ },
1461
+
1462
+ "testing": {
1463
+ "framework": {
1464
+ "bdd": "cucumber",
1465
+ "unit": "jest"
1466
+ },
1467
+
1468
+ "runOn": {
1469
+ "featurePlanning": "dry-run",
1470
+ "speedMode": "continuous",
1471
+ "stableMode": "continuous",
1472
+ "productionMode": "comprehensive"
1473
+ },
1474
+
1475
+ "gitHooks": {
1476
+ "preCommit": {
1477
+ "enabled": true,
1478
+ "runTests": true,
1479
+ "contextAware": true
1480
+ },
1481
+ "prePush": {
1482
+ "enabled": true,
1483
+ "runTests": true,
1484
+ "requirePassing": true
1485
+ }
1486
+ }
1487
+ },
1488
+
1489
+ "documentation": {
1490
+ "testsAreDocumentation": true,
1491
+ "generateMarkdownDocs": true,
1492
+ "autoUpdateOnTest": true
1493
+ },
1494
+
1495
+ "ai": {
1496
+ "readTestsForContext": true,
1497
+ "generateTestsFromScenarios": true,
1498
+ "suggestMissingTests": true
1499
+ }
1500
+ }
1501
+ ```
1502
+
1503
+ ---
1504
+
1505
+ ## Summary: Testing for Non-Engineers
1506
+
1507
+ ### The JettyPod Testing Philosophy
1508
+
1509
+ **1. Tests = Documentation**
1510
+ - No separate docs needed
1511
+ - Tests explain how everything works
1512
+ - AI reads tests to understand system
1513
+ - Users read BDD scenarios to understand features
1514
+
1515
+ **2. 100% Coverage Goal**
1516
+ - Every function documented via unit tests
1517
+ - Every workflow documented via BDD scenarios
1518
+ - Every error case explained via tests
1519
+ - No undocumented behavior
1520
+
1521
+ **3. JettyPod Facilitates Everything**
1522
+ - Auto-generates test infrastructure
1523
+ - Guides scenario writing (plain English)
1524
+ - Runs tests continuously during implementation
1525
+ - Tracks coverage and identifies gaps
1526
+ - Generates documentation from tests
1527
+
1528
+ **4. User Experience**
1529
+ - Write scenarios in plain English
1530
+ - AI implements with TDD
1531
+ - Tests run automatically
1532
+ - Coverage tracked automatically
1533
+ - Documentation generated automatically
1534
+
1535
+ ### What Users See
1536
+
1537
+ **Feature planning:**
1538
+ ```
1539
+ You: "Add login"
1540
+ JettyPod: "Let's write scenarios..."
1541
+ [Collaborative scenario writing]
1542
+ โœ… Scenarios created (your documentation)
1543
+ ```
1544
+
1545
+ **Speed mode:**
1546
+ ```
1547
+ You: "Implement login"
1548
+ JettyPod: "Implementing with tests..."
1549
+ [TDD implementation with progress]
1550
+ โœ… Happy path works (tests show how)
1551
+ ```
1552
+
1553
+ **Stable mode:**
1554
+ ```
1555
+ You: "Add error handling"
1556
+ JettyPod: "Adding error scenarios..."
1557
+ [Error cases + tests]
1558
+ โœ… All cases handled (tests document errors)
1559
+ ```
1560
+
1561
+ **Production mode:**
1562
+ ```
1563
+ You: "Make it production-ready"
1564
+ JettyPod: "Adding security/performance..."
1565
+ [Production hardening + tests]
1566
+ โœ… Production-ready (tests prove it)
1567
+ ```
1568
+
1569
+ ### The Result
1570
+
1571
+ **For users:**
1572
+ - Features explained in plain English (BDD scenarios)
1573
+ - No need to understand code
1574
+ - Clear documentation of what works and what doesn't
1575
+
1576
+ **For AI assistants:**
1577
+ - Complete understanding of system (unit tests)
1578
+ - All edge cases documented (test cases)
1579
+ - Implementation patterns clear (step definitions)
1580
+
1581
+ **For future developers:**
1582
+ - Onboard by reading tests
1583
+ - Understand behavior from scenarios
1584
+ - See examples of every pattern
1585
+
1586
+ **100% coverage = Complete documentation of the system**
1587
+
1588
+ This is the JettyPod way: Tests aren't overhead, they're the deliverable.