Conversation
87d467e to
cfb2428
Compare
CI E2E report — ❌ Failed
|
|
cfb2428 to
4b765ed
Compare
|
All five addressed in 1. Fail-closed killed promotion for the bench lanes. Confirmed, and the shape is slightly different on current
On the test: agreed the old ones couldn't have caught this, since every one hardcoded 2. Report claimed "within budget" unconditionally. Fixed — it compares now. Against a 200 ms budget with 1211 ms kept it reads 3. 4. Resume cleared the env tier before restoring it. Guarded exactly as you suggested. Worth flagging: that fix exposed a latent crash one line further on — with the env no longer popped, an unparseable 5. What the rebase changed. One adjacent bug, already dead — no action. While confirming finding 1 I found the same class of bug in the retired lane's Verification. |
4b765ed to
552cef9
Compare
|
Adding the concrete case that motivated the flag, since the "why" is easier to Measured on one MI355X running a 1.26B-parameter vision model at six views per The sharp edge is that this is not mere tolerance of a regression. Facing a lever With Three design points that follow from this, and are the reason the PR is shaped
Note on the force-push since my reply above: the branch is now rebased onto the |
552cef9 to
93dc8b9
Compare
|
The constraint should land — a throughput-only gate doesn't tolerate a 1. One field. Every 2. One veto channel. 3. One copy of the budget. 4. Fail closed at the boundary. If the baseline is already over budget, don't 5. Prompt: one line of contract, no defensive try/except. Keep the 6. Tests follow the contract. Predicate, lift veto, explore REVERT, real lane The constraint is worth merging. What merges should be one more veto on KEEP, |
93dc8b9 to
6180540
Compare
|
Redrawn rather than guarded, in Two of your points turned out to be live bugs rather than only shape objections, and I want to name both because the second one is worse than filed. 1. One field. Confirmed, including the divergence you pointed at. On the old head the gate read through Every dict reaching the gate now carries 2. One veto channel. Done, and it collapsed further than the review asked. 3. One copy of the budget. 4. Fail closed at the boundary. Agreed, and this is the one I find hardest to defend as it stood. The old code's own comment said an over-budget baseline meant "every candidate that follows will be refused, and the session would otherwise spend its whole run discovering that one KEEP at a time" — and then warned and continued anyway. It described the failure and chose the weaker response. It now stops with 5. Prompt. 6. Tests. 57 → 44 in Verification. Full tree: 16323 passed, 8 failed — 7 reproduce identically on pristine One thing worth flagging that only the redraw caught, since it is a repo rule rather than a review point: |
994e51c to
ef53c3b
Compare
Redraw of the constraint after review. The previous shape landed a parallel latency subsystem beside three mechanisms that already owned the concern; this rides the ones that exist. Business code is 633 -> 194 lines, and two live bugs in the old shape are gone with it. One veto channel. The SLA is applied where the gain gates already rule: graded_comparison marks an over-budget candidate REVERT and names it in GradedComparison.veto_reason, so the promotion choke point, explore's round ladder and the kernel stack honour it by reading the verdict they already read. Explore refuses in the round that measured the variant, so an over-budget config is never folded onto the stack and never becomes the anchor the rest of the batch is graded against; its ledger row says latency_budget_exceeded rather than blaming a gain it comfortably made. One field. Every dict reaching the gate carries e2el_mean_ms, copied from VariantResult by the lane that built it. The alias table and the nested descent are gone: a lane that does not carry the field is that lane's bug, not a spelling the lookup should learn. This also removes the divergence the old shape had, where the gate read through the decoder while current_best archived the raw key -- a candidate reporting mean_e2el_ms passed a 200 ms budget on 150 ms and then archived None, so the report said "latency not measured" about a KEEP it had just graded. The tests could not catch it because they built the lift dict by splatting the decoder over the result, which is the decoder validating itself; they now drive each lane's real return dict. One copy of the budget. SharedState.latency_budget_ms, written at launch and archived with the session. HYPERLOOM_MAX_LATENCY_MS is gone -- the gate runs in the Coordinator process, so no worker read it -- as is the params tier, which nothing wrote. Four parsers of one float collapse to zero: argparse validates it, so an unusable value exits 2 rather than resolving to "no budget". A fail-closed gate must not have a switch that fails open; --max-latency-ms 200ms previously turned the SLA off while the operator believed it was on. Fail closed at the boundary. A baseline already over the ceiling stops the run with baseline_over_latency_budget instead of warning and then refusing every candidate for the rest of --max-hours to learn what was knowable at launch. That removes the baseline exemption, the over-budget champion prose in the report, and with it the case where a session ends "target reached" holding a current_best no Objective.reached() knew was inadmissible. Prompt and docs. to_latency_budget_summary renders "=== Latency budget (constraint) ===" and is called unwrapped: the neighbouring try/except blocks guard advisory sections, and swallowing this one would have the model route as if the session were unconstrained -- a silent failure of the constraint itself. orchestration.md names the block, SKILL.md's flag table carries the row, and optimization-loop.md, where KEEP semantics are defined, states the constraint. Tests follow the contract: the predicate, the lift veto and its recorded refusal, explore's REVERT driven end to end through the real ladder, the lanes' real return dicts, CLI validation, and resume from archived state. The source-string assertion, the self-referential payload, the permutations of the four resolvers and the retired framework task kind are gone -- _lift_to_current_best is near-agnostic to task_kind, so the seven-way parametrization was one path run seven times. Co-authored-by: Cursor <cursoragent@cursor.com>
A terminal the report cannot explain is a run that ends with a token and no account of itself, which is what the vocab test guards. Names what the stop means and what to do next: the ceiling may be under this workload's floor on this hardware, or the baseline configuration is itself the thing to fix. Co-authored-by: Cursor <cursoragent@cursor.com>
`latency_budget_ms or 0.0` is the pattern the no-falsy-budget rehearsal rule exists to catch: a budget tested for truth reads zero as absent. Harmless here only because zero happens to mean "off", which is exactly the coincidence the rule refuses to rely on. The field is a plain float with a 0.0 default, so read it. Co-authored-by: Cursor <cursoragent@cursor.com>
ef53c3b to
6d6425d
Compare
Why
The optimizer maximized
output_throughputand nothing else. Latency wasmeasured, reported and fed to the prompts, but no latency number could block a
KEEP.
That is survivable for a lever that raises throughput without touching
per-request latency. It is unsafe for any lever that raises throughput by
making each stream slower: against a throughput-only gate such a lever does not
merely tolerate a latency regression, it selects for the largest one on offer,
because that is where the throughput is.
Measured on one MI355X running a 1.26B-parameter vision model at six views per
forward pass: against the best unsplit configuration, splitting the card into
eight partitions with two streams each raised aggregate throughput about 20%
while mean end-to-end latency went from 183 ms to 1211 ms, a 6.6x
regression. Under a throughput-only gate that candidate is promoted,
current_bestbecomes the 1211 ms configuration, and the session signs off witha +20% win that nobody serving an interactive workload can deploy.
What
--max-latency-msnames a ceiling on mean end-to-end latency. It is aconstraint, not a target: it does not say when the run stops, only which
winners are admissible, so it sits outside the
--target-*mutually-exclusivegroup and composes with whichever objective is in use. It is absolute rather
than relative, because an SLA is a fixed number the workload owner already
knows and a percentage cap would ratchet upward as the baseline improved. It is
off by default, leaving KEEP behaviour exactly as it was when unset.
Shape
This is a redraw. An earlier revision of this PR landed the constraint as a
parallel latency subsystem — its own module, its own resolver chain, its own
gate beside the existing ones. Review was that it should ride the mechanisms
that already own the concern, and it does now: 200 lines of business code,
down from 633, with the 266-line
_latency_budget.pydeleted outright.One veto channel. The SLA is applied where the gain gates already rule.
graded_comparisonmarks an over-budget candidateREVERTand names it in anew
GradedComparison.veto_reason, so every consumer of the verdict honours itwithout a check of its own: the promotion choke point, explore's round ladder,
the kernel stack, the integrate lane. Explore therefore refuses in the round
that measured the variant, which keeps an over-budget config from being folded
onto the stack and becoming the anchor the rest of the batch is graded against —
and its ledger row says
latency_budget_exceededrather than blaming a gain thevariant comfortably made.
One field. Every dict reaching the gate carries
e2el_mean_ms, copied fromVariantResultby the lane that built it. There is no alias table and no nesteddescent: a lane that does not carry the field is that lane's bug, not a spelling
the lookup should learn.
One copy of the budget.
SharedState.latency_budget_ms, written at launchand archived with the session, so a resume restores it with no second source to
reconcile. No environment variable (the gate runs in the Coordinator process, so
nothing else read it) and no task-params tier (nothing wrote it). Parse failures
happen only at the CLI, which exits 2 — the switch on a fail-closed gate must
not itself fail open.
Fail-closed
When set, the gate refuses a candidate that reported no end-to-end latency,
because an unmeasured constraint is not a satisfied one. That makes latency part
of the promotion contract rather than a field lanes may or may not fill, which
is why each lane copies it: the rule must refuse the untimed, not the
unplumbed.
It fails closed at the boundary too. If the baseline itself exceeds the ceiling,
the run stops with
baseline_over_latency_budgetinstead of warning and thenrefusing every candidate for the rest of
--max-hoursto discover somethingknowable at launch. That also means no
current_bestcan be over budget, so noObjective.reached()needs to learn about the constraint to avoid signing offon an inadmissible champion.
Refusals are recorded to
SharedState.latency_refusalsand render into theorchestration prompt as
=== Latency budget (constraint) ===. Without it asession that ends near baseline is indistinguishable from one that exhausted its
headroom, and the router cannot tell a binding SLA from an exhausted search
space — the two call for opposite responses. The block is rendered unwrapped:
swallowing it would have the model route as if the session were unconstrained,
which is a silent failure of the constraint itself.
Tests
44 in
test_latency_budget.py: the predicate, the lift veto and its recordedrefusal, the lanes' real return dicts, CLI validation, resume from archived
state, and the rendered prompt block. Explore's REVERT is an end-to-end test in
test_explore_executor.pythat drives the real ladder through the executorharness and asserts the reverted row's reason and gate.
The lane tests are built from each executor's own return dict rather than from a
fixture already shaped the way the gate wants — a fixture that supplies the
field cannot catch a lane that forgets it, and one test strips the field back
off to show the gate then refuses.
Docs
SKILL.md's operator→CLI flag table (the source of truth for forwarding astated value, so an SLA given in prompt form is not dropped), the
orchestration.mdrouting rule naming the prompt block, anddocs/conceptual/optimization-loop.md, where KEEP semantics are defined.Review notes
Split out of #1288, where the flag existed but only
ExploreExecutorhonouredit while the help text claimed otherwise. Orthogonal to the partition work: the
constraint applies to any throughput-for-latency trade, so it is reviewable and
useful on its own.