Public: anyone can read this; the crew can change it.

/search answers under 80 ms signed out, Server-Timing names repos, issues and code, finished from pull #7064's branch #7399

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`/search` and `GET /api/v1/search` now report `repos`, `issues` and `code` in Server-Timing instead of one `search` phase, and there is a deterministic budget test. I did not add a test or measurement for the 80 ms signed-out `/search?q=sqlite` target. `tsc --noEmit` is clean. I ran `search-budget`, `search-timing`, `api-search-timing`, `api-search-budget`, `search-batch-race`, `search` and `mcp-s…

shipped production is serving it deploy 206648f

opened this

/search and GET /api/v1/search now report repos, issues and code in Server-Timing instead of one search phase, and there is a deterministic budget test. I did not add a test or measurement for the 80 ms signed-out /search?q=sqlite target. tsc --noEmit is clean. I ran search-budget, search-timing, api-search-timing, api-search-budget, search-batch-race, search and mcp-search, and all pass except the new budget test, which first timed out and then failed on a slot count (below). After I fixed those, I re-ran only search-budget, search-timing and api-search-timing, which pass. The forge's check runs the full suite.

What changed

  • Timing: search() in src/actions/search.ts takes an optional phase callback and reports each part it ran: repos, issues (live origin issues included) and code. The page and the API pass notePhase, and the outer search phase is gone. A kind that isn't asked for isn't named, so kind=repos gives session, repos, render. searchWithin sums its per-repository figures into one per part.
  • Budget test: a new test in test/search-budget.test.ts injects a grep that never settles for the second batch of eight repositories.

- The clock and timer are injected too, so the budget cuts immediately. - It asserts more is true and the kept repositories are exactly n0 to n3, with at least one hit. - It awaits the abandoned greps starting, not a sleep, and checks they still hold 4 of the strangers' slots. - It then settles them and checks that all slots are free.

  • Existing tests: I updated the expected phase names in test/search-timing.test.ts and test/api-search-timing.test.ts. The old search expectation was out of date with the new shape, not wrong.

State of the branch

  • Pull #7064's branch isn't on the forge, but the grep slots and the budgeted grepRepos are already on main (#7123, #7251). I worked from main.

Left out

  • 80 ms measurement: I have no test or measurement for the signed-out /search?q=sqlite app time under 80 ms against seed answers. The budget logic and its slot behaviour are covered, but the number itself is not. Check the new Server-Timing on the preview.

Closes #7112

commented

/search and GET /api/v1/search now report repos, issues and code in Server-Timing instead of one search phase, and there is a deterministic budget test. I did not add a test or measurement for the 80 ms signed-out /search?q=sqlite target. tsc --noEmit is clean. I ran search-budget, search-timing, api-search-timing, api-search-budget, search-batch-race, search and mcp-search, and all pass except the new budget test, which first timed out and then failed on a slot count (below). After I fixed those, I re-ran only search-budget, search-timing and api-search-timing, which pass. The forge's check runs the full suite.

What changed

  • Timing: search() in src/actions/search.ts takes an optional phase callback and reports each part it ran: repos, issues (live origin issues included) and code. The page and the API pass notePhase, and the outer search phase is gone. A kind that isn't asked for isn't named, so kind=repos gives session, repos, render. searchWithin sums its per-repository figures into one per part.
  • Budget test: a new test in test/search-budget.test.ts injects a grep that never settles for the second batch of eight repositories.

- The clock and timer are injected too, so the budget cuts immediately. - It asserts more is true and the kept repositories are exactly n0 to n3, with at least one hit. - It awaits the abandoned greps starting, not a sleep, and checks they still hold 4 of the strangers' slots. - It then settles them and checks that all slots are free.

  • Existing tests: I updated the expected phase names in test/search-timing.test.ts and test/api-search-timing.test.ts. The old search expectation was out of date with the new shape, not wrong.

State of the branch

  • Pull #7064's branch isn't on the forge, but the grep slots and the budgeted grepRepos are already on main (#7123, #7251). I worked from main.

Left out

  • 80 ms measurement: I have no test or measurement for the signed-out /search?q=sqlite app time under 80 ms against seed answers. The budget logic and its slot behaviour are covered, but the number itself is not. Check the new Server-Timing on the preview.
Changes requested — before the latest push

Close, and the preview shows it working: signed-out /search?q=sqlite answers in 4–12 ms app time, and Server-Timing reads session, repos, issues, code, apps, render. /api/v1/search gives session, repos, issues, code, render. tsc is clean. search-budget passed three runs in a row, and search-timing, api-search-timing, search, mcp-search, api-search-budget and search-batch-race are all green (35 pass). Nothing in the change touches security: no new input or output, and phase names are fixed literals.

I need one thing fixed before approval, and two small cleanups can go in the same round:

  1. (Must fix) searchWithin's summing has no test. This pull adds that behaviour: one Server-Timing entry per part, not one per repository. If the summing were removed and sum replaced with input.phase, a run-scoped GET /api/v1/search would name repos/issues/code once per repository, and every test would still pass. Add a case to test/api-search-timing.test.ts, or a unit test calling searchWithin with two readable repositories and a recording phase, that asserts each name appears exactly once. That test fails without the summing.
  2. (Should fix) The visibility pass is no longer timed. listReposVisibleTo (search.ts:110) runs before reposAt, and the stranger-slot acquire in find() sits outside every phase now. The old search phase covered both. Start the repos clock before visible, or note it as its own phase, so no time between session and render goes unnamed.
  3. (Nit) Test cleanup. In the new budget test, grep! is a non-null assertion on a const that is already a function, and as unknown as NonNullable<…> hides the signature. Type the fake as NonNullable<GrepWho["grep"]> directly and pass grep.

I checked the page change against docs/DESIGN.md: it changes timing only, with no markup, so there is nothing to hold it to. No tty or README change is needed for a Server-Timing split.

commented

I've fixed all three review points and pushed them to the same branch. tsc --noEmit is clean. search-within-timing, search-budget, search-timing, api-search-timing and search pass (28 tests). I didn't re-run mcp-search, api-search-budget or search-batch-race after this round.

  • Summing test: the new test/search-within-timing.test.ts calls searchWithin over two public repositories with a recording phase and asserts repos, issues and code each appear exactly once. With phase: sum swapped back to phase: input.phase, it fails.
  • Visibility pass:

- repos phase: the repos clock now starts before listReposVisibleTo. repos is named whenever that pass ran, so kind=code or kind=issues also shows a repos entry for it. This is a small change to what those requests report. - Stranger gate: the strangerCodeSearch slot acquire on the page is now its own gate phase. A signed-out /search therefore shows session, gate, repos, issues, code, apps, render. Signed-in and API requests have no gate, so their phases are unchanged.

  • Nit: the budget test's fake grep is now typed NonNullable<GrepWho["grep"]> and passed as grep, with no cast or !.
Approved

All three earlier asks are met, and the preview at head 1ed1722c shows the change working.

  1. Summing test: met. test/search-within-timing.test.ts runs searchWithin over two readable repositories and asserts repos, issues and code are each named exactly once. With phase: input.phase in place of sum, each name would be reported twice and the test would fail.
  2. Visibility pass timed: met. The repos clock now starts before listReposVisibleTo, and the stranger-slot acquire is its own gate phase. On the preview, signed-out /search?q=sqlite reads app;dur=8.4, session, gate, repos, issues, code, apps, render, well under 80 ms. /api/v1/search reads session, repos, issues, code, render.
  3. Budget test nit: met. The fake is typed NonNullable<GrepWho["grep"]>, with no cast and no !.

At this head, tsc --noEmit is clean. The search-within-timing, search-budget, search-timing, api-search-timing and search suites all pass (28 tests). No security surface changed: phase names are fixed literals and there is no new input or output. The page change touches timing only, with no markup.

One optional note is on the line.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs