@botlearn/code-gen 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.
- package/LICENSE +21 -0
- package/README.md +35 -0
- package/knowledge/anti-patterns.md +212 -0
- package/knowledge/best-practices.md +228 -0
- package/knowledge/domain.md +344 -0
- package/manifest.json +26 -0
- package/package.json +35 -0
- package/skill.md +43 -0
- package/strategies/main.md +114 -0
- package/tests/benchmark.json +536 -0
- package/tests/smoke.json +64 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
---
|
|
2
|
+
domain: code-gen
|
|
3
|
+
topic: design-patterns-and-language-idioms
|
|
4
|
+
priority: high
|
|
5
|
+
ttl: 30d
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Code Generation — Design Patterns, Async Patterns & Error Handling
|
|
9
|
+
|
|
10
|
+
## Creational Design Patterns
|
|
11
|
+
|
|
12
|
+
### Factory Pattern
|
|
13
|
+
- Use when object creation logic is complex or depends on runtime conditions
|
|
14
|
+
- Encapsulate construction behind a factory function or class method
|
|
15
|
+
- Return interface types rather than concrete implementations
|
|
16
|
+
```typescript
|
|
17
|
+
interface Logger { log(msg: string): void; }
|
|
18
|
+
function createLogger(type: "console" | "file" | "remote"): Logger {
|
|
19
|
+
switch (type) {
|
|
20
|
+
case "console": return new ConsoleLogger();
|
|
21
|
+
case "file": return new FileLogger();
|
|
22
|
+
case "remote": return new RemoteLogger();
|
|
23
|
+
default: throw new InvalidLoggerTypeError(type);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Builder Pattern
|
|
29
|
+
- Use for constructing complex objects with many optional parameters
|
|
30
|
+
- Prefer over constructors with 4+ parameters
|
|
31
|
+
- Chain methods and return `this` for fluent API
|
|
32
|
+
```typescript
|
|
33
|
+
const query = new QueryBuilder()
|
|
34
|
+
.select("name", "email")
|
|
35
|
+
.from("users")
|
|
36
|
+
.where("active", true)
|
|
37
|
+
.orderBy("created_at", "desc")
|
|
38
|
+
.limit(50)
|
|
39
|
+
.build();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Singleton / Module Pattern
|
|
43
|
+
- Use for shared resources: database connections, configuration, caches
|
|
44
|
+
- In modern JS/TS: prefer module-level instances over class-based singletons
|
|
45
|
+
- Always make singletons injectable for testability
|
|
46
|
+
```typescript
|
|
47
|
+
// Module singleton (preferred)
|
|
48
|
+
const config = loadConfig();
|
|
49
|
+
export { config };
|
|
50
|
+
|
|
51
|
+
// Injectable singleton (testable)
|
|
52
|
+
let instance: DbPool | null = null;
|
|
53
|
+
export function getPool(factory = createPool): DbPool {
|
|
54
|
+
if (!instance) instance = factory();
|
|
55
|
+
return instance;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Structural Design Patterns
|
|
60
|
+
|
|
61
|
+
### Adapter Pattern
|
|
62
|
+
- Use to wrap third-party libraries behind your own interface
|
|
63
|
+
- Isolates vendor lock-in; makes swapping implementations easy
|
|
64
|
+
```typescript
|
|
65
|
+
interface StorageAdapter {
|
|
66
|
+
get(key: string): Promise<string | null>;
|
|
67
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
68
|
+
delete(key: string): Promise<void>;
|
|
69
|
+
}
|
|
70
|
+
// RedisAdapter, MemcachedAdapter, InMemoryAdapter all implement StorageAdapter
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Repository Pattern
|
|
74
|
+
- Abstract data access behind a repository interface
|
|
75
|
+
- Keep business logic free from database query details
|
|
76
|
+
```typescript
|
|
77
|
+
interface UserRepository {
|
|
78
|
+
findById(id: string): Promise<User | null>;
|
|
79
|
+
findByEmail(email: string): Promise<User | null>;
|
|
80
|
+
create(data: CreateUserDTO): Promise<User>;
|
|
81
|
+
update(id: string, data: UpdateUserDTO): Promise<User>;
|
|
82
|
+
delete(id: string): Promise<void>;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Middleware / Pipeline Pattern
|
|
87
|
+
- Chain processing steps for request handling, data transformation, or validation
|
|
88
|
+
- Each middleware receives context and a `next` function
|
|
89
|
+
```typescript
|
|
90
|
+
type Middleware<T> = (ctx: T, next: () => Promise<void>) => Promise<void>;
|
|
91
|
+
|
|
92
|
+
function compose<T>(middlewares: Middleware<T>[]): Middleware<T> {
|
|
93
|
+
return (ctx, next) => {
|
|
94
|
+
let index = -1;
|
|
95
|
+
function dispatch(i: number): Promise<void> {
|
|
96
|
+
if (i <= index) return Promise.reject(new Error("next() called multiple times"));
|
|
97
|
+
index = i;
|
|
98
|
+
const fn = i === middlewares.length ? next : middlewares[i];
|
|
99
|
+
return fn(ctx, () => dispatch(i + 1));
|
|
100
|
+
}
|
|
101
|
+
return dispatch(0);
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Behavioral Design Patterns
|
|
107
|
+
|
|
108
|
+
### Strategy Pattern
|
|
109
|
+
- Use when an algorithm needs to vary at runtime
|
|
110
|
+
- Define a common interface; inject the desired strategy
|
|
111
|
+
```typescript
|
|
112
|
+
interface CompressionStrategy {
|
|
113
|
+
compress(data: Buffer): Promise<Buffer>;
|
|
114
|
+
decompress(data: Buffer): Promise<Buffer>;
|
|
115
|
+
}
|
|
116
|
+
// GzipStrategy, BrotliStrategy, LZ4Strategy all implement CompressionStrategy
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Observer / Event Emitter Pattern
|
|
120
|
+
- Use for decoupled communication between components
|
|
121
|
+
- Prefer typed event maps over string-based events
|
|
122
|
+
```typescript
|
|
123
|
+
type EventMap = {
|
|
124
|
+
"user:created": { id: string; email: string };
|
|
125
|
+
"user:deleted": { id: string };
|
|
126
|
+
"order:completed": { orderId: string; total: number };
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
interface TypedEmitter<T extends Record<string, unknown>> {
|
|
130
|
+
on<K extends keyof T>(event: K, handler: (data: T[K]) => void): void;
|
|
131
|
+
emit<K extends keyof T>(event: K, data: T[K]): void;
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Async Patterns
|
|
136
|
+
|
|
137
|
+
### Promise Composition
|
|
138
|
+
```typescript
|
|
139
|
+
// Parallel execution — use when tasks are independent
|
|
140
|
+
const [users, orders, products] = await Promise.all([
|
|
141
|
+
fetchUsers(),
|
|
142
|
+
fetchOrders(),
|
|
143
|
+
fetchProducts(),
|
|
144
|
+
]);
|
|
145
|
+
|
|
146
|
+
// Settled — use when you need results even if some fail
|
|
147
|
+
const results = await Promise.allSettled([
|
|
148
|
+
riskyOperation1(),
|
|
149
|
+
riskyOperation2(),
|
|
150
|
+
]);
|
|
151
|
+
const successes = results.filter(r => r.status === "fulfilled");
|
|
152
|
+
const failures = results.filter(r => r.status === "rejected");
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Retry with Exponential Backoff
|
|
156
|
+
```typescript
|
|
157
|
+
async function withRetry<T>(
|
|
158
|
+
fn: () => Promise<T>,
|
|
159
|
+
options: { maxRetries: number; baseDelay: number; maxDelay: number }
|
|
160
|
+
): Promise<T> {
|
|
161
|
+
for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
|
|
162
|
+
try {
|
|
163
|
+
return await fn();
|
|
164
|
+
} catch (error) {
|
|
165
|
+
if (attempt === options.maxRetries) throw error;
|
|
166
|
+
const delay = Math.min(
|
|
167
|
+
options.baseDelay * Math.pow(2, attempt) + Math.random() * 100,
|
|
168
|
+
options.maxDelay
|
|
169
|
+
);
|
|
170
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
throw new Error("Unreachable");
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Async Iterator / Stream Processing
|
|
178
|
+
```typescript
|
|
179
|
+
async function* paginate<T>(
|
|
180
|
+
fetchPage: (cursor: string | null) => Promise<{ data: T[]; nextCursor: string | null }>
|
|
181
|
+
): AsyncGenerator<T> {
|
|
182
|
+
let cursor: string | null = null;
|
|
183
|
+
do {
|
|
184
|
+
const { data, nextCursor } = await fetchPage(cursor);
|
|
185
|
+
for (const item of data) yield item;
|
|
186
|
+
cursor = nextCursor;
|
|
187
|
+
} while (cursor !== null);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Circuit Breaker
|
|
192
|
+
```typescript
|
|
193
|
+
class CircuitBreaker {
|
|
194
|
+
private failures = 0;
|
|
195
|
+
private lastFailureTime = 0;
|
|
196
|
+
private state: "closed" | "open" | "half-open" = "closed";
|
|
197
|
+
|
|
198
|
+
constructor(
|
|
199
|
+
private readonly threshold: number,
|
|
200
|
+
private readonly resetTimeoutMs: number
|
|
201
|
+
) {}
|
|
202
|
+
|
|
203
|
+
async execute<T>(fn: () => Promise<T>): Promise<T> {
|
|
204
|
+
if (this.state === "open") {
|
|
205
|
+
if (Date.now() - this.lastFailureTime > this.resetTimeoutMs) {
|
|
206
|
+
this.state = "half-open";
|
|
207
|
+
} else {
|
|
208
|
+
throw new CircuitOpenError("Circuit breaker is open");
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
const result = await fn();
|
|
213
|
+
this.onSuccess();
|
|
214
|
+
return result;
|
|
215
|
+
} catch (error) {
|
|
216
|
+
this.onFailure();
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private onSuccess(): void {
|
|
222
|
+
this.failures = 0;
|
|
223
|
+
this.state = "closed";
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private onFailure(): void {
|
|
227
|
+
this.failures++;
|
|
228
|
+
this.lastFailureTime = Date.now();
|
|
229
|
+
if (this.failures >= this.threshold) this.state = "open";
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Error Handling Patterns
|
|
235
|
+
|
|
236
|
+
### Custom Error Hierarchy
|
|
237
|
+
```typescript
|
|
238
|
+
class AppError extends Error {
|
|
239
|
+
constructor(
|
|
240
|
+
message: string,
|
|
241
|
+
public readonly code: string,
|
|
242
|
+
public readonly statusCode: number = 500,
|
|
243
|
+
public readonly isOperational: boolean = true,
|
|
244
|
+
public readonly cause?: Error
|
|
245
|
+
) {
|
|
246
|
+
super(message);
|
|
247
|
+
this.name = this.constructor.name;
|
|
248
|
+
Error.captureStackTrace(this, this.constructor);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
class ValidationError extends AppError {
|
|
253
|
+
constructor(message: string, public readonly fields: Record<string, string[]>) {
|
|
254
|
+
super(message, "VALIDATION_ERROR", 400);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
class NotFoundError extends AppError {
|
|
259
|
+
constructor(resource: string, id: string) {
|
|
260
|
+
super(`${resource} with id '${id}' not found`, "NOT_FOUND", 404);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
class ExternalServiceError extends AppError {
|
|
265
|
+
constructor(service: string, cause: Error) {
|
|
266
|
+
super(`External service '${service}' failed: ${cause.message}`, "EXTERNAL_SERVICE_ERROR", 502, true, cause);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Result Type (Rust-inspired)
|
|
272
|
+
```typescript
|
|
273
|
+
type Result<T, E = Error> =
|
|
274
|
+
| { ok: true; value: T }
|
|
275
|
+
| { ok: false; error: E };
|
|
276
|
+
|
|
277
|
+
function ok<T>(value: T): Result<T, never> {
|
|
278
|
+
return { ok: true, value };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function err<E>(error: E): Result<never, E> {
|
|
282
|
+
return { ok: false, error };
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Usage: eliminates try/catch proliferation
|
|
286
|
+
async function parseConfig(path: string): Promise<Result<Config, ConfigError>> {
|
|
287
|
+
const raw = await readFile(path);
|
|
288
|
+
if (!raw) return err(new ConfigError("File not found"));
|
|
289
|
+
const parsed = JSON.parse(raw);
|
|
290
|
+
const validated = configSchema.safeParse(parsed);
|
|
291
|
+
if (!validated.success) return err(new ConfigError(validated.error.message));
|
|
292
|
+
return ok(validated.data);
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Graceful Degradation
|
|
297
|
+
```typescript
|
|
298
|
+
async function getUserProfile(userId: string): Promise<UserProfile> {
|
|
299
|
+
const user = await userRepo.findById(userId); // Required — throw on failure
|
|
300
|
+
if (!user) throw new NotFoundError("User", userId);
|
|
301
|
+
|
|
302
|
+
// Optional enrichment — degrade gracefully
|
|
303
|
+
const [avatar, preferences] = await Promise.allSettled([
|
|
304
|
+
avatarService.getAvatar(userId),
|
|
305
|
+
preferencesService.getPreferences(userId),
|
|
306
|
+
]);
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
...user,
|
|
310
|
+
avatar: avatar.status === "fulfilled" ? avatar.value : DEFAULT_AVATAR,
|
|
311
|
+
preferences: preferences.status === "fulfilled" ? preferences.value : DEFAULT_PREFERENCES,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Language-Specific Idioms
|
|
317
|
+
|
|
318
|
+
### TypeScript
|
|
319
|
+
- Use `unknown` instead of `any` for type-safe narrowing
|
|
320
|
+
- Prefer `interface` for object shapes; `type` for unions, intersections, and mapped types
|
|
321
|
+
- Use discriminated unions for state modeling
|
|
322
|
+
- Leverage `as const` for literal types and exhaustive checks
|
|
323
|
+
- Use branded types for domain identifiers (`type UserId = string & { __brand: "UserId" }`)
|
|
324
|
+
|
|
325
|
+
### Python
|
|
326
|
+
- Use dataclasses or Pydantic models for structured data
|
|
327
|
+
- Use context managers (`with` statement) for resource management
|
|
328
|
+
- Prefer `pathlib.Path` over string-based file operations
|
|
329
|
+
- Use type hints with `TypeVar`, `Generic`, `Protocol` for generic code
|
|
330
|
+
- Use `enum.Enum` for fixed sets of values; `@dataclass(frozen=True)` for value objects
|
|
331
|
+
|
|
332
|
+
### Go
|
|
333
|
+
- Return `(result, error)` tuples; check errors immediately
|
|
334
|
+
- Use `context.Context` for cancellation and timeout propagation
|
|
335
|
+
- Prefer composition over inheritance via struct embedding
|
|
336
|
+
- Use interfaces implicitly (no `implements` keyword)
|
|
337
|
+
- Use `defer` for cleanup; `sync.WaitGroup` for goroutine coordination
|
|
338
|
+
|
|
339
|
+
### Rust
|
|
340
|
+
- Leverage the ownership system; prefer `&str` over `String` in function signatures
|
|
341
|
+
- Use `Result<T, E>` and the `?` operator for error propagation
|
|
342
|
+
- Use `enum` for algebraic data types and state machines
|
|
343
|
+
- Implement `From<OtherError>` for custom error types to enable `?`
|
|
344
|
+
- Use `Iterator` trait methods instead of manual loops
|
package/manifest.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@botlearn/code-gen",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Complete code generation with proper architecture, error handling, type safety, and test accompaniment for OpenClaw Agent",
|
|
5
|
+
"category": "programming-assistance",
|
|
6
|
+
"author": "BotLearn",
|
|
7
|
+
"benchmarkDimension": "code-generation",
|
|
8
|
+
"expectedImprovement": 50,
|
|
9
|
+
"dependencies": {},
|
|
10
|
+
"compatibility": {
|
|
11
|
+
"openclaw": ">=0.5.0"
|
|
12
|
+
},
|
|
13
|
+
"files": {
|
|
14
|
+
"skill": "skill.md",
|
|
15
|
+
"knowledge": [
|
|
16
|
+
"knowledge/domain.md",
|
|
17
|
+
"knowledge/best-practices.md",
|
|
18
|
+
"knowledge/anti-patterns.md"
|
|
19
|
+
],
|
|
20
|
+
"strategies": [
|
|
21
|
+
"strategies/main.md"
|
|
22
|
+
],
|
|
23
|
+
"smokeTest": "tests/smoke.json",
|
|
24
|
+
"benchmark": "tests/benchmark.json"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@botlearn/code-gen",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Complete code generation with proper architecture, error handling, type safety, and test accompaniment for OpenClaw Agent",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "manifest.json",
|
|
7
|
+
"files": [
|
|
8
|
+
"manifest.json",
|
|
9
|
+
"skill.md",
|
|
10
|
+
"knowledge/",
|
|
11
|
+
"strategies/",
|
|
12
|
+
"tests/",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"botlearn",
|
|
17
|
+
"openclaw",
|
|
18
|
+
"skill",
|
|
19
|
+
"programming-assistance"
|
|
20
|
+
],
|
|
21
|
+
"author": "BotLearn",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/readai-team/botlearn-awesome-skills.git",
|
|
26
|
+
"directory": "packages/skills/code-gen"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/readai-team/botlearn-awesome-skills/tree/main/packages/skills/code-gen",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/readai-team/botlearn-awesome-skills/issues"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/skill.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-gen
|
|
3
|
+
role: Code Generation Specialist
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
triggers:
|
|
6
|
+
- "write code"
|
|
7
|
+
- "generate function"
|
|
8
|
+
- "create API"
|
|
9
|
+
- "implement feature"
|
|
10
|
+
- "code this"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Role
|
|
14
|
+
|
|
15
|
+
You are a Code Generation Specialist. When activated, you produce complete, production-ready code with proper architecture, comprehensive error handling, strong type safety, and accompanying tests. You transform high-level requirements into well-structured implementations that follow language idioms, framework conventions, and established design patterns.
|
|
16
|
+
|
|
17
|
+
# Capabilities
|
|
18
|
+
|
|
19
|
+
1. Analyze requirements to determine optimal architecture, language features, and design patterns before writing any code
|
|
20
|
+
2. Generate complete implementations with proper module structure, interface definitions, error handling, and input validation
|
|
21
|
+
3. Apply language-specific idioms and framework conventions (e.g., Pythonic patterns, idiomatic Go, modern TypeScript, Rust ownership)
|
|
22
|
+
4. Produce typed interfaces and data models that enforce correctness at compile time and document intent
|
|
23
|
+
5. Generate accompanying unit tests, integration tests, and usage examples alongside the implementation
|
|
24
|
+
6. Implement comprehensive error handling with custom error types, recovery strategies, and meaningful error messages
|
|
25
|
+
|
|
26
|
+
# Constraints
|
|
27
|
+
|
|
28
|
+
1. Never generate code without first analyzing requirements and choosing an appropriate architecture
|
|
29
|
+
2. Never omit error handling — every external interaction (I/O, network, parsing, user input) must have explicit error handling
|
|
30
|
+
3. Never produce untyped code when the language supports a type system — always define interfaces, types, or schemas
|
|
31
|
+
4. Never skip input validation — all public function parameters must be validated at the boundary
|
|
32
|
+
5. Never generate code without at least one accompanying test or usage example
|
|
33
|
+
6. Never use `any` type (TypeScript), bare `except` (Python), or equivalent type-erasure patterns unless explicitly justified
|
|
34
|
+
|
|
35
|
+
# Activation
|
|
36
|
+
|
|
37
|
+
WHEN the user requests code generation or implementation:
|
|
38
|
+
1. Analyze the requirement to identify scope, constraints, target language, and quality expectations
|
|
39
|
+
2. Select architecture and design patterns following strategies/main.md
|
|
40
|
+
3. Apply language idioms and framework conventions from knowledge/domain.md
|
|
41
|
+
4. Implement with type safety and error handling per knowledge/best-practices.md
|
|
42
|
+
5. Verify against knowledge/anti-patterns.md to avoid common code generation mistakes
|
|
43
|
+
6. Output complete implementation with types, error handling, tests, and usage documentation
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
strategy: code-gen
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
steps: 6
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Code Generation Strategy
|
|
8
|
+
|
|
9
|
+
## Step 1: Requirement Analysis
|
|
10
|
+
- Parse the user's request to identify: **target language**, **framework/runtime**, **functional requirements**, **non-functional requirements** (performance, scale, security)
|
|
11
|
+
- Classify the task type: utility function / API endpoint / data model / CLI tool / state machine / full-stack feature / library/SDK
|
|
12
|
+
- Identify input/output contract: what data comes in, what data goes out, what types are involved
|
|
13
|
+
- Determine the scope boundary: what this code is responsible for vs. what it delegates
|
|
14
|
+
- IF requirements are ambiguous THEN ask one focused clarifying question before proceeding
|
|
15
|
+
- Extract constraints: target runtime (Node.js, browser, serverless), dependencies allowed, coding standards, existing codebase conventions
|
|
16
|
+
|
|
17
|
+
## Step 2: Architecture Decision
|
|
18
|
+
- SELECT architecture pattern based on task type and complexity:
|
|
19
|
+
- Simple utility → Pure function with types and validation
|
|
20
|
+
- API endpoint → Controller + Service + Repository layers with DTO types
|
|
21
|
+
- Data pipeline → Pipeline/middleware pattern with typed stages
|
|
22
|
+
- State management → State machine with discriminated union states and typed transitions
|
|
23
|
+
- CLI tool → Command pattern with argument parsing, validation, and help generation
|
|
24
|
+
- Library/SDK → Public API with types, internal implementation, and barrel exports
|
|
25
|
+
- SELECT design patterns from knowledge/domain.md:
|
|
26
|
+
- Use Factory when construction varies by input
|
|
27
|
+
- Use Strategy when algorithm varies at runtime
|
|
28
|
+
- Use Repository when abstracting data access
|
|
29
|
+
- Use Adapter when wrapping external services
|
|
30
|
+
- Use Builder when object construction has many optional parameters
|
|
31
|
+
- DECIDE error handling strategy:
|
|
32
|
+
- Result type (functional style) for libraries and utilities
|
|
33
|
+
- Exception hierarchy (OOP style) for applications and APIs
|
|
34
|
+
- Error codes with typed payloads for cross-boundary communication
|
|
35
|
+
- DOCUMENT the chosen architecture in a brief comment block at the top of the output
|
|
36
|
+
|
|
37
|
+
## Step 3: Interface Design
|
|
38
|
+
- Define all public types, interfaces, and data transfer objects BEFORE writing implementation
|
|
39
|
+
- For each public function, specify:
|
|
40
|
+
- Parameter names and types (with validation constraints noted)
|
|
41
|
+
- Return type (including error cases)
|
|
42
|
+
- Side effects (I/O, mutations, logging)
|
|
43
|
+
- Preconditions and postconditions
|
|
44
|
+
- Apply type safety practices from knowledge/best-practices.md:
|
|
45
|
+
- Use discriminated unions for state modeling
|
|
46
|
+
- Use branded types for domain identifiers
|
|
47
|
+
- Derive types from validation schemas when possible
|
|
48
|
+
- Prefer `readonly` for immutable data
|
|
49
|
+
- Define error types specific to this module:
|
|
50
|
+
- One base error class extending the standard error
|
|
51
|
+
- Specific error subclasses for each failure mode
|
|
52
|
+
- Include contextual fields (resource name, expected vs. received values)
|
|
53
|
+
- IF the code involves an API THEN define the request/response schemas with validation
|
|
54
|
+
|
|
55
|
+
## Step 4: Implementation
|
|
56
|
+
- Implement each function following the interface contracts from Step 3
|
|
57
|
+
- Apply language idioms from knowledge/domain.md:
|
|
58
|
+
- TypeScript: strict mode, no `any`, discriminated unions, `async`/`await`
|
|
59
|
+
- Python: type hints, dataclasses/Pydantic, context managers, pathlib
|
|
60
|
+
- Go: error returns, context propagation, defer, interface composition
|
|
61
|
+
- Rust: ownership, Result/Option, trait implementations, iterators
|
|
62
|
+
- IMPLEMENT error handling at every boundary:
|
|
63
|
+
- Validate all inputs at the function entry point
|
|
64
|
+
- Wrap external calls (I/O, network, parsing) in try/catch with specific error types
|
|
65
|
+
- Provide meaningful error messages with context (field name, expected format, received value)
|
|
66
|
+
- IF the function interacts with external services THEN implement timeout, retry, and circuit breaker as appropriate
|
|
67
|
+
- Apply async patterns from knowledge/domain.md:
|
|
68
|
+
- Use `Promise.all` for independent parallel operations
|
|
69
|
+
- Use `Promise.allSettled` when partial success is acceptable
|
|
70
|
+
- Use async iterators for paginated or streaming data
|
|
71
|
+
- Implement cancellation support via AbortController or context
|
|
72
|
+
- VERIFY against anti-patterns from knowledge/anti-patterns.md:
|
|
73
|
+
- No `any` types or bare catches
|
|
74
|
+
- No silent error swallowing
|
|
75
|
+
- No hard-coded configuration
|
|
76
|
+
- No god functions (each function < 40 lines of logic)
|
|
77
|
+
- No missing input validation
|
|
78
|
+
|
|
79
|
+
## Step 5: Self-Testing
|
|
80
|
+
- Generate unit tests for every public function:
|
|
81
|
+
- **Happy path**: valid input produces expected output
|
|
82
|
+
- **Edge cases**: empty input, boundary values, maximum sizes, unicode, zero/null
|
|
83
|
+
- **Error paths**: invalid input throws the correct error type with expected message
|
|
84
|
+
- Follow Arrange-Act-Assert pattern (from knowledge/best-practices.md)
|
|
85
|
+
- Name tests descriptively: `should [expected behavior] when [condition]`
|
|
86
|
+
- For async code: test timeout behavior, cancellation, retry exhaustion
|
|
87
|
+
- For state machines: test all valid transitions and verify invalid transitions are rejected
|
|
88
|
+
- IF the code involves I/O THEN generate integration test scaffolding with mock setup
|
|
89
|
+
- Target minimum coverage:
|
|
90
|
+
- All public functions have at least one test
|
|
91
|
+
- All error branches have at least one test
|
|
92
|
+
- All state transitions have at least one test
|
|
93
|
+
|
|
94
|
+
## Step 6: Review & Output
|
|
95
|
+
- SELF-REVIEW the generated code against this checklist:
|
|
96
|
+
- [ ] All public types are defined and exported
|
|
97
|
+
- [ ] All inputs are validated at the boundary
|
|
98
|
+
- [ ] All errors are handled with specific types and contextual messages
|
|
99
|
+
- [ ] No `any`, no bare catches, no silent swallowing
|
|
100
|
+
- [ ] Functions are under 40 lines of logic each
|
|
101
|
+
- [ ] At least one test per public function
|
|
102
|
+
- [ ] Usage example is included
|
|
103
|
+
- [ ] Dependencies are explicitly imported (no implicit globals)
|
|
104
|
+
- [ ] Configuration is externalized (no hard-coded URLs, keys, or magic numbers)
|
|
105
|
+
- [ ] Code follows the target language's naming conventions and idioms
|
|
106
|
+
- IF any check fails THEN loop back to the relevant step and fix
|
|
107
|
+
- FORMAT the output in this order:
|
|
108
|
+
1. Architecture comment block (pattern chosen, rationale)
|
|
109
|
+
2. Type definitions and interfaces
|
|
110
|
+
3. Error types
|
|
111
|
+
4. Implementation
|
|
112
|
+
5. Tests
|
|
113
|
+
6. Usage example
|
|
114
|
+
- PROVIDE brief inline comments for non-obvious logic (the "why", not the "what")
|