- conforms_to::[[Observation Form Contract]]
- has_epistemic_status::[[Empirical Observation]]
- in_practice_domain::[[eOS Continuum]]
- authored_by::[[Christopher Allen]]
- has_lifecycle::[[Seed Stage]]↗
- has_curation::[[Working Draft]]↗
A Recursion Killed Mid-Flight Resumes From an Interval Snapshot and Delivers Its Result
Claim
In the eOS-Harness recursion domain running against DGD 1.7.9 plus eOSContinuum/eOS-kernellib, a recursive task in flight when the runtime process is killed with SIGKILL -- no shutdown, no orchestrated dump -- completes after a restore from the most recent interval snapshot and delivers its result to an external harness that holds no loop state of its own. The recursion's frame tree, its context object, and the pending call_out that represents the not-yet-run child step all ride the snapshot; after restore the surviving call_out fires with its remaining delay, the child computes, the parent's continuation closes the root frame, and the reconnecting harness reads the result from the frame tree rather than replaying any history. The snapshot that carried the state was written by a runtime-side interval cadence, not by any action taken in anticipation of the kill.
Grounds
This is an Empirical Observation. The grounds are a kill-and-restore drill run 2026-08-09 against a staged private instance (telnet 38023, binary 38080), plus the interval-cadence measurements taken on the same instance.
Setup:
- Driver: DGD 1.7.9 built from
eOSContinuum/dgd. - Kernel layer:
eOSContinuum/eOS-kernellibat its public HEAD, staged into a disposable build tree. - Recursion domain:
/usr/RLM/-- frame clonables forming a task tree (one root per task, children sharing the root's context object), a scheduler daemon whoseadvance()feeds a completed step's result into its frame and schedules the parent's continuation viacall_out, and per-frame deadlinecall_outs so a frame that never completes expires loudly. - Snapshot cadence: a System-tier daemon running a
call_outinterval loop arounddump_state(FALSE), armed at 15 seconds, plus on-demand dumps at recursion milestones (root opened, root closed). The cadence is runtime-side by necessity: DGD schedules no periodic dumps of its own -- the configdump_intervalis not a dump timer but the post-restore snapshot rebuild spread (src/object.cpp,dinterval). - Harness: an external process that submits a task over the telnet line protocol, polls the frame tree for the result, and on connection loss reconnects and reads -- it holds no state the runtime does not also hold.
- The submitted drill task runs as a deliberately slow recursion (child work scheduled 20 seconds out) so the kill lands mid-flight with the child step still pending.
The drill sequence:
- Harness submits the task; the root frame opens and the slow child step is scheduled.
kill -9is delivered to the DGD process at 00:15:16, with the child step pending. The last interval dump had fired at 00:15:08; nothing about the kill was anticipated.- The runtime is restarted against the interval snapshot (
** State restored.). - The pending child
call_outfires with its remaining delay, computes the answer into the shared context, andadvance()closes the child; the parent's default continuation closes the root withchildren: 42. - The harness, which had logged two
Connection refusedreconnect attempts during the downtime, reconnects, reads the closed root's result from the frame tree, and exits 0.
Post-restore cadence check: query_dumps() = 11 and query_interval() = 15 after the restore -- the armed interval loop itself rode the snapshot and resumed dumping with no re-arming, so the next kill would be covered by the same mechanism.
Replay guard: a separately exercised guard refuses advance() on a frame that is no longer open (logged as advance REFUSED ... result dropped), so terminal-path replays -- possible when an external caller retries across a restore boundary -- cannot double-apply a result. The drill's delivered result was unchanged by a deliberately replayed advance.
What the evidence establishes:
- Crash recovery, not merely clean-dump persistence: the process died by
SIGKILLwith work in flight, and the recursion still completed. Loss was bounded by the interval cadence (at most the seconds since the last interval dump), not total. - Scheduled work is durable state: the pending
call_outis part of the image, survives the crash, and fires after restore with its remaining delay -- the recursion resumes because the schedule itself was persisted, with no recovery code in the application. - The externalized-loop discipline holds under failure: because the harness reads the frame tree rather than holding loop state, runtime death cost it nothing but reconnect attempts.
What the evidence does not establish:
- Torn-state behavior. The interval dump fired between task-level steps; a dump landing mid-write of the frame tree was not exercised. DGD's dump semantics (the kfun sets a flag and the driver writes after the current task completes) argue a torn frame tree cannot occur, but this drill does not test that argument.
- In-flight external exchanges. The killed recursion's pending work was a scheduled computation, not an open network exchange to an external service. A kill during an open exchange loses the connection with the image carrying the frame that awaited it; re-driving that frame is a harness-or-scheduler policy this drill does not exercise.
- Scale. One recursion, depth 2, one pending call_out. Snapshot cost and restore time under thousands of frames are not measured here.
What Would Revise It
- A kill during an open external exchange, observing what the restored image does with a frame whose exchange can never complete -- whether the deadline
call_outexpires it loudly as designed, and what re-drive policy closes it. This would extend the claim from "scheduled work survives" toward "arbitrary in-flight work is recoverable or loudly fails". - A forced dump mid-mutation -- triggering
dump_statefrom inside a frame-tree write rather than between tasks -- would test the after-current-task dump semantics this drill leans on but does not probe. - A scaling drill with a deep or wide frame tree, measuring dump time, snapshot size, and restore-to-first-callout latency, would establish whether interval cadence remains viable as recursion state grows.
- A runtime upgrade changing snapshot or call_out semantics. The claim is pinned to DGD 1.7.9's behavior that pending call_outs resume with remaining delay (downtime invisible); a release changing that would require re-running the drill.
Sources
src/usr/RLM/sys/rlmd.c(eOS-Harness) -- the scheduler daemon: frame-tree advance, continuation scheduling, deadline call_outs, and the non-open-frame replay guard.src/usr/RLM/obj/frame.c,src/usr/RLM/obj/context.c(eOS-Harness) -- the frame and context clonables whose clones are the persisted recursion state.src/usr/System/sys/rlm_snapshotd.c(eOS-Harness) -- the interval-cadence daemon:set_interval()call_out loop arounddump_state(FALSE)plus the milestone dump surface.scripts/harness.py(eOS-Harness) -- the external driver: submit, poll, reconnect-and-read.src/object.cpp(eOSContinuum/dgd) --dinterval: the configdump_intervalspreads the post-restore snapshot rebuild; it schedules no periodic dumps, which is why the cadence daemon exists.
Relations
-
conforms_to::[[Observation Form Contract]]
- Carries
has_epistemic_status::[[Empirical Observation]], names the measurement (one kill-and-restore drill with timestamped kill and dump, plus post-restore cadence counters), states the limits (torn state, in-flight exchanges, and scale unexercised), and lists concrete revision conditions.
- Carries
-
informed_by::[[Chat Room State Survives Statedump and Restore]]
- The clean-dump precedent: that Observation demonstrated state surviving an orchestrated
dump_state()plus shutdown, and named a crash-recovery probe --SIGKILLwith no clean dump, restore from the last periodic snapshot -- as one of its revision conditions. This drill is that probe, run with a recursion in flight; it extends the persistence claim across the crash boundary the clean-dump case left open.
- The clean-dump precedent: that Observation demonstrated state surviving an orchestrated
-
informs_downstream::[[Runtime State Is Persistent by Default, Not by Application Discipline]]
- The recursion carried no recovery code: no journal, no checkpoint calls, no replay log. The frame tree, context, and pending schedule survived because the runtime image is the persistence layer; the only application-visible artifact of durability is the cadence daemon that asks the runtime to dump periodically.
-
informs_downstream::[[Agent Harnesses Drive the Runtime, Not the Reverse]]
- The harness's restore path is reconnect-and-read because the runtime, not the harness, is the system of record for the loop's state. The drill shows the division of labor surviving a process kill: everything the harness needed after the crash was in the restored frame tree.