@danieljvdm/dev-kit 0.11.3 → 0.13.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 (79) hide show
  1. package/README.md +111 -78
  2. package/dev-kit.example.jsonc +0 -4
  3. package/package.json +10 -6
  4. package/schema/dev-kit.schema.json +1 -46
  5. package/skills/build-effect-apis/SKILL.md +77 -0
  6. package/skills/build-effect-apis/agents/openai.yaml +4 -0
  7. package/skills/build-effect-apis/references/cloudflare-workers.md +71 -0
  8. package/skills/build-effect-apis/references/effect-atom-client.md +161 -0
  9. package/skills/build-effect-apis/references/effect-atom-lifecycle.md +78 -0
  10. package/skills/build-effect-apis/references/effect-atom-testing.md +74 -0
  11. package/skills/build-effect-apis/references/runtime-assembly.md +56 -0
  12. package/skills/build-effect-apis/references/server-and-middleware.md +174 -0
  13. package/skills/build-effect-apis/references/shared-contracts.md +108 -0
  14. package/skills/build-effect-apis/references/tanstack-start.md +86 -0
  15. package/skills/build-effect-apis/references/verification.md +50 -0
  16. package/skills/build-effect-clis/SKILL.md +61 -0
  17. package/skills/build-effect-clis/agents/openai.yaml +4 -0
  18. package/skills/build-effect-clis/references/command-design.md +93 -0
  19. package/skills/build-effect-clis/references/entrypoints-and-testing.md +59 -0
  20. package/skills/build-effect-clis/references/processes-and-platform.md +73 -0
  21. package/skills/dev-kit/SKILL.md +77 -48
  22. package/skills/effect-architecture-audit/SKILL.md +26 -0
  23. package/skills/effect-architecture-audit/agents/openai.yaml +4 -0
  24. package/skills/effect-architecture-audit/references/service-and-boundary-audit.md +150 -0
  25. package/skills/effect-ts/SKILL.md +21 -256
  26. package/skills/effect-ts/agents/openai.yaml +3 -3
  27. package/skills/testing/SKILL.md +5 -0
  28. package/src/catalog-manager.ts +16 -17
  29. package/src/catalog.ts +71 -16
  30. package/src/effect-source.ts +46 -24
  31. package/src/effect-tsgo.ts +86 -24
  32. package/src/gitignore.ts +5 -5
  33. package/src/index.ts +3 -6
  34. package/src/manifest.ts +0 -34
  35. package/src/node-symbolic-link.ts +2 -2
  36. package/src/oxfmt.js +5 -0
  37. package/src/oxfmt.ts +5 -0
  38. package/src/oxlint.js +5 -0
  39. package/src/oxlint.ts +5 -0
  40. package/src/package-skill-source.ts +51 -59
  41. package/src/path-digest.ts +7 -7
  42. package/src/project-package.ts +8 -7
  43. package/src/project-process-lock.ts +17 -12
  44. package/src/project-state.ts +1 -1
  45. package/src/skill-manager.ts +18 -16
  46. package/src/skill-selector.ts +12 -0
  47. package/src/sync.ts +181 -131
  48. package/src/tool-ignore-patterns.js +9 -0
  49. package/src/tool-ignore-patterns.ts +15 -0
  50. package/src/vendor.ts +67 -61
  51. package/src/vite-plus-dependency.ts +10 -11
  52. package/src/vite-plus-hooks.ts +24 -14
  53. package/src/vite-plus-quality.ts +21 -172
  54. package/src/vite-plus.js +81 -0
  55. package/src/vite-plus.ts +102 -0
  56. package/templates/AGENTS.md +1 -1
  57. package/skills/effect-ts/UPSTREAM.md +0 -28
  58. package/skills/effect-ts/references/atom-cache-lifecycle.md +0 -78
  59. package/skills/effect-ts/references/atom-http-and-invalidation.md +0 -97
  60. package/skills/effect-ts/references/atom-tanstack-start.md +0 -69
  61. package/skills/effect-ts/references/atom-testing.md +0 -67
  62. package/skills/effect-ts/references/audit-services.md +0 -144
  63. package/skills/effect-ts/references/features.md +0 -525
  64. package/skills/effect-ts/references/guide-atom-data-fetching.md +0 -44
  65. package/skills/effect-ts/references/guide-cli.md +0 -107
  66. package/skills/effect-ts/references/guide-datetime.md +0 -72
  67. package/skills/effect-ts/references/guide-effect.md +0 -440
  68. package/skills/effect-ts/references/guide-error-handling.md +0 -565
  69. package/skills/effect-ts/references/guide-http-boundaries.md +0 -55
  70. package/skills/effect-ts/references/guide-layers.md +0 -989
  71. package/skills/effect-ts/references/guide-observability.md +0 -746
  72. package/skills/effect-ts/references/guide-retries.md +0 -434
  73. package/skills/effect-ts/references/guide-schedule.md +0 -343
  74. package/skills/effect-ts/references/guide-schema.md +0 -664
  75. package/skills/effect-ts/references/guide-sql.md +0 -536
  76. package/skills/effect-ts/references/guide-testing.md +0 -532
  77. package/skills/effect-ts/references/guide-type-safety-and-boundaries.md +0 -131
  78. package/skills/effect-ts/references/version-and-source.md +0 -86
  79. package/templates/vite-plus/vite.config.ts +0 -22
