deb,config: keep the newest and the newest successful staged trees

The retention kept the newest five staged trees per target, so the
staged trees of a kernel-scale target alone could hold three-digit
GiB. The policy is now the pair that earns its disk: the newest
staged tree (what a failed run is re-forked from explicitly) and the
newest successful one (what the next --incremental run forks
automatically) — one record when they coincide; every other staged
tree degrades to metadata-only at the next build's retention. The
retention decision moved into a pure planner over (success, size) so
the policy is table-testable.

The size cap no longer drops a tree outright: an --incremental run's
own tree is always kept by its own run — the user asked for a carried
tree, and at least one always exists — and the cap only thins the kept
pair while another member covers the resume, the newest successful
tree being the last one standing. Oversized trees left by older pkh
versions or interrupted builds come down at the next build's
retention, once their lock is free.

The cap moves to the first user settings file, config.yml in
~/.config/pkh (YAML, like the data files; missing file or keys mean
defaults, a corrupt file is backed up, PKH_STAGED_MAXSIZE overrides),
replacing the JSON sketch from the previous commit. Default 20G, 0
disables the size rule. Every retained tree's size is measured once at
retention and recorded in the manifest, so sweeps never re-walk the
trees.
This commit is contained in:
2026-10-03 21:29:07 +02:00
parent 93943dcce0
commit a9a6d2001c
7 changed files with 363 additions and 173 deletions
+18 -12
View File
@@ -164,9 +164,9 @@ pkh deb # plain run: fresh chroot, fresh tree; the
# (nothing is kept even on failure or
# interrupt)
pkh deb --incremental # fork the newest successful record of the
# target (among the last five carrying a staged
# tree) and keep this run's staged tree, for
# the next fork to carry
# target (pkh keeps the newest and the newest
# successful staged trees) and keep this run's
# staged tree, for the next fork to carry
pkh deb --incremental <id>
# fork that exact record (see `pkh deb list`);
# a failed record is fine if its staged tree is
@@ -183,18 +183,24 @@ pkh deb profile [<id>] # a record's per-phase timing profile: how
pkh deb --no-ccache # build without the shared compile cache
```
Each target keeps at most five staged trees: when a sixth is retained,
the oldest degrades to a metadata-only record (manifest and log stay).
A staged tree larger than 20 GiB is never kept at all — a tree that
size costs more disk than the resume it buys, so its record degrades
too and the next build re-stages from scratch. The cap is a setting:
Each target keeps two staged trees: the newest one and the newest
successful one — the tree the next `--incremental` run forks
automatically, and the tree a failed run can be re-forked from
explicitly. An `--incremental` run always keeps its own tree, so at
least one staged tree exists even when the newest build failed. Every
other staged tree degrades to a metadata-only record (manifest and log
stay).
```json
// ~/.config/pkh/config.json (missing = defaults; keys may be omitted)
{ "staged_maxsize": "20G" }
A staged tree larger than 20 GiB comes down as well, as soon as the
pair has another member covering the resume — a tree that size costs
more disk than the resume it buys. The cap is a setting:
```yaml
# ~/.config/pkh/config.yml (missing file or keys = defaults)
staged_maxsize: 20G
```
`"0"` disables the size rule entirely, and `PKH_STAGED_MAXSIZE`
`0` disables the size rule entirely, and `PKH_STAGED_MAXSIZE`
overrides the file when set. `pkh prune` removes records older than a
week. `pkh prune --dry-run` previews everything it would remove,
grouped by kind with sizes; `--all` ignores the age and removes