Skip to content

Seed: admission precedes identity on the pure-call path; retire the eval-frame result memo - #11741

Closed
gunbai-bot[bot] wants to merge 9 commits into
mainfrom
session/merry-fox-260
Closed

gunbai-bot[bot] wants to merge 9 commits into
mainfrom
session/merry-fox-260

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Handback (2026-09-20, lane merry-fox-260 wound down) — read this first

Standing: HELD as a draft under the parent's ruling (option A, root-first). Not landable in this shape; not stalled — the blockers are attributed, named and partly discharged. Remaining work is carried on the roadmap: gunbc#11859, row eval-memo-admission-rewire-program.

The change here: the seed's pure-call path consumes the std.materialization_ladder judgment before deriving any identity; the eval-frame result memo (EvalCallMemo, GUNBC_EVAL_MEMO, its provider row extdeps.realization.eval_memo) is deleted, the cross-claim tier and parse-table memo (both admitted-first) are untouched, the trace ledger keys only under GUNBC_RECOMPUTE_TRACE=1. A RED control (own test binary) reads the new per-frame identity odometer at zero and goes red when unconditional keying is restored. json.parse goes from quadratic (502 s at 1.09 MB) to linear (39 s), 24 receipts byte-identical.

Why it is held — the floor RED, by the change's own qualification: matched required-floor runs (base 35458211949 vs this head 35466872753): 2,767 / 4,161 claims cost more eval steps without the memo (p90 3.6×, max 116×); 76 grandfathered claims over the 361,500-step ceiling (base 0); 23 pass → budget_interrupted; 134 adjudication blockers. The corpus's witnesses were leaning on the memo for authored within-frame duplication — ladder rule 1, prescribed Share, never a cache — so the ruling refused both a declared-roster memo (B) and withdrawal (C): rewire the shared producers as their own qualified changes, then re-qualify the retirement as a combined cutover on an exact head.

What landed / is landing (each with its own before/after under both realizations):

Remaining, in order (roadmap row): stage 3 — the rust.dag nullary node constants as data (drafted, unopened, preserved on session/merry-fox-260-stage3 at c1c925060c; it resolves and passes, measured 1.71M → 1.10M eval steps memo-retired on the binop catalog claim with memo-on flat — its nine-module before/after was not completed) and the bind_outcome chains; then the combined re-qualification of this head on the repaired corpus (matched floor: population and terminal results unchanged, no pass → budget_interrupted, regen completing). The eager data environment (build_initial_env evaluates every data in the closure on plain gunbc run) is no longer a blocker but is still undemanded work; its own reading is pending (is eager evaluation load-bearing for any refusal/disclosure/gate?).

Do not re-derive: (1) the producer ranking must come from the floor's own required_floor_cross_claim_demand.tsv (within-claim repeats = evals − claims), NOT from claim_batch, which installs no cross-claim roster and therefore charges producers the floor already warm-serves — the first ranking in the comments below was wrong for that reason and is corrected further down; (2) diagnostics_merge ×5,512 on one key in the memo-on trace was memo-hit verification cost on a large argument (Value::eq on serve), not real work — the memo-retired trace shows ~0 wasted for it.

Attribution and ranking comments: attribution, corrected ranking, floor comparison.

What

The seed's pure-call path consumes the materialization judgment before deriving any identity. An undeclared single pure demand (std.materialization_ladder rule 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 row extdeps.realization.eval_memo are deleted. Net seed delta: −363/+287 lines across the change, −207/+64 in v1_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 the Memoize verdict 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 discloses argument_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 is AcceptedSingleRecompute (rule 5); a repeated demand whose LCA is a shared-state frame is AuthoredDuplication, prescribed Share, never Memoize (rule 1); only a plural demand at an isolation boundary or under declared emergence is Discharged into 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 under a: 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_call built eval_recompute_key for every pure call because b told it to; Value::Str is hashed in full per call (composites have allocation-local hash reuse, strings never had one).
  • d — extdeps.languages.json.parse threads the document through every *_at(s, i) call → O(n²) key building; gunbc.fleet_health selected GUNBC_EVAL_MEMO=0 to route around it.

The refused fixes (pointer-hash string cache, name allowlist, adaptive seed cache) all keep boundary b and cheapen the work done past it. Deleting b is 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

  1. A direct-recompute demand reaches neither key construction nor memo storage, with a RED control. src/v1/stage0/tests/pure_demand_recompute_admission.rs (its own binary because the trace latch is process-wide): two equal pure demands with a String argument 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 unconditional eval_recompute_key before admission: left: 2, right: 0.
  2. Equal demands still reuse where admitted; different args stay different; collision controls kept. The cross-claim tier's enrolled controls are unchanged and pass: 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).
  3. Output + refusal equality on valid / malformed / truncated / trailing / large. New instrument 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 .out files are byte-compared between the merge-base binary (memo on, default) and this branch's binary. See table below.
  4. Input-size series. Same instrument: bytes, elapsed per subject, argument_identities_derived (0 on the production route by construction; the ledger's count under trace), peak RSS via getrusage. See table below.
  5. Matched floor runs. See the CI comparison below (per-entry 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/-j4 release)

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. elapsed is the BEGIN→out mtime bracket per subject; out_sha is the receipt's sha256 (serialized value on a parse, typed gap text on a refusal); process peak RSS from getrusage (dominated by corpus resolution, ~6 GB on every run).

subject bytes base memo-on (s) base memo-off (s) this branch (s) receipt sha (identical across all three)
m0250 67,215 3.44 2.28 2.53 f8b402654ef8449e
m0500 134,715 10.58 4.50 5.27 7fd206782c72cc91
m1000 269,719 36.00 8.92 9.62 a5a6ac664447dbe1
m2000 542,719 132.21 18.17 19.15 77168613d65e7374
m4000 (large) 1,088,719 502.01 36.65 38.81 651fe1b20ff509ed
malformed 22 0.00 0.00 0.00 a67cbf106140902a (REFUSED not readable as JSON at offset 17)
truncated 13,321 0.36 0.33 0.36 e7747c2ac3d16f7f (REFUSED not readable as JSON at offset 13321)
trailing 831 0.02 0.02 0.02 88d56bd3bac11191 (REFUSED … trailing content at offset 830)
whole process wall 811 s / user 989 s / RSS 6969 MB wall 194 s / user 188 s / RSS 6140 MB wall 206 s / user 199 s / RSS 6141 MB

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_value gains 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 under rust_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_standing purpose test: every interpreted v2 route — the self-host compile, the required floor, every instrument — paid this per-call identity derivation; the change is BehaviorPreservingRedundancyRemoval that leaves the seed smaller. Refused classes: no new language behavior, no compatibility obligation (GUNBC_EVAL_MEMO is 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_growth enumerates the two added items (argument_identities_derived, note_argument_identity_derived) and is enrolled in seed_growth_justification_roster.
  • gunbc.materialization_provider_targets drops the eval-memo row (witness count pin 7 → 6, renamed); tools.cause_assertion_census no 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) sets GUNBC_EVAL_MEMO=0; after this lands that variable is unread and can be dropped there — recompute is the only realization.
  • Recorded honestly in ci_floor_materialization_receipt_note: no consumer of take_process_eval_recompute_totals exists in the tree today, so target/floor-materialization-receipt.txt is not written by any current surface. That predates this change and is a separate finding.

🤖 Generated with Claude Code

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

gunbai-bot Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

Acceptance (5): matched floor runs — the consumer-wide qualification, and it is red

Base run 35458211949 (13d9308, same required-gate population) vs this PR's run 35466872753 (d0d90d3): 4,184 common claims, 4,161 with eval_steps on both sides.

base (memo on) this head (memo retired)
claims doing MORE eval steps — 2,767 / 4,161 (median +14 %, p90 3.6×, p99 19×, max 116×)
claims unchanged — 1,394
grandfathered claims over the 361,500-step ceiling 0 76
new-witness claims over the 72,300-step line 52 245
pass → budget_interrupted — 23
fail 19 19 (same set)
adjudication green REFUSED, 134 blockers

Largest movers: test.claim.runner_capacity_plan_witness.* (116×, 69×, 37×), v2.test.claim.translate_underived_refusal.* (94×, 93×), test.claim.compiler_frontend_program_status_witness.* (70×, 55×, 37×). Terminal results are otherwise preserved (no pass↔fail flips); what moved is cost.

Reading: the corpus's witnesses carry a large population of within-frame repeated pure demands — std.materialization_ladder rule 1 AuthoredDuplication, prescribed Share — that the memo was discharging invisibly. The retirement is the ladder's own reading, but the qualification says the consumers are not rewired, so this head cannot land the floor green as-is. Escalated to the parent with three options (A: rewire program first; B: recompute by default + the memo kept only as a DECLARED roster provider filed as a §4b(3) drop against rule 1 with "rewire to Share" as its trigger; C: withdraw). Recommendation on the escalation is B. Nothing more lands on this PR until that ruling.

Reply to review 68632 (REQUEST_CHANGES)

Verified and agreed: gunbc.rung_drop.determinism_transitive_reachability told later lanes to protect the memo on the strength of a memo-on-with-keying vs memo-off-with-keying arm (the retired GUNBC_EVAL_MEMO=0 realization still derived an identity per call). Re-measured on its one surviving executing consumer, determinism_live_intra_holds, with claim_batch --claim-run on both binaries: 165,094 → 327,130 eval_steps (2.0×, not 100×; CPU 312 ms → 582 ms), under its grandfathered 361,500-step ceiling. The row is reconciled on the branch (next push): the two live-tense GUNBC_EVAL_MEMO sentences are dated and marked retired, the "protect it" constraint is withdrawn with the measurement that withdraws it, and the loop-invariant the memo was hiding is restated as part of the row's own trigger obligation (carry, don't re-demand). docs/design-rung-drops.md is regenerated from the row.

Brian Searls and others added 3 commits September 19, 2026 22:17
…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>
@gunbai-bot

gunbai-bot Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

Two more qualification readings, both against landing this head as-is

tools.docs_projection_gate regen (the DESIGN/rung-drops projection, run in CI): merge-base binary 4m59s wall / 4m50s CPU; this branch's binary killed at 48 min elapsed, 47 min CPU, 11 GB RSS, still running — at least 10× and unbounded from where I stopped it. docs/design-rung-drops.md on this branch was therefore regenerated with the merge-base binary over the reconciled rows.

What the memo was serving (claim_batch --claim-run under GUNBC_RECOMPUTE_TRACE=1 on v2.test.claim.translate_underived_refusal, the module with the 93×/94× movers), wasted ms summed over the module's 14 claims, top of the ledger:

producer wasted ms repeat calls
infer 16,530 120
infer_entries_for_tree 16,428 120
rust_integer_facts_node (nullary) 7,253 2,998
translate_grounding_derived_gate 6,992 216
infer_gather_fold_init 6,954 864
rust_add_i32_facts_node (nullary) 6,936 2,946
inferred_facts_witness_for_node 6,388 198
infer_language_inhabitants_roster_roots (nullary) 6,067 3,441

Two shapes, both std.materialization_ladder rule 1 (AuthoredDuplication → Share): (i) infer re-demanded on the same tree from many sites (the whole inferred-facts fold recomputed ~120× per claim); (ii) nullary pure fns used as constants (rust_integer_facts_node() demanded ~3,000 times) — a fn standing where a data declaration belongs, which the seed's per-ctx data_cache would already evaluate once. The memo was the corpus's undeclared discharge for both. Same shape on determinism_live_intra_holds (node_callee_symbol, primitive_definition_of, decls_in_modules).

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

gunbai-bot Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

Reply to review 68692 (REQUEST_CHANGES), both findings verified and fixed in fb0e2df: the two receipts in memo_key_rehashes_a_growing_persistent_value that still presented GUNBC_EVAL_MEMO=0 / extdeps.realization.eval_memo as a selectable mitigation are dated (2026-09-18) and marked superseded by the repair receipt; the rung after repair now reads MECHANICALLY PREVENTABLE — the state is writable by one restored call, the control refuses it, and that control sits under rust_unit_tests_off_the_merge_path — with the structural ceiling and its M1 trigger stated beside it rather than claimed. PR body updated to match. The escalation on whether this head can land at all (floor red, 134 blockers) is still open with the parent.

@gunbai-bot
gunbai-bot Bot marked this pull request as draft September 19, 2026 23:35
@gunbai-bot

gunbai-bot Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

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 fns → data; the repeated infer demand carried instead of re-demanded), each with its own before/after. Option B (a declared within-frame provider roster) is refused: the dependencies are ladder rule-1 AuthoredDuplication and a roster prices discharge, it does not reclassify a demand. Also binding: the docs-projection regen that never completed is independently disqualifying (a base-binary regen preserves the artifact, proves nothing about the replacement), a red floor is not delete-first licence (gap-intolerant boundary: prepare the replacement, switch when it preserves the contract), and the 23 pass→budget_interrupted flips break the floor's contract on their own. In progress on this lane: per-producer attribution of the regen blowup and a measured ranking of the shared producers to order the rewires.

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

gunbai-bot Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

Reply to review 68707 (REQUEST_CHANGES): verified — dag/gunbc/legacy_extdeps_scope_frontier.tsv still rostered the deleted dag/extdeps/realization/eval_memo.dag; the row is removed in 71af78b. Merge readiness is unchanged: the PR is a draft under the parent's option-A ruling and is not landable in its current shape regardless of review state (floor red by the change's own qualification; producer rewires first).

# Conflicts:
#	dag/gunbc/seed_growth_admission.dag
@gunbai-bot

gunbai-bot Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor Author

Attribution and ranking (option-A work, no landing)

1. The docs-regen blowup is attributed, and it is NOT the producers

Re-derived on the memo-retired binary (gunbc run --entry dag/gunbc/instruments/docs_projection_gate.dag):

route memo-retired binary
expected_design_failure_modes_md via --claim-run (no eager data env) completes, 254 s wall, resolve-dominated
whole failure_mode_document() serialization (354 rows, 2.56 MB) from a scratch entry ~15 s over resolve
same producer via plain gunbc run (eager data env) timed out at 25 min
build_initial_env alone (any function, plain gunbc run) with per-declaration begin/end marks 3,137 data declarations finish (largest: int128_interval_spec 456 ms); data witness_floor_workflow (dag/gunbc/witness/witness_floor_workflow.dag) never finishes (>15 min, killed)

Chain: (a) plain gunbc run eagerly evaluates every data declaration in the entry's closure before calling the function (v1_interpreter::build_initial_env, eager_data_env = !claim_run) — the regen never demands the CI workflow, yet pays it; (b) witness_floor_workflow's body carries an authored recurrence the memo was serving: on the memo-on trace of the same eager env, diagnostics_merge is re-demanded 5,512× on one key, bash_fold_serialize_body 10× at ~800 ms, plus the grammar production-matching family (formal_production_rhs_matches_emitted_conj_step, formal_production_for_lhs_exact, …). Two rewires, each its own change: the eager env (undemanded work; eval_var already evaluates data lazily through data_cache) and the workflow fold's recurrence.

2. Shared producers ranked by measured contribution

Memo-on binary, GUNBC_RECOMPUTE_TRACE=1, claim_batch --claim-run over every module with an over-line or interrupted claim in run 35466872753 (115 modules, 627 claims traced). "projected inclusive ms" = Σ over ledger keys of first-evaluation time × (repeats), inclusive of callees, so nested producers double-count — it is an ORDER, not a sum.

rank producer shape projected inclusive ms repeats claims declaration
1 grammar_node_insert_atom_identities_child args 8,081,003 264,219 44 src/v2/std/grammar.dag
2 grammar_node_insert_atom_identities args 5,175,335 233,015 44 src/v2/std/grammar.dag
3 dag_canonical_symbols nullary 496,176 125 25 src/v2/extdeps/languages/dag.dag
4 dag_canonical_symbol_map nullary 495,884 125 25 src/v2/extdeps/languages/dag.dag
5 rustc_phase_order ? 490,901 480,193 74 dag/gunbc/self_host_compile_phase_frontier.dag
6 grammar_carried_symbol_map ? 490,473 125 25 src/v2/extdeps/languages/dag.dag
7 dag_language_model ? 482,581 105 14 src/v2/workflow/floor_cost_debt_edit.dag
8 grammar_expr_node args 224,858 280,242 39 src/v2/std/grammar.dag
9 floor_route_gap_roster ? 166,518 1,060 45 dag/gunbc/witness/v2_native_route.dag
10 inferred_tree_digest ? 163,002 2,352 24 src/v2/test/claim/execution/native_selected_witness_bundle_test.dag
11 grammar_named_edge args 162,417 414,909 41 src/v2/std/grammar.dag
12 parse_expr_with_first args 153,278 8,744 29 src/v2/compiler/02_parse.dag
13 structural_property_witness_digest args 132,443 15,737 40 src/v2/compiler/05_eval.dag
14 grammar_to_node args 128,075 147 29 src/v2/std/grammar.dag
15 grammar_root_to_node args 120,068 119 24 src/v2/std/grammar.dag
16 grammar_productions_to_node args 119,694 118 23 src/v2/std/grammar.dag
17 grammar_production_to_list_step args 118,776 4,647 21 src/v2/std/grammar.dag
18 descent_witness_digest args 116,020 9,128 40 src/v2/compiler/05_eval.dag
19 grammar_production_to_node args 115,533 4,635 20 src/v2/std/grammar.dag
20 grammar_expr_to_node args 112,515 4,705 33 src/v2/std/grammar.dag
21 milestone_status args 109,627 4,115 28 dag/gunbc/compiler_frontend_program_status.dag
22 floor_expected_red_roster ? 99,316 1,060 45 dag/gunbc/witness/v2_native_route.dag
23 selected_logic_primary_plan nullary 97,335 331 23 src/v2/test/claim/execution/native_selected_witness_bundle_test.dag
24 floor_route_gap_expectations nullary 89,178 962 45 src/v2/workflow/floor_route_gap.dag
25 gunbc_runner_cores_per_slot nullary 89,138 1,756 60 dag/gunbc/runner/runner_slot_allocation.dag
26 selected_logic_identity args 82,873 1,155 23 src/v2/test/claim/execution/native_selected_witness_bundle_test.dag
27 selected_logic_plan_for args 79,786 367 23 src/v2/test/claim/execution/native_selected_witness_bundle_test.dag
28 inferred_tree_evaluated_facts_digest args 79,165 1,202 37 src/v2/compiler/05_eval.dag
29 selected_logic_native_member args 78,697 1,075 20 src/v2/test/claim/execution/native_selected_witness_bundle_test.dag
30 parse_expr_sequence args 77,433 3,097 29 src/v2/compiler/02_parse.dag

Reading: ranks 1–7 are ONE root — the nullary constants dag_language_model() → dag_canonical_symbols() → dag_canonical_symbol_map() → grammar_carried_symbol_map(grammar: dag_grammar()), demanded ~125× across 25–44 claims and re-walking the whole grammar tree each time (grammar_node_insert_atom_identities*, 264k/233k repeats). Converting that family (and dag_grammar/dag_lex/dag_lex_rules beneath it) from nullary fn to data is stage 1: one change, measured before/after on those 44 claims. Stage 2: the other nullary constants demanded per call — rustc_phase_order (480k repeats / 74 claims; it takes a phase argument, so it is a table lookup re-deriving its table), the floor rosters floor_route_gap_roster / floor_expected_red_roster / floor_route_gap_expectations (~1k repeats / 45 claims), gunbc_runner_cores_per_slot / gunbc_runner_slot_desired (60 claims). Stage 3: the carried-result rewires — the 05_eval infer digests (structural_property_witness_digest, descent_witness_digest, inferred_node_facts_cache_digest, 12–16k repeats / 40 claims) and 02_parse parse_expr_with_first / parse_expr_sequence re-demands — which are the "carried infer result" class the ruling names.

@gunbai-bot

gunbai-bot Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor Author

Ranking correction — the floor-faithful census supersedes the claim_batch one above

The ranking in the previous comment was measured with claim_batch, which installs no cross-claim roster, so it charged producers the floor already serves from the warm tier (dag_canonical_symbol_map is a rostered warm row; its grammar_carried_symbol_map walk is paid once per floor run, not per claim). The floor's own census from the memo-retired run 35466872753 (required_floor_cross_claim_demand.tsv; within-claim repeats = evals − claims per producer key, summed over keys; inclusive of callees, so an ORDER, not a sum) is the ranking that the stages follow:

rank producer within-claim repeat ms (memo retired, inclusive) same, base memo-on repeats declaration
1 integer_pow2_magnitude 2,050,922 1,844 22,715 src/v2/std/integer.dag
2 formal_production_for_lhs_exact 931,054 2,957 86,155 src/v2/std/grammar.dag
3 formal_production_for_lhs_exact_supported 927,613 0 86,155 src/v2/std/grammar.dag
4 formal_production_unique_lhs_exact_match 926,151 0 86,155 src/v2/std/grammar.dag
5 formal_production_rhs_matches_emitted_conj_step 895,624 1,570 170,205 src/v2/std/grammar.dag
6 formal_production_matches_lhs_exact_child 813,661 997 371,712 src/v2/std/grammar.dag
7 lhs_exact_production_match_fold_step 787,746 0 371,660 src/v2/std/grammar.dag
8 formal_production_matches_emitted_child 763,370 2 371,340 src/v2/std/grammar.dag
9 formal_production_rhs_matches_emitted_conj 733,769 0 97,173 src/v2/std/grammar.dag
10 formal_production_rhs_matches_emitted_conj_conj 731,003 0 97,138 src/v2/std/grammar.dag
11 decimal_digits_double 549,729 0 296,253 src/v2/std/integer.dag
12 bind_outcome 349,034 55,003 89,476 src/v2/std/diagnostic.dag
13 formal_productions_for_lhs 87,312 334 87,840 src/v2/std/grammar.dag
14 decimal_digit_of_units 79,593 3 579,483 src/v2/std/integer.dag
15 rust_integer_facts_node 71,013 229 11,309 src/v2/extdeps/languages/rust.dag
16 formal_productions_for_lhs_step 66,411 0 4,662,659 src/v2/std/grammar.dag
17 rust_integer_range_node 61,923 0 11,309 src/v2/extdeps/languages/rust.dag
18 decimal_digit_double 59,289 0 362,484 src/v2/std/integer.dag
19 decimal_nonzero_double 57,995 0 22,683 src/v2/std/integer.dag
20 rust_integer_inhabitant_node 49,831 221 1,926 src/v2/extdeps/languages/rust.dag
21 rust_declared_inhabitants_root 47,588 644 143 src/v2/extdeps/languages/rust.dag
22 rust_integer_carrier_interval_spec 45,718 0 11,267 src/v2/extdeps/languages/rust.dag
23 decimal_digit_value 42,867 0 4,427,718 src/v2/std/integer.dag
24 inferred_facts_witness_for_node 39,518 66 9,644 src/v2/compiler/04_infer.dag
25 rust_add_declared_inhabitants_root 36,878 0 125 src/v2/extdeps/languages/rust.dag
26 rust_coercion_candidate_edges 36,875 0 125 src/v2/extdeps/languages/rust.dag
27 translate_grounding_derived_gate 32,531 104 7,447 src/v2/compiler/06_translate.dag
28 rust_target_model_core_edges_with_operators 31,719 0 108 src/v2/extdeps/languages/rust.dag
29 rust_target_model_core_edges_full 30,852 0 108 src/v2/extdeps/languages/rust.dag
30 rust_add_inferred_facts_for 30,029 8 8,091 src/v2/test/claim/manual/rust_add_emit_translate_test.dag

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 formal_production_* grammar lookup family (ranks 2–10, 13, 16), then bind_outcome chains and the rust.dag nullary node constants (ranks 15, 17, 20–22).

Brian Searls and others added 2 commits September 20, 2026 08:00
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-20T14:57:08.438862Z e85c469 Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@gunbai-bot
gunbai-bot Bot marked this pull request as draft September 20, 2026 14:51

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@briansrls briansrls closed this Sep 20, 2026
gunbai-bot Bot pushed a commit that referenced this pull request Sep 27, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant