A submitter's own moves say where they may be made from

portal compiles one access rule per state a self_transition names, and
without them assumed the day the case arrived. The builder already
knew the answer - `moves_of(need, SUBMITTER)` carries the from-state
of every move - and now writes it down, so the applicant answering a
request for papers from `incomplete` gets a rule for it, and withdrawal
is offered from wherever the case has got to.

Measured on the building authority: the submitter had two rules, both
out of `open`. It now has ten, across applications and appeals.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bendik Aagaard Lynghaug
2026-09-25 21:35:32 +02:00
co-authored by Claude Opus 5
parent 3e1c299490
commit 040a95ee07
8 changed files with 48 additions and 1 deletions
@@ -6,4 +6,8 @@ alternatives:
self_transition:
bucket: appeals
to: withdrawn
from:
- before_the_board
- open
- reconsidered
label: Withdrawn
@@ -6,4 +6,9 @@ alternatives:
self_transition:
bucket: exemptions
to: withdrawn
from:
- county_answered
- county_asked
- open
- recommended
label: Withdrawn
@@ -6,4 +6,7 @@ alternatives:
self_transition:
bucket: firms
to: checked
from:
- open
- papers_missing
label: Checked
@@ -6,4 +6,8 @@ alternatives:
self_transition:
bucket: objections
to: withdrawn
from:
- answered_by_applicant
- open
- registered
label: Withdrawn
@@ -6,10 +6,19 @@ alternatives:
self_transition:
bucket: applications
to: complete
from:
- incomplete
- open
label: Complete
- name: Withdrawn
description: ''
self_transition:
bucket: applications
to: withdrawn
from:
- complete
- incomplete
- on_hearing
- open
- recommended
label: Withdrawn
@@ -6,4 +6,8 @@ alternatives:
self_transition:
bucket: meetings
to: cancelled
from:
- met
- open
- scheduled
label: Cancelled
@@ -6,10 +6,19 @@ alternatives:
self_transition:
bucket: applications
to: complete
from:
- incomplete
- open
label: Complete
- name: Withdrawn
description: ''
self_transition:
bucket: applications
to: withdrawn
from:
- complete
- incomplete
- on_hearing
- open
- recommended
label: Withdrawn
+10 -1
View File
@@ -1595,6 +1595,15 @@ pub fn render(plan: &Plan, words: &BTreeMap<String, Value>) -> anyhow::Result<BT
let path = decide_path(need);
let w = &words[&path];
let targets: BTreeSet<&String> = theirs.iter().map(|(_, to)| to).collect();
// Where each of their moves may be made from. A person is in
// dialogue with their case for as long as it runs: the
// applicant answers a request for papers from `incomplete`,
// and withdraws from wherever the case has got to by then.
// Portal compiles one policy rule per state named here, and
// without them it assumes the day the case arrived.
let from_for = |to: &String| -> Vec<&String> {
theirs.iter().filter(|(_, t)| t == to).map(|(from, _)| from).collect()
};
files.insert(
path,
json!({
@@ -1603,7 +1612,7 @@ pub fn render(plan: &Plan, words: &BTreeMap<String, Value>) -> anyhow::Result<BT
"alternatives": targets.iter().map(|to| json!({
"name": s(&w["moves"][to.as_str()]["heading"]),
"description": s(&w["moves"][to.as_str()]["description"]),
"self_transition": { "bucket": need.lands_in, "to": to, "label": s(&w["moves"][to.as_str()]["button"]) },
"self_transition": { "bucket": need.lands_in, "to": to, "from": from_for(to), "label": s(&w["moves"][to.as_str()]["button"]) },
})).collect::<Vec<_>>(),
}),
);