Project>project overview from the dashboard endpoint; tools chooser drawn in Board>board; docs for Shell and t

This commit is contained in:
Sam
2026-11-10 21:48:03 +11:00
parent 3d31243317
commit 3e90ca82ab
14 changed files with 1225 additions and 9 deletions

View File

@@ -309,3 +309,133 @@ Committed as `7f18c54`. Say which item you want first and I will build only that
- session: [[packs/paperclip-harness/80-sessions/paperclip-harness-reverted-pane-split-interface-gap-discover|Paperclip-harness — reverted pane split, interface gap discovery, and PLAN-INTERFACE roadmap]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-home-2026-11-10-05-41-48|Rich discovery: home 2026-11-10 05:41:48]]
- context: [[packs/paperclip-harness/20-context/home|home]]
---
## Update (2026-11-10 10:01:16)
## Rich discovery update (2026-11-10 10:01:16)
Explored all of it. Recorded in `docs/PLAN-INTERFACE.md`; the short version:
## Skills per agent — Paperclip already models it
`GET /api/agents/{id}/skills` returns a desired set, a managed set and a state per skill. On `Builder` today:
```
desired: ["paperclipai/paperclip/paperclip"]
company/<id>/obsidian-cli desired: false managed: true state: "stale"
```
`POST /api/agents/{id}/skills/sync` takes `add`, `remove` or **`replace`** — `replace` is exactly "this agent gets these and nothing else", which is how a sub-agent's context stays small. There is also a company skill catalog, versions, audit, and `GET/PUT /api/companies/{id}/skill-policy` with an `evaluate` call.
Proposal: two rows in `Agents>agents` settings — **skills** (the desired set, read-only first, add/remove later) and **skill source**. A full browser is a later screen, not a panel. Also: `obsidian-cli` sitting `stale` on Builder is worth fixing.
## Memory — three different things
| | state here | what it is |
|---|---|---|
| **engram** | installed, v1.16.1, MCP mode, **not** registered in `~/.pi/agent/mcp.json` (only `codebase-memory`, `graphify-vault`) | persistent memory |
| **headroom** | running, v0.24.0, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression on | a prompt-compression proxy, not a store |
| **pi memctx** | in use now | injects notes into a prompt |
They are complementary. Paperclip's only per-agent lever is `adapterConfig` and `runtimeConfig`, so memory is set per agent by pointing that agent at the proxy or store it should use. Proposal: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, and nothing more until one agent has run both ways and been measured.
## MOUSE-1
`MOUSE_API_KEY` is set (checked the name only, never the value). `JEV_API_KEY` too. No `mouse`, `mouse1`, `jev` or `switch` binary is installed.
There **are** notes, and they are good ones — in the old project's plan documents:
> MOUSE-1 is *"triage only: label, score, route, escalate. Never a gate, never a permit"* — explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error makes a green run a lie.
I would adopt that policy unchanged. Its place, if added: ordering `Board>board`'s needs-you list, or pre-sorting findings in `Work>review`. Never the merge, never an approval.
## Lazygit
Already wired: `t` in `Board>board` or `Work>work`, choose Lazygit. Verified opening in the right workspace and closing with `q`.
## The old `office` — and what ours lacks
The previous `office` did four things: remember the host; run `new-project` to write the scaffold (`settings.toml`, a file per role, `verify.sh`, the per-screen notes) writing **only what is missing**; refuse if the session does not exist and print the exact `tuios new` line; then build the pages.
Ours does the host, the refusal and the pages — but **no scaffold**. No per-role files, no `verify.sh`, no page notes. That is the cheapest real gap in the whole plan.
## Dashboard — the API answers it in one call
`GET /api/companies/{id}/dashboard`, 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, utilization 0}
runActivity [14 entries]
```
Proposal: a `Project>overview` panel with those blocks and a sparkline drawn in Go with `tuios.dev/plot`, rather than embedding the web dashboard in a pane.
## Not doing
Artifacts — dropped as instructed.
I am ready for the task you are about to deliver; nothing in the tree is half-changed, the eight workspaces are running, and the last commit is `3d31243`.
## Source paths observed
- `home/sam/.local/bin/engram`
- `home/sam/.config/environment.d/10-secrets.conf`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/80-sessions/paperclip-harness-reverted-pane-split-interface-gap-discover.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/80-sessions/rich-discovery-tmp-2026-11-10-07-35-38.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/80-sessions/rich-discovery-home-2026-11-10-05-41-48.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/20-context/home.md`
- `github.com/Gentleman-Programming/engram/cmd/engram`
- `api/skills/available`
- `api/skills/catalog`
- `api/skills/index`
- `paperclipai/paperclip/paperclip`
- `company/d4921013-e5da-4d88-8016-57d5746e2d03/obsidian-cli`
- `home/sam/.paperclip/instances/default/skills/d4921013-e5da-4d88-8016-57d5746e2d03/obsidian-cli`
- `home/sam/.pi/agent/skills/obsidian-`
- `dir/.harness/host`
- `home/sam/paseo/projects/tuios_coding_harness/plan/82-control-room.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/83-interface.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/80-forked-plan.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/91-paperclip-or-oma.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/50-open-work.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/skills/graphify/SKILL.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/skills/system-architect/SKILL.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/extensions/pi-graphify/skills/graphify/SKILL.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/node_modules`
- `google/genai/dist/node/index.cjs`
- `google/genai/dist/node/node.d.ts`
- `home/sam/.config/systemd/user/lan-mouse.service`
- `home/sam/.config/lan-mouse`
- `home/sam/.config/lan-mouse/lan-mouse.pem`
- `home/sam/.cache/lan-mouse`
- `home/sam/.local/bin/lan-mouse-011`
- `home/sam/.pi/agent/auth.json`
- `home/sam/.pi/agent/mcp-cache.json`
- `home/sam/.pi/agent/mcp.json`
- `home/sam/.pi/agent/models.json`
- `home/sam/.pi/agent/models-store.json`
- `home/sam/.pi/agent/settings.json`
- `home/sam/.pi/agent/trust.json`
- `home/sam/.local/bin/codebase-memory-mcp`
## Evidence
- Confidence: 84%
- Reason: Update component/repository context with detailed discovered structure and configuration
## Related learned memories <!-- same-turn-2026-11-10 10:01:16 -->
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Paperclip per-agent skills state and sync semantics]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|Adopt an existing folder into the harness with `office` (and its known scaffold gap)]]
- decision: [[packs/paperclip-harness/50-decisions/mouse-1-restricted-to-triage-never-a-gate-or-permit|MOUSE-1 restricted to triage; never a gate or permit]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Recorded interface plan for Paperclip + TUIOS harness in docs/PLAN-INTERFACE.md]]
- session: [[packs/paperclip-harness/80-sessions/paperclip-tuios-interface-discovery-skills-api-memory-stack-|Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold]]
- context: [[packs/paperclip-harness/20-context/paperclip-tuios-harness-sam-s-coding-harness-office-board-wo|Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-paperclipai-2026-11-10-10-01-16|Rich discovery: paperclipai 2026-11-10 10:01:16]]
- context: [[packs/paperclip-harness/20-context/home|paperclipai]]

View File

