Skip to content

feat(code): Inbox 2.0#2547

Open
Twixes wants to merge 41 commits into
mainfrom
inbox-v2-pr
Open

feat(code): Inbox 2.0#2547
Twixes wants to merge 41 commits into
mainfrom
inbox-v2-pr

Conversation

@Twixes

@Twixes Twixes commented Jun 9, 2026

Copy link
Copy Markdown
Member

Summary

Replaces the legacy Inbox list with the v2 Self-driving: Pull requests, Reports, Agents, plus scoped For you filtering.
Polished list/detail UI for PRs, reports, and agent runs, including repo/source metadata, reviewer affordances, and task-log-backed run details.
Promotes agent configuration into a first-class view.

Screenshot 2026-06-09 at 13 29 29@2x

Twixes and others added 2 commits June 8, 2026 14:39
Documents how agents navigate the Vite preview (?previewMode=true), capture screenshots via cursor-ide-browser, and extend mocks in index.html when fixtures are insufficient.
Co-authored-by: Michael Matloka <dev@twixes.com>
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

React Doctor found 21 issues in 13 files · 21 warnings.

21 warnings

src/renderer/features/inbox/components/AgentRunCard.tsx

src/renderer/features/inbox/components/AgentRunDetail.tsx

src/renderer/features/inbox/components/InboxDetailFrame.tsx

src/renderer/features/inbox/components/InboxMetaRow.tsx

src/renderer/features/inbox/components/PrDiffIndicator.tsx

src/renderer/features/inbox/components/PriorityMonogram.tsx

src/renderer/features/inbox/components/PullRequestDetail.tsx

src/renderer/features/inbox/components/SuggestedReviewersSection.tsx

src/renderer/features/sidebar/components/SidebarMenu.tsx

src/renderer/routes/code/inbox/agents.tsx

src/renderer/routes/code/inbox/pulls.$reportId.tsx

src/renderer/routes/code/inbox/reports.$reportId.tsx

src/renderer/routes/code/inbox/runs.$reportId.tsx

Reviewed by React Doctor for commit 2d7ca68.

Comment thread apps/code/scripts/screenshot-dev-preview.ts Fixed
@Twixes Twixes changed the title feat(code): ship inbox v2 feat(code): Inbox 2.0 Jun 9, 2026
Twixes added 2 commits June 9, 2026 13:45
…ill.

Ship screenshot:preview commands and a persistent-server capture script so
agents can verify the Vite preview without cursor-ide-browser.
@Twixes Twixes requested a review from a team June 9, 2026 12:45

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

LGTM, your change to the remote debugging port looks unintentional

Twixes added 2 commits June 9, 2026 14:09
Debug port for screenshot/Electron attach lives on add-screenshot-dev-app-skill.
Makes Electron renderer attachable on :9222 during normal dev, alongside
the Playwright preview screenshot tooling.
@Twixes

Twixes commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

Tis intentional, but better belongs on #2527 @joshsny - moving the change there

Twixes added 2 commits June 9, 2026 14:12
…not merge)

Adds a parent /sync-inbox-to-cloud skill plus five sub-skills that orchestrate
porting features and UI polish from the desktop Inbox to PostHog Cloud:

- /inspect-inbox-surfaces
- /plan-inbox-sync
- /implement-inbox-sync (with translation.md reference)
- /finalize-inbox-sync
- /reflect-on-inbox-sync

Plus references/parallelization.md describing how to slice work across
parallel sub-agents and the upcoming-direction mock screenshots used as
supplementary context.

Not for merge — this branch exists as a long-lived reference / checkout target
while the cloud Inbox port is in flight. See PR description.
Internal-shape changes from a multi-reviewer pass on the Inbox 2.0 surface.
Behavior visible to users: dismiss buttons on the PR and Report detail
screens are now wired up (previously disabled placeholders), the "Stop run"
placeholder on agent-run detail is gone (no backend endpoint exists),
deep-linked reports route directly to the correct tab/detail based on
whether the report has an implementation PR, and PR list cards no longer
fire one GitHub REST call each for diff stats.

Behavior + correctness:
- `isInboxDetailPath` matches the runs detail route too, so the global
  Inbox header no longer stacks on top of run detail pages.
- `findReportInInboxListCache` runtime-narrows each prefix-matched cache
  entry; seeded detail entries and scope-count numbers no longer cause a
  TypeError when resolving an uncached detail.
- Bulk-action partial failures keep failed ids in the selection so the
  user can retry; only succeeded ids are dropped.
- `isReportTabReport` guards against terminal-status reports.
- `isAgentRunReport` accepts `pending_input` to match the doc.
- Deep links navigate to `/code/inbox/pulls/$id` or `/code/inbox/reports/$id`
  based on `implementation_pr_url`.
- "Open in GitHub" re-validates `implementation_pr_url` via `parsePrUrl`
  at click time so only `https://github.com/<owner>/<repo>/pull/<n>` is
  ever opened.

Performance:
- New `git.getPrDiffStatsBatch(prUrls[])` runs one GitHub GraphQL request
  (alias-batched) for the entire visible PR list. `PrDiffStats` reads from
  a `PrDiffStatsBatchProvider` mounted by `PullRequestsTab`; falls back to
  the per-PR REST query on detail pages only.
- `useInboxScopeOptionCounts` no longer fans out one list-count request
  per teammate when the scope menu opens — counts are limited to For you
  and Entire project.
- Inbox card detail prefetch drops the redundant `onPointerEnter` handler;
  TanStack `<Link preload="intent">` already covers it.
- Single O(N) `buildSuppressDisabledReasonMap` lookup per render replaces
  the inline O(N²) helper that fired per card on every search keystroke.

Architecture:
- `InboxReportListTab` shell owns the dismiss state machine, skeleton,
  search bar, and scope-aware empty state. `PullRequestsTab` / `ReportsTab`
  are thin configuration wrappers; `RunsTab` keeps its own layout.
- `InboxReportDetailGate` shares the loading / missing-report fallback for
  both detail screens.
- `InboxDetailFrame` owns the entire header + summary/evidence column for
  PR and Report detail; variants supply breadcrumb, meta prefix, extra
  badges, primary action, and section titles via slots.
- `useInboxReportDismissAction` packages the per-report dismiss flow.
- `useInboxCloudTaskRunner` extracts the shared cloud-task driver
  (guards, model resolution, `TaskService.createTask`, toast/track/openTask
  wiring). `useCreatePrReport` / `useDiscussReport` are thin wrappers.
- `useSignalSourceManager` is split into `useSignalSourceToggles`,
  `useSignalEvaluations`, `useSignalTeamConfigMutations`, and
  `useSignalUserAutonomyMutations`. The existing entry point is preserved
  as a thin aggregator so call sites keep their flat destructured shape.
- `inboxReportKeys` lives in a new leaf module (`utils/inboxQueryKeys`)
  shared by hooks, detail cache, and bulk actions.

Cleanups:
- Type-safe `SOURCE_PRODUCT_META` (`Partial<Record<SourceProduct, …>>`)
  with a `getSourceProductMeta` helper.
- Renderer `trpcClient.*` direct calls migrated to `useQuery` / `useMutation`.
- `useReportTasks` drops the `as unknown as Task` double-cast.
- Inline `style={}` for static values converted to Tailwind classes.
- Path-alias violations under `features/inbox/components` and the
  `../../task-detail/service/service` reach-up fixed.
- Dead state slots in `inboxSignalsFilterStore` deleted, with a `persist`
  `migrate` that drops the old localStorage keys.
- Dead `pendingInboxOpenMethod` module, unused `INBOX_BADGE_RADIUS_CLASS`
  export, unused `ReviewerScope` alias, and unused `suggestedReviewerSeed`
  removed.
- Inbox tab list routes centralized as `INBOX_TAB_LIST_ROUTE`; the
  detail-path regex derives from `INBOX_TAB_KEYS`.
- Date label on `ReportCard` falls back to `created_at`.
- Dismiss tooltip no longer promises GitHub PR closure (closing the
  upstream PR remains a known gap; TODO unchanged).

Tests: 128 inbox tests pass; +4 new (`inboxRoutes.test.ts`, mixed-shape
case for `inboxReportDetailCache`, `pending_input` case for
`isAgentRunReport`, migrate-from-v1 test for `inboxSignalsFilterStore`).

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

Did the usual and just dump3e my ui feedback somewhere vaguely sensible, and let you route it properly to the relevant code.

Seems like the major things are the fetching tasks associated with a particular report is broken, and you deleted functionality around changing the suggested reviewers list. Also I think we could go 2 column in the detail view

import { ConventionalCommitScopeTag } from "@features/inbox/components/ConventionalCommitScopeTag";
import { InboxCardSourceMeta } from "@features/inbox/components/InboxCardSourceMeta";
import { InboxCardTitle } from "@features/inbox/components/InboxCardTitle";
import { SuggestedReviewerAvatarStack } from "@features/inbox/components/SuggestedReviewerAvatarStack";

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.

I dislike the the variance in corner radius here, particularly this close together and not nested, and generally I like the idea of using icons here but making them look a bit like buttons is ugly imo

Image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Late addition to the PR with those icons, got messed up indeed!

import type { SignalReport } from "@shared/types";
import { Link, useNavigate } from "@tanstack/react-router";
import { PriorityMonogram } from "./PriorityMonogram";

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.

I really want a link to the relevant commit here, or at least it's short hash so I can go look at it.

Image

}

export function ReportCard({
report,

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.

I see the open in GitHub button but no way to view the associated tasks? Seems like either the pulling of associated tasks is broken, or this is missing?

Image

report,
detailRoute,
);
const navigate = useNavigate();

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.

Feels wider than it needs to be, and puts the evidence and artifacts at the bottom. Particularly once we/I move towards "artifacts as log", we should make this two-column (dynamic to single column when the screen is too narrow) imo, otherwise your burying all the rich data (diffs, tasks, artefacts) below this wall of text

Image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed, should be no more than 100 chars wide really

So, I like "artifacts" as long. It's kind of a matter of responsive design. If we have the space, via a container query, we can have the description on the left, and the other details to the right. Slightly like a Facebook page UI 🤔

const { data: artefactsResp } = useInboxReportArtefacts(report.id, {
staleTime: 5 * 60 * 1000,
refetchOnWindowFocus: false,
});

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.

My impression is "runs" is only meant to show ongoing tasks? Seems like a bit of an arbitrary limitation imo, but given it, I'd call it "running" or "live" instead

Image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Primarily for ongoing runs, but it makes sense to me to show the ongoing ones first, and finished ones lower down

});
const repoSlug = extractRepoSelectionRepository(artefactsResp?.results);
const firstSource = report.source_products?.[0];
const sourceMeta = firstSource ? SOURCE_PRODUCT_META[firstSource] : null;

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.

UI seems to be lying about there being only 100 items (what items? reports? runs?) "for me"

Image

Also this feels like a weird place to put this, I thought it would be a tab of curated reports or something, not a filtering UI

undefined,
{ month: "short", day: "numeric" },
);
const isReady = report.status === "ready";

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.

Spacing between the "findings" header and the first finding is bad, count is in a pill but the rest of the ui uses round rects, count pill has a BG color that matches the rest of the UI but icon doesn't

Also feels weird to call them "findings" here but "evidence" in the PR version, unless I'm confused about what this is displaying (it's just a single, right?)

Image

const conventionalTitle = parseConventionalCommitTitle(report.title);
const cardTitle = displayConventionalCommitTitle(
report.title,
"Untitled report",

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.

This header in general could be removed imo, but failing that, "this is your inbox" is really odd and should be removed

Image

);

const openDetail = () => {
prefetch();

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.

No way to view suggested reviewers inside a report, even though we display them in the list view, and no way to modify suggested reviewers on a report OR a PR detail page (serious regression I'd actually block merging on)

Image

Twixes added 3 commits June 9, 2026 17:24
Tighten the review-feedback commit before it lands:

- AgentRunDetail uses InboxReportDetailGate (drops its own loading +
  missing-report fallback to match PR and Report detail).
- PullRequestDetail's "Open in GitHub" handler stops reconstructing the URL
  from `parsePrUrl` parts; the parser already proves the source URL is a
  canonical GitHub PR URL.
- useInboxReportDismissAction memoizes the closed-dialog "no reports" array
  to a stable identity so useInboxBulkActions' eligibility memo doesn't
  bust on every parent render of the detail screen.
- useDiscussReport drops `pendingQuestion` state in favor of a ref; the
  question now travels through buildInput without retriggering the runner.
- git.getPrDiffStatsBatch chunks into groups of 25 PRs and parallelizes the
  chunks with Promise.all so a single GraphQL request never exceeds
  GitHub's complexity budget on large list views.
- usePrDiffStatsBatch sets explicit gcTime so distinct filter/search
  snapshots don't accumulate stat blobs in the React Query cache
  indefinitely.
- PrDiffStatsBatchProvider is inlined: the context object and
  usePrDiffStatsFromBatch consumer hook live in
  utils/prDiffStatsBatchContext.ts, and the provider mounting collapses
  into a small PullRequestsBatchProvider colocated in PullRequestsTab.
- Centralize team-config / user-autonomy / source-configs query keys as
  signalsConfigKeys in inboxQueryKeys.ts; mutation hooks import from there
  instead of inlining string-literal keys.
- Flatten the 3-level empty-title ternary in InboxReportListTab into a
  resolveEmptyTitle helper with early returns.
- Drop the unused lookupPrDiffStats export.
- Trim narrate-the-refactor JSDoc on useInboxReports, useSignalSourceManager,
  useInboxCloudTaskRunner, useInboxReportDismissAction, and
  usePrDiffStatsBatch.

Tests: 128 inbox + 27 git service pass; 0 typecheck errors.
Twixes added 20 commits June 9, 2026 17:37
# Conflicts:
#	apps/code/src/renderer/features/inbox/components/InboxEmptyStates.tsx
#	apps/code/src/renderer/features/inbox/components/InboxSignalsTab.tsx
#	apps/code/src/renderer/features/inbox/components/InboxView.tsx
#	apps/code/src/renderer/features/sidebar/components/items/HomeItem.tsx
#	apps/code/src/renderer/hooks/useAppView.ts
#	apps/code/src/renderer/routeTree.gen.ts
…d (reference, do not merge)""

This reverts commit a4efbef.
Restore deleted functionality, fix styling complaints, and split the
detail view into a responsive two-column layout.

Restored / new

- `SuggestedReviewersSection` is back on both PR detail and Report detail
  with view + add + remove. Renders short commit hashes (`abc1234`) as
  link chips with the reason as a tooltip, addressing both the missing
  editor (blocker) and Olly's request for commit hash/link surfacing.
- New `ReportDetailActions` cluster: Discuss (split-button with optional
  first-question popover) on every detail screen; Create PR on Report
  detail only. The hooks (`useDiscussReport`, `useCreatePrReport`)
  survived from v1 — they just didn't have invocation surfaces.
- New `ReportTasksSection` lists implementation / research tasks linked
  to the report on PR and Report detail. Each row is clickable, with a
  status icon + relationship badge.
- New `useReportActionTracker` hook centralizes `INBOX_REPORT_ACTION`
  emission for detail surfaces; pre-fills report identity so call sites
  just pass the action type and any extras.

Styling and copy

- `DetailSection` drops the button-look (border, panel bg, inset shadow)
  on the section-icon container. The right-slot is no longer wrapped in a
  rounded-full pill that clashed with the round-rect rest of the UI.
- ReportDetail's "Findings reviewed" section renames to "Evidence" to
  match the PR detail surface. Individual items stay "signal" / "finding"
  in copy and under the hood.
- The InboxPageHeader subtitle ("This is your inbox.") is gone. The
  header is now just the tab bar + scope picker — no narrating preamble.

Layout

- `InboxDetailFrame` body is a container-query grid: at narrow widths
  everything stacks; at `@4xl` it splits into Summary on the left and
  Evidence / Tasks / Suggested reviewers on the right. The wall-of-text
  no longer pushes the actionable artefacts off-screen below the fold.
- Detail view's `max-w-4xl` shrinks to `max-w-3xl` for the single-column
  fallback so the prose stays around 100 chars wide.

Counts removed from the scope picker

- The "100" total next to "For you" and the per-option counts inside the
  dropdown (165 / 10931 / per-teammate) are gone. They were either lying
  (page-size-bound) or expensive (per-teammate fan-out). The scope
  selector is now just a picker.
- `useInboxScopeOptionCounts` is deleted; the slim
  `useInboxScopeOptions` replaces it.

Runs tab

- Live (in-progress / pending-input) runs render first under a "Live"
  header with the existing pulse dot. A new "Recently finished" section
  below shows the most recent 10 non-excluded reports (sorted by updated
  desc). Tab predicate / membership is unchanged.

Verification

- 155 tests pass; 0 typecheck errors.
- Visually verified via the `screenshot-dev-app` skill against the Vite
  preview on each fix.
Drops the split-button. Discuss is now a single button that opens the
question popover; the only way to launch is to submit the message. There
is no fire-and-forget "discuss with no question" path anymore — the
submit button stays disabled until the textarea has content.

Matches the intent that every Discuss task starts from a deliberate
prompt the user typed, not from an empty click.
Layout

- Description column caps at 80ch (~520px at 13px) inside the prose body
  so the wall of text never blocks the side column from being read.
- Detail grid is `[minmax(0,80ch) minmax(0,1fr)]`, with the container
  capped at `160ch + 5rem`. The right column grows beyond the prose to
  use the leftover space, but never exceeds 50% of the total — wider
  viewports get larger side gutters instead.

Runs (formerly "Tasks")

- Renamed from "Tasks" to "Runs" (Twixes: it's debug-level info, low-key,
  not something users browse day to day).
- Section is no longer a `DetailSection` — small caption + tight rows in
  monospace, status as a 6px dot rather than a 16px icon, link icon only
  shows on hover.

Suggested reviewers (compact + linked)

- Rows lose the bordered card chrome and inherit the section's spacing
  instead. Tighter padding, smaller avatar (sm), smaller badges.
- Both the avatar and the name now link to https://github.com/<login>
  when a GitHub handle is available. The standalone `@<login>` chip is
  gone — it was redundant with the name link.
- The commit hash collapses into the reason line as a low-key
  `(abc1234)` mono link; the tooltip is dropped because the reason is
  already rendered alongside it.
There was no real "primary" distinction in the data — `SuggestedReviewer`
has no `primary` field; the first entry was just the agent's top-ranked.
Drop the misleading badge.

New primitives so Evidence / Runs / Suggested reviewers all read as one
system instead of three competing visual treatments:

- `RightColumnSection` — slim caption header (uppercase 11px label + small
  icon + optional right slot, no spanning divider line). Replaces
  `DetailSection` for everything in the side column. The main Summary on
  the left keeps `DetailSection` so the hierarchy is clear: one main
  affordance, several supporting captions.
- `MeBadge` mirrors `ForYouBadge` exactly (warning variant + `EyeIcon` +
  "You" with the same tooltip). The free-floating lowercase "you" pill
  is gone — the reviewer row now shares the same visual language as the
  report-level "For you" indicator.

Reviewer rows lose all the card chrome (no border, no panel background).
Plain row with a hover bg, avatar (linked) + name (linked) + optional
`<MeBadge />`, reason text below with the commit hash as a low-key
`(abc1234)` mono link in the same line. No more separate `@<login>` chip
— the name is the link.
Detail header

- Collapsed three rows (badges → meta → actions) into one. Priority,
  status, For-you, actionability badges now flow inline with the
  timestamp / findings count / source on the left; action buttons stay
  right-aligned. Recovers ~32px of vertical space and reads as a single
  cluster instead of three competing rows.
- Type+scope tag now uses the same `compact` variant the list cards use,
  so it reads consistently — small mono badge, neutral panel, soft
  type-coloured icon — instead of a louder coloured pill.
- PR diff stats moved out of the meta row and into the Open in GitHub
  button as a high-contrast chip (translucent black bg + bright green /
  red glyphs) so the diff sits where the action is. `PrDiffIndicator`
  gains a `tone="on-primary"` variant for this.

Action buttons

- Dismiss, Discuss, Create PR, Copy link, Open in GitHub are all
  `Button variant="outline"` (or `primary` for Open in GitHub) at
  `size="sm"` with `rounded-full`. The Dismiss button stops using the
  custom Radix `UiButton` (which gave it a slightly different height)
  and now matches the rest exactly.

Inbox list-view header restored

- "Inbox" title (22px) + a short description above the tab bar:
  "The research agent watches errors, replays, support, and issues —
  and ships pull requests." Kept the standalone "This is your inbox."
  out per Olly's earlier note.
… commit, cap left column

- Drop `rounded-full` from Dismiss / Discuss / Create PR / Copy / Open in GitHub
  and restore Dismiss to the soft-gray UiButton it was before the pill round.
- Move PR diff stats out of the Open in GitHub button and back into the meta
  row just left of the Dismiss button via a new `metaSuffix` slot.
- In `SuggestedReviewersSection`, move the commit hash onto the name line as a
  muted mono chip with explicit gaps to the You badge.
- Cap the left detail column at the same prose width by setting a 13px font
  context on the grid container so `80ch` resolves to the same value the
  prose uses inside the markdown.
- Capitalize the Runs relationship labels (Research / Implementation /
  Repo selection) via a single label map.
- Rename the Report detail summary section title to "Summary" so the
  scaffolding matches PullRequestDetail; only the icon differs.
- Remove the now-dead `tone` prop from PrDiffIndicator / PrDiffStats.
The detail view leaned on the signals query to know how many findings to
expect, so the Evidence section just disappeared while loading. We already
have `report.signal_count` in the list response; use that as the immediate
count and render a skeleton with that many cards while signals stream in.

Also tighten what's selectable. Chrome shouldn't behave like prose: the
signal card metadata bar, reviewer rationale, meta row (timestamps / source
product / findings count), section headers, badges, the inbox page title,
and the runs list now have `select-none cursor-default`. Content people
might actually copy — the title, the summary body, the signal body, code
paths — stays selectable.
…ggle

Dismiss button in detail headers is now a Quill `Button variant="outline"
size="sm"` matching Discuss / Open in GitHub instead of the Radix soft-gray
UiButton it was before — same height, same corner radius, no more odd one
out in that action row.

"Ready" is the default terminal state — surfacing it everywhere was noise.
When the report has an actionability classification (Actionable / Needs
input / Not actionable), that takes the badge slot; the status badge only
falls through for the rare ready+no-actionability case or for non-ready
states. Detail frame now also owns the actionability badge directly so PR
detail picks it up too; the unused `extraBadges` prop on the frame is gone.

The reviewer scope control is a SegmentedControl now instead of a combobox.
Olly's review flagged the old dropdown as confusing — it read like a
filter, not the primary reviewer pivot — and the per-teammate sub-options
were rarely used. Dropped `InboxScopeOptionRow` and `useInboxScopeOptions`
since nothing else consumed them; persisted `teammate:UUID` scopes still
route correctly and just visually show "Entire project" in the toggle.
Runs tab partitions by run lifecycle now, not by everything-else:

  Queued    — `potential` / `candidate` reports the signals pipeline is
              still grouping, before any task spawns.
  Live      — `in_progress` / `pending_input`, the same set as before.
  Recently  — top 10 of `ready` + `failed`, with an inline "Show all N more"
  finished    that flips to "Show less". Pulled `failed` out of the
              global excluded-statuses set so failed runs can surface here
              (and added it to the pipeline status filter); other tabs
              still hide failed via their own predicates.

The tab count chip stays Queued + Live so it doesn't balloon to hundreds
once recently-finished is unbounded.

AgentRunCard reflects the lifecycle now too: queued = idle gray orb /
"Queued" badge, live = pulsing blue / "Running", completed = green /
"Completed", failed = red / "Failed". Timestamp label flips with state
(Started / Queued / Finished / Failed).

In AgentRunDetail the "Run summary" section made no sense for a completed
run — the report or PR _is_ the run summary, so duplicating it inline was
just noise. Replaced with a sleek widget that links straight into the
output (`/code/inbox/pulls/$id` or `/code/inbox/reports/$id`). Failed runs
get a red warning card framing instead. Queued / live keep an inline
"Draft summary" section because the output doesn't exist yet.

Re-research indicator: if the report has more than one `research`-
relationship task and at least one previous one ran to `completed` while
the current one is still in motion, we show a "Re-research" badge in the
header. Inferred client-side from `useReportTasks`, no backend signal.
…es everywhere

Run detail now mirrors InboxDetailFrame's container-query grid: the task
log fills the left column at the same prose width as the report view, with
evidence on the right. Dropped the fixed 420px log container in favour of
viewport-relative height so the log panel itself isn't an inner scroll
region – the page scrolls when content overflows.

Replaced the per-task Runs section on the report and pull request detail
with a single ViewRunWidget pointing at /code/inbox/runs/$reportId. The
widget shows tiny status chips per linked task (Research, Implementation)
so the user can see at a glance which stages exist without leaving the
page. ReportTasksSection is gone; the run view is the canonical place for
task-level visibility.

Run detail also picks a smarter primary task (newest non-terminal,
otherwise newest by created date) and surfaces a small DropdownMenu
switcher in the Task log section's right slot when more than one task is
linked – so the multi-task and re-research cases stay legible without
stacking full log panels.

Em-dash sweep: this PR was sprinkling em dashes through comments and copy.
Replaced every PR-added em dash with an en dash and confirmed no
pre-existing em dashes were touched.
…copy-link

Three review agents flagged the same things; this pass folds them in:

- Extracted shared `TaskRunStatusDot` (was byte-identical in both
  `AgentRunDetail` and `ViewRunWidget`) into
  `features/inbox/components/utils/TaskRunStatusDot.tsx`.
- Extracted `formatRunId(reportId)` and `useCopyDeepLink(path)` so
  `AgentRunCard`, `AgentRunDetail`, and `ReportDetail` stop hand-rolling
  the same templates.
- Collapsed `AgentRunCard`'s `RunStatusOrb` from four near-identical
  branches into a single component driven by a `VARIANT_META` table that
  also owns label, badge tone, and timestamp prefix per variant.
- `RunsTab` now partitions `scopedReports` in a single pass instead of
  three separate `.filter` walks, and the nested ternary that built the
  Show all / Show less control is lifted into a `resolveShowAllControl`
  helper with a discriminated union (`kind: "expand" | "collapse"`).
- `useInboxReportDetailPrefetch` was invalidating `prefetch` every render
  because the `route` object is inlined by callers; switched its deps to
  the destructured `to` + `reportId` so the callback stays stable.
- Trimmed a couple of narrative comments that explained what the next few
  lines did rather than why.
Restore the master-branch behaviour: Create PR shows only when the report
is genuinely actionable and doesn't already have a PR. Mirrors the
server-side autostart rules in a `canCreateImplementationPr(report)`
predicate:

  - hidden if `implementation_pr_url` is set (PR already exists),
  - hidden if `already_addressed` is true (the issue's already fixed),
  - shown when status is `pending_input` (waiting on user to supply input),
  - shown when status is `ready` AND actionability is
    `immediately_actionable` or `requires_human_input`.

`ReportDetailActions` now derives this internally; dropped the
`showCreatePr` prop on both callers since the predicate captures both
intents – PullRequestDetail's reports always have `implementation_pr_url`
set so the button stays hidden there automatically.
- Dropped `formatRunId` + the `resp_` prefix; we now just show the
  first 8 chars of the report UUID at every call site.
- Inlined `handleCopyLink` in `AgentRunDetail` and `ReportDetail`. A 6-line
  copy is fine; a dedicated `useCopyDeepLink` hook in its own file is
  overkill.
- Moved `TaskRunStatusDot` from its own file into `AgentRunDetail.tsx` and
  re-exported it from there; `ViewRunWidget` imports it from
  `AgentRunDetail`. The standalone utils file is gone.
Reports use time-ordered UUIDs, so the first 8 chars collide across runs
created in the same window and the abbreviation stopped being useful.
Switched to the last hyphen-segment (the random tail), prefixed with `…`
so it's obvious it's a truncation.
The segmented toggle already advertises which scope is active, so the
Combobox's auto-rendered right-edge check on the selected row reads as
visual noise. Hide it and reclaim the reserved padding so the row sits
flush against the right edge.
…w all

Three small alignment fixes from the look-back round:

- Re-research now counts any prior terminal research (completed, failed,
  cancelled) as evidence of a re-attempt. The framing is "we already
  tried, now we're trying again", regardless of how the first attempt
  ended.
- AgentRunDetail's header timestamp label mirrors AgentRunCard now:
  "Queued" / "Started" / "Finished" / "Failed" depending on lifecycle
  state, instead of always reading "Started".
- The Queued section gains the same inline "Show all N more" / "Show
  less" pattern that the Recently finished section already had – so
  hundreds of queued runs don't blow up the page.
…ligned, empty state, primary Create PR

Bringing back the previous Runs-section shape on report/PR detail because
the chunky "View the run" card read as visual noise next to the slim
Reviewers caption. New ReportTasksSection mirrors the RightColumnSection
chrome – one row per linked task (status dot, relationship, task title),
each row navigates to /code/inbox/runs/$reportId.

On the run detail, the "Open the pull request" widget gets replaced by a
richer info card: repo/PR number in mono, diff stats from PrDiffStats,
the PR or report title (2-line clamp), and the "Open …" action as a
quiet inline link. For non-PR reports it surfaces source product instead
of diff stats. Failed runs keep the red warning framing.

Also:
- Truncated run id reads `…-tail` instead of `…tail` so the hyphen makes
  it clear it's a UUID segment.
- Tab bar's scope toggle (For you / Entire project) now sits flush to
  the far right via `justify="between"`.
- Live section's empty state is a small icon + 2-line copy card instead
  of a single muted line of text.
- Create PR on reports is `variant="primary"` (was `outline`).
- Task log container drops the viewport-relative height so it grows to
  content; keeps a 420px minimum for the placeholder state.
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.

6 participants