fix: compile-check keeps the records of assemblies it blocks

Merged
HA
10h ago
+195-56

Summary

  • After an assembly had errors, the first run where it compiled again no longer rebuilds everything below it when its public surface came back the same.

User Impact

  • Before: a run where an assembly had errors blocked the assemblies below it and also deleted their outputs and records. The next successful run then compiled every one of those dependents again. On a project with 561 assemblies, an assembly with 18 dependents cost about 10 extra seconds each time this happened (3 of 32 runs in one session of real use). It happened both after a full compile with errors and after a typo the changed-files check reported.
  • After: the blocked assemblies keep their outputs and records. When the assembly with errors comes back with the same reference assembly, its dependents are reused, or checked on their changed files when they were edited. When it comes back with a different public surface, they compile as before.

Changes

  • A blocked assembly is no longer cleaned up. It is still listed in BlockedAssemblies, and everything below it is still blocked.
  • Why keeping them is safe:
    • Nothing in the blocking run reads them: every assembly that references a blocked one is blocked too.
    • A later run uses them only after its usual checks. A replayed compile needs the same input key, which reads a reference this run rebuilds by content, and outputs that still hash as recorded. A changed-files check needs the baseline's compile result on disk and the same non-source key.
  • Assemblies skipped because their references kept Unity's public surface are still cleaned up, so the assemblies below them read Unity's build.
  • The compile-check doc and skill no longer say a blocked assembly loses its baseline.

Verification

  • Inverted pin: TestCompileUnitsBlocksTheDependentsOfAnAssemblyThatFailedToCompile now requires the blocked unit's earlier output to stay.

  • Replaced test: TestBaselineRemovedByBlockedRunIsNotCalledNeverCompiled is now TestBlockedRunKeepsTheBaselineOfTheBlockedAssembly. A body edit in the blocked assembly is answered by the changed-files check once the reference comes back the same.

  • New tests:

    • a blocked dependent is reused when its reference comes back with the same bytes;
    • it is compiled again when the reference comes back changed;
    • after a typo the changed-files check reported, fixing it, or undoing it, leaves the blocked dependent reused.
  • Before the fix, every new or changed test failed except the "reference comes back changed" one, which describes behaviour that does not change.

  • Mutations, each restored afterwards:

    MutationFails
    Remove the blocked unit's outputs and records againthe inverted pin, the four reuse / baseline tests
    Remove only its recordsthe four reuse / baseline tests
    Remove only its outputsthe inverted pin, the four reuse / baseline tests
    Key a rebuilt reference without its contentthe "reference comes back changed" test (and the existing input-key test)
    Stop blocking what is below a blocked unitthe inverted pin
  • cli/dispatcher:

    • golangci-lint fmt --diff is empty; go vet ./... passes; golangci-lint run and the complexity config both report 0 issues.
    • go test ./... and go test -race ./internal/compilecheck/... pass.
    • Coverage with the CI exclusions: 94.26% (baseline 94.2).
  • cli/release-automation: go test ./... passes; check-skill-size passes; the file-length check passes.

  • scripts/sync-tool-docs.sh --check reports no drift.

  • Repository CI does not run on pull requests into this branch; the checks above were run locally.