v0.11.5 - Native Harness Loops & iOS Network Resilience
Bundles PR #432 — clean reimplementation of the still-unique work from the abandoned #430 (Codex goal mode + iOS network resilience WIP).
Features
Native harness loops as Automation rows
Claudecode and codex /goal continuation loops now materialize as first-class rows in the Automations panel, with iteration badges and a per-row stop button — alongside OA-scheduled automations.
- New
NativeLoopAdaptertrait + registry insrc/backend/native_loops.rs - Broadcast subscriber
src/api/native_loop_observer.rstranslatesGoalIteration/GoalStatusevents intoAutomation+AutomationExecutionrows mission_storegains aCommandSource::NativeLoop { harness, command, args }variant and anAutomationDriver { Scheduler, HarnessLoop }enum (defaults toSchedulerfor back-compat)- Idempotent SQL migration adds a
drivercolumn toautomations - The harness CLI still drives iteration; OA only observes
iOS network resilience
- Dedicated JSON
URLSessionwith bounded 15s request / 60s resource timeouts (was unbounded behindURLSession.shareddefaults) - Retry/backoff on transient failures, SSE parser hardening
- Filesystem-backed mission cache; the old multi-MB UserDefaults blob is drained once via
SandboxedDashboardApp.init - New
NetworkResilienceTeststarget pinning the behaviours
Claude Code built-in ScheduleWakeup bridge
mission_runnerwatches for Claude Code's built-inScheduleWakeuptool call, captures(delaySeconds, prompt, reason), and on a successful tool result POSTs an interval automation that fires the prompt back into the mission after the requested delay (clamped to[60, 3600])- New 300s heartbeat (env-tunable via
SANDBOXED_SH_CLAUDECODE_HEARTBEAT_INTERVAL_SECS) keeps the actor-level stuck-mission watchdog quiet during extended thinking, where the CLI emits only scaffolding stream events for minutes
Bugbot follow-ups (within the release window)
- sqlite: drop a duplicate
drivercolumn fromget_mission_automationsSELECT native_loop_observer: evict the mission cache entry on terminal status, and skip inactive rows when matching — so a new/goalon the same mission creates a fresh automation row instead of appending to the hidden inactive oneControlView: restore the 15s timeout on image fetches that the resilience pass had droppedAPIService: drop unused error structs (StreamInactivityError,StreamOversizeError)
Upgrade notes
Existing rows automatically default to driver = scheduler via the migration; no manual data fix required.
Full Changelog: v0.11.4...v0.11.5