styles/tokens.cssDesignT-UI-01Designcards/views/<Card>View.tsxDesignT-UI-07 · T-UI-08DesignCardProps<M,V,G> ↓ onAction(tag, {...args, ...input}) · onView(patch)<Card>Container · T-APP-nnFrontend lead (b8)CardProps<M,V,G>filter actions[] and gestures for the viewerbind argscardActions → flowActionview state per memberframes and URL
flowAction runs a catalog commandspec.md §7.2 · §6.1Engineering- Design builds every visual piece; engineering wires data and actions (Will, 2026-10-02).
- The seam is one zod view model per card,
packages/rpc/src/<Card>Card.ts(T-APP-19). Until it lands, Views build against ui-components.md with local fixtures. Local fixtures are provisional; acceptance uses T-APP-19 schema fixtures. - A View exists only for a spec.md §14.3 row. Retained cards (Issue, PR, Review findings, Wiki, flow Form) keep their schemas.
Source spec.md §14.2.1, §14.3, §14.3.0, §7.2, §6.1; mvp.md §2 (rules 1 and 4), §6.4, M-35, M-36; ui-components.md v0.4 (opening diagram, Rules, Order of need, Completion gates); apps/app/src/mainview/styles/tokens.css. Engineering view ↗
Example: Answer on T9, a shared-state action
type Action = { // filtered for the viewer by the container
tag: CatalogTag // the catalog's tag type (T-CAT-01), opaque to the View
label: string // "Answer", "Merge", "Retry"
args?: Record<string, string> // bound by the container, e.g. { n: "12" }; the View passes them back unchanged
primary?: boolean
disabled?: { reason: string } // e.g. "Waiting for T8"
input?: FormField[] // present when the action needs a form
}
type BaseView = { maximized: boolean; tab?: string; filter?: string }
type CardProps<M, V = {}, G extends string = never> = {
model: M
actions: Action[] // buttons, in order
gestures: Partial<Record<G, Action>> // non-button gestures by name
onAction: (tag: CatalogTag, input?: Record<string, string>) => void
view: BaseView & V // this member's view state (§14.1.2)
onView: (patch: Partial<BaseView & V>) => void
}
// handler 1: onAction(action.tag, {...action.args, ...input})
args- Bound by the Container, e.g.
{ n: "9" }. The View passes them back unchanged. gestures- Non-button gestures by name: hover, go to definition, a docs link. A missing one does nothing.
disabled.reason- Shows as text in place of the button (#card).
input- A form for exactly the missing fields, never a usage sentence (FORM LAW).
onView- This member's view state: maximize, tab, filter, scroll, selection. Private; never shared state.
- Handlers
- Each does one of three: 1
onAction, 2onView, 3 local state, DOM focus or the clipboard (copyText). - Three doors
- A slash command, a button and the agent run the same command (THREE-DOOR LAW).
- A missing action means no button; a missing gesture does nothing. The Container filters
actions[]andgesturesfor the viewer; the View never decides who may act. - Tags are opaque. The View hands back
action.tagwith{...action.args, ...input}, and the control carriesdata-flow={action.tag}. - Handler 3 never leaves the View: roving tabindex, Escape to close, controlled inputs, disclosures that don't persist, Copy.
- A field the View needs but the props lack is a spec change. Raise it with the tech lead (8a), who updates spec.md §14.3, ui-components.md and T-APP-19 together.
Source mvp.md §2 (rule 1), Appendix A (three doors); ui-components.md v0.4 (Rules: three handler kinds, gestures; Shared types: Action, BaseView, CardProps<M,V,G>); spec.md §14.2.1, §14.1.2, §14.1.4, §6.1, §6.1.4, §7.2, §7.2.1; check C-UI-08; apps/app/AGENTS.md (THREE-DOOR LAW, FORM LAW); apps/app/src/mainview/cards/CardActions.ts (cardActions), apps/app/src/mainview/flows/FlowAction.ts (flowAction).
Shell anatomy: one conversation per branch, a timeline rail on desktop, pills on narrow screens
#shellDesktop: a viewport at least 1180 px wide. Alice's screen in retry-webhooks.
Narrow (390 px)
Composer and palette open
A card maximized (here the Run card: Inspect)
- 1Crumbs. Repository / main / branch. A parent crumb goes up; the last opens the tree.
- 2Branch tree. main, each item's branch in stack order, forks under their origin, with presence. ↑ ↓ move, ⏎ opens, ← goes up; focus returns to the crumb.
- 3Conversation. The branch's shared entries: prompts with their author, Smithers' answers with Context · n, and cards.
- 4Top edge. Live work above the screen, each with its single action. Two pinned rows, people-needed first, then “+N above”, which opens every hidden entry.
- 5Band. The entries on screen.
- 6List. One line per entry. Title; run entries also have an optional fast-model summary. Live entries pulse, Needs you is gold, failures are ember.
- 7Bottom edge. Live work below. Two pinned rows, then “+N below”, which opens every hidden entry.
- 8Notices. At most three, then “+N more”. Docked in the rail.
- 9Chat ⌘K. Opens the composer and palette in this branch's conversation.
- 10Composer and palette. Floats at the top over the conversation. Esc, a press outside or ⌘K again closes it; focus returns to the opener.
- 11Maximize. The same component, larger, over a scrim, with Restore; the chat control stays. Keyboard reachable; focus returns to the opener.
- 12Narrow edges. Below 1180 px: no timeline, one pill per edge, in the header and footer rows.
- 13Narrow notices. Float at the bottom left.
Shared by everyone on the branch
- Entries: prompts with their author, answers, events
- Shared cards, excluding private Confirm and uncommitted Draft
- Receipts: what an act did, as its own entry
- Run entries' summaries
- Claude Code and Codex conversations from branch terminals, read-only: no edit, resend, answer, approve, retry, stop or steer S2
Each person's own
- Scroll position and last-seen entry
- Card view: maximized, tab, filter, scroll, selection
- Theme
- Hidden notices
- Drafts: composer text, and a Draft card until Commit
- Confirm cards: only the asker sees one; others see nothing until the shared receipt
- Everything embeds in the conversation. Nothing opens full screen unless the person maximizes it (EMBED LAW).
- The timeline is desktop only. Hiding a notice preserves the entry; any still-applicable action remains available.
- UI-only flows (theme, open, maximize, navigate, palette, filters) change only the screen of the person who ran them, even when their app agent ran them.
Source mvp.md §6.4 (Home card, Branch conversations, Toasts, Timeline, Browser notifications), M-08, Appendix B.1; spec.md §14.1.1–§14.1.4, §14.2, §14.4, §14.5.1–§14.5.4, §15.1.5, §7.2.2; ui-components.md v0.4 (Rules: view state); apps/app/AGENTS.md (EMBED LAW, onboarding brief on the composer); mock AppFrame.tsx, Rail.tsx, Tree.tsx, mock.css (PORT · the left rail).
- 1Title. The ref chip and the title.
- 2Status word. One pill per state (#states).
- 3Header end. Owner, presence or a save state. See the variants below.
- 4Maximize. Becomes Restore when maximized.
- 5Body. Meta line, step strip, run flags, the question, evidence.
- 6Actions row. Only the actions supplied, in order: ghost buttons, then the one solid primary or a reason. A question is open, so no Stop.
Button weights
Header end, by card
One entry per thing
RunView, maximized: the monitor. No second conversation entry.- A View renders only the actions it is given. Stop is refused while a question or approval wait is open (spec.md §10.7.1), so this card has none.
- One solid button per card, for its primary act, with ghost buttons before it.
- One persistent entry per entity, keyed (kind, id). Showing it again jumps to that entry (spec.md §14.5.1).
- Header slots are presentation only: they show model fields and add none.
- A reason replaces the button it blocks, as text. An
Actionwithdisabled.reasonrenders that way. - Card body lines hold 12 words or fewer, in product words only.
Source mvp.md §2 (rules 4 and 7), §6.6 (TODO card), §6.14 (Monitor, Inspect); spec.md §14.2, §14.3 (TODO and Run rows), §14.6b, §11.6.4, §10.7.1, §4.1.0a; ui-components.md v0.4 Rules, Action, T-UI-04; apps/app/AGENTS.md (EMBED LAW, MINIMAL TEXT); design README (Visual rules); mock parts.tsx (Card), cards/Todo.tsx, cards/Run.tsx (RunFlags), world.ts (showCard).
| Mark | Reads as | Actor | Presence | Activity row | Line flag | Terminal header | Chat author |
|---|---|---|---|---|---|---|---|
AP |
Alicea person: a circle in their color | personcolor_index 1 |
editing retry.ts:10 | steers, answers | Alice | owner, or a watcher with | prompt author |
S |
Smithers for Benthe app agent for Ben: its square in Ben's color | agent smithersfor_member Ben · id: its session · color_index 0 |
Smithers for Ben · reading retry.ts | Smithers for Ben steered T9 | Smithers for Benwiki pages | none: never types | answers Ben, as everyone sees it |
S |
Smithersinstall events only: the ink square | systemnever an agent |
none | Rebased onto T8 | none: edits no lines | none | none |
C |
Claude Code for Benan external agent: its own square in Ben's color | agent claude-codefor_member Ben · id: its session · color_index 0 |
Claude Code for Ben · terminal 1 | Claude Code for Ben answered T9 | Claude Code for Ben | Claude Code for Ben, in Ben's terminal; Ben stays its owner | its terminal conversation, read-only; prompts name Ben S2 |
| Coding agent for Bena TODO's agent: its square in the owner's color | agent coding · T9for_member Ben · id: the run · color_index 0 |
Coding agent for Ben · Verify on T9; breathes while working | steps, Read, Context, Asks | Coding agent for Ben | its own session | asks through Needs you | |
R |
Reviewer for Bena review run: its own square in Ben's color | agent reviewerfor_member Ben · id: the review run · color_index 0 |
Reviewer for Ben · T9 at 5e7d2b0 | Reviewer for Ben: no blocking issues | none: reads only | none | none |
| Coding agentacting for nobody: the default agent color | agent codingno for_member · id: the run · color_index 6 |
at a learning run's step | a background run's steps | Coding agent | its own session | none | |
MC |
Maya via SSHthe person is the actor: her circle, a terminal badge | person · via sshcolor_index 2 |
editing retry.ts:2 | Maya via SSH changed 12 files | Maya · SSH | none: her own client | none |
| Changed outside Smithersno single session can claim it: a neutral square | outsidecolor_index 7 |
none | Changed outside Smithers · 3 files | none; the File card says “Changed outside Smithers · Compare” | none | none | |
@login |
@logina GitHub user who is not a member: the GitHub mark | githubcolor_index 7 |
none | @login on rows from GitHub | none | none | none |
- People are circles; agents, Smithers included, are rounded squares.
- Every agent doing work is its own participant with a stable id: Smithers, Claude Code, the coding agent, reviewers (M-34). It never collapses into the person's avatar.
- An agent acting for a member, Smithers included, takes that member's color and reads “Claude Code for Ben”. Plain “Smithers” in ink marks install events (
system), never an agent. - Only a person's own doors keep their circle, with a small badge: “Maya via SSH”, “Ben's terminal”, “Ben via CLI”.
color_index: 0–5 a member's color, also for anything acting for them; 6 an agent acting for nobody; 7 neutral, for GitHub users and outside writes. Tokens per index: #color.
Source mvp.md §3.1, §6.8 (Presence, External changes), M-21, M-27, M-32, M-34; settled ruling on M-34 marks (2026-10-02); spec.md §7.3.1, §7.3.2, §14.6a.1; ui-components.md v0.4 Actor, T-UI-01; mock parts.tsx (Avatar, actorName, flagName), world.ts (isSmithers, forWhom, via), mock.css (PORT · avatars), css/code.css (flags).
Status meanings: ui-components.md Tone. Token table v1, light and dark, each pair subject to contrast checks.
Teal · live or act
Working, Starting, the current step, live timeline rows, the solid button, the focus ring.
Gold · a person is needed
Needs you, stack attention, an approval toast, a wait for a person, a stale sync, the notification ask, a merge blocked until a person acts.
Ember · failed
Failed, a failed check (required ones too), a failed background run, “Merged · not active”.
ember-600 · ember-400
Neutral · settled or automatic
Queued, Paused, In review, Merged, Dropped, the wait for merge, waiting for a machine, system and order waits such as “Merges after T8”.
Actors · who, never what state
Colors 0–5 mark members and any agent or Smithers acting for them. Undelegated defaults: teal for an agent acting for nobody (6), neutral for GitHub users and outside writes (7). Ink marks install events.
#eda381 · Ben
#8cc5e8 · Alice
#bea6e6 · Maya
#d9be70
#8acaba
#e5a1b8
#ece7db · system
#45c4b2 · 6
Retired as status and agent chrome
Violet no longer marks a status or an agent. Identity violet stays: color 2, Maya.
- Status colors have fixed semantics: live is teal, attention is gold, failed is ember; done and quiet are neutral. In review is quiet.
- Actor color is a separate channel. It says who, never what state, and a status never borrows an actor color.
- Both themes gate acceptance: every swatch has a light and a dark value.
Source ui-components.md v0.4 (Tone, Actor); settled rulings on Tone and M-34 marks (2026-10-02); design README (Visual rules); mvp.md §6.3 (Sync status), §6.4 (Timeline), §6.12 (Pinned versions), §12; spec.md §4.4, §14.5.2; apps/app/src/mainview/styles/tokens.css; mock mock.css (PORT · identity and state tokens, PORT · TODO state, “Teal means live or act” overrides).
Waits
- Run waits: question, approval. Opened while working.
- Branch waits: conflict, moved off, outside push. Opened from any unmerged state.
- Settling one wait never settles another. Each open wait shows on the TODO card with its own action.
Precedence: the first that holds
- Merged
- Dropped
- Needs you: any wait open
- Paused
- Failed
- In review, Working, Starting or Queued: the run's phase
When the last open wait settles: Working, or Queued after release, if work is needed; In review if not; Paused if stopped; Failed if blocked.
- Each state has one glyph and one pill, the same on every card, row and timeline line.
- Merged is done. Learning is a receipt on the merged card (“2 lessons”), never a state.
- Drawn from mvp.md §4.1 and spec.md §4.1. spec.md's transition table is authoritative and adds rarer edges: a PR reopened on GitHub within 7 days revives a Dropped TODO, and a merge on GitHub counts from any unmerged state.
Source mvp.md §4.1, M-15; spec.md §4.1 (with §4.1.0a precedence and §4.1.1 queue copy), §10.7.1, §10.7.4, §10.8.0–§10.8.2; settled rulings on Stop and answers (2026-10-02); mock parts.tsx (StateGlyph, StatePill, stateLabel), mock.css (PORT · TODO state).
The TODO card's step strip mirrors the run
- Plan
- Implement
- Verify
- Review
- Propose
- Merge
- Plan
- Implement
- Verify
- Review
- Propose
- Merge
- Plan
- Implement
- Verify
- Review
- Propose
- Merge
- Plan
- Implement
- Verify
- Review
- Propose
- Merge
| After the wait, on | Back to | Then |
|---|---|---|
| a steer or requested change | Implement | Verify, Review, Propose |
| a clean rebase | Verify: checks only | Propose; the prior review stays (same patch-id) |
| a conflict-resolved rebase, or an edit | Verify | a new Review, then Propose |
| a merge or a drop | none | the run ends |
Inside a step: phases and cells, as Inspect shows them
- One attempt is one durable run of its pinned flow version. It lives until the TODO merges or is dropped; Retry starts a new attempt beside the old one.
- A machine restart re-runs no finished step: the run resumes, or shows interrupted with Retry (spec.md §19.1).
- Capture (
stack.candidate) and Propose (stack.propose) are system acceptance, not overridable flow steps. The step strip keeps its labels. - After Propose the run holds at the wait for merge. The wait needs no machine: the machine is released once safe-idle, and its slot stays held until the stop is confirmed.
- A clean rebase reruns checks only, and the prior review stays (same patch-id). A conflict-resolved rebase or a code change reruns review. Any rebase voids an approval.
- Phase titles and cell labels are deterministic. ✦ marks what the fast model wrote, only for runs someone inspects.
Source mvp.md §6.12 (Pinned versions), §6.14 (Monitor), Appendix B.5, J11; settled rebase ruling (2026-10-02); spec.md §10.3.1, §8.3.2, §10.4.1, §10.4.3, §10.4.4, §10.4.5, §10.5.3, §10.6.2c, §10.7.1, §11.4, §19.1, §11.6.3, §11.6.4, §14.5.3; ui-components.md T-UI-04 (steps), T-UI-10 (signals), T-UI-12 (RunModel); mock cards/Run.tsx, parts.tsx (StepStrip), cards/Flow.tsx, journeys/run.ts. Engineering view ↗
Mergeready · waiting · blocked · merging · donedone).
Authorizer. A session of an owner or maintainer. A member gets no Merge and reads the same reason, or “Ready · a maintainer merges”.
MergeReady(todo, reviewed_head_sha) · rows in order · the first that fails gives reason
- 1 ·
stateIn review: no open wait, not paused?noblocked - 2 ·
orderFirst unmerged item in the stack?nowaitingMerges after T8 - 3 ·
attentionNo stack attention open?noblocked - 4 ·
mergingNo merge fence set?nomerging - 5 ·
recheckingGeneration accepted after machine checks and review; PR push settled; PR head set?nowaitingChecks running on 5e7d2b0 - 6 ·
recheckingNo rebase pending; based on main's tip?nowaitingRebase pending - 7 ·
pending_workNo pending work since that generation?1nowaiting - 8 ·
stale_headReviewed head = PR head = GitHub's head?noblockedon GitHub ↗ - 9 ·
checksreview_requiredgithubRequired GitHub checks pass, required reviews met, not draft, mergeable?noblockedlint failedrequiredon GitHub ↗ readyEvery row holdsMergeReview & merge adds “Merges as Ben”
1 Row 7: no unconsumed input above inputs_seq (steer, amendment, review comment delivered as a steer, run answer), and the valid newest capture equals the accepted tree. A missing capture blocks.
Gold: a person must act. Neutral: system and order waits. Ember: a failed check.
Evidence is per revision
1b2c3d4earlier revision5e7d2b0current revision9e8f7a6new patch- One rule for every merge surface: no card offers a merge another card would refuse.
- MergeReady's nine rows run in order. The first failing row's reason replaces Merge, as text.
- Role and session sit outside MergeReady, in the authorizer. Only required GitHub checks block; machine checks and review count through the accepted generation (row 5).
- A clean rebase reruns checks only and keeps the prior review (same patch-id). A conflict-resolved rebase or a code change reruns review; an earlier review shows only when its patch-id matches. Any rebase voids an approval.
Source mvp.md §4.2 (Rebase, Merging), §6.3 (Checks finish, GitHub branch protection), §6.10, M-05; spec.md §10.6.1, §10.6.2, §10.6.2a, §10.6.2b, §10.6.2c, §10.4.3, §10.5.3; ui-components.md v0.4 (Merge, Evidence); settled merge and rebase rulings (2026-10-02); mock cards/Home.tsx, cards/Todo.tsx (Evidence), cards/Confirm.tsx. Engineering view ↗
Runs at once A · run
- Reads: code, branches, runs, the wiki
- Steer, answer, stop, resume, retry
- Rebase, fork, run a flow
- Wiki writes: pages keep history
- The asker's own screen: theme, open, maximize
- Open the asker's terminal; never type in it
One-click confirmation A✓ · confirm
- Commit, amend or drop a TODO
- Add to stack
- Bring in or Discard an outside push (Discard: maintainer)
- Delete a wiki page
- Propose a flow or agent edit
- Review a PR (
/review)
/todo.new Send one reset emailCClaude Code for Ben askedMerge A✓ · review_merge
- Opens the asker's own private Review & merge. Only a requesting owner or maintainer gets one.
No agent path – · never
- Members and roles
- Secrets
- Settings: model access, capacity, GitHub App
- Approvals that gate a merge
B.3: the coding agent's actions render in the cards a person's do
read · ls · glob · grepA “Read” line in the branch activity; each file opens the File cardReadretry.tsbackoff.tswrite · edit · apply_patchAn attributed edit in the File and Diff cards, with its line flagCoding agent for Benawait sleep(backoff(1))bash · testIts own Terminal session on the branch; anyone can watchterminal 2Coding agent for Benmemory · recallThe Context line; the preflight cell in InspectContext · 3askNeeds you, with Answer, on the TODO cardNeeds you- The app agent acts with the asker's authority and shows as Smithers for that person. It never merges or approves.
- External agents through the CLI or skill follow the same run, confirm and never rules.
- Only the asker sees Confirm; others see nothing until the shared action receipt.
- A flow renders the same card whoever runs it, and each run is its own instance. Exceptions: a Confirm card, seen only by its asker, and a Draft, seen only by its author until Commit. Only the actor's mark tells a person's act from an agent's.
Source mvp.md §3.1, Appendix B (legend, B.1, B.2, B.3, B.4, B.6), M-21, M-33, M-34; settled Confirm ruling (product, 16:51, 2026-10-02); spec.md §5.2, §5.3, §5.4, §6.1.2, §14.3 (Confirm, Draft), §14.5.1, §15.1.3, §15.1.5; ui-components.md v0.4 T-UI-05; mock cards/Act.tsx, cards/Confirm.tsx, cards/Draft.tsx, journeys/ask.ts, journeys/agent.ts, world.ts (ask, pressed).
Component traceability: each design ticket, its View, the mock that draws it, and the reel steps that show it
#components| Ticket | View | Mock source | Reel steps | Stage |
|---|---|---|---|---|
| T-UI-01T-APP-09 | ActorChip StateWord Tone | parts.tsx Rail.tsx | ?j=states&s=1?j=j3&s=2?j=j3&s=10 | S1 |
| T-UI-02T-APP-03 · T-FLW-12 | SetupView SettingsView | cards/Setup.tsx | ?j=j1&s=3?j=j1&s=8?j=j1&s=30?j=states&s=41 | S1 |
| T-UI-07T-APP-16 · T-APP-17 | BranchTree EntryRow ContextLine, Earlier archiveThe mock has no Earlier node. S2: read-only Claude Code and Codex conversations (spec.md §14.5.5). | Tree.tsx AppFrame.tsx parts.tsx | ?j=j6&s=10?j=agent&s=6?j=ask&s=6 | S1 |
| T-UI-06T-APP-01 · T-GH-08 | HomeView | cards/Home.tsx | ?j=j4&s=1?j=states&s=3?j=j10&s=14 | S1 |
| T-UI-11T-APP-15 | CodeEditorView (File, read-only), DiffView | cards/Code.tsx | ?j=j1&s=12?j=j1&s=21?j=j11&s=7 | S1 |
| T-UI-03T-APP-02 | DraftView | cards/Draft.tsx | ?j=j2&s=2?j=j2&s=5?j=j7&s=3 | S1 |
| T-UI-04T-APP-02 | TodoView: every state, question and approval forms, failure, evidence, PR line, merge control | cards/Todo.tsx | ?j=j4&s=2?j=states&s=5?j=states&s=10?j=j10&s=11 | S1 |
| T-UI-08T-APP-07 · T-APP-18 | ToastStack EdgeMap Timeline | Rail.tsx | ?j=j2&s=10?j=j2&s=11?j=j4&s=11 | S1 |
| T-UI-05T-APP-04 | ConfirmView (one_click, review_merge) | cards/Act.tsx cards/Confirm.tsx | ?j=agent&s=15?j=ask&s=10?j=states&s=16 | S1 |
| T-UI-09T-APP-06 | MembersView | cards/People.tsx | ?j=j1&s=24?j=j1&s=25?j=states&s=39 | S1 |
| T-UI-14T-CAT-01 | CommandsView (/help) | cards/Commands.tsx | ?j=ask&s=1 | S1 |
| T-UI-10T-APP-05 | FlowView | cards/Flow.tsx | ?j=j5&s=7?j=j11&s=5?j=states&s=36?j=states&s=37 | S1 |
| T-UI-12T-FLW-07 | RunView monitor and Inspect | cards/Run.tsx | ?j=run&s=1?j=run&s=2?j=run&s=6?j=j11&s=1 | S1 |
| T-UI-13T-FLW-08 | AgentView and model roles | cards/Agent.tsx cards/Setup.tsx | ?j=j11&s=14?j=j11&s=15?j=j1&s=8 | S1 |
| T-UI-23T-STK-08 · T-MCH-08 · T-GH-06 | TodoView repair parts: conflict view, moved-off and outside-push forms, Fork, Add to stackThe mock puts Fork and Add to stack on the Branch card. | cards/Todo.tsx cards/Branch.tsx | ?j=states&s=7?j=states&s=8?j=j10&s=6?j=states&s=24?j=j7&s=6?j=j7&s=11 | S1 |
| T-UI-15T-APP-10 · T-COL-05 | BranchView with moved-off controls | cards/Branch.tsx | ?j=j3&s=2?j=j7&s=6?j=states&s=23?j=states&s=24 | S2 |
| T-UI-16T-APP-11 | File and Diff states: reload, gone, renamed, Restore, Compare | cards/Code.tsx | ?j=states&s=25?j=states&s=26?j=states&s=27?j=states&s=29 | S2 |
| T-UI-17T-APP-12 | TerminalView | cards/Terminal.tsx | ?j=j3&s=3?j=j3&s=5?j=agent&s=10?j=states&s=31 | S2 |
| T-UI-18T-APP-13 | SecretsView | cards/People.tsx | ?j=j1&s=27?j=j1&s=29?j=states&s=40 | S2 |
| T-UI-21T-APP-20 | DocsView (/docs) | none yetThe mock lists /docs only in /help. | none yet | S2 |
| T-UI-22T-APP-21 | DebugApiView (/debug-api) | none yetThe mock lists /debug-api only in /help. | none yet | S2 |
| T-UI-19T-APP-14 | Co-editing visuals on CodeEditorView | cards/Code.tsx cards/Wiki.tsx | ?j=j3&s=8?j=states&s=28?j=j8&s=6 | S3 |
| T-UI-20T-FLW-06 | ProposalView and the lessons receipt | cards/Learning.tsx cards/Todo.tsx | ?j=j5&s=13?j=j5&s=14?j=j8&s=4 | S3 |
- Rows follow ui-components.md v0.4 Order of need. Stage 1 comes first; within a stage, the order a fresh install meets each component in J1, then J2, J4, J5 and J11.
- Step links open the built mock (
node .specs/design/mock/build.mjs).s=nshows the frame after step n. - Mock sources and reel steps are guidance. Acceptance is C-UI-12: each View renders every T-APP-19 fixture in light and dark, at 1280 and 390 px.
- A change to a retained card's fields first adds its spec.md §14.3 row.
Source mvp.md §5 (journeys), §11 (stages 1 to 3), M-35, M-36; ui-components.md v0.4 (Order of need, Completion gates, Props per component); spec.md §14.3, §14.3.0; tickets/README.md; tickets T-UI-01 to T-UI-23; mock src/journeys/*.ts (step numbers checked 2026-10-02), src/cards/*.tsx.
The mock (design)
.specs/design/ ├─ README.md decisions the mock embodies ├─ architecture.html this page └─ mock/ ├─ build.mjs → dist/index.html, one file ├─ check.mjs every step renders ├─ copy.mjs copy lint ├─ shot.mjs screenshots └─ src/ ├─ world.ts the model; mergeReadiness, revise ├─ parts.tsx Avatar, actorName, StepStrip, Card ├─ AppFrame.tsx shell: crumbs, conversation, │ composer, maximize ├─ Rail.tsx timeline, edges, notices ├─ Tree.tsx branch tree ├─ cards/*.tsx one file per card ├─ journeys/*.ts 15 reels; states.ts shows │ every card state ├─ mock.css, css/ PORT rules move to the app; │ MOCK rules stay └─ Player.tsx … the review harness
The app (planned)
apps/app/src/mainview/ ├─ styles/tokens.css Paper tokens ├─ cards/ │ ├─ views/ design · props only │ │ ├─ HomeView.tsx TodoView.tsx DraftView.tsx │ │ ├─ ConfirmView.tsx BranchView.tsx │ │ ├─ CodeEditorView.tsx DiffView.tsx │ │ ├─ TerminalView.tsx RunView.tsx FlowView.tsx │ │ ├─ AgentView.tsx CommandsView.tsx │ │ ├─ SetupView.tsx SettingsView.tsx │ │ ├─ MembersView.tsx SecretsView.tsx │ │ ├─ DocsView.tsx DebugApiView.tsx │ │ ├─ ProposalView.tsx │ │ └─ shell parts: BranchTree, EntryRow, ContextLine, │ │ ToastStack, EdgeMap, Timeline │ ├─ <Card>Container.tsx engineering · path not fixed │ ├─ CardRenderers.tsx renders Containers │ └─ CardActions.ts cardActions └─ flows/FlowAction.ts flowAction apps/app/src/docs/ bundled pages, toc.ts (T-APP-20) docs/api/openapi.yaml Debug API operations, bundled packages/rpc/ ├─ src/<Card>Card.ts zod view model (T-APP-19) │ TodoCard, DocsCard, DebugApiCard … └─ test/fixtures/<Card>.ts fixtures for the stories Todo, Docs, DebugApi … packages/smithers/ui/src/ @smthrs/ui: shared primitives
- Each new §14.3 card maps to a View; mock files may combine/split those presentations. Retained cards keep existing renderers.
- PORT and MOCK CSS annotations are migration guidance. The fixture gates are acceptance.
world.tsis the design's view of the data, not an API. The props are ui-components.md, then the zod schemas.- Each View ships fixture stories for every state its props allow: light and dark, at 1280 and 390 px (C-UI-12).
Source design README (Run it, Porting); ui-components.md v0.4 (opening diagram, Rules, Completion gates, T-UI-21, T-UI-22); spec.md §14.2.1, §14.3 (Docs, Debug API rows), §14.3.0; delta.md §9; tickets T-UI-01 to T-UI-23 (Scope, Changes); mock build.mjs, check.mjs, copy.mjs, shot.mjs.
Smithers MVP design architecture · smithers-06 · 2026-10-02. Contradictions between sources go to the design lead, not onto this page.