Specification · Section 2 of 14
Vocabulary
Twelve blocks, two containers and one directive, why the set is closed, and why @markdown deliberately does not exist.
ASK (produce a <stamp>, then freeze)
@choice one-of-N or many-of-N, text rows
@gallery the same, but visual: images, swatches, typefaces, cards
@input typed fields
@upload file drop. Real attachments, not links.
@link paste a URL, get a fetched preview card
@scale one or more sliders between two named poles
@order drag N items into a ranking
@connect a key to somewhere the agent cannot reach on its own
SHOW (never produce a stamp, never freeze)
@note prose, hints, warnings. Body is markdown.
@code a verbatim literal, inside the block
@example a canned value that fills an ASK block
@board task rows grouped into lanes
@chart one series of numbers, drawn as a shape
@flow steps and arrows, drawn as a diagram
SHOW, until ask= (a record; with ask= it is an ASK block and stamps once)
@card one work item: subtasks, counted progress, status
@message a message an agent proposes to send
LAYOUT (holds blocks, has no identity, cannot be answered)
@grid up to N columns, collapsing on the container
@stack one column, controlled gap
@end closes the innermost container
CONTROL
@void retract an unanswered block the conversation moved past
Sixteen blocks, two containers and one directive. The set is closed on
purpose. Almost everything an implementer is tempted to add (@confirm,
@yesno, @palette, @rate, @multi, @markdown) is one of these with an
attribute set.
The set splits on what the human sees, not on what the data is. That line
has been here since the beginning — @choice and @gallery hold identical
rows and differ only in how they are drawn — and it is the test a new block
has to pass. @board is @card’s rows in lanes, and it earns a name for the
same reason @gallery does: lanes and a checklist are two different things to
look at, and an attribute that silently changes what a block is on screen is
harder to read than a second name.
@card passes a stronger test than that. A work item drawn as a @note full
of markdown has a progress number the agent typed by hand, and a number typed
by hand is a number that can disagree with the list underneath it. A block that
counts cannot.
Two blocks change category on an attribute, and both say so out loud: @card
and @message are records until ask= turns them into questions. Nothing else
in the set does this, and nothing else should.
@markdown in particular does not exist and should not be added: it would be
@note with different escaping. @note renders markdown. @code lang=markdown
is a third thing again — show markdown source rather than render it — so the
two are deliberately not aliased.