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

The explorer's kind and freshness chips narrow the list through the query string, server-rendered #11332

Merged opened this

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

Merged

Most of this was already built, so the change is small: `since` now works as another name for the existing `updated` window on both the page and the MCP `explore` tool. I tested it; I didn't run the design lint or the gate script.

shipped production is serving it deploy 0b060c6

opened this

Most of this was already built, so the change is small: since now works as another name for the existing updated window on both the page and the MCP explore tool. I tested it; I didn't run the design lint or the gate script.

What was already there. /explore already took kind, sort, updated, owner and archived as query parameters. The kind and freshness controls were already plain server-rendered links showing their active state, with no client JavaScript. The MCP tool already took the same words as separate arguments.

What changed.

  • since is now read as updated in exploreLineFrom (src/actions/explore.ts). /explore?kind=app&since=7d works. The MCP tool has a since argument, with a one-line note in its description and in docs/MCP.md.
  • A new test in test/explore-url.test.ts covers since on the page and the 422 on a bad value.
  • explore-url, explore-mcp-q and mcp-size pass and tsc is clean. I did not raise any size ceiling.

What I left alone.

  • An unknown value still returns 422, not the 400 the issue names. Existing tests (explore-parity, explore-unknown-words, explore-url) and the API already treat 422 as the contract for unknown filters, so I kept one status everywhere. Moving all of it to 400 is a separate decision for you.
  • The chips still emit updated= in their links, since the existing URL tests pin it. since is accepted on input only.
  • I did not add a timing test. The page's existing timing tests cover the request path, but I did not measure the 50 ms budget for the filtered view.

Push note. The forge's pre-push hook required a "Try:" commit, so the branch has an extra empty commit for that.

How to try it. Open /explore?kind=app&since=7d. /explore?since=9y returns 422 naming 1d, 7d, 30d.

Closes #11232

commented

Most of this was already built, so the change is small: since now works as another name for the existing updated window on both the page and the MCP explore tool. I tested it; I didn't run the design lint or the gate script.

What was already there. /explore already took kind, sort, updated, owner and archived as query parameters. The kind and freshness controls were already plain server-rendered links showing their active state, with no client JavaScript. The MCP tool already took the same words as separate arguments.

What changed.

  • since is now read as updated in exploreLineFrom (src/actions/explore.ts). /explore?kind=app&since=7d works. The MCP tool has a since argument, with a one-line note in its description and in docs/MCP.md.
  • A new test in test/explore-url.test.ts covers since on the page and the 422 on a bad value.
  • explore-url, explore-mcp-q and mcp-size pass and tsc is clean. I did not raise any size ceiling.

What I left alone.

  • An unknown value still returns 422, not the 400 the issue names. Existing tests (explore-parity, explore-unknown-words, explore-url) and the API already treat 422 as the contract for unknown filters, so I kept one status everywhere. Moving all of it to 400 is a separate decision for you.
  • The chips still emit updated= in their links, since the existing URL tests pin it. since is accepted on input only.
  • I did not add a timing test. The page's existing timing tests cover the request path, but I did not measure the 50 ms budget for the filtered view.

Push note. The forge's pre-push hook required a "Try:" commit, so the branch has an extra empty commit for that.

How to try it. Open /explore?kind=app&since=7d. /explore?since=9y returns 422 naming 1d, 7d, 30d.

commented

The check failed because the generated tool table in docs/MCP.md was stale after my change to the explore tool's description. I ran bun scripts/mcp-table.ts to regenerate it. test/mcp-table.test.ts and test/mcp-size.test.ts now pass (12 tests), and the fix is committed and pushed. I did not re-run the full check here.

The pull is otherwise unchanged:

  • since: it is accepted as another name for updated on /explore and on the MCP explore tool.
  • Unknown values: they still return 422, not 400, because the existing tests and the API already use 422.
  • Chips: they still emit updated= in their links.

To try it, open /explore?kind=app&since=7d.

Changes requested — before the latest push

No security finding: since is length-capped and goes through the same validation as updated. Two misses against the issue:

  1. Unknown values still return 422, but box 1 says 400 naming the valid ones. Either return 400 on /explore and the MCP explore tool, updating explore-parity, explore-unknown-words and explore-url, or get the issue text amended by a person. Fix this first.
  2. Box 4 asks for a test per filter that fails without it and for an answer under 50 ms. The only new test covers the since alias. Add a test that kind=app|forge|person and since=7d|30d each narrow the list (the result set differs from the unfiltered one). Add a timing assertion on the filtered view.

Smaller points: the chips still emit updated=, while the issue names since= as the chip URL. Either emit since= or say why not in the issue. The MCP since schema has maxLength 10 while its siblings use 100. The MCP test only covers the page; add one that calls the tool with since.

commented

I've addressed the review points on this pull and pushed. The explore tests, mcp-size, mcp-table, web-ui, search-note and tsc all pass here. I did not re-run the full check.

  • 400, not 422. An unknown filter value now returns 400 on /explore and GET /api/v1/explore, still naming the valid words. The MCP tool already returned an error for it. I updated explore-parity, explore-unknown-words and explore-url to match. I also updated docs/features/explore.md, which still said 422 and updated=.
  • Chips emit since=. exploreParams now writes since. updated= is still read as an alias. When both are given, updated wins, and a test pins that.
  • Schema. The MCP since argument now has maxLength: 100, like its siblings.
  • Per-filter tests. In test/explore-url.test.ts, kind=app, kind=person, kind=forge, since=7d and since=30d each give a different list from the unfiltered one.
  • Filtered-view timing. The same test asserts that three filtered views each answer in under 50 ms.
  • MCP test. test/explore-mcp-q.test.ts now calls the tool with since. 7d narrows the list, and 9y is an error naming 1d, 7d, 30d.

The since tests only prove the window drops rows when nothing has shipped. The existing updated: test in test/explore.test.ts covers rows that did ship.

commented

The explorer's kind and freshness chips now come with a test that bounds the filtered view by work done, not by time. The check failed because my test used a wall-clock bound. It timed /explore?kind=app&since=7d and two other filtered URLs and asserted each took under 50 ms. The repo's rules reject raw clock budgets in tests.

I replaced the clock with a count of SQL statements per request (expectWork and requestStatements from test/helpers/work.ts), capped at 40 per request. I picked 40 as a loose ceiling and did not measure the actual count first, so it would catch an N+1 but is not tight. I also renamed the test to say "costs few statements".

Only test/explore-url.test.ts changed. It passes (8 tests), bun scripts/gate.ts and bun x tsc --noEmit are clean, and I pushed. I did not run the full suite; the forge will run the full check on this push.

Pull description: The explorer gets kind and freshness chips that link with since=. An unknown filter now returns a 400. The MCP tool table is regenerated. Tests cover each kind and each window, and a filtered view's cost is bounded by statement count. To try it, open /explore?kind=app&since=7d.

Approved

Earlier asks met: unknown filters are now 400 on the page and API (docs and tests moved with them); chips emit since= with updated= kept as an alias; the MCP since argument has maxLength 100; there are per-kind and per-window tests; the filtered views are bounded by statement count instead of a clock. No new security surface: since goes through the same validation and escaping as updated. No design change beyond the link query. Non-blocking: the 40-statement ceiling is loose, so measure the real count and tighten it. Non-blocking: the box asks for a 50 ms answer, and the test bounds work, not time.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs