-
Notifications
You must be signed in to change notification settings - Fork 1
review: replace the Claude Agent SDK harness with Pi, and sandbox tool subprocesses with srt #305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
jwbron
wants to merge
20
commits into
main
Choose a base branch
from
jwies/review-pi-harness-seam
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
d62a33b
[jwies/review-pi-harness-seam] review: add a Pi-backed sub-agent harn…
jwbron a265267
[jwies/review-pi-harness-seam] review: test the Pi tool-surface bound…
jwbron 5abe6e3
[jwies/review-pi-harness-seam] review: remove the Claude Agent SDK ha…
jwbron fae24c9
[jwies/review-pi-harness-seam] review: run every reviewer tool subpro…
jwbron ea141d5
[jwies/review-pi-harness-seam] review: resolve model pins to dated re…
jwbron 64bbe0b
[jwies/review-pi-harness-seam] review: restore sub-agent retries, nam…
jwbron aca1595
[jwies/review-pi-harness-seam] review: pin the sandbox policy in a te…
jwbron 9eb19b0
Merge branch 'main' into jwies/review-pi-harness-seam
jwbron 63626ae
[jwies/review-pi-harness-seam] review: split the per-agent dispatch m…
jwbron 46b33a8
[jwies/review-pi-harness-seam] review: prove the production tool surf…
jwbron 2e0952b
[jwies/review-pi-harness-seam] review: a harness probe for the findin…
jwbron cb88a31
[jwies/review-pi-harness-seam] review: install ripgrep for srt, which…
jwbron d18b664
[jwies/review-pi-harness-seam] review: unblock bwrap on the runner, a…
jwbron 284f4a5
[jwies/review-pi-harness-seam] review: make the smoke exit, and put a…
jwbron a6d96bc
[jwies/review-pi-harness-seam] review: give the harness probe a dispa…
jwbron f7754f6
[jwies/review-spend-ceiling] review: fix the harness probe's scoring …
jwbron 149b211
[jwies/harness-probe-fix] review: make the eval exit, and stop a prob…
jwbron 8b46909
[jwies/review-pi-docfix] review: state the real reason the Pi tools a…
jwbron 3393ae2
[jwies/review-pi-tool-surface] review: trim the tool surface to Read/…
jwbron 1845b88
[jwies/review-pi-harness-seam] review: close the Pi-seam review feedb…
jwbron File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| --- | ||
| "review": minor | ||
| --- | ||
|
|
||
| review: make the Pi runner the only sub-agent harness and remove the Claude | ||
| Agent SDK runner | ||
|
|
||
| Scripted dispatch now runs every sub-agent through the Pi-backed runner | ||
| (`lib/dispatch-runner-pi.ts`, built on `@earendil-works/pi-ai` + | ||
| `@earendil-works/pi-agent-core`). The Claude Agent SDK runner | ||
| (`lib/dispatch-runner.ts`) is deleted, along with the | ||
| `REVIEW_DISPATCH_RUNNER` selection seam; a leftover `REVIEW_DISPATCH_RUNNER` | ||
| setting now fails the run loudly instead of silently selecting a harness that | ||
| no longer exists. `@anthropic-ai/claude-agent-sdk` leaves the dependency tree | ||
| entirely, and `zod` is no longer a direct dependency (it stays in the lockfiles | ||
| transitively, via pi-ai / sandbox-runtime / mcp-sdk). | ||
|
|
||
| The removal is grounded in the re-anchoring harness A/B (run 30666183461): | ||
| two full-corpus repeats with identical model pins and byte-identical | ||
| review.md showed arm-to-arm quality parity (recall 41/46 vs 40/46 and 40/46 | ||
| vs 41/46, verdict agreement 32/35 vs 33/35 both repeats, comparable | ||
| investigation depth by tool-call count) with the Pi arm at roughly half the | ||
| cost (1.78x and 1.94x) and 60% of the wall clock (1.65x both repeats). | ||
|
|
||
| No model pin changes. The pins still resolve through Pi's Anthropic catalog | ||
| (`resolveModelId`), which throws on an unknown pin rather than silently | ||
| substituting. Pi reports usage with a per-component `cost` breakdown, so | ||
| `AgentResult.usd` no longer inherits the api-proxy default-pricing path's | ||
| cache-write under-count. | ||
|
|
||
| The corpus recall figures, noise bands, and drift budget measured on the SDK | ||
| loop era do not transfer numerically; the re-anchoring run above is the | ||
| reference point for Pi-harness numbers going forward. | ||
|
|
||
| Two posture details the SDK runner used to own and the Pi runner now owns | ||
| explicitly. Sub-agent turns retry transient provider failures twice: pi-ai | ||
| does not read `ANTHROPIC_MAX_RETRIES` (it calls the Anthropic SDK with | ||
| `maxRetries: 0` and defaults its own retry helper to 0), so the runner passes | ||
| the budget itself; without it one 429/529 on any turn sheds a whole review | ||
| lens. And hitting the turn cap now reports `stopReason=max_turns` instead of | ||
| looking like a clean free-text finish, so the single contract-parse retry | ||
| tells an out-of-turns agent to conclude rather than correcting a JSON shape | ||
| that was never the problem. | ||
|
|
||
| Every reviewer tool subprocess now also runs inside an OS sandbox | ||
| (`@anthropic-ai/sandbox-runtime`, the engine behind Claude Code's own | ||
| sandbox: bubblewrap on Linux, Seatbelt on macOS): the checkout is mounted | ||
| read-only (the one writable staging path is the investigation-cap journal, | ||
| plus a scratch dir), and tool-level network is denied outright. In | ||
| production this stacks inside the awf firewall; in the eval, which runs on a | ||
| bare runner VM, it is the only boundary the tools have, and the A/B workflow | ||
| now installs bubblewrap+socat for it. Sandbox initialization is fail-closed: | ||
| if it cannot start (bubblewrap missing, user namespaces blocked in a nested | ||
| container), dispatch refuses to run rather than silently degrading; | ||
| `REVIEW_SANDBOX=off` is the explicit, logged escape hatch that restores the | ||
| pre-sandbox posture. | ||
|
|
||
| One consequence of that network denial, caught by the new sandbox smoke job | ||
| before it could reach a consumer: the sub-agent prompts used to run the | ||
| investigation cap as `npx -y tsx workflows/review/lib/investigation-cap.ts`, | ||
| and inside the sandbox npx cannot resolve tsx (the registry is denied; `npx | ||
| --offline` fails with ENOTCACHED even after the cache is warmed, and tsx | ||
| itself cannot start there at all because it opens a unix socket, which | ||
| bubblewrap refuses with EPERM). Every cap request would have failed, and the | ||
| prompt's own fallback for a denied budget is "stop investigating and report | ||
| what you have" — bounded investigation would have gone quietly inert. The | ||
| prompts now invoke it as `node | ||
| --disable-warning=MODULE_TYPELESS_PACKAGE_JSON | ||
| workflows/review/lib/investigation-cap.ts`, which works on the node 24 the | ||
| agent job already pins (native type stripping). Because type stripping | ||
| reparses the file as ESM, the CLI's entry guard is now argv-based rather than | ||
| `require.main === module` (which never fires under ESM and would have turned | ||
| every cap request into a silent no-op success), and `node:fs` is a static | ||
| import. Two constraints on that file follow: its imports stay type-only or | ||
| node: builtins, and it is invoked with `node`, never `tsx`. | ||
|
|
||
| New in the A/B workflow: a `sandbox-smoke` job that exercises the PRODUCTION | ||
| tool surface under srt, which the measured arms deliberately do not (they stay | ||
| on Read/Grep/Glob so the corpus calibration holds). Its boundary probes run | ||
| through the same `createToolExec()` the production runner calls and assert | ||
| each of read-the-checkout, write-the-checkout, the cap journal via the real | ||
| CLI, the scratch dir, and outbound TCP lands on the policy's side; they cost | ||
| nothing and are the hard gate. A second phase dispatches one live case on the | ||
| full tool surface to prove the loop reaches Bash at all. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| --- | ||
| "review": minor | ||
| --- | ||
|
|
||
| review: trim the sub-agent tool surface to Read/Grep/Bash, and window Read | ||
|
|
||
| Two tools leave `createReviewTools`, raised in review on #305: LS wrapped | ||
| `ls -la` verbatim and added nothing over sandboxed Bash, and Glob's | ||
| `find -path` emulation was wrong rather than merely limited (`*` matched | ||
| across `/`, so a reviewer asking for `src/*.ts` silently received nested | ||
| files too). Directory listing and file finding go through Bash, where the | ||
| model owns the semantics of its own command. Every tool runs through the | ||
| same sandboxed executor, so the named tools that remain earn their place on | ||
| model ergonomics, not containment: Read for windowed, line-numbered file | ||
| views, Grep because structured params avoid the shell-quoting failure class. | ||
|
|
||
| Read gains `offset`/`limit` windowing. Previously a large file was silently | ||
| truncated at the output cap and its tail was unreachable, a recall defect; | ||
| the window keeps `cat -n` line numbers so findings still anchor on real | ||
| lines, and a partial view says which lines of how many it shows. | ||
|
|
||
| The eval's measured arms now run this production surface unrestricted | ||
| (previously they were pinned to Read/Grep/Glob, a surface production never | ||
| ran), so the A/B measures what production ships, by construction. The | ||
| re-anchoring run for the new surface is on the PR. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note (non-blocking): harness-probe job + eval/harness-probe.ts are shipped here but framed by the description as future follow-up, not delivered work. The body's only reference to the dm-default-backfill loss is "One follow-up owed before the model question" and "Sequencing from here" item 3 ("after the dm-default-backfill transcript read"), i.e. future work; neither the body nor the changeset states this PR adds the probe tooling/job to do it. No linked Jira/Confluence ticket key is present in the title, so this was judged against the PR description and changeset alone. Everything in the three enumerated commits is present and matches intent; this is a scope-disclosure gap, not a functional one.