Handover: history, plan, API measurements, checklist, open issues from the OMA attempt

This commit is contained in:
sam
2026-11-10 09:46:47 +11:00
commit 41a6ae6210
8 changed files with 878 additions and 0 deletions

193
docs/FALLBACK-OMA.md Normal file
View File

@@ -0,0 +1,193 @@
# Understanding OMA before planning anything else
**Objective set by the person, 2026-11-09:** understand `@open-multi-agent/core`
fully, then build a plan against it. Not a rewrite. Not a second engine.
## What OMA is, first facts
- Package: `@open-multi-agent/core`, version 1.23.0, installed at
`/home/sam/paseo/harness/phase2/node_modules/@open-multi-agent/core`.
- Its own description: "Self-hosted TypeScript agent runtime with durable approvals
and verifiable run records."
- It ships a CLI, `oma`, with `run`, `task`, `dashboard`, `eval run`, `eval gate`,
`provider`.
- It exports, among others, `observability`, `observability/file`, `acp`, `process`,
`mcp`, `ai-sdk`, `classifiers`, `shell`, `eval`, `eval/file`.
## Why this document exists
The harness grew a second implementation of things OMA already provides: an approval
path, a viewer, a task starter, a card renderer. That is why faults arrived in threes
and why the same question had two answers. This document records what OMA actually
does, with evidence, so that the next plan puts each job in one place.
## Rules for the work that follows
1. The harness is the cockpit: pages, panes, notes, project files, the decision.
2. OMA is the engine: coordinator, task graph, approvals, run records, the graph.
3. Paperclip is inspiration, not a blueprint: approvals as objects, blockers as
edges, a plan attached to each task, every action tied to its run.
4. Nothing is deleted until its replacement has run a real task and the result can
be shown.
## Findings
(to be filled from the research: CLI, team/tasks schemas, approval API, eval gate,
trace store, process backend, upstream docs)
Read from the installed package (v1.23.0) on 2026-11-09. Evidence is
`phase2/node_modules/@open-multi-agent/core/dist/...`.
### The CLI (`dist/cli/oma.js`)
- `oma run --goal <text> --team <team.json> [--orchestrator <orch.json>] [--coordinator <coord.json>]`
- `oma task --file <tasks.json> [--team <team.json>]`
- `oma dashboard --trace-store <traces.ndjson> --run-id <id> [--output <run.html>]`
- `oma eval run --set <evalset.json> --target <target.mjs> [--scorers <s.mjs>] [--repeats n] [--concurrency n] [--tags a,b] [--report json|markdown|junit]... [--out dir] [--meta k=v]... [--gate <gate.json>] [--baseline <report.json>]`
- `oma eval gate --report <report.json> --gate <gate.json> [--baseline <report.json>]`
- `oma provider [list | template <provider>]`
- Exit codes: `0` success, `1` run/eval gate failed, `2` usage/validation, `3` internal.
- `team.json` may be a `TeamConfig` or `{ team, orchestrator }`. `tasks.json` is
`{ team, tasks, orchestrator? }`.
### Task shape (`types.d.ts:1341-1377`, `RunTaskSpec`)
`title`, `description`, `assignee?`, `dependsOn?: string[]`,
`memoryScope?: 'dependencies' | 'all'`, `dependencyPayload?: 'output' | 'structured' | 'both'`,
`metadata?`, `maxRetries?`, `retryDelayMs?`, `retryBackoff?`, `role?`,
`priority?: low|normal|high|critical`, `requires?` (requiredTools, requiredCapabilities,
requiredBackend, requiredProvider), and **`verify?: ConsensusVerifyOptions`**.
`memoryScope: 'dependencies'` and `dependencyPayload` mean OMA itself decides what a
task sees of its predecessors — we were assembling that by hand.
### Verification per task — `ConsensusVerifyOptions` (`types.d.ts:1883-1898`)
`judges: AgentConfig[]`, `mode: 'refute' | 'lens'`, `quorum` (default ceil(n/2)),
`maxRounds` (default 2), `verdictSchema` (zod; a schema failure counts as dissent),
`onDissent: 'revise' | 'reject' | 'keep'`, `judgePrompt`.
Result: `verdict: 'accepted' | 'rejected'`, plus `dissent[]` and `rounds`.
That is a review gate already built into the runtime, per task. Our hand-written
`gate`/`ocr` path overlaps it and is not aware of it.
### Approvals — durable, scoped, exact (`types.d.ts:318-390`, `approval/durable.d.ts`)
- `ApprovalScope = 'plan' | 'task_round' | 'task_dispatch' | 'tool_call'`.
- `ApprovalRequest` is immutable and **content-bound**: `id`, `runId`, `scope`,
`boundary`, `requestHash` (SHA-256 of scope+boundary+content), `content`.
- `PlanApprovalContent` carries the tasks (`TaskSnapshot[]`) and
`continuation: 'execute' | 'plan_only'` — the same plan can either resume
execution or be returned for a person to read.
- `ApprovalDecisionRecord`: `decision: 'approved' | 'rejected'`, `reviewer{id,displayName}`,
`decidedAt`, bound to the request hash.
- `DurableApprovalLedger` stores rows in a `MemoryStore` under
`__oma_approval__/`, with atomic decision writes and stable error codes
(`APPROVAL_STALE_DECISION`, `APPROVAL_CONFLICT`, `APPROVAL_INTEGRITY_ERROR`).
### The gates the runtime itself calls (`types.d.ts:2194-2246`)
- **`onPlanReady(tasks)`** — once, after the coordinator decomposes the goal, before
anything runs. Return `true/allow` to proceed, `false/deny` to abort, or
**`suspend`** to persist the exact plan for a later decision.
- **`onTaskDispatch(task)`** — immediately before a ready task is dispatched.
`deny` stops new dispatches; running tasks settle; the rest are marked `skipped`.
- **`onApproval(completed, next)`** — between rounds (legacy executor; mutually
exclusive with `onTaskDispatch`).
- `requireConsequentialConfirmation` + `onToolCall` — gate consequential tool calls.
- `PlanPatch` (`types.d.ts:1397`) — append-only repair of the not-yet-executed part
of the graph: `addTasks`, `retargetPending`, `supersedePending`. The executed
topology is immutable.
### Trace events (`types.d.ts:2017`)
`agent_start | agent_complete | task_start | task_complete | task_skipped | task_retry |
approval_pending | plan_revision | recovery_decision | budget_exceeded | message |
warning | error`, in a `FileTraceStore`, exported per run by `oma dashboard`.
### What this changes
1. **The approval we hand-built is a weaker copy of `onPlanReady` + `suspend` +
`DurableApprovalLedger`.** OMA's version is content-bound (a changed plan cannot
be approved by a stale decision), scoped, and recorded with a reviewer identity.
2. **Per-task checks belong in `verify`, not in a side script.** A task can carry its
own judges, quorum and dissent policy, and the result is
`accepted | rejected` with the dissent text.
3. **Dependencies and what a task sees of them are OMA's job** (`dependsOn`,
`memoryScope`, `dependencyPayload`), not ours to re-derive — which is why the
re-plan lost them and nothing noticed.
4. **`oma task --file tasks.json` is the supported way to run a plan you already
have**, which is what `bin/run-start` tried to be.
5. **Still ours to own:** the pages, the pane layout, the notes, the project files,
the wording of the checks, and the decision surface — plus the graph view, where
we add per-task state and the verdict on top of OMA's data rather than drawing a
second graph from a different source.
### Questions the research did not settle
- Which gates are available when the CLI is used, versus only through the library
(`onPlanReady` is documented as `runTeam()` only).
- How a `suspend` decision is later resumed from the CLI, as opposed to in-process.
- Whether `verify` judges can run shell commands (our checks are commands), or only
reason over the task output.
## Upstream documentation (researched 2026-11-09)
- npm `@open-multi-agent/core@1.23.0`, published 2026-10-29. MIT. Author: Shenzhen
YuanASI Technology. One npm maintainer. ~3,100 downloads in the last month.
- Repository `github.com/open-multi-agent/open-multi-agent`, subdirectory
`packages/core`, tag `v1.23.0`.
- **There is real documentation**, not just a README: 40+ guides under `docs/`, an
examples tree (`basics/`, `cookbook/`, `patterns/`, `providers/`, `integrations/`),
and a docs site at open-multi-agent.com.
- The pages that matter to us:
`docs/cli.md` (team/tasks files), `docs/coordinator.md`,
`docs/durable-approvals.md`, `docs/evaluation-ci.md`, `docs/observability.md`,
`docs/run-viewer.md`, `docs/external-agents.md`, `docs/glossary.md`.
### Planning, from the docs
`runTeam(team, goal)` is the only planning entry point. One coordinator model call
produces a JSON array of task specs, validated against a Zod schema generated from
the live roster, with one corrective retry. Caps: 200 tasks, 200 dependencies. An
invalid plan **fails the run** (`COORDINATOR_PLAN_INVALID`, `INVALID_ASSIGNEE`,
`INVALID_TASK_DEPENDENCIES`) and is never downgraded to a single agent. Ordering is
then OMA's (`TaskQueue` + `Scheduler`); the coordinator does not re-engage mid-run.
A deterministic router short-circuits simple goals to a single agent — that is why
`mode: 'team'` is required for the split to happen at all.
### Approvals
Four boundaries: `onPlanReady`, `onApproval`, `onTaskDispatch`, `onToolCall`; each may
return `allow`, `deny` or `suspend`. Suspension needs checkpointing and a `MemoryStore`
with atomic `compareAndSet`. Decisions are first-wins. The docs are explicit that the
hash is **not** a cryptographic signature against storage administration.
### External agents
`process` (command; stdin/argv in, stdout/exit code out) and `acp` (JSON-RPC over
stdio; Gemini CLI, Claude Code, Codex). Important limit from the docs: the tool gate,
filesystem sandbox and LLM egress policy **do not apply** to external agents.
### Verifiable records — with honest limits
Three separate things: an execution receipt (pure function, no I/O), an opt-in run
journal (`verifyRun()` checks sequence monotonicity and per-block hashes), and the
trace store plus static HTML run viewer. The docs state plainly: no hash chain, no
signature, no WORM storage — a writer with file access can rewrite an event and
recompute its hash.
### Coding use
Generic orchestration, with coding documented as a use case ("hybrid team": LLM
planner → external coding CLI → LLM reviewer over the diff). Pattern examples include
`multi-perspective-code-review`, `risk-gated-bash`, `external-agent-acp`.
### Gaps this research settled
- `onApproval` and `onTaskDispatch` are **library-only**: function options cannot be
passed through the CLI. So a CLI-driven run cannot use our gates; the coordinator
must be our own small Node process calling the library.
- Our earlier note about `oma eval gate --repo` is not in the upstream docs; only
`oma eval run --gate <gate.json>`.

34
docs/OPEN-ISSUES.md Normal file
View File

@@ -0,0 +1,34 @@
# Open issues in the old project (for reference, not to fix now)
These belong to `~/paseo/harness` and `~/paseo/projects/tuios_coding_harness`. They are
recorded so that nothing is lost if you go back, and so the new project does not repeat
them.
## Known broken or unfinished
- The task pane's check is not the check that was approved: the run still falls back to
guessing a test command, so a "pass" can mean "detection said so".
- Two implementations of the same jobs existed (approval, viewer, task starter, cards).
They disagreed, which produced repeated faults.
- A plan re-run re-planned itself and lost its dependencies.
- Task state was matched by folder-name similarity rather than by the task's own record.
- `bin/home`'s per-task list is view-only; starting a single task is blocked by
dependencies being absent from the stored plan.
- Worktree/merge/review path (`ocr`, serial merge) exists in pieces but has never run end
to end.
- Redaction of secrets on outbound provider requests is built but not connected.
- Mouse-1 is used only for routing failures; intake scoring was never built.
- Grid layout (50/50 by pane count) was deferred by you and never done.
- Session creation in TUIOS cannot be scripted: `tuios new` needs a terminal.
- Subagent models in this environment fail with a 404 (`claude-haiku-4.5` unavailable), so
delegated research silently returns nothing.
- The page notes and layout are correct as documents, but the layout has been lost twice
to TUIOS renumbering; repair now carries the project, but it is lightly tested.
## Decisions in the old project that are still good
- Approvals must be content-bound (a changed plan cannot ride an old approval).
- A task is finished when a command says so, not when an agent says so.
- One writer per fact; the queue belongs to the coordination layer.
- Untrusted repository text is data, never instructions.
- A secret must not leave the machine; redaction belongs on the request, not in a prompt.

