Skip to content
Closed
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ this file. The format follows Keep a Changelog, and versioned releases follow
Semantic Versioning where the repository publishes a release.

## [Unreleased]
- Remove Noema's fixed 120-second LLM response timeout. The central workflow
now owns cancellation, allowing the documented multi-hour review path to
finish instead of failing after a healthy orchestrator preflight.
- Harden the review sidecar's per-account catalog cap against silent drift:
`contextual_orchestrator_review_launcher.py`'s two
`build_zdr_prioritized_catalog` call sites now source their
Expand Down
15 changes: 15 additions & 0 deletions docs/doctoring/noema-orchestrator-free-zdr.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ Runtime acceptance requires a GitHub review whose commit and embedded head SHA
both match the live PR head. A successful Actions job without that review body
is not Noema review evidence.

## 2026-08-31 response timeout removal

Two exact-head naruon Noema jobs reached a healthy sidecar and then failed at
the same `urllib` call after its hard-coded 120-second response timeout. This
was shorter than the standing review contract, which permits central LLM
reviews to take two hours or more. `call_llm` now passes `timeout=None`; the
workflow remains the cancellation and concurrency boundary. Redirect refusal,
URL validation, loopback pinning, bounded prompt construction, and substantive
verdict validation are unchanged.

Regression tests assert that both the ordinary provider seam and the rejected
verdict repair call use the unbounded request contract. Hosted acceptance still
requires an exact-head review verdict; removing the client timeout does not
turn an incomplete run into passing evidence.

For GitHub App credentials, reviewer identity is bound to the pinned token
mint action's app slug and numeric installation ID. PAT and OIDC credentials
continue to resolve their actor through GitHub's authenticated API.
3 changes: 2 additions & 1 deletion scripts/ci/noema_review_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,8 @@ def call_llm(
method="POST",
)
opener = urllib.request.build_opener(NoRedirectHandler())
with opener.open(request, timeout=120) as response: # nosec B310
# Noema reviews can legitimately take hours; the workflow owns cancellation.
with opener.open(request, timeout=None) as response: # nosec B310
Comment on lines +656 to +657

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Cancellation remains externally bounded

timeout=None removes connection and read deadlines. Workflow concurrency still cancels superseded runs, so stalled requests remain bounded by Actions cancellation.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

raw = response.read().decode("utf-8")
data = json.loads(raw)
content = (((data.get("choices") or [{}])[0].get("message") or {}).get("content") or "").strip()
Expand Down
2 changes: 1 addition & 1 deletion tests/test_noema_review_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ def read(self):

class Opener:
def open(self, request, timeout):
assert timeout == 120
assert timeout is None
payloads.append(json.loads(request.data))
return Response(invalid if len(payloads) == 1 else valid)

Expand Down
4 changes: 2 additions & 2 deletions tests/test_repository_branch_coverage_review_schedulers.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ def read(self) -> bytes:
class Opener:
"""Open one deterministic provider response."""

def open(self, _request: Any, timeout: int) -> Response:
assert timeout == 120
def open(self, _request: Any, timeout: None) -> Response:
assert timeout is None
return Response()

monkeypatch.setattr(noema.urllib.request, "build_opener", lambda *_args: Opener())
Expand Down
Loading