Skip to content

Commit f4a23bc

Browse files
authored
sync-alphalib-2026-05-15 (#414)
1 parent 758fe7d commit f4a23bc

27 files changed

Lines changed: 1374 additions & 716 deletions

.ai/rules/coding-style.mdc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ Coding style:
1212
- Favor using real paths (`../lib/schemas.ts`) over aliases (`@/app/lib/schemas`).
1313
- Favor `for (const comment of comments) {` over `comments.forEach((comment) => {`
1414
- Favor named exports over default exports, with the exception of Next.js pages
15+
- Avoid namespace `*` imports unless the API is intentionally consumed as a namespace. Prefer named
16+
imports so usage is explicit and bundlers can optimize.
17+
- Avoid broad file-level lint suppressions. Prefer the narrowest scoped suppression on the exact
18+
line, with a reason when the exception is not obvious.
19+
- Preserve existing dependency import paths and module-system interop unless the change is required
20+
and explained. Do not rewrite package imports to `node_modules/...`, switch ESM/CJS shapes, or add
21+
duplicate export styles just to satisfy local tooling.
1522
- Do not wrap each function body and function call in `try`/`catch` blocks. It pollutes the code.
1623
Assume we will always have an e.g.
1724
`main().catch((err) => { console.error(err); process.exit(1) })` to catch us. I repeat: Avoid
@@ -28,8 +35,22 @@ Coding style:
2835
- Use Prettier with 100 char line width, single quotes for JS/TS, semi: false
2936
- Use descriptive names: PascalCase for components/types, camelCase for variables/methods/schemas
3037
- Alphabetize imports, group by source type (built-in/external/internal)
38+
- Preserve existing sorted lists and config ordering unless intentionally changing the order.
3139
- Favor US English over UK English, so `summarizeError` over `summarise Error`
3240
- Favor `.replaceAll('a', 'b)` over `.replace(/a/g, 'b')` or `.replace(new RegExp('a', 'g'), 'b')` when the only need for regeses was replacing all strings. That's usually both easier to read and more performant.
3341
- Use typographic characters: ellipsis (`…`) instead of `...`, curly quotes (`'` `"`) instead of straight quotes in user-facing text
42+
- Generated text files should end with a trailing newline. Do not trim serializer output when the
43+
serializer intentionally emits POSIX-style text.
44+
- Comments should explain why code exists or why an exception is needed, not narrate what the next
45+
line already says.
46+
- Do not put TODOs, internal implementation notes, or future-work placeholders in user-facing text
47+
or schema descriptions. Put those in code comments, issues, or docs for maintainers instead.
3448
- Put API keys and secrets in `.env` files, not hardcoded in components
49+
- Do not return raw errors, stack traces, third-party responses, payment objects, database errors, or
50+
credential data to clients. Show sanitized user-facing messages and log only redacted diagnostic
51+
details server-side.
52+
- When wrapping or rethrowing an error, preserve the original value with `new Error(message, {
53+
cause: error })` when possible instead of stringifying it away.
54+
- Remove temporary debug logging/instrumentation before merge. Keep new logs only when they are
55+
intentional, useful in production, and do not expose sensitive data.
3556
- Check for existing hooks before creating new ones (e.g., `useUppy()` for Uppy functionality)

.ai/rules/general.mdc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ General:
1111
- Avoid blocking the conversation with terminal commands. For example: A) most of my git commands run through pagers, so pipe their output to `cat` to avoid blocking the
1212
terminal. B) You can use `tail` for logs, but be smart and use `-n` instead of `-f`, or the conversation will block
1313
- Use the `gh` tool to interact with GitHub (search/view an Issue, create a PR).
14+
- When using `fetch()` directly, check `response.ok` before parsing the body, and surface non-2xx
15+
responses as errors with enough context for debugging.
1416
- Treat `AGENTS.md` and `CLAUDE.md` as generated artifacts (single source of truth is `.ai/rules/`), managed by `~/code/content/_scripts/alphalib-sync.ts`; never edit those files directly. If you'd like to make a modification, do it here in `.ai/rules/` and the script will ensure proper preservation and syncing. If you need a rule specific to this repo, add it to `.ai/rules/repo.mdc`.
1517
- All new files are to be in TypeScript. Even if someone suggests: make this new foo3 feature, model it after `foo1.js`, create: `foo3.ts`. Chances are, a `foo2.ts` already exist that you can take a look at also for inspiration.

.ai/rules/typescript.mdc

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,76 @@ description:
33
globs:
44
alwaysApply: true
55
---
6+
67
For Typescript:
78

89
- Favor `contentGapItemSchema = z.object()` over `ContentGapItemSchema = z.object()`
910
- Favor `from './PosterboyCommand.ts'` over `from './PosterboyCommand'`
1011
- Favor `return ideas.filter(isPresent)` over `ideas.filter((idea): idea is Idea => idea !== null)`
1112
- Favor using `.tsx` over `.jsx` file extensions.
12-
- Use Node v24's native typestripping vs `tsx` or `ts-node`. These days you do not even need to pass `--experimental-strip-types`, `node app.ts` will just work.
13-
- Favor `satisfies` over `as`, consider `as` a sin
13+
- Use Node v24's native typestripping vs `tsx` or `ts-node`. These days you do not even need to pass
14+
`--experimental-strip-types`, `node app.ts` will just work.
15+
- In ESM TypeScript, use `import.meta.dirname` / `import.meta.filename` or `URL` objects instead of
16+
rebuilding `__dirname` with `fileURLToPath(import.meta.url)` unless compatibility requires it.
17+
- Use `satisfies` when you need literal preservation or structural conformance while keeping the
18+
expression's inferred type. If the variable should simply have a declared type, use a type
19+
annotation instead.
20+
- Avoid redundant type annotations inside expressions when TypeScript already infers the exact type,
21+
especially callback parameters. Keep explicit return types and public boundary annotations.
22+
- Avoid `as`, consider it a sin. If a cast is unavoidable, keep it as narrow as possible and explain
23+
the upstream type mismatch or runtime invariant.
24+
- For DOM queries and browser APIs, prefer runtime narrowing such as
25+
`element instanceof HTMLAnchorElement` over type casts. Decide explicitly whether a missing element
26+
should throw, return early, or no-op.
27+
- Browser/client code must not use Node-only globals or APIs such as `Buffer`. Use browser platform
28+
APIs such as `btoa`, `TextEncoder`, `Blob`, or `URL`, or isolate the logic in server-only code.
29+
- When browser APIs are missing TypeScript declarations, augment the global interface in
30+
`_types/global.ts` (or the relevant shared global types file) and narrow with checks such as
31+
`typeof navigator.setAppBadge === 'function'` instead of casting `navigator` locally.
32+
- Prefer typed DOM properties such as `element.inert = true` and `element.tabIndex = -1` when the
33+
platform exposes them. Use `setAttribute()` only when you intentionally need raw attribute
34+
semantics.
1435
- Favor `unknown` over `any`, consider `any` a sin
36+
- Avoid `as unknown as ...` and `biome-ignore lint/suspicious/noExplicitAny`. If an upstream library
37+
type forces either, isolate it in a tiny adapter/helper with a comment naming the bad upstream
38+
type.
39+
- Every `@ts-expect-error` must be narrow and include a short explanation of the upstream type gap or
40+
invariant that makes it safe.
1541
- Favor validating data with Zod over using `any` or custom type guards
16-
- For local TypeScript files, import with the `.ts` / `.tsx` extension (not `.js`, not extensionless).
17-
Note: we do not currently enable the TS 5.7 `rewriteRelativeImportExtensions` compiler option,
18-
because it errors on non-relative imports that include `.ts`/`.tsx` (for example via `paths`
19-
aliases like `@/…`). If/when we enable it, we will need to adjust those imports first.
42+
- Extract duplicated Zod object shapes, regexes, and descriptions into reusable schema fragments
43+
when they describe the same domain concept. Keep property-level concerns such as `.optional()` and
44+
`.default()` at the property site unless absence is intrinsic to the reusable fragment.
45+
- Boolean Zod properties should usually use explicit defaults instead of `.optional()` when omission
46+
has normal default behavior. Only leave a boolean optional when `undefined` is semantically
47+
different from `false`.
48+
- Prefer `z.union([...])` over chained `.or()` for multi-branch unions, and prefer `z.enum()` or
49+
literal unions over clever regexes when the accepted values are finite and autocomplete matters.
50+
- Do not duplicate supported values in user-facing schema descriptions when schema metadata such as
51+
enums or suggested values can carry that information.
52+
- In TypeScript files, use TypeScript syntax instead of JSDoc type annotations. In JavaScript files,
53+
prefer JSDoc `@import` / `@param` forms over noisy inline `import('...')` annotations, and make
54+
sure `@type` annotates the expression it is meant to type.
55+
- Avoid hand-written `.d.ts` files when the declaration can come from TypeScript source or
56+
generation. If a declaration file is unavoidable, do not rely on `skipLibCheck` to hide duplicate
57+
or invalid exports.
58+
- Avoid `Reflect.get` for normal object property reads. After narrowing to a record, use
59+
`record[key]` or a small typed reader helper. Only keep `Reflect.get` for exotic receivers such as
60+
proxies or framework objects where its semantics are intentionally required, and document why.
61+
- Prefer `Number.isFinite()` / `Number.isNaN()` over global `isFinite()` / `isNaN()` so numeric
62+
checks do not silently coerce non-numbers.
63+
- `isRecord` style guards must reject arrays:
64+
`typeof value === 'object' && value !== null && !Array.isArray(value)`. Prefer importing a shared
65+
guard when one already exists in the relevant shared layer.
66+
- Type-only refactors must preserve runtime behavior. If the behavior intentionally changes, call it
67+
out in the PR and cover the changed behavior with tests.
68+
- Use ECMAScript `#private` fields for private state. Do not rely on underscore names or TypeScript
69+
`private` to imply runtime privacy.
70+
- Prefer Zod defaults/preprocessing for schema-backed default values instead of duplicating default
71+
objects in runtime code.
72+
- For local TypeScript files, import with the `.ts` / `.tsx` extension (not `.js`, not
73+
extensionless). Note: we do not currently enable the TS 5.7 `rewriteRelativeImportExtensions`
74+
compiler option, because it errors on non-relative imports that include `.ts`/`.tsx` (for example
75+
via `paths` aliases like `@/…`). If/when we enable it, we will need to adjust those imports first.
2076
- Favor defining props as an interface over inline
2177
- Favor explicit return types over inferring them as it makes typescript a lot faster in the editor
2278
on our scale

