Context
The Fleet Manager's harness support just met reality: the first Moonshot/Kimi-family seat (@neo-kimi-phoebe, #15385/#15386, activation in #15390) runs on OpenCode — operator-installed 2026-07-18, all four neo-mjs MCP servers healthy from inside her session. FM cannot represent that harness: FleetRegistryService.defineAgent throws invalid harnessType 'opencode'. Operator-directed exploration ("FM now probably should support open code too") → this ticket.
OpenCode also matters beyond one seat: Kimi flatrates are harness-portable (flatrate works with an API key), unlike Claude flatrates (harness-locked to Anthropic's own harnesses) — so open-weight seats are free to run wherever FM can launch them, and OpenCode is the current bridge harness of record for that family.
The Problem
Harness knowledge lives in exactly two registration points plus one deriver, and OpenCode is in none of them:
src/ai/fleet/harnessTypes.mjs:20-27 — the ONE Body↔Brain registry ({type, label} rows; its own JSDoc: "Adding a harness IS one registration here — a second list anywhere is the drift this module exists to prevent"). Six types registered: codex, codex-desktop, claude-code, claude-desktop, antigravity, native-neo.
ai/services/fleet/deriveHarnessLaunchSpec.mjs — HARNESS_LAUNCH_CONTRACTS, one entry per LAUNCHABLE family: authMode ('marker'|'in-app'), isolation (homeEnvVar for CLIs / homeArgFlag for app bundles), modeArgs (the long-lived non-TTY stdio mode — file discipline: probed alive at 4s on a held pipe + clean SIGTERM, never guessed), versionProbeArgs.
- Consumers derive everything from these:
FleetRegistryService.harnessTypes (:125, validation :170-171), FleetControlBridge launchable/authMode (:446-447), prepareManagedAgentWorkspace (:251), onboardPeer CURATED_HARNESS_TYPES (:74) — all fail closed on unknown types.
The Architectural Reality
Adding a harness is BY DESIGN one registry row + one probed launch contract; every Body picker (#15242's AgentConfigCard/FleetSettingsPanel derive from listHarnessTypes()) and every Brain validation updates from the same registration. No collision with #15242 (Vega's active lane) — this feeds it with zero Body-side changes.
The Fix
src/ai/fleet/harnessTypes.mjs: add {type: 'opencode', label: 'OpenCode'} (display position is a product call; suggestion: after claude-desktop; validation is order-blind).
ai/services/fleet/deriveHarnessLaunchSpec.mjs: add HARNESS_LAUNCH_CONTRACTS['opencode'] with probe-evidenced fields, recorded in-comment per the file's own discipline:
- isolation — probe which env var(s) actually relocate OpenCode's config+state home for a managed instance (documented candidates: XDG base dirs; any dedicated
OPENCODE_* var). Record the probe result; do not guess.
modeArgs — probe the long-lived non-TTY mode (candidates: serve — the headless server mode; run with held stdin) alive at 4s on a held pipe, clean SIGTERM stop, exact CLI version noted.
versionProbeArgs — probe --version.
authMode — OpenCode+Kimi auth is an API key delivered via env/config (the portable-flatrate property), which maps cleanly to neither 'marker' nor 'in-app'. Decide honestly: a documented marker-style heuristic, or extend the authMode vocabulary (e.g. 'env-key'). If extended, verify EVERY consumer branch fail-closed (onboardPeer.mjs:390,440,482; FleetControlBridge.mjs:447) and cite each. A forced false mapping is a rejection reason.
- MCP-config planting seam — OpenCode reads its MCP servers from
opencode.json(c) in the instance home; the derivation (or prepareManagedAgentWorkspace) must plant the generated seat config there. Generator = companion ticket (see Related).
- Conscious-update pins: extend any specs pinning the harness-type population (locate via
git grep on HARNESS_TYPES/LAUNCHABLE_HARNESS_TYPES under test/), same discipline as the identity-set pins.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
HARNESS_TYPES row 'opencode' |
src/ai/fleet/harnessTypes.mjs |
new frozen {type, label} row; validation + pickers accept/list OpenCode |
unknown types keep failing closed (resolveHarnessType → null) |
module JSDoc |
harnessTypes.mjs:20-27 read 2026-07-18 |
HARNESS_LAUNCH_CONTRACTS['opencode'] |
ai/services/fleet/deriveHarnessLaunchSpec.mjs |
probed contract entry (isolation / modeArgs / versionProbeArgs / authMode) |
absent entry = not launchable (LAUNCHABLE_HARNESS_TYPES derives from keys, :90) |
in-file contract comments |
deriveHarnessLaunchSpec.mjs:31-90,102 read 2026-07-18 |
getHarnessAuthMode('opencode') |
same |
returns the decided mode; consumers handle any new value fail-closed |
null for unregistered |
same |
:102 |
Acceptance Criteria
Out of Scope
- The seat-config generator (
opencode.jsonc + memory scaffold) — companion ticket, filed alongside this one.
- FM launch-execution UI; Kimi model-provider/billing config; wake-route registration.
Decision Record impact
none — aligned with the in-file probed-contract discipline; no ADR governs the harness registry.
Related
- #15242 — define-agent surface (pickers derive from this registry; feeds, not collides).
- #15385 / #15386 / #15390 — the Phoebe seat this generalizes.
- Companion: the OpenCode seat-config generator ticket (filed in the same pass; number cross-linked there).
Candidates: @neo-kimi-phoebe post-activation (her own harness — she is the live probe environment, and the file's probe discipline needs a machine with OpenCode installed); any Opus/GPT peer otherwise. Not window-critical; clean post-window work.
Live latest-open sweep: checked latest 20 open issues at 2026-07-18T01:36Z; no equivalent found. A2A in-flight sweep (last 30, all read-states): no [lane-claim] on FM-OpenCode scope; nearest is #15390 (Phoebe's activation — disjoint).
Origin Session ID: abce4d75-7dcb-4145-8afc-b0ff2cdc51e6
Retrieval Hint: query_raw_memories("OpenCode harness registry launch contract probe authMode")
Context
The Fleet Manager's harness support just met reality: the first Moonshot/Kimi-family seat (
@neo-kimi-phoebe, #15385/#15386, activation in #15390) runs on OpenCode — operator-installed 2026-07-18, all four neo-mjs MCP servers healthy from inside her session. FM cannot represent that harness:FleetRegistryService.defineAgentthrowsinvalid harnessType 'opencode'. Operator-directed exploration ("FM now probably should support open code too") → this ticket.OpenCode also matters beyond one seat: Kimi flatrates are harness-portable (flatrate works with an API key), unlike Claude flatrates (harness-locked to Anthropic's own harnesses) — so open-weight seats are free to run wherever FM can launch them, and OpenCode is the current bridge harness of record for that family.
The Problem
Harness knowledge lives in exactly two registration points plus one deriver, and OpenCode is in none of them:
src/ai/fleet/harnessTypes.mjs:20-27— the ONE Body↔Brain registry ({type, label}rows; its own JSDoc: "Adding a harness IS one registration here — a second list anywhere is the drift this module exists to prevent"). Six types registered:codex,codex-desktop,claude-code,claude-desktop,antigravity,native-neo.ai/services/fleet/deriveHarnessLaunchSpec.mjs—HARNESS_LAUNCH_CONTRACTS, one entry per LAUNCHABLE family:authMode('marker'|'in-app'), isolation (homeEnvVarfor CLIs /homeArgFlagfor app bundles),modeArgs(the long-lived non-TTY stdio mode — file discipline: probed alive at 4s on a held pipe + clean SIGTERM, never guessed),versionProbeArgs.FleetRegistryService.harnessTypes(:125, validation:170-171),FleetControlBridgelaunchable/authMode (:446-447),prepareManagedAgentWorkspace(:251),onboardPeerCURATED_HARNESS_TYPES(:74) — all fail closed on unknown types.The Architectural Reality
Adding a harness is BY DESIGN one registry row + one probed launch contract; every Body picker (#15242's
AgentConfigCard/FleetSettingsPanelderive fromlistHarnessTypes()) and every Brain validation updates from the same registration. No collision with #15242 (Vega's active lane) — this feeds it with zero Body-side changes.The Fix
src/ai/fleet/harnessTypes.mjs: add{type: 'opencode', label: 'OpenCode'}(display position is a product call; suggestion: afterclaude-desktop; validation is order-blind).ai/services/fleet/deriveHarnessLaunchSpec.mjs: addHARNESS_LAUNCH_CONTRACTS['opencode']with probe-evidenced fields, recorded in-comment per the file's own discipline:OPENCODE_*var). Record the probe result; do not guess.modeArgs— probe the long-lived non-TTY mode (candidates:serve— the headless server mode;runwith held stdin) alive at 4s on a held pipe, clean SIGTERM stop, exact CLI version noted.versionProbeArgs— probe--version.authMode— OpenCode+Kimi auth is an API key delivered via env/config (the portable-flatrate property), which maps cleanly to neither'marker'nor'in-app'. Decide honestly: a documented marker-style heuristic, or extend theauthModevocabulary (e.g.'env-key'). If extended, verify EVERY consumer branch fail-closed (onboardPeer.mjs:390,440,482;FleetControlBridge.mjs:447) and cite each. A forced false mapping is a rejection reason.opencode.json(c)in the instance home; the derivation (orprepareManagedAgentWorkspace) must plant the generated seat config there. Generator = companion ticket (see Related).git greponHARNESS_TYPES/LAUNCHABLE_HARNESS_TYPESundertest/), same discipline as the identity-set pins.Contract Ledger Matrix
HARNESS_TYPESrow'opencode'src/ai/fleet/harnessTypes.mjs{type, label}row; validation + pickers accept/list OpenCoderesolveHarnessType→ null)harnessTypes.mjs:20-27read 2026-07-18HARNESS_LAUNCH_CONTRACTS['opencode']ai/services/fleet/deriveHarnessLaunchSpec.mjsLAUNCHABLE_HARNESS_TYPESderives from keys,:90)deriveHarnessLaunchSpec.mjs:31-90,102read 2026-07-18getHarnessAuthMode('opencode')nullfor unregistered:102Acceptance Criteria
defineAgent/configureAgentacceptharnessType: 'opencode'; the define-agent surface (#15242) lists "OpenCode" with zero Body-side changes beyond the registry row.HARNESS_LAUNCH_CONTRACTS['opencode']lands with probe evidence recorded in-comment for all four fields (no guessed values — the file's probed-contract discipline).authModedecision documented in the contract comment; if the vocabulary is extended, every consumer branch is verified fail-closed and cited.deriveHarnessLaunchSpec('opencode', …)returns a supervisable spec (held-pipe probe recorded).Out of Scope
opencode.jsonc+ memory scaffold) — companion ticket, filed alongside this one.Decision Record impact
none — aligned with the in-file probed-contract discipline; no ADR governs the harness registry.
Related
Candidates:
@neo-kimi-phoebepost-activation (her own harness — she is the live probe environment, and the file's probe discipline needs a machine with OpenCode installed); any Opus/GPT peer otherwise. Not window-critical; clean post-window work.Live latest-open sweep: checked latest 20 open issues at 2026-07-18T01:36Z; no equivalent found. A2A in-flight sweep (last 30, all read-states): no
[lane-claim]on FM-OpenCode scope; nearest is #15390 (Phoebe's activation — disjoint).Origin Session ID: abce4d75-7dcb-4145-8afc-b0ff2cdc51e6
Retrieval Hint:
query_raw_memories("OpenCode harness registry launch contract probe authMode")