@dv.nghiem/flowdeck 0.2.3 → 0.3.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 (100) hide show
  1. package/README.md +24 -41
  2. package/dist/hooks/memory-hook.d.ts +21 -0
  3. package/dist/hooks/memory-hook.d.ts.map +1 -0
  4. package/dist/hooks/orchestrator-guard-hook.d.ts +2 -1
  5. package/dist/hooks/orchestrator-guard-hook.d.ts.map +1 -1
  6. package/dist/hooks/todo-hook.d.ts +1 -7
  7. package/dist/hooks/todo-hook.d.ts.map +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +649 -310
  10. package/dist/services/memory-store.d.ts +40 -0
  11. package/dist/services/memory-store.d.ts.map +1 -0
  12. package/dist/services/telemetry.d.ts +1 -1
  13. package/dist/services/telemetry.d.ts.map +1 -1
  14. package/dist/tools/memory-search.d.ts +3 -0
  15. package/dist/tools/memory-search.d.ts.map +1 -0
  16. package/docs/commands/fd-doctor.md +21 -0
  17. package/docs/commands/fd-quick.md +33 -0
  18. package/docs/commands/fd-reflect.md +23 -0
  19. package/docs/commands/fd-status.md +31 -0
  20. package/docs/commands/fd-translate-intent.md +17 -0
  21. package/docs/commands.md +209 -271
  22. package/docs/configuration.md +2 -1
  23. package/docs/index.md +22 -28
  24. package/docs/memory.md +69 -0
  25. package/docs/quick-start.md +1 -1
  26. package/docs/workflows.md +72 -320
  27. package/package.json +1 -2
  28. package/src/commands/fd-deploy-check.md +189 -34
  29. package/src/commands/fd-discuss.md +44 -6
  30. package/src/commands/fd-fix-bug.md +47 -20
  31. package/src/commands/fd-map-codebase.md +66 -18
  32. package/src/commands/fd-multi-repo.md +130 -6
  33. package/src/commands/fd-new-feature.md +164 -21
  34. package/src/commands/fd-new-project.md +14 -1
  35. package/src/commands/fd-plan.md +66 -44
  36. package/src/commands/fd-quick.md +60 -0
  37. package/src/commands/fd-reflect.md +41 -2
  38. package/src/commands/fd-status.md +84 -0
  39. package/src/commands/fd-write-docs.md +55 -23
  40. package/src/rules/README.md +8 -7
  41. package/src/skills/agent-harness-construction/SKILL.md +227 -0
  42. package/src/skills/api-design/SKILL.md +5 -0
  43. package/src/skills/backend-patterns/SKILL.md +105 -0
  44. package/src/skills/clean-architecture/SKILL.md +85 -0
  45. package/src/skills/cqrs/SKILL.md +230 -0
  46. package/src/skills/ddd-architecture/SKILL.md +104 -0
  47. package/src/skills/django-patterns/SKILL.md +304 -0
  48. package/src/skills/django-tdd/SKILL.md +297 -0
  49. package/src/skills/event-driven-architecture/SKILL.md +152 -0
  50. package/src/skills/frontend-pattern/SKILL.md +159 -0
  51. package/src/skills/hexagonal-architecture/SKILL.md +80 -0
  52. package/src/skills/layered-architecture/SKILL.md +64 -0
  53. package/src/skills/postgres-patterns/SKILL.md +74 -0
  54. package/src/skills/python-patterns/SKILL.md +5 -0
  55. package/src/skills/saga-architecture/SKILL.md +113 -0
  56. package/dist/tools/run-parallel.d.ts +0 -4
  57. package/dist/tools/run-parallel.d.ts.map +0 -1
  58. package/docs/command-migration.md +0 -175
  59. package/docs/commands/fd-analyze-change.md +0 -107
  60. package/docs/commands/fd-dashboard.md +0 -11
  61. package/docs/commands/fd-evaluate-risk.md +0 -134
  62. package/docs/commands/fd-guarded-edit.md +0 -105
  63. package/docs/commands/fd-progress.md +0 -11
  64. package/docs/commands/fd-review-code.md +0 -29
  65. package/docs/commands/fd-roadmap.md +0 -10
  66. package/docs/commands/fd-settings.md +0 -10
  67. package/docs/parallel-execution.md +0 -227
  68. package/src/commands/fd-analyze-change.md +0 -57
  69. package/src/commands/fd-approve.md +0 -64
  70. package/src/commands/fd-blast-radius.md +0 -49
  71. package/src/commands/fd-dashboard.md +0 -57
  72. package/src/commands/fd-evaluate-risk.md +0 -62
  73. package/src/commands/fd-guarded-edit.md +0 -69
  74. package/src/commands/fd-impact-radar.md +0 -51
  75. package/src/commands/fd-learn.md +0 -36
  76. package/src/commands/fd-progress.md +0 -50
  77. package/src/commands/fd-regression-predict.md +0 -57
  78. package/src/commands/fd-review-code.md +0 -62
  79. package/src/commands/fd-review-route.md +0 -54
  80. package/src/commands/fd-roadmap.md +0 -46
  81. package/src/commands/fd-settings.md +0 -57
  82. package/src/commands/fd-test-gap.md +0 -54
  83. package/src/commands/fd-volatility-map.md +0 -64
  84. package/src/commands/fd-workspace-status.md +0 -34
  85. package/src/skills/parallel-execute/SKILL.md +0 -92
  86. package/src/workflows/debug-flow.md +0 -119
  87. package/src/workflows/deploy-check-flow.md +0 -98
  88. package/src/workflows/discuss-flow.md +0 -97
  89. package/src/workflows/execute-flow.md +0 -233
  90. package/src/workflows/execute-phase.md +0 -145
  91. package/src/workflows/fix-bug-flow.md +0 -210
  92. package/src/workflows/map-codebase-flow.md +0 -92
  93. package/src/workflows/multi-repo-flow.md +0 -226
  94. package/src/workflows/parallel-execution-flow.md +0 -236
  95. package/src/workflows/plan-flow.md +0 -126
  96. package/src/workflows/plan-phase.md +0 -101
  97. package/src/workflows/refactor-flow.md +0 -122
  98. package/src/workflows/review-code-flow.md +0 -105
  99. package/src/workflows/spec-driven-flow.md +0 -43
  100. package/src/workflows/write-docs-flow.md +0 -95
@@ -0,0 +1,84 @@
1
+ ---
2
+ description: View project status — combined status, roadmap, workspace overview, and progress
3
+ argument-hint: [--roadmap | --workspace | --phase=N]
4
+ ---
5
+
6
+ # Status
7
+
8
+ View project status combining progress, roadmap, and workspace overview.
9
+
10
+ **Input:** $ARGUMENTS — optional flags
11
+
12
+ ## Modes
13
+
14
+ ### Default (no flags)
15
+
16
+ Read `.planning/STATE.md` and display combined status:
17
+
18
+ ```
19
+ ════════════════════════════════════════════════════════════
20
+ Phase: <N> | Status: <status> | Updated: <timestamp>
21
+ ────────────────────────────────────────────────────────────
22
+ Plan: <X> steps (<Y> complete)
23
+ Plan confirmed: <yes/no>
24
+ ════════════════════════════════════════════════════════════
25
+ ```
26
+
27
+ ### Roadmap (`--roadmap`)
28
+
29
+ Display project roadmap with phase statuses:
30
+
31
+ ```
32
+ ═══════════════════════════════════════
33
+ PROJECT ROADMAP
34
+ ═══════════════════════════════════════
35
+ ✅ Phase 1: <name> — completed
36
+ 🔄 Phase 2: <name> — in progress ← current
37
+ ⏳ Phase 3: <name> — planned
38
+ ═══════════════════════════════════════
39
+ ```
40
+
41
+ Read from `.planning/ROADMAP.md` and `.planning/STATE.md`.
42
+
43
+ ### Workspace (`--workspace`)
44
+
45
+ Display overview of all registered repositories:
46
+
47
+ ```
48
+ ════════════════════════════════════════════════════
49
+ WORKSPACE OVERVIEW
50
+ ════════════════════════════════════════════════════
51
+ frontend — Phase 2 | in_progress | Plan: ✅ | Updated: <time>
52
+ backend — Phase 3 | completed | Plan: ✅ | Updated: <time>
53
+ shared — Phase 1 | planned | Plan: ❌ | Updated: <time>
54
+ ────────────────────────────────────────────────────
55
+ Total: 3 repos | 1 in progress | 1 completed | 1 planned
56
+ ════════════════════════════════════════════════════
57
+ ```
58
+
59
+ Read from `.planning/config.json` for repo list, each repo's STATE.md for phase/status.
60
+
61
+ ### Phase Detail (`--phase=N`)
62
+
63
+ Show detailed progress for a specific phase:
64
+
65
+ ```
66
+ ════════════════════════════════════════════════════════════
67
+ PHASE <N> DETAIL
68
+ ════════════════════════════════════════════════════════════
69
+ Status: <status>
70
+ Plan file: <path>
71
+ Plan confirmed: <yes/no>
72
+
73
+ Steps:
74
+ ✅ Step 1: <name> — completed
75
+ 🔄 Step 2: <name> — in progress
76
+ ⬜ Step 3: <name> — pending
77
+ ⬜ Step 4: <name> — pending
78
+ ════════════════════════════════════════════════════════════
79
+ ```
80
+
81
+ ## Error Handling
82
+
83
+ - If `.planning/STATE.md` not found: "No active project. Run /fd-new-project first."
84
+ - If `--phase` requested but phase directory doesn't exist: "Phase N not found."
@@ -5,46 +5,78 @@ argument-hint: [--scope=path | --format=api,guide,readme]
5
5
 
6
6
  # Write Docs
7
7
 
8
- Generate documentation for the codebase or a specific scope.
8
+ Generate accurate, up-to-date documentation from the codebase.
9
9
 
10
10
  **Input:** $ARGUMENTS — optional `--scope=<path>` and `--format=<type>`
11
11
 
12
12
  Supported formats: `api` (API reference), `guide` (usage guide), `readme` (README)
13
13
  Default: all formats
14
14
 
15
- ## Pipeline
15
+ ## Process
16
16
 
17
- ### Phase 1 Explore
17
+ ### Step 1: Explore APIs
18
18
 
19
- - **@researcher**: Find all public APIs, exported functions, classes, types, and their signatures
20
- - **@code-explorer**: Identify existing documentation, JSDoc comments, README sections
19
+ Spawn `@mapper` to:
20
+ - Find all exported functions, classes, and types
21
+ - Identify public API entry points
22
+ - Map key workflows and integration points
21
23
 
22
- ### Phase 2 — Draft
24
+ ```bash
25
+ # Find exports
26
+ grep -rn "export " src/ --include="*.ts"
27
+ # Find public interfaces
28
+ grep -rn "export interface\|export type\|export class" src/ --include="*.ts"
29
+ ```
23
30
 
24
- - **@writer**: Draft documentation based on the exploration findings
25
- - API docs: function signatures, parameters, return types, examples
26
- - Guides: usage examples, step-by-step instructions
27
- - README: project overview, install, quickstart, API summary
31
+ ### Step 2: Draft Documentation
28
32
 
29
- ### Phase 3 — Review
33
+ Spawn `@writer` to produce:
30
34
 
31
- - **@reviewer**: Check accuracy — verify all documented APIs exist and signatures are correct
32
- - Flag any documentation that contradicts the implementation
33
- - Flag missing documentation for public APIs
35
+ **API Reference**
36
+ ```markdown
37
+ ## functionName(param: Type): ReturnType
34
38
 
35
- ### Phase 4 Finalize
39
+ Description of what the function does.
36
40
 
37
- - **@writer**: Apply reviewer corrections, finalize and write documentation files
41
+ **Parameters:**
42
+ - `param` (Type) — description
38
43
 
39
- ## Output Files
44
+ **Returns:** description
40
45
 
41
- Based on `--format`:
42
- - `api` → writes or updates `docs/API.md`
43
- - `guide` writes or updates `docs/GUIDE.md`
44
- - `readme` → updates `README.md`
46
+ **Example:**
47
+ \`\`\`typescript
48
+ const result = functionName(value);
49
+ \`\`\`
50
+ ```
45
51
 
46
- If `--scope` is set, documentation applies only to files within that path.
52
+ **Usage Guide**
53
+ - Step-by-step workflow with examples
54
+ - Common patterns and best practices
55
+ - Configuration options
47
56
 
48
- ## Completion
57
+ **Troubleshooting**
58
+ - Common errors and their solutions
59
+
60
+ ### Step 3: Review for Accuracy
61
+
62
+ Spawn `@reviewer` to verify:
63
+ - Every documented function/method actually exists
64
+ - Parameter types match the actual signatures
65
+ - Examples are syntactically correct
66
+ - No outdated API references
67
+
68
+ ### Step 4: Finalize
69
+
70
+ Writer incorporates feedback and writes final docs to:
71
+ - `README.md` — project overview and quick start
72
+ - `docs/API.md` — complete API reference
73
+ - `docs/USER_GUIDE.md` — detailed usage guide
74
+
75
+ ## Output
76
+
77
+ Updated documentation files with:
78
+ - Accurate function signatures
79
+ - Working code examples
80
+ - Clear explanations of behavior
49
81
 
50
82
  Report: files written/updated, public APIs documented, any gaps found.
@@ -2,22 +2,23 @@
2
2
 
3
3
  Coding standards for projects using FlowDeck. These define conventions that FlowDeck agents follow automatically.
4
4
 
5
- ## How to Use
5
+ ## How It Works
6
6
 
7
- Add a rule file to `opencode.json` under `instructions`:
7
+ Rules are loaded **automatically** by the FlowDeck plugin. No manual configuration is needed — when FlowDeck is installed, all rule files in this directory are injected into OpenCode's `instructions` at startup.
8
+
9
+ ## Selective Rules (Optional)
10
+
11
+ If you want to override the default set and load only specific rules, add them to `opencode.json` under `instructions`:
8
12
 
9
13
  ```json
10
14
  {
11
15
  "instructions": [
12
- ".flowdeck/rules/common/coding-style.md",
13
- ".flowdeck/rules/common/security.md",
14
- ".flowdeck/rules/typescript/patterns.md"
16
+ "node_modules/@dv.nghiem/flowdeck/src/rules/common/coding-style.md",
17
+ "node_modules/@dv.nghiem/flowdeck/src/rules/typescript/patterns.md"
15
18
  ]
16
19
  }
17
20
  ```
18
21
 
19
- Agents will read these files and follow the conventions defined in them.
20
-
21
22
  ## Available Rules
22
23
 
23
24
  ### Common Rules (language-agnostic)
