feat(dev): lab auto-launches AFK runs per project under the global cap #75
No reviewers
Labels
No labels
bug
enhancement
in-progress
needs-info
needs-triage
p0
ready-for-agent
ready-for-human
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/nixos!75
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/64"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Implements the automatic AFK mode (parent #61, governed by ADR-0007). Each Forgejo-hosted project gains a persisted
autoEnabledtoggle in its ⋯ menu, and a server-side scheduler launches AFK runs on its own while the toggle is on and ready issues remain — serial per project, additive to manual runs, under the global instance cap.How it maps to the acceptance criteria
autoEnabled— new per-project field in the JSON store, keyed by project name likelastOpenedAt; round-trips across a restart (Store.AutoEnabled/SetAutoEnabled,TestStore_autoEnabledRoundTrips).Auto AFK runs: On/Offstateful form-button (never<input type=checkbox>, whosecheckedthe DOM morph treats as client-owned and never repaints; the label is server text the morph syncs). Posts/afk/auto/<project>to flip + persist + re-render. Forgejo-only; a direct POST offgit.cloonar.comis refused, not just hidden.runAFKScheduleron a ~45s ticker (ADR-0007's 30–60s band), a second long-lived worker distinct from the reaper and the ~4s client poll. No-ops when the AFK seams aren't wired.select → cap-check → claim → worktree → trust-seed → spawn → rollbackcore is factored intolaunchAFKRun(holdingafkMu), reused verbatim by the handler and the scheduler so the claim stays single-flighted.afk-auto-<N>session-name marker (vs manualafk-<N>);launchAFKRunre-checks one-auto-run-per-project underafkMuon fresh liveness, so a toggle-on kick is race-safe against the ticker. Manual runs never register as auto, so they're additive (bounded only by the cap).parseAFKLabelrecovers both kinds and the issue number, so the reaper still reaps auto runs (the documented hazard: a naiveafk-auto-<N>would have brokenstrconv.Atoiand silently stopped reaping). A restart re-adopts runs with the right kind from their names.shouldLaunchAuto(autoEnabled ∧ under-cap ∧ no-auto-in-flight ∧ ready-issue-exists), table-tested in isolation from tmux/tea/clock (TestShouldLaunchAuto), shaped (a struct + single expression) so #65's&& !pausedterm slots in without restructuring.Logged-out ticks claim nothing (a doomed session would park its issue in
in-progressfor nothing), gated on a fresh login check exactly as the manual Start is.Tests
New: store round-trip, the pure predicate, scheduler launch / serial-per-project / manual-additive / auto-off / no-ready-idle / at-cap / concurrent-sweeps-stay-serial (race) / logged-out, the toggle handler (persist + refuse-non-Forgejo + On/Off render), auto-run-is-reaped (hazard regression), and extended label round-trip + reject tables for the auto marker.
go test ./...,go test -race ./...,go vet ./...,go build ./..., andgofmt -lall clean in the lab module. The repo pre-commit hook is eval-only (nix-instantiate) and does not exercise the Go, so the module was validated locally; thefwdry-build passes.Known limitation (follow-up for #65, out of scope here)
A run that fails (death/timeout) parks its issue in
in-progressand keeps itsafk/<N>branch + worktree for inspection (#63) — so the scheduler does not auto-churn on it (it's out of the ready queue). But if a human later requeues that issue toready-for-agentwithout removing the leftoverafk/<N>branch, the next claim'sgit worktree add -b afk/<N>fails and rolls the label back, so an auto-enabled project can re-attempt it each tick. This is a pre-existing property of the #62 claim path (faithfully reused here); the clean fix is the #65 reset UX cleaning up the branch (or a self-healing claim that doesn't clobber the kept-for-inspection worktree). Not addressed here to respect this slice's scope (ADR-0007 defers failure handling — counter + three-strikes pause + reset — to #65).Closes #64