[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6ENBMFAMMK7C9JPBAMR09AT":3,"skill-same:01M6ENBMFAMMK7C9JPBAMR09AT":112},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":35,"linkOnly":36,"markdownContent":37,"markdownBody":38,"frontMatter":39,"refName":40,"commitSha":41,"skillDirectory":42,"forksCount":43,"repositoryHtmlUrl":44,"repositoryHomepageUrl":6,"ownerHtmlUrl":45,"ownerBlogUrl":6,"ownerDescription":46,"updatedAt":47,"install":48,"resources":61},"01M6ENBMFAMMK7C9JPBAMR09AT","effect-ts",null,"Use when working with Effect-TS patterns, services, layers, schemas, error handling, streams, concurrency, or writing\u002Frefactoring code that imports from 'effect'. Also covers Svelte 5 + Effect integration and conduit's ongoing Effect migration.","dibstern\u002Fconduit","dibstern","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F16970307?v=4","01M6ENBH1PHAQ5RZZTR2TKTRA7","David Stern","01M6ENBH5ZBECS0MFBF0F10V20",15,"MIT","https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34],"effect","effect ts","writing","code","error handling","integration","services","concurrency","conduit","refactoring","use","migration","svelte 5","patterns","svelte","error","2026-11-10 10:12:30",false,"---\nname: effect-ts\ndescription: Use when working with Effect-TS patterns, services, layers, schemas, error handling, streams, concurrency, or writing\u002Frefactoring code that imports from 'effect'. Also covers Svelte 5 + Effect integration and conduit's ongoing Effect migration.\n---\n\n# Effect-TS Expert\n\nExpert guidance for functional programming with the Effect library — typed errors, dependency injection, composability,\nconcurrency, and testing patterns. Tailored for the conduit codebase (Svelte 5 + Node.js daemon, mid-migration to Effect).\n\n## Prerequisites Check\n\nBefore starting any Effect-related work, verify the Effect-TS source code exists at `~\u002Fsrc\u002Fpersonal\u002F.effect`.\n\n**If missing, stop immediately and inform the user.** Clone it before proceeding:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002FEffect-TS\u002Feffect.git ~\u002Fsrc\u002Fpersonal\u002F.effect\n```\n\n## Research Strategy\n\nEffect-TS has many ways to accomplish the same task. Proactively research best practices using the Agent tool to spawn\nresearch agents when working with Effect patterns, especially for moderate to high complexity tasks.\n\n### Research Sources (Priority Order)\n\n1. **Codebase Patterns First** — Examine similar patterns in the current project before implementing. If Effect patterns\n   exist in the codebase, follow them for consistency. If no patterns exist, skip this step.\n\n2. **Effect Source Code** — For complex type errors, unclear behavior, or implementation details, examine the Effect\n   source at `~\u002Fsrc\u002Fpersonal\u002F.effect\u002Fpackages\u002Feffect\u002Fsrc\u002F`. This contains the core Effect logic and modules.\n\n### When to Research\n\n**HIGH Priority (Always Research):**\n\n- Implementing Services, Layers, or complex dependency injection\n- Error handling with multiple error types or complex error hierarchies\n- Stream-based operations and reactive patterns\n- Resource management with scoped effects and cleanup\n- Concurrent\u002Fparallel operations and performance-critical code\n- Testing patterns, especially unfamiliar test scenarios\n\n**MEDIUM Priority (Research if Complex):**\n\n- Refactoring imperative code (try-catch, promises) to Effect patterns\n- Adding new service dependencies or restructuring service layers\n- Custom error types or extending existing error hierarchies\n- Integrations with external systems (databases, APIs, third-party services)\n\n### Research Approach\n\n- Spawn multiple concurrent agents when investigating multiple related patterns\n- Focus on canonical, readable, and maintainable solutions over clever optimizations\n- Verify against existing codebase patterns for consistency (if patterns exist)\n- When multiple approaches are possible, research to find the most idiomatic Effect-TS solution\n\n## Core Principles\n\n### Error Handling\n\n- Use Effect's typed error system instead of throwing exceptions\n- Define descriptive error types with `Data.TaggedError` or `Schema.TaggedError` (serializable)\n- Use `Effect.fail`, `Effect.catchTag`, `Effect.catchAll` for error control flow\n- Categorize: expected rejections, domain errors, defects, interruptions, unknown\u002Fforeign\n- See `.\u002Freferences\u002Fcritical-rules.md` for forbidden patterns\n- See `.\u002Freferences\u002Ferror-handling.md` for comprehensive patterns\n\n### Dependency Injection\n\n- Implement DI using Services and Layers\n- Define services with `Context.Tag` or `Effect.Service` (simplified)\n- Compose layers with `Layer.merge`, `Layer.provide`, `Layer.provideMerge`\n- Provide layers at the composition root, not scattered through business logic\n- See `.\u002Freferences\u002Flayers.md` for full patterns\n\n### Composability\n\n- Leverage Effect's composability for complex operations\n- Use appropriate constructors: `Effect.succeed`, `Effect.fail`, `Effect.tryPromise`, `Effect.try`\n- Apply proper resource management with scoped effects\n- Chain with `Effect.flatMap`, `Effect.map`, `Effect.tap`\n\n### Code Quality\n\n- Write type-safe code that leverages Effect's type system\n- Use `Effect.gen` for readable sequential code (preferred)\n- Use `pipe` for simple one-liner transformations\n- Prefer `Effect.fn()` for named functions — automatic telemetry and better stack traces\n- Implement proper testing patterns using `@effect\u002Fvitest`\n\n## Critical Rules\n\n**Read `.\u002Freferences\u002Fcritical-rules.md` before writing any Effect code.** Key rules:\n\n### INEFFECTIVE: try-catch in Effect.gen\n\nEffect failures are returned as exits, not thrown. `try-catch` inside `Effect.gen` will NOT catch Effect failures.\n\n```typescript\n\u002F\u002F WRONG — catches nothing\nEffect.gen(function* () {\n  try { const r = yield* someEffect } catch (e) { \u002F* never runs *\u002F }\n})\n\n\u002F\u002F RIGHT\nEffect.gen(function* () {\n  const result = yield* Effect.catchTag(someEffect, \"MyError\", (e) => Effect.succeed(fallback))\n})\n```\n\n### AVOID: Type assertions (`as never`, `as any`, `as unknown`)\n\nFix underlying type issues instead. Occasional assertions for poorly-typed external libraries are acceptable if documented.\n\n### RECOMMENDED: `return yield*` for errors\n\nMakes termination explicit and prevents unreachable-code warnings:\n\n```typescript\nEffect.gen(function* () {\n  if (bad) {\n    return yield* Effect.fail(new MyError({ reason: \"bad\" }))\n  }\n  return yield* doWork()\n})\n```\n\n## Quick Reference\n\n### The Effect Type\n\n```typescript\nEffect\u003CSuccess, Error, Requirements>\n\u002F\u002F     ^        ^       ^\n\u002F\u002F     |        |       └── Services\u002Fdependencies needed (Context)\n\u002F\u002F     |        └────────── Typed error channel\n\u002F\u002F     └─────────────────── Success value type\n```\n\n### Creating Effects\n\n```typescript\nEffect.succeed(value)           \u002F\u002F Wrap success value\nEffect.fail(error)              \u002F\u002F Create failed effect\nEffect.tryPromise(fn)           \u002F\u002F Wrap promise-returning function (rejects → typed error)\nEffect.try(fn)                  \u002F\u002F Wrap synchronous throwing function\nEffect.sync(fn)                 \u002F\u002F Wrap synchronous non-throwing function\nEffect.promise(fn)              \u002F\u002F Wrap promise (rejects → defect — prefer tryPromise)\n```\n\n### Composing Effects\n\n```typescript\nEffect.flatMap(effect, fn)      \u002F\u002F Chain effects\nEffect.map(effect, fn)          \u002F\u002F Transform success value\nEffect.tap(effect, fn)          \u002F\u002F Side effect without changing value\nEffect.all([...effects])        \u002F\u002F Run effects (concurrency configurable)\nEffect.forEach(items, fn)       \u002F\u002F Map over items with effects\n\n\u002F\u002F Collect ALL errors (not just first)\nEffect.all([e1, e2, e3], { mode: \"validate\" })\n\n\u002F\u002F Partial success handling\nEffect.partition([e1, e2, e3])  \u002F\u002F Returns [failures, successes]\n```\n\n### Error Handling\n\n```typescript\n\u002F\u002F Define typed errors with Data.TaggedError (preferred)\nclass UserNotFoundError extends Data.TaggedError(\"UserNotFoundError\")\u003C{\n  userId: string\n}> {}\n\n\u002F\u002F Direct yield of errors in gen (no Effect.fail wrapper needed)\nEffect.gen(function* () {\n  if (!user) return yield* new UserNotFoundError({ userId })\n})\n\nEffect.catchTag(effect, tag, fn) \u002F\u002F Handle specific error tag\nEffect.catchTags(effect, { ... }) \u002F\u002F Handle multiple tags\nEffect.catchAll(effect, fn)      \u002F\u002F Handle all errors\nEffect.result(effect)            \u002F\u002F Convert to Exit value\nEffect.either(effect)            \u002F\u002F Convert to Either\u003CE, A>\nEffect.orElse(effect, alt)       \u002F\u002F Fallback effect\n```\n\n### Error Taxonomy\n\n| Category                | Examples                   | Handling                  |\n| ----------------------- | -------------------------- | ------------------------- |\n| **Expected Rejections** | User cancel, deny          | Graceful exit, no retry   |\n| **Domain Errors**       | Validation, business rules | Show to user, don't retry |\n| **Defects**             | Bugs, assertions           | Log + alert, investigate  |\n| **Interruptions**       | Fiber cancel, timeout      | Cleanup, may retry        |\n| **Unknown\u002FForeign**     | Thrown exceptions          | Normalize at boundary     |\n\n### Pattern Matching (Match Module)\n\n```typescript\nimport { Match } from \"effect\"\n\n\u002F\u002F Type-safe exhaustive matching on tagged errors\nconst handleError = Match.type\u003CAppError>().pipe(\n  Match.tag(\"UserCancelledError\", () => null),\n  Match.tag(\"ValidationError\", (e) => e.message),\n  Match.tag(\"NetworkError\", () => \"Connection failed\"),\n  Match.exhaustive  \u002F\u002F Compile error if case missing\n)\n\n\u002F\u002F Cleaner than chained catchTag\nEffect.catchAll(effect, (error) =>\n  Match.value(error).pipe(\n    Match.tag(\"A\", handleA),\n    Match.tag(\"B\", handleB),\n    Match.exhaustive\n  )\n)\n```\n\n### Services and Layers\n\n```typescript\n\u002F\u002F Pattern 1: Context.Tag (implementation provided separately via Layer)\nclass MyService extends Context.Tag(\"MyService\")\u003CMyService, { ... }>() {}\nconst MyServiceLive = Layer.succeed(MyService, { ... })\n\n\u002F\u002F Pattern 2: Effect.Service (default implementation bundled)\nclass UserRepo extends Effect.Service\u003CUserRepo>()(\"UserRepo\", {\n  effect: Effect.gen(function* () {\n    const db = yield* Database\n    return { findAll: db.query(\"SELECT * FROM users\") }\n  }),\n  dependencies: [Database.Default],\n  accessors: true  \u002F\u002F Auto-generate method accessors\n}) {}\n\n\u002F\u002F Pattern 3: Context.Reference (defaultable tags — 3.11.0+)\nclass SpecialNumber extends Context.Reference\u003CSpecialNumber>()(\n  \"SpecialNumber\",\n  { defaultValue: () => 2048 }\n) {}\n```\n\n### Generator Pattern\n\n```typescript\n\u002F\u002F Effect.gen — recommended for sequential code\nEffect.gen(function* () {\n  const a = yield* effectA\n  const b = yield* effectB\n  return result\n})\n\n\u002F\u002F Effect.fn — automatic tracing\u002Ftelemetry (preferred for named functions)\nconst fetchUser = Effect.fn(\"fetchUser\")(function* (id: string) {\n  const db = yield* Database\n  return yield* db.query(id)\n})\n```\n\n### Running Effects\n\n```typescript\nEffect.runSync(effect)           \u002F\u002F Sync, throws on async\u002Ferror\nEffect.runPromise(effect)        \u002F\u002F Returns Promise\u003CA>\nEffect.runPromiseExit(effect)    \u002F\u002F Returns Promise\u003CExit\u003CA, E>>\n\n\u002F\u002F Production (with runtime)\nconst runtime = ManagedRuntime.make(AppLayer)\nawait runtime.runPromise(effect)\nawait runtime.dispose()          \u002F\u002F Cleanup\n```\n\n### Resource Management\n\n```typescript\nEffect.acquireUseRelease(acquire, use, release)\nEffect.scoped(effect)\nEffect.addFinalizer(cleanup)\n```\n\n### Duration\n\nEffect accepts human-readable duration strings anywhere a `DurationInput` is expected:\n\n```typescript\nDuration.toMillis(\"5 minutes\")    \u002F\u002F 300000\nDuration.toMillis(\"100 millis\")   \u002F\u002F 100\n\u002F\u002F Units: nanos, micros, millis, seconds, minutes, hours, days, weeks\n```\n\n### Scheduling\n\n```typescript\nEffect.retry(effect, Schedule.exponential(\"100 millis\"))\nEffect.repeat(effect, Schedule.fixed(\"1 second\"))\nSchedule.compose(s1, s2)\n```\n\n### Concurrency\n\n```typescript\nEffect.fork(effect)              \u002F\u002F Run in background fiber\nFiber.join(fiber)                \u002F\u002F Wait for result\nFiber.interrupt(fiber)           \u002F\u002F Cancel fiber\nEffect.race(e1, e2)              \u002F\u002F First to complete wins\nEffect.all([...], { concurrency: 5 })  \u002F\u002F Bounded parallel\n```\n\n### Configuration\n\n```typescript\nconst port = Config.integer(\"PORT\")\nconst host = Config.withDefault(Config.string(\"HOST\"), \"localhost\")\nconst secret = Config.redacted(\"API_KEY\")   \u002F\u002F Masked in logs\nconst db = Config.nested(\"DATABASE\")(Config.all({ host: Config.string(\"HOST\"), port: Config.integer(\"PORT\") }))\n```\n\n### State Management\n\n```typescript\nRef.make(initial)                \u002F\u002F Mutable reference (atomic)\nRef.get(ref) \u002F Ref.set(ref, v)\nQueue.bounded\u003CT>(n)              \u002F\u002F Producer\u002Fconsumer\nDeferred.make\u003CE, A>()            \u002F\u002F One-shot signal\nEffect.makeSemaphore(n)          \u002F\u002F Concurrency limiter\n```\n\n### Array Operations\n\n```typescript\nimport { Array as Arr, Order } from \"effect\"\n\nArr.sort([3, 1, 2], Order.number)                    \u002F\u002F [1, 2, 3]\nArr.sortWith(users, (u) => u.age, Order.number)       \u002F\u002F Sort by field\nArr.sortBy(users, Order.mapInput(Order.number, (u: User) => u.age))  \u002F\u002F Multi-criteria\n```\n\n### Deprecations\n\n- `BigDecimal.fromNumber` → use `BigDecimal.unsafeFromNumber` (3.11.0+)\n- `Schema.annotations()` now removes previously set identifier annotations (3.17.10)\n\n## Conduit Migration Conventions\n\nConduit is mid-migration to Effect. Read `docs\u002Fplans\u002F2026-04-23-effect-ts-migration-plan.md` for the full roadmap.\n\n### Migration Layers (in order)\n\n1. **Schema + Errors** — branded types, error hierarchy, RelayMessage union\n2. **Resources** — SQLite lifecycle, connection pool\n3. **Concurrency** — AbortSignal → Effect.interrupt, fiber supervision\n4. **Dependency Injection** — ServiceRegistry → Layers\n5. **Handlers** — request handlers as Effects\n6. **Server** — HTTP\u002FWS server as Effect program\n7. **Frontend** — Svelte stores bridging to Effect runtime\n\n### Key Mappings\n\n| Current Pattern | Effect Replacement |\n|---|---|\n| `AbortSignal` \u002F `AbortController` | `Fiber.interrupt` \u002F `Effect.scoped` |\n| `try-catch` + `async\u002Fawait` | `Effect.gen` + typed errors |\n| `RelayError` class hierarchy | `Schema.TaggedError` union |\n| `ServiceRegistry` + constructor injection | `Context.Tag` \u002F `Effect.Service` + Layers |\n| `Promise.all()` \u002F `Promise.allSettled()` | `Effect.all()` with concurrency options |\n| `TrackedService` lifecycle | `Layer.scoped` with `acquireRelease` |\n| pino structured logging | `Effect.log` + custom logger layer |\n\n### Testing\n\nConduit uses Vitest with multiple config variants. When testing Effect code:\n\n- Default unit tests: `pnpm test:unit`\n- Run specific: `pnpm vitest run \u003Cpath>`\n- Use `@effect\u002Fvitest` for `it.effect`, `it.scoped`, `it.live`\n- TestClock is active in `it.effect` — advance with `TestClock.adjust()`\n- See `.\u002Freferences\u002Ftesting.md` for comprehensive patterns\n\n### Verification Path\n\n```bash\npnpm check          # tsgo type checking\npnpm lint           # biome\npnpm test:unit      # unit tests\n```\n\n## Reference Files\n\nRead these when working on specific topics:\n\n- **`.\u002Freferences\u002Fcritical-rules.md`** — Forbidden patterns and mandatory conventions\n- **`.\u002Freferences\u002Ferror-handling.md`** — Typed errors, defects, recovery, retry, timeout\n- **`.\u002Freferences\u002Fschema.md`** — Validation, encoding\u002Fdecoding, branded types, class schemas\n- **`.\u002Freferences\u002Flayers.md`** — Dependency injection, service composition, Layer construction\n- **`.\u002Freferences\u002Fconcurrency.md`** — Fibers, synchronization primitives, interruption\n- **`.\u002Freferences\u002Fstreams.md`** — Stream creation, transformation, consumption, backpressure\n- **`.\u002Freferences\u002Ftesting.md`** — TestClock, test layers, mocking, `@effect\u002Fvitest` patterns\n- **`.\u002Freferences\u002Fanti-patterns.md`** — Common mistakes and how to fix them\n- **`.\u002Freferences\u002Foption-null.md`** — Option vs null boundary patterns\n- **`.\u002Freferences\u002Fconfig.md`** — Configuration management, env vars, secrets\n- **`.\u002Freferences\u002Fsvelte-effect.md`** — Svelte 5 + Effect integration patterns\n- **`.\u002Freferences\u002Fconduit-migration.md`** — Conduit-specific migration patterns and mappings\n","# Effect-TS Expert\n\nExpert guidance for functional programming with the Effect library — typed errors, dependency injection, composability,\nconcurrency, and testing patterns. Tailored for the conduit codebase (Svelte 5 + Node.js daemon, mid-migration to Effect).\n\n## Prerequisites Check\n\nBefore starting any Effect-related work, verify the Effect-TS source code exists at `~\u002Fsrc\u002Fpersonal\u002F.effect`.\n\n**If missing, stop immediately and inform the user.** Clone it before proceeding:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002FEffect-TS\u002Feffect.git ~\u002Fsrc\u002Fpersonal\u002F.effect\n```\n\n## Research Strategy\n\nEffect-TS has many ways to accomplish the same task. Proactively research best practices using the Agent tool to spawn\nresearch agents when working with Effect patterns, especially for moderate to high complexity tasks.\n\n### Research Sources (Priority Order)\n\n1. **Codebase Patterns First** — Examine similar patterns in the current project before implementing. If Effect patterns\n   exist in the codebase, follow them for consistency. If no patterns exist, skip this step.\n\n2. **Effect Source Code** — For complex type errors, unclear behavior, or implementation details, examine the Effect\n   source at `~\u002Fsrc\u002Fpersonal\u002F.effect\u002Fpackages\u002Feffect\u002Fsrc\u002F`. This contains the core Effect logic and modules.\n\n### When to Research\n\n**HIGH Priority (Always Research):**\n\n- Implementing Services, Layers, or complex dependency injection\n- Error handling with multiple error types or complex error hierarchies\n- Stream-based operations and reactive patterns\n- Resource management with scoped effects and cleanup\n- Concurrent\u002Fparallel operations and performance-critical code\n- Testing patterns, especially unfamiliar test scenarios\n\n**MEDIUM Priority (Research if Complex):**\n\n- Refactoring imperative code (try-catch, promises) to Effect patterns\n- Adding new service dependencies or restructuring service layers\n- Custom error types or extending existing error hierarchies\n- Integrations with external systems (databases, APIs, third-party services)\n\n### Research Approach\n\n- Spawn multiple concurrent agents when investigating multiple related patterns\n- Focus on canonical, readable, and maintainable solutions over clever optimizations\n- Verify against existing codebase patterns for consistency (if patterns exist)\n- When multiple approaches are possible, research to find the most idiomatic Effect-TS solution\n\n## Core Principles\n\n### Error Handling\n\n- Use Effect's typed error system instead of throwing exceptions\n- Define descriptive error types with `Data.TaggedError` or `Schema.TaggedError` (serializable)\n- Use `Effect.fail`, `Effect.catchTag`, `Effect.catchAll` for error control flow\n- Categorize: expected rejections, domain errors, defects, interruptions, unknown\u002Fforeign\n- See `.\u002Freferences\u002Fcritical-rules.md` for forbidden patterns\n- See `.\u002Freferences\u002Ferror-handling.md` for comprehensive patterns\n\n### Dependency Injection\n\n- Implement DI using Services and Layers\n- Define services with `Context.Tag` or `Effect.Service` (simplified)\n- Compose layers with `Layer.merge`, `Layer.provide`, `Layer.provideMerge`\n- Provide layers at the composition root, not scattered through business logic\n- See `.\u002Freferences\u002Flayers.md` for full patterns\n\n### Composability\n\n- Leverage Effect's composability for complex operations\n- Use appropriate constructors: `Effect.succeed`, `Effect.fail`, `Effect.tryPromise`, `Effect.try`\n- Apply proper resource management with scoped effects\n- Chain with `Effect.flatMap`, `Effect.map`, `Effect.tap`\n\n### Code Quality\n\n- Write type-safe code that leverages Effect's type system\n- Use `Effect.gen` for readable sequential code (preferred)\n- Use `pipe` for simple one-liner transformations\n- Prefer `Effect.fn()` for named functions — automatic telemetry and better stack traces\n- Implement proper testing patterns using `@effect\u002Fvitest`\n\n## Critical Rules\n\n**Read `.\u002Freferences\u002Fcritical-rules.md` before writing any Effect code.** Key rules:\n\n### INEFFECTIVE: try-catch in Effect.gen\n\nEffect failures are returned as exits, not thrown. `try-catch` inside `Effect.gen` will NOT catch Effect failures.\n\n```typescript\n\u002F\u002F WRONG — catches nothing\nEffect.gen(function* () {\n  try { const r = yield* someEffect } catch (e) { \u002F* never runs *\u002F }\n})\n\n\u002F\u002F RIGHT\nEffect.gen(function* () {\n  const result = yield* Effect.catchTag(someEffect, \"MyError\", (e) => Effect.succeed(fallback))\n})\n```\n\n### AVOID: Type assertions (`as never`, `as any`, `as unknown`)\n\nFix underlying type issues instead. Occasional assertions for poorly-typed external libraries are acceptable if documented.\n\n### RECOMMENDED: `return yield*` for errors\n\nMakes termination explicit and prevents unreachable-code warnings:\n\n```typescript\nEffect.gen(function* () {\n  if (bad) {\n    return yield* Effect.fail(new MyError({ reason: \"bad\" }))\n  }\n  return yield* doWork()\n})\n```\n\n## Quick Reference\n\n### The Effect Type\n\n```typescript\nEffect\u003CSuccess, Error, Requirements>\n\u002F\u002F     ^        ^       ^\n\u002F\u002F     |        |       └── Services\u002Fdependencies needed (Context)\n\u002F\u002F     |        └────────── Typed error channel\n\u002F\u002F     └─────────────────── Success value type\n```\n\n### Creating Effects\n\n```typescript\nEffect.succeed(value)           \u002F\u002F Wrap success value\nEffect.fail(error)              \u002F\u002F Create failed effect\nEffect.tryPromise(fn)           \u002F\u002F Wrap promise-returning function (rejects → typed error)\nEffect.try(fn)                  \u002F\u002F Wrap synchronous throwing function\nEffect.sync(fn)                 \u002F\u002F Wrap synchronous non-throwing function\nEffect.promise(fn)              \u002F\u002F Wrap promise (rejects → defect — prefer tryPromise)\n```\n\n### Composing Effects\n\n```typescript\nEffect.flatMap(effect, fn)      \u002F\u002F Chain effects\nEffect.map(effect, fn)          \u002F\u002F Transform success value\nEffect.tap(effect, fn)          \u002F\u002F Side effect without changing value\nEffect.all([...effects])        \u002F\u002F Run effects (concurrency configurable)\nEffect.forEach(items, fn)       \u002F\u002F Map over items with effects\n\n\u002F\u002F Collect ALL errors (not just first)\nEffect.all([e1, e2, e3], { mode: \"validate\" })\n\n\u002F\u002F Partial success handling\nEffect.partition([e1, e2, e3])  \u002F\u002F Returns [failures, successes]\n```\n\n### Error Handling\n\n```typescript\n\u002F\u002F Define typed errors with Data.TaggedError (preferred)\nclass UserNotFoundError extends Data.TaggedError(\"UserNotFoundError\")\u003C{\n  userId: string\n}> {}\n\n\u002F\u002F Direct yield of errors in gen (no Effect.fail wrapper needed)\nEffect.gen(function* () {\n  if (!user) return yield* new UserNotFoundError({ userId })\n})\n\nEffect.catchTag(effect, tag, fn) \u002F\u002F Handle specific error tag\nEffect.catchTags(effect, { ... }) \u002F\u002F Handle multiple tags\nEffect.catchAll(effect, fn)      \u002F\u002F Handle all errors\nEffect.result(effect)            \u002F\u002F Convert to Exit value\nEffect.either(effect)            \u002F\u002F Convert to Either\u003CE, A>\nEffect.orElse(effect, alt)       \u002F\u002F Fallback effect\n```\n\n### Error Taxonomy\n\n| Category                | Examples                   | Handling                  |\n| ----------------------- | -------------------------- | ------------------------- |\n| **Expected Rejections** | User cancel, deny          | Graceful exit, no retry   |\n| **Domain Errors**       | Validation, business rules | Show to user, don't retry |\n| **Defects**             | Bugs, assertions           | Log + alert, investigate  |\n| **Interruptions**       | Fiber cancel, timeout      | Cleanup, may retry        |\n| **Unknown\u002FForeign**     | Thrown exceptions          | Normalize at boundary     |\n\n### Pattern Matching (Match Module)\n\n```typescript\nimport { Match } from \"effect\"\n\n\u002F\u002F Type-safe exhaustive matching on tagged errors\nconst handleError = Match.type\u003CAppError>().pipe(\n  Match.tag(\"UserCancelledError\", () => null),\n  Match.tag(\"ValidationError\", (e) => e.message),\n  Match.tag(\"NetworkError\", () => \"Connection failed\"),\n  Match.exhaustive  \u002F\u002F Compile error if case missing\n)\n\n\u002F\u002F Cleaner than chained catchTag\nEffect.catchAll(effect, (error) =>\n  Match.value(error).pipe(\n    Match.tag(\"A\", handleA),\n    Match.tag(\"B\", handleB),\n    Match.exhaustive\n  )\n)\n```\n\n### Services and Layers\n\n```typescript\n\u002F\u002F Pattern 1: Context.Tag (implementation provided separately via Layer)\nclass MyService extends Context.Tag(\"MyService\")\u003CMyService, { ... }>() {}\nconst MyServiceLive = Layer.succeed(MyService, { ... })\n\n\u002F\u002F Pattern 2: Effect.Service (default implementation bundled)\nclass UserRepo extends Effect.Service\u003CUserRepo>()(\"UserRepo\", {\n  effect: Effect.gen(function* () {\n    const db = yield* Database\n    return { findAll: db.query(\"SELECT * FROM users\") }\n  }),\n  dependencies: [Database.Default],\n  accessors: true  \u002F\u002F Auto-generate method accessors\n}) {}\n\n\u002F\u002F Pattern 3: Context.Reference (defaultable tags — 3.11.0+)\nclass SpecialNumber extends Context.Reference\u003CSpecialNumber>()(\n  \"SpecialNumber\",\n  { defaultValue: () => 2048 }\n) {}\n```\n\n### Generator Pattern\n\n```typescript\n\u002F\u002F Effect.gen — recommended for sequential code\nEffect.gen(function* () {\n  const a = yield* effectA\n  const b = yield* effectB\n  return result\n})\n\n\u002F\u002F Effect.fn — automatic tracing\u002Ftelemetry (preferred for named functions)\nconst fetchUser = Effect.fn(\"fetchUser\")(function* (id: string) {\n  const db = yield* Database\n  return yield* db.query(id)\n})\n```\n\n### Running Effects\n\n```typescript\nEffect.runSync(effect)           \u002F\u002F Sync, throws on async\u002Ferror\nEffect.runPromise(effect)        \u002F\u002F Returns Promise\u003CA>\nEffect.runPromiseExit(effect)    \u002F\u002F Returns Promise\u003CExit\u003CA, E>>\n\n\u002F\u002F Production (with runtime)\nconst runtime = ManagedRuntime.make(AppLayer)\nawait runtime.runPromise(effect)\nawait runtime.dispose()          \u002F\u002F Cleanup\n```\n\n### Resource Management\n\n```typescript\nEffect.acquireUseRelease(acquire, use, release)\nEffect.scoped(effect)\nEffect.addFinalizer(cleanup)\n```\n\n### Duration\n\nEffect accepts human-readable duration strings anywhere a `DurationInput` is expected:\n\n```typescript\nDuration.toMillis(\"5 minutes\")    \u002F\u002F 300000\nDuration.toMillis(\"100 millis\")   \u002F\u002F 100\n\u002F\u002F Units: nanos, micros, millis, seconds, minutes, hours, days, weeks\n```\n\n### Scheduling\n\n```typescript\nEffect.retry(effect, Schedule.exponential(\"100 millis\"))\nEffect.repeat(effect, Schedule.fixed(\"1 second\"))\nSchedule.compose(s1, s2)\n```\n\n### Concurrency\n\n```typescript\nEffect.fork(effect)              \u002F\u002F Run in background fiber\nFiber.join(fiber)                \u002F\u002F Wait for result\nFiber.interrupt(fiber)           \u002F\u002F Cancel fiber\nEffect.race(e1, e2)              \u002F\u002F First to complete wins\nEffect.all([...], { concurrency: 5 })  \u002F\u002F Bounded parallel\n```\n\n### Configuration\n\n```typescript\nconst port = Config.integer(\"PORT\")\nconst host = Config.withDefault(Config.string(\"HOST\"), \"localhost\")\nconst secret = Config.redacted(\"API_KEY\")   \u002F\u002F Masked in logs\nconst db = Config.nested(\"DATABASE\")(Config.all({ host: Config.string(\"HOST\"), port: Config.integer(\"PORT\") }))\n```\n\n### State Management\n\n```typescript\nRef.make(initial)                \u002F\u002F Mutable reference (atomic)\nRef.get(ref) \u002F Ref.set(ref, v)\nQueue.bounded\u003CT>(n)              \u002F\u002F Producer\u002Fconsumer\nDeferred.make\u003CE, A>()            \u002F\u002F One-shot signal\nEffect.makeSemaphore(n)          \u002F\u002F Concurrency limiter\n```\n\n### Array Operations\n\n```typescript\nimport { Array as Arr, Order } from \"effect\"\n\nArr.sort([3, 1, 2], Order.number)                    \u002F\u002F [1, 2, 3]\nArr.sortWith(users, (u) => u.age, Order.number)       \u002F\u002F Sort by field\nArr.sortBy(users, Order.mapInput(Order.number, (u: User) => u.age))  \u002F\u002F Multi-criteria\n```\n\n### Deprecations\n\n- `BigDecimal.fromNumber` → use `BigDecimal.unsafeFromNumber` (3.11.0+)\n- `Schema.annotations()` now removes previously set identifier annotations (3.17.10)\n\n## Conduit Migration Conventions\n\nConduit is mid-migration to Effect. Read `docs\u002Fplans\u002F2026-04-23-effect-ts-migration-plan.md` for the full roadmap.\n\n### Migration Layers (in order)\n\n1. **Schema + Errors** — branded types, error hierarchy, RelayMessage union\n2. **Resources** — SQLite lifecycle, connection pool\n3. **Concurrency** — AbortSignal → Effect.interrupt, fiber supervision\n4. **Dependency Injection** — ServiceRegistry → Layers\n5. **Handlers** — request handlers as Effects\n6. **Server** — HTTP\u002FWS server as Effect program\n7. **Frontend** — Svelte stores bridging to Effect runtime\n\n### Key Mappings\n\n| Current Pattern | Effect Replacement |\n|---|---|\n| `AbortSignal` \u002F `AbortController` | `Fiber.interrupt` \u002F `Effect.scoped` |\n| `try-catch` + `async\u002Fawait` | `Effect.gen` + typed errors |\n| `RelayError` class hierarchy | `Schema.TaggedError` union |\n| `ServiceRegistry` + constructor injection | `Context.Tag` \u002F `Effect.Service` + Layers |\n| `Promise.all()` \u002F `Promise.allSettled()` | `Effect.all()` with concurrency options |\n| `TrackedService` lifecycle | `Layer.scoped` with `acquireRelease` |\n| pino structured logging | `Effect.log` + custom logger layer |\n\n### Testing\n\nConduit uses Vitest with multiple config variants. When testing Effect code:\n\n- Default unit tests: `pnpm test:unit`\n- Run specific: `pnpm vitest run \u003Cpath>`\n- Use `@effect\u002Fvitest` for `it.effect`, `it.scoped`, `it.live`\n- TestClock is active in `it.effect` — advance with `TestClock.adjust()`\n- See `.\u002Freferences\u002Ftesting.md` for comprehensive patterns\n\n### Verification Path\n\n```bash\npnpm check          # tsgo type checking\npnpm lint           # biome\npnpm test:unit      # unit tests\n```\n\n## Reference Files\n\nRead these when working on specific topics:\n\n- **`.\u002Freferences\u002Fcritical-rules.md`** — Forbidden patterns and mandatory conventions\n- **`.\u002Freferences\u002Ferror-handling.md`** — Typed errors, defects, recovery, retry, timeout\n- **`.\u002Freferences\u002Fschema.md`** — Validation, encoding\u002Fdecoding, branded types, class schemas\n- **`.\u002Freferences\u002Flayers.md`** — Dependency injection, service composition, Layer construction\n- **`.\u002Freferences\u002Fconcurrency.md`** — Fibers, synchronization primitives, interruption\n- **`.\u002Freferences\u002Fstreams.md`** — Stream creation, transformation, consumption, backpressure\n- **`.\u002Freferences\u002Ftesting.md`** — TestClock, test layers, mocking, `@effect\u002Fvitest` patterns\n- **`.\u002Freferences\u002Fanti-patterns.md`** — Common mistakes and how to fix them\n- **`.\u002Freferences\u002Foption-null.md`** — Option vs null boundary patterns\n- **`.\u002Freferences\u002Fconfig.md`** — Configuration management, env vars, secrets\n- **`.\u002Freferences\u002Fsvelte-effect.md`** — Svelte 5 + Effect integration patterns\n- **`.\u002Freferences\u002Fconduit-migration.md`** — Conduit-specific migration patterns and mappings\n",{"name":5,"description":7},"main","2390b741d6daa7385cfb01fe351f64305cda49d5",".agents\u002Fskills\u002Feffect-ts",2,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit","https:\u002F\u002Fgithub.com\u002Fdibstern","Software Engineer at Renowned, ex-Rome2Rio","2026-10-29 15:51:30",{"source":8,"skillName":5,"commands":49,"prompt":59,"zipAvailable":60},[50,53,56],{"tool":51,"command":52},"npx","npx skills add dibstern\u002Fconduit --skill effect-ts",{"tool":54,"command":55},"bunx","bunx skills add dibstern\u002Fconduit --skill effect-ts",{"tool":57,"command":58},"pnpm","pnpm dlx skills add dibstern\u002Fconduit --skill effect-ts","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002FSKILL.md",true,[62,68,72,76,80,84,88,92,96,100,104,108],{"path":63,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":66,"sourceHtmlUrl":67},"references\u002Fanti-patterns.md","REFERENCE","参考文档",4678,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Fanti-patterns.md",{"path":69,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":70,"sourceHtmlUrl":71},"references\u002Fconcurrency.md",5253,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Fconcurrency.md",{"path":73,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":74,"sourceHtmlUrl":75},"references\u002Fconduit-migration.md",7785,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Fconduit-migration.md",{"path":77,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":78,"sourceHtmlUrl":79},"references\u002Fconfig.md",3969,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Fconfig.md",{"path":81,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":82,"sourceHtmlUrl":83},"references\u002Fcritical-rules.md",3881,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Fcritical-rules.md",{"path":85,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":86,"sourceHtmlUrl":87},"references\u002Ferror-handling.md",6904,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Ferror-handling.md",{"path":89,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":90,"sourceHtmlUrl":91},"references\u002Flayers.md",5515,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Flayers.md",{"path":93,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":94,"sourceHtmlUrl":95},"references\u002Foption-null.md",2435,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Foption-null.md",{"path":97,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":98,"sourceHtmlUrl":99},"references\u002Fschema.md",5796,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Fschema.md",{"path":101,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":102,"sourceHtmlUrl":103},"references\u002Fstreams.md",5391,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Fstreams.md",{"path":105,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":106,"sourceHtmlUrl":107},"references\u002Fsvelte-effect.md",7964,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Fsvelte-effect.md",{"path":109,"resourceType":64,"resourceTypeDesc":65,"sizeBytes":110,"sourceHtmlUrl":111},"references\u002Ftesting.md",7167,"https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Feffect-ts\u002Freferences\u002Ftesting.md",[113,127,138,164,183,190],{"skillNo":114,"name":115,"nameZh":6,"description":116,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":35},"01M6ENE9PDF6ZTQ0HN0M2NY8YN","release-notes","Drafts release notes. Fixture skill for conduit's recorded skill-loads-turn trace.","https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002Ftest\u002Ffixtures\u002Fclaude-sdk-traces\u002Fskill-loads-turn-skills\u002Frelease-notes\u002FSKILL.md",[],[120,121,122,27,123,124,125,126],"notes","release notes","release","trace","fixture skill","fixture","loads",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":133,"publishedAt":35},"01M6ENE72EV36TVDA9A00WHZWP","changelog-style","House style for changelog entries. Fixture skill for conduit's recorded skill-loads-turn trace.","https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002Ftest\u002Ffixtures\u002Fclaude-sdk-traces\u002Fskill-loads-turn-skills\u002Fchangelog-style\u002FSKILL.md",[],[134,135,136,27,123,124,137,125,126],"changelog","style","changelog style","entries",{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":144,"publishedAt":35},"01M6ENE3R4WX66WR1SNJ98F89W","typescript-advanced-types","Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.","https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Ftypescript-advanced-types\u002FSKILL.md",[],[145,146,147,148,149,150,151,152,153,154,29,155,156,157,158,159,160,161,162,163],"typescript","types","typescript advanced","typescript advanced types","type system","reusable","time","logic","type","master","template","utility","Type Safety","system","safe","compile","Safety","applications","projects",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":168,"categories":169,"keywords":175,"publishedAt":35},"01M6ENDWT23VWB5YJBXZFBRYRZ","sveltekit-svelte5-tailwind-skill","Comprehensive integration skill for building sites with SvelteKit 2, Svelte 5, and Tailwind CSS v4","https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fsveltekit-svelte5-tailwind-skill\u002FSKILL.md",[170],{"categoryNo":171,"categoryName":172,"taxonomyType":173,"taxonomyTypeDesc":174},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[176,177,178,179,24,180,31,181,33,182],"sveltekit","Tailwind","sveltekit svelte5 tailwind skill","css","only","Tailwind CSS","sites",{"skillNo":184,"name":185,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":186,"categories":187,"keywords":188,"publishedAt":35},"01M6ENDSRWQ1XYJECFESE5R7EH","svelte5-inspect","https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fsvelte5-inspect\u002FSKILL.md",[],[189],"svelte5 inspect",{"skillNo":191,"name":192,"nameZh":6,"description":193,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":194,"categories":195,"keywords":200,"publishedAt":35},"01M6ENDNVCSJ87AD76V5QTKG49","playwright-cli","Automates browser interactions for web testing, form filling, screenshots, and data extraction. Use when the user needs to navigate websites, interact with web pages, fill forms, take screenshots, test web applications, or extract information from web pages.","https:\u002F\u002Fgithub.com\u002Fdibstern\u002Fconduit\u002Fblob\u002Fmain\u002F.opencode\u002Fskills\u002Fplaywright-cli\u002FSKILL.md",[196,199],{"categoryNo":197,"categoryName":198,"taxonomyType":173,"taxonomyTypeDesc":174},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":171,"categoryName":172,"taxonomyType":173,"taxonomyTypeDesc":174},[201,202,203,204,205,206,207,208,209,162,210,211,29,212,213,214,215,216,217,218],"playwright cli","playwright","cli","form","screenshots","test","web","browser","data","Bash","extract","take","test web","web testing","forms","pages","Data Extraction","testing"]