@@ -0,0 +1,227 @@
1
+ ---
2
+ name: agent-harness-construction
3
+ description: Build autonomous agent pipelines — construct agent loops, wire multi-agent orchestration, implement self-healing retry logic, and measure agent effectiveness
4
+ origin: FlowDeck
5
+ ---
6
+
7
+ # Agent Harness Construction Skill
8
+
9
+ Constructs autonomous agent pipelines that can plan, execute, self-correct, and measure their own effectiveness.
10
+
11
+ ## When to Activate
12
+
13
+ Activate when:
14
+ - Building multi-agent orchestration systems
15
+ - Implementing autonomous loops (self-correcting agents)
16
+ - Designing agent retry and self-healing policies
17
+ - Wiring agent-to-agent communication
18
+ - Measuring and optimizing agent effectiveness
19
+
20
+ ## Agent Loop Architecture
21
+
22
+ ### Core Loop Pattern
23
+
24
+ ```
25
+ ┌─────────────────────────────────────────────┐
26
+ │ 1. OBSERVE → Gather context state │
27
+ │ 2. THINK → Plan next action │
28
+ │ 3. ACT → Execute tool call │
29
+ │ 4. EVALUATE → Check result quality │
30
+ │ 5. ADAPT → Retry or proceed │
31
+ └─────────────────────────────────────────────┘
32
+ ```
33
+
34
+ ```typescript
35
+ interface AgentLoop {
36
+ observe: () => Promise<Context>;
37
+ think: (ctx: Context) => Promise<Plan>;
38
+ act: (plan: Plan) => Promise<Result>;
39
+ evaluate: (result: Result) => Evaluation;
40
+ adapt: (evaluation: Evaluation) => 'continue' | 'retry' | 'complete';
41
+ }
42
+ ```
43
+
44
+ ### Self-Healing Retry Logic
45
+
46
+ ```typescript
47
+ async function withRetry<T>(
48
+ fn: () => Promise<T>,
49
+ options: {
50
+ maxAttempts?: number;
51
+ backoff?: 'linear' | 'exponential';
52
+ onRetry?: (attempt: number, error: Error) => void;
53
+ } = {}
54
+ ): Promise<T> {
55
+ const { maxAttempts = 3, backoff = 'exponential', onRetry } = options;
56
+
57
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
58
+ try {
59
+ return await fn();
60
+ } catch (error) {
61
+ if (attempt === maxAttempts) throw error;
62
+ const delay = backoff === 'exponential'
63
+ ? Math.pow(2, attempt - 1) * 1000
64
+ : attempt * 1000;
65
+ onRetry?.(attempt, error as Error);
66
+ await sleep(delay);
67
+ }
68
+ }
69
+ throw new Error('unreachable');
70
+ }
71
+ ```
72
+
73
+ ## Multi-Agent Orchestration
74
+
75
+ ### Supervisor Pattern
76
+
77
+ ```typescript
78
+ interface AgentMessage {
79
+ from: string;
80
+ to: string;
81
+ type: 'request' | 'response' | 'delegate' | 'result';
82
+ payload: unknown;
83
+ traceId: string;
84
+ }
85
+
86
+ class SupervisorAgent {
87
+ private agents: Map<string, Agent>;
88
+ private messageQueue: AgentMessage[] = [];
89
+
90
+ async delegate(task: Task, targetAgent: string): Promise<Result> {
91
+ const message: AgentMessage = {
92
+ from: this.id,
93
+ to: targetAgent,
94
+ type: 'delegate',
95
+ payload: task,
96
+ traceId: generateTraceId(),
97
+ };
98
+ return this.sendAndWait(message);
99
+ }
100
+
101
+ async parallelDelegate(tasks: Task[], agents: string[]): Promise<Result[]> {
102
+ return Promise.all(
103
+ tasks.map((task, i) => this.delegate(task, agents[i % agents.length]))
104
+ );
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### Council Pattern
110
+
111
+ Multiple agents deliberate and vote on a decision:
112
+
113
+ ```typescript
114
+ interface CouncilMember {
115
+ id: string;
116
+ specialty: 'security' | 'performance' | 'correctness';
117
+ vote: (proposal: Proposal) => Promise<Vote>;
118
+ }
119
+
120
+ interface CouncilDecision {
121
+ votes: Vote[];
122
+ decision: 'approve' | 'reject' | 'revise';
123
+ consensus: number; // 0-1
124
+ }
125
+
126
+ async function councilDeliberate(
127
+ proposal: Proposal,
128
+ members: CouncilMember[]
129
+ ): Promise<CouncilDecision> {
130
+ const votes = await Promise.all(members.map(m => m.vote(proposal)));
131
+ const approvals = votes.filter(v => v.approve).length;
132
+ const consensus = approvals / votes.length;
133
+
134
+ return {
135
+ votes,
136
+ decision: consensus >= 0.7 ? 'approve' : consensus >= 0.4 ? 'revise' : 'reject',
137
+ consensus,
138
+ };
139
+ }
140
+ ```
141
+
142
+ ## Agent Effectiveness Measurement
143
+
144
+ ### Trace-Based Metrics
145
+
146
+ ```typescript
147
+ interface AgentTrace {
148
+ traceId: string;
149
+ agentId: string;
150
+ spans: {
151
+ name: string;
152
+ startTime: number;
153
+ endTime: number;
154
+ success: boolean;
155
+ tokensUsed?: number;
156
+ error?: string;
157
+ }[];
158
+ outcome: 'success' | 'failure' | 'timeout';
159
+ }
160
+
161
+ // Track effectiveness
162
+ function measureAgentEffectiveness(traces: AgentTrace[]): AgentMetrics {
163
+ return {
164
+ successRate: traces.filter(t => t.outcome === 'success').length / traces.length,
165
+ avgDuration: traces.reduce((sum, t) => {
166
+ const duration = t.spans[t.spans.length - 1].endTime - t.spans[0].startTime;
167
+ return sum + duration;
168
+ }, 0) / traces.length,
169
+ avgTokensPerTask: traces.reduce((sum, t) =>
170
+ sum + (t.spans.reduce((s, span) => s + (span.tokensUsed ?? 0), 0) / t.spans.length), 0
171
+ ) / traces.length,
172
+ retryRate: traces.filter(t => t.spans.some(s => s.name === 'retry')).length / traces.length,
173
+ };
174
+ }
175
+ ```
176
+
177
+ ## Error Classification
178
+
179
+ ```typescript
180
+ type ErrorCategory =
181
+ | 'transient' // Network blip, timeout — retry eligible
182
+ | 'recoverable' // Missing context, bad input — can fix with adaptation
183
+ | 'fatal'; // Auth failure, permission — cannot proceed
184
+
185
+ function classifyError(error: Error): ErrorCategory {
186
+ if (error.message.includes('timeout') || error.message.includes('ECONNREFUSED')) {
187
+ return 'transient';
188
+ }
189
+ if (error.message.includes('invalid input') || error.message.includes('missing context')) {
190
+ return 'recoverable';
191
+ }
192
+ return 'fatal';
193
+ }
194
+ ```
195
+
196
+ ## Self-Healing Policies
197
+
198
+ ```typescript
199
+ interface HealingPolicy {
200
+ trigger: (error: Error) => boolean;
201
+ action: (context: AgentContext) => Promise<Action>;
202
+ }
203
+
204
+ const healingPolicies: HealingPolicy[] = [
205
+ {
206
+ trigger: (e) => e.message.includes('rate limit'),
207
+ action: async (ctx) => {
208
+ ctx.throttleDelay = Math.min(ctx.throttleDelay * 2, 60000);
209
+ return { type: 'backoff', delay: ctx.throttleDelay };
210
+ },
211
+ },
212
+ {
213
+ trigger: (e) => e.message.includes('context too long'),
214
+ action: async (ctx) => {
215
+ ctx.summarizeOlderHistory();
216
+ return { type: 'compact' };
217
+ },
218
+ },
219
+ ];
220
+ ```
221
+
222
+ ## Related Skills
223
+
224
+ - [self-healing-policies](self-healing-policies) — Define recovery policies
225
+ - [agent-introspection-debugging](agent-introspection-debugging) — Debug agent issues
226
+ - [eval-harness](eval-harness) — Evaluate agent performance
227
+ - [continuous-agent-loop](continuous-agent-loop) — Maintain persistent agent sessions
@@ -141,3 +141,8 @@ X-RateLimit-Reset: 1609459200
141
141
  ```
