From b1f0210691307832739867205968e15bc94373d9 Mon Sep 17 00:00:00 2001 From: Bendik Aagaard Lynghaug Date: Thu, 24 Sep 2026 01:55:39 +0200 Subject: [PATCH] build: personas naming undeclared needs is the reader's mapping, not a builder bug Co-Authored-By: Claude Fable 5.1 --- src/build.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/build.rs b/src/build.rs index 309287e..54ee171 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1570,8 +1570,17 @@ pub fn run(argv: &[String]) -> anyhow::Result<()> { if let Some(lint) = value("--lint") { let output = std::process::Command::new(&lint).arg("--path").arg(out.join("questions")).output().with_context(|| format!("running {lint}"))?; - print!("{}{}", String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr)); + let stderr = String::from_utf8_lossy(&output.stderr); + print!("{}{}", String::from_utf8_lossy(&output.stdout), stderr); if !output.status.success() { + // Personas are attached from a file and name needs by id; a + // planned site whose model chose other ids fails only on + // that mapping, which is the reader's to fix, not the + // builder's. + let unmapped = stderr.lines().filter(|l| l.starts_with("FAIL")).all(|l| l.contains("points at a need that is not declared") || l.contains("unmet business need finding")); + if unmapped && stderr.contains("points at a need that is not declared") { + bail!("the site is sound, but the personas name needs this plan does not declare: map each persona's `need:` to one of the plan's ids, or rename the plan's needs, then build again"); + } bail!("the verifier rejected a deterministically built site - that is a bug in the builder, not in the words"); } }