Events → commands → views contract: available_commands, command submit, view/lens registry, events stream #15

Closed
opened 2026-10-04 20:21:33 +00:00 by peterswimm · 1 comment
Owner

Engineering half of Toilville/toilville-design#177. Revised 2026-10-04: reframed around events → commands → views. Run streaming is dropped from this issue because it's already covered by the ratified StreamEvent/FrameTurn contract (PR #6).

Additions to openapi.yaml

  1. Commands

    • GET /wishes/{id} returns available_commands[], each {command, label, input_schema, sealed_confirm?}
    • POST /wishes/{id}/commands with {command, inputs, idempotency_key} returns 202 {command_id}. The resulting fact arrives on the event stream, and a rejection arrives as wish.command_rejected.
    • The same pair for parlays.
  2. Events: GET /api/v1/events (an SSE lifecycle stream with resume and per-actor filtering; see the gateway issue). Event payload schemas come from the exported Kafka message_schema registry, not hand-written YAML.

  3. Views: GET /views?type=<event_or_entity_type>&variant=<row|card|detail|timeline|command_form>&surface=&actor= returns the resolved block spec (actor lens, then surface, then any) plus provenance and sealed_block_ids. PUT /views/... saves a lens (user provenance, validated).

  4. Forms: GET /intents/{name}/form (slot form) and POST /interactions/{id}/submit, generalising /wishes/active/hydrate.

  5. Add wish and parlay to the entity_type enum on /{entity_type}/{entity_id}/blocks.

  6. Block vocabulary (decided in Toilville/toilville-design#177, 2026-10-05)

    • Add code, diff and progress variants to the ForgeBlock union in openapi.yaml and schemas/forge_block.json. This is additive, so it's a minor version bump. Field shapes come from the design issues: Toilville/toilville-design#186 (code), #187 (diff) and #185 (progress, from the run views).
    • No confirm variant. A confirmation is a composition of existing blocks. For a renderer to see "a confirmation" and not just a section, a toggle and actions, the wire format has to carry meaning. forge_block.json has no semantic_intent or importance today, so add both as optional fields on every block. Their enums mirror UDG's: CEREMONY, ACTION_PRIMARY, STATUS_INDICATOR, MEDIA_HERO and so on, and critical | high | normal | low.
    • available_commands[].sealed_confirm is served as that composition with semantic_intent: CEREMONY and importance: critical.
  7. Lenses carry Personality, not raw tokens. A lens saved through PUT /views/... holds block arrangement plus values for the named Personality dials: accent (a validated palette id, never a free hue), density, corner softness, motion energy and atmosphere. Hero is not a dial. Each mode is a designed preset of the same dials, so resolution runs house style, then mode preset, then actor lens. Clamp values for each dial are still open in Toilville/toilville-design#189.

Acceptance criteria

  • Spec additions above, with a surface enum that includes cli.
  • Event schemas referenced from the generated components, not duplicated.
  • The breaking-change detector passes.
  • code, diff and progress are in the ForgeBlock union. There is no confirm variant.
  • Blocks carry optional semantic_intent and importance, and a sealed_confirm is served as a CEREMONY/critical composition.
  • The lens schema expresses Personality dial values and a palette id, not token values. Reset is possible both to the mode preset and to the house style.
Engineering half of Toilville/toilville-design#177. **Revised 2026-10-04:** reframed around events → commands → views. Run streaming is dropped from this issue because it's already covered by the ratified `StreamEvent`/`FrameTurn` contract (PR #6). ## Additions to `openapi.yaml` 1. **Commands** - `GET /wishes/{id}` returns `available_commands[]`, each `{command, label, input_schema, sealed_confirm?}` - `POST /wishes/{id}/commands` with `{command, inputs, idempotency_key}` returns `202 {command_id}`. The resulting fact arrives on the event stream, and a rejection arrives as `wish.command_rejected`. - The same pair for parlays. 2. **Events**: `GET /api/v1/events` (an SSE lifecycle stream with resume and per-actor filtering; see the gateway issue). Event payload schemas come from the exported Kafka `message_schema` registry, not hand-written YAML. 3. **Views**: `GET /views?type=<event_or_entity_type>&variant=<row|card|detail|timeline|command_form>&surface=&actor=` returns the resolved block spec (actor lens, then surface, then `any`) plus `provenance` and `sealed_block_ids`. `PUT /views/...` saves a lens (user provenance, validated). 4. **Forms**: `GET /intents/{name}/form` (slot form) and `POST /interactions/{id}/submit`, generalising `/wishes/active/hydrate`. 5. Add `wish` and `parlay` to the `entity_type` enum on `/{entity_type}/{entity_id}/blocks`. 6. **Block vocabulary** ([decided in Toilville/toilville-design#177](https://git.toilville.dev/Toilville/toilville-design/issues/177#issuecomment-26060), 2026-10-05) - Add `code`, `diff` and `progress` variants to the `ForgeBlock` union in `openapi.yaml` and `schemas/forge_block.json`. This is additive, so it's a minor version bump. Field shapes come from the design issues: Toilville/toilville-design#186 (code), #187 (diff) and #185 (progress, from the run views). - **No `confirm` variant.** A confirmation is a composition of existing blocks. For a renderer to see "a confirmation" and not just a section, a toggle and actions, the wire format has to carry meaning. `forge_block.json` has no `semantic_intent` or `importance` today, so add both as optional fields on every block. Their enums mirror UDG's: `CEREMONY`, `ACTION_PRIMARY`, `STATUS_INDICATOR`, `MEDIA_HERO` and so on, and `critical | high | normal | low`. - `available_commands[].sealed_confirm` is served as that composition with `semantic_intent: CEREMONY` and `importance: critical`. 7. **Lenses carry Personality, not raw tokens.** A lens saved through `PUT /views/...` holds block arrangement plus values for the named Personality dials: accent (a validated palette id, never a free hue), density, corner softness, motion energy and atmosphere. Hero is not a dial. Each mode is a designed preset of the same dials, so resolution runs house style, then mode preset, then actor lens. Clamp values for each dial are still open in Toilville/toilville-design#189. ## Acceptance criteria - [ ] Spec additions above, with a `surface` enum that includes `cli`. - [ ] Event schemas referenced from the generated components, not duplicated. - [ ] The breaking-change detector passes. - [ ] `code`, `diff` and `progress` are in the `ForgeBlock` union. There is no `confirm` variant. - [ ] Blocks carry optional `semantic_intent` and `importance`, and a `sealed_confirm` is served as a CEREMONY/critical composition. - [ ] The lens schema expresses Personality dial values and a palette id, not token values. Reset is possible both to the mode preset and to the house style.
peterswimm changed title from Interaction contract: served forms, generic submit, confirm/transition/progress specs, streaming invoke + cancel to Events → commands → views contract: available_commands, command submit, view/lens registry, events stream 2026-10-04 20:34:14 +00:00
Author
Owner

Reconciled against main (0.67.0): closing

Everything this issue asked for has landed, across five merges. Item by item:

# Asked for Where it landed
1 Wish commands: available_commands[] and POST …/commands → 202 GET/POST /api/v1/wishes/{wish_id}/commands, #16 (0.62.0). Each command gained a form in #19 (0.65.0).
1 The same pair for parlays GET/POST /api/v1/parlays/{parlay_id}/commands (0.64.0), plus GET /api/v1/parlays in #20 (0.66.0)
2 GET /api/v1/events SSE stream with resume and per-actor filtering #16 (0.62.0): LineageFact, EventsReady, EventsResync
3 Views resolved by lens, then surface, then any, with provenance and sealed_block_ids GET /api/v1/views → ResolvedView, #19 (0.65.0)
3 PUT /views/... to save a lens GET/PUT/DELETE /api/v1/lens, #19. One lens per person, not one per view path.
4 GET /intents/{name}/form Superseded: form on PatternSchema, #21 (0.67.0)
4 POST /interactions/{id}/submit Superseded: POST /api/v1/intents/{name}/run for intents (#21) and …/commands for wishes and parlays
5 wish/parlay in the entity_type enum on /{entity_type}/{entity_id}/blocks Not served yet. ritual-core/src/blocks.rs fetch_entity_data has no wish or parlay arm, and this repo documents only what the server serves. Moved to Toilville/ritual-engine#917.
6 code, diff, progress; no confirm; semantic_intent and importance forge_block.json 1.2 and openapi.yaml 0.63.0
7 The lens carries Personality, not tokens, with both resets schemas/lens.json 1.0

The acceptance criteria are all met. surface includes cli (openapi L1210, L3401); event schemas are referenced, not duplicated; there's no confirm variant; both resets work by omitting a member.

Two differences from the issue as written are intentional. Both are recorded in CHANGELOG under "Differs from #15 as written":

  • Semantics is a nested semantics: {intent, importance, variant} object rather than flat fields, because the Flutter and macOS clients already parse it that way.
  • The lens carries no accent, following ville's revision in toilville-design#189: a mode's accent is a state signal.

Housekeeping: feat/spec-blocks-views-forms (6db049c, the first draft of /views and /lens) was superseded by #19 and is deleted.

The client half continues in Toilville/toilville_rituals#496.

## Reconciled against `main` (0.67.0): closing Everything this issue asked for has landed, across five merges. Item by item: | # | Asked for | Where it landed | |---|---|---| | 1 | Wish commands: `available_commands[]` and `POST …/commands` → 202 | `GET`/`POST /api/v1/wishes/{wish_id}/commands`, #16 (0.62.0). Each command gained a `form` in #19 (0.65.0). | | 1 | The same pair for parlays | `GET`/`POST /api/v1/parlays/{parlay_id}/commands` (0.64.0), plus `GET /api/v1/parlays` in #20 (0.66.0) | | 2 | `GET /api/v1/events` SSE stream with resume and per-actor filtering | #16 (0.62.0): `LineageFact`, `EventsReady`, `EventsResync` | | 3 | Views resolved by lens, then surface, then `any`, with `provenance` and `sealed_block_ids` | `GET /api/v1/views` → `ResolvedView`, #19 (0.65.0) | | 3 | `PUT /views/...` to save a lens | `GET`/`PUT`/`DELETE /api/v1/lens`, #19. One lens per person, not one per view path. | | 4 | `GET /intents/{name}/form` | Superseded: `form` on `PatternSchema`, #21 (0.67.0) | | 4 | `POST /interactions/{id}/submit` | Superseded: `POST /api/v1/intents/{name}/run` for intents (#21) and `…/commands` for wishes and parlays | | 5 | `wish`/`parlay` in the `entity_type` enum on `/{entity_type}/{entity_id}/blocks` | **Not served yet.** `ritual-core/src/blocks.rs` `fetch_entity_data` has no `wish` or `parlay` arm, and this repo documents only what the server serves. Moved to Toilville/ritual-engine#917. | | 6 | `code`, `diff`, `progress`; no `confirm`; `semantic_intent` and `importance` | `forge_block.json` 1.2 and `openapi.yaml` 0.63.0 | | 7 | The lens carries Personality, not tokens, with both resets | `schemas/lens.json` 1.0 | The acceptance criteria are all met. `surface` includes `cli` (openapi L1210, L3401); event schemas are referenced, not duplicated; there's no `confirm` variant; both resets work by omitting a member. Two differences from the issue as written are intentional. Both are recorded in CHANGELOG under "Differs from #15 as written": - Semantics is a nested `semantics: {intent, importance, variant}` object rather than flat fields, because the Flutter and macOS clients already parse it that way. - The lens carries no accent, following ville's revision in toilville-design#189: a mode's accent is a state signal. Housekeeping: `feat/spec-blocks-views-forms` (6db049c, the first draft of `/views` and `/lens`) was superseded by #19 and is deleted. The client half continues in Toilville/toilville_rituals#496.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
You do not have permission to read 1 dependency
Reference
Toilville/rituals-api-spec#15
No description provided.