Skip to content

[Improvement] Add retention helper to /remove-outputs: keep N newest runs within a tag #309

Closed

Description

@timdegroot1996

Problem

A common housekeeping need is "delete the oldest runs until only N remain", optionally scoped to a tag ("keep the N newest runs with tag X, untouch the rest"). This currently requires custom client-side scripting on top of /get-outputs + /remove-outputs. It would be useful to support this natively.

Current behavior

/remove-outputs already supports:

  • limit -> keep N most recent, but global, ignores tags (_remove_by_limit in database.py).
  • tags -> remove all runs with tag (_remove_by_tag in database.py).

These run independently, so "keep N newest among runs with tag X" cannot be expressed today.

Proposed direction

Make limit respect the tags filter when both are supplied: compute the candidate run set (runs matching any given tag), keep the N newest of that set, remove the rest. No new endpoint needed - extend the existing limit handling so it filters run_starts by tag before slicing.

  • {"limit": 10} -> unchanged (global, keep 10 newest).
  • {"limit": 10, "tags": ["nightly"]} -> keep 10 newest nightly runs, delete older nightly runs, leave other runs untouched.

Notes

  • Pure superset of current behavior -> backward compatible.
  • Covers both the no-tag and with-tag retention cases in one call.
  • Add tests for: limit-only (unchanged), limit+single tag, limit+multiple tags, limit >= matching count (warn, no-op).

Activity

  1. changed the title [-]Add retention helper to /remove-outputs: keep N newest runs within a tag[/-] [+][Improvement] Add retention helper to /remove-outputs: keep N newest runs within a tag[/+] on Jun 24, 2026
  2. timdegroot1996 commented on Sep 13, 2026

    @timdegroot1996
    CollaboratorAuthor

    Scoped the implementation in PR #313 down to exactly what this issue asked for: limit + tags only.

    The branch had grown a parallel age + tags combination that this issue never requested. That extra combination doubled the validation/detection logic in arguments.py and server.py, and required database.py to parse a hand-rolled ;-encoded tag suffix in two separate functions instead of one — complexity that wasn't earning its keep for an unrequested feature.

    Dropped age + tags: it now behaves exactly like on main today (two independent operations, no scoping). limit + tags is untouched and still matches this issue's proposed direction and examples exactly:

    • {"limit": 10} → unchanged, global keep-10-newest.
    • {"limit": 10, "tags": ["nightly"]} → keep 10 newest nightly runs, remove older matching runs, leave everything else untouched.

    Tests cover limit-only, limit+single tag, limit+multiple tags, and limit ≥ matching count (warn, no-op) — exactly what was asked for in the issue's Notes section.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions