@orchestrator-claude/definitions 3.5.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 (73) hide show
  1. package/agents/api-extractor.md +687 -0
  2. package/agents/business-rule-miner.md +754 -0
  3. package/agents/code-archaeologist.md +720 -0
  4. package/agents/docs-guardian.md +524 -0
  5. package/agents/implementer.md +512 -0
  6. package/agents/legacy-discoverer.md +583 -0
  7. package/agents/legacy-synthesizer.md +1101 -0
  8. package/agents/orchestrator.md +165 -0
  9. package/agents/planner.md +365 -0
  10. package/agents/researcher.md +447 -0
  11. package/agents/reviewer.md +514 -0
  12. package/agents/schema-extractor.md +781 -0
  13. package/agents/specifier.md +360 -0
  14. package/agents/task-generator.md +390 -0
  15. package/bin/orch-defs.js +2 -0
  16. package/dist/cli.d.ts +3 -0
  17. package/dist/cli.d.ts.map +1 -0
  18. package/dist/cli.js +172 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/commands/DiffCommand.d.ts +13 -0
  21. package/dist/commands/DiffCommand.d.ts.map +1 -0
  22. package/dist/commands/DiffCommand.js +74 -0
  23. package/dist/commands/DiffCommand.js.map +1 -0
  24. package/dist/commands/SeedCommand.d.ts +19 -0
  25. package/dist/commands/SeedCommand.d.ts.map +1 -0
  26. package/dist/commands/SeedCommand.js +56 -0
  27. package/dist/commands/SeedCommand.js.map +1 -0
  28. package/dist/http/ApiClient.d.ts +50 -0
  29. package/dist/http/ApiClient.d.ts.map +1 -0
  30. package/dist/http/ApiClient.js +58 -0
  31. package/dist/http/ApiClient.js.map +1 -0
  32. package/dist/index.d.ts +12 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +11 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/manifest/ManifestLoader.d.ts +34 -0
  37. package/dist/manifest/ManifestLoader.d.ts.map +1 -0
  38. package/dist/manifest/ManifestLoader.js +110 -0
  39. package/dist/manifest/ManifestLoader.js.map +1 -0
  40. package/dist/manifest/types.d.ts +59 -0
  41. package/dist/manifest/types.d.ts.map +1 -0
  42. package/dist/manifest/types.js +5 -0
  43. package/dist/manifest/types.js.map +1 -0
  44. package/dist/scripts/generate-manifest.d.ts +10 -0
  45. package/dist/scripts/generate-manifest.d.ts.map +1 -0
  46. package/dist/scripts/generate-manifest.js +114 -0
  47. package/dist/scripts/generate-manifest.js.map +1 -0
  48. package/hooks/post-agent-artifact-relay.sh +157 -0
  49. package/hooks/post-artifact-generate.sh +39 -0
  50. package/hooks/post-implement-validate.sh +139 -0
  51. package/hooks/post-phase-checkpoint.sh +322 -0
  52. package/hooks/pre-agent-invoke.sh +34 -0
  53. package/hooks/pre-phase-advance.sh +40 -0
  54. package/hooks/track-agent-invocation.sh +241 -0
  55. package/kb/auth-strategies.md +742 -0
  56. package/kb/docs-constitution.md +310 -0
  57. package/kb/error-handling.md +555 -0
  58. package/kb/rest-conventions.md +458 -0
  59. package/kb/validation-patterns.md +589 -0
  60. package/manifest.json +314 -0
  61. package/package.json +65 -0
  62. package/skills/artifact-validator/SKILL.md +226 -0
  63. package/skills/docs-guardian/SKILL.md +230 -0
  64. package/skills/kb-lookup/SKILL.md +257 -0
  65. package/skills/phase-gate-evaluator/SKILL.md +274 -0
  66. package/skills/release/SKILL.md +239 -0
  67. package/skills/release/release.sh +491 -0
  68. package/skills/smoke-test/SKILL.md +195 -0
  69. package/skills/workflow-status/SKILL.md +322 -0
  70. package/workflows/bug-fix.json +74 -0
  71. package/workflows/feature-development.json +88 -0
  72. package/workflows/legacy-analysis.json +304 -0
  73. package/workflows/refactoring.json +74 -0
@@ -0,0 +1,555 @@
1
+ ---
2
+ title: "Error Handling Patterns"
3
+ category: "patterns"
4
+ tier: "foundational"
5
+ tags: ["api", "errors", "express", "middleware"]
6
+ template: "api"
7
+ ---
8
+
9
+ # Error Handling Patterns
10
+
11
+ ## Overview
12
+
13
+ This document defines error handling patterns and strategies for building robust, maintainable REST APIs with consistent error responses.
14
+
15
+ **Project**: my-project
16
+ **Template**: api
17
+
18
+ ---
19
+
20
+ ## 1. Error Response Format
21
+
22
+ ### Standard Error Structure
23
+
24
+ All API errors MUST follow this consistent format:
25
+
26
+ ```typescript
27
+ interface ErrorResponse {
28
+ error: string; // Error type/name
29
+ message: string; // Human-readable message
30
+ details?: unknown; // Optional additional context
31
+ timestamp: string; // ISO 8601 timestamp
32
+ path: string; // Request path
33
+ requestId?: string; // Request ID for tracing
34
+ }
35
+ ```
36
+
37
+ ### Example
38
+
39
+ ```json
40
+ {
41
+ "error": "ValidationError",
42
+ "message": "Invalid email format",
43
+ "details": {
44
+ "field": "email",
45
+ "value": "invalid-email",
46
+ "constraint": "Must be a valid email address"
47
+ },
48
+ "timestamp": "2025-01-06T12:00:00Z",
49
+ "path": "/api/v1/users",
50
+ "requestId": "550e8400-e29b-41d4-a716-446655440000"
51
+ }
52
+ ```
53
+
54
+ ---
55
+
56
+ ## 2. Error Types
57
+
58
+ ### Domain Errors
59
+
60
+ Errors from business logic (domain layer).
61
+
62
+ ```typescript
63
+ // src/domain/errors/UserNotFoundError.ts
64
+ export class UserNotFoundError extends Error {
65
+ constructor(userId: string) {
66
+ super(`User not found: ${userId}`);
67
+ this.name = 'UserNotFoundError';
68
+ }
69
+ }
70
+
71
+ // src/domain/errors/DuplicateEmailError.ts
72
+ export class DuplicateEmailError extends Error {
73
+ constructor(email: string) {
74
+ super(`Email already exists: ${email}`);
75
+ this.name = 'DuplicateEmailError';
76
+ }
77
+ }
78
+ ```
79
+
80
+ ### Validation Errors
81
+
82
+ Errors from input validation (using Zod).
83
+
84
+ ```typescript
85
+ import { z } from 'zod';
86
+
87
+ const CreateUserSchema = z.object({
88
+ name: z.string().min(1).max(100),
89
+ email: z.string().email(),
90
+ age: z.number().int().positive().optional(),
91
+ });
92
+
93
+ // Validation error example
94
+ const result = CreateUserSchema.safeParse(input);
95
+ if (!result.success) {
96
+ // result.error.issues contains detailed validation errors
97
+ }
98
+ ```
99
+
100
+ ### Infrastructure Errors
101
+
102
+ Errors from external systems (database, APIs).
103
+
104
+ ```typescript
105
+ export class DatabaseError extends Error {
106
+ constructor(message: string, public readonly cause?: Error) {
107
+ super(message);
108
+ this.name = 'DatabaseError';
109
+ }
110
+ }
111
+
112
+ export class ExternalAPIError extends Error {
113
+ constructor(
114
+ service: string,
115
+ message: string,
116
+ public readonly statusCode?: number
117
+ ) {
118
+ super(`${service}: ${message}`);
119
+ this.name = 'ExternalAPIError';
120
+ }
121
+ }
122
+ ```
123
+
124
+ ---
125
+
126
+ ## 3. Error Middleware
127
+
128
+ ### Global Error Handler
129
+
130
+ ```typescript
131
+ // src/presentation/middleware/errorHandler.ts
132
+ import type { Request, Response, NextFunction } from 'express';
133
+
134
+ export function errorHandler(
135
+ err: Error,
136
+ req: Request,
137
+ res: Response,
138
+ next: NextFunction
139
+ ): void {
140
+ // Log error
141
+ console.error('API Error:', {
142
+ error: err.name,
143
+ message: err.message,
144
+ stack: process.env.NODE_ENV === 'development' ? err.stack : undefined,
145
+ path: req.path,
146
+ method: req.method,
147
+ requestId: req.id,
148
+ });
149
+
150
+ // Map error to HTTP status
151
+ const statusCode = getStatusCode(err);
152
+ const errorResponse = createErrorResponse(err, req);
153
+
154
+ res.status(statusCode).json(errorResponse);
155
+ }
156
+
157
+ function getStatusCode(err: Error): number {
158
+ // Domain errors
159
+ if (err.name === 'UserNotFoundError') return 404;
160
+ if (err.name === 'DuplicateEmailError') return 409;
161
+ if (err.name === 'UnauthorizedError') return 401;
162
+ if (err.name === 'ForbiddenError') return 403;
163
+
164
+ // Validation errors
165
+ if (err.name === 'ZodError') return 400;
166
+
167
+ // Default to 500
168
+ return 500;
169
+ }
170
+
171
+ function createErrorResponse(err: Error, req: Request): ErrorResponse {
172
+ const isProduction = process.env.NODE_ENV === 'production';
173
+
174
+ return {
175
+ error: err.name,
176
+ message: isProduction && err.name === 'Error'
177
+ ? 'An unexpected error occurred'
178
+ : err.message,
179
+ details: getErrorDetails(err),
180
+ timestamp: new Date().toISOString(),
181
+ path: req.path,
182
+ requestId: req.id,
183
+ };
184
+ }
185
+
186
+ function getErrorDetails(err: Error): unknown {
187
+ // For Zod validation errors
188
+ if (err.name === 'ZodError') {
189
+ const zodError = err as z.ZodError;
190
+ return zodError.issues.map(issue => ({
191
+ path: issue.path.join('.'),
192
+ message: issue.message,
193
+ code: issue.code,
194
+ }));
195
+ }
196
+
197
+ // For other errors, return nothing in production
198
+ if (process.env.NODE_ENV === 'production') {
199
+ return undefined;
200
+ }
201
+
202
+ return { stack: err.stack };
203
+ }
204
+ ```
205
+
206
+ ### Register Error Handler
207
+
208
+ ```typescript
209
+ // src/server.ts
210
+ import express from 'express';
211
+ import { errorHandler } from './presentation/middleware/errorHandler';
212
+
213
+ const app = express();
214
+
215
+ // ... routes ...
216
+
217
+ // Error handler MUST be last middleware
218
+ app.use(errorHandler);
219
+
220
+ export default app;
221
+ ```
222
+
223
+ ---
224
+
225
+ ## 4. Validation Error Handling
226
+
227
+ ### Request Validation Middleware
228
+
229
+ ```typescript
230
+ // src/presentation/middleware/validateRequest.ts
231
+ import type { Request, Response, NextFunction } from 'express';
232
+ import type { z } from 'zod';
233
+
234
+ export function validateRequest<T extends z.ZodSchema>(schema: T) {
235
+ return (req: Request, res: Response, next: NextFunction) => {
236
+ const result = schema.safeParse(req.body);
237
+
238
+ if (!result.success) {
239
+ const errorResponse: ErrorResponse = {
240
+ error: 'ValidationError',
241
+ message: 'Request validation failed',
242
+ details: result.error.issues.map(issue => ({
243
+ path: issue.path.join('.'),
244
+ message: issue.message,
245
+ code: issue.code,
246
+ })),
247
+ timestamp: new Date().toISOString(),
248
+ path: req.path,
249
+ requestId: req.id,
250
+ };
251
+
252
+ return res.status(400).json(errorResponse);
253
+ }
254
+
255
+ // Attach validated data to request
256
+ req.body = result.data;
257
+ next();
258
+ };
259
+ }
260
+ ```
261
+
262
+ ### Usage in Routes
263
+
264
+ ```typescript
265
+ import { validateRequest } from '../middleware/validateRequest';
266
+ import { CreateUserSchema } from '../schemas/user';
267
+
268
+ router.post(
269
+ '/api/v1/users',
270
+ validateRequest(CreateUserSchema),
271
+ async (req, res, next) => {
272
+ try {
273
+ // req.body is now type-safe and validated
274
+ const result = await createUserUseCase.execute(req.body);
275
+
276
+ if (result.isErr()) {
277
+ // Convert domain error to HTTP error
278
+ return next(new DuplicateEmailError(req.body.email));
279
+ }
280
+
281
+ res.status(201).json(result.value);
282
+ } catch (err) {
283
+ next(err); // Pass to error handler
284
+ }
285
+ }
286
+ );
287
+ ```
288
+
289
+ ---
290
+
291
+ ## 5. Async Error Handling
292
+
293
+ ### Async Route Handler Wrapper
294
+
295
+ ```typescript
296
+ // src/presentation/middleware/asyncHandler.ts
297
+ import type { Request, Response, NextFunction } from 'express';
298
+
299
+ type AsyncRouteHandler = (
300
+ req: Request,
301
+ res: Response,
302
+ next: NextFunction
303
+ ) => Promise<void>;
304
+
305
+ export function asyncHandler(fn: AsyncRouteHandler) {
306
+ return (req: Request, res: Response, next: NextFunction) => {
307
+ Promise.resolve(fn(req, res, next)).catch(next);
308
+ };
309
+ }
310
+ ```
311
+
312
+ ### Usage
313
+
314
+ ```typescript
315
+ import { asyncHandler } from '../middleware/asyncHandler';
316
+
317
+ router.get(
318
+ '/api/v1/users/:id',
319
+ asyncHandler(async (req, res) => {
320
+ const result = await getUserUseCase.execute({ userId: req.params.id });
321
+
322
+ if (result.isErr()) {
323
+ throw new UserNotFoundError(req.params.id);
324
+ }
325
+
326
+ res.json(result.value);
327
+ })
328
+ );
329
+ ```
330
+
331
+ ---
332
+
333
+ ## 6. Result Pattern
334
+
335
+ ### Use Result<T, E> for Use Cases
336
+
337
+ ```typescript
338
+ // src/shared/types/Result.ts
339
+ export type Result<T, E> =
340
+ | { isOk: true; value: T }
341
+ | { isOk: false; error: E };
342
+
343
+ export function ok<T>(value: T): Result<T, never> {
344
+ return { isOk: true, value };
345
+ }
346
+
347
+ export function err<E>(error: E): Result<never, E> {
348
+ return { isOk: false, error };
349
+ }
350
+
351
+ // Usage in Use Case
352
+ export class GetUserUseCase {
353
+ async execute(input: { userId: string }): Promise<Result<User, string>> {
354
+ const user = await this.userRepository.findById(input.userId);
355
+
356
+ if (!user) {
357
+ return err('User not found');
358
+ }
359
+
360
+ return ok(user);
361
+ }
362
+ }
363
+
364
+ // Usage in Route
365
+ router.get('/api/v1/users/:id', async (req, res, next) => {
366
+ const result = await getUserUseCase.execute({ userId: req.params.id });
367
+
368
+ if (!result.isOk) {
369
+ return next(new UserNotFoundError(req.params.id));
370
+ }
371
+
372
+ res.json(result.value);
373
+ });
374
+ ```
375
+
376
+ ---
377
+
378
+ ## 7. Not Found Handler
379
+
380
+ ### 404 Handler
381
+
382
+ ```typescript
383
+ // src/presentation/middleware/notFoundHandler.ts
384
+ import type { Request, Response } from 'express';
385
+
386
+ export function notFoundHandler(req: Request, res: Response): void {
387
+ const errorResponse: ErrorResponse = {
388
+ error: 'NotFound',
389
+ message: `Route not found: ${req.method} ${req.path}`,
390
+ timestamp: new Date().toISOString(),
391
+ path: req.path,
392
+ requestId: req.id,
393
+ };
394
+
395
+ res.status(404).json(errorResponse);
396
+ }
397
+ ```
398
+
399
+ ### Register Before Error Handler
400
+
401
+ ```typescript
402
+ // src/server.ts
403
+ import { notFoundHandler } from './presentation/middleware/notFoundHandler';
404
+ import { errorHandler } from './presentation/middleware/errorHandler';
405
+
406
+ // ... routes ...
407
+
408
+ // 404 handler
409
+ app.use(notFoundHandler);
410
+
411
+ // Error handler
412
+ app.use(errorHandler);
413
+ ```
414
+
415
+ ---
416
+
417
+ ## 8. Error Logging
418
+
419
+ ### Structured Logging
420
+
421
+ ```typescript
422
+ interface ErrorLog {
423
+ level: 'error';
424
+ error: string;
425
+ message: string;
426
+ stack?: string;
427
+ context: {
428
+ requestId?: string;
429
+ path: string;
430
+ method: string;
431
+ userId?: string;
432
+ };
433
+ timestamp: string;
434
+ }
435
+
436
+ function logError(err: Error, req: Request): void {
437
+ const log: ErrorLog = {
438
+ level: 'error',
439
+ error: err.name,
440
+ message: err.message,
441
+ stack: err.stack,
442
+ context: {
443
+ requestId: req.id,
444
+ path: req.path,
445
+ method: req.method,
446
+ userId: req.user?.id, // If authenticated
447
+ },
448
+ timestamp: new Date().toISOString(),
449
+ };
450
+
451
+ // Log as JSON for parsing by log aggregators
452
+ console.error(JSON.stringify(log));
453
+ }
454
+ ```
455
+
456
+ ---
457
+
458
+ ## 9. Rate Limit Errors
459
+
460
+ ### Rate Limit Handler
461
+
462
+ ```typescript
463
+ import rateLimit from 'express-rate-limit';
464
+
465
+ const limiter = rateLimit({
466
+ windowMs: 15 * 60 * 1000, // 15 minutes
467
+ max: 100,
468
+ handler: (req, res) => {
469
+ const errorResponse: ErrorResponse = {
470
+ error: 'TooManyRequests',
471
+ message: 'Too many requests from this IP, please try again later',
472
+ timestamp: new Date().toISOString(),
473
+ path: req.path,
474
+ requestId: req.id,
475
+ };
476
+
477
+ res.status(429).json(errorResponse);
478
+ },
479
+ standardHeaders: true,
480
+ legacyHeaders: false,
481
+ });
482
+
483
+ app.use('/api/', limiter);
484
+ ```
485
+
486
+ ---
487
+
488
+ ## 10. Testing Error Handling
489
+
490
+ ### Test Error Responses
491
+
492
+ ```typescript
493
+ import request from 'supertest';
494
+ import { app } from '../src/server';
495
+
496
+ describe('Error Handling', () => {
497
+ it('should return 404 for non-existent route', async () => {
498
+ const response = await request(app)
499
+ .get('/api/v1/nonexistent')
500
+ .expect(404);
501
+
502
+ expect(response.body).toHaveProperty('error', 'NotFound');
503
+ expect(response.body).toHaveProperty('message');
504
+ expect(response.body).toHaveProperty('timestamp');
505
+ expect(response.body).toHaveProperty('path', '/api/v1/nonexistent');
506
+ });
507
+
508
+ it('should return 400 for validation errors', async () => {
509
+ const response = await request(app)
510
+ .post('/api/v1/users')
511
+ .send({ name: '', email: 'invalid' })
512
+ .expect(400);
513
+
514
+ expect(response.body.error).toBe('ValidationError');
515
+ expect(response.body.details).toBeInstanceOf(Array);
516
+ });
517
+
518
+ it('should return 500 for unexpected errors', async () => {
519
+ // Mock repository to throw error
520
+ jest.spyOn(userRepository, 'findById').mockRejectedValue(new Error('DB Error'));
521
+
522
+ const response = await request(app)
523
+ .get('/api/v1/users/123')
524
+ .expect(500);
525
+
526
+ expect(response.body.error).toBe('Error');
527
+ expect(response.body.message).toBeTruthy();
528
+ });
529
+ });
530
+ ```
531
+
532
+ ---
533
+
534
+ ## Best Practices
535
+
536
+ 1. **Always use middleware for error handling** - Don't handle errors in routes
537
+ 2. **Log all errors** - Include request context for debugging
538
+ 3. **Use Result pattern** - Avoid throwing errors in use cases
539
+ 4. **Consistent error format** - All errors follow same structure
540
+ 5. **Sanitize in production** - Don't expose stack traces or sensitive data
541
+ 6. **Test error scenarios** - Test all error cases (4xx, 5xx)
542
+
543
+ ---
544
+
545
+ ## References
546
+
547
+ - [Express Error Handling](https://expressjs.com/en/guide/error-handling.html)
548
+ - [HTTP Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
549
+ - [Zod Validation](https://zod.dev/)
550
+
551
+ ---
552
+
553
+ **Generated for**: my-project
554
+ **Template**: api
555
+ **Constitution Preset**: orchestrator