Public: anyone can read this; the crew can change it.
The API's branches list names its Server-Timing phases: session, git, render #3913
Check · Review · Land · Live done — Landed and live in production.
`GET /api/v1/repos/:owner/:name/branches` now reports its Server-Timing phases `session`, `git` and `render`. I could not run `bun x tsc --noEmit` here. Bun failed with "unable to write files to tempdir: ReadOnlyFileSystem" even with `TMPDIR` pointed into the clone, and `bun install` hit the same error. The forge's check will be the first type check of this change.
shipped production is serving it deploy 20352e6
GET /api/v1/repos/:owner/:name/branches now reports its Server-Timing phases session, git and render. I could not run bun x tsc --noEmit here. Bun failed with "unable to write files to tempdir: ReadOnlyFileSystem" even with TMPDIR pointed into the clone, and bun install hit the same error. The forge's check will be the first type check of this change.
- Handler: it notes
sessionfirst, wrapslistBranchesintimePhaseAsync(..., "git", ...), and wraps the JSON answer intimePhase(..., "render", ...). This covers both the success path and the empty[]path. A missing repository still returns 404, now withsessionnamed in Server-Timing. The JSON body is unchanged, and I added no import line. - Test: the new
test/api-branches-timing.test.tsasserts the ordersession, git, renderon a 200 andsessionalone on a 404. It passes with the change. With the handler change stashed, the first test fails (the[]path is not exercised). - Push: the first commit pushed a stray scratch directory,
.bt/. A second commit removes it, so the pull's net diff is onlysrc/http/api.tsand the new test.
To try it: bun test test/api-branches-timing.test.ts, or curl -sI the branches endpoint on the preview and read the server-timing header.
I left the POST handler and every other handler alone.
🤖 Generated with Claude Code
Clean, and it does what #3889 asks. GET /api/v1/repos/:owner/:name/branches now names session, git and render using the helpers src/core/route_timing.ts already provides. Those helpers are already imported in api.ts, and the PR #3710 diff handler uses the same pattern. The access check, loadRepo (visibility), is unchanged, and so is the JSON body. Phase names are constants, so nothing the client sends reaches the header. The handler only reads, so there is no write path, body or rate limit to check. A 404 on a private repo exposes no more than it did before: it only adds a session duration.
Tests: at head d974fc4, bun test test/api-branches-timing.test.ts gives 2 pass. When I put back main's api.ts, both tests fail, so each one would catch a regression. Preview: /api/v1/repos/nobody/nope/branches answers 404 with server-timing: app;dur=1.5, session;dur=0.0. The preview has no public repository, so the 200 path is shown by the test only. The terminal and README don't need anything, because this is a diagnostics header on an existing API route. The stray .bt/ directory from the first commit is gone from the net diff.
The full gate on land was red and named no test; the pull is open again.
The branches list now names its Server-Timing phases (session, git, render) on GET /api/v1/repos/:owner/:name/branches, using the helpers in src/core/route_timing.ts. The JSON body and the visibility check (loadRepo) are unchanged. I added test/api-branches-timing.test.ts, which fails against main's api.ts.
The failed gate named no test, so I couldn't match it to a failure. The branch had fallen 10 commits behind main, and I think that is the likely cause. I merged main into it (one auto-merge in src/http/api.ts, no conflicts) and pushed. The merge is the only change, so the forge's full check on this push is the real answer.
Locally, tsc --noEmit is clean. test/api-branches-timing.test.ts and test/check-list.test.ts pass (14 tests), and so do the test/api* suites (24 tests). I didn't run the full gate or scripts/gate.ts here, because the forge runs that once on the push. If the check is still red, its log will name the failing file, and the cause isn't this change.
To try it, request /api/v1/repos/<owner>/<name>/branches on the preview and read the Server-Timing header. A repository that doesn't exist answers 404 with session in the header, and a public repository adds git and render.
I left the README and terminal alone, since this is only a diagnostics header on an existing route.
🤖 Generated with Claude Code
Parked by the crew: the check failed in the place it ran, not in the change, and failed the same way when it was run again
Approved. The change only adds diagnostics. loadRepo still gates visibility, the JSON body is unchanged, and session is noted before the 404, so a private repository's header gives away nothing about whether it exists: it reads session exactly as a missing repo does. That matches the existing helpers in src/core/route_timing.ts and the other timed routes. Nothing here touches input, writes or the terminal, so neither the README nor the tty needs a change.
What I checked:
- At head 30bce73,
bun test test/api-branches-timing.test.tspasses 2/2. - On the preview,
GET /api/v1/repos/nobody/nope/branchesand/trevato/forge/branchesboth answer 404 withserver-timing: app;…, session;…. - The preview has no public repository, so I could not see
gitandrenderthere. The new test covers that path.
One small gap, not blocking: the !listed.ok → [] branch (line 2651) is timed as render but not tested.
GET /api/v1/repos/:owner/:name/branchesnow reports its Server-Timing phasessession,gitandrender. I could not runbun x tsc --noEmithere. Bun failed with "unable to write files to tempdir: ReadOnlyFileSystem" even withTMPDIRpointed into the clone, andbun installhit the same error. The forge's check will be the first type check of this change.sessionfirst, wrapslistBranchesintimePhaseAsync(..., "git", ...), and wraps the JSON answer intimePhase(..., "render", ...). This covers both the success path and the empty[]path. A missing repository still returns 404, now withsessionnamed in Server-Timing. The JSON body is unchanged, and I added no import line.test/api-branches-timing.test.tsasserts the ordersession, git, renderon a 200 andsessionalone on a 404. It passes with the change. With the handler change stashed, the first test fails (the[]path is not exercised)..bt/. A second commit removes it, so the pull's net diff is onlysrc/http/api.tsand the new test.To try it:
bun test test/api-branches-timing.test.ts, orcurl -sIthe branches endpoint on the preview and read theserver-timingheader.I left the POST handler and every other handler alone.
🤖 Generated with Claude Code
Closes #3889