Context
Leaf of Epic #15586 (Full Kimi Code support in the Neo Agent Harness / Fleet Manager), decomposed at the epic's own precondition — both harness adapters are now production-proven (wake: fire/no-fire + #15596/PR #15600 merged; presence: #15580 → PR #15587 at ready-flip). Two kimi seats exist, and both were hand-built: Phoebe's OpenCode seat (2026-07-18, productized as generateOpenCodeSeatConfig.mjs) and the Iris seat (2026-07-19, hand-provisioned — its config.toml + hook wiring is the living reference). A third kimi seat today means hand-building again. The generator needs a Kimi Code target, and the launch-template registry needs the harness type it hangs on.
Live latest-open sweep: checked latest 20 open issues at 2026-07-20 ~15:55Z — no equivalent (#15392 is the seat-config generator surface this leaf extends, not a duplicate; #15592 per-seat evidence records is adjacent-not-duplicate). A2A in-flight sweep (last 30, all read-states): no competing claim on this scope.
The Problem
- Registry gap:
src/ai/fleet/harnessTypes.mjs (HARNESS_TYPES) has no 'kimi-code' entry — and deriveHarnessLaunchSpec.mjs's import-time lockstep guard enforces that a launch contract can only exist for a registered type, so every Kimi launch/steer surface is blocked at the registry.
- Launch-contract gap: the per-family launch template (isolation home, supervisable mode, version probe, auth mode) is undefined for Kimi Code. The contract facts are knowable but unprobed:
KIMI_CODE_HOME is the harness's config/state home env var (official docs), kimi web is the resident server mode (v0.28; --port, bearer auth, /api/v1/sessions/* REST surface verified live 2026-07-20), auth rides the seat env (flatrate API key) or OAuth file storage. Which mode is supervisable (EOF-stdin tolerance, SIGTERM cleanliness, port auto-assign) needs the same empirical probe evidence the sibling contracts carry.
- Generator gap:
generateOpenCodeSeatConfig.mjs emits the OpenCode seat (opencode.jsonc + memory-layer scaffold + wake boot hook) as a pure params→files emission. No Kimi sibling exists: the seat's config.toml (permission rules per MCP server, provider/model blocks, hooks array), the SessionStart wake-envelope hook, and the always-loaded memory-layer wiring are all hand-authored per seat today.
The Architectural Reality
ai/services/fleet/generateOpenCodeSeatConfig.mjs — the sibling precedent: pure emission (no config imports/env/fs), island guard (server code resolves inside the canonical checkout), seat-personal --env-file binding, memory-layer scaffold with story-sovereignty (identity.md near-empty by construction).
ai/services/fleet/deriveHarnessLaunchSpec.mjs — contract map + lockstep guard; the 'opencode' entry (serve mode, XDG two-var isolation, env-key auth, --version probe) is the shape the Kimi entry mirrors.
src/ai/fleet/harnessTypes.mjs — the shared registry authority the Body's pickers/cards also derive from (one registration feeds both hemispheres).
- The Iris seat's hand-built reference (verified 2026-07-20):
~/.kimi-code/config.toml (permission rules per mcp__neo-mjs-* server; managed:kimi-code provider + OAuth file storage; K3 model block; [[hooks]] SessionStart → .kimi-code/hooks/wakeEnvelopeHook.mjs + the presence-hook family once #15580 lands); the MCP server set is the same four canonical servers (OPENCODE_SEAT_SERVERS shape — kimi wiring path to be pinned at implementation: project-level .kimi-code/ vs home-level config).
- Kimi has no OpenCode-style
instructions slot — the day-two reload lesson (identity.md present but not auto-loaded) proves the always-loaded layer needs a deliberate wiring decision for this harness (candidate surfaces: seat-checkout AGENTS.md pointer, harness memory config if shipped). This is a named design question, not an afterthought — a generated seat that forgets its identity layer is worse than none.
- Runner-shape seam (epic steward note, 2026-07-20): seats exist as TUI-hosted vs server-hosted runners with different wake-addressability; the generated config must produce the wake-addressable shape by default (resident server + envelope hook), with the TUI shape as the documented interactive alternative.
The Fix
- Register the type: add
{type: 'kimi-code', label: 'Kimi Code'} to HARNESS_TYPES (lockstep guard then passes; Body pickers inherit).
- Launch contract in
HARNESS_LAUNCH_CONTRACTS: homeEnvVar: 'KIMI_CODE_HOME', authMode: 'env-key' (flatrate API key rides seat env; OAuth file storage documented as the interactive alternative), versionProbeArgs: ['--version'], supervisable modeArgs determined by probe (kimi web --no-open --port … resident server vs documented alternative) — with the probe evidence recorded in the JSDoc exactly as the sibling contracts do (EOF/held-pipe liveness, SIGTERM-clean stop, port assignment, isolation census under a fresh KIMI_CODE_HOME).
generateKimiSeatConfig.mjs (sibling, pure emission): emits config.toml (canonical four-server MCP wiring + permission allow rules + provider/model defaults + hooks array), the SessionStart wake-envelope hook script (standalone node, C1-clean, mode 0600 envelope — the #15596 coordinate contract by construction), and the memory-layer scaffold with the always-loaded wiring decided per the design question above. Island guard + seat-personal --env-file discipline mirrored.
- Unit specs in the existing fleet/generator spec family: registry/lockstep, contract derivation (isolation env, probe args, password-free emission), emission content (TOML parses, hook script parses, island guard rejects escapes, identity.md stays near-empty).
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
HARNESS_TYPES registry |
src/ai/fleet/harnessTypes.mjs |
'kimi-code' registered |
lockstep guard throws on drift |
module JSDoc |
unit: registry subset |
| Launch contract |
deriveHarnessLaunchSpec.mjs |
kimi-code entry per above |
unknown type throws (existing) |
fn JSDoc probe record |
unit: derivation |
KIMI_CODE_HOME |
Kimi Code official docs (config-files/data-locations) |
Isolation home env var |
n/a |
launch contract JSDoc |
live: doctor/config reads |
kimi web resident mode |
v0.28.0 observed behavior |
Supervisable server shape (probed) |
documented alternative if probe fails |
launch contract JSDoc |
probe: liveness/SIGTERM/port |
generateKimiSeatConfig.mjs |
new sibling module |
Pure params→files emission |
n/a |
module JSDoc |
unit: emission specs |
Decision Record impact: aligned-with ADR 0020 (agent harness seat architecture — this leaf is the Kimi target of its seat-config/launch surfaces, not a new shape). Also consumes (does not amend) the ADR 0019 SSOT discipline: the generator stays a pure emission with zero config imports.
Acceptance Criteria
Out of Scope
- The cockpit driver/registry UI surface (Epic #15586's sibling leaf — roster/definitions/rails).
- Presence-hook emission beyond the wiring seam (owned by #15580/PR #15587's contract; this leaf wires the hook array, it does not redefine presence semantics).
- Wake-policy / heartbeat floors (
#15405 owns).
Avoided Traps
- Kimi-specific branches in generic FM surfaces — one registry entry + one contract + one sibling generator; nothing kimi leaks into shared paths (the epic's core anti-trap).
- Hand-copying the Iris seat's config.toml as the template — the hand-built seat carries liveproof/personal residue; the emission derives from the canonical pattern (like the OpenCode generator), with the seat's file as evidence, not as the source.
- Emitting credentials — tokens/OAuth material never enter emitted files; auth stays seat-env/OAuth-store at call time (the opencode envelope discipline, mirrored).
Related
- Epic #15586 (parent) ·
#15579/PR #15588 + #15596/PR #15600 (wake adapter, proven) · #15580/PR #15587 (presence hooks) · #15392 (seat-config generator surface) · #15390 × #15581 (harness-diff pair-zero) · ADR 0020 · D#15595 OQ11 (harness-server residency — the runner-shape seam's design home)
Origin Session ID: session_e86fa9f0-866e-45e8-a6df-d7bb6dd4d8b5 (kimi-code session, Iris seat)
Handoff Retrieval Hints: query_raw_memories("kimi seat config generator harness launch contract KIMI_CODE_HOME"); living reference = the Iris seat's hand-built ~/.kimi-code/config.toml + .kimi-code/hooks/wakeEnvelopeHook.mjs; sibling pattern = ai/services/fleet/generateOpenCodeSeatConfig.mjs + its spec family.
Context
Leaf of Epic #15586 (Full Kimi Code support in the Neo Agent Harness / Fleet Manager), decomposed at the epic's own precondition — both harness adapters are now production-proven (wake: fire/no-fire +
#15596/PR #15600 merged; presence: #15580 → PR #15587 at ready-flip). Two kimi seats exist, and both were hand-built: Phoebe's OpenCode seat (2026-07-18, productized asgenerateOpenCodeSeatConfig.mjs) and the Iris seat (2026-07-19, hand-provisioned — itsconfig.toml+ hook wiring is the living reference). A third kimi seat today means hand-building again. The generator needs a Kimi Code target, and the launch-template registry needs the harness type it hangs on.Live latest-open sweep: checked latest 20 open issues at 2026-07-20 ~15:55Z — no equivalent (
#15392is the seat-config generator surface this leaf extends, not a duplicate;#15592per-seat evidence records is adjacent-not-duplicate). A2A in-flight sweep (last 30, all read-states): no competing claim on this scope.The Problem
src/ai/fleet/harnessTypes.mjs(HARNESS_TYPES) has no'kimi-code'entry — andderiveHarnessLaunchSpec.mjs's import-time lockstep guard enforces that a launch contract can only exist for a registered type, so every Kimi launch/steer surface is blocked at the registry.KIMI_CODE_HOMEis the harness's config/state home env var (official docs),kimi webis the resident server mode (v0.28;--port, bearer auth,/api/v1/sessions/*REST surface verified live 2026-07-20), auth rides the seat env (flatrate API key) or OAuth file storage. Which mode is supervisable (EOF-stdin tolerance, SIGTERM cleanliness, port auto-assign) needs the same empirical probe evidence the sibling contracts carry.generateOpenCodeSeatConfig.mjsemits the OpenCode seat (opencode.jsonc+ memory-layer scaffold + wake boot hook) as a pure params→files emission. No Kimi sibling exists: the seat'sconfig.toml(permission rules per MCP server, provider/model blocks, hooks array), the SessionStart wake-envelope hook, and the always-loaded memory-layer wiring are all hand-authored per seat today.The Architectural Reality
ai/services/fleet/generateOpenCodeSeatConfig.mjs— the sibling precedent: pure emission (no config imports/env/fs), island guard (server code resolves inside the canonical checkout), seat-personal--env-filebinding, memory-layer scaffold with story-sovereignty (identity.mdnear-empty by construction).ai/services/fleet/deriveHarnessLaunchSpec.mjs— contract map + lockstep guard; the'opencode'entry (servemode, XDG two-var isolation,env-keyauth,--versionprobe) is the shape the Kimi entry mirrors.src/ai/fleet/harnessTypes.mjs— the shared registry authority the Body's pickers/cards also derive from (one registration feeds both hemispheres).~/.kimi-code/config.toml(permission rules permcp__neo-mjs-*server;managed:kimi-codeprovider + OAuth file storage; K3 model block;[[hooks]]SessionStart →.kimi-code/hooks/wakeEnvelopeHook.mjs+ the presence-hook family once #15580 lands); the MCP server set is the same four canonical servers (OPENCODE_SEAT_SERVERSshape —kimiwiring path to be pinned at implementation: project-level.kimi-code/vs home-level config).instructionsslot — the day-two reload lesson (identity.md present but not auto-loaded) proves the always-loaded layer needs a deliberate wiring decision for this harness (candidate surfaces: seat-checkout AGENTS.md pointer, harness memory config if shipped). This is a named design question, not an afterthought — a generated seat that forgets its identity layer is worse than none.The Fix
{type: 'kimi-code', label: 'Kimi Code'}toHARNESS_TYPES(lockstep guard then passes; Body pickers inherit).HARNESS_LAUNCH_CONTRACTS:homeEnvVar: 'KIMI_CODE_HOME',authMode: 'env-key'(flatrate API key rides seat env; OAuth file storage documented as the interactive alternative),versionProbeArgs: ['--version'], supervisablemodeArgsdetermined by probe (kimi web --no-open --port …resident server vs documented alternative) — with the probe evidence recorded in the JSDoc exactly as the sibling contracts do (EOF/held-pipe liveness, SIGTERM-clean stop, port assignment, isolation census under a freshKIMI_CODE_HOME).generateKimiSeatConfig.mjs(sibling, pure emission): emitsconfig.toml(canonical four-server MCP wiring + permission allow rules + provider/model defaults + hooks array), the SessionStart wake-envelope hook script (standalone node, C1-clean, mode 0600 envelope — the#15596coordinate contract by construction), and the memory-layer scaffold with the always-loaded wiring decided per the design question above. Island guard + seat-personal--env-filediscipline mirrored.Contract Ledger Matrix
HARNESS_TYPESregistrysrc/ai/fleet/harnessTypes.mjs'kimi-code'registeredderiveHarnessLaunchSpec.mjsKIMI_CODE_HOMEkimi webresident modegenerateKimiSeatConfig.mjsDecision Record impact:
aligned-with ADR 0020(agent harness seat architecture — this leaf is the Kimi target of its seat-config/launch surfaces, not a new shape). Also consumes (does not amend) the ADR 0019 SSOT discipline: the generator stays a pure emission with zero config imports.Acceptance Criteria
'kimi-code'registered inHARNESS_TYPES; lockstep guard green; Body pickers derive the type from the same entrygenerateKimiSeatConfig.mjsemits config.toml + wake hook + memory scaffold; TOML/hook parse checks green; island guard rejects canonicalRoot escapesnpx playwright test)#15596contract held by construction)Out of Scope
#15405owns).Avoided Traps
Related
#15579/PR #15588 +#15596/PR #15600 (wake adapter, proven) ·#15580/PR #15587 (presence hooks) ·#15392(seat-config generator surface) ·#15390×#15581(harness-diff pair-zero) · ADR 0020 · D#15595 OQ11 (harness-server residency — the runner-shape seam's design home)Origin Session ID: session_e86fa9f0-866e-45e8-a6df-d7bb6dd4d8b5 (kimi-code session, Iris seat)
Handoff Retrieval Hints:
query_raw_memories("kimi seat config generator harness launch contract KIMI_CODE_HOME"); living reference = the Iris seat's hand-built~/.kimi-code/config.toml+.kimi-code/hooks/wakeEnvelopeHook.mjs; sibling pattern =ai/services/fleet/generateOpenCodeSeatConfig.mjs+ its spec family.