Skip to content

report: name the real gap (destination binding for Report); record why GroupAddr::Pair is not the pivot model - #1331

Merged
AdaWorldAPI merged 6 commits into
mainfrom
claude/report-groupaddr-pair
Oct 5, 2026
Merged

AdaWorldAPI merged 6 commits into
mainfrom
claude/report-groupaddr-pair

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Documentation only. This PR first lowered every two-ordinal report to Quack's GroupAddr::Pair (one pass, hi · stride + lo). That was the wrong model and the change has been reverted. What remains is a corrected doc comment and the board record. Runtime behaviour is unchanged.

Why the Pair path was wrong

GroupAddr::Pair addresses the dense product of two dimension domains. Lowering to it automatically made |A| × |B| the execution geometry only because the primitive existed; no consumer had asked for a dense cube. For IAM-sized dimensions (64k × 64k) that is 4·10⁹ slots.

The intended model is PowerShell-Hashtable / Excel-Pivot:

  • a row's aggregate destination is resolved;
  • the row folds directly into it;
  • accumulator state scales with the demanded / resolved destination universe.

GroupAddr::Pair remains valid only for a consumer that explicitly demands a dense mixed-radix destination universe.

The missing capability: destination binding for Report

The missing capability is destination binding / coordinate resolution for Report. Once a compact destination ordinal or functional reference is bound, the existing Local / Via keyed fold is already the execution primitive.

semantic coordinate(s)
        ↓
BIND / RESOLVE DESTINATION
        ↓
compact destination ordinal / functional route
        ↓
existing GroupAddr::Local / GroupAddr::Via keyed fold  (caller-sized K sink, K = destination count)

What CoordSpec cannot express today. Its only variants are Field, Bucket and MaskSet. It has no way to represent:

  • a functional-reference coordinate, such as user → department;
  • a composed functional route;
  • several semantic coordinates bound to ONE compact destination ordinal.

So Report partitions instead.

Law: a join or pivot used only to determine an aggregate destination must compile to destination binding / resolution + fold. It must not compile to an intermediate relation, and must not automatically become a dense product.

How destinations get bound:

  • Normal path: destinations are bound beforehand. That means a resident ordinal, a CAM / codebook binding, or a Via or composed functional reference.
  • Fallback only: a query-local compact interner, used solely for a destination universe that genuinely cannot be bound beforehand. It is not the canonical path.
  • Not in this PR: no new type, address, CoordSpec variant or substrate primitive is introduced.

What the source shows (recon, VERIFIED-IN-CODE)

Keyed reduction. ndarray, mask-risc and Quack share one keyed-reduction walker. It has three addresses: Lane, Via and Pair. All three write a caller-sized K-slot sink.

The sparse path's cost. Report's Layout::Sparse is reached in two stages:

  1. One discovery population scan for each ordinal partition dimension.
  2. T × FoldStates population folds, where T is the product of the partition radices:
    • for an ordinal dimension, its discovered members;
    • for a Bucket / MaskSet dimension, its full configured radix.

On top of that comes one selection-materialization scan when the ReusedMask carrier is chosen. For example, 100 × 100 observed members × 4 FoldStates = 40,000 fold scans after discovery. This partition-rescan architecture is what destination binding exists to eliminate.

This PR

exec.rs module doc (doc lines only) names the gap as destination binding, as described above.

Board entry entries/2026-10-05-report-pair-key-and-stack-recon.md, titled "Report Pair experiment superseded; destination-binding gap and stack recon":

  • The Pair cut is kept as a ⊘ superseded record. The greedy-Pair optimization is a historical observation only, not open work.
  • The sparse cost is corrected as above.
  • Decision 1 is struck. Decisions 2–5 of the stack recon stand.

Verification

  • Report unchanged. The planner files (plan.rs, explain.rs, result.rs, lib.rs), Cargo.toml and the tests are byte-identical to main. exec.rs has zero non-doc changed lines.
  • Checks: lance-graph-report tests pass; fmt and clippy -D warnings are clean.
  • Board gates: the append-only and entries-index gates pass, and SUPERSESSION was regenerated. citation_decay reports the same output as before this change.

The fold contract and the keyed partial-sink merge live in #1332, not here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately names the destination-binding gap for Report and explains why GroupAddr::Pair is not the pivot model. It is specific and related to the main changes.
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cursor

cursor Bot commented Oct 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 0b1d7966-9619-42f1-947d-f860cff471ae)

@cursor

cursor Bot commented Oct 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: 72538497-e5fe-4ba2-ba8a-e1e968ae428a)

@AdaWorldAPI AdaWorldAPI changed the title report: fold two ordinal coordinates in one pass via Quack's GroupAddr::Pair report: name the real fold gap (destination-resolving keyed fold); record why GroupAddr::Pair is not the pivot model Oct 5, 2026
@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review October 5, 2026 10:15

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e8d25cf8b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/lance-graph-report/src/exec.rs Outdated
Comment thread .claude/board/entries/2026-10-05-report-pair-key-and-stack-recon.md Outdated
AdaWorldAPI pushed a commit that referenced this pull request Oct 5, 2026
…escan cost

Wording only (codex review on #1331):
- the ACCUMULATE half exists (GroupAddr::Local / Via fold into a K-slot
  sink; K can be the compact destination count). The missing half is
  binding/resolving ONE destination from several coordinates in Report's
  CoordSpec / binder -- not an ndarray fold.
- the sparse path costs one discovery scan per ordinal partition plus one
  run per fold state per tuple of the product of observed members, not one
  rescan per observed member.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2
@cursor

cursor Bot commented Oct 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: add716df-d78d-4f56-b938-1c7c8b5bbfeb)

claude added 5 commits October 5, 2026 10:22
…r::Pair

lance-graph-report planned a two-dimensional report as one population pass
per partition member and called the composite-key group fold a named
substrate gap. Quack already has GroupAddr::Pair, so the physical planner
now picks a fold major: the widest other ordinal whose product with the fold
key's domain fits domain_buffer_budget. Both coordinates then fold in ONE
pass (20x30: 20 passes -> 1, 80 population scans -> 4).

- Buckets, mask sets and a third ordinal stay partitions (no value-derived
  or multi-plane group key in Quack).
- A pair-keyed SUM lowers to the NULL-preserving GroupReduce{SumI32}; its raw
  sink goes through Quack's normalize_group_sink (empty -> 0). Count/Min/Max
  already seed the report's own identities.
- PhysicalPlan gains fold_major; explain labels it.

Tests: new pair == per-member test over a mostly-empty space (cells, totals,
hidden-axis merges; budget threshold 600 pairs / 599 does not); a disable
run with the normalization removed goes red. t9 pins the pair programs plus
a per-member twin; the pass-budget test moves to three ordinals.
lance-graph-report 33/33, report-ogar 4/4, z8run-lance 10/10 (pivot_flow
handle sizes and plan equality unchanged), clippy -D warnings clean.

Board: one entry with the stack-convergence recon and the five decisions
that scoped this cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2
…dy pair choice as OPEN

Review nit: the knob now also bounds the product of the fold key's and the
fold major's domains, not only a single coordinate's domain. Doc-only.

The entry gains the review's non-blocking finding: the pair choice is
greedy (widest key first), so 100x60x60 at budget 3600 runs 3600 passes
where a joint (key, major) choice would run 100. REVISIT WHEN the planner
is next touched; kept out of this PR to keep the fold key unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2
…n-resolving keyed fold)

Correction before merge. GroupAddr::Pair addresses the dense product of two
dimension domains; lowering every two-ordinal report to it made the
Cartesian product the execution geometry because the primitive existed, not
because a dense cube was demanded. The intended fold model resolves each
row's accumulator destination directly, with accumulator state scaling with
observed destinations (PowerShell hashtable / Excel pivot), not with
|A| x |B|.

- Reverted fold_major, fold_addr, Pair SUM normalization, the product
  budget, Pair strides/decode and the Pair-pinning tests: Report's planner
  is main's again.
- exec.rs's gap doc now names the real missing primitive: a
  destination-resolving keyed fold (resolved key tuple -> compact slot in
  the same pass), substrate-first in ndarray's keyed-reduction family.
  Pair stays in Quack/mask-risc/ndarray for explicitly dense problems.
- The board entry keeps the Pair cut as a superseded record and states why;
  decision 1 is struck; decisions 2-5 stand.

lance-graph-report 32/32, fmt, clippy -D warnings clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2
… the greedy-Pair OPEN item

Wording only. exec.rs gap doc: bind/resolve -> destination -> fold, with the
law that a join/pivot used only to find an aggregate destination compiles to
destination resolution + fold, never to an intermediate relation and never
automatically to a dense product; the normal path binds destinations
beforehand (ordinal, CAM/codebook, Via / composed reference) and only an
unbindable universe uses a query-local compact resolver. No physical
representation is chosen.

Board entry: heading names the superseded Pair experiment; the greedy-Pair
optimization leaves OPEN and is kept only as a historical observation under
the superseded cut; the missing-primitive OPEN line no longer prescribes
keys-SoA / observed-destination storage. Decisions 2-5 unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2
…escan cost

Wording only (codex review on #1331):
- the ACCUMULATE half exists (GroupAddr::Local / Via fold into a K-slot
  sink; K can be the compact destination count). The missing half is
  binding/resolving ONE destination from several coordinates in Report's
  CoordSpec / binder -- not an ndarray fold.
- the sparse path costs one discovery scan per ordinal partition plus one
  run per fold state per tuple of the product of observed members, not one
  rescan per observed member.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2
@AdaWorldAPI
AdaWorldAPI force-pushed the claude/report-groupaddr-pair branch from 9fd9292 to eb71675 Compare October 5, 2026 10:22
… cost

Wording only (codex review on #1331, operator-confirmed):
- the missing capability is destination binding / coordinate resolution for
  Report. Once a compact destination ordinal or functional reference is
  bound, the existing GroupAddr::Local / Via keyed fold is the execution
  primitive. CoordSpec (Field, Bucket, MaskSet) cannot express a functional
  reference, a composed route, or several coordinates bound to one compact
  destination ordinal. A query-local interner is only a fallback.
- Layout::Sparse costs one discovery scan per ordinal partition dimension,
  then T x FoldStates population folds, where T is the product of the
  partition radices (discovered members for ordinals, full radix for
  Bucket / MaskSet), plus a ReusedMask selection scan when chosen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2
@AdaWorldAPI AdaWorldAPI changed the title report: name the real fold gap (destination-resolving keyed fold); record why GroupAddr::Pair is not the pivot model report: name the real gap (destination binding for Report); record why GroupAddr::Pair is not the pivot model Oct 5, 2026
@AdaWorldAPI
AdaWorldAPI merged commit 4778f86 into main Oct 5, 2026
9 checks passed
AdaWorldAPI pushed a commit that referenced this pull request Oct 5, 2026
…te index

Wording only, after rebasing onto main (#1331, #1333):
- entries/README.md regenerated from the rebased tree (218 rows).
- Fold-contract OPEN splits the old "destination resolution" item into
  A. destination binding / coordinate resolution (frontend / binder; lowers
  to the existing Local / Via fold; not a missing ndarray primitive) and
  B. functional route composition beyond depth 2 (substrate / R2IL; chain vs
  precomposed lane unmeasured).
- TD-KEYED-SINK-MERGE-IDENTITY-1 states exactly what merge_group_sink checks
  (supported keyed i64 terminal, equal length) and adds binding identity,
  contribution-population identity, and the working law that an ordinal has
  meaning only inside its destination-space / codebook identity.
- merge_group_sink precondition 5 names the binding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2
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