feat(config): make the canvas-generation/version pairing a gate, not a habit (T-1242)
project.yaml's version is the Atlas disk cache's only invalidation signal, and nothing enforced that changing canvas GENERATION also moved it. It broke five times -- 0.4.2 lake_margin_q, 0.4.3 coast_warp_px, 0.4.4 the extent inversion, 0.4.5 the Global sentinel, 0.4.6 one-course-per-river -- each bumped only after someone noticed a wrong map. The failure is invisible to its author: it needs a warm cache to reproduce, so a cold checkout looks fine. T-1239 is the last one, and it took eight days. tooling/canvas_sources.py is the path registry; tooling/check-canvas-version rejects a push that touches those paths without moving project.yaml's version line. Wired into the pre-push hook, `make check-canvas-version`, and, for the parsing units, `make test-tooling`. Verified against real history rather than a synthetic branch: run over4e503c356-- the commit that actually caused T-1239 -- the gate rejects and names the three files. Run over the commits that DID bump (bdea71953,39f0fd8c5, and T-1239's own fix), it passes. The registry is globbed, not hand-listed. step_canvas.rs imports ten sibling modules and those import more, so a traced closure would be stale within a month, and stale here is silent. It over-includes on purpose: a false positive costs one bump and one round of cache misses, a false negative costs another week of a wrong map -- the ticket's own ruling. Two deliberate calls worth naming. The registry includes ITSELF, which closes the narrowing hole: remove a path and change that same path in one push, and the gate still fires because the registry file is in the set. And there is no override flag -- it would be reached for exactly when someone is certain their change is harmless, which is the reasoning behind all five regressions. Version bumped 0.4.6 -> 0.4.7 with NO canvas-generation change: self-inclusion means adding the registry trips its own rule. Spent rather than special-cased, because the first exception is how a rule like this dies. The units cover the property no branch run can show -- that editing project.yaml's comment block, which quotes old version NUMBERS directly above the field, is not a bump -- plus a registry-coverage test naming the files each of the five known regressions touched, so a future narrowing past them fails loudly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -298,6 +298,24 @@ if [ -f "$REPO_ROOT/tooling/check-client-version" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Canvas-generation / version pairing (T-1242) ---
|
||||
# A change to how a canvas is GENERATED is half a change; the other half is
|
||||
# bumping project.yaml's version, or every warm Atlas cache keeps serving
|
||||
# canvases built by code that no longer exists. That pairing broke five times
|
||||
# (0.4.2 through 0.4.6), every one bumped after the fact, the last costing the
|
||||
# eight-day T-1239 diagnosis. The path registry is tooling/canvas_sources.py.
|
||||
#
|
||||
# Self-check first: the registry fails closed on an empty glob, and a registry
|
||||
# that cannot load must not be read as "nothing to enforce".
|
||||
if [ -f "$REPO_ROOT/tooling/check-canvas-version" ]; then
|
||||
echo "pre-push: checking canvas-generation version pairing..."
|
||||
if python3 "$REPO_ROOT/tooling/check-canvas-version"; then
|
||||
:
|
||||
else
|
||||
fail_check "canvas generation changed without a project.yaml version bump"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- Clerk review (D-221) ---
|
||||
# DISABLED 2026-05-23 (#965) pending rework. Two problems made it net-negative:
|
||||
# 1. Non-exhaustive — a single run reports ~the first contradiction it finds
|
||||
|
||||
Reference in New Issue
Block a user