Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
76be330
fix(tests): update 3 tests stale after intentional orchestrator/free …
claude Sep 1, 2026
a065431
ci: pin available Linux runner
seonghobae Sep 1, 2026
a32c736
ci: pin fuzz Linux runner
seonghobae Sep 1, 2026
62479a9
ci: pin security Linux runner
seonghobae Sep 1, 2026
f3ef3dc
test: preserve mixed spend evidence semantics
seonghobae Sep 1, 2026
25ec482
test: isolate spend source from optional judge dependency
seonghobae Sep 1, 2026
fd9aac5
fix: reject non-empty all-zero served_usage as reported spend evidence
claude Sep 1, 2026
3c8373b
test(accounting): isolate provider usage capture
seonghobae Sep 1, 2026
903aa4f
test(judge): distinguish provider zero usage provenance
seonghobae Sep 1, 2026
1f97228
test(judge): probe usage provenance aliases and TOCTOU
seonghobae Sep 1, 2026
934fdb0
chore: apply one-shot usage provenance repair
seonghobae Sep 1, 2026
9556fc8
ci(repair): move usage provenance one-shot off saturated Linux queue
seonghobae Sep 1, 2026
1fac323
fix(judge): preserve provider usage provenance
claude Sep 1, 2026
c4d46b7
Merge remote-tracking branch 'origin/fix/orchestrated-responses-strea…
claude Sep 1, 2026
8b2ff71
ci(repair): make usage provenance writer single-flight
seonghobae Sep 1, 2026
9447030
fix(judge): preserve provider usage provenance
github-actions[bot] Sep 1, 2026
39736e7
Merge remote-tracking branch 'origin/fix/orchestrated-responses-strea…
claude Sep 1, 2026
917ce40
test(judge): cover Responses zero usage fields
seonghobae Sep 1, 2026
238a880
ci(repair): apply usage counter family fix once
seonghobae Sep 1, 2026
9ab8c59
ci(repair): move usage counter writer to Linux
seonghobae Sep 1, 2026
4351a04
ci(temp): repair Responses usage alias accounting
seonghobae Sep 1, 2026
82cb7ed
Merge remote-tracking branch 'origin/fix/orchestrated-responses-strea…
claude Sep 1, 2026
589210a
fix(repair): make usage alias writer executable
seonghobae Sep 1, 2026
6eafe23
fix(judge): accept Responses usage counters in both accounting helpers
claude Sep 1, 2026
dfc04d8
ci(repair): remove superseded usage counter writer
seonghobae Sep 1, 2026
06e6369
ci: remove temporary usage repair workflow
seonghobae Sep 1, 2026
e53e92f
ci(temp): execute bounded Responses usage repair
seonghobae Sep 1, 2026
c1bf375
ci(repair): apply Responses usage alias fix with locked test env
seonghobae Sep 1, 2026
bd8f8f8
ci: remove failed one-shot usage repair workflow
seonghobae Sep 1, 2026
2f5f84e
ci: remove queued one-shot usage repair workflow
seonghobae Sep 1, 2026
d9ceca4
ci(repair): retry Responses alias repair with minimal writer
seonghobae Sep 1, 2026
bcc7d18
Merge remote-tracking branch 'origin/fix/orchestrated-responses-strea…
claude Sep 1, 2026
ebb087b
chore: remove now-fulfilled usage alias repair retry workflow
claude Sep 1, 2026
c499516
ci(repair): trigger Responses alias repair on PR events
seonghobae Sep 1, 2026
8f9fd87
Merge remote-tracking branch 'origin/fix/orchestrated-responses-strea…
claude Sep 1, 2026
2253866
test(batch): add exact-head worker usage fixture repair driver
seonghobae Sep 2, 2026
cbf5860
ci(test): run exact-head batch usage fixture repair
seonghobae Sep 2, 2026
22f665c
chore(test): mark current-main convergence intent
seonghobae Sep 2, 2026
44dcb0a
chore(test): add exact current-main merge helper
seonghobae Sep 2, 2026
c8bff9a
chore(test): stage non-destructive current-main merge
seonghobae Sep 2, 2026
338464a
merge current main into PR 1002 without rewriting history
seonghobae Sep 2, 2026
61384c5
test(batch): isolate provider usage fixture from optional judge
Sep 2, 2026
2f325e8
docs(tests): close CodeRabbit's diff-scoped docstring coverage gap
claude Sep 2, 2026
cef6214
Merge remote-tracking branch 'origin/main' into pr1002-work
claude Sep 2, 2026
02b61e4
Merge remote-tracking branch 'origin/main' into pr1002-work
claude Sep 3, 2026
65f5a03
fix(tests): wait for provider embedding batch completion before asser…
claude Sep 3, 2026
91ef087
fix: capture judge usage provenance atomically, immune to pool races
claude Sep 3, 2026
27b6ba5
Merge branch 'main' into fix/orchestrated-responses-stream-and-spend-…
opencode-agent[bot] Sep 4, 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
33 changes: 24 additions & 9 deletions tests/test_orchestrated_responses_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,20 @@ def test_virtual_models_stream_openai_reasoning_summaries(model: str) -> None:
for event in events
if event["type"] == "response.reasoning_summary_text.delta"
]
assert summaries == [
"Planning the approach.",
"Executing the selected approach.",
"Checking the result for errors and unsupported claims.",
"Preparing the final answer.",
]
# orchestrator/free unconditionally stays on the single-worker route path
# (would_route excludes it from the conduct-eligible model set -- see
# "Keep orchestrator/free on the auto route path"), so only the "worker"
# stage summary is emitted. Every other virtual model still runs the full
# thinker/worker/verifier/synthesizer conduct workflow.
if model == TaskOrchestrator.FREE_MODEL:
assert summaries == ["Executing the selected approach."]
else:
assert summaries == [
"Planning the approach.",
"Executing the selected approach.",
"Checking the result for errors and unsupported claims.",
"Preparing the final answer.",
]
assert all("[" not in summary for summary in summaries)
assert any(
event["event_name"] == "responses_orchestrated"
Expand All @@ -84,7 +92,7 @@ def test_virtual_models_stream_openai_reasoning_summaries(model: str) -> None:
runs = list(orchestrator._workflow_runs.values())
assert len(runs) == 1
run = runs[0]
assert run["mode"] == "conduct"
assert run["mode"] == ("route" if model == TaskOrchestrator.FREE_MODEL else "conduct")
assert run["prompt_text"] == "Research, implement, and verify a safe design."
assert run["policy_snapshot"] == orchestrator.policy.as_dict()
assert orchestrator.get_access_report(run["workflow_run_id"])["policy_snapshot"] == run[
Expand Down Expand Up @@ -473,8 +481,12 @@ def recording_chat(agent, messages, *args, **kwargs):
thread.join(timeout=5)

assert observed_messages
# orchestrator/free always takes the single-worker route path (see
# would_route), which forwards the original message array to the agent
# unchanged -- unlike conduct, it does not prepend a per-stage system
# instruction, so the caller's messages start at index 0.
assert any(
[message.get("role") for message in messages][1:4]
[message.get("role") for message in messages][0:3]
== ["system", "user", "assistant"]
for messages in observed_messages
)
Expand Down Expand Up @@ -526,7 +538,10 @@ def test_stream_failure_emits_terminal_responses_event() -> None:
orchestrator = TaskOrchestrator([
ModelAgent("free_worker", "free-model", tags=("reasoning", "cost:free"))
])
orchestrator.conduct = lambda *args, **kwargs: (_ for _ in ()).throw(RuntimeError("secret failure")) # type: ignore[method-assign]
# orchestrator/free always takes the single-worker route path (see
# would_route), so streaming failures for this model surface through
# stream_route rather than conduct.
orchestrator.stream_route = lambda *args, **kwargs: (_ for _ in ()).throw(RuntimeError("secret failure")) # type: ignore[method-assign]
server = build_server(orchestrator, port=0, security=SecurityConfig(auth_token=token))
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
Expand Down
11 changes: 10 additions & 1 deletion tests/test_spend_analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,16 @@ def test_exact_output_without_prompt_usage_is_explicitly_unavailable() -> None:
assert report["totals"]["output_tokens"] > 0
assert report["totals"]["prompt_tokens"] is None
assert report["totals"]["cost_usd"] is None
assert row["usage_source"] == "mixed"
# The single "general_agent" runs every conduct stage (and the realtime
# judge) against the mock:// transport, which never populates usage --
# ModelClient.chat() resets self._local.usage to None and leaves it
# unset on the mock path (see _step_output_tokens: "reported" strictly
# requires a step["usage"] dict with a valid completion/output token
# count). Every step therefore falls back to the exact declared-model
# tokenizer, so this bucket is homogeneously "tokenizer" -- "mixed"
# requires at least one genuinely provider-reported step, which this
# offline fixture can never produce.
assert row["usage_source"] == "tokenizer"
assert row["cost_usd"] is None
assert not any("estimated" in key for key in row | report["totals"])

Expand Down
Loading