v0.279.0: after_install (decision 45), known default logins on the page, Part D empty-backup alarm, night chain (R-705), R-706
gates / gates (push) Successful in 27s

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-28 18:38:30 +02:00
parent 2e9a948cbd
commit 0c702f834a
35 changed files with 1119 additions and 16 deletions
@@ -473,3 +473,23 @@ func TestR687_EmptyLegReportsEmptySteps(t *testing.T) {
t.Fatalf("an empty leg must report steps as [], got %s", b)
}
}
// R-705 (v0.279.0) — the MANUAL chain's leg runs by day: at 18:00 the night's W+5h (07:30) has passed, so the
// night leg starts nothing (window_end), while RunUpdateLegNow gives the leg its normal length from its own
// start and presses the step. COMPANION RED-PROOF: drop the `if manual` deadline in runUpdateLeg → the manual
// run also reports window_end and starts nothing.
func TestR705_TheManualLegRunsByDay(t *testing.T) {
day := time.Date(2026, 9, 25, 18, 0, 0, 0, time.UTC)
m, _, _, ups, _ := legManager(t)
legOpts(m, func(o *UpdateLegOptions) { o.Now = func() time.Time { return day } })
if s := m.RunUpdateLeg(context.Background(), "night"); s == nil || s.Stopped != LegSkipWindowEnd || len(*ups) != 0 {
t.Fatalf("by day the NIGHT leg must start nothing: ups=%v summary=%+v", *ups, s)
}
s := m.RunUpdateLegNow(context.Background(), "manual-chain")
if s == nil || !s.Deadline.Equal(day.Add(195*time.Minute)) {
t.Fatalf("the manual leg's deadline %v, want %v", s.Deadline, day.Add(195*time.Minute))
}
if len(*ups) == 0 || legStepFor(s, "nextcloud").Reason == LegSkipWindowEnd {
t.Fatalf("the manual leg pressed nothing by day: ups=%v summary=%+v", *ups, s)
}
}