Two small hardening items found while reviewing the REVISION 7 orchestration work (#13). Neither is a defect today — both were checked and neither is reachable in the current code. Recorded so they are decided rather than forgotten.
1. gauntlet_layers.sh keeps its working state in unprefixed globals
POSIX sh has no local, so run_layer and finish_gauntlet assign layer, rc and missing into the caller's scope.
Verified there is no collision today: the only other sourced helper, must_not_match.sh, uses pattern, and the layer wrapper functions in gauntlet.sh (layer_lint_format, layer_must_not_scans) touch none of the three. finish_gauntlet reassigns layer on every iteration, so the leak from run_layer cannot be read stale.
The hazard is a future layer function that happens to use one of those names — most plausibly rc, which is the obvious name for a status variable and is exactly what a multi-command layer wrapper would reach for. That would corrupt the status run_layer reports, in a mechanism whose entire job is reporting status honestly.
Cheap fix: prefix them (_gl_layer, _gl_rc, _gl_missing). Worth deciding whether that is worth a rebind cycle on its own or should ride along with the next change to tools/.
2. "names every missing layer" has no control
spec.md REVISION 7 states:
A successful command sequence that omits any expected layer fails at the final audit and names every missing layer.
finish_gauntlet does implement this — it loops the full manifest, echoes each absent layer, and only then returns 1. But scenario 1 of test_gauntlet_orchestration.sh omits a single layer (mutation), so the plural half of the clause is asserted by nobody.
A control omitting two layers and asserting both names appear would close it, in the same shape as the existing scenarios. Small, and it is the difference between a contract that is true and a contract that is shown to be true — which is the distinction this repo exists to maintain.
Not proposed here
Extending coverage or mutation across tools/. That was decided against in REVISION 7 for the reason recorded in evidence.md: the shallow-history defect in REVISION 5 would have survived 100% coverage and a full mutation run, because it was a missing scenario, not an unkilled mutant. Targeted negative controls remain the instrument for trust-chain tooling.
Two small hardening items found while reviewing the REVISION 7 orchestration work (#13). Neither is a defect today — both were checked and neither is reachable in the current code. Recorded so they are decided rather than forgotten.
1.
gauntlet_layers.shkeeps its working state in unprefixed globalsPOSIX
shhas nolocal, sorun_layerandfinish_gauntletassignlayer,rcandmissinginto the caller's scope.Verified there is no collision today: the only other sourced helper,
must_not_match.sh, usespattern, and the layer wrapper functions ingauntlet.sh(layer_lint_format,layer_must_not_scans) touch none of the three.finish_gauntletreassignslayeron every iteration, so the leak fromrun_layercannot be read stale.The hazard is a future layer function that happens to use one of those names — most plausibly
rc, which is the obvious name for a status variable and is exactly what a multi-command layer wrapper would reach for. That would corrupt the statusrun_layerreports, in a mechanism whose entire job is reporting status honestly.Cheap fix: prefix them (
_gl_layer,_gl_rc,_gl_missing). Worth deciding whether that is worth a rebind cycle on its own or should ride along with the next change totools/.2. "names every missing layer" has no control
spec.mdREVISION 7 states:finish_gauntletdoes implement this — it loops the full manifest, echoes each absent layer, and only then returns 1. But scenario 1 oftest_gauntlet_orchestration.shomits a single layer (mutation), so the plural half of the clause is asserted by nobody.A control omitting two layers and asserting both names appear would close it, in the same shape as the existing scenarios. Small, and it is the difference between a contract that is true and a contract that is shown to be true — which is the distinction this repo exists to maintain.
Not proposed here
Extending coverage or mutation across
tools/. That was decided against in REVISION 7 for the reason recorded inevidence.md: the shallow-history defect in REVISION 5 would have survived 100% coverage and a full mutation run, because it was a missing scenario, not an unkilled mutant. Targeted negative controls remain the instrument for trust-chain tooling.