test(cli): RED — graph build lacks the tier hint for namespaced ids (#244)

RED pin: graph_build_hints_attach_for_namespaced_ids_in_a_data_only_project
(graph_construct.rs e2e) — the op-script path reports OpError::
UnknownNodeType without consulting the tier-aware hint the blueprint
load path carries.

refs #244
This commit is contained in:
2026-07-12 19:55:25 +02:00
parent d79d5af036
commit 72bfdf79d1
+55
View File
@@ -1214,3 +1214,58 @@ fn graph_build_gang_on_a_bound_member_reports_unknown_param() {
"the bound member reads as an ordinary unknown param, not a gang-specific fault: {stderr}"
);
}
/// Like `run_in`, but also pipes `stdin_doc` to the child — the combination
/// `aura graph build` needs, since it reads its op-script from stdin AND must
/// discover the project from the working directory. Neither `run` (stdin, no
/// cwd) nor `run_in` (cwd, no stdin) covers both.
fn run_in_stdin(
dir: &std::path::Path,
args: &[&str],
stdin_doc: &str,
) -> (String, String, Option<i32>) {
let mut child = Command::new(BIN)
.args(args)
.current_dir(dir)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("spawn aura");
child.stdin.take().unwrap().write_all(stdin_doc.as_bytes()).unwrap();
let out = child.wait_with_output().expect("wait aura");
(
String::from_utf8_lossy(&out.stdout).into_owned(),
String::from_utf8_lossy(&out.stderr).into_owned(),
out.status.code(),
)
}
/// Property (#244): the tier-aware unresolved-namespace hint fires on the
/// op-script `aura graph build` path exactly as it does on the blueprint LOAD
/// path (`project_load.rs::data_only_project_hints_attach_for_namespaced_ids`,
/// which this mirrors). Inside a data-only project (a bare `Aura.toml`, no node
/// crate attached), an op-script referencing a project-namespaced type
/// (`nosuch::Node`) the vocabulary cannot resolve refuses non-zero AND the
/// refusal carries the tier hint — "binds no node crate" + the `aura nodes new`
/// attach verb — not the bare unknown-type error. Same consumer mistake, same
/// diagnostic quality across both entry surfaces. (The refusal/non-zero exit
/// already works today; the hint text is the absent behaviour.)
#[test]
fn graph_build_hints_attach_for_namespaced_ids_in_a_data_only_project() {
let dir = temp_cwd("graph-build-dataonly-hint");
std::fs::write(dir.join("Aura.toml"), "").expect("write bare Aura.toml");
// A single op is enough: `replay` fails fast at the unknown-type `add`.
let ops = r#"[{"op":"add","type":"nosuch::Node","name":"n"}]"#;
let (stdout, stderr, code) = run_in_stdin(&dir, &["graph", "build"], ops);
assert_ne!(code, Some(0), "an unresolvable namespaced type refuses: {stderr}");
assert!(stdout.is_empty(), "no blueprint emitted on a fault: {stdout}");
assert!(
stderr.contains("binds no node crate"),
"the data-only tier hint fires on the graph-build path: {stderr}"
);
assert!(
stderr.contains("aura nodes new"),
"the hint points at the attach verb: {stderr}"
);
}