bc88e18247
Builder: NodeHandle::param -> ParamRef, GraphBuilder::gang, build() resolves
the gang table (collect-then-reject, BuildError::{UnknownParam,AmbiguousParam,
BadGang}) and terminates in Composite::with_gangs — the same predicate the
op-script and serde boundaries use. C24 lockstep extended: an op-script gang
replay serializes byte-identically to the GraphBuilder twin (FlatGraph edges +
sources + canonical JSON).
Render: model_to_json emits a per-scope gangs fragment (name, kind, [node,pos,
"param"] members) for ganged scopes only — the gang-free model stays
byte-identical (model_golden untouched). graph-viewer.js annotates a ganged
open param with its public knob name; guarded by a viewer_gang_param.{mjs,rs}
pair RED-first per the established viewer_bound_param convention (a welcome
extra beyond the plan's file list).
Ratified deviation: the model's kind string uses the serde form ("I64") — the
plan's implementation snippet (kind_str -> "i64") contradicted its own test;
resolved toward the test + the blueprint_serde form. Two quality nits held as
principled plan-holds (inline resolution block; the unreachable unwrap_or
placeholder check_gangs refuses first).
Verified: aura-engine lib 264/0 (model_golden, lockstep, builder, carrier all
green), viewer_gang_param 1/0, workspace clippy -D warnings clean. Slice
resumed across a transient API failure via workflow resume (cached prefix).
refs #61
38 lines
1.4 KiB
Rust
38 lines
1.4 KiB
Rust
//! Integration guard: the `aura graph` viewer decorates a ganged param slot
|
|
//! with its public gang name, and leaves a gang-free scope's slots bare.
|
|
//!
|
|
//! The property lives in JavaScript (`cellLabel`'s `gangFor` lookup in
|
|
//! assets/graph-viewer.js), so this shells out to `node` running the headless
|
|
//! guard `tests/viewer_gang_param.mjs`, which loads the real viewer module and
|
|
//! drives the exported `genDot` over two minimal models (one ganged, one not).
|
|
//!
|
|
//! `node` is REQUIRED: if it is not on PATH this test FAILS (a skipped guard is
|
|
//! not a guard).
|
|
|
|
use std::path::PathBuf;
|
|
use std::process::Command;
|
|
|
|
#[test]
|
|
fn viewer_annotates_a_ganged_param_slot() {
|
|
let script = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.join("tests")
|
|
.join("viewer_gang_param.mjs");
|
|
assert!(script.exists(), "guard script missing at {}", script.display());
|
|
|
|
let out = match Command::new("node").arg(&script).output() {
|
|
Ok(out) => out,
|
|
Err(e) => panic!(
|
|
"node is required for the viewer gang-param guard but could not be run \
|
|
({e}); install Node.js or ensure `node` is on PATH"
|
|
),
|
|
};
|
|
|
|
let stdout = String::from_utf8_lossy(&out.stdout);
|
|
let stderr = String::from_utf8_lossy(&out.stderr);
|
|
assert!(
|
|
out.status.success(),
|
|
"viewer gang-param guard failed (exit {:?}).\n--- node stdout ---\n{stdout}\n--- node stderr ---\n{stderr}",
|
|
out.status.code()
|
|
);
|
|
}
|