@grimoire-cc/cli 0.13.3 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/bin.js +15 -5
  2. package/dist/bin.js.map +1 -1
  3. package/dist/commands/agent-paths.d.ts +11 -0
  4. package/dist/commands/agent-paths.d.ts.map +1 -0
  5. package/dist/commands/agent-paths.js +69 -0
  6. package/dist/commands/agent-paths.js.map +1 -0
  7. package/dist/commands/agent-skills.d.ts +10 -0
  8. package/dist/commands/agent-skills.d.ts.map +1 -0
  9. package/dist/commands/agent-skills.js +159 -0
  10. package/dist/commands/agent-skills.js.map +1 -0
  11. package/dist/commands/config.d.ts +7 -0
  12. package/dist/commands/config.d.ts.map +1 -0
  13. package/dist/commands/config.js +62 -0
  14. package/dist/commands/config.js.map +1 -0
  15. package/dist/commands/list.d.ts.map +1 -1
  16. package/dist/commands/list.js +237 -75
  17. package/dist/commands/list.js.map +1 -1
  18. package/dist/commands/update.d.ts +1 -2
  19. package/dist/commands/update.d.ts.map +1 -1
  20. package/dist/commands/update.js +18 -0
  21. package/dist/commands/update.js.map +1 -1
  22. package/dist/enforce.d.ts +9 -9
  23. package/dist/enforce.d.ts.map +1 -1
  24. package/dist/enforce.js +56 -23
  25. package/dist/enforce.js.map +1 -1
  26. package/dist/frontmatter.d.ts +16 -0
  27. package/dist/frontmatter.d.ts.map +1 -0
  28. package/dist/frontmatter.js +74 -0
  29. package/dist/frontmatter.js.map +1 -0
  30. package/dist/grimoire-config.d.ts +6 -0
  31. package/dist/grimoire-config.d.ts.map +1 -0
  32. package/dist/grimoire-config.js +23 -0
  33. package/dist/grimoire-config.js.map +1 -0
  34. package/dist/prompt.d.ts.map +1 -1
  35. package/dist/prompt.js +13 -8
  36. package/dist/prompt.js.map +1 -1
  37. package/dist/remove.d.ts +4 -0
  38. package/dist/remove.d.ts.map +1 -1
  39. package/dist/remove.js +8 -0
  40. package/dist/remove.js.map +1 -1
  41. package/dist/resolve.d.ts.map +1 -1
  42. package/dist/resolve.js +12 -5
  43. package/dist/resolve.js.map +1 -1
  44. package/dist/setup.d.ts.map +1 -1
  45. package/dist/setup.js +45 -2
  46. package/dist/setup.js.map +1 -1
  47. package/dist/summary.d.ts.map +1 -1
  48. package/dist/summary.js +9 -0
  49. package/dist/summary.js.map +1 -1
  50. package/package.json +1 -1
  51. package/packs/dev-pack/agents/grimoire.tdd-specialist.md +194 -27
  52. package/packs/dev-pack/grimoire.json +0 -38
  53. package/packs/dev-pack/skills/grimoire.conventional-commit/SKILL.md +69 -65
  54. package/packs/dotnet-pack/agents/grimoire.csharp-coder.md +110 -113
  55. package/packs/dotnet-pack/grimoire.json +23 -5
  56. package/packs/dotnet-pack/skills/grimoire.unit-testing-dotnet/SKILL.md +252 -0
  57. package/packs/{dev-pack/skills/grimoire.tdd-specialist → dotnet-pack/skills/grimoire.unit-testing-dotnet}/reference/anti-patterns.md +78 -0
  58. package/packs/dotnet-pack/skills/grimoire.unit-testing-dotnet/reference/tdd-workflow-patterns.md +259 -0
  59. package/packs/frontend-pack/agents/grimoire.angular-coder.md +193 -0
  60. package/packs/frontend-pack/grimoire.json +7 -0
  61. package/packs/go-pack/grimoire.json +19 -0
  62. package/packs/go-pack/skills/grimoire.unit-testing-go/SKILL.md +256 -0
  63. package/packs/go-pack/skills/grimoire.unit-testing-go/reference/anti-patterns.md +244 -0
  64. package/packs/go-pack/skills/grimoire.unit-testing-go/reference/tdd-workflow-patterns.md +259 -0
  65. package/packs/python-pack/grimoire.json +19 -0
  66. package/packs/python-pack/skills/grimoire.unit-testing-python/SKILL.md +239 -0
  67. package/packs/python-pack/skills/grimoire.unit-testing-python/reference/anti-patterns.md +244 -0
  68. package/packs/python-pack/skills/grimoire.unit-testing-python/reference/tdd-workflow-patterns.md +259 -0
  69. package/packs/rust-pack/grimoire.json +29 -0
  70. package/packs/rust-pack/skills/grimoire.unit-testing-rust/SKILL.md +243 -0
  71. package/packs/rust-pack/skills/grimoire.unit-testing-rust/reference/anti-patterns.md +244 -0
  72. package/packs/rust-pack/skills/grimoire.unit-testing-rust/reference/tdd-workflow-patterns.md +259 -0
  73. package/packs/ts-pack/agents/grimoire.typescript-coder.md +36 -1
  74. package/packs/ts-pack/grimoire.json +27 -1
  75. package/packs/ts-pack/skills/grimoire.unit-testing-typescript/SKILL.md +255 -0
  76. package/packs/ts-pack/skills/grimoire.unit-testing-typescript/reference/anti-patterns.md +244 -0
  77. package/packs/ts-pack/skills/grimoire.unit-testing-typescript/reference/tdd-workflow-patterns.md +259 -0
  78. package/dist/commands/enforce-agent.d.ts +0 -5
  79. package/dist/commands/enforce-agent.d.ts.map +0 -1
  80. package/dist/commands/enforce-agent.js +0 -94
  81. package/dist/commands/enforce-agent.js.map +0 -1
  82. package/packs/dev-pack/skills/grimoire.tdd-specialist/SKILL.md +0 -248
  83. package/packs/dev-pack/skills/grimoire.tdd-specialist/reference/language-frameworks.md +0 -388
  84. package/packs/dev-pack/skills/grimoire.tdd-specialist/reference/tdd-workflow-patterns.md +0 -135
  85. package/packs/dotnet-pack/skills/grimoire.dotnet-unit-testing/SKILL.md +0 -293
  86. package/packs/dotnet-pack/skills/grimoire.dotnet-unit-testing/reference/anti-patterns.md +0 -329
  87. package/packs/dotnet-pack/skills/grimoire.dotnet-unit-testing/reference/framework-guidelines.md +0 -361
  88. package/packs/dotnet-pack/skills/grimoire.dotnet-unit-testing/reference/parameterized-testing.md +0 -378
  89. package/packs/dotnet-pack/skills/grimoire.dotnet-unit-testing/reference/test-organization.md +0 -476
  90. package/packs/dotnet-pack/skills/grimoire.dotnet-unit-testing/reference/test-performance.md +0 -576
  91. package/packs/dotnet-pack/skills/grimoire.dotnet-unit-testing/templates/tunit-template.md +0 -438
  92. package/packs/dotnet-pack/skills/grimoire.dotnet-unit-testing/templates/xunit-template.md +0 -303
