Repository navigation
Seed: admission precedes identity on the pure-call path; retire the eval-frame result memo - #11741
gunbai-bot[bot] wants to merge 9 commits into
Conversation
…val-frame result memo An undeclared single pure demand is AcceptedSingleRecompute under std.materialization_ladder (rule 5), and a within-frame repeat is AuthoredDuplication prescribed Share (rule 1) -- never Memoize. The eval-frame result memo (extdeps.realization.eval_memo) was a provider scoped to one shared-state frame, so the ladder never discharged a demand into it: its admitted population was empty by construction, yet it derived an identity for every pure call before any admission was asked. On a fold threading a document through recursion (extdeps.languages.json.parse) that is O(n^2) key building. eval_pure_named_call now consumes the judgment before any key: the cross-claim tier (roster-admitted) and the parse-table memo (Memoize-carried) keep admitting first and keying second; an undeclared demand derives nothing, looks nothing up, retains nothing. EvalCallMemo, GUNBC_EVAL_MEMO, eval_call_memo_frame_exit, the memo receipt fields and the provider row are deleted. The recompute-trace ledger still keys under GUNBC_RECOMPUTE_TRACE=1 as the rule-4 instrument and now discloses argument_identities_derived, its own keying work. Enrolled control: tests/pure_demand_recompute_admission reads the new per-frame odometer back at zero on the production route and goes red when unconditional keying is restored; the trace ledger is its positive control. Instrument: tools.json_parse_cost_probe re-derives the size series and the output/refusal receipts across binaries. gunbc.recurring_failure_mode.memo_key_rehashes_a_growing_persistent_value records the second (string) instance, the earliest unjustified boundary, the repair and the rung after repair; gunbc.pure_demand_admission_seed_growth enumerates the two added seed items. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Acceptance (5): matched floor runs — the consumer-wide qualification, and it is redBase run 35458211949 (13d9308, same required-gate population) vs this PR's run 35466872753 (d0d90d3): 4,184 common claims, 4,161 with
Largest movers: Reading: the corpus's witnesses carry a large population of within-frame repeated pure demands — Reply to review 68632 (REQUEST_CHANGES)Verified and agreed: |
…e memo retirement Review 68632: the row told later lanes to protect the eval-frame memo on a memo-on-vs-memo-off-with-keying arm, and cited GUNBC_EVAL_MEMO in the present tense. The two sentences are dated and marked retired, the constraint is withdrawn with the reading at the retiring head (determinism_live_intra_holds 165094 -> 327130 eval steps, 2x not 100x, under its grandfathered ceiling), and the loop-invariant the memo hid is restated as part of the row's own trigger obligation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts: # dag/gunbc/seed_growth_admission.dag
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two more qualification readings, both against landing this head as-is
What the memo was serving (
Two shapes, both So the honest statement of this PR's standing: the root repair is right and its consumer-wide qualification says the corpus is not ready for it — option A on the escalation is a corpus program (nullary-fn→data and infer-sharing rewires), not a follow-up. Holding for the parent's ruling. |
… rung as mechanically preventable Review 68692: two receipts still described GUNBC_EVAL_MEMO=0 and the eval_memo provider row as a selectable mitigation after this change deletes both, and the rung after repair claimed structural impossibility for a state that one restored call can write. Both receipts are dated and marked superseded; the rung is mechanically preventable, with the control's off-merge-path standing (rust_unit_tests_off_the_merge_path) and the structural ceiling and its trigger stated beside it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Reply to review 68692 (REQUEST_CHANGES), both findings verified and fixed in fb0e2df: the two receipts in |
|
Ruling (parent, relaying the side-chat): option A. This PR is HELD in its current shape and converted to draft. The root repair (admission before identity; the memo, its switch and its provider row deleted) and the RED control stay on the branch; the retirement is re-qualified only as a combined cutover on an exact head AFTER the shared producers are rewired as their own qualified changes (nullary producer |
…pe frontier Review 68707: the frontier roster is remove-only and disk-resolution is merge-gated; the row for dag/extdeps/realization/eval_memo.dag must leave in the same change that deletes the file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Reply to review 68707 (REQUEST_CHANGES): verified — |
# Conflicts: # dag/gunbc/seed_growth_admission.dag
Attribution and ranking (option-A work, no landing)1. The docs-regen blowup is attributed, and it is NOT the producersRe-derived on the memo-retired binary (
Chain: (a) plain 2. Shared producers ranked by measured contributionMemo-on binary,
Reading: ranks 1–7 are ONE root — the nullary constants |
Ranking correction — the floor-faithful census supersedes the claim_batch one aboveThe ranking in the previous comment was measured with
total within-claim repeat ms (inclusive, do not sum): pr=12787193 base=89549 Stage 1 (rank 1, the integer decode re-deriving every standard type's 2^n ladder) is #11784. Stage 2 is the |
# Conflicts: # docs/design-rung-drops.md
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e85c4690db
ℹ️ 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".
| let interner = ctx.symbols.borrow(); | ||
| let mut keys = Vec::with_capacity(args.len()); | ||
| for (_, v) in args { | ||
| note_argument_identity_derived(ctx); |
There was a problem hiding this comment.
Increment the identity counter only after successful derivation
When recompute tracing encounters an unkeyable argument, such as a closure, this increments the counter before eval_recompute_arg_key returns None; eval_pure_named_call then invokes eval_recompute_partial_key, which traverses and increments the same positions again. Consequently the new public accessor and [recompute-trace] field report failed attempts—and double-count a prefix—as argument_identities_derived, making the diagnostic evidence inaccurate for the floor's known unkeyable-call population. Increment only after receiving Some, or report attempts under a distinct name.
Useful? React with 👍 / 👎.
…ap key derived per insert Replaces the admission change (option A) under neat-boar-16's ruling (B-lite): #12066 is the standing authority for this class, and #11741 showed A is a program of its own. Mechanism, corrected by measurement: with the key cost removed the parse was still quadratic. The cost was eval_call_memo_get's verification. value_fast_eq shortcut only on top-level allocation identity, so a served hit on parse_table_with_furthest -- a ParseTable rebuilt as a new record around the SAME entries map and grammar analysis -- fell into a deep Value::eq over the whole table: O(|table|) per hit, quadratic per parse. value_fast_eq now descends to the first differing allocation, agreeing with Value::eq arm for arm. Also, per the ruling: the map key is derived per insert and overwrite (eval_recompute_extend_insert_hash, beside #12066's per-push list key), with a property control (derived == from-scratch over randomized insert/overwrite, through both production arms). Residue filed as an rfm: instrumentation_counters_inside_a_semantic_value_defeat_identity. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
What
The seed's pure-call path consumes the materialization judgment before deriving any identity. An undeclared single pure demand (
std.materialization_ladderrule 5:AcceptedSingleRecompute→Recompute) now constructs, looks up and retains no result-memo key. The eval-frame result memo (EvalCallMemo,GUNBC_EVAL_MEMO,eval_call_memo_frame_exit, its hit/miss/overflow receipt fields,value_fast_eq) and its provider rowextdeps.realization.eval_memoare deleted. Net seed delta: −363/+287 lines across the change, −207/+64 inv1_interpreter.rs.The two provider tiers that remain each already decide admission first and key second, and are untouched: the cross-claim tier (roster of
v2.workflow.floor_pure_producer_share, admitted by resolved declaration identity, then content-hashed, then verified on serve) and the parse-table memo (admitted by theMemoizeverdict carried on the table). The recompute-trace ledger (GUNBC_RECOMPUTE_TRACE=1, which the floor sets for itself) still keys every pure demand — it is the rule-4 measurement instrument and serves nothing — and now also disclosesargument_identities_derived, its own keying work.Chain re-derivation (DESIGN §6b) — why this is the root and not a symptom patch
a—std.materialization_ladder: a single undeclared pure demand isAcceptedSingleRecompute(rule 5); a repeated demand whose LCA is a shared-state frame isAuthoredDuplication, prescribed Share, never Memoize (rule 1); only a plural demand at an isolation boundary or under declared emergence isDischargedinto a covering provider.b—extdeps.realization.eval_memo: declared itself "the ladder's single-site discharge provider" serving "every repeated pure named-fn demand within one InterpContext". A provider scoped to ONE shared-state frame can never be the discharging provider of anything undera: every demand it could see was either single (Recompute) or a within-frame repeat (Share). Its admitted population was empty by construction. This is the earliest unjustified boundary.c—eval_pure_named_callbuilteval_recompute_keyfor every pure call becausebtold it to;Value::Stris hashed in full per call (composites have allocation-local hash reuse, strings never had one).d—extdeps.languages.json.parsethreads the document through every*_at(s, i)call → O(n²) key building;gunbc.fleet_healthselectedGUNBC_EVAL_MEMO=0to route around it.The refused fixes (pointer-hash string cache, name allowlist, adaptive seed cache) all keep boundary
band cheapen the work done past it. Deletingbis the repair; a gate over an empty admitted set would be dead weight of the same kind, so the memo is deleted rather than gated.Acceptance
src/v1/stage0/tests/pure_demand_recompute_admission.rs(its own binary because the trace latch is process-wide): two equal pure demands with aStringargument on the production route derive 0 argument identities (a new per-frame odometer,argument_identities_derived, single writer at the three keying sites) and both evaluate in full (equal evaluator-step deltas — a served repeat takes no callee steps). Positive control: the same pair under the trace ledger derives exactly 2 and still evaluates both. Verified red by temporarily restoring an unconditionaleval_recompute_keybefore admission:left: 2, right: 0.a_rostered_producer_fills_once_and_serves_later_claims,the_same_args_under_a_different_fn_identity_miss,cross_claim_memo_key_distinguishes_field_names_across_ordinal_collisions,every_field_of_a_served_record_resolves_under_a_reordered_interner,a_homonym_outside_the_roster_identity_does_not_store(cargo test --release -p v1-compiler --lib -- recompute cross_claim: 29 passed).tools.json_parse_cost_probe(dag/gunbc/instruments/json_parse_cost_probe.dag) writes the serialized value or the typed gap text per subject; the.outfiles are byte-compared between the merge-base binary (memo on, default) and this branch's binary. See table below.argument_identities_derived(0 on the production route by construction; the ledger's count under trace), peak RSS viagetrusage. See table below.eval_steps/ cpu deltas against the base run at the same population).Size series and receipt equality (
tools.json_parse_cost_probe, this session's arm64 container, both binaries built locally at-j2/-j4release)Three runs over the same eight subjects: the merge-base binary (56375ec, memo on = default), the merge-base binary with
GUNBC_EVAL_MEMO=0, and this branch's binary.elapsedis the BEGIN→out mtime bracket per subject;out_shais the receipt's sha256 (serialized value on a parse, typed gap text on a refusal); process peak RSS fromgetrusage(dominated by corpus resolution, ~6 GB on every run).REFUSED not readable as JSON at offset 17)REFUSED not readable as JSON at offset 13321)REFUSED … trailing content at offset 830)Memo-on is quadratic (×2 bytes → ×3.7–3.8 s); this branch is linear and coincides with memo-off within noise. Key-building work on the production route is 0 identities by construction (the RED control reads the odometer); the deleted work is the difference between the memo-on and memo-off columns. All 24 receipts are byte-identical across the three binaries.
Recurring failure mode, purpose test, seed growth
gunbc.recurring_failure_mode.memo_key_rehashes_a_growing_persistent_valuegains its second instance (the string case), the earliest-unjustified-boundary reading, the repair, and the rung after repair at the declared grain: mechanically preventable for undeclared demands (the state stays writable; the RED above refuses it, and that RED is off the merge path underrust_unit_tests_off_the_merge_path), unchanged for the roster-admitted cross-claim population, whose ceiling, trigger and program remedy (retire the seed) stand. The row's "no new seed cache, no evaluator patch" is honoured: this change deletes a cache.gunbc.v1_maintenance_standingpurpose test: every interpreted v2 route — the self-host compile, the required floor, every instrument — paid this per-call identity derivation; the change isBehaviorPreservingRedundancyRemovalthat leaves the seed smaller. Refused classes: no new language behavior, no compatibility obligation (GUNBC_EVAL_MEMOis retired, not kept as a no-op arm), no escape hatch, no seed capability; exported surface grows by exactly one reader.gunbc.pure_demand_admission_seed_growthenumerates the two added items (argument_identities_derived,note_argument_identity_derived) and is enrolled inseed_growth_justification_roster.gunbc.materialization_provider_targetsdrops the eval-memo row (witness count pin 7 → 6, renamed);tools.cause_assertion_censusno longer prefixes its invocation with a switch that no longer exists.Consumers
gunbc.fleet_health(HEALTH-0: an out-of-band, read-only fleet health check #11681, untouched) setsGUNBC_EVAL_MEMO=0; after this lands that variable is unread and can be dropped there — recompute is the only realization.ci_floor_materialization_receipt_note: no consumer oftake_process_eval_recompute_totalsexists in the tree today, sotarget/floor-materialization-receipt.txtis not written by any current surface. That predates this change and is a separate finding.🤖 Generated with Claude Code