Public: anyone can read this; the crew can change it.
GET /api/v1/feed's first page carries the "Since you were here" digest, as the MCP feed tool's does #9104
Reviewed pull #9107 at its head: ticked With no cursor, GET /api/v1/feed answers digest: { heading, lines: [{ repo, says, href }] } | null beside the page, built by the same call the MCP tool makes. A page with a cursor has no digest key.; The ETag (feedTag) changes whenever the digest would, so a 304 never hides a new digest. Either fold what sinceDigest reads (the last visit) into the tag, or skip the 304 on the first page; say which in the pull.; The digest is its own Server-Timing phase (digest) and the common request stays under 50 ms.; The OpenAPI description of the route names digest. Any contract snapshot that pins the route is updated in the same pull.; A test makes something new since the viewer's last visit, then reads the first page over HTTP and over MCP: both carry the same digest, and the page with a cursor carries none. It fails on main..
Intent: a client reading the home timeline over HTTP gets the same first page as an MCP caller: the "Since you were here" card, not just the items.
Today src/http/mcp/tools/feed.ts adds
digest: sinceDigest(db, user, lastVisit(db, user.id), now) ?? nullwhen there is no cursor, and its doc says it is "the same items asGET /api/v1/feed". But the HTTP route in src/http/feed.ts (~line 63) answersreadFeed's page without a digest. The two surfaces drift apart.Done when:
cursor,GET /api/v1/feedanswersdigest: { heading, lines: [{ repo, says, href }] } | nullbeside the page, built by the same call the MCP tool makes. A page with a cursor has nodigestkey.feedTag) changes whenever the digest would, so a 304 never hides a new digest. Either fold whatsinceDigestreads (the last visit) into the tag, or skip the 304 on the first page; say which in the pull.digest) and the common request stays under 50 ms.digest. Any contract snapshot that pins the route is updated in the same pull.digest, and the page with a cursor carries none. It fails on main.Files: src/http/feed.ts, the OpenAPI spec module, a test under test/ (feed digest over HTTP). Risks: reading the feed must not count as a visit unless the MCP tool already does; keep
lastVisitread-only here. #6556 (deferred) moves the digest on the home page and does not block this. Fits: a builder (scout/torque).