Repository navigation
Proposal: optional harness plugin and three small host APIs #150
Description
This follows the feedback on #132, #134, #135 and #137. Nothing here touches core. A first version of the plugin that uses only the existing plugin APIs is working locally (phase 1 below); before publishing it and before proposing any host API, I would like agreement on the flow and on the three APIs. Related core PRs: #147, #148, #133, #136, #149.
Principles
- Nothing new on default surfaces: HOME, dock, launch dialog, Agents settings and the empty-canvas menu stay as they are on main.
- One optional plugin (the existing assistant plugin, extended), installed from Settings → Plugins with the normal manifest/permission review and native-code trust.
- Automatic by default: the orchestrator decides how many agents to start, the plugin picks models and accounts, and changes made by a subagent in a worktree are reviewed when it finishes.
- The person sees something only when a decision is needed: a secret request, a loop, a budget limit, or a finished review. These use the existing attention panel and system notifications.
- Flows never start without a preview of roles and tasks.
- The host keeps all validation, trust, credentials and redaction. A plugin recommendation never grants access.
- Usage counting reuses the usage history from feat(usage): add quota history and session estimates #138; the plugin does not read provider logs itself.
1. Scenarios
A. Large task, no setup. The person starts an Orchestrator as usual and describes the task. The orchestrator calls the plugin's route tool for each subagent and gets provider, model and account. It then uses core spawn_agent. Nothing is asked unless a rule below fires.
B. Review without asking. A subagent working in a worktree environment finishes. The plugin starts a reviewer that sees only the diff. When the verdict is ready, one attention entry appears. Open review shows the changes in the review dialog accepted in #133, with Accept/Reject still requiring a click.
C. Something needs a person. An agent repeats the same failing command, or its task reaches the token budget the person set. One attention entry appears with at most two actions, for example Stop agent / Ignore. Nothing else changes on screen.
2. What the person sees
Card menu (existing cardActions, shown only while the plugin is enabled and trusted):
Orchestrator card ⋯ Agent card ⋯
…existing items… …existing items…
Plan from flow… Report
Task board
Plugin canvas card (canvas-app, opened by Plan from flow…, standard 54px header and summary below 0.5×):
[header] Flow: Executor and reviewer (built-in, localized)
What it does: one agent implements, one reviews the diff.
Roles Provider/model (auto) Tasks
executor codex / gpt-5 implement parser
reviewer claude / sonnet review diff
Permissions are unchanged: each agent uses the launch profile you chose.
[Cancel] [Start]
User flows from .canvastty/flows/*.yaml are marked "From this project". Their text is shown as written.
Plugin settings page (settingsContribution, reached from the plugin's Settings action in Settings → Plugins). It has four rows in the SettingGroup row grammar (label and help on the left, one control on the right):
Command review [Strict | Warn | Off]
Automatic review [on/off] reviews worktree subagents when they finish
Task budget [ empty = no limit ] tokens
Model choice [Automatic | Ask before start]
Attention entries (needs proposal A; until then only card badges):
Review ready · "parser" · 2 findings [Open review] [Dismiss]
Possible loop · "tests" · same command ×5 [Stop agent] [Ignore]
Budget reached · "refactor" · 200k tokens [Allow +50k] [Stop task]
Secret requested · "release" · GITHUB_TOKEN [Allow once] [Deny]
Card badges (existing cards.setBadge, at most two per card, only when there is a signal): review: 2, budget 80%, loop?, 3/5 tasks.
All built-in strings come from the plugin in en/ru using initialize.locale and the context locale. This includes badges, tool descriptions and action titles. The pages take the palette from context. One open question for you: would you accept a host stylesheet with tokens and --ui-scale for plugin pages, so they do not copy values?
3. Feature → existing API
| Feature | Existing API on main |
|---|---|
| Model and account choice | agent tool route (tools:agents, orchestrator role) → core spawn_agent model + accounts plugin account (delegable launch option) |
| Team size | orchestrator's own decision; flow_plan tool only suggests roles |
| Flow preview and start | service reads <cwd>/.canvastty/flows; canvas-app; card action filtered to orchestrator role; approved plan returned to the orchestrator through the flow_status tool |
| Task board | agent tools task_* (orchestrator + subagent roles), plugin storage, badge |
| Automatic review | sessions:events (exited/idle + environment ref) → sessions.create reviewer in a confining environment kind with only the diff → review_submit tool → card action result review (#133 dialog) |
| Command review, data classes | decide (decision:provide) + launch policy + dataClass launch field; settings only on the plugin page |
| Budget enforcement | decide deny "budget reached" + launch policy refusing new spawns |
| Loop detection (before the call) | fingerprints from the plugin's own decide calls |
| Continue after quota | accounts plugin card action (exists) |
| Agents on a server | environments plugin ssh-host (exists) |
Missing: raising attention entries, per-session token usage and tool outcomes, and restarting a subagent in its card.
4. Missing host APIs (three separate PRs)
A. attention:raise: plugin entries in the attention panel
- Contract:
attention.raise {key, sessionId?, kind: "info"|"needs-input"|"warning", title ≤60, body ≤240, actions ≤2 [{id, title}]}→{id};attention.clear {key}. A click sendscanvastty.attention.action {key, actionId}. The text is plain and masked by the host. - Shown in the existing panel and system notifications according to the existing General/Appearance settings. No new settings. Rate limit of about 6 per minute per plugin.
- Permission: install-time "can show items in your attention panel".
- Revocation: entries are cleared on disable, uninstall, untrust or update. A missing service means the action is dropped and the entry closes.
B. sessions:activity + usage:read: read-only facts
usage.session {sessionId}→ theSessionTokenUsageunion already proposed indocs/metrics-and-telemetry.md, filled from the feat(usage): add quota history and session estimates #138 usage history. No account scope and no quota history.- Event
canvastty.sessions.eventtypetool:{sessionId, turnId, at, name, resultClass: success|error|denied|unknown, actionHash, errorHash?}. The hashes are HMAC with a per-plugin host key. There is no prompt, response or output text. parentSessionIdandroleare added tocanvastty.launch.prepareso the launch policy can apply budgets per task.- Disabled or not granted: nothing is sent, and PostToolUse hooks are not installed for it.
C. sessions:delegate: restart a subagent in its card
sessions.restart {sessionId, resume?}→{started}. Only for subagents of the orchestrator that called the plugin tool, where the host checks the parent; or for the card where the person clicked the plugin's action. It uses the normal launch pipeline, so refusals appear on the card.sessions.create {role: "orchestrator"}for a flow started from the preview.- Permission: install-time "can restart agents your orchestrator gives it".
- Revocation: the grant ends when the parent exits, the card closes, or the plugin is disabled or untrusted. Calls are idempotent; on timeout the card stays as it was.
- This also delivers an approved secret: it goes through the plugin's launch
secretEnvon restart, so the value never passes through tool output.
5. Not proposed
- The D0–D3 / execution-destination editor in core Agents settings.
- A flow picker in the launch dialog.
- The session inspector dashboard (timeline, usage, report and notification tabs).
- Core
model: "auto"/model:route, or plugin ids hard-coded in core. - Separate usage or cost tracking and pricing tables (feat(usage): add quota history and session estimates #138 covers this), terminal output history, process pause (SIGSTOP), and canvas edges or "Gather" between cards.
6. Phases (smallest first)
- feat: a worktree per subagent, a combined change review and rollback points #133 rebuilt on main (already accepted). Separately, narrow core bug fixes without UI.
- Plugin on existing APIs only:
route, flow preview, task tools, automatic review into the feat: a worktree per subagent, a combined change review and rollback points #133 dialog, command review, settings page. Signals appear as badges only. - Proposal A, then attention entries in the plugin.
- Proposal B, then budgets and loop detection after the call.
- Proposal C, only if retry in place and secret approval are still needed after phase 3.
Each phase ships Linux light/dark screenshots, a screenshot at --ui-scale ≠ 1, and Russian UI checks.
Activity