jettypod 4.4.115 → 4.4.118
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 +25 -9
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +7 -3
- 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/connect-claude/page.tsx +24 -0
- package/apps/dashboard/app/install-claude/page.tsx +8 -6
- package/apps/dashboard/app/login/page.tsx +229 -0
- package/apps/dashboard/app/page.tsx +5 -3
- package/apps/dashboard/app/settings/page.tsx +2 -0
- package/apps/dashboard/app/subscribe/page.tsx +11 -0
- package/apps/dashboard/app/welcome/page.tsx +23 -0
- package/apps/dashboard/components/AppShell.tsx +51 -9
- package/apps/dashboard/components/CardMenu.tsx +14 -5
- package/apps/dashboard/components/ClaudePanel.tsx +65 -9
- package/apps/dashboard/components/ConnectClaudeScreen.tsx +223 -0
- package/apps/dashboard/components/DragContext.tsx +73 -64
- package/apps/dashboard/components/DraggableCard.tsx +6 -46
- package/apps/dashboard/components/GateCard.tsx +21 -0
- package/apps/dashboard/components/InstallClaudeScreen.tsx +132 -30
- package/apps/dashboard/components/KanbanBoard.tsx +173 -56
- package/apps/dashboard/components/PlaceholderCard.tsx +9 -19
- package/apps/dashboard/components/ProjectSwitcher.tsx +28 -0
- package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +34 -3
- package/apps/dashboard/components/RealTimeTestsWrapper.tsx +30 -2
- package/apps/dashboard/components/SubscribeContent.tsx +191 -0
- package/apps/dashboard/components/TipCard.tsx +176 -0
- package/apps/dashboard/components/UpgradeBanner.tsx +29 -0
- package/apps/dashboard/components/WelcomeScreen.tsx +14 -4
- package/apps/dashboard/components/settings/AccountSection.tsx +163 -0
- package/apps/dashboard/contexts/ClaudeSessionContext.tsx +292 -29
- package/apps/dashboard/contexts/UsageContext.tsx +131 -0
- package/apps/dashboard/contexts/usageHelpers.js +9 -0
- package/apps/dashboard/electron/ipc-handlers.js +220 -114
- package/apps/dashboard/electron/main.js +415 -37
- package/apps/dashboard/electron/preload.js +23 -4
- package/apps/dashboard/electron/session-manager.js +141 -0
- package/apps/dashboard/electron-builder.config.js +3 -5
- package/apps/dashboard/lib/claude-process-manager.ts +6 -4
- package/apps/dashboard/lib/db-bridge.ts +32 -0
- package/apps/dashboard/lib/db.ts +159 -13
- package/apps/dashboard/lib/session-state-machine.ts +3 -0
- package/apps/dashboard/lib/session-stream-manager.ts +76 -13
- package/apps/dashboard/lib/tests.ts +3 -1
- package/apps/dashboard/next.config.js +19 -14
- package/apps/dashboard/package.json +3 -1
- package/apps/dashboard/scripts/upload-to-r2.js +89 -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 +1074 -0
- package/apps/update-server/tsconfig.json +16 -0
- package/apps/update-server/wrangler.toml +35 -0
- package/docs/bdd-guidance.md +390 -0
- package/jettypod.js +5 -4
- package/lib/migrations/027-plan-at-creation-column.js +31 -0
- package/lib/migrations/028-ready-for-review-column.js +27 -0
- package/lib/schema.js +3 -1
- package/lib/seed-onboarding.js +100 -68
- package/lib/work-commands/index.js +43 -13
- package/lib/work-tracking/index.js +46 -27
- package/package.json +1 -1
- package/skills-templates/bug-mode/SKILL.md +5 -11
- package/skills-templates/request-routing/SKILL.md +24 -11
- package/skills-templates/simple-improvement/SKILL.md +35 -19
- package/skills-templates/stable-mode/SKILL.md +5 -6
- 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
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"lib": ["ESNext"],
|
|
7
|
+
"types": ["@cloudflare/workers-types"],
|
|
8
|
+
"strict": true,
|
|
9
|
+
"noEmit": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src/**/*.ts"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name = "jettypod-update-server"
|
|
2
|
+
main = "src/index.ts"
|
|
3
|
+
compatibility_date = "2025-02-01"
|
|
4
|
+
|
|
5
|
+
# R2 bucket for release artifacts (DMG, ZIP, latest-mac.yml)
|
|
6
|
+
[[r2_buckets]]
|
|
7
|
+
binding = "RELEASE_ARTIFACTS"
|
|
8
|
+
bucket_name = "jettypod-releases"
|
|
9
|
+
|
|
10
|
+
# D1 database for user accounts + usage tracking
|
|
11
|
+
[[d1_databases]]
|
|
12
|
+
binding = "AUTH_DB"
|
|
13
|
+
database_name = "jettypod-auth"
|
|
14
|
+
database_id = "80205398-8f56-4e04-a612-4a348458098f"
|
|
15
|
+
|
|
16
|
+
# KV namespace for OTP codes (with TTL)
|
|
17
|
+
[[kv_namespaces]]
|
|
18
|
+
binding = "AUTH_KV"
|
|
19
|
+
id = "91b43f72715e4c26a15b1dc0371af225"
|
|
20
|
+
|
|
21
|
+
# Stripe secrets - set via wrangler:
|
|
22
|
+
# wrangler secret put STRIPE_SECRET_KEY
|
|
23
|
+
# wrangler secret put STRIPE_WEBHOOK_SECRET
|
|
24
|
+
# wrangler secret put STRIPE_MONTHLY_PRICE_ID
|
|
25
|
+
# wrangler secret put STRIPE_LIFETIME_PRICE_ID
|
|
26
|
+
# Auth secrets - set via wrangler:
|
|
27
|
+
# wrangler secret put GOOGLE_CLIENT_ID
|
|
28
|
+
# wrangler secret put GOOGLE_CLIENT_SECRET
|
|
29
|
+
# wrangler secret put JWT_SECRET
|
|
30
|
+
# wrangler secret put RESEND_API_KEY
|
|
31
|
+
# Do NOT put actual keys here. Use wrangler secrets for sensitive values.
|
|
32
|
+
|
|
33
|
+
# Environment variables (non-secret)
|
|
34
|
+
[vars]
|
|
35
|
+
ENVIRONMENT = "production"
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
What BDD actually is (and isn’t)
|
|
2
|
+
|
|
3
|
+
BDD is a collaboration + specification technique that uses concrete examples to describe behavior in a shared language.
|
|
4
|
+
|
|
5
|
+
The “unit tests” are not the point. The examples are the point.
|
|
6
|
+
|
|
7
|
+
BDD tests should validate behavior that matters to users/business—without leaking implementation details.
|
|
8
|
+
|
|
9
|
+
BDD ≠ “write all tests in Gherkin.” BDD can be done with plain unit/integration tests too. Gherkin is just a common interface for readability and stakeholder alignment.
|
|
10
|
+
|
|
11
|
+
A good mental model:
|
|
12
|
+
|
|
13
|
+
Feature files describe “what” and “why.”
|
|
14
|
+
|
|
15
|
+
Step definitions implement “how,” but only at a high level.
|
|
16
|
+
|
|
17
|
+
Lower-level details live in helper layers (Page Objects, API clients, domain helpers).
|
|
18
|
+
|
|
19
|
+
The BDD flow (what “good” looks like)
|
|
20
|
+
|
|
21
|
+
Discovery (3 Amigos: product + dev + QA)
|
|
22
|
+
|
|
23
|
+
Agree on behavior via examples: happy path + edge cases.
|
|
24
|
+
|
|
25
|
+
Formulation
|
|
26
|
+
|
|
27
|
+
Turn examples into scenarios (often in Gherkin).
|
|
28
|
+
|
|
29
|
+
Automation
|
|
30
|
+
|
|
31
|
+
Implement step definitions that call into a small, reusable automation layer.
|
|
32
|
+
|
|
33
|
+
Living documentation
|
|
34
|
+
|
|
35
|
+
Keep scenarios accurate and stable; prune duplicates; version behavior over time.
|
|
36
|
+
|
|
37
|
+
Gherkin, done well (the style rules that save you later)
|
|
38
|
+
Core primitives
|
|
39
|
+
|
|
40
|
+
Feature: coherent behavior area
|
|
41
|
+
|
|
42
|
+
Scenario: one concrete example
|
|
43
|
+
|
|
44
|
+
Given/When/Then:
|
|
45
|
+
|
|
46
|
+
Given: preconditions / state
|
|
47
|
+
|
|
48
|
+
When: action
|
|
49
|
+
|
|
50
|
+
Then: observable outcomes
|
|
51
|
+
|
|
52
|
+
Good scenario traits
|
|
53
|
+
|
|
54
|
+
Small: one behavior, one reason to fail
|
|
55
|
+
|
|
56
|
+
Declarative: describes intent, not UI clicks
|
|
57
|
+
|
|
58
|
+
Stable: avoids brittle details (pixel-level UI, timing hacks)
|
|
59
|
+
|
|
60
|
+
Deterministic: no reliance on “whatever data happens to exist”
|
|
61
|
+
|
|
62
|
+
Example (good)
|
|
63
|
+
Scenario: User can retry a failed payment
|
|
64
|
+
Given a user with an unpaid invoice
|
|
65
|
+
And the payment processor returns "insufficient_funds"
|
|
66
|
+
When the user retries payment with a different card
|
|
67
|
+
Then the invoice is marked as paid
|
|
68
|
+
And the user sees a receipt
|
|
69
|
+
|
|
70
|
+
Example (brittle / not great)
|
|
71
|
+
Scenario: Pay invoice
|
|
72
|
+
Given I click the "Billing" tab
|
|
73
|
+
And I wait 2 seconds
|
|
74
|
+
And I click the third button on the page
|
|
75
|
+
When I type "4111111111111111" into the card field
|
|
76
|
+
Then I should see "Success"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
This is more of a UI macro recorder than a behavioral spec.
|
|
80
|
+
|
|
81
|
+
Step definitions: the most common place things go off the rails
|
|
82
|
+
The biggest rule
|
|
83
|
+
|
|
84
|
+
Step definitions should be thin.
|
|
85
|
+
They should:
|
|
86
|
+
|
|
87
|
+
parse parameters
|
|
88
|
+
|
|
89
|
+
call a helper/API/page-object method
|
|
90
|
+
|
|
91
|
+
assert outcomes at the correct level
|
|
92
|
+
|
|
93
|
+
They should not:
|
|
94
|
+
|
|
95
|
+
contain lots of branching logic
|
|
96
|
+
|
|
97
|
+
do complex loops
|
|
98
|
+
|
|
99
|
+
embed SQL queries
|
|
100
|
+
|
|
101
|
+
“know” too much about UI selectors
|
|
102
|
+
|
|
103
|
+
implement multi-step workflows inline
|
|
104
|
+
|
|
105
|
+
The “thin step” pattern
|
|
106
|
+
|
|
107
|
+
Step def → calls one intentful function (e.g., billing.retryPaymentWith(card)), rather than doing click/type/wait directly.
|
|
108
|
+
|
|
109
|
+
Example structure:
|
|
110
|
+
|
|
111
|
+
// step definition
|
|
112
|
+
When('the user retries payment with a different card', async () => {
|
|
113
|
+
await billing.retryPaymentWith(validCard2);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// helper layer (page object / service client)
|
|
117
|
+
async function retryPaymentWith(card) {
|
|
118
|
+
await openBilling();
|
|
119
|
+
await selectInvoice(...);
|
|
120
|
+
await enterCard(card);
|
|
121
|
+
await submit();
|
|
122
|
+
await waitForReceipt(); // smart wait, not sleep(2000)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Handling “complex things” in BDD tests (the hard parts)
|
|
126
|
+
1) Asynchrony and eventual consistency
|
|
127
|
+
|
|
128
|
+
Problem: background jobs, queues, delayed writes, distributed systems.
|
|
129
|
+
|
|
130
|
+
Best practices
|
|
131
|
+
|
|
132
|
+
Prefer event-based or state-based polling with timeouts over fixed sleeps.
|
|
133
|
+
|
|
134
|
+
Assert intermediate states if meaningful (“processing” → “completed”).
|
|
135
|
+
|
|
136
|
+
If possible, expose a test-only hook (e.g., “job runner runs immediately” in test env).
|
|
137
|
+
|
|
138
|
+
What to do:
|
|
139
|
+
|
|
140
|
+
await waitFor(() => order.status === 'COMPLETED', { timeout: 10_000 })
|
|
141
|
+
|
|
142
|
+
avoid: sleep(5000)
|
|
143
|
+
|
|
144
|
+
2) External dependencies (payment providers, email/SMS, maps)
|
|
145
|
+
|
|
146
|
+
Problem: flaky tests, slow runs, rate limits.
|
|
147
|
+
|
|
148
|
+
Best practices
|
|
149
|
+
|
|
150
|
+
For most BDD runs: stub at the boundary (in-process fake server, contract stub).
|
|
151
|
+
|
|
152
|
+
Have a smaller set of true end-to-end smoke tests that hit real external services (maybe nightly).
|
|
153
|
+
|
|
154
|
+
3) Authentication flows (OAuth, magic links)
|
|
155
|
+
|
|
156
|
+
Best practices
|
|
157
|
+
|
|
158
|
+
Prefer test auth shortcuts:
|
|
159
|
+
|
|
160
|
+
a test-only endpoint to mint tokens
|
|
161
|
+
|
|
162
|
+
bypass UI login with session injection
|
|
163
|
+
|
|
164
|
+
Keep one or two UI-login scenarios if you must, but don’t make every scenario pay the “login tax.”
|
|
165
|
+
|
|
166
|
+
4) Data setup that is “realistic” but not fragile
|
|
167
|
+
|
|
168
|
+
Problem: complicated prerequisites create scenario bloat.
|
|
169
|
+
|
|
170
|
+
Best practices
|
|
171
|
+
|
|
172
|
+
Use factories/fixtures with names that encode intent:
|
|
173
|
+
|
|
174
|
+
givenUserWithUnpaidInvoice()
|
|
175
|
+
|
|
176
|
+
givenWorkspaceWith3MembersAndNoAdmin()
|
|
177
|
+
|
|
178
|
+
Avoid “Given the database has…” in feature files. That’s implementation leakage.
|
|
179
|
+
|
|
180
|
+
5) Time, randomness, and IDs
|
|
181
|
+
|
|
182
|
+
Best practices
|
|
183
|
+
|
|
184
|
+
Freeze time (clock.set("2026-02-10T10:00:00Z")) or inject time providers.
|
|
185
|
+
|
|
186
|
+
Seed randomness.
|
|
187
|
+
|
|
188
|
+
Don’t assert on raw IDs; assert on meaning (“receipt exists”, “email sent to user”).
|
|
189
|
+
|
|
190
|
+
6) UI interactions that are inherently finicky
|
|
191
|
+
|
|
192
|
+
Best practices
|
|
193
|
+
|
|
194
|
+
Use stable locators (data-testid, ARIA roles) rather than CSS chains.
|
|
195
|
+
|
|
196
|
+
Use smart waits (element visible/enabled, network idle) not sleeps.
|
|
197
|
+
|
|
198
|
+
Put selectors in one place (page objects / screen model).
|
|
199
|
+
|
|
200
|
+
7) Distributed workflows (webhook in, job runs, UI updates)
|
|
201
|
+
|
|
202
|
+
Best practices
|
|
203
|
+
|
|
204
|
+
Split assertions by layer:
|
|
205
|
+
|
|
206
|
+
API-level scenario verifies webhook → status update
|
|
207
|
+
|
|
208
|
+
UI-level scenario verifies status display
|
|
209
|
+
|
|
210
|
+
Don’t force one scenario to validate every link in the chain unless it’s explicitly a top-level acceptance test.
|
|
211
|
+
|
|
212
|
+
The test pyramid in BDD terms (where each kind of test belongs)
|
|
213
|
+
|
|
214
|
+
A very effective setup:
|
|
215
|
+
|
|
216
|
+
Many unit tests (fast, deterministic): pure logic
|
|
217
|
+
|
|
218
|
+
Many integration/contract tests: service boundaries, DB, message bus (still fast-ish)
|
|
219
|
+
|
|
220
|
+
Some BDD scenarios: critical user journeys and key edge cases
|
|
221
|
+
|
|
222
|
+
Very few UI E2E: smoke and “are we totally broken?” checks
|
|
223
|
+
|
|
224
|
+
BDD scenarios can exist at multiple levels (API-level BDD is often a sweet spot).
|
|
225
|
+
|
|
226
|
+
Mocks, stubs, fakes: what they are (and why people argue about them)
|
|
227
|
+
Definitions (practical, not academic)
|
|
228
|
+
|
|
229
|
+
Mock: a test double you can verify interactions with
|
|
230
|
+
(“Was chargeCard() called with amount=4999?”)
|
|
231
|
+
|
|
232
|
+
Stub: a test double that returns predetermined responses
|
|
233
|
+
(“When /payments is called, return 402 insufficient_funds”)
|
|
234
|
+
|
|
235
|
+
Fake: a lightweight working implementation
|
|
236
|
+
(in-memory DB, fake email inbox, fake queue)
|
|
237
|
+
|
|
238
|
+
Spy: like a mock, but wraps a real object and records calls
|
|
239
|
+
|
|
240
|
+
When to use what
|
|
241
|
+
|
|
242
|
+
Use stubs/fakes for most BDD scenarios because they support behavior assertions (“user sees receipt”) without coupling to call patterns.
|
|
243
|
+
|
|
244
|
+
Use mocks sparingly, mostly in unit tests or when verifying a critical side effect is the purpose of the scenario.
|
|
245
|
+
|
|
246
|
+
The big danger of mocks in BDD
|
|
247
|
+
|
|
248
|
+
Mocks push you toward testing implementation details:
|
|
249
|
+
|
|
250
|
+
“did we call X?” rather than “did the user get the outcome?”
|
|
251
|
+
|
|
252
|
+
Sometimes verifying calls is legitimate (e.g., “audit event emitted”), but generally:
|
|
253
|
+
|
|
254
|
+
BDD asserts outcomes, not internal choreography.
|
|
255
|
+
|
|
256
|
+
Step definition best practices checklist (great for “is my AI behaving?”)
|
|
257
|
+
✅ Green flags
|
|
258
|
+
|
|
259
|
+
Steps are short (often 1–5 lines)
|
|
260
|
+
|
|
261
|
+
Steps call named helper methods (domain language)
|
|
262
|
+
|
|
263
|
+
Assertions are in Then steps (or helper assertions)
|
|
264
|
+
|
|
265
|
+
Givens set up intentful state, not low-level DB edits
|
|
266
|
+
|
|
267
|
+
Reuse happens through helper methods, not giant shared step defs
|
|
268
|
+
|
|
269
|
+
Steps avoid sleeps; use smart waits
|
|
270
|
+
|
|
271
|
+
Scenario language avoids UI specifics unless truly necessary
|
|
272
|
+
|
|
273
|
+
🚩 Red flags (AI assistants love these)
|
|
274
|
+
|
|
275
|
+
Step defs contain:
|
|
276
|
+
|
|
277
|
+
loops, conditionals, try/catch gymnastics
|
|
278
|
+
|
|
279
|
+
direct SQL / direct ORM writes sprinkled everywhere
|
|
280
|
+
|
|
281
|
+
lots of selectors + click/type chains inline
|
|
282
|
+
|
|
283
|
+
random sleeps/timeouts to “make it pass”
|
|
284
|
+
|
|
285
|
+
Steps are overly generic:
|
|
286
|
+
|
|
287
|
+
“When I do the thing”
|
|
288
|
+
|
|
289
|
+
“Then it works”
|
|
290
|
+
|
|
291
|
+
Heavy parameterization:
|
|
292
|
+
|
|
293
|
+
Steps with 6–10 parameters usually mean you’re encoding a DSL no one can read
|
|
294
|
+
|
|
295
|
+
Shared state is global and leaky across scenarios
|
|
296
|
+
|
|
297
|
+
One scenario validates 12 different outcomes (“kitchen sink test”)
|
|
298
|
+
|
|
299
|
+
A strict architecture that keeps BDD clean
|
|
300
|
+
|
|
301
|
+
If you want your AI to stay disciplined, give it a structure it can’t easily “freestyle” out of:
|
|
302
|
+
|
|
303
|
+
Recommended layers
|
|
304
|
+
|
|
305
|
+
Feature files (behavior)
|
|
306
|
+
|
|
307
|
+
Step definitions (glue)
|
|
308
|
+
|
|
309
|
+
Domain tasks / Screenplay actions (intentful operations)
|
|
310
|
+
|
|
311
|
+
Drivers
|
|
312
|
+
|
|
313
|
+
UI driver (page objects / screen model)
|
|
314
|
+
|
|
315
|
+
API client
|
|
316
|
+
|
|
317
|
+
DB helper (sparingly)
|
|
318
|
+
|
|
319
|
+
Message bus helper
|
|
320
|
+
|
|
321
|
+
Test fixtures/factories
|
|
322
|
+
|
|
323
|
+
Rule of thumb:
|
|
324
|
+
|
|
325
|
+
Step defs may depend on domain tasks
|
|
326
|
+
|
|
327
|
+
Domain tasks may depend on drivers
|
|
328
|
+
|
|
329
|
+
Feature files know nothing about drivers
|
|
330
|
+
|
|
331
|
+
This prevents selector soup from infecting Gherkin.
|
|
332
|
+
|
|
333
|
+
Making your AI assistant “strict” (practical constraints you can enforce)
|
|
334
|
+
|
|
335
|
+
Here are concrete constraints you can put in your prompt / code review rubric:
|
|
336
|
+
|
|
337
|
+
Step definition max complexity
|
|
338
|
+
|
|
339
|
+
No loops
|
|
340
|
+
|
|
341
|
+
No conditionals except trivial parameter mapping
|
|
342
|
+
|
|
343
|
+
No sleeps
|
|
344
|
+
|
|
345
|
+
Selectors forbidden in steps
|
|
346
|
+
|
|
347
|
+
Must live in page objects/screen models only
|
|
348
|
+
|
|
349
|
+
One intentful call per step
|
|
350
|
+
|
|
351
|
+
Steps call one task method
|
|
352
|
+
|
|
353
|
+
Outcome assertions only in Then
|
|
354
|
+
|
|
355
|
+
No shared global mutable state
|
|
356
|
+
|
|
357
|
+
Use scenario context object only
|
|
358
|
+
|
|
359
|
+
Deterministic data
|
|
360
|
+
|
|
361
|
+
Factories generate known entities; tests never depend on prod-like ambient data
|
|
362
|
+
|
|
363
|
+
If you tell the AI “follow best practices,” it’ll nod vigorously and then sleep(2000) anyway. If you tell it “sleep is banned,” it suddenly remembers how to wait for elements like an adult.
|
|
364
|
+
|
|
365
|
+
Quick example: translating complex behavior into clean steps
|
|
366
|
+
|
|
367
|
+
Complex behavior: “User triggers export; job runs async; user is notified; file is downloadable.”
|
|
368
|
+
|
|
369
|
+
Good BDD split:
|
|
370
|
+
|
|
371
|
+
Scenario asserts user-level behavior
|
|
372
|
+
|
|
373
|
+
Implementation uses polling and test doubles
|
|
374
|
+
|
|
375
|
+
Scenario: User can download a completed export
|
|
376
|
+
Given a user with 3 projects
|
|
377
|
+
When the user requests a project export
|
|
378
|
+
Then the export eventually completes
|
|
379
|
+
And the user can download the export file
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
Implementation strategy:
|
|
383
|
+
|
|
384
|
+
request export calls API
|
|
385
|
+
|
|
386
|
+
eventually completes polls status endpoint with timeout
|
|
387
|
+
|
|
388
|
+
can download checks signed URL returns 200 and file has expected headers
|
|
389
|
+
|
|
390
|
+
No sleeps, no digging into job queue internals (unless you’re specifically testing that).
|
package/jettypod.js
CHANGED
|
@@ -877,6 +877,11 @@ async function initializeProject() {
|
|
|
877
877
|
}
|
|
878
878
|
});
|
|
879
879
|
if (result) {
|
|
880
|
+
// Mark onboarding chores as conversational (no worktree, no 5s delay)
|
|
881
|
+
const db = getDb();
|
|
882
|
+
for (const choreId of result.choreIds) {
|
|
883
|
+
db.run('UPDATE work_items SET conversational = 1 WHERE id = ?', [choreId]);
|
|
884
|
+
}
|
|
880
885
|
console.log(`📋 Created onboarding epic with ${result.choreIds.length} chores`);
|
|
881
886
|
console.log(` Start with: jettypod work start ${result.choreIds[0]}`);
|
|
882
887
|
}
|
|
@@ -2200,10 +2205,6 @@ switch (command) {
|
|
|
2200
2205
|
}
|
|
2201
2206
|
});
|
|
2202
2207
|
|
|
2203
|
-
// Clear checkpoint
|
|
2204
|
-
const checkpoint = require('./lib/discovery-checkpoint');
|
|
2205
|
-
checkpoint.clearCheckpoint();
|
|
2206
|
-
|
|
2207
2208
|
await generateClaude({ autoCommit: true });
|
|
2208
2209
|
|
|
2209
2210
|
console.log('✅ Project discovery complete!');
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: Add plan_at_creation column to work_items
|
|
3
|
+
*
|
|
4
|
+
* Purpose: Track which plan the user was on when creating each work item.
|
|
5
|
+
* Used for local usage tracking — only work items created on the 'free'
|
|
6
|
+
* plan count toward the weekly limit.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
id: '027-plan-at-creation-column',
|
|
11
|
+
description: 'Add plan_at_creation column to work_items',
|
|
12
|
+
|
|
13
|
+
async up(db) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
db.run(`ALTER TABLE work_items ADD COLUMN plan_at_creation TEXT DEFAULT NULL`, (err) => {
|
|
16
|
+
if (err) return reject(err);
|
|
17
|
+
// Backfill existing work items — assume free plan for all existing items
|
|
18
|
+
db.run(`UPDATE work_items SET plan_at_creation = 'free' WHERE plan_at_creation IS NULL`, (err2) => {
|
|
19
|
+
if (err2) return reject(err2);
|
|
20
|
+
resolve();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
async down(db) {
|
|
27
|
+
// SQLite doesn't support DROP COLUMN before 3.35.0
|
|
28
|
+
// Column will just be ignored if not used
|
|
29
|
+
return Promise.resolve();
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration: Add ready_for_review column to work_items
|
|
3
|
+
*
|
|
4
|
+
* Purpose: Gate accept/reject button visibility on kanban cards.
|
|
5
|
+
* When ready_for_review = 1, the card shows accept/reject buttons.
|
|
6
|
+
* Auto-set when all child chores complete; cleared on rejection.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
id: '028-ready-for-review-column',
|
|
11
|
+
description: 'Add ready_for_review column to work_items',
|
|
12
|
+
|
|
13
|
+
async up(db) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
db.run(`ALTER TABLE work_items ADD COLUMN ready_for_review INTEGER DEFAULT 0`, (err) => {
|
|
16
|
+
if (err) return reject(err);
|
|
17
|
+
resolve();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
async down(db) {
|
|
23
|
+
// SQLite doesn't support DROP COLUMN before 3.35.0
|
|
24
|
+
// Column will just be ignored if not used
|
|
25
|
+
return Promise.resolve();
|
|
26
|
+
}
|
|
27
|
+
};
|
package/lib/schema.js
CHANGED
|
@@ -30,7 +30,9 @@ const SCHEMA_SQL = `
|
|
|
30
30
|
scenario_file TEXT,
|
|
31
31
|
completed_at TEXT,
|
|
32
32
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
33
|
-
display_order INTEGER DEFAULT NULL
|
|
33
|
+
display_order INTEGER DEFAULT NULL,
|
|
34
|
+
conversational INTEGER DEFAULT 0,
|
|
35
|
+
plan_at_creation TEXT DEFAULT NULL
|
|
34
36
|
);
|
|
35
37
|
|
|
36
38
|
CREATE TABLE IF NOT EXISTS project_config (
|