R-899: a daytime press never cancels the night's whole-guest backup (operator ruling 2026-10-08, option A); press sends trigger=manual
gates / gates (push) Successful in 1m3s
gates / gates (push) Successful in 1m3s
Unreleased; ships with tomorrow's release. 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:
@@ -131,6 +131,10 @@ type Loop struct {
|
||||
// restartFailed (F-CRIT-1) is the set of stacks this loop stopped and could NOT restart. Guarded
|
||||
// by suppressMu — same concern, same lock. See suppress.go.
|
||||
restartFailed map[string]struct{}
|
||||
// R-899: the whole-guest ledger (nightowed.go) — the last successful press and scheduled run per tier.
|
||||
// ledgerMu guards the file and memLedger (the in-memory copy used when there is no marker path).
|
||||
ledgerMu sync.Mutex
|
||||
memLedger map[string]ledgerTier
|
||||
}
|
||||
|
||||
// SetTierNotifier wires the hub-event seam. INIT-ONLY — call once at startup, before Run.
|
||||
@@ -256,7 +260,7 @@ func (l *Loop) runOnce(ctx context.Context) error {
|
||||
// cadence+24h" — cannot be suppressed by a fresher sibling tier.
|
||||
if l.windowStartFn != nil {
|
||||
window := l.windowStartFn()
|
||||
if !scheduledRunAllowed(l.now().In(budapestLocation()), window, oldestAge(dueTiers), valveLicensed(dueTiers), l.cadence) {
|
||||
if !scheduledRunAllowed(l.now().In(budapestLocation()), window, gateAge(dueTiers), valveLicensed(withoutOwed(dueTiers)), l.cadence) {
|
||||
from, to := gateBounds(window)
|
||||
l.logger.Printf("[DEBUG] [quiesce] scheduled backup due but outside the backup window [%s–%s) — deferring to the next poll inside it", from, to)
|
||||
return nil
|
||||
@@ -432,6 +436,9 @@ func (l *Loop) TriggerNow() error {
|
||||
// The page says so in both languages (templates/backups.html, keys
|
||||
// backups.a_mentes_alatt_az_alkalmazasok + backups.elinditod_a_teljes_rendszermentest_most,
|
||||
// pinned by TestR518_BackupButtonStatesTheShortLocalOnlyStop).
|
||||
// R-899: the press is marked, so its success is recorded as a press (it does not count for
|
||||
// tonight's backup) and the agent is told not to start the night's OS leg after it.
|
||||
ctx = WithManualTrigger(ctx)
|
||||
if err := l.quiesceAndPollTiers(ctx, l.manualRunTiers(ctx)); err != nil {
|
||||
l.logger.Printf("[ERROR] [quiesce] manual backup cycle error: %v", err)
|
||||
}
|
||||
@@ -641,6 +648,7 @@ func (l *Loop) quiesceAndPollTiers(ctx context.Context, tiers []dueTier) error {
|
||||
// must NOT count as a failure, or a slow-but-healthy tier would back itself off.
|
||||
default:
|
||||
l.noteTierSuccess(t.target, label)
|
||||
l.recordWholeGuestSuccess(t.target, IsManualTrigger(ctx)) // R-899 (nightowed.go)
|
||||
}
|
||||
if stillRunning {
|
||||
// The max-quiesce guard fired while THIS tier's backup is still going (a first full
|
||||
|
||||
Reference in New Issue
Block a user