claude-toolkit 0.9.0 → 0.11.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.
- package/CHANGELOG.md +22 -0
- package/README.md +27 -32
- package/bin/cli.ts +198 -162
- package/bin/postinstall.mjs +69 -0
- package/core/agents/ct-code-reviewer.md +5 -4
- package/core/agents/ct-github-workflow.md +28 -15
- package/core/commands/ct/code-quality.md +22 -2
- package/core/commands/ct/onboard.md +8 -3
- package/core/commands/ct/pr-review.md +22 -88
- package/core/commands/ct/pr-summary.md +6 -3
- package/core/commands/ct/ticket.md +20 -3
- package/core/hooks/{skill-eval.js → skill-eval.cjs} +103 -41
- package/core/hooks/skill-rules.schema.json +4 -0
- package/core/skills/ct-systematic-debugging/SKILL.md +1 -1
- package/core/skills/ct-testing-patterns/SKILL.md +5 -7
- package/core/skills/ct-typescript-conventions/SKILL.md +15 -11
- package/core/skills/ct-verification-before-completion/SKILL.md +2 -1
- package/docs/README.md +4 -0
- package/docs/commands/code-quality.md +2 -8
- package/docs/commands/onboard.md +2 -11
- package/docs/commands/pr-review.md +2 -13
- package/docs/commands/pr-summary.md +2 -2
- package/docs/commands/proto-check.md +4 -4
- package/docs/commands/ticket.md +2 -2
- package/docs/skills/systematic-debugging.md +1 -1
- package/docs/skills/testing-patterns.md +78 -56
- package/docs/skills/typescript-conventions.md +23 -10
- package/docs/skills/verification-before-completion.md +1 -1
- package/package.json +3 -1
- package/src/generator.ts +84 -12
- package/src/utils.ts +8 -15
- package/{core/commands/ct → stacks/protobuf/commands}/proto-check.md +11 -2
- package/templates/skill-rules.base.json +1 -29
- package/core/hooks/skill-eval.sh +0 -35
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ct-testing-patterns
|
|
3
|
-
description: Generic test-driven development practices and patterns applicable to any language or test framework.
|
|
3
|
+
description: Generic test-driven development practices and patterns applicable to any language or test framework. Use when writing tests, setting up a test suite, or deciding what to test at which layer
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Testing Patterns
|
|
@@ -28,6 +28,8 @@ description: Generic test-driven development practices and patterns applicable t
|
|
|
28
28
|
| Interaction | ~20% | Component variants, user interactions, accessibility, visual regression |
|
|
29
29
|
| E2E | ~10% | Critical user journeys, authentication flows, cross-page workflows |
|
|
30
30
|
|
|
31
|
+
> **Scope:** This core skill owns the layering _decision_ below, the unit and interaction layers, and the cross-cutting E2E principles. Runner-specific E2E setup and execution live in the stack skills (e.g. `ct-playwright-patterns`) when a matching stack is installed.
|
|
32
|
+
|
|
31
33
|
### When to Use Which Layer
|
|
32
34
|
|
|
33
35
|
| Question | Layer |
|
|
@@ -103,13 +105,9 @@ bun test path/to/file.test.ts # single file
|
|
|
103
105
|
|
|
104
106
|
Bun supports `describe`, `it`/`test`, `expect`, lifecycle hooks, and snapshot testing out of the box with no additional dependencies.
|
|
105
107
|
|
|
106
|
-
## Test Pyramid
|
|
107
|
-
|
|
108
|
-
See 3-Layer Testing Strategy above. Many unit tests (fast, focused) > some interaction tests (component sandbox) > few E2E tests (full flow). Aim for 70/20/10 distribution.
|
|
109
|
-
|
|
110
108
|
## Test Speed
|
|
111
109
|
|
|
112
|
-
Three levers recur across
|
|
110
|
+
Three levers recur across common runners (Vitest, Playwright, Storybook browser mode). Stated once here; each stack skill carries the framework-specific syntax.
|
|
113
111
|
|
|
114
112
|
- **Parallelism sized to the runner.** Enable file-level parallelism (Vitest `fileParallelism`, Playwright `fullyParallel`), but cap workers to the runner's *real* vCPUs (`"50%"` or a measured count). GitHub standard runners are 2 vCPU (private) / 4 (public); oversubscribing thrashes.
|
|
115
113
|
- **Shard across CI jobs, then merge the blob reports.** Sharding splits at the *file* level (`--shard=i/n`), so wall-clock is gated by the slowest shard -- balance file sizes. Always emit a blob report per shard (`--reporter=blob`) and merge it (`merge-reports` / `--merge-reports`) in a dependent job, or results and coverage are fragmented and incomplete.
|
|
@@ -117,7 +115,7 @@ Three levers recur across every runner (Vitest, Playwright, Storybook browser mo
|
|
|
117
115
|
|
|
118
116
|
Profile before tuning, and never `sleep` to mask timing -- use the framework's auto-waiting (see Shared Principles).
|
|
119
117
|
|
|
120
|
-
Per-runner config: `ct-vite-vitest-patterns`, `ct-playwright-patterns`, `ct-storybook-patterns`.
|
|
118
|
+
Per-runner config, if the corresponding stack is installed: `ct-vite-vitest-patterns`, `ct-playwright-patterns`, `ct-storybook-patterns`.
|
|
121
119
|
|
|
122
120
|
## Anti-Patterns
|
|
123
121
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ct-typescript-conventions
|
|
3
|
-
description: Strict TypeScript patterns for type safety, readability, and maintainable codebases.
|
|
3
|
+
description: Strict TypeScript patterns for type safety, readability, and maintainable codebases. Use when writing or reviewing TypeScript, adding or tightening types, or deciding between type and interface
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# TypeScript Conventions
|
|
@@ -10,7 +10,7 @@ Strict mode enabled. Catch errors at compile time, not runtime.
|
|
|
10
10
|
## Rules
|
|
11
11
|
|
|
12
12
|
- **No `any`** -- Use `unknown` + narrowing, generics, or specific types.
|
|
13
|
-
-
|
|
13
|
+
- **Default to `type`.** Use `interface` only when you need `extends` (object inheritance). `type` aliases have an implicit index signature, so they stay assignable to `Record<string, unknown>`; interfaces do not.
|
|
14
14
|
- **`as const`** for literal types and readonly tuples.
|
|
15
15
|
- **Never disable strict checks.** Hard-to-type code = design issue.
|
|
16
16
|
|
|
@@ -42,19 +42,21 @@ type AsyncState<T> =
|
|
|
42
42
|
|
|
43
43
|
## `satisfies` Operator
|
|
44
44
|
|
|
45
|
-
Validate a value
|
|
45
|
+
Validate a value conforms to a type while keeping the *narrowest inferred type* per property, instead of widening every property to the target's value type (as an explicit annotation would). Against a union-typed target, the matching literal is preserved.
|
|
46
46
|
|
|
47
47
|
```typescript
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
//
|
|
48
|
+
const config = {
|
|
49
|
+
mode: "production",
|
|
50
|
+
level: 3,
|
|
51
|
+
} satisfies { mode: "development" | "production"; level: number };
|
|
52
|
+
|
|
53
|
+
// config.mode is the literal "production" (not widened to string),
|
|
54
|
+
// because the target property is a union of literals. A plain
|
|
55
|
+
// annotation `const config: {...}` would widen it to the full union.
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
Note: `satisfies` does not by itself narrow to literals against a _wide_ target -- e.g. `satisfies Record<string, string>` still infers `string` for each value, and `satisfies Record<string, { path: string }>` leaves each `path` as `string`. Combine with `as const` when you need literals preserved against a `string`-typed target.
|
|
59
|
+
|
|
58
60
|
## `const` Type Parameters
|
|
59
61
|
|
|
60
62
|
Infer literal types from arguments without requiring callers to write `as const`:
|
|
@@ -68,6 +70,8 @@ function createConfig<const T extends readonly string[]>(names: T): Record<T[num
|
|
|
68
70
|
const flags = createConfig(["debug", "verbose"]);
|
|
69
71
|
```
|
|
70
72
|
|
|
73
|
+
The `as Record<T[number], boolean>` above is the narrow exception to anti-pattern #1: `Object.fromEntries` is typed to return a wide `Record<string, boolean>`, so a localized cast _at a generic helper's return_ -- where the signature already proves the tighter type -- is acceptable. Reach for type guards everywhere else.
|
|
74
|
+
|
|
71
75
|
## Template Literal Types
|
|
72
76
|
|
|
73
77
|
Build precise string types from unions:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ct-verification-before-completion
|
|
3
|
-
description: Evidence-based completion claims -- never say "done" without proof that the work is correct.
|
|
3
|
+
description: Evidence-based completion claims -- never say "done" without proof that the work is correct. Use when about to claim a task is done, fixed, or passing, or before committing or opening a PR
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Verification Before Completion
|
|
@@ -21,6 +21,7 @@ Before claiming complete, run and show output for each:
|
|
|
21
21
|
- Empty inputs (empty string, empty array, null, undefined)
|
|
22
22
|
- Boundary values (zero, negative, max, off-by-one)
|
|
23
23
|
- Invalid inputs (wrong types, malformed data, missing fields)
|
|
24
|
+
- Concurrent access (simultaneous requests or operations)
|
|
24
25
|
- Error paths (network failure, permission denied)
|
|
25
26
|
|
|
26
27
|
Do not assume edge cases work because the happy path works.
|
package/docs/README.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Complete reference for all skills, commands, and agents provided by claude-toolkit.
|
|
4
4
|
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
Run `bunx claude-toolkit` in your project — on the first run it creates `claude-toolkit.config.ts` (pre-filled from stack detection) and generates `.claude/`. Run it again anytime to regenerate; add `--update` to pull newly-detected stacks into the config. `.claude/` also regenerates automatically on install when the toolkit version changes. See the [README](../README.md#cli-commands) for the full CLI.
|
|
8
|
+
|
|
5
9
|
## Core Skills
|
|
6
10
|
|
|
7
11
|
Skills that are always included regardless of stack configuration.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# /code-quality
|
|
1
|
+
# /ct:code-quality
|
|
2
2
|
|
|
3
3
|
> Run code quality checks (lint, typecheck, format) on a directory or file.
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
/code-quality [path]
|
|
12
|
+
/ct:code-quality [path]
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Workflow
|
|
@@ -29,12 +29,6 @@ The command produces a structured report with:
|
|
|
29
29
|
- **Format Issues** -- table with file and status
|
|
30
30
|
- **Summary** -- total issues across files with actionable suggestions
|
|
31
31
|
|
|
32
|
-
## Best Practices Reference
|
|
33
|
-
|
|
34
|
-
| Topic | Guide |
|
|
35
|
-
| --- | --- |
|
|
36
|
-
| Recommended `tsconfig.json` settings | [TSConfig Cheat Sheet](../best-practices/typescript/tsconfig-cheat-sheet.md) |
|
|
37
|
-
|
|
38
32
|
## Notes
|
|
39
33
|
|
|
40
34
|
- Always uses the project's own configuration; does not impose external rules
|
package/docs/commands/onboard.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# /onboard
|
|
1
|
+
# /ct:onboard
|
|
2
2
|
|
|
3
3
|
> Systematically explore and understand a codebase area, module, or task context.
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
/onboard [area]
|
|
12
|
+
/ct:onboard [area]
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
If no area is specified, starts from the project root.
|
|
@@ -56,15 +56,6 @@ If no area is specified, starts from the project root.
|
|
|
56
56
|
- {Things that are unclear or undocumented}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
## Best Practices Reference
|
|
60
|
-
|
|
61
|
-
Conventions to look for during onboarding:
|
|
62
|
-
|
|
63
|
-
| Topic | Guide |
|
|
64
|
-
| --- | --- |
|
|
65
|
-
| TypeScript conventions and patterns | [TypeScript Best Practices](../best-practices/typescript/README.md) |
|
|
66
|
-
| SolidJS conventions and patterns | [SolidJS Best Practices](../best-practices/solidjs/README.md) |
|
|
67
|
-
|
|
68
59
|
## Notes
|
|
69
60
|
|
|
70
61
|
- Prioritizes understanding over completeness -- deeply understand 5 key files rather than skim 50
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# /pr-review
|
|
1
|
+
# /ct:pr-review
|
|
2
2
|
|
|
3
3
|
> Perform a checklist-based code review on the current PR or a specified PR number.
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
/pr-review [pr-number]
|
|
12
|
+
/ct:pr-review [pr-number]
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
If no PR number is provided, diffs the current branch against the base branch.
|
|
@@ -83,17 +83,6 @@ The command evaluates all changed files against these criteria:
|
|
|
83
83
|
### Summary
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
## Best Practices Reference
|
|
87
|
-
|
|
88
|
-
Review criteria informed by these guides:
|
|
89
|
-
|
|
90
|
-
| Review Area | Guide |
|
|
91
|
-
| --- | --- |
|
|
92
|
-
| Type safety: `any` usage, unsafe casts | [any & unknown](../best-practices/typescript/any-and-unknown.md) |
|
|
93
|
-
| State modeling with unions | [Discriminated Unions](../best-practices/typescript/discriminated-unions.md) |
|
|
94
|
-
| SolidJS-specific issues (props, reactivity) | [SolidJS Anti-Patterns](../best-practices/solidjs/anti-patterns.md) |
|
|
95
|
-
| Performance: re-renders, reactivity mistakes | [SolidJS Performance](../best-practices/solidjs/performance.md) |
|
|
96
|
-
|
|
97
86
|
## Notes
|
|
98
87
|
|
|
99
88
|
- References specific file names and line numbers
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
# /proto-check
|
|
1
|
+
# /ct:proto-check
|
|
2
2
|
|
|
3
3
|
> Validate protobuf definitions for correctness, lint compliance, and backward compatibility.
|
|
4
4
|
|
|
5
5
|
**Type:** Command (slash command)
|
|
6
|
-
**Source:** [`
|
|
7
|
-
**Allowed Tools:** Bash, Read, Glob, Grep
|
|
6
|
+
**Source:** [`stacks/protobuf/commands/proto-check.md`](../stacks/protobuf/commands/proto-check.md) (installed only with the protobuf stack)
|
|
7
|
+
**Allowed Tools:** Bash (scoped to `buf`/`protoc` and build commands), Read, Glob, Grep
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
11
|
```
|
|
12
|
-
/proto-check
|
|
12
|
+
/ct:proto-check
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Workflow
|
package/docs/commands/ticket.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# /ticket
|
|
1
|
+
# /ct:ticket
|
|
2
2
|
|
|
3
3
|
> Work end-to-end on a ticket or issue: understand, explore, plan, implement, deliver.
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
11
|
```
|
|
12
|
-
/ticket [issue-number-or-description]
|
|
12
|
+
/ct:ticket [issue-number-or-description]
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Phases
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Systematic Debugging
|
|
2
2
|
|
|
3
|
-
> Four-phase methodology for diagnosing and fixing bugs efficiently without guesswork.
|
|
3
|
+
> Four-phase methodology for diagnosing and fixing bugs efficiently without guesswork. Use when investigating a bug, test failure, or unexpected behavior before proposing a fix
|
|
4
4
|
|
|
5
5
|
**Type:** Core Skill (always included)
|
|
6
6
|
**Source:** [`core/skills/ct-systematic-debugging/SKILL.md`](../core/skills/ct-systematic-debugging/SKILL.md)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Testing Patterns
|
|
2
2
|
|
|
3
|
-
> Generic test-driven development practices and patterns applicable to any language or test framework.
|
|
3
|
+
> Generic test-driven development practices and patterns applicable to any language or test framework. Use when writing tests, setting up a test suite, or deciding what to test at which layer
|
|
4
4
|
|
|
5
5
|
**Type:** Core Skill (always included)
|
|
6
6
|
**Source:** [`core/skills/ct-testing-patterns/SKILL.md`](../core/skills/ct-testing-patterns/SKILL.md)
|
|
@@ -11,77 +11,90 @@ Principles and patterns for writing tests that catch bugs, enable refactoring, a
|
|
|
11
11
|
|
|
12
12
|
## TDD Cycle: Red, Green, Refactor
|
|
13
13
|
|
|
14
|
-
1. **Red** -- Write a failing test
|
|
15
|
-
2. **Green** -- Write the minimal code to make
|
|
16
|
-
3. **Refactor** --
|
|
14
|
+
1. **Red** -- Write a failing test for the desired behavior. Confirm it fails for the right reason.
|
|
15
|
+
2. **Green** -- Write the minimal code to make it pass. No optimization yet.
|
|
16
|
+
3. **Refactor** -- Clean up while keeping tests green.
|
|
17
17
|
|
|
18
18
|
Commit at each stage. The cycle keeps scope small and provides a safety net for every change.
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## 3-Layer Testing Strategy
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
```
|
|
23
|
+
/ E2E \ Real browsers, full user flows
|
|
24
|
+
/----------\
|
|
25
|
+
/ Interaction \ Component sandbox, behavior, a11y
|
|
26
|
+
/----------------\
|
|
27
|
+
/ Unit \ Pure logic, signals, utilities
|
|
28
|
+
/--------------------\
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
| Layer | Target Ratio | What to Cover |
|
|
32
|
+
| ----------- | ------------ | ---------------------------------------------------------------------------- |
|
|
33
|
+
| Unit | ~70% | Business logic, utilities, data transforms, reactive primitives, error paths |
|
|
34
|
+
| Interaction | ~20% | Component variants, user interactions, accessibility, visual regression |
|
|
35
|
+
| E2E | ~10% | Critical user journeys, authentication flows, cross-page workflows |
|
|
23
36
|
|
|
24
|
-
|
|
37
|
+
> **Scope:** This core skill owns the layering decision below, the unit and interaction layers, and the cross-cutting E2E principles. Runner-specific E2E setup and execution live in the stack skills (e.g. `ct-playwright-patterns`) when a matching stack is installed.
|
|
25
38
|
|
|
26
|
-
|
|
27
|
-
- **Bad:** "calls `String.prototype.concat` with first name and space and last name"
|
|
39
|
+
### When to Use Which Layer
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
| Question | Layer |
|
|
42
|
+
| ------------------------------------------------- | -------------------------------------- |
|
|
43
|
+
| Does this logic need a DOM? | **Unit** if no, **Interaction** if yes |
|
|
44
|
+
| Does it involve multiple pages or navigation? | **E2E** |
|
|
45
|
+
| Am I testing a single component's visual states? | **Interaction** |
|
|
46
|
+
| Am I testing a reactive primitive (signal, memo)? | **Unit** |
|
|
47
|
+
| Does it require authentication or real network? | **E2E** |
|
|
48
|
+
| Am I testing component accessibility? | **Interaction** (axe-core) |
|
|
49
|
+
| Does it need the full server running? | **E2E** |
|
|
30
50
|
|
|
31
|
-
|
|
51
|
+
## Test Behavior, Not Implementation
|
|
52
|
+
|
|
53
|
+
Test _what_ code does (public interface, observable outputs), not _how_ (internal state, call counts). Implementation-coupled tests break on every refactor.
|
|
54
|
+
|
|
55
|
+
## Factory Pattern
|
|
32
56
|
|
|
33
57
|
```
|
|
34
58
|
function getMockUser(overrides = {}) {
|
|
35
|
-
return {
|
|
36
|
-
id: "user-1",
|
|
37
|
-
email: "test@example.com",
|
|
38
|
-
name: "Test User",
|
|
39
|
-
role: "member",
|
|
40
|
-
createdAt: new Date("2024-01-01"),
|
|
41
|
-
...overrides,
|
|
42
|
-
};
|
|
59
|
+
return { id: "user-1", email: "test@example.com", name: "Test User", role: "member", ...overrides };
|
|
43
60
|
}
|
|
44
|
-
|
|
45
|
-
// Usage: only specify what matters for this test
|
|
46
61
|
const admin = getMockUser({ role: "admin" });
|
|
47
62
|
```
|
|
48
63
|
|
|
49
|
-
|
|
64
|
+
New required fields update the factory once, not every test.
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
- **One test file per module** -- name it `module.test.ext` or `module.spec.ext`
|
|
53
|
-
- **Group related tests** using `describe` blocks
|
|
54
|
-
- **Use descriptive test names** that read as sentences
|
|
66
|
+
## Organization
|
|
55
67
|
|
|
56
|
-
|
|
68
|
+
- Co-locate tests or mirror source structure. One test file per module (`module.test.ext`).
|
|
69
|
+
- Group with `describe`, name as sentences: `it("rejects expired tokens")`.
|
|
57
70
|
|
|
58
|
-
|
|
59
|
-
- **Mock at boundaries** -- external services only, not internal modules
|
|
60
|
-
- **Keep mocks minimal** -- only mock the methods your code actually calls
|
|
61
|
-
- **Verify mock contracts** -- ensure mocks match real API behavior
|
|
62
|
-
- **Reset mocks between tests** -- prevent shared state and order-dependent failures
|
|
71
|
+
## Shared Principles
|
|
63
72
|
|
|
64
|
-
|
|
73
|
+
- **Prefer role-based queries.** Use `getByRole`, `getByLabel`, `getByText` over test IDs or CSS selectors.
|
|
74
|
+
- **Never sleep.** Use framework-provided waiting mechanisms (`waitFor`, `findBy*`, web-first assertions).
|
|
75
|
+
- **One assertion focus per test.** Multiple assertions are fine if they verify facets of the same behavior.
|
|
76
|
+
- **Isolate tests.** No test should depend on another test's side effects. Reset state between tests.
|
|
65
77
|
|
|
66
|
-
|
|
67
|
-
|---|---|---|---|
|
|
68
|
-
| **Unit tests** | Single function or class | Fast | Many |
|
|
69
|
-
| **Integration tests** | Multiple components together | Slower | Some |
|
|
70
|
-
| **End-to-end tests** | Full user flow | Slowest | Few |
|
|
78
|
+
## Mocking Rules
|
|
71
79
|
|
|
72
|
-
|
|
80
|
+
- Prefer real dependencies (in-memory DB, local server) when feasible.
|
|
81
|
+
- Mock at boundaries only (external APIs, email, payments), not internal modules.
|
|
82
|
+
- Keep mocks minimal -- only methods your code calls. Reset between tests.
|
|
83
|
+
- Verify mocks match the real API. Update when APIs change.
|
|
73
84
|
|
|
74
85
|
## Property-Based Testing
|
|
75
86
|
|
|
76
|
-
When a function has a contract ("for all valid inputs X, property Y holds"), use property-based tests to verify across generated inputs instead of hand-picked examples:
|
|
87
|
+
When a function has a contract ("for all valid inputs X, property Y holds"), use property-based tests to verify it across generated inputs instead of hand-picked examples:
|
|
77
88
|
|
|
78
89
|
```typescript
|
|
79
90
|
// Instead of testing 3-4 specific inputs:
|
|
80
91
|
test("sort is idempotent", () => {
|
|
81
|
-
fc.assert(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
fc.assert(
|
|
93
|
+
fc.property(fc.array(fc.integer()), (arr) => {
|
|
94
|
+
const sorted = mySort(arr);
|
|
95
|
+
expect(mySort(sorted)).toEqual(sorted);
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
85
98
|
});
|
|
86
99
|
```
|
|
87
100
|
|
|
@@ -89,7 +102,7 @@ Good candidates: serialization round-trips, math properties, parsers, encoding/d
|
|
|
89
102
|
|
|
90
103
|
## Bun Test Runner
|
|
91
104
|
|
|
92
|
-
Bun includes a built-in test runner
|
|
105
|
+
Bun includes a built-in test runner. Use `bun test` for projects on the Bun runtime:
|
|
93
106
|
|
|
94
107
|
```bash
|
|
95
108
|
bun test # run all *.test.ts files
|
|
@@ -98,21 +111,30 @@ bun test --coverage # with code coverage
|
|
|
98
111
|
bun test path/to/file.test.ts # single file
|
|
99
112
|
```
|
|
100
113
|
|
|
101
|
-
|
|
114
|
+
Bun supports `describe`, `it`/`test`, `expect`, lifecycle hooks, and snapshot testing out of the box with no additional dependencies.
|
|
115
|
+
|
|
116
|
+
## Test Speed
|
|
117
|
+
|
|
118
|
+
Three levers recur across common runners (Vitest, Playwright, Storybook browser mode). Stated once here; each stack skill carries the framework-specific syntax.
|
|
119
|
+
|
|
120
|
+
- **Parallelism sized to the runner.** Enable file-level parallelism (Vitest `fileParallelism`, Playwright `fullyParallel`), but cap workers to the runner's _real_ vCPUs (`"50%"` or a measured count). GitHub standard runners are 2 vCPU (private) / 4 (public); oversubscribing thrashes.
|
|
121
|
+
- **Shard across CI jobs, then merge the blob reports.** Sharding splits at the _file_ level (`--shard=i/n`), so wall-clock is gated by the slowest shard -- balance file sizes. Always emit a blob report per shard (`--reporter=blob`) and merge it (`merge-reports` / `--merge-reports`) in a dependent job, or results and coverage are fragmented and incomplete.
|
|
122
|
+
- **Skip isolation where state is clean.** Per-file environment isolation is the safe default but the biggest run-speed cost. Disable it (Vitest `isolate: false`, `pool: 'threads'`) only for side-effect-free logic suites; keep it where tests mutate globals/env/timers.
|
|
123
|
+
|
|
124
|
+
Profile before tuning, and never `sleep` to mask timing -- use the framework's auto-waiting (see Shared Principles).
|
|
125
|
+
|
|
126
|
+
Per-runner config (if the stack is installed): `ct-vite-vitest-patterns`, `ct-playwright-patterns`, `ct-storybook-patterns`.
|
|
102
127
|
|
|
103
|
-
## Anti-
|
|
128
|
+
## Anti-Patterns
|
|
104
129
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
| **Ignoring flaky tests** | A sometimes-failing test is either wrong or exposing a real bug. Fix or delete it. |
|
|
112
|
-
| **Testing only the happy path** | Error cases, edge cases, and boundary conditions are where bugs live. |
|
|
130
|
+
1. **Testing implementation** -- Asserting internal state or call counts breaks on refactors.
|
|
131
|
+
2. **Overmocking** -- If most of the test is mock setup, you're testing mocks.
|
|
132
|
+
3. **Copy-paste tests** -- Use factories and parameterized tests.
|
|
133
|
+
4. **No assertions** -- Worse than no test. False confidence.
|
|
134
|
+
5. **Ignoring flaky tests** -- Fix or delete; never skip indefinitely.
|
|
135
|
+
6. **Happy path only** -- Error cases and boundary conditions are where bugs live.
|
|
113
136
|
|
|
114
137
|
## Trigger Conditions
|
|
115
138
|
|
|
116
139
|
- **Keywords:** `test`, `spec`, `tdd`, `mock`, `factory`
|
|
117
140
|
- **File patterns:** `**/*.test.ts`, `**/*.spec.ts`
|
|
118
|
-
- **Excludes:** "e2e", "end-to-end"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TypeScript Conventions
|
|
2
2
|
|
|
3
|
-
> Strict TypeScript patterns for type safety, readability, and maintainable codebases.
|
|
3
|
+
> Strict TypeScript patterns for type safety, readability, and maintainable codebases. Use when writing or reviewing TypeScript, adding or tightening types, or deciding between type and interface
|
|
4
4
|
|
|
5
5
|
**Type:** Core Skill (always included)
|
|
6
6
|
**Source:** [`core/skills/ct-typescript-conventions/SKILL.md`](../core/skills/ct-typescript-conventions/SKILL.md)
|
|
@@ -36,21 +36,29 @@ Never use `any`. It disables type checking entirely.
|
|
|
36
36
|
- Use generics when the type varies but has a consistent shape
|
|
37
37
|
- Use specific types when you know the data shape
|
|
38
38
|
|
|
39
|
-
###
|
|
39
|
+
### Type vs Interface
|
|
40
40
|
|
|
41
|
-
- **
|
|
42
|
-
- **Use `
|
|
41
|
+
- **Default to `type`.** It covers object shapes, unions, intersections, mapped types, and utility types.
|
|
42
|
+
- **Use `interface` only when you need `extends`** (an inheritance hierarchy or declaration merging).
|
|
43
43
|
|
|
44
44
|
```typescript
|
|
45
|
-
//
|
|
46
|
-
|
|
45
|
+
// Default: use type for object shapes
|
|
46
|
+
type User = {
|
|
47
47
|
id: string;
|
|
48
48
|
email: string;
|
|
49
49
|
role: UserRole;
|
|
50
|
-
}
|
|
50
|
+
};
|
|
51
51
|
|
|
52
|
-
//
|
|
52
|
+
// Unions, intersections, utilities: type
|
|
53
53
|
type UserRole = "admin" | "member" | "guest";
|
|
54
|
+
|
|
55
|
+
// interface only when you need extends
|
|
56
|
+
interface Animal {
|
|
57
|
+
name: string;
|
|
58
|
+
}
|
|
59
|
+
interface Dog extends Animal {
|
|
60
|
+
breed: string;
|
|
61
|
+
}
|
|
54
62
|
```
|
|
55
63
|
|
|
56
64
|
### `as const` for Literal Types
|
|
@@ -96,7 +104,7 @@ type AsyncState<T> =
|
|
|
96
104
|
|
|
97
105
|
### `satisfies` Operator
|
|
98
106
|
|
|
99
|
-
Validate a value conforms to a type
|
|
107
|
+
Validate a value conforms to a type while keeping the value's own narrower inferred type instead of collapsing to the annotation. Here it preserves the exact key set (`home`, `user`) rather than the index signature `Record<string, Route>`:
|
|
100
108
|
|
|
101
109
|
```typescript
|
|
102
110
|
type Route = { path: string; children?: Route[] };
|
|
@@ -106,7 +114,9 @@ const routes = {
|
|
|
106
114
|
user: { path: "/user/:id", children: [{ path: "settings" }] },
|
|
107
115
|
} satisfies Record<string, Route>;
|
|
108
116
|
|
|
109
|
-
// routes.home.
|
|
117
|
+
// routes.home and routes.user are known keys -- not `Route | undefined` from the index signature.
|
|
118
|
+
// Note: routes.home.path is `string`, NOT the literal "/", because `Route` declares `path: string`,
|
|
119
|
+
// which widens the literal. To keep a literal, target a narrower type (e.g. a union) or add `as const`.
|
|
110
120
|
```
|
|
111
121
|
|
|
112
122
|
### `const` Type Parameters
|
|
@@ -115,6 +125,9 @@ Infer literal types from arguments without requiring callers to write `as const`
|
|
|
115
125
|
|
|
116
126
|
```typescript
|
|
117
127
|
function createConfig<const T extends readonly string[]>(names: T): Record<T[number], boolean> {
|
|
128
|
+
// `Object.fromEntries` is typed to return a wide `Record<string, boolean>`, so a single
|
|
129
|
+
// localized `as` at a generic helper's return boundary is acceptable here -- it keeps the
|
|
130
|
+
// public signature precise. This is the narrow exception to the "no `as` casts" anti-pattern.
|
|
118
131
|
return Object.fromEntries(names.map(n => [n, false])) as Record<T[number], boolean>;
|
|
119
132
|
}
|
|
120
133
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Verification Before Completion
|
|
2
2
|
|
|
3
|
-
> Evidence-based completion claims -- never say "done" without proof that the work is correct.
|
|
3
|
+
> Evidence-based completion claims -- never say "done" without proof that the work is correct. Use when about to claim a task is done, fixed, or passing, or before committing or opening a PR
|
|
4
4
|
|
|
5
5
|
**Type:** Core Skill (always included)
|
|
6
6
|
**Source:** [`core/skills/ct-verification-before-completion/SKILL.md`](../core/skills/ct-verification-before-completion/SKILL.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-toolkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Reusable Claude Code configuration toolkit with stack-specific connectors",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
"typecheck": "tsc --noEmit",
|
|
26
26
|
"lint": "biome check --write",
|
|
27
27
|
"lint:check": "biome check",
|
|
28
|
+
"test": "bun test",
|
|
29
|
+
"postinstall": "bun bin/postinstall.mjs || node bin/postinstall.mjs || exit 0",
|
|
28
30
|
"prepare": "npx husky"
|
|
29
31
|
},
|
|
30
32
|
"lint-staged": {
|