fix: register detached runs in DB at launch (#2)#84
Merged
mattleaverton merged 1 commit intoApr 24, 2026
Merged
Conversation
Before this change, running with --detach forked a child process and
exited immediately. The run row was only written to the run database when
the child's engine.RunWithConfig path reached RecordRunStart — which
could be seconds or minutes after the parent exited.
Consequences: `runs list`, `runs show <id>`, and
`runs wait --latest --label ...` all failed to find the run until it
reached a terminal state, because the DB had no row for it yet. Users
had to capture logs_root= from launch stdout and poll final.json by hand.
The fix adds registerDetachedRunInDB() (cmd/kilroy/run_detach_db.go),
which is called in the detach branch of attractorRun() — after paths are
resolved, before launchDetached() forks the child. It reads the graph
file to extract graphName/goal/dotSource (best-effort; falls back to
the filename stem if parsing fails), then inserts a row with
status=running and all available metadata (labels, inputs, invocation,
logs_root) via rundb.InsertRun.
The child's engine path later calls InsertRun (INSERT OR REPLACE), which
overwrites the parent's row with full metadata (worktreeDir, runBranch,
etc.); status remains running until CompleteRun sets the terminal value.
Added tests in cmd/kilroy/run_detach_db_test.go:
- TestRegisterDetachedRunInDB_AppearsBefore_TerminalState: writes the
pre-registration row, then asserts GetRun and ListRuns with a label
filter both find the run with status=running — exactly the path used
by `runs wait --latest --label KEY=VALUE`.
- TestRegisterDetachedRunInDB_FallsBackToFilename: verifies that when
the graph file is missing the row is still written using the
filename stem as graph_name.
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.
Summary
From
docs/plans/2026-04-24-kilroy-fixes-from-feedback.mditem #2.Bug:
kilroy attractor run --detachforked a child and exited before any DB row was written. Until the child reachedengine.RunWithConfig→RecordRunStart, every query (runs list,runs show <id>,runs wait --latest --label …) returned "not found." Callers had to capturelogs_root=from stdout and pollfinal.jsonby hand.Fix: Added
registerDetachedRunInDB()(new filecmd/kilroy/run_detach_db.go), called in theif detach {branch ofattractorRun()just beforelaunchDetached(). Writesstatus="running"with labels, inputs, invocation, repoPath before the parent exits. The child's existingRecordRunStart()usesINSERT OR REPLACEso full metadata (worktreeDir,runBranch) lands once the engine starts.CompleteRun()updates to the terminal status as before.Test plan
TestRegisterDetachedRunInDB_AppearsBefore_TerminalState— covers theGetRunandListRuns(Labels: ...)paths (exactly whatruns wait --latest --label KEY=VALUEdoes).TestRegisterDetachedRunInDB_FallsBackToFilename— falls back gracefully when the graph file is missing.go test ./cmd/kilroy/...passes.Risks / follow-ups
started_at = time.Now(); child'sINSERT OR REPLACEresets it to the child's start time (ms later). Could useINSERT OR IGNOREin the engine path to preserve the parent's timestamp. Minor.registerDetachedRunInDBlogs a warning on stderr but doesn't fail the launch, consistent with the existing best-effort DB design. If the DB is corrupt the launch succeeds but the run stays invisible.Context
Produced by a dogfood quick-launch run against this repo — the engine's own worktree isolation (PR #83) was validated end-to-end by this process.
🤖 Generated with Claude Code