Cinatra — Application Design — Agent run & review

The agent run surface under /agents — the run's steps down a left rail, its detail on the right, and the lifecycle-interception gates that pause it, resolved in place inside the run rather than on any standalone page. Its central gate is the generic artifact-review gate: the type-agnostic surface on which a human continues with, regenerates, comments on, or — through the run's conversational prompt window — requests changes to an artifact the run produced. It is referenced by Application Design — Artifacts (§ Change review). This page specifies the design only — how the run engine implements the gate is specified with the engine, not here. Part of Cinatra Application Design; match it exactly.

Version 0.15.0

I. The agent run surface — steps, gates & detail

/agents · left step rail · right run detail

A run is one page, read down a rail. An agent run opens at its own canonical route under /agents. The surface is a two-column frame: a step rail down the left names the run's ordered steps, and the run detail on the right shows the selected step. Nothing about the run lives on a separate page — every step, and every gate that pauses the run, is reached by selecting its entry on the rail and reads in the same run.

The step rail — merged steps and gate entries. The rail lists the run's steps in order, merged so that a gate is not a page outside the run but a step in the run: the ordinary work steps, and — inline at the point the run reached it — a gate entry (a Skills step to answer, a list to pick one thing from, a review to decide). The step the run is paused on is highlighted; steps already passed sit above it, steps still to come below. A resolved gate stays on the rail as read-only history — its entry keeps its place and records how it was settled (continued, superseded by a regeneration, changes requested), so the rail is the run's whole lifecycle at a glance, not just its live tip.

The run detail. Selecting a step opens it on the right. A work step shows what it did; a gate step opens the gate's own surface in place — a pending review renders the review gate (§III–§VII) right here in the run detail, under the same rail, never as a standalone document. A resolved gate opens read-only: what was decided, and the one target it froze, kept for the run's audit trail.

Example — the run surface (left step rail · right run detail, paused on a review gate)
Skills
Fetched Q3 cohort
Drafted re-engagement email
Review
3Send sequence
Review requested Awaiting your decision

The gated step opens its review here in the run detail — gate header, the one review target, decision bar and the prompt window — under the same rail. The reviewer decides in the run, with the steps in view. One artifact per review: a run that made several raises one of these per artifact, in order (§I.3).

A pending gate deep-links to the run

When a run pauses on a gate that needs a human, the notification it raises (Application Design — Notifications) deep-links straight to that gate inside the run — it opens /agents at the run with the gated step selected and the rail's resolved-gate history intact, never at a detached review page. Acting on the notification and opening the run reach the same in-run gate.

One page per gate — the step's own card, and nothing else. Selecting a step opens that step's page in the run detail, and the page carries the one card of the step it belongs to. A gate that has already been answered is read the same way, by selecting its own step: an answered Skills row is never drawn above the HITL card, the review card, the schedule card or any other card, and two cards are never stacked in one detail.

Opening the Skills step twice gives two readings. Opened before the run starts, the step's page carries the row with the boxes still able to take a change and Continue beneath them: a reader may come back and change the selection, and Continue keeps it. Opened once the run has started, the same page carries the same pills read-only, with no Continue. Both readings are the row and nothing else; the anatomy of the pill and its box is fixed in Lifecycle cards §V.

Example — the Skills step opened before the run starts (the boxes still take a change, Continue beneath them)
Skills
1Fetch cohort
2Draft email
3Review
4Send sequence
Enrich contacts by Northstar Draft email by Cinatra Schedule send by Acme Corp
Example — the Skills step of a run that has started, opened on its own page (the boxes read-only, no Continue)
Skills
Fetched Q3 cohort
Drafted re-engagement email
Review
3Send sequence
Enrich contacts by Northstar Draft email by Cinatra Schedule send by Acme Corp

While the run works, the detail carries a placeholder. A run that will ask for a review carries, in the run detail, the run progress card — and while the run is working that card is a placeholder for the review screen: the card frame, and a spinning icon, the indigo arc of Components § Skeleton / Spinner. It names no status, reports no result and draws nothing to press.

It is replaced, in place, when the output is generated. The placeholder becomes the Review requested gate above — the same detail, under the same rail. It happens on its own: there is nothing for the reader to open or press to bring it.

Example — one run detail, two readings: the placeholder, then the review
Before — the output has not been generated
Skills
Fetched Q3 cohort
Drafted re-engagement email
4Review
Agentic Run Progress
After — the output was generated
Skills
Fetched Q3 cohort
Drafted re-engagement email
Review
Review requestedAwaiting your decision

One run detail, twice, in the same column under the same rail: first the placeholder, then the gate itself.

A schedule is a step on the rail, never a card in the detail. Where the run carries a schedule, the rail's first entry is Schedule, above the run's work steps and above Review. Selecting it opens the schedule to the right of the rail, in the run detail, exactly the way every other step opens — never directly under a step, and never as a card among the review cards: a schedule decides when the run happens, and a review exists only after it has happened, so the two are never on screen together.

What opens is the scheduling form, and only the scheduling form. The detail carries the standard scheduling step (Components § Standard scheduling step) on the values that are set — the same heading, the same three option rows, the same estimated duration — with no summary panel above it, no status label, no held-steps list and no Adjust to press first. The rows are the reading, and changing a row is how the schedule is changed. Save changes closes the form, and is quiet until a row actually changes. For a recurring schedule it is joined by Cancel schedule, which stops the recurring schedule and then leaves the scheduler no longer editable; a one-off schedule never carries it. There is no Run now. Beneath the form the run’s prompt window (§IX) sits where it always sits — below the scheduler, in the same column.

Before the schedule fires, the rail carries Schedule alone and the detail carries the form alone. Nothing has run yet, so there are no work steps under Schedule and no run-progress card beside it. Once it fires, the run’s own steps appear on the rail beneath Schedule and the detail carries the ordinary run-progress reading.

What a fired schedule still allows depends on which schedule fired. A run set to Run right after setup or Schedule for later is spent when it fires: its Schedule entry settles on the rail, and opening it shows the form read-only, with no controls at all. A run set to Recurring is not spent — it has runs still to come — so its Schedule entry stays an ordinary reachable row on the rail, and opening it shows the same editable rows, the same Save changes and the same Cancel schedule as before the fire; a change applies to the runs still to come. Pressing Cancel schedule stops the recurring schedule, and the scheduler is not editable after that.

Example — the run’s Schedule step, a recurring schedule set
1Schedule
When should this run?
Run right after setup
Schedule for later
Recurring
Repeat every
1
week(s)
On
Sun Mon Tue Wed Thu Fri Sat
At
09
:
00
Timezone
Europe/Berlin
Estimated run duration
About 45s – 3.4 hr.
Ask Cinatra to set the schedule above, or ask about it…
Example — after a one-off schedule fires
1Schedule
Step 1
Agentic Run Progress completed
Run complete

This run finished. Its output is in the run transcript below.

Example — after a recurring schedule fires, the Schedule step reopened
1Schedule
Step 1
When should this run?
Run right after setup
Schedule for later
Recurring
Repeat every
1
week(s)
On
Sun Mon Tue Wed Thu Fri Sat
At
09
:
00
Timezone
Europe/Berlin
Estimated run duration
About 45s – 3.4 hr.
Ask Cinatra to set the schedule above, or ask about it…

I.1 · The stored-ideas step — a list of what is stored, and one pick

Run rail · a gate that lists · one pick · Agents Lifecycle (C) §5.1 · §6 step 2

A gate that offers a list, not a field. A gate entry may pause the run to have a person choose one thing the organisation already has. An agent's declared list step is that gate drawn: its page carries one row per entry the agent's declared list offers — which entries it offers, and which it holds back, is the agent's declaration too — each row carrying the title the declaration binds over the entry's own detail line, and the person selects exactly one. Nothing is selected for them. A page that opened with a row already chosen would settle the run's subject without being read, so the Continue stays unavailable until a row is picked. This page draws how the host renders any such step, never one agent's own.

What the step draws beside the list. Under the rows sits the primary Continue, right-aligned over a hairline floor: the same control floor every gate page draws (§II) — and nothing else, because the host draws one control on a gate page, and any further control is the agent's own to declare and to draw. The list is the whole page; one page per gate (§I). One further reading the list carries beyond the pick itself. Where the declared list is empty, the host draws the empty-state message the agent declared, as the agent wrote it — the host names no system and writes no message of its own — and the run waits at this step until there is something to pick, rather than ending on it.

Example — a list step that takes one pick, as the host draws it for any agent that declares one (as it opens · the pick made · the declared list empty)
Skills
The list step
3The step after
4Review
The question the agent declared for this step Awaiting your pick
First entry Detail line · from the agent's declaration
Second entry Detail line · from the agent's declaration
Third entry Detail line · from the agent's declaration
And once a row is chosen — the same page, the pick made, Continue available
First entry Detail line · from the agent's declaration
Second entry Detail line · from the agent's declaration
Third entry Detail line · from the agent's declaration
The same step when the agent's declared list is empty — the agent's own message, and the run waits
Skills
The list step
3The step after
4Review
The question the agent declared for this step Awaiting your pick

There is nothing to choose from yet. Add something for this run to work from, then open this step again.

Every reading says what it is — never a silent pick

The three readings above are the same step, and the differences between them are the whole point: the page opens with no row chosen and its Continue unavailable, and only a reader's pick makes it available; and where the declared list is empty, the page draws the message the agent declared and the run waits at this step. No reading ever chooses a row on the reader's behalf, and none leaves the page blank.

A list step may take several picks, and the floor is one. One pick is this step's shape, not every list step's: where the agent's declared step says so, the same list takes several picks instead of one. Each row then carries the design system's multi-select checkbox (Components · Checkbox / Radio / Switch) in place of the single-select mark, and nothing else about the list changes. Nothing is ticked for the reader, for the reason nothing is chosen for them above, and at least one row is required: the Continue stays unavailable until a row is ticked, and stays available from that first tick however many more are ticked — the floor is one and there is no ceiling. The run receives every ticked row, not the last one ticked. What the list holds, what each row is titled by and what the step asks are the agent's declaration too: this page draws how the host renders any such step, never one agent's own. And where such a declared list is empty, the host draws the empty-state message the agent declared, as the agent wrote it — the host names no system and writes no message of its own — and the run waits at this step until there is something to pick, rather than ending on it.

Example — a list step that takes several picks, as the host draws it for any agent that declares one (as it opens · two rows ticked)
Skills
The list step
3The step after
4Review
The question the agent declared for this step Awaiting your picks
First entry Detail line · from the agent's declaration
Second entry Detail line · from the agent's declaration
Third entry Detail line · from the agent's declaration
And once two rows are ticked — the same list, the picks made, Continue available
First entry Detail line · from the agent's declaration
Second entry Detail line · from the agent's declaration
Third entry Detail line · from the agent's declaration
Example — the same step when the agent's list is empty: the agent's declared message, and the run waits (it does not end)
Skills
The list step
3The step after
4Review
The question the agent declared for this step Awaiting your picks

There is nothing to pick from yet. Add an entry where this run reads from, then open this step again.

I.2 · The run's last step — what the run made

Run rail · the last step · the run's artifacts · Agents Lifecycle (C) §6 step 6 · §4.1 item 0.17

A finished run says what it made. The rail's last entry is the run's own record, and its page lists the run's work: one row per artifact the run wrote, and — where the run consumed an artifact to make them — that artifact too, marked used, because a reader needs to see what the run started from as well as what it produced. Every row carries the artifact's title, the type that owns it, the revision the run filed or read, and the control that opens it on its own page. Every row is a pointer, never a copy — the work lives in the artifact, and this page is where a reader finds out that it exists at all.

Only what reached an artifact, and everything that did. The list is not a summary the run wrote about itself: a row appears because the work reached an artifact, so nothing an agent made is left to be looked for elsewhere. Rows are not ranked or graded — a file that could only be typed as bytes is listed like any other row and drawn by its own display (§V.2), never marked as a failure. A run that wrote nothing and used nothing draws the empty reading and says exactly that, rather than an empty panel.

Example — the run's last step (a row per artifact the run wrote, and the idea it used · each opens on its own page)
Choose the idea
Drafted the post and its featured image
Review · the post · continued
Review · featured image · continued
Done
What this run made Finished

Four artifacts written — the post and its featured image, the LinkedIn post, and one file nothing could name — and the idea they came from. Each opens on its own page; the run keeps the revision it filed or read.

Why migrations are the hardest partBlog post @cinatra-ai/blog:post · revision rev_7f10… · text/markdown
Featured image — the upgrade roadBlog image @cinatra-ai/blog:image · revision rev_a934… · image/png · featured
Announcing the Q3 upgrade roadLinkedIn post @cinatra-ai/linkedin:post-draft · revision rev_31be… · text/markdown
upgrade-road-notes.binBinary @cinatra-ai/binary:file · revision rev_0c58… · application/octet-stream
Why migrations are the hardest part of self-hostingBlog ideaUsed @cinatra-ai/blog:idea · revision rev_2c71… · read by this run · now drafted
The same step for a run that kept nothing
Read the cohort
Done
What this run made Finished

This run wrote no artifact and used none — it read the cohort and reported back, and no step of it made work that outlives the run.

The list is the run's evidence, not its summary

Every row on this page stands for an artifact that exists, at the revision named beside it. That is what makes the page readable as proof: a reader who sees five rows can open five pages, and a reader who sees the empty reading knows the run kept nothing — not that the page failed to load it.

I.3 · The review step on the run page — one review per artifact, on the rail

Run rail · the review step · one artifact per review · Agents Lifecycle (C) §6 step 4

A review is a step, and it opens where every step opens. A review that pauses the run is an entry on the rail, and selecting it opens the review in place, in the run detail (§I) — the same gate header, target, decision bar and prompt window the gate draws anywhere else (§III–§VII). The run page hosts the same card the conversation hosts: the card an assistant turn carries in a thread (Lifecycle cards §II.1) and the card the rail opens here are one card — same target, same floor, same states. Only the frame around it changes: a thread ends in its composer, and the run detail ends in the prompt window (§VI).

One review per artifact, and the rail says so. A run that wrote a post and its featured image does not raise one gate over both. It raises one gate per artifact, each its own rail entry, in the order the run asks: the post first, then its featured image. The run waits at each — one entry is highlighted at a time — and when a review is decided the rail keeps it as read-only history and moves to the next review beneath it (§I). The two readings below are the same frame twice: the review step selected on the post, and — once that one is continued — the review step selected on the featured image.

What each of the two readings carries. On the post’s review the target is the post drawn by the markdown displayPreview active, Code one press away, both read-only (§V.1) — and what that display renders is the post itself: its title and its body text. The picture is not in it. The featured image is a separate artifact, related to the post but not part of it, and it is drawn on the review step beneath this one — never inside the rendered post: the display renders the post’s own representation and composes no other artifact into it. On the featured image’s review the target is the picture drawn by the image display and nothing else — the display carries no Regenerate of its own. Both readings end in the same floor — Comment, Regenerate, Continue, over the one Note field the person’s words go in (§VI). On the featured image that field opens carrying the prompt that made the picture, to be edited rather than re-typed; on the post it opens empty and takes what the reader wants changed. Either way Regenerate settles the gate it was pressed on as superseded and mints a successor gate for that same artifact — a fresh review entry beneath the settled one — and no other artifact’s review is re-opened.

Example — the review step on the run page, selected on the post (the rail on the left, the post’s review in the run detail)
Choose the idea
Drafted the post and its featured image
Review · the post
4Review · featured image
5Done
Review requestedAwaiting your decision

Agent summary  Drafted the post from the stored idea and made its featured image. This review is for the post; the featured image is reviewed on its own step.

Why migrations are the hardest partBlog post

@cinatra-ai/blog:post · revision rev_7f10… · pinned · Team · Private · text/markdown

Why migrations are the hardest part

Teams pick a stack in an afternoon and then live with its upgrade path for years. Start at the upgrade guide, then run cinatra upgrade.

Add a note, or say what to change before Regenerate…
Ask Cinatra about this review, or ask for changes to the work…
Example — the same frame once the post is decided: the rail has moved to the next review, selected on the featured image
Choose the idea
Drafted the post and its featured image
Review · the post · continued
Review · featured image
5Done
Review requestedAwaiting your decision

Agent summary  The post is continued. This review is for the featured image — continue with it, or change the words in the note beneath it and regenerate it.

Featured image — the upgrade roadBlog image

@cinatra-ai/blog:image · revision rev_a934… · pinned · image/png · featured

A long road over layered ground, cool light, no text.
Ask Cinatra about this review, or ask for changes to the work…
The same card, in both frames

The review the rail opens and the review a conversation carries are the same card over the same gate: one artifact, one pinned reference, one floor. A reader who decides it in the run and a reader who decides it in a thread settle the same gate, and the second of them is told it is no longer open (§VII) rather than being let through twice.

II. The Skills step — the first entry on the rail

The first rail entry · a page of its own · one pill per skill · a checkbox in front of each name and vendor · Continue beneath the list · placement only

A run can open on its skills. Where a run begins by recommending the skills it proposes to use, that question is the run's first gate — the first entry on the step rail, where it is named Skills, ahead of the work steps it would authorize. Selecting it opens the Skills page in the run detail, and that page carries a chip-row: one pill per skill, each carrying a checkbox in front of its label — the skill's name then by its vendor in the muted secondary colour — and one Continue beneath the list — the same Continue the HITL screen draws.

The Skills page and the schedule page are two pages. One page per gate (§I): the Skills step is a page of its own, and the schedule step is a page of its own — each opened by selecting its own entry on the rail. The Skills row is never drawn on the schedule page, the scheduling form is never drawn on the Skills page, and neither step is a region of one screen the two share.

Placement here; the card's anatomy on the lifecycle page. This section fixes where the row lives — the Skills entry at the head of the rail, in the same two-column run frame as every other gate, its pills and their Continue filling the run detail while the rail carries the run's steps beside it. What a checked box means, what Continue keeps, and how the row reads before and after the run starts are fixed once in Lifecycle cards §V — the single anatomy every host reuses; this page places it and matches its layout.

Example — the Skills step, the first entry on the rail (placement & layout; the anatomy is fixed in Lifecycle cards §V)
Skills
1Fetch cohort
2Draft email
Enrich contacts by Northstar Draft email by Cinatra Schedule send by Acme Corp

III. The in-run review gate — one gate, any artifact type

In-run · type-agnostic · /agents/[vendor]/[package]/[runId]/review/[reviewTaskId]

The review is a gate inside the run, not a page of its own. When a run pauses on a review gate, the reviewer opens it at /agents/[vendor]/[package]/[runId]/review/[reviewTaskId] — a route within the run. The run's step rail stays on the left with the gated step highlighted and resolved gates above it as history (§I); the gate itself — header, the one review target, decision bar and the run's prompt window — fills the run detail on the right. There is no standalone review document; the reviewer decides in the run, with its steps in view.

One review gate, never a per-type one. The gate is type-agnostic: it keys on no concrete artifact type, binding, or renderer identity, so a new artifact type is reviewable with no new review surface — a type that ships a renderer shows through it, and a type that ships none still reviews through the generic floor (§V). The gate presents one review target — the single artifact it pins — mounts it through its type's renderer (Application Design — Artifacts § Renderer dispatch), and wraps that rendered view in host-owned decision chrome — the renderer displays; the host decides.

The gate's frame. Inside the run detail, the gate opens with a gate header (what is under review, and — when the producing agent supplied one — a one-line summary of what it made and why), then the review target, then the decision bar and the conversational prompt window (§VI). A gate carries one target: one artifact, one pinned reference. Work that made several artifacts raises one gate per artifact, in order — each its own entry on the rail, the run waiting at each — never one gate combining them (§VI, §I.3).

Treatment & layout axes. The surface inherits the shared design-system tokens and the app's single light treatment (cream paper, etched rules, ink text) — it defines no palette of its own. It is responsive: the step rail collapses and the run detail reflows beneath it as width narrows, the one target panel taking the detail's full measure, a wide representation scrolls inside its own container rather than widening the page, and the decision bar and prompt window stay reachable at the foot of the run detail at every width.

You continue on exactly what you saw

Each target is pinned to one exact representation revision, frozen when the gate was raised. The reviewer decides on that revision — a later re-materialization of the artifact can never silently change what was decided, and the gate holds the decision to the exact revision on screen (§VI). The renderer is resolved from the artifact's type, never chosen by the caller or the model.

IV. The review target — immutable header & representation

Immutable {artifact · pinned revision} · display-only props

An immutable target header. Every target opens with a header that names what is under review and fixes it in place: the artifact's display title over a mono meta line carrying its type, the pinned representation revision (shown as a mono revision id with a pinned marker), and the read-only row facts the host authorized — owner level / visibility, MIME, and updated time. The header is inert: it exposes no edit control and no revision picker, because the target is versioned and frozen — the only revision on this surface is the one the gate pinned.

The representation slot. Beneath the header sits the representation slot — the single region into which the artifact's type renderer mounts, fed the host's display-only props (row metadata, the resolved representation, and host-authorized preview / download / open-in-source links; no callbacks — the renderer cannot act, only display). The renderer fills the slot exactly as it would on the detail surface; the review surface adds no per-type controls of its own around it. For a text/markdown target the renderer that mounts here is the markdown display, drawn on a target exactly as §V.1 fixes it.

Example — a review target (immutable header + type-rendered representation)
Review requested Awaiting your decision

Agent summary  Drafted a re-engagement email for the Q3 cohort; ready for your decision before it sends.

Q3 re-engagement email Email

@cinatra-ai/email:draft · revision rev_8f3a… · pinned · Team · Private · text/html · updated 8 min ago

To: prospects@acme.example
Re-connecting on Q3 priorities

Hi there — following up on the pilot we scoped last quarter. Are you open to a short call next week?

V. Renderer provenance & the never-blank floor

Type-resolved · build-time / runtime / floor · never blank

The host resolves the renderer — and the target draws none of that. The renderer for a target is resolved by the host from the artifact's type, and it resolves to one of three: a build-time renderer (one the defining extension ships in the build), a runtime renderer (one loaded from a marketplace-installed extension), or — where the type resolves to no usable renderer — the generic floor. The resolution is host-derived, never a claim the client or the model can forge. It is not put on screen: a display shows the work and nothing about itself — no renderer name, no package identity, no provenance line — because the reader is deciding on the work, not on what drew it. That is what the three readings below show: a build-time renderer and a runtime one are drawn the same way, because nothing on either target says which resolved it — only the caption, written for the reader of this page, names the tier. The one that does speak on a surface is the floor, and only because a reader must be told a render failed.

The floor is never a blank. Whenever a target does not resolve to a type renderer, it renders the floor — a sanitized, telemetry-safe one-line diagnostic (package · slot · reason, never a raw error or manifest value) — so the surface never shows an empty panel where a target should be. The floor comes in two shapes. A type-level floor — the type's renderer is installed but absent from this build (needs a rebuild), or the type resolves to no renderer — still has an authorized representation, so its diagnostic sits above the generic read-only structured-data view of that representation. An artifact-level floor — the artifact is unknown or tombstoned, read-refused for this reviewer, or its pinned revision is no longer a member — has nothing to show, so it renders the diagnostic alone (no representation content, because there is no authorized representation to render).

Example — build-time renderer
Re-connecting on Q3
Example — runtime renderer (marketplace-installed)
Case · Login loop on SSO
Example — the generic floor (never blank)
Floorstructured data

review target unavailable — package “@acme/support”, slot “detail”, reason “requires-rebuild”

{
  "subject": "Login loop on SSO",
  "priority": "high"
}
Floor is a display state, not a gate block

The floor is the per-target display degrade — a target that could not be shown through its type renderer, kept visible rather than blank. It is distinct from the gate-level blocks in §VII, which stop the whole surface before any target renders. A floor keeps a target on screen; whether that target can be terminally decided is a separate question the gate settles at submit — a target whose pinned revision is no longer live cannot be continued and surfaces as a block (§VII), not as a silent pass.

V.1 · The markdown display — Code and Preview, and the saving indicator

Artifact page · Code / Preview · saving indicator · Agents Lifecycle (C) §4.1 item 0.20

Two tabs, and only one of them on screen. Markdown is drawn by a display of its own, and that display carries two tabs — Code and Preview. Only the active tab's view is shown: Code shows the markdown as it is written — syntax-highlighted, never plain text: the application's own highlighter, with the application's own light and dark themes, run over the markdown grammar — the same treatment fenced code gets everywhere else in the product; this page, like every page here, draws the light one — so a heading, an emphasis marker, link syntax and a code span each read in their own colour from this system's palette. Preview renders it. They are never drawn side by side, and there is no third reading. They are drawn as tabs — the design system's tab strip (Components § Tabs): labels at 13px sans, the inactive one slate, the active one indigo under a 2px indigo underline that meets the header's rule. Underline only: never pill tabs, and never a toggle or a segmented control — the two views are two tabs of one display, not two positions of one switch. The tab strip is the display's header: the two tabs, and the saving indicator below, and nothing else — no renderer chip and no provenance line, here or on any other surface this display is drawn (§V). What resolved it is the host's business, not the reader's, and the surface around it adds no controls of its own (§IV).

Editable where the artifact lives, read-only where it is reviewed. On the artifact's own page the Code view takes an edit in place: there is no edit mode to enter and no Save button to find, and a change is stored as it is made. On a review target the same display is drawn read-only — both tabs, neither editable — because a target is pinned to one frozen revision (§IV): an edit on this surface would move what is under review, so the surface does not offer one. A review target opens on Preview, with Code one press away: a reviewer decides on the work as it will read, and the source stays a tab away for whoever wants it. That holds wherever the target is drawn — the run surface here and the review card in a conversation (Lifecycle cards §II) are the same display, opened the same way.

The saving indicator says where the change is. Beside the tabs — alone with them in the header — sits one indicator with two readings while all is well: a spinner from the moment the reader starts editing, and a check once the latest change is stored. It is never absent while an edit is in flight, and it never reads as stored before it is. Two further readings are drawn because they change what the reader should do. A save that fails keeps the spinner, and the indicator reads Not saved rather than reading as stored. And a save onto a revision that moved on is refused rather than written over: the editor reloads onto the newer revision, so the newer work is never silently overwritten.

The reason is a toast, never a note inside the display. Neither failure writes a row into the display: the display carries its indicator and nothing else, and the sentence that explains what happened reports through the app's toast surface (Components § Toast / Sonner) — the popover surface, a status-coloured border and matching text, the type's icon leading, Copy and Close on the right. A save the store could not take is an error toast; a save refused because the artifact moved on is a warning toast, because nothing was lost and the newer revision is already on screen. The toast is transient, blocks nothing, and takes nothing from the display: the display's chrome is the same under either toast — the same tabs, the same header, the indicator in its usual place. What the display shows moves only where the reading above already says it moves: a save that did not go through leaves the reader's own text exactly where they left it, while a refused save has already reloaded the newer revision, which is the whole point of refusing it.

Example — the markdown display (Code, editable, saving · Code, stored · Preview · read-only on a target, opened on Preview · a save that did not go through, its toast · a save the store refused, its toast)
On the artifact page — Code active, a change in flight
Saving…
# Why migrations are the hardest part

Teams pick a stack in an afternoon and then live
with its **upgrade path** for years. Start at the
[upgrade guide](/docs/upgrade), then run `cinatra upgrade`.
The same header once the change is stored
Saved
Preview active — the same display, the other tab, the indicator and nothing else
Saved
Why migrations are the hardest part

Teams pick a stack in an afternoon and then live with its upgrade path for years. Start at the upgrade guide, then run cinatra upgrade.

On a review target — the same display, read-only, opened on Preview, no indicator to draw
Why migrations are the hardest part Blog post

@cinatra-ai/blog:post · revision rev_7f10… · pinned · Team · Private · text/markdown · updated 4 min ago

Why migrations are the hardest part

Teams pick a stack in an afternoon and then live with its upgrade path for years. Start at the upgrade guide, then run cinatra upgrade.

A save that did not go through — the toast carries the reason, the display keeps its indicator
This change has not been saved — the store could not be reached.
Not saved
# Why migrations are the hardest part

Teams pick a stack in an afternoon and then live
with its **upgrade path** for years. Start at the
[upgrade guide](/docs/upgrade), then run `cinatra upgrade`.
A save the store refused — the toast carries the reason, and the newer revision is loaded
This artifact moved to a newer revision while you were editing, so the save was refused rather than written over it. The newer revision is loaded here.
Not saved
# Why migrations are the hardest part

Teams choose a stack in an afternoon and then live
with its **upgrade path** for years. Start at the
[upgrade guide](/docs/upgrade), then run `cinatra upgrade`.
Editing is the display's, the pinned revision is the gate's

The tabs, the in-place edit and the indicator all belong to the display. What a review pins belongs to the gate: a target holds the revision it froze (§IV), and an edit made on the artifact's page after that never moves it. The reviewer keeps deciding on the revision on screen — a later revision arrives as a new review, never as a change under the open one.

V.2 · The download card — a display for bytes, never the floor

Binary base · name / form / size / download · not the floor · Agents Lifecycle (C) §4.1 item 0.19

Bytes nothing can name still have a display. Where no reading of a file can say what kind of work it is, it is not left to the floor: it belongs to a base of its own, and that base's display is the download card — the file's name, its form, its size, and the download — and no reading of the bytes, because there is none to make. The card is resolved exactly as every other display is (§V) — a build-time renderer its base extension ships, resolved from the artifact's type like any other — and, like every other display, it draws none of that on the card. It has no tabs and nothing else to put in a header, so it carries no header strip at all: the file, and the download.

A display and a floor are never drawn for each other. The floor above means no renderer resolved, and it says so in a sanitized diagnostic over whatever representation is left. The download card means this is what the artifact is and reports no failure, because none happened: bytes of an unnamed form are a kind of work, not a broken render. So a target drawing the download card is a review of a file — the card offers the file, and the ordinary decision floor sits beneath it (§VI). Drawing the floor's diagnostic here would tell the reviewer that something went wrong with a target that is intact; drawing the download card in the floor's place would hide a renderer that genuinely failed to resolve.

Example — the download card beside the floor (the same width, and only one of them reports a failure)
The download card — a display
upgrade-road-notes.bin application/octet-stream · 2.4 MB
The floor — a render that did not resolve
Floorstructured data

review target unavailable — package “@acme/support”, slot “detail”, reason “requires-rebuild”

{
  "subject": "Login loop on SSO",
  "priority": "high"
}
Every kind of work draws itself — bytes included

The download card is what closes the last hole in §V: with it, no artifact has to fall to the floor for want of a display. A target on the floor now means one thing only — a renderer that was expected and did not resolve — which is what makes the floor worth reading at all.

VI. The decision — comment, regenerate, continue & the prompt window

Comment / regenerate / continue floor · one note field · conversational request-changes · atomic · re-validated at submit

The decision floor: comment, regenerate, continue. A single decision bar sits at the foot of the gate, governing the one target under it. It offers exactly three affordances: Continue (primary), Regenerate, and Comment. Continue and Regenerate are terminal — they resolve the gate and hand the run its outcome: Continue releases the run to go on with the revision on screen; Regenerate sends the work back to be made again from the words in the note field, settles this gate as superseded, and raises its successor over the new revision (§VIII). Comment is a non-terminal annotation: it records the reviewer's note against the review and leaves the gate pending — nothing resumes, and the run stays paused. There is nothing to press for “no”: a reader who does not want the run to go on leaves it as it is, and nothing is decided or destroyed (§VIII).

Requesting changes is a conversation, not a fourth button. Beneath the decision bar the run detail carries a conversational prompt window — a chat-style input onto the run, offered as “Ask Cinatra about this review, or ask for changes to the work…”. Typing a change request into it is how a reviewer requests changes; there is no dedicated “request changes” button. On submit, the gate resolves changes-requested and a repair goes in flight — the run takes the reviewer's note and works the target again — and the corrected version returns as a fresh review in the same run: a new review gate entry on the rail, beneath the one just resolved. The reviewer's request and the returned revision stay in the run, in order — the reviewer keeps the whole exchange in one place rather than crossing to a separate screen. The review draws no card that names who requested changes: there is no “Changes requested by …” card on this surface.

One note field, and it reads for both roads. The decision bar carries one free-text Note field — the same field whatever the decision, because the floor is type-agnostic (§III) and a second input that appeared only for one kind of artifact would make it type-aware. It is optional on Continue, where it travels with the decision into the audit trail and into the note the run resumes with; on Regenerate it is the words the work is made from again; and it is itself the substance of a Comment. Where the producer holds the words that made the reviewed revision — a picture's prompt — the field opens carrying them, to be edited rather than re-typed; where it does not, the field opens empty and takes what the reader wants changed. Words the reader never touched are not filed as the reader's: a Continue or a Comment over an untouched pre-filled field records no note at all, because the producer's words were never the reader's to sign. (A change request is carried by the prompt window, not this field.)

One artifact per review, one reference per gate. A gate pins one artifact at one reference, and a terminal decision settles that gate. There is no combined gate and no per-target verdict to reconcile: a run that made several artifacts raises one review per artifact and waits at each (§I.3), so what a reviewer continues on is always the single thing that was on screen. A pending gate's pin is immutable — a submission naming a different reference is refused, never quietly re-pinned — and a decided gate retains and displays the target it froze. A Comment, being non-terminal, records a note against the review without resolving it.

The gate can change under you. If the gate is no longer the one you opened — it was already decided, or the run moved on — your decision does not slip through: instead of committing, the surface shows a blocked state (§VII) naming the reason, with a refresh back to the live gate. And submitting the same decision twice is safe — it resolves the gate once, never twice. (How the gate is re-checked and settled is engine behaviour; this page fixes only these visible outcomes.)

Example — the decision bar (the note field + comment / regenerate / continue)
Add a note, or say what to change before Regenerate…
Example — the conversational prompt window (typing a change request is how changes are requested)
Ask Cinatra about this review, or ask for changes to the work…

Submitting a change request here resolves the gate as changes-requested and sends a repair in flight; the corrected version returns as a fresh review gate on the rail, in the same run. There is no separate request changes button — the window is the request. It is not the same act as Regenerate. Regenerate runs the same producing step again from the words in the note field, files a new revision of the same artifact, and settles this gate superseded beneath a successor over that same artifact; nothing is interpreted and no new work is planned. A request typed here is read by the run, which works out for itself what to change and how before it works the target again, and settles this gate changes-requested.

Regenerate is not a quiet Continue

The Regenerate affordance is visually and structurally distinct from Continue — its own treatment, its own path — and a regeneration can never be mistaken for or routed as a continuation. Regenerating appends a revision and settles the gate it was pressed on as superseded, which keeps that revision on screen and destroys nothing (§VIII). A change request is distinct again: it is neither, but a resolve-to-repair, typed in the reader's own words, that returns the work for a fresh review.

VII. Permission, loading & blocked states

Run-access gated · disabled · loading · blocked / error

The decision is permission-gated. Deciding a gate requires the reviewer to hold the run access the decision needs — a terminal Continue / Regenerate requires approve access on the run, a Comment or a change request in the prompt window requires respond access. A reviewer who may see the gate but not act on it gets the affordances disabled, with a one-line reason, rather than a live control that fails on click. A viewer with no access to the run at all never reaches the surface: it opens to the standard not-authorized panel, never to the target.

Loading and blocked. While the host prepares the target the surface shows a loading skeleton in the target slot — never a flash of empty chrome. A gate that cannot be prepared or decided shows a single blocked state naming the reason from the closed set: the gate is no longer pending (already decided, or the run moved on), the target doesn't match the gate (a stale or tampered view — a hard block, never a silent degrade), or a revision is no longer live. A blocked gate offers a refresh back to the live gate; it never lets a stale decision through.

Example — mixed access (comment allowed, decide gated)

You can respond to this review, so Comment and the prompt window are live — but a terminal Continue / Regenerate needs approve access on the run, so those stay disabled with the reason shown. (A viewer with no run access never reaches the surface — they get the not-authorized panel.)

Example — loading
Example — blocked (no longer pending)

This review is no longer open

The gate was already decided or the run moved on. Refresh

VIII. Leaving it as it is — nothing decided, nothing destroyed

No turn-back decision · the gate stays pending · a revision is appended, never replaced

There is no control for “no”. A reader who does not want the run to go on leaves it as it is: they press nothing, and the gate stays exactly where it was — pending, on the revision it pinned, with the run paused at it. Nothing is turned back, nothing is ended, and no verdict is recorded; a run is stopped or abandoned with the run’s own controls (§I), never with a decision on the review floor. A reader who wants to say why without settling anything has Comment, which annotates and leaves the gate pending (§VI).

Regenerating preserves what it supersedes. Regenerate appends a revision — it never overwrites or deletes the one under review. The gate it was pressed on is settled as superseded and keeps and displays the target it froze; its successor opens beneath it on the new revision, and both stay readable in order. The decision, the one reviewed revision it settled, and how that revision was rendered stay on the run’s audit trail — and on the run’s rail, as the gate’s read-only history (§I).

Never a destructive delete

No affordance on this surface hard-deletes an artifact. Continue settles a gate, Regenerate files a new revision beside the one it superseded, and Comment settles nothing at all. Every revision the run filed remains, for the audit trail and any downstream re-draft.

IX. The conversation above the prompt window

the shipped panel · the reader's turns right, the assistant's left · kept with the run

The prompt window is unchanged; what is added is the exchange above it. The window itself — its panel, its placeholder, its send control — is exactly the window §VI already fixes, and nothing about it moves. What this section documents is the panel that opens above the field once something has been asked on the screen the reader is standing on, drawn oldest at the top and newest at the bottom.

The exchange is drawn as turns, not as a transcript. Each message is a bubble: the reader's own turns are right-aligned on the indigo ground in white; the assistant's are left-aligned on the muted surface in ink. A bubble takes at most four-fifths of the panel's width, keeps the line breaks it was written with, and carries no author label, no avatar and no timestamp — the side it sits on is who said it.

While the assistant is working, the wait is a turn of its own. Beneath the last bubble, on the assistant's side, a small dot and the word Thinking… in muted; it is not a bubble. The field goes quiet with it: it takes no new text, and its send control becomes a stop glyph — drawn quiet, because this window offers nothing to stop. Nothing else on the window changes. The panel scrolls at its own cap and holds itself at the bottom, so the newest turn is the one in view.

It opens when there is something in it. There is no panel above an empty exchange — the window is the field alone until the first message. After that the panel opens on its own; clicking into the field opens it again, and clicking anywhere outside the window closes it without losing what is in it.

The exchange is kept with the run. The window's exchange is the person's conversation about the run it sits under, and it is kept per run: it is stored with the run, it is there after a reload, and it can be read later beside the run. The same assistant a person meets in the chat answers here, with the run in view. What survives a reload is therefore both — the turns above the field and the reader's unsent draft in it. When the run reaches a gate of a different kind the panel closes, because the thing in front of the reader has changed; what was said is not discarded with it — the exchange stays with the run and opens again on the next click into the field.

The window is drawn only for a person who may answer the run. The right to type here is the run's own access — the agent's install scope and the run's access tiers, the same rule that decides who may start the run, continue it, answer its screen or decide its review, and never more. A person with respond access on the run sees the box and is answered, a run owner who is not a platform administrator among them; a person without respond access never sees the box, rather than a field that would be refused.

Example — the window with the exchange above it
Please tighten the opening paragraph and add a short closing summary before this continues.
Changes requested. The reviewed work has been turned back for repair — a repair is now in flight.
Ask Cinatra about this review, or ask for changes to the work…
Example — the window while the answer is out
Please tighten the opening paragraph and add a short closing summary before this continues.
Thinking…
Ask Cinatra about this review, or ask for changes to the work…
Example — the window before anything has been asked
Ask Cinatra about this review, or ask for changes to the work…
Kept with the run, and never a second chat thread

What is said here is kept with the run: stored as the run's own exchange, there after a reload, and readable beside the run afterwards. It is not the chat thread and never becomes one — where a chat thread already carries the run, this window is a second view of it and hands off to that thread rather than opening a second conversation about the same step. The same holds inside a third-party application: the conversation there is one the product keeps, so it carries its own composer and the window hands off to that composer rather than being drawn inside the conversation. Anything a request decides is still recorded by the act it drove — a change request lands on the review, and its reply stays on screen.

X. One window, five readings

the sentence in the field · five surfaces · never five windows

These are five readings of one window, never five windows. Outside the chat the window appears on five surfaces, and on every one of them it is the same window: the same panel above the field (§IX), the same field, the same send control, in the same place under the work it belongs to. One thing is read per surface — the sentence in the empty field, which names what the window does where it stands. Nothing else about the window changes from one reading to the next.

On a surface with a form, the sentence names filling — and the button stays the person's. The window fills the fields the person can see with what they asked for, and nothing is submitted until they press the screen's own button, unless the same message plainly asks for it to be submitted. A question about the step is answered as a question and touches no field.

On the review page, the sentence names the review. There is no form there: an explicit request for changes is placed by the card's own comment machinery, word for word, and the gate resolves changes-requested with a repair in flight, exactly as §VI fixes it; a question is answered and files nothing. Continue, Regenerate and Comment keep working exactly as §VI fixes them.

Example — the five readings of the one window
The run page — a step waiting for its fields
Ask Cinatra to fill the fields above, or ask about this step…

Fills the fields the step is waiting for with what was asked for. Nothing is submitted until the person presses the step's own button — unless the same message asks for it in so many words.

The step-by-step screen — one step of a multi-step run
Ask Cinatra to fill this step's fields, or ask about the run…

The same filling, one step of a sequence: the values land in the fields in view and the person presses the step's button. A question about the run is answered without touching the form.

The schedule screen — the scheduler form, in both of its states
Ask Cinatra to set the schedule above, or ask about it…

Fills the scheduler form's own rows — when the run starts, its time, its timezone — whether the schedule is being set for the first time or changed once it stands. The person presses the form's own button, unless the same message plainly asks for it to be submitted.

The armed-trigger tab — the run's schedule as it stands
Ask Cinatra to change this schedule, or ask about it…

Changes the schedule that stands — until a one-off fires, and for a recurring schedule's future runs — through the tab's own controls. The schedule on screen is what is true.

The review page — under the decision bar
Ask Cinatra about this review, or ask for changes to the work…

Places an explicit request for changes by the card's own comment machinery, word for word; the gate resolves changes-requested and a repair goes in flight (§VI). A question is answered and files nothing.

One sentence is the whole difference

A reading is not a variant of the window: the panel, the field, the send control, the placement and the access rule are one across all five (§IX), and the exchange is one per run — a person who reaches the same run from two of these surfaces is in the same conversation, never in a second one about the same step.

XI. The displays the fleet adds — one per type, on the artifact’s own page

Own display per type · no decision affordance · Agents Lifecycle (D) §3.4 waves 1–4

One display per type, and the type’s own extension owns it. The surfaces below are the displays this fleet adds, drawn on the artifact’s own page. Each is registered for its extension’s own type and draws every content form that type accepts, so it never falls through to a form provider and never reaches the floor (§V). The same display is drawn, unchanged, wherever the artifact is read — the artifact page here, the review step on the run page (§I.3) and the review card in a conversation (Lifecycle cards §XIII). A display’s chrome travels with it: what it carries here it carries there.

What a display never carries. A display draws the work and nothing about itself — no renderer chip and no provenance line (§V) — the mono line names the artifact’s own type and revision, never the package that drew it. It carries no decision affordance: Comment, Regenerate and Continue are the review floor’s (§VI), drawn by the surface around the display and never inside it, so a display drawn where there is no review shows no control at all. It carries no note row of its own: a sentence about a failure — a read that did not go through, a save the store refused — reports through the app’s toast surface (Components § Toast / Sonner), never as a line written into the panel. A reading the display has is not a note: where content is absent by right — a capture the host could not make, a series the reader may not read — the display draws the named gap in the missing thing’s place, never a blank plate and never a row appended beneath the work. Where a display divides one artifact into readings, they are the design system’s tabs (Components § Tabs) — labels at 13px sans, the active one indigo under a 2px indigo underline — never a toggle and never a segmented control.

Pinned where it is reviewed, and settled below the card. On a review target every display draws the one revision the gate pinned (§IV) and is read-only: the meta line names the revision with its pinned marker, and nothing on the surface can move it. Where a display shows live numbers over a pinned configuration — the dashboard and the portlet — it says both things at once: the configuration is frozen at the revision, the numbers are current, and the reading carries the time they were read. A capture — a page or a screen — is drawn to one aspect, the viewport it was taken at, so the same picture area is the same shape at every measure it is read on; only an embedded viewer takes its height from the surface, because that is the height the host gives it. Once a decision is taken, the settled marker is drawn below the whole card — a block of its own beneath the display, never a row inside it — and Continued is the only settled reading a display has: there is no second, later status for the same decision.

How to read the drawings below. Inside the frame is what the product draws — the real tab labels, the real field labels, the real content, the real controls, and nothing else. Every explanation of a drawing — which reading it is, which state it stands in, at which measure it is drawn — sits outside the frame in this page’s annotation voice: the mono line above a frame, set against the annotation rule, and the callouts beneath. No line inside a drawn frame is a note about the drawing.

XI.1 · The email body — a text display, and no picture in it

Artifact page · own type · text projection · Agents Lifecycle (D) §3.4 wave 1

The body is the artifact, and it is read as mail. An email draft lands as one body artifact of the email extension’s own body type, and that extension’s display draws it as the mail detail pane, in one view: the sender block — the initials avatar, the name that will send it, and the address on the line right beneath that name — the date at the end of that same line, the subject under them, and the body under a rule. There is no tab strip and no second reading to switch to: a body is one thing to read, and the pane draws it whole.

The subject and the body are edited in place, and nothing else is offered. Where the artifact lives — its own page — the subject and the body take an edit in the pane itself: there is no edit mode to enter and no Save button to find, and a change is stored as it is made, under the same saving indicator the markdown display carries (§V.1). Where the same artifact is a review target the pane is drawn read only, because a target is pinned to one frozen revision (§IV) and an edit there would move what is under review. Beyond those two fields the pane offers nothing: it carries no reply field and no compose affordance of any kind — not inert, not disabled, absent — because answering a message is not part of this display on any surface. A text display draws no picture: the avatar is the sender’s initials set in a plain disc, never an image. The address the draft will go to is not drawn — the recipient is a record of its own, which projects nothing; the address in the pane is the sending account’s own. The only controls a reader ever meets around the pane are the review floor’s — Comment, Regenerate and Continue (§VI) — and those belong to the surface, never to the pane.

Example — the email body display: one view on the artifact’s own page, the subject and the body edited in place, then the same pane read-only on a review target
On the artifact’s own page — the subject and the body edited in place
Re-connecting on Q3 prioritiesEmail bodySaved

@cinatra-ai/email-artifacts:body · revision rev_4c21… · Team · Private · text/markdown

Anna Keller
anna.keller@acme.example
14 Aug 2026, 09:12
Re-connecting on Q3 priorities

Hi there — following up on the pilot we scoped last quarter. Two of the three teams you named have since moved onto the new plan.

Are you open to a short call next week? I can bring the migration notes.

On a review target — the same pane, pinned and read only
Re-connecting on Q3 prioritiesEmail body

@cinatra-ai/email-artifacts:body · revision rev_4c21… · pinned · Team · Private · text/markdown

Anna Keller
anna.keller@acme.example
14 Aug 2026, 09:12
Re-connecting on Q3 priorities

Hi there — following up on the pilot we scoped last quarter. Two of the three teams you named have since moved onto the new plan.

Are you open to a short call next week? I can bring the migration notes.

The sent and received records are read, never reviewed

A sent email and a received reply are records, not drafts: their display reads the object’s projection live and carries the same chrome as the body display above, read only throughout, because a record is not drafted and nothing in it takes an edit. They carry addresses, so they are read only through the authorized live read; a review over one, if it is ever asked for, pins a minted snapshot and draws it exactly as any other target (§IV).

XI.2 · The seven mixed kinds — one display each, over text and over pdf, on the fleet’s own renderers

Artifact page · own type · two content forms · markdown · embedded pdf · Agents Lifecycle (D) §3.4 wave 2

Seven kinds, two forms, one shell. Seven extensions claim a kind of working document — brand voice, competitive analysis, contract, ICP, marketing strategy, product portfolio and sales playbook. Each is written by an agent as text, or handed over by a person as a pdf. Owning the type takes the pdf case away from the pdf extension, so each display must draw both forms — and all seven draw them on the renderers the fleet already has: the markdown display over text (§V.1), and the embedded PDF viewer the pdf extension mounts over pdf. Seven extensions grow no seven viewers between them, because none of them writes a viewer at all.

The text form is the markdown display; the pdf form is the embedded viewer. Over text a kind draws through the same Code and Preview tabs as any other markdown work (§V.1), read-only on a target. Over pdf the shell is the embedded PDF viewer the pdf extension already mounts, and both of its readings are that extension’s own, never this kind’s: the embedded viewer, where the browser’s bundled viewer fills the panel and does its own scrolling, so the display adds no page counter, no Previous and no Next; and that extension’s download floor, where there is no preview to show, so the panel is never blank. No viewer is written for this kind: in both readings the reader is looking at the pdf extension’s own display, and no renderer of ours paints a document’s pages. Over pdf there are no tabs — a pdf has one reading. Which form it is is never a choice on screen: the display branches on the artifact’s own content form, and the reader sees one panel, not two.

Example — a mixed kind on the artifact’s own page: the text form, then the pdf form in the embedded viewer and its download floor
Brand voiceCompetitive analysisContractICPMarketing strategyProduct portfolioSales playbook

The seven kinds that share one pdf road. Each is its own extension and its own type; the pdf reading is the embedded viewer the pdf extension already mounts, taken whole and never forked.

Over text — the markdown display, Preview active
Acme brand voice — 2026Brand voice

@cinatra-ai/brand-voice-artifact:artifact · revision rev_11b8… · pinned · Team · Private · text/markdown

How we sound

Plain, unhurried, and specific. We name the thing we changed and the person it helps, in that order.

We do not write revolutionary, seamless or unlock.

Over pdf — the embedded viewer, filling the panel
Acme brand voice — 2026Brand voice

@cinatra-ai/brand-voice-artifact:artifact · revision rev_11b8… · pinned · Team · Private · application/pdf

Over pdf — no preview to show, and the floor that is never blank
Acme brand voice — 2026Brand voice

@cinatra-ai/brand-voice-artifact:artifact · revision rev_11b8… · pinned · Team · Private · application/pdf

This PDF cannot be previewed here.

Download PDF
An own display must draw every form its type accepts — with the fleet’s own renderers

A display registered for a type wins outright for that type and never falls through to a form provider (§V). So a kind that accepts text and pdf must draw both: a kind that drew only its text form would leave its pdf rows blank, not delegated. It draws them with the renderers the fleet already has — the markdown display for text (§V.1) and the embedded pdf viewer for pdf — never a viewer written for one kind. That is why seven extensions grow no seven viewers between them.

XI.3 · The screenshot — the picture, and what was captured

Artifact page · own type · byte road · Agents Lifecycle (D) §3.4 wave 3

A screenshot draws its picture. The display shows the captured picture and, beneath it, the facts that make a screenshot readable a week later: where it was taken, at what viewport, and when. The picture is fetched through the island-scoped byte road, so the display draws the same inside a third-party application as it does here; where the bytes are refused it draws the named gap, never a blank plate.

Example — the screenshot display on the artifact’s own page
Checkout — step 2Screenshot

@cinatra-ai/screenshot-artifact:artifact · revision rev_66d0… · pinned · Team · Private · image/png

shop.acme.example/checkout · 1440×900 · captured 12 minutes ago

XI.4 · The slide deck — the exported deck, in the same embedded viewer

Artifact page · own type · byte road · Agents Lifecycle (D) §3.4 wave 3

A deck is read in the viewer the fleet already has. The deck type accepts one content form — the exported pdf — and its display draws it through the same embedded PDF viewer as every other pdf reading (§XI.2): the browser’s own bundled viewer fills the panel, pages and scrolls itself, and the display adds no controls of its own. Moving through the deck is the viewer’s, and it changes nothing about the artifact — a deck under review is pinned like any other target, and reading it is reading, not editing. The same two readings hold as anywhere else: the embedded viewer, and the download floor beneath it where there is no preview to show.

Example — the slide deck display on the artifact’s own page: the embedded viewer and its download floor
The exported deck — the embedded viewer, filling the panel
Q3 business reviewSlide deck

@cinatra-ai/slide-deck-artifact:artifact · revision rev_9ac3… · pinned · Team · Private · application/pdf

No preview to show — the floor that is never blank
Q3 business reviewSlide deck

@cinatra-ai/slide-deck-artifact:artifact · revision rev_9ac3… · pinned · Team · Private · application/pdf

This PDF cannot be previewed here.

Download PDF
A deck handed over in its office format is an office document, not a deck

The deck type accepts the exported pdf and nothing else, so a presentation handed over in its office format is never typed as a deck: it is an office document, and the office-document display draws it. The drawing above mounts the embedded pdf viewer the pdf extension ships for that one supported form, and exporting the deck to pdf is the road onto it. The office-document display is a named download shell here — the format, the size, and one download — and its presentation form gains an embedded OpenXML viewer with the document extension’s own retrofit in this plan, which is the wave that draws it.

XI.5 · The dashboard — the pinned configuration, drawn as a view, with current numbers

Artifact page · own type · read-only composition · Agents Lifecycle (D) §5 call 6

A dashboard is drawn, not pointed at. The dashboard extension’s display renders the dashboard through the shared read-only composition: the same layout and the same portlets a person sees on the dashboard’s own home, as a viewno toolbar, no filters, no drag, no save, and no decision affordance.

The configuration is frozen; the numbers are current; the live dashboard waits for the decision. Each revision of the dashboard artifact carries the configuration it was cut at, and the display renders that configuration — not whatever the dashboard looks like now. The series are read live, under a short-lived data capability sealed to the reader, the run, the gate, the artifact, the revision and that pinned configuration, and the panel says both facts in one line, with the time the numbers were read. Open live dashboard is drawn only once the review is continued: while a decision is still open the proposal is not the live dashboard, so the display offers no way to open one, and the navigation appears with the settled marker. Inside a third-party application the same capability feeds the same view; a capability the host refuses leaves the no-series reading — chrome, titles and layout, no numbers — and never a blank.

Example — the dashboard display on the artifact’s own page: while the review is open, once it is continued, and the refused-capability reading
While the review is open — the pinned configuration, numbers read live, and no live dashboard
Pipeline health — Q3Dashboards

@cinatra-ai/dashboard-artifact:dashboard · revision rev_2e77… · pinned · Team: Growth · Private

Qualified pipeline
€1.24m
Win rate
31%
Cycle time
38 days

Configuration frozen at this revision · numbers as of 09:14 today.

Continued — the same view, the marker below the whole display, and the live dashboard
Pipeline health — Q3Dashboards

@cinatra-ai/dashboard-artifact:dashboard · revision rev_2e77… · pinned · Team: Growth · Private

Qualified pipeline
€1.24m
Win rate
31%
Cycle time
38 days

Configuration frozen at this revision · numbers as of 09:14 today. Open live dashboard

ContinuedDecided on the revision above. The dashboard is live from here.
The data capability refused — chrome, titles and layout, and no numbers
Pipeline health — Q3Dashboards

@cinatra-ai/dashboard-artifact:dashboard · revision rev_2e77… · pinned · Team: Growth · Private

Qualified pipeline
Win rate
Cycle time

No series — this reader has no live data for this dashboard here. The layout is the pinned one; the numbers are not shown. Configuration frozen at this revision · no numbers were read.

XI.6 · The portlet — one entry of a dashboard, addressable on its own

Artifact page · own type · cut on demand · Agents Lifecycle (D) §5 call 6

A portlet is one entry, with an identity. A portlet artifact is exactly one portlet as it appears in its dashboard: its identity is the dashboard and the entry’s stable instance id, and each revision holds that single configuration entry, the sanitized dashboard context its bindings need, and the dashboard revision it was cut from. A portlet artifact is created by an explicit cut; an ordinary dashboard save mints none.

Drawn exactly as it sits in the dashboard. The display draws the one portlet through the same read-only composition — the same title, the same chrome, the same numbers — and says which dashboard and which dashboard revision it was cut from, so a reader can always get back to where it came from. The configuration is frozen and the series are live, on the same rule as the dashboard above — and on the same rule, the way back to the live dashboard is drawn only once the review is continued.

Example — the portlet display on the artifact’s own page: while the review is open, and once it is continued
While the review is open — the cut entry, and no way back to a live dashboard
Qualified pipeline — Q3Dashboards

@cinatra-ai/dashboard-artifact:portlet · revision rev_5b02… · pinned · Team: Growth · Private

Qualified pipeline
€1.24m

Cut from Pipeline health — Q3 at revision rev_2e77… · entry pl-0417
Configuration frozen at this revision · numbers as of 09:14 today.

Continued — the same entry, the marker below the whole display, and the live dashboard
Qualified pipeline — Q3Dashboards

@cinatra-ai/dashboard-artifact:portlet · revision rev_5b02… · pinned · Team: Growth · Private

Qualified pipeline
€1.24m

Cut from Pipeline health — Q3 at revision rev_2e77… · entry pl-0417
Configuration frozen at this revision · numbers as of 09:14 today. Open live dashboard

ContinuedDecided on the revision above. The dashboard it was cut from is live from here.

XI.7 · The Drupal pointer — the page it points at, drawn by the same renderer

Artifact page · own type · never a review target · Agents Lifecycle (D) §3.4 wave 4

A page is a page, whichever system holds it. The connector keeps a pointer type for the live node on a Drupal site, and its display draws that node through the page display (§XI.8) — the same one view, the same page embedded live in a frame, the same diff of the changed excerpts beneath it, the same Open in the CMS under that, and the same settled marker below the whole display. That display is one renderer@cinatra-ai/website-artifacts:page-diff — and both the WordPress and the Drupal extension draw through it: neither writes a page renderer of its own, and the identity line of every page names the renderer that drew it. Where the connector has a change staged against that node the excerpts are that change; where it has none, the diff draws its named gap in their place, on the same rule as any other absent reading. A Drupal page and a WordPress page are one drawing: only the identity line — the connector it names, and the platform beside it — tells them apart.

