From 89d703dd99c0128d0f44511cb661f5c7c8d86141 Mon Sep 17 00:00:00 2001 From: claude Date: Mon, 13 Jul 2026 23:50:48 +0200 Subject: [PATCH] =?UTF-8?q?test:=20red=20executable-spec=20for=20#261=20?= =?UTF-8?q?=E2=80=94=20SessionFrankfurt=20preset=20reachable=20from=20blue?= =?UTF-8?q?prints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A data-only op-script naming the roster id SessionFrankfurt must resolve to a Frankfurt-baked Session preset (09:00 Europe/Berlin baked, one period_minutes: I64 knob, bars_since_open: I64 out) and build to a finished Composite. Fails on std_vocabulary returning None — the preset is absent from the roster; fork decision on the issue. refs #261 --- crates/aura-engine/src/construction.rs | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/crates/aura-engine/src/construction.rs b/crates/aura-engine/src/construction.rs index f601e9a..ffa93e7 100644 --- a/crates/aura-engine/src/construction.rs +++ b/crates/aura-engine/src/construction.rs @@ -659,6 +659,51 @@ mod tests { assert_eq!(names, ["length"]); } + /// #261 — the Frankfurt `Session` preset is reachable from a blueprint. The + /// property this pins: a data-only op-script (a blueprint) that names the + /// preset's closed-roster type-id resolves it through `std_vocabulary`, + /// carries its one scalar `period_minutes` knob and the `bars_since_open: + /// i64` session-index output, wires its `trigger` input through the ordinary + /// edge convention, and builds to a finished `Composite`. Reachability is the + /// whole ask — the node's tz-aware/DST session SEMANTICS are already pinned + /// in `aura-std/src/session.rs` and are not re-pinned here. Today the preset + /// id is absent from the roster (the base `Session` builder takes structural + /// construction args, so the zero-arg macro cannot host it), so the lookup + /// returns `None` and the op-script's `Add` would fail `UnknownNodeType`. + #[test] + fn session_frankfurt_preset_is_reachable_from_a_blueprint() { + // (a) the preset resolves through the closed roster as the Session preset + // — its one scalar knob and its i64 session-index output, not some + // other node parked under the id. + let preset = std_vocabulary("SessionFrankfurt") + .expect("the Frankfurt Session preset is in the std vocabulary roster"); + assert_eq!(preset.label(), "SessionFrankfurt"); + let schema = preset.schema(); + assert_eq!(schema.params.len(), 1, "exactly one scalar knob"); + assert_eq!(schema.params[0].name, "period_minutes"); + assert_eq!(schema.params[0].kind, ScalarKind::I64); + assert_eq!(schema.inputs.len(), 1); + assert_eq!(schema.inputs[0].name, "trigger"); + assert_eq!(schema.output[0].name, "bars_since_open"); + assert_eq!(schema.output[0].kind, ScalarKind::I64); + + // (b) an op-script naming that id builds: a bound trigger source feeds the + // preset's `trigger`, its `period_minutes` knob binds, and the i64 bar + // index exposes — a data-only blueprint reaching the session stream. + let ops = vec![ + Op::Source { role: "trigger".into(), kind: ScalarKind::F64 }, + Op::Add { + type_id: "SessionFrankfurt".into(), + as_name: Some("session".into()), + bind: vec![("period_minutes".into(), Scalar::i64(15))], + }, + Op::Feed { role: "trigger".into(), into: vec!["session.trigger".into()] }, + Op::Expose { from: "session.bars_since_open".into(), as_name: "bars".into() }, + ]; + super::replay("session_blueprint", ops, &std_vocabulary) + .expect("the preset resolves, wires and builds through an op-script"); + } + /// Eager refusals: unknown member param (a member bound at `Add` has left the /// open schema), kind mismatch across members, a doubly-ganged member, a /// single-member gang, and an unknown node identifier.