From 153324c1759b5f1d60af9b4ef1f03bcc058ba76b Mon Sep 17 00:00:00 2001 From: Benoit Travers Date: Wed, 26 Aug 2026 23:44:46 +0200 Subject: [PATCH 1/3] chore: point CodeRabbit at this repository's own conventions A `.coderabbit.yaml` whose `path_instructions` name the spec file rather than restating it, so there is one copy of the rules and it is the one already under review. The `path_filters` keep generated output and the lockfile out of the diff it reads. --- .coderabbit.yaml | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000..ddfbab10 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,44 @@ +# yaml-language-server: $schema=https://storage.googleapis.com/coderabbit_public_assets/schema.v2.json + +reviews: + path_filters: + - "!**/src/generated/**" + - "!**/docs/.vitepress/dist/**" + - "!pnpm-lock.yaml" + path_instructions: + - path: "**/*.ts" + instructions: | + The authoritative spec is the root `AGENTS.md` (`CLAUDE.md` is a symlink to it) — read it first, and treat a suggestion it has already rejected as noise. + + Errors are values here (`unthrown`), not exceptions. Suggestions that + assume otherwise are wrong rather than debatable: + + - No `try`/`catch` around a `Result` pipeline. Every combinator catches + a thrown callback and converts it to a `Defect`; the `defect` arm of + the final `match` is the catch. A `try` in the diff is either a + boundary around a foreign throwing API — legitimate, and they carry a + reason — or a mistake. + - There is no `mapErr`. The error combinators are `mapErrCases`, + `flatMapErrCases`, `recoverErrCases` and `tapErrCases`, and they are + exhaustive by design: `P._` is a lint error outside a helper generic + in `E`. + - Every async surface returns `AsyncResult`, never a bare `Promise` — + the infallible ones included (`AsyncResult`). + - `Ok(v).toAsync()` is `OkAsync(v)`; `Err(e).toAsync()` is + `ErrAsync(e)`. A `flatMap` returning the value it was handed is + `ensure`. A nullable lookup is `fromNullable`, not a ternary. + - `E` is never `unknown`, `any` or `Error`; a `Defect` never appears + in it. + + Comments are sparse by convention: rationale lives in the spec file, + not beside the code. Do not ask for more comments, or for TSDoc on a + private symbol. + + `type` not `interface`, `unknown` not `any`, and every relative import + carries `.js` — `moduleResolution: NodeNext`. + + - path: "**/{CLAUDE,AGENTS}.md" + instructions: | + This is the spec, not commentary. Check its claims against the code in + the same diff: a sentence that counts call sites or describes a + signature is a claim that can go stale silently. From d091e32778bc1a9bfac0ac0c4476272d9115eb90 Mon Sep 17 00:00:00 2001 From: Benoit Travers Date: Wed, 26 Aug 2026 23:56:48 +0200 Subject: [PATCH 2/3] fix: do not list CLAUDE.md/AGENTS.md in path_instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit auto-detects them as code guidelines. Naming them in `path_instructions` tells it to REVIEW those files rather than USE them, which is the opposite of what the entry was for — and it made the rest of the instructions redundant, since auto-detection was already loading the spec. The claim check the entry existed for moves onto the code's own glob, where it belongs: when a diff changes the spec alongside the code, hold the spec to the code. --- .coderabbit.yaml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index ddfbab10..2eb79430 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -8,7 +8,10 @@ reviews: path_instructions: - path: "**/*.ts" instructions: | - The authoritative spec is the root `AGENTS.md` (`CLAUDE.md` is a symlink to it) — read it first, and treat a suggestion it has already rejected as noise. + When the same diff also changes a `CLAUDE.md`, an `AGENTS.md` or a + README, check what it now claims against this code. A sentence that + counts call sites, names "the one such site" or describes a signature is + a claim that goes stale silently, and one already had. Errors are values here (`unthrown`), not exceptions. Suggestions that assume otherwise are wrong rather than debatable: @@ -36,9 +39,3 @@ reviews: `type` not `interface`, `unknown` not `any`, and every relative import carries `.js` — `moduleResolution: NodeNext`. - - - path: "**/{CLAUDE,AGENTS}.md" - instructions: | - This is the spec, not commentary. Check its claims against the code in - the same diff: a sentence that counts call sites or describes a - signature is a claim that can go stale silently. From 9de3a2b79f2f440f39abeca7b51e743cd7aaa31f Mon Sep 17 00:00:00 2001 From: Benoit Travers Date: Thu, 27 Aug 2026 00:00:22 +0200 Subject: [PATCH 3/3] fix: a filter for a gitignored path is dead config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every `path_filter` except the lockfile named a path git already ignores — `src/generated/**`, `.vitepress/dist/**`, `.vitepress/cache/**` — so none of them could ever appear in a diff for CodeRabbit to filter. Checked with `git ls-files` across all seven repositories: zero tracked files behind any of them. `pnpm-lock.yaml` is the one that is tracked, and the one worth filtering. --- .coderabbit.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 2eb79430..565174d9 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -2,8 +2,6 @@ reviews: path_filters: - - "!**/src/generated/**" - - "!**/docs/.vitepress/dist/**" - "!pnpm-lock.yaml" path_instructions: - path: "**/*.ts"