feat(canvas): show generation task nested under canvas in sidebar#2847
feat(canvas): show generation task nested under canvas in sidebar#2847raquelmsmith wants to merge 8 commits into
Conversation
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
Reviews (1): Last reviewed commit: "fix(canvas): keep nested task put while ..." | Re-trigger Greptile |
| // Tasks are private to their creator; one that isn't in our list can't be | ||
| // shown (or deduped) — leave it out. | ||
| if (!task) continue; | ||
| const data = deriveTaskData(narrowFullTask(task as unknown as FullTask), { |
There was a problem hiding this comment.
Task cast to FullTask bypasses type safety
task as unknown as FullTask sidesteps the compiler. If FullTask later gains a required field that Task doesn't carry, this will silently pass compilation and blow up at runtime inside narrowFullTask. The two types are currently structurally compatible (both have id, title, created_at, updated_at, origin_product, repository, latest_run), but a narrower overload of narrowFullTask — or a dedicated helper that accepts Task directly — would eliminate the escape hatch entirely.
| ); | ||
|
|
||
| // A short status word under the title (running / merged / …), mirroring the | ||
| // task's live state. Falls back to the run status when there's no PR yet. | ||
| // task's live state. Repo-less local tasks (e.g. canvas generation) have no | ||
| // backend run record, so `taskRunStatus` is undefined once the turn ends — | ||
| // fall back to the live session so the row still shows a status line. | ||
| const status = | ||
| taskData?.isGenerating === true | ||
| ? "running" |
There was a problem hiding this comment.
"connecting" session state mapped to "completed" status
When a local canvas-generation task's session is in the "connecting" state (the ACP handshake is in flight) but isPromptPending hasn't been set yet, taskData.isGenerating will be false. The fallback chain then reaches the session branch and maps any non-"error" status — including "connecting" — to "completed", briefly showing a wrong status. A guard that treats "connecting" as "running" (or just skips the session fallback until the session reaches a terminal state) would prevent the flash.
| </ContextMenuContent> | ||
| </ContextMenu> | ||
|
|
||
| {generationTask && dashboard.generationTaskId ? ( | ||
| <CanvasGenerationTaskRow | ||
| channelId={channelId} | ||
| taskId={dashboard.generationTaskId} | ||
| task={generationTask} | ||
| channelTaskId={generationChannelTaskId} | ||
| channels={channels} | ||
| /> |
There was a problem hiding this comment.
Redundant
dashboard.generationTaskId guard
generationTask is only ever non-undefined when showGen is true, which already requires genTaskId (i.e. dashboard.generationTaskId) to be truthy. Checking dashboard.generationTaskId again in the render condition is always vacuously true at that point — it can be dropped to say the same thing once.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
When a canvas has a generation task, render that task beneath the canvas name in the channels sidebar: indented under the canvas with a down-then-right elbow arrow, in a smaller font, showing only the task icon and title (no draft/merged/queued status subtitle). Clicking it opens the task. Surfaces `generationTaskId` on the dashboard summary so the sidebar list can render the run without a per-canvas get(). Generated-By: PostHog Code Task-Id: 5345f523-bc53-4fa8-a3e8-f654aadc5015
Show the generation task nested under its canvas only while the run is still active; once it reaches a terminal state the row disappears. Also dedupe: while a generation task is shown nested under its canvas, it no longer appears in the channel's flat task list below. Generated-By: PostHog Code Task-Id: 5345f523-bc53-4fa8-a3e8-f654aadc5015
…ask actions Rework when a canvas's generation task shows nested under the canvas: - Show it while generating AND afterwards until the user has seen the result (unread), instead of only while the run is non-terminal. Canvas generation runs locally, so a stopped run never reaches a terminal latest_run.status — the old record-only check kept stopped tasks pinned. Keying off the session's isGenerating + unread fixes that: a stopped, viewed task now drops out, while a finished-but-unseen task stays put until opened. - Decide nesting once, in bulk, via useNestedGenerationTaskIds (one sessions + timestamps read) so the nested row and the flat-list dedupe share a single source of truth and can't diverge. - Give the nested row the same right-click menu as a regular filed task (File to… / Archive / Remove from channel) by extracting the shared TaskRowContextMenu used by both rows. Generated-By: PostHog Code Task-Id: 5345f523-bc53-4fa8-a3e8-f654aadc5015
…otice when done Two fixes to canvas generation status: - Nested sidebar row: stay until the user has actually seen the task, not just until it finishes. A never-viewed task counts as unseen, so a just-finished generation stays nested instead of vanishing the instant it completes; opening it (now also marks channel tasks viewed, which the website space wasn't doing) drops it back into the regular list, and a follow-up re-nests it while it regenerates. - Canvas "Generating… View task" notice: a local ACP session stays "connected" after its single generation prompt finishes, so the notice (and disabled composer/undo) never cleared. Key the generating UI off the pending prompt instead, while still polling the record on the broader session-alive signal so a just-published canvas appears. Generated-By: PostHog Code Task-Id: 5345f523-bc53-4fa8-a3e8-f654aadc5015
Repo-less local tasks (canvas generation) have no backend run record, so `taskRunStatus` is undefined once the turn ends and the channel TaskRow rendered only the title. Fall back to the live session status — "failed" on error, otherwise "completed" — so the moved-down row shows the same two-line treatment (title + status) as other filed tasks. Generated-By: PostHog Code Task-Id: 5345f523-bc53-4fa8-a3e8-f654aadc5015
Opening a generation task from under its canvas marked it viewed, which dropped it into the channel's regular list immediately — so it visibly jumped while the user was still on its task view. Keep the currently-open task nested regardless of viewed state; it moves into the flat list once the user navigates away. Generated-By: PostHog Code Task-Id: 5345f523-bc53-4fa8-a3e8-f654aadc5015
Viewed/unread state is stored per-device on the task's `workspaces` row, but repo-less channel tasks (e.g. canvas generation) deliberately have no such row — their working dir is a scratch dir. So `markViewed` updated zero rows and the view was forgotten on reload, leaving a viewed generation task pinned under its canvas forever. Add a dedicated `task_metadata` table keyed by task id as the fallback home for pin/view/activity timestamps. The metadata service routes by presence: tasks that own a workspace row keep their exact current behavior; rowless tasks read and write this table instead. Projections union both sources. Generated-By: PostHog Code Task-Id: 5345f523-bc53-4fa8-a3e8-f654aadc5015
Review feedback:
- Drop the `as unknown as FullTask` escape hatch: `narrowFullTask` now
accepts the canonical `Task` directly, so the canvas hooks narrow without
casting.
- Treat a session still mid-handshake ("connecting") as "running" in the
task-row status line instead of flashing "completed".
- Remove the vacuously-true `dashboard.generationTaskId` guard on the nested
row; use `generationTask.id`.
Cleanup:
- Extract a shared `TaskStatusIcon` so `TaskRow` and
`CanvasGenerationTaskRow` build the status icon from one definition.
Flaky test:
- `event-stream-sender` "stops retrying after the stop deadline" used
`stopTimeoutMs: 1`, racing the 5ms retry wait against timer granularity and
occasionally sending a second request under CI load. Use `stopTimeoutMs: 0`
so the deadline is hit deterministically after the first attempt.
Also Biome-format the generated migration snapshot/journal.
Generated-By: PostHog Code
Task-Id: caabd110-f966-47da-9912-171a5a1cb6e6
0e9db59 to
671d4e3
Compare
Problem
When a canvas has a generation task associated with it, there was no way to see that task from the channels sidebar. This surfaces the run inline so you can jump straight to it.
Why: Raquel wants the generating task visible right under its canvas for quick access.
Changes
generationTaskIdon the dashboard summary so the sidebar can render the run without a per-canvasget().How did you test this?
Not yet manually tested — opening as draft for you to pull down and verify in the running app.
Automatic notifications
Created with PostHog Code