Skip to content

fix(review-gateway): import Any so the module's annotations resolve - #1160

Open
seonghobae wants to merge 2 commits into
mainfrom
fix/review-gateway-missing-any-import
Open

fix(review-gateway): import Any so the module's annotations resolve#1160
seonghobae wants to merge 2 commits into
mainfrom
fix/review-gateway-missing-any-import

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

The bug

review_pool_admissions is annotated Sequence[Any], but review_gateway imports only Mapping and Sequence from typing. from __future__ import annotations keeps annotations as strings, so the module imports cleanly and every existing test passes. The break surfaces only for a caller that resolves the annotations:

>>> import typing
>>> from contextual_orchestrator import review_gateway
>>> typing.get_type_hints(review_gateway.review_pool_admissions)
NameError: name 'Any' is not defined

That reaches any runtime type checker, dataclass/schema generator, docs builder, or validation layer that introspects this module — which matters here specifically, because review_pool_admissions is the owner-side provenance projection a consumer is meant to read instead of re-deriving admission itself. Its own docstring says the point is that a caller sends only the gateway token and model: orchestrator/free. A consumer building that integration against a typed contract is exactly the caller that resolves these hints.

Scope is one name, deliberately

A package-wide get_type_hints sweep flags three modules. I checked each rather than fixing what the sweep printed:

Module Name Verdict
review_gateway Any real — plain typing name, never imported, no TYPE_CHECKING block
model_discovery PriceBook correct as written — if TYPE_CHECKING: from .cost_ledger import PriceBook, annotations properly quoted
provider_catalog_store PrivacyPolicyAssessment correct as written — same deliberate pattern

The latter two are the documented circular-import remedy, whose cost is precisely that get_type_hints cannot resolve them. Fixing them would mean undoing the remedy. Left alone. review_gateway declares no TYPE_CHECKING block, so it has no name it is entitled to leave unresolvable — which is what makes the sweep below a sound contract for this module and not for those.

Test

tests/test_review_gateway_annotation_resolution.py sweeps every function and class the module defines and asserts its hints resolve, so the next such name is caught rather than waiting for a consumer to hit it. It also:

  • pins the no-TYPE_CHECKING premise the sweep rests on, so the contract fails loudly if the module ever adopts deferred imports rather than silently becoming wrong;
  • guards against passing vacuously on an empty member list.

Verified it actually fails without the one-line fix:

without fix: 2 failed, 10 passed
with fix:    12 passed

Verification

3611 passed, 2 skipped
interrogate: RESULT: PASSED (minimum: 100.0%, actual: 100.0%)
tests/test_self_check.py, tests/test_api_contract.py, tests/test_conventions.py — all OK

Two unrelated failures (test_psychometric_routing, test_spend_analytics) reproduce identically on unmodified origin/main in this container and are environmental, not regressions: fast_mlsirm is a python_full_version >= '3.12' dependency and this container runs Python 3.11.15, and tiktoken is absent, which moves usage_source from "mixed" to "tokenizer". CI installs the full lock on the right interpreter.

Context

Found while validating ContextualWisdomLab/.github#2137, which advances the central review sidecar's vendored pin to 012beaac and inspects every symbol the sidecar imports from this package at that revision.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KPmJErfkcHer4UVEgrQxUX


Generated by Claude Code

Summary by CodeRabbit

  • 버그 수정

    • 리뷰 게이트웨이에서 일부 타입 주석이 런타임에 올바르게 해석되지 않을 수 있는 문제를 수정했습니다.
    • 리뷰 풀 입장 정보의 타입 처리를 안정화했습니다.
  • 테스트

    • 모듈 내 주요 기능의 타입 주석이 정상적으로 해석되는지 자동으로 검증하는 테스트를 추가했습니다.
    • 향후 타입 주석 변경으로 인한 회귀 문제를 조기에 확인할 수 있습니다.

review_pool_admissions is annotated `Sequence[Any]` while the module imports
only Mapping and Sequence from typing. `from __future__ import annotations`
keeps annotations as strings, so the module imports cleanly and every existing
test passes -- the break surfaces only for a caller that *resolves* the
annotations:

    >>> import typing
    >>> from contextual_orchestrator import review_gateway
    >>> typing.get_type_hints(review_gateway.review_pool_admissions)
    NameError: name 'Any' is not defined

That reaches any runtime type checker, dataclass/schema generator, docs
builder, or validation layer that introspects this module -- which matters
here because review_pool_admissions is the owner-side provenance projection a
consumer is meant to read instead of re-deriving admission itself.

Scope is exactly one name. A package-wide sweep also flags
model_discovery.PriceBook and provider_catalog_store.PrivacyPolicyAssessment,
but both are deliberate `if TYPE_CHECKING:` deferred imports with correctly
quoted annotations -- the documented circular-import remedy, whose cost is
precisely that get_type_hints cannot resolve them. Those are correct as
written and are left alone. review_gateway declares no TYPE_CHECKING block, so
it has no name it is entitled to leave unresolvable.

tests/test_review_gateway_annotation_resolution.py sweeps every function and
class the module defines and asserts its hints resolve, so the next such name
is caught rather than waiting for a consumer to hit it. Verified the sweep
fails without this one-line fix (2 failed) and passes with it (12 passed); it
also pins the no-TYPE_CHECKING premise the sweep rests on, and guards against
passing vacuously on an empty member list.

Suite: 3611 passed, 2 skipped. Two unrelated failures
(test_psychometric_routing, test_spend_analytics) reproduce identically on
unmodified origin/main in this container and are environmental: fast_mlsirm is
a `python_full_version >= '3.12'` dependency and this container runs 3.11.15,
and tiktoken is absent, which moves usage_source from "mixed" to "tokenizer".
interrogate: 100%.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KPmJErfkcHer4UVEgrQxUX
@coderabbitai

coderabbitai Bot commented Sep 13, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: eca90fa1-b575-4fc4-a7c6-979a716b30c4

📥 Commits

Reviewing files that changed from the base of the PR and between 012beaa and 985aa1a.

📒 Files selected for processing (2)
  • contextual_orchestrator/review_gateway.py
  • tests/test_review_gateway_annotation_resolution.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

review_gatewayAny import가 추가되었습니다. 새 테스트는 모듈 구성원의 annotation이 런타임에 해석되는지 확인하고, review_pool_admissionsSequence[Any] 해석과 TYPE_CHECKING 블록 부재를 검증합니다.

Changes

Annotation resolution 보강

Layer / File(s) Summary
Annotation import 및 검증 테스트
contextual_orchestrator/review_gateway.py, tests/test_review_gateway_annotation_resolution.py
review_gatewayAny를 import합니다. 새 테스트는 모듈 고유 함수와 클래스를 수집하고, 각 annotation에 typing.get_type_hints를 적용합니다. review_pool_admissionsagents annotation이 Sequence[Any]로 해석되는지 확인합니다. 모듈에 TYPE_CHECKING 블록이 없는지도 확인합니다.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 71cb6

The annotation-resolution regression is addressed and covered by focused tests; no actionable merge risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 Any import 추가를 통해 review_gateway의 런타임 어노테이션을 해결하는 주요 변경 사항을 정확하고 간결하게 설명합니다.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 2 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/review-gateway-missing-any-import

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

The three CodeQL compatibility analysis shards — org-central publish failure, not this PR's

Failing on 985aa1a3: CodeQL compatibility analysis for python, actions, and javascript-typescript. Otherwise 14 success, 2 in progress (noema-review, strix), 4 queued.

One argument I can't use here, so I'm not going to. On the .github side of this same failure I could point at the base branch being red. That doesn't transfer: main@012beaac carries no CodeQL compatibility analysis check runs at all — these are injected by the org required-workflow ruleset on pull_request_target, which doesn't fire on base pushes. Absence there is not evidence in either direction, so this rests on the direct root cause instead.

What the shards actually say. Each fails in about three minutes with the designed fast-fail, not with a finding:

##[error] CodeQL scan dispatched. The dispatch workflow will rerun this exact
          failed CodeQL job after publishing its terminal verdict.

They are waiting to be woken. The wake never arrives.

Where it dies. The most recent CodeQL dispatch targeting this repository — run 34730169632 for contextual-orchestrator#995, 108 minutes before this PR's head existed — completes its scan fully (Exporting results to SARIF..., XmlBomb.bqrs and the rest resolved, validate-dispatch success with 4 steps) and then fails on Wake exact CodeQL required job in all three language shards:

##[notice] CodeQL dispatch status publish using target-app-token did not succeed:
           gh: Resource not accessible by integration (HTTP 403)
##[notice] CodeQL dispatch status publish using github-token did not succeed:
           gh: Resource not accessible by integration (HTTP 403)
##[error]  Actions-capable CodeQL wake credential is unavailable.

Cross-repo makes this strictly worse than the same failure inside .github. Publishing to POST /repos/ContextualWisdomLab/contextual-orchestrator/statuses/<sha> and rerunning a job here both require permissions on this repository, held by a workflow running in .github. GITHUB_TOKEN categorically cannot have them, so only the App token could — and it is refused 403 too. That is the Actions-capable CodeQL wake credential is unavailable line: not a transient, a missing grant.

No dispatch for this head yet. I searched roughly 300 recent repository_dispatch runs in .github and found none for contextual-orchestrator#1160@985aa1a3; the only CO-targeting dispatches are the co#995 pair above. Dispatch current-head CodeQL scan is still queued on this head, and .github's dispatch queue currently holds runs sitting queued 8–26 minutes. So this head's sequence has not finished — I am not claiming it already failed, only that co#995 shows where it lands.

No fix exists for me to port. This PR adds one name to a typing import and one test file. It touches no workflow, no CodeQL configuration, no query. The blocker is a credential grant in another repository's control plane, which nothing in this diff can carry. Evidence is on .github#2040 and .github#2137, where the same class is being worked.

The one permitted re-run stays unspent. A 403 on a fixed endpoint with two fixed credentials is deterministic; re-running would consume a runner to watch the same refusal. It remains available if something changes and it becomes informative.

This PR stays watched and I will re-check at each check-in. Nothing on my side turns these three green — they resolve when the wake credential does.

Refs ContextualWisdomLab/.github#1929, ContextualWisdomLab/.github#2040.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

Correction to one clause above — the cross-repo diagnosis holds, the comparison to .github did not

In my comment above I wrote that cross-repo "makes this strictly worse than the same failure inside .github," implying .github hits the same wall. It does not, and I had mislabelled the evidence that led me there — the run I had been treating as .github-targeting actually targets naruon. Full retraction on .github#2040.

The substance for this PR is unchanged, and is now better supported. The two paths genuinely differ:

  • Same-repo (.github scanning itself): the POST /statuses/<sha> 403 is survivable. The wake step falls through to POST /actions/jobs/{id}/rerun and that call succeeds. Demonstrated on .github#2137 this hour — CodeQL compatibility analysis (actions) went green at 03:13:05Z by exactly that fallback, after its status publish had 403'd.
  • Cross-repo (this repository, naruon, every other sibling): the wake never reaches that fallback. It exits earlier with Actions-capable CodeQL wake credential is unavailable, verified identically on contextual-orchestrator#995 (run 34730169632) and the naruon run. Re-running a job in this repository needs Actions write here, held by a workflow running in .github — which GITHUB_TOKEN cannot have and the App token evidently does not carry.

So the escape hatch that rescues .github's own PRs is structurally unavailable to this one. That strengthens rather than weakens the conclusion I drew: these three shards are not this PR's to fix, no fix exists in a one-name typing import to port, and they turn green when an Actions-capable credential for this repository does.

One thing I should flag rather than leave implied: I have not verified any App installation grant or repository setting. Those endpoints are blocked to me by my own tooling proxy, not by GitHub, so "the App token evidently does not carry it" is inference from the error string, not a reading of the configuration.


Generated by Claude Code

Copy link
Copy Markdown
Contributor Author

strix — sandbox bootstrap, not a security finding

Run 34734003260 / job 103662659095 failed at 03:29:18Z:

STRIX_PROVIDER_UNAVAILABLE: STRIX_SANDBOX_UNAVAILABLE: the last Strix attempt
ended in the sandbox bootstrap (Caido proxy on 127.0.0.1 unreachable through
Strix's log…)

STRIX_SANDBOX_UNAVAILABLE is the token .github#1953 introduced precisely so this class stops being attributed to the gateway: the sandbox container never reaches its Caido proxy, so the run dies before any analysis happens. No vulnerability analysis ran, so this is not a finding against the diff — which is one name added to a typing import plus a test file, touching no network path, no sandbox, and no dependency.

Two observations worth recording rather than acting on here:

  • The outer message still says "provider/backend was unavailable" even though the inner token says sandbox. .github#1953 fixed that mis-attribution in opencode-review-dispatch.yml's finding emitter; the gate's own error line still leads with STRIX_PROVIDER_UNAVAILABLE: before the sandbox token. Cosmetic here, but it is the same wrong attribution one layer up, and it will send a reader at gateway or provider configuration for a container networking failure. Belongs to .github, not this PR.
  • The job ran with CWL_STRIX_UNBOUNDED_INFERENCE: 1, which is the correct posture per ADR-0003 and is unrelated to this failure — the run never got as far as inference.

No fix to port and nothing to push. Not re-running it: the previous CodeQL re-run on the sibling .github#2137 established that a re-run here buys a second identical result rather than information, and sandbox bootstrap failures are not the "died before any test body ran" case where a re-run is cheap and diagnostic — the container did start, it just could not reach its proxy.

This PR now stands at 19 success, three CodeQL shards red on the cross-repo wake-credential gap described above, and strix red on sandbox bootstrap. None of the four is caused by the diff, and none is fixable from inside it. Staying watched.

Refs ContextualWisdomLab/.github#1953, ContextualWisdomLab/.github#2141.


Generated by Claude Code

@seonghobae
seonghobae marked this pull request as ready for review September 13, 2026 11:17
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants