@danieljvdm/dev-kit 0.14.0 → 0.16.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 (35) hide show
  1. package/README.md +155 -99
  2. package/dev-kit.example.jsonc +4 -3
  3. package/package.json +1 -1
  4. package/schema/dev-kit.schema.json +19 -42
  5. package/skills/build-effect-apis/SKILL.md +13 -31
  6. package/skills/build-effect-apis/references/verification.md +3 -3
  7. package/skills/dev-kit/SKILL.md +115 -222
  8. package/skills/effect-atom-state/SKILL.md +97 -0
  9. package/skills/effect-atom-state/agents/openai.yaml +4 -0
  10. package/skills/effect-atom-state/references/effect-atom-workflows.md +180 -0
  11. package/skills/open-pull-request/SKILL.md +62 -23
  12. package/src/bin/dev-kit.ts +21 -0
  13. package/src/catalog.ts +39 -15
  14. package/src/effect-source.ts +70 -4
  15. package/src/global-cache.ts +304 -0
  16. package/src/index.ts +6 -6
  17. package/src/manifest.ts +28 -29
  18. package/src/oxlint.js +23 -0
  19. package/src/oxlint.ts +37 -1
  20. package/src/path-digest.ts +0 -13
  21. package/src/project-package.ts +127 -12
  22. package/src/project-state.ts +3 -0
  23. package/src/scaffold.ts +79 -0
  24. package/src/sync.ts +100 -173
  25. package/src/vite-plus-workflow.ts +82 -0
  26. package/src/vite-plus.js +8 -1
  27. package/src/vite-plus.ts +15 -1
  28. package/src/worktrunk-config.ts +88 -0
  29. package/templates/vite-plus/github-actions-check.yml +0 -2
  30. package/templates/worktrunk/wt.toml +27 -0
  31. package/src/vite-plus-quality.ts +0 -148
  32. /package/skills/{build-effect-apis → effect-atom-state}/references/effect-atom-client.md +0 -0
  33. /package/skills/{build-effect-apis → effect-atom-state}/references/effect-atom-lifecycle.md +0 -0
  34. /package/skills/{build-effect-apis → effect-atom-state}/references/effect-atom-testing.md +0 -0
  35. /package/skills/{build-effect-apis → effect-atom-state}/references/tanstack-start.md +0 -0
package/README.md CHANGED
@@ -137,6 +137,7 @@ the root package itself.
137
137
  | `dev-kit gitignore` | Add `.repos/` and `.dev-kit/` to `.gitignore`. |
138
138
  | `dev-kit effect sync` | Sync `.repos/effect` to the installed Effect version. |
139
139
  | `dev-kit tsgo patch` | Validate and patch Effect TypeScript-Go directly. |
140
+ | `dev-kit cache prune` | Evict stale machine-global cache content (`--all` wipes). |
140
141
  | `dev-kit catalog refresh` | Maintainer command to approve current upstream refs. |
141
142
  | `dev-kit catalog add <repository>` | Inspect a repository and approve selected skills. |
142
143
  | `dev-kit catalog remove <source-or-skill>` | Revoke an approval (`--yes` outside a terminal). |
@@ -199,21 +200,15 @@ tool versions. A project-local process lock also prevents concurrent applies.
199
200
  ```
200
201
 
201
202
  - `dev-kit` installs guidance for operating the toolkit itself.
202
- - `open-pull-request` provides a conventional, context-complete PR workflow
203
- with terse English descriptions and verified proof of work.
204
- - `effect` expands to the package-guidance `effect-ts` bootstrap, the
205
- opinionated `effect-architecture-audit`, `build-effect-apis` for shared HTTP
206
- contracts and clients, and `build-effect-clis` for typed command-line
207
- applications, one-off scripts, and CI/deploy/build automation. The focused
208
- references cover Effect Atom, TanStack Start, Cloudflare Workers, child
209
- processes, runtime entrypoints, and script/CLI testing.
210
- - Prefer individual external skills such as `workers-best-practices` and
211
- `wrangler`, selected after scanning the project for relevant technologies.
212
- - `serve-sim` selects the approved Evan Bacon simulator skill directly.
203
+ - `effect` is a built-in family: the `effect-ts` bootstrap,
204
+ `effect-architecture-audit`, `build-effect-apis`, `effect-atom-state`, and
205
+ `build-effect-clis`.
206
+ - External Git skills (`workers-best-practices`, `serve-sim`, …) are selected
207
+ individually after scanning the project for relevant technologies. An
208
+ approved source ID selects every skill from that source; use it only when
209
+ the scan confirms that every member applies.
213
210
  - `@tanstack/ai#ai-core` explicitly selects a skill discovered in that direct
