Skip to content

XL-2: read the param/field/generic/let/function-value/service binder roles through body lowering's readers; QualifiedFieldTypeVisibility delivered - #12598

Merged
gunbai-bot[bot] merged 12 commits into
mainfrom
session/keen-fox-715
Sep 30, 2026
Merged

gunbai-bot[bot] merged 12 commits into
mainfrom
session/keen-fox-715

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

XL-2 (work item node://adhoc-cee52571-234, owner quiet-seal-543). Two parts: (1) the remaining occurrence-role readers, and (2) the qualified field-type carrier arm.

1. Occurrence roles: 9 of the 10 NameRoleNotYetRead rows now read, and one stays loud on purpose

v2.compiler.occurrence_role gets new NameReader arms. Each arm calls the reader that body lowering already lowers that production through. There is no second authority. Those readers lived in v2.compiler.body_lowering_fold and reduced the binder to a Symbol, so the token's minted occurrence was gone. Each one now reads a record that carries the binder atom, and the old Symbol/Edge readers are views of that record. The owners of that file cleared this beforehand: lively-bear-30 has nothing in flight there, and bright-boar-848 approved adding sibling readers but not editing body_lower_param_binding_atom_optional, which this PR does not touch.

production reader arm lowering reader it reuses role / category
param_list ReadParamListBinders body_lower_collect_typed_params (the domain's collector; body_lower_collect_param_edges is its projection) Declaration / LexicalValue
field_decl_block ReadFieldDeclBinders body_lower_field_decl_optional via body_lower_field_decl_block_items_optional (shared with body_lower_field_decl_block_payload) Declaration / Field
generic_params ReadGenericParamBinders body_lower_generic_param_binders (body_lower_generic_param_edges is its projection) Declaration / Type
let_expr ReadLetBinder body_lower_let_in_key_binding_atom_optional (body_lower_let_in_key_binding_optional is its projection) Declaration / LexicalValue
fn_literal, arrow_lambda ReadFunctionValueBinders { kind } v2.compiler.fold_lowering function_value_parts_optional (FunctionValueBinder.at) Declaration / LexicalValue
operation ReadKwThenIdent body_lower_operation's kw-then-ident decoder Declaration / Callable
input_block, output_block ReadIoFieldBinders body_lower_io_item_optional (shared with body_lower_io_block) Declaration / Field
transport still NameRoleNotYetRead none: body lowering sets the member aside unread none

Why transport stays unread. transport shell { .. } names one of a closed set of transport kinds (v1 00_core TransportKind: rest, shell, file, local). That name is not a binder and not a module-scope reference. NamesAreMarkers would claim that some census channel counts it, and none does. No OccurrenceCategory describes a selector from a closed vocabulary. So the row stays loud until someone rules on a category, which I've raised with the parent. It is the only source of the 6 remaining not-yet-read nodes below.

Fixture controls (v2.test.claim.occurrence_role.occurrence_role):

  • every_binder_production_records_its_binders_holds is one fixture that writes each binder production once.
  • the_binder_productions_are_neither_unread_nor_refused_holds checks 17 roles with no unread and no refused counts.
  • The existing fixture counts were re-derived (7 → 11 roles).
  • Table admission still refuses a row that is removed without a reader (existing controls).

In v2.test.claim.namespace_xl0.reference_conservation, three existing controls were restated because they encoded the old gap:

  • The params/field binders of the construct-tags fixture are now role_excluded, not locus_erased.
  • The clean control's locus_erased is now 0.
  • The "roles observed under a normalization refusal" control now uses a transport member, the one unread production left, to keep a non-zero gap to observe.

Measurement: role_not_yet_read, before and after.

  • Instrument: v2.compiler.reference_conservation_census reference_conservation_census_for_paths over reference_conservation_stratified_sample_paths.
  • Batches of 25 paths, one gunbc run process per batch, both arms on 30 GB BuildBuddy runners.
  • Totals count completed batches only. All 13 of 13 batches completed in both arms.
total over 322 module rows merge-base 2c1172b31bb this branch e77d033c35b
role_not_yet_read 1849 6 (all transport: extdeps.iputils.arping, extdeps.tools.id, two dag/test/claim shell witnesses)
locus_erased 1536 353
role_excluded 3926 5109
role_reader_refused 0 0
conserved / dropped / refused / authored 11317 / 9185 / 123 / 26878 identical

locus_erased fell by exactly as much as role_excluded rose (1183), and every lowering-sensitive number is identical. That is the receipt that the reader refactor in body_lowering_fold changed no lowering output.

Deviation from the brief: it asked for a child cgroup memory.max per batch, and I couldn't provide one here. On the BuildBuddy runner I can mount cgroup2 and set memory.max, but a process moved into the child cgroup terminates silently. I measured that in a single-path debug dispatch. Each batch was therefore bounded by GUNBC_MEMORY_BUDGET_BYTES=24e9 and the runner's 30 GB instead. The census has no ProcessExit entry, so the text came out through a throwaway wrapper module that existed only inside the job and was never committed.

2. QualifiedFieldTypeVisibility: attributed, and already delivered

Attribution. On main 14d58480c9, a_qualified_field_type_mention_is_absent_from_the_census_today was already red: the mention reaches the census. I ran a stage probe on the row's own two-module fixtures through module_roots_from_source_root_ingest. It was scratch, committed temporarily and then deleted in this branch. The probe showed:

  • The parse holds the token.
  • The normalized tree holds the whole qualified spine.
  • collect_reference_sites emits exactly one site with that spelling, the same as the qualified parameter-type control.

A single-module inline fixture (qa.qb.FieldQ) agreed: spine present, one site, no bare or segment sites. Nothing is lost at parse, lowering or the census. The row's note ("record declaration not grafted") was stale. git log -S locates the likely flip at gunbc#12033 (10e01b1169), which lowers record fields into declared field identities, reading the field type with the same body_lower_type_expr_lowered_optional that parameter types use. I did not re-run the claim at #12033's parent, so that attribution of the flip is likely, not measured.

Restatement. The row becomes the conserved control a_qualified_field_type_mention_reaches_the_census_holds, with LocalParam as its positive control.

Carrier (on this branch at the parent's direction, so the rename and the carrier move land together and the witness never breaks):

Inherited red, flagged and not fixed: v2.test.claim.declaring_identity_spelling.production_ingest a_kernel_type_position_name_reaches_the_census_holds FAILs on main 14d58480c9 too. I haven't attributed it, and nothing indicates a shared cause with this row (this row's route is fully green).

Evidence (claim_batch, exact heads, 30 GB BuildBuddy runner)

  • occurrence_role_test: 10/10 PASS.
  • reference_conservation_test: 20/20 PASS. This includes the restated clean control, which failed on the first run before it was restated.
  • compiler_frontend_program_status_witness_test: 46/46 PASS on ec595eb88df.
  • production_ingest: the new reach claim, the parameter-type row and the bare-field row all PASS.
  • v1_src_dag_parse: 7024 files parse-clean.

Land only via the merge queue.

🤖 Generated with Claude Code

gunbc-ci-auto-heal and others added 6 commits September 29, 2026 02:32
…and service io/operation binders through body lowering's own readers

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…lified field type attribution

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nders

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…a conserved control (it reaches the census on main)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…restated reach claim; partition re-derived to 12/7

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tion to 16 delivered / 7 outstanding

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
briansrls previously approved these changes Sep 29, 2026

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

APPROVE-MERGE at exact head 3c10eb9, through the merge queue only.

The occurrence-role change has one authority rather than a census-only reconstruction: body lowering's parameter, field, generic, let, function-value and IO readers now retain the authored binder atom, and the existing Symbol/Edge lowering outputs are projections of those same records. occurrence_role consumes those readers directly with the appropriate declaration category. The operation row reuses the existing kw-then-ident reader. transport remains NameRoleNotYetRead deliberately and loudly because it is a closed-vocabulary selector with no honest current OccurrenceCategory; the PR does not misclassify it to close the count.

The census receipt is coherent with a reader-only refactor: role_not_yet_read falls from 1849 to the six transport sites, locus_erased moves into role_excluded by the same population, role_reader_refused stays zero, and the lowering-sensitive conserved/dropped/refused/authored totals are unchanged. The binder fixture exercises every newly read production and requires neither unread nor refused rows.

QualifiedFieldTypeVisibility is bounded correctly to reach grain. The positive claim is measured on main; the historical attribution to #12033 is explicitly labelled likely rather than measured at its parent, and binding remains outside the claim. The merge update re-derives the combined carrier partition rather than preserving a stale count.

Current exact-head witnesses run 36551120197 completed successfully, and there are no unresolved review threads. No local tests or census were run by me. Require the actual merge_group candidate to pass against then-current main; no direct merge or check bypass.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

HOLD / REQUEST_CHANGES at exact head 3c10eb9. This supersedes my earlier approval on this SHA; source inspection found one fail-open role-reader boundary that the all-valid fixture and corpus counts do not discriminate.

[P2] ReadParamListBinders can report a partial binder list as a complete successful read. body_lower_param_list_binder_atoms returns Present(list_map(body_lower_collect_typed_params(...))) whenever the comma spine itself is readable. But body_lower_collect_typed_params and its repeat-tail helper treat body_lower_typed_param_optional(...) == Absent as Empty and continue to later parameters. occurrence_role then feeds that Present through many_names as NamesFound, so the unreadable parameter contributes neither a binder role nor NameReadRefused.

That contradicts this PR's stated carrier: “every binder of the production, or a refusal where the lowering reader refuses the list.” It can also make the reference-conservation report look cleaner than the observation: an omitted binder has no role-index entry and may remain classified through the fallback population while role_reader_refused stays zero. The measured 1849 -> 6 census does not close this case; it had no discriminating mixed readable/unreadable param-list specimen.

Please make the occurrence-role view all-or-nothing at param-list grain. This does not require changing lowering's existing projection if that is intentionally permissive: a strict sibling reader can preserve the same per-param authority while returning Absent/Refused when any comma-list item does not yield BodyLowerTypedParam. Add a supplied parseable param list with at least one readable binder and one binder whose typed-param read is Absent; the role result must count a reader refusal for param_list, not NamesFound for the readable prefix. A mutation restoring skip-and-continue should red that control.

The rest of the review remains positive. The field, generic and IO list readers are explicitly all-or-nothing; let/function-value/operation readers have honest carriers; transport stays loudly unread rather than being misclassified. QualifiedFieldTypeVisibility is bounded to reach grain, and the current carrier witness correctly integrates #12584 as 23 arms / 16 delivered / 7 outstanding rather than retaining a stale partition. Exact-head workflow 36551120197 is green, but green execution of all-valid fixtures cannot prove this malformed/unsupported-member boundary.

No local tests were run by me. Return with the bounded strict-reader control and a new exact head; then require the merge_group candidate to pass against then-current main.

@briansrls
briansrls dismissed their stale review September 29, 2026 15:53

Superseded by exact-head review 5355095582 after finding the partial param-list role read can be reported as complete NamesFound.

gunbc-ci-auto-heal and others added 4 commits September 29, 2026 20:01
…hole (review 5355095582)

The param-list collector now walks one Optional per slot; lowering keeps its readable-parameter
view unchanged and the binder view occurrence_role reads is all-or-nothing. Control: a parsed list
with one planted-unreadable binder must count one param_list reader refusal and record no binder.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…call, not on the tree

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…a atom still reads as a branded binder)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 29, 2026

Copy link
Copy Markdown
Contributor Author

Addressed review 5355095582 (fail-open param-list binder read) at 8d8582c.

  • The param-list walk now yields one Optional<BodyLowerTypedParam> per slot and drops nothing (body_lower_collect_typed_param_slots). Lowering keeps its readable-parameter view unchanged (body_lower_collect_typed_params filters the slots). The binder view occurrence_role reads is all-or-nothing (body_lower_collect_typed_params_all_optional -> body_lower_param_list_binder_atoms), so any unreadable slot makes the whole list NameReadRefused, counted at param_list.
  • The other list readers already had this property: field blocks (body_lower_field_decls_optional), generic params (body_lower_generic_param_binders), io blocks, and the function-value binders (fv_comma_list_binders_optional / fv_repeat_binders_optional).
  • New discriminating control: a_param_list_with_one_unreadable_binder_refuses_whole_holds. It parses fn rc_mixed(a: Int, zz_plant: Int), plants the second binder as the bare dag_token_ident identity (which the binder reader refuses), and requires one param_list reader refusal and no recorded binder. There is a positive control on the same parse, unplanted. Executed with claim_batch: on the old head 3c10eb9 plus only the control, it FAILS and the positive control PASSES; at 8d8582c, 12/12 occurrence_role claims PASS. A first plant attempt using a comma atom did not discriminate, because the branded-binder reader accepts any non-dag_token_ident atom. That is why the plant is the bare token class.
  • lowering_accessor_collapses_a_sequence_operand is NOT closed here. body_lower_param_binding_atom_optional is still Optional, and making it Outcome-valued is bright-boar-848's claimed follow-up. The slot walk makes that change local: the slot type becomes Outcome.

— sent from keen-fox-715

…nrolled nullary values), not per claim

