Skip to content

Expire unapplied workspace cleanup plans - #1277

Merged
chubes4 merged 1 commit into
mainfrom
fix/expire-unapplied-cleanup-plans
Aug 27, 2026
Merged

Expire unapplied workspace cleanup plans#1277
chubes4 merged 1 commit into
mainfrom
fix/expire-unapplied-cleanup-plans

Conversation

@chubes4

@chubes4 chubes4 commented Aug 27, 2026

Copy link
Copy Markdown
Member

Problem

Every cleanup plan and dry run persists a run row so an operator can review it and apply it later. Nothing ever removed the rows that were never applied, so they accumulate for the life of the install.

On this workspace:

41,554  mode=artifacts  status=planned
  • created between 2026-06-07 and today
  • none carry completed_at
  • no requested_by_user_id, requested_by_agent_id, parent_job_id, or batch_job_id, so they come from plan and dry-run invocations rather than a scheduled job

The rate follows agent activity rather than a fixed cadence: 3,559 on 2026-08-21 and 3,219 on 2026-08-24 during heavy automation, then 8 and 2 on quiet days. workspace hygiene performs an inventory-only cleanup classification on every call, so routine inspection persists plans too.

These runs also fan out into worktree_cleanup_chunk jobs and Action Scheduler actions, which is why actionscheduler_actions reached 436,869 rows on this install. Data Machine retention was deleting 58,533 of those rows in a single pass, so the exhaust was being handled correctly while its source kept growing.

Fix

CleanupRunRepository::expire_runs() deletes runs in a given status that were created before a cutoff, removing each run's items first and bounding the work per pass. WorkspaceRetentionCleanupTask calls it on the daily retention pass that already exists.

Only the unapplied planning state expires. Applied, completed, and in-flight runs are untouched, and a dry-run retention pass reports the cutoff without deleting.

Two filters cover tuning: datamachine_code_cleanup_plan_max_age_days (7) and datamachine_code_cleanup_plan_expiry_limit (2000).

expire_runs() is deliberately not added to CleanupRunRepositoryInterface, which is the narrow progress-writing contract implemented by orchestrator test fakes.

Verification

  • php tests/cleanup-plan-expiry.php — 7 checks covering the empty candidate set, reported counts, status/age/bound selection, item-before-run ordering, run-id scoping, and clamping of the per-pass bound
  • full suite: 144 passing. tests/worktree-add-lifecycle.php times out on this branch and on an unmodified checkout, so it is pre-existing.

Note

The cleanup system itself is working: 593 worktrees removed and 5.94 TB of artifacts reclaimed to date. This closes the one record type that had no retention.

AI assistance

OpenAI GPT-5.6-Sol via OpenCode was used to trace the Action Scheduler growth to its source, verify the retention chain, implement the expiry, and run the suite. I directed and reviewed the investigation.

@chubes4
chubes4 merged commit e03bc1a into main Aug 27, 2026
11 checks passed
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.

1 participant