Skip to content

feat(engine): persistent interactive sessions — no per-turn respawn (spec 2026-07-02) - #95

Merged
Pher217 merged 1 commit into
mainfrom
claude/2026-07-02-interactive-engine
Jul 2, 2026
Merged

feat(engine): persistent interactive sessions — no per-turn respawn (spec 2026-07-02)#95
Pher217 merged 1 commit into
mainfrom
claude/2026-07-02-interactive-engine

Conversation

@Pher217

@Pher217 Pher217 commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Goal

Phase-2 centerpiece of the session-bridge spec (vault: 05 Specs/2026-07-02-interactive-engine-orc-owned-sessions.md, operator-approved): ORC owns a persistent claude -p --input-format stream-json --output-format stream-json process per session — the operator's own insight ("the VS Code extension is just a wrapper around this; own the process ourselves").

Why

  • Latency: spike-verified turn-2 in 2.6s on a warm process vs ~5–15s per-turn --resume respawn; blocks stream as they complete.
  • Robustness: no resume-or-create fallback races (gotcha docs(spec): reverse path — Telegram → live session input (orc run + PTY) #24), no per-turn spawn cost, context held by one process.
  • Foundation for interrupts/steering and the Windows daemon (pure stdio — no tmux).

Changes

  • host-agent/agent_host/interactive_engine.py — subprocess manager: daemon reader thread, FIFO for mid-turn sends, lazy crash-respawn with --resume (context survives via transcript), stale-reader guard, 1MB line skip, deterministic stop().
  • wsclient.pyORC_HEADLESS_ENGINE=interactive routes headless.prompt to a per-session engine registry (same per-session lock, same digest/reset delivery frames, same tail-suppression contract). Default and sdk paths untouched — the env var remains the instant rollback switch (2026-06-22 lesson: one mechanism at a time).
  • daemon.py — engines stopped on shutdown.
  • Tests: fake_claude.py protocol stand-in + 8 tests (multi-turn on ONE process, FIFO queueing, crash→resume respawn, tool steps, idempotent stop, routing, suppression). No API calls in CI.

Review

Independent review (gpt-5.5) found 4 real concurrency/lifecycle bugs — all fixed: event-loop-blocking stdin write (now asyncio.to_thread), turn flag stuck after double write failure, late events after stop/recycle, unreaped process + unjoined reader on kill.

Test Summary

host-agent: 259 passed; 2 pre-existing test_wsclient.py drain failures (identical on main). Backend: untouched (0 files). Ruff clean.

Deploy / live gate (after merge — per spec, before flipping the default)

  1. git pull, set ORC_HEADLESS_ENGINE=interactive in deploy/orc-stack/orc-stack.env, kickstart daemon.
  2. Live gate: dispatch → two Telegram turns (context retained) → daemon restart → third turn continues.
  3. Rollback: unset the env var.

Built per operator routing: engine core by kimi-k2.7-code:cloud, tests by glm-5.2:cloud, routing + review + fixes by the lead.

…SS_ENGINE=interactive)

One long-lived 'claude -p --input-format stream-json --output-format
stream-json' process per session, managed by the daemon:

- interactive_engine.py: thread-based reader, FIFO for mid-turn sends,
  lazy crash-respawn via --resume (context survives), stale-reader epoch
  guard, oversized-line skip, deterministic stop (reap + join).
- wsclient: ORC_HEADLESS_ENGINE=interactive routes headless.prompt to a
  per-session engine registry under the existing per-session lock; same
  digest/reset delivery semantics; tail suppression contract preserved;
  blocking pipe IO kept off the event loop. Default per-turn path and
  sdk path untouched — env var stays the rollback switch.
- daemon: engines stopped on shutdown.
- tests: fake_claude.py protocol stand-in (echo/crash/tool modes),
  6 engine unit tests (multi-turn same process, FIFO, crash-resume,
  tool steps, idempotent stop), 2 routing tests (persistent process
  across prompts, tail suppression).

Spike-verified against the real binary: multi-turn context retained on
one process, turn-2 latency 2.6s vs ~5-15s per-turn respawn. Review
findings addressed: loop-blocking stdin write, stuck turn flag on
double write failure, late events after stop, unreaped kill.

Suite: 259 passed (2 pre-existing wsclient drain failures, on main too).
@Pher217 Pher217 self-assigned this Jul 2, 2026
@Pher217
Pher217 merged commit 2f8b160 into main Jul 2, 2026
1 check passed
@Pher217
Pher217 deleted the claude/2026-07-02-interactive-engine branch July 4, 2026 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant