The issue detail
An issue has one screen. Whether you clicked a row on the board, followed a/issues/ENG-4 link from the dashboard, hit it from ⌘K, or opened it from the
Inbox, you land on the same surface with the same controls.
That was not true before. Clicking a row inside /issues opened an inline
panel; the canonical link /issues/<identifier> — the one the dashboard, the
palette, the inbox, activity, the crew tabs and every sub-issue link point at —
opened a completely different page, with different chrome, a different rail and
a different set of things you could change. Which screen you got depended on how
you arrived.
The two routes
Both render
components/features/issues/issue-detail-surface.tsx. The route
only decides what sits above it.
The selection is in the URL
Opening an issue or a project writes it into the query string:- You can share it. Paste the URL and the other person opens the same issue, under the same project filter.
- A refresh keeps it. The selection is no longer component state.
- Back closes the detail instead of leaving the page. Selections are written
with
history.pushState, so each one is a history entry.
?project= used to be read on arrival and never written, so ⌘K could send you
to a project but selecting one in the page left the URL saying nothing. Both
params are now read and written, and they do not clobber each other — opening
an issue inside a project keeps the project.
Writes go through the History API rather than
router.push. A same-path query
change through the App Router re-evaluates the dashboard layout subtree and
flashes the auth provider’s full-screen spinner. Same reason as
hooks/use-shallow-search-param.ts; the only difference is push versus replace.What you can do on it
Everything the two old screens could do, plus the things only one of them could.
Two of these did not work before this landed, and now do:
- Labels. The sidebar sent
label_ids, whichPATCH /api/v1/crews/{crewId}/issues/{identifier}has no field for — the request fell through to400 No fields to update. The field islabels. - Clear estimate.
estimatedecoded into a*int, so a JSONnullwas indistinguishable from an omitted field and the clear arrived as an empty patch. The handler now reads it as raw JSON and tellsnullapart from absent. A non-number is a400.
The layout
Everything on the surface is a card, including Run activity — it used to render bare, a heading and a list of steps sitting on the page background in the middle of a stack of cards. It is now a card like the rest, with the step count as its subtitle and the Running / Waiting-for-approval indicator in the header. The timeline itself is shared with the routine run panel and the activity bar, which still get the bare rail; the card is opt-in. On wide viewports (xl and up) the right rail follows you as you scroll.
A description longer than the rail used to leave an empty column beside it for
the rest of the page. The rail is capped at the height of the viewport and
scrolls internally if it is taller, so a long rail on a short window is still
reachable. Below xl the columns stack and the rail scrolls with the page,
exactly as before.
Finding issues: one filter, two places
/issues filters by crew, agent, priority and status, and the four
combine — “Engineering crew, high priority, still in Backlog” is one
selection, not three attempts. Each pick used to clear the others, so the
dropdown behaved like a set of switches; picking a crew left the priority
alone, picking an agent did not, and no combination survived.
The two are one piece of state, not two filters: picking Backlog in the
dropdown lights the Backlog chip, and clearing the chip clears it in the
dropdown. The chips are the quick, count-carrying affordance and disappear
when an issue detail takes the centre pane; the dropdown is always reachable,
which is why status belongs in it too.
Clearing:
- Click an active value again to drop that facet.
- All crews / All agents / Any priority / Any status resets one facet and leaves the others.
- Clear all in the dropdown header drops everything, as does
Escon the board.
hooks/use-filtered-issues.ts). It used to apply only crew and agent, so a
priority picked in the dropdown narrowed the board while the list beside it
went on showing the rows the filter had excluded.
Read-only
The card renders without any of the editors when the host does not pass them — the same layout, every value as text. That is what a reader without permission gets, and it is what the/issues-new design preview was before this shipped.
That route is gone: keeping it would have been a second URL for the same screen
minus the editing, which is the defect this replaced.
The project detail
/issues?project=<id> renders the matching project card:
identity → figures → the project’s issues → breakdown → health → properties.
Name, icon, colour, status, priority, health, lead and dates are all
editable. Dates are new: the old rail drew a row reading “Set dates” that had
nothing behind it, while PATCH /api/v1/projects has taken start_date and
target_date all along.