diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cabf2c..ac9911b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ One line per change, grouped by the release that shipped it. Newest first. Each release names the portal tag it is built against. +## Unreleased + +- The effort budget counts what a person fills in: a `type: record` field (the case an answer is about, carried on the link) and a `hidden` preset are not asked and no longer count. An objection page whose form carried the application's id used to be one field over. + ## 0.5.6 (2026-09-30) - portal v0.5.6 - Matches portal v0.5.6 (released by portal's publish job). diff --git a/src/needs.rs b/src/needs.rs index c462c05..032882b 100644 --- a/src/needs.rs +++ b/src/needs.rs @@ -157,11 +157,14 @@ fn visible(q: &Question, as_group: Option<&str>) -> bool { } } +/// What a person has to fill in: required fields, less the ones that +/// carry rather than ask - a `record` naming the case an answer is +/// about, a `hidden` preset - which cost nobody anything. fn required_fields(alt: &Alternative) -> usize { alt.features .iter() .flat_map(|f| &f.requirements) - .filter(|r| !r.optional) + .filter(|r| !r.optional && r.kind != "record" && r.kind != "hidden") .count() } @@ -860,6 +863,19 @@ mod tests { let (questions, aggregates) = site(FULL_DESK); let findings = check(&needs(" max_fields: 1\n"), &questions, &aggregates); assert_eq!(fails(&findings), vec!["the path asks for 2 required field(s), over the budget of 1"]); + // A field that carries rather than asks is not effort: the + // record an answer is about arrives on the link. + let (mut questions, aggregates) = site(FULL_DESK); + let front = questions.get_mut("/").unwrap(); + let brief = &mut front.alternatives[0].features[0].requirements; + let mut carrier = brief[0].clone(); + carrier.name = "case".into(); + carrier.kind = "record".into(); + carrier.of = Some("projects".into()); + carrier.optional = false; + brief.push(carrier); + let findings = check(&needs(" max_fields: 2\n"), &questions, &aggregates); + assert!(fails(&findings).is_empty(), "{findings:?}"); } #[test]