Skip to content

feat: populate remote session result summary - #154

Merged
delete-cloud merged 2 commits into
mainfrom
feat/session-result-summary
May 14, 2026
Merged

delete-cloud merged 2 commits into
mainfrom
feat/session-result-summary

Conversation

@delete-cloud

@delete-cloud delete-cloud commented May 14, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • populate /sessions/{id}/result final_answer from the latest session tape turn
  • add conservative tool activity summaries for result verification context
  • persist and return recorded session turn failure details

Validation

  • uv run pytest tests/ui/test_http_server.py -q -k "session_result"
  • uv run pytest tests/ui/test_http_server.py tests/ui/test_session_manager_public_api.py tests/ui/test_session_persistence.py -q
  • uv run basedpyright --level error src/coding_agent/ui/http_server.py src/coding_agent/ui/session_manager.py src/coding_agent/ui/schemas.py tests/ui/test_http_server.py
  • uv run ruff format --check src/coding_agent/ui/http_server.py src/coding_agent/ui/session_manager.py tests/ui/test_http_server.py
  • git diff --check

Summary by CodeRabbit

Release Notes

  • New Features

    • Session result responses now include final answers, tool activity verification summaries, and detailed failure information for better visibility into session execution.
  • Tests

    • Added comprehensive test coverage for enhanced session result endpoint functionality.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 14, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@delete-cloud has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 53 minutes and 56 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1ba4f7e8-6869-46b0-9cff-8b40fc9838ab

📥 Commits

Reviewing files that changed from the base of the PR and between a9e7924 and 2cf9c4c.

📒 Files selected for processing (1)
  • coding-agent/tests/ui/test_http_server.py
📝 Walkthrough

Walkthrough

The PR enriches /sessions/{session_id}/result responses with tool activity summaries and failure details. Session tracks persistent failure information via a new last_failure_details field with serialization support. Exception handling in run_agent populates this field with error-specific messages. The HTTP endpoint uses tape helpers to extract verification summaries from recorded tool calls and failure details from the session state.

Changes

Session Result Enrichment with Failure Details and Tool Activity

Layer / File(s) Summary
Session Failure Tracking Contract
coding-agent/src/coding_agent/ui/session_manager.py
Session dataclass adds last_failure_details: str | None field; to_store_data() and from_store_data() serialize and validate the field during persistence cycles.
Session Failure Recording in run_agent
coding-agent/src/coding_agent/ui/session_manager.py
Exception handling in SessionManager.run_agent resets last_failure_details at turn start and populates it with error-specific messages ("Fatal tool execution failed: ..." or "HTTP session turn failed: ...") when failures occur.
Result Response Helpers and Configuration
coding-agent/src/coding_agent/ui/http_server.py
Imports tape extraction types (extract_turns, ToolCallRecord, TurnTrace, Tape); defines configuration constants for eligible tool-argument fields and summary size limits; implements helpers to compact argument text, extract per-tool details, build verification summaries with overflow counts, restore/extract tape snapshots, and compute failure-detail messages.
Result Endpoint Implementation
coding-agent/src/coding_agent/ui/http_server.py
get_session_result computes latest_turn via tape restoration and extraction helpers; populates SessionResultResponse fields (final_answer, verification_summary, failure_details) using helper outputs instead of None.
Result Response Contract Tests
coding-agent/tests/ui/test_http_server.py
Three new test cases under TestRemoteResultPublicationContract validate runtime tape-derived responses, persisted tape restoration when runtime is unloaded, and failure status/detail propagation for failed sessions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • delete-cloud/Coding-Agent-Loop#143: Modifies the same /sessions/{session_id}/result endpoint to populate response fields; the previous PR initiated the field changes and this PR completes enrichment with failure details and tape-derived summaries.

Poem

🐰 Hop through the tape, extract the tale,
Tool calls and failures, no detail's too pale,
Sessions now remember what went awry,
Rich result responses no more say goodbye! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 'feat: populate remote session result summary' directly matches the main changes: populating the /sessions/{id}/result endpoint with final_answer, verification_summary, and failure_details derived from session tape.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/session-result-summary

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 and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
coding-agent/tests/ui/test_http_server.py (1)

3518-3538: ⚡ Quick win

Add a contract test for failed turns without persisted failure details.

Current coverage validates explicit last_failure_details, but not the fallback message path when turn_status == "failed" and details are absent. Adding that case will lock down the new fallback behavior.

Suggested additional test
+    async def test_session_result_uses_default_failure_details_when_missing(
+        self, client: AsyncClient
+    ) -> None:
+        session = register_session(
+            "result-failed-default-details",
+            execution_binding=CloudWorkspaceBinding(
+                workspace_url="docker://agent-ws-result/workspace",
+                workspace_id="ws-failed-default-result",
+            ),
+        )
+        session.turn_status = "failed"
+        session.last_failure_details = None
+
+        response = await client.get(f"/sessions/{session.id}/result")
+
+        assert response.status_code == 200
+        data = response.json()
+        assert (
+            data["failure_details"]
+            == "Session turn failed; no failure details were recorded."
+        )
🤖 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 `@coding-agent/tests/ui/test_http_server.py` around lines 3518 - 3538, Add a
test case that covers the fallback message when a turn failed but no persisted
details exist: duplicate or extend
test_session_result_includes_recorded_failure_details to create a session via
register_session (with CloudWorkspaceBinding), set session.turn_status =
"failed" and set session.last_failure_details = None or "" (falsy), call GET
/sessions/{session.id}/result, assert status_code == 200, data["status"] ==
"failed" and data["turn_status"] == "failed", and assert data["failure_details"]
equals the expected fallback failure message produced by the result endpoint
(the fallback that the code returns when last_failure_details is absent).
🤖 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 `@coding-agent/src/coding_agent/ui/http_server.py`:
- Around line 1805-1812: The current _session_result_latest_turn can raise if
_session_result_tape, tape.snapshot() or extract_turns throws, causing
/sessions/{id}/result to 500; wrap the await _session_result_tape(session),
tape.snapshot() and extract_turns(...) calls in a try/except that catches
exceptions, logs a debug/error (including exception message) and returns None on
failure so the endpoint degrades gracefully and returns session metadata with
final_answer/verification_summary as None; modify _session_result_latest_turn to
handle these failures (and consider using _session_result_tape and extract_turns
names to locate the calls).

---

Nitpick comments:
In `@coding-agent/tests/ui/test_http_server.py`:
- Around line 3518-3538: Add a test case that covers the fallback message when a
turn failed but no persisted details exist: duplicate or extend
test_session_result_includes_recorded_failure_details to create a session via
register_session (with CloudWorkspaceBinding), set session.turn_status =
"failed" and set session.last_failure_details = None or "" (falsy), call GET
/sessions/{session.id}/result, assert status_code == 200, data["status"] ==
"failed" and data["turn_status"] == "failed", and assert data["failure_details"]
equals the expected fallback failure message produced by the result endpoint
(the fallback that the code returns when last_failure_details is absent).
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ff3734d8-d067-4bda-91f0-06c0250fbefd

📥 Commits

Reviewing files that changed from the base of the PR and between 3555b90 and a9e7924.

📒 Files selected for processing (3)
  • coding-agent/src/coding_agent/ui/http_server.py
  • coding-agent/src/coding_agent/ui/session_manager.py
  • coding-agent/tests/ui/test_http_server.py

Comment on lines +1805 to +1812
async def _session_result_latest_turn(session: Session) -> TurnTrace | None:
tape = await _session_result_tape(session)
if tape is None:
return None
turns = extract_turns(tape.snapshot())
if not turns:
return None
return turns[-1]

@coderabbitai coderabbitai Bot May 14, 2026 •

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Harden /result against tape read/parse failures.

On Line 1806 and Line 1809, an exception from tape restore/snapshot extraction will currently bubble up and turn /sessions/{id}/result into a 500. This endpoint should degrade gracefully and still return session metadata with final_answer/verification_summary as None.

Proposed fix
 async def _session_result_latest_turn(session: Session) -> TurnTrace | None:
-    tape = await _session_result_tape(session)
+    try:
+        tape = await _session_result_tape(session)
+    except Exception:
+        logger.exception(
+            "Failed to load tape for session result session_id=%s",
+            session.id,
+        )
+        return None
     if tape is None:
         return None
-    turns = extract_turns(tape.snapshot())
+    try:
+        turns = extract_turns(tape.snapshot())
+    except Exception:
+        logger.exception(
+            "Failed to extract turns for session result session_id=%s",
+            session.id,
+        )
+        return None
     if not turns:
         return None
     return turns[-1]
🤖 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 `@coding-agent/src/coding_agent/ui/http_server.py` around lines 1805 - 1812,
The current _session_result_latest_turn can raise if _session_result_tape,
tape.snapshot() or extract_turns throws, causing /sessions/{id}/result to 500;
wrap the await _session_result_tape(session), tape.snapshot() and
extract_turns(...) calls in a try/except that catches exceptions, logs a
debug/error (including exception message) and returns None on failure so the
endpoint degrades gracefully and returns session metadata with
final_answer/verification_summary as None; modify _session_result_latest_turn to
handle these failures (and consider using _session_result_tape and extract_turns
names to locate the calls).

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Skipped this change after checking the endpoint contract. Tape read/parse failure means the auditable result source is unavailable or corrupt; returning metadata with null result fields would hide that failure. The endpoint should fail visibly until we add a dedicated result_extraction_error field or equivalent explicit partial-result contract.

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.

@delete-cloud, that's a solid rationale — surfacing a 500 is more honest than silently returning null fields when the authoritative result source is unavailable or corrupt. Understood, skipping this change.

Would you like me to open a follow-up GitHub issue to track adding a result_extraction_error field (or an equivalent explicit partial-result contract) to SessionResultResponse? That would make it easier to revisit graceful degradation once the contract is properly defined.

(◕‿◕✿) 🐇


✏️ Learnings added
Learnt from: delete-cloud
Repo: delete-cloud/Coding-Agent-Loop PR: 154
File: coding-agent/src/coding_agent/ui/http_server.py:1805-1812
Timestamp: 2026-05-14T06:43:40.163Z
Learning: In `coding-agent/src/coding_agent/ui/http_server.py`, the `/sessions/{id}/result` endpoint (`get_session_result`) intentionally lets tape read/parse errors propagate as 500s rather than degrading gracefully with null `final_answer`/`verification_summary` fields. The design decision is that a tape failure means the auditable result source is unavailable or corrupt, and silent null fields would hide that failure. Graceful degradation should only be added when a dedicated `result_extraction_error` field or an explicit partial-result contract is introduced in `SessionResultResponse`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@delete-cloud
delete-cloud merged commit dd260e4 into main May 14, 2026
1 check passed
@delete-cloud
delete-cloud deleted the feat/session-result-summary branch May 14, 2026 06:44
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.

1 participant