# CODING_STANDARDS.md Standards every engineering role (Backend, Frontend, ML, QA, Security, DevOps) is held to, and every reviewer enforces. These exist so a reviewer never has to guess what "good" means on this team, and so code from five different engineering roles reads as one coherent codebase. ## Formatting - Use the formatter/linter already configured in a given project's repository — don't hand-format against personal preference. If a project has no formatter configured yet, that's a gap the DevOps or Architect role should close, and it gets recorded as a Task, not silently worked around per-PR. - Auto-formatting runs before a commit, not as a separate cleanup PR. Formatting-only diffs mixed into a feature PR make review harder — keep them separate if a reformat is genuinely needed. ## Testing - New behavior ships with tests that verify that behavior — not tests that verify the implementation happens to do what the implementation does. A test should fail if the feature is broken, not just if the code is edited. - Bug fixes include a regression test that fails without the fix and passes with it. A bug fix PR without one is incomplete. - Never report a test suite as passing without having run it (`EMPLOYEE_HANDBOOK.md`). This is restated here because it is the standard most tempting to shortcut under time pressure, and the most damaging to shortcut. - QA verification (`WORKFLOW.md`) checks against acceptance criteria, which may go beyond unit tests — an engineer's own tests passing is necessary, not sufficient, for QA sign-off. ## Documentation - Public functions/APIs/modules get documentation proportional to how non-obvious they are — not a docstring on every function regardless of whether it adds information. - A PR that changes behavior described in a project's `PROJECT.md`, an ADR, or a role's handbook-level doc updates that doc in the same PR, or opens a follow-up Task explicitly if it can't (see `COMPANY.md` values — documentation is a deliverable). ## Comments - Default to no comments. Well-named code explains what it does. - Write a comment only when the *why* isn't obvious from the code itself: a non-obvious constraint, a workaround for a specific external bug, an invariant a future editor could easily break without knowing it's there. - Never write a comment that only restates what the next line does, references a specific Task ID as the reason code exists ("added for LOC-142"), or narrates a change that's already visible in Git history. ## Naming - Names should make comments unnecessary. If a reviewer has to ask "what does this variable hold," that's a naming problem to fix, not a documentation gap to fill. - Match the existing naming convention of the project/language you're working in over introducing a new one mid-codebase, even if you'd have picked differently starting fresh. ## Architecture - Don't introduce a new abstraction, dependency, or pattern for a single use case — three similar lines beat a premature abstraction (this applies to AI-written code exactly as much as human-written code). - Architectural changes that affect more than the current Task's scope go through the Architect and get recorded as an ADR (`DECISIONS.md`) before implementation, not after. - Don't build a fallback, feature flag, or backwards-compatibility shim for a scenario that can't currently happen. Solve the problem you have. - Validate at system boundaries (user input, external APIs, cross-service calls). Trust internal code and framework guarantees rather than defensively re-checking them everywhere. ## Scope discipline A Task's PR does what the Task describes — it doesn't drift into adjacent cleanup, refactoring, or "while I'm in here" changes. If you notice something else worth fixing while working a Task, flag it (a comment on the Task, or a new Task) rather than silently expanding the current PR's diff. Reviewers should push back on scope creep in a PR even when the extra change is itself good — it belongs in its own Task.