joycraft 0.3.1 → 0.5.1

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.
@@ -1,1129 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/bundled-files.ts
4
- var SKILLS = {
5
- "decompose.md": `---
6
- name: decompose
7
- description: Break a feature brief into atomic specs \u2014 small, testable, independently executable units
8
- ---
9
-
10
- # Decompose Feature into Atomic Specs
11
-
12
- You have a Feature Brief (or the user has described a feature). Your job is to decompose it into atomic specs that can be executed independently \u2014 one spec per session.
13
-
14
- ## Step 1: Verify the Brief Exists
15
-
16
- Look for a Feature Brief in \`docs/briefs/\`. If one doesn't exist yet, tell the user:
17
-
18
- > No feature brief found. Run \`/new-feature\` first to interview and create one, or describe the feature now and I'll work from your description.
19
-
20
- If the user describes the feature inline, work from that description directly. You don't need a formal brief to decompose \u2014 but recommend creating one for complex features.
21
-
22
- ## Step 2: Identify Natural Boundaries
23
-
24
- **Why:** Good boundaries make specs independently testable and committable. Bad boundaries create specs that can't be verified without other specs also being done.
25
-
26
- Read the brief (or description) and identify natural split points:
27
-
28
- - **Data layer changes** (schemas, types, migrations) \u2014 always a separate spec
29
- - **Pure functions / business logic** \u2014 separate from I/O
30
- - **UI components** \u2014 separate from data fetching
31
- - **API endpoints / route handlers** \u2014 separate from business logic
32
- - **Test infrastructure** (mocks, fixtures, helpers) \u2014 can be its own spec if substantial
33
- - **Configuration / environment** \u2014 separate from code changes
34
-
35
- Ask yourself: "Can this piece be committed and tested without the other pieces existing?" If yes, it's a good boundary.
36
-
37
- ## Step 3: Build the Decomposition Table
38
-
39
- For each atomic spec, define:
40
-
41
- | # | Spec Name | Description | Dependencies | Size |
42
- |---|-----------|-------------|--------------|------|
43
-
44
- **Rules:**
45
- - Each spec name is \`verb-object\` format (e.g., \`add-terminal-detection\`, \`extract-prompt-module\`)
46
- - Each description is ONE sentence \u2014 if you need two, the spec is too big
47
- - Dependencies reference other spec numbers \u2014 keep the dependency graph shallow
48
- - More than 2 dependencies on a single spec = it's too big, split further
49
- - Aim for 3-7 specs per feature. Fewer than 3 = probably not decomposed enough. More than 10 = the feature brief is too big
50
-
51
- ## Step 4: Present and Iterate
52
-
53
- Show the decomposition table to the user. Ask:
54
- 1. "Does this breakdown match how you think about this feature?"
55
- 2. "Are there any specs that feel too big or too small?"
56
- 3. "Should any of these run in parallel (separate worktrees)?"
57
-
58
- Iterate until the user approves.
59
-
60
- ## Step 5: Generate Atomic Specs
61
-
62
- For each approved row, create \`docs/specs/YYYY-MM-DD-spec-name.md\`. Create the \`docs/specs/\` directory if it doesn't exist.
63
-
64
- **Why:** Each spec must be self-contained \u2014 a fresh Claude session should be able to execute it without reading the Feature Brief. Copy relevant constraints and context into each spec.
65
-
66
- Use this structure:
67
-
68
- \`\`\`markdown
69
- # [Verb + Object] \u2014 Atomic Spec
70
-
71
- > **Parent Brief:** \`docs/briefs/YYYY-MM-DD-feature-name.md\` (or "standalone")
72
- > **Status:** Ready
73
- > **Date:** YYYY-MM-DD
74
- > **Estimated scope:** [1 session / N files / ~N lines]
75
-
76
- ---
77
-
78
- ## What
79
- One paragraph \u2014 what changes when this spec is done?
80
-
81
- ## Why
82
- One sentence \u2014 what breaks or is missing without this?
83
-
84
- ## Acceptance Criteria
85
- - [ ] [Observable behavior]
86
- - [ ] Build passes
87
- - [ ] Tests pass
88
-
89
- ## Constraints
90
- - MUST: [hard requirement]
91
- - MUST NOT: [hard prohibition]
92
-
93
- ## Affected Files
94
- | Action | File | What Changes |
95
- |--------|------|-------------|
96
-
97
- ## Approach
98
- Strategy, data flow, key decisions. Name one rejected alternative.
99
-
100
- ## Edge Cases
101
- | Scenario | Expected Behavior |
102
- |----------|------------------|
103
- \`\`\`
104
-
105
- If \`docs/templates/ATOMIC_SPEC_TEMPLATE.md\` exists, reference it for the full template with additional guidance.
106
-
107
- Fill in all sections \u2014 each spec must be self-contained (no "see the brief for context"). Copy relevant constraints from the Feature Brief into each spec. Write acceptance criteria specific to THIS spec, not the whole feature.
108
-
109
- ## Step 6: Recommend Execution Strategy
110
-
111
- Based on the dependency graph:
112
- - **Independent specs** \u2014 "These can run in parallel worktrees"
113
- - **Sequential specs** \u2014 "Execute these in order: 1 -> 2 -> 4"
114
- - **Mixed** \u2014 "Start specs 1 and 3 in parallel. After 1 completes, start 2."
115
-
116
- Update the Feature Brief's Execution Strategy section with the plan (if a brief exists).
117
-
118
- ## Step 7: Hand Off
119
-
120
- Tell the user:
121
- \`\`\`
122
- Decomposition complete:
123
- - [N] atomic specs created in docs/specs/
124
- - [N] can run in parallel, [N] are sequential
125
- - Estimated total: [N] sessions
126
-
127
- To execute:
128
- - Sequential: Open a session, point Claude at each spec in order
129
- - Parallel: Use worktrees \u2014 one spec per worktree, merge when done
130
- - Each session should end with /session-end to capture discoveries
131
-
132
- Ready to start execution?
133
- \`\`\`
134
- `,
135
- "interview.md": `---
136
- name: interview
137
- description: Brainstorm freely about what you want to build \u2014 yap, explore ideas, and get a structured summary you can use later
138
- ---
139
-
140
- # Interview \u2014 Idea Exploration
141
-
142
- You are helping the user brainstorm and explore what they want to build. This is a lightweight, low-pressure conversation \u2014 not a formal spec process. Let them yap.
143
-
144
- ## How to Run the Interview
145
-
146
- ### 1. Open the Floor
147
-
148
- Start with something like:
149
- "What are you thinking about building? Just talk \u2014 I'll listen and ask questions as we go."
150
-
151
- Let the user talk freely. Do not interrupt their flow. Do not push toward structure yet.
152
-
153
- ### 2. Ask Clarifying Questions
154
-
155
- As they talk, weave in questions naturally \u2014 don't fire them all at once:
156
-
157
- - **What problem does this solve?** Who feels the pain today?
158
- - **What does "done" look like?** If this worked perfectly, what would a user see?
159
- - **What are the constraints?** Time, tech, team, budget \u2014 what boxes are we in?
160
- - **What's NOT in scope?** What's tempting but should be deferred?
161
- - **What are the edge cases?** What could go wrong? What's the weird input?
162
- - **What exists already?** Are we building on something or starting fresh?
163
-
164
- ### 3. Play Back Understanding
165
-
166
- After the user has gotten their ideas out, reflect back:
167
- "So if I'm hearing you right, you want to [summary]. The core problem is [X], and done looks like [Y]. Is that right?"
168
-
169
- Let them correct and refine. Iterate until they say "yes, that's it."
170
-
171
- ### 4. Write a Draft Brief
172
-
173
- Create a draft file at \`docs/briefs/YYYY-MM-DD-topic-draft.md\`. Create the \`docs/briefs/\` directory if it doesn't exist.
174
-
175
- Use this format:
176
-
177
- \`\`\`markdown
178
- # [Topic] \u2014 Draft Brief
179
-
180
- > **Date:** YYYY-MM-DD
181
- > **Status:** DRAFT
182
- > **Origin:** /interview session
183
-
184
- ---
185
-
186
- ## The Idea
187
- [2-3 paragraphs capturing what the user described \u2014 their words, their framing]
188
-
189
- ## Problem
190
- [What pain or gap this addresses]
191
-
192
- ## What "Done" Looks Like
193
- [The user's description of success \u2014 observable outcomes]
194
-
195
- ## Constraints
196
- - [constraint 1]
197
- - [constraint 2]
198
-
199
- ## Open Questions
200
- - [things that came up but weren't resolved]
201
- - [decisions that need more thought]
202
-
203
- ## Out of Scope (for now)
204
- - [things explicitly deferred]
205
-
206
- ## Raw Notes
207
- [Any additional context, quotes, or tangents worth preserving]
208
- \`\`\`
209
-
210
- ### 5. Hand Off
211
-
212
- After writing the draft, tell the user:
213
-
214
- \`\`\`
215
- Draft brief saved to docs/briefs/YYYY-MM-DD-topic-draft.md
216
-
217
- When you're ready to move forward:
218
- - /new-feature \u2014 formalize this into a full Feature Brief with specs
219
- - /decompose \u2014 break it directly into atomic specs if scope is clear
220
- - Or just keep brainstorming \u2014 run /interview again anytime
221
- \`\`\`
222
-
223
- ## Guidelines
224
-
225
- - **This is NOT /new-feature.** Do not push toward formal briefs, decomposition tables, or atomic specs. The point is exploration.
226
- - **Let the user lead.** Your job is to listen, clarify, and capture \u2014 not to structure or direct.
227
- - **Mark everything as DRAFT.** The output is a starting point, not a commitment.
228
- - **Keep it short.** The draft brief should be 1-2 pages max. Capture the essence, not every detail.
229
- - **Multiple interviews are fine.** The user might run this several times as their thinking evolves. Each creates a new dated draft.
230
- `,
231
- "new-feature.md": `---
232
- name: new-feature
233
- description: Guided feature development \u2014 interview the user, produce a Feature Brief, then decompose into atomic specs
234
- ---
235
-
236
- # New Feature Workflow
237
-
238
- You are starting a new feature. Follow this process in order. Do not skip steps.
239
-
240
- ## Phase 1: Interview
241
-
242
- Interview the user about what they want to build. Let them talk \u2014 your job is to listen, then sharpen.
243
-
244
- **Why:** A thorough interview prevents wasted implementation time. Most failed features fail because the problem wasn't understood, not because the code was wrong.
245
-
246
- **Ask about:**
247
- - What problem does this solve? Who is affected?
248
- - What does "done" look like? How will a user know this works?
249
- - What are the hard constraints? (business rules, tech limitations, deadlines)
250
- - What is explicitly NOT in scope? (push hard on this \u2014 aggressive scoping is key)
251
- - Are there edge cases or error conditions we need to handle?
252
- - What existing code/patterns should this follow?
253
-
254
- **Interview technique:**
255
- - Let the user "yap" \u2014 don't interrupt their flow of ideas
256
- - After they finish, play back your understanding: "So if I'm hearing you right..."
257
- - Ask clarifying questions that force specificity: "When you say 'handle errors,' what should the user see?"
258
- - Push toward testable statements: "How would we verify that works?"
259
-
260
- Keep asking until you can fill out a Feature Brief. When ready, say:
261
- "I have enough context. Let me write the Feature Brief for your review."
262
-
263
- ## Phase 2: Feature Brief
264
-
265
- Write a Feature Brief to \`docs/briefs/YYYY-MM-DD-feature-name.md\`. Create the \`docs/briefs/\` directory if it doesn't exist.
266
-
267
- **Why:** The brief is the single source of truth for what we're building. It prevents scope creep and gives every spec a shared reference point.
268
-
269
- Use this structure:
270
-
271
- \`\`\`markdown
272
- # [Feature Name] \u2014 Feature Brief
273
-
274
- > **Date:** YYYY-MM-DD
275
- > **Project:** [project name]
276
- > **Status:** Interview | Decomposing | Specs Ready | In Progress | Complete
277
-
278
- ---
279
-
280
- ## Vision
281
- What are we building and why? The full picture in 2-4 paragraphs.
282
-
283
- ## User Stories
284
- - As a [role], I want [capability] so that [benefit]
285
-
286
- ## Hard Constraints
287
- - MUST: [constraint that every spec must respect]
288
- - MUST NOT: [prohibition that every spec must respect]
289
-
290
- ## Out of Scope
291
- - NOT: [tempting but deferred]
292
-
293
- ## Decomposition
294
- | # | Spec Name | Description | Dependencies | Est. Size |
295
- |---|-----------|-------------|--------------|-----------|
296
- | 1 | [verb-object] | [one sentence] | None | [S/M/L] |
297
-
298
- ## Execution Strategy
299
- - [ ] Sequential (specs have chain dependencies)
300
- - [ ] Parallel worktrees (specs are independent)
301
- - [ ] Mixed
302
-
303
- ## Success Criteria
304
- - [ ] [End-to-end behavior 1]
305
- - [ ] [No regressions in existing features]
306
- \`\`\`
307
-
308
- If \`docs/templates/FEATURE_BRIEF_TEMPLATE.md\` exists, reference it for the full template with additional guidance.
309
-
310
- Present the brief to the user. Focus review on:
311
- - "Does the decomposition match how you think about this?"
312
- - "Is anything in scope that shouldn't be?"
313
- - "Are the specs small enough? Can each be described in one sentence?"
314
-
315
- Iterate until approved.
316
-
317
- ## Phase 3: Generate Atomic Specs
318
-
319
- For each row in the decomposition table, create a self-contained spec file at \`docs/specs/YYYY-MM-DD-spec-name.md\`. Create the \`docs/specs/\` directory if it doesn't exist.
320
-
321
- **Why:** Each spec must be understandable WITHOUT reading the Feature Brief. This prevents the "Curse of Instructions" \u2014 no spec should require holding the entire feature in context. Copy relevant context into each spec.
322
-
323
- Use this structure for each spec:
324
-
325
- \`\`\`markdown
326
- # [Verb + Object] \u2014 Atomic Spec
327
-
328
- > **Parent Brief:** \`docs/briefs/YYYY-MM-DD-feature-name.md\`
329
- > **Status:** Ready
330
- > **Date:** YYYY-MM-DD
331
- > **Estimated scope:** [1 session / N files / ~N lines]
332
-
333
- ---
334
-
335
- ## What
336
- One paragraph \u2014 what changes when this spec is done?
337
-
338
- ## Why
339
- One sentence \u2014 what breaks or is missing without this?
340
-
341
- ## Acceptance Criteria
342
- - [ ] [Observable behavior]
343
- - [ ] Build passes
344
- - [ ] Tests pass
345
-
346
- ## Constraints
347
- - MUST: [hard requirement]
348
- - MUST NOT: [hard prohibition]
349
-
350
- ## Affected Files
351
- | Action | File | What Changes |
352
- |--------|------|-------------|
353
-
354
- ## Approach
355
- Strategy, data flow, key decisions. Name one rejected alternative.
356
-
357
- ## Edge Cases
358
- | Scenario | Expected Behavior |
359
- |----------|------------------|
360
- \`\`\`
361
-
362
- If \`docs/templates/ATOMIC_SPEC_TEMPLATE.md\` exists, reference it for the full template with additional guidance.
363
-
364
- ## Phase 4: Hand Off for Execution
365
-
366
- Tell the user:
367
- \`\`\`
368
- Feature Brief and [N] atomic specs are ready.
369
-
370
- Specs:
371
- 1. [spec-name] \u2014 [one sentence] [S/M/L]
372
- 2. [spec-name] \u2014 [one sentence] [S/M/L]
373
- ...
374
-
375
- Recommended execution:
376
- - [Parallel/Sequential/Mixed strategy]
377
- - Estimated: [N] sessions total
378
-
379
- To execute: Start a fresh session per spec. Each session should:
380
- 1. Read the spec
381
- 2. Implement
382
- 3. Run /session-end to capture discoveries
383
- 4. Commit and PR
384
-
385
- Ready to start?
386
- \`\`\`
387
-
388
- **Why:** A fresh session for execution produces better results. The interview session has too much context noise \u2014 a clean session with just the spec is more focused.
389
-
390
- You can also use \`/decompose\` to re-decompose a brief if the breakdown needs adjustment, or run \`/interview\` first for a lighter brainstorm before committing to the full workflow.
391
- `,
392
- "session-end.md": `---
393
- name: session-end
394
- description: Wrap up a session \u2014 capture discoveries, verify, prepare for PR or next session
395
- ---
396
-
397
- # Session Wrap-Up
398
-
399
- Before ending this session, complete these steps in order.
400
-
401
- ## 1. Capture Discoveries
402
-
403
- **Why:** Discoveries are the surprises \u2014 things that weren't in the spec or that contradicted expectations. They prevent future sessions from hitting the same walls.
404
-
405
- Check: did anything surprising happen during this session? If yes, create or update a discovery file at \`docs/discoveries/YYYY-MM-DD-topic.md\`. Create the \`docs/discoveries/\` directory if it doesn't exist.
406
-
407
- Only capture what's NOT obvious from the code or git diff:
408
- - "We thought X but found Y" \u2014 assumptions that were wrong
409
- - "This API/library behaves differently than documented" \u2014 external gotchas
410
- - "This edge case needs handling in a future spec" \u2014 deferred work with context
411
- - "The approach in the spec didn't work because..." \u2014 spec-vs-reality gaps
412
- - Key decisions made during implementation that aren't in the spec
413
-
414
- **Do NOT capture:**
415
- - Files changed (that's the diff)
416
- - What you set out to do (that's the spec)
417
- - Step-by-step narrative of the session (nobody re-reads these)
418
-
419
- Use this format:
420
-
421
- \`\`\`markdown
422
- # Discoveries \u2014 [topic]
423
-
424
- **Date:** YYYY-MM-DD
425
- **Spec:** [link to spec if applicable]
426
-
427
- ## [Discovery title]
428
- **Expected:** [what we thought would happen]
429
- **Actual:** [what actually happened]
430
- **Impact:** [what this means for future work]
431
- \`\`\`
432
-
433
- If nothing surprising happened, skip the discovery file entirely. No discovery is a good sign \u2014 the spec was accurate.
434
-
435
- ## 2. Run Validation
436
-
437
- Run the project's validation commands. Check CLAUDE.md for project-specific commands. Common checks:
438
-
439
- - Type-check (e.g., \`tsc --noEmit\`, \`mypy\`, \`cargo check\`)
440
- - Tests (e.g., \`npm test\`, \`pytest\`, \`cargo test\`)
441
- - Lint (e.g., \`eslint\`, \`ruff\`, \`clippy\`)
442
-
443
- Fix any failures before proceeding.
444
-
445
- ## 3. Update Spec Status
446
-
447
- If working from an atomic spec in \`docs/specs/\`:
448
- - All acceptance criteria met \u2014 update status to \`Complete\`
449
- - Partially done \u2014 update status to \`In Progress\`, note what's left
450
-
451
- If working from a Feature Brief in \`docs/briefs/\`, check off completed specs in the decomposition table.
452
-
453
- ## 4. Commit
454
-
455
- Commit all changes including the discovery file (if created) and spec status updates. The commit message should reference the spec if applicable.
456
-
457
- ## 5. Report
458
-
459
- \`\`\`
460
- Session complete.
461
- - Spec: [spec name] \u2014 [Complete / In Progress]
462
- - Build: [passing / failing]
463
- - Discoveries: [N items / none]
464
- - Next: [what the next session should tackle, or "ready for PR"]
465
- \`\`\`
466
- `,
467
- "tune.md": `---
468
- name: tune
469
- description: Assess and upgrade your project's AI development harness \u2014 score 7 dimensions, apply fixes, show path to Level 5
470
- ---
471
-
472
- # Tune \u2014 Project Harness Assessment & Upgrade
473
-
474
- You are evaluating and upgrading this project's AI development harness. Follow these steps in order.
475
-
476
- ## Step 1: Detect Harness State
477
-
478
- Check the following and note what exists:
479
-
480
- 1. **CLAUDE.md** \u2014 Read it if it exists. Check whether it contains meaningful content (not just a project name or generic README).
481
- 2. **Key directories** \u2014 Check for: \`docs/specs/\`, \`docs/briefs/\`, \`docs/discoveries/\`, \`docs/templates/\`, \`.claude/skills/\`
482
- 3. **Boundary framework** \u2014 Look for \`Always\`, \`Ask First\`, and \`Never\` sections in CLAUDE.md (or similar behavioral constraints under any heading).
483
- 4. **Skills infrastructure** \u2014 Check \`.claude/skills/\` for installed skill files.
484
- 5. **Test configuration** \u2014 Look for test commands in package.json, pyproject.toml, Cargo.toml, Makefile, or CI config files.
485
-
486
- ## Step 2: Route Based on State
487
-
488
- ### If No Harness (no CLAUDE.md, or CLAUDE.md is just a README with no structured sections):
489
-
490
- Tell the user:
491
- - Their project has no AI development harness
492
- - Recommend running \`npx joycraft init\` to scaffold one
493
- - Briefly explain what it sets up: CLAUDE.md with boundaries, spec/brief templates, skills, documentation structure
494
- - **Stop here** \u2014 do not run the full assessment on a bare project
495
-
496
- ### If Harness Exists (CLAUDE.md has structured content \u2014 boundaries, commands, architecture, or domain rules):
497
-
498
- Continue to Step 3 for the full assessment.
499
-
500
- ## Step 3: Score 7 Dimensions
501
-
502
- Read CLAUDE.md thoroughly. Explore the project structure. Score each dimension on a 1-5 scale with specific evidence.
503
-
504
- ### Dimension 1: Spec Quality
505
-
506
- Look in \`docs/specs/\` for specification files.
507
-
508
- | Score | Criteria |
509
- |-------|----------|
510
- | 1 | No specs directory or no spec files |
511
- | 2 | Specs exist but are informal notes or TODOs |
512
- | 3 | Specs have structure (sections, some criteria) but lack consistency |
513
- | 4 | Specs are structured with clear acceptance criteria and constraints |
514
- | 5 | Atomic specs: self-contained, acceptance criteria, constraints, edge cases, affected files |
515
-
516
- **Evidence:** Number of specs found, example of best/worst, whether acceptance criteria are present.
517
-
518
- ### Dimension 2: Spec Granularity
519
-
520
- Can each spec be completed in a single coding session?
521
-
522
- | Score | Criteria |
523
- |-------|----------|
524
- | 1 | No specs |
525
- | 2 | Specs cover entire features or epics |
526
- | 3 | Specs are feature-sized (multi-session but bounded) |
527
- | 4 | Most specs are session-sized with clear scope |
528
- | 5 | All specs are atomic \u2014 one session, one concern, clear done state |
529
-
530
- ### Dimension 3: Behavioral Boundaries
531
-
532
- Read CLAUDE.md for explicit behavioral constraints.
533
-
534
- | Score | Criteria |
535
- |-------|----------|
536
- | 1 | No CLAUDE.md or no behavioral guidance |
537
- | 2 | CLAUDE.md exists with general instructions but no structured boundaries |
538
- | 3 | Some boundaries exist but not organized as Always/Ask First/Never |
539
- | 4 | Always/Ask First/Never sections present with reasonable coverage |
540
- | 5 | Comprehensive boundaries covering code style, testing, deployment, dependencies, and dangerous operations |
541
-
542
- **Important:** Projects may have strong rules under different headings (e.g., "Critical Rules", "Constraints"). Give credit for substance over format \u2014 a project with clear, enforced rules scores higher than one with empty Always/Ask First/Never sections.
543
-
544
- ### Dimension 4: Skills & Hooks
545
-
546
- Look in \`.claude/skills/\` for skill files. Check for hooks configuration.
547
-
548
- | Score | Criteria |
549
- |-------|----------|
550
- | 1 | No .claude/ directory |
551
- | 2 | .claude/ exists but empty or minimal |
552
- | 3 | A few skills installed, no hooks |
553
- | 4 | Multiple relevant skills, basic hooks |
554
- | 5 | Comprehensive skills covering workflow, hooks for validation |
555
-
556
- ### Dimension 5: Documentation
557
-
558
- Examine \`docs/\` directory structure and content.
559
-
560
- | Score | Criteria |
561
- |-------|----------|
562
- | 1 | No docs/ directory |
563
- | 2 | docs/ exists with ad-hoc files |
564
- | 3 | Some structure (subdirectories) but inconsistent |
565
- | 4 | Structured docs/ with templates and clear organization |
566
- | 5 | Full structure: briefs/, specs/, templates/, architecture docs, referenced from CLAUDE.md |
567
-
568
- ### Dimension 6: Knowledge Capture
569
-
570
- Look for discoveries, decisions, and session notes.
571
-
572
- | Score | Criteria |
573
- |-------|----------|
574
- | 1 | No knowledge capture mechanism |
575
- | 2 | Ad-hoc notes in random locations |
576
- | 3 | A dedicated notes or decisions directory exists |
577
- | 4 | Structured discoveries/decisions directory with entries |
578
- | 5 | Active capture: discoveries with entries, session-end workflow, decision log |
579
-
580
- ### Dimension 7: Testing & Validation
581
-
582
- Look for test config, CI setup, and validation commands.
583
-
584
- | Score | Criteria |
585
- |-------|----------|
586
- | 1 | No test configuration |
587
- | 2 | Test framework installed but few/no tests |
588
- | 3 | Tests exist with reasonable coverage |
589
- | 4 | Tests + CI pipeline configured |
590
- | 5 | Tests + CI + validation commands in CLAUDE.md + scenario tests |
591
-
592
- ## Step 4: Write Assessment
593
-
594
- Write the assessment to \`docs/joycraft-assessment.md\` AND display it in the conversation. Use this format:
595
-
596
- \`\`\`markdown
597
- # Joycraft Assessment \u2014 [Project Name]
598
-
599
- **Date:** [today's date]
600
- **Overall Level:** [1-5, based on average score]
601
-
602
- ## Scores
603
-
604
- | Dimension | Score | Summary |
605
- |-----------|-------|---------|
606
- | Spec Quality | X/5 | [one-line summary] |
607
- | Spec Granularity | X/5 | [one-line summary] |
608
- | Behavioral Boundaries | X/5 | [one-line summary] |
609
- | Skills & Hooks | X/5 | [one-line summary] |
610
- | Documentation | X/5 | [one-line summary] |
611
- | Knowledge Capture | X/5 | [one-line summary] |
612
- | Testing & Validation | X/5 | [one-line summary] |
613
-
614
- **Average:** X.X/5
615
-
616
- ## Detailed Findings
617
-
618
- ### [Dimension Name] \u2014 X/5
619
- **Evidence:** [specific files, paths, counts found]
620
- **Gap:** [what's missing]
621
- **Recommendation:** [specific action to improve]
622
-
623
- ## Upgrade Plan
624
-
625
- To reach Level [current + 1], complete these steps:
626
- 1. [Most impactful action] \u2014 addresses [dimension] (X -> Y)
627
- 2. [Next action] \u2014 addresses [dimension] (X -> Y)
628
- [up to 5 actions, ordered by impact]
629
- \`\`\`
630
-
631
- ## Step 5: Apply Upgrades
632
-
633
- Immediately after presenting the assessment, apply upgrades using the three-tier model below. Do NOT ask for per-item permission \u2014 batch everything and show a consolidated report at the end.
634
-
635
- ### Tier 1: Silent Apply (just do it)
636
- These are safe, additive operations. Apply them without asking:
637
- - Create missing directories (\`docs/specs/\`, \`docs/briefs/\`, \`docs/discoveries/\`, \`docs/templates/\`)
638
- - Install missing skills to \`.claude/skills/\`
639
- - Copy missing templates to \`docs/templates/\`
640
- - Create AGENTS.md if it doesn't exist
641
-
642
- ### Git Autonomy Preference
643
-
644
- Before applying Behavioral Boundaries to CLAUDE.md, ask the user ONE question:
645
-
646
- > How autonomous should git operations be?
647
- > 1. **Cautious** \u2014 commits freely, asks before pushing or opening PRs *(good for learning the workflow)*
648
- > 2. **Autonomous** \u2014 commits, pushes to branches, and opens PRs without asking *(good for spec-driven development)*
649
-
650
- Based on their answer, use the appropriate git rules in the Behavioral Boundaries section:
651
-
652
- **If Cautious (default):**
653
- \`\`\`
654
- ### ASK FIRST
655
- - Pushing to remote
656
- - Creating or merging pull requests
657
- - Any destructive git operation (force-push, reset --hard, branch deletion)
658
-
659
- ### NEVER
660
- - Push directly to main/master without approval
661
- - Amend commits that have been pushed
662
- \`\`\`
663
-
664
- **If Autonomous:**
665
- \`\`\`
666
- ### ALWAYS
667
- - Push to feature branches after each commit
668
- - Open a PR when all specs in a feature are complete
669
- - Use descriptive branch names: feature/spec-name
670
-
671
- ### ASK FIRST
672
- - Merging PRs to main/master
673
- - Any destructive git operation (force-push, reset --hard, branch deletion)
674
-
675
- ### NEVER
676
- - Push directly to main/master (always use feature branches + PR)
677
- - Amend commits that have been pushed to remote
678
- \`\`\`
679
-
680
- This is the ONLY question asked during the upgrade flow. Everything else is batch-applied.
681
-
682
- ### Tier 2: Apply and Show Diff (do it, then report)
683
- These modify important files but are additive (append-only). Apply them, then show what changed so the user can review. Git is the undo button.
684
- - Add missing sections to CLAUDE.md (Behavioral Boundaries, Development Workflow, Getting Started with Joycraft, Key Files, Common Gotchas)
685
- - Use the git autonomy preference from above when generating the Behavioral Boundaries section
686
- - Draft section content from the actual codebase \u2014 not generic placeholders. Read the project's real rules, real commands, real structure.
687
- - Only append \u2014 never modify or reformat existing content
688
-
689
- ### Tier 3: Confirm First (ask before acting)
690
- These are potentially destructive or opinionated. Ask before proceeding:
691
- - Rewriting or reorganizing existing CLAUDE.md sections
692
- - Overwriting files the user has customized
693
- - Suggesting test framework installation or CI setup (present as recommendations, don't auto-install)
694
-
695
- ### Reading a Previous Assessment
696
-
697
- If \`docs/joycraft-assessment.md\` already exists, read it first. If all recommendations have been applied, report "nothing to upgrade" and offer to re-assess.
698
-
699
- ### After Applying
700
-
701
- Append a history entry to \`docs/joycraft-history.md\` (create if needed):
702
- \`\`\`
703
- | [date] | [new avg score] | [change from last] | [summary of what changed] |
704
- \`\`\`
705
-
706
- Then display a single consolidated report:
707
-
708
- \`\`\`markdown
709
- ## Upgrade Results
710
-
711
- | Dimension | Before | After | Change |
712
- |------------------------|--------|-------|--------|
713
- | Spec Quality | X/5 | X/5 | +X |
714
- | ... | ... | ... | ... |
715
-
716
- **Previous Level:** X \u2014 **New Level:** X
717
-
718
- ### What Changed
719
- - [list each change applied]
720
-
721
- ### Remaining Gaps
722
- - [anything still below 3.5, with specific next action]
723
- \`\`\`
724
-
725
- Update \`docs/joycraft-assessment.md\` with the new scores and today's date.
726
-
727
- ## Step 6: Show Path to Level 5
728
-
729
- After the upgrade report, always show the Level 5 roadmap tailored to the project's current state:
730
-
731
- \`\`\`markdown
732
- ## Path to Level 5 \u2014 Autonomous Development
733
-
734
- You're at Level [X]. Here's what each level looks like:
735
-
736
- | Level | You | AI | Key Skill |
737
- |-------|-----|-----|-----------|
738
- | 2 | Guide direction | Multi-file changes | AI-native tooling |
739
- | 3 | Review diffs | Primary developer | Code review at scale |
740
- | 4 | Write specs, check tests | End-to-end development | Specification writing |
741
- | 5 | Define what + why | Specs in, software out | Systems design |
742
-
743
- ### Your Next Steps Toward Level [X+1]:
744
- 1. [Specific action based on current gaps \u2014 e.g., "Write your first atomic spec using /new-feature"]
745
- 2. [Next action \u2014 e.g., "Add vitest and write tests for your core logic"]
746
- 3. [Next action \u2014 e.g., "Use /session-end consistently to build your discoveries log"]
747
-
748
- ### What Level 5 Looks Like (Your North Star):
749
- - A backlog of ready specs that agents pull from and execute autonomously
750
- - CI failures auto-generate fix specs \u2014 no human triage for regressions
751
- - Multi-agent execution with parallel worktrees, one spec per agent
752
- - External holdout scenarios (tests the agent can't see) prevent overfitting
753
- - CLAUDE.md evolves from discoveries \u2014 the harness improves itself
754
-
755
- ### You'll Know You're at Level 5 When:
756
- - You describe a feature in one sentence and walk away
757
- - The system produces a PR with tests, docs, and discoveries \u2014 without further input
758
- - Failed CI runs generate their own fix specs
759
- - Your harness improves without you manually editing CLAUDE.md
760
-
761
- This is a significant journey. Most teams are at Level 2. Getting to Level 4 with Joycraft's workflow is achievable \u2014 Level 5 requires building validation infrastructure (scenario tests, spec queues, CI feedback loops) that goes beyond what Joycraft scaffolds today. But the harness you're building now is the foundation.
762
- \`\`\`
763
-
764
- Tailor the "Next Steps" section based on the project's actual gaps \u2014 don't show generic advice.
765
-
766
- ## Edge Cases
767
-
768
- - **Not a git repo:** Note this. Joycraft works best in a git repo.
769
- - **CLAUDE.md is just a README:** Treat as "no harness."
770
- - **Non-Joycraft skills already installed:** Acknowledge them. Do not replace \u2014 suggest additions.
771
- - **Monorepo:** Assess the root CLAUDE.md. Note if component-level CLAUDE.md files exist.
772
- - **Project has rules under non-standard headings:** Give credit. Suggest reformatting as Always/Ask First/Never but acknowledge the rules are there.
773
- - **Assessment file missing when upgrading:** Run the full assessment first, then offer to apply.
774
- - **Assessment is stale:** Warn and offer to re-assess before proceeding.
775
- - **All recommendations already applied:** Report "nothing to upgrade" and stop.
776
- - **User declines a recommendation:** Skip it, continue, include in "What Was Skipped."
777
- - **CLAUDE.md does not exist at all:** Create it with recommended sections, but ask the user first.
778
- - **Non-Joycraft content in CLAUDE.md:** Preserve exactly as-is. Only append or merge \u2014 never remove or reformat existing content.
779
- `
780
- };
781
- var TEMPLATES = {
782
- "ATOMIC_SPEC_TEMPLATE.md": `# [Verb + Object] \u2014 Atomic Spec
783
-
784
- > **Parent Brief:** \`docs/briefs/YYYY-MM-DD-feature-name.md\` (or "standalone")
785
- > **Status:** Draft | Ready | In Progress | Complete
786
- > **Date:** YYYY-MM-DD
787
- > **Estimated scope:** [1 session / 2-3 files / ~N lines]
788
-
789
- ---
790
-
791
- ## What
792
-
793
- One paragraph. What changes when this spec is done? A developer with no context should understand the change in 15 seconds.
794
-
795
- ## Why
796
-
797
- One sentence. What breaks, hurts, or is missing without this? Links to the parent brief if part of a larger feature.
798
-
799
- ## Acceptance Criteria
800
-
801
- - [ ] [Observable behavior \u2014 what a human would see/verify]
802
- - [ ] [Another observable behavior]
803
- - [ ] [Regression: existing behavior X still works]
804
- - [ ] Build passes
805
- - [ ] Tests pass
806
-
807
- > These are your "done" checkboxes. If Claude says "done" and these aren't all green, it's not done.
808
-
809
- ## Constraints
810
-
811
- - MUST: [hard requirement]
812
- - MUST NOT: [hard prohibition]
813
- - SHOULD: [strong preference, with rationale]
814
-
815
- > Use RFC 2119 language. 2-5 constraints is typical. Zero is a red flag \u2014 every change has boundaries.
816
-
817
- ## Affected Files
818
-
819
- | Action | File | What Changes |
820
- |--------|------|-------------|
821
- | Create | \`path/to/file.ts\` | [brief description] |
822
- | Modify | \`path/to/file.ts\` | [what specifically changes] |
823
-
824
- ## Approach
825
-
826
- How this will be implemented. Not pseudo-code \u2014 describe the strategy, data flow, and key decisions. Name one rejected alternative and why it was rejected.
827
-
828
- _Scale to complexity: 3 sentences for a bug fix, 1 page max for a feature. If you need more than a page, this spec is too big \u2014 decompose further._
829
-
830
- ## Edge Cases
831
-
832
- | Scenario | Expected Behavior |
833
- |----------|------------------|
834
- | [what could go wrong] | [what should happen] |
835
-
836
- > Skip for trivial changes. Required for anything touching user input, data, or external APIs.`,
837
- "FEATURE_BRIEF_TEMPLATE.md": `# [Feature Name] \u2014 Feature Brief
838
-
839
- > **Date:** YYYY-MM-DD
840
- > **Project:** [project name]
841
- > **Status:** Interview | Decomposing | Specs Ready | In Progress | Complete
842
-
843
- ---
844
-
845
- ## Vision
846
-
847
- What are we building and why? This is the "yap" distilled \u2014 the full picture in 2-4 paragraphs.
848
-
849
- ## User Stories
850
-
851
- - As a [role], I want [capability] so that [benefit]
852
-
853
- ## Hard Constraints
854
-
855
- - MUST: [constraint that every spec must respect]
856
- - MUST NOT: [prohibition that every spec must respect]
857
-
858
- ## Out of Scope
859
-
860
- - NOT: [tempting but deferred]
861
-
862
- ## Decomposition
863
-
864
- | # | Spec Name | Description | Dependencies | Est. Size |
865
- |---|-----------|-------------|--------------|-----------|
866
- | 1 | [verb-object] | [one sentence] | None | [S/M/L] |
867
-
868
- ## Execution Strategy
869
-
870
- - [ ] Sequential (specs have chain dependencies)
871
- - [ ] Agent teams (parallel teammates within phases)
872
- - [ ] Parallel worktrees (specs are independent)
873
-
874
- ## Success Criteria
875
-
876
- - [ ] [End-to-end behavior 1]
877
- - [ ] [No regressions in existing features]`,
878
- "IMPLEMENTATION_PLAN_TEMPLATE.md": `# [Feature Name] \u2014 Implementation Plan
879
-
880
- > **Design Spec:** \`docs/specs/YYYY-MM-DD-feature-name.md\`
881
- > **Date:** YYYY-MM-DD
882
- > **Estimated Tasks:** [number]
883
-
884
- ---
885
-
886
- ## Prerequisites
887
-
888
- - [ ] Design spec is approved
889
- - [ ] Branch created (if warranted): \`feature/feature-name\`
890
- - [ ] Required context loaded: [list any docs Claude should read first]
891
-
892
- ## Task 1: [Descriptive Name]
893
-
894
- **Goal:** One sentence \u2014 what is true after this task that wasn't true before.
895
-
896
- **Files:**
897
- - \`path/to/file.ts\` \u2014 [what changes]
898
-
899
- **Steps:**
900
- 1. [Concrete action]
901
- 2. [Next concrete action]
902
-
903
- **Verification:**
904
- - [ ] [How to confirm this task worked]
905
-
906
- **Commit:** \`feat: description\`
907
-
908
- ---
909
-
910
- ## Task N: Final Verification
911
-
912
- **Goal:** Confirm everything works end-to-end.
913
-
914
- **Steps:**
915
- 1. Run full type-check
916
- 2. Run linter
917
- 3. Run tests
918
- 4. Walk through verification checklist from design spec
919
-
920
- **Verification:**
921
- - [ ] All design spec verification items pass
922
- - [ ] No regressions in existing functionality`,
923
- "BOUNDARY_FRAMEWORK.md": `# Boundary Framework
924
-
925
- > Add this to the TOP of your CLAUDE.md, before any project context.
926
- > Customize the specific rules per project, but keep the three-tier structure.
927
-
928
- ---
929
-
930
- ## Behavioral Boundaries
931
-
932
- ### ALWAYS (do these without asking)
933
- - Run type-check and lint before every commit
934
- - Commit after completing each discrete task (atomic commits)
935
- - Follow patterns in existing code \u2014 match existing code style
936
- - Check the active implementation plan before starting work
937
-
938
- ### ASK FIRST (pause and confirm before doing these)
939
- - Adding new dependencies
940
- - Modifying database schema, migrations, or data models
941
- - Changing authentication or authorization flows
942
- - Deviating from an approved implementation plan
943
- - Any destructive operation (deleting files, dropping tables, force-pushing)
944
- - Modifying CI/CD, deployment, or infrastructure configuration
945
-
946
- ### NEVER (do not do these under any circumstances)
947
- - Push to production or main branch without explicit approval
948
- - Delete specs, plans, or documentation
949
- - Modify environment variables or secrets
950
- - Skip type-checking or linting to "save time"
951
- - Make changes outside the scope of the current spec/plan
952
- - Commit code that doesn't build
953
- - Remove or weaken existing tests
954
- - Hardcode secrets, API keys, or credentials`,
955
- "examples/example-brief.md": `# Add User Notifications \u2014 Feature Brief
956
-
957
- > **Date:** 2026-03-15
958
- > **Project:** acme-web
959
- > **Status:** Specs Ready
960
-
961
- ---
962
-
963
- ## Vision
964
-
965
- Our users have no idea when things happen in their account. A teammate comments on their pull request, a deployment finishes, a billing threshold is hit \u2014 they find out by accident, minutes or hours later. This is the #1 complaint in our last user survey.
966
-
967
- We are building a notification system that delivers real-time and batched notifications across in-app, email, and (later) Slack channels. Users will have fine-grained control over what they receive and how. When this ships, no important event goes unnoticed, and no user gets buried in noise they didn't ask for.
968
-
969
- The system is designed to be extensible \u2014 new event types plug in without touching the notification infrastructure. We start with three event types (PR comments, deploy status, billing alerts) and prove the pattern works before expanding.
970
-
971
- ## User Stories
972
-
973
- - As a developer, I want to see a notification badge in the app when someone comments on my PR so that I can respond quickly
974
- - As a team lead, I want to receive an email when a production deployment fails so that I can coordinate the response
975
- - As a billing admin, I want to get alerted when usage exceeds 80% of our plan limit so that I can upgrade before service is disrupted
976
- - As any user, I want to control which notifications I receive and through which channels so that I am not overwhelmed
977
-
978
- ## Hard Constraints
979
-
980
- - MUST: All notifications go through a single event bus \u2014 no direct coupling between event producers and delivery channels
981
- - MUST: Email delivery uses the existing SendGrid integration (do not add a new email provider)
982
- - MUST: Respect user preferences before delivering \u2014 never send a notification the user has opted out of
983
- - MUST NOT: Store notification content in plaintext in the database \u2014 use the existing encryption-at-rest pattern
984
- - MUST NOT: Send more than 50 emails per user per day (batch if necessary)
985
-
986
- ## Out of Scope
987
-
988
- - NOT: Slack/Discord integration (Phase 2)
989
- - NOT: Push notifications / mobile (Phase 2)
990
- - NOT: Notification templates with rich HTML \u2014 plain text and simple markdown only for now
991
- - NOT: Admin dashboard for monitoring notification delivery rates
992
- - NOT: Retroactive notifications for events that happened before the feature ships
993
-
994
- ## Decomposition
995
-
996
- | # | Spec Name | Description | Dependencies | Est. Size |
997
- |---|-----------|-------------|--------------|-----------|
998
- | 1 | add-notification-preferences-api | Create REST endpoints for users to read and update their notification preferences | None | M |
999
- | 2 | add-event-bus-infrastructure | Set up the internal event bus that decouples event producers from notification delivery | None | M |
1000
- | 3 | add-notification-delivery-service | Build the service that consumes events, checks preferences, and dispatches to channels (in-app, email) | Spec 1, Spec 2 | L |
1001
- | 4 | add-in-app-notification-ui | Add notification bell, dropdown, and badge count to the app header | Spec 3 | M |
1002
- | 5 | add-email-batching | Implement daily digest batching for email notifications that exceed the per-user threshold | Spec 3 | S |
1003
-
1004
- ## Execution Strategy
1005
-
1006
- - [x] Agent teams (parallel teammates within phases, sequential between phases)
1007
-
1008
- \`\`\`
1009
- Phase 1: Teammate A -> Spec 1 (preferences API), Teammate B -> Spec 2 (event bus)
1010
- Phase 2: Teammate A -> Spec 3 (delivery service) \u2014 depends on Phase 1
1011
- Phase 3: Teammate A -> Spec 4 (UI), Teammate B -> Spec 5 (batching) \u2014 both depend on Spec 3
1012
- \`\`\`
1013
-
1014
- ## Success Criteria
1015
-
1016
- - [ ] User updates notification preferences via API, and subsequent events respect those preferences
1017
- - [ ] A PR comment event triggers an in-app notification visible in the UI within 2 seconds
1018
- - [ ] A deploy failure event sends an email to subscribed users via SendGrid
1019
- - [ ] When email threshold (50/day) is exceeded, remaining notifications are batched into a daily digest
1020
- - [ ] No regressions in existing PR, deployment, or billing features
1021
-
1022
- ## External Scenarios
1023
-
1024
- | Scenario | What It Tests | Pass Criteria |
1025
- |----------|--------------|---------------|
1026
- | opt-out-respected | User disables email for deploy events, deploy fails | No email sent, in-app notification still appears |
1027
- | batch-threshold | Send 51 email-eligible events for one user in a day | 50 individual emails + 1 digest containing the overflow |
1028
- | preference-persistence | User sets preferences, logs out, logs back in | Preferences are unchanged |
1029
- `,
1030
- "examples/example-spec.md": `# Add Notification Preferences API \u2014 Atomic Spec
1031
-
1032
- > **Parent Brief:** \`docs/briefs/2026-03-15-add-user-notifications.md\`
1033
- > **Status:** Ready
1034
- > **Date:** 2026-03-15
1035
- > **Estimated scope:** 1 session / 4 files / ~250 lines
1036
-
1037
- ---
1038
-
1039
- ## What
1040
-
1041
- Add REST API endpoints that let users read and update their notification preferences. Each user gets a preferences record with per-event-type, per-channel toggles (e.g., "PR comments: in-app=on, email=off"). Preferences default to all-on for new users and are stored encrypted alongside the user profile.
1042
-
1043
- ## Why
1044
-
1045
- The notification delivery service (Spec 3) needs to check preferences before dispatching. Without this API, there is no way for users to control what they receive, and we cannot build the delivery pipeline.
1046
-
1047
- ## Acceptance Criteria
1048
-
1049
- - [ ] \`GET /api/v1/notifications/preferences\` returns the current user's preferences as JSON
1050
- - [ ] \`PATCH /api/v1/notifications/preferences\` updates one or more preference fields and returns the updated record
1051
- - [ ] New users get default preferences (all channels enabled for all event types) on first read
1052
- - [ ] Preferences are validated \u2014 unknown event types or channels return 400
1053
- - [ ] Preferences are stored using the existing encryption-at-rest pattern (\`EncryptedJsonColumn\`)
1054
- - [ ] Endpoint requires authentication (returns 401 for unauthenticated requests)
1055
- - [ ] Build passes
1056
- - [ ] Tests pass (unit + integration)
1057
-
1058
- ## Constraints
1059
-
1060
- - MUST: Use the existing \`EncryptedJsonColumn\` utility for storage \u2014 do not roll a new encryption pattern
1061
- - MUST: Follow the existing REST controller pattern in \`src/controllers/\`
1062
- - MUST NOT: Expose other users' preferences (scope queries to authenticated user only)
1063
- - SHOULD: Return the full preferences object on PATCH (not just the changed fields), so the frontend can replace state without merging
1064
-
1065
- ## Affected Files
1066
-
1067
- | Action | File | What Changes |
1068
- |--------|------|-------------|
1069
- | Create | \`src/controllers/notification-preferences.controller.ts\` | New controller with GET and PATCH handlers |
1070
- | Create | \`src/models/notification-preferences.model.ts\` | Sequelize model with EncryptedJsonColumn for preferences blob |
1071
- | Create | \`src/migrations/20260315-add-notification-preferences.ts\` | Database migration to create notification_preferences table |
1072
- | Create | \`tests/controllers/notification-preferences.test.ts\` | Unit and integration tests for both endpoints |
1073
- | Modify | \`src/routes/index.ts\` | Register the new controller routes |
1074
-
1075
- ## Approach
1076
-
1077
- Create a \`NotificationPreferences\` model backed by a single \`notification_preferences\` table with columns: \`id\`, \`user_id\` (unique FK), \`preferences\` (EncryptedJsonColumn), \`created_at\`, \`updated_at\`. The \`preferences\` column stores a JSON blob shaped like \`{ "pr_comment": { "in_app": true, "email": true }, "deploy_status": { ... } }\`.
1078
-
1079
- The GET endpoint does a find-or-create: if no record exists for the user, create one with defaults and return it. The PATCH endpoint deep-merges the request body into the existing preferences, validates the result against a known schema of event types and channels, and saves.
1080
-
1081
- **Rejected alternative:** Storing preferences as individual rows (one per event-type-channel pair). This would make queries more complex and would require N rows per user instead of 1. The JSON blob approach is simpler and matches how the frontend will consume the data.
1082
-
1083
- ## Edge Cases
1084
-
1085
- | Scenario | Expected Behavior |
1086
- |----------|------------------|
1087
- | PATCH with empty body \`{}\` | Return 200 with unchanged preferences (no-op) |
1088
- | PATCH with unknown event type \`{"foo": {"email": true}}\` | Return 400 with validation error listing valid event types |
1089
- | GET for user with no existing record | Create default preferences, return 200 |
1090
- | Concurrent PATCH requests | Last-write-wins (optimistic, no locking) \u2014 acceptable for user preferences |
1091
- `
1092
- };
1093
-
1094
- // src/version.ts
1095
- import { readFileSync, writeFileSync, existsSync } from "fs";
1096
- import { join } from "path";
1097
- import { createHash } from "crypto";
1098
- var VERSION_FILE = ".joycraft-version";
1099
- function hashContent(content) {
1100
- return createHash("sha256").update(content).digest("hex");
1101
- }
1102
- function readVersion(dir) {
1103
- const filePath = join(dir, VERSION_FILE);
1104
- if (!existsSync(filePath)) return null;
1105
- try {
1106
- const raw = readFileSync(filePath, "utf-8");
1107
- const parsed = JSON.parse(raw);
1108
- if (typeof parsed.version === "string" && typeof parsed.files === "object") {
1109
- return parsed;
1110
- }
1111
- return null;
1112
- } catch {
1113
- return null;
1114
- }
1115
- }
1116
- function writeVersion(dir, version, files) {
1117
- const filePath = join(dir, VERSION_FILE);
1118
- const data = { version, files };
1119
- writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
1120
- }
1121
-
1122
- export {
1123
- SKILLS,
1124
- TEMPLATES,
1125
- hashContent,
1126
- readVersion,
1127
- writeVersion
1128
- };
1129
- //# sourceMappingURL=chunk-LLJVCCB2.js.map