diff --git a/dag/extdeps/systemd/systemd.dag b/dag/extdeps/systemd/systemd.dag index 3a6ad970174..d7e5598a064 100644 --- a/dag/extdeps/systemd/systemd.dag +++ b/dag/extdeps/systemd/systemd.dag @@ -68,7 +68,6 @@ type SystemdUnitProperty | SubState | Result | ExecMainStatus - | SubState | ExecStartProperty | User | WorkingDirectoryProperty @@ -108,7 +107,6 @@ fn systemd_unit_property_wire(property: SystemdUnitProperty) -> NonEmptyStr { SubState => "SubState" as NonEmptyStr Result => "Result" as NonEmptyStr ExecMainStatus => "ExecMainStatus" as NonEmptyStr - SubState => "SubState" as NonEmptyStr ExecStartProperty => "ExecStart" as NonEmptyStr User => "User" as NonEmptyStr WorkingDirectoryProperty => "WorkingDirectory" as NonEmptyStr diff --git a/dag/gunbc/compiler_frontend_program_status.dag b/dag/gunbc/compiler_frontend_program_status.dag index 37bff2b62b5..c8d77f404a5 100644 --- a/dag/gunbc/compiler_frontend_program_status.dag +++ b/dag/gunbc/compiler_frontend_program_status.dag @@ -180,8 +180,8 @@ type MissingInstrument fn missing_instrument_label(i: MissingInstrument) -> String { match i { PhaseCargoExecutionFact => "a per-phase cargo-execution fact on gunbc.required_ci_phase_roster" - DeclaringIdentitySpellingCensus => "a census of occurrences not spelled at their declaring identity (XL-3's population)" - RepairInputOriginRosterProducer => "a repair-input origin roster producer: source-declaration carriers plus rendered target-vocabulary carriers, separately typed, over one base, before eligibility or repair disposition (XL-0's population)" + DeclaringIdentitySpellingCensus => "a declaring-identity spelling census that answers over XL-3's usable population on the production ingest route: QUALIFIED cross-module mentions (every position) and bare type names in FIELD position, joined to their declaring identity - the producer v2.compiler.declaring_identity_spelling_census spelling_census_from_ingest exists and answers over the bare same-module classes only, which is not that population (XL-3's population)" + RepairInputOriginRosterProducer => "a repair-input origin roster producer that yields a NON-EMPTY denominator over the tree the production ingest actually yields: source-declaration carriers plus rendered target-vocabulary carriers, separately typed, over one base, before eligibility or repair disposition (XL-0's population)" ExactOccurrenceResidualCensus => "the exact occurrence and import-declaration residual an XL-2 rehearsal produces (XL-5's population)" PersistedBehavioralReceipt => "a persisted behavioral receipt over a discriminating corpus" PersistedPromotionOutcome => "a persisted PromotionOutcome over a named candidate" @@ -404,7 +404,8 @@ fn stage_subject_outstanding(stage: NamespaceCutStage) -> List { // named, observed piece of outstanding work, and reporting it unanswerable hid real known // work behind the missing-instrument label. The AVAILABLE arm reads the persist outstanding // fold: v2.workflow.legacy_baseline_persisted_observation holds a capture by its own -// GitObjectId, never a receipts roster, and the live pin is unpinned until ACT-0 names a base. +// GitObjectId, never a receipts roster. Production pin stays PreCutBaseUnpinned until ACT-0 +// names B; the AVAILABLE arm is outstanding until then. That is not ACT-0's BaselineCaptureReceipt. // THE THREE DELETION MILESTONES, DERIVED FROM THE SUBJECT ROSTER SINCE F-0 -- at DECLARED-ROW // grain, stated at exactly that strength. gunbc.namespace_cut_subject_roster carries every // authority scheduled to disappear as string-identity probes (not authored citations, which @@ -902,7 +903,7 @@ fn stage_status(s: NamespaceCutStage) -> MilestoneStanding { ) StageXL0Denominator => NotDerivable { - why: "XL-0 is the REPAIR-INPUT ORIGIN DENOMINATOR -- source-declaration carriers plus rendered target-vocabulary carriers, separately typed, over one base, before eligibility or repair disposition. XL-0A splits and tags the six producer channels before their compatibility projection, but it deliberately does not claim the source declaration continuity or subject-bound roster that XL-0B-D owe. The arm that used to stand here read gunbc.namespace_cut_subject_roster's unobservable host probes instead, which answered a different question entirely: the subject roster is the cut's ROOT-AUTHORITY denominator, one row per family, and probe observability is a property of the instrument rather than a measure of the denominator's completeness. Deriving XL-0 from it let a join repair read as the denominator being produced. Derivable once the repair-input origin roster producer is complete." as NonEmptyStr, + why: "XL-0 is the REPAIR-INPUT ORIGIN DENOMINATOR, and the producer built for it does not yet answer over the tree production yields. THIS ARM BRIEFLY READ CLEAR OFF A DELIVERY RECEIPT AND THAT WAS WRONG: the receipt was earned against HAND-BUILT Node trees, while a substrate-only fixture driving the real ingest -- v2.compiler.program_assembly module_roots_from_source_root_ingest, projected through v2.compiler.normalized_tree normalized_tree_roots_to_nodes -- showed the collector returning NO sites at all for a module that plainly contains them. Independently reproduced by the XL-4 lane over real .dag files. A stage that reads CLEAR off a green-on-fixtures, empty-on-corpus instrument is reporting a denominator that does not exist, which is DESIGN section 5 silent wrongness rather than an incomplete measurement, so the honest standing is NOT DERIVABLE and the instrument stays outstanding. Re-run rather than trust this sentence: v2.test.claim.namespace_xl0.call_argument_mention_survival. THE MISS IS NOT ONE FACT AND ITS TRIGGER IS NOT ONE TRIGGER. Measured over every ingested root, a bare same-module value reference, a parameter reference and a bare type name in PARAMETER position all reach the producer; a QUALIFIED CROSS-MODULE reference, a call argument, a callee name and a bare type name in FIELD position do not. WRITING THAT AS \"a type-position name\" WOULD BE TOO COARSE AND AN EARLIER REVISION OF THIS ARM WROTE IT THAT WAY: the same bare spelling reaches from a parameter and does not reach from a field, so a trigger written against the merged class retires while half of it stays dead. The cross-module row is why there is no denominator, because an import-to-containment denominator is made of references that cross a module boundary and the surviving population is the part XL-0 cannot use. Two causes were mine and are fixed -- a parse-projection exclusion that blacked out the corpus, and a census that folded the roots while discarding its accumulator and so measured only the last one, which manufactured a reported type-position miss that does not exist. The third is open and deliberately unattributed: a dotted reference in a BODY is not a qualified-name production at all, so the collector never reassembles it, and whether resolution itself reads dotted body access is UNANSWERED because the probe built for it fails its own control. A FOURTH is open and also unattributed, and it is not a dotted case because the spelling that misses carries no dot: the bare FIELD-position miss, reproduced on two routes, where the whole record declaration is findable in the ingested tree as neither an atom nor a named edge while a parameter-type control is present. Cause unestablished on purpose -- if the declaration is absent from the tree then no collector-side trigger could ever fire. Producer: v2.test.claim.namespace_xl0.field_type_tree_presence. So the body-lowering repair (XL-2, gunbc#11207) is NOT this stage's trigger: it restores the call classes and leaves the cross-module class missing, and a trigger naming less than the capability it restores is retired while the capability stays dead (DESIGN section 4b(3)). Derivable once the producer answers non-empty over CROSS-MODULE references on the production route. THE CAPABILITY THIS STAGE WAITS ON IS UNOWNED, AND THAT IS STATED HERE RATHER THAN LEFT TO BE INFERRED FROM THE ABSENCE OF A LANE: the call classes have an owner (XL-2, gunbc#11207) and the cross-module dotted-reference capability -- the only one XL-0 actually needs -- has none. DESIGN section 4b(2) admits a stall only when it is declared, and separates cannot-climb from can-climb-after-one-grounding from can-climb-now-but-unbuilt; this is the THIRD, so the honest reading is not that XL-0 is blocked by physics but that nobody is assigned to it. A stage whose trigger points at unowned work will sit here indefinitely while every carrier around it reads as though progress were scheduled." as NonEmptyStr, cause: needs(i: RepairInputOriginRosterProducer) } StageXL1BaselineCapture => @@ -921,7 +922,7 @@ fn stage_status(s: NamespaceCutStage) -> MilestoneStanding { ) StageXL3DeclaringIdentitySpelling => NotDerivable { - why: "no carrier censuses occurrences not yet spelled at their declaring identity. The wave wall's binding channel keys on leaf segments, deliberately invariant under requalification, so it cannot answer this either. Derivable once the spelling census exists." as NonEmptyStr, + why: "the spelling census producer exists (v2.compiler.declaring_identity_spelling_census spelling_census_from_ingest) over the production ingest route. Frontiers are separate capabilities: BARE value outside a call, parameter reference, and BARE type name in PARAMETER position reach; BARE type name in FIELD position does not (not a qualification fact -- measured by v2.test.claim.declaring_identity_spelling.production_ingest field_vs_parameter); names inside calls are missing (body-lowering, eager-raven / #11207); QUALIFIED/dotted references are missing in every position (dotted-reference gap, not lowering). A qualified field type is absent for both independent reasons and cannot discriminate. kernel Int has no corpus declaration. IdentityUnbound on a same-module ingest census row is an index-path probe, not a compiler fact -- enrolled control v2.test.claim.provenance.cross_file_provenance cfp_own_module_site binds on resolve_reference_provenance. Derivable once the producer answers over qualified mentions; restoring dotted will not restore bare field types. The producer landed with #11201 in gunbc#11461; what remains UNBUILT is the capability the instrument label names, not the producer file." as NonEmptyStr, cause: needs(i: DeclaringIdentitySpellingCensus) } StageXL4ReferenceDerivedGraph => diff --git a/dag/gunbc/instruments/reference_derived_graph.dag b/dag/gunbc/instruments/reference_derived_graph.dag new file mode 100644 index 00000000000..25eb60653c1 --- /dev/null +++ b/dag/gunbc/instruments/reference_derived_graph.dag @@ -0,0 +1,200 @@ +module tools.reference_derived_graph + +import std.process { ExitSuccess, ProcessExit, exit_failure } +import std.types { Bool, List, String } +import extdeps.filesystem.filesystem_io +import v2.std.algebra { any, fold_list } +import v2.std.diagnostic { Accepted, Outcome, Rejected } +import v2.lens.module_graph { + ImportResolutionFact, + ModuleDependencyEdge, + dependency_edges_from_import_facts, + import_resolution_facts_live, + reference_derived_resolution_facts, +} + +// XL-4 instrument: the reference-derived graph (swap body of v2.lens.module_graph) and its +// typed difference against the import-derived graph, over a named source root. +// +// gunbc run --source-root dag --source-root src/v2 \ +// --entry dag/gunbc/instruments/reference_derived_graph.dag --function main +// +// Discriminating run is the fixture root below. Qualified mentions are a declared frontier +// triggered on the dotted-reference capability, not lowering. Call contents are +// eager-raven-113. Bare field types have a tree-side census with UNVERIFIED cause. Collector-only. +// Unused-import-must-not-mint-a-reference-edge still is. It does not swap +// dependency_resolution_facts_live (NAMESPACE-XL STAGE XL-6). + +data instrument_source_roots: List = ["dag/test/fixture/reference_derived_graph"] + +data instrument_exclude: List = [] + +data provider_module: String = "test.fixture.reference_derived_graph.provider" + +data consumer_reference_only_path: String = "dag/test/fixture/reference_derived_graph/consumer_reference_only.dag" + +data consumer_import_only_path: String = "dag/test/fixture/reference_derived_graph/consumer_import_only.dag" + +type ReferenceImportEdgeDiff + = SharedEdge { path: String, target_module: String } + | ReferenceOnlyEdge { path: String, target_module: String } + | ImportOnlyEdge { path: String, target_module: String } + +type ReferenceDerivedGraphReport { + source_roots: List + reference_edges: List + import_edges: List + diffs: List +} + +fn has_identity(edges: List, path: String, target_module: String) -> Bool { + any(xs: edges, predicate: fn(e) { e.path == path && e.target_module == target_module }) +} + +fn diff_against_import( + reference_edges: List, + import_edges: List +) -> List { + let from_reference = fold_list( + xs: reference_edges, + empty: [], + cons: fn(acc, edge) { + concat(acc, [ + if has_identity(edges: import_edges, path: edge.path, target_module: edge.target_module) { + SharedEdge { path: edge.path, target_module: edge.target_module } + } else { + ReferenceOnlyEdge { path: edge.path, target_module: edge.target_module } + } + ]) + } + ) + fold_list( + xs: import_edges, + empty: from_reference, + cons: fn(acc, edge) { + if has_identity(edges: reference_edges, path: edge.path, target_module: edge.target_module) { + acc + } else { + concat(acc, [ImportOnlyEdge { path: edge.path, target_module: edge.target_module }]) + } + } + ) +} + +fn report(source_roots: List) -> Outcome { + match reference_derived_resolution_facts( + pool_roots: source_roots, + importer_roots: source_roots, + exclude_substrings: instrument_exclude + ) { + Rejected { diagnostics: d } => Rejected { diagnostics: d } + Accepted { value: reference_edges, diagnostics: pending } => { + let import_edges = dependency_edges_from_import_facts( + edges: import_resolution_facts_live( + pool_roots: source_roots, + importer_roots: source_roots, + exclude_substrings: instrument_exclude + ) + ) + Accepted { + value: ReferenceDerivedGraphReport { + source_roots: source_roots, + reference_edges: reference_edges, + import_edges: import_edges, + diffs: diff_against_import( + reference_edges: reference_edges, + import_edges: import_edges + ) + }, + diagnostics: pending + } + } + } +} + +fn fixture_report() -> Outcome { + report(source_roots: instrument_source_roots) +} + +fn diffs_include_reference_only(diffs: List, path: String, target: String) -> Bool { + any(xs: diffs, predicate: fn(d) { + match d { + ReferenceOnlyEdge { path: p, target_module: t } => p == path && t == target + SharedEdge { path: _, target_module: _ } => false + ImportOnlyEdge { path: _, target_module: _ } => false + } + }) +} + +fn diffs_include_import_only(diffs: List, path: String, target: String) -> Bool { + any(xs: diffs, predicate: fn(d) { + match d { + ImportOnlyEdge { path: p, target_module: t } => p == path && t == target + SharedEdge { path: _, target_module: _ } => false + ReferenceOnlyEdge { path: _, target_module: _ } => false + } + }) +} + +fn diffs_include_shared(diffs: List, path: String, target: String) -> Bool { + any(xs: diffs, predicate: fn(d) { + match d { + SharedEdge { path: p, target_module: t } => p == path && t == target + ReferenceOnlyEdge { path: _, target_module: _ } => false + ImportOnlyEdge { path: _, target_module: _ } => false + } + }) +} + +fn main() -> ProcessExit { + match fixture_report() { + Rejected { diagnostics: _ } => + exit_failure( + reason: "tools.reference_derived_graph.report refused over the fixture source root" + ) + Accepted { value: r, diagnostics: _ } => + if !(diffs_include_reference_only( + diffs: r.diffs, + path: consumer_reference_only_path, + target: provider_module + ) || diffs_include_shared( + diffs: r.diffs, + path: consumer_reference_only_path, + target: provider_module + )) { + exit_failure( + reason: "positive control absent: the reference-only fixture produced no reference-derived edge, so every negative check below would pass on an empty edge set" + ) + } else if diffs_include_import_only( + diffs: r.diffs, + path: consumer_reference_only_path, + target: provider_module + ) { + exit_failure( + reason: "the reference-only fixture was classified as import-only, so the instrument is reading import syntax" + ) + } else if !diffs_include_import_only( + diffs: r.diffs, + path: consumer_import_only_path, + target: provider_module + ) { + exit_failure( + reason: "an import with no reference produced a reference-derived edge or dropped the import-only difference" + ) + } else if diffs_include_reference_only( + diffs: r.diffs, + path: consumer_import_only_path, + target: provider_module + ) || diffs_include_shared( + diffs: r.diffs, + path: consumer_import_only_path, + target: provider_module + ) { + exit_failure( + reason: "an unused import minted a reference-derived edge" + ) + } else { + ExitSuccess + } + } +} diff --git a/dag/gunbc/namespace/emit_rust_reference_derived_rows_bridge_seed_growth.dag b/dag/gunbc/namespace/emit_rust_reference_derived_rows_bridge_seed_growth.dag new file mode 100644 index 00000000000..99f1e71f312 --- /dev/null +++ b/dag/gunbc/namespace/emit_rust_reference_derived_rows_bridge_seed_growth.dag @@ -0,0 +1,55 @@ +module gunbc.emit_rust_reference_derived_rows_bridge_seed_growth + +import std.decl_ref { DeclarationRef, WholeDeclaration } +import std.types { String } +import gunbc.roadmap_model { RoadmapNodeId } +import gunbc.seed_growth { SeedGrowthJustification } + +data emit_rust_reference_derived_rows_bridge_seed_growth_justification: SeedGrowthJustification = SeedGrowthJustification { + hand_authored_declarations: [ + DeclarationRef { + module_path: "v1_compiler.cli_run.emit_host", + decl_name: "Xl1PrimaryRootTap", + field: WholeDeclaration + }, + DeclarationRef { + module_path: "v1_compiler.cli_run.emit_host", + decl_name: "compile_xl1_primary_root_tap", + field: WholeDeclaration + }, + DeclarationRef { + module_path: "v1_compiler.cli_run.emit_host", + decl_name: "ObservedOccurrenceBindingHalves", + field: WholeDeclaration + }, + DeclarationRef { + module_path: "v1_compiler.cli_run.emit_host", + decl_name: "observed_occurrence_transport_and_bindings", + field: WholeDeclaration + }, + DeclarationRef { + module_path: "v1_interpreter", + decl_name: "reference_derived_candidate_rows_value", + field: WholeDeclaration + }, + DeclarationRef { + module_path: "v1_interpreter", + decl_name: "reference_derived_candidate_disposition_value", + field: WholeDeclaration + }, + DeclarationRef { + module_path: "v1_interpreter", + decl_name: "occurrence_transport_value", + field: WholeDeclaration + }, + DeclarationRef { + module_path: "v1_interpreter", + decl_name: "xl1_primary_root_tap_value", + field: WholeDeclaration + } + ], + reason: "WHY A HOST BRIDGE RATHER THAN A .dag CONSUMER CALLING THE PRODUCER DIRECTLY. The rows are produced by v1.compiler.emit_rust emit_rust_reference_derived_rows over a ResolvedGraph. The required floor and every dag/src/v2 workflow resolve --source-root dag --source-root src/v2 only. Measured: no module under those roots imports a v1 module, so a consumer there cannot name that function. Adding --source-root src/v1 lets the spelling resolve; calling it from the interpreter still needs a ResolvedGraph, and compile_to_resolved over an authored source vector hits the Node.ident wall (no default for an omitted optional field).\n\nWHY PRIMARYROOT, MEASURED. gunbc run / claim_executor compile_to_resolved only the entry's reference-derived closure (resolve_entry_with_index). The one existing path that compile_to_resolved every indexed module under a root is gunbc compile without --entry (CompileSubject::PrimaryRoot). That transaction emits bytes and never called this arm. compile_dag_reference_occurrence_binding_census compiles a caller-supplied (paths, contents) vector and does not encode OccurrenceTransport (no containment, declarations, or index entries), so ValidatedOccurrenceTransport cannot mint from it. This widening keeps ONE arm and ONE encoding: PrimaryRoot(source_roots[0]) with the rest as pool, then encode repair rows AND the seed-observed OccurrenceTransport (per-module sidecars concatenated as stored; never reconstructed on the v2 side). Binding rows over that same transport travel in the same encoding. If occurrence_transport_validate cannot mint, capture refuses LegacyBaselineObservedTransportRefused rather than fabricating containment.\n\nWHY IT IS ADMITTED AGAINST THE v1 FREEZE: gunbc.v1_maintenance_standing v1_seed_standing admits by PURPOSE (fierce-lark-661, PrimaryRoot widening 2026-09-12). The v1 oracle is the differential referent for the XL-6 qualification sweep. HAND-ITEM DELTA is the identities in hand_authored_declarations: the emit_host host (Xl1PrimaryRootTap, compile_xl1_primary_root_tap) plus the ObservedOccurrenceBindingHalves extraction that compile_dag_reference_occurrence_binding_census now shares, plus the four v1_interpreter encoders. The dispatch arm is ExistingSeedItemModified inside eval_builtin_inner. v1_interpreter_dispatch_generated.rs is generated from gunbc.v1_interpreter_primitive_surface.", + owning_dissolution_lane: "v1-interpreter-delete" as RoadmapNodeId, + trigger: "Delete this arm with v1.compiler.emit_rust and the interpreter. A producer existing is not the dissolve; the arm is listed in that deletion population from the day it lands.", + current_boundary: "src/v1/stage0/src/cli_run/emit_host.rs compile_xl1_primary_root_tap (Xl1PrimaryRootTap, ObservedOccurrenceBindingHalves, observed_occurrence_transport_and_bindings); src/v1/stage0/src/v1_interpreter.rs free_call.emit_rust_reference_derived_rows_bridge arm and its encoders (repair rows, seed-observed OccurrenceTransport, binding rows over that transport); dag/gunbc/v1/v1_interpreter_primitive_surface.dag roster row; src/v1/04_method.dag builtin signature; dag/std/primitives.dag spelling roster; sole consumer v2.workflow.legacy_repair_tap persist_named_base_from_primary_root_tap" +} diff --git a/dag/gunbc/namespace/namespace_cut_stage.dag b/dag/gunbc/namespace/namespace_cut_stage.dag index 14c1a7133e5..faf3c968718 100644 --- a/dag/gunbc/namespace/namespace_cut_stage.dag +++ b/dag/gunbc/namespace/namespace_cut_stage.dag @@ -163,8 +163,86 @@ data required_stage_delivery_evidence_kinds: List = [ ReferenceGraphInstrumentDelivered, ] -// Empty by construction today: neither instrument exists. A row lands here when the stage that -// owes it delivers it. +// Empty: neither instrument is delivered. XL-4's reference-graph instrument exists, but on the +// production ingest route it emits no reference-derived edge for any fixture, so it has no accepted +// positive control there (review 64925 on gunbc#11202). A receipt discriminated only over hand-built +// roots would inflate the rung (DESIGN 4b(1)). The row lands when tools.reference_derived_graph main +// exits success on the production route, which requires its positive control. +// XL-0 OWES NO DELIVERY RECEIPT AND HAS NO DELIVERY KIND ON THIS CHANNEL. Both the receipt and the +// KIND were withdrawn; an earlier revision of this change removed the receipt and left +// DenominatorRosterInstrumentDelivered standing in the type and in the required roster with NOTHING +// READING IT. That is the attractor the withdrawal existed to kill: two answers to "is XL-0's +// instrument ready?" -- a required delivery kind no standing consults, beside the MissingInstrument +// cause StageXL0Denominator actually cites. DESIGN section 3, one fact one place. XL-0's readiness +// is the instrument question and nothing else; if it ever owes this channel, the kind comes back +// WITH the standing that reads it, in the same change. +// +// THE RECEIPT THAT STOOD HERE WAS WITHDRAWN, BY EXECUTION, BEFORE IT EVER LANDED ON MAIN. +// +// WHAT IT CLAIMED: that v2.compiler.repair_input_origin_roster had been delivered and discriminated +// once. WHAT WAS TRUE: it had been discriminated against HAND-BUILT Node trees, and on the tree the +// production route actually yields it produced an EMPTY denominator -- zero mentions for a module +// that plainly contains them. A green witness over a universe the corpus never produces is DESIGN +// section 5's specification-without-execution wearing the costume of real execution, and a stage +// reading CLEAR off it would have reported a denominator that does not exist. +// +// ESTABLISHED BY EXECUTION, not by review: a substrate-only fixture drives the real ingest +// (v2.compiler.program_assembly module_roots_from_source_root_ingest, projected through +// v2.compiler.normalized_tree normalized_tree_roots_to_nodes), and the collector returns no sites +// at all. Independently reproduced by warm-ibex-518 over real .dag files, with and without +// normalize. The producer is named here so the next reader re-runs it rather than trusting this +// sentence: v2.test.claim.namespace_xl0.call_argument_mention_survival. +// +// WHAT THE PRODUCER ACTUALLY SEES ON THE PRODUCTION ROUTE, MEASURED OVER EVERY INGESTED ROOT: +// +// REACHES IT: a bare same-module value reference outside any call; a parameter reference; +// a bare type name in PARAMETER position +// DOES NOT: a QUALIFIED CROSS-MODULE reference, with or without a call; +// a call argument; a callee name; +// a bare type name in FIELD position +// +// "A TYPE-POSITION NAME" IS TOO COARSE TO WRITE HERE, AND AN EARLIER REVISION OF THIS TABLE WROTE +// IT. The same bare spelling REACHES from a parameter and DOES NOT reach from a field, so a row +// naming "type position" without saying which one merges a class that works with a class that does +// not, and a trigger written against it would retire while half the class stayed dead. The producer +// that separates them is the same one this note names: its Xl0FieldOnly row is spelled bare and +// used in exactly one place, a field type, which isolates field position from qualification. +// +// THE FIRST ROW OF THE SECOND GROUP IS WHY XL-0 HAS NO DENOMINATOR, and it is not the same fact as +// the call erasure. An import-to-containment denominator is made of references that CROSS a module +// boundary; a bare same-module name resolves inside its own module and contributes nothing. So the +// population that survives is the part XL-0 cannot use, and a non-empty site list must not be read +// as a working instrument. +// +// THREE CAUSES HAVE BEEN SEPARATED SO FAR, AND THE TRIGGERS ARE NOT ONE TRIGGER: +// 1. MINE, FIXED: the collector's parse-projection exclusion skipped the subtree carrying a real +// module's content, which blacked out the corpus while hand-built fixtures stayed green. +// 2. MINE, FIXED: its census folded the ingested roots while discarding the accumulator, so every +// "is absent" row was measured over the LAST root alone. That one manufactured a reported miss +// in PARAMETER type position that does not exist -- the row above is the corrected measurement. +// 3. OPEN, AND NOT ATTRIBUTED: the qualified cross-module miss. A dotted reference in a BODY is +// not a dag_surface_qualified_name production at all -- it reaches the tree as a dot access +// over operand atoms -- so the collector, which recognises only the fold-list spine, never +// reassembles it. Whether resolution itself reads dotted body access is UNANSWERED: the probe +// built for it fails its own control, so no executed evidence exists either way. +// +// 4. OPEN, AND NOT ATTRIBUTED: the bare FIELD-position miss. It is a fourth class rather than a +// dotted case, because the spelling that misses carries no dot. The tree-side discriminator has +// run on two routes and agrees on the MEASUREMENT and on neither cause: the whole +// `type Wrapper { f: T }` declaration is findable in the ingested tree as neither an atom nor a +// named edge, while a parameter-type control is present. If the declaration is absent from the +// tree then no collector-side trigger could ever fire, so naming one here would be a trigger +// pointed at the wrong layer. Producer: v2.test.claim.namespace_xl0.field_type_tree_presence. +// +// THE RESTORATION TRIGGER IS THEREFORE NOT THE BODY-LOWERING REPAIR ALONE, and an earlier revision +// of this note said it was. Body lowering (XL-2, gunbc#11207) restores the call classes and NOTHING +// ELSE; the qualified cross-module class is independent of calls and would still be missing after +// it lands. A trigger naming less than the capability it restores gets retired while the capability +// stays dead, which DESIGN section 4b(3) names exactly. XL-0 derives when the producer answers +// NON-EMPTY over cross-module references on the production route -- that is the capability, and the +// call classes are a separate, smaller one. +// +// Empty by construction again, and honestly so: no stage delivery instrument exists yet. data held_stage_delivery_receipts: List = [] fn stage_delivery_outstanding(held: List) -> List { diff --git a/dag/gunbc/namespace/reference_derived_candidate.dag b/dag/gunbc/namespace/reference_derived_candidate.dag new file mode 100644 index 00000000000..bd3f3e5eb0e --- /dev/null +++ b/dag/gunbc/namespace/reference_derived_candidate.dag @@ -0,0 +1,22 @@ +module gunbc.reference_derived_candidate + +import std.types { String } + +// THE EMIT-RUST REFERENCE-DERIVED CANDIDATE, ONE HOME. v1.compiler.emit_rust produces rows of this +// shape; v2.workflow.legacy_repair_tap consumes the same types through the host bridge. Reachability +// of ResolvedGraph explains the bridge, not a second copy of the coproduct (review 64840). + +type ReferenceDerivedCandidateDisposition + = CandidateSurvived { provider_module: String } + | CandidateOwnModule + | CandidateVariantDelegatedToParent { parent_enum: String } + | CandidateVariantParentUnresolved + | CandidateRegistryAbsent + | CandidateLeafAmbiguous + | CandidateExportProofFailed { provider_module: String } + +type ReferenceDerivedCandidateRow { + module_name: String + name: String + disposition: ReferenceDerivedCandidateDisposition +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_row_for_info_candidateexportprooffailed.dag b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_row_for_info_candidateexportprooffailed.dag new file mode 100644 index 00000000000..5d3f67b43ab --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_row_for_info_candidateexportprooffailed.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_qualified_type_reference_row_for_info_candidateexportprooffailed + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateExportProofFailed binding inside +// v1.compiler.emit_rust qualified_type_reference_row_for_info now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_qualified_type_reference_row_for_info_candidateexportprooffailed: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust qualified_type_reference_row_for_info CandidateExportProofFailed: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "qualified_type_reference_row_for_info"), + spelling: "CandidateExportProofFailed" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateExportProofFailed")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_row_for_info_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_row_for_info_candidatesurvived.dag new file mode 100644 index 00000000000..dd1146db61a --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_row_for_info_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_qualified_type_reference_row_for_info_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.compiler.emit_rust qualified_type_reference_row_for_info now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_qualified_type_reference_row_for_info_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust qualified_type_reference_row_for_info CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "qualified_type_reference_row_for_info"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_row_for_info_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_row_for_info_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..21c4aa9ac92 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_row_for_info_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_qualified_type_reference_row_for_info_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.compiler.emit_rust qualified_type_reference_row_for_info now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_qualified_type_reference_row_for_info_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust qualified_type_reference_row_for_info ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "qualified_type_reference_row_for_info"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_rows_candidateleafambiguous.dag b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_rows_candidateleafambiguous.dag new file mode 100644 index 00000000000..eb589b793c1 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_rows_candidateleafambiguous.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_qualified_type_reference_rows_candidateleafambiguous + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateLeafAmbiguous binding inside +// v1.compiler.emit_rust qualified_type_reference_rows now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_qualified_type_reference_rows_candidateleafambiguous: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust qualified_type_reference_rows CandidateLeafAmbiguous: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "qualified_type_reference_rows"), + spelling: "CandidateLeafAmbiguous" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateLeafAmbiguous")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_rows_candidateregistryabsent.dag b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_rows_candidateregistryabsent.dag new file mode 100644 index 00000000000..42054c5eded --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_rows_candidateregistryabsent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_qualified_type_reference_rows_candidateregistryabsent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateRegistryAbsent binding inside +// v1.compiler.emit_rust qualified_type_reference_rows now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_qualified_type_reference_rows_candidateregistryabsent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust qualified_type_reference_rows CandidateRegistryAbsent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "qualified_type_reference_rows"), + spelling: "CandidateRegistryAbsent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateRegistryAbsent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_rows_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_rows_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..1fe35f41145 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_rows_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_qualified_type_reference_rows_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.compiler.emit_rust qualified_type_reference_rows now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_qualified_type_reference_rows_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust qualified_type_reference_rows ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "qualified_type_reference_rows"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_use_lines_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_use_lines_candidatesurvived.dag new file mode 100644 index 00000000000..266c4fa4ac2 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_use_lines_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_qualified_type_reference_use_lines_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.compiler.emit_rust qualified_type_reference_use_lines now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_qualified_type_reference_use_lines_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust qualified_type_reference_use_lines CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "qualified_type_reference_use_lines"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_use_lines_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_use_lines_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..b32a3271768 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_qualified_type_reference_use_lines_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_qualified_type_reference_use_lines_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.compiler.emit_rust qualified_type_reference_use_lines now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_qualified_type_reference_use_lines_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust qualified_type_reference_use_lines ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "qualified_type_reference_use_lines"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateexportprooffailed.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateexportprooffailed.dag new file mode 100644 index 00000000000..aba60ea76ca --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateexportprooffailed.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_disposition_candidateexportprooffailed + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateExportProofFailed binding inside +// v1.compiler.emit_rust reference_derived_candidate_disposition now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_disposition_candidateexportprooffailed: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_disposition CandidateExportProofFailed: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_disposition"), + spelling: "CandidateExportProofFailed" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateExportProofFailed")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateleafambiguous.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateleafambiguous.dag new file mode 100644 index 00000000000..084577ae77d --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateleafambiguous.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_disposition_candidateleafambiguous + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateLeafAmbiguous binding inside +// v1.compiler.emit_rust reference_derived_candidate_disposition now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_disposition_candidateleafambiguous: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_disposition CandidateLeafAmbiguous: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_disposition"), + spelling: "CandidateLeafAmbiguous" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateLeafAmbiguous")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateownmodule.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateownmodule.dag new file mode 100644 index 00000000000..85c44a66d57 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateownmodule.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_disposition_candidateownmodule + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateOwnModule binding inside +// v1.compiler.emit_rust reference_derived_candidate_disposition now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_disposition_candidateownmodule: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_disposition CandidateOwnModule: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_disposition"), + spelling: "CandidateOwnModule" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateOwnModule")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateregistryabsent.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateregistryabsent.dag new file mode 100644 index 00000000000..3d3836ef185 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidateregistryabsent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_disposition_candidateregistryabsent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateRegistryAbsent binding inside +// v1.compiler.emit_rust reference_derived_candidate_disposition now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_disposition_candidateregistryabsent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_disposition CandidateRegistryAbsent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_disposition"), + spelling: "CandidateRegistryAbsent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateRegistryAbsent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidatesurvived.dag new file mode 100644 index 00000000000..c3dc54163e3 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_disposition_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.compiler.emit_rust reference_derived_candidate_disposition now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_disposition_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_disposition CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_disposition"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidatevariantdelegatedtoparent.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidatevariantdelegatedtoparent.dag new file mode 100644 index 00000000000..a83bdd55e49 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidatevariantdelegatedtoparent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_disposition_candidatevariantdelegatedtoparent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantDelegatedToParent binding inside +// v1.compiler.emit_rust reference_derived_candidate_disposition now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_disposition_candidatevariantdelegatedtoparent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_disposition CandidateVariantDelegatedToParent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_disposition"), + spelling: "CandidateVariantDelegatedToParent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantDelegatedToParent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidatevariantparentunresolved.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidatevariantparentunresolved.dag new file mode 100644 index 00000000000..80b359c7bcd --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_candidatevariantparentunresolved.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_disposition_candidatevariantparentunresolved + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantParentUnresolved binding inside +// v1.compiler.emit_rust reference_derived_candidate_disposition now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_disposition_candidatevariantparentunresolved: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_disposition CandidateVariantParentUnresolved: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_disposition"), + spelling: "CandidateVariantParentUnresolved" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantParentUnresolved")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_referencederivedcandidatedisposition.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_referencederivedcandidatedisposition.dag new file mode 100644 index 00000000000..96910f502bc --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_disposition_referencederivedcandidatedisposition.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_disposition_referencederivedcandidatedisposition + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateDisposition binding inside +// v1.compiler.emit_rust reference_derived_candidate_disposition now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_disposition_referencederivedcandidatedisposition: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_disposition ReferenceDerivedCandidateDisposition: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_disposition"), + spelling: "ReferenceDerivedCandidateDisposition" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateDisposition")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_survived_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_survived_candidatesurvived.dag new file mode 100644 index 00000000000..1c54268ee25 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_survived_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_survived_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.compiler.emit_rust reference_derived_candidate_survived now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_survived_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_survived CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_survived"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_survived_referencederivedcandidatedisposition.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_survived_referencederivedcandidatedisposition.dag new file mode 100644 index 00000000000..a702f911d76 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_candidate_survived_referencederivedcandidatedisposition.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_candidate_survived_referencederivedcandidatedisposition + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateDisposition binding inside +// v1.compiler.emit_rust reference_derived_candidate_survived now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_candidate_survived_referencederivedcandidatedisposition: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_candidate_survived ReferenceDerivedCandidateDisposition: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_candidate_survived"), + spelling: "ReferenceDerivedCandidateDisposition" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateDisposition")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateexportprooffailed.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateexportprooffailed.dag new file mode 100644 index 00000000000..da372f9216a --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateexportprooffailed.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_census_candidateexportprooffailed + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateExportProofFailed binding inside +// v1.compiler.emit_rust reference_derived_census now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_census_candidateexportprooffailed: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_census CandidateExportProofFailed: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_census"), + spelling: "CandidateExportProofFailed" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateExportProofFailed")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateleafambiguous.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateleafambiguous.dag new file mode 100644 index 00000000000..ed4f01ef239 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateleafambiguous.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_census_candidateleafambiguous + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateLeafAmbiguous binding inside +// v1.compiler.emit_rust reference_derived_census now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_census_candidateleafambiguous: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_census CandidateLeafAmbiguous: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_census"), + spelling: "CandidateLeafAmbiguous" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateLeafAmbiguous")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateownmodule.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateownmodule.dag new file mode 100644 index 00000000000..3c04d07512c --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateownmodule.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_census_candidateownmodule + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateOwnModule binding inside +// v1.compiler.emit_rust reference_derived_census now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_census_candidateownmodule: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_census CandidateOwnModule: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_census"), + spelling: "CandidateOwnModule" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateOwnModule")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateregistryabsent.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateregistryabsent.dag new file mode 100644 index 00000000000..91f34840f08 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidateregistryabsent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_census_candidateregistryabsent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateRegistryAbsent binding inside +// v1.compiler.emit_rust reference_derived_census now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_census_candidateregistryabsent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_census CandidateRegistryAbsent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_census"), + spelling: "CandidateRegistryAbsent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateRegistryAbsent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidatesurvived.dag new file mode 100644 index 00000000000..13e69fe9dbd --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_census_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.compiler.emit_rust reference_derived_census now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_census_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_census CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_census"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidatevariantdelegatedtoparent.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidatevariantdelegatedtoparent.dag new file mode 100644 index 00000000000..89b789d427d --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidatevariantdelegatedtoparent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_census_candidatevariantdelegatedtoparent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantDelegatedToParent binding inside +// v1.compiler.emit_rust reference_derived_census now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_census_candidatevariantdelegatedtoparent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_census CandidateVariantDelegatedToParent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_census"), + spelling: "CandidateVariantDelegatedToParent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantDelegatedToParent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidatevariantparentunresolved.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidatevariantparentunresolved.dag new file mode 100644 index 00000000000..aed5903ece2 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_candidatevariantparentunresolved.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_census_candidatevariantparentunresolved + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantParentUnresolved binding inside +// v1.compiler.emit_rust reference_derived_census now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_census_candidatevariantparentunresolved: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_census CandidateVariantParentUnresolved: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_census"), + spelling: "CandidateVariantParentUnresolved" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantParentUnresolved")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..1a31b847ea6 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_census_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_census_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.compiler.emit_rust reference_derived_census now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_census_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_census ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_census"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateexportprooffailed.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateexportprooffailed.dag new file mode 100644 index 00000000000..42f9af93a28 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateexportprooffailed.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_disposition_name_candidateexportprooffailed + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateExportProofFailed binding inside +// v1.compiler.emit_rust reference_derived_disposition_name now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_disposition_name_candidateexportprooffailed: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_disposition_name CandidateExportProofFailed: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_disposition_name"), + spelling: "CandidateExportProofFailed" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateExportProofFailed")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateleafambiguous.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateleafambiguous.dag new file mode 100644 index 00000000000..e3dbeafdc5b --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateleafambiguous.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_disposition_name_candidateleafambiguous + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateLeafAmbiguous binding inside +// v1.compiler.emit_rust reference_derived_disposition_name now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_disposition_name_candidateleafambiguous: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_disposition_name CandidateLeafAmbiguous: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_disposition_name"), + spelling: "CandidateLeafAmbiguous" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateLeafAmbiguous")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateownmodule.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateownmodule.dag new file mode 100644 index 00000000000..746be034b5f --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateownmodule.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_disposition_name_candidateownmodule + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateOwnModule binding inside +// v1.compiler.emit_rust reference_derived_disposition_name now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_disposition_name_candidateownmodule: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_disposition_name CandidateOwnModule: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_disposition_name"), + spelling: "CandidateOwnModule" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateOwnModule")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateregistryabsent.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateregistryabsent.dag new file mode 100644 index 00000000000..2195b5b214a --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidateregistryabsent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_disposition_name_candidateregistryabsent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateRegistryAbsent binding inside +// v1.compiler.emit_rust reference_derived_disposition_name now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_disposition_name_candidateregistryabsent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_disposition_name CandidateRegistryAbsent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_disposition_name"), + spelling: "CandidateRegistryAbsent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateRegistryAbsent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidatesurvived.dag new file mode 100644 index 00000000000..d33938ecb48 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_disposition_name_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.compiler.emit_rust reference_derived_disposition_name now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_disposition_name_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_disposition_name CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_disposition_name"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidatevariantdelegatedtoparent.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidatevariantdelegatedtoparent.dag new file mode 100644 index 00000000000..d7dec0ccd77 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidatevariantdelegatedtoparent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_disposition_name_candidatevariantdelegatedtoparent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantDelegatedToParent binding inside +// v1.compiler.emit_rust reference_derived_disposition_name now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_disposition_name_candidatevariantdelegatedtoparent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_disposition_name CandidateVariantDelegatedToParent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_disposition_name"), + spelling: "CandidateVariantDelegatedToParent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantDelegatedToParent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidatevariantparentunresolved.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidatevariantparentunresolved.dag new file mode 100644 index 00000000000..1207be6185d --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_candidatevariantparentunresolved.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_disposition_name_candidatevariantparentunresolved + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantParentUnresolved binding inside +// v1.compiler.emit_rust reference_derived_disposition_name now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_disposition_name_candidatevariantparentunresolved: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_disposition_name CandidateVariantParentUnresolved: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_disposition_name"), + spelling: "CandidateVariantParentUnresolved" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantParentUnresolved")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_referencederivedcandidatedisposition.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_referencederivedcandidatedisposition.dag new file mode 100644 index 00000000000..44ce27f71cf --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_disposition_name_referencederivedcandidatedisposition.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_disposition_name_referencederivedcandidatedisposition + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateDisposition binding inside +// v1.compiler.emit_rust reference_derived_disposition_name now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_disposition_name_referencederivedcandidatedisposition: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_disposition_name ReferenceDerivedCandidateDisposition: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_disposition_name"), + spelling: "ReferenceDerivedCandidateDisposition" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateDisposition")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateexportprooffailed.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateexportprooffailed.dag new file mode 100644 index 00000000000..82e2161d3e0 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateexportprooffailed.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_row_diagnostics_candidateexportprooffailed + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateExportProofFailed binding inside +// v1.compiler.emit_rust reference_derived_row_diagnostics now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_row_diagnostics_candidateexportprooffailed: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_row_diagnostics CandidateExportProofFailed: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_row_diagnostics"), + spelling: "CandidateExportProofFailed" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateExportProofFailed")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateleafambiguous.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateleafambiguous.dag new file mode 100644 index 00000000000..fc95d0f9007 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateleafambiguous.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_row_diagnostics_candidateleafambiguous + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateLeafAmbiguous binding inside +// v1.compiler.emit_rust reference_derived_row_diagnostics now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_row_diagnostics_candidateleafambiguous: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_row_diagnostics CandidateLeafAmbiguous: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_row_diagnostics"), + spelling: "CandidateLeafAmbiguous" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateLeafAmbiguous")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateownmodule.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateownmodule.dag new file mode 100644 index 00000000000..d1b35884e5c --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateownmodule.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_row_diagnostics_candidateownmodule + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateOwnModule binding inside +// v1.compiler.emit_rust reference_derived_row_diagnostics now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_row_diagnostics_candidateownmodule: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_row_diagnostics CandidateOwnModule: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_row_diagnostics"), + spelling: "CandidateOwnModule" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateOwnModule")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateregistryabsent.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateregistryabsent.dag new file mode 100644 index 00000000000..ec800b3a65a --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidateregistryabsent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_row_diagnostics_candidateregistryabsent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateRegistryAbsent binding inside +// v1.compiler.emit_rust reference_derived_row_diagnostics now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_row_diagnostics_candidateregistryabsent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_row_diagnostics CandidateRegistryAbsent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_row_diagnostics"), + spelling: "CandidateRegistryAbsent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateRegistryAbsent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidatesurvived.dag new file mode 100644 index 00000000000..f7bf5af68d7 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_row_diagnostics_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.compiler.emit_rust reference_derived_row_diagnostics now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_row_diagnostics_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_row_diagnostics CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_row_diagnostics"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidatevariantdelegatedtoparent.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidatevariantdelegatedtoparent.dag new file mode 100644 index 00000000000..640660edb46 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidatevariantdelegatedtoparent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_row_diagnostics_candidatevariantdelegatedtoparent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantDelegatedToParent binding inside +// v1.compiler.emit_rust reference_derived_row_diagnostics now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_row_diagnostics_candidatevariantdelegatedtoparent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_row_diagnostics CandidateVariantDelegatedToParent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_row_diagnostics"), + spelling: "CandidateVariantDelegatedToParent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantDelegatedToParent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidatevariantparentunresolved.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidatevariantparentunresolved.dag new file mode 100644 index 00000000000..124b8d01596 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_candidatevariantparentunresolved.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_row_diagnostics_candidatevariantparentunresolved + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantParentUnresolved binding inside +// v1.compiler.emit_rust reference_derived_row_diagnostics now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_row_diagnostics_candidatevariantparentunresolved: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_row_diagnostics CandidateVariantParentUnresolved: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_row_diagnostics"), + spelling: "CandidateVariantParentUnresolved" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantParentUnresolved")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..2cd1e2bd2a3 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_row_diagnostics_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_row_diagnostics_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.compiler.emit_rust reference_derived_row_diagnostics now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_row_diagnostics_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_row_diagnostics ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_row_diagnostics"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_use_line_plan_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_use_line_plan_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..f1a57499316 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/emit_rust_reference_derived_use_line_plan_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.emit_rust_reference_derived_use_line_plan_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.compiler.emit_rust reference_derived_use_line_plan now resolves to the gunbc.reference_derived_candidate authority. +data emit_rust_reference_derived_use_line_plan_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.compiler.emit_rust reference_derived_use_line_plan ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.compiler.emit_rust", "reference_derived_use_line_plan"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/gunbc_spark_serving_offer_spark_serving_route_standing_DeclaredUnitDigestStanding.dag b/dag/gunbc/namespace/transition_admission/gunbc_spark_serving_offer_spark_serving_route_standing_DeclaredUnitDigestStanding.dag deleted file mode 100644 index b3a7aad8604..00000000000 --- a/dag/gunbc/namespace/transition_admission/gunbc_spark_serving_offer_spark_serving_route_standing_DeclaredUnitDigestStanding.dag +++ /dev/null @@ -1,24 +0,0 @@ -module gunbc.namespace.transition_admission.gunbc_spark_serving_offer_spark_serving_route_standing_DeclaredUnitDigestStanding - -import std.types { NonEmptyStr, List } -import std.integer { UInt32 } -import std.decl_ref { decl_ref } -import gunbc.compiler_frontend_program_interlock { TargetChanged } -import gunbc.namespace.transition_admission { TransitionAdmission, Binding, NotAuthored } - -// gunbc#11440 declared-unit-digest home: DeclaredUnitDigestStanding and its two arms relocate -// verbatim from gunbc.spark.serving_offer to gunbc.spark.pair_serving_realization, the render -// boundary that mints the SHA-256 of the rendered head-unit bytes. A spelling authored on both -// sides whose candidate module changed; the declaration it denotes did not. -// DISSOLVE-ON: gunbc#11440 merging. -data gunbc_spark_serving_offer_spark_serving_route_standing_DeclaredUnitDigestStanding: TransitionAdmission = TransitionAdmission { - label: "gunbc#11440 DeclaredUnitDigestStanding moves to pair_serving_realization" as NonEmptyStr, - subject: Binding { - enclosing: decl_ref("gunbc.spark.serving_offer", "spark_serving_route_standing"), - spelling: "DeclaredUnitDigestStanding" as NonEmptyStr, - expected_candidates: [decl_ref("gunbc.spark.pair_serving_realization", "DeclaredUnitDigestStanding")], - }, - disposition: TargetChanged, - deletion_follow_up: NotAuthored, - owner_pull_request: 11440 as UInt32, -} diff --git a/dag/gunbc/namespace/transition_admission/reference_deps_reference_declared_module_prefix_facts_symbol_eq.dag b/dag/gunbc/namespace/transition_admission/reference_deps_reference_declared_module_prefix_facts_symbol_eq.dag new file mode 100644 index 00000000000..072721d8c6a --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_deps_reference_declared_module_prefix_facts_symbol_eq.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_deps_reference_declared_module_prefix_facts_symbol_eq + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (review 67052): the module-local symbol_eq copy in v2.lens.reference_deps is +// deleted and the spelling now resolves to the one authority v2.std.node symbol_eq. +data reference_deps_reference_declared_module_prefix_facts_symbol_eq: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v2.lens.reference_deps reference_declared_module_prefix_facts symbol_eq: v2.lens.reference_deps -> v2.std.node" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v2.lens.reference_deps", "reference_declared_module_prefix_facts"), + spelling: "symbol_eq" as NonEmptyStr, + expected_candidates: [decl_ref("v2.std.node", "symbol_eq")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_a_variant_whose_parent_is_ambiguous_is_not_delegated_to_nothing_candidatevariantparentunresolved.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_a_variant_whose_parent_is_ambiguous_is_not_delegated_to_nothing_candidatevariantparentunresolved.dag new file mode 100644 index 00000000000..300bb844eba --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_a_variant_whose_parent_is_ambiguous_is_not_delegated_to_nothing_candidatevariantparentunresolved.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_a_variant_whose_parent_is_ambiguous_is_not_delegated_to_nothing_candidatevariantparentunresolved + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantParentUnresolved binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test a_variant_whose_parent_is_ambiguous_is_not_delegated_to_nothing now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_a_variant_whose_parent_is_ambiguous_is_not_delegated_to_nothing_candidatevariantparentunresolved: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test a_variant_whose_parent_is_ambiguous_is_not_delegated_to_nothing CandidateVariantParentUnresolved: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "a_variant_whose_parent_is_ambiguous_is_not_delegated_to_nothing"), + spelling: "CandidateVariantParentUnresolved" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantParentUnresolved")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_an_unresolved_parent_is_not_reported_as_registry_absent_candidatevariantparentunresolved.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_an_unresolved_parent_is_not_reported_as_registry_absent_candidatevariantparentunresolved.dag new file mode 100644 index 00000000000..d67923f9b52 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_an_unresolved_parent_is_not_reported_as_registry_absent_candidatevariantparentunresolved.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_an_unresolved_parent_is_not_reported_as_registry_absent_candidatevariantparentunresolved + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantParentUnresolved binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test an_unresolved_parent_is_not_reported_as_registry_absent now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_an_unresolved_parent_is_not_reported_as_registry_absent_candidatevariantparentunresolved: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test an_unresolved_parent_is_not_reported_as_registry_absent CandidateVariantParentUnresolved: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "an_unresolved_parent_is_not_reported_as_registry_absent"), + spelling: "CandidateVariantParentUnresolved" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantParentUnresolved")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateexportprooffailed.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateexportprooffailed.dag new file mode 100644 index 00000000000..1d8856ef177 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateexportprooffailed.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateexportprooffailed + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateExportProofFailed binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateexportprooffailed: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately CandidateExportProofFailed: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "census_counts_each_arm_separately"), + spelling: "CandidateExportProofFailed" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateExportProofFailed")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateownmodule.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateownmodule.dag new file mode 100644 index 00000000000..acd0460d379 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateownmodule.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateownmodule + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateOwnModule binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateownmodule: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately CandidateOwnModule: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "census_counts_each_arm_separately"), + spelling: "CandidateOwnModule" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateOwnModule")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateregistryabsent.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateregistryabsent.dag new file mode 100644 index 00000000000..4b30d8067c8 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateregistryabsent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateregistryabsent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateRegistryAbsent binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidateregistryabsent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately CandidateRegistryAbsent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "census_counts_each_arm_separately"), + spelling: "CandidateRegistryAbsent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateRegistryAbsent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatesurvived.dag new file mode 100644 index 00000000000..e192af4fed3 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "census_counts_each_arm_separately"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantdelegatedtoparent.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantdelegatedtoparent.dag new file mode 100644 index 00000000000..65b36a1e72c --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantdelegatedtoparent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantdelegatedtoparent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantDelegatedToParent binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantdelegatedtoparent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately CandidateVariantDelegatedToParent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "census_counts_each_arm_separately"), + spelling: "CandidateVariantDelegatedToParent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantDelegatedToParent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantparentunresolved.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantparentunresolved.dag new file mode 100644 index 00000000000..e109b0c3b9e --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantparentunresolved.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantparentunresolved + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantParentUnresolved binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_candidatevariantparentunresolved: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately CandidateVariantParentUnresolved: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "census_counts_each_arm_separately"), + spelling: "CandidateVariantParentUnresolved" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantParentUnresolved")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..2533f4c2e5c --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_census_counts_each_arm_separately_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test census_counts_each_arm_separately ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "census_counts_each_arm_separately"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_cross_module_candidate_with_export_proof_survives_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_cross_module_candidate_with_export_proof_survives_candidatesurvived.dag new file mode 100644 index 00000000000..7b15f7f5cba --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_cross_module_candidate_with_export_proof_survives_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_cross_module_candidate_with_export_proof_survives_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test cross_module_candidate_with_export_proof_survives now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_cross_module_candidate_with_export_proof_survives_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test cross_module_candidate_with_export_proof_survives CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "cross_module_candidate_with_export_proof_survives"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_known_variant_is_delegated_to_its_parent_not_registry_absent_candidatevariantdelegatedtoparent.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_known_variant_is_delegated_to_its_parent_not_registry_absent_candidatevariantdelegatedtoparent.dag new file mode 100644 index 00000000000..6eae60be25d --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_known_variant_is_delegated_to_its_parent_not_registry_absent_candidatevariantdelegatedtoparent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_known_variant_is_delegated_to_its_parent_not_registry_absent_candidatevariantdelegatedtoparent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantDelegatedToParent binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test known_variant_is_delegated_to_its_parent_not_registry_absent now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_known_variant_is_delegated_to_its_parent_not_registry_absent_candidatevariantdelegatedtoparent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test known_variant_is_delegated_to_its_parent_not_registry_absent CandidateVariantDelegatedToParent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "known_variant_is_delegated_to_its_parent_not_registry_absent"), + spelling: "CandidateVariantDelegatedToParent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantDelegatedToParent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateexportprooffailed.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateexportprooffailed.dag new file mode 100644 index 00000000000..99cdb7f757e --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateexportprooffailed.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateexportprooffailed + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateExportProofFailed binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateexportprooffailed: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic CandidateExportProofFailed: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "only_export_proof_failed_produces_a_diagnostic"), + spelling: "CandidateExportProofFailed" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateExportProofFailed")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateownmodule.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateownmodule.dag new file mode 100644 index 00000000000..a1ecbf8fb81 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateownmodule.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateownmodule + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateOwnModule binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateownmodule: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic CandidateOwnModule: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "only_export_proof_failed_produces_a_diagnostic"), + spelling: "CandidateOwnModule" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateOwnModule")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateregistryabsent.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateregistryabsent.dag new file mode 100644 index 00000000000..dcfccfa7e8d --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateregistryabsent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateregistryabsent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateRegistryAbsent binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidateregistryabsent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic CandidateRegistryAbsent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "only_export_proof_failed_produces_a_diagnostic"), + spelling: "CandidateRegistryAbsent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateRegistryAbsent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatesurvived.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatesurvived.dag new file mode 100644 index 00000000000..bd6fd90ef62 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatesurvived.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatesurvived + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateSurvived binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatesurvived: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic CandidateSurvived: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "only_export_proof_failed_produces_a_diagnostic"), + spelling: "CandidateSurvived" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateSurvived")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatevariantdelegatedtoparent.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatevariantdelegatedtoparent.dag new file mode 100644 index 00000000000..e5e245cbab1 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatevariantdelegatedtoparent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatevariantdelegatedtoparent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateVariantDelegatedToParent binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_candidatevariantdelegatedtoparent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic CandidateVariantDelegatedToParent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "only_export_proof_failed_produces_a_diagnostic"), + spelling: "CandidateVariantDelegatedToParent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateVariantDelegatedToParent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..2b5e5a876a0 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_only_export_proof_failed_produces_a_diagnostic_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test only_export_proof_failed_produces_a_diagnostic ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "only_export_proof_failed_produces_a_diagnostic"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_candidateregistryabsent.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_candidateregistryabsent.dag new file mode 100644 index 00000000000..425f7e73b3e --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_candidateregistryabsent.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_candidateregistryabsent + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateRegistryAbsent binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test registry_absent_produces_no_diagnostic now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_candidateregistryabsent: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test registry_absent_produces_no_diagnostic CandidateRegistryAbsent: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "registry_absent_produces_no_diagnostic"), + spelling: "CandidateRegistryAbsent" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateRegistryAbsent")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..21acb5a7062 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test registry_absent_produces_no_diagnostic now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_registry_absent_produces_no_diagnostic_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test registry_absent_produces_no_diagnostic ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "registry_absent_produces_no_diagnostic"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_candidateexportprooffailed.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_candidateexportprooffailed.dag new file mode 100644 index 00000000000..4b8ef197a27 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_candidateexportprooffailed.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_candidateexportprooffailed + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateExportProofFailed binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test the_export_unproven_diagnostic_is_advisory now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_candidateexportprooffailed: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test the_export_unproven_diagnostic_is_advisory CandidateExportProofFailed: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "the_export_unproven_diagnostic_is_advisory"), + spelling: "CandidateExportProofFailed" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateExportProofFailed")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..4e575364d52 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test the_export_unproven_diagnostic_is_advisory now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_the_export_unproven_diagnostic_is_advisory_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test the_export_unproven_diagnostic_is_advisory ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "the_export_unproven_diagnostic_is_advisory"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_candidateexportprooffailed.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_candidateexportprooffailed.dag new file mode 100644 index 00000000000..b56ce555882 --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_candidateexportprooffailed.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_candidateexportprooffailed + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local CandidateExportProofFailed binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test the_export_unproven_message_names_its_own_remedy now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_candidateexportprooffailed: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test the_export_unproven_message_names_its_own_remedy CandidateExportProofFailed: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "the_export_unproven_message_names_its_own_remedy"), + spelling: "CandidateExportProofFailed" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "CandidateExportProofFailed")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_referencederivedcandidaterow.dag b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_referencederivedcandidaterow.dag new file mode 100644 index 00000000000..da4d073271c --- /dev/null +++ b/dag/gunbc/namespace/transition_admission/reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_referencederivedcandidaterow.dag @@ -0,0 +1,21 @@ +module gunbc.namespace.transition_admission.reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_referencederivedcandidaterow + +import std.types { NonEmptyStr, List } +import std.integer { UInt32 } +import std.decl_ref { decl_ref } +import gunbc.compiler_frontend_program_interlock { TargetChanged } +import gunbc.namespace.transition_admission { TransitionAdmission, Binding, PullRequest } + +// gunbc#11461 (XL-4 reference-derived graph): the local ReferenceDerivedCandidateRow binding inside +// v1.tests.claim.reference_derived_disposition_census_witness_test the_export_unproven_message_names_its_own_remedy now resolves to the gunbc.reference_derived_candidate authority. +data reference_derived_disposition_census_witness_test_the_export_unproven_message_names_its_own_remedy_referencederivedcandidaterow: TransitionAdmission = TransitionAdmission { + label: "gunbc#11461 v1.tests.claim.reference_derived_disposition_census_witness_test the_export_unproven_message_names_its_own_remedy ReferenceDerivedCandidateRow: v1.compiler.emit_rust -> gunbc.reference_derived_candidate" as NonEmptyStr, + subject: Binding { + enclosing: decl_ref("v1.tests.claim.reference_derived_disposition_census_witness_test", "the_export_unproven_message_names_its_own_remedy"), + spelling: "ReferenceDerivedCandidateRow" as NonEmptyStr, + expected_candidates: [decl_ref("gunbc.reference_derived_candidate", "ReferenceDerivedCandidateRow")], + }, + disposition: TargetChanged, + deletion_follow_up: PullRequest { number: 11466 as UInt32 }, + owner_pull_request: 11461 as UInt32, +} diff --git a/dag/gunbc/namespace/transition_admission/test_claim_spark_spark_serving_offer_route_witness_test_t_declared_DeclaredUnitDigestStanding.dag b/dag/gunbc/namespace/transition_admission/test_claim_spark_spark_serving_offer_route_witness_test_t_declared_DeclaredUnitDigestStanding.dag deleted file mode 100644 index c4b80926a45..00000000000 --- a/dag/gunbc/namespace/transition_admission/test_claim_spark_spark_serving_offer_route_witness_test_t_declared_DeclaredUnitDigestStanding.dag +++ /dev/null @@ -1,24 +0,0 @@ -module gunbc.namespace.transition_admission.test_claim_spark_spark_serving_offer_route_witness_test_t_declared_DeclaredUnitDigestStanding - -import std.types { NonEmptyStr, List } -import std.integer { UInt32 } -import std.decl_ref { decl_ref } -import gunbc.compiler_frontend_program_interlock { TargetChanged } -import gunbc.namespace.transition_admission { TransitionAdmission, Binding, NotAuthored } - -// gunbc#11440 declared-unit-digest home: DeclaredUnitDigestStanding and its two arms relocate -// verbatim from gunbc.spark.serving_offer to gunbc.spark.pair_serving_realization, the render -// boundary that mints the SHA-256 of the rendered head-unit bytes. A spelling authored on both -// sides whose candidate module changed; the declaration it denotes did not. -// DISSOLVE-ON: gunbc#11440 merging. -data test_claim_spark_spark_serving_offer_route_witness_test_t_declared_DeclaredUnitDigestStanding: TransitionAdmission = TransitionAdmission { - label: "gunbc#11440 DeclaredUnitDigestStanding moves to pair_serving_realization" as NonEmptyStr, - subject: Binding { - enclosing: decl_ref("test.claim.spark.spark_serving_offer_route_witness_test", "t_declared"), - spelling: "DeclaredUnitDigestStanding" as NonEmptyStr, - expected_candidates: [decl_ref("gunbc.spark.pair_serving_realization", "DeclaredUnitDigestStanding")], - }, - disposition: TargetChanged, - deletion_follow_up: NotAuthored, - owner_pull_request: 11440 as UInt32, -} diff --git a/dag/gunbc/namespace/transition_admission/test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestStanding.dag b/dag/gunbc/namespace/transition_admission/test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestStanding.dag deleted file mode 100644 index c47faa17d1e..00000000000 --- a/dag/gunbc/namespace/transition_admission/test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestStanding.dag +++ /dev/null @@ -1,24 +0,0 @@ -module gunbc.namespace.transition_admission.test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestStanding - -import std.types { NonEmptyStr, List } -import std.integer { UInt32 } -import std.decl_ref { decl_ref } -import gunbc.compiler_frontend_program_interlock { TargetChanged } -import gunbc.namespace.transition_admission { TransitionAdmission, Binding, NotAuthored } - -// gunbc#11440 declared-unit-digest home: DeclaredUnitDigestStanding and its two arms relocate -// verbatim from gunbc.spark.serving_offer to gunbc.spark.pair_serving_realization, the render -// boundary that mints the SHA-256 of the rendered head-unit bytes. A spelling authored on both -// sides whose candidate module changed; the declaration it denotes did not. -// DISSOLVE-ON: gunbc#11440 merging. -data test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestStanding: TransitionAdmission = TransitionAdmission { - label: "gunbc#11440 DeclaredUnitDigestStanding moves to pair_serving_realization" as NonEmptyStr, - subject: Binding { - enclosing: decl_ref("test.claim.spark.spark_serving_offer_route_witness_test", "t_unit_unavailable"), - spelling: "DeclaredUnitDigestStanding" as NonEmptyStr, - expected_candidates: [decl_ref("gunbc.spark.pair_serving_realization", "DeclaredUnitDigestStanding")], - }, - disposition: TargetChanged, - deletion_follow_up: NotAuthored, - owner_pull_request: 11440 as UInt32, -} diff --git a/dag/gunbc/namespace/transition_admission/test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestUnavailable.dag b/dag/gunbc/namespace/transition_admission/test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestUnavailable.dag deleted file mode 100644 index ccdc2cc3d50..00000000000 --- a/dag/gunbc/namespace/transition_admission/test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestUnavailable.dag +++ /dev/null @@ -1,24 +0,0 @@ -module gunbc.namespace.transition_admission.test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestUnavailable - -import std.types { NonEmptyStr, List } -import std.integer { UInt32 } -import std.decl_ref { decl_ref } -import gunbc.compiler_frontend_program_interlock { TargetChanged } -import gunbc.namespace.transition_admission { TransitionAdmission, Binding, NotAuthored } - -// gunbc#11440 declared-unit-digest home: DeclaredUnitDigestStanding and its two arms relocate -// verbatim from gunbc.spark.serving_offer to gunbc.spark.pair_serving_realization, the render -// boundary that mints the SHA-256 of the rendered head-unit bytes. A spelling authored on both -// sides whose candidate module changed; the declaration it denotes did not. -// DISSOLVE-ON: gunbc#11440 merging. -data test_claim_spark_spark_serving_offer_route_witness_test_t_unit_unavailable_DeclaredUnitDigestUnavailable: TransitionAdmission = TransitionAdmission { - label: "gunbc#11440 DeclaredUnitDigestStanding moves to pair_serving_realization" as NonEmptyStr, - subject: Binding { - enclosing: decl_ref("test.claim.spark.spark_serving_offer_route_witness_test", "t_unit_unavailable"), - spelling: "DeclaredUnitDigestUnavailable" as NonEmptyStr, - expected_candidates: [decl_ref("gunbc.spark.pair_serving_realization", "DeclaredUnitDigestUnavailable")], - }, - disposition: TargetChanged, - deletion_follow_up: NotAuthored, - owner_pull_request: 11440 as UInt32, -} diff --git a/dag/gunbc/recurring_failure_mode/a_coproduct_declares_one_variant_twice.dag b/dag/gunbc/recurring_failure_mode/a_coproduct_declares_one_variant_twice.dag new file mode 100644 index 00000000000..b973278f82e --- /dev/null +++ b/dag/gunbc/recurring_failure_mode/a_coproduct_declares_one_variant_twice.dag @@ -0,0 +1,19 @@ +module gunbc.recurring_failure_mode.a_coproduct_declares_one_variant_twice + +import std.types { NonEmptyStr } +import gunbc.recurring_failure_mode { RecurringFailureMode } + +data a_coproduct_declares_one_variant_twice: RecurringFailureMode = RecurringFailureMode { + identity: "a_coproduct_declares_one_variant_twice" as NonEmptyStr, + receipts: [ + "INVALID STATE: one coproduct declaration names the same variant twice. One name, two declarations, in a single type -- the section 3 single-authority defect stated at the grain where the substrate can see it, and distinct from two variants sharing a leaf name under DIFFERENT containment, which is a namespace-identity question and not this row.", + "HARM: lookup by exact authored name takes the first match and never asks whether a second exists, so the duplicate is not merely tolerated, it is unobservable. Every consumer resolves to the first declaration and the second is dead vocabulary that still reads as declared. Nothing downstream can distinguish the two, so no consumer can report the defect either; the declaration is degenerate and the whole pipeline answers as though it were not.", + "RECEIPT, AND IT IS A LIVE ONE RATHER THAN A CONSTRUCTED SPECIMEN: extdeps.systemd SystemdUnitProperty carried two identical SubState declaration arms and two identical wire arms, on origin/main since gunbc#9761 and gunbc#10443, through every required run in that window without a single diagnostic. It was surfaced only when v1.compiler.infer_patterns find_variant_child_keyed began keying variant lookup and refusing on more than one match: both children key equal, lookup refuses, and required-witnesses-floor and heal-generated-artifacts both refused with ChangedWitnessObservationFailed naming that declaration.", + "POPULATION, BY INSTRUMENT RATHER THAN BY ASSERTION: an arm-level duplicate-leaf census over every coproduct declaration under dag/ and src/ -- splitting each type declaration right-hand side on its top-level pipe and counting duplicate leaf keys per declaration, rather than matching lines -- identifies the membership. SystemdUnitProperty was its sole member at the time of this receipt. The census is the reproduction route; a transcribed count is not the authority and would rot away from it.", + "RUNG FOUND AT: mechanically preventable, and BY ACCIDENT. The refusal that caught it is a lookup-time consequence of keying variant identity for an unrelated repair, not a wall anybody built for this class. Nothing in the parser, normalize or resolve folds refuses a duplicate variant at declaration, so on any route that does not key -- which is every route before that change -- the class remains entirely silent. Reporting this as a standing mechanical prevention would be rung inflation: the mechanism is real, executes, and is enrolled, but it guards the class only where a keyed lookup happens to reach the declaration.", + "CEILING: structurally impossible, and the argument is that the invalid state has no constructor once the declaration fold refuses it. A coproduct whose declared variant names are not distinct is not a weakly-typed program but a malformed declaration; a fold that refuses a repeated leaf at ingest leaves no accepted program in which the duplicate exists, so no validation, lookup rule or consumer discipline is needed downstream. This is a decidable, fully modeled class -- the declared children and their authored names are both in hand at the point of declaration -- so section 4b admits nothing weaker as its ceiling.", + "NEXT-RUNG TRIGGER, NAMING THE CAPABILITY AND NOT AN ARTIFACT: the declaration fold that constructs a Disj node refuses a declaration whose children do not carry pairwise distinct authored names, with a typed located diagnostic naming the type and the repeated name, executed on a paired probe -- a duplicate declaration refused, and a declaration whose variants merely share a prefix or differ only outside the leaf accepted. Owner unassigned at filing. A lookup-side refusal does NOT retire this row: it catches the class only where a keyed lookup reaches the declaration, which is what this receipt shows was true for years while the duplicate stood.", + "DISPOSITION: filed from gunbc#11301, whose subject is the one-sided coverage and lookup key in v1.compiler.infer_patterns. The SystemdUnitProperty deletion landed there as a forced consequence of that PR's refusal arm, with the population measured before the edit. The declaration-time wall is deliberately NOT that PR's scope and is left to this row's trigger, so the repair that surfaced the class is not mistaken for the wall against it.", + ], + evidence: [], +} diff --git a/dag/gunbc/recurring_failure_mode/a_gate_sized_for_the_largest_subject_refuses_every_smaller_one.dag b/dag/gunbc/recurring_failure_mode/a_gate_sized_for_the_largest_subject_refuses_every_smaller_one.dag new file mode 100644 index 00000000000..5fe309ea478 --- /dev/null +++ b/dag/gunbc/recurring_failure_mode/a_gate_sized_for_the_largest_subject_refuses_every_smaller_one.dag @@ -0,0 +1,18 @@ +module gunbc.recurring_failure_mode.a_gate_sized_for_the_largest_subject_refuses_every_smaller_one + +import std.types { NonEmptyStr } +import gunbc.recurring_failure_mode { RecurringFailureMode } + +data a_gate_sized_for_the_largest_subject_refuses_every_smaller_one: RecurringFailureMode = RecurringFailureMode { + identity: "a_gate_sized_for_the_largest_subject_refuses_every_smaller_one" as NonEmptyStr, + receipts: [ + "INVALID STATE: an admission gate is sized for the largest subject its producer can take and is applied to every subject regardless of size, so a small subject the host could serve trivially is refused wherever the host cannot serve the largest one. The refusal is correct for the subject it was measured on and an over-prohibition for every other (DESIGN section 4d, second arm: forbidding more of the world than the cited variables support).", + "HARM: the producer's positive controls cannot execute on the required route, so its capability is either inflated (a constant read as Clear with only refusal arms exercised) or honestly demoted with no required evidence route at all - and the over-prohibition is invisible because the refusal wears the shape of a resource limit rather than a modeling gap.", + "RECEIPT: v1.stage0 cli_run emit_host compile_xl1_primary_root_tap gates on memory_governor whole_corpus_compile_admission before discovery. At filing the gate was a fixed DECLARED_WHOLE_CORPUS_COMPILE_MEASURED_DEMAND_BYTES against the host budget for ANY source root; gunbc#11265 keyed it on the ROOT's own measured row in gunbc.whole_corpus_compile_demand_projection, which moves the fact from one constant to one row per measured root and leaves the class standing for every root without a row (a fixture root refuses RefusedUnmeasuredRoot, the drop gunbc#11265 declares) - the subject is still not sized. On a session host the tap answers Xl1PrimaryRootObserved over the eleven-module fixture root dag/test/fixture/reference_derived_graph in 25 ms; on the required floor mid-run (gunbc#11461 run 35074340220, then run 35079253040 after the controls moved to a long home) the same two controls refused in under 300 microseconds - the admission, not the emitter - and the floor executes a CHANGED witness once even in a long home, so no enrolment of the Observed arm can be green on that route while the gate stands.", + "RUNG FOUND AT: mitigatable - a constant sized for the whole corpus refused every smaller root, and the XL-1 producer reported CaptureBlocked with its Observed-arm controls withdrawn. RUNG NOW: mechanically preventable. gunbc#11265 replaced the constant with one row per measured root (gunbc.whole_corpus_compile_admission whole_corpus_compile_measured_root_demands, joined by root identity), so a subject is admitted on its own measurement and never on another root's; the invalid state - one figure applied to every subject - has no constructor left in the admission, and what remains writable is a root with NO row, which refuses as unmeasured rather than being admitted or extrapolated. That is a refusal, not the over-prohibition: the measurement is the remedy the refusal names.", + "CEILING: structurally guaranteed - an admission keyed by the SUBJECT's measured demand (the closure the tap will compile, sized before the compile), so a fixture root is admitted where the whole corpus is refused, and the whole-corpus figure is one row of that function rather than its only value.", + "RECEIPT OF THE CLIMB: the XL-4 fixture root with dag/std as its pool was measured by gunbc measure-root-demand and its row authored (whole_corpus_compile_xl1_fixture_root_demand, replayed through gunbc.root_demand_measurement measured_for_root_from_receipt by test.claim.root_demand_measurement_witness); the required floor then executed the tap's Observed arm over it at preparation (gunbc#11461 run 35181521483, prepared-effect-input-acquire xl1_fixture_root_tap disposition=Xl1PrimaryRootObserved) with both controls green in test.claim.legacy_repair_tap_live_bridge_witness, and legacy_baseline_capture_capability reads CaptureAvailable on that receipt. Those controls stay enrolled as the regression evidence (DESIGN 4b(4)).", + "NEXT-RUNG TRIGGER, THE RESIDUAL CAPABILITY: structurally guaranteed needs a demand that is DERIVED from the subject rather than looked up by root identity - a measured-demand producer keyed on the closure the compile will take (its module count and source bytes as the row already records), so that a root nobody measured by hand is priced by construction and the unmeasured-root refusal has nothing left to refuse. The instrument that would produce it is the .dag entry point gunbc.whole_corpus_compile_admission whole_corpus_compile_measured_demand_note already names as its own next-rung trigger (scope + target in, exit status + peak out, in one carrier). Owner unassigned at filing (memory_governor and the admission model are the self-host lane's).", + ], + evidence: [], +} diff --git a/dag/gunbc/recurring_failure_mode/absent_reads_identically_to_never_looked.dag b/dag/gunbc/recurring_failure_mode/absent_reads_identically_to_never_looked.dag index 7a4f2034d24..78d1cd4f579 100644 --- a/dag/gunbc/recurring_failure_mode/absent_reads_identically_to_never_looked.dag +++ b/dag/gunbc/recurring_failure_mode/absent_reads_identically_to_never_looked.dag @@ -51,6 +51,11 @@ data absent_reads_identically_to_never_looked: RecurringFailureMode = RecurringF "THE SAME LANE CARRIES THE PREVENTED FORM ONE LAYER DOWN, WHICH IS WHY THE CARRIER IS WORTH NAMING: product.fabric.provider_route ProviderPathStanding is Located | Absent | Unread, so on the Hetzner census (gunbc#11188) NINE data paths on two routes were answered and ProviderPathAbsent was taken ZERO times -- not because every path is populated, but because nobody had stated that telemetry or spill do not exist, and Absent is a claim rather than a silence. Both routes refuse. The contrast is the whole lesson: where the distinction is a CONSTRUCTOR the representation PRESERVES it and forces an explicit choice -- the census under pressure to look complete chose Unread -- whereas where it is a RENDERED EMPTY LIST nothing stops the collapse downstream. THE NODE-RENTAL SUPPLY CELL IS THAT CONSTRUCTOR AGAIN, NOT A FACE OF THIS ROW: SupplyUnobserved survived the region join, overflow stayed SelectionNeedsEvidence, and overflow_quota_increase_authorized stayed false. The operator half (CAX purchasability, GCP/OCI supply, control-plane siting) is not discharged by naming the neighbour.", "AND THE EMPTY POPULATION HAD TWO INDEPENDENT CAUSES WHOSE REMEDIES DIFFER, WHICH A SINGLE EMPTY VALUE CANNOT CARRY: the route facts were incomplete (a data path unread, a downstream unassessed), AND no compliance posture or sanction roster had ever been declared, so even a fully Located route would have been admitted by nothing. Reporting one when the other holds names the wrong thing to go and fix. Recorded with the miss that produced it: the lane manager twice instructed the worker to ship the empty disclosures, and the worker refused both times -- once declining to infer that no processing occurs from no admitted routes, once declining to render a boundary no permit could produce. THE WORKER WAS RIGHT AND THE INSTRUCTION WAS WRONG, and it is filed that way because an author under instruction is exactly the position from which this class is hardest to refuse.", + + "**THE FOLD THAT DISCARDS ITS ACCUMULATOR IS THIS CLASS WITH NO MISSING FILE AND NO WRONG PATH** (gunbc#11201, 2026-09-13, NAMESPACE-XL-0). Two folds one screen apart in one witness file gathered reference sites across ingested module roots as `cons: fn(acc, root) { collect(root).sites }` -- RETURNING the new value instead of appending to `acc`. Every path resolved, every file was read, the instrument reached its subject, and the census still answered over THE LAST ROOT ALONE. Every 'is absent' row in the file is a NEGATIVE claim, and a negative claim is satisfied for free by a population that never contained the subject: the readings were truthful about a corpus of one module while reading as though they covered two. The control that looked like it protected them was green BY INGEST ORDERING -- reorder the two reads and the whole census changes with no test naming why. This widens the row rather than repeating it: the three specimens above miss the subject by ADDRESSING it wrongly (a wrong path, an unread region), and here addressing is perfect and the ACCUMULATION drops it, so a reviewer checking that the instrument resolved its subject would have cleared this one.", + "**THE REMEDY THAT ACTUALLY HOLDS IS TO MAKE THE POPULATION ITSELF A SUBJECT, WHICH IS THIS ROW'S TELL TURNED INTO TWO ENROLLED ASSERTIONS.** The tell above asks for a denominator or a positive control. On this specimen the repair was exactly that, and it is cheap enough to be the standing answer for any 'is absent' family: one witness PINS THE COUNT the census speaks for (it must cover every ingested root, not some), and one requires the collection to be TOTAL, so a subject that could not be read can never be the reason an absence row is green. Both are assertions about the POPULATION rather than about the finding, and either one reds on the acc-discard while every original absence row stays green. The second is only expressible because the same change made the lost-subject case a typed, counted refusal instead of a silent skip -- an absence row cannot be defended while the instrument is allowed to drop subjects quietly.", + "**HARM MEASURED, AND IT LEFT THE FILE: TWO OF THESE READINGS WERE EXPORTED TO SIBLING LANES AS MEASURED DEFICIENCIES BEFORE BEING RETRACTED.** The XL-3 lane was holding type-position census fixtures RED on one of them and the XL-4 lane carried a type-position row on its declared frontier. A false absence that stays in its own file costs its author a review round; one that is reported as a finding becomes a premise other lanes build on, and DESIGN section 5 names fabricated plausible output rather than incomplete measurement. THE OPERATIONAL RULE THIS SPECIMEN ADDS: a negative result is not exportable until the population it was measured over is itself asserted -- and if it has already been exported, RE-DERIVING it is owed to the lanes that consumed it rather than a correction they are left to notice.", + "**BOUNDED AGAINST TWO NEIGHBOURS THAT AROSE IN THE SAME FILE AND ARE NOT THIS CLASS, recorded because a reviewer grouped all four as one and the grouping does not hold.** A spelling match that found `Bool` in an `import` line and was read as a TYPE POSITION is a FALSE POSITIVE from a predicate too coarse to separate two sources -- the instrument reached its subject and answered about the wrong one, so it is the dual of this row and shares no repair. And 'a bare same-module name reaches the collector', reported as though it covered cross-module references, is a TRUE reading over-generalized past its evidence -- DESIGN section 4d's second arm, an assertion outrunning the variables it cites. Three mechanisms, three repairs: assert the population; sharpen the predicate; state the claim at the grain it was measured. Filing them as one class would have bought one row and lost two repairs.", ], evidence: [], diff --git a/dag/gunbc/recurring_failure_mode/shared_precondition_re_derived_once_per_claim_frame.dag b/dag/gunbc/recurring_failure_mode/shared_precondition_re_derived_once_per_claim_frame.dag index b70a1f47ecf..2680e5b463f 100644 --- a/dag/gunbc/recurring_failure_mode/shared_precondition_re_derived_once_per_claim_frame.dag +++ b/dag/gunbc/recurring_failure_mode/shared_precondition_re_derived_once_per_claim_frame.dag @@ -27,6 +27,8 @@ data shared_precondition_re_derived_once_per_claim_frame: RecurringFailureMode = "ITS MEASUREMENT SHARPENS THE ROW'S GRAIN, and is the reason it is filed here rather than left in a PR. Four probe claims under claim_batch over roots dag and src/v2, one per hypothesis: the keyed read at 1ms, the whole-pool walk at 3628ms, one guarded call at 4392ms, and FOUR guarded calls inside ONE claim frame at 15420ms. The last figure is the informative one -- four times one, linearly -- so the precondition was re-derived once per CALL and shared at no grain, not even within the single frame the evaluator does memoize across. That is the same narrowing the second specimen reported per parse call, now measured additively rather than inferred, and it says a producer share keyed per claim frame would have addressed only the smaller half of this instance.", "ITS REPAIR IS THE ONE THIS ROW PRESCRIBES, taken at the seam where the fact is already resolved: v2.std.decl_index type_declarer_qualified_names answers the bare-name question against the SAME memoized declaration pool decl_facts_at already reads, marshalling no declaration nodes -- which is where the whole-pool cost actually lived. The nine claims that cost 3.6s each then cost 1-3ms each. Recorded with the boundary that admitted it, because the boundary is what keeps the repair from founding a new defect: the host returns EVERY candidate and never chooses among them, so the multiplicity and the candidate identities are decided in the substrate and a bare-name identity defect is not reintroduced one layer below the one being removed.", + "XL-4 SPECIMEN, gunbc#11202. Two claim files -- v2.test.claim.reference_derived_graph_call_arg_tree and v2.test.claim.reference_derived_graph_production_ingest -- re-derived the same parse-and-normalize ingest once per claim frame. Floor run 34730467598: verdict=FloorRefused, interrupted_before_verdict=23, ENROLMENT-MARGIN-REFUSED at the 500ms ceiling. Hoisting into module-scope data rows does not help (the claim frame is narrower than the file). The repair is one warm producer, v2.test.claim.reference_derived_graph_fixture.xl4_fixture_trees, consumed by both files. The seam is the ingest, not the collector: the claims name the collector and the edge fold.", + "THIRD SPECIMEN, gunbc#11201, and what it ADDS is that THE TWO NEAREST-MISS REPAIRS BOTH WEAR THIS DOCUMENT'S OWN VOCABULARY. The family is the NAMESPACE-XL-0 production-route probes in v2.test.claim.namespace_xl0.call_argument_mention_survival, each driving a real parse-and-normalize of two inline fixture modules; the floor returned budget_interrupted / right_censored at the per-claim CPU deadline with nothing failing, recognised from the floor's own per-claim cost artifact required_floor_claim_cost.tsv rather than from the lane summary. The first repair attempted was to hoist the chain into module-scope `data` rows, and it is worth recording because it is not a lazy move: DESIGN section 2 says to share a repeated pure demand at its least common ancestor, the ancestor here reads as the FILE, and a `data` row is exactly the substrate's share-at-the-file construct. It changed nothing, because the repetition is not within the file's evaluation -- it IS the evaluation, repeated, and the claim frame is narrower than the ancestor the rule directs you to. An author reasoning correctly from section 2 alone lands on this and gets an identical artifact. The second near-miss is the lane re-home this row already calls wrong, with a further reason specific to it: relocating under long/ cannot help a CHANGED file at all, since changed-witness selection plans it regardless of cadence. The repair was this row's prescribed one -- warm enrolment in v2.workflow.floor_pure_producer_share -- and the seam choice is the part worth carrying: that roster keeps normalize OUT so every claim still executes the stage it names, and these claims name the COLLECTOR, so the shared value is the ingest and the reference-site walk stays per claim. Sharing one stage further would have bought the green by handing each claim a precomputed answer to the question it asks.", "WHAT THE DIAGNOSTIC OFFERED AND WHY BOTH ARMS WERE WRONG, recorded because two readers took them in turn and neither questioned the frame. The refusal named exactly two remedies -- reduce the cost, or move the row to a lane declaring its own ceiling -- and a cost ladder showed the first unreachable, since the cheapest possible precondition was already 1.45x the line. That made the second arm look forced, and it is worse than it looks: the only off-floor home in the tree is a namespace the floor's own authority describes as NOT COVERED by anything, so routing there would have executed the rows nowhere and greened the gate over four unobserved claims. A diagnostic that enumerates its remedies teaches its reader that the enumeration is exhaustive; here the repair was in neither arm, and the reason is that both arms are about what the cost is ALLOWED to be while the defect was how many times it was paid.", diff --git a/dag/gunbc/recurring_failure_mode/stale_claim_survives_its_own_correct_edit.dag b/dag/gunbc/recurring_failure_mode/stale_claim_survives_its_own_correct_edit.dag index b4581bcaaa7..0f0ed1d17dd 100644 --- a/dag/gunbc/recurring_failure_mode/stale_claim_survives_its_own_correct_edit.dag +++ b/dag/gunbc/recurring_failure_mode/stale_claim_survives_its_own_correct_edit.dag @@ -69,6 +69,12 @@ data stale_claim_survives_its_own_correct_edit: RecurringFailureMode = Recurring "**AND SECTION 4c BOUNDS THE CARRIER, NOT THE DETECTABILITY.** While a fact lives in an annotation it is unreadable to any fold, so one remedy is available regardless of sub-case: move the fact into a typed carrier and it becomes foldable. That is what happened to the fifth receipt -- the open map-dedup obligation was parked in a source comment with a dissolution condition, section 4c puts a status with a dissolution condition in a typed carrier, and it moved into the drop row where that walk's other cost shapes are already folded. A per-fact migration is not a mechanism anyone builds once, so it does not retire this class; it removes one fact from the class's reach.", + "**FOUR INSTANCES IN ONE PULL REQUEST IN NINE HOURS, AND THE SHAPE THEY SHARE IS A PARTIAL RETRACTION** (gunbc#11201, 2026-09-13, NAMESPACE-XL-0). Each was one author correcting one claim and leaving a SECOND carrier of the same claim standing, and each was caught by the next review rather than by the edit: (1) the collector was fixed while the fixture-green delivery claim it falsified stayed; (2) the section 4b(3) trigger was corrected in two carriers while THE INSTRUMENT THOSE CARRIERS TELL THE READER TO RE-RUN kept contradicting them; (3) the delivery RECEIPT was withdrawn while the delivery KIND stayed enrolled in the required roster, so a withdrawn concept still had a live constructor; (4) a repoint was written into a NarrativeOnly String while the typed carrier beside it stayed stale. A fifth followed in the same PR after this receipt was drafted: two status carriers both said 'a type-position name reaches' after the PR's own instrument had split parameter position from field position.", + + "**WHY THE PARTIAL RETRACTION IS THE EXPENSIVE SUB-CASE AND DESERVES ITS OWN RECOGNITION RULE.** An ordinary stale claim is a sentence nobody revisited. A partial retraction is a sentence the author DID revisit, in the same hour, with the correct fact in hand -- so every instinct that would catch a forgotten claim reports clean. The author knows the old claim is dead; what they do not know is how many places asserted it. THE RULE, and it is executable in one command: WHEN YOU WITHDRAW A CLAIM, GREP THE CLAIM'S VOCABULARY BEFORE COMMITTING THE WITHDRAWAL, and treat the withdrawal as unfinished while any hit remains -- the delivery kind, the label arm, the required roster, the cited instrument, the sibling carrier, the narrative String. Retracting is N edits, and the author is the one person positioned to know N. The tell for a reviewer is a diff that REMOVES an assertion and touches exactly one file.", + + "**THIS IS ALSO THE STRONGEST EVIDENCE THIS ROW HAS FOR ITS OWN NEXT-RUNG TRIGGER, AND THAT IS THE REASON IT IS FILED RATHER THAN FIXED FOUR TIMES.** The trigger below says nothing MECHANICAL makes the join today. Four consecutive reviews made it BY HAND on one PR, each finding a different surviving half, which prices the manual wall exactly: it works, it is staffed by reviewers, and it costs one review round per instance. The author fixed all four instances individually and filed the specimen against a DIFFERENT row -- the cost row -- before filing this one, which is itself the failure this class describes applied to the ledger: the cheap graduation was taken and the expensive one was left as instances. Recorded at the author's own cost so the next reader sees the ratio rather than the anecdotes.", + "**RECEIPT, THE STAGE0 MIRRORS AS HAND-SYNCED TWINS.** `v1.compiler.runtime_rust` -- the template that emits `v1_rt.rs` -- carried three claims calling the stage0 mirrors HAND-SYNCED: the trace_mark dissolution trigger named `v1_compiler_infer_method.rs` a `hand-synced twin` and `v1_compiler_compile.rs` a `hand-synced` counterpart, and the phase-render divergence note called the compile path a `hand-synced path`. True when written. Falsified by a correct edit elsewhere: the generated-artifact gate landed a `stage0-mirrors` population that REGENERATES and byte-compares those files, so they are emitted and gated, not hand-synced. Nothing in the citing artifact changed at that moment. The class is exactly this row, and the cost was paid by a later lane: bright-bear-236 hand-edited `v1_compiler_compile.rs` on #11072 -- doing what the surviving comment said was the maintenance route -- and was refused with `generated surface drift: v1_compiler_compile.rs`. So the stale claim did not merely misinform, it ROUTED an author into the refusal. The fix was made at the EMITTER (`src/v1/runtime_rust.dag`) and the mirror regenerated, because the artifact carrying the false claim is itself generated -- correcting it in the `.rs` would have been the same refused edit.", "SPECIMEN, AN ANNOTATION ABOUT A NEIGHBOUR MECHANISM, WHICH IS STRICTLY WORSE THAN AN ANNOTATION ABOUT ITS OWN. `gunbc.bare_name_fork_lens` leading `//` block asserts, as the design rationale for why the floor is the backstop: `A per-entry compile contains ONE of them, so the call resolves and the entry reports clean; the floor's whole-corpus preparation contains both, and the same call fails to resolve.` Quoted with backticks from the annotation, not restated. THAT SENTENCE IS FALSE OF THE FLOOR. The producer is `v1.compiler.cli_run` `assemble_prepared_subject_closure` (required-floor assemble on a clean tree, no changed-witness seeds). Identity-level observation, not a count: `test.claim.fabric.common_paper_csa_agreement_witness` is present in that function's `full_inventory` and ABSENT from its prepared keep set. There is no whole-corpus preparation. The lens as a reader can still take `v2.std.decl_index` `decl_facts` pool roots. MERGE-PATH STATUS OF THAT LENS, SETTLED: (1) the required lane does not reach `floor_global_invariants_recomputed` -- `required_floor_runner` has no occurrence of it, and `gunbc.incremental_floor_authority` states no production consumer exists because the required floor is whole-corpus today (`gunbc.witness_floor_workflow`). (2) even that fold does not PERFORM the check: it is `all` over `floor_global_invariants` of `floor_global_invariant_discharged(results: attempt.global_invariants, row: row)`, and discharge is `recomputed_at_head && passed` on a caller-supplied list. `test.claim.bare_name_fork_lens_witness_test` is on `required_gate_prefixes` (`test.claim.bare_name_`) and drives the folds over AUTHORED fixture facts via `bare_name_fork_standing_over`, not live-corpus `decl_facts`. `tools.bare_name_fork_check` remains one subject, not floor-wired. A green floor cannot tell `lens ran` from `lens never computed`. What is false is the STATED REASON why the floor catches the residue. DESIGN section 4c: an annotation is never evidence that a machine claim holds. This one is about a NEIGHBOUR -- nothing in the lens can check the floor's keep-set size, and nothing in the floor knows the lens describes it -- so it rots with no owner. Falsified only because someone measured the neighbour for an unrelated question. THIS DOES NOT EXTEND THE RECOGNITION RULE; it is the rule: `when prose asserts a fact whose subject lives in ANOTHER file`. The subject is `assemble_prepared_subject_closure`'s keep set; the claim lives in the lens file. Gate-bounded prepare is recorded in that function's own comments as of 2026-08-29; the lens specimen it cites is gunbc#9213 (2026-08-25). Nothing in the lens file had to change for the sentence to go false.", diff --git a/dag/gunbc/seed_growth_admission.dag b/dag/gunbc/seed_growth_admission.dag index d064371ff50..e796a1d8a1f 100644 --- a/dag/gunbc/seed_growth_admission.dag +++ b/dag/gunbc/seed_growth_admission.dag @@ -23,6 +23,7 @@ import gunbc.emitted_closure_compile_seed_growth { emitted_closure_compile_seed_ import gunbc.exit_failure_outcome_seed_growth { exit_failure_outcome_seed_growth_justification } import gunbc.evaluation_budget_falsifier_seed_growth { evaluation_budget_falsifier_seed_growth_justification } import gunbc.namespace_structural_observation_bridge_seed_growth { namespace_structural_observation_bridge_seed_growth_justification } +import gunbc.emit_rust_reference_derived_rows_bridge_seed_growth { emit_rust_reference_derived_rows_bridge_seed_growth_justification } import gunbc.namespace_wave_admission { namespace_wave_admission_seed_growth_justification } import gunbc.parsed_import_statement_bridge_seed_growth { parsed_import_statement_bridge_seed_growth_justification } import gunbc.parse_refusal_location_seed_growth { parse_refusal_location_seed_growth_justification } @@ -252,6 +253,7 @@ fn seed_growth_justification_roster() -> List { exit_failure_outcome_seed_growth_justification, evaluation_budget_falsifier_seed_growth_justification, namespace_structural_observation_bridge_seed_growth_justification, + emit_rust_reference_derived_rows_bridge_seed_growth_justification, namespace_wave_admission_seed_growth_justification, parsed_import_statement_bridge_seed_growth_justification, qualified_pipe_callee_seed_growth_justification, diff --git a/dag/gunbc/type_reference_decl_file_occurrence_census.dag b/dag/gunbc/type_reference_decl_file_occurrence_census.dag index 2ae896fccd7..24708669f7b 100644 --- a/dag/gunbc/type_reference_decl_file_occurrence_census.dag +++ b/dag/gunbc/type_reference_decl_file_occurrence_census.dag @@ -438,8 +438,21 @@ data type_reference_decl_file_adjacent_findings: List = [ // the authority arriving, which is exactly the condition that row named. The two CorrectAsPosition // classes are unchanged and were never debt. The sibling-fallback class dissolved with the helper. // -// WHAT IS NOT DISCHARGED: CorpusDeclared still carries a path matched by contains, so the surviving -// arm answers WHAT a declaration realizes as positionally. That is the residue both decided classes +// WHAT IS NOT DISCHARGED HERE, AND WHERE IT WAS DISCHARGED INSTEAD (XL-0B/C, 2026-09-12). +// CorpusDeclared still carries a path matched by contains, so on the v1 route the surviving arm +// answers WHAT a declaration realizes as positionally. THE DeclarationRef CARRIER THE ROW ABOVE +// ASKS FOR NOW EXISTS, ON THE v2 ROUTE: std.repair_input_origin RepairInputDeclarationProvenance +// carries the declaration as a DeclarationRef and nothing positional, filled by +// v2.compiler.repair_input_origin_roster from the resolver's own answers -- so the deferral that +// row records against std.repair_input_origin is closed. +// +// THE v1 POSITION IS NOT CONVERTED AND WILL NOT BE. Holding both a DeclarationRef and a decl_file +// for one declaration is the two-identities fork this census exists to warn about, and converting +// the v1 arm would be building on a route scheduled for deletion -- DESIGN section 3's replacement +// migration doctrine prices an intermediate representation destined to be discarded as redundant +// work. THE RETIREMENT TRIGGER IS THEREFORE THE DELETION OF v1.compiler.emit_rust AND ITS CLOSURE, +// not a conversion and not a later carrier edit: the position dies with the only route that reads +// it. That is the residue both decided classes // named, and its successor is the key v1.compiler.infer_env global_bare_fallback_invariant already // declares. This carrier's own dissolution condition is likewise NOT satisfied by the discharge: it // names a derived lens, and a hand roster that has been repaired is still a hand roster. diff --git a/dag/gunbc/v1/v1_interpreter_primitive_surface.dag b/dag/gunbc/v1/v1_interpreter_primitive_surface.dag index 109c2a2c317..3801c1aeb9c 100644 --- a/dag/gunbc/v1/v1_interpreter_primitive_surface.dag +++ b/dag/gunbc/v1/v1_interpreter_primitive_surface.dag @@ -1226,6 +1226,15 @@ fn v1_interpreter_authored_roster_arms() -> List = [ whole_corpus_compile_public_root_demand, + whole_corpus_compile_xl1_fixture_root_demand, ] // THE JOIN. A root with no MeasuredForRoot row in the roster is UnmeasuredRoot -- never the nearest diff --git a/dag/std/declaring_identity_spelling.dag b/dag/std/declaring_identity_spelling.dag new file mode 100644 index 00000000000..f30a75b958a --- /dev/null +++ b/dag/std/declaring_identity_spelling.dag @@ -0,0 +1,108 @@ +module std.declaring_identity_spelling + +import std.types { Bool } +import std.decl_ref { DeclarationRef, decl_ref } +import std.dissolution { DissolutionCondition, retires_dissolution } +import v2.std.algebra { is_prefix_of, list_reverse } +import v2.std.qualified_name { QualifiedName } + +// XL-3: whether one mention is spelled as the identity that declared its target. +// Canonical spelling is the SymbolIndex path (v2.std.symbol_index), the same qualified +// projection 03_resolve already uses. This module does not walk trees and does not collect +// sites. Producer consumes v2.compiler.reference_site_collector's +// ReferenceSiteCollection (.sites plus .unreadable_roots) and refuse to treat the +// census as complete unless reference_site_collection_is_total. Do not add a second +// collector or a parse-tree walker. +// +// WHAT PRODUCTION INGEST ACTUALLY SEES is measured by +// v2.test.claim.declaring_identity_spelling.production_ingest and +// v2.test.claim.namespace_xl0.call_argument_mention_survival: +// SURVIVES as sites (unusable for requalification): a BARE value not inside a +// call; a parameter reference; a BARE type name in PARAMETER position. +// DOES NOT: a BARE type name in FIELD position (separate from qualification); +// names inside calls (body-lowering, eager-raven / #11207); +// QUALIFIED/dotted references in any position (dotted-reference gap, not lowering); +// kernel types, which have no corpus declaration. +// A qualified field type is absent for two independent reasons and cannot +// discriminate either class. +// A bare same-module name resolves inside its own module, so it is not the XL-3 +// population. The usable class is the qualified cross-module mention, absent with +// no call anywhere; a trigger naming only body-lowering (#11207) does not cover it. + +// ResolvedSpelling.declaring is consumed TODAY from +// v2.compiler.repair_input_origin_roster carrier_provenance (RepairInputDeclared). +// That DeclarationRef is spelling-derived (owner-prefix drop + dotted render) and is a +// DECLARED FRONTIER on that producer -- repair_input_declared_binding_frontier_dissolve_on. +// This census inherits that frontier: when that row retires, this field is DERIVED from +// std.occurrence_binding OccurrenceBindingResult over ScopedOccurrenceRef (gunbc#11264's +// surviving authority) and must never be a third minted identity here. canonical is +// ProvenanceResolved.target and is unaffected. +data declaring_identity_spelling_declared_binding_frontier_dissolve_on: DissolutionCondition = retires_dissolution( + ref: decl_ref( + module_path: "v2.compiler.repair_input_origin_roster", + decl_name: "repair_input_declared_binding_frontier_dissolve_on" + ) +) + +type UnresolvableCause + = IdentityAmbiguous + | IdentityUnbound + | IdentityOwnerless + +type ResolvedPathVerdict + = SpelledCanonically + | SpelledShorter + | ResolvedAuthoredNotOnCanonicalPath + +type DeclaringIdentitySpelling + = ResolvedSpelling { + authored: QualifiedName + declaring: DeclarationRef + canonical: QualifiedName + path_verdict: ResolvedPathVerdict + } + | UnresolvableSpelling { + authored: QualifiedName + cause: UnresolvableCause + } + +fn authored_is_suffix_of_canonical(authored: QualifiedName, canonical: QualifiedName) -> Bool { + is_prefix_of( + prefix: list_reverse(xs: authored), + xs: list_reverse(xs: canonical), + eq: fn(a, b) { a == b } + ) +} + +fn resolved_path_verdict(authored: QualifiedName, canonical: QualifiedName) -> ResolvedPathVerdict { + if authored == canonical { + SpelledCanonically + } else if authored_is_suffix_of_canonical(authored: authored, canonical: canonical) { + SpelledShorter + } else { + ResolvedAuthoredNotOnCanonicalPath + } +} + +fn declaring_identity_spelling_resolved( + authored: QualifiedName, + declaring: DeclarationRef, + canonical: QualifiedName +) -> DeclaringIdentitySpelling { + ResolvedSpelling { + authored: authored, + declaring: declaring, + canonical: canonical, + path_verdict: resolved_path_verdict(authored: authored, canonical: canonical) + } +} + +fn declaring_identity_spelling_unresolvable( + authored: QualifiedName, + cause: UnresolvableCause +) -> DeclaringIdentitySpelling { + UnresolvableSpelling { + authored: authored, + cause: cause + } +} diff --git a/dag/std/primitives.dag b/dag/std/primitives.dag index e8f9c969c23..677d7fb7589 100644 --- a/dag/std/primitives.dag +++ b/dag/std/primitives.dag @@ -634,6 +634,7 @@ fn builtin_registry_surface_names() -> List { "parsed_import_statements", "floor_discovery_source_inventory", "namespace_structural_observation_admissions", + "emit_rust_reference_derived_rows_bridge", "witness_layer_roots_compile_clean_check", "witness_layer_roots_compile_clean_emit_check", "install_or_consume_floor_compile_clean_gate_receipt", diff --git a/dag/std/repair_input_origin.dag b/dag/std/repair_input_origin.dag index 48463a0a69b..0eaefd6930e 100644 --- a/dag/std/repair_input_origin.dag +++ b/dag/std/repair_input_origin.dag @@ -1,6 +1,7 @@ module std.repair_input_origin import std.types { String, List } +import std.decl_ref { DeclarationRef } // XL-0A splits the emitter's six candidate-bearing inputs BEFORE their historical string union. // The source branch is deliberately named Candidate rather than DeclarationCarrier: XL-0B/C will @@ -19,6 +20,91 @@ type SourceCarrierOrigin type RenderedTypeSurfaceOrigin {} +// --------------------------------------------------------------------------------------------- +// XL-0B/C: THE DeclarationCarrier HALF THE HEADER ABOVE DEFERS, LANDED ON THE v2 ROUTE. +// +// WHAT CHANGED SINCE THE DEFERRAL. The header says claiming a DeclarationRef here would require +// an emitter-side registry reconstruction, and that was true of the route it was written for: the +// six channels above are collectors internal to v1.compiler.emit_rust's Rust use-line planner, and +// that planner is the only place on the v1 route where references were ever enumerated. The v2 +// route enumerates them where they actually live -- v2.compiler.reference_site_collector walks the +// containment tree and v2.compiler.resolution_provenance resolves each mention through the same +// symbol index the live resolver uses, answering with the module that CONTAINS the target. No +// registry is reconstructed because none is consulted: the declaration is the resolver's own +// answer. +// +// THE TWO CARRIERS ARE SEPARATELY TYPED OVER ONE BASE, which is what the XL-0 stage label demands. +// A source-declaration carrier names a mention in authored source and the declaration that +// answered it. A rendered target-vocabulary carrier names a token that exists only in a target's +// rendered vocabulary and has no source declaration to name. They are different facts with +// different repairs, so a union of their spellings -- which is what the compatibility projection +// below still is, for the v1 route's lifetime -- cannot tell them apart. +// +// THE v1 ARM SURVIVES AND IS FROZEN. SourceCarrierCandidate stays exactly as XL-0A authored it and +// stays consumed by v1.compiler.emit_rust. It is not a rival of the arm below: it is the same +// question asked where the only available answer was a spelling, on a route scheduled for +// deletion, and it retires with that route rather than by a conversion. + +// PROVENANCE: A DECLARED ANSWER CARRIES ITS DECLARATION, AND THE THREE WAYS OF NOT HAVING ONE ARE +// THREE FACTS. +// +// THIS DIVERGES FROM std.coercion TypeDeclarationProvenance, DELIBERATELY, AND HERE IS THE REASON +// (DESIGN section 3b admits a stated departure and refuses only a silent one). Three departures, +// each with its own cause: +// +// 1. CorpusDeclared carries `decl_file: String` -- A POSITION. +// gunbc.type_reference_decl_file_occurrence_census names that as the undischarged and larger +// half of its repair, and a carrier holding BOTH a DeclarationRef and a decl_file would give +// one fact two identities, which is the section 3 fork the census exists to warn about. So +// the declared arm here carries the DeclarationRef and nothing positional. The v1 position +// is NOT converted: it retires when v1.compiler.emit_rust is deleted. +// +// 2. KernelMinted HAS NO PRODUCER ON THIS ROUTE. The kernel-minted arm is obliged to derive from +// the exact-equality kernel identity predicate rather than a prefix test, and that minter -- +// v1.std.core kernel_span -- exists only on the v1 route; no v2 module mints a kernel span. +// An arm with no producer is permanently uninhabited, which DESIGN section 4b calls a +// decoration rather than a weak wall, and worse than absent because it would be cited as +// coverage. What the v2 route can establish exactly is the neighbouring fact: a target that +// resolves through the symbol index while NO DECLARATION IDENTITY CAN BE MINTED FOR IT. Two +// structural facts produce that, and they are one arm because they are one fact for a repair: +// no rostered module contains the target, or the target IS a module and names no declaration +// inside one. Both are derived by v2.compiler.resolution_provenance provenance_owner_of_target, +// by containment-prefix over the module roster -- an exact structural test, never a prefix +// test on a name -- so the state is carried under its own name rather than borrowed under the +// kernel's. +// +// 3. DeclarationIdentityAbsent CONFLATES TWO STATES WITH DIFFERENT REPAIRS. A mention the +// resolver could not bind at all and a mention it could bind two ways are not one fact: the +// first is repaired by a declaration or a spelling, the second only by disambiguation, and a +// roster that reported them as one number would hide which. Two states, two arms. +type RepairInputDeclarationProvenance + = RepairInputDeclared { declaring: DeclarationRef } + | RepairInputTargetWithoutDeclarationIdentity { target_spelling: String } + | RepairInputIdentityAmbiguous + | RepairInputIdentityAbsent + +// THE MENTION, ITS POSITION AND WHAT ANSWERED IT -- AND NOTHING ABOUT WHETHER IT SHOULD BE +// REPAIRED. The XL-0 stage label says this denominator is taken BEFORE eligibility or repair +// disposition, so there is no eligibility field to set and no disposition arm to pick: a consumer +// that wants a narrower population derives it from these rows and owns its own filter. +// +// `reference_position` is the mention's CONTAINMENT CHAIN -- the module qualified name followed by +// the declaration path the mention sits under -- which is what makes two mentions of one name in +// one module two rows rather than one. THERE IS NO SEPARATE referencing-module FIELD, and its +// absence is the point: the module is the longest rostered module prefix of this chain, so a +// second field carrying it would be the same fact stored twice (DESIGN section 2) and would then +// need a fabricated answer for a position no roster covers. Every consumer of this denominator +// holds the module roster already -- the producer builds the roster and the carrier from the same +// roots -- so the module is DERIVED where it is wanted rather than carried where it can drift. +// +// The module that ANSWERED the mention is not here either: it is inside the provenance, where it +// cannot be misread as a property of the site. +type SourceDeclarationCarrierIdentity { + reference_position: String + authored_spelling: String + provenance: RepairInputDeclarationProvenance +} + type SourceCarrierCandidateIdentity { emitting_module: String candidate_spelling: CandidateSpelling @@ -34,6 +120,7 @@ type RenderedTargetVocabularyIdentity { type RepairInputOriginCandidate = SourceCarrierCandidate { identity: SourceCarrierCandidateIdentity } | RenderedTargetVocabularyCarrier { identity: RenderedTargetVocabularyIdentity } + | SourceDeclarationCarrier { identity: SourceDeclarationCarrierIdentity } fn candidate_spelling_from_text(name: String) -> CandidateSpelling { let segments = name |> split(delimiter: ".") @@ -108,6 +195,7 @@ fn repair_input_origin_candidate_name(candidate: RepairInputOriginCandidate) -> QualifiedCandidate { authored_qualifier, member } => concat(authored_qualifier, ".", member) } RenderedTargetVocabularyCarrier { identity } => identity.rendered_identifier + SourceDeclarationCarrier { identity } => identity.authored_spelling } } @@ -118,6 +206,9 @@ fn repair_input_origin_compatibility_names(candidates: List, ) -> List { @@ -136,6 +227,7 @@ fn qualified_item_emit_surface_compatibility_names( VariantPayloadSurfaceOrigin => [] } RenderedTargetVocabularyCarrier { identity: _ } => [] + SourceDeclarationCarrier { identity: _ } => [] } ) } diff --git a/dag/test/claim/compiler_frontend_program_status_witness_test.dag b/dag/test/claim/compiler_frontend_program_status_witness_test.dag index da3f7e3b4ad..2ebca133b21 100644 --- a/dag/test/claim/compiler_frontend_program_status_witness_test.dag +++ b/dag/test/claim/compiler_frontend_program_status_witness_test.dag @@ -53,6 +53,7 @@ import gunbc.namespace_cut_stage { StageXL0Denominator, StageXL1BaselineCapture, StageXL2RootDeletionRehearsal, + StageXL3DeclaringIdentitySpelling, StageXL4ReferenceDerivedGraph, StageAct0ActivationGate, stage_prerequisites, @@ -571,13 +572,19 @@ test fn no_subject_is_scheduled_for_the_waves_and_xl5_is_not_derivable_from_the_ && standing_is(want: ClassNotDerivable, s: stage_status(s: StageXL5Waves)) } -// F1 -- XL-0 IS THE REPAIR-INPUT ORIGIN DENOMINATOR AND NOTHING ELSE ANSWERS IT. +// F1 -- XL-0 IS THE REPAIR-INPUT ORIGIN DENOMINATOR, AND IT MAY NOT READ CLEAR OFF AN INSTRUMENT +// THAT IS EMPTY ON THE CORPUS. // -// The arm this replaced read the subject roster's unobservable host probes, so making every host -// probe observable would have flipped XL-0 to CLEAR while no repair-input origin roster had been -// produced. That is the falsifier stated as a rule: XL-0's standing may not be a function of probe -// observability at all. Asserting NOT-DERIVABLE with this exact cause holds it, because a rewiring -// back onto any observable population would have to abandon the cause to change the standing. +// THIS PROBE HAS NOW BEEN FALSIFIED TWICE AND BOTH FALSIFICATIONS ARE THE SAME RULE. The original +// arm read gunbc.namespace_cut_subject_roster's unobservable host probes, so repairing probe +// observability would have flipped XL-0 while no denominator existed. A later arm -- landed on this +// branch and withdrawn on it -- read a STAGE DELIVERY RECEIPT, which was earned against hand-built +// Node trees while the producer returned NO sites over the tree production actually yields. Both +// made XL-0's standing a function of something that is not the denominator. +// +// So the assertion is NOT-DERIVABLE with this exact cause, which is the one statement that survives +// both: a rewiring onto any other observable population has to abandon the cause to move the +// standing, and a receipt re-landed before the producer answers non-empty reds this witness. test fn xl0_is_not_derivable_and_awaits_the_repair_input_origin_producer() -> Bool { standing_is(want: ClassNotDerivable, s: stage_status(s: StageXL0Denominator)) && any(stages_awaiting(i: RepairInputOriginRosterProducer), @@ -585,12 +592,22 @@ test fn xl0_is_not_derivable_and_awaits_the_repair_input_origin_producer() -> Bo && count(milestones_awaiting(i: RepairInputOriginRosterProducer)) == 0 } +// XL-3 stays NotDerivable while the usable class -- qualified cross-module +// mentions -- is invisible on the production ingest route. Bare PARAMETER +// type names are not that class: they reach. Bare FIELD type names are a +// fourth missing class, not a dotted case, and are also not the usable class. +test fn xl3_is_not_derivable_while_qualified_cross_module_mentions_are_invisible() -> Bool { + standing_is(want: ClassNotDerivable, s: stage_status(s: StageXL3DeclaringIdentitySpelling)) + && any(stages_awaiting(i: DeclaringIdentitySpellingCensus), + l => l == namespace_cut_stage_label(s: StageXL3DeclaringIdentitySpelling)) +} + // F2 -- XL-1 IS THE CAPABILITY, THE BASELINE MILESTONE IS THE BASE-SPECIFIC FACT, AND THEY ARE NOT // THE SAME QUESTION. XL-1 used to delegate to NamespaceBaselineObservationComplete outright, which // made "the capture transaction can succeed" and "a capture has been taken against THIS base" one // row. They separate exactly on the CaptureAvailable arm: the stage clears (its deliverable is the -// capability) while the milestone reads persisted_legacy_baseline_outstanding (unpinned live pin, -// so outstanding until ACT-0 names a base). This arm asserts the contract on whichever arm is live. +// capability) while the milestone reads persisted_legacy_baseline_outstanding (production pin +// unpinned until ACT-0 names a base). This arm asserts the contract on whichever arm is live. test fn xl1_follows_the_capability_while_the_baseline_milestone_follows_the_base() -> Bool { match legacy_baseline_capture_capability() { CaptureBlocked { phase: p, cause: c } => diff --git a/dag/test/claim/decl_fact_value_projection_witness_test.dag b/dag/test/claim/decl_fact_value_projection_witness_test.dag index e365a392866..9c28e450cc8 100644 --- a/dag/test/claim/decl_fact_value_projection_witness_test.dag +++ b/dag/test/claim/decl_fact_value_projection_witness_test.dag @@ -1,11 +1,11 @@ module test.claim.decl_fact_value_projection_witness import v2.std.decl_index { DeclFact, decl_facts_at } -import v2.std.fn_index { atom_identities_in_node, fn_index_symbol_eq } +import v2.std.fn_index { atom_identities_in_node } import v2.std.algebra { contains, fold_list, for_all, length, list_snoc_item } import v2.std.collection { List } import v2.std.logic { Bool } -import v2.std.node { Symbol } +import v2.std.node { Symbol, symbol_eq } import v2.std.text { String } // WHAT THIS FILE MEASURES. A consumer that asks "which declarations name v1" keys on the @@ -45,7 +45,7 @@ fn same_atoms(a: String, b: String) -> Bool { let xs = atoms_at(qn: a) let ys = atoms_at(qn: b) (length(xs: xs) == length(xs: ys)) - && for_all(xs: xs, predicate: fn(s) { contains(xs: ys, item: s, eq: fn_index_symbol_eq) }) + && for_all(xs: xs, predicate: fn(s) { contains(xs: ys, item: s, eq: symbol_eq) }) } fn distinct_values_project_distinct_atoms(a: String, b: String) -> Bool { diff --git a/dag/test/claim/legacy_baseline_capture_witness_test.dag b/dag/test/claim/legacy_baseline_capture_witness_test.dag index 64293143780..aca855790da 100644 --- a/dag/test/claim/legacy_baseline_capture_witness_test.dag +++ b/dag/test/claim/legacy_baseline_capture_witness_test.dag @@ -49,11 +49,13 @@ import v2.workflow.legacy_baseline_capture { LegacyBaselineRepairRosterMalformed, LegacyBaselineRepairSubjectDiverged, LegacyBaselineExecutionRefused, + LegacyBaselineObservedTransportRefused, subject_field_label, legacy_baseline_capture_capability, CaptureBlocked, CaptureAvailable } +import v2.workflow.legacy_repair_observation { repair_subject_field_label } data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly @@ -239,6 +241,7 @@ fn lbc_run( LegacyBaselineRepairSubjectDiverged { field: f } => concat("repair-subject-diverged:", repair_subject_field_label(f: f) as String) LegacyBaselineRepairIncomplete { completeness: _ } => "repair-incomplete" LegacyBaselineExecutionRefused { phase: _, cause: _ } => "execution-refused" + LegacyBaselineObservedTransportRefused { refusal: _ } => "observed-transport-refused" } } } @@ -450,10 +453,18 @@ test fn a_roster_whose_identity_is_not_the_subject_digest_refuses_as_repair_rost } } -test fn the_reported_capability_is_blocked_until_a_live_repair_tap_exists() -> Bool { +// THE CAPABILITY REPORTS EXECUTED EVIDENCE: it read CaptureBlocked while the Observed arm had no +// required route (reviews 66841, 66891), and flipped to CaptureAvailable on the receipt of that +// arm executing on the required floor over the measured fixture root (gunbc#11461 run +// 35181521483). This is the former expecting-red probe turned permanent regression control +// (DESIGN 4b(4)): it reads the constant, and the controls that make the constant honest are +// a_measured_fixture_root_reaches_the_observed_arm_with_rows_and_bindings and +// the_live_census_over_the_measured_fixture_root_counts_its_rows in +// test.claim.legacy_repair_tap_live_bridge_witness - delete the Observed arm and THOSE red. +test fn the_reported_capability_is_available_because_the_observed_arm_executes_on_the_required_floor() -> Bool { match legacy_baseline_capture_capability() { - CaptureAvailable => false - CaptureBlocked { phase: _, cause: _ } => true + CaptureAvailable => true + CaptureBlocked { phase: _, cause: _ } => false } } diff --git a/dag/test/claim/legacy_baseline_persisted_observation_witness_test.dag b/dag/test/claim/legacy_baseline_persisted_observation_witness_test.dag index 1be1e024bd4..d4787746686 100644 --- a/dag/test/claim/legacy_baseline_persisted_observation_witness_test.dag +++ b/dag/test/claim/legacy_baseline_persisted_observation_witness_test.dag @@ -46,7 +46,8 @@ import v2.workflow.legacy_baseline_capture { LegacyBaselineRepairRosterMismatch, LegacyBaselineRepairSubjectDiverged, LegacyBaselineRepairIncomplete, - LegacyBaselineExecutionRefused + LegacyBaselineExecutionRefused, + LegacyBaselineObservedTransportRefused } import v2.workflow.legacy_baseline_persisted_observation { persist_legacy_baseline, @@ -203,6 +204,7 @@ fn lbp_minted_capture_persisted() -> Bool { LegacyBaselineRepairSubjectDiverged { field: _ } => false LegacyBaselineRepairIncomplete { completeness: _ } => false LegacyBaselineExecutionRefused { phase: _, cause: _ } => false + LegacyBaselineObservedTransportRefused { refusal: _ } => false } } } @@ -213,7 +215,7 @@ test fn persist_binds_only_to_the_capture_base_commit() -> Bool { lbp_minted_capture_persisted() } -test fn live_outstanding_is_the_enrollment_fold_with_no_held_capture() -> Bool { +test fn live_outstanding_is_the_enrollment_fold_with_unpinned_production_pin() -> Bool { match current_pre_cut_base_pin() { PreCutBasePinned { base: _ } => false PreCutBaseUnpinned => diff --git a/dag/test/claim/legacy_repair_observation_witness_test.dag b/dag/test/claim/legacy_repair_observation_witness_test.dag index 2f4b409960e..d3f1c9a2e05 100644 --- a/dag/test/claim/legacy_repair_observation_witness_test.dag +++ b/dag/test/claim/legacy_repair_observation_witness_test.dag @@ -271,7 +271,7 @@ test fn an_observation_taken_on_another_base_refuses_against_a_proven_roster() - proven: p ) { RepairObservationSubjectDiverged { field: f } => - (repair_subject_field_label(f: f) as String) == (repair_subject_field_label(f: RepairSemanticSourceDigestField) as String) + f == RepairSemanticSourceDigestField RepairObservationAdmitted { admitted: _ } => false RepairObservationRefused { completeness: _ } => false } diff --git a/dag/test/claim/legacy_repair_tap_live_bridge_witness_test.dag b/dag/test/claim/legacy_repair_tap_live_bridge_witness_test.dag new file mode 100644 index 00000000000..568aea4c4bb --- /dev/null +++ b/dag/test/claim/legacy_repair_tap_live_bridge_witness_test.dag @@ -0,0 +1,128 @@ +module test.claim.legacy_repair_tap_live_bridge_witness + +import std.types { String, Bool, List, list_length } +import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } +import std.content_hash { structural_content_hash } +import std.decl_ref { decl_ref } +import gunbc.whole_corpus_compile_admission { whole_corpus_compile_repository } +import gunbc.whole_corpus_compile_demand_projection { whole_corpus_compile_demand_projection_path } +import extdeps.git.object_store { git_sha1_object_id } +import v2.workflow.legacy_binding_observation { + LegacyBindingObservationSubject, + ImportScopedPolicy +} +import v2.workflow.legacy_baseline_capture { + materialization_receipt, + tree_derived_subject +} +import v2.workflow.legacy_baseline_persisted_observation { + PersistAdmitted, + PersistRefusedNotCaptured +} +import v2.workflow.legacy_repair_tap { + Xl1PrimaryRootTap, + Xl1PrimaryRootObserved, + Xl1PrimaryRootRefused, + xl1_live_repair_tap_census, + xl1_live_repair_tap_census_of, + Xl1LiveRepairTapRows, + Xl1LiveRepairTapUnavailable, + persist_named_base_from_primary_root_tap +} + +// Discriminating RED for the PrimaryRoot tap (review 64801): empty source_roots must refuse +// inside the seed arm, not mint an Observed encoding. Executes emit_rust_reference_derived_rows_bridge. +data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree + +// THE OBSERVED ARM'S POSITIVE CONTROL, ON THE REQUIRED FLOOR. The tap asks the same per-root +// admission as the compile transaction (gunbc.whole_corpus_compile_admission, #11265), and the +// XL-4 fixture root with dag/std as its pool is a MEASURED root +// (whole_corpus_compile_xl1_fixture_root_demand, authored from its measurement receipt), so +// the admission that refused every earlier control (gunbc#11461 runs 35074340220, +// 35079253040 - a whole-corpus constant sized for the largest root) now admits this subject on +// its own row. The tap over that root is a nullary PREPARED EFFECT INPUT +// (v2.workflow.floor_pure_producer_share floor_cross_claim_prepared_effect_inputs): the floor +// acquires it once at preparation, so no claim pays the compile, and the Observed encoding it +// stores is what the two claims below read. Deleting the Observed arm of +// compile_xl1_primary_root_tap in src/v1/stage0/src/cli_run/emit_host.rs turns them red; +// deleting the fixture root's measured row turns them red at admission (review 67146). +fn xl1_fixture_root_tap() -> Xl1PrimaryRootTap { + emit_rust_reference_derived_rows_bridge( + ["dag/test/fixture/reference_derived_graph", "dag/std"], + whole_corpus_compile_repository as String, + whole_corpus_compile_demand_projection_path() + ) +} + +test fn a_measured_fixture_root_reaches_the_observed_arm_with_rows_and_bindings() -> Bool { + match xl1_fixture_root_tap() { + Xl1PrimaryRootRefused { cause: _ } => false + Xl1PrimaryRootObserved { + primary_root: root, + repair_rows: rows, + occurrence_transport: _, + binding_rows: bindings + } => + list_length(items: rows) > 0 + && list_length(items: bindings) > 0 + && root == "dag/test/fixture/reference_derived_graph" + } +} + +test fn the_live_census_over_the_measured_fixture_root_counts_its_rows() -> Bool { + match xl1_live_repair_tap_census_of(tap: xl1_fixture_root_tap()) { + Xl1LiveRepairTapUnavailable { cause: _ } => false + Xl1LiveRepairTapRows { count: n } => n > 0 + } +} + +test fn empty_source_roots_refuse_the_xl1_primary_root_tap() -> Bool { + match emit_rust_reference_derived_rows_bridge([], whole_corpus_compile_repository as String, whole_corpus_compile_demand_projection_path()) { + Xl1PrimaryRootRefused { cause: c } => string_contains(s: c, pattern: "empty") + Xl1PrimaryRootObserved { + primary_root: _, + repair_rows: _, + occurrence_transport: _, + binding_rows: _ + } => false + } +} + +test fn empty_source_roots_do_not_tally_as_zero_rows() -> Bool { + match xl1_live_repair_tap_census([]) { + Xl1LiveRepairTapUnavailable { cause: c } => string_contains(s: c, pattern: "empty") + Xl1LiveRepairTapRows { count: _ } => false + } +} + +fn lrt_live_subject() -> LegacyBindingObservationSubject { + LegacyBindingObservationSubject { + semantic_source_digest: structural_content_hash(digest: "1111111111111111"), + source_set_digest: structural_content_hash(digest: "2222222222222222"), + compiler_artifact_digest: structural_content_hash(digest: "3333333333333333"), + resolver_identity: decl_ref(module_path: "v1.compiler.infer_env", decl_name: "lookup_binding_by_name"), + resolver_policy: ImportScopedPolicy, + occurrence_transport_digest: structural_content_hash(digest: "4444444444444444"), + declaration_index_digest: structural_content_hash(digest: "5555555555555555") + } +} + +test fn empty_source_roots_refuse_named_base_persist_through_the_tap() -> Bool { + match git_sha1_object_id(hex: "1007efb256a20749f77c3b1295eed144fddeb9fd") { + Absent => false + Present { value: a } => match git_sha1_object_id(hex: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") { + Absent => false + Present { value: t } => + match persist_named_base_from_primary_root_tap( + materialization: materialization_receipt( + requested: a, observed_head: a, observed_tree: t, commit_tree: t + ), + tree_subject: tree_derived_subject(tree: t, subject: lrt_live_subject()), + source_roots: [] + ) { + PersistRefusedNotCaptured => true + PersistAdmitted { persisted: _ } => false + } + } + } +} diff --git a/dag/test/claim/legacy_repair_tap_persisted_capture_witness_test.dag b/dag/test/claim/legacy_repair_tap_persisted_capture_witness_test.dag new file mode 100644 index 00000000000..f81fea8b69d --- /dev/null +++ b/dag/test/claim/legacy_repair_tap_persisted_capture_witness_test.dag @@ -0,0 +1,192 @@ +module test.claim.legacy_repair_tap_persisted_capture_witness + +import std.types { String, Bool, List, NonEmptyStr, SourceSpan } +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } +import std.content_hash { structural_content_hash } +import std.decl_ref { decl_ref } +import extdeps.git.object_store { git_sha1_object_id } +import std.occurrence_identity { + OccurrenceId, + OccurrenceIndex, + OccurrenceIndexEntry, + OccurrenceProjection, + OccurrenceContainmentPath, + LexicalValueOccurrence, + DeclarationOccurrence, + ReferenceOccurrence, + OccurrenceTransport, + OccurrenceTransportValidated, + OccurrenceTransportRefused, + occurrence_transport_validate +} +import v2.workflow.legacy_binding_observation { + LegacyBindingObservation, + LegacyBindingObservationRow, + LegacyBindingObservationSubject, + ImportScopedPolicy +} +import v2.workflow.legacy_baseline_capture { + materialization_receipt, + tree_derived_subject +} +import v2.workflow.legacy_baseline_persisted_observation { + PersistAdmitted, + PersistRefusedNotCaptured, + persisted_against_requested +} +import gunbc.reference_derived_candidate { + ReferenceDerivedCandidateRow, + CandidateOwnModule, + CandidateRegistryAbsent +} +import v2.workflow.legacy_repair_tap { + BridgeRowsAdmitted, + BridgeRowsRefused, + admit_bridge_rows, + persist_capture_from_bridge_rows, + never_emitted_declared_modules, + repair_emitted_module_names +} + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +type LrtBinding + = LrtBound + | LrtUnbound + +fn lrt_span() -> SourceSpan { + SourceSpan { file: "legacy-repair-tap-persist-fixture.dag", start: 1, end: 2 } +} + +fn lrt_path() -> OccurrenceContainmentPath { + OccurrenceContainmentPath { ancestors: [OccurrenceId { value: 900 }], terminal: OccurrenceId { value: 10 } } +} + +fn lrt_commit() -> String { "1007efb256a20749f77c3b1295eed144fddeb9fd" } +fn lrt_tree() -> String { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } + +fn lrt_rows() -> List { + [ + ReferenceDerivedCandidateRow { + module_name: "std.logic", + name: "Bool", + disposition: CandidateOwnModule + } + ] +} + +fn lrt_subject() -> LegacyBindingObservationSubject { + LegacyBindingObservationSubject { + semantic_source_digest: structural_content_hash(digest: "1111111111111111"), + source_set_digest: structural_content_hash(digest: "2222222222222222"), + compiler_artifact_digest: structural_content_hash(digest: "3333333333333333"), + resolver_identity: decl_ref(module_path: "v1.compiler.infer_env", decl_name: "lookup_binding_by_name"), + resolver_policy: ImportScopedPolicy, + occurrence_transport_digest: structural_content_hash(digest: "4444444444444444"), + declaration_index_digest: structural_content_hash(digest: "5555555555555555") + } +} + +test fn roster_from_bridge_rows_is_the_same_row_tautology() -> Bool { + match admit_bridge_rows(rows: lrt_rows()) { + BridgeRowsRefused { malformed: _ } => false + BridgeRowsAdmitted { roster: roster, rows: rows } => + (roster.sites |> count) == 1 + && (rows |> count) == 1 + && (roster.sites |> any(s => s.module_name == ("std.logic" as NonEmptyStr) && s.name == ("Bool" as NonEmptyStr))) + } +} + +test fn persist_capture_from_bridge_rows_admits_a_complete_same_row_observation() -> Bool { + match git_sha1_object_id(hex: lrt_commit()) { + Absent => false + Present { value: a } => match git_sha1_object_id(hex: lrt_tree()) { + Absent => false + Present { value: t } => + match occurrence_transport_validate(transport: OccurrenceTransport { + index: OccurrenceIndex { entries: [ + OccurrenceIndexEntry { + projection: OccurrenceProjection { + occurrence: OccurrenceId { value: 900 }, + authored_name: "root", + diagnostic_span: lrt_span() + }, + containment: OccurrenceContainmentPath { ancestors: [], terminal: OccurrenceId { value: 900 } } + }, + OccurrenceIndexEntry { + projection: OccurrenceProjection { + occurrence: OccurrenceId { value: 10 }, + authored_name: "r", + diagnostic_span: lrt_span() + }, + containment: lrt_path() + } + ] }, + declarations: [DeclarationOccurrence { + occurrence: OccurrenceId { value: 900 }, + containment: OccurrenceContainmentPath { ancestors: [], terminal: OccurrenceId { value: 900 } }, + category: LexicalValueOccurrence, + diagnostic_span: lrt_span() + }], + references: [ReferenceOccurrence { + occurrence: OccurrenceId { value: 10 }, + containment: lrt_path(), + category: LexicalValueOccurrence, + diagnostic_span: lrt_span() + }] + }) { + OccurrenceTransportRefused { refusal: _ } => false + OccurrenceTransportValidated { transport: tr } => + match persist_capture_from_bridge_rows( + materialization: materialization_receipt( + requested: a, observed_head: a, observed_tree: t, commit_tree: t + ), + tree_subject: tree_derived_subject(tree: t, subject: lrt_subject()), + observation: LegacyBindingObservation { + subject: lrt_subject(), + rows: [LegacyBindingObservationRow { occurrence: OccurrenceId { value: 10 }, outcome: LrtBound }] + }, + transport: tr, + rows: lrt_rows() + ) { + PersistRefusedNotCaptured => false + PersistAdmitted { persisted: p } => persisted_against_requested(persisted: p, requested: a) + } + } + } + } +} + +// THE DISCRIMINATING RED FOR THE DROP ARM (review 66826 on gunbc#11461): a bridge row with an +// empty spelling must REFUSE the whole admission, located by index, not vanish from the roster +// and the observation. A well-formed sibling in the same batch does not rescue it - the +// admission is all-or-nothing, because the roster digest attests the whole census. +test fn empty_name_row_refuses_the_admission_located_by_index() -> Bool { + let rows = [ + ReferenceDerivedCandidateRow { + module_name: "std.logic", + name: "Bool", + disposition: CandidateRegistryAbsent + }, + ReferenceDerivedCandidateRow { + module_name: "", + name: "Bool", + disposition: CandidateRegistryAbsent + } + ] + match admit_bridge_rows(rows: rows) { + BridgeRowsAdmitted { roster: _, rows: _ } => false + BridgeRowsRefused { malformed: m } => + (m |> count) == 1 && (m |> any(r => r.index == 1 && r.module_name == "" && r.name == "Bool")) + } +} + +test fn never_emitted_is_declared_modules_absent_from_the_emitter_walk() -> Bool { + let emitted = repair_emitted_module_names(rows: lrt_rows()) + let never = never_emitted_declared_modules( + declared_modules: ["std.logic", "std.not.emitted"], + emitted_modules: emitted + ) + (never |> any(m => m == "std.not.emitted")) && !(never |> any(m => m == "std.logic")) +} + diff --git a/dag/test/claim/match_exhaustiveness_coproduct_witness_test.dag b/dag/test/claim/match_exhaustiveness_coproduct_witness_test.dag index ea89b3604ca..d0154ad4326 100644 --- a/dag/test/claim/match_exhaustiveness_coproduct_witness_test.dag +++ b/dag/test/claim/match_exhaustiveness_coproduct_witness_test.dag @@ -295,3 +295,113 @@ test fn w_variant_named_in_type_position_is_judged_against_its_parent_roster() - test fn w_variant_type_position_covering_the_parent_roster_is_clean() -> Bool { non_exhaustive_blocking_count(source: variant_type_position_parent_covered_source) == 0 } + +// -- ONE IDENTITY FOR THE DECLARED CONSTRUCTOR AND THE PATTERN -- +// +// A coproduct arm may be authored with a DOTTED name -- `type T = a.b.Alpha | Beta` -- because +// parse_type_body_after_eq takes the first arm through parse_dotted_ident, shared with the +// type-alias lookahead. The child's authored name is then the whole dotted spelling, and two +// separate sites compared it against a pattern name that had been reduced to its leaf while the +// child had not: the coverage key in pattern_matches_constructor, which lost its declaration-side +// application in the nested-pattern matrix rewrite, and the three variant-lookup sites in +// lookup_variant_in_type, which never had one. The first reported the arm missing; the second +// refused the bare pattern with VariantNotFound. Both are the same identity applied to one side. +// +// THE REDUCTION IS THE WHOLE SOURCE, and the two class-scoped controls beneath it say which site +// closes which half -- so a repair of one alone cannot green this section and be mistaken for a +// repair of the class. Every arm is named in both directions: the negative differs from the +// positive by exactly the omitted `Beta`. + +data dotted_declared_arm_source: String = "module dotted_decl_covered\ntype T = a.b.Alpha | Beta\nfn f(t: T) -> Bool {\n match t {\n Alpha => true\n Beta => false\n }\n}\n" + +data dotted_declared_arm_missing_source: String = "module dotted_decl_missing\ntype T = a.b.Alpha | Beta\nfn f(t: T) -> Bool {\n match t {\n Alpha => true\n }\n}\n" + +data dotted_later_arm_source: String = "module dotted_decl_later_arm\ntype T = Alpha | a.b.Beta\nfn f(t: T) -> Bool {\n match t {\n Alpha => true\n Beta => false\n }\n}\n" + +fn single_source_run(path: String, source: String) -> MultiModuleCompileFixtureOutcome { + compile_fixture(MultiModuleCompileFixture { + sources: [fixture_source(path, source)], + entry: path + }) +} + +fn fixture_all_blocking_count(o: MultiModuleCompileFixtureOutcome) -> Int { + match o { + FixtureCompileRefused { module_count: _, diagnostics: rows, source_digest: _, compiler_digest: _ } => + census_total_count(rows: fixture_blocking_rows(rows: rows)) + FixtureCompileCompleted { module_count: _, emitted_files: _, resolved_rust_functions: _, diagnostics: rows, source_digest: _, compiler_digest: _ } => + census_total_count(rows: fixture_blocking_rows(rows: rows)) + FixtureInstrumentRefused { cause: _ } => -1 + } +} + +test fn w_dotted_declared_arm_covered_by_bare_patterns_compiles_clean() -> Bool { + fixture_all_blocking_count( + o: single_source_run(path: "dotted/covered.dag", source: dotted_declared_arm_source) + ) == 0 +} + +test fn w_dotted_declared_arm_is_not_reported_missing() -> Bool { + fixture_blocking_class_count( + o: single_source_run(path: "dotted/covered.dag", source: dotted_declared_arm_source), + wanted: "NonExhaustiveMatch" + ) == 0 +} + +test fn w_bare_pattern_resolves_against_a_dotted_declared_arm() -> Bool { + fixture_blocking_class_count( + o: single_source_run(path: "dotted/covered.dag", source: dotted_declared_arm_source), + wanted: "VariantNotFound" + ) == 0 +} + +// THE NEGATIVE. Keying both sides must not make a real gap disappear: omitting `Beta` from the +// same declaration still refuses, and with exactly one missing arm rather than a widened roster. +test fn w_dotted_declaration_with_a_genuinely_missing_arm_still_refuses() -> Bool { + fixture_blocking_class_count( + o: single_source_run(path: "dotted/missing.dag", source: dotted_declared_arm_missing_source), + wanted: "NonExhaustiveMatch" + ) == 1 +} + +// THE REACHABILITY BOUNDARY, recorded rather than repaired. Only the FIRST arm of the +// no-leading-pipe form reaches parse_dotted_ident; parse_more_variants_acc takes every later arm +// through expect_ident, so a dotted arm in second position refuses at parse. That refusal is a +// parser fact this change does not touch, and it is the reason the subject above is written with +// the dotted arm first. It is asserted as a REFUSAL, not as an exhaustiveness count: a parse +// refusal and a clean compile both report zero rows of any later class. +test fn w_dotted_arm_in_later_position_refuses_at_parse() -> Bool { + fixture_all_blocking_count( + o: single_source_run(path: "dotted/later.dag", source: dotted_later_arm_source) + ) > 0 +} + +// -- A LEAF KEY THAT TWO DECLARED ARMS SHARE REFUSES, IT DOES NOT PICK ONE -- +// +// Keying by leaf makes `a.b.Alpha | Alpha` possible, which exact-name matching could not produce: +// one bare `Alpha` arm now keys equal to BOTH declared children. Measured against the first-match +// revision of find_variant_child_keyed, this source compiles CLEAN -- the bare arm binds the first +// child and the match is called exhaustive while the second declared variant is unhandled. That is +// the failure arm widening instead of refusing, inside the very function whose annotation declares +// the collision unresolved. find_variant_child_keyed therefore treats more-than-one as no-match, +// which the call sites carry into the existing variant_not_found_result rather than a minted +// ambiguity spelling. +// +// THE SHAPE IS CONSTRAINED BY WHAT PARSES, and the first draft of this witness got it wrong in the +// direction that hides: `a.b.Alpha | c.d.Alpha` is green under BOTH revisions, because +// parse_more_variants_acc takes every arm after the first through expect_ident, so the second +// dotted arm refuses at parse and the collision is never reached. A witness over that source is +// permanently green and would stand as coverage for an arm it never exercises. The dotted name +// must therefore be FIRST and the colliding one bare. +// +// THIS IS THE DECLARED FRONTIER'S ARM, NOT ITS CLOSURE. Distinguishing the two variants needs the +// scope-carrying identity the namespace program is converging on; until that lands the honest +// answer is a refusal, and this witness is what keeps it a refusal. + +data colliding_leaf_declaration_source: String = "module colliding_leaf_decl\ntype T = a.b.Alpha | Alpha\nfn f(t: T) -> Bool {\n match t {\n Alpha => true\n }\n}\n" + +test fn w_two_declared_arms_sharing_a_leaf_key_refuse_rather_than_bind_the_first() -> Bool { + fixture_all_blocking_count( + o: single_source_run(path: "dotted/collide.dag", source: colliding_leaf_declaration_source) + ) > 0 +} diff --git a/dag/test/claim/root_demand_measurement_witness_test.dag b/dag/test/claim/root_demand_measurement_witness_test.dag index 4c1911ef103..9ef47564815 100644 --- a/dag/test/claim/root_demand_measurement_witness_test.dag +++ b/dag/test/claim/root_demand_measurement_witness_test.dag @@ -12,6 +12,8 @@ import gunbc.whole_corpus_compile_admission { MeasuredForRoot, UnmeasuredRoot, whole_corpus_compile_public_root, + whole_corpus_compile_xl1_fixture_root, + whole_corpus_compile_xl1_fixture_root_demand, } import gunbc.root_demand_measurement { RootDemandMeasurementLimitReading, @@ -169,3 +171,41 @@ test fn a_kill_a_refusal_or_a_missing_census_never_authors_a_row() -> Bool { } exceeded && nonzero && signalled && no_census } + +// THE XL-1 FIXTURE ROW IS THE CONSTRUCTOR'S OUTPUT OVER ITS RECEIPT, NOT A HAND-TYPED NUMBER. +// gunbc.whole_corpus_compile_admission whole_corpus_compile_xl1_fixture_root_demand cannot call +// measured_for_root_from_receipt (that module is upstream of this one), so this claim replays the +// receipt the row cites - completed, exit 0, census 14 sources / 73093 bytes, peak 278921216 - +// through the constructor and checks the authored row's identity, census and grain peak against +// the result. Retype the peak by hand and this reds. +test fn the_xl1_fixture_row_is_the_constructor_output_over_its_receipt() -> Bool { + let run = RootDemandMeasurementRun { + root: whole_corpus_compile_xl1_fixture_root, + limit: byte_size(33578549248), + limit_source: "cgroup memory.max (/sys/fs/cgroup/)" as NonEmptyStr, + measured_on_host: "60e1d18cada1" as NonEmptyStr, + instrument_run: "gunbc measure-root-demand" as NonEmptyStr, + census: CensusReported { census: WholeCorpusCompileSourceCensus { source_count: 14, source_bytes: SourceBytesRecorded { bytes: byte_size(73093) } } }, + } + match measured_for_root_from_receipt( + root: whole_corpus_compile_xl1_fixture_root, + receipt: MeasurementCompleted { run: run, exit_status: 0, peak: byte_size(278921216) }, + measured_on: "2026-09-17" as NonEmptyStr, + evidence: evidence(), + ) { + MeasuredRowAuthored { demand: d } => match d { + MeasuredForRoot { root: r, census: c, peak: p, receipt: _ } => + match whole_corpus_compile_xl1_fixture_root_demand { + MeasuredForRoot { root: ar, census: ac, peak: ap, receipt: _ } => + byte_size_count(b: p) == byte_size_count(b: ap) + && c.source_count == ac.source_count + && r.primary_root == ar.primary_root + UnmeasuredRoot { root: _ } => false + } + UnmeasuredRoot { root: _ } => false + } + MeasuredRowRefusedReceiptForAnotherRoot { root: _, receipt_root: _ } => false + MeasuredRowRefusedLowerBound { limit: _, why: _ } => false + MeasuredRowRefusedRunDidNotComplete { why: _ } => false + } +} diff --git a/dag/test/fixture/reference_derived_graph/consumer_body_value.dag b/dag/test/fixture/reference_derived_graph/consumer_body_value.dag new file mode 100644 index 00000000000..4803189ce6b --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_body_value.dag @@ -0,0 +1,7 @@ +module test.fixture.reference_derived_graph.consumer_body_value + +import std.types { Int } + +fn uses() -> Int { + test.fixture.reference_derived_graph.provider.provided_value +} diff --git a/dag/test/fixture/reference_derived_graph/consumer_both.dag b/dag/test/fixture/reference_derived_graph/consumer_both.dag new file mode 100644 index 00000000000..7e9471a6f1e --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_both.dag @@ -0,0 +1,8 @@ +module test.fixture.reference_derived_graph.consumer_both + +import std.types { Int } +import test.fixture.reference_derived_graph.provider { provided_value } + +fn uses_imported_provider() -> Int { + test.fixture.reference_derived_graph.provider.provided_value +} diff --git a/dag/test/fixture/reference_derived_graph/consumer_call_only.dag b/dag/test/fixture/reference_derived_graph/consumer_call_only.dag new file mode 100644 index 00000000000..74fe3017177 --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_call_only.dag @@ -0,0 +1,9 @@ +module test.fixture.reference_derived_graph.consumer_call_only + +import std.types { Int } + +fn sink(x: Int) -> Int { x } + +fn uses_only_in_call() -> Int { + sink(x: test.fixture.reference_derived_graph.provider.provided_value) +} diff --git a/dag/test/fixture/reference_derived_graph/consumer_callee_only.dag b/dag/test/fixture/reference_derived_graph/consumer_callee_only.dag new file mode 100644 index 00000000000..e263de251f2 --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_callee_only.dag @@ -0,0 +1,7 @@ +module test.fixture.reference_derived_graph.consumer_callee_only + +import std.types { Int } + +fn uses_only_as_callee() -> Int { + test.fixture.reference_derived_graph.provider.provided_fn() +} diff --git a/dag/test/fixture/reference_derived_graph/consumer_field_bare_local.dag b/dag/test/fixture/reference_derived_graph/consumer_field_bare_local.dag new file mode 100644 index 00000000000..1b4640bba52 --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_field_bare_local.dag @@ -0,0 +1,15 @@ +module test.fixture.reference_derived_graph.consumer_field_bare_local + +import std.types { Int } + +type LocalFieldOnly + +type LocalParamMarker + +type LocalWrapper { + f: LocalFieldOnly +} + +fn uses(x: LocalParamMarker) -> Int { + 1 +} diff --git a/dag/test/fixture/reference_derived_graph/consumer_import_only.dag b/dag/test/fixture/reference_derived_graph/consumer_import_only.dag new file mode 100644 index 00000000000..cc99d908251 --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_import_only.dag @@ -0,0 +1,3 @@ +module test.fixture.reference_derived_graph.consumer_import_only + +import test.fixture.reference_derived_graph.provider { ProvidedMarker } diff --git a/dag/test/fixture/reference_derived_graph/consumer_reference_only.dag b/dag/test/fixture/reference_derived_graph/consumer_reference_only.dag new file mode 100644 index 00000000000..ebf7ec1be7c --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_reference_only.dag @@ -0,0 +1,7 @@ +module test.fixture.reference_derived_graph.consumer_reference_only + +import std.types { Int } + +fn uses_provider() -> Int { + test.fixture.reference_derived_graph.provider.provided_value +} diff --git a/dag/test/fixture/reference_derived_graph/consumer_type_bare_local.dag b/dag/test/fixture/reference_derived_graph/consumer_type_bare_local.dag new file mode 100644 index 00000000000..92c771c9fe1 --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_type_bare_local.dag @@ -0,0 +1,9 @@ +module test.fixture.reference_derived_graph.consumer_type_bare_local + +import std.types { Int } + +type LocalMarker + +fn uses(x: LocalMarker) -> Int { + 1 +} diff --git a/dag/test/fixture/reference_derived_graph/consumer_type_imported.dag b/dag/test/fixture/reference_derived_graph/consumer_type_imported.dag new file mode 100644 index 00000000000..592bac92419 --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_type_imported.dag @@ -0,0 +1,8 @@ +module test.fixture.reference_derived_graph.consumer_type_imported + +import std.types { Int } +import test.fixture.reference_derived_graph.provider { ProvidedMarker } + +fn uses(x: ProvidedMarker) -> Int { + 1 +} diff --git a/dag/test/fixture/reference_derived_graph/consumer_type_only.dag b/dag/test/fixture/reference_derived_graph/consumer_type_only.dag new file mode 100644 index 00000000000..f4c4103dce1 --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/consumer_type_only.dag @@ -0,0 +1,9 @@ +module test.fixture.reference_derived_graph.consumer_type_only + +import std.types { Int } + +fn uses( + x: test.fixture.reference_derived_graph.provider.ProvidedMarker +) -> Int { + 1 +} diff --git a/dag/test/fixture/reference_derived_graph/provider.dag b/dag/test/fixture/reference_derived_graph/provider.dag new file mode 100644 index 00000000000..87185505ede --- /dev/null +++ b/dag/test/fixture/reference_derived_graph/provider.dag @@ -0,0 +1,9 @@ +module test.fixture.reference_derived_graph.provider + +import std.types { Int } + +type ProvidedMarker + +data provided_value: Int = 1 + +fn provided_fn() -> Int { 1 } diff --git a/dag/test/probe/declaring_identity_spelling_unresolvable_probe.dag b/dag/test/probe/declaring_identity_spelling_unresolvable_probe.dag new file mode 100644 index 00000000000..7058f3a0b5a --- /dev/null +++ b/dag/test/probe/declaring_identity_spelling_unresolvable_probe.dag @@ -0,0 +1,10 @@ +module test.probe.declaring_identity_spelling_unresolvable_probe + +// THIS MODULE MUST NOT RESOLVE. It is the XL-3 declaring-identity spelling census's +// unresolvable-mention fixture: a type-position name declared nowhere, read as source by +// v2.test.claim.declaring_identity_spelling.production_ingest through the ingest route +// (never as a module in a closure), so the census's IdentityUnbound verdict has an +// authorable subject. It lives under dag/test/probe/ because the required floor's +// prepared subject excludes that roster by design (floor_prepared_subject_exclusions). + +data row: ThisNameIsNotDeclaredInThisFixture = 0 diff --git a/src/v1/04_method.dag b/src/v1/04_method.dag index edc3721c78e..920d52f4bfb 100644 --- a/src/v1/04_method.dag +++ b/src/v1/04_method.dag @@ -333,6 +333,7 @@ data builtin_function_registry: Map = { "shell_materialize_operation_argv": BuiltinSignature { params: [BuiltinParam { name: "operation", ty: NamedTemplate { name: "String" } }, BuiltinParam { name: "workspace_dir", ty: NamedTemplate { name: "String" } }, BuiltinParam { name: "files", ty: ContainerOf { source: Named { name: "List" }, element: NamedTemplate { name: "String" } } }, BuiltinParam { name: "environment", ty: ContainerOf { source: Named { name: "List" }, element: NamedTemplate { name: "String" } } }], returns: type_variable_node(id: "argv_materialization_result") }, "shell_transport_operation_rows": BuiltinSignature { params: [], returns: list_of_type_variable(id: "shell_transport_operation_row_elem") }, "namespace_structural_observation_admissions": BuiltinSignature { params: [BuiltinParam { name: "file", ty: NamedTemplate { name: "String" } }, BuiltinParam { name: "source", ty: NamedTemplate { name: "String" } }, BuiltinParam { name: "neighbour_name", ty: NamedTemplate { name: "String" } }, BuiltinParam { name: "branch_binder_name", ty: NamedTemplate { name: "String" } }, BuiltinParam { name: "later_name", ty: NamedTemplate { name: "String" } }, BuiltinParam { name: "homonym_name", ty: NamedTemplate { name: "String" } }], returns: list_of_type_variable(id: "ordinary_compile_structural_admission_elem") }, + "emit_rust_reference_derived_rows_bridge": BuiltinSignature { params: [BuiltinParam { name: "source_roots", ty: ContainerOf { source: Named { name: "List" }, element: NamedTemplate { name: "String" } } }, BuiltinParam { name: "repository", ty: NamedTemplate { name: "String" } }, BuiltinParam { name: "measured_root_demands", ty: NamedTemplate { name: "String" } }], returns: type_variable_node(id: "xl1_primary_root_tap") }, "extdeps_shape_transport_policy_facts_for_qualified_name": BuiltinSignature { params: [BuiltinParam { name: "module", ty: NamedTemplate { name: "String" } }], returns: type_variable_node(id: "extdeps_module_facts_record") }, "extdeps_qualified_name_resolves_in_derived_module_set": BuiltinSignature { params: [BuiltinParam { name: "module", ty: NamedTemplate { name: "String" } }], returns: bool_type }, "extdeps_external_authority_facts_for_qualified_name": BuiltinSignature { params: [BuiltinParam { name: "module", ty: NamedTemplate { name: "String" } }], returns: type_variable_node(id: "extdeps_external_authority_module_facts_record") }, diff --git a/src/v1/04_patterns.dag b/src/v1/04_patterns.dag index 9e4656b007f..d89e6428cb6 100644 --- a/src/v1/04_patterns.dag +++ b/src/v1/04_patterns.dag @@ -290,9 +290,9 @@ fn lookup_variant_in_type(scrut: PatternSubject, variant_name: String, module_na match symbol_index_lookup(index: env.symbol_index, qualified_name: variant_name) { Present { value: resolved } => if (resolved.connective == Disj) { - match find_child_named(n: resolved, name: qualified_last_segment(name: variant_name), source_indices: source_indices) { + match find_variant_child_keyed(n: resolved, variant_name: variant_name, source_indices: source_indices) { Present { value: variant_child } => - match find_child_named(n: expand_scrut_type_for_variant_lookup(scrut_node: scrut_node, env: env), name: qualified_last_segment(name: variant_name), source_indices: source_indices) { + match find_variant_child_keyed(n: expand_scrut_type_for_variant_lookup(scrut_node: scrut_node, env: env), variant_name: variant_name, source_indices: source_indices) { Present { value: scrut_child } => node_lookup_resolved(node: scrut_child) Absent => node_lookup_resolved(node: variant_child) } @@ -326,7 +326,7 @@ fn lookup_variant_in_type(scrut: PatternSubject, variant_name: String, module_na let optional_coproduct_subject = scrut_name == "Optional" && (variant_name == "Present" || variant_name == "Absent") - let direct_match = find_child_named(n: scrut_node, name: variant_name, source_indices: source_indices) + let direct_match = find_variant_child_keyed(n: scrut_node, variant_name: variant_name, source_indices: source_indices) let record_destructure = field_binding_count > 0 && scrut_node.connective == Conj @@ -366,11 +366,58 @@ fn lookup_field_in_variant(variant: PatternSubject, field_name: String, module_n } } +// THE KEY IS APPLIED TO BOTH SIDES OR IT IS NOT AN IDENTITY. This is the seed's incumbent +// variant-name identity -- the same bare leaf that symbol_index.global_bare is keyed on and that +// qualified_last_segment joins on throughout infer -- and it must key the DECLARED constructor +// exactly as it keys the pattern. It was authored symmetrically; the nested-pattern matrix rewrite +// kept the pattern-side application and dropped the two declaration-side ones, after which a +// declared arm carrying a dotted authored name could be covered by no pattern spelling at all and +// was reported missing under its dotted name. Every coverage comparison in the fold routes through +// pattern_matches_constructor, so keying both operands there is the whole of the matching repair; +// the absent-constructor witness cell carries the key separately because it names the gap. +// +// WHAT A LEAF-KEYED IDENTITY STILL LEAVES OPEN, so it does not stall untracked (section 4b(2)): +// two variants sharing a leaf name under different containment collide on one key. That is the +// namespace program's class, not this one's, and it is not narrowed here. Its trigger is the +// scope-carrying binding cutover answering by execution; this function is that cutover's consumer. fn variant_pattern_coverage_key(name: String) -> String { let segs = split(name, separator: ".") if segs |> count == 0 { name } else { fold(segs, init: "", f: (_, seg) => seg) } } +// VARIANT LOOKUP IS THE SAME IDENTITY QUESTION AS COVERAGE, so it is keyed by the same function on +// both sides. The three variant-lookup sites in lookup_variant_in_type each compared a name against +// a child's RAW authored name: the qualified branch reduced only the pattern, and the bare branch +// reduced neither, so a bare arm could not resolve against a child declared under a dotted authored +// name and refused with VariantNotFound -- the coverage defect one function up, one layer down. +// Unlike the coverage key that is a lost symmetry, this asymmetry is as old as the function. +// +// THIS IS DELIBERATELY NOT find_child_named. That helper also resolves FIELDS, at +// lookup_field_in_variant; keying it would make field matching leaf-keyed, which widens what a +// field name may match rather than repairing an identity, so it is left exactly as it is. +// +// AMBIGUITY REFUSES; IT DOES NOT PICK. Keying by leaf makes it possible for TWO declared children +// to key equal -- `a.b.Alpha | c.d.Alpha` -- which exact-name matching could not produce, so this +// function creates the collision and owes it an arm. Taking the first match would answer with a +// variant the source did not name, inside the very function whose annotation declares that +// collision unresolved: fail-open at the exact point the frontier is admitted. More than one match +// therefore resolves to NO match, which the three call sites already carry into +// variant_not_found_result -- a typed, located refusal in the existing vocabulary. No ambiguity +// diagnostic is minted here: the frontier is the missing scope-carrying identity, and inventing a +// spelling for it would be modeling the gap instead of refusing over it. +fn find_variant_child_keyed(n: Node, variant_name: String, source_indices: Map) -> Node? { + let key = variant_pattern_coverage_key(name: variant_name) + let matches = n.children |> filter(c => variant_pattern_coverage_key(name: authored_name_at(source_indices: source_indices, node: c)) == key) + if matches |> count > 1 { + none + } else { + match matches |> first { + Present { value: ch } => Present { value: ch } + Absent => none + } + } +} + // -- NESTED PATTERN EXHAUSTIVENESS: THE COLUMNS ARE CARRIED JOINTLY -- // // The flat fold this replaces keyed coverage on the arm HEAD alone and discarded @@ -533,7 +580,7 @@ fn pattern_row_is_irrefutable(row: List) -> Bool { fn pattern_matches_constructor(p: MatchPattern, ctor: String) -> Bool { match p { VariantPattern { name: n, parent_enum: _, field_bindings: _ } => - variant_pattern_coverage_key(name: n) == ctor + variant_pattern_coverage_key(name: n) == variant_pattern_coverage_key(name: ctor) LitPattern { value: v } => match v { LitBool { value: b } => if b { ctor == "True" } else { ctor == "False" } @@ -619,7 +666,7 @@ fn exhaustiveness_witnesses(rows: List>, columns: List, rows: default_pattern_rows(rows: rows), columns: rest_columns, env: env, module_name: module_name ) - absent_ctors |> flat_map(c => sub |> map(w => PatternWitnessRow { cells: concat([c], w.cells) })) + absent_ctors |> flat_map(c => sub |> map(w => PatternWitnessRow { cells: concat([variant_pattern_coverage_key(name: c)], w.cells) })) } else { ctors |> fold(init: [], f: (acc, c) => let fields = constructor_fields(type_node: head_type, ctor: c, env: env, module_name: module_name) diff --git a/src/v1/05_emit_rust.dag b/src/v1/05_emit_rust.dag index d30fe924cb7..f61a4fad130 100644 --- a/src/v1/05_emit_rust.dag +++ b/src/v1/05_emit_rust.dag @@ -12,6 +12,17 @@ import std.repair_input_origin { import std.primitive_projection { primitive_identity_runtime_name, primitive_projection_row_for_declaration } +import gunbc.reference_derived_candidate { + ReferenceDerivedCandidateDisposition, + CandidateSurvived, + CandidateOwnModule, + CandidateVariantDelegatedToParent, + CandidateVariantParentUnresolved, + CandidateRegistryAbsent, + CandidateLeafAmbiguous, + CandidateExportProofFailed, + ReferenceDerivedCandidateRow +} import extdeps.languages.rust.capabilities { phantom_opaque_carrier_derive_traits } @@ -4891,25 +4902,6 @@ fn local_coproduct_variant_names(items: List, source_indices: Map Result>, PrimaryRootSubjectRefusal> { + let root_prefix = workspace_relative_entry_path(root); + let mut seen: HashMap> = HashMap::new(); + let mut entry_sources: Vec> = Vec::new(); + for (module_path, source) in index.source_files.iter() { + let rel = workspace_relative_entry_path(&source.path); + if rel == root_prefix || rel.starts_with(&format!("{root_prefix}/")) { + seen.insert(module_path.clone(), source.clone()); + entry_sources.push(source.clone()); + } + } + let moduleless = match moduleless_dag_entry_paths_under_root(&root_prefix) { + Ok(paths) => paths, + Err(cause) => { + return Err(PrimaryRootSubjectRefusal { + phase: "subject-read", + cause, + }) + } + }; + report_moduleless_dag_entry_skips(&moduleless); + if entry_sources.is_empty() { + return Err(PrimaryRootSubjectRefusal { + phase: "subject-discovery", + cause: format!( + "no indexed module has a source file under the primary root '{root}' \ + -- the compile has no subject (pass a --source-root that covers it)" + ), + }); + } + entry_sources.sort_by(|a, b| a.path.cmp(&b.path)); + let import_closure = resolve_transitively_bfs_legacy(entry_sources, &index.source_files, seen); + extend_sources_to_both_closure_fixpoint(import_closure, index).map_err(|e| { + PrimaryRootSubjectRefusal { + phase: "closure-load", + cause: format!("reference-derived closure load failed: {e}"), + } + }) +} + fn compile_not_executed( subject: &CompileSubject, started: std::time::Instant, @@ -7868,137 +7935,39 @@ pub fn compile_emission(request: &CompileRequest) -> CompileRun { // and reporting it as `Completed { emitted_count: 0 }` is the empty-observation // narrow DESIGN names -- the exact shape that makes a ratchet read zero errors from // a run that compiled nothing. + // EVERY MODULE UNDER THE PRIMARY ROOT IS AN ENTRY. The derivation of that subject -- + // root-prefix filter, the module-less-`.dag` visibility step, the empty-root refusal, + // the import walk and the reference-closure fixpoint -- is ONE function, + // `primary_root_subject_closure`, because the XL-1 live tap (emit_host.rs + // `compile_xl1_primary_root_tap`) derives the same subject for the same question and a + // second copy had already drifted: it lacked the module-less step, so a `.dag` under the + // root with no `module` header would have left its closure silently (review 66847 on + // gunbc#11461; DESIGN 2/6 forked logic). Each refusal names its phase so this arm maps it + // onto compile_not_executed and the tap onto its own refusal, from one derivation. + // Both population arms name a root and derive the same subject from it. CompileSubject::PrimaryRoot(_) | CompileSubject::RootDemandMeasurement(_) => { let root = request .subject .population_root() .expect("both population arms name a root"); - let root_prefix = workspace_relative_entry_path(root); - let mut seen: HashMap> = HashMap::new(); - let mut entry_sources: Vec> = Vec::new(); - for (module_path, source) in index.source_files.iter() { - let rel = workspace_relative_entry_path(&source.path); - if rel == root_prefix || rel.starts_with(&format!("{root_prefix}/")) { - seen.insert(module_path.clone(), source.clone()); - entry_sources.push(source.clone()); - } - } - // MODULE-LESS FILES UNDER THE ROOT ARE REPORTED, NOT SILENTLY DROPPED. - // - // The subject is discovered from `index.source_files`, which is keyed by module - // path -- so a `.dag` file under the root with NO `module` declaration is not in - // the index, is not in the subject, and would vanish with the transaction - // reporting `Completed`. The empty-root arm below cannot catch it, because a root - // holding one good file and one forgotten one is not empty. - // - // That visibility existed in the pipeline this transaction replaced and the - // consolidation dropped it. It is restored here through the SAME authority that - // already owned it -- `moduleless_dag_entry_paths` / `report_moduleless_dag_entry_skips`, - // both already `pub` in this file with their own tests. An earlier revision of the - // deletion note claimed this behaviour had no counterpart in `cli_run`; that was an - // absence asserted without grepping for it, and it was false. - // - // It REPORTS rather than refuses, which is the weaker of the two arms and is - // declared as such: a module-less `.dag` is a legitimate parse fixture today, so - // refusing would break real callers. The terminal form is the total role - // classification (`RootPopulation`), under which every `.dag` carries exactly one - // role and an unclassified file refuses. Until that lands this is countable - // visibility, not a wall. - // A `.dag` THAT CANNOT BE READ IS A REFUSAL, NOT AN OMISSION. The walk's contract - // is "every `.dag` under the root", and an `if let Ok(..)` that skips an unreadable - // file narrows that to "every READABLE `.dag`" while still reporting under the - // wider name -- so a permission error or a mid-walk deletion would remove a file - // from the visibility population that exists to say which files were removed from - // the subject. That is the empty-observation narrow at the one place whose job is - // to prevent it. - let moduleless = match moduleless_dag_entry_paths_under_root(&root_prefix) { - Ok(paths) => paths, - Err(cause) => { - return compile_not_executed(&request.subject, started, "subject-read", cause) - } - }; - report_moduleless_dag_entry_skips(&moduleless); - - if entry_sources.is_empty() { - return compile_not_executed( - &request.subject, - started, - "subject-discovery", - format!( - "no indexed module has a source file under the primary root '{root}' \ - -- the compile has no subject (pass a --source-root that covers it)" - ), - ); - } - entry_sources.sort_by(|a, b| a.path.cmp(&b.path)); - let import_closure = - resolve_transitively_bfs_legacy(entry_sources, &index.source_files, seen); - // THEN THE REFERENCE CLOSURE, FOR THE SAME REASON THE ENTRY ARM USES IT. - // - // The import-edge walk alone was wrong here, and the assumption that made it look - // right is worth stating because it is nearly true: when every module under the - // root is already an entry, reference derivation can only over-pull WITHIN the - // root. That holds inside the root and fails at the POOL boundary. This corpus - // resolves most cross-module references with no import line at all, so a module - // under the root that names a type or fn in a pool module has NO edge to walk, the - // provider stays census-only -- a name for lookup, no definition for emit -- and - // the compile refuses with `unresolved type` or `function not found in scope` - // against a module that is present and correct. - // - // Measured on the specimen that produced this fix: compiling `src/v2` with `dag` as - // the pool refused with 36 blocking diagnostics, of which 16 were exactly this -- - // `ContextAccess` and `StringLiteral` in `dag/extdeps/github/expressions.dag`, - // `run_bootstrap_witness` in `dag/gunbc/instruments/bootstrap_witness_transport.dag`, - // `KvmObservedScreen` in `dag/gunbc/os_install_deduction.dag`, every one of them a - // live module the walk could not reach. They are not 16 defects; they are one - // closure being derived from the wrong relation. - // - // `extend_sources_to_both_closure_fixpoint` is the SAME function the entry arm - // calls -- bare-reference closure and pool-reference closure iterated to a - // fixpoint -- so the two subjects now derive their closures by one relation - // instead of two that had to agree by luck. That they did not agree is what this - // repair is: DESIGN's namespace Rule-1 reasoning applied to the arm that was left - // out of it. - match extend_sources_to_both_closure_fixpoint(import_closure, &index) { + match primary_root_subject_closure(&index, root) { Ok(closure) => closure, - Err(e) => { - return compile_not_executed( - &request.subject, - started, - "closure-load", - format!("reference-derived closure load failed: {e}"), - ); + Err(PrimaryRootSubjectRefusal { phase, cause }) => { + return compile_not_executed(&request.subject, started, phase, cause); } } } }; - let closure_modules: std::collections::HashSet = closure - .iter() - .filter_map(|s| extract_module_path(&s.content)) - .collect(); - // Everything indexed and outside the closure enters the NAME CENSUS only. This is - // what makes the transaction see a parse break anywhere under the source roots, and - // membership is keyed on MODULE PATH rather than file path because the closure loader - // and the index normalize paths differently -- a file-path compare would fail to - // exclude closure modules and double-load them into the census. - let mut census_only: Vec> = index - .source_files - .iter() - .filter( - |(module_path, _): &(&String, &Rc)| { - !closure_modules.contains(*module_path) - }, - ) - .map(|(_, source)| source.clone()) - .collect(); - census_only.sort_by(|a, b| a.path.cmp(&b.path)); - let census_modules = census_only.len(); + // what makes the transaction see a parse break anywhere under the source roots. ONE + // derivation, shared with the required floor and the XL-1 tap: + // compile_clean_census_only_sources_for_compiled keys membership on MODULE PATH + // because the closure loader and the index normalize paths differently (review 67039 + // on gunbc#11461: this arm and the tap each carried a copy, and the copies had already + // drifted from the helper in sort order). + let options = compile_clean_pipeline_options_for_sources(Some(&index), &closure); + let census_modules = options.census_only_sources.len(); - let options = Rc::new(v1_compiler_compile::CompilePipelineOptions { - analyze_complexity: false, - census_only_sources: Rc::new(census_only.into()), - }); // RESOLVE ONCE, EMIT N TIMES. `compile_sources_with_options` is literally // `emit_resolved_for_target ∘ compile_to_resolved_with_options`, so the single-target // path through this pair is the same computation it was before multi-target routing -- diff --git a/src/v1/stage0/src/cli_run/emit_host.rs b/src/v1/stage0/src/cli_run/emit_host.rs index 7410b8e170d..b5a08e68989 100644 --- a/src/v1/stage0/src/cli_run/emit_host.rs +++ b/src/v1/stage0/src/cli_run/emit_host.rs @@ -697,6 +697,39 @@ pub fn compile_dag_reference_occurrence_binding_census( }; }; + match observed_occurrence_transport_and_bindings(graph.as_ref()) { + ObservedOccurrenceBindingHalves::Refused { cause } => { + ReferenceOccurrenceBindingCensus::Refused { cause } + } + ObservedOccurrenceBindingHalves::Ready { + denominator, + observations, + .. + } => ReferenceOccurrenceBindingCensus::Observed { + source_digest, + compiler_digest, + denominator, + observations, + }, + } +} + +pub(crate) enum ObservedOccurrenceBindingHalves { + Ready { + transport: Rc, + denominator: Vec, + observations: Vec, + }, + Refused { + cause: String, + }, +} + +/// Seed-observed occurrence transport (per-module sidecars concatenated as stored) plus the +/// occurrence-grain binding walk over that same transport. Callers must not rebuild containment. +pub(crate) fn observed_occurrence_transport_and_bindings( + graph: &v1_compiler_compile::ResolvedGraph, +) -> ObservedOccurrenceBindingHalves { use crate::std_occurrence_binding_candidates as candidates; use crate::std_occurrence_identity as identity; let mut entries = Vec::new(); @@ -757,7 +790,7 @@ pub fn compile_dag_reference_occurrence_binding_census( index.clone() } other => { - return ReferenceOccurrenceBindingCensus::Refused { + return ObservedOccurrenceBindingHalves::Refused { cause: format!("reference binding census: candidate index refused: {other:?}"), } } @@ -789,8 +822,8 @@ pub fn compile_dag_reference_occurrence_binding_census( .get(&reference.occurrence.value) .cloned() else { - return ReferenceOccurrenceBindingCensus::Refused { - cause: format!( + return ObservedOccurrenceBindingHalves::Refused { + cause: format!( "reference binding census: occurrence {} is in the references view with no \ recorded consumer module; the walk that fills both changed under this instrument", reference.occurrence.value @@ -798,7 +831,7 @@ pub fn compile_dag_reference_occurrence_binding_census( }; }; let Some(authored_name) = names.get(&reference.occurrence.value).cloned() else { - return ReferenceOccurrenceBindingCensus::Refused { + return ObservedOccurrenceBindingHalves::Refused { cause: format!( "reference binding census: occurrence {} is in the references view with no \ entry in the occurrence index, so it has no authored spelling", @@ -844,7 +877,7 @@ pub fn compile_dag_reference_occurrence_binding_census( .iter() .find(|module| module.type_env.module_path == consumer_module) else { - return ReferenceOccurrenceBindingCensus::Refused { + return ObservedOccurrenceBindingHalves::Refused { cause: format!( "reference binding census: consumer module '{consumer_module}' \ carries occurrence {} but is absent from the resolved graph, so \ @@ -887,9 +920,8 @@ pub fn compile_dag_reference_occurrence_binding_census( disposition, }); } - ReferenceOccurrenceBindingCensus::Observed { - source_digest, - compiler_digest, + ObservedOccurrenceBindingHalves::Ready { + transport, denominator, observations, } @@ -1366,3 +1398,138 @@ pub fn transport_script_position_facts_for_path( } facts } + +/// Host body of the one XL-1 builtin `emit_rust_reference_derived_rows_bridge`. +/// Not a builtin spelling, CLI flag, or second compile entry: only that interpreter arm calls it. +#[derive(Debug, Clone)] +pub(crate) enum Xl1PrimaryRootTap { + Refused { + cause: String, + }, + Observed { + primary_root: String, + repair_rows: Rc>>, + occurrence_transport: Rc, + binding_rows: Vec, + }, +} + +pub(crate) fn compile_xl1_primary_root_tap( + source_roots: &[String], + repository: &str, + measured_root_demands: &str, +) -> Xl1PrimaryRootTap { + if source_roots.is_empty() { + return Xl1PrimaryRootTap::Refused { + cause: "xl1 primary-root tap: source_roots is empty".to_string(), + }; + } + let root = source_roots[0].clone(); + // THE ROOT DEMAND IS DECLARED BY THE CALLER, exactly as `gunbc compile` receives it on + // argv: the repository identity and the projection path are repository facts + // (gunbc.whole_corpus_compile_admission whole_corpus_compile_repository, + // gunbc.whole_corpus_compile_demand_projection), so the .dag caller names them and the + // tap borrows no identity. Admission is then the SAME whole-root admission the compile + // transaction asks, on the root's own measured row (#11265). + let request = CompileRequest { + subject: CompileSubject::PrimaryRoot(root.clone()), + source_roots: source_roots.to_vec(), + primary_precedence: false, + render_targets: vec![crate::v1_compiler_artifact::RenderTarget::Rust], + root_demand: RootDemandDeclaration { + repository: Some(repository.to_string()), + measured_root_demands: Some(measured_root_demands.to_string()), + }, + }; + if let Err(cause) = request.primary_root_agrees_with_precedence() { + return Xl1PrimaryRootTap::Refused { cause }; + } + let identity = crate::memory_governor::WholeCorpusCompileRootIdentity { + repository: repository.to_string(), + primary_root: root.clone(), + dependency_pools: source_roots.iter().skip(1).cloned().collect(), + }; + let read = + crate::memory_governor::read_whole_corpus_compile_demands(Some(measured_root_demands)); + let budget = crate::memory_governor::read_host_budget_resolution(); + let admission = + crate::memory_governor::whole_corpus_compile_admission(&budget, &identity, &read); + if let Some(diagnostic) = + crate::memory_governor::whole_corpus_compile_refusal_diagnostic(&admission) + { + return Xl1PrimaryRootTap::Refused { cause: diagnostic }; + } + let root_abs = if std::path::Path::new(&root).is_absolute() { + std::path::PathBuf::from(&root) + } else { + process_workspace_root().join(&root) + }; + if repo_relative_path(&root_abs).is_err() { + return Xl1PrimaryRootTap::Refused { + cause: format!( + "primary source root is outside the workspace root: {} is not under {}", + root_abs.display(), + process_workspace_root().display() + ), + }; + } + let index = match try_process_shared_index(source_roots) { + Ok(idx) => idx, + Err(cause) => { + return Xl1PrimaryRootTap::Refused { + cause: format!("xl1 primary-root tap: source-discovery: {cause}"), + } + } + }; + // ONE DERIVATION OF THE PRIMARY-ROOT SUBJECT, shared with the compile transaction's + // `CompileSubject::PrimaryRoot` arm (`cli_run.rs` `primary_root_subject_closure`). This + // tap used to carry its own copy and the copy had drifted in the fail-open direction: it + // had no module-less-`.dag` visibility step, so a `.dag` under the root that lost its + // `module` header would have left the closure silently and the census would have + // under-counted while reporting rows (review 66847 on gunbc#11461). + let closure = match primary_root_subject_closure(&index, &root) { + Ok(c) => c, + Err(PrimaryRootSubjectRefusal { phase, cause }) => { + return Xl1PrimaryRootTap::Refused { + cause: format!("xl1 primary-root tap: {phase}: {cause}"), + } + } + }; + // The pool outside the closure enters the name census only -- the SAME derivation the + // compile transaction's PrimaryRoot arm and the required floor consume, never a copy + // (review 67039 on gunbc#11461). + let options = compile_clean_pipeline_options_for_sources(Some(&index), &closure); + let resolved = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + v1_compiler_compile::compile_to_resolved_with_options( + Rc::new(closure.clone().into()), + options, + ) + })) { + Ok(value) => value, + Err(_) => { + return Xl1PrimaryRootTap::Refused { + cause: "xl1 primary-root tap: frontend panicked before producing a graph" + .to_string(), + } + } + }; + let Some(graph) = resolved.graph.clone() else { + return Xl1PrimaryRootTap::Refused { + cause: "xl1 primary-root tap: frontend produced no resolved graph".to_string(), + }; + }; + let repair_rows = crate::v1_compiler_emit_rust::emit_rust_reference_derived_rows(graph.clone()); + match observed_occurrence_transport_and_bindings(graph.as_ref()) { + ObservedOccurrenceBindingHalves::Refused { cause } => Xl1PrimaryRootTap::Refused { cause }, + ObservedOccurrenceBindingHalves::Ready { + transport, + observations, + .. + } => Xl1PrimaryRootTap::Observed { + primary_root: root, + repair_rows, + occurrence_transport: transport, + binding_rows: observations, + }, + } +} diff --git a/src/v1/stage0/src/emitted_population.rs b/src/v1/stage0/src/emitted_population.rs index 8727aa0d72d..4da63253737 100644 --- a/src/v1/stage0/src/emitted_population.rs +++ b/src/v1/stage0/src/emitted_population.rs @@ -33,6 +33,7 @@ // src/gunbc_cli_dispatch_generated.rs // src/gunbc_cli_dispatch_surface.rs // src/gunbc_namespace_reference_derived_closure_admission.rs +// src/gunbc_reference_derived_candidate.rs // src/gunbc_rust_decl_type_overlay.rs // src/gunbc_rust_source_type_bindings.rs // src/gunbc_stage0_crate_layout_generated.rs diff --git a/src/v1/stage0/src/gunbc_reference_derived_candidate.rs b/src/v1/stage0/src/gunbc_reference_derived_candidate.rs new file mode 100644 index 00000000000..7c0467fde85 --- /dev/null +++ b/src/v1/stage0/src/gunbc_reference_derived_candidate.rs @@ -0,0 +1,29 @@ +// Generated by v1 compiler -- do not edit. +// Source module: gunbc.reference_derived_candidate + +use self::ReferenceDerivedCandidateDisposition::*; +use crate::v1_rt; +use crate::v1_rt::{VecCompat, VecJoin}; +use crate::NonEmptyBTreeSet; +use crate::NonEmptyVec; +use im::{vector as vec, HashMap, OrdSet as BTreeSet, Vector as Vec}; +use std::rc::Rc; + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[serde(tag = "_variant")] +pub enum ReferenceDerivedCandidateDisposition { + CandidateSurvived { provider_module: String }, + CandidateOwnModule, + CandidateVariantDelegatedToParent { parent_enum: String }, + CandidateVariantParentUnresolved, + CandidateRegistryAbsent, + CandidateLeafAmbiguous, + CandidateExportProofFailed { provider_module: String }, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct ReferenceDerivedCandidateRow { + pub module_name: String, + pub name: String, + pub disposition: Rc, +} diff --git a/src/v1/stage0/src/lib.rs b/src/v1/stage0/src/lib.rs index e1aae95e67d..9543d092f13 100644 --- a/src/v1/stage0/src/lib.rs +++ b/src/v1/stage0/src/lib.rs @@ -136,6 +136,17 @@ pub mod gunbc_namespace_reference_derived_closure_admission; suspicious_double_ref_op, clippy::all )] +pub mod gunbc_reference_derived_candidate; +#[allow( + unused_imports, + unused_variables, + unused_mut, + unused_parens, + dead_code, + non_shorthand_field_patterns, + suspicious_double_ref_op, + clippy::all +)] pub mod gunbc_rust_decl_type_overlay; #[allow( unused_imports, diff --git a/src/v1/stage0/src/std_repair_input_origin.rs b/src/v1/stage0/src/std_repair_input_origin.rs index 619c32389a9..711f6737afe 100644 --- a/src/v1/stage0/src/std_repair_input_origin.rs +++ b/src/v1/stage0/src/std_repair_input_origin.rs @@ -2,8 +2,10 @@ // Source module: std.repair_input_origin use self::CandidateSpelling::*; +use self::RepairInputDeclarationProvenance::*; use self::RepairInputOriginCandidate::*; use self::SourceCarrierOrigin::*; +pub use crate::std_decl_ref::DeclarationRef; pub use crate::std_types::List; use crate::v1_rt; use crate::v1_rt::{VecCompat, VecJoin}; @@ -39,6 +41,22 @@ pub enum SourceCarrierOrigin { #[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)] pub struct RenderedTypeSurfaceOrigin; +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +#[serde(tag = "_variant")] +pub enum RepairInputDeclarationProvenance { + RepairInputDeclared { declaring: Rc }, + RepairInputTargetWithoutDeclarationIdentity { target_spelling: String }, + RepairInputIdentityAmbiguous, + RepairInputIdentityAbsent, +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct SourceDeclarationCarrierIdentity { + pub reference_position: String, + pub authored_spelling: String, + pub provenance: Rc, +} + #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct SourceCarrierCandidateIdentity { pub emitting_module: String, @@ -62,6 +80,9 @@ pub enum RepairInputOriginCandidate { RenderedTargetVocabularyCarrier { identity: Rc, }, + SourceDeclarationCarrier { + identity: Rc, + }, } pub fn candidate_spelling_from_text(name: String) -> Rc { @@ -205,6 +226,9 @@ pub fn repair_input_origin_candidate_name(candidate: Rc identity.rendered_identifier.clone(), + RepairInputOriginCandidate::SourceDeclarationCarrier { + identity: identity, .. + } => identity.authored_spelling.clone(), } } @@ -254,6 +278,9 @@ pub fn qualified_item_emit_surface_compatibility_names( identity: _, .. } => Rc::new(vec![]), + RepairInputOriginCandidate::SourceDeclarationCarrier { + identity: _, .. + } => Rc::new(vec![]), }) .iter() .cloned(), diff --git a/src/v1/stage0/src/v1_compiler_emit_rust.rs b/src/v1/stage0/src/v1_compiler_emit_rust.rs index 84a4199ed1d..40d9b950a6f 100644 --- a/src/v1/stage0/src/v1_compiler_emit_rust.rs +++ b/src/v1/stage0/src/v1_compiler_emit_rust.rs @@ -8,7 +8,6 @@ use self::DataRefResolution::*; use self::DataReferenceUnresolvableCause::*; use self::IterOwnedReceiverCloneDisposition::*; use self::ParamDefaultResolution::*; -use self::ReferenceDerivedCandidateDisposition::*; use self::WitnessCtorPathVerdict::*; pub use crate::extdeps_cargo_version::render_cargo_package_header_prefix; pub use crate::extdeps_languages_rust_capabilities::phantom_opaque_carrier_derive_traits; @@ -40,6 +39,14 @@ pub use crate::gunbc_cli_dispatch_surface::{ CliArmRealization, CliBootstrapDagOperationBinding, CliBootstrapExecutionClass, CliOperandRow, CliOptionArity, CliOptionRow, CliOptionValue, CliSubcommandRow, }; +use crate::gunbc_reference_derived_candidate::ReferenceDerivedCandidateDisposition::{ + CandidateExportProofFailed, CandidateLeafAmbiguous, CandidateOwnModule, + CandidateRegistryAbsent, CandidateSurvived, CandidateVariantDelegatedToParent, + CandidateVariantParentUnresolved, +}; +pub use crate::gunbc_reference_derived_candidate::{ + ReferenceDerivedCandidateDisposition, ReferenceDerivedCandidateRow, +}; pub use crate::gunbc_rust_decl_type_overlay::rust_decl_type_container_overlay_is_admitted; pub use crate::gunbc_stage0_crate_layout_generated::generated_pub_mod_block; pub use crate::gunbc_stage0_crate_partition_generated::generated_partition_crate_rows; @@ -9611,25 +9618,6 @@ pub fn local_coproduct_variant_names( }) } -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -#[serde(tag = "_variant")] -pub enum ReferenceDerivedCandidateDisposition { - CandidateSurvived { provider_module: String }, - CandidateOwnModule, - CandidateVariantDelegatedToParent { parent_enum: String }, - CandidateVariantParentUnresolved, - CandidateRegistryAbsent, - CandidateLeafAmbiguous, - CandidateExportProofFailed { provider_module: String }, -} - -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct ReferenceDerivedCandidateRow { - pub module_name: String, - pub name: String, - pub disposition: Rc, -} - pub fn reference_derived_candidate_disposition( name: String, this_module_name: String, diff --git a/src/v1/stage0/src/v1_compiler_infer_method.rs b/src/v1/stage0/src/v1_compiler_infer_method.rs index fc645d05e26..7d1257c73a8 100644 --- a/src/v1/stage0/src/v1_compiler_infer_method.rs +++ b/src/v1/stage0/src/v1_compiler_infer_method.rs @@ -970,6 +970,30 @@ pub fn builtin_function_registry() -> Rc>> }), })]), returns: list_of_type_variable("ordinary_compile_structural_admission_elem".to_string()), + })); + __m.insert("emit_rust_reference_derived_rows_bridge".to_string(), Rc::new(BuiltinSignature { + params: Rc::new(vec![Rc::new(BuiltinParam { + name: "source_roots".to_string(), + ty: Rc::new(AlgebraTypeTemplate::ContainerOf { + source: Rc::new(ContainerSource::Named { + name: "List".to_string(), + }), + element: Rc::new(AlgebraTypeTemplate::NamedTemplate { + name: "String".to_string(), + }), + }), + }), Rc::new(BuiltinParam { + name: "repository".to_string(), + ty: Rc::new(AlgebraTypeTemplate::NamedTemplate { + name: "String".to_string(), + }), + }), Rc::new(BuiltinParam { + name: "measured_root_demands".to_string(), + ty: Rc::new(AlgebraTypeTemplate::NamedTemplate { + name: "String".to_string(), + }), + })]), + returns: type_variable_node("xl1_primary_root_tap".to_string()), })); __m.insert("extdeps_shape_transport_policy_facts_for_qualified_name".to_string(), Rc::new(BuiltinSignature { params: Rc::new(vec![Rc::new(BuiltinParam { diff --git a/src/v1/stage0/src/v1_compiler_infer_patterns.rs b/src/v1/stage0/src/v1_compiler_infer_patterns.rs index 578d0bae4c6..267a03957f5 100644 --- a/src/v1/stage0/src/v1_compiler_infer_patterns.rs +++ b/src/v1/stage0/src/v1_compiler_infer_patterns.rs @@ -602,19 +602,17 @@ pub fn lookup_variant_in_type( ) { Some(resolved) => { if (resolved.connective.clone() == Connective::Disj) { - match crate::v1_std_core::find_child_named( + match find_variant_child_keyed( resolved.clone(), - crate::v1_std_core::qualified_last_segment(variant_name.clone()), + variant_name.clone(), source_indices.clone(), ) { - Some(variant_child) => match crate::v1_std_core::find_child_named( + Some(variant_child) => match find_variant_child_keyed( expand_scrut_type_for_variant_lookup( scrut_node.clone(), env.clone(), ), - crate::v1_std_core::qualified_last_segment( - variant_name.clone(), - ), + variant_name.clone(), source_indices.clone(), ) { Some(scrut_child) => node_lookup_resolved(scrut_child.clone()), @@ -704,12 +702,11 @@ pub fn lookup_variant_in_type( == "Present".to_string()) || (variant_name.clone() == "Absent".to_string()))); - let direct_match = - crate::v1_std_core::find_child_named( - scrut_node.clone(), - variant_name.clone(), - source_indices.clone(), - ); + let direct_match = find_variant_child_keyed( + scrut_node.clone(), + variant_name.clone(), + source_indices.clone(), + ); let record_destructure = (((field_binding_count .clone() > 0) @@ -828,6 +825,37 @@ pub fn variant_pattern_coverage_key(name: String) -> String { } } +pub fn find_variant_child_keyed( + n: Rc, + variant_name: String, + source_indices: Rc>>, +) -> Option> { + { + let key = variant_pattern_coverage_key(variant_name.clone()); + let matches = Rc::new({ + let mut __result = Vec::new(); + for c in n.children.clone().iter().cloned() { + if (variant_pattern_coverage_key(crate::v1_std_core::authored_name_at( + source_indices.clone(), + c.clone(), + )) == key.clone()) + { + __result.push(c); + } + } + __result + }); + if ((matches.clone().len() as i64) > 1) { + std::option::Option::None + } else { + match matches.clone().first().cloned() { + Some(ch) => Some(ch.clone()), + std::option::Option::None => std::option::Option::None, + } + } + } +} + #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] #[serde(tag = "_variant")] pub enum ConstructorRoster { @@ -966,7 +994,7 @@ pub fn pattern_row_is_irrefutable(row: Rc>>) -> bool { pub fn pattern_matches_constructor(p: Rc, ctor: String) -> bool { match (*p.clone()).clone() { MatchPattern::VariantPattern { name: n, .. } => { - (variant_pattern_coverage_key(n.clone()) == ctor.clone()) + (variant_pattern_coverage_key(n.clone()) == variant_pattern_coverage_key(ctor.clone())) } MatchPattern::LitPattern { value: v, .. } => match (*v.clone()).clone() { LiteralValue::LitBool { value: b, .. } => { @@ -1258,7 +1286,11 @@ pub fn exhaustiveness_witnesses( for w in sub.iter().cloned() { __result.push(Rc::new(PatternWitnessRow { cells: v1_rt::concat( - Rc::new(vec![c.clone()]), + Rc::new(vec![ + variant_pattern_coverage_key( + c.clone(), + ), + ]), w.cells.clone(), ), })); diff --git a/src/v1/stage0/src/v1_interpreter.rs b/src/v1/stage0/src/v1_interpreter.rs index f62ead7c4cf..35cd452d64c 100644 --- a/src/v1/stage0/src/v1_interpreter.rs +++ b/src/v1/stage0/src/v1_interpreter.rs @@ -13047,6 +13047,66 @@ fn compile_diagnostic_census_row_value( } } +fn reference_derived_candidate_disposition_value( + disposition: &crate::v1_compiler_emit_rust::ReferenceDerivedCandidateDisposition, + ctx: &InterpContext, +) -> Value { + use crate::v1_compiler_emit_rust::ReferenceDerivedCandidateDisposition as D; + let variant = |name: &str, fields: Vec<(Symbol, Value)>| Value::Variant { + type_name: ctx.sym("ReferenceDerivedCandidateDisposition"), + variant_name: ctx.sym(name), + fields: Rc::new(sorted_fields(fields)), + }; + match disposition { + D::CandidateSurvived { provider_module } => variant( + "CandidateSurvived", + vec![( + ctx.sym("provider_module"), + str_value(provider_module.clone()), + )], + ), + D::CandidateOwnModule => variant("CandidateOwnModule", vec![]), + D::CandidateVariantDelegatedToParent { parent_enum } => variant( + "CandidateVariantDelegatedToParent", + vec![(ctx.sym("parent_enum"), str_value(parent_enum.clone()))], + ), + D::CandidateVariantParentUnresolved => variant("CandidateVariantParentUnresolved", vec![]), + D::CandidateRegistryAbsent => variant("CandidateRegistryAbsent", vec![]), + D::CandidateLeafAmbiguous => variant("CandidateLeafAmbiguous", vec![]), + D::CandidateExportProofFailed { provider_module } => variant( + "CandidateExportProofFailed", + vec![( + ctx.sym("provider_module"), + str_value(provider_module.clone()), + )], + ), + } +} + +fn reference_derived_candidate_rows_value( + rows: &im::Vector>, + ctx: &InterpContext, +) -> Value { + list_value( + rows.iter() + .map(|row| Value::Record { + type_name: ctx.sym("ReferenceDerivedCandidateRow"), + fields: Rc::new(sorted_fields(vec![ + (ctx.sym("module_name"), str_value(row.module_name.clone())), + (ctx.sym("name"), str_value(row.name.clone())), + ( + ctx.sym("disposition"), + reference_derived_candidate_disposition_value( + row.disposition.as_ref(), + ctx, + ), + ), + ])), + }) + .collect::>(), + ) +} + fn compile_diagnostic_census_value( census: crate::cli_run::CompileDiagnosticCensus, ctx: &InterpContext, @@ -13244,6 +13304,211 @@ fn multi_module_compile_fixture_value( } } +fn occurrence_id_value( + id: crate::std_occurrence_identity::OccurrenceId, + ctx: &InterpContext, +) -> Value { + Value::Record { + type_name: ctx.sym("OccurrenceId"), + fields: Rc::new(sorted_fields(vec![( + ctx.sym("value"), + Value::Int(id.value), + )])), + } +} + +fn authored_source_span_value(span: &crate::std_types::SourceSpan, ctx: &InterpContext) -> Value { + Value::Record { + type_name: ctx.sym("SourceSpan"), + fields: Rc::new(sorted_fields(vec![ + (ctx.sym("file"), str_value(span.file.clone())), + (ctx.sym("start"), Value::Int(span.start)), + (ctx.sym("end"), Value::Int(span.end)), + ])), + } +} + +fn occurrence_containment_path_value( + path: &crate::std_occurrence_identity::OccurrenceContainmentPath, + ctx: &InterpContext, +) -> Value { + Value::Record { + type_name: ctx.sym("OccurrenceContainmentPath"), + fields: Rc::new(sorted_fields(vec![ + ( + ctx.sym("ancestors"), + list_value( + path.ancestors + .iter() + .copied() + .map(|id| occurrence_id_value(id, ctx)) + .collect::>(), + ), + ), + (ctx.sym("terminal"), occurrence_id_value(path.terminal, ctx)), + ])), + } +} + +fn occurrence_transport_value( + transport: &crate::std_occurrence_identity::OccurrenceTransport, + ctx: &InterpContext, +) -> Value { + let projection = |p: &crate::std_occurrence_identity::OccurrenceProjection| Value::Record { + type_name: ctx.sym("OccurrenceProjection"), + fields: Rc::new(sorted_fields(vec![ + ( + ctx.sym("occurrence"), + occurrence_id_value(p.occurrence, ctx), + ), + (ctx.sym("authored_name"), str_value(p.authored_name.clone())), + ( + ctx.sym("diagnostic_span"), + authored_source_span_value(p.diagnostic_span.as_ref(), ctx), + ), + ])), + }; + let index_entry = |e: &crate::std_occurrence_identity::OccurrenceIndexEntry| Value::Record { + type_name: ctx.sym("OccurrenceIndexEntry"), + fields: Rc::new(sorted_fields(vec![ + (ctx.sym("projection"), projection(e.projection.as_ref())), + ( + ctx.sym("containment"), + occurrence_containment_path_value(e.containment.as_ref(), ctx), + ), + ])), + }; + let declaration = |d: &crate::std_occurrence_identity::DeclarationOccurrence| Value::Record { + type_name: ctx.sym("DeclarationOccurrence"), + fields: Rc::new(sorted_fields(vec![ + ( + ctx.sym("occurrence"), + occurrence_id_value(d.occurrence, ctx), + ), + ( + ctx.sym("containment"), + occurrence_containment_path_value(d.containment.as_ref(), ctx), + ), + ( + ctx.sym("category"), + occurrence_category_value(&d.category, ctx), + ), + ( + ctx.sym("diagnostic_span"), + authored_source_span_value(d.diagnostic_span.as_ref(), ctx), + ), + ])), + }; + let reference = |r: &crate::std_occurrence_identity::ReferenceOccurrence| Value::Record { + type_name: ctx.sym("ReferenceOccurrence"), + fields: Rc::new(sorted_fields(vec![ + ( + ctx.sym("occurrence"), + occurrence_id_value(r.occurrence, ctx), + ), + ( + ctx.sym("containment"), + occurrence_containment_path_value(r.containment.as_ref(), ctx), + ), + ( + ctx.sym("category"), + occurrence_category_value(&r.category, ctx), + ), + ( + ctx.sym("diagnostic_span"), + authored_source_span_value(r.diagnostic_span.as_ref(), ctx), + ), + ])), + }; + Value::Record { + type_name: ctx.sym("OccurrenceTransport"), + fields: Rc::new(sorted_fields(vec![ + ( + ctx.sym("index"), + Value::Record { + type_name: ctx.sym("OccurrenceIndex"), + fields: Rc::new(sorted_fields(vec![( + ctx.sym("entries"), + list_value( + transport + .index + .entries + .iter() + .map(|e| index_entry(e.as_ref())) + .collect::>(), + ), + )])), + }, + ), + ( + ctx.sym("declarations"), + list_value( + transport + .declarations + .iter() + .map(|d| declaration(d.as_ref())) + .collect::>(), + ), + ), + ( + ctx.sym("references"), + list_value( + transport + .references + .iter() + .map(|r| reference(r.as_ref())) + .collect::>(), + ), + ), + ])), + } +} + +fn xl1_primary_root_tap_value( + tap: crate::cli_run::Xl1PrimaryRootTap, + ctx: &InterpContext, +) -> Value { + let variant = |name: &str, fields: Vec<(Symbol, Value)>| Value::Variant { + type_name: ctx.sym("Xl1PrimaryRootTap"), + variant_name: ctx.sym(name), + fields: Rc::new(sorted_fields(fields)), + }; + match tap { + crate::cli_run::Xl1PrimaryRootTap::Refused { cause } => variant( + "Xl1PrimaryRootRefused", + vec![(ctx.sym("cause"), str_value(cause))], + ), + crate::cli_run::Xl1PrimaryRootTap::Observed { + primary_root, + repair_rows, + occurrence_transport, + binding_rows, + } => variant( + "Xl1PrimaryRootObserved", + vec![ + (ctx.sym("primary_root"), str_value(primary_root)), + ( + ctx.sym("repair_rows"), + reference_derived_candidate_rows_value(repair_rows.as_ref(), ctx), + ), + ( + ctx.sym("occurrence_transport"), + occurrence_transport_value(occurrence_transport.as_ref(), ctx), + ), + ( + ctx.sym("binding_rows"), + list_value( + binding_rows + .into_iter() + .map(|row| reference_occurrence_binding_census_row_value(row, ctx)) + .collect::>(), + ), + ), + ], + ), + } +} + fn occurrence_category_value( category: &crate::std_occurrence_identity::OccurrenceCategory, ctx: &InterpContext, @@ -13264,6 +13529,96 @@ fn occurrence_category_value( } } +fn reference_occurrence_binding_census_row_value( + row: crate::cli_run::ReferenceOccurrenceBindingRow, + ctx: &InterpContext, +) -> Value { + let source_value = |source: crate::cli_run::UnlistedImportBindingSource| Value::Variant { + type_name: ctx.sym("UnlistedImportBindingSource"), + variant_name: ctx.sym(match source { + crate::cli_run::UnlistedImportBindingSource::ListedImport => "ListedImport", + crate::cli_run::UnlistedImportBindingSource::PoolCoincidence => "PoolCoincidence", + crate::cli_run::UnlistedImportBindingSource::DefinerResolvable => "DefinerResolvable", + crate::cli_run::UnlistedImportBindingSource::AmbiguousLeaf => "AmbiguousLeaf", + }), + fields: Rc::new(vec![]), + }; + let disposition = match row.disposition { + crate::cli_run::ReferenceOccurrenceBindingDisposition::Bound { + declaration_occurrence, + provider_module, + binding_source, + } => Value::Variant { + type_name: ctx.sym("ReferenceOccurrenceBindingDisposition"), + variant_name: ctx.sym("ReferenceOccurrenceBound"), + fields: Rc::new(sorted_fields(vec![ + ( + ctx.sym("declaration_occurrence"), + Value::Int(declaration_occurrence), + ), + (ctx.sym("provider_module"), str_value(provider_module)), + (ctx.sym("binding_source"), source_value(binding_source)), + ])), + }, + crate::cli_run::ReferenceOccurrenceBindingDisposition::Unresolved => Value::Variant { + type_name: ctx.sym("ReferenceOccurrenceBindingDisposition"), + variant_name: ctx.sym("ReferenceOccurrenceUnresolved"), + fields: Rc::new(vec![]), + }, + crate::cli_run::ReferenceOccurrenceBindingDisposition::Ambiguous { candidates } => { + Value::Variant { + type_name: ctx.sym("ReferenceOccurrenceBindingDisposition"), + variant_name: ctx.sym("ReferenceOccurrenceAmbiguous"), + fields: Rc::new(sorted_fields(vec![( + ctx.sym("candidates"), + list_value(candidates.into_iter().map(Value::Int).collect::>()), + )])), + } + } + crate::cli_run::ReferenceOccurrenceBindingDisposition::Refused { cause } => { + Value::Variant { + type_name: ctx.sym("ReferenceOccurrenceBindingDisposition"), + variant_name: ctx.sym("ReferenceOccurrenceBindingRefused"), + fields: Rc::new(sorted_fields(vec![(ctx.sym("cause"), str_value(cause))])), + } + } + }; + Value::Record { + type_name: ctx.sym("ReferenceOccurrenceBindingRow"), + fields: Rc::new(sorted_fields(vec![ + ( + ctx.sym("occurrence"), + Value::Int(row.denominator.occurrence), + ), + ( + ctx.sym("consumer_file"), + str_value(row.denominator.consumer_file), + ), + ( + ctx.sym("consumer_module"), + str_value(row.denominator.consumer_module), + ), + ( + ctx.sym("authored_name"), + str_value(row.denominator.authored_name), + ), + ( + ctx.sym("category"), + occurrence_category_value(&row.denominator.category, ctx), + ), + ( + ctx.sym("file_reference_ordinal"), + Value::Int(row.denominator.file_reference_ordinal), + ), + ( + ctx.sym("span_start"), + Value::Int(row.denominator.span_start), + ), + (ctx.sym("disposition"), disposition), + ])), + } +} + fn reference_occurrence_binding_census_value( census: crate::cli_run::ReferenceOccurrenceBindingCensus, ctx: &InterpContext, @@ -20217,6 +20572,20 @@ macro_rules! v1_builtin_arms { ))) }, + arm "free_call.emit_rust_reference_derived_rows_bridge" { "emit_rust_reference_derived_rows_bridge" } => { + let source_roots = expect_str_list($positional.first().copied(), $name)?; + let repository = expect_str($positional.get(1).copied(), $name)?; + let measured_root_demands = expect_str($positional.get(2).copied(), $name)?; + Ok(Some(xl1_primary_root_tap_value( + crate::cli_run::compile_xl1_primary_root_tap( + &source_roots, + &repository, + &measured_root_demands, + ), + $ctx, + ))) + }, + arm "free_call.compile_dag_rust_emit_check" { "compile_dag_rust_emit_check" } => { let source = expect_str($positional.first().copied(), $name)?; let file_path = expect_str($positional.get(1).copied(), $name)?; diff --git a/src/v1/stage0/src/v1_interpreter_dispatch_generated.rs b/src/v1/stage0/src/v1_interpreter_dispatch_generated.rs index 2bde719b59d..c34c928b62f 100644 --- a/src/v1/stage0/src/v1_interpreter_dispatch_generated.rs +++ b/src/v1/stage0/src/v1_interpreter_dispatch_generated.rs @@ -100,6 +100,7 @@ pub enum EvalBuiltinArm { FreeCallFloorDiscoverySourceInventory, FreeCallParsedImportStatements, FreeCallNamespaceStructuralObservationAdmissions, + FreeCallEmitRustReferenceDerivedRowsBridge, FreeCallCompileDagRustEmitCheck, FreeCallCompileDagDiagnosticCensus, FreeCallCompileDagMultiModuleFixture, @@ -242,6 +243,7 @@ pub fn lookup_eval_builtin_inner(spelling: &str) -> Option { "floor_discovery_source_inventory" => Some(EvalBuiltinArm::FreeCallFloorDiscoverySourceInventory), "parsed_import_statements" => Some(EvalBuiltinArm::FreeCallParsedImportStatements), "namespace_structural_observation_admissions" => Some(EvalBuiltinArm::FreeCallNamespaceStructuralObservationAdmissions), + "emit_rust_reference_derived_rows_bridge" => Some(EvalBuiltinArm::FreeCallEmitRustReferenceDerivedRowsBridge), "compile_dag_rust_emit_check" => Some(EvalBuiltinArm::FreeCallCompileDagRustEmitCheck), "compile_dag_diagnostic_census" => Some(EvalBuiltinArm::FreeCallCompileDagDiagnosticCensus), "compile_dag_multi_module_fixture" => Some(EvalBuiltinArm::FreeCallCompileDagMultiModuleFixture), @@ -382,6 +384,7 @@ macro_rules! eval_builtin_inner_arm { ("free_call.floor_discovery_source_inventory") => { $crate::v1_interpreter_dispatch_generated::EvalBuiltinArm::FreeCallFloorDiscoverySourceInventory }; ("free_call.parsed_import_statements") => { $crate::v1_interpreter_dispatch_generated::EvalBuiltinArm::FreeCallParsedImportStatements }; ("free_call.namespace_structural_observation_admissions") => { $crate::v1_interpreter_dispatch_generated::EvalBuiltinArm::FreeCallNamespaceStructuralObservationAdmissions }; + ("free_call.emit_rust_reference_derived_rows_bridge") => { $crate::v1_interpreter_dispatch_generated::EvalBuiltinArm::FreeCallEmitRustReferenceDerivedRowsBridge }; ("free_call.compile_dag_rust_emit_check") => { $crate::v1_interpreter_dispatch_generated::EvalBuiltinArm::FreeCallCompileDagRustEmitCheck }; ("free_call.compile_dag_diagnostic_census") => { $crate::v1_interpreter_dispatch_generated::EvalBuiltinArm::FreeCallCompileDagDiagnosticCensus }; ("free_call.compile_dag_multi_module_fixture") => { $crate::v1_interpreter_dispatch_generated::EvalBuiltinArm::FreeCallCompileDagMultiModuleFixture }; diff --git a/src/v1/stage0/src/v1_tests_claim_reference_derived_disposition_census_witness_test.rs b/src/v1/stage0/src/v1_tests_claim_reference_derived_disposition_census_witness_test.rs index 383ec161f47..5114e1fec37 100644 --- a/src/v1/stage0/src/v1_tests_claim_reference_derived_disposition_census_witness_test.rs +++ b/src/v1/stage0/src/v1_tests_claim_reference_derived_disposition_census_witness_test.rs @@ -1,21 +1,22 @@ // Generated by v1 compiler -- do not edit. // Source module: v1.tests.claim.reference_derived_disposition_census_witness_test -pub use crate::std_types::SourceSpan; -pub use crate::v1_compiler_compile::compile_to_resolved; -pub use crate::v1_compiler_compile::SourceFile; -use crate::v1_compiler_emit_rust::ReferenceDerivedCandidateDisposition::{ +use crate::gunbc_reference_derived_candidate::ReferenceDerivedCandidateDisposition::{ CandidateExportProofFailed, CandidateOwnModule, CandidateRegistryAbsent, CandidateSurvived, CandidateVariantDelegatedToParent, CandidateVariantParentUnresolved, }; +pub use crate::gunbc_reference_derived_candidate::{ + ReferenceDerivedCandidateDisposition, ReferenceDerivedCandidateRow, +}; +pub use crate::std_types::SourceSpan; +pub use crate::v1_compiler_compile::compile_to_resolved; +pub use crate::v1_compiler_compile::SourceFile; +pub use crate::v1_compiler_emit_rust::ReferenceDerivedCensus; pub use crate::v1_compiler_emit_rust::{ build_module_index, emit_rust_reference_derived_census, emit_rust_reference_derived_rows, reference_derived_candidate_disposition, reference_derived_census, reference_derived_disposition_name, reference_derived_row_diagnostics, }; -pub use crate::v1_compiler_emit_rust::{ - ReferenceDerivedCandidateDisposition, ReferenceDerivedCandidateRow, ReferenceDerivedCensus, -}; pub use crate::v1_compiler_infer_emit_info::empty_emit_graph_info; use crate::v1_compiler_infer_emit_info::TypeRepr::EnumRepr; pub use crate::v1_compiler_infer_emit_info::{TypeRepr, TypeSummary}; diff --git a/src/v1/tests/claim/reference_derived_disposition_census_witness_test.dag b/src/v1/tests/claim/reference_derived_disposition_census_witness_test.dag index d383a465190..37f3cc600c5 100644 --- a/src/v1/tests/claim/reference_derived_disposition_census_witness_test.dag +++ b/src/v1/tests/claim/reference_derived_disposition_census_witness_test.dag @@ -1,14 +1,6 @@ module v1.tests.claim.reference_derived_disposition_census_witness_test import v1.compiler.emit_rust { - ReferenceDerivedCandidateDisposition, - CandidateSurvived, - CandidateOwnModule, - CandidateRegistryAbsent, - CandidateExportProofFailed, - CandidateVariantDelegatedToParent, - CandidateVariantParentUnresolved, - ReferenceDerivedCandidateRow, reference_derived_row_diagnostics, ReferenceDerivedCensus, reference_derived_candidate_disposition, @@ -18,6 +10,16 @@ import v1.compiler.emit_rust { emit_rust_reference_derived_census, build_module_index } +import gunbc.reference_derived_candidate { + ReferenceDerivedCandidateDisposition, + CandidateSurvived, + CandidateOwnModule, + CandidateRegistryAbsent, + CandidateExportProofFailed, + CandidateVariantDelegatedToParent, + CandidateVariantParentUnresolved, + ReferenceDerivedCandidateRow +} import v1.compiler.infer_items { ItemInfo, FnItem } import v1.std.core { ErrorNode, SourceSpan, no_span, diagnostic_to_message, is_error_diagnostic diff --git a/src/v2/compiler/declaring_identity_spelling_census.dag b/src/v2/compiler/declaring_identity_spelling_census.dag new file mode 100644 index 00000000000..0c912b10407 --- /dev/null +++ b/src/v2/compiler/declaring_identity_spelling_census.dag @@ -0,0 +1,145 @@ +module v2.compiler.declaring_identity_spelling_census + +import std.algebra { Empty, FreeMonoid } +import std.declaring_identity_spelling { + DeclaringIdentitySpelling, + IdentityAmbiguous, + IdentityOwnerless, + IdentityUnbound, + declaring_identity_spelling_resolved, + declaring_identity_spelling_unresolvable +} +import std.repair_input_origin { + RepairInputDeclared, + RepairInputIdentityAbsent, + RepairInputIdentityAmbiguous, + RepairInputTargetWithoutDeclarationIdentity +} +import v2.std.algebra { fold_list, list_snoc_item } +import v2.std.diagnostic { Outcome, bind_outcome, outcome_accepted } +import v2.std.language_model { LanguageModel } +import v2.std.node { Node } +import v2.std.symbol_index { empty_symbol_index } +import v2.compiler.normalized_tree { normalized_tree_roots_to_nodes } +import v2.compiler.program_assembly { module_roots_from_source_root_ingest } +import v2.compiler.reference_site_collector { + UnreadableModuleRoot, + collect_reference_sites +} +import v2.compiler.repair_input_origin_roster { carrier_provenance } +import v2.compiler.resolution_provenance { + ProvenanceAmbiguous, + ProvenanceOwnerless, + ProvenanceResolved, + ProvenanceUnbound, + ResolutionProvenance, + answer_site, + module_roster_from_roots, + resolve_reference_sites +} +import v2.compiler.source_authority { SourceRootIngest } +import v2.compiler.symbol_index_fill { symbol_index_fill_module_roots } + +// XL-3 PRODUCER: one mention, one spelling row, over the production ingest route. +// +// Route: v2.compiler.program_assembly module_roots_from_source_root_ingest +// -> v2.compiler.normalized_tree normalized_tree_roots_to_nodes +// -> v2.compiler.reference_site_collector collect_reference_sites +// -> v2.compiler.resolution_provenance resolve_reference_sites +// -> std.declaring_identity_spelling +// +// Consume ReferenceSiteCollection as a whole: .sites for the fold, .unreadable_roots +// carried through. Completeness is emptiness of that carried list (the same fact +// reference_site_collection_is_total names on the collection), never a second Bool +// helper and never inferred from a short row list. +// +// WHAT THIS ROUTE CANNOT SEE is measured, not speculated. +// IdentityUnbound on a same-module ingest census row is an INDEX-PATH probe: +// enrolled control cfp_own_module_site binds; ingest fill does not insert the +// data name at the collector site's parser-keyed path (same class as +// v2.test.claim.provenance.loaded_carrier_receipts receipt 2). Not a fact +// that v2 cannot compile a local name. + +type DeclaringIdentitySpellingCensus { + rows: FreeMonoid + unreadable_roots: FreeMonoid +} + +fn spelling_from_answer(answer: ResolutionProvenance) -> DeclaringIdentitySpelling { + let site = answer_site(answer: answer) + match carrier_provenance(answer: answer) { + RepairInputDeclared { declaring: declaring } => + match answer { + ProvenanceResolved { site: _, target: target, owner: _ } => + declaring_identity_spelling_resolved( + authored: site.spelling, + declaring: declaring, + canonical: target + ) + ProvenanceOwnerless { site: _, target: _ } => + declaring_identity_spelling_unresolvable( + authored: site.spelling, + cause: IdentityOwnerless + ) + ProvenanceAmbiguous { site: _ } => + declaring_identity_spelling_unresolvable( + authored: site.spelling, + cause: IdentityAmbiguous + ) + ProvenanceUnbound { site: _ } => + declaring_identity_spelling_unresolvable( + authored: site.spelling, + cause: IdentityUnbound + ) + } + RepairInputTargetWithoutDeclarationIdentity { target_spelling: _ } => + declaring_identity_spelling_unresolvable( + authored: site.spelling, + cause: IdentityOwnerless + ) + RepairInputIdentityAmbiguous => + declaring_identity_spelling_unresolvable( + authored: site.spelling, + cause: IdentityAmbiguous + ) + RepairInputIdentityAbsent => + declaring_identity_spelling_unresolvable( + authored: site.spelling, + cause: IdentityUnbound + ) + } +} + +fn spelling_census_over_roots(roots: FreeMonoid) -> DeclaringIdentitySpellingCensus { + let collected = collect_reference_sites(roots: roots) + DeclaringIdentitySpellingCensus { + rows: fold_list( + xs: resolve_reference_sites( + index: symbol_index_fill_module_roots(index: empty_symbol_index(), roots: roots), + roster: module_roster_from_roots(roots: roots), + sites: collected.sites + ), + empty: Empty, + cons: fn(acc, answer) { + list_snoc_item(xs: acc, item: spelling_from_answer(answer: answer)) + } + ), + unreadable_roots: collected.unreadable_roots + } +} + +fn spelling_census_from_ingest( + ingest: SourceRootIngest, + lm: LanguageModel +) -> Outcome { + bind_outcome( + o: module_roots_from_source_root_ingest(ingest: ingest, lm: lm), + f: fn(normalized) { + outcome_accepted( + value: spelling_census_over_roots( + roots: normalized_tree_roots_to_nodes(roots: normalized) + ) + ) + } + ) +} diff --git a/src/v2/compiler/program_assembly.dag b/src/v2/compiler/program_assembly.dag index 985bfb62694..c0c71d97286 100644 --- a/src/v2/compiler/program_assembly.dag +++ b/src/v2/compiler/program_assembly.dag @@ -25,7 +25,7 @@ import v2.std.cross_tree.resolution { source_root_index_insert } import std.algebra { Empty, FreeMonoid } -import v2.std.algebra { fold_list, list_snoc_item } +import v2.std.algebra { fold_list, list_map, list_snoc_item } import v2.std.diagnostic { Accepted, Diagnostics, @@ -48,10 +48,52 @@ type ProgramAssemblyFoldState diagnostics: NonEmptyDiagnostics } +// A normalized root together with the path of the read that produced it. The assembly fold +// iterates the reads, so it is the one place the path-to-tree association exists by +// construction; a consumer that needs it reads this pair, never a positional zip of two lists +// across this module's boundary (DESIGN 5: completeness is an identity join, not a count +// equality). The tree-only fold state above is a projection of the located one. A plain +// record, not sole_constructor: the pair carries no invariant beyond its fields, and the +// v2 grammar realization (v2.extdeps.languages.dag dag_grammar_type_decl_expr) admits no +// modifier between the type name and its field block, so the emitted compiler refused this +// file with parse_g0_tokens_remain (gunbc#11461 srv2 pair, fold11461g) - a load-bearing +// stage must stay native-readable. +type LocatedNormalizedTree { + path: String, + tree: NormalizedTree +} + +type ProgramAssemblyLocatedFoldState + = ProgramAssemblyLocatedFoldOk { + located: FreeMonoid, + index: SourceRootIndex + } + | ProgramAssemblyLocatedFoldFailed { + diagnostics: NonEmptyDiagnostics + } + fn program_assembly_empty_roots() -> FreeMonoid { Empty } +fn program_assembly_empty_located_roots() -> FreeMonoid { + Empty +} + +fn program_assembly_fold_state_from_located( + state: ProgramAssemblyLocatedFoldState +) -> ProgramAssemblyFoldState { + match state { + ProgramAssemblyLocatedFoldFailed { diagnostics: d } => + ProgramAssemblyFoldFailed { diagnostics: d } + ProgramAssemblyLocatedFoldOk { located: located, index: idx } => + ProgramAssemblyFoldOk { + roots: list_map(xs: located, f: fn(item) { item.tree }), + index: idx + } + } +} + fn program_assembly_read_to_normalized_root_prepared( read: DagSourceReadWitness, lm: LanguageModel, @@ -99,29 +141,32 @@ fn program_assembly_read_to_normalized_root( } fn program_assembly_fold_step( - state: ProgramAssemblyFoldState, + state: ProgramAssemblyLocatedFoldState, read: DagSourceReadWitness, lm: LanguageModel, prepared: PreparedGrammar, residue: Diagnostics -) -> ProgramAssemblyFoldState { +) -> ProgramAssemblyLocatedFoldState { match state { - ProgramAssemblyFoldFailed { diagnostics: d } => - ProgramAssemblyFoldFailed { diagnostics: d } - ProgramAssemblyFoldOk { roots: acc, index: idx } => + ProgramAssemblyLocatedFoldFailed { diagnostics: d } => + ProgramAssemblyLocatedFoldFailed { diagnostics: d } + ProgramAssemblyLocatedFoldOk { located: acc, index: idx } => match program_assembly_read_to_normalized_root_prepared(read: read, lm: lm, prepared: prepared, residue: residue) { Accepted { value: root, diagnostics: _ } => match qualified_name_from_module_node(root: root.root) { Accepted { value: qn, diagnostics: _ } => - ProgramAssemblyFoldOk { - roots: list_snoc_item(xs: acc, item: root), + ProgramAssemblyLocatedFoldOk { + located: list_snoc_item( + xs: acc, + item: LocatedNormalizedTree { path: read.artifact.file_path, tree: root } + ), index: source_root_index_insert(index: idx, module: qn, root: read.source_root) } Rejected { diagnostics: d } => - ProgramAssemblyFoldFailed { diagnostics: d } + ProgramAssemblyLocatedFoldFailed { diagnostics: d } } Rejected { diagnostics: d } => - ProgramAssemblyFoldFailed { diagnostics: d } + ProgramAssemblyLocatedFoldFailed { diagnostics: d } } } } @@ -152,25 +197,25 @@ fn dag_prepared_grammar() -> Outcome { prepare_grammar(grammar: dag_grammar()) } -fn program_assembly_fold_ingest( +fn program_assembly_fold_ingest_located( ingest: SourceRootIngest, lm: LanguageModel -) -> ProgramAssemblyFoldState { +) -> ProgramAssemblyLocatedFoldState { match ingest { Empty => - ProgramAssemblyFoldOk { - roots: program_assembly_empty_roots(), + ProgramAssemblyLocatedFoldOk { + located: program_assembly_empty_located_roots(), index: source_root_index_empty() } _ => match prepare_grammar(grammar: lm.grammar) { Rejected { diagnostics: d } => - ProgramAssemblyFoldFailed { diagnostics: d } + ProgramAssemblyLocatedFoldFailed { diagnostics: d } Accepted { value: prepared, diagnostics: residue } => fold_list( xs: ingest, - empty: ProgramAssemblyFoldOk { - roots: program_assembly_empty_roots(), + empty: ProgramAssemblyLocatedFoldOk { + located: program_assembly_empty_located_roots(), index: source_root_index_empty() }, cons: fn(state, read) { @@ -181,6 +226,27 @@ fn program_assembly_fold_ingest( } } +fn program_assembly_fold_ingest( + ingest: SourceRootIngest, + lm: LanguageModel +) -> ProgramAssemblyFoldState { + program_assembly_fold_state_from_located( + state: program_assembly_fold_ingest_located(ingest: ingest, lm: lm) + ) +} + +fn located_module_roots_from_source_root_ingest( + ingest: SourceRootIngest, + lm: LanguageModel +) -> Outcome> { + match program_assembly_fold_ingest_located(ingest: ingest, lm: lm) { + ProgramAssemblyLocatedFoldOk { located: located, index: _ } => + outcome_accepted(value: located) + ProgramAssemblyLocatedFoldFailed { diagnostics: d } => + Rejected { diagnostics: d } + } +} + fn module_roots_from_source_root_ingest( ingest: SourceRootIngest, lm: LanguageModel diff --git a/src/v2/compiler/reference_site_collector.dag b/src/v2/compiler/reference_site_collector.dag new file mode 100644 index 00000000000..d4345b27dcd --- /dev/null +++ b/src/v2/compiler/reference_site_collector.dag @@ -0,0 +1,342 @@ +module v2.compiler.reference_site_collector + +import std.algebra { Cons, Empty, FreeMonoid } +import v2.std.algebra { fold_list, is_empty, length, list_snoc_item } +import v2.std.diagnostic { Accepted, Locus, Rejected, node_locus } +import v2.std.integer { Int } +import v2.std.logic { Bool } +import v2.std.node { + Atom, + Conj, + Edge, + Named, + Node, + Positional, + Symbol, + TypeNode +} +import v2.std.optional { Absent, Present } +import v2.std.qualified_name { + QualifiedName, + qualified_name_from_node, + qualified_name_snoc +} +import v2.compiler.resolution_provenance { ReferenceSite } +import v2.extdeps.languages.dag { + dag_node_is_int_literal_atom, + dag_surface_module_header_metadata_edge, + namespace_graft_spine_segment_edge_optional, + qualified_name_from_module_node +} + +// THE MENTION PRODUCER v2.compiler.resolution_provenance HAS BEEN MISSING SINCE IT WAS WRITTEN. +// That module models one name resolved at one position answering with its target and the module +// that contains it, and it models the dependency fold over those answers -- but nothing in the +// corpus produced a ReferenceSite. The only constructors were five hand-authored fixture rows in +// one witness, which makes a well-shaped module dangling in DESIGN section 3c's exact sense: a +// declaration whose consumers are described rather than executed. This module is that producer. +// +// ONE COLLECTOR, TWO STAGES -- AND THAT CLAIM WAS FALSE AS FIRST WRITTEN, SO IT IS RESTATED HERE +// RATHER THAN QUIETLY DROPPED. +// +// This header said "the site enumeration is here, once, and both stages consume it". It is not +// once. v2.lens.reference_deps reference_sites_collect_node ALREADY enumerates reference sites, +// from the PARSED tree, via ^dag_surface_qualified_name productions -- and its own dissolution note +// describes the successor in terms that name this module's territory: "dissolves when +// symbol_index_fill projects reference edges from the filled containment tree and non-import +// qualified-name sites require the parsed census path". I did not find it before writing this +// module, which is the section 6 move -- DFS the concept DAG before inventing vocabulary -- skipped +// at the one point it mattered most. +// +// THE OVERLAP IS REAL BUT NARROWER THAN I FIRST WROTE, AND I CHECKED THE SECOND TIME. I claimed +// the lens recognises "exactly the class this collector misses -- a qualified cross-module +// reference in a body". THAT IS FALSE. The lens keys on ^dag_surface_qualified_name and the import +// productions and NOTHING ELSE -- it carries no dot or field-access handling at all. A qualified +// reference in a BODY parses as a field access, not a qualified-name production, so the lens misses +// it too. What the lens does see is a qualified name in a TYPE position, where the production +// survives. +// +// SO NEITHER INSTRUMENT SEES A QUALIFIED BODY REFERENCE, and the overlap between them is the +// type-position qualified name rather than the whole qualified class. That is also why +// warm-ibex-518's deleted parse walk was genuinely a duplicate: it keyed on the same production. +// +// THE CONSOLIDATION IS RULED AND IT IS NOT "CONSUME THE LENS". The authority for reference sites is +// the collector over the tree THE RESOLVER CONSUMES -- a site must be something resolution +// resolves, and the lens reads the parse tree. The lens is itself a declared SCAFFOLD whose own +// dissolution names a symbol_index_fill-derived projection, so consuming its recogniser would be +// building on a scaffold. Its disposition is repointed at this module instead, and the overlap is +// recorded as a DECLARED FRONTIER rather than as consolidated: two enumerators stand today, on two +// trees, and this one becomes the single authority when it covers qualified sites -- which waits on +// the dotted-reference capability, still under verification and NOT escalated to another lane. +// WHAT COUNTS AS A MENTION, AND WHY A DECLARATION IS NOT ONE. In the v2 containment tree a +// declaration's NAME is an EDGE LABEL (v2.compiler.symbol_index_fill binds at +// Named { name } edges and indexes edge.target as the declaration), so a declared name never +// appears as a node. An Atom node is therefore a reference by construction rather than by a filter +// that could be wrong -- there is no declaration-shaped Atom for this walk to have to exclude. +// +// ONE DELIBERATE EXCLUSION, AND IT IS NOT A FILTER ON ELIGIBILITY. Module-header metadata subtrees +// carry the module's OWN qualified name, which is a declaration of position and not a mention of +// anything. It is recognised by the SAME predicate v2.compiler.symbol_index_fill consults, never by +// a second spelling of it. +// +// A SECOND EXCLUSION STOOD HERE AND WAS DELETED BY MEASUREMENT. It skipped every `_node_projection` +// edge, on the reasoning that such an edge carries a parse projection of source already visited and +// descending would double-count. THAT DOUBLE-COUNT WAS NEVER DEMONSTRATED, and the guard's real +// effect was the opposite of its intent: on the tree the production ingest yields, a module's +// content hangs under exactly those edges, so the exclusion returned ZERO sites for the whole +// corpus while hand-built fixtures -- which carry no such edge -- stayed green. Isolated by +// disabling the arm and re-running the same fixture. The lesson is kept here rather than in a +// commit message because the guard looks obviously correct in isolation: a speculative exclusion +// over a shape the author has not observed is indistinguishable from a blackout until something +// executes against the real tree. + +// SPINE UNWRAPPING IS A MODULE-BOUNDARY MOVE AND IS DONE ONCE, AT THE ROOT, IN +// module_reference_sites BELOW. It used to run on EVERY node, which was wrong for a reason worth +// stating: namespace_graft_spine_segment_edge_optional recognises ANY single named edge targeting a +// Conj, not specifically a module-prefix spine segment, so applying it recursively silently dropped +// ordinary nested declaration and field labels from the position while continuing to walk -- which +// yields a mention recorded at a containment chain it does not sit at, and therefore resolved +// against the wrong lexical scope. A mislocated mention is worse than a missing one: it is a +// fabricated plausible answer (DESIGN section 5) rather than an absence someone can count. +// +// POSITION IS THE CONTAINMENT CHAIN OF THE MENTION, AND IT IS NOT THE INDEX'S PATH RULE. +// v2.compiler.symbol_index_fill specialises Disj (variant paths) and Arrow (domain only) because +// it is deciding WHERE A BINDING LIVES. This walk is deciding where a MENTION SITS, and a mention +// in an arrow's codomain sits exactly where its containment chain says it does -- so the rule here +// is uniform over edges: a named edge extends the position by its label, a positional edge does +// not. The two rules agree wherever a binding and a mention coincide and differ only where the +// index deliberately stops walking, which is the difference between the two questions rather than +// a divergence between two answers to one question. +// THE O(1) REJECT THAT KEEPS THIS WALK LINEAR IS INSIDE qualified_name_from_node ITSELF. +// +// qualified_name_from_node FOLDS AN ENTIRE SUBTREE before it can answer, and this walk then +// descends into that same subtree -- so asking it at every Conj made the traversal quadratic in +// nesting depth. DESIGN section 6 rules a proven cost-shape defect is always fixed regardless of +// the realised n, so a cheap precondition is required; the question was WHERE IT LIVES. +// +// IT WAS WRITTEN HERE FIRST AND THAT WAS A SECOND RECOGNISER FOR ONE CONCEPT. Two places deciding +// what a qualified-name spine looks like is section 3's nickname at the meaning layer, and the +// failure is silent and lands on exactly this PR's subject: widen the accepted spine in +// qualified_name and a prefilter sitting over here answers `false`, so this walk falls through to +// the children and emits every segment of `a.b.C` as its own BARE SAME-MODULE mention -- which is +// the cross-module class XL-0's denominator is made of, quietly turned into local noise. +// +// It was written here first, then moved beside that fold as a pair of Bool predicates, and is now +// the fold's OWN FIRST STEP -- because a Bool sitting beside the Outcome was still a second surface +// deciding the same thing, and section 2's test is net CONCEPTS rather than net files. This module +// matches the Outcome and gets the linear behaviour for free. +fn reference_sites_in_edge( + acc: ReferenceSiteCollection, + position: QualifiedName, + edge: Edge +) -> ReferenceSiteCollection { + match edge.label { + Named { name: sym } => + if dag_surface_module_header_metadata_edge(name: sym) { + acc + } else { + reference_sites_in_node( + acc: acc, + position: qualified_name_snoc(qn: position, segment: sym), + node: edge.target + ) + } + Positional => + reference_sites_in_node( + acc: acc, + position: position, + node: edge.target + ) + } +} + +fn reference_sites_in_children( + acc: ReferenceSiteCollection, + position: QualifiedName, + node: Node +) -> ReferenceSiteCollection { + fold(node.children, init: acc, f: fn(inner, edge) { + reference_sites_in_edge( + acc: inner, + position: position, + edge: edge + ) + }) +} + +fn collection_snoc_site( + acc: ReferenceSiteCollection, + site: ReferenceSite +) -> ReferenceSiteCollection { + ReferenceSiteCollection { + sites: list_snoc_item(xs: acc.sites, item: site), + unreadable_roots: acc.unreadable_roots + } +} + +// THE ACCUMULATOR IS THREADED, NEVER APPENDED. A walk that built a list per node and concatenated +// on the way up is the copied-accumulator cost shape DESIGN section 6 rules is always fixed +// regardless of the realised n, so the single list is carried down and snoc'd at the two emit +// points. Every recursion below therefore takes `acc` and returns the same list grown. +// A DOTTED MENTION IS ONE SITE, NOT ONE PER SEGMENT. `qualified_name_from_node` accepts only the +// fold-list-of-atoms shape an authored qualified spelling has, so a Conj it accepts IS the mention +// and its segment atoms are that mention's spelling rather than mentions of their own. Descending +// after emitting would count `a.b.C` four times. +// +// AN INT LITERAL ATOM CARRIES A VALUE, NOT A NAME: the resolver's own atom arm short-circuits it +// before any lookup, so admitting it here would manufacture an unbound mention the resolver never +// asks about. +fn reference_sites_in_node( + acc: ReferenceSiteCollection, + position: QualifiedName, + node: Node +) -> ReferenceSiteCollection { + match qualified_name_from_node(root: node) { + Accepted { value: qn, diagnostics: _ } => + if is_empty(xs: qn) { + reference_sites_in_children( + acc: acc, + position: position, + node: node + ) + } else { + collection_snoc_site( + acc: acc, + site: ReferenceSite { position: position, spelling: qn } + ) + } + Rejected { diagnostics: _ } => + match node.kind { + TypeNode { connective: Atom { identity: sym } } => + if dag_node_is_int_literal_atom(node: node) { + acc + } else { + collection_snoc_site( + acc: acc, + site: ReferenceSite { + position: position, + spelling: Cons { head: sym, tail: Empty } + } + ) + } + _ => + reference_sites_in_children( + acc: acc, + position: position, + node: node + ) + } + } +} + +type UnreadableModuleRoot { + locus: Locus +} + +// The collector's answer is the pair, never the sites alone, so a caller cannot take the population +// without also taking what was lost producing it. That is the shape section 5 asks for: the refusal +// travels WITH the result rather than beside it where it can be ignored. +// THERE IS NO IMPORT ARM, AND THE REASON IS A MEASUREMENT THAT REVERSED THE ORIGINAL DESIGN. +// +// This module carried one: import mentions were classified into a second `import_sites` list, +// threaded through the walk on an `inside_import` flag. It was built to fix a real defect -- a +// spelling match could not tell an import mention from a use, and this collector's own witness +// once read GREEN ON AN IMPORT LINE. THE FIX WAS AIMED AT A CONDITION THAT DOES NOT EXIST ON THIS +// ROUTE. Import statements are consumed before the normalized tree this collector walks, so the +// production identities the classifier keyed on never appear, the arm could not be inhabited by +// any input, and nothing read it. Measured: an import-only spelling in the fixture reaches neither +// list (v2.test.claim.namespace_xl0.call_argument_mention_survival). +// +// AN UNINHABITABLE ARM IS A DECORATION, WHICH IS THE RULE THIS PR APPLIES ONE FILE OVER AND FAILED +// TO APPLY HERE. dag/std/repair_input_origin declines to mint a KernelMinted arm on exactly this +// ground -- an arm with no producer is permanently uninhabited, and DESIGN section 4b calls that a +// decoration rather than a weak wall, worse than absent because it gets cited as coverage. Section +// 3c is the same verdict from the consumption side: a declaration whose consumer cannot be named +// is dangling, and it is red however well modeled it is. The earlier defence -- that a consumer +// walking a PARSE tree would want the classification -- named no consumer and no trigger, which is +// precisely what section 3c refuses to accept as a frontier. +// +// IF A PARSE-TREE CONSUMER EVER LANDS IT REBUILDS THIS, and that is the cheaper direction: the +// classifier was four production identities and a threaded Bool, while an uninhabitable arm is +// carried, reviewed and cited for as long as it stands. +type ReferenceSiteCollection { + sites: FreeMonoid + unreadable_roots: FreeMonoid +} + +fn empty_reference_site_collection() -> ReferenceSiteCollection { + ReferenceSiteCollection { sites: Empty, unreadable_roots: Empty } +} + +fn reference_site_collection_is_total(collection: ReferenceSiteCollection) -> Bool { + is_empty(xs: collection.unreadable_roots) +} + +// THE SPINE IS ONE WRAPPER PER SEGMENT, SO ONE UNWRAP WAS WRONG BY length(module_qn) - 1. +// +// v2.compiler.namespace_graft namespace_graft_fold_spine folds the module's qualified name and +// wraps ONCE PER SEGMENT. Unwrapping a single level left the remaining wrappers standing, and the +// generic named-edge rule below then walked them as ordinary containment -- re-appending those very +// segments to a position that already carried them, so a mention in `a.b.c` was recorded at +// `a.b.c.b.c`. A mislocated mention is a fabricated plausible answer (DESIGN section 5), and it +// changes which lexical scope the resolver walks, so it is worse than an absent one. +// +// THE COUNT IS DERIVED, NOT GUESSED. It is the length of the module qualified name this same walk +// already resolved from the header -- the identical value the spine was folded from -- rather than +// "keep unwrapping while the shape matches". That distinction is load-bearing: +// namespace_graft_spine_segment_edge_optional recognises ANY single named edge targeting a Conj, so +// a shape-driven loop would happily eat a genuine one-declaration module body. Consuming the count +// makes over-unwrapping unwritable rather than merely unlikely. +fn module_spine_unwrapped(root: Node, segments_remaining: Int) -> Node { + if segments_remaining <= 0 { + root + } else { + match namespace_graft_spine_segment_edge_optional(node: root) { + Present { value: spine_edge } => + module_spine_unwrapped( + root: spine_edge.target, + segments_remaining: segments_remaining - 1 + ) + Absent => root + } + } +} + +fn module_reference_sites( + acc: ReferenceSiteCollection, + root: Node +) -> ReferenceSiteCollection { + match qualified_name_from_module_node(root: root) { + Accepted { value: module_qn, diagnostics: _ } => + reference_sites_in_node( + acc: acc, + position: module_qn, + node: module_spine_unwrapped( + root: root, + segments_remaining: length(xs: module_qn) + ) + ) + Rejected { diagnostics: _ } => + ReferenceSiteCollection { + sites: acc.sites, + unreadable_roots: list_snoc_item( + xs: acc.unreadable_roots, + item: UnreadableModuleRoot { locus: node_locus(node: root) } + ) + } + } +} + +fn collect_module_reference_sites(root: Node) -> ReferenceSiteCollection { + module_reference_sites(acc: empty_reference_site_collection(), root: root) +} + +fn collect_reference_sites(roots: FreeMonoid) -> ReferenceSiteCollection { + fold_list( + xs: roots, + empty: empty_reference_site_collection(), + cons: fn(acc, root) { + module_reference_sites(acc: acc, root: root) + } + ) +} diff --git a/src/v2/compiler/repair_input_origin_roster.dag b/src/v2/compiler/repair_input_origin_roster.dag new file mode 100644 index 00000000000..b68b1ecfc2e --- /dev/null +++ b/src/v2/compiler/repair_input_origin_roster.dag @@ -0,0 +1,265 @@ +module v2.compiler.repair_input_origin_roster + +import std.algebra { Empty, FreeMonoid } +import std.decl_ref { DeclarationRef, decl_ref } +import std.dissolution { DissolutionCondition, unbound_dissolution } +import std.types { NonEmptyStr } +import std.repair_input_origin { + RepairInputDeclarationProvenance, + RepairInputDeclared, + RepairInputIdentityAbsent, + RepairInputIdentityAmbiguous, + RenderedTargetVocabularyCarrier, + RepairInputOriginCandidate, + RepairInputTargetWithoutDeclarationIdentity, + SourceCarrierCandidate, + SourceDeclarationCarrier, + SourceDeclarationCarrierIdentity +} +import v2.std.algebra { fold_list, is_empty, length, list_snoc_item, skip } +import v2.std.node { Node } +import v2.std.qualified_name { + QualifiedName, + qualified_name_to_dotted_string +} +import v2.std.symbol_index { SymbolIndex, empty_symbol_index } +import v2.std.logic { Bool } +import v2.std.text { String } +import v2.compiler.reference_site_collector { + ReferenceSiteCollection, + UnreadableModuleRoot, + collect_reference_sites +} +import v2.compiler.resolution_provenance { + ProvenanceAmbiguous, + ProvenanceOwnerless, + ProvenanceResolved, + ProvenanceUnbound, + ReferenceSite, + ResolutionProvenance, + answer_site, + module_roster_from_roots, + resolve_reference_sites +} +import v2.compiler.symbol_index_fill { symbol_index_fill_module_roots } + +// NAMESPACE-XL STAGE XL-0: THE REPAIR-INPUT ORIGIN DENOMINATOR, ON THE v2 ROUTE. +// +// gunbc.namespace_cut_stage StageXL0Denominator asks for source-declaration carriers plus rendered +// target-vocabulary carriers, separately typed, over one base, BEFORE eligibility or repair +// disposition. This module fills the source-declaration half from the resolver's own answers. It +// contains no filter: every mention v2.compiler.reference_site_collector finds becomes a row, and +// the four ways the resolver can answer become four provenance arms rather than an admitted set +// and a dropped one. A denominator that filtered would be measuring its filter. +// +// WHY THIS IS NOT THE SIX v1 CHANNELS PORTED. std.repair_input_origin's first half tags six +// candidate-bearing inputs of v1.compiler.emit_rust's Rust use-line planner. The v2 route emits no +// Rust use lines and has no such planner, so those six channels have no analogue here and +// reproducing them would mint a dying emitter's artifact on a route that never had the surface. +// What survives the route change is the QUESTION -- what does an import-to-containment repair take +// as input -- and on v2 that is a resolver fact rather than an emitter one. +// +// THE RENDERED HALF IS NOT PRODUCED HERE AND THAT IS NOT AN OMISSION. A rendered +// target-vocabulary carrier names a token minted by a target's rendered vocabulary; on the v2 +// route no stage renders a target vocabulary that mints names, so a producer for it would have no +// input. The arm stays declared on the shared base -- it is the v1 emitter's, for that route's +// lifetime -- and this module answers for the half it can establish rather than fabricating the +// half it cannot. + +// THE DECLARATION THE MENTION RESOLVED TO, KEPT AT ITS OWN GRAIN. +// +// `decl_name` is the WHOLE remainder of the target after its owning module, not the target's last +// segment. A variant lives at module.Type.Variant, so reducing it to `Variant` would make two +// variants of two types in one module one identity -- a name used as a key at the wrong grain, +// which is a different defect from a name used for display. The owner is the LONGEST rostered +// module prefix, so the remainder is exactly the declaration path inside that module. +// THIS DECLARATION IDENTITY IS DERIVED FROM A SPELLING, WHICH IS NOT THE SURVIVING AUTHORITY. +// +// carrier_declaration_ref reconstructs decl_name by dropping the owner prefix BY LENGTH and +// rendering the remainder to a dotted string. That is an identity invented from how a reference was +// SPELLED, and the v2 binding model being built in gunbc#11264 rules it out in terms that name this +// construction: no identity invented from a bare spelling, and no ordinal or scope derived from a +// filename, spelling or path. The relation it approximates already exists and is better founded -- +// std.occurrence_binding OccurrenceBindingResult over ScopedOccurrenceRef, which retains the +// reference occurrence AND the declaration's exact containment path instead of re-deriving either. +// +// IT IS ADMITTED AS A DECLARED FRONTIER RATHER THAN A FORK BECAUSE IT IS DORMANT, AND THE DORMANCY +// IS A MEASUREMENT, NOT A PLAN. XL-0 stands NotDerivable: the collector sees no cross-module +// reference on the production route, so the roster is EMPTY there and this function executes only +// over the hand-built trees in v2.test.claim.namespace_xl0.repair_input_origin_denominator. A second +// relation that currently answers nothing is not yet a second authority. It becomes one the moment +// the roster starts producing -- which is the same moment XL-0 stops being NotDerivable, so the two +// cannot diverge unobserved. +// +// The condition below is the section 3c trigger stated BESIDE the declaration rather than in a pull +// request body, because a reader who opens this module next month can reach an annotation here and +// cannot reach a discussion elsewhere. +data repair_input_declared_binding_frontier_dissolve_on: DissolutionCondition = unbound_dissolution(description: "DISSOLVE-ON, AT CAPABILITY GRAIN: when the v2 resolver emits std.occurrence_binding OccurrenceBindingResult over ScopedOccurrenceRef BY EXECUTION, std.repair_input_origin RepairInputDeclared.declaring is DERIVED from that binding's declaration containment path, and carrier_declaration_ref -- the owner-prefix drop plus dotted render in this module -- is DELETED rather than retained as a fallback, together with this row. RepairInputIdentityAmbiguous and RepairInputIdentityAbsent map onto that relation's own refusal arms instead of being decided here. NOT retired by gunbc#11264 merging: the trigger is the resolver ANSWERING by execution, because a landed carrier that nothing produces would satisfy a merge-shaped trigger while this spelling-derived identity stayed the only thing answering -- which is the grain mismatch DESIGN section 4b(3) forbids." as NonEmptyStr) + +fn carrier_declaration_ref(owner: QualifiedName, target: QualifiedName) -> DeclarationRef { + decl_ref( + module_path: qualified_name_to_dotted_string(qn: owner), + decl_name: qualified_name_to_dotted_string( + qn: skip(xs: target, n: length(xs: owner)) + ) + ) +} + +// THE FOUR RESOLVER ANSWERS BECOME FOUR PROVENANCE STATES, AND THE ONE COLLAPSE IS STATED. +// ProvenanceResolved with an EMPTY remainder means the mention named the owning module itself, so +// there is no declaration to cite; that is the same fact for a repair as ProvenanceOwnerless -- +// the target resolves and names no declaration -- so the two share one arm, deliberately, rather +// than an arm carrying an empty decl_name that no reader could distinguish from a lost one. +fn carrier_provenance(answer: ResolutionProvenance) -> RepairInputDeclarationProvenance { + match answer { + ProvenanceResolved { site: _, target: target, owner: owner } => + if length(xs: target) > length(xs: owner) { + RepairInputDeclared { + declaring: carrier_declaration_ref(owner: owner, target: target) + } + } else { + RepairInputTargetWithoutDeclarationIdentity { + target_spelling: qualified_name_to_dotted_string(qn: target) + } + } + ProvenanceOwnerless { site: _, target: target } => + RepairInputTargetWithoutDeclarationIdentity { + target_spelling: qualified_name_to_dotted_string(qn: target) + } + ProvenanceAmbiguous { site: _ } => RepairInputIdentityAmbiguous + ProvenanceUnbound { site: _ } => RepairInputIdentityAbsent + } +} + +fn carrier_from_answer(answer: ResolutionProvenance, site: ReferenceSite) -> RepairInputOriginCandidate { + SourceDeclarationCarrier { + identity: SourceDeclarationCarrierIdentity { + reference_position: qualified_name_to_dotted_string(qn: site.position), + authored_spelling: qualified_name_to_dotted_string(qn: site.spelling), + provenance: carrier_provenance(answer: answer) + } + } +} + +// ONE ROW PER MENTION, NEVER COLLAPSED. Two mentions of one name at two positions are two repair +// inputs, so the roster does not unique. v2.compiler.resolution_provenance makes the same +// distinction in the other direction -- its `answers` never collapse and only `dependencies` do -- +// and this fold consumes the uncollapsed half for exactly that reason. +fn repair_input_origin_roster_from_sites( + index: SymbolIndex, + module_roster: FreeMonoid, + sites: FreeMonoid +) -> FreeMonoid { + fold_list( + xs: resolve_reference_sites(index: index, roster: module_roster, sites: sites), + empty: Empty, + cons: fn(acc, answer) { + list_snoc_item( + xs: acc, + item: carrier_from_answer(answer: answer, site: answer_site(answer: answer)) + ) + } + ) +} + +// THE DENOMINATOR TRAVELS WITH WHAT WAS LOST PRODUCING IT. +// +// A roster returned as a bare list would let a caller read a number while the collector had +// silently failed to read some roots -- and for a DENOMINATOR that is not a slightly small answer, +// it is a different question answered under the same name. So the unreadable roots the collector +// counted are carried through rather than discarded at this seam, and a consumer that needs a TOTAL +// denominator asks roster_is_total before believing the population. +type RepairInputOriginRoster { + carriers: FreeMonoid + unreadable_roots: FreeMonoid +} + +fn repair_input_origin_roster_is_total(roster: RepairInputOriginRoster) -> Bool { + is_empty(xs: roster.unreadable_roots) +} + +// THE WHOLE DENOMINATOR OVER ONE BASE'S MODULE ROOTS: index, roster and sites all derived from the +// same roots, so no consumer can pair a roster with an index built from a different tree. +fn repair_input_origin_roster_over_roots( + roots: FreeMonoid +) -> RepairInputOriginRoster { + let collected = collect_reference_sites(roots: roots) + RepairInputOriginRoster { + carriers: repair_input_origin_roster_from_sites( + index: symbol_index_fill_module_roots(index: empty_symbol_index(), roots: roots), + module_roster: module_roster_from_roots(roots: roots), + sites: collected.sites + ), + unreadable_roots: collected.unreadable_roots + } +} + +// --------------------------------------------------------------------------------------------- +// THE DIGEST ENTRY POINT gunbc.namespace_cut_stage ActivationReceiptKind DenominatorRosterDigest +// CONSUMES. The receipt's digest is taken over THESE LINES and over nothing else, so the rendering +// is the digest's definition rather than a debug view of it: one line per mention, carrying the +// position, the authored spelling and the provenance arm, in the order the containment walk +// produced them. Order is part of the digest and is therefore not sorted here -- the walk is +// deterministic over a fixed tree, and re-sorting would hide a change in where a mention sits. +// +// NO RECEIPT ROW LANDS FROM THIS MODULE. An activation receipt is this rendering digested against +// ONE base the manager pins at ACT-0, and gunbc.namespace_cut_stage is explicit that a delivery +// receipt carries no base because it makes no claim about one. This is the producer; pinning is +// ACT-0's act. +// +// ACT-0 COMPOSES THE TWO FUNCTIONS THAT EXIST; THERE IS NO ROOTS-TAKING CONVENIENCE WRAPPER HERE. +// One was authored and deleted: it had no call site, and the delivery receipt names +// repair_input_origin_roster_over_roots as the producer rather than the wrapper, so the wrapper +// was not the frontier's named entry point and stating a frontier beside it did not make it one. +// A caller with roots writes repair_input_origin_roster_digest_lines over +// repair_input_origin_roster_over_roots, both of which the XL-0 witness exercises. +fn provenance_digest_token(provenance: RepairInputDeclarationProvenance) -> String { + match provenance { + RepairInputDeclared { declaring: declaring } => + concat( + "declared ", + declaring.module_path as String, + " ", + declaring.decl_name as String + ) + RepairInputTargetWithoutDeclarationIdentity { target_spelling: target_spelling } => + concat("no-declaration-identity ", target_spelling) + RepairInputIdentityAmbiguous => "ambiguous" + RepairInputIdentityAbsent => "unbound" + } +} + +// THE TWO v1-ROUTE ARMS CANNOT OCCUR IN A ROSTER THIS MODULE PRODUCES. They are matched by NAME +// rather than swept by a wildcard so that a fourth arm added to the shared base refuses to compile +// here instead of silently rendering as one of these -- and each renders to a line that is loud +// rather than absent, because a digest that skipped a row would report a smaller denominator with +// no evidence that anything was dropped. +fn carrier_digest_line(candidate: RepairInputOriginCandidate) -> String { + match candidate { + SourceDeclarationCarrier { identity: identity } => + concat( + identity.reference_position, + concat( + " ", + concat( + identity.authored_spelling, + concat(" ", provenance_digest_token(provenance: identity.provenance)) + ) + ) + ) + SourceCarrierCandidate { identity: _ } => "v1-source-carrier-candidate-not-produced-on-this-route" + RenderedTargetVocabularyCarrier { identity: _ } => "v1-rendered-target-vocabulary-carrier-not-produced-on-this-route" + } +} + +fn repair_input_origin_roster_digest_lines( + roster: FreeMonoid +) -> FreeMonoid { + fold_list( + xs: roster, + empty: Empty, + cons: fn(acc, candidate) { + list_snoc_item(xs: acc, item: carrier_digest_line(candidate: candidate)) + } + ) +} diff --git a/src/v2/compiler/resolution_provenance.dag b/src/v2/compiler/resolution_provenance.dag index 7727868e979..f4b3f59ed4a 100644 --- a/src/v2/compiler/resolution_provenance.dag +++ b/src/v2/compiler/resolution_provenance.dag @@ -11,7 +11,7 @@ import v2.std.algebra { } import v2.std.diagnostic { Accepted, Rejected } import v2.std.logic { Bool } -import v2.std.node { Node, Symbol } +import v2.std.node { Node, Symbol, symbol_eq } import v2.std.optional { Absent, Optional, @@ -72,10 +72,6 @@ fn provenance_qualified_name_eq(a: QualifiedName, b: QualifiedName) -> Bool { a == b } -fn provenance_symbol_eq(a: Symbol, b: Symbol) -> Bool { - a == b -} - fn module_roster_from_roots(roots: FreeMonoid) -> FreeMonoid { fold_list( xs: roots, @@ -106,7 +102,7 @@ fn provenance_owner_of_target( xs: roster, empty: optional_absent(), cons: fn(best, candidate) { - if is_prefix_of(prefix: candidate, xs: target, eq: provenance_symbol_eq) { + if is_prefix_of(prefix: candidate, xs: target, eq: symbol_eq) { match best { Absent => optional_present(value: candidate) Present { value: current } => diff --git a/src/v2/lens/fn_index_depth_agreement.dag b/src/v2/lens/fn_index_depth_agreement.dag index e027cf12ebc..7fdf53436eb 100644 --- a/src/v2/lens/fn_index_depth_agreement.dag +++ b/src/v2/lens/fn_index_depth_agreement.dag @@ -7,7 +7,7 @@ import v2.std.algebra { any, contains, fold_list, length, list_snoc_item } import v2.std.collection { Absent, List, Present } import v2.std.grammar { node_atom_identity_optional } import v2.std.logic { Bool } -import v2.std.node { Edge, Node, NodeFold, Symbol, fold_node, node_subtree_count } +import v2.std.node { Edge, Node, NodeFold, Symbol, fold_node, node_subtree_count, symbol_eq } import v2.std.node_query { call_callee_target, node_is_call } import v2.std.diagnostic { Accepted, Rejected } import v2.std.text { String, string_eq } @@ -62,12 +62,8 @@ data no_terminal_callees: List = [] data agreement_pool_roots: List = ["dag", "src/v2"] data agreement_pool_files: List = [] -fn agreement_symbol_eq(a: Symbol, b: Symbol) -> Bool { - a == b -} - fn snoc_unique(xs: List, sym: Symbol) -> List { - if contains(xs: xs, item: sym, eq: agreement_symbol_eq) { + if contains(xs: xs, item: sym, eq: symbol_eq) { xs } else { list_snoc_item(xs: xs, item: sym) diff --git a/src/v2/lens/module_graph.dag b/src/v2/lens/module_graph.dag index 6a4939af812..17643c9bff2 100644 --- a/src/v2/lens/module_graph.dag +++ b/src/v2/lens/module_graph.dag @@ -6,7 +6,7 @@ import v2.lens.common.construction_justification { ConstructionJustification, Wa import std.decl_ref { DeclarationRef, WholeDeclaration } import std.disposition { Disposition, Scaffold, SingleAuthority } import std.algebra { Cons, Empty, FreeMonoid } -import v2.std.algebra { any, contains, fold_list, list_append, list_reverse, list_snoc_item } +import v2.std.algebra { any, contains, fold_list, is_empty, list_append, list_reverse, list_snoc_item } import v2.std.collection { List, Map, @@ -19,9 +19,52 @@ import v2.std.optional { Optional, Present } -import v2.std.diagnostic { Outcome, outcome_accepted } +import v2.std.diagnostic { + Accepted, + Diagnostic, + ExternalContractUnknown, + Outcome, + Rejected, + Textual, + Unavailable, + WholeFile, + bind_outcome, + outcome_accepted, + outcome_rejected +} import v2.std.logic { Bool } +import v2.std.node { Node, Symbol, symbol_eq } +import v2.std.qualified_name { + QualifiedName, + qualified_name_to_dotted_string +} +import v2.std.symbol_index { + SymbolIndex, + empty_symbol_index +} import v2.std.text { String, string_eq } +import v2.compiler.program_assembly { located_module_roots_from_source_root_ingest } +import v2.compiler.reference_site_collector { + ReferenceSiteCollection, + UnreadableModuleRoot, + collect_module_reference_sites +} +import v2.compiler.resolution_provenance { + FileDependencyProvenance, + ReferenceSite, + module_dependencies_from_sites +} +import v2.compiler.source_authority { + SourceRef, + SourceRootIngest, + source_ref_for_storage_path +} +import v2.compiler.source_authority_read { source_root_ingest_from_source_refs } +import v2.compiler.symbol_index_fill { symbol_index_fill_module_root } +import v2.extdeps.languages.dag { + dag_language_model, + qualified_name_from_module_node +} type ModuleDeclarationFact { module: String @@ -40,7 +83,7 @@ type ModuleDependencyEdge { target_declared: Bool } -data dependency_edge_source_migration_note: String = "EDGE SOURCE, isolated as the single swappable fact producer (operator constraint, 2026-07-10, on the entry_file_touched reground): today dependency_resolution_facts_live unions import_resolution_facts_live with strict-tier reference_derived_import_resolution_facts_live (host twin selection_adjacency in cli_run.rs). The namespace-only resolution thread (operator-signed 2026-07-06) deletes the import grammar at its terminal step and derives dependencies from container.member references instead — when that lands, dependency_resolution_facts_live swaps to reference_derived_resolution_facts_flagged_pending_reference_producer and nothing above it changes: dependency_closure, import_closure, touched_path_in_closure, entry_affected_by_touched_paths, and every consumer of the closure query are edge-source-agnostic by construction (they read ModuleDependencyEdge rows as data, never import syntax). Do not add a second edge producer beside dependency_resolution_facts_live; the swap replaces its body." +data dependency_edge_source_migration_note: String = "EDGE SOURCE, isolated as the single swappable fact producer (operator constraint, 2026-07-10, on the entry_file_touched reground): today dependency_resolution_facts_live unions import_resolution_facts_live with strict-tier reference_derived_import_resolution_facts_live (host twin selection_adjacency in cli_run.rs). The namespace-only resolution thread (operator-signed 2026-07-06) deletes the import grammar at its terminal step and derives dependencies from container.member references instead — when that lands, dependency_resolution_facts_live swaps to reference_derived_resolution_facts and nothing above it changes: dependency_closure, import_closure, touched_path_in_closure, entry_affected_by_touched_paths, and every consumer of the closure query are edge-source-agnostic by construction (they read ModuleDependencyEdge rows as data, never import syntax). Do not add a second edge producer beside dependency_resolution_facts_live; the swap replaces its body." // Namespace-lane handoff specimens from gunbc#7908 (operator ruling 2026-08-06, msg_8e1c9e9d): // three closure-binding failures from #6848 import stripping that whole-tree compile-clean repaired @@ -60,12 +103,12 @@ data reference_derived_edge_source_disposition: Disposition = Scaffold { dissolves_to: SingleAuthority, bind: DeclarationRef { module_path: "v2.lens.module_graph", - decl_name: "reference_derived_resolution_facts_flagged_pending_reference_producer", + decl_name: "reference_derived_resolution_facts", field: WholeDeclaration } } -data reference_derived_edge_source_dissolution_note: String = "Scaffold producer for namespace terminal step (docs/plans/namespace-resolution-design.md §8 step 5): module-graph dependency edges derived from parsed-tree container.member qualified-name use sites (v2.lens.reference_deps.reference_resolution_facts_from_parsed_corpus census today; symbol_index_fill projection at steady state). Not wired into dependency_resolution_facts_live until the import grammar is deleted — dependency_resolution_facts_live already unions strict-tier host reference_resolution_facts with import_resolution_facts_live; this scaffold is the import-only stand-in for the terminal reference-only swap. Name suffix _pending_reference_producer marks that the body is still import-backed (interim stand-in), not parsed-tree reference-derived yet. On the import-only corpus the reference census matches import facts at module-prefix grain (reference_closure_b2_safety_wall_holds); this scaffold maps import facts through ModuleDependencyEdge until the swap repoints dependency_resolution_facts_live here without changing closure consumers." +data reference_derived_edge_source_dissolution_note: String = "XL-4 swap body: collect_module_reference_sites.sites plus module_dependencies_from_sites. Unreadable roots travel on ReferenceDerivedEdgeFold; production Outcome refuses on the first unreadable root (outcome_from_reference_derived_edge_fold). Import-syntax mentions dropped in the EDGE fold. File ingest is located_roots_from_source_root_ingest. Collector-only: do not feed v2.lens.reference_deps parse-QN sites. Frontiers: the DissolutionCondition rows beside this carrier." fn import_resolution_facts_live( pool_roots: List, @@ -181,19 +224,374 @@ fn dependency_resolution_facts_live( ) } -fn reference_derived_resolution_facts_flagged_pending_reference_producer( +data no_located_roots: List = [] + +data no_source_refs: List = [] + +data no_reference_derived_edges: List = [] + +data no_reference_sites: FreeMonoid = Empty + +type ReferenceDerivedPool { + index: SymbolIndex + trees: Map + roster: FreeMonoid + qn_by_path: Map +} + +type LocatedModuleRoot { + path: String + root: Node +} + +type ReferenceDerivedEdgeFold { + edges: List + unreadable_roots: FreeMonoid +} + +data empty_reference_derived_edge_fold: ReferenceDerivedEdgeFold = ReferenceDerivedEdgeFold { + edges: [], + unreadable_roots: Empty +} + +fn reference_derived_edge_fold_is_total(fold: ReferenceDerivedEdgeFold) -> Bool { + is_empty(xs: fold.unreadable_roots) +} + +fn reference_derived_path_excluded(path: String, exclude_substrings: List) -> Bool { + any(xs: exclude_substrings, predicate: fn(sub) { string_contains(s: path, sub: sub) }) +} + +fn reference_derived_path_under_roots(path: String, roots: List) -> Bool { + any(xs: roots, predicate: fn(root) { starts_with(s: path, prefix: concat(root, "/")) }) +} + +fn source_refs_from_declared(declared: List) -> List { + fold_list( + xs: declared, + empty: no_source_refs, + cons: fn(acc, fact) { + list_snoc_item(xs: acc, item: source_ref_for_storage_path(path: fact.path)) + } + ) +} + +// The path-to-tree association is read from the assembly fold that produced it +// (LocatedNormalizedTree), never recovered by zipping two lists positionally: a mislocated +// mention is a fabricated plausible answer (DESIGN 5), and a count check cannot tell a +// reordering from a correct pairing. An unpaired root has no representation here. +fn located_roots_from_source_root_ingest( + ingest: SourceRootIngest +) -> Outcome> { + bind_outcome( + o: located_module_roots_from_source_root_ingest(ingest: ingest, lm: dag_language_model()), + f: fn(located) { + outcome_accepted( + value: fold_list( + xs: located, + empty: no_located_roots, + cons: fn(acc, item) { + list_snoc_item( + xs: acc, + item: LocatedModuleRoot { path: item.path, root: item.tree.root } + ) + } + ) + ) + } + ) +} + +fn site_is_import_syntax_mention(site: ReferenceSite) -> Bool { + contains(xs: site.position, item: ^dag_surface_import_decl, eq: symbol_eq) + || contains(xs: site.position, item: ^dag_surface_import_block, eq: symbol_eq) + || contains( + xs: site.position, + item: ^dag_surface_import_decl_qualified_name, + eq: symbol_eq + ) +} + +fn reference_sites_excluding_import_syntax( + sites: FreeMonoid +) -> FreeMonoid { + fold_list( + xs: sites, + empty: no_reference_sites, + cons: fn(acc, site) { + if site_is_import_syntax_mention(site: site) { + acc + } else { + list_snoc_item(xs: acc, item: site) + } + } + ) +} + +fn snoc_reference_edge_unique( + acc: List, + edge: ModuleDependencyEdge +) -> List { + if any(xs: acc, predicate: fn(existing) { + string_eq(a: existing.path, b: edge.path) && string_eq(a: existing.target_module, b: edge.target_module) + }) { + acc + } else { + list_snoc_item(xs: acc, item: edge) + } +} + +fn edges_from_provenance_owners( + rel_path: String, + provenance: FileDependencyProvenance +) -> List { + fold_list( + xs: provenance.dependencies, + empty: no_reference_derived_edges, + cons: fn(acc, owner) { + snoc_reference_edge_unique( + acc: acc, + edge: ModuleDependencyEdge { + path: rel_path, + target_module: qualified_name_to_dotted_string(qn: owner), + target_declared: true + } + ) + } + ) +} + +fn load_reference_derived_pool( + declared: List +) -> Outcome { + bind_outcome( + o: source_root_ingest_from_source_refs(refs: source_refs_from_declared(declared: declared)), + f: fn(ingest) { + bind_outcome( + o: located_roots_from_source_root_ingest(ingest: ingest), + f: fn(items) { + outcome_accepted(value: reference_derived_pool_from_located_roots(items: items)) + } + ) + } + ) +} + +// The production site selection: every mention the collector yields MINUS import-syntax +// mentions. It is a fixed composition, not a mode - an unused import must never mint a +// reference-derived edge, and that property is not caller-selectable (DESIGN 3 meaning fork, +// DESIGN 5 escape hatch). The discriminating mutant that re-admits import mentions is +// composed at the test boundary from collect_module_reference_sites and +// reference_edges_for_located_root_sites, never through a flag here (review 65639). +fn sites_for_reference_edge_fold(root: Node) -> ReferenceSiteCollection { + let collected = collect_module_reference_sites(root: root) + ReferenceSiteCollection { + sites: reference_sites_excluding_import_syntax(sites: collected.sites), + unreadable_roots: collected.unreadable_roots + } +} + +fn emit_reference_edges_for_located_root( + item: LocatedModuleRoot, + pool: ReferenceDerivedPool +) -> ReferenceDerivedEdgeFold { + reference_edges_for_located_root_sites( + item: item, + pool: pool, + collected: sites_for_reference_edge_fold(root: item.root) + ) +} + +// Edge derivation over an already-selected site collection. Consumed by the production +// composition above and by the test-boundary mutant. +// THE ABSENT ARM IS REACHED ONLY FOR A ROOT THE COLLECTOR HAS ALREADY COUNTED AS UNREADABLE. +// The pool leaves a path out of qn_by_path exactly when qualified_name_from_module_node +// rejects the root, and reference_site_collector module_reference_sites rejects on the SAME +// call and snocs the root into unreadable_roots at its locus - one predicate, two consumers. +// So `edges: none` here is not a silent drop: `collected.unreadable_roots` carries the root, +// reference_derived_edge_fold_is_total answers false, and the production Outcome refuses. +// Executed evidence, both root shapes: +// v2.test.claim.reference_derived_graph_witness unreadable_root_is_counted_not_a_silent_leaf +// (bare Atom) and a_headerless_module_root_is_counted_unreadable_not_zero_edges (a Conj +// with a body and no header) - review 66859 on gunbc#11461 read this arm as uncounted; it +// is counted one call earlier, and counting it here again would double the roster. +fn reference_edges_for_located_root_sites( + item: LocatedModuleRoot, + pool: ReferenceDerivedPool, + collected: ReferenceSiteCollection +) -> ReferenceDerivedEdgeFold { + match map_lookup_where_rejected_unreachable(m: pool.qn_by_path, key: item.path) { + Absent => + ReferenceDerivedEdgeFold { + edges: no_reference_derived_edges, + unreadable_roots: collected.unreadable_roots + } + Present { value: module_qn } => + ReferenceDerivedEdgeFold { + edges: edges_from_provenance_owners( + rel_path: item.path, + provenance: module_dependencies_from_sites( + index: pool.index, + roster: pool.roster, + module_qn: module_qn, + sites: collected.sites + ) + ), + unreadable_roots: collected.unreadable_roots + } + } +} + +fn empty_reference_derived_pool() -> ReferenceDerivedPool { + ReferenceDerivedPool { + index: empty_symbol_index(), + trees: empty_map(), + roster: Empty, + qn_by_path: empty_map() + } +} + +fn reference_derived_pool_from_located_roots( + items: List +) -> ReferenceDerivedPool { + fold_list( + xs: items, + empty: empty_reference_derived_pool(), + cons: fn(pool, item) { + match qualified_name_from_module_node(root: item.root) { + Rejected { diagnostics: _ } => + ReferenceDerivedPool { + index: symbol_index_fill_module_root(index: pool.index, root: item.root), + trees: map_insert(m: pool.trees, key: item.path, value: item.root), + roster: pool.roster, + qn_by_path: pool.qn_by_path + } + Accepted { value: module_qn, diagnostics: _ } => + ReferenceDerivedPool { + index: symbol_index_fill_module_root(index: pool.index, root: item.root), + trees: map_insert(m: pool.trees, key: item.path, value: item.root), + roster: list_snoc_item(xs: pool.roster, item: module_qn), + qn_by_path: map_insert(m: pool.qn_by_path, key: item.path, value: module_qn) + } + } + } + ) +} + +fn reference_derived_edges_from_located_roots( + items: List +) -> ReferenceDerivedEdgeFold { + let pool = reference_derived_pool_from_located_roots(items: items) + fold_list( + xs: items, + empty: empty_reference_derived_edge_fold, + cons: fn(acc, item) { + let piece = emit_reference_edges_for_located_root(item: item, pool: pool) + ReferenceDerivedEdgeFold { + edges: list_append(left: acc.edges, right: piece.edges), + unreadable_roots: list_append(left: acc.unreadable_roots, right: piece.unreadable_roots) + } + } + ) +} + +// The pool is keyed from the same declared list the importer fold iterates, so an importer absent +// from it is a broken invariant (e.g. declared-path and ingest-path spellings disagree), never an +// importer with no references. It refuses with a typed, located cause rather than contributing an +// empty edge fold (review 64967 on gunbc#11202; DESIGN 5). +fn importer_absent_from_reference_pool() -> Outcome { + outcome_rejected( + d: Diagnostic { + reason: ^reference_derived_importer_absent_from_pool, + at: Textual { file: ^reference_derived_importer_absent_from_pool, extent: WholeFile }, + correction: Unavailable { reason: ExternalContractUnknown } + } + ) +} + +fn emit_reference_edges_for_importer( + fact: ModuleDeclarationFact, + pool: ReferenceDerivedPool +) -> Outcome { + match map_lookup_where_rejected_unreachable(m: pool.trees, key: fact.path) { + Absent => importer_absent_from_reference_pool() + Present { value: root } => + outcome_accepted( + value: emit_reference_edges_for_located_root( + item: LocatedModuleRoot { path: fact.path, root: root }, + pool: pool + ) + ) + } +} + +fn append_outcome_edge_folds( + acc: Outcome, + more: Outcome +) -> Outcome { + bind_outcome( + o: acc, + f: fn(acc_fold) { + bind_outcome( + o: more, + f: fn(more_fold) { + outcome_accepted( + value: ReferenceDerivedEdgeFold { + edges: list_append(left: acc_fold.edges, right: more_fold.edges), + unreadable_roots: list_append( + left: acc_fold.unreadable_roots, + right: more_fold.unreadable_roots + ) + } + ) + } + ) + } + ) +} + +fn outcome_from_reference_derived_edge_fold( + fold: ReferenceDerivedEdgeFold +) -> Outcome> { + match fold.unreadable_roots |> first { + Absent => outcome_accepted(value: fold.edges) + Present { value: unreadable } => + outcome_rejected( + d: Diagnostic { + reason: ^reference_derived_graph_unreadable_roots, + at: unreadable.locus, + correction: Unavailable { reason: ExternalContractUnknown } + } + ) + } +} + +fn reference_derived_resolution_facts( pool_roots: List, importer_roots: List, exclude_substrings: List ) -> Outcome> { - outcome_accepted( - value: dependency_edges_from_import_facts( - edges: import_resolution_facts_live( - pool_roots: pool_roots, - importer_roots: importer_roots, - exclude_substrings: exclude_substrings + let declared = module_declaration_facts_live(pool_roots: pool_roots) + |> filter(fact => !reference_derived_path_excluded(path: fact.path, exclude_substrings: exclude_substrings)) + bind_outcome( + o: load_reference_derived_pool(declared: declared), + f: fn(pool) { + bind_outcome( + o: fold_list( + xs: declared |> filter(fact => reference_derived_path_under_roots(path: fact.path, roots: importer_roots)), + empty: outcome_accepted(value: empty_reference_derived_edge_fold), + cons: fn(acc, fact) { + append_outcome_edge_folds( + acc: acc, + more: emit_reference_edges_for_importer(fact: fact, pool: pool) + ) + } + ), + f: fn(fold) { + outcome_from_reference_derived_edge_fold(fold: fold) + } ) - ) + } ) } @@ -488,4 +886,12 @@ data construction_justification: ConstructionJustification = ConstructionJustifi class: WallAfterGrounding { dissolves_to: SingleAuthority } } -data reference_derived_edge_source_dissolve_on: DissolutionCondition = unbound_dissolution(description: "the namespace terminal step (namespace-resolution-design section 8 step 5) makes container.member references the derived dependency authority, at which point this scaffold producer over parsed-tree use sites deletes") +data reference_derived_edge_source_dissolve_on: DissolutionCondition = unbound_dissolution(description: "NAMESPACE-XL STAGE XL-6 swaps dependency_resolution_facts_live onto this producer; until then the live edge source stays the import/reference union and this body stays the unused swap target") + +data reference_derived_call_contents_frontier: DissolutionCondition = unbound_dissolution(description: "Call-argument and callee mentions wait on eager-raven-113 lowering, then this ingest. Instruments: v2.test.claim.reference_derived_graph_production_ingest production_route_call_contents_are_missing_today_holds, production_route_callee_with_no_arguments_is_missing_today_holds; v2.test.claim.reference_derived_graph_call_arg_tree call_argument_only_reference_is_missing_from_parse_tree_today_holds, call_argument_only_reference_is_missing_from_normalized_tree_today_holds, body_value_outside_call_is_missing_from_parse_tree_today_holds, body_value_outside_call_is_missing_from_normalized_tree_today_holds.") + +data reference_derived_qualified_mention_frontier: DissolutionCondition = unbound_dissolution(description: "Qualified / dotted reference in any position waits on the dotted-reference capability. Type-shaped mentions additionally wait on filled-symbol-index Named edges (sleek-lynx-500 case 4: v2.test.claim.namespace.cross_module_resolve_witness, head reason resolve_reason_unbound_symbol). Instruments: v2.test.claim.reference_derived_graph_production_ingest production_route_reference_only_plain_value_is_missing_today_holds, production_route_both_plain_value_is_missing_today_holds, production_route_type_position_qualified_site_is_missing_today_holds, production_route_type_position_qualified_edge_is_missing_today_holds; v2.test.claim.reference_derived_graph_call_arg_tree type_position_only_is_missing_from_parse_tree_today_holds, type_position_only_is_missing_from_normalized_tree_today_holds.") + +data reference_derived_bare_field_type_frontier: DissolutionCondition = unbound_dissolution(description: "Bare FIELD type site is absent at the collector; tree-side census cause unverified. No collector trigger until those separate. Instruments: v2.test.claim.reference_derived_graph_production_ingest production_route_bare_field_type_site_is_missing_today_holds, production_tree_field_fixture_wrapper_name_unfindable_today_holds, production_tree_field_fixture_field_name_unfindable_today_holds, production_tree_field_fixture_field_type_unfindable_today_holds. Positive controls: production_route_bare_param_type_in_field_fixture_is_present_holds, production_tree_field_fixture_param_type_atom_is_present_holds, production_route_bare_local_type_position_site_is_present_holds.") + +data reference_derived_imported_bare_parameter_edge_frontier: DissolutionCondition = unbound_dissolution(description: "Imported bare parameter-type site is present and still yields no edge. Instruments: v2.test.claim.reference_derived_graph_production_ingest production_route_type_imported_bare_site_is_present_holds, production_route_type_imported_site_does_not_yield_edge_today_holds.") diff --git a/src/v2/lens/reference_deps.dag b/src/v2/lens/reference_deps.dag index b921ac1acb5..4acb9ff5d6c 100644 --- a/src/v2/lens/reference_deps.dag +++ b/src/v2/lens/reference_deps.dag @@ -9,6 +9,7 @@ import v2.std.algebra { contains, fold_list, list_reverse } import std.algebra { Cons, Empty, FreeMonoid } import v2.compiler.name_resolve { Admission, Import, ImportVisible, ResolutionSubject, resolve_diagnostics } import v2.std.text { string_eq } +import v2.std.node { symbol_eq } type ReferenceResolutionFact { @@ -31,13 +32,13 @@ type ReferenceResolutionCensus { data reference_deps_parsed_tree_disposition: Disposition = Scaffold { dissolves_to: SingleAuthority, bind: DeclarationRef { - module_path: "v2.lens.reference_deps", - decl_name: "reference_resolution_facts_from_parsed_corpus", + module_path: "v2.compiler.reference_site_collector", + decl_name: "collect_reference_sites", field: WholeDeclaration } } -data reference_deps_dissolution_note: String = "B2 reference edges from parsed-tree qualified-name use sites (imports + body/type refs via ingest → fold). Segment-prefix match against declared module paths (QualifiedName segments, not string scan). On the import-only corpus reference_closure_live delegates to import_closure_live_excluding (same edge producer, no O(n²) fact re-materialization). reference_parsed_tree_facts_match_import_facts_at_path is green-by-execution on the conformance entry (witnessed in reference_closure_b2_safety_wall_holds). reference_parsed_tree_matches_import_facts_on_closure and reference_closure_parsed_live are scaffold-only until interpreter parse-per-member cost is bounded; parsed_reference_closure_two_entry_no_result_observation carries the exact emitted-surface census subject that produced no result within its deadline, with deciding-stage reach explicitly unproven. reference_resolution_facts_from_parsed_corpus is the full-corpus scaffold census (no witness yet). Dissolves when symbol_index_fill projects reference edges from the filled containment tree and non-import qualified-name sites require the parsed census path." +data reference_deps_dissolution_note: String = "B2 reference edges from parsed-tree qualified-name use sites (imports + body/type refs via ingest → fold). Segment-prefix match against declared module paths (QualifiedName segments, not string scan). On the import-only corpus reference_closure_live delegates to import_closure_live_excluding (same edge producer, no O(n²) fact re-materialization). reference_parsed_tree_facts_match_import_facts_at_path is green-by-execution on the conformance entry (witnessed in reference_closure_b2_safety_wall_holds). reference_parsed_tree_matches_import_facts_on_closure and reference_closure_parsed_live are scaffold-only until interpreter parse-per-member cost is bounded; parsed_reference_closure_two_entry_no_result_observation carries the exact emitted-surface census subject that produced no result within its deadline, with deciding-stage reach explicitly unproven. reference_resolution_facts_from_parsed_corpus is the full-corpus scaffold census (no witness yet)." // NO EXECUTION RECEIPT, NO COST RESULT. // @@ -86,10 +87,6 @@ data empty_reference_facts: List = [] data empty_reference_refusals: List = [] -fn symbol_eq(a: Symbol, b: Symbol) -> Bool { - a == b -} - fn reference_ingest_refusal_diagnostic(refusal: ReferenceIngestRefusal) -> Diagnostic { Diagnostic { reason: refusal.reason, @@ -952,7 +949,27 @@ data construction_justification: ConstructionJustification = ConstructionJustifi class: WallAfterGrounding { dissolves_to: SingleAuthority } } -data reference_deps_dissolve_on: DissolutionCondition = unbound_dissolution(description: "the namespace terminal step lands and reference edges come from the containment authority rather than this segment-prefix match over parsed-tree qualified-name use sites (namespace-resolution-design section 8)") +// THE DISSOLUTION CONDITION IS REPOINTED (NAMESPACE-XL XL-0). The successor this row described +// abstractly -- "the containment authority" -- now exists by name: +// v2.compiler.reference_site_collector collect_reference_sites, which walks the tree the RESOLVER +// consumes rather than the parse tree, so its sites are things resolution resolves. The Scaffold +// disposition above binds to it. +// +// THE TRIGGER IS NOT "THE NAMESPACE STEP LANDS", AND THE TWO WALKERS STAND TOGETHER UNTIL IT FIRES. +// This lens keys on ^dag_surface_qualified_name and the import productions and carries NO dot or +// field-access handling, so it sees a qualified name in TYPE position and misses one in a BODY, +// which parses as a field access. The collector reads the normalized tree, where a qualified +// spelling is not that production at all, and misses both. Neither instrument covers the qualified +// class today, so this is a DECLARED FRONTIER rather than a consolidation, and the condition names +// the capability that actually ends it. +// +// STATED HERE AND NOT IN THE NARRATIVE ROW BESIDE IT. An earlier revision of this change appended +// the repoint to reference_deps_dissolution_note, a String whose lifecycle content was already +// EXTRACTED to this carrier -- gunbc.dissolution_migration_census classifies that row NarrativeOnly +// for exactly that reason. The result was one lifecycle condition in two places with two different +// contents, and the one a consumer reads was the stale one. DESIGN section 4c: a dissolution +// condition belongs in a typed carrier, and `//` is where the rationale goes. +data reference_deps_dissolve_on: DissolutionCondition = unbound_dissolution(description: "v2.compiler.reference_site_collector collect_reference_sites covers QUALIFIED reference sites, which waits on the dotted-reference capability -- a dotted spelling is not a qualified-name production in a body, so neither this lens nor that collector recognises it today. Landing the namespace terminal step does NOT satisfy this on its own.") fn collect_import_decl_nodes(n: Node, acc: FreeMonoid) -> FreeMonoid { let here = match parse_production_emitted_identity_optional(node: n) { diff --git a/src/v2/std/fn_index.dag b/src/v2/std/fn_index.dag index 8622b45fbad..69e634e78c1 100644 --- a/src/v2/std/fn_index.dag +++ b/src/v2/std/fn_index.dag @@ -23,7 +23,7 @@ import v2.std.compilers.lexing { symbol_lexeme } import v2.std.diagnostic { Accepted, Rejected } import v2.std.grammar { node_atom_identity_optional } import v2.std.logic { Bool } -import v2.std.node { Edge, Node, NodeFold, Symbol, fold_node } +import v2.std.node { Edge, Node, NodeFold, Symbol, fold_node, symbol_eq } import v2.std.node_query { call_callee_target, node_is_call } import v2.std.text { String } @@ -128,10 +128,6 @@ fn fn_index_string_eq(a: String, b: String) -> Bool { a == b } -fn fn_index_symbol_eq(a: Symbol, b: Symbol) -> Bool { - a == b -} - fn decl_module_prefix(mod_path: String) -> String { concat(mod_path, ".") } @@ -207,7 +203,7 @@ fn atom_identities_in_node(node: Node) -> List { let from_children = fold(node.children, init: empty_fn_arrow_symbol_list, f: fn(acc, e) { match node_atom_identity_optional(node: e.target) { Present { value: sym } => - if contains(xs: acc, item: sym, eq: fn_index_symbol_eq) { + if contains(xs: acc, item: sym, eq: symbol_eq) { acc } else { list_snoc_item(xs: acc, item: sym) @@ -217,7 +213,7 @@ fn atom_identities_in_node(node: Node) -> List { }) match node_atom_identity_optional(node: node) { Present { value: sym } => - if contains(xs: from_children, item: sym, eq: fn_index_symbol_eq) { + if contains(xs: from_children, item: sym, eq: symbol_eq) { from_children } else { list_snoc_item(xs: from_children, item: sym) @@ -236,7 +232,7 @@ fn atom_scan_init(n: Node) -> AtomScanState { } fn atom_scan_snoc(xs: List, sym: Symbol) -> List { - if contains(xs: xs, item: sym, eq: fn_index_symbol_eq) { + if contains(xs: xs, item: sym, eq: symbol_eq) { xs } else { list_snoc_item(xs: xs, item: sym) diff --git a/src/v2/std/node.dag b/src/v2/std/node.dag index 18e1690a526..39ca7d241ff 100644 --- a/src/v2/std/node.dag +++ b/src/v2/std/node.dag @@ -818,6 +818,12 @@ fn combine_hash(a: Fnv1a64Structural, b: Fnv1a64Structural) -> Fnv1a64Structural content_hash_combine_structural(left: a, right: b) } +// The one Symbol equality, owned by the module that owns Symbol. Consumers that need an `eq` +// callback (contains, dedup, ...) take this; a module-local `*_symbol_eq` alias re-mints it. +fn symbol_eq(a: Symbol, b: Symbol) -> Bool { + a == b +} + fn symbol_identity_digest(sym: Symbol) -> Hash { content_hash_atom(value: sym) } diff --git a/src/v2/std/qualified_name.dag b/src/v2/std/qualified_name.dag index 2d42e4c6837..41c841fb300 100644 --- a/src/v2/std/qualified_name.dag +++ b/src/v2/std/qualified_name.dag @@ -27,7 +27,7 @@ import v2.std.optional { } import v2.std.compilers.lexing { symbol_intern_lexeme, symbol_lexeme } import v2.std.logic { Bool } -import v2.std.node { Atom, Conj, Edge, Named, Node, NodeFold, Symbol, TypeNode, fold_node } +import v2.std.node { Atom, Conj, Edge, EdgeLabel, Named, Node, NodeFold, Positional, Symbol, TypeNode, fold_node } import v2.std.text { String } type QualifiedName = FreeMonoid @@ -72,6 +72,29 @@ fn qn_fold_init(n: Node) -> QnFoldStatus { } } +// THE SPINE LABEL SET, SPELLED ONCE. qn_fold_step consumes the role to choose its arm and +// qualified_name_spine_shape_present consumes it to gate; neither names ^fold_list_node_head +// or ^fold_list_node_tail itself (review 67072 on gunbc#11461: the gate had re-spelled the +// set the fold owns, so a renamed or added spine label would have narrowed acceptance silently). +type QnSpineRole + = QnSpineHead + | QnSpineTail + | QnNotSpine + +fn qn_spine_role(label: EdgeLabel) -> QnSpineRole { + match label { + Named { name: sym } => + if sym == ^fold_list_node_head { + QnSpineHead + } else if sym == ^fold_list_node_tail { + QnSpineTail + } else { + QnNotSpine + } + Positional => QnNotSpine + } +} + fn qn_fold_step(acc: QnFoldStatus, edge: Edge, child: QnFoldStatus) -> QnFoldStatus { match acc { QnFoldError { diag: d } => QnFoldError { diag: d } @@ -79,9 +102,8 @@ fn qn_fold_step(acc: QnFoldStatus, edge: Edge, child: QnFoldStatus) -> QnFoldSta match child { QnFoldError { diag: d } => QnFoldError { diag: d } QnFoldDone { qn: child_qn } => - match edge.label { - Named { name: ename } => - if ename == ^fold_list_node_head { + match qn_spine_role(label: edge.label) { + QnSpineHead => match edge.target.kind { TypeNode { connective: Atom { identity: _ } } => match child_qn { @@ -115,7 +137,7 @@ fn qn_fold_step(acc: QnFoldStatus, edge: Edge, child: QnFoldStatus) -> QnFoldSta correction: Unavailable { reason: ExternalContractUnknown } }} } - } else if ename == ^fold_list_node_tail { + QnSpineTail => match edge.target.kind { TypeNode { connective: Conj } => match acc { @@ -133,14 +155,7 @@ fn qn_fold_step(acc: QnFoldStatus, edge: Edge, child: QnFoldStatus) -> QnFoldSta correction: Unavailable { reason: ExternalContractUnknown } }} } - } else { - QnFoldError { diag: Diagnostic { - reason: ^qualified_name_structure_invalid, - at: node_locus(node: edge.target), - correction: Unavailable { reason: ExternalContractUnknown } - }} - } - _ => QnFoldError { diag: Diagnostic { + QnNotSpine => QnFoldError { diag: Diagnostic { reason: ^qualified_name_structure_invalid, at: node_locus(node: edge.target), correction: Unavailable { reason: ExternalContractUnknown } @@ -215,14 +230,48 @@ fn qualified_name_snoc(qn: QualifiedName, segment: Symbol) -> QualifiedName { list_snoc_item(xs: qn, item: segment) } +// THE O(1) SHAPE GATE LIVES INSIDE THE FOLD'S OWN ENTRY, NOT BESIDE IT. fold_node is a +// bottom-up catamorphism with no pruning, so a walker that folded every Conj re-folded every +// subtree it then descended into. The gate is the fold's first step so that no second surface +// re-spells which labels form the spine, and it is VERDICT-PRESERVING: the acceptance set of +// qualified_name_from_node is exactly what qn_fold_init / qn_fold_step already accepted - +// a zero-child Conj is the empty name, a two-child head/tail Conj is folded, and every other +// root is refused - only the refusal now happens before any child is folded. +fn qualified_name_spine_shape_present(root: Node) -> Bool { + match root.kind { + TypeNode { connective: Conj } => + if count(root.children) == 2 { + fold(root.children, init: true, f: fn(acc, edge) { + acc && (match qn_spine_role(label: edge.label) { + QnNotSpine => false + _ => true + }) + }) + } else { + false + } + _ => false + } +} + fn qualified_name_from_node(root: Node) -> Outcome { match root.kind { TypeNode { connective: Conj } => - let acc = fold_node(n: root, algebra: NodeFold { init: qn_fold_init, step: qn_fold_step }) - match acc { - QnFoldDone { qn: qn } => outcome_accepted(value: qn) - QnFoldError { diag: d } => outcome_rejected(d: d) - _ => outcome_rejected(d: Diagnostic { + if count(root.children) == 0 { + outcome_accepted(value: Empty) + } else if qualified_name_spine_shape_present(root: root) { + let acc = fold_node(n: root, algebra: NodeFold { init: qn_fold_init, step: qn_fold_step }) + match acc { + QnFoldDone { qn: qn } => outcome_accepted(value: qn) + QnFoldError { diag: d } => outcome_rejected(d: d) + _ => outcome_rejected(d: Diagnostic { + reason: ^qualified_name_structure_invalid, + at: node_locus(node: root), + correction: Unavailable { reason: ExternalContractUnknown } + }) + } + } else { + outcome_rejected(d: Diagnostic { reason: ^qualified_name_structure_invalid, at: node_locus(node: root), correction: Unavailable { reason: ExternalContractUnknown } diff --git a/src/v2/test/claim/declaring_identity_spelling/production_ingest_test.dag b/src/v2/test/claim/declaring_identity_spelling/production_ingest_test.dag new file mode 100644 index 00000000000..92fb97915d4 --- /dev/null +++ b/src/v2/test/claim/declaring_identity_spelling/production_ingest_test.dag @@ -0,0 +1,507 @@ +module v2.test.claim.declaring_identity_spelling.production_ingest + +import v2.compiler.declaring_identity_spelling_census { + DeclaringIdentitySpellingCensus, + spelling_census_from_ingest +} +import v2.compiler.normalized_tree { normalized_tree_roots_to_nodes } +import v2.compiler.program_assembly { module_roots_from_source_root_ingest } +import v2.compiler.reference_site_collector { collect_reference_sites } +import v2.compiler.resolution_provenance { + ProvenanceAmbiguous, + ProvenanceOwnerless, + ProvenanceResolved, + ProvenanceUnbound, + resolve_reference_provenance +} +import v2.compiler.source_authority { DagSourceReadWitness, SourceRootIngest } +import v2.compiler.symbol_index_fill { symbol_index_fill_module_roots } +import v2.extdeps.languages.dag { dag_language_model } +import v2.std.algebra { fold_list, is_empty } +import v2.std.artifact { Artifact, SourceFile } +import v2.std.cross_tree.import_model { V2Tree } +import v2.std.diagnostic { Accepted, Rejected } +import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } +import v2.std.collection { List } +import v2.std.logic { Bool } +import v2.std.node { Node, Symbol } +import v2.std.optional { Absent, Optional, Present, optional_absent, optional_present } +import v2.std.qualified_name { + qualified_name_last_segment, + qualified_name_snoc, + qualified_name_to_dotted_string +} +import v2.std.symbol_index { empty_symbol_index, symbol_index_lookup } +import v2.test.claim.provenance.cross_file_provenance { + cfp_index, + cfp_own_module_site, + cfp_roster +} +import std.algebra { Cons, Empty, FreeMonoid } +import std.declaring_identity_spelling { + IdentityUnbound, + IdentityAmbiguous, + IdentityOwnerless, + ResolvedSpelling, + UnresolvableSpelling +} +import extdeps.communication.medium { Lossless, Medium } +import extdeps.filesystem.filesystem_io + +data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree + +// FILE FIXTURES ARE THE AUTHORITY. Ingest reads those bytes via filesystem_read; there is +// no second inline copy of the same source. + +data value_outside_call_path: String = "src/v2/test/fixture/declaring_identity_spelling/value_outside_call.dag" + +data shorter_path: String = "src/v2/test/fixture/declaring_identity_spelling/shorter.dag" + +data unresolvable_path: String = "dag/test/probe/declaring_identity_spelling_unresolvable_probe.dag" + +data call_only_path: String = "src/v2/test/fixture/declaring_identity_spelling/call_only.dag" + +data matched_type_vs_value_path: String = "src/v2/test/fixture/declaring_identity_spelling/matched_type_vs_value.dag" + +data field_vs_parameter_path: String = "src/v2/test/fixture/declaring_identity_spelling/field_vs_parameter.dag" + +data cross_provider_path: String = "src/v2/test/fixture/declaring_identity_spelling/cross_provider.dag" + +data cross_consumer_path: String = "src/v2/test/fixture/declaring_identity_spelling/cross_consumer.dag" + +data qualified_cross_module_spelling: String = "v2.test.fixture.declaring_identity_spelling.cross_provider.Probe" + +data qualified_type_position_spelling: String = "v2.test.fixture.declaring_identity_spelling.cross_provider.ProvidedMarker" + +data qualified_field_type_spelling: String = "v2.test.fixture.declaring_identity_spelling.cross_provider.ProvidedFieldMarker" + +fn fixture_read(path: String, unit: Symbol) -> DagSourceReadWitness { + DagSourceReadWitness { + source: Medium { carried: filesystem_read(path: path).content, fidelity: Lossless }, + artifact: Artifact { + kind: SourceFile, + id: unit, + file_path: path + }, + compilation_unit: unit, + source_root: V2Tree + } +} + +fn authored_unbound(census: DeclaringIdentitySpellingCensus, spelling: String) -> Bool { + fold_list( + xs: census.rows, + empty: false, + cons: fn(acc, row) { + acc || match row { + UnresolvableSpelling { authored: authored, cause: cause } => + qualified_name_to_dotted_string(qn: authored) == spelling + && match cause { + IdentityUnbound => true + IdentityAmbiguous => false + IdentityOwnerless => false + } + ResolvedSpelling { authored: _, declaring: _, canonical: _, path_verdict: _ } => false + } + } + ) +} + +// ONE READ, ONE CENSUS PER FIXTURE, SHARED ACROSS THE CLAIM FRAMES. The required floor builds a +// fresh frame per claim, so each claim that parsed its own fixture re-derived the whole +// parse-and-normalize (gunbc#11461 run 35074340220: fifteen claims of this file +// COMPLETED-OVER-COST-REQUIREMENT at 130k-430k eval steps against the new-witness budget - +// gunbc.recurring_failure_mode.shared_precondition_re_derived_once_per_claim_frame). The reads +// are the world, so they are a PreparedEffectInput (xl3_fixture_reads, acquired once at +// preparation); the censuses are a CarriedInputWarmRow over it (xl3_fixture_censuses, +// ImplicitAcquisition) in v2.workflow.floor_pure_producer_share, and every claim below is a +// field read of that value. Each fixture is STILL its own single-file ingest - the census +// semantics are per file, never one combined ingest - so nothing a claim measures changed. +fn xl3_fixture_reads() -> SourceRootIngest { + Cons { + head: fixture_read(path: value_outside_call_path, unit: ^xl3_value_outside_call), + tail: Cons { + head: fixture_read(path: shorter_path, unit: ^xl3_shorter), + tail: Cons { + head: fixture_read(path: unresolvable_path, unit: ^xl3_unresolvable), + tail: Cons { + head: fixture_read(path: call_only_path, unit: ^xl3_call_only), + tail: Cons { + head: fixture_read(path: matched_type_vs_value_path, unit: ^xl3_matched_type_vs_value), + tail: Cons { + head: fixture_read(path: field_vs_parameter_path, unit: ^xl3_field_vs_parameter), + tail: Cons { + head: fixture_read(path: cross_provider_path, unit: ^xl3_cross_provider), + tail: Cons { + head: fixture_read(path: cross_consumer_path, unit: ^xl3_cross_consumer), + tail: Empty + } + } + } + } + } + } + } + } +} + +type Xl3PathCensus { + path: String + census: Optional +} + +type Xl3FixtureCensuses { + by_path: List + two_module: Optional + value_outside_call_roots: Optional> +} + +fn read_for_path(reads: SourceRootIngest, path: String) -> Optional { + fold_list( + xs: reads, + empty: Absent, + cons: fn(acc, w) { + match acc { + Present { value: found } => Present { value: found } + Absent => + if w.artifact.file_path == path { + optional_present(value: w) + } else { + optional_absent() + } + } + } + ) +} + +fn census_of_read(w: DagSourceReadWitness) -> Optional { + match spelling_census_from_ingest( + ingest: Cons { head: w, tail: Empty }, + lm: dag_language_model() + ) { + Accepted { value: census, diagnostics: _ } => Present { value: census } + Rejected { diagnostics: _ } => Absent + } +} + +fn path_census(reads: SourceRootIngest, path: String) -> Xl3PathCensus { + Xl3PathCensus { + path: path, + census: match read_for_path(reads: reads, path: path) { + Absent => Absent + Present { value: w } => census_of_read(w: w) + } + } +} + +fn xl3_fixture_censuses() -> Xl3FixtureCensuses { + let reads = xl3_fixture_reads() + let two = match read_for_path(reads: reads, path: cross_provider_path) { + Absent => Absent + Present { value: provider } => + match read_for_path(reads: reads, path: cross_consumer_path) { + Absent => Absent + Present { value: consumer } => + match spelling_census_from_ingest( + ingest: Cons { head: provider, tail: Cons { head: consumer, tail: Empty } }, + lm: dag_language_model() + ) { + Accepted { value: census, diagnostics: _ } => Present { value: census } + Rejected { diagnostics: _ } => Absent + } + } + } + let roots = match read_for_path(reads: reads, path: value_outside_call_path) { + Absent => Absent + Present { value: w } => + match module_roots_from_source_root_ingest( + ingest: Cons { head: w, tail: Empty }, + lm: dag_language_model() + ) { + Accepted { value: normalized, diagnostics: _ } => + Present { value: normalized_tree_roots_to_nodes(roots: normalized) } + Rejected { diagnostics: _ } => Absent + } + } + Xl3FixtureCensuses { + by_path: [ + path_census(reads: reads, path: value_outside_call_path), + path_census(reads: reads, path: shorter_path), + path_census(reads: reads, path: unresolvable_path), + path_census(reads: reads, path: call_only_path), + path_census(reads: reads, path: matched_type_vs_value_path), + path_census(reads: reads, path: field_vs_parameter_path) + ], + two_module: two, + value_outside_call_roots: roots + } +} + +// `unit` is the fixture's compilation-unit symbol as before; the census is served from the +// warm value keyed by path, so the same call sites read the same answer without re-parsing. +fn census_of(path: String, unit: Symbol) -> Optional { + fold_list( + xs: xl3_fixture_censuses().by_path, + empty: Absent, + cons: fn(acc, row) { + match acc { + Present { value: c } => Present { value: c } + Absent => + if row.path == path { + row.census + } else { + optional_absent() + } + } + } + ) +} + +fn census_unreadable_roots_empty(census: DeclaringIdentitySpellingCensus) -> Bool { + is_empty(xs: census.unreadable_roots) +} + +fn authored_is(census: DeclaringIdentitySpellingCensus, spelling: String) -> Bool { + fold_list( + xs: census.rows, + empty: false, + cons: fn(acc, row) { + acc || match row { + ResolvedSpelling { authored: authored, declaring: _, canonical: _, path_verdict: _ } => + qualified_name_to_dotted_string(qn: authored) == spelling + UnresolvableSpelling { authored: authored, cause: _ } => + qualified_name_to_dotted_string(qn: authored) == spelling + } + } + ) +} + +test fn value_outside_call_ingests_holds() -> Bool { + match census_of(path: value_outside_call_path, unit: ^xl3_value_outside_call) { + Present { value: census } => census_unreadable_roots_empty(census: census) + Absent => false + } +} + +test fn a_bare_value_mention_outside_a_call_reaches_the_census_holds() -> Bool { + match census_of( + path: value_outside_call_path, + unit: ^xl3_value_outside_call + ) { + Present { value: census } => authored_is(census: census, spelling: "marker") + Absent => false + } +} + +// CONTROL: the enrolled two-module provenance witness binds a same-module name +// on resolve_reference_provenance. If this is green, IdentityUnbound on the +// ingest census is not "v2 cannot compile a local name". +test fn enrolled_same_module_site_binds_on_the_resolution_path_holds() -> Bool { + match resolve_reference_provenance( + index: cfp_index, + roster: cfp_roster, + site: cfp_own_module_site + ) { + ProvenanceResolved { site: _, target: _, owner: _ } => true + ProvenanceOwnerless { site: _, target: _ } => false + ProvenanceAmbiguous { site: _ } => false + ProvenanceUnbound { site: _ } => false + } +} + +fn value_outside_call_roots() -> Optional> { + xl3_fixture_censuses().value_outside_call_roots +} + +fn marker_site_fill_lookup_is_present(roots: FreeMonoid) -> Bool { + let collected = collect_reference_sites(roots: roots) + let index = symbol_index_fill_module_roots(index: empty_symbol_index(), roots: roots) + fold_list( + xs: collected.sites, + empty: false, + cons: fn(acc, site) { + acc || ( + qualified_name_to_dotted_string(qn: site.spelling) == "marker" + && match qualified_name_last_segment(qn: site.spelling) { + Absent => false + Present { value: name } => + match symbol_index_lookup( + index: index, + qualified_path: qualified_name_snoc(qn: site.position, segment: name) + ) { + Present { value: _ } => true + Absent => false + } + } + ) + } + ) +} + +// INDEX-PATH ONLY, not a fact about 03_resolve. Parser-keyed fill lookup at the +// collector site's position. Green means fill never inserted `marker`; that is +// the step that makes the census row IdentityUnbound. +test fn ingest_fill_does_not_index_the_same_module_data_name_today() -> Bool { + match value_outside_call_roots() { + Present { value: roots } => !marker_site_fill_lookup_is_present(roots: roots) + Absent => false + } +} + +// Retracted as a compiler fact. Kept as an index-path measurement: the census +// row is Unbound because fill missed, not because the name cannot compile. +test fn a_bare_value_mention_outside_a_call_is_unbound_today() -> Bool { + match census_of( + path: value_outside_call_path, + unit: ^xl3_value_outside_call + ) { + Present { value: census } => authored_unbound(census: census, spelling: "marker") + Absent => false + } +} + +// BARE type name in PARAMETER position (fixture 1: `x: Marker`). Reaches. +// "Type position" is too coarse: a bare FIELD type does not reach. +test fn a_user_type_position_name_reaches_the_census_today() -> Bool { + match census_of( + path: shorter_path, + unit: ^xl3_shorter + ) { + Present { value: census } => authored_is(census: census, spelling: "Marker") + Absent => false + } +} + +test fn an_unbound_type_position_name_is_unresolvable_today() -> Bool { + match census_of( + path: unresolvable_path, + unit: ^xl3_unresolvable + ) { + Present { value: census } => + authored_unbound(census: census, spelling: "ThisNameIsNotDeclaredInThisFixture") + Absent => false + } +} + +test fn a_callee_name_is_absent_from_the_census_today() -> Bool { + match census_of( + path: call_only_path, + unit: ^xl3_call_only + ) { + Present { value: census } => + census_unreadable_roots_empty(census: census) + && authored_is(census: census, spelling: "LocalParam") + && !authored_is(census: census, spelling: "helper") + Absent => false + } +} + +// Census-row spelling "Int": kernel types have no corpus declaration. Not a +// type-position collector miss and not a lowering class. +test fn a_kernel_type_position_name_is_absent_from_the_census_today() -> Bool { + match census_of( + path: value_outside_call_path, + unit: ^xl3_value_outside_call + ) { + Present { value: census } => + authored_is(census: census, spelling: "marker") + && !authored_is(census: census, spelling: "Int") + Absent => false + } +} + +fn matched_census() -> Optional { + census_of( + path: matched_type_vs_value_path, + unit: ^xl3_matched_type_vs_value + ) +} + +// Same module, no call. User type_only in PARAMETER position REACHES. Imported +// Bool as a census-row spelling may still be absent here; that is not a collector +// parameter-type miss and is not a reason to hold fixtures 1-3. +test fn matched_value_only_mention_reaches_the_census_today() -> Bool { + match matched_census() { + Present { value: census } => authored_is(census: census, spelling: "value_only") + Absent => false + } +} + +test fn matched_user_type_position_mention_reaches_the_census_today() -> Bool { + match matched_census() { + Present { value: census } => authored_is(census: census, spelling: "type_only") + Absent => false + } +} + +test fn matched_imported_kernel_type_position_is_absent_from_the_census_today() -> Bool { + match matched_census() { + Present { value: census } => + authored_is(census: census, spelling: "value_only") + && !authored_is(census: census, spelling: "Bool") + Absent => false + } +} + +fn two_module_census() -> Optional { + xl3_fixture_censuses().two_module +} + +fn two_module_usable_class_probe(census: DeclaringIdentitySpellingCensus) -> Bool { + census_unreadable_roots_empty(census: census) + && authored_is(census: census, spelling: "LocalParam") +} + +// THE USABLE CLASS: a qualified cross-module value mention outside any call, and +// nothing else in the ingest can produce that spelling. Absent today. A bare +// same-module name is not this row. Goes red when the mention reaches the census. +// LocalParam is the positive control: Rejected ingest cannot green these. +test fn a_qualified_cross_module_mention_is_absent_from_the_census_today() -> Bool { + match two_module_census() { + Present { value: census } => + two_module_usable_class_probe(census: census) + && !authored_is(census: census, spelling: qualified_cross_module_spelling) + Absent => false + } +} + +// QUALIFIED parameter-type, no call. Same ingest as the value-position Probe miss. +// Absent while bare LocalParam reaches: this miss is qualification, not field position. +test fn a_qualified_type_position_mention_is_absent_from_the_census_today() -> Bool { + match two_module_census() { + Present { value: census } => + two_module_usable_class_probe(census: census) + && !authored_is(census: census, spelling: qualified_type_position_spelling) + Absent => false + } +} + +// QUALIFIED field type. Absent for two independent reasons (qualification AND +// field position) so it cannot discriminate. The discriminator is field_vs_parameter. +test fn a_qualified_field_type_mention_is_absent_from_the_census_today() -> Bool { + match two_module_census() { + Present { value: census } => + two_module_usable_class_probe(census: census) + && !authored_is(census: census, spelling: qualified_field_type_spelling) + Absent => false + } +} + +fn field_vs_parameter_census() -> Optional { + census_of( + path: field_vs_parameter_path, + unit: ^xl3_field_vs_parameter + ) +} + +// SAME ingest, BARE names, no dots. Parameter type reaches; field type does not. +// Qualification is not what the field miss measures. +test fn a_bare_parameter_type_reaches_while_a_bare_field_type_does_not() -> Bool { + match field_vs_parameter_census() { + Present { value: census } => + census_unreadable_roots_empty(census: census) + && authored_is(census: census, spelling: "ParamOnly") + && !authored_is(census: census, spelling: "FieldOnly") + Absent => false + } +} diff --git a/src/v2/test/claim/declaring_identity_spelling/verdict_fold_test.dag b/src/v2/test/claim/declaring_identity_spelling/verdict_fold_test.dag new file mode 100644 index 00000000000..0a42d81339a --- /dev/null +++ b/src/v2/test/claim/declaring_identity_spelling/verdict_fold_test.dag @@ -0,0 +1,129 @@ +module v2.test.claim.declaring_identity_spelling.verdict_fold + +import std.decl_ref { DeclarationRef, decl_ref } +import std.declaring_identity_spelling { + DeclaringIdentitySpelling, + IdentityUnbound, + IdentityAmbiguous, + IdentityOwnerless, + ResolvedAuthoredNotOnCanonicalPath, + ResolvedSpelling, + SpelledCanonically, + SpelledShorter, + UnresolvableSpelling, + declaring_identity_spelling_resolved, + declaring_identity_spelling_unresolvable, + resolved_path_verdict +} +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } +import v2.std.logic { Bool } +import v2.std.qualified_name { QualifiedName, qualified_name_from_dotted_string } + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +// HAND-BUILT INPUTS FOR THE VERDICT FOLD ONLY. These QualifiedName values are not +// collector output and are not production evidence. Production ingest subjects +// live under v2.test.claim.declaring_identity_spelling.production_ingest. + +data fold_fixture_module: String = "v2.test.fixture.declaring_identity_spelling.shorter" + +fn fold_canonical_marker() -> QualifiedName { + qualified_name_from_dotted_string( + dotted: "v2.test.fixture.declaring_identity_spelling.shorter.Marker" + ) +} + +fn fold_bare_marker() -> QualifiedName { + qualified_name_from_dotted_string(dotted: "Marker") +} + +fn fold_partial_marker() -> QualifiedName { + qualified_name_from_dotted_string( + dotted: "declaring_identity_spelling.shorter.Marker" + ) +} + +fn fold_off_path() -> QualifiedName { + qualified_name_from_dotted_string(dotted: "other.Marker") +} + +fn fold_declaring() -> DeclarationRef { + decl_ref( + module_path: fold_fixture_module, + decl_name: "Marker" + ) +} + +fn fold_resolved( + authored: QualifiedName +) -> DeclaringIdentitySpelling { + declaring_identity_spelling_resolved( + authored: authored, + declaring: fold_declaring(), + canonical: fold_canonical_marker() + ) +} + +test fn bare_authored_is_spelled_shorter_holds() -> Bool { + let row = fold_resolved(authored: fold_bare_marker()) + match row { + ResolvedSpelling { authored: _, declaring: _, canonical: _, path_verdict: verdict } => + match verdict { + SpelledShorter => true + SpelledCanonically => false + ResolvedAuthoredNotOnCanonicalPath => false + } + UnresolvableSpelling { authored: _, cause: _ } => false + } +} + +test fn full_path_is_spelled_canonically_holds() -> Bool { + let row = fold_resolved(authored: fold_canonical_marker()) + match row { + ResolvedSpelling { authored: _, declaring: _, canonical: _, path_verdict: verdict } => + match verdict { + SpelledCanonically => true + SpelledShorter => false + ResolvedAuthoredNotOnCanonicalPath => false + } + UnresolvableSpelling { authored: _, cause: _ } => false + } +} + +test fn partial_qualification_is_spelled_shorter_holds() -> Bool { + match resolved_path_verdict( + authored: fold_partial_marker(), + canonical: fold_canonical_marker() + ) { + SpelledShorter => true + SpelledCanonically => false + ResolvedAuthoredNotOnCanonicalPath => false + } +} + +test fn resolved_off_canonical_path_is_its_own_arm_holds() -> Bool { + match resolved_path_verdict( + authored: fold_off_path(), + canonical: fold_canonical_marker() + ) { + ResolvedAuthoredNotOnCanonicalPath => true + SpelledCanonically => false + SpelledShorter => false + } +} + +test fn unbound_is_unresolvable_holds() -> Bool { + let row = declaring_identity_spelling_unresolvable( + authored: qualified_name_from_dotted_string(dotted: "ThisNameIsNotDeclaredInThisFixture"), + cause: IdentityUnbound + ) + match row { + UnresolvableSpelling { authored: _, cause: cause } => + match cause { + IdentityUnbound => true + IdentityAmbiguous => false + IdentityOwnerless => false + } + ResolvedSpelling { authored: _, declaring: _, canonical: _, path_verdict: _ } => false + } +} diff --git a/src/v2/test/claim/namespace_xl0/call_argument_mention_survival_test.dag b/src/v2/test/claim/namespace_xl0/call_argument_mention_survival_test.dag new file mode 100644 index 00000000000..3eb16fd6c8e --- /dev/null +++ b/src/v2/test/claim/namespace_xl0/call_argument_mention_survival_test.dag @@ -0,0 +1,399 @@ +module v2.test.claim.namespace_xl0.call_argument_mention_survival + +import v2.compiler.program_assembly { module_roots_from_source_root_ingest } +import v2.compiler.normalized_tree { NormalizedTree, normalized_tree_roots_to_nodes } +import v2.compiler.reference_site_collector { + ReferenceSiteCollection, + collect_reference_sites, + empty_reference_site_collection, + reference_site_collection_is_total +} +import v2.compiler.resolution_provenance { ReferenceSite } +import v2.compiler.source_authority { DagSourceReadWitness, SourceRootIngest } +import v2.extdeps.languages.dag { dag_language_model, qualified_name_from_module_node } +import v2.std.algebra { fold_list, length } +import v2.std.artifact { Artifact, SourceFile } +import v2.std.cross_tree.import_model { DagTree } +import v2.std.diagnostic { Accepted, Outcome, Rejected } +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } +import v2.std.logic { Bool } +import v2.std.node { Node } +import v2.std.qualified_name { qualified_name_to_dotted_string } +import v2.std.text { String } +import v2.std.integer { Int } +import std.algebra { Cons, Empty, FreeMonoid } +import extdeps.communication.medium { Lossless, Medium } + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +// XL-0 / XL-4's SILENT-UNDERCOUNT PROBE, ASKED OF THE REAL PIPELINE RATHER THAN A SYNTHETIC TREE. +// +// WHY THIS EXISTS. The XL-0 denominator witness beside this one builds module roots by hand, which +// proves the collector's WALK is correct and proves nothing about the TREE a production caller +// hands it. The canonical route is v2.compiler.program_assembly +// module_roots_from_source_root_ingest, and its return type is FreeMonoid -- so a +// production caller walks a NORMALIZED tree. If normalization erases call expressions, then every +// reference that occurs only inside a call argument is invisible to the collector, and the XL-0 +// denominator and the XL-4 reference graph both undercount exactly that class WITHOUT SAYING SO. +// That is DESIGN section 5 silent wrongness, which is outside the ladder and forbidden outright, +// so it is asked here by execution instead of being reasoned about. +// +// THE PROJECTION OUT OF THE SEALED CARRIER IS THE MODELED ROUTE, NOT A DODGE. NormalizedTree is a +// sole_constructor carrier over a Node, and v2.compiler.normalized_tree normalized_tree_roots_to_nodes +// is its declared projection "for consumers genuinely about Node structure, not admission -- the +// symbol-index fill, for one". A reference-site walk is exactly that kind of consumer, and it is the +// same projection v2.compiler.symbol_index_fill consumes, so this probe reaches the collector the +// way a production caller would rather than by unwrapping the carrier by hand. +// +// THE FIXTURE IS SUBSTRATE-ONLY AND STILL EXERCISES THE REAL PARSE AND NORMALIZE. The source text +// is inline in a DagSourceReadWitness, so no host read happens, but the bytes go through the same +// ingest the compiler uses. +// +// THE DISCRIMINATOR IS A MATCHED PAIR, AND THE FIRST VERSION OF IT WAS BROKEN. It used one type +// named CallArgumentOnlyMention, which the fixture then mentioned TWICE -- once as a parameter type +// and once as a call argument -- so it was never call-only, and its absence could not distinguish +// "calls are erased" from "this collector finds nothing in this tree at all". A negative result +// does not defend itself. The pair below fixes that by varying ONE thing: +// +// xl0_no_call is referenced exactly once, in a body, OUTSIDE any call +// xl0_call_only is referenced exactly once, as a CALL ARGUMENT and nowhere else +// +// Both are module-level data declarations of the same type, both are referenced exactly once, and +// the only difference between them is whether that reference sits inside a call. So a green on the +// first with a red on the second isolates call erasure and nothing else, while a red on BOTH says +// the collector is blind to this tree generally and the probe is uninformative. +data xl0_provider_source: String = "module v2.test.xl0_provider\n\nimport v2.std.logic { Bool }\n\ndata xl0_provided_value: Bool = true\n" + +data call_argument_fixture_source: String = "module v2.test.xl0_call_fixture\n\nimport v2.std.logic { Bool }\n\nimport v2.std.optional { Absent }\n\ndata xl0_call_only: Bool = true\n\ndata xl0_no_call: Bool = true\n\nfn xl0_callee(probe: Bool) -> Bool { probe }\n\nfn xl0_outside() -> Bool { xl0_no_call }\n\ntype Xl0UserType {}\n\ntype Xl0FieldOnly {}\n\ntype Xl0Wrapper { fld: Xl0FieldOnly }\n\nfn xl0_typed(u: Xl0UserType) -> Bool { true }\n\nfn xl0_inside() -> Bool { xl0_callee(probe: xl0_call_only) }\n\nfn xl0_qualified_outside() -> Bool { v2.test.xl0_provider.xl0_provided_value }\n" + +fn xl0_provider_read() -> DagSourceReadWitness { + DagSourceReadWitness { + source: Medium { carried: xl0_provider_source, fidelity: Lossless }, + artifact: Artifact { + kind: SourceFile, + id: ^xl0_provider_fixture_read, + file_path: "src/v2/test/fixture/namespace_xl0/provider_fixture.dag" + }, + compilation_unit: ^xl0_provider_fixture_cu, + source_root: DagTree + } +} + +fn call_argument_fixture_read() -> DagSourceReadWitness { + DagSourceReadWitness { + source: Medium { carried: call_argument_fixture_source, fidelity: Lossless }, + artifact: Artifact { + kind: SourceFile, + id: ^xl0_call_argument_fixture_read, + file_path: "src/v2/test/fixture/namespace_xl0/call_argument_fixture.dag" + }, + compilation_unit: ^xl0_call_argument_fixture_cu, + source_root: DagTree + } +} + +data call_argument_fixture_ingest: SourceRootIngest = Cons { + head: xl0_provider_read(), + tail: Cons { head: call_argument_fixture_read(), tail: Empty } +} + +// THE INGEST IS A CROSS-CLAIM SHARED PURE PRODUCER, ENROLLED, AND TWO WEAKER REMEDIES FAILED FIRST. +// +// THE DEFECT. Every claim below needs the same parsed-and-normalized fixture, and the required +// floor builds a FRESH EVALUATION FRAME PER CLAIM -- deliberately, so one witness cannot +// contaminate the next -- so the real parse+normalize was re-derived once per claim. It did not +// fail; it came back `budget_interrupted` / `right_censored` against the operator's per-claim CPU +// deadline, which is NEITHER PASS NOR FAIL, so the lane blocked on the absence of a verdict rather +// than on a wrong answer. The instrument is the floor's own per-claim cost artifact, +// `required_floor_claim_cost.tsv`, whose rows for this module name the deadline and the interrupt. +// +// WHAT DID NOT WORK, RECORDED BECAUSE THE NEXT AUTHOR WILL REACH FOR IT. Hoisting the chain into +// module-scope `data` rows does not help: a `data` row is shared within ONE frame, and the thing +// being repeated here is the frame itself. Relocating the file under `long/` does not help either, +// because changed-witness selection plans a changed file regardless of its cadence. +// +// THE MODELED REMEDY IS THE ONE THE SUBSTRATE ALREADY CARRIES: v2.workflow.floor_pure_producer_share +// warms a nullary pure producer ONCE during strict preparation, outside every per-claim budget, and +// serves it to each claim. `call_argument_fixture_normalized` is enrolled WARM there. It is nullary, +// pure (the sources are inline, so no host read is dispatched), and its value reifies totally: +// Outcome> bottoms out in Nodes, symbols, strings and loci with no +// closure or evaluator-node reference at any depth. +// +// THE SEAM IS THE INGEST AND NOT THE COLLECTION, WHICH IS THAT ROSTER'S OWN RULE RATHER THAN A +// PREFERENCE: it enrolls parse rows and says normalize is deliberately not the share point, so that +// every claim still EXECUTES THE STAGE IT NAMES. The claims here name the COLLECTOR. Sharing the +// collection would hand each of them a precomputed answer to the question it is asking, which is a +// green bought by deleting the measurement. So the walk stays per claim -- it is a fold over two +// small roots -- and only the parse-and-normalize that no claim below is about is shared. +fn call_argument_fixture_normalized() -> Outcome> { + module_roots_from_source_root_ingest( + ingest: call_argument_fixture_ingest, + lm: dag_language_model() + ) +} + +fn fixture_roots() -> FreeMonoid { + match call_argument_fixture_normalized() { + Accepted { value: roots, diagnostics: _ } => normalized_tree_roots_to_nodes(roots: roots) + Rejected { diagnostics: _ } => Empty + } +} + +fn fixture_ingest_accepted() -> Bool { + match call_argument_fixture_normalized() { + Accepted { value: _, diagnostics: _ } => true + Rejected { diagnostics: _ } => false + } +} + +fn fixture_root_count() -> Int { + length(xs: fixture_roots()) +} + +fn fixture_collection() -> ReferenceSiteCollection { + collect_reference_sites(roots: fixture_roots()) +} + +fn fixture_sites() -> FreeMonoid { + fixture_collection().sites +} + +fn sites_mention(sites: FreeMonoid, spelling: String) -> Bool { + fold_list( + xs: sites, + empty: false, + cons: fn(acc, site) { acc || qualified_name_to_dotted_string(qn: site.spelling) == spelling } + ) +} + +// WHAT THE COLLECTOR ACTUALLY SEES ON THE PRODUCTION ROUTE, MEASURED, AS ENROLLED TESTS. +// +// These are not aspirations. Each asserts what executing the real ingest ACTUALLY produces today, +// so the file is green while the deficiency stands and goes RED the moment the deficiency is +// repaired -- which is the point: the repair must come back here and re-state what is true, rather +// than silently widening a denominator nobody re-measured. DESIGN section 4b(4) keeps a class's +// discriminating evidence enrolled after the climb; this is the same discipline applied before it. +// +// THE POPULATION THAT SURVIVES IS NARROWER THAN THIS FILE FIRST CLAIMED, AND THE CORRECTION IS THE +// MOST IMPORTANT ROW IN IT. +// +// SURVIVES: a BARE, SAME-MODULE value reference outside any call; a parameter reference; +// a TYPE-POSITION name +// DOES NOT: a QUALIFIED CROSS-MODULE reference, with or without a call +// a call argument; a callee name +// +// The first revision of these rows measured a bare same-module name and reported "a value +// reference outside any call is found", which read as though cross-module references survived. They +// do not. warm-ibex-518 measured a qualified cross-module reference on the XL-4 side and found +// nothing, which is what forced the discriminator now enrolled below -- two claims had been +// conflated, and the weaker one was stated as if it covered the stronger. +// +// WHY THE DISTINCTION IS THE WHOLE STORY RATHER THAN A REFINEMENT: a bare same-module name resolves +// to a declaration in its OWN module, so it yields no dependency edge and contributes nothing to an +// import-to-containment denominator, which is by definition about references that CROSS a module +// boundary. The surviving population is therefore the part neither XL-0 nor XL-4 has any use for. +// Stated plainly so no reader mistakes a non-empty site list for a working instrument: over the +// production route this collector currently sees nothing that either stage needs. +// THERE IS NO SINGLE RESTORATION TRIGGER FOR THE ROWS BELOW, AND AN EARLIER REVISION OF THIS NOTE +// CLAIMED THERE WAS. It said every red-stated row is restored by the v2 body-lowering repair. That +// is the section 4b(3) grain mismatch stated in DESIGN's own words -- a plural loss under a +// singular trigger -- and it contradicted the carriers that cite THIS MODULE as the instrument to +// re-run: gunbc.compiler_frontend_program_status StageXL0Denominator and +// gunbc.namespace_cut_stage both say body-lowering is NOT XL-0's trigger precisely because the +// cross-module class would still be missing after it lands. +// +// THE LOSSES BELOW ARE THREE CAPABILITIES, NOT ONE, AND NOTHING THAT RESTORES ONE RESTORES ANOTHER: +// +// call argument, callee name -> the v2 body-lowering repair that stops normalize erasing +// call expressions (XL-2, gunbc#11207) +// qualified / dotted reference -> the dotted-reference capability: a dotted spelling is +// (any position, body or type) not a qualified-name production in a body at all, so +// this is not downstream of call lowering. UNDER +// VERIFICATION, not assigned to a lane. +// bare type in FIELD position -> UNATTRIBUTED. The measurement is reproduced on two +// routes; the cause is not established, and if the +// declaration is absent from the tree then no +// collector-side trigger could ever fire. +// +// XL-0's denominator is made of the SECOND row -- references that cross a module boundary -- so +// StageXL0Denominator stays NotDerivable on the dotted-reference capability and on nothing else. +// A row here must never be retired by a trigger that does not restore it. + +test fn the_call_argument_fixture_ingests_holds() -> Bool { + fixture_ingest_accepted() +} + +test fn the_call_argument_fixture_yields_two_module_roots_holds() -> Bool { + fixture_root_count() == 2 +} + +// THE CONTROL THAT MAKES EVERY ROW BELOW MEAN SOMETHING: a mention outside any call, found by the +// same walk over the same tree. If this ever reds, the collector is blind generally and every +// deficiency row below is uninformative rather than a measurement. +test fn a_mention_outside_any_call_reaches_the_collector_holds() -> Bool { + sites_mention(sites: fixture_sites(), spelling: "xl0_no_call") +} + +test fn a_parameter_reference_reaches_the_collector_holds() -> Bool { + sites_mention(sites: fixture_sites(), spelling: "probe") +} + +// MEASURED DEFICIENCY 1: a reference occurring only as a call ARGUMENT does not reach the +// collector. Asserted as absent so this reds when the lowering repair lands. +test fn a_call_argument_mention_is_absent_from_the_denominator_today() -> Bool { + !sites_mention(sites: fixture_sites(), spelling: "xl0_call_only") +} + +// MEASURED DEFICIENCY 2: the CALLEE name of a call does not reach the collector either, so the +// erasure is of the whole call expression rather than of its arguments alone. +test fn a_callee_name_is_absent_from_the_denominator_today() -> Bool { + !sites_mention(sites: fixture_sites(), spelling: "xl0_callee") +} + +// WHAT "Bool REACHES THE COLLECTOR" ACTUALLY MEASURES, AND IT IS NOT WHAT ITS FIRST NAME CLAIMED. +// +// THIS ROW HAS BEEN WRONG TWICE IN OPPOSITE DIRECTIONS, AND THE SECOND CORRECTION WAS ALSO WRONG. +// First it asserted a type-position name was ABSENT, which was the truncated census talking. Then +// it asserted the name REACHED and I renamed it, on the theory that it was green for the wrong +// reason -- that the collector does not exclude import statements, that `Bool` appears in +// `import v2.std.logic { Bool }` in both fixture modules, and that a spelling match cannot tell an +// import mention from a type-position one. +// +// THAT THEORY IS RETRACTED AND IT IS RECORDED HERE RATHER THAN DELETED, because it was told to two +// sibling lanes. Imports are consumed before the normalized tree this collector walks, which the +// row below now measures: a spelling that exists ONLY on an import line reaches the collector in no +// form at all. So no `Bool` mention in `sites` can have come from an import line, and the row that +// asserted a type-position name reaches was correct as ORIGINALLY written. I renamed a correct row +// on a hypothesis I had not tested, which is the same error as the two measurement errors above, +// made one layer up in the explanation rather than in the fold. +// +// WHAT SURVIVES FROM XL-3'S RESULT IS STILL THE FINER SPLIT AND IS STILL THE REASON THE ROW BELOW +// EXISTS: an IMPORTED type name behaves differently from a USER-DECLARED one, so the honest +// type-position question is asked by `Xl0UserType`, which appears in no import anywhere. A test +// whose name claims more than its predicate measures is worse than a red one, because it is cited +// as coverage. +// +// This assertion was authored as "is absent" and passed, and it was WRONG: fixture_sites() folded the +// roots while discarding the accumulator, so it answered over the LAST root only. `Bool` is +// mentioned in both fixture modules, the provider's sites were the ones dropped, and the absence +// was manufactured by the fold rather than observed in the tree. Over the full population the name +// is present, and it is asserted that way here. +// +// THE COST OF THE WRONG VERSION WAS NOT LOCAL. It was reported to the XL-3 and XL-4 lanes as a +// measured deficiency; XL-3 was holding type-position census fixtures red on it, and XL-4 carried a +// type-position row on its declared frontier. A negative claim measured over a silently truncated +// population is exactly the fabricated plausible output DESIGN section 5 forbids, and it travelled +// further than the file it lived in. +// THE DISCRIMINATOR THAT SEPARATES A REAL TYPE-POSITION HIT FROM AN IMPORT-STATEMENT HIT. +// `Xl0UserType` is declared in this module and used ONLY as a parameter type -- it appears in no +// import statement anywhere, so a site spelling it can only have come from the type position. +test fn a_user_declared_type_in_parameter_position_reaches_the_collector_holds() -> Bool { + sites_mention(sites: fixture_sites(), spelling: "Xl0UserType") +} + +// EVERY root, not the last one. This fold dropped `acc` too -- the same defect the review found in +// fixture_sites(), in the same file, one screen below it. Answering for the last root while reading +// as though it answered for all of them is the identical silent truncation, so it is fixed the +// same way: the fold conjoins, and the empty case is the identity rather than a verdict. +test fn characterise_the_module_header_resolves_on_a_normalized_root() -> Bool { + fold_list( + xs: fixture_roots(), + empty: true, + cons: fn(acc, root) { + acc && match qualified_name_from_module_node(root: root) { + Accepted { value: _, diagnostics: _ } => true + Rejected { diagnostics: _ } => false + } + } + ) +} + +// BARE VERSUS QUALIFIED, THE DISCRIMINATOR XL-4'S RESULT FORCED. I reported "a value reference +// outside any call IS found" on the strength of a BARE same-module name. warm-ibex-518 measured a +// QUALIFIED cross-module value reference outside any call and found no edge. Those are two +// different claims and I had conflated them, which matters because a denominator and a dependency +// graph both care about the CROSS-MODULE case and almost not at all about the bare local one. +// `v2.test.xl0_provider.xl0_provided_value` is referenced exactly once, in a body, outside any +// call, and nothing else in either fixture module can produce that spelling. +test fn a_qualified_cross_module_reference_is_absent_from_the_denominator_today() -> Bool { + !sites_mention( + sites: fixture_sites(), + spelling: "v2.test.xl0_provider.xl0_provided_value" + ) +} + +// THE WALL THAT WOULD HAVE CAUGHT THE DEFECT THAT INVALIDATED EVERY NEGATIVE ROW ABOVE. +// +// fixture_sites() used to fold the roots with `cons: fn(acc, root) { collect_module_reference_sites( +// root: root).sites }` -- DISCARDING acc. It therefore returned only the LAST root's sites, and +// threw away .unreadable_roots at the same time. Every "is absent" row in this file is a NEGATIVE +// claim, and a negative claim is satisfied for free by a population that never contained the root +// in question: the census was truthful about a corpus of one module while reporting as though it +// covered two. The control was green by INGEST ORDERING, not by the walk -- reorder the reads and +// the whole census changes with no test naming why. +// +// TWO THINGS MADE IT INVISIBLE AND BOTH ARE THE SAME LESSON. It hand-rolled a traversal beside +// collect_reference_sites, which already threads the accumulator AND carries both halves -- the +// section 3 fork, in the one file whose job is measuring that collector. And it discarded the +// typed, counted refusal THIS PR ADDS precisely so a lost root cannot be mistaken for an empty +// one, at the only production-route call site in the PR. +// +// These two rows make the population itself a subject. The first pins the root count the census +// speaks for, so a fold that silently covers fewer reds instead of quietly agreeing. The second +// requires the collection to be total, so a root that could not be read can never be the reason an +// "is absent" row is green. +test fn the_census_population_covers_every_ingested_root_holds() -> Bool { + length(xs: fixture_roots()) == 2 && fixture_root_count() == 2 +} + +test fn the_census_population_has_no_unreadable_roots_holds() -> Bool { + reference_site_collection_is_total(collection: fixture_collection()) +} + +// IMPORTS DO NOT REACH THIS ROUTE, AND THE ASSERTION THAT SAID SO WAS ITSELF A DECORATION. +// +// WHAT THIS MEASURES AND WHY IT IS WORTH AN ENROLLED ROW. `Absent` is imported by the consumer +// fixture and used NOWHERE else, so it exists at exactly one point in the source: an import line. +// It reaches the collector not at all. That is the fact that retires an explanation I gave earlier +// in this file and told two sibling lanes -- that a type-position row of mine had been green on an +// `import ... { Bool }` line. It could not have been: import statements are consumed before the +// normalized tree this collector walks, so the `Bool` mentions in `sites` are real type positions. +// +// WHAT WAS REMOVED, AND IT IS THE SAME RULE THIS FILE APPLIES ELSEWHERE. The row used to also +// assert `is_empty(xs: fixture_import_sites())` against a second classified arm on the collector. +// Since no input on this route can populate that arm, the conjunct was PERMANENTLY GREEN BY +// CONSTRUCTION -- DESIGN section 4b's decoration, worse than absent because it gets cited as +// coverage. The header above it had already declined to author a control for exactly that reason +// and then enrolled the assertion anyway, which is the inconsistency rather than a second one. The +// arm is gone from v2.compiler.reference_site_collector, so what remains here is the measurement +// that actually discriminates: a spelling that exists ONLY on an import line reaches the collector +// in no form at all, and that row reds the moment imports begin surviving into this tree. +test fn an_import_only_spelling_does_not_reach_this_route_holds() -> Bool { + !sites_mention(sites: fixture_sites(), spelling: "Absent") + && sites_mention(sites: fixture_sites(), spelling: "Bool") +} + +test fn a_type_name_in_parameter_position_reaches_the_collector_holds() -> Bool { + sites_mention(sites: fixture_sites(), spelling: "Bool") + && sites_mention(sites: fixture_sites(), spelling: "Xl0UserType") +} + +// IS A BARE FIELD TYPE ITS OWN MISSING CLASS? The three-class rule this PR states -- bare reaches, +// qualified does not, calls erase their contents -- was measured on PARAMETER and BODY positions. +// XL-3 reported a field-type case absent and grouped it with the dotted rows, but their fixture's +// spelling leaves it open whether FIELD POSITION or QUALIFICATION is doing the work. If a BARE +// field type were absent, field position would be a fourth class and this PR's table would be +// wrong. +// +// `Xl0FieldOnly` is declared here, spelled BARE, and used in exactly one place: the field type of +// Xl0Wrapper. No dot, no parameter, no body. It isolates field position from qualification. +// +// IT IS ABSENT, SO FIELD POSITION IS A FOURTH CLASS AND NOT A DOTTED CASE. That matters for +// everyone's trigger: XL-3 measured a field-type miss and grouped it with the qualified rows, and +// this fixture shows qualification is not what is doing the work -- a BARE field type is missing +// too. A type-position claim that does not say WHICH type position is therefore too coarse: the +// same bare name reaches from a parameter and does not reach from a field. +test fn a_bare_field_type_is_absent_from_the_denominator_today() -> Bool { + !sites_mention(sites: fixture_sites(), spelling: "Xl0FieldOnly") + && sites_mention(sites: fixture_sites(), spelling: "Xl0UserType") +} diff --git a/src/v2/test/claim/namespace_xl0/field_type_tree_presence_test.dag b/src/v2/test/claim/namespace_xl0/field_type_tree_presence_test.dag new file mode 100644 index 00000000000..973cc70d133 --- /dev/null +++ b/src/v2/test/claim/namespace_xl0/field_type_tree_presence_test.dag @@ -0,0 +1,144 @@ +module v2.test.claim.namespace_xl0.field_type_tree_presence + +import v2.compiler.normalized_tree { normalized_tree_roots_to_nodes } +import v2.std.algebra { fold_list } +import v2.std.compilers.lexing { symbol_lexeme } +import v2.std.diagnostic { Accepted, Rejected } +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } +import v2.std.logic { Bool } +import v2.std.node { Atom, Edge, Named, Node, Positional, TypeNode, node_subtree_nodes } +import v2.std.text { String } +import v2.test.claim.namespace_xl0.call_argument_mention_survival { call_argument_fixture_normalized } +import std.algebra { Empty, FreeMonoid } + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +// COLLECTOR OR TREE, ASKED OF THE FIELD-TYPE ABSENCE BEFORE IT IS CALLED A CLASS. +// +// A bare field type is absent from the collector's output. That is measured. WHAT CAUSES IT IS NOT, +// and the dotted case is the reason not to guess: there, an absence measured through my own walker +// looked like a tree loss and was my own speculative exclusion. v2 must resolve record field types +// to typecheck anything at all, so a real normalize loss there would be surprising. +// +// This reads the ingested roots with node_subtree_nodes and a lexeme comparison -- NOT through +// v2.compiler.reference_site_collector -- so the answer cannot inherit the walker's blind spots. +// +// ATOM PRESENT -> the tree carries the field type and the COLLECTOR misses the +// type-declaration field representation. No fourth class; a collector fix. +// ATOM ABSENT -> normalization drops field types, which is a lowering-class finding with a +// trigger of its own. +// +// THE CONTROL IS THE PAIR, NOT THE ROW. `Xl0UserType` is the same kind of locally declared bare +// type name and DOES reach the collector, so it must be present in the tree too. If the control is +// absent, this probe is reading the wrong tree and says nothing about fields. +// THE INGEST IS THE SIBLING MODULE'S ENROLLED WARM PRODUCER, NOT A SECOND CALL TO THE SAME STAGE. +// +// Both folds below need the same parsed-and-normalized fixture, and they used to reach it by +// calling module_roots_from_source_root_ingest directly -- twice per claim, over the same two +// inline sources the sibling module already ingests. Under the required floor that is fatal rather +// than merely slow: the floor builds a fresh evaluation frame per claim, so every claim in this +// file re-derived the whole ingest and came back budget-refused before reaching a verdict, which is +// neither pass nor fail. Measured: on run 34738510974 these four claims are the ONLY +// budget-refused-before-verdict rows in the entire required floor. +// +// v2.test.claim.namespace_xl0.call_argument_mention_survival call_argument_fixture_normalized is +// already enrolled WARM in v2.workflow.floor_pure_producer_share, so it is forced once during +// strict preparation, outside every per-claim budget. Consuming it here needs no second roster row +// and deletes a duplicated call site at the same time -- one producer, two consuming files, which +// is what DESIGN section 2 asks for rather than two enrolments of one stage. +// +// THE PROBE IS UNAFFECTED, WHICH IS THE ONLY THING THAT COULD HAVE MADE THIS A BAD TRADE. What is +// shared is the INGEST; what this file measures is the shape of the tree that ingest produces, and +// both folds below still walk it themselves. Sharing the stage a claim NAMES would hand it its own +// answer; sharing the stage that merely feeds it does not. +fn fixture_atom_lexemes() -> FreeMonoid { + match call_argument_fixture_normalized() { + Accepted { value: roots, diagnostics: _ } => + fold_list( + xs: normalized_tree_roots_to_nodes(roots: roots), + empty: Empty, + cons: fn(outer, root) { + fold(node_subtree_nodes(root: root), init: outer, f: fn(acc, n) { + match n.kind { + TypeNode { connective: Atom { identity: sym } } => + concat(acc, [symbol_lexeme(sym: sym)]) + _ => acc + } + }) + } + ) + Rejected { diagnostics: _ } => Empty + } +} + +fn atom_present(lexeme: String) -> Bool { + any(fixture_atom_lexemes(), s => s == lexeme) +} + +// ATOMS ARE NOT THE ONLY PLACE A NAME LIVES, AND MY OWN CONTROL PROVED IT. The Xl0Wrapper row +// below fails because a type DECLARATION name is an EDGE LABEL, never a node -- which is the very +// fact this collector's design rests on. So an atom-only search cannot establish absence: it +// establishes "not an atom". This collects the other half, every Named edge label in the tree, so +// "absent" can mean absent from BOTH representations rather than from the one I happened to check. +fn fixture_edge_label_lexemes() -> FreeMonoid { + match call_argument_fixture_normalized() { + Accepted { value: roots, diagnostics: _ } => + fold_list( + xs: normalized_tree_roots_to_nodes(roots: roots), + empty: Empty, + cons: fn(outer, root) { + fold(node_subtree_nodes(root: root), init: outer, f: fn(acc, n) { + fold(n.children, init: acc, f: fn(inner, e) { + match e.label { + Named { name: sym } => concat(inner, [symbol_lexeme(sym: sym)]) + Positional => inner + } + }) + }) + } + ) + Rejected { diagnostics: _ } => Empty + } +} + +fn label_present(lexeme: String) -> Bool { + any(fixture_edge_label_lexemes(), s => s == lexeme) +} + +fn present_anywhere(lexeme: String) -> Bool { + atom_present(lexeme: lexeme) || label_present(lexeme: lexeme) +} + +test fn control_a_parameter_type_name_is_an_atom_in_the_tree_holds() -> Bool { + atom_present(lexeme: "Xl0UserType") +} + +// CONTROL, CORRECTED: a type DECLARATION name is an edge label, not an atom. Asserting it as an +// atom was my error and its red said nothing about the tree. Asserted where it actually lives. +test fn the_record_type_declaration_is_absent_from_the_tree_today() -> Bool { + !present_anywhere(lexeme: "Xl0Wrapper") +} + +// WHAT WAS MEASURED, AND WHY IT IS NOT YET ATTRIBUTED TO ANYONE. +// +// The fixture source demonstrably contains `type Xl0Wrapper { fld: Xl0FieldOnly }`, the ingest +// ACCEPTS and yields both module roots, and the parameter-type control above finds Xl0UserType as +// an atom. Yet the record declaration's NAME, its FIELD name, and the field's TYPE are ALL absent +// from the ingested tree, in atoms and in edge labels alike. So the missing thing is not "field +// types" -- it is the whole record-type-with-a-field declaration. +// +// TWO HYPOTHESES REMAIN AND THIS FIXTURE CANNOT SEPARATE THEM: normalization drops such a +// declaration, or it is represented in some third way neither an atom search nor a label search +// reaches. I am not naming a capability on that, because the last four times I attributed an +// absence measured through one representation, the representation was the defect. The rows are +// therefore enrolled as MEASUREMENTS of what the search finds today, and the PR carries the cause +// as unverified. +test fn the_bare_field_type_is_absent_from_the_tree_today() -> Bool { + !present_anywhere(lexeme: "Xl0FieldOnly") +} + +// The field NAME itself, as a third data point: if `fld` is a label but its TYPE is nowhere, the +// declaration survived and only the type reference inside it was dropped. +test fn the_field_name_is_absent_from_the_tree_today() -> Bool { + !present_anywhere(lexeme: "fld") +} diff --git a/src/v2/test/claim/namespace_xl0/repair_input_origin_denominator_test.dag b/src/v2/test/claim/namespace_xl0/repair_input_origin_denominator_test.dag new file mode 100644 index 00000000000..36e53d904eb --- /dev/null +++ b/src/v2/test/claim/namespace_xl0/repair_input_origin_denominator_test.dag @@ -0,0 +1,264 @@ +module v2.test.claim.namespace_xl0.repair_input_origin_denominator + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +// NAMESPACE-XL XL-0's executing evidence. Two subjects, and they fail for different reasons: +// the COLLECTOR (which mentions exist, and at what containment position) and the ROSTER (what +// answered each mention). A witness over only the second would be green with a collector that +// found half the tree, because a denominator's defect is a row that is not there. + +fn xl0_qn_spine(segments: FreeMonoid) -> Node { + fold_list_node( + xs: segments, + item_node: fn(sym) { + Node { + kind: TypeNode { connective: Atom { identity: sym } }, + children: [], + occurrence_id: OccurrenceSynthetic + } + } + ) +} + +fn xl0_module_root(qn_spine: Node, exports: List) -> Node { + Node { + kind: TypeNode { connective: Conj }, + children: concat( + [ + dag_named_edge( + name: ^dag_surface_module_header, + target: dag_grammar_atom(id: ^dag_surface_module_header) + ), + dag_named_edge( + name: ^dag_surface_module_header_qualified_name, + target: qn_spine + ) + ], + exports + ), + occurrence_id: OccurrenceSynthetic + } +} + +fn xl0_atom(sym: Symbol) -> Node { + Node { + kind: TypeNode { connective: Atom { identity: sym } }, + children: [], + occurrence_id: OccurrenceSynthetic + } +} + +// A declaration whose BODY is a mention of some other name -- the realistic `type X = Y` shape. +// The declared name X is an EDGE LABEL and the mentioned name Y is the NODE, which is the whole +// structural reason the collector needs no filter to tell a declaration from a reference. +fn xl0_declaration_of(decl_sym: Symbol, body: Node) -> Edge { + Edge { label: Named { name: decl_sym }, target: body } +} + +data xl0_producer_qn: FreeMonoid = qualified_name_from_dotted_string( + dotted: "v2.test.xl0_producer" +) + +data xl0_consumer_qn: FreeMonoid = qualified_name_from_dotted_string( + dotted: "v2.test.xl0_consumer" +) + +data xl0_producer_root: Node = xl0_module_root( + qn_spine: xl0_qn_spine(segments: xl0_producer_qn), + exports: [ + xl0_declaration_of(decl_sym: ^Xl0Marker, body: xl0_atom(sym: ^Xl0Marker)), + xl0_declaration_of(decl_sym: ^Xl0Helper, body: xl0_atom(sym: ^Xl0Helper)) + ] +) + +data xl0_consumer_root: Node = xl0_module_root( + qn_spine: xl0_qn_spine(segments: xl0_consumer_qn), + exports: [ + xl0_declaration_of(decl_sym: ^Xl0BareUse, body: xl0_atom(sym: ^Xl0Marker)), + xl0_declaration_of( + decl_sym: ^Xl0QualifiedUse, + body: xl0_qn_spine( + segments: qualified_name_from_dotted_string(dotted: "v2.test.xl0_producer.Xl0Helper") + ) + ), + xl0_declaration_of(decl_sym: ^Xl0MissingUse, body: xl0_atom(sym: ^Xl0NeverDeclared)) + ] +) + +data xl0_roots: FreeMonoid = Cons { + head: xl0_producer_root, + tail: Cons { head: xl0_consumer_root, tail: Empty } +} + +data xl0_consumer_sites: FreeMonoid = collect_module_reference_sites(root: xl0_consumer_root).sites + +fn xl0_site_spelling(site: ReferenceSite) -> String { + qualified_name_to_dotted_string(qn: site.spelling) +} + +fn xl0_site_position(site: ReferenceSite) -> String { + qualified_name_to_dotted_string(qn: site.position) +} + +fn xl0_any_site(sites: FreeMonoid, f: fn(ReferenceSite) -> Bool) -> Bool { + fold_list(xs: sites, empty: false, cons: fn(acc, site) { acc || f(site) }) +} + +fn xl0_count_sites_spelled(sites: FreeMonoid, spelling: String) -> Int { + fold_list( + xs: sites, + empty: 0, + cons: fn(acc, site) { if xl0_site_spelling(site: site) == spelling { acc + 1 } else { acc } } + ) +} + +// RED 1 -- THE ONE THAT DISCRIMINATES A COLLECTOR FROM A SYMBOL SWEEP. A declared name is an edge +// label and must never be reported as a mention of itself, and the module header's own qualified +// name is a declaration of position rather than a mention of anything. A collector that walked +// edge labels, or descended into the header subtree, is green on every other clause in this file +// and red here. +// The third clause below is the positive half, so the first two cannot be satisfied by a +// collector that found nothing at all. +test fn declared_names_and_the_module_header_are_not_mentions_holds() -> Bool { + let no_declared_name_reported = + xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "Xl0BareUse") == 0 + && xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "Xl0QualifiedUse") == 0 + && xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "Xl0MissingUse") == 0 + let no_header_segment_reported = + xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "v2") == 0 + && xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "test") == 0 + && xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "xl0_consumer") == 0 + let the_three_bodies_are_reported = + length(xs: xl0_consumer_sites) == 3 + && xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "Xl0Marker") == 1 + && xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "Xl0NeverDeclared") == 1 + no_declared_name_reported && no_header_segment_reported && the_three_bodies_are_reported +} + +// RED 2 -- A DOTTED MENTION IS ONE SITE. `v2.test.xl0_producer.Xl0Helper` is four atoms in the +// tree and one reference in the source. A walk that emitted a site per atom reports four mentions +// and a denominator four times too large, and it also loses the only spelling that resolves. +test fn a_dotted_mention_is_one_site_not_one_per_segment_holds() -> Bool { + xl0_count_sites_spelled( + sites: xl0_consumer_sites, + spelling: "v2.test.xl0_producer.Xl0Helper" + ) == 1 + && xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "Xl0Helper") == 0 + && xl0_count_sites_spelled(sites: xl0_consumer_sites, spelling: "xl0_producer") == 0 +} + +// RED 3 -- POSITION IS THE MENTION'S CONTAINMENT CHAIN, NOT ITS MODULE. Two mentions in one module +// at two positions are two repair inputs; a collector that stamped every site with the module +// qualified name would make them indistinguishable and would also change how the resolver walks +// the containment chain to answer them. +test fn a_mention_sits_at_its_containment_position_holds() -> Bool { + let sits_at_its_declaration = xl0_any_site( + sites: xl0_consumer_sites, + f: fn(site) { + xl0_site_spelling(site: site) == "Xl0Marker" + && xl0_site_position(site: site) == "v2.test.xl0_consumer.Xl0BareUse" + } + ) + let none_stamped_with_the_module = !xl0_any_site( + sites: xl0_consumer_sites, + f: fn(site) { xl0_site_position(site: site) == "v2.test.xl0_consumer" } + ) + sits_at_its_declaration && none_stamped_with_the_module +} + +data xl0_roster: FreeMonoid = repair_input_origin_roster_over_roots(roots: xl0_roots).carriers + +fn xl0_roster_has(roster: FreeMonoid, f: fn(SourceDeclarationCarrierIdentity) -> Bool) -> Bool { + fold_list( + xs: roster, + empty: false, + cons: fn(acc, candidate) { + acc || match candidate { + SourceDeclarationCarrier { identity: identity } => f(identity) + SourceCarrierCandidate { identity: _ } => false + RenderedTargetVocabularyCarrier { identity: _ } => false + } + } + ) +} + +// THE POSITIVE CONTROL BY EXECUTION: a cross-module mention carries the DECLARATION that answered +// it, as a DeclarationRef naming the owning module and the declaration inside it -- not a file +// path, which is the position std.repair_input_origin's divergence note refuses to carry. +test fn a_cross_module_mention_carries_its_declaring_identity_holds() -> Bool { + xl0_roster_has( + roster: xl0_roster, + f: fn(identity) { + identity.reference_position == "v2.test.xl0_consumer.Xl0BareUse" + && identity.authored_spelling == "Xl0Marker" + && match identity.provenance { + RepairInputDeclared { declaring: declaring } => + (declaring.module_path as String) == "v2.test.xl0_producer" + && (declaring.decl_name as String) == "Xl0Marker" + RepairInputTargetWithoutDeclarationIdentity { target_spelling: _ } => false + RepairInputIdentityAmbiguous => false + RepairInputIdentityAbsent => false + } + } + ) +} + +// RED 4 -- THE DENOMINATOR IS TAKEN BEFORE ELIGIBILITY, SO AN UNANSWERABLE MENTION IS A ROW. +// A producer that dropped what it could not resolve would report a roster of only the easy half +// and would be indistinguishable from a tree with nothing left to repair. +// The second clause below holds the digest the ACT-0 receipt is taken over to one line per row: a +// rendering that silently skipped an arm would digest a smaller denominator than the roster says. +test fn an_unanswerable_mention_is_a_row_and_not_a_drop_holds() -> Bool { + let unbound_row_present = xl0_roster_has( + roster: xl0_roster, + f: fn(identity) { + identity.authored_spelling == "Xl0NeverDeclared" + && match identity.provenance { + RepairInputIdentityAbsent => true + RepairInputDeclared { declaring: _ } => false + RepairInputTargetWithoutDeclarationIdentity { target_spelling: _ } => false + RepairInputIdentityAmbiguous => false + } + } + ) + let digest_covers_every_row = + length(xs: repair_input_origin_roster_digest_lines(roster: xl0_roster)) + == length(xs: xl0_roster) + unbound_row_present && digest_covers_every_row +} + +// AN UNREADABLE ROOT IS COUNTED, NOT DROPPED -- the wall for the arm that used to be +// `Rejected => acc`. A bare atom is not a module root: its header cannot resolve, so it +// contributes no mentions. The defect was that it also contributed no EVIDENCE, leaving a caller +// unable to tell an unreadable module from an empty one. Both halves are asserted, because either +// alone is satisfiable by the wrong implementation: the sites must be unchanged (the root really +// did contribute nothing) AND the refusal must be present and countable (it said so). +data xl0_unreadable_root: Node = xl0_atom(sym: ^Xl0NotAModuleRoot) + +data xl0_roots_with_one_unreadable: FreeMonoid = Cons { + head: xl0_consumer_root, + tail: Cons { head: xl0_unreadable_root, tail: Empty } +} + +test fn an_unreadable_module_root_is_counted_and_not_silently_dropped_holds() -> Bool { + let clean = collect_reference_sites(roots: Cons { head: xl0_consumer_root, tail: Empty }) + let with_bad = collect_reference_sites(roots: xl0_roots_with_one_unreadable) + length(xs: with_bad.sites) == length(xs: clean.sites) + && length(xs: with_bad.unreadable_roots) == 1 + && is_empty(xs: clean.unreadable_roots) + && !reference_site_collection_is_total(collection: with_bad) + && reference_site_collection_is_total(collection: clean) +} + +// THE REFUSAL SURVIVES THE SEAM INTO THE ROSTER. A collector that counted the loss and a producer +// that dropped it at the next call would be the same silent degradation one layer down. +test fn the_roster_carries_the_unreadable_roots_it_was_built_over_holds() -> Bool { + let roster = repair_input_origin_roster_over_roots(roots: xl0_roots_with_one_unreadable) + length(xs: roster.unreadable_roots) == 1 + && !repair_input_origin_roster_is_total(roster: roster) + && repair_input_origin_roster_is_total( + roster: repair_input_origin_roster_over_roots( + roots: Cons { head: xl0_consumer_root, tail: Empty } + ) + ) +} diff --git a/src/v2/test/claim/reference_derived_graph_call_arg_tree_test.dag b/src/v2/test/claim/reference_derived_graph_call_arg_tree_test.dag new file mode 100644 index 00000000000..b56a7a67c99 --- /dev/null +++ b/src/v2/test/claim/reference_derived_graph_call_arg_tree_test.dag @@ -0,0 +1,306 @@ +module v2.test.claim.reference_derived_graph_call_arg_tree + +import std.types { Int } +import v2.extdeps.languages.dag { + parse_production_captured_child_optional, + parse_production_emitted_identity_optional, + parse_qualified_name_segments_from_capture, + qualified_name_from_module_node, + qualified_name_from_symbol_segments, +} +import v2.compiler.reference_site_collector { collect_module_reference_sites } +import v2.lens.module_graph { + LocatedModuleRoot, + ModuleDependencyEdge, + reference_derived_edges_from_located_roots, +} +import v2.std.algebra { length, list_snoc_item } +import v2.std.collection { List } +import v2.std.diagnostic { + Accepted, + Diagnostic, + ExternalContractUnknown, + Outcome, + Rejected, + Unavailable, + diagnostics_singleton, + node_locus, + outcome_accepted +} +import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } +import v2.std.logic { Bool } +import v2.std.node { Edge, Node } +import v2.std.optional { Absent, Present } +import v2.std.qualified_name { QualifiedName, qualified_name_to_dotted_string } +import v2.std.text { String } +import v2.test.claim.reference_derived_graph_fixture { + consumer_body_value_path, + consumer_call_only_path, + consumer_type_only_path, + provider_module, + provider_path, + xl4_fixture_trees, + xl4_item_at, +} + +data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree + +// COLLECTOR-ROUTE DEFICIENCY PROBES over the shared ingest xl4_fixture_trees. The production +// edge producer is the collector, not a parse-tree qualified-name walk. Call-argument == 0 is +// tree-side (eager-raven-113). Qualified type-position is the dotted-reference capability. + +fn ca_edge_count(edges: List, path: String, target: String) -> Int { + length(xs: edges |> filter(e => e.path == path && e.target_module == target)) +} + +fn ca_edges_from_pair( + provider_root: Node, + consumer_path: String, + consumer_root: Node +) -> List { + reference_derived_edges_from_located_roots( + items: [ + LocatedModuleRoot { path: provider_path, root: provider_root }, + LocatedModuleRoot { path: consumer_path, root: consumer_root } + ] + ).edges +} + +data ca_ingest_refused_count: Int = -1 + +fn ca_pair_edge_count_from_trees( + trees: Outcome>, + consumer_path: String +) -> Int { + match trees { + Rejected { diagnostics: _ } => ca_ingest_refused_count + Accepted { value: items, diagnostics: _ } => + match xl4_item_at(items: items, path: provider_path) { + Absent => ca_ingest_refused_count + Present { value: provider } => + match xl4_item_at(items: items, path: consumer_path) { + Absent => ca_ingest_refused_count + Present { value: consumer } => + ca_edge_count( + edges: ca_edges_from_pair( + provider_root: provider.root, + consumer_path: consumer_path, + consumer_root: consumer.root + ), + path: consumer_path, + target: provider_module + ) + } + } + } +} + +data ca_provided_value_dotted: String = "test.fixture.reference_derived_graph.provider.provided_value" + +data ca_provided_marker_dotted: String = "test.fixture.reference_derived_graph.provider.ProvidedMarker" + +fn ca_parse_site_count(consumer_path: String, needle: String) -> Int { + match xl4_fixture_trees().parsed { + Rejected { diagnostics: _ } => ca_ingest_refused_count + Accepted { value: items, diagnostics: _ } => + match xl4_item_at(items: items, path: consumer_path) { + Absent => ca_ingest_refused_count + Present { value: item } => + length( + xs: collect_module_reference_sites(root: item.root).sites + |> filter(site => qualified_name_to_dotted_string(qn: site.spelling) == needle) + ) + } + } +} + +fn ca_parse_call_arg_edge_count() -> Int { + ca_parse_site_count(consumer_path: consumer_call_only_path, needle: ca_provided_value_dotted) +} + +fn ca_normalized_call_arg_edge_count() -> Int { + ca_pair_edge_count_from_trees(trees: xl4_fixture_trees().located, consumer_path: consumer_call_only_path) +} + +fn ca_parse_type_pos_edge_count() -> Int { + ca_parse_site_count(consumer_path: consumer_type_only_path, needle: ca_provided_marker_dotted) +} + +fn ca_normalized_type_pos_edge_count() -> Int { + ca_pair_edge_count_from_trees(trees: xl4_fixture_trees().located, consumer_path: consumer_type_only_path) +} + +fn ca_parse_body_value_edge_count() -> Int { + ca_parse_site_count(consumer_path: consumer_body_value_path, needle: ca_provided_value_dotted) +} + +fn ca_normalized_body_value_edge_count() -> Int { + ca_pair_edge_count_from_trees(trees: xl4_fixture_trees().located, consumer_path: consumer_body_value_path) +} + +test fn call_argument_only_reference_is_missing_from_parse_tree_today_holds() -> Bool { + ca_parse_call_arg_edge_count() == 0 +} + +test fn call_argument_only_reference_is_missing_from_normalized_tree_today_holds() -> Bool { + ca_normalized_call_arg_edge_count() == 0 +} + +test fn type_position_only_is_missing_from_parse_tree_today_holds() -> Bool { + ca_parse_type_pos_edge_count() == 0 +} + +test fn type_position_only_is_missing_from_normalized_tree_today_holds() -> Bool { + ca_normalized_type_pos_edge_count() == 0 +} + +test fn body_value_outside_call_is_missing_from_parse_tree_today_holds() -> Bool { + ca_parse_body_value_edge_count() == 0 +} + +test fn body_value_outside_call_is_missing_from_normalized_tree_today_holds() -> Bool { + ca_normalized_body_value_edge_count() == 0 +} + +data ca_no_qn_sites: List = [] + +fn ca_qn_from_qualified_name_production(production_node: Node, module_root: Node) -> Outcome { + match parse_production_captured_child_optional(node: production_node) { + Absent => + Rejected { + diagnostics: diagnostics_singleton( + d: Diagnostic { + reason: ^ca_parse_qn_oracle_capture_missing, + at: node_locus(node: production_node), + correction: Unavailable { reason: ExternalContractUnknown } + } + ) + } + Present { value: capture } => + match parse_qualified_name_segments_from_capture(qn_capture: capture, root: module_root) { + Rejected { diagnostics: d } => Rejected { diagnostics: d } + Accepted { value: segments, diagnostics: _ } => + qualified_name_from_symbol_segments(segments: segments, root: module_root) + } + } +} + +fn ca_collect_non_import_qn_sites_from_edges( + edges: List, + module_root: Node, + module_qn: QualifiedName, + acc: List +) -> Outcome> { + match edges |> first { + Absent => outcome_accepted(value: acc) + Present { value: edge } => + match ca_collect_non_import_qn_sites_from_node( + node: edge.target, + module_root: module_root, + module_qn: module_qn, + acc: acc + ) { + Rejected { diagnostics: d } => Rejected { diagnostics: d } + Accepted { value: next_acc, diagnostics: _ } => + ca_collect_non_import_qn_sites_from_edges( + edges: edges |> skip(1), + module_root: module_root, + module_qn: module_qn, + acc: next_acc + ) + } + } +} + +fn ca_collect_non_import_qn_sites_from_node( + node: Node, + module_root: Node, + module_qn: QualifiedName, + acc: List +) -> Outcome> { + match parse_production_emitted_identity_optional(node: node) { + Present { value: id } => + if id == ^dag_surface_import_decl { + outcome_accepted(value: acc) + } else if id == ^dag_surface_qualified_name { + match ca_qn_from_qualified_name_production(production_node: node, module_root: module_root) { + Rejected { diagnostics: d } => Rejected { diagnostics: d } + Accepted { value: site_qn, diagnostics: _ } => + ca_collect_non_import_qn_sites_from_edges( + edges: node.children, + module_root: module_root, + module_qn: module_qn, + acc: if site_qn == module_qn { + acc + } else { + list_snoc_item(xs: acc, item: site_qn) + } + ) + } + } else { + ca_collect_non_import_qn_sites_from_edges( + edges: node.children, + module_root: module_root, + module_qn: module_qn, + acc: acc + ) + } + Absent => + ca_collect_non_import_qn_sites_from_edges( + edges: node.children, + module_root: module_root, + module_qn: module_qn, + acc: acc + ) + } +} + +fn ca_collect_non_import_qn_sites(module_root: Node) -> Outcome> { + match qualified_name_from_module_node(root: module_root) { + Rejected { diagnostics: d } => Rejected { diagnostics: d } + Accepted { value: module_qn, diagnostics: _ } => + ca_collect_non_import_qn_sites_from_node( + node: module_root, + module_root: module_root, + module_qn: module_qn, + acc: ca_no_qn_sites + ) + } +} + +fn ca_parse_qn_walk_site_count(consumer_path: String, needle: String) -> Int { + match xl4_fixture_trees().parsed { + Rejected { diagnostics: _ } => ca_ingest_refused_count + Accepted { value: items, diagnostics: _ } => + match xl4_item_at(items: items, path: consumer_path) { + Absent => ca_ingest_refused_count + Present { value: item } => + match ca_collect_non_import_qn_sites(module_root: item.root) { + Rejected { diagnostics: _ } => ca_ingest_refused_count + Accepted { value: sites, diagnostics: _ } => + length(xs: sites |> filter(qn => qualified_name_to_dotted_string(qn: qn) == needle)) + } + } + } +} + +test fn parse_qn_walk_sees_type_position_provided_marker_holds() -> Bool { + ca_parse_qn_walk_site_count( + consumer_path: consumer_type_only_path, + needle: ca_provided_marker_dotted + ) > 0 +} + +test fn parse_qn_walk_does_not_see_body_value_provided_value_today_holds() -> Bool { + ca_parse_qn_walk_site_count( + consumer_path: consumer_body_value_path, + needle: ca_provided_value_dotted + ) == 0 +} + +test fn parse_qn_walk_does_not_see_call_arg_provided_value_today_holds() -> Bool { + ca_parse_qn_walk_site_count( + consumer_path: consumer_call_only_path, + needle: ca_provided_value_dotted + ) == 0 +} diff --git a/src/v2/test/claim/reference_derived_graph_fixture.dag b/src/v2/test/claim/reference_derived_graph_fixture.dag new file mode 100644 index 00000000000..349742a117c --- /dev/null +++ b/src/v2/test/claim/reference_derived_graph_fixture.dag @@ -0,0 +1,169 @@ +module v2.test.claim.reference_derived_graph_fixture + +import extdeps.communication.medium { Lossless, Medium } +import extdeps.filesystem.filesystem_io +import std.algebra { Cons, Empty, FreeMonoid } +import v2.compiler.parse { parse_module } +import v2.compiler.source_authority { DagSourceReadWitness, SourceRootIngest } +import v2.compiler.tokenize { tokenize } +import v2.extdeps.languages.dag { dag_language_model } +import v2.lens.module_graph { + LocatedModuleRoot, + located_roots_from_source_root_ingest, + no_located_roots +} +import v2.std.algebra { fold_list } +import v2.std.artifact { Artifact, SourceFile } +import v2.std.collection { List } +import v2.std.cross_tree.import_model { DagTree } +import v2.std.diagnostic { + Accepted, + Outcome, + Rejected, + bind_outcome, + outcome_accepted +} +import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } +import v2.std.node { Symbol } +import v2.std.optional { Optional } +import v2.std.optional { Absent, Present } +import v2.std.text { String } + +// ONE INGEST, TWO CLAIM FILES. Files under dag/test/fixture/reference_derived_graph are the +// authority (review 65417). The floor builds a fresh frame per claim, so a data row cannot share +// parse-and-normalize. v2.workflow.floor_pure_producer_share warms xl4_fixture_trees once at +// preparation. The seam is the ingest, not the collector: both files name the collector or the +// edge fold, so sharing those would delete the measurement. located uses the XL-0 production +// ingest located_roots_from_source_root_ingest; parsed is tokenize+parse of the same bytes. + +data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree + +data provider_path: String = "dag/test/fixture/reference_derived_graph/provider.dag" + +data consumer_reference_only_path: String = "dag/test/fixture/reference_derived_graph/consumer_reference_only.dag" + +data consumer_import_only_path: String = "dag/test/fixture/reference_derived_graph/consumer_import_only.dag" + +data consumer_both_path: String = "dag/test/fixture/reference_derived_graph/consumer_both.dag" + +data consumer_call_only_path: String = "dag/test/fixture/reference_derived_graph/consumer_call_only.dag" + +data consumer_type_only_path: String = "dag/test/fixture/reference_derived_graph/consumer_type_only.dag" + +data consumer_callee_only_path: String = "dag/test/fixture/reference_derived_graph/consumer_callee_only.dag" + +data consumer_type_imported_path: String = "dag/test/fixture/reference_derived_graph/consumer_type_imported.dag" + +data consumer_type_bare_local_path: String = "dag/test/fixture/reference_derived_graph/consumer_type_bare_local.dag" + +data consumer_field_bare_local_path: String = "dag/test/fixture/reference_derived_graph/consumer_field_bare_local.dag" + +data consumer_body_value_path: String = "dag/test/fixture/reference_derived_graph/consumer_body_value.dag" + +data provider_module: String = "test.fixture.reference_derived_graph.provider" + +type Xl4WarmIngest { + parsed: Outcome> + located: Outcome> +} + +fn fixture_read(path: String, unit: Symbol) -> DagSourceReadWitness { + DagSourceReadWitness { + source: Medium { carried: filesystem_read(path: path).content, fidelity: Lossless }, + artifact: Artifact { kind: SourceFile, id: unit, file_path: path }, + compilation_unit: unit, + source_root: DagTree + } +} + +fn fixture_ingest() -> SourceRootIngest { + Cons { + head: fixture_read(path: provider_path, unit: ^provider_unit), + tail: Cons { + head: fixture_read(path: consumer_reference_only_path, unit: ^reference_only_unit), + tail: Cons { + head: fixture_read(path: consumer_import_only_path, unit: ^import_only_unit), + tail: Cons { + head: fixture_read(path: consumer_both_path, unit: ^both_unit), + tail: Cons { + head: fixture_read(path: consumer_call_only_path, unit: ^call_only_unit), + tail: Cons { + head: fixture_read(path: consumer_type_only_path, unit: ^type_only_unit), + tail: Cons { + head: fixture_read(path: consumer_callee_only_path, unit: ^callee_only_unit), + tail: Cons { + head: fixture_read(path: consumer_type_imported_path, unit: ^type_imported_unit), + tail: Cons { + head: fixture_read(path: consumer_type_bare_local_path, unit: ^type_bare_local_unit), + tail: Cons { + head: fixture_read(path: consumer_field_bare_local_path, unit: ^field_bare_local_unit), + tail: Cons { + head: fixture_read(path: consumer_body_value_path, unit: ^body_value_unit), + tail: Empty + } + } + } + } + } + } + } + } + } + } + } +} + +fn parse_one(w: DagSourceReadWitness) -> Outcome { + let lm = dag_language_model() + bind_outcome( + o: tokenize(text: w.source.carried, file: w.compilation_unit, rules: lm.lex), + f: fn(token_stream) { + bind_outcome( + o: parse_module(tokens: token_stream, grammar: lm.grammar), + f: fn(artifact) { + outcome_accepted(value: LocatedModuleRoot { path: w.artifact.file_path, root: artifact.tree }) + } + ) + } + ) +} + +fn parse_located_from_ingest(ingest: SourceRootIngest) -> Outcome> { + fold_list( + xs: ingest, + empty: outcome_accepted(value: no_located_roots), + cons: fn(acc, w) { + bind_outcome( + o: acc, + f: fn(items) { + bind_outcome( + o: parse_one(w: w), + f: fn(item) { + outcome_accepted(value: concat(items, [item])) + } + ) + } + ) + } + ) +} + +fn xl4_fixture_trees() -> Xl4WarmIngest { + let ingest = fixture_ingest() + match parse_located_from_ingest(ingest: ingest) { + Rejected { diagnostics: d } => + Xl4WarmIngest { + parsed: Rejected { diagnostics: d }, + located: Rejected { diagnostics: d } + } + Accepted { value: parsed_items, diagnostics: _ } => + Xl4WarmIngest { + parsed: outcome_accepted(value: parsed_items), + located: located_roots_from_source_root_ingest(ingest: ingest) + } + } +} + +fn xl4_item_at(items: List, path: String) -> Optional { + items |> filter(item => item.path == path) |> first +} diff --git a/src/v2/test/claim/reference_derived_graph_production_ingest_test.dag b/src/v2/test/claim/reference_derived_graph_production_ingest_test.dag new file mode 100644 index 00000000000..2e69b09304c --- /dev/null +++ b/src/v2/test/claim/reference_derived_graph_production_ingest_test.dag @@ -0,0 +1,238 @@ +module v2.test.claim.reference_derived_graph_production_ingest + +import std.types { Int } +import v2.compiler.reference_site_collector { collect_module_reference_sites } +import v2.lens.module_graph { + LocatedModuleRoot, + ModuleDependencyEdge, + reference_derived_edges_from_located_roots +} +import v2.std.algebra { length } +import v2.std.collection { List } +import v2.std.diagnostic { Accepted, Rejected } +import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } +import v2.std.logic { Bool } +import v2.std.node { + Arrow, + Atom, + Cardinality, + ComputationNode, + Conj, + Disj, + Instantiation, + Named, + Node, + Positional, + Symbol, + TypeNode, + node_subtree_nodes, + fold_node, + NodeFold +} +import v2.std.optional { Absent, Optional, Present } +import v2.std.qualified_name { qualified_name_to_dotted_string } +import v2.std.text { String } +import v2.test.claim.reference_derived_graph_fixture { + consumer_both_path, + consumer_call_only_path, + consumer_callee_only_path, + consumer_field_bare_local_path, + consumer_import_only_path, + consumer_reference_only_path, + consumer_type_bare_local_path, + consumer_type_imported_path, + consumer_type_only_path, + provider_module, + provider_path, + xl4_fixture_trees, + xl4_item_at, +} + +data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree + +// MEASUREMENTS OF TODAY'S XL-4 ROUTE over the shared ingest xl4_fixture_trees.located. +// The collector and edge fold stay per claim. Call-argument and callee: tree-side. +// Qualified mentions: dotted-reference capability. Bare field-type: tree-side census. + +data provided_marker_dotted: String = "test.fixture.reference_derived_graph.provider.ProvidedMarker" + +data provided_marker_bare: String = "ProvidedMarker" + +data local_marker_bare: String = "LocalMarker" + +data local_field_only_bare: String = "LocalFieldOnly" + +data local_param_marker_bare: String = "LocalParamMarker" + +data local_wrapper_sym: Symbol = ^LocalWrapper + +data local_field_only_sym: Symbol = ^LocalFieldOnly + +data local_param_marker_sym: Symbol = ^LocalParamMarker + +data local_wrapper_field_name_sym: Symbol = ^f + +data production_ingest_refused_count: Int = -1 + +fn located_pair(items: List, consumer_path: String) -> Optional> { + match xl4_item_at(items: items, path: provider_path) { + Absent => Absent + Present { value: provider } => + match xl4_item_at(items: items, path: consumer_path) { + Absent => Absent + Present { value: consumer } => Present { value: [provider, consumer] } + } + } +} + +fn production_edge_count(path: String, target: String) -> Int { + match xl4_fixture_trees().located { + Rejected { diagnostics: _ } => production_ingest_refused_count + Accepted { value: items, diagnostics: _ } => + match located_pair(items: items, consumer_path: path) { + Absent => production_ingest_refused_count + Present { value: pair } => + length( + xs: reference_derived_edges_from_located_roots( + items: pair + ).edges |> filter(e => e.path == path && e.target_module == target) + ) + } + } +} + +fn site_spelling_count(path: String, needle: String) -> Int { + match xl4_fixture_trees().located { + Rejected { diagnostics: _ } => production_ingest_refused_count + Accepted { value: items, diagnostics: _ } => + match xl4_item_at(items: items, path: path) { + Absent => production_ingest_refused_count + Present { value: item } => + length( + xs: collect_module_reference_sites(root: item.root).sites + |> filter(site => qualified_name_to_dotted_string(qn: site.spelling) == needle) + ) + } + } +} + +fn node_atom_is(n: Node, needle: Symbol) -> Bool { + match n.kind { + TypeNode { connective: Atom { identity: id } } => id == needle + TypeNode { connective: Conj } => false + TypeNode { connective: Disj } => false + TypeNode { connective: Arrow } => false + TypeNode { connective: Cardinality } => false + TypeNode { connective: Instantiation } => false + ComputationNode { behavior: _ } => false + } +} + +fn tree_named_edge_count_in_root(root: Node, needle: Symbol) -> Int { + fold_node( + n: root, + algebra: NodeFold { + init: fn(_) { 0 }, + step: fn(acc, edge, child_count) { + let here = match edge.label { + Named { name: nm } => if nm == needle { 1 } else { 0 } + Positional => 0 + } + acc + here + child_count + } + } + ) +} + +fn tree_atom_count(path: String, needle: Symbol) -> Int { + match xl4_fixture_trees().located { + Rejected { diagnostics: _ } => production_ingest_refused_count + Accepted { value: items, diagnostics: _ } => + match xl4_item_at(items: items, path: path) { + Absent => production_ingest_refused_count + Present { value: item } => + length(xs: node_subtree_nodes(root: item.root) |> filter(n => node_atom_is(n: n, needle: needle))) + } + } +} + +fn tree_named_edge_count(path: String, needle: Symbol) -> Int { + match xl4_fixture_trees().located { + Rejected { diagnostics: _ } => production_ingest_refused_count + Accepted { value: items, diagnostics: _ } => + match xl4_item_at(items: items, path: path) { + Absent => production_ingest_refused_count + Present { value: item } => + tree_named_edge_count_in_root(root: item.root, needle: needle) + } + } +} + +fn tree_atom_and_label_absent(path: String, needle: Symbol) -> Bool { + tree_atom_count(path: path, needle: needle) == 0 + && tree_named_edge_count(path: path, needle: needle) == 0 +} + +test fn production_route_reference_only_plain_value_is_missing_today_holds() -> Bool { + production_edge_count(path: consumer_reference_only_path, target: provider_module) == 0 +} + +test fn production_route_import_only_has_no_reference_edge_holds() -> Bool { + production_edge_count(path: consumer_import_only_path, target: provider_module) == 0 +} + +test fn production_route_both_plain_value_is_missing_today_holds() -> Bool { + production_edge_count(path: consumer_both_path, target: provider_module) == 0 +} + +test fn production_route_call_contents_are_missing_today_holds() -> Bool { + production_edge_count(path: consumer_call_only_path, target: provider_module) == 0 +} + +test fn production_route_type_position_qualified_site_is_missing_today_holds() -> Bool { + site_spelling_count(path: consumer_type_only_path, needle: provided_marker_dotted) == 0 +} + +test fn production_route_type_position_qualified_edge_is_missing_today_holds() -> Bool { + production_edge_count(path: consumer_type_only_path, target: provider_module) == 0 +} + +test fn production_route_type_imported_bare_site_is_present_holds() -> Bool { + site_spelling_count(path: consumer_type_imported_path, needle: provided_marker_bare) > 0 +} + +test fn production_route_type_imported_site_does_not_yield_edge_today_holds() -> Bool { + production_edge_count(path: consumer_type_imported_path, target: provider_module) == 0 +} + +test fn production_route_bare_local_type_position_site_is_present_holds() -> Bool { + site_spelling_count(path: consumer_type_bare_local_path, needle: local_marker_bare) > 0 +} + +test fn production_route_bare_param_type_in_field_fixture_is_present_holds() -> Bool { + site_spelling_count(path: consumer_field_bare_local_path, needle: local_param_marker_bare) > 0 +} + +test fn production_route_bare_field_type_site_is_missing_today_holds() -> Bool { + site_spelling_count(path: consumer_field_bare_local_path, needle: local_field_only_bare) == 0 +} + +test fn production_tree_field_fixture_param_type_atom_is_present_holds() -> Bool { + tree_atom_count(path: consumer_field_bare_local_path, needle: local_param_marker_sym) > 0 +} + +test fn production_tree_field_fixture_wrapper_name_unfindable_today_holds() -> Bool { + tree_atom_and_label_absent(path: consumer_field_bare_local_path, needle: local_wrapper_sym) +} + +test fn production_tree_field_fixture_field_name_unfindable_today_holds() -> Bool { + tree_atom_and_label_absent(path: consumer_field_bare_local_path, needle: local_wrapper_field_name_sym) +} + +test fn production_tree_field_fixture_field_type_unfindable_today_holds() -> Bool { + tree_atom_and_label_absent(path: consumer_field_bare_local_path, needle: local_field_only_sym) +} + +test fn production_route_callee_with_no_arguments_is_missing_today_holds() -> Bool { + production_edge_count(path: consumer_callee_only_path, target: provider_module) == 0 +} diff --git a/src/v2/test/claim/reference_derived_graph_witness_test.dag b/src/v2/test/claim/reference_derived_graph_witness_test.dag new file mode 100644 index 00000000000..d3529d00ce3 --- /dev/null +++ b/src/v2/test/claim/reference_derived_graph_witness_test.dag @@ -0,0 +1,278 @@ +module v2.test.claim.reference_derived_graph_witness + +import std.algebra { Cons, Empty, FreeMonoid } +import std.occurrence_identity { OccurrenceSynthetic } +import std.types { Int } +import v2.extdeps.languages.dag { dag_grammar_atom, dag_named_edge } +import v2.compiler.reference_site_collector { collect_module_reference_sites } +import v2.lens.module_graph { + LocatedModuleRoot, + ModuleDependencyEdge, + reference_derived_edge_fold_is_total, + reference_derived_edges_from_located_roots, + reference_derived_pool_from_located_roots, + reference_edges_for_located_root_sites, +} +import v2.std.algebra { fold_list, fold_list_node, length } +import v2.std.collection { List } +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } +import v2.std.logic { Bool } +import v2.std.node { + Atom, + Conj, + Edge, + Named, + Node, + Positional, + Symbol, + TypeNode +} +import v2.std.qualified_name { QualifiedName, qualified_name_from_dotted_string } +import v2.std.text { String } + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +data rd_provider_path: String = "dag/test/fixture/reference_derived_graph/provider.dag" + +data rd_reference_only_path: String = "dag/test/fixture/reference_derived_graph/consumer_reference_only.dag" + +data rd_import_only_path: String = "dag/test/fixture/reference_derived_graph/consumer_import_only.dag" + +data rd_both_path: String = "dag/test/fixture/reference_derived_graph/consumer_both.dag" + +data rd_provider_module: String = "test.fixture.reference_derived_graph.provider" + +data rd_provider_qn: QualifiedName = qualified_name_from_dotted_string( + dotted: "test.fixture.reference_derived_graph.provider" +) + +data rd_reference_only_qn: QualifiedName = qualified_name_from_dotted_string( + dotted: "test.fixture.reference_derived_graph.consumer_reference_only" +) + +data rd_import_only_qn: QualifiedName = qualified_name_from_dotted_string( + dotted: "test.fixture.reference_derived_graph.consumer_import_only" +) + +data rd_both_qn: QualifiedName = qualified_name_from_dotted_string( + dotted: "test.fixture.reference_derived_graph.consumer_both" +) + +data rd_provided_marker_qn: QualifiedName = qualified_name_from_dotted_string( + dotted: "test.fixture.reference_derived_graph.provider.ProvidedMarker" +) + +fn rd_qn_spine(segments: FreeMonoid) -> Node { + fold_list_node( + xs: segments, + item_node: fn(sym) { + Node { + kind: TypeNode { connective: Atom { identity: sym } }, + children: [], + occurrence_id: OccurrenceSynthetic + } + } + ) +} + +fn rd_module_root(qn_spine: Node, body: List) -> Node { + Node { + kind: TypeNode { connective: Conj }, + children: concat( + [ + dag_named_edge( + name: ^dag_surface_module_header, + target: dag_grammar_atom(id: ^dag_surface_module_header) + ), + dag_named_edge( + name: ^dag_surface_module_header_qualified_name, + target: qn_spine + ) + ], + body + ), + occurrence_id: OccurrenceSynthetic + } +} + +fn rd_declaration(decl_sym: Symbol) -> Edge { + Edge { + label: Named { name: decl_sym }, + target: Node { + kind: TypeNode { connective: Atom { identity: decl_sym } }, + children: [], + occurrence_id: OccurrenceSynthetic + } + } +} + +fn rd_qualified_mention() -> Edge { + Edge { + label: Positional, + target: rd_qn_spine(segments: rd_provided_marker_qn) + } +} + +fn rd_import_syntax_mention() -> Edge { + Edge { + label: Named { name: ^dag_surface_import_decl }, + target: Node { + kind: TypeNode { connective: Conj }, + children: [ + Edge { + label: Positional, + target: Node { + kind: TypeNode { connective: Atom { identity: ^ProvidedMarker } }, + children: [], + occurrence_id: OccurrenceSynthetic + } + } + ], + occurrence_id: OccurrenceSynthetic + } + } +} + +data rd_provider_root: Node = rd_module_root( + qn_spine: rd_qn_spine(segments: rd_provider_qn), + body: [rd_declaration(decl_sym: ^ProvidedMarker)] +) + +data rd_reference_only_root: Node = rd_module_root( + qn_spine: rd_qn_spine(segments: rd_reference_only_qn), + body: [rd_qualified_mention()] +) + +data rd_import_only_root: Node = rd_module_root( + qn_spine: rd_qn_spine(segments: rd_import_only_qn), + body: [rd_import_syntax_mention()] +) + +data rd_both_root: Node = rd_module_root( + qn_spine: rd_qn_spine(segments: rd_both_qn), + body: [rd_import_syntax_mention(), rd_qualified_mention()] +) + +data rd_located_roots: List = [ + LocatedModuleRoot { path: rd_provider_path, root: rd_provider_root }, + LocatedModuleRoot { path: rd_reference_only_path, root: rd_reference_only_root }, + LocatedModuleRoot { path: rd_import_only_path, root: rd_import_only_root }, + LocatedModuleRoot { path: rd_both_path, root: rd_both_root }, +] + +fn rd_edge_count( + edges: List, + path: String, + target_module: String +) -> Int { + length( + xs: edges |> filter(e => e.path == path && e.target_module == target_module) + ) +} + +fn rd_production_edges() -> List { + reference_derived_edges_from_located_roots( + items: rd_located_roots + ).edges +} + +// The mutant is composed HERE, at the test boundary: the collector's raw site collection +// (import-syntax mentions included) is fed straight into the edge stage, bypassing the +// production selection. The production producer carries no switch for this (review 65639). +fn rd_mutant_re_admitting_import_decl_edges() -> List { + let pool = reference_derived_pool_from_located_roots(items: rd_located_roots) + fold_list( + xs: rd_located_roots, + empty: [], + cons: fn(acc, item) { + concat( + acc, + reference_edges_for_located_root_sites( + item: item, + pool: pool, + collected: collect_module_reference_sites(root: item.root) + ).edges + ) + } + ) +} + +test fn reference_only_module_has_edge_and_unused_import_does_not() -> Bool { + let edges = rd_production_edges() + rd_edge_count( + edges: edges, + path: rd_reference_only_path, + target_module: rd_provider_module + ) == 1 + && rd_edge_count( + edges: edges, + path: rd_import_only_path, + target_module: rd_provider_module + ) == 0 +} + +test fn both_gives_exactly_one_reference_derived_edge() -> Bool { + rd_edge_count( + edges: rd_production_edges(), + path: rd_both_path, + target_module: rd_provider_module + ) == 1 +} + +test fn mutant_re_admitting_import_decl_makes_import_only_property_red() -> Bool { + rd_edge_count( + edges: rd_mutant_re_admitting_import_decl_edges(), + path: rd_import_only_path, + target_module: rd_provider_module + ) != 0 +} + +test fn readable_fixture_fold_is_total() -> Bool { + reference_derived_edge_fold_is_total( + fold: reference_derived_edges_from_located_roots( + items: rd_located_roots + ) + ) +} + +fn rd_unreadable_root() -> Node { + Node { + kind: TypeNode { connective: Atom { identity: ^rd_unreadable_root_atom } }, + children: [], + occurrence_id: OccurrenceSynthetic + } +} + +// THE DISCRIMINATING RED FOR THE HEADERLESS-CONJ ARM (review 66859 on gunbc#11461): a +// well-formed module tree whose header does not yield a qualified name walks fine (the +// collector counts nothing unreadable) but the pool cannot name it, and the edge fold used +// to answer Absent with zero edges while still reporting total. A headerless root is a +// Conj carrying a body and no header edges; it must be COUNTED in unreadable_roots so the +// fold is non-total, exactly like the bare-Atom root below. +fn rd_headerless_root() -> Node { + Node { + kind: TypeNode { connective: Conj }, + children: [rd_declaration(decl_sym: ^rd_headerless_decl)], + occurrence_id: OccurrenceSynthetic + } +} + +test fn a_headerless_module_root_is_counted_unreadable_not_zero_edges() -> Bool { + let fold = reference_derived_edges_from_located_roots( + items: [ + LocatedModuleRoot { path: rd_provider_path, root: rd_provider_root }, + LocatedModuleRoot { path: "headerless.dag", root: rd_headerless_root() } + ] + ) + !reference_derived_edge_fold_is_total(fold: fold) + && length(xs: fold.unreadable_roots) == 1 +} + +test fn unreadable_root_is_counted_not_a_silent_leaf() -> Bool { + let fold = reference_derived_edges_from_located_roots( + items: [LocatedModuleRoot { path: "unreadable.dag", root: rd_unreadable_root() }] + ) + !reference_derived_edge_fold_is_total(fold: fold) + && length(xs: fold.unreadable_roots) == 1 + && length(xs: fold.edges) == 0 +} diff --git a/src/v2/test/claim/repair_input_origin_split_witness_test.dag b/src/v2/test/claim/repair_input_origin_split_witness_test.dag index 1d67fbb056b..78cce8ac2d0 100644 --- a/src/v2/test/claim/repair_input_origin_split_witness_test.dag +++ b/src/v2/test/claim/repair_input_origin_split_witness_test.dag @@ -6,6 +6,7 @@ import std.repair_input_origin { RepairInputOriginCandidate, SourceCarrierCandidate, RenderedTargetVocabularyCarrier, + SourceDeclarationCarrier, repair_input_origin_candidates, repair_input_origin_compatibility_names, qualified_item_emit_surface_compatibility_names, @@ -17,6 +18,7 @@ fn is_rendered(candidate: RepairInputOriginCandidate, want: String) -> Bool { match candidate { RenderedTargetVocabularyCarrier { identity } => identity.rendered_identifier == want SourceCarrierCandidate { identity: _ } => false + SourceDeclarationCarrier { identity: _ } => false } } @@ -25,6 +27,7 @@ fn is_source(candidate: RepairInputOriginCandidate, want: String) -> Bool { SourceCarrierCandidate { identity } => repair_input_origin_compatibility_names(candidates: [SourceCarrierCandidate { identity: identity }]) |> any(name => name == want) RenderedTargetVocabularyCarrier { identity: _ } => false + SourceDeclarationCarrier { identity: _ } => false } } diff --git a/src/v2/test/fixture/declaring_identity_spelling/call_only.dag b/src/v2/test/fixture/declaring_identity_spelling/call_only.dag new file mode 100644 index 00000000000..d56efeec270 --- /dev/null +++ b/src/v2/test/fixture/declaring_identity_spelling/call_only.dag @@ -0,0 +1,7 @@ +module v2.test.fixture.declaring_identity_spelling.call_only + +type LocalParam {} + +fn helper() -> Int { 0 } + +fn go(x: LocalParam) -> Int { helper() } diff --git a/src/v2/test/fixture/declaring_identity_spelling/cross_consumer.dag b/src/v2/test/fixture/declaring_identity_spelling/cross_consumer.dag new file mode 100644 index 00000000000..42245221aaf --- /dev/null +++ b/src/v2/test/fixture/declaring_identity_spelling/cross_consumer.dag @@ -0,0 +1,11 @@ +module v2.test.fixture.declaring_identity_spelling.cross_consumer + +type LocalParam {} + +fn go() -> Int { v2.test.fixture.declaring_identity_spelling.cross_provider.Probe } + +fn uses(x: v2.test.fixture.declaring_identity_spelling.cross_provider.ProvidedMarker) -> Int { 0 } + +fn uses_local(x: LocalParam) -> Int { 0 } + +type Wrapper { f: v2.test.fixture.declaring_identity_spelling.cross_provider.ProvidedFieldMarker } diff --git a/src/v2/test/fixture/declaring_identity_spelling/cross_provider.dag b/src/v2/test/fixture/declaring_identity_spelling/cross_provider.dag new file mode 100644 index 00000000000..78916ecefc6 --- /dev/null +++ b/src/v2/test/fixture/declaring_identity_spelling/cross_provider.dag @@ -0,0 +1,7 @@ +module v2.test.fixture.declaring_identity_spelling.cross_provider + +data Probe: Int = 0 + +type ProvidedMarker {} + +type ProvidedFieldMarker {} diff --git a/src/v2/test/fixture/declaring_identity_spelling/field_vs_parameter.dag b/src/v2/test/fixture/declaring_identity_spelling/field_vs_parameter.dag new file mode 100644 index 00000000000..71008cf65ff --- /dev/null +++ b/src/v2/test/fixture/declaring_identity_spelling/field_vs_parameter.dag @@ -0,0 +1,9 @@ +module v2.test.fixture.declaring_identity_spelling.field_vs_parameter + +type ParamOnly {} + +type FieldOnly {} + +fn uses(x: ParamOnly) -> Int { 0 } + +type Wrapper { f: FieldOnly } diff --git a/src/v2/test/fixture/declaring_identity_spelling/matched_type_vs_value.dag b/src/v2/test/fixture/declaring_identity_spelling/matched_type_vs_value.dag new file mode 100644 index 00000000000..51c0a441e57 --- /dev/null +++ b/src/v2/test/fixture/declaring_identity_spelling/matched_type_vs_value.dag @@ -0,0 +1,9 @@ +module v2.test.fixture.declaring_identity_spelling.matched_type_vs_value + +import v2.std.logic { Bool } + +type type_only {} + +data value_only: Int = 0 + +fn go(x: type_only, flag: Bool) -> Int { value_only } diff --git a/src/v2/test/fixture/declaring_identity_spelling/shorter.dag b/src/v2/test/fixture/declaring_identity_spelling/shorter.dag new file mode 100644 index 00000000000..9c7318d2628 --- /dev/null +++ b/src/v2/test/fixture/declaring_identity_spelling/shorter.dag @@ -0,0 +1,5 @@ +module v2.test.fixture.declaring_identity_spelling.shorter + +type Marker {} + +fn f(x: Marker) -> Int { 0 } diff --git a/src/v2/test/fixture/declaring_identity_spelling/value_outside_call.dag b/src/v2/test/fixture/declaring_identity_spelling/value_outside_call.dag new file mode 100644 index 00000000000..f770c76f69a --- /dev/null +++ b/src/v2/test/fixture/declaring_identity_spelling/value_outside_call.dag @@ -0,0 +1,5 @@ +module v2.test.fixture.declaring_identity_spelling.value_outside_call + +data marker: Int = 0 + +fn go() -> Int { marker } diff --git a/src/v2/workflow/bootstrap.dag b/src/v2/workflow/bootstrap.dag index 7ccf95db6db..efefcfcc298 100644 --- a/src/v2/workflow/bootstrap.dag +++ b/src/v2/workflow/bootstrap.dag @@ -3,7 +3,7 @@ module v2.workflow.bootstrap import std.occurrence_identity { OccurrenceSynthetic } import std.dissolution { DissolutionCondition, dissolution_description, unbound_dissolution } -import v2.std.node { Atom, Conj, Edge, Hash, Named, Node, NodeFold, Symbol, TypeNode, content_hash, fold_node } +import v2.std.node { Atom, Conj, Edge, Hash, Named, Node, NodeFold, Symbol, TypeNode, content_hash, fold_node, symbol_eq } import v2.std.algebra { bag_eq, contains, @@ -163,10 +163,6 @@ fn bs_diagnostic(reason: Symbol) -> Diagnostic { } } -fn bs_symbol_eq(left: Symbol, right: Symbol) -> Bool { - left == right -} - fn bootstrap_construct_eq(left: BootstrapConstruct, right: BootstrapConstruct) -> Bool { left.identity == right.identity } @@ -349,7 +345,7 @@ fn bootstrap_canonical_snapshot_content_hash() -> BootstrapHashPin { } fn bs_list_eq(a: List, b: List) -> Bool { - bag_eq(xs: a, ys: b, eq: bs_symbol_eq) + bag_eq(xs: a, ys: b, eq: symbol_eq) } fn bootstrap_constructs_eq(left: List, right: List) -> Bool { diff --git a/src/v2/workflow/floor_pure_producer_share.dag b/src/v2/workflow/floor_pure_producer_share.dag index 0da9f12b287..b9657a12944 100644 --- a/src/v2/workflow/floor_pure_producer_share.dag +++ b/src/v2/workflow/floor_pure_producer_share.dag @@ -438,7 +438,35 @@ import v2.std.collection { List } // `test.claim.live_deploy.emit.*` rows), so the ceiling does not refuse them today. A durable fix // has to make the producer's module reachable from the subject the roster is read in; until that // exists, no row here may name a module outside the gate closure. - +// +// THE LAST ROW IS THE NAMESPACE-XL-4 FIXTURE INGEST, SHARED BY TWO CLAIM FILES. Floor run +// 34730467598 refused v2.test.claim.reference_derived_graph_call_arg_tree and +// v2.test.claim.reference_derived_graph_production_ingest as ENROLMENT-MARGIN-REFUSED / +// interrupted_before_verdict at the 500ms per-claim CPU ceiling -- the class +// gunbc.recurring_failure_mode.shared_precondition_re_derived_once_per_claim_frame. Re-derive with +// claim_batch --entry on those files plus the run's [floor-shared-fill] ledger. ONE producer, consumed +// by both files. THE SEAM IS THE INGEST: those claims name the collector and the edge fold, so sharing +// collection would hand each claim a precomputed answer. Parse trees and located roots travel on the +// same nullary value so parse-tree probes do not re-tokenize. +// THE LAST ROW IS THE NAMESPACE-XL-0 PRODUCTION-ROUTE FIXTURE, AND IT EARNS ITS PLACE THE WAY THIS +// HEADER ASKS: BY A FLOOR COST RECEIPT, NOT A TRANSCRIBED NUMBER. Every claim in +// v2.test.claim.namespace_xl0.call_argument_mention_survival drives the REAL parse-and-normalize +// ingest of two inline fixture modules, and with the producer absent the floor's own +// `required_floor_claim_cost.tsv` records that module's rows as budget_interrupted / +// right_censored against the per-claim CPU deadline -- INTERRUPTED BEFORE VERDICT, which is neither +// pass nor fail, so the lane blocks on a missing answer rather than a wrong one. That is the +// recurrence this tier deletes, and the disposition is worse than a slow pass: an uninterpretable +// row cannot be read as coverage at all. Re-derive with `claim_batch --entry` on that file plus the +// run's [floor-shared-fill] ledger, which must show this fill landing at preparation with +// disposition=Stored and the former interrupted claims serving hits. +// +// WARM, and the value is portable to the bottom: Outcome> is Nodes, +// symbols, strings and loci -- no Closure and no evaluator-node reference at any depth. It is +// nullary and its sources are INLINE in the witness, so preparation forces it without dispatching a +// host read. THE SEAM IS THE INGEST RATHER THAN THE REFERENCE-SITE COLLECTION, for exactly the +// reason the parse rows above keep normalize out: the claims in that file are ABOUT the collector, +// so sharing the collection would hand each one a precomputed answer to the question it asks. The +// walk stays per claim; only the stage no claim names is shared. data floor_cross_claim_pure_producers_warm: List = [ "v2.test.native_decl_selection.collision_resolved", "v2.extdeps.languages.bash_command_fold.bash_fold_formal_productions", @@ -466,7 +494,8 @@ data floor_cross_claim_pure_producers_warm: List = [ "v2.test.parse.where_refinement_clause_parse.where_refinement_bare_parsed", "v2.test.parse.expression_bodied_fn_decl_parse.expression_bodied_fn_parsed", "v2.test.parse.expression_bodied_fn_decl_parse.expression_bodied_literal_fn_parsed", - "v2.test.parse.expression_bodied_fn_decl_parse.braced_fn_control_parsed" + "v2.test.parse.expression_bodied_fn_decl_parse.braced_fn_control_parsed", + "v2.test.claim.namespace_xl0.call_argument_mention_survival.call_argument_fixture_normalized" ] // grammar_relation_row_for_emitted HAS NOW BEEN MEASURED ON THE THIRD CONJUNCT, AND IT PASSES. @@ -1137,6 +1166,24 @@ type CarriedInputWarmRow { } data floor_cross_claim_prepared_effect_inputs: List = [ + PreparedEffectInput { + acquisition: "v2.test.claim.declaring_identity_spelling.production_ingest.xl3_fixture_reads", + checkout_input: "src/v2/test/fixture/declaring_identity_spelling/ (+ dag/test/probe/declaring_identity_spelling_unresolvable_probe.dag)", + ground: "The NAMESPACE-XL-3 fixture corpus: eight committed .dag files read through filesystem_read into one list of read witnesses; each census is STILL a single-file ingest over its own witness (the census semantics are per file), the acquisition only performs the reads once. Content fixed by the commit the run prepared. Demanded by every claim of v2.test.claim.declaring_identity_spelling.production_ingest through xl3_fixture_censuses.", + measurement: "The floor's own refusal on gunbc#11461 run 35074340220 is the absent arm: fifteen claims of that file COMPLETED-OVER-COST-REQUIREMENT at 130k-430k eval steps against the new-witness budget, each re-deriving its own parse-and-normalize. The present arm is the same run shape with these rows enrolled, read over required_floor_claim_cost.tsv and the [floor-shared-fill] ledger; the acquisition's own arm is the effect-dispatch count for this carrier - eight reads at preparation with the row enrolled, eight per consuming claim without it." + }, + PreparedEffectInput { + acquisition: "v2.test.claim.reference_derived_graph_fixture.fixture_ingest", + checkout_input: "dag/test/fixture/reference_derived_graph/", + ground: "The NAMESPACE-XL-4 fixture corpus: eleven committed .dag modules under the checkout root, read through filesystem_read into one SourceRootIngest so the reference-derived graph claims measure the SAME files the instrument tools.reference_derived_graph reads (one fixture authority - review 65417 on gunbc#11202). Their content is fixed by the commit the run prepared, which is what makes one acquisition at preparation the same ingest every claim would have read for itself. Demanded by v2.test.claim.reference_derived_graph_call_arg_tree and reference_derived_graph_production_ingest through xl4_fixture_trees.", + measurement: "The floor's own refusal on gunbc#11461 run 35059914771 (PureProducerShareWarmDispatchedEffect producer=xl4_fixture_trees effects=11) is the absent arm: the warm reached the world eleven times. The present arm is the same run shape with this row enrolled, read over required_floor_claim_cost.tsv and the [floor-shared-fill] ledger; the acquisition's own arm is the effect-dispatch count for this carrier, which is one prepared acquisition with the row enrolled and eleven inside the warm without it." + }, + PreparedEffectInput { + acquisition: "test.claim.legacy_repair_tap_live_bridge_witness.xl1_fixture_root_tap", + checkout_input: "dag/test/fixture/reference_derived_graph/ (primary root) + dag/std/ (dependency pool) + tools/whole_corpus_compile_measured_root_demands.json (the root's admission row)", + ground: "The NAMESPACE-XL-1 live tap over its measured fixture root: the seed builtin emit_rust_reference_derived_rows_bridge compiles the eleven committed fixture modules against the dag/std pool and returns the Observed encoding (repair rows, occurrence transport, binding rows). Every input is under the checkout root and fixed by the commit the run prepared - the sources, and the demand projection whose row admits the root - so one acquisition at preparation is the same value each of the two Observed-arm claims of that module would have compiled for itself. Demanded by a_measured_fixture_root_reaches_the_observed_arm_with_rows_and_bindings and the_live_census_over_the_measured_fixture_root_counts_its_rows. THE MODULE IS UNDER dag/test/claim/**, OUTSIDE THE GATE CLOSURE, AND THAT IS ADMITTED BY gunbc#11455 RATHER THAN BY THE LIVE-DEPLOY ARGUMENT ABOVE: roster admission is scoped to the prepared subject, and a rostered module present in the corpus but outside the subject is counted and not evaluated (required_floor_runner disposition 2) - so this acquisition runs exactly when its two consumers are planned, which is when this witness module is in the subject, and is never demanded by a subject that does not carry it.", + measurement: "Absent arm: claim_batch --entry dag/test/claim/legacy_repair_tap_live_bridge_witness_test.dag on a session host records each of those two claims paying the compile itself (the [witness] lines carry seconds of cpu against the floor's 500 ms per-claim ceiling), and before this row's root was measured the floor refused the arm at admission in microseconds (gunbc#11461 runs 35074340220, 35079253040). Present arm: the same run shape with this row enrolled, read over required_floor_claim_cost.tsv and the [floor-shared-fill] ledger, the acquisition landing once at preparation with disposition=Stored and both claims serving hits." + }, PreparedEffectInput { acquisition: "gunbc.roadmap_authority.roadmap_acceptance_event_history_load", checkout_input: "dag/gunbc/roadmap/roadmap_acceptance_event_history.jsonl", @@ -1146,6 +1193,18 @@ data floor_cross_claim_prepared_effect_inputs: List = [ ] data floor_cross_claim_carried_input_warm_rows: List = [ + CarriedInputWarmRow { + producer: "v2.test.claim.declaring_identity_spelling.production_ingest.xl3_fixture_censuses", + carried_input: "v2.test.claim.declaring_identity_spelling.production_ingest.xl3_fixture_reads", + dependence: ImplicitAcquisition, + measurement: "The per-fixture parse-normalize-census of the carried reads, computed once and served to every claim of the file as a field read. Present-vs-absent as its input row (gunbc#11461 run 35074340220 absent; the enrolled run present), normalised on claims in no consumer module of any enrolled key. ImplicitAcquisition: xl3_fixture_censuses is nullary and calls xl3_fixture_reads inside itself." + }, + CarriedInputWarmRow { + producer: "v2.test.claim.reference_derived_graph_fixture.xl4_fixture_trees", + carried_input: "v2.test.claim.reference_derived_graph_fixture.fixture_ingest", + dependence: ImplicitAcquisition, + measurement: "The parse-and-normalize of the carried ingest, shared by the two XL-4 claim files whose claims name the collector and the edge fold (the seam is the ingest, not the collection). Present-vs-absent as its input row: gunbc#11202 run 34730467598 refused both files ENROLMENT-MARGIN-REFUSED at the 500ms ceiling without the share; run 34762428707 passed with it as a plain warm row; the carried-input shape replaces that row because the warm reached the world (run 35059914771). ImplicitAcquisition: xl4_fixture_trees is nullary and calls fixture_ingest inside itself." + }, CarriedInputWarmRow { producer: "gunbc.roadmap_authority.roadmap_authority_projection", carried_input: "gunbc.roadmap_authority.roadmap_acceptance_event_history_load", diff --git a/src/v2/workflow/legacy_baseline_capture.dag b/src/v2/workflow/legacy_baseline_capture.dag index 247e4654a48..bbea5742847 100644 --- a/src/v2/workflow/legacy_baseline_capture.dag +++ b/src/v2/workflow/legacy_baseline_capture.dag @@ -1,8 +1,15 @@ module v2.workflow.legacy_baseline_capture -import std.types { String, List, Int, Bool, NonEmptyStr } +import std.types { String, List, Int, Bool, NonEmptyStr, list_length } import std.content_hash { Fnv1a64Structural } -import std.occurrence_identity { ValidatedOccurrenceTransport } +import std.occurrence_identity { + ValidatedOccurrenceTransport, + OccurrenceTransport, + OccurrenceTransportRefusal, + OccurrenceTransportValidated, + OccurrenceTransportRefused, + occurrence_transport_validate +} import extdeps.git.object_store { GitObjectId, git_object_id_eq } import v2.workflow.legacy_repair_observation { CompleteLegacyRepairObservation, @@ -131,9 +138,25 @@ type LegacyBaselineCapturePhase | BindingObservationPhase | RepairCensusPhase +// A BRIDGE ROW WHOSE SPELLING IS EMPTY IS A REFUSAL, NOT A DROP. The seed's repair encoder can +// only ever produce a degenerate (module_name == "" or name == "") row by defect; a fold that +// skipped it would shrink the roster and the observation together, silently, and the roster +// digest would then attest a census that never counted the row (DESIGN 5: a failure arm must +// refuse, never widen). The row is located by its index in the bridge's own order. +type MalformedBridgeRow { + index: Int + module_name: String + name: String +} + +// The Observed arm's block (ObservedArmUnexercisedOnRequiredRoute) is retired: the required +// floor now executes it over a MEASURED fixture root (gunbc#11265 keyed whole-root admission on +// the root's own row; whole_corpus_compile_xl1_fixture_root_demand is that row), and the +// controls that read it are enrolled in test.claim.legacy_repair_tap_live_bridge_witness. The +// variant went with its block: a cause nothing constructs is a dangling declaration (DESIGN 3c). type LegacyBaselineCaptureRefusal - = ObserverNeverReachedDecision - | LiveRepairObservationTapAbsent + = ObserverNeverReachedDecision {} + | BridgeRowSpellingEmpty { malformed: List } // THE SUBJECT FIELD THAT DISAGREED IS NAMED RATHER THAN COUNTED, because the seven digests have // different owners and different repairs: a source-set mismatch means the tree was not the one @@ -172,6 +195,7 @@ type LegacyBaselineCaptureOutcome phase: LegacyBaselineCapturePhase, cause: LegacyBaselineCaptureRefusal } + | LegacyBaselineObservedTransportRefused { refusal: OccurrenceTransportRefusal } // THE SUBJECT THE MATERIALIZED TREE ENTITLES A CAPTURE TO CLAIM. Condition 4 asks that the digests // were DERIVED from that tree -- a fact about the run, not about any value reachable here -- so the @@ -241,6 +265,29 @@ fn first_repair_base_disagreement( // BEFORE the next comparison and before any promotion. Head before worktree, worktree before // subject, subject before admission, admission before the repair census -- so a dirty worktree can // never be reported as a subject disagreement, nor an incomplete observation as a repair gap. +fn capture_legacy_baseline_from_observed_transport( + materialization: CheckoutMaterialization, + tree_subject: TreeDerivedSubjectReceipt, + observation: LegacyBindingObservation, + observed_transport: OccurrenceTransport, + repair_observation: LegacyRepairObservation, + repair_roster: RepairSiteRoster +) -> LegacyBaselineCaptureOutcome { + match occurrence_transport_validate(transport: observed_transport) { + OccurrenceTransportRefused { refusal: r } => + LegacyBaselineObservedTransportRefused { refusal: r } + OccurrenceTransportValidated { transport: t } => + capture_legacy_baseline( + materialization: materialization, + tree_subject: tree_subject, + observation: observation, + transport: t, + repair_observation: repair_observation, + repair_roster: repair_roster + ) + } +} + fn capture_legacy_baseline( materialization: CheckoutMaterialization, tree_subject: TreeDerivedSubjectReceipt, @@ -304,19 +351,30 @@ fn capture_legacy_baseline( // // CAPABILITY IS WHETHER A LIVE CAPTURE OF A NAMED BASE CAN BE TAKEN, not whether the fold can mint // given caller-supplied rows. Fixtures already drive capture_legacy_baseline to LegacyBaselineCaptured. -// No executing producer yet yields a LegacyRepairObservation for a live checkout: emit_rust -// reference_derived_census exists in the seed, is not mapped into this envelope, and has no -// executing consumer that hands capture a graph. Until that tap lands, CaptureAvailable would -// read as "a capture can be taken". Named later change: a v2 producer that maps the repairer's -// per-site dispositions into LegacyRepairObservation + RepairSiteRoster over one GitObjectId -// checkout, without growing the v1 emitter. Trigger: that producer is called from a capture -// entry that materializes the named base. Dissolve LiveRepairObservationTapAbsent then. +// The executing producer is v2.workflow.legacy_repair_tap persist_named_base_from_primary_root_tap: +// it materializes CheckoutMaterialization.requested (a GitObjectId) through +// emit_rust_reference_derived_rows_bridge into LegacyRepairObservation + RepairSiteRoster and the +// tap's binding rows. CaptureAvailable is not ACT-0's BaselineCaptureReceipt and is not a +// corpus-oracle claim. CaptureBlocked remains the typed arm for a later producer loss; +// ObserverNeverReachedDecision is the remaining refuse cause. type LegacyBaselineCaptureCapability = CaptureBlocked { phase: LegacyBaselineCapturePhase, cause: LegacyBaselineCaptureRefusal } | CaptureAvailable +// THE CAPABILITY IS A REPORT OF EXECUTED EVIDENCE ON A REQUIRED ROUTE, NOT A CONSTANT BY FIAT. +// Both arms of the tap now execute on the required floor: the refusal arms as before, and the +// Observed arm over the measured XL-4 fixture root, acquired once at preparation as the +// prepared effect input test.claim.legacy_repair_tap_live_bridge_witness.xl1_fixture_root_tap +// and read by a_measured_fixture_root_reaches_the_observed_arm_with_rows_and_bindings and +// the_live_census_over_the_measured_fixture_root_counts_its_rows (first executed there on +// gunbc#11461 run 35181521483: the floor's own [floor-phase] prepared-effect-input-acquire +// line carries disposition=Xl1PrimaryRootObserved). That is the evidence CaptureAvailable +// reports; delete the Observed arm of compile_xl1_primary_root_tap, or the fixture root's +// measured row, and those controls red before this constant can lie (review 66841, 67146). +// The stage carrier folds this into StageXL1BaselineCapture; the base-specific capture +// (a PersistedLegacyBaseline against the pinned pre-cut base) stays the milestone's question. fn legacy_baseline_capture_capability() -> LegacyBaselineCaptureCapability { - CaptureBlocked { phase: RepairCensusPhase, cause: LiveRepairObservationTapAbsent } + CaptureAvailable } fn capture_blocked_reason(c: LegacyBaselineCaptureCapability) -> List { @@ -339,7 +397,8 @@ fn capture_phase_label(p: LegacyBaselineCapturePhase) -> String { fn capture_refusal_label(cause: LegacyBaselineCaptureRefusal) -> String { match cause { - ObserverNeverReachedDecision => "the observer never reached its decision stage" - LiveRepairObservationTapAbsent => "no executing producer yields LegacyRepairObservation for a live named base" + ObserverNeverReachedDecision {} => "the observer never reached its decision stage" + BridgeRowSpellingEmpty { malformed: m } => + concat("the repair bridge emitted a row with an empty spelling (", concat(to_string(list_length(items: m)), " row(s), located by index)")) } } diff --git a/src/v2/workflow/legacy_baseline_persisted_observation.dag b/src/v2/workflow/legacy_baseline_persisted_observation.dag index 34829e69f66..f744dc3ade3 100644 --- a/src/v2/workflow/legacy_baseline_persisted_observation.dag +++ b/src/v2/workflow/legacy_baseline_persisted_observation.dag @@ -14,7 +14,8 @@ import v2.workflow.legacy_baseline_capture { LegacyBaselineRepairRosterMismatch, LegacyBaselineRepairSubjectDiverged, LegacyBaselineRepairIncomplete, - LegacyBaselineExecutionRefused + LegacyBaselineExecutionRefused, + LegacyBaselineObservedTransportRefused } // PERSISTENCE IS THE CAPTURE CARRIER, NOT A RECEIPTS ROSTER. A row of (base, identity) is a @@ -23,10 +24,12 @@ import v2.workflow.legacy_baseline_capture { // compares the requested GitObjectId to capture.base_commit; a different id cannot be written onto // a held capture. // -// THIS MODULE DOES NOT CLAIM A CORPUS ORACLE. The live pin is PreCutBaseUnpinned until ACT-0 names -// a base. A fixture capture may be held in tests; it does not enroll HEAD. Consumers: capture -// mint, gunbc.compiler_frontend_program_status NamespaceBaselineObservationComplete (outstanding -// fold), ACT-0 BaselineCaptureReceipt (later digest of a re-run), XL-2 chain prerequisite via XL-1 +// THIS MODULE DOES NOT CLAIM A CORPUS ORACLE AND DOES NOT PIN THE PRE-CUT BASE. Pinning B is +// ACT-0's operator decision. Production is PreCutBaseUnpinned; persisted_legacy_baseline_outstanding +// reports outstanding until that pin. A fixture capture may be joined to PreCutBasePinned inside +// a witness via persisted_enrollment_outstanding; that join is not the live pin. Consumers: +// persist_legacy_baseline, persist_named_base_from_primary_root_tap, NamespaceBaselineObservationComplete +// (outstanding fold), ACT-0 BaselineCaptureReceipt (later digest of a re-run), XL-2 via XL-1 // capability, and the discriminating witnesses. type PersistedLegacyBaseline sole_constructor { @@ -52,6 +55,7 @@ fn persist_legacy_baseline( LegacyBaselineRepairSubjectDiverged { field: _ } => PersistRefusedNotCaptured LegacyBaselineRepairIncomplete { completeness: _ } => PersistRefusedNotCaptured LegacyBaselineExecutionRefused { phase: _, cause: _ } => PersistRefusedNotCaptured + LegacyBaselineObservedTransportRefused { refusal: _ } => PersistRefusedNotCaptured } } diff --git a/src/v2/workflow/legacy_repair_tap.dag b/src/v2/workflow/legacy_repair_tap.dag new file mode 100644 index 00000000000..f4067d7b609 --- /dev/null +++ b/src/v2/workflow/legacy_repair_tap.dag @@ -0,0 +1,260 @@ +module v2.workflow.legacy_repair_tap + +import std.types { String, List, Bool, Int, NonEmptyStr, list_length } +import std.decl_ref { decl_ref } +import gunbc.whole_corpus_compile_admission { whole_corpus_compile_repository } +import gunbc.whole_corpus_compile_demand_projection { whole_corpus_compile_demand_projection_path } +import std.occurrence_identity { + ValidatedOccurrenceTransport, + OccurrenceTransport, + OccurrenceId +} +import v2.workflow.legacy_repair_observation { + RepairSite, + RepairSiteRoster, + LegacyRepairObservation, + LegacyRepairObservationRow, + LegacyRepairObservationSubject, + repair_site_roster_identity +} +import v2.workflow.legacy_binding_observation { + LegacyBindingObservation, + LegacyBindingObservationRow, + LegacyBindingObservationSubject +} +import v2.workflow.legacy_baseline_capture { + BridgeRowSpellingEmpty, + CheckoutMaterialization, + LegacyBaselineCaptureOutcome, + LegacyBaselineExecutionRefused, + MalformedBridgeRow, + RepairCensusPhase, + TreeDerivedSubjectReceipt, + capture_legacy_baseline, + capture_legacy_baseline_from_observed_transport +} +import tools.reference_occurrence_binding_census { + ReferenceOccurrenceBindingRow, + ReferenceOccurrenceBindingDisposition +} +import gunbc.reference_derived_candidate { + ReferenceDerivedCandidateDisposition, + ReferenceDerivedCandidateRow +} +import v2.workflow.legacy_baseline_persisted_observation { + persist_legacy_baseline, + PersistAdmission, + PersistRefusedNotCaptured +} + +// XL-1 LIVE REPAIR TAP. Sole consumer of the seed builtin emit_rust_reference_derived_rows_bridge. +// Roster-from-same-rows is a declared tautology (parent 2026-09-12): checkable, not structurally +// independent of answering. The arm is never enrolled on a required-floor path; one offline run +// per pinned base stores the observation. Deleted with v1.compiler.emit_rust / the interpreter. + +type Xl1PrimaryRootTap + = Xl1PrimaryRootObserved { + primary_root: String + repair_rows: List + occurrence_transport: OccurrenceTransport + binding_rows: List + } + | Xl1PrimaryRootRefused { cause: String } + + +// ONE FOLD ADMITS THE BRIDGE ROWS OR REFUSES THEM; nothing is dropped. A row whose spelling is +// empty is a defect of the seed encoder, and a fold that skipped it would shrink the roster and +// the observation together while the roster digest still attested a census (review 66826 on +// gunbc#11461; DESIGN 5 - refuse, never widen). The refusal travels as the located row list, the +// same shape the reference-site collector uses for unreadable roots. +type BridgeRowsFold { + sites: List + rows: List> + malformed: List + next_index: Int +} + +type BridgeRowsAdmission + = BridgeRowsAdmitted { + roster: RepairSiteRoster, + rows: List> + } + | BridgeRowsRefused { malformed: List } + +fn fold_bridge_row(acc: BridgeRowsFold, row: ReferenceDerivedCandidateRow) -> BridgeRowsFold { + if row.module_name == "" || row.name == "" { + BridgeRowsFold { + sites: acc.sites, + rows: acc.rows, + malformed: concat(acc.malformed, [MalformedBridgeRow { + index: acc.next_index, + module_name: row.module_name, + name: row.name + }]), + next_index: acc.next_index + 1 + } + } else { + let site = RepairSite { + module_name: row.module_name as NonEmptyStr, + name: row.name as NonEmptyStr + } + BridgeRowsFold { + sites: concat(acc.sites, [site]), + rows: concat(acc.rows, [LegacyRepairObservationRow { site: site, outcome: row.disposition }]), + malformed: acc.malformed, + next_index: acc.next_index + 1 + } + } +} + +fn admit_bridge_rows(rows: List) -> BridgeRowsAdmission { + let folded = fold( + rows, + init: BridgeRowsFold { sites: [], rows: [], malformed: [], next_index: 0 }, + f: fold_bridge_row + ) + if list_length(items: folded.malformed) == 0 { + BridgeRowsAdmitted { roster: RepairSiteRoster { sites: folded.sites }, rows: folded.rows } + } else { + BridgeRowsRefused { malformed: folded.malformed } + } +} + +fn repair_observation_from_admitted_rows( + admitted_rows: List>, + roster: RepairSiteRoster, + tree: LegacyBindingObservationSubject +) -> LegacyRepairObservation { + LegacyRepairObservation { + subject: LegacyRepairObservationSubject { + semantic_source_digest: tree.semantic_source_digest, + source_set_digest: tree.source_set_digest, + compiler_artifact_digest: tree.compiler_artifact_digest, + repairer_identity: decl_ref(module_path: "v1.compiler.emit_rust", decl_name: "emit_rust_reference_derived_rows"), + repair_site_roster_digest: repair_site_roster_identity(roster: roster), + resolution_registry_digest: tree.declaration_index_digest + }, + rows: admitted_rows + } +} + +fn bridge_rows_refused_outcome( + malformed: List +) -> LegacyBaselineCaptureOutcome { + LegacyBaselineExecutionRefused { + phase: RepairCensusPhase, + cause: BridgeRowSpellingEmpty { malformed: malformed } + } +} + +fn persist_capture_from_bridge_rows( + materialization: CheckoutMaterialization, + tree_subject: TreeDerivedSubjectReceipt, + observation: LegacyBindingObservation, + transport: ValidatedOccurrenceTransport, + rows: List +) -> PersistAdmission { + match admit_bridge_rows(rows: rows) { + BridgeRowsRefused { malformed: m } => + persist_legacy_baseline(outcome: bridge_rows_refused_outcome(malformed: m)) + BridgeRowsAdmitted { roster: roster, rows: admitted } => + persist_legacy_baseline( + outcome: capture_legacy_baseline( + materialization: materialization, + tree_subject: tree_subject, + observation: observation, + transport: transport, + repair_observation: repair_observation_from_admitted_rows(admitted_rows: admitted, roster: roster, tree: tree_subject.subject), + repair_roster: roster + ) + ) + } +} + +fn binding_observation_from_tap_rows( + subject: LegacyBindingObservationSubject, + rows: List +) -> LegacyBindingObservation { + LegacyBindingObservation { + subject: subject, + rows: rows |> map(r => LegacyBindingObservationRow { + occurrence: OccurrenceId { value: r.occurrence }, + outcome: r.disposition + }) + } +} + +// THE NAMED-BASE CAPTURE ENTRY. CheckoutMaterialization.requested is the GitObjectId the capture +// will bind; the tap is the only producer of live repair rows and of the occurrence transport those +// rows were taken with. Caller-supplied binding observations are not this entry: they can mint +// without the tap. persist_capture_from_bridge_rows is the fixture injection (validated transport +// plus rows, no live builtin). Empty source_roots refuse inside the seed arm. +fn persist_named_base_from_primary_root_tap( + materialization: CheckoutMaterialization, + tree_subject: TreeDerivedSubjectReceipt, + source_roots: List +) -> PersistAdmission { + match emit_rust_reference_derived_rows_bridge(source_roots, whole_corpus_compile_repository as String, whole_corpus_compile_demand_projection_path()) { + Xl1PrimaryRootRefused { cause: _ } => PersistRefusedNotCaptured + Xl1PrimaryRootObserved { + repair_rows: rows, + occurrence_transport: ot, + binding_rows: bindings, + primary_root: _ + } => + match admit_bridge_rows(rows: rows) { + BridgeRowsRefused { malformed: m } => + persist_legacy_baseline(outcome: bridge_rows_refused_outcome(malformed: m)) + BridgeRowsAdmitted { roster: roster, rows: admitted } => + persist_legacy_baseline( + outcome: capture_legacy_baseline_from_observed_transport( + materialization: materialization, + tree_subject: tree_subject, + observation: binding_observation_from_tap_rows(subject: tree_subject.subject, rows: bindings), + observed_transport: ot, + repair_observation: repair_observation_from_admitted_rows(admitted_rows: admitted, roster: roster, tree: tree_subject.subject), + repair_roster: roster + ) + ) + } + } +} + +fn append_unique_module(acc: List, n: String) -> List { + if n == "" || (acc |> any(x => x == n)) { + acc + } else { + concat(acc, [n]) + } +} + +fn repair_emitted_module_names(rows: List) -> List { + fold(rows, init: [], f: (acc, row) => append_unique_module(acc: acc, n: row.module_name)) +} + +fn never_emitted_declared_modules( + declared_modules: List, + emitted_modules: List +) -> List { + declared_modules |> filter(d => !(emitted_modules |> any(e => e == d))) +} + +type Xl1LiveRepairTapCensus + = Xl1LiveRepairTapRows { count: Int } + | Xl1LiveRepairTapUnavailable { cause: String } + +// The census is a fold over a TAP VALUE so a prepared (floor-acquired) tap serves it without a +// second compile; the source-roots entry composes the live bridge with it. +fn xl1_live_repair_tap_census_of(tap: Xl1PrimaryRootTap) -> Xl1LiveRepairTapCensus { + match tap { + Xl1PrimaryRootRefused { cause: c } => Xl1LiveRepairTapUnavailable { cause: c } + Xl1PrimaryRootObserved { repair_rows: rows, primary_root: _, occurrence_transport: _, binding_rows: _ } => + Xl1LiveRepairTapRows { count: list_length(items: rows) } + } +} + +fn xl1_live_repair_tap_census(source_roots: List) -> Xl1LiveRepairTapCensus { + xl1_live_repair_tap_census_of( + tap: emit_rust_reference_derived_rows_bridge(source_roots, whole_corpus_compile_repository as String, whole_corpus_compile_demand_projection_path()) + ) +} diff --git a/tools/whole_corpus_compile_measured_root_demands.json b/tools/whole_corpus_compile_measured_root_demands.json index 17ab9368baf..46c28e1e634 100644 --- a/tools/whole_corpus_compile_measured_root_demands.json +++ b/tools/whole_corpus_compile_measured_root_demands.json @@ -1 +1 @@ -{"schema": "gunbc.whole_corpus_compile_demand_projection/1", "rows": [{"repository": "gunbc", "primary_root": "dag", "dependency_pools": ["src/v2"], "peak_bytes": 17179869184, "source_count": 3109, "source_bytes": null, "measured_on": "2026-08-28", "instrument_run": "gunbc compile --source-root dag --source-root src/v2 --target dag under /usr/bin/time -v on srv1: completing run by warm-ant-908 at be89e236c9 (exit 0), refusing runs by clever-tern-899 at 91c05c1b34", "evidence": "gunbc.whole_corpus_compile_admission::whole_corpus_compile_measured_demand_note"}]} +{"schema": "gunbc.whole_corpus_compile_demand_projection/1", "rows": [{"repository": "gunbc", "primary_root": "dag", "dependency_pools": ["src/v2"], "peak_bytes": 17179869184, "source_count": 3109, "source_bytes": null, "measured_on": "2026-08-28", "instrument_run": "gunbc compile --source-root dag --source-root src/v2 --target dag under /usr/bin/time -v on srv1: completing run by warm-ant-908 at be89e236c9 (exit 0), refusing runs by clever-tern-899 at 91c05c1b34", "evidence": "gunbc.whole_corpus_compile_admission::whole_corpus_compile_measured_demand_note"}, {"repository": "gunbc", "primary_root": "dag/test/fixture/reference_derived_graph", "dependency_pools": ["dag/std"], "peak_bytes": 1073741824, "source_count": 14, "source_bytes": 73093, "measured_on": "2026-09-17", "instrument_run": "gunbc measure-root-demand --repository gunbc --source-root dag/test/fixture/reference_derived_graph --source-root dag/std (3d35de172cc5c26bce303073efde2a7dfa00efd6-dirty, child pid 737628 at unix 1789616975) on 60e1d18cada1 under cgroup memory.max (/sys/fs/cgroup/), limit 33578549248: completed, exit 0, peak 278921216", "evidence": "gunbc.root_demand_measurement::measured_for_root_from_receipt"}]}