feat(sbd-v6): declare the axis a session graded on, and record it where it is resolved - #1480
Open
haishuok0525 wants to merge 1 commit into
Open
feat(sbd-v6): declare the axis a session graded on, and record it where it is resolved#1480haishuok0525 wants to merge 1 commit into
haishuok0525 wants to merge 1 commit into
Conversation
…re it is resolved Nothing in session_breakdown.json said which axis its gains were on. An AgentX replay is ranked on the slow-tail interactivity percentile with total throughput held as a guard; a synthetic run is ranked on output throughput alone. Every throughput field in the document is the output axis by construction, benchmark_mode reaches reports/final.json but never this document, and on the canonical corpus the two axes differ by roughly two orders of magnitude -- so a consumer had no way to keep an AgentX session out of a synthetic leaderboard. It would sort one against the other and every number would look plausible. metadata.grading declares what the session was configured to rank on: benchmark_mode, objective, and the tput_guard that rides along with the interactivity objective. outcome.validation.graded_on is the separate fact of what the run actually decided its last promotion on, read off that promotion; the two differ whenever a comparison could not supply the axis pair and fell back to output. Neither resolves the other. Publishing the configured axis in outcome would put an interactivity label on an output number, and resolving metadata from outcome would erase what the session asked for. The axis is resolved once at seed and recorded in SharedState.grading, next to benchmark_mode and agentx_epoch, which live there for exactly the same reason. Resolution reads HYPERLOOM_PERF_METRIC and HYPERLOOM_PERF_NOISE_PCT, and every later reader of those is somewhere the environment is not evidence: a resume is a new process, a re-baseline runs in a subprocess, and CLOSE drives the breakdown export from one that frequently never inherited them. resolve_graded_comparison was re-deriving on every comparison, so a shell that lost the metric var would flip a session back to the output axis mid-run and a lost noise var would silently widen a 3.5% guard band to the 5% default -- the KEEP and REVERT rule has to be the one the session started with. Both now come from resolved_grading, and the recorded band reaches passes_intvty_gate and passes_tput_guard, which were taking the ambient default. Sessions seeded before the field derive as before and report a null band, because the band they applied was never recorded and today's default is not evidence of it. Recording it rather than projecting it also removes the environment from the export path entirely: the metadata collector projects nothing for this block, so it lands from the spool alone through the existing leaf overlay. The four graded axes now land beside the output figures instead of being parsed and discarded. They are recorded where the measurement is taken -- the baseline round's own measurement block, which is already where outcome.baseline comes from, and the stack validation row that produced the gain -- rather than read off state.baseline_perf and current_best at export. A second source for one baseline is a second answer, and a revalidation moves the cumulative gain without re-promoting the recipe, so current_best can be a later measurement than the gain beside it. An unmeasured axis is an explicit null: absent would be indistinguishable from an axis the framework failed to report, and zero reads as "measured, and it was zero". TPOT p90 was already parsed out of the benchmark report and dropped at five call sites; it now lands. An adoption that fell off the configured axis is reported as a validation.notes finding naming the count and the reason. Its contribution sits in the same sum as the axis-graded ones, so the total is not single-axis and the reader has to be told. The reason is recorded on the adoption because that is the only comparison that can degrade: the whole-stack validation is recorded only when the orchestrator found the comparison comparable, so its axis is always the configured one. Additive to the wire shape. throughput_tok_s_per_gpu, output_throughput and every other existing key keep their output-axis meaning, so nothing downstream has to change to keep working. Cortex has no column for the interactivity or total axes yet, so the immediate value is that an AgentX session becomes identifiable, which is the prerequisite for keeping it off a leaderboard it is not comparable on. Co-authored-by: Cursor <cursoragent@cursor.com>
6 tasks
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
Makes the grading axis of a session visible in
session_breakdown.json, and records it where the run resolves it rather than re-deriving it at export.Supersedes #1380, which was written against the pre-#1455 collector export and against the pre-#1444 objective. Both premises have moved; see Why this is not #1380 rebased below.
Why
Nothing in the document said which axis its gains were on. An AgentX replay is ranked on the slow-tail interactivity percentile (
e2e_norm_intvty_p90) with total throughput held as a guard; a synthetic run is ranked on output throughput alone. Every throughput field in the breakdown is the output axis by construction,benchmark_modereachesreports/final.jsonbut never this document, and on the canonical corpus the two axes differ by roughly two orders of magnitude.A consumer therefore had no way to keep an AgentX session out of a synthetic leaderboard: it would sort one against the other and every number would look plausible.
The two blocks, and why they are two
metadata.gradingis what the session was configured to rank on.outcome.validation.graded_onis what the run actually decided its last promotion on, read off that promotion. The two differ whenever a comparison could not supply the axis pair and fell back to output.Neither resolves the other, deliberately. Publishing the configured axis in
outcomewould put an interactivity label on an output number; resolvingmetadatafromoutcomewould erase what the session asked for. There is a test on each direction.outcome.final.graded_onagrees withoutcome.validation.graded_onby construction -- they are the same figure read twice -- and a test locks it.Recorded, not re-derived
Resolution reads
HYPERLOOM_PERF_METRIC/HYPERLOOM_PERF_NOISE_PCT. Every later reader of those is somewhere the environment is not evidence: a resume is a new process, a re-baseline runs in a subprocess, and CLOSE drives this export from one that frequently never inherited them. So the axis and its band are resolved once at seed and recorded inSharedState.grading, next tobenchmark_modeandagentx_epoch, which live there for exactly the same reason.This fixes a live defect rather than only serving the export.
resolve_graded_comparisonwas re-deriving on every comparison, so a shell that lost the metric var would flip a session back to the output axis mid-run, and a lost noise var would silently widen a 3.5% guard band back to the 5% default. The KEEP/REVERT rule has to be the one the session started with. Both now come from one resolution point,resolved_grading, and the recorded band reachespasses_intvty_gateandpasses_tput_guard, which were taking the ambient default despite both already accepting the parameter.Sessions seeded before the field derive as before and report a null band: the band they actually applied was never recorded, and today's default is not evidence of it.
Recording it also removes the environment from the export path entirely. The metadata collector projects nothing for this block, so it lands from the spool alone through the existing leaf overlay --
collectors/v6.py's metadata path is untouched.The axes themselves
outcome.baseline.perf,outcome.final.perfandoutcome.validation.perfcarry the four AgentX axes. They are recorded where the measurement is taken: the baseline round's own measurement block, which is already whereoutcome.baselinecomes from, and the stack validation row that produced the gain.Not read off
state.baseline_perfandcurrent_bestat export, for two separate reasons. A second source for one baseline is a second answer to the same question. And a revalidation moves the cumulative gain without re-promoting the recipe, socurrent_bestcan be a later measurement than the gain published beside it.An unmeasured axis is an explicit null. Absent would be indistinguishable from an axis the framework failed to report, and zero reads as "measured, and it was zero", so a synthetic run publishes four nulls. TPOT p90 was already parsed out of the benchmark report and dropped at five call sites; it now lands.
Degrade is a finding, not a field
An adoption that fell off the configured axis is reported through
validation.notes, naming the count and the reason. Its contribution sits in the same sum as the axis-graded ones, so the total is not single-axis and the reader has to be told.The reason is recorded on the adoption because that is the only comparison that can degrade. The whole-stack validation is recorded only after the orchestrator found the comparison comparable, so a
degrade_reasonon that row would never be non-empty -- a field that reads as protection the document does not have.Why this is not #1380 rebased
#1380 is stale in two independent ways.
Semantics. It declares
objective: "total_throughput"under anintvty_veto, from #1362. #1444 inverted that: interactivity became the objective and throughput the guard, andtotal_tput_serving_grading_enabledno longer exists. Carrying its block over would have made the document state an axis no session grades on -- precisely the failure it was written to prevent.Architecture. Its export side patched
collectors/optimizations.py, deleted by #1455.outcome.validationnow reads the stack ledger timeline event, whose rows the orchestrator records as each adoption lands, sograded_objectivewas already recorded and simply unpublished. Its 113-line_grading_projectionis not needed at all: the author-time snapshot reachesmetadata.gradingthrough the overlay with no collector change and noos.environfallback, which is the weakness #1380's own description acknowledged.Rollout
Additive to the wire shape.
throughput_tok_s_per_gpu,output_throughputand every other existing key keep their output-axis meaning, so nothing downstream has to change to keep working.Cortex has no column for the interactivity or total axes yet, so the immediate value is that an AgentX session becomes identifiable -- the prerequisite for keeping it off a leaderboard it is not comparable on.
Test
25 new cases in
test_sbd_v6_grading.py: both axes at seed, the scriptable-framework carve-out, recorded-beats-environment in both directions, the null band on a legacy session, the block surviving the recorder and the overlay end to end, the metadata/outcome separation locks in both directions, the axis fallback for a session that adopted but never validated, explicit nulls, and the degrade finding.Two exact-equality assertions on
outcome.baselineintest_sbd_v6_stages.pyupdated for the new key.3200+ tests pass across the SBD, grading, promotion, writeback, bootstrap and executor suites.
ruff checkandruff formatclean onsrc/hyperloom.docs/reference/session-breakdown.mdandbreakdown/SKILL.mdupdated for the new keys.