ADR-0040: Forms and dashboards in the template¶
Status: Accepted, amended by ADR-0041 Date: 2026-10-17 Deciders: Alex Nodeland
Builds stackr's row of lattice RFC-0005's phase 1: the template's ui question, which wires artifactr's forms and dashboards (artifactr.ui, behind artifactr-ai[forms]), their types, toolset and checks, and relayr's projections of them (relayr.ui), into a generated application.
Context¶
artifactr.ui lets an agent ask a form, which pauses its run until a person answers, make a form that takes submissions without a run waiting, and show a dashboard. An application wires it in four places: its types in artifactr's Workspaces and in the agent's ArtifactWorkspace, its checks in Workspaces(checks=...), its toolset on the agent, and, with relayr, relayr.ui's projections in the followers and its events and publishers in reflexr's Workspaces. Two things were open.
- Who administers a form. The checks let only a form's author change its
schemaor close it, or whom the application'sis_adminallows; artifactr can't import grantr, so the application answers it (artifactr ADR-0075). grantr's catalogs have no action that means "administers forms". - Whether it is on by default. The template's other optional parts,
evals,bridgeandportal, are.
Decision¶
- A
uiquestion, asked only when the application has artifactr, on by default, as the other optional parts are.use_uiis the derived answer the files read, so an application on reflexr alone never has it. Without it, the application is as it was. - It is an extra of the libraries the application has already:
artifactr-ai[forms], andrelayr-ai[forms]when the bridge is on, from lattice at the commit the template was rendered from (ADR-0018), or fromlibraries_pathin lattice's own checks. - The types are registered as
artifactr.uidocuments: all ofUI_TYPESinCollaboration'sWorkspaces, so every kind a person or the agent sends is read and checked, andAGENT_TYPES(formanddashboard) besidenotein the notes agent'sArtifactWorkspace, the kinds its own tools write. Asubmissionis a person's and anappis defined and not offered: portalr shows an app's label and summary alone in phase 1. - The toolset is
artifactr.ui's defaults,ui_tools():ask_form,create_form,show_dashboardandupdate_dashboard. The notes agent'soutput_typealready includesDeferredToolRequests, whichask_formneeds. Apps are RFC-0005's phase 2, and the toolset has no parameter for them yet (artifactr ADR-0078). Its instructions gain one line: ask with a form for several answers at once, and show figures as a dashboard. - The checks are
ui_checks(); with grantr,is_adminisAccess.administers: whoever maygrantr:restricton the workspace, which its admins and the tenant's owners and admins hold and its editors and viewers don't. That is grantr's existing notion of who governs what is in a workspace (who may hide a thread or an artifact), so the template adds no action to a catalog andaccess.mdis unchanged. The actor is mapped to grantr's subject as every other check maps it, so a person's agent run is checked as the person. Without grantr, there is nois_admin, and only a form's author changes it. - The
Integrationsport and artifactr's gate are not wired, for the forms as for every other integration the template has: forms and dashboards keep their defaults, on, until the template wires lattice ADR-0027's port and artifactr ADR-0081's gate for all of them (artifactr ADR-0080). - With the bridge, relayr's followers take
Projections(**UI_PROJECTIONS). The template has no projections of its own, sorelayr.ui's are the whole set; an application that adds its own merges each mapping with them. reflexr'sWorkspacesacceptUI_EVENTSand reserve theuinamespace to the follower withUI_PUBLISHERS, besideartifactr's, so no client publishes aui:form_submitteditself.ui:form_submittedis then among the event types rules from chat are checked against, so a person may draft a rule on it. - No example rule on
ui:form_submitted. The incident timeline is the template's example of a rule acting in artifactr; a second would be code every application deletes. The generated tests check that the event reaches reflexr instead. - It is checked as everything in the template is.
check-templaterenders eighteen variants, one of them withoutui, and CI's Template job runs that one'smake checktoo. The generated tests: the notes agent asks a form, an answer that doesn't fit the schema is refused, and the run resumes with the one that does (test_collaboration.py); with grantr, an editor can't close a form someone else made and the tenant's admin can (test_access.py); with the bridge, a submission to a form reaches reflexr asui:form_submittedand a client's forged one is refused (test_bridge.py).
Options considered¶
| Option | For | Against |
|---|---|---|
is_admin as grantr:restrict on the workspace (chosen) |
An action grantr already has, held by exactly the workspace's admins and the tenant's owners and admins | It ties closing a form to restricting, which a role could separate only by a new action |
No is_admin |
Nothing to explain | No one but its author can close a form, however a workspace is run |
A new action, such as artifactr:administer |
Says what it means | A change to artifactr's catalog and every role for one template's check |
| On by default (chosen) | As the template's other optional parts are; forms and dashboards are phase 1's whole point | An application updated with copier update gains four tools on its agent unless it says no |
| Off by default | An updated application is unchanged | Unlike every other optional part |
Consequences¶
- Easier:
copier copygives the notes agent forms and dashboards, checked before they commit, and, with the bridge, an event for rules from either way of asking. - Harder: the notes agent has four more tools in its prompt.
- Not done: apps, RFC-0005's phase 2, which adds
apps.<host>at the edge and the apps setting; and portalr's renderers, which phase 1 builds in portalr, not here.