349 lines
17 KiB
Markdown
349 lines
17 KiB
Markdown
# The interface: what we need, how it is grouped, and how it is drawn
|
|
|
|
Written 2026-11-10. This replaces the earlier layout note: it is now the one document that
|
|
says what the interface contains. Layout comes after this, and is chosen from it.
|
|
|
|
Plain English throughout. No invented shorthand. If a word here is not obvious, it is
|
|
defined in "Words we use".
|
|
|
|
---
|
|
|
|
## Words we use
|
|
|
|
- **Workspace** — one page in TUIOS. The person switches between workspaces.
|
|
- **Panel** — one pane inside a workspace. Each panel is a program, or one area of one
|
|
program, that holds one kind of content.
|
|
- **View** — a way of looking at a panel, for example "the task tree" or "the diff". A
|
|
panel can hold several views and show one at a time.
|
|
- **Focus** — which panel receives the keys. Exactly one panel has focus at a time, and
|
|
the person can always see which one.
|
|
- **Fact** — a piece of truth with exactly one owner. Tasks, blockers, comments, runs,
|
|
costs and worktrees belong to Paperclip.
|
|
|
|
A workspace holds at most **four** panels. More than four cannot be read at a glance on
|
|
one screen, so a fifth thing to look at becomes a view inside a panel, or a new workspace.
|
|
|
|
---
|
|
|
|
## How things are grouped
|
|
|
|
The grouping is by what the person is doing, not by which system the data came from. There
|
|
are four things a person does with this factory:
|
|
|
|
1. **Decide and direct.** What is the state of the work, what is blocked, what is waiting
|
|
on me, what do I do next.
|
|
2. **Watch.** What is an agent doing right now, what has it changed, what has it cost.
|
|
3. **Talk.** Answer an agent, correct it mid-task, unblock a task with words.
|
|
4. **Author and govern.** Write a new task or plan, set the verify command, watch the
|
|
budget, repair the layout when TUIOS loses it.
|
|
|
|
That gives six workspaces. They are deliberately fewer than the number of things we could
|
|
show, because a person who cannot find the screen they need has gained nothing from more
|
|
screens.
|
|
|
|
| Workspace | The question it answers | Panels (maximum four) |
|
|
|---|---|---|
|
|
| **Board** | what is the state of the work, and what needs me | Task tree · Task summary · Needs you |
|
|
| **Work** | what is happening now, and what changed | Run log · Diff · Worktree facts |
|
|
| **Conversation** | what has been said, and what do I say back | Thread · Composer · Task header |
|
|
| **Author** | what am I asking for, and how will it be judged | Task form · Guidance · Preview |
|
|
| **Project** | which folder, which machine, what limits, what cost | Project facts · Costs · Settings |
|
|
| **Repair** | is the layout sound, and what went wrong | Layout map · Health · Log |
|
|
|
|
The **shell** workspace stays as it is: one pane with a prompt in the project folder, for
|
|
the moments when the person needs a shell and should not have to leave.
|
|
|
|
---
|
|
|
|
## The user interface items
|
|
|
|
These are the pieces the panels are made from. Each one says what it is for, which
|
|
Charmbracelet component implements it, and what it must show in its empty, loading and
|
|
failed states. The list is deliberately finite: if an item is not here, a panel does not
|
|
invent it.
|
|
|
|
### Navigation and framing
|
|
|
|
**1. Workspace strip.** A one-line strip at the top of every panel showing which
|
|
workspace this is and how many there are, with the current one marked. Implemented in
|
|
Lipgloss; TUIOS switches workspaces, so this is a position indicator, not a control.
|
|
Empty state: never empty. Failed state: never applicable.
|
|
|
|
**2. Panel frame.** A border with a title and a focus marker. Rounded border when the
|
|
panel has focus, plain border when it does not, plus the word `focus` in the title so the
|
|
difference does not depend on colour. Implemented with Lipgloss borders. Every panel has
|
|
one, and the frame is what the "too small" message replaces.
|
|
|
|
**3. Footer key hints.** The keys that work right now, in this panel, in this state. Uses
|
|
the `help` component with `key.Binding`, so a key that does not apply is not shown.
|
|
Never shows a key that would do nothing.
|
|
|
|
**4. Notice line.** One line for the result of an action, such as "sent", "created
|
|
AUD-166", or the exact error text. Disappears when the next action starts. Uses Lipgloss
|
|
only; the text is always the server's own words, never a paraphrase.
|
|
|
|
**5. Stale marker.** The time of the last successful read, shown in the panel title. The
|
|
purpose is honesty: a panel that has not read recently says so instead of looking current.
|
|
|
|
### Lists and rows
|
|
|
|
**6. Task row.** One line per task: selection cursor, identifier, status, assignee, title,
|
|
and a blocker badge when something blocks it. The `list` component with a custom
|
|
delegate, so filtering and scrolling come for free.
|
|
|
|
**7. Group header.** A heading with a count, such as "Blocked (2)". Not selectable.
|
|
Implemented in the list delegate.
|
|
|
|
**8. Status pill.** The task's state as a short word with a distinct style per state, and
|
|
a different shape as well as colour so it survives a monochrome terminal and colour
|
|
blindness.
|
|
|
|
**9. Assignee chip.** The agent's name, or a dash. Uses the agent name from Paperclip,
|
|
never an identifier fragment.
|
|
|
|
**10. Blocker badge.** `waits on AUD-163` on the row, read per task from the blocker
|
|
diagnosis. When the blocker is finished the badge says `ready`, because a task that is
|
|
ready but still marked blocked is the most confusing state we have.
|
|
|
|
**11. Needs-you card.** One card per decision waiting on a person: a refused merge, a
|
|
task waiting for an answer, a task whose blocker finished while it was still marked
|
|
blocked. Each card says what happened, what is expected, and the one key that acts on it.
|
|
Implemented as `list` items with a different delegate.
|
|
|
|
**12. Table.** For figures that must be compared: per-task cost, per-run duration,
|
|
per-file change counts. Uses the `table` component with fixed column widths taken from the
|
|
panel width, never from a constant.
|
|
|
|
### Reading long content
|
|
|
|
**13. Thread message.** Author, time, and the body with paragraph breaks and code blocks
|
|
preserved. Bodies are wrapped to the panel, never truncated with an ellipsis in the middle
|
|
of a sentence. Scrolls inside a `viewport`.
|
|
|
|
**14. Composer.** A multi-line text area for the reply, growing with the text up to a
|
|
third of the panel, then scrolling. Uses `textarea`. Enter sends and needs to be stated in
|
|
the footer, because a text area normally treats Enter as a new line.
|
|
|
|
**15. Diff view.** File headers, hunks, and line numbers, with additions and deletions
|
|
distinguished by a leading character as well as colour. Scrolls inside a `viewport`.
|
|
Very large diffs are capped with an explicit line saying how many lines were left out, and
|
|
a key that shows everything.
|
|
|
|
**16. Run timeline.** One row per run: state, what woke it, start and end, duration, cost,
|
|
and a link to the agent's final message. Uses `table` or a list delegate.
|
|
|
|
**17. Worktree facts.** The folder, the branch, the base it was cut from, and the
|
|
delivery state. Small, monospaced, never wrapped.
|
|
|
|
### Input and forms
|
|
|
|
**18. Form field.** A label, an optional "(required)", a hint line under it, and the value.
|
|
Single-line fields use `textinput`; the description uses `textarea`. Tab moves forward,
|
|
Shift-Tab moves back, Enter on the last field submits.
|
|
|
|
**19. Validation message.** Directly under the field that is wrong, in the field's own
|
|
words, and the submit key stays available so the person can correct and try again.
|
|
|
|
**20. Result receipt.** After a write: the identifier that was created or the state that
|
|
was set, with the server's response behind it. A failure shows the server's message
|
|
verbatim, because paraphrasing an error we do not understand is how an afternoon is lost.
|
|
|
|
**21. Confirmation prompt.** For anything destructive: the exact thing being removed, and
|
|
the word that must be typed to continue. Uses `textinput` with no suggestions.
|
|
|
|
### Status and feedback
|
|
|
|
**22. Spinner with a verb.** While a read or a write is in flight: what is happening, not
|
|
just that something is. Uses `spinner`.
|
|
|
|
**23. Progress bar.** Only for things with a known count, such as "3 of 7 tasks read".
|
|
Uses `progress`. Never used as decoration, and never used to fake a duration.
|
|
|
|
**24. Health row.** One line per check in the Repair workspace: name, pass, fail or not
|
|
run, and the reason. Three states, never two, because "not run" is not "pass".
|
|
|
|
**25. Empty state.** Every panel says why it is empty: "no tasks in this project", "this
|
|
task has never run", "no worktree, so nothing to compare". An empty panel with no words is
|
|
a bug.
|
|
|
|
**26. Error state.** The failed thing, the exact message, and the one action that is still
|
|
possible, such as retry or open the Repair workspace.
|
|
|
|
### Icons
|
|
|
|
**27. Glyphs.** A small set used consistently: running, waiting, blocked, done, failed,
|
|
unread. Taken from the glyph set TUIOS reports, with an ASCII fallback, and never the only
|
|
carrier of meaning. Checked with `tuios list-glyphs` before use, not assumed.
|
|
|
|
---
|
|
|
|
## What each panel shows, and where the facts come from
|
|
|
|
| Panel | Shows | Reads from |
|
|
|---|---|---|
|
|
| Task tree | groups, rows, badges | company issue list, then the blocker diagnosis per task |
|
|
| Task summary | status, assignee, priority, blockers, verify command, cost, last run | single task read, blocker diagnosis, cost summary |
|
|
| Needs you | decisions and waits | task states, merge refusals, pending answers already on the task |
|
|
| Run log | run timeline and activity | runs, activity |
|
|
| Diff | changed files and the change | `git` in the task's own worktree |
|
|
| Worktree facts | folder, branch, base, delivery state | the task's current execution workspace |
|
|
| Thread | messages | comments |
|
|
| Composer | the text being written, the status to send | the person, then a comment or a status change |
|
|
| Task header | identifier, title, status, assignee | single task read |
|
|
| Task form | the fields being written | the person, then a created task |
|
|
| Guidance | what a good task needs, and the project's verify command | the project's `.harness` file |
|
|
| Preview | the description as the agent will receive it | the form, not the server |
|
|
| Project facts | folder, machine, session, project identifier | the project's `.harness` file |
|
|
| Costs | spend by task and by agent | cost summary per task, agent budget |
|
|
| Settings | verify command, budget, watched task | the `.harness` file, then Paperclip for what it owns |
|
|
| Layout map | workspaces and panels as they actually exist | TUIOS |
|
|
| Health | checks and their outcome | the checks themselves |
|
|
| Log | what the repair did | the repair's own output |
|
|
|
|
Two rules follow and are not negotiable:
|
|
|
|
- **A panel never invents a fact.** If Paperclip does not have it, the panel says it does
|
|
not have it.
|
|
- **A panel shows when it last read.** So a wrong panel is visibly stale rather than
|
|
quietly wrong.
|
|
|
|
---
|
|
|
|
## How it is drawn
|
|
|
|
**One theme, semantic roles.** Colours are named by role (text, muted, accent, success,
|
|
warning, error, and a surface colour), and panels ask for the role, never for a hex value.
|
|
A dark and a light variant exist from the start.
|
|
|
|
**Focus is unmistakable.** The focused panel gets a rounded border, a bright border colour,
|
|
and the word `focus` in its title. Two of those three do not depend on colour.
|
|
|
|
**Density.** One cell of horizontal padding inside a frame, one blank line between
|
|
sections, no blank line between rows. Rows are single lines except thread messages, which
|
|
are the only content that gets paragraph space.
|
|
|
|
**Alignment.** Identifiers, statuses, assignee names and numbers are aligned into columns
|
|
whose widths are computed from the content in view, capped at a share of the panel width.
|
|
Never a hardcoded column width.
|
|
|
|
**Truncation.** A truncated title ends in an ellipsis and the full text is available with a
|
|
key that opens a detail view. Nothing important is truncated silently.
|
|
|
|
**No decoration that carries no meaning.** No gradients, no box-drawing around every row,
|
|
no colour that does not correspond to a state.
|
|
|
|
**Motion.** Only two things animate: the spinner while something is in flight, and the
|
|
selection cursor as it moves. Nothing else moves on its own.
|
|
|
|
**The Charmbracelet pieces we use:** `list` for rows and decisions, `table` for figures,
|
|
`viewport` for anything scrollable, `textarea` for the composer, `textinput` for fields
|
|
with one line, `help` and `key` for the footer, `spinner` and `progress` for feedback.
|
|
Tabs are not a component in this collection, so a view switcher inside a panel is built
|
|
from Lipgloss and the `help` component, and is styled like the rest of the interface.
|
|
|
|
---
|
|
|
|
## Keys
|
|
|
|
TUIOS keeps `h`, `j`, `k`, `l`, `z` and `n` in window management mode, so no panel may use
|
|
them. A bare Esc must stay free, because it closes a box.
|
|
|
|
| Where | Key | Does |
|
|
|---|---|---|
|
|
| Any panel | Tab, Shift-Tab | move focus to the next or previous panel |
|
|
| Any panel | ? | show the keys for this panel |
|
|
| Any panel | r | read again from Paperclip |
|
|
| Any panel | q | leave this panel's program, returning the pane to its shell |
|
|
| Any panel | Esc | close the open overlay or leave the composer, never quit |
|
|
| Task tree | Up, Down | move the selection |
|
|
| Task tree | Enter | open this task in the Conversation and Work workspaces |
|
|
| Task tree | a | assign to the configured agent |
|
|
| Task tree | Space | expand or collapse a group |
|
|
| Thread | Up, Down, Page Up, Page Down | scroll |
|
|
| Composer | Enter | send |
|
|
| Composer | Shift-Enter | new line |
|
|
| Composer | s | choose the status to send with the reply |
|
|
| Diff | Up, Down, Page Up, Page Down | scroll |
|
|
| Diff | f | show the whole file, not the capped view |
|
|
| Forms | Tab, Shift-Tab | next or previous field |
|
|
| Forms | Enter | next field, and submit on the last one |
|
|
| Destructive | typed word | confirm |
|
|
|
|
No key means two things in two panels. Where a panel needs a key that is taken, it uses a
|
|
different one rather than overloading.
|
|
|
|
---
|
|
|
|
## Size, and what happens when there is not enough
|
|
|
|
Every panel declares a smallest useful size. When a panel is smaller than that, it draws
|
|
its own short message with the size it has and the size it needs, and nothing else. The
|
|
program never draws a broken layout and never invents a scrollbar to hide the problem.
|
|
|
|
| Panel | Smallest useful size |
|
|
|---|---|
|
|
| Task tree | 30 columns by 10 rows |
|
|
| Task summary | 30 by 8 |
|
|
| Needs you | 30 by 6 |
|
|
| Run log | 40 by 10 |
|
|
| Diff | 40 by 12 |
|
|
| Worktree facts | 30 by 6 |
|
|
| Thread | 40 by 12 |
|
|
| Composer | 40 by 4 |
|
|
| Task form | 50 by 14 |
|
|
| Guidance | 30 by 6 |
|
|
| Preview | 40 by 10 |
|
|
| Project facts, Costs, Settings | 40 by 8 |
|
|
| Layout map, Health, Log | 40 by 8 |
|
|
|
|
The workspace itself needs 80 columns by 24 rows. Below that, the whole workspace shows one
|
|
message naming the size it has and the size it needs.
|
|
|
|
---
|
|
|
|
## Layout, once the panels are settled
|
|
|
|
The panels above do not fit in one workspace, and should not. Layout is chosen by the
|
|
width of the terminal, so the person gets as much as their screen can carry and never a
|
|
layout pretending to have room it does not.
|
|
|
|
- **150 columns and wider:** Board shows tree and summary side by side with Needs you under
|
|
the tree. Work shows run log and diff side by side. Conversation shows thread above
|
|
composer with the task header above both.
|
|
- **110 to 149 columns:** two panels per workspace at most; the third becomes a view
|
|
switched with a tab inside the panel that shares its kind of content.
|
|
- **80 to 109 columns:** one panel per workspace at full width, in the order Board, Work,
|
|
Conversation, Author.
|
|
- **Below 80 by 24:** one message, nothing else.
|
|
|
|
The exact three candidate arrangements are drawn in the earlier note and are still valid
|
|
for the wide case; what changes here is that the panels themselves are now defined, so the
|
|
layout is a matter of which panels share a workspace rather than what a panel contains.
|
|
|
|
---
|
|
|
|
## What is not in this version, deliberately
|
|
|
|
- No chat with an agent as a separate thing: the Conversation workspace is the chat.
|
|
- No plan editor: a plan is a task's description, and the Author workspace writes it.
|
|
- No second task board: TUIOS has one, Paperclip has one, and this interface is the one
|
|
that knows about blockers and worktrees.
|
|
- No settings for colours: one theme, two variants, no per-panel colour choices.
|
|
- No dashboards of figures with nothing to act on: every number sits next to the thing it
|
|
describes.
|
|
|
|
---
|
|
|
|
## Decisions needed before building
|
|
|
|
1. **Does the tree drive the other workspaces?** Proposal: pressing Enter writes the chosen
|
|
task's identifier into the project's `.harness/harness.toml` as `watching`, and asks
|
|
TUIOS to show the Conversation workspace. The other panels watch that file and reload
|
|
when it changes. One fact, one owner, no message bus, and it survives a restart.
|
|
2. **Six workspaces, or fewer?** The proposal is six. Fewer means more switching inside a
|
|
panel, which costs a key and hides state.
|
|
3. **Which glyph set?** Depends on the font in the terminal; must be checked with
|
|
`tuios list-glyphs` on the machine the person actually uses.
|
|
4. **Is the diff a panel or a view inside the Work workspace?** A panel never squeezes the
|
|
run log; a view keeps the workspace count down.
|