Version: allium 3.5.0 (language versions: 1, 2, 3), installed via brew tap juxt/allium && brew install allium.
Bug: allium check's allium.status.unreachableValue diagnostic does not recognize ensures: clauses nested inside if/else branches as valid assignments, even though allium parse shows the AST correctly captures them as IfBlock items.
Repro (widget.allium):
-- allium: 3
entity Widget {
status: pending | approved | rejected
transitions status {
pending -> approved
pending -> rejected
terminal: approved, rejected
}
}
rule Decide {
when: Decide(widget, ok)
if ok:
ensures: widget.status = approved
else:
ensures: widget.status = rejected
}
Actual: allium check widget.allium reports:
Status 'approved' in entity 'Widget' is never assigned by any rule ensures clause.
Status 'rejected' in entity 'Widget' is never assigned by any rule ensures clause.
Expected: both statuses should be recognized as reachable, since they are assigned by Decide (conditionally). Confirmed via allium parse widget.allium that the AST correctly contains both ensures: widget.status = approved and ensures: widget.status = rejected inside the IfBlock's two branches — so this looks like a gap in the reachability analysis pass specifically, not the parser.
Impact: any rule that assigns a status conditionally (a very common pattern — e.g. approve/reject outcomes depending on a guard) produces false-positive "unreachable status" warnings for every branch, which drowns out real reachability findings (we ran into this distilling a real spec with 3 conditional branches; all 5 conditionally-assigned statuses were flagged, alongside 1 genuine issue elsewhere).
Version:
allium 3.5.0 (language versions: 1, 2, 3), installed viabrew tap juxt/allium && brew install allium.Bug:
allium check'sallium.status.unreachableValuediagnostic does not recognizeensures:clauses nested insideif/elsebranches as valid assignments, even thoughallium parseshows the AST correctly captures them asIfBlockitems.Repro (
widget.allium):Actual:
allium check widget.alliumreports:Expected: both statuses should be recognized as reachable, since they are assigned by
Decide(conditionally). Confirmed viaallium parse widget.alliumthat the AST correctly contains bothensures: widget.status = approvedandensures: widget.status = rejectedinside theIfBlock's two branches — so this looks like a gap in the reachability analysis pass specifically, not the parser.Impact: any rule that assigns a status conditionally (a very common pattern — e.g. approve/reject outcomes depending on a guard) produces false-positive "unreachable status" warnings for every branch, which drowns out real reachability findings (we ran into this distilling a real spec with 3 conditional branches; all 5 conditionally-assigned statuses were flagged, alongside 1 genuine issue elsewhere).