Skip to content

feat(lint): per-file allow-list in eigs.json (#455)#524

Merged
InauguralPhysicist merged 2 commits into
mainfrom
feat/lint-eigs-json-allowlist-455
Jul 9, 2026
Merged

feat(lint): per-file allow-list in eigs.json (#455)#524
InauguralPhysicist merged 2 commits into
mainfrom
feat/lint-eigs-json-allowlist-455

Conversation

@InauguralPhysicist

Copy link
Copy Markdown
Collaborator

What

The last residual of #399: a project can now silence a lint code for a whole file via eigs.json, without editing the file — the escape for generated or vendored modules a project shouldn't sprinkle # lint: allow comments through.

{ "lint": { "allow": { "lib/generated.eigs": ["W003", "W017"], "vendor/x.eigs": ["all"] } } }
  • Keys are project-root-relative paths; "all" silences every code.
  • Resolution walks up from the linted file to the project root (the dir containing eigs.json — the same walk the module resolver stops at), so it applies regardless of the cwd the linter runs from.
  • A code allowed here filters exactly like a # lint: allow-file <code> in the file.

Implementation

Reuses the public eigs_json_parse_value parser. The allow-list is read once per lint (not per warning) and is refcount-clean: incref the borrowed codes list before decref'ing the parsed manifest, decref after the filter loop — ASan leak-clean. Self-contained in src/lint.c; freestanding build unaffected (host-CLI-only path).

Scope is --lint. The in-file directives (# lint: allow / allow-file / loaded-by) still cover the LSP; wiring the eigs.json list into eigenlsp is a possible follow-up (the LSP works on in-memory buffers that may lack a saved path/root).

Verification

  • tests/test_lint.sh (5 new cases): suppress-listed-code, non-listed-file-still-fires, wrong-code-still-fires, "all", and cwd-independent root discovery.
  • Full suite green release AND ASan (detect_leaks=1): 2694/2694, 0 failed, no leak-tally increase.

Docs

Closes #455

🤖 Generated with Claude Code

InauguralPhysicist and others added 2 commits July 9, 2026 15:18
builtin_args returned argv directly, unwrapped — the last un-taped
nondeterminism source reachable by a pure script, and a hole in the
closed-world invariant behind deterministic replay. A program that
branched on `args` recorded a tape under one invocation and silently
diverged when replayed under a different argv — the exact class the
#408 task layer's chaos-mode `--seed N` scheduling would hit.

The recorded argument list now rides the tape as one N record and
replay serves it regardless of the live argv. Because `args` builds its
list before returning, it uses the TRACE_NONDET_TAKE / TRACE_NONDET_RECORD
pair (not TRACE_NONDET_RET): under replay the early TAKE short-circuits
before the list is built, so the live construction is neither run nor
leaked. The tape already round-trips a list of strings (parse_value_p),
so no serialization work was needed.

Regression: tests/test_replay.sh records under `A B`, then replays the
same script under `X Y Z` and asserts the recorded args win (and that a
live run under `X Y Z` differs, proving the tape actually overrides).
docs/TRACE.md gains a Process category and the TAKE/RECORD-for-builders
note; CHANGELOG under Unreleased.

Full suite green release + ASan (leaks on), 2689/2689, no leak-tally
increase.

Closes #471

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Residual of #399: a project can now silence a lint code for a whole file
via eigs.json, without sprinkling inline `# lint: allow` comments — the
escape for generated or vendored modules a project shouldn't edit.

    { "lint": { "allow": { "lib/generated.eigs": ["W003", "W017"] } } }

Keys are project-root-relative paths; "all" silences every code.
Resolution walks up from the linted file to the project root (the dir
containing eigs.json — the same walk the module resolver stops at), so it
applies regardless of the cwd the linter runs from. A code allowed here is
filtered exactly like a `# lint: allow-file <code>` in the file.

Implementation reuses the public eigs_json_parse_value parser; the allow
list is read once per lint (not per warning) and refcount-clean (incref
the borrowed codes list before decref'ing the parsed manifest, decref
after the filter loop) — ASan leak-clean.

Scope is `--lint`; the in-file directives still cover the LSP (noted as a
possible follow-up). Regression: tests/test_lint.sh — suppress-listed-code,
non-listed-file-still-fires, wrong-code-still-fires, "all", and
cwd-independent root discovery.

Full suite green release + ASan (leaks on), 2694/2694, no leak-tally
increase.

Closes #455

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@InauguralPhysicist InauguralPhysicist merged commit f8d5ee5 into main Jul 9, 2026
17 checks passed
@InauguralPhysicist InauguralPhysicist deleted the feat/lint-eigs-json-allowlist-455 branch July 9, 2026 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--lint: per-file allow-list in eigs.json (residual of #399)

1 participant