Inbox + sessions: replay by export ID, stacked report logs, cloud workspace bootstrap#2011
Inbox + sessions: replay by export ID, stacked report logs, cloud workspace bootstrap#2011
Conversation
…bootstrap - Signal session_problem replay loads export by ID only (no list fallback) - Per-relationship TaskLogs panels in inbox report detail - Cloud workspace bootstrap in TaskLogsPanel for cloud runs - useSessionViewState isCloud aligns with workspace row + latest_run env
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
apps/code/src/renderer/features/task-detail/components/TaskLogsPanel.tsx:130-134
**Cache invalidation skipped on early unmount**
If the component unmounts while `workspaceApi.create` is still in flight, the cleanup sets `cancelled = true`, the creation still succeeds on the server, but `queryClient.invalidateQueries` is never called. On the next mount, `persistedWorkspace` is still `null` (the query's `staleTime` is 60 s so it won't re-fetch), the effect fires again, and a second create is attempted.
`invalidateQueries` updates the shared cache — it is safe to call even after the component that triggered it has unmounted. The guard should be removed:
```ts
} catch (error) {
bootstrapCloudLog.warn("Cloud workspace bootstrap failed", { taskId, error });
}
// Always invalidate — cache updates are safe after unmount and prevent
// a stale null workspace from causing a duplicate-create on next mount.
void queryClient.invalidateQueries(
trpcReact.workspace.getAll.pathFilter(),
);
})();
```
### Issue 2 of 2
apps/code/src/renderer/features/task-detail/components/TaskLogsPanel.tsx:107-113
**No in-flight guard for concurrent bootstrap calls**
The effect fires whenever any of its dependencies change (e.g., `isSuspended` toggling). If a dependency change triggers the cleanup and immediately re-fires the effect while the previous `workspaceApi.create` call is still awaiting a response, two creates are in flight simultaneously — `persistedWorkspace` is still `null` for both, so neither guard catches the other.
Bypassing the `useMutation` path also means `isCreatingWorkspace` doesn't reflect the bootstrap's pending state. Consider a `useRef` in-flight flag or using the existing mutation hook to serialise concurrent bootstrap attempts.
Reviews (1): Last reviewed commit: "feat(inbox): Session video via exported_..." | Re-trigger Greptile |
| if (!cancelled) { | ||
| void queryClient.invalidateQueries( | ||
| trpcReact.workspace.getAll.pathFilter(), | ||
| ); | ||
| } |
There was a problem hiding this comment.
Cache invalidation skipped on early unmount
If the component unmounts while workspaceApi.create is still in flight, the cleanup sets cancelled = true, the creation still succeeds on the server, but queryClient.invalidateQueries is never called. On the next mount, persistedWorkspace is still null (the query's staleTime is 60 s so it won't re-fetch), the effect fires again, and a second create is attempted.
invalidateQueries updates the shared cache — it is safe to call even after the component that triggered it has unmounted. The guard should be removed:
} catch (error) {
bootstrapCloudLog.warn("Cloud workspace bootstrap failed", { taskId, error });
}
// Always invalidate — cache updates are safe after unmount and prevent
// a stale null workspace from causing a duplicate-create on next mount.
void queryClient.invalidateQueries(
trpcReact.workspace.getAll.pathFilter(),
);
})();Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/task-detail/components/TaskLogsPanel.tsx
Line: 130-134
Comment:
**Cache invalidation skipped on early unmount**
If the component unmounts while `workspaceApi.create` is still in flight, the cleanup sets `cancelled = true`, the creation still succeeds on the server, but `queryClient.invalidateQueries` is never called. On the next mount, `persistedWorkspace` is still `null` (the query's `staleTime` is 60 s so it won't re-fetch), the effect fires again, and a second create is attempted.
`invalidateQueries` updates the shared cache — it is safe to call even after the component that triggered it has unmounted. The guard should be removed:
```ts
} catch (error) {
bootstrapCloudLog.warn("Cloud workspace bootstrap failed", { taskId, error });
}
// Always invalidate — cache updates are safe after unmount and prevent
// a stale null workspace from causing a duplicate-create on next mount.
void queryClient.invalidateQueries(
trpcReact.workspace.getAll.pathFilter(),
);
})();
```
How can I resolve this? If you propose a fix, please make it concise.| useEffect(() => { | ||
| if (!isWorkspaceLoaded) return; | ||
| if (persistedWorkspace) return; | ||
| if (task.latest_run?.environment !== "cloud") return; | ||
| if (isSuspended) return; | ||
| if (isProvisioning) return; | ||
|
|
There was a problem hiding this comment.
No in-flight guard for concurrent bootstrap calls
The effect fires whenever any of its dependencies change (e.g., isSuspended toggling). If a dependency change triggers the cleanup and immediately re-fires the effect while the previous workspaceApi.create call is still awaiting a response, two creates are in flight simultaneously — persistedWorkspace is still null for both, so neither guard catches the other.
Bypassing the useMutation path also means isCreatingWorkspace doesn't reflect the bootstrap's pending state. Consider a useRef in-flight flag or using the existing mutation hook to serialise concurrent bootstrap attempts.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/task-detail/components/TaskLogsPanel.tsx
Line: 107-113
Comment:
**No in-flight guard for concurrent bootstrap calls**
The effect fires whenever any of its dependencies change (e.g., `isSuspended` toggling). If a dependency change triggers the cleanup and immediately re-fires the effect while the previous `workspaceApi.create` call is still awaiting a response, two creates are in flight simultaneously — `persistedWorkspace` is still `null` for both, so neither guard catches the other.
Bypassing the `useMutation` path also means `isCreatingWorkspace` doesn't reflect the bootstrap's pending state. Consider a `useRef` in-flight flag or using the existing mutation hook to serialise concurrent bootstrap attempts.
How can I resolve this? If you propose a fix, please make it concise.
Summary
PostHog Code (this PR)
Session-problem rasterized replay in the inbox trusts
exported_asset_idon the signal and loads export content directly—no extras client-side lookups.In signal report detail, stacked report/remediation rows each mount their logs panel under that row, with layout fixes so the docked pane scrolls cleanly.
Opening cloud-backed task logs can bootstrap a minimal cloud workspace row when the workspace catalog exists but none is persisted yet. Session view routing treats a task as cloud when a workspace row exists with
mode: cloud, otherwise falls back onlatest_run.environment === "cloud".Depends on companion: PostHog/posthog #57541 — export retrieve/content allowed for teammates in the project (RBAC on linked resources unchanged; listings stay per-user).