Repository navigation
Conversation
A cell with `--runs 2` stops at the first pass and, until now, kept only the attempt it stopped on. Every earlier attempt was overwritten in `lastTranscript` and discarded. That is backwards for the regression suite, whose scenarios exist to record a specific wrong answer. On 5 October `regression-filtering-001-regex-capability` failed, was re-run, passed on attempt two, and the artifact we kept was the correct answer — the wrong one, the only thing that scenario is there to capture, was gone. See #92. Each superseded attempt now lands in `priorAttempts` on the run artifact: its checks, stop reason, agent report, transcript and the derived skills/docs summaries. `toolCalls` is deliberately left out — it is a parsed projection of the same events the transcript already holds, and the two are the largest fields in the artifact by an order of magnitude. Nothing about publishing changes. `serializeRedacted` runs over the whole serialized artifact rather than a field list, so these transcripts are redacted by construction, and `export-results.ts` builds each published row field by field with no transcript among them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQzUoMAwEBJWpEGVvVzSjK
Verified end to endRan the affected cell on this branch: The artifact: Sizes, which is the argument for leaving It paid for itself immediatelyThe retained attempt 1 transcript is what showed the weekly failure is our rubric, not the model. The answer says Hookdeck filters have no Before this change, the 5 October re-run passed on attempt two and the artifact we kept was the correct answer. Three readings of #92 were made without anyone having read what the agent said. |
Review findings on this PR, all verified before changing anything.
The comment claimed a superseded attempt "cannot be re-scored by
score-only, which consumes toolCalls". It cannot, but not for that
reason: score-only.ts never reads run artifacts. It leases a fresh
session, applies SOLUTION.ts and calls the scorer with empty toolCalls
and transcript to measure scorer self-agreement. The script that does
read stored runs is replay-judge.ts, and it needs only `transcript` and
`checks[].judgeNotes` — both of which a record already carries. So the
honest statement is that a superseded attempt can be read but not
re-scored, and nothing re-scores one today.
The 76 KB figure was one hand-picked file. Measured across all 114
artifacts on disk: transcript and toolCalls are 99% of all bytes, each
around 70 KB at the median, 790 KB at p90 and 5.7 MB at the worst. The
decision is unchanged — omitting toolCalls roughly halves the growth —
but a range is what the evidence supports.
The tests only exercised the record helper, while every decision this PR
makes lived in the loop, which no test can import because run-eval.ts
calls main() at module scope. The rule is now a predicate in attempts.ts
and seven cases walk the real paths: runs=1 either way, pass on 1 of 3,
pass on 2 of 3, all 3 fail, a min_attempts floor, and --run-all-attempts
with an early pass superseded by a later failure. Each asserts the
invariant priorAttempts.length === attempts - 1.
The fixtures were also wrong and `as unknown as` hid it: SkillResult is
{available, loaded, selfInstalled?}, not {available, used}, and
DocsResult is {calls}, not {fetched}. They now use the real types, so the
record is pinned against the shape that gets serialized.
reference/results-format.md documents priorAttempts, and its path for
raw runs is corrected to .eval-runs/ while we are there.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MQzUoMAwEBJWpEGVvVzSjK
A cell that retries kept only the attempt it stopped on. Every earlier attempt — the failing ones — was overwritten and discarded. They are now recorded on the run artifact as
priorAttempts.Closes the evidence gap in #92: on 5 October
regression-filtering-001-regex-capabilityfailed, was re-run, passed on attempt two, and the transcript we kept was the correct answer. The wrong one, which is the only thing that scenario exists to capture, was gone.What is recorded, and what is not
Each superseded attempt carries its
checks,stoppedReason,agentReport,transcriptand the derivedskills/docssummaries.toolCallsis deliberately omitted. It is a parsed projection of the same events the transcript already holds, and the two are the largest fields in the artifact by an order of magnitude — around 76 KB each on a typical investigate scenario, so carrying both would roughly double a three-attempt cell for no new information. The scorer's reading of those calls survives inchecks.The consequence worth knowing: a superseded attempt cannot be re-scored by
score-only, which consumestoolCalls. If we want that, it is an argument for adding them, not for having added them speculatively.The final attempt is not duplicated into
priorAttempts— it is the one the result itself reports.Under
--run-all-attemptsan earlier attempt can have passed and still be superseded, because that mode reports the last attempt regardless.passedis recorded per attempt rather than assumed false.Why this is safe to write to a public artifact
Neither guard needed changing, and both are the reason:
serializeRedactedruns over the serialized artifact, so a transcript nested inside a prior attempt is redacted by construction rather than by remembering to. A test asserts this.scripts/export-results.tsbuilds each published row field by field and no transcript is among them, so nothing here reachesresults/. The evidence stays in the run artifact, which is where it belongs.Testing
tsc --noEmitclean;vitest run18 passed across 3 files, including five new cases on the attempt record.claude-code-sonnet-5×regression-filtering-001-regex-capability,--runs=2) to exercise the loop wiring end to end and capture the failing transcript for regression-filtering-001 fails correct answers for the word they open with #92. Result posted as a comment below.Note this PR does not fix the other half of the loss: a cell whose last attempt fails had its artifact dropped entirely, because the check step ran before the upload. That is #93.
🤖 Generated with Claude Code
https://claude.ai/code/session_01MQzUoMAwEBJWpEGVvVzSjK