Repository navigation
Floor: a prepared EFFECT INPUT, acquired once and carried into nullary warm rows (PR two of the #10994 chain) - #11370
Conversation
…y warm rows The cross-claim share roster admitted two fill dispositions and only two: a WARM row is nullary and preparation-forceable, a CLAIM-FORCED row has claim-shaped arguments. A producer whose value depends on one read of a committed carrier fits neither -- the store keys on (resolved fn node, portable argument row), and a nullary call that reaches a read contributes nothing about what it read to that key. So such a producer could only re-derive once per claim frame, the rostered shared_precondition_re_derived_once_per_claim_frame class. The floor now acquires such an input ONCE at preparation, keeps it as a content-identified carried value, and warms the pure fold over it. No stale serve is unwritable rather than guarded: the carried content IS the key material. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019yWfxLfJjJLsqJsFN2amD9
The floor's parse phase refused src/v2/workflow/floor_prepared_effect_input_ladder.dag with "expected RParen, found keyword 'input'". Also rework the carried-input controls to evaluate through a CALL SITE and assert an observed SERVE: `run_in_context` calls `call_function` directly, so it reaches neither the cross-claim tier nor the prepared-input binding, and a control that evaluated the producer that way asserted a value recompute also produces. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019yWfxLfJjJLsqJsFN2amD9
…snapshot
The RED caught a real stale serve in the first cut: CROSS_CLAIM_IMPLICIT_CARRY held a
CLONE of the carry, so re-binding the acquisition to a different content left the map
pointing at the old value, the key stayed the same, and the producer was SERVED a value
derived from the previous carrier. It now holds the acquisition NODE and reads the
current binding at every key derivation -- one authority for the carried value.
Also rename a `fn(acc, input)` lambda parameter in the ladder module: `input` is a
reserved keyword and the floor's parse phase refused the file.
Discrimination receipt: with `cross_claim_key_args` returning None (the empty-argument-row
implementation this control targets), the changed-carrier test FAILS
("the producer must not be SERVED under a changed carrier"); with the real implementation
all 17 pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019yWfxLfJjJLsqJsFN2amD9
…actually found Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019yWfxLfJjJLsqJsFN2amD9
…aid so by execution Run 34854251612 refused `the_carry_is_discharged_at_the_preparation_lca`: at a SHARED-STATE obligation LCA `group_redundant_verdict` answers AuthoredDuplication and never reaches a provider, because DESIGN section 2's repair there is to CARRY the first value, not to cache it -- "caching a later request only makes redundant work cheap and suppresses the signal that would make it rank for deletion". Asserting Discharged asked the ladder to bless the move it exists to refuse. The witness now states the transition the carry performs: AuthoredDuplication over the claim-sited demands before, AcceptedSingleRecompute (and every verdict green) over the minimized graph after. The provider's own obligations -- content keying, store tier, bounded retention -- stay checked against std.cache_interface, because it is still where the carried value is held. Also guard the prepared-input lookup on the interpreter's hottest path with a presence Cell, so a nullary call pays a bool read rather than a RefCell borrow and a hash lookup when no input is installed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019yWfxLfJjJLsqJsFN2amD9
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017fnsiH9vEgKE1Suqm7MucA
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce0614ce96
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| CROSS_CLAIM_PREPARED_INPUT.with(|m| { | ||
| m.borrow_mut() | ||
| .insert(Rc::as_ptr(acquisition_node) as usize, carry); |
There was a problem hiding this comment.
Include carried inputs in the tier's byte budget
When a prepared-input roster contains a large or currently unused acquisition, this inserts its complete value into CROSS_CLAIM_PREPARED_INPUT without checking either the 4096-entry cap or the 256 MiB byte budget enforced by store_cross_claim_pure_memo. Such carries remain resident for the entire prepared run even if no producer row subsequently accounts for them, so roster growth or a large checkout input can bypass the tier's stated retention bound and exhaust memory; measure the portable carry and refuse or charge it before retaining it.
Useful? React with 👍 / 👎.
| if let Some(carry) = prepared_input_for(&fn_node) { | ||
| cross_claim_observe_hit(&func_name); | ||
| return Ok(carry.value.clone()); |
There was a problem hiding this comment.
Record acquisition fills before reporting their hits
In every carried-input warm, the producer calls the bound acquisition and this reports a cross_claim_pure_share hit, but acquisition setup only creates a SharedBuildObservation and never calls the ledger's matching record_fill for the acquisition key. Consequently shared_fill::record_hit takes its no-fill branch and increments unattributed_hits even on a correctly instrumented run, while direct acquisition consumers are omitted from the per-key consumer set; this corrupts the [floor-shared-fill] evidence used by the roster's present-vs-absent measurement.
Useful? React with 👍 / 👎.
warm_cross_claim_pure_producer stored without the effect guard the fold path holds, so an effectful nullary row rostered as a plain warm row was stored content-blind under the empty argument row. It now refuses with PureProducerShareWarmDispatchedEffect, enrolled by a fixture performing one real hermetic checkout read (ruled by eager-raven-113 / fierce-lark-661 from warm-heron-775's model). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017fnsiH9vEgKE1Suqm7MucA
…carry the XL-4 fixture ingest as a prepared effect input
review 66826 on gunbc#11461: v2.workflow.legacy_repair_tap answered a bridge row with an
empty spelling (module_name == "" or name == "") with `Absent => acc` in BOTH the roster
fold and the observation fold - the row vanished uncounted while the roster digest still
attested a census that never counted it, and the drop was enrolled as intended behaviour.
DESIGN 5: a failure arm must refuse, never widen. Now ONE fold (admit_bridge_rows)
either admits (roster + observation rows, built together so they cannot disagree) or
refuses with the located rows (MalformedBridgeRow { index, module_name, name }); both
capture entries route the refusal through the capture outcome as
LegacyBaselineExecutionRefused { phase: RepairCensusPhase, cause: BridgeRowSpellingEmpty }
(new arm on LegacyBaselineCaptureRefusal, rendered by capture_refusal_label). The former
drop witness is now the discriminating RED empty_name_row_refuses_the_admission_located_by_index
(a well-formed sibling does not rescue the batch) beside the positive control.
Floor run 35059914771 on 557188a refused PureProducerShareWarmDispatchedEffect for
v2.test.claim.reference_derived_graph_fixture.xl4_fixture_trees (effects=11): the rule
landed on main in #11370 after #11202's last green run, and a warm row that reads the
world has an input its empty argument row cannot represent. Re-rostered in the shape that
rule prescribes: fixture_ingest is a PreparedEffectInput (the eleven committed fixture
modules under dag/test/fixture/reference_derived_graph/, acquired once at preparation,
content-keyed) and xl4_fixture_trees is a CarriedInputWarmRow over it
(ImplicitAcquisition); the plain warm row is removed. Measurements on both rows name the
runs and ledgers that re-derive the present-vs-absent verdict.
Executed locally (branch seed claim_batch, scoped): legacy_repair_tap_persisted_capture
5/5, legacy_repair_tap_live_bridge 3/3, legacy_baseline_capture 13/13,
floor_prepared_effect_input_ladder 7/7, floor/pure_producer_share_refusal 13/13,
reference_derived_graph_witness 5/5, reference_derived_graph_production_ingest 16/16.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013k9hjAXuaD1HiC1yzd4wnC
What this is
PR two of the #10994 chain: the floor gains a third fill disposition — a prepared effect input, acquired once and carried into a nullary warm row.
The gap, stated at the key rather than at taste
v2.workflow.floor_pure_producer_shareadmitted two dispositions and only two: a WARM row is nullary and preparation-forceable, a CLAIM-FORCED row has claim-shaped arguments and fills inside the fold. A producer whose value depends on one read of a committed carrier fits neither, and the reason is mechanical: a stored entry is keyed on (resolved fn node, portable argument row), and a nullary call that reaches a read contributes nothing about what it read to that key. Warming it would let two different carrier contents share one entry — the content form of the ctx-blind homonym class this file already refuses by resolving every spelling to a node. So such a producer could only be CLAIM-FORCED, where it re-derives once per claim frame: the rosteredshared_precondition_re_derived_once_per_claim_frame.The live instance is
gunbc.roadmap_authority.roadmap_authority_projection— oneFilesystem.Readof the acceptance-event carrier followed by a pure fold, demanded by seven required-lane claims and by #10994, whose merge path is blocked by an enrolment margin sitting on exactly this shared precondition.Why carrying it is binding an input and not caching an effect
This is the whole licence for the row kind, and it is a fact of the existing substrate rather than a new assertion: hermetic evaluation already classifies this read as INPUT ACCESS. The checkout-input carve-out in
v1_interpreter::eval_service_calldispatches a readonlyFilesystem.Read/Listwet whenhermetic_checkout_input_dispositionconfirms the path under the checkout root, and refuses — typed and located — everything it cannot confirm (out-of-root, a.git/targetcomponent, unresolvable). The value is therefore a function of the commit the run prepared, and a producer reaching host state that wall cannot confirm is never carryable, because that wall refuses it first.The shape
Two roster declarations beside the existing two lists, plus
CarriedInputDependence = BoundParameter { parameter } | ImplicitAcquisition— two arms because there are exactly two ways a producer reaches the acquisition (taking it as an argument, which is where #11303 is moving the roadmap projections; or reaching it inside itself, which is the shape on main today).Preparation gains one phase, ordered before the plain warm loop: resolve the acquisition to its node, refuse any acquisition that is not nullary, evaluate it once under
observe_shared_build(so it is billed to preparation and adjudicated by the same preparation refusal as every other shared build), reify it totally to its portable form — the same total walk publication already performs — take its structural digest as the carried content identity, and bind it for the prepared subject's lifetime, cleared with the tier.No stale serve is unwritable rather than guarded. The carried content IS the key material: a changed carrier produces a different portable argument row, the stored row fails to match, and the producer recomputes. There is no staleness check to forget to run.
The pure memo's
effect_dispatch_countrefusal is untouched — it is correct and stays. A prepared input is served by a different, roster-declared admission keyed on resolved fn-node identity, and it is served ineval_callrather than one tier down, because a declaration that reaches the world may declareusesand a fn with non-emptyusesnever reaches the pure path at all.The effect wall on the implicit arm, which is what separates "its only input is this carrier" from "we hope it is": with the carry installed, the producer's warm must dispatch no effect. One that still reaches the world has an input the key does not represent, and the row is refused (
PreparedEffectInputProducerStillDispatchesEffect) rather than stored under a key that cannot see what it read.Adjudication, and the three conditions
Both decisions were sent as a model before any code (docs/plans/prepared-effect-input-carry.md) and approved by eager-raven-113, fierce-lark-661 and bright-boar-435 on 2026-09-14.
phase=prepared-effect-input-acquireline carries the carried value's outermost variant name beside its content digest, so a run whose carrier refused is diagnosable instead of reading as a corpus problem.ArtifactRequestvariant. That algebra keys durable cross-run artifacts by digest with a realization receipt naming a provider; the carried input is an in-process value bound for one prepared subject. Condition (fierce-lark, eager-raven): citestd.materialization_ladderin source, with the four obligations as typed values rather than prose.v2.workflow.floor_prepared_effect_input_ladderstates the provider (MemoTier { ContentKeyed }, scoped to the preparation frame, retention released at scope exit with the tier's exact 256 MiB ceiling) and the demands (the acquisition aWorldReadwith its envelope declared — the envelope IS the prepared subject; the producer aPureComputation), andevery_carried_identity_is_dischargedis decided by the ladder's own fold. The four are derived from the row, not transcribed beside it: copying scope and retention per row would be one fact in two places (§3) and the transcription §6 forbids; the roster header names each of the four and the symbol that derives it.the_prepared_input_binding_is_absent_after_the_tier_is_cleared.Evidence
cargo test --release -p v1-compiler --lib pure_producer_share— 17 passed, 0 failed (remote, BuildBuddy). Five are this change's: the acquire-once-and-warm positive; the changed-carrier RED; the binding-cleared control; a row naming an unprepared input stopping the line; a non-nullary acquisition refused.Three controls found real defects, which is why they are worth more than their green:
run_in_context, which callscall_functiondirectly and reaches neither the tier nor the binding — so it asserted a value recompute also produces. Discovered by planting the wrong implementation and watching the RED stay green. The controls now evaluate through an ordinary call site and assert an observed serve from the tier's own hit observer.the_carry_is_discharged_at_the_preparation_lca→Bool(false)). At a SHARED-STATE obligation LCA,group_redundant_verdictanswersAuthoredDuplicationand never reaches a provider at all — because §2's repair there is to carry the first value, not to cache it: "caching a later request only makes redundant work cheap and suppresses the signal that would make it rank for deletion". AssertingDischargedwas asking the ladder to bless the move it exists to refuse. The witness now states the transition this mechanism performs —AuthoredDuplicationover the claim-sited demands before,AcceptedSingleRecomputeand every verdict green over the minimized graph after — which is a stronger statement than the one it replaced, and it is the ladder's own words rather than mine.Discrimination receipt for the RED (executed, both arms): with
cross_claim_key_argsreturningNone— the empty-argument-row implementation this control targets —a_changed_carrier_content_is_not_served_the_value_derived_from_the_old_oneFAILS with "the producer must not be SERVED under a changed carrier"; with the real implementation all 17 pass. A control that only asserted "the carried value is served" would pass on both.What is owed at live grain, stated as owed
The live row is enrolled (
roadmap_acceptance_event_history_loadas the prepared input;roadmap_authority_projectionas anImplicitAcquisitionwarm row), so the required floor executes the whole path over the real corpus on this PR. What is not claimed here is the present-vs-absent measurement: it needs twoworkflow_dispatchruns on a branch ref pinned to an exact sha (the corrected procedure in the roster's own header — a pushed side branch triggers nothing and a PR pair measures two different merge refs), read overrequired_floor_claim_cost.tsvand the run's[floor-shared-fill]ledger. The row is admitted only on serve-below-recompute at identity grain; if it does not clear that, it is withdrawn intofloor_cross_claim_refused_candidatesrather than defended by a family aggregate.Wind-down state at
36c54cde2e9(2026-09-14, handed off by gentle-ram-506)Added after the adjudication above (ruling relayed by eager-raven-113 and fierce-lark-661, from warm-heron-775's duplicate model on the closed #11381):
ImplicitAcquisitionalready was this form, so no mechanism change was needed.warm_cross_claim_pure_producerstored with no effect-dispatch guard, so an effectful nullary row rostered as a plain warm row was stored under the empty argument row, blind to what it read. It now refuses withcause=PureProducerShareWarmDispatchedEffect producer=… effects=Nthrough a typedPureProducerWarmRefusal. RED:a_plain_warm_row_that_dispatches_an_effect_stops_the_lineperforms one real hermetic checkout read. All 10pure_producer_share_testspass remotely. Discrimination receipt: with the guard disabled, the test fails atexpect_errbecause the row stored without refusal. Positive control:a_carried_roster_warms_and_stores_its_nullary_rows.prepared-effect-input/<name>, named apart from a share hit.Pending, not claimed:
workflow_dispatchpair described above, and the serve-below-recompute admission decision forroadmap_authority_projection. If the row does not clear it, it is withdrawn intofloor_cross_claim_refused_candidates.LoadRefusedfromLoaded); (b) a shared-fill ledger COUNT for serves refused because the binding changed.#11303 (PR one) is further out than this chain assumed — it was evicted from the merge queue over an unrelated eval-steps ceiling. This PR does not depend on it: the live row uses the
ImplicitAcquisitionarm, which is the shape on main. When #11303 lands, the row becomesBoundParameter— a row edit, not a mechanism change.