Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c1dea89
fix(control-plane): resume unstarted cadence reservations
Duang777 Oct 8, 2026
4cd68b6
Merge upstream/main into codex/fix-cadence-reservation-resume
Duang777 Oct 9, 2026
aa8dc6e
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
fa84358
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
ae91942
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
5294cc1
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
f423116
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
1b06b30
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
bbdd45d
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
a0ca47c
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
7d038e6
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
2bf12c9
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
579f728
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
9f0028d
Merge latest upstream/main into cadence reservation fix
Duang777 Oct 9, 2026
949b298
Merge latest upstream/main and document cadence recovery
Duang777 Oct 9, 2026
641855d
Merge remote-tracking branch 'upstream/main' into codex/fix-cadence-r…
Duang777 Oct 9, 2026
8ad09a7
test(control-plane): close cadence recovery review gaps
Duang777 Oct 10, 2026
e8ba0a6
Merge remote-tracking branch 'upstream/main' into codex/fix-cadence-r…
Duang777 Oct 10, 2026
093bdd8
Merge remote-tracking branch 'upstream/main' into codex/fix-cadence-r…
Duang777 Oct 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions loopx/control_plane/quota/automation_cadence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,8 @@ export async function admitAutomationStart(p: JsonObject): Promise<JsonObject> {
}
if (held !== undefined) {
// Same identity, no durable host attempt: keep the original interval anchor.
return manual === null && current.eligible_now !== true
? {...current, admitted: false, reserved: false, reason: "minimum_interval_wait"}
: {...current, admitted: true, reserved: true, resumed: true,
reason: "resumed_unstarted_reservation"};
return {...current, admitted: true, reserved: true, resumed: true,
reason: "resumed_unstarted_reservation"};
}
if (manual === null && current.eligible_now !== true) {
return {...current, admitted: false, reserved: false, reason: "minimum_interval_wait"};
Expand Down
4 changes: 2 additions & 2 deletions tests/control_plane_ts/automation_cadence.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ test("an unconfirmed reservation resumes while a confirmed start fails closed",
await manage({...base, operation: "configure", expected_revision: 0, min_interval_minutes: 60,
owner_reference: "owner-request", execute: true});
assert.equal((await start("turn:1", 1000)).reserved, true);
assert.equal((await start("turn:1", 1000 + 3_600_000 - 1)).reason, "minimum_interval_wait");
const resumed = await start("turn:1", 1000 + 3_600_000);
assert.equal((await start("turn:2", 1001)).reason, "minimum_interval_wait");
const resumed = await start("turn:1", 1001, {trigger_at_ms: 1000});
assert.equal(resumed.admitted, true);
assert.equal(resumed.resumed, true);
assert.equal(resumed.reason, "resumed_unstarted_reservation");
Expand Down
4 changes: 2 additions & 2 deletions tests/test_loopx_turn_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1322,7 +1322,7 @@ def die_after_reservation(identity: Mapping[str, object]) -> dict[str, object]:
assert calls == {"host": 0, "writeback": 0, "spend": 0, "scheduler": 0}

started_at_ms = int(_cadence_starts(runtime_root)[0]["started_at_ms"])
monkeypatch.setattr(turn_cadence, "time", _FrozenTurnClock(started_at_ms + 120_000))
monkeypatch.setattr(turn_cadence, "time", _FrozenTurnClock(started_at_ms + 1))
restart = _managed_cadence(runtime_root)
recovered = run_loopx_turn_once(
plan, admit_start=restart.admit, confirm_start=restart.confirm, **common
Expand Down Expand Up @@ -1368,7 +1368,7 @@ def die_before_attempt_record(path: Path, journal: dict[str, object]) -> None:
assert calls == {"host": 0, "writeback": 0, "spend": 0, "scheduler": 0}

started_at_ms = int(_cadence_starts(runtime_root)[0]["started_at_ms"])
monkeypatch.setattr(turn_cadence, "time", _FrozenTurnClock(started_at_ms + 120_000))
monkeypatch.setattr(turn_cadence, "time", _FrozenTurnClock(started_at_ms + 1))
restart = _managed_cadence(runtime_root)
recovered = run_loopx_turn_once(
plan, admit_start=restart.admit, confirm_start=restart.confirm, **common
Expand Down
Loading