Rituals views: how a wish's available commands are presented #181
Labels
No labels
build-dist
priority
P1
priority
P2
priority
P3
priority
P4
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Toilville/toilville-design#181
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #177. Revised: this was "wish edit and status change". You no longer design the status rules. The API supplies them.
What it's for: how a wish's available commands look.
GET /wishes/{id}will returnavailable_commands[]: the actions allowed from the current state (start, complete, cancel, reopen, block, set priority, declare a dependency, patch fields), each with its input fields. Buttons map one-to-one to commands, so no client hard-codes which status can follow which.Please design
Acceptance criteria
peterswimm referenced this issue from Toilville/rituals-api-spec2026-10-04 20:21:33 +00:00
Rituals pattern: wish edit and status changeto Rituals views: how a wish's available commands are presentedDecisions for #181 (wish commands). They answer the acceptance criteria. They are written for wish commands. #183 can reuse them for parlay commands. The command list, ranks, severities and input schemas come from the command contract. The renderer never derives them from a command name, its inputs or the wish state. Styling follows the existing tokens.
Order and placement
criticalimportance alone does not forbid being primary.Commands and inputs
Complete
equalsrule for the dispositions that need a replacement. There is no special case for the command name.Confirmation
none, Simple, Review, Ceremony or Destructive. #182 is the authoritative list of severity values. A missing or invalid value is a contract error. It does not mean "no confirmation".Change summary
States after sending
Commands that are not available
CLI
Accessibility (Grammar)
@peterswimm
Accepted. This answers the three acceptance criteria, and "the contract declares, the renderer places" is the right division — it is held consistently all the way through, including the refusal to special-case Complete by command name. The Tier 2 floor for an authoritative command list also matches the client rule that nothing contacts the Forge below Tier 2.
Engineering consequences filed separately, no design input needed on either: toilville/toilville_rituals#577 (per-command rank and importance needs a schema move —
intentandimportanceare block-level today, so a command cannot carry its own) and toilville/toilville_rituals#578 (min_tieris decoded in Flutter and never gated on, while macOS implements it — a pre-existing parity defect that your locked-command rules now govern).Four things block implementation
Each wants a sentence, not a redesign.
1. Nothing exits Pending. The sent command is disabled, there is no optimistic update, and no timeout is defined. If the result never arrives, that command stays disabled indefinitely with no path to Failed — and Failed is the only state carrying a recovery action. #183 already requires a visible Cancel on every waiting state. Does the command lifecycle contract own the Pending → Failed transition, or should #181 define a way out?
2. Simple severity with no inputs has no confirmation. "A command with no inputs runs from its command action, under its declared severity", but "Simple: submitting the completed form is the confirmation, with no second dialog" — with no inputs there is no form to submit. #182's CLI section says Simple is
[y/N]. So the same severity behaves differently in the two surfaces for the same command. Is Simple-with-no-inputs one click, or a lightweight confirmation?3. Rank has no contract-error rule. A missing or invalid severity is a contract error. Two commands declared primary, and a Destructive command declared primary, are not covered — and the second is the one case where the renderer must override a declared rank, against the opening rule that it never derives placement. Are both contract errors, or does the renderer silently demote?
4.
noneextends #182's enum. #182 ratified four levels. #181 requires a fifth member,none, on the same setting, and makes a missing value an error rather than a synonym for it — which is the right call, but it means the authoritative member list now lives in two issues. Amending #182 would give it one home.Three edits to sibling issues
Not new design. Say the word and I will make them.
5. "There is no per-field accept" contradicts #187's acceptance criteria, which require accept all, accept some, or nothing, per change. Defensible — a field patch is not a file diff — but then the change summary borrows #187's visuals without being the diff-then-apply pattern, and #187 should say so in both directions, so nobody builds partial-accept machinery for wish patches or assumes reuse the other way.
6. #187's "conflicts with a newer version" state becomes unreachable for wish commands under "a generic 409 is a rejection, the renderer does not guess that it is a concurrent-edit conflict". Agreed on the rule, but that state now depends on a distinct conflict result the API does not return, so it is an engineering dependency rather than a design deliverable.
7. Applied does not mention lineage. "The wish updates from the authoritative result. That is the lasting evidence." #177 seals the lineage proof line, #187 says every apply writes a lineage entry, and the client rule is that every action produces an auditable record. Does a wish command write a lineage entry, and does Applied show the proof line?
Smaller, non-blocking
ritual_clifrom theritualbinary. Wishes exist only in the latter, which already has named verbs —ritual wish start / complete / cancel / reopen / depend.ritual wish browseis not covered. It is a full-screen triage console and the place wish commands actually get used in bulk. It is neither the graphical UI nor a one-shot CLI prompt.One scope question
This is prose, and #177 defines a view's deliverable as a
block_specsentry. Is the presentation spec in the first acceptance criterion closed by this comment, or does it still want a spec entry and a rendered comparison? Asking because of toilville/toilville_rituals#301 — the token comparison artifact there went a long time without a link anyone could open.My answers to the four blocking points (2026-10-20):
none, so there's one authoritative list.Scope: accept the three sibling edits as written. The presentation spec in your comment counts as the spec, and a rendered comparison can be a separate request. @ville, over to you to update #181 and #182 and proceed.
All requested follow-up edits are now in #181 and #182. I also added the two accepted clarifications to #187. The lineage point is now resolved in #181 as well. Ready for close/review.
Closing — decided. All four blocking points are folded in, and the engineering dependency is filed.
I re-read your decision comment and confirmed each of the four answers landed:
none. ✔Plus the lineage point: "A successful wish command that changes the wish writes a lineage entry, and Applied shows the resulting lineage proof line." ✔ And the three sibling edits are in #187.
What blocks implementation is now one issue, not a design question
Toilville/rituals-api-spec#22. Your opening rule — the contract declares, the renderer places — is the right division, and it turns out no surface declares any of it. I measured all three:
core.wish_available_commandsritual-core::AvailableCommandopenapi.yamlcommand,label,to_status,required_inputs,input_schema,formNo
rank, noimportance, noseverity, nolocked/reason/next-step, no timeout, no lineage reference.Outcomeisapplied | noop | rejected | duplicatewith noconflict, andWishCommandResultcarriesreasonbut noerrors.Worth stressing that this is not spec drift — the three agree with each other. The vocabulary simply does not exist yet, so #22 sequences it spel → ritual-engine → spec, which is the order that repo requires.
One thing already satisfied, recorded so nobody re-opens it: your "a retry reuses the same command ID" works.
WishCommandRequest.command_idis documented as "Idempotency key … Generated when absent", andritual-coreexposeswith_command_id. The client has to mint it rather than let the server generate one, or a transport failure means the key was never learned — but that is a client rule, not a contract gap.The four smaller points, for the record
Not blocking, and not design asks:
ritualbinary, which already has named verbs (ritual wish start / complete / cancel / reopen / depend). The Dartritual_clihas no wish surface.ritual wish browse— the full-screen triage console is where wish commands get used in bulk. Neither the graphical UI nor a one-shot prompt. Treating it as a third surface of this decision rather than a gap in it.Engineering issues that carry this forward: rituals-api-spec#22, and Toilville/toilville_rituals#577 (rank/importance attach to a command, not a block), #578 (
min_tier), #581 (confirmations as a composition), #583 (screen migrations).