feat: compile-check's record store can keep the last changed-files check

Merged
HA
1d ago
+390-4

Summary

  • compile-check's record store can now keep what the last changed-files check of an assembly reported, so a later run can report it again instead of starting the worker.
  • No behaviour changes yet: nothing writes or reads the new record. The next PR wires it into the changed-files check.

User Impact

  • None in this PR. With the follow-up, running compile-check again on the same edit answers without checking the same files a second time.

Changes

  • A fourth record per assembly, <Assembly>.fastresult.json, next to <Assembly>.result.json, at format version 1. It holds the input key, the baseline's input key, the worker build key, and what the check reported: success, diagnostics, changed files, unchecked codes, and whether generators were not rerun.
  • The store's API gains one read and one write:
    type FastCheckResult[D any] struct { Succeeded bool; Diagnostics []D; ChangedFiles, UncheckedCodes []string; GeneratorsNotRerun bool }
    func (s Store[D]) ReusableFastCheck(assembly, key string, baseline Baseline[D], workerKey string) (FastCheckResult[D], bool)
    func (s Store[D]) RecordFastCheck(assembly, key string, baseline Baseline[D], workerKey string, result FastCheckResult[D]) error
    
  • ReusableFastCheck hands the record back only when all three keys match and the format version is this build's. An empty input key never matches, and an unreadable record counts as no record.
  • RecordFastCheck refuses to write without an input key, a baseline or a worker build. A record under an empty key could later match another empty key. It writes through a temporary file, like the other records.
  • Forget removes the new record as well, after the other three, so no check outlives the compile it was checked against.
  • The package comment lists the fourth record and its contract.

Verification

  • New tests in resultstore:
    • the record comes back exactly as written, with every field set;
    • another input key, baseline or worker build each stops the match;
    • another format version, an unreadable record, and an empty input key each stop it too;
    • each missing key is refused and writes nothing;
    • a failed rename leaves no temporary file;
    • Forget removes the record;
    • a golden test of the recorded bytes.
  • Mutations, each restored afterwards. Each fails exactly the matching test:
    • not comparing the baseline's input key;
    • not comparing the worker build;
    • not comparing the format version;
    • not refusing an empty input key on read;
    • accepting an empty worker build on write;
    • Forget keeping the record;
    • swapping two fields of the record.
  • 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.23% (baseline 94.2).
  • cli/release-automation: go test ./... passes. The file-length check passes.