Tests for what an operand's draw actually fixes

Widening the fence used containment for both kinds of hold, which is right
for a level a path reads and wrong for a sibling a calc reads. A path may
read into anything the level contains; an operand's draw fixes only the value
it renders. So containment rejects a reference to a sibling the operand never
renders, which loads fine today and cannot disagree, and misses a reference
reaching what the operand renders through, which disagreed in 20 of 40 draws.

Also pins the repeated reference arm, the one kind that reaches the repeat
check by passing the per-arm checks rather than falling through them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
M
2026-08-31 14:01:07 +02:00
committed by lilleman-tw
parent 909596ec2d
commit 779b89a804
2 changed files with 35 additions and 6 deletions
+6
View File
@@ -137,6 +137,12 @@ func TestNewErrors(t *testing.T) {
map[string]string{"a": `{"format":"{p.v|p.v}","p":{"format":"{v}","v":["1"]}}`},
`arm "p.v" is repeated`,
},
// A reference arm is the only kind that reaches the repeat check by passing
// the per-arm checks rather than falling through them.
"repeated reference arm": {
map[string]string{"a": `["x"]`, "b": `{"format":"{..a|..a}"}`},
`arm "..a" is repeated`,
},
// An arm that is broken on its own terms is reported as that, not as a
// repeat: the repeat is a consequence of the real mistake.
"repeated arm with no path": {