Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# AGENTS.md

<!-- distilled from vault Reference/code-standards-* on 2026-07-22; refresh: run the sync-code-standards skill -->
<!-- distilled from vault Reference/code-standards-* on 2026-08-24; refresh: run the sync-code-standards skill -->

Project conventions for AI-assisted development on umm-actually.

Expand Down Expand Up @@ -87,20 +87,31 @@ files. Prefer SDK-provided types over redefining shapes.
goes through the `env-var` package
(`envVar.from(env).get("NAME").required().asString()`), with the env
record injectable for tests.
- Comments explain non-obvious domain context; never restate what a
self-documenting name already says. Regex constants get doc comments.
- Comment decision at write time (use `/** */`; only when earned):
(1) Can a reader understand this from name + params + return type? β†’ no
comment β€” this is most functions. (2) Something non-obvious? β†’ one-line
JSDoc stating the constraint the signature doesn't convey. (3) Does the
JSDoc restate the function name? β†’ delete it. (4) More than 2 lines? β†’
pick the format the reader absorbs quickest (bullets, numbered steps),
never multi-paragraph prose. Inline comments go directly above the
relevant line β€” don't stuff implementation details into the docstring.
Regex constants get doc comments.
- Scope constants to where they're used β€” module level overstates
visibility when only one function needs the value.
- A boolean mode param means the function does two things β€” split into
two single-responsibility functions; the caller owns the gating.
- Type-only imports over structural duplication β€” don't clone interfaces
for "module purity"; type imports are erased at compile time.
- Extract multi-step `.map()`/`.reduce()` callbacks into named functions
when they nest chains or build intermediates. Prefer `.filter(Boolean)`
over conditional spreads. Name non-trivial `.filter()` predicates.
when they nest chains or build intermediates. Conditional spreads and
`.filter(Boolean)` are both fine β€” pick whichever reads clearer; don't
convert mechanically. Name non-trivial `.filter()` predicates.
- Per-operation try/catch β€” each catch encloses one operation with one
failure meaning. Broad catch-alls are banned. Every catch logs or
re-throws; a swallowed error is worse than an uncaught one.
- Required inputs enforced at every entry point β€” fail fast at boot/load.
Making an already-expected value mandatory is a bug fix, not a breaking
change.
- Parse structured strings with a declarative regex (named groups), not
index arithmetic.
- `Boolean(x)` over `!!x`. TS β‰₯5.5 infers `.filter()` predicates from
Expand Down Expand Up @@ -166,6 +177,13 @@ files. Prefer SDK-provided types over redefining shapes.
changes the feature surface.
- Adding a concept (env var, input, file, feature) means sweeping every
doc that lists its peers.
- Write-time format decision: information gets structured format (table
for lookups, bullets for parallel items, numbered steps for sequences);
narrative goes in the PR description, not committed files. More than 3
sentences of prose β†’ wrong format. Match sibling sections in length.
Comment thread
aliasunder marked this conversation as resolved.
- No internal references in any public artifact β€” issue/PR numbers,
task-board IDs, incident dates, deployment names, and investigation
chronology never enter committed files, PR descriptions, or comments.

## Review instruction authoring

Expand Down