feat(state): persist attached runs and cap state dir by size#8
Merged
Conversation
- Persist attached (synchronous) runs to the state dir like detached: writeState(running) before setup, updateState on exit/cancel/error. Synchronous runs become visible to listStates() and reconcilable after a launcher restart. They cannot be resumed live (AutoRemove + no onLog replay); the state file is for observability and reconciliation only. - Add DockerRunner.cleanupOldStates(maxBytes?): evicts terminal states (exited|cancelled|failed) oldest-first until the state dir is back under budget, never touching running states. Wires up deleteState(), which was defined but never called anywhere. - Add LIGHT_RUNNER_STATE_MAX_BYTES (default 50 MiB) read via stateMaxBytes(), mirroring reapAgeMs(). Kept distinct from cleanupOrphanStates, which only reconciles running -> failed and deletes nothing. - Tests: 3 unit cases for cleanupOldStates (no-op under budget, oldest-first eviction, running preserved) plus an e2e case asserting an attached run writes a terminal state file. build with cc
enixCode
added a commit
that referenced
this pull request
May 29, 2026
Ship attached-run state persistence + state-dir size cap (PR #8) and the GitHub Pages base-path fix (PR #9). Version bump done manually because the preversion hook's local VitePress build is unusable on a OneDrive-synced working tree; the published npm package (dist JS) and the deployed docs site (CI Docs workflow) are unaffected. build with cc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two changes so
light-runcan treatlight-runneras the single source of truth for run state (readlistStates/readState, reattach on boot, no separate store).runner/attached.tsnow writes the state file like the detached path:writeState({ status: 'running' })before setup,updateStateon exit / cancel / error. Synchronous runs become visible tolistStates()and reconcilable after a launcher restart. Documented limitation: attached runs cannot be resumed live (AutoRemoveremoves the container on exit andonLogis not replayed).DockerRunner.cleanupOldStates(maxBytes?)evicts terminal states (exited/cancelled/failed) oldest-first until the state dir is back under budget;runningstates are never removed. Wires updeleteState(), which existed but was never called. Kept distinct fromcleanupOrphanStates(reconcile != delete).LIGHT_RUNNER_STATE_MAX_BYTES(default 50 MiB) read viastateMaxBytes(), mirroringreapAgeMs().cleanupOldStates(no-op under budget, oldest-first eviction, running preserved) + 1 e2e case asserting an attached run writes a terminal state file. Local run: unit 69/69, e2eattach.test.js8/8.cleanupOldStates, attached persistence and the onLog limitation; API reference regenerated.build with cc