135
docs/PAPERCLIP-API-NOTES.md Normal file
View File

@@ -0,0 +1,135 @@
# Paperclip API — read-only probe, 2026-11-09
Probe only: no writes, no task created, nothing in the existing projects touched. All
requests were `GET` with `Authorization: Bearer $PAPERCLIP_API_KEY` read from the
environment; the key is never printed here.
## Where it runs
- Local server: `http://127.0.0.1:3100`, pid 1588, started 2026-11-05.
From `~/.paperclip/instances/default/runtime-info.json`.
- Public URL: `https://paperclip.lab.audasmedia.com.au`.
- Postgres: `postgres://paperclip@127.0.0.1:5433/paperclip` (embedded, local).
- CLI: `paperclipai` 2026.916.1, managed install under `~/.paperclip/cli/installs`.
## Endpoints that answered
| Request | Result |
|---|---|
| `GET /api/health` | 200, 899 bytes |
| `GET /api/openapi.json` | 200, 1.1 MB — **685 paths** |
| `GET /api/agents/me` | 200 — identity, company, adapter |
| `GET /api/companies/{companyId}/issues?limit=200` | 200 — 145 issues |
| `GET /api/issues/{id}` | 200 |
| `GET /api/issues/{id}/comments` | 200 |
| `GET /api/issues/{id}/activity` | 200 |
| `GET /api/issues/{id}/cost-summary` | 200 |
| `GET /api/issues?limit=5` | 400 — "Missing companyId in path" |
## The identity the API answered as
`name: Hub`, `role: general`, `status: idle`, `adapterType: **pi_local**`,
model `omni/deepseek/deepseek-v4-flash`. So **Pi is the installed worker adapter**, not
something we must write.
## What already exists in this instance
- 10 projects, 145 issues: 139 `done`, 2 `blocked`, 2 `in_progress`, 1 `todo`, 1 `backlog`.
- Every status the four-screen TUI needs is already a first-class value.
## Endpoints the TUI and the executor will need (from the 685 in the spec)
- Read: `/api/companies/{companyId}/issues`, `/api/issues/{id}`,
`/api/issues/{id}/comments`, `/api/issues/{id}/activity`,
`/api/issues/{id}/children`, `/api/issues/{id}/diagnostics/blockers`,
`/api/issues/{id}/cost-summary`, `/api/issues/{id}/runs`,
`/api/issues/{id}/heartbeat-context`, `/api/agents/me/inbox-lite`.
- Write (later, not in this probe): `/api/issues`, `/api/issues/{id}/comments`,
`/api/issues/{id}/checkout`, `/api/issues/{id}/release`,
`/api/approvals/{id}/approve|reject|request-revision`,
`/api/cases/{caseId}/blockers`, `/api/issues/{id}/interactions/{interactionId}/respond`.
- Trees and holds: `/api/issues/{id}/tree-control/state|preview`,
`/api/issues/{id}/tree-holds`, `/api/issues/{id}/diagnostics/subtree`.
## Hypotheses
- **H1 — the control plane answers.** PASS. Health, identity, 145 issues.
- **H2 — task with a blocker via API.** NOT TESTED (a write; out of scope for a
read-only probe). Note: the two blocked issues returned `blockedByIssueIds: None`, so
the blocker relation may live in `/api/cases/{caseId}/blockers` or
`/api/issues/{id}/diagnostics/blockers` rather than on the issue row. This must be
established before trusting screen 1.
- **H3 — a comment wakes an agent.** NOT TESTED. The wake plumbing is visible in the
spec (`heartbeat-context`, `inbox-lite`, `queued-comments/steer`,
`diagnostics/wakes`), and agents run on heartbeats, so the shape is right. Unproven.
- **H4 — Pi can be a worker.** Likely PASS: `adapterType: pi_local` is the identity's
own adapter, and `Pi` is listed as a supported runtime upstream.
- **H5 — cost and run history readable.** PASS. `/api/issues/{id}/cost-summary` returns
`costCents`, `inputTokens`, `cachedInputTokens`, `outputTokens`, `runCount`.
## What this changes
The premise holds: there is a live control plane, with the statuses, threads, activity,
cost and blocker diagnostics a four-screen TUI needs, and Pi is already the adapter. The
work that remains is small and specific: prove a blocker edge by API, prove a comment
wakes an agent, and write the executor that puts a task into a git worktree, runs it and
reports back.
## Sandbox writes, 2026-11-09 (approved in advance)
Sandbox created: project **spike-2026-11-09** (`9e3f61f6-cce9-49b1-8083-3130345a04a5`),
status `backlog`, workspace `git_repo` at `/tmp/pc-sandbox` (a throwaway repo with one
commit). It is safe to delete.
Two issues created by API, status `todo`:
- `AUD-157` Spike T1 — write a file (`2ce09ea8-…`)
- `AUD-158` Spike T2 — read that file (`abc5d318-…`)
### The permission rule, learned the hard way
With `PAPERCLIP_API_KEY` (the agent `Hub`), **every write returned 403**:
> "Cross-issue writes need a run to attribute them to (Heartbeat run context). Every
> agent comment and task update is attributed to a heartbeat run so the cross-issue cap
> can be counted and the audit trail can name who acted for whom."
So an agent key is only usable **inside a heartbeat run**, with `X-Paperclip-Run-Id`.
A cockpit acting for the person must use the **user** credential
(`PAPERCLIP_BOARD_KEY`), not the agent key. That is a design fact, not an obstacle: the
TUI is the person's surface, and the audit trail correctly refuses anonymous agent
writes.
### H2 — a task with a blocker: PASS
`PATCH /api/issues/{id}` with `{"blockedByIssueIds":["<t1>"]}` → 200, and the edge reads
back. `GET /api/issues/{id}/diagnostics/blockers` returns:
```
readiness: { allBlockersDone: false, isDependencyReady: false, unresolvedBlockerCount: 1 }
blockers: [ "Spike T1 — write a file" ]
```
Note: the blocker edge is **not** on the issue list rows (`blockedByIssueIds: 0` there).
A tree view must read `diagnostics/blockers` (or the single-issue GET) per task, not the
list. That is the one place screen 1 could have lied to us.
### H3 — a comment lands on a blocked task: PASS
`POST /api/issues/{id}/comments` with the user key → 201, `authorType: user`, and the
comment is on the thread of the blocked task. What this does **not** yet prove is that a
comment *wakes* an agent: that requires a real agent on the task and a heartbeat. The
wake plumbing is present in the spec (`heartbeat-context`, `inbox-lite`,
`queued-comments/steer`, `diagnostics/wakes`); the wake itself is unproven.
### Updated verdict
H1 pass, H2 pass, H3 partly (comment lands; wake unproven), H4 likely (Pi is the
adapter), H5 pass. The remaining proof is one real agent doing one task, which is
Milestone 1 of `plan/92-paperclip-spike.md`, not a probe.
### One more thing worth knowing
A project can be created with an `executionWorkspacePolicy` whose `workspaceStrategy.type`
is `git_worktree`, with `baseRef`, `branchTemplate`, `worktreeParentDir`, provision and
teardown commands. **Paperclip may already do the worktrees we assumed we would build.**
That deserves its own probe before any executor is written.

