aura graph / render: expose rendering for a consumer's OWN graph (not just the built-in sample) #28

Closed
opened 2026-06-05 22:36:08 +02:00 by Brummel · 6 comments
Owner

Milestone fieldtest (Construction layer, docs/specs/fieldtest-milestone-construction-layer.md) headline friction: aura graph renders ONLY the built-in sample, and the render adapter lives in the aura-cli binary (crates/aura-cli/src/graph.rs) — it is not a public library API. So a downstream researcher who authors their own Blueprint can introspect it as data (the accessors work) but cannot RENDER it as an ASCII DAG without copying the CLI adapter.

This is the milestone payoff only half-realized: "render the structure so any mis-wiring is visible before a run" is demonstrated on the engine sample, but a mis-wire lives in YOUR graph, not the sample. Same posture as aura run (sample-bound), so it is consistent with the current CLI-demonstrator stage — but it is the natural next step.

Direction (two coupled moves):

  1. Make the render a public API so a consumer can call it on their own Blueprint / compilat (e.g. a render entry reachable without the binary — a small render surface, keeping ascii-dag out of aura-engine per C16; candidate homes: a thin aura-cli lib target or a dedicated render crate).
  2. Let aura graph reach a consumer-authored graph (ties into the project-crate / cdylib loading of the World layer, C9/C17 — likely a later milestone).

Subsumes the reachability of #26: the nested-composite clustered-render unimplemented! is structurally unreachable from the public CLI TODAY (only the single-level sample renders), but becomes LIVE the moment the render is parameterizable. Sequence #26 to land with this.

context: surfaced by the Construction-layer milestone fieldtest; no bug (sample render is correct + deterministic), friction = reach. Likely belongs to the next (consumer-project / World) milestone.

Milestone fieldtest (Construction layer, docs/specs/fieldtest-milestone-construction-layer.md) headline friction: `aura graph` renders ONLY the built-in sample, and the render adapter lives in the aura-cli binary (crates/aura-cli/src/graph.rs) — it is not a public library API. So a downstream researcher who authors their own Blueprint can introspect it as data (the accessors work) but cannot RENDER it as an ASCII DAG without copying the CLI adapter. This is the milestone payoff only half-realized: "render the structure so any mis-wiring is visible before a run" is demonstrated on the engine sample, but a mis-wire lives in YOUR graph, not the sample. Same posture as `aura run` (sample-bound), so it is consistent with the current CLI-demonstrator stage — but it is the natural next step. Direction (two coupled moves): 1. Make the render a public API so a consumer can call it on their own Blueprint / compilat (e.g. a render entry reachable without the binary — a small render surface, keeping ascii-dag out of aura-engine per C16; candidate homes: a thin aura-cli lib target or a dedicated render crate). 2. Let `aura graph` reach a consumer-authored graph (ties into the project-crate / cdylib loading of the World layer, C9/C17 — likely a later milestone). Subsumes the reachability of #26: the nested-composite clustered-render `unimplemented!` is structurally unreachable from the public CLI TODAY (only the single-level sample renders), but becomes LIVE the moment the render is parameterizable. Sequence #26 to land with this. context: surfaced by the Construction-layer milestone fieldtest; no bug (sample render is correct + deterministic), friction = reach. Likely belongs to the next (consumer-project / World) milestone.
Brummel added the feature label 2026-06-05 22:36:08 +02:00
Author
Owner

Re-scope — partially delivered since filing. Two of the three moves are done:

  • model_to_json(&Composite) is now public (aura-engine/src/lib.rs) and render_html(&Composite) is parameterized on any composite (aura-cli/src/render.rs). The data + render path is no longer hardcoded to the built-in sample.

What remains open is the reach, not the data path:

  1. A public render entry-point: render_html still lives in the aura-cli binary (no aura-cli lib target), so a consumer cannot call it on their own blueprint without copying the adapter.
  2. aura graph still renders the built-in sample (main.rs); letting it reach a consumer-authored graph ties into project-crate / cdylib loading (C9/C17) and belongs to the later World/consumer-project milestone.

