Skip to content

Lint and audit projects in the build shards, and shard when checkers change - #822

Open
Vilin97 wants to merge 7 commits into
mainfrom
vasil/shard-validation
Open

Vilin97 wants to merge 7 commits into
mainfrom
vasil/shard-validation

Conversation

@Vilin97

@Vilin97 Vilin97 commented Nov 14, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #820 and #821 (their commits show here until they merge). This is the "use the spare runners" part of the CI speedup work.

Why

Lint and the quality audits reuse per-project pass receipts, so an ordinary PR validates only what it touches. But a change to any checker input (the workflow, validation_cache.py, quality.py, the no-lint lists, the pins) invalidates every receipt. One job then validates the whole pool, one project at a time. In run 42594711151 "Assemble and lint" spent 36.4 min in Lint and 67.8 min in Repository quality checks. The merge queue and the push to main repeat it.

In-job concurrency does not fix the lint half: #785 measured that one lint process already saturates a 4-vCPU runner (35 min with 4 concurrent units against 34 serially). The org has 60 concurrent runners and typically uses about 5.

What

  • Shards validate what they build. After uploading its build outputs, each shard job runs python -m lean_pool.shard_validation --units <its projects>: the per-project lint, declaration, axiom and option-backdoor checks, through the same functions the whole-pool run uses. It uploads only its pass receipts (ci-validation-NN).
  • finalize still decides. It merges the shards' passes (validation_cache merge) and then runs the unchanged Lint and Repository quality steps. Those recompute every fingerprint, reuse matching passes, and run anything without one, plus the repository-wide checks and the root unit. The shard validation and upload steps are continue-on-error, so a shard can neither fail nor pass the run by itself; a real failure is re-run and reported in finalize. A shard keeps the passes it earned even when one of its projects fails.
  • The planner fans out when checker inputs change, even with a warm build cache. Shards replay the build and spend their time validating. It reads the input list from validation_cache.py itself, with a test that it equals GLOBAL_INPUTS.
  • MAX_SHARDS goes from 10 to 14. Past that the costliest project (MovingSofa) fills a shard alone, so more shards stop lowering the maximum.

quality.py is not modified. No check changes what it accepts: a receipt only counts where finalize computes the same fingerprint for the same modules.

Relation to #785

#785 runs quality audits 4-wide inside one job (62 → 36 min) and is still open. The two are complementary, and both edit ValidationCache.check; whichever merges second needs the small units filter moved into the other's loop.

Verification (Azure VM, Lean v4.35.0)

  • Ran python -m lean_pool.shard_validation --units Champernowne on a real build: 4 fresh checks (lint, declarations, axioms, backdoors) in 28 s, every other unit skipped. After merge, a whole-pool cache re-validated none of that unit's lint, axiom or backdoor checks.
  • New tests cover the unit filter, shard runs keeping passes when one unit fails, merge by fingerprint (an edited project is checked again), corrupt fragments, the planner trigger, and the workflow contract (step order, continue-on-error, no cache saves in shards).
  • Full Python suite on the VM: 953 passed. The 5 failures (4 process-watchdog tests and test_repository_notice_is_current) fail the same way without this change in that environment.

This PR's own CI is the first real fan-out: it edits the workflow, so every receipt is invalid. Its shard and finalize timings are the measurement to compare against the 104 minutes above.

🤖 Generated with Claude Code

Vilin97 and others added 5 commits November 14, 2026 13:33
Lake writes a .setup.json compiler input per module listing absolute
artifact paths for every transitive import (~1.6 MB each, 46 GB of the
69 GB pool build). Lake never reads them back, and the validation cache
and exposition extractor only use keys naming local modules. Drop the
other keys after every CI build step so restores, saves, uploads, and
lint/quality fingerprinting stop handling the dead weight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both readers use only import names, and big projects list hundreds of
local imports with four absolute paths each (4.8 GB pool-wide).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Runs under the pinned-Lean CI step so a toolchain bump that starts
reading setup files back fails loudly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nt main

The build-time gate deleted the output of every file a PR changed relative
to main so each run would time it afresh. A PR adding a 1,300-file project
recompiled all of it on every push, in the merge queue, and on main.

- build_time_limits: `check` writes a per-module timing receipt bound to a
  hash of the module's .olean outputs; `prepare` only invalidates changed
  modules without a matching receipt; `check` judges the recorded time of
  reused output against the limit. Untimed output is still always rebuilt.
- ci_pr_build / rebase_fastpath: restore the unchanged-source modules of
  the PR's newest successful run instead of requiring identical sources;
  Lake's traces decide what is still valid. Shards restore them too.
- Workflow: measure a PR's changes from the tested merge commit's first
  parent. The event's base.sha can trail main by days, which made every
  project merged since count as changed and be rebuilt.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…change

A change to any checker input invalidates every validation receipt. One
job then linted the whole pool (~36 min) and audited it (~68 min), one
project at a time, on the PR, in the merge queue, and again on main.

- validation_cache: `shard --units ...` runs the per-project lint and
  quality checks for a shard's own projects and saves only its passes;
  `merge` adds shard passes to the assembling job's receipts.
- Workflow: each shard validates the projects it built and uploads its
  passes; `finalize` merges them before the unchanged Lint and quality
  steps, which recompute every fingerprint and run whatever has no pass.
- Planner: shard the whole pool when checker inputs change, even with a
  warm build cache; raise MAX_SHARDS from 10 to 14.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Proof profile (new / modified Lean files)

No added or modified Lean files under LeanPool/ in this PR. No compile-cost measurements are needed.

Advisory only — never blocks merge.

@greptile-apps

greptile-apps Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Advisory cross-file review against Lean Pool's supervisory rubric. This is not by itself a significance, source-verification, or merge verdict.

RetriggerView in Greptile

[Medium impact] The latest change appears safe to merge; both earlier import findings are fixed.

Summary

The PR spreads project lint and quality checks across build shards. finalize checks each receipt against current inputs and runs checks without matching passes.

  • Checker changes send project validation across parallel build shards.
  • Later PR builds reuse unchanged modules with recorded build times.
  • CI trims Lake setup files while keeping local import names.

Reviews (3) · Last reviewed commit: "Move a test import to the top of the fil..." · Reviewed by Greptile

Comment thread python/lean_pool/validation_cache.py Resolved
quality.py imports validation_cache.py, so the shard entry point could
only reach the quality checks through a function-level import. A separate
module imports both at the top. Its source joins the receipt fingerprints.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>

@Vilin97 Vilin97 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes needed at 64b3fad333f4171ea0b4a6dc994bfb46eafaa34c — the new shard-validation logic is supported, but the stacked timing repairs remain necessary.

I reviewed all eight complete incremental patches from PR821's 53136ce, their current cache/shard/planner/workflow implementations and the unchanged quality-check provider. I also reconciled the author's one-file import cleanup from c2bd07d to this head. Both existing import discussions are now resolved; I made no branch change.

The shard design preserves the final decision: unselected units issue no pass, only successful checks enter the used receipts, merging a fragment does not certify it, and unrestricted assembly recomputes fingerprints and runs missing checks. Global/root checks remain with assembly. In-memory execution of the published code confirmed exact-pass reuse, changed-input rechecking, rejection of malformed/failed receipts and the planner's agreement with all 16 current fingerprint inputs. This is source and contract evidence; it does not claim a hosted CI or Lean build.

The stack still contains both Source275 findings: the null-output receipt reader is unchanged, and assembly still excludes shard projects from both timing passes. Apply the non-null digest guard and remove the assembly exclusions, with the missing-output and fallback-over-limit regressions, before integration. The new parallel validation code does not repair those inherited timing gaps.

Fresh checks on the repaired head and the separately required direct gate/workflow authorization remain necessary. No older head's CI or advisory verdict is transferred here.

This branch has not been deployed

No deployments
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.

1 participant