Skip to content

feat(web): let users scan and analyze their own session failures - #6800

Open
maphew wants to merge 19 commits into
Kilo-Org:mainfrom
maphew:feat/session-failure-history
Open

maphew wants to merge 19 commits into
Kilo-Org:mainfrom
maphew:feat/session-failure-history

Conversation

@maphew

@maphew maphew commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes #6167 (the unresolved part: users have no way to scan and analyze their own threads).

Today a failed Cloud Agent session shows one safe error line. The user cannot see which runs failed, when, or why, and support intake depends on the user manually collecting session IDs. This PR gives the calling user read access to their own failure records and a support-ticket export.

What changes

  • New cloudAgentNextFailures tRPC router (apps/web/src/routers/cloud-agent-next-failures-router.ts), mounted at the root router:
    • getSessionFailureHistory: per-session history with session identifiers, the setup failure (stage, code, responsibility, reason, safe diagnostic), and run attempts (status, timestamps, failure fields, wrapperRunId). The list is capped at the latest 50 runs; the cap is part of the output.
    • exportSessionDiagnostics: the same data as a JSON document or CSV, with cloud_agent_session_id, kilo_session_id, and timestamps so users can paste identifiers into tickets. Expired diagnostics (error_expires_at) are withheld, matching the admin router rule. CSV cells that start with a formula character are guarded against spreadsheet formula injection.
  • Session Info dialog: a failure-history section (failure list with dates, safe diagnostics, counts) plus Download diagnostics and Download CSV actions. Hidden when the session has no failures. Covers both legacy agent_ and control-plane workspace_ session ids, so worktree chats are included.
  • Shared taxonomy: user-visible failure message maps move from the cloud-agent-next projection into @kilocode/worker-utils/cloud-agent-failure so the web router reuses one source of truth; projection strings are unchanged (177 service unit tests pass). The setup-failure stage/code unions now share one type.

Access rule

A caller can read failure data for a session only when they own the cli_sessions_v2 row (by kilo_user_id), and for organization rows only while they are still a current member of that live (not deleted) organization, enforced by queryAccessibleCloudAgentSession. Because cloud_agent_session_id is unique across cli_sessions_v2, one session has exactly one owning row. Tests cover both denial directions.

Scope decisions

STE note

User-facing copy, commit messages, and this PR use Simplified Technical English: short sentences, active voice, one term per concept.

Verification

  • tsc --noEmit: @kilocode/worker-utils, services/cloud-agent-next pass.
  • tsgo --noEmit: apps/web passes.
  • oxlint + oxfmt on changed files: clean.
  • services/cloud-agent-next unit tests for the projection: 177 pass.
  • Added: DB-backed jest tests for the new router (cloud-agent-next-failures-router.test.ts: scoping in both directions, timestamp normalization from raw Postgres text, diagnostic expiry, JSON/CSV export, CSV formula guard, wrapperRunId) and a pure unit test for the UI summary helper. The jest suites need the test Postgres and could not run in the authoring sandbox (no database); they run in CI.

Review

An adversarial review pass found fixture and copy defects (blocker: fixture violated the unique index on cloud_agent_session_id; blocker: two wrong test expectations; major: workspace_ sessions invisible in the panel; major: CSV formula injection; minor: wrapper_run_id missing, run-cap labeling). All are fixed in 0a1c98b.

Follow-ups (not in this PR)

  • Cross-session failure overview and per-day trend in the session list.
  • Link the failure panel to the feedback dialog so a ticket can attach the export in one step.

@maphew
maphew marked this pull request as ready for review September 28, 2026 18:36
@kilo-code-bot

kilo-code-bot Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The latest commit 01dfbb3f2 fixes both prior findings: the failure-history error panel now renders when the query fails with no cached history, and the diagnostics download releases the object URL and anchor in finally on every path, so no blob URL or detached anchor can leak. No new issues were found in the changed lines.

Files Reviewed (3 files)
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx - clean (both prior findings resolved)
  • apps/web/src/components/cloud-agent-next/SessionInfoDialog.tsx - context check only, unchanged since the merge of main
  • apps/web/src/routers/root-router.ts - context check only, unchanged since the merge of main

The other seven PR files are unchanged since the previous review and were verified current, not re-analyzed.

Previous Review Summaries (7 snapshots, latest commit 140304a)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 140304a)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

The current PR head has regressed two previously-fixed behaviors in SessionFailureHistory.tsx: the failure-history error panel is unreachable again because the !history guard returns before the isError branch, and the diagnostics-download blob URL and anchor cleanup still run only on success, so a throw leaks the object URL.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx 41 Error panel unreachable. history is historyQuery.data, and `if (!enabled

SUGGESTION

File Line Issue
apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx 86 Object URL and anchor are cleaned up only inside the try block (anchor.remove(), URL.revokeObjectURL(url)). If document.body.appendChild(anchor) or anchor.click() throws, the catch skips both, leaking the object URL and leaving a detached <a> on document.body; finally only resets isDownloading. An active review thread on this line already covers it, so no duplicate inline comment was posted.
Files Reviewed (10 files)
  • apps/web/src/components/cloud-agent-next/ChatHeader.test.ts
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx - 2 issues (regressed)
  • apps/web/src/components/cloud-agent-next/SessionInfoDialog.tsx
  • apps/web/src/components/cloud-agent-next/session-failure-summary.test.ts
  • apps/web/src/components/cloud-agent-next/session-failure-summary.ts
  • apps/web/src/routers/cloud-agent-next-failures-router.test.ts
  • apps/web/src/routers/cloud-agent-next-failures-router.ts
  • apps/web/src/routers/root-router.ts
  • packages/worker-utils/src/cloud-agent-failure.ts
  • services/cloud-agent-next/src/session/safe-failure-projection.ts

Fix these issues in Kilo Cloud

Previous review (commit 8e6e504)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

The current PR head has regressed two previously-fixed behaviors in SessionFailureHistory.tsx: the failure-history error panel is unreachable again because the !history guard returns before the isError branch, and the diagnostics-download blob URL/anchor cleanup still runs only on success, so a throw leaks the object URL.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx 41 Error panel unreachable. history is historyQuery.data, and if (!enabled || !history) { return null; } runs before if (historyQuery.isError) {...}. On a failed query with no cached data data is undefined, so the component returns null and the error state is dead code. The intended order (check isError when history is missing) and the SessionFailureHistory.test.ts referenced by the fix reply are not present in this branch.

SUGGESTION

File Line Issue
apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx 86 Object URL and anchor are cleaned up only inside try (anchor.remove(), URL.revokeObjectURL(url)). If document.body.appendChild(anchor) or anchor.click() throws, the catch skips both, leaking the object URL and leaving a detached <a> on document.body; the finally block only resets isDownloading. Move the cleanup into finally.
Files Reviewed (10 files)
  • apps/web/src/components/cloud-agent-next/ChatHeader.test.ts
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx - 2 issues
  • apps/web/src/components/cloud-agent-next/SessionInfoDialog.tsx
  • apps/web/src/components/cloud-agent-next/session-failure-summary.test.ts
  • apps/web/src/components/cloud-agent-next/session-failure-summary.ts
  • apps/web/src/routers/cloud-agent-next-failures-router.test.ts
  • apps/web/src/routers/cloud-agent-next-failures-router.ts
  • apps/web/src/routers/root-router.ts
  • packages/worker-utils/src/cloud-agent-failure.ts
  • services/cloud-agent-next/src/session/safe-failure-projection.ts

The latest commit (9f4c956) only realigns shared import paths, adds the required role to the org-membership fixture, and restores admission_billing_unavailable / container_limit_reached to the shared message map; those changes are correct.

Fix these issues in Kilo Cloud

Previous review (commit 5b8063b)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx 104 Blob URL revocation and anchor removal run only inside try, so an exception during download skips both: the object URL is never revoked and a detached <a> stays in the DOM
Files Reviewed (11 files)
  • apps/web/src/components/cloud-agent-next/ChatHeader.test.ts
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.test.ts
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx - 1 issue
  • apps/web/src/components/cloud-agent-next/SessionInfoDialog.tsx
  • apps/web/src/components/cloud-agent-next/session-failure-summary.test.ts
  • apps/web/src/components/cloud-agent-next/session-failure-summary.ts
  • apps/web/src/routers/cloud-agent-next-failures-router.test.ts
  • apps/web/src/routers/cloud-agent-next-failures-router.ts
  • apps/web/src/routers/root-router.ts
  • packages/worker-utils/src/cloud-agent-failure.ts
  • services/cloud-agent-next/src/session/safe-failure-projection.ts

Fix these issues in Kilo Cloud

Previous review (commit 6fe4ac6)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The new failure-history router, dialog panel, and shared taxonomy are correct and access-scoped; the only finding is a conditional blob-URL/anchor cleanup leak in the download handler.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx 104 Object URL revocation and anchor removal run only inside try, so an exception during download skips cleanup
Files Reviewed (11 files)
  • apps/web/src/components/cloud-agent-next/ChatHeader.test.ts
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.test.ts
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx - 1 issue
  • apps/web/src/components/cloud-agent-next/SessionInfoDialog.tsx
  • apps/web/src/components/cloud-agent-next/session-failure-summary.test.ts
  • apps/web/src/components/cloud-agent-next/session-failure-summary.ts
  • apps/web/src/routers/cloud-agent-next-failures-router.test.ts
  • apps/web/src/routers/cloud-agent-next-failures-router.ts
  • apps/web/src/routers/root-router.ts
  • packages/worker-utils/src/cloud-agent-failure.ts
  • services/cloud-agent-next/src/session/safe-failure-projection.ts

Fix these issues in Kilo Cloud

Previous review (commit 972b045)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The follow-up commit 972b0454 fixes both prior findings: the failure-history error panel is now reachable with an in-dialog retry, and the org-membership test fixture supplies the required role. The new static-markup tests cover both error paths, and no new issues were found in the changed lines.

Files Reviewed (3 changed files)
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx - clean (prior unreachable-panel finding resolved)
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.test.ts - clean
  • apps/web/src/routers/cloud-agent-next-failures-router.test.ts - clean (prior missing-role finding resolved)

The other seven PR files are unchanged since the prior review and were not re-analyzed.

Previous review (commit 138d911)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

The commit that was meant to fix the two prior findings does not: the new failure-history error panel is unreachable because the !history guard returns first, and the org-membership test insert omits the required role column so it cannot type-check or run.

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx 41 Error branch unreachable: the `!enabled
apps/web/src/routers/cloud-agent-next-failures-router.test.ts 135 organization_memberships insert omits the required NOT NULL role column; it fails the Drizzle insert type and raises a not-null violation at setup.
Files Reviewed (2 changed files)
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx - 1 issue
  • apps/web/src/routers/cloud-agent-next-failures-router.test.ts - 1 issue

The other eight files from the prior review are unchanged since f135bcd and were not re-analyzed.

Fix these issues in Kilo Cloud

Previous review (commit f135bcd)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

Authorization and runtime behavior look correct; the notable gaps are a test that does not actually exercise the organization-membership denial it claims to cover, and a transient-error path that silently hides the failure panel.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 2
Issue Details (click to expand)

SUGGESTION

File Line Issue
apps/web/src/routers/cloud-agent-next-failures-router.test.ts 197 Org-membership denial path not exercised: no organization_memberships row is created, so the denial is over-determined by ownership.
apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx 36 retry: false plus the isError early return silently hides the whole panel on a single transient fetch error.
Files Reviewed (10 files)
  • apps/web/src/routers/cloud-agent-next-failures-router.ts - clean (access is owner-scoped via queryAccessibleCloudAgentSession; zod input/output matches DB types and the run-status check; timestamps normalized to ISO; CSV has 20 aligned columns and a formula guard)
  • apps/web/src/routers/cloud-agent-next-failures-router.test.ts - 1 issue
  • apps/web/src/components/cloud-agent-next/SessionFailureHistory.tsx - 1 issue (no memory leak: object URL is revoked and the anchor removed)
  • apps/web/src/components/cloud-agent-next/session-failure-summary.ts - clean
  • apps/web/src/components/cloud-agent-next/session-failure-summary.test.ts - clean
  • apps/web/src/components/cloud-agent-next/SessionInfoDialog.tsx - clean
  • apps/web/src/components/cloud-agent-next/ChatHeader.test.ts - clean
  • apps/web/src/routers/root-router.ts - clean
  • packages/worker-utils/src/cloud-agent-failure.ts - clean (moved maps are byte-identical; satisfies key parity holds)
  • services/cloud-agent-next/src/session/safe-failure-projection.ts - clean (behavior-preserving delegation; subpath export resolves)

Fix these issues in Kilo Cloud


Reviewed by deepseek-flash-latest · Input: 55.2K · Output: 6.2K · Cached: 553.2K

Review guidance: REVIEW.md from base branch main

@maphew
maphew force-pushed the feat/session-failure-history branch from f135bcd to 138d911 Compare September 28, 2026 19:48
@maphew
maphew force-pushed the feat/session-failure-history branch 2 times, most recently from 5b8063b to 8e6e504 Compare October 4, 2026 20:59
@maphew
maphew force-pushed the feat/session-failure-history branch from 90a5d82 to 9f4c956 Compare October 13, 2026 21:00
maphew and others added 6 commits October 13, 2026 14:56
Users only see a one-line safe error for failed Cloud Agent sessions and
cannot inspect which runs failed, when, or why (Kilo-Org#6167).

- Add shared user-visible failure message maps to the worker-utils
  failure taxonomy; the cloud-agent-next projection now reuses them
- Add a cloudAgentNextFailures tRPC router scoped to the calling user:
  per-session failure history (run attempts, codes, timestamps) and a
  JSON/CSV diagnostics export for support tickets
- Show a failure history section with a diagnostics download in the
  Session Info dialog; expired diagnostics are hidden

Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
- Fix the router test fixture: one cli_sessions_v2 row per cloud agent
  session id, since the table has a unique index on that column
- Fix the summary test expectation and the CSV row count
- Accept legacy agent_ and control-plane workspace_ session ids in the
  failure panel gate, so worktree chats are covered
- Escape leading formula characters in the CSV export
- Select and emit wrapper_run_id in the history and the CSV export
- Report the history run limit and label the retention window from
  session creation; rename the download loading copy
@maphew
maphew force-pushed the feat/session-failure-history branch from 9f4c956 to 140304a Compare October 13, 2026 21:56

@maphew maphew left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed both findings: the error panel is evaluated when the query has no cached history, and the diagnostics download now removes the anchor and revokes the object URL in finally so a throw cannot leak either.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant