The TS1295/TS1287 errors were not an LSP misconfiguration: the server was still running from an earlier local test that had emptied package.json, and kept the corrupted project state alive. Driven with pi-lsp's exact handshake, tsc --lsp --stdio reads tsconfig.json correctly. Record the real caveat instead: no file watchers, so tsconfig.json/package.json edits can leave diagnostics stale until the server restarts.
7.2 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: F#-style 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). Preferlsp_referencesovergrep -wfor widely-colliding identifiers (matches,type, …); uselsp_hoverto read inferred types on generic-heavy code. 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. -
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. -
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-lineascasts 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. The oxlint-disable-location rule in CONTRIBUTING.md § Rules the tools don't enforce is a human last-resort convention (so a reviewer can spot a deliberate suppression) — it is not permission for you to add one. 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
-
Task with subtasks (a task that has indented children): 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 on each subtask with commits, 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:
git checkout main && git merge --no-ff <branch>. The branching model is documented in CONTRIBUTING.md § Branching model. -
Leaf task (no indented children): implement on the current branch and commit.
In both cases, follow CONTRIBUTING.md § Testing discipline (type-driven). Each subtask gets one or more commits.
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). - README.md § Tooling decisions — 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).