Skip to content

Spec + plan 0010: gather spill-aware interim references - #362

Merged
jimmytacks merged 1 commit into
mainfrom
spec-0010-spill-aware-gather
Aug 28, 2026
Merged

jimmytacks merged 1 commit into
mainfrom
spec-0010-spill-aware-gather

Conversation

@jimmytacks

Copy link
Copy Markdown
Collaborator

Docs only — no code changes. Adds specs/0010-gather-spill-aware-references.md and plans/0010-gather-spill-aware-references.md.

Parent issue: #352 (children #353-#360).

What it covers

/Gather only produces a good LET when the calculation was built dynamically from the start. When an interim step spills and the author references the spilled cells individually — a two-capture REGEXEXTRACT, then reading each value separately — the spill children come out as unrelated cell-reference inputs.

The spec adds spill geometry to ICellSource (GetSpill replacing the HasSpill bool), classifies every reference against the spill it lands in, and rewrites it as a named slice binding over the anchor's binding:

=LET(extracted, REGEXEXTRACT(txt, pat, 1),
     first,  INDEX(extracted,1,1),
     second, INDEX(extracted,1,2),
     ...)

The slice ladder prefers the simplest expression — positional INDEX for single cells, edge-relative signed TAKE for flush bands (TAKE(arr,,-1) for the last column, not a counted CHOOSECOLS), TAKE(DROP(...)) for interior blocks.

Two pre-existing defects folded in

  • A spill child emits B1# as its RHS, which is #REF! on a non-anchor — gather can currently produce a LET that does not evaluate. Contingent on the PR 1 spike (see below).
  • A scalar ref to a spilling anchor (=A1*2) is silently widened to the whole array. Correctly INDEX(arr,1,1).

Worth a look on review

The spec's Problem section rests on an unverified assumption. It asserts spill children report HasFormula false. If the spike in PR 1 (#353) finds otherwise, today's failure mode is a duplicated step rather than a stray input, and the "broken B1#" claim is withdrawn. The design holds either way — only the problem statement and PR 3's regression tests differ. PR 1 is scoped to settle this and amend the spec before anything depends on it.

Rule ordering carries the 1x1 guarantee. Single-cell is checked before whole-array, so a range that is simultaneously one cell and the whole spill (A1:A1 on a 1x1 spill) takes the scalar path. Getting this backwards would hand downstream steps a 1x1 array, which is not a scalar and collapses SEQUENCE/REGEXEXTRACT. A defensive @ prefix was considered and rejected in Out of Scope — it would be redundant against INDEX and would mask exactly this class of generator bug.

Deliberately out of scope

Fill-down blocks (C2:C10 each =B2*2) still promote to a single range input rather than becoming a MAP — the other half of "not built dynamically", recorded with reasoning for a later spec. Also legacy CSE arrays, implicit intersection, and shape-robust slice expressions.

/Gather only produces a good LET when the calculation was built
dynamically from the start. When an interim step spills and the author
references the spilled cells individually, the spill children come out
as unrelated cell-reference inputs instead of slices of the array.

The spec adds spill geometry to ICellSource (GetSpill replacing the
HasSpill bool), classifies every reference against the spill it lands
in, and rewrites it as a named slice binding over the anchor's binding.
The slice ladder prefers the simplest expression: positional INDEX for
single cells, edge-relative signed TAKE for flush bands, TAKE(DROP(...))
for interior blocks. Single-cell is checked before whole-array so a
range that is simultaneously one cell and the whole spill takes the
scalar path — a 1x1 array is not a scalar.

Also covers two pre-existing defects in the same area: a spill child
emitting B1# as its RHS (invalid on a non-anchor), and a scalar ref to
a spilling anchor being silently widened to the whole array.

The plan sequences eight PRs, front-loading a COM spike and a pure,
unwired slice generator so PR 3 is a tracer bullet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jimmytacks
jimmytacks requested a review from taglotacks August 28, 2026 15:30
@jimmytacks
jimmytacks merged commit 1ab5c4b into main Aug 28, 2026
2 checks passed
@jimmytacks
jimmytacks deleted the spec-0010-spill-aware-gather branch August 28, 2026 15:32
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.

2 participants