fix(tests): repair 4 pre-existing test failures on main - #1002
fix(tests): repair 4 pre-existing test failures on main#1002seonghobae wants to merge 48 commits into
Conversation
…routing change; fix 1 impossible usage_source assertion Root causes (all test-only fixes; no production code changed): 1-3. tests/test_orchestrated_responses_stream.py: commit 9173923 ("Keep orchestrator/free on the auto route path") intentionally removed FREE_MODEL from would_route()'s conduct-eligible set, so orchestrator/free now unconditionally takes the single-worker route path instead of the thinker/worker/verifier/synthesizer conduct workflow, regardless of _needs_workflow(). That commit already added its own passing regression tests (test_chat_orchestration_mode_http_honesty.py, test_routing_eval.py) locking in the new behavior, but left 3 tests in this file asserting the old conduct-path shape for orchestrator/free: - test_virtual_models_stream_openai_reasoning_summaries[orchestrator/free]: expected a 4-stage reasoning summary; route now emits only one ("Executing the selected approach."), and run["mode"] is "route" not "conduct". Verified against the pre-9173923b revision that the test passed there, confirming the routing change is what broke it. - test_http_virtual_responses_preserves_message_array_and_sampling_controls: asserted the caller's [system, user, assistant] messages at slice [1:4], which only holds when conduct prepends a per-stage system instruction at index 0. route_once forwards the original messages unchanged, so they start at index 0 -- confirmed by direct instrumentation of client.chat(). - test_stream_failure_emits_terminal_responses_event: patched orchestrator.conduct to raise, but orchestrator/free's stream now never calls conduct, so the failure injection no longer fired. Repointed the mock to stream_route (the method actually invoked on this path); the generic Exception handler's redaction/response.failed behavior in _stream_orchestrated_response is unchanged. 4. tests/test_spend_analytics.py::test_exact_output_without_prompt_usage_is_explicitly_unavailable: asserted usage_source == "mixed", which is structurally unreachable for this fixture. _step_output_tokens() only returns "reported" when a step carries a usage dict with a valid completion/output token count, and the single agent here uses the mock:// transport, which ModelClient.chat() never populates with usage (self._local.usage stays None on that path). Every conduct-stage and judge step therefore falls back to the exact tokenizer, so the bucket is homogeneously "tokenizer" -- "mixed" would require at least one genuinely provider-reported step, which this offline fixture can never produce. Confirmed by direct inspection of _step_output_tokens and by exercising the fixture with a working fast-mlsirm judge mocked in (still all-tokenizer). This was wrong from the test's introduction in b2a2607 (#975) and unrelated to any later commit. The tests/test_psychometric_routing.py::test_fast_mlsirm_fit_uses_judge_acceptance_item_for_context_score failure (ModuleNotFoundError: fast_mlsirm, gated on python_full_version >= 3.12) is confirmed environment-scoped, not touched here. Verification (Python 3.11.15 venv, pinned hash-locked install per CLAUDE.md/AGENTS.md; fast-mlsirm's private-repo tarball could not be fetched through this sandbox's egress proxy, so numpy/fast_mlsirm and tests/test_psychometric_routing.py are unavailable here -- a sandbox limitation, not a code issue): - python -m pytest tests -q --continue-on-collection-errors: 3300 passed, 2 skipped (docker CLI unavailable; optional mcp/_token_packer deps not installed), 1 collection error (the known numpy/fast_mlsirm gap above). All 4 target tests now pass; no other regressions. - coverage run -m pytest tests -q --ignore=tests/test_psychometric_routing.py: 3300 passed, 2 skipped, 0 failed. coverage report: 95% (gaps are the same fast-mlsirm/numpy-gated branches, e.g. psychometric_routing.py at 50%; pre-existing and unrelated to this change -- production code was not modified). - interrogate: RESULT PASSED (minimum: 100.0%, actual: 100.0%). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughJudge 사용량의 출처와 snapshot 처리를 명확히 하고, provider 및 mock usage의 회계 규칙과 테스트를 갱신했습니다. GitHub Actions 작업의 실행 러너를 ChangesJudge 사용량 회계
CI 실행 환경 고정
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: 🔵 Low · up to The embedding-batch test synchronization change is approved, but an earlier workflow configuration concern remains unresolved and should be addressed before relying on that automation. Sequence Diagram(s)sequenceDiagram
participant FastMLSIJudgeAdapter
participant ProviderOrMockTransport
participant TaskOrchestrator
FastMLSIJudgeAdapter->>ProviderOrMockTransport: Judge 요청
ProviderOrMockTransport-->>FastMLSIJudgeAdapter: 응답과 usage 반환
FastMLSIJudgeAdapter->>FastMLSIJudgeAdapter: usage snapshot과 출처 기록
FastMLSIJudgeAdapter-->>TaskOrchestrator: judge 결과와 accounting fields 반환
TaskOrchestrator->>TaskOrchestrator: judge_usage 우선 판정
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
_judge_adapter_accounting_fields() used a plain truthiness check on served_usage, so a non-empty-but-all-zero usage dict (which fast-mlsirm produces when it aggregates a missing trace) was treated as genuine reported spend, disagreeing with the already-guarded sibling check a few lines above for the identical issue (Devin review on #961). Add a shared _usage_has_positive_evidence() helper and apply it consistently at both call sites so a completed-but-unmeasured judge call stays honestly attributed as unmeasured rather than fabricated as reported-zero spend. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4
|
Pushed Devin's finding that Fix: a shared Added two regression tests to
This is independent of and additive to the test-isolation fix already on this branch — both fixes fix different halves of the same underlying Generated by Claude Code |
Manually completes the fix the "One-shot usage provenance repair" workflow (added in 934fdb0) was written to apply, since that workflow has been stuck queued on this org's saturated Actions fleet since it was added (first on ubuntu-24.04, then macos-15 in 9556fc8 -- neither has run) and the underlying finding is merge-blocking per review. Applies the exact same patch the workflow's embedded script specifies, plus two fixes the workflow itself did not cover: - complete()'s served_usage_source resolution looks up the actually- served agent via self.orchestrator._agent(served_id) to classify provenance; when _invoke fails over to (or a test stands in) an agent outside the orchestrator's own candidate pool, that lookup raises KeyError. Catch it and fall back to unknown provenance (None, already the documented "unmeasured" case) instead of losing the call's accounting entirely. - tests/test_model_judge_usage_provenance_regression.py's ModelAgent fixtures used "judge-agent"/hyphenated ids, which fail this repo's two-word snake_case object-name convention (contextual_orchestrator.conventions.require_object_name) at construction. Renamed to "judge_agent". - tests/test_model_judge.py::test_fast_mlsirm_path_is_used_when_available asserted judge_usage against fast-mlsirm's result.usage aggregate; the new logic intentionally prefers the adapter's own transport- boundary served_usage capture when both carry evidence, so updated the expectation to the served_usage value that test's own mocked _invoke call actually returns. Removes the now-fulfilled one-shot workflow file per this repo's self-modifying-workflow convention (delete once its purpose is achieved) and cancels both of its stuck queued runs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4
…m-and-spend-analytics-20260901' into fix/orchestrated-responses-stream-and-spend-analytics-20260901 # Conflicts: # .github/workflows/_temp_usage_provenance_repair.yml
…m-and-spend-analytics-20260901' into fix/orchestrated-responses-stream-and-spend-analytics-20260901 # Conflicts: # contextual_orchestrator/orchestrator.py
CodeRabbit flagged 52.17% docstring coverage (12/23 functions) against this PR's diff, below its 80% threshold. This repo's own `interrogate` gate already passed at 100% throughout (it excludes tests/ and private/semiprivate functions), so no production code was undocumented -- the gap was entirely in touched test functions and their nested helper classes, which CodeRabbit's own scanner does count. Added 11 concise, accurate docstrings across the exact 5 files/23 functions CodeRabbit analyzed (verified: 12/23 = 52.1739...% matches their reported 52.17% precisely once nested defs inside touched test functions are included): - tests/test_model_judge_usage_provenance_regression.py: _ChangingUsageResponse.__init__, _ChangingUsageResponse.get, _adapter - tests/test_model_judge.py: test_fast_mlsirm_path_is_used_when_available and its nested _FakeJudge.__init__, _FakeJudge.judge, _Criterion.__init__ - tests/test_batch_optimizer.py: test_batch_route_persists_runs_with_usage - tests/test_provider_usage_capture.py: test_reported_usage_preferred_and_labeled, test_reported_prompt_tokens_surface_in_totals - tests/test_spend_analytics.py: test_exact_output_without_prompt_usage_is_explicitly_unavailable Separately verified CodeRabbit's "Merge Risk: Moderate" usage-accounting and repair-workflow findings against the PR's actual current head and found both already resolved by earlier commits on this branch (the review was submitted against commit 4351a04, a mid-repair state): Responses-API input_tokens/output_tokens aliases were already added to both _usage_has_positive_evidence/_usage_is_reported_token_mapping (6eafe23), and all _temp_usage_*_repair.yml workflow files were already deleted (ebb087b, 06e6369, and others) once their one-shot purpose was fulfilled -- confirmed no such files exist on this head. No production code change needed for either. Full suite verified clean: 3316 passed, 2 skipped, 1 failed (the known, environment-scoped fast_mlsirm ModuleNotFoundError; not a regression). interrogate: RESULT PASSED (100.0%). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4
CodeRabbit follow-up: verified all three findings; docstrings fixed, two already stale, one flagged for owner decisionRe-checked against the PR's actual current head, since CodeRabbit's review ( Docstring coverage (fixed, pushed in "Drops valid Responses usage" (already resolved, no action needed). "Non-parseable repair workflow" (already resolved, no action needed). Adapter reuse lifecycle — documenting for explicit owner attention, not fixing here.
The latent issue is reuse within a single verification call. If that path were ever exercised, each Verified this is dormant, not currently firing: This needs an explicit owner decision on intended adapter lifecycle before
Flagging precisely so it isn't lost, per this session's standing loop directive. 🤖 Generated with Claude Code https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4 Generated by Claude Code |
…fast-mlsirm judge test_exact_output_without_prompt_usage_is_explicitly_unavailable failed on protected main (212ff43, unmodified) and reproduced identically here: AssertionError: assert 'tokenizer' == 'mixed'. The optional fast-mlsirm judge integration is environment-dependent (present/absent changes whether a second judge step contributes a different usage source, which is what made "mixed" true in whatever environment originally authored this assertion) -- this environment has no fast_mlsirm installed, so only the single tokenizer-sourced worker step exists and the correct, deterministic usage_source is "tokenizer". Port PR #1002's fix for this same test (verified there): patch _resolve_fast_mlsirm_components to return None so the assertion is pinned to the raw-output tokenizer-fallback contract this test actually owns, independent of whether the optional dependency happens to be installed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KPmJErfkcHer4UVEgrQxUX
Rebased onto current
|
Diagnosis: pre-
|
…tions Ports the identical fix from #1044 (not yet merged) into this PR's head, per the standing PR-governance rule to port the same change now rather than wait on a separate PR to merge. PR #1002's "Full unit and contract suite" check failed on its current head with exactly one failure, unrelated to this PR's own diff: FAILED tests/test_provider_embedding_batch_backend.py::test_unknown_tokenizer_byte_bound_never_becomes_recorded_usage[한글🙂é] - KeyError: 'total_tokens' 1 failed, 3400 passed, 2 skipped Root cause (from #1044): both test_unknown_tokenizer_uses_authoritative_provider_usage and test_unknown_tokenizer_byte_bound_never_becomes_recorded_usage call complete_embeddings_batch() on a provider-backed (non-mock) embedding agent without wait_timeout. That backend completes asynchronously in a background ThreadPoolExecutor thread, so without wait_timeout the calling thread can read the document before the job finishes, hitting the not-is_complete early-return branch that omits total_tokens entirely. Under CI load this triggers intermittently; the failing Unicode parametrize case is incidental, not causal. Test-only change, no production code touched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4
Ported test-only race fix from #1044 (not yet merged)Diagnosis. This PR's "Full unit and contract suite" check failed on head This is the exact race condition already root-caused and fixed in #1044 ( Per the standing PR-governance rule (port the same change into the affected PR now rather than wait on the origin PR to merge — it no-ops once the base carries it), I ported #1044's identical diff directly onto this PR's head rather than waiting on #1044. Change applied (byte-identical to #1044's diff, verified via matching pre/post blob hashes Verification:
Freshness: confirmed PR head unchanged ( Pushed non-force as a fast-forward: 🤖 Generated with Claude Code Generated by Claude Code |
Devin review on PR #1002 (thread PRRT_kwDOTB3CTs6eVM7K, contextual_orchestrator/orchestrator.py lines ~414-419): after TaskOrchestrator._invoke returns, _FastMLSIJudgeAdapter.complete() re-resolved the serving agent via self.orchestrator._agent(served_id) -- a fresh scan of the *live*, mutable TaskOrchestrator.candidates list -- to classify served_usage_source (provider_reported vs synthetic_mock). Verified the race is real, not theoretical: every pool-mutation API (add/patch/remove/promote/demote candidate, lines ~6018-6265) reassigns self.candidates to a new list rather than mutating it in place, and no lock guards it. build_server() (server.py) wires one TaskOrchestrator instance into every request Handler closure, served by ThreadingHTTPServer, so an admin-API pool mutation on one request thread can race an in-flight judge call's _invoke on another thread against the same orchestrator instance. served_model already avoided this (captured directly from _invoke's own return tuple), but served_usage_source did not -- so a same-id pool replacement landing between the provider call completing and this lookup could relabel a genuine provider-reported all-zero usage as synthetic (spend silently dropped as unmeasured), or relabel synthetic mock/fast-mlsirm zero-fill as provider-reported (fake measured spend recorded) -- exactly Devin's description. Fix: TaskOrchestrator._invoke gains an optional on_success callback, invoked with the exact (frozen) ModelAgent that served the winning call, at both success points -- the sequential failover loop and the immediate endpoint race -- before _invoke returns. Because ModelAgent is a frozen dataclass and candidates/race_members are call-local snapshots immune to a later self.candidates reassignment, this reference can never be retroactively altered by a concurrent pool mutation, unlike a post-hoc self._agent(served_id) lookup. _FastMLSIJudgeAdapter.complete() now prefers this atomically-captured agent for usage-source classification, falling back to the previous self._agent(served_id) lookup only when on_success was never invoked (a custom _invoke test double that ignores the new kwarg entirely) -- preserving compatibility for exactly the test doubles Devin's own suggested direction called out. _invoke's return type and all of its other callers/test doubles are unchanged. Added two regression tests to tests/test_model_judge_usage_provenance_regression.py reproducing the race in both directions Devin asked for: a ModelClient.chat() override mutates orchestrator.candidates (same id, different base_url) as a side effect of serving the call, simulating a concurrent admin request. Confirmed RED against unmodified orchestrator.py (provider-to-mock: served_usage_source flips to synthetic_mock and judge_usage is dropped; mock-to-provider: flips to provider_reported and synthetic zero usage is recorded as measured), then GREEN with this fix. Full suite: 3402 passed, 2 skipped (unrelated), 1 deselected (fast-mlsirm needs Python >=3.12, this venv is 3.11) -- 0 failed. interrogate on the touched production file: 100%. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BV96rXhqoR3tYZ9AeAVur4
…analytics-20260901
Summary
Repair the pre-existing Responses/spend/test failures that README PR #994 exposed after its runner admission repair made the full suite execute.
orchestrator/freeon the integrated single-worker auto-route contract while non-free virtual models retain conduct-path assertions;ubuntu-24.04rather than the starved floating selector;prompt_tokens/completion_tokens) and Responses (input_tokens/output_tokens) token-counter families without converting authoritative all-zero provider evidence into estimated spend.Causal repair lineage
The hosted full suite first exposed worker-accounting fixtures whose evidence scope was polluted by the optional fast-mlsirm judge call. Those tests now suppress only that optional judge path while retaining the actual worker provider call and its usage assertions.
A subsequent valid review showed that an all-zero usage mapping was ambiguous: the same value shape can be a real provider measurement or synthetic mock/fast-mlsirm zero-fill. The source repair therefore records
served_usage_sourceat the transport boundary, follows the agent that actually served after failover, snapshots mutable provider usage, treats provider-reported zero as measured, and leaves synthetic/unknown zero unmeasured.A later exact-head review correctly found that the zero-usage validator only recognized legacy Chat Completions fields. The current source and regression suite now accept complete non-negative Responses counters (
input_tokens,output_tokens,total_tokens) as the same authoritative usage family. Positive aggregate fallback uses the same aliases. The focused regression explicitly proves provider-reported all-zero Responses usage survives accounting.Temporary self-modifying repair workflows used during the source repair have been removed from the branch. Superseded temp-writer review findings are resolved only because those workflow files no longer exist.
Why this owns README #994's blocker
README PR #994 did not create these accounting/test defects; its runner repair exposed them. The causal production/test fixes therefore live here. #994 must converge onto protected
mainonly after this owner repair integrates and then reacquire exact-head README checks/reviews on the new base.Current authority
Exact current head:
8f9fd87283fc6998fc590d3ab7ea3c6007db3bdbon recorded protected basemain@4d143601c2904a28e95d091b261c0a15e9a4f283.Current review-thread inventory is resolved. Fresh exact-head Tests, Security, Fuzz, SAST Semgrep, and Security Scan runs are queued and therefore non-passing. No predecessor-head workflow result transfers. Merge only if this unchanged head becomes terminal-clean and then-live review/thread/branch governance permits the ordinary protected path.
Scope
Tests, repository-owned CI runner admission, and the accounting source repair required to make their asserted evidence truthful. No security threshold, release, deployment, credential, or governance gate is weakened.
Summary by CodeRabbit
개선 사항
품질 개선