@danieljvdm/dev-kit 0.13.0 → 0.15.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 +84 -90
- 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 +22 -0
- package/skills/build-effect-apis/references/verification.md +16 -1
- package/skills/build-effect-clis/SKILL.md +48 -17
- package/skills/build-effect-clis/agents/openai.yaml +3 -3
- package/skills/build-effect-clis/references/entrypoints-and-testing.md +5 -0
- package/skills/build-effect-clis/references/processes-and-platform.md +3 -2
- package/skills/dev-kit/SKILL.md +115 -222
- package/skills/open-pull-request/SKILL.md +122 -0
- package/skills/open-pull-request/agents/openai.yaml +4 -0
- package/src/index.ts +6 -6
- package/src/manifest.ts +28 -29
- package/src/path-digest.ts +0 -13
- package/src/project-package.ts +51 -0
- package/src/project-state.ts +3 -0
- package/src/scaffold.ts +79 -0
- package/src/sync.ts +64 -171
- package/src/vite-plus-workflow.ts +82 -0
- 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/README.md
CHANGED
|
@@ -179,6 +179,7 @@ tool versions. A project-local process lock also prevents concurrent applies.
|
|
|
179
179
|
"include": [
|
|
180
180
|
"dev-kit",
|
|
181
181
|
"effect",
|
|
182
|
+
"open-pull-request",
|
|
182
183
|
"workers-best-practices",
|
|
183
184
|
"wrangler",
|
|
184
185
|
"serve-sim",
|
|
@@ -198,18 +199,14 @@ tool versions. A project-local process lock also prevents concurrent applies.
|
|
|
198
199
|
```
|
|
199
200
|
|
|
200
201
|
- `dev-kit` installs guidance for operating the toolkit itself.
|
|
201
|
-
- `effect`
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
`wrangler`, selected after scanning the project for relevant technologies.
|
|
208
|
-
- `serve-sim` selects the approved Evan Bacon simulator skill directly.
|
|
202
|
+
- `effect` is a built-in family: the `effect-ts` bootstrap,
|
|
203
|
+
`effect-architecture-audit`, `build-effect-apis`, and `build-effect-clis`.
|
|
204
|
+
- External Git skills (`workers-best-practices`, `serve-sim`, …) are selected
|
|
205
|
+
individually after scanning the project for relevant technologies. An
|
|
206
|
+
approved source ID selects every skill from that source; use it only when
|
|
207
|
+
the scan confirms that every member applies.
|
|
209
208
|
- `@tanstack/ai#ai-core` explicitly selects a skill discovered in that direct
|
|
210
209
|
project dependency; discovery alone never selects it.
|
|
211
|
-
- An approved source ID is broad shorthand that selects every skill from that
|
|
212
|
-
source. Use it only when the scan confirms that every member applies.
|
|
213
210
|
|
|
214
211
|
Dev Kit reserves `.repos/<source-id>` for project-local source checkouts. Run
|
|
215
212
|
`dev-kit gitignore` to add `.repos/` and `.dev-kit/` to the project ignore file.
|
|
@@ -235,18 +232,17 @@ bridge in the manifest:
|
|
|
235
232
|
`AGENTS.md`, preserving handwritten project guidance around them. The Dev Kit
|
|
236
233
|
section contains a short description and a pointer to the installed `dev-kit`
|
|
237
234
|
skill. When the root `package.json` declares `vite-plus` directly, Dev Kit
|
|
238
|
-
renders its own repository-specific Vite+ guidance
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
owned update. Ambiguous or malformed managed markers fail closed.
|
|
235
|
+
renders its own repository-specific Vite+ guidance — toolchain overview, help
|
|
236
|
+
and documentation entry points, `vp env doctor` troubleshooting — rather than
|
|
237
|
+
importing Vite+'s generic `AGENTS.md`, which can contradict the repository's
|
|
238
|
+
exact commands; transitive installations do not opt a project in. Ambiguous or
|
|
239
|
+
malformed managed markers fail closed.
|
|
244
240
|
|
|
245
241
|
The Dev Kit section also renders an opinionated project command policy. A
|
|
246
242
|
direct Vite+ dependency makes `vp` the only supported front door: built-in
|
|
247
243
|
format, lint, and test commands use `vp`, while repository tasks and package
|
|
248
|
-
scripts use `vp run`. When
|
|
249
|
-
full validation and typecheck commands are `vp run check` and
|
|
244
|
+
scripts use `vp run`. When the manifest enables the Vite+ workflow scaffold,
|
|
245
|
+
the canonical full validation and typecheck commands are `vp run check` and
|
|
250
246
|
`vp run typecheck`; `vp check` alone is only the Vite+ static-check command.
|
|
251
247
|
Without Vite+, Bun is the required package-script runner and Dev Kit lists only
|
|
252
248
|
quality scripts the root package actually declares. The package manager named
|
|
@@ -287,7 +283,7 @@ worktree converges its own copy during install while the project-owned
|
|
|
287
283
|
## Vite+ quality setup
|
|
288
284
|
|
|
289
285
|
The repository always owns `vite.config.ts`. Compose Dev Kit's quality defaults
|
|
290
|
-
from that project-owned config, then opt into the
|
|
286
|
+
from that project-owned config, then opt into the scaffolded GitHub Actions
|
|
291
287
|
workflow independently:
|
|
292
288
|
|
|
293
289
|
```ts
|
|
@@ -317,13 +313,6 @@ Project and framework-generated paths belong in `ignorePatterns` as shown;
|
|
|
317
313
|
custom harness target paths belong there too. Dev Kit does not grow a global
|
|
318
314
|
framework ignore list.
|
|
319
315
|
|
|
320
|
-
Vite+ 0.2.6 forwards JavaScript-plugin declarations into its effective lint
|
|
321
|
-
config but its bundled native Oxlint path does not register or execute those
|
|
322
|
-
rules. Native Oxlint rules and Oxfmt settings remain active; run standalone
|
|
323
|
-
Oxlint when enforcement of Dev Kit's `effect/*` or
|
|
324
|
-
`stylistic/padding-line-between-statements` rules is required. This limitation
|
|
325
|
-
can be removed once a supported Vite+ release executes configured JS plugins.
|
|
326
|
-
|
|
327
316
|
```jsonc
|
|
328
317
|
{
|
|
329
318
|
"include": ["dev-kit", "effect"],
|
|
@@ -331,19 +320,24 @@ can be removed once a supported Vite+ release executes configured JS plugins.
|
|
|
331
320
|
"effectTsgo": { "enabled": true },
|
|
332
321
|
"vitePlus": {
|
|
333
322
|
"hooks": { "enabled": true },
|
|
334
|
-
"
|
|
335
|
-
"workflow": { "enabled": true },
|
|
336
|
-
},
|
|
323
|
+
"workflow": { "enabled": true },
|
|
337
324
|
},
|
|
338
325
|
},
|
|
339
326
|
}
|
|
340
327
|
```
|
|
341
328
|
|
|
342
|
-
`
|
|
343
|
-
rewrites, adopts, or removes `vite.config.ts`.
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
329
|
+
`setup.vitePlus.workflow` scaffolds `.github/workflows/check.yml` and never
|
|
330
|
+
reads, rewrites, adopts, or removes `vite.config.ts`. Scaffolds are
|
|
331
|
+
create-only: the file is written only when missing, never recorded in
|
|
332
|
+
`dev-kit.lock.json`, and never touched again — the repository owns it from
|
|
333
|
+
creation, and disabling the task leaves it in place. Edit the YAML directly
|
|
334
|
+
for repository-specific preparation steps or a custom typecheck command; when
|
|
335
|
+
the shipped template improves, compare against the installed copy under
|
|
336
|
+
`node_modules/@danieljvdm/dev-kit/templates/` and merge what fits.
|
|
337
|
+
Scaffolding requires direct `@danieljvdm/dev-kit`, `vite-plus`, `effect`,
|
|
338
|
+
`@effect/tsgo`, and native TypeScript dependencies with
|
|
339
|
+
`setup.effectTsgo.enabled`, and the installed Vite+ must satisfy Dev Kit's
|
|
340
|
+
peer range.
|
|
347
341
|
|
|
348
342
|
Workspaces select bounded, dependency-ordered typechecking in their config:
|
|
349
343
|
|
|
@@ -359,44 +353,51 @@ export default defineConfig(
|
|
|
359
353
|
);
|
|
360
354
|
```
|
|
361
355
|
|
|
362
|
-
Each listed package must expose a pure `typecheck` script.
|
|
363
|
-
|
|
356
|
+
Each listed package must expose a pure `typecheck` script.
|
|
357
|
+
|
|
358
|
+
The scaffolded workflow performs one frozen, script-suppressed install, runs
|
|
359
|
+
`dev-kit apply --locked`, and only then runs formatting, linting, tests, and
|
|
360
|
+
`vp run typecheck`. See the primary
|
|
361
|
+
[`setup-vp` versioning guidance](https://github.com/voidzero-dev/setup-vp#versioning),
|
|
362
|
+
[Vite+ install guide](https://viteplus.dev/guide/install), and
|
|
363
|
+
[Vite Task run guide](https://viteplus.dev/guide/run) when maintaining the
|
|
364
|
+
templates.
|
|
365
|
+
|
|
366
|
+
## Worktrunk project config
|
|
367
|
+
|
|
368
|
+
Enable a scaffolded default [Worktrunk](https://worktrunk.dev) project config
|
|
369
|
+
in the manifest:
|
|
364
370
|
|
|
365
371
|
```jsonc
|
|
366
372
|
{
|
|
373
|
+
"include": ["dev-kit"],
|
|
367
374
|
"setup": {
|
|
368
|
-
"
|
|
369
|
-
"vitePlus": {
|
|
370
|
-
"quality": {
|
|
371
|
-
"workflow": {
|
|
372
|
-
"enabled": true,
|
|
373
|
-
"beforeChecks": [
|
|
374
|
-
{
|
|
375
|
-
"name": "Install media tools",
|
|
376
|
-
"run": ["sudo apt-get update", "sudo apt-get install --yes ffmpeg"],
|
|
377
|
-
},
|
|
378
|
-
],
|
|
379
|
-
"typecheck": [
|
|
380
|
-
"vp run -F './apps/*' -F './packages/*' check",
|
|
381
|
-
"vp exec tsc --noEmit -p scripts/tsconfig.json",
|
|
382
|
-
],
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
},
|
|
375
|
+
"worktrunk": { "config": { "enabled": true } },
|
|
386
376
|
},
|
|
387
377
|
}
|
|
388
378
|
```
|
|
389
379
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
380
|
+
`setup.worktrunk.config` scaffolds `.config/wt.toml` with the portable hooks an
|
|
381
|
+
app repository wants in every worktree: a `pre-start` pipeline that copies
|
|
382
|
+
gitignored files matched by `.worktreeinclude` (a no-op without that file) and
|
|
383
|
+
then installs dependencies, plus a `pre-merge` full-validation hook. Hook
|
|
384
|
+
commands render for the repository's command runner: a direct `vite-plus`
|
|
385
|
+
dependency selects `vp install` and `vp run check`; otherwise Dev Kit requires
|
|
386
|
+
a declared root `check` package script, runs it through `bun run check`, and
|
|
387
|
+
takes the install command from the detected package manager. Repositories with
|
|
388
|
+
neither fail the plan instead of shipping a broken hook.
|
|
389
|
+
|
|
390
|
+
The config follows the same create-only scaffold semantics as the check
|
|
391
|
+
workflow above: created once, never locked or touched again, owned by the
|
|
392
|
+
repository. Edit hooks freely after creation.
|
|
393
|
+
|
|
394
|
+
The config intentionally carries no worktree-path template or other user
|
|
395
|
+
preferences—those belong in each user's `~/.config/worktrunk/config.toml`. A
|
|
396
|
+
commented `post-start` block shows how to run a per-worktree dev server on a
|
|
397
|
+
stable branch-derived port (`{{ branch | hash_port }}`) under `wt step tether`;
|
|
398
|
+
point it at the repository's dev entrypoint and uncomment to opt in. Worktrunk
|
|
399
|
+
never runs project hooks until each user approves them with
|
|
400
|
+
`wt config approvals add`.
|
|
400
401
|
|
|
401
402
|
## Effect source checkout
|
|
402
403
|
|
|
@@ -518,31 +519,20 @@ bun x dev-kit add @tanstack/ai#ai-core
|
|
|
518
519
|
That writes `@tanstack/ai#ai-core` to `dev-kit.jsonc` and, unless
|
|
519
520
|
`--no-apply` is passed, installs it through the normal ownership-safe sync
|
|
520
521
|
path. The qualifier prevents ambiguity when two dependencies publish the same
|
|
521
|
-
skill name, and the installed output carries it
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
`devDependencies`, `optionalDependencies`, or `peerDependencies` are
|
|
536
|
-
scanned;
|
|
537
|
-
- package code is never imported or executed;
|
|
538
|
-
- npm-style and pnpm/workspace symlinks under `node_modules` are supported;
|
|
539
|
-
- Yarn Plug'n'Play and transitive dependency traversal are not scanned; and
|
|
540
|
-
- immediate `skills/<name>/SKILL.md` roots are listed. Nested topic skills and
|
|
541
|
-
references remain part of that root and are copied with it.
|
|
542
|
-
|
|
543
|
-
The last rule adapts Intent's routed, nested skill trees to the immediate folder
|
|
544
|
-
and frontmatter-name invariants expected by Agent Skills targets. Dev Kit does
|
|
545
|
-
not rewrite nested names or ask Intent to manage agent configuration.
|
|
522
|
+
skill name, and the installed output carries it: the copied directory flattens
|
|
523
|
+
the package name and appends the skill name (`@tanstack/ai#ai-core` →
|
|
524
|
+
`tanstack-ai-ai-core`), and the copied `SKILL.md` frontmatter `name:` is
|
|
525
|
+
rewritten to match because harnesses identify a skill by its directory name.
|
|
526
|
+
Symlink-mode targets link straight into `node_modules`, so only the link
|
|
527
|
+
carries the qualified name. Two selections that would write the same
|
|
528
|
+
destination are rejected before any output changes.
|
|
529
|
+
|
|
530
|
+
The compatibility boundary is intentionally small and deterministic: only the
|
|
531
|
+
root project's direct dependencies are scanned, package code is never imported
|
|
532
|
+
or executed, npm-style and pnpm/workspace symlinks are supported (Yarn
|
|
533
|
+
Plug'n'Play and transitive traversal are not), and only immediate
|
|
534
|
+
`skills/<name>/SKILL.md` roots are listed — nested topic skills and references
|
|
535
|
+
are copied as part of their root.
|
|
546
536
|
|
|
547
537
|
The project `dev-kit.lock.json` records the selected package name, installed
|
|
548
538
|
version, original bare skill name, and the `node_modules` content digest.
|
|
@@ -648,7 +638,11 @@ export default defineConfig({
|
|
|
648
638
|
The Oxlint preset enables `stylistic/padding-line-between-statements`: adjacent
|
|
649
639
|
variable declarations remain grouped, while the next logical statement and
|
|
650
640
|
all `return` statements require a separating blank line. The rule is fixable,
|
|
651
|
-
so `vp lint --fix` repairs missing spacing automatically.
|
|
641
|
+
so `vp lint --fix` repairs missing spacing automatically. Vite+ 0.2.6 forwards
|
|
642
|
+
the preset's JavaScript-plugin declarations but its native Oxlint path does not
|
|
643
|
+
execute their rules — run standalone Oxlint when `effect/*` or the padding rule
|
|
644
|
+
must be enforced, until a supported Vite+ release executes configured JS
|
|
645
|
+
plugins.
|
|
652
646
|
|
|
653
647
|
The preset also registers the shared `effect` JavaScript plugin. Effect
|
|
654
648
|
projects opt into its rules in path-specific overrides, for example
|
package/dev-kit.example.jsonc
CHANGED
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
"effectTsgo": { "enabled": true },
|
|
9
9
|
"vitePlus": {
|
|
10
10
|
"hooks": { "enabled": true },
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
"workflow": { "enabled": true },
|
|
12
|
+
},
|
|
13
|
+
"worktrunk": {
|
|
14
|
+
"config": { "enabled": true },
|
|
14
15
|
},
|
|
15
16
|
},
|
|
16
17
|
"targets": {
|
package/package.json
CHANGED
|
@@ -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
|
-
"
|
|
148
|
-
"$ref": "#/$defs/
|
|
150
|
+
"workflow": {
|
|
151
|
+
"$ref": "#/$defs/vitePlusWorkflowSetup"
|
|
149
152
|
}
|
|
150
153
|
}
|
|
151
154
|
},
|
|
@@ -160,61 +163,35 @@
|
|
|
160
163
|
}
|
|
161
164
|
}
|
|
162
165
|
},
|
|
163
|
-
"
|
|
164
|
-
"description": "
|
|
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
|
-
"
|
|
169
|
-
"
|
|
171
|
+
"enabled": {
|
|
172
|
+
"type": "boolean",
|
|
173
|
+
"default": false
|
|
170
174
|
}
|
|
171
175
|
}
|
|
172
176
|
},
|
|
173
|
-
"
|
|
174
|
-
"description": "Manage
|
|
177
|
+
"worktrunkSetup": {
|
|
178
|
+
"description": "Manage project-local Worktrunk setup tasks.",
|
|
175
179
|
"type": "object",
|
|
176
180
|
"additionalProperties": false,
|
|
177
181
|
"properties": {
|
|
178
|
-
"
|
|
179
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
208
|
-
"type": "
|
|
209
|
-
"
|
|
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
|
},
|
|
@@ -64,6 +64,28 @@ from another version.
|
|
|
64
64
|
runs on Cloudflare Workers or uses `effect-cf`, bindings, Durable Objects,
|
|
65
65
|
Queues, WebSockets, streaming, or raw byte routes.
|
|
66
66
|
|
|
67
|
+
## Choose typed Schema codecs by default
|
|
68
|
+
|
|
69
|
+
Match the codec to the static type at the call site. When decoding a value that
|
|
70
|
+
is already typed as the schema's `Encoded` type, use `Schema.decodeEffect` or
|
|
71
|
+
the typed `Schema.decodeSync`, `Schema.decodeExit`, `Schema.decodeOption`,
|
|
72
|
+
`Schema.decodeResult`, or `Schema.decodePromise` variant. When encoding a value
|
|
73
|
+
that is already typed as the schema's `Type`, use `Schema.encodeEffect` or the
|
|
74
|
+
corresponding typed `Schema.encodeSync`, `Schema.encodeExit`,
|
|
75
|
+
`Schema.encodeOption`, `Schema.encodeResult`, or `Schema.encodePromise` variant.
|
|
76
|
+
|
|
77
|
+
Reserve `Schema.decodeUnknown*` and `Schema.encodeUnknown*` for genuinely
|
|
78
|
+
untyped boundaries: values from `JSON.parse`, `Response.json`, external
|
|
79
|
+
messages, or persistence APIs whose declared result is actually `unknown`.
|
|
80
|
+
Never choose an unknown codec to bypass a `Schema.Class` or other static type
|
|
81
|
+
mismatch. Map the source value or construct the correct schema `Type` first,
|
|
82
|
+
then use the typed encoder; similarly, establish the correct `Encoded` value
|
|
83
|
+
before using a typed decoder.
|
|
84
|
+
|
|
85
|
+
This rule is toolchain-neutral. A repository may reinforce it with a lint
|
|
86
|
+
warning and a documented local suppression for a justified untyped boundary,
|
|
87
|
+
but the boundary and type reasoning remain the source of truth.
|
|
88
|
+
|
|
67
89
|
## Boundary rules
|
|
68
90
|
|
|
69
91
|
- Let schemas own wire validation, encoding, status metadata, and branded IDs.
|
|
@@ -11,6 +11,20 @@ test integration and command authority.
|
|
|
11
11
|
- Assert each expected error carries the intended HTTP status and body encoding.
|
|
12
12
|
- Compare or smoke-test generated OpenAPI when the public contract changes.
|
|
13
13
|
|
|
14
|
+
## Unknown codec audit
|
|
15
|
+
|
|
16
|
+
Inventory every `Schema.decodeUnknown*` and `Schema.encodeUnknown*` call in the
|
|
17
|
+
changed scope. Record a concrete untyped-boundary justification for each one,
|
|
18
|
+
such as `JSON.parse`, `Response.json`, an external message, or a persistence API
|
|
19
|
+
whose declared result is actually `unknown`. Replace any call whose input is
|
|
20
|
+
already the schema's `Encoded` or `Type` with the corresponding typed `Effect`,
|
|
21
|
+
`Sync`, `Exit`, `Option`, `Result`, or `Promise` codec.
|
|
22
|
+
|
|
23
|
+
An unknown codec is not a valid workaround for a `Schema.Class` or other static
|
|
24
|
+
type mismatch: map or construct the correct typed value instead. If the
|
|
25
|
+
repository enforces this policy with a lint warning, keep any necessary local
|
|
26
|
+
suppression documented with the same concrete boundary justification.
|
|
27
|
+
|
|
14
28
|
## Server tests
|
|
15
29
|
|
|
16
30
|
- Build every changed group and fail the test if an endpoint handler is missing.
|
|
@@ -47,4 +61,5 @@ Account for every changed endpoint across these columns:
|
|
|
47
61
|
| Params, query, headers, payload, success, errors | Scope, provided services, errors | Identifier, invariants, workflow | Typed call shape, identity, cache/invalidation | Round-trip and boundary behavior |
|
|
48
62
|
|
|
49
63
|
Completion means every changed endpoint has an entry in every applicable
|
|
50
|
-
column
|
|
64
|
+
column, every unknown codec call has a concrete boundary justification, and the
|
|
65
|
+
repository's formatter, linter, typechecker, and tests pass.
|
|
@@ -1,30 +1,61 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: build-effect-clis
|
|
3
|
-
description:
|
|
3
|
+
description: Write and maintain every executable script and command-line application in an Effect repository as an Effect program. Use when creating or changing any script, one-off automation, CI check, deploy/release/build glue, package-script entrypoint, CLI command, arguments, flags, prompts, child process, filesystem or environment workflow, Node/Bun entrypoint, or integration test—including extending an existing plain-TypeScript script.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Build Effect CLIs
|
|
6
|
+
# Build Effect Scripts and CLIs
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
## Effect-first scope
|
|
9
|
+
|
|
10
|
+
Every executable script and CLI in an Effect repository is an Effect program.
|
|
11
|
+
This includes one-off scripts, CI checks, deploy/release/build glue, files under
|
|
12
|
+
`scripts/`, package-script targets, migrations, and application entrypoints—not
|
|
13
|
+
only polished command-line tools.
|
|
14
|
+
|
|
15
|
+
Apply this rule when modifying code as well as when creating it. When a task
|
|
16
|
+
touches an existing plain-TypeScript script, convert the whole script to Effect
|
|
17
|
+
in the same change; matching the surrounding file's style or minimizing the
|
|
18
|
+
diff is not a valid exception. Prefer the repository's established Effect
|
|
19
|
+
patterns, including those in sibling scripts, over legacy patterns in the file
|
|
20
|
+
being converted.
|
|
21
|
+
|
|
22
|
+
Leave a script outside Effect only for a good, concrete technical or user
|
|
23
|
+
constraint that makes Effect unsuitable. Explicitly state that reason before
|
|
24
|
+
proceeding and in the final handoff, and keep the exception as narrow as
|
|
25
|
+
possible. Convenience, one-off status, and existing plain-TypeScript style are
|
|
26
|
+
not sufficient reasons.
|
|
27
|
+
|
|
28
|
+
Use Effect platform services for filesystem, path, environment, terminal, and
|
|
29
|
+
child-process work. Raw `node:*` or Bun runtime imports, `process.env`, `fs`,
|
|
30
|
+
`path`, `child_process`, and synchronous helpers such as `execFileSync` do not
|
|
31
|
+
belong in script workflows. If the installed Effect platform has no required
|
|
32
|
+
capability, isolate the runtime call in an explicit boundary adapter whose API
|
|
33
|
+
returns an Effect with typed errors, and document why that adapter is required.
|
|
34
|
+
|
|
35
|
+
Treat each executable as an Effect application. For a CLI, the `Command` tree
|
|
36
|
+
owns the user-facing contract, handlers adapt decoded input into application
|
|
37
|
+
workflows, services own capabilities, and the executable entrypoint supplies
|
|
38
|
+
platform Layers and runs the program. A fixed automation script with no public
|
|
39
|
+
arguments may export an Effect workflow directly instead of inventing a
|
|
40
|
+
`Command` tree. Do not introduce a separate CLI framework for command work.
|
|
12
41
|
|
|
13
42
|
Effect CLI and process APIs are version-sensitive. Read the target repository's
|
|
14
43
|
`node_modules/effect/AGENTS.md` completely, follow its CLI and child-process
|
|
15
44
|
references, and confirm exact signatures from the installed declarations before
|
|
16
45
|
editing.
|
|
17
46
|
|
|
18
|
-
## Build the
|
|
47
|
+
## Build the executable boundary
|
|
19
48
|
|
|
20
49
|
1. Inventory the existing executable entrypoints, package scripts, command
|
|
21
50
|
tree, shared flags, prompts, application services, platform Layers, output
|
|
22
51
|
modes, and subprocess helpers. Finish when every way to invoke and test the
|
|
23
|
-
CLI is known
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
52
|
+
affected scripts or CLI is known, including sibling Effect scripts whose
|
|
53
|
+
patterns should replace legacy plain-TypeScript style.
|
|
54
|
+
2. When the executable accepts public arguments or flags, read
|
|
55
|
+
[command-design.md](references/command-design.md). Define arguments and flags
|
|
56
|
+
with `Argument` and `Flag`, compose commands with `Command`, and give every
|
|
57
|
+
public input useful help. Use `Effect.fn` handlers and yield the root command
|
|
58
|
+
when a subcommand needs shared parent input.
|
|
28
59
|
3. Keep handlers thin. Decode user and file input at the boundary, enforce
|
|
29
60
|
cross-input invariants, then call an application service. Keep persistence,
|
|
30
61
|
network calls, orchestration, retries, and transactions in services.
|
|
@@ -32,15 +63,15 @@ editing.
|
|
|
32
63
|
platform failures into application-owned errors near the adapter that knows
|
|
33
64
|
what the operation means. Let defects remain defects.
|
|
34
65
|
5. Read [entrypoints-and-testing.md](references/entrypoints-and-testing.md).
|
|
35
|
-
Export the command tree without running it, wire
|
|
36
|
-
|
|
37
|
-
|
|
66
|
+
Export the command tree or fixed script workflow without running it, wire
|
|
67
|
+
one Node or Bun entrypoint, and verify the applicable success, expected
|
|
68
|
+
failure, help, parsing, JSON, dry-run, and confirmation paths.
|
|
38
69
|
|
|
39
70
|
## Optional branches
|
|
40
71
|
|
|
41
72
|
- Read [processes-and-platform.md](references/processes-and-platform.md) when a
|
|
42
|
-
command reads files, inspects the environment, starts child
|
|
43
|
-
streams their output, or differs between Node and Bun.
|
|
73
|
+
script or command reads files, inspects the environment, starts child
|
|
74
|
+
processes, streams their output, or differs between Node and Bun.
|
|
44
75
|
- Use `Prompt` only for an intentionally interactive path. Keep required inputs
|
|
45
76
|
expressible as arguments or flags so automation never depends on a terminal.
|
|
46
77
|
- Add `--dry-run` for commands that mutate important state and `--yes` for
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
|
-
display_name: "Build Effect CLIs"
|
|
3
|
-
short_description: "
|
|
4
|
-
default_prompt: "Use $build-effect-clis to
|
|
2
|
+
display_name: "Build Effect Scripts and CLIs"
|
|
3
|
+
short_description: "Write every script and CLI with Effect"
|
|
4
|
+
default_prompt: "Use $build-effect-clis to write or modify this script or CLI as an Effect program with explicit platform boundaries and tests."
|
|
@@ -4,6 +4,11 @@ Separate command definition from execution. Importing a command module in a test
|
|
|
4
4
|
or another program must not parse `process.argv`, start fibers, or terminate the
|
|
5
5
|
process.
|
|
6
6
|
|
|
7
|
+
For a fixed CI or automation script with no public command syntax, export its
|
|
8
|
+
Effect workflow and provide platform Layers only in a thin executable module;
|
|
9
|
+
it does not need an artificial `Command` tree. Use the same `runMain` boundary,
|
|
10
|
+
typed failures, platform services, and import-safety rules shown below.
|
|
11
|
+
|
|
7
12
|
```ts
|
|
8
13
|
// src/cli/command.ts
|
|
9
14
|
export const command = root.pipe(Command.withSubcommands([deploy, status]));
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Processes and platform services
|
|
2
2
|
|
|
3
3
|
Use Effect platform services inside CLI workflows. Keep direct `node:*`, Bun
|
|
4
|
-
globals, `process`, filesystem calls, and shell execution
|
|
5
|
-
|
|
4
|
+
globals, `process`, filesystem calls, and shell execution inside explicit
|
|
5
|
+
boundary adapters. The executable boundary itself should use Effect platform
|
|
6
|
+
runtime and service APIs.
|
|
6
7
|
|
|
7
8
|
## Own subprocess behavior in a service
|
|
8
9
|
|