Skip to content

AGENTS.md: add a verification-discipline section #356

Description

@ptr727

Proposal

Add a Verification Discipline section to AGENTS.md covering the checks that separate work actually done from work that merely reports success. Implemented and in use at ptr727/ESPHome-NonRoot#165; raising it here because none of it is repo-specific.

The unifying property: each failure below is green. A skipped job and a passing job are indistinguishable in the aggregator; a pattern that matches less still exits zero; a gate that stops gating still reports success. Nothing in the existing lint, review, or status-check layers catches any of them.

Where it fits against what already exists

Three adjacent rules already cover narrower cases, so this complements rather than duplicates them:

  • "Running the Linters Locally" documents how to invoke each linter, not the rule that all of them run before every push.
  • The changes-job note ("must succeed, not just not-fail... silently skipped") is the aggregator-specific instance of the general "green is not evidence" rule.
  • The line-endings section covers preserving endings and notes file is unreliable, but not the regex mechanism that corrupts them.

Proposed rules

New, not covered anywhere today:

  1. A test must assert the mechanism it names. Label each case by the behavior it proves, and satisfy yourself it would fail if that mechanism broke. A case that passes for an incidental reason - the right answer reached by the wrong path - is worse than no case, because it is later cited as evidence. (This one caused a real defect: a gate test passed because the branch happened to contain a matching file, not because the fail-open path worked. It was cited twice as proof before review found the gap.)
  2. Gates, filters, and gate-like watchers must fail loud, never narrow quietly. A pattern that silently matches less, an allowlist that silently stops matching, or a gate that silently stops gating all report success while doing nothing. When a construct exists to notice something, make the not-noticing case produce an error or an annotation.
  3. Run the repo's whole lint gate before every push, not the parts that look relevant. CI runs all of them, so a partial local run only defers the failure - and the tool most likely to catch a given change is often the one it seems least about (an edit that manipulates line endings is exactly when editorconfig-checker matters).
  4. Editing CRLF files programmatically: . matches \r in a regex, so a captured line keeps its carriage return and rejoining with \r\n yields CRCRLF. Prefer line-based edits (splitlines(keepends=True)) or literal replacement over regex reassembly. This is the mechanism behind the existing "a programmatic edit can silently flip endings" warning, and it is worth naming because the corruption is invisible in a diff.

Generalizations of rules that exist in narrower form:

  1. A green check is not evidence the work happened. A skipped job and a passing job are indistinguishable in the aggregated required check. When a job exists to exercise something, confirm from its log that it ran and produced the output it promises. (Generalizes the changes-job note beyond that one job.)
  2. A workflow change is only fully exercised by CI. Extracting a run: block and executing it locally validates the script and nothing else - secrets: inherit, permissions:, needs: wiring, and reusable-workflow inputs are only resolved by a real run. (Complements the existing permissions-before-if: and success/skipped allowlist notes, which are instances of the same class.)

Also worth considering

The README Rules index could carry one or two of these under Always - "Run the full lint gate before pushing" and "Make gates fail loud, never narrow quietly" are the two that read as fleet-wide invariants rather than technique. That would need the Table of Contents updated to match.

Reference implementation

ptr727/ESPHome-NonRoot#165 has the wording as merged, if it is easier to adapt than to rewrite.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions