Pin the per-head walk, and say where the hold stops

Sharing renders' seen set across heads left the suite green while silently
under-rejecting: the first head's walk marks the only route to the second
head's draw. This PR widens heads from the bound levels to every held name,
so two heads in one template is now the ordinary case; a rejected case whose
violation sits on the later head pins the scoping.

An operand rendering one field twice covers the revisit guard, taking
coverage to 97.8% against main's 97.4%.

The README said the two spellings are rejected alike without saying what the
hold follows, which is not true where the operand reaches its own field
through a reference. It now names the plain {field} tokens the walk follows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
M
2026-08-31 21:44:24 +02:00
committed by lilleman-tw
parent 21e7af6c1f
commit 4b3dd011fc
3 changed files with 23 additions and 9 deletions
+5 -5
View File
@@ -366,11 +366,11 @@ the reference sits, including in a field the format renders.
A `{calc()}` operand is held on its own terms too, so the same fence guards it:
`{..cat.net} x 2 = {calc(net * 2, 2)}` names one field two ways and is a load
error, with no path token anywhere. A calc renders its operand whole, so the hold
pins every value that render settled: naming the operand and reaching into it
both conflict, and `{net.v}` and `{..cat.net.v}` are rejected alike. The hold
ends at a `{..path}`, where the operand's own value ends and a shared source
begins — two names drawing from one referenced category are two draws, as
`{word} {word}` is, so two dice over one `{..die}` are fine.
pins what that render settled, following the operand's plain `{field}` tokens —
`{net.v}` and `{..cat.net.v}` are rejected alike. It stops at a `{..path}`, where
the operand's own value ends and a shared source begins: two names drawing from
one referenced category are two draws, as `{word} {word}` is, so two dice over
one `{..die}` are fine.
```text
token {p} renders a level that {p.first} reads a path into; name the fields you want instead