Skip to content

Floor enrolment margin gate: refuse a newly enrolled witness not shown to reach a verdict inside the measured runner margin - #11090

Merged
briansrls merged 5 commits into
mainfrom
session/gentle-crane-24
Sep 12, 2026
Merged

briansrls merged 5 commits into
mainfrom
session/gentle-crane-24

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

What this pays

gunbc.floor_cost_distribution implied_clean_run_budget already 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 is NoMeasuredMarginAtRunnerLimiter, its attribution is CountAndSelectedLiveTreePopulationConfounded, and its instrument reads cgroup heartbeat and RSS — GrowthStagedAgainstMeasuredHeadroom is 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:

PR its own PR run floor job what it named
#10882 34521851736 required-witnesses-floor failure, verdict=FloorRefused its 4 v2.test.native_decl_selection.* at 503–521ms
#10946 34532246628 required-witnesses-floor failure 01:35, verdict=FloorRefused; aggregate witnesses job failed 02:31:57 the same where_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_drop floor_cost_claim_qualification_unavailable in this file's own units.

Why 302ms is not the two repudiated ceilings

required_floor records 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_steps were 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 main runs, twelve distinct runner registrations, three hosts, 398 identities at identical eval_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: its required-v2-native job 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_observation

That is the obvious authority for the exact/censored distinction, and the omission is deliberate rather than an oversight. gunbc.recurring_failure_mode binding_chosen_by_pool_membership_rather_than_by_the_declared_rule names that module and gunbc.floor_cost_distribution as its specimen: a closure holding both binds RightCensoredCost ambiently from the pool. This gate needs implied_clean_run_budget from the second, so importing the first is the documented collision. (Independently: an oracle compile of v2.workflow.claim_cost_observation as entry refuses today on main with one blocking error at its own exact_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_distribution ClaimCostReading instead — 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 main for every row already living between the margin and the ceiling).

The population is then joined to what the run actually planned (Planned | PlannedAsChangedWitness in 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 as enrolment_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 to changed_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 so adjudicated + deferred == newly_enrolled is checkable on the line.

Declared residual: a brand-new test fn added 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 in v2.workflow.floor_diff_observe sufficient 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 under claim_batch --hermetic, each at cpu=0ms.

Discriminating RED, verified by mutation in an isolated worktree (envelope permille 1653 → 1000, i.e. budget collapses to the ceiling):

FAIL the_enrolment_budget_is_strictly_below_the_ceiling
FAIL the_enrolment_budget_is_the_derived_p90_clean_run_figure
FAIL a_row_under_the_ceiling_but_over_the_margin_is_refused_at_enrolment
FAIL the_margin_boundary_admits_the_budget_and_refuses_one_above_it
FAIL the_fold_reports_only_blocking_rows_with_their_causes
PASS (the 6 margin-insensitive arms)

a_row_under_the_ceiling_but_over_the_margin_is_refused_at_enrolment is 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_ceiling is 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=11 with every row admitted.

Enrolled, not advisory

required_floor_outcome_is_clean gains a tenth conjunct, inside the existing required-witnesses-floor job — 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 main through 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

gunbc-ci-auto-heal and others added 2 commits September 11, 2026 19:37
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
@gunbai-bot gunbai-bot Bot changed the title Floor enrolment gate: refuse witnesses not shown to reach a verdict within the per-claim ceiling Floor enrolment margin gate: refuse a newly enrolled witness not shown to reach a verdict inside the measured runner margin Sep 11, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review September 11, 2026 20:11
gunbc-ci-auto-heal and others added 2 commits September 11, 2026 20:14
…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
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Review 64022 — confirmed and fixed in c767bdc. The finding is correct and it was a real merge-blocker in this PR, not a style point.

Verified before fixing. changed_witness_set ranges over the whole diff; declared_identity_set ranges over the discovery roots; undeclarable_changed is exactly that difference (required_floor_runner.rs, undeclarable_changed), and its members get DeclinedChangedWitnessOutsideDiscovery and never execute. My newly_enrolled was derived through the same root-agnostic path (changed_witness_identities_from_edited_test_fns over enrolled_test_fns), so a wholly-added or rename-destination .dag test file homed outside the source roots would have been enrolled, declined, absent from the cost population, and refused as enrolment_not_measured. That is the block's own warning — an identity no edit inside the offending PR could ever satisfy — rebuilt one gate over. You also cited the right authority: §5's completeness is an identity join, not a count equality, and my gate had no join at all.

Which of your two repairs I took, and why both, not either. You offered the changed_witness_expected intersection or a typed decline. I took the typed decline and joined on the disposition rather than on changed_witness_expected, because that set only removes the outside-discovery population — an added witness declined as declined_fixture_member or declined_long_module would still have reached the lookup-miss arm. The join is now on the disposition receipt itself (Planned | PlannedAsChangedWitness), which is the single authority on "did this run undertake to execute this identity" and is total over every present and future decline arm.

The new arm does not block, and that is a deferral rather than an exemption. EnrolmentNotPlanned → EnrolmentOutsideThisRunsExecution. A newly enrolled identity is by construction a changed identity, so a declined one reaches changed_witness_standing_blocks through its Declined arm and still refuses the run, carrying the disposition's own wire name. No refusal is lost — the run stops with the remedy the author can act on ("this file is outside the discovery roots") instead of one they cannot ("produce a measurement"). Two gates refusing one row with two causes, one of them wrong, is worse than one gate refusing it with the right one.

A missing disposition row is also treated as not-planned, for the same reason: changed_witness_standing_blocks already refuses it as MissingDisposition, and asserting "planned" about an identity the receipt never mentions would be the count-equality reasoning again.

The narrowing is counted, not silent. The summary line now prints newly_enrolled=N adjudicated=A deferred_outside_execution=D, so A + D == N is checkable on the line itself — a gate that quietly stopped looking at most of its population cannot render as one that looked and found nothing (§5, no silent caps).

On your second finding (floor_enrolment_margin.dag EnrolmentMarginStanding / enrolment_margin_standing_blocks): same class, same fix. NotMeasured blocked unconditionally and so conflated "planned but untimed" with "the runner withheld it". The model now distinguishes them, and enrolment_margin_standing_name was added so every standing has a name while only the refusing ones have a cause.

Evidence: three new witnesses, 14/14 green —

  • an_identity_the_runner_withheld_is_not_refused_by_this_gate
  • a_withheld_identity_and_an_unmeasured_planned_one_are_different_standings
  • the_fold_omits_withheld_rows_and_keeps_over_margin_ones (stated over the fold, not only the predicate, because the fold is what the merge gate reads)

The planned-but-untimed row still blocks — an_unmeasured_identity_is_refused_and_not_confused_with_a_slow_one is unchanged and still green, so the repair narrowed the population without weakening the arm the gate exists for.

— 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
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Review 64039 — both findings confirmed and fixed in 45da185.

1. Two derivations answering one question. Verified: git grep -n "changed_witness_identities\b" -- src returns no callers for the wrapper, and changed_witness_identities_with_index was reachable only through it once this PR rewired the live call site. So the diff did leave a §3 fork — and your framing of it is the one that decided the fix: "A fork always gets consolidated later, so it is a correctness concern, not a style one."

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 changed_witness_identities wrapper was already callerless on main (git grep ... origin/main -- src is empty), so this PR orphaned one of the two and inherited the other. Both go.

2. The citation pointed at a header that said nothing. Also verified — grep -n "trigger\|residual" src/v2/workflow/floor_enrolment_margin.dag returned empty, while FloorDiffEdits::enrolled_test_fns told the reader to see that header for the declared gap. You are right that this is two defects at once: a §3 citation to a declaration that does not carry what is claimed, and a §4b(2) untracked stall — the residual existed only in the PR body, which is exactly where a claim rots unchallenged.

The header now carries it, in the terms §4b(2) asks for:

  • The gated population and why it is sound (every member provably did not exist before, so the conjunct cannot refuse a change for a witness it did not author).
  • The residual: a brand-new test fn added to an existing file is newly enrolled and is not gated, and why the diff alone cannot separate it from a modified sibling — both appear as a touched declaration in a modified path, and line ranges report which lines the diff reached, not which names are new.
  • The class: can climb now but unbuilt, not cannot climb further.
  • The trigger, named as the CAPABILITY rather than an artifact: a modeled base-revision declaration observation in v2.workflow.floor_diff_observe, sufficient for answering "was this identity declared at the merge base" per touched path, refusing rather than widening when the base cannot be read. With it the enrolled set becomes declared now minus declared at base and the residual closes.
  • What the residual costs, measured: 9 of the 11 identities that refused main on the specimen, because both incident PRs introduced their expensive witnesses in wholly new files.

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 --all-targets -D warnings clean, verified against a control that must fail.

— sent from gentle-crane-24

@briansrls
briansrls merged commit 2264026 into main Sep 12, 2026
4 checks passed
@briansrls
briansrls deleted the session/gentle-crane-24 branch September 12, 2026 00:10
@briansrls
briansrls restored the session/gentle-crane-24 branch September 12, 2026 00:14
briansrls pushed a commit that referenced this pull request Sep 12, 2026
… 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant