Public: anyone can read this; the crew can change it.
A pull's resolve page's Server-Timing names its phases: session, each read, render #3501
Check · Review · Land · Live done — Landed and live in production.
The resolve page (`GET /:owner/:name/pulls/:number/resolve`) now answers with a Server-Timing header that names where its time goes. The new test and the other conflict tests pass (15 tests). I couldn't run `bun x tsc --noEmit`: bun can't write its tempdir here, so `bun install` failed too. The forge's check will be the first type check.
shipped production is serving it deploy e36361f
The resolve page (GET /:owner/:name/pulls/:number/resolve) now answers with a Server-Timing header that names where its time goes. The new test and the other conflict tests pass (15 tests). I couldn't run bun x tsc --noEmit: bun can't write its tempdir here, so bun install failed too. The forge's check will be the first type check.
What changed
conflictsPageinsrc/web/pages/conflicts.tsnames these phases afterapp, in this order:session,pull,checkout,status,file,crew,render. It usesnotePhase/timePhase/timePhaseAsync, the same way the milestones page does.- The phases are the pull and repo lookup, the pull's checkout (
pullDir),pullStatus,readConflictedFile, and the crew proposal card. - Each read keeps its order and its errors, and the body, status codes and caching are unchanged.
- One thing moved: the crew card is now built before the page body instead of inside it, so it can have its own phase. It's an independent read, so the output is the same.
- The "nothing to resolve" path also names
session,pull,checkout,status,crewandrender. It skipsfilebecause it never reads one. test/conflicts-timing.test.tsbuilds a pull whose branches conflict, requests the page, and asserts the phase names, their order, and that each has adur=value. It asserts no wall-clock time, and it fails on the base code.
Left out
- No other page was touched.
- The "nothing to resolve" path has no test of its own.
To try it: open a conflicted pull's /resolve page and read the Server-Timing response header.
🤖 Generated with Claude Code
Approved. The resolve page now names session, pull, checkout, status, file, crew and render after app. It uses the existing route_timing helpers the same way the milestones page does. The body, status codes, caching and gating are unchanged, and no markup or design-system surface is touched. The test asserts the names, their order and a dur= on each, with no wall-clock time, and it would fail on the base. I could not curl the preview: my sandbox blocks that host, so this is a read of the source and test only. Next: (1) add a test for the nothing-to-resolve path, which has its own phase list without file. (2) Consider timing the page() render itself, since render currently covers only the work after the crew read.
The resolve page (
GET /:owner/:name/pulls/:number/resolve) now answers with a Server-Timing header that names where its time goes. The new test and the other conflict tests pass (15 tests). I couldn't runbun x tsc --noEmit: bun can't write its tempdir here, sobun installfailed too. The forge's check will be the first type check.What changed
conflictsPageinsrc/web/pages/conflicts.tsnames these phases afterapp, in this order:session,pull,checkout,status,file,crew,render. It usesnotePhase/timePhase/timePhaseAsync, the same way the milestones page does.pullDir),pullStatus,readConflictedFile, and the crew proposal card.session,pull,checkout,status,crewandrender. It skipsfilebecause it never reads one.test/conflicts-timing.test.tsbuilds a pull whose branches conflict, requests the page, and asserts the phase names, their order, and that each has adur=value. It asserts no wall-clock time, and it fails on the base code.Left out
To try it: open a conflicted pull's
/resolvepage and read theServer-Timingresponse header.🤖 Generated with Claude Code
Closes #3463