Five cases, including the failure path that matters — this is the gate with
five shipped regressions behind it.
A fixture repo does not work here, and finding out why exposed a real
inconsistency in the port: canvas_sources globs from a __file__-derived root,
so under SR_REPO_ROOT the service would diff the fixture while globbing the
real tree. Git goes through config.repo_root(); the registry does not. Harmless
in production since they are the same repo, but it is the same
no-root-override asymmetry the domain map noted about the old scripts, now
inside the new code. Not fixed here — making it dynamic means restructuring six
module-level constants in a module the old script still imports.
Real history is the better fixture anyway: both implementations see identical
input, nothing is mutated, and nothing can drift from the thing it models. Two
of the cases are genuine historical instances of the regression this gate
exists to catch — T-1237 and T-1194 both changed canvas generation and were
bumped only after the fact. The history that produced the check, used as its
own test.
The test also asserts no changed file is dropped from the failure message. That
list is the actionable half; "something changed" without saying what leaves the
reader to re-derive the intersection by hand.
Proven to fail by truncating the touched-file set, which reported both the
exit-code divergence and all three omitted filenames by name. Each case also
asserts the OLD script still behaves as the case claims, so a rewritten history
would say so rather than silently checking nothing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>