You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary (self-improvement signal from a stale-engineer investigation, #4400 path)
The periodic claim-reaper (src/overseer/claim_reaper.rs) reaps healthy standing/perpetual-goal engineers as false positives. Its liveness probe judges death purely from worktree presence + newest-file mtime idle age and never inherits the is_perpetual() benign-idle exemption the OODA no-progress breaker already applies (src/ooda_loop/no_progress.rs:407-420, issue #2589). The two subsystems therefore disagree: the daemon logs "standing/perpetual goal idled … goal stays active" while the reaper reclaims the same claim_key on heartbeat-stale/no-worktree.
Diagnosed during an overseer stale-engineer investigation of goal advance-rysweet-agent-kgpacks-rs-to-full-parity-f29bb15c (a perpetual goal). Archived evidence at ~/.simard/reaped-engineers/rysweet_Simard_advance-rysweet-agent-kgpacks-rs-to-full-parity-f29bb15c-1784692815/.
Evidence (line-cited, from the durable archive)
The engineer was ALIVE, not dead — zero crash signals:
journal.txt: 0 real panics / SIGKILL / signal:9 / OOM / core-dumped / non-zero-exit / recipe-runner-failure / brain-call-failure. All 65 raw panic hits are tokens=[…] memory-array noise (65 hits, 65 on tokens=[ lines → 0 real).
OODA cycles advanced monotonically 2369 → 2387; last real activity journal.txt cycle 2387 @ 2026-07-22T03:57:39Z: OODA consolidation: stored procedure 'pr-merge:advance-rysweet-agent-kgpacks-rs-to-full-parity-f29bb15c | triggers…' immediately before benign-idle @ 03:58:08.
14× benign-idle: no-progress breaker: standing/perpetual goal idled this cycle (normal, not a fault) — counter reset, goal stays active.
manifest.json: idle_age_secs=2171 (worktree newest-file mtime age = normal bursty quiescence), archived 1784692815 (2026-07-22T04:00:15Z, ~2 min after last activity).
The reaper reclaimed the live claim anyway (the bug):
19×OODA start: cleared stale assignment 'engineer-…-1784561556919' — repeated churn on the same live perpetual goal.
Daemon restarted mid-window (PID 3165616 → 1230193 ~02:46); the perpetual claim survived and kept idling benignly.
Root cause (code seam)
src/overseer/claim_reaper.rs contains 0 references to is_perpetual / perpetual / standing.
WorktreeClaimLivenessProbe::assess (claim_reaper.rs:312-360) derives Dead{HeartbeatStale|NoWorktree} from directory presence + newest_file_age_secs only — no goal-type awareness.
reap_stale_claims (claim_reaper.rs:143-183) reclaims on any confident Dead verdict with no is_perpetual() exemption before release_engineer_claim (claim_reaper.rs:203).
Precedent for the safer pattern: the tombstoned-goal reaper (#4242) reaps only on an authoritative signal (tombstone), never on mere absence/quiescence.
Make the reaper honor the daemon's benign-idle classification for perpetual goals:
Give reap_stale_claims access to a perpetual-goal predicate (e.g. pass a &dyn PerpetualGoalOracle / goal-board handle, or a is_perpetual: impl Fn(&str)->bool), resolving the goal via goal_id_from_claim_key.
Keep fail-closed behavior and the SIMARD_CLAIM_REAP_ENABLED off-switch intact. Add a unit test: a perpetual goal past stale_secs is exempted; a non-perpetual goal past stale_secs is still reclaimed.
Constraints: no Bridge naming; structured tracing + OTel, no stray print!; no silent fallbacks.
Dedup
Searched rysweet/Simard issues for reaper/perpetual/heartbeat-stale/false-positive — no existing open tracking issue. #4099 (reaper impl, CLOSED) and #4400 (investigate-before-reap, CLOSED) are related predecessors; this tracks the missing is_perpetual() exemption they left open.
Verdict of the investigation
still-alive (false positive) — fail-closed. The engineer was NOT reaped for death; no claim release / worktree removal was performed by this investigation. The worktree's absence was the reaper's own prior action (reason=no-worktree), not death evidence.
Summary (self-improvement signal from a stale-engineer investigation, #4400 path)
The periodic claim-reaper (
src/overseer/claim_reaper.rs) reaps healthy standing/perpetual-goal engineers as false positives. Its liveness probe judges death purely from worktree presence + newest-file mtime idle age and never inherits theis_perpetual()benign-idle exemption the OODA no-progress breaker already applies (src/ooda_loop/no_progress.rs:407-420, issue #2589). The two subsystems therefore disagree: the daemon logs "standing/perpetual goal idled … goal stays active" while the reaper reclaims the same claim_key onheartbeat-stale/no-worktree.Diagnosed during an overseer stale-engineer investigation of goal
advance-rysweet-agent-kgpacks-rs-to-full-parity-f29bb15c(a perpetual goal). Archived evidence at~/.simard/reaped-engineers/rysweet_Simard_advance-rysweet-agent-kgpacks-rs-to-full-parity-f29bb15c-1784692815/.Evidence (line-cited, from the durable archive)
The engineer was ALIVE, not dead — zero crash signals:
journal.txt: 0 real panics / SIGKILL / signal:9 / OOM / core-dumped / non-zero-exit / recipe-runner-failure / brain-call-failure. All 65 rawpanichits aretokens=[…]memory-array noise (65 hits, 65 ontokens=[lines → 0 real).journal.txtcycle 2387 @2026-07-22T03:57:39Z:OODA consolidation: stored procedure 'pr-merge:advance-rysweet-agent-kgpacks-rs-to-full-parity-f29bb15c | triggers…'immediately before benign-idle @ 03:58:08.no-progress breaker: standing/perpetual goal idled this cycle (normal, not a fault) — counter reset, goal stays active.manifest.json:idle_age_secs=2171(worktree newest-file mtime age = normal bursty quiescence), archived1784692815(2026-07-22T04:00:15Z, ~2 min after last activity).The reaper reclaimed the live claim anyway (the bug):
simard::claim_reaper: reclaimed rysweet/Simard:advance-…-f29bb15c— 3×reason=heartbeat-stale(age=5083s,3052s,4470s), 2×reason=no-worktree.verdict=no-investigation(journal.txt@ 03:10:27) — the reaper reclaimed without running the Make Simard investigate a quiet/idle engineer BEFORE ever reaping it (evidence-preserve + agentic WHY, feed self-improvement; only reap if genuinely dead). READ THE FULL AUTHORITATIVE BRIEF and follow #4400 investigate-before-reap path.OODA start: cleared stale assignment 'engineer-…-1784561556919'— repeated churn on the same live perpetual goal.3165616→1230193~02:46); the perpetual claim survived and kept idling benignly.Root cause (code seam)
src/overseer/claim_reaper.rscontains 0 references tois_perpetual/perpetual/standing.WorktreeClaimLivenessProbe::assess(claim_reaper.rs:312-360) derivesDead{HeartbeatStale|NoWorktree}from directory presence +newest_file_age_secsonly — no goal-type awareness.reap_stale_claims(claim_reaper.rs:143-183) reclaims on any confident Dead verdict with nois_perpetual()exemption beforerelease_engineer_claim(claim_reaper.rs:203).no_progress.rs:407-420reuses the sameis_perpetual()flag (goal_curation/types.rs:350) and treats idle as "normal, not a fault." The reaper (Read /tmp/claim-reaper-task.txt IN FULL and implement exactly what it specifies: add a periodic stale-engineer-claim REAPER to the Overseer tick that reclaims engineer_claims whose engineer is provabl #4099) was added later and never inherited it.Precedent for the safer pattern: the tombstoned-goal reaper (#4242) reaps only on an authoritative signal (tombstone), never on mere absence/quiescence.
Scoped corrective brief (minimal, additive, non-breaking, CI-green)
Make the reaper honor the daemon's benign-idle classification for perpetual goals:
reap_stale_claimsaccess to a perpetual-goal predicate (e.g. pass a&dyn PerpetualGoalOracle/ goal-board handle, or ais_perpetual: impl Fn(&str)->bool), resolving the goal viagoal_id_from_claim_key.claim_reaper.rs:162-183), after a confidentDeadverdict but before reclaim, skip (continue, count as exempted) any goal whereis_perpetual()is true and the verdict isHeartbeatStale(benign idle). Reuse the SAMEis_perpetual()flag (goal_curation/types.rs:350) — never a second notion.NoWorktreeon a perpetual goal should route through the Make Simard investigate a quiet/idle engineer BEFORE ever reaping it (evidence-preserve + agentic WHY, feed self-improvement; only reap if genuinely dead). READ THE FULL AUTHORITATIVE BRIEF and follow #4400 investigation rather than a bareverdict=no-investigationreclaim.no_progress.rs("standing/perpetual goal idle — reaper exempt").SIMARD_CLAIM_REAP_ENABLEDoff-switch intact. Add a unit test: a perpetual goal paststale_secsis exempted; a non-perpetual goal paststale_secsis still reclaimed.Constraints: no
Bridgenaming; structuredtracing+ OTel, no strayprint!; no silent fallbacks.Dedup
Searched rysweet/Simard issues for reaper/perpetual/heartbeat-stale/false-positive — no existing open tracking issue. #4099 (reaper impl, CLOSED) and #4400 (investigate-before-reap, CLOSED) are related predecessors; this tracks the missing
is_perpetual()exemption they left open.Verdict of the investigation
still-alive(false positive) — fail-closed. The engineer was NOT reaped for death; no claim release / worktree removal was performed by this investigation. The worktree's absence was the reaper's own prior action (reason=no-worktree), not death evidence.