Skip to content

The base quality rules ask for a strict type checker, a linter and a formatter - #2440

Merged
braboj merged 9 commits into
mainfrom
feat/static-checks
Nov 9, 2026
Merged

braboj merged 9 commits into
mainfrom
feat/static-checks

Conversation

@braboj

@braboj braboj commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

core/quality.md, which every chain loads, gains a "Static checks" section. Until now no template asked for a type checker, and the linter rule loaded only when adding a check.

Where What changed
templates/core/quality.md New "Static checks": strict type checker, annotated public signatures, linter and formatter, run before commit and in CI
docs/architecture/08-crosscutting-concepts.md Generated context-cost table: +67 words a root, regenerated

Why, from the efficacy benchmark, round 5e:

Arms Type errors per KLOC
Root names mypy --strict from the project brief 4 to 13
Templates alone 63 to 89
No file 99
  • Stack-neutral: no language or tool named, so each rule passes the waist test (ADR-050)
  • py tests/run.py all: 3 suites, 0 failed

Closes #2439

Also: this repository runs the three checks on itself. Until #2441 cleans the tooling (P1, before v3.0), the check reports its findings without failing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DpT5xSQaG8RrSCyeihaQsm

@braboj braboj added the changelog:added Changelog section: Added label Nov 9, 2026
braboj and others added 2 commits November 9, 2026 09:10
…here under a generated freeze

core/quality.md's static-check rules gain a fenced check with placeholders
and a pass condition. This repository adopts them: mypy strict and the
ruff formatter under a freeze tools/freeze_static.py writes into
pyproject.toml from their own output, and pyflakes as the linter. CI
installs the three, pinned to minor ranges, and fails on a stale freeze.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpT5xSQaG8RrSCyeihaQsm
@braboj

braboj commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator Author

Codex round 1: one finding, fixed in the two commits above.

Sev Finding Fix
P2 The new static-check rules had no runnable check A fenced check with placeholders and a pass condition; its disposition runs it here

Fixing it showed this repository broke its own new rule (no type checker, no formatter). Owner's choice: keep the rules MUST and adopt them here.

  • mypy strict and the ruff formatter, under a freeze tools/freeze_static.py writes into pyproject.toml from their own output
  • pyflakes stays the linter
  • CI installs the three (minor-range pins) and fails on a stale freeze
  • Clearing the freeze: Fix the tooling's type errors and unformatted files before v3.0 #2441 (38 modules, 1,384 errors; 40 files)
  • py tests/run.py all: 3 suites, 0 failed; every other CI gate passes locally

braboj and others added 2 commits November 9, 2026 09:22
…nd setup lists the checkers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpT5xSQaG8RrSCyeihaQsm
…tooling

The type checker and the formatter now run over every file. Until the
tooling is cleaned (#2441), conformance's static check fails here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpT5xSQaG8RrSCyeihaQsm
@braboj

braboj commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator Author

Codex round 2: three findings.

Sev Finding What became of it
P2 Regenerating the freeze could add a newly failing file Moot: the freeze is dropped
P2 A failed checker run read as no findings Moot: the freeze is dropped
P2 Local setup did not list mypy, ruff and pyflakes Fixed: CONTRIBUTING.md Setup lists them with versions

Owner's choice: no freeze. The static checks read the whole tooling, so conformance's static check fails until #2441 lands; #2441 is P1 in the v3.0 milestone.

@braboj

braboj commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator Author

Codex round 3: one finding, P1, the static check fails on the existing tooling. By design: the owner chose no freeze and accepted conformance failing until #2441 (P1, v3.0 milestone) cleans the tooling. Not fixed here.

… until the tooling is clean

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpT5xSQaG8RrSCyeihaQsm
@braboj

braboj commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator Author

Owner's choice after round 3: the static check reports, and does not fail, until #2441 cleans the tooling. main stays green.

  • Disposition: expect: [READ], so every finding line is a reading in the conformance report, never scored
  • Each command ends || true, as the runner fails any nonzero exit
  • Fix the tooling's type errors and unformatted files before v3.0 #2441 restores the gate: expect: [] and no || true
  • py tests/run.py all: 3 suites, 0 failed; the report carries the findings

…assing

With the exits ignored, the check reported PASS over the tooling's type
errors and added nothing to the count awaiting a reading. It is now a
manual, budgeted reading, so the run says it is not clean yet. The runner
refuses an entry that ignores an exit with `|| true` unless it is manual.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpT5xQWkHtQPrPyMoXzWMG
@braboj

braboj commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator Author

Codex round 4: one finding, fixed in a87085f.

Severity Finding What became of it
P2 The report-only static check read as PASS over real type errors, and added nothing to "awaiting a reading" Fixed

The fix:

  • The check is now manual, and its title is in reading-budget.txt
  • A run says "1 reading still to read, so this run is not clean yet"
  • The runner refuses any entry that ignores an exit with || true unless it is manual
  • Once the tooling is clean the check prints nothing and fails, which prompts Fix the tooling's type errors and unformatted files before v3.0 #2441 to restore the gate

Before and after, py tests/run.py conformance "<type-check-command>":

before: 1 passed  ...  0 awaiting a reading
after:  0 passed  ...  1 awaiting a reading   (budgeted)

Without the disposition change, the runner's new rule fails the run.

py tests/run.py all: 3 suites, 0 failed. Codex round 5 is next.

`|| true` ignored every exit, so a bad configuration or a crash read as a
budgeted finding. The static checks now carry only the findings exit (1)
past, and any other exit stops the block with it. The runner refuses a
substitution that uses `|| true`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpT5xS97qSXAAX4YJ54Tvz
@braboj

braboj commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator Author

Codex round 5: one finding, fixed in 29d0e52.

Severity Finding What became of it
P2 || true also hid a checker that could not run (bad config, crash), so it read as a budgeted finding Fixed

The fix:

  • Each static command ends in FINDINGS_ONLY instead of || true
  • Exit 1 (findings) is carried past, so the check stays a budgeted reading
  • Any other exit stops the block with that code, so the check fails
  • The runner now refuses a substitution that uses || true

Before and after, a block whose first checker crashes:

before: (exit 2) || true; (exit 1) || true      -> exit 0, budgeted REVIEW
after:  (exit 2) FINDINGS_ONLY; (exit 1) ...    -> exit 2, check fails

Without the change to the entry, the runner's new rule fails the run.

py tests/run.py all: 3 suites, 0 failed. Codex round 6 is next.

A checker missing from the interpreter exits 1 with "No module named ...",
the same exit as findings, so it read as a budgeted finding. Each command
now imports its checker first and stops the block with exit 2 when it is
absent. The runner refuses a findings-exit substitution without that
import.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DpT5xS97qSXAAX4YJ54Tvz
@braboj

braboj commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator Author

Codex round 6: one finding, fixed in 28a3d8d.

Severity Finding What became of it
P2 A checker missing from the interpreter exits 1 ("No module named ..."), the same as findings, so it read as a budgeted finding Fixed

The fix:

  • Each command now comes from findings_only(python, module, args)
  • It imports the checker first, and exits 2 if that fails
  • The runner refuses a findings-exit command with no import first

Before and after, with the checker not installed:

before: python -m nosuchchecker x  || {...}   -> exit 0, budgeted REVIEW
after:  python -c "import nosuchchecker" || exit 2; ...   -> exit 2, fails

Without the change to the entry, the runner's new rule fails the run.

py tests/run.py all: 3 suites, 0 failed. Codex round 7 is next.

@braboj

braboj commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator Author

Codex round 7: no findings. Smoke, conformance, doc sync and the quality ratchet pass; three readings wait as intended, the static checks among them. The review loop is done; the PR waits on the owner.

@braboj
braboj merged commit 589f0d2 into main Nov 9, 2026
16 checks passed
@braboj
braboj deleted the feat/static-checks branch November 9, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog:added Changelog section: Added

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The base quality rules ask for a strict type checker, a linter and a formatter

1 participant