feat: count shell fetches as docs activation, read Codex's web_search action - #130
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
AI-958 Investigate incomplete Codex web search / docs activation results
Motivation: Changelog content activation is suspiciously low. Initial research suggests that Codex's web search tool masks which underlying pages it read content from which might be under-representing it in the content-ful docs activation results. |
…vestigate-incomplete-codex-web-search-docs-activation # Conflicts: # apps/web/src/App.tsx
web_search action
Rodriguespn
left a comment
There was a problem hiding this comment.
LGTM. We discussed offline the details of this so I'm in the loop. Nice catch and thkx for taking care of this
barryroodt
left a comment
There was a problem hiding this comment.
For the sake of completeness, I had my agent run a thorough review on this, all feedback below, along with the inline comments, is a result of that run.
Nice direction, though the shell heuristic still miscounts a few common cases, all in the direction that moves the number this PR exists to make accurate.
echo "run curl https://supabase.com/changelog.md next"records a page read withhasContent: true. The wordcurlanywhere in the segment is enough.curl -fsSL <changelog> 2>/dev/null | head -50records nothing at all.- A 404 counts as a read, since curl without
-fexits 0 and the error body lands inresult.
Left those inline with the details. A regression test for each would be the useful part, more than the specific fix.
Separately on the results: they look re-run rather than re-scored. 71 of 190 rows differ, 53 of those changed a run-level field like attempts or checks, search_docs moved 146 to 142 even though this PR doesn't touch that branch, and 7 rows flipped pass/fail. Nothing wrong with re-running, just worth a line in the description so nobody reads those flips as effects of this change.
One structural thing I'd like your take on, and I think it's fine as a follow-up: the Codex action handling lives in docs-results.ts even though that module is meant to stay agent-agnostic.
Yep, that's just a byproduct of refreshing results on the PR w/ nondeterminism. All good. |
Agreed it's not ideal, I'm okay leaving it for now because this doesn't affect the persisted results shape, and can be simplified by using the existing normalized |
…vestigate-incomplete-codex-web-search-docs-activation # Conflicts: # apps/web/src/data/eval-results.json
A curl without -f/--fail exits 0 on a 4xx/5xx, so its output landing in `result` doesn't prove the page was actually read. wget doesn't need the same check since it already fails on HTTP errors by default.
isSupabaseUrl (any *.supabase.com subdomain) and isSupabaseDocsUrl (apex host only) disagreed on whether a service subdomain like mcp.supabase.com counts as a read, depending on which tool channel reported it. Consolidate on the stricter apex-only check everywhere.
Keeps scorers/judges seeing the same truncated result the agent did, instead of the full rehydrated content meant only for docs metrics. Also checks the truncation stub before running the shell-fetch regex scan, skipping that work for the common non-truncated case.
A stderr-only redirect (2>/dev/null, 2>&1) was tripping the same "output redirected" check as a real stdout redirect, dropping curl fetches like `curl ... 2>/dev/null | head` entirely even though the page body still reaches the model.
Matching /\bcurl\b/ anywhere in a shell segment counted a mere mention of the word (e.g. `echo curl https://supabase.com/changelog.md`) as a page read. Anchors curl/wget to the segment's leading command instead, unwrapping `bash/sh/zsh -c "..."` wrappers first so a fetch piped inside one of those still resolves correctly.
Changes how we track docs activation for Codex:
curlandwget -O -are now counted as docs calls (with content)web_searchtool'sactionpayload is now used to determine whether the model opened a page, instead of inferring this based on a URL-shapedqueryhasContentis undefined are rendered with a distinct question mark instead of falling back to looking like content-ful callsExample of the new
SHELLdocs activation tracking in the "cli 001: bootstrap app" eval run from the preview app:Another example where the
hasContentcouldn't be determined:Motivation
Our skill tells agents to fetch
https://supabase.com/changelog.mdand in several of our runs, Codex achieves this withcurlwhich we're not currently counting. For comparison, Claude Code usesWebFetchwhich is counted.This change aims to more accurately count changelog reads, among other docs pages.
The
web_searchchange is less important, but still a technical accuracy thing for how we count page reads in Codex.What's counted
This only counts commands that write page content to stdout, since we can generally trust that means the content was added to context. It counts
supabase.comdomains only, excluding service subdomains.resultCharsis measured after whatever the agent piped the response through, so it counts what reached the model rather than the size of the whole page. If the command has ambiguous output, we treathasContentas undefined.It doesn't count commands that don't direct to stdout (e.g. downloading a page and then reading it from filesystem). The reasoning is that it's harder to reliably track this, as there's tons of ways that our heuristics might be inaccurate. We also don't see evidence of this happening in practice to justify the effort. We can revisit that sort of tracking once we notice it impacting results.
See tests cases for more context on what's counted vs excluded.
Impact on transcript and UI
This adds a
shell_fetchtype toDocsCall.sourcesimilar to existing MCPseach_docsand harnessweb_fetchandweb_searchsources.In this UI this appears as a
SHELLchip tagged on the docs call. I label it as such since it represents multiple possible shell fetch strategies, but if desired we could split into the specific binary likeCURL,WGET, etc.Shell invocations that mix multiple commands w/o piping are counted as docs calls but with
hasContentundefined, since we can't be sure what content was printed to stdout as context. Those now render distinctly in the UI from known content-ful or content-less calls.On
web_search.actionchangeNote that although this PR starts reading Codex's
web_search.actionpayload, there's a bug in Codex preventing this helping to its full potential. Similar to this fixed issue, there's inconsistency in theactioncasing between validation (camelCase vs. snake_case) that causes theopen_pageaction (or any multi-word action) to fall back toother.You can see this in practice by running:
We can consider opening an issue in the Codex repo, and for now this change is a guard for if/when that validation issue gets fixed.
Nonetheless, the other
actionfalls back to the existing URL-shaped query heuristic, so it's not regressing our results.I've updated results for the Codex experiments on this PR, I didn't refresh other harnesses since I haven't observed them using shell to fetch web pages thusfar.
Closes AI-958