Showcase README; Outline collection for agents; repository created on Gitea

This commit is contained in:
Sam
2026-11-11 21:12:35 +11:00
parent 28993d029d
commit f07e7b5d98
9 changed files with 608 additions and 112 deletions

View File

@@ -524,3 +524,91 @@ Say go on 1 and I will run the project-docs pass before anything else.
- session: [[packs/paperclip-harness/80-sessions/paperclip-harness-headroom-integration-machine-drift-cancel-|paperclip-harness: headroom integration, machine drift, cancel feature, office workflow]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-itself-2026-11-11-08-00-32|Rich discovery: itself 2026-11-11 08:00:32]]
- context: [[packs/paperclip-harness/20-context/tmp|itself]]
---
## Update (2026-11-11 08:20:35)
## Rich discovery update (2026-11-11 08:20:35)
You were right to push back on Headroom, and I had the reason wrong. Here is what the tests actually show.
## Headroom: corrected, with evidence
```
router POST /v1/chat/completions deepseek/deepseek-v4-flash → 200, SSE, "ok" in 1.1 s
headroom POST /v1/chat/completions deepseek/deepseek-v4-flash → 502 {"code":"proxy_error"}
```
`docker logs headroom` shows LiteLLM repeating *"Provider List: https://docs.litellm.ai/docs/providers"*. Headroom runs from `ghcr.io/chopratejas/headroom:latest` and is built on **LiteLLM**, which does not recognise this router's model ids (`deepseek/deepseek-v4-flash`, `auto/best-fast`), so it never makes the call. The same request to the router succeeds, so key, model and request shape are all fine.
So it is **not** blocked by Anthropic and **not** by a key. It is blocked by LiteLLM not knowing your router's models. To use it as a provider, headroom's own model list must define them, for example `openai/deepseek-v4-flash` with `api_base: http://192.168.20.13:20129/v1` and your key. That is a change inside that container, not in our software. My earlier "needs an Anthropic credential" was wrong, and the docs are corrected.
## headroom-ai installed, and tested
Installed for Pi on **`.13`, `.27` and `.51`**, and the library resolves and calls the service:
```
tokensBefore: 2809 tokensAfter: 2809 message length 12800 of 12800
```
No saving there because headroom protects a single long user message — the tool works, the test case was just one it deliberately leaves alone. So `compress_for_agent` can now load; giving it to one agent is `space` in `Agents>agents` → extensions.
## Machines
| | `.13` | `.27` | `.51` |
|---|---|---|---|
| Go | 1.26.5 | 1.26.2 | **added to config, needs a rebuild** |
| headroom-ai for Pi | installed | installed | installed |
| Nerd Fonts | 384 | 98 | 98 |
| Pi | 0.82.1 | 0.82.1 | 0.87.1 |
On `.51` I added `go gopls` to `/etc/nixos/hosts/sam-thinkpad/configuration.nix` (backup at `.bak-go`), and `nix build --dry-run` evaluates cleanly. You rebuild with:
```
sudo nixos-rebuild switch --flake /etc/nixos#sam-thinkpad
```
`.13` and `.27` are behind `.51` on Pi (0.82.1 vs 0.87.1). That is a flake bump, and I would do it with you rather than alone.
## Documentation: first piece done
`docs/architecture.mmd` and `docs/diagrams/architecture.png` — one diagram showing the person, the eight TUIOS panes, the `bin/` commands, Paperclip with its database and Pi agents, and where the work physically happens (worktrees, Pi sessions, skills, git). Linked from the README top. Committed as `28993d0`.
The project-docs skill prescribes five layers, and I need one answer from you before writing into them:
1. **Gitea** — this repo has no remote. Should I create a Gitea repo and push?
2. **Obsidian** — a note in `010 inbox` on `.27` (the skill says never to choose its folder; `obsidian-sorter` proposes and you approve).
3. **Mermaid + Archify** — the diagram is written and rendered; publishing the interactive map to `maps.lab.audasmedia.com.au/paperclip-harness/` is the remaining step.
4. **Vikunja** — a board for human task tracking, or the JSON in `docs/`.
5. **Outline** — the AI-context collection (`00-index`, `01-system-overview`, `02-config-and-env`, `03-code-map`, `04-agent-runbook`).
Say which of 1, 2, 4, 5 you want (3 is half done), and I will write them in that order.
## Source paths observed
- `nix/store/kh6c296264jngs70d8ibqk7zglyvd533-user-units.drv`
- `nix/store/qv508bjxrbsnn6hj8lvrlb38x3j631lx-etc.drv`
- `nix/store/v8rgpfj7ighpjbjmz184djg11m20c7bm-activate.drv`
- `nix/store/jarpr30smi73c6wwjlrigd98dmhj7vnl-nixos-system-sam-thinkpad-26.11.20260926.e158d9e.drv`
- `home/sam/.pi/agent/skills/project-docs--6f4714e4e7/SKILL.md`
- `home/sam/.agents/skills/project-docs`
- `home/sam/.agents/skills/project-docs/SKILL.md`
- `etc/profiles/per-user/sam/bin/mmdc`
- `docs/diagrams/architecture.png`
- `v1/chat/completions`
- `docs.litellm.ai/docs/providers`
- `ghcr.io/chopratejas/headroom`
- `etc/nixos/hosts/sam-thinkpad/configuration.nix`
## Evidence
- Confidence: 84%
- Reason: Update component/repository context with detailed discovered structure and configuration
## Related learned memories <!-- same-turn-2026-11-11 08:20:35 -->
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-has-2026-11-11-08-20-35|Rich discovery: has 2026-11-11 08:20:35]]
- context: [[packs/paperclip-harness/20-context/paperclip-harness|has]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|has repository structure and configuration patterns]]

View File

@@ -3533,3 +3533,91 @@ Say go on 1 and I will run the project-docs pass before anything else.
- session: [[packs/paperclip-harness/80-sessions/paperclip-harness-headroom-integration-machine-drift-cancel-|paperclip-harness: headroom integration, machine drift, cancel feature, office workflow]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-itself-2026-11-11-08-00-32|Rich discovery: itself 2026-11-11 08:00:32]]
- context: [[packs/paperclip-harness/20-context/tmp|itself]]
---
## Update (2026-11-11 08:20:35)
## Structural/configuration observations (2026-11-11 08:20:35)
You were right to push back on Headroom, and I had the reason wrong. Here is what the tests actually show.
## Headroom: corrected, with evidence
```
router POST /v1/chat/completions deepseek/deepseek-v4-flash → 200, SSE, "ok" in 1.1 s
headroom POST /v1/chat/completions deepseek/deepseek-v4-flash → 502 {"code":"proxy_error"}
```
`docker logs headroom` shows LiteLLM repeating *"Provider List: https://docs.litellm.ai/docs/providers"*. Headroom runs from `ghcr.io/chopratejas/headroom:latest` and is built on **LiteLLM**, which does not recognise this router's model ids (`deepseek/deepseek-v4-flash`, `auto/best-fast`), so it never makes the call. The same request to the router succeeds, so key, model and request shape are all fine.
So it is **not** blocked by Anthropic and **not** by a key. It is blocked by LiteLLM not knowing your router's models. To use it as a provider, headroom's own model list must define them, for example `openai/deepseek-v4-flash` with `api_base: http://192.168.20.13:20129/v1` and your key. That is a change inside that container, not in our software. My earlier "needs an Anthropic credential" was wrong, and the docs are corrected.
## headroom-ai installed, and tested
Installed for Pi on **`.13`, `.27` and `.51`**, and the library resolves and calls the service:
```
tokensBefore: 2809 tokensAfter: 2809 message length 12800 of 12800
```
No saving there because headroom protects a single long user message — the tool works, the test case was just one it deliberately leaves alone. So `compress_for_agent` can now load; giving it to one agent is `space` in `Agents>agents` → extensions.
## Machines
| | `.13` | `.27` | `.51` |
|---|---|---|---|
| Go | 1.26.5 | 1.26.2 | **added to config, needs a rebuild** |
| headroom-ai for Pi | installed | installed | installed |
| Nerd Fonts | 384 | 98 | 98 |
| Pi | 0.82.1 | 0.82.1 | 0.87.1 |
On `.51` I added `go gopls` to `/etc/nixos/hosts/sam-thinkpad/configuration.nix` (backup at `.bak-go`), and `nix build --dry-run` evaluates cleanly. You rebuild with:
```
sudo nixos-rebuild switch --flake /etc/nixos#sam-thinkpad
```
`.13` and `.27` are behind `.51` on Pi (0.82.1 vs 0.87.1). That is a flake bump, and I would do it with you rather than alone.
## Documentation: first piece done
`docs/architecture.mmd` and `docs/diagrams/architecture.png` — one diagram showing the person, the eight TUIOS panes, the `bin/` commands, Paperclip with its database and Pi agents, and where the work physically happens (worktrees, Pi sessions, skills, git). Linked from the README top. Committed as `28993d0`.
The project-docs skill prescribes five layers, and I need one answer from you before writing into them:
1. **Gitea** — this repo has no remote. Should I create a Gitea repo and push?
2. **Obsidian** — a note in `010 inbox` on `.27` (the skill says never to choose its folder; `obsidian-sorter` proposes and you approve).
3. **Mermaid + Archify** — the diagram is written and rendered; publishing the interactive map to `maps.lab.audasmedia.com.au/paperclip-harness/` is the remaining step.
4. **Vikunja** — a board for human task tracking, or the JSON in `docs/`.
5. **Outline** — the AI-context collection (`00-index`, `01-system-overview`, `02-config-and-env`, `03-code-map`, `04-agent-runbook`).
Say which of 1, 2, 4, 5 you want (3 is half done), and I will write them in that order.
## Source paths observed
- `nix/store/kh6c296264jngs70d8ibqk7zglyvd533-user-units.drv`
- `nix/store/qv508bjxrbsnn6hj8lvrlb38x3j631lx-etc.drv`
- `nix/store/v8rgpfj7ighpjbjmz184djg11m20c7bm-activate.drv`
- `nix/store/jarpr30smi73c6wwjlrigd98dmhj7vnl-nixos-system-sam-thinkpad-26.11.20260926.e158d9e.drv`
- `home/sam/.pi/agent/skills/project-docs--6f4714e4e7/SKILL.md`
- `home/sam/.agents/skills/project-docs`
- `home/sam/.agents/skills/project-docs/SKILL.md`
- `etc/profiles/per-user/sam/bin/mmdc`
- `docs/diagrams/architecture.png`
- `v1/chat/completions`
- `docs.litellm.ai/docs/providers`
- `ghcr.io/chopratejas/headroom`
- `etc/nixos/hosts/sam-thinkpad/configuration.nix`
## Evidence
- Confidence: 82%
- Reason: Captured factual repo structure/configuration patterns from rich discovery
## Related learned memories <!-- same-turn-2026-11-11 08:20:35 -->
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-has-2026-11-11-08-20-35|Rich discovery: has 2026-11-11 08:20:35]]
- context: [[packs/paperclip-harness/20-context/paperclip-harness|has]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|has repository structure and configuration patterns]]

View File

@@ -0,0 +1,107 @@
---
type: session
id: session.paperclip-harness.rich-discovery-has-2026-11-11-08-20-35
title: Rich discovery: has 2026-11-11 08:20:35
status: active
source_of_truth: false
freshness: current
last_reviewed: 2026-11-11
tags:
- pack/paperclip-harness
- agent-memory/session
- autolearn
- rich-discovery
- repo/has
---
# Rich discovery: has 2026-11-11 08:20:35
Sanitized rich discovery snapshot captured automatically from the completed turn.
## Source paths observed
- `nix/store/kh6c296264jngs70d8ibqk7zglyvd533-user-units.drv`
- `nix/store/qv508bjxrbsnn6hj8lvrlb38x3j631lx-etc.drv`
- `nix/store/v8rgpfj7ighpjbjmz184djg11m20c7bm-activate.drv`
- `nix/store/jarpr30smi73c6wwjlrigd98dmhj7vnl-nixos-system-sam-thinkpad-26.11.20260926.e158d9e.drv`
- `home/sam/.pi/agent/skills/project-docs--6f4714e4e7/SKILL.md`
- `home/sam/.agents/skills/project-docs`
- `home/sam/.agents/skills/project-docs/SKILL.md`
- `etc/profiles/per-user/sam/bin/mmdc`
- `docs/diagrams/architecture.png`
- `v1/chat/completions`
- `docs.litellm.ai/docs/providers`
- `ghcr.io/chopratejas/headroom`
- `etc/nixos/hosts/sam-thinkpad/configuration.nix`
## Final answer snapshot
You were right to push back on Headroom, and I had the reason wrong. Here is what the tests actually show.
## Headroom: corrected, with evidence
```
router POST /v1/chat/completions deepseek/deepseek-v4-flash → 200, SSE, "ok" in 1.1 s
headroom POST /v1/chat/completions deepseek/deepseek-v4-flash → 502 {"code":"proxy_error"}
```
`docker logs headroom` shows LiteLLM repeating *"Provider List: https://docs.litellm.ai/docs/providers"*. Headroom runs from `ghcr.io/chopratejas/headroom:latest` and is built on **LiteLLM**, which does not recognise this router's model ids (`deepseek/deepseek-v4-flash`, `auto/best-fast`), so it never makes the call. The same request to the router succeeds, so key, model and request shape are all fine.
So it is **not** blocked by Anthropic and **not** by a key. It is blocked by LiteLLM not knowing your router's models. To use it as a provider, headroom's own model list must define them, for example `openai/deepseek-v4-flash` with `api_base: http://192.168.20.13:20129/v1` and your key. That is a change inside that container, not in our software. My earlier "needs an Anthropic credential" was wrong, and the docs are corrected.
## headroom-ai installed, and tested
Installed for Pi on **`.13`, `.27` and `.51`**, and the library resolves and calls the service:
```
tokensBefore: 2809 tokensAfter: 2809 message length 12800 of 12800
```
No saving there because headroom protects a single long user message — the tool works, the test case was just one it deliberately leaves alone. So `compress_for_agent` can now load; giving it to one agent is `space` in `Agents>agents` → extensions.
## Machines
| | `.13` | `.27` | `.51` |
|---|---|---|---|
| Go | 1.26.5 | 1.26.2 | **added to config, needs a rebuild** |
| headroom-ai for Pi | installed | installed | installed |
| Nerd Fonts | 384 | 98 | 98 |
| Pi | 0.82.1 | 0.82.1 | 0.87.1 |
On `.51` I added `go gopls` to `/etc/nixos/hosts/sam-thinkpad/configuration.nix` (backup at `.bak-go`), and `nix build --dry-run` evaluates cleanly. You rebuild with:
```
sudo nixos-rebuild switch --flake /etc/nixos#sam-thinkpad
```
`.13` and `.27` are behind `.51` on Pi (0.82.1 vs 0.87.1). That is a flake bump, and I would do it with you rather than alone.
## Documentation: first piece done
`docs/architecture.mmd` and `docs/diagrams/architecture.png` — one diagram showing the person, the eight TUIOS panes, the `bin/` commands, Paperclip with its database and Pi agents, and where the work physically happens (worktrees, Pi sessions, skills, git). Linked from the README top. Committed as `28993d0`.
The project-docs skill prescribes five layers, and I need one answer from you before writing into them:
1. **Gitea** — this repo has no remote. Should I create a Gitea repo and push?
2. **Obsidian** — a note in `010 inbox` on `.27` (the skill says never to choose its folder; `obsidian-sorter` proposes and you approve).
3. **Mermaid + Archify** — the diagram is written and rendered; publishing the interactive map to `maps.lab.audasmedia.com.au/paperclip-harness/` is the remaining step.
4. **Vikunja** — a board for human task tracking, or the JSON in `docs/`.
5. **Outline** — the AI-context collection (`00-index`, `01-system-overview`, `02-config-and-env`, `03-code-map`, `04-agent-runbook`).
Say which of 1, 2, 4, 5 you want (3 is half done), and I will write them in that order.
## Evidence
- Confidence: 86%
- Reason: Preserve full sanitized discovery detail from a rich investigation turn
## Related
- [[packs/paperclip-harness/00-system/pi-agent/memory-manifest|Memory Manifest]]
## Related learned memories <!-- same-turn-2026-11-11 08:20:35 -->
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-has-2026-11-11-08-20-35|Rich discovery: has 2026-11-11 08:20:35]]
- context: [[packs/paperclip-harness/20-context/paperclip-harness|has]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|has repository structure and configuration patterns]]

217
README.md
View File

@@ -1,124 +1,117 @@
# Paperclip harness — start here
# Paperclip Harness
This is a new project. Nothing here runs yet. It exists so the third attempt starts from
a clean place, with the history of the first two attempts attached.
If you are an agent: read `AGENTS.md` first, then `HANDOVER.md`, then `docs/PLAN.md`.
If you are the person: read these in order:
1. `HANDOVER.md` — what we tried before, what worked, what failed, and why this is different.
2. `docs/PLAN.md` — the plan: the four screens, the milestones, what is Paperclip's job and what is ours.
3. `docs/PAPERCLIP-API-NOTES.md` — what we measured against your running Paperclip, with the endpoint and the response.
4. `CHECKLIST.md` — the exact steps for the next session, in order, with boxes to tick.
5. `docs/TUIOS-RUNBOOK.md` — TUIOS, not tmux: the three machines, starting a session, driving panes.
6. `docs/OPERATING-RULES.md` — the nine rules, including how a task is judged finished.
7. `docs/DOCMAP.md` — which document is authoritative for what. One home per document.
6. `docs/ENVIRONMENT-FACTS.md` — the ids, the installed tools, and the one step that is
still unproven.
**A terminal control room for an AI coding factory.** Paperclip runs the work — tasks,
blockers, agents, runs, cost and a git worktree per task. This is the surface a person uses to
see it, direct it, and decide what lands.
![architecture](docs/diagrams/architecture.png)
## The one-line version
Eight workspaces in TUIOS, one Go program in each, and a small set of commands for the parts
that should not be a keystroke (merge, review, adopt a folder). No web UI, no database of our
own, no second copy of any fact.
Paperclip already owns tasks, blockers, comments, approvals, runs, cost and git
worktrees. We are building one small Go terminal program with four screens on top of it.
Nothing else.
---
## What you need installed (all present on .13 today)
## What it does
- Paperclip server running locally on `http://127.0.0.1:3100` (it is; 685 endpoints).
- `PAPERCLIP_BOARD_KEY` in the environment — the **user** key. The terminal program uses
this one. An agent key cannot write outside a heartbeat run.
- Go toolchain — **now installed** (`go1.26.5`, from `nix profile`). The NixOS config change
that makes it permanent is staged in `/etc/nixos/configuration.nix` and needs one
`sudo nixos-rebuild switch`. See `docs/ENVIRONMENT-FACTS.md`.
- Pi, which is already the worker adapter on your Paperclip agent.
| Workspace | What it answers | What it shows |
|---|---|---|
| **Board** | what is the state of the work | tasks by group, the chosen task with its blockers and check, what needs a person |
| **Work** | what is happening and what changed | run timeline, the diff from the task's own worktree, review verdicts, the run's log, and a merge that asks before it acts |
| **Agents** | who is working, on what, for how much | agent roster with spend and budget, every run in the company, the run log, editable role/model/budget/heartbeat, per-agent skills and extensions |
| **Reply** | what was said and what I say back | the thread and a reply box that can also set the task's status |
| **New task** | what am I asking for | a five-field form, what each field means, and exactly the text the agent will receive |
| **Project** | which folder, which machine, what it costs | a dashboard (agents, tasks, money, run activity), costs as bars, the project's settings, adopted projects |
| **Repair** | is the layout sound | three-state health checks, the live TUIOS layout, the rebuild log, session cleanup |
| **Shell** | where am I | a prompt in the project folder, above a box naming every path that matters |
## Running the terminal program
Keys follow TUIOS's rules: `Tab` moves between panels, `↑↓` or `jk` move, `(` `)` switch tabs,
`R` rebuilds the layout, `?` lists the keys for the panel you are in. A bare `Esc` closes a box
and never quits.
```bash
bin/layout # open every screen as a TUIOS pane
bin/screen reply AUD-162 # or one screen
---
cd tui
go run . -screen tree -project spike-2026-11-10 # one screen in this terminal
go run . -screen tree -project spike-2026-11-10 -dump # the same data as plain text
## The design decisions that matter
**One owner per fact.** Tasks, blockers, comments, approvals, runs, cost and worktrees belong to
Paperclip. The interface reads them every time and stores none of them. Two screens cannot
disagree because there is only one record.
**One project is one folder on one machine.** That is the only thing we keep: a small file in
`<folder>/.harness/harness.toml` naming the session, the machine and the task being watched.
Everything else is Paperclip's.
**Choosing a task is one act.** `Enter` on the board writes the choice into that file and every
other workspace follows within a second. No message bus, no second state to keep in sync.
**A task is finished when the agent says so.** A review stage or `ocr` can refuse the change. A
project's `check.sh` is a regression check at merge time — the same job a CI pipeline does — not
the definition of done.
**Merging is a decision, so it asks.** `m` names the branch, the base branch and the checks, and
waits for `y`. It takes a lock, rebases, runs the checks, runs the review, merges, then re-runs
the checks on the base branch and rolls back if they fail.
**TUIOS owns the keyboard.** `h j k l z n` and `[ ] tab , . = ;` and the digits are its. The
program navigates with arrows, `jk`, `(` `)`, `Space` and `Enter`, and keeps `Esc` free.
**Nothing hardcodes a size.** Every pane re-asks the terminal for its size on each refresh,
because a window manager can re-tile a pane without the program hearing about it.
---
## Measured, not asserted
| Claim | Measurement |
|---|---|
| An assignment wakes the agent | wake recorded 46 ms after the assignment, run started 0.1 s later, task done in 28 s |
| Cost is readable per task | `cost-summary`: 1 cent, 101,002 input tokens, 1,515 output tokens, one run |
| Blockers are real answers | `diagnostics/blockers` returns `unresolvedBlockerCount: 1` — and the task **list** never carries it, so the tree asks per task |
| Worktrees are Paperclip's | branch `AUD-160-…` at `.paperclip/worktrees/…`, cut from `main` |
| A review can refuse a merge | `ocr` found `rm -rf "$HOME/tmp"` deleting `/tmp` when `HOME` is empty; the merge was refused and the file never landed |
| A task can have several runs | `AUD-166`: `assignment`, then `automation` — Paperclip's corrective wake |
| Per-agent skills work | adding one skill changed that agent's list and no other |
| A new project can be adopted in one command | `bin/office` created the session, wrote the project file and built all eight panes |
---
## Technology
- **Go** with Bubble Tea, Lipgloss, Bubbles and BubbleZone; one binary, one program per pane.
- **TUIOS** for sessions, workspaces and panes, including the control-protocol verbs used to
create sessions and switch between them.
- **Paperclip** as the control plane: 685 API endpoints, isolated git worktrees per task, Pi as
the agent runtime.
- **ocr** for code review over the diff; **Lazygit**, **Hunk**, **Yazi**, **Neovim**, **fzf** and
a shell open as tool panes on demand instead of being rebuilt.
- **Mouse-1** for one narrow job — labelling a failed run with one of four next actions.
---
## What this demonstrates
- **Integration under real constraints**: a dozen independent systems (TUIOS, Paperclip, git
worktrees, Pi agents, ocr, skills) joined so that each keeps its own job.
- **Single-source-of-truth discipline**: no cached facts, no second task list, no guessed state —
and the API was measured until the traps were known (blockers absent from list endpoints,
cross-issue writes refused outside a run).
- **Failure-aware design**: a merge that asks, a review that can refuse, a lock so two merges
cannot overlap, a rollback when post-merge checks fail, and health checks that have three
states because "not run" is not "pass".
- **Terminal interface engineering**: resize handling, a focus model, tabs, overlays that wrap
instead of clipping, and keys chosen around another program's keymap.
- **Evidence-based reporting**: every claim in the docs names the command that showed it, and the
unproven ones are marked unproven.
---
## Repository
```
bin/ commands: office, board, merge, review, triage, project-reset
tui/ the Go program: one binary, eight screens
docs/ the plan, the measurements, the runbook, the test plan
docs/architecture.mmd the system diagram, rendered to docs/diagrams/
```
The screens live in the session named `paperclip-harness`, one per workspace. How that is
built and repaired is in `docs/TUIOS-RUNBOOK.md`.
The project can be an id or its url key. Keys inside the program: arrows or Tab and
Shift-Tab move, `r` re-reads from Paperclip, `q` quits. A bare Esc is left free, because in
TUIOS it has to close a box.
## The six workspaces
Written the way we talk about them: **Workspace>pane**. `Board>board` means the board
program running in the Board workspace.
| Workspace>pane | shows | keys |
|---|---|---|
| Shell>shell | a prompt in the project folder, with a box saying where the project's files, worktrees and Pi sessions are | — |
| Board>board | tasks by group · the chosen task · needs you | ↑↓ j k · enter · a · u · / · t (tools) · tab |
| Work>work | runs · change · facts · review · log · merge | [ ] tab · n p (task) · o (pick task) · ↑↓ j k · enter (open a run) · m (merge, asks first) · t (tools) |
| Reply>reply | the task · the thread · the reply box | enter · s · esc |
| New task>new | the form · what a task needs · what will be sent | tab · enter · ctrl+n |
| Project>project | overview · facts · costs · settings | [ ] tab · ↑↓ j k |
| Repair>repair | health · layout · rebuild log | [ ] tab · ↑↓ j k · R · B |
| Agents>agents | roster · runs · log · settings | [ ] tab · ↑↓ j k · enter · p P w · A |
Choosing a task on the board and pressing Enter writes it into the project's
`.harness/harness.toml`, and every other workspace follows within a second.
### Tool panes
`t` in `Board>board` or `Work>work` opens a chooser: shell, Lazygit, Hunk, Yazi, Neovim,
fzf, ocr. Note that TUIOS also binds `t` in **window management mode** (toggle tiling, new
window); inside the program the pane must be in terminal mode for `t` to arrive, which is
the normal state while you are typing in it. The tool opens as a pane beside the one you are in, in the same workspace, and
`esc` closes the chooser. Quitting the tool (its own key) closes its pane. Nothing is added
to the layout, so the eight workspaces stay as they are.
### Refresh and rebuild
- **`r`** — read the data again in this panel. Nothing closes, nothing moves, the
layout is untouched. Use it when the numbers look stale.
- **`B`** — on the Repair screen only: add whatever panes are missing without
closing any, so it is safe to press from inside a pane.
- **`?`** — the keys for the panel you are in, as an overlay.
- **`/`** — filter the task list by identifier, title or assignee name.
- **`u`** — unblock a task whose blocker has finished but which still says blocked.
- **`R`** — rebuild everything: `bin/board --replace` closes each pane the layout
owns and builds all seven again, in order. It runs detached in its own session,
because the panel you pressed it in is one of the panes being replaced; the
output is written to `/tmp/paperclip-harness-rebuild.log`, and the Repair
workspace shows that log on its third tab.
`R` is on every screen except the new-task form, where letters are text.
## How an interface change is tested
Not in a plain terminal, and not in tmux. TUIOS owns part of the keyboard and forwards
clicks relative to the pane, so the check is a real TUIOS pane read back with
`capture-pane`. The commands are in `docs/TUIOS-RUNBOOK.md`, which is the one place they
live.
## The commands
| command | what it does |
|---|---|
| `bin/office <folder> [--project X] [--session Y]` | adopt a folder: write `.harness/harness.toml`, build its pages |
| `bin/board [--folder DIR] [--replace]` | build or repair the pages; run twice and nothing is duplicated |
| `bin/project-reset <folder> [--dry-run] [--yes]` | close the pages, remove the worktrees and branches; keep the folder and every Paperclip record |
| `bin/merge <task> [--check]` | rebase, verify, review with `ocr`, merge; a refusal is a decision for the person |
| `bin/review <task> [--post]` | the same review on its own |
| `bin/screen <screen> [task or project]` | open one page by name |
## Rules for this project
- No interface work before a real task has run end to end.
- Paperclip owns the facts. We never keep a second copy of a task, a blocker or a cost.
- Every claim in a document names the command that showed it.
- Nothing is copied from the old project except documents.
Start with `HANDOVER.md`, then `docs/WORKSPACES.md`, then `docs/PLAN-INTERFACE.md`.

26
docs/outline/00-index.md Normal file
View File

@@ -0,0 +1,26 @@
# Index
What is in this collection, and what each document is for. Written in Simplified Technical
English: short sentences, one idea each, no metaphor.
| Document | Read it when |
|---|---|
| `01-system-overview.md` | you need to know what the system is and how the parts fit |
| `02-config-and-env.md` | you need to run it, or find a setting, a path or a key |
| `03-code-map.md` | you need to change the code and want to know which file does what |
| `04-agent-runbook.md` | an agent is picking up this project and needs the rules and the traps |
Outside this collection:
| File | What it is |
|---|---|
| `AGENTS.md` | the first file an agent reads |
| `HANDOVER.md` | where the project is now, and why it is shaped this way |
| `docs/PLAN-INTERFACE.md` | the plan, and the measurements behind each decision |
| `docs/WORKSPACES.md` | every workspace and pane, with its status |
| `docs/RUNS-AND-MERGE.md` | what a task, a run and a merge are |
| `docs/TEST-PLAN.md` | every step of a manual test, with the keys |
| `docs/SESSIONS.md` | TUIOS sessions, Pi conversations, cleanup |
| `docs/PAPERCLIP-API-NOTES.md` | what the API actually returned |
| `docs/ENVIRONMENT-FACTS.md` | ids, machines, toolchain, fonts |
| `docs/NEXT.md` | what is left to build, and what is unproven |

View File

@@ -0,0 +1,45 @@
# System overview
## What it is
Paperclip Harness is a terminal interface over Paperclip. Paperclip is a control plane. It keeps
tasks, blockers, comments, approvals, runs, cost and a git worktree for each task. This project
shows that work in a terminal, inside TUIOS, and adds the few actions a person needs.
## The parts
- **Paperclip** on `http://127.0.0.1:3100`. It owns every fact. It runs Pi agents.
- **TUIOS**. It owns sessions, workspaces, panes and part of the keyboard.
- **The Go program** in `tui/`. One binary. Each pane runs one screen.
- **Commands** in `bin/`. They do the work that should not be a keystroke: adopt a folder, build
panes, merge one task, review one task, ask Mouse-1 one question.
## The eight workspaces
| Workspace | Purpose |
|---|---|
| Shell | a prompt in the project folder, with the paths printed above it |
| Board | the state of the work, and what needs a person |
| Work | runs, diff, facts, review, run log, merge |
| Agents | who is working, on what, for how much; and their settings, skills, extensions |
| Reply | the task thread and a reply box |
| New task | the form that creates a task |
| Project | dashboard, costs, settings, adopted projects |
| Repair | health checks, live layout, rebuild log, session cleanup |
## The data flow
1. A person creates a task in `New task`, or one already exists in Paperclip.
2. The person assigns it on `Board`. Paperclip wakes the agent.
3. The agent works in its own git worktree, on its own branch.
4. The agent comments and sets the status.
5. The person reads the run log, the diff and the review.
6. The person merges. `bin/merge` rebases, checks, reviews, merges, and checks again.
## What the project stores
One file per project: `<folder>/.harness/harness.toml`. It holds the session name, the machine,
the Paperclip project id, and the task being watched. It holds no task data.
A registry at `~/.config/paperclip-harness/projects.toml` lists adopted projects, so a person can
see which folder lives where.

View File

@@ -0,0 +1,58 @@
# Configuration and environment
## Required
| Name | Where | What it is |
|---|---|---|
| `PAPERCLIP_BOARD_KEY` | `~/.config/environment.d/10-secrets.conf` | the person's key. All writes use it. |
| `PAPERCLIP_API_KEY` | the same file | the agent key. Use it for reads only. Writes are refused outside a run. |
| `MOUSE_API_KEY` | the same file | the Mouse-1 API key |
| `GITEA_TOKEN` | the same file | used once, to create and push the repository |
Never print a key. Never commit a key. Never put a key in a prompt.
## The project file
`<folder>/.harness/harness.toml`:
```toml
session = "paperclip-harness"
watching = "AUD-171"
[paperclip]
company = "d4921013-…"
project = "17adbb47-…"
[machine]
host = "nixos-desktop"
folder = "/tmp/pc-sandbox-2026-11-10"
```
`bin/office <folder>` writes it and also writes `.harness/check.sh` and `.harness/NOTES.md` when
they are missing. It never overwrites an existing file.
## Paths that matter
| What | Where |
|---|---|
| task worktrees | `<folder>/.paperclip/worktrees/<branch>` |
| Pi conversations | `~/.pi/paperclips/<timestamp>-<agentId>.jsonl` |
| Pi skills (installed by Paperclip) | `~/.pi/agent/skills/` |
| the person's skills | `~/.agents/skills/` |
| Paperclip data | `~/.paperclip/instances/default/` |
| merge log | `/tmp/paperclip-harness-merge.log` |
| rebuild log | `/tmp/paperclip-harness-rebuild.log` |
## Instance settings that change behaviour
- `enableIsolatedWorkspaces` and `enableWorktreeRunExecution` must be true, or no task gets a
worktree. `GET /api/instance/settings/experimental` shows them.
- `enableIsolatedWorkspacesByDefault` is left off. Only projects that ask for a worktree get one.
## Machines, measured 2026-11-11
| | `.13` | `.27` | `.51` |
|---|---|---|---|
| Go | 1.26.5 | 1.26.2 | installed in config, needs a rebuild |
| Pi | 0.82.1 | 0.82.1 | 0.87.1 |
| TUIOS | 0.12.1 | 0.12.1 | 0.12.1 |

View File

@@ -0,0 +1,46 @@
# Code map
## The binary
`tui/` builds one binary. `main.go` reads the flags and starts one screen.
| File | Does |
|---|---|
| `main.go` | flags, palette, which screen to start |
| `model.go` | the task tree screen and the shared row loader |
| `board.go` | `Board`: tasks, chosen task, needs you |
| `work.go` | `Work`: runs, change, facts, review, log, merge |
| `agents.go` | `Agents`: roster, runs, log, settings, skills, extensions |
| `reply.go` | `Reply`: thread and reply box |
| `newtask.go` | `New task`: the form, guidance, preview |
| `project.go` | `Project`: overview, facts, costs, settings, projects |
| `repair.go` | `Repair`: health, layout, log, cleanup |
| `frame.go` | the panel frame, tabs, hints, overlays, wrapping |
| `theme.go` | the palette and the icon set |
| `toolpane.go` | opening a tool as a pane, and finding the current workspace |
| `picker.go` | skills and extensions for one agent |
| `rebuild.go` | detached rebuild, merge and review, and their logs |
`tui/paperclip/client.go` is the whole API client. It holds no state.
## The commands
| File | Does |
|---|---|
| `bin/office` | adopt a folder, create its session, build its panes |
| `bin/board` | build or repair the panes, by name, in order |
| `bin/merge` | rebase, check, review, merge, re-check, roll back on failure |
| `bin/review` | the review alone |
| `bin/triage` | ask Mouse-1 one four-option question |
| `bin/project-reset` | close panes, remove worktrees and branches, keep the folder |
| `bin/shell-banner` | the box printed at the top of `Shell` |
| `bin/lib/tuios.py` | sessions, workspaces, panes: claim by name, never by number |
| `bin/lib/harness.py` | API, git, ocr, and the tool-path fix |
| `bin/lib/project.py` | the project file and the registry |
## The rules the code keeps
- No network or git call inside an update or view function. They run in commands.
- No hardcoded sizes. The size comes from the terminal on every refresh.
- One click-zone manager, created once, wrapping the whole view.
- Every panel line is exactly the width asked for. `tui/frame_test.go` fails if it is not.

View File

@@ -0,0 +1,45 @@
# Agent runbook
Read this before you change anything.
## First
1. Read `AGENTS.md`.
2. Read `HANDOVER.md`.
3. Run `tuios ls` and find the session called `paperclip-harness`.
4. In a pane, run `Repair>repair`. Every check must pass. If it does not, fix that first.
## Build and restart
```sh
cd tui && go build -o ../bin/harness .
```
Then press `R` in `Repair>repair`. Do not start a second copy of a panel: `bin/board` adopts the
pane that is already there.
## Rules that are not preferences
- Writes use `PAPERCLIP_BOARD_KEY`. The agent key is refused outside a run, and that refusal is
correct.
- Read blockers from `/api/issues/{id}/diagnostics/blockers`. The task list does not carry them.
- Read a worktree path from a single-task read. The task list does not carry it either.
- Never store a fact Paperclip owns.
- A comment on an assigned task wakes its agent. Tool verdicts hand the task back to the person
first.
- TUIOS keeps `h j k l z n` and also `[ ] Tab , . = ;` and the digits. Use arrows, `jk`, `(` `)`,
`Space`, `Enter`. Keep `Esc` free.
## Traps, measured
- A pane started by TUIOS has a smaller `PATH`. `bin/lib/harness.py` and `toolpane.go` add the
usual directories for that reason.
- TUIOS can re-tile a pane without the program hearing about it. Re-ask for the size.
- Closing the last pane deletes a workspace and renumbers the rest. Resolve workspaces by name.
- `switch-session` is refused when the call comes from a pane. A program cannot move the person's
client.
## Reporting
Say what you ran and what came back. If something is unproven, say it is unproven. A dry run is
not a test.