@@ -0,0 +1,51 @@
---
type: context
id: context.paperclip-harness.paperclip-tuios-harness-sam-s-coding-harness-office-board-wo
title: Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)
status: active
source_of_truth: false
freshness: current
last_reviewed: 2026-11-10
tags:
- pack/paperclip-harness
- agent-memory/context
- paperclip
- tuios
- harness
- architecture
- paths
---
# Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)
The user's coding harness is a TUIOS-based multi-screen workspace over the Paperclip API, with old source in /home/sam/paseo/projects/tuios_coding_harness (scripts `office`, `new-project`, `board`; plan/ docs 50-open-work, 80-forked-plan, 82-control-room, 83-interface, 91-paperclip-or-oma).
Screens/proposals: Agents>agents (skills rows + skill source, memory row), Project>overview (dashboard summary + Go sparkline via tuios.dev/plot), Board>board (needs-you list, `t` → Lazygit), Work>work (review/findings, `t` → Lazygit).
`office <dir> --session <name>`: detects/remembers host in .harness/host, dry-run flag, refuses when the TUIOS session does not exist (non-interactive session creation impossible) and prints `tuios new <session>`; then invokes board to build pages. Old version additionally ran new-project to write scaffold only-what-is-missing; current version lacks this scaffold step (known gap). Attach: `tuios-gpui attach <session>` (graphical) or `tuios attach <session>`, remote via `tuios-gpui attach --host <host> <session>`.
Paperclip company id in this instance: d4921013-e5da-4d88-8016-57d5746e2d03; agent adapterType pi_local, mode persistent, skills materialized under /home/sam/.paperclip/instances/default/skills/<companyId>/ and targeted at /home/sam/.pi/agent/skills/. Per-agent config levers: adapterConfig, runtimeConfig. Paperclip state at discovery: 6 active agents, 8 open / 4 blocked / 147 done tasks, 0 pending approvals, month spend 11 cents.
Local MCP: codebase-memory and graphify-vault. Pi config repo: /home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config (skills graphify, system-architect; extension pi-graphify). Also present: ~/.config/systemd/user/lan-mouse.service, /home/sam/.local/bin/codebase-memory-mcp, relay-graphify-mcp; ~/.pi/agent/{auth,mcp,models,settings,trust}.json.
Artifacts feature: dropped per instruction. Last commit at time of planning: 3d31243.
## Evidence
- Confidence: 85%
- Reason: Durable component overview with paths, environment split, screens, and integration points for the existing harness.
## Related
- [[packs/paperclip-harness/00-system/pi-agent/memory-manifest|Memory Manifest]]
## Related learned memories <!-- same-turn-2026-11-10 10:01:16 -->
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Paperclip per-agent skills state and sync semantics]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|Adopt an existing folder into the harness with `office` (and its known scaffold gap)]]
- decision: [[packs/paperclip-harness/50-decisions/mouse-1-restricted-to-triage-never-a-gate-or-permit|MOUSE-1 restricted to triage; never a gate or permit]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Recorded interface plan for Paperclip + TUIOS harness in docs/PLAN-INTERFACE.md]]
- session: [[packs/paperclip-harness/80-sessions/paperclip-tuios-interface-discovery-skills-api-memory-stack-|Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold]]
- context: [[packs/paperclip-harness/20-context/paperclip-tuios-harness-sam-s-coding-harness-office-board-wo|Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-paperclipai-2026-11-10-10-01-16|Rich discovery: paperclipai 2026-11-10 10:01:16]]
- context: [[packs/paperclip-harness/20-context/home|paperclipai]]

View File

@@ -371,3 +371,92 @@ Also field-verified that per-agent settings PATCH merges into existing config (c
- context: [[packs/paperclip-harness/20-context/tmp|tmp]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|tmp deployment operations]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|tmp repository structure and configuration patterns]]
---
## Update (2026-11-10 10:01:16)
Deliverable: `docs/PLAN-INTERFACE.md` (commit `3d31243`) capturing the full interface plan: skills rows in Agents>agents (desired set + skill source, backed by existing /api/agents/{id}/skills + sync), memory row (engram/headroom/memctx), MOUSE-1 limited to triage, Project>overview panel built from /api/companies/{id}/dashboard with tuios.dev/plot sparkline, and adopting the old office scaffold (settings.toml, per-role file, verify.sh, per-screen notes) as the cheapest real gap. Lazygit confirmed already wired (`t` in Board>board / Work>work). Artifacts dropped. Validation: tree clean, eight workspaces running, no half-changes. Follow-ups: fix stale obsidian-cli on Builder; implement scaffold step in office; optionally register engram in mcp.json.
## Detailed deliverable from completed turn
Explored all of it. Recorded in `docs/PLAN-INTERFACE.md`; the short version:
## Skills per agent — Paperclip already models it
`GET /api/agents/{id}/skills` returns a desired set, a managed set and a state per skill. On `Builder` today:
```
desired: ["paperclipai/paperclip/paperclip"]
company/<id>/obsidian-cli desired: false managed: true state: "stale"
```
`POST /api/agents/{id}/skills/sync` takes `add`, `remove` or **`replace`** — `replace` is exactly "this agent gets these and nothing else", which is how a sub-agent's context stays small. There is also a company skill catalog, versions, audit, and `GET/PUT /api/companies/{id}/skill-policy` with an `evaluate` call.
Proposal: two rows in `Agents>agents` settings — **skills** (the desired set, read-only first, add/remove later) and **skill source**. A full browser is a later screen, not a panel. Also: `obsidian-cli` sitting `stale` on Builder is worth fixing.
## Memory — three different things
| | state here | what it is |
|---|---|---|
| **engram** | installed, v1.16.1, MCP mode, **not** registered in `~/.pi/agent/mcp.json` (only `codebase-memory`, `graphify-vault`) | persistent memory |
| **headroom** | running, v0.24.0, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression on | a prompt-compression proxy, not a store |
| **pi memctx** | in use now | injects notes into a prompt |
They are complementary. Paperclip's only per-agent lever is `adapterConfig` and `runtimeConfig`, so memory is set per agent by pointing that agent at the proxy or store it should use. Proposal: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, and nothing more until one agent has run both ways and been measured.
## MOUSE-1
`MOUSE_API_KEY` is set (checked the name only, never the value). `JEV_API_KEY` too. No `mouse`, `mouse1`, `jev` or `switch` binary is installed.
There **are** notes, and they are good ones — in the old project's plan documents:
> MOUSE-1 is *"triage only: label, score, route, escalate. Never a gate, never a permit"* — explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error makes a green run a lie.
I would adopt that policy unchanged. Its place, if added: ordering `Board>board`'s needs-you list, or pre-sorting findings in `Work>review`. Never the merge, never an approval.
## Lazygit
Already wired: `t` in `Board>board` or `Work>work`, choose Lazygit. Verified opening in the right workspace and closing with `q`.
## The old `office` — and what ours lacks
The previous `office` did four things: remember the host; run `new-project` to write the scaffold (`settings.toml`, a file per role, `verify.sh`, the per-screen notes) writing **only what is missing**; refuse if the session does not exist and print the exact `tuios new` line; then build the pages.
Ours does the host, the refusal and the pages — but **no scaffold**. No per-role files, no `verify.sh`, no page notes. That is the cheapest real gap in the whole plan.
## Dashboard — the API answers it in one call
`GET /api/companies/{id}/dashboard`, 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, utilization 0}
runActivity [14 entries]
```
Proposal: a `Project>overview` panel with those blocks and a sparkline drawn in Go with `tuios.dev/plot`, rather than embedding the web dashboard in a pane.
## Not doing
Artifacts — dropped as instructed.
I am ready for the task you are about to deliver; nothing in the tree is half-changed, the eight workspaces are running, and the last commit is `3d31243`.
## Evidence
- Confidence: 90%
- Reason: Completed deliverable with artifact path, commit, validation, and follow-ups.; enriched with final-answer detail because persistence should be reusable
## Related learned memories <!-- same-turn-2026-11-10 10:01:16 -->
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Paperclip per-agent skills state and sync semantics]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|Adopt an existing folder into the harness with `office` (and its known scaffold gap)]]
- decision: [[packs/paperclip-harness/50-decisions/mouse-1-restricted-to-triage-never-a-gate-or-permit|MOUSE-1 restricted to triage; never a gate or permit]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Recorded interface plan for Paperclip + TUIOS harness in docs/PLAN-INTERFACE.md]]
- session: [[packs/paperclip-harness/80-sessions/paperclip-tuios-interface-discovery-skills-api-memory-stack-|Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold]]
- context: [[packs/paperclip-harness/20-context/paperclip-tuios-harness-sam-s-coding-harness-office-board-wo|Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-paperclipai-2026-11-10-10-01-16|Rich discovery: paperclipai 2026-11-10 10:01:16]]
- context: [[packs/paperclip-harness/20-context/home|paperclipai]]

View File

@@ -0,0 +1,107 @@
---
type: decision
id: decision.paperclip-harness.mouse-1-restricted-to-triage-never-a-gate-or-permit
title: MOUSE-1 restricted to triage; never a gate or permit
status: active
source_of_truth: false
freshness: current
last_reviewed: 2026-11-10
tags:
- pack/paperclip-harness
- agent-memory/decision
- mouse-1
- policy
- triage
- board
- review
---
# MOUSE-1 restricted to triage; never a gate or permit
Adopted the existing note policy unchanged: MOUSE-1 is triage only — label, score, route, escalate; never a gate, never a permit. Rationale: it is an external service (key + network hop, unproven product) and fails open on network errors, so a green run would be misleading if it gated merges or approvals. Permitted future uses: ordering Board>board's needs-you list, pre-sorting findings in Work>review. Consequences: no MOUSE-1 calls in merge/approval/tool-permission paths; MOUSE_API_KEY/JEV_API_KEY env names exist but no mouse/jev/switch binaries installed. Review caveat: revisit only after measured reliability evidence.
## Detailed decision context from completed turn
Explored all of it. Recorded in `docs/PLAN-INTERFACE.md`; the short version:
## Skills per agent — Paperclip already models it
`GET /api/agents/{id}/skills` returns a desired set, a managed set and a state per skill. On `Builder` today:
```
desired: ["paperclipai/paperclip/paperclip"]
company/<id>/obsidian-cli desired: false managed: true state: "stale"
```
`POST /api/agents/{id}/skills/sync` takes `add`, `remove` or **`replace`** — `replace` is exactly "this agent gets these and nothing else", which is how a sub-agent's context stays small. There is also a company skill catalog, versions, audit, and `GET/PUT /api/companies/{id}/skill-policy` with an `evaluate` call.
Proposal: two rows in `Agents>agents` settings — **skills** (the desired set, read-only first, add/remove later) and **skill source**. A full browser is a later screen, not a panel. Also: `obsidian-cli` sitting `stale` on Builder is worth fixing.
## Memory — three different things
| | state here | what it is |
|---|---|---|
| **engram** | installed, v1.16.1, MCP mode, **not** registered in `~/.pi/agent/mcp.json` (only `codebase-memory`, `graphify-vault`) | persistent memory |
| **headroom** | running, v0.24.0, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression on | a prompt-compression proxy, not a store |
| **pi memctx** | in use now | injects notes into a prompt |
They are complementary. Paperclip's only per-agent lever is `adapterConfig` and `runtimeConfig`, so memory is set per agent by pointing that agent at the proxy or store it should use. Proposal: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, and nothing more until one agent has run both ways and been measured.
## MOUSE-1
`MOUSE_API_KEY` is set (checked the name only, never the value). `JEV_API_KEY` too. No `mouse`, `mouse1`, `jev` or `switch` binary is installed.
There **are** notes, and they are good ones — in the old project's plan documents:
> MOUSE-1 is *"triage only: label, score, route, escalate. Never a gate, never a permit"* — explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error makes a green run a lie.
I would adopt that policy unchanged. Its place, if added: ordering `Board>board`'s needs-you list, or pre-sorting findings in `Work>review`. Never the merge, never an approval.
## Lazygit
Already wired: `t` in `Board>board` or `Work>work`, choose Lazygit. Verified opening in the right workspace and closing with `q`.
## The old `office` — and what ours lacks
The previous `office` did four things: remember the host; run `new-project` to write the scaffold (`settings.toml`, a file per role, `verify.sh`, the per-screen notes) writing **only what is missing**; refuse if the session does not exist and print the exact `tuios new` line; then build the pages.
Ours does the host, the refusal and the pages — but **no scaffold**. No per-role files, no `verify.sh`, no page notes. That is the cheapest real gap in the whole plan.
## Dashboard — the API answers it in one call
`GET /api/companies/{id}/dashboard`, 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, utilization 0}
runActivity [14 entries]
```
Proposal: a `Project>overview` panel with those blocks and a sparkline drawn in Go with `tuios.dev/plot`, rather than embedding the web dashboard in a pane.
## Not doing
Artifacts — dropped as instructed.
I am ready for the task you are about to deliver; nothing in the tree is half-changed, the eight workspaces are running, and the last commit is `3d31243`.
## Evidence
- Confidence: 90%
- Reason: Architectural/policy convention with rationale and explicit boundaries.; enriched with final-answer detail because persistence should be reusable
## Related
- [[packs/paperclip-harness/00-system/pi-agent/memory-manifest|Memory Manifest]]
## Related learned memories <!-- same-turn-2026-11-10 10:01:16 -->
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Paperclip per-agent skills state and sync semantics]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|Adopt an existing folder into the harness with `office` (and its known scaffold gap)]]
- decision: [[packs/paperclip-harness/50-decisions/mouse-1-restricted-to-triage-never-a-gate-or-permit|MOUSE-1 restricted to triage; never a gate or permit]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Recorded interface plan for Paperclip + TUIOS harness in docs/PLAN-INTERFACE.md]]
- session: [[packs/paperclip-harness/80-sessions/paperclip-tuios-interface-discovery-skills-api-memory-stack-|Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold]]
- context: [[packs/paperclip-harness/20-context/paperclip-tuios-harness-sam-s-coding-harness-office-board-wo|Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-paperclipai-2026-11-10-10-01-16|Rich discovery: paperclipai 2026-11-10 10:01:16]]
- context: [[packs/paperclip-harness/20-context/home|paperclipai]]

View File

@@ -1304,3 +1304,188 @@ Committed as `7b12b45`. Say go and I run that list end to end and report each re
- context: [[packs/paperclip-harness/20-context/tmp|tmp]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|tmp deployment operations]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|tmp repository structure and configuration patterns]]
---
## Update (2026-11-10 10:01:16)
`GET /api/agents/{id}/skills` returns supported/mode, desiredSkills + desiredSkillEntries (key/versionId), and entries[] with key, runtimeName, versionId, currentVersionId, desired, managed, state, sourcePath, targetPath.
Observed on agent Builder (adapterType pi_local, mode persistent): desired=[`paperclipai/paperclip/paperclip`]; entry `company/d4921013-e5da-4d88-8016-57d5746e2d03/obsidian-cli` has desired=false, managed=true, state=`stale`, runtimeName `obsidian-cli--b74ae42966`, sourcePath under /home/sam/.paperclip/instances/default/skills/<companyId>/obsidian-cli, targetPath under /home/sam/.pi/agent/skills/.
`POST /api/agents/{id}/skills/sync` supports add / remove / replace; `replace` gives an exclusive skill set (keeps sub-agent context small).
Company-level skill management surface: /api/companies/{companyId}/skills (GET,POST, /{skillId} GET/PATCH/DELETE), versions (GET,POST, /{versionId}), files, audit, comments, fork + fork-precheck, rename, reset, star, install-update, update-status, test-inputs, test-runs (+cancel), categories, import, install-catalog, scan-projects, browse-project; skill-policy GET/PUT/DELETE + /evaluate; skill-test-run-templates. Public: /api/skills/{index,available,catalog,catalogId,skillName}; invite-scoped /api/invites/{token}/skills/...
## Evidence
- Confidence: 90%
- Reason: Factual API/state discovery likely to be reused when implementing skills UI or fixing stale skills.
---
## Update (2026-11-10 10:01:16)
`GET /api/companies/{id}/dashboard` returns (observed 1.8 KB): agents {active, running, paused, error} = 6/0/0/0; tasks {open, inProgress, blocked, done} = 8/0/4/147; costs {monthSpendCents, monthBudgetCents, monthUtilizationPercent} = 11/0/0; pendingApprovals 0; budgets {activeIncidents, pendingApprovals, pausedAgents, pausedProjects} all 0; runActivity list of 14. Proposed UI: a Project>overview panel rendering these blocks with a Go sparkline (tuios.dev/plot) instead of embedding the web dashboard.
## Detailed observations from completed turn
Explored all of it. Recorded in `docs/PLAN-INTERFACE.md`; the short version:
## Skills per agent — Paperclip already models it
`GET /api/agents/{id}/skills` returns a desired set, a managed set and a state per skill. On `Builder` today:
```
desired: ["paperclipai/paperclip/paperclip"]
company/<id>/obsidian-cli desired: false managed: true state: "stale"
```
`POST /api/agents/{id}/skills/sync` takes `add`, `remove` or **`replace`** — `replace` is exactly "this agent gets these and nothing else", which is how a sub-agent's context stays small. There is also a company skill catalog, versions, audit, and `GET/PUT /api/companies/{id}/skill-policy` with an `evaluate` call.
Proposal: two rows in `Agents>agents` settings — **skills** (the desired set, read-only first, add/remove later) and **skill source**. A full browser is a later screen, not a panel. Also: `obsidian-cli` sitting `stale` on Builder is worth fixing.
## Memory — three different things
| | state here | what it is |
|---|---|---|
| **engram** | installed, v1.16.1, MCP mode, **not** registered in `~/.pi/agent/mcp.json` (only `codebase-memory`, `graphify-vault`) | persistent memory |
| **headroom** | running, v0.24.0, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression on | a prompt-compression proxy, not a store |
| **pi memctx** | in use now | injects notes into a prompt |
They are complementary. Paperclip's only per-agent lever is `adapterConfig` and `runtimeConfig`, so memory is set per agent by pointing that agent at the proxy or store it should use. Proposal: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, and nothing more until one agent has run both ways and been measured.
## MOUSE-1
`MOUSE_API_KEY` is set (checked the name only, never the value). `JEV_API_KEY` too. No `mouse`, `mouse1`, `jev` or `switch` binary is installed.
There **are** notes, and they are good ones — in the old project's plan documents:
> MOUSE-1 is *"triage only: label, score, route, escalate. Never a gate, never a permit"* — explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error makes a green run a lie.
I would adopt that policy unchanged. Its place, if added: ordering `Board>board`'s needs-you list, or pre-sorting findings in `Work>review`. Never the merge, never an approval.
## Lazygit
Already wired: `t` in `Board>board` or `Work>work`, choose Lazygit. Verified opening in the right workspace and closing with `q`.
## The old `office` — and what ours lacks
The previous `office` did four things: remember the host; run `new-project` to write the scaffold (`settings.toml`, a file per role, `verify.sh`, the per-screen notes) writing **only what is missing**; refuse if the session does not exist and print the exact `tuios new` line; then build the pages.
Ours does the host, the refusal and the pages — but **no scaffold**. No per-role files, no `verify.sh`, no page notes. That is the cheapest real gap in the whole plan.
## Dashboard — the API answers it in one call
`GET /api/companies/{id}/dashboard`, 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, utilization 0}
runActivity [14 entries]
```
Proposal: a `Project>overview` panel with those blocks and a sparkline drawn in Go with `tuios.dev/plot`, rather than embedding the web dashboard in a pane.
## Not doing
Artifacts — dropped as instructed.
I am ready for the task you are about to deliver; nothing in the tree is half-changed, the eight workspaces are running, and the last commit is `3d31243`.
## Evidence
- Confidence: 90%
- Reason: Concrete endpoint shape and counts support future Project>overview implementation.; enriched with final-answer detail because persistence should be reusable
---
## Update (2026-11-10 10:01:16)
Three complementary memory mechanisms: (a) engram v1.16.1 installed in MCP mode but NOT registered in ~/.pi/agent/mcp.json; (b) headroom prompt-compression proxy v0.24.0 healthy at 192.168.20.13:8787 with memory backend disabled (memory check enabled=false, backend null) and compression on; (c) pi memctx, which injects notes into a prompt. Registered MCP servers at discovery: only codebase-memory and graphify-vault (both lifecycle lazy). Paperclip exposes only adapterConfig and runtimeConfig per agent, so memory choice is expressed by pointing an agent at the desired proxy/store. Proposal: a memory row in Agents>agents showing which mechanism an agent uses, pending measurement.
## Detailed observations from completed turn
Explored all of it. Recorded in `docs/PLAN-INTERFACE.md`; the short version:
## Skills per agent — Paperclip already models it
`GET /api/agents/{id}/skills` returns a desired set, a managed set and a state per skill. On `Builder` today:
```
desired: ["paperclipai/paperclip/paperclip"]
company/<id>/obsidian-cli desired: false managed: true state: "stale"
```
`POST /api/agents/{id}/skills/sync` takes `add`, `remove` or **`replace`** — `replace` is exactly "this agent gets these and nothing else", which is how a sub-agent's context stays small. There is also a company skill catalog, versions, audit, and `GET/PUT /api/companies/{id}/skill-policy` with an `evaluate` call.
Proposal: two rows in `Agents>agents` settings — **skills** (the desired set, read-only first, add/remove later) and **skill source**. A full browser is a later screen, not a panel. Also: `obsidian-cli` sitting `stale` on Builder is worth fixing.
## Memory — three different things
| | state here | what it is |
|---|---|---|
| **engram** | installed, v1.16.1, MCP mode, **not** registered in `~/.pi/agent/mcp.json` (only `codebase-memory`, `graphify-vault`) | persistent memory |
| **headroom** | running, v0.24.0, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression on | a prompt-compression proxy, not a store |
| **pi memctx** | in use now | injects notes into a prompt |
They are complementary. Paperclip's only per-agent lever is `adapterConfig` and `runtimeConfig`, so memory is set per agent by pointing that agent at the proxy or store it should use. Proposal: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, and nothing more until one agent has run both ways and been measured.
## MOUSE-1
`MOUSE_API_KEY` is set (checked the name only, never the value). `JEV_API_KEY` too. No `mouse`, `mouse1`, `jev` or `switch` binary is installed.
There **are** notes, and they are good ones — in the old project's plan documents:
> MOUSE-1 is *"triage only: label, score, route, escalate. Never a gate, never a permit"* — explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error makes a green run a lie.
I would adopt that policy unchanged. Its place, if added: ordering `Board>board`'s needs-you list, or pre-sorting findings in `Work>review`. Never the merge, never an approval.
## Lazygit
Already wired: `t` in `Board>board` or `Work>work`, choose Lazygit. Verified opening in the right workspace and closing with `q`.
## The old `office` — and what ours lacks
The previous `office` did four things: remember the host; run `new-project` to write the scaffold (`settings.toml`, a file per role, `verify.sh`, the per-screen notes) writing **only what is missing**; refuse if the session does not exist and print the exact `tuios new` line; then build the pages.
Ours does the host, the refusal and the pages — but **no scaffold**. No per-role files, no `verify.sh`, no page notes. That is the cheapest real gap in the whole plan.
## Dashboard — the API answers it in one call
`GET /api/companies/{id}/dashboard`, 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, utilization 0}
runActivity [14 entries]
```
Proposal: a `Project>overview` panel with those blocks and a sparkline drawn in Go with `tuios.dev/plot`, rather than embedding the web dashboard in a pane.
## Not doing
Artifacts — dropped as instructed.
I am ready for the task you are about to deliver; nothing in the tree is half-changed, the eight workspaces are running, and the last commit is `3d31243`.
## Evidence
- Confidence: 85%
- Reason: Durable operational facts about memory components and configuration gaps.; enriched with final-answer detail because persistence should be reusable
## Related learned memories <!-- same-turn-2026-11-10 10:01:16 -->
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Paperclip per-agent skills state and sync semantics]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|Adopt an existing folder into the harness with `office` (and its known scaffold gap)]]
- decision: [[packs/paperclip-harness/50-decisions/mouse-1-restricted-to-triage-never-a-gate-or-permit|MOUSE-1 restricted to triage; never a gate or permit]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Recorded interface plan for Paperclip + TUIOS harness in docs/PLAN-INTERFACE.md]]
- session: [[packs/paperclip-harness/80-sessions/paperclip-tuios-interface-discovery-skills-api-memory-stack-|Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold]]
- context: [[packs/paperclip-harness/20-context/paperclip-tuios-harness-sam-s-coding-harness-office-board-wo|Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-paperclipai-2026-11-10-10-01-16|Rich discovery: paperclipai 2026-11-10 10:01:16]]
- context: [[packs/paperclip-harness/20-context/home|paperclipai]]

View File

@@ -101,3 +101,305 @@ Committed as `7b12b45`. Say go and I run that list end to end and report each re
- context: [[packs/paperclip-harness/20-context/tmp|tmp]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|tmp deployment operations]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|tmp repository structure and configuration patterns]]
---
## Update (2026-11-10 10:01:16)
Trigger: bringing an existing git repo or folder into the TUIOS harness.
Procedure (`office <dir> [--session <name>] [--dry]`):
1. Resolve host: read/write `<dir>/.harness/host`; mkdir `<dir>/.harness` if missing (dry-run prints planned actions and exits).
2. Detect whether project is 'adopting (writing what is missing)' vs 'already a harness project'.
3. Ensure TUIOS session exists: `timeout 20 tuios list-sessions` (strip ANSI, parse column 2) must contain the session. If absent, office prints `tuios new <session>` and exits 2 — TUIOS cannot create sessions non-interactively in this build ('Standard output is not a terminal').
4. Run `board` with HARNESS_REPO and HARNESS_SESSION set to build/repair pages.
5. Print attach commands: `tuios-gpui attach <session>`, `tuios attach <session>`, remote `tuios-gpui attach --host <hostname> <session>`.
Known gap: old office also ran `new-project` to write scaffold (settings.toml, one file per role, verify.sh, per-screen notes) only when missing; current office skips this. Safe: office/new-project never overwrite existing files. Troubleshooting: 'office: new-project failed' or 'office: board failed' indicate the respective step; re-run is idempotent.
## Detailed procedure from completed turn
Explored all of it. Recorded in `docs/PLAN-INTERFACE.md`; the short version:
## Skills per agent — Paperclip already models it
`GET /api/agents/{id}/skills` returns a desired set, a managed set and a state per skill. On `Builder` today:
```
desired: ["paperclipai/paperclip/paperclip"]
company/<id>/obsidian-cli desired: false managed: true state: "stale"
```
`POST /api/agents/{id}/skills/sync` takes `add`, `remove` or **`replace`** — `replace` is exactly "this agent gets these and nothing else", which is how a sub-agent's context stays small. There is also a company skill catalog, versions, audit, and `GET/PUT /api/companies/{id}/skill-policy` with an `evaluate` call.
Proposal: two rows in `Agents>agents` settings — **skills** (the desired set, read-only first, add/remove later) and **skill source**. A full browser is a later screen, not a panel. Also: `obsidian-cli` sitting `stale` on Builder is worth fixing.
## Memory — three different things
| | state here | what it is |
|---|---|---|
| **engram** | installed, v1.16.1, MCP mode, **not** registered in `~/.pi/agent/mcp.json` (only `codebase-memory`, `graphify-vault`) | persistent memory |
| **headroom** | running, v0.24.0, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression on | a prompt-compression proxy, not a store |
| **pi memctx** | in use now | injects notes into a prompt |
They are complementary. Paperclip's only per-agent lever is `adapterConfig` and `runtimeConfig`, so memory is set per agent by pointing that agent at the proxy or store it should use. Proposal: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, and nothing more until one agent has run both ways and been measured.
## MOUSE-1
`MOUSE_API_KEY` is set (checked the name only, never the value). `JEV_API_KEY` too. No `mouse`, `mouse1`, `jev` or `switch` binary is installed.
There **are** notes, and they are good ones — in the old project's plan documents:
> MOUSE-1 is *"triage only: label, score, route, escalate. Never a gate, never a permit"* — explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error makes a green run a lie.
I would adopt that policy unchanged. Its place, if added: ordering `Board>board`'s needs-you list, or pre-sorting findings in `Work>review`. Never the merge, never an approval.
## Lazygit
Already wired: `t` in `Board>board` or `Work>work`, choose Lazygit. Verified opening in the right workspace and closing with `q`.
## The old `office` — and what ours lacks
The previous `office` did four things: remember the host; run `new-project` to write the scaffold (`settings.toml`, a file per role, `verify.sh`, the per-screen notes) writing **only what is missing**; refuse if the session does not exist and print the exact `tuios new` line; then build the pages.
Ours does the host, the refusal and the pages — but **no scaffold**. No per-role files, no `verify.sh`, no page notes. That is the cheapest real gap in the whole plan.
## Dashboard — the API answers it in one call
`GET /api/companies/{id}/dashboard`, 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, utilization 0}
runActivity [14 entries]
```
Proposal: a `Project>overview` panel with those blocks and a sparkline drawn in Go with `tuios.dev/plot`, rather than embedding the web dashboard in a pane.
## Not doing
Artifacts — dropped as instructed.
I am ready for the task you are about to deliver; nothing in the tree is half-changed, the eight workspaces are running, and the last commit is `3d31243`.
## Evidence
- Confidence: 85%
- Reason: Repeatable procedure with prerequisites, exit codes, safe behavior, and the known-scaffold caveat.; enriched with final-answer detail because persistence should be reusable
---
## Update (2026-11-10 10:01:16)
Trigger: desired skill set for an agent changed, or a skill shows `stale`.
1. Inspect: `GET /api/agents/{id}/skills` — read desiredSkills, desiredSkillEntries, and entries[] (desired, managed, state, runtimeName, sourcePath, targetPath).
2. Decide mode: `POST /api/agents/{id}/skills/sync` with add / remove, or `replace` for an exclusive set (recommended for sub-agents to keep context small).
3. For company-level operations use `/api/companies/{companyId}/skills/...` (import, install-catalog, scan-projects, versions, audit, fork, install-update). Policy checks: `GET/PUT /api/companies/{companyId}/skill-policy` and `POST .../skill-policy/evaluate`.
4. Verify after sync that entries show desired=true and state not `stale`.
Caveats: managed skills materialize from /home/sam/.paperclip/instances/default/skills/<companyId>/ into /home/sam/.pi/agent/skills/; a `stale` managed skill (e.g. obsidian-cli on Builder) needs reset/install-update, not just add. Avoid `replace` on the top-level orchestrator agent, which intentionally carries the `paperclipai/paperclip/paperclip` skill.
## Detailed procedure from completed turn
Explored all of it. Recorded in `docs/PLAN-INTERFACE.md`; the short version:
## Skills per agent — Paperclip already models it
`GET /api/agents/{id}/skills` returns a desired set, a managed set and a state per skill. On `Builder` today:
```
desired: ["paperclipai/paperclip/paperclip"]
company/<id>/obsidian-cli desired: false managed: true state: "stale"
```
`POST /api/agents/{id}/skills/sync` takes `add`, `remove` or **`replace`** — `replace` is exactly "this agent gets these and nothing else", which is how a sub-agent's context stays small. There is also a company skill catalog, versions, audit, and `GET/PUT /api/companies/{id}/skill-policy` with an `evaluate` call.
Proposal: two rows in `Agents>agents` settings — **skills** (the desired set, read-only first, add/remove later) and **skill source**. A full browser is a later screen, not a panel. Also: `obsidian-cli` sitting `stale` on Builder is worth fixing.
## Memory — three different things
| | state here | what it is |
|---|---|---|
| **engram** | installed, v1.16.1, MCP mode, **not** registered in `~/.pi/agent/mcp.json` (only `codebase-memory`, `graphify-vault`) | persistent memory |
| **headroom** | running, v0.24.0, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression on | a prompt-compression proxy, not a store |
| **pi memctx** | in use now | injects notes into a prompt |
They are complementary. Paperclip's only per-agent lever is `adapterConfig` and `runtimeConfig`, so memory is set per agent by pointing that agent at the proxy or store it should use. Proposal: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, and nothing more until one agent has run both ways and been measured.
## MOUSE-1
`MOUSE_API_KEY` is set (checked the name only, never the value). `JEV_API_KEY` too. No `mouse`, `mouse1`, `jev` or `switch` binary is installed.
There **are** notes, and they are good ones — in the old project's plan documents:
> MOUSE-1 is *"triage only: label, score, route, escalate. Never a gate, never a permit"* — explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error makes a green run a lie.
I would adopt that policy unchanged. Its place, if added: ordering `Board>board`'s needs-you list, or pre-sorting findings in `Work>review`. Never the merge, never an approval.
## Lazygit
Already wired: `t` in `Board>board` or `Work>work`, choose Lazygit. Verified opening in the right workspace and closing with `q`.
## The old `office` — and what ours lacks
The previous `office` did four things: remember the host; run `new-project` to write the scaffold (`settings.toml`, a file per role, `verify.sh`, the per-screen notes) writing **only what is missing**; refuse if the session does not exist and print the exact `tuios new` line; then build the pages.
Ours does the host, the refusal and the pages — but **no scaffold**. No per-role files, no `verify.sh`, no page notes. That is the cheapest real gap in the whole plan.
## Dashboard — the API answers it in one call
`GET /api/companies/{id}/dashboard`, 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, utilization 0}
runActivity [14 entries]
```
Proposal: a `Project>overview` panel with those blocks and a sparkline drawn in Go with `tuios.dev/plot`, rather than embedding the web dashboard in a pane.
## Not doing
Artifacts — dropped as instructed.
I am ready for the task you are about to deliver; nothing in the tree is half-changed, the eight workspaces are running, and the last commit is `3d31243`.
## Evidence
- Confidence: 80%
- Reason: Actionable procedure derived from concrete API behavior and observed stale state.; enriched with final-answer detail because persistence should be reusable
---
## Update (2026-11-10 10:01:16)
## Deployment/runbook details discovered (2026-11-10 10:01:16)
Explored all of it. Recorded in `docs/PLAN-INTERFACE.md`; the short version:
## Skills per agent — Paperclip already models it
`GET /api/agents/{id}/skills` returns a desired set, a managed set and a state per skill. On `Builder` today:
```
desired: ["paperclipai/paperclip/paperclip"]
company/<id>/obsidian-cli desired: false managed: true state: "stale"
```
`POST /api/agents/{id}/skills/sync` takes `add`, `remove` or **`replace`** — `replace` is exactly "this agent gets these and nothing else", which is how a sub-agent's context stays small. There is also a company skill catalog, versions, audit, and `GET/PUT /api/companies/{id}/skill-policy` with an `evaluate` call.
Proposal: two rows in `Agents>agents` settings — **skills** (the desired set, read-only first, add/remove later) and **skill source**. A full browser is a later screen, not a panel. Also: `obsidian-cli` sitting `stale` on Builder is worth fixing.
## Memory — three different things
| | state here | what it is |
|---|---|---|
| **engram** | installed, v1.16.1, MCP mode, **not** registered in `~/.pi/agent/mcp.json` (only `codebase-memory`, `graphify-vault`) | persistent memory |
| **headroom** | running, v0.24.0, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression on | a prompt-compression proxy, not a store |
| **pi memctx** | in use now | injects notes into a prompt |
They are complementary. Paperclip's only per-agent lever is `adapterConfig` and `runtimeConfig`, so memory is set per agent by pointing that agent at the proxy or store it should use. Proposal: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, and nothing more until one agent has run both ways and been measured.
## MOUSE-1
`MOUSE_API_KEY` is set (checked the name only, never the value). `JEV_API_KEY` too. No `mouse`, `mouse1`, `jev` or `switch` binary is installed.
There **are** notes, and they are good ones — in the old project's plan documents:
> MOUSE-1 is *"triage only: label, score, route, escalate. Never a gate, never a permit"* — explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error makes a green run a lie.
I would adopt that policy unchanged. Its place, if added: ordering `Board>board`'s needs-you list, or pre-sorting findings in `Work>review`. Never the merge, never an approval.
## Lazygit
Already wired: `t` in `Board>board` or `Work>work`, choose Lazygit. Verified opening in the right workspace and closing with `q`.
## The old `office` — and what ours lacks
The previous `office` did four things: remember the host; run `new-project` to write the scaffold (`settings.toml`, a file per role, `verify.sh`, the per-screen notes) writing **only what is missing**; refuse if the session does not exist and print the exact `tuios new` line; then build the pages.
Ours does the host, the refusal and the pages — but **no scaffold**. No per-role files, no `verify.sh`, no page notes. That is the cheapest real gap in the whole plan.
## Dashboard — the API answers it in one call
`GET /api/companies/{id}/dashboard`, 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, utilization 0}
runActivity [14 entries]
```
Proposal: a `Project>overview` panel with those blocks and a sparkline drawn in Go with `tuios.dev/plot`, rather than embedding the web dashboard in a pane.
## Not doing
Artifacts — dropped as instructed.
I am ready for the task you are about to deliver; nothing in the tree is half-changed, the eight workspaces are running, and the last commit is `3d31243`.
## Source paths observed
- `home/sam/.local/bin/engram`
- `home/sam/.config/environment.d/10-secrets.conf`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/80-sessions/paperclip-harness-reverted-pane-split-interface-gap-discover.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/80-sessions/rich-discovery-tmp-2026-11-10-07-35-38.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/80-sessions/rich-discovery-home-2026-11-10-05-41-48.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/20-context/home.md`
- `github.com/Gentleman-Programming/engram/cmd/engram`
- `api/skills/available`
- `api/skills/catalog`
- `api/skills/index`
- `paperclipai/paperclip/paperclip`
- `company/d4921013-e5da-4d88-8016-57d5746e2d03/obsidian-cli`
- `home/sam/.paperclip/instances/default/skills/d4921013-e5da-4d88-8016-57d5746e2d03/obsidian-cli`
- `home/sam/.pi/agent/skills/obsidian-`
- `dir/.harness/host`
- `home/sam/paseo/projects/tuios_coding_harness/plan/82-control-room.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/83-interface.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/80-forked-plan.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/91-paperclip-or-oma.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/50-open-work.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/skills/graphify/SKILL.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/skills/system-architect/SKILL.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/extensions/pi-graphify/skills/graphify/SKILL.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/node_modules`
- `google/genai/dist/node/index.cjs`
- `google/genai/dist/node/node.d.ts`
- `home/sam/.config/systemd/user/lan-mouse.service`
- `home/sam/.config/lan-mouse`
- `home/sam/.config/lan-mouse/lan-mouse.pem`
- `home/sam/.cache/lan-mouse`
- `home/sam/.local/bin/lan-mouse-011`
- `home/sam/.pi/agent/auth.json`
- `home/sam/.pi/agent/mcp-cache.json`
- `home/sam/.pi/agent/mcp.json`
- `home/sam/.pi/agent/models.json`
- `home/sam/.pi/agent/models-store.json`
- `home/sam/.pi/agent/settings.json`
- `home/sam/.pi/agent/trust.json`
- `home/sam/.local/bin/codebase-memory-mcp`
## Evidence
- Confidence: 83%
- Reason: Extracted repeatable deploy/configuration procedure from rich discovery
## Related learned memories <!-- same-turn-2026-11-10 10:01:16 -->
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Paperclip per-agent skills state and sync semantics]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|Adopt an existing folder into the harness with `office` (and its known scaffold gap)]]
- decision: [[packs/paperclip-harness/50-decisions/mouse-1-restricted-to-triage-never-a-gate-or-permit|MOUSE-1 restricted to triage; never a gate or permit]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Recorded interface plan for Paperclip + TUIOS harness in docs/PLAN-INTERFACE.md]]
- session: [[packs/paperclip-harness/80-sessions/paperclip-tuios-interface-discovery-skills-api-memory-stack-|Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold]]
- context: [[packs/paperclip-harness/20-context/paperclip-tuios-harness-sam-s-coding-harness-office-board-wo|Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-paperclipai-2026-11-10-10-01-16|Rich discovery: paperclipai 2026-11-10 10:01:16]]
- context: [[packs/paperclip-harness/20-context/home|paperclipai]]

View File

@@ -0,0 +1,55 @@
---
type: session
id: session.paperclip-harness.paperclip-tuios-interface-discovery-skills-api-memory-stack-
title: Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold
status: active
source_of_truth: false
freshness: current
last_reviewed: 2026-11-10
tags:
- pack/paperclip-harness
- agent-memory/session
- paperclip
- tuios
- skills-api
- memory
- mouse-1
- dashboard
- office-scaffold
---
# Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold
Discovery pass recorded in `docs/PLAN-INTERFACE.md`, last commit `3d31243`.
1) Skills per agent: `GET /api/agents/{id}/skills` returns desired/managed sets + per-skill state. Builder currently: desired=[paperclipai/paperclip/paperclip]; company/<id>/obsidian-cli desired=false, managed=true, state="stale" (runtimeName obsidian-cli--b74ae42966, currentVersionId cf41ba39-..., sourcePath /home/sam/.paperclip/instances/default/skills/<companyId>/obsidian-cli). `POST /api/agents/{id}/skills/sync` accepts add/remove/replace (`replace` = exclusive set, keeps sub-agent context small). Full skills API surface: company skills CRUD/import/install-catalog/scan-projects/browse-project, versions, audit, comments, files, fork + fork-precheck, rename, reset, star, test-inputs, test-runs(+cancel), install-update, update-status, `GET/PUT/DELETE /api/companies/{id}/skill-policy` + `/evaluate`, skill-test-run-templates, `/api/skills/{index,available,catalog,...}`, invite-scoped skill index. Proposal: two rows in Agents>agents settings — skills (desired set, read-only first) and skill source; full browser later; fix stale obsidian-cli.
2) Memory is three distinct things: engram (v1.16.1 installed, MCP mode, NOT registered in ~/.pi/agent/mcp.json), headroom (v0.24.0 proxy at 192.168.20.13:8787, healthy, memory backend disabled, compression on — not a store), and pi memctx (injects notes into prompt). Only mcp servers registered: codebase-memory (/home/sam/.local/bin/codebase-memory-mcp), graphify-vault (/home/sam/.local/bin/relay-graphify-mcp), both lazy. Paperclip per-agent levers are adapterConfig/runtimeConfig. Proposal: a memory row in Agents>agents showing which of the three an agent uses, nothing more until measured.
3) MOUSE-1: MOUSE_API_KEY and JEV_API_KEY env names present (values not inspected); no mouse/mouse1/jev/switch binary installed. Existing notes state policy: "triage only: label, score, route, escalate. Never a gate, never a permit" — ruled out for merges/tool-call gating because it fails open on network errors. Adopted unchanged; if added, may only order Board>board needs-you list or pre-sort findings in Work>review.
4) Lazygit: already wired — `t` in Board>board or Work>work, opens in correct workspace, quits with `q`.
5) Old `office` (~/paseo/projects/tuios_coding_harness, scripts office/new-project/board): remembers host in .harness/host; runs new-project to write scaffold (settings.toml, per-role file, verify.sh, per-screen notes) only what is missing; refuses if session absent and prints exact `tuios new <session>` line (TUIOS cannot create sessions non-interactively — "Standard output is not a terminal"); then builds pages. Current office does host/refusal/pages but NO scaffold — cheapest real gap.
6) Dashboard: `GET /api/companies/{id}/dashboard` returns ~1.8KB: agents{active 6, running 0, paused 0, error 0}, tasks{open 8, inProgress 0, blocked 4, done 147}, costs{monthSpendCents 11, monthBudgetCents 0, utilization 0}, runActivity[14]. Proposal: Project>overview panel with those blocks + sparkline via tuios.dev/plot instead of embedding web dashboard. Artifacts explicitly dropped.
## Evidence
- Confidence: 90%
- Reason: Rich evidence-backed discovery snapshot with concrete endpoints, component versions, paths, and proposals useful to future agents.
## Related
- [[packs/paperclip-harness/00-system/pi-agent/memory-manifest|Memory Manifest]]
## Related learned memories <!-- same-turn-2026-11-10 10:01:16 -->
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Paperclip per-agent skills state and sync semantics]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|Adopt an existing folder into the harness with `office` (and its known scaffold gap)]]
- decision: [[packs/paperclip-harness/50-decisions/mouse-1-restricted-to-triage-never-a-gate-or-permit|MOUSE-1 restricted to triage; never a gate or permit]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Recorded interface plan for Paperclip + TUIOS harness in docs/PLAN-INTERFACE.md]]
- session: [[packs/paperclip-harness/80-sessions/paperclip-tuios-interface-discovery-skills-api-memory-stack-|Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold]]
- context: [[packs/paperclip-harness/20-context/paperclip-tuios-harness-sam-s-coding-harness-office-board-wo|Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-paperclipai-2026-11-10-10-01-16|Rich discovery: paperclipai 2026-11-10 10:01:16]]
- context: [[packs/paperclip-harness/20-context/home|paperclipai]]

View File

@@ -0,0 +1,149 @@
---
type: session
id: session.paperclip-harness.rich-discovery-paperclipai-2026-11-10-10-01-16
title: Rich discovery: paperclipai 2026-11-10 10:01:16
status: active
source_of_truth: false
freshness: current
last_reviewed: 2026-11-10
tags:
- pack/paperclip-harness
- agent-memory/session
- autolearn
- rich-discovery
- repo/paperclipai
---
# Rich discovery: paperclipai 2026-11-10 10:01:16
Sanitized rich discovery snapshot captured automatically from the completed turn.
## Source paths observed
- `home/sam/.local/bin/engram`
- `home/sam/.config/environment.d/10-secrets.conf`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/80-sessions/paperclip-harness-reverted-pane-split-interface-gap-discover.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/80-sessions/rich-discovery-tmp-2026-11-10-07-35-38.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/80-sessions/rich-discovery-home-2026-11-10-05-41-48.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups.md`
- `home/sam/paseo/projects/paperclip-harness/.pi/memory-vault/packs/paperclip-harness/20-context/home.md`
- `github.com/Gentleman-Programming/engram/cmd/engram`
- `api/skills/available`
- `api/skills/catalog`
- `api/skills/index`
- `paperclipai/paperclip/paperclip`
- `company/d4921013-e5da-4d88-8016-57d5746e2d03/obsidian-cli`
- `home/sam/.paperclip/instances/default/skills/d4921013-e5da-4d88-8016-57d5746e2d03/obsidian-cli`
- `home/sam/.pi/agent/skills/obsidian-`
- `dir/.harness/host`
- `home/sam/paseo/projects/tuios_coding_harness/plan/82-control-room.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/83-interface.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/80-forked-plan.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/91-paperclip-or-oma.md`
- `home/sam/paseo/projects/tuios_coding_harness/plan/50-open-work.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/skills/graphify/SKILL.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/skills/system-architect/SKILL.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/extensions/pi-graphify/skills/graphify/SKILL.md`
- `home/sam/.pi/agent/git/gitea.lab.audasmedia.com.au/sam/pi-config/node_modules`
- `google/genai/dist/node/index.cjs`
- `google/genai/dist/node/node.d.ts`
- `home/sam/.config/systemd/user/lan-mouse.service`
- `home/sam/.config/lan-mouse`
- `home/sam/.config/lan-mouse/lan-mouse.pem`
- `home/sam/.cache/lan-mouse`
- `home/sam/.local/bin/lan-mouse-011`
- `home/sam/.pi/agent/auth.json`
- `home/sam/.pi/agent/mcp-cache.json`
- `home/sam/.pi/agent/mcp.json`
- `home/sam/.pi/agent/models.json`
- `home/sam/.pi/agent/models-store.json`
- `home/sam/.pi/agent/settings.json`
- `home/sam/.pi/agent/trust.json`
- `home/sam/.local/bin/codebase-memory-mcp`
## Final answer snapshot
Explored all of it. Recorded in `docs/PLAN-INTERFACE.md`; the short version:
## Skills per agent — Paperclip already models it
`GET /api/agents/{id}/skills` returns a desired set, a managed set and a state per skill. On `Builder` today:
```
desired: ["paperclipai/paperclip/paperclip"]
company/<id>/obsidian-cli desired: false managed: true state: "stale"
```
`POST /api/agents/{id}/skills/sync` takes `add`, `remove` or **`replace`** — `replace` is exactly "this agent gets these and nothing else", which is how a sub-agent's context stays small. There is also a company skill catalog, versions, audit, and `GET/PUT /api/companies/{id}/skill-policy` with an `evaluate` call.
Proposal: two rows in `Agents>agents` settings — **skills** (the desired set, read-only first, add/remove later) and **skill source**. A full browser is a later screen, not a panel. Also: `obsidian-cli` sitting `stale` on Builder is worth fixing.
## Memory — three different things
| | state here | what it is |
|---|---|---|
| **engram** | installed, v1.16.1, MCP mode, **not** registered in `~/.pi/agent/mcp.json` (only `codebase-memory`, `graphify-vault`) | persistent memory |
| **headroom** | running, v0.24.0, healthy at `192.168.20.13:8787`, memory backend **disabled**, compression on | a prompt-compression proxy, not a store |
| **pi memctx** | in use now | injects notes into a prompt |
They are complementary. Paperclip's only per-agent lever is `adapterConfig` and `runtimeConfig`, so memory is set per agent by pointing that agent at the proxy or store it should use. Proposal: a **memory** row in `Agents>agents` settings showing which of the three that agent uses, and nothing more until one agent has run both ways and been measured.
## MOUSE-1
`MOUSE_API_KEY` is set (checked the name only, never the value). `JEV_API_KEY` too. No `mouse`, `mouse1`, `jev` or `switch` binary is installed.
There **are** notes, and they are good ones — in the old project's plan documents:
> MOUSE-1 is *"triage only: label, score, route, escalate. Never a gate, never a permit"* — explicitly ruled out for deciding a merge or allowing a tool call, because a cheap classifier that fails open on a network error makes a green run a lie.
I would adopt that policy unchanged. Its place, if added: ordering `Board>board`'s needs-you list, or pre-sorting findings in `Work>review`. Never the merge, never an approval.
## Lazygit
Already wired: `t` in `Board>board` or `Work>work`, choose Lazygit. Verified opening in the right workspace and closing with `q`.
## The old `office` — and what ours lacks
The previous `office` did four things: remember the host; run `new-project` to write the scaffold (`settings.toml`, a file per role, `verify.sh`, the per-screen notes) writing **only what is missing**; refuse if the session does not exist and print the exact `tuios new` line; then build the pages.
Ours does the host, the refusal and the pages — but **no scaffold**. No per-role files, no `verify.sh`, no page notes. That is the cheapest real gap in the whole plan.
## Dashboard — the API answers it in one call
`GET /api/companies/{id}/dashboard`, 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, utilization 0}
runActivity [14 entries]
```
Proposal: a `Project>overview` panel with those blocks and a sparkline drawn in Go with `tuios.dev/plot`, rather than embedding the web dashboard in a pane.
## Not doing
Artifacts — dropped as instructed.
I am ready for the task you are about to deliver; nothing in the tree is half-changed, the eight workspaces are running, and the last commit is `3d31243`.
## 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-10 10:01:16 -->
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Paperclip per-agent skills state and sync semantics]]
- runbook: [[packs/paperclip-harness/70-runbooks/tmp-deployment-operations|Adopt an existing folder into the harness with `office` (and its known scaffold gap)]]
- decision: [[packs/paperclip-harness/50-decisions/mouse-1-restricted-to-triage-never-a-gate-or-permit|MOUSE-1 restricted to triage; never a gate or permit]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Recorded interface plan for Paperclip + TUIOS harness in docs/PLAN-INTERFACE.md]]
- session: [[packs/paperclip-harness/80-sessions/paperclip-tuios-interface-discovery-skills-api-memory-stack-|Paperclip-TUIOS interface discovery: skills API, memory stack, MOUSE-1, dashboard, old office scaffold]]
- context: [[packs/paperclip-harness/20-context/paperclip-tuios-harness-sam-s-coding-harness-office-board-wo|Paperclip-TUIOS harness (sam's coding harness: office/board/work screens)]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-paperclipai-2026-11-10-10-01-16|Rich discovery: paperclipai 2026-11-10 10:01:16]]
- context: [[packs/paperclip-harness/20-context/home|paperclipai]]

View File

@@ -58,12 +58,12 @@ program running in the Board workspace.
| Workspace>pane | shows | keys |
|---|---|---|
| Shell>shell | a prompt in the project folder | — |
| Shell>shell | a prompt in the project folder: the pane that never exits, and the escape hatch for anything no panel covers | — |
| Board>board | tasks by group · the chosen task · needs you | ↑↓ j k · enter · a · u · / · t (tools) · tab |
| Work>work | runs · change · facts · review | [ ] tab · ↑↓ j k · g G · 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 | facts · costs · settings | [ ] tab · ↑↓ j k |
| 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 |
@@ -73,7 +73,9 @@ Choosing a task on the board and pressing Enter writes it into the project's
### Tool panes
`t` in `Board>board` or `Work>work` opens a chooser: shell, Lazygit, Hunk, Yazi, Neovim,
fzf, ocr. The tool opens as a pane beside the one you are in, in the same workspace, and
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.

Binary file not shown.

View File

@@ -6,7 +6,16 @@ panels are what the pane's program draws, switched with Tab or the tab keys.
Status: **built** means running in the project session now. **missing** means planned, not
written yet.
## 1. Shell
## 1. Shell — a plain prompt in the project folder
It is not a screen of the factory. It is there because some things are quicker to type than
to click, and because every workspace needs one pane that never exits: TUIOS deletes a
workspace whose last pane closes and renumbers the rest. It is also the fallback for a
command no panel covers, and the place a tool pane is opened *from* when you know what you
want.
There is deliberately nothing in it beyond your own shell, in the project folder, so that
what it shows is never a second copy of anything.
| Pane | Shows | Status |
|---|---|---|
@@ -58,7 +67,7 @@ written yet.
| Pane | Shows | Status |
|---|---|---|
| `Project>project` | project, folder, machine, session, agents | built |
| `Project>project` | overview: agents, tasks, money, run activity sparkline — then facts, costs, settings | built |
| `Project>costs` | spend per task and the total | built |
| `Project>settings` | the project's own file, and the limits Paperclip holds | built |

View File

@@ -355,6 +355,17 @@ func (m boardModel) View() string {
m.width, m.height))
}
if m.tools {
entries := make([][2]string, 0, len(tools))
for i, t := range tools {
mark := " "
if i == m.toolAt {
mark = "▸ "
}
entries = append(entries, [2]string{mark + t.name, t.about})
}
return helpOverlay("open a tool pane here", entries, m.width, m.height)
}
if m.showHelp {
return helpOverlay("keys on this panel", [][2]string{
{"↑ ↓ j k", "choose a task"},
@@ -517,7 +528,10 @@ func (m boardModel) treeLines(width int) []string {
// makes the groups visible at a glance without a box around every one.
func groupHeading(name string, count, width int) string {
label := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color(active.Mauve)).Render(strings.ToUpper(name))
n := lipgloss.NewStyle().Foreground(lipgloss.Color(active.Muted)).Render(fmt.Sprintf(" %d ", count))
n := ""
if count >= 0 {
n = lipgloss.NewStyle().Foreground(lipgloss.Color(active.Muted)).Render(fmt.Sprintf(" %d ", count))
}
rule := strings.Repeat("─", max(0, width-lipgloss.Width(label)-lipgloss.Width(n)))
return label + dimStyle().Render(rule) + n
}

View File

@@ -458,3 +458,44 @@ func (c *Client) AgentRaw(agentID string) (map[string]any, error) {
err := c.do("GET", "/api/agents/"+agentID, nil, &out)
return out, err
}
// Dashboard is the company's own summary: counts, spend and recent run activity.
// One call, 1.8 KB, cheap enough to poll.
type Dashboard struct {
Agents struct {
Active int `json:"active"`
Running int `json:"running"`
Paused int `json:"paused"`
Error int `json:"error"`
} `json:"agents"`
Tasks struct {
Open int `json:"open"`
InProgress int `json:"inProgress"`
Blocked int `json:"blocked"`
Done int `json:"done"`
} `json:"tasks"`
Costs struct {
MonthSpendCents int `json:"monthSpendCents"`
MonthBudgetCents int `json:"monthBudgetCents"`
MonthUtilizationPercent float64 `json:"monthUtilizationPercent"`
} `json:"costs"`
PendingApprovals int `json:"pendingApprovals"`
Budgets struct {
ActiveIncidents int `json:"activeIncidents"`
PausedAgents int `json:"pausedAgents"`
PausedProjects int `json:"pausedProjects"`
} `json:"budgets"`
RunActivity []struct {
Date string `json:"date"`
Total int `json:"total"`
Succeeded int `json:"succeeded"`
Failed int `json:"failed"`
} `json:"runActivity"`
}
// DashboardSummary reads the company's dashboard.
func (c *Client) DashboardSummary() (Dashboard, error) {
var out Dashboard
err := c.do("GET", "/api/companies/"+c.Company+"/dashboard", nil, &out)
return out, err
}

View File

@@ -19,6 +19,7 @@ import (
)
type projectMsg struct {
dash paperclip.Dashboard
project paperclip.Project
cfg map[string]string
agents []paperclip.Agent
@@ -38,6 +39,7 @@ type projectModel struct {
client *paperclip.Client
folder string
dash paperclip.Dashboard
project paperclip.Project
cfg map[string]string
agents []paperclip.Agent
@@ -53,7 +55,7 @@ type projectModel struct {
width, height int
}
var projectTabs = []string{"facts", "costs", "settings"}
var projectTabs = []string{"overview", "facts", "costs", "settings"}
func newProjectModel(c *paperclip.Client, folder string) projectModel {
return projectModel{client: c, folder: folder}
@@ -96,7 +98,8 @@ func (m projectModel) load() tea.Cmd {
}
costs = append(costs, taskCost{t.Identifier, t.Status, cost.CostCents, cost.RunCount})
}
return projectMsg{project: proj, cfg: cfg, agents: agents, costs: costs}
dash, _ := c.DashboardSummary()
return projectMsg{project: proj, cfg: cfg, agents: agents, costs: costs, dash: dash}
}
}
@@ -182,6 +185,7 @@ func (m projectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
case projectMsg:
m.dash = msg.dash
m.project = msg.project
m.cfg = msg.cfg
m.agents = msg.agents
@@ -225,8 +229,10 @@ func (m projectModel) View() string {
var body []string
switch m.tab {
case 0:
body = m.factLines()
body = m.overviewLines(m.width - 4)
case 1:
body = m.factLines()
case 2:
body = m.costLines()
default:
body = m.settingLines()
@@ -268,6 +274,82 @@ func (m projectModel) row(label, value string) string {
lipgloss.NewStyle().Foreground(lipgloss.Color(active.Text)).Render(value)
}
// overviewLines is the company dashboard, drawn as numbers a person can act on
// and a sparkline of the last two weeks of runs. Everything here comes from
// GET /api/companies/{id}/dashboard in one call.
func (m projectModel) overviewLines(width int) []string {
d := m.dash
out := []string{"", groupHeading("agents", -1, width), ""}
out = append(out, " "+stat("active", d.Agents.Active, active.Text)+
" "+stat("running", d.Agents.Running, active.Info)+
" "+stat("paused", d.Agents.Paused, active.Warning)+
" "+stat("error", d.Agents.Error, active.Error))
out = append(out, "", groupHeading("tasks", -1, width), "")
out = append(out, " "+stat("open", d.Tasks.Open, active.Text)+
" "+stat("in progress", d.Tasks.InProgress, active.Info)+
" "+stat("blocked", d.Tasks.Blocked, active.Error)+
" "+stat("done", d.Tasks.Done, active.Success))
out = append(out, "", groupHeading("money, this month", -1, width), "")
budget := "no company budget set"
if d.Costs.MonthBudgetCents > 0 {
budget = fmt.Sprintf("%.0f%% of %d cents", d.Costs.MonthUtilizationPercent, d.Costs.MonthBudgetCents)
}
out = append(out, " "+stat("cents spent", d.Costs.MonthSpendCents, active.Text)+" "+
mutedStyle2().Render(budget))
out = append(out, " "+stat("pending approvals", d.PendingApprovals, active.Warning))
if d.Budgets.ActiveIncidents > 0 || d.Budgets.PausedAgents > 0 || d.Budgets.PausedProjects > 0 {
out = append(out, " "+stat("budget incidents", d.Budgets.ActiveIncidents, active.Error)+
mutedStyle2().Render(fmt.Sprintf(" paused: %d agent(s), %d project(s)",
d.Budgets.PausedAgents, d.Budgets.PausedProjects)))
}
out = append(out, "", groupHeading("runs, last two weeks", -1, width), "")
out = append(out, " "+sparkline(d.RunActivity))
if n := len(d.RunActivity); n > 0 {
first, last := d.RunActivity[0].Date, d.RunActivity[n-1].Date
out = append(out, dimStyle().Render(" "+first+" → "+last+" one bar per day, taller is more runs"))
}
out = append(out, "")
out = append(out, dimStyle().Render(" read from Paperclip's own dashboard, not counted here."))
return out
}
// stat is a label and a number, the number first because it is what you look at.
func stat(label string, value int, colour string) string {
return lipgloss.NewStyle().Foreground(lipgloss.Color(colour)).Bold(true).Render(fmt.Sprintf("%d", value)) +
" " + mutedStyle2().Render(label)
}
// sparkline draws one bar per day using block characters, scaled so the busiest
// day fills the height. No chart library, no second language: the data is in
// memory and the terminal already knows how to draw blocks.
func sparkline(points []struct {
Date string `json:"date"`
Total int `json:"total"`
Succeeded int `json:"succeeded"`
Failed int `json:"failed"`
}) string {
bars := []rune("▁▂▃▄▅▆▇█")
peak := 0
for _, p := range points {
if p.Total > peak {
peak = p.Total
}
}
if peak == 0 {
return mutedStyle2().Render("no runs in the last two weeks")
}
var b strings.Builder
for _, p := range points {
idx := int(float64(p.Total) / float64(peak) * float64(len(bars)-1))
colour := active.Success
if p.Failed > 0 {
colour = active.Warning
}
b.WriteString(lipgloss.NewStyle().Foreground(lipgloss.Color(colour)).Render(string(bars[idx])))
}
return b.String()
}
func (m projectModel) factLines() []string {
out := []string{""}
if m.project.Name != "" {