@mutmutco/opencode-mmi 2.55.0 → 2.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/opencode-mmi",
3
- "version": "2.55.0",
3
+ "version": "2.56.0",
4
4
  "description": "MMI Future OpenCode adapter — registers mmi, secrets, stage, rcand, release, hotfix, bootstrap, grind, overlord, build, handoff, coop, and browser-automation skills, workflow commands, and deterministic guardrail hooks.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,11 +1,12 @@
1
1
  ---
2
2
  name: coop
3
- description: Cross-repo, cross-PC multi-agent coordination coordinator + joiners, GitHub issue handshake, #mmi-agents bus, Hub wake. Use instead of send_message or ad-hoc Slack MCP in unsupervised mode.
3
+ description: Cross-repo, cross-PC multi-agent coordination through the #mmi-agents Slack channel, with a GitHub proof issue and Hub wake. Use instead of send_message or ad-hoc Slack MCP in unsupervised mode.
4
4
  ---
5
5
 
6
6
  # /coop — agent coordination
7
7
 
8
- Opt-in **multi-agent alignment** when parallel agents (different worktrees, IDEs, PCs, or repos) must handshake before merging or continuing.
8
+ Slack-first coordination for parallel agents in different worktrees, IDEs, PCs, or repos.
9
+ `#mmi-agents` is the live coordination surface. The GitHub issue is the proof/context record.
9
10
 
10
11
  ## When to use
11
12
 
@@ -17,23 +18,23 @@ Opt-in **multi-agent alignment** when parallel agents (different worktrees, IDEs
17
18
 
18
19
  - Serial merge train → use `wave land`
19
20
  - Session transfer → use `/handoff`
20
- - General Slack chat → not chatops; `#mmi-agents` + `COOP_*` protocol only
21
+ - General Slack chat → not chatops; `#mmi-agents` is only for the `COOP_*` protocol
21
22
 
22
23
  ## Quick start
23
24
 
24
- **Coordinator** (creates issue + posts `COOP_START`):
25
+ **Coordinator** (creates proof issue + posts `COOP_START` in `#mmi-agents`):
25
26
 
26
27
  ```bash
27
28
  mmi-cli coop start --repo mutmutco/MyRepo --message-file tmp/coop-open.md
28
29
  ```
29
30
 
30
- **Joiner**:
31
+ **Joiner** (joins the `#mmi-agents` coordination chat):
31
32
 
32
33
  ```bash
33
34
  mmi-cli coop join <coopId> [--cloud]
34
35
  ```
35
36
 
36
- **Handshake** (substance on the **GitHub issue**; Slack gets stubs):
37
+ **Handshake and information exchange** (substance in `#mmi-agents`; GitHub gets proof/context only):
37
38
 
38
39
  ```bash
39
40
  mmi-cli coop say <coopId> --phase HANDSHAKE_OPEN --message-file tmp/proposal.md
@@ -60,7 +61,8 @@ Hub dispatches wake on every coop message targeting joiners:
60
61
  ## Rules
61
62
 
62
63
  - **Never** use Claude `send_message` or harness-specific live chat for org coordination
63
- - **Substance on GitHub issue**; keep Slack stubs short
64
+ - Use `#mmi-agents` for the live handshake, questions, counters, constraints, and shared facts
65
+ - Use the GitHub issue for start context, proof links, decisions reached, and final outcome
64
66
  - Any **mutmutco org member** with a Hub session may join
65
67
  - Coordinator drives until `SHOOK` or explicit abort
66
68
 
@@ -18,6 +18,15 @@ unchanged.
18
18
  Read every issue (title, body, labels, linked code). First drop any **not-grindable** issue (per
19
19
  the Hard rule) — unclaimed, no branch/PR, just a line in the final report. Partition the rest into
20
20
  execution groups — **mode per group, not one global mode.** No override flags; you always decide.
21
+
22
+ **Pre-claim executable-set cap (#2118).** Before any `board claim`, estimate the grouped set against
23
+ this run's tier/caps. If the full requested set is heterogeneous enough that the run would predictably
24
+ hit cap/stuck — mixed unrelated subsystems, milestone-scale epics beside small bugs, or more groups than
25
+ the tier can execute within the bounded loop — shrink the executable set **before claiming**. Claim only
26
+ the first coherent batch/parallel wave that fits the cap. Leave later groups unclaimed and report them as
27
+ `queued-not-claimed` in the final report, or file/link a follow-up queue issue when the input did not
28
+ already have separate issues. Never move a whole board slice to In Progress merely because the user said
29
+ `--auto all`; ownership should reflect work actually entering this bounded run.
21
30
  - **Batch** → one shared worktree/branch → one PR that `Closes` every issue in the group. Stay
22
31
  there until PR/integration; don't bounce to main for routine re-sync. For issues
23
32
  that are facets of one change (same files/module, no independent value).
@@ -35,8 +44,9 @@ artifact counts as a shared file:** when 2+ items rebuild the same checked-in bu
35
44
  retest step for every follow-on PR, never treating the conflict as a surprise. A real set may mix
36
45
  modes (e.g.
37
46
  `{950,951}` batched, `{952}` parallel, `{953}` serialized after `952`). **Concurrency bound:**
38
- at most **3 grind loops run at once**; the rest queue. Claim every **partitioned** (grindable)
39
- issue `--for <login>` before its work, in every mode — never the not-grindable ones already dropped.
47
+ at most **3 grind loops run at once**; the rest queue. Claim every **partitioned + executable** (grindable,
48
+ inside this run's pre-claim cap) issue `--for <login>` before its work, in every mode — never the
49
+ not-grindable ones already dropped, and never the `queued-not-claimed` groups deferred by the pre-claim cap.
40
50
  If `/stage` is running, keep it attached to the active worktree; don't restart it for git
41
51
  bookkeeping. If a new worktree is truly needed, stop/destroy/recreate stage there, or warn
42
52
  first when intent is unclear.
@@ -25,31 +25,33 @@ it on every move). Closed/finished items auto-archive after they go quiet; archi
25
25
  for identity — `viewer` is for work items only (Step 1).
26
26
  - Known login → `👋 Welcome back, @<login> — pulling up your board…`
27
27
  - `source: unknown` → generic `👋 Welcome back — pulling up your board…`
28
- 2. **Run doctor preflight synchronously before `board read` when a heal may be needed (#1871).** A healthy
29
- setup stays **completely silent and fast** no background task, no "setup looks good" line. When the
30
- CLI or plugin is behind, the dev must see the wait **up front**, not after a silent multi-minute gap.
28
+ 2. **Keep the board fast: read first, run doctor only when evidence says it can change this render (#2112).**
29
+ The normal happy path is identity board read. Do **not** block the board on `doctor --preflight` just to
30
+ check freshness. Run doctor synchronously only after a hard signal that the current setup may be broken:
31
+ `mmi-cli` is missing, `board read` reports missing auth/project scope, the command surface is absent, or a
32
+ cached/session-start health line explicitly says a heal is needed.
31
33
 
32
34
  ```bash
33
- mmi-cli doctor --preflight # silent when healthy; upfront notice + eager heal when version/plugin update needed
34
- mmi-cli board read --json # Step 1 only after preflight (or greet-first on the all-green path)
35
+ mmi-cli board read --json # Step 1 first useful render on the happy path
36
+ mmi-cli doctor --preflight # only after a hard setup signal, or in the background after the render if needed
35
37
  ```
36
38
 
37
39
  `doctor --preflight` detects a stale npm global, plugin clone, or installed-plugin record and runs the
38
- same self-heal as interactive `doctor` — but prints `↻ Updating mmi tooling, one moment…` **before** the
39
- wait and a clear `↻ MMI tooling updated …` line when done (reload/restart guidance included). A behind
40
- npm global runs `npm install -g @mutmutco/cli@latest` (effective next invocation); a behind plugin clone
41
- fast-forwards (effective next session). On a Claude surface it also self-heals a **stale or duplicate
42
- installed plugin** it drives `claude plugin marketplace remove mmi` `claude plugin marketplace remove
43
- mutmutco` `claude plugin marketplace add mutmutco/MMI-Hub` → `claude plugin install mmi@mutmutco` (a
44
- fresh reinstall, never `claude plugin update`, which nests into itself past MAX_PATH on Windows and wipes
45
- the marketplace clone, #1126), collapses duplicate `mmi@mutmutco` rows in
46
- `~/.claude/plugins/installed_plugins.json` to one user-scope entry, and quarantines stale MMI-only cache
47
- dirs under Claude/Codex plugin caches while preserving the active/released version. Plugin updates still
48
- take effect after a reload: **restart Claude Code / run `/reload-plugins`** (native), or **reopen the
49
- workspace** (VS Code extension).
50
-
51
- - **All green** → `doctor --preflight` prints nothing; proceed straight to `board read`.
52
- - **Stale tooling** → relay the `↻` lines from stderr to the dev, then `board read`.
40
+ same self-heal as interactive `doctor` — but it belongs off the critical board path unless it has proof it
41
+ must heal. When it does run and prints `↻ Updating mmi tooling, one moment…`, relay that before waiting;
42
+ when it prints `↻ MMI tooling updated …`, relay the reload/restart guidance. A behind npm global runs
43
+ `npm install -g @mutmutco/cli@latest` (effective next invocation); a behind plugin clone fast-forwards
44
+ (effective next session). On a Claude surface it also self-heals a **stale or duplicate installed plugin**
45
+ it drives `claude plugin marketplace remove mmi` → `claude plugin marketplace remove mutmutco` → `claude
46
+ plugin marketplace add mutmutco/MMI-Hub` → `claude plugin install mmi@mutmutco` (a fresh reinstall, never
47
+ `claude plugin update`, which nests into itself past MAX_PATH on Windows and wipes the marketplace clone,
48
+ #1126), collapses duplicate `mmi@mutmutco` rows in `~/.claude/plugins/installed_plugins.json` to one
49
+ user-scope entry, and quarantines stale MMI-only cache dirs under Claude/Codex plugin caches while
50
+ preserving the active/released version. Plugin updates still take effect after a reload: **restart Claude
51
+ Code / run `/reload-plugins`** (native), or **reopen the workspace** (VS Code extension).
52
+
53
+ - **Fast path** → `whoami` then `board read`; no foreground doctor.
54
+ - **Hard setup signal** → run `doctor --preflight`, relay `↻` lines, then retry `board read` when appropriate.
53
55
  - **`mmi-cli: command not found`** → plugin PATH provisioning has not applied, or the standalone CLI is not installed.
54
56
  In Claude Code, reopen the session; if it persists, install the MMI plugin:
55
57
  `/plugin marketplace add mutmutco/MMI-Hub` → `/plugin install mmi@mutmutco` → `/reload-plugins`.
@@ -11,7 +11,7 @@ Default pool: 3 servants total: one `fugu-ultra` and two normal `fugu` servants.
11
11
 
12
12
  Allowed range: `--3` through `--6`. Exactly one servant is Ultra in every run.
13
13
 
14
- First supported engine: `codex-fugu` through the Overlord controller's PTY leash.
14
+ Supported engines: `codex-fugu` through the PTY leash and OpenCode/Fugu through session-backed `opencode run --session` routing. OpenCode is preferred when available because it exposes parseable JSON events, session ids, and completion state.
15
15
 
16
16
  ## Start Contract
17
17
 
@@ -23,7 +23,7 @@ First supported engine: `codex-fugu` through the Overlord controller's PTY leash
23
23
  6. Own worktrees, stage/dev servers, Playwright, browsers, PRs, merges, and cleanup.
24
24
  7. Keep servants leased until `/overlord stop`, `mmi-cli overlord stop`, or explicit controlled shutdown.
25
25
 
26
- CLI startup persists a gitignored run registry at `tmp/overlord/runs.json`, starts a durable controller, and lets the controller spawn servant PTYs. `mmi-cli overlord send <target> <message>` queues redirects into that registry so the controller can deliver them to live servant PTYs. The launch profile uses `-a never` plus explicit sandbox settings so routine servant tool calls do not bounce approval prompts back to the human.
26
+ CLI startup persists a gitignored run registry at `tmp/overlord/runs.json`, starts a durable controller, and lets the controller spawn servant PTYs or OpenCode sessions. `mmi-cli overlord send <target> <message>` queues redirects into that registry so the controller can route them to live servants. On OpenCode, redirects use `opencode run --session <session-id> -m sakana/fugu --format json <message>` and advance a real message lifecycle (`queuedAt`, `startedAt`, `completedAt`, `failedAt`) from JSON events. The launch profile uses `-a never` plus explicit sandbox settings where the engine supports them so routine servant tool calls do not bounce approval prompts back to the human.
27
27
 
28
28
  ## Reference Loading
29
29
 
@@ -37,16 +37,21 @@ Read only what the task requires:
37
37
  - `references/servant-liveness.md`: liveness lease and awaiting-human behavior.
38
38
  - `references/controller-orphan-guard.md`: abrupt close, stale heartbeat, adoption, exact stop, and uncertainty.
39
39
  - `references/codex-fugu-preflight.md`: setup, update, model, API key, and Windows/Git Bash path checks.
40
+ - `references/opencode-fugu-engine.md`: OpenCode preflight, JSON event parsing, session-backed mailbox, ledger, and liveness model.
40
41
  - `references/shell-adapters.md`: PowerShell, cmd, Git Bash, macOS zsh/bash, Linux bash/sh, and unknown-shell rules.
41
42
  - `references/state-schema.md`: durable run-state fields.
42
43
  - `references/failure-pressure-scenarios.md`: tests and lessons from the first Overlord design run.
43
44
 
44
45
  ## Hard Rules
45
46
 
47
+ - **Fugu only — never a sub-agent fallback.** Overlord servants are Fugu (`fugu-ultra` + `fugu`) driven through the Overlord controller. Never satisfy an Overlord run with platform sub-agents, `multi_agent_v1`, generic workers, or any non-Fugu agent pool — not as a primary path and not as a fallback when the Fugu controller is missing or inactive. If the Fugu controller cannot start, is inactive, or cannot prove readable/writable handles, stop and report `blocked: fugu-controller-unavailable` with diagnosis; do not simulate Overlord with other agents.
46
48
  - Do not spawn servants on an unreadable or undrivable surface.
47
- - Launch servants with explicit no-approval and sandbox profiles.
48
- - Treat routine approval prompts as launch-profile failures.
49
+ - **Probe the engine before launch.** Run the Codex/Fugu (or OpenCode) preflight + `--help`/status probe before any servant launch; never launch into an unprobed surface.
50
+ - Codex/Fugu PTY servants launch with explicit `-a never` (no-approval) and an appropriate `-s` sandbox profile — read-only for consultation, workspace-write only in an owned worktree. OpenCode servants use `opencode run --format json --session` and rely on the OpenCode session mailbox instead of PTY submit probing.
51
+ - **Any routine approval prompt during startup, planning, or assigned work is a launch-profile failure** — record and recover it, never hand-wave it away or train the human to approve routine commands. Consultation servants get read-only plus the disk-read permission ordinary host config reads need, or the Overlord performs those reads itself.
49
52
  - Probe submit behavior before sending real prompts.
53
+ - **Delivery is not execution.** `mmi-cli overlord send` records a `queued`/`started` lifecycle, not completion. A redirect counts as delivered only when the servant journal shows the assignment left the composer and produced a new useful signal. If text remains at the `›` composer prompt after a bounded interval, mark the servant `delivery-stuck-composer` and the message `failed` — never report it as ready or delivered.
54
+ - **No handoff after delivery = stalled, not ready.** When a servant stays `ready` but produces no non-TUI output after a bounded handoff-expected interval, mark it `stalled-after-delivery`; do not keep reporting it as ready.
50
55
  - Never rely on stale ACKs as liveness proof.
51
56
  - Never broad-kill by process name, title, shell name, or model command.
52
57
  - Never let servants mutate shared state without assigned ownership.
@@ -0,0 +1,104 @@
1
+ # OpenCode Fugu engine
2
+
3
+ OpenCode is the preferred Fugu engine when it is installed and exposes the required models.
4
+
5
+ ## Preflight
6
+
7
+ Before servant launch, verify:
8
+
9
+ - `opencode` is on PATH
10
+ - `opencode --version` returns a version
11
+ - `opencode models` lists `sakana/fugu` and `sakana/fugu-ultra`
12
+ - `opencode run -m sakana/fugu --format json "ACK probe"` emits parseable JSON events
13
+ - the event stream includes a session id, text, step start/finish, and a finish reason
14
+
15
+ Fail closed if any required fact is missing.
16
+
17
+ ## Session-backed servants
18
+
19
+ Start or resume servants through session ids.
20
+
21
+ Use normal servants with:
22
+
23
+ ```text
24
+ opencode run --session <session-id> -m sakana/fugu --format json <message>
25
+ ```
26
+
27
+ Use the Ultra servant with:
28
+
29
+ ```text
30
+ opencode run --session <session-id> -m sakana/fugu-ultra --format json <message>
31
+ ```
32
+
33
+ Record these facts in the run registry:
34
+
35
+ - `engine`
36
+ - `provider`
37
+ - `model`
38
+ - `opencodeSessionId`
39
+ - `opencodeVersion`
40
+ - `eventJournalPath`
41
+ - `lastEventAt`
42
+ - `lastMessageCompletedAt`
43
+
44
+ ## Mailbox lifecycle
45
+
46
+ A mailbox message is not complete when text is written.
47
+
48
+ Track:
49
+
50
+ - `queuedAt`
51
+ - `startedAt`
52
+ - `completedAt`
53
+ - `failedAt`
54
+ - `ackText`
55
+ - `responseText`
56
+ - `eventJournalPath`
57
+
58
+ `send` returns success only after a servant response is captured or a bounded failure is recorded.
59
+
60
+ ## Ledger and artifacts
61
+
62
+ Append servant outputs to:
63
+
64
+ ```text
65
+ tmp/overlord/<runId>/ledger.jsonl
66
+ ```
67
+
68
+ Artifact records are references, not side channels:
69
+
70
+ - `artifactId`
71
+ - `ownerSlotId`
72
+ - `kind`
73
+ - `version`
74
+ - `path`
75
+ - `status`
76
+ - `dependsOn`
77
+
78
+ The coordinator routes artifact refs between servants.
79
+
80
+ Servants do not directly own PRs, merges, releases, browser sessions, Playwright, shared stage servers, or cross-servant worktrees.
81
+
82
+ ## Liveness
83
+
84
+ Use JSON events as liveness signals.
85
+
86
+ Distinguish:
87
+
88
+ - idle
89
+ - running
90
+ - blocked
91
+ - failed
92
+ - lost
93
+
94
+ A ready servant that receives work but produces no non-TUI output before the bounded handoff interval is `stalled-after-delivery`.
95
+
96
+ A message pasted into a composer but not submitted is `delivery-stuck-composer`.
97
+
98
+ ## Stop and resume
99
+
100
+ Stop only exact run-owned OpenCode resources.
101
+
102
+ Prefer headless `opencode run --session` calls so fewer live PTYs need process ownership.
103
+
104
+ Resume from registry session ids, event journals, and the ledger.
@@ -33,15 +33,17 @@ Servant fields:
33
33
  - `role`
34
34
  - `model`
35
35
  - `profile`
36
- - `state`
36
+ - `state` (includes `stalled-after-delivery` for elapsed handoff windows, and `delivery-stuck-composer` when a redirect is pasted but unsubmitted)
37
37
  - `pid`
38
38
  - `runToken`
39
39
  - `fingerprint`
40
40
  - `composerSubmitMode`
41
+ - `opencodeSessionId`
41
42
  - `lastAckAt`
42
43
  - `lastLivenessCheckAt`
43
44
  - `lastUsefulSignalAt`
44
45
  - `journalPath`
46
+ - `eventJournalPath`
45
47
  - `assignment`
46
48
  - `handoff`
47
49
 
@@ -51,7 +53,14 @@ Message fields:
51
53
  - `target`
52
54
  - `text`
53
55
  - `createdAt`
54
- - `deliveredAt`
56
+ - `state` (`queued` | `started` | `completed` | `failed`)
57
+ - `queuedAt`
58
+ - `startedAt`
59
+ - `completedAt`
60
+ - `failedAt`
61
+ - `responseText`
62
+ - `failureReason`
63
+ - `deliveredAt` (legacy PTY-only; superseded by the lifecycle fields)
55
64
 
56
65
  Owned resource fields:
57
66