Skip to content

v0.5.0 — Stabilization: lifecycle reset #137

Description

@iret77

Root cause: aiui fuses three components with different lifecycles into one binary whose lifetime hangs on a fragile proxy (mcp-stdio child-count + 60s grace) instead of the real signal (is Claude Desktop alive). The remote path additionally lacks the resurrection / cold-start retry the local path has. Independent code analysis + Codex diagnosis converged; three pivotal facts externally validated.

Target: v0.5.0 — a clean break from the 0.4.x lifecycle whack-a-mole line. Wire protocol extended but kept backward-compatible with 0.4.x Python bridges (companion still serves the blocking POST /render for old remotes). 1.0.0 reserved for "proven stable in real use".

Full spec (authoritative, guards against drift): docs/architecture/stabilization-plan.md.

Steps — each independently shippable, sequential 1→4

  • 1 — Host lifetime invariant. Single exit authority host_should_exit() = uninstall/update || !is_claude_desktop_running(). Gate the last-child grace edge on Claude.app liveness (no objc bridge, no poll tick). Window-X = hide (not exit). ExitRequested default-deny. Child-counter demoted to telemetry + start-trigger. → branch fix/host-lifetime-invariant
  • 2 — Remote bridge never killed to force a version. Drop the GUI-startup / Settings pkill -f aiui-mcp (mid-call crash + cross-session blast radius). Pin applies at next natural spawn; cooperative wire_version floor instead of external kill.
  • 3 — Async /render + bridge parity. POST /render returns {id} immediately; bounded long-poll GET /render/{id}. Both bridges identical (cold-start poll, progress notifications, error classification: TCP-refused vs connected-but-no-HTTP vs 401). Closes the ReadError class.
  • 4 — Tunnel mechanism + multi-window. Exactly one Mac-side tunnel owner (piggyback vs dedicated — decided empirically: does Claude Desktop's SSH carry a RemoteForward? multi-session-per-remote needed?). Drop single-occupancy 409; one window per render, each carrying a human-legible session identifier (session field set by caller; remote bridge auto-injects its hostname as session_origin).

Cross-cutting

  • Lifecycle state machine + named event log (replaces ad-hoc trace).
  • Integration test harness for the remote path (tunnel-down, GUI-down-mid-call, update-mid-call, parallel sessions, Claude-Desktop quit/restart) — the coverage gap that made this whack-a-mole in the first place.

Invariants (I1–I8) and per-step file lists: see the stabilization plan doc.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions