Slot form: the form vocabulary toilville-design#178 requires, and form_schema is untyped #23
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Toilville/rituals-api-spec#23
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?
toilville-design#178 (slot form) is decided and accepted. It is the most-used pattern and most of the others build on it. Its engineering follow-up, in ville's words:
The renderer half belongs to the clients. The schema half has no contract, and the part that does exist is untyped. That is what this issue is for.
Companion to #22, which covers the command vocabulary. This one is the form vocabulary. They meet at item 4.
What the spec says about a slot today: nothing
PatternSchema.form_schemais the whole declaration:There is no
Slotschema, no field kinds, no attributes. AndPatternSchemadoes not declareattributesat all, whichGET /patterns/{name}does emit (ritual-server/src/main.rs:2991) — so the spec is behind the server on the one field the slot list actually travels in.The live path is the one the client calls legacy
macOS resolves slots like this (
apps/rituals-macos/Networking/ForgeAPIClient+Patterns.swift:130):slotsarray from the server;attributes.input_schema, an array of{key, label, type, required}.Step 1 never fires. There is no
slotscolumn oncore.patterns(ritual-core/src/schema/core.rs:624), and neitherGET /patterns(main.rs:2925) norGET /patterns/{name}emits aslotskey. The only"slots"in the engine isritual-core/src/wish_slots.rs, which is model-extracted wish slots in a tool-call result — a different concept entirely.So every slot in production comes from step 2, which hardcodes:
Two of the six documented slot attributes are therefore unreachable, and one of them is a #178 deliverable. ville's decision requires:
A sealed slot cannot be expressed, so that state is undeliverable. The client's own test says so out loud —
ForgeAPIClientPatternsTests.swift:131: "synthesized bridge slots default to fungible — sealed is unrecoverable from the legacy shape". That assertion has been passing as a description of the bug.GET /patterns(the list) also omitsform_schemaandformentirely, while the spec documents both on the sharedPatternSchema. Both are optional, so nothing is strictly invalid, butform's description ("null otherwise") reads as present-but-null when the list omits the key.What to add
1. A declared
Slot, replacing the untypedform_schemaToday's vocabulary, from
SlotDTO(ForgeAPIClient+Patterns.swift:44) and #178:key/name,label,type,required,mutability(sealed|fungible),default_value. Declare it, and settle thekeyvsnamesplit while doing so —SlotDTOdecodesname, theattributes.input_schemafallback readskey, and #178's text sayskey.Then decide whether a slot list stays inside
attributes, moves to a declaredslotsmember (which the client already expects and nothing serves), or becomes a JSON Schema inform_schemawith the extras beside it. All three are live in the code right now.2. The field kinds #178 adds
typeistext | textarea | enum | int | booltoday. #178 decides these as well:date,time--field, and a stored secret is never shown in clear textsecretis the one with a security consequence, not just a presentation one: #178 forbids it on the CLI flag path, so the contract has to mark it before the CLI can refuse it.schemas/forge_block.json'sInputElementalready covers text (withmultiline), number, date, time, toggle and choice (withmulti_selectandstyle). It has nosecret, nofileand no entity picker.3. The per-field attributes
Against the current block vocabulary:
InputBlock.hint✔TextInputElement.placeholder,NumberInputElement.placeholder✔AvailableCommand.required_inputscovers a command's inputs; a standalone slot form has nothing. #178 wants*with the accessible name "required"ChoiceOptionis{label, value}. #181 requires "a short description for each", read with its optionChoiceInputElement. #181: "the schema supplies … the default (Done). The renderer does not hard-code the default"sectionblocklength_at_leastTextInputElementhasmax_lengthand no minimummatches_patternequals(conditional visibility)4. Where the rules live — settle this first
#178 asks for three field-level rules —
equalsfor conditional visibility,length_at_leastandmatches_patternfor validation — and adds:There are two candidate homes and the code currently implies both:
AvailableCommand.input_schemais "JSON Schema of the command's input form", and JSON Schema already spells all three:minLength,pattern, andif/thenfor visibility.POST /patterns/{name}/validatevalidates againstform_schemathis way.command_formview made of ForgeBlocks, and a renderer renders blocks. A rule a renderer never reads cannot hide a field or show an error under it.Deciding this is engineering, not design — #178 says so — but it has to be decided before any of items 2 and 3 can be written down, because it determines which document they go in. Note two constraints that follow from #178 regardless of the answer:
GateExpressionis unaffected. It stays a step-level mechanism and needs no new types. Validation, conditional visibility and step gating are three separate behaviours.5. Not in scope
secret, item 2.ritual_clifrom theritualbinary; that split is a client question.Acceptance
Slotschema exists,form_schemais no longer the only declaration, andattributesis declared or the slot list has moved out of it.ForgeAPIClientPatternsTests.swift:131's assertion is replaced by one that proves it round-trips rather than one that records that it cannot.secretis markable, so the CLI can refuse it through--field.CLAUDE.md. Sequence: spel → ritual-engine → here.Blocks
_ParametersPanelinritual_execution_screen.dartcannot migrate to a served slot form until the form is expressibleDesign side is closed: toilville-design#178 is decided and accepted. Nothing here needs a design answer.