@@ -0,0 +1,259 @@
1
+ # TDD Workflow Patterns
2
+
3
+ Guidance on the test-driven development process, when to apply it, and advanced techniques.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Canon TDD — Start with a Test List](#canon-tdd--start-with-a-test-list)
8
+ - [Red-Green-Refactor](#red-green-refactor)
9
+ - [Transformation Priority Premise](#transformation-priority-premise)
10
+ - [F.I.R.S.T. Principles](#first-principles)
11
+ - [London School vs Detroit School](#london-school-vs-detroit-school)
12
+ - [When to Use TDD](#when-to-use-tdd)
13
+ - [When TDD Is Less Effective](#when-tdd-is-less-effective)
14
+ - [BDD and ATDD Extensions](#bdd-and-atdd-extensions)
15
+ - [Advanced Techniques](#advanced-techniques)
16
+
17
+ ## Canon TDD — Start with a Test List
18
+
19
+ > Source: https://tidyfirst.substack.com/p/canon-tdd
20
+
21
+ Kent Beck's recommended starting point is not a single test but a **test list** — a written enumeration of all behaviors you intend to verify. This separates the creative work (what to test) from the mechanical work (write, make pass, refactor).
22
+
23
+ **Process:**
24
+ 1. Write down all behaviors the code needs — a flat list, not tests
25
+ 2. Pick the simplest item on the list
26
+ 3. Write one failing test for it
27
+ 4. Make it pass with the minimum code
28
+ 5. Refactor
29
+ 6. Cross off the item; repeat
30
+
31
+ **Why test order matters:** Starting with simpler behaviors forces simpler transformations (see TPP below) and lets the design emerge naturally. Jumping to complex cases early leads to over-engineered solutions. The test list keeps you focused and prevents scope creep.
32
+
33
+ ## Red-Green-Refactor
34
+
35
+ > Source: https://martinfowler.com/bliki/TestDrivenDevelopment.html
36
+
37
+ The core TDD cycle, repeated in small increments:
38
+
39
+ ### 1. Red — Write a Failing Test
40
+
41
+ Write the smallest test that describes the next piece of behavior. The test MUST fail before you write any production code. A test that passes immediately provides no confidence.
42
+
43
+ **Rules:**
44
+ - Write only ONE test at a time
45
+ - The test should compile/parse but fail at the assertion
46
+ - If the test passes immediately, it's either trivial or testing existing behavior
47
+
48
+ ### 2. Green — Make It Pass
49
+
50
+ Write the MINIMUM code to make the failing test pass. Do not add extra logic, handle cases not yet tested, or optimize.
51
+
52
+ **Rules:**
53
+ - Write the simplest code that makes the test pass
54
+ - It's OK to hardcode values initially — the next test will force generalization
55
+ - Do not add code for future tests
56
+ - All existing tests must still pass
57
+
58
+ ### 3. Refactor — Clean Up
59
+
60
+ With all tests green, improve the code structure without changing behavior. Tests give you the safety net.
61
+
62
+ **Rules:**
63
+ - No new functionality during refactoring
64
+ - All tests must remain green after each refactoring step
65
+ - Remove duplication, improve naming, extract methods
66
+ - Refactor both production code AND test code
67
+
68
+ ### Cycle Length
69
+
70
+ Each Red-Green-Refactor cycle should take 1–10 minutes. If you're spending more than 10 minutes in the Red or Green phase, the step is too large — break it down.
71
+
72
+ ## Transformation Priority Premise
73
+
74
+ > Source: http://blog.cleancoder.com/uncle-bob/2013/05/27/TheTransformationPriorityPremise.html
75
+
76
+ When going from Red to Green, prefer simpler transformations over complex ones. Listed from simplest to most complex:
77
+
78
+ 1. **Constant** — return a hardcoded value
79
+ 2. **Scalar** — replace constant with a variable
80
+ 3. **Direct** — replace unconditional with conditional (if/else)
81
+ 4. **Collection** — operate on a collection instead of a scalar
82
+ 5. **Iteration** — add a loop
83
+ 6. **Recursion** — add recursive call
84
+ 7. **Assignment** — replace computed value with mutation
85
+
86
+ **Example — building FizzBuzz with TDD:**
87
+
88
+ ```
89
+ Test 1: input 1 → "1" Transformation: Constant
90
+ Test 2: input 2 → "2" Transformation: Scalar (use the input)
91
+ Test 3: input 3 → "Fizz" Transformation: Direct (add if)
92
+ Test 4: input 5 → "Buzz" Transformation: Direct (add another if)
93
+ Test 5: input 15 → "FizzBuzz" Transformation: Direct (add combined if)
94
+ Test 6: input 1-15 → full list Transformation: Iteration (generalize)
95
+ ```
96
+
97
+ By following this priority, you avoid over-engineering early and let the design emerge naturally from the tests.
98
+
99
+ ## F.I.R.S.T. Principles
100
+
101
+ Every unit test must satisfy these five properties:
102
+
103
+ | Principle | Definition | Violation Signal |
104
+ |-----------|------------|-----------------|
105
+ | **Fast** | Runs in milliseconds | Real I/O, network calls, `sleep()` |
106
+ | **Independent** | No dependency on other tests | Shared mutable state, ordered execution |
107
+ | **Repeatable** | Same result every run | System clock, random data without seed, race conditions |
108
+ | **Self-Validating** | Pass or fail without manual interpretation | Tests that print output for a human to read |
109
+ | **Timely** | Written before or alongside production code | Tests added weeks after a feature shipped |
110
+
111
+ F.I.R.S.T. is a diagnostic checklist: if a test violates any property, it will erode team trust and reduce the value of the suite.
112
+
113
+ ## London School vs Detroit School
114
+
115
+ > Source: https://martinfowler.com/articles/mocksArentStubs.html
116
+
117
+ Two schools of TDD with different philosophies on test doubles. Most teams use a hybrid.
118
+
119
+ ### Detroit School (Classicist, Inside-Out)
120
+
121
+ - **Unit definition**: A module of any size — can span multiple classes
122
+ - **Approach**: Bottom-up; start from domain logic, build outward
123
+ - **Test doubles**: Avoid mocks; use real objects when feasible
124
+ - **Verification**: State verification — examine the result after execution
125
+ - **Testing style**: Black-box; test through public API
126
+ - **Refactoring**: Safe — tests aren't coupled to implementation details
127
+ - **Best for**: Building confidence in real interactions; reducing brittleness
128
+
129
+ ### London School (Mockist, Outside-In)
130
+
131
+ - **Unit definition**: A single class in isolation
132
+ - **Approach**: Top-down; start from the API, work inward
133
+ - **Test doubles**: Mock all collaborators
134
+ - **Verification**: Behavior verification — confirm correct method calls occurred
135
+ - **Testing style**: White-box; tests know about internals
136
+ - **Refactoring**: Can be brittle — tests break when implementation changes
137
+ - **Best for**: Designing interactions upfront; driving architecture decisions
138
+
139
+ ### Recommended: Hybrid Approach
140
+
141
+ Apply Detroit discipline as the default — use real objects, verify state. Apply London mocking only at architectural boundaries (external APIs, databases, clocks). Never mock value objects, pure functions, or in-process helpers.
142
+
143
+ The most important rule: if you're mocking to make a test easy to write, that's often a design smell (see The Hard Test in anti-patterns). If you're mocking because the dependency is genuinely external or slow, that's the right use.
144
+
145
+ ## When to Use TDD
146
+
147
+ TDD is most valuable when:
148
+
149
+ - **Business logic** — Complex rules, calculations, state machines. TDD forces you to think through all cases before implementing.
150
+ - **Algorithm development** — Sorting, parsing, validation, transformation logic. Tests serve as a specification.
151
+ - **Bug fixes** — Write a test that reproduces the bug first (Red), then fix it (Green). This prevents regressions.
152
+ - **API/interface design** — Writing tests first helps you design interfaces from the consumer's perspective.
153
+ - **Refactoring** — Ensure tests exist before refactoring. If they don't, write characterization tests first, then refactor.
154
+
155
+ ## When TDD Is Less Effective
156
+
157
+ TDD is not universally optimal. Use judgment:
158
+
159
+ - **UI/visual components** — Layout, styling, animations are hard to express as unit tests. Use visual regression testing or snapshot tests instead.
160
+ - **Exploratory/prototype code** — When you don't know what to build yet, writing tests first slows exploration. Spike first, then write tests.
161
+ - **Thin integration layers** — Simple pass-through code (e.g., a controller that calls a service) may not benefit from test-first approach. Integration tests are more valuable here.
162
+ - **Infrastructure/glue code** — Database migrations, config files, build scripts. Test these with integration or end-to-end tests.
163
+ - **External API wrappers** — Thin clients wrapping external APIs are better tested with integration tests against the real (or sandboxed) API.
164
+
165
+ For these cases, write tests AFTER the implementation (test-last), but still write them.
166
+
167
+ ## BDD and ATDD Extensions
168
+
169
+ ### Behavior-Driven Development (BDD)
170
+
171
+ > Source: https://martinfowler.com/bliki/GivenWhenThen.html
172
+
173
+ BDD extends TDD by using natural language to describe behavior. Useful when tests need to be readable by non-developers.
174
+
175
+ **Given-When-Then** structure:
176
+
177
+ ```gherkin
178
+ Given a cart with items totaling $100
179
+ When a 10% discount is applied
180
+ Then the total should be $90
181
+ ```
182
+
183
+ Maps to test code:
184
+
185
+ ```python
186
+ def test_cart_with_10_percent_discount_totals_90():
187
+ # Given
188
+ cart = Cart(items=[Item(price=100)])
189
+
190
+ # When
191
+ cart.apply_discount(PercentageDiscount(10))
192
+
193
+ # Then
194
+ assert cart.total == 90.0
195
+ ```
196
+
197
+ ### Acceptance TDD (ATDD)
198
+
199
+ Write high-level acceptance tests before implementing a feature. These tests describe the feature from the user's perspective and drive the overall design. Unit tests (via TDD) then drive the implementation of each component.
200
+
201
+ **Flow:**
202
+ 1. Write acceptance test (fails — Red)
203
+ 2. Use TDD to implement components needed to pass it
204
+ 3. Acceptance test passes (Green)
205
+ 4. Refactor
206
+
207
+ ATDD is most valuable for features with clear acceptance criteria and when working with product owners or stakeholders.
208
+
209
+ ## Advanced Techniques
210
+
211
+ ### Property-Based Testing
212
+
213
+ Instead of writing individual input/output pairs, define **properties** that should always hold true and let a framework generate hundreds of test cases automatically.
214
+
215
+ **Best for:** Pure functions, algorithms, data transformations, serialization round-trips.
216
+
217
+ **Tools:**
218
+ - Python: [Hypothesis](https://hypothesis.readthedocs.io)
219
+ - JavaScript/TypeScript: [fast-check](https://fast-check.dev)
220
+ - Go: `testing/quick` (stdlib), [gopter](https://github.com/leanovate/gopter)
221
+ - Rust: [proptest](https://github.com/proptest-rs/proptest)
222
+ - Java: [jqwik](https://jqwik.net)
223
+ - Elixir: [StreamData](https://hexdocs.pm/stream_data)
224
+
225
+ **Example property** (Python/Hypothesis):
226
+ ```python
227
+ from hypothesis import given, strategies as st
228
+
229
+ @given(st.lists(st.integers()))
230
+ def test_sort_is_idempotent(lst):
231
+ assert sorted(sorted(lst)) == sorted(lst)
232
+ ```
233
+
234
+ ### Mutation Testing
235
+
236
+ Mutation testing introduces small code changes (mutations) and checks whether your tests catch them. A test suite that lets mutations survive has gaps in its coverage.
237
+
238
+ **Metric:** Mutation score = % of mutations killed. Target 80%+.
239
+
240
+ **Tools:**
241
+ - JavaScript/TypeScript/C#: [Stryker](https://stryker-mutator.io)
242
+ - Java: [PITest](https://pitest.org)
243
+ - Python: [mutmut](https://mutmut.readthedocs.io)
244
+ - Go: [go-mutesting](https://github.com/zimmski/go-mutesting)
245
+
246
+ Run mutation testing periodically (not on every commit) to identify weak spots in the test suite.
247
+
248
+ ### Contract Testing
249
+
250
+ In microservice or distributed architectures, contract tests verify that services communicate correctly without running full integration tests.
251
+
252
+ **How it works:**
253
+ 1. Consumer defines a contract (expected interactions)
254
+ 2. Provider verifies it can fulfill the contract
255
+ 3. Both test independently — no need to spin up the full system
256
+
257
+ **Tool:** [Pact](https://pact.io) — supports most major languages.
258
+
259
+ Contract tests replace the expensive integration test layer for inter-service communication while still catching breaking API changes early.
@@ -2,12 +2,23 @@
2
2
  name: grimoire.typescript-coder
3
3
  description: "Use this agent when the user needs to write, refactor, debug, review, or understand TypeScript code in any environment — Node.js backends, React, Angular, Vue, Svelte, or any other TypeScript-compatible platform. This includes tasks like designing type-safe data models, implementing utility types, handling errors with discriminated unions, refactoring JavaScript to TypeScript, or reviewing TypeScript code for type safety and correctness.\\n\\nExamples:\\n<example>\\nContext: User wants to write a type-safe API client.\\nuser: \"Write a type-safe fetch wrapper that handles errors without throwing\"\\nassistant: \"I'll use the grimoire.typescript-coder agent to implement this with a Result type pattern.\"\\n<commentary>\\nThe user needs TypeScript code involving error handling and type safety — a perfect fit for the grimoire.typescript-coder agent.\\n</commentary>\\n</example>\\n\\n<example>\\nContext: User is refactoring an existing function.\\nuser: \"Refactor this function to be more type-safe and remove the use of `any`\"\\nassistant: \"Let me hand this off to the grimoire.typescript-coder agent to refactor it properly.\"\\n<commentary>\\nRemoving `any` and improving type safety is core to what this agent does.\\n</commentary>\\n</example>\\n\\n<example>\\nContext: User is building a Vue 3 composable.\\nuser: \"Create a reusable composable for paginated data fetching with TypeScript\"\\nassistant: \"I'll use the grimoire.typescript-coder agent to design this composable with proper types.\"\\n<commentary>\\nFramework-specific TypeScript (Vue Composition API here) is within scope for this agent.\\n</commentary>\\n</example>\\n\\n<example>\\nContext: User asks about discriminated unions.\\nuser: \"How do I model a payment result that can succeed or fail with different error types?\"\\nassistant: \"I'll use the grimoire.typescript-coder agent to model this with a discriminated union Result type.\"\\n<commentary>\\nType design questions are core responsibilities of this agent.\\n</commentary>\\n</example>"
4
4
  tools: Glob, Grep, Read, Edit, Write, Skill, TaskCreate, TaskGet, TaskUpdate, TaskList, mcp__plugin_context7_context7__resolve-library-id, mcp__plugin_context7_context7__query-docs
5
- model: sonnet
6
5
  memory: project
7
6
  ---
8
7
 
9
8
  You are an expert TypeScript developer with deep mastery of the TypeScript type system, modern language features, and best practices across all major frameworks and runtimes. Your role is to write, refactor, debug, and review high-quality, production-ready TypeScript code. You are platform-agnostic and framework-agnostic — equally fluent in Node.js backends, React, Angular, Vue, Svelte, and any other TypeScript-compatible environment.
10
9
 
10
+ You own the implementation end-to-end. You receive a task, read the codebase, make design decisions, and deliver working TypeScript code that fits the project.
11
+
12
+ ## How You Work
13
+
14
+ 1. **Read the task** — understand what needs to be built or changed
15
+ 2. **Look up docs when needed** — use Context7 for API reference when working with unfamiliar libraries or APIs
16
+ 3. **Break down complex work** — use tasks to track progress on multi-file implementations
17
+ 4. **Implement** — write clean, working code that fits the existing codebase
18
+ 5. **Verify** — ensure code compiles logically, follows existing patterns, handles edge cases
19
+
20
+ When the task specifies an approach, follow it. When it doesn't, choose the best one yourself. Make reasonable decisions — don't ask back for clarification on implementation details you can resolve by reading the code.
21
+
11
22
  ## Core Principles
12
23
 
13
24
  ### Type Safety
@@ -108,3 +119,27 @@ Before presenting code, verify:
108
119
  - [ ] Error cases are modeled explicitly
109
120
  - [ ] Code compiles cleanly under `strict: true` assumptions
110
121
  - [ ] Logic is idiomatic for the target framework (if applicable)
122
+
123
+ # Persistent Agent Memory
124
+
125
+ Your `memory: project` setting gives you a persistent memory directory (under `.claude/agent-memory/grimoire.typescript-coder/`). Contents persist across conversations.
126
+
127
+ Consult your memory files to build on previous experience. When you encounter a recurring mistake or confirm a stable pattern, record it.
128
+
129
+ Guidelines:
130
+ - `MEMORY.md` is always loaded into your system prompt — keep it under 200 lines
131
+ - Create separate topic files (e.g., `debugging.md`, `patterns.md`) for details and link from MEMORY.md
132
+ - Update or remove memories that turn out to be wrong or outdated
133
+ - Organize by topic, not chronologically
134
+
135
+ What to save:
136
+ - Stable patterns and conventions confirmed across multiple interactions
137
+ - Key architectural decisions, important file paths, and project structure
138
+ - User preferences for workflow, tools, and communication style
139
+ - Solutions to recurring problems and debugging insights
140
+
141
+ What NOT to save:
142
+ - Session-specific context (current task details, in-progress work)
143
+ - Information that might be incomplete — verify before writing
144
+ - Anything that duplicates existing CLAUDE.md instructions
145
+ - Speculative conclusions from reading a single file
@@ -6,7 +6,7 @@
6
6
  "name": "grimoire.typescript-coder",
7
7
  "path": "agents/grimoire.typescript-coder.md",
8
8
  "description": "Use this agent when the user needs to write, refactor, debug, review, or understand TypeScript code in any environment — Node.js backends, React, Angular, Vue, Svelte, or any other TypeScript-compatible platform. This includes tasks like designing type-safe data models, implementing utility types, handling errors with discriminated unions, refactoring JavaScript to TypeScript, or reviewing TypeScript code for type safety and correctness.",
9
- "version": "1.0.0",
9
+ "version": "2.0.0",
10
10
  "file_patterns": ["*.ts", "*.tsx", "*.mts", "*.cts", "*.js", "*.mjs", "*.cjs"]
11
11
  }
12
12
  ],
@@ -37,6 +37,32 @@
37
37
  ],
38
38
  "file_paths": ["**/tsconfig*", "**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"]
39
39
  }
40
+ },
41
+ {
42
+ "name": "grimoire.unit-testing-typescript",
43
+ "path": "skills/grimoire.unit-testing-typescript",
44
+ "description": "TypeScript/JavaScript unit testing specialist. Framework selection, patterns, and best practices for Vitest, Jest, Mocha, and Node test runner. Use when writing tests for .ts/.tsx/.js files, configuring test frameworks, or asking about TypeScript testing patterns, mocking, assertions, async testing.",
45
+ "version": "1.0.0",
46
+ "triggers": {
47
+ "keywords": ["vitest", "jest", "mocha"],
48
+ "file_extensions": [".ts", ".tsx", ".js", ".jsx"],
49
+ "patterns": [
50
+ "write.*test",
51
+ "add.*test",
52
+ "create.*test",
53
+ "test.*coverage",
54
+ "typescript.*test"
55
+ ],
56
+ "file_paths": [
57
+ "__tests__/**",
58
+ "**/*.test.ts",
59
+ "**/*.spec.ts",
60
+ "**/*.test.js",
61
+ "**/*.spec.js",
62
+ "**/vitest.config.*",
63
+ "**/jest.config.*"
64
+ ]
65
+ }
40
66
  }
41
67
  ]
42
68
  }
@@ -0,0 +1,255 @@
1
+ ---
2
+ name: grimoire.unit-testing-typescript
3
+ description: "TypeScript/JavaScript unit testing specialist. Framework selection, patterns, and best practices for Vitest, Jest, Mocha, and Node test runner. Use when writing tests for .ts/.tsx/.js files, configuring test frameworks, or asking about TypeScript testing patterns, mocking, assertions, async testing."
4
+ ---
5
+
6
+ # TypeScript Unit Testing
7
+
8
+ Focused guidance for writing clean, type-safe unit tests in TypeScript and JavaScript projects.
9
+
10
+ ## Framework Selection
11
+
12
+ ### Detection
13
+
14
+ 1. Check existing test files first — always match what the project uses
15
+ 2. Check `package.json` devDependencies for `vitest`, `jest`, `mocha`, `@types/mocha`
16
+ 3. Check for config files: `vitest.config.ts`, `jest.config.ts`, `.mocharc.*`
17
+
18
+ ### Decision Table
19
+
20
+ | Condition | Use | Reason |
21
+ |-----------|-----|--------|
22
+ | Project has existing tests | **Match existing** | Consistency is paramount |
23
+ | Vite-based project | **Vitest** | Native integration, fastest |
24
+ | New TypeScript project | **Vitest** | ESM-native, Jest-compatible API, fast |
25
+ | React (CRA) or existing Jest | **Jest** | Mature ecosystem, wide adoption |
26
+ | Legacy project, custom setup | **Mocha + Chai** | Flexible, pluggable |
27
+ | Node.js 20+, minimal deps | **Node test runner** | Built-in, zero dependencies |
28
+ | User explicitly requests | **Requested** | Respect user preference |
29
+
30
+ ## Naming Conventions
31
+
32
+ Use descriptive strings in `test()` or `it()`:
33
+
34
+ ```typescript
35
+ // Pattern: 'methodName scenario expected behavior'
36
+ test('getUser with invalid id throws NotFound', () => { ... });
37
+ test('calculateTotal with discount applies percentage', () => { ... });
38
+ test('parseConfig with missing required fields throws ValidationError', () => { ... });
39
+
40
+ // describe blocks for grouping
41
+ describe('OrderService', () => {
42
+ describe('processOrder', () => {
43
+ test('with valid order saves and returns id', async () => { ... });
44
+ test('with invalid order throws ValidationError', async () => { ... });
45
+ });
46
+ });
47
+ ```
48
+
49
+ ## Patterns
50
+
51
+ ### AAA with Vitest/Jest
52
+
53
+ ```typescript
54
+ import { describe, test, expect, vi, beforeEach } from 'vitest';
55
+
56
+ describe('OrderService', () => {
57
+ let mockRepo: MockedObject<OrderRepository>;
58
+ let service: OrderService;
59
+
60
+ beforeEach(() => {
61
+ mockRepo = { save: vi.fn(), findById: vi.fn() };
62
+ service = new OrderService(mockRepo);
63
+ });
64
+
65
+ test('processOrder with valid order saves and returns id', async () => {
66
+ // Arrange
67
+ const order = createValidOrder();
68
+ mockRepo.save.mockResolvedValue({ id: '123' });
69
+
70
+ // Act
71
+ const result = await service.processOrder(order);
72
+
73
+ // Assert
74
+ expect(result.id).toBe('123');
75
+ expect(mockRepo.save).toHaveBeenCalledWith(order);
76
+ });
77
+
78
+ test('processOrder with invalid order throws ValidationError', async () => {
79
+ // Arrange
80
+ const order = createInvalidOrder();
81
+
82
+ // Act & Assert
83
+ await expect(service.processOrder(order)).rejects.toThrow(ValidationError);
84
+ });
85
+ });
86
+ ```
87
+
88
+ ### Parameterized Tests
89
+
90
+ ```typescript
91
+ // Vitest/Jest
92
+ test.each([
93
+ { discount: 0, expected: 100.0 },
94
+ { discount: 10, expected: 90.0 },
95
+ { discount: 50, expected: 50.0 },
96
+ ])('applyDiscount with $discount% returns $expected', ({ discount, expected }) => {
97
+ expect(applyDiscount(100, discount)).toBe(expected);
98
+ });
99
+
100
+ // With descriptive names via tagged template
101
+ test.each`
102
+ input | expected
103
+ ${''} | ${false}
104
+ ${'abc'} | ${true}
105
+ ${'a'} | ${true}
106
+ `('isNonEmpty("$input") returns $expected', ({ input, expected }) => {
107
+ expect(isNonEmpty(input)).toBe(expected);
108
+ });
109
+ ```
110
+
111
+ ### Async Testing
112
+
113
+ ```typescript
114
+ // Async/await (preferred)
115
+ test('fetchUser resolves with user data', async () => {
116
+ const user = await fetchUser('123');
117
+ expect(user.name).toBe('Alice');
118
+ });
119
+
120
+ // Promise rejection
121
+ test('fetchUser with bad id rejects with NotFound', async () => {
122
+ await expect(fetchUser('bad')).rejects.toThrow(NotFoundError);
123
+ });
124
+
125
+ // Callback-based (rare, legacy)
126
+ test('legacyFetch calls back with data', (done) => {
127
+ legacyFetch('123', (err, data) => {
128
+ expect(err).toBeNull();
129
+ expect(data.name).toBe('Alice');
130
+ done();
131
+ });
132
+ });
133
+ ```
134
+
135
+ ### Error Testing
136
+
137
+ ```typescript
138
+ // Sync errors
139
+ test('divide by zero throws', () => {
140
+ expect(() => divide(1, 0)).toThrow('Cannot divide by zero');
141
+ });
142
+
143
+ // Async errors
144
+ test('save invalid order rejects with ValidationError', async () => {
145
+ await expect(service.save(invalidOrder)).rejects.toThrow(ValidationError);
146
+ });
147
+
148
+ // Error properties
149
+ test('validation error includes field name', async () => {
150
+ try {
151
+ await service.save(invalidOrder);
152
+ expect.fail('should have thrown');
153
+ } catch (err) {
154
+ expect(err).toBeInstanceOf(ValidationError);
155
+ expect((err as ValidationError).field).toBe('items');
156
+ }
157
+ });
158
+ ```
159
+
160
+ ## Mocking
161
+
162
+ ### Vitest (`vi`)
163
+
164
+ ```typescript
165
+ // Function mock
166
+ const mockFn = vi.fn().mockReturnValue(42);
167
+
168
+ // Module mock
169
+ vi.mock('./emailService', () => ({
170
+ sendEmail: vi.fn().mockResolvedValue(true),
171
+ }));
172
+
173
+ // Spy on object method
174
+ const spy = vi.spyOn(console, 'log');
175
+
176
+ // Timer mocking
177
+ vi.useFakeTimers();
178
+ vi.advanceTimersByTime(1000);
179
+ vi.useRealTimers();
180
+
181
+ // Mock reset
182
+ beforeEach(() => vi.clearAllMocks());
183
+ ```
184
+
185
+ ### Jest (`jest`)
186
+
187
+ ```typescript
188
+ // Same API, replace `vi` with `jest`
189
+ const mockFn = jest.fn().mockReturnValue(42);
190
+ jest.mock('./emailService');
191
+ jest.spyOn(console, 'log');
192
+ jest.useFakeTimers();
193
+ ```
194
+
195
+ ### Type-safe mocking
196
+
197
+ ```typescript
198
+ // Use MockedObject for full type safety
199
+ import type { MockedObject } from 'vitest';
200
+
201
+ let mockRepo: MockedObject<OrderRepository>;
202
+
203
+ // Or create typed mock factories
204
+ function createMockRepo(overrides?: Partial<OrderRepository>): MockedObject<OrderRepository> {
205
+ return {
206
+ save: vi.fn(),
207
+ findById: vi.fn(),
208
+ delete: vi.fn(),
209
+ ...overrides,
210
+ } as MockedObject<OrderRepository>;
211
+ }
212
+ ```
213
+
214
+ ### What NOT to mock
215
+
216
+ - Value objects, DTOs, plain data structures
217
+ - Pure functions with no side effects
218
+ - The class/module under test itself
219
+ - Simple utility functions
220
+
221
+ Mock only at system boundaries: APIs, databases, file system, timers, randomness.
222
+
223
+ ## File Conventions
224
+
225
+ - `*.test.ts` / `*.spec.ts` (co-located or in `__tests__/`)
226
+ - `vitest.config.ts` or `jest.config.ts` for configuration
227
+ - `vitest` or `jest` in `package.json` scripts
228
+ - Shared test utilities in `test/helpers/` or `__tests__/helpers/`
229
+
230
+ ## Package Setup
231
+
232
+ ```bash
233
+ # Vitest
234
+ npm install -D vitest @vitest/coverage-v8
235
+
236
+ # Jest with TypeScript
237
+ npm install -D jest ts-jest @types/jest
238
+ npx ts-jest config:init
239
+
240
+ # Optional: testing-library for DOM
241
+ npm install -D @testing-library/react @testing-library/jest-dom
242
+ ```
243
+
244
+ ## Authoritative Sources
245
+
246
+ - Vitest: https://vitest.dev
247
+ - Jest: https://jestjs.io
248
+ - Mocha: https://mochajs.org
249
+ - Kent Beck — Canon TDD: https://tidyfirst.substack.com/p/canon-tdd
250
+ - Martin Fowler — Mocks Aren't Stubs: https://martinfowler.com/articles/mocksArentStubs.html
251
+
252
+ ## Reference Materials
253
+
254
+ - **[Anti-Patterns](reference/anti-patterns.md)** — Common testing mistakes and how to fix them
255
+ - **[TDD Workflow Patterns](reference/tdd-workflow-patterns.md)** — Red-Green-Refactor, Transformation Priority Premise, when to use TDD