Problem
runs.file_count means different things per run kind. For peer-sync runs it is
the number of files the sync actually acted on; for bucket (rclone) syncs and
index runs it is files considered, not moved. So there is no column that
answers "did this run change anything?" across kinds.
That left a deliberate gap in the F19 work from #161 (PR #179):
runs --changes (runIsInteresting in cmd/squirrel/runs.go) and the TUI's
f fold (runIsNoOp in tui/runs.go) both key on
status == success && file_count == 0.
- That predicate collapses peer-sync no-ops correctly, but a bucket or index
no-op has a non-zero file_count, so it stays visible — the deliberately
fail-safe choice (better a visible no-op than a hidden run that moved
content), documented in both call sites.
Result: in the reference household's steady state the filters and the fold
still leave the bulk of the noise on screen, because most rows are per-destination
bucket pushes. F19's "steady-state no-op rows drown signal" is only half solved.
Why it wasn't done in #161
It needs a schema migration, and at the time #157 owned v25 and #158 owned v26
(both now merged; SchemaVersion is 26). #179 was scoped as reporting-only —
no schema change — so the honest partial landed with the caveat recorded rather
than a silent half-fix.
Scope
Notes
Follow-up to #161 (F19); the caveat is spelled out in PR #179's description.
Problem
runs.file_countmeans different things per run kind. For peer-sync runs it isthe number of files the sync actually acted on; for bucket (rclone) syncs and
index runs it is files considered, not moved. So there is no column that
answers "did this run change anything?" across kinds.
That left a deliberate gap in the F19 work from #161 (PR #179):
runs --changes(runIsInterestingincmd/squirrel/runs.go) and the TUI'sffold (runIsNoOpintui/runs.go) both key onstatus == success && file_count == 0.no-op has a non-zero
file_count, so it stays visible — the deliberatelyfail-safe choice (better a visible no-op than a hidden run that moved
content), documented in both call sites.
Result: in the reference household's steady state the filters and the fold
still leave the bulk of the noise on screen, because most rows are per-destination
bucket pushes. F19's "steady-state no-op rows drown signal" is only half solved.
Why it wasn't done in #161
It needs a schema migration, and at the time #157 owned v25 and #158 owned v26
(both now merged;
SchemaVersionis 26). #179 was scoped as reporting-only —no schema change — so the honest partial landed with the caveat recorded rather
than a silent half-fix.
Scope
runsin a v27 migration — a new column(e.g.
changed_count INTEGER, NULL for historical rows so old runs staytruthfully "unknown" rather than falsely "no-op"). Per the convention in
AGENTS.md, any new table isSTRICT; this is anALTER … ADD COLUMNonthe existing non-STRICT
runstable, so it rides the current shape (seeAdopt SQLite STRICT tables in the index schema #148 for the bulk conversion).
count for bucket pushes (the same source as
already_correct=Nfrom F7),the disposition list for peer syncs, added/superseded for index runs.
runIsInteresting/runIsNoOpto the new column, falling back totoday's
file_count == 0heuristic only wherechanged_count IS NULL, sopre-migration history keeps its current (conservative) rendering.
store/schema.sql(go test ./store -update-schema) and extendthe
runsfilter tests to cover a bucket no-op collapsing and a bucket runthat moved content staying visible.
Notes
rewritten — the audit trail stays intact.
already_correct=N(F7) and the fold agree on one number,which is also what status: per volume×destination coverage + durability panel (CLI, then TUI in this issue) #159's status grid wants when it says "caught up".
Follow-up to #161 (F19); the caveat is spelled out in PR #179's description.