Work>review and tool panes; panes re-sync their size; the Work pane follows the Board again

This commit is contained in:
Sam
2026-11-10 18:06:07 +11:00
parent ec7e907b2e
commit 4a23f05d20
18 changed files with 884 additions and 25 deletions

View File

@@ -0,0 +1,78 @@
---
type: context
id: context.paperclip-harness.both-defects-fixed-and-the-settings-editor-is-in
title: both-defects-fixed-and-the-settings-editor-is-in
status: active
source_of_truth: false
freshness: current
last_reviewed: 2026-11-10
tags:
- pack/paperclip-harness
- agent-memory/context
- autolearn
- rich-discovery
- repo/both-defects-fixed-and-the-settings-editor-is-in
---
# both-defects-fixed-and-the-settings-editor-is-in
## Rich discovery update (2026-11-10 06:23:51)
Both defects fixed, and the settings editor is in.
## The three things you reported
**Runs were every run in Paperclip.** Correct — 281 company-wide. They are now scoped to this project's tasks, resolved through each run's own task reference, and the task column shows `AUD-166` instead of a bare identifier. `A` toggles between "this project" and "everything in the company", because both are legitimate questions but not the same one.
**Scrolling instead of selecting.** The run list had no cursor at all — arrows only moved the viewport. There is now one cursor per tab, the selected row is highlighted, and the list scrolls only to keep the cursor visible. `enter` opens that run's log. Tested: picked the second run, its log opened.
**Roster could not be walked.** Same cause, same fix. The roster is sorted by name so the cursor stays on the same agent after a reload, and `▸` marks the row.
The log itself also became readable: it is a stream of token deltas, so deltas are gathered back into paragraphs while tool calls, prompts and turn markers become single lines:
```
15:55:57 toolcall_start
15:55:57 {"command": "pwd && ls -la && git log --oneline -10 2>/dev/null"}
15:55:58 toolcall_end
15:55:58 assistant: I'll start by inspecting the workspace…
```
## Agents>settings is built
Fourth tab. Role, job title, model, monthly budget, heartbeat. `enter` edits the chosen field inline, `esc` cancels; heartbeat is a toggle. Every save is one `PATCH /api/agents/{id}` that merges into that agent's existing configuration, so a model change does not wipe its working folder or instructions — verified by reading the record back after a save.
`p`, `P`, `w` pause, resume and wake, acting on the agent chosen on that tab.
**One thing you should know:** `Builder` was paused at 16:56 with `pauseReason: manual`, from the board key — that was my keystroke test, not you. I have resumed it and it is idle again. Sorry for the scare.
## Still missing, in order
1. **Work>review** — the ocr verdict beside the diff. That is now the only missing panel.
2. **Tool panes** — `t` opens Lazygit, Hunk, Yazi, Neovim, fzf or ocr in the current workspace; `esc` closes it.
`docs/WORKSPACES.md` is updated: 22 panels built across 8 workspaces, one panel missing, six tool panes to wire. Committed as `ec7e907`.
Which of those two next?
## Source paths observed
- `omni/deepseek/deepseek-v4-flash`
## Evidence
- Confidence: 84%
- Reason: Update component/repository context with detailed discovered structure and configuration
## Related
- [[packs/paperclip-harness/00-system/pi-agent/memory-manifest|Memory Manifest]]
## Related learned memories <!-- same-turn-2026-11-10 06:23:51 -->
- context: [[packs/paperclip-harness/20-context/tmp|Paperclip TUI Agents pane]]
- context: [[packs/paperclip-harness/20-context/paperclip-tui-workspaces-panels-and-tools-status|Paperclip TUI workspaces/panels and tools status]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Agents pane defect causes: missing cursors, unscoped runs]]
- runbook: [[packs/paperclip-harness/70-runbooks/editing-agent-settings-and-pausing-resuming-in-tui|Editing agent settings and pausing/resuming in TUI]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Agents pane: scoped runs, cursors, settings editor]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-both-defects-fixed-and-the-settings-editor-is|Rich discovery: both-defects-fixed-and-the-settings-editor-is-in 2026-11-10 06:23:51]]
- context: [[packs/paperclip-harness/20-context/both-defects-fixed-and-the-settings-editor-is-in|both-defects-fixed-and-the-settings-editor-is-in]]

View File

