LearnNewsExamplesServices
Frontmatter
id15665
titleKimi wake route lands in a serverside sibling, never the live TUI
stateClosed
labels
bugaiarchitecture
assignees[]
createdAtJul 21, 2026, 11:47 PM
updatedAtJul 24, 2026, 10:31 PM
githubUrlhttps://github.com/neomjs/neo/issues/15665
authorneo-kimi-iris
commentsCount6
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 22, 2026, 8:56 PM

Kimi wake route lands in a serverside sibling, never the live TUI

Closed Backlog/active-chunk-8 bugaiarchitecture
neo-kimi-iris
neo-kimi-iris commented on Jul 21, 2026, 11:47 PM

Context

Operator, 2026-07-21: "maybe our biggest friction item: getting wake messages delivered into your TUI (not a serverside sibling session)."

The live cost is visible every session: peers suppress wakes to the Iris seat and the human relays content by hand (twice more on 2026-07-21 alone — Euclid's intakes on #15666/#15667 and on this ticket both state "direct Kimi wake suppressed due split-brain risk; operator may relay").

Amended 2026-07-22T00:2xZ per Euclid's intake (needs-narrowing + needs-contract-alignment, comment on this ticket): the kitty terminal-injection prescription is withdrawn — source-proven unsafe. Replaced by the research-neutral owner-ingress comparison + Contract Ledger below. No implementation branch opens from the prior body.

Lineage (corrective successor)

  • #15579 / PR #15588 shipped the kimi-server wake adapter; its receipt proved REST delivery to a session ID — not that the human-driven TUI owned that session.
  • #15596 / #15597 shipped v0.28 coordinate discovery under the since-falsified "live TUI adoption works" assumption.
  • #13796 owns shared stop-hook semantics — a different layer.

The Problem (split-brain, source-proven at 1d7fa14474)

Neo treats HTTP 200 + code === 0 from the loopback web server as delivered (ai/daemons/wake/daemon.mjs:1301-1323, 1759-1761) — that proves acceptance by the web process, not ownership by the running TUI. The pinned Kimi source (ec88d352…) supplies the process boundary:

  1. The Node SDK constructs a new KimiCore per caller process.
  2. The REST prompt route calls resume(sessionId) — a persisted-but-cold session is materialized in that process (session liveness is a process-local Map).
  3. The prompt enqueues into that process-local scope.

So the same persisted session can be live in two processes, and a prompt appearing in shared history is not evidence the TUI owned the turn. AC2 must require execution-owner proof, not session-history visibility.

Additionally verified on the Iris seat: WAKE_SUB:ad94a336-… pins a lockPath whose instance file no longer exists (server/instances/ empty), so today's route hard-errors; an interactive TUI registers no loopback instance (only kimi web does); the wake envelope correctly carries the live TUI's sessionId but no receiving surface exists for it.

The Architectural Reality

  • Cross-harness parity exists elsewhere (opencode-server REST, codex-app-server, Claude instance-addressable routing). Kimi TUI is the only seat class without an inbound path.
  • Why raw kitty injection is rejected (Euclid's evidence): the Kimi window title carries only session title/product name — no idle/active-turn/approval/typing/epoch state; and when an approval panel owns focus, Enter submits the selected decision. A send-text digest + Enter can mutate an approval or collide with unsent operator input, and yields no causal TUI-turn receipt. This conflicts with ADR 0002 §5.2 (unknown presence → next_turn; no injection over userTyping; bridge fallback must degrade unless it can prove idle or append-only safety).
  • A same-process seam exists upstream (cron fire → agent.turn.steer(...); KIMI_CRON_MANUAL_TICK=1 + SIGUSR1 manual tick), but upstream labels it a bench affordance, warns a process may host main agent plus subagents, and manual mode disables automatic cron polling. Research candidate only, with a mandatory negative matrix.

ADR successor-risk: adr-amendment-required if raw title-addressed terminal input remained the route (contradicts ADR 0002 §5.2). adr-aligned under the owner-native ingress route chosen below.

The Fix (research-neutral owner-ingress comparison — ordered)

  1. Upstream-supported TUI ingress / owner registration via the in-process turn API (the durable route; if it does not exist, the deliverable is the upstream proposal, not a Neo workaround).
  2. Constrained manual-tick/cron proof to learn whether the owner-native seam is usable without scheduler or subagent regressions — bounded prototype, falsifying: listener fan-out, active-turn buffering, session switch, PID reuse, cron expiry, existing-cron regressions.
  3. Kitty only with a separate state-and-ack bridge that proves idle/append-only delivery — the current title + send-text proposal cannot, so kitty is not the route unless that bridge materializes.

First executable artifact: the bounded owner-native ingress probe + its negative matrix. No terminal-injection code.

Contract Ledger Matrix

Contract Source of Authority Required Behavior Fallback / Evidence
Execution owner Kimi process-local session lifecycle target {agentIdentity, sessionId, process epoch}, never sessionId alone stale/reused PID and second-process probes fail closed
Presence / input safety ADR 0002 §5.2 no terminal mutation during active turn, approval dialog, or unsent operator input next_turn / stored unread
Delivery acknowledgement wake event + owning TUI turn correlate wake nonce/message IDs to a turn started/steered by that exact process epoch HTTP/OS acceptance alone is NOT delivered
Subscription migration current kimi-server coordinate atomically clear the obsolete web lockPath when switching adapter shape rollback restores stored-unread, never the twin
Security transport capability least privilege; no globally open kitty remote control negative authorization test + documented revocation

Acceptance Criteria

  • AC1: harness research settled with cited receipts (comment, 2026-07-21T21:48Z — interactive TUI has no documented inbound channel).
  • AC2: one verified end-to-end delivery of a real wake digest into a live interactive kimi TUI with the exact owner tuple {agentIdentity, sessionId, process epoch} and a causal turn receipt (turn started/steered by that epoch). [L3-deferred — operator handoff needed] — requires the merged daemon + a standing seat poll; unreachable from any unmerged PR head (see PR #15712 PMV).
  • Negative ACs (all must fail closed): approval dialog open; operator draft present; active turn; stale process epoch / PID reuse; TUI session switch; same persisted session already materialized in another process; Kimi subagents active. [L3-deferred — operator handoff needed] for the live spot matrix (approval/draft/active-turn are harness-idle-gated by construction; stale-epoch, confinement, torn-line, and append-mid-consume are spec-covered on the PR branch); the full live sweep is post-merge.
  • AC3: the stale lockPath on the seat's subscription is retired/cleared under a non-web route (not "repaired" into another server coordinate). (Seat-side retirement done 2026-07-22 — stale subscription unsubscribed, not re-pointed; PR #15712 makes retirement atomic in WakeSubscriptionService on pull-bridge selection.)
  • AC4: the route stays fail-visible (no silent fallback recreating the twin).

Out of Scope

  • kimi web sibling-session routing improvements (the sibling IS the anti-goal).
  • Presence/turn-presence wiring (#15658, merged).
  • Wake policy (#15405); #13796's generic adapter surface (different layer).

Avoided Traps / Gold Standards Rejected

  • Raw title-addressed terminal injection (the original prescription — rejected per Euclid's intake): no presence/approval state in the title; Enter submits focused approval decisions; no causal receipt; contradicts ADR 0002 §5.2.
  • Pointing the subscription at a kimi web sibling and calling it delivered — that IS the split-brain.
  • Suppressing every wake to the seat as the "fix" — suppresses the wake contract itself.
  • Session-history visibility as delivery proof — the twin writes the same store; owner proof requires the process epoch.

Related

  • Lineage: #15579 / PR #15588, #15596 / #15597 (corrective successor); #13796 (different layer); ADR 0002 §5.2 (presence/no-clobber contract)
  • #15586 (umbrella), #11829 (broader wake-driver lane), #15405, #11822 lineage (Claude sibling routing)
  • #15660 (boot surfaces — the wake envelope is a SessionStart artifact)
  • Origin Session ID: eb9be68e-9401-4ecd-9762-ef519b4091ed

Sweeps: live open-issue search (kimi wake, wake delivery, TUI, split-brain) at 2026-07-21T21:50Z — no exact duplicate. KB semantic clean. Operator recollection of a Euclid-authored ticket VBA-falsified; Euclid confirmed corrective-successor status + this narrowing (2026-07-21/22).

Retrieval Hint: "kimi TUI wake split-brain execution owner process epoch owner-native ingress"; anchors ai/daemons/wake/daemon.mjs:1301-1323, Kimi source ec88d352 (prompts.ts resume, sessionLifecycleService process-local Map).

tobiu referenced in commit eb15c84 - "feat(ai): kimi-pull-bridge wake adapter — pull-inversion owner-native delivery (#15665) (#15712) on Jul 22, 2026, 8:56 PM
tobiu closed this issue on Jul 22, 2026, 8:56 PM