codecruise 0.1.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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/bin/codecruise.js +68 -0
  4. package/config/CLAUDE.md +107 -0
  5. package/config/agents/analyst.md +48 -0
  6. package/config/agents/architect-reviewer.md +161 -0
  7. package/config/agents/architect.md +119 -0
  8. package/config/agents/critic.md +63 -0
  9. package/config/agents/developer.md +96 -0
  10. package/config/agents/devops.md +81 -0
  11. package/config/agents/orchestrator.md +91 -0
  12. package/config/agents/planner.md +139 -0
  13. package/config/agents/retro.md +52 -0
  14. package/config/agents/reviewer.md +101 -0
  15. package/config/agents/security-reviewer.md +57 -0
  16. package/config/agents/stack/expo/AGENT.md +473 -0
  17. package/config/agents/stack/expo/rules/critical.md +427 -0
  18. package/config/agents/stack/expo/rules/native.md +455 -0
  19. package/config/agents/stack/expo/rules/navigation.md +445 -0
  20. package/config/agents/stack/expo/rules/performance.md +415 -0
  21. package/config/agents/stack/fastify/AGENT.md +397 -0
  22. package/config/agents/stack/fastify/rules/api-design.md +283 -0
  23. package/config/agents/stack/fastify/rules/critical.md +232 -0
  24. package/config/agents/stack/fastify/rules/queues.md +303 -0
  25. package/config/agents/stack/fastify/rules/security.md +384 -0
  26. package/config/agents/stack/index.yaml +48 -0
  27. package/config/agents/stack/nextjs/AGENT.md +421 -0
  28. package/config/agents/stack/nextjs/rules/components.md +413 -0
  29. package/config/agents/stack/nextjs/rules/critical.md +391 -0
  30. package/config/agents/stack/nextjs/rules/performance.md +403 -0
  31. package/config/agents/stack/nextjs/rules/styling.md +334 -0
  32. package/config/agents/stack/shared-ts/AGENT.md +384 -0
  33. package/config/agents/stack/shared-ts/rules/critical.md +315 -0
  34. package/config/agents/stack/shared-ts/rules/patterns.md +384 -0
  35. package/config/agents/stack/shared-ts/rules/zod.md +427 -0
  36. package/config/agents/tester.md +79 -0
  37. package/config/commands/architect-discuss.md +366 -0
  38. package/config/commands/architect-list.md +160 -0
  39. package/config/commands/architect-review.md +111 -0
  40. package/config/commands/architect.md +118 -0
  41. package/config/commands/compact.md +118 -0
  42. package/config/commands/companion.md +279 -0
  43. package/config/commands/dashboard.md +152 -0
  44. package/config/commands/doctor.md +227 -0
  45. package/config/commands/dogfood-report.md +101 -0
  46. package/config/commands/flags/run-autonomous.md +110 -0
  47. package/config/commands/flags/run-pause.md +80 -0
  48. package/config/commands/ingest.md +173 -0
  49. package/config/commands/init.md +128 -0
  50. package/config/commands/metrics.md +87 -0
  51. package/config/commands/parallel.md +320 -0
  52. package/config/commands/pause.md +55 -0
  53. package/config/commands/plan-review.md +130 -0
  54. package/config/commands/plan.md +216 -0
  55. package/config/commands/production-check.md +308 -0
  56. package/config/commands/refine.md +323 -0
  57. package/config/commands/resume.md +72 -0
  58. package/config/commands/retro.md +121 -0
  59. package/config/commands/retry.md +75 -0
  60. package/config/commands/role.md +310 -0
  61. package/config/commands/run.md +417 -0
  62. package/config/commands/scope.md +85 -0
  63. package/config/commands/setup-permissions.md +104 -0
  64. package/config/commands/skip.md +75 -0
  65. package/config/commands/spec-forge.md +213 -0
  66. package/config/commands/spec-help.md +194 -0
  67. package/config/commands/spec-patch.md +342 -0
  68. package/config/commands/spec-resolve.md +110 -0
  69. package/config/commands/spec-review.md +153 -0
  70. package/config/commands/status.md +114 -0
  71. package/config/commands/sync.md +131 -0
  72. package/config/commands/task.md +138 -0
  73. package/config/commands/verify.md +124 -0
  74. package/config/hooks/README.md +632 -0
  75. package/config/hooks/activity-log.sh +187 -0
  76. package/config/hooks/anti-rationalize.sh +52 -0
  77. package/config/hooks/capture-verification.sh +112 -0
  78. package/config/hooks/collect-metrics.sh +135 -0
  79. package/config/hooks/enforce-file-scope.sh +75 -0
  80. package/config/hooks/enforce-state-machine.sh +161 -0
  81. package/config/hooks/enforce-tdd.sh +180 -0
  82. package/config/hooks/format.sh +40 -0
  83. package/config/hooks/lib/activity-helpers.sh +162 -0
  84. package/config/hooks/lib/read-settings.sh +71 -0
  85. package/config/hooks/load-context-skills.sh +95 -0
  86. package/config/hooks/notify.sh +81 -0
  87. package/config/hooks/pre-commit.sample +35 -0
  88. package/config/hooks/protect-files.sh +63 -0
  89. package/config/hooks/track-agents.sh +41 -0
  90. package/config/hooks/track-commands.sh +37 -0
  91. package/config/hooks/track-enforcement.sh +44 -0
  92. package/config/hooks/track-ooda.sh +77 -0
  93. package/config/hooks/validate-commit-msg.sh +35 -0
  94. package/config/hooks/validate-plan.sh +213 -0
  95. package/config/hooks/verify-criteria.sh +46 -0
  96. package/config/hooks/verify-todo-completion.sh +140 -0
  97. package/config/rules/comments.md +25 -0
  98. package/config/rules/decision-rules.md +308 -0
  99. package/config/rules/hygiene.md +247 -0
  100. package/config/rules/pattern-detection.md +372 -0
  101. package/config/rules/profiles.md +193 -0
  102. package/config/rules/recovery.md +83 -0
  103. package/config/rules/scope-detection.md +213 -0
  104. package/config/rules/standards.md +127 -0
  105. package/config/rules/workflow.md +121 -0
  106. package/config/schemas.md +767 -0
  107. package/config/settings.json +195 -0
  108. package/config/skills/backend/SKILL.md +734 -0
  109. package/config/skills/database/SKILL.md +426 -0
  110. package/config/skills/frontend/SKILL.md +434 -0
  111. package/config/skills/git/SKILL.md +396 -0
  112. package/config/skills/index.yaml +36 -0
  113. package/config/skills/observability/SKILL.md +430 -0
  114. package/config/skills/package-dev/SKILL.md +498 -0
  115. package/config/skills/performance/SKILL.md +378 -0
  116. package/config/skills/resilience/SKILL.md +573 -0
  117. package/config/skills/testing/SKILL.md +398 -0
  118. package/config/skills/testing-patterns/SKILL.md +276 -0
  119. package/config/skills/typescript/SKILL.md +152 -0
  120. package/config/templates/CLAUDE.md +70 -0
  121. package/config/templates/README.md +117 -0
  122. package/config/templates/steering/adr-template.md +102 -0
  123. package/config/templates/steering/product.md +60 -0
  124. package/config/templates/steering/rfc-template.md +159 -0
  125. package/config/templates/steering/structure.md +146 -0
  126. package/config/templates/steering/tech.md +85 -0
  127. package/package.json +40 -0
  128. package/src/install.js +163 -0
  129. package/src/report.js +310 -0
@@ -0,0 +1,427 @@
1
+ # Zod Schema Patterns
2
+
3
+ Runtime validation with type inference.
4
+
5
+ ---
6
+
7
+ ## Schema Basics
8
+
9
+ ### ZOD-001: Define base schemas
10
+
11
+ ```typescript
12
+ import { z } from 'zod';
13
+
14
+ // Primitives
15
+ const stringSchema = z.string();
16
+ const numberSchema = z.number();
17
+ const booleanSchema = z.boolean();
18
+ const dateSchema = z.date();
19
+
20
+ // With constraints
21
+ const emailSchema = z.string().email();
22
+ const positiveSchema = z.number().positive();
23
+ const nonEmptySchema = z.string().min(1);
24
+
25
+ // Optional and nullable
26
+ const optionalSchema = z.string().optional(); // string | undefined
27
+ const nullableSchema = z.string().nullable(); // string | null
28
+ const nullishSchema = z.string().nullish(); // string | null | undefined
29
+ ```
30
+
31
+ ### ZOD-002: Use coercion for form data
32
+
33
+ ```typescript
34
+ // Coerce strings to proper types
35
+ const formSchema = z.object({
36
+ age: z.coerce.number().int().min(0).max(150),
37
+ birthDate: z.coerce.date(),
38
+ isActive: z.coerce.boolean(),
39
+ price: z.coerce.number().positive(),
40
+ });
41
+
42
+ // Handles: "25" -> 25, "true" -> true, "2024-01-01" -> Date
43
+ const data = formSchema.parse({
44
+ age: '25',
45
+ birthDate: '2024-01-01',
46
+ isActive: 'true',
47
+ price: '99.99',
48
+ });
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Object Schemas
54
+
55
+ ### ZOD-003: Compose object schemas
56
+
57
+ ```typescript
58
+ // Base schema
59
+ const baseEntitySchema = z.object({
60
+ id: z.string().cuid(),
61
+ createdAt: z.coerce.date(),
62
+ updatedAt: z.coerce.date(),
63
+ });
64
+
65
+ // Extended schema
66
+ const userSchema = baseEntitySchema.extend({
67
+ email: z.string().email().toLowerCase(),
68
+ name: z.string().min(2).max(100),
69
+ role: z.enum(['USER', 'ADMIN']),
70
+ });
71
+
72
+ // Merge schemas
73
+ const fullUserSchema = userSchema.merge(
74
+ z.object({
75
+ profile: z.object({
76
+ bio: z.string().optional(),
77
+ avatar: z.string().url().optional(),
78
+ }),
79
+ })
80
+ );
81
+ ```
82
+
83
+ ### ZOD-004: Create input/output schemas
84
+
85
+ ```typescript
86
+ // Full entity (from database)
87
+ const userSchema = z.object({
88
+ id: z.string().cuid(),
89
+ email: z.string().email(),
90
+ password: z.string(),
91
+ name: z.string(),
92
+ createdAt: z.date(),
93
+ });
94
+
95
+ // Create input (no id, no timestamps)
96
+ const createUserSchema = userSchema.omit({
97
+ id: true,
98
+ createdAt: true,
99
+ });
100
+
101
+ // Update input (all optional except id)
102
+ const updateUserSchema = userSchema
103
+ .partial()
104
+ .required({ id: true });
105
+
106
+ // Public output (no password)
107
+ const publicUserSchema = userSchema.omit({
108
+ password: true,
109
+ });
110
+
111
+ // Types
112
+ type User = z.infer<typeof userSchema>;
113
+ type CreateUser = z.infer<typeof createUserSchema>;
114
+ type UpdateUser = z.infer<typeof updateUserSchema>;
115
+ type PublicUser = z.infer<typeof publicUserSchema>;
116
+ ```
117
+
118
+ ---
119
+
120
+ ## Transforms
121
+
122
+ ### ZOD-005: Normalize input with transforms
123
+
124
+ ```typescript
125
+ const userInputSchema = z.object({
126
+ // Normalize email
127
+ email: z
128
+ .string()
129
+ .email()
130
+ .toLowerCase()
131
+ .trim(),
132
+
133
+ // Normalize whitespace in name
134
+ name: z
135
+ .string()
136
+ .trim()
137
+ .transform(s => s.replace(/\s+/g, ' ')),
138
+
139
+ // Extract digits from phone
140
+ phone: z
141
+ .string()
142
+ .optional()
143
+ .transform(s => s?.replace(/\D/g, '')),
144
+
145
+ // Parse tags from comma-separated string
146
+ tags: z
147
+ .string()
148
+ .transform(s => s.split(',').map(t => t.trim()).filter(Boolean)),
149
+ });
150
+ ```
151
+
152
+ ### ZOD-006: Transform to domain types
153
+
154
+ ```typescript
155
+ // Transform to branded types
156
+ const userIdSchema = z.string().cuid().transform(id => id as UserId);
157
+
158
+ // Transform to class instance
159
+ const dateRangeSchema = z
160
+ .object({
161
+ start: z.coerce.date(),
162
+ end: z.coerce.date(),
163
+ })
164
+ .transform(({ start, end }) => new DateRange(start, end));
165
+
166
+ // Transform with validation
167
+ const positiveIntSchema = z
168
+ .number()
169
+ .transform((n, ctx) => {
170
+ const int = Math.floor(n);
171
+ if (int <= 0) {
172
+ ctx.addIssue({
173
+ code: z.ZodIssueCode.custom,
174
+ message: 'Must be positive integer',
175
+ });
176
+ return z.NEVER;
177
+ }
178
+ return int;
179
+ });
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Refinements
185
+
186
+ ### ZOD-007: Add custom validation
187
+
188
+ ```typescript
189
+ // Single field refinement
190
+ const passwordSchema = z
191
+ .string()
192
+ .min(8)
193
+ .refine(
194
+ (password) => /[A-Z]/.test(password),
195
+ { message: 'Must contain uppercase letter' }
196
+ )
197
+ .refine(
198
+ (password) => /[0-9]/.test(password),
199
+ { message: 'Must contain number' }
200
+ );
201
+
202
+ // Object-level refinement
203
+ const dateRangeSchema = z
204
+ .object({
205
+ startDate: z.coerce.date(),
206
+ endDate: z.coerce.date(),
207
+ })
208
+ .refine(
209
+ (data) => data.endDate > data.startDate,
210
+ {
211
+ message: 'End date must be after start date',
212
+ path: ['endDate'],
213
+ }
214
+ );
215
+ ```
216
+
217
+ ### ZOD-008: Use superRefine for complex validation
218
+
219
+ ```typescript
220
+ const registrationSchema = z
221
+ .object({
222
+ password: z.string().min(8),
223
+ confirmPassword: z.string(),
224
+ email: z.string().email(),
225
+ })
226
+ .superRefine((data, ctx) => {
227
+ if (data.password !== data.confirmPassword) {
228
+ ctx.addIssue({
229
+ code: z.ZodIssueCode.custom,
230
+ message: 'Passwords must match',
231
+ path: ['confirmPassword'],
232
+ });
233
+ }
234
+
235
+ if (data.password.toLowerCase().includes(data.email.split('@')[0])) {
236
+ ctx.addIssue({
237
+ code: z.ZodIssueCode.custom,
238
+ message: 'Password cannot contain email',
239
+ path: ['password'],
240
+ });
241
+ }
242
+ });
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Unions & Discriminated Unions
248
+
249
+ ### ZOD-009: Use discriminated unions
250
+
251
+ ```typescript
252
+ // Event types
253
+ const eventSchema = z.discriminatedUnion('type', [
254
+ z.object({
255
+ type: z.literal('USER_CREATED'),
256
+ userId: z.string(),
257
+ email: z.string().email(),
258
+ }),
259
+ z.object({
260
+ type: z.literal('USER_UPDATED'),
261
+ userId: z.string(),
262
+ changes: z.record(z.unknown()),
263
+ }),
264
+ z.object({
265
+ type: z.literal('USER_DELETED'),
266
+ userId: z.string(),
267
+ deletedAt: z.date(),
268
+ }),
269
+ ]);
270
+
271
+ type Event = z.infer<typeof eventSchema>;
272
+ // Properly typed discriminated union
273
+ ```
274
+
275
+ ### ZOD-010: Handle multiple valid shapes
276
+
277
+ ```typescript
278
+ // Config that can be string or object
279
+ const configSchema = z.union([
280
+ z.string(), // Simple string value
281
+ z.object({
282
+ value: z.string(),
283
+ options: z.object({
284
+ required: z.boolean().default(false),
285
+ maxLength: z.number().optional(),
286
+ }),
287
+ }),
288
+ ]);
289
+
290
+ // Normalize to object
291
+ const normalizedConfigSchema = configSchema.transform((config) => {
292
+ if (typeof config === 'string') {
293
+ return { value: config, options: { required: false } };
294
+ }
295
+ return config;
296
+ });
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Error Handling
302
+
303
+ ### ZOD-011: Format errors for API responses
304
+
305
+ ```typescript
306
+ import { ZodError, ZodIssue } from 'zod';
307
+
308
+ interface FieldError {
309
+ field: string;
310
+ message: string;
311
+ code: string;
312
+ }
313
+
314
+ function formatZodError(error: ZodError): FieldError[] {
315
+ return error.issues.map((issue: ZodIssue) => ({
316
+ field: issue.path.join('.'),
317
+ message: issue.message,
318
+ code: issue.code,
319
+ }));
320
+ }
321
+
322
+ // Usage
323
+ try {
324
+ userSchema.parse(input);
325
+ } catch (e) {
326
+ if (e instanceof ZodError) {
327
+ return {
328
+ error: {
329
+ code: 'VALIDATION_ERROR',
330
+ message: 'Invalid input',
331
+ details: formatZodError(e),
332
+ },
333
+ };
334
+ }
335
+ throw e;
336
+ }
337
+ ```
338
+
339
+ ### ZOD-012: Use safeParse for non-throwing validation
340
+
341
+ ```typescript
342
+ // safeParse returns Result-like object
343
+ const result = userSchema.safeParse(input);
344
+
345
+ if (result.success) {
346
+ const user = result.data; // Typed as User
347
+ await saveUser(user);
348
+ } else {
349
+ const errors = formatZodError(result.error);
350
+ return { error: { code: 'VALIDATION_ERROR', details: errors } };
351
+ }
352
+
353
+ // Async validation
354
+ const asyncResult = await asyncSchema.safeParseAsync(input);
355
+ ```
356
+
357
+ ---
358
+
359
+ ## Integration Patterns
360
+
361
+ ### ZOD-013: Convert to JSON Schema (Fastify/OpenAPI)
362
+
363
+ ```typescript
364
+ import { zodToJsonSchema } from 'zod-to-json-schema';
365
+
366
+ const userSchema = z.object({
367
+ id: z.string().cuid(),
368
+ email: z.string().email(),
369
+ name: z.string().min(2),
370
+ });
371
+
372
+ // For Fastify route schema
373
+ const routeSchema = {
374
+ body: zodToJsonSchema(createUserSchema),
375
+ response: {
376
+ 200: zodToJsonSchema(userSchema),
377
+ 400: zodToJsonSchema(errorSchema),
378
+ },
379
+ };
380
+ ```
381
+
382
+ ### ZOD-014: Environment validation
383
+
384
+ ```typescript
385
+ const envSchema = z.object({
386
+ NODE_ENV: z.enum(['development', 'test', 'production']),
387
+ PORT: z.coerce.number().default(3000),
388
+ DATABASE_URL: z.string().url(),
389
+ REDIS_URL: z.string().url(),
390
+ JWT_SECRET: z.string().min(32),
391
+ LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
392
+ });
393
+
394
+ // Validate at startup
395
+ export const env = envSchema.parse(process.env);
396
+
397
+ // Type-safe access
398
+ console.log(env.PORT); // number
399
+ console.log(env.NODE_ENV); // 'development' | 'test' | 'production'
400
+ ```
401
+
402
+ ### ZOD-015: Form validation (React Hook Form)
403
+
404
+ ```typescript
405
+ import { zodResolver } from '@hookform/resolvers/zod';
406
+ import { useForm } from 'react-hook-form';
407
+
408
+ const formSchema = z.object({
409
+ email: z.string().email('Invalid email'),
410
+ password: z.string().min(8, 'At least 8 characters'),
411
+ });
412
+
413
+ type FormData = z.infer<typeof formSchema>;
414
+
415
+ function LoginForm() {
416
+ const { register, handleSubmit, formState: { errors } } = useForm<FormData>({
417
+ resolver: zodResolver(formSchema),
418
+ });
419
+
420
+ return (
421
+ <form onSubmit={handleSubmit(onSubmit)}>
422
+ <input {...register('email')} />
423
+ {errors.email && <span>{errors.email.message}</span>}
424
+ </form>
425
+ );
426
+ }
427
+ ```
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: tester
3
+ description: Write and run tests. Use for testing features or validating implementations.
4
+ tools: Read, Write, Edit, Bash, Glob, Grep
5
+ model: haiku
6
+ ---
7
+
8
+ # Tester Agent
9
+
10
+ Write integration and e2e tests. Verify implementations.
11
+
12
+ ## Test Types
13
+
14
+ | Type | Purpose | Speed | When |
15
+ |------|---------|-------|------|
16
+ | Unit | Individual functions | Fast | Business logic |
17
+ | Integration | Component interactions, APIs, DB | Medium | API endpoints, services |
18
+ | E2E | Complete user flows | Slow | Critical paths only |
19
+
20
+ ## Principles
21
+
22
+ 1. **Deterministic** — Same input → same result (no timing deps)
23
+ 2. **Independent** — No order dependency between tests
24
+ 3. **Focused** — One behavior per test
25
+ 4. **Readable** — Test name describes scenario
26
+
27
+ ## Test Structure
28
+
29
+ ```
30
+ describe: Feature or component
31
+ describe: Scenario or condition
32
+ it: should + expected behavior
33
+ ```
34
+
35
+ **Pattern**: Arrange → Act → Assert
36
+
37
+ ## Coverage Priority
38
+
39
+ 1. **Happy path** — Main success scenario
40
+ 2. **Error cases** — Validation, network, auth failures
41
+ 3. **Edge cases** — Empty, null, boundary values
42
+ 4. **Security cases** — Auth bypass, injection
43
+
44
+ ## Mocking Decisions
45
+
46
+ | Dependency | Mock? | Why |
47
+ |------------|-------|-----|
48
+ | External APIs | Yes | Unreliable, slow, costs |
49
+ | Time/Date | Yes | Determinism |
50
+ | Database | Integration: No, Unit: Yes | Reality vs speed |
51
+ | File system | Usually Yes | Speed |
52
+ | Internal modules | No | Test real behavior |
53
+
54
+ ## Anti-Patterns to Avoid
55
+
56
+ - ❌ Testing implementation details (test behavior, not internals)
57
+ - ❌ Flaky tests (timing-dependent, order-dependent)
58
+ - ❌ Over-mocking (testing mocks, not code)
59
+ - ❌ Duplicate coverage
60
+ - ❌ Testing third-party code
61
+
62
+ ## Quality Checklist
63
+
64
+ - [ ] Tests cover acceptance criteria
65
+ - [ ] Tests are meaningful (not just coverage)
66
+ - [ ] Edge cases considered
67
+ - [ ] Error cases tested
68
+ - [ ] No flaky tests
69
+ - [ ] Factories for test data (not inline objects)
70
+ - [ ] Mocks only for external deps
71
+
72
+ ## Output
73
+
74
+ ```
75
+ ✓ Tests: {path}
76
+ ✓ should {case 1}
77
+ ✓ should {case 2}
78
+ Coverage: X% (if available)
79
+ ```