# The plan, and how the interface sits on Paperclip Written 2026-11-10, after a wrong turn: I split every workspace into three panes without being asked, and it broke the working layout. It has been reverted. This document says what exists, what is proposed, and which Paperclip endpoint each thing reads or writes. Nothing here is invented: every endpoint below was called on this machine and answered. ## What is on screen today Seven workspaces, one pane each: `Shell>shell`, `Board>board`, `Work>work`, `Reply>reply`, `New task>new`, `Project>project`, `Repair>repair`. Inside a pane the program draws several panels (Board draws three), and you switch focus with Tab. That is the state that works. ## Paperclip's objects, and where each one is seen | Paperclip object | Endpoint, measured | Where it appears now | |---|---|---| | company | `GET /api/companies/{id}` | not shown; the id is in the project file | | project | `GET /api/companies/{id}/projects` | `Project>project` | | task | `GET /api/companies/{id}/issues`, `GET /api/issues/{id}` | `Board>board`, `Reply>reply` task panel | | blockers of a task | `GET /api/issues/{id}/diagnostics/blockers` | `Board>board`, per row | | comment thread | `GET /api/issues/{id}/comments` | `Reply>reply` | | runs of a task | `GET /api/issues/{id}/runs` | `Work>work` | | activity | `GET /api/issues/{id}/activity` | `Board>board` needs-you tab, `Work>work` | | cost per task | `GET /api/issues/{id}/cost-summary` | `Board>board` detail, `Work>work` facts, `Project>project` costs | | worktree and branch | the task's `currentExecutionWorkspace` | `Work>work` change and facts | | agents | `GET /api/companies/{id}/agents` | `Project>project` facts and limits, by name and budget | | **an agent's runs, company-wide** | `GET /api/companies/{id}/heartbeat-runs` | **nowhere yet** | | **a run's log** | `GET /api/heartbeat-runs/{runId}/log` — 300 KB of JSON lines for one finished run | **nowhere yet** | | **a run's events** | `GET /api/heartbeat-runs/{runId}/events` | **nowhere yet** | | agent pause, resume, wake | `POST /api/agents/{id}/pause`, `/resume`, `/wakeup` | **nowhere yet** | | agent settings | `PATCH /api/agents/{id}` — accepts `role`, `adapterConfig` (the model), `runtimeConfig` (heartbeat), `budgetMonthlyCents`, `status` | **nowhere yet** | So the honest answer to "where do I see the Pi agents working": **you cannot, yet.** The data is all there and the runs are already recorded — 281 of them on this instance — but no screen shows them. That is the largest missing piece, and it is the next workspace. ## Missing: the Agents workspace This is the one the person keeps asking for and it does not exist. Proposed as one pane, the same shape as the others, drawing three panels with tabs: ``` Agents>agents ╭─ agents roster runs ╮ │ Campfire idle │ ● Builder running AUD-163 started 14:12 1m 20s 1 cent │ ● Hub idle last run 13:58 │ ● Documenter idle ╰───────────────────────────╯ ``` - **roster** — every agent: name, state (`idle`, `running`, `needs input`, and Paperclip's own status), current task if any, spend this month, budget. From `GET /api/companies/{id}/agents`. - **runs** — the company's run list, newest first: agent, task, state, what woke it, start, duration, cost. From `GET /api/companies/{id}/heartbeat-runs` (281 today). - **log** — the tail of the chosen run, from `GET /api/heartbeat-runs/{runId}/log`. This is the closest thing to "watching Pi work": the log grows while the run is live, and `lastOutputAt`/`lastOutputBytes` on the run say how fresh it is. Actions, all with the user key, all reversible: - `enter` on a run → its log in the log tab. - `p` pause, `P` resume an agent (`POST /api/agents/{id}/pause|resume`). - `w` wake an agent (`POST /api/agents/{id}/wakeup`). - `e` open its settings (see below). ## Missing: working on an agent — role, model, cost Paperclip owns these, so the interface edits Paperclip, never a local file. One more panel, `Agents>settings`, or a tab inside `Agents>agents`: | Field | Paperclip field | Endpoint | |---|---|---| | name and job title | `name`, `title` | `PATCH /api/agents/{id}` | | role | `role` | same | | who it reports to | `reportsTo` | same | | model (the LLM) | `adapterConfig.model` | same, with `replaceAdapterConfig` care | | heartbeat on/off, concurrency | `runtimeConfig.heartbeat` | same | | monthly budget | `budgetMonthlyCents` | same | | pause / resume | `POST /api/agents/{id}/pause`, `/resume` | separate calls | Two rules that fall out of this and are not negotiable: a change to a model applies to that agent's **next** run, never to one in flight; and a budget change is recorded with who changed it, because Paperclip's audit trail is the only record we have. ## Tool panels: Lazygit, Hunk, a shell, the review Both are installed on this machine and I verified the paths: `/run/current-system/sw/bin/lazygit` and `/etc/profiles/per-user/sam/bin/hunk`. They are **not** to be reimplemented. The proposal is one key in `Work>work`: - `t` opens a chooser: `shell · lazygit · hunk · git log · ocr`. - The chosen tool opens as a pane **in the current workspace**, beside the panel you were reading, and takes focus. - `q` or `esc` closes it and focus returns exactly where it was. - Nothing is created until you ask, so the layout stays as it is today. This is the answer to "I thought we had Lazygit and Hunk": they are installed, they are not wired in, and wiring them in is one pane-opener plus a key. ## The review: ocr is installed and has already run `ocr` is at `/home/sam/.local/bin/ocr`, version `open-code-review v1.13.6`. It is in the project's `bin/merge` and `bin/review`, and it has blocked a real merge: on `AUD-165` it reported a critical finding (`rm -rf "$HOME/tmp"` deleting `/tmp` when `HOME` is empty) and the merge was refused. The Repair screen once said "not on the path" because a pane started by TUIOS gets a smaller PATH than a shell; that was fixed by looking in the usual places. Where it belongs in the interface: a **review panel inside `Work>work`**, showing the last verdict for the chosen task, its findings, and the blocking ones in red. The merge stays a command (`bin/merge`), because a merge is a decision with a lock, not a keystroke. ## Mouse-1 and Switch Measured just now: **not installed** — no `mouse`, `mouse1` or `switch` binary on this machine, and nothing obviously serving them locally. So nothing can be built on them yet without adding software first. Where they would fit if added: Mouse-1 is a small probability model that answers typed questions; Switch turns a state into those questions. The honest use in this factory is **routing and judgement that must be cheap and repeatable** — "is this task ready", "does this comment answer the question", "which agent should take this" — rather than prose generation. That is a later milestone, after agents and the review panel, and it needs a decision about installing both, plus a measurement of whether they are better than the existing cheap model already configured for agents (`omni/deepseek/deepseek-v4-flash`). ## The order I propose 1. **Agents workspace** — roster, runs, log. This is the missing view of Pi working, and it is read-only, so it cannot break anything. 2. **Agent settings** — role, model, budget, pause/resume. First write surface aimed at agents rather than tasks. 3. **Tool panels** — `t` opens Lazygit, Hunk, a shell, `ocr` in the current workspace. 4. **Review panel** in `Work>work` — the last verdict and its findings, beside the diff. 5. **Mouse-1 / Switch** — only after the above, and only after they are installed and measured. Each of the first four is one pane, one program, no change to the working layout. Nothing in this list requires splitting workspaces again. --- # Answers to the open questions, 2026-11-10 **Where settings are set.** `Agents>agents` has a fourth tab, **settings**, which edits the chosen agent: role, job title, model, monthly budget, heartbeat. `enter` edits the field in place, `esc` cancels, and `p` / `P` / `w` pause, resume and wake. Each save is one `PATCH /api/agents/{id}` merged into that agent's existing configuration, so a model change never wipes its folder or instructions. `Project>project` shows spend and limits read-only, because Paperclip owns them and a second editable copy is how two screens start disagreeing. **Spend.** Read from `cost-summary` per task (`Project>costs`, `Board>board`, `Work>work`). The monthly budget is per agent, set in `Agents>agents` settings. There is no company-level control on any screen yet. **Skills for sub-agents.** Not in the interface. Paperclip has the endpoints — `GET /api/agents/{id}/skills`, `POST /api/agents/{id}/skills/sync` with `add`, `remove` or `replace` — so a read-only skills row is cheap and a full editor is a later step. The rule worth keeping: an agent gets the skills its job needs and no more, which the `add`/`replace` model already expresses. **Where work is added.** `New task>new`, which writes a Paperclip task. A second place to write tasks (Tuxedo, a notes file, a card board) would be a second owner for the same fact and is exactly the failure the old project had. Personal notes are different from tasks: if they are wanted, they belong in the project's own `.harness/NOTES.md`, and Tuxedo can read it per project without pretending to be a task board. **`office --host` from another machine.** Not implemented, and the runbook says why: session creation needs a real terminal, so a person creates the session (`tuios new --host nixos-desktop "new test project"`) and then runs `bin/office ` inside it, on the machine that owns the folder. `--host` today only records the host in the project file. Driving `bin/office` on `.27` from `.13` would need ssh plus a remote `bin/board`, which is a deliberate later step, not an accident. **Seeing and switching projects.** Not built. Paperclip has the list (`GET /api/companies/{id}/projects`); what it cannot know is which folder on which machine each one lives in. The proposal: a small local registry of adopted projects (`~/.config/paperclip-harness/projects.toml`: project id, folder, host, session), filled by `bin/office`, and a `Project>projects` tab that lists them and switches by writing the project into the current folder's `.harness/harness.toml`. A project on another machine can only be switched to if the pane can reach it, so it would be shown as `on .27`, not offered. **Artifacts.** Paperclip work products: an uploaded file, a pull request, a preview URL, a commit or a branch, attached to a task by an agent. They are inspectable records of what a task produced. Nothing shows them yet; the natural home is a `Work>artifacts` tab listing them with their links, read from the task's work products. **"Workspaces" in Paperclip.** Paperclip has no workspaces. It has companies, projects, issues (tasks), agents and runs. A *workspace* is TUIOS's word for a page; a *pane* is a terminal inside it. When Paperclip says workspace it means a project's code folder (`currentExecutionWorkspace`), which is the git worktree a task runs in. **Charts.** TUIOS ships `plot` (Go), `loom` and TML. Go is the better fit here because the panels are already Go and the data is already in memory: a spend-by-day chart in `Project>costs` is a few dozen lines against `tuios.dev/plot`, where a TML surface would be a second language and a second round trip. Worth doing once the functional tests pass. **Mouse-1 and Switch.** Still not installed on this machine. Unchanged from the earlier note: they would serve cheap repeatable judgement, later, after they are installed and measured. --- # Findings for the next round of decisions, 2026-11-10 Everything below was measured on this machine. Nothing here is proposed without saying so. ## Skills per agent — the API already models it `GET /api/agents/{id}/skills` returns, for each agent: ``` mode: "persistent" desiredSkills: ["paperclipai/paperclip/paperclip"] entries: [ { key: "company//obsidian-cli", runtimeName: "obsidian-cli--b74ae42966", desired: false, managed: true, state: "stale", sourcePath: "…/instances/default/skills//obsidian-cli", targetPath: "/home/sam/.pi/agent/skills/obsidian-cli--b74ae42966" } ] ``` So Paperclip already models exactly what is wanted: a desired set per agent, a managed set actually installed, and a state (`stale` today for `obsidian-cli` on `Builder`, which is worth fixing on its own). `POST /api/agents/{id}/skills/sync` with `add`, `remove` or `replace` sets the desired set; `replace` is the operation that means "this agent gets these and nothing else", which is how a sub-agent's context is kept small. Company level, there is more: `GET/POST /api/companies/{id}/skills` (the catalog), `/skills/{id}/versions`, `/skills/{id}/audit`, and `GET/PUT /api/companies/{id}/skill-policy` with `/skill-policy/evaluate`, which is a company-wide rule about which skills may be used. Proposed in the interface: `Agents>agents` settings tab gains two rows — **skills** (the desired set, read-only at first, with `add`/`remove` later) and **skill source** (company catalog or the agent's own). A full skill browser is a later screen, not a panel. ## Memory — three different things wearing one word | What | State here | What it does | |---|---|---| | **engram** | installed, `engram v1.16.1`, MCP server mode, no pi MCP entry yet | persistent memory for agents, over HTTP or MCP | | **headroom** | running, `headroom-proxy v0.24.0`, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression enabled | compresses prompts on the way out; it is a proxy, not a store | | **pi memctx** | in use in this session | the memory gateway that injects notes into a prompt | They are not alternatives: engram stores, headroom compresses, memctx injects. For agents, the only lever Paperclip gives us is per-agent configuration — `adapterConfig` (the folder, the model, the instructions bundle) and `runtimeConfig` — so memory is set per agent by pointing that agent at the proxy or the storage it should use, not by a global switch. Proposed: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, read from its adapter configuration; and nothing more until one agent has been run both ways and the difference measured. ## MOUSE-1 - `MOUSE_API_KEY` **is** set in `~/.config/environment.d/10-secrets.conf` (name checked, value never printed). `JEV_API_KEY` is set as well. - No `mouse`, `mouse1`, `jev` or `switch` binary is installed. - The previous project already wrote the policy, in `~/paseo/projects/tuios_coding_harness/plan/*`: MOUSE-1 is **"triage only: label, score, route, escalate. Never a gate, never a permit"**, and explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error turns a green run into a lie. That policy is right and should be adopted unchanged. Its place in this interface, if it is added: `Board>board` needs-you could be ordered by a MOUSE-1 score, and `Work>review` could use it to pre-sort findings. Never the merge, never an approval. ## Lazygit Already wired: `t` in `Board>board` or `Work>work`, then choose Lazygit. It opens beside the pane, in the same workspace, and `q` closes it. Hunk, Yazi, Neovim, fzf, a shell and ocr are in the same chooser. ## The old `office` command, and what ours is missing The previous project's `office` does four things, in order: 1. makes the folder and remembers the host in `/.harness/host`; 2. runs `new-project` to write the project scaffold — `settings.toml`, one file per role, `verify.sh`, the per-screen notes — **writing only what is missing, never overwriting**; 3. refuses to continue if the TUIOS session does not exist, and prints the exact `tuios new ` line to run; 4. runs its `board` to build or repair the pages, then prints how to attach. Ours does 1, 3 and 4 (with a different file: `.harness/harness.toml`). It does **not** do 2: there is no scaffold, no per-role file, no `verify.sh`, no page notes. That is a real gap and the cheapest useful one to close. ## Dashboard — the API already answers it `GET /api/companies/{id}/dashboard` returns 1.8 KB: ``` agents: {active: 6, running: 0, paused: 0, error: 0} tasks: {open: 8, inProgress: 0, blocked: 4, done: 147} costs: {monthSpendCents: 11, monthBudgetCents: 0, monthUtilizationPercent: 0} pendingApprovals: 0 budgets: {activeIncidents: 0, pendingApprovals: 0, pausedAgents: 0, pausedProjects: 0} runActivity: [14 entries] ``` That is a whole dashboard in one call, and it is cheap enough to poll. Proposal: a `Project>overview` panel showing those four blocks and a sparkline of `runActivity`, drawn in Go with `tuios.dev/plot` rather than embedding Paperclip's web dashboard. ## Not doing Artifacts, as instructed. Nothing about them will be added.