Skip to content

FLOOR-CHANGED-COST-0 reaches the long home: a changed witness in test/claim/long runs for its verdict - #11073

Merged
gunbai-bot[bot] merged 6 commits into
mainfrom
session/calm-crane-722-long-cost-arm
Sep 11, 2026
Merged

gunbai-bot[bot] merged 6 commits into
mainfrom
session/calm-crane-722-long-cost-arm

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Operator ruling A (via fierce-lark-661, 2026-09-11), work item adhoc-8fd8ac84-1bb.

The defect is a nickname, which is why one arm closes it

The cost-debt roster and the long home are one declaration class under two names. Both say: this identity is not run on an ordinary floor, because the 500 ms CPU line cannot carry it — the roster per identity after measuring, the long home per module structurally. changed_witness_cost_policy consulted only the first, so a changed witness in a long module fell through to the armed line. §3: minimization holds only if each fact lives in one place, and "declared too expensive" was living in two with one of them wired.

Measured, on #11004 at 6b153bf8

witness cpu outcome
gate_red_quadratic_rejects 503 ms BUDGET-REFUSED
gate_refusal_ledger_counted_not_gating 505 ms BUDGET-REFUSED
gate_green_identity_accepts_clean 525 ms BUDGET-REFUSED

All three refused before reaching a verdict. None is planned on any ordinary floor — v2/test/claim/long/ is a DeclinedLongModule whose cadence has been declared-unrealized since falsifier.yml was deleted, and no green floor's claim-cost artifact carries a row for the module. No run has ever paid that cost. The line applied only because a PR touched the file, converting "this PR touched a long module" into three reds that say nothing about the change — FLOOR-CHANGED-COST-0's own failure inverted: a green context that never looked, made into a red context that looked and could not finish.

What the arm does and does not do

Keyed on the classification the floor already computes — the same long_home_prefixes() roster required_floor_site_disposition folds to reach DeclinedLongModule, matched on the module's authored name, not its path. No second list.

The verdict still gates: observed-only means the CPU figure is measured and published and decides nothing, the wall stays armed, and a semantic failure, panic, route gap or missing verdict is red under either policy. Only a rostered identity enters the cost-debt seen set — inserting a long-module witness would make a row look exercised that no roster line names, which is how a stale roster line hides.

The controls discriminate, and I checked that rather than assuming it

Reverting the arm to its pre-ruling behaviour:

FAIL changed_long_module_witness_takes_the_verdict_only_policy
PASS changed_short_module_witness_still_takes_the_ordinary_policy
FAIL every_long_prefix_selects_the_verdict_only_policy
PASS unchanged_long_module_witness_takes_no_verdict_only_policy

That split is the evidence: the two reds detect the arm's absence, and the two boundary controls are insensitive to it — so they guard the boundary rather than echoing the arm. An arm that cannot be shown to stop somewhere is indistinguishable from raising the ceiling, which docs/plans/floor-cost-distribution-near-the-ceiling.md refuses for this class. All three authored long prefixes are covered, because a one-prefix reading once excluded 42 rows of an expected ~310.

The drop is declared, and its trigger cannot discharge itself

This removes a standing wall, so gunbc.rung_drop long_module_changed_witness_cpu_observed_only declares it. The trigger names a capability in two halves: the front end paid once per run rather than once per claim, and a shared value that survives consumption. The netting half is already demonstrated (three producers stored at preparation, moving 868/496/571 ms out of the per-claim budget); the consumption half failed on that same run, which is the serve-boundary defect (adhoc-a2708dd9-252) and the whole-corpus prepare defect (#11060).

The row states explicitly that the three witnesses merely passing under observed-only does not discharge it — a trigger keyed on them going green would have retired the moment this arm landed, which is a drop that dissolves itself.

Why the fixed cost is not shrinkable: three snippets differing by 32% in size cost 503, 505 and 525 ms, with the shortest the slowest. There is no size term to cut.

46 witnesses green. Projection regenerated: 4 insertions, 0 deletions, no existing row moved.

🤖 Generated with Claude Code

https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f

…e control that keeps it an arm

Operator ruling A (via fierce-lark-661, 2026-09-11).

THE DEFECT IS A NICKNAME, which is why one arm closes it. The cost-debt roster
and the long home are ONE declaration class under two names -- both say this
identity is not run on an ordinary floor because the 500ms CPU line cannot carry
it, the roster per identity after measuring, the long home per module
structurally. changed_witness_cost_policy consulted only the first, so a changed
witness in a long module fell through to the armed line.

MEASURED, on gunbc#11004 at 6b153bf: touching one long module planned its three
witnesses as changed witnesses and all three were budget-refused BEFORE reaching
a verdict, at 503ms, 505ms and 525ms. None is planned on any ordinary floor, and
no green floor's claim-cost artifact carries a row for the module -- so no run
has ever paid that cost. The line applied only because a PR touched the file,
converting "this PR touched a long module" into three reds that say nothing about
the change. That is FLOOR-CHANGED-COST-0's own failure inverted: a green context
that never looked, made into a red context that looked and could not finish.

KEYED ON THE CLASSIFICATION THE FLOOR ALREADY COMPUTES, not a second list: the
same long_home_prefixes() roster required_floor_site_disposition folds to reach
DeclinedLongModule, matched on the module's AUTHORED NAME rather than its path,
for the reason that roster states.

THE VERDICT STILL GATES. Observed-only means the CPU figure is measured and
published and decides nothing; the wall stays armed, and a semantic failure,
panic, route gap or missing verdict is red under either policy. Only a ROSTERED
identity enters the cost-debt seen set -- a long-module witness is not a roster
member, and inserting it would make a row look exercised that no line names,
which is exactly how a stale roster line hides.

FOUR CONTROLS, AND THE PLANTED CHECK THAT SHOWS THEY DISCRIMINATE. Reverting the
arm to its pre-ruling behaviour fails changed_long_module_witness_takes_the_
verdict_only_policy and every_long_prefix_selects_the_verdict_only_policy while
changed_short_module_witness_still_takes_the_ordinary_policy and
unchanged_long_module_witness_takes_no_verdict_only_policy still PASS. That split
is the evidence: the reds detect the arm's absence, and the boundary controls are
insensitive to it, so they guard the boundary rather than echoing the arm. All
three authored long prefixes are covered because a one-prefix reading once
excluded 42 rows of an expected ~310.

THE DROP IS DECLARED AND ITS TRIGGER CANNOT DISCHARGE ITSELF. This removes a
standing wall, so gunbc.rung_drop long_module_changed_witness_cpu_observed_only
declares it, and the trigger names a capability in two halves: the front end paid
once per run rather than once per claim, AND a shared value that survives
consumption. The netting half is already demonstrated (three producers stored at
preparation, 868/496/571ms moved out of the per-claim budget) and the consumption
half failed on that same run. The row says explicitly that the three witnesses
merely passing under observed-only does NOT discharge it -- a trigger keyed on
them going green would have retired the moment this arm landed.

46 witnesses green; projection regenerated (4 insertions, 0 deletions, no
existing row moved).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
…ger rests on it

Review 63937. I copied instrument output into prose in three places -- the
per-claim milliseconds in the required_floor annotation, the drop row's header
and restoration_trigger, and the seed comment -- which DESIGN section 6 forbids:
name the producer that re-derives a measurement, never copy its numbers, because
a transcribed number is unreachable from the thing that owns it and rots without
anyone touching either end.

IT WAS LOAD-BEARING, NOT DECORATIVE, which is why the reviewer was right to
block on it. The trigger's claim that netting is "already demonstrated" rested on
three copied figures that no entry point re-derives, in a row whose whole purpose
is to say when a declared drop retires. A reader cannot check that claim and
cannot tell when it stops being true.

The text now names the producers: the floor's per-claim cost receipt for the run
(its BUDGET-REFUSED announcements and the required-floor-claim-cost artifact) for
the refusals, and the run's pure-producer-share-warm phase receipt reporting
disposition=Stored for the netting. The qualitative facts stay, because they are
what the receipt says rather than what it measured: every one of the three
refused before a verdict, no green floor's artifact carries a row for the module,
the receipt orders the three independently of their source sizes with the
shortest slowest, and a paired before/after moved two of three the wrong way.

The 500ms line stays a number because it is a declared policy constant rather
than a measurement -- the same distinction the corpus's own precedent draws when
it cites a run and an artifact beside its budget figure.

I quoted this rule correctly in another annotation on this branch while breaking
it three files over. Acknowledging a rule in prose is not following it.

Projection regenerated; my row carries no transcribed figure. Both modules
compile with 0 blocking errors.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Review 63937 fixed in 6874db41.

You're right, and the finding is sharper than "prose style": the transcribed figures were load-bearing. The restoration trigger's claim that netting is already demonstrated rested on three copied millisecond values that no entry point re-derives — in the one field whose entire job is to say when a declared safety regression ends. A reader can't check that claim and can't tell when it stops being true. §6's reason for the rule is exactly this: a transcribed number is unreachable from the thing that owns it, so it rots without anyone touching either end.

Removed from all three sources and the projection regenerated:

  • required_floor.dag's MEASURED block → names the floor's per-claim cost receipt for the run (its BUDGET-REFUSED announcements and the required-floor-claim-cost artifact beside them).
  • the drop row's header and restoration_trigger → names that same receipt for the refusals, and the run's pure-producer-share-warm phase receipt reporting disposition=Stored for the netting.
  • required_floor_runner.rs's comment → same citation, no digits.

The qualitative facts stay, because they are what the receipt says rather than what it measured: every one of the three refused before a verdict; no green floor's artifact carries a row for the module at all; the receipt orders the three independently of their source sizes, with the shortest source the slowest; and a paired before/after across a source-shortening change moved two of the three the wrong way. That last pair is what makes "there is no size term to shrink" checkable without a number in the prose.

500 ms stays, because it is a declared policy constant rather than a measurement — the same distinction the corpus draws elsewhere when it cites a run and an artifact beside its budget figure.

Worth recording: I quoted this rule correctly in a neighbouring annotation on this same branch while breaking it three files over. Citing a rule and following it are different acts, and the reviewer catching it is the system working as intended.

My row in docs/design-rung-drops.md now contains no transcribed figure (checked against the row's own section, not the whole file — other rows carry their own). Both modules compile with 0 blocking errors, and the run at the previous head came back success before this push.

— sent from calm-crane-722

… controls hold the seam

Review 63963, and the finding is one my own comment argued me into.

I kept long-home identities out of cost_debt_verdict_only, reasoning that only a
rostered identity may enter "the cost-debt seen set". That reason is TRUE of a
different set. cost_debt_seen is roster accounting -- it feeds
reconcile_withheld_against_dispositions, which asserts the withheld set and the
DeclinedCostDebt dispositions name the same identities, so a non-roster identity
there really would make a row look exercised that no roster line names.
cost_debt_verdict_only is the PROJECTION's policy source, with exactly one
consumer: changed_witness_projection_rows. I skipped the wrong one, and the
comment I wrote pointed at the right object under the wrong name.

WHAT THAT PRODUCED is the fabrication section 5 names. The claim executed under
the override -- CPU stood down, observation published -- and then the projection
rebuilt its policy from a set the identity never entered, so the row greened as
an ordinary planned-and-passed rather than planned-and-passed-with-cost-debt-
observed, and CostObservationMissingUnderVerdictOnly could never fire for it. A
gate stood down and an ordinary pass reported: exactly what
v2.workflow.floor_changed_witness forbids when it says the override "keeps the
COST FACT in the standing rather than laundering it into an ordinary pass".

Long-home identities now enter cost_debt_verdict_only. They still do NOT enter
cost_debt_seen -- neither branch writes it, which is why the declaration keeps
the two sets apart. I caught myself adding that insert mid-fix and took it back
out; it would have broken the withheld-to-disposition reconciliation.

THE DEFECT LIVED BETWEEN TWO CORRECT HALVES, which is why no existing control
saw it: the policy fold answered verdict-only, the standing fold projected
verdict-only readings correctly, and the seam between them disagreed. The three
new controls COMPOSE them -- the policy is taken from changed_witness_cost_policy
rather than written in by hand, so a control goes red if either half moves. A
hand-written ChangedCostDebtVerdictOnly would have tested the standing fold twice
and the join not at all, which is what left the gap open.

Planted check: reverting the arm fails both long-module controls and PASSES the
short-module one. The reds detect the defect; the boundary control is insensitive
to it. 49 witnesses green, 0 blocking errors.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Review 63963 fixed in 79f0aeb7. This one is worth spelling out because my own comment argued me into it.

The two sets are not the same set. I kept long-home identities out of cost_debt_verdict_only, with the reason "only a rostered identity enters the cost-debt seen set". That reason is true — of cost_debt_seen, which feeds reconcile_withheld_against_dispositions and where a non-roster identity genuinely would make a row look exercised that no roster line names. cost_debt_verdict_only is a different set with exactly one consumer, changed_witness_projection_rows. I skipped the wrong one, and the prose pointed at the right object under the wrong name — so re-reading it confirmed the decision rather than catching it.

What that produced is the §5 fabrication you name. The claim executed under the override — CPU stood down, observation published — and the projection then rebuilt its policy from a set the identity never entered, so the row greened as planned-and-passed instead of planned-and-passed-with-cost-debt-observed, and CostObservationMissingUnderVerdictOnly could never fire for that population. A gate stood down and an ordinary pass reported, which is precisely what floor_changed_witness forbids when it says the override "keeps the COST FACT in the standing rather than laundering it into an ordinary pass".

Long-home identities now enter cost_debt_verdict_only. They still do not enter cost_debt_seen — neither branch writes it. I caught myself adding that insert mid-fix and took it back out; it would have broken the withheld↔DeclinedCostDebt reconciliation, i.e. fixing one set-confusion by introducing its mirror.

Why no existing control saw it, and what the new ones do. The defect lived between two correct halves: the policy fold answered verdict-only, the standing fold projected verdict-only readings correctly, and only the seam disagreed. So the three new controls compose them — the policy is taken from changed_witness_cost_policy for a long-module identity rather than written in by hand:

  • a_long_module_changed_pass_carries_its_cost_debt_observation
  • a_long_module_changed_pass_without_a_measurement_is_red (so the new red can reach this population at all)
  • a_short_module_changed_pass_is_an_ordinary_pass (the boundary)

A hand-written ChangedCostDebtVerdictOnly in those tests would have exercised the standing fold twice and the join not at all — which is exactly how the gap stayed open.

Planted check: reverting the arm fails both long-module controls and passes the short-module one, so the reds detect the defect and the boundary control is insensitive to it. 49 witnesses green, 0 blocking errors.

On the previous run at 6874db41: the floor refused with MemoryStallRefusedPageThrash (306,617 major faults/minute at 4% CPU share) — the rostered host-oversubscription class, unobserved rather than red. The build lane passed and the floor never reached a verdict; this push is the next observation.

— sent from calm-crane-722

Brian Searls and others added 2 commits September 11, 2026 20:49
…ved rather than resolved

#11023 and the 19:00-20:20 landings put another rung-drop row on main, so the two
conflicts were the tracked roster and the document it generates -- two lanes each
appending one row.

THE ROSTER KEEPS BOTH, main's first because it landed first, and the order
matters: gunbc.design_ledgers renders the ledger by folding this list, so the
list IS the document's order. Taking either side alone would have deleted a
landed drop declaration -- the same both-sides property as the failure-mode row
conflict earlier tonight, and the same reason a side-take is wrong on an append.

THE PROJECTION IS REGENERATED FROM THE MERGED AUTHORITIES, NOT RESOLVED BY HAND
OR LEFT TO HEAL. docs/design-rung-drops.md is generated from gunbc.rung_drop; a
hand-merge of its text would be a second authoring of a derived file, and leaving
it to heal would re-author it after the push, MOVE THE HEAD, and spend the
approval this PR already holds. So: resolve the roster, regenerate, verify, then
commit. Verified by content rather than by the regen's exit code -- both rows are
present in the output (mine and the v1 consumer census one), and the projection
diff is six insertions with nothing displaced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
…e push

The first merge resolved against main at ad5609b; #11055 landed at 011877f
while its compile check was running, so pushing then would have shipped a merge
of a stale main and gone BEHIND on arrival. Checked with merge-base rather than
assuming the tip had held still.

This merge is clean: #11055 touches dag/gunbc/ and this branch touches
dag/gunbc/rung_drop/ and v2.workflow.required_floor, so nothing overlaps. NO
PROJECTION REGENERATION IS OWED -- the only rung_drop differences against main
are this branch's own row and roster line, so #11055 added no drop and
docs/design-rung-drops.md is still the projection of the merged authorities.
Verified by diffing the rung_drop directory against main rather than by
re-running the regen and trusting a zero.

Both authorities compile against the merged tree: the policy arm's witnesses and
the rung_drop roster, 0 blocking errors each. A clean text merge does not
establish that the merged tree resolves, which is the whole reason that check
exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Correction before landing: one sentence in the drop row's restoration_trigger is falsified. The trigger itself is not.

dag/gunbc/rung_drop/long_module_changed_witness_cpu_observed_only.dag says, inside restoration_trigger:

The consumption half failed on that same run: every claim reading a served normalized tree errored with no field kind on type NormalizedTree [...] Until a served tree answers field access the deriving frame answered, netting cannot be turned on

That error was not a serve-boundary defect. It was a type error in the probe fixture on the measuring branch: ProbeNormalized.root is declared Node, and the branch passed the NormalizedTree wrapper (root: normalized) instead of root: normalized.root. 37e643d7f6 (#11025) repaired that site on main, and git merge-base --is-ancestor confirms it is not an ancestor of the head I measured on (8c80a9a5f4). Both of my readings of that error were therefore of the same authored defect, and neither was evidence about the preparation/consumption boundary. zesty-moth-312, the lane that owns that question, bisected it to the same line with claim_batch on one binary and reports the share served exactly the value the producer built.

What this does not change, and why the row still stands. The drop rests on the cost, which none of this touches: the per-claim front end is a fixed charge with no size term, and the floor's own per-claim cost receipt still reports all three claims refused at the line before reaching a verdict. The capability the trigger names — netting that survives consumption, so a long-module claim's measured CPU is its own work — is unchanged and still unmet. A stale rationale beside a correct trigger does not retire or mis-retire the drop, which is why this lands as a comment rather than a new head (operator ruling).

Where the fix goes. #11004 carries the rewrite: the blocker sentence becomes the measured fact (fixed per-claim front end, no size term), with the withdrawal recorded explicitly rather than dropped silently — the false claim is what scoped this row, so deleting it quietly would erase the reason the scope is what it is — and both halves kept as a capability to be demonstrated at retirement rather than assumed. The same push carries the §6 annotation fix review 64058 named in floor_changed_witness_test.dag.

— sent from calm-crane-722

No code change. Three prose corrections held for one push because each
re-spends the approval on its own.

1. required_floor.dag stated the OLD one-name rule in present tense beside
the two-name implementation (fierce-lark hold). "A changed identity not
enrolled in the cost-debt roster keeps ordinary policy" and "membership
comes from floor_cost_debt_holds" both describe a function that no longer
exists: ordinary now means selected-as-changed AND neither cost-debt
rostered nor long-home classified, and the expensiveness authority is
changed_witness_expensiveness_is_declared = floor_cost_debt_holds(identity)
OR first_module_prefix_match(module, long_home_prefixes()). An annotation
that names one of two disjuncts sends a reader to a rule the code stopped
following.

2. The drop row's restoration_trigger cited a blocker that is FALSE. It
said netting cannot be turned on because a served NormalizedTree loses
field access, quoting "no field 'kind' on type 'NormalizedTree'". That was
a type error in the probe fixture on the measuring branch, which passed a
NormalizedTree where ProbeNormalized.root is declared Node; 37e643d
(gunbc#11025) repaired that site and the measuring head did not carry it,
so both readings were of one authored defect and neither was evidence about
the serve boundary. zesty-moth-312, which owns that question, bisected to
the same line. The withdrawal is RECORDED rather than deleted, because the
false claim is what scoped this row: the trigger now rests on the measured
fact -- a fixed per-claim front end with no size term -- and keeps survival
of consumption as a capability to be DEMONSTRATED at retirement rather than
asserted as a current defect.

3. floor_changed_witness_test.dag transcribed three millisecond figures
into an annotation (review 64058, which named it and declined to raise it).
The producer is named instead, as DESIGN section 6 requires and as the drop
row already did.

Evidence: claim_batch over all 49 witnesses of floor_changed_witness_test,
rc=0, 49 PASS; gunbc compile of gunbc.rung_drop.roster, 0 blocking errors;
docs_projection_gate regen, one line changed in docs/design-rung-drops.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
@gunbai-bot
gunbai-bot Bot merged commit 278dd37 into main Sep 11, 2026
4 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/calm-crane-722-long-cost-arm branch September 11, 2026 23:58
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.

0 participants