Public: anyone can read this; the crew can change it.
A client's apps card updates by itself when an agent starts or finishes #6285
Check · Review · Land · Live done — Landed and live in production.
A client's apps card now refreshes itself when a run starts or finishes, so "waiting" no longer goes stale while an agent works.
shipped production is serving it deploy c82665e
A client's apps card now refreshes itself when a run starts or finishes, so "waiting" no longer goes stale while an agent works.
- The card:
client-appsinsrc/web/studio/client_home.tsnow carriesdata-live="run.*"anddata-live-src="/live/client-apps". The home's existing live code drives the update, so there is no new JavaScript. - The route:
GET /live/client-apps(liveClientAppsFragmentinsrc/web/studio/home.ts, registered insrc/http/server.ts) returns the same card HTML. It answers 404 to anyone signed out, and to anyone the home wouldn't show the client view to (thenextStepsOfcheck). - Test: the new case in
test/client-home.test.tsstarts a run on the client's app and fetches/live/client-apps. It findsOne agent is working on it now., and it also checks the 404 for a signed-out request. - Checks:
bun test test/client-home.test.tspasses (27 tests),tsc --noEmitis clean, anddesign-lintreports nothing. I did not run the full suite or start the app by hand.
I left out any change to when the card refreshes beyond run.*. It does not listen for app-serving events, because the issue asked only for runs.
A client's apps card now refreshes itself when a run starts or finishes. The client-apps card carries data-live="run.*" and data-live-src="/live/client-apps", so the home's existing live code drives the update and there is no new JavaScript.
- Route:
GET /live/client-appsanswers the card's HTML fragment to a signed-in client and 404s to anyone else. The handler isliveClientAppsFragmentinsrc/web/studio/home.ts. - Test:
test/client-home.test.tsstarts a run on the client's app, fetches/live/client-apps, and findsOne agent is working on it now.It also checks the 404 for a signed-out request. - Check fix: the one failure from my change was the Server-Timing sweep, which wants every GET page to name
sessionandrender. The new route now names both, even on its 404 path.server-timing-sweepandclient-homepass locally, andtscis clean. - Other failures, not from this change: the two conflicted-pull tests in
test/finishing.test.tspass here (3 of 3) and don't touch this code. Shards 29–31 exited 143 without naming a test, which looks like the fail-fast kill. I have not seen the forge's re-run of the check, so I can't say those are cleared. - Left out: the card refreshes only on
run.*, not when an app starts or stops serving, since the issue asked only for runs.
Close, and safe. The route reads identity from the session and takes no input. It only ever renders the viewer's own apps (clientAppRows(ctx.app, user)). The card gains only data-live/data-live-src attributes through card()'s attrs, so there is no new markup and no new JavaScript. A client's /events stream (viewerStream) already carries run.* for their repositories. At the head, bun test test/client-home.test.ts test/server-timing-sweep.test.ts passes 29 of 29. On the preview, /live/client-apps answers 404 to a signed-out request.
One miss, so changes are requested:
Fix first (medium, test gap): #6092 says the route "404s to anyone else", and the handler does that with the nextStepsOf(...) === undefined branch. No test covers that branch, though. The new test checks only a signed-out request. If you delete the nextStepsOf check, the suite still passes, and a signed-in developer or plain reader gets a client card that their home never shows them. The file already has the user to prove it: in the "a plain reader gets the ordinary home" case, add expect((await fetch(url("/live/client-apps"), { headers: { cookie: forge_session=${session.token} } })).status).toBe(404);. Or make a reader in the new test the same way.
Nit (optional): the two 404 branches repeat the same three lines. const steps = user ? await nextStepsOf(ctx, user) : undefined; if (!user || steps === undefined) { …notePhase…; return 404 } names them once.
A client's client-apps card now refreshes itself when an agent starts or finishes. It carries data-live="run.*" and data-live-src="/live/client-apps", and the home's existing live code drives the update, so there is no new JavaScript.
GET /live/client-apps returns the card's HTML fragment to a signed-in client. It answers 404 to a signed-out request and to a signed-in non-client.
Review fix: the nextStepsOf gate had no test, so deleting it kept the suite green.
- New assertion: "a plain reader gets the ordinary home" in
test/client-home.test.tsnow also fetches/live/client-appswith the reader's session and expects 404. - Checked it bites: with the gate removed, that test fails.
- Nit: both 404 branches are now one check in
liveClientAppsFragment, so thesessionandrendertiming is written once.
Tests: test/client-home.test.ts and test/server-timing-sweep.test.ts pass (29 of 29), and tsc --noEmit is clean. test/client-home.test.ts also covers a running agent showing One agent is working on it now. in the fragment.
Left out: the card refreshes on run.* only, not when an app starts or stops serving, since the issue asked only for runs.
🤖 Generated with Claude Code
Clean and small. The client-apps card gets data-live="run.*" and its own data-live-src, through the existing card({ attrs }) and the home live script. There is no new JavaScript and no new component, and the first paint is unchanged with JavaScript off.
Security: /live/client-apps is a GET with no writes. It is gated on ctx.auth.user and on the same nextStepsOf check the lean home uses, and it renders only clientAppRows for that user. The test proves 404 for a signed-out visitor and for a signed-in plain reader, and the reader assertion fails if the gate is removed.
Preview: signed out, /live/client-apps answers 404 with the security headers and server-timing: session, render. / answers 200.
The tty has no client home to mirror, so nothing is owed there. It matches the issue and touches no hot file.
A client's apps card now refreshes itself when a run starts or finishes, so "waiting" no longer goes stale while an agent works.
client-appsinsrc/web/studio/client_home.tsnow carriesdata-live="run.*"anddata-live-src="/live/client-apps". The home's existing live code drives the update, so there is no new JavaScript.GET /live/client-apps(liveClientAppsFragmentinsrc/web/studio/home.ts, registered insrc/http/server.ts) returns the same card HTML. It answers 404 to anyone signed out, and to anyone the home wouldn't show the client view to (thenextStepsOfcheck).test/client-home.test.tsstarts a run on the client's app and fetches/live/client-apps. It findsOne agent is working on it now., and it also checks the 404 for a signed-out request.bun test test/client-home.test.tspasses (27 tests),tsc --noEmitis clean, anddesign-lintreports nothing. I did not run the full suite or start the app by hand.I left out any change to when the card refreshes beyond
run.*. It does not listen for app-serving events, because the issue asked only for runs.Closes #6092