Skip to content

Add opt-in checkpoint retention policy (TASK-049) - #84

Merged
AdamClemens merged 3 commits into
mainfrom
feat/checkpoint-retention-policy
Sep 9, 2026
Merged

Add opt-in checkpoint retention policy (TASK-049)#84
AdamClemens merged 3 commits into
mainfrom
feat/checkpoint-retention-policy

Conversation

@AdamClemens

Copy link
Copy Markdown
Owner

Summary

Closes Stage 8's Completion Criterion 8 (see #83): RecordingConfig. max_checkpoints_retained bounds a recording's total on-disk checkpoint
count, opt-in and unbounded by default.

  • RecordingConfig.max_checkpoints_retained: int | None = None,
    validated > 0 if set.
  • Frame 0 is never pruned -- confirmed by a deliberate mutation
    (removing that exclusion) observed to fail the regression test before
    being reverted.
  • Factored the checkpoint-filename parsing replay.py used to
    duplicate into a shared checkpoint.list_checkpoints helper, used by
    both the new pruning logic and replay.find_checkpoint_at_or_before.
  • --max-checkpoints-retained on both pyflow record and pyflow resume, same override-config shape --checkpoint-interval already
    has.

Stacked on #83 (docs/reopen-stage-8) -- this branch was cut from
it since it needed that PR's TASK-049 stub entry in roadmap.md. The
diff below includes #83's commits until that one merges; it will shrink
to just this branch's own two commits once #83 lands.

Test plan

  • Strict TDD: every new test written first, confirmed red, then
    green
  • Mutation test on the "frame 0 never pruned" branch specifically,
    confirmed to fail before being reverted
  • make lint and every relevant make check-* target clean
  • make test -- 1161 passed, 21 skipped, exit 0
  • Verified by hand against the real CLI (not only the test suite):
    pyflow record --config examples/golden-demos/heat_diffusion.yaml --max-frames 25 --checkpoint-interval 5 --max-checkpoints-retained 2 reports 6 checkpoints written but
    leaves exactly {0, 20, 25} on disk; --help on both record
    and resume shows the new flag

🤖 Generated with Claude Code

AdamClemens and others added 3 commits September 9, 2026 11:22
An audit found this stage was scoped ad-hoc -- opened and fully built
in one day with its own criteria written the same day as its first
task -- and that its Goal's own "scrubbed to any point" clause shipped
with no operationalised criterion or mechanism at all. Adds Completion
Criteria 6-9 (live scrub, combined solved-velocity + declared-field
playback, checkpoint retention, partial-overlap cache reuse), drafts
TASK-048/049/050/051 with their settled design decisions ahead of
implementation, and sanctions "Status: Not started, drafted <date>" as
a valid task-entry status in stage-specification.md now that
check_stages.py's own TASK_DONE marker already handles it correctly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…uses

check_stages.py's lifecycle computation greps each task for an inline
**Status: Done** marker, which Stage 0's tasks never carried -- they
predate that convention and only ever recorded completion in the
stage's own summary table. That made Stage.lifecycle read "opened" with
0/11 done, silently wrong since Stage 0 closed on 2026-08-19. Fixed by
adding the marker to each task entry (dates from the existing summary
table; TASK-008 marked Done with no date, since none was ever recorded)
rather than special-casing Stage 0 in the checker, so the one general
mechanism stays correct for every stage. Regression test added and
confirmed red before the fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Closes Stage 8's Completion Criterion 8: `RecordingConfig.
max_checkpoints_retained` bounds a recording's total on-disk checkpoint
count, opt-in and unbounded by default so every existing config and
golden demo is unaffected. Frame 0 is never pruned, confirmed by a
deliberate mutation observed to fail the regression test before being
reverted. Factored the checkpoint-filename parsing `replay.py` used to
duplicate into a shared `checkpoint.list_checkpoints` helper, used by
both the new pruning logic and `replay.find_checkpoint_at_or_before`.

`--max-checkpoints-retained` added to both `pyflow record` and `pyflow
resume`, overriding the config field the same way `--checkpoint-interval`
already does. Verified by hand against the real CLI, not only the test
suite: a 25-frame recording with `--checkpoint-interval 5
--max-checkpoints-retained 2` reports 6 checkpoints written but leaves
exactly frame 0 plus the newest two on disk.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@AdamClemens
AdamClemens merged commit 7c300f2 into main Sep 9, 2026
2 checks passed
@AdamClemens
AdamClemens deleted the feat/checkpoint-retention-policy branch September 9, 2026 15:10
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