Commit 073eead
authored
fix: batch-2 bug sweep — scheduler DST wedge, stale 429 masking, export route alias, rune-safe redaction, cutoff parity (#171)
* fix(schedule): Next() infinite loop across DST fall-back
The hour-jump advanced via time.Date(...).Add(time.Hour). time.Date
resolves an ambiguous wall time to its FIRST occurrence, so across a
DST fall-back transition the hop could land back on the repeated wall
hour and stop advancing entirely when that hour is not in the hour
mask — an infinite loop that wedged the scheduler daemon and every
schedule add/list/next invocation. When the jump makes no progress,
fall back to plain duration arithmetic, which crosses the transition
by construction.
RED-first regression test: TestNext_DstFallBackRepeatedHourNotInMask
(observed hanging 5s before the fix; hermetic via time/tzdata).
* fix(llm): stale 429 state no longer masks the final failure
lastStatus/lastBody were set on non-200 responses and never cleared,
so a 429 early in the retry loop wrapped a LATER different failure in
RateLimitError on exhaustion — the exact type the serve turn handler
reads as 'provider throttled' (dead-prompt handling). A final
malformed-200 (buffered) or streaming failure after an earlier 429 now
reports its real cause. Fixed on both the buffered and streaming paths.
RED-first regression test: TestClient_Call_Stale429DoesNotMaskMalformed200.
* fix(subagents): redactGoal truncation is rune-safe
redactGoal sliced by bytes while the constant promises chars: a
multi-byte rune at the boundary was split, corrupting the goal text
with invalid UTF-8 exactly when the clamp engaged (long goals are the
normal case for real tasks). Now truncates on a rune boundary.
RED-first regression test: TestRedactGoal_TruncationIsRuneSafe.
* fix(serve): /export suffix stripped for GET only
handleSessionByID stripped the /export suffix for ALL methods while
only GET dispatches to the export handler — so DELETE
/api/sessions/{id}/export fell through to the base-session delete
(destroying the session through a documented read-only route) and
POST .../export renamed it. Mirrors the GET-only /plan guard, which
exists for exactly this reason.
RED-first regression test: TestSessionExportSuffix_NotAliasedForMutatingMethods.
* fix(cleanup): dry-run cutoffs share the sweep's DaysAgo math
The sweep computes day-based retention cutoffs with duration
arithmetic (N*24h) to avoid DST-sensitive calendar math; the dry-run
preview used time.AddDate, so after a DST transition the previewed
deletion set diverged from the sweep's by up to an hour of files.
The helper is now exported (maintenance.DaysAgo) and shared, making
preview/sweep divergence impossible by construction.
RED observation: the regression test referenced the not-yet-existing
maintenance.DaysAgo (capability-absent compile RED), then passed.1 parent d18cf93 commit 073eead
12 files changed
Lines changed: 269 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
135 | 135 | | |
136 | 136 | | |
137 | 137 | | |
138 | | - | |
| 138 | + | |
139 | 139 | | |
140 | 140 | | |
141 | | - | |
| 141 | + | |
142 | 142 | | |
143 | 143 | | |
144 | 144 | | |
145 | | - | |
| 145 | + | |
146 | 146 | | |
147 | 147 | | |
148 | 148 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2411 | 2411 | | |
2412 | 2412 | | |
2413 | 2413 | | |
| 2414 | + | |
| 2415 | + | |
| 2416 | + | |
| 2417 | + | |
| 2418 | + | |
2414 | 2419 | | |
2415 | | - | |
| 2420 | + | |
2416 | 2421 | | |
2417 | 2422 | | |
2418 | 2423 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
358 | 358 | | |
359 | 359 | | |
360 | 360 | | |
361 | | - | |
362 | | - | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
363 | 367 | | |
364 | 368 | | |
365 | 369 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
618 | 618 | | |
619 | 619 | | |
620 | 620 | | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
621 | 627 | | |
622 | 628 | | |
623 | 629 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
246 | 246 | | |
247 | 247 | | |
248 | 248 | | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
249 | 253 | | |
250 | 254 | | |
251 | 255 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
216 | 216 | | |
217 | 217 | | |
218 | 218 | | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
219 | 229 | | |
220 | 230 | | |
221 | 231 | | |
| |||
0 commit comments