test: red for the select-rule refusal enumerating the accepted roster (refs #301)

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.
This commit is contained in:
2026-07-21 14:44:40 +02:00
parent 0a70f67711
commit edb8c37916
+32
View File
@@ -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",