feat(workflow): report every data reason of an unavailable affordance #64

Merged
claude merged 1 commit from MEDECA-655-affordance-all-reasons into main 2026-10-04 10:04:06 +00:00
Member

Summary

For MEDECA-655. An unavailable Affordance carried only the DFS-first data message of its guard failure. MEDECA must show every missing prerequisite under a disabled button (for example "plán projektu" and "plán nákladů").

  • Affordance gets an additive field failure: Option[GuardFailure] = None: the whole failure of the gated requires guard. None when available.
  • New public GuardFailure.dataMessages(f): List[UserMessage]:
    • Conjunction: all data leaves of all parts, DFS order, no duplicates.
    • Disjunction: only the data leaves of the first branch that has a data leaf (any one branch is enough to pass, so joining the branches would ask for every alternative).
    • Unauthorized leaves give no message.
    • The head always equals firstDataMessage, the message decide reports as Rejection.Invalid (property test over generated trees).
  • reason is unchanged.

Compatibility: source-compatible for callers that construct Affordance with 4 arguments or read its fields. A pattern match case Affordance(a, b, c, d) would no longer compile; no such match exists in this repository or in MEDECA.

Same patch on release/0.1.x: the 0.1.x PR. The workflow module is identical on main and release/0.1.x.

0.1.25 is to carry this change together with the MEDECA-630 MongoFileStore change.

Tests

  • ./mill workflow.jvm.test: 76 passed, 0 failed (63 before; +10 GuardFailureSpec, +3 AffordancesSpec).
  • ./mill workflow.js.test: 76 passed, 0 failed.
  • Pre-push ./mill __.test: passed.
  • Mutation check: joining all Disjunction branches makes 2 GuardFailureSpec tests fail.

🤖 Generated with Claude Code

## Summary For **MEDECA-655**. An unavailable `Affordance` carried only the DFS-first data message of its guard failure. MEDECA must show every missing prerequisite under a disabled button (for example "plán projektu" and "plán nákladů"). - `Affordance` gets an additive field `failure: Option[GuardFailure] = None`: the whole failure of the gated `requires` guard. `None` when available. - New public `GuardFailure.dataMessages(f): List[UserMessage]`: - `Conjunction`: all data leaves of all parts, DFS order, no duplicates. - `Disjunction`: only the data leaves of the first branch that has a data leaf (any one branch is enough to pass, so joining the branches would ask for every alternative). - `Unauthorized` leaves give no message. - The head always equals `firstDataMessage`, the message `decide` reports as `Rejection.Invalid` (property test over generated trees). - `reason` is unchanged. **Compatibility:** source-compatible for callers that construct `Affordance` with 4 arguments or read its fields. A pattern match `case Affordance(a, b, c, d)` would no longer compile; no such match exists in this repository or in MEDECA. Same patch on `release/0.1.x`: the 0.1.x PR. The `workflow` module is identical on `main` and `release/0.1.x`. **0.1.25 is to carry this change together with the MEDECA-630 `MongoFileStore` change.** ## Tests - `./mill workflow.jvm.test`: 76 passed, 0 failed (63 before; +10 `GuardFailureSpec`, +3 `AffordancesSpec`). - `./mill workflow.js.test`: 76 passed, 0 failed. - Pre-push `./mill __.test`: passed. - Mutation check: joining all `Disjunction` branches makes 2 `GuardFailureSpec` tests fail. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(workflow): report every data reason of an unavailable affordance
All checks were successful
CI / Check Formatting (pull_request) Successful in 1m14s
CI / Compile (pull_request) Successful in 2m54s
CI / Run Tests (pull_request) Successful in 3m57s
CI / Check Linting (pull_request) Successful in 2m52s
12502f8438
An unavailable Affordance carried only the DFS-first data message of its
guard failure. A caller that shows why a command is withheld could name
one missing prerequisite, and the user found the others by trial.

- Affordance gets an additive field `failure: Option[GuardFailure]`
  (default None), set to the whole failure of the gated `requires` guard.
- GuardFailure.dataMessages collects every data message: all parts of a
  Conjunction, only the first data-bearing branch of a Disjunction (any
  one branch is enough to pass), auth leaves skipped, no duplicates.
  Its head is always firstDataMessage, the message decide reports.
- `reason` is unchanged.

For MEDECA-655. To be released in 0.1.25 with the MEDECA-630 change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude merged commit 84ca292caf into main 2026-10-04 10:04:06 +00:00
Sign in to join this conversation.
No description provided.