169
docs/PLAN.md Normal file
View File

@@ -0,0 +1,169 @@
# The plan from here: Paperclip underneath, a Go terminal app on top
Written 2026-11-09. Read with `WHAT-WE-ARE-BUILDING.md`. This is the third attempt, and
it says where we have been as well as where we are going, because the first two were
lost by plans that only said "next".
---
## 1. What we set out to make
A coding factory that runs inside TUIOS. A person writes a goal; it is split into tasks;
each task runs on its own copy of the code; tests and a review decide whether the work is
finished; finished work is merged one at a time; the person is interrupted only to make a
decision. Terminal only. Per project, not per machine.
## 2. Where we have been
**Attempt one (OMA, our own cockpit).** We built a coordinator around the
`@open-multi-agent` library, which is genuinely good at planning a task graph and
verifying output. Then we spent two weeks building the things it does not have: an
approval path, a viewer, a task starter, a card board. Those were built twice, because
faults appeared in threes — two implementations of the same job disagreeing.
**What went wrong, specifically.**
- Nothing was ever run end to end on a small plan. Every failure had several causes, so
every fix was a guess.
- The interface came before the engine: nine pages, panes, notes and filters before one
task had passed one test.
- A plan that was re-run was re-planned, which silently threw away its dependencies.
- A task's state was guessed from folder names, so old work coloured new cards.
- The layout was lost twice: TUIOS deletes a workspace when its last pane closes, and a
repair command did not carry the project with it.
**What we achieved and keep.** A working page layout and page notes in plain language; a
project convention (`.harness/settings.toml`, role files, notes, a to-do list per
project); `office` for opening a project; `project-reset`; and a real understanding of
what an approval and a per-task check must be (`plan/90`).
**Attempt two (understanding, not building).** We read OMA properly and found it has
approvals, checks and worktrees of its own kind. We then studied Paperclip instead of
assuming.
## 3. What Paperclip actually is, from our own probes
Not marketing — measured on this machine (`spike/api-notes.md`).
- A server with a database, already running here: `http://127.0.0.1:3100`, 685 API
endpoints, browser UI at `https://paperclip.lab.audasmedia.com.au`.
- Your work is already in it: 10 projects, 145 tasks, with statuses `todo`, `backlog`,
`in_progress`, `blocked`, `done`.
- **Pi is the worker already installed** on the agent identity (`adapterType: pi_local`).
- Blockers are real: setting one returned "1 unresolved blocker" and named the task that
blocks it. **But the blocker is not on the task list**, only on the single task and its
blocker diagnosis. A tree must ask per task.
- Comments land on a blocked task's thread.
- **Cost per task is readable** — cents, input and output tokens, run count.
- **Writes from an agent key are refused** unless it is inside a heartbeat run. A person's
tool must use the user key. This is Paperclip protecting its own audit trail.
- **Paperclip creates git worktrees itself.** The installed code runs `git worktree` and
enforces a workspace strategy of `git_worktree` with a branch template, a worktree
parent folder, and setup and teardown commands. The worktree was on our list; it is
not ours to build.
## 4. Pitfalls, so the third attempt does not repeat the first two
1. **One owner per fact.** The task queue, blockers, approvals, comments, runs and cost
belong to Paperclip. Our code never keeps a second copy. If a screen disagrees with
Paperclip, the screen is wrong.
2. **No interface before a working run.** The first milestone ends with a task that a
person watched finish. Nothing is styled before that.
3. **Small plans only, until small plans work.** Two tasks, then three, then a real job.
4. **Never judge a task by a folder name.** State comes from the task's record.
5. **The layout is ours to protect.** A workspace dies when its last pane closes, so
every page keeps a pane that does not close. Repair must carry the project name.
6. **Agent keys are not person keys.** Anything the TUI does on your behalf uses the user
credential, so the audit trail names you.
7. **Do not re-plan a plan.** A stored plan is read, never regenerated.
8. **Every claim comes with the command that showed it.**
## 5. What Paperclip does not do, and is ours
- **Per project, not per company.** Paperclip has companies, projects and tasks. Our unit
of work is one project in one folder on one machine. Mapping and scoping are ours.
- **Which host.** Moving between `.13`, `.27` and `.51`, remembering where a project
lives and building its layout there. Ours.
- **The layout and its repair.** Pages, panes, and rebuilding them after a crash or on a
new machine. Ours.
- **Project lifecycle.** Create, adopt, reset, delete. Ours.
- **The code review gate.** `ocr` over the diff, and the merge order. Paperclip has
approvals; it does not know our review tool.
- **Serial merging.** One task at a time, re-checked after each rebase. Ours.
- **The wording of a task's test.** Paperclip records a task; the command that decides it
is finished is our convention, kept with the project.
- **The notes.** What each screen is for, in plain language. Ours.
## 6. The shape: four screens, one Go program
Go, with Bubble Tea, Lipgloss, Bubbles, Huh and BubbleZone. One program, four screens,
each in a TUIOS pane. All data comes from Paperclip's API; nothing is stored twice.
**Screen 1 — Task tree.** Todo, in progress, blocked, done, for the current project. Each
row shows the task, who has it, and what blocks it (read per task, not from the list).
Enter opens the task. This replaces the old HOME, BOARD and DONE pages.
**Screen 2 — New task.** A form: title, description, what must finish first, and the test
that decides it is done. On submit it calls Paperclip, and the task appears in the tree.
**Screen 3 — Live log and diff.** For the selected task: what the agent is doing, the
files it touched, and the change as a diff. Reads Paperclip's run and activity records;
the diff comes from the task's own worktree, which Paperclip made.
**Screen 4 — Unblock and reply.** The task's thread, with a box to reply. Sending posts a
comment, and optionally changes status — which is what wakes the agent.
Around those four, the things we already know we need, kept as thin pages rather than a
second application: project open/reset, the notes page, and a repairs page that rebuilds
the layout.
## 7. Plan of attack
**Milestone 0 — done.** Read-only probe of the API, plus sandbox writes. Results in
`spike/api-notes.md`.
**Milestone 1 — one task, really run.** In the sandbox project, give the task to Pi,
let Paperclip make the worktree and run it, and see the comment and the status change
come back. Pass when: the task goes todo → in progress → done, a comment written by Pi
holds the change, and the cost appears. No interface.
**Milestone 2 — screen 1 and screen 4.** Read the tree from the API, and reply from a box.
Pass when: you move a blocked task forward entirely from the terminal, without a browser
and without a shell command.
**Milestone 3 — screen 2 and screen 3.** Create a task with a blocker and a test; watch a
running task's log and diff. Pass when: a two-task plan is created, ordered and finished
from the terminal alone.
**Milestone 4 — the project layer.** Adopt a folder, remember its host, build the layout,
repair it, reset it. Pass when: a new project on another machine can be opened and used
from here.
**Milestone 5 — the review gate and merging.** `ocr` over the diff, and serial merge.
Pass when: a task that fails review is refused, and the next task cannot merge until the
first is settled.
## 8. On the Bubble Tea analysis
It is correct, and it names the two things that would otherwise cost a week:
- **Resize.** Handle the window-size message, never hardcode sizes, subtract border
sizes, and show a short "too small" screen rather than a broken one. Also run in the
alternate screen so TUIOS scrollback does not fight the redraws.
- **Keys.** In TUIOS window mode, `h j k l`, `z` and `n` belong to TUIOS and never reach
the app. So inner navigation uses Tab, Shift-Tab, arrows, Space and Enter, and a bare
Esc must be free to close a box. This is a design constraint, not a detail.
Two additions from our own experience:
- Wrap the whole top-level view in one BubbleZone scan, and create the zone manager once.
Per-component scanning drifts when panes resize.
- Never do network or git work inside the update or view functions; do it in commands
that return messages. A freeze is visible to the person as a stuck pane.
## 9. Decisions this plan needs from the person
1. Confirm Paperclip as the owner of tasks, blockers, comments, approvals, runs and cost.
2. Confirm the four screens and the thin pages around them.
3. Confirm that the first milestone runs a task with no interface at all, even though the
interface is the part you most want to see.

View File

@@ -0,0 +1,176 @@
# What we are building
Behaviour first. No commands, no file names, no workspace numbers — those are in
the build documents. This page is what the thing *is* and what it feels like to
use, so that someone picking up the work understands the product, not just the
plumbing.
## One sentence
**An autonomous coding factory you can walk around: a CEO that plans and assigns,
workers that do the work in their own folders, and an interface where you can see
everything, direct anyone, and are interrupted only for decisions.**
Paperclip is the reference. Same idea — a goal becomes work, roles carry it out,
there are approvals, budgets and a record — but as a terminal interface rather
than a web dashboard.
Budgets are not strict at this stage and are more a record than a hard line.
A better understanding can be found through these headline docs.
Paperclip overview.
https://github.com/paperclipai/paperclip
Working
https://docs.paperclip.ing/guides/day-to-day/dashboard/
Org and agents
https://docs.paperclip.ing/guides/org/agents/
Projects
https://docs.paperclip.ing/guides/projects-workflow/projects/
## My Desire.
A place where I can quickly keyboard navigate and when needed mouse that is functional, terminal based system which looks good. I can launch it from folders on my main machines .13, 51, 27 - or via web on those machiens as TUIOS allows this. I can take over pre-existing work, or initiate entirely new project, which may be simple research and document creation on a research project, or a full software system integrated with version control and Gitea.
The system, tuios coding harness, will take a plan or directive and divide it into phases and then specific tasks which it will disseminate and coordinate in a systematic manner to deliver that plan. Those tasks are handed to agents via oma with pi-durable for resumption and using pi as the agent. I can interact with the main controller or other agents as needed to redirect, answer questions etc. I might answer questions in the pi in terminal such as "pi ask user question" after an alert is raised in the main admin area, or the main admin area might raise an alert and there is box I can simply type into or select options. The project is delivered in a systematic documented manner. We can see the audit log, phases and tasks completed, costs, with notes on issues.
I should be able to resume the project when ever needed. The system when using Gitea should use worktrees, spaces, sessions so there are no conflicts - see technical notes, and ensure things are working with something like ALibaba code review. Keys, Passwords, Secrets should be redacted and not exposed, The one mechanism known to work is redaction at the outbound provider request — a proxy on the wire.
## The roles
- **CEO.** Takes the goal. Writes the plan, splits it into phases and tasks,
assigns each to a worker, tracks progress, reports back, raises problems. This is OMA and Pi-durable.
- **Workers.** Do one task each, in their own folder on their own branch, with
their own conversation. Visible while they work.
- **The person.** Approves or rejects a plan, changes how a role behaves, talks to
anyone, and decides the things a machine should not decide.
Each role has **settings** that belong to it, not to a run: which model, what
budget, what it may do (merge? touch tests? run commands?). Changing a setting
changes that role from then on.
## The four ways work starts
1. **You type a goal.** One line. The CEO plans it and shows you the plan before
it spends anything.
2. **You write the plan.** Paste or type phases and tasks directly; it turns them
into assigned work without inventing its own.
3. **Something else calls it.** n8n, a script, a webhook. A run starts with no
person present, and the outcome comes back as data: what ran, what passed,
what merged, what it cost.
4. **You open it in a folder.** Point it at any project, any directory, and it
works on that. It is not tied to one repository or one machine.
## The three things you do while it runs
- **Watch a worker.** See what it is doing right now, what it has spent, what it
is about to change.
- **Talk to anyone.** Send a worker a correction mid-task and it continues in the
same conversation. Ask the CEO what it is waiting for. Same for a task that has
already finished.
- **Approve or reject.** A plan before it starts; a change before it merges when
it is not obvious.
## The four main things it tells you
- **Progress** — what is planned, what is running, what has finished.
- **Completed** — merged, tested, with what it cost and what changed.
- **Problems** — failed, blocked, or a check that could not run. With the reason,
and something you can do about it.
- **Decisions needed** — the short list of things waiting for you, and nothing
else. If it is not waiting for you, it does not belong there.
## A finished run
Everything merged is tested and was re-checked after it was rebased onto the
latest work. Nothing merges that a check could not verify. The record of the run
is a set of files: the plan, each task, its cost, its verdict, its change. You can
read it a week later without asking anyone, and reopen any task's conversation.
## Our own agent awareness — do not hand this to TUIOS
TUIOS is transport — panes, navigation, focus, opening files. The model of the run — roles, plans, costs, verdicts, decisions — is ours.
We are building **our own** system for fast terminal navigation on top of TUIOS:
who is running, where, on what, what they cost, what needs you. It may look like
what TUIOS already offers — alerts, "what is running where", a list of agents, an
inbox of things wanting attention. **That is fine and expected.** Overlap is not a
problem.
Both can exist. TUIOS keeps everything it has, nothing is blocked or removed, and
it remains excellent at windows, panes and opening files.
The rule is only about where the factory's own awareness lives: **it lives in our
interface.** If the answer to "what is happening and what needs me" is "use
TUIOS's agent list", the factory has no view of its own and the product is a pile
of scripts. Our interface must know the roles, the plan, the budgets, the verdicts
and the outstanding decisions — because TUIOS cannot: it sees terminals, not
phases.
We can also leverage TUIOS CLI for navigation, control, refresh, rebuild - including preset terminal layouts.
## Additional Notes
- Page generally refers to workspace. Confirm if unsure.
- Rebuilding and starting the layout should be consistent with a set layout. A full reset. Define left, right, top-left, top-right, bottom-left, bottom-right etc.
- Refresh refreshes the panels and workspaces as they were.
- Workspaces should open in the same order.
- We should be able to jump to workers or other workspaces using TUIOS cli - eg exec(`tuios workspace switch ${workspaceNum}
- WE should have an area where we can start a new project, where we can see the projects plan and objectives, where we can write a plan, where we can write a prompt to the OMA to direct a variation or new task.
- If the project is started in an existing folder of work which is not from the tuios coding harness we are making then it can look at the AGENTS.md or other docs and formulate a plan.
- We should have a workers page where agents are running.
- We shold have a page where we can edit the workers directives, LLM etc
- We should have a Documents or Files page which might show us the output of documents, code etc. These might be diffs - Hunk or images, pdfs, documents that might need to be opened externally or viewed internall.
- We need a page where we can interact with the Gitea and similar. Hunk, LazyGit etc.
- Some panels may need custom interfaces while many can simply be terminal tools.
- Tasks and todo can and should also be shown via Tuxedo
- We can use a terminal tool to show CPU if needed there are several installed.
- I want to include Mouse-1 (probability LLM) and possibly switch which simply builds Mouse-1 JSON (I think, needs research), where feasible for massive speed and cost savings. Ensure these are understood.
- https://mouse.dev/blog/compare/mouse-vs-openai-decisions/
- API https://mouse.dev/api
- Docs https://mouse.dev/docs
- And we use Switch which can turn the "state of a task" into typed questions for Mouse-1 or Jev
- Understand it here https://github.com/osolmaz/switch
- We can use Apprise to send alerts to me.
- We can use the TUIOS CLI to achieve things like navigation.
- We can interact with other Docker or local tools installed to improve functionality.
- Pi-durable is a candidate for durable run records, not something in the loop.
- Some tools named in here may already be installed, others may not. Confirm do not assume.
- a workspace holds panes; a page is what you see on a workspace; a panel is one pane's content.
## CRITICAL
- We work together to have a very well defined interface, workspaces, panels that we write down in a document to follow. We will work towards a system similar to other autonomous coding software factories with paperclip as our inspiration. We have decided upon Open Multi Agent as our main coordinator with pi-durable for resumable operations, pi as our in pane interactive agents which CAN use "ask user question".
## Additional Notes from previous session
Where settings live. One file per project, in the project's own hidden folder, holding one block per role: the role's prompt, its model and provider,
its budget for a run, and its permissions — may it merge, may it change tests, may it run commands. The worker-settings page reads and writes that file;
it owns it, nothing else writes it. A change applies to that role's next task, never to one already running: the page shows "active now" versus "next
task", and no agent is ever repointed mid-conversation. Runs copy the settings they started with into the run record, so a later change never rewrites
history.
Concurrency. Three workers at a time by default, set per project. Three because that is what merges cleanly without babysitting; more is a setting, not
a rewrite. Two tasks wanting the same file is not prevented, it is contained: each works in its own folder on its own branch, so they cannot overwrite
each other; the collision shows up at merge, where merges are one at a time, each rebased onto the latest and re-checked. If the rebase conflicts or the
re-check fails, that task is held with a reason and appears as a decision for you. If you know two tasks touch the same file, the CEO should give them
an order (one depends on the other) so they never collide at all.
Failure policy. Three answers, three behaviours. Pass → merges. Fail → returned to the same worker, once, in the same conversation, with the check's
reasons included; if it fails a second time it stops and becomes a decision for you — the machine never retries a third time. Refuse (the check could
not run) → never retried automatically, because retrying will fail identically; it becomes a decision immediately, and the reason is the checker, not
the agent. Blocked is different from failed: a task is blocked when it cannot start — its dependency is not merged, or its folder or permissions are
unavailable. Blocked tasks are not failures and must not be counted as such; they are waiting, and the reason is always shown.
Resume, twice over. Resuming a task means reopening its own conversation in its own folder, continuing with the context it already had. Resuming a run
means reading the plan again and continuing the plan: tasks already merged are skipped because their branch is already in the main line, tasks pending
are dispatched, tasks failed or blocked come back as they were. Resuming a run never redoes merged work and never re-plans unless you ask. Opening the
project is the third and simplest: the plan, the tasks, the costs and the record are on disk, so it looks the same a week later. For all three to be
true, these must persist: the plan, each task's own record, and the branch-and-merge state of each task.
Exposure. Only .13 is reachable over the web; .27 and .51 are local only. What the web surface gives is a full terminal on that machine, so it must be
treated as equivalent to root on .13: bind it to the LAN only, never expose it to the internet, and assume anyone who can reach it can do anything the
account can do. I have not verified whether tuios-web requires its own login — that must be checked before it is relied on, and until it is, treat it as
open to the local network. The standing decision stays: no production use until X1 passes (reference/acceptance-tests.md), and secrets are stripped on
the outbound provider request — a prompt instruction is not a control.