agent-zero/plugins/_time_travel/webui
King0James0 c42dffa54e feat: Time Travel shadow-repo retention (orphan cleanup, optional age-out, stale-lock repair)
Time Travel keeps a hidden git repository per workspace under
/a0/usr/.time_travel/workspaces/<id>/repo.git and snapshots on every file
change, but ships no retention: nothing deletes a shadow repository when its
chat or project is removed (chat_remove never touches .time_travel), there is
no delete/prune endpoint in the API or web UI, and a workspace whose 'git add'
ever exceeds GIT_TIMEOUT_SECONDS strands repo.git/index.lock, failing every
later snapshot with 'index.lock: File exists'. Observed on a live instance:
518 shadow repositories / 12 GB, most belonging to long-deleted chats, plus a
permanently wedged workspace.

This adds a throttled retention sweep driven from job_loop:

- Orphans: live workspace paths (project folders, the configured workdir,
  per-chat workdirs) are forward-enumerated and hashed with the existing
  workspace_id_for derivation; a shadow directory matching none of them is
  unreachable from the UI forever and is removed after a grace window.
- Optional age-out: retention_max_age_days (default 0 = keep forever) removes
  a live workspace's history when it has had no snapshot in N days. Time
  Travel lazily re-initializes an empty history on the next snapshot, so this
  is always safe for the feature.
- Stale locks: repo.git/index.lock older than retention_stale_lock_minutes is
  removed (git subprocesses are killed at GIT_TIMEOUT_SECONDS, so no
  legitimate lock lives that long), un-wedging future snapshots.
- Corrupt-repo set-asides (repo.git.invalid*) past the grace window.

Deletion is refused for any path outside the shadow root. Settings render in
the existing plugin-config pattern (default_config.yaml + webui/config.html,
settings_sections: agent): enable toggle, sweep interval, age-out days,
orphan grace, stale-lock age. Durable evidence lives next to the workspaces
dir: retention.json (running totals + last sweep stamp) and retention.log
(one JSON line per sweep naming everything removed, tail-capped at 1000).

Sweeps run in a worker thread off the event loop, at most one in flight,
default every 6 hours.

Tests: tests/test_time_travel_retention.py (config defaults/clamps, the full
sweep matrix, keep-forever default, disabled no-op, deletion guard, marker
accrual, per-sweep history + cap, throttle, and workspace_id_for parity).
2026-08-12 14:34:16 +02:00
..
config.html feat: Time Travel shadow-repo retention (orphan cleanup, optional age-out, stale-lock repair) 2026-08-12 14:34:16 +02:00
main.html Align Time Travel modal with settings shell 2026-05-05 17:33:59 +02:00
thumbnail.jpg Add plugin thumbnails 2026-04-28 15:04:19 +02:00
time-travel-panel.html Unify WebUI icons and fix message collapsing 2026-07-31 13:32:41 +00:00
time-travel-store.js Time Travel workspace selector + LiteLLM globals 2026-06-09 17:16:41 +02:00