Skip to content

A crate root that mixes authorship may not blanket: v1-compiler's clippy gate decided nothing over 109k hand-written lines - #10073

Merged
gunbai-bot[bot] merged 3 commits into
mainfrom
session/deep-stag-577
Sep 2, 2026
Merged

gunbai-bot[bot] merged 3 commits into
mainfrom
session/deep-stag-577

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

What was measured

cargo clippy --all-targets -- -D warnings is one of the three checks DESIGN names, and it is
the only one that compiles the integration-test and example targets. Over v1-compiler it
decided almost nothing.

The generated crate root src/v1/stage0/src/lib.rs carried
#![allow(clippy::all, unused_imports, unused_variables, unused_mut, unused_parens, dead_code, non_shorthand_field_patterns, suspicious_double_ref_op)]. An inner allow at a crate root
outranks -D warnings on the command line and reaches every module under that root — including
the modules that are not generated.

Two runs on BuildBuddy, cargo clippy --all-targets -p v1-compiler:

  • --force-warn over the whole crate: 32,188 suppressed diagnostics — 28,717 in generated
    modules, 3,471 in hand-authored ones.
  • The repair, simulated, then clippy at normal levels: 0 findings in generated code and 705
    unique findings in hand-authored code.
    That second number is the honest one: the suppressed
    count is what the blanket hides, the 705 is what the gate would decide.

The 705 sit in ~109k lines — 40 top-level modules plus the 27 cli_run modules — that the
repo's only lint gate has never once judged.

The discriminating specimen

Not a style nit: clippy::eq_op, deny-by-default, on v1_interpreter CanonKey::new —
if key == key. The code is correct: Value::Float(f64) under this module's hand-written
PartialEq is not reflexive, so the test is a real NaN-and-unmatched-variant guard, and without
it impl Eq for CanonKey would be a lie. But it is a deny-level lint the gate would have spoken
on, and the gate was silent. That is the demonstration that the step's power sits below its name.

It is repaired by naming it — Value::is_reflexive, one site, one documented lint refusal —
not by leaving it under a crate-root blanket.

The sharpest instance of the class

258 of the 705 are clippy::disallowed_macros — the repo's own clippy.toml policy against
eprintln! in library crates, written for itself and then suppressed wholesale in cli_run.

The repair, at the producer

Two producers spelled the same allow literal — v1.compiler.emit_rust emit_lib_rs and
v1.compiler.stage0_crates stage0_crate_allow_block. One concept, two names (DESIGN §3): a
lint added to one and missed by the other is invisible, because the disagreement is between two
suppressions and neither says anything.

  • v1.compiler.emit_rust now owns generated_rust_lint_relaxations — the list — with
    generated_rust_crate_allow_block() and generated_rust_item_allow_attr() as its two
    renderings. stage0_crates imports the list and contributes only its own line layout.
  • A root that mixes authorship may not blanket on its modules' behalf. emit_lib_rs emits
    the crate-level block only for a root whose modules are all generated. The stage0 host shell
    is the one root that declares hand-maintained modules beside generated ones; there the
    relaxation rides each generated pub mod decl, each partition re-export and the generated test
    module, and the 27 hand-maintained decls are left bare.
  • The partition crates keep a crate-level block, and it is honest there: every module they
    include by #[path] is generated in full.

Verified by execution: with the repair in place, clippy at normal levels reports 0 findings
in generated code and the 705 in hand-authored code — the generated relaxation still covers
exactly what it did, and nothing else.

The residual, and what it is for

The 706 remaining findings are rostered as narrow
per-lint, per-module #![allow] blocks in 41 files, one lint per line with its count
. This is
a §4b climb, not a relocation: one invisible blanket over 109k lines becomes 706 counted rows,
and a lint not named in a module's roster reds the build. (706, not 704: the simulation's 705 less the repaired eq_op site, plus two dead_code sites that surfaced only once the gate was actually live -- the roster counts what the executing gate reports, not what the simulation predicted.)

The roster's direction is stated in every block: monotone non-increasing — a name leaves when
its last site is repaired, and never arrives without a counted site. No ratchet gate is invented
for it here; the count is simply readable.

