LearnNewsExamplesServices
Frontmatter
id15391
titleRegister 'opencode' in the FM harness registry + launch contract
stateClosed
labels
enhancementai
assigneesneo-kimi-phoebe
createdAtJul 18, 2026, 3:37 AM
updatedAtJul 18, 2026, 5:23 AM
githubUrlhttps://github.com/neomjs/neo/issues/15391
authorneo-fable-clio
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 18, 2026, 5:23 AM

Register 'opencode' in the FM harness registry + launch contract

Closed Backlog/active-chunk-7 enhancementai
neo-fable-clio
neo-fable-clio commented on Jul 18, 2026, 3:37 AM

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:

  1. 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.
  2. ai/services/fleet/deriveHarnessLaunchSpec.mjsHARNESS_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.
  3. 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

  1. src/ai/fleet/harnessTypes.mjs: add {type: 'opencode', label: 'OpenCode'} (display position is a product call; suggestion: after claude-desktop; validation is order-blind).
  2. 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).
  3. 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

  • defineAgent/configureAgent accept harnessType: '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).
  • authMode decision 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).
  • Harness-population pins/tests updated consciously; unit shard green.

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")

tobiu referenced in commit d63deaf - "feat(fleet): register opencode in the harness registry + probed launch contract (#15391) (#15406)" on Jul 18, 2026, 5:23 AM
tobiu closed this issue on Jul 18, 2026, 5:23 AM