fix(coding-dev): scoped suppressions, contribution-dependent precedence

- suppressions: prefer the narrowest scope that covers the problem (line,
  function, module) with a reason comment; a project-wide disable silences
  the rule in code nobody has written yet. Always name the specific rule.
  Propagated to rust (#[allow]), csharp (#pragma/SuppressMessage).
- precedence: a project's own rules win only when contributing upstream.
  For local/private work these rules win, adopting only the project's
  load-bearing conventions.
- type checking must pass with zero errors *or warnings*.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
BluscreamandClaude Opus 5 committed 2026-09-18 12:34:51 +02:00
1 parent 57968904bf
commit 9571eb52d2
4 files changed
+48 -17

No files matched your search

+27 -9
View File
@@ -14,9 +14,17 @@ These are the defaults for **all** code work, in any language. They are preferen
reasons attached, not style trivia — most exist because ignoring them caused a real problem.
> [!IMPORTANT]
> **A project's own rules win.** If a repository has an `AGENTS.md`, `CLAUDE.md`, `AGENT.md`,
> `.rules`, or `CONTRIBUTING.md`, read it first — it is more specific than this document and
> overrides it on conflict. This file is the default for everything those files do not say.
> **Whose rules win depends on where the code is going.** Always read a repository's
> `AGENTS.md`, `CLAUDE.md`, `AGENT.md`, `.rules`, or `CONTRIBUTING.md` first — but what you do
> on a conflict differs:
>
> | Situation | Precedence |
> | :--- | :--- |
> | **Contributing upstream** — a PR, a patch, or anything landing in someone else's repo | **The project's rules win.** Match their conventions exactly, even where they contradict this document. A PR that fights the house style gets rejected on style instead of reviewed on substance. |
> | **Local / private work** — our own repos, forks we don't upstream, private branches, local patches | **These rules win.** A project's conventions are a data point, not an obligation. Adopt the ones that are load-bearing (their build gate, their architecture contracts, anything that breaks if ignored) and apply our own preferences for the rest. |
>
> When in doubt about which mode you are in, **ask** — it changes the answer on strictness,
> file size, typing, and test policy all at once.
Per-language specifics live in [`code-languages/`](./code-languages/):
@@ -39,10 +47,15 @@ Strict mode is the starting point, not an aspiration to migrate toward later.
- Warnings are errors in CI and in the build gate (`-warnaserror`, `-D warnings`, `--strict`).
- Enable the pedantic/extra lint tiers, not just the defaults.
- Type checking must pass with **zero** errors — `tsc --noEmit`, `mypy`, `cargo check` alike.
- Type checking must pass with **zero errors or warnings** — `tsc --noEmit`, `mypy`,
`cargo check` alike.
- Never weaken a check to make a build pass. Fix the failing step. If a check is genuinely
wrong for the codebase, disable it **project-wide in one place with a comment explaining
why**, so the decision is visible and reviewable — never with a scattered inline suppression.
wrong for a specific piece of code, **suppress it at the narrowest scope that covers the
problem — the line, the function, or the module — with a comment explaining why.** A
project-wide disable is a bigger hammer than it looks: it silences the rule everywhere,
including in code written later by someone who never saw the reason. Reach for it only when
the rule is genuinely wrong for the *whole* codebase, never as a shortcut for a stubborn
call site.
### Suppressions are a last resort, and they expire
@@ -50,9 +63,14 @@ Strict mode is the starting point, not an aspiration to migrate toward later.
- When you do suppress one, **say so explicitly in your report to the user** — name the
warning, where it is, and why it could not be fixed. A silent suppression is the failure
mode this rule exists to prevent.
- **Re-test suppressions periodically.** Removing an `#[allow]` / `// eslint-disable` /
`#pragma warning disable` that no longer suppresses anything should produce no warning —
if it doesn't, delete it. Stale suppressions accumulate and hide real regressions.
- **Every suppression carries a comment saying why.** A bare `#[allow]` / `// eslint-disable`
/ `# noqa` with no reason is indistinguishable from someone giving up, and nobody will ever
dare remove it.
- **Name the specific rule**, never a blanket suppression: `# noqa: S603`, not `# noqa`;
`//nolint:errcheck`, not `//nolint`.
- **Re-test suppressions periodically.** Removing one that no longer suppresses anything
should produce no warning — if it doesn't, delete it. Stale suppressions accumulate and
hide real regressions.
---