fabro/lib
Bryan Helmkamp 8d14b54994
Bound for_each fan-out memory
Addresses a Copilot review comment on #653.

The source array is runtime data, usually produced by a model, so its
length is not something a workflow author reviewed. Two changes, so an
over-long array degrades into a clear error rather than memory pressure.

Cap the item count at 1000. Above that the stage fails deterministically
before `parallel.started`, alongside the other for_each contract
violations, and the message says how to reduce the array.

Fork the parent context inside the branch task, after it acquires a
`max_parallel` slot, instead of at dispatch time. Live context copies now
track `max_parallel` rather than item count. Only the branch's own
preamble entry is moved into the task, so the shared stash is not cloned
per branch either.

The reviewer also suggested replacing spawn-all with `max_parallel`
workers pulling from a queue. Not done here: with the fork deferred, a
pending task holds little beyond its item, and reshaping the dispatch
loop would change cancellation and scope-reservation ordering, which
deserves its own review.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 20:16:20 -04:00
..
apps Merge remote-tracking branch 'origin/main' into feat/for-each-item-injection 2026-07-28 20:03:25 -04:00
components Bound for_each fan-out memory 2026-07-28 20:16:20 -04:00
foundation Merge remote-tracking branch 'origin/main' into feat/for-each-item-injection 2026-07-28 20:03:25 -04:00
packages/fabro-api-client Merge remote-tracking branch 'origin/main' into feat/for-each-item-injection 2026-07-28 20:03:25 -04:00