LearnNewsExamplesServices
Frontmatter
id15597
titlekimi-server wake route: discover v0.28 lock via server/instances dir
stateClosed
labels
bugairegression
assigneesneo-kimi-iris
createdAtJul 20, 2026, 1:05 PM
updatedAtJul 20, 2026, 1:19 PM
githubUrlhttps://github.com/neomjs/neo/issues/15597
authorneo-kimi-iris
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 20, 2026, 1:19 PM

kimi-server wake route: discover v0.28 lock via server/instances dir

Closed Backlog/active-chunk-8 bugairegression
neo-kimi-iris
neo-kimi-iris commented on Jul 20, 2026, 1:05 PM

Context

Operator directive this morning (2026-07-20): verify that A2A wake messages actually reach the kimi-code harness seat (@neo-kimi-iris). The seat's wake subscription was registered this morning (WAKE_SUB:ad94a336-7e4a-4534-9efb-331f413bb276, trigger SENT_TO_ME, adapter kimi-server), completing the day-1 handover pickup item. The fire/no-fire proof (#12913 shape) then isolated a hard breakage: the kimi CLI auto-updated v0.27.0 → v0.28.0 between sessions, and v0.28 deprecates kimi server ("no longer works — use kimi web instead") — and kimi web no longer writes ~/.kimi-code/server/lock. The adapter merged one day earlier (PR #15588) reads exactly that file.

The Problem

Verified evidence chain, all at current dev head on the Iris seat:

  1. Fire path works up to the delivery seam. Subscription registered 10:42Z → wake daemon detected the wake-worthy edge → correctly selected the kimi-server route → delivery attempt failed closed: kimi-server requires a readable server lock at '/Users/tobiasuhlig/.kimi-code/server/lock' (ENOENT) → 5 attempts → wake dropped (.neo-ai-data/wake-daemon/wake-daemon.log 10:50:07Z / 10:50:19Z, WAKE_SUB:ad94a336).
  2. No-fire path verified: a wakeSuppressed: true message produced zero daemon activity for the subscription.
  3. v0.28 contract change, verified empirically: kimi server prints a deprecation notice and exits non-zero; kimi web --no-open (v0.28.0) listens on loopback but writes no server/lock. Instead it writes ~/.kimi-code/server/instances/{server_id}.json shaped {server_id, pid, host, port, started_at, heartbeat_at, host_version} (heartbeat refreshes while the server lives).
  4. What survived the version bump: the bearer token (~/.kimi-code/server.token — byte-identical across the bump), the REST route (POST /api/v1/sessions/{session_id}/prompts present in v0.28's /openapi.json), and the wake-envelope contract (~/.kimi-code/wake-envelope.json, written by the seat's SessionStart hook).
  5. Delivery seam itself proven intact: a direct loopback POST to /api/v1/sessions/{live-TUI-session-id}/prompts injected a user message into the running TUI session mid-turn (delivery preempts the in-flight turn — steer-class semantics). So TUI sessions ARE wake-addressable; only lock discovery is broken.

Net: the daemon↔harness pipeline is correct end-to-end except one contract — server-coordinate discovery — which drifted in a same-day harness release.

The Architectural Reality

  • ai/daemons/wake/daemon.mjsdeliverViaKimiServer resolves coordinates at L1146-1150: lockPath = harnessTargetMetadata.lockPath override || ~/.kimi-code/server/lock; then reads + validates the lock (loopback host, port range) at L1177-1204, posts to the prompts route, and expects HTTP 200 + code: 0. The JSDoc contract block at L1125-1130 documents the v0.27 lock/token files as THE contract. The adapter deliberately fails closed (no fallback to osascript/tmux) so a misconfigured route surfaces loudly rather than delivering into the wrong surface.
  • Unit contracts live in test/playwright/unit/ai/daemons/wake/daemon.spec.mjs (the 50-contract suite from PR #15588).
  • Peer adapters with the same discovery shape (opencode-server, codex-app-server) resolve coordinates from their own envelope/lock files — this ticket does not audit them (see Out of Scope).
  • Related discussion substrate: D#15595's divergence window surfaced this class as OQ11 candidate — seat-local edge contracts across harness releases (comment DC_kwDODSospM4BDhUV). This ticket is the narrow operational fix, independent of that ideation track.

The Fix

Refactor lock discovery inside deliverViaKimiServer (plus a small helper) into a precedence chain:

  1. Explicit override winsharnessTargetMetadata.lockPath (existing test seam; unchanged).
  2. Legacy v0.27 path~/.kimi-code/server/lock, honored when present (back-compat for pinned seats).
  3. v0.28 instances scan — read ~/.kimi-code/server/instances/*.json, select the entry with the freshest heartbeat_at, and validate: pid liveness (process.kill(pid, 0)), heartbeat freshness (≤ ~60s), loopback host, integer port in range, non-empty server_id/host_version. Two or more live instances → fail closed with a descriptive ambiguity error (consistent with the adapter's existing fail-closed discipline; no wrong-instance routing). Zero live entries → fail closed with an actionable "no running kimi server found" error naming both contract shapes.

Update the JSDoc contract block (~L1125-1130) to document the two-shape discovery contract, and extend daemon.spec.mjs with focused contracts: override precedence, legacy path, instances path, freshest-heartbeat selection, ambiguity fail-closed, stale heartbeat fail-closed.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
harnessTargetMetadata.lockPath daemon.mjs:1148 (current code) Unchanged; override wins adapter JSDoc + openapi.yaml existing code + #15588 contracts
~/.kimi-code/server/lock kimi CLI v0.27.0 observed behavior Honored when present (back-compat) instances scan when absent adapter JSDoc yesterday's live probe (server ran 2026-07-19 22:03Z)
~/.kimi-code/server/instances/{server_id}.json kimi CLI v0.28.0 observed behavior (file shape cat'd) Primary discovery when legacy absent fail closed (ambiguous/stale/none) adapter JSDoc this morning's kimi web run + file contents
~/.kimi-code/server.token v0.27 + v0.28 observed (byte-identical value) Unchanged adapter JSDoc token compare this morning
POST /api/v1/sessions/{id}/prompts v0.28 /openapi.json Unchanged adapter JSDoc live in-session injection proof this morning
~/.kimi-code/wake-envelope.json SessionStart hook + daemon reads Unchanged hook + adapter JSDoc envelope written 08:54:01Z today

Decision Record impact

none — no ADR governs wake-adapter coordinate discovery. ADR 0014 classifies the wake-delivery lane as local-only but says nothing about harness coordinate mechanics.

Acceptance Criteria

  • Lock discovery precedence: explicit lockPath override → legacy server/lockserver/instances/*.json scan
  • Instances scan picks freshest heartbeat_at; validates pid liveness, heartbeat freshness, loopback host, port range
  • ≥2 live instances → fail closed with descriptive ambiguity error; 0 live instances → actionable "no running kimi server" error naming both contract shapes
  • test/playwright/unit/ai/daemons/wake/daemon.spec.mjs extended for all new paths; existing 50 contracts still green
  • JSDoc contract block updated to the two-shape discovery contract
  • (post-merge-only) Live fire/no-fire re-proof on the Iris seat: a daemon-delivered wake lands in-session via the v0.28 discovery path

Out of Scope

  • Seat-launch-contract policy (whether seats run kimi web resident, OS-service install, version pinning) — operator/harness-policy decision, surfaced in D#15595 OQ11.
  • opencode-server / codex-app-server adapter contract audits (separate tickets if their vendors drift).
  • Wake-delivery preemption semantics (steer-class interruption of in-flight turns) — observed and noted, not changed here.

Avoided Traps

  • Per-seat lockPath override pointing at a hand-maintained symlink — recreates per-seat folk state (the exact class D#15595 divergence #8 flags); the discovery must derive from the harness's own files.
  • Pinning the kimi CLI version — fights the harness's default auto-update; unenforceable across seats; treats a contract-drift class as a one-off.
  • Treating ENOENT as transient retry — it is a contract change; retries just burn 5 attempts and drop the wake.

Related

  • #15579 (kimi-server wake adapter ticket) · PR #15588 (merged adapter, v0.27 contract)
  • #15580 · PR #15587 (turn-presence adapter, @neo-gpt — open)
  • D#15595 comment DC_kwDODSospM4BDhUV (OQ11 candidate; context only — this ticket is NOT graduated from that Discussion)
  • #12913 (fire/no-fire proof shape)

Origin harness session: session_e86fa9f0-866e-45e8-a6df-d7bb6dd4d8b5 (kimi-code v0.28.0, Iris day-2 seat session; day-1 MC session: 958d6302-181d-40ae-beda-4c3790d3220d)

Retrieval Hint: query_raw_memories: "kimi-server wake adapter v0.28 server instances lock discovery" · anchor files ai/daemons/wake/daemon.mjs, test/playwright/unit/ai/daemons/wake/daemon.spec.mjs


Live latest-open sweep: checked latest 20 open issues at 2026-07-20T11:02Z (106 open total); no equivalent found. A2A in-flight sweep: list_messages all/30 at 11:03Z; no competing claim on this scope. KB semantic sweep (type=ticket) + local resources/content/** grep: no equivalent.