Skip to content

Add streaming retry resilience coverage - #6376

Merged
ilblackdragon merged 1 commit into
mainfrom
agent/reborn-streaming-retry-resilience
Jul 21, 2026
Merged

ilblackdragon merged 1 commit into
mainfrom
agent/reborn-streaming-retry-resilience

Conversation

@ilblackdragon

@ilblackdragon ilblackdragon commented Jul 20, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Wire Rig-backed LLM calls through provider streaming and preserve streamed reasoning while emitting text deltas through the existing sink.
  • Add programmable Python mock LLM faults for delayed responses, transient HTTP errors, and broken SSE streams, committed atomically after validation.
  • Cover WebUI v2 served streaming/retry/cancel behavior, including stream: true request assertions and lifecycle SSE completion.
  • Allow failed runs with no checkpoint records to retry from the accepted user message, while preserving checkpoint resume for resumable checkpoints and rejecting non-resumable checkpoint states.
  • Add runner coverage for retrying after a transient checkpoint-state outage before the first checkpoint write.

Change Type

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI/Infrastructure
  • Security
  • Dependencies

Linked Issue

None.

Validation

  • cargo fmt --all -- --check equivalent: cargo fmt -p ironclaw_llm -p ironclaw_turns -p ironclaw_runner
  • cargo clippy --all --benches --tests --examples --all-features -- -D warnings equivalent: cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo build
  • Relevant tests pass:
    • python3 -m py_compile tests/e2e/mock_llm.py tests/e2e/conftest.py tests/e2e/scenarios/test_reborn_webui_v2_streaming_run_control_api.py
    • cargo test -p ironclaw_llm rig_adapter
    • cargo test -p ironclaw_turns --test retry_failed_turn_store_contract
    • cargo test -p ironclaw_runner --all-features --test loop_driver_host
    • python3 -m pytest -q tests/e2e/scenarios/test_reborn_webui_v2_streaming_run_control_api.py
  • cargo test --features integration if database-backed or integration behavior changed
  • Manual testing: served WebUI v2 E2E exercises mock LLM delay, broken stream, transient error, streaming request shape, and cancellation thread release.
  • If a coding agent was used and supports it, review-pr or pr-shepherd --fix was run before requesting review: addressed unresolved review threads and reran local validation.

Security Impact

No new credentials, permissions, sandbox policy, or file access. This changes provider request shape to use streaming for Rig-backed model calls and adds hermetic mock-server fault controls under E2E tests only.

Reborn Trust-Boundary Checklist

  • Public policy/evidence/trust-bearing types: no new public trust-bearing types; retry stays inside the turn-state store and existing coordinator/runner path.
  • Untrusted content enters prompts only through an envelope/escaping primitive: unchanged; original accepted user message ref is replayed through the existing turn execution path.
  • Hashes declare purpose; trust/binding/authenticity uses SHA-256/BLAKE3 or separate authenticity check: no hash changes.
  • New/changed status, exit, policy, runtime, or error variants: no new variants; existing host_stage_unavailable_checkpoint and retryable lifecycle flag are reused. Audited through rg -n "host_stage_unavailable_checkpoint|RunNotRetryable|retry_turn_once|run_has_loop_checkpoint" crates/ironclaw_turns crates/ironclaw_runner.
  • Security/durability serde(default) fields fail closed or have migration tests: no new persisted fields or schema changes.
  • Queues/maps/buffers/counters have bounds and overflow-safe arithmetic: retry remains under existing admission/thread-lock/idempotency paths; mock fault scripts are reset between tests and committed atomically.
  • Driver/operator-visible errors have stable class semantics (Transient, Permanent, Misconfigured, PolicyDenied or equivalent): existing checkpoint unavailable category remains stable and retryable when safe.
  • Sandbox/native/host names accurately describe trust boundary: no sandbox/native host naming changes.

Database Impact

None. No migrations or schema changes. Turn-state retry semantics are covered against the filesystem-backed row store contract.

Blast Radius

Touches Rig-backed LLM streaming, Reborn turn retry classification, runner checkpoint-outage behavior, and WebUI v2 served E2E mock LLM scenarios. Regressions would most likely appear as provider streaming request-shape issues, missing reasoning metadata in streamed completions, or incorrect retry affordances for failed runs.

Rollback Plan

Revert this PR commit. That returns Rig-backed WebUI runs to the previous non-streaming provider path and restores the old checkpoint-only retry behavior. No data migration rollback is required.

Review Follow-Through

Addressed review feedback for reasoning propagation, duplicated stream-drain logic, dead test seam shape after turn-state decomposition, duplicate checkpoint helper use, atomic mock LLM fault validation, and duplicated E2E fault scenario structure. Existing IronLoop reviewer could not run validation in its environment; local validation above was run after the latest rebase.


Review track: C (runtime/turn retry and provider streaming behavior)

@ironloopai

ironloopai Bot commented Jul 20, 2026 •

Copy link
Copy Markdown
Contributor

🔎 IronLoop Review Status

Head: 51a2ab8bded5e2df42c4e198f9cce5f534666bab
Result: One or more review results were superseded by a newer PR head.
Next: Run @ironloopai review on the latest PR head.
Updated: 2026-07-21T02:21:34.524Z

Current reviewers:

Reviewer State Verdict Findings Last update
ironloop/common-reviewer (reviewer) Superseded N/A N/A 2026-07-21T00:38:08.855Z
Reviewer summaries
Reviewer Detail
ironloop/common-reviewer (reviewer) Superseded by a newer PR head. New head: 0aa0c25. Previous verdict: Needs validation.
Recent activity
Time Reviewer State Detail
2026-07-20T22:41:02.404Z ironloop/common-reviewer (reviewer) Queued Accepted review request for head ab90450.
2026-07-20T22:41:02.404Z ironloop/common-reviewer (reviewer) Queued Waiting for this reviewer lane to become available.
2026-07-20T22:41:02.920Z ironloop/common-reviewer (reviewer) Started Reviewer worker started.
2026-07-20T22:41:05.812Z ironloop/common-reviewer (reviewer) Workspace ready Prepared isolated checkout (merge_ref) at 5527178.
2026-07-20T22:50:31.207Z ironloop/common-reviewer (reviewer) Result captured Needs validation; 0 blocking findings.
2026-07-20T22:50:31.207Z ironloop/common-reviewer (reviewer) Completed Review completed and terminal status was persisted.
2026-07-21T00:38:08.855Z ironloop/common-reviewer (reviewer) Superseded A newer PR head replaced this review (0aa0c25).
Available commands
  • @ironloopai help
  • @ironloopai agents
  • @ironloopai review
  • @ironloopai review --agent <agent>
Run metadata

Admission: webhook accepted the request and IronLoop persisted reviewer state before this projection.

@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6376 July 20, 2026 22:41 Destroyed
@github-actions github-actions Bot added scope: docs Documentation size: L 200-499 changed lines risk: low Changes to docs, tests, or low-risk modules contributor: core 20+ merged PRs labels Jul 20, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request introduces streaming support for Rig-backed model calls in WebUI v2 runs, adds robust E2E tests for delayed, broken, cancelled, and transient mock LLM behaviors, and enables retrying failed runs after transient checkpoint-state outages, including those failing before the first checkpoint. The review feedback identifies an issue in complete_streaming where reasoning content is discarded and hardcoded to None in CompletionResponse, and suggests propagating the extracted reasoning value to support reasoning-focused models.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/ironclaw_llm/src/rig_adapter.rs Outdated

@ironloopai ironloopai Bot left a comment

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.

⚠️ IronLoop Review: reviewer

Review at a glance

Verdict Blocking Notes Inline Head
⚠️ Needs validation 0 0 0 ab90450e3a7d

Head: ab90450e3a7d442b3bffbe50eaceb02e1aad63e3
Next: Human review or validation is required before merging.

Run details

Status: Current
Needs human: no
Needs validation: yes

Summary

Static review found no blocking correctness or security issue. Targeted Rust and Python validation could not run because this reviewer environment lacks cargo and python3.

Findings

None.

Developer follow-up

After fixing this feedback:

  1. Push the fix to this PR branch.
  2. Re-run this reviewer with @ironloopai review --agent reviewer if you only changed this reviewer's findings.
  3. Re-run all reviewers with @ironloopai review when the fix may affect multiple areas.

@railway-app

railway-app Bot commented Jul 20, 2026 •

Copy link
Copy Markdown

🚅 Deployed to the ironclaw-pr-6376 environment in ironclaw-ci-preview

Service Status Web Updated (UTC)
ironclaw ❌ Build Failed (View Logs) Web Jul 21, 2026 at 2:21 am

@github-actions

github-actions Bot commented Jul 20, 2026 •

Copy link
Copy Markdown
Contributor

Coverage ratchet

Ratchet mode: ENFORCING

RATCHET PASS: global
  observed: 86.41% (321234 / 371765 lines)
  floor:    85.3% (tolerance 0.5pp -> effective floor 84.8%)
  denominator: 371765 lines now vs 320188 at floor capture (+51577 lines, +16.11%) — material change (>5%)

⚠️ 2 Reborn crate(s) have 0 int-tier coverage (target: 0) — ironclaw_prompt_envelope, ironclaw_scripts

Reborn integration-tier coverage

Line coverage (Reborn crates): 86.41% — 321234 / 371765 lines

Per-crate breakdown (65 crates, lowest-covered first)
Crate Line % Covered / Total
ironclaw_prompt_envelope 0% 0 / 88
ironclaw_scripts 0% 0 / 345
ironclaw_runtime_policy 33.84% 89 / 263
ironclaw_event_projections 43.31% 673 / 1554
ironclaw_observability 61.54% 16 / 26
ironclaw_authorization 62.46% 604 / 967
ironclaw_dispatcher 62.88% 83 / 132
ironclaw_mcp 64.89% 595 / 917
ironclaw_filesystem 68.64% 4139 / 6030
ironclaw_channel_host 68.65% 219 / 319
ironclaw_memory 69.2% 773 / 1117
ironclaw_reborn_migration 70.39% 2361 / 3354
ironclaw_trust 72.88% 661 / 907
ironclaw_wasm_limiter 74.6% 47 / 63
ironclaw_extractors 74.72% 538 / 720
ironclaw_capabilities 75.76% 2103 / 2776
ironclaw_projects 76.48% 400 / 523
ironclaw_reborn_cli 76.54% 9890 / 12922
ironclaw_triggers 77.33% 2531 / 3273
ironclaw_llm 78.44% 20553 / 26203
ironclaw_product_context 78.57% 11 / 14
ironclaw_telegram_extension 80.18% 4842 / 6039
ironclaw_wasm_product_adapters 80.36% 1448 / 1802
ironclaw_process_sandbox 80.65% 671 / 832
ironclaw_first_party_extensions 81.06% 5965 / 7359
ironclaw_memory_native 81.17% 3195 / 3936
ironclaw_events 81.95% 1594 / 1945
ironclaw_network 82.98% 673 / 811
ironclaw_reborn_event_store 83.03% 1169 / 1408
ironclaw_reborn_identity 83.59% 433 / 518
ironclaw_processes 83.76% 939 / 1121
ironclaw_secrets 83.79% 2548 / 3041
ironclaw_wasm 84.44% 1069 / 1266
ironclaw_reborn_config 84.66% 2152 / 2542
ironclaw_product_workflow 84.75% 11088 / 13083
ironclaw_auth 84.97% 3279 / 3859
ironclaw_run_state 85.61% 458 / 535
ironclaw_channel_delivery 85.79% 1383 / 1612
ironclaw_common 86.13% 1714 / 1990
ironclaw_threads 87.22% 4838 / 5547
ironclaw_slack_v2_adapter 87.3% 1491 / 1708
ironclaw_skills 87.58% 4470 / 5104
ironclaw_product_adapter_registry 88.06% 531 / 603
ironclaw_product_adapters 88.1% 3384 / 3841
ironclaw_turns 88.12% 13941 / 15821
ironclaw_reborn_traces 88.2% 11946 / 13544
ironclaw_host_runtime 88.69% 18153 / 20467
ironclaw_reborn_openai_compat 88.79% 3778 / 4255
ironclaw_host_api 88.83% 4635 / 5218
ironclaw_webui 89.33% 7700 / 8620
ironclaw_extensions 89.33% 2955 / 3308
ironclaw_telegram_v2_adapter 89.65% 2712 / 3025
ironclaw_reborn_composition 89.8% 75735 / 84338
ironclaw_approvals 90.18% 1598 / 1772
ironclaw_conversations 90.39% 3123 / 3455
ironclaw_event_streams 90.82% 1009 / 1111
ironclaw_hooks 90.88% 10075 / 11086
ironclaw_runner 91.09% 16926 / 18581
ironclaw_resources 91.67% 4477 / 4884
ironclaw_loop_host 92.24% 15992 / 17338
ironclaw_attachments 93.06% 630 / 677
ironclaw_agent_loop 94.95% 9424 / 9925
ironclaw_safety 95.09% 3682 / 3872
ironclaw_outbound 95.52% 3451 / 3613
ironclaw_first_party_extension_ports 95.62% 3672 / 3840

This table itself is informational and never gates the PR on its own — not the percentage, not the per-crate holes, not the 0-coverage callout. A separate coverage ratchet (dry-run until enforce=true; see tests/integration/coverage-floor.toml) can fail the build on specific configured floors.

Exemptions (3 entry/entries excluded from the accounting above)
Module / Crate Reason Issue
crate: ironclaw_embeddings v1-only: consumed only by root ironclaw (src/app.rs, src/tools/builtin/memory.rs, src/workspace/mod.rs, src/config/{mod,embeddings}.rs); no crates/* dependents. Covered by "Tests (Legacy)". #5657
crate: ironclaw_gateway v1-only: consumed only by root ironclaw (src/channels/web/platform/static_files.rs, src/channels/web/handlers/frontend.rs); no crates/* dependents. Covered by "Tests (Legacy)". #5657
crate: ironclaw_tui v1-only: consumed only by root ironclaw (src/main.rs, src/channels/tui.rs); no crates/* dependents. Crate's own doc comment confirms it bridges INTO v1, not Reborn. Covered by "Tests (Legacy)". #5657

@ilblackdragon
ilblackdragon force-pushed the agent/reborn-streaming-retry-resilience branch from ab90450 to 0aa0c25 Compare July 21, 2026 00:38
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6376 July 21, 2026 00:38 Destroyed
@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

RigAdapter now preserves reasoning during plain and tool streaming. Turn retries support failed runs without checkpoints, including transient checkpoint-store recovery. WebUI v2 end-to-end coverage adds scripted mock LLM faults for retries, delays, broken streams, and cancellation.

Changes

Streaming reasoning propagation

Layer / File(s) Summary
Accumulate and return streamed reasoning
crates/ironclaw_llm/src/rig_adapter.rs
Streaming text is forwarded to the sink; reasoning chunks are accumulated and included in plain and tool completion responses.
Validate streaming reasoning fixtures
crates/ironclaw_llm/src/rig_adapter.rs
Streaming-only models and recording sinks test text emission and reasoning-delta propagation.

Checkpointless failed-run retry

Layer / File(s) Summary
Define retryability and checkpoint linkage
crates/ironclaw_turns/src/filesystem_store/turn_state_engine/*
Retryability now permits failures without loop checkpoints and creates retries with optional checkpoint links.
Update checkpointless retry contract
crates/ironclaw_turns/tests/retry_failed_turn_store_contract.rs
The contract test verifies queued checkpointless retries preserve the accepted message reference.
Exercise transient checkpoint recovery
crates/ironclaw_runner/tests/loop_driver_host.rs
A transient checkpoint-store failure is injected, then the failed run is retried and completed without duplicate model dispatch.

Mock LLM fault-driven run control

Layer / File(s) Summary
Implement mock LLM fault controls
tests/e2e/conftest.py, tests/e2e/mock_llm.py
Fault scripts support reset, configuration, matching, delays, HTTP errors, and broken streaming responses.
Cover WebUI v2 streaming recovery
tests/e2e/scenarios/test_reborn_webui_v2_streaming_run_control_api.py
End-to-end tests cover retry, delayed completion, SSE completion, cancellation, and subsequent thread reuse.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant StreamingCompletionModel
  participant RigAdapter
  participant CompletionStreamSink
  StreamingCompletionModel->>RigAdapter: emit text and reasoning chunks
  RigAdapter->>CompletionStreamSink: forward text deltas
  RigAdapter->>RigAdapter: accumulate reasoning details
  RigAdapter-->>StreamingCompletionModel: return final response with reasoning
Loading
sequenceDiagram
  participant WebChatClient
  participant RebornServe
  participant MockLLM
  WebChatClient->>RebornServe: submit message
  RebornServe->>MockLLM: request streaming completion
  MockLLM-->>RebornServe: fault, delay, or broken stream
  RebornServe->>MockLLM: retry request when applicable
  MockLLM-->>RebornServe: completed assistant stream
  RebornServe-->>WebChatClient: completed SSE event
Loading

Suggested reviewers: serrrfirat, think-in-universe

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title is clearly related to the PR’s main change: streaming retry resilience coverage.
Description check ✅ Passed The description matches the template structure and includes the required summary, validation, impact, rollback, and follow-through sections.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/ironclaw_llm/src/rig_adapter.rs`:
- Around line 1072-1105: The streaming response drain logic is duplicated
between the current streaming method and complete_with_tools_streaming. Extract
the shared stream.next() processing, usage/cache extraction, extract_response
call, and StreamedReasoningAccumulator::finish() handling into a helper such as
drain_reasoning_stream, then have both callers use it while preserving their
existing sink behavior and returned values.

In `@crates/ironclaw_turns/src/filesystem_store/turn_state_engine.rs`:
- Around line 3645-3656: Remove the duplicate has_loop_checkpoints_for_run
helper and reuse run_has_loop_checkpoint instead. At
crates/ironclaw_turns/src/filesystem_store/turn_state_engine.rs:3645-3656,
update failed_run_retryable to call run_has_loop_checkpoint with record.scope,
record.turn_id, and record.run_id; at :2961-2979, replace the
has_loop_checkpoints_for_run call on failed with the equivalent
run_has_loop_checkpoint arguments.
- Around line 492-494: Remove the unconditional #[allow(dead_code)] from
with_block_persistence and gate this crate-private test seam with the
repository’s appropriate test configuration, such as #[cfg(any(test, feature =
"test-support"))]. Preserve its availability for tests and test-support builds
without suppressing the dead-code lint.

In `@tests/e2e/mock_llm.py`:
- Around line 3358-3397: Update set_llm_faults to validate and construct the
complete fault-script list in a local collection before changing
_llm_fault_scripts. Only after every fault passes validation should the handler
reset and atomically commit the validated list; any 400 response must leave the
existing shared fault scripts unchanged.

In `@tests/e2e/scenarios/test_reborn_webui_v2_streaming_run_control_api.py`:
- Around line 288-442: Extract the repeated submit, SSE completion wait,
assistant-content wait, request-count wait, and assertions from the three tests
into a shared async helper named _run_fault_scenario. Parameterize it with
marker, actions, and expected_request_count, then update
test_reborn_v2_retries_mock_llm_http_error_then_finalizes,
test_reborn_v2_retries_mock_llm_broken_sse_stream_then_finalizes, and
test_reborn_v2_delayed_mock_llm_response_finalizes to configure their fault
payloads and call the helper while preserving the stream=True assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 918f0bb9-cc77-47f2-b6b8-4e0b8f061478

📥 Commits

Reviewing files that changed from the base of the PR and between 034c177 and 0aa0c25.

⛔ Files ignored due to path filters (1)
  • CHANGELOG.md is excluded by !CHANGELOG.md
📒 Files selected for processing (7)
  • crates/ironclaw_llm/src/rig_adapter.rs
  • crates/ironclaw_runner/tests/loop_driver_host.rs
  • crates/ironclaw_turns/src/filesystem_store/turn_state_engine.rs
  • crates/ironclaw_turns/tests/retry_failed_turn_store_contract.rs
  • tests/e2e/conftest.py
  • tests/e2e/mock_llm.py
  • tests/e2e/scenarios/test_reborn_webui_v2_streaming_run_control_api.py

Comment thread crates/ironclaw_llm/src/rig_adapter.rs Outdated
Comment thread crates/ironclaw_turns/src/filesystem_store/turn_state_engine.rs Outdated
Comment thread crates/ironclaw_turns/src/filesystem_store/turn_state_engine.rs Outdated
Comment thread tests/e2e/mock_llm.py
Comment thread tests/e2e/scenarios/test_reborn_webui_v2_streaming_run_control_api.py Outdated
@ilblackdragon
ilblackdragon force-pushed the agent/reborn-streaming-retry-resilience branch from 0aa0c25 to 51a2ab8 Compare July 21, 2026 02:21
@railway-app
railway-app Bot temporarily deployed to ironclaw-ci-preview / ironclaw-pr-6376 July 21, 2026 02:21 Destroyed
@ilblackdragon
ilblackdragon merged commit 9a9779d into main Jul 21, 2026
64 of 65 checks passed
@ilblackdragon
ilblackdragon deleted the agent/reborn-streaming-retry-resilience branch July 21, 2026 05:09
@serrrfirat serrrfirat mentioned this pull request Jul 29, 2026
18 of 29 tasks

This branch was successfully deployed

No deployments
ironclaw-ci-preview / ironclaw-pr-6376 — 51a2ab8b Deployed Jul 21, 2026 by railway-app[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: core 20+ merged PRs risk: low Changes to docs, tests, or low-risk modules scope: docs Documentation size: L 200-499 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant