Showcase README; Outline collection for agents; repository created on Gitea
This commit is contained in:
@@ -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]]
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -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
217
README.md
@@ -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.
|
||||
|
||||

|
||||
|
||||
## 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
26
docs/outline/00-index.md
Normal 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 |
|
||||
45
docs/outline/01-system-overview.md
Normal file
45
docs/outline/01-system-overview.md
Normal 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.
|
||||
58
docs/outline/02-config-and-env.md
Normal file
58
docs/outline/02-config-and-env.md
Normal 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 |
|
||||
46
docs/outline/03-code-map.md
Normal file
46
docs/outline/03-code-map.md
Normal 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.
|
||||
45
docs/outline/04-agent-runbook.md
Normal file
45
docs/outline/04-agent-runbook.md
Normal 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.
|
||||
Reference in New Issue
Block a user