test(cliffs): the cascade's 2 false rejections are KNOCK-ONS, not defects (#84) - #147
Merged
Merged
Conversation
…ects (#84) #143 priced the destruction cascade as a net +8 shipping gain - 10 fewer missed cells for 2 more false rejections - and left it untaken with an explicit instruction: look at the 2 new false rejections before the 10 wins, because #134 recorded a gate the port does not model. This is that look. Zero capture. Splitting every SECONDARY removal - a cell the cascade took that nothing killed directly - by whether the game also destroyed the ROOT of its chain: root the game destroyed too 27 removals, 0 wrong root the game KEPT 2 removals, 2 wrong Conditional on a correct root the cascade's precision is 1.000. Both disagreements descend from a kill that was already wrong - (1318,2618.5) from an ORE false rejection, (3134,3002.5) from a LAVA one - so it is not one rule's problem, and the two account for the entire falseAfter - falseBefore increment. Both roots survive in the game carrying the orientation we placed them at, so neither was trimmed either. #134's gate is therefore UNSUPPORTED here rather than refuted: nothing is left in this sample for it to explain. Consequence for adoption: the net-8 gain's cost is NOT intrinsic. Adopting the cascade makes the port worse at nothing; it makes two existing precision defects visible at two extra cells, and fixing either root removes its knock-on free. The control that nearly inverted this: cell 2's root sits at y=2998.5, OUTSIDE its region's y0=3000. Tested against the region-filtered game set it reads as "the game destroyed it", which would have made that cell a genuine cascade defect and halved the finding. The root check runs against the UNFILTERED dump, which does contain it. Coverage, planted rather than claimed: cascade never fires -> fails 4; every trim destroys -> fails 4 (908 false after, not 14); dropping the isCliffConnected parity guard -> PASSES. That last is a real gap - destroyEnd is already a no-op on a side the orientation lacks, so the guard only bites on a wrong-parity facing side and no cell in these 14 regions has one. Recorded in the spec so a green run is not read as covering the parity rule. Verified: pnpm run verify green - 1562 app (up 4) + 13 worker + 3 container, 0 warnings, exit 0. Measurement only; shipping accuracy unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HKjzpWJw1HbnigPP9udqN2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#143 priced the destruction cascade as a net +8 shipping gain - 10 fewer missed cells for 2 more false rejections - and deliberately left it untaken with one instruction: look at the 2 new false rejections before the 10 wins, because #134 recorded a gate the port does not model (
Cliff::destroyEndrefuses toforceDestroywhen entity flag bit 4 of+0x6eis set, leaving the orientation UNCHANGED).This is that look. No capture - every fact comes from fixtures already committed.
The split that settles it
Every secondary removal - a cell the cascade took that nothing killed directly - classified by whether the game also destroyed the root of its chain:
Conditional on a correct root, the cascade's precision is 1.000. Both disagreements descend from a kill that was already wrong, and the two rows account for the entire
falseAfter - falseBeforeincrement.(1318, 2618.5)none-to-south(1318, 2622.5)north-to-east(3134, 3002.5)north-to-none(3134, 2998.5)east-to-southOne ore, one lava, so this is not a single rule's precision problem. Both roots survive in the game carrying the orientation we placed them at, so neither was trimmed either - they were not touched at all.
What it does to #134's gate, and to the adoption decision
The gate is UNSUPPORTED here rather than refuted: there is nothing left in this sample for it to explain. A cascade that force-destroys every single-ended neighbour reproduces the game exactly, 27 times out of 27, whenever it is fed a correct kill.
So the net-8 gain's cost is not intrinsic. Adopting the cascade makes the port worse at nothing - it makes two existing precision defects visible at two extra cells, and fixing either root removes its knock-on for free. That is a materially different decision from the one #143 recorded.
The control that nearly inverted the result
Cell 2's root sits at
y = 2998.5, outside its region'sy0 = 3000. Tested against the region-filtered game set it reads as "the game destroyed it" - which would have made that cell a genuine cascade defect and halved the finding. The root check therefore runs against the unfiltered dump, which carries cliffs beyond the region and does contain it. Same family as the clamped comparison #139 hit.Note what the orientations do not prove: both surviving cells are single-ended, so "kept unchanged" is the only alternative to "destroyed" - there is no third state to observe. The unchanged orientation is consistent with the gate without being evidence for it. The root check is what carries the argument, and the spec says so.
Coverage, planted rather than claimed
next = -1)isCliffConnectedparity guard is droppedThat last row is a real gap, recorded in the spec rather than left implicit.
destroyEndis already a no-op on a side the orientation lacks, so the guard only bites when a neighbour presents the facing side with the wrong parity, and no cell in these 14 regions does. A green run here is not evidence for the parity rule;test/cliffConnections.spec.tspins that from the orientation tables.Where #84 stands now
The open question is unchanged in kind but smaller: the residual is still 31 destruction decisions, the border enrichment still survives both deflations (#134, #143), and the ore recall gap is still the six cells of #142. What has closed is the objection blocking the shipping gain.
Verification
pnpm run verifygreen - 1562 app (up 4) + 13 worker + 3 container tests, 0 warnings, exit 0. Measurement only; shipping accuracy unchanged.🤖 Generated with Claude Code
https://claude.ai/code/session_01HKjzpWJw1HbnigPP9udqN2