feat(analyst): add prime as a first-class analyst-benchmark runner - #547
Conversation
Port the proven external prime-analyst rig into the repository so the prime-vs-dspy CodeTraceBench comparison is reproducible from 'agent-eval analyst-benchmark' alone. - createPrimeBenchmarkRunner (src/analyst/benchmark-runner-prime.ts): OpenAI-compatible cli-bridge runner with an injectable transport. Inline-JSON trajectory delivery from the same prepared trace store every runner receives (verification spans already appended by the command), chunked viewSpans fallback for oversized traces, the short-strings block contract (no rationale; measured stream-splice corruption on long strings), one bounded repair turn that carries the malformed reply but never the trajectory, block validation, and the published expandCodeTraceFailureBlocks expansion. Still-malformed replies and transport failures become typed failed observations; zero valid blocks from a well-formed reply is an honest null. Usage receipts keep the bridge's exact token counts with rate-estimated USD and stay uncaptured when the bridge omits usage. - CLI: 'prime' joins AnalystBenchmarkRunnerKind with --bridge-url (default http://localhost:4181) and --no-repair; prime is codetracebench-only and rejects --model-owner-module (the bridge owns execution). Run identity records ownerCallRef cli-bridge:<url>; the local receipt omits modelOwnerModule for prime. - Implementation digest manifest gains the new source file; the pinned ANALYST_BENCHMARK_IMPLEMENTATION_SHA256 is recomputed accordingly. - Tests: runner unit tests over an injected fake transport (happy path, repair, failed observation, chunked projection, deadline, abort, usage capture) plus a command-level end-to-end prime run and flag validation. dspy-rlm and direct behavior is untouched; no existing assertion changed. - Docs: docs/prime-analyst.md (bridge prerequisites, reproduce commands, protocol notes, status) linked from docs/trace-analysis.md.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 26c1cb08
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
tangletools · auto-approval · reason: drewstone_author · 2026-08-08T03:42:59Z
tangletools
left a comment
There was a problem hiding this comment.
🟠 Value Audit — better-approach-exists
| Verdict | better-approach-exists |
| Concerns | 2 (1 medium-concern, 1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 134.4s (2 bridge agents) |
| Total | 134.4s |
💰 Value — better-approach-exists
Adds a third scored analyst arm (RLM agent via OpenAI-compatible bridge) cleanly into the existing benchmark plumbing, but reimplements the package's own OpenAI chat-completions client + fenced-JSON extraction instead of reusing it.
- What it does: Introduces
--analyst prime(codetracebench-only): a newcreatePrimeBenchmarkRunnerthat sends the CodeTraceBench task + inline-JSON trajectory to a cli-bridge/v1/chat/completions, parses fenced{answer,blocks}JSON, optionally does one bounded repair turn, and expands accepted blocks into scored findings via the sharedexpandCodeTraceFailureBlocks— scored by the same Hungarian grader a - Goals it achieves: Make the prime-vs-dspy-rlm comparison reproducible from this repo alone, on identical selected rows, with byte-unaffected receipts for the existing two arms — so the RLM coding agent can be scored as a first-class arm of the analyst benchmark rather than only on an external rig.
- Assessment: Mostly in-grain: it slots behind the existing
AnalystBenchmarkRunnerinterface, reuses the shared block-expansion/scoring/comparison path, and the type-widening + fail-loudrequireModelOwnerSettingsnarrowing keeps dspy-rlm/direct receipts byte-identical via conditional spreads. The prime runner's contract design (short-strings rule, raw-usage-in-metadata, honest-null-vs-failure, per-observati - Better / existing approach: The repo already has a canonical, heavily-tested OpenAI
/chat/completionsclient (src/llm-client.ts:573-868callLlm) and a provider-neutralChatClientthat ships a literalcli-bridgetransport (src/analyst/chat-client.ts:34,79-83,131-140). The prime runner instead reimplements the POST+status+JSON-parse+content/usage-extraction (benchmark-runner-prime.ts:142-186bridgeCall, `:287-322 - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: opencode: opencode error
🎯 Usefulness — sound-with-nits
A coherent, well-fitted third analyst arm that reuses the existing runner/scoring/expansion machinery and adds minimal new surface (a cli-bridge transport + output contract); ahead of its first live caller, which is fine.
- Integration: Fully reachable:
--analyst primeis parsed (benchmark-command.ts:569-605), dispatched bycli.ts:160, and the defaultcreateAnalystRunnerfactory (benchmark-command.ts:226-243) constructs the prime runner whenconfig.analyst==='prime'.createPrimeBenchmarkRunneris exported through the public barrel (index.ts:154-168 via benchmark-real-model.ts:36-44), and the new file is registered in th - Fit with existing patterns: Follows the established runner pattern exactly: same
AnalystBenchmarkRunner<AnalystRunInputs>interface ascreatePublicBenchmarkRlmRunner/createPublicBenchmarkDirectRunner, sameexpandCodeTraceFailureBlocksexpansion (benchmark-runner-prime.ts:251), same Hungarian-assignment scoring. The newPublicAnalystBenchmarkModelSettingstype (benchmark-public-types.ts:90-94) cleanly models 'prime - Real-world viability: Robust on the non-happy paths: node:http transport with explicit AbortController deadline (benchmark-runner-prime.ts:150-170) deliberately avoids undici's 5-min header-kill; oversized-trace chunked viewSpans fallback fails loud on any dropped span (:399-419); usage-merge treats uncaptured as poisoning rather than silent zero (:646-657); malformed reply becomes a typed error observation identical i
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🎯 Usefulness Audit
🟡 Default bridge transport is http-only; a TLS bridge fails with a misleading TypeError [robustness] ``
nodeHttpPrimeBridgeTransport throws
bridge URL must be http:for any non-http protocol (benchmark-runner-prime.ts:291). This is defensible for the documented localhost bridge (docs/prime-analyst.md only references http://localhost:4181) and the rationale is avoiding undici's header timeout, but a reviewer should confirm a remote/TLS bridge is genuinely out of scope. If one is ever wanted, HTTPS support would need its own deadline-safe transport rather than relaxing this check. Not gating — the
💰 Value Audit
🟠 Reimplements the package's own OpenAI client instead of extending it [duplication] ``
src/analyst/benchmark-runner-prime.ts:142-186(bridgeCall),:287-322(nodeHttpPrimeBridgeTransport), and:506-542(extractReplyContent/extractRawUsage/extractJsonObject) collectively reimplement the OpenAI chat-completions POST, status/JSON handling, choices[0].message.content extraction, usage parsing, and fenced-JSON recovery that already live insrc/llm-client.ts(callLlmat :573-868,extractJsonPayloadat :502). The provider-neutralChatClienteven has a dedicatedcli-bridge
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
What
--analyst primejoinsdspy-rlm|directin the analyst benchmark: an OpenAI-compatible-bridge runner (createPrimeBenchmarkRunner) that drives the prime-agent RLM harness through cli-bridge on the same CodeTraceBench rows, scored by the same Hungarian-assignment grader. New--bridge-urlflag; model formprime/zai/glm-5.2.The protocol is a faithful port of the externally-proven rig (30+ live cases at time of writing): inline-JSON viewTrace projection with a chunked viewSpans fallback for oversized traces, the short-strings block contract (measured stream-splice corruption on long strings — rationale field removed; the scorer never read it), one bounded repair turn that carries the malformed reply but never the trajectory, typed failure observations, per-observation
primeAnalystProtocolSha256. Two deliberate deviations, both documented in-code: no machine-local mutex (the benchmark's own run lock governs), and span enumeration from the prepared store (which already carries the appended verification artifacts) rather than raw OTLP.docs/prime-analyst.mddocuments the exact same-rows reproduce commands (--analyst primevs--analyst dspy-rlm), bridge prerequisites, and protocol rationale; linked fromdocs/trace-analysis.md.Proof
Verifier notes (accepted, fail-safe direction)
Two minor receipt drifts vs the external rig, both with raw bridge usage preserved in metadata: partial token reports collapse to uncaptured (never a silent zero), and the bridge's
estimatedflag lives inmetadata.bridgeUsagerather than the receipt. A prime response-cache for--resumeof in-flight cases is a named follow-up.