Skip to content

purge --check-policy: add a retention horizon for checkpoint-* directories #1069

Open

Description

@cemililik

CR-A10-042 (from #102) noted the retention scan (forgelm/cli/subcommands/_purge.py _check_policy horizons list, ~:1210-1232) covers audit_log, staging dirs, compliance bundle, data-audit report and raw_documents, but not checkpoint-* directories, which every completed run leaves under training.output_dir. The memorisation-warning side of CR-A10-042 is being fixed on branch issue-102-purge-config-memorisation; the retention horizon needs its own config field (e.g. retention.checkpoint_retention_days, default 0 = disabled, opt-in per project principle 8) plus a _discover_checkpoint_horizons helper mirroring _discover_per_run_staging_horizons, tests, and EN+TR doc updates to docs/reference/purge_subcommand.md and the audit/retention reference pages. Refs #102, CR-A10-042.

Acceptance criteria

  • retention.checkpoint_retention_days (int, ge=0, default 0 = never reported) with a description that names the report, not enforcement. The default stays 0: the other three horizons default to non-zero values, but a non-zero default here would add violations to every existing install that still has old checkpoints and flip the count == 0 gate of the jq -e recipe in docs/reference/purge_subcommand.md.
  • forgelm purge --check-policy reports each checkpoint-* directory directly under --output-dir older than the horizon, as checkpoint_dir[<name>], with age_source=mtime. These directories are not run-scoped, so they must not take the audit log's genesis age (_resolve_artefact_age falls back to it for any artefact without a run_id).
  • A fresh checkpoint inside the horizon, a non-directory entry named checkpoint-*, and a horizon of 0 are not reported; tests pin the exact boundary.
  • The scan root is --output-dir, like every other horizon; following config-named training or pipeline layouts is out of scope here.
  • config_template.yaml, the field-description guard, the wizard-defaults sync guard and the EN+TR docs are updated per the add-config-field skill (docs/reference/purge_subcommand.md, docs/reference/configuration.md, the GDPR erasure guide and manual page). The docs say plainly that checkpoints are reported, never deleted.
  • Size budget: forgelm/config.py has no headroom and forgelm/cli/subcommands/_purge.py very little, so record a budget_history entry in tools/check_module_size.py (decision C-18) or place the helper in a new module.

Activity

  1. added
    needs-triageNot triaged yet: every new issue starts with it; only a maintainer removes it
    on Oct 23, 2026
  2. added
    enhancementNew feature or request
    severity: lowMinor defect, inaccuracy or rough edge
    wave: 4Roadmap wave 4: low / info / watch, when touching the module
    on Oct 23, 2026
  3. cemililik commented on Oct 23, 2026

    @cemililik
    CollaboratorAuthor

    Triaged on development e6bf28d, after #1068 merged during this triage. Each finding was first checked on 83e62f6 and on #1068's head (ab5ce5f), whose code is identical to the merge.

    Accepted: enhancement, severity low, wave 4, under the W4 module-sweep epic #875.

    What I checked

    • _scan_retention_violations has no checkpoint-* horizon on development. purge: find the weights a run really leaves behind (fixes #102) #1068 keeps it that way on purpose (its docstring: "checkpoint-* directories are deliberately not walked: no retention: horizon covers them") and documents the limit. This issue is the opt-in way to close it. It stays low because purge: find the weights a run really leaves behind (fixes #102) #1068 already makes the memorisation warning list these directories; what is missing is only the Art. 5(1)(e) report.
    • A run leaves up to training.save_total_limit (default 3) checkpoint-* directories once it passes training.save_steps (default 200) steps, and nothing removes them afterwards, auto-revert included.

    Two points I added to the acceptance criteria (the body now has a list; it had none)

    1. Default 0 is right, and not only because of principle 8. The other three horizons default to non-zero values, but a non-zero default here would add violations to every existing install that still has old checkpoints, and flip the count == 0 gate of the jq -e recipe in docs/reference/purge_subcommand.md.
    2. Age from mtime, not from the audit log. _resolve_artefact_age falls back to the log's genesis timestamp for any artefact without a run_id. A checkpoint is not run-scoped by name, so one written yesterday into a long-lived output directory would be reported at the log's age (the same false-positive family as CR-A10-023 in [Wave 3] Medium — Module sweep: GDPR purge / reverse-pii and the human-approval gate (part 1/2) #554).

    Notes for whoever implements it

    Not open for contribution yet: this needs a maintainer decision first. If you would like to work on it, please comment with your proposed approach before opening a pull request.

  4. removed
    needs-triageNot triaged yet: every new issue starts with it; only a maintainer removes it
    on Oct 23, 2026
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

    area: operator-cmdsCode area: operator-cmdsenhancementNew feature or requestseverity: lowMinor defect, inaccuracy or rough edgewave: 4Roadmap wave 4: low / info / watch, when touching the module

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions