@martinffx/atelier 1.4.0 → 3.0.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 (93) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +95 -220
  3. package/agents/architect.md +6 -6
  4. package/agents/oracle.md +1 -1
  5. package/agents/{recon.md → sentinel.md} +3 -3
  6. package/dist/atelier.js +167 -26
  7. package/package.json +2 -1
  8. package/skills/atelier-orchestrator/SKILL.md +180 -0
  9. package/skills/atelier-setup/SKILL.md +80 -0
  10. package/skills/code-review/SKILL.md +2 -2
  11. package/skills/code-review/references/reviewers.md +3 -3
  12. package/skills/code-review/references/rq.md +9 -9
  13. package/skills/code-subagents/SKILL.md +44 -75
  14. package/skills/code-subagents/references/batch-reviewer-prompt.md +44 -0
  15. package/skills/code-subagents/references/implementor-prompt.md +10 -11
  16. package/skills/spec-brainstorm/SKILL.md +21 -16
  17. package/skills/spec-finish/SKILL.md +14 -14
  18. package/skills/spec-implement/SKILL.md +42 -42
  19. package/skills/spec-plan/SKILL.md +72 -26
  20. package/skills/spec-plan/references/plan_template.md +77 -0
  21. package/skills/code-subagents/references/code-quality-reviewer-prompt.md +0 -48
  22. package/skills/code-subagents/references/spec-reviewer-prompt.md +0 -62
  23. package/skills/python-architecture/SKILL.md +0 -148
  24. package/skills/python-architecture/references/data-modeling.md +0 -558
  25. package/skills/python-architecture/references/ddd.md +0 -569
  26. package/skills/python-architecture/references/functional-core.md +0 -337
  27. package/skills/python-build-tools/SKILL.md +0 -153
  28. package/skills/python-build-tools/references/basedpyright.md +0 -321
  29. package/skills/python-build-tools/references/ruff.md +0 -225
  30. package/skills/python-build-tools/references/uv.md +0 -257
  31. package/skills/python-fastapi/SKILL.md +0 -184
  32. package/skills/python-fastapi/references/api-design.md +0 -563
  33. package/skills/python-fastapi/references/dependencies.md +0 -479
  34. package/skills/python-fastapi/references/middleware.md +0 -475
  35. package/skills/python-fastapi/references/validation.md +0 -497
  36. package/skills/python-modern-python/SKILL.md +0 -201
  37. package/skills/python-modern-python/references/async.md +0 -76
  38. package/skills/python-modern-python/references/pattern-matching.md +0 -89
  39. package/skills/python-modern-python/references/typing.md +0 -96
  40. package/skills/python-monorepo/SKILL.md +0 -146
  41. package/skills/python-monorepo/references/docker.md +0 -515
  42. package/skills/python-monorepo/references/namespace-packages.md +0 -426
  43. package/skills/python-monorepo/references/workspace-config.md +0 -341
  44. package/skills/python-sqlalchemy/SKILL.md +0 -119
  45. package/skills/python-sqlalchemy/references/async.md +0 -51
  46. package/skills/python-sqlalchemy/references/models.md +0 -67
  47. package/skills/python-sqlalchemy/references/queries.md +0 -57
  48. package/skills/python-temporal/SKILL.md +0 -128
  49. package/skills/python-temporal/references/patterns.md +0 -87
  50. package/skills/python-temporal/references/testing.md +0 -54
  51. package/skills/python-testing/SKILL.md +0 -161
  52. package/skills/python-testing/references/boundaries.md +0 -449
  53. package/skills/python-testing/references/mocking.md +0 -449
  54. package/skills/python-testing/references/pytest.md +0 -524
  55. package/skills/spec-orchestrator/SKILL.md +0 -145
  56. package/skills/typescript-api-design/SKILL.md +0 -396
  57. package/skills/typescript-api-design/references/error-responses.md +0 -469
  58. package/skills/typescript-build-tools/SKILL.md +0 -447
  59. package/skills/typescript-build-tools/references/biome.md +0 -436
  60. package/skills/typescript-build-tools/references/bun.md +0 -432
  61. package/skills/typescript-build-tools/references/turborepo.md +0 -426
  62. package/skills/typescript-build-tools/references/vitest.md +0 -518
  63. package/skills/typescript-drizzle-orm/SKILL.md +0 -398
  64. package/skills/typescript-drizzle-orm/references/cloudflare.md +0 -392
  65. package/skills/typescript-drizzle-orm/references/entity-pattern.md +0 -412
  66. package/skills/typescript-drizzle-orm/references/postgresql.md +0 -191
  67. package/skills/typescript-drizzle-orm/references/repository-pattern.md +0 -479
  68. package/skills/typescript-drizzle-orm/references/sqlite.md +0 -291
  69. package/skills/typescript-dynamodb-toolbox/SKILL.md +0 -370
  70. package/skills/typescript-dynamodb-toolbox/references/entity-layer.md +0 -574
  71. package/skills/typescript-dynamodb-toolbox/references/error-handling.md +0 -495
  72. package/skills/typescript-dynamodb-toolbox/references/modeling.md +0 -332
  73. package/skills/typescript-dynamodb-toolbox/references/repository-layer.md +0 -631
  74. package/skills/typescript-dynamodb-toolbox/references/testing.md +0 -718
  75. package/skills/typescript-dynamodb-toolbox/references/transactions.md +0 -423
  76. package/skills/typescript-effect-ts/SKILL.md +0 -341
  77. package/skills/typescript-effect-ts/references/core.md +0 -412
  78. package/skills/typescript-effect-ts/references/error-handling.md +0 -468
  79. package/skills/typescript-effect-ts/references/resources.md +0 -476
  80. package/skills/typescript-effect-ts/references/schema.md +0 -536
  81. package/skills/typescript-effect-ts/references/services.md +0 -461
  82. package/skills/typescript-fastify/SKILL.md +0 -405
  83. package/skills/typescript-fastify/references/plugins.md +0 -329
  84. package/skills/typescript-fastify/references/typeid.md +0 -315
  85. package/skills/typescript-functional-patterns/SKILL.md +0 -402
  86. package/skills/typescript-functional-patterns/references/adts.md +0 -497
  87. package/skills/typescript-functional-patterns/references/branded-types.md +0 -542
  88. package/skills/typescript-functional-patterns/references/migration-guide.md +0 -695
  89. package/skills/typescript-functional-patterns/references/option-result.md +0 -585
  90. package/skills/typescript-testing/SKILL.md +0 -353
  91. package/skills/typescript-testing/references/mocking.md +0 -675
  92. package/skills/typescript-testing/references/msw.md +0 -852
  93. package/skills/typescript-testing/references/snapshot-testing.md +0 -774
@@ -1,536 +0,0 @@
1
- # Effect Schema
2
-
3
- Effect Schema is a powerful library for defining, validating, and transforming data structures with full TypeScript type inference.
4
-
5
- ## Basic Schemas
6
-
7
- ### Primitive Types
8
-
9
- ```typescript
10
- import { Schema } from "effect"
11
-
12
- // Basic primitives
13
- const str = Schema.String // Schema<string>
14
- const num = Schema.Number // Schema<number>
15
- const bool = Schema.Boolean // Schema<boolean>
16
- const bigint = Schema.BigInt // Schema<bigint>
17
-
18
- // Literals
19
- const literal = Schema.Literal("active", "inactive")
20
- // Schema<"active" | "inactive">
21
-
22
- // Unknown and Any
23
- const unknown = Schema.Unknown // Schema<unknown>
24
- const any = Schema.Any // Schema<any>
25
-
26
- // Void and Undefined
27
- const voidSchema = Schema.Void
28
- const undef = Schema.Undefined
29
- const nil = Schema.Null
30
- ```
31
-
32
- ### Objects (Struct)
33
-
34
- ```typescript
35
- import { Schema } from "effect"
36
-
37
- const User = Schema.Struct({
38
- id: Schema.String,
39
- name: Schema.String,
40
- email: Schema.String,
41
- age: Schema.Number,
42
- isActive: Schema.Boolean
43
- })
44
-
45
- // Infer TypeScript type
46
- type User = Schema.Schema.Type<typeof User>
47
- // { id: string; name: string; email: string; age: number; isActive: boolean }
48
- ```
49
-
50
- ### Optional Fields
51
-
52
- ```typescript
53
- import { Schema } from "effect"
54
-
55
- const User = Schema.Struct({
56
- id: Schema.String,
57
- name: Schema.String,
58
- bio: Schema.optional(Schema.String), // string | undefined
59
- age: Schema.optional(Schema.Number, { exact: true }), // number | undefined (no null)
60
- nickname: Schema.optionalWith(Schema.String, { default: () => "Anonymous" })
61
- })
62
-
63
- // With default value
64
- const Config = Schema.Struct({
65
- host: Schema.String,
66
- port: Schema.optionalWith(Schema.Number, { default: () => 3000 }),
67
- debug: Schema.optionalWith(Schema.Boolean, { default: () => false })
68
- })
69
- ```
70
-
71
- ### Arrays and Tuples
72
-
73
- ```typescript
74
- import { Schema } from "effect"
75
-
76
- // Array
77
- const Numbers = Schema.Array(Schema.Number)
78
- // Schema<number[]>
79
-
80
- // Non-empty array
81
- const NonEmptyNumbers = Schema.NonEmptyArray(Schema.Number)
82
- // Schema<[number, ...number[]]>
83
-
84
- // Tuple
85
- const Point = Schema.Tuple(Schema.Number, Schema.Number)
86
- // Schema<[number, number]>
87
-
88
- // Tuple with rest
89
- const Args = Schema.Tuple(
90
- [Schema.String], // First element
91
- Schema.Number // Rest elements
92
- )
93
- // Schema<[string, ...number[]]>
94
- ```
95
-
96
- ### Unions
97
-
98
- ```typescript
99
- import { Schema } from "effect"
100
-
101
- // Union of schemas
102
- const StringOrNumber = Schema.Union(Schema.String, Schema.Number)
103
- // Schema<string | number>
104
-
105
- // Discriminated union
106
- const Shape = Schema.Union(
107
- Schema.Struct({
108
- type: Schema.Literal("circle"),
109
- radius: Schema.Number
110
- }),
111
- Schema.Struct({
112
- type: Schema.Literal("rectangle"),
113
- width: Schema.Number,
114
- height: Schema.Number
115
- })
116
- )
117
- // Schema<{ type: "circle"; radius: number } | { type: "rectangle"; width: number; height: number }>
118
- ```
119
-
120
- ### Records
121
-
122
- ```typescript
123
- import { Schema } from "effect"
124
-
125
- // Record with string keys
126
- const StringRecord = Schema.Record({
127
- key: Schema.String,
128
- value: Schema.Number
129
- })
130
- // Schema<Record<string, number>>
131
-
132
- // Record with literal keys
133
- const StatusCounts = Schema.Record({
134
- key: Schema.Literal("active", "inactive", "pending"),
135
- value: Schema.Number
136
- })
137
- // Schema<Record<"active" | "inactive" | "pending", number>>
138
- ```
139
-
140
- ## Decoding and Encoding
141
-
142
- ### Synchronous Decoding
143
-
144
- ```typescript
145
- import { Schema } from "effect"
146
-
147
- const User = Schema.Struct({
148
- id: Schema.String,
149
- name: Schema.String,
150
- age: Schema.Number
151
- })
152
-
153
- // Decode unknown data (throws on failure)
154
- const user = Schema.decodeUnknownSync(User)({
155
- id: "123",
156
- name: "Alice",
157
- age: 30
158
- })
159
- // { id: "123", name: "Alice", age: 30 }
160
-
161
- // Throws ParseError on invalid data
162
- try {
163
- Schema.decodeUnknownSync(User)({ id: 123 }) // id should be string
164
- } catch (e) {
165
- console.log(e) // ParseError
166
- }
167
- ```
168
-
169
- ### Effect-based Decoding
170
-
171
- ```typescript
172
- import { Schema, Effect } from "effect"
173
-
174
- const User = Schema.Struct({
175
- id: Schema.String,
176
- name: Schema.String
177
- })
178
-
179
- // Returns Effect<User, ParseError, never>
180
- const decode = Schema.decodeUnknown(User)
181
-
182
- const program = Effect.gen(function* () {
183
- const user = yield* decode({ id: "123", name: "Alice" })
184
- return user
185
- })
186
- ```
187
-
188
- ### Either-based Decoding
189
-
190
- ```typescript
191
- import { Schema, Either } from "effect"
192
-
193
- const User = Schema.Struct({
194
- id: Schema.String,
195
- name: Schema.String
196
- })
197
-
198
- // Returns Either<User, ParseError>
199
- const result = Schema.decodeUnknownEither(User)({
200
- id: "123",
201
- name: "Alice"
202
- })
203
-
204
- if (Either.isRight(result)) {
205
- console.log(result.right) // User
206
- } else {
207
- console.log(result.left) // ParseError
208
- }
209
- ```
210
-
211
- ### Encoding
212
-
213
- ```typescript
214
- import { Schema } from "effect"
215
-
216
- const User = Schema.Struct({
217
- id: Schema.String,
218
- createdAt: Schema.Date // Encodes to ISO string
219
- })
220
-
221
- type User = Schema.Schema.Type<typeof User>
222
- // { id: string; createdAt: Date }
223
-
224
- type UserEncoded = Schema.Schema.Encoded<typeof User>
225
- // { id: string; createdAt: string }
226
-
227
- const user: User = { id: "123", createdAt: new Date() }
228
-
229
- // Encode to serializable form
230
- const encoded = Schema.encodeSync(User)(user)
231
- // { id: "123", createdAt: "2024-01-15T..." }
232
- ```
233
-
234
- ## Transformations
235
-
236
- ### Built-in Transformations
237
-
238
- ```typescript
239
- import { Schema } from "effect"
240
-
241
- // String to Number
242
- const NumberFromString = Schema.NumberFromString
243
- Schema.decodeUnknownSync(NumberFromString)("42") // 42
244
-
245
- // Date from string
246
- const DateFromString = Schema.Date
247
- Schema.decodeUnknownSync(DateFromString)("2024-01-15") // Date object
248
-
249
- // Trim whitespace
250
- const Trimmed = Schema.Trimmed
251
- Schema.decodeUnknownSync(Trimmed)(" hello ") // "hello"
252
-
253
- // Lowercase
254
- const Lowercased = Schema.Lowercased
255
- Schema.decodeUnknownSync(Lowercased)("HELLO") // "hello"
256
- ```
257
-
258
- ### Custom Transformations
259
-
260
- ```typescript
261
- import { Schema } from "effect"
262
-
263
- // Transform between encoded and decoded types
264
- const Cents = Schema.transform(
265
- Schema.Number, // From (encoded)
266
- Schema.Number, // To (decoded)
267
- {
268
- decode: (n) => Math.round(n * 100), // dollars to cents
269
- encode: (n) => n / 100 // cents to dollars
270
- }
271
- )
272
-
273
- const price = Schema.decodeUnknownSync(Cents)(19.99) // 1999
274
- const encoded = Schema.encodeSync(Cents)(1999) // 19.99
275
- ```
276
-
277
- ### Transform with Effects
278
-
279
- ```typescript
280
- import { Schema, Effect } from "effect"
281
-
282
- // Async transformation
283
- const UserFromId = Schema.transformOrFail(
284
- Schema.String,
285
- Schema.Struct({ id: Schema.String, name: Schema.String }),
286
- {
287
- decode: (id) => Effect.tryPromise({
288
- try: () => fetchUser(id),
289
- catch: () => new Error(`User not found: ${id}`)
290
- }),
291
- encode: (user) => Effect.succeed(user.id)
292
- }
293
- )
294
- ```
295
-
296
- ## Refinements and Filters
297
-
298
- ### Built-in Refinements
299
-
300
- ```typescript
301
- import { Schema } from "effect"
302
-
303
- // String refinements
304
- const NonEmpty = Schema.NonEmptyString
305
- const Email = Schema.String.pipe(Schema.pattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/))
306
- const MinLength = Schema.String.pipe(Schema.minLength(3))
307
- const MaxLength = Schema.String.pipe(Schema.maxLength(100))
308
-
309
- // Number refinements
310
- const Positive = Schema.Number.pipe(Schema.positive())
311
- const NonNegative = Schema.Number.pipe(Schema.nonNegative())
312
- const Int = Schema.Number.pipe(Schema.int())
313
- const Between = Schema.Number.pipe(Schema.between(1, 100))
314
-
315
- // Array refinements
316
- const NonEmptyArray = Schema.Array(Schema.String).pipe(Schema.minItems(1))
317
- const MaxItems = Schema.Array(Schema.Number).pipe(Schema.maxItems(10))
318
- ```
319
-
320
- ### Custom Refinements
321
-
322
- ```typescript
323
- import { Schema } from "effect"
324
-
325
- // Filter with predicate
326
- const EvenNumber = Schema.Number.pipe(
327
- Schema.filter((n) => n % 2 === 0, {
328
- message: () => "Expected even number"
329
- })
330
- )
331
-
332
- // Brand for nominal typing
333
- const UserId = Schema.String.pipe(Schema.brand("UserId"))
334
- type UserId = Schema.Schema.Type<typeof UserId>
335
- // string & Brand<"UserId">
336
-
337
- const OrderId = Schema.String.pipe(Schema.brand("OrderId"))
338
- type OrderId = Schema.Schema.Type<typeof OrderId>
339
-
340
- // Cannot mix: userId = orderId would be type error
341
- ```
342
-
343
- ## Common Patterns
344
-
345
- ### API Request/Response Schemas
346
-
347
- ```typescript
348
- import { Schema } from "effect"
349
-
350
- // Request schema
351
- const CreateUserRequest = Schema.Struct({
352
- name: Schema.NonEmptyString,
353
- email: Schema.String.pipe(
354
- Schema.pattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)
355
- ),
356
- age: Schema.Number.pipe(Schema.int(), Schema.between(0, 150))
357
- })
358
-
359
- // Response schema (includes generated fields)
360
- const UserResponse = Schema.Struct({
361
- id: Schema.String,
362
- name: Schema.String,
363
- email: Schema.String,
364
- age: Schema.Number,
365
- createdAt: Schema.Date
366
- })
367
-
368
- // List response with pagination
369
- const UsersListResponse = Schema.Struct({
370
- data: Schema.Array(UserResponse),
371
- total: Schema.Number,
372
- page: Schema.Number,
373
- pageSize: Schema.Number
374
- })
375
- ```
376
-
377
- ### Configuration Schema
378
-
379
- ```typescript
380
- import { Schema } from "effect"
381
-
382
- const DatabaseConfig = Schema.Struct({
383
- host: Schema.NonEmptyString,
384
- port: Schema.Number.pipe(Schema.int(), Schema.between(1, 65535)),
385
- database: Schema.NonEmptyString,
386
- username: Schema.NonEmptyString,
387
- password: Schema.NonEmptyString,
388
- ssl: Schema.optionalWith(Schema.Boolean, { default: () => false }),
389
- poolSize: Schema.optionalWith(
390
- Schema.Number.pipe(Schema.int(), Schema.positive()),
391
- { default: () => 10 }
392
- )
393
- })
394
-
395
- const AppConfig = Schema.Struct({
396
- env: Schema.Literal("development", "staging", "production"),
397
- port: Schema.Number.pipe(Schema.int(), Schema.between(1, 65535)),
398
- database: DatabaseConfig,
399
- logLevel: Schema.optionalWith(
400
- Schema.Literal("debug", "info", "warn", "error"),
401
- { default: () => "info" as const }
402
- )
403
- })
404
- ```
405
-
406
- ### Discriminated Union for Events
407
-
408
- ```typescript
409
- import { Schema } from "effect"
410
-
411
- const UserCreated = Schema.Struct({
412
- type: Schema.Literal("UserCreated"),
413
- userId: Schema.String,
414
- email: Schema.String,
415
- timestamp: Schema.Date
416
- })
417
-
418
- const UserUpdated = Schema.Struct({
419
- type: Schema.Literal("UserUpdated"),
420
- userId: Schema.String,
421
- changes: Schema.Record({ key: Schema.String, value: Schema.Unknown }),
422
- timestamp: Schema.Date
423
- })
424
-
425
- const UserDeleted = Schema.Struct({
426
- type: Schema.Literal("UserDeleted"),
427
- userId: Schema.String,
428
- timestamp: Schema.Date
429
- })
430
-
431
- const UserEvent = Schema.Union(UserCreated, UserUpdated, UserDeleted)
432
- type UserEvent = Schema.Schema.Type<typeof UserEvent>
433
-
434
- // Handle events with exhaustive matching
435
- const handleEvent = (event: UserEvent) => {
436
- switch (event.type) {
437
- case "UserCreated":
438
- return `User ${event.userId} created`
439
- case "UserUpdated":
440
- return `User ${event.userId} updated`
441
- case "UserDeleted":
442
- return `User ${event.userId} deleted`
443
- }
444
- }
445
- ```
446
-
447
- ### Extend and Compose Schemas
448
-
449
- ```typescript
450
- import { Schema } from "effect"
451
-
452
- // Base schema
453
- const BaseEntity = Schema.Struct({
454
- id: Schema.String,
455
- createdAt: Schema.Date,
456
- updatedAt: Schema.Date
457
- })
458
-
459
- // Extend with additional fields
460
- const User = Schema.Struct({
461
- ...BaseEntity.fields,
462
- name: Schema.String,
463
- email: Schema.String
464
- })
465
-
466
- // Pick specific fields
467
- const UserSummary = Schema.pick(User, "id", "name")
468
- // Schema<{ id: string; name: string }>
469
-
470
- // Omit specific fields
471
- const UserWithoutDates = Schema.omit(User, "createdAt", "updatedAt")
472
- // Schema<{ id: string; name: string; email: string }>
473
-
474
- // Make all fields optional
475
- const PartialUser = Schema.partial(User)
476
- // Schema<{ id?: string; name?: string; ... }>
477
- ```
478
-
479
- ## Error Handling
480
-
481
- ### Parse Errors
482
-
483
- ```typescript
484
- import { Schema, Either } from "effect"
485
-
486
- const User = Schema.Struct({
487
- id: Schema.String,
488
- age: Schema.Number.pipe(Schema.positive())
489
- })
490
-
491
- const result = Schema.decodeUnknownEither(User)({
492
- id: 123, // Wrong type
493
- age: -5 // Negative
494
- })
495
-
496
- if (Either.isLeft(result)) {
497
- // Access detailed error information
498
- const error = result.left
499
- console.log(error.message)
500
- // Contains path, expected type, actual value
501
- }
502
- ```
503
-
504
- ### Custom Error Messages
505
-
506
- ```typescript
507
- import { Schema } from "effect"
508
-
509
- const Email = Schema.String.pipe(
510
- Schema.pattern(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, {
511
- message: () => "Invalid email format"
512
- })
513
- )
514
-
515
- const Age = Schema.Number.pipe(
516
- Schema.between(0, 150, {
517
- message: () => "Age must be between 0 and 150"
518
- })
519
- )
520
-
521
- const Password = Schema.String.pipe(
522
- Schema.minLength(8, { message: () => "Password must be at least 8 characters" }),
523
- Schema.pattern(/[A-Z]/, { message: () => "Password must contain uppercase" }),
524
- Schema.pattern(/[0-9]/, { message: () => "Password must contain a number" })
525
- )
526
- ```
527
-
528
- ## Best Practices
529
-
530
- 1. **Infer types from schemas** - Use `Schema.Schema.Type<typeof X>` instead of manual types
531
- 2. **Use brands for domain types** - Prevents mixing IDs of different entities
532
- 3. **Validate at boundaries** - Decode external data early, work with typed data internally
533
- 4. **Compose schemas** - Build complex schemas from simpler ones
534
- 5. **Add custom error messages** - Make validation errors user-friendly
535
- 6. **Use transformations** - Handle format differences between API and domain
536
- 7. **Keep schemas close to usage** - Define schemas where they're used or in a shared module