214
211
  project dependency; discovery alone never selects it.
215
- - An approved source ID is broad shorthand that selects every skill from that
216
- source. Use it only when the scan confirms that every member applies.
217
212
 
218
213
  Dev Kit reserves `.repos/<source-id>` for project-local source checkouts. Run
219
214
  `dev-kit gitignore` to add `.repos/` and `.dev-kit/` to the project ignore file.
@@ -239,18 +234,17 @@ bridge in the manifest:
239
234
  `AGENTS.md`, preserving handwritten project guidance around them. The Dev Kit
240
235
  section contains a short description and a pointer to the installed `dev-kit`
241
236
  skill. When the root `package.json` declares `vite-plus` directly, Dev Kit
242
- renders its own repository-specific Vite+ guidance, including the unified
243
- toolchain overview, help and documentation entry points, and `vp env doctor`
244
- troubleshooting. It does not import Vite+'s generic `AGENTS.md`, which can
245
- conflict with the repository's exact commands; transitive installations do not
246
- opt a project in. Previously managed Vite+ sections are removed during a safe
247
- owned update. Ambiguous or malformed managed markers fail closed.
237
+ renders its own repository-specific Vite+ guidance toolchain overview, help
238
+ and documentation entry points, `vp env doctor` troubleshooting — rather than
239
+ importing Vite+'s generic `AGENTS.md`, which can contradict the repository's
240
+ exact commands; transitive installations do not opt a project in. Ambiguous or
241
+ malformed managed markers fail closed.
248
242
 
249
243
  The Dev Kit section also renders an opinionated project command policy. A
250
244
  direct Vite+ dependency makes `vp` the only supported front door: built-in
251
245
  format, lint, and test commands use `vp`, while repository tasks and package
252
- scripts use `vp run`. When Dev Kit manages the quality config, the canonical
253
- full validation and typecheck commands are `vp run check` and
246
+ scripts use `vp run`. When the manifest enables the Vite+ workflow scaffold,
247
+ the canonical full validation and typecheck commands are `vp run check` and
254
248
  `vp run typecheck`; `vp check` alone is only the Vite+ static-check command.
255
249
  Without Vite+, Bun is the required package-script runner and Dev Kit lists only
256
250
  quality scripts the root package actually declares. The package manager named
@@ -291,7 +285,7 @@ worktree converges its own copy during install while the project-owned
291
285
  ## Vite+ quality setup
292
286
 
293
287
  The repository always owns `vite.config.ts`. Compose Dev Kit's quality defaults
294
- from that project-owned config, then opt into the hardened GitHub Actions
288
+ from that project-owned config, then opt into the scaffolded GitHub Actions
295
289
  workflow independently:
296
290
 