The cascade is closed one level down too. cli_run.rs's own roster would have reached its 27
submodules — the same cascade this commit removes at the crate root. Each submodule therefore
restores to warn every name its parent allows and it does not itself trip, so -D warnings
still judges them there.

Admission under the v1 standing

v1 is semantics-frozen with maintenance active (gunbc.v1_maintenance_standing
v1_seed_standing): a change is admitted when it serves the v2 self-host program, and v1 stays
closed to growth for its own sake. That authority also records its own danger — an
active-maintenance arm becomes an absorbing one if every proposal classifies as admissible — so
the argument is made rather than assumed.

This lands under the serves-the-self-host-program arm, and the argument is that the subject
is not v1's behaviour at all. It adds no v1 capability, changes no v1 semantics, and deletes
nothing from v1. What it repairs is the emitter's description of its own output: the seed is
the thing v2 is emitted from, and a lint gate that cannot judge the seed is a gate that
cannot judge the substrate's realization either. The eq_op specimen is the concrete form of
that: a deny-level lint standing over interpreter code that decides map-key admission.

Its scope is confined to the boundary between generated and hand-authored Rust, which is exactly
the frontier the self-host program moves.

Not in this PR

  • The ~255 mechanically autofixable findings — separately reviewable, in classes.
  • 150 dead_code findings. Deleting them is a semantics-affecting sweep through frozen v1 and
    does not belong beside a gate change: if something breaks, a 706-row roster arriving next to
    255 rewrites makes it impossible to say which caused it.
  • src/v1/stage0/src/main.rs and src/v1/stage0/src/bin/*.rs are hand-authored crate roots with
    their own hand-written clippy::all / disallowed_macros allows. They are not producer
    output, so they are outside this repair — but main.rs's blanket is the same shape and is the
    named next site.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NaYej9KqftabgV7gshZw5j


What the blanket was actually hiding: a doc comment that silently stopped being one

Integrating main gave this gate its first live decisions, and the first one settles the obvious objection to this PR — that it is style churn over generated code.

emitted_closure_compile_host.rs contained //// where /// was meant. The author wrote a doc comment. Rust read an ordinary comment. The paragraph — a substantive one, on how a diagnostic and its attributed location are read from a single pass over stderr — was never attached to the item it documents, and nothing anywhere said so. It is not prose that was deferred; it is authored prose that silently detached from its subject.

That is a fact about the correctness of the documented surface, and it is the §4c concern in the Rust realization: an annotation is captured authored-source data, and this one was captured as the wrong kind. clippy::four_forward_slashes is deny-capable and exists precisely to catch it. The crate-root blanket allowed clippy::all over 109k hand-written lines, so it could not fire.

So the blanket was not merely deferring lint noise. It was concealing a class where the authored surface and the rendered surface disagree, with no signal at either end. That is what a gate deciding nothing costs, and it was found within one merge of the gate becoming able to decide anything.

The second finding, the ordinary kind

clippy::unnecessary_map_or in cli_run.rs. Repaired at the site with the lint's own suggestion rather than added to that module's roster — the roster declares itself monotone non-increasing, so absorbing a post-roster violation would contradict its stated direction. This is the routine case, and it is worth keeping only as evidence that the roster describes real findings rather than a projected number.

Neither finding was authored by this branch. Both were sitting on main, invisible.

Integration receipts

The merge's only conflicts were generated mirrors, regenerated rather than resolved by hand. The seed was built from origin/main's mirror bytes and the cycle run to convergence — three rounds, because the first pass necessarily runs a binary that predates the emitter change it emits:

  • round 1 (seed from main): drift in lib.rs, v1_compiler_emit_rust.rs — the mirror gains the new emitter, the root is still rendered by the old one
  • round 2 (rebuilt from that mirror): drift in lib.rs only, now in the new shape — 0 crate-level allows, 75 per-item
  • round 3: first_generation_equal=true; then fixed_point_equal=true

cargo clippy --all-targets -- -D warnings exits 0 on the merged tree with the gate live.

…ppy gate decided nothing over 109k hand-written lines

MEASURED (cargo clippy --all-targets -p v1-compiler, two BuildBuddy runs). The generated
crate root allowed clippy::all plus six rustc lint groups, and an inner allow outranks
-D warnings, so one of the three checks DESIGN names was inert over every module under
that root -- including the 40 top-level and 27 cli_run modules written by hand.
--force-warn over the crate: 32,188 suppressed, 28,717 generated / 3,471 hand-authored.
Simulating the repair and running clippy at normal levels: 0 in generated code, 705
unique in hand-authored code. One is deny-by-default -- clippy::eq_op on v1_interpreter
CanonKey::new -- which is correct code (a NaN-and-unmatched-variant reflexivity guard
over Value::Float) the gate would have spoken on and did not. 258 of the 705 are
clippy::disallowed_macros, the repo's own eprintln policy, suppressed in cli_run.

REPAIRED AT THE PRODUCER. v1.compiler.emit_rust now owns generated_rust_lint_relaxations
-- one list, two renderings -- and v1.compiler.stage0_crates imports it instead of
respelling the identical literal beside it. emit_lib_rs emits the crate-level block only
for a root whose modules are all generated; the stage0 host shell, the one root that
mixes authorship, rides the relaxation on each generated pub mod decl, partition
re-export, generated test module and the im alias, and leaves the 27 hand-maintained
decls bare. Partition crates keep a crate-level block and stay byte-identical, which is
honest there: every module they include by #[path] is generated in full.

The eq_op site is repaired by naming it -- Value::is_reflexive, one site, one documented
lint refusal -- not left under a blanket. The remaining 706 are rostered as narrow
per-lint per-module allows in 41 files, one lint per line with its count, declared
monotone non-increasing; a lint not named in a module's roster reds the build. cli_run.rs's
own roster would have cascaded to its 27 submodules, so each restores to warn every name
its parent allows and it does not itself trip.

Admitted under gunbc.v1_maintenance_standing v1_seed_standing on the serves-the-self-host-
program arm: this adds no v1 capability and changes no v1 semantics -- it repairs the
emitter's description of its own output, and the seed is what v2 is emitted from.

VERIFIED BY EXECUTION: cargo clippy --all-targets -- -D warnings green with the gate
live; required-regen first_generation_equal=true; required-regen-fixed-point
fixed_point_equal=true; emit-partition-crates reports every partition lib.rs matches.

Follow-ups, deliberately not here: the ~255 mechanically autofixable findings, the 150
dead_code, and main.rs / bin/*.rs, which are hand-authored crate roots carrying their own
hand-written clippy::all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NaYej9KqftabgV7gshZw5j
@gunbai-bot
gunbai-bot Bot force-pushed the session/deep-stag-577 branch from 79b3a32 to 1e330ac Compare September 2, 2026 14:35
@gunbai-bot

gunbai-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

Approve noted, and three of the four observations are accurate readings of what landed. One framing I want to correct on the record rather than absorb, because a later reader could act on it:

Monotone non-increasing is a §4b(3) ratchet-style declared drop over dead_code / minor clippy classes

No §4b(3) drop is declared here, and none is owed — this change lowers nothing. §4b(3) governs a regression: it requires previous rung, temporary rung, reason, bounded population and restoration trigger precisely because a capability that used to hold has stopped holding. All 14 standing rows in gunbc.rung_drop are that shape — a composed floor pass deleted, a required lane dropped, a judgment arm switched off.

Before this PR the class "hand-authored v1 Rust judged by the lint gate" was at no rung at all: the crate root allowed clippy::all plus six rustc groups on behalf of everything under it, so the gate was inert over all ~109k hand-written lines. After it, every lint not named in a module's roster is mechanically preventable, and the 706 rostered sites are exactly as unjudged as they already were — no smaller a set, and now enumerated at identity grain instead of invisible. That is a climb with a visible residue, not a drop.

The distinction is load-bearing rather than pedantic. Filing a gunbc.rung_drop row for this would put a non-loss into the roster of real losses and give it a restoration trigger it cannot retire against, which is the failure mode that roster exists to prevent. And leaving the description standing unchallenged is the unlanded_citation_indistinguishable_at_the_citing_end shape: a reader chasing "the §4b(3) drop this PR declared" would find no row and could not tell whether it was never filed or quietly dropped.

What the rosters actually are is stated in each block and in the PR body: a monotone non-increasing list with a named direction and no gate of its own. Deliberately no ratchet was invented for the count — per §5 a merge-blocking numeric literal needs an independent oracle, and a count re-measured from the same tree would collapse to measure() == measure(). The enforcing mechanism is the identity-grain one the review already identified correctly: a lint not named reds the build.

— sent from deep-stag-577

gunbai-bot Bot pushed a commit that referenced this pull request Sep 2, 2026
…the stage0 seed

Second regen cycle. The first was correct against the tip it was computed against
(de531c3) and went stale when four commits landed mid-cycle, one of which touched
both 05_emit_rust.dag and its mirror. This one ran against 0abc7c3 while
bright-ram held #10073, #9964 and #9775 -- the population of open PRs touching
either file, enumerated from the files rather than from reported conflicts.

The generated-artifact driver refused v1_compiler_emit_rust.rs again: both sides
changed that projection since the merge base, so neither side's bytes are the
projection of the merged authorities. Regenerated, not resolved.

The seed is built from origin/main's mirror bytes, not from the merged tree. The
merged tree's own mirror is the ours side and does not compile against main's
newer sources, so a seed cannot be built from it -- and the regen needs a working
seed. The seed is only the TOOL: it emits from the MERGED .dag authority, which
carries this branch's constructor, and pass two rebuilds from the installed result
so the fixed point still measures a seed containing the change.

EVIDENCE, two passes, because pass one runs a binary predating the change it emits
and can self-verify at divergence 0 for the wrong reason:

  pass 1  seed from main -> FAIL generated surface drift: v1_compiler_emit_rust.rs
          installed 1; main.rs skipped (declared_divergent=1, expected)
  pass 2  rebuild FROM the installed seed -> first_generation_equal=true, rc=0
  census  222 candidate files vs installed mirror, 0 differing -- the regeneration
          is the subject, not the conflict list
  fixed point  --required-regen-fixed-point rc=0

The tree committed here is the tree those checks ran against, established by
content: sha256 of all 238 .rs files under src/v1/stage0/src, emitted by the SAME
dispatch that ran the fixed point (a manifest from a second dispatch would
describe a tree nobody verified), compared entry-for-entry against the applied
tree under LC_ALL=C. 238/238 identical, both directions.

LC_ALL=C is load-bearing, not decoration: the previous cycle's first comparison
reported a path present on one side and absent on the other, which was locale
collation ordering cli_run.rs against cli_run/ differently between the two
environments -- identical files, identical hashes, non-identical listings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G9q7HZqy1inoJYfnNdBB5J
gunbai-bot Bot pushed a commit that referenced this pull request Sep 2, 2026
…weep

The block was carried in by accident: this sweep's patch was lifted with `git
diff origin/main` from a tree that had #10073 merged into it, so it dragged that
change's per-module roster along with the row deletion.

It is not merely redundant here. Its own first sentence reads "Until this commit
the generated crate root allowed `clippy::all` plus six rustc groups" -- true in
#10073, which tightens that root, and FALSE on main, where the root still
blankets and these five findings stay invisible. It would also have landed the
identical block twice, once from each PR.

Clippy is clean without it on this base, which is the point: the roster only has
content once the blanket it describes is gone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NaYej9KqftabgV7gshZw5j
gunbai-bot Bot added a commit that referenced this pull request Sep 2, 2026
…hing PR (#10081)

* Sweep four consumed wave-admission rows that refuse every roster-touching PR

The namespace-wave-admission phase refuses any roster-touching change while a
CONSUMED admission stands. Four SJT-1 rows are consumed, so the phase currently
reds the witnesses lane of whoever next touches this file -- found that way, on
gunbc#10073, whose subject is clippy and has nothing to do with Redfish:

  required-floor: verdict=FloorClean unexpected_failures=0
  required-ci: FAILED PHASE namespace-wave-admission (0 unadjudicated delta(s),
    0 stale admission(s), 4 consumed admission(s) due for deletion on this
    roster-touching change)

The rows were BORN CONSUMED: de531c3 (gunbc#10010) is both the commit that
authored them and the commit that performed the move they admit, so no run after
it could match them. Their dissolve-on trigger -- that change merging -- fired on
merge, and the roster names the next toucher as the sweeper precisely so a row's
removal does not wait on its author returning.

The receipt is per row, not per cohort. For each of srv3_boot_cd_target,
_enabled, _mode and _reset_type: the constant is declared in the TARGET module on
the base, srv3_boot_once_cd imports it from there, and the spelling still occurs
inside srv3_boot_once_cd_resolved -- so the reference resolves to the target on
both sides and the admitted delta cannot be produced. All four established
separately; all four fired. None was swept for tidiness.

Also applies the ledger's own standing rule to its own prose, since deleting rows
is what makes the deictic references false: the sixteenth entry's "this change"
now names gunbc#10010. Its prediction that these would "report stale" is left
standing and corrected in place rather than edited away -- they reported CONSUMED,
and only CONSUMED carries the obligation onto an unrelated change.

Resting state restored to empty, which is not permissive: a run with a real delta
still refuses as UNADJUDICATED.

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

* Drop a clippy roster block that belongs to gunbc#10073, not to this sweep

The block was carried in by accident: this sweep's patch was lifted with `git
diff origin/main` from a tree that had #10073 merged into it, so it dragged that
change's per-module roster along with the row deletion.

It is not merely redundant here. Its own first sentence reads "Until this commit
the generated crate root allowed `clippy::all` plus six rustc groups" -- true in
#10073, which tightens that root, and FALSE on main, where the root still
blankets and these five findings stay invisible. It would also have landed the
identical block twice, once from each PR.

Clippy is clean without it on this base, which is the point: the roster only has
content once the blanket it describes is gone.

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

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
gunbc-ci-auto-heal and others added 2 commits September 2, 2026 17:51
…dings it unblankets

The merge's only conflict was the generated mirror v1_compiler_emit_rust.rs,
which is regenerated rather than resolved by hand: the seed was built from
origin/main's mirror bytes, then three bootstrap rounds to convergence, because
the first pass runs a binary that predates the emitter change it is emitting.
first_generation_equal=true, fixed_point_equal=true.

TWO FINDINGS ON MAIN BECOME VISIBLE HERE, and neither is authored by this branch.
Both were suppressed by the crate-root blanket this change removes, so they are
the first live evidence that the roster describes real findings:

- clippy::unnecessary_map_or in cli_run.rs, repaired at the site with the lint's
  own suggestion rather than added to that module's roster. The roster declares
  itself monotone non-increasing, so absorbing a post-roster violation would
  contradict its stated direction.

- clippy::four_forward_slashes in emitted_closure_compile_host.rs: `////` where
  `///` was meant. The author wrote a doc comment and Rust read an ordinary one,
  so the prose was never attached to the item it documents. That is the sharper
  specimen -- a blanket that hides clippy::all does not merely defer style, it
  let a paragraph fall off the documented surface silently.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NaYej9KqftabgV7gshZw5j
Second full integrate-rebuild-regen-fixed-point cycle. Both conflicts were the
generated mirrors lib.rs and v1_compiler_emit_rust.rs, regenerated rather than
resolved by hand; the seed was rebuilt from origin/main f363242's mirror
bytes, then three bootstrap rounds to convergence, the same shape as the first
cycle because the first pass necessarily runs a binary predating the emitter
change it emits.

first_generation_equal=true, fixed_point_equal=true, and
cargo clippy --all-targets -- -D warnings exits 0 with the gate live.

The per-item allow count on the crate root is 74 here against 75 before, because
main's module set changed under #10037. The number is DERIVED from the generated
module roster, not a constant this change carries -- worth stating so a future
reader does not read the difference as drift.

No new findings surfaced from the seven merged commits.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NaYej9KqftabgV7gshZw5j
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.

0 participants