Skip to content

Commit c92c57d

Browse files
committed
fmt
1 parent 87ab5c7 commit c92c57d

265 files changed

Lines changed: 5705 additions & 8140 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/wrdn-effect-atom-optimistic/SKILL.md‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ When the trace cannot resolve with the files at hand, drop the finding.
4646

4747
## Severity ladder
4848

49-
| Level | Criteria |
50-
|-------|----------|
49+
| Level | Criteria |
50+
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
5151
| **medium** | New optimistic-mutation code that bypasses `Atom.optimistic` / `Atom.optimisticFn` and rolls its own pending state. Or a mixed read/write where the read goes through the plain query atom and the write goes through the optimistic mutation. |
52-
| **low** | Subtle defects in an `Atom.optimisticFn` reducer that work today but degrade under racing (clock-based identity, missing `Atom.family` wrapper, computed-once captures of `scopeId`). |
52+
| **low** | Subtle defects in an `Atom.optimisticFn` reducer that work today but degrade under racing (clock-based identity, missing `Atom.family` wrapper, computed-once captures of `scopeId`). |
5353

5454
Do not invent `high`. Pick `low` when in doubt and explain why.
5555

@@ -103,9 +103,7 @@ export const updateSecretOptimistic = Atom.family((scopeId: ScopeId) =>
103103
Atom.optimisticFn({
104104
reducer: (current, arg: { path: { secretId: SecretId }; payload: { value: string } }) =>
105105
Result.map(current, (rows) =>
106-
rows.map((r) =>
107-
r.id === arg.path.secretId ? { ...r, value: arg.payload.value } : r,
108-
),
106+
rows.map((r) => (r.id === arg.path.secretId ? { ...r, value: arg.payload.value } : r)),
109107
),
110108
fn: updateSecret,
111109
}),
@@ -136,8 +134,12 @@ export interface PendingSecret {
136134
readonly value: string;
137135
}
138136

139-
export const useSecretsWithPending = (scopeId: ScopeId) => { /* ... */ };
140-
export const usePendingSecrets = () => { /* ... */ };
137+
export const useSecretsWithPending = (scopeId: ScopeId) => {
138+
/* ... */
139+
};
140+
export const usePendingSecrets = () => {
141+
/* ... */
142+
};
141143
```
142144

143145
Flag any new entry in `PendingResource` and any new `use<X>WithPending` / `usePending<X>` hook. The file is closed for new patterns.

‎.agents/skills/wrdn-effect-typed-errors/SKILL.md‎

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ throw new Error("Missing source");
9696
Good in `Effect.gen`:
9797

9898
```ts
99-
return yield* new SourceNotFoundError({ sourceId });
99+
return yield * new SourceNotFoundError({ sourceId });
100100
```
101101

102102
Good in combinators:
@@ -112,13 +112,13 @@ If a third-party interface requires throwing, keep the throw at the adapter edge
112112
Prefer yielding the error directly in generator code:
113113

114114
```ts
115-
return yield* new SourceNotFoundError({ sourceId });
115+
return yield * new SourceNotFoundError({ sourceId });
116116
```
117117

118118
Do not write:
119119

120120
```ts
121-
return yield* Effect.fail(new SourceNotFoundError({ sourceId }));
121+
return yield * Effect.fail(new SourceNotFoundError({ sourceId }));
122122
```
123123

124124
Use `Effect.fail(...)` in non-generator combinator code:
@@ -167,16 +167,14 @@ Effect.ignore(
167167
Bad in domain code:
168168

169169
```ts
170-
program.pipe(Effect.orDie)
171-
Effect.die(error)
170+
program.pipe(Effect.orDie);
171+
Effect.die(error);
172172
```
173173

174174
Good:
175175

176176
```ts
177-
program.pipe(
178-
Effect.mapError((cause) => new DomainError({ message: "Operation failed", cause })),
179-
)
177+
program.pipe(Effect.mapError((cause) => new DomainError({ message: "Operation failed", cause })));
180178
```
181179

182180
`Effect.die`, `Effect.dieMessage`, `Effect.orDie`, and `Effect.orDieWith` turn typed failures into defects. Use them only at a true runtime boundary where the host cannot represent typed failures, and keep that usage behind a narrow lint suppression with a `boundary:` reason. Do not use `orDie` to avoid threading an error type through normal Effect code.
@@ -305,16 +303,19 @@ Bad:
305303
const connectionError = (message: string) =>
306304
new McpConnectionError({ transport: "remote", message });
307305

308-
return yield* connectionError("Endpoint URL is required");
306+
return yield * connectionError("Endpoint URL is required");
309307
```
310308

311309
Good:
312310

313311
```ts
314-
return yield* new McpConnectionError({
315-
transport: "remote",
316-
message: "Endpoint URL is required",
317-
});
312+
return (
313+
yield *
314+
new McpConnectionError({
315+
transport: "remote",
316+
message: "Endpoint URL is required",
317+
})
318+
);
318319
```
319320

320321
Helpers are allowed only when they do real work, such as:

‎.skills/cli-release/SKILL.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ description: Runbook for releasing the `executor` CLI package (stable and beta).
66
# Executor CLI release runbook
77

88
## Authoritative doc
9+
910
`RELEASING.md` at repo root is the source of truth. This skill encodes the owner's preferences on top of it.
1011

1112
## What the `executor` CLI actually ships
1213

1314
The CLI binary bundles:
15+
1416
- `apps/cli/**` — CLI source + daemon
1517
- `apps/local/**` — the web UI (embedded as a virtual module via `apps/cli/src/build.ts:178`) + drizzle migrations (`build.ts:205`)
1618
- `packages/**` — `core`, `kernel`, `hosts/mcp`, `runtime-quickjs`, and every plugin under `packages/plugins/**`
1719

1820
Does **not** ship in the CLI:
21+
1922
- `apps/cloud/**` (Cloudflare Workers deployment)
2023
- `apps/marketing/**`, `apps/desktop/**`
2124
- `examples/**`, `tests/**`
@@ -37,14 +40,17 @@ The owner doesn't want GitHub's auto-generated "PR title by @user" list. Release
3740
**`apps/cli/release-notes/next.md` is the canonical user-facing changelog.** Per-package workspace `CHANGELOG.md` files are one-line stubs required by `changesets/action@v1` (the GitHub Action wrapping the CLI in `release.yml`) — it reads each bumped package's `CHANGELOG.md` to build the Version Packages PR description and crashes with `ENOENT` if any is missing. The stubs satisfy that read; don't put release content in them.
3841

3942
### How it's wired
43+
4044
`apps/cli/src/release.ts` reads `apps/cli/release-notes/next.md` and uses
4145
its contents as the GitHub Release body. If the file is missing or empty,
4246
falls back to `gh release create --generate-notes`. There's no
4347
per-version archive in the repo — historical release bodies live on
4448
GitHub Releases (durable, indexed, linkable).
4549

4650
### Writing conventions
51+
4752
Structure release-notes files as:
53+
4854
```
4955
## Highlights
5056
### <user-facing story> # e.g. "Per-user OAuth for OpenAPI and MCP sources"
@@ -74,17 +80,20 @@ External contributor bullets end with `Thanks @<user> (#PR)`:
7480
Do not `Thanks` maintainers, bots, or the repo owner — the lint script rejects `@claude`, `@anthropic`, `@github-actions`, `@dependabot`, `@renovate`, `@rhyssullivan`, `@rhys-sullivan`. Run `bun run lint:release-notes` before pushing notes.
7581

7682
### When drafting from `git log`
83+
7784
- Look at `git diff v<last>..HEAD -- README.md` first — it's the best single view of user-facing changes.
7885
- Read commit messages in bulk (`git log --oneline v<last>..HEAD -- apps/cli apps/local packages`), then bucket by theme before writing prose.
7986
- Don't list every commit. Merge PRs and refactor-chain commits into one line.
8087

8188
### Pairing with changesets
89+
8290
- A `.changeset/*.md` describes the version bump (semver level + a short summary for the Version Packages PR description). It is **not** the user-facing changelog.
8391
- If your PR adds a `.changeset/*.md` for the `executor` package, also edit `apps/cli/release-notes/next.md` for the user-facing story. They have different audiences.
8492
- The `.changeset/*.md` body can be a one-liner pointing at the release-notes section it expands; users read the GitHub release body, not the changeset.
8593
- Frontmatter is `"executor": patch` (or `minor`/`major` if owner says so).
8694

8795
### Starting a new release cycle
96+
8897
There's no post-release rename step. When you start work on the next
8998
release, replace the existing `next.md` content with new entries — the
9099
previous cycle's content is already preserved on the matching `vX.Y.Z`

‎.skills/effect-atom-optimistic-updates/SKILL.md‎

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ sources/connections.
1616

1717
- A list query atom (`Atom.optimistic` wraps the query)
1818
- Plus one or more mutation atoms that change rows in that list (create / update / delete)
19-
- And you want the UI to reflect the change *immediately* on click, before the server roundtrip
19+
- And you want the UI to reflect the change _immediately_ on click, before the server roundtrip
2020

2121
If you only need the UI to be "eventually consistent" (i.e. you're fine waiting
2222
~200ms for the server response and the existing reactivity refetch), skip
@@ -109,10 +109,7 @@ existing `reactivityKeys` plumbing still applies — pass them in the call.
109109
```typescript
110110
import { useAtomValue, useAtomSet } from "@effect-atom/atom-react";
111111

112-
import {
113-
policiesOptimisticAtom,
114-
updatePolicyOptimistic,
115-
} from "../api/atoms";
112+
import { policiesOptimisticAtom, updatePolicyOptimistic } from "../api/atoms";
116113
import { policyWriteKeys } from "../api/reactivity-keys";
117114

118115
export function PoliciesPage() {
@@ -203,10 +200,7 @@ export const removePolicyOptimistic = Atom.family((scopeId: ScopeId) =>
203200
path: { scopeId: ScopeId; policyId: PolicyId };
204201
reactivityKeys?: ReadonlyArray<unknown>;
205202
},
206-
) =>
207-
Result.map(current, (rows) =>
208-
rows.filter((r) => r.id !== arg.path.policyId),
209-
),
203+
) => Result.map(current, (rows) => rows.filter((r) => r.id !== arg.path.policyId)),
210204
fn: removePolicy,
211205
}),
212206
),
@@ -244,7 +238,7 @@ read, optimistic create/update/remove, no custom state.
244238

245239
## When you must NOT use this
246240

247-
- The mutation has cross-cutting effects on data that *isn't* in the same list
241+
- The mutation has cross-cutting effects on data that _isn't_ in the same list
248242
(e.g. a single mutation invalidates `tools` AND `policies`). Reactivity keys
249243
still handle that — optimistic only paints the list-local change.
250244
- You need to show transient UI state that isn't a row property (toasts,

0 commit comments

Comments
 (0)