A pointer is still never a review target. A pointer is not pinnable, so it carries no pinned revision and opens no gate: the identity line reads not pinnable where a target reads its revision, and no decision floor is drawn anywhere the pointer appears (Lifecycle cards §XIII). Where a run has something to review about that page, the target is the page snapshot (§XI.8), never the pointer — and once that review is continued, the pointer draws the same settled marker, because the page it points at now carries the change.

Example — the Drupal pointer on the artifact’s own page: the same one view, the same changed excerpts, and the same settled marker as a WordPress page
While the review is open — the node the pointer names, embedded, and its changed excerpts beneath it
Pricing — 2026 plansCMS page

@cinatra-ai/drupal-artifacts:node-pointer · drawn by @cinatra-ai/website-artifacts:page-diff · not pinnable · Drupal · Team · Private · acme.example/pricing

Changes
Pricing that grows with you Pricing — 2026 plans

Three plans, a price held since 2024 one price change, and the migration note under each.

  • Team — 35 per seat Team — 39 per seat
Continued — the marker below the whole display, as on any other page
Pricing — 2026 plansCMS page

@cinatra-ai/drupal-artifacts:node-pointer · drawn by @cinatra-ai/website-artifacts:page-diff · not pinnable · Drupal · Team · Private · acme.example/pricing

Changes
Pricing that grows with you Pricing — 2026 plans

Three plans, a price held since 2024 one price change, and the migration note under each.

  • Team — 35 per seat Team — 39 per seat
ContinuedDecided on the revision above. The change went to the site, which published it at 09:20.

XI.8 · The CMS page — one view: the page embedded, and the changed excerpts beneath it

Artifact page · page snapshot · one embedded view · the changed excerpts · Agents Lifecycle (D) §5 call 7

One display, one view. When a connector stages a change to a page on a WordPress or a Drupal site, the reviewed thing is the page snapshot — one type for both systems, the system a fact on the revision. Its display draws one view and no tab strip: the page itself, embedded live in a frame, at the width the surface gives it, and beneath it a diff of only the changed excerpts — never the whole page. Each excerpt is drawn in the page’s own formatting, a heading as a heading and a paragraph as a paragraph, with what the change removes and what it adds highlighted in place and the unchanged run between two excerpts left out under an elision. Open in the CMS is drawn under the excerpts, the same way in every reading. The whole display is one renderer@cinatra-ai/website-artifacts:page-diff — which both CMS extensions draw through: the WordPress page here and the Drupal node a pointer names (§XI.7) are the same drawing, and the identity line names that renderer on both.

Two readings, and no more. The display has one reading while the review is open and one once it is settled; the settled one is Continued, drawn as the marker below the whole display, and there is no second status after it — what the site published is read in the same one view, never under a status of its own. A site that does not answer is a condition of the embed, never a reading of its own, so it is not drawn as one: inside whichever reading is open the frame names the gap in the embed’s own place, and the excerpts are still drawn beneath it, because the words of the change are the part that always exists.

Example — the CMS page display: the page embedded with its changed excerpts beneath it, the settled marker below the whole display
While the review is open — the page embedded, and its changed excerpts beneath it
Pricing — 2026 plansCMS page

@cinatra-ai/objects:cms-content-snapshot · drawn by @cinatra-ai/website-artifacts:page-diff · revision rev_c410… · pinned · WordPress · Team · Private · acme.example/pricing

Changes
Pricing that grows with you Pricing — 2026 plans

Three plans, a price held since 2024 one price change, and the migration note under each.

  • Team — 35 per seat Team — 39 per seat
Continued — the same display, and the marker below the whole display
Pricing — 2026 plansCMS page

@cinatra-ai/objects:cms-content-snapshot · drawn by @cinatra-ai/website-artifacts:page-diff · revision rev_c410… · pinned · WordPress · Team · Private · acme.example/pricing

Changes
Pricing that grows with you Pricing — 2026 plans

Three plans, a price held since 2024 one price change, and the migration note under each.

  • Team — 35 per seat Team — 39 per seat
ContinuedDecided on the revision above. The change went to the site, which published it at 09:20.

XI.9 · The chart — declared display-only, and asked for no document display

Chat view only · out of the rendering gate · Agents Lifecycle (D) §5 call 1

Not every extension owns a display. The chart extension ships no artifact display of its own — it draws charts in the conversation, and claims no object type. It does accept one content form, so a stored chart file has an artifact page like any other file, drawn by the form provider that form already has (§V); what this extension declares is that it renders nothing there. And a chart is not an element of a dashboard the way a portlet is: a dashboard is composed of portlets, and where its entries are the analytics kind, one portlet carries a whole embedded analytics configuration rather than one portlet per chart. So there is nothing about a chart to address, cut, pin or review on its own, and no dedicated chart artifact display to draw beside the portlet (§XI.6). The extension is therefore declared display-only: it is out of the rendering gate by construction, and no build check ever asks it for a document display. No chart display is drawn on an artifact page, no review card carries one, and nothing on this page draws one.

Example — the chart’s declaration, and the surface it has (a chat view, no document display)
Chartsdisplay-only

Ships no display, and claims no object type. It binds one chat view and no artifact renderer, so it is display-only: nothing asks this extension for a display on an artifact page or a review card, and its absence from those surfaces is the declaration working, not a gap. It does accept one content form — a chart file — and a stored file of that form is drawn, as any form with no registered display is, by the form provider its content form already has (§V).

A chart is also not an element of a dashboard the way a portlet is: a dashboard is composed of portlets, and an analytics entry carries a whole embedded configuration in one portlet rather than one portlet per chart. There is nothing to cut, pin or review, so there is no dedicated chart artifact and no display for one.

XI.10 · The promoted row — an upload re-typed into the extension that claims it

Library row · matcher assertion · person’s confirmation · Agents Lifecycle (D) §3.4 waves 2–3

Why a row is promoted at all. An uploaded file is typed by its file kind and may be given a meaning by the person or by the matcher (Artifacts §VI). A meaning associated with an extension is not enough for that extension to draw the file: a display is registered for a type, and an associated row still carries the base type. Promotion is the step that closes that gap — the row gains a revision of the claiming extension’s own type over the same content, and from that moment the extension’s own display draws it (§XI.2, §XI.3, §XI.4). One live claimant per type and scope, so a row is promoted into one extension, never shared between two.

Nothing is re-typed silently, and the file kind never moves. Promotion happens only on the matcher’s assertion at its threshold and with the person’s confirmation, or on the person’s own assertion, which outranks the matcher. What changes is the row’s type — what the file means, and therefore who draws it. What does not change is the file kind: a pdf stays a pdf, the bytes are the same bytes, and the same content is shared by the new revision (Artifacts §VI.1). An association on its own promotes nothing: a row that carries a meaning and no claiming type is not promoted behind anyone’s back — it stays as it is until someone asks.

The row says what happened. After promotion the row reads as the claiming extension’s row — its type on the mono line, its extension on the tag — and carries a Promoted reading with the base it came from, so a person who remembers uploading a file still recognises it and can see what it became.

Example — the confirmation that promotes a matched upload (nothing is re-typed without it)
Is this a pricing sheet?

The matcher is confident that 2026 pricing sheet.pdf is a pricing sheet. Confirming lets the Sales extension draw it with its own display.

  • Its type becomes @acme/sales:pricing-sheet, and that extension draws it from now on.
  • The file kind does not move — it stays a application/pdf, and the same file is kept.
matcher 0.94
Example — the same upload before and after promotion
Before — a base row associated with the extension, drawn by the base display
  • 2026 pricing sheet.pdfapplication/pdf

    @cinatra-ai/pdf-artifact:artifact · associated with Sales · drawn by the pdf display

After — the claiming extension’s own type, drawn by its own display
  • 2026 pricing sheetSalesPromoted

    @acme/sales:pricing-sheet · revision rev_7d44… · from application/pdf · drawn by the Sales display

    Open
Meaning moves the type; the file kind is still fixed at upload

The ingest rule (Artifacts §VI.1) fixes the file kind at upload and never lets a picker move it. Promotion does not move it either: it adds a revision of the claiming extension’s type over the same content, so the artifact now means a pricing sheet while it is still the same pdf. That is the whole change, and it is the change that lets the extension’s own display draw the file at all.