diff --git a/dag/gunbc/self_host_compile_phase_frontier.dag b/dag/gunbc/self_host_compile_phase_frontier.dag index 6e8917b848d..f75ba06c596 100644 --- a/dag/gunbc/self_host_compile_phase_frontier.dag +++ b/dag/gunbc/self_host_compile_phase_frontier.dag @@ -127,13 +127,16 @@ fn canonical_identity_set(identities: List) -> List { deduplicate_identities(identities: identities) |> sort_by(identity => identity) } -// Duplicate handling is a POPULATION fact, and the two populations answer it at different sites. -// raw_identities is set-deduplicated by the live producer before the fold, and on the persisted -// path a repeat makes the deduplicated total disagree with the raw count, which receipt coherence -// refuses. parse_refused_files had neither wall: a path rustfmt refused twice would be counted -// twice in the Parse row and kept twice in the digest, so the digest would answer about a multiset -// while its name claims a set. Refusing is the right arm rather than deduplicating here, because -// collapsing the repeat would hide the producer defect behind a well-formed-looking census. +// A census population carries no repeats, and this predicate is where that is decided. Refusal is +// the arm rather than collapsing the repeat: deduplicating here would make a duplicated population +// indistinguishable from a clean one, hiding a producer defect behind a census that still looked +// well-formed -- widening instead of refusing. +// +// It answers for BOTH populations reaching receipt coherence, and the refused-file population is +// the reason it exists: a path refused twice would be counted twice in the Parse row and kept twice +// in the digest, so the digest would answer about a multiset while its name claims a set. +// The falsifier is enrolled: deleting either call in receipt_population_coherent must turn +// a_receipt_whose_refused_population_repeats_a_path_is_refused_by_coherence red. fn census_population_is_duplicate_free(identities: List) -> Bool { count(deduplicate_identities(identities: identities)) == count(identities) } @@ -178,20 +181,19 @@ fn first_failing_checked_phase(ds: List) -> RustcPhase { // refuses a receipt whose census is in fact identical. The two populations stay separate segments: // canonicalizing them jointly would let a refused path and an identity trade places. // -// EmissionOrderedV1 is retired and NO PRODUCER CONSTRUCTS IT. Its justification is NOT that it -// labels a live value -- it does not. docs/design-ledgers.md published an emission-order digest -// until this change, and regenerating that projection replaces it, so after this commit no -// artifact in the tree carries one and the retired value survives only in git history. -// -// It is kept because an algorithm identity with exactly ONE inhabitant distinguishes nothing. The -// field exists to stop two incompatible digest meanings hiding behind a single unlabeled hash, and -// that requires both meanings to be nameable. So the honest fork is not "drop the arm" but "drop -// the arm AND the field": a one-inhabitant tag is decoration, and keeping the tag while deleting -// its only contrast is the worse of the two shapes. +// EmissionOrderedV1 is retired and no producer constructs it. It is kept because an algorithm +// identity with exactly ONE inhabitant distinguishes nothing: the field exists so two incompatible +// digest meanings cannot hide behind one unlabeled hash, and that requires both meanings to be +// nameable. Keeping the tag while deleting its only contrast is the worse of the two shapes, so the +// fork is the arm AND the field together, never the arm alone. A second fold is then a row rather +// than a migration. // -// It is read by production -- census_identity_domain_separator matches it exhaustively -- and by a -// witness asserting the two separators differ, so it is not an inert carrier under -// v2.lens.inert_carrier, whose scope is carriers read by no production code. +// The evidence that the arm is not decorative is the witness: +// the_census_digest_carries_the_algorithm_that_produced_it asserts the two separators differ, so +// unifying them goes red. Supporting that, census_identity_domain_separator must handle the arm in +// an exhaustive match -- a compile-time read, not a runtime one, since nothing constructs the arm. +// That forces an edit on deletion but does not by itself distinguish a live arm from an inert one, +// which is true of every arm of every coproduct. type CensusIdentityAlgorithm = EmissionOrderedV1 | CanonicalIdentitySetV1 @@ -210,6 +212,15 @@ type CensusIdentityDigest { digest: Fnv1a64Structural } +// NEITHER SORT MAY BE REMOVED ON THE GROUNDS THAT A CALLER ALREADY CANONICALIZES. The PERSISTED +// path calls this function with receipt.raw_error_diagnostic_identities directly, and that list +// passes through no caller-side canonicalization at all -- so no property of any caller, present or +// future, can substitute for these sorts. Delete either one and the live path stays correct while +// the persisted path silently returns to being order-contaminated, which is the defect this fold +// exists to close, reintroduced by a plausible cleanup. +// +// The falsifier is enrolled rather than described: removing a sort must turn +// the_census_digest_is_invariant_under_reordering_of_either_population red. fn phase_census_digest(parse_refused_files: List, raw_identities: List) -> CensusIdentityDigest { CensusIdentityDigest { algorithm: CanonicalIdentitySetV1, diff --git a/dag/test/claim/self_host_compile_phase_frontier_witness_test.dag b/dag/test/claim/self_host_compile_phase_frontier_witness_test.dag index a8c329b3e82..b4ee626fa71 100644 --- a/dag/test/claim/self_host_compile_phase_frontier_witness_test.dag +++ b/dag/test/claim/self_host_compile_phase_frontier_witness_test.dag @@ -1,7 +1,10 @@ module test.claim.self_host_compile_phase_frontier_witness import std.types { Bool, Int, String, NonEmptyStr } -import std.content_hash { content_hash_atom } +import std.content_hash { content_hash_atom, Sha1Digest } +import extdeps.git.object_store { GitSha1ObjectId } +import extdeps.crypto.hash { sha256_digest } +import v2.workflow.floor_discovery { floor_discovery_tree_id } import extdeps.git.inspect { CommitSha } import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } import extdeps.languages.rust.compiler_phases { RustcPhase, Parse, Expand, Resolve, Typeck, Borrowck } @@ -36,6 +39,15 @@ import gunbc.self_host_compile_phase_frontier { self_host_compile_phase_frontier_receipts, PersistedPhaseBoardFold, phase_board_from_census_identities, + receipt_population_coherent, + CompilePhaseFrontierReceipt, + seal_compile_phase_receipt, + CompilePhaseReceiptSubject, + CompilePhaseInvocation, + PhaseBoardProducer, + PhaseBoardBaseline, + ParseReached, + rustc_phase_classification_policy_digest, board_row, CompilePhaseFrontierValidated, compile_phase_frontier_standing, @@ -564,3 +576,108 @@ test fn a_new_emitted_module_disposition_refuses_a_file_the_predecessor_already_ identity: "src/old.rs:9:9\tE0599\tno method" ) } + +// PINS THE WIRING, NOT THE PREDICATE. census_population_is_duplicate_free already has a direct +// probe, but nothing drove receipt_population_coherent with a duplicated population, so DELETING +// the conjunct outright left every witness green -- the wall executed as a predicate and unexecuted +// as a wall, failing in the direction of simply not being there. +// +// The subject is a duplicated refused_files list, and that choice is load-bearing. A duplicated +// raw_error_diagnostic_identities would also break the separate +// total_error_diagnostics == count(raw_error_diagnostic_identities) conjunct, so the probe would +// stay red with the duplicate conjunct deleted and would pin nothing. Duplicated refused_files +// breaks ONLY the duplicate wall: the board rows derive from the same list on both sides so they +// still agree, and the error totals concern identities rather than refused paths. So this witness +// goes red exactly when the wall is removed. +fn duplicated_refusal_receipt() -> CompilePhaseFrontierReceipt { + let parse = RustfmtParseObservation { + producer: "fixture-rustfmt", + files_observed: 2, + refused_files: ["src/a.rs", "src/a.rs"] + } + let fold = phase_board_from_census_identities(parse_observation: parse, raw_identities: []) + seal_compile_phase_receipt( + sequence: 0, + observed_at: "2026-08-31T00:00:00Z" as NonEmptyStr, + subject: CompilePhaseReceiptSubject { + source_revision: "1111111111111111111111111111111111111111" as CommitSha, + git_tree_object: floor_discovery_tree_id(object_id: GitSha1ObjectId { digest: Sha1Digest { hex: "2222222222222222222222222222222222222222" } }), + emitted_artifact_identity: sha256_digest(hex: "3333333333333333333333333333333333333333333333333333333333333333" as NonEmptyStr), + compiler_identity: sha256_digest(hex: "4444444444444444444444444444444444444444444444444444444444444444" as NonEmptyStr), + assembler_identity: sha256_digest(hex: "5555555555555555555555555555555555555555555555555555555555555555" as NonEmptyStr), + cargo_identity: "cargo fixture" as NonEmptyStr, + rustc_identity: "rustc fixture" as NonEmptyStr, + invocation: CompilePhaseInvocation { target: "fixture-target", profile: "check/dev", features: [] }, + classification_policy_digest: rustc_phase_classification_policy_digest, + comparison_epoch: "fixture-epoch" as NonEmptyStr + }, + invocation: "fixture-invocation" as NonEmptyStr, + position: PhaseBoardBaseline, + previous_prefix_digest: none, + parse_evidence: ParseReached { evidence: parse }, + board: fold.board, + raw_error_diagnostic_identities: [], + unplaced_identities: fold.unplaced_identities, + newly_exposed: [], + unadmitted_regressions: [], + regression_repairs: [], + reclassified_predecessor_board: none, + producer: PhaseBoardProducer { + module_path: "test.claim.self_host_compile_phase_frontier_witness", + function: "duplicated_refusal_receipt", + entry: "fixture" + } + ) +} + +test fn a_receipt_whose_refused_population_repeats_a_path_is_refused_by_coherence() -> Bool { + !receipt_population_coherent(receipt: duplicated_refusal_receipt()) +} + +// Positive control for the probe above: the SAME receipt shape with the repeat removed must be +// coherent. Without it, a receipt that failed for any unrelated reason would satisfy the refusal +// assertion and the probe would pin nothing. +fn clean_refusal_receipt() -> CompilePhaseFrontierReceipt { + let parse = RustfmtParseObservation { + producer: "fixture-rustfmt", + files_observed: 2, + refused_files: ["src/a.rs", "src/b.rs"] + } + let fold = phase_board_from_census_identities(parse_observation: parse, raw_identities: []) + seal_compile_phase_receipt( + sequence: 0, + observed_at: "2026-08-31T00:00:00Z" as NonEmptyStr, + subject: CompilePhaseReceiptSubject { + source_revision: "1111111111111111111111111111111111111111" as CommitSha, + git_tree_object: floor_discovery_tree_id(object_id: GitSha1ObjectId { digest: Sha1Digest { hex: "2222222222222222222222222222222222222222" } }), + emitted_artifact_identity: sha256_digest(hex: "3333333333333333333333333333333333333333333333333333333333333333" as NonEmptyStr), + compiler_identity: sha256_digest(hex: "4444444444444444444444444444444444444444444444444444444444444444" as NonEmptyStr), + assembler_identity: sha256_digest(hex: "5555555555555555555555555555555555555555555555555555555555555555" as NonEmptyStr), + cargo_identity: "cargo fixture" as NonEmptyStr, + rustc_identity: "rustc fixture" as NonEmptyStr, + invocation: CompilePhaseInvocation { target: "fixture-target", profile: "check/dev", features: [] }, + classification_policy_digest: rustc_phase_classification_policy_digest, + comparison_epoch: "fixture-epoch" as NonEmptyStr + }, + invocation: "fixture-invocation" as NonEmptyStr, + position: PhaseBoardBaseline, + previous_prefix_digest: none, + parse_evidence: ParseReached { evidence: parse }, + board: fold.board, + raw_error_diagnostic_identities: [], + unplaced_identities: fold.unplaced_identities, + newly_exposed: [], + unadmitted_regressions: [], + regression_repairs: [], + reclassified_predecessor_board: none, + producer: PhaseBoardProducer { + module_path: "test.claim.self_host_compile_phase_frontier_witness", + function: "clean_refusal_receipt", + entry: "fixture" + } + ) +} + +test fn the_same_receipt_without_the_repeat_is_coherent() -> Bool { + receipt_population_coherent(receipt: clean_refusal_receipt()) +}