142
142
 
143
143
  Return 429 when limit exceeded with `Retry-After` header.
144
+
145
+ ## Related Skills
146
+ - backend-patterns
147
+ - postgres-patterns
148
+ - api-connector-builder
@@ -0,0 +1,105 @@
1
+ # backend-patterns
2
+
3
+ ## When to Activate
4
+ When implementing backend services, APIs, or server-side logic. Use when designing service layers, data access patterns, or middleware.
5
+
6
+ ## Steps
7
+ 1. **Identify the service layer** - Determine if you need a service layer to orchestrate business logic
8
+ 2. **Apply Repository Pattern** - Encapsulate data access behind repository interfaces for testability
9
+ 3. **Use Dependency Injection** - Pass dependencies explicitly rather than creating them inside classes
10
+ 4. **Implement error handling** - Add comprehensive error handling with appropriate HTTP status codes
11
+ 5. **Add middleware/logging** - Log requests, responses, and errors consistently
12
+
13
+ ## Examples
14
+
15
+ ```typescript
16
+ // Service Layer with Repository Pattern
17
+ interface UserRepository {
18
+ findById(id: string): Promise<User | null>;
19
+ findAll(filter?: UserFilter): Promise<User[]>;
20
+ create(attributes: CreateUserDTO): Promise<User>;
21
+ update(id: string, attributes: UpdateUserDTO): Promise<User>;
22
+ delete(id: string): Promise<void>;
23
+ }
24
+
25
+ class UserService {
26
+ constructor(private readonly userRepository: UserRepository) {}
27
+
28
+ async getUser(id: string): Promise<User> {
29
+ const user = await this.userRepository.findById(id);
30
+ if (!user) {
31
+ throw new NotFoundError(`User with id ${id} not found`);
32
+ }
33
+ return user;
34
+ }
35
+
36
+ async createUser(dto: CreateUserDTO): Promise<User> {
37
+ const existing = await this.userRepository.findByEmail(dto.email);
38
+ if (existing) {
39
+ throw new ConflictError('User with this email already exists');
40
+ }
41
+ return this.userRepository.create(dto);
42
+ }
43
+ }
44
+
45
+ // Dependency Injection Container
46
+ const container = new Container();
47
+ container.register('userRepository', () => new PostgresUserRepository());
48
+ container.register('userService', () => new UserService(container.resolve('userRepository')));
49
+ ```
50
+
51
+ ```typescript
52
+ // Error Handling with Custom Exceptions
53
+ class AppError extends Error {
54
+ constructor(
55
+ message: string,
56
+ public readonly code: string,
57
+ public readonly statusCode: number = 500
58
+ ) {
59
+ super(message);
60
+ this.name = 'AppError';
61
+ }
62
+ }
63
+
64
+ class NotFoundError extends AppError {
65
+ constructor(message: string) {
66
+ super(message, 'NOT_FOUND', 404);
67
+ }
68
+ }
69
+
70
+ class ValidationError extends AppError {
71
+ constructor(
72
+ message: string,
73
+ public readonly details?: Record<string, string[]>
74
+ ) {
75
+ super(message, 'VALIDATION_ERROR', 422);
76
+ }
77
+ }
78
+
79
+ // Global Error Handler Middleware
80
+ function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
81
+ if (err instanceof AppError) {
82
+ return res.status(err.statusCode).json({
83
+ error: {
84
+ code: err.code,
85
+ message: err.message,
86
+ details: err instanceof ValidationError ? err.details : undefined,
87
+ },
88
+ });
89
+ }
90
+ console.error('Unhandled error:', err);
91
+ return res.status(500).json({
92
+ error: {
93
+ code: 'INTERNAL_ERROR',
94
+ message: 'An unexpected error occurred',
95
+ },
96
+ });
97
+ }
98
+ ```
99
+
100
+ ## Related Skills
101
+ - api-design
102
+ - postgres-patterns
103
+ - python-patterns
104
+ - layered-architecture
105
+ - ddd-architecture
@@ -0,0 +1,85 @@
1
+ # clean-architecture
2
+
3
+ ## When to Activate
4
+ When designing or implementing a new feature or service that needs clear separation of concerns, testability, and independence from frameworks, databases, or UI libraries.
5
+
6
+ ## Steps
7
+ 1. **Identify the core business logic** - Determine the essential domain rules that would exist even if the application had no UI, database, or external services.
8
+ 2. **Define the boundary** - Draw a clear boundary between the inner circles (entities, use cases) and outer circles (interfaces, infrastructure).
9
+ 3. **Place dependencies pointing inward** - Dependencies should always point toward the center. The inner circle knows nothing about the outer circle.
10
+ 4. **Define ports (interfaces)** - Create interfaces in the domain layer that define how the outside world can interact with it.
11
+ 5. **Implement adapters** - Create concrete implementations (adapters) for databases, web frameworks, external APIs, etc. in the outer layers.
12
+ 6. **Wire everything via dependency injection** - Use a composition root or DI container to assemble the application.
13
+
14
+ ## Examples
15
+ ```typescript
16
+ // Domain Layer - Enterprise Business Rules (innermost circle)
17
+ class Order {
18
+ constructor(
19
+ private readonly id: string,
20
+ private readonly items: OrderItem[],
21
+ private readonly status: OrderStatus
22
+ ) {}
23
+
24
+ get total(): number {
25
+ return this.items.reduce((sum, item) => sum + item.price * item.quantity, 0)
26
+ }
27
+
28
+ canBeFulfilled(): boolean {
29
+ return this.status === 'pending' && this.items.length > 0
30
+ }
31
+ }
32
+
33
+ // Application Layer - Application Business Rules
34
+ interface OrderRepository {
35
+ findById(id: string): Promise<Order | null>
36
+ save(order: Order): Promise<void>
37
+ }
38
+
39
+ interface NotificationService {
40
+ sendOrderConfirmation(order: Order): Promise<void>
41
+ }
42
+
43
+ class PlaceOrderUseCase {
44
+ constructor(
45
+ private readonly orderRepo: OrderRepository,
46
+ private readonly notifier: NotificationService
47
+ ) {}
48
+
49
+ async execute(orderData: OrderData): Promise<Order> {
50
+ const order = new Order(orderData.id, orderData.items, 'pending')
51
+
52
+ if (!order.canBeFulfilled()) {
53
+ throw new InvalidOrderError('Order cannot be fulfilled')
54
+ }
55
+
56
+ await this.orderRepo.save(order)
57
+ await this.notifier.sendOrderConfirmation(order)
58
+
59
+ return order
60
+ }
61
+ }
62
+
63
+ // Infrastructure Layer - Interface Adapters (outermost circle)
64
+ class PostgresOrderRepository implements OrderRepository {
65
+ async findById(id: string): Promise<Order | null> {
66
+ // Database implementation
67
+ }
68
+
69
+ async save(order: Order): Promise<void> {
70
+ // Database implementation
71
+ }
72
+ }
73
+
74
+ class EmailNotificationService implements NotificationService {
75
+ async sendOrderConfirmation(order: Order): Promise<void> {
76
+ // Email implementation
77
+ }
78
+ }
79
+ ```
80
+
81
+ ## Related Skills
82
+ - layered-architecture
83
+ - hexagonal-architecture
84
+ - ddd-architecture
85
+ - backend-patterns