Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion scripts/consume_daily_briefing.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ def main(argv: list[str] | None = None) -> int:
except (OSError, ValueError, TypeError, KeyError, OverflowError):
summary = {"status": "unavailable", "reason": "briefing_input_unavailable", "advisory_only": True}
print(json.dumps({"day": args.day, "ai_summary": summary}, ensure_ascii=False, indent=2))
return 0 if summary["status"] in {"available", "dry_run"} else 3
# deferred = trusted capacity/scheduling decision with artifact; do not
# fail the OIDC Actions job (red CI) the way unavailable/input errors do.
return 0 if summary["status"] in {"available", "dry_run", "deferred"} else 3
result = consume_briefing_dir(report_dir, day=args.day)
payload: dict = result.to_dict()
if args.dispatch:
Expand Down
14 changes: 12 additions & 2 deletions scripts/run_global_etf_research_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,25 @@ def _read_json(path: Path, reason: str) -> dict[str, Any]:


def _trusted_deferred_retry_at(raw: Any, *, now: float | None = None) -> int | None:
"""Return the bounded retry time for the one recognized pre-execution deferral."""
"""Return the bounded retry time for the one recognized pre-execution deferral.

Service-side 429 defer bodies may omit ``failure_category``; the gateway
client injects ``quota_or_capacity_failure`` when present. Accept either
the exact category or a missing/empty category when the other quota fields
already match, so deferred is not mis-labeled ``global_codegen_gateway_failed``.
"""
if not isinstance(raw, Mapping):
return None
retry_at = raw.get("retry_at")
failure_category = raw.get("failure_category")
if (
raw.get("status") != "deferred"
or raw.get("execution_started") is not False
or raw.get("error") != _DEFERRED_QUOTA_ERROR
or raw.get("failure_category") != _DEFERRED_FAILURE_CATEGORY
or (
failure_category not in (None, "")
and failure_category != _DEFERRED_FAILURE_CATEGORY
)
or isinstance(retry_at, bool)
or not isinstance(retry_at, (int, float))
or not math.isfinite(retry_at)
Expand Down
8 changes: 7 additions & 1 deletion service/ai_gateway_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,13 @@ def _admit_codex_execute(quota: Any, repo: str, payload: dict[str, Any]) -> dict
and route["reason"] in {"codex_quota_reserved", "codex_account_unavailable", "codex_account_stale"}
and str(payload.get("model") or "") in {"", "auto"}):
return _admit_cursor_execute(quota, repo, payload)
return {"status": "deferred", "error": route["reason"], "retry_at": route["retry_at"], "execution_started": False}
return {
"status": "deferred",
"error": route["reason"],
"retry_at": route["retry_at"],
"execution_started": False,
"failure_category": "quota_or_capacity_failure",
}
payload.update(model=route["model"], reasoning_effort=route["reasoning_effort"])
return None
result = quota.check(repo, "codex-cli", str(payload.get("prompt") or ""), codex_account=True)
Expand Down
14 changes: 14 additions & 0 deletions tests/test_daily_briefing_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,20 @@ def test_real_sdk_unavailable_or_deferred_does_not_fallback_or_leak(report, kind
assert result["retry_at"] == 9000


def test_summary_only_deferred_exits_zero_for_oidc_actions(report, capsys):
path, _ = report
with patch(
"scripts.consume_daily_briefing.summarize_briefing",
return_value={"status": "deferred", "advisory_only": True, "retry_at": 9000},
), patch(
"scripts.consume_daily_briefing.consume_briefing_dir",
return_value=object(),
):
assert main(["--report-dir", str(path), "--day", "2026-09-09", "--summary-only"]) == 0
payload = json.loads(capsys.readouterr().out)
assert payload["ai_summary"]["status"] == "deferred"


@pytest.mark.parametrize("field,value", [
("as_of", None), ("as_of", "invalid"), ("as_of", "2026-09-09T22:00:00"),
("as_of", "9999-12-31T23:59:59+00:00"), ("as_of", "2026-09-08T00:00:00+00:00"),
Expand Down
21 changes: 21 additions & 0 deletions tests/test_global_etf_research_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,27 @@ def test_trusted_quota_deferral_preserves_completed_test_summary_and_replays_wit
)
self.assertEqual(replay, result)

def test_service_shape_quota_deferral_without_failure_category_is_deferred(self):
retry_at = int(codegen.datetime.now(codegen.timezone.utc).timestamp()) + 60
response = SimpleNamespace(
success=False, provider="codex", model="", output="",
raw={
"status": "deferred", "execution_started": False,
"retry_at": retry_at, "error": "codex_quota_reserved",
},
)
with TemporaryDirectory() as tmp, patch.object(codegen, "_docker_preflight"), patch.object(
codegen, "_read_global_base", return_value=(codegen.GLOBAL_ETF_RESEARCH_CODEGEN_UES_COMMIT, {})), patch.dict(
sys.modules, {"scripts.run_new_research": SimpleNamespace(_archive_codegen_base=lambda *a, **k: None)}):
result = codegen.run_global_etf_research_codegen_case(
ues_repo_root=tmp, run_root=tmp, source_ref="a" * 40, fetch_source=_source,
candidate_test_runner=lambda *args, **kwargs: {"status": "passed"},
execute=lambda prompt: response,
)
self.assertEqual(result["status"], "deferred")
self.assertEqual(result["reason"], "global_codegen_quota_deferred")
self.assertEqual(result["retry_at"], retry_at)

def test_legacy_gateway_failure_is_deferred_only_for_the_exact_saved_quota_shape(self):
source = _source()
identity = codegen._identity(source=source, source_commit=codegen.GLOBAL_ETF_RESEARCH_CODEGEN_UES_COMMIT)
Expand Down