Skip to content

Enforce diagnostic-tagging discipline: pre-commit hook + backfill of 76 partial sites #682

@aallan

Description

@aallan

Finding

spec/00-introduction.md §0.5.1 says every diagnostic MUST include description, rationale, fix, and spec_ref. Live state at HEAD 08c1197:

Surface Total self._error / self._warning calls Fully tagged
vera/checker/expressions.py 21 3
vera/checker/calls.py 20 2
vera/checker/control.py 17 4
vera/verifier.py 9 3
vera/checker/core.py 7 4
(others) 24 6
Total 98 22 (22%)

Of the 76 partially-tagged sites, 75 are missing fix=, 44 are missing rationale=, 44 are missing spec_ref=.

This shows up in real output. Example: E140 (operator type mismatch on numeric operands) produces description + rationale + spec_ref but no Fix: paragraph — exactly the kind of error where a Fix (showing a conversion or a type-correcting move) is the cheapest possible signal for the model.

$ vera check wrong_type.vera
[E140] Error at wrong_type.vera, line 4, column 3:
      @Bool.0 + @Int.0
      ^

  Operator '+' requires numeric operands, found Bool and Int.

  Arithmetic operators work on Int, Nat, or Float64.

  See: Chapter 4, Section 4.3 "Operators"

No Fix: paragraph. Compare with E001 / E122 / E130 / E500, all of which are fully curated.

Suggested fix — mechanical, two-pass

Pass 1: enforcement going forward

Add a pre-commit hook (extending the scripts/check_walker_coverage.py pattern) that parses every Diagnostic(...) constructor and every self._error(...) / self._warning(...) call in vera/, and fails if any of them is missing rationale=, fix=, or spec_ref=.

Defensive / internal-only errors (e.g. Unknown expression type in expressions.py fallback branches) can opt out per-call with # noqa: diag-fields comment carrying an inlined reason — mirroring how the walker-coverage check handles its categories.

Pass 2: backfill the existing 76 partial sites

Once the hook exists, run a one-pass cleanup across checker, verifier, and codegen call sites to populate the missing fields. Error codes are stable; spec sections are stable; Fix patterns follow predictable categories. Single PR of mostly-mechanical work, possibly split by phase (parse / type / verify).

Acceptance criteria

  1. New script scripts/check_diagnostic_fields.py parses every Diagnostic(...) constructor and _error() / _warning() call in vera/ and fails when any of rationale= / fix= / spec_ref= is missing without an opt-out marker
  2. Hook runs in CI on every PR + pre-commit
  3. Opt-out is per-call with # noqa: diag-fields and the reason must be inlined as a sibling comment
  4. All existing _error / _warning call sites in vera/checker/, vera/verifier.py, and vera/codegen/ either populate all three fields or carry an opt-out marker with rationale
  5. vera check wrong_type.vera (where wrong_type.vera mixes @Bool.0 + @Int.0) produces a Fix: paragraph

Estimated effort

A day for the hook + audit script. 2–3 days for the backfill PR, splittable into smaller phase-scoped PRs.

Related

Origin

Surfaced by a strategic compiler review on 2026-05-18 (v0.0.155). Marked P1 (quality, load-bearing claim — "diagnostics as instructions" is a core differentiator). All counts independently verified before filing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttoolingIssue around tooling built for the language (e.g. package managers, IDE plug-ins)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions