Skip to content

feat(z8run-lance): native report nodes over the lance-graph ABI substrate - #1

Merged
AdaWorldAPI merged 2 commits into
mainfrom
claude/brave-mayer-65y3cy
Sep 23, 2026
Merged

AdaWorldAPI merged 2 commits into
mainfrom
claude/brave-mayer-65y3cy

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

What

A new workspace-excluded crate, crates/z8run-lance, adds eight native nodes. Together they build a lance-graph ReportPlan inside a visual flow:

node on a plan handle on a result handle
lance-source emits a fresh plan over a named published source —
lance-filter / lance-axis / lance-measure / lance-top-k rewrites the immutable plan and emits a new handle top-k re-views the result
lance-pivot rewrites roles (metadata only) re-views the same aggregate cells, with no fold
lance-execute folds in lance-graph, or reuses a cached fold with the same role-free physical key —
lance-materialize refuses a plan the explicit terminal: data export only (JSON / CSV)

Paged and screen output (HTML, Typst → PDF) is not a report node's job. lance-materialize refuses those formats at configure time, and its error message points to OGAR composition: the result is embedded in a DocCompose by reference and rendered by OGAR's renderers (via lance-graph-report-ogar in the companion lance-graph PR).

The control-plane rule

A FlowMessage payload is only a handle, about 100 bytes:

{"$kind":"lance-abi","role":"plan","handle":17,"generation":4,"source":9}

Rows, lanes, masks and aggregate cells never enter JSON. The only node that produces text is lance-materialize, and it resolves CAM labels only for the members it presents.

The strings in node config (field names, labels) are resolved to FieldIds and ordinals when the node is configured. The plans the nodes emit hold ids only.

A source that is republished gets a new generation, and handles minted against the old generation fail closed.

Why the crate is excluded

It path-depends on the sibling AdaWorldAPI/lance-graph checkout, and through that on AdaWorldAPI/ndarray. z8run's own CI checks out z8run alone. The crate carries its own rust-toolchain.toml (1.98.1, matching lance-graph).

To build it from a fleet checkout:

cargo test --manifest-path crates/z8run-lance/Cargo.toml

Depends on

The lance-graph-report crate in the companion PR AdaWorldAPI/lance-graph#1271, on branch claude/brave-mayer-65y3cy.

Tests (6, all green locally)

  • Envelope size: every hop's payload is under 128 B at both 1 000 and 200 000 rows.
  • Plan equality: the z8run-built plan equals the hand-built native plan, and so do their lowered first-pass programs.
  • No re-fold on pivot: pivoting a result handle, and re-executing a rotated plan, both run zero extra folds. Execution count stays 1, the cache hit count is 1, and the aggregate Arc is shared.
  • Stale handles: a republished source makes old handles fail closed.
  • Materialize guard: lance-materialize refuses a plan handle.
  • Paged output refused: format: html fails to configure with a pointer to OGAR composition. Its stay-silent twin checks that json and csv still configure.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DCEP2fZdHYdMCtcEVcTpS2

…rate

Adds a workspace-excluded crate with eight native nodes (lance-source,
-filter, -axis, -measure, -pivot, -top-k, -execute, -materialize) that
build a lance-graph `ReportPlan` node by node. FlowMessages carry only a
~100-byte `{"$kind":"lance-abi",...}` handle; populations, masks and
aggregate cells never enter JSON. Only `lance-materialize` produces text.

- Names/labels in node config resolve to FieldIds/ordinals when the node
  is configured (catalog + CAM); emitted plans hold ids only.
- `lance-pivot` on a result handle re-views the same aggregate space; on a
  plan it rewrites roles. `lance-execute` caches by the role-free physical
  key, so a rotated plan reuses its twin's fold.
- A republished source bumps its generation; older handles fail closed.

Excluded from the workspace because it path-depends on the sibling
lance-graph checkout, which z8run's own CI does not clone.

Tests: 5 node-level falsifiers (envelope size independent of population
at 1k and 200k rows; z8run plan == native plan incl. lowered programs;
no refold on rotation; stale handle refusal; materialize refuses plans).

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

lance-graph-report dropped its HTML terminal (the reporting engine must not
become a paper engine). lance-materialize now accepts json/csv and refuses
html/typst/pdf with a pointer to the OGAR composition path, where a report
is embedded by reference (lance-graph-report-ogar) and rendered by OGAR's
emitters. New test: the refusal fires, and json/csv still configure.

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

cursor Bot commented Sep 23, 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: serverGenReqId_4b5be112-de4d-446e-a0bd-9873b65defec)

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review September 23, 2026 18:25
@AdaWorldAPI
AdaWorldAPI merged commit ae2c894 into main Sep 23, 2026
1 check passed
@cursor

cursor Bot commented Sep 23, 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: serverGenReqId_b99e37b2-1581-4218-ac92-bd389cf48da2)

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