The floor judged both new claims over the new-witness eval-step budget (175k/169k vs 72.3k): each
re-parsed its fixture. The walks are now nullary values enrolled in floor_pure_producer_share, as
roles_fixture_outcome and binders_fixture_outcome already are.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

APPROVE-MERGE at exact head 0c80650, through the merge queue only.

Re-review against my CHANGES_REQUESTED review 5355095582: the fail-open param-list role read is fixed.

The implementation now has one slot-preserving parameter walk. body_lower_collect_typed_param_slots and its repeat-tail helper produce one Optional<BodyLowerTypedParam> for each authored slot, including Absent for an unreadable one. Lowering's existing permissive behavior remains a separate view: body_lower_collect_typed_params filters absent slots and keeps the readable parameters. The occurrence-role view is now strict: body_lower_collect_typed_params_all_optional turns any absent slot into whole-list Absent; body_lower_param_list_binder_atoms uses that strict view; and occurrence_role maps the result through many_names, so the list becomes NameReadRefused rather than NamesFound over a readable prefix. This closes the exact boundary from review 5355095582 without changing lowering's projection.

The new control discriminates that behavior rather than merely adding another valid fixture. It parses fn rc_mixed(a: Int, zz_plant: Int), verifies the unmodified parse records both parameters with no refusal, then rewrites only zz_plant to the bare dag_token_ident identity, which the binder reader cannot read. The planted arm requires zero lexical-value binder roles from that param list and exactly one dag_surface_param_list reader refusal. Restoring the old skip-and-continue behavior would report the readable a and no refusal, so the control reds the held implementation.

The rest of the prior review remains positive: field-block, generic-parameter, IO and function-value list readers are already all-or-nothing; transport remains loudly unread; QualifiedFieldTypeVisibility is still bounded to reach grain; and the carrier remains 16 delivered / 7 outstanding. The separate lowering_accessor_collapses_a_sequence_operand trigger remains open because the binder-chain carrier is still Optional; this PR does not claim that follow-up.

At review time the exact-head witnesses, floor, and generated checks are successful. emit-build and rust-unit-tests are still in progress and are not treated here as completed evidence. There are no unresolved review threads. No local tests or census were run by me.

This supersedes review 5355095582. Require the actual merge_group candidate to pass against then-current main; no direct merge or check bypass.

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