← back to Ticket System
reaper: --block now honors suggest() disposition (done/blocked/open), not hardcoded blocked
4c64af7e2eee289008953e99df6776e205b29bac · 2026-09-14 08:30:41 -0700 · Steve Abrams
Steve's call 2026-09-14: honor the per-ticket suggestion literally. A zombie whose
last action reads complete/verified/shipped closes to done; a gated/awaiting-Steve
one goes blocked; a died-mid-work one returns to open (re-enters the RUN-NOW/dispatch
queue). All three are valid STATUSES; every set stays reversible (tk status <id> doing).
Header doc + console output updated to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ua2TVTdVcyufh968ZCZXdc
Files touched
Diff
commit 4c64af7e2eee289008953e99df6776e205b29bac
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Sep 14 08:30:41 2026 -0700
reaper: --block now honors suggest() disposition (done/blocked/open), not hardcoded blocked
Steve's call 2026-09-14: honor the per-ticket suggestion literally. A zombie whose
last action reads complete/verified/shipped closes to done; a gated/awaiting-Steve
one goes blocked; a died-mid-work one returns to open (re-enters the RUN-NOW/dispatch
queue). All three are valid STATUSES; every set stays reversible (tk status <id> doing).
Header doc + console output updated to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ua2TVTdVcyufh968ZCZXdc
---
reaper.js | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/reaper.js b/reaper.js
index 298ab414..80cf1d87 100644
--- a/reaper.js
+++ b/reaper.js
@@ -3,11 +3,13 @@
// Root cause (found 2026-07-27): nothing transitions a ticket out of `doing`
// when its owning Claude session ends, so `doing` silently accumulates zombies.
// This finds DOING tickets that are (a) idle > THRESHOLD_H and (b) have NO live
-// `claude … Work ticket <id>` process, then SUGGESTS a disposition from the last
-// action text. Report-only by default; --block sets the safe default (→ blocked).
+// worker (matched by a "Work ticket <id>" cmdline OR the ticket's owner label in
+// a live process's TK_AGENT env), then SUGGESTS a disposition from the last action
+// text (done / blocked / open). Report-only by default; --block honors that
+// suggestion literally (done→done, blocked→blocked, open→re-open for dispatch).
//
// node reaper.js # report zombies + suggested dispositions
-// node reaper.js --block # additionally set each zombie → blocked (reversible)
+// node reaper.js --block # set each zombie → its suggested status (reversible)
//
const { execSync } = require('child_process');
const { tickets: loadTickets } = require('./lib.js'); // read the store directly
@@ -73,12 +75,16 @@ for (const z of zombies)
console.log(` ${z.id.padEnd(11)} idle ${String(z.idleH).padStart(6)}h @${(z.assignee||'—').padEnd(22)} → ${z.suggest.padEnd(7)} «${z.last}»`);
if (BLOCK) {
- console.log(`\n--block: setting each zombie → blocked (reversible; safe default)…`);
+ console.log(`\n--block: setting each zombie → its suggested disposition (done/blocked/open; reversible)…`);
const TK = require('path').join(__dirname, 'tk');
+ const icon = { done: '✅', blocked: '⛔', open: '↩︎' };
for (const z of zombies) {
- sh(`TK_AGENT=reaper node ${TK} comment ${z.fullId} "reaper: DOING but idle ${z.idleH}h with no live worker → auto-blocked (suggested: ${z.suggest}). Owning session ended without tk done/status." 2>/dev/null`);
- sh(`TK_AGENT=reaper node ${TK} status ${z.fullId} blocked 2>/dev/null`);
- console.log(` ⛔ ${z.id} → blocked`);
+ // Honor suggest() literally: done→done, blocked→blocked, open→open. `open`
+ // returns the ticket to the dispatch queue (Steve's call 2026-09-14). All
+ // three are valid STATUSES and every set is reversible (tk status <id> doing).
+ sh(`TK_AGENT=reaper node ${TK} comment ${z.fullId} "reaper: DOING but idle ${z.idleH}h with no live worker → auto-set ${z.suggest} (owning session ended without tk done/status). Reversible: tk status ${z.fullId} doing." 2>/dev/null`);
+ sh(`TK_AGENT=reaper node ${TK} status ${z.fullId} ${z.suggest} 2>/dev/null`);
+ console.log(` ${icon[z.suggest] || '•'} ${z.id} → ${z.suggest}`);
}
} else {
console.log(`\n(report-only — re-run with --block to auto-block, or reconcile by hand.)`);
← 321f4cfd Record bounded empty-queue monitoring cycle yf1520
·
back to Ticket System
·
auto-data-snapshot: 2026-09-14T09:19:35 (1 data files) — dat 65fa9e87 →