@@ -0,0 +1,85 @@
---
type: context
id: context.paperclip-harness.paperclip-tui-workspaces-panels-and-tools-status
title: Paperclip TUI workspaces/panels and tools status
status: active
source_of_truth: false
freshness: current
last_reviewed: 2026-11-10
tags:
- pack/paperclip-harness
- agent-memory/context
- paperclip
- tui
- workspaces
- panels
- docs
- ocr
---
# Paperclip TUI workspaces/panels and tools status
Paperclip TUI organizes UI into workspaces containing panels. As of commit `ec7e907` (`docs/WORKSPACES.md`): **22 panels built across 8 workspaces**, with **one panel missing** and **six tool panes** still to wire.
Remaining work:
1. **Work>review** — the ocr verdict shown beside the diff. This is the only missing panel.
2. **Tool panes** — `t` opens Lazygit, Hunk, Yazi, Neovim, fzf, or ocr in the current workspace; `esc` closes it. The six tools: Lazygit, Hunk, Yazi, Neovim, fzf, ocr.
`docs/WORKSPACES.md` is the tracking doc for panel/tool-workspace status and should be updated as panels are built.
## Detailed context from completed turn
Both defects fixed, and the settings editor is in.
## The three things you reported
**Runs were every run in Paperclip.** Correct — 281 company-wide. They are now scoped to this project's tasks, resolved through each run's own task reference, and the task column shows `AUD-166` instead of a bare identifier. `A` toggles between "this project" and "everything in the company", because both are legitimate questions but not the same one.
**Scrolling instead of selecting.** The run list had no cursor at all — arrows only moved the viewport. There is now one cursor per tab, the selected row is highlighted, and the list scrolls only to keep the cursor visible. `enter` opens that run's log. Tested: picked the second run, its log opened.
**Roster could not be walked.** Same cause, same fix. The roster is sorted by name so the cursor stays on the same agent after a reload, and `▸` marks the row.
The log itself also became readable: it is a stream of token deltas, so deltas are gathered back into paragraphs while tool calls, prompts and turn markers become single lines:
```
15:55:57 toolcall_start
15:55:57 {"command": "pwd && ls -la && git log --oneline -10 2>/dev/null"}
15:55:58 toolcall_end
15:55:58 assistant: I'll start by inspecting the workspace…
```
## Agents>settings is built
Fourth tab. Role, job title, model, monthly budget, heartbeat. `enter` edits the chosen field inline, `esc` cancels; heartbeat is a toggle. Every save is one `PATCH /api/agents/{id}` that merges into that agent's existing configuration, so a model change does not wipe its working folder or instructions — verified by reading the record back after a save.
`p`, `P`, `w` pause, resume and wake, acting on the agent chosen on that tab.
**One thing you should know:** `Builder` was paused at 16:56 with `pauseReason: manual`, from the board key — that was my keystroke test, not you. I have resumed it and it is idle again. Sorry for the scare.
## Still missing, in order
1. **Work>review** — the ocr verdict beside the diff. That is now the only missing panel.
2. **Tool panes** — `t` opens Lazygit, Hunk, Yazi, Neovim, fzf or ocr in the current workspace; `esc` closes it.
`docs/WORKSPACES.md` is updated: 22 panels built across 8 workspaces, one panel missing, six tool panes to wire. Committed as `ec7e907`.
Which of those two next?
## Evidence
- Confidence: 80%
- Reason: Architecture/status details from final summary and commit reference; useful for future work on remaining panels.; 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 06:23:51 -->
- context: [[packs/paperclip-harness/20-context/tmp|Paperclip TUI Agents pane]]
- context: [[packs/paperclip-harness/20-context/paperclip-tui-workspaces-panels-and-tools-status|Paperclip TUI workspaces/panels and tools status]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Agents pane defect causes: missing cursors, unscoped runs]]
- runbook: [[packs/paperclip-harness/70-runbooks/editing-agent-settings-and-pausing-resuming-in-tui|Editing agent settings and pausing/resuming in TUI]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Agents pane: scoped runs, cursors, settings editor]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-both-defects-fixed-and-the-settings-editor-is|Rich discovery: both-defects-fixed-and-the-settings-editor-is-in 2026-11-10 06:23:51]]
- context: [[packs/paperclip-harness/20-context/both-defects-fixed-and-the-settings-editor-is-in|both-defects-fixed-and-the-settings-editor-is-in]]

View File

@@ -466,3 +466,33 @@ Say which of the three you want next, and I will build only that.
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-the-full-list-at-the-end-of-the-project-with-|Rich discovery: the-full-list-at-the-end-of-the-project-with-what-exists-tod 2026-11-10 05:59:07]]
- context: [[packs/paperclip-harness/20-context/tmp|the-full-list-at-the-end-of-the-project-with-what-exists-tod]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|the-full-list-at-the-end-of-the-project-with-what-exists-tod repository structure and configuration patterns]]
---
## Update (2026-11-10 06:23:51)
The Paperclip terminal UI (TUI) has an "Agents" pane with four tabs: roster, runs, log, and settings. It tracks agents (researcher, System, Hub, Chief of Staff, Builder, Documenter), their states (idle/paused), spend vs. budget, and run history.
Key behaviors:
- **runs tab**: project-scoped to the current project's tasks by default (resolved through each run's task reference, shown as e.g. `AUD-166`). `A` toggles between "this project" and company-wide runs. Company-wide total at time of work: 281 runs.
- **log tab**: renders run logs. Logs are a stream of token deltas; the viewer merges deltas into paragraphs while tool calls, prompts, and turn markers each become single lines (e.g. `toolcall_start`, `toolcall_end`, `assistant:` lines).
- **settings tab**: editable fields for each agent — role, job title, model, monthly budget, heartbeat. `enter` edits a field inline, `esc` cancels, heartbeat is a toggle. Saves go through one `PATCH /api/agents/{id}` that merges into the agent's existing config (does not wipe working folder or instructions). `p`/`P`/`w` pause/resume/wake the selected agent.
- **Navigation**: each tab has its own cursor; `enter` opens detail (e.g. run log). Roster is sorted by name so cursor stays on the same agent after reload; `▸` marks the selected row.
The pause control writes `pausedAt` and `pauseReason` (e.g. `manual` from a board key) to the agent status.
## Evidence
- Confidence: 85%
- Reason: Evidence-backed overview of the Agents pane architecture and behaviors from the turn's tool output and final summary.
## Related learned memories <!-- same-turn-2026-11-10 06:23:51 -->
- context: [[packs/paperclip-harness/20-context/tmp|Paperclip TUI Agents pane]]
- context: [[packs/paperclip-harness/20-context/paperclip-tui-workspaces-panels-and-tools-status|Paperclip TUI workspaces/panels and tools status]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Agents pane defect causes: missing cursors, unscoped runs]]
- runbook: [[packs/paperclip-harness/70-runbooks/editing-agent-settings-and-pausing-resuming-in-tui|Editing agent settings and pausing/resuming in TUI]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Agents pane: scoped runs, cursors, settings editor]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-both-defects-fixed-and-the-settings-editor-is|Rich discovery: both-defects-fixed-and-the-settings-editor-is-in 2026-11-10 06:23:51]]
- context: [[packs/paperclip-harness/20-context/both-defects-fixed-and-the-settings-editor-is-in|both-defects-fixed-and-the-settings-editor-is-in]]

View File