@@ -0,0 +1,150 @@
1
+ # Service And Boundary Audit
2
+
3
+ ## Contents
4
+
5
+ - [Establish authority](#establish-authority)
6
+ - [Build the inventory](#build-the-inventory)
7
+ - [Trace requirements](#trace-requirements)
8
+ - [Classify candidates](#classify-candidates)
9
+ - [Audit type boundaries](#audit-type-boundaries)
10
+ - [Audit test substitutes](#audit-test-substitutes)
11
+ - [Report findings](#report-findings)
12
+
13
+ ## Establish authority
14
+
15
+ Read the repository's architecture guidance and version-matched Effect package
16
+ instructions. Treat installed declarations and source as the authority for API
17
+ signatures. Record local conventions that affect service ownership, adapter
18
+ placement, error translation, and testing.
19
+
20
+ ## Build the inventory
21
+
22
+ Find every:
23
+
24
+ - Effect service, tag, Layer, constructor, and provisioning call.
25
+ - Service-shaped interface, class, dependency bag, registry, or callback.
26
+ - Direct use of time, randomness, IDs, configuration, credentials, HTTP,
27
+ persistence, filesystems, runtime bindings, or mutable globals.
28
+ - Test Layer, fake, in-memory implementation, and module mock.
29
+ - Public Effect with an `unknown` or overly broad error channel.
30
+ - `any`, assertion, non-null assertion, custom predicate, structural probe,
31
+ unvalidated JSON parse, Promise rejection mapper, and expected throw.
32
+ - Schema or codec that overlaps another representation of the same logical
33
+ model.
34
+
35
+ Record one row per service or candidate:
36
+
37
+ | Field | Question |
38
+ | ------------ | ---------------------------------------------------- |
39
+ | Owner | Which module owns the capability's meaning? |
40
+ | Contract | Where is its public contract defined? |
41
+ | Construction | Are all construction requirements visible? |
42
+ | Production | Who chooses the concrete implementation? |
43
+ | Consumers | Is the capability yielded or drilled as a value? |
44
+ | Boundary | Who owns decoding, narrowing, and error translation? |
45
+ | Tests | Is its substitute strategy intentional and honest? |
46
+ | Verdict | Keep, deepen, relocate, merge, remove, or create? |
47
+
48
+ Complete the inventory when each discovered capability and unsafe boundary
49
+ appears exactly once.
50
+
51
+ ## Trace requirements
52
+
53
+ For each row:
54
+
55
+ 1. Trace one caller-visible operation through every effect it performs.
56
+ 2. Mark where each dependency first appears and whether code yields, passes,
57
+ captures, or concretely provides it.
58
+ 3. Verify that the module selecting a concrete Layer owns that implementation
59
+ choice.
60
+ 4. Follow every Layer requirement to a composition root or an explicit value
61
+ boundary.
62
+ 5. Check version-matched Effect capabilities before recommending an
63
+ application wrapper.
64
+
65
+ Flag hidden requirements created by inner provisioning, dependency bags,
66
+ handler-builder service values, mutable registries, or Layer selection inside
67
+ business operations. Prefer provision at a program or subsystem edge. Avoid
68
+ thin exported helpers that only yield a service and forward one method.
69
+
70
+ ## Classify candidates
71
+
72
+ Assign one evidence-backed classification:
73
+
74
+ - **Built-in Effect capability** — yield the existing capability directly.
75
+ - **Application-owned authority** — define a narrow port beside the operation
76
+ whose policy gives it meaning.
77
+ - **Technology adapter** — implement an application-owned port at the external
78
+ boundary.
79
+ - **Request or domain value** — keep deterministic, per-call data explicit.
80
+ - **Framework boundary** — contain framework-required state or assertions in
81
+ the adapter or composition root.
82
+ - **Pass-through abstraction** — fold it into the actual owner.
83
+
84
+ Apply the deletion test: if removing an abstraction leaves equally clear code
85
+ without spreading authority, resource ownership, or policy, remove it. Prefer
86
+ an existing owner or a merge over a generic registry.
87
+
88
+ ## Audit type boundaries
89
+
90
+ Assign every `unknown` value a boundary owner.
91
+
92
+ - Reserve `unknown` for external input, foreign library output, and opaque
93
+ diagnostic causes.
94
+ - Decode structured external data once, at the earliest boundary that owns its
95
+ meaning.
96
+ - Pass decoded values and concrete error unions through internal services.
97
+ - Keep unavoidable framework assertions at the narrowest adapter and document
98
+ the contract they bridge.
99
+ - Remove runtime narrowing already guaranteed by the inferred type.
100
+ - Preserve irreducible foreign causes as diagnostic fields inside concrete
101
+ domain errors instead of broadening public error channels.
102
+
103
+ Prefer one source Schema per logical model. Use Schema transformations or
104
+ derived variants when a storage or transport representation differs without
105
+ changing the model's meaning. Create a separate Schema only for a real semantic
106
+ difference.
107
+
108
+ Keep a helper only when it owns domain policy, reusable refinement, repeated
109
+ non-trivial mechanics, or a meaningful observability boundary. Inline one-use
110
+ tag comparisons and structural checks that add no meaning.
111
+
112
+ ## Audit test substitutes
113
+
114
+ Record the intended test strategy for every production service.
115
+
116
+ - Make a shared test Layer's name match the behavior it fully provides.
117
+ - Keep partial fixtures local instead of publishing them as general in-memory
118
+ implementations.
119
+ - Use a real local adapter when persistence, transactions, serialization, or
120
+ lifecycle behavior is the subject under test.
121
+ - Keep timing deterministic; never add wall-clock sleeps to stabilize a test.
122
+ - Test protocol round trips when encoding or decoding behavior is a durable,
123
+ regression-prone public seam.
124
+
125
+ An explicit production-only rationale is valid when a substitute would not
126
+ protect durable behavior.
127
+
128
+ ## Report findings
129
+
130
+ Prioritize findings by impact:
131
+
132
+ - **P0** — hidden authority, unsafe runtime access, wrong implementation
133
+ ownership, unchecked external data, or expected failures escaping the typed
134
+ channel.
135
+ - **P1** — dependency drilling, hidden Layer requirements, duplicated
136
+ capabilities, manual shape discovery, unjustified assertions, pass-through
137
+ abstractions, or dishonest test substitutes.
138
+ - **P2** — naming and co-location cleanup that belongs with a nearby change.
139
+
140
+ For each finding, include:
141
+
142
+ 1. File, line, or symbol evidence.
143
+ 2. The hidden requirement or caller burden.
144
+ 3. The smallest target shape and its owner.
145
+ 4. Composition-root and testing impact.
146
+ 5. Behavior and modules that must remain unchanged.
147
+
148
+ End with explicit keep decisions for pure functions, request values, framework
149
+ boundaries, correctly separated ports and adapters, and services whose
150
+ requirements already remain visible.
@@ -1,270 +1,35 @@
1
1
  ---
2
2
  name: effect-ts
3
- description: Use this skill whenever working in a repository that uses Effect, even if the current task is in a new file or the user does not explicitly ask for Effect help. Apply it to Effect patterns, services, layers, schemas, streams, runtimes, typed errors, DateTime, Effect Atom, observability, testing, HTTP, SQL, command-line scripts, project automation, and supporting tooling.
3
+ description: Use this skill when setting up a repository that uses the Effect Typescript library.
4
4
  ---
5
5
 
6
- # Effect Expert
6
+ # Step 1: Install effect
7
7
 
8
- Expert guidance for programming with the Effect library, covering error handling, dependency injection, composability, and testing patterns.
8
+ Use the users preferred package manager:
9
9
 
10
- ## Version Baseline
10
+ ```
11
+ pnpm add effect@beta
12
+ ```
11
13
 
12
- This skill targets Effect v4. The guidance was last reviewed against
13
- `effect@4.0.0-beta.102` and the matching `@effect/*` v4 packages.
14
+ If in a monorepo, install it as a dev dependency at the root, so you can access
15
+ the source code from `node_modules/effect/src`.
14
16
 
15
- Before changing code, determine the version installed by the target repository.
16
- The target repository's manifest and lockfile are authoritative. Do not migrate
17
- or upgrade it merely to match this review baseline.
17
+ ```
18
+ pnpm add -D effect@beta
19
+ ```
18
20
 
19
- Read `./references/version-and-source.md` before installing packages, resolving
20
- version-sensitive APIs, or using upstream source as evidence.
21
+ # Step 2: Update AGENTS.md / CLAUDE.md
21
22
 
22
- ## Research Strategy
23
+ Ensure that the agent instructions contain the following:
23
24
 
24
- Effect has many ways to accomplish the same task. Proactively research best practices when working with Effect patterns, especially for moderate to high complexity tasks.
25
+ ```md
26
+ # Learning more about the Effect
25
27
 
26
- Use the local guides in `./references/` first. They are the preferred source for best practices, conventions, and common implementation patterns.
28
+ This repository uses the Effect Typescript library.
27
29
 
28
- Only go directly to the canonical Effect source when:
30
+ Before writing any Effect code, first read `node_modules/effect/AGENTS.md`
31
+ **completely**, and follow the links in the file when required.
29
32
 
30
- - the guides do not cover the question
31
- - you need exact API details or signatures
32
- - you need deeper implementation details
33
- - you need to verify a behavior against the source
34
-
35
- ### Research Sources
36
-
37
- 1. Local skill guides first. Start with the relevant files in `./references/`
38
- before doing deeper research.
39
- 2. Codebase patterns second. Examine similar patterns in the current project
40
- before implementing. If Effect patterns already exist, follow them for
41
- consistency unless they conflict with an explicit local policy in this
42
- skill.
43
- 3. Installed package source third. Use the target repository's resolved
44
- `effect` and `@effect/*` packages for exact exports, declarations, and API
45
- signatures.
46
- 4. Version-matched upstream source last. For gaps in the guides, complex type
47
- errors, unclear behavior, or implementation details, inspect the canonical
48
- `Effect-TS/effect` source at the tag or commit matching the installed
49
- version. A project-local source checkout is optional, never a prerequisite.
50
-
51
- ### When To Research
52
-
53
- - Always research for services, layers, or complex dependency injection.
54
- - Always research for error handling with multiple error types or complex error hierarchies.
55
- - Always research for stream-based operations and reactive patterns.
56
- - Always research for resource management with scoped effects and cleanup.
57
- - Always research for concurrent or performance-critical code.
58
- - Always research for unfamiliar testing patterns.
59
- - Research when needed for complex refactors from promises or try/catch into Effect.
60
- - Research when needed for new service dependencies or layer restructuring.
61
- - Research when needed for custom error types or extensions of existing error hierarchies.
62
- - Research when needed for integrations with external systems such as databases, APIs, or third-party services.
63
-
64
- ### Research Approach
65
-
66
- - Focus on canonical, readable, and maintainable solutions rather than clever optimizations.
67
- - Verify suggested approaches against existing codebase patterns when those
68
- patterns exist.
69
- - When multiple approaches are possible, prefer the most idiomatic Effect
70
- solution supported by the codebase, these local policies, and version-matched
71
- Effect source.
72
-
73
- ### Codebase Pattern Discovery
74
-
75
- When working in a project that uses Effect, check for existing patterns before implementing new code:
76
-
77
- 1. Search for Effect imports and existing module usage to understand current conventions.
78
- 2. Identify how services and layers are structured in the project.
79
- 3. Note how errors are defined and propagated.
80
- 4. Examine how Effect code is tested in the project.
81
-
82
- If no Effect patterns exist in the codebase, proceed using these guides and
83
- canonical patterns from version-matched Effect source and examples. Do not
84
- block on missing codebase patterns or a missing source checkout.
85
-
86
- ### Feature Discovery
87
-
88
- When you need to discover available Effect modules, packages, or capabilities, search `./references/features.md` first.
89
-
90
- - Use it to identify the right package or module for a task.
91
- - Treat listed repo paths as discovery hints. Confirm them against the target
92
- repository's installed version before relying on exact names or signatures.
93
- - Use it before inventing custom abstractions when Effect may already provide the functionality.
94
-
95
- ### Guide Discovery
96
-
97
- When the task touches one of these areas, consult the matching guide before implementing:
98
-
99
- - `./references/guide-effect.md` for core `Effect` usage patterns, common constructors, composition, provisioning, and runtime boundaries
100
- - `./references/guide-error-handling.md` for defining errors, schema-based errors, failure handling, defects, and interrupts
101
- - `./references/guide-layers.md` for service ownership, service design, layer
102
- construction, dependency visibility, composition, and provisioning
103
- - `./references/guide-observability.md` for `Effect.fn`, spans, structured
104
- logging, metrics, annotations, and telemetry wiring
105
- - `./references/guide-retries.md` for retry policies, retry conditions, fallback strategies, and `ExecutionPlan`
106
- - `./references/guide-schedule.md` for retries, repeats, backoff, polling, cron, and schedule composition
107
- - `./references/guide-schema.md` for schema-first application modeling,
108
- service contracts, transformations, unions, recursion, and branded types
109
- - `./references/guide-datetime.md` for current time, parsing, UTC and zoned
110
- values, time zones, DST-safe arithmetic, formatting, Date interoperability,
111
- and deterministic `TestClock` tests
112
- - `./references/guide-atom-data-fetching.md` for the core Effect Atom HTTP
113
- data-fetching workflow, React hook choice, and action-lifetime ownership rules
114
- - `./references/atom-cache-lifecycle.md` for Effect Atom registry scope,
115
- runtime memoization, families, TTL, SWR, polling, and aggregation resets
116
- - `./references/atom-http-and-invalidation.md` for `AtomHttpApi.Service`,
117
- queries, mutations, reactivity keys, and invalidation
118
- - `./references/atom-tanstack-start.md` only for TanStack Start provider
119
- placement, SSR isolation, hydration, and focus guidance
120
- - `./references/atom-testing.md` when adding or diagnosing deterministic Effect
121
- Atom lifecycle tests
122
- - `./references/guide-sql.md` for Effect SQL usage, transactions, resolvers, schema-aware SQL, and migrations
123
- - `./references/guide-testing.md` for `@effect/vitest`, deterministic testing,
124
- honest test Layers, property tests, and protocol round trips
125
- - `./references/guide-cli.md` for Effect-powered command-line scripts and
126
- project automation
127
- - `./references/guide-http-boundaries.md` for `HttpApi` contracts, handlers,
128
- DTOs, transport errors, and route boundaries
129
- - `./references/audit-services.md` for a complete service and type-boundary
130
- audit workflow
131
- - `./references/guide-type-safety-and-boundaries.md` for `unknown`, assertions,
132
- runtime shape checks, external decoding, and boundary ownership
133
-
134
- Treat each topic guide as the single authority for that topic. Do not skip the
135
- guides and jump straight to source unless source-level confirmation is needed
136
- or the guides do not answer the question.
137
-
138
- ## Effect Principles
139
-
140
- Apply these core principles when writing Effect code.
141
-
142
- ## Installation
143
-
144
- When installing Effect v4 packages in a user repository:
145
-
146
- - use the current `effect@beta` version only for a new v4 installation
147
- - preserve the repository's resolved v4 beta for existing installations unless
148
- the user asks for an upgrade
149
- - keep `effect` and all v4 `@effect/*` packages on the exact same beta version
150
- - install only the packages needed for the user's runtime and actual task
151
-
152
- ### Version Rules
153
-
154
- - `effect@latest` is still the v3 release line; use `effect@beta` when creating
155
- a new v4 repository.
156
- - Resolve the beta tag at installation time. Do not assume the review baseline
157
- is still current.
158
- - If you install any v4 `@effect/*` package, make sure it and `effect` use the
159
- same exact beta version.
160
- - Do not mix v3 integration packages with Effect v4 packages.
161
-
162
- ### Package Selection
163
-
164
- Choose packages based on the runtime and the work being done.
165
-
166
- - core library: `effect@beta`
167
- - Node.js runtime needs: install the matching `@effect/platform-node@beta`
168
- - browser runtime needs: install the matching `@effect/platform-browser@beta`
169
- - Bun runtime needs: install the matching `@effect/platform-bun@beta`
170
- - Vitest integration needs: install the matching `@effect/vitest@beta`
171
- - OpenTelemetry integration needs: install the matching
172
- `@effect/opentelemetry@beta`
173
-
174
- Install additional `@effect/*` packages only when the user task actually needs them.
175
-
176
- ### Practical Rule
177
-
178
- - start with the current resolved `effect@beta`
179
- - add matching v4 `@effect/*` packages only as needed by runtime and features
180
- - pin the full installed Effect v4 package set to the same exact beta
181
-
182
- ### Error Handling
183
-
184
- - Use Effect's typed error system instead of throwing exceptions.
185
- - Define descriptive error types with proper error propagation.
186
- - Prefer `Schema.TaggedErrorClass` when the error can be schema-defined.
187
- - Use `Effect.fail`, `Effect.catchTag`, and `Effect.catch` for error control flow.
188
-
189
- ### Dependency Injection
190
-
191
- - Implement dependency injection using services and layers.
192
- - Define services with `Context.Service`.
193
- - Compose layers with `Layer.merge` and `Layer.provide`.
194
- - Use `Effect.provide` to inject dependencies at the edge, avoid providing locally.
195
- - Keep services encapsulated; avoid exporting trivial accessor wrappers that only forward to one service method.
196
-
197
- ### Composability
198
-
199
- - Leverage Effect composability for complex operations.
200
- - Use appropriate constructors such as `Effect.succeed`, `Effect.fail`, `Effect.tryPromise`, `Effect.try`, and `Effect.sync`.
201
- - Apply proper resource management with scoped effects.
202
- - Chain operations with `Effect.flatMap`, `Effect.map`, and `Effect.tap`.
203
-
204
- ### Business Logic Functions
205
-
206
- - Prefer `Effect.fn` for reusable business-logic functions that return `Effect`.
207
- - Prefer `Effect.fn` over raw `Effect.gen` definitions even when the function takes no arguments.
208
- - If you do not want an explicit named span, use `Effect.fn` without a span name.
209
- - Do not use `Effect.fnUntraced` as the default.
210
- - Use `Effect.fnUntraced` only for edge cases with a concrete low-level reason, such as measured hot-path overhead.
211
-
212
- ### TypeScript Preferences
213
-
214
- - Do not use `any` in Effect application, service, or workflow code.
215
- - Decode external values instead of asserting their shape.
216
- - Isolate unavoidable compiler or framework adapter assertions at the
217
- narrowest boundary and document the contract they bridge.
218
- - Do not use `namespace` to hide services, layers, or mutable state.
219
- - Prefer correct typing, schema-driven decoding, narrowing, and proper generic constraints instead of forcing types.
220
- - If a value comes from an external boundary, validate or decode it instead of asserting its type.
221
- - If a type is hard to express, simplify the design or introduce a properly typed helper instead of using unsafe TypeScript.
222
- - For layers, do not hide them inside `namespace` blocks. Prefer either `static` members on the service class or plain exported layer constants.
223
-
224
- ### Date and Time
225
-
226
- - Prefer Effect `DateTime` over vanilla JavaScript `Date` for application
227
- logic. Keep `Date` as an interoperability type at external boundaries.
228
- - Use `DateTime.now` inside Effect programs so current time remains driven by
229
- the `Clock` service and deterministic under `TestClock`.
230
- - Preserve the distinction between instants, zoned wall-clock values, and
231
- date-only domain values.
232
-
233
- ### Code Quality
234
-
235
- - Write type-safe code that leverages Effect's type system.
236
- - Use `Effect.gen` for readable sequential code.
237
- - Implement proper testing patterns using Effect testing utilities.
238
- - Prefer existing Effect primitives before introducing custom helpers.
239
- - Prefer `Schema.Class` / `Schema.TaggedClass` variants over plain `Schema.Struct` for named reusable schemas when possible.
240
-
241
- ### Explaining Solutions
242
-
243
- When providing solutions, explain the Effect concepts being used and why they
244
- fit the specific use case. If you encounter patterns not covered in local
245
- references, prefer consistency with the codebase when possible and otherwise
246
- rely on installed declarations and version-matched canonical Effect source.
247
-
248
- ## References
249
-
250
- - `./references/features.md`
251
- - `./references/guide-effect.md`
252
- - `./references/guide-error-handling.md`
253
- - `./references/guide-layers.md`
254
- - `./references/guide-observability.md`
255
- - `./references/guide-retries.md`
256
- - `./references/guide-schedule.md`
257
- - `./references/guide-schema.md`
258
- - `./references/guide-datetime.md`
259
- - `./references/guide-atom-data-fetching.md`
260
- - `./references/atom-cache-lifecycle.md`
261
- - `./references/atom-http-and-invalidation.md`
262
- - `./references/atom-tanstack-start.md`
263
- - `./references/atom-testing.md`
264
- - `./references/guide-sql.md`
265
- - `./references/guide-testing.md`
266
- - `./references/guide-cli.md`
267
- - `./references/guide-http-boundaries.md`
268
- - `./references/audit-services.md`
269
- - `./references/guide-type-safety-and-boundaries.md`
270
- - `./references/version-and-source.md`
33
+ If you need to learn more about particular Effect apis and concepts that the
34
+ guide doesn't cover, search through the source code in `node_modules/effect/src`.
35
+ ```
@@ -1,4 +1,4 @@
1
1
  interface:
2
- display_name: "Effect Expert"
3
- short_description: "Apply current Effect v4 patterns and tooling"
4
- default_prompt: "Use $effect-ts to apply the relevant Effect architecture, DateTime, Atom, schema, service, error, testing, HTTP, SQL, observability, or CLI guidance."
2
+ display_name: "Effect TypeScript Setup"
3
+ short_description: "Set up version-matched Effect guidance"
4
+ default_prompt: "Use $effect-ts to set up Effect and its package-bundled agent guidance."
@@ -21,3 +21,8 @@ Write a test only when every condition holds:
21
21
  If any condition fails, skip the test and use the cheapest sufficient verification instead. Moving MVP behavior often warrants no committed tests.
22
22
 
23
23
  Test capabilities, not files. Use the fewest tests that protect the risk, and ignore coverage targets unless the user explicitly asks for them.
24
+
25
+ Never commit an intentionally failing or red-only suite. Keep time-driven tests
26
+ deterministic instead of stabilizing them with wall-clock sleeps. A shared fake
27
+ or in-memory implementation must fully provide the behavior its name promises;
28
+ keep partial substitutes local to the tests that need them.
@@ -36,10 +36,9 @@ export type CatalogAddOptions = CatalogCommandOptions & {
36
36
  readonly dryRun?: boolean;
37
37
  };
38
38
 
39
- class CatalogManagerError extends Schema.TaggedErrorClass<CatalogManagerError>()(
40
- "CatalogManagerError",
41
- { message: Schema.String },
42
- ) {}
39
+ class CatalogManagerError extends Schema.TaggedError<CatalogManagerError>()("CatalogManagerError", {
40
+ message: Schema.String,
41
+ }) {}
43
42
 
44
43
  const formattingOptions = { insertSpaces: true, tabSize: 2 } as const;
45
44
 
@@ -63,17 +62,17 @@ const readJsonc = Effect.fn("readCatalogManagerJsonc")(function* <A>(
63
62
  const fs = yield* FileSystem.FileSystem;
64
63
 
65
64
  if (!(yield* fs.exists(filePath))) {
66
- return yield* new CatalogManagerError({ message: `file not found: ${filePath}` });
65
+ return yield* CatalogManagerError.make({ message: `file not found: ${filePath}` });
67
66
  }
68
67
  const raw = yield* fs.readFileString(filePath);
69
68
  const errors: Array<ParseError> = [];
70
69
  const parsed = parseJsonc(raw, errors, { allowTrailingComma: true });
71
70
 
72
71
  if (errors.length > 0) {
73
- return yield* new CatalogManagerError({ message: `could not parse ${filePath}` });
72
+ return yield* CatalogManagerError.make({ message: `could not parse ${filePath}` });
74
73
  }
75
74
  const value = yield* Schema.decodeUnknownEffect(schema)(parsed).pipe(
76
- Effect.mapError((error) => new CatalogManagerError({ message: error.message })),
75
+ Effect.mapError((error) => CatalogManagerError.make({ message: error.message })),
77
76
  );
78
77
 
79
78
  return { raw, value };
@@ -105,7 +104,7 @@ const selectSkills = Effect.fn("selectCatalogSkills")(function* (
105
104
  const unknown = requested.filter((skill) => !available.has(skill));
106
105
 
107
106
  if (unknown.length > 0) {
108
- return yield* new CatalogManagerError({
107
+ return yield* CatalogManagerError.make({
109
108
  message: `repository does not contain: ${unknown.join(", ")}`,
110
109
  });
111
110
  }
@@ -117,7 +116,7 @@ const selectSkills = Effect.fn("selectCatalogSkills")(function* (
117
116
  if (requested.length > 0)
118
117
  return { include: [...new Set(requested)], selected: [...new Set(requested)] };
119
118
  if (!(yield* isInteractiveTerminal)) {
120
- return yield* new CatalogManagerError({
119
+ return yield* CatalogManagerError.make({
121
120
  message: "choose skills with --skill <name>, or pass --all",
122
121
  });
123
122
  }
@@ -194,7 +193,7 @@ export const addCatalogSource = Effect.fn("addCatalogSource")(function* (
194
193
  options: CatalogAddOptions,
195
194
  ) {
196
195
  if (options.all && (options.skills?.length ?? 0) > 0) {
197
- return yield* new CatalogManagerError({ message: "use either --all or --skill, not both" });
196
+ return yield* CatalogManagerError.make({ message: "use either --all or --skill, not both" });
198
197
  }
199
198
  const state = yield* readState(options);
200
199
  const inspection = yield* inspectCatalogRepository({
@@ -210,12 +209,12 @@ export const addCatalogSource = Effect.fn("addCatalogSource")(function* (
210
209
  const byRepository = sources.findIndex((source) => source.repository === inspection.repository);
211
210
 
212
211
  if (byId >= 0 && sources[byId]?.repository !== inspection.repository) {
213
- return yield* new CatalogManagerError({
212
+ return yield* CatalogManagerError.make({
214
213
  message: `source id ${inspection.id} is already used by ${sources[byId]?.repository}`,
215
214
  });
216
215
  }
217
216
  if (byRepository >= 0 && sources[byRepository]?.id !== inspection.id) {
218
- return yield* new CatalogManagerError({
217
+ return yield* CatalogManagerError.make({
219
218
  message: `repository is already cataloged as ${sources[byRepository]?.id}`,
220
219
  });
221
220
  }
@@ -226,7 +225,7 @@ export const addCatalogSource = Effect.fn("addCatalogSource")(function* (
226
225
  const existing = sources[existingIndex];
227
226
 
228
227
  if (existing === undefined) {
229
- return yield* new CatalogManagerError({ message: "catalog source index is out of bounds" });
228
+ return yield* CatalogManagerError.make({ message: "catalog source index is out of bounds" });
230
229
  }
231
230
  const approved =
232
231
  state.lock?.value.sources.find((source) => source.id === existing.id)?.skills ?? [];
@@ -308,12 +307,12 @@ export const removeCatalogEntry = Effect.fn("removeCatalogEntry")(function* (
308
307
  const owner = state.lock?.value.sources.find((source) => source.skills.includes(name));
309
308
 
310
309
  if (!owner)
311
- return yield* new CatalogManagerError({ message: `catalog entry not found: ${name}` });
310
+ return yield* CatalogManagerError.make({ message: `catalog entry not found: ${name}` });
312
311
  const index = sources.findIndex((source) => source.id === owner.id);
313
312
  const source = sources[index];
314
313
 
315
314
  if (!source)
316
- return yield* new CatalogManagerError({ message: `source not found: ${owner.id}` });
315
+ return yield* CatalogManagerError.make({ message: `source not found: ${owner.id}` });
317
316
  if (source.include.includes("*")) {
318
317
  const exclude = [...new Set([...(source.exclude ?? []), name])];
319
318
 
@@ -342,7 +341,7 @@ export const removeCatalogEntry = Effect.fn("removeCatalogEntry")(function* (
342
341
  }
343
342
  if (!options.yes) {
344
343
  if (!(yield* isInteractiveTerminal)) {
345
- return yield* new CatalogManagerError({
344
+ return yield* CatalogManagerError.make({
346
345
  message: "catalog removal requires --yes outside a terminal",
347
346
  });
348
347
  }
@@ -388,7 +387,7 @@ export const showCatalogSource = Effect.fn("showCatalogSource")(function* (
388
387
  const source = state.sources.value.sources.find((candidate) => candidate.id === id);
389
388
 
390
389
  if (!source)
391
- return yield* new CatalogManagerError({ message: `catalog source not found: ${id}` });
390
+ return yield* CatalogManagerError.make({ message: `catalog source not found: ${id}` });
392
391
  const locked = state.lock?.value.sources.find((candidate) => candidate.id === id);
393
392
 
394
393
  yield* printLine(source.id);