.ai/skills/gh-pr-to-green/SKILL.md

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,31 @@ description:
1111

1212
## Workflow
1313

14-
- Get context from PR with `gh`, make sure if have all comments
15-
- Write them as a markdown todolist in `repodocs/prompts/${YYYY}-${MM}-${DD}-${sluggedSemanticTopic}.md` and commit it. If the `repodocs/prompts/` dir does not exist, use the `docs/prompts/` dir.
14+
- Get context from PR with `gh`; make sure all review comments, threads, CI failures, and PR
15+
description updates are included.
16+
- Write them as a markdown todolist in
17+
`repodocs/prompts/${YYYY}-${MM}-${DD}-${sluggedSemanticTopic}.md` and commit it. If the
18+
`repodocs/prompts/` dir does not exist, use the `docs/prompts/` dir.
1619
- Merge the latest main into our branch and resolve any conflict carefully.
1720
- Determine which review items are correct.
18-
- Keep working until all items are checked off, either by fixing the issue, or explaining why not in the markdown list as well as comments in code where applicable/sensible
19-
- commit and push
21+
- Keep working until all items are checked off, either by fixing the issue, or explaining why not in
22+
the markdown list as well as comments in code where applicable/sensible.
23+
- Commit and push.
2024
- Invoke `council-review`
21-
- Run the repo-required checks (often `yarn check`)
22-
- Fix any issue that you deem related and worth fixing
23-
- commit and push
25+
- If the PR has UI/UX impact, invoke `claude-usertest` instead of duplicating browser-test
26+
instructions here. Treat its output as reviewer input, reconcile findings yourself, and fold valid
27+
fixes back into this PR-to-green loop.
28+
- Run the repo-required checks (often `yarn check`).
29+
- Fix any issue that you deem related and worth fixing.
30+
- Commit and push.
2431
- Monitor CI until green:
2532
- Prefer `gh run watch` (works everywhere with `gh`).
2633
- If `gh-run-watch.ts` exists in the repo, it's fine to use that too.
27-
- Fix any issue that you deem related and worth fixing
28-
- Rinse and repeat until CI is green, or there are only 100% unrelated issues remaining
34+
- Fix any issue that you deem related and worth fixing.
35+
- Rinse and repeat until CI is green, or there are only 100% unrelated issues remaining.
2936

30-
Report back with a list of all changes made, and offer a link to the PR for inspection and merge. Offer to squash merge with `--admin` if the human thinks a last manual review is not needed.
37+
This skill is PR orchestration only. Do not add inline UX/browser/user-test instructions here; use
38+
dedicated validation skills for those workflows.
39+
40+
Report back with a list of all changes made, and offer a link to the PR for inspection and merge.
41+
Offer to squash merge with `--admin` if the human thinks a last manual review is not needed.

.yarnrc.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
nodeLinker: node-modules
22

3+
npmMinimalAgeGate: 2880
4+
35
packageExtensions:
46
"@oxc-resolver/binding-wasm32-wasi@*":
57
dependencies:
6-
"@emnapi/core": "1.10.0"
7-
"@emnapi/runtime": "1.10.0"
8-
9-
npmMinimalAgeGate: 2880
8+
"@emnapi/core": 1.10.0
9+
"@emnapi/runtime": 1.10.0

0 commit comments

Comments
 (0)