From edb8c3791687d7ed804532ff0494470b88727420 Mon Sep 17 00:00:00 2001 From: claude Date: Tue, 21 Jul 2026 14:44:40 +0200 Subject: [PATCH] test: red for the select-rule refusal enumerating the accepted roster (refs #301) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A process document carrying an unknown select rule refuses correctly but names no accepted vocabulary; the fieldtest's bare-plateau paste (df_3) hits an opaque wall. The unit test pins the wanted property at the site that builds the prose (select_from): the refusal enumerates argmax, plateau:mean, plateau:worst beside the quoted offending value. No alias-hint sentence — the enumeration alone rescues the paste case and the project's refusal prose stays sparse; the document schema stays strict per #300 F7. --- crates/aura-research/src/lib.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/crates/aura-research/src/lib.rs b/crates/aura-research/src/lib.rs index 34cb060..f754de4 100644 --- a/crates/aura-research/src/lib.rs +++ b/crates/aura-research/src/lib.rs @@ -1381,6 +1381,38 @@ mod tests { assert!(matches!(parse_process("not json"), Err(DocError::NotJson(_)))); } + /// #301 (fieldtest cycle-300 df_3): the unknown-select-rule refusal must + /// teach the accepted vocabulary, not just refuse — an author who learned + /// bare `plateau` at the CLI pastes it into a document and needs the + /// roster (argmax | plateau:mean | plateau:worst) in the refusal prose to + /// self-serve the fix. The schema stays strict: bare "plateau" remains + /// refused in documents (#300 F7 — it is a CLI-only argv alias), and the + /// prose stays sparse — the roster only, no alias-bridging sentence. + #[test] + fn unknown_select_rule_refusal_enumerates_accepted_rules() { + let bare_plateau = PROCESS_FIXTURE.replacen("plateau:worst", "plateau", 1); + let err = + parse_process(&bare_plateau).expect_err("bare plateau stays refused in documents"); + let DocError::Malformed(msg) = err else { + panic!("expected DocError::Malformed, got {err:?}"); + }; + // The existing contract survives: the offending value stays named, quoted. + assert!( + msg.contains("unknown select rule \"plateau\""), + "offending value no longer named: {msg}" + ); + // The new behaviour: the refusal enumerates the accepted rules. + for accepted in ["argmax", "plateau:mean", "plateau:worst"] { + assert!( + msg.contains(accepted), + "accepted rule {accepted:?} not enumerated in the refusal: {msg}" + ); + } + // Precise and sparse: the roster alone rescues the paste case — no + // alias-hint sentence bridging plateau -> plateau:mean. + assert!(!msg.contains("alias"), "refusal grew an alias hint: {msg}"); + } + pub(crate) const CAMPAIGN_FIXTURE: &str = r#"{ "format_version": 1, "kind": "campaign",