controller v0.272.0: the backup page says when a whole-box backup does not fit (R-685); R-671, R-670, R-677
gates / gates (push) Successful in 26s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-25 11:19:27 +02:00
parent 71accca427
commit 44ae4dea70
21 changed files with 376 additions and 10 deletions
@@ -607,6 +607,21 @@ func (m *Manager) clearUpdateHoldAfterRestore(stackName string) {
return
}
m.logger.Printf("[INFO] [backup] %s: restore completed — the update hold (set %s) is CLEARED", stackName, h.At)
// R-671 (v0.272.0): the undo copies the hold kept describe the state this restore just replaced. They
// were kept so the hold's data stayed recoverable; once the app is restored whole they are dead weight
// (measured 2026-09-24 on 9202: three nextcloud copies, ~0.9 GiB, outlived the hold and nothing named
// them). Removed here, and only here — never for a restore hold (R-379), never while an update moves the
// app. Pinned by TestR671_RestoreThatClearsAnUpdateHoldRemovesItsUndoCopies.
if m.undoCopyRemover != nil && (m.updatingCheck == nil || !m.updatingCheck(stackName)) {
n := m.undoCopyRemover(stackName)
m.logger.Printf("[INFO] [backup] %s: removed %d undo cop(y/ies) the lifted update hold had kept (R-671)", stackName, n)
}
}
// SetUndoCopyRemover wires the undo-copy cleanup (R-671): stacks.Manager.RemoveUndoCopies. INIT-ONLY, main.go —
// pinned by TestUndoCopyRemoverIsWiredAtStartup (an AST walk). The backup package cannot import stacks.
func (m *Manager) SetUndoCopyRemover(fn func(stackName string) int) {
m.undoCopyRemover = fn
}
// UpdateHeldStacks is the set of apps held stopped after a failed update (R-660, v0.268.0) — the