Repository navigation
Floor enrolment margin gate: refuse a newly enrolled witness not shown to reach a verdict inside the measured runner margin - #11090
Conversation
A newly enrolled witness must be SHOWN to reach a verdict with headroom, where the headroom is derived from how much a RUNNER varies on identical work rather than from what our claims happen to cost. Consumes gunbc.floor_cost_distribution implied_clean_run_budget, which until now had a witness and a renderer and no admission consumer at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Us78rJCqVqKF8qQj77vrAn
…conjunct The model landed in the previous commit; this makes it decide something. A witness a change NEWLY ENROLS must be measured, and measured inside the margin the runner envelope implies rather than merely inside the 500ms ceiling. - floor_enrolment_margin_budget_ms_count: the host read point, so the seed evaluates the derivation instead of mirroring a literal. - REQUIRED_FLOOR_RUNTIME_AUTHORITY_MODULES gains the module, which is what makes evaluating it by name legitimate. It cannot live in the policy module's frame: the gate imports required_floor for the ceiling, so the reverse import would close a cycle. - FloorDiffEdits.enrolled_test_fns: test fns in paths whose declaration set is established fresh at NEW. A strict subset of the edited set and deliberately narrower than "newly enrolled" in full, because every member provably did not exist before -- which is what makes a merge-blocking conjunct safe. - required_floor_outcome_is_clean gains a tenth conjunct. The budget reader refuses a figure at or above the ceiling: a margin that does not sit inside the line it protects is permanently green by construction. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Us78rJCqVqKF8qQj77vrAn
…entity `find` over the executed rows inside the loop over newly enrolled identities is an `enrolled x executed` fold — 11 x 3,667 on the run that lands this gate, which is nothing, and that is exactly the argument DESIGN section 6's bare-minimum-cost rule refuses: "n is small here" is not a time-stable fact. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Us78rJCqVqKF8qQj77vrAn
The enrolled population is derived from the DIFF and is root-agnostic; the executed population is bounded by the discovery roots. Without a join, a wholly-added or rename-destination test file homed OUTSIDE those roots is enrolled, declined by the runner as DeclinedChangedWitnessOutsideDiscovery, absent from the cost population, and refused as `enrolment_not_measured` -- demanding a measurement that no edit inside the offending PR could produce. That is the class the seed's own `undeclarable_changed` block was written to repair, rebuilt one gate over. The repair is a typed arm rather than a filter: - EnrolmentNotPlanned / EnrolmentOutsideThisRunsExecution in the model, and the mirror in the host. It does NOT block here -- it DEFERS to changed_witness_blocking, which refuses the same row carrying the disposition's own wire name. A newly enrolled identity is by construction a changed identity, so no refusal is lost; the run stops with the remedy the author can act on instead of one they cannot. - The deferred count is printed beside the adjudicated one, so `adjudicated + deferred == newly_enrolled` is checkable on the line and a gate that stopped looking cannot render as one that looked and found nothing. - enrolment_margin_standing_name: every standing has a NAME, only the refusing ones have a CAUSE. Three new witnesses, 14/14 green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Us78rJCqVqKF8qQj77vrAn
|
Review 64022 — confirmed and fixed in Verified before fixing. Which of your two repairs I took, and why both, not either. You offered the The new arm does not block, and that is a deferral rather than an exemption. A missing disposition row is also treated as not-planned, for the same reason: The narrowing is counted, not silent. The summary line now prints On your second finding ( Evidence: three new witnesses, 14/14 green —
The planned-but-untimed row still blocks — — sent from gentle-crane-24 |
…ion points (review 64039) Two findings, both confirmed against the code. ONE DERIVATION, NOT TWO. The enrolment gate landed as a near-verbatim second copy of changed_witness_identities_with_index with one extra projection, so two functions independently answered "which witnesses did this change touch" -- the section 3 fork that always gets consolidated later, hence a correctness concern rather than a style one. The copy is now the only derivation and carries the original's doc; the callerless changed_witness_identities wrapper (already dead on main) goes with it. Delete-first rather than leaving it for that later consolidation. THE RESIDUAL IS NOW WHERE ITS CITATION SENDS THE READER. FloorDiffEdits enrolled_test_fns said "a declared gap with a named trigger, not silence; see the gate module's own header", and the header said nothing -- a section 3 citation defect and a section 4b(2) untracked stall at once. The header now states the gated population, the residual (a brand-new test fn in an EXISTING file is newly enrolled and is not gated), why the diff alone cannot separate it from a modified sibling, the class (can climb now but unbuilt), the trigger named as the CAPABILITY -- a modeled base-revision declaration observation in v2.workflow.floor_diff_observe sufficient for "was this identity declared at the merge base" -- and what the residual costs, measured: 9 of the 11 specimen identities reached. 14/14 witnesses green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Us78rJCqVqKF8qQj77vrAn
|
Review 64039 — both findings confirmed and fixed in 1. Two derivations answering one question. Verified: Fixed the way the new function's own doc-comment argued for, and the way §3's replacement-migration rule requires: the extended derivation is now the only one, carrying the original's doc, and both dead functions are deleted rather than left for that later consolidation. One detail worth recording since it changes who owns what: the 2. The citation pointed at a header that said nothing. Also verified — The header now carries it, in the terms §4b(2) asks for:
I deliberately did not reach for a heuristic on declaration order or line position to close the gap inside this lane — that would be a smuggled confidence threshold standing where a missing observation belongs. 14/14 witnesses green; clippy — sent from gentle-crane-24 |
… an existing file is gated (#11119) * Enrolment margin: census test-decl names at the diff base so a new fn in an existing file is gated. The #11090 residual was that only wholly-added paths were newly enrolled. Listing the resolved base tree before git show keeps absence and unreadability apart; enrolment is then declared-now minus declared-at-base, still inside the existing floor job, still p90 over twelve runs. Co-authored-by: Cursor <cursoragent@cursor.com> * Enrolment looks up rename-from at the base so a moved file does not gate every fn. The census stays path-keyed: a dest path is absent at the base, which is empty names, not unreadability. The gate joins that to git's rename-from and subtracts the source names, so a pure move is not newly enrolled and a name the source never declared still is. Co-authored-by: Cursor <cursoragent@cursor.com> * Drop the unconsumed census wrapper and split the base-tree listing once. floor_observe_base_test_decl_census had no call site; production already resolves the base via floor_diff_comparison_readout and calls floor_run_base_test_decl_census. Membership now builds one map from the NUL listing above the per-path fold instead of re-splitting the blob on every touched path. Co-authored-by: Cursor <cursoragent@cursor.com> * Drop the extra to_string on the floor census base so clippy -D warnings is clean. Co-authored-by: Cursor <cursoragent@cursor.com> * Delete the reminted list-contains and the added-path enrolment fallback. review 64246: import string_list_contains, inline the Optional match, and leave enrolled empty without a census. Co-authored-by: Cursor <cursoragent@cursor.com> * Drive the census witnesses from the listing fold so they can finish on the hermetic floor. ListTreePathsAtRevision has no mock_response; new test fns that called it were planned without a verdict. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
What this pays
gunbc.floor_cost_distributionimplied_clean_run_budgetalready derives the largest clean-run cost that still lands under the ceiling after inflation. Until this PR it had a witness and a renderer and no admission consumer — it decided nothing. This gate is its first, which is the payment: consuming the derivation rather than minting a second statistic beside it (DESIGN §3c).It does NOT pay
required_floor_growth_budget_standing. The brief asked me to lead with that; it is the wrong debt. Its limiter arm isNoMeasuredMarginAtRunnerLimiter, its attribution isCountAndSelectedLiveTreePopulationConfounded, and its instrument reads cgroup heartbeat and RSS —GrowthStagedAgainstMeasuredHeadroomis runner memory headroom for roster growth. A CPU-ceiling gate does not discharge it, and that row is untouched here.What this is NOT: a second detector
The brief's premise was that #10882 and #10946 were "found by main's floor AFTERWARDS". Measured on the PRs' own runs, both were found before merge, by their own floor, naming the exact identities:
34521851736required-witnesses-floorfailure,verdict=FloorRefusedv2.test.native_decl_selection.*at 503–521ms34532246628required-witnesses-floorfailure 01:35,verdict=FloorRefused; aggregatewitnessesjob failed 02:31:57where_refinement_clause_parse.*/d1_declaration_grammar_parse.*rows main later named(Cite the job conclusions, not the run conclusions — #10946's run-level conclusion is
cancelled, which misreads as "never adjudicated".) Both merged over that red.So enrolment-time refusal of an over-ceiling witness already exists, sits at rung 2, and fired twice. Detection was never what failed, and a second detector would be a §3 fork that prevented neither incident. This PR adds the margin, not the detection.
The argument: it is a cliff, not a tail
All fifteen interrupts across the two PR runs and the main run sit between 501ms and 521ms against a 500ms line — every observation within four percent above the line, none far above it. These claims are not decisively expensive; they finish just after the bell, and which side they land on is decided by the host that dequeued the job.
That shape is why the remedy is a margin and not a bigger ceiling. A row measured at 450ms clears the ceiling on the run that measures it and is a coin flip on every run after, and today nothing refuses it —
gunbc.rung_dropfloor_cost_claim_qualification_unavailablein this file's own units.Why 302ms is not the two repudiated ceilings
required_floorrecords 500→1552 and 1552→5000 as authority failures: 1552 was "whatever the slowest row happened to cost", a merge-blocking literal grounded in a measurement of the same current tree, which DESIGN §5 forbids by name.The inflation envelope is not a measurement of our corpus. It is measured over rows whose
eval_stepswere identical across runs — the same work, re-run on different machines — so it characterises the runner, not the tree. It does not move when our claims get cheaper or dearer; deleting half the corpus would not shift it. One host holding the maximum for 279 of 398 rows is a fact about hosts. That is an independent referent in exactly §5's sense.302ms appears in no declaration. The gate consumes
implied_clean_run_budget(ceiling, envelope), so if the envelope is re-measured and p90 moves, the gate moves with it — the property the two failed ceilings did not have.Percentile p90 (1653 permille), sample size stated everywhere it appears: twelve green
mainruns, twelve distinct runner registrations, three hosts, 398 identities at identicaleval_steps. p90 over worst (219ms) because worst buys the last ~10% of runs by narrowing admission a further 28% and this sample cannot justify that. p99 is not available from this data at all — quoting one would be precision inflation.No threshold here is calibrated on current costs, so the sequencing constraint in the brief does not bind this PR. (It is discharged anyway: bold-crane-426's hoist landed as #11032 at 06:34 on 2026-09-11.)
The rung, stated at the rung it reaches
Rung 2, mechanically preventable — a gate requiring evidence. Not a wall and not a proof: whether a witness completes inside a CPU envelope is not statically decidable from its source, the invalid state stays writable, and safety depends on this gate executing and staying enrolled. Calling it a wall would be the rung inflation §4b(1) names.
NOT-MEASURED is a separate arm, with a live specimen
A witness nobody timed and a witness timed at 840ms are different states with different remedies; collapsing them is the absorbing fallback in a new costume. Three distinct blocking causes, because they have three distinct remedies:
enrolment_measured_over_margin— reduce the cost.enrolment_censored_at_ceiling— the figure is a lower bound, never rendered into a cost field (its own arm, so a bound cannot occupy a slot named for a cost).enrolment_not_measured— produce a measurement at all. D1 A: parse type-alias where refinements #10946 is the live specimen: itsrequired-v2-nativejob was cancelled, so those identities carried no measurement — not a fast one, not a slow one, none.Why it does not import
v2.workflow.claim_cost_observationThat is the obvious authority for the exact/censored distinction, and the omission is deliberate rather than an oversight.
gunbc.recurring_failure_modebinding_chosen_by_pool_membership_rather_than_by_the_declared_rulenames that module andgunbc.floor_cost_distributionas its specimen: a closure holding both bindsRightCensoredCostambiently from the pool. This gate needsimplied_clean_run_budgetfrom the second, so importing the first is the documented collision. (Independently: an oracle compile ofv2.workflow.claim_cost_observationas entry refuses today on main with one blocking error at its ownexact_completion_population— untouched by this PR and deliberately not repaired here, since folding a second class's repair into this lane is the widening DESIGN §6 prices as redundant work.)The gate consumes
gunbc.floor_cost_distributionClaimCostReadinginstead — which is also the type the seed's required-floor runner already mirrors per claim, so this is a consumer of the authority the producer already speaks rather than a third spelling.Scope, and what it deliberately does not cover
The gated population is test fns in paths whose declaration set is established fresh at NEW (wholly-added files and rename destinations) — a strict subset of the changed set. Every member provably did not exist before, which is what makes a merge-blocking conjunct safe: this cannot red a PR for debt it did not author, and it never reads the standing corpus (a corpus-wide margin would refuse
mainfor every row already living between the margin and the ceiling).The population is then joined to what the run actually planned (
Planned | PlannedAsChangedWitnessin the disposition receipt). The enrolled set is derived from the diff and is root-agnostic; the executed set is bounded by the discovery roots, so without the join an added test file homed outside those roots would be refused asenrolment_not_measured— a state no edit inside the offending PR could satisfy (review 64022). An identity the runner withheld gets its own non-blocking arm,EnrolmentOutsideThisRunsExecution, and defers tochanged_witness_blocking, which refuses the same row carrying the disposition's own name. No refusal is lost; the deferred count is printed beside the adjudicated one soadjudicated + deferred == newly_enrolledis checkable on the line.Declared residual: a brand-new
test fnadded to an existing file is also newly enrolled and is not covered. Distinguishing it from a modified sibling needs the base revision's declaration names, which no observation in this tree produces today. Trigger: a modeled base-revision declaration census inv2.workflow.floor_diff_observesufficient to answer "was this identity declared at the merge base" per touched path — the capability, not an artifact. On the specimen the shipped scope covers 9 of the 11 main interrupts.Evidence
v2.test.floor_enrolment_margin, 14 witnesses, 14 PASS underclaim_batch --hermetic, each atcpu=0ms.Discriminating RED, verified by mutation in an isolated worktree (envelope permille 1653 → 1000, i.e. budget collapses to the ceiling):
a_row_under_the_ceiling_but_over_the_margin_is_refused_at_enrolmentis the load-bearing one: 450ms is under the 500ms ceiling, so the floor admits it today. It reds if the gate is deleted, if the budget widens back to the ceiling, or if the comparison is written the wrong way round.the_enrolment_budget_is_strictly_below_the_ceilingis the decoration guard — at permille 1000 the budget equals the ceiling and every other arm still type-checks while the gate silently becomes the line it was built to sit inside. The host budget reader refuses the same state at runtime.Positive control in production: this PR is the gate's own first live subject. Its 11 witnesses are newly enrolled in an added file, so the run must report
newly_enrolled=11with every rowadmitted.Enrolled, not advisory
required_floor_outcome_is_cleangains a tenth conjunct, inside the existingrequired-witnesses-floorjob — no new lane job and no roster growth. A red that does not block gets merged over; this blocks.Not in scope
Both incidents reached
mainthrough a merge over a red required context, not a missing detector. A margin gate makes the red arrive earlier and on firmer ground; it does not make a red harder to merge over. That is a separate lane and crisp-lynx-452 is raising it.🤖 Generated with Claude Code
https://claude.ai/code/session_01Us78rJCqVqKF8qQj77vrAn