297
291
  ```ts
@@ -321,13 +315,6 @@ Project and framework-generated paths belong in `ignorePatterns` as shown;
321
315
  custom harness target paths belong there too. Dev Kit does not grow a global
322
316
  framework ignore list.
323
317
 
324
- Vite+ 0.2.6 forwards JavaScript-plugin declarations into its effective lint
325
- config but its bundled native Oxlint path does not register or execute those
326
- rules. Native Oxlint rules and Oxfmt settings remain active; run standalone
327
- Oxlint when enforcement of Dev Kit's `effect/*` or
328
- `stylistic/padding-line-between-statements` rules is required. This limitation
329
- can be removed once a supported Vite+ release executes configured JS plugins.
330
-
331
318
  ```jsonc
332
319
  {
333
320
  "include": ["dev-kit", "effect"],
@@ -335,19 +322,24 @@ can be removed once a supported Vite+ release executes configured JS plugins.
335
322
  "effectTsgo": { "enabled": true },
336
323
  "vitePlus": {
337
324
  "hooks": { "enabled": true },
338
- "quality": {
339
- "workflow": { "enabled": true },
340
- },
325
+ "workflow": { "enabled": true },
341
326
  },
342
327
  },
343
328
  }
344
329
  ```
345
330
 
346
- `quality.workflow.enabled` owns `.github/workflows/check.yml` but never reads,
347
- rewrites, adopts, or removes `vite.config.ts`. Workflow setup requires direct
348
- `@danieljvdm/dev-kit`, `vite-plus`, `effect`, `@effect/tsgo`, and native
349
- TypeScript dependencies with `setup.effectTsgo.enabled`. The installed Vite+
350
- must satisfy Dev Kit's peer range.
331
+ `setup.vitePlus.workflow` scaffolds `.github/workflows/check.yml` and never
332
+ reads, rewrites, adopts, or removes `vite.config.ts`. Scaffolds are
333
+ create-only: the file is written only when missing, never recorded in
334
+ `dev-kit.lock.json`, and never touched again — the repository owns it from
335
+ creation, and disabling the task leaves it in place. Edit the YAML directly
336
+ for repository-specific preparation steps or a custom typecheck command; when
337
+ the shipped template improves, compare against the installed copy under
338
+ `node_modules/@danieljvdm/dev-kit/templates/` and merge what fits.
339
+ Scaffolding requires direct `@danieljvdm/dev-kit`, `vite-plus`, `effect`,
340
+ `@effect/tsgo`, and native TypeScript dependencies with
341
+ `setup.effectTsgo.enabled`, and the installed Vite+ must satisfy Dev Kit's
342
+ peer range.
351
343
 
352
344
  Workspaces select bounded, dependency-ordered typechecking in their config:
353
345
 
@@ -363,44 +355,98 @@ export default defineConfig(
363
355
  );
364
356
  ```
365
357
 
366
- Each listed package must expose a pure `typecheck` script. Repositories can
367
- also declare workflow-specific preparation and typecheck commands:
358
+ Each listed package must expose a pure `typecheck` script.
359
+
360
+ The scaffolded workflow performs one frozen, script-suppressed install, runs
361
+ `dev-kit apply --locked`, and only then runs formatting, linting, tests, and
362
+ `vp run typecheck`. See the primary
363
+ [`setup-vp` versioning guidance](https://github.com/voidzero-dev/setup-vp#versioning),
364
+ [Vite+ install guide](https://viteplus.dev/guide/install), and
365
+ [Vite Task run guide](https://viteplus.dev/guide/run) when maintaining the
366
+ templates.
367
+
368
+ ### Absolute (path-alias) imports
369
+
370
+ Opt into enforcing path-alias imports for selected app sources. The factory
371
+ appends an Oxlint override that errors on `../` imports inside the given
372
+ globs, so those files import through tsconfig path aliases such as `@/*`:
373
+
374
+ ```ts
375
+ export default defineConfig(
376
+ createRecommendedVitePlusConfig({
377
+ absoluteImports: {
378
+ files: ["apps/app/src/**/*.{ts,tsx}", "apps/mobile/src/**/*.{ts,tsx}"],
379
+ },
380
+ }),
381
+ );
382
+ ```
383
+
384
+ The lint rule only forbids relative parent imports; each covered app must map
385
+ the alias itself. Add the `paths` entry to the app's `tsconfig.json`:
368
386
 
369
387
  ```jsonc
