Test the cycle safety the header only claimed

The module said a cycle terminates rather than hanging. That was prose. The
manifest has six self-composing edges today, through the bundle/profile form,
and upg100 measured that a naive recursive walk hangs on it -- so the claim was
load-bearing and untested, which is the same gap as an untested fallback.

The fixture now carries a self-composing bundle and a mutual two-cycle. If the
closure ever regresses to recursion this test does not fail, it hangs, which is
a louder signal than a red assertion.
This commit is contained in:
Doxa Maps 2026-09-28 13:26:39 +00:00
parent 17a141538a
commit d614b46243

View file

@ -500,6 +500,15 @@ const STAGE_FIXTURE = {
{ bundle: 'deep-exp', stage: 'experimental' },
{ bundle: 'pair', stage: 'experimental' },
{ bundle: 'lonely-exp', stage: 'experimental' },
// ★ CYCLES ARE REAL IN THIS MANIFEST, not hypothetical: six edges are self-composition via the
// bundle/profile form (country-posters, my-upg-100-list, regions-dashboard all compose
// themselves), and upg100 measured that a naive recursive walk hangs on it TODAY. The header
// claimed termination in prose and never tested it, which is the same gap as an untested
// fallback — so a self-cycle and a mutual cycle are both in the fixture. If the closure ever
// regresses to recursion this test does not fail, it HANGS, which is its own loud signal.
{ bundle: 'selfie', stage: 'production', composes: ['selfie/one', 'selfie/two', 'ring-a'] },
{ bundle: 'ring-a', stage: 'experimental', composes: ['ring-b'] },
{ bundle: 'ring-b', stage: 'experimental', composes: ['ring-a'] },
],
}
@ -586,6 +595,8 @@ function selfTest() {
ok(eff.includes('pair'), "a composes entry of the form 'bundle/profile' resolves to its BUNDLE")
ok(!eff.includes('lonely-exp'), 'CONTROL: an experimental bundle nobody composes stays out of scope')
ok(stageReason(STAGE_FIXTURE, 'mid-exp').startsWith('composed by'), 'and the report can say WHY it is in scope')
ok(eff.includes('selfie'), 'a SELF-COMPOSING bundle resolves rather than looping (6 such edges exist in the real manifest)')
ok(eff.includes('ring-a') && eff.includes('ring-b'), 'and a MUTUAL cycle terminates, marking both members')
console.log(fails ? `\nSELF-TEST: ${fails} FAIL(s)` : '\nSELF-TEST: the gate can see planted leaks and stays quiet on correct code')
return fails
}