168 lines
8.4 KiB
Markdown
168 lines
8.4 KiB
Markdown
# Multi-work
|
|
|
|
`multi-work` is a **primary-only** agent for coordinating independent work in
|
|
Herdr-managed Git worktrees. Like `coordinate`, it uses the configured `deep-lo`
|
|
model and effort, falling back to `good-lo` when `deep-lo` is unavailable. No
|
|
extra custom model assignment is required.
|
|
|
|
```text
|
|
multi-work (root checkout)
|
|
├── fast-lo (local retrieval)
|
|
└── coordinate (new Herdr worktree)
|
|
└── existing leaf workers (that worktree)
|
|
```
|
|
|
|
## Availability
|
|
|
|
The agent appears when the plugin can verify a live, unambiguous Herdr root
|
|
workspace for the current **checkout root directory**, and coordinate/fast-lo are
|
|
available. Herdr and Git must be executable by the OpenCode server. The CLI uses
|
|
that server process's Herdr socket/session configuration; it never targets the
|
|
UI-focused workspace.
|
|
|
|
Eligibility is location-based: all OpenCode clients viewing the eligible location
|
|
can see the agent. This does not identify the client's pane. Linked worktrees,
|
|
subdirectories, closed workspaces, duplicate workspace ownership, unavailable CLI,
|
|
and failed discovery do not qualify. Missing workspace metadata is resolved using
|
|
Herdr's worktree inventory rather than assuming a Git root is a Herdr root.
|
|
|
|
The registry refreshes every 30 seconds. Every multi-work model turn and delegation
|
|
rechecks the executing session's location; creation revalidates the root again
|
|
immediately before its Git/Herdr operations. Stale picker visibility cannot authorize
|
|
creation. Creating/opening the root workspace remains a user action.
|
|
|
|
## Configuration
|
|
|
|
Use OpenCode **2.0.4**, the version this integration targets. At both the root and
|
|
destination locations, configure:
|
|
|
|
```jsonc
|
|
{
|
|
"experimental": { "subagent_depth": 2 },
|
|
}
|
|
```
|
|
|
|
The plugin does not modify your global configuration. Native OpenCode still
|
|
enforces nesting depth; its default of 1 is insufficient for coordinate's workers.
|
|
The public plugin context does not expose a configuration reader to preflight
|
|
the effective depth.
|
|
|
|
Each destination must load the multi-work-enabled plugin and the required worker
|
|
models. A global plugin installation/configuration is useful when source branches
|
|
have different project configuration. The tool checks the destination's live agent
|
|
registry for the coordinate protocol marker and required worker agents before
|
|
prompting. This checks feature availability, not the trustworthiness of other
|
|
plugins or project configuration.
|
|
|
|
## Delegation
|
|
|
|
Multi-work retains the native tool name, `subagent`. It adds one argument:
|
|
|
|
```js
|
|
subagent({
|
|
agent: "coordinate",
|
|
description: "Implement API change",
|
|
prompt: "Goal, scope, constraints, and acceptance checks...",
|
|
worktree: { base: "feature/source" },
|
|
background: true,
|
|
});
|
|
```
|
|
|
|
`base` identifies a locally available branch or remote-tracking branch. The tool
|
|
resolves its commit and creates a new unique `multi-work/<uuid>` branch with Herdr.
|
|
It does not fetch refs or copy uncommitted root changes. Herdr determines the
|
|
checkout path; the tool parses and verifies the returned checkout/workspace.
|
|
Creation explicitly preserves focus with `--no-focus`.
|
|
|
|
For focused retrieval, use native `subagent` with `agent: "fast-lo"` and no
|
|
`worktree`. Resume an owned coordinate child with its `sessionID` and **omit**
|
|
`worktree`. Resumes verify parent, agent, checkout, branch, and live Herdr ownership.
|
|
Bound coordinate children cannot be repurposed through native delegation.
|
|
|
|
Neither multi-work nor coordinate has general shell/edit permissions. Multi-work
|
|
also rejects non-reading/non-delegation tools at execution, including Code Mode,
|
|
even if a session permission override would expose them. Worktree preparation
|
|
requires effective `herdr_worktree: allow`, evaluated against the canonical root
|
|
directory using ordered agent and session rules. `ask` fails explicitly because
|
|
the public plugin API cannot request custom-tool approval. Native subagent
|
|
permissions are still asserted by OpenCode before preparation starts.
|
|
|
|
Worktree permissions inherit the base plugin's **effective build-permission
|
|
snapshot**, including configuration applied after plugin transforms. Its existing
|
|
`agent.updated` listener refreshes that snapshot and replays the registry when it
|
|
changes. Later `multi-work` agent rules and session rules retain their precedence;
|
|
inheritance does not turn a build deny into an unconditional execution-time veto
|
|
against an explicitly configured later allow.
|
|
|
|
## Native lifecycle and placement
|
|
|
|
The plugin composes the original **Effect executor** in place, preserving the
|
|
`subagent` tool identity, native child ancestry, progress/result metadata,
|
|
foreground results, background job handling, and completion notifications. It does
|
|
not create substitute top-level sessions or a separate job scheduler.
|
|
|
|
OpenCode 2.0.4 awaits a child-ID progress callback after child creation and before
|
|
prompting. The wrapper uses that boundary to create the worktree, move the explicit
|
|
child ID, and confirm its actual session location before allowing the task prompt.
|
|
A move-request acknowledgement alone is insufficient. Confirmation is bounded to
|
|
30 seconds and remains interruptible. The parent session does not move.
|
|
|
|
Coordinate is child-capable only through an owned, ready worktree binding. Prompt
|
|
admission and model-context guards reject unbound or moved coordinate children.
|
|
Multi-work cannot be a child, and the existing workers remain leaves.
|
|
|
|
Normal delegation cards and child navigation recognize the retained `subagent`
|
|
name. Children remain in the session family after moving; they do not become
|
|
top-level entries in root-session pickers. Moving a session does not attach an
|
|
OpenCode TUI to the new Herdr pane.
|
|
|
|
## Failures and verification limits
|
|
|
|
The plugin records the attempted child/branch and the returned worktree binding,
|
|
and reports progress IDs during preparation. Failed or interrupted initialization
|
|
does not admit the task prompt. It retains resources rather than deleting checkouts
|
|
or closing workspace groups. Inspect reported IDs and Herdr inventory before
|
|
retrying an ambiguous creation failure; CLI interruption cannot roll back a request
|
|
already accepted by Herdr. Unready children are not resumable as completed setups.
|
|
|
|
The ordinary suite uses isolated Git repositories and simulated Herdr responses.
|
|
It covers gating, source refs, ordering, failures, and interruption. Composite tests
|
|
run the exported plugin through the real Promise adapter, apply configuration after
|
|
both plugin transforms, replay twice, and test separate location registries sharing
|
|
disk-backed bindings across plugin scope restarts. Their executor is simulated.
|
|
|
|
An opt-in integration check runs the **real OpenCode 2.0.4 server and native
|
|
subagent executor**:
|
|
|
|
```sh
|
|
OPENCODE_204=/absolute/path/to/2.0.4/opencode bun scripts/test-multi-work-host.ts
|
|
```
|
|
|
|
It requires the exact-version binary (for Linux x64, published as
|
|
`@opencode/cli-linux-x64@2.0.4`), uses fresh HOME/XDG/config/database paths under
|
|
`/tmp/opencode`, and starts only loopback services. Herdr is a fake CLI performing
|
|
real Git worktree operations in the fixture repository; the model is a deterministic
|
|
HTTP endpoint. Fixture resources and logs are retained at the printed path.
|
|
|
|
Verified with this host check:
|
|
|
|
- Late configured build deny and a subsequent session allow.
|
|
- Native child creation/ancestry, confirmed move before first prompt, and foreground result.
|
|
- Separate root/destination plugin instances reading the host's persistent binding store.
|
|
- Resuming that child after a complete host restart, then native background completion
|
|
and its synthetic notification to the parent.
|
|
- Interrupting a foreground RPC while the child awaits its model response causes
|
|
the native executor to interrupt the child; the parent remains at the root.
|
|
|
|
The fixture RPC invokes the actual wrapped executor; it does not exercise the
|
|
parent model's tool-call dispatch or rendered tool cards. Recovery of an **in-flight**
|
|
job across a crash, coordinate-to-leaf nesting, background cancellation, live Herdr
|
|
focus/pane behavior, and TUI/web/mini navigation remain unverified end-to-end. A
|
|
completed child resumed after restart is not evidence of in-flight job recovery.
|
|
|
|
The progress boundary is version-sensitive, not a documented initialization hook.
|
|
Before upgrading OpenCode, verify native initialization order, foreground/background
|
|
interruption, notifications/recovery, and TUI/web/mini navigation after refresh.
|
|
Other authenticated clients/plugins are trusted: these guards are not an API-wide
|
|
sandbox, and cwd placement is not filesystem isolation for shell-capable workers.
|