diff --git a/.claude/docs/landing-prs.md b/.claude/docs/landing-prs.md index 04bca60ea615..d9643b5f42d4 100644 --- a/.claude/docs/landing-prs.md +++ b/.claude/docs/landing-prs.md @@ -53,6 +53,7 @@ Companion to the "Landing PRs: What Bun Reviewers Catch" section in CLAUDE.md. T - **Sweep the same PR for everything describing the old state.** When behavior, names, or contracts change — including mid-PR pivots — update or delete: comments beyond the hunk, sibling/mirror implementations, JSDoc, "see above" cross-references, READMEs, CLAUDE.md, --help text, error-message hints. A comment contradicting the code is a correctness bug, not a nit — a stale refcount comment invites a future maintainer to "restore" unref() and cause a double-free. Write comments about the code as it now is, never narrating the change. - **Comments must be load-bearing and true.** Any line correct for a non-obvious reason gets a why-comment: special-case branches (with a triggering input), deliberate deviations from the reference, magic constants (cite the spec line), workarounds (link the upstream issue). When a reviewer asks "is this state possible?" — answer with a code comment, not just a thread reply; articulating the invariant routinely exposes that it doesn't hold. SAFETY comments state the precise invariant and where it's enforced — against every caller — and get re-verified after each refactor. Encode documented preconditions as debug assertions rather than prose. - **Verify every documentation claim you publish, by execution.** Run each snippet end-to-end exactly as written; fetch every URL; check option names/defaults against the implementation on main; preview rendered markdown (an unbalanced fence swallows everything after it). Replace marketing language with the specific guaranteed property. Never claim full compatibility when partial — enumerate what works. Don't publish claims you haven't verified — verify, scope down, or drop them (an AI-drafted page with unverifiable claims was deleted wholesale, +9/-325). Existing docs you didn't touch are out of scope. +- **Docs prose follows the voice rules in `docs/project/contributing.mdx` ("Voice").** Short sentences, one point each (a sentence with several commas or a dash-separated aside becomes two sentences or a list); active voice with the actor named ("Bun reads X", not "X is read"); present tense for current behavior (no "will"); "you" for the reader, never tutorial "we"/"let's"; no "easy"/"simple"/"just"/"quick"; name the subject where a bare "this" is ambiguous; say what to do rather than what not to do. Docs-wide passes have been merged to remove exactly these patterns (#28788, #33112), and #38686 rewrote pages that had reintroduced them the same day they merged; prose that breaks these rules costs a follow-up PR. - **TypeScript declarations mirror the runtime exactly, in the same PR.** Declare only what's implemented — verify by running the API, never docs or the PR description; no types for stubbed APIs. Literal unions for fixed string sets (`'A' | 'B' | (string & {})` for open sets); overloads so parameters are only accepted where the runtime accepts them; `prop?: T | undefined` for exactOptionalPropertyTypes; `Uint8Array` generics (TS 5.9+); new type parameters get defaults so existing call sites compile; no new globals colliding with lib.dom/@types/node (use the Bun namespace); never widen a type or `as any` to silence one call site. No `*/` inside JSDoc (glob patterns break the entire .d.ts parse). Validate by compiling realistic usage in bun-types fixtures under BOTH tsconfigs (with and without DOM). - **Write JSDoc for a zero-context reader.** Option docs explain what the option DOES — semantics, edge behavior, sentinel meanings (0 = unlimited), when it has no effect, the equivalent CLI flag — never a wordier restatement of the name. The .d.ts JSDoc is the canonical IDE-tooltip surface; constraints documented only in .mdx are invisible at the point of discovery. Security-adjacent examples must be safe to copy verbatim (least privilege, never User=root).