feat(cli): swap the scaffold's starter node for a param-bearing Scale (#183)

The `aura new` scaffold shipped one node, a param-less Identity, so a
downstream author had no public example of a build closure consuming a
bound param — the highest-value gap the project-environment fieldtest found
(F2): a newcomer could copy a param-less node but had to read engine source
to write their first *tunable* one, which the consumer contract forbids.
Swap that single starter node for a Scale node (mirroring the std gain
operator): its schema declares a `factor` ParamSpec and its build closure
reads the bound value (`|p| Box::new(Scale::new(p[0].f64()))`), and the
starter blueprint binds `factor` so `aura run` exercises the bound-param
path with zero hand-editing.

factor is bound to 1.0 — a neutral identity default the newcomer then tunes,
not the only C7-safe value (only |factor|>1 would push the terminal `bias`
output past the bounded [-1,+1] contract; the knob is genuinely read and
multiplied each cycle). The param-reading closure is the copyable template
content #183 delivers; a hypothetical `|_|` regression is caught by the
scaffold unit test's source guard, and tests/project_new.rs re-validates the
swap by building and running the scaffold end to end.

Template-side only (#181): the frozen 0102 demo-project fixture is untouched.

closes #183
This commit is contained in:
2026-07-10 00:52:29 +02:00
parent 93a2e2bb60
commit 67f98b6bc5
2 changed files with 22 additions and 26 deletions
+3 -3
View File
@@ -64,7 +64,7 @@ fn new_scaffold_builds_and_runs_the_authoring_loop() {
let introspect = aura(&["graph", "introspect", "--vocabulary"], &proj);
assert!(introspect.status.success());
let text = String::from_utf8_lossy(&introspect.stdout);
assert!(text.contains("demo_lab::Identity"), "project id listed");
assert!(text.contains("demo_lab::Scale"), "project id listed");
let _ = std::fs::remove_dir_all(&base);
}
@@ -136,8 +136,8 @@ fn new_namespace_override_reaches_the_built_vocabulary() {
let introspect = aura(&["graph", "introspect", "--vocabulary"], &proj);
assert!(introspect.status.success());
let text = String::from_utf8_lossy(&introspect.stdout);
assert!(text.contains("custom_ns::Identity"), "overridden namespace listed: {text}");
assert!(!text.contains("demo_lab::Identity"), "default-derived namespace must not leak");
assert!(text.contains("custom_ns::Scale"), "overridden namespace listed: {text}");
assert!(!text.contains("demo_lab::Scale"), "default-derived namespace must not leak");
let _ = std::fs::remove_dir_all(&base);
}