The #26 nested-composite clustered-render path stays sequenced to land with move 1 — it goes live the moment the render is consumer-parameterizable.

Re-scope — partially delivered since filing. Two of the three moves are done: - `model_to_json(&Composite)` is now public (aura-engine/src/lib.rs) and `render_html(&Composite)` is parameterized on any composite (aura-cli/src/render.rs). The data + render path is no longer hardcoded to the built-in sample. What remains open is the *reach*, not the data path: 1. A public render entry-point: `render_html` still lives in the aura-cli binary (no aura-cli lib target), so a consumer cannot call it on their own blueprint without copying the adapter. 2. `aura graph` still renders the built-in sample (main.rs); letting it reach a consumer-authored graph ties into project-crate / cdylib loading (C9/C17) and belongs to the later World/consumer-project milestone. The #26 nested-composite clustered-render path stays sequenced to land with move 1 — it goes live the moment the render is consumer-parameterizable.
Author
Owner

Re-scope (recon 2026-06-18): two decoupled moves; defer both to the World / consumer-project milestone; drop the #26 coupling.

A code recon confirms the current state and corrects two stale premises in the body.

Data path — done (as the 2026-06-14 comment noted). model_to_json(&Composite) is public (aura-engine/src/graph_model.rs:257, re-exported at lib.rs:59) and render_html(&Composite) is parameterized on any Composite (aura-cli/src/render.rs:64). No model/serializer work remains.

Move (1) — public render entry-point — small, but its payoff is latent. The sole blocker is packaging: render.rs lives in a binary-only crate (aura-cli/Cargo.toml has only [[bin]], no [lib], no src/lib.rs), so render_html — though pub — is unreachable by a downstream crate. The surface that would move is self-contained: one pub fn + four private consts + three include_str!'d JS assets (paths are crate-relative, so assets/ moves with the code); the body is unchanged and the only call site is main.rs:885.

Recommended home: a dedicated render crate (aura-viz), not a thin [lib] on aura-cli. Substance (not effort): #28 wants a reusable surface; the natural consumer edge is consumer-project -> aura-viz -> aura-engine. A thin lib on aura-cli would force a consumer to import the CLI host crate (run/sweep/mc/walkforward machinery, arg-parsing, the sample builders) just to render — conflating host-binary with reusable library. A dedicated crate keeps render engine-only-dependent and asset-self-contained; C16 stays satisfied (the viz assets never touch aura-engine).

Why defer move (1) rather than do it now: its entire value is reuse by a consumer project, and no consumer projects exist yet — recon found zero cdylib / Aura.toml / project-loader machinery anywhere in the repo. Today the only consumer is an in-repo examples/ fixture. Two substantive reasons to land it with the World / consumer-project milestone:

  • The render crate's shape is World-informed. Per C12 the playground is a trace explorer (structure before, live streams during, recorded traces after); render_html is one facet of that. Extracting a structure-only aura-viz now risks drawing the wrong crate boundary if the playground later wants structure + streams + traces in one viewer.
  • It belongs to the deferred consumer-project sequence (aura new / cdylib / deploy land after the World layer + experiment-API hardening), not the active orchestration-families milestone.

Cost of waiting is ~zero: the sample renders, and an own graph is viewable ad hoc today via an example that emits model_to_json and swaps it into the rendered viewer page.

Move (2) — aura graph <consumer-graph> — blocked on unbuilt infra. No cdylib / project-crate / Aura.toml loading exists (only doc-comment prose). Composite is not serde and there is no model_from_json, so the CLI cannot reconstruct a consumer Composite from a file — it needs a live Composite, i.e. actual project-crate / cdylib loading (libloading + Aura.toml + a Composite-export convention). This is the World / C9 / C17 seam — a later milestone, as the body already flags.

#26 coupling — drop it. The unimplemented!("nested-composite cluster rendering") this issue says to sequence with move (1) no longer exists: it lived in crates/aura-cli/src/graph.rs, retired with ascii-dag in cycle 0026 (commit 66dff88). #26 is closed; nested composites render recursively in the JS viewer (graph-viewer.js) and are depth-2 guarded (viewer_nested_depth.rs). The only possible residue is a separate, unverified item from #26's body — SourceSpec carries no name, so two F64 root sources render indistinguishably — which is not part of #28.

Stale spec note (not a code gap): docs/specs/fieldtest-milestone-construction-layer.md still describes ASCII-DAG output and an aura graph --compiled flag; both were retired in cycle 0026. Doc cleanup, handled separately.

Net: both moves park in the World / consumer-project milestone — move (1) is a small aura-viz extraction that lands first (unblocks a consumer rendering its own graph), move (2) depends on the cdylib loader. Nothing scheduled now.

**Re-scope (recon 2026-06-18): two decoupled moves; defer both to the World / consumer-project milestone; drop the #26 coupling.** A code recon confirms the current state and corrects two stale premises in the body. **Data path — done** (as the 2026-06-14 comment noted). `model_to_json(&Composite)` is public (`aura-engine/src/graph_model.rs:257`, re-exported at `lib.rs:59`) and `render_html(&Composite)` is parameterized on any `Composite` (`aura-cli/src/render.rs:64`). No model/serializer work remains. **Move (1) — public render entry-point — small, but its payoff is latent.** The sole blocker is packaging: `render.rs` lives in a binary-only crate (`aura-cli/Cargo.toml` has only `[[bin]]`, no `[lib]`, no `src/lib.rs`), so `render_html` — though `pub` — is unreachable by a downstream crate. The surface that would move is self-contained: one `pub fn` + four private consts + three `include_str!`'d JS assets (paths are crate-relative, so `assets/` moves with the code); the body is unchanged and the only call site is `main.rs:885`. Recommended home: a dedicated render crate (`aura-viz`), not a thin `[lib]` on aura-cli. Substance (not effort): #28 wants a *reusable* surface; the natural consumer edge is `consumer-project -> aura-viz -> aura-engine`. A thin lib on aura-cli would force a consumer to import the CLI host crate (run/sweep/mc/walkforward machinery, arg-parsing, the sample builders) just to render — conflating host-binary with reusable library. A dedicated crate keeps render engine-only-dependent and asset-self-contained; C16 stays satisfied (the viz assets never touch aura-engine). **Why defer move (1) rather than do it now:** its entire value is reuse by a consumer project, and no consumer projects exist yet — recon found zero cdylib / `Aura.toml` / project-loader machinery anywhere in the repo. Today the only consumer is an in-repo `examples/` fixture. Two substantive reasons to land it *with* the World / consumer-project milestone: - The render crate's shape is World-informed. Per C12 the playground is a trace explorer (structure before, live streams during, recorded traces after); `render_html` is one facet of that. Extracting a structure-only `aura-viz` now risks drawing the wrong crate boundary if the playground later wants structure + streams + traces in one viewer. - It belongs to the deferred consumer-project sequence (`aura new` / cdylib / deploy land after the World layer + experiment-API hardening), not the active orchestration-families milestone. Cost of waiting is ~zero: the sample renders, and an own graph is viewable ad hoc today via an example that emits `model_to_json` and swaps it into the rendered viewer page. **Move (2) — `aura graph <consumer-graph>` — blocked on unbuilt infra.** No cdylib / project-crate / `Aura.toml` loading exists (only doc-comment prose). `Composite` is not serde and there is no `model_from_json`, so the CLI cannot reconstruct a consumer `Composite` from a file — it needs a *live* `Composite`, i.e. actual project-crate / cdylib loading (libloading + `Aura.toml` + a Composite-export convention). This is the World / C9 / C17 seam — a later milestone, as the body already flags. **#26 coupling — drop it.** The `unimplemented!("nested-composite cluster rendering")` this issue says to sequence with move (1) no longer exists: it lived in `crates/aura-cli/src/graph.rs`, retired with ascii-dag in cycle 0026 (commit 66dff88). #26 is closed; nested composites render recursively in the JS viewer (`graph-viewer.js`) and are depth-2 guarded (`viewer_nested_depth.rs`). The only possible residue is a separate, unverified item from #26's body — `SourceSpec` carries no `name`, so two F64 root sources render indistinguishably — which is not part of #28. **Stale spec note (not a code gap):** `docs/specs/fieldtest-milestone-construction-layer.md` still describes ASCII-DAG output and an `aura graph --compiled` flag; both were retired in cycle 0026. Doc cleanup, handled separately. **Net:** both moves park in the World / consumer-project milestone — move (1) is a small `aura-viz` extraction that lands first (unblocks a consumer rendering its own graph), move (2) depends on the cdylib loader. Nothing scheduled now.
Author
Owner

cycle-0088 fieldtest triage — detailed finding follows in a moment.

cycle-0088 fieldtest triage — detailed finding follows in a moment.
Author
Owner

Reconfirmed from the op-script side — cycle-0088 fieldtest

The construction op-script service (#157) makes this gap concrete from the authoring direction. aura graph build emits a format_version:1 #155 blueprint to stdout, but no CLI subcommand consumes one back: aura graph ignores stdin and renders the hard-wired sample (verified byte-identical with and without a piped blueprint), and there is no aura graph render <bp> / aura run <bp>. A pure-CLI consumer can now author topology as data and build it, but cannot render, run, or reload-validate the result through the CLI — the round-trip dead-ends at the blueprint_from_json library boundary (#155).

The missing edge this issue names (render a consumer's OWN graph) is now the same edge the op-script flow needs: a CLI path that takes either an op-list or an emitted #155 blueprint and renders/runs it. It is also why the acyclicity bug #161 is invisible to a CLI consumer — there is no compile/run path to surface a non-DAG.

Evidence: fieldtests/cycle-0088-construction-op-script/FINDINGS.md (spec_gap "No CLI consumer for the emitted blueprint"). The render adapter being binary-private (noted in this issue's body, crates/aura-cli/src/render.rs) still holds — render_html(&Composite) is reachable only inside the binary.

## Reconfirmed from the op-script side — cycle-0088 fieldtest The construction op-script service (#157) makes this gap concrete from the authoring direction. `aura graph build` emits a `format_version:1` #155 blueprint to stdout, but no CLI subcommand consumes one back: `aura graph` ignores stdin and renders the hard-wired sample (verified byte-identical with and without a piped blueprint), and there is no `aura graph render <bp>` / `aura run <bp>`. A pure-CLI consumer can now author topology as data and build it, but cannot render, run, or reload-validate the result through the CLI — the round-trip dead-ends at the `blueprint_from_json` library boundary (#155). The missing edge this issue names (render a consumer's OWN graph) is now the same edge the op-script flow needs: a CLI path that takes either an op-list or an emitted #155 blueprint and renders/runs it. It is also why the acyclicity bug #161 is invisible to a CLI consumer — there is no compile/run path to surface a non-DAG. Evidence: `fieldtests/cycle-0088-construction-op-script/FINDINGS.md` (spec_gap "No CLI consumer for the emitted blueprint"). The render adapter being binary-private (noted in this issue's body, `crates/aura-cli/src/render.rs`) still holds — `render_html(&Composite)` is reachable only inside the binary.
Brummel added this to the Triage harvest 2026-07 — surface honesty & authoring ergonomics milestone 2026-07-09 17:31:15 +02:00
Author
Owner

Triage 2026-07-09 (tree at 68317ec) — the 2026-06-18 deferral is fully unblocked; re-scoped to the CLI move:

  • Both blockers named in that deferral have shipped: blueprint_from_json exists (crates/aura-engine/src/blueprint_serde.rs:207, re-exported in lib.rs:61) and the project load boundary exists (crates/aura-cli/src/project.rs — project-cdylib ∪ std vocabulary resolution).
  • aura graph is now the ONE verb still sample-bound: the no-subcommand arm renders only the embedded examples/r_sma_open.json (crates/aura-cli/src/main.rs:2645-2654), while run/sweep/mc/walkforward/generalize all consume consumer blueprint files via is_blueprint_file (:2267).
  • render_html(&Composite) is parameterized and self-contained (crates/aura-cli/src/render.rs:85, aura.css embedded), so aura graph <blueprint.json> is: read file + blueprint_from_json(env.resolve) + render_html — the same pattern as dispatch_run.
  • The library-packaging half (a dedicated render crate reachable by downstream Rust) has shrunk in value since the ratified consumer surface is CLI-over-blueprint-data (verb-dissolution milestone); it warrants an explicit re-decision — likely a drop — rather than silent inheritance.
Triage 2026-07-09 (tree at 68317ec) — the 2026-06-18 deferral is fully unblocked; re-scoped to the CLI move: - Both blockers named in that deferral have shipped: blueprint_from_json exists (crates/aura-engine/src/blueprint_serde.rs:207, re-exported in lib.rs:61) and the project load boundary exists (crates/aura-cli/src/project.rs — project-cdylib ∪ std vocabulary resolution). - `aura graph` is now the ONE verb still sample-bound: the no-subcommand arm renders only the embedded examples/r_sma_open.json (crates/aura-cli/src/main.rs:2645-2654), while run/sweep/mc/walkforward/generalize all consume consumer blueprint files via is_blueprint_file (:2267). - render_html(&Composite) is parameterized and self-contained (crates/aura-cli/src/render.rs:85, aura.css embedded), so `aura graph <blueprint.json>` is: read file + blueprint_from_json(env.resolve) + render_html — the same pattern as dispatch_run. - The library-packaging half (a dedicated render crate reachable by downstream Rust) has shrunk in value since the ratified consumer surface is CLI-over-blueprint-data (verb-dissolution milestone); it warrants an explicit re-decision — likely a drop — rather than silent inheritance.
Author
Owner

Design decision: CLI move only, drop the library-packaging half (/boss)

The 2026-07-09 triage flagged the library-packaging half — a dedicated,
downstream-linkable render crate (issue-body move #1) — for an explicit
re-decision rather than silent inheritance.

Decision: drop the library-packaging half; #28 is the CLI move only. Basis:
derived — the ratified consumer surface is CLI-over-blueprint-data (the
verb-dissolution milestone: a downstream researcher authors topology as data and
drives it through the aura CLI, not by linking a Rust render library). A
dedicated downstream-linkable render crate serves a consumer shape the project no
longer targets, and the CLI move fully realizes the milestone payoff — "render
YOUR graph to see mis-wiring before a run" — for the actual consumer surface.

Scope: aura graph <blueprint.json> gains a first-positional blueprint and
renders it via render_html, mirroring dispatch_run's is_blueprint_file
branch (read file → blueprint_from_json(env.resolve)render_html); the
no-argument form keeps rendering the embedded sample; the build/introspect/
register subcommands are unaffected.

The nested-composite concern (#26 — the old graph.rs unimplemented! on a
composite-within-a-composite) is moot: that ASCII render was retired, the current
render.rs::render_html serializes via model_to_json with no panic, and #26 is
already closed. No guard needed.

## Design decision: CLI move only, drop the library-packaging half (/boss) The 2026-07-09 triage flagged the library-packaging half — a dedicated, downstream-linkable render crate (issue-body move #1) — for an explicit re-decision rather than silent inheritance. Decision: **drop the library-packaging half; #28 is the CLI move only.** Basis: derived — the ratified consumer surface is CLI-over-blueprint-data (the verb-dissolution milestone: a downstream researcher authors topology as data and drives it through the `aura` CLI, not by linking a Rust render library). A dedicated downstream-linkable render crate serves a consumer shape the project no longer targets, and the CLI move fully realizes the milestone payoff — "render YOUR graph to see mis-wiring before a run" — for the actual consumer surface. Scope: `aura graph <blueprint.json>` gains a first-positional blueprint and renders it via `render_html`, mirroring `dispatch_run`'s `is_blueprint_file` branch (read file → `blueprint_from_json(env.resolve)` → `render_html`); the no-argument form keeps rendering the embedded sample; the `build`/`introspect`/ `register` subcommands are unaffected. The nested-composite concern (#26 — the old `graph.rs` `unimplemented!` on a composite-within-a-composite) is moot: that ASCII render was retired, the current `render.rs::render_html` serializes via `model_to_json` with no panic, and #26 is already closed. No guard needed.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#28