@@ -280,3 +280,35 @@ Follow-up: user asked to pick item 1..5; only build the chosen item.
- 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 06:23:51)
Delivered and committed (`ec7e907`: "Agents pane: project-scoped runs with selection, roster cursor, editable settings").
Changes:
- Runs tab now project-scoped by default with task column, `A` toggles company-wide.
- Added per-tab cursors for runs and roster; `enter` opens the selected run's log; selection highlighted, scroll-follows-cursor.
- Log viewer now merges token deltas into paragraphs; tool calls/prompts/turn markers as single lines.
- New settings tab (4th tab): edit role, job title, model, monthly budget, heartbeat via inline edit (`enter` saves, `esc` cancels, heartbeat toggle). Saves are single `PATCH /api/agents/{id}` merging into existing config; verified config preserved after save.
- `p`/`P`/`w` pause/resume/wake act on the selected agent.
- Updated `docs/WORKSPACES.md` (22 panels across 8 workspaces, 1 missing panel, 6 tool panes to wire).
Validation: build passed (`build=0`); manual tests of run selection/open, settings edit/save, and pause/resume round-trip.
## Evidence
- Confidence: 90%
- Reason: Completed, verified deliverable with commit hash, artifacts, and validation.
## Related learned memories <!-- same-turn-2026-11-10 06:23:51 -->
- context: [[packs/paperclip-harness/20-context/tmp|Paperclip TUI Agents pane]]
- context: [[packs/paperclip-harness/20-context/paperclip-tui-workspaces-panels-and-tools-status|Paperclip TUI workspaces/panels and tools status]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Agents pane defect causes: missing cursors, unscoped runs]]
- runbook: [[packs/paperclip-harness/70-runbooks/editing-agent-settings-and-pausing-resuming-in-tui|Editing agent settings and pausing/resuming in TUI]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Agents pane: scoped runs, cursors, settings editor]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-both-defects-fixed-and-the-settings-editor-is|Rich discovery: both-defects-fixed-and-the-settings-editor-is-in 2026-11-10 06:23:51]]
- context: [[packs/paperclip-harness/20-context/both-defects-fixed-and-the-settings-editor-is-in|both-defects-fixed-and-the-settings-editor-is-in]]

View File

@@ -979,3 +979,172 @@ Say which of the three you want next, and I will build only that.
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-the-full-list-at-the-end-of-the-project-with-|Rich discovery: the-full-list-at-the-end-of-the-project-with-what-exists-tod 2026-11-10 05:59:07]]
- context: [[packs/paperclip-harness/20-context/tmp|the-full-list-at-the-end-of-the-project-with-what-exists-tod]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|the-full-list-at-the-end-of-the-project-with-what-exists-tod repository structure and configuration patterns]]
---
## Update (2026-11-10 06:23:51)
Three defects were diagnosed in the Paperclip TUI Agents pane:
- **Runs list was company-wide** (281 runs) instead of project-scoped; fixed by resolving each run's task reference to the current project and showing the task ID (e.g. `AUD-166`). Added `A` to toggle project/all scope.
- **Scrolling instead of selecting** (runs tab): the list had no cursor, so arrow keys only moved the viewport. Fix: per-tab cursor, highlighted selection row, scroll only to keep cursor visible. `enter` opens the selected run's log.
- **Roster could not be walked**: same root cause (no cursor); fixed with per-tab cursor and name-sorted roster so selection is stable across reloads.
Also fixed log readability: raw token-delta stream was gathered into paragraphs while tool calls/prompts/turn markers became single lines.
## Detailed observations from completed turn
Both defects fixed, and the settings editor is in.
## The three things you reported
**Runs were every run in Paperclip.** Correct — 281 company-wide. They are now scoped to this project's tasks, resolved through each run's own task reference, and the task column shows `AUD-166` instead of a bare identifier. `A` toggles between "this project" and "everything in the company", because both are legitimate questions but not the same one.
**Scrolling instead of selecting.** The run list had no cursor at all — arrows only moved the viewport. There is now one cursor per tab, the selected row is highlighted, and the list scrolls only to keep the cursor visible. `enter` opens that run's log. Tested: picked the second run, its log opened.
**Roster could not be walked.** Same cause, same fix. The roster is sorted by name so the cursor stays on the same agent after a reload, and `▸` marks the row.
The log itself also became readable: it is a stream of token deltas, so deltas are gathered back into paragraphs while tool calls, prompts and turn markers become single lines:
```
15:55:57 toolcall_start
15:55:57 {"command": "pwd && ls -la && git log --oneline -10 2>/dev/null"}
15:55:58 toolcall_end
15:55:58 assistant: I'll start by inspecting the workspace…
```
## Agents>settings is built
Fourth tab. Role, job title, model, monthly budget, heartbeat. `enter` edits the chosen field inline, `esc` cancels; heartbeat is a toggle. Every save is one `PATCH /api/agents/{id}` that merges into that agent's existing configuration, so a model change does not wipe its working folder or instructions — verified by reading the record back after a save.
`p`, `P`, `w` pause, resume and wake, acting on the agent chosen on that tab.
**One thing you should know:** `Builder` was paused at 16:56 with `pauseReason: manual`, from the board key — that was my keystroke test, not you. I have resumed it and it is idle again. Sorry for the scare.
## Still missing, in order
1. **Work>review** — the ocr verdict beside the diff. That is now the only missing panel.
2. **Tool panes** — `t` opens Lazygit, Hunk, Yazi, Neovim, fzf or ocr in the current workspace; `esc` closes it.
`docs/WORKSPACES.md` is updated: 22 panels built across 8 workspaces, one panel missing, six tool panes to wire. Committed as `ec7e907`.
Which of those two next?
## Evidence
- Confidence: 85%
- Reason: Diagnosis and root-cause findings from tool output and summary; valuable for future Agents pane work.; enriched with final-answer detail because persistence should be reusable
---
## Update (2026-11-10 06:23:51)
The Builder agent was observed paused with `status: paused pausedAt: 2026-11-10T05:56:47.518Z reason: manual`, caused by a keystroke test on the board key (not the user). Resuming via the pause/resume control returned HTTP 200 and the agent returned to `status: idle`.
Caveat for future agents: pause/resume/wake keys (`p`/`P`/`w`) act on the currently selected agent and can unintentionally pause a live agent; always confirm the selection before keying. Pause state persists in agent status and can be resumed via the same control.
## Detailed observations from completed turn
Both defects fixed, and the settings editor is in.
## The three things you reported
**Runs were every run in Paperclip.** Correct — 281 company-wide. They are now scoped to this project's tasks, resolved through each run's own task reference, and the task column shows `AUD-166` instead of a bare identifier. `A` toggles between "this project" and "everything in the company", because both are legitimate questions but not the same one.
**Scrolling instead of selecting.** The run list had no cursor at all — arrows only moved the viewport. There is now one cursor per tab, the selected row is highlighted, and the list scrolls only to keep the cursor visible. `enter` opens that run's log. Tested: picked the second run, its log opened.
**Roster could not be walked.** Same cause, same fix. The roster is sorted by name so the cursor stays on the same agent after a reload, and `▸` marks the row.
The log itself also became readable: it is a stream of token deltas, so deltas are gathered back into paragraphs while tool calls, prompts and turn markers become single lines:
```
15:55:57 toolcall_start
15:55:57 {"command": "pwd && ls -la && git log --oneline -10 2>/dev/null"}
15:55:58 toolcall_end
15:55:58 assistant: I'll start by inspecting the workspace…
```
## Agents>settings is built
Fourth tab. Role, job title, model, monthly budget, heartbeat. `enter` edits the chosen field inline, `esc` cancels; heartbeat is a toggle. Every save is one `PATCH /api/agents/{id}` that merges into that agent's existing configuration, so a model change does not wipe its working folder or instructions — verified by reading the record back after a save.
`p`, `P`, `w` pause, resume and wake, acting on the agent chosen on that tab.
**One thing you should know:** `Builder` was paused at 16:56 with `pauseReason: manual`, from the board key — that was my keystroke test, not you. I have resumed it and it is idle again. Sorry for the scare.
## Still missing, in order
1. **Work>review** — the ocr verdict beside the diff. That is now the only missing panel.
2. **Tool panes** — `t` opens Lazygit, Hunk, Yazi, Neovim, fzf or ocr in the current workspace; `esc` closes it.
`docs/WORKSPACES.md` is updated: 22 panels built across 8 workspaces, one panel missing, six tool panes to wire. Committed as `ec7e907`.
Which of those two next?
## Evidence
- Confidence: 80%
- Reason: Concrete observed state, API behavior, and operational caveat.; enriched with final-answer detail because persistence should be reusable
---
## Update (2026-11-10 06:23:51)
## Structural/configuration observations (2026-11-10 06:23:51)
Both defects fixed, and the settings editor is in.
## The three things you reported
**Runs were every run in Paperclip.** Correct — 281 company-wide. They are now scoped to this project's tasks, resolved through each run's own task reference, and the task column shows `AUD-166` instead of a bare identifier. `A` toggles between "this project" and "everything in the company", because both are legitimate questions but not the same one.
**Scrolling instead of selecting.** The run list had no cursor at all — arrows only moved the viewport. There is now one cursor per tab, the selected row is highlighted, and the list scrolls only to keep the cursor visible. `enter` opens that run's log. Tested: picked the second run, its log opened.
**Roster could not be walked.** Same cause, same fix. The roster is sorted by name so the cursor stays on the same agent after a reload, and `▸` marks the row.
The log itself also became readable: it is a stream of token deltas, so deltas are gathered back into paragraphs while tool calls, prompts and turn markers become single lines:
```
15:55:57 toolcall_start
15:55:57 {"command": "pwd && ls -la && git log --oneline -10 2>/dev/null"}
15:55:58 toolcall_end
15:55:58 assistant: I'll start by inspecting the workspace…
```
## Agents>settings is built
Fourth tab. Role, job title, model, monthly budget, heartbeat. `enter` edits the chosen field inline, `esc` cancels; heartbeat is a toggle. Every save is one `PATCH /api/agents/{id}` that merges into that agent's existing configuration, so a model change does not wipe its working folder or instructions — verified by reading the record back after a save.
`p`, `P`, `w` pause, resume and wake, acting on the agent chosen on that tab.
**One thing you should know:** `Builder` was paused at 16:56 with `pauseReason: manual`, from the board key — that was my keystroke test, not you. I have resumed it and it is idle again. Sorry for the scare.
## Still missing, in order
1. **Work>review** — the ocr verdict beside the diff. That is now the only missing panel.
2. **Tool panes** — `t` opens Lazygit, Hunk, Yazi, Neovim, fzf or ocr in the current workspace; `esc` closes it.
`docs/WORKSPACES.md` is updated: 22 panels built across 8 workspaces, one panel missing, six tool panes to wire. Committed as `ec7e907`.
Which of those two next?
## Source paths observed
- `omni/deepseek/deepseek-v4-flash`
## Evidence
- Confidence: 82%
- Reason: Captured factual repo structure/configuration patterns from rich discovery
## Related learned memories <!-- same-turn-2026-11-10 06:23:51 -->
- context: [[packs/paperclip-harness/20-context/tmp|Paperclip TUI Agents pane]]
- context: [[packs/paperclip-harness/20-context/paperclip-tui-workspaces-panels-and-tools-status|Paperclip TUI workspaces/panels and tools status]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Agents pane defect causes: missing cursors, unscoped runs]]
- runbook: [[packs/paperclip-harness/70-runbooks/editing-agent-settings-and-pausing-resuming-in-tui|Editing agent settings and pausing/resuming in TUI]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Agents pane: scoped runs, cursors, settings editor]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-both-defects-fixed-and-the-settings-editor-is|Rich discovery: both-defects-fixed-and-the-settings-editor-is-in 2026-11-10 06:23:51]]
- context: [[packs/paperclip-harness/20-context/both-defects-fixed-and-the-settings-editor-is-in|both-defects-fixed-and-the-settings-editor-is-in]]

View File

