Skip to content

Binding fidelity: a collection a loop iterates reads as unused - #508

Merged
m2ux merged 1 commit into
mainfrom
fix/binding-fidelity-loop-over
Aug 25, 2026
Merged

Binding fidelity: a collection a loop iterates reads as unused#508
m2ux merged 1 commit into
mainfrom
fix/binding-fidelity-loop-over

Conversation

@m2ux

@m2ux m2ux commented Aug 25, 2026

Copy link
Copy Markdown
Owner

Summary

A check that measures whether a declared value is ever used has to know every way a value can be used. This one knew several and not the one a loop uses, so a value produced for a loop to iterate read as unused.

What happens today

The binding-fidelity guard reports a declared output that nothing consumes, which is how a technique that produces a value nobody wants gets noticed. To do that it collects every site where a name is consumed: a {token} read in prose, a variable named by a gate expression, a value or remap passed at a step binding, and an input of the same name declared by another technique — the convention by which one operation's output chains into the next one's input.

A loop is missing from that list. When an activity iterates a collection, it names that collection once, in the loop's over. That is the only place the collection is read, and the guard does not look there. A technique whose output exists to be iterated therefore reports as dead.

The corpus does not currently show this, and the reason is incidental rather than structural. The collections it iterates — the open assumptions, the plan's tasks — happen to be declared as an input by some other technique as well, so the name-match convention rescues them. A collection that is only ever iterated has nothing to rescue it.

The fix

The loop's over joins the consumption sites. A collection reaching a loop and nothing else is live.

The name resolves against its head, the same way a {token} read does, because a loop iterates a field of a produced object about as often as it iterates the object itself — implementation_plan.tasks is produced as implementation_plan. Without that, three existing loops in the corpus would have been reported as reading something nothing produces. That is not a hypothetical: the first version of this change produced exactly those three, which is how the head rule earned its place.

Verification

Against the unchanged corpus the guard reports the same 70 findings before and after, all triaged, none live, none untriaged. The change adds sight rather than findings.

Against a branch that adds a technique producing a collection for a loop, the finding it previously raised is gone.

Typecheck is clean and the full suite is green at 1097 passed, 2 skipped, 0 failed.

Scope

The consumption set, and the head resolution that makes it correct for a dotted collection.

Acceptance criteria

  • A technique output consumed only as a loop's over collection is live.
  • A loop naming a collection nothing produces is still reported.
  • The unchanged corpus reports the same findings as before.

Non-goals

This does not change the other three checks the guard makes, and does not change which findings are triaged.

This does not address the scope question in #491 finding 1 — that bindings are verified against the workflow that authored a technique rather than the one running it. That is a separate defect in the same guard and is not touched here.

A forEach loop names the collection it iterates, and that name is the one
place the collection is read. Binding fidelity now records it as a
consumption site, so a technique output reaching a loop and nothing else
is live rather than dead.

The name resolves against its head, because a loop iterates a field of a
produced object as often as the object itself.

The corpus reports the same seventy findings before and after, all
triaged, so the change adds sight rather than findings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@m2ux
m2ux merged commit 5213fbd into main Aug 25, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant