Skip to content

distinguish the timeout failure which should mark the is_session_completed true - #55

Merged
BinHuangPJLAB merged 1 commit into
AI45Lab:v2from
BinHuangPJLAB:rewardfix
Aug 11, 2026
Merged

distinguish the timeout failure which should mark the is_session_completed true#55
BinHuangPJLAB merged 1 commit into
AI45Lab:v2from
BinHuangPJLAB:rewardfix

Conversation

@BinHuangPJLAB

@BinHuangPJLAB BinHuangPJLAB commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Sessions can now be closed as either complete or aborted.
    • Session closure responses and records reflect the selected completion status.
    • Invalid completion modes are rejected with a clear error.
  • Bug Fixes

    • Aborted sessions no longer retain completion rewards or reusable leases.
    • Session progress and reward totals reset when completion is reverted.
    • Timeout reporting now identifies the relevant waiting stage.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Session completion modes

Layer / File(s) Summary
Completion state storage
core/data_manager/manager.py, core/data_manager/strategy/*
Data manager and storage strategies accept explicit completion states. Incomplete sessions reset terminal state and rewards.
Gateway close propagation
evaluator/gateway_client.py, gateway/app.py, gateway/telemetry.py, gateway/storage.py
Gateway requests validate and return complete or abort. Telemetry and storage receive the selected completion state.
Rollout mode finalization
manager/simulation_worker.py, manager/rjob_episode_runner.py
Rollout results determine the gateway completion mode. Aborted rollouts clear rewards and disable lease reuse. Timeout results include timeout_layer.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SimulationWorker
  participant GatewayClient
  participant GatewayApp
  participant GatewayTelemetry
  participant GatewayStorage
  participant StorageStrategy

  SimulationWorker->>SimulationWorker: classify rollout result
  SimulationWorker->>GatewayClient: close session with completion_mode
  GatewayClient->>GatewayApp: send close request
  GatewayApp->>GatewayTelemetry: enqueue completion status
  GatewayApp->>GatewayStorage: record session close
  GatewayStorage->>StorageStrategy: update latest session completion state
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title identifies the timeout handling and session completion state, which are central aspects of the changes.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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: 2

🤖 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 `@core/data_manager/strategy/sqlite_strategy_impl.py`:
- Around line 537-544: Update the incomplete-session branch in the session
completion flow around the latest-row update so that when completed is false,
rewards and step rewards are cleared for every trajectory row belonging to the
same session and model, not only latest.id. Preserve the existing latest-row
completion and terminal flags, and ensure fetch_done_steps_with_context cannot
return earlier trainable rows from an aborted session.

In `@manager/simulation_worker.py`:
- Around line 499-514: Update _gateway_completion_mode to evaluate recognized
timeout_layer values before checking metrics["rjob_status"], so
rjob_wait_terminal and the other timeout layers return "complete" even when
rjob_status is "Stopped", "Failed", or "Killed". Preserve the existing
truncated, succeeded, and abort behavior for results without a recognized
timeout layer.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7347847d-79b9-4e0d-9b0e-a9769851aff4

📥 Commits

Reviewing files that changed from the base of the PR and between c67df46 and 0562d45.

📒 Files selected for processing (10)
  • core/data_manager/manager.py
  • core/data_manager/strategy/base_strategy.py
  • core/data_manager/strategy/cloud_strategy_impl.py
  • core/data_manager/strategy/sqlite_strategy_impl.py
  • evaluator/gateway_client.py
  • gateway/app.py
  • gateway/storage.py
  • gateway/telemetry.py
  • manager/rjob_episode_runner.py
  • manager/simulation_worker.py

Comment on lines +537 to +544
updates: Dict[str, Any] = {
"is_session_completed": completed,
"is_terminal": completed,
}
if not completed:
updates.update(step_reward=0.0, reward=0.0)
with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id):
updated = await SessionStep.filter(id=latest.id).update(
is_session_completed=True,
is_terminal=True,
)
updated = await SessionStep.filter(id=latest.id).update(**updates)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Clear rewards for all aborted trajectory rows.

When an aborted session has more than one trainable row, this update clears rewards only on the latest row. fetch_done_steps_with_context still returns earlier trainable rows without checking completion state. Those rows can enter training with rewards from an aborted session.

Update all trajectory rows for the session and model when completed is false. Alternatively, exclude incomplete sessions in fetch_done_steps_with_context.

Proposed fix
-            with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id):
-                updated = await SessionStep.filter(id=latest.id).update(**updates)
+            target = SessionStep.filter(session_id=session_id)
+            if llm_model:
+                target = target.filter(llm_model=llm_model)
+            with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id):
+                updated = await target.update(**updates)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
updates: Dict[str, Any] = {
"is_session_completed": completed,
"is_terminal": completed,
}
if not completed:
updates.update(step_reward=0.0, reward=0.0)
with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id):
updated = await SessionStep.filter(id=latest.id).update(
is_session_completed=True,
is_terminal=True,
)
updated = await SessionStep.filter(id=latest.id).update(**updates)
updates: Dict[str, Any] = {
"is_session_completed": completed,
"is_terminal": completed,
}
if not completed:
updates.update(step_reward=0.0, reward=0.0)
target = SessionStep.filter(session_id=session_id)
if llm_model:
target = target.filter(llm_model=llm_model)
with trace.span("db_write.mark_session_completed", row_id=latest.id, step_id=latest.step_id):
updated = await target.update(**updates)
🤖 Prompt for 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.

In `@core/data_manager/strategy/sqlite_strategy_impl.py` around lines 537 - 544,
Update the incomplete-session branch in the session completion flow around the
latest-row update so that when completed is false, rewards and step rewards are
cleared for every trajectory row belonging to the same session and model, not
only latest.id. Preserve the existing latest-row completion and terminal flags,
and ensure fetch_done_steps_with_context cannot return earlier trainable rows
from an aborted session.

Comment on lines +499 to +514
@staticmethod
def _gateway_completion_mode(result: SimulationStartResult) -> str:
metrics = result.metrics if isinstance(result.metrics, dict) else {}
if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}:
return "abort"
if result.truncated:
return "complete"
if str(metrics.get("timeout_layer") or "") in {
"docker_exec",
"sandbox_command",
"rjob_wait_terminal",
}:
return "complete"
if result.status == "succeeded":
return "complete"
return "abort"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Prioritize timeout-layer classification.

If TimeoutError.last_status is "Stopped", RJobEpisodeRunner stores that value in metrics["rjob_status"]. This method then returns "abort" before it checks timeout_layer="rjob_wait_terminal". The gateway marks that timeout session incomplete and clears its reward.

Check recognized timeout layers before rjob_status.

Proposed fix
     def _gateway_completion_mode(result: SimulationStartResult) -> str:
         metrics = result.metrics if isinstance(result.metrics, dict) else {}
-        if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}:
-            return "abort"
         if result.truncated:
             return "complete"
         if str(metrics.get("timeout_layer") or "") in {
             "docker_exec",
             "sandbox_command",
             "rjob_wait_terminal",
         }:
             return "complete"
+        if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}:
+            return "abort"
         if result.status == "succeeded":
             return "complete"
         return "abort"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@staticmethod
def _gateway_completion_mode(result: SimulationStartResult) -> str:
metrics = result.metrics if isinstance(result.metrics, dict) else {}
if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}:
return "abort"
if result.truncated:
return "complete"
if str(metrics.get("timeout_layer") or "") in {
"docker_exec",
"sandbox_command",
"rjob_wait_terminal",
}:
return "complete"
if result.status == "succeeded":
return "complete"
return "abort"
`@staticmethod`
def _gateway_completion_mode(result: SimulationStartResult) -> str:
metrics = result.metrics if isinstance(result.metrics, dict) else {}
if result.truncated:
return "complete"
if str(metrics.get("timeout_layer") or "") in {
"docker_exec",
"sandbox_command",
"rjob_wait_terminal",
}:
return "complete"
if str(metrics.get("rjob_status") or "") in {"Failed", "Stopped", "Killed"}:
return "abort"
if result.status == "succeeded":
return "complete"
return "abort"
🤖 Prompt for 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.

In `@manager/simulation_worker.py` around lines 499 - 514, Update
_gateway_completion_mode to evaluate recognized timeout_layer values before
checking metrics["rjob_status"], so rjob_wait_terminal and the other timeout
layers return "complete" even when rjob_status is "Stopped", "Failed", or
"Killed". Preserve the existing truncated, succeeded, and abort behavior for
results without a recognized timeout layer.

@WangXuhongCN WangXuhongCN left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@BinHuangPJLAB
BinHuangPJLAB merged commit b85762e into AI45Lab:v2 Aug 11, 2026
1 check passed
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