The served trace chart's x-axis no longer plots against raw timestamps by
default — non-trading gaps (nights, weekends) left horizontal blanks that
dominated the view. The x spine is now ordinal by default: every recorded slot
sits at an even position, so gaps collapse and the signal fills the width. A
header toggle flips to continuous (real-time-proportional) spacing and back;
default ordinal honours the requested "x-axis should not be continuous", with
continuous as the one-click option.
Comfort, all on the read/render side (the engine and the Rust serve contract
are untouched — window.AURA_TRACES still carries the real xs, the ordinal
indices are derived client-side):
- ordinal mode keeps the axis honest: ticks and the legend value-readout map a
collapsed index back to the real xs[i], never the index itself.
- wheel-zoom (x, cursor-anchored), drag-pan, double-click-reset on the plot
(uPlot's default drag-box-zoom is disabled so drag pans).
- panels share a cursor.sync key, so the crosshair lines up across stacked
panels.
Confined to chart-viewer.js (buildCharts gains an xMode param + a wheelZoomPlugin
factory; mount re-renders on the toggle) and render.rs (CHART_HEAD toggle button
+ a chart-only style). The two twin node guards (build/gaps) re-point to the
ordinal default in lockstep; a new x-mode guard pins ordinal-default / continuous
/ panel-sync / plugin wiring, and a label-honesty guard (gappy-traces fixture,
xs far from the index spine) pins that ordinal ticks report the real timestamp.
Verified: cargo test --workspace green (incl. the four chart guards + render
inline tests), clippy --all-targets -D warnings clean, e2e (aura run --trace +
aura chart) emits a self-contained page defaulting to ordinal with the toggle.
Spec docs/specs/0057, plan docs/plans/0057 (boss-signed; grounding-check PASS).
Derived-fork decision log in the issue comments.
closes#103
Iteration 2 (serve half) of the visual face — spec 0056 / plan 0056:
read a persisted run's traces and serve them as a self-contained uPlot
HTML chart. Completes the goal "tap data from a graph, serve it as a
chart in the browser".
- chart-viewer.js (first-party): a pure buildCharts(traces, mode) that
maps the injected window.AURA_TRACES to uPlot configs (no DOM) — overlay
= one plot, every series on its own y-scale over the shared xs; panels =
one plot per series, all on the same timestamp x. A browser-only mount()
instantiates the vendored global uPlot. Guarded by a node .mjs DOM test
(+ a sparse/gaps variant) shelling out exactly like viewer_dot.rs.
- render_chart_html + ChartMode/ChartData/Series (aura-cli/render.rs):
mirrors render_html — self-contained page, uPlot (1.6.32, vendored
d534f10) + chart-viewer.js inlined via include_str!, data injected as
window.AURA_TRACES.
- emit_chart + build_chart_data (aura-cli/main.rs): the spec-§6 3-step
union-spine alignment — xs = sorted-dedup union of every tap's ts; a
synthetic empty-payload spine + ALL taps as symmetric join_on_ts sides
(no tap privileged, no point dropped); flatten each (tap,column) to a
Series of Option<f64>. New arms `aura chart <name> [--panels]`; a
missing run is stderr + exit 2 (TraceStoreError::NotFound), never a
panic. USAGE advertises the verb in lockstep.
Verified by the orchestrator: `cargo test --workspace` green (incl. the
node guards, render_chart_html, and the chart e2e); `cargo clippy
--workspace --all-targets -D warnings` exit 0; and a real end-to-end —
`aura run --trace demo && aura chart demo` emits a 57KB self-contained
page (doctype + inlined uPlot + AURA_TRACES carrying the equity/exposure
series), `--panels` reflects the panels mode, `aura chart nope` exits 2.
Implementer deviation folded in (compiler-prescribed): serde added to
aura-cli/Cargo.toml for the Series derive (Cargo.lock updated).
refs #101