@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.
- package/README.md +155 -99
- package/dev-kit.example.jsonc +4 -3
- package/package.json +1 -1
- package/schema/dev-kit.schema.json +19 -42
- package/skills/build-effect-apis/SKILL.md +13 -31
- package/skills/build-effect-apis/references/verification.md +3 -3
- package/skills/dev-kit/SKILL.md +115 -222
- package/skills/effect-atom-state/SKILL.md +97 -0
- package/skills/effect-atom-state/agents/openai.yaml +4 -0
- package/skills/effect-atom-state/references/effect-atom-workflows.md +180 -0
- package/skills/open-pull-request/SKILL.md +62 -23
- package/src/bin/dev-kit.ts +21 -0
- package/src/catalog.ts +39 -15
- package/src/effect-source.ts +70 -4
- package/src/global-cache.ts +304 -0
- package/src/index.ts +6 -6
- package/src/manifest.ts +28 -29
- package/src/oxlint.js +23 -0
- package/src/oxlint.ts +37 -1
- package/src/path-digest.ts +0 -13
- package/src/project-package.ts +127 -12
- package/src/project-state.ts +3 -0
- package/src/scaffold.ts +79 -0
- package/src/sync.ts +100 -173
- package/src/vite-plus-workflow.ts +82 -0
- package/src/vite-plus.js +8 -1
- package/src/vite-plus.ts +15 -1
- package/src/worktrunk-config.ts +88 -0
- package/templates/vite-plus/github-actions-check.yml +0 -2
- package/templates/worktrunk/wt.toml +27 -0
- package/src/vite-plus-quality.ts +0 -148
- /package/skills/{build-effect-apis → effect-atom-state}/references/effect-atom-client.md +0 -0
- /package/skills/{build-effect-apis → effect-atom-state}/references/effect-atom-lifecycle.md +0 -0
- /package/skills/{build-effect-apis → effect-atom-state}/references/effect-atom-testing.md +0 -0
- /package/skills/{build-effect-apis → effect-atom-state}/references/tanstack-start.md +0 -0
package/skills/dev-kit/SKILL.md
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dev-kit
|
|
3
|
-
description: Dev-kit operations for projects that configure dev-kit.jsonc, sync portable skills, run plan/apply or automatic postinstalls, perform locked CI checks, maintain dev-kit.lock.json, resolve ownership conflicts,
|
|
3
|
+
description: Dev-kit operations for projects that configure dev-kit.jsonc, sync portable skills, run plan/apply or automatic postinstalls, perform locked CI checks, maintain dev-kit.lock.json, resolve ownership conflicts, or enable Effect TypeScript-Go.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Dev Kit
|
|
7
7
|
|
|
8
8
|
Treat `dev-kit.jsonc` as desired state, `dev-kit.lock.json` as the committed
|
|
9
|
-
resolution, and `.dev-kit/state.json` as local ownership receipts.
|
|
9
|
+
resolution, and `.dev-kit/state.json` as local ownership receipts. Deep
|
|
10
|
+
reference — catalog maintenance, package-skill discovery rules, preset
|
|
11
|
+
internals — lives in the package README
|
|
12
|
+
(`node_modules/@danieljvdm/dev-kit/README.md`).
|
|
10
13
|
|
|
11
14
|
Use the high-level commands for routine changes: `dev-kit init`, `dev-kit add
|
|
12
15
|
<skill...>`, `dev-kit remove <skill...>`, `dev-kit list --all`, `dev-kit search
|
|
13
16
|
<words...>`, and `dev-kit info <skill>`. Add and remove apply immediately unless
|
|
14
17
|
passed `--no-apply`; `dev-kit sync` applies an already-edited manifest.
|
|
15
18
|
|
|
16
|
-
For distro maintenance, use `dev-kit catalog add <repository>` to inspect and
|
|
17
|
-
approve upstream skills, `catalog list`/`catalog info` to review provenance,
|
|
18
|
-
`catalog remove <source-or-skill>` to revoke approval, and `catalog verify` in
|
|
19
|
-
CI. Pass repeated `--skill` flags or `--all` outside a terminal. Approval always
|
|
20
|
-
stores explicit skill names and exact commit/content digests.
|
|
21
|
-
|
|
22
19
|
## Apply loop
|
|
23
20
|
|
|
24
21
|
1. Establish the Git root. Read project agent instructions, the current
|
|
@@ -33,14 +30,12 @@ stores explicit skill names and exact commit/content digests.
|
|
|
33
30
|
requested creative or advisory skills even when they have no mechanical
|
|
34
31
|
dependency signal.
|
|
35
32
|
3. Choose the narrowest useful set. Prefer focused external skills over a
|
|
36
|
-
generic umbrella
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
the skill routes to them. A multi-product repository can therefore justify
|
|
43
|
-
an umbrella while still excluding unrelated top-level skills.
|
|
33
|
+
generic umbrella; select an umbrella or source family only when its full
|
|
34
|
+
breadth is intentionally useful, never because one member matches. Explain
|
|
35
|
+
any uncertain inclusion before applying it. Unused `references/` folders
|
|
36
|
+
inside a selected skill cost repository space, not agent context, so a
|
|
37
|
+
multi-product repository can justify an umbrella while still excluding
|
|
38
|
+
unrelated top-level skills.
|
|
44
39
|
4. Update `dev-kit.jsonc`. Preserve JSONC comments and validate against the
|
|
45
40
|
package schema. Finish with each desired resource represented once and every
|
|
46
41
|
external selection supported by repository evidence or an explicit request.
|
|
@@ -51,126 +46,108 @@ stores explicit skill names and exact commit/content digests.
|
|
|
51
46
|
6. Resolve conflicts, then run `dev-kit apply`. Commit the manifest and
|
|
52
47
|
regenerated `dev-kit.lock.json`; keep `.dev-kit/` local. Finish when a second
|
|
53
48
|
plan reports only unchanged resources and setup tasks.
|
|
54
|
-
7. Use `dev-kit apply` in the package lifecycle so intentional dependency
|
|
55
|
-
upgrades regenerate owned outputs and `dev-kit.lock.json`. For strict CI,
|
|
56
|
-
either disable lifecycle scripts before `dev-kit apply --locked`, or run the
|
|
57
|
-
normal lifecycle and require the tracked working tree to remain clean. Never
|
|
58
|
-
run an unlocked apply before locked verification. Finish when a clean install
|
|
59
|
-
converges from the committed manifest and lock.
|
|
60
49
|
|
|
61
50
|
## Manifest
|
|
62
51
|
|
|
63
52
|
Use skill names or family names in `include`; subtract selections with
|
|
64
|
-
`exclude`. Built-in families such as `effect` are intentional bundles.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
skill
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
`<package>#<skill>` selector. The selector stays package-qualified in the
|
|
71
|
-
manifest, lock, and CLI listings, and the installed output keeps that identity:
|
|
72
|
-
the copied directory is named by flattening the package name (drop `@`, turn
|
|
73
|
-
every other non-alphanumeric run into one dash) and appending the skill name,
|
|
74
|
-
so `@tanstack/table-core#core` installs as `tanstack-table-core-core`. The
|
|
75
|
-
copied `SKILL.md` frontmatter `name:` is rewritten to the same install name;
|
|
76
|
-
everything else is verbatim. Symlink-mode targets still point at
|
|
77
|
-
`node_modules`, so their frontmatter keeps the upstream bare name. Two selected
|
|
78
|
-
skills that flatten to the same install name are rejected before any output
|
|
79
|
-
changes.
|
|
53
|
+
`exclude`. Built-in families such as `effect` are intentional bundles. Include
|
|
54
|
+
this skill as `dev-kit` when project agents should carry the toolkit
|
|
55
|
+
procedure. Skills bundled inside installed packages need the exact
|
|
56
|
+
`<package>#<skill>` selector; the copied output flattens that identity into
|
|
57
|
+
one directory name (`@tanstack/table-core#core` → `tanstack-table-core-core`)
|
|
58
|
+
and rewrites the copied frontmatter `name:` to match.
|
|
80
59
|
|
|
81
60
|
```jsonc
|
|
82
61
|
{
|
|
83
62
|
"$schema": "./node_modules/@danieljvdm/dev-kit/schema/dev-kit.schema.json",
|
|
84
63
|
"include": ["dev-kit", "effect"],
|
|
85
|
-
"exclude": [],
|
|
86
64
|
"setup": {
|
|
87
65
|
"agentInstructions": { "enabled": true },
|
|
88
66
|
"claudeInstructions": { "enabled": true },
|
|
89
67
|
"vitePlus": {
|
|
90
68
|
"hooks": { "enabled": true },
|
|
91
|
-
"
|
|
92
|
-
|
|
93
|
-
|
|
69
|
+
"workflow": { "enabled": true },
|
|
70
|
+
},
|
|
71
|
+
"worktrunk": {
|
|
72
|
+
"config": { "enabled": true },
|
|
94
73
|
},
|
|
95
74
|
},
|
|
96
75
|
"targets": {
|
|
97
76
|
"agents": { "enabled": true, "mode": "copy" },
|
|
98
77
|
"claude": { "enabled": true, "mode": "symlink" },
|
|
99
|
-
"opencode": { "enabled": false, "mode": "symlink" },
|
|
100
78
|
},
|
|
101
79
|
}
|
|
102
80
|
```
|
|
103
81
|
|
|
104
82
|
Prefer a copied `.agents/skills` target as the project-local source of truth;
|
|
105
83
|
use symlinks for additional harness discovery paths. Keep every target path
|
|
106
|
-
project-relative and separate from the manifest, lock, state
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
`
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Kit owns; remove a legacy owned Vite+ section during migration.
|
|
119
|
-
When `effect` is a declared direct dependency and the installed package ships a
|
|
120
|
-
regular `node_modules/effect/AGENTS.md` file, the managed section also directs
|
|
121
|
-
agents to read that version-matched guide completely and use
|
|
122
|
-
`node_modules/effect/src` for gaps. Omit the pointer when the package is absent,
|
|
123
|
-
transitive, or too old to ship the guide; never generate a dangling path.
|
|
124
|
-
The managed section also publishes the repository's command authority. Direct
|
|
125
|
-
Vite+ projects must use `vp` built-ins and `vp run <task>`; projects using the
|
|
126
|
-
recommended Vite+ factory use `vp run check` for the complete
|
|
127
|
-
format/lint/test/typecheck suite and `vp run typecheck` for the Effect-patched
|
|
128
|
-
compiler. Non-Vite+ projects run
|
|
129
|
-
existing root quality scripts through `bun run`; package-manager metadata and
|
|
130
|
-
lockfiles affect dependency-install guidance only. Never substitute another
|
|
84
|
+
project-relative and separate from the manifest, lock, and state paths.
|
|
85
|
+
|
|
86
|
+
## Managed instructions
|
|
87
|
+
|
|
88
|
+
`setup.agentInstructions` manages marked sections in the project-root
|
|
89
|
+
`AGENTS.md` and preserves handwritten content around them; edit only outside
|
|
90
|
+
the markers. The section points agents at this skill, renders the repository's
|
|
91
|
+
command policy from live evidence (a direct `vite-plus` dependency makes `vp`
|
|
92
|
+
the only front door; otherwise Bun runs declared root scripts), and adds the
|
|
93
|
+
Effect guide pointer when the installed `effect` package ships one. Treat
|
|
94
|
+
duplicate, overlapping, reversed, or unmatched managed markers as a conflict
|
|
95
|
+
rather than guessing which content Dev Kit owns. Never substitute another
|
|
131
96
|
script runner or call raw `tsc`, test, lint, or format binaries when a project
|
|
132
97
|
command exists.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
Enable `setup.vitePlus.hooks` when an installed direct `vite-plus` dependency
|
|
141
|
-
should manage Git hooks. Each apply checks the local `.vite-hooks/_` dispatcher,
|
|
142
|
-
its internal `.gitignore`, the portable `.vite-hooks/pre-commit` hook, and
|
|
143
|
-
`core.hooksPath`, then runs the project-local `vp config --no-agent` when they
|
|
144
|
-
need convergence. This recreates ignored dispatchers in linked worktrees.
|
|
145
|
-
Preserve other hook managers; Dev Kit
|
|
146
|
-
refuses to replace an unrelated `core.hooksPath`. Use `VITE_GIT_HOOKS=0` or
|
|
147
|
-
`HUSKY=0` to skip hook setup for an invocation.
|
|
98
|
+
|
|
99
|
+
`setup.claudeInstructions` manages `CLAUDE.md` as a relative symlink to
|
|
100
|
+
`AGENTS.md`. Disabling either task removes only unchanged managed content and
|
|
101
|
+
leaves handwritten content in place.
|
|
102
|
+
|
|
103
|
+
## Vite+ setup
|
|
148
104
|
|
|
149
105
|
The repository always owns `vite.config.ts`. Compose
|
|
150
|
-
`createRecommendedVitePlusConfig` from `@danieljvdm/dev-kit/vite-plus` there
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
pure `typecheck`
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
106
|
+
`createRecommendedVitePlusConfig` from `@danieljvdm/dev-kit/vite-plus` there,
|
|
107
|
+
adding repository/framework-generated paths (and any overridden harness target
|
|
108
|
+
paths) through `ignorePatterns`. Spread the returned top-level config before
|
|
109
|
+
local options, spread a returned nested block before overriding it, and merge
|
|
110
|
+
nested collections such as `lint.rules` so the recommended rules stay active.
|
|
111
|
+
The factory provides matching Oxlint/Oxfmt ignores, staged checks, and
|
|
112
|
+
separate `check` and pure `typecheck` tasks; standalone Oxc projects import
|
|
113
|
+
`recommendedOxlintConfig`/`recommendedOxfmtConfig` directly.
|
|
114
|
+
|
|
115
|
+
Run the Effect-patched compiler separately with `vp run typecheck`; neither
|
|
116
|
+
Oxlint's bundled `tsgolint` nor Vite+'s native lint path uses the Effect patch,
|
|
117
|
+
and Vite+ 0.2.6 does not execute the preset's JavaScript-plugin rules — use
|
|
118
|
+
standalone Oxlint when `effect/*` or
|
|
119
|
+
`stylistic/padding-line-between-statements` must be enforced. The `effect`
|
|
120
|
+
plugin's scope-sensitive rules stay consumer-scoped: enable them per path in
|
|
121
|
+
Effect-owned code, with exceptions for tests and host boundaries.
|
|
122
|
+
|
|
123
|
+
`setup.vitePlus.hooks` converges the Git-ignored `.vite-hooks/_` dispatcher by
|
|
124
|
+
running the project-local `vp config --no-agent`, recreating it in linked
|
|
125
|
+
worktrees. It requires a direct `vite-plus` dependency, refuses to replace an
|
|
126
|
+
unrelated `core.hooksPath`, and is skipped per invocation with
|
|
127
|
+
`VITE_GIT_HOOKS=0` or `HUSKY=0`.
|
|
128
|
+
|
|
129
|
+
## Scaffolds
|
|
130
|
+
|
|
131
|
+
`setup.vitePlus.workflow` and `setup.worktrunk.config` are create-only
|
|
132
|
+
scaffolds: apply writes the file only when it is missing, records nothing in
|
|
133
|
+
the lock, and never reads, updates, or removes an existing file — the
|
|
134
|
+
repository owns it from creation and edits it directly. When the shipped
|
|
135
|
+
template improves, diff the repository's file against the installed template
|
|
136
|
+
under `node_modules/@danieljvdm/dev-kit/templates/` and merge what fits.
|
|
137
|
+
|
|
138
|
+
- `setup.vitePlus.workflow` scaffolds `.github/workflows/check.yml`. It
|
|
139
|
+
requires direct Dev Kit, compatible Vite+, Effect, Effect TypeScript-Go, and
|
|
140
|
+
native TypeScript dependencies with `setup.effectTsgo.enabled`. Add
|
|
141
|
+
preparation steps or a custom typecheck command by editing the YAML.
|
|
142
|
+
- `setup.worktrunk.config` scaffolds `.config/wt.toml`: a
|
|
143
|
+
copy-ignored-then-install pre-start pipeline, a full-validation pre-merge
|
|
144
|
+
hook, and a commented per-worktree dev-server block to enable deliberately.
|
|
145
|
+
Hook commands render for the repository's runner — `vp` with a direct
|
|
146
|
+
`vite-plus` dependency, otherwise the detected package manager's install
|
|
147
|
+
command with `bun run check` from a declared root `check` script. Keep
|
|
148
|
+
user-level Worktrunk settings such as worktree-path templates out of the
|
|
149
|
+
project config; each user approves the hooks once with
|
|
150
|
+
`wt config approvals add`.
|
|
174
151
|
|
|
175
152
|
## Ownership and conflicts
|
|
176
153
|
|
|
@@ -190,17 +167,10 @@ Preserve a conflicting path and inspect it:
|
|
|
190
167
|
Retain `.dev-kit/state.json` across routine applies and branch changes so its
|
|
191
168
|
receipts can update or remove previously applied outputs safely.
|
|
192
169
|
|
|
193
|
-
##
|
|
194
|
-
|
|
195
|
-
Run `dev-kit gitignore` to add `.repos/` and `.dev-kit/` additively. Preview with
|
|
196
|
-
`dev-kit gitignore --dry-run`. Treat `.repos/<source-id>` as the reserved source
|
|
197
|
-
checkout root.
|
|
170
|
+
## Lifecycle
|
|
198
171
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
package lifecycle scripts and locked CI verification.
|
|
202
|
-
|
|
203
|
-
For one lifecycle entry point, configure:
|
|
172
|
+
Run `dev-kit gitignore` to add `.repos/` and `.dev-kit/` additively
|
|
173
|
+
(`--dry-run` to preview). For one lifecycle entry point, configure:
|
|
204
174
|
|
|
205
175
|
```jsonc
|
|
206
176
|
{
|
|
@@ -210,117 +180,40 @@ For one lifecycle entry point, configure:
|
|
|
210
180
|
}
|
|
211
181
|
```
|
|
212
182
|
|
|
213
|
-
This intentionally refreshes the committed lock and owned outputs when
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
verification as
|
|
183
|
+
This intentionally refreshes the committed lock and owned outputs when an
|
|
184
|
+
installed Dev Kit or selected package-skill version changes; review and commit
|
|
185
|
+
those changes with the dependency update. Keep `dev-kit apply --locked` as a
|
|
186
|
+
verification command, never the local lifecycle, and never run an unlocked
|
|
187
|
+
apply before locked verification. Invoke locked consumer verification as
|
|
219
188
|
`bun ./node_modules/@danieljvdm/dev-kit/bin/dev-kit.mjs apply --locked` so a
|
|
220
189
|
package script named `dev-kit` cannot shadow the executable.
|
|
221
190
|
|
|
222
|
-
## Effect
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
installed
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
CI, preserves a dirty or unrelated destination, and never deletes the checkout
|
|
238
|
-
when disabled. Use `dev-kit effect sync --dry-run` for focused diagnosis.
|
|
239
|
-
|
|
240
|
-
Override `packageName`, `path`, or `repository` only for a compatible Effect
|
|
241
|
-
distribution or a deliberate mirror.
|
|
242
|
-
|
|
243
|
-
## Effect TypeScript-Go
|
|
244
|
-
|
|
245
|
-
Enable the setup task in the same manifest:
|
|
246
|
-
|
|
247
|
-
```jsonc
|
|
248
|
-
{
|
|
249
|
-
"setup": {
|
|
250
|
-
"effectTsgo": { "enabled": true },
|
|
251
|
-
},
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
Install the exact `@effect/tsgo` and native `typescript` versions required by
|
|
256
|
-
the installed dev-kit. Point `tsconfig.json` at
|
|
257
|
-
`./node_modules/@effect/tsgo/schema.json` and configure the
|
|
258
|
-
`@effect/language-service` compiler plugin with Dev Kit's exported
|
|
259
|
-
`recommendedEffectTsgoPlugin` profile: warnings for
|
|
260
|
-
`anyUnknownInErrorContext` and `unsafeEffectTypeAssertion`; suggestions for
|
|
261
|
-
`instanceOfSchema`, `nestedEffectGenYield`, `newSchemaClass`, and
|
|
262
|
-
`preferSchemaTypeProperty`; plus a `src/**/*.ts` override that warns on
|
|
263
|
-
`nodeBuiltinImport` and suggests `preferSchemaOverJson`. Copy the exact JSON
|
|
264
|
-
profile from the README into JSON tsconfigs. In monorepos, child
|
|
191
|
+
## Effect setup tasks
|
|
192
|
+
|
|
193
|
+
`setup.effectSource` converges the ignored `.repos/effect` checkout on the
|
|
194
|
+
`effect@<version>` tag matching the installed package. It skips CI, preserves
|
|
195
|
+
a dirty or unrelated destination, and never deletes the checkout when
|
|
196
|
+
disabled. Diagnose with `dev-kit effect sync --dry-run`; override
|
|
197
|
+
`packageName`, `path`, or `repository` only for a compatible Effect
|
|
198
|
+
distribution.
|
|
199
|
+
|
|
200
|
+
`setup.effectTsgo` validates and patches the project-local native TypeScript
|
|
201
|
+
compiler. Install the exact `@effect/tsgo` and `typescript` versions required
|
|
202
|
+
by the installed dev-kit, point `tsconfig.json` at
|
|
203
|
+
`./node_modules/@effect/tsgo/schema.json`, and configure the
|
|
204
|
+
`@effect/language-service` plugin with the `recommendedEffectTsgoPlugin`
|
|
205
|
+
profile — copy the exact JSON from the package README. In monorepos, child
|
|
265
206
|
`compilerOptions.plugins` arrays replace rather than merge the root array, so
|
|
266
|
-
workspace configs must inherit the root plugin without redeclaring it and the
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
Use `dev-kit tsgo patch --dry-run` for focused diagnosis. Use `--force` only
|
|
272
|
-
after the user accepts a potentially commit-incompatible TypeScript binary.
|
|
273
|
-
|
|
274
|
-
## Oxlint and Oxfmt configurations
|
|
275
|
-
|
|
276
|
-
Use Dev Kit's composable factory in Vite+ projects:
|
|
277
|
-
|
|
278
|
-
```ts
|
|
279
|
-
import { createRecommendedVitePlusConfig } from "@danieljvdm/dev-kit/vite-plus";
|
|
280
|
-
import { defineConfig } from "vite-plus";
|
|
281
|
-
|
|
282
|
-
export default defineConfig(
|
|
283
|
-
createRecommendedVitePlusConfig({
|
|
284
|
-
ignorePatterns: ["src/routeTree.gen.ts"],
|
|
285
|
-
}),
|
|
286
|
-
);
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
The factory composes the canonical Oxlint/Oxfmt objects, excludes tracked skill
|
|
290
|
-
copies plus symlinked harness targets from both tools, and accepts additional
|
|
291
|
-
project-owned ignores. Standalone `oxlint.config.ts` uses
|
|
292
|
-
`extends: [recommendedOxlintConfig]`; standalone `oxfmt.config.ts` spreads
|
|
293
|
-
`recommendedOxfmtConfig`. The shared lint preset enables `typeAware` for
|
|
294
|
-
semantic lint rules but leaves `typeCheck` disabled. Effect TypeScript-Go
|
|
295
|
-
projects must run the patched native compiler separately with
|
|
296
|
-
`vp run typecheck` after `vp fmt --check`, `vp lint`, and `vp test`; Oxlint's
|
|
297
|
-
bundled `tsgolint` does not use the Effect patch.
|
|
298
|
-
|
|
299
|
-
The Oxlint preset enables the fixable
|
|
300
|
-
`stylistic/padding-line-between-statements` rule. It keeps adjacent variable
|
|
301
|
-
declarations grouped, requires a blank line before the next logical statement,
|
|
302
|
-
and separates every `return` statement from the preceding statement.
|
|
303
|
-
|
|
304
|
-
Vite+ 0.2.6 forwards the preset's JavaScript-plugin declarations but its native
|
|
305
|
-
Oxlint path does not register or execute their rules. Treat native rules and
|
|
306
|
-
Oxfmt as active through `vp`, and use standalone Oxlint when the `effect/*` or
|
|
307
|
-
`stylistic/padding-line-between-statements` rules must be enforced. Re-enable a
|
|
308
|
-
Vite+ execution assertion when a supported release adds JS-plugin execution.
|
|
309
|
-
|
|
310
|
-
The Oxlint preset registers Dev Kit's shared Effect plugin as `effect`, but
|
|
311
|
-
does not enable its scope-sensitive rules globally. Effect projects should
|
|
312
|
-
enable rules such as `effect/no-effect-run`, `effect/no-unsafe-promise`, and
|
|
313
|
-
`effect/no-untyped-throw` only in Effect-owned code, with explicit exceptions
|
|
314
|
-
for tests and host boundaries. The stricter `effect/no-async-workflow`,
|
|
315
|
-
`effect/no-promise-atom-mode`, and `effect/no-sync-boundary-decode` rules also
|
|
316
|
-
need consumer-owned scopes. Keep repository-specific paths and platform rules
|
|
317
|
-
in the consuming project.
|
|
207
|
+
workspace configs must inherit the root plugin without redeclaring it, and the
|
|
208
|
+
`src/**/*.ts` override must be relative to the config that contains it.
|
|
209
|
+
Diagnose with `dev-kit tsgo patch --dry-run`; use `--force` only after the
|
|
210
|
+
user accepts a potentially commit-incompatible TypeScript binary.
|
|
318
211
|
|
|
319
212
|
## Current boundary
|
|
320
213
|
|
|
321
214
|
Manage skill outputs, the `setup.agentInstructions` marked sections, the
|
|
322
215
|
`setup.claudeInstructions` link, the `setup.vitePlus.hooks` dispatcher, the
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
`
|
|
326
|
-
|
|
216
|
+
`setup.effectSource` checkout, and the explicit `setup.effectTsgo` task. The
|
|
217
|
+
`setup.vitePlus.workflow` and `setup.worktrunk.config` scaffolds belong to the
|
|
218
|
+
repository once created. `vite.config.ts`, dependency, and `tsconfig.json`
|
|
219
|
+
contributions remain deliberate user-owned edits.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: effect-atom-state
|
|
3
|
+
description: Manage client-side state and server data in React with Effect Atom, which fills the role TanStack/React Query, SWR, Zustand, Redux, or Jotai play in other stacks — use this skill instead of reaching for those libraries or hand-rolled useEffect fetching whenever a component needs shared state, data fetching, caching, mutations, or optimistic updates. Also use when reading or dispatching atoms (useAtomValue, useAtomSet, useAtom), refactoring promise chains or useState-held server state into atom workflows, choosing reactivity keys and invalidation, deriving AtomHttpApi or HttpApiClient clients from a shared contract, deciding where the Effect→Promise boundary sits, or wiring RegistryProvider and SSR with TanStack Start.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Effect Atom State
|
|
7
|
+
|
|
8
|
+
Effect Atom is the client-state and server-data layer in an Effect repository:
|
|
9
|
+
the role other stacks give TanStack Query, SWR, Zustand, Redux, or Jotai.
|
|
10
|
+
Every need that would reach for one of those libraries — or for hand-rolled
|
|
11
|
+
`useEffect` fetching — is atom work; never introduce a second state or query
|
|
12
|
+
library beside it.
|
|
13
|
+
|
|
14
|
+
Business logic stays in Effect for as long as possible. Components read
|
|
15
|
+
`AsyncResult` values and dispatch actions; workflows, optimistic updates, and
|
|
16
|
+
cache invalidation live in atoms, not in promise chains at the React boundary.
|
|
17
|
+
|
|
18
|
+
Effect Atom APIs are version-sensitive. Read the target repository's manifests
|
|
19
|
+
and lockfile, inspect its existing imports, and confirm exact signatures from
|
|
20
|
+
the installed `effect` and `@effect/atom-react` declarations before editing.
|
|
21
|
+
In current Effect v4 betas the atom modules live in
|
|
22
|
+
`effect/unstable/reactivity` and the React hooks in `@effect/atom-react`.
|
|
23
|
+
|
|
24
|
+
## Build the client state graph
|
|
25
|
+
|
|
26
|
+
1. Inventory the existing `RegistryProvider`, runtime factories,
|
|
27
|
+
`AtomHttpApi.Service` clients, query atoms and families, mutation and
|
|
28
|
+
workflow atoms, reactivity-key constructors, state atoms, and promise-mode
|
|
29
|
+
dispatch sites. Finish when every consumer of the affected state is
|
|
30
|
+
identified.
|
|
31
|
+
2. Read [effect-atom-client.md](references/effect-atom-client.md), then derive
|
|
32
|
+
one `AtomHttpApi.Service` per contract, stable query atoms or families,
|
|
33
|
+
mutation atoms, and one reactivity-key vocabulary. For non-React Effect
|
|
34
|
+
code, use the direct `HttpApiClient` branch. Finish when consumers call the
|
|
35
|
+
shared contract rather than redefining wire types or using ad hoc `fetch`
|
|
36
|
+
for declared endpoints.
|
|
37
|
+
3. Read [effect-atom-workflows.md](references/effect-atom-workflows.md), then
|
|
38
|
+
express every multi-step action — mutate then invalidate, optimistic echo
|
|
39
|
+
then rollback — as an `Atom.fn` effect composing other atoms through the fn
|
|
40
|
+
context. Finish when no component or route chains `.then`/`.catch` on a
|
|
41
|
+
dispatch and no `useState` holds state a workflow atom must own.
|
|
42
|
+
4. Read [effect-atom-lifecycle.md](references/effect-atom-lifecycle.md) when
|
|
43
|
+
changing registry scope, atom identity, retention, freshness, polling,
|
|
44
|
+
cancellation, or aggregate stability.
|
|
45
|
+
5. Read [effect-atom-testing.md](references/effect-atom-testing.md), then give
|
|
46
|
+
changed atom behavior deterministic coverage below React first, with a
|
|
47
|
+
deterministic HTTP layer so request encoding, invalidation, and lifecycle
|
|
48
|
+
remain observable. Run the repository's format, lint, typecheck, and test
|
|
49
|
+
commands. Finish when changed queries, mutations, invalidation, and
|
|
50
|
+
workflow atoms have deterministic tests and every repository check passes.
|
|
51
|
+
|
|
52
|
+
## Optional branches
|
|
53
|
+
|
|
54
|
+
- Read [tanstack-start.md](references/tanstack-start.md) when the client is
|
|
55
|
+
TanStack Start, SSR, hydration, `ClientOnly`, loaders, server functions, or a
|
|
56
|
+
proxied separate API.
|
|
57
|
+
- Use the `$build-effect-apis` skill when the change reaches the contract or
|
|
58
|
+
server: shared `HttpApiEndpoint`/`HttpApiGroup` definitions, handlers,
|
|
59
|
+
middleware, or runtime assembly.
|
|
60
|
+
|
|
61
|
+
## Keep the Promise boundary logic-free
|
|
62
|
+
|
|
63
|
+
The Effect→Promise boundary sits at the outermost edge and carries no logic.
|
|
64
|
+
|
|
65
|
+
- Return a promise-mode dispatch (`useAtomSet(action, { mode: "promise" })`)
|
|
66
|
+
bare to a leaf component whose contract is promise-shaped — a pending
|
|
67
|
+
button, a composer that owns its in-flight state. A `.then` or `.catch`
|
|
68
|
+
chain in a component or route is a violation: move that logic into the
|
|
69
|
+
action's Effect.
|
|
70
|
+
- Express multi-step workflows as `Atom.fn` effects composing other atoms
|
|
71
|
+
through the fn context: `get.setResult` awaits another fn atom, `get.set`
|
|
72
|
+
writes state atoms. Reads through the fn context callable are untracked, so
|
|
73
|
+
mutating a state atom from inside the effect cannot re-trigger the workflow.
|
|
74
|
+
- Declare cross-query invalidation as reactivity keys on the mutation; never
|
|
75
|
+
chain a manual refresh at a call site. When several `AtomHttpApi` services
|
|
76
|
+
share one Atom runtime, one `Reactivity` instance spans them, so a mutation
|
|
77
|
+
on one client invalidates another client's query keys.
|
|
78
|
+
- Keep optimistic UI state in `Atom.family` state atoms keyed by the entity,
|
|
79
|
+
not `useState`, so the workflow atom that writes it owns its lifecycle.
|
|
80
|
+
- Genuine view state — controlled inputs, open/closed toggles, reconciling
|
|
81
|
+
optimistic rows against rendered props — stays in React; do not force it
|
|
82
|
+
into Effect.
|
|
83
|
+
|
|
84
|
+
A repository may reinforce the boundary with a lint warning on `then` scoped
|
|
85
|
+
to component and route modules, with a documented local suppression for a
|
|
86
|
+
genuinely promise-shaped contract, but the boundary reasoning remains the
|
|
87
|
+
source of truth.
|
|
88
|
+
|
|
89
|
+
## Boundary rules
|
|
90
|
+
|
|
91
|
+
- Let client data modules own API services, query identity, cache policy,
|
|
92
|
+
invalidation keys, mutation atoms, and workflow atoms.
|
|
93
|
+
- Let workflow atoms own orchestration, optimistic echo, rollback, and
|
|
94
|
+
cross-query invalidation.
|
|
95
|
+
- Let UI action owners own navigation, toasts, form reset, and presentation
|
|
96
|
+
derived from `AsyncResult` state.
|
|
97
|
+
- Let React own view state that no atom needs to write.
|