Files
tmu 8261759190 📝 Restore and rewrite the README entry point
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.
2026-09-24 21:55:51 +00:00

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 via tsc --lsp --stdio and 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 before rg/grep — lsp_references / lsp_find_symbol / lsp_definition / lsp_document_symbols are semantic and cross-file, so they see shadowing, imports and overloads that a text search cannot; use lsp_hover to read inferred types on generic-heavy code. Use rg for 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 from rg). It has no rename / code-action / apply-edit surface — the write side is pi's edit tool + check:tsc. Treat empty LSP output as inconclusive, not success: npm run test / npm run verify remain 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 change tsconfig.json / package.json mid-session its diagnostics can be stale — when LSP output disagrees with check:tsc, trust check:tsc and 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 in README.md / CONTRIBUTING.md? Run npm run create:doc-tests first: it regenerates the gitignored tests under src/doc-test/__generated__/, formats and type-checks them, so verify executes the documented example. CI runs it in an explicit step before test: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 into development/ or the reason into CONTRIBUTING.md — and change both in the same commit when a rule changes.

  • npm run maintain is 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.json to silence a finding (e.g. turning typescript/no-floating-promises off)
  • as casts 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-write git 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, runs npm 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