feat: project page - #2738
Draft
camielvs wants to merge 18 commits into
Draft
feat: project page#2738camielvs wants to merge 18 commits into
camielvs wants to merge 18 commits into
Conversation
🎩 PreviewA preview build has been created at: |
camielvs
force-pushed
the
09-17-explore_new_project_card
branch
from
September 18, 2026 21:19
15b2a3f to
b07c324
Compare
camielvs
force-pushed
the
09-17-feat_project_page
branch
from
September 18, 2026 21:19
d70b987 to
1e2f163
Compare
camielvs
force-pushed
the
09-17-explore_new_project_card
branch
from
September 18, 2026 21:26
b07c324 to
ff8d4e6
Compare
camielvs
force-pushed
the
09-17-feat_project_page
branch
from
September 18, 2026 21:26
1e2f163 to
501de46
Compare
camielvs
force-pushed
the
09-17-explore_new_project_card
branch
from
September 18, 2026 21:44
ff8d4e6 to
a4b9b99
Compare
camielvs
force-pushed
the
09-17-feat_project_page
branch
from
September 18, 2026 21:45
501de46 to
98b2313
Compare
camielvs
force-pushed
the
09-17-explore_new_project_card
branch
from
September 18, 2026 22:09
a4b9b99 to
d3bc8fa
Compare
camielvs
force-pushed
the
09-17-feat_project_page
branch
from
September 18, 2026 22:09
98b2313 to
74d9257
Compare
This was referenced Sep 18, 2026
Collaborator
Author
This was referenced Sep 18, 2026
camielvs
force-pushed
the
09-17-explore_new_project_card
branch
from
September 23, 2026 20:57
d3bc8fa to
c23da09
Compare
camielvs
force-pushed
the
09-17-feat_project_page
branch
from
September 23, 2026 20:57
74d9257 to
1b73d44
Compare
This was referenced Sep 23, 2026
camielvs
force-pushed
the
09-17-explore_new_project_card
branch
from
September 23, 2026 23:00
c23da09 to
e2ed9cc
Compare
camielvs
force-pushed
the
09-17-feat_project_page
branch
2 times, most recently
from
September 23, 2026 23:36
1a0f4ce to
4fe29b1
Compare
camielvs
force-pushed
the
09-17-explore_new_project_card
branch
from
September 23, 2026 23:36
e2ed9cc to
2379fd2
Compare
camielvs
force-pushed
the
09-17-feat_project_page
branch
from
September 23, 2026 23:57
4fe29b1 to
ff3a142
Compare
camielvs
force-pushed
the
09-17-explore_new_project_card
branch
from
September 23, 2026 23:57
2379fd2 to
40c40a8
Compare
The route landed on a placeholder. It now shows the project it names: who made it, when, and the actions that were previously only reachable from its card. A deleted project returns to the list rather than leaving the visitor on a page that no longer exists. A missing project reads as missing rather than as a failure, since a shared project URL outlives the project. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Description and notes are editable on the page and save when the field is left, the way run notes already work. Notes had no home before this: they come back only from the single-project response, so no other surface could show them. Renaming goes through a dialog rather than an in-place field, since a name wrong by a keystroke is worse than a description wrong by one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resource counts on a card said a project held three pipelines without saying which. The page lists them, grouped by kind, and every kind is named even when empty so the shape of a project is legible before anything is in it. An unrecognised kind still gets a group: the backend stores the entity as a plain string and expects more members, so an unknown one must not vanish. Removing an item says plainly that it leaves the pipeline or document itself alone, since "remove" next to a project that hard-deletes its contents is otherwise an alarming word. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Documents are the one kind of resource a project can hold without pointing at something else, so they are the one kind this page can create: the backend requires a document to carry a payload and forbids it an entity_id, both confirmed against the API before the form was shaped. The payload keeps the body under `content`. Nothing server-side validates inside the payload, so that key is this app's convention and not a rule. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The page description promises pipelines and runs, so the runs belong on it. The endpoint exists but is absent from the generated client, whose checked-in copy predates it; regenerating would swap the whole client for whatever backend happens to be running, so this one call is written out by hand against the client the provider already configures. A 4xx is no longer retried. Without that, a url for a deleted project sat on a spinner through three backoffs before it could say the project was gone, which made the not-found state effectively unreachable. Runs carry no execution status, so none is shown rather than implied. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ource cards The stacked page spent a full-width row on two textareas and then split the resources into three near-empty tables, so a project with four items filled a screen and a half. Viewing and editing now sit side by side: the main column holds the resources and the runs, and a right-hand column holds the description, notes, metadata and every project action. Resources are one grid of cards of whatever kind, with a type filter that appears only once there is more than one kind to filter, so a project of documents never shows a filter with one option. The inline "Add document" button becomes a single "Add" menu; pipelines and agent sessions sit in it disabled under a line saying where they will come from, which reads as a roadmap rather than a missing feature. The header keeps only the back link and the project's name, and the actions it used to hide behind a kebab are three labelled buttons in the sidebar.
…lumn At 2000px the capped grid left a third of the window empty and the sidebar sat in the middle of it. The sidebar is now a fixed 320px rail against the right edge and the resources and runs sit in a centred column of their own, capped so a five-card row does not stretch across the whole monitor. The header moved inside that column so the page reads as one document beside a rail rather than a title adrift at the far left. The empty state and the add menu drop their "coming soon" wording: the disabled entries say enough on their own.
Centring it left a wide gap between the page's left edge and its first heading, so the content read as adrift rather than composed. The column now starts at the gutter and keeps a cap, and the sidebar stays against the right edge; the empty state is held to a narrower box so it does not float to the middle of an otherwise left-aligned column.
The page had a wide empty middle and no way to look inside anything it
listed. Picking a card now previews it beside the list: a document shows its
own body, highlighted by whatever its name implies, and a pipeline shows the
yaml of its saved spec. An item whose payload has no body of its own is
dumped as yaml rather than shown as blank, and an item carrying nothing at
all says so.
`GET /api/pipelines/{id}` is missing from the checked-in generated client, so
it is written out by hand against the configured client for the same reason
the project runs call is: regenerating would replace every operation from
whatever backend happens to be running.
Runs joins the resources in the first column, which widens to hold both. All
three columns now carry a heading of the same height, so their panels start
on one line instead of the sidebar riding up above the preview.
Cards cost the width the preview needs: at four or five items they wrapped into a block as tall as the viewer beside them, and squaring the two columns up would have taken a third of the preview away. Rows under an inline heading per kind say the same thing in a quarter of the space, and the heading counts its group, so the filter pills are gone with nothing lost. A kind the project holds none of is left out rather than shown empty: the add menu already says what a project can hold, and three empty groups in a narrow column is the noise the cards were.
A row was clickable but said nothing about it: the default cursor over the name read as text, and the only action behind the kebab was a remove, so the menu was two clicks wrapping one. The row now shows a pointer and carries the remove inline, named after the item so it reads on its own. Nothing could get back out of a preview either. Picking the row that is already showing puts the column back to nothing selected, and a Clear beside the preview heading says so for anyone who would not think to try.
Picking the showing row again already puts the column back to nothing selected, so a second control for it was only another thing to keep in step.
The runs table said what ran and when but not how it went, and it was set in
a type a size larger than the resources beside it. Rows now match that
typography and carry the run's overall status, icon and label, from the same
task counts the main runs table reads.
Those counts turn out to need asking for: `/api/pipeline_runs/{id}` omits
`execution_status_stats` unless `include_execution_stats` is passed, and the
shared `fetchPipelineRun` does not pass it, so a first cut of this silently
rendered every run as unknown. The project page asks for its own rather than
changing the payload every other caller of that helper caches.
The author column is gone: a run is reached through the project that holds it,
so who started it earns less room than what it did.
… runs table scrolling The started column was 96px holding a 104px date, and the table cell it sits in cannot wrap, so the runs table scrolled sideways by exactly that overflow. The column is wide enough now, the resources table gets the same treatment before it grows the same problem, and the whole column is wider, so a run's pipeline name has 208px instead of 176. A previewed pipeline also gets a link into the editor, built by the same `getDefaultEditorPath` the pipelines dashboard uses, so it follows the `v2_editor` flag. The editor addresses a pipeline by the path it is saved under, which is not always its title, so the fetch now returns that alongside the spec.
…ires Rebasing onto the current service branch picked up `extraData` as a required field on a project and its resources, so every fixture on this branch has to name it.
…eting it A bin icon that turned red on hover read as "destroy this pipeline", which is the one thing the action does not do. An X in the row's own colour says "take it out of here", and the confirmation now says plainly that the item is not deleted and stays wherever it lives.
…n apart The table had no header row, so `table-fixed` had nothing to size its columns from and split them evenly, leaving the row action stranded in the middle of a wide cell. It now carries the same header row the runs table beside it does, which is where the widths belong. An item the project only points at is unlinked when removed, but a document lives nowhere else and is destroyed. The row now says which: an X and "remove from this project" for a reference, a bin and "delete" for something the project holds outright, with the confirmation wording to match.
A verdict only, green or red: anyone who wants the detail opens the pipeline. It reuses the editor's own validator so the two never disagree, and runs on the spec the preview has already fetched, so it costs no extra request and no perceptible wait. A pipeline whose tasks arrived without their component specs gets no verdict at all rather than a misleading red, since the validator reads embedded specs and never fetches one.
camielvs
force-pushed
the
09-17-explore_new_project_card
branch
from
September 24, 2026 00:13
40c40a8 to
89b0612
Compare
camielvs
force-pushed
the
09-17-feat_project_page
branch
from
September 24, 2026 00:13
ff3a142 to
8f3a12c
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Stage 2 of the projects MVP:
/projects/$projectIdbecomes a real page, replacing the placeholder from #2734. Branches off #2735.Layout
Three columns, stacking to one below
xl:All three columns share a heading row of the same height, so their panels start on one line rather than the sidebar riding up above the preview.
Resources
Rows grouped under an inline heading per kind, which counts its group. A kind the project holds none of is left out rather than shown empty. Clicking a row previews it; clicking it again returns to nothing selected. Remove is inline, labelled after the item it removes, behind a confirmation that is explicit that it takes the item out of the project without deleting what the item points at.
Adding is one
Addmenu. Only documents can be added here: a pipeline resource needs a stable server-side pipeline id, which local pipelines do not have yet. Pipeline and agent session appear disabled rather than hidden, so the gap reads as a roadmap.Preview
readme.md→ markdown, no extension → plain text).getDefaultEditorPaththe pipelines dashboard uses, so it follows thev2_editorflag.Runs
Each run carries its overall status, from the same task counts the main runs table reads. Who started a run is left out: a run is reached through the project that holds it.
Two endpoints written out by hand
GET /api/projects/{id}/runsandGET /api/pipelines/{id}are both absent from the checked-in generated client. Regenerating emits every operation of whatever backend happens to be running — the checked-in copy has 61 functions against 124 live operations — so that is worth doing deliberately on its own branch rather than inside a UI change. Both calls go through the already-configured client, so they inherit the base url and headers like any generated call, and each carries a comment saying why it is hand-written.Things a reviewer should know
GET /api/pipeline_runs/{id}omitsexecution_status_statsunlessinclude_execution_statsis passed, and the sharedfetchPipelineRundoes not pass it. A first cut of the status column silently rendered every run as unknown because of this. This branch asks for its own rather than changing the payload every other caller of that helper caches — but ainclude_execution_statson the project runs endpoint would make the whole column free instead of one request per row.pipeline | agent_session | document, so that path is covered by unit tests only.Verification
npm run validateclean, full suite passing. Driven end to end against a local backend at 2000 / 1440 / 1200 / 900 px in both themes: no horizontal overflow on either table, description and notes persist across a reload, add and remove a document, a real pipeline renders as yaml and its editor link loads, a deleted pipeline says so, removing the previewed item clears the preview. Seeded and cleaned up through the API in atry/finallyso a mid-run failure could not leave rows behind.🤖 Generated with Claude Code