@@ -0,0 +1,90 @@
---
type: runbook
id: runbook.paperclip-harness.editing-agent-settings-and-pausing-resuming-in-tui
title: Editing agent settings and pausing/resuming in TUI
status: active
source_of_truth: false
freshness: current
last_reviewed: 2026-11-10
tags:
- pack/paperclip-harness
- agent-memory/runbook
- paperclip
- tui
- runbook
- agents
- settings
- pause
---
# Editing agent settings and pausing/resuming in TUI
Trigger: need to change an agent's role/job title/model/budget/heartbeat, or pause/resume/wake an agent via the Paperclip TUI.
Prerequisites: TUI running, Agents pane available.
Procedure:
1. Navigate to Agents>settings tab.
2. Move cursor to the target agent on the roster; confirm `▸` is on the intended row (pause keys act on the selected agent — misselection can pause a live agent).
3. `enter` on a field to edit inline; type value; `enter` saves, `esc` cancels. Heartbeat is a toggle.
4. Save issues a single `PATCH /api/agents/{id}` that merges into existing config (does not wipe working folder/instructions). Model change applies to the agent's next run, not an in-flight run.
5. To pause/resume/wake the selected agent press `p` / `P` / `w` respectively.
Verification / rollback: read the agent record back after saving to confirm fields persisted. If you accidentally pause an agent, resume with `P`; expect resume to return HTTP 200 and status to return to idle.
## Detailed procedure from completed turn
Both defects fixed, and the settings editor is in.
## The three things you reported
**Runs were every run in Paperclip.** Correct — 281 company-wide. They are now scoped to this project's tasks, resolved through each run's own task reference, and the task column shows `AUD-166` instead of a bare identifier. `A` toggles between "this project" and "everything in the company", because both are legitimate questions but not the same one.
**Scrolling instead of selecting.** The run list had no cursor at all — arrows only moved the viewport. There is now one cursor per tab, the selected row is highlighted, and the list scrolls only to keep the cursor visible. `enter` opens that run's log. Tested: picked the second run, its log opened.
**Roster could not be walked.** Same cause, same fix. The roster is sorted by name so the cursor stays on the same agent after a reload, and `▸` marks the row.
The log itself also became readable: it is a stream of token deltas, so deltas are gathered back into paragraphs while tool calls, prompts and turn markers become single lines:
```
15:55:57 toolcall_start
15:55:57 {"command": "pwd && ls -la && git log --oneline -10 2>/dev/null"}
15:55:58 toolcall_end
15:55:58 assistant: I'll start by inspecting the workspace…
```
## Agents>settings is built
Fourth tab. Role, job title, model, monthly budget, heartbeat. `enter` edits the chosen field inline, `esc` cancels; heartbeat is a toggle. Every save is one `PATCH /api/agents/{id}` that merges into that agent's existing configuration, so a model change does not wipe its working folder or instructions — verified by reading the record back after a save.
`p`, `P`, `w` pause, resume and wake, acting on the agent chosen on that tab.
**One thing you should know:** `Builder` was paused at 16:56 with `pauseReason: manual`, from the board key — that was my keystroke test, not you. I have resumed it and it is idle again. Sorry for the scare.
## Still missing, in order
1. **Work>review** — the ocr verdict beside the diff. That is now the only missing panel.
2. **Tool panes** — `t` opens Lazygit, Hunk, Yazi, Neovim, fzf or ocr in the current workspace; `esc` closes it.
`docs/WORKSPACES.md` is updated: 22 panels built across 8 workspaces, one panel missing, six tool panes to wire. Committed as `ec7e907`.
Which of those two next?
## Evidence
- Confidence: 80%
- Reason: Repeatable procedure with a safety caveat learned during the turn.; 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 06:23:51 -->
- context: [[packs/paperclip-harness/20-context/tmp|Paperclip TUI Agents pane]]
- context: [[packs/paperclip-harness/20-context/paperclip-tui-workspaces-panels-and-tools-status|Paperclip TUI workspaces/panels and tools status]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Agents pane defect causes: missing cursors, unscoped runs]]
- runbook: [[packs/paperclip-harness/70-runbooks/editing-agent-settings-and-pausing-resuming-in-tui|Editing agent settings and pausing/resuming in TUI]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Agents pane: scoped runs, cursors, settings editor]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-both-defects-fixed-and-the-settings-editor-is|Rich discovery: both-defects-fixed-and-the-settings-editor-is-in 2026-11-10 06:23:51]]
- context: [[packs/paperclip-harness/20-context/both-defects-fixed-and-the-settings-editor-is-in|both-defects-fixed-and-the-settings-editor-is-in]]

View File

@@ -0,0 +1,81 @@
---
type: session
id: session.paperclip-harness.rich-discovery-both-defects-fixed-and-the-settings-editor-is
title: Rich discovery: both-defects-fixed-and-the-settings-editor-is-in 2026-11-10 06:23:51
status: active
source_of_truth: false
freshness: current
last_reviewed: 2026-11-10
tags:
- pack/paperclip-harness
- agent-memory/session
- autolearn
- rich-discovery
- repo/both-defects-fixed-and-the-settings-editor-is-in
---
# Rich discovery: both-defects-fixed-and-the-settings-editor-is-in 2026-11-10 06:23:51
Sanitized rich discovery snapshot captured automatically from the completed turn.
## Source paths observed
- `omni/deepseek/deepseek-v4-flash`
## Final answer snapshot
Both defects fixed, and the settings editor is in.
## The three things you reported
**Runs were every run in Paperclip.** Correct — 281 company-wide. They are now scoped to this project's tasks, resolved through each run's own task reference, and the task column shows `AUD-166` instead of a bare identifier. `A` toggles between "this project" and "everything in the company", because both are legitimate questions but not the same one.
**Scrolling instead of selecting.** The run list had no cursor at all — arrows only moved the viewport. There is now one cursor per tab, the selected row is highlighted, and the list scrolls only to keep the cursor visible. `enter` opens that run's log. Tested: picked the second run, its log opened.
**Roster could not be walked.** Same cause, same fix. The roster is sorted by name so the cursor stays on the same agent after a reload, and `▸` marks the row.
The log itself also became readable: it is a stream of token deltas, so deltas are gathered back into paragraphs while tool calls, prompts and turn markers become single lines:
```
15:55:57 toolcall_start
15:55:57 {"command": "pwd && ls -la && git log --oneline -10 2>/dev/null"}
15:55:58 toolcall_end
15:55:58 assistant: I'll start by inspecting the workspace…
```
## Agents>settings is built
Fourth tab. Role, job title, model, monthly budget, heartbeat. `enter` edits the chosen field inline, `esc` cancels; heartbeat is a toggle. Every save is one `PATCH /api/agents/{id}` that merges into that agent's existing configuration, so a model change does not wipe its working folder or instructions — verified by reading the record back after a save.
`p`, `P`, `w` pause, resume and wake, acting on the agent chosen on that tab.
**One thing you should know:** `Builder` was paused at 16:56 with `pauseReason: manual`, from the board key — that was my keystroke test, not you. I have resumed it and it is idle again. Sorry for the scare.
## Still missing, in order
1. **Work>review** — the ocr verdict beside the diff. That is now the only missing panel.
2. **Tool panes** — `t` opens Lazygit, Hunk, Yazi, Neovim, fzf or ocr in the current workspace; `esc` closes it.
`docs/WORKSPACES.md` is updated: 22 panels built across 8 workspaces, one panel missing, six tool panes to wire. Committed as `ec7e907`.
Which of those two next?
## 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 06:23:51 -->
- context: [[packs/paperclip-harness/20-context/tmp|Paperclip TUI Agents pane]]
- context: [[packs/paperclip-harness/20-context/paperclip-tui-workspaces-panels-and-tools-status|Paperclip TUI workspaces/panels and tools status]]
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|Agents pane defect causes: missing cursors, unscoped runs]]
- runbook: [[packs/paperclip-harness/70-runbooks/editing-agent-settings-and-pausing-resuming-in-tui|Editing agent settings and pausing/resuming in TUI]]
- action: [[packs/paperclip-harness/40-actions/2026-11-10-wrote-docs-ui-layout-md-and-three-live-layout-mockups|Agents pane: scoped runs, cursors, settings editor]]
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-both-defects-fixed-and-the-settings-editor-is|Rich discovery: both-defects-fixed-and-the-settings-editor-is-in 2026-11-10 06:23:51]]
- context: [[packs/paperclip-harness/20-context/both-defects-fixed-and-the-settings-editor-is-in|both-defects-fixed-and-the-settings-editor-is-in]]

View File

@@ -59,16 +59,24 @@ program running in the Board workspace.
| Workspace>pane | shows | keys |
|---|---|---|
| Shell>shell | a prompt in the project folder | — |
| Board>board | tasks by group · the chosen task · needs you | ↑↓ j k · enter · a · u · / · tab |
| Work>work | runs · change · facts | [ ] tab · ↑↓ j k · g G |
| 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 |
| 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. 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

Binary file not shown.

View File

@@ -27,7 +27,7 @@ written yet.
| `Work>runs` | run timeline and activity, with cost per run | built |
| `Work>change` | worktree, branch, base, commits, changed files, the diff | built |
| `Work>facts` | task, state, worktree path, branch, base, cost | built |
| `Work>review` | the last ocr verdict for this task: findings, blocking ones in red, and whether a merge would be refused | **missing** |
| `Work>review` | the verdicts recorded on this task: review findings, refused merges, merged results, blocking ones in red | built |
## 4. Reply
@@ -78,19 +78,20 @@ Yazi, fzf, Neovim, Lazygit, Hunk and anything else fits without being rebuilt by
| Tool | What it is for | Status |
|---|---|---|
| Lazygit | branches, commits, staging, history | installed, **not wired** |
| Hunk | reading a change as a review | installed, **not wired** |
| Yazi | files | installed, **not wired** |
| Neovim | editing a file the task touched | installed, **not wired** |
| fzf | picking anything | installed, **not wired** |
| Lazygit | branches, commits, staging, history | wired: `t` in Board>board or Work>work |
| Hunk | reading a change as a review | wired the same way |
| Yazi | files | wired the same way |
| Neovim | editing a file the task touched | wired the same way |
| fzf | picking anything | wired the same way |
| shell | any command the interface does not cover | built (`Shell>shell`) |
| ocr | the review of the current change | installed, behind `bin/review` |
## Count
- **22 panels built**, across 8 workspaces.
- **1 panel missing**: `Work>review`.
- **6 tool panes** to wire: Lazygit, Hunk, Yazi, Neovim, fzf, ocr.
- **23 panels built**, across 8 workspaces. Nothing is missing from the list above.
- **tool panes wired** in Board>board and Work>work: `t` opens the chooser, `enter` opens
the tool beside the pane, `esc` closes it, and the tool's own quit key closes its pane.
The other workspaces can get the same key whenever it is wanted.
Nothing in the missing list changes the layout: each is one more panel inside a pane that
already exists, or one pane-opener for a tool.

View File

@@ -84,7 +84,7 @@ func newAgentsModel(c *paperclip.Client, folder string) agentsModel {
}
func (m agentsModel) Init() tea.Cmd {
return tea.Batch(m.load(), tickEvery(5*time.Second))
return tea.Batch(m.load(), tickEvery(5*time.Second), tea.WindowSize())
}
func (m agentsModel) load() tea.Cmd {

View File

@@ -49,6 +49,8 @@ type boardModel struct {
activity []paperclip.Activity
needsTab int
tools bool
toolAt int
zones *zone.Manager
filter string
typing bool
@@ -71,7 +73,7 @@ func newBoardModel(c *paperclip.Client, proj paperclip.Project, folder string) b
}
func (m boardModel) Init() tea.Cmd {
return tea.Batch(m.reload(), tickEvery(5*time.Second))
return tea.Batch(m.reload(), tickEvery(5*time.Second), tea.WindowSize())
}
func (m boardModel) reload() tea.Cmd {
@@ -157,6 +159,27 @@ func (m boardModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
case tea.KeyMsg:
if m.tools {
switch msg.String() {
case "esc", "q", "t":
m.tools = false
return m, nil
case "up", "k":
m.toolAt = max(0, m.toolAt-1)
return m, nil
case "down", "j":
m.toolAt = min(len(tools)-1, m.toolAt+1)
return m, nil
case "enter":
t := tools[m.toolAt]
m.tools = false
if err := openTool(m.folder, t.name); err != nil {
m.err = err
}
return m, nil
}
return m, nil
}
if m.showHelp {
m.showHelp = false
return m, nil
@@ -192,6 +215,9 @@ func (m boardModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case "?":
m.showHelp = true
return m, nil
case "t":
m.tools = true
return m, nil
case "/":
m.typing = true
return m, nil
@@ -424,6 +450,7 @@ func (m boardModel) footerLine() string {
keyHint("enter", "show it everywhere"),
keyHint("a", "assign"),
keyHint("u", "unblock"),
keyHint("t", "tools"),
keyHint("/", "filter"),
keyHint("?", "keys"),
keyHint("tab", "next panel"),

View File

@@ -80,11 +80,9 @@ func main() {
if dir == "" {
dir, _ = os.Getwd()
}
issue := *issue
if issue == "" {
issue = watchedTask(dir)
}
m = newWorkModel(client, dir, issue)
// Pass the flag, not a resolved task: an empty flag means "follow the
// task chosen on the Board", and resolving it here would pin the pane.
m = newWorkModel(client, dir, *issue)
case "tree":
proj, err := client.ResolveProject(*project)

View File

@@ -60,7 +60,7 @@ func newProjectModel(c *paperclip.Client, folder string) projectModel {
}
func (m projectModel) Init() tea.Cmd {
return tea.Batch(m.load(), tickEvery(10*time.Second))
return tea.Batch(m.load(), tickEvery(10*time.Second), tea.WindowSize())
}
func (m projectModel) load() tea.Cmd {

View File

@@ -63,7 +63,7 @@ func newRepairModel(c *paperclip.Client, folder string) repairModel {
}
func (m repairModel) Init() tea.Cmd {
return tea.Batch(m.load(), tickEvery(8*time.Second))
return tea.Batch(m.load(), tickEvery(8*time.Second), tea.WindowSize())
}
func (m repairModel) load() tea.Cmd {
@@ -194,7 +194,7 @@ func (m repairModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
case tickMsg:
return m, tea.Batch(m.load(), tickEvery(8*time.Second))
return m, tea.Batch(m.load(), tickEvery(8*time.Second), tea.WindowSize())
case tea.KeyMsg:
if m.showHelp {

View File

@@ -55,7 +55,7 @@ func newReplyModel(c *paperclip.Client, folder, issueID string) replyModel {
}
func (m replyModel) Init() tea.Cmd {
return tea.Batch(m.load(), tickEvery(5*time.Second))
return tea.Batch(m.load(), tickEvery(5*time.Second), tea.WindowSize())
}
func (m replyModel) load() tea.Cmd {

180
tui/toolpane.go Normal file
View File

@@ -0,0 +1,180 @@
package main
// Tool panes: any terminal program this interface does not cover, opened beside
// what you were reading and closed when you are done with it.
//
// Nothing is rebuilt. Lazygit, Hunk, Yazi, Neovim, fzf and ocr are the tools
// people already use, and a pane is the correct place for them: they keep their
// own keys, their own colours and their own way of working.
//
// A tool pane is not part of the layout. It is created on demand in the
// workspace you are in and it disappears when the program exits, so the eight
// workspaces stay as they are.
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"syscall"
)
type tool struct {
name string
command string
about string
}
// tools are offered in this order: the shell first because it can reach
// anything, then the three that read code, then the review.
var tools = []tool{
{"shell", "exec zsh -i", "a prompt in the project folder"},
{"lazygit", "lazygit", "branches, commits, staging, history"},
{"hunk", "hunk", "a change read as a review"},
{"yazi", "yazi", "files"},
{"nvim", "nvim", "editing one file"},
{"fzf", "fzf", "picking anything"},
{"ocr", "ocr review", "the review of the current change, in the terminal"},
}
// currentWorkspace finds the workspace this program is drawn in. TUIOS knows;
// the environment names the pane, and the pane's window says which workspace.
func currentWorkspace() (string, string, error) {
session := os.Getenv("TUIOS_SESSION")
pane := os.Getenv("TUIOS_PANE_ID")
if session == "" || pane == "" {
return "", "", fmt.Errorf("this is not running inside a TUIOS pane")
}
out, err := exec.Command("tuios", "list-windows", "-s", session, "--json").Output()
if err != nil {
return "", "", fmt.Errorf("cannot ask TUIOS where this pane is: %w", err)
}
ws := workspaceOf(string(out), pane)
if ws == "" {
return "", "", fmt.Errorf("this pane is not in the layout TUIOS reports")
}
return session, ws, nil
}
// workspaceOf finds the workspace number of one window in the JSON TUIOS
// prints. It decodes properly rather than scanning text: a pane id appears in
// more than one place, and the first match is not always the window.
func workspaceOf(raw, paneID string) string {
var doc struct {
Windows []struct {
WindowID string `json:"window_id"`
Workspace int `json:"workspace"`
} `json:"windows"`
}
if err := json.Unmarshal([]byte(raw), &doc); err != nil {
return ""
}
for _, w := range doc.Windows {
if w.WindowID == paneID {
return strconv.Itoa(w.Workspace)
}
}
return ""
}
// openTool starts a program as a new pane in the current workspace.
func openTool(folder, name string) error {
var chosen *tool
for i := range tools {
if tools[i].name == name {
chosen = &tools[i]
}
}
if chosen == nil {
return fmt.Errorf("no tool called %q", name)
}
session, ws, err := currentWorkspace()
if err != nil {
return err
}
log, _ := os.Create(filepath.Join(os.TempDir(), "paperclip-harness-tool.log"))
cmd := exec.Command("tuios", "new-window", chosen.name, "-s", session,
"--workspace", ws, "--cwd", folder, "--", "/bin/sh", "-c", chosen.command)
cmd.Stdout = log
cmd.Stderr = log
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
if err := cmd.Start(); err != nil {
return fmt.Errorf("cannot open %s: %w", chosen.name, err)
}
go func() {
cmd.Wait()
if log != nil {
log.Close()
}
}()
return nil
}
// --- the smallest JSON reader that does this one job -------------------------
type scanner struct {
s string
pos int
}
func newScanner(s string) *scanner { return &scanner{s: s} }
// nextObject returns the next {...} block, or "" at the end.
func (sc *scanner) nextObject() string {
for sc.pos < len(sc.s) && sc.s[sc.pos] != '{' {
sc.pos++
}
if sc.pos >= len(sc.s) {
return ""
}
depth := 0
start := sc.pos
for sc.pos < len(sc.s) {
switch sc.s[sc.pos] {
case '{':
depth++
case '}':
depth--
if depth == 0 {
sc.pos++
return sc.s[start:sc.pos]
}
}
sc.pos++
}
return ""
}
func contains(s, sub string) bool {
for i := 0; i+len(sub) <= len(s); i++ {
if s[i:i+len(sub)] == sub {
return true
}
}
return false
}
// fieldNumber reads "name": 12 out of an object.
func fieldNumber(obj, name string) string {
key := `"` + name + `":`
for i := 0; i+len(key) <= len(obj); i++ {
if obj[i:i+len(key)] != key {
continue
}
j := i + len(key)
for j < len(obj) && (obj[j] == ' ' || obj[j] == '"') {
j++
}
start := j
for j < len(obj) && obj[j] >= '0' && obj[j] <= '9' {
j++
}
if _, err := strconv.Atoi(obj[start:j]); err == nil {
return obj[start:j]
}
}
return ""
}

View File

@@ -44,20 +44,22 @@ type workModel struct {
tab int
scroll int
tools bool
toolAt int
readAt time.Time
showHelp bool
width, height int
}
var workTabs = []string{"runs", "change", "facts"}
var workTabs = []string{"runs", "change", "facts", "review"}
func newWorkModel(c *paperclip.Client, folder, issueID string) workModel {
return workModel{client: c, folder: folder, issue: issueID, explicit: issueID != ""}
}
func (m workModel) Init() tea.Cmd {
return tea.Batch(m.load(), tickEvery(5*time.Second))
return tea.Batch(m.load(), tickEvery(5*time.Second), tea.WindowSize())
}
func (m workModel) load() tea.Cmd {
@@ -120,14 +122,38 @@ func (m workModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, nil
case tickMsg:
return m, tea.Batch(m.load(), tickEvery(5*time.Second))
return m, tea.Batch(m.load(), tickEvery(5*time.Second), tea.WindowSize())
case tea.KeyMsg:
if m.tools {
switch msg.String() {
case "esc", "q", "t":
m.tools = false
return m, nil
case "up", "k":
m.toolAt = max(0, m.toolAt-1)
return m, nil
case "down", "j":
m.toolAt = min(len(tools)-1, m.toolAt+1)
return m, nil
case "enter":
t := tools[m.toolAt]
m.tools = false
if err := openTool(m.folder, t.name); err != nil {
m.err = err
}
return m, nil
}
return m, nil
}
if m.showHelp {
m.showHelp = false
return m, nil
}
switch msg.String() {
case "t":
m.tools = true
return m, nil
case "?":
m.showHelp = true
return m, nil
@@ -225,10 +251,24 @@ func (m workModel) View() string {
body = m.runsLines(m.width - 4)
case 1:
body = m.diffLines(m.width - 4)
case 3:
body = m.reviewLines(m.width - 4)
default:
body = m.factsLines(m.width - 4)
}
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)
}
p := panel{
title: "the work", width: m.width, height: m.height - 2,
tabs: workTabs, active: m.tab, focused: true,
@@ -249,6 +289,7 @@ func (m workModel) View() string {
footer := hintLine([]string{
keyHint("[ ]", "switch tab"),
keyHint("↑↓ or j k", "scroll"),
keyHint("t", "open a tool pane"),
keyHint("r", "read again"),
keyHint("R", "rebuild every pane"),
keyHint("q", "leave"),
@@ -355,6 +396,45 @@ func (m workModel) diffLines(width int) []string {
return out
}
// reviewLines shows the verdicts already recorded on the task. A review is
// written as a comment, so the record lives with the work and survives us.
func (m workModel) reviewLines(width int) []string {
out := []string{"", dimStyle().Render(" verdicts recorded on this task")}
if m.task.Identifier == "" {
return append(out, mutedStyle2().Render(" no task chosen"))
}
cs, err := m.client.Comments(m.task.ID)
if err != nil {
return append(out, lipgloss.NewStyle().Foreground(lipgloss.Color(active.Error)).Render(" "+err.Error()))
}
found := 0
for i := len(cs) - 1; i >= 0 && found < 3; i-- {
body := cs[i].Body
if !strings.HasPrefix(body, "## Review") &&
!strings.HasPrefix(body, "## Merge refused") &&
!strings.HasPrefix(body, "## Merged") &&
!strings.HasPrefix(body, "## Merge undone") {
continue
}
found++
blocking := strings.Contains(body, "critical") || strings.Contains(body, "**high/")
colour := active.Success
if strings.HasPrefix(body, "## Merge refused") || blocking {
colour = active.Error
}
for _, ln := range wrap(strings.ReplaceAll(body, "\n", " · "), width-2) {
out = append(out, " "+lipgloss.NewStyle().Foreground(lipgloss.Color(colour)).Render(ln))
}
out = append(out, "")
}
if found == 0 {
out = append(out, mutedStyle2().Render(" no review recorded for this task yet"))
out = append(out, "")
out = append(out, dimStyle().Render(" run one with: bin/review "+m.task.Identifier+" --post"))
}
return out
}
func (m workModel) factsLines(width int) []string {
var out []string
out = append(out, "")