370
388
  {
389
+ "compilerOptions": {
390
+ "paths": { "@/*": ["./src/*"] },
391
+ },
392
+ }
393
+ ```
394
+
395
+ Vite-built apps also resolve the alias from the same tsconfig by setting
396
+ `resolve: { tsconfigPaths: true }` in the app's Vite config. Expo apps need no
397
+ Metro configuration: Expo SDK 49+ resolves tsconfig `paths` by default.
398
+
399
+ Standalone Oxlint projects compose the same override directly:
400
+
401
+ ```ts
402
+ // oxlint.config.ts
403
+ import {
404
+ createAbsoluteImportsOxlintOverride,
405
+ recommendedOxlintConfig,
406
+ } from "@danieljvdm/dev-kit/oxlint";
407
+ import { defineConfig } from "oxlint";
408
+
409
+ export default defineConfig({
410
+ extends: [recommendedOxlintConfig],
411
+ overrides: [createAbsoluteImportsOxlintOverride({ files: ["src/**/*.{ts,tsx}"] })],
412
+ });
413
+ ```
414
+
415
+ ## Worktrunk project config
416
+
417
+ Enable a scaffolded default [Worktrunk](https://worktrunk.dev) project config
418
+ in the manifest:
419
+
420
+ ```jsonc
421
+ {
422
+ "include": ["dev-kit"],
371
423
  "setup": {
372
- "effectTsgo": { "enabled": true },
373
- "vitePlus": {
374
- "quality": {
375
- "workflow": {
376
- "enabled": true,
377
- "beforeChecks": [
378
- {
379
- "name": "Install media tools",
380
- "run": ["sudo apt-get update", "sudo apt-get install --yes ffmpeg"],
381
- },
382
- ],
383
- "typecheck": [
384
- "vp run -F './apps/*' -F './packages/*' check",
385
- "vp exec tsc --noEmit -p scripts/tsconfig.json",
386
- ],
387
- },
388
- },
389
- },
424
+ "worktrunk": { "config": { "enabled": true } },
390
425
  },
391
426
  }
392
427
  ```
393
428
 
394
- The workflow performs one frozen, script-suppressed install, runs
395
- `dev-kit apply --locked`, and only then runs preparation, formatting, linting,
396
- tests, and typechecking. Its default typecheck command is `vp run typecheck`;
397
- `workflow.typecheck` replaces it. Existing workflows remain user-owned until
398
- their rendered content matches exactly—Dev Kit never merges YAML. See the
399
- primary
400
- [`setup-vp` versioning guidance](https://github.com/voidzero-dev/setup-vp#versioning),
401
- [Vite+ install guide](https://viteplus.dev/guide/install), and
402
- [Vite Task run guide](https://viteplus.dev/guide/run) when maintaining the
403
- templates.
429
+ `setup.worktrunk.config` scaffolds `.config/wt.toml` with the portable hooks an
430
+ app repository wants in every worktree: a `pre-start` pipeline that copies
431
+ gitignored files matched by `.worktreeinclude` (a no-op without that file) and
432
+ then installs dependencies, plus a `pre-merge` full-validation hook. Hook
433
+ commands render for the repository's command runner: a direct `vite-plus`
434
+ dependency selects `vp install` and `vp run check`; otherwise Dev Kit requires
435
+ a declared root `check` package script, runs it through `bun run check`, and
436
+ takes the install command from the detected package manager. Repositories with
437
+ neither fail the plan instead of shipping a broken hook.
438
+
439
+ The config follows the same create-only scaffold semantics as the check
440
+ workflow above: created once, never locked or touched again, owned by the
441
+ repository. Edit hooks freely after creation.
442
+
443
+ The config intentionally carries no worktree-path template or other user
444
+ preferences—those belong in each user's `~/.config/worktrunk/config.toml`. A
445
+ commented `post-start` block shows how to run a per-worktree dev server on a
446
+ stable branch-derived port (`{{ branch | hash_port }}`) under `wt step tether`;
447
+ point it at the repository's dev entrypoint and uncomment to opt in. Worktrunk
448
+ never runs project hooks until each user approves them with
449
+ `wt config approvals add`.
404
450
 
405
451
  ## Effect source checkout
406
452
 
@@ -416,9 +462,12 @@ Enable a local checkout of the exact installed Effect release in the manifest:
416
462
  ```
417
463
 
418
464
  `dev-kit apply` reads `node_modules/effect/package.json`, then shallow-clones or
419
- updates `.repos/effect` to the detached `effect@<version>` tag. It skips the
420
- checkout in CI, leaves the repository in place when the task is disabled, and
421
- refuses to switch a checkout with local changes or an unexpected origin.
465
+ updates `.repos/effect` to the detached `effect@<version>` tag. Tag fetches go
466
+ through a shared clone in the machine-global cache, so a new worktree or
467
+ project reuses tags already cached on the machine and only contacts the
468
+ network for a tag the cache has never seen. It skips the checkout in CI,
469
+ leaves the repository in place when the task is disabled, and refuses to
470
+ switch a checkout with local changes or an unexpected origin.
422
471
 
423
472
  The path, package name, and repository URL may be overridden for compatible
424
473
  Effect package layouts. Use `dev-kit effect sync --dry-run` to inspect this
@@ -522,31 +571,20 @@ bun x dev-kit add @tanstack/ai#ai-core
522
571
  That writes `@tanstack/ai#ai-core` to `dev-kit.jsonc` and, unless
523
572
  `--no-apply` is passed, installs it through the normal ownership-safe sync
524
573
  path. The qualifier prevents ambiguity when two dependencies publish the same
525
- skill name, and the installed output carries it too: the copied directory is
526
- named by flattening the package name (drop `@`, turn every other
527
- non-alphanumeric run into one dash) and appending the skill name, so
528
- `@tanstack/ai#ai-core` installs as `tanstack-ai-ai-core`. Agent harnesses
529
- identify a project skill by its directory name, so the copied `SKILL.md`
530
- frontmatter `name:` is rewritten to that same install name; all other content
531
- is copied verbatim. Symlink-mode targets link straight into `node_modules`, so
532
- only the link itself carries the qualified name while the linked frontmatter
533
- keeps the upstream bare name. Two selected skills that would both write the
534
- same destination are rejected before any output is changed.
535
-
536
- The initial compatibility boundary is intentionally small and deterministic:
537
-
538
- - only packages named in the root project's `dependencies`,
539
- `devDependencies`, `optionalDependencies`, or `peerDependencies` are
540
- scanned;
541
- - package code is never imported or executed;
542
- - npm-style and pnpm/workspace symlinks under `node_modules` are supported;
543
- - Yarn Plug'n'Play and transitive dependency traversal are not scanned; and
544
- - immediate `skills/<name>/SKILL.md` roots are listed. Nested topic skills and
545
- references remain part of that root and are copied with it.
546
-
547
- The last rule adapts Intent's routed, nested skill trees to the immediate folder
548
- and frontmatter-name invariants expected by Agent Skills targets. Dev Kit does
549
- not rewrite nested names or ask Intent to manage agent configuration.
574
+ skill name, and the installed output carries it: the copied directory flattens
575
+ the package name and appends the skill name (`@tanstack/ai#ai-core`
576
+ `tanstack-ai-ai-core`), and the copied `SKILL.md` frontmatter `name:` is
577
+ rewritten to match because harnesses identify a skill by its directory name.
578
+ Symlink-mode targets link straight into `node_modules`, so only the link
579
+ carries the qualified name. Two selections that would write the same
580
+ destination are rejected before any output changes.
581
+
582
+ The compatibility boundary is intentionally small and deterministic: only the
583
+ root project's direct dependencies are scanned, package code is never imported
584
+ or executed, npm-style and pnpm/workspace symlinks are supported (Yarn
585
+ Plug'n'Play and transitive traversal are not), and only immediate
586
+ `skills/<name>/SKILL.md` roots are listed — nested topic skills and references
587
+ are copied as part of their root.
550
588
 
551
589
  The project `dev-kit.lock.json` records the selected package name, installed
552
590
  version, original bare skill name, and the `node_modules` content digest.
@@ -601,9 +639,23 @@ names and paths, rejects symlinks and collisions, extracts descriptions, and
601
639
  updates `skill-sources.lock.json`.
602
640
 
603
641
  When a project selects one of these Git-backed skills, Dev Kit fetches the
604
- approved commit into the ignored `.dev-kit/cache` and installs it through the
605
- same ownership-safe sync path. Only a reviewed catalog refresh changes the
606
- approved Git content.
642
+ approved commit into a machine-global cache and installs it through the same
643
+ ownership-safe sync path. Cache entries are keyed by resolved commit SHA, so
644
+ every project and git worktree on the machine shares one download; a warm
645
+ `dev-kit plan` or `dev-kit apply` performs no network operations. The cache
646
+ lives in `$XDG_CACHE_HOME/dev-kit` (falling back to `~/Library/Caches/dev-kit`
647
+ on macOS and `~/.cache/dev-kit` elsewhere) and may be overridden with
648
+ `DEV_KIT_CACHE_DIR`; it is safe to delete at any time. Populating this
649
+ immutable commit-keyed cache is not project state, so planning and `--locked`
650
+ verification use it too. Only a reviewed catalog refresh changes the approved
651
+ Git content.
652
+
653
+ The cache does not grow without bounds: every use refreshes a recency stamp,
654
+ and `dev-kit apply` sweeps content unused for 30 days at most once a day.
655
+ Shared Effect repositories drop unused tags individually and are removed whole
656
+ once empty. Run `dev-kit cache prune` to sweep on demand (`--max-age-days` to
657
+ tune the threshold, `--all` to clear the cache entirely); an evicted entry is
658
+ simply fetched again the next time a project needs it.
607
659
 
608
660
  ## Oxlint and Oxfmt configurations
609
661
 
@@ -652,7 +704,11 @@ export default defineConfig({
652
704
  The Oxlint preset enables `stylistic/padding-line-between-statements`: adjacent
653
705
  variable declarations remain grouped, while the next logical statement and
654
706
  all `return` statements require a separating blank line. The rule is fixable,
655
- so `vp lint --fix` repairs missing spacing automatically.
707
+ so `vp lint --fix` repairs missing spacing automatically. Vite+ 0.2.6 forwards
708
+ the preset's JavaScript-plugin declarations but its native Oxlint path does not
709
+ execute their rules — run standalone Oxlint when `effect/*` or the padding rule
710
+ must be enforced, until a supported Vite+ release executes configured JS
711
+ plugins.
656
712
 
657
713
  The preset also registers the shared `effect` JavaScript plugin. Effect
658
714
  projects opt into its rules in path-specific overrides, for example
@@ -8,9 +8,10 @@
8
8
  "effectTsgo": { "enabled": true },
9
9
  "vitePlus": {
10
10
  "hooks": { "enabled": true },
11
- "quality": {
12
- "workflow": { "enabled": true },
13
- },
11
+ "workflow": { "enabled": true },
12
+ },
13
+ "worktrunk": {
14
+ "config": { "enabled": true },
14
15
  },
15
16
  },
16
17
  "targets": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danieljvdm/dev-kit",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "private": false,
5
5
  "description": "Declarative project development toolkit with portable agent skills.",
6
6
  "license": "MIT",
@@ -48,6 +48,9 @@
48
48
  },
49
49
  "vitePlus": {
50
50
  "$ref": "#/$defs/vitePlusSetup"
51
+ },
52
+ "worktrunk": {
53
+ "$ref": "#/$defs/worktrunkSetup"
51
54
  }
52
55
  },
53
56
  "default": {}
@@ -144,8 +147,8 @@
144
147
  "hooks": {
145
148
  "$ref": "#/$defs/vitePlusHooksSetup"
146
149
  },
147
- "quality": {
148
- "$ref": "#/$defs/vitePlusQualitySetup"
150
+ "workflow": {
151
+ "$ref": "#/$defs/vitePlusWorkflowSetup"
149
152
  }
150
153
  }
151
154
  },
@@ -160,61 +163,35 @@
160
163
  }
161
164
  }
162
165
  },
163
- "vitePlusQualitySetup": {
164
- "description": "Manage the Vite+ quality workflow while the repository owns and extends vite.config.ts.",
166
+ "vitePlusWorkflowSetup": {
167
+ "description": "Scaffold the canonical GitHub Actions check workflow (.github/workflows/check.yml); the repository owns the file after creation.",
165
168
  "type": "object",
166
169
  "additionalProperties": false,
167
170
  "properties": {
168
- "workflow": {
169
- "$ref": "#/$defs/vitePlusQualityWorkflowSetup"
171
+ "enabled": {
172
+ "type": "boolean",
173
+ "default": false
170
174
  }
171
175
  }
172
176
  },
173
- "vitePlusQualityWorkflowSetup": {
174
- "description": "Manage the canonical GitHub Actions check workflow without requiring Dev Kit to own the Vite config.",
177
+ "worktrunkSetup": {
178
+ "description": "Manage project-local Worktrunk setup tasks.",
175
179
  "type": "object",
176
180
  "additionalProperties": false,
177
181
  "properties": {
178
- "enabled": {
179
- "type": "boolean",
180
- "default": false
181
- },
182
- "beforeChecks": {
183
- "description": "Repository-specific preparation steps inserted after locked setup verification and before quality checks.",
184
- "type": "array",
185
- "items": {
186
- "$ref": "#/$defs/vitePlusQualityWorkflowStep"
187
- },
188
- "default": []
189
- },
190
- "typecheck": {
191
- "description": "Shell commands for the workflow's pure typecheck step.",
192
- "type": "array",
193
- "minItems": 1,
194
- "items": {
195
- "type": "string",
196
- "minLength": 1
197
- },
198
- "default": ["vp run typecheck"]
182
+ "config": {
183
+ "$ref": "#/$defs/worktrunkConfigSetup"
199
184
  }
200
185
  }
201
186
  },
202
- "vitePlusQualityWorkflowStep": {
187
+ "worktrunkConfigSetup": {
188
+ "description": "Scaffold the default Worktrunk project config (.config/wt.toml) with portable pre-start and pre-merge hooks rendered for the repository's command runner; the repository owns the file after creation.",
203
189
  "type": "object",
204
190
  "additionalProperties": false,
205
- "required": ["name", "run"],
206
191
  "properties": {
207
- "name": {
208
- "type": "string",
209
- "minLength": 1
210
- },
211
- "run": {
212
- "type": "array",
213
- "minItems": 1,
214
- "items": {
215
- "type": "string",
216
- "minLength": 1
217
- }
192
+ "enabled": {
193
+ "type": "boolean",
194
+ "default": false
218
195
  }
219
196
  }
220
197
  },
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: build-effect-apis
3
- description: Build and consume contract-first Effect HTTP APIs. Use when defining shared HttpApiEndpoint/HttpApiGroup contracts, implementing HttpApiBuilder or HttpApiServer handlers and middleware, deriving HttpApiClient or Effect Atom clients, or integrating those APIs with TanStack Start and Cloudflare Workers/effect-cf.
3
+ description: Build contract-first Effect HTTP APIs. Use when defining shared HttpApiEndpoint/HttpApiGroup contracts, implementing HttpApiBuilder or HttpApiServer handlers and middleware, assembling server runtimes and OpenAPI docs, or serving on Cloudflare Workers/effect-cf. For consuming an API from client state, use $effect-atom-state.
4
4
  ---
5
5
 
6
6
  # Build Effect APIs
@@ -9,12 +9,11 @@ Treat the shared `HttpApi` value as the **contract spine**: schemas, server,
9
9
  OpenAPI, and clients all derive from it. Keep transport contracts isomorphic;
10
10
  keep runtime behavior in handlers, services, layers, and client state modules.
11
11
 
12
- Effect HTTP and reactivity APIs are version-sensitive. Read the target
13
- repository's manifests and lockfile, inspect its existing imports, and confirm
14
- exact signatures from the installed package declarations before editing. In
15
- current Effect v4 betas the server module is `HttpApiBuilder`; a request that
16
- mentions `HttpApiServer` may refer to the same server-building responsibility
17
- from another version.
12
+ Effect HTTP APIs are version-sensitive. Read the target repository's manifests
13
+ and lockfile, inspect its existing imports, and confirm exact signatures from
14
+ the installed package declarations before editing. In current Effect v4 betas
15
+ the server module is `HttpApiBuilder`; a request that mentions `HttpApiServer`
16
+ may refer to the same server-building responsibility from another version.
18
17
 
19
18
  ## Build the contract spine
20
19
 
@@ -31,35 +30,21 @@ from another version.
31
30
  decoded boundary adapters into application services and assemble all
32
31
  requirements at the runtime edge. Finish when each endpoint identifier has
33
32
  exactly one handler and every declared middleware has a provided layer.
34
- 4. Choose the consumer branch:
35
- - For React server state, read
36
- [effect-atom-client.md](references/effect-atom-client.md) and
37
- [effect-atom-lifecycle.md](references/effect-atom-lifecycle.md), then
38
- derive one `AtomHttpApi.Service`, stable query atoms or families, mutation
39
- atoms, and one reactivity-key vocabulary.
40
- - For non-React Effect code, use the direct `HttpApiClient` branch in
41
- [effect-atom-client.md](references/effect-atom-client.md).
42
-
43
- Finish when consumers call the shared contract rather than redefining wire
44
- types or using ad hoc `fetch` for declared endpoints.
45
-
33
+ 4. Route consumer changes through the `$effect-atom-state` skill: deriving
34
+ `AtomHttpApi` or direct `HttpApiClient` clients, query and mutation atoms,
35
+ reactivity keys, and React integration all live there. Finish when consumers
36
+ call the shared contract rather than redefining wire types or using ad hoc
37
+ `fetch` for declared endpoints.
46
38
  5. Read [verification.md](references/verification.md). Run the repository's
47
39
  format, lint, typecheck, and test commands. Finish when changed schemas
48
- round-trip, middleware failures use declared error channels, server and
49
- client agree on every request shape, and changed atom lifecycles have
50
- deterministic coverage.
40
+ round-trip, middleware failures use declared error channels, and server and
41
+ client agree on every request shape.
51
42
 
52
43
  ## Optional branches
53
44
 
54
45
  - Read [runtime-assembly.md](references/runtime-assembly.md) when wiring a
55
46
  conventional Node/Bun server, generated API docs, process entrypoint, or
56
47
  serverless web handler.
57
- - Read [effect-atom-testing.md](references/effect-atom-testing.md) when changing
58
- Atom cache retention, SWR, polling, invalidation, cancellation, aggregation,
59
- provider placement, SSR, or hydration behavior.
60
- - Read [tanstack-start.md](references/tanstack-start.md) when the client is
61
- TanStack Start, SSR, hydration, `ClientOnly`, loaders, server functions, or a
62
- proxied separate API.
63
48
  - Read [cloudflare-workers.md](references/cloudflare-workers.md) when the server
64
49
  runs on Cloudflare Workers or uses `effect-cf`, bindings, Durable Objects,
65
50
  Queues, WebSockets, streaming, or raw byte routes.
@@ -94,6 +79,3 @@ but the boundary and type reasoning remain the source of truth.
94
79
  - Let handlers own transport-to-application mapping and boundary invariants.
95
80
  - Let application services own orchestration, persistence, retries, and
96
81
  transactions.
97
- - Let client data modules own API services, query identity, cache policy,
98
- invalidation keys, and mutation atoms; let UI action owners own navigation,
99
- toasts, optimistic presentation, and form reset.
@@ -48,9 +48,9 @@ decoding are skipped.
48
48
  `HttpApiMiddleware.layerClient` and assert that it transforms the request.
49
49
  - Assert params, query, headers, payload, and expected errors at least once for
50
50
  every changed request shape.
51
- - For Atom clients, complete every applicable scenario routed through
52
- `effect-atom-testing.md`; use a deterministic HTTP layer so request encoding,
53
- invalidation, and lifecycle remain observable.
51
+ - For Atom clients, complete every applicable scenario in the
52
+ `$effect-atom-state` skill's testing reference; use a deterministic HTTP
53
+ layer so request encoding, invalidation, and lifecycle remain observable.
54
54
 
55
55
  ## Completion matrix
56
56