Repository navigation
Identity-bearing required-lens registration, and a closed registration/observation join at the compile door - #11004
Conversation
…n/observation join at the compile door
Step 1 of the compile-obligation activation brief: make the required-lens
roster name its lenses, so "the required lenses ran" stops being a claim
about a list length.
- One registration roster (required_compile_lens_roster), partitioned by
grain through required_lenses_at_grain, replaces the two lists
always_required_lenses / always_required_root_lenses. Each row carries
the DeclarationRef of the gate authority that decides it plus its grain.
- LensGateWitness carries the lens identity and the grain it was produced
at, so every observation names its producer.
- join_required_lens_coverage closes the join bidirectionally and refuses
by name: RequiredLensRosterEmpty, RegistrationDuplicated,
RegistrationUnobserved, ObservationUnregistered, ObservedAtWrongGrain,
RootLensObservedMoreThanOnce. Root grain states exactly-one; subtree
grain is at-least-one, because subtree registrations are observed once
per node by construction.
- validate_then_compile runs each lens at its registered grain (caller
lenses included, which previously ran at root whatever they declared),
derives the coverage from the witnesses it actually collected, and
refuses the compile when it is not closed. Validated carries the
receipt with the roster digest.
Divergence from the brief, stated: one CompileLens carrier gains the two
fields rather than a second RequiredCompileLens type. Requiredness is
membership in the roster, not a property of the carrier, and a caller
lens must stamp its witnesses the same way for the join to be closed.
Evidence, by execution (claim_batch, local release build):
- v2.test.lens_application.required_lens_coverage_join: 7 witnesses green
- one positive control over the real roster,
- one control that runs all eight registered gates through the door's
own two runners and joins the witnesses they actually stamped,
- five discriminating REDs, one per refusal arm, each asserting the
cause AND the lens identity.
- the eight touched pre-existing lens witnesses: all green.
Not established, and not claimed: an Accepted validate_then_compile
carrying the receipt. No fixture in this corpus reaches Accepted through
that door today (measured on fixture_add_resolved_tree in TranslateTo and
Eval; the refusal is upstream of the lens rosters). That frontier is
recorded in the test module's header.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
…iminates (test-only) door_root_roster_runs_and_passes_clean_tree called validate_then_compile and accepted EITHER an Accepted compile OR any Rejected whose diagnostics lacked the poly2 suspect. Measured: the door REFUSES this fixture, so the check was green on a refusal and would have stayed green if the root roster had stopped running altogether — a permanently-green check cited as coverage (DESIGN §4b). The refusal is now located, and it is neither infer nor the root roster: infer Accepts fixture_add_resolved_tree, the root-required roster Accepts the inferred tree, and the SUBTREE-grain roster refuses it. So the control becomes door_root_roster_accepts_clean_inferred_tree: infer must Accept and every root-registered gate must Accept the real inferred tree, with no tolerance for an unrelated refusal. The module header's claim that the fixture "passes through the root-required roster ... proving the roster RUNS on every door call" is corrected to the root-roster claim it actually supports, and the now-unused stub target and its imports are removed. The door-grain positive control (an Accepted validate_then_compile carrying its coverage receipt) stays a declared frontier in v2.test.lens_application.required_lens_coverage_join. Evidence: door_root_roster_accepts_clean_inferred_tree PASS. The module's other three witnesses (gate_red_quadratic_rejects, gate_green_identity_accepts_clean, gate_refusal_ledger_counted_not_gating) fail on the interpreted path with "no field 'kind' on type 'NormalizedTree'" BEFORE this change as well — verified by running them on the committed file — so they are untouched by it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
gunbc.witness_deferral_freeze names (entry, function) pairs at identity grain and REFUSES a row naming a witness the tree no longer carries as a stale freeze row. Renaming door_root_roster_runs_and_passes_clean_tree in the previous commit made its row stale, so the roster's own wall would fire on this branch. One field, the new name. This also explains why the re-scoped control's three sibling witnesses in the same entry were red without anyone noticing: the whole entry is a LegacyFrozenPathDeferral, i.e. admitted by path policy with no executing consumer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
srv2 167-member closure receipt (closure-neutral; emitted compiler builds with the new
|
…prohibition forward (review 63457)
Two findings, both real, both verified against the current tree.
1. STALE CITATIONS. required_lens_grain_note was re-asserted verbatim while
both symbols it is about — always_required_lenses and
always_required_root_lenses — were deleted in the same diff, and five more
prose sites named them too. A replacement migration that cuts over at the
root owes the citation cut-over in the same motion (DESIGN §3 standing
rule). The note is rewritten to carry the same cost argument in terms of
what survives — a CompileLensSubtree registration runs per subtree node, a
CompileLensRoot registration runs once at the root, grain is a FIELD and
required_lenses_at_grain derives each execution's list — and it now also
records that a caller-supplied lens runs at its own declared grain. The
other five: v2.lens.determinism, v2.lens.mandatory_tag,
v2.lens.mandatory_tag.corpus_scan, v2.lens.machine_shape,
v2.lens.undecidable_verdict_collapse, v1.compiler.emit_rust,
gunbc.declaration_index_seed_growth, and
test.claim.computation_demand_duplication_witness.
2. DROPPED PROHIBITION. The lens_module_gate de-enrollment rationale was
deleted with the old root roster and nothing carried it forward — a standing
prohibition tied to a named red class (lying_substrate_inputs_only_stamp_census,
31 stamps). Worse, the replacement text invited the regression it warned
about ("Adding a lens is one row") with no eligibility statement. It is
carried forward in force beside the roster, plus the eligibility rule it
implies: a row must be a PURE FOLD OVER THE TREE BEING COMPILED at its
declared grain; a nullary gate, a corpus scan, or any gate reading the live
tree rather than its InferredTree argument is ineligible at either grain.
Not done, and stated rather than left silent: three test MODULES still carry
the deleted symbol in their own names
(lens_fact_density.hollow_alias_blocked_via_always_required_lenses and the two
lens_unit_modeling siblings). Renaming them is a file-and-module rename whose
citations include gunbc.live_deploy.srv1_residue_rehearsal — a RECORDED PATH
WIRE, i.e. an observation receipt — and dag/gunbc/witness/witness_row_cost_basis.tsv.
Editing a recorded observation to match a rename is not a citation repair, so
that cut is its own change.
Evidence: the coverage-join witnesses re-run green after the edits
(required_lens_coverage_closes_over_executed_gates_holds,
required_lens_coverage_refuses_unobserved_registration_holds).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
|
Both findings in review 63457 verified against the current tree and fixed in 1. Stale citations — confirmed, and wider than the note. Also cut over: 2. Dropped prohibition — confirmed, and the new text did invite the regression. The Not done, stated rather than left silent. Three test modules still carry the deleted symbol in their own names ( Evidence: the coverage-join witnesses re-run green after the edits ( — sent from calm-crane-722 |
git add -A in the citation-cutover commit swept two untracked 4a files that had followed a branch switch into the worktree: dag/std/realization_cost_fidelity.dag and dag/test/claim/realization_cost_fidelity_witness_test.dag. Neither belongs here — 4a's design was still undecided when they were committed, and this PR is registration plus the citation cutover plus the de-enrollment prohibition and nothing else. They move to their own branch and land after their own closure receipt. The other three files in that commit stay: declaration_index_seed_growth, computation_demand_duplication_witness_test and v1.compiler.emit_rust are one-to-three-line citation cutovers of the deleted roster symbols, which is exactly what review 63457 asked for. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
…465) The SPECIMEN receipt named v2.test.lens_application.required_lens_coverage_join as the home of the door-grain frontier. That module is declared in #11004, which is not merged, so on this branch and on base the citation resolves to nothing — the exact defect DESIGN §3's standing rule exists to prevent, and it was load-bearing for the row's "wall behind that frontier" claim. The row now states the CONSEQUENCE instead of pointing at a file: while a mandatory gate refuses the corpus its door must admit, a door-grain positive control is not authorable at all, so any coverage receipt attached to that door necessarily lands with its positive control declared as a frontier. The link is the class, not the file name, and the row says explicitly why it does not cite the module. Nothing else changes; every remaining citation in both rows resolves on main. Verified: the module resolves and evaluates (gunbc run reaching `authored`'s arity check, i.e. past parse and typecheck). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
Both verified; both were real. - v2.test.long.mandatory_tag_gate_witness: the file is already in this diff (its import moved to required_lenses_at_grain / CompileLensRoot), so its prose and its code disagreed inside one file. Now "the CompileLensRoot partition of required_compile_lens_roster". - docs/plans/determinism-boundary-relative.md: the citation sits inside a block the file's own header declares "preserved verbatim" from a DESIGN.md row deleted on operator ruling. Rewriting a symbol inside a quotation falsifies the quotation, so the quoted sentence is left as authored and the current symbol is named beside it in brackets — the same reason the three test-module renames are not folded into this PR. Remaining hits are src/v1/stage0/**, the seed's own mirror of this module, addressed on the PR rather than edited here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
|
Both fixed in
You misread the stage0 hits, and it is worth knowing in which direction. I am not fixing it in this PR, and the reason is not scope-aversion: that module is the independent oracle this change is checked against, and editing the oracle in the same push as the subject removes the independence for exactly the run that matters. It also widens a registration change into a seed edit whose bootstrap blast radius is its own review. It is reported to the lane owner as its own item; if the call is to fold it in, say so and it is one string.
— sent from calm-crane-722 |
srv2 167-member closure receipt, re-taken at
|
…, not documentation (review 63517) I argued the opposite an hour ago and I was wrong, for a reason worth writing down: I reasoned from a general principle — do not edit the independent oracle in the same push as its subject — without checking whether anything ASSERTS EQUALITY on the string. Something does. dag/gunbc/instruments/self_host_00_compile_shims/witness_main.rs compares emitted::required_lens_grain_note() against seed::required_lens_grain_note() and makes equality the Gate-A behavioral receipt. So this literal is not a mirror of the authority for a reader's benefit; it is the value the self-host equivalence claim is made of. Changing the .dag without it does not preserve the oracle's independence — it falsifies the receipt my own change is supposed to keep true. The reviewer measured the divergence (1288 vs 934) that I had asserted away. The seed literal is DERIVED from the .dag line rather than retyped, and byte-equality verified programmatically: equal? True, 1288 == 1288. cargo check on the seed lib is clean. The oracle's header now says what it actually is — the compared value, which cuts over with the authority — so the next reader does not repeat my reasoning about independence. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
|
review 63517 is right and I am reversing my earlier position on this PR. Fixed in What I got wrong, and why it is worth stating rather than just patching. Earlier in this PR I argued the opposite — that the stage0 oracle should not be cut over here, because editing the independent oracle in the same push as its subject removes the independence for exactly the run that matters. That reasoning is sound in general. It is wrong for this string, and I never checked the one thing that decides it: whether anything asserts equality on it. Something does. The fix, and how it was verified rather than eyeballed. The seed literal is derived from the I also changed the oracle's header to say what it actually is, so the next reader does not repeat my reasoning:
One note on the §7 framing, which I think is exactly right and is the part I would have missed even after fixing the string: the seed-retained oracle is the self-host differential, so "do not touch the oracle" and "the oracle must agree with the authority" are not in tension — the oracle is independent in its derivation, not in its content. — sent from calm-crane-722 |
|
The failing check on What failed: followed by the runner losing its own action cache: So Why not re-run now: this PR is held from merge pending the D-train, and when it is released it must re-merge main and take a fresh closure receipt anyway — so a run started now is a run that gets superseded, on a runner pool that is currently the binding constraint for three other PRs and for main itself (main is red on the floor at The check will be re-run as part of the post-D4 remerge, which is the point at which its result means something about the head that will actually land. — sent from calm-crane-722 |
…tree, without stopping at the first no WORK IN PROGRESS, STACKED ON #11004, NOT FOR REVIEW HERE. It is committed so this branch stops being a verbatim copy of #11004's head; it lands as its own PR from main once #11004 is in. The compile door answers a DECISION: the first refusing obligation rejects and nothing behind it is asked. That is right for a gate and useless for a census — knowing that one obligation refuses the compiler's own tree says nothing about the other seven, and "repair it and see" is a serial walk of unknown length. Complexity-first is a RANKING, and you cannot rank repairs across obligations you have not measured. - v2.compiler.compile: the runner gains a MODE PARAMETER rather than a twin. run_required_lens_gates_in_mode / _on_subtree_in_mode carry it; the existing entry points become thin enforcing callers, so the door's behaviour is unchanged. The ledger therefore shares the door's registration AND traversal and differs only in the mode argument — a second traversal would be a second answer to "what would the door say" and would drift the first time either moved (§3). - v2.compiler.self_host.compile_obligation_ledger: all eight registrations over ONE prepared InferredTree, every answer reported, keyed by lens identity and grain, carrying the roster digest so two ledgers can be compared. Four things the module states about itself, each load-bearing: - It is NOT a gate. It decides nothing and admits nothing, and no consumer may read a clean ledger as an accepted compile — validate_then_compile remains the single gate authority. - The tree is prepared ONCE by the caller, and there is deliberately no per-file entry point: the corpus roster gate's per-subject path re-tokenizes and re-parses every file and is CI-excluded for that cost, so a census built on it would be a cost defect wearing a census's name. - ObligationLedgerUnobservable is a real arm. An observation that could not be made is not one that passed, because a vanished row and a holding row are indistinguishable in a count (§5). - Rows stay at observation grain rather than collapsing per registration: collapsing discards WHERE a subtree obligation refused, which is the fact a repair needs. This is the production consumer CompileLensIntrospect was built for; until now it had only witness-level consumers. Evidence, four witnesses green on the interpreted path — and that is the ENTRY RUNNER's verdict, not the floor's, which is the distinction filed in #11028 and already wrong once today in exactly this direction. The discriminating control runs the ledger over a tree the DOOR REFUSES: there the door reports one refusal and nothing behind it, while the ledger must report every registration, at least one violating, and the rest still holding. The door's refusal on that tree is executed as its own premise control, so if it ever goes green the control announces that it has stopped discriminating. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
… receipt and none is authored LOCAL COMMIT, NOT PUSHED, on the step-2 ledger branch under the same terms you approved for step 2: authored against #11004's frozen API, becomes a branch-from-main when #11004 lands. All eight required compile lenses are ALREADY registered and ALREADY run on every validate_then_compile call. Nothing here adds a switch, a flag, or an enrolment step, because none is missing. What is missing is EVIDENCE, so this authority is a derivation from receipts to a state and the state is never authored: a data row saying "accumulator_copy: Qualified" would be a claim with no producer, which is the rung inflation §4b names. THE LADDER, and only the last three are on: Registered, Reached, Executed, Qualified, Observed, ClosureClosed, CandidateEnforced, SuccessorEnforced, SeedIndependent. Each rung requires its own receipt AND every receipt below it, so a late receipt supplied early cannot lift a missing foundation — which is how an activation board comes to read higher than the system it describes. Four things the design insists on, each with a control that withholds exactly one receipt: - QUALIFICATION IS TWO RECEIPTS. A gate that refuses everything refuses the planted red too, so a caught red alone establishes nothing; the accepted green is what separates a wall from a wall that is permanently down. Withholding only the green drops the state to Executed. - UNCLASSIFIABLE RESIDUE CLOSES THE CLOSURE ONLY IF CARRIED BY NAME. Silent residue holds it open; named residue is open coverage someone can close. - A BUNDLE REPORTS ITS WEAKEST MEMBER (§4b(1) applied to a group). Complexity is the accumulator-copy gate AND the realization-cost fidelity join; determinism is the gate AND the traversal-order facts AND non-primitive reachability, because absence from a declared roster is not evidence of determinism. - THE PROGRAM IS ITS WEAKEST OBLIGATION. No average, no count, no majority: seven qualified and one registered is a program at Registered, because the door admits a program only if every required obligation admitted it. Coverage joins both directions — a node with no registration is a board row with no subject, a registration with no node is an obligation nobody tracks — and both refuse rather than go quiet, exactly as the door's own registration/observation join does. The ledger supplies the Observed receipt and nothing else: it can raise an obligation to Observed and can never raise it past ClosureClosed, because what it reports is what the obligation SAID, and whether findings were repaired is a different fact with a different producer. Thirteen witnesses green on the interpreted path — the entry runner's verdict, not the floor's. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
…mar (review 63628) LOCAL COMMIT, NOT PUSHED: #11026 is held and under a no-push rule. Committed so the work does not follow a branch switch, which is how the 4a drafts leaked into #11004 earlier today. std.induction already owns a sum-of-products cost algebra over named parameters: AtomicCost (PolyCost { param, exponent } / LogCost { param }), ProductBound, SumOfProductsBound — and owns it more completely than what I wrote, since PolynomialExponent carries fractional and log-based exponents my four-factor grammar could not express. The equivalences are exact: cost_nlogn IS linearithmic, and cost_graph_linear IS the concat specimen, already in the corpus. So I minted a second cost grammar — §2 failed decomposition, §3 nicknaming — in the change that argued a second cost vocabulary beside a consumer is the fork §3 forbids, in a module whose subject is a cost authority disagreeing with itself. I DFS'd CostShape and stopped there instead of following the concept DAG one step further. - std.algebra: CostFactor / CostTerm / StructuredCost deleted; CostShape stays, with an annotation recording the failed decomposition and naming CostBound. - std.induction: AtomicCost gains CallerBodyCost { param } plus cost_iterate_body — the one fact genuinely absent, and the reason a projection from this authority could not reach ShapeIterateBody at all. Nothing outside induction.dag matches on AtomicCost, so the arm adds no obligation elsewhere. - The growth derivation and the CostShape projection move to std.induction, beside the carrier they read: ParamGrowth { degree, logs, bodies, representable }, lexicographic on (degree, logs), body held out of the order, and representable:false for fractional exponents, log-based exponents, ForeverBound and ErrorBound — a real bound this reading cannot order says so rather than rounding. - The join consumes CostBound and speaks its vocabulary (param_*, not operand_*): having renamed the authority, keeping a second name for its parameters would be the same defect one scale down. Nineteen witnesses green, every verdict preserved across the migration, plus one control that only became AUTHORABLE on the richer authority: cost_sqrt exists in std.induction, and a fractional exponent must not round to a shape. The specimen witness now reads cost_graph_linear(v_param: "left", e_param: "right") — a constructor that was already there, which is the plainest statement of what the review caught. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
…L, CITED-DECLARATION-ABSENT) required-ci: declarations FAIL CITED-DECLARATION-ABSENT dag/gunbc/recurring_failure_mode/stale_present_tense_coverage_claim_in_the_authority_consulted_first.dag:47:5 cites v2.compiler.compile always_required_root_lenses, which that module does not declare Mine, and the same class I swept eight sites of in this PR: a replacement migration owes the citation cut-over. The reason this one was missed is worth recording — the row did not exist when I swept. It landed on main afterwards with #10942 (the compile-obligation census), citing a symbol this PR deletes at its root, so the break appeared in the merge rather than in either change. Neither lane could have seen it alone: the census cited a declaration that was live on main, and my sweep covered every citation that existed at the time. - The evidence decl_ref now names required_compile_lens_roster, which is what replaced it and what the row's argument is actually about. - The row's prose cited the same symbol in its specimen sentence and cuts over with it. - gunbc.v2_compile_obligation_census names the deleted symbol in two annotations; both now name the surviving roster, and the one about staleness says explicitly that the argument does not turn on there having been two lists. Deliberately untouched: the census's entry/function/module_path rows for hollow_alias_blocked_via_always_required_lenses and its two siblings. Those are module and function IDENTITIES that still resolve, not symbol citations — their rename is the separate cut whose citations include a recorded path wire. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
… cuts over (review 63812) 1. MY OWN HEADER CLAIMED SOMETHING FALSE. The module said "one discriminating RED per refusal arm" and the PR body said "five discriminating REDs, one per refusal arm", while RequiredLensJoinCause has SIX arms. RegistrationDuplicated — the arm whose whole job is catching a roster that acquired a second row for one identity — had no control asserting it ever fires. The "unreachable at the door" defence does not hold, and §4b decides it at the fixture rather than at the door: a state unrepresentable in the accepted corpus may still be representable as source handed to the join by a fixture, and where the refusal is authorable there, declining it is specification without execution. The sibling REDs already hand the join synthetic rosters, so it was one call — append a repeated row — which is what makes the omission indefensible rather than a judgement call. Eight controls now, and the header claim is true. 2. THE THIRD MERGE-ONLY CITATION TODAY. v2_compile_obligation_census_witness_test names both deleted symbols in its "what is still not checked" annotation. That file arrived with #10942 AFTER my citation sweep, so the break exists only in the merge, exactly like the two the declarations phase caught. It now names required_compile_lens_roster, and records that the gap it describes never turned on how many lists there were. Left alone deliberately, again: the entry/function/module_path rows for hollow_alias_blocked_via_always_required_lenses. Those are identities that still resolve, not symbol citations. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
|
Both fixed in 1. The header claim was false, and I wrote it. The "unreachable at the door" observation is true and is not a defence, and §4b settles where the question is decided: a state unrepresentable in the ACCEPTED corpus may still be perfectly representable as source handed to the compiler by a fixture… if the refusal is still authorable there, the evidence is enrollable there and declining it is specification-without-execution. The sibling REDs already hand the join synthetic rosters, so this was one call — 2. The census witness citation. Cut over to That is the third instance today of the same shape, and it is worth naming since it will keep happening: Untouched deliberately: the — sent from calm-crane-722 |
… 63827) The rename in this PR (always_required_root_lenses -> required_compile_lens_roster) updated seven sibling citations and missed one: the mandatory-tag scaffold comment in the seed's cli_run.rs still named the deleted symbol as where the modeled lens is enrolled. At this head it was the only surviving live citation -- the remaining grep hits are witness function names and module paths, which are not citations of the symbol. It now names the registration as it actually stands: required_compile_lens_roster at CompileLensRoot grain, the mandatory_tag_lens row. That is the point of the rename -- the grain is a field on the row rather than a fact about which of two lists a lens was written into -- so the citation has to say the row, not the list. This is the class the PR itself edits (DESIGN 3: a stale name is decidable and enforceable). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
|
Review 63827's finding is correct and is fixed in c12c66c. I verified the claim rather than taking it: at The comment now names the registration as it actually stands: Thank you for checking whether the file was a projection before recommending a hand edit; it is hand-maintained seed Rust, and had it been generated the repair would have belonged in the authority instead. On the run at this head: the floor's measurement completed (3625 passed, 0 failed) with one identity budget-refused at 507/500 ms cpu while the host was page-thrashing at 300-400k majflt/min — an unobserved host condition rather than a result, so this push's run is the observation. — sent from calm-crane-722 |
…ed import goes Review 63842. The distinction the review draws is the right one and I am keeping it: the JOIN is consumed by execution in this change -- validate_then_compile refuses a compile whose coverage is not closed -- so the gate was never the dangling part. The receipt CARRIED on Validated is a separate declaration with a separate consumer, and nothing outside this module reads it today. The prose that was there named a consumer (the obligation census) and stated no trigger, which is a half-classification: DESIGN section 3c admits a frontier only with the trigger beside it, precisely so that "a later change will read this" cannot be said indefinitely. The field now carries consumer, route and trigger, with the trigger stated as a CAPABILITY -- the promotion path routing its candidate through this door and refusing on a named uncovered lens, sufficient that a candidate cannot be promoted without its coverage having been observed on the same compile that produced it. It also states the kill condition, because a frontier that cannot expire is not a classification: if that capability does not land, the field is redundant work and the honest move is to DELETE it, since the refusal is already the gate. WholeDeclaration was imported and never used; removed. 8 join controls green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
MEASURED FIRST, because the cut I was about to make was aimed at the wrong thing. claim_batch over this module's four witnesses in one remote dispatch: the three source-path rows cost 534-680ms of CPU against a 500ms per-claim ceiling, while door_root_roster_accepts_clean_inferred_tree -- same gate area, hand-built node fixture, no front end -- costs 50ms. Three DIFFERENT four-line snippets spread only ~150ms over a ~530ms base, so the base is the front end itself, not the snippets. Shrinking the planted ledger could not have moved a 680ms witness under 500ms when its two ledger-free siblings pay 534 and 618 for the same prefix. The consequence that matters more than the one failing row: ALL THREE source-path witnesses here are at or over the ceiling on an unloaded runner. gate_refusal_ledger_counted_not_gating is not defective beside three healthy ones; it is the one 80ms above its nearest sibling. Host thrash is why it trips today, the budget is why it would trip anyway. THE CUT KEEPS THE SOURCE PATH. The three claims are now nullary producers enrolled WARM in v2.workflow.floor_pure_producer_share, so the floor forces each once during strict preparation, outside every per-claim budget, exactly as v2.test.claim.parse.d1_declaration_grammar_parse does for the identical defect (seven of its eight rows were interrupted at this same ceiling). Nothing about what executes changes: same source, same tokenize, same parse, same normalize, same tree, paid once. The alternative -- moving the ledger assertion onto a hand-built fixture -- would have bought the budget by trading what the witness proves, ledger behaviour on a tree the real front end produced. DESIGN 4b(1) prices that as a rung drop, not a cost fix. SEAM CHOICE, and it differs from the d1 precedent deliberately: that module shares at the PARSE tree because some of its claims name normalize as their subject, and sharing normalize would stop them executing the stage they claim. No witness here names any front-end stage -- all three branch on the normalized root and assert about accumulator_copy_compile_gate -- so the whole front end is upstream of every subject in this file and the honest seam is its output. VERIFICATION BOUND, stated because it is real: claim_batch under my invocation refuses this module with "no field 'kind' on type 'NormalizedTree'" inside normalize while the floor accepts it (3625 passed, 0 failed at this head), so I cannot execute these three witnesses locally at all. What I verified is that both modules parse in a whole-corpus index and the roster fold evaluates with the three rows present. Whether the NormalizedProbe value reifies portably is decided by the floor, and a warm row that refuses to store STOPS THE LINE rather than degrading -- the precedent shares Outcome<Node>, the same shape class. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
|
Pushed 540c92c — the per-claim cost of this PR's touched witness, cut at the place the measurement pointed rather than the place it was first assumed to be. Why the obvious cut was wrong. The blocker is
Three different four-line snippets spread ~150 ms over a ~530 ms base, so the base is the front end, not the snippets — and the ledger-free siblings pay 534 and 618 for the same prefix. Shrinking the ledger could not have moved a 680 ms witness under 500 ms. The larger fact: all three source-path witnesses here are at or over the ceiling on an unloaded runner. This one is not defective beside three healthy ones; it is the one 80 ms above its nearest sibling. Host thrash is why it trips today; the budget is why it would trip anyway. The cut keeps the source path. The three claims are now nullary producers enrolled WARM in I did not move the ledger assertion onto a hand-built fixture. That buys the budget by trading what the witness proves — ledger behaviour on a tree the real front end produced — which §4b(1) prices as a rung drop, not a cost fix. One deliberate divergence from the precedent: Verification bound, stated plainly: Review 63865's approval noted, with nothing actionable in it. — sent from calm-crane-722 |
…rved value did not survive MY PREVIOUS COMMIT BROKE THREE PASSING WITNESSES, and this withdraws it. The floor at 540c92c reports all three accumulator-gate claims failing with "no field 'kind' on type 'NormalizedTree'", cause=claim_failed. They pass when each claim derives its own tree. That is a regression I introduced, and a budget refusal traded for three failing witnesses is strictly worse than the budget refusal. WHAT THE EXPERIMENT ESTABLISHED, because it is not nothing. The netting worked exactly as ruled: disposition=Stored for all three producers during strict preparation, 868ms, 496ms and 571ms of front end paid outside every per-claim budget. That is the diagnosis confirmed by execution rather than by argument -- the front end IS the per-claim cost in this module, and the shared-producer tier does move it. AND IT RESOLVED THE EARLIER MYSTERY IN THE OTHER DIRECTION. I had reported the claim_batch-vs-floor disagreement on this module as an instrument quirk, because the floor was green on the same witnesses my instrument refused. It is not the instrument: the floor now reports the SAME error the moment the normalized tree is produced outside the frame that consumes it. Two observations, one mechanism -- a normalized tree does not survive being handed across that boundary. The instrument was never the variable, and I said it was. WHAT RETURNS THE ROWS, as a capability: a normalized tree that survives the cross-claim serve boundary, so the value a claim is handed is the value it would have derived. The producers stay as plain helpers -- each claim calls one and derives its own tree, exactly as before the share -- so this file is now behaviourally identical to the pre-cut state with the measurement recorded in it. The per-claim front end therefore stands, and the budget question it raises is a budget question rather than a witness question. No witness here should be moved onto a fixture to buy it: that trades what these witnesses prove. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
Semantic-neutral by construction: only names shrank -- module names, the list binder, the lambda binders. The RED still copies the accumulator through list_append inside the fold, the GREEN is still its non-copying twin, and the ledger probe still calls a combiner no registry knows. No arm, type annotation or call shape was touched, because each of those is what the gate reads. So the run measures cost and nothing else. THE PREDICTION IS STATED BEFORE THE MEASUREMENT, so it can be wrong rather than fitted afterwards. Two points from the earlier lower-bound measurement -- 88 bytes at 534ms, 116 bytes at 618ms -- put the marginal cost near 3ms/byte and imply about 285ms paid per claim BEFORE a single byte of snippet exists. These cuts remove 9, 10 and 19 bytes, so the predicted saving is tens of milliseconds against a worst row that needs 180. Projected: ~591, ~504, ~623 against a 500ms budget. If the floor lands them clearly under 500, this model is wrong in the useful direction -- the front end is superlinear in source size rather than mostly fixed -- and the sources were the defect after all. If they land near the projection, the sources were never the defect and the budget grain is, which is a declared-drop question rather than a witness question. The floor decides either way: claim_batch cannot measure this module at all, because it fails at the same serve boundary that broke the withdrawn share. THE FIXED COST IS THE FINDING, not the saving. ~285ms of front end per claim before any snippet exists is a section-6 bare-minimum-cost defect in its own right, and it is the same subject as the serve-boundary work item: netting that survives consumption is exactly what would delete it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
Review 63901. The note asserted "Witness accumulation on the subtree fold uses prepend-then-reverse, not append-in-step" while the fold does exactly append-in-step: list_append(left: child_ws, right: ws) inside step copies the child's whole accumulated list every step, with one list_reverse at the end. TWO THINGS COMPOUND AND THE SECOND IS THE ACUTE ONE. The cost shape is real, and it is the accumulator-copy shape THIS DOOR'S OWN LENS EXISTS TO REFUSE. But the note is not prose: this PR's own annotation states it is the COMPARED VALUE that the Gate-A witness asserts byte-equality on. So a false cost claim was green by equality on both sides -- a check certifying its own wrong description. I DID NOT "FIX" THE FOLD, and that is a decision rather than an omission. list_append costs its LEFT operand; the carrier's rc_list_concat copies its RIGHT one (dag/std/nat.dag already records that asymmetry as a measured cost shape). Neither the accumulator nor a child's subtree accumulation is reliably the shorter, so no argument order makes a fold over a tree linear -- it needs a concat that copies neither operand, which is carrier work. Swapping the operands would have moved the copy while letting me report the defect fixed, which is the same species as the claim I am deleting. So the note now states what the code does, names the shape, says why the repair is carrier work and not an argument order, and says why it is stated in a compared value at all. DESIGN section 6 root-causes to the language layer rather than patching locally; section 5 forbids the fabricated claim regardless. Byte-equality preserved: both sides carry the identical 2088-byte note, verified by extracting the .dag string and asserting containment in the oracle rather than by eye. gunbc compile --entry 00_compile.dag --target dag: 0 blocking errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
|
Accepted-path measurement, and a correction to my own earlier reasoning on this PR. The floor at
The shortest snippet is the slowest. Sizes differ by 32%, costs by 4%, and the ordering is inverted — source size and cost are uncorrelated here. That refutes the rationale in commit 87a3632. That commit cut the probe sources and predicted ~3 ms/byte, saving 27/30/57 ms. The model was fitted to two lower-bound points from What the numbers actually establish, which is more useful than the cut:
And the framing I had wrong. These three witnesses are never planned on main: The corpus already carries the policy for this shape — Separately, review 63901's fix is in — sent from calm-crane-722 |
|
The snippet cut is now falsified by a paired measurement, not just a cross-sectional one. Same three witnesses, before and after the cut, both on the floor's accepted path:
Commit What the numbers do establish: the per-claim cost is a ~500 ms fixed front end — This PR needs no further fix for it. These three witnesses are never planned on an ordinary floor ( The operator ruled on it (A, via fierce-lark-661): — sent from calm-crane-722 |
…verts Review 63922, plus the revert the measurement earned. THE COUNT COULD NOT FAIL. Both coverage assertions checked `length(rows) == length(roster())`, and both sides derive from the same fold inside join_required_lens_coverage, which emits exactly one row per registration by construction. The conjunct was structurally green and said nothing about WHICH lenses were covered -- while the comment beside it claimed the closed rows are the roster's own identities, which is more than a count establishes. DESIGN section 5: completeness is an identity join, not a count equality. The case a count cannot see is concrete: a join that DROPS one registration and DUPLICATES another keeps the count exactly equal. rows_join_the_roster_exactly runs the join at (identity, grain) in BOTH directions, because the directions fail differently -- a registration with no row is a lens that never ran, and a row naming no registration is coverage claimed for something the roster does not require. Grain is part of the key rather than a separate assertion: the join's own ObservedAtWrongGrain arm exists because covered-at-the-wrong-grain is a different fact from covered. THE SNIPPET CUT REVERTS BECAUSE IT WAS MEASURED AND BOUGHT NOTHING. Paired before/after on the same three witnesses: two of the three got SLOWER after bytes were removed, and the third's gain is the same size as the noise. The prediction in that commit -- a marginal cost near 3ms/byte -- is refuted, and cross-sectionally too, since the shortest source is the slowest of the three. The sources are restored to the forms that read clearly, and the annotation now carries the measured outcome instead of the prediction: the per-claim cost is a fixed front end, invariant to the subject-specific work, and it is closed by the FLOOR-CHANGED-COST-0 long-home arm rather than here. 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
…line repair one of them specifies (#11025) * Two failure-mode rows from the compile-door measurement, and the one-line repair one of them specifies Both classes were found by running things during the required-lens registration work (#11004), and both are filed here rather than there because a ledger append and a compiler change are separate merge surfaces. mandatory_gate_refuses_the_corpus_it_is_mandatory_on — a gate registered as mandatory on a door refuses the very corpus that door exists to admit, so the door is unreachable and the obligation reads enforced while nothing passes through it. Specimen, measured: on fixture_add_resolved_tree, infer ACCEPTS, the root-grain required roster ACCEPTS the inferred tree, and the subtree-grain roster (fact_density + unit_modeling + lifecycle_carrier) REFUSES it — in both TranslateTo and Eval. So no fixture in this corpus reaches Accepted through the v2 compile door. This is the wall behind the declared frontier in v2.test.lens_application.required_lens_coverage_join, named as one class so retiring the frontier and repairing this are the same act. Rung 1, ceiling 2, trigger: the lens-semantics repair. sole_constructor_wrapper_satisfies_a_typecheck_declared_for_its_payload — a single-field wrapper value passes a typecheck written for its payload and then dies at evaluation on a field the payload has and the wrapper does not. Acceptance coerces, evaluation does not. Rung 1, ceiling 4 (the question is decidable from the declaration), trigger: the compiler treating carrier and payload identically at BOTH ends. The site repair that row specifies lands with it: normalized_of stored the NormalizedTree normalize returns into a field declared Node, so three witnesses in v2.test.long.accumulator_copy_compile_gate failed at eval with "no field 'kind' on type 'NormalizedTree'". `root: normalized.root` turns all three green — verified red before, green after. The row and the fix land together deliberately: a fix alone would hide the acceptance hole, a row alone leaves a red nobody executes. Why nobody noticed: that entry is a LegacyFrozenPathDeferral in gunbc.witness_deferral_freeze — admitted by path policy with no executing consumer — recorded in the row as a second, separate finding. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * Drop the unresolvable citation from the mandatory-gate row (review 63465) The SPECIMEN receipt named v2.test.lens_application.required_lens_coverage_join as the home of the door-grain frontier. That module is declared in #11004, which is not merged, so on this branch and on base the citation resolves to nothing — the exact defect DESIGN §3's standing rule exists to prevent, and it was load-bearing for the row's "wall behind that frontier" claim. The row now states the CONSEQUENCE instead of pointing at a file: while a mandatory gate refuses the corpus its door must admit, a door-grain positive control is not authorable at all, so any coverage receipt attached to that door necessarily lands with its positive control declared as a frontier. The link is the class, not the file name, and the row says explicitly why it does not cite the module. Nothing else changes; every remaining citation in both rows resolves on main. Verified: the module resolves and evaluates (gunbc run reaching `authored`'s arity check, i.e. past parse and typecheck). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * File the deferral finding against the class that owns it (review 63679) The "WHY IT SURVIVED" receipt described a class that already has a home — witness_module_absent_from_the_executed_set — from inside a row whose subject is a coercion hole at a use site. §4b says a newly discovered class files or updates ONE row; I updated the wrong one. The inconsistency was internal to this PR: its other row cites [[witness_module_absent_from_the_executed_set]] by name. The receipt moves there, and carries two things that row did not have: - A SECOND HARM. Every instance it holds is a correct check whose green is wrongly cited as coverage. But a module outside the executed set is equally free to BREAK and stay broken: three witnesses in this PR's own subject had been failing at eval with "no field 'kind' on type 'NormalizedTree'" for an unknown length of time — loud when run, invisible because nothing runs them. The repair was one field; the reason it survived was membership. - A DIFFERENT ADMISSION MECHANISM, which changes detection. The existing instances are modules nobody scheduled — a gap, found by joining modules-on-disk to modules-scheduled. This one was scheduled OUT, deliberately, by path policy, and the roster recording it is honest about what it is. Same consequence, but a deferral roster is already a written list of modules whose reds nobody will see, and can be read directly rather than derived. The coercion row keeps only the acceptance hole and links the sibling, with one line on why they compose: one made the mistake writable, the other made it invisible, and keeping both in one row buries a membership finding behind a coercion class where nobody looking for it would read it. Verified the edited row resolves and typechecks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * The specimen states what it measured, not the universal it was promoted to Required repair from the landing ruling. The row said "no fixture in this corpus reaches Accepted through the v2 compile door" on the evidence of ONE fixture in TWO modes. That is an existential result promoted to a universal: what was measured is that the compiler's own clean resolved add fixture is refused upstream of emission on both paths, and the corpus was never enumerated. THE IRONY IS THE POINT AND THE ROW NOW SAYS SO. This is the claim-wider-than-its -evidence defect committed inside a row about evidence, in a ledger whose whole job is to catch it. A row that overstates its own reach is worse than a missing row, because it will be cited at the reach it claims. WHAT THE TEXT NOW STATES, at the grain it was measured at: this fixture is refused on both paths, and NO ACCEPTED POSITIVE CONTROL HAS BEEN PRODUCED for the door. What it explicitly does NOT claim: that no fixture can reach Accepted. What the universal would need is named rather than assumed -- a derived, closed fixture population with the door executed over all of it -- and recorded as missing measurement, which is the honest state. The consequence sentence inherited the same over-reach and is scoped with it: "not authorable at all" and "any coverage receipt NECESSARILY lands" become what happened -- the obvious candidate does not produce a positive control, so the coverage receipt attached to that door landed with its positive control declared as a frontier rather than executed. The ceiling and the next-rung trigger are unchanged: both were already stated over the per-gate accepting-traversal control and the lens-semantics repair, neither of which rested on the universal. The second row on this PR is untouched. 0 blocking errors. The run at the prior head came back success before this push. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts: # dag/gunbc/recurring_failure_mode/stale_present_tense_coverage_claim_in_the_authority_consulted_first.dag
Review 64177, both findings. No behaviour change. 1. `CompileLens.identity` is authored on the row beside `gate` and bound to it by nothing, so swapping two rows' gates leaves the join closed and the roster digest unchanged. The module claimed more than that in two places -- "registration and observation form one closed, machine-checkable join" and a digest that "does not cover the gate function, which is named by the identity it is registered under". The second sentence asserted precisely the pairing nothing verifies. Both now state the honest claim: a gate REGISTERED UNDER this identity ran at this grain. The residual is recorded at MITIGATION grain with its ceiling and its next-rung trigger beside the field, per section 4b(2). No discriminating RED is authorable today and the annotation says why: a control would have to recover a declaration identity FROM an opaque function value, and one comparing the authored identity to itself would be the permanently-green decoration section 4b warns about at the top rung -- worse than absent, because it would be cited as coverage of the gap it does not close. The trigger is a reified declaration identity for function values, which makes the field derived rather than authored and collapses the pair to one fact. The witness module's own "what this does not establish" roster now names it too, which the reviewer noted it omitted. 2. `first_root_registration` returned the LAST root-grain row: the fold overwrites `acc` on every `CompileLensRoot`. The controls were unaffected (they call it on both sides), but the name asserted a position the code did not have. Renamed to `a_root_grain_registration`, claiming no position at all, because the contract does not care -- and NOT repaired by returning the first, since `unregistered_placeholder_lens()` is itself `CompileLensRoot` and a keep-the-first fold would latch onto the sentinel and never reach a real row. Evidence: claim_batch over required_lens_coverage_join, rc=0, 8 PASS; gunbc compile of v2.compiler.compile, the witness module and the amended failure-mode row, 0 blocking errors each; docs_projection_gate regen is a no-op against the committed projection. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
Review 64196, both findings. No behaviour change. 1. The annotation above validate_then_compile said "an obligation that silently stopped executing stops the line". That is false AT THIS DOOR, and the reviewer is right about why: both sides of the join come from required_compile_lens_roster() inside one call. run_required_lens_gates folds the roster and stamps each witness with the identity and grain of the row it is folding, so the observation list is a structural image of the roster rather than an independent reading of it; required_lens_observations then drops any witness that is not a registration before the join is asked. RegistrationUnobserved, ObservedAtWrongGrain, RootLensObservedMoreThanOnce and ObservationUnregistered therefore have no authorable RED here. What can fire is RegistrationDuplicated and RequiredLensRosterEmpty. An obligation stops executing by LEAVING THE ROSTER, and a join whose both sides are the roster cannot see that by construction. The arms are not decoration -- they are discriminated where their REDs are authorable, in the fixture-grain suite, which section 4b explicitly sanctions as the place a compiler's invalid states get expressed. So the honest statement is about GRAIN: fixture-grain the join discriminates six ways, door-grain it catches a duplicated or empty roster. The trigger for the stronger claim is named: an independent observation channel, a receipt carried out of the runner rather than a list re-derived from the roster it is compared against. This is the second inflated claim in this file found by review rather than by me, after the identity/gate binding. Both have the same shape -- a sentence describing what the mechanism would catch if its two sides were independent, when they are not. 2. grain_key was a byte-identical copy of compile_lens_grain_name, and the test hand-rolled equality as a string compare where compile_lens_grain_eq exists -- both in a module this test already imports from (section 3 nicknaming). The copy is deleted and the authority's comparison consumed; the roster digest's grain spelling and the test's can no longer drift. Evidence: claim_batch over required_lens_coverage_join, rc=0, 8 PASS, including refuses_wrong_grain_observation, which is the arm that exercises the swapped comparison; gunbc compile of v2.compiler.compile and the witness module, 0 blocking errors each. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
…n home, and a per-operand join that consumes std.pareto (#11026) * Realization-cost fidelity: the structured cost form in CostShape's own home, and a per-operand join that consumes std.pareto The compile-obligation census's one row WITHOUT A HOME: the modeled cost of an operation and the cost its chosen realization actually has were two facts with nothing joining them, so a declared cost could be realized slower, or faster, and neither direction had a carrier able to state it. WHY NOT THE BRIEFED SHAPE. The brief homed the join on CostShape. CostShape names a growth RANK, so it cannot distinguish work over both operands from work over one — both are "linear" — and the join would have returned CostShapePreserved on exactly the specimen the class was written about (gunbc.recurring_failure_mode lens_prices_the_authority_while_the_lane_runs_the_realization: concat_contract declares work over both operands while the realization charges the right one only, so a cost model reading the contract convicts the correct construction). A wall whose RED is unauthorable for its own motivating case is DESIGN §4b's decoration. WHAT LANDED INSTEAD, per operator ruling: extend CostShape's OWN home rather than mint a second vocabulary beside a consumer. - dag/std/algebra.dag gains the structured form: CostFactor over a NAMED operand (constant / logarithmic / linear / linearithmic), CostTerm as a product of factors, StructuredCost as a sum of terms. CostShape stays, now as the PROJECTION of that expression via structured_cost_to_shape — partial and saying so: a cost linear in two operands has no CostShape image, and the absent arm is the vocabulary gap stated rather than a rounded rank. - dag/std/realization_cost_fidelity.dag joins modeled to realized PER OPERAND and CONSUMES std.pareto for the dominance algebra rather than restating it (DESIGN §3d), which also inherits Pareto's separation of Incomparable from DominanceUndecided. FIVE ARMS WHERE THE BRIEF ASKED FOR FOUR, both additions stated: RealizationDivergesByOperand is a proven trade-off — cheaper in one operand, dearer in another — and collapsing it into Unknown would be the absorbing fallback; ModeledCostNotStructured is the counted migration frontier for contracts not yet restated in the structured form. RealizationCostUnknown stays reachable only from a MISSING realization fact, never from a comparison. Evidence, by execution (claim_batch): 8 witnesses green, led by the specimen — concat modeled over both operands against realized over the right one comes out RealizationFasterThanModeled (the model over-prices the left operand). Its discriminator lives beside it in the corpus rather than in this message: the rank-only reading cannot see that divergence, which is why the structured form had to land first. NOT CARRIED, and declared rather than implied: the row population. Asserting a realized cost for a primitive without measuring the emitted compiler would be the fabricated fact this authority exists to catch, so the rows land with the measurement, and the contracts' migration to the structured form is the trigger that retires ModeledCostNotStructured. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * Build the operand lists with List's own constructors, not FreeMonoid's (floor red) The floor refused at dag/std/algebra.dag:367 — "variant 'Empty' not found in type 'List'", same for 'Cons'. In dag/std, List and FreeMonoid are distinct types: `[]` and `concat([x], acc)` build the former, `Empty` and `Cons` the latter, and I had mixed them in four fold accumulators plus a match in structured_cost_to_shape. All five sites now use List's own idiom, and the projection reads the operand list with length() and first() rather than matching FreeMonoid variants against it. WHAT THIS COST, recorded because it changes what my evidence is worth in this layer: the local claim_batch run was GREEN on exactly the code the floor refused. The interpreter accepted the mixed constructors; the floor's resolve did not. For dag/std changes the floor is the oracle and a local pass is not evidence of one. The eight witnesses pass again after the repair, including the concat specimen (RealizationFasterThanModeled) and its rank-only discriminator. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * The projection no longer rounds, and the frontier is declared in the diff (review 63523) Two findings, both real. 1. THE PROJECTION ROUNDED INSIDE THE FUNCTION THAT FORBIDS ROUNDING. rank 1 is LOGARITHMIC in the operand and CostShape has no logarithmic spelling, but shape_for_single_operand_rank answered ShapeConstant for it — a cost that grows reported as one that does not, which is exactly the fabricated answer the annotation three lines above says the authority exists to prevent. It answers absent now, like every other cost CostShape cannot say, and two witnesses keep the distinction executed rather than asserted: the logarithmic case must not project, and the neighbouring linear and linearithmic ranks still must. 2. THE FRONTIER WAS IN THE PR BODY, NOT IN THE DIFF. §3c admits a declaration whose consumer lands later only with the trigger stated BESIDE it, and names "consumption described in the PR body but absent from the diff" as a tell. The module now carries it: the named consumer (the compile-obligation census's realization-cost-fidelity row, joined per (primitive, target) through realization_cost_fidelity_rows, with the three counters as its reported populations), the route, and the trigger as a CAPABILITY — the emitted compiler being measurable per primitive, so a realized cost is an observation rather than an assertion. It also records why there are deliberately no RealizationCostFact rows yet: hand-authoring one would make the model and the realization agree by construction, which is the failure this join exists to make impossible. And it says plainly what a green run means today — the arms are proven against authored costs, and the population this will judge does not exist yet. Ten witnesses pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * Growth in an operand is a pair, not an ordinal; target equality is a match, not a slug table (review 63550) Two findings, both real, and the first is the same defect one level deeper than the last round's. 1. THE RANK ARITHMETIC COLLIDED, AND A COLLISION HAS NO REFUSAL DOOR. Growth was a single ordinal (constant 0, log 1, linear 2, linearithmic 3) summed across the factors of a term, so log(n)*log(n) and n both scored 2: cost_fidelity_of(modeled: log^2 n, realized: n) answered CostShapePreserved, and structured_cost_to_shape projected log^2 n as ShapeLinearScan. A real divergence reported as preserved, by the module built to make that impossible — and, as the review put it, the absent arm proves refusal was available while a collided rank offers no such door. Growth in an operand is n^degree * (log n)^logs, which is two numbers. It is carried as OperandGrowth { degree, logs }, multiplied within a term (a term is a product, so the exponents add — separately) and maxed across terms under a LEXICOGRAPHIC order, which is the true order of those functions: n beats (log n)^k for every k. The projection follows: CostShape can say exactly constant, linear and linearithmic in one operand, and logarithmic, quadratic and log-squared each answer absent rather than rounding to the nearest thing it can say. The axis comparison moves from axis_comparison_int to axis_comparison(goal, value_order:) accordingly. std.pareto still owns dominance; supplying the ordering of a growth rate is this authority's own job. 2. TARGET EQUALITY MINTED A SECOND NAMING SCHEME. cost_realization_target_slug gave each arm of a closed three-arm coproduct a string and compared strings — names for arms the type already names (§3). realization_target_eq is a structural match now, which also fails in the right direction: a fourth target stops the match compiling, where a slug table would silently answer "not equal" for a missing row. Three new controls, thirteen witnesses green: log^2 versus linear must come out RealizationSlowerThanModeled, and log^2 and one-operand-quadratic must each have no CostShape. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * Give ShapeIterateBody a preimage: the caller's body is a fact the cost vocabulary was missing (review 63577) CostShape is not a pure growth vocabulary. ShapeIterateBody means "once per element, times whatever the caller's body costs", and it is the cost std.primitive_identity carries TODAY for fold_list and index_by. StructuredCost had no factor for that, so when those primitives migrate the only honest spelling was LinearInOperand — and the projection answered ShapeLinearScan, a DIFFERENT arm of the same authority, silently. ShapeIterateBody had no preimage and ShapeLinearScan had two: two names answering one question and disagreeing (§3), and the rounding this function's own annotation forbids (§5). The review offered two repairs and this takes the modelling one, because refusing the linear case would leave ShapeIterateBody permanently unreachable and the projection nearly vacuous, while the body is a real fact that belongs in the vocabulary: - CostFactor gains CallerBodyPerElementIn { operand }, and OperandGrowth gains a bodies count. - THE BODY IS NOT AN EXPONENT. It multiplies the work without changing growth in the operand, so it counts separately and the order stays over (degree, logs). - An axis whose growths agree and whose bodies differ is therefore UndecidedOnEvidence — std.pareto's own word — because the body may be O(1). Calling it Same hides a real difference; calling it worse invents one. - That lands as a sixth arm, RealizationCostBodyDependent, rather than being folded into RealizationCostUnknown, which stays reachable only from a MISSING fact. Without the new arm the undecided case would have reported "not measured" about something measured. - The projection is total with exactly one preimage per arm: (0,0,0) constant, (1,0,1) iterate-body, (1,0,0) linear-scan, (1,1,0) sort-body. Three new controls, sixteen witnesses green: the two formerly-colliding arms must project differently, a per-element-body difference must be undecided rather than preserved, and a body must not outrank a real growth difference. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * The body survives a losing term, and the undecided arm is counted (review 63603) Two findings, both real, both arms I introduced and did not enumerate. 1. THE BODY COUNT WAS DROPPED BY A GROWTH-DOMINATED TERM. operand_growth_max returned the winning term's OperandGrowth whole and consulted bodies only on an Equal tie, so modeled [n*n] against realized [n*n, body(n)] both collapsed to (2,0,0), compared Same, and answered CostShapePreserved — for a realization that runs a caller-supplied body per element where the model runs none. The fabricated preserved this module exists to refuse, produced by the function meant to keep those two facts apart. A cost is a SUM, so growth in an operand comes from the largest term; a body is a fact about the COST, not about the winning term. Growth now comes from the ordering and bodies are maxed independently — the same argument that keeps degree and logs separate rather than summed. 2. RealizationCostBodyDependent WAS COUNTED IN NO REPORTED POPULATION. Not a finding, not unmeasured, not unmigrated — so a measured-but-undecided row was invisible in all three counts the declared consumer reports. The arm exists so an undecided comparison is not read as preserved; being uncountable defeats it just as completely and more quietly. It has its own population now, count_cost_body_dependent, and the module's consumer statement names four populations rather than three. Two new controls, eighteen green: a body in a losing term must not be dropped, and the undecided arm must appear in a reported population — the second asserting all four counts on one ledger, so the type cannot gain an arm again without the accounting being revisited. THE PATTERN, fourth round running on this module: the defect sat in a combination the vocabulary admits and no witness constructed. #11031 files that class. This round sharpens it — adding an arm to a coproduct is not finished when the arm is REACHABLE, it is finished when every fold over that type has been revisited, and the counting folds are the ones that fail silently. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * Consume std.induction CostBound instead of minting a second cost grammar (review 63628) LOCAL COMMIT, NOT PUSHED: #11026 is held and under a no-push rule. Committed so the work does not follow a branch switch, which is how the 4a drafts leaked into #11004 earlier today. std.induction already owns a sum-of-products cost algebra over named parameters: AtomicCost (PolyCost { param, exponent } / LogCost { param }), ProductBound, SumOfProductsBound — and owns it more completely than what I wrote, since PolynomialExponent carries fractional and log-based exponents my four-factor grammar could not express. The equivalences are exact: cost_nlogn IS linearithmic, and cost_graph_linear IS the concat specimen, already in the corpus. So I minted a second cost grammar — §2 failed decomposition, §3 nicknaming — in the change that argued a second cost vocabulary beside a consumer is the fork §3 forbids, in a module whose subject is a cost authority disagreeing with itself. I DFS'd CostShape and stopped there instead of following the concept DAG one step further. - std.algebra: CostFactor / CostTerm / StructuredCost deleted; CostShape stays, with an annotation recording the failed decomposition and naming CostBound. - std.induction: AtomicCost gains CallerBodyCost { param } plus cost_iterate_body — the one fact genuinely absent, and the reason a projection from this authority could not reach ShapeIterateBody at all. Nothing outside induction.dag matches on AtomicCost, so the arm adds no obligation elsewhere. - The growth derivation and the CostShape projection move to std.induction, beside the carrier they read: ParamGrowth { degree, logs, bodies, representable }, lexicographic on (degree, logs), body held out of the order, and representable:false for fractional exponents, log-based exponents, ForeverBound and ErrorBound — a real bound this reading cannot order says so rather than rounding. - The join consumes CostBound and speaks its vocabulary (param_*, not operand_*): having renamed the authority, keeping a second name for its parameters would be the same defect one scale down. Nineteen witnesses green, every verdict preserved across the migration, plus one control that only became AUTHORABLE on the richer authority: cost_sqrt exists in std.induction, and a fractional exponent must not round to a shape. The specimen witness now reads cost_graph_linear(v_param: "left", e_param: "right") — a constructor that was already there, which is the plainest statement of what the review caught. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * Orderability is asked before any comparison, and it has its own arm and its own count (review 63797) Both claimed silent wrong answers REPRODUCED by execution before I touched anything: cost_fidelity_of(modeled: cost_linear("n"), realized: cost_sqrt("n")) -> RealizationFasterThanModeled (sqrt(n) reported cheaper than n) cost_fidelity_of(ForeverBound, ConstantBound) -> CostShapePreserved (unbounded reported as preserving) The cause is the one the review names: ParamGrowth carries `representable` and the PROJECTION consults it, while param_growth_order compares only (degree, logs) — so an unrepresentable growth was ordered as (0,0), i.e. constant. The module's own annotation says a reader reporting constant or linear for such a bound "would be fabricating". The join did exactly that, three lines of indirection away, which is the same shape as the two rounds before it: the refusal existed and the consumer did not ask. ForeverBound is worse and needed a second look: it names no parameters at all, so the axis list was EMPTY, and an empty axis list is Equivalent in std.pareto. "No axes" and "no difference" are not the same fact. That is why orderability is a property of the WHOLE BOUND (cost_bound_is_orderable in std.induction) rather than a per-parameter flag — a bound with no parameters has no per-parameter flag to carry. CostGrowthNotOrderable is its OWN arm, not overloaded onto RealizationCostBodyDependent as the review warned against. They are different ignorances with different repairs: body-dependent means both costs are fully known and their ORDER turns on an unmodeled body cost; not-orderable means this reading cannot place a bound on the lattice at all. Folding them together would send a reader to model a body when the real gap is a fractional exponent. The arm is COUNTED — count_cost_not_orderable, a fifth reported population — and every existing fold over CostFidelity was revisited. That is the rule this module learned two rounds ago after shipping a reachable arm no count reported: adding an arm is not done when the arm is reachable, it is done when every fold over the type has been revisited. Five new controls, twenty-four green, including two_constants_still_compare_as_ preserved so the gate is about ORDERABILITY rather than about having no parameters — without it I would have no evidence I had not simply broken the constant case. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * Unorderable growth becomes an arm, and the census row stops claiming the join it now has Review 63818, both findings. ONE, by construction rather than by a later gate. `ParamGrowth.representable` was an in-band sum: a growth this reading cannot place still carried a degree and a log count, and param_growth_order compared them without consulting the flag. That is how sqrt(n) came to order cheaper than n and an unbounded cost came to compare equal to a constant; the orderability gate added last round caught both AFTER the illegal comparison was written, which is validation standing where construction was available (DESIGN 5). type GrowthRank { degree, logs, bodies } type ParamGrowth = OrderableGrowth { rank } | GrowthNotOrderable fn param_growth_order(a: GrowthRank, b: GrowthRank) -> Ordering A caller holding an unplaceable growth now has nothing to pass the order, so the comparison the flag existed to prevent has no way to be written. The construction found a live caller on its first run: the existing witness the_rank_only_reading_cannot_see_the_concat_divergence was handing two ParamGrowth values straight into param_growth_order, and the module refused it. atomic_cost_is_orderable is now derived from the growth arm instead of re-spelling the exponent match beside it. cost_bound_is_orderable stays, because a bound with no parameters yields no per-parameter growth at all and ForeverBound is exactly that shape -- that residue is what it covers, and the annotation now says so. std.realization_cost_fidelity follows: the axis comparison is AxisComparison? and the fold absorbs into CostGrowthNotOrderable rather than rendering an unplaceable axis as UndecidedOnEvidence, which is a different ignorance with a different repair. TWO. The census row's NoHomeExists payload said nothing declares the preservation join, and this head declares it -- a false payload is a meaning fork of the modeling-state fact. `nearest` now points at std.realization_cost_fidelity cost_fidelity_of, and the reason and trigger state what is actually still missing: nothing reads a cost bound off an emitted realization, so the join has no realized operand, and the home remains wherever a target realization is selected. Five new controls on the arms; 29 witnesses green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * Regenerate the std_induction.rs stage0 mirror from the merged authorities Build-lane regen candidate (claim_executor --required-ci --required-lane build) at b376035 on srv2; the only drifted mirror. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AMR4u1m3S6WS5RM7pRSe2n * The body delta is consulted beside the order, and the witness that asserted otherwise flips Review 63838, both findings. ONE. rank_axis_comparison decided the axis from (degree, logs) alone on the Less/Greater arms and consulted the body count ONLY when growths were equal. The body is caller-supplied work this carrier cannot bound -- std.induction says exactly that in its own annotation -- so a body delta OPPOSING the growth delta can outweigh it by any amount. n x body(n) against n log n was answered RealizationSlowerThanModeled with confidence; at a body of O(n^2) the modeled side is n^3 and the realization is dramatically faster. The mirror direction is worse because the answer flatters the realization: a modeled n^2 against a realization running an unbounded body per element answered FASTER. And the wrong answer was enrolled as a GREEN witness. That is the part worth naming: a_body_does_not_outrank_a_real_growth_difference encoded my reasoning instead of testing it, so it could only ever confirm what I already believed. ONE RULE REPLACES TWO: the axis is decided exactly when the body delta agrees with the growth delta or is zero, and is UndecidedOnEvidence when they oppose. That SUBSUMES the equal-growth case -- growths equal with bodies differing is opposition at a growth delta of zero -- so this is one rule rather than a new arm beside the old one, and the module got smaller. Three controls, and they discriminate against each other by construction: the two opposing directions (which the old rule answered Slower and Faster) and an agreeing-delta control, so the repair is not a blanket retreat into undecided. 31 witnesses green. TWO. The arm-roster annotation opened with a count that went stale the moment this branch added an arm. Deleted rather than corrected: DESIGN section 4c says an annotation must not restate what the declaration structurally says, and a count is exactly that restatement -- it is the reason it could drift at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * A key with two facts is contradicted, not first-picked, and the input partition is enforced Required repairs from the landing ruling. Two defects at two grains, repaired at the grain each belongs to. ONE, PER KEY: realization_cost_for stopped at the first matching (primitive, target) fact, so [linear, quadratic] and [quadratic, linear] answered DIFFERENTLY for one key. The verdict was decided by the caller's list order rather than by the realization -- a well-formed wrong answer, which is worse than a refusal because nothing about it looks wrong. The lookup is now three arms, and the fold reaches Duplicated from EITHER order, which is what makes the answer independent of how the list was built. The contradiction surfaces as a counted CostFidelity arm classified as a FINDING, because two facts disagreeing about one key is something a person must repair. A CONTRADICTED KEY IS NOT AN UNMEASURED ONE, and its own control says so. Both are "no usable realized cost", and collapsing them would file the repair against the wrong lane: unmeasured means nobody looked, contradicted means two people looked and disagreed. TWO, ACROSS KEYS: modeled and unstructured are the two halves of one question -- has this primitive stated its cost in the structured form -- and nothing enforced that they partition. A primitive in both produced TWO rows for one key, one with a real fidelity and one ModeledCostNotStructured, leaving a reader to pick. That is not a per-row fact but a broken premise, so the whole report refuses with a named cause rather than emitting rows derived from it. Duplicates within either list are the same defect at shorter range. THE PLANTED CHECK IS THE EVIDENCE. Restoring first-pick fails two_facts_for_one_key_contradict_in_either_order and a_contradicted_key_is_not_counted_as_unmeasured, while a_single_fact_for_one_key_still_compares and a_disjoint_partition_still_reports_rows still PASS -- so the reds detect the defect and the boundary controls are insensitive to it. The test helper returns NO ROWS for a refused report on purpose: every count assertion then fails loudly rather than reading as "nothing to report", which is the one reading that would hide a refusal. Adding the arm forced updates to four counting folds in the authority and twelve matches in the witnesses -- each one a place a wildcard would have swallowed the new arm silently. 38 witnesses green, 0 blocking errors. This edits dag/std/realization_cost_fidelity.dag, a closure member, so the PR re-takes its srv2 receipt. It does NOT touch induction.dag or any stage0 mirror. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * One classifier for the reported populations, and the frontier note names the carrier it duplicates Review 63996, findings 1 and 2-in-part. Finding 3 and the migration half of finding 2 are escalated rather than done, with the blockers named below. FINDING 1 -- SIX FOLDS FOR ONE MAPPING, AND I ADDED TO IT. count_cost_* plus cost_fidelity_is_finding were six near-identical nine-arm matches differing only in which arm incremented: six independent sources for one fact, "which reported population does this row belong to". I know the price exactly, because the previous commit added the seventh arm and the substrate made me touch four folds here and twelve matches in the witnesses -- and I reported that churn as the exhaustiveness check working. It was. That is not the same as the shape being right, and DESIGN section 2 is explicit that the test of an edit is whether net concepts grew by re-invention. Now: one cost_fidelity_population classifier, one counting fold returning a record, and the six named counts read it. THE PARTITION IS TOTAL BY CONSTRUCTION, because every arm maps to exactly one population -- and the witness asserts it by execution too. Nothing established that before: all six folds could have skipped the same arm and every population assertion would still have passed, since each checked its own count in isolation. FINDING 2 -- THE FORK IS REAL AND THE NOTE NOW SAYS WHICH ONE. The frontier note named only the std.primitives contract-cost strings while the carrier this module actually duplicates is std.primitive_identity PrimitiveCostFact, a CostShape keyed on PrimitiveIdentity -- the coarse projection of the structured form ModeledCostBoundFact carries. A loss sentence about one carrier under a trigger about another is the grain mismatch section 4b(3) names as the review tell. WHY I DID NOT PERFORM THE CUT. Migrating PrimitiveCostFact.cost to CostBound looks like a substitution and is not one: the six populated rows record a shape and NO PARAMETER, and every CostBound constructor needs one. The parameter is load-bearing -- param_axis_comparison keys on it and param_union matches it across the modeled and realized sides -- so an invented name yields a spurious axis and a fabricated verdict. Recovering each row's real parameter is modelling per primitive, not a rewrite. Doing it by pattern-substitution would manufacture the exact kind of fact this authority exists to catch, so it is named in the note and sequenced separately. FINDING 3 is correct and designed but not in this push: routing the empty-axis case through cost_bound_growth_in_param deletes all three orderability walkers, and it edits dag/std/induction.dag, whose stage0 mirror I cannot regenerate here (it OOM-killed on the remote runner; srv2 ran it last time). Escalated with that blocker rather than half-done. 39 witnesses green, 0 blocking errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * The three orderability walkers delete, and the fold that owned the question answers it Review 63996 finding 3, under your ruling to do it here with the mirror regenerated on srv2. WHAT WAS DUPLICATED. cost_bound_is_orderable, atomic_factors_are_orderable and atomic_cost_is_orderable re-walked CostBound's arms in parallel with cost_bound_growth_in_param, which already decides orderability per parameter and already recurses SumBound. Two walks over one storage shape is one authority too many, and the second drifts silently because nothing forces them to agree. WHAT THEY ACTUALLY COVERED, which is the part worth getting right: only the bound with NO PARAMETERS. Every other unorderable bound reaches the axis fold as an unplaceable growth on some parameter and is already absorbed there. With no parameters there is no axis to carry the refusal, and the dominance fold would answer Equivalent over an empty comparison list -- reporting an unbounded cost as PRESERVED against a constant. So the residue is now one question put to the canonical authority rather than a parallel recursion: ask cost_bound_growth_in_param about a parameter the bound does not carry. ForeverBound and ErrorBound answer not-orderable whatever they are asked, a structured bound answers zero growth in a parameter it never mentions, and a SumBound recurses to its terms through the same fold. The gate in cost_fidelity_of is gone with them. THE EVIDENCE IS THE TWO CONTROLS THAT ALREADY EXISTED, and they are why "39 green" is not the claim here: deleting an orderability gate and staying green could mean the fold picked the refusal up, or that nothing checked the refusal at all. an_unbounded_cost_is_not_preserved_against_a_constant and a_malformed_bound_is_not_orderable both assert through the public entry, so they are indifferent to HOW orderability is decided, and both PASS by name. They exist because sqrt-ordered-as-constant and ForeverBound-ordered-as-constant were real fabrications in this module. THE MIRROR IS STALE ON THIS HEAD AND THAT IS EXPECTED: this edits dag/std/induction.dag, whose stage0 mirror regenerates on srv2, per your sequencing. Nothing else lands on this branch until that mirror commit is on it. 39 witnesses green, 0 blocking errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f * Regenerate the stage0 mirror(s) from the merged authorities (srv2, build-lane candidate) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AMR4u1m3S6WS5RM7pRSe2n * The success arm names the cost it compared, not a shape it never asked for Review 64030: `CostShapePreserved` claimed a fact this join never establishes. The comparison runs over `CostBound`s through `std.pareto`; the shape projection (`cost_bound_to_shape`) is a real, partial, neighbouring concept carried on every row as `projected_shape` -- so two adjacent facts shared one name, which is the DESIGN section 3 meaning fork. The module's own witnesses proved it in both directions: `the_rank_only_reading_cannot_see_the_concat_divergence` asserts the concat specimen has NO shape, and `identical_costs_are_preserved` compared a bound against itself and got a "shape preserved" verdict. Rename to `ModeledCostPreserved` at all 17 sites across the authority and its witness suite, with the reasoning carried as a leading annotation on the arm's own declaration. Evidence: `claim_batch --entry dag/test/claim/realization_cost_fidelity_witness_test.dag` over all 39 witnesses, rc=0, 39 PASS. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Brian Searls <searlsbrian@gmail.com>
Reviews 64177 and 64196 found two claims in `v2.compiler.compile` that described what a mechanism would catch if its two sides were independent, when they are not. One class, two specimens, so it gets a row rather than two annotations that each explain themselves. `gunbc.recurring_failure_mode comparison_whose_operands_share_a_producer`. The discriminator is one sentence: the comparison's two operands have a common producer. It is decidable by reading each operand back to its source, and it is worth asking before the check is written rather than after it greens. Checked the directory before filing rather than assuming, and the four nearest rows are excluded BY NAME in the row itself. Not `roster_is_its_own_denominator`: there is no second statement there at all and the repair is to obtain one; here two exist and are compared, and the repair is to make one independent. Not `population_selector_that_cannot_admit_a_counterexample`: that is a defect in how a population was constructed by a lexical proxy; here the population is correct and stable and the defect is the second operand. Not `corroboration_without_an_independent_derivation_axis`: that is a property of the relationship between two human readers, which no artifact records, so it carries ceiling 1 and no trigger; this one is mechanical, visible in source at both call sites, and decidable. Not `a_positive_control_certifies_the_defect_it_exists_to_catch`: there the control reads the right accessor against a wrong subject, so a correct subject fixes it; here the subject is right and the comparison still cannot fail. The general form, and the reason it is a control-shaped class rather than a compiler one: it is DESIGN section 5's oracle rule applied to a control instead of to a literal. "A measurement copied from the same current tree is not an oracle" becomes "a list re-derived from the roster it is compared against is not an observation". RUNG FOUND AT is mitigation by review, and an earlier draft got this wrong in a way worth recording: it said `mitigatable` and justified that by pointing at the join's refusal arms firing at fixture grain. Those arms discriminate a malformed observation set; none of them can detect that a comparison's operands share a producer, so that was a fact about the specimen and not containment of the class. Nothing in the corpus asks the question, so the honest rung is what a human reading two call sites established. Ceiling is structurally guaranteed, because operand provenance is a declaration-grain question the Node tree already answers. Class trigger is provenance-aware comparison analysis; the specimen's own trigger - an independent observation channel - is recorded separately and explicitly does NOT discharge the class. Both annotations in `00_compile.dag` now cite the row. Evidence: gunbc compile of the row and of v2.compiler.compile, 0 blocking errors each; docs_projection_gate regen renders the row into the combined view (the roster and that projection are both gitignored, so the row file is the entire committed change). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
Review 64245. The grain note admitted a cost defect in this door's own witness fold and disposed of it with "tracked as its own cost defect rather than patched locally here", naming no carrier, row or symbol. Nothing tracked it, so the sentence asserted a disposition that did not exist -- section 4b(2)'s untracked stall, stated in the authority a reader consults first. Filed `gunbc.recurring_failure_mode enforcement_exhibits_the_shape_it_refuses` and cited it from the sentence. The class is the machinery that enforces an invariant being written in the shape that invariant refuses -- DESIGN section 7's self-application obligation failing in the direction nobody looks, because the enforcement's own code reads as infrastructure rather than as a subject. The specimen is half repaired and half standing, which is what makes it worth a row: the subtree fold was already rewritten to prepend-then-reverse, while the concat stands, because `list_append` costs its LEFT operand and `rc_list_concat` copies its RIGHT one and neither accumulation is reliably shorter. The trigger is named as a CAPABILITY and the falsified experiment is recorded beside it: a concat that copies neither operand, which is carrier work in the list algebra and explicitly NOT a rewrite of call sites -- docs/plans/emit-type-surface-traversal-cost.md tried exactly that substitution at 215 sites plus rc_list_concat and measured byte-identical output with no measurable change at the emit seam. That is evidence about that seam and not this one, and it is written down so the next author does not re-run a falsified experiment believing it is the repair. The row's own next rung is the required-lens gates applied to the compiler's own modules as ordinary subjects, which is section 7's claim made executable. The seed mirror moves in lockstep: both sides of the self-host behavioral receipt are byte-identical at 2556 characters, asserted by comparing the extracted strings rather than by inspection. Evidence: gunbc compile of v2.compiler.compile, the new row and the cause-swap witness, 0 blocking errors each; claim_batch over claim_entailing_evidence_cause_swap_witness, rc=0, 8 PASS -- that suite carries the transcript fixtures that mention this declaration, and its `seed_len` figures are authored specimens of transcript SHAPE rather than live measurements of the string, so they are unaffected by its length changing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
|
Review 64245, secondary finding — not fixed, and here is why rather than an acknowledgement. The finding is that The premise that makes that repair cheap does not hold here: this string is not commentary, it is a compared value. It is the only case in the self-host behavioral receipt — The defect the finding is pointing at is real, and it is already rostered: So the honest disposition is: the §4c placement is a consequence of the rostered defect rather than an independent one, and fixing it locally in this PR would change the self-host receipt's subject as a side effect of a comment-placement edit. That belongs with the row that owns it. The primary finding is fixed in Both sides of the receipt moved in lockstep and are byte-identical at 2556 characters, asserted by extracting and comparing the two strings rather than by inspection. — sent from calm-crane-722 |
…t hold
Review 64262, plus the dark row gunbc#11073's long-home arm exposed.
WHAT THE ARM FOUND. v2.test.long.accumulator_copy_compile_gate
gate_red_quadratic_rejects failed on its FIRST REAL EXECUTION (srv3-02, no
thrash). It is not a regression: run with one binary against origin/main and
against this head, it FAILS on both while both sibling controls PASS on
both. It had simply never run, because its home test/claim/long/ is a
witness_exclusion_frontier pattern and no required lane plans it.
AND THE FAILURE IS THE WORST OF THE THREE AVAILABLE. A three-way
discriminator separates them: the specimen normalizes fine, the gate does
not reject with a wrong reason -- accumulator_copy_compile_gate ACCEPTS it.
accumulator_copy_findings returns NO suspect for
fold(xs, init: 0, f: fn(acc, x) { list_append(left: acc, right: x) }),
which is the textbook shape the lens exists to refuse.
Three consequences, all here, none of them the analyzer repair (that is its
own lane, starting from the discriminator posted on the PR):
1. RUNG HONESTY. accumulator_copy_obligation claimed MechanicallyPreventable
on the strength of that control. Executed evidence says the invalid state is
not prevented, so the claim is downgraded to Mitigatable -- the gate is
total and returns a typed outcome, so harm is contained and nothing above
that is established. DESIGN 4b(1) admits only the rung executed evidence
supports, and the restoration is the analyzer trigger rather than the
witness greening by any other route.
2. THE CLASS. gunbc.recurring_failure_mode
required_lens_red_control_never_executes_from_its_home: a lens enrolled as
required, reporting a mechanical rung, whose discriminating red lives where
the floor never plans. The discriminator is a JOIN -- the cited red and the
planned population do not intersect -- which is why neither roster looks
wrong alone. Ceiling structurally guaranteed, because that join is over two
rosters this tree already declares.
3. THE KNOWN RED, without which the floor stays red on every future head.
Admitted in gunbc.explicit_witness_admission with a dissolution naming the
CAPABILITY: accumulator_copy_findings returns a non-empty suspects list for
the fold-append specimen and the gate refuses that tree. That fact is false
today and was MEASURED false by execution on both trees, so the trigger
cannot be satisfied by editing the specimen or the control -- which is
exactly the defect that roster's own note records two lanes failing.
REVIEW 64262. The expanded grain note restated the body of the row this PR
files, and transcribed a 215-site measurement into two files including the
Rust oracle mirror. Both are right: the prose was the duplicate rather than
the carrier, and section 6 says name the instrument, never transcribe it.
The note now cites the row instead of restating it; both sides byte-identical
at 2117 characters, asserted by extracting and comparing.
Evidence: compile 0 blocking on all four touched authorities and the new
row; v2_compile_obligation_census_witness 9 PASS. exact_witness_admission
carries three failures that are IDENTICAL on origin/main (18 PASS 3 FAIL
both sides) and my row satisfies explicit_witness_admission_well_formed by
inspection of the predicate -- QuarantineProbeExpectRed executes, entry
non-empty -- and shares kind and budget with an existing row in that batch.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f
|
For the accumulator-copy analyzer lane — the three-way discriminator, verbatim, so you start from evidence rather than rediscovering it.
Result on Latency, established rather than assumed: one binary, same functions, These three belong in the analyzer PR as enrolled controls, not in a throwaway worktree — This PR does not touch the analyzer. It carries the rung downgrade ( — sent from calm-crane-722 |
…h authorities survive The only conflict was src/v2/compiler/00_compile.dag, and it was two sides adding imports to the same block rather than a rename or a contested declaration. Resolved as a per-module union: std.algebra keeps this branch's `trim` beside main's Cons/Empty/FreeMonoid; v2.std.algebra keeps contains/is_empty/length and the promoted list_find_first beside main's folds; v2.std.collection takes main's Map/empty_map/map_insert/map_lookup beside List; and main's new std.decl_ref, std.content_hash, std.types, v2.std.integer and v2.std.logic imports all land. One import line per module, no duplicate module imports. Verified rather than assumed, since a clean auto-merge is weak evidence when both sides touch the same closure: this branch's native_lane_universe, native_lane_closure_modules, native_lane_module_for_path and list_find_first are all present; main's #11004 lens-registration join is present (85 references to CompileLens / declaration_ref_display_key / content_hash_of_value); the file is brace-balanced; the seventh row is intact in dag/std/compiler_entry.dag and the emitter; and the driver template is still the adjudicate one (2 x 'adjudicate <host-facts', 0 x universe.tsv). ONE DELIBERATE DIVERGENCE FROM THE STANDING MIRROR RULE, flagged rather than silent. The rule has been to take main's side on the stage0 mirrors, which was right while main carried the newer ones. Here the opposite holds: 86761d1's regen put THIS branch's route contract into them, and main has no such commit. So the merge keeps the regenerated mirrors -- universe.tsv 0, adjudicate 1, INGEST-CLOSURE 1, row_serialization 1. They are now stale against #11004's additions and will drift for the next regen either way; keeping them means anything that runs before that regen still gets the right driver rather than the pre-route one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013aZDLk2CxsCDznqn49Xhe8
Step 1 of the compile-obligation activation brief (ACT lane, work item adhoc-74a1fd50-8f9): the substrate everything else keys on — the required-lens roster names its lenses, and registration/observation is one closed, machine-checkable join.
What changed
required_compile_lens_rostercarries all eight required lenses, each asCompileLens { identity: DeclarationRef, grain, gate }.required_lenses_at_grainderives the two execution partitions;always_required_lenses/always_required_root_lensesare deleted at the root and their five consumers cut over.LensGateWitness { lens, grain, witness }.join_required_lens_coverage→RequiredLensCoverageClosed { roster_digest, rows }orRequiredLensCoverageRefused { cause }, with causesRequiredLensRosterEmpty | RegistrationDuplicated | RegistrationUnobserved | ObservationUnregistered | ObservedAtWrongGrain | RootLensObservedMoreThanOnce. Root grain states exactly-one; subtree grain is at-least-one, because subtree registrations are observed once per node by construction — stating exactly-one for both would refuse every tree with more than one node.validate_then_compileruns each lens at its registered grain (caller-supplied lenses included — they previously ran at root whatever grain they declared), derives the coverage from the witnesses it collected, and refuses the compile when it is not closed.Validatedcarries the receipt.map_lookupon the display key, nevermap_keys(the determinism lens registered here refuses key-order reads), and are linear in the observation count.Divergence, stated (DESIGN §3b)
The brief named a new
RequiredCompileLensbesideCompileLens. Requiredness is membership in the roster, not a property of the carrier — and a caller-supplied lens has the same three facts and must stamp its witnesses identically for the join to be closed at all — so one carrier gains the two fields instead of a second type being minted.Evidence, by execution
claim_batch --source-root dag --source-root src/v2, local release build.v2.test.lens_application.required_lens_coverage_join— 7 green:required_lens_coverage_closes_on_complete_observations_holds(positive control over the real roster, digest asserted)required_lens_coverage_closes_over_executed_gates_holds— runs all eight registered gates through the door's own two runners and joins the witnesses they actually stampedThe eight touched pre-existing lens witnesses: all green (
rejecting_lens_blocks_before_compile,enforce_rejecting_gate_fires,introspect_clean_tree_passes,apply_lens_introspect_rejection_is_advisory,empty_required_lenses_skip_gate,hollow_alias_blocked_via_always_required_lenses,unit_modeling_blocked_via_always_required_lenses,modeled_unit_field_admitted_via_always_required_lenses).Not established, and not claimed (DESIGN §4b rung honesty)
An Accepted
validate_then_compilecarrying the receipt. No fixture in this corpus reaches Accepted through that door today — measured onfixture_add_resolved_treein bothTranslateTo(stub target) andEval, where the refusal is upstream of the lens rosters and names neithercompile_pipeline_not_realizednorcompile_lens_gate_rejected. The door-grain positive control is a declared frontier whose trigger is a route that reaches Accepted through the door — the activation authority's Executed→Qualified step. The frontier is recorded in the test module header, not only here.Side finding for the census lane:
door_root_roster_runs_and_passes_clean_treeinv2.test.long.accumulator_copy_compile_gateis green on a fixture the door rejects — its assertion tolerates any rejection that is not the poly2 suspect.Follow-ups from the brief (separate PRs): the all-lens introspection ledger, the activation authority
compile_obligation_activation.dag, the complexity bundle, and receipts into promotion admission. The census join (every registration has one census row) waits ongunbc.v2_compile_obligation_censuslanding.🤖 Generated with Claude Code
https://claude.ai/code/session_01RPVTQBSK9E8j3UDQGPZN1f