Found by simulating a generated site: the owner wrote "they come in, we go and look at the building, we send a quote", and the generated machine went open -> quoted. Nothing compared the machine to what the business said, so it passed. A need may now list its stages as the business describes them; each must be a state of the bucket and reachable through the handling group's desk. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L4jrCgLiKKHAEFuZUJjckH
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
7f90c14554
commit
cbbc1c0da5
@@ -79,6 +79,13 @@ pub struct Need {
|
|||||||
/// What a simulation or a live bucket report counts toward.
|
/// What a simulation or a live bucket report counts toward.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub success: Vec<String>,
|
pub success: Vec<String>,
|
||||||
|
/// Every stage the business said a case goes through, in its own
|
||||||
|
/// order, first to last. Written from how the business describes
|
||||||
|
/// its work, before any state machine exists, so that a machine
|
||||||
|
/// which quietly skips a stage ("we go and look, then we quote"
|
||||||
|
/// becoming open -> quoted) fails instead of passing.
|
||||||
|
#[serde(default)]
|
||||||
|
pub stages: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root() -> String {
|
fn root() -> String {
|
||||||
@@ -455,6 +462,25 @@ pub fn check(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for stage in &need.stages {
|
||||||
|
if !schema.has_state(stage) {
|
||||||
|
report(
|
||||||
|
Level::Fail,
|
||||||
|
format!(
|
||||||
|
"the business describes a stage {stage:?} that {:?} has no state for",
|
||||||
|
need.lands_in
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if !reached.contains(stage) {
|
||||||
|
report(
|
||||||
|
Level::Fail,
|
||||||
|
format!(
|
||||||
|
"stage {stage:?} exists but {:?} is offered no moves that reach it",
|
||||||
|
need.handled_by
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
for state in &need.success {
|
for state in &need.success {
|
||||||
if !need.done_when.contains(state) {
|
if !need.done_when.contains(state) {
|
||||||
report(
|
report(
|
||||||
@@ -841,6 +867,15 @@ mod tests {
|
|||||||
assert_eq!(model["buckets"]["projects"]["initial"], "open");
|
assert_eq!(model["buckets"]["projects"]["initial"], "open");
|
||||||
assert_eq!(model["personas"][0]["id"], "founder");
|
assert_eq!(model["personas"][0]["id"], "founder");
|
||||||
|
|
||||||
|
// A stage the business named must exist as a state.
|
||||||
|
file.needs[0].stages = vec!["open".into(), "surveyed".into(), "quoted".into()];
|
||||||
|
assert_eq!(
|
||||||
|
fails(&check(&file, &questions, &aggregates)),
|
||||||
|
vec!["the business describes a stage \"surveyed\" that \"projects\" has no state for"]
|
||||||
|
);
|
||||||
|
file.needs[0].stages = vec!["open".into(), "quoted".into(), "won".into()];
|
||||||
|
assert!(check(&file, &questions, &aggregates).is_empty());
|
||||||
|
|
||||||
file.needs[0].success = vec!["quoted".to_string()];
|
file.needs[0].success = vec!["quoted".to_string()];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
fails(&check(&file, &questions, &aggregates)),
|
fails(&check(&file, &questions, &aggregates)),
|
||||||
|
|||||||
Reference in New Issue
Block a user