Skip to content

Declare the two bare type references in gunbc.spark.serving_execution_schedule, and enroll the closure pair that can see them - #10022

Merged
gunbai-bot[bot] merged 5 commits into
mainfrom
session/clever-ibex-130
Sep 2, 2026
Merged

gunbai-bot[bot] merged 5 commits into
mainfrom
session/clever-ibex-130

Conversation

@briansrls

@briansrls briansrls commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

gunbc.spark.serving_execution_schedule named SparkServingObservationProvenance (declared in gunbc.spark.serving_observation_transaction) and HostIdentity (declared in product.placement_supply) at field and parameter positions while naming neither in any import. A bare type position resolves against the whole module pool by global uniqueness rather than by import binding, so the full-corpus compile was green; under any narrower source closure the compiler answers unresolved type, pointing at the using module — which reads like a corpus bug and is not one.

What lands

  • Two declared imports in gunbc.spark.serving_execution_schedule. No resolution rule is widened or weakened.
  • test.claim.spark.spark_serving_schedule_closure_resolution_witness_test — the pair that can actually see the defect, because the import line alone is invisible to every check here (green before, green after):
    • subject: a synthetic single-import module over gunbc.fleet_converge_plan, whose closure contains the repaired module, through compile_dag_rust_emit_check.
    • positive control: the same shape over gunbc.spark.serving_realization, which compiled before the repair as well as after.
    • The RED is authorable: deleting either import line turns the subject red and leaves the control green.

The witness executes in CI's floor run; I have no local gunbc binary and did not run it in this session — the floor result on this PR is the execution receipt, not a claim made here.

The class is corpus-grain, and this PR does NOT remedy it

Census of bare type references that are neither declared locally nor named in any import, over the denominator of 4,459 .dag modules under dag/** and src/v2/**:

  • 789 modules carry at least one
  • 2,190 (module, name) pairs

By tree: v2 1,732 · test 1,231 · gunbc 414 · extdeps 137 · std 32 · product 4 · tools 1 (pair counts, pre-refinement pass). The largest single name is LiveTreeDisposition (427 modules writing data live_tree_disposition: LiveTreeDisposition = … with no import of v2.std.live_tree).

The compiler already models this class: src/v1/04_resolve.dag emits UnlistedImportUse as an advisory, non-erroring diagnostic against source_visible_names, and its own annotation names the burndown of genuine unlisted uses to zero as the trigger that promotes it to a hard UnresolvedType — i.e. the corpus-grain remedy already has a declared home and a declared dissolution trigger. Scoping that burndown is not this PR.

Second commit: the sizing is recorded where the flip happens

Parent's ruling: stop at this PR, no burndown lane tonight (CI capacity — 789 modules of import edits at a ~40min median witnesses run with no merge queue starves every other lane). But the sizing had to be recorded against the existing dissolution rather than left in an inbox, and this PR is the only one on the board whose subject is this class.

gunbc.compile_clean_diagnostic_policy now carries unlisted_import_use_burndown_sizing, a typed observation beside compile_clean_unlisted_import_use_enforcement_dissolve_on:

  • the numbers travel bound to their producer (SizedByStandInExtractor, this session's one-pass static extractor), to how far it was checked (10 hand-drawn rows, 1 false positive found and corrected), and to how they may be read (LowerBoundOnOrder, not a count) — DESIGN §6, name the instrument rather than transcribe its output.
  • it names the authority that supersedes it: cli_run::compile_clean::compile_clean_unlisted_import_census computes the same census tree-wide with the UnlistedImportBindingSource attribution the extractor cannot produce — and has never been invoked. Its entry point was deleted, as one member of the 25-file unrostered-seed-probe sweep in Delete unrostered seed probes and orphan tests #9160, recorded as a Delete in gunbc.live_deploy.srv1_residue_rehearsal. So the burndown has never once been measured by its own authority.
  • the annotation states what the next reader should do: restore reachability from an entry point that already earns its keep, not author a new bin — a new bin recreates exactly the unrostered property that got the old one swept, and unlisted_import_use_census_hand_rust_dissolve_trigger is already a standing retirement obligation on that transport.

Roughly one module in six resolves a type name it never imports, so this burndown is a prerequisite for any closure-computing tooling, not hygiene.

Third commit: the class witness, and the sizing arm sharpened

The narrowed module-grain subject went GREEN on the floor (both claims standing=planned-and-passed). The floor job is still red, for one BUDGET-REFUSED claim going undecided — test.claim.compiler_frontend_program_status_witness.a_live_milestone_row_agrees_with_its_own_folds, INTERRUPTED-BEFORE-VERDICT, unexpected_failures=0 failed=0 passed=3403. Not this diff; required-witnesses-floor is red on main's last four runs, and rust-unit-tests is red on main at this merge base with the identical single test (compiler_tests::shell_service_unmodeled_output_key_refuses, 644 passed / 1 failed both sides).

Added test.claim.undeclared_bare_type_reference_class_witness, which witnesses the class rather than one module's repair, and which no corpus closure can hold hostage. tools.multi_module_compile_fixture compiles a caller-authored manifest with no module index and no corpus roots:

  • RED: a definer module and a user module naming the definer's type at a field position with no import edge → asserts UnresolvedType with a blocking row.
  • Control: the same bytes plus one import line → must complete with zero diagnostics.
  • The definer is present in both manifests deliberately: without it the red is satisfied by a misspelled name, which is a different and already-walled class.

read_as on the sizing observation is now OrderOnlyBothDirections, not LowerBoundOnOrder. The extractor over-reports (measured: an isolated closure containing extdeps.uri, which it flags, compiled clean) and under-reports (positions its filter does not scan; no binding-source attribution). Neither direction is bounded.

Not paid: no regen first_generation_equal receipt — there is no local gunbc binary here and the doc/mirror regen is a local-only whole-tree job. The diff touches five .dag files and no generated-artifact path; that is an argument, not a receipt, and is labelled as one.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BjBjo69owLCe6RWESLtQQf

…_schedule, and enroll the closure pair that can see them

gunbc.spark.serving_execution_schedule named SparkServingObservationProvenance
(declared in gunbc.spark.serving_observation_transaction) and HostIdentity
(declared in product.placement_supply) at field and parameter positions while
naming neither in any import. A bare type position resolves against the whole
module pool by global uniqueness rather than by import binding, so the
full-corpus compile was green; under any narrower source closure the compiler
answered `unresolved type` pointing at the using module, which reads like a
corpus bug and is not one.

The import lines alone are invisible to every check here -- green before, green
after -- so the repair lands with the evidence that can distinguish the two
states. test.claim.spark.spark_serving_schedule_closure_resolution_witness_test
compiles a synthetic single-import module over gunbc.fleet_converge_plan (whose
closure contains the repaired module) and, as a positive control, the same shape
over gunbc.spark.serving_realization, which compiled before the repair as well.
Deleting either import line turns the subject red and leaves the control green.

The class is corpus-grain and is NOT remedied here: a census of bare type
references neither declared locally nor named in any import, over the 4,459 .dag
modules under dag/ and src/v2/, finds the same shape in 789 modules (2,190
module/name pairs). That measurement is reported separately; this change claims
only its own two modules.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjBjo69owLCe6RWESLtQQf
@gunbai-bot gunbai-bot Bot changed the title Declare the SparkServingObservationProvenance import in gunbc.spark.serving_execution_schedule: the module resolves it by global uniqueness, so every closure-based tool fails on it Declare the two bare type references in gunbc.spark.serving_execution_schedule, and enroll the closure pair that can see them Sep 2, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review September 2, 2026 07:42
Brian Searls and others added 4 commits September 2, 2026 07:54
…at consumes it, and name the authority census whose entry point was deleted

compile_clean_unlisted_import_use_enforcement flips to Enforced on two
conditions, and the second -- the corpus burndown of genuine unlisted uses
reaching zero -- had no size attached to it anywhere. An unmeasured trigger
cannot be scheduled, so the size lands at the one place the flip happens.

It is recorded as a typed sizing OBSERVATION, not as a corpus fact: the numbers
travel bound to their producer (a static extractor written for one pass by this
session), to how far it was checked (ten hand-drawn rows, one false positive
found and corrected), and to how they may be read (LowerBoundOnOrder, not a
count) -- DESIGN section 6, name the instrument rather than transcribe output.

The row also carries the fact that makes it self-retiring. The authority
instrument, cli_run::compile_clean::compile_clean_unlisted_import_census, has
binding-source attribution the extractor cannot produce and has never been
invoked: its entry point was DELETED as one member of the 25-file unrostered
seed-probe sweep in gunbc#9160, recorded as a Delete in
gunbc.live_deploy.srv1_residue_rehearsal. Restoring reachability from an entry
point that already earns its keep is the first task; a new bin would recreate
the unrostered property that got the old one swept, and
unlisted_import_use_census_hand_rust_dissolve_trigger is already a standing
retirement obligation on that hand-Rust transport.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjBjo69owLCe6RWESLtQQf
…_plan one measured red, and it was asserting the whole burndown

The first subject imported gunbc.fleet_converge_plan, which reaches the repaired
module -- but through a 733-module closure, and the static census finds 30 of
those modules carrying an instance of this same class. The floor run measured it
RED with the positive control GREEN, so the harness was working and the refusal
was real: a closure that wide cannot be made to compile by repairing one module,
and a subject that asserts it does is asserting the whole burndown, which is
explicitly not this PR's scope.

The subject is now a synthetic single-import module over
gunbc.spark.serving_execution_schedule itself -- the smallest closure that
contains the repaired module (194 modules). The control is unchanged. The
measurement that forced the narrowing is recorded in the annotation, because it
cost a floor run to learn and it is the reason not to widen the subject back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjBjo69owLCe6RWESLtQQf
…ing observation to say the extractor errs in BOTH directions

The narrowed module-grain subject went GREEN on the floor (both claims
planned-and-passed), so the repair now has executed evidence at its own grain.
But that subject can only ever witness ONE module's repair, and the class it
belongs to is corpus-wide: a bare type position resolves by global uniqueness,
so a module may name a type it never imports and a whole-corpus compile stays
green while every narrower closure refuses.

test.claim.undeclared_bare_type_reference_class_witness witnesses the CLASS at a
grain no corpus closure can hold hostage. tools.multi_module_compile_fixture
compiles a caller-authored manifest with no module index and no corpus roots, so
the subject is two authored modules: a definer, and a user naming the definer's
type at a field position with no import edge. The RED asserts UnresolvedType with
a blocking row; the positive control is the SAME bytes plus one import line and
must compile with zero diagnostics. The definer is present in both manifests on
purpose -- without that the red is satisfied by a misspelled name, which is a
different and already-walled class.

The sizing observation's read_as arm is renamed to OrderOnlyBothDirections. The
extractor over-reports -- measured, not assumed: a floor run compiled an isolated
closure containing extdeps.uri, which the extractor flags -- and it also
under-reports, since it cannot see a position its filter does not scan and cannot
attribute a binding source at all. Neither direction is bounded, so
LowerBoundOnOrder was claiming more than the instrument supports.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjBjo69owLCe6RWESLtQQf
… is the broken-harness signature: the fixture imported std.types, and the isolated manifest has no such module

Both arms of test.claim.undeclared_bare_type_reference_class_witness returned
false in under 4ms. Control-red-with-subject-red says the harness broke, not that
the class is real, so the control is read first and the subject's red is worth
nothing until it is green.

THE CAUSE. tools.multi_module_compile_fixture compiles the supplied manifest with
NO module index and no corpus roots -- that isolation is the whole reason to use
it. Both fixture modules opened with `import std.types { Int }`, which names a
module that is not in the subject, so the compile refused before reaching
anything about import edges. Int needs no import: it is in kernel_type_set and
every module sees it. The import lines are gone and the annotation records why
their absence is load-bearing rather than terse.

THE CLAIM IS ALSO WEAKENED TO WHAT WAS ACTUALLY OBSERVED. The red arm asserted
UnresolvedType with a blocking row. Two arms are live and they are different
facts: the definer IS supplied, so the manifest pool may resolve the name by the
very global-uniqueness rule under test and answer with the advisory
UnlistedImportUse instead of refusing. Naming one without having seen which fires
is a diagnostic name asserted over a silent mechanism. The subject now asserts
that the compiler produced SOME diagnostic and the control that it produced NONE
-- still discriminating over the same bytes plus one import line -- and the
next-rung trigger is to read the class off this claim's own floor run and pin it.

The two spark closure claims passed again on the previous head, unchanged here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjBjo69owLCe6RWESLtQQf
@gunbai-bot
gunbai-bot Bot merged commit baf6a7c into main Sep 2, 2026
8 of 12 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/clever-ibex-130 branch September 2, 2026 11:02
@briansrls
briansrls restored the session/clever-ibex-130 branch September 2, 2026 11:11
@gunbai-bot
gunbai-bot Bot deleted the session/clever-ibex-130 branch September 2, 2026 12:58
@briansrls
briansrls restored the session/clever-ibex-130 branch September 2, 2026 13:40
@gunbai-bot
gunbai-bot Bot deleted the session/clever-ibex-130 branch September 2, 2026 13:43
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