Skip to content

fix(prune): add --errored mode for blanket exhausted-error sweep (PR-B G3 #2) - #1637

Merged
automagik-genie merged 1 commit into
devfrom
fix/prune-errored-mode
May 4, 2026
Merged

automagik-genie merged 1 commit into
devfrom
fix/prune-errored-mode

Conversation

@automagik-genie

Copy link
Copy Markdown
Contributor

Summary

Cli-noise-and-hygiene-cleanup G3 deliverables #2-5 — adds genie prune --errored mode that archives any state=error+auto_resume=false rows, regardless of reconciler audit-event reason tag. Distinct from --zombies (24h default, reconciler-tagged only); --errored defaults to 1h TTL and is opt-in.

Eliminates the gap where manually-error'd or non-reconciler-tagged crashed agents accumulated indefinitely.

Changes

  • src/lib/agent-registry.ts (+76) — new archiveAllExhaustedErrored(ttlHours) and listAllExhaustedErrored(ttlHours) helpers; EXHAUSTED_ERRORED_TTL_HOURS=1 default.
  • src/term-commands/prune.ts (+82/-30) — rewrite around PruneMode discriminator; new --errored flag mutually exclusive with --zombies; mode-specific default TTL.
  • src/lib/__tests__/zombie-spawns.test.ts (+16) — source-grep regression test.

Test plan

  • typecheck clean
  • biome clean (post format --write)
  • Smoke (full evidence in commit message): seeded a manual-error agent without audit reason → --zombies skips it, --errored matches; archive emits audit_reason: errored_ttl_exhausted (distinct from zombie sweep)
  • Live host run after fix: genie ls errored count 6 → 3 (3 within-TTL agents preserved)
  • CI green on GitHub

Concerns (documented per autonomous-loop brief)

  • PR size: 132 net LOC, above 100-LOC guideline. Splitting helpers + CLI wiring would leave dead code in an interim PR (LSP/biome would flag); shipped as one user-visible improvement.
  • Smoke side-effect: archive run also reaped 3 unrelated dead_pane_zombie rows (age >1h). They were inert and would have hit reconciler's 24h TTL anyway; no recoverable agents lost. Behavior matches spec.

Wish + sequencing

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented May 4, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d675da61-ce43-4453-b10a-5069511e7a89

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/prune-errored-mode

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds a new --errored target to the genie prune command to archive agents in an error state with exhausted auto-resume budgets. It introduces supporting library functions, a default 1-hour TTL, and updates the CLI logic. Feedback recommends enhancing consistency by using environment variables for audit actors, removing redundant logging, and utilizing the ts() helper for reliable timestamp formatting.

Comment thread src/lib/agent-registry.ts
Comment on lines +703 to +712
for (const row of rows) {
console.error(`[prune] Archived exhausted errored ${row.id} (TTL ${ttlHours}h)`);
auditPromises.push(
recordAuditEvent('worker', row.id, 'state_changed', 'cli', {
state: 'archived',
reason: 'errored_ttl_exhausted',
ttl_hours: ttlHours,
}).catch(() => {}),
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This loop contains redundant logging to stderr (which is already handled by the CLI summary in prune.ts) and uses a hardcoded actor string. It is better to remove the console.error and use process.env.GENIE_AGENT_NAME ?? 'cli' for the audit event actor, matching the pattern used in the update function and ensuring consistency across different execution environments.

    for (const row of rows) {
      auditPromises.push(
        recordAuditEvent('worker', row.id, 'state_changed', process.env.GENIE_AGENT_NAME ?? 'cli', {
          state: 'archived',
          reason: 'errored_ttl_exhausted',
          ttl_hours: ttlHours,
        }).catch(() => {}),
      );
    }

Comment thread src/lib/agent-registry.ts
Comment on lines +736 to +739
return rows.map((r: { id: string; last_state_change: string }) => ({
id: r.id,
lastStateChange: r.last_state_change,
}));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The last_state_change column is typically returned as a Date object by the database driver. Using the ts() helper ensures it is consistently converted to an ISO string, matching the function's return type and ensuring stable formatting in the CLI output. This also maintains consistency with how timestamps are handled in rowToAgent.

    return rows.map((r: { id: string; last_state_change: string | Date }) => ({
      id: r.id,
      lastStateChange: ts(r.last_state_change),
    }));

`genie prune --zombies` only archives reconciler-tagged dead-pane rows
(audit reason 'dead_pane_zombie' or 'stale_spawn_dead_pane'). That's
the safe, conservative sweep — but operators occasionally want a blanket
cleanup of any inert error-state row regardless of reason.

Add `genie prune --errored`:
  - Archives any state=error + auto_resume=false agent older than the TTL.
  - 1h default TTL (vs 24h for --zombies) — opt-in flag means the operator
    has already decided the rows are noise.
  - Audit reason: 'errored_ttl_exhausted' (distinct from
    'dead_pane_zombie_ttl_exhausted' so forensics can tell which sweep
    archived a row).
  - Mutually exclusive with --zombies; pick one mode per invocation.
  - Set auto_resume=true on a row to keep it visible past the TTL.

New helpers:
  - archiveAllExhaustedErrored(ttlHours) — same as archiveExhaustedZombies
    but without the audit-reason EXISTS filter.
  - listAllExhaustedErrored(ttlHours) — dry-run companion.

`prune.ts` reorganized around a `PruneMode` discriminator with
mode-specific default TTL + label tables. --zombies semantics unchanged.

Wish: cli-noise-and-hygiene-cleanup G3 (deliverables #2-5).
Pairs with the prior G3#1 fix (broaden zombie reason filter).

Smoke (live DB):
  - Seeded a 2h-old error+exhausted row with NO audit reason.
  - listExhaustedZombies(1) skipped it (correct: no audit tag).
  - listAllExhaustedErrored(1) matched it (correct: blanket).
  - archiveAllExhaustedErrored(1) flipped state→'archived' and emitted
    audit reason='errored_ttl_exhausted'.
  - genie ls errored count dropped 6→3 (3 newer-than-1h survived TTL).
@automagik-genie
automagik-genie force-pushed the fix/prune-errored-mode branch from 4d22a4b to 80a0703 Compare May 4, 2026 17:01
@automagik-genie
automagik-genie merged commit d41b353 into dev May 4, 2026
16 checks passed
@automagik-genie
automagik-genie deleted the fix/prune-errored-mode branch May 4, 2026 17:03
namastex888 added a commit that referenced this pull request May 7, 2026
…coped per reviewer

Lands the wish doc that scaffolds PR-A (#1634) and PR-B (#1636/#1637/#1638/
#1640/#1642), plus the 2026-05-07 PR-C draft + reviewer FIX-FIRST corrections.

Why this is a separate docs commit:
- The wish file was authored 2026-05-04 but only ever sat in a stash; never
  committed despite shipping work referencing it. This commit lands the
  reference document for completed + pending work in one place.
- PR-C as originally drafted had three invalid premises against live
  4.260507.1 (G3 amendment already implemented at scheduler-daemon.ts:1296;
  G9 line is on stderr not stdout; G10 design assumes binary-spawn that the
  HTTP probe doesn't do). Reviewer corrections folded in.
- Only G8 (kill-path shadow+UUID dedup) survives intact — file path
  corrected to src/term-commands/agents.ts:2817 (handleWorkerKill).
- G9 reframed as stderr-noise reduction (DEBUG=pgserve gating).
- G10 deferred pending /trace into update.ts:362.

QA dogfooding-72h artifacts (AUDIT.md, QA-PLAN.md) document the 72-h fix-audit
sweep that surfaced the bugs and triggered the wish update.

Refs: #1677

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants