The README collapsed to API-only prose once the old match/P surface was dropped. Rebuild its entry-point shape: a quick-start Synopsis walked through a Contact union, a dedicated Installation section, and a real-world Examples section (primitive-union dispatch, a fallback, a property union narrowed by the tagged-union matcher, and the widening variant). Set the tagline and Description to the library's identity — exhaustive, type-safe pattern matching for TypeScript — and state the goal Moose-style: type-safe pattern matching with a lean syntax, accomplished by exhaustive branches and typed per-branch handler parameters, backed by autocomplete and a tiny footprint. Drop the F#-style framing and the stale "matches method is a type guard" and "(not regex)" copy from the README, AGENTS.md and the package.json description. Every fence is a doc-test, so the examples cannot drift from the API.
8.5 KiB
AGENTS.md
Machine entry point for AI coding agents working in this repo. The authoritative guidance for humans lives in CONTRIBUTING.md and README.md; this file only points at it and states the stable first-action facts. Do not restate evolving prose here — it will drift.
First action
-
Project: pattern matching for TypeScript/ESM. Node
>=26(pinned via.node-version), ESM-only (no CommonJS shim). -
While iterating:
npm run test(check:tsc+ the unit suite) for fast feedback on the files you changed. -
Optional code intelligence: this repo installs
@spences10/pi-lsp(pinned in.pi/settings.json) as a project-local pi extension. It talks to the repo's own TypeScript 7 viatsc --lsp --stdioand exposes read-only tools —lsp_hover,lsp_definition,lsp_references,lsp_find_symbol,lsp_document_symbols,lsp_diagnostics(_many). When you are looking for a symbol, reach for the LSP beforerg/grep—lsp_references/lsp_find_symbol/lsp_definition/lsp_document_symbolsare semantic and cross-file, so they see shadowing, imports and overloads that a text search cannot; uselsp_hoverto read inferred types on generic-heavy code. Usergfor what the LSP cannot see — doc prose, string literals, config, task lists, file discovery — and reconcile the two sets before editing (symbols from the LSP, strings and prose fromrg). It has no rename / code-action / apply-edit surface — the write side is pi'sedittool +check:tsc. Treat empty LSP output as inconclusive, not success:npm run test/npm run verifyremain the sole authoritative gate (see the next bullet). The server keeps running across that gate with a ~5 min idle timeout and registers no file watchers, so if you changetsconfig.json/package.jsonmid-session its diagnostics can be stale — when LSP output disagrees withcheck:tsc, trustcheck:tscand restart pi (or wait out the idle timeout) before concluding the LSP is wrong. -
Definition of done — run this before you call the work finished:
npm run verify. If all green, commit. If red, look at the output, fix the root cause, and re-run. -
Touched a
ts-tagged fence inREADME.md/CONTRIBUTING.md? Runnpm run create:doc-testsfirst: it regenerates the gitignored tests undersrc/doc-test/__generated__/, formats and type-checks them, soverifyexecutes the documented example. CI runs it in an explicit step beforetest:ci; the fast local tiers do not. See development/docs.md. -
On commit: write a good message (see CONTRIBUTING.md § Commit messages). Lefthook's pre-commit hook already runs the fast, offline, staged-file checks — don't run them by hand. If the hook fails on style,
npm run fix, restage, recommit. -
Document decisions where the next maintainer will look: rationale, rejected alternatives and known issues go in
development/<category>.md(see development/README.md); the actionable rule stays in CONTRIBUTING.md and links to it. Write each fact once — never copy the rule intodevelopment/or the reason intoCONTRIBUTING.md— and change both in the same commit when a rule changes. -
npm run maintainis NOT part of the feature loop. Its scans are advisory, never a gate; run them only on an explicit maintenance / update-deps branch.npm run test # while iterating (fast feedback) npm run verify # definition of done: whole-project correctness, one shot
Never do
Don't silence the type system to force a green run. As an agent these are forbidden:
// @ts-nocheck,// @ts-ignore,// @ts-expect-error// oxlint-disable/// oxlint-disable-next-line- editing
.oxlintrc.jsonto silence a finding (e.g. turningtypescript/no-floating-promisesoff) ascasts used to push an expression through (type-aware oxlint already flags unsafe assertions)
Fix the root cause with the type system instead — narrowing, generics, satisfies, conditional / mapped types, utility types (NonNullable, Exclude, …). TypeScript can express it; that's the intended tool. Suppressions — a source oxlint-disable or a .oxlintrc.json entry — are a human last resort, not a tool for you. If the types genuinely cannot express something, stop and surface the conflict (commit message / handover) rather than suppress it.
The same applies to the checks themselves: never git commit --no-verify (or otherwise skip a pre-commit / pre-push hook). The checks are fast and offline, so a redundant run is fine — bypassing a hook to get green is the identical anti-pattern. If a commit already skipped a hook, redo it through one: git reset --soft HEAD~1 && git commit -C <skipped-sha>.
Never start a long-lived / blocking process such as npm run watch. It runs until a human stops it with Ctrl-C, so in an agent turn it hangs forever and floods the context with continuous output. Reach for a one-shot command instead — npm run test (or npm run check) — to get feedback.
Backlog
backlog.tasks uses the vscode-todotasks format (not Markdown). A line ending in : is a project; every other line is a task. Status glyphs: ☐ open, ✔ done, ✘ cancelled; subtasks nest by indentation. Inline @tags carry metadata — @done / @cancelled mark completion, @critical / @high / @low / @today set priority. The (…) timestamp after @done is editor-generated: omit it when checking off by hand.
Required coupling: a ✔ line must also carry @done, and a ✘ line must carry @cancelled. The sandy081.todotasks extension treats the glyph as the completion signal, then unconditionally searches for the matching tag to decorate; a bare ✔/✘ with no tag makes it compute an illegal Range (negative character offset) that throws and kills all highlighting/decoration for the document. A ☐ may stand alone. So check off by hand as ✔ … @done (optionally @done (timestamp)), never a lone ✔.
Working on tasks
Every task — with or without subtasks — goes through the complete branching model:
-
Create the branch with
npm run create:branch -- <prefix>/<desc>, inferring the prefix from the task content (feature/…/fix/…/chore/…) — do not hand-writegit switch -c, the command enforces the clean-tree / current-main/ green-baseline precondition. Work with commits (each subtask gets one or more), then present a concise handover for the user to review. Use this fixed shape:## Handover — <branch> **Implemented:** <what was built, and how> **Judgement calls:** <where the task was unclear, and what you assumed> **Known problems:** <open issues, caveats, follow-ups>Once the user has no further objections, merge back:
npm run create:finish(on the branch — it merges--no-ff, runsnpm run verify, and deletes the branch). The branching model is documented in CONTRIBUTING.md § Branching model.
Follow CONTRIBUTING.md § Testing discipline (type-driven) throughout.
Read these
- CONTRIBUTING.md § Rules the tools don't enforce — the constraints the linters don't catch; CI/review bounce these. The most important section.
- CONTRIBUTING.md § Testing discipline (type-driven) — write the
expectTypeOf(type) before theassert(red); the types are the feature. - CONTRIBUTING.md § Script prefix convention — adding an
npm runscript? reuse an existing prefix or it doesn't belong. - CONTRIBUTING.md § Commit messages — gitmoji + imperative + 50/72.
- CONTRIBUTING.md § Feedback tiers — what runs when and at what cost (
watch/ pre-commit / pre-push /check/verify/fix/maintain/ CI). - development/ — the decisions, rejected alternatives and known issues behind the rules; the “why” that CONTRIBUTING.md links to. Read the relevant file before changing an area.
- development/tooling.md — the rationale behind each tool choice; read before changing tooling.
- package.json
#scripts— the source of truth for every command (theLEFTHOOK_FILESconvention scopes them to staged files vs. the whole project).