diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25d6ed1e7aa..4ab5537484f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,16 +105,16 @@ jobs: ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) set -o pipefail BUILD_LOG=$(mktemp) - if ! ("$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin frontier_probe_survey --bin namespace_structural_root_exposure_generated_witness) 2>&1 | tee "$BUILD_LOG"; then + if ! ("$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin namespace_structural_root_exposure_generated_witness) 2>&1 | tee "$BUILD_LOG"; then if grep -qiE 'Resource temporarily unavailable|failed to spawn|sccache: encountered fatal error|(exit status: 254)|sccache: error: failed to execute compile' "$BUILD_LOG"; then echo "::warning::cargo/sccache EAGAIN under fleet pressure; cold retry CARGO_BUILD_JOBS=1 (keep sccache)" - CARGO_BUILD_JOBS=1 "$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin frontier_probe_survey --bin namespace_structural_root_exposure_generated_witness + CARGO_BUILD_JOBS=1 "$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin namespace_structural_root_exposure_generated_witness else exit 1 fi fi rm -f "$BUILD_LOG" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" sccache --show-stats 2>/dev/null || true timeout-minutes: 45 - name: cargo test -p v1-compiler-tests --release (retained-kernel execution gate; reuses release v1-compiler) @@ -148,7 +148,7 @@ jobs: run: | # 🟡 dissolve-on: ci_release_bins_pack_script — concat-built foreign-executor (GitHub Actions run:) release-bins tar pack runner; membership of archived bin names is derived from gunbc.ci_release_bins, but the pack transport itself remains hand-shell; DISSOLVES WHEN bash-emit (#5828 / ROADMAP 6-shell-slice0 / shell→intent Phase 2) realizes the pack runner through orchestration emit or typed host_effect_apply without a medium-as-string concat scaffold ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) - tar -czf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" "claim_executor" "gunbc" "regen_floor_skip_witness" "floor_skip_discovery_witness" "selection_control_skip_witness" "discover_source_root_ingest" "claim_batch" "regen_stage0" "interp_recorded_fixture_witness" "v1_src_dag_parse" "auth_declared_but_unwired_witness" "bootstrap_witness" "dag_collect_fingerprint_witness" "diagnostics_witness" "effects_rest_transport_witness" "infer_semantics_witness" "parse_witness" "resolution_divergence_census" "cssl_assemble" "frontier_probe_survey" "namespace_structural_root_exposure_generated_witness" + tar -czf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" "claim_executor" "gunbc" "regen_floor_skip_witness" "floor_skip_discovery_witness" "selection_control_skip_witness" "discover_source_root_ingest" "claim_batch" "regen_stage0" "interp_recorded_fixture_witness" "v1_src_dag_parse" "auth_declared_but_unwired_witness" "bootstrap_witness" "dag_collect_fingerprint_witness" "diagnostics_witness" "effects_rest_transport_witness" "infer_semantics_witness" "parse_witness" "resolution_divergence_census" "cssl_assemble" "namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: Upload release-bins artifact uses: actions/upload-artifact@v4 @@ -212,7 +212,7 @@ jobs: mkdir -p "$ROOT/target/release" tar -xzf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" rm -f "$ROOT/release-bins.tgz" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: gunbc ci regen (self-host fixed-point — required) run: | @@ -310,7 +310,7 @@ jobs: mkdir -p "$ROOT/target/release" tar -xzf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" rm -f "$ROOT/release-bins.tgz" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: Floor cgroup peak pre-read (calibration; reset if permitted) run: | @@ -389,7 +389,7 @@ jobs: mkdir -p "$ROOT/target/release" tar -xzf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" rm -f "$ROOT/release-bins.tgz" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: Converge repository-local Git integration bindings (repo_local_git_config converge) run: | @@ -631,7 +631,7 @@ jobs: mkdir -p "$ROOT/target/release" tar -xzf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" rm -f "$ROOT/release-bins.tgz" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: WIF auth (OIDC -> fleet-cloud-convergence SA, access token only) id: wif_auth diff --git a/.github/workflows/falsifier.yml b/.github/workflows/falsifier.yml index e7e039a576a..8666094d2ec 100644 --- a/.github/workflows/falsifier.yml +++ b/.github/workflows/falsifier.yml @@ -74,23 +74,23 @@ jobs: ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) set -o pipefail BUILD_LOG=$(mktemp) - if ! ("$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin frontier_probe_survey --bin namespace_structural_root_exposure_generated_witness) 2>&1 | tee "$BUILD_LOG"; then + if ! ("$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin namespace_structural_root_exposure_generated_witness) 2>&1 | tee "$BUILD_LOG"; then if grep -qiE 'Resource temporarily unavailable|failed to spawn|sccache: encountered fatal error|(exit status: 254)|sccache: error: failed to execute compile' "$BUILD_LOG"; then echo "::warning::cargo/sccache EAGAIN under fleet pressure; cold retry CARGO_BUILD_JOBS=1 (keep sccache)" - CARGO_BUILD_JOBS=1 "$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin frontier_probe_survey --bin namespace_structural_root_exposure_generated_witness + CARGO_BUILD_JOBS=1 "$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin namespace_structural_root_exposure_generated_witness else exit 1 fi fi rm -f "$BUILD_LOG" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" sccache --show-stats 2>/dev/null || true timeout-minutes: 45 - name: Pack release bins for cross-job handoff (tar keeps exec bits) run: | # 🟡 dissolve-on: ci_release_bins_pack_script — concat-built foreign-executor (GitHub Actions run:) release-bins tar pack runner; membership of archived bin names is derived from gunbc.ci_release_bins, but the pack transport itself remains hand-shell; DISSOLVES WHEN bash-emit (#5828 / ROADMAP 6-shell-slice0 / shell→intent Phase 2) realizes the pack runner through orchestration emit or typed host_effect_apply without a medium-as-string concat scaffold ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) - tar -czf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" "claim_executor" "gunbc" "regen_floor_skip_witness" "floor_skip_discovery_witness" "selection_control_skip_witness" "discover_source_root_ingest" "claim_batch" "regen_stage0" "interp_recorded_fixture_witness" "v1_src_dag_parse" "auth_declared_but_unwired_witness" "bootstrap_witness" "dag_collect_fingerprint_witness" "diagnostics_witness" "effects_rest_transport_witness" "infer_semantics_witness" "parse_witness" "resolution_divergence_census" "cssl_assemble" "frontier_probe_survey" "namespace_structural_root_exposure_generated_witness" + tar -czf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" "claim_executor" "gunbc" "regen_floor_skip_witness" "floor_skip_discovery_witness" "selection_control_skip_witness" "discover_source_root_ingest" "claim_batch" "regen_stage0" "interp_recorded_fixture_witness" "v1_src_dag_parse" "auth_declared_but_unwired_witness" "bootstrap_witness" "dag_collect_fingerprint_witness" "diagnostics_witness" "effects_rest_transport_witness" "infer_semantics_witness" "parse_witness" "resolution_divergence_census" "cssl_assemble" "namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: Upload release-bins artifact uses: actions/upload-artifact@v4 @@ -154,7 +154,7 @@ jobs: mkdir -p "$ROOT/target/release" tar -xzf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" rm -f "$ROOT/release-bins.tgz" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: Affected-set selection control (floor_skip_discovery_witness) run: | @@ -222,7 +222,7 @@ jobs: mkdir -p "$ROOT/target/release" tar -xzf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" rm -f "$ROOT/release-bins.tgz" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: Floor cgroup peak pre-read (calibration; reset if permitted) run: | diff --git a/.github/workflows/fleet-converge.yml b/.github/workflows/fleet-converge.yml index caf8b7e7d15..49b982a7e97 100644 --- a/.github/workflows/fleet-converge.yml +++ b/.github/workflows/fleet-converge.yml @@ -89,23 +89,23 @@ jobs: ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) set -o pipefail BUILD_LOG=$(mktemp) - if ! ("$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin frontier_probe_survey --bin namespace_structural_root_exposure_generated_witness) 2>&1 | tee "$BUILD_LOG"; then + if ! ("$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin namespace_structural_root_exposure_generated_witness) 2>&1 | tee "$BUILD_LOG"; then if grep -qiE 'Resource temporarily unavailable|failed to spawn|sccache: encountered fatal error|(exit status: 254)|sccache: error: failed to execute compile' "$BUILD_LOG"; then echo "::warning::cargo/sccache EAGAIN under fleet pressure; cold retry CARGO_BUILD_JOBS=1 (keep sccache)" - CARGO_BUILD_JOBS=1 "$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin frontier_probe_survey --bin namespace_structural_root_exposure_generated_witness + CARGO_BUILD_JOBS=1 "$CARGO_BIN" build -p v1-compiler --release --features text_lookup_work_counter,interp_test_witness,test_hooks --bin claim_executor --bin gunbc --bin regen_floor_skip_witness --bin floor_skip_discovery_witness --bin selection_control_skip_witness --bin discover_source_root_ingest --bin claim_batch --bin regen_stage0 --bin interp_recorded_fixture_witness --bin v1_src_dag_parse --bin auth_declared_but_unwired_witness --bin bootstrap_witness --bin dag_collect_fingerprint_witness --bin diagnostics_witness --bin effects_rest_transport_witness --bin infer_semantics_witness --bin parse_witness --bin resolution_divergence_census --bin cssl_assemble --bin namespace_structural_root_exposure_generated_witness else exit 1 fi fi rm -f "$BUILD_LOG" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" sccache --show-stats 2>/dev/null || true timeout-minutes: 45 - name: Pack release bins for cross-job handoff (tar keeps exec bits) run: | # 🟡 dissolve-on: ci_release_bins_pack_script — concat-built foreign-executor (GitHub Actions run:) release-bins tar pack runner; membership of archived bin names is derived from gunbc.ci_release_bins, but the pack transport itself remains hand-shell; DISSOLVES WHEN bash-emit (#5828 / ROADMAP 6-shell-slice0 / shell→intent Phase 2) realizes the pack runner through orchestration emit or typed host_effect_apply without a medium-as-string concat scaffold ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) - tar -czf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" "claim_executor" "gunbc" "regen_floor_skip_witness" "floor_skip_discovery_witness" "selection_control_skip_witness" "discover_source_root_ingest" "claim_batch" "regen_stage0" "interp_recorded_fixture_witness" "v1_src_dag_parse" "auth_declared_but_unwired_witness" "bootstrap_witness" "dag_collect_fingerprint_witness" "diagnostics_witness" "effects_rest_transport_witness" "infer_semantics_witness" "parse_witness" "resolution_divergence_census" "cssl_assemble" "frontier_probe_survey" "namespace_structural_root_exposure_generated_witness" + tar -czf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" "claim_executor" "gunbc" "regen_floor_skip_witness" "floor_skip_discovery_witness" "selection_control_skip_witness" "discover_source_root_ingest" "claim_batch" "regen_stage0" "interp_recorded_fixture_witness" "v1_src_dag_parse" "auth_declared_but_unwired_witness" "bootstrap_witness" "dag_collect_fingerprint_witness" "diagnostics_witness" "effects_rest_transport_witness" "infer_semantics_witness" "parse_witness" "resolution_divergence_census" "cssl_assemble" "namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: Upload release-bins artifact uses: actions/upload-artifact@v4 @@ -142,7 +142,7 @@ jobs: mkdir -p "$ROOT/target/release" tar -xzf "$ROOT/release-bins.tgz" -C "$ROOT/target/release" rm -f "$ROOT/release-bins.tgz" - "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/frontier_probe_survey" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" + "$ROOT/target/release/claim_executor" --verify-build-artifacts "$ROOT/target/release/claim_executor" "$ROOT/target/release/gunbc" "$ROOT/target/release/regen_floor_skip_witness" "$ROOT/target/release/floor_skip_discovery_witness" "$ROOT/target/release/selection_control_skip_witness" "$ROOT/target/release/discover_source_root_ingest" "$ROOT/target/release/claim_batch" "$ROOT/target/release/regen_stage0" "$ROOT/target/release/interp_recorded_fixture_witness" "$ROOT/target/release/v1_src_dag_parse" "$ROOT/target/release/auth_declared_but_unwired_witness" "$ROOT/target/release/bootstrap_witness" "$ROOT/target/release/dag_collect_fingerprint_witness" "$ROOT/target/release/diagnostics_witness" "$ROOT/target/release/effects_rest_transport_witness" "$ROOT/target/release/infer_semantics_witness" "$ROOT/target/release/parse_witness" "$ROOT/target/release/resolution_divergence_census" "$ROOT/target/release/cssl_assemble" "$ROOT/target/release/namespace_structural_root_exposure_generated_witness" timeout-minutes: 5 - name: WIF auth (OIDC -> fleet-cloud-convergence SA, access token only) id: wif_auth diff --git a/ROADMAP.md b/ROADMAP.md index 905113f36d4..3349494fd64 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -10,7 +10,7 @@ Parked context (non-dispatchable): [compiler algorithm survey](docs/plans/compil The graph has sixteen lanes: SCM compatibility · namespace · P-derive · observation · placement · compute · CI cost · CI control · generated artefacts · v1 exit (four finish lines: compiler fixed point, interpreter deleted, products v1-free, zero hand-maintained Rust) · shell · roadmap runtime · fleet/hygiene · judgment · hermetic toolchain · compiler-guarantee (the DESIGN §4b ladder climbs; rung STATE lives in the guarantee claims carrier and is emitted, never restated in tickets — [gap analysis](docs/plans/compiler-guarantee-recovery-gap-analysis.md)). The three independent SCM R0 models, the separate P−1 evidence carrier, R1 compatibility-shape extraction, and P0 user-contract/landing spine are accepted; the operator-authored P1 proof-kernel node is active and fail-closed pending its first discriminating closing validation, while P2 and later product lanes remain parked. The toolchain pin model is an independent root. The P-derive receipt feeds the emitter fixed point, so the v1 chain nests under it. Compute owns the one contract everything else asks for work through — an exact subject in, a typed ending and the outputs it promised back out — and it sits ABOVE CI rather than inside it, because owning CI, converging the fleet, serving models and eventually judging changes are four consumers of one fabric, not four execution systems. It grounds on the signed realization spine rather than minting a second scheduler beside it. CI control owns who starts, queues and hands out required work and how its result reaches GitHub; CI cost owns how much computation that work performs. Fleet owns whether a merge to main becomes applied machine state and whether that question has one answer. Node fields define boundary, first slice, RED control, exclusions, owner, and handback. -**Focused view — the compute fabric + the infrastructure stabilisation lanes + fleet convergence from main.** 107 active deliverable(s) in other lanes are declared in the authority and hidden here; nothing is deleted or parked by focusing. Clear `roadmap_focus_selection` in `dag/gunbc/roadmap_authority.dag` to restore the full page. 6 of the rows below are NOT lane deliverables — they are prerequisites pulled in from other lanes because lane work is blocked on them: observation-scoped-run-consumer, observation-scoped-run-seed-growth-justification, observation-scoped-run-seed-growth-justification-closing-contract, shell-gate-migration, shell-effectplan-to-bash, shell-typed-invocation. Hidden lanes remain readable through their carriers: [docs/plans/dag-scm-design.md](docs/plans/dag-scm-design.md) · [docs/plans/namespace-unique-on-chain-operational-plan.md](docs/plans/namespace-unique-on-chain-operational-plan.md) · [docs/plans/v2-self-hosting.md](docs/plans/v2-self-hosting.md) · [src/v2/compiler/05_emit.dag](src/v2/compiler/05_emit.dag) · [docs/plans/progress-observation-design.md](docs/plans/progress-observation-design.md) · [src/v2/compiler/self_host/candidate_generation.dag](src/v2/compiler/self_host/candidate_generation.dag) · [src/v2/compiler/self_host/frontier.dag](src/v2/compiler/self_host/frontier.dag) · [dag/gunbc/v1_deletion_plan.dag](dag/gunbc/v1_deletion_plan.dag) · [dag/gunbc/stage0_rust_host_observation.dag](dag/gunbc/stage0_rust_host_observation.dag) · [docs/plans/witness-realization-plan.md](docs/plans/witness-realization-plan.md) · [src/v1/05_emit_rust.dag](src/v1/05_emit_rust.dag) · [dag/gunbc/v1_interpreter_primitive_surface.dag](dag/gunbc/v1_interpreter_primitive_surface.dag) · [docs/plans/shell-to-dag-residual-census-and-arc-completion.md](docs/plans/shell-to-dag-residual-census-and-arc-completion.md) · [docs/plans/roadmap-workspace-ux-plan.md](docs/plans/roadmap-workspace-ux-plan.md) · [docs/plans/provider-control-interface-audit.md](docs/plans/provider-control-interface-audit.md) · [docs/plans/enforcement-intent-design.md](docs/plans/enforcement-intent-design.md) · [docs/plans/hermetic-tool-provisioning-design.md](docs/plans/hermetic-tool-provisioning-design.md) · [dag/gunbc/capability_binding.dag](dag/gunbc/capability_binding.dag) · [dag/gunbc/roadmap_component.dag](dag/gunbc/roadmap_component.dag) · [dag/gunbc/design_document.dag](dag/gunbc/design_document.dag) · [docs/plans/compiler-guarantee-recovery-gap-analysis.md](docs/plans/compiler-guarantee-recovery-gap-analysis.md) · [docs/plans/cardinality-refinement.md](docs/plans/cardinality-refinement.md). +**Focused view — the compute fabric + the infrastructure stabilisation lanes + fleet convergence from main.** 107 active deliverable(s) in other lanes are declared in the authority and hidden here; nothing is deleted or parked by focusing. Clear `roadmap_focus_selection` in `dag/gunbc/roadmap_authority.dag` to restore the full page. 6 of the rows below are NOT lane deliverables — they are prerequisites pulled in from other lanes because lane work is blocked on them: observation-scoped-run-consumer, observation-scoped-run-seed-growth-justification, observation-scoped-run-seed-growth-justification-closing-contract, shell-gate-migration, shell-effectplan-to-bash, shell-typed-invocation. Hidden lanes remain readable through their carriers: [docs/plans/dag-scm-design.md](docs/plans/dag-scm-design.md) · [docs/plans/namespace-unique-on-chain-operational-plan.md](docs/plans/namespace-unique-on-chain-operational-plan.md) · [docs/plans/v2-self-hosting.md](docs/plans/v2-self-hosting.md) · [src/v2/compiler/05_emit.dag](src/v2/compiler/05_emit.dag) · [docs/plans/progress-observation-design.md](docs/plans/progress-observation-design.md) · [src/v2/compiler/self_host/candidate_generation.dag](src/v2/compiler/self_host/candidate_generation.dag) · [src/v2/compiler/self_host/wet_receipt_enrollment.dag](src/v2/compiler/self_host/wet_receipt_enrollment.dag) · [src/v2/compiler/self_host/v2_emitter_direct_rust_door_contract.dag](src/v2/compiler/self_host/v2_emitter_direct_rust_door_contract.dag) · [dag/gunbc/v1_deletion_plan.dag](dag/gunbc/v1_deletion_plan.dag) · [dag/gunbc/stage0_rust_host_observation.dag](dag/gunbc/stage0_rust_host_observation.dag) · [docs/plans/witness-realization-plan.md](docs/plans/witness-realization-plan.md) · [src/v1/05_emit_rust.dag](src/v1/05_emit_rust.dag) · [dag/gunbc/v1_interpreter_primitive_surface.dag](dag/gunbc/v1_interpreter_primitive_surface.dag) · [docs/plans/shell-to-dag-residual-census-and-arc-completion.md](docs/plans/shell-to-dag-residual-census-and-arc-completion.md) · [docs/plans/roadmap-workspace-ux-plan.md](docs/plans/roadmap-workspace-ux-plan.md) · [docs/plans/provider-control-interface-audit.md](docs/plans/provider-control-interface-audit.md) · [docs/plans/enforcement-intent-design.md](docs/plans/enforcement-intent-design.md) · [docs/plans/hermetic-tool-provisioning-design.md](docs/plans/hermetic-tool-provisioning-design.md) · [dag/gunbc/capability_binding.dag](dag/gunbc/capability_binding.dag) · [dag/gunbc/roadmap_component.dag](dag/gunbc/roadmap_component.dag) · [dag/gunbc/design_document.dag](dag/gunbc/design_document.dag) · [docs/plans/compiler-guarantee-recovery-gap-analysis.md](docs/plans/compiler-guarantee-recovery-gap-analysis.md) · [docs/plans/cardinality-refinement.md](docs/plans/cardinality-refinement.md). - [ ] **Describe what a command should do, instead of writing shell text** — Callers say which operation and which arguments; nobody hands over an opaque string of shell as the instruction. Why: Shell syntax embedded in decision-making code cannot be checked before it runs, and cannot be reused anywhere else. [authority](docs/plans/shell-to-dag-residual-census-and-arc-completion.md) - [ ] **Turn a described plan into shell through one translator** — One place turns a described plan into a shell script, preserving order, captured output, and failure behaviour. Why: Deletes the per-workflow shell writers and the scripts assembled by gluing strings together. [authority](docs/plans/shell-to-dag-residual-census-and-arc-completion.md) diff --git a/dag/extdeps/languages/rust/types.dag b/dag/extdeps/languages/rust/types.dag index 3dd4b5ee337..385dd2b1a23 100644 --- a/dag/extdeps/languages/rust/types.dag +++ b/dag/extdeps/languages/rust/types.dag @@ -25,11 +25,11 @@ data rust_type_checkpoints: List = [ { dag_name: "Bytes", target_type: "Vec", default_expr: "Vec::new()", is_copy: false, literal_suffix: none }, { dag_name: "Secret", target_type: "String", default_expr: "String::new()", is_copy: false, literal_suffix: ".to_string()" }, { dag_name: "Json", target_type: "serde_json::Value", default_expr: "serde_json::Value::Null", is_copy: false, literal_suffix: none }, - { dag_name: "Hash", target_type: "v1_rt::Hash", default_expr: none, is_copy: false, literal_suffix: ".to_string()" }, - { dag_name: "Witness", target_type: "Witness", default_expr: none, is_copy: false, literal_suffix: none }, - { dag_name: "witness", target_type: "Witness", default_expr: none, is_copy: false, literal_suffix: none } + { dag_name: "Hash", target_type: "v1_rt::Hash", default_expr: none, is_copy: false, literal_suffix: ".to_string()" } ] +data rust_checkpoint_scalar_arity_note: String = "A TypeCheckpoint row states one thing: how a target SPELLS a dag type whose Rust arity is zero. It cannot express arity, so membership of this table IS the emitter's arity-0 claim — v1.compiler.05_emit_rust rust_scalar_checkpoint_render_base reads it, and rust_render_checkpoint_scalar_bare strips every type argument from any leaf it matches (the E0109 wall, rust_checkpoint_scalar_phantom_params_note). Witness/witness rows were removed here 2026-08-16: Witness is the generic enum v2.std.witness.Witness (src/v2/std/witness.dag), arity 1 by its single authority std.types container_type_arity, so the rows made the emitter drop the argument of every Witness in type position and emit `Rc` — rustc E0107 'missing generics for enum Witness', 4 sites in the 06_translate closure alone (docs/probes/root_d_generic_arity_2026-08-16.md). Nothing else was lost with them: coerce_primitive_type renders the bare leaf name 'Witness' through qualified_last_segment either way, and is_copy's Absent arm and Present\{false\} arm are the same decision at every consumer. A generic type may not be added to this table; its spelling is not the missing fact, its arity is." + data rust_algebra_inhabitants: List = [ { algebra: "FreeMonoid", diff --git a/dag/extdeps/ollama/server_env.dag b/dag/extdeps/ollama/server_env.dag new file mode 100644 index 00000000000..240c7e16c36 --- /dev/null +++ b/dag/extdeps/ollama/server_env.dag @@ -0,0 +1,69 @@ +module extdeps.ollama.server_env + +import std.types { NonEmptyStr, String } +import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } +import extdeps.uri { Uri, Https } +import std.decl_ref { DeclarationRef, WholeDeclaration } + +// OLLAMA'S SERVER ENVIRONMENT VARIABLES, WHICH ARE OLLAMA'S NAMES. +// +// `OLLAMA_HOST` and `OLLAMA_MODELS` are part of the dependency's configuration surface. Before this +// module they appeared in the tree exactly once, inside a prose comment, so any consumer needing to +// configure a server had no choice but to spell the literals itself -- and a consumer that spells an +// upstream's identifier is a second authority for it (§3), which is how one typo becomes a server +// that silently binds the wrong address. +// +// The variables are modeled as an assignment-producing surface rather than as bare name constants, +// because the thing a consumer actually needs is `NAME=value` and exposing only the name invites +// every caller to re-implement the joining. + +data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "docs.ollama.com/faq" + } +} + +data extdeps_model_scope: ExternalModelScope = ExternalModelScope { + subject: ExternalSubjectRef { + declaration: DeclarationRef { + module_path: "extdeps.ollama.server_env", + decl_name: "OllamaServerEnvVariable", + field: WholeDeclaration + } + }, + first_citation: extdeps_external_authority_anchor, + further_citations: [] +} + +// A closed set of the variables this repository has grounded against the cited surface. It is +// deliberately small: an unmodeled variable should be absent rather than approximated, so that +// needing one is a visible modeling step and not a string a caller quietly invents. +type OllamaServerEnvVariable + = OllamaHost + | OllamaModels + +fn ollama_server_env_name(variable: OllamaServerEnvVariable) -> NonEmptyStr { + match variable { + OllamaHost => "OLLAMA_HOST" as NonEmptyStr + OllamaModels => "OLLAMA_MODELS" as NonEmptyStr + } +} + +fn ollama_server_env_assignment( + variable: OllamaServerEnvVariable, + value: NonEmptyStr, +) -> NonEmptyStr { + join([ollama_server_env_name(variable: variable) as String, "=", value as String], "") as NonEmptyStr +} + +// The address the server listens on. Ollama binds 127.0.0.1:11434 when this is unset; which address +// a given deployment binds is a deployment fact, so it is a parameter here and never a default. +fn ollama_host_env_assignment(bind: NonEmptyStr) -> NonEmptyStr { + ollama_server_env_assignment(variable: OllamaHost, value: bind) +} + +// Where the server stores and looks for model blobs. +fn ollama_models_env_assignment(root: NonEmptyStr) -> NonEmptyStr { + ollama_server_env_assignment(variable: OllamaModels, value: root) +} diff --git a/dag/extdeps/systemd/unit_file.dag b/dag/extdeps/systemd/unit_file.dag new file mode 100644 index 00000000000..ed6afe0e17a --- /dev/null +++ b/dag/extdeps/systemd/unit_file.dag @@ -0,0 +1,147 @@ +module extdeps.systemd.unit_file + +import std.types { NonEmptyStr, String, List } +import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } +import extdeps.uri { Uri, Https } +import std.decl_ref { DeclarationRef, WholeDeclaration } + +// THE UNIT FILE FORMAT ITSELF, not a unit's runtime state. +// +// `extdeps.systemd` models a unit's observable PROPERTIES (LoadState, ActiveState, MemoryMax) and +// `extdeps.systemd.systemctl` models the manager INVOCATIONS. Neither models the on-disk file, so a +// consumer that needs to WRITE a unit had no authority to render one and would have had to spell +// systemd's INI syntax itself -- a second systemd authority living inside a product module, which is +// exactly the §3 nicknaming this module exists to prevent. +// +// The subject is the unit file format as specified by systemd.unit(5) and systemd.service(5). Those +// are two citations of ONE subject, which is what `further_citations` is for. + +data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "www.freedesktop.org/software/systemd/man/latest/systemd.unit.html" + } +} + +data systemd_service_directive_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "www.freedesktop.org/software/systemd/man/latest/systemd.service.html" + } +} + +data extdeps_model_scope: ExternalModelScope = ExternalModelScope { + subject: ExternalSubjectRef { + declaration: DeclarationRef { + module_path: "extdeps.systemd.unit_file", + decl_name: "SystemdUnitFile", + field: WholeDeclaration + } + }, + first_citation: extdeps_external_authority_anchor, + further_citations: [systemd_service_directive_authority] +} + +// ONE DIRECTIVE TYPE PER SECTION, SO A MISPLACED DIRECTIVE HAS NO REPRESENTATION. +// +// systemd rejects `ExecStart=` in `[Unit]` and `WantedBy=` in `[Service]`, and a renderer carrying one +// flat directive name would make both writable -- caught, at best, by a remote systemd refusing to +// load the file long after it was delivered. Three disjoint types put that class at the top of the +// §4b ladder instead: the invalid file has no constructor, so no validation of section placement is +// needed anywhere downstream. +// +// These are deliberately NOT the full directive vocabulary. systemd specifies hundreds; enumerating +// them speculatively would be a large closed set that is still incomplete, which is worse than a +// small one, because incompleteness in a closed enum reads as "this directive is not permitted" +// rather than "this directive is not modeled yet". Each is a §2-horizontal row: a consumer needing +// `RestartSec=` adds one variant and one wire row, and nothing else changes. + +type SystemdUnitDirective + = Description { text: NonEmptyStr } + | After { target: NonEmptyStr } + | Wants { target: NonEmptyStr } + +type SystemdServiceDirective + = ServiceType { mode: NonEmptyStr } + | ExecStart { command: NonEmptyStr } + | Restart { policy: NonEmptyStr } + | Environment { assignment: NonEmptyStr } + | WorkingDirectory { path: NonEmptyStr } + +type SystemdInstallDirective + = WantedBy { target: NonEmptyStr } + | RequiredBy { target: NonEmptyStr } + +// The directive names are systemd's, spelled once here. A consumer never writes the literal +// "ExecStart"; it constructs `ExecStart { command }` and this module decides how that renders. + +fn systemd_unit_directive_line(directive: SystemdUnitDirective) -> String { + match directive { + Description { text: v } => join(["Description=", v as String], "") + After { target: v } => join(["After=", v as String], "") + Wants { target: v } => join(["Wants=", v as String], "") + } +} + +fn systemd_service_directive_line(directive: SystemdServiceDirective) -> String { + match directive { + ServiceType { mode: v } => join(["Type=", v as String], "") + ExecStart { command: v } => join(["ExecStart=", v as String], "") + Restart { policy: v } => join(["Restart=", v as String], "") + Environment { assignment: v } => join(["Environment=", v as String], "") + WorkingDirectory { path: v } => join(["WorkingDirectory=", v as String], "") + } +} + +fn systemd_install_directive_line(directive: SystemdInstallDirective) -> String { + match directive { + WantedBy { target: v } => join(["WantedBy=", v as String], "") + RequiredBy { target: v } => join(["RequiredBy=", v as String], "") + } +} + +// A unit file is exactly three sections in systemd's order. Modeling it as a record rather than a +// list of (section, directives) pairs means a file with two `[Service]` sections, or with its +// sections transposed, is likewise unwritable rather than merely discouraged. + +type SystemdUnitFile { + unit: List + service: List + install: List +} + +data systemd_unit_section_header: String = "[Unit]" + +data systemd_service_section_header: String = "[Service]" + +data systemd_install_section_header: String = "[Install]" + +// SERIALIZATION IS TOTAL, and every unit file ends with a trailing newline: systemd's parser is +// line-oriented and a final directive without one is the classic silently-truncated last line. +// Because the byte comparison that observes an already-delivered unit compares against exactly this +// output, the trailing newline is load-bearing for convergence and not cosmetic -- a renderer that +// omitted it would diff against every correctly-written file on disk forever. +fn serialize_systemd_unit_file(file: SystemdUnitFile) -> String { + join( + concat( + concat( + concat( + [systemd_unit_section_header], + map(file.unit, d => systemd_unit_directive_line(directive: d)), + ), + concat( + [systemd_service_section_header], + map(file.service, d => systemd_service_directive_line(directive: d)), + ), + ), + concat( + [systemd_install_section_header], + concat( + map(file.install, d => systemd_install_directive_line(directive: d)), + [""], + ), + ), + ), + "\n", + ) +} diff --git a/dag/gunbc/ci_layer_roots.dag b/dag/gunbc/ci_layer_roots.dag index 08e732ca6f7..5de38282b29 100644 --- a/dag/gunbc/ci_layer_roots.dag +++ b/dag/gunbc/ci_layer_roots.dag @@ -561,12 +561,6 @@ data witness_exclusion_frontier: List = [ reason: "the LONG-test home at dir grain (operator 5-second rule). It removes these entries from per-PR discovery and NOTHING MORE: since 2026-08-04 it no longer answers the admission question, because the eval-deadline backstop it was blessed on is disarmed by the very relocation it was supposed to govern (long_lane_exclusion_note carries the retraction and the gunbc#7762 receipt). Admission is decided at identity grain by gunbc.witness_deferral_freeze plus gunbc.explicit_witness_admission", dissolution: unbound_dissolution(description: "the frozen path-deferral population reaches empty — every resident carrying an exact admission with a declared purpose, cost and executing cadence — then this row and the path-policy pass-through arm delete together") }, - WitnessExclusionRow { - pattern: "compiler_frontier_per_module_probe_test.dag", - classification: OfflineLocalRecipe, - reason: "operator-ruled OFFLINE long-lane resident (Lane E closeout): per-module frontier_probe_emit_from_ingest over 27 modules exceeds the 5s fast-lane budget; test/claim/long/ dir grain excludes discovery but this row names the OFFLINE local recipe consumer (compiler_frontier_per_module_probe_exclusion_note)", - dissolution: unbound_dissolution(description: "all 27 roster modules have execution_measurement receipts at one pinned source_head in host_frontier_probe_survey_manifest, frontier.dag rows hand-authored from that manifest, compiler_frontier_per_module_probe_survey_holds greens via the local recipe, totality wall witnesses pass — then row deletes with the probe scaffold dissolution") - }, WitnessExclusionRow { pattern: "no_fake_anomalies_witness_test.dag", classification: FalsifierRehomedBinWet, @@ -892,7 +886,7 @@ fn witness_admission_fixture_exclusion_substrings() -> List { data witness_exclusion_single_authority_reconciliation_note: String = "Single-authority reconciliation (module-identity-storage-binding Phase 0(b) follow-on; the prior note's dissolve-on FIRED 2026-07-22 via the group-of-units ruling): witness_exclusion_frontier is the ONE typed discovery-exclusion roster — every row carries pattern, consumer classification (the std.witness_admission WitnessConsumerCadence authority, no minted twin), reason, and dissolve_on. The former parallel lists witness_admission_offline_exclusion_substrings / witness_admission_fixture_exclusion_substrings are now DERIVED projections (classification filters) — the hand-kept containment alignment they needed is unwritable, so the old one-way-containment witness dissolved with them; v2.test.claim.witness_exclusion_reconciliation_test now witnesses row well-formedness (no DiscoverySelection row; NoConsumer only for the synthetic admission RED-control path; nonempty reason and dissolve_on per row) and explicit-roster consistency (BinWitnessWet / rehomed / substrate-long-lane rows name files the corresponding rosters actually run). As of 2026-08-03 it is a PATH POLICY roster: exact witness admission moved to gunbc.explicit_witness_admission at function grain and a QuarantineProbeExpectRed row here is refused outright, because a substring pattern can only be checked for containment against a schedule row and containment is not identity. whole_tree_resolve_exclusion_substrings stays the ONE concat(witness_exclusion_substrings(), whole_tree_strict_resolve_exclusion_substrings) pattern authority in .dag; the host projection in cli_run.rs parses the frontier rows with the real front-end and must stay list-identical (Rust unit test witness_whole_tree_resolve_exclusion_matches_concat_authority). Strict-walk probe bins consume whole_tree_probe_exclusion_substrings() — pattern rows ∪ host-derived module-path closure (census_exclude_derive) with LiveImporterExclusion receipts; docs/probes/census_extra_excludes.txt is a historical drift witness only (not authority). The roster is enrolled in gunbc.roster_registry as a DeclaredFrontier group. Dissolves when the enforcement-intent registry absorbs the roster or floor admission consumes per-row cost and consumer declarations directly." -data witness_admission_offline_note: String = "Phase 0(b) admission invariant (module-identity-storage-binding): operator-ruled OFFLINE exclusion substrings whose witness rows carry OfflineLocalRecipe consumers — documented local recipes in the paired exclusion notes (wet_integration_offline_note, enforcement_coverage_exclusion_note, accumulator_copy_roster_gate_exclusion_note, identity_captured_navigation_roster_gate_exclusion_note, lever_a_local_receipt_witness_exclusion_note, compiler_frontier_per_module_probe_exclusion_note, long_lane_exclusion_note). Dissolves when each row graduates to a scheduled CI consumer or deletes." +data witness_admission_offline_note: String = "Phase 0(b) admission invariant (module-identity-storage-binding): operator-ruled OFFLINE exclusion substrings whose witness rows carry OfflineLocalRecipe consumers — documented local recipes in the paired exclusion notes (wet_integration_offline_note, enforcement_coverage_exclusion_note, accumulator_copy_roster_gate_exclusion_note, identity_captured_navigation_roster_gate_exclusion_note, lever_a_local_receipt_witness_exclusion_note, long_lane_exclusion_note). Dissolves when each row graduates to a scheduled CI consumer or deletes." data crate_layout_transport_exclusion_note: String = "self_host/crate_layout_witness_test.dag is excluded from hermetic discovery and consumed by v2.workflow.module_binding_supply_transport (run_module_binding_supply_gate, reached from source_root_ingest_gate) — the same posture as its siblings program_assembly/real_ingest_test.dag and self_host/compiler_closure_emit_from_ingest_test.dag, which are transport-run for the same reason. @@ -915,9 +909,8 @@ fn known_red_probe_roster() -> List { ) } -data long_lane_exclusion_note: String = "test/claim/long/ is the LONG-test home (operator 5-second rule, 2026-07-12; authority + enforcement: gunbc_ci_fast_lane_rule_note / gunbc_ci_fast_lane_witness_eval_budget in v2.workflow.ci_floor_plan): a witness whose own eval reaches 5s does not run in per-PR discovery — the executor's cooperative eval deadline REDs it by name (EvalBudgetExceeded), and the fix is moving its file here (dag/test/claim/long/, src/v2/test/claim/long/), where discovery excludes it at dir grain and it runs via the local recipe (claim_batch --source-root dag --source-root src/v2 --entry --functions ) or the scheduled lane's future enrollment. First residents (receipted): s1_closure_receipt_test (whole-closure re-parse through the interpreted v2 frontend, 90+min eval, the run-29183446733 wedge class) and self_host_module_emit_derisk_test (~31s/witness). Named consumer with file-grain exclusion row: compiler_frontier_per_module_probe_test.dag (compiler_frontier_per_module_probe_exclusion_note). Membership here was called a HOME rather than a per-file ruling on the ground that the 5s deadline makes an over-budget fast-lane witness unwritable-in-place, so the roster could not silently grow stale. THAT SENTENCE WAS FALSE AND IS RETRACTED (2026-08-04). The deadline is evaluated only while a witness RUNS; relocating its file under this prefix is precisely what stops it running, so the claimed construction backstop is disarmed by the exact move it was supposed to govern, and the home grew by whatever anyone moved into it. BudgetExceeded is an interruption plus a measured lower bound on cost — never a semantic verdict on a witness, and never a discharge of one by causing its relocation. Receipt: gunbc#7762 commit 0cfd199f8, thirteen witnesses relocated here under the title fix CI fast-lane budget failures with a claim_batch command line as their only stated consumer and no cadence row. WHAT NOW HOLDS THE LINE: this prefix still organizes the files, but it no longer answers the admission question. gunbc.witness_deferral_freeze enumerates the exact legacy identities path policy had already admitted, and any offline-classified witness outside that frozen set and outside gunbc.explicit_witness_admission refuses as UnclassifiedPathDeferral, while a frozen row the tree no longer carries refuses as StaleFrozenPathDeferral. Dissolve-on: the freeze reaching empty — every resident carrying an exact admission with a declared purpose, cost and executing cadence — at which point the pass-through arm and this dir row delete together." +data long_lane_exclusion_note: String = "test/claim/long/ is the LONG-test home (operator 5-second rule, 2026-07-12; authority + enforcement: gunbc_ci_fast_lane_rule_note / gunbc_ci_fast_lane_witness_eval_budget in v2.workflow.ci_floor_plan): a witness whose own eval reaches 5s does not run in per-PR discovery — the executor's cooperative eval deadline REDs it by name (EvalBudgetExceeded), and the fix is moving its file here (dag/test/claim/long/, src/v2/test/claim/long/), where discovery excludes it at dir grain and it runs via the local recipe (claim_batch --source-root dag --source-root src/v2 --entry --functions ) or the scheduled lane's future enrollment. First residents (receipted): s1_closure_receipt_test (whole-closure re-parse through the interpreted v2 frontend, 90+min eval, the run-29183446733 wedge class) and self_host_module_emit_derisk_test (~31s/witness). Membership here was called a HOME rather than a per-file ruling on the ground that the 5s deadline makes an over-budget fast-lane witness unwritable-in-place, so the roster could not silently grow stale. THAT SENTENCE WAS FALSE AND IS RETRACTED (2026-08-04). The deadline is evaluated only while a witness RUNS; relocating its file under this prefix is precisely what stops it running, so the claimed construction backstop is disarmed by the exact move it was supposed to govern, and the home grew by whatever anyone moved into it. BudgetExceeded is an interruption plus a measured lower bound on cost — never a semantic verdict on a witness, and never a discharge of one by causing its relocation. Receipt: gunbc#7762 commit 0cfd199f8, thirteen witnesses relocated here under the title fix CI fast-lane budget failures with a claim_batch command line as their only stated consumer and no cadence row. WHAT NOW HOLDS THE LINE: this prefix still organizes the files, but it no longer answers the admission question. gunbc.witness_deferral_freeze enumerates the exact legacy identities path policy had already admitted, and any offline-classified witness outside that frozen set and outside gunbc.explicit_witness_admission refuses as UnclassifiedPathDeferral, while a frozen row the tree no longer carries refuses as StaleFrozenPathDeferral. Dissolve-on: the freeze reaching empty — every resident carrying an exact admission with a declared purpose, cost and executing cadence — at which point the pass-through arm and this dir row delete together." -data compiler_frontier_per_module_probe_exclusion_note: String = "src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag is operator-ruled OFFLINE (Lane 1 exact-head closeout): fixture-free per-module frontier_probe_emit_from_ingest receipts over all 27 compiler modules exceed the 5s per-PR fast-lane eval budget; discovery excludes via test/claim/long/ dir grain and per-PR CI never executes these witnesses — green CI says nothing about execution_measurement counts unless the local recipe below ran at a pinned FrontierSurveySubject. LOCAL RECIPE (authority): (1) predecessors #7776, #7762, and #7767 are merged; authoritative 27/27 remains on operator hold; (2) from a clean detached worktree at the selected commit, cargo build --release -p v1-compiler --bin frontier_probe_survey — WRAP IT AS ctrl-build --local, which is REQUIRED and not a preference: ctrl-build defaults to CTRL_BUILD_MODE=remote in session containers and BuildBuddy refuses a detached worktree ('remote config: get base branch and commit: unexpected branch state * (no branch)'), so step (2)'s mandated DETACHED worktree and the default remote build path are mutually exclusive and anyone following this recipe verbatim hits it first (measured tidy-bee-50 2026-08-06); (3) primary: target/release/frontier_probe_survey with every --source-root via v2.workflow.frontier_probe_survey_transport survey_manifest_emit_args (one-shot over compiler_frontier_sweep_order at one subject; OOM fallback: docs/probes/run_frontier_probe_survey_per_module.sh — TSV wire carries rejection_chain and overlap_roster_detail projections, not full detail/assemble_detail variant AST on manifest-only round-trip; every shard carries complete FrontierSurveySubject, all 27 subjects must compare exactly equal); (4) emit host_frontier_probe_survey_manifest FrontierSurveyManifest to target/frontier-probe-survey/; (5) claim_batch --source-root src/v2 --source-root dag --source-root target/frontier-probe-survey --entry src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag --functions compiler_frontier_per_module_probe_survey_holds,compiler_frontier_gap_clustering_common_root_at_blocker_class_holds,compiler_frontier_wave2_blocker_partition_totality_holds,compiler_frontier_roster_bidirectional_totality_live_survey_holds,compiler_frontier_receipt_totality_wall_live_survey_holds,compiler_frontier_wave2_emit_surface_dominates_holds,compiler_frontier_wave2_sizing_band_a_leaf_count_holds. RUNS INTERRUPTED, not only held: step (3) has not yet produced a receipt for ANY module — six probe invocations were SIGKILLed with zero receipts, on both the primary one-shot and the per-module path. The CAUSE IS OPEN and is NOT a demonstrated capacity limit: the cgroup never reached its own cap (memory.events max 0, oom 0; memory.peak 8.5 GiB against a 31.3 GiB memory.max), so the kills came from outside it and probe memory cost is UNMEASURED rather than high. 'Unreachable' is NOT established — treat this recipe as interrupted and retryable, and per operator ruling retry it in a fresh job or runner whose real kill boundary is observable rather than trimming the probe to fit. Authority for the measurements and the withdrawn earlier claims is v2.compiler.self_host.frontier_probe_survey frontier_probe_run_interruption_note, which this clause must not restate beyond pointing at it. Dissolve-on: execution_measurement=27 at one pinned FrontierSurveySubject, frontier.dag rows hand-authored from manifest, totality wall witnesses pass via this recipe — then this note, the file-grain exclusion row, and the probe scaffold delete together." data wet_integration_offline_note: String = "Four wet-integration entries above (host_effect_apply, deploy_access_privilege, ci_deploy_observed_wet, random_bytes_csprng) are OFFLINE per the hermetic-floor posture (operator 2026-07-11: integration-style witnesses must not run regularly; CI runs hermetic/mocked behavior checks). Each performs genuinely live host effects the hermetic envelope refuses by construction: host_effect_apply drives real LocalShell/SSH host effects (the 133s row atop the slow-witness census), deploy_access_privilege applies privileged shell mutations through fixture actors, ci_deploy_observed_wet shells whoami + sudo -n, random_bytes_csprng reads host entropy. Hermetic duals stay discovered where they exist (the ci_deploy split keeps the pure half; deploy_access_check(access, actor) is the mock-shaped dual). Local recipe: claim_batch --wet --source-root dag --source-root src/v2 --entry per file. Dissolve-on: the scheduled (nightly) lane un-darkens and admits wet integration rows under its own budget — then these four enroll there as declared execution rows and the exclusion rows delete." @@ -927,7 +920,7 @@ data bin_witness_wet_note: String = "The remaining excluded entries are the BIN- data bin_witness_wet_per_row_actions_log_observation_gap_note: String = "CLOSED (measured 2026-08-06, Lane D / still-bat-561): main push run 31060353614 job 92492124511 (post-#7857 instrumentation) discriminates the four collapsed states. Batch 4 `bin-witness-corpus` PASS (146 witnesses); worker wrote `target/floor-wet-witness-row-outcome-receipt.tsv` with 192 rows; coordinator replayed 192 `[wet-witness-row-outcome]` lines; post-step dumps TSV + phase journal; `live_rust_observation_matches_actions_subject` row shows `outcome=passed` (batch=4). Prior zero-row reads conflated the regen job's legitimate 0-row receipt (no wet discovery batches) with the per-PR ci worker — observation collapse, not batch-not-reached or transport failure. HISTORY: COUNTED OBSERVATION GAP opened 2026-08-02 (#7698 run 30765850510); mechanism landed #7698 worker receipt + coordinator replay; scheduling proof #7857; observation extension #7857 labels + journal persistence + post-step dump." -data falsifier_self_host_wet_note: String = "The nightly falsifier Wet follow-on batch (gunbc_falsifier_batches batch 2 in v2.workflow.ci_floor_plan): explicit ExecutionWitnessKind rows whose fns realize the emit->compile->run->equals-seed self-host behavioral receipt chain (cargo build, process execution, real gunbc emit) — too heavy and fidelity-sensitive for per-PR hermetic discovery. Gate-4 std/logic (self_host_logic_behavioral_witness_test.dag) is the inaugural template migrated out of bin_witness_wet_entries; compiler modules enroll via v2.compiler.self_host.wet_receipt_enrollment when their frontier row flips SelfEmitted (green-only — never known-red). Runs SelectionApplied (always run, not predict-only) after the hermetic affected-set falsifier sweep. Local recipe: claim_batch --wet --source-root dag --source-root src/v2 --entry --functions . Dissolve-on: per-module self-host receipts graduate to continuous CI only when the emit-on-demand / self-host cutover lane proves each module's receipt is cheap enough for per-PR admission — until then this scheduled lane is the sole live consumer." +data falsifier_self_host_wet_note: String = "The nightly falsifier Wet follow-on batch (gunbc_falsifier_batches batch 2 in v2.workflow.ci_floor_plan): explicit ExecutionWitnessKind rows whose fns realize the emit->compile->run->equals-seed self-host behavioral receipt chain (cargo build, process execution, real gunbc emit) — too heavy and fidelity-sensitive for per-PR hermetic discovery. Gate-4 std/logic (self_host_logic_behavioral_witness_test.dag) is the inaugural template migrated out of bin_witness_wet_entries; compiler modules enroll via v2.compiler.self_host.wet_receipt_enrollment through a SelfHostWetReceiptBinding (green-only — never known-red); the frontier-row flip that formerly gated that enrollment is gone with the self-host frontier roster, and the term it fed was already empty when it was deleted (wet_enrollment_roster_term_deleted_note), so the lane ran on template entries alone before and after. Runs SelectionApplied (always run, not predict-only) after the hermetic affected-set falsifier sweep. Local recipe: claim_batch --wet --source-root dag --source-root src/v2 --entry --functions . Dissolve-on: per-module self-host receipts graduate to continuous CI only when the emit-on-demand / self-host cutover lane proves each module's receipt is cheap enough for per-PR admission — until then this scheduled lane is the sole live consumer." // The R1 dark-lane status note JOINS two authorities — this module's waiting-pattern // projection and v2.compiler.self_host.wet_receipt_enrollment's cadence/enrollment facts — diff --git a/dag/gunbc/ci_release_bins.dag b/dag/gunbc/ci_release_bins.dag index c12d8f60737..22078d7fe59 100644 --- a/dag/gunbc/ci_release_bins.dag +++ b/dag/gunbc/ci_release_bins.dag @@ -14,10 +14,14 @@ data ci_release_bins_authority_note: String = "Single authority for the CI relea ci_floor_required_artifact_names() is DERIVED (floor ∪ witness-declared, stable order, no dupes). The old hand List in gunbc.ci_spec is deleted. Construction half in tools.host_prelude: witness_bin_ensure_built_typed refuses WitnessBinNotEnrolled for a bin_name absent from the derived pack — it does NOT cargo-build an unenrolled name (the mid-floor cold-monolith absorption the job split exists to bound). Intentionally-absent negative control no_such_witness_bin_zzz stays OFF this list. -Measured gap that priced this PR (2026-07-26): cssl_assemble and frontier_probe_survey were addressed by production transports but absent from the pack — live absorption risk. cssl_assemble enrolls below. frontier_probe_survey remains enrolled. +Measured gap that priced this PR (2026-07-26): cssl_assemble and frontier_probe_survey were addressed by production transports but absent from the pack — live absorption risk. cssl_assemble enrolls below. frontier_probe_survey was enrolled here and is removed by the roster cut — see the second-removal paragraph below. CORRECTION (2026-08-15, cli-run cut). An earlier revision of this row DELETED four bins — frontier_probe_survey, discover_source_root_ingest, effects_rest_transport_witness and resolution_divergence_census — and justified all four with one sentence: 'every one of them was a probe bin whose only subject was src/v1/stage0/src/cli_run.rs'. That sentence was asserted once and never checked per bin, and it is FALSE FOR ALL FOUR. All four are restored. +SECOND REMOVAL OF frontier_probe_survey (self-host frontier roster cut), justified per bin rather than by a class sentence, because the correction above is exactly the mistake to avoid repeating. This one is not a probe bin whose subject was cli_run, which is what that sentence claimed of all four. Its subject was the 27-row self-host frontier roster, which is deleted in this change: the bin read compiler_frontier_sweep_order from frontier.dag at runtime to decide which modules to survey, and its own Cargo comment stated that census as its checkable receipt (before=27 from compiler_frontier_roster_count). With the roster gone the bin has no module census to read and no receipt to produce. Its .dag surface (v2.compiler.self_host.frontier_probe_survey) and its host transport (v2.workflow.frontier_probe_survey_transport) are deleted in the same change, so nothing remains that could invoke it. + +The independent fact that made the removal easy rather than merely consistent: the harness produces no receipts on any host and has not since at least 2026-08-06 — six invocations six kills on a shared host, a silent death after ~27 minutes on a dedicated BuildBuddy runner with the module filter narrowed to one small module, and a kernel OOM elsewhere the same day. Packing a binary that cannot complete a run is not coverage. If a per-module emit survey is wanted again it is authored against whatever replaces the roster, not restored from this bin. + The distinction it collapsed is the load-bearing one. USING AN ENGINE IS NOT THE SAME RELATION AS PROBING A DRIVER. Each of these bins imports engine functions out of cli_run — resolve_entry_graph, workspace_root, discover_source_root_reads, collect_rest_transport_operations, project_resolution_divergence_census and their neighbours — while its SUBJECT is something else entirely: the v2 self-host frontier survey, source-root ingest discovery, declared REST transport operations, the namespace-resolution §12.4 divergence census. The cli-run cut deletes the DRIVER and retains the ENGINE frozen in place, so every symbol these four import survives it (measured: twelve of twelve). A cut that removes a driver has no claim on a consumer of the engine, and 'imports from cli_run' is not evidence of subjecthood — it is evidence the engine had no other home, which is the thing this cut is about rather than a reason to delete its callers. What made the error invisible was that nothing on this branch objected. Their surviving invokers are transports, not compile-time references, so the crate still built; the two witnesses that would have redded the roster change are deleted by a sibling lane, so CI would have been green on loan. The check that found it was a one-command sweep of the deleted bin names across dag/, src/v2/ and .github/, which turned up five live structural invocation sites — three production transports for discover_source_root_ingest alone, plus fleet-converge pack lines for all four. A deletion census trained on who DEFINES a thing must also ask who CALLS it. @@ -47,7 +51,6 @@ data witness_declared_release_bins: List = [ "parse_witness", "resolution_divergence_census", "cssl_assemble", - "frontier_probe_survey", "namespace_structural_root_exposure_generated_witness" ] diff --git a/dag/gunbc/dissolution_migration_census.dag b/dag/gunbc/dissolution_migration_census.dag index 1950f2cfaee..e63e8bd0a01 100644 --- a/dag/gunbc/dissolution_migration_census.dag +++ b/dag/gunbc/dissolution_migration_census.dag @@ -112,7 +112,6 @@ fn narrative_only_rows() -> List { residue_row(module_path: "gunbc.live_deploy.spec", decl_name: "blue_green_retirement_stateful_root_scaffold_note", class: NarrativeOnly, rationale: "rationale only; its lifecycle condition was extracted to blue_green_retirement_stateful_root_scaffold_dissolve_on"), residue_row(module_path: "test.claim.long.reference_closure_equivalence", decl_name: "conformance_import_envelope_dissolution_note", class: NarrativeOnly, rationale: "rationale only; its lifecycle condition was extracted to conformance_import_envelope_dissolve_on"), residue_row(module_path: "v2.lens.cost.copied_port_citations", decl_name: "copied_port_citation_frontier_dissolution_note", class: NarrativeOnly, rationale: "rationale only; its lifecycle condition was extracted to copied_port_citation_frontier_dissolve_on"), - residue_row(module_path: "v2.compiler.self_host.frontier_probe_survey", decl_name: "frontier_probe_survey_dissolution_note", class: NarrativeOnly, rationale: "rationale only; its lifecycle condition was extracted to frontier_probe_survey_dissolve_on"), residue_row(module_path: "v2.lens.enforcement.lens_module_gate", decl_name: "lens_module_gate_surface_table_dissolution_note", class: NarrativeOnly, rationale: "rationale only; its lifecycle condition was extracted to lens_module_gate_surface_table_dissolve_on"), residue_row(module_path: "std.occurrence_binding_candidates", decl_name: "module_path_file_row_dissolution_note", class: NarrativeOnly, rationale: "rationale only; its lifecycle condition was extracted to module_path_file_row_dissolve_on"), residue_row(module_path: "v2.lens.reference_deps", decl_name: "reference_deps_dissolution_note", class: NarrativeOnly, rationale: "rationale only; its lifecycle condition was extracted to reference_deps_dissolve_on"), diff --git a/dag/gunbc/doc_graph_roots.dag b/dag/gunbc/doc_graph_roots.dag index c6ee4449641..7b3ff6a7912 100644 --- a/dag/gunbc/doc_graph_roots.dag +++ b/dag/gunbc/doc_graph_roots.dag @@ -1138,13 +1138,6 @@ data hand_authored_doc_binds: List = [ additional_works: [], dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "dissolves with the emitter residual classes it maps (dotted-alias #6981, generic-T fold closures)") }, }, - HandAuthoredDocBind { - home: ProbeDoc, - slug: "root_b_primitive_repr_fork_2026-08-16", - primary_work: DeclarationRef { module_path: "v1.compiler.infer", decl_name: "rust_corpus_repr", field: WholeDeclaration }, - additional_works: [], - dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "the primitive representation stops being selected from a single corpus-wide Boolean and is derived per declaration, so this probe's measurement of the fork describes a shape the compiler no longer has") }, - }, HandAuthoredDocBind { home: ProbeDoc, slug: "gate1_repr_mismatch_e0308_diagnosis_2026-07-23", @@ -1166,6 +1159,13 @@ data hand_authored_doc_binds: List = [ additional_works: [], dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "Slice A Clone-bound propagation lands in v1 trait_derive_emit (where-clause + container bounds) and canonical-seven E0599 census reaches tails-only; or doc migrates into a registered gunbc.plan.Plan row") }, }, + HandAuthoredDocBind { + home: ProbeDoc, + slug: "root_d_generic_arity_2026-08-16", + primary_work: DeclarationRef { module_path: "v1.compiler.emit_rust", decl_name: "rust_render_checkpoint_scalar_bare", field: WholeDeclaration }, + additional_works: [DeclarationRef { module_path: "extdeps.languages.rust.types", decl_name: "rust_type_checkpoints", field: WholeDeclaration }], + dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "lookup_checkpoint stops being keyed on the bare authored leaf name — the arity half is closed by the declared-arity guard this probe measures, and the remaining identity half (7 of 10 rust_type_checkpoints rows name a type src/v2 also declares) is the identity-keyed realization work; when the table is keyed on resolved declaration identity, both halves this probe localises are structurally unreachable and the probe deletes with this row") }, + }, HandAuthoredDocBind { home: PlanDoc, slug: "e0599-implementation-proposal", @@ -1222,20 +1222,6 @@ data hand_authored_doc_binds: List = [ additional_works: [], dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "the structural declaration-container overlay predicate is consumed by a self-emitted emitter and the before/after receipt is absorbed into the Gate-1 behavioral fixed-point carrier; then this probe bind deletes with the md") }, }, - HandAuthoredDocBind { - home: ProbeDoc, - slug: "frontier_probe_exact_head_survey_2026-08-03", - primary_work: DeclarationRef { module_path: "v2.compiler.self_host.frontier_probe_survey", decl_name: "frontier_probe_exact_head_closeout_note", field: WholeDeclaration }, - additional_works: [DeclarationRef { module_path: "v2.compiler.self_host.frontier", decl_name: "compiler_frontier_receipt_totality_wall_holds", field: WholeDeclaration }], - dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "execution_measurement=27 at one pinned source_head in host_frontier_probe_survey_manifest, frontier.dag rows hand-authored from that manifest, compiler_frontier_per_module_probe_survey_holds greens, and totality wall witnesses pass — then this interim audit receipt deletes with this row") }, - }, - HandAuthoredDocBind { - home: ProbeDoc, - slug: "frontier_probe_run_interrupted_2026-08-06", - primary_work: DeclarationRef { module_path: "v2.compiler.self_host.frontier_probe_survey", decl_name: "frontier_probe_run_interruption_note", field: WholeDeclaration }, - additional_works: [DeclarationRef { module_path: "v2.compiler.self_host.frontier_probe_survey", decl_name: "frontier_roster_provenance_constructor_inflation_note", field: WholeDeclaration }], - dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "the probe emits a receipt for at least one module at a pinned FrontierSurveySubject and roster row provenance becomes structural — then this interrupted-run receipt deletes with this row") }, - }, HandAuthoredDocBind { home: ProbeDoc, slug: "srv2-05-native-agreement-divergence-diagnosis", @@ -1247,7 +1233,13 @@ data hand_authored_doc_binds: List = [ home: PlanDoc, slug: "rc-ownership-wrap-decision-design", primary_work: DeclarationRef { module_path: "v2.compiler.wrap_decision", decl_name: "WrapDecisionBundleChildLookup", field: WholeDeclaration }, - additional_works: [], + additional_works: [ + DeclarationRef { module_path: "v1.compiler.emit_rust", decl_name: "build_shared_types", field: WholeDeclaration }, + DeclarationRef { module_path: "v1.compiler.emit_rust", decl_name: "render_rust_shared_type_if_needed", field: WholeDeclaration }, + DeclarationRef { module_path: "v1.compiler.emit_rust", decl_name: "render_rust_fn_sig_type", field: WholeDeclaration }, + DeclarationRef { module_path: "v1.compiler.emit_rust", decl_name: "emit_struct_field_from_child", field: WholeDeclaration }, + DeclarationRef { module_path: "v1.compiler.emit", decl_name: "render_node_type", field: WholeDeclaration }, + ], dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "doc migrates into a registered gunbc.plan.Plan row (the registration becomes the binding)") }, }, HandAuthoredDocBind { @@ -1543,10 +1535,9 @@ data hand_authored_doc_binds: List = [ HandAuthoredDocBind { home: PlanDoc, slug: "self-host-cargo-refusal-root-partition", - primary_work: DeclarationRef { module_path: "v2.compiler.self_host.frontier_band_a_emit_readiness", decl_name: "compiler_frontier_band_a_emit_readiness_note", field: WholeDeclaration }, + primary_work: DeclarationRef { module_path: "v2.compiler.self_host.v2_emitter_direct_rust_door_contract", decl_name: "v2_emitter_direct_rust_door_contract_dissolution_note", field: WholeDeclaration }, additional_works: [ DeclarationRef { module_path: "v2.compiler.infer", decl_name: "node_grounding_frontier_note", field: WholeDeclaration }, - DeclarationRef { module_path: "v2.compiler.self_host.v2_emitter_direct_rust_door_contract", decl_name: "v2_emitter_direct_rust_door_contract_dissolution_note", field: WholeDeclaration }, ], dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "the root partition this document coordinates is confirmed, its roots are owned, and the emitted Rust compiles for at least one module — at which point the wall it describes is history and the document deletes with this bind. Registered at subject grain: the bound declarations are the three carriers whose movement would make this document's framing false — the Band A readiness note that routes the blocker to the namespace cut, the inference frontier note whose counted-not-refused status is the correction this document records, and the direct-door dissolution note that says emission is already reached. It is a shared coordination surface for two sessions rather than an authority, which is why every claim in it names its measurement and the unconfirmed hypotheses are labelled as such; a coordination narrative that outlived its lanes would be the parallel-ledger shape DESIGN section 6 warns about.") }, }, diff --git a/dag/gunbc/extdeps_scope_frontier.dag b/dag/gunbc/extdeps_scope_frontier.dag index 28e2a4ad689..200cffa8fa0 100644 --- a/dag/gunbc/extdeps_scope_frontier.dag +++ b/dag/gunbc/extdeps_scope_frontier.dag @@ -170,6 +170,7 @@ data scope_carrier_paths: List = [ "dag/extdeps/ollama/binary_release.dag", "dag/extdeps/ollama/capability.dag", "dag/extdeps/ollama/gpu_support.dag", + "dag/extdeps/ollama/server_env.dag", "dag/extdeps/automation/playwright.dag", "dag/extdeps/package.dag", "dag/extdeps/npm.dag", @@ -245,6 +246,7 @@ data scope_carrier_paths: List = [ "dag/extdeps/vendor/navepoint.dag", "dag/extdeps/vendor/rosewill.dag", "dag/extdeps/vendor/tp_link.dag", + "dag/extdeps/systemd/unit_file.dag", "dag/extdeps/systems/nvidia.dag", "dag/extdeps/systems/nvidia_dgx_spark_pxe.dag", "dag/extdeps/systems/nvidia_fleet_lifecycle.dag", diff --git a/dag/gunbc/fleet_multi_principal_probe.dag b/dag/gunbc/fleet_multi_principal_probe.dag index 38a19b54060..ab62126079e 100644 --- a/dag/gunbc/fleet_multi_principal_probe.dag +++ b/dag/gunbc/fleet_multi_principal_probe.dag @@ -29,6 +29,9 @@ import gunbc.fleet_ssh_credential_verify { FleetSshCredentialIdentityMismatch, FleetSshCredentialDerivationRefused, verify_fleet_ssh_agent_credential, + materialize_agent_public_selector, + AgentSelectorMaterialized, + AgentSelectorRefused, fleet_ssh_credential_verification_refusal_reason, } import extdeps.ssh.session { ssh_session_exec_portable_words } @@ -194,7 +197,6 @@ fn probe_agent_socket() -> NonEmptyStr? { // The public key file that selects the fleet identity out of the agent. Not a secret, and not what // authenticates -- see `openssh_exact_agent_credential_options`. It is named here so the binding this // probe verifies is the same binding an exact transport would carry. -data probe_agent_public_selector_file: NonEmptyStr = "/tmp/gunbc-fleet-automation-selector.pub" // The verification, replacing `modeled_fleet_automation_credential_identity`. That function hashed // the DECLARED material and stamped it onto every `PrincipalReachObservation`, so the receipt's @@ -202,7 +204,7 @@ data probe_agent_public_selector_file: NonEmptyStr = "/tmp/gunbc-fleet-automatio // the same defect `gunbc.fleet_ssh_credential_verify` closed on the identity-file route, present a // second time on this one. The identity now comes from a binding that exists only because the agent // was observed to hold the declared fingerprint. -func probe_agent_credential_verification() -> FleetSshCredentialVerification +func probe_agent_credential_verification(attempt: FleetSshAttemptIdentity) -> FleetSshCredentialVerification uses net: Network { match probe_agent_socket() { @@ -211,12 +213,16 @@ func probe_agent_credential_verification() -> FleetSshCredentialVerification cause: "SSH_AUTH_SOCK is unset or empty: this run has no named agent to verify the fleet credential against", } Present { value: sock } => - verify_fleet_ssh_agent_credential( - agent_socket: sock, - public_selector_file: probe_agent_public_selector_file, - expected_key: fleet_automation_ssh_key, - expected_fingerprint: fleet_automation_ssh_key_fingerprint as NonEmptyStr, - ) + match materialize_agent_public_selector(attempt: attempt, key: fleet_automation_ssh_key) { + AgentSelectorRefused { cause: cause } => FleetSshCredentialDerivationRefused { cause: cause } + AgentSelectorMaterialized { selector: selector } => + verify_fleet_ssh_agent_credential( + agent_socket: sock, + selector: selector, + expected_key: fleet_automation_ssh_key, + expected_fingerprint: fleet_automation_ssh_key_fingerprint as NonEmptyStr, + ) + } } } @@ -629,7 +635,23 @@ fn spark_standing_unobserved_host(standings: List) - // ONE derivation, read twice: the receipt renders the standings and the exit folds the same values. // Deriving them a second time for the exit would let the two disagree (review 51710). func spark_managed_access_standing_with_attempt(attempt_raw: String) -> ProcessExit { - match probe_agent_credential_verification() { + match probe_attempt_identity(raw: attempt_raw) { + Absent => + exit_failure(reason: "spark managed-access standing refused before any observation: attempt identity is not a safe path segment, so the agent selector has no attempt-owned path to be materialized at") + Present { value: attempt } => + spark_managed_access_standing_for_attempt(attempt_raw: attempt_raw, attempt: attempt) + } +} + +// The credential gate, split out so the attempt-identity match above has one expression per arm +// rather than a nested match indented back to the outer column (review 52733). +func spark_managed_access_standing_for_attempt( + attempt_raw: String, + attempt: FleetSshAttemptIdentity, +) -> ProcessExit + uses net: Network +{ + match probe_agent_credential_verification(attempt: attempt) { FleetSshCredentialIdentityMismatch { expected_line: expected, observed_line: observed } => exit_failure( reason: fleet_ssh_credential_verification_refusal_reason( diff --git a/dag/gunbc/fleet_ssh_credential_verify.dag b/dag/gunbc/fleet_ssh_credential_verify.dag index aa3ab0948c0..4a71322f61e 100644 --- a/dag/gunbc/fleet_ssh_credential_verify.dag +++ b/dag/gunbc/fleet_ssh_credential_verify.dag @@ -4,9 +4,20 @@ import std.types { Bool, NonEmptyStr, String } import std.resources { Network } import std.algebra { trim } import extdeps.exec.command { ArgvCommand, LocalExec } -import extdeps.ssh { SshPublicKey, ssh_key_algorithm_token } +import extdeps.ssh { SshPublicKey, ssh_key_algorithm_token, ssh_public_key_line } +import std.decl_ref { decl_ref } +import extdeps.filesystem.filesystem_io { Filesystem } +import std.content_hash { + ContentHash, + content_hash_of_value, + compare_content_hash, + ContentHashEqual, + ContentHashDifferent, + ContentHashCrossFamilyIncomparable, +} import gunbc.command_runner { ShellCaptureResult, run_shell_command_capture } import gunbc.fleet_known_hosts_anchor { + FleetSshAttemptIdentity, FleetSshCredentialBinding, fleet_ssh_credential_binding_of_derived_material, fleet_ssh_agent_credential_binding_of_listed_key, @@ -113,6 +124,101 @@ func verify_fleet_ssh_credential( ) } +// ── The agent selector file ───────────────────────────────────────────────────────────────────── +// +// THE FILE THAT SELECTS ONE IDENTITY OUT OF THE AGENT, materialized and read back rather than named. +// +// This closes a gap the agent arm shipped with: `public_selector_file` was a path a caller passed in, +// and nothing established that anything was at it. With `IdentitiesOnly=yes` that file is what makes +// a success evidence about the modeled key, so a path naming a file that does not exist -- or a file +// holding a DIFFERENT public key -- silently removes the exactness the option set was chosen for. A +// path string is not a selector; the bytes are. +// +// Same construction as `KnownHostsAnchor` and for the same reason: write, read back, compare content +// identities, and seal only on agreement. `AgentSelectorFile` is `sole_constructor` with one mint, so +// a literal path cannot reach `classify_agent_key_listing` at all -- the only way to hold one is to +// have materialized it. +// +// The contents are PUBLIC. This file never carries a private key; the private half stays in the agent +// and is never written anywhere by this module. +type AgentSelectorFile sole_constructor { + path: NonEmptyStr + selector_identity: ContentHash +} + +fn agent_selector_file_seal(path: NonEmptyStr, selector_identity: ContentHash) -> AgentSelectorFile + admit_callers: [ + decl_ref(module_path: "gunbc.fleet_ssh_credential_verify", decl_name: "materialize_agent_public_selector"), + decl_ref(module_path: "test.claim.fleet_ssh_credential_verify_witness_test", decl_name: "witness_selector_fixture"), + ] + = AgentSelectorFile { path: path, selector_identity: selector_identity } + +type AgentSelectorMaterialization = + AgentSelectorMaterialized { selector: AgentSelectorFile } + | AgentSelectorRefused { cause: String } + +// Attempt-owned, exactly as the anchor path is: two concurrent runs must not write one another's +// selector, and a stale file from another attempt must never be readable as this one's. +fn agent_public_selector_path(attempt: FleetSshAttemptIdentity) -> NonEmptyStr { + join(["target/fleet-ssh-attempt-", attempt as String, "-selector.pub"], "") as NonEmptyStr +} + +// The authorized_keys line form, which is what OpenSSH expects in a public key file, with the +// trailing newline a well-formed file carries. +fn agent_public_selector_content(key: SshPublicKey) -> String { + concat(ssh_public_key_line(k: key), "\n") +} + +func materialize_agent_public_selector( + attempt: FleetSshAttemptIdentity, + key: SshPublicKey, +) -> AgentSelectorMaterialization + uses net: Network +{ + let path = agent_public_selector_path(attempt: attempt) + let content = agent_public_selector_content(key: key) + let expected_identity = content_hash_of_value(value: content as NonEmptyStr) + let existing = Filesystem.Read(path: path as String) + let already = existing.success && existing.content == content + let written = if already { true } else { Filesystem.Write(path: path as String, content: content).success } + if !written { + AgentSelectorRefused { + cause: join(["agent selector materialization refused: could not write ", path as String], ""), + } + } else { + let back = Filesystem.Read(path: path as String) + if !back.success { + AgentSelectorRefused { + cause: join([ + "agent selector materialization refused: readback of ", path as String, " failed -- ", + trim(s: back.error), + ], ""), + } + } else { + match compare_content_hash( + left: expected_identity, + right: content_hash_of_value(value: back.content as NonEmptyStr), + ) { + ContentHashEqual => + AgentSelectorMaterialized { + selector: agent_selector_file_seal(path: path, selector_identity: expected_identity), + } + ContentHashDifferent => + AgentSelectorRefused { + cause: join([ + "agent selector materialization refused: the bytes read back from ", path as String, + " are not the declared public key, so IdentitiesOnly would select something else", + ], ""), + } + ContentHashCrossFamilyIncomparable => + AgentSelectorRefused { + cause: "agent selector materialization refused: selector identities are in different hash families and are therefore incomparable", + } + } + } + } +} + // ── The agent arm ─────────────────────────────────────────────────────────────────────────────── // // Same question, different observation. The private half is held by an agent and never appears on @@ -138,7 +244,7 @@ fn agent_listing_lists_fingerprint(listing: String, fingerprint: NonEmptyStr) -> // mismatch, because the empty string does not contain the fingerprint. fn classify_agent_key_listing( agent_socket: NonEmptyStr, - public_selector_file: NonEmptyStr, + selector: AgentSelectorFile, expected_key: SshPublicKey, expected_fingerprint: NonEmptyStr, listing_succeeded: Bool, @@ -150,7 +256,7 @@ fn classify_agent_key_listing( FleetSshCredentialVerified { binding: fleet_ssh_agent_credential_binding_of_listed_key( agent_socket: agent_socket, - public_selector_file: public_selector_file, + public_selector_file: selector.path, listed_material: expected_key.material, ), } @@ -182,7 +288,7 @@ func list_agent_identities(agent_socket: NonEmptyStr) -> ShellCaptureResult func verify_fleet_ssh_agent_credential( agent_socket: NonEmptyStr, - public_selector_file: NonEmptyStr, + selector: AgentSelectorFile, expected_key: SshPublicKey, expected_fingerprint: NonEmptyStr, ) -> FleetSshCredentialVerification @@ -191,7 +297,7 @@ func verify_fleet_ssh_agent_credential( let observation = list_agent_identities(agent_socket: agent_socket) classify_agent_key_listing( agent_socket: agent_socket, - public_selector_file: public_selector_file, + selector: selector, expected_key: expected_key, expected_fingerprint: expected_fingerprint, listing_succeeded: observation.success, diff --git a/dag/gunbc/language_target_registry.dag b/dag/gunbc/language_target_registry.dag index c3b2084b19d..89d860aac9e 100644 --- a/dag/gunbc/language_target_registry.dag +++ b/dag/gunbc/language_target_registry.dag @@ -163,7 +163,7 @@ data jsx_registry_role_note: String = "JSX'S REGISTRY ROLE IS AN OPEN DECISION, data d0_scope_boundary_note: String = "WHAT THIS REGISTRY IS AND IS NOT, so it is not read as closing more than it does (cursor review 48122, P1 — a fair objection to how this work could be presented). This is the D0 IDENTITY AND GROUNDING slice: which targets exist, what upstream authority grounds each, and which surfaces join which subject. IT DOES NOT CLOSE THE SUPPORT REGISTRY. The support contract requires every registered target to carry declared support PROFILES, required CAPABILITY sets, EVIDENCE refs, and checker bindings in one typed registry, and none of those exist here. What is here in their place is deliberately weaker and should be read as such: priority appears only as free text inside parked reasons, and there are no capability or profile rows at all. Anyone treating a registration in this file as a support claim is reading it wrong — grounding says a target has an authority behind it, not that anything about it is supported." -data governing_contract_id_resolution_note: String = "WHY THIS ROW CARRIES A MODULE NAME AND NOT THE GOVERNING CONTRACT IDENTIFIERS, and the answer is a publication boundary rather than a citation gap. The strategy authority that governs Rust is not in this repository: it lives in a separate private overlay, so its contract identifiers cannot be resolved — or verified — from here, and a sweep of this tree finds nothing no matter how thorough. THAT IS A FIFTH FAILURE SHAPE, worth naming because it is NOT the hand-carried-string class this lane spent the day fixing: those strings named nothing anywhere, while these name something real that is invisible from where the check stands. A measurement that cannot reach an authority must not conclude the authority is absent. WHY THE IDS ARE NOT SIMPLY COPIED IN: the private overlay runs an opt-in-public model in which publishing is an explicit act, so transcribing its identifiers into a public row would be a PUBLICATION DECISION taken by a registry edit — above this lane, and not repaired by the identifiers looking innocuous. The interim carried here is v2.compiler.self_host.frontier, a real module in this repository that a reader can open, which is weaker than the governing contract but resolvable rather than dangling. Rust is genuinely governed by MORE THAN ONE contract, which is why the carrier is plural and why this single entry is an interim rather than the truth. NEXT TRIGGER: the operator rules on whether the strategy keys are published; if they are, this field takes the exact governing identifiers and this note deletes. THE ECMASCRIPT AND C++ DECISION IDS ARE A DIFFERENT CASE: they name a document section in THIS repository, which is a positional citation — weaker than a symbol, but openable." +data governing_contract_id_resolution_note: String = "WHY THIS ROW CARRIES A MODULE NAME AND NOT THE GOVERNING CONTRACT IDENTIFIERS, and the answer is a publication boundary rather than a citation gap. The strategy authority that governs Rust is not in this repository: it lives in a separate private overlay, so its contract identifiers cannot be resolved — or verified — from here, and a sweep of this tree finds nothing no matter how thorough. THAT IS A FIFTH FAILURE SHAPE, worth naming because it is NOT the hand-carried-string class this lane spent the day fixing: those strings named nothing anywhere, while these name something real that is invisible from where the check stands. A measurement that cannot reach an authority must not conclude the authority is absent. WHY THE IDS ARE NOT SIMPLY COPIED IN: the private overlay runs an opt-in-public model in which publishing is an explicit act, so transcribing its identifiers into a public row would be a PUBLICATION DECISION taken by a registry edit — above this lane, and not repaired by the identifiers looking innocuous. The interim carried here is v2.compiler.self_host.emitter_producer_provenance, a real module in this repository that a reader can open, which is weaker than the governing contract but resolvable rather than dangling. It replaced v2.compiler.self_host.frontier when the self-host frontier roster was deleted; the first repoint went to emit_coverage_frontier and was wrong, because that module answers whether a witness body runs native (its axis a) and explicitly disclaims module self-emission (its axis b) — the name resembled the deleted one, which is not a reason. Rust is genuinely governed by MORE THAN ONE contract, which is why the carrier is plural and why this single entry is an interim rather than the truth. NEXT TRIGGER: the operator rules on whether the strategy keys are published; if they are, this field takes the exact governing identifiers and this note deletes. THE ECMASCRIPT AND C++ DECISION IDS ARE A DIFFERENT CASE: they name a document section in THIS repository, which is a positional citation — weaker than a symbol, but openable." data registered_language_targets: List = [ @@ -201,7 +201,7 @@ data registered_language_targets: List = [ }, LanguageTargetRegistration { grounding: ExternalGrounding { scope: rust_language_model_scope }, - disposition: TargetGovernedByContracts { contract_ids: ["v2.compiler.self_host.frontier"] } + disposition: TargetGovernedByContracts { contract_ids: ["v2.compiler.self_host.emitter_producer_provenance"] } }, LanguageTargetRegistration { grounding: ExternalGrounding { scope: ecmascript_language_model_scope }, diff --git a/dag/gunbc/plans/cli_run_hollowing_plan.dag b/dag/gunbc/plans/cli_run_hollowing_plan.dag index 7dba1ac7cdb..a7e59e0c960 100644 --- a/dag/gunbc/plans/cli_run_hollowing_plan.dag +++ b/dag/gunbc/plans/cli_run_hollowing_plan.dag @@ -96,7 +96,7 @@ fn cli_run_hollowing_plan_body() -> List { ]), row(cells: [ cell(text: "Regen oracle & self-host scope"), - cell(text: "`regen_stage0` · `v2.compiler.self_host.frontier`"), + cell(text: "`regen_stage0` (the `v2.compiler.self_host.frontier` half of this scope is deleted with the roster)"), cell(text: "delete-with-v1"), cell(text: "Wave 4 real-fixpoint cutover (`5-real-fixpoint`)"), ]), diff --git a/dag/gunbc/plans/discrete_cost_derivation.dag b/dag/gunbc/plans/discrete_cost_derivation.dag index 69274bf4569..1970b39d518 100644 --- a/dag/gunbc/plans/discrete_cost_derivation.dag +++ b/dag/gunbc/plans/discrete_cost_derivation.dag @@ -20,7 +20,7 @@ fn discrete_cost_derivation_body() -> List { li(text: "`gunbc_falsifier_substrate_long_lane_budget_note` — *'Dissolve-on: per-witness declared cost envelopes (the witness-cost-locality admission law, the same trigger `gunbc_ci_fast_lane_rule_note` names) replace every blanket lane budget with declared per-row rows.'*"), li(text: "`long_lane_exclusion_note` (`gunbc.ci_layer_roots`) — *'Dissolve-on: per-witness declared cost envelopes (witness-cost-locality admission law) subsume the dir grain.'*"), ]), - p(text: "So the displaced cost is concrete and already priced by the tree: **three live scaffolds are blocked on one missing derivation**, and each additional witness that disappears into `long/` is a row that per-PR CI stops proving while a green CI keeps implying it did (`compiler_frontier_per_module_probe_exclusion_note` states this outright: *'green CI says nothing about survey numbers unless the local recipe below ran'*). The benefit is not an elegant cost algebra; it is retiring a proxy that silently removes coverage."), + p(text: "So the displaced cost is concrete and already priced by the tree: **three live scaffolds are blocked on one missing derivation**, and each additional witness that disappears into `long/` is a row that per-PR CI stops proving while a green CI keeps implying it did (the frontier per-module probe's exclusion note stated this outright — *green CI says nothing about survey numbers unless the local recipe below ran* — and that note has since been deleted with the roster it surveyed, which is the pattern rather than a counterexample to it). The benefit is not an elegant cost algebra; it is retiring a proxy that silently removes coverage."), p(text: "**Priced honestly:** the threshold is also doing real work today and must not be removed before its successor exists. The 5s deadline is a *construction* wall (`long_lane_exclusion_note`: 'the 5s deadline makes an over-budget fast-lane witness unwritable-in-place, so the roster cannot silently grow stale'), and it was the tourniquet for the run-29183446733 wedge — 243 of 270 minutes burned in billed silence. A replacement that is merely more principled but not fail-closed is a regression."), h2(text: "2. Three quantities, never one number"), diff --git a/dag/gunbc/plans/language_target_self_host_frontier.dag b/dag/gunbc/plans/language_target_self_host_frontier.dag index b817e474ec7..ce7c9b29ab9 100644 --- a/dag/gunbc/plans/language_target_self_host_frontier.dag +++ b/dag/gunbc/plans/language_target_self_host_frontier.dag @@ -31,7 +31,7 @@ fn language_target_self_host_frontier_body() -> List { row(cells: [cell(text: "**F2**"), cell(text: "VEP (`TargetValueExpressionProjection`) — the general body producer"), cell(text: "**partial** (rust: `^rust_token_unwired_\{else,loop,match,fat_arrow\}`, `v2.extdeps.languages.rust` `rust_value_expression_projection`) · partial (TS: match/loop/bind-in unwired) · **absent** (python, ecmascript)")]), row(cells: [cell(text: "**F3**"), cell(text: "`BlockEvaluationMode` statement spine (`ValueProducing` vs `StatementSequenced`)"), cell(text: "✓ type exists; TS's `StatementSequenced` arm produces the correct fail-closed refusals")]), row(cells: [cell(text: "**F4**"), cell(text: "`ProcessProgram` transport + `run_emit_host`; executable identity **bound per extdeps transport row** (`v2.std.host_transport` `HostTransportDescriptor` / `ProcessProgram`), compiler dispatch **generic** (`v2.compiler.emit_host` `process_program_name`)"), cell(text: "✓ done — `HostToolProgram.executable` is carried by the row and generic dispatch returns that value; target-specific work is only to configure a runtime row where one is absent")]), - row(cells: [cell(text: "**F5**"), cell(text: "self-host frontier runner (`v2.compiler.emit_host` `run_test_claim_module_emit_vs_eval`: emit → build → run → compare-to-eval)"), cell(text: "✓ machinery **for Rust only**, run **OFFLINE** (excluded from discovery). Rust is **not** self-hosted: `v2.compiler.self_host.frontier` `compiler_frontier_emitter_produced_count` is pinned to `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline = 0`; `v2.compiler.self_host.frontier` `compiler_frontier_roster_count` derives the roster size.")]), + row(cells: [cell(text: "**F5**"), cell(text: "self-host frontier runner (`v2.compiler.emit_host` `run_test_claim_module_emit_vs_eval`: emit → build → run → compare-to-eval)"), cell(text: "✓ machinery **for Rust only**, run **OFFLINE** (excluded from discovery). Rust is **not** self-hosted: `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline` (the roster's `compiler_frontier_emitter_produced_count` is deleted; this is the surviving count of the same fact) is pinned to `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline = 0`; the roster is DELETED, so no roster size derives — `v2.compiler.self_host.emitter_producer_provenance` carries the producer facts that outlived it.")]), row(cells: [cell(text: "**F6**"), cell(text: "`solve` — **structural** = existing `solve_constraints` / `ConstraintGraph` authority (extend, no fork); **numerical** = *absent* typed gap (finite measure + `TerminationProof`, typed residual-acceptance contract, extdeps solver handler)"), cell(text: "**off critical path** — not needed for emit-to-simulator; see solve doc")]), row(cells: [cell(text: "**F7**"), cell(text: "declaration emission generic over target (`v2.compiler.emit_semantic_decl` `emit_semantic_type_decl`)"), cell(text: "✓ done — the declaration emitter accepts a `TargetModel` and reads its emission bundle through `v2.std.compilers.semantic_decl_emission` `semantic_decl_emission_from_target`")]), ], @@ -46,7 +46,7 @@ fn language_target_self_host_frontier_body() -> List { header: row(cells: [cell(text: "target"), cell(text: "family"), cell(text: "current bar (verified)"), cell(text: "honest end-state"), cell(text: "key deps"), cell(text: "stress axis")]), alignments: [AlignNone, AlignNone, AlignNone, AlignNone, AlignNone, AlignNone], rows: [ - row(cells: [cell(text: "**rust**"), cell(text: "compiled"), cell(text: "compiled; bar-c; F2 **partial** (`^rust_token_unwired_\{else,loop,match,fat_arrow\}`, `v2.extdeps.languages.rust` `rust_value_expression_projection`); F5 emit-vs-eval fixture **OFFLINE**"), cell(text: "**`SeedRetained` roster; zero producer-qualified emissions** — `v2.compiler.self_host.frontier` `compiler_frontier_emitter_produced_count` equals `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline = 0`, and `seed_emitter_behavioral_green_count` equals `seed_emitter_behavioral_green_baseline = 0`; reference model, **NOT self-hosted**"), cell(text: "F2 completion; F5 self-host generalization"), cell(text: "(reference model)")]), + row(cells: [cell(text: "**rust**"), cell(text: "compiled"), cell(text: "compiled; bar-c; F2 **partial** (`^rust_token_unwired_\{else,loop,match,fat_arrow\}`, `v2.extdeps.languages.rust` `rust_value_expression_projection`); F5 emit-vs-eval fixture **OFFLINE**"), cell(text: "**`SeedRetained` roster; zero producer-qualified emissions** — `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline` (the roster's `compiler_frontier_emitter_produced_count` is deleted; this is the surviving count of the same fact) equals `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline = 0`, and `seed_emitter_behavioral_green_count` equals `seed_emitter_behavioral_green_baseline = 0`; reference model, **NOT self-hosted**"), cell(text: "F2 completion; F5 self-host generalization"), cell(text: "(reference model)")]), row(cells: [cell(text: "**cpp — Phase-0-C**"), cell(text: "compiled"), cell(text: "bar-c via `cc`, proven by an **OFFLINE** witness in `test/claim/execution/` (excluded from discovery)"), cell(text: "bar-c green (offline); self-host N/A at this phase"), cell(text: "F5-generalize"), cell(text: "(confirms)")]), row(cells: [cell(text: "**cpp — full C target**"), cell(text: "compiled"), cell(text: "**below bar-a** for full C"), cell(text: "blocked — needs **monomorphization** (grep-**zero** in tree), **closure conversion**, a **discriminant-tag row kind**, **multi-file (header/impl) projection**, and **ABI/linkage** — none present"), cell(text: "monomorphization, closure conversion, tag-row kind, multi-file projection, ABI/linkage"), cell(text: "(confirms — hard)")]), row(cells: [cell(text: "**go**"), cell(text: "compiled"), cell(text: "**skeleton** — needs TargetModel buildout"), cell(text: "**self-host** (first non-rust self-host — the F5 generalization proof), once built"), cell(text: "TargetModel buildout, surface spellings, F5"), cell(text: "**self-host axis**")]), diff --git a/dag/gunbc/plans/v2_self_hosting.dag b/dag/gunbc/plans/v2_self_hosting.dag index 68e9c397112..b0c3fefe4a4 100644 --- a/dag/gunbc/plans/v2_self_hosting.dag +++ b/dag/gunbc/plans/v2_self_hosting.dag @@ -7,7 +7,7 @@ import gunbc.plans.md_helpers { h2, h3, p, li, ul, ol, quote } fn v2_self_hosting_body() -> List { [ - p(text: "**Status:** planning tracker for the **Weak Self Host -> Strong Self Host** program (operator-signed 2026-07-11, manager: sharp-bee-290) · **DESIGN.md + the carriers remain the authority** (DESIGN §6). A task's real state is its branch/PR, not this file. Linked from `ROADMAP.md` §1 *Get off v1*. The **typed self-host frontier carrier** (`src/v2/compiler/self_host/frontier.dag`) holds the live roster and per-module gap breakdown; this doc is the wave sequencer only. Related: [namespace-resolution-design.md](namespace-resolution-design.md) · [general-body-producer-design.md](general-body-producer-design.md) · [s2-v2-self-emit-direction.md](s2-v2-self-emit-direction.md) · [decl-emission-defork-design.md](decl-emission-defork-design.md) · [dag-v2-defork-audit.md](dag-v2-defork-audit.md) · [seed-shrink-census.md](seed-shrink-census.md) · [typescript-gap-census.md](typescript-gap-census.md) · [emitted-crate-partition-design.md](emitted-crate-partition-design.md) · [c-linkage-unit-realization-design.md](c-linkage-unit-realization-design.md) (the C realization of the same target-agnostic `CompilationUnit` shape self-host emission is built on — the 2nd realization, staffed to stress-test that the shape doesn't cement Rust's acyclic-linkage assumption)."), + p(text: "**Status:** planning tracker for the **Weak Self Host -> Strong Self Host** program (operator-signed 2026-07-11, manager: sharp-bee-290) · **DESIGN.md + the carriers remain the authority** (DESIGN §6). A task's real state is its branch/PR, not this file. Linked from `ROADMAP.md` §1 *Get off v1*. **THE 27-ROW ROSTER CARRIER IS DELETED** (`src/v2/compiler/self_host/frontier.dag`, cut 2026-08-17): it was a hand-authored denominator that no consumer derived, and DESIGN §3's delete-first ruling says a superseded authority comes out at the root rather than being maintained while it dies. This doc is the wave sequencer only; **it no longer has a roster carrier to point at**, and the per-module dispositions it used to defer to must be re-derived from the emitter rather than re-authored. Surviving self-host authorities: `v2.compiler.self_host.emitter_producer_provenance` (which producer emitted a module), `v2.compiler.self_host.stage0_crate_layout` (crate partition), `v2.compiler.self_host.v2_emitter_direct_rust_door_contract` (the emit door). Related: [namespace-resolution-design.md](namespace-resolution-design.md) · [general-body-producer-design.md](general-body-producer-design.md) · [s2-v2-self-emit-direction.md](s2-v2-self-emit-direction.md) · [decl-emission-defork-design.md](decl-emission-defork-design.md) · [dag-v2-defork-audit.md](dag-v2-defork-audit.md) · [seed-shrink-census.md](seed-shrink-census.md) · [typescript-gap-census.md](typescript-gap-census.md) · [emitted-crate-partition-design.md](emitted-crate-partition-design.md) · [c-linkage-unit-realization-design.md](c-linkage-unit-realization-design.md) (the C realization of the same target-agnostic `CompilationUnit` shape self-host emission is built on — the 2nd realization, staffed to stress-test that the shape doesn't cement Rust's acyclic-linkage assumption)."), quote(blocks: [ p(text: "**END GOAL (decided 2026-06-21 — anchored in ROADMAP §1, do not re-litigate).** `.dag` is the authority/truth; **v2 emits BOTH Rust AND TypeScript as first-class realizations** (not one-or-the-other). Rust is the active seed language today; TypeScript joins the fixed point **after Rust self-host lands** (ROADMAP `5-ts-first-class` — deferred, not dropped). Each realization is proven **by execution**: self-emitted modules compile cargo-green and are **behaviorally equivalent** to the v1 seed on a discriminating corpus (green-by-execution + a discriminating RED, DESIGN §5). **Byte-identity with the seed is explicitly NOT the goal** (operator, 2026-07-08). The seed shrinks across a **typed self-host frontier** (DESIGN §7): each of the 27 compiler modules is *self-emitted* or *seed-retained* with a reason + migration trigger — countable, prioritizable, never a silent escape hatch. **Terminal (Wave 4):** hand-written compiler logic -> 0; a pinned, content-addressed, v2-emitted bootstrap kernel survives (~8-15k LOC)."), ]), @@ -15,7 +15,7 @@ fn v2_self_hosting_body() -> List { ThematicBreak, h2(text: "0. State of play"), ul(items: [ - li(text: "**0/27 self-host-green — FIRM.** `compiler_frontier_self_emitted_baseline = 0` on the 27-row roster (#6445). No compiler module is self-emitted with a green behavioral-equivalence receipt today."), + li(text: "**No compiler module is self-emitted with a green behavioral-equivalence receipt today.** That statement survives the roster cut; the way it used to be *counted* does not. `compiler_frontier_self_emitted_baseline = 0` on a hand-authored 27-row roster (#6445) is deleted along with the carrier — the denominator was authored, not discovered, so `0/27` measured the roster's opinion of how many modules exist rather than the corpus. Do not restore a numerator/denominator here: the honest replacement is a derived one, and until it exists this row is a qualitative claim, stated as such."), li(text: "**Emit surface is the dominant blocker — FIRM (qualitative).** The long pole is Rust emit-surface completeness (body producer, value-expression wiring, decl emit), not front-end parse/resolve. Per-module class breakdown is **not** transcribed here — see §2."), li(text: "**Wave 1 — IN FLIGHT.** Emit-surface + naming foundation; highest risk; no v1 deleted in this wave."), li(text: "**Front-end + emit infrastructure — background facts (not active tracks).** `src/v2/` is 100% `.dag`; full pipeline present. Route-A cargo-green landed (#5777/#5873); CI `dag_compile_clean` + `regen --verify` (#5873). Multi-target emitter: one `fold_node` catamorphism, 14+ targets."), @@ -25,8 +25,8 @@ fn v2_self_hosting_body() -> List { h3(text: "Wave 1 — emit-surface + naming foundation (IN FLIGHT)"), p(text: "The old 2-wave plan collapsed here: \"Wave 2 = the sweep\" hid the emit-surface keystone. Exit gate — **all** must be green-by-execution before Wave 2 opens:"), ol(items: [ - li(text: "**General body producer emits REAL ingested fn bodies** — RECEIPT LANDED (#6558 body producer + #6526/#6523 fast+long witnesses). Residual explicitly NOT proven by those witnesses: Stage D MVP subsumption, FLAG D binding-key re-grounding, frontier probe per-module receipts, FLAG E body_lowering_fold dissolution."), - li(text: "**Namespace SymbolIndex / tree-resolution lands** — RECEIPT LANDED (#6523 gate-2 witnesses + #6538 scaling receipt). Residual: 03_name_resolve/03_resolve end-to-end ingest wire + frontier probe blocker_class rows."), + li(text: "**General body producer emits REAL ingested fn bodies** — RECEIPT LANDED (#6558 body producer + #6526/#6523 fast+long witnesses). Residual explicitly NOT proven by those witnesses: Stage D MVP subsumption, FLAG D binding-key re-grounding, FLAG E body_lowering_fold dissolution. (A fourth residual, `frontier probe per-module receipts`, is retired rather than outstanding: the probe survey is deleted with the roster cut.)"), + li(text: "**Namespace SymbolIndex / tree-resolution lands** — RECEIPT LANDED (#6523 gate-2 witnesses + #6538 scaling receipt). Residual: 03_name_resolve/03_resolve end-to-end ingest wire. (The `frontier probe blocker_class rows` half is retired with the roster cut, not outstanding.)"), li(text: "**FLAG D binder identity grounded** — RECEIPT LANDED (#6575). EnvironmentBindingKey re-grounding on identity; `bind_eval_occurrence_identity_defect` witnesses green; conform-now protocol closed ([general-body-producer-design.md](general-body-producer-design.md) §9)."), li(text: "**Weak self-host behavioral receipt green** — RECEIPT LANDED (#6578). `dag/tools/self_host_logic_behavioral_transport.dag` emit→compile→run→equals-seed chain green-by-execution for `dag/std/logic.dag` (plain + `--inject-fault` RED control)."), ]), @@ -34,7 +34,7 @@ fn v2_self_hosting_body() -> List { h3(text: "Wave 2 — first real flips"), p(text: "The two big emit-surface tracks (~11 modules) **self-emit + behaviorally verify + REPLACE their v1 counterparts** -> **first v1 deletions**."), h3(text: "Wave 3 — remaining module drain"), - p(text: "Remaining ~13 roster modules flip to self-emitted **or** are declared **pinned-kernel** rows with an honest reason + migration trigger. Exit: **27/27 self-emitted-or-declared-kernel** = **strong self-host** milestone."), + p(text: "Every remaining compiler module flips to self-emitted **or** is declared a **pinned-kernel** row with an honest reason + migration trigger. The exit used to read `27/27 self-emitted-or-declared-kernel`; that fraction is retired with the roster carrier, because both halves came from the same hand-authored row list. **The exit condition is unchanged in substance and now needs a derived denominator to state it against** — an emitter-side census of what the compiler actually consists of, not a re-authored list. Naming that derivation is the first Wave 3 obligation."), h3(text: "Wave 4 — collapse to kernel + delete v1"), ol(items: [ li(text: "Pipeline runs on **emitted Rust** (not v1 seed mirror)."), @@ -45,10 +45,9 @@ fn v2_self_hosting_body() -> List { ]), h2(text: "2. Census honesty — what is firm vs carrier-held"), ul(items: [ - li(text: "**FIRM:** 0/27 self-emitted (`compiler_frontier_self_emitted_baseline`, census witnesses on `frontier.dag`)."), - li(text: "**FIRM (qualitative):** emit surface is the dominant blocker class across the roster."), - li(text: "**Carrier-held (do not transcribe counts in this doc):** per-module gap classification lives on `src/v2/compiler/self_host/frontier.dag` as the 27-row roster's `SeedRetained { reason, migration_trigger }` dispositions plus `compiler_frontier_census_attribution: ExecutionMeasured` — **the carrier holds the numbers; this doc points at the carrier** (DESIGN §2/§6: no parallel-ledger doc)."), - li(text: "**LANDED mechanism (#6464):** structural census + fail-closed classifier on `frontier.dag`; per-module `frontier_probe_emit_from_ingest` execution receipts bind via `frontier_probe_survey` host transport — overlay manifest must not append trailing imports post-namespace-wave (header-only import rule)."), + li(text: "**FIRM (qualitative):** emit surface is the dominant blocker class. This is the one census claim that survived the cut, because it never depended on the roster's row count."), + li(text: "**WAS carrier-held, now unheld.** Per-module gap classification lived on the deleted `frontier.dag` as 27 `SeedRetained { reason, migration_trigger }` rows plus `compiler_frontier_census_attribution: ExecutionMeasured`. The pointing-at-a-carrier discipline (DESIGN §2/§6: no parallel-ledger doc) is unchanged and is *why* nothing was transcribed back into this doc when the carrier went — a plan that answers a question its authority no longer answers is the parallel ledger that rule forbids. The gap is declared, not filled."), + li(text: "**RETIRED mechanism (was #6464):** the structural census, its fail-closed classifier, and the `frontier_probe_emit_from_ingest` / `frontier_probe_survey` host-transport receipts are deleted with the roster. The survey never produced a receipt on any host, including a dedicated runner, so what is lost is machinery rather than evidence — read emitter refusals by driving emission directly."), ]), h2(text: "3. Import-deletion ladder (parallel track — NOT a wave gate)"), p(text: "Namespace resolution and import deletion are **separate timelines**. Tree-resolution can work while imports still exist."), @@ -74,6 +73,6 @@ data v2_self_hosting_plan: Plan = Plan { slug: "v2-self-hosting", title: "Plan — v2 self-hosting", body: v2_self_hosting_body(), - retirement: PlanRetiresWhen { condition: unbound_dissolution(description: "Delete this doc when Wave 4 lands: pipeline on emitted Rust, import grammar deleted, v1 collapsed to pinned kernel, CI compile cone gone. The frontier carrier + absent v1 compiler logic are the authority; this tracker is redundant.") + retirement: PlanRetiresWhen { condition: unbound_dissolution(description: "Delete this doc when Wave 4 lands: pipeline on emitted Rust, import grammar deleted, v1 collapsed to pinned kernel, CI compile cone gone. Absent v1 compiler logic is the authority at that point; this tracker is redundant. (The frontier carrier this condition used to name was deleted 2026-08-17 — it is not a retirement input any more.)") } } diff --git a/dag/gunbc/plans/wave2_prep_design.dag b/dag/gunbc/plans/wave2_prep_design.dag index e5c2133c8c6..93bc282ccec 100644 --- a/dag/gunbc/plans/wave2_prep_design.dag +++ b/dag/gunbc/plans/wave2_prep_design.dag @@ -7,7 +7,7 @@ import gunbc.plans.md_helpers { h2, h3, p, li, ul, ol, quote, cell, row } fn status_block() -> MarkdownBlock { quote(blocks: [ - p(text: "**Status: design/scoping (checkpoint 0)** — Wave 2 prep for first real module self-emit flips. Design-first; NO load-bearing pipeline edits in this plan. Authored as a .dag Plan and NOT yet enrolled as a generated docs/plans md (no PlanArtifact, no plan_registry entry, no roadmap node) — enrollment is checkpoint 1; until then this module is reviewable from its own source. Authority chain: gunbc.plans.v2_self_hosting (wave sequencer) · general-body-producer-design (FLAG E / body producer) · namespace-resolution-design · type-env-single-authority-design (SymbolIndex index half) · **census carrier** v2.compiler.self_host.frontier (`frontier.dag`). DESIGN §2/§6: census counts and per-module ranks live on the carrier — this plan cites symbols, never a parallel ledger."), + p(text: "**Status: SUPERSEDED BY THE ROSTER CUT (2026-08-17) — quarry, not a plan.** Every mechanism this document names as its authority — `compiler_frontier_roster` and its 27 rows, `compiler_frontier_module_count_expected`, `compiler_frontier_self_emitted_baseline`, `compiler_frontier_census_attribution`, `compiler_frontier_sweep_order` and its monotonicity witness, `compiler_frontier_census_holds`, `compiler_frontier_band_a_emit_readiness_roster` — was deleted with the self-host frontier roster. The symbols below are NOT repointed to survivors, deliberately: there is no mapping from a roster row to a replacement, and inventing one would fabricate an authority this document never had. Per DESIGN §3, a plan authored while the deleted structure lived is re-read as quarry — its area map and its findings may still be evidence, but its sequencing is the old structure's gravity written down and is not authority over what replaces it. Read every symbol reference below as naming something that no longer exists. Original status line follows. **Status: design/scoping (checkpoint 0)** — Wave 2 prep for first real module self-emit flips. Design-first; NO load-bearing pipeline edits in this plan. Authored as a .dag Plan and NOT yet enrolled as a generated docs/plans md (no PlanArtifact, no plan_registry entry, no roadmap node) — enrollment is checkpoint 1; until then this module is reviewable from its own source. Authority chain: gunbc.plans.v2_self_hosting (wave sequencer) · general-body-producer-design (FLAG E / body producer) · namespace-resolution-design · type-env-single-authority-design (SymbolIndex index half) · **census carrier** v2.compiler.self_host.frontier (`frontier.dag`). DESIGN §2/§6: census counts and per-module ranks live on the carrier — this plan cites symbols, never a parallel ledger."), ]) } diff --git a/dag/gunbc/roadmap_authority.dag b/dag/gunbc/roadmap_authority.dag index c432b966023..346fda6e81d 100644 --- a/dag/gunbc/roadmap_authority.dag +++ b/dag/gunbc/roadmap_authority.dag @@ -1514,7 +1514,7 @@ fn declared_roadmap_nodes() -> List { identity: "rn_KSJNTEDB15YG37HBQXP8P62XJ8", id: "v2-emitter-producer-provenance", owner: "self-host", - path: "src/v2/compiler/self_host/frontier.dag", + path: "src/v2/compiler/self_host/emitter_producer_provenance.dag", t: fields( headline: "Record which generator actually produced each result", boundary: "Every result says which generator made it and how far it got, as two separate facts. Claiming the new generator made something, without the evidence that it did, has to be impossible to write down.", @@ -1545,7 +1545,7 @@ fn declared_roadmap_nodes() -> List { identity: "rn_KD37MRQ3ZA6F502DBKE6FE0VB8", id: "v2-emitter-first-behavioral-module", owner: "self-host", - path: "src/v2/compiler/self_host/frontier.dag", + path: "src/v2/compiler/self_host/wet_receipt_enrollment.dag", t: fields( headline: "Regenerate one already-tested module with the new generator", boundary: "Take a module that already has working tests, change only which generator produces it, and confirm it still passes the same tests including the deliberately broken one.", @@ -1560,7 +1560,7 @@ fn declared_roadmap_nodes() -> List { identity: "rn_5E7W23B34MW5Z7XMATBBJ11QFS", id: "v2-emitter-native-bootstrap", owner: "self-host", - path: "src/v2/compiler/self_host/frontier.dag", + path: "src/v2/compiler/self_host/v2_emitter_direct_rust_door_contract.dag", t: fields( headline: "Build the new generator with itself, then do it again", boundary: "The generator, and only the generator: it writes and builds a native version of itself, that native version writes and builds another, and the second one needs nothing from the old compiler. The other parts of the compiler are still produced the old way at this point.", diff --git a/dag/gunbc/roster_registry.dag b/dag/gunbc/roster_registry.dag index 0ee6664603c..e9a06d9c000 100644 --- a/dag/gunbc/roster_registry.dag +++ b/dag/gunbc/roster_registry.dag @@ -313,14 +313,6 @@ data roster_registry: List = [ reason: "emit_fn_def module_path allowlist: List> value-param type exprs reach emit as opaque containers, so v1_fn_param_type_needs_clone_bound cannot derive K/V; the override emits Clone on every item generic for listed modules only — extending the list is a counted roster edit, not a silent OR branch (trait_derive_emit_fn_clone_bound_keyed_carrier_module_scaffold_note)", dissolution: unbound_dissolution(description: "v1 param_node_type_expr preserves container element applied-type children (or an equivalent typed surface) so v1_fn_generic_clone_bound_via_bounded_container_element / v1_fn_generic_clone_bound_via_referenced_decl derive keyed-row carrier bounds without the module_path arm; then delete the allowlist, its emit_fn_def consumer, and this registration") } - }, - RosterRegistration { - roster: roster_decl(module_path: "v2.compiler.self_host.emitter_producer_provenance", decl_name: "producer_emission_oracle_rows"), - unit_kind: "V1SeedEmitter module path with producer emission receipt", - membership: DeclaredFrontier { - reason: "each row binds an EmitterProduced disposition to a producer emission receipt with enrolled behavioral witness citation; no producer claim without receipt evidence (2026-07-20 flip-wave reverted after 0/6 cargo-green)", - dissolution: unbound_dissolution(description: "per-module frontier_probe_survey receipts bind execution-measured digests and rows graduate to ByDerivation membership") - } } ] diff --git a/dag/gunbc/self_host_promotion_obligations.dag b/dag/gunbc/self_host_promotion_obligations.dag index 94891dfd273..18201fea2c0 100644 --- a/dag/gunbc/self_host_promotion_obligations.dag +++ b/dag/gunbc/self_host_promotion_obligations.dag @@ -85,15 +85,29 @@ data artifact_axis_omits_build_path: PromotionObligation = PromotionObligation { // uses. That is a property of every bound trigger, mitigated the same way — the name // here is the specified authoring point, not a guess, and it is stated in the paragraph // above so a future author renaming it knows to move this row with it. +// RE-HOMED, NOT RETIRED (self-host frontier roster cut). Both refs named +// v2.compiler.self_host.frontier, which is deleted, so the subject pointed at a ghost +// and — worse — the bound trigger became one that can never fire: DeclarationAppears +// waits for a declaration in a module nobody will re-create, which is a permanently +// pending obligation wearing a checkable trigger. +// +// The obligation itself survives the roster because it was never about the roster. The +// hazard is that a self-host promotion can be granted on evidence produced by the v1 +// seed, and its live subject is the producer axis in +// v2.compiler.self_host.emitter_producer_provenance, whose EmitterProducer still carries +// a V1SeedEmitter arm. The "n/27" framing goes with the roster; the hazard does not. +// The trigger keeps its declaration name and moves to the module that is now the +// specified authoring point, per the paragraph above about a bound ref naming where the +// carrier will be authored rather than where it is. data frontier_numerator_admits_seed_evidence: PromotionObligation = PromotionObligation { subject: decl_ref( - module_path: "v2.compiler.self_host.frontier", - decl_name: "SelfHostFrontierDisposition" + module_path: "v2.compiler.self_host.emitter_producer_provenance", + decl_name: "EmitterProducer" ), - claim_at_risk: "A reported n/27 means n modules were emitted by a v2 emitter; today the promoted disposition would also admit a module emitted by the v1 seed." as NonEmptyStr, + claim_at_risk: "A self-host promotion is supposed to mean a v2 emitter produced the module; the producer axis still carries a V1SeedEmitter arm, so a promotion granted on seed-produced evidence is representable." as NonEmptyStr, condition: bound_dissolution( ref: decl_ref( - module_path: "v2.compiler.self_host.frontier", + module_path: "v2.compiler.self_host.emitter_producer_provenance", decl_name: "v2_self_hosted_promotions" ) ), diff --git a/dag/gunbc/spark_serving_converge_plan.dag b/dag/gunbc/spark_serving_converge_plan.dag index ea60364d443..18fb161aadc 100644 --- a/dag/gunbc/spark_serving_converge_plan.dag +++ b/dag/gunbc/spark_serving_converge_plan.dag @@ -1,5 +1,11 @@ module gunbc.spark_serving_converge_plan +import gunbc.spark_serving_observed_members { + SparkServingObservedMemberProjection, + SparkServingObservedMembers, + SparkServingObservedMembersRefused, +} + import std.types { String, List, Bool, NonEmptyStr, Int } import std.content_hash { content_hash_of_value, serialize_content_hash, Fnv1a64 } import product.placement_supply { HostIdentity } @@ -15,7 +21,9 @@ import gunbc.spark_serving_membership { spark_serving_executor_linger_disabled_state_digest, spark_serving_membership_reconcile, spark_serving_membership_noop, + spark_serving_desired_members, } +import gunbc.spark_serving_release { SparkServingOccurrence, SparkServingRelease } import gunbc.spark_serving_member_realization { spark_serving_install_effects_for_member_action, spark_serving_install_effects_include, @@ -101,15 +109,40 @@ fn fleet_converge_spark_serving_typed_action( } } +// A PLANNED MEMBER THAT DOES NOT TRANSLATE REFUSES; IT IS NOT DROPPED. +// +// This projection used to be `flat_map` with `Absent => []`, which discarded any action carrying no +// install effects and produced a SHORTER row list with no diagnostic. The only action that reaches +// that arm is `MemberRemovalRefused` -- itself a refusal, so the drop erased a refusal by silently +// succeeding, and the artifact then reported a typed_row_count that did not cover its own plan. +// +// Its observed frequency was zero BY CONSTRUCTION: the only live plan is linger-only and linger +// always translates, so nothing ever exercised the arm. That is what made it worth closing before +// the plan widens rather than after -- a four-member plan is exactly the input that reaches it. +type SparkServingTypedActionProjection + = SparkServingTypedActionsProjected { rows: List } + | SparkServingTypedActionsRefused { cause: String } + fn fleet_converge_spark_serving_typed_actions( plan: MembershipPlan, -) -> List { - flat_map(plan.actions, a => +) -> SparkServingTypedActionProjection { + let rows = flat_map(plan.actions, a => match fleet_converge_spark_serving_typed_action(action: a) { Present { value: row } => [row] Absent => [] } ) + if length(rows) == length(plan.actions) { + SparkServingTypedActionsProjected { rows: rows } + } else { + SparkServingTypedActionsRefused { + cause: join([ + "spark serving typed actions refused: ", to_string(length(plan.actions)), + " planned member actions projected to only ", to_string(length(rows)), + " typed rows, so a planned member would have been dropped from the frozen artifact", + ], ""), + } + } } fn spark_serving_fleet_converge_apply_shell( @@ -118,6 +151,12 @@ fn spark_serving_fleet_converge_apply_shell( fleet_converge_apply_shell(timer_plan: timer_plan) } +// DECLARED RESIDUE, named rather than left to be found. This function propagates a typed-action +// refusal but not its CAUSE: `FleetConvergePlanArtifact?` has no arm to carry one, so the wet slice +// renders the generic `plan-refused` verdict and a reader cannot tell a dropped member from a +// non-Spark host. The arm is unreachable under the linger-only plan, so this is a bounded gap and +// not a live one. Trigger: it dissolves with the artifact return type, which the full-population +// cutover has to widen anyway -- that is the commit where the cause gets somewhere to go. fn spark_serving_fleet_converge_plan_artifact( host: NonEmptyStr, prior_generation: Int, @@ -133,8 +172,30 @@ fn spark_serving_fleet_converge_plan_artifact( host: host_identity, linger_enabled: linger_enabled, ) - let spark_rows = fleet_converge_spark_serving_typed_actions(plan: linger_plan) - let subject = fleet_converge_plan_subject( + match fleet_converge_spark_serving_typed_actions(plan: linger_plan) { + SparkServingTypedActionsRefused { cause: _ } => none + SparkServingTypedActionsProjected { rows: spark_rows } => + spark_serving_fleet_converge_plan_artifact_from_rows( + host: host, + prior_generation: prior_generation, + observed_timers: observed_timers, + observed_caps: observed_caps, + linger_plan: linger_plan, + spark_rows: spark_rows, + ) + } + } +} + +fn spark_serving_fleet_converge_plan_artifact_from_rows( + host: NonEmptyStr, + prior_generation: Int, + observed_timers: List, + observed_caps: List, + linger_plan: MembershipPlan, + spark_rows: List, +) -> FleetConvergePlanArtifact? { + let subject = fleet_converge_plan_subject( host: host, observed_timers: observed_timers, observed_caps: observed_caps, @@ -202,7 +263,6 @@ fn spark_serving_fleet_converge_plan_artifact( } _ => Absent } - } } fn spark_serving_linger_slice_noop_when_converged(linger_enabled: Bool) -> Bool { @@ -224,3 +284,37 @@ fn spark_serving_frozen_linger_effect(row: FleetConvergeSparkServingTypedAction) none } } + +// THE FULL-POPULATION PLAN. `spark_serving_linger_membership_plan` above reconciles a single-element +// desired list, so three of the four modeled members were never planned and the install effects that +// act on them could never be selected. This reconciles the whole declared population against what was +// actually observed. +// +// It refuses rather than planning when the observation could not be made: a refused observation +// rendered as an empty observed population would plan every member as an addition against a host +// nobody saw. +fn spark_serving_full_membership_plan( + occurrence: SparkServingOccurrence, + serving_release: SparkServingRelease, + projection: SparkServingObservedMemberProjection, +) -> SparkServingFullMembershipPlan { + match projection { + SparkServingObservedMembersRefused { cause: cause } => + SparkServingFullMembershipPlanRefused { cause: cause } + SparkServingObservedMembers { members: observed, unit_observed: unit_observed } => + SparkServingFullMembershipPlanReady { + plan: spark_serving_membership_reconcile( + desired: spark_serving_desired_members( + occurrence: occurrence, + serving_release: serving_release, + ), + observed: observed, + ), + unit_observed: unit_observed, + } + } +} + +type SparkServingFullMembershipPlan + = SparkServingFullMembershipPlanReady { plan: MembershipPlan, unit_observed: Bool } + | SparkServingFullMembershipPlanRefused { cause: String } diff --git a/dag/gunbc/spark_serving_converge_slice_wet.dag b/dag/gunbc/spark_serving_converge_slice_wet.dag index 05becc7326d..7b0f73211ae 100644 --- a/dag/gunbc/spark_serving_converge_slice_wet.dag +++ b/dag/gunbc/spark_serving_converge_slice_wet.dag @@ -28,9 +28,9 @@ import gunbc.fleet_multi_principal_probe { import gunbc.typed_argv_exec { TypedArgvExecConverged, TypedArgvExecRefused } import gunbc.host_effect { HostEffectTransport } import gunbc.spark_serving_credential_locus { - SparkServingSliceCredentialLocus, - SparkServingSliceAnchoredContext, - SparkServingSliceRunnerAgent, + SparkServingContextReady, + SparkServingContextRefused, + prepare_spark_serving_agent_context, spark_serving_slice_transport, spark_serving_slice_locus_label, } @@ -241,12 +241,12 @@ fn spark_serving_converge_slice_exec_verdict( } fn spark_serving_converge_slice_wet_host_report( - locus: SparkServingSliceCredentialLocus, + context: FleetSshExecutionContext, host: HostIdentity, execute_apply: Bool, ) -> SparkServingSliceHostReport { let endpoint = fleet_probe_endpoint_for(host: host as String) - let transport = spark_serving_slice_transport(locus: locus, host: host) + let transport = spark_serving_slice_transport(context: context, host: host) match spark_serving_probe_linger(transport: transport) { TypedArgvExecRefused { reason: probe_refusal } => spark_serving_converge_slice_host_line( @@ -392,7 +392,7 @@ func spark_serving_converge_slice_wet() -> ProcessExit SparkConvergeTargetRefused { reason: why } => exit_failure(reason: why) SparkConvergeTargetSingle { host: only } => spark_serving_converge_slice_emit_receipt( - locus: SparkServingSliceAnchoredContext { context: context }, + context: context, now: now, attempt_raw: attempt_raw, trust_line: known_hosts_materialization_receipt(outcome: materialization), @@ -401,7 +401,7 @@ func spark_serving_converge_slice_wet() -> ProcessExit ) SparkConvergeTargetAllObserveOnly => spark_serving_converge_slice_emit_receipt( - locus: SparkServingSliceAnchoredContext { context: context }, + context: context, now: now, attempt_raw: attempt_raw, trust_line: known_hosts_materialization_receipt(outcome: materialization), @@ -430,7 +430,7 @@ func spark_serving_converge_slice_wet() -> ProcessExit // this fold never has to decide what "no target" means — the only way to reach it with the // full host list is the observe-only arm. fn spark_serving_converge_slice_emit_receipt( - locus: SparkServingSliceCredentialLocus, + context: FleetSshExecutionContext, now: NonEmptyStr, attempt_raw: String, trust_line: String, @@ -440,7 +440,7 @@ fn spark_serving_converge_slice_emit_receipt( let reports = map( hosts, h => spark_serving_converge_slice_wet_host_report( - locus: locus, + context: context, host: h, execute_apply: execute_apply, ), @@ -453,7 +453,7 @@ fn spark_serving_converge_slice_emit_receipt( join([ "execute_apply=", if execute_apply { "yes" } else { "no" }, - " credential_locus=", spark_serving_slice_locus_label(locus: locus), + " credential_locus=", spark_serving_slice_locus_label(context: context), " address_authority=fleet_probe_endpoint_for→dgx_spark_procurement OperatorAllocation\n", ], ""), trust_line, @@ -485,35 +485,50 @@ fn spark_serving_converge_slice_emit_receipt( // runtime rather than degrading. Wiring that entry into the fleet-converge job therefore // produced a dispatch mode that could not execute on the runners it targeted (review 52564). // -// This entry is the runner-side sibling, and it mirrors the arrangement the enrolled -// fleet_multi_principal_probe_wet already uses: no Secret Manager fetch, no token source, no -// known-hosts materialization inside the entry. The key is already loaded in the in-run -// ssh-agent and the anchor is already materialized, both by the job's own key-agent step, so -// the transport is SshShell and the receipt says so rather than implying an anchored context -// it never held. +// This entry is the runner-side sibling: no Secret Manager fetch and no token source, because the +// key is already loaded in the in-run ssh-agent. What it no longer does is ASSUME that. It used to +// pass a nullary runner-agent locus projecting to a bare SshShell, with a trust_line reading +// "established by the runner job, not by this entry" -- an accurate sentence describing a +// precondition the entry had no way to check, so a job step that stopped materializing the anchor, +// or an agent holding a different key, produced the same receipt and the same legs. // -// It carries no attempt identity for the same reason: attempt identity exists to name a -// credential materialization this entry does not perform. +// It now prepares its own sealed context: verify the agent holds the declared fleet key, materialize +// the selector and the known-hosts anchor under an attempt-owned path, and refuse before any host is +// contacted if any of that fails. It therefore DOES carry an attempt identity, because it now +// performs materializations that must not collide with another run's. +data spark_serving_converge_ci_attempt_raw: String = "spark-serving-converge-ci" + func spark_serving_converge_slice_ci_wet() -> ProcessExit { + match prepare_spark_serving_agent_context(attempt_raw: spark_serving_converge_ci_attempt_raw) { + SparkServingContextRefused { cause: cause } => exit_failure(reason: cause) + SparkServingContextReady { context: context, receipt: context_receipt } => + spark_serving_converge_slice_ci_with_context(context: context, context_receipt: context_receipt) + } +} + +func spark_serving_converge_slice_ci_with_context( + context: FleetSshExecutionContext, + context_receipt: String, +) -> ProcessExit { let now = clock_now_probed_at() let execute_apply = spark_converge_execute_apply_from_env() match spark_converge_target_selection(execute_apply: execute_apply) { SparkConvergeTargetRefused { reason: why } => exit_failure(reason: why) SparkConvergeTargetSingle { host: only } => spark_serving_converge_slice_emit_receipt( - locus: SparkServingSliceRunnerAgent, + context: context, now: now, - attempt_raw: "runner-agent-no-attempt-identity", - trust_line: "trust=in-run ssh-agent + job-materialized known_hosts anchor (established by the runner job, not by this entry)", + attempt_raw: spark_serving_converge_ci_attempt_raw, + trust_line: context_receipt, hosts: [only], execute_apply: execute_apply, ) SparkConvergeTargetAllObserveOnly => spark_serving_converge_slice_emit_receipt( - locus: SparkServingSliceRunnerAgent, + context: context, now: now, - attempt_raw: "runner-agent-no-attempt-identity", - trust_line: "trust=in-run ssh-agent + job-materialized known_hosts anchor (established by the runner job, not by this entry)", + attempt_raw: spark_serving_converge_ci_attempt_raw, + trust_line: context_receipt, hosts: spark_serving_converge_slice_wet_hosts, execute_apply: execute_apply, ) diff --git a/dag/gunbc/spark_serving_credential_locus.dag b/dag/gunbc/spark_serving_credential_locus.dag index e432ed7ab9b..0dbd166c0cb 100644 --- a/dag/gunbc/spark_serving_credential_locus.dag +++ b/dag/gunbc/spark_serving_credential_locus.dag @@ -1,17 +1,55 @@ module gunbc.spark_serving_credential_locus -import std.types { String, NonEmptyStr } +import std.types { String, Bool, NonEmptyStr } +import std.resources { Network } import product.placement_supply { HostIdentity } -import gunbc.fleet_known_hosts_anchor { FleetSshExecutionContext, SshTarget } +import gunbc.fleet_known_hosts_anchor { + FleetSshExecutionContext, + FleetSshAttemptIdentity, + FleetSshCredentialBinding, + SshTarget, + fleet_ssh_attempt_identity, + fleet_ssh_execution_context_of, + materialize_fleet_known_hosts_anchor, + known_hosts_materialization_receipt, + fleet_ssh_credential_locus_label, +} +import gunbc.fleet_ssh_access { fleet_automation_ssh_key, fleet_automation_ssh_key_fingerprint } +import gunbc.fleet_ssh_credential_verify { + FleetSshCredentialVerified, + FleetSshCredentialIdentityMismatch, + FleetSshCredentialDerivationRefused, + AgentSelectorMaterialized, + AgentSelectorRefused, + materialize_agent_public_selector, + verify_fleet_ssh_agent_credential, + fleet_ssh_credential_verification_refusal_reason, +} import gunbc.fleet_reach_endpoint { fleet_probe_endpoint_for } -import gunbc.host_effect { HostEffectTransport, FleetSsh, SshShell } +import gunbc.host_effect { HostEffectTransport, FleetSsh } import gunbc.spark_serving_desired { spark_serving_automation_principal_login } +import extdeps.shell +import std.algebra { trim } -data spark_serving_credential_locus_note: String = "THE TWO CREDENTIAL LOCI A SPARK-DIRECTED ENTRY CAN RUN UNDER. Extracted to its own module so the converge slice and the serving observation can both name the same distinction without one importing the other. AnchoredContext is the operator-workstation route: unconstructible without a context whose anchor passed a content readback, reaching the Spark over FleetSsh. RunnerAgent is the GHA self-hosted route: those hosts carry no gcloud, so the Secret Manager fetch behind AnchoredContext fails at runtime there (spark_credential_workflow spark_credential_access_token_frontier_note), and the key instead lives in the in-run ssh-agent the job materialized. RunnerAgent therefore carries NO trust facts of its own; the job establishes them out of band, exactly as the enrolled fleet_multi_principal_probe_wet does. Naming the locus in a receipt is what lets a reader tell which preconditions a run actually held instead of inferring them from a function name." - -type SparkServingSliceCredentialLocus = - SparkServingSliceAnchoredContext { context: FleetSshExecutionContext } - | SparkServingSliceRunnerAgent +// ONE CREDENTIAL LOCUS, because there is only one kind of thing an SSH leg may run under: a sealed +// `FleetSshExecutionContext`. +// +// WHAT THIS DELETES AND WHY. `SparkServingSliceCredentialLocus` used to be a two-armed coproduct -- +// `SparkServingSliceAnchoredContext { context }` for the operator workstation, and a nullary +// `SparkServingSliceRunnerAgent` for the GHA route. The second arm's own authority note said it +// "carries NO trust facts of its own; the job establishes them out of band", and it projected to a +// bare `SshShell { ssh_host: "user@host" }` -- no anchor, no credential, no OpenSSH posture. Every +// exactness property the fleet SSH machinery exists to hold was absent on the route that actually +// runs against the Sparks. +// +// It existed because of a REPRESENTATION GAP, not a decision: `FleetSshCredentialBinding` required an +// identity file, an agent-held key has none, so the runner route could not build a binding, could not +// build a context, and had nothing to pass. Once the agent-held locus and its verification landed, +// that arm stopped being a second kind of run and became a second name for one -- so it is deleted +// rather than kept beside the thing that replaced it. +// +// With one arm left the coproduct itself was a nickname for `FleetSshExecutionContext`, so it is gone +// too. The helpers below take the context directly. fn spark_serving_locus_ssh_target(host: HostIdentity) -> SshTarget { SshTarget { @@ -20,27 +58,122 @@ fn spark_serving_locus_ssh_target(host: HostIdentity) -> SshTarget { } } +// One transport, derived. There is no arm that can produce an unanchored one. fn spark_serving_slice_transport( - locus: SparkServingSliceCredentialLocus, + context: FleetSshExecutionContext, host: HostIdentity, ) -> HostEffectTransport { - match locus { - SparkServingSliceAnchoredContext { context: c } => - FleetSsh { target: spark_serving_locus_ssh_target(host: host), context: c } - SparkServingSliceRunnerAgent => - SshShell { - ssh_host: join([ - spark_serving_automation_principal_login() as String, - "@", - fleet_probe_endpoint_for(host: host as String), - ], "") as NonEmptyStr, + FleetSsh { target: spark_serving_locus_ssh_target(host: host), context: context } +} + +// The receipt line naming where the credential was held, read off the binding the context carries +// rather than off a label the caller chose. A run cannot claim an anchored posture it did not obtain, +// because the string is derived from the sealed value. +fn spark_serving_slice_locus_label(context: FleetSshExecutionContext) -> String { + fleet_ssh_credential_locus_label(binding: context.credential) +} + +// ── Preparing the runner-side context ─────────────────────────────────────────────────────────── + +type SparkServingContextPreparation = + SparkServingContextReady { context: FleetSshExecutionContext, receipt: String } + | SparkServingContextRefused { cause: String } + +fn spark_serving_agent_socket() -> NonEmptyStr? { + match shell.Env.Get(name: "SSH_AUTH_SOCK" as NonEmptyStr).value { + Present { value: raw } => + if trim(s: raw) == "" { none } else { Present { value: trim(s: raw) as NonEmptyStr } } + Absent => none + } +} + +// THE RUNNER ROUTE'S CONTEXT, built here rather than assumed. +// +// The entries that used to pass `SparkServingSliceRunnerAgent` carried a `trust_line` reading +// "established by the runner job, not by this entry". That sentence was accurate and it was the +// problem: the entry asserted a precondition it had no way to check, so a job step that silently +// stopped materializing the anchor, or an agent holding a different key, produced the same receipt. +// +// Each step here is observed and each refusal is typed and located. On any refusal the caller holds +// no context, and since `spark_serving_slice_transport` is the only way to a transport and it +// requires one, zero SSH legs execute -- a property of the types rather than a discipline. +func prepare_spark_serving_agent_context(attempt_raw: String) -> SparkServingContextPreparation + uses net: Network +{ + match fleet_ssh_attempt_identity(raw: attempt_raw) { + Absent => + SparkServingContextRefused { + cause: join([ + "spark serving context refused: attempt identity `", attempt_raw, + "` is not a safe path segment, so the anchor and selector have no attempt-owned path", + ], ""), + } + Present { value: attempt } => + match spark_serving_agent_socket() { + Absent => + SparkServingContextRefused { + cause: "spark serving context refused: SSH_AUTH_SOCK is unset or empty, so there is no named agent to verify the fleet credential against", + } + Present { value: sock } => + match materialize_agent_public_selector(attempt: attempt, key: fleet_automation_ssh_key) { + AgentSelectorRefused { cause: cause } => + SparkServingContextRefused { cause: cause } + AgentSelectorMaterialized { selector: selector } => + match verify_fleet_ssh_agent_credential( + agent_socket: sock, + selector: selector, + expected_key: fleet_automation_ssh_key, + expected_fingerprint: fleet_automation_ssh_key_fingerprint as NonEmptyStr, + ) { + FleetSshCredentialIdentityMismatch { expected_line: e, observed_line: o } => + SparkServingContextRefused { + cause: fleet_ssh_credential_verification_refusal_reason( + verification: FleetSshCredentialIdentityMismatch { expected_line: e, observed_line: o }, + ), + } + FleetSshCredentialDerivationRefused { cause: cause } => + SparkServingContextRefused { + cause: fleet_ssh_credential_verification_refusal_reason( + verification: FleetSshCredentialDerivationRefused { cause: cause }, + ), + } + FleetSshCredentialVerified { binding: binding } => + spark_serving_context_from_verified_binding( + attempt: attempt, + binding: binding, + ) + } + } } } } -fn spark_serving_slice_locus_label(locus: SparkServingSliceCredentialLocus) -> String { - match locus { - SparkServingSliceAnchoredContext { context: _ } => "anchored-fleet-ssh-context" - SparkServingSliceRunnerAgent => "runner-in-run-ssh-agent" +// The anchor half, entered only with a verified credential. Deliberately last: materializing a +// known-hosts file is cheap and harmless, but the ORDER states the priority -- the credential is +// established before anything about reaching a host is prepared. +func spark_serving_context_from_verified_binding( + attempt: FleetSshAttemptIdentity, + binding: FleetSshCredentialBinding, +) -> SparkServingContextPreparation + uses net: Network +{ + let materialization = materialize_fleet_known_hosts_anchor(attempt: attempt) + match fleet_ssh_execution_context_of(outcome: materialization, credential: binding) { + Absent => + SparkServingContextRefused { + cause: join([ + "spark serving context refused before any ssh leg: ", + known_hosts_materialization_receipt(outcome: materialization), + ], ""), + } + Present { value: context } => + SparkServingContextReady { + context: context, + receipt: join([ + "credential ", fleet_ssh_credential_locus_label(binding: binding), + " trust=attempt-owned known_hosts anchor materialized and content-verified by THIS entry\n", + known_hosts_materialization_receipt(outcome: materialization), + ], ""), + } } } diff --git a/dag/gunbc/spark_serving_observe.dag b/dag/gunbc/spark_serving_observe.dag index 4ad03201f65..e3e95593e4c 100644 --- a/dag/gunbc/spark_serving_observe.dag +++ b/dag/gunbc/spark_serving_observe.dag @@ -25,8 +25,9 @@ import gunbc.fleet_multi_principal_probe { fleet_ssh_attempt_raw_from_env } import gunbc.spark_credential_workflow { run_with_materialized_fleet_ssh_binding } import gunbc.auth.access_token_source { GcloudPrintToken } import gunbc.spark_serving_credential_locus { - SparkServingSliceCredentialLocus, - SparkServingSliceRunnerAgent, + SparkServingContextReady, + SparkServingContextRefused, + prepare_spark_serving_agent_context, spark_serving_slice_transport, spark_serving_slice_locus_label, } @@ -117,13 +118,13 @@ type SparkServingObservationReport // rather than collapsing to `none`, so an unreachable host and an unportable word list do not // arrive at the caller as the same value. fn spark_serving_probe_leg_via_locus( - locus: SparkServingSliceCredentialLocus, + context: FleetSshExecutionContext, host: HostIdentity, raw_words: List, ) -> SshSessionExecResult? { match run_typed_argv_transport( argv: raw_words, - transport: spark_serving_slice_transport(locus: locus, host: host), + transport: spark_serving_slice_transport(context: context, host: host), ) { TypedArgvExecConverged { result: r } => Present { value: r } TypedArgvExecRefused { reason: _ } => none @@ -131,17 +132,17 @@ fn spark_serving_probe_leg_via_locus( } fn spark_serving_observe_host_via_locus( - locus: SparkServingSliceCredentialLocus, + context: FleetSshExecutionContext, host: HostIdentity, ) -> SparkServingObservation { let readback = spark_serving_readback_from_probe_results( host: host, - load_state: spark_serving_probe_leg_via_locus(locus: locus, host: host, raw_words: spark_serving_load_state_probe_words()), - is_active: spark_serving_probe_leg_via_locus(locus: locus, host: host, raw_words: spark_serving_active_probe_words()), - version: spark_serving_probe_leg_via_locus(locus: locus, host: host, raw_words: spark_serving_version_probe_words), - tags: spark_serving_probe_leg_via_locus(locus: locus, host: host, raw_words: spark_serving_tags_probe_words), - nvidia_driver: spark_serving_probe_leg_via_locus(locus: locus, host: host, raw_words: spark_serving_nvidia_driver_probe_words), - runtime_receipt: spark_serving_probe_leg_via_locus(locus: locus, host: host, raw_words: spark_serving_runtime_receipt_probe_words()), + load_state: spark_serving_probe_leg_via_locus(context: context, host: host, raw_words: spark_serving_load_state_probe_words()), + is_active: spark_serving_probe_leg_via_locus(context: context, host: host, raw_words: spark_serving_active_probe_words()), + version: spark_serving_probe_leg_via_locus(context: context, host: host, raw_words: spark_serving_version_probe_words), + tags: spark_serving_probe_leg_via_locus(context: context, host: host, raw_words: spark_serving_tags_probe_words), + nvidia_driver: spark_serving_probe_leg_via_locus(context: context, host: host, raw_words: spark_serving_nvidia_driver_probe_words), + runtime_receipt: spark_serving_probe_leg_via_locus(context: context, host: host, raw_words: spark_serving_runtime_receipt_probe_words()), ) derive_spark_serving_observation(readback: readback) } @@ -572,20 +573,32 @@ func spark_serving_observe_with_attempt(attempt_raw: String) -> ProcessExit // through the in-run ssh-agent the job already materialized, so the same probe legs run where // the fleet actually is. It is READ-ONLY: every word list here is a query. func spark_serving_observe_ci_wet() -> ProcessExit { + match prepare_spark_serving_agent_context(attempt_raw: spark_serving_observe_ci_attempt_raw) { + SparkServingContextRefused { cause: cause } => exit_failure(reason: cause) + SparkServingContextReady { context: context, receipt: context_receipt } => + spark_serving_observe_ci_with_context(context: context, context_receipt: context_receipt) + } +} + +// The attempt this entry owns. It names the entry rather than a run, because the anchor and selector +// paths it scopes live under target/ in a workspace one job owns. +data spark_serving_observe_ci_attempt_raw: String = "spark-serving-observe-ci" + +func spark_serving_observe_ci_with_context( + context: FleetSshExecutionContext, + context_receipt: String, +) -> ProcessExit { let now = clock_now_probed_at() let observations = map( spark_serving_desired_hosts, - h => spark_serving_observe_host_via_locus(locus: SparkServingSliceRunnerAgent, host: h), + h => spark_serving_observe_host_via_locus(context: context, host: h), ) let body = join( concat( [ join(["spark_serving_observe_ci_wet probed_at=", now as String, "\n"], ""), - join([ - "credential_locus=", - spark_serving_slice_locus_label(locus: SparkServingSliceRunnerAgent), - " trust=in-run ssh-agent + job-materialized known_hosts anchor (established by the runner job, not by this entry)\n", - ], ""), + join(["credential_locus=", spark_serving_slice_locus_label(context: context), "\n"], ""), + context_receipt, ], map(observations, o => spark_serving_observation_line(observation: o)), ), diff --git a/dag/gunbc/spark_serving_observed_members.dag b/dag/gunbc/spark_serving_observed_members.dag new file mode 100644 index 00000000000..ce55fdac11b --- /dev/null +++ b/dag/gunbc/spark_serving_observed_members.dag @@ -0,0 +1,197 @@ +module gunbc.spark_serving_observed_members + +import std.types { Bool, List, NonEmptyStr, String } +import std.content_hash { serialize_content_hash } +import product.placement_supply { HostIdentity } +import gunbc.ownership { Owned, Ensured } +import gunbc.spark_serving_release { + SparkServingObservation, + SparkServingObserved, + SparkServingAbsent, + SparkServingObservationRefused, + SparkServingRelease, +} +import gunbc.spark_serving_membership { + SparkServingMember, + SparkServingRuntimeRootAddress, + SparkServingUserUnitAddress, + SparkServingModelSlotAddress, + SparkServingLingerAddress, + spark_serving_member, + spark_serving_primary_model_slot, + spark_serving_serving_principal, + spark_serving_executor_linger_state_digest, +} + +// THE OBSERVED SIDE OF THE FOUR-MEMBER POPULATION. +// +// WHAT THIS REPLACES. `spark_serving_desired_members` builds the full desired population -- runtime +// root, user unit, primary model slot, linger -- and until now it had ZERO production consumers. The +// live plan was `spark_serving_linger_membership_plan`, whose desired side is the single-element list +// `[spark_serving_desired_linger_member(host)]`. So three of the four modeled members were never +// planned, and the three unrealized install effects that act on them could never be SELECTED however +// well they were implemented. Adding executor arms above a linger-only plan is +// specification-without-execution: it typechecks, it witnesses green, and it converges nothing. +// +// The desired side already exists and is correct. What was missing is the observed side, which is +// what this module supplies, plus the plan that reconciles the two (gunbc.spark_serving_converge_plan +// `spark_serving_full_membership_plan`). +// +// THE PROJECTION IS FROM AN OBSERVATION, NEVER FROM THE DESIRED STATE. Deriving an observed member's +// state digest from the desired release would make every member reconcile as converged by +// construction -- the reconcile would compare a value to itself and the plan would always be empty. +// That is the failure this whole lane exists to avoid, so the desired release is deliberately NOT a +// parameter of the observed projection. + +// WHAT AN OBSERVATION CAN AND CANNOT ESTABLISH, as a typed value rather than an assumption. +// +// `SparkServingObserved` carries a `SparkServingReleaseIdentity` -- one digest over the runtime and +// model the host actually has loaded. That is enough to state the runtime and model members. It says +// NOTHING about the unit file's bytes: the live observer reads LoadState and is-active, not the +// file's content and not `is-enabled`. +// +// So a converged-looking host cannot yet have its user-unit member OBSERVED, and this type says so +// instead of guessing. `UserUnitStateUnobserved` is not a failure -- it is the honest answer for an +// observation that did not carry those bytes, and it keeps "we did not look" separate from "the unit +// is absent", which have different remedies and must not collapse. +type SparkServingObservedUnitState + = UserUnitStateObserved { unit_state_digest: NonEmptyStr } + | UserUnitStateAbsent + | UserUnitStateUnobserved + +// Linger is observed by its own slice over a separate probe, so it arrives beside the serving +// observation rather than inside it. +type SparkServingObservedLingerState + = LingerObservedEnabled + | LingerObservedDisabled + | LingerUnobservedState + +type SparkServingObservedMemberProjection + = SparkServingObservedMembers { members: List, unit_observed: Bool } + | SparkServingObservedMembersRefused { cause: String } + +// A member is present in the OBSERVED list only when something was actually observed to be there. +// Absence from the list is what makes `membership_reconcile` plan an addition, so an unobserved +// member must not be listed -- listing it with a placeholder digest would either fabricate a state +// or plan a change against a value nobody measured. +fn spark_serving_observed_linger_members( + host: HostIdentity, + linger: SparkServingObservedLingerState, +) -> List { + match linger { + LingerObservedEnabled => [ + spark_serving_member( + host: host, + principal: spark_serving_serving_principal(), + address: SparkServingLingerAddress, + state_digest: spark_serving_executor_linger_state_digest(), + ownership: Ensured, + ), + ] + LingerObservedDisabled => [] + LingerUnobservedState => [] + } +} + +fn spark_serving_observed_unit_members( + host: HostIdentity, + unit: SparkServingObservedUnitState, +) -> List { + match unit { + UserUnitStateObserved { unit_state_digest: d } => [ + spark_serving_member( + host: host, + principal: spark_serving_serving_principal(), + address: SparkServingUserUnitAddress, + state_digest: d, + ownership: Owned, + ), + ] + UserUnitStateAbsent => [] + UserUnitStateUnobserved => [] + } +} + +// THE PROJECTION. +// +// `SparkServingAbsent` is a real observation, not ignorance: the host was reached and the serving +// runtime is not there. So the runtime and model members are genuinely absent and the plan should +// add them -- which is exactly the bare-srv6 path this lane needs. +// +// `SparkServingObservationRefused` is the opposite and refuses the whole projection: an observation +// that could not be made cannot be rendered as "nothing is there", which would narrow the plan to +// nothing and silently converge a host we never saw. That is the empty-observation narrow DESIGN +// names, and it is the mirror of the absorbing fallback. +// +// `unit_observed` travels beside the members so a consumer can tell a plan built on a complete +// observation from one built on a partial one, without inferring it from list length. +fn spark_serving_observed_members( + observation: SparkServingObservation, + unit: SparkServingObservedUnitState, + linger: SparkServingObservedLingerState, +) -> SparkServingObservedMemberProjection { + match observation { + SparkServingObservationRefused { host: h, cause: cause } => + SparkServingObservedMembersRefused { + cause: join([ + "spark serving observed members refused for host=", h as String, + ": the observation itself was refused (", cause as String, + "), and an observation that could not be made must not be rendered as an empty population", + ], ""), + } + SparkServingAbsent { host: h } => + SparkServingObservedMembers { + members: concat( + spark_serving_observed_unit_members(host: h, unit: unit), + spark_serving_observed_linger_members(host: h, linger: linger), + ), + unit_observed: spark_serving_unit_state_was_observed(unit: unit), + } + SparkServingObserved { host: h, loaded_release: loaded } => + SparkServingObservedMembers { + members: concat( + [ + spark_serving_member( + host: h, + principal: spark_serving_serving_principal(), + address: SparkServingRuntimeRootAddress, + state_digest: serialize_content_hash(hash: loaded.digest) as NonEmptyStr, + ownership: Owned, + ), + spark_serving_member( + host: h, + principal: spark_serving_serving_principal(), + address: SparkServingModelSlotAddress { slot: spark_serving_primary_model_slot }, + state_digest: serialize_content_hash(hash: loaded.digest) as NonEmptyStr, + ownership: Owned, + ), + ], + concat( + spark_serving_observed_unit_members(host: h, unit: unit), + spark_serving_observed_linger_members(host: h, linger: linger), + ), + ), + unit_observed: spark_serving_unit_state_was_observed(unit: unit), + } + } +} + +fn spark_serving_unit_state_was_observed(unit: SparkServingObservedUnitState) -> Bool { + match unit { + UserUnitStateObserved { unit_state_digest: _ } => true + UserUnitStateAbsent => true + UserUnitStateUnobserved => false + } +} + +// A plan built while the unit member was never looked at cannot honestly report convergence: the +// unit would be planned as an addition on every run, so a second plan can never be empty. Consumers +// that care about the empty-replan bar read this rather than re-deriving it. +fn spark_serving_projection_supports_empty_replan( + projection: SparkServingObservedMemberProjection, +) -> Bool { + match projection { + SparkServingObservedMembersRefused { cause: _ } => false + SparkServingObservedMembers { members: _, unit_observed: observed } => observed + } +} diff --git a/dag/gunbc/spark_serving_unit_render.dag b/dag/gunbc/spark_serving_unit_render.dag new file mode 100644 index 00000000000..172a46b8a25 --- /dev/null +++ b/dag/gunbc/spark_serving_unit_render.dag @@ -0,0 +1,82 @@ +module gunbc.spark_serving_unit_render + +import std.types { String, NonEmptyStr, FilePath } +import extdeps.systemd.unit_file { + SystemdUnitFile, + Description, + After, + ServiceType, + ExecStart, + Restart, + Environment, + WorkingDirectory, + WantedBy, + serialize_systemd_unit_file, +} +import extdeps.ollama.server_env { ollama_host_env_assignment, ollama_models_env_assignment } +import gunbc.spark_serving_install_paths { + SparkServingUserUnitSpec, + spark_serving_user_unit_spec, + spark_serving_runtime_root, + spark_serving_models_root, +} +import gunbc.spark_serving_desired { spark_serving_desired_bind_host_port } + +// THE ONE PLACE A SPARK SERVING UNIT BECOMES BYTES. +// +// `SparkServingUserUnitSpec` is deliberately typed fields and NOT systemd INI syntax -- its own +// authority note says so. That left a gap rather than a decision: nothing could turn the spec into a +// file, so `WriteUserUnitFile` had no bytes to deliver and the unit member had nothing to be +// observed against. The missing piece was never gunbc's to invent, because spelling `[Service]` and +// `ExecStart=` here would have made this module a second systemd authority (§3). It belongs to +// `extdeps.systemd.unit_file`, which is cited to systemd.unit(5) and systemd.service(5); this module +// only maps gunbc's typed fields onto it. +// +// The mapping is total and takes no decisions of its own: every directive below is a spec field or a +// path derived from the install-paths authority. There is no arm that can omit a directive or supply +// a default, so a spec change cannot silently fail to reach the file. + +fn spark_serving_exec_start_command(spec: SparkServingUserUnitSpec) -> NonEmptyStr { + join([ + spark_serving_runtime_root() as String, + "/bin/ollama ", + spec.exec_subcommand as String, + ], "") as NonEmptyStr +} + +// The runtime and model roots come from the install-paths authority rather than from the spec's +// relative strings, so the unit and the installer cannot disagree about where the runtime lives. +fn spark_serving_user_unit_file(spec: SparkServingUserUnitSpec) -> SystemdUnitFile { + SystemdUnitFile { + unit: [ + Description { text: spec.description }, + After { target: spec.after }, + ], + service: [ + ServiceType { mode: spec.service_type }, + Environment { assignment: ollama_host_env_assignment(bind: spec.bind_host_port) }, + Environment { + assignment: ollama_models_env_assignment(root: spark_serving_models_root() as NonEmptyStr), + }, + WorkingDirectory { path: spark_serving_runtime_root() as NonEmptyStr }, + ExecStart { command: spark_serving_exec_start_command(spec: spec) }, + Restart { policy: spec.restart }, + ], + install: [WantedBy { target: spec.wanted_by }], + } +} + +// THE DELIVERED BYTES, and the value an observed unit file is compared against. One function, so the +// write side and the observe side cannot drift into two renderings of one spec -- which would make +// every host report a permanent MemberChanged against itself. +fn spark_serving_user_unit_text(spec: SparkServingUserUnitSpec) -> String { + serialize_systemd_unit_file(file: spark_serving_user_unit_file(spec: spec)) +} + +fn spark_serving_desired_user_unit_text() -> String { + spark_serving_user_unit_text( + spec: spark_serving_user_unit_spec( + bind_host_port: spark_serving_desired_bind_host_port() as NonEmptyStr, + ), + ) +} diff --git a/dag/gunbc/stage0_crate_layout_emit.dag b/dag/gunbc/stage0_crate_layout_emit.dag index e15193150b0..3e4bd8c2635 100644 --- a/dag/gunbc/stage0_crate_layout_emit.dag +++ b/dag/gunbc/stage0_crate_layout_emit.dag @@ -1,6 +1,6 @@ module gunbc.stage0_crate_layout_emit -import v2.compiler.self_host.frontier { +import v2.compiler.self_host.stage0_crate_layout { emit_hand_maintained_pub_mod_block, hand_maintained_pub_mod_basenames, hand_maintained_stage0_dirs, @@ -52,7 +52,7 @@ fn expected_stage0_crate_layout_generated_dag() -> String { concat( "module gunbc.stage0_crate_layout_generated\n\n", "import std.types { List, String }\n\n", - "data stage0_crate_layout_generated_note: String = \"Generated by gunbc stage0_crate_layout_emit — do not hand-edit. Authority: v2.compiler.self_host.frontier; regen via dag/tools/generated_artifact_gate.dag main_wet.\"\n\n", + "data stage0_crate_layout_generated_note: String = \"Generated by gunbc stage0_crate_layout_emit — do not hand-edit. Authority: v2.compiler.self_host.stage0_crate_layout; regen via dag/tools/generated_artifact_gate.dag main_wet.\"\n\n", "data generated_pub_mod_block: String = \"", escape_dag_string_body(s: pub_mod_block), "\"\n\n", @@ -73,7 +73,7 @@ fn expected_stage0_crate_layout_generated_rs() -> String { let stage0_dirs = hand_maintained_stage0_dirs() concat( "// Generated by gunbc stage0_crate_layout_emit — do not hand-edit.\n", - "// Authority: v2.compiler.self_host.frontier; regen via dag/tools/generated_artifact_gate.dag main_wet.\n\n", + "// Authority: v2.compiler.self_host.stage0_crate_layout; regen via dag/tools/generated_artifact_gate.dag main_wet.\n\n", "#[rustfmt::skip]\n", "pub const HAND_MAINTAINED_STAGE0_FILES: &[&str] = &[\n", render_rust_str_slice_items(xs: stage0_filenames), diff --git a/dag/gunbc/stage0_crate_layout_generated.dag b/dag/gunbc/stage0_crate_layout_generated.dag index 8a4447bee7e..8b7d1a78590 100644 --- a/dag/gunbc/stage0_crate_layout_generated.dag +++ b/dag/gunbc/stage0_crate_layout_generated.dag @@ -2,7 +2,7 @@ module gunbc.stage0_crate_layout_generated import std.types { List, String } -data stage0_crate_layout_generated_note: String = "Generated by gunbc stage0_crate_layout_emit — do not hand-edit. Authority: v2.compiler.self_host.frontier; regen via dag/tools/generated_artifact_gate.dag main_wet." +data stage0_crate_layout_generated_note: String = "Generated by gunbc stage0_crate_layout_emit — do not hand-edit. Authority: v2.compiler.self_host.stage0_crate_layout; regen via dag/tools/generated_artifact_gate.dag main_wet." data generated_pub_mod_block: String = "\n#[macro_use]\npub mod v1_interpreter_dispatch_generated;\npub mod v1_interpreter;\npub mod ci_control_plane;\npub mod cli_run;\npub mod coproduct_reflection;\npub mod data_initializer_identity;\npub mod resolved_graph_cache;\npub mod shared_typecheck_store;\npub mod recorded_fixture;\npub mod derived_realization_schedule;\npub mod memory_governor;\npub mod module_path_index;\npub mod usv_pilot_v2_std_algebra;\npub mod usv_pilot_v2_std_collection;\npub mod usv_pilot_v2_std_node;\npub mod v2_compiler_resolve;\npub mod v2_compiler_program_partition;\npub mod v2_compiler_tokenize;\npub mod v2_compiler_infer;" diff --git a/dag/gunbc/stage0_emit_plan.dag b/dag/gunbc/stage0_emit_plan.dag index f4e9fb48563..5a3fca8d7d9 100644 --- a/dag/gunbc/stage0_emit_plan.dag +++ b/dag/gunbc/stage0_emit_plan.dag @@ -69,7 +69,7 @@ type GeneratedStage0FilesOutcome = GeneratedStage0FilesAvailable { files: List } | GeneratedStage0FilesRefused { cause: Stage0EmissionPlanRefusalCause } -data stage0_projection_disposition_authority_note: String = "GeneratedProjection versus HandMaintainedCandidate derives from gunbc.stage0_crate_layout_generated.generated_stage0_filenames, the enrolled projection of v2.compiler.self_host.frontier seed-retained facts. This module never owns a second exclusion list." +data stage0_projection_disposition_authority_note: String = "GeneratedProjection versus HandMaintainedCandidate derives from gunbc.stage0_crate_layout_generated.generated_stage0_filenames, the enrolled projection of v2.compiler.self_host.stage0_crate_layout hand-maintained filename facts (carved out of the deleted self-host frontier roster, which is where this projection used to source them). This module never owns a second exclusion list." data stage0_source_identity_supply_scaffold_note: String = "DECLARED SCAFFOLD. stage0_emission_source_identities_host observes SOURCE only: the Rust seed walks gunbc.cli_run.regen_input_sources and parses every row through the source-authority-aligned module binding parser. It must never observe EmitResult or share the emit-output path. DISSOLVE-ON: generated_artifact_gate accepts a v2.compiler.source_authority.ModuleStorageIndex; then this host builtin and this scaffold carrier delete, and the same pure folds consume that index directly." diff --git a/dag/gunbc/stage0_rust_source_lifecycle_scaffold.dag b/dag/gunbc/stage0_rust_source_lifecycle_scaffold.dag index f17bed2007e..a93d7f28205 100644 --- a/dag/gunbc/stage0_rust_source_lifecycle_scaffold.dag +++ b/dag/gunbc/stage0_rust_source_lifecycle_scaffold.dag @@ -22,7 +22,7 @@ import std.keyed_roster { path_occurrence_count } import std.decl_ref { DeclarationRef, WholeDeclaration } import std.disposition { Disposition, Scaffold, SingleAuthority } import gunbc.roadmap_model { RoadmapNodeId } -import v2.compiler.self_host.frontier { hand_maintained_stage0_filenames } +import v2.compiler.self_host.stage0_crate_layout { hand_maintained_stage0_filenames } import v2.std.algebra { any, filter, fold_list, length, list_map, list_snoc_item } import v2.std.collection { List } import v2.std.text { String } @@ -294,7 +294,7 @@ data generated_stage0_files_authority_ref: DeclarationRef = DeclarationRef { } data hand_maintained_stage0_filenames_authority_ref: DeclarationRef = DeclarationRef { - module_path: "v2.compiler.self_host.frontier", + module_path: "v2.compiler.self_host.stage0_crate_layout", decl_name: "hand_maintained_stage0_filenames", field: WholeDeclaration } diff --git a/dag/gunbc/typed_remote_file_write.dag b/dag/gunbc/typed_remote_file_write.dag index fccfde62cbb..7f386fe2296 100644 --- a/dag/gunbc/typed_remote_file_write.dag +++ b/dag/gunbc/typed_remote_file_write.dag @@ -1,6 +1,7 @@ module gunbc.typed_remote_file_write -import std.types { String, List, NonEmptyStr, FilePath } +import std.types { String, Bool, List, NonEmptyStr, FilePath } +import std.algebra { trim } import std.content_hash { content_hash_atom } import extdeps.ssh.session { ssh_session_exec_portable_words_with_stdin, @@ -32,6 +33,106 @@ type TypedRemoteFileWriteOutcome = TypedRemoteFileWriteRemoteExecAccepted { result: SshSessionExecResult } | TypedRemoteFileWriteOutcomeRefused { reason: String } +// ── Convergence ───────────────────────────────────────────────────────────────────────────────── +// +// `TypedRemoteFileWriteRemoteExecAccepted` is a zero exit from the writing process and the authority +// note above is explicit that this is NOT convergence: it proves the remote accepted stdin, not that +// the declared bytes are at the declared path with the declared mode. This section adds the arm that +// ruling reserved. +// +// FOUR STEPS, and the ORDER is the property. +// +// 1. stage -- write the bytes to a sibling staging path, never to the destination +// 2. mode -- set the mode on the staged file, before anything can observe it at its real name +// 3. rename -- `mv -f` within one directory, which POSIX makes atomic, so no reader ever sees a +// partially written or wrong-moded file at the destination +// 4. read back-- `cat` the DESTINATION and compare to the declared content in the model +// +// Writing straight to the destination and then chmod-ing is the shape this replaces: it publishes +// incomplete bytes under the real name, and on a unit file that is a window where systemd can read +// something that was never a valid unit. +// +// WHY `dd status=none` AND NOT `tee`. `tee` copies stdin to stdout, so every byte written is also +// echoed back across the SSH channel and into whatever captures it -- doubling transfer and putting +// file content into logs. `dd status=none` writes and says nothing. This is not a style preference: +// a credential or config file written through `tee` has its contents in the run log. +// +// WHY READ-BACK BY CONTENT AND NOT BY DIGEST. A digest comparison needs a digest of the INTENDED +// bytes, and `.dag` has no SHA-256 over a `String` -- `extdeps.crypto.hash` `Digest` carries a hex +// its caller supplies. Comparing a remote `sha256sum` of the staged file to a remote `sha256sum` of +// the destination would prove only that the rename moved the same bytes, saying nothing about +// whether those bytes were the ones intended, which is the question. Reading the file back and +// comparing to the declared content answers it directly and the comparison happens in the model, +// where a witness can exercise it. For a unit file the transfer is a few hundred bytes. +type RemoteFileMode + = RemoteFileModeOwnerReadWrite + | RemoteFileModeOwnerReadWriteWorldRead + +fn remote_file_mode_octal(mode: RemoteFileMode) -> String { + match mode { + RemoteFileModeOwnerReadWrite => "600" + RemoteFileModeOwnerReadWriteWorldRead => "644" + } +} + +type TypedRemoteFileConvergence + = TypedRemoteFileConverged { path: FilePath, mode: RemoteFileMode } + | TypedRemoteFileConvergenceRefused { step: String, reason: String } + +// The staging sibling. It MUST share a directory with the destination: `mv` is atomic only within +// one filesystem, and a suffix on the same path is the cheapest way to guarantee that without +// modeling mount points. The suffix is dot-separated so it stays inside the portable-word allowlist. +fn typed_remote_file_staging_path(write: TypedRemoteFileWrite) -> String { + concat(write.path as String, ".gunbc-staging") +} + +fn typed_remote_file_stage_argv(write: TypedRemoteFileWrite) -> List { + ["dd", "status=none", concat("of=", typed_remote_file_staging_path(write: write))] +} + +fn typed_remote_file_chmod_argv(write: TypedRemoteFileWrite, mode: RemoteFileMode) -> List { + ["chmod", remote_file_mode_octal(mode: mode), typed_remote_file_staging_path(write: write)] +} + +fn typed_remote_file_rename_argv(write: TypedRemoteFileWrite) -> List { + ["mv", "-f", typed_remote_file_staging_path(write: write), write.path as String] +} + +fn typed_remote_file_readback_argv(write: TypedRemoteFileWrite) -> List { + ["cat", write.path as String] +} + +// The read-back judgment, pure so every arm is reachable hermetically. Exact comparison, with no +// trimming: normalizing whitespace here would let a real difference pass, and a file whose trailing +// bytes differ from the declared content is not the file that was declared. +fn classify_typed_remote_file_readback( + write: TypedRemoteFileWrite, + mode: RemoteFileMode, + readback_succeeded: Bool, + readback_stdout: String, + readback_stderr: String, +) -> TypedRemoteFileConvergence { + if !readback_succeeded { + TypedRemoteFileConvergenceRefused { + step: "read-back", + reason: concat( + concat("could not read back ", write.path as String), + concat(" after rename: ", readback_stderr), + ), + } + } else if readback_stdout == write.content { + TypedRemoteFileConverged { path: write.path, mode: mode } + } else { + TypedRemoteFileConvergenceRefused { + step: "read-back", + reason: concat( + concat("the bytes at ", write.path as String), + " are not the declared content: the write reported success and the file is something else", + ), + } + } +} + data typed_remote_file_write_tee_command: String = "tee" fn typed_remote_file_write_seal( @@ -147,3 +248,112 @@ fn typed_remote_file_write_over_fleet_ssh( } } } + +// ── The converging sequence ───────────────────────────────────────────────────────────────────── + +// One remote step: portable-word admission, then the leg. A non-portable argv refuses BEFORE the +// leg rather than being quoted into something the far-side shell may re-split. +fn typed_remote_file_step( + target: SshTarget, + context: FleetSshExecutionContext, + raws: List, + stdin_payload: String, +) -> SshSessionExecResult? { + match portable_remote_words(raws: raws) { + Absent => none + Present { value: words } => Present { + value: ssh_session_exec_portable_words_with_stdin( + client_args: shape_fleet_ssh_exec(context: context, target: target, words: words), + stdin_payload: stdin_payload, + ), + } + } +} + +// A step that carries no stdin still goes through the stdin-bearing operation with an empty payload, +// so there is ONE leg shape rather than two that could drift apart. +fn typed_remote_file_step_outcome( + target: SshTarget, + context: FleetSshExecutionContext, + step: String, + raws: List, + stdin_payload: String, +) -> TypedRemoteFileConvergence? { + match typed_remote_file_step(target: target, context: context, raws: raws, stdin_payload: stdin_payload) { + Absent => Present { + value: TypedRemoteFileConvergenceRefused { + step: step, + reason: "remote argv refused as non-portable under the far-side shell re-parse allowlist", + }, + } + Present { value: r } => + if r.success { none } else { + Present { + value: TypedRemoteFileConvergenceRefused { + step: step, + reason: concat("remote step failed: ", trim(s: r.stderr)), + }, + } + } + } +} + +// STAGE -> MODE -> RENAME -> READ BACK, halting at the first refusal. Each step's failure is located +// by name, so a converge that stops is a statement about WHICH invariant did not hold rather than a +// single opaque false. Nothing is published under the destination name until the rename, and nothing +// is called converged until the destination has been read back and compared. +func converge_typed_remote_file( + target: SshTarget, + context: FleetSshExecutionContext, + admission: TypedRemoteFileWriteAdmission, + mode: RemoteFileMode, +) -> TypedRemoteFileConvergence { + match admission { + TypedRemoteFileWriteAdmissionRefused { cause: cause } => + TypedRemoteFileConvergenceRefused { step: "admission", reason: cause as String } + TypedRemoteFileWriteAdmitted { write: write } => + match typed_remote_file_step_outcome( + target: target, context: context, step: "stage", + raws: typed_remote_file_stage_argv(write: write), + stdin_payload: typed_remote_file_write_stdin_payload(write: write), + ) { + Present { value: refusal } => refusal + Absent => + match typed_remote_file_step_outcome( + target: target, context: context, step: "mode", + raws: typed_remote_file_chmod_argv(write: write, mode: mode), + stdin_payload: "", + ) { + Present { value: refusal } => refusal + Absent => + match typed_remote_file_step_outcome( + target: target, context: context, step: "rename", + raws: typed_remote_file_rename_argv(write: write), + stdin_payload: "", + ) { + Present { value: refusal } => refusal + Absent => + match typed_remote_file_step( + target: target, context: context, + raws: typed_remote_file_readback_argv(write: write), + stdin_payload: "", + ) { + Absent => + TypedRemoteFileConvergenceRefused { + step: "read-back", + reason: "remote argv refused as non-portable under the far-side shell re-parse allowlist", + } + Present { value: back } => + classify_typed_remote_file_readback( + write: write, + mode: mode, + readback_succeeded: back.success, + readback_stdout: back.stdout, + readback_stderr: back.stderr, + ) + } + } + } + } + } +} diff --git a/dag/gunbc/witness_deferral_freeze.dag b/dag/gunbc/witness_deferral_freeze.dag index 4ec3f79adf6..a6dde051512 100644 --- a/dag/gunbc/witness_deferral_freeze.dag +++ b/dag/gunbc/witness_deferral_freeze.dag @@ -20,7 +20,7 @@ data witness_deferral_freeze_shrink_log_note: String = "SHRINK LOG. The 701-iden data witness_deferral_freeze_purpose_frontier_note: String = "WHAT THIS FREEZE DELIBERATELY DOES NOT CARRY, so its coverage is not overread. A frozen row records IDENTITY only — that this exact (entry, function) was already deferred by path policy when the wall landed. It records no purpose, no measured cost, and no consumer, because it has none: the whole point of the freeze is that these 701 identities (152 entries, measured at the freeze point) were admitted without any of the three. The purpose taxonomy (which boundary, population, external effect, or resource contract justifies the size) and the per-witness cost envelope are the NEXT slice, and a frozen row is the debt marker that one is owed. -A FROZEN ROW ASSERTS MEMBERSHIP AND NOTHING ELSE, and that neutrality is load-bearing rather than incidental. It records that this exact identity was already path-deferred at the freeze point. It does NOT say the witness is a violation, that it will owe a cadence, or that it is permanently unadmitted — because which of those it turns out to be is not yet decided, and a baseline everyone reads afterward is the most expensive place to bake a wrong label. At least three dispositions live in this population and they owe different things: a PERMANENT regression witness owes a scheduled consumer, since an offline recipe can establish that this head was tested once but never that a later regression will be observed; a TERMINATING one-shot survey owes no cadence at all, because it has no later — it runs once at a pinned head to produce a manifest and then deletes itself, and demanding a cadence would enroll a job whose whole purpose is to be removed; and a witness with no discriminating red owes deletion rather than either. Live specimen of the terminating kind, already in this roster: the seven rows of src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag, whose compiler_frontier_per_module_probe_exclusion_note names all seven functions, the exact invocation, the pinned subject and a dissolve_on under which the note, the exclusion row and the probe scaffold delete together at 27 of 27 receipts. +A FROZEN ROW ASSERTS MEMBERSHIP AND NOTHING ELSE, and that neutrality is load-bearing rather than incidental. It records that this exact identity was already path-deferred at the freeze point. It does NOT say the witness is a violation, that it will owe a cadence, or that it is permanently unadmitted — because which of those it turns out to be is not yet decided, and a baseline everyone reads afterward is the most expensive place to bake a wrong label. At least three dispositions live in this population and they owe different things: a PERMANENT regression witness owes a scheduled consumer, since an offline recipe can establish that this head was tested once but never that a later regression will be observed; a TERMINATING one-shot survey owes no cadence at all, because it has no later — it runs once at a pinned head to produce a manifest and then deletes itself, and demanding a cadence would enroll a job whose whole purpose is to be removed; and a witness with no discriminating red owes deletion rather than either. The roster carried a specimen of the terminating kind — the seven rows of src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag, a per-module survey over the self-host frontier roster — and it terminated, though not the way its own dissolve_on described: the roster it surveyed was deleted outright before the survey ever produced 27 of 27 receipts, so the witness, its exclusion note and its freeze rows went with the subject rather than with the receipts. That is worth keeping as the concrete case, because it is the disposition this mechanism cannot express: nothing here could distinguish a survey that ends by completing from one that ends because its subject is gone, and both left the roster looking identical. THE ARM THAT DOES NOT EXIST YET, named so its absence is not read as a decision: this mechanism cannot tell a terminating one-shot from a permanent witness, because the distinction lives in prose. Typing it is strictly more demanding than typing a cadence, not less — a one-shot owes a pinned subject, a mechanically checkable dissolution trigger, AND a deadline after which an undissolved one-shot refuses. Without that deadline every permanent witness can simply claim to be a one-shot, which is the same laundering as an extrapolation wearing the word measured. NEXT TRIGGER: the purpose taxonomy, where PermanentRegressionWitness and TerminatingSurvey become distinct carriers with distinct obligations; until then this roster deliberately labels neither. @@ -688,29 +688,6 @@ data frozen_path_deferrals: List = [ ] }, FrozenPathDeferral { entry: "src/v2/test/claim/long/compile_door_ledger_test.dag", functions: ["ledger_cause_histogram_over_mixed_affected_set"] }, - FrozenPathDeferral { - entry: "src/v2/test/claim/long/compiler_frontier_measured_roster_test.dag", - functions: [ - "compiler_frontier_structural_census_invariants_holds", - "compiler_frontier_measured_parse_engine_hooks_self_emit_ready_holds", - "compiler_frontier_measured_tokenize_emit_surface_holds", - "compiler_frontier_measured_compile_emit_surface_holds", - "compiler_frontier_sweep_order_has_expected_length_holds", - "compiler_frontier_measured_sweep_order_matches_tractability_rank_holds" - ] - }, - FrozenPathDeferral { - entry: "src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag", - functions: [ - "compiler_frontier_per_module_probe_survey_holds", - "compiler_frontier_gap_clustering_common_root_at_blocker_class_holds", - "compiler_frontier_wave2_blocker_partition_totality_holds", - "compiler_frontier_roster_bidirectional_totality_live_survey_holds", - "compiler_frontier_receipt_totality_wall_live_survey_holds", - "compiler_frontier_wave2_emit_surface_dominates_holds", - "compiler_frontier_wave2_sizing_band_a_leaf_count_holds" - ] - }, FrozenPathDeferral { entry: "src/v2/test/claim/long/compiler_frontier_probe_entry_test.dag", functions: [ @@ -1078,7 +1055,6 @@ data frozen_path_deferrals: List = [ FrozenPathDeferral { entry: "src/v2/test/claim/self_host/crate_layout_witness_test.dag", functions: [ - "transition_parity_host_index_agrees_with_hand_rows", "projection_refuses_on_absent_index", "crate_layout_witnesses" ] }, diff --git a/dag/product/pcb/copper.dag b/dag/product/pcb/copper.dag index a8031f8e3c4..f716bab3d56 100644 --- a/dag/product/pcb/copper.dag +++ b/dag/product/pcb/copper.dag @@ -1,7 +1,7 @@ module product.pcb.copper import std.logic { Bool } -import std.types { Int, List, NonEmptyStr } +import std.types { Int, List } import std.decl_ref { DeclarationRef } import product.compute_board.analog { ElectricalNet, NetIdentity } import v2.std.algebra { fold_list } @@ -127,32 +127,30 @@ type NetCopperRealization { type CopperRefusalCause = RealizationNamesNoSuchNet { net: NetIdentity } - | NetRealizedMoreThanOnce { net: NetIdentity } | RealizationSelectedAgainstAnotherStackup { net: NetIdentity } + | NetSplitAcrossLayersWithoutAConnection { net: NetIdentity } + | NetHasTwoConductorsOnOneLayer { net: NetIdentity } + | InterlayerConnectionNamesNoSuchNet { net: NetIdentity } + | InterlayerConnectionSelectedAgainstAnotherStackup { net: NetIdentity } + | InterlayerConnectionJoinsALayerToItself { net: NetIdentity, ordinal: Int } + | InterlayerConnectionEndpointHasNoConductor { net: NetIdentity, ordinal: Int } // ADMISSION IS AN IDENTITY JOIN, NOT A COUNT. The failure this catches is ordinary and quiet: a net // is renamed in the schematic and its copper realization keeps the old identity, so the board has a // conductor belonging to nothing and a net with no conductor. Counting realizations against nets // would report both boards as fine, because the count did not change (DESIGN section 5 - completeness // is an identity join). -// COPPER TAKES THE NET ROSTER, NOT THE CIRCUIT INTENT, and that boundary is the whole point of this -// correction. The first cut of this module took an AnalogCircuitIntent, which looks harmless because -// the only field it read was .nets -- but AnalogCircuitIntent carries components: it is the RC -// specimen's article, and ElectricalComponentInstance is a CLOSED coproduct of resistor, capacitor -// and independent voltage source. A CPU, a BMC, a DDR slot, a regulator or a connector has no -// variant there. -// -// So the copper carrier could only have acquired the Altra motherboard as a consumer by making the -// motherboard impersonate a three-part analog board. The universe a lens ranges over has to be the -// objects it is genuinely about, and copper is about ELECTRICAL CONNECTIVITY, not about one -// product's SPICE article. +// COPPER TAKES THE NET ROSTER, NOT THE CIRCUIT INTENT. The first cut took an AnalogCircuitIntent, +// which looks harmless because the only field it read was .nets -- but that type carries components, +// and ElectricalComponentInstance is a CLOSED coproduct of resistor, capacitor and independent +// voltage source. A CPU, a BMC, a DDR slot, a regulator or a connector has no variant there, so the +// copper carrier could only have acquired the motherboard as a consumer by making the motherboard +// impersonate a three-part analog board. // // ElectricalNet is already general: its members are component-and-terminal identities, which say -// nothing about what kind of component. Only the intent wrapper was specimen-bound, so the fix is to -// stop taking the wrapper. HOMING IS STILL WRONG and is the declared next step: ElectricalNet, -// NetIdentity and ElectricalTerminalRef are general concepts living in a specimen module, and they -// belong in a connectivity authority that the analog article and this both consume. That migration -// touches the article and its SPICE projection, so it is its own change rather than a rider here. +// nothing about what kind of component. Only the wrapper was specimen-bound. HOMING IS STILL WRONG +// and is the declared next step -- these net concepts live in a specimen module and belong in a +// connectivity authority both the analog article and this consume. fn net_exists(nets: List, net: NetIdentity) -> Bool { count(filter(nets, n => n.identity == net)) > 0 } @@ -161,51 +159,276 @@ fn realizations_of_net(rs: List, net: NetIdentity) -> List filter(rs, r => r.net == net) } -// A NET REALIZED TWICE IS TWO CONDUCTORS CLAIMING ONE NAME. That is not a redundant route - a real -// net split across layers is one realization with vias, which this increment does not yet model - -// so at this grain it is an authority fork in copper and refuses. -// ONE CAUSE PER NET FOR THE NET-GRAIN CAUSE, because a net realized twice is ONE fork however many -// rows are involved. Deriving it from the realization list emitted one cause per row, so a -// doubly-realized net reported two identical causes and a reader counting findings saw two problems -// where one exists - a duplicate wearing the counted-causes policy, and DESIGN section 3 rules a -// duplicate a fork whether or not the copies agree. The row-grain causes stay per-row because theirs -// genuinely are: each realization naming a net the roster lacks is its own row to fix. The net-grain -// cause derives from the roster, and a realization naming a net the roster lacks is still caught by -// RealizationNamesNoSuchNet rather than silently skipped by the narrower iteration. +// A NET REALIZED TWICE ON ONE LAYER IS TWO CONDUCTORS CLAIMING ONE NAME, and that is an authority +// fork in copper rather than a redundant route. A net legitimately present on SEVERAL layers is a +// different fact, carried by InterlayerConnection below and judged by the connectivity refusal - the +// two questions were one check until this increment split them. +// ONE CAUSE PER NET FOR THE NET-GRAIN CAUSES, because those are facts ABOUT A NET rather than about +// a row: a net on four layers with no via is one problem, not four, and two rows on one layer is one +// fork however many rows are involved. Deriving them from the realization list emitted one per row, +// which is a duplicate wearing the counted-causes policy, and DESIGN section 3 rules a duplicate a +// fork whether or not the copies agree. The row-grain causes stay per-row because theirs genuinely +// are: each realization naming a net the schematic lacks is its own row to fix. The net-grain causes +// derive from intent.nets, so the population is the schematic's, and a realization naming a net the +// schematic lacks is still caught by RealizationNamesNoSuchNet rather than silently skipped. fn copper_refusal_causes( nets: List, board: AdmittedStackup, rs: List, + vs: List, ) -> List { let unknown = map( filter(rs, r => !net_exists(nets: nets, net: r.net)), r => RealizationNamesNoSuchNet { net: r.net }, ) let duplicated = map( - filter(nets, n => count(realizations_of_net(rs: rs, net: n.identity)) > 1), - n => NetRealizedMoreThanOnce { net: n.identity }, + filter(nets, n => net_split_is_unrouted(rs: rs, vs: vs, net: n.identity)), + n => NetSplitAcrossLayersWithoutAConnection { net: n.identity }, + ) + let stacked = map( + filter(nets, n => net_has_duplicate_on_one_layer(rs: rs, net: n.identity)), + n => NetHasTwoConductorsOnOneLayer { net: n.identity }, ) let foreign = map( filter(rs, r => r.layer.stackup_authority != admitted_stackup_authority(a: board)), r => RealizationSelectedAgainstAnotherStackup { net: r.net }, ) - unknown + duplicated + foreign + unknown + duplicated + stacked + foreign + interlayer_refusal_causes(nets: nets, board: board, rs: rs, vs: vs) +} + +// A VIA IS A CONDUCTOR BETWEEN TWO LAYERS OF ONE NET. It is what makes a net legitimately present +// on more than one layer, which the previous increment had to refuse outright because it had no way +// to tell a routed layer change from two conductors forking one name. +// +// Both endpoints are CopperLayerRefs, so both inherit the stackup binding: a via cannot join a layer +// of one board to a layer of another, and it cannot name an ordinal that board does not have. +// What the reference cannot carry is the two endpoints being DIFFERENT - that is a relation between +// two values rather than a property of either, so it is a checked refusal, and a via from a layer to +// itself is a drilled hole that connects nothing. +type InterlayerConnection { + net: NetIdentity + from_layer: CopperLayerRef + to_layer: CopperLayerRef +} + +fn interlayer_ordinals(v: InterlayerConnection) -> List { + [copper_layer_ordinal(r: v.from_layer), copper_layer_ordinal(r: v.to_layer)] +} + +fn interlayer_touches_ordinal(v: InterlayerConnection, ordinal: Int) -> Bool { + count(filter(interlayer_ordinals(v: v), o => o == ordinal)) > 0 +} + +fn connections_of_net(vs: List, net: NetIdentity) -> List { + filter(vs, v => v.net == net) +} + +// WHETHER A SPLIT NET IS ONE CONDUCTOR OR SEVERAL ISLANDS. The first cut of this asked only that +// every realized layer be TOUCHED by some connection of the net, and said so honestly: a net on +// layers 0, 1, 2, 3 with connections 0-1 and 2-3 satisfied it while being two electrically separate +// islands, and it admitted. That is the state-space conflation DESIGN section 5 names - "every layer +// is reached by something" and "every layer is reached by the same something" are different facts, +// and the weaker one was standing in for the stronger. +// +// It is now the real question, because the graph is bounded and both endpoints already carry exact +// layer identity: reachability from the net's first realized layer, expanded to a fixpoint over the +// net's own connections, and every realized layer must land in that one component. +// +// WHY THE ITERATION COUNT IS THE REALIZATION COUNT AND NOT A GUESS. Each expansion pass adds at +// least one new ordinal or the set is already closed, and the set can never exceed the number of +// realized layers, so count(on) passes reach the fixpoint for any connection population. The fold is +// over the realization list itself purely to supply that many passes - its elements are unread. +fn ordinal_is_reached(reached: List, ordinal: Int) -> Bool { + count(filter(reached, o => o == ordinal)) > 0 +} + +// One expansion pass: a connection whose one endpoint is already reached contributes its other +// endpoint. Appending only the absent ones keeps the set a set, so the growth bound above holds. +fn expand_reached( + conns: List, + reached: List, +) -> List { + fold_list( + xs: conns, + empty: reached, + cons: fn(acc, c) { + let from = copper_layer_ordinal(r: c.from_layer) + let to = copper_layer_ordinal(r: c.to_layer) + let with_to = if ordinal_is_reached(reached: acc, ordinal: from) && !ordinal_is_reached(reached: acc, ordinal: to) { + acc + [to] + } else { + acc + } + if ordinal_is_reached(reached: with_to, ordinal: to) && !ordinal_is_reached(reached: with_to, ordinal: from) { + with_to + [from] + } else { + with_to + } + }, + ) +} + +fn net_reached_ordinals( + rs: List, + vs: List, + net: NetIdentity, + seed: Int, +) -> List { + let conns = connections_of_net(vs: vs, net: net) + let on = realizations_of_net(rs: rs, net: net) + fold_list( + xs: on, + empty: [seed], + cons: fn(acc, _unused) { expand_reached(conns: conns, reached: acc) }, + ) +} + +// TWO ROWS FOR ONE NET ON ONE LAYER IS THE ORIGINAL FORK, AND NARROWING THE SPLIT REFUSAL LOST IT. +// Before vias, any net with more than one realization refused, which caught this case by accident. +// Replacing that with a via-reachability question asked only whether each REALIZED LAYER is reached +// by a via - and two rows on layer 0 are both on a layer a via reaches, so both passed. Confirmed by +// execution before fixing: a probe with vcc realized twice on layer 0 plus a vcc via 0 to 1 was +// ADMITTED. +// +// The lesson is worth the comment: narrowing a refusal is a deletion, and it silently drops every +// case the old form caught for reasons the new form does not model. Same-layer duplication and +// cross-layer routing are different questions, so they are now two causes rather than one that got +// re-aimed. +// +// The cause carries the net and not the ordinal. Naming WHICH layer is duplicated needs a fold over +// distinct ordinals that this increment does not build, and picking one of them would name a layer +// the model did not establish as the offender. +fn net_has_duplicate_on_one_layer(rs: List, net: NetIdentity) -> Bool { + let on = realizations_of_net(rs: rs, net: net) + count(filter(on, r => + count(filter(on, other => copper_layer_ordinal(r: other.layer) == copper_layer_ordinal(r: r.layer))) > 1 + )) > 0 +} + +// THE REFUSAL, ASKED WITHOUT PICKING A SEED. Rather than extracting a head realization to start +// from - which would need a sentinel for the empty case, and a sentinel here is the absorbing +// fallback DESIGN section 5 forbids - this asks the question from EVERY realized layer and refuses +// if any of them fails to reach all the others. For a connected net every start reaches everything, +// so the two readings agree; for an islanded net every start fails, so the refusal is not sensitive +// to which layer it began from. +fn net_split_is_unrouted(rs: List, vs: List, net: NetIdentity) -> Bool { + let on = realizations_of_net(rs: rs, net: net) + if count(on) <= 1 { + false + } else { + count(filter(on, r => { + let reached = net_reached_ordinals(rs: rs, vs: vs, net: net, seed: copper_layer_ordinal(r: r.layer)) + count(filter(on, other => !ordinal_is_reached(reached: reached, ordinal: copper_layer_ordinal(r: other.layer)))) > 0 + })) > 0 + } +} + +// AN ENDPOINT THAT LANDS ON NO CONDUCTOR IS A HOLE INTO NOTHING. The stackup checks establish that +// an endpoint names a layer this board HAS; they say nothing about whether the net being connected +// is actually realized in copper there. Without this, a VCC connection could terminate on a layer +// carrying no VCC conductor - or sit on an entirely unrouted net - and admission would call it +// harmless, because every check it faced was about the layer rather than about the join. +data no_refusal_causes: List = [] + +fn connection_orphan_endpoints( + rs: List, + v: InterlayerConnection, +) -> List { + let on = realizations_of_net(rs: rs, net: v.net) + let realized = map(on, r => copper_layer_ordinal(r: r.layer)) + fold_list( + xs: interlayer_ordinals(v: v), + empty: no_refusal_causes, + cons: fn(acc, o) { + if ordinal_is_reached(reached: realized, ordinal: o) { + acc + } else { + acc + [InterlayerConnectionEndpointHasNoConductor { net: v.net, ordinal: o }] + } + }, + ) +} + +fn interlayer_refusal_causes( + nets: List, + board: AdmittedStackup, + rs: List, + vs: List, +) -> List { + let unknown = map( + filter(vs, v => !net_exists(nets: nets, net: v.net)), + v => InterlayerConnectionNamesNoSuchNet { net: v.net }, + ) + let foreign = map( + filter(vs, v => + v.from_layer.stackup_authority != admitted_stackup_authority(a: board) + || v.to_layer.stackup_authority != admitted_stackup_authority(a: board)), + v => InterlayerConnectionSelectedAgainstAnotherStackup { net: v.net }, + ) + let degenerate = map( + filter(vs, v => copper_layer_ordinal(r: v.from_layer) == copper_layer_ordinal(r: v.to_layer)), + v => InterlayerConnectionJoinsALayerToItself { net: v.net, ordinal: copper_layer_ordinal(r: v.from_layer) }, + ) + let orphaned = fold_list( + xs: vs, + empty: no_refusal_causes, + cons: fn(acc, v) { acc + connection_orphan_endpoints(rs: rs, v: v) }, + ) + unknown + foreign + degenerate + orphaned +} + +// THE ADMITTED VALUE CARRIES EVERY INPUT ADMISSION JUDGED, not only the realizations. The first cut +// returned the realization list alone while the interlayer connections had been read to decide the +// verdict - so two different connection populations could justify one admitted result, and nothing +// downstream (a renderer, a DRC, a KiCad projection) could recover which joins were supposed to make +// the split nets whole. Evidence that decides a verdict may not vanish across the admission boundary. +// +// The board binding is carried for the same reason it is carried on AdmittedStackup: VCC on one +// board is not the same net as VCC on another, and an admitted result must not be replayable against +// a different board whose net labels happen to agree. +type AdmittedCopper sole_constructor { + board: DeclarationRef + realizations: List + interlayer_connections: List } type CopperAdmission - = CopperAdmitted { realizations: List } + = CopperAdmitted { admitted: AdmittedCopper } | CopperRefused { causes: List } +fn mint_admitted_copper( + board: DeclarationRef, + rs: List, + vs: List, +) -> CopperAdmission + admit_callers: [ + decl_ref(module_path: "product.pcb.copper", decl_name: "admit_copper"), + ] + = CopperAdmitted { admitted: AdmittedCopper { board: board, realizations: rs, interlayer_connections: vs } } + +fn admitted_copper_realizations(a: AdmittedCopper) -> List { + a.realizations +} + +fn admitted_copper_connections(a: AdmittedCopper) -> List { + a.interlayer_connections +} + +fn admitted_copper_board(a: AdmittedCopper) -> DeclarationRef { + a.board +} + fn admit_copper( nets: List, board: AdmittedStackup, rs: List, + vs: List, ) -> CopperAdmission { - let causes = copper_refusal_causes(nets: nets, board: board, rs: rs) + let causes = copper_refusal_causes(nets: nets, board: board, rs: rs, vs: vs) if count(causes) > 0 { CopperRefused { causes: causes } } else { - CopperAdmitted { realizations: rs } + mint_admitted_copper(board: admitted_stackup_authority(a: board), rs: rs, vs: vs) } } diff --git a/dag/test/claim/ci_release_bins_witness_test.dag b/dag/test/claim/ci_release_bins_witness_test.dag index 0f0787c3f4c..d442904b4e5 100644 --- a/dag/test/claim/ci_release_bins_witness_test.dag +++ b/dag/test/claim/ci_release_bins_witness_test.dag @@ -21,7 +21,7 @@ import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly -data ci_release_bins_witness_note: String = "Authority: gunbc.ci_release_bins. Pack membership is derived (floor ∪ witness-declared). Positives: measured gap bins cssl_assemble / frontier_probe_survey are enrolled and appear on the build line. Retirement negative: compile_clean_floor_skip_witness is absent from the roster, release build line, and both generated workflows. RED: no_such_witness_bin_zzz is NOT enrolled, and ensure_built refuses WitnessBinNotEnrolled without cargo (construction wall). Per-claim test fns (no AND-umbrella; #7287 pattern)." +data ci_release_bins_witness_note: String = "Authority: gunbc.ci_release_bins. Pack membership is derived (floor ∪ witness-declared). Positive: the measured gap bin cssl_assemble is enrolled and appears on the build line. frontier_probe_survey was the other measured gap bin and is removed with the self-host frontier roster it surveyed (per-bin justification in gunbc.ci_release_bins), so the positives here are one bin, not two. Retirement negative: compile_clean_floor_skip_witness is absent from the roster, release build line, and both generated workflows. RED: no_such_witness_bin_zzz is NOT enrolled, and ensure_built refuses WitnessBinNotEnrolled without cargo (construction wall). Per-claim test fns (no AND-umbrella; #7287 pattern)." test fn witness_pack_includes_every_floor_invoked() -> Bool { fold( @@ -41,13 +41,11 @@ test fn witness_pack_includes_every_witness_declared() -> Bool { test fn witness_measured_gap_bins_enrolled() -> Bool { release_bin_is_enrolled(bin_name: "cssl_assemble") - && release_bin_is_enrolled(bin_name: "frontier_probe_survey") } test fn witness_build_line_carries_gap_bins() -> Bool { let line = ci_release_build_line() string_contains(s: line, pattern: "--bin cssl_assemble") - && string_contains(s: line, pattern: "--bin frontier_probe_survey") && string_contains(s: line, pattern: "--bin claim_executor") } diff --git a/dag/test/claim/fleet_ssh_credential_verify_witness_test.dag b/dag/test/claim/fleet_ssh_credential_verify_witness_test.dag index ab3b7bc909f..5decce90d94 100644 --- a/dag/test/claim/fleet_ssh_credential_verify_witness_test.dag +++ b/dag/test/claim/fleet_ssh_credential_verify_witness_test.dag @@ -1,7 +1,9 @@ module test.claim.fleet_ssh_credential_verify_witness_test import std.types { NonEmptyStr, String } -import extdeps.ssh { SshPublicKey, Ed25519, Rsa } +import std.content_hash { content_hash_of_value } +import extdeps.ssh { SshPublicKey, Ed25519, Rsa, ssh_public_key_line } +import gunbc.fleet_known_hosts_anchor { fleet_ssh_attempt_identity } import gunbc.fleet_ssh_access { fleet_automation_ssh_key, fleet_automation_ssh_key_fingerprint } import gunbc.fleet_ssh_credential_verify { FleetSshCredentialVerification, @@ -11,6 +13,12 @@ import gunbc.fleet_ssh_credential_verify { expected_public_key_line, classify_derived_public_key_line, classify_agent_key_listing, + AgentSelectorFile, + agent_selector_file_seal, + AgentSelectorMaterialized, + AgentSelectorRefused, + agent_public_selector_path, + agent_public_selector_content, fleet_ssh_credential_verification_refusal_reason, } @@ -169,13 +177,22 @@ test fn derivation_refusal_reason_carries_the_stderr() -> Bool { // ── The agent arm ─────────────────────────────────────────────────────────────────────────────── data subject_socket: NonEmptyStr = "/tmp/gunbc-agent-witness.sock" -data subject_selector: NonEmptyStr = "/tmp/gunbc-fleet-selector.pub" +// The selector is SEALED -- its only production mint is the materializer, which writes the file and +// reads it back. A hermetic witness has no filesystem, so it is admitted explicitly here, exactly as +// the known-hosts anchor admits its own witness fixture. What that buys is that no OTHER module can +// hand `classify_agent_key_listing` a path it merely named. +fn witness_selector_fixture() -> AgentSelectorFile { + agent_selector_file_seal( + path: "/tmp/gunbc-fleet-selector.pub" as NonEmptyStr, + selector_identity: content_hash_of_value(value: "witness-selector" as NonEmptyStr), + ) +} data subject_fingerprint: NonEmptyStr = "SHA256:mGT7qJsh36VsVb8OPh3m8br3oHedQHxRukRkW5P0CoQ" fn classify_agent(succeeded: Bool, stdout: String, stderr: String) -> FleetSshCredentialVerification { classify_agent_key_listing( agent_socket: subject_socket, - public_selector_file: subject_selector, + selector: witness_selector_fixture(), expected_key: subject_key, expected_fingerprint: subject_fingerprint, listing_succeeded: succeeded, @@ -251,6 +268,37 @@ test fn the_declared_fingerprint_is_the_fleet_authority() -> Bool { (fleet_automation_ssh_key_fingerprint as String) == (subject_fingerprint as String) } +// ── The agent selector file ───────────────────────────────────────────────────────────────────── + +// Attempt-owned, for the same reason the known-hosts anchor path is: two concurrent runs must not +// write one another's selector, and a stale file from another attempt must not be readable as this +// one's. +test fn the_selector_path_is_attempt_owned() -> Bool { + match fleet_ssh_attempt_identity(raw: "witness-attempt-a") { + Absent => false + Present { value: a } => match fleet_ssh_attempt_identity(raw: "witness-attempt-b") { + Absent => false + Present { value: b } => { + let pa = agent_public_selector_path(attempt: a) as String + let pb = agent_public_selector_path(attempt: b) as String + pa != pb && string_contains(pa, "witness-attempt-a") && string_contains(pb, "witness-attempt-b") + } + } + } +} + +// The bytes are the authorized_keys line form OpenSSH expects in a public key file, newline included. +test fn the_selector_content_is_the_public_key_line() -> Bool { + agent_public_selector_content(key: subject_key) + == concat(ssh_public_key_line(k: subject_key), "\n") +} + +// It carries the PUBLIC material and nothing else. A selector file is not a place a private key goes. +test fn the_selector_content_carries_the_public_material() -> Bool { + string_contains(agent_public_selector_content(key: subject_key), subject_key.material as String) + && string_contains(agent_public_selector_content(key: subject_key), "ssh-ed25519") +} + // ── The expected line is built from the modeled key, not re-spelled ───────────────────────────── test fn expected_line_is_the_registered_token_then_the_material() -> Bool { diff --git a/dag/test/claim/pcb_copper_witness_test.dag b/dag/test/claim/pcb_copper_witness_test.dag index f8bcbef3c44..c256db198e3 100644 --- a/dag/test/claim/pcb_copper_witness_test.dag +++ b/dag/test/claim/pcb_copper_witness_test.dag @@ -18,14 +18,23 @@ import product.pcb.stackup { } import product.pcb.copper { CopperAdmitted, + CopperLayerRef, CopperRefused, + InterlayerConnection, + InterlayerConnectionEndpointHasNoConductor, + InterlayerConnectionJoinsALayerToItself, + InterlayerConnectionNamesNoSuchNet, + InterlayerConnectionSelectedAgainstAnotherStackup, LayerOutsideStackup, LayerSelected, NetCopperRealization, - NetRealizedMoreThanOnce, + NetHasTwoConductorsOnOneLayer, + NetSplitAcrossLayersWithoutAConnection, RealizationNamesNoSuchNet, RealizationSelectedAgainstAnotherStackup, admit_copper, + admitted_copper_connections, + admitted_copper_realizations, copper_is_complete_over_nets, copper_layer_function, copper_layer_ordinal, @@ -49,6 +58,17 @@ data three_layer: Stackup = Stackup { ], } +// Four coppers, because two islands is the smallest arrangement that distinguishes "every layer is +// touched by a connection" from "every layer is on the same conductor", and that needs 0-1 and 2-3. +data four_layer: Stackup = Stackup { + top: sig, + plies: [ + StackupPly { dielectric: core, copper: gnd }, + StackupPly { dielectric: core, copper: sig }, + StackupPly { dielectric: core, copper: gnd }, + ], +} + data board_authority: DeclarationRef = DeclarationRef { module_path: "test.claim.pcb_copper_witness", decl_name: "three_layer", @@ -60,10 +80,9 @@ data gnd_net: NetIdentity = "GND" as NetIdentity data absent_net: NetIdentity = "SPI_CLK" as NetIdentity // THE FIXTURE IS A BARE NET ROSTER, AND THAT IS THE POINT. Copper takes the nets, not a circuit -// intent, so this witness can hand it a roster that belongs to no analog article at all. If the -// carrier still required an AnalogCircuitIntent, this file would not compile -- which makes the -// decoupling a fact the suite depends on rather than a claim in a comment. The identities are -// motherboard rails rather than the RC specimen's, for the same reason. +// intent, so this witness hands it a roster belonging to no analog article at all. If the carrier +// still required an AnalogCircuitIntent this file would not compile, which makes the decoupling a +// fact the suite depends on rather than a claim in a comment. data board_nets: List = [ ElectricalNet { identity: vcc, members: [] }, ElectricalNet { identity: gnd_net, members: [] }, @@ -198,8 +217,8 @@ test fn w_copper_naming_real_nets_admits() -> Bool { Absent => false Present { value: board } => { let rs = realization_on(net: vcc, ordinal: 0) + realization_on(net: gnd_net, ordinal: 1) - match admit_copper(nets: board_nets, board: board, rs: rs) { - CopperAdmitted { realizations: out } => count(out) == 2 + match admit_copper(nets: board_nets, board: board, rs: rs, vs: []) { + CopperAdmitted { admitted: out } => count(admitted_copper_realizations(a: out)) == 2 CopperRefused { causes: _ } => false } } @@ -215,13 +234,18 @@ test fn w_red_copper_naming_a_net_the_schematic_lacks_is_refused() -> Bool { Present { value: board } => { let rs = realization_on(net: vcc, ordinal: 0) + realization_on(net: absent_net, ordinal: 1) count(rs) == count(board_nets) - && match admit_copper(nets: board_nets, board: board, rs: rs) { - CopperAdmitted { realizations: _ } => false + && match admit_copper(nets: board_nets, board: board, rs: rs, vs: []) { + CopperAdmitted { admitted: _ } => false CopperRefused { causes: c } => count(c) == 1 && count(filter(c, x => match x { RealizationNamesNoSuchNet { net: n } => n == absent_net - NetRealizedMoreThanOnce { net: _ } => false + NetHasTwoConductorsOnOneLayer { net: _ } => false + NetSplitAcrossLayersWithoutAConnection { net: _ } => false + InterlayerConnectionNamesNoSuchNet { net: _ } => false + InterlayerConnectionSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionJoinsALayerToItself { net: _, ordinal: _ } => false + InterlayerConnectionEndpointHasNoConductor { net: _, ordinal: _ } => false RealizationSelectedAgainstAnotherStackup { net: _ } => false })) == 1 } @@ -229,23 +253,28 @@ test fn w_red_copper_naming_a_net_the_schematic_lacks_is_refused() -> Bool { } } -// RED control: one net realized on two layers is two conductors claiming one name. Exactly ONE -// cause, because the problem is a fact about the net rather than about either row -- the same net -// reported twice would be a duplicate finding, not a second one. -test fn w_red_a_net_realized_twice_is_refused() -> Bool { +// RED control: one net on two layers with NO via is two conductors claiming one name. Exactly ONE +// cause, because the problem is a fact about the net rather than about either row - the same net +// reported twice would be a duplicate, not a second finding. +test fn w_red_a_net_split_across_layers_without_a_via_is_refused() -> Bool { match admitted_board(s: three_layer, authority: board_authority) { Absent => false Present { value: board } => { let rs = realization_on(net: vcc, ordinal: 0) + realization_on(net: vcc, ordinal: 2) - match admit_copper(nets: board_nets, board: board, rs: rs) { - CopperAdmitted { realizations: _ } => false + match admit_copper(nets: board_nets, board: board, rs: rs, vs: []) { + CopperAdmitted { admitted: _ } => false CopperRefused { causes: c } => count(rs) == 2 && count(c) == 1 && count(filter(c, x => match x { - NetRealizedMoreThanOnce { net: n } => n == vcc + NetHasTwoConductorsOnOneLayer { net: _ } => false + NetSplitAcrossLayersWithoutAConnection { net: n } => n == vcc RealizationNamesNoSuchNet { net: _ } => false RealizationSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionNamesNoSuchNet { net: _ } => false + InterlayerConnectionSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionJoinsALayerToItself { net: _, ordinal: _ } => false + InterlayerConnectionEndpointHasNoConductor { net: _, ordinal: _ } => false })) == 1 } } @@ -259,9 +288,9 @@ test fn w_an_empty_board_admits_and_covers_nothing() -> Bool { match admitted_board(s: three_layer, authority: board_authority) { Absent => false Present { value: board } => { - match admit_copper(nets: board_nets, board: board, rs: []) { + match admit_copper(nets: board_nets, board: board, rs: [], vs: []) { CopperRefused { causes: _ } => false - CopperAdmitted { realizations: _ } => + CopperAdmitted { admitted: _ } => count(unrealized_nets(nets: board_nets, rs: [])) == 2 && !copper_is_complete_over_nets(nets: board_nets, rs: []) } @@ -290,19 +319,371 @@ test fn w_red_copper_selected_against_another_stackup_is_refused() -> Bool { let native = realization_on(net: vcc, ordinal: 1) count(foreign) == 1 && count(native) == 1 - && match admit_copper(nets: board_nets, board: board, rs: native) { + && match admit_copper(nets: board_nets, board: board, rs: native, vs: []) { CopperRefused { causes: _ } => false - CopperAdmitted { realizations: _ } => - match admit_copper(nets: board_nets, board: board, rs: foreign) { - CopperAdmitted { realizations: _ } => false + CopperAdmitted { admitted: _ } => + match admit_copper(nets: board_nets, board: board, rs: foreign, vs: []) { + CopperAdmitted { admitted: _ } => false CopperRefused { causes: c } => count(filter(c, x => match x { RealizationSelectedAgainstAnotherStackup { net: n } => n == vcc RealizationNamesNoSuchNet { net: _ } => false - NetRealizedMoreThanOnce { net: _ } => false + NetHasTwoConductorsOnOneLayer { net: _ } => false + NetSplitAcrossLayersWithoutAConnection { net: _ } => false + InterlayerConnectionNamesNoSuchNet { net: _ } => false + InterlayerConnectionSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionJoinsALayerToItself { net: _, ordinal: _ } => false + InterlayerConnectionEndpointHasNoConductor { net: _, ordinal: _ } => false })) == 1 } } } } } + +fn layer_of(a: AdmittedStackup, ordinal: Int) -> CopperLayerRef? { + match select_copper_layer(a: a, ordinal: ordinal) { + LayerSelected { layer: l } => Present { value: l } + LayerOutsideStackup { requested: _, layer_count: _ } => none + } +} + +// THE POINT OF THE WHOLE INCREMENT, asserted in BOTH directions in one run: the identical split +// realization refuses with no via and admits with one. If only the admitting half were asserted, a +// refusal that had quietly stopped firing would read as success. +test fn w_a_via_makes_a_split_net_admissible() -> Bool { + match admitted_board(s: three_layer, authority: board_authority) { + Absent => false + Present { value: board } => { + let split = realization_on(net: vcc, ordinal: 0) + realization_on(net: vcc, ordinal: 2) + match layer_of(a: board, ordinal: 0) { + Absent => false + Present { value: top } => + match layer_of(a: board, ordinal: 2) { + Absent => false + Present { value: bottom } => { + let joined = [InterlayerConnection { net: vcc, from_layer: top, to_layer: bottom }] + count(split) == 2 + && match admit_copper(nets: board_nets, board: board, rs: split, vs: []) { + CopperAdmitted { admitted: _ } => false + CopperRefused { causes: _ } => + match admit_copper(nets: board_nets, board: board, rs: split, vs: joined) { + CopperRefused { causes: _ } => false + CopperAdmitted { admitted: out } => count(admitted_copper_realizations(a: out)) == 2 + } + } + } + } + } + } + } +} + +// RED control: a via belonging to a DIFFERENT net does not route this one. Same two layers, same +// count of vias — only the net identity differs, so a check that merely counted vias would pass. +test fn w_red_a_via_on_another_net_does_not_route_this_one() -> Bool { + match admitted_board(s: three_layer, authority: board_authority) { + Absent => false + Present { value: board } => { + let split = realization_on(net: vcc, ordinal: 0) + realization_on(net: vcc, ordinal: 2) + match layer_of(a: board, ordinal: 0) { + Absent => false + Present { value: top } => + match layer_of(a: board, ordinal: 2) { + Absent => false + Present { value: bottom } => { + let wrong_net = [InterlayerConnection { net: gnd_net, from_layer: top, to_layer: bottom }] + match admit_copper(nets: board_nets, board: board, rs: split, vs: wrong_net) { + CopperAdmitted { admitted: _ } => false + CopperRefused { causes: c } => + count(filter(c, x => match x { + NetHasTwoConductorsOnOneLayer { net: _ } => false + NetSplitAcrossLayersWithoutAConnection { net: n } => n == vcc + RealizationNamesNoSuchNet { net: _ } => false + RealizationSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionNamesNoSuchNet { net: _ } => false + InterlayerConnectionSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionJoinsALayerToItself { net: _, ordinal: _ } => false + InterlayerConnectionEndpointHasNoConductor { net: _, ordinal: _ } => false + })) > 0 + } + } + } + } + } + } +} + +// RED control: a via whose endpoints are the same layer is a drilled hole connecting nothing, and +// it reports the ordinal so the author knows which one. +test fn w_red_a_via_from_a_layer_to_itself_is_refused() -> Bool { + match admitted_board(s: three_layer, authority: board_authority) { + Absent => false + Present { value: board } => + match layer_of(a: board, ordinal: 1) { + Absent => false + Present { value: mid } => { + let degenerate = [InterlayerConnection { net: vcc, from_layer: mid, to_layer: mid }] + match admit_copper(nets: board_nets, board: board, rs: realization_on(net: vcc, ordinal: 1), vs: degenerate) { + CopperAdmitted { admitted: _ } => false + CopperRefused { causes: c } => + count(filter(c, x => match x { + InterlayerConnectionJoinsALayerToItself { net: n, ordinal: o } => n == vcc && o == 1 + InterlayerConnectionEndpointHasNoConductor { net: _, ordinal: _ } => false + NetHasTwoConductorsOnOneLayer { net: _ } => false + NetSplitAcrossLayersWithoutAConnection { net: _ } => false + RealizationNamesNoSuchNet { net: _ } => false + RealizationSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionNamesNoSuchNet { net: _ } => false + InterlayerConnectionSelectedAgainstAnotherStackup { net: _ } => false + })) == 1 + } + } + } + } +} + +// RED control: a via inherits the stackup binding through its endpoints, so one selected against +// another board refuses without the via model needing its own check for it. +test fn w_red_a_via_selected_against_another_stackup_is_refused() -> Bool { + match admitted_board(s: three_layer, authority: board_authority) { + Absent => false + Present { value: board } => + match admitted_board(s: other_board, authority: other_authority) { + Absent => false + Present { value: elsewhere } => + match layer_of(a: board, ordinal: 0) { + Absent => false + Present { value: here } => + match layer_of(a: elsewhere, ordinal: 2) { + Absent => false + Present { value: there } => { + let crossed = [InterlayerConnection { net: vcc, from_layer: here, to_layer: there }] + match admit_copper(nets: board_nets, board: board, rs: realization_on(net: vcc, ordinal: 0), vs: crossed) { + CopperAdmitted { admitted: _ } => false + CopperRefused { causes: c } => + count(filter(c, x => match x { + InterlayerConnectionSelectedAgainstAnotherStackup { net: n } => n == vcc + NetHasTwoConductorsOnOneLayer { net: _ } => false + NetSplitAcrossLayersWithoutAConnection { net: _ } => false + RealizationNamesNoSuchNet { net: _ } => false + RealizationSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionNamesNoSuchNet { net: _ } => false + InterlayerConnectionJoinsALayerToItself { net: _, ordinal: _ } => false + InterlayerConnectionEndpointHasNoConductor { net: _, ordinal: _ } => false + })) == 1 + } + } + } + } + } + } +} + +// RED control: TWO CONDUCTORS ON ONE LAYER, WITH A VIA PRESENT. This is the case the split refusal +// stopped catching when it narrowed to via-reachability: both rows sit on layer 0, a vcc via touches +// layer 0, so every realized layer IS via-reached and the routing question is satisfied. It is still +// two rows claiming one net on one layer. Confirmed admitted by a probe before this refusal existed. +test fn w_red_two_conductors_on_one_layer_are_refused_even_with_a_via() -> Bool { + match admitted_board(s: three_layer, authority: board_authority) { + Absent => false + Present { value: board } => { + let dup = realization_on(net: vcc, ordinal: 0) + realization_on(net: vcc, ordinal: 0) + match layer_of(a: board, ordinal: 0) { + Absent => false + Present { value: top } => + match layer_of(a: board, ordinal: 1) { + Absent => false + Present { value: mid } => { + let v = [InterlayerConnection { net: vcc, from_layer: top, to_layer: mid }] + count(dup) == 2 + && match admit_copper(nets: board_nets, board: board, rs: dup, vs: v) { + CopperAdmitted { admitted: _ } => false + CopperRefused { causes: c } => + count(filter(c, x => match x { + NetHasTwoConductorsOnOneLayer { net: n } => n == vcc + NetSplitAcrossLayersWithoutAConnection { net: _ } => false + RealizationNamesNoSuchNet { net: _ } => false + RealizationSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionNamesNoSuchNet { net: _ } => false + InterlayerConnectionSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionJoinsALayerToItself { net: _, ordinal: _ } => false + InterlayerConnectionEndpointHasNoConductor { net: _, ordinal: _ } => false + })) == 1 + } + } + } + } + } + } +} + +// THE CASE THE WEAK FORM ADMITTED. VCC realized on all four layers, joined 0-1 and 2-3: every +// realized layer is touched by a connection of its own net, so the previous reachability question +// answered yes, and the board admitted with two electrically separate VCC islands. This asserts the +// refusal, and w_islands_joined_into_one_conductor_admits asserts the same population admits once +// the two halves are bridged — both directions in one run, so a refusal that stopped firing cannot +// read as success. +test fn w_two_islands_of_one_net_refuse() -> Bool { + match admitted_board(s: four_layer, authority: board_authority) { + Absent => false + Present { value: board } => { + let all = realization_at(board: board, net: vcc, ordinal: 0) + + realization_at(board: board, net: vcc, ordinal: 1) + + realization_at(board: board, net: vcc, ordinal: 2) + + realization_at(board: board, net: vcc, ordinal: 3) + match islanded_connections(board: board) { + Absent => false + Present { value: conns } => + count(all) == 4 + && match admit_copper(nets: board_nets, board: board, rs: all, vs: conns) { + CopperAdmitted { admitted: _ } => false + CopperRefused { causes: c } => + count(filter(c, x => match x { + NetSplitAcrossLayersWithoutAConnection { net: n } => n == vcc + NetHasTwoConductorsOnOneLayer { net: _ } => false + RealizationNamesNoSuchNet { net: _ } => false + RealizationSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionNamesNoSuchNet { net: _ } => false + InterlayerConnectionSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionJoinsALayerToItself { net: _, ordinal: _ } => false + InterlayerConnectionEndpointHasNoConductor { net: _, ordinal: _ } => false + })) > 0 + } + } + } + } +} + +// realization_on is pinned to the three-layer fixture, so it cannot reach ordinal 3. This selects +// against whichever board it is handed, which is what the four-layer cases need. +fn realization_at(board: AdmittedStackup, net: NetIdentity, ordinal: Int) -> List { + match layer_of(a: board, ordinal: ordinal) { + Absent => [] + Present { value: l } => [NetCopperRealization { net: net, layer: l }] + } +} + +fn islanded_connections(board: AdmittedStackup) -> List? { + match layer_of(a: board, ordinal: 0) { + Absent => none + Present { value: l0 } => + match layer_of(a: board, ordinal: 1) { + Absent => none + Present { value: l1 } => + match layer_of(a: board, ordinal: 2) { + Absent => none + Present { value: l2 } => + match layer_of(a: board, ordinal: 3) { + Absent => none + Present { value: l3 } => Present { value: [ + InterlayerConnection { net: vcc, from_layer: l0, to_layer: l1 }, + InterlayerConnection { net: vcc, from_layer: l2, to_layer: l3 }, + ] } + } + } + } + } +} + +// The other direction: bridge the two islands with a third connection and the same four +// realizations admit. Without this, the refusal above could be firing for any reason at all. +test fn w_islands_joined_into_one_conductor_admits() -> Bool { + match admitted_board(s: four_layer, authority: board_authority) { + Absent => false + Present { value: board } => { + let all = realization_at(board: board, net: vcc, ordinal: 0) + + realization_at(board: board, net: vcc, ordinal: 1) + + realization_at(board: board, net: vcc, ordinal: 2) + + realization_at(board: board, net: vcc, ordinal: 3) + match islanded_connections(board: board) { + Absent => false + Present { value: conns } => + match layer_of(a: board, ordinal: 1) { + Absent => false + Present { value: l1 } => + match layer_of(a: board, ordinal: 2) { + Absent => false + Present { value: l2 } => { + let bridged = conns + [InterlayerConnection { net: vcc, from_layer: l1, to_layer: l2 }] + match admit_copper(nets: board_nets, board: board, rs: all, vs: bridged) { + CopperRefused { causes: _ } => false + CopperAdmitted { admitted: out } => + count(admitted_copper_realizations(a: out)) == 4 + && count(admitted_copper_connections(a: out)) == 3 + } + } + } + } + } + } + } +} + +// THE EVIDENCE MUST SURVIVE ADMISSION. Two connection populations that both admit must produce +// admitted values that DIFFER, or the carrier has dropped the evidence it judged. Asserting the +// count alone would be satisfied by a carrier that stored the number and discarded the rows, so this +// also reads a connection back out and checks it names the net it was authored with. +test fn w_admitted_copper_retains_the_connections_it_judged() -> Bool { + match admitted_board(s: three_layer, authority: board_authority) { + Absent => false + Present { value: board } => { + let split = realization_on(net: vcc, ordinal: 0) + realization_on(net: vcc, ordinal: 2) + match layer_of(a: board, ordinal: 0) { + Absent => false + Present { value: top } => + match layer_of(a: board, ordinal: 2) { + Absent => false + Present { value: bottom } => { + let joined = [InterlayerConnection { net: vcc, from_layer: top, to_layer: bottom }] + match admit_copper(nets: board_nets, board: board, rs: split, vs: joined) { + CopperRefused { causes: _ } => false + CopperAdmitted { admitted: out } => { + let back = admitted_copper_connections(a: out) + count(back) == 1 && count(filter(back, c => c.net == vcc)) == 1 + } + } + } + } + } + } + } +} + +// AN ENDPOINT ON A LAYER THE NET DOES NOT OCCUPY. VCC is realized on 0 and 2 and the connection runs +// 0 to 1 — layer 1 exists on this board and the connection names a real net, so every stackup and +// identity check it faces passes. What it does not do is land on VCC copper, and before this refusal +// the board admitted. The net is still split, so the connectivity refusal fires too; this asserts +// the endpoint cause specifically, which is the one that names WHERE the hole goes nowhere. +test fn w_a_connection_endpoint_with_no_conductor_refuses() -> Bool { + match admitted_board(s: three_layer, authority: board_authority) { + Absent => false + Present { value: board } => { + let split = realization_on(net: vcc, ordinal: 0) + realization_on(net: vcc, ordinal: 2) + match layer_of(a: board, ordinal: 0) { + Absent => false + Present { value: top } => + match layer_of(a: board, ordinal: 1) { + Absent => false + Present { value: middle } => { + let dangling = [InterlayerConnection { net: vcc, from_layer: top, to_layer: middle }] + match admit_copper(nets: board_nets, board: board, rs: split, vs: dangling) { + CopperAdmitted { admitted: _ } => false + CopperRefused { causes: c } => + count(filter(c, x => match x { + InterlayerConnectionEndpointHasNoConductor { net: n, ordinal: o } => n == vcc && o == 1 + NetSplitAcrossLayersWithoutAConnection { net: _ } => false + NetHasTwoConductorsOnOneLayer { net: _ } => false + RealizationNamesNoSuchNet { net: _ } => false + RealizationSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionNamesNoSuchNet { net: _ } => false + InterlayerConnectionSelectedAgainstAnotherStackup { net: _ } => false + InterlayerConnectionJoinsALayerToItself { net: _, ordinal: _ } => false + })) == 1 + } + } + } + } + } + } +} diff --git a/dag/test/claim/reference_derived_authored_source_gate_witness_test.dag b/dag/test/claim/reference_derived_authored_source_gate_witness_test.dag index 08c53b6e480..e4acf930e55 100644 --- a/dag/test/claim/reference_derived_authored_source_gate_witness_test.dag +++ b/dag/test/claim/reference_derived_authored_source_gate_witness_test.dag @@ -1,6 +1,6 @@ module test.claim.reference_derived_authored_source_gate_witness_test -data reference_derived_authored_source_gate_witness_note: String = "Discriminating controls for the authored-source gate law inside reference_derived_use_lines (production authority: v1.compiler.emit_rust.reference_derived_candidate_spelled_in_module). Floor compile-clean's witness_layer_roots do not close over src/v1, so this witness cannot import that module without an unresolved-import hard diagnostic; the oracle below is the same total predicate (module_source != \"\" && string_contains) and must stay identical to the production fn. GREEN: a name spelled in module source is admitted. RED: AuthoredTokenOrdinal-shaped over-collection against an http_path-like source that never mentions it is refused — the exact fabrication that previously emitted pub use crate::std_occurrence_binding_candidates::AuthoredTokenOrdinal from std.http_path with no .dag authority. Empty source refuses all (fail-closed). Integration receipt (quiet-hawk): regen without hand-pinning std_http_path.rs on a tree that enrolls occurrence-binding candidates must leave AuthoredTokenOrdinal absent, and the generated stage0 crate must build green. Dissolve-on: (1) derive use-lines from BoundReferenceProvider / P2a candidate-producer — this text-presence gate is interim; (2) floor compile-clean closes over src/v1 for this import OR the predicate lives in a dag-reachable shared module — then delete the local oracle and import the production symbol." +data reference_derived_authored_source_gate_witness_note: String = "Discriminating controls for the authored-source gate law inside reference_derived_use_lines (production authority: v1.compiler.emit_rust.reference_derived_candidate_spelled_in_module). Floor compile-clean's witness_layer_roots do not close over src/v1, so this witness cannot import that module without an unresolved-import hard diagnostic; the oracle below is the same total predicate (module_source != \"\" && string_contains) and must stay identical to the production fn. SCOPE, so this file is not read as the whole gate: reference_derived_candidate_spelled_in_module is the DIRECT arm only. Since Root K the gate decision is reference_derived_candidate_authored, a disjunction of this arm and a variant-induced arm that admits a unit-only enum whose variant is spelled and binds unambiguously back to it; that second arm and its homonym refusal are witnessed separately in reference_derived_variant_induced_parent_gate_witness_test.dag. Extending THIS oracle to cover it would fork the second witness rather than complete this one. GREEN: a name spelled in module source is admitted. RED: AuthoredTokenOrdinal-shaped over-collection against an http_path-like source that never mentions it is refused — the exact fabrication that previously emitted pub use crate::std_occurrence_binding_candidates::AuthoredTokenOrdinal from std.http_path with no .dag authority. Empty source refuses all (fail-closed). Integration receipt (quiet-hawk): regen without hand-pinning std_http_path.rs on a tree that enrolls occurrence-binding candidates must leave AuthoredTokenOrdinal absent, and the generated stage0 crate must build green. Dissolve-on: (1) derive use-lines from BoundReferenceProvider / P2a candidate-producer — this text-presence gate is interim; (2) floor compile-clean closes over src/v1 for this import OR the predicate lives in a dag-reachable shared module — then delete the local oracle and import the production symbol." fn authored_source_gate_oracle(module_source: String, name: String) -> Bool { module_source != "" && string_contains(s: module_source, pattern: name) diff --git a/dag/test/claim/reference_derived_variant_induced_parent_gate_witness_test.dag b/dag/test/claim/reference_derived_variant_induced_parent_gate_witness_test.dag new file mode 100644 index 00000000000..5dc653d5545 --- /dev/null +++ b/dag/test/claim/reference_derived_variant_induced_parent_gate_witness_test.dag @@ -0,0 +1,96 @@ +module test.claim.reference_derived_variant_induced_parent_gate_witness_test + +// Discriminating controls for the variant-induced half of the authored-source gate inside +// reference_derived_use_lines (production authority: v1.compiler.emit_rust +// reference_derived_candidate_authored and reference_derived_variant_induced_parent_spelled). +// +// The mirrored-oracle discipline and its reason are inherited verbatim from the sibling witness +// reference_derived_authored_source_gate_witness_test: floor compile-clean witness_layer_roots do +// not close over src/v1, so this module cannot import the production symbol without an +// unresolved-import hard diagnostic, and the oracle below must stay identical to the production +// predicate. +// +// What this witness establishes is the ADMISSION LAW only. The executed evidence that the law fixes +// the emitter is a separate integration receipt and is deliberately NOT restated here as a claim +// this module proves — it lives in the change that introduced the arm. +// +// Dissolve-on: identical to the sibling witness — derive use-lines from BoundReferenceProvider / +// P2a candidate-producer, at which point the spelling question and both oracles disappear. + +fn authored_source_gate_oracle(module_source: String, name: String) -> Bool { + module_source != "" && string_contains(s: module_source, pattern: name) +} + +fn variant_induced_parent_oracle(module_source: String, enum_name: String, variants: List, variant_to_enum: Map) -> Bool { + variants |> any(vn => + match map_get(variant_to_enum, vn) { + Present { value: parent } => parent == enum_name && authored_source_gate_oracle(module_source: module_source, name: vn) + Absent => false + } + ) +} + +fn candidate_authored_oracle(module_source: String, name: String, variants: List, variant_to_enum: Map) -> Bool { + authored_source_gate_oracle(module_source: module_source, name: name) + || variant_induced_parent_oracle(module_source: module_source, enum_name: name, variants: variants, variant_to_enum: variant_to_enum) +} + +data root_k_module_source: String = "fn kind_of type match n.kind case ComputationNode payload arrow true case wildcard arrow false" + +data node_kind_variants: List = ["ComputationNode", "ValueNode"] + +data unambiguous_variant_to_enum: Map = { + "ComputationNode": "NodeKind", + "ValueNode": "NodeKind" +} + +data homonym_variant_to_enum: Map = { + "Present": "", + "Absent": "" +} + +test fn unspelled_parent_with_spelled_variant_admitted_holds() -> Bool { + authored_source_gate_oracle(module_source: root_k_module_source, name: "NodeKind") == false + && candidate_authored_oracle( + module_source: root_k_module_source, + name: "NodeKind", + variants: node_kind_variants, + variant_to_enum: unambiguous_variant_to_enum, + ) +} + +test fn unspelled_parent_with_no_spelled_variant_refused_holds() -> Bool { + !candidate_authored_oracle( + module_source: root_k_module_source, + name: "Behavior", + variants: ["TransformBehavior", "BranchBehavior"], + variant_to_enum: {"TransformBehavior": "Behavior", "BranchBehavior": "Behavior"}, + ) +} + +test fn homonym_variant_admits_neither_enum_holds() -> Bool { + !candidate_authored_oracle( + module_source: "match r case Present binds value arrow v case Absent arrow zero", + name: "Optional", + variants: ["Present", "Absent"], + variant_to_enum: homonym_variant_to_enum, + ) +} + +test fn unspelled_authored_token_ordinal_still_refused_holds() -> Bool { + !candidate_authored_oracle( + module_source: root_k_module_source, + name: "AuthoredTokenOrdinal", + variants: [], + variant_to_enum: unambiguous_variant_to_enum, + ) +} + +test fn empty_module_source_refuses_all_holds() -> Bool { + !candidate_authored_oracle( + module_source: "", + name: "NodeKind", + variants: node_kind_variants, + variant_to_enum: unambiguous_variant_to_enum, + ) +} diff --git a/dag/test/claim/root4_measure_missing_generics_witness_test.dag b/dag/test/claim/root4_measure_missing_generics_witness_test.dag index 603cc0a55aa..8d16e29c52d 100644 --- a/dag/test/claim/root4_measure_missing_generics_witness_test.dag +++ b/dag/test/claim/root4_measure_missing_generics_witness_test.dag @@ -5,7 +5,7 @@ import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly -data root4_measure_missing_generics_witness_note: String = "Root-4 measure_missing_generics family: a function-generic container argument must preserve its applied arguments through render_rust_decl_type overlay resolution. The executable emitter-level fixtures use deliberately synthetic Root4AppliedCarrier, Root4AliasCarrier, and Root4ZeroArityCarrier names, so they exercise the structural shape without re-declaring the canonical std.measure.Measure authority; canonical Measure behavior is covered by the stamped canonical-seven receipt. The decision is structural (__applied_type_args or resolved-type children), never a type-name check. The combined-state fixture proves that an explicitly empty applied-argument property does not suppress non-empty resolved children. RED controls: w_zero_param_alias_list_param_unchanged preserves the existing closed-alias realization; w_unrelated_zero_param_leaf_unchanged proves a bare leaf without applied or resolved children does not gain arguments." +data root4_measure_missing_generics_witness_note: String = "Root-4 measure_missing_generics family: a function-generic container argument must preserve its applied arguments through render_rust_decl_type overlay resolution. The executable emitter-level fixtures use deliberately synthetic Root4AppliedCarrier, Root4AliasCarrier, and Root4ZeroArityCarrier names, so they exercise the structural shape without re-declaring the canonical std.measure.Measure authority; canonical Measure behavior is covered by the stamped canonical-seven receipt. The decision is structural (__applied_type_args or resolved-type children), never a type-name check. The combined-state fixture proves that an explicitly empty applied-argument property does not suppress non-empty resolved children. RED controls: w_zero_param_alias_use_site_stays_bare pins the closed-alias use site to the bare alias name; w_unrelated_zero_param_leaf_unchanged proves a bare leaf without applied or resolved children does not gain arguments. w_zero_param_alias_use_site_stays_bare previously asserted the OPPOSITE shape -- Rc>>, an alias declared in Rust with no parameters and then applied to three arguments, which rustc refuses as E0107. It was enrolled and green, so the defect had a defender: the emitted declaration pub type ClosedCarrierAlias = Rc>; already carries the substitution, and a use site that re-supplies the definition arguments cannot compile under any reading. The witness now asserts the declaration and the bare use site together, and excludes the applied spelling, so the emitted pair is checked for agreement rather than either half alone." fn w_applied_generic_carrier_preserves_arguments() -> Bool { compile_dag_rust_emit_check( @@ -43,12 +43,12 @@ fn w_empty_applied_property_falls_through_to_resolved_children() -> Bool { ) } -fn w_zero_param_alias_list_param_unchanged() -> Bool { +fn w_zero_param_alias_use_site_stays_bare() -> Bool { compile_dag_rust_emit_check( "module root4_closed_alias\n\ntype ProbeQuantity\ntype ProbeScale\ntype ProbeMagnitude\ntype Root4AliasCarrier { payload: M }\ntype ClosedCarrierAlias = Root4AliasCarrier\n\nfn witness(items: List) -> List {\n items\n}\n", "src/root4_closed_alias.rs", - ["Rc>"], - ["Vec>;", "Rc>"], + ["ClosedCarrierAlias<", "Vec Bool { test fn root4_measure_missing_generics_witness_holds() -> Bool { w_applied_generic_carrier_preserves_arguments() && w_empty_applied_property_falls_through_to_resolved_children() - && w_zero_param_alias_list_param_unchanged() + && w_zero_param_alias_use_site_stays_bare() && w_unrelated_zero_param_leaf_unchanged() } diff --git a/dag/test/claim/root_d_checkpoint_scalar_declared_arity_witness_test.dag b/dag/test/claim/root_d_checkpoint_scalar_declared_arity_witness_test.dag new file mode 100644 index 00000000000..9c48554e85c --- /dev/null +++ b/dag/test/claim/root_d_checkpoint_scalar_declared_arity_witness_test.dag @@ -0,0 +1,39 @@ +module test.claim.root_d_checkpoint_scalar_declared_arity_witness + +import std.types { is_container_type } +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +data root_d_checkpoint_scalar_declared_arity_witness_note: String = "Root D half 2: a leaf whose arity is declared by the single authority (std.types container_type_arity) may never be classified a checkpoint scalar, because the E0109 strip in v1.compiler.05_emit_rust rust_render_checkpoint_scalar_bare removes EVERY type argument from whatever it matches. Before the guard, extdeps.languages.rust.types carried a { dag_name: Witness, target_type: Witness } spelling row, so v2.std.witness.Witness was read as arity 0 and emitted as Rc — rustc E0107 'missing generics for enum Witness'. The positive fixture RED-fails on that emission. The null control keeps the wall it must not break: a genuine arity-0 checkpoint scalar reached with phantom arguments still renders bare (i64, never i64), which is the class rust_checkpoint_scalar_phantom_params_note exists for. Live measurement and localisation: docs/probes/root_d_generic_arity_2026-08-16.md. + +The positive fixture declares its own Witness rather than importing v2.std.witness, and the reason is not cosmetic: the table this witness constrains is keyed on the BARE SPELLING, so the spelling is the load-bearing input and a synthetic name would exercise nothing. This is not a second authority for the concept — the fixture declares a two-arm coproduct with no consumer, and the real declaration keeps its single home in v2.std.witness. It is also why the fixture cannot simply import that module: compile_dag_rust_emit_check compiles a virtual single-module source through the witness-root index, and importing v2.std.witness (or v2.std.node beneath it) refuses with hard diagnostics in that mode, which would make this claim unrunnable rather than red. Dissolve-on: when lookup_checkpoint is re-keyed from a bare String to a resolved declaration identity (eager-deer-389's lane), the spelling stops being the key and this fixture should import the authority instead." + +fn w_declared_arity_leaf_is_not_a_checkpoint_scalar() -> Bool { + compile_dag_rust_emit_check( + "module root_d.witness_arity\n\ntype Witness\n = Holds { value: C }\n | Violates { reason: String }\n\nfn root_d_probe(w: Witness) -> Witness {\n w\n}\n", + "src/root_d_witness_arity.rs", + ["Witness"], + ["-> Rc {", "-> Witness {"] + ) +} + +fn w_arity_zero_checkpoint_scalar_still_strips_phantom_arguments() -> Bool { + compile_dag_rust_emit_check( + "module root_d.checkpoint_scalar\nimport std.integer { Int8 }\n\nfn root_d_scalar_probe(value: Int8) -> Int8 {\n value\n}\n", + "src/std_integer.rs", + ["Compose Bool { + is_container_type(name: "Witness") + && !is_container_type(name: "Int") +} + +test fn root_d_checkpoint_scalar_declared_arity_witness_holds() -> Bool { + w_declared_arity_leaf_is_not_a_checkpoint_scalar() + && w_arity_zero_checkpoint_scalar_still_strips_phantom_arguments() + && w_arity_authority_answers_for_both_fixtures() +} diff --git a/dag/test/claim/self_host_module_behavioral_transport_roster_test.dag b/dag/test/claim/self_host_module_behavioral_transport_roster_test.dag deleted file mode 100644 index 6cffe71ba14..00000000000 --- a/dag/test/claim/self_host_module_behavioral_transport_roster_test.dag +++ /dev/null @@ -1,40 +0,0 @@ -module test.claim.self_host_module_behavioral_transport_roster - -import tools.self_host_module_behavioral_transport_roster { compiler_module_behavioral_transport_roster } -import v2.compiler.self_host.frontier { compiler_frontier_roster } -import v2.std.algebra { fold_list, list_map, contains, unique } -import v2.std.collection { List } -import v2.std.logic { Bool } -import v2.std.text { String } - -data self_host_module_behavioral_transport_roster_construction_doc: String = "Construction-holds cross-check tying the roster (dag/tools/self_host_module_behavioral_transport_roster.dag) back to its single naming authority, v2.compiler.self_host.frontier's compiler_frontier_roster (DESIGN §3 — no second, drifting roster). Every roster row's module_path must name a real frontier row, and no roster row may duplicate another's module_path." - -fn frontier_module_paths() -> List { - list_map(xs: compiler_frontier_roster, f: fn(row) { row.module_path }) -} - -fn roster_module_paths() -> List { - list_map(xs: compiler_module_behavioral_transport_roster, f: fn(cfg) { cfg.module_path }) -} - -fn string_eq(a: String, b: String) -> Bool { - a == b -} - -test fn self_host_module_behavioral_transport_roster_rows_are_frontier_members_holds() -> Bool { - let known = frontier_module_paths() - fold_list( - xs: compiler_module_behavioral_transport_roster, - empty: true, - cons: fn(acc, cfg) { - match acc { - true => contains(xs: known, item: cfg.module_path, eq: string_eq) - false => false - } - } - ) -} - -test fn self_host_module_behavioral_transport_roster_module_paths_unique_holds() -> Bool { - unique(xs: roster_module_paths(), eq: string_eq) -} diff --git a/dag/test/claim/spark_serving_full_plan_witness_test.dag b/dag/test/claim/spark_serving_full_plan_witness_test.dag new file mode 100644 index 00000000000..d189f9b73bd --- /dev/null +++ b/dag/test/claim/spark_serving_full_plan_witness_test.dag @@ -0,0 +1,275 @@ +module test.claim.spark_serving_full_plan_witness_test + +import std.types { Bool, List, NonEmptyStr, String } +import product.placement_supply { HostIdentity } +import gunbc.membership_reconcile { MembershipPlan, membership_write_count } +import gunbc.spark_serving_membership { spark_serving_membership_reconcile } +import gunbc.spark_serving_release { + SparkServingObservation, + SparkServingObserved, + SparkServingAbsent, + SparkServingObservationRefused, + SparkServingReleaseIdentity, + SparkServingOccurrence, + SparkServingRelease, +} +import gunbc.spark_serving_membership { + SparkServingMember, + SparkServingMemberAt, + spark_serving_desired_members, +} +import gunbc.spark_serving_observed_members { + SparkServingObservedUnitState, + UserUnitStateObserved, + UserUnitStateAbsent, + UserUnitStateUnobserved, + SparkServingObservedLingerState, + LingerObservedEnabled, + LingerObservedDisabled, + LingerUnobservedState, + SparkServingObservedMemberProjection, + SparkServingObservedMembers, + SparkServingObservedMembersRefused, + spark_serving_observed_members, + spark_serving_projection_supports_empty_replan, +} +import gunbc.spark_serving_converge_plan { + SparkServingTypedActionProjection, + SparkServingTypedActionsProjected, + SparkServingTypedActionsRefused, + fleet_converge_spark_serving_typed_actions, + spark_serving_desired_linger_member, + SparkServingFullMembershipPlan, + SparkServingFullMembershipPlanReady, + SparkServingFullMembershipPlanRefused, + spark_serving_full_membership_plan, + spark_serving_linger_membership_plan, +} +import gunbc.spark_serving_desired { + SparkServingDesiredAdmission, + SparkServingDesiredAdmitted, + SparkServingDesiredRefused, + spark_serving_desired_admission, + spark_serving_occurrence, +} + +data subject_host: HostIdentity = "srv6" as HostIdentity + +// The subject is the DECLARED release, so these claims move with the real authority rather than a +// fixture that could drift from it. A refused admission has no release to plan against, and the +// witness says so rather than substituting one. +fn subject_release() -> SparkServingRelease? { + match spark_serving_desired_admission { + SparkServingDesiredAdmitted { serving_release: r } => Present { value: r } + SparkServingDesiredRefused { cause: _ } => none + } +} + +fn project( + obs: SparkServingObservation, + unit: SparkServingObservedUnitState, + linger: SparkServingObservedLingerState, +) -> SparkServingObservedMemberProjection { + spark_serving_observed_members(observation: obs, unit: unit, linger: linger) +} + +fn observed_count(p: SparkServingObservedMemberProjection) -> Int { + match p { + SparkServingObservedMembersRefused { cause: _ } => 0 - 1 + SparkServingObservedMembers { members: ms, unit_observed: _ } => length(ms) + } +} + +fn plan_writes(p: SparkServingFullMembershipPlan) -> Int { + match p { + SparkServingFullMembershipPlanRefused { cause: _ } => 0 - 1 + SparkServingFullMembershipPlanReady { plan: plan, unit_observed: _ } => + membership_write_count(plan: plan) + } +} + +fn full_plan_writes( + obs: SparkServingObservation, + unit: SparkServingObservedUnitState, + linger: SparkServingObservedLingerState, +) -> Int { + match subject_release() { + Absent => 0 - 2 + Present { value: r } => + plan_writes( + p: spark_serving_full_membership_plan( + occurrence: spark_serving_occurrence(host: subject_host, serving_release: r), + serving_release: r, + projection: project(obs: obs, unit: unit, linger: linger), + ), + ) + } +} + +fn full_plan_refuses( + obs: SparkServingObservation, + unit: SparkServingObservedUnitState, + linger: SparkServingObservedLingerState, +) -> Bool { + match subject_release() { + Absent => false + Present { value: r } => + match spark_serving_full_membership_plan( + occurrence: spark_serving_occurrence(host: subject_host, serving_release: r), + serving_release: r, + projection: project(obs: obs, unit: unit, linger: linger), + ) { + SparkServingFullMembershipPlanRefused { cause: c } => string_contains(c, "refused") + SparkServingFullMembershipPlanReady { plan: _, unit_observed: _ } => false + } + } +} + +// ── The defect this closes ────────────────────────────────────────────────────────────────────── + +// The declared desired population is four members. This is the denominator every claim below divides +// by, asserted rather than assumed. +test fn the_declared_desired_population_is_four_members() -> Bool { + match subject_release() { + Absent => false + Present { value: r } => + length(spark_serving_desired_members( + occurrence: spark_serving_occurrence(host: subject_host, serving_release: r), + serving_release: r, + )) == 4 + } +} + +// THE KEYSTONE. On a bare host the production plan planned ONE member; the full plan plans four. +// Without this the three unrealized install effects could never be selected however well implemented. +test fn a_bare_host_plans_all_four_members_not_only_linger() -> Bool { + full_plan_writes( + obs: SparkServingAbsent { host: subject_host }, + unit: UserUnitStateAbsent, + linger: LingerObservedDisabled, + ) == 4 +} + +// The contrast, executed rather than asserted in prose: the superseded plan writes exactly one. +test fn the_superseded_linger_plan_writes_exactly_one() -> Bool { + membership_write_count( + plan: spark_serving_linger_membership_plan(host: subject_host, linger_enabled: false), + ) == 1 +} + +// ── Observation, never the desired state ──────────────────────────────────────────────────────── + +// A bare host observes no runtime, unit or model member. If the projection derived observed state +// from the desired release, this would be four and the plan would be empty on a bare machine. +test fn a_bare_host_observes_no_serving_members() -> Bool { + observed_count(p: project(obs: SparkServingAbsent { host: subject_host }, unit: UserUnitStateAbsent, linger: LingerObservedDisabled)) == 0 +} + +// Linger is observed independently, so it is carried even when serving is absent. +test fn linger_is_carried_on_a_bare_host_when_it_is_enabled() -> Bool { + observed_count(p: project(obs: SparkServingAbsent { host: subject_host }, unit: UserUnitStateAbsent, linger: LingerObservedEnabled)) == 1 +} + +// With linger already enabled a bare host needs three writes, not four. +test fn a_bare_host_with_linger_already_enabled_plans_three() -> Bool { + full_plan_writes( + obs: SparkServingAbsent { host: subject_host }, + unit: UserUnitStateAbsent, + linger: LingerObservedEnabled, + ) == 3 +} + +// ── The refusal that must not narrow ──────────────────────────────────────────────────────────── + +// A refused observation may NOT be rendered as an empty observed population: that would plan every +// member as an addition against a host nobody saw. It refuses, and the plan refuses with it. +test fn a_refused_observation_refuses_the_projection() -> Bool { + match project( + obs: SparkServingObservationRefused { host: subject_host, cause: "ssh unreachable" as NonEmptyStr }, + unit: UserUnitStateUnobserved, + linger: LingerUnobservedState, + ) { + SparkServingObservedMembersRefused { cause: _ } => true + SparkServingObservedMembers { members: _, unit_observed: _ } => false + } +} + +test fn a_refused_observation_refuses_the_plan_rather_than_planning_four_writes() -> Bool { + full_plan_refuses( + obs: SparkServingObservationRefused { host: subject_host, cause: "ssh unreachable" as NonEmptyStr }, + unit: UserUnitStateUnobserved, + linger: LingerUnobservedState, + ) +} + +// The refusal names the host, so a fleet-wide run says WHICH host was not seen. +test fn the_projection_refusal_names_the_host() -> Bool { + match project( + obs: SparkServingObservationRefused { host: subject_host, cause: "ssh unreachable" as NonEmptyStr }, + unit: UserUnitStateUnobserved, + linger: LingerUnobservedState, + ) { + SparkServingObservedMembersRefused { cause: c } => + string_contains(c, "srv6") && string_contains(c, "ssh unreachable") + SparkServingObservedMembers { members: _, unit_observed: _ } => false + } +} + +// ── Unobserved is not absent ──────────────────────────────────────────────────────────────────── + +// An unobserved unit is not listed, so it plans as an addition — the same OUTCOME as absent, but the +// two must remain distinguishable because only one of them supports an empty replan. +test fn an_unobserved_unit_does_not_support_an_empty_replan() -> Bool { + !spark_serving_projection_supports_empty_replan( + projection: project(obs: SparkServingAbsent { host: subject_host }, unit: UserUnitStateUnobserved, linger: LingerObservedEnabled), + ) +} + +test fn an_observed_absent_unit_does_support_an_empty_replan() -> Bool { + spark_serving_projection_supports_empty_replan( + projection: project(obs: SparkServingAbsent { host: subject_host }, unit: UserUnitStateAbsent, linger: LingerObservedEnabled), + ) +} + +test fn a_refused_projection_never_supports_an_empty_replan() -> Bool { + !spark_serving_projection_supports_empty_replan( + projection: project( + obs: SparkServingObservationRefused { host: subject_host, cause: "x" as NonEmptyStr }, + unit: UserUnitStateUnobserved, + linger: LingerUnobservedState, + ), + ) +} + +// ── The typed-action projection refuses rather than dropping ──────────────────────────────────── + +// Removing an `Ensured` member is refused by the reconcile, and that refusal used to be ERASED: the +// projection was a flat_map whose `Absent` arm returned the empty list, so the artifact froze fewer +// typed rows than its own plan had actions and reported no diagnostic. Its frequency was zero by +// construction because the only live plan is linger-only and linger always translates -- which is +// exactly why it is worth an executed witness rather than a reading of the code. +fn removal_refusing_plan() -> MembershipPlan { + spark_serving_membership_reconcile( + desired: [], + observed: [spark_serving_desired_linger_member(host: subject_host)], + ) +} + +test fn a_plan_whose_member_cannot_translate_refuses_the_typed_projection() -> Bool { + match fleet_converge_spark_serving_typed_actions(plan: removal_refusing_plan()) { + SparkServingTypedActionsRefused { cause: c } => + string_contains(c, "dropped") && string_contains(c, "1 planned member actions") + SparkServingTypedActionsProjected { rows: _ } => false + } +} + +// The positive control: the ordinary bare-host linger plan still projects, so the refusal above is a +// property of the untranslatable action and not of the projection refusing everything. +test fn an_ordinary_linger_plan_still_projects_its_rows() -> Bool { + match fleet_converge_spark_serving_typed_actions( + plan: spark_serving_linger_membership_plan(host: subject_host, linger_enabled: false), + ) { + SparkServingTypedActionsProjected { rows: rows } => length(rows) == 1 + SparkServingTypedActionsRefused { cause: _ } => false + } +} diff --git a/dag/test/claim/stage0_crate_layout_witness_test.dag b/dag/test/claim/stage0_crate_layout_witness_test.dag index c33a2b955ed..5544f6bdef2 100644 --- a/dag/test/claim/stage0_crate_layout_witness_test.dag +++ b/dag/test/claim/stage0_crate_layout_witness_test.dag @@ -1,26 +1,31 @@ module test.claim.stage0_crate_layout_witness import gunbc.stage0_crate_layout_generated { generated_stage0_dirs, generated_stage0_filenames } -import v2.compiler.self_host.frontier { +import v2.compiler.self_host.stage0_crate_layout { hand_maintained_stage0_dirs, - hand_maintained_stage0_filenames, - compiler_frontier_emitter_produced_count, - compiler_frontier_emitter_produced_stage0_mod_basenames + hand_maintained_stage0_filenames } -import std.types { Bool, Int } +import std.types { Bool } -test fn w_hand_maintained_stage0_filenames_include_self_emitted() -> Bool { - if compiler_frontier_emitter_produced_count() == 0 { - true - } else { - generated_stage0_filenames - |> any(f => f == "v2_compiler_use_site_verdict.rs") - && generated_stage0_filenames - |> any(f => f == "v2_compiler_parse_engine_hooks.rs") - && generated_stage0_filenames - |> any(f => f == "v2_compiler_discovery_enumeration.rs") - } -} +// Two witnesses were deleted here with the self-host frontier roster, and both +// were green by construction rather than by evidence. +// +// w_hand_maintained_stage0_filenames_include_self_emitted opened with +// `if compiler_frontier_emitter_produced_count() == 0 { true }`. That count was +// zero at every commit the witness ever ran under, so the three filename +// assertions inside the else arm had never been evaluated — the witness +// reported a pass without testing anything. +// +// w_self_emitted_derived_count asserted that the emitter-produced basename list +// had the same length as the emitter-produced count. Both sides were derived +// from the same empty roster projection, so it compared zero against zero and +// could not fail while the roster held no EmitterProduced row. +// +// Neither is retired as a claim someone should re-establish elsewhere: their +// subject was the roster's promotion state, and the roster is gone. The two +// witnesses below are the ones that were doing work — they hold the committed +// generated artifact byte-for-byte against the registration rows it derives +// from, which is a live drift wall independent of self-host progress. test fn w_generated_stage0_filenames_match_frontier() -> Bool { generated_stage0_filenames.length() == hand_maintained_stage0_filenames().length() @@ -33,8 +38,3 @@ test fn w_generated_stage0_dirs_match_frontier() -> Bool { && generated_stage0_dirs |> all(d => hand_maintained_stage0_dirs() |> any(g => g == d)) } - -test fn w_self_emitted_derived_count() -> Bool { - compiler_frontier_emitter_produced_stage0_mod_basenames().length() == compiler_frontier_emitter_produced_count() -} - diff --git a/dag/test/claim/systemd_unit_file_witness_test.dag b/dag/test/claim/systemd_unit_file_witness_test.dag new file mode 100644 index 00000000000..df36646b801 --- /dev/null +++ b/dag/test/claim/systemd_unit_file_witness_test.dag @@ -0,0 +1,118 @@ +module test.claim.systemd_unit_file_witness_test + +import std.types { Bool, String, NonEmptyStr } +import extdeps.systemd.unit_file { + SystemdUnitFile, + SystemdUnitDirective, + Description, + After, + Wants, + SystemdServiceDirective, + ServiceType, + ExecStart, + Restart, + Environment, + WorkingDirectory, + SystemdInstallDirective, + WantedBy, + RequiredBy, + systemd_unit_directive_line, + systemd_service_directive_line, + systemd_install_directive_line, + serialize_systemd_unit_file, +} + +fn sample() -> SystemdUnitFile { + SystemdUnitFile { + unit: [ + Description { text: "gunbc Spark serving" as NonEmptyStr }, + After { target: "network-online.target" as NonEmptyStr }, + ], + service: [ + ServiceType { mode: "simple" as NonEmptyStr }, + ExecStart { command: "/opt/x/bin/ollama serve" as NonEmptyStr }, + Restart { policy: "on-failure" as NonEmptyStr }, + ], + install: [WantedBy { target: "default.target" as NonEmptyStr }], + } +} + +// THE KEYSTONE: exact bytes, not a shape or a substring. +// +// This is the file that gets delivered to a host and, byte for byte, the value an already-delivered +// unit is compared against to decide convergence. A `string_contains` check would pass on a file with +// its sections transposed, a missing trailing newline, or CRLF endings -- all of which are real +// systemd failures or permanent false diffs. So the claim is equality with a literal written out +// here independently of the serializer's own composition. +test fn a_unit_file_serializes_to_exactly_these_bytes() -> Bool { + serialize_systemd_unit_file(file: sample()) == + "[Unit]\nDescription=gunbc Spark serving\nAfter=network-online.target\n[Service]\nType=simple\nExecStart=/opt/x/bin/ollama serve\nRestart=on-failure\n[Install]\nWantedBy=default.target\n" +} + +// systemd's parser is line-oriented; a final directive with no newline is the classic silently +// truncated last line. It is also load-bearing for convergence: the observed-vs-rendered byte +// comparison would differ forever against every correctly written file on disk. +test fn the_rendered_unit_file_ends_with_a_newline() -> Bool { + ends_with(s: serialize_systemd_unit_file(file: sample()), suffix: "default.target\n") +} + +// Section order is systemd's, and it is asserted rather than assumed: the sections are three +// separate fields, so nothing about the record's shape forces the emission order. +test fn sections_are_emitted_in_unit_service_install_order() -> Bool { + let out = serialize_systemd_unit_file(file: sample()) + starts_with(s: out, prefix: "[Unit]\n") + && string_contains(out, "\n[Service]\n") + && string_contains(out, "\n[Install]\n") +} + +// An empty section still emits its header. A unit file with no [Install] directives is legitimate +// (a unit started by another unit rather than enabled), and the header's presence is what makes the +// rendered bytes a function of the record alone rather than of which fields happened to be nonempty. +test fn an_empty_section_still_emits_its_header() -> Bool { + serialize_systemd_unit_file( + file: SystemdUnitFile { + unit: [Description { text: "d" as NonEmptyStr }], + service: [], + install: [], + }, + ) == "[Unit]\nDescription=d\n[Service]\n[Install]\n" +} + +// ── The directive names are systemd's, and each is pinned to a distinct constant ──────────────── + +// `ServiceType` renders as `Type=`, NOT `ServiceType=`. The variant is named for what it is in the +// model; the wire name is systemd's. Nothing but an assertion on the literal catches a variant whose +// constructor name leaked into the emitted bytes. +test fn service_type_renders_as_the_type_directive() -> Bool { + systemd_service_directive_line(directive: ServiceType { mode: "notify" as NonEmptyStr }) + == "Type=notify" +} + +test fn each_unit_directive_renders_its_own_systemd_name() -> Bool { + systemd_unit_directive_line(directive: Description { text: "a" as NonEmptyStr }) == "Description=a" + && systemd_unit_directive_line(directive: After { target: "b" as NonEmptyStr }) == "After=b" + && systemd_unit_directive_line(directive: Wants { target: "c" as NonEmptyStr }) == "Wants=c" +} + +test fn each_service_directive_renders_its_own_systemd_name() -> Bool { + systemd_service_directive_line(directive: ExecStart { command: "a" as NonEmptyStr }) == "ExecStart=a" + && systemd_service_directive_line(directive: Restart { policy: "b" as NonEmptyStr }) == "Restart=b" + && systemd_service_directive_line(directive: Environment { assignment: "K=v" as NonEmptyStr }) + == "Environment=K=v" + && systemd_service_directive_line(directive: WorkingDirectory { path: "/d" as NonEmptyStr }) + == "WorkingDirectory=/d" +} + +test fn each_install_directive_renders_its_own_systemd_name() -> Bool { + systemd_install_directive_line(directive: WantedBy { target: "a" as NonEmptyStr }) == "WantedBy=a" + && systemd_install_directive_line(directive: RequiredBy { target: "b" as NonEmptyStr }) + == "RequiredBy=b" +} + +// An `Environment=` value legitimately contains `=`. Splitting on the first separator is the obvious +// wrong implementation, and this pins the whole assignment through. +test fn an_environment_assignment_keeps_its_own_equals_sign() -> Bool { + systemd_service_directive_line( + directive: Environment { assignment: "OLLAMA_HOST=127.0.0.1:11434" as NonEmptyStr }, + ) == "Environment=OLLAMA_HOST=127.0.0.1:11434" +} diff --git a/dag/test/claim/typed_remote_file_converge_witness_test.dag b/dag/test/claim/typed_remote_file_converge_witness_test.dag new file mode 100644 index 00000000000..b2412c50d61 --- /dev/null +++ b/dag/test/claim/typed_remote_file_converge_witness_test.dag @@ -0,0 +1,199 @@ +module test.claim.typed_remote_file_converge_witness_test + +import std.types { Bool, String, NonEmptyStr, FilePath } +import gunbc.file_access { FileTreeScope } +import gunbc.typed_remote_file_write { + TypedRemoteFileWrite, + TypedRemoteFileWriteAdmission, + TypedRemoteFileWriteAdmitted, + TypedRemoteFileWriteAdmissionRefused, + RemoteFileMode, + RemoteFileModeOwnerReadWrite, + RemoteFileModeOwnerReadWriteWorldRead, + TypedRemoteFileConvergence, + TypedRemoteFileConverged, + TypedRemoteFileConvergenceRefused, + remote_file_mode_octal, + typed_remote_file_staging_path, + typed_remote_file_stage_argv, + typed_remote_file_chmod_argv, + typed_remote_file_rename_argv, + typed_remote_file_readback_argv, + classify_typed_remote_file_readback, + typed_remote_file_write_seal, +} + +data unit_dir_scope: FileTreeScope = FileTreeScope { root_path: "/home/gunbc/.config/systemd/user" as NonEmptyStr } + +data subject_path: FilePath = "/home/gunbc/.config/systemd/user/gunbc-serving.service" as FilePath + +data subject_content: String = "[Unit]\nDescription=gunbc serving\n\n[Service]\nExecStart=/usr/bin/true\n" + +fn subject_write() -> TypedRemoteFileWrite? { + match typed_remote_file_write_seal( + path: subject_path, + content: subject_content, + allowed_scope: unit_dir_scope, + ) { + TypedRemoteFileWriteAdmitted { write: w } => Present { value: w } + TypedRemoteFileWriteAdmissionRefused { cause: _ } => none + } +} + +fn converged(c: TypedRemoteFileConvergence) -> Bool { + match c { + TypedRemoteFileConverged { path: _, mode: _ } => true + TypedRemoteFileConvergenceRefused { step: _, reason: _ } => false + } +} + +fn refusal_step(c: TypedRemoteFileConvergence) -> String { + match c { + TypedRemoteFileConverged { path: _, mode: _ } => "converged" + TypedRemoteFileConvergenceRefused { step: s, reason: _ } => s + } +} + +// ── The staging discipline ────────────────────────────────────────────────────────────────────── + +// Atomic rename requires one directory. The staging path is the destination plus a suffix, so it is +// a sibling by construction rather than by a convention someone must maintain. +test fn the_staging_path_is_a_sibling_of_the_destination() -> Bool { + match subject_write() { + Absent => false + Present { value: w } => + typed_remote_file_staging_path(write: w) + == concat(subject_path as String, ".gunbc-staging") + } +} + +// Nothing is ever written directly to the destination: the write step names the STAGING path. +test fn the_stage_step_writes_to_staging_never_the_destination() -> Bool { + match subject_write() { + Absent => false + Present { value: w } => { + let argv = typed_remote_file_stage_argv(write: w) + argv == ["dd", "status=none", concat("of=", typed_remote_file_staging_path(write: w))] + } + } +} + +// `dd status=none`, not `tee`: tee echoes every written byte back over the channel, putting file +// content in the log. The absence of tee here is the claim. +test fn the_stage_step_does_not_echo_content_back() -> Bool { + match subject_write() { + Absent => false + Present { value: w } => { + let argv = typed_remote_file_stage_argv(write: w) + !string_list_contains(xs: argv, wanted: "tee") + && string_list_contains(xs: argv, wanted: "dd") + && string_list_contains(xs: argv, wanted: "status=none") + } + } +} + +// The mode is applied to the STAGED file, before it is published under the destination name. +test fn the_mode_is_set_on_staging_before_the_rename() -> Bool { + match subject_write() { + Absent => false + Present { value: w } => + typed_remote_file_chmod_argv(write: w, mode: RemoteFileModeOwnerReadWriteWorldRead) + == ["chmod", "644", typed_remote_file_staging_path(write: w)] + } +} + +test fn the_rename_moves_staging_onto_the_destination() -> Bool { + match subject_write() { + Absent => false + Present { value: w } => + typed_remote_file_rename_argv(write: w) + == ["mv", "-f", typed_remote_file_staging_path(write: w), subject_path as String] + } +} + +// Read-back interrogates the DESTINATION, not the staging file. Reading back what we just staged +// would prove the rename moved something, not that the destination holds it. +test fn the_read_back_reads_the_destination_not_the_staging_file() -> Bool { + match subject_write() { + Absent => false + Present { value: w } => { + let argv = typed_remote_file_readback_argv(write: w) + argv == ["cat", subject_path as String] + && !string_list_contains(xs: argv, wanted: typed_remote_file_staging_path(write: w)) + } + } +} + +test fn the_two_modes_render_their_octals() -> Bool { + remote_file_mode_octal(mode: RemoteFileModeOwnerReadWrite) == "600" + && remote_file_mode_octal(mode: RemoteFileModeOwnerReadWriteWorldRead) == "644" +} + +// ── The convergence judgment ──────────────────────────────────────────────────────────────────── + +fn classify(succeeded: Bool, stdout: String, stderr: String) -> TypedRemoteFileConvergence { + match subject_write() { + Absent => + TypedRemoteFileConvergenceRefused { step: "fixture", reason: "seal refused" } + Present { value: w } => + classify_typed_remote_file_readback( + write: w, + mode: RemoteFileModeOwnerReadWriteWorldRead, + readback_succeeded: succeeded, + readback_stdout: stdout, + readback_stderr: stderr, + ) + } +} + +// The positive control. Without it every refusal below would pass on a function that never converges. +test fn destination_holding_the_declared_bytes_converges() -> Bool { + converged(c: classify(succeeded: true, stdout: subject_content, stderr: "")) +} + +// THE CLAIM THIS ARM EXISTS FOR: a successful write whose destination holds something else. This is +// exactly what a zero exit from the writing process cannot distinguish, and why RemoteExecAccepted +// was never convergence. +test fn destination_holding_other_bytes_refuses() -> Bool { + !converged(c: classify(succeeded: true, stdout: "[Unit]\nDescription=something else\n", stderr: "")) +} + +// Truncation is the failure a digest-free "it wrote ok" check misses most often. +test fn a_truncated_destination_refuses() -> Bool { + !converged(c: classify(succeeded: true, stdout: "[Unit]\nDescription=gunbc serving\n", stderr: "")) +} + +// Exact comparison, deliberately: normalizing trailing whitespace would let a real difference pass. +test fn a_destination_differing_only_in_trailing_bytes_refuses() -> Bool { + !converged(c: classify(succeeded: true, stdout: concat(subject_content, "\n"), stderr: "")) +} + +// An empty read on a zero exit is not evidence of an empty file being correct — it is not the +// declared content, so it refuses by the same comparison rather than by a special case. +test fn an_empty_destination_refuses() -> Bool { + !converged(c: classify(succeeded: true, stdout: "", stderr: "")) +} + +test fn an_unreadable_destination_refuses_and_is_located_to_read_back() -> Bool { + let c = classify(succeeded: false, stdout: "", stderr: "cat: No such file or directory") + !converged(c: c) && refusal_step(c: c) == "read-back" + && string_contains( + match c { TypedRemoteFileConverged { path: _, mode: _ } => "" TypedRemoteFileConvergenceRefused { step: _, reason: r } => r }, + "No such file or directory", + ) +} + +// ── Path containment still governs ────────────────────────────────────────────────────────────── + +// Convergence does not weaken admission: a path outside the declared scope has no admitted write, so +// no staging path and no steps are ever produced for it. +test fn a_path_outside_the_scope_is_never_admitted() -> Bool { + match typed_remote_file_write_seal( + path: "/etc/systemd/system/evil.service" as FilePath, + content: subject_content, + allowed_scope: unit_dir_scope, + ) { + TypedRemoteFileWriteAdmitted { write: _ } => false + TypedRemoteFileWriteAdmissionRefused { cause: _ } => true + } +} diff --git a/docs/plans/cli-run-hollowing-plan.md b/docs/plans/cli-run-hollowing-plan.md index 038697cc19d..d1fb955d385 100644 --- a/docs/plans/cli-run-hollowing-plan.md +++ b/docs/plans/cli-run-hollowing-plan.md @@ -27,7 +27,7 @@ | Affected-set & diff provenance | `gunbc.ci_spec` selection · `v2.lens.effect_reach` · [module-identity-storage-binding-design.md](module-identity-storage-binding-design.md) | emit-when | Declared `SourceRef` boundary + provenance ingest | | Floor / witness execution | `claim_executor` · `src/v2/workflow/ci_floor_plan.dag` · [witness-realization-plan.md](witness-realization-plan.md) | emit-when | Workflow `host_effect_apply` replaces HAND driver | | Compile-clean shard scope | `tools.dag_compile_clean_scope` · `v2.compiler.compile` | partial | Import-closure authority unified on `module_graph` | -| Regen oracle & self-host scope | `regen_stage0` · `v2.compiler.self_host.frontier` | delete-with-v1 | Wave 4 real-fixpoint cutover (`5-real-fixpoint`) | +| Regen oracle & self-host scope | `regen_stage0` (the `v2.compiler.self_host.frontier` half of this scope is deleted with the roster) | delete-with-v1 | Wave 4 real-fixpoint cutover (`5-real-fixpoint`) | | Host builtin bridge (interpreter seam) | `v1_interpreter` builtins · per-lens `*_live` projections | seed-kernel-retained | Node-tree readers dissolve seams (#5364 class); kernel keeps physics | | Lens census / hygiene host feeds | `v2.lens.*` tables · `non_fold_residue` · `fact_cardinality` | emit-when | Each lens lands node-tree reader or explicit host row retires | | Floor observability & width | `gunbc.floor_materialization` · `dag/std/realization_width.dag` · [realization-measurement-loop.md](realization-measurement-loop.md) | partial | Scheduler emits receipts; HAND timing deletes with floor native routing | diff --git a/docs/plans/discrete-cost-derivation.md b/docs/plans/discrete-cost-derivation.md index 49e9951e6f7..094cb25fee8 100644 --- a/docs/plans/discrete-cost-derivation.md +++ b/docs/plans/discrete-cost-derivation.md @@ -13,7 +13,7 @@ This is not a proposal to overturn that rule. **Both blanket-budget authorities - `gunbc_falsifier_substrate_long_lane_budget_note` — *'Dissolve-on: per-witness declared cost envelopes (the witness-cost-locality admission law, the same trigger `gunbc_ci_fast_lane_rule_note` names) replace every blanket lane budget with declared per-row rows.'* - `long_lane_exclusion_note` (`gunbc.ci_layer_roots`) — *'Dissolve-on: per-witness declared cost envelopes (witness-cost-locality admission law) subsume the dir grain.'* -So the displaced cost is concrete and already priced by the tree: **three live scaffolds are blocked on one missing derivation**, and each additional witness that disappears into `long/` is a row that per-PR CI stops proving while a green CI keeps implying it did (`compiler_frontier_per_module_probe_exclusion_note` states this outright: *'green CI says nothing about survey numbers unless the local recipe below ran'*). The benefit is not an elegant cost algebra; it is retiring a proxy that silently removes coverage. +So the displaced cost is concrete and already priced by the tree: **three live scaffolds are blocked on one missing derivation**, and each additional witness that disappears into `long/` is a row that per-PR CI stops proving while a green CI keeps implying it did (the frontier per-module probe's exclusion note stated this outright — *green CI says nothing about survey numbers unless the local recipe below ran* — and that note has since been deleted with the roster it surveyed, which is the pattern rather than a counterexample to it). The benefit is not an elegant cost algebra; it is retiring a proxy that silently removes coverage. **Priced honestly:** the threshold is also doing real work today and must not be removed before its successor exists. The 5s deadline is a *construction* wall (`long_lane_exclusion_note`: 'the 5s deadline makes an over-budget fast-lane witness unwritable-in-place, so the roster cannot silently grow stale'), and it was the tourniquet for the run-29183446733 wedge — 243 of 270 minutes burned in billed silence. A replacement that is merely more principled but not fail-closed is a regression. diff --git a/docs/plans/effect-namespace-grants.md b/docs/plans/effect-namespace-grants.md index 076d2ee546e..2e41b8d4571 100644 --- a/docs/plans/effect-namespace-grants.md +++ b/docs/plans/effect-namespace-grants.md @@ -127,4 +127,4 @@ This is also what dissolves the **String model↔realization fork** that blocked | Q3 | `AuthScope` — converge into the grant model where it encodes reach, or stay identity-side? | Defer: identity-side for P-A; revisit when a reach-encoding consumer names the cost (avoid speculative convergence). | _pending_ | | Q4 | Doc handoff from #6738 — take into this lane (drop from #6738), or land #6738 first and extend on main? | Take into this lane | **RESOLVED — take into this lane** (operator, earlier: "subsume that doc in your own PR"; "you'll be owning that doc"). #6738's copy is orphaned (session archived); trivial new-file conflict at merge. | -**Sibling thread disposition (origin 2026-07-21; superseded by operator ruling 2026-08-01):** node/subtree visibility was prototyped as `Reference` and `Publish` verbs riding this grant algebra, with publication audiences encoded as `AudienceScopeTree`. That carrier experiment is deleted: neither verb nor the audience tree remains in `std.effect_grant`, and its only consumer `std.visibility_grant` dissolved with the Stage 0 placement gate. This retires the carrier, not publication as a required capability; no replacement publication ontology is selected pending operator design review. The distinct reference-edge question is a separate deferred capability awaiting a concrete consumer, not a consequence of the publication rollback; neither capability alters this doc's landed Read/Write/Execute grant model. → [retired node/subtree carrier experiment](docs/plans/node-subtree-visibility-grants.md) +**Sibling thread disposition (origin 2026-07-21; superseded by operator ruling 2026-08-01):** node/subtree visibility was prototyped as `Reference` and `Publish` verbs riding this grant algebra, with publication audiences encoded as `AudienceScopeTree`. That carrier experiment is deleted: neither verb nor the audience tree remains in `std.effect_grant`, and its only consumer `std.visibility_grant` dissolved with the Stage 0 placement gate. This retires the carrier, not publication as a required capability; no replacement publication ontology is selected pending operator design review. The distinct reference-edge question is a separate deferred capability awaiting a concrete consumer, not a consequence of the publication rollback; neither capability alters this doc's landed Read/Write/Execute grant model. → [retired node/subtree carrier experiment](node-subtree-visibility-grants.md) diff --git a/docs/plans/language-target-self-host-frontier.md b/docs/plans/language-target-self-host-frontier.md index d880530f239..8cb8f5df265 100644 --- a/docs/plans/language-target-self-host-frontier.md +++ b/docs/plans/language-target-self-host-frontier.md @@ -32,7 +32,7 @@ The whole point of exotic-first is that the curly-brace family *confirms* the de | **F2** | VEP (`TargetValueExpressionProjection`) — the general body producer | **partial** (rust: `^rust_token_unwired_{else,loop,match,fat_arrow}`, `v2.extdeps.languages.rust` `rust_value_expression_projection`) · partial (TS: match/loop/bind-in unwired) · **absent** (python, ecmascript) | | **F3** | `BlockEvaluationMode` statement spine (`ValueProducing` vs `StatementSequenced`) | ✓ type exists; TS's `StatementSequenced` arm produces the correct fail-closed refusals | | **F4** | `ProcessProgram` transport + `run_emit_host`; executable identity **bound per extdeps transport row** (`v2.std.host_transport` `HostTransportDescriptor` / `ProcessProgram`), compiler dispatch **generic** (`v2.compiler.emit_host` `process_program_name`) | ✓ done — `HostToolProgram.executable` is carried by the row and generic dispatch returns that value; target-specific work is only to configure a runtime row where one is absent | -| **F5** | self-host frontier runner (`v2.compiler.emit_host` `run_test_claim_module_emit_vs_eval`: emit → build → run → compare-to-eval) | ✓ machinery **for Rust only**, run **OFFLINE** (excluded from discovery). Rust is **not** self-hosted: `v2.compiler.self_host.frontier` `compiler_frontier_emitter_produced_count` is pinned to `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline = 0`; `v2.compiler.self_host.frontier` `compiler_frontier_roster_count` derives the roster size. | +| **F5** | self-host frontier runner (`v2.compiler.emit_host` `run_test_claim_module_emit_vs_eval`: emit → build → run → compare-to-eval) | ✓ machinery **for Rust only**, run **OFFLINE** (excluded from discovery). Rust is **not** self-hosted: `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline` (the roster's `compiler_frontier_emitter_produced_count` is deleted; this is the surviving count of the same fact) is pinned to `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline = 0`; the roster is DELETED, so no roster size derives — `v2.compiler.self_host.emitter_producer_provenance` carries the producer facts that outlived it. | | **F6** | `solve` — **structural** = existing `solve_constraints` / `ConstraintGraph` authority (extend, no fork); **numerical** = *absent* typed gap (finite measure + `TerminationProof`, typed residual-acceptance contract, extdeps solver handler) | **off critical path** — not needed for emit-to-simulator; see solve doc | | **F7** | declaration emission generic over target (`v2.compiler.emit_semantic_decl` `emit_semantic_type_decl`) | ✓ done — the declaration emitter accepts a `TargetModel` and reads its emission bundle through `v2.std.compilers.semantic_decl_emission` `semantic_decl_emission_from_target` | @@ -46,7 +46,7 @@ The whole point of exotic-first is that the curly-brace family *confirms* the de | target | family | current bar (verified) | honest end-state | key deps | stress axis | | --- | --- | --- | --- | --- | --- | -| **rust** | compiled | compiled; bar-c; F2 **partial** (`^rust_token_unwired_{else,loop,match,fat_arrow}`, `v2.extdeps.languages.rust` `rust_value_expression_projection`); F5 emit-vs-eval fixture **OFFLINE** | **`SeedRetained` roster; zero producer-qualified emissions** — `v2.compiler.self_host.frontier` `compiler_frontier_emitter_produced_count` equals `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline = 0`, and `seed_emitter_behavioral_green_count` equals `seed_emitter_behavioral_green_baseline = 0`; reference model, **NOT self-hosted** | F2 completion; F5 self-host generalization | (reference model) | +| **rust** | compiled | compiled; bar-c; F2 **partial** (`^rust_token_unwired_{else,loop,match,fat_arrow}`, `v2.extdeps.languages.rust` `rust_value_expression_projection`); F5 emit-vs-eval fixture **OFFLINE** | **`SeedRetained` roster; zero producer-qualified emissions** — `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline` (the roster's `compiler_frontier_emitter_produced_count` is deleted; this is the surviving count of the same fact) equals `v2.compiler.self_host.emitter_producer_provenance` `emitter_produced_baseline = 0`, and `seed_emitter_behavioral_green_count` equals `seed_emitter_behavioral_green_baseline = 0`; reference model, **NOT self-hosted** | F2 completion; F5 self-host generalization | (reference model) | | **cpp — Phase-0-C** | compiled | bar-c via `cc`, proven by an **OFFLINE** witness in `test/claim/execution/` (excluded from discovery) | bar-c green (offline); self-host N/A at this phase | F5-generalize | (confirms) | | **cpp — full C target** | compiled | **below bar-a** for full C | blocked — needs **monomorphization** (grep-**zero** in tree), **closure conversion**, a **discriminant-tag row kind**, **multi-file (header/impl) projection**, and **ABI/linkage** — none present | monomorphization, closure conversion, tag-row kind, multi-file projection, ABI/linkage | (confirms — hard) | | **go** | compiled | **skeleton** — needs TargetModel buildout | **self-host** (first non-rust self-host — the F5 generalization proof), once built | TargetModel buildout, surface spellings, F5 | **self-host axis** | diff --git a/docs/plans/rc-ownership-wrap-decision-design.md b/docs/plans/rc-ownership-wrap-decision-design.md index 6866f88cd66..4384c996ad3 100644 --- a/docs/plans/rc-ownership-wrap-decision-design.md +++ b/docs/plans/rc-ownership-wrap-decision-design.md @@ -19,6 +19,156 @@ Benign for immutable-value pilot modules (zero emit diagnostics). **Latent fail- Band A flip policy (`frontier_band_a_emit_readiness.dag`) already blocks `parse_engine_hooks` and `discovery_enumeration` until this gate lands. +## R1 — the emitted-crate census, and the correction it forces to the paragraph above (2026-08-17, bold-lark-722) + +The paragraph above says the fail-open is that the emitter *wraps every `shared_types` member*. Measured against a real emitted corpus that is **not what happens**, and the difference decides what a fix may be. This section records the correction, the located root, the two facts a fix has to respect, and what was built in consequence. + +### What was measured, by whom, and on which emitter + +smart-ibex-716 built an emitted-crate census at `M=11` compiler-module entries (`05_emit`, `06_translate`, `04_infer`, `03_ingest`, `emit_host`, `01_tokenize`, `materialization_carriers`, `emit_module`, `03_normalize`, `program_partition`, `05_eval`; head `5e1a73fa33`), using the `docs/probes/curated_cargo_probe_one.sh` invocation contract with `cargo check --message-format=json` so the expected/found pair comes from the span label rather than a text grep. **55** E0308 `Rc` mismatches survive dedup to distinct `(file, line, column, code, signature)`: **28 under-wrapped** (`expected Rc, found T`) and **27 over-wrapped**. **54** of those appear in the `03_ingest` closure, the one tree kept on disk, and **53 of those 54 sit at call-argument position** (1 record literal, 0 signatures). The three totals are three denominators, not an arithmetic error, and one site (`v2_compiler_parse.rs:582:12`) carries **both** signs, so 55 diagnostics do not mean 55 distinct positions. + +**That denominator is keyed on rendered diagnostic text, which is a method hazard with no measured cost to this count.** A proposed `+18` correction to the 55 was published here and is **withdrawn**: `smart-ibex-716` read a `pub type Nat = …` specimen from one module's artifact and applied it to 18 sites in `01_tokenize`, whose `Nat` is an *enum* (`v2_std_nat::Nat`) and whose closure contains no such alias at all. Those sites did not move across a carrier deletion because nothing about their type changed, and `Rc` against `i64` is a full carrier disagreement rather than a wrap decision — so they belong where the census already put them. The `43`-site "one mechanism split by inconsistent rendering" reading is withdrawn with it: the two spellings were two *different* types sharing a leaf name, not one type printed two ways. **The 55/28/27 stands unaltered**, and it is recorded this way rather than quietly reverted because a count that survived a challenge is worth more than one nobody tested. + +The hazard the episode does establish is **real, unmeasured, and not repairable by alias expansion**: the leaf name `Nat` denotes two different types under two different module authorities, and a diagnostic prints both identically. **A census pooled across modules is keyed on a name that is not unique over the population it pools** — so the sound discriminator is resolved type identity *per artifact*, not merely expanded realization. Its extent here is unknown and no number is claimed. None of it bears on the mechanism below, which never reads a printed type name. + +**The emitter under measurement is frozen v1, not v2.** Three independent reads, none of them inference from the emitted files' `v2_*` names (those name the *source* modules, which are v2 `.dag` files): `src/v1/stage0/src` contains `v1_compiler_emit_rust.rs` and **no** `v2_compiler_translate.rs`, so `v2.compiler.06_translate` and `wrap_decision_gate` are not compiled into the `gunbc` binary at all; `build_shared_types` appears in exactly two stage0 files, `v1_compiler_emit_rust.rs` and `v1_compiler_infer_emit_info.rs`; and `cli_run.rs`, the `compile` subcommand's own module, imports `crate::v1_compiler_emit_rust` directly. So `gunbc compile --target rust` is the v1 seed emitter end to end, and every one of the 55 sites is v1 output. This retires, for this census, an earlier cross-lane inference that joined the v2 `rust_sg_rc_use_site_ownership_catalog` position fork to these numbers: that fork is real and is described below as a *separate* finding on the v2 path, but it was dormant while these sites were produced. A fact that fits is not a fact that applies. + +### The root: a type-level fact consumed through occurrence-level keys + +`build_shared_types` computes membership **once per type**, from the type summary — `StructRepr`, or `EnumRepr` with `unit_only == false`, minus grounded-coproduct-native aliases and `is_type_constant`. That is a property of the *type*. + +It is then *consumed* at every occurrence through keys and predicates that are properties of **that occurrence's syntax**, by three seams that do not share an authority: + +1. **Signature.** `v1.compiler.emit_rust` `render_rust_fn_sig_type` selects among six arms on a cascade over `type_node_has_value_variant_arg`, `connective`, children count, `is_container_type`, `rust_fn_sig_peel_closed_alias`, `rust_fn_sig_preserves_authored_alias_leaf`, whether `generic_param_names` is non-empty, and the presence of an `__applied_type_args` property. Three arms wrap; three delegate to `render_rust_decl_type` or `render_rust_type_with_applied_binding`, which never wrap. +2. **Struct field.** `v1.compiler.emit_rust` `emit_struct_field_from_child` wraps iff `rt_child.return_cardinality != CardOptional` **and** `set_contains(shared_types, authored_name_at(rt_child))` — the authored name *at that occurrence's resolved type node*, which is neither the type's identity nor necessarily the name membership was computed under. (Recursion is handled on the preceding, independent `needs_box_wrapping` arm, for sizedness; that arm is not part of this defect.) +3. **General type rendering.** `v1.compiler.emit` `render_node_type` recomputes `shared = set_contains(shared_types, authored_name_at(n))` and applies it on its Disj, Conj-named, Conj-container, bare-leaf, map and single-child arms, while the `type_annotation != none` refined arm and the tuple arms return unwrapped. + +So **one type receives several wrap answers**, selected by how each occurrence happens to be spelled and resolved. Which of those selectors actually fires in the live corpus is a separate question from which ones exist, and the sweep below answers it: seam 2's `authored_name_at` key is the one demonstrably missing, at fourteen field occurrences across ten types. Seams 1 and 3 are named here because they are the same class and are writable, not because this census pins a failure on them — an enclosing-item-genericity reading of seam 1 was predicted and refuted (below). That is §3's single-authority violation in its plainest form — one fact, several representations — and the §5 half is that **no arm refuses**: `render_rust_shared_type_if_needed` returns the unwrapped rendering on a miss, silently, so a disagreement is emitted rather than located. Per §4b this class sits **below the ladder** on the source→Rust-emission path: not mitigatable, not detected, silently wrong until rustc happens to catch it. rustc is not the guarantee; it is the accident that makes this one visible. + +### Why the counts split by sign, and why they are per-type stable + +Per type the answer is mostly stable, so this is two largely disjoint populations rather than one rule oscillating: over-wrapped only — `ScopeRoster` 6, `SubjectRoster` 6, `ConsumerRequirement` 6, `SpanIndex` 7; under-wrapped only — `DecimalDigitsStep` 4, `Edge` 2, `DeriveGrammarRelationTokensProgress` 2, and a long tail of singletons. + +Membership is **not** the discriminator, and this is the measurement that kills the original problem statement: `ScopeRoster`, `SubjectRoster`, `ConsumerRequirement`, `SpanIndex` **and** `DecimalDigitsStep` are all shared types, and they split 28/27 by sign anyway. "The emitter over-wraps `shared_types` members" cannot explain a population that is entirely shared and yet disagrees in both directions. + +#### How narrow the inconsistency actually is + +Two `03_ingest` emits, produced independently on two instruments, were each swept for every type occurring in struct-field position and in `fn` signature position, counting bare against `Rc<…>` occurrences per type — including occurrences **nested inside container types**, which the first pass of this sweep missed by keying only on a field's outermost type. The overwhelming majority of types are perfectly consistent; the inconsistent population is **ten types and fourteen bare field occurrences**, and the two instruments agree on it type for type, count for count, and file-and-line for file-and-line: + +| type | sig `Rc` | sig bare | field `Rc` | field bare | a bare field occurrence | +|---|---|---|---|---|---| +| `Nat` | 197 | 0 | 1 | 4 | `v2_std_verdict.rs:138` — `Nat` | +| `Finding` | 26 | 0 | 0 | 1 | `…copy_analyze.rs:602` — `Rc>` | +| `TerminationProof` | 16 | 0 | 1 | 1 | `v2_compiler_infer.rs:86` — `Rc>` | +| `PortReading` | 16 | 0 | 0 | 1 | `…copy_analyze.rs:430` — `Rc>` | +| `SpanIndex` | 10 | 0 | 1 | 2 | `v2_compiler_parse.rs:80` — `SpanIndex` | +| `Determinism` | 10 | 0 | 0 | 1 | `v2_std_determinism.rs:17` — `Determinism` | +| `ScopeRoster` | 4 | 0 | 0 | 1 | `…standing_intent.rs:75` — `ScopeRoster` | +| `NarrowingReason` | 3 | 0 | 0 | 1 | `…standing_intent.rs:80` — `Rc>` | +| `SubjectRoster` | 2 | 0 | 0 | 1 | `…standing_intent.rs:76` — `SubjectRoster` | +| `ConsumerRequirement` | 1 | 0 | 0 | 1 | `…standing_intent.rs:78` — `ConsumerRequirement` | + +Every row has the **same shape**: wrapped at every signature occurrence without exception, bare at one or more field occurrences, and **zero bare signature occurrences anywhere in the population**. So R1's structural cause is not a broad mis-rule over positions: it is **fourteen bare field occurrences across ten types, where `emit_struct_field_from_child`'s `set_contains(shared_types, authored_name_at(rt_child))` misses while the signature path hits.** + +Two refinements the sweep forced, both recorded because they change what a fix must cover: + +- **The miss also happens at element position inside a container field**, not only at a field's own head. `Rc>` has the container wrapped and the element bare, while every signature mentioning `Finding` says `Rc`. A fix that reconciles only a field's outermost type leaves `Finding`, `PortReading`, `NarrowingReason` and `TerminationProof` untouched. +- **`Witness` is excluded from this population despite matching on a naive read.** It carries 65 bare *signature* occurrences, which no other row has; its cause is the checkpoint-table row asserting a bare target for a generic declaration, a different root. Admitting it would give this population a second mechanism. + +The element-position rows also reclassify work across roots: four diagnostics previously filed under a separate "vector wrap/element shape" bucket are this mechanism at element grain (`expected Rc>>, found Rc>` and three siblings), and they show **both** directions at element grain, which is the one-defect-both-signs reading reproducing at a second grain. + +That narrowness is the finding, and it settles a question left open above: **this is one defect producing both signs, not two mechanisms.** A signature that returns `Rc` feeding a bare field is the **over**; a bare field read into a parameter typed `Rc` is the **under**. One inconsistency, both directions — which is why a fix that makes field membership agree with signature membership should move both counts together, and why a fix that adjusts a position rule instead would not. + +Two earlier position-based readings are retired by this sweep and are recorded as retired rather than deleted, because both were held with confidence and one of them was authored into a doc section: that signature position wraps while field position does not (measured across all shared types in one tree, plain struct fields run 121 wrapped against 5 bare — fields overwhelmingly *do* wrap), and that a shared type inside a generic `fn` or generic struct comes out bare (refuted at 17 of 17 generic signature occurrences and 6 of 6 generic struct-field occurrences, all wrapped). The first was drawn from a sample selected by the failing sites themselves; an error census says where disagreement occurred and never what the majority behaviour is. The second was a prediction from reading the arm cascade, offered for falsification and duly falsified — what survives is that the cascade *has* non-wrapping arms, not that enclosing-item genericity is what selects them. + +`OccurrenceIdAllocator` remains the negative control: not a shared type, bare in both positions, **zero** R1 sites. A type with one answer has no disagreement to have. + +### The discriminating specimen + +One line carries both directions and shows the mechanism without reading the emitter at all: + +``` +v2_compiler_parse.rs:78 pub struct ParseProvenanceState { pub alloc: OccurrenceIdAllocator, pub index: SpanIndex } +v2_std_provenance.rs:61 pub fn span_index_empty() -> Rc +v2_std_provenance.rs:87 pub fn span_index_merge(base: Rc, incoming: Rc) -> Rc + +v2_compiler_parse.rs:582 index: span_index_merge(base.index.clone(), incoming.index.clone()), +``` + +`base.index` is a field, emitted bare `SpanIndex`, passed into a parameter emitted `Rc` — the **under**. The call's `Rc` result is assigned into the bare field `index` — the **over**. One expression, one type, two seams, opposite signs. Any candidate fix should be argued against this line first and the bulk second. + +### Separately: the v2 path carries its own position fork (not the cause of the above) + +On the v2 emit path, which produced none of these sites, `rust_sg_rc_use_site_ownership_catalog` gives `Diagnostics` and `Node` **opposite** layers by position — `OwnershipAtBindingProjection → ReferenceLayerRc`, `OwnershipAtFunctionParameter → ReferenceLayerOwned` — while `TargetOwnershipUseSite` has exactly four inhabitants and **none of them is a call argument**, and `v2.compiler.06_translate` `translate_coerced_with_atom_realization` supplies `OwnershipAtBindingProjection` unconditionally for the generic node fold. So on that path an argument is emitted with the producer-side layer and the callee-parameter question is never asked. Recorded here because it is the same class one authority over and it will produce the same census when the emitter flips; it is **not** evidence for anything measured above, and the two must not be merged into one burn-down. + +### Two constraints on any fix + +**The fix site is inside frozen v1.** Step 3 of the implementation sequence below already records that v2 emit routes through `wrap_decision_gate` with zero `shared_types` references under `src/v2`, and that `gunbc compile --target rust` keeps the seed `shared_types` **until v1 delete (S3)**. Repairing the three seams in `v1.compiler.emit_rust` / `v1.compiler.emit` is therefore completion work on the structure scheduled for deletion — DESIGN §3's consequences (1) and (2) exactly: improvements that die with X, and optimizations Y is later forced to negotiate with. Fixing it in v2 instead cannot be validated against this census, because the v2 emitter did not produce it and cannot be run over that corpus today. **This is an operator/manager disposition, not an implementer's call.** Three options were put: (a) a declared bounded exception to the freeze, (b) treat the sites as a *specification* for the v2 emitter with synthetic discriminating controls in both directions and leave the v1 image red, or (c) fold R1 into the v1 deletion lane as quarry. + +**Ruled (b)** by smart-ram-730, 2026-08-17. (a) was **refused**, on three grounds worth keeping because they generalize: DESIGN §5 puts an exception verdict *outside* the diff and outside the manager, so a manager authoring their own approval is the same forgery as an author authoring it; the frozen-X carve-out requires that no Y can hold the boundary, and the defect is a concept v2 is missing rather than an independent v1 bug; and consequences (1) and (2) apply verbatim to a renderer scheduled for deletion. (a) was escalated to the operator as an open question rather than decided silently. (c) was rejected on the ground that R1 is not un-actionable — it is a specification for a missing concept. + +**What (b) costs, declared rather than discovered later:** the v1 image stays red on these sites, the burn-down is **unmeasurable** until the emitter flips, and the after-measurement is synthetic-control-only. That is a real coverage gap in the acceptance evidence, stated here as a declared one. + +### What landed under (b) + +`v2.compiler.wrap_decision` `wrap_decision_flow_gate` — the flow, not the position, as the decided unit. It projects `wrap_decision_gate` at the producer site and at the consumer site through the **same** authority — one function over one catalog, so no second *opinion* exists to drift — and refuses — typed, located, naming the carrier — when the catalog's own answers for the two positions differ. `wrap_decisions_equal` compares reference *layers*, not merely by-value against by-reference. + +Precisely: this is **two traversals of one catalog**, not one traversal. What it rules out is a divergent authority, not a repeated read. The repeated read is a real cost shape — two folds where a per-carrier policy built once would serve both ends — and it is named rather than waved off as small, per §6. It is not fixed here because that policy carrier is the same carrier change the next rung needs, and building half of it now to save one fold would fork what the transition work has to own; the trigger is that carrier landing. + +**Deliberately not built: a fifth `TargetOwnershipUseSite` inhabitant.** Adding `OwnershipAtCallArgument` would be a fifth position opinion about a defect whose cause is that every position already holds its own. A missing inhabitant is the right fix only when the missing position is the one that should decide; here no position should decide alone. This is also why *53 of 54 at call-argument position* does not locate the defect: that is where rustc points, and the cause is in the field declaration. + +**Rung (§4b), stated with its distance to the ceiling.** This moves the class from silent wrongness — outside the ladder, emitted and compiled and wrong — to **mitigatable**: the line stops with a located refusal. It does **not** reach structural impossibility and must not be read as doing so; the invalid state stays writable, because a catalog may still state different layers at two positions and this function's only answer is to refuse the flow. The next rung is a modeled layer **transition** — `TargetValueExpression` carrying its current layer plus a total raise/lower/refuse over `(from, to)` — at which point an agreeing flow is *derived* rather than checked and the refusal narrows to genuinely unconvertible pairs. That is a carrier change, and model-before-implement puts it ahead of the pipeline edit rather than inside it. + +**Not wired into `06_translate` by this change.** The authority and its executing controls land; wiring the consuming seams is a separate motion with its own evidence. + +**The miss refuses at this authority; the class stays open.** A missing use-site ownership catalog and an absent value-semantics bundle both reach `outcome_rejected` with a typed located diagnostic — absence-as-no-facts has no arm here, and `wrap_decision_flow_missing_row_refuses` drives that arm rather than inferring it. What that does **not** do is close the class: absence-as-no-facts remains writable at other ownership lookups, including a live one in frozen v1 where `map_get(emit_info.ownership_index, …)` answers an `Absent` with `empty_set()` and no refusal — structurally the same shape as `render_rust_shared_type_if_needed` returning the unwrapped rendering on a miss, and an under-wrap producer, which is 28 of the 55. Closing the class means making ownership-absence *unrepresentable* rather than refused — the same modeled layer carrier named as this row's next rung — so widening refusal to N further lookups would add N validations where construction is the answer, which is more of §5's patch, not less. Stated here so the rung is read as what it is: one authority refusing, not a class walled. + +**Evidence, by execution.** Six new witnesses in `wrap_decision_predicate_test.dag`, green, alongside the six pre-existing ones unregressed. Both error directions are drawn from the live rust catalog by varying only flow direction over `Diagnostics`, whose rows already disagree by position (`OwnershipAtBindingProjection → ReferenceLayerRc`, `OwnershipAtFunctionParameter → ReferenceLayerOwned`): binding→param is the over shape, param→binding the under shape, and both must refuse. + +Two mutations were executed rather than asserted, and the profile is **not uniform**, so it is reported as measured: + +| mutation | RED | GREEN | +|---|---|---| +| `wrap_decision_gates_agree` forced `true` | over-wrap, under-wrap, distinct-layer | missing-row, both accept controls | +| `wrap_decisions_equal` made layer-blind | distinct-layer only | everything else | + +The missing-row witness therefore does **not** discriminate this reconciliation — it is a regression control proving an underlying catalog miss still propagates through the flow gate rather than being swallowed by it. Calling it a disagreement control would be rung inflation. The distinct-layer witness earns its place from mutation two: `Rc` against `Box` is a real disagreement that a by-value-versus-by-reference comparison calls agreement, and every other witness passes under that bug. + +### Two-arm artifact diff, and both halves of the prediction that failed + +The claim "this changes no emitted output outside its own module" is the kind that is comfortable to assert and cheap to test, so it was tested. Two emissions of the **same entry** (`03_ingest`), same command, same source roots, same `gunbc` binary — the binary is the compiler and the edits are its `.dag` input, so it is held constant by construction — differing **only** in the commit. `M` is therefore fixed by construction; a corpus census at a different `M` is the right before-arm for a corpus-wide claim and the wrong one for a change-detection question. + +The prediction was written before the run, in both directions: `v2_compiler_wrap_decision.rs` **would** change (gaining the flow-gate functions, losing two note constants); every other file **would not**. + +The whole artifact was diffed — all 177 files, no grep for the shape believed touched, since the hazard is precisely a second consequence the author did not predict. Result: **2 files differ, not 1**, and both halves of the prediction were wrong in detail. + +| file | predicted | actual | +|---|---|---| +| `v2_compiler_wrap_decision.rs` | +4 fns, −2 note constants | +45 lines (4 fns), −1 line — a **glob import** `use …WrapDecision::*` replaced by explicit imports. The note constants are absent from both arms — see the retraction below. | +| `v2_std_cross_tree_resolution.rs` | unchanged | **2 `pub use` lines reordered** — a module this change never touched | + +**RETRACTED — the second file is excluded from attribution, not explained.** An earlier revision of this receipt read the reorder in `v2_std_cross_tree_resolution.rs` as *deterministically caused by this change*, on the strength of a `B vs B′` repeat-emit control returning 0 differing files. That inference is withdrawn. `smart-ibex-716` ran the pure null — same binary, same SHA (detached worktree at `a6bceb6903`), fresh output dir per emission, `--dependency-pool-index primary-precedence` passed, 177 files both times — and obtained **the same file, the same shape, and the same two lines**: `pub use crate::v2_std_qualified_name::{QualifiedName}` and `…{qualified_name_from_dotted_string}` at a different position, with byte count, line count and sorted content identical. A phenomenon the null produces on its own cannot be attributed to a change by a control that merely failed to observe it; two agreeing repeats do not establish that a sometimes-moving thing never moves. The moved pair here is *the same pair*, so the two phenomena are not separable, which was the one test that could have saved the finding. + +Recorded because it is the error this receipt elsewhere warns against: a control can only accumulate failures to refute, so its verdict must be stated as `n`, not as proof. The repeat count in this environment is **n=4 pairs at 0 differing** (`A` vs an SHA-pinned re-take of `A`; `B` vs `B′`; `B` vs `B″`; `B′` vs `B″`), and the closure **does** contain the unstable file, so this is not the vacuous zero. It clears nothing: the file's flip rate was later measured at **4 of 12** on a twelve-emission run, so four pairs miss a genuinely unstable file often, and no repeat count is offered here as a clearing argument. What excludes the file is **membership in the known-unstable set**, not repetition. DESIGN's `v2.std.determinism` open thread names the mechanism a re-export list would take: a Map projection over host-unspecified traversal order, whose generic aliases the determinism lens cannot see. + +The differing files were then re-read with the two line-grain instruments the lane converged on, and the second one **misreported this branch's own subject file**. The per-file sorted-multiset test separates them correctly: `v2_compiler_wrap_decision.rs` is a real content change, `v2_std_cross_tree_resolution.rs` is multiset-identical — a pure reorder. The common-line **relative-order** test, which is meant to subsume it, reported `REORDERED` on *both*. It is wrong about the subject file: that file is a pure **addition** of four functions, and adding code adds copies of high-multiplicity boilerplate lines (`}`, `},`, `} else {`), which a greedy multiplicity cap mis-pairs — so the surviving content lines appear transposed around the mis-paired braces. The verdict only resolved to `SAME-ORDER` after excluding that boilerplate (163 → 163 → 117 → 113 common lines across successive filters), while the genuinely reordered file stayed `REORDERED` at every level (226 → 163 → 144). Both the planted-transposition positive control and the pure-addition negative control behaved correctly at every level, so **the instrument passes its own validation while giving a wrong answer on a real file** — its failing arm is a false *fire*, not a false clear, and it is invisible to synthetic fixtures because a planted transposition in an unmodified file adds no multiplicity. The boilerplate filter used here is a heuristic that can itself hide a reorder *of* boilerplate; the principled form does not depend on a filter at all. The instrument this conclusion rests on is the **diff-based** one: a reorder exists iff some line is both *deleted and added* by an alignment (`SequenceMatcher(autojunk=False)`, deleted ∩ added by min-count). It asks the question directly instead of extracting a common subsequence and comparing two orderings, so it is immune to the whole multiplicity family — every earlier variant was at the mercy of *which copies* got extracted. It reports `SAME-ORDER` for the subject file and `REORDERED` for the re-export file, and it **names the moved lines**: `pub use crate::v2_std_qualified_name::{QualifiedName}` and `…{qualified_name_from_dotted_string}` — one occurrence each. Naming a mover at all requires an argument, because a transposition admits two alignments and a symmetric one has no fact of the matter about which side moved. The operational test is **run the mover set in both directions**: agreement names the movers, disagreement *is* the observable signature of a symmetric transposition, where the honest output is the unordered pair and printing one confident name for an arbitrarily broken tie would be fabricated plausible output inside a measuring instrument. Here forward and reverse return the same two lines, so the naming stands. It stands as a **wager, not an observation**: the two groups are unequal — a block of *two* `qualified_name` re-exports crosses a block of *four* `cross_tree_import_model` lines — and minimality is a cost argument, so if the emitter in fact moved the four-line block the instrument names the two-line group and is confidently wrong. Read it as *the likelier mover*; only the equal-size refusal carries no wager. Two weaker readings taken along the way are recorded only as the route: the boilerplate heuristic (which can hide a reorder *of* boilerplate) and the unique-valued restriction (which cannot see a reorder of *repeated* lines at all, so it is a cross-check and never a clearing instrument). A first-divergence index is not used as evidence here — the planted positive control diverges at the same index as the real one, purely from where it was planted. + +What survives: **the first file's 4-file/8-line substitution half is untouched** — it never rested on the reorder. And the argument the whole-artifact diff was run for survives in weakened form: 177 files, 2 differ, and the one differing file outside the change's subject is a member of the closure's known-unstable set, so it carries no information either way rather than being counted as a caused consequence. + +What this buys is a positive argument rather than an absence: 177 files, 2 differ, 46 lines total, every other byte identical — so if some path had keyed on emitted text this change perturbed, it would have had to surface as some *other* emitted movement, and there is none. A targeted count of the shape believed edited could not have supported that, and would have missed the second file entirely. + +**Retracted from this receipt: any claim about whether prose rows emit.** An earlier revision read the note constants' absence from both arms as evidence that a `data NAME_note: String` row emits nothing. That is the vacuous-closure error this section elsewhere warns about, committed here against its own author: the prose rows existed only on an intermediate commit, so **neither arm ever contained one**, and an absence measured over a closure that never held the shape proves nothing about the shape. Worse, the general form is independently known false — another lane watched a `_note` row appear in generated `.rs`. Whether a prose row emits is a **per-site fact requiring its own two-arm receipt**, and this receipt does not carry one. The prose-to-annotation conversion in this branch is therefore justified by §4c modeling debt alone, which was always its only real argument. + +A related discipline that follows, for anyone converting prose rows: do not convert on a PR whose emission measurement is already banked, since the conversion may itself be an artifact change that invalidates it. + +Two hazards checked and not applicable here, recorded so the next reader need not re-derive them: no `string_contains`/substring predicate over emitted content appears anywhere in this diff, so the emitter-self-match class has no subject; and the emission logs carry real output (`0 blocking, 545 advisory`) rather than a bare exit status, so the exit-0-without-a-compile class does not apply. + +**The acceptance condition is two numbers, never one.** The populations are largely disjoint and oppositely signed, so a fix validated on a sample drawn from one direction will look correct, move about half the population, and make the other half worse. Any candidate must carry a discriminating control **in each direction**, and the after-measurement must show **both** counts falling, reported separately. 28→0 while 27→40 is a regression wearing a burn-down. + +### Status of the reproduction + +The 55-site census and its direction/position breakdown are smart-ibex-716's, on their instrument, and have **not** been independently reproduced — reproducing them needs the `cargo check` half, which was not run here. The emitter-identity reads and the three located seams are this session's, read against `src/v1/05_emit_rust.dag` and `src/v1/05_emit.dag`. The 928-type consistency sweep and the six-type table are this session's, on an independent `03_ingest` emit, and agree with the other instrument where the two overlap (`ParseProvenanceState` at `v2_compiler_parse.rs:78`, `SpanIndex` 10 wrapped signatures against 2 bare fields). So: the root is read-verified *and* corroborated across two independently produced trees; the site counts the acceptance condition is stated in terms of remain single-instrument. Said plainly rather than smoothed over, because those counts are what a burn-down would be judged against. + ## The fork (§3) Three independent opinions on whether to wrap a type in `Rc` / `Box`: diff --git a/docs/plans/self-host-cargo-refusal-root-partition.md b/docs/plans/self-host-cargo-refusal-root-partition.md index af4f81341e1..abccce6336e 100644 --- a/docs/plans/self-host-cargo-refusal-root-partition.md +++ b/docs/plans/self-host-cargo-refusal-root-partition.md @@ -1215,8 +1215,8 @@ cause. |---|---|---|---| | B — algebra/numeric carrier, closure flag | ~~509~~ → **at most 146 repr-shaped (§18)**, and narrower still: sites whose type carries a checkpoint row do not move | `eager-deer-389` | identity-keying design; flip control executed both directions | | C — variant ambiguity sentinel | 167, 113 in one file | `gentle-dove-833` | fix in `src/v1/05_emit_rust.dag`, regen fixed point confirmed twice | -| D — checkpoint arity | 116 = 65 alias + 33 `Witness` | `vivid-wren-870` | `Witness` row deletion ready; alias half entangled with B | -| A — derive/bounds | **unknown; under challenge** | this session | see 12.5 | +| D — checkpoint arity | 116 = 65 alias + 33 `Witness` | half 2 `vivid-wren-870`, half 1 `stern-badger-166` | **both halves LANDED** — half 1 as `bbb52138b25` ([PR #8350](https://github.com/gunb-ai/gunbc/pull/8350)), which also retired an enrolled witness that had been asserting the broken shape; half 2 as `7cfeb6f0fd7` ([PR #8341](https://github.com/gunb-ai/gunbc/pull/8341)), deleting the `Witness` checkpoint-scalar rows so scalar arity derives from its single authority | +| A — derive/bounds | **LANDED**, [PR #8347](https://github.com/gunb-ai/gunbc/pull/8347) merged as `c4e9cc918c5` | this session | see 12.5 for what the diagnosis got wrong on the way | | tail — six mid-sized roots + 62 singletons | 1,874 distinct total | `smart-ibex-716` | partitioned, §11 | **Live collision:** B and D both land on `rust_scalar_checkpoint_render_base`. The split asked for @@ -1241,8 +1241,32 @@ suspicious independent of which trigger scopes what. A's split into CloneSharedR TargetApiRequirement 168 / OwnedDeconstructionRequirement 63 came from the same July TSV that produced two of the dead claims in 12.2. -**A's live size, code mix and cause signatures are requested from §11's instrument. Until they -land, treat A as unpartitioned, not as diagnosed.** +~~**A's live size, code mix and cause signatures are requested from §11's instrument. Until they +land, treat A as unpartitioned, not as diagnosed.**~~ — **SUPERSEDED by the RESOLVED block below; +A is landed, not open.** Struck rather than deleted because the instruction was correct when +written and the paragraph above it records *why* the then-current diagnosis was refused, which is +the part that still governs. + +**RESOLVED 2026-08-17 — and the challenge above was right, which is why what landed is not what +this section proposed.** [PR #8347](https://github.com/gunb-ai/gunbc/pull/8347) merged as +`c4e9cc918c5`: *split the clone-bounds map into the two facts it was answering.* The fix is a +fused-map decomposition, not the coproduct-skip edit the retracted diagnosis pointed at — the skip +is still there and still deliberate, exactly as `trait_derive_emit_item_clone_bound_wf_propagation_note` +defends it. The E0599-vs-E0277 mismatch this section flagged is what kept that edit from being made. + +Two receipts worth keeping, because both were nearly missed: + +- **The landed change needed a stage0 regeneration that was not in the first push.** Four generated + files (`v1_compiler_emit_rust`, `v1_compiler_infer`, `v1_compiler_infer_emit_info`, + `v1_compiler_trait_derive_emit`) were stale against the `.dag` edit; `regen` was green on the + final head, which is the receipt that matters. +- **Two regen runs before that reported a PERFECT FIXED POINT while measuring nothing.** + `ctrl-build --remote` syncs to the *invoking* head, and the fix lived on a different branch, so + the runs compiled a tree that never contained it. A wrong-branch arm is worse than a stale one — + correct SHA, correct binary, correct argv, clean provenance, and every other check passes on it. + Only a subject-presence grep printed beside the verdict (`grep -c` on a construct the change + introduces: 0 in base, >0 in the change arm) distinguishes the two. Anyone regenerating stage0 + for a root fix should print that count next to the fixed-point verdict, always. ### 12.6 Adjacent, landed: the self-host frontier roster is deleted @@ -2317,3 +2341,21 @@ large enough to hide three mechanisms inside one plausible name. **Consequence for anyone measuring the repr cut:** a `RustCorpusRepr` change should be expected to move the repr-shaped sites, at most 146 and possibly fewer — **not 509.** If a receipt shows far less than 509 moving, that is this mis-sizing and not an underperforming cut. + +### 18.3 The measured Root B flip, and one retraction + +`smart-ibex-716` executed the flip in both directions. **What holds, measured:** 211 → 204 errors, +203 → 196 sites, with 195 common, 8 removed and 1 added; containment 0-of-18 disjoint. + +**Retracted in full and recorded so nobody re-derives it:** a reading that 43 sites showed renderer +inconsistency, that 18 sites reassigned from B to R1, and that the two roots were fused. The +specimen behind it was read from a different module's artifact. Nothing from that reading reached a +carrier. + +**What survives from it is worth more than the retracted claim.** The leaf name `Nat` denotes two +different types under two module authorities — `01_tokenize`'s is an enum, not the algebra alias — +so **a census pooled across modules is keyed on a name that is not unique over the population it +pools.** That is §18.2's failure one level deeper: grouping by a type name is unsound not only +because a name says involvement rather than mechanism, but because the same name may not denote one +type at all. Key on resolved type identity per artifact, never on the printed name, and allow a site +to carry more than one root. diff --git a/docs/plans/v2-self-hosting.md b/docs/plans/v2-self-hosting.md index b1a0eee4b93..4e14443474b 100644 --- a/docs/plans/v2-self-hosting.md +++ b/docs/plans/v2-self-hosting.md @@ -1,6 +1,6 @@ # Plan — v2 self-hosting -**Status:** planning tracker for the **Weak Self Host -> Strong Self Host** program (operator-signed 2026-07-11, manager: sharp-bee-290) · **DESIGN.md + the carriers remain the authority** (DESIGN §6). A task's real state is its branch/PR, not this file. Linked from `ROADMAP.md` §1 *Get off v1*. The **typed self-host frontier carrier** (`src/v2/compiler/self_host/frontier.dag`) holds the live roster and per-module gap breakdown; this doc is the wave sequencer only. Related: [namespace-resolution-design.md](namespace-resolution-design.md) · [general-body-producer-design.md](general-body-producer-design.md) · [s2-v2-self-emit-direction.md](s2-v2-self-emit-direction.md) · [decl-emission-defork-design.md](decl-emission-defork-design.md) · [dag-v2-defork-audit.md](dag-v2-defork-audit.md) · [seed-shrink-census.md](seed-shrink-census.md) · [typescript-gap-census.md](typescript-gap-census.md) · [emitted-crate-partition-design.md](emitted-crate-partition-design.md) · [c-linkage-unit-realization-design.md](c-linkage-unit-realization-design.md) (the C realization of the same target-agnostic `CompilationUnit` shape self-host emission is built on — the 2nd realization, staffed to stress-test that the shape doesn't cement Rust's acyclic-linkage assumption). +**Status:** planning tracker for the **Weak Self Host -> Strong Self Host** program (operator-signed 2026-07-11, manager: sharp-bee-290) · **DESIGN.md + the carriers remain the authority** (DESIGN §6). A task's real state is its branch/PR, not this file. Linked from `ROADMAP.md` §1 *Get off v1*. **THE 27-ROW ROSTER CARRIER IS DELETED** (`src/v2/compiler/self_host/frontier.dag`, cut 2026-08-17): it was a hand-authored denominator that no consumer derived, and DESIGN §3's delete-first ruling says a superseded authority comes out at the root rather than being maintained while it dies. This doc is the wave sequencer only; **it no longer has a roster carrier to point at**, and the per-module dispositions it used to defer to must be re-derived from the emitter rather than re-authored. Surviving self-host authorities: `v2.compiler.self_host.emitter_producer_provenance` (which producer emitted a module), `v2.compiler.self_host.stage0_crate_layout` (crate partition), `v2.compiler.self_host.v2_emitter_direct_rust_door_contract` (the emit door). Related: [namespace-resolution-design.md](namespace-resolution-design.md) · [general-body-producer-design.md](general-body-producer-design.md) · [s2-v2-self-emit-direction.md](s2-v2-self-emit-direction.md) · [decl-emission-defork-design.md](decl-emission-defork-design.md) · [dag-v2-defork-audit.md](dag-v2-defork-audit.md) · [seed-shrink-census.md](seed-shrink-census.md) · [typescript-gap-census.md](typescript-gap-census.md) · [emitted-crate-partition-design.md](emitted-crate-partition-design.md) · [c-linkage-unit-realization-design.md](c-linkage-unit-realization-design.md) (the C realization of the same target-agnostic `CompilationUnit` shape self-host emission is built on — the 2nd realization, staffed to stress-test that the shape doesn't cement Rust's acyclic-linkage assumption). > **END GOAL (decided 2026-06-21 — anchored in ROADMAP §1, do not re-litigate).** `.dag` is the authority/truth; **v2 emits BOTH Rust AND TypeScript as first-class realizations** (not one-or-the-other). Rust is the active seed language today; TypeScript joins the fixed point **after Rust self-host lands** (ROADMAP `5-ts-first-class` — deferred, not dropped). Each realization is proven **by execution**: self-emitted modules compile cargo-green and are **behaviorally equivalent** to the v1 seed on a discriminating corpus (green-by-execution + a discriminating RED, DESIGN §5). **Byte-identity with the seed is explicitly NOT the goal** (operator, 2026-07-08). The seed shrinks across a **typed self-host frontier** (DESIGN §7): each of the 27 compiler modules is *self-emitted* or *seed-retained* with a reason + migration trigger — countable, prioritizable, never a silent escape hatch. **Terminal (Wave 4):** hand-written compiler logic -> 0; a pinned, content-addressed, v2-emitted bootstrap kernel survives (~8-15k LOC). @@ -10,7 +10,7 @@ Historical receipts through 2026-06-23 (Track A/B/T/Z, session-era drift finding ## 0. State of play -- **0/27 self-host-green — FIRM.** `compiler_frontier_self_emitted_baseline = 0` on the 27-row roster (#6445). No compiler module is self-emitted with a green behavioral-equivalence receipt today. +- **No compiler module is self-emitted with a green behavioral-equivalence receipt today.** That statement survives the roster cut; the way it used to be *counted* does not. `compiler_frontier_self_emitted_baseline = 0` on a hand-authored 27-row roster (#6445) is deleted along with the carrier — the denominator was authored, not discovered, so `0/27` measured the roster's opinion of how many modules exist rather than the corpus. Do not restore a numerator/denominator here: the honest replacement is a derived one, and until it exists this row is a qualitative claim, stated as such. - **Emit surface is the dominant blocker — FIRM (qualitative).** The long pole is Rust emit-surface completeness (body producer, value-expression wiring, decl emit), not front-end parse/resolve. Per-module class breakdown is **not** transcribed here — see §2. - **Wave 1 — IN FLIGHT.** Emit-surface + naming foundation; highest risk; no v1 deleted in this wave. - **Front-end + emit infrastructure — background facts (not active tracks).** `src/v2/` is 100% `.dag`; full pipeline present. Route-A cargo-green landed (#5777/#5873); CI `dag_compile_clean` + `regen --verify` (#5873). Multi-target emitter: one `fold_node` catamorphism, 14+ targets. @@ -23,8 +23,8 @@ Operator-signed 2026-07-11. Each wave is a **dependency-gated exit** (green-by-e The old 2-wave plan collapsed here: "Wave 2 = the sweep" hid the emit-surface keystone. Exit gate — **all** must be green-by-execution before Wave 2 opens: -1. **General body producer emits REAL ingested fn bodies** — RECEIPT LANDED (#6558 body producer + #6526/#6523 fast+long witnesses). Residual explicitly NOT proven by those witnesses: Stage D MVP subsumption, FLAG D binding-key re-grounding, frontier probe per-module receipts, FLAG E body_lowering_fold dissolution. -2. **Namespace SymbolIndex / tree-resolution lands** — RECEIPT LANDED (#6523 gate-2 witnesses + #6538 scaling receipt). Residual: 03_name_resolve/03_resolve end-to-end ingest wire + frontier probe blocker_class rows. +1. **General body producer emits REAL ingested fn bodies** — RECEIPT LANDED (#6558 body producer + #6526/#6523 fast+long witnesses). Residual explicitly NOT proven by those witnesses: Stage D MVP subsumption, FLAG D binding-key re-grounding, FLAG E body_lowering_fold dissolution. (A fourth residual, `frontier probe per-module receipts`, is retired rather than outstanding: the probe survey is deleted with the roster cut.) +2. **Namespace SymbolIndex / tree-resolution lands** — RECEIPT LANDED (#6523 gate-2 witnesses + #6538 scaling receipt). Residual: 03_name_resolve/03_resolve end-to-end ingest wire. (The `frontier probe blocker_class rows` half is retired with the roster cut, not outstanding.) 3. **FLAG D binder identity grounded** — RECEIPT LANDED (#6575). EnvironmentBindingKey re-grounding on identity; `bind_eval_occurrence_identity_defect` witnesses green; conform-now protocol closed ([general-body-producer-design.md](general-body-producer-design.md) §9). 4. **Weak self-host behavioral receipt green** — RECEIPT LANDED (#6578). `dag/tools/self_host_logic_behavioral_transport.dag` emit→compile→run→equals-seed chain green-by-execution for `dag/std/logic.dag` (plain + `--inject-fault` RED control). @@ -36,7 +36,7 @@ The two big emit-surface tracks (~11 modules) **self-emit + behaviorally verify ### Wave 3 — remaining module drain -Remaining ~13 roster modules flip to self-emitted **or** are declared **pinned-kernel** rows with an honest reason + migration trigger. Exit: **27/27 self-emitted-or-declared-kernel** = **strong self-host** milestone. +Every remaining compiler module flips to self-emitted **or** is declared a **pinned-kernel** row with an honest reason + migration trigger. The exit used to read `27/27 self-emitted-or-declared-kernel`; that fraction is retired with the roster carrier, because both halves came from the same hand-authored row list. **The exit condition is unchanged in substance and now needs a derived denominator to state it against** — an emitter-side census of what the compiler actually consists of, not a re-authored list. Naming that derivation is the first Wave 3 obligation. ### Wave 4 — collapse to kernel + delete v1 @@ -48,10 +48,9 @@ Remaining ~13 roster modules flip to self-emitted **or** are declared **pinned-k ## 2. Census honesty — what is firm vs carrier-held -- **FIRM:** 0/27 self-emitted (`compiler_frontier_self_emitted_baseline`, census witnesses on `frontier.dag`). -- **FIRM (qualitative):** emit surface is the dominant blocker class across the roster. -- **Carrier-held (do not transcribe counts in this doc):** per-module gap classification lives on `src/v2/compiler/self_host/frontier.dag` as the 27-row roster's `SeedRetained { reason, migration_trigger }` dispositions plus `compiler_frontier_census_attribution: ExecutionMeasured` — **the carrier holds the numbers; this doc points at the carrier** (DESIGN §2/§6: no parallel-ledger doc). -- **LANDED mechanism (#6464):** structural census + fail-closed classifier on `frontier.dag`; per-module `frontier_probe_emit_from_ingest` execution receipts bind via `frontier_probe_survey` host transport — overlay manifest must not append trailing imports post-namespace-wave (header-only import rule). +- **FIRM (qualitative):** emit surface is the dominant blocker class. This is the one census claim that survived the cut, because it never depended on the roster's row count. +- **WAS carrier-held, now unheld.** Per-module gap classification lived on the deleted `frontier.dag` as 27 `SeedRetained { reason, migration_trigger }` rows plus `compiler_frontier_census_attribution: ExecutionMeasured`. The pointing-at-a-carrier discipline (DESIGN §2/§6: no parallel-ledger doc) is unchanged and is *why* nothing was transcribed back into this doc when the carrier went — a plan that answers a question its authority no longer answers is the parallel ledger that rule forbids. The gap is declared, not filled. +- **RETIRED mechanism (was #6464):** the structural census, its fail-closed classifier, and the `frontier_probe_emit_from_ingest` / `frontier_probe_survey` host-transport receipts are deleted with the roster. The survey never produced a receipt on any host, including a dedicated runner, so what is lost is machinery rather than evidence — read emitter refusals by driving emission directly. ## 3. Import-deletion ladder (parallel track — NOT a wave gate) @@ -76,4 +75,4 @@ Related: [S2 — v2 emits v2: strategic direction & decomposition](s2-v2-self-em ## Dissolution trigger (DESIGN §6) -Delete this doc when Wave 4 lands: pipeline on emitted Rust, import grammar deleted, v1 collapsed to pinned kernel, CI compile cone gone. The frontier carrier + absent v1 compiler logic are the authority; this tracker is redundant. +Delete this doc when Wave 4 lands: pipeline on emitted Rust, import grammar deleted, v1 collapsed to pinned kernel, CI compile cone gone. Absent v1 compiler logic is the authority at that point; this tracker is redundant. (The frontier carrier this condition used to name was deleted 2026-08-17 — it is not a retirement input any more.) diff --git a/docs/probes/diff_frontier_declared_vs_survey.sh b/docs/probes/diff_frontier_declared_vs_survey.sh deleted file mode 100755 index 221b8617b56..00000000000 --- a/docs/probes/diff_frontier_declared_vs_survey.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env bash -# Compare declared frontier.dag measured_probe facts against an independent survey TSV. -# Refuses (non-zero exit) on mismatch — oracle on each side, never writes rows. -# SCAFFOLD — dissolve-on: totality-wall witness binds roster↔manifest without this shell diff. -set -euo pipefail - -ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" -FRONTIER="$ROOT/src/v2/compiler/self_host/frontier.dag" -TSV="${1:-$ROOT/docs/probes/frontier_probe_exact_head_survey_2026-08-03.tsv}" - -if [[ ! -f "$TSV" ]]; then - echo "diff_frontier_declared_vs_survey: missing TSV: $TSV" >&2 - exit 2 -fi -if [[ ! -f "$FRONTIER" ]]; then - echo "diff_frontier_declared_vs_survey: missing frontier: $FRONTIER" >&2 - exit 2 -fi - -python3 - "$FRONTIER" "$TSV" <<'PY' -import re -import sys -from pathlib import Path - -frontier_path, tsv_path = sys.argv[1], sys.argv[2] -text = Path(frontier_path).read_text() - -survey: dict[str, tuple[str, str, str]] = {} -with open(tsv_path) as f: - f.readline() - for line in f: - parts = line.rstrip("\n").split("\t") - if len(parts) < 5: - continue - module, _, blocker, stage, reason = parts[:5] - survey[module] = (blocker, stage, reason) - -# Extract declared measured_probe per module_path from roster rows. -declared: dict[str, dict[str, str]] = {} -row_re = re.compile( - r"data compiler_frontier_row_\w+: CompilerModuleFrontierRow = [\s\S]*?\n\)", - re.MULTILINE, -) -for block in row_re.findall(text): - path_m = re.search(r'module_path: "([^"]+)"', block) - if not path_m: - continue - path = path_m.group(1) - blocker_m = re.search(r"measured_blocker: ([^\n,]+)", block) - stage_m = re.search(r"located_stage: (ProbeStage\w+)", block) - reason_m = re.search(r"located_reason: (\^?\w+)", block) - if not blocker_m or not stage_m or not reason_m: - continue - blocker = blocker_m.group(1).strip() - if blocker == "compiler_frontier_measured_upstream_unresolved_blocker": - blocker = "UpstreamSemanticRefusal" - declared[path] = { - "blocker": blocker, - "stage": stage_m.group(1), - "reason": reason_m.group(1), - } - -mismatches = [] -missing_declared = [] -missing_survey = [] - -for module, (s_blocker, s_stage, s_reason) in sorted(survey.items()): - if module not in declared: - missing_declared.append(module) - continue - d = declared[module] - fields = [] - if d["blocker"] != s_blocker: - fields.append(f"blocker declared={d['blocker']} survey={s_blocker}") - if d["stage"] != s_stage: - fields.append(f"stage declared={d['stage']} survey={s_stage}") - d_reason = d["reason"] - if not d_reason.startswith("^"): - d_reason = f"^{d_reason}" - if d_reason != s_reason: - fields.append(f"reason declared={d_reason} survey={s_reason}") - if fields: - mismatches.append((module, fields)) - -for module in sorted(declared): - if module not in survey: - missing_survey.append(module) - -print("=== frontier declared vs survey oracle ===") -print(f"survey rows: {len(survey)}") -print(f"declared rows scanned: {len(declared)}") -print(f"mismatches: {len(mismatches)}") -for module, fields in mismatches: - print(f"MISMATCH {module}") - for f in fields: - print(f" {f}") -if missing_declared: - print(f"missing declared row for {len(missing_declared)} survey module(s)") - for m in missing_declared: - print(f" NO_ROW {m}") -if missing_survey: - print(f"survey missing {len(missing_survey)} declared module(s) (ok if partial survey)") - -if mismatches or missing_declared: - sys.exit(1) -print("OK: all surveyed modules match declared measured_probe") -PY diff --git a/docs/probes/frontier_probe_exact_head_survey_2026-08-03.md b/docs/probes/frontier_probe_exact_head_survey_2026-08-03.md deleted file mode 100644 index 1098e1805de..00000000000 --- a/docs/probes/frontier_probe_exact_head_survey_2026-08-03.md +++ /dev/null @@ -1,52 +0,0 @@ -# Frontier probe exact-head survey (Lane E interim census) - -**Status:** INTERIM AUDIT — superseded vocabulary; not a roster closeout. Do not cite "17 surveyed / 10 open." - -**Census at head `9f978aa8df` only:** execution_measurement=17, no_execution_measurement=10, self_emit_ready=0, emitter_produced=0. All 27 rows remain SeedRetained. Not combinable with a later head. Three NameResolutionGap rows in the 17 are suspect pre-#7762 manifest-elision artifacts (see #7762). - -**Head:** `9f978aa8df` (main at survey start, 2026-08-02) on worktree `neat-cat-330`. **Point-in-time only:** at time of writing current main is `19cc776d4e` (44 commits later); five of those commits touched the v1 emission path (#7685, #7691, #7708, #7709, #7733). Verdicts may have moved — this receipt is a dated reading, not a claim about current main. Spot-check at merged main (`d1fe52102b`, 2026-08-03): `04_infer`, `06_translate`, `materialization_carriers` still `RealizationGap`/`^parse_grammar_choice_overlap_residue` @ assemble; `03_ingest` still `NameResolutionGap`/`^resolve_module_not_found` @ assemble. - -**Harness:** `frontier_probe_survey` seed bin, per-module via `frontier_probe_emit_from_ingest` (fixture-free ingest overlay). Receipt TSV: `frontier_probe_exact_head_survey_2026-08-03.tsv`. - -**Denominator:** 27 modules in `compiler_frontier_sweep_order` (`frontier.dag`). **execution_measurement at 9f978aa8df:** 17. **no_execution_measurement at 9f978aa8df:** 10 (listed below). - -## Findings (execution-measured, assemble stage only) - -| Blocker class | Count (of 17) | Located stage | Dominant located_reason | -|---------------|---------------|---------------|-------------------------| -| RealizationGap | 14 | ProbeStageAssemble | `^parse_grammar_choice_overlap_residue` | -| NameResolutionGap | 3 | ProbeStageAssemble | `^resolve_module_not_found` | - -**Not observed in this slice:** EmitSurfaceGap, UpstreamSemanticRefusal, SelfEmitReady. The probe stops at assemble for the dominant class — emit and semantic-derivation stages were not reached for these 17 modules. This is evidence about which stage blocks the probe, not an inferred emit blocker. - -### NameResolutionGap modules (3/17; suspect pre-#7762 manifest elision) - -- `src/v2/compiler/source_authority.dag` -- `src/v2/compiler/00_compile.dag` -- `src/v2/compiler/03_ingest.dag` - -### Reconciliation vs pre-7627 roster rows - -PR #7627 landed vocabulary + totality wall without a second measurement pass. Before this PR, several roster rows carried `UpstreamSemanticRefusal` / `EmitSurfaceGap` at emit/semantic stages from prior knowledge attribution. This survey **contradicted** those rows for all 17 probed modules: each refuses at **ProbeStageAssemble** with grammar residue or module-not-found, not at emit. - -**This document is an audit receipt.** In PR #7697 all **17 execution-measured** `frontier.dag` rows were hand-authored from this TSV (`measured_probe` aligned; `migration_trigger` kept as authored claims). Totality-wall witnesses and the remaining **10 no-execution-measurement** roster rows await a follow-up closeout PR (blocked on #7762 merge for post-fix 27/27 rerun). - -## Declared vs survey oracle (2026-08-03) - -Run: `docs/probes/diff_frontier_declared_vs_survey.sh` — refuses when `frontier.dag` measured_probe disagrees with this TSV (independent oracles; does not write rows). - -**At survey time (pre-hand-edit):** 12 mismatches among the 17 execution-measured modules — declared rows still carried #7627 `UpstreamSemanticRefusal` / `EmitSurfaceGap` at emit/semantic stages while survey measured `RealizationGap` or `NameResolutionGap` at **ProbeStageAssemble** only. - -| Declared (pre-PR #7697 edit) | Survey (17/17 measured) | -|------------------------------|---------------------------| -| UpstreamSemanticRefusal @ SemanticDerivation, `^gate_a_flip_probe_unresolved_compiler_error` | RealizationGap @ Assemble, `^parse_grammar_choice_overlap_residue` (9 modules) | -| UpstreamSemanticRefusal @ SemanticDerivation | NameResolutionGap @ Assemble, `^resolve_module_not_found` (3 modules) | -| EmitSurfaceGap @ Emit, type-ref / namespace reasons | RealizationGap @ Assemble, grammar residue (2 modules) | - -**After PR #7697:** all 17 execution-measured modules have hand-authored rows in `frontier.dag` aligned to this TSV; `diff_frontier_declared_vs_survey.sh` greens for 17/17. The **10 no-execution-measurement** modules (`03_normalize` through `program_assembly` below) were not rewritten — their rows still reflect pre-survey knowledge attribution. - -**Authoring rule:** update `frontier.dag` rows by hand using this TSV as evidence; migration triggers state what would let migration, not restate the measured located_reason. - -## Remaining modules (no_execution_measurement at 9f978aa8df; roster rows not rewritten in PR #7697) - -`03_normalize`, `03_resolve`, `03_name_resolve`, `emit_module`, `05_emit_orchestration`, `emit_semantic_decl`, `emit_host`, `emit_produced`, `03_body_producer`, `program_assembly` diff --git a/docs/probes/frontier_probe_run_interrupted_2026-08-06.md b/docs/probes/frontier_probe_run_interrupted_2026-08-06.md deleted file mode 100644 index 8469eb58bd3..00000000000 --- a/docs/probes/frontier_probe_run_interrupted_2026-08-06.md +++ /dev/null @@ -1,169 +0,0 @@ -# Frontier probe runs interrupted — exact-head survey did not complete (2026-08-06) - -**Status:** EXECUTED RECEIPT OF AN INTERRUPTED RUN. This is not a frontier measurement and contains no blocker-class counts. The authoritative 27/27 survey **did not run**: every probe invocation was SIGKILLed before emitting a receipt for any module. - -**Do not read any frontier count out of this document.** The only numbers here are about the instrument, not about the compiler frontier. - -**Do not read a probe memory requirement out of it either.** The cause of the kills is **not attributable from inside this container**, and this receipt was renamed from `frontier_probe_memory_refusal_2026-08-06` precisely because that name asserted a memory-refusal conclusion the evidence does not support. Probe memory cost is **unmeasured**, not high. - -## What was attempted - -The Lane 1 exact-head closeout recipe (`gunbc.ci_layer_roots` `compiler_frontier_per_module_probe_exclusion_note`), rehearsed end to end. Predecessors #7776, #7762 and #7767 are merged on main. - -- Subject head (rehearsal only, **not** a pin): `2be88489b1303357a10b135dd90704103ea93b0e`. -- Build: clean detached worktree, `cargo build --release -p v1-compiler --bin frontier_probe_survey`. -- Provenance: `build.rs` stamps `BUILD_COMMIT` / `BUILD_TREE` / `BUILD_DIRTY`; `verify_build_provenance` refuses stale binary, commit mismatch, tree mismatch and dirty-worktree builds. All gates passed — the binary is genuinely from that tree. - -## The refusal - -Every probe invocation was SIGKILLed by an OOM killer. Host `memory.max` = 33578549248 bytes (31.3 GiB / 32023 MiB) — but see the counter analysis below: **this cgroup's cap was never the binding constraint.** - -| # | Invocation | Source roots | Result | -|---|------------|--------------|--------| -| 1 | one-shot, all 27 modules | `src/v2` + `dag` | killed **during module 1 of 27**, no manifest emitted | -| 2 | `03_normalize`, fresh process | `src/v2` + `dag` | exit 137 | -| 3 | `03_resolve`, fresh process | `src/v2` + `dag` | exit 137 | -| 4 | `01_tokenize`, fresh process | `src/v2` + `dag` | exit 137 | -| 5 | `03_normalize`, fresh process | `src/v2` only | exit 137 | -| 6 | `01_tokenize` retry, low host load | `src/v2` + `dag` | exit 137 — survived to 3.5 min at ~2.0 GB, past every earlier run, then killed anyway without raising `memory.peak` | - -Six for six. Zero receipts produced. - -**Located identically in all five:** death occurs immediately after the `probing ` line, inside the interpreted `frontier_probe_emit_from_ingest` evaluation. The ingest closure is read to completion first (the `[file] read …` lines), so this is not an ingest or discovery failure. - -### Instrument check — and the misattribution it caught - -Exit 137 alone does not establish an OOM — it is also the shape of a harness timeout or an external kill (see the repo's standing `exit 137 != red` caution). cgroup `memory.events` `oom_kill` incremented **1 → 2 → 3 → 4 → 5**, one per killed run, in exact lockstep, which establishes that these were genuine kernel kills of processes in this cgroup. - -**It does not establish what killed them, and an earlier revision of this receipt drew exactly that wrong conclusion.** The full counter set: - -``` -memory.max 33578549248 (31.3 GiB) -memory.peak 9136902144 ( 8.5 GiB) <- cgroup high-water across ALL runs -memory.events max 0 oom 0 oom_kill 8 -``` - -- `max 0` — allocation in this cgroup **never** reached `memory.max`. -- `oom 0` — the **cgroup** OOM killer was **never invoked**. -- `oom_kill 8` — eight processes in this cgroup were nonetheless killed. In cgroup v2 this counter also counts tasks in the cgroup reaped by the **global** OOM killer. -- `memory.peak` **8.5 GiB against a 31.3 GiB cap** — the cgroup never exceeded 27% of its limit at any point tonight. - -**Conclusion: these kills came from host-level memory pressure on a shared machine, not from this cgroup's limit and not from the probe's own working set.** The probe was killed at or below 8.5 GiB cgroup-wide, which is *not* the signature of a runaway. - -Two claims an earlier revision of this receipt asserted are therefore **withdrawn as refuted**: - -1. ~~"the probe requires more than 31 GiB"~~ — refuted by `memory.peak` = 8.5 GiB. -2. ~~"this host cannot cold-build `v1-compiler` at all"~~ — refuted by an independent control on the same fleet under a **byte-identical** `memory.max` of 33578549248: a genuine cold build (sccache cache hits 0, 1 compilation, 163 s of rustc) completed in 2m59s at a **3.26 GiB** peak with `oom_kill 0`. The crate needs ~3.3 GiB, not 31. - -The `oom_kill` counter incrementing in lockstep is a sound control for *"was this a kill?"* and a worthless one for *"what hit the limit?"*. Reading the second off the first is the mistake this section now records. `memory.events max` / `oom` and `memory.peak` are the fields that answer it, and they were available the entire time. - -## Two hypotheses raised and refuted by execution - -Both were plausible, both were wrong, and both were killed by a control before being reported as causes. - -**H1 — "the 10 never-measured modules are the ones that exhaust memory."** The interim TSV holds exactly 17 rows, and the 10 absent ones are sweep-order positions **1–9 and 11** — a near-prefix, with only `source_authority` (position 10) interrupting it. That clustering made a module-specific property look likely. **Refuted:** `01_tokenize` is one of the 17 that *did* measure, and it OOMs now (run 4). - -**H2 — "the widened root set (`src/v2` + `dag`) is the cause."** The interim audit probed with `src/v2` only; the authoritative closeout mandates both roots, which genuinely widens the closure. **Refuted:** `03_normalize` OOMs with `src/v2` alone (run 5). - -The cause is therefore *not* module identity and *not* the root set. It remains open. - -## Open: regression vs host capacity - -The decisive experiment is to build the probe at the interim audit head `9f978aa8df` — where 17 modules measured cleanly — and run it on this host. Success would mean a regression landed since; failure would mean the host cap is simply too small for this probe. - -That experiment did not complete here. Three attempts to build `v1-compiler` at the old head were all killed (`sccache: Compiler killed by signal 9`): - -| Attempt | Configuration | Result | -|---|---|---| -| 1 | release, `CARGO_BUILD_JOBS=15` (default) | killed, `oom_kill` → 6 | -| 2 | release, `CARGO_BUILD_JOBS=1` | killed, `oom_kill` → 7 | -| 3 | debug profile (`opt-level=2` per dev profile) | killed, `oom_kill` → 8 | - -**These are victims, not diagnoses.** Per the counter analysis above, none of them hit this cgroup's limit, and an independent same-cap control cold-builds this crate at a 3.26 GiB peak. So the builds died to host-level pressure they did not cause, and they say nothing about the crate's requirements. The tempting inference — one rustc died, therefore one rustc needs the whole cap — is invalid, because a process killed by an external OOM killer tells you about the machine at that moment, not about itself. - -Consequence: **regression vs host capacity is UNRESOLVED**, but the reason is contention on a shared host rather than any established capacity limit, and it is retryable rather than blocking. Per operator direction it is reported, not chased, and the probe is not trimmed to fit. - -### One candidate, not a diagnosis - -#7762 closed the manifest-elision hole — the silent-narrow the survey carrier describes. Before it the probe elided closure rows; after it, it admits the full closure. Closing a narrowing that had been *implicitly* bounding memory would produce this shape, and it has a named precedent in DESIGN: removing the scan-all-keys fail-open exposed 8 real deficits its silence had hidden. - -This is a hypothesis with a mechanism, **not** a finding. It has not been tested, and it should be assessed by the owner of that change rather than diagnosed from outside. - -## Consequence for the closeout - -27/27 **did not complete in this window** on either documented path — the one-shot or the per-module fallback (`docs/probes/run_frontier_probe_survey_per_module.sh`). - -**"Unreachable" is not established, and an earlier revision of this receipt wrongly claimed it.** Since no run reached the cgroup limit, nothing here shows the probe cannot fit; the runs were interrupted by external pressure they did not cause. The correct reading is *interrupted and retryable*, not *impossible*. - -Any per-module cost figure for the probe remains **unmeasured**. It becomes measurable only when a run completes, or when a kill is attributable to this cgroup — `memory.events` `max` or `oom` incrementing, rather than `oom_kill` alone. - -Per operator direction the probe must **not** be trimmed to fit the host; a probe shrunk to fit a box measures a different question. On this evidence there is also nothing to shrink it *to*. - -**The retry is redesigned rather than repeated.** The most expensive property of the runs above is not that they died — it is that each death cost *everything*: the one-shot lost all 27 modules when module 1 was killed, six times over. The ruled execution model is therefore **27 independent module jobs** against one pinned subject, one receipt artifact per module, and a final exact-subject aggregator, so a killed job costs one interrupted row instead of the whole survey. Authority and full conditions: `v2.compiler.self_host.frontier_probe_survey` `frontier_probe_exact_head_closeout_note` — not restated here. - -## Recipe defects found while rehearsing - -**1 — the mandated detached worktree and the default build path are mutually exclusive.** `ctrl-build` defaults to remote (`CTRL_BUILD_MODE=remote`) in these sessions, and BuildBuddy refuses a detached worktree: `remote config: get base branch and commit: unexpected branch state * (no branch)`. The closeout recipe requires a clean *detached* worktree, so `ctrl-build --local` is **required**, not a preference. Anyone following the recipe as written hits this first. - -**2 — WITHDRAWN: the suspected module collision is refuted by execution.** I predicted that the recipe's `--source-root target/frontier-probe-survey`, passed alongside `src/v2`, would refuse: both declare module `v2.test.workflow.host_frontier_probe_survey_manifest`, and the seed carries `duplicate_module_path_across_roots_refuses_loudly` (`v1_compiler.cli_run`). - -Two executed runs say otherwise. A duplicate of the manifest module was placed in a third source root and `claim_batch` run over `compiler_frontier_per_module_probe_test.dag`: - -| Third root | Location | Result | -|---|---|---| -| `target/collision-test` | inside `target/` | exit 0, witness PASS, zero refusal messages | -| `dup_root_probe` | outside `target/` | exit 0, zero refusal messages | - -Duplicates across roots are tolerated on this path, so **the recipe does not collide** and the prediction is withdrawn. The seed wall evidently governs a different index path than the one `claim_batch` takes — worth knowing, but not a defect in this recipe. - -**2b — ALSO WITHDRAWN: `target/`-resident source roots are read.** The collision runs could not distinguish "read" from "ignored", because the stub and the duplicate carry identical content and both produce the same outcome either way. That mattered, because the seed skips `target/` beside a `Cargo.toml` as build output (`cargo_target_dir_output_never_enters_the_module_index`); had that applied to an explicitly-passed root, the recipe's emitted manifest would be **silently ignored** and the witnesses would read the stub — worse than a collision, since several of them green **vacuously** on `Empty` receipts (`compiler_frontier_wave2_blocker_partition_totality_holds` did exactly that in both runs above, a green asserting nothing). - -Settled by a discriminating probe rather than by reasoning: a syntactically invalid `.dag` placed in a third root under `target/` is loud if the root is indexed and silent if skipped. It was **loud** — - -``` -for_each_parsed_module_binding: parse error in .../target/broken_root/b.dag: expected item declarat… -exit 101 -``` - -So an explicitly-passed source root under `target/` **is** indexed, the recipe's emitted manifest **will** be read, and the vacuous-green risk does not arise from this mechanism. - -**Net: no recipe defect survives except item 1.** Both predictions here were wrong, and both were killed by execution rather than argument. The vacuous-green *property* is nonetheless real and worth remembering independently: `compiler_frontier_wave2_blocker_partition_totality_holds` passes on an empty manifest, so it must never be read as evidence that a survey ran. - -## Incidental: 4 hard diagnostics on this head, unrelated to this work - -While verifying that this PR's `.dag` edits compile, all three edited modules returned **zero diagnostics in their own files** — but every compile still exits 1, on 4 hard diagnostics in `dag/extdeps/systems/nvidia.dag`: - -``` -source annotation sits inside a declaration body. Only module-item grain is modeled; -move it above the declaration it describes. (dag/extdeps/systems/nvidia.dag:4538-4620, :4625-4701, :4706-4788, :4793-4869) -``` - -The cited offsets exceed the file's 120 lines but fit its 5555 bytes, so they are **byte** offsets. The refusal is exactly what DESIGN §4c specifies: the initial `.dag` realization admits only standalone leading `//` blocks on module-scope declarations, and body-grain forms refuse until separately modeled. - -Attribution: that file arrives with SPARK-0 (`2be88489b13`) and is **not touched by this branch** — this diff is four files and none is `nvidia.dag`. The diagnostics also appear when compiling a 26-source closure that does not contain the file, so they surface tree-wide rather than closure-scoped. - -Recorded as an observation for routing, not diagnosed here. Whether the compile-clean gate scopes around it has not been investigated. - -## Roster provenance finding (independent of the OOM) - -Separate from the memory refusal, and not caused by it. - -`v2.compiler.self_host.frontier` declares `knowledge_attributed_blocker_class_seed_retained_row` — the constructor whose name honestly marks a row as knowledge-attributed rather than measured. It has **zero call sites**: repo-wide, the only occurrence of that symbol is its own definition. - -Meanwhile all **10** roster modules that have never been execution-measured at any head are authored through `execution_measured_seed_retained_row`, the constructor whose name asserts execution measurement — 8 directly, and 2 (`03_normalize`, `03_body_producer`) via `quarantine_seed_retained_row_from_oracle`, which itself delegates to it. - -The never-measured 10, derived by joining `compiler_frontier_sweep_order` against the interim TSV's module column: - -`03_body_producer`, `03_name_resolve`, `03_normalize`, `03_resolve`, `05_emit_orchestration`, `emit_host`, `emit_module`, `emit_produced`, `emit_semantic_decl`, `program_assembly` - -This is DESIGN §4b **rung inflation**: a carrier named for the top rung while occupying the bottom, and "an inflated class never ranks for climbing." - -**The mechanism matters more than the count.** `execution_measured_seed_retained_row` takes `measured_blocker`, `located_stage` and `located_reason` as ordinary parameters. It therefore *cannot* distinguish a measured row from an attributed one — the constructor's **name** asserts a provenance the **type** does not carry, so no amount of care at the call site can make the claim checkable. The §5 construction fix is a provenance field on the row, making an attributed row unrepresentable as measured; the honest-constructor-plus-discipline approach has already been tried here and produced zero adoption. - -No roster row is edited by this receipt. `frontier.dag` is load-bearing and the change above is a model change, flagged for routing rather than landed. - -## What is still true and unaffected - -The interim audit at `9f978aa8df` (`frontier_probe_exact_head_survey_2026-08-03`) stands exactly as written: 17 modules, 14 `^parse_grammar_choice_overlap_residue` and 3 `^resolve_module_not_found`, all at `ProbeStageAssemble`, at that head with `src/v2`-only roots. Verified directly from the TSV for this receipt. - -It remains **not combinable** with any later head or changed source-root set, and nothing in this document changes or extends it. diff --git a/docs/probes/root_d_generic_arity_2026-08-16.md b/docs/probes/root_d_generic_arity_2026-08-16.md new file mode 100644 index 00000000000..186e85de1f4 --- /dev/null +++ b/docs/probes/root_d_generic_arity_2026-08-16.md @@ -0,0 +1,302 @@ +# Root D — generic argument count (E0107): live measurement and root cause, 2026-08-16 + +Lane: `vivid-wren-870`. Coordination surface: `docs/plans/self-host-cargo-refusal-root-partition.md` +(`smart-ram-730`, draft PR #8333). This file is the receipt; the shared doc should cite it rather +than restate it. + +## 1. What was measured, and with what + +Instrument: `docs/probes/curated_cargo_probe_one.sh` (emit -> `cssl_assemble` -> cargo), per the +shared doc's working agreement 2. `frontier_probe_survey` was not used. + +- worktree `/home/briansrls/.worktrees/gunbc/vivid-wren-870`, branch `session/vivid-wren-870` +- entry `src/v2/compiler/06_translate.dag`, `CSSL_STD_SEED_LINK=1`, no lane shim +- release `gunbc` + `cssl_assemble` built in this worktree + +Live result for `06_translate`: emit succeeds (92 files, 218 diagnostics), cargo refuses with +**671 coded errors**, of which **E0107 = 21**. July's snapshot for the same module was 364 total / +E0107 13, so this is consistent with the shared doc's "the wall grew" note. No cause is attributed +to that growth here. + +The 21 split by exact text: + +``` + 9 E0107: type alias takes 0 generic arguments but 1 generic argument was supplied + 8 E0107: type alias takes 0 generic arguments but 2 generic arguments were supplied + 4 E0107: missing generics for enum `Witness` +``` + +**Sizing beyond this one module is NOT claimed.** The July corpus figure (~76) is not refreshed by +this receipt. What is established below is the mechanism, on live evidence, at exact sites. + +## 2. The emitted text, at the exact sites + +``` +src/v2_std_collection.rs:41 pub fn optional_present_witness(opt: Option) -> Rc { +src/v2_std_collection.rs:68 pub value: Rc, +src/v2_std_qualified_name.rs:296 pub fn qualified_name_from_node(root: Rc) -> Rc>> { +src/std_integer.rs:96 pub type PositiveInt = Rc>; +``` + +Authored sources: + +- `src/v2/std/collection.dag` — `fn optional_present_witness(opt: Optional) -> Witness`, + and `type IndexedLookup { value: Witness }`. The argument is **dropped**. +- `dag/std/nat.dag` — `type Nat = CommutativeSemiring` (zero parameters); + `dag/std/integer.dag` — `type PositiveInt = Nat where gt_zero`. The emitted text keeps the + **alias name** `Nat` and appends the **resolved definition's** argument `Magnitude`. Same shape + for `QualifiedName = FreeMonoid` -> `QualifiedName`. + +So the two halves are not opposites of each other in cause: one **drops** a reference's own +argument, the other **fuses** an authored name with a resolved definition's arguments. Both are +decided by the same predicate, below. + +## 3. Root cause, by execution + +Method: the emitter's generated realization `src/v1/stage0/src/v1_compiler_emit_rust.rs` was +temporarily instrumented (probe-then-revert, working agreement 4; the tree is reverted, no +instrumentation is committed) to print the node reaching `render_rust_decl_type` and the string it +returned. + +Observed, emitting `src/v2/std/collection.dag`: + +``` +4 ROOTD decl_type leaf=Witness raw_name=Witness nkids=1 kids=["T"] applied_prop=false +4 ROOTD result raw=Witness nkids=1 conn=NoConnective -> Rc +``` + +The node is **correct** — name `Witness`, one child `T`, `NoConnective`. The argument is dropped +inside the renderer, not upstream. Two further probes localise it: `render_rust_applied_type` and +`rust_fn_sig_peel_closed_alias` are **never called** for these nodes, which leaves exactly one arm +that can return a bare name from a children-bearing node: + +`v1.compiler.05_emit_rust` `rust_render_checkpoint_scalar_bare` -> `rust_scalar_checkpoint_render_base` +-> `lookup_checkpoint(target: Rust, dag_name: leaf)`. + +That is the **E0109 construction wall** documented in-tree at +`rust_checkpoint_scalar_phantom_params_note`: *"A checkpoint scalar has arity 0 in Rust; DAG phantom +params must not surface as `i64`."* It strips type arguments whenever the leaf name resolves to a +checkpoint scalar. And `extdeps.languages.rust.types` `rust_type_checkpoints` contains: + +``` +{ dag_name: "Witness", target_type: "Witness", ... } +{ dag_name: "witness", target_type: "Witness", ... } +``` + +`Witness` is not a scalar. It is the generic enum `Witness` declared in `v2.std.witness` (`src/v2/std/witness.dag`), +and `std.types` `container_type_arity` independently records `"Witness": 1`. So **two authorities +disagree about one type's arity** (DESIGN section 3), the emitter believes the checkpoint table, and +every `Witness` in type position loses its argument. That is the whole of half 2 (`missing +generics for enum Witness`). + +Half 1 is the same function taking its *other* exit. For `Nat` the node reaching the renderer is +`raw_name=CommutativeSemiring nkids=1 kids=["Magnitude"]` while `rust_fn_sig_leaf_name` returns the +authored `Nat` — the renderer composes the authored **name** with the resolved node's **children**. +`Nat` is absent from `rust_type_checkpoints`, so whether the arity-0 strip fires is decided by the +fallback `rust_seed_host_numeric_alias(name, corpus_repr)`, which answers `i64` for `Nat`/`Int` +**only when `corpus_repr_is_host`**. Otherwise no checkpoint matches, the strip does not fire, and +the fused `Nat` is emitted. + +## 4. This is a third instance of the closure-shape meta-root + +Asked by `smart-ram-730` (msg_b0361cc2): does Root D's mechanism contain a closure-shape branch? +**Yes, on half 1, and it is the same `RustCorpusRepr` flag `eager-deer-389` root-caused for Root B.** + +- seed closure (`HostNative`): `Nat`/`Int` render as `i64`, arity 0, arguments dropped, compiles. +- pure-v2 closure (`FaithfulFreeMonoid`): no checkpoint matches, and the same node renders as + authored-alias-name + resolved-definition-args, which cannot compile. + +So half 1 is invisible in any closure containing `src/v1` paths and appears only in seed-free +closures. Half 2 (`Witness`) is **not** closure-shape dependent — it is a hard table row and would +fire in a seed closure too. + +Caveat kept deliberately: I attempted a direct control by adding `--source-root src/v1` to the +minimal `dag/std/integer.dag` emit and the output did not flip (`Nat` both times). That +does **not** refute the branch — `corpus_has_v1_seed_source_indices` reads the loaded modules' +source indices, and adding a source root does not pull a v1 module into that closure. The +closure-shape claim above rests on reading the branch, plus the observed non-firing of the strip in +this closure; a discriminating control that genuinely varies the flag has **not** been executed. + +## 5. Minimal reproducer (per `eager-deer-389`'s method) + +No cargo needed — the defect is visible in emitted text: + +``` +gunbc compile --source-root dag --source-root src/v2 \ + --entry dag/std/integer.dag --output-dir --target rust \ + --dependency-pool-index primary-precedence +grep -n 'PositiveInt' /src/std_integer.rs # -> pub type PositiveInt = Nat; +``` + +and for half 2, the same command with `--entry src/v2/std/collection.dag`: + +``` +grep -n 'Witness' /src/v2_std_collection.rs # -> pub fn ...(...) -> Rc +``` + +Each is ~2m40s against ~8 minutes for a compiler-module cargo probe. + +## 6. What follows, and what does not + +- The fix for half 2 is **construction, not validation**: `Witness` should not be a checkpoint + scalar row. Its arity has a single authority already (`std.types` `container_type_arity`), and the + E0109 wall should derive arity from it rather than from membership of a target spelling table + that cannot express arity at all. Note the shape of the defect: the strip is a **widening failure + arm** (DESIGN section 5) — it answers "drop the arguments" for two different questions, *this type + has no arguments in Rust* and *I have no row for this type*. +- Half 1's fix is not the same edit and is not proposed here: the renderer's composition of an + authored leaf name with a resolved node's children is a distinct defect, and it is entangled with + the corpus-repr flag that Root B owns. Fixing the `Witness` row will not move it. +- Nothing here sizes the corpus. A live E0107 census across modules is still owed. + +## 7. The fix, and what it measured (2026-08-17) + +Landed in this lane, half 2 only. + +**Authority edits.** `extdeps.languages.rust.types` `rust_type_checkpoints` loses its two `Witness` +rows (`"Witness"` and the lowercase twin), and `v1.compiler.05_emit_rust` +`rust_render_checkpoint_scalar_bare` consults the declared-arity authority first +(`std.types is_container_type`) so no leaf with declared arity can be classified a checkpoint +scalar however the target's spelling table is later edited. The row deletion removes today's wrong +answer; the guard is what makes re-adding one harmless. Both `.dag` authorities and their +regenerated `src/v1/stage0` projections move together; the generated coercion-registry assertions in +`compiler_tests.rs` dropped their two `Witness` rows on regen, because those assertions were derived +from the table rather than independent evidence of anything. + +Nothing else was lost with the rows, checked rather than assumed: `coerce_primitive_type(Rust, +"Witness")` still answers `"Witness"` through the `qualified_last_segment` fallback, and `is_copy`'s +`Absent` arm and its former `Present{false}` arm are the same decision at every consumer. + +**Emitted-text before/after, same command, same worktree.** + +``` +src/v2/std/collection.dag closure 4 lines changed, and only those 4: + - pub fn optional_present_witness(opt: Option) -> Rc { + + pub fn optional_present_witness(opt: Option) -> Rc> { + - pub value: Rc, + + pub value: Rc>, + - pub fn witness_from_optional(...) -> Rc { + + pub fn witness_from_optional(...) -> Rc> { + - pub fn list_nth(...) -> Rc { + + pub fn list_nth(...) -> Rc> { + +dag/std/integer.dag closure byte-identical, zero files differ +``` + +The second line is the collateral control: half 1's `pub type PositiveInt = Nat` is +unchanged, which is the intended scope and not an oversight. + +**Cargo, same module, same route, same head — one module, M = 1 on both sides.** + +``` + before after +E0107 21 17 the 4 `missing generics for enum Witness` are gone +E0308 286 286 +E0277 115 115 +E0599 80 80 +E0369 57 57 +every other code identical +``` + +Read this as one module's exact sites, NOT as corpus burn-down: per the program's fixed-denominator +rule, a total that moves with the number of entries probed is mostly a statement about how many +entries were probed. Both sides here are the same single entry, so the 4 is a real per-site +difference; it is not 4/116 of the corpus root, and the corpus figure for this half (33 sites, +`smart-ibex-716`'s eleven-module distinct-site census) is measured elsewhere and not re-derived here. + +**Evidence enrolled.** `dag/test/claim/root_d_checkpoint_scalar_declared_arity_witness_test.dag`: + +- positive — a declared-arity leaf keeps its argument through emission (`Witness`, never + `-> Rc`); +- null control — a genuine arity-0 checkpoint scalar reached with phantom arguments still renders + bare (`Compose`, never `i64<...>`), so the E0109 wall this guard sits inside is intact; +- the arity authority answers for both fixtures. + +Discriminating in both directions **by execution**: green with the change, and red with the change +reverted and the binary rebuilt from the reverted tree (the whole diff reverted, not the witness +disarmed). + +## 8. Does identity-keyed realization subsume this? + +Asked by `smart-ram-730`; `eager-deer-389` is re-keying `lookup_checkpoint` from a bare `String` to +a resolved declaration identity. **No for the rows, yes for the arm's neighbourhood.** + +Re-keying makes the lookup match the *right declaration*. It does not make a row that claims arity 0 +for an arity-1 declaration correct — under identity keys the `Witness` row would match the real +`v2.std.witness.Witness` and still strip its argument. The missing fact in these two rows is arity, +not identity, so they are wrong under any key and the deletion is not downstream of that change. + +Where the two do meet: a `TypeCheckpoint` row states a target *spelling*, and the emitter reads +membership as the proposition "arity 0 in Rust". That is one Present arm answering several +questions — the same shape as the name-keying deficit, one level up from it. The lowercase +`"witness"` twin is a pure name-keying artifact (two spellings of one concept) and belongs to that +lane; it is deleted here only because it goes with its sibling. + +## 9. Two-arm artifact diff over the whole probed closure (2026-08-17) + +Prompted by `smart-ram-730`'s retraction of the "previously masked, not new breakage" phrasing, +after `gentle-dove-833` measured 21 of 25 new diagnostics in their own lane as breakage their change +INTRODUCED. The class that motivates it: a defect's *output* can be load-bearing for an unrelated +consumer, so removing the wrong thing removes a marker something else keyed on, and nothing refuses. +An error histogram cannot see that — both unmasking and new emission read as "new diagnostics". + +Section 7's per-code table is a histogram, so it does not settle the question on its own. The +artifact diff does, and it was run over the **entire emitted closure**, not the two minimal +reproducers — same entry, same command, same worktree, the only variable being the binary: + +``` +91 emitted .rs files in both arms + 2 files differ + 8 changed lines = 4 sites, every one of them: + - ... -> Rc + ... -> Rc> + - pub value: Rc, + pub value: Rc>, +``` + +**Every other emitted byte in the closure is identical.** One emitted form did not become a +different form, no new form appeared, and the four sites that changed are exactly the four the fix +targets. `M` is the same on both arms by construction — one entry — so the comparison is not a +function of how many entries were probed. + +This does not make section 7's per-code equality redundant; the two answer different questions. +The histogram says no diagnostic class moved. The artifact diff says no *emitted text* moved either, +which is the stronger statement and the only one that can see a marker whose removal silently +changes an unrelated consumer's behaviour. + +## 10. The before-arm, re-taken with checkable provenance (2026-08-17) + +Section 9's before-arm came from this working tree, and my defence of it was a chronology — the tree +was emitted before I edited anything. That is an account, not an audit: an emit reads the WORKING +TREE, so an uncommitted edit leaves no trace a timestamp can reveal, and "when did I run this +relative to my own edits" is not recoverable afterwards by anyone, including me. + +So the arm was re-taken from a detached worktree, and both checks the program converged on were run: + +``` +git worktree add --detach /basewt 5e1a73fa339 # the merge-base with origin/main +git status --porcelain (excluding target/) -> 0 dirty tracked files +build gunbc there with RUSTC_WRAPPER= CTRL_BUILD_WRAP_CARGO=0 -> real compile output +emit src/v2/compiler/06_translate.dag with the same command as both other arms +``` + +**Provenance (prevention).** The arm is now reproducible by a third party from the SHA alone. + +**WHAT read (verification).** The construct this change introduces — `Witness` in the two files +that move — is **absent from the base arm**: 0 in `v2_std_witness.rs`, 0 in `v2_std_collection.rs`. +An arm that already contained it would have been mid-change whatever its timestamp said. + +**Result.** + +``` +base arm (SHA 5e1a73fa) vs section 9's before-arm -> 0 files differ, byte-identical +base arm vs after-arm -> 2 files, 8 lines, the same 4 Witness sites +``` + +So section 9's measurement stands unchanged, and it now rests on bytes reproducible from a commit +rather than on my recollection of when I ran it. Recorded as a re-take rather than a correction: +the original arm was in fact clean, and the point is that nobody could have checked that before. + +One scope note carried from the same review, because it applies to this receipt's own numbers: the +include count `Witness` is **0 -> 4 per-file** across the two files that change, and **1 -> 5 +tree-wide** over the same closure, because `v2_compiler_translate.rs` already produced that spelling +in the base arm for unrelated reasons. Count an include at the scope the assertion uses; a per-file +0 does not license a tree-wide include. diff --git a/docs/probes/run_frontier_probe_survey_per_module.sh b/docs/probes/run_frontier_probe_survey_per_module.sh deleted file mode 100755 index ed14f061bcc..00000000000 --- a/docs/probes/run_frontier_probe_survey_per_module.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env bash -# SCAFFOLD — probe one-off beside docs/probes/curated_cargo_probe_one.sh (not a general scripts/ home). -# dissolve-on: ^migrate_when_frontier_per_module_probe_receipt_binds — floor-enrolled -# v2.workflow.frontier_probe_survey_transport runs the survey without this shell loop; delete -# this script when the transport + single-process survey path is green on CI hosts without OOM. -# Runtime-present: invokes frontier_probe_survey seed bin per module (not bash-emitted workflow). -set -euo pipefail -ROOT="$(cd "$(dirname "$0")/../.." && pwd)" -cd "$ROOT" - -if [[ -n "$(git status --porcelain)" ]]; then - echo "frontier_probe_survey: SurveyPinRefused: dirty working tree — run from a clean detached worktree at the selected commit" >&2 - exit 1 -fi - -SOURCE_COMMIT="$(git rev-parse HEAD)" -echo "frontier_probe_survey: building release bin at source_commit=${SOURCE_COMMIT}" >&2 -/opt/cargo/bin/cargo build --release -p v1-compiler --bin frontier_probe_survey - -BIN="$ROOT/target/release/frontier_probe_survey" -if [[ ! -x "$BIN" ]]; then - echo "frontier_probe_survey: release bin missing after build: $BIN" >&2 - exit 1 -fi - -SURVEY_DIR="$ROOT/target/frontier-probe-survey" -TSV="$SURVEY_DIR/frontier_probe_survey.tsv" -MANIFEST="$SURVEY_DIR/host_frontier_probe_survey_manifest.dag" -mkdir -p "$SURVEY_DIR" - -MODULES=( - "src/v2/compiler/03_normalize.dag" - "src/v2/compiler/03_resolve.dag" - "src/v2/compiler/03_name_resolve.dag" - "src/v2/compiler/emit_module.dag" - "src/v2/compiler/05_emit_orchestration.dag" - "src/v2/compiler/emit_semantic_decl.dag" - "src/v2/compiler/emit_host.dag" - "src/v2/compiler/emit_produced.dag" - "src/v2/compiler/03_body_producer.dag" - "src/v2/compiler/program_assembly.dag" - "src/v2/compiler/source_authority.dag" - "src/v2/compiler/00_compile.dag" - "src/v2/compiler/03_ingest.dag" - "src/v2/compiler/parse_engine_hooks.dag" - "src/v2/compiler/use_site_verdict.dag" - "src/v2/compiler/discovery_enumeration.dag" - "src/v2/compiler/01_tokenize.dag" - "src/v2/compiler/self_host.dag" - "src/v2/compiler/materialization_carriers.dag" - "src/v2/compiler/07_target_carriers.dag" - "src/v2/compiler/fold_lowering.dag" - "src/v2/compiler/04_infer.dag" - "src/v2/compiler/05_eval.dag" - "src/v2/compiler/06_translate.dag" - "src/v2/compiler/05_emit.dag" - "src/v2/compiler/program_partition.dag" - "src/v2/compiler/02_parse.dag" -) - -echo "module source_commit source_tree survey_executable source_roots_digest probe_policy_revision self_emit_ready blocker_class located_stage located_reason rejection_chain overlap_roster_detail probe_error" > "$TSV" -failures=0 -for mod in "${MODULES[@]}"; do - echo "=== probing $mod ===" >&2 - rm -f "$SURVEY_DIR/tmp_row.tsv" - if ! "$BIN" \ - --source-root src/v2 \ - --source-root dag \ - --module "$mod" \ - --survey-dir "$SURVEY_DIR" \ - --emit-survey-manifest "$SURVEY_DIR/tmp_manifest.dag" \ - --emit-tsv "$SURVEY_DIR/tmp_row.tsv" >"$SURVEY_DIR/tmp_probe.log" 2>&1 - then - echo "frontier_probe_survey refused for $mod (exit $?)" >&2 - tail -20 "$SURVEY_DIR/tmp_probe.log" >&2 - rm -f "$SURVEY_DIR/tmp_row.tsv" - failures=$((failures + 1)) - continue - fi - if [[ ! -f "$SURVEY_DIR/tmp_row.tsv" ]]; then - echo "frontier_probe_survey produced no row file for $mod" >&2 - failures=$((failures + 1)) - continue - fi - tail -n +2 "$SURVEY_DIR/tmp_row.tsv" >> "$TSV" -done - -if [[ failures -ne 0 ]]; then - echo "survey refused: $failures module probe(s) failed — TSV not promoted to manifest" >&2 - exit 1 -fi - -"$BIN" \ - --source-root src/v2 \ - --source-root dag \ - --emit-survey-manifest "$MANIFEST" \ - --emit-manifest-only \ - --receipt-tsv "$TSV" - -echo "Survey complete: $MANIFEST (source_commit=${SOURCE_COMMIT})" diff --git a/scripts/run-large-json-probe-experiment.sh b/scripts/run-large-json-probe-experiment.sh index 345d23b46f6..fd917c96f57 100755 --- a/scripts/run-large-json-probe-experiment.sh +++ b/scripts/run-large-json-probe-experiment.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SCAFFOLD — STR-RC-0 clean-process survival experiment beside json_parse_scaling_probe -# (not a general scripts/ home; same transport class as docs/probes/run_frontier_probe_survey_per_module.sh). +# (not a general scripts/ home; one-off probe transport lives beside the probe it serves). # dissolve-on: delete when STR-RC-0 survival receipts are floor-enrolled or the branch reverts. # Runtime-present: invokes json_parse_scaling_probe seed bin per (carrier, size) in a fresh process. # STR-RC-0 clean-process survival experiment: pre (String) vs post (Rc). diff --git a/scripts/run-memo0-mechanism-100kb.sh b/scripts/run-memo0-mechanism-100kb.sh index 9b452ae6bac..9e82f1fef5a 100755 --- a/scripts/run-memo0-mechanism-100kb.sh +++ b/scripts/run-memo0-mechanism-100kb.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # SCAFFOLD — STR-RC-0 memo0 mechanism receipt beside json_parse_scaling_probe -# (not a general scripts/ home; same transport class as docs/probes/run_frontier_probe_survey_per_module.sh). +# (not a general scripts/ home; one-off probe transport lives beside the probe it serves). # dissolve-on: delete when STR-RC-0 mechanism receipts are floor-enrolled or the branch reverts. # Runtime-present: invokes json_parse_scaling_probe seed bin with GUNBC_EVAL_MEMO=0. # STR-RC-0 mechanism check: post 100KB survival with GUNBC_EVAL_MEMO=0 only. diff --git a/src/v1/05_emit_rust.dag b/src/v1/05_emit_rust.dag index 2e7989f7afd..2d80ec19586 100644 --- a/src/v1/05_emit_rust.dag +++ b/src/v1/05_emit_rust.dag @@ -454,12 +454,15 @@ fn rust_scalar_checkpoint_render_base(dag_name: String, corpus_repr: RustCorpusR } } +data rust_checkpoint_scalar_declared_arity_guard_note: String = "The strip below reads table MEMBERSHIP as the proposition 'this leaf has arity 0 in Rust'. A TypeCheckpoint row cannot state arity — it states target spelling — so the two facts 'this is a scalar' and 'I have a spelling for this name' arrive as one Present, and the arm answers 'drop every type argument' to both. That is DESIGN section 5's widening failure arm: the dropped argument leaves plausible output rather than a diagnostic, so the deficit's frequency was zero by construction until rustc reported E0107. The guard consults the single arity authority (std.types is_container_type / container_expected_arity) FIRST, so a leaf with declared arity can never be classified scalar however the target's spelling table is edited. Receipt: docs/probes/root_d_generic_arity_2026-08-16.md." + data rust_checkpoint_scalar_phantom_params_note: String = "Construction wall for E0109 (type arguments are not allowed on builtin type i64). A checkpoint scalar (lookup_checkpoint / rust_seed_host_numeric_alias — Int, Nat, i64, etc.) has arity 0 in Rust; DAG phantom params from GroupCompletion or Compose> must not surface as i64. Root fix: refuse phantom arg emission at the type-node renderer when the leaf is a checkpoint scalar and children > 0 — not a post-hoc string strip on the rendered output (DESIGN section 5: widening instead of refusing)." fn rust_render_checkpoint_scalar_bare(n: Node, corpus_repr: RustCorpusRepr, source_indices: Map, shared_types: Set) -> String? { if n.children |> count == 0 { none } else { let leaf = rust_fn_sig_leaf_name(source_indices: source_indices, n: n) + if is_container_type(name: leaf) { return none } match rust_scalar_checkpoint_render_base(dag_name: leaf, corpus_repr: corpus_repr) { Present { value: scalar } => if set_contains(shared_types, leaf) && !rust_type_is_rc_wrapped(type_name: scalar) { @@ -533,7 +536,7 @@ fn rust_witness_parent_leaf(parent: String) -> Bool { qualified_last_segment(name: parent) == "Witness" } -data rust_witness_variant_arm_names_note: String = "Holds/Violates literals below are the two arms of std.witness.Witness (dag/std/witness.dag) — not minted nicknames. Pattern position routes via variant_pattern_qualified_path like any other modeled enum; construction turbofish here keys type-arg resolution off the modeled arm names only." +data rust_witness_variant_arm_names_note: String = "Holds/Violates literals below are the two arms of v2.std.witness.Witness (src/v2/std/witness.dag; this citation read std.witness / dag/std/witness.dag until 2026-08-16, naming a module that does not exist in the tree) — not minted nicknames. Pattern position routes via variant_pattern_qualified_path like any other modeled enum; construction turbofish here keys type-arg resolution off the modeled arm names only." fn rust_peel_one_rc_type_node(type_node: Node, source_indices: Map) -> Node { let seg = qualified_last_segment(name: type_node.name) @@ -933,7 +936,7 @@ fn render_rust_decl_type(n: Node, generic_param_names: List, shared_type } else if type_node_has_unbound_type_variable(n: n, generic_param_names: generic_param_names, source_indices: source_indices) { "_" } else { - render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices) + render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, env: env) } } } @@ -1009,12 +1012,12 @@ fn render_rust_fn_sig_type_applied_binding(n: Node, shared_types: Set, c if outer_name != "" && outer_name != "fn" && !is_container_type(name: outer_name) && n.connective == NoConnective && (n.children |> count) == 0 && rust_fn_sig_peel_closed_alias(env: env, n: n) && rust_fn_sig_preserves_authored_alias_leaf(name: outer_name, corpus_repr: corpus_repr) { render_rust_shared_type_with_optional(n: n, type_name: outer_name, rendered: outer_name, shared_types: shared_types) } else { - render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices) + render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, env: env) } } else { - render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices) + render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, env: env) } - Absent => render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices) + Absent => render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, env: env) } } @@ -2932,7 +2935,7 @@ fn expand_variant_payload_struct_imports(names: List, type_summaries: Ma ) } -data reference_derived_authored_source_gate_note: String = "reference_derived_use_lines synthesizes a use-line only when the candidate name appears in this module's authored source text (NewlineIndex char_codes). A name that enters the candidate set only via inferred/type-summary over-collection — never spelled in the module — must not become a pub use. Empty/unavailable module source REFUSES every candidate (fail-closed): ⊤-as-ignorance must not admit the full candidate set (§5 absorbing fallback). Receipt: after occurrence-binding stage0 enrollment, AuthoredTokenOrdinal entered the registry and std.http_path (which never mentions it) emitted a fabricated pub use. UnlistedImportUse names are already spelled at the use site, so they pass when source text is readable; variant-parent enums that appear only via from_variant still require their parent spelling OR an authored variant ctor whose parent is harvested — parent-only imports without any authored spelling of parent or variant remain a separate gap, not this gate's subject. Dissolve-on: derive use-lines from the module's bound-reference structure (P2a candidate-producer / BoundReferenceProvider) — this text-presence gate is the conservative interim, not the destination." +data reference_derived_authored_source_gate_note: String = "reference_derived_use_lines synthesizes a use-line only for a candidate the module's authored source text ATTESTS (NewlineIndex char_codes), and there are exactly two attesting forms, both decided by reference_derived_candidate_authored. Direct: the candidate's own name is spelled. Variant-induced: the candidate is a unit-only enum and the module spells at least one variant that binds UNAMBIGUOUSLY back to it — derive_variant_to_enum maps a variant shared by two enums to the empty string, so a homonym never equals the enum name and is REFUSED rather than picked. A name that enters the candidate set only via inferred/type-summary over-collection — attested by neither form — must not become a pub use. Empty/unavailable module source REFUSES every candidate (fail-closed): ⊤-as-ignorance must not admit the full candidate set (§5 absorbing fallback). Receipt: after occurrence-binding stage0 enrollment, AuthoredTokenOrdinal entered the registry and std.http_path (which never mentions it) emitted a fabricated pub use — that name is a record, not a unit-only enum, so the variant-induced arm cannot readmit it. Second receipt (Root K): the emitter qualifies variants as Parent::Variant in pattern and nested-argument positions where the source spells only the variant, so asking whether the PARENT was spelled refused a parent the module demonstrably uses — 109 of 132 sites. UnlistedImportUse names are already spelled at the use site, so they pass when source text is readable. Declared residue, in two classes that fail at DIFFERENT stages — this gate is a filter over a candidate set, so it can only refuse, never propose. Refused HERE: a parent enum with neither its own name nor any binding variant spelled, and a non-enum candidate whose only evidence is over-collection. Never REACHING here, and therefore unfixable by any gate decision: a name the candidate collector never proposes. Measured by execution — forcing this gate to admit unconditionally and re-emitting v2.lens.complexity_accumulator_copy.analyze still produces no use-line for Behavior, whose unit-only variant Transform is spelled bare in a pattern position and binds unambiguously, so the arm's preconditions hold and the name is simply absent upstream. That class is pre-existing and unchanged by Root K (identical count in both arms), and it is where the remaining sites live: widening this gate further cannot reach them. Dissolve-on: derive use-lines from the module's bound-reference structure (P2a candidate-producer / BoundReferenceProvider) — this text-attestation gate is the conservative interim, not the destination." fn module_authored_source_text(module: Node, source_indices: Map) -> String { match map_get(source_indices, module.span.file) { @@ -2945,6 +2948,48 @@ fn reference_derived_candidate_spelled_in_module(module_source: String, name: St module_source != "" && string_contains(s: module_source, pattern: name) } +// WHY the authored-source gate has a second arm for parent enums. +// +// The gate asks whether a candidate name is spelled in the module. For a PARENT ENUM that is the +// wrong question: the emitter qualifies a variant by its parent (Parent::Variant, via +// variant_pattern_qualified_path and the variant-ctor emit path) at sites where the .dag source +// spells only the VARIANT — a bare match arm on Accepted, a nested construction of Unavailable. +// The parent is then never in the module text, so its use-line was refused and the emitted +// Parent::Variant had no import. +// +// The gate is therefore not relaxed; the question is corrected. A parent-enum candidate is admitted +// when an authored VARIANT of that same enum is spelled, and only on the UNAMBIGUOUS binding: +// derive_variant_to_enum maps a variant name shared by two enums to the empty string, so a homonym +// variant admits NEITHER enum rather than picking one — fail-closed, no plausible guess. +// +// Residue, declared not hidden: a corpus-wide ambiguous variant leaves its parent unimported even +// where the emitter qualifies it from the scrutinee type, and a parent reached by neither its own +// spelling nor an unambiguous authored variant stays unsynthesized. Both refuse rather than +// fabricate. This arm carries no dissolution condition of its own — it dissolves with the text gate +// it corrects, on the trigger reference_derived_authored_source_gate_note already declares. + +fn reference_derived_variant_induced_parent_spelled(module_source: String, enum_name: String, type_summaries: Map, variant_to_enum: Map) -> Bool { + match map_get(type_summaries, enum_name) { + Present { value: summary } => + match summary.repr { + EnumRepr { unit_only: _ } => + sorted_map_keys(summary.variant_name_set) |> any(vn => + match map_get(variant_to_enum, vn) { + Present { value: parent } => parent == enum_name && reference_derived_candidate_spelled_in_module(module_source: module_source, name: vn) + Absent => false + } + ) + _ => false + } + Absent => false + } +} + +fn reference_derived_candidate_authored(module_source: String, name: String, type_summaries: Map, variant_to_enum: Map) -> Bool { + reference_derived_candidate_spelled_in_module(module_source: module_source, name: name) + || reference_derived_variant_induced_parent_spelled(module_source: module_source, enum_name: name, type_summaries: type_summaries, variant_to_enum: variant_to_enum) +} + fn reference_derived_use_lines(items: List, unlisted_type_names: List, this_module_name: String, registry: Map, emit_info: EmitGraphInfo, local_type_names: List, already_imported_names: List, export_sets: Map>, typed_modules: List, source_indices: Map, module_index: ModuleIndex) -> List { { let module_source = match typed_modules |> filter(tm => authored_name_at(source_indices: source_indices, node: tm.module) == this_module_name) |> first { @@ -2956,7 +3001,7 @@ fn reference_derived_use_lines(items: List, unlisted_type_names: List filter(name => reference_derived_candidate_spelled_in_module(module_source: module_source, name: name)) + |> filter(name => reference_derived_candidate_authored(module_source: module_source, name: name, type_summaries: emit_info.type_summaries, variant_to_enum: emit_info.variant_to_enum)) let local_decl_names = items |> flat_map(item => let nm = authored_name_at(source_indices: source_indices, node: item) if nm == "" { [] } else { [nm] } @@ -5070,7 +5115,9 @@ fn emit_struct_from_children(name: String, type_params: String, generic_param_na } } -fn render_rust_type_with_applied_binding(n: Node, shared_types: Set, corpus_repr: RustCorpusRepr, source_indices: Map) -> String { +data render_rust_type_applied_binding_env_note: String = "Construction wall for the zero-parameter-alias applied-argument class (E0107 'type alias takes 0 generic arguments but N were supplied'). A reference to a closed alias arrives at the emitter carrying the RESOLVED DEFINITION's type arguments as its children while its authored spelling is still the alias name, so a renderer that prints name-plus-children emits ClosedCarrierAlias for a Rust alias declared with no parameters. Four renderers already refuse that shape by asking the single peel authority rust_fn_sig_peel_closed_alias: render_rust_applied_type, render_rust_decl_type, render_rust_fn_sig_type and render_rust_alias_rhs_type. This function is the fifth path, and it did NOT lack the guard -- it reached render_rust_applied_type, which asked, and was answered with an EMPTY TypeEnv this function constructed inline plus an empty_emit_graph_info() it passed to render_rust_type. An empty env resolves no binding, and the peel predicate renders 'I could not look this up' identically to 'this declaration has parameters' -- the state-space conflation DESIGN section 5 names, failing open into the widened applied form rather than refusing. Every one of this function's callers already holds the TypeEnv it was discarding, so the fix is to stop discarding it: the peel authority stays the single authority and is simply answered truthfully. Measured on the src/v2/compiler/03_ingest.dag closure. The next rung is upstream and not taken here: an alias reference that preserved its AUTHORED arity would make the bad shape unwritable rather than merely refused, at which point no renderer would need to ask at all." + +fn render_rust_type_with_applied_binding(n: Node, shared_types: Set, corpus_repr: RustCorpusRepr, source_indices: Map, env: TypeEnv) -> String { if is_host_text_carrier_type(n: n, source_indices: source_indices, corpus_repr: corpus_repr) { return rust_carrier_optional_wrap(n: n, rendered: "String") } match find_property(props: n.properties, prop_name: "__applied_type_args", source_indices: source_indices) { Present { value: applied } => @@ -5081,15 +5128,15 @@ fn render_rust_type_with_applied_binding(n: Node, shared_types: Set, cor if outer_name != applied_name { render_rust_shared_type_with_optional(n: n, type_name: outer_name, rendered: outer_name, shared_types: shared_types) } else { - render_rust_applied_type_shared(n: applied, generic_param_names: [], shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, variant_to_enum: empty_map(), env: TypeEnv { module_path: "", bindings: empty_map(), str_bindings: empty_map(), ancestry_str_bindings: empty_map(), parents: [], recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: empty_intern_table(), source_visible_names: empty_map(), symbol_index: empty_symbol_index() }) + render_rust_applied_type_shared(n: applied, generic_param_names: [], shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, variant_to_enum: empty_map(), env: env) } } else { - render_rust_applied_type_shared(n: applied, generic_param_names: [], shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, variant_to_enum: empty_map(), env: TypeEnv { module_path: "", bindings: empty_map(), str_bindings: empty_map(), ancestry_str_bindings: empty_map(), parents: [], recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: empty_intern_table(), source_visible_names: empty_map(), symbol_index: empty_symbol_index() }) + render_rust_applied_type_shared(n: applied, generic_param_names: [], shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, variant_to_enum: empty_map(), env: env) } } else { - render_rust_type(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, emit_info: empty_emit_graph_info()) + render_rust_type(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, emit_info: emit_info_with_fn_type_context(emit_info: empty_emit_graph_info(), generic_param_names: [], env: env)) } - Absent => render_rust_type(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, emit_info: empty_emit_graph_info()) + Absent => render_rust_type(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, emit_info: emit_info_with_fn_type_context(emit_info: empty_emit_graph_info(), generic_param_names: [], env: env)) } } @@ -5098,13 +5145,13 @@ fn render_rust_field_type_with_applied_binding(field: Node, generic_param_names: if generic_param_names |> count > 0 { render_rust_decl_type(n: resolved_type(n: field), generic_param_names: generic_param_names, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, variant_to_enum: variant_to_enum, env: env) } else if find_property(props: field.properties, prop_name: "__applied_type_args", source_indices: source_indices) != none { - render_rust_type_with_applied_binding(n: field, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices) + render_rust_type_with_applied_binding(n: field, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, env: env) } else if find_property(props: authored_type.properties, prop_name: "__applied_type_args", source_indices: source_indices) != none { - render_rust_type_with_applied_binding(n: authored_type, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices) + render_rust_type_with_applied_binding(n: authored_type, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, env: env) } else if authored_type.connective == NoConnective && authored_type.children |> count > 0 { render_rust_type(n: authored_type, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, emit_info: empty_emit_graph_info()) } else { - render_rust_type_with_applied_binding(n: resolved_type(n: field), shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices) + render_rust_type_with_applied_binding(n: resolved_type(n: field), shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, env: env) } } @@ -5114,11 +5161,11 @@ fn emit_struct_field_from_child(struct_name: String, child: Node, generic_param_ let ty = if generic_param_names |> count > 0 { render_rust_decl_type(n: rt_child, generic_param_names: generic_param_names, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices, variant_to_enum: emit_info.variant_to_enum, env: env) } else if find_property(props: child.properties, prop_name: "__applied_type_args", source_indices: env.source_indices) != none { - render_rust_type_with_applied_binding(n: child, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices) + render_rust_type_with_applied_binding(n: child, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices, env: env) } else if find_property(props: authored_child_type.properties, prop_name: "__applied_type_args", source_indices: env.source_indices) != none { - render_rust_type_with_applied_binding(n: authored_child_type, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices) + render_rust_type_with_applied_binding(n: authored_child_type, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices, env: env) } else if find_property(props: rt_child.properties, prop_name: "__applied_type_args", source_indices: env.source_indices) != none { - render_rust_type_with_applied_binding(n: rt_child, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices) + render_rust_type_with_applied_binding(n: rt_child, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices, env: env) } else if is_product_type(n: rt_child) && rt_child.ident_span != none && rt_child.children |> count > 2 { let rt_child_name = authored_name_at(source_indices: env.source_indices, node: rt_child) match lookup_type_by_name(env: env, name: rt_child_name) { @@ -5453,7 +5500,7 @@ fn emit_variant_from_child(child: Node, enum_name: String, generic_param_names: } else { render_rust_type(n: type_node, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices, emit_info: emit_info) } - let ty = if find_property(props: type_node.properties, prop_name: "__applied_type_args", source_indices: env.source_indices) != none { render_rust_type_with_applied_binding(n: type_node, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices) } else { raw_ty } + let ty = if find_property(props: type_node.properties, prop_name: "__applied_type_args", source_indices: env.source_indices) != none { render_rust_type_with_applied_binding(n: type_node, shared_types: shared_types, corpus_repr: emit_info.corpus_repr, source_indices: env.source_indices, env: env) } else { raw_ty } let final_ty = if needs_box_wrapping(n: type_node, recursive_types: recursive_types, shared_types: shared_types, source_indices: env.source_indices) { concat("Box<", ty, ">") } else { ty } @@ -10243,7 +10290,7 @@ fn emit_data_def(name: String, type_node: Node, value: Node, registry: Map" { match field_value_by_name(record: value, field_name: "top", source_indices: scope.type_env.source_indices) { diff --git a/src/v1/stage0/Cargo.toml b/src/v1/stage0/Cargo.toml index 81339a292ce..dabcc31405c 100644 --- a/src/v1/stage0/Cargo.toml +++ b/src/v1/stage0/Cargo.toml @@ -100,15 +100,6 @@ path = "src/bin/discover_owned_data.rs" name = "discover_source_root_ingest" path = "src/bin/discover_source_root_ingest.rs" -# SCAFFOLD (DESIGN §7 seed-retained HAND-RUST / P5) — per-module emit-frontier survey host transport. -# Authority: module census reads `compiler_frontier_sweep_order` from `frontier.dag` at runtime (no parallel roster). -# NOT floor-enrolled — long-lane local recipe via `frontier_probe_survey_transport.dag`. -# CHECKABLE RECEIPT: census before=27 (`compiler_frontier_roster_count`); after shrink=0 LOC when manifest witness greens. -# Bin LOC: 821 (origin/main) → 1088 (+267 Lane 2 assemble_detail/overlap manifest serialize; see frontier_probe_survey_transport_scaffold_note). -# DISSOLUTION: `gunbc.plans.wave2_prep_design` §2.3 + `^migrate_when_frontier_per_module_probe_receipt_binds`; then delete bin. -[[bin]] -name = "frontier_probe_survey" -path = "src/bin/frontier_probe_survey.rs" # CI2-0 Commit B sweep driver — local recipe only (NOT floor-enrolled, not WitnessBin-addressed): # per-entry canonical realization sweep over the frontier-probe overlay transport. diff --git a/src/v1/stage0/build.rs b/src/v1/stage0/build.rs index 7d9929ffe2e..d4db60d9f1d 100644 --- a/src/v1/stage0/build.rs +++ b/src/v1/stage0/build.rs @@ -21,7 +21,6 @@ fn main() { // v1-compiler compile when alternating cargo build and cargo test. Pointing at // the real HEAD path would be worse: every commit would invalidate the shared lib. println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-changed=src/bin/frontier_probe_survey.rs"); let commit = git_output(&["rev-parse", "HEAD"]).unwrap_or_default(); let tree = git_output(&["rev-parse", "HEAD^{tree}"]).unwrap_or_default(); diff --git a/src/v1/stage0/src/bin/frontier_probe_survey.rs b/src/v1/stage0/src/bin/frontier_probe_survey.rs deleted file mode 100644 index 3bb902d0465..00000000000 --- a/src/v1/stage0/src/bin/frontier_probe_survey.rs +++ /dev/null @@ -1,1487 +0,0 @@ -#![allow(clippy::disallowed_macros)] - -use std::fs; -use std::io::Write; -use std::path::{Path, PathBuf}; -use std::process::{Command, ExitCode}; - -use v1_compiler::cli_run::{ - discover_source_root_reads_for_entry, emit_source_ref_dag_for_path, - emit_source_root_ingest_manifest, parse_source_root_entry_admission, resolve_entry_graph, -}; -use v1_compiler::std_content_hash::{content_hash_atom, content_hash_combine_structural}; -use v1_compiler::v1_interpreter::{ - self, free_monoid_symbol_value_to_dotted_string, ExecutionMode, InterpContext, Value, -}; - -const PROBE_ENTRY: &str = "src/v2/test/claim/long/compiler_frontier_probe_entry_test.dag"; -const PROBE_RECEIPT_FN: &str = "frontier_probe_entry_receipt"; -const WITNESS_LAYER_ROOTS: &[&str] = &["dag", "src/v2"]; -const FRONTIER_SWEEP_ORDER_ENTRY: &str = "src/v2/compiler/self_host/frontier.dag"; -const SWEEP_ORDER_DATA: &str = "compiler_frontier_sweep_order"; -const HOST_REASON_SYMBOLS_ENTRY: &str = "src/v2/compiler/self_host/frontier_probe_types.dag"; -const HOST_RUNTIME_ERROR_REASON_DATA: &str = "frontier_probe_survey_host_runtime_error_reason"; -const HOST_OOM_OR_BUDGET_REASON_DATA: &str = "frontier_probe_survey_host_oom_or_budget_reason"; - -fn free_monoid_elems<'a>(value: &'a Value, ctx: &InterpContext) -> Result, String> { - let mut out = Vec::new(); - let mut cur = value; - loop { - match cur { - Value::Variant { - variant_name, - fields, - .. - } if ctx.sym_eq(*variant_name, "Cons") => { - let head = ctx - .field(fields, "head") - .ok_or_else(|| "Cons without `head` field".to_string())?; - out.push(head); - cur = ctx - .field(fields, "tail") - .ok_or_else(|| "Cons without `tail` field".to_string())?; - } - Value::Variant { variant_name, .. } if ctx.sym_eq(*variant_name, "Empty") => { - return Ok(out); - } - Value::List(items) => { - out.extend(items.iter()); - return Ok(out); - } - other => { - return Err(format!( - "expected a List (Cons/Empty), got {}", - other.type_label_public() - )); - } - } - } -} - -fn str_list_from_value(value: &Value, ctx: &InterpContext) -> Result, String> { - let mut out = Vec::new(); - for elem in free_monoid_elems(value, ctx)? { - match elem { - Value::Str(s) => out.push(s.to_string()), - other => { - return Err(format!( - "expected a List element, got {}", - other.type_label_public() - )); - } - } - } - Ok(out) -} - -fn load_compiler_frontier_sweep_order(source_roots: &[String]) -> Result, String> { - let mut roots: Vec = WITNESS_LAYER_ROOTS.iter().map(|r| r.to_string()).collect(); - roots.extend(source_roots.iter().cloned()); - let (graph, source_indices) = - resolve_entry_graph(&roots, FRONTIER_SWEEP_ORDER_ENTRY).map_err(|e| format!("{e}"))?; - let ctx = InterpContext::new(&graph, source_indices, ExecutionMode::Hermetic); - let value = v1_interpreter::run_in_context(&ctx, SWEEP_ORDER_DATA, true) - .map_err(|e| format!("read {SWEEP_ORDER_DATA}: {e}"))?; - str_list_from_value(&value, &ctx) -} - -struct ProbeReceiptRow { - module_path: String, - blocker_variant: String, - located_stage: String, - located_reason: String, - detail: String, - assemble_detail_manifest: String, - rejection_chain: String, - overlap_roster_detail: String, - probe_error: Option, - subject: SurveySubjectPin, -} - -fn dag_manifest_scalar_escape(s: &str) -> Result { - if s.contains('{') || s.contains('}') { - return Err(format!( - "manifest scalar escape: '{{' and '}}' forbidden in {:?}", - s - )); - } - Ok(s.replace('\\', "\\\\").replace('"', "\\\"")) -} - -fn int_from_value(value: &Value) -> Result { - match value { - Value::Int(n) => Ok(*n), - other => Err(format!("expected Int, got {}", other.type_label_public())), - } -} - -fn str_from_value(value: &Value) -> Result { - match value { - Value::Str(s) => Ok(s.to_string()), - other => Err(format!( - "expected String, got {}", - other.type_label_public() - )), - } -} - -fn qualified_name_emit(value: &Value) -> Result { - let dotted = free_monoid_symbol_value_to_dotted_string(value); - if dotted.is_empty() { - return Err("empty QualifiedName".to_string()); - } - let escaped = dag_manifest_scalar_escape(&dotted)?; - Ok(format!( - "qualified_name_from_dotted_string(dotted: \"{escaped}\")" - )) -} - -fn content_hash_emit(value: &Value, ctx: &InterpContext) -> Result { - let digest = content_hash_digest_string(value, ctx)?; - let escaped = dag_manifest_scalar_escape(&digest)?; - Ok(format!( - "Fnv1a64(Fnv1a64Structural {{ digest: \"{escaped}\" }})" - )) -} - -fn content_hash_digest_string(value: &Value, ctx: &InterpContext) -> Result { - match value { - Value::Variant { - variant_name, - fields, - .. - } => { - let family = ctx.resolve(*variant_name); - if family != "Fnv1a64" { - return Err(format!( - "unsupported ContentHash family {family} in survey manifest" - )); - } - if let Some(inner) = ctx.field(fields, "0") { - return digest_from_structural(inner, ctx); - } - for (_, field_value) in fields.iter() { - if let Ok(digest) = digest_from_structural(field_value, ctx) { - return Ok(digest); - } - } - Err("Fnv1a64 variant missing structural payload".to_string()) - } - Value::Record { type_name, .. } if ctx.resolve(*type_name) == "Fnv1a64Structural" => { - digest_from_structural(value, ctx) - } - other => Err(format!( - "expected ContentHash variant, got {}", - other.type_label_public() - )), - } -} - -fn digest_from_structural(value: &Value, ctx: &InterpContext) -> Result { - match value { - Value::Record { fields, .. } | Value::Variant { fields, .. } => { - let digest = ctx - .field(fields, "digest") - .ok_or_else(|| "Fnv1a64Structural missing digest".to_string())?; - str_from_value(digest) - } - other => Err(format!( - "expected Fnv1a64Structural record, got {}", - other.type_label_public() - )), - } -} - -fn source_root_ref_emit(value: &Value, ctx: &InterpContext) -> Result { - variant_name(ctx, value) -} - -fn source_ref_emit(value: &Value, ctx: &InterpContext) -> Result { - let path = str_from_value(record_field(ctx, value, "path")?)?; - let source_root = source_root_ref_emit(record_field(ctx, value, "source_root")?, ctx)?; - let content_hash = content_hash_emit(record_field(ctx, value, "content_hash")?, ctx)?; - let escaped_path = dag_manifest_scalar_escape(&path)?; - Ok(format!( - "SourceRef {{ path: \"{escaped_path}\", source_root: {source_root}, content_hash: {content_hash} }}" - )) -} - -fn source_root_coverage_emit(value: &Value, ctx: &InterpContext) -> Result { - match value { - Value::Variant { - variant_name, - fields, - .. - } => { - let name = ctx.resolve(*variant_name); - if name == "SourceRootCoverageComplete" || name == "SourceRootManifestAbsent" { - return Ok(name); - } - if name == "SourceRootManifestElided" { - let read_count = int_from_value( - ctx.field(fields, "read_count") - .ok_or_else(|| format!("{name} missing read_count"))?, - )?; - let cap = int_from_value( - ctx.field(fields, "cap") - .ok_or_else(|| format!("{name} missing cap"))?, - )?; - return Ok(format!("{name} {{ read_count: {read_count}, cap: {cap} }}")); - } - if name == "SourceRootRowsMissing" { - let read_count = int_from_value( - ctx.field(fields, "read_count") - .ok_or_else(|| format!("{name} missing read_count"))?, - )?; - let produced_row_count = int_from_value( - ctx.field(fields, "produced_row_count") - .ok_or_else(|| format!("{name} missing produced_row_count"))?, - )?; - return Ok(format!( - "{name} {{ read_count: {read_count}, produced_row_count: {produced_row_count} }}" - )); - } - Err(format!("unknown SourceRootCoverage variant {name}")) - } - _ => Err(format!( - "expected SourceRootCoverage variant, got {}", - value.type_label_public() - )), - } -} - -fn detail_variant_emit(value: &Value, ctx: &InterpContext) -> Result { - match value { - Value::Variant { - variant_name, - fields, - .. - } => { - let name = ctx.resolve(*variant_name); - match name.as_str() { - "FrontierProbeDetailAbsent" => Ok(name), - "MissingModule" => { - let requested = ctx - .field(fields, "requested") - .ok_or_else(|| format!("{name} missing requested"))?; - Ok(format!( - "{name} {{ requested: {} }}", - qualified_name_emit(requested)? - )) - } - "SourceRootManifestElidedProbe" => { - let read_count = int_from_value( - ctx.field(fields, "read_count") - .ok_or_else(|| format!("{name} missing read_count"))?, - )?; - let cap = int_from_value( - ctx.field(fields, "cap") - .ok_or_else(|| format!("{name} missing cap"))?, - )?; - Ok(format!("{name} {{ read_count: {read_count}, cap: {cap} }}")) - } - "FrontierProbeClosurePopulationRefused" => { - let cause = ctx - .field(fields, "cause") - .ok_or_else(|| format!("{name} missing cause"))?; - Ok(format!("{name} {{ cause: {} }}", value_symbol_name(cause)?)) - } - "FrontierProbeCoverageRefused" => { - let coverage = ctx - .field(fields, "coverage") - .ok_or_else(|| format!("{name} missing coverage"))?; - Ok(format!( - "{name} {{ coverage: {} }}", - source_root_coverage_emit(coverage, ctx)? - )) - } - "SourceRefReadRefused" => { - let source_ref = ctx - .field(fields, "source_ref") - .ok_or_else(|| format!("{name} missing source_ref"))?; - let error = str_from_value( - ctx.field(fields, "error") - .ok_or_else(|| format!("{name} missing error"))?, - )?; - let escaped_error = dag_manifest_scalar_escape(&error)?; - Ok(format!( - "{name} {{ source_ref: {}, error: \"{escaped_error}\" }}", - source_ref_emit(source_ref, ctx)? - )) - } - "SourceRefContentHashMismatch" => { - let source_ref = ctx - .field(fields, "source_ref") - .ok_or_else(|| format!("{name} missing source_ref"))?; - let expected = ctx - .field(fields, "expected") - .ok_or_else(|| format!("{name} missing expected"))?; - let observed = ctx - .field(fields, "observed") - .ok_or_else(|| format!("{name} missing observed"))?; - Ok(format!( - "{name} {{ source_ref: {}, expected: {}, observed: {} }}", - source_ref_emit(source_ref, ctx)?, - content_hash_emit(expected, ctx)?, - content_hash_emit(observed, ctx)? - )) - } - other => Err(format!("unsupported FrontierProbeDetail variant {other}")), - } - } - _ => Err(format!( - "expected FrontierProbeDetail variant, got {}", - value.type_label_public() - )), - } -} - -fn symbol_list_csv(value: &Value, ctx: &InterpContext) -> Result { - let mut parts = Vec::new(); - for item in free_monoid_elems(value, ctx)? { - parts.push(value_symbol_name(item)?); - } - Ok(parts.join(",")) -} - -fn non_empty_symbol_chain_csv_flat(value: &Value, ctx: &InterpContext) -> Result { - let head = record_field(ctx, value, "head")?; - let tail = record_field(ctx, value, "tail")?; - let mut parts = vec![value_symbol_name(head)?]; - for item in free_monoid_elems(tail, ctx)? { - parts.push(value_symbol_name(item)?); - } - Ok(parts.join(",")) -} - -fn symbol_list_dag_emit(value: &Value, ctx: &InterpContext) -> Result { - let mut parts = Vec::new(); - for item in free_monoid_elems(value, ctx)? { - parts.push(value_symbol_name(item)?); - } - let mut list = String::from("Empty"); - while let Some(sym) = parts.pop() { - list = format!("Cons {{\n head: {sym},\n tail: {list}\n}}"); - } - Ok(list) -} - -fn grammar_choice_ambiguity_row_emit(value: &Value, ctx: &InterpContext) -> Result { - let production = value_symbol_name(record_field(ctx, value, "production")?)?; - let left_list = symbol_list_dag_emit(record_field(ctx, value, "left_first_terminals")?, ctx)?; - let right_list = symbol_list_dag_emit(record_field(ctx, value, "right_first_terminals")?, ctx)?; - let overlap_list = symbol_list_dag_emit(record_field(ctx, value, "overlap_terminals")?, ctx)?; - let both_nullable = match record_field(ctx, value, "both_nullable")? { - Value::Bool(b) => { - if *b { - "true" - } else { - "false" - } - } - other => { - return Err(format!( - "both_nullable not Bool: {}", - other.type_label_public() - )); - } - }; - Ok(format!( - "GrammarChoiceAmbiguityRow {{\n production: {production},\n left_first_terminals: {left_list},\n right_first_terminals: {right_list},\n overlap_terminals: {overlap_list},\n both_nullable: {both_nullable}\n}}" - )) -} - -fn non_empty_grammar_rows_emit(value: &Value, ctx: &InterpContext) -> Result { - let head = grammar_choice_ambiguity_row_emit(record_field(ctx, value, "head")?, ctx)?; - let tail = record_field(ctx, value, "tail")?; - let mut tail_nodes: Vec = Vec::new(); - for item in free_monoid_elems(tail, ctx)? { - tail_nodes.push(grammar_choice_ambiguity_row_emit(item, ctx)?); - } - let mut list = String::from("Empty"); - while let Some(node) = tail_nodes.pop() { - list = format!("Cons {{\n head: {node},\n tail: {list}\n}}"); - } - Ok(format!( - "NonEmptyGrammarChoiceAmbiguityRows {{\n head: {head},\n tail: {list}\n}}" - )) -} - -fn non_empty_symbol_chain_emit(value: &Value, ctx: &InterpContext) -> Result { - let head = value_symbol_name(record_field(ctx, value, "head")?)?; - let tail = symbol_list_dag_emit(record_field(ctx, value, "tail")?, ctx)?; - Ok(format!( - "NonEmptySymbolChain {{\n head: {head},\n tail: {tail}\n}}" - )) -} - -// The cause location is emitted, not dropped, because a reason symbol alone does not say -// WHICH file refused. It sits on AssembleRejectionDetail beside the cause rather than -// inside it, because a position is not part of what the refusal IS. It is a probe-owned -// coproduct rather than a bare Locus precisely so this emitter can be TOTAL: a position -// with no serializable form becomes the closed CauseLocationNodeNotSerializable arm -// instead of aborting a 27-module survey, and no arm invents a position it did not observe. -fn cause_location_emit(value: &Value, ctx: &InterpContext) -> Result { - match value { - Value::Variant { - variant_name, - fields, - .. - } => { - let name = ctx.resolve(*variant_name); - if name == "CauseLocationTextual" { - let file = ctx - .field(fields, "file") - .ok_or_else(|| format!("{name} missing file"))?; - let extent = ctx - .field(fields, "extent") - .ok_or_else(|| format!("{name} missing extent"))?; - Ok(format!( - "CauseLocationTextual {{ file: \"{}\", extent: {} }}", - dag_manifest_scalar_escape(&str_from_value(file)?)?, - extent_emit(extent, ctx)? - )) - } else if name == "CauseLocationPort" { - let port = ctx - .field(fields, "port") - .ok_or_else(|| format!("{name} missing port"))?; - Ok(format!( - "CauseLocationPort {{ port: {} }}", - value_symbol_name(port)? - )) - } else if name == "CauseLocationNodeNotSerializable" { - Ok("CauseLocationNodeNotSerializable".to_string()) - } else { - Err(format!("unknown FrontierProbeCauseLocation variant {name}")) - } - } - _ => Err("cause location not a variant".to_string()), - } -} - -fn extent_emit(value: &Value, ctx: &InterpContext) -> Result { - match value { - Value::Variant { - variant_name, - fields, - .. - } => { - let name = ctx.resolve(*variant_name); - if name == "WholeFile" { - Ok("WholeFile".to_string()) - } else if name == "ByteRange" { - let start = ctx - .field(fields, "start") - .ok_or_else(|| format!("{name} missing start"))?; - let end = ctx - .field(fields, "end") - .ok_or_else(|| format!("{name} missing end"))?; - Ok(format!( - "ByteRange {{ start: {}, end: {} }}", - int_from_value(start)?, - int_from_value(end)? - )) - } else { - Err(format!("unknown Extent variant {name}")) - } - } - _ => Err("extent not a variant".to_string()), - } -} - -fn assemble_rejection_cause_emit(value: &Value, ctx: &InterpContext) -> Result { - match value { - Value::Variant { - variant_name, - fields, - .. - } => { - let name = ctx.resolve(*variant_name); - if name == "GrammarChoiceOverlap" { - let rows = ctx - .field(fields, "rows") - .ok_or_else(|| format!("{name} missing rows"))?; - Ok(format!( - "GrammarChoiceOverlap {{ rows: {} }}", - non_empty_grammar_rows_emit(rows, ctx)? - )) - } else if name == "MaskedAssembleRefusal" { - let overlap_evidence = ctx - .field(fields, "overlap_evidence") - .ok_or_else(|| format!("{name} missing overlap_evidence"))?; - let remaining_chain = ctx - .field(fields, "remaining_chain") - .ok_or_else(|| format!("{name} missing remaining_chain"))?; - Ok(format!( - "MaskedAssembleRefusal {{\n overlap_evidence: {},\n remaining_chain: {}\n}}", - non_empty_grammar_rows_emit(overlap_evidence, ctx)?, - non_empty_symbol_chain_emit(remaining_chain, ctx)? - )) - } else if name == "MaskedAssembleRefusalWithoutEvidence" { - let remaining_chain = ctx - .field(fields, "remaining_chain") - .ok_or_else(|| format!("{name} missing remaining_chain"))?; - Ok(format!( - "MaskedAssembleRefusalWithoutEvidence {{\n remaining_chain: {}\n}}", - non_empty_symbol_chain_emit(remaining_chain, ctx)? - )) - } else if name == "AssembleMissingModule" { - let requested = ctx - .field(fields, "requested") - .ok_or_else(|| format!("{name} missing requested"))?; - Ok(format!( - "AssembleMissingModule {{ requested: {} }}", - qualified_name_emit(requested)? - )) - } else if name == "MissingModuleIdentityUnavailable" { - Ok("MissingModuleIdentityUnavailable".to_string()) - } else if name == "OtherAssembleRefusal" { - let reason = ctx - .field(fields, "reason") - .ok_or_else(|| format!("{name} missing reason"))?; - Ok(format!( - "OtherAssembleRefusal {{ reason: {} }}", - value_symbol_name(reason)? - )) - } else { - Err(format!("unknown AssembleRejectionCause variant {name}")) - } - } - _ => Err("assemble cause not a variant".to_string()), - } -} - -fn assemble_detail_emit(value: &Value, ctx: &InterpContext) -> Result { - match value { - Value::Variant { - variant_name, - fields, - .. - } => { - let name = ctx.resolve(*variant_name); - if name == "NoFrontierProbeDetail" { - Ok("NoFrontierProbeDetail".to_string()) - } else if name == "AssembleRejectionDetail" { - let chain = ctx - .field(fields, "rejection_chain") - .ok_or_else(|| format!("{name} missing rejection_chain"))?; - let cause = ctx - .field(fields, "cause") - .ok_or_else(|| format!("{name} missing cause"))?; - let at = ctx - .field(fields, "at") - .ok_or_else(|| format!("{name} missing at"))?; - Ok(format!( - "AssembleRejectionDetail {{\n rejection_chain: {},\n cause: {},\n at: {}\n}}", - non_empty_symbol_chain_emit(chain, ctx)?, - assemble_rejection_cause_emit(cause, ctx)?, - cause_location_emit(at, ctx)? - )) - } else { - Err(format!("unknown assemble_detail variant {name}")) - } - } - _ => Err("assemble_detail not a variant".to_string()), - } -} - -fn overlap_rows_detail_from_rows_value( - value: &Value, - ctx: &InterpContext, -) -> Result { - let mut rows = Vec::new(); - let head = record_field(ctx, value, "head")?; - rows.push(head); - for item in free_monoid_elems(record_field(ctx, value, "tail")?, ctx)? { - rows.push(item); - } - let mut out = Vec::new(); - for row in rows { - let production = value_symbol_name(record_field(ctx, row, "production")?)?; - let left = symbol_list_csv(record_field(ctx, row, "left_first_terminals")?, ctx)?; - let right = symbol_list_csv(record_field(ctx, row, "right_first_terminals")?, ctx)?; - let overlap = symbol_list_csv(record_field(ctx, row, "overlap_terminals")?, ctx)?; - out.push(format!( - "{production}|left={left}|right={right}|overlap={overlap}" - )); - } - Ok(out.join(";")) -} - -fn overlap_roster_detail_from_assemble_detail( - value: &Value, - ctx: &InterpContext, -) -> Result { - match value { - Value::Variant { - variant_name, - fields, - .. - } if ctx.sym_eq(*variant_name, "AssembleRejectionDetail") => { - let cause = ctx - .field(fields, "cause") - .ok_or_else(|| "AssembleRejectionDetail missing cause".to_string())?; - match cause { - Value::Variant { - variant_name: cause_name, - fields: cause_fields, - .. - } if ctx.sym_eq(*cause_name, "GrammarChoiceOverlap") => { - let rows = ctx - .field(cause_fields, "rows") - .ok_or_else(|| "GrammarChoiceOverlap missing rows".to_string())?; - overlap_rows_detail_from_rows_value(rows, ctx) - } - Value::Variant { - variant_name: cause_name, - fields: cause_fields, - .. - } if ctx.sym_eq(*cause_name, "MaskedAssembleRefusal") => { - let overlap_evidence = - ctx.field(cause_fields, "overlap_evidence").ok_or_else(|| { - "MaskedAssembleRefusal missing overlap_evidence".to_string() - })?; - overlap_rows_detail_from_rows_value(overlap_evidence, ctx) - } - _ => Ok(String::new()), - } - } - _ => Ok(String::new()), - } -} - -fn rejection_chain_from_assemble_detail( - value: &Value, - ctx: &InterpContext, -) -> Result { - match value { - Value::Variant { - variant_name, - fields, - .. - } if ctx.sym_eq(*variant_name, "AssembleRejectionDetail") => { - let chain = ctx - .field(fields, "rejection_chain") - .ok_or_else(|| "AssembleRejectionDetail missing rejection_chain".to_string())?; - non_empty_symbol_chain_csv_flat(chain, ctx) - } - _ => Ok(String::new()), - } -} - -fn survey_manifest_needs_detail_imports(rows: &[ProbeReceiptRow]) -> bool { - rows.iter().any(|row| { - row.detail != "FrontierProbeDetailAbsent" - || row.assemble_detail_manifest != "NoFrontierProbeDetail" - }) -} - -fn survey_manifest_import_block(rows: &[ProbeReceiptRow]) -> String { - let mut imports = String::from( - "import extdeps.git.object_store { GitSha1ObjectId }\n\ - import std.content_hash { Fnv1a64Structural, Sha1Digest, Sha256Digest, as_content_hash_structural }\n\ - import v2.compiler.self_host.frontier_probe_types {\n\ - FrontierProbeReceipt,\n\ - FrontierSurveyManifest,\n\ - FrontierSurveySubject\n\ - }\n\ - import v2.std.algebra { Cons, Empty }\n\ - import v2.std.collection { List }\n", - ); - if survey_manifest_needs_detail_imports(rows) { - imports.push_str( - "import v2.compiler.source_authority { SourceRef, SourceRootCoverage }\n\ - import std.content_hash { ContentHash, Fnv1a64 }\n\ - import v2.std.cross_tree.import_model { SourceRootRef, V2Tree, DagTree }\n\ - import v2.std.grammar_choice_ambiguity { GrammarChoiceAmbiguityRow, NonEmptyGrammarChoiceAmbiguityRows }\n\ - import v2.std.qualified_name { qualified_name_from_dotted_string }\n", - ); - } - imports.push('\n'); - imports -} - -struct HostFailureReasons { - runtime_error: String, - oom_or_budget: String, -} - -fn require_value(args: &[String], idx: usize, flag: &str) -> Result { - match args.get(idx) { - Some(v) => Ok(v.clone()), - None => { - eprintln!("frontier_probe_survey: {flag} requires a value"); - Err(ExitCode::from(2)) - } - } -} - -fn symbol_to_manifest(sym: &str) -> String { - if sym.starts_with('^') { - sym.to_string() - } else { - format!("^{sym}") - } -} - -fn value_symbol_name(value: &Value) -> Result { - match value { - Value::Str(s) => Ok(symbol_to_manifest(s.as_ref())), - other => Err(format!( - "expected symbol String, got {}", - other.type_label_public() - )), - } -} - -fn load_symbol_data_from_entry( - source_roots: &[String], - entry: &str, - data_name: &str, -) -> Result { - let mut roots: Vec = WITNESS_LAYER_ROOTS.iter().map(|r| r.to_string()).collect(); - roots.extend(source_roots.iter().cloned()); - let (graph, source_indices) = resolve_entry_graph(&roots, entry).map_err(|e| format!("{e}"))?; - let ctx = InterpContext::new(&graph, source_indices, ExecutionMode::Hermetic); - let value = v1_interpreter::run_in_context(&ctx, data_name, true) - .map_err(|e| format!("read {data_name}: {e}"))?; - let sym = value_symbol_name(&value)?; - Ok(sym.trim_start_matches('^').to_string()) -} - -fn load_host_failure_reasons(source_roots: &[String]) -> Result { - Ok(HostFailureReasons { - runtime_error: load_symbol_data_from_entry( - source_roots, - HOST_REASON_SYMBOLS_ENTRY, - HOST_RUNTIME_ERROR_REASON_DATA, - )?, - oom_or_budget: load_symbol_data_from_entry( - source_roots, - HOST_REASON_SYMBOLS_ENTRY, - HOST_OOM_OR_BUDGET_REASON_DATA, - )?, - }) -} - -fn variant_name(ctx: &InterpContext, value: &Value) -> Result { - match value { - Value::Variant { variant_name, .. } => Ok(ctx.resolve(*variant_name)), - _ => Err(format!( - "expected variant, got {}", - value.type_label_public() - )), - } -} - -fn record_field<'a>( - ctx: &InterpContext, - value: &'a Value, - name: &str, -) -> Result<&'a Value, String> { - match value { - Value::Record { fields, .. } => ctx - .field(fields, name) - .ok_or_else(|| format!("record missing field {name}")), - _ => Err(format!( - "expected record, got {}", - value.type_label_public() - )), - } -} - -fn blocker_variant_emit(blocker: &Value, ctx: &InterpContext) -> Result { - match blocker { - Value::Variant { - variant_name, - fields, - .. - } => { - let name = ctx.resolve(*variant_name); - if name == "UnknownProbeCause" { - let reason = ctx - .field(fields, "reason") - .or_else(|| ctx.field(fields, "cause")) - .ok_or_else(|| format!("{name} missing reason/cause"))?; - let reason_sym = value_symbol_name(reason)?; - Ok(format!("{name} {{ reason: {reason_sym} }}")) - } else if name == "UpstreamSemanticRefusal" { - // HAND-RUST GATE (+12 LOC): mechanical serialize arm for new coproduct variant — - // see v2.compiler.self_host.frontier_probe_survey::frontier_probe_survey_blocker_variant_emit_rust_gate_note - let diagnostic_class = ctx - .field(fields, "diagnostic_class") - .ok_or_else(|| format!("{name} missing diagnostic_class"))?; - let diagnostic_name = ctx - .field(fields, "diagnostic_name") - .ok_or_else(|| format!("{name} missing diagnostic_name"))?; - let class_sym = value_symbol_name(diagnostic_class)?; - let name_sym = value_symbol_name(diagnostic_name)?; - Ok(format!( - "{name} {{ diagnostic_class: {class_sym}, diagnostic_name: {name_sym} }}" - )) - } else { - Ok(name) - } - } - _ => Err("blocker_class not a variant".to_string()), - } -} - -fn extract_probe_receipt(value: &Value, ctx: &InterpContext) -> Result { - let module_path = match record_field(ctx, value, "module_path")? { - Value::Str(s) => s.to_string(), - other => { - return Err(format!( - "module_path not String: {}", - other.type_label_public() - )); - } - }; - let blocker = record_field(ctx, value, "blocker_class")?; - let stage = record_field(ctx, value, "located_stage")?; - let reason = record_field(ctx, value, "located_reason")?; - let detail = record_field(ctx, value, "detail")?; - let assemble_detail = record_field(ctx, value, "assemble_detail")?; - let assemble_detail_manifest = assemble_detail_emit(assemble_detail, ctx)?; - let rejection_chain = rejection_chain_from_assemble_detail(assemble_detail, ctx)?; - let overlap_roster_detail = overlap_roster_detail_from_assemble_detail(assemble_detail, ctx)?; - Ok(ProbeReceiptRow { - module_path, - blocker_variant: blocker_variant_emit(blocker, ctx)?, - located_stage: variant_name(ctx, stage)?, - located_reason: value_symbol_name(reason)?, - detail: detail_variant_emit(detail, ctx)?, - assemble_detail_manifest, - rejection_chain, - overlap_roster_detail, - probe_error: None, - subject: SurveySubjectPin { - source_commit: String::new(), - source_tree: String::new(), - survey_executable: String::new(), - source_roots_digest: String::new(), - probe_policy_revision: String::new(), - }, - }) -} - -fn unknown_probe_row( - module_path: &str, - cause: &str, - subject: &SurveySubjectPin, -) -> ProbeReceiptRow { - ProbeReceiptRow { - module_path: module_path.replace('\\', "/"), - blocker_variant: format!("UnknownProbeCause {{ reason: ^{cause} }}"), - located_stage: "ProbeStageAssemble".to_string(), - located_reason: format!("^{cause}"), - detail: "FrontierProbeDetailAbsent".to_string(), - assemble_detail_manifest: "NoFrontierProbeDetail".to_string(), - rejection_chain: String::new(), - overlap_roster_detail: String::new(), - probe_error: Some(cause.to_string()), - subject: subject.clone(), - } -} - -fn write_probe_overlay_manifest( - module_path: &str, - ingest_manifest: &Path, - entry_source_ref: &str, -) -> Result<(), String> { - let escaped = module_path.replace('\\', "/"); - let append = format!( - "\ndata frontier_probe_entry_module_path: String = \"{escaped}\"\n\ - data frontier_probe_entry_source_ref: SourceRef = {entry_source_ref}\n" - ); - let mut body = - fs::read_to_string(ingest_manifest).map_err(|e| format!("read ingest manifest: {e}"))?; - if body.contains("frontier_probe_entry_module_path") { - return Ok(()); - } - body.push_str(&append); - fs::write(ingest_manifest, body).map_err(|e| format!("append module_path overlay: {e}")) -} - -fn per_module_overlay_dir(survey_dir: &Path, module_path: &str) -> PathBuf { - let slug = module_path - .replace('\\', "/") - .trim_start_matches("src/v2/") - .replace('/', "__"); - survey_dir.join(slug) -} - -fn run_probe_for_module( - source_roots: &[String], - survey_dir: &Path, - module_path: &str, -) -> Result { - let exclude = vec!["host_source_root_ingest_manifest.dag".to_string()]; - let overlay_dir = per_module_overlay_dir(survey_dir, module_path); - fs::create_dir_all(&overlay_dir) - .map_err(|e| format!("mkdir overlay {:?}: {e}", overlay_dir))?; - - let mut discover_roots: Vec = - WITNESS_LAYER_ROOTS.iter().map(|r| r.to_string()).collect(); - for root in source_roots { - if !discover_roots.iter().any(|existing| existing == root) { - discover_roots.push(root.clone()); - } - } - let records = discover_source_root_reads_for_entry(&discover_roots, module_path, &exclude)?; - let entry_source = - fs::read_to_string(module_path).map_err(|e| format!("read entry {module_path}: {e}"))?; - let admission = parse_source_root_entry_admission(&entry_source)?; - let ingest_manifest = overlay_dir.join("host_source_root_ingest_manifest.dag"); - emit_source_root_ingest_manifest(&ingest_manifest, &records, Some(&admission))?; - let entry_source_ref = emit_source_ref_dag_for_path(&records, module_path)?; - write_probe_overlay_manifest(module_path, &ingest_manifest, &entry_source_ref)?; - - let mut roots: Vec = WITNESS_LAYER_ROOTS.iter().map(|r| r.to_string()).collect(); - roots.push(overlay_dir.to_string_lossy().into_owned()); - - let (graph, source_indices) = resolve_entry_graph(&roots, PROBE_ENTRY)?; - let ctx = InterpContext::new(&graph, source_indices, ExecutionMode::Hermetic); - let value = - v1_interpreter::run_in_context(&ctx, PROBE_RECEIPT_FN, true).map_err(|e| format!("{e}"))?; - extract_probe_receipt(&value, &ctx) -} - -fn emit_receipt_row(row: &ProbeReceiptRow) -> String { - format!( - "FrontierProbeReceipt {{\n module_path: \"{}\",\n blocker_class: {},\n located_stage: {},\n located_reason: {},\n detail: {},\n assemble_detail: {}\n}}", - row.module_path.replace('\\', "/"), - row.blocker_variant, - row.located_stage, - row.located_reason, - row.detail, - row.assemble_detail_manifest, - ) -} - -fn emit_survey_manifest( - path: &Path, - rows: &[ProbeReceiptRow], - subject: &SurveySubjectPin, -) -> Result<(), String> { - if let Some(parent) = path.parent() { - fs::create_dir_all(parent).map_err(|e| format!("mkdir {:?}: {e}", parent))?; - } - let mut receipt_nodes: Vec = rows.iter().map(emit_receipt_row).collect(); - let mut list = String::from("Empty"); - while let Some(head) = receipt_nodes.pop() { - list = format!("Cons {{\n head: {head},\n tail: {list}\n}}"); - } - let imports = survey_manifest_import_block(rows); - let body = format!( - "// GENERATED by frontier_probe_survey — execution receipt table. Regenerate via frontier_probe_survey bin.\n\ - module v2.test.workflow.host_frontier_probe_survey_manifest\n\n\ - {imports}\ - data host_frontier_probe_survey_manifest: FrontierSurveyManifest = FrontierSurveyManifest {{\n\ - subject: FrontierSurveySubject {{\n\ - source_commit: \"{source_commit}\",\n\ - source_tree: GitSha1ObjectId {{\n\ - digest: Sha1Digest {{ hex: \"{source_tree}\" }}\n\ - }},\n\ - survey_executable: Sha256Digest {{ hex: \"{survey_executable}\" }},\n\ - source_roots_digest: Fnv1a64Structural {{ digest: \"{source_roots_digest}\" }},\n\ - probe_policy_revision: as_content_hash_structural(structural: Fnv1a64Structural {{ digest: \"{probe_policy_revision}\" }})\n\ - }},\n\ - receipts: {list}\n\ - }}\n", - source_commit = subject.source_commit, - source_tree = subject.source_tree, - survey_executable = subject.survey_executable, - source_roots_digest = subject.source_roots_digest, - probe_policy_revision = subject.probe_policy_revision, - ); - fs::write(path, body).map_err(|e| format!("write survey manifest: {e}")) -} - -fn emit_tsv(path: &Path, rows: &[ProbeReceiptRow]) -> Result<(), String> { - let mut out = fs::File::create(path).map_err(|e| format!("create tsv: {e}"))?; - writeln!( - out, - "module\tsource_commit\tsource_tree\tsurvey_executable\tsource_roots_digest\tprobe_policy_revision\tself_emit_ready\tblocker_class\tlocated_stage\tlocated_reason\trejection_chain\toverlap_roster_detail\tprobe_error" - ) - .map_err(|e| format!("write tsv header: {e}"))?; - for row in rows { - let self_emit = if row.blocker_variant == "SelfEmitReady" { - "yes" - } else { - "no" - }; - writeln!( - out, - "{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}", - row.module_path, - row.subject.source_commit, - row.subject.source_tree, - row.subject.survey_executable, - row.subject.source_roots_digest, - row.subject.probe_policy_revision, - self_emit, - row.blocker_variant, - row.located_stage, - row.located_reason, - row.rejection_chain, - row.overlap_roster_detail, - row.probe_error.as_deref().unwrap_or("") - ) - .map_err(|e| format!("write tsv row: {e}"))?; - } - Ok(()) -} - -// Diagnostic stderr histogram only — NOT the Wave-2 sizing verdict authority. -// Canonical clustering: `frontier_gap_clustering_from_receipts` in -// `v2.compiler.self_host.frontier_probe_survey` (witness: -// `compiler_frontier_gap_clustering_common_root_at_blocker_class_holds`). -// Deletes with the seed `frontier_probe_survey` bin (P5 scaffold). -fn cluster_summary(rows: &[ProbeReceiptRow]) -> String { - use std::collections::BTreeMap; - let mut by_reason: BTreeMap = BTreeMap::new(); - let mut by_blocker: BTreeMap = BTreeMap::new(); - for row in rows { - *by_reason.entry(row.located_reason.clone()).or_insert(0) += 1; - *by_blocker.entry(row.blocker_variant.clone()).or_insert(0) += 1; - } - let mut lines = vec![ - "=== frontier_probe_survey cluster summary ===".to_string(), - format!("modules: {}", rows.len()), - "--- by blocker_class ---".to_string(), - ]; - for (k, v) in &by_blocker { - lines.push(format!(" {v}\t{k}")); - } - lines.push("--- by located_reason (root clustering) ---".to_string()); - for (k, v) in &by_reason { - lines.push(format!(" {v}\t{k}")); - } - lines.push(format!("distinct located_reasons: {}", by_reason.len())); - lines.push( - "verdict: (see frontier_gap_clustering_from_receipts on emitted manifest)".to_string(), - ); - lines.join("\n") -} - -struct SurveySubjectPin { - source_commit: String, - source_tree: String, - survey_executable: String, - source_roots_digest: String, - probe_policy_revision: String, -} - -impl Clone for SurveySubjectPin { - fn clone(&self) -> Self { - Self { - source_commit: self.source_commit.clone(), - source_tree: self.source_tree.clone(), - survey_executable: self.survey_executable.clone(), - source_roots_digest: self.source_roots_digest.clone(), - probe_policy_revision: self.probe_policy_revision.clone(), - } - } -} - -fn subjects_equal(left: &SurveySubjectPin, right: &SurveySubjectPin) -> bool { - left.source_commit == right.source_commit - && left.source_tree == right.source_tree - && left.survey_executable == right.survey_executable - && left.source_roots_digest == right.source_roots_digest - && left.probe_policy_revision == right.probe_policy_revision -} - -fn attach_subject(row: ProbeReceiptRow, subject: &SurveySubjectPin) -> ProbeReceiptRow { - ProbeReceiptRow { - subject: subject.clone(), - ..row - } -} - -fn validate_lowercase_hex(label: &str, value: &str, expected_len: usize) -> Result<(), String> { - if value.len() != expected_len { - return Err(format!( - "SurveyPinRefused: {label} length {} != {}", - value.len(), - expected_len - )); - } - if !value - .chars() - .all(|c| c.is_ascii_digit() || ('a'..='f').contains(&c)) - { - return Err(format!("SurveyPinRefused: {label} is not lowercase hex")); - } - Ok(()) -} - -fn git_output(args: &[&str]) -> Result { - let out = Command::new("git") - .args(args) - .output() - .map_err(|e| format!("SurveyPinRefused: git {args:?} spawn failed: {e}"))?; - if !out.status.success() { - return Err(format!( - "SurveyPinRefused: git {args:?} failed: {}", - String::from_utf8_lossy(&out.stderr) - )); - } - Ok(String::from_utf8_lossy(&out.stdout).trim().to_string()) -} - -fn ensure_clean_tree() -> Result<(), String> { - let porcelain = git_output(&["status", "--porcelain"])?; - if !porcelain.is_empty() { - return Err( - "SurveyPinRefused: dirty working tree — run from a clean detached worktree at the selected commit" - .to_string(), - ); - } - Ok(()) -} - -fn frontier_probe_source_roots_digest_rust(source_roots: &[String]) -> String { - // SCAFFOLD — duplicates v2.compiler.self_host.frontier_probe_types - // frontier_probe_source_roots_digest (same structural fold). Dissolve-on: frontier_probe_survey - // self-emits from the .dag authority once emit crosses this module. - source_roots - .iter() - .fold( - content_hash_atom("frontier-probe-source-roots".to_string()), - |acc, root| content_hash_combine_structural(acc, content_hash_atom(root.clone())), - ) - .digest - .clone() -} - -fn frontier_probe_policy_revision_digest_rust() -> String { - // SCAFFOLD — duplicates frontier_probe_policy_revision() in frontier_probe_types.dag. - // Dissolve-on: same emit-crosses-module trigger as frontier_probe_source_roots_digest_rust. - content_hash_atom("frontier-probe-survey-policy-v1".to_string()) - .digest - .clone() -} - -fn verify_build_provenance(subject: &SurveySubjectPin) -> Result<(), String> { - const BUILD_DIRTY: Option<&str> = option_env!("FRONTIER_PROBE_SURVEY_BUILD_DIRTY"); - if BUILD_DIRTY == Some("1") { - return Err( - "SurveyPinRefused: binary built from dirty worktree — rebuild from clean sources" - .to_string(), - ); - } - const BUILD_COMMIT: Option<&str> = option_env!("FRONTIER_PROBE_SURVEY_BUILD_COMMIT"); - const BUILD_TREE: Option<&str> = option_env!("FRONTIER_PROBE_SURVEY_BUILD_TREE"); - match (BUILD_COMMIT, BUILD_TREE) { - (Some(build_commit), Some(build_tree)) - if !build_commit.is_empty() && !build_tree.is_empty() => - { - if subject.source_commit != build_commit { - return Err(format!( - "SurveyPinRefused: binary built at commit {build_commit} but survey subject is {}", - subject.source_commit - )); - } - if subject.source_tree != build_tree { - return Err(format!( - "SurveyPinRefused: binary built at tree {build_tree} but survey subject tree is {}", - subject.source_tree - )); - } - Ok(()) - } - _ => Err( - "SurveyPinRefused: frontier_probe_survey missing embedded build provenance — rebuild with cargo build" - .to_string(), - ), - } -} - -fn resolve_survey_subject(source_roots: &[String]) -> Result { - ensure_clean_tree()?; - let source_commit = git_output(&["rev-parse", "HEAD"])?; - validate_lowercase_hex("source_commit", &source_commit, 40)?; - let source_tree = git_output(&["rev-parse", "HEAD^{tree}"])?; - validate_lowercase_hex("source_tree", &source_tree, 40)?; - let exe_path = std::env::current_exe() - .map_err(|e| format!("SurveyPinRefused: current_exe unavailable: {e}"))?; - let bytes = fs::read(&exe_path).map_err(|e| { - format!( - "SurveyPinRefused: read survey executable {:?}: {e}", - exe_path - ) - })?; - use sha2::{Digest, Sha256}; - let survey_executable = format!("{:x}", Sha256::digest(bytes)); - validate_lowercase_hex("survey_executable", &survey_executable, 64)?; - let source_roots_digest = frontier_probe_source_roots_digest_rust(source_roots); - validate_lowercase_hex("source_roots_digest", &source_roots_digest, 16)?; - let probe_policy_revision = frontier_probe_policy_revision_digest_rust(); - validate_lowercase_hex("probe_policy_revision", &probe_policy_revision, 16)?; - Ok(SurveySubjectPin { - source_commit, - source_tree, - survey_executable, - source_roots_digest, - probe_policy_revision, - }) -} - -fn resolve_and_verify_survey_subject(source_roots: &[String]) -> Result { - let subject = resolve_survey_subject(source_roots)?; - verify_build_provenance(&subject)?; - Ok(subject) -} - -fn load_probe_rows_from_tsv(path: &Path) -> Result, String> { - let body = fs::read_to_string(path).map_err(|e| format!("read tsv {:?}: {e}", path))?; - let mut rows = Vec::new(); - for (lineno, line) in body.lines().enumerate() { - if lineno == 0 { - continue; - } - if line.trim().is_empty() { - continue; - } - let parts: Vec<&str> = line.split('\t').collect(); - if parts.len() < 13 { - return Err(format!( - "malformed tsv line {}: expected 13 subject/receipt columns, got {line}", - lineno + 1 - )); - } - let subject = SurveySubjectPin { - source_commit: parts[1].to_string(), - source_tree: parts[2].to_string(), - survey_executable: parts[3].to_string(), - source_roots_digest: parts[4].to_string(), - probe_policy_revision: parts[5].to_string(), - }; - rows.push(ProbeReceiptRow { - module_path: parts[0].to_string(), - subject, - blocker_variant: parts[7].to_string(), - located_stage: parts[8].to_string(), - located_reason: parts[9].to_string(), - rejection_chain: parts[10].to_string(), - overlap_roster_detail: parts[11].to_string(), - detail: "FrontierProbeDetailAbsent".to_string(), - assemble_detail_manifest: "NoFrontierProbeDetail".to_string(), - probe_error: if parts[12].is_empty() { - None - } else { - Some(parts[12].to_string()) - }, - }); - } - if rows.is_empty() { - return Err("receipt tsv has zero data rows".to_string()); - } - let first = &rows[0].subject; - for (idx, row) in rows.iter().enumerate().skip(1) { - if !subjects_equal(first, &row.subject) { - return Err(format!( - "SurveySubjectMismatch: row {} subject {} != row 1 subject {}", - idx + 1, - row.subject.source_commit, - first.source_commit - )); - } - } - Ok(rows) -} - -fn run() -> Result { - let args: Vec = std::env::args().collect(); - let mut source_roots: Vec = Vec::new(); - let mut survey_manifest: Option = None; - let mut survey_tsv: Option = None; - let mut survey_dir: Option = None; - let mut only_modules: Vec = Vec::new(); - let mut used_module_filter = false; - let mut emit_manifest_only = false; - let mut receipt_tsv: Option = None; - - let mut i = 1; - while i < args.len() { - match args[i].as_str() { - "--source-root" => { - i += 1; - source_roots.push(require_value(&args, i, "--source-root")?); - } - "--module" => { - i += 1; - only_modules.push(require_value(&args, i, "--module")?); - used_module_filter = true; - } - "--emit-survey-manifest" => { - i += 1; - survey_manifest = Some(PathBuf::from(require_value( - &args, - i, - "--emit-survey-manifest", - )?)); - } - "--emit-tsv" => { - i += 1; - survey_tsv = Some(PathBuf::from(require_value(&args, i, "--emit-tsv")?)); - } - "--survey-dir" => { - i += 1; - survey_dir = Some(PathBuf::from(require_value(&args, i, "--survey-dir")?)); - } - "--emit-manifest-only" => { - emit_manifest_only = true; - } - "--receipt-tsv" => { - i += 1; - receipt_tsv = Some(PathBuf::from(require_value(&args, i, "--receipt-tsv")?)); - } - other => { - eprintln!("frontier_probe_survey: unknown argument: {other}"); - return Err(ExitCode::from(2)); - } - } - i += 1; - } - - if source_roots.is_empty() { - eprintln!("frontier_probe_survey: provide at least one --source-root"); - return Err(ExitCode::from(2)); - } - let subject = resolve_and_verify_survey_subject(&source_roots).map_err(|msg| { - eprintln!("frontier_probe_survey: {msg}"); - ExitCode::from(1) - })?; - let survey_manifest = survey_manifest.ok_or_else(|| { - eprintln!("frontier_probe_survey: --emit-survey-manifest required"); - ExitCode::from(2) - })?; - - if emit_manifest_only { - let tsv_path = receipt_tsv.ok_or_else(|| { - eprintln!("frontier_probe_survey: --emit-manifest-only requires --receipt-tsv"); - ExitCode::from(2) - })?; - let rows = load_probe_rows_from_tsv(&tsv_path).map_err(|msg| { - eprintln!("frontier_probe_survey: {msg}"); - ExitCode::from(1) - })?; - if !subjects_equal(&rows[0].subject, &subject) { - eprintln!( - "frontier_probe_survey: SurveySubjectMismatch: receipt tsv subject {} != current subject {}", - rows[0].subject.source_commit, subject.source_commit - ); - return Err(ExitCode::from(1)); - } - emit_survey_manifest(&survey_manifest, &rows, &rows[0].subject).map_err(|msg| { - eprintln!("frontier_probe_survey: {msg}"); - ExitCode::from(1) - })?; - eprintln!( - "frontier_probe_survey: wrote {} ({} receipt(s), manifest-only)", - survey_manifest.display(), - rows.len() - ); - return Ok(ExitCode::from(0)); - } - - let survey_dir = survey_dir.unwrap_or_else(|| { - survey_manifest - .parent() - .map(Path::to_path_buf) - .unwrap_or_else(|| PathBuf::from("target/frontier-probe-survey")) - }); - fs::create_dir_all(&survey_dir).map_err(|e| { - eprintln!("frontier_probe_survey: mkdir {:?}: {e}", survey_dir); - ExitCode::from(1) - })?; - - let mut module_paths = load_compiler_frontier_sweep_order(&source_roots).map_err(|msg| { - eprintln!("frontier_probe_survey: {msg}"); - ExitCode::from(1) - })?; - if !only_modules.is_empty() { - module_paths = only_modules; - } - if module_paths.is_empty() { - eprintln!("frontier_probe_survey: no module paths to probe"); - return Err(ExitCode::from(1)); - } - if used_module_filter { - eprintln!( - "frontier_probe_survey: probing {} module path(s) (--module filter)", - module_paths.len() - ); - } else { - eprintln!( - "frontier_probe_survey: probing {} module path(s) from {SWEEP_ORDER_DATA}", - module_paths.len() - ); - } - - let host_failure_reasons = load_host_failure_reasons(&source_roots).map_err(|msg| { - eprintln!("frontier_probe_survey: {msg}"); - ExitCode::from(1) - })?; - - let mut rows: Vec = Vec::new(); - for module_path in &module_paths { - eprintln!("frontier_probe_survey: probing {module_path}"); - match run_probe_for_module(&source_roots, &survey_dir, module_path) { - Ok(row) => { - eprintln!( - " blocker={} stage={} reason={} chain={} overlap={}", - row.blocker_variant, - row.located_stage, - row.located_reason, - row.rejection_chain, - row.overlap_roster_detail - ); - rows.push(attach_subject(row, &subject)); - } - Err(msg) => { - let cause = if msg.contains("EvalBudgetExceeded") || msg.contains("OOM") { - host_failure_reasons.oom_or_budget.as_str() - } else { - host_failure_reasons.runtime_error.as_str() - }; - eprintln!("frontier_probe_survey: {module_path}: {msg} -> Unknown({cause})"); - rows.push(unknown_probe_row(module_path, cause, &subject)); - } - } - } - - emit_survey_manifest(&survey_manifest, &rows, &subject).map_err(|msg| { - eprintln!("frontier_probe_survey: {msg}"); - ExitCode::from(1) - })?; - if let Some(tsv_path) = survey_tsv { - emit_tsv(&tsv_path, &rows).map_err(|msg| { - eprintln!("frontier_probe_survey: {msg}"); - ExitCode::from(1) - })?; - eprintln!("frontier_probe_survey: wrote {}", tsv_path.display()); - } - let summary = cluster_summary(&rows); - eprintln!("{summary}"); - if let Some(parent) = survey_manifest.parent() { - let summary_path = parent.join("frontier_probe_survey_summary.txt"); - let _ = fs::write(&summary_path, &summary); - } - eprintln!( - "frontier_probe_survey: wrote {} ({} receipt(s))", - survey_manifest.display(), - rows.len() - ); - Ok(ExitCode::from(0)) -} - -fn main() -> ExitCode { - match run() { - Ok(code) => code, - Err(code) => code, - } -} diff --git a/src/v1/stage0/src/bootstrap_stage0_crate_layout_generated.rs b/src/v1/stage0/src/bootstrap_stage0_crate_layout_generated.rs index 2d39b7455b3..88cbad78e20 100644 --- a/src/v1/stage0/src/bootstrap_stage0_crate_layout_generated.rs +++ b/src/v1/stage0/src/bootstrap_stage0_crate_layout_generated.rs @@ -1,5 +1,5 @@ // Generated by gunbc stage0_crate_layout_emit — do not hand-edit. -// Authority: v2.compiler.self_host.frontier; regen via dag/tools/generated_artifact_gate.dag main_wet. +// Authority: v2.compiler.self_host.stage0_crate_layout; regen via dag/tools/generated_artifact_gate.dag main_wet. #[rustfmt::skip] pub const HAND_MAINTAINED_STAGE0_FILES: &[&str] = &[ diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index dfbf004d96b..b62d20c1268 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -1889,14 +1889,6 @@ mod compiler_tests { coerce_primitive_type(RenderTarget::Rust, "Hash".into()), "v1_rt::Hash" ); - assert_eq!( - coerce_primitive_type(RenderTarget::Rust, "Witness".into()), - "Witness" - ); - assert_eq!( - coerce_primitive_type(RenderTarget::Rust, "witness".into()), - "Witness" - ); } #[test] @@ -2085,8 +2077,6 @@ mod compiler_tests { assert_eq!(is_copy(RenderTarget::Rust, "Secret".into()), Some(false)); assert_eq!(is_copy(RenderTarget::Rust, "Json".into()), Some(false)); assert_eq!(is_copy(RenderTarget::Rust, "Hash".into()), Some(false)); - assert_eq!(is_copy(RenderTarget::Rust, "Witness".into()), Some(false)); - assert_eq!(is_copy(RenderTarget::Rust, "witness".into()), Some(false)); } #[test] diff --git a/src/v1/stage0/src/extdeps_languages_rust_types.rs b/src/v1/stage0/src/extdeps_languages_rust_types.rs index e4224f36571..c52f1de0d21 100644 --- a/src/v1/stage0/src/extdeps_languages_rust_types.rs +++ b/src/v1/stage0/src/extdeps_languages_rust_types.rs @@ -34,13 +34,22 @@ pub fn extdeps_external_authority_anchor() -> Rc { pub fn rust_type_checkpoints() -> Rc>> { thread_local! { static CACHED: Rc>> = { - serde_json::from_value(serde_json::json!([{"dag_name": "Int", "target_type": "i64", "default_expr": "0", "is_copy": true, "literal_suffix": null}, {"dag_name": "Float", "target_type": "f64", "default_expr": "0.0", "is_copy": true, "literal_suffix": null}, {"dag_name": "Bool", "target_type": "bool", "default_expr": "false", "is_copy": true, "literal_suffix": null}, {"dag_name": "Symbol", "target_type": "String", "default_expr": "String::new()", "is_copy": false, "literal_suffix": ".to_string()"}, {"dag_name": "Unit", "target_type": "()", "default_expr": "()", "is_copy": true, "literal_suffix": null}, {"dag_name": "String", "target_type": "String", "default_expr": "String::new()", "is_copy": false, "literal_suffix": ".to_string()"}, {"dag_name": "Bytes", "target_type": "Vec", "default_expr": "Vec::new()", "is_copy": false, "literal_suffix": null}, {"dag_name": "Secret", "target_type": "String", "default_expr": "String::new()", "is_copy": false, "literal_suffix": ".to_string()"}, {"dag_name": "Json", "target_type": "serde_json::Value", "default_expr": "serde_json::Value::Null", "is_copy": false, "literal_suffix": null}, {"dag_name": "Hash", "target_type": "v1_rt::Hash", "default_expr": null, "is_copy": false, "literal_suffix": ".to_string()"}, {"dag_name": "Witness", "target_type": "Witness", "default_expr": null, "is_copy": false, "literal_suffix": null}, {"dag_name": "witness", "target_type": "Witness", "default_expr": null, "is_copy": false, "literal_suffix": null}])) + serde_json::from_value(serde_json::json!([{"dag_name": "Int", "target_type": "i64", "default_expr": "0", "is_copy": true, "literal_suffix": null}, {"dag_name": "Float", "target_type": "f64", "default_expr": "0.0", "is_copy": true, "literal_suffix": null}, {"dag_name": "Bool", "target_type": "bool", "default_expr": "false", "is_copy": true, "literal_suffix": null}, {"dag_name": "Symbol", "target_type": "String", "default_expr": "String::new()", "is_copy": false, "literal_suffix": ".to_string()"}, {"dag_name": "Unit", "target_type": "()", "default_expr": "()", "is_copy": true, "literal_suffix": null}, {"dag_name": "String", "target_type": "String", "default_expr": "String::new()", "is_copy": false, "literal_suffix": ".to_string()"}, {"dag_name": "Bytes", "target_type": "Vec", "default_expr": "Vec::new()", "is_copy": false, "literal_suffix": null}, {"dag_name": "Secret", "target_type": "String", "default_expr": "String::new()", "is_copy": false, "literal_suffix": ".to_string()"}, {"dag_name": "Json", "target_type": "serde_json::Value", "default_expr": "serde_json::Value::Null", "is_copy": false, "literal_suffix": null}, {"dag_name": "Hash", "target_type": "v1_rt::Hash", "default_expr": null, "is_copy": false, "literal_suffix": ".to_string()"}])) .expect("valid data definition") }; } CACHED.with(|c: &Rc>>| c.clone()) } +pub fn rust_checkpoint_scalar_arity_note() -> String { + thread_local! { + static CACHED: String = { + "A TypeCheckpoint row states one thing: how a target SPELLS a dag type whose Rust arity is zero. It cannot express arity, so membership of this table IS the emitter's arity-0 claim — v1.compiler.05_emit_rust rust_scalar_checkpoint_render_base reads it, and rust_render_checkpoint_scalar_bare strips every type argument from any leaf it matches (the E0109 wall, rust_checkpoint_scalar_phantom_params_note). Witness/witness rows were removed here 2026-08-16: Witness is the generic enum v2.std.witness.Witness (src/v2/std/witness.dag), arity 1 by its single authority std.types container_type_arity, so the rows made the emitter drop the argument of every Witness in type position and emit `Rc` — rustc E0107 'missing generics for enum Witness', 4 sites in the 06_translate closure alone (docs/probes/root_d_generic_arity_2026-08-16.md). Nothing else was lost with them: coerce_primitive_type renders the bare leaf name 'Witness' through qualified_last_segment either way, and is_copy's Absent arm and Present{false} arm are the same decision at every consumer. A generic type may not be added to this table; its spelling is not the missing fact, its arity is.".to_string() + }; + } + CACHED.with(|c: &String| c.clone()) +} + pub fn rust_algebra_inhabitants() -> Rc>> { thread_local! { static CACHED: Rc>> = { diff --git a/src/v1/stage0/src/gunbc_stage0_crate_layout_generated.rs b/src/v1/stage0/src/gunbc_stage0_crate_layout_generated.rs index 1f74e42f4cc..3612a52fb9a 100644 --- a/src/v1/stage0/src/gunbc_stage0_crate_layout_generated.rs +++ b/src/v1/stage0/src/gunbc_stage0_crate_layout_generated.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub fn stage0_crate_layout_generated_note() -> String { thread_local! { static CACHED: String = { - "Generated by gunbc stage0_crate_layout_emit — do not hand-edit. Authority: v2.compiler.self_host.frontier; regen via dag/tools/generated_artifact_gate.dag main_wet.".to_string() + "Generated by gunbc stage0_crate_layout_emit — do not hand-edit. Authority: v2.compiler.self_host.stage0_crate_layout; regen via dag/tools/generated_artifact_gate.dag main_wet.".to_string() }; } CACHED.with(|c: &String| c.clone()) diff --git a/src/v1/stage0/src/v1_compiler_emit_rust.rs b/src/v1/stage0/src/v1_compiler_emit_rust.rs index 524d229e1e3..504a329b789 100644 --- a/src/v1/stage0/src/v1_compiler_emit_rust.rs +++ b/src/v1/stage0/src/v1_compiler_emit_rust.rs @@ -772,6 +772,15 @@ pub fn rust_scalar_checkpoint_render_base( } } +pub fn rust_checkpoint_scalar_declared_arity_guard_note() -> String { + thread_local! { + static CACHED: String = { + "The strip below reads table MEMBERSHIP as the proposition 'this leaf has arity 0 in Rust'. A TypeCheckpoint row cannot state arity — it states target spelling — so the two facts 'this is a scalar' and 'I have a spelling for this name' arrive as one Present, and the arm answers 'drop every type argument' to both. That is DESIGN section 5's widening failure arm: the dropped argument leaves plausible output rather than a diagnostic, so the deficit's frequency was zero by construction until rustc reported E0107. The guard consults the single arity authority (std.types is_container_type / container_expected_arity) FIRST, so a leaf with declared arity can never be classified scalar however the target's spelling table is edited. Receipt: docs/probes/root_d_generic_arity_2026-08-16.md.".to_string() + }; + } + CACHED.with(|c: &String| c.clone()) +} + pub fn rust_checkpoint_scalar_phantom_params_note() -> String { thread_local! { static CACHED: String = { @@ -792,6 +801,9 @@ pub fn rust_render_checkpoint_scalar_bare( } else { { let leaf = rust_fn_sig_leaf_name(source_indices.clone(), n.clone()); + if is_container_type(leaf.clone()) { + return None; + } match rust_scalar_checkpoint_render_base(leaf.clone(), corpus_repr.clone()) { Some(scalar) => { if (v1_rt::set_contains(&shared_types, leaf.clone()) @@ -893,7 +905,7 @@ pub fn rust_witness_parent_leaf(parent: String) -> bool { pub fn rust_witness_variant_arm_names_note() -> String { thread_local! { static CACHED: String = { - "Holds/Violates literals below are the two arms of std.witness.Witness (dag/std/witness.dag) — not minted nicknames. Pattern position routes via variant_pattern_qualified_path like any other modeled enum; construction turbofish here keys type-arg resolution off the modeled arm names only.".to_string() + "Holds/Violates literals below are the two arms of v2.std.witness.Witness (src/v2/std/witness.dag; this citation read std.witness / dag/std/witness.dag until 2026-08-16, naming a module that does not exist in the tree) — not minted nicknames. Pattern position routes via variant_pattern_qualified_path like any other modeled enum; construction turbofish here keys type-arg resolution off the modeled arm names only.".to_string() }; } CACHED.with(|c: &String| c.clone()) @@ -2004,6 +2016,7 @@ if peel.clone() { shared_types.clone(), corpus_repr.clone(), source_indices.clone(), + env.clone(), ) } } @@ -2209,6 +2222,7 @@ pub fn render_rust_fn_sig_type_applied_binding( shared_types.clone(), corpus_repr.clone(), source_indices.clone(), + env.clone(), ) } } @@ -2218,6 +2232,7 @@ pub fn render_rust_fn_sig_type_applied_binding( shared_types.clone(), corpus_repr.clone(), source_indices.clone(), + env.clone(), ) } } @@ -2226,6 +2241,7 @@ pub fn render_rust_fn_sig_type_applied_binding( shared_types.clone(), corpus_repr.clone(), source_indices.clone(), + env.clone(), ), } } @@ -6754,7 +6770,7 @@ pub fn expand_variant_payload_struct_imports( pub fn reference_derived_authored_source_gate_note() -> String { thread_local! { static CACHED: String = { - "reference_derived_use_lines synthesizes a use-line only when the candidate name appears in this module's authored source text (NewlineIndex char_codes). A name that enters the candidate set only via inferred/type-summary over-collection — never spelled in the module — must not become a pub use. Empty/unavailable module source REFUSES every candidate (fail-closed): ⊤-as-ignorance must not admit the full candidate set (§5 absorbing fallback). Receipt: after occurrence-binding stage0 enrollment, AuthoredTokenOrdinal entered the registry and std.http_path (which never mentions it) emitted a fabricated pub use. UnlistedImportUse names are already spelled at the use site, so they pass when source text is readable; variant-parent enums that appear only via from_variant still require their parent spelling OR an authored variant ctor whose parent is harvested — parent-only imports without any authored spelling of parent or variant remain a separate gap, not this gate's subject. Dissolve-on: derive use-lines from the module's bound-reference structure (P2a candidate-producer / BoundReferenceProvider) — this text-presence gate is the conservative interim, not the destination.".to_string() + "reference_derived_use_lines synthesizes a use-line only for a candidate the module's authored source text ATTESTS (NewlineIndex char_codes), and there are exactly two attesting forms, both decided by reference_derived_candidate_authored. Direct: the candidate's own name is spelled. Variant-induced: the candidate is a unit-only enum and the module spells at least one variant that binds UNAMBIGUOUSLY back to it — derive_variant_to_enum maps a variant shared by two enums to the empty string, so a homonym never equals the enum name and is REFUSED rather than picked. A name that enters the candidate set only via inferred/type-summary over-collection — attested by neither form — must not become a pub use. Empty/unavailable module source REFUSES every candidate (fail-closed): ⊤-as-ignorance must not admit the full candidate set (§5 absorbing fallback). Receipt: after occurrence-binding stage0 enrollment, AuthoredTokenOrdinal entered the registry and std.http_path (which never mentions it) emitted a fabricated pub use — that name is a record, not a unit-only enum, so the variant-induced arm cannot readmit it. Second receipt (Root K): the emitter qualifies variants as Parent::Variant in pattern and nested-argument positions where the source spells only the variant, so asking whether the PARENT was spelled refused a parent the module demonstrably uses — 109 of 132 sites. UnlistedImportUse names are already spelled at the use site, so they pass when source text is readable. Declared residue, in two classes that fail at DIFFERENT stages — this gate is a filter over a candidate set, so it can only refuse, never propose. Refused HERE: a parent enum with neither its own name nor any binding variant spelled, and a non-enum candidate whose only evidence is over-collection. Never REACHING here, and therefore unfixable by any gate decision: a name the candidate collector never proposes. Measured by execution — forcing this gate to admit unconditionally and re-emitting v2.lens.complexity_accumulator_copy.analyze still produces no use-line for Behavior, whose unit-only variant Transform is spelled bare in a pattern position and binds unambiguously, so the arm's preconditions hold and the name is simply absent upstream. That class is pre-existing and unchanged by Root K (identical count in both arms), and it is where the remaining sites live: widening this gate further cannot reach them. Dissolve-on: derive use-lines from the module's bound-reference structure (P2a candidate-producer / BoundReferenceProvider) — this text-attestation gate is the conservative interim, not the destination.".to_string() }; } CACHED.with(|c: &String| c.clone()) @@ -6779,6 +6795,57 @@ pub fn reference_derived_candidate_spelled_in_module(module_source: String, name && v1_rt::string_contains(&module_source, name.clone())) } +pub fn reference_derived_variant_induced_parent_spelled( + module_source: String, + enum_name: String, + type_summaries: Rc>>, + variant_to_enum: Rc>, +) -> bool { + match v1_rt::map_get(&type_summaries, enum_name.clone()) { + Some(summary) => match (*summary.repr.clone()).clone() { + TypeRepr::EnumRepr { unit_only: _, .. } => { + let mut __found = false; + for vn in Rc::new(v1_rt::sorted_map_keys(&summary.variant_name_set.clone())) + .iter() + .cloned() + { + if match v1_rt::map_get(&variant_to_enum, vn.clone()) { + Some(parent) => { + ((parent.clone() == enum_name.clone()) + && reference_derived_candidate_spelled_in_module( + module_source.clone(), + vn.clone(), + )) + } + None => false, + } { + __found = true; + break; + } + } + __found + } + _ => false, + }, + None => false, + } +} + +pub fn reference_derived_candidate_authored( + module_source: String, + name: String, + type_summaries: Rc>>, + variant_to_enum: Rc>, +) -> bool { + (reference_derived_candidate_spelled_in_module(module_source.clone(), name.clone()) + || reference_derived_variant_induced_parent_spelled( + module_source.clone(), + name.clone(), + type_summaries.clone(), + variant_to_enum.clone(), + )) +} + pub fn reference_derived_use_lines( items: Rc>>, unlisted_type_names: Rc>, @@ -6866,9 +6933,11 @@ pub fn reference_derived_use_lines( .iter() .cloned() { - if reference_derived_candidate_spelled_in_module( + if reference_derived_candidate_authored( module_source.clone(), name.clone(), + emit_info.type_summaries.clone(), + emit_info.variant_to_enum.clone(), ) { __result.push(name); } @@ -12681,11 +12750,21 @@ pub fn emit_struct_from_children( } } +pub fn render_rust_type_applied_binding_env_note() -> String { + thread_local! { + static CACHED: String = { + "Construction wall for the zero-parameter-alias applied-argument class (E0107 'type alias takes 0 generic arguments but N were supplied'). A reference to a closed alias arrives at the emitter carrying the RESOLVED DEFINITION's type arguments as its children while its authored spelling is still the alias name, so a renderer that prints name-plus-children emits ClosedCarrierAlias for a Rust alias declared with no parameters. Four renderers already refuse that shape by asking the single peel authority rust_fn_sig_peel_closed_alias: render_rust_applied_type, render_rust_decl_type, render_rust_fn_sig_type and render_rust_alias_rhs_type. This function is the fifth path, and it did NOT lack the guard -- it reached render_rust_applied_type, which asked, and was answered with an EMPTY TypeEnv this function constructed inline plus an empty_emit_graph_info() it passed to render_rust_type. An empty env resolves no binding, and the peel predicate renders 'I could not look this up' identically to 'this declaration has parameters' -- the state-space conflation DESIGN section 5 names, failing open into the widened applied form rather than refusing. Every one of this function's callers already holds the TypeEnv it was discarding, so the fix is to stop discarding it: the peel authority stays the single authority and is simply answered truthfully. Measured on the src/v2/compiler/03_ingest.dag closure. The next rung is upstream and not taken here: an alias reference that preserved its AUTHORED arity would make the bad shape unwritable rather than merely refused, at which point no renderer would need to ask at all.".to_string() + }; + } + CACHED.with(|c: &String| c.clone()) +} + pub fn render_rust_type_with_applied_binding( n: Rc, shared_types: Rc>, corpus_repr: RustCorpusRepr, source_indices: Rc>>, + env: Rc, ) -> String { { if is_host_text_carrier_type(n.clone(), source_indices.clone(), corpus_repr.clone()) { @@ -12721,29 +12800,7 @@ pub fn render_rust_type_with_applied_binding( corpus_repr.clone(), source_indices.clone(), v1_rt::rc_empty_map::(), - Rc::new(TypeEnv { - module_path: "".to_string(), - bindings: v1_rt::rc_empty_map::>(), - str_bindings: v1_rt::rc_empty_map::>( - ), - ancestry_str_bindings: v1_rt::rc_empty_map::< - String, - Rc, - >( - ), - parents: Rc::new(vec![]), - recursive_types: Rc::new(vec![]), - recursive_type_set: v1_rt::rc_empty_map::(), - inductive_fields: v1_rt::rc_empty_map::< - String, - Rc>>, - >( - ), - source_indices: source_indices.clone(), - intern_table: empty_intern_table(), - source_visible_names: v1_rt::rc_empty_map::(), - symbol_index: empty_symbol_index(), - }), + env.clone(), ) } } else { @@ -12754,26 +12811,7 @@ pub fn render_rust_type_with_applied_binding( corpus_repr.clone(), source_indices.clone(), v1_rt::rc_empty_map::(), - Rc::new(TypeEnv { - module_path: "".to_string(), - bindings: v1_rt::rc_empty_map::>(), - str_bindings: v1_rt::rc_empty_map::>(), - ancestry_str_bindings: v1_rt::rc_empty_map::< - String, - Rc, - >(), - parents: Rc::new(vec![]), - recursive_types: Rc::new(vec![]), - recursive_type_set: v1_rt::rc_empty_map::(), - inductive_fields: v1_rt::rc_empty_map::< - String, - Rc>>, - >(), - source_indices: source_indices.clone(), - intern_table: empty_intern_table(), - source_visible_names: v1_rt::rc_empty_map::(), - symbol_index: empty_symbol_index(), - }), + env.clone(), ) } } @@ -12783,7 +12821,11 @@ pub fn render_rust_type_with_applied_binding( shared_types.clone(), corpus_repr.clone(), source_indices.clone(), - empty_emit_graph_info(), + emit_info_with_fn_type_context( + empty_emit_graph_info(), + Rc::new(vec![]), + env.clone(), + ), ) } } @@ -12792,7 +12834,11 @@ pub fn render_rust_type_with_applied_binding( shared_types.clone(), corpus_repr.clone(), source_indices.clone(), - empty_emit_graph_info(), + emit_info_with_fn_type_context( + empty_emit_graph_info(), + Rc::new(vec![]), + env.clone(), + ), ), } } @@ -12831,6 +12877,7 @@ pub fn render_rust_field_type_with_applied_binding( shared_types.clone(), corpus_repr.clone(), source_indices.clone(), + env.clone(), ) } else { if (find_property( @@ -12844,6 +12891,7 @@ pub fn render_rust_field_type_with_applied_binding( shared_types.clone(), corpus_repr.clone(), source_indices.clone(), + env.clone(), ) } else { if ((authored_type.connective.clone() == Connective::NoConnective) @@ -12862,6 +12910,7 @@ pub fn render_rust_field_type_with_applied_binding( shared_types.clone(), corpus_repr.clone(), source_indices.clone(), + env.clone(), ) } } @@ -12904,6 +12953,7 @@ pub fn emit_struct_field_from_child( shared_types.clone(), emit_info.corpus_repr.clone(), env.source_indices.clone(), + env.clone(), ) } else { if (find_property( @@ -12917,6 +12967,7 @@ pub fn emit_struct_field_from_child( shared_types.clone(), emit_info.corpus_repr.clone(), env.source_indices.clone(), + env.clone(), ) } else { if (find_property( @@ -12930,6 +12981,7 @@ pub fn emit_struct_field_from_child( shared_types.clone(), emit_info.corpus_repr.clone(), env.source_indices.clone(), + env.clone(), ) } else { if ((is_product_type(rt_child.clone()) @@ -13976,6 +14028,7 @@ pub fn emit_variant_from_child( shared_types.clone(), emit_info.corpus_repr.clone(), env.source_indices.clone(), + env.clone(), ) } else { raw_ty.clone() @@ -29096,6 +29149,7 @@ pub fn emit_data_def( shared_types.clone(), emit_info.corpus_repr.clone(), scope.type_env.clone().source_indices.clone(), + scope.type_env.clone(), ) } }; diff --git a/src/v2/compiler/self_host/emitter_producer_provenance.dag b/src/v2/compiler/self_host/emitter_producer_provenance.dag index 1ed62868f88..d44f9cd35cd 100644 --- a/src/v2/compiler/self_host/emitter_producer_provenance.dag +++ b/src/v2/compiler/self_host/emitter_producer_provenance.dag @@ -1,21 +1,6 @@ module v2.compiler.self_host.emitter_producer_provenance import std.content_hash { content_hash_atom } -import v2.compiler.self_host.frontier_probe_types { - FrontierProbeDetailAbsent, - NoFrontierProbeDetail, - FrontierProbeReceipt, - FrontierProbeStage, - ProbeStageEmit, - SelfEmitReady -} -import tools.self_host_module_behavioral_transport_roster { - module_behavioral_transport_config_for -} -import v2.compiler.self_host.seed_emitter_behavioral_wet_known_red_entries { - schedule_witness_entry_cited, - seed_emitter_behavioral_wet_known_red_entries -} import v2.std.algebra { any, fold_list, length } import v2.std.collection { List } import v2.std.logic { Bool } @@ -29,8 +14,32 @@ import v2.std.optional { } import v2.std.text { String } -data emitter_producer_provenance_note: String = "CompilerFixedPoint producer/qualification authority (session valiant-crab-382, calm-badger-682 ruling 2026-07-29): replaces SelfEmitted state-space conflation with orthogonal EmitterProducer x EmissionQualification axes. A frontier EmitterProduced row is reachable ONLY from a ProducerEmissionReceipt minted through mint_producer_emission_receipt — never from a hand-authored ProducerEmissionReceipt literal in a data row (review 44333). Static oracle derivation never mints BuildGreen (reviews 44441/44455/44460/44468). producer_emission_canonical_receipt_for_executed_verdict is unwritable at baseline (always Absent) until witness-realization + frontier_probe_survey bind execution-measured verdict digests. Wet execution proof: each enrolled probe witness runs tools.self_host_module_behavioral_transport_roster.compiler_module_behavioral_receipt_for. Structural wall: V2Emitter* is unwritable when v1.compiler.emit_rust is in the realized closure." - +data emitter_producer_provenance_note: String = "Producer/qualification authority for emitted Rust: orthogonal EmitterProducer x EmissionQualification axes, replacing the SelfEmitted state-space conflation (session valiant-crab-382, calm-badger-682 ruling 2026-07-29). A ProducerEmissionReceipt is reachable only through mint_producer_emission_receipt, never as a hand-authored literal in a data row (review 44333), and a receipt advances along the qualification axis only through an admission its current state permits. Structural wall: a V2Emitter* producer is unwritable when v1.compiler.emit_rust is in the realized closure, which is what makes the closure carriers load-bearing rather than descriptive. The roster-authorization half of this module was deleted with the self-host frontier roster; the annotation above type EmitterProducer records what went and what survived." + +// HALF OF THIS MODULE WAS DELETED with v2.compiler.self_host.frontier, because that half had +// exactly one subject: authorizing an EmitterProduced row on the 27-row self-host frontier +// roster. Gone are the ProducerEmissionOracleRow population and its enrollment/transport-roster +// joins, the executed-verdict authorization pipeline, AuthorizedEmitterProducedDisposition and +// its registry bindings, the hand-forgery refusal controls, the ProducerQualifiedCountAxis +// projections, and the five producer-qualified baselines. Every one of them answered a question +// about roster rows; with no roster there are no rows to authorize, and the machinery could not +// be reached even in principle. +// +// What survives is the part that was never about the roster: the EmitterProducer x +// EmissionQualification axes, the realized-closure carriers and the seed-reachability wall over +// them, the receipt type with its admission-gated advances, the single mint, and the structural +// equalities. Its live consumers are v2.compiler.self_host.candidate_generation, +// v2.compiler.self_host.v2_emitter_direct_rust_door_contract and +// v2.lens.production_qualification_origin_probe — none of which ever read a roster row. +// +// An honest note on what the deletion removed in evidence terms: the forgery controls +// (hand_forged_emitter_produced_authorization_fails_mint_consistency_holds and its siblings) +// proved that an unauthorized EmitterProduced disposition was unwritable. That claim is not +// weakened, it is RETIRED — the disposition type it guarded no longer exists, so there is no +// state left to forge. DESIGN section 4b permits retiring evidence whose only subject is gone; +// it forbids retiring evidence for a claim that survives. The surviving claims here — that a +// V2Emitter receipt cannot be minted with the seed emitter in its realized closure, and that a +// receipt cannot advance past its admission — keep their controls. type EmitterProducer = V1SeedEmitter | V2EmitterInterpreted @@ -130,21 +139,6 @@ type ProducerEmissionReceipt { realized_closure: RealizedEmitterClosure } -type ProducerEmissionOracleRow { - module_path: String - measured_probe: FrontierProbeReceipt - behavioral_probe_entry: String - behavioral_probe_function: String -} - -type ProducerEmissionExecutedGreenReceipt { - module_path: String - behavioral_probe_entry: String - behavioral_probe_function: String - wet_execution_digest: Hash -} - -data producer_emission_executed_green_receipts_note: String = "Witness-realization mint contract (reviews 44455/44460/44465/44468): ProducerEmissionExecutedGreenReceipt type names the future executed-verdict carrier. producer_emission_canonical_receipt_for_executed_verdict is unwritable at baseline (always Absent) — no synthesizable digest from declarative oracle fields can mint BuildGreen. Dissolve-on: frontier_probe_survey binds execution-measured verdict digests; witness-realization becomes the sole host minter. Static oracle derivation never mints BuildGreen." data v1_seed_emit_rust_qualified_module: String = "v1.compiler.emit_rust" @@ -397,210 +391,6 @@ fn mint_producer_emission_receipt( } } -fn producer_emission_measured_probe_receipt(module_path: String) -> FrontierProbeReceipt { - FrontierProbeReceipt { - module_path: module_path, - blocker_class: SelfEmitReady, - located_stage: ProbeStageEmit, - located_reason: ^measured_probe_self_emit_ready, - detail: FrontierProbeDetailAbsent, - assemble_detail: NoFrontierProbeDetail - } -} - -data producer_emission_receipt_digest_scaffold_note: String = "SCAFFOLD (review 44333 partial landing): mint_producer_emission_receipt still keys digests on symbol_identity_digest scaffolds until frontier_probe_survey binds execution-measured module/emitter/emitted-source hashes. The construction wall landed here is: (1) no hand-authored ProducerEmissionReceipt in oracle data rows; (2) BuildRefused cannot authorize EmitterProduced; (3) every oracle row's probe has a matching compiler_module_behavioral_transport_roster row executed by its wet witness." - -fn seed_emitter_behavioral_oracle_row( - module_path: String, - behavioral_probe_entry: String, - behavioral_probe_function: String -) -> ProducerEmissionOracleRow { - ProducerEmissionOracleRow { - module_path: module_path, - measured_probe: producer_emission_measured_probe_receipt(module_path: module_path), - behavioral_probe_entry: behavioral_probe_entry, - behavioral_probe_function: behavioral_probe_function - } -} - -fn producer_emission_oracle_probe_is_known_red_quarantine(row: ProducerEmissionOracleRow) -> Bool { - producer_emission_oracle_probe_is_enrolled(row: row) -} - -data producer_emission_canonical_receipt_for_executed_verdict_note: String = "Executed-verdict authorization pipeline (reviews 44468/44477): matches oracle row + enrolled probe, refuses synthesizable declarative digests (44468), then requires producer_emission_executed_digest_is_execution_measured (false at baseline until witness-realization binds host-measured claim_executor verdict digests). Static oracle derivation never mints BuildGreen." - -fn producer_emission_executed_receipt_matches_oracle_row( - row: ProducerEmissionOracleRow, - executed: ProducerEmissionExecutedGreenReceipt -) -> Bool { - (row.module_path == executed.module_path) - && (row.behavioral_probe_entry == executed.behavioral_probe_entry) - && (row.behavioral_probe_function == executed.behavioral_probe_function) -} - -fn producer_emission_executed_digest_is_synthesizable_from_declarative_inputs( - row: ProducerEmissionOracleRow, - executed: ProducerEmissionExecutedGreenReceipt -) -> Bool { - let digest = executed.wet_execution_digest - digest == content_hash_atom(value: row.behavioral_probe_entry) - || digest == content_hash_atom(value: row.behavioral_probe_function) - || digest == content_hash_atom(value: row.module_path) - || digest == scaffold_digest_for_module_path(module_path: row.module_path) - || digest == symbol_identity_digest(sym: ^frontier_producer_receipt_scaffold_digest) -} - -data producer_emission_execution_measured_digest_admissible_note: String = "Construction wall (reviews 44468/44477): unwritable at baseline — witness-realization + frontier_probe_survey bind host-measured verdict digests. Refusing synthesizable declarative digests alone is insufficient (any other Hash is forgeable in-model); this predicate is the dissolve-on hook." - -fn producer_emission_executed_digest_is_execution_measured( - row: ProducerEmissionOracleRow, - executed: ProducerEmissionExecutedGreenReceipt -) -> Bool { - false -} - -fn producer_emission_canonical_receipt_for_executed_verdict( - row: ProducerEmissionOracleRow, - executed: ProducerEmissionExecutedGreenReceipt -) -> Optional { - if !producer_emission_executed_receipt_matches_oracle_row(row: row, executed: executed) { - optional_absent() - } else if !producer_emission_oracle_probe_is_enrolled(row: row) { - optional_absent() - } else if producer_emission_executed_digest_is_synthesizable_from_declarative_inputs( - row: row, - executed: executed - ) { - optional_absent() - } else if !producer_emission_executed_digest_is_execution_measured(row: row, executed: executed) { - optional_absent() - } else { - match mint_producer_emission_receipt( - module_path: row.module_path, - producer: V1SeedEmitter, - qualifications: behavioral_equivalent_qualifications, - build_result: BuildGreen, - behavioral_probe: BehavioralProbeBound { - entry: row.behavioral_probe_entry, - function: row.behavioral_probe_function - }, - realized_closure: cssl_harness_realized_closure - ) { - Present { value: receipt } => - match receipt.build_result { - BuildGreen => optional_present(value: receipt) - BuildRefused { cause: _ } => optional_absent() - } - Absent => optional_absent() - } - } -} - -fn producer_emission_build_result_for_oracle_row(row: ProducerEmissionOracleRow) -> EmissionBuildResult { - if producer_emission_oracle_probe_is_known_red_quarantine(row: row) { - BuildRefused { cause: ^cssl_harness_assemble_red } - } else { - BuildRefused { cause: ^producer_emission_probe_not_executed_green } - } -} - -fn producer_emission_receipt_from_oracle_row( - row: ProducerEmissionOracleRow -) -> Optional { - mint_producer_emission_receipt( - module_path: row.module_path, - producer: V1SeedEmitter, - qualifications: behavioral_equivalent_qualifications, - build_result: producer_emission_build_result_for_oracle_row(row: row), - behavioral_probe: BehavioralProbeBound { - entry: row.behavioral_probe_entry, - function: row.behavioral_probe_function - }, - realized_closure: cssl_harness_realized_closure - ) -} - -fn producer_emission_canonical_receipt_for_oracle_row( - row: ProducerEmissionOracleRow -) -> Optional { - match producer_emission_receipt_from_oracle_row(row: row) { - Present { value: receipt } => - match receipt.build_result { - BuildGreen => optional_present(value: receipt) - BuildRefused { cause: _ } => optional_absent() - } - Absent => optional_absent() - } -} - -data emitter_produced_baseline: Int = 0 - -data emitter_produced_baseline_note: String = "Review 44362/44441/44455/44460/44465/44468: frontier EmitterProduced count stays zero until witness-realization enables producer_emission_canonical_receipt_for_executed_verdict with execution-measured verdict digests (frontier_probe_survey dissolve-on). That mint path is unwritable at baseline — no synthesizable executed receipt from declarative fields. Static oracle derivation never mints BuildGreen." - -data producer_emission_oracle_row_body_producer: ProducerEmissionOracleRow = seed_emitter_behavioral_oracle_row( - module_path: "src/v2/compiler/03_body_producer.dag", - behavioral_probe_entry: "dag/test/claim/self_host_body_producer_behavioral_witness_test.dag", - behavioral_probe_function: "self_host_body_producer_behavioral_receipt_holds" -) - -data producer_emission_oracle_row_03_normalize: ProducerEmissionOracleRow = seed_emitter_behavioral_oracle_row( - module_path: "src/v2/compiler/03_normalize.dag", - behavioral_probe_entry: "dag/test/claim/self_host_03_normalize_behavioral_witness_test.dag", - behavioral_probe_function: "self_host_03_normalize_behavioral_receipt_holds" -) - -data producer_emission_oracle_row_07_target_carriers: ProducerEmissionOracleRow = seed_emitter_behavioral_oracle_row( - module_path: "src/v2/compiler/07_target_carriers.dag", - behavioral_probe_entry: "dag/test/claim/self_host_target_carriers_behavioral_witness_test.dag", - behavioral_probe_function: "self_host_target_carriers_behavioral_receipt_holds" -) - -data producer_emission_oracle_row_discovery_enumeration: ProducerEmissionOracleRow = seed_emitter_behavioral_oracle_row( - module_path: "src/v2/compiler/discovery_enumeration.dag", - behavioral_probe_entry: "dag/test/claim/self_host_discovery_enumeration_behavioral_witness_test.dag", - behavioral_probe_function: "self_host_discovery_enumeration_behavioral_receipt_holds" -) - -data producer_emission_oracle_row_parse_engine_hooks: ProducerEmissionOracleRow = seed_emitter_behavioral_oracle_row( - module_path: "src/v2/compiler/parse_engine_hooks.dag", - behavioral_probe_entry: "dag/test/claim/self_host_parse_engine_hooks_behavioral_witness_test.dag", - behavioral_probe_function: "self_host_parse_engine_hooks_behavioral_receipt_holds" -) - -data producer_emission_oracle_row_use_site_verdict: ProducerEmissionOracleRow = seed_emitter_behavioral_oracle_row( - module_path: "src/v2/compiler/use_site_verdict.dag", - behavioral_probe_entry: "dag/test/claim/self_host_use_site_verdict_behavioral_witness_test.dag", - behavioral_probe_function: "self_host_use_site_verdict_behavioral_receipt_holds" -) - -data producer_emission_oracle_row_00_compile_flip_wave_red_note: String = "Secondary regression (2026-07-20 flip-wave): synthetic row for 00_compile dishonest claim replay — NEVER in live registry." - -data producer_emission_oracle_row_00_compile_flip_wave_red: ProducerEmissionOracleRow = ProducerEmissionOracleRow { - module_path: "src/v2/compiler/00_compile.dag", - measured_probe: producer_emission_measured_probe_receipt(module_path: "src/v2/compiler/00_compile.dag"), - behavioral_probe_entry: "src/v2/test/claim/execution/does_not_exist_flip_wave_test.dag", - behavioral_probe_function: "fabricated_flip_wave_all_holds" -} - -data producer_emission_oracle_rows: List = [ - producer_emission_oracle_row_body_producer, - producer_emission_oracle_row_03_normalize, - producer_emission_oracle_row_07_target_carriers, - producer_emission_oracle_row_discovery_enumeration, - producer_emission_oracle_row_parse_engine_hooks, - producer_emission_oracle_row_use_site_verdict -] - -data producer_emission_oracle_rows_empty: List = [] - -data producer_emission_flip_wave_reverted_module_paths: List = [ - "src/v2/compiler/00_compile.dag", - "src/v2/compiler/02_parse.dag", - "src/v2/compiler/03_ingest.dag", - "src/v2/compiler/materialization_carriers.dag", - "src/v2/compiler/program_assembly.dag", - "src/v2/compiler/source_authority.dag" -] fn emitter_producer_eq(left: EmitterProducer, right: EmitterProducer) -> Bool { match left { @@ -693,304 +483,6 @@ fn producer_emission_receipt_eq(left: ProducerEmissionReceipt, right: ProducerEm && realized_closure_eq(left: left.realized_closure, right: right.realized_closure) } -fn producer_emission_oracle_probe_is_enrolled(row: ProducerEmissionOracleRow) -> Bool { - schedule_witness_entry_cited( - probe_entry: row.behavioral_probe_entry, - probe_function: row.behavioral_probe_function, - entries: seed_emitter_behavioral_wet_known_red_entries - ) -} - -fn producer_emission_oracle_rows_match_transport_roster_holds() -> Bool { - fold_list( - xs: producer_emission_oracle_rows, - empty: true, - cons: fn(ok, row) { - ok && match module_behavioral_transport_config_for(module_path: row.module_path) { - Present { value: _ } => true - Absent => false - } - } - ) -} - -fn producer_emission_oracle_row_for_module(module_path: String) -> List { - fold_list( - xs: producer_emission_oracle_rows, - empty: producer_emission_oracle_rows_empty, - cons: fn(acc, row) { - if row.module_path == module_path { - concat(acc, [row]) - } else { - acc - } - } - ) -} - -data producer_emission_oracle_authorization_note: String = "Reviews 44328/44480: authorization is ONLY via producer_emission_canonical_receipt_for_executed_verdict (row + executed_verdict on EmitterProduced) — never producer_emission_canonical_receipt_for_oracle_row (static enrollment/quarantine only). producer_emission_executed_digest_is_execution_measured is false at baseline until witness-realization + frontier_probe_survey. Enrollment binds BuildRefused quarantine receipts + transport roster." - -fn producer_emission_oracle_enrolls_row( - module_path: String, - receipt: ProducerEmissionReceipt -) -> Bool { - any( - xs: producer_emission_oracle_row_for_module(module_path: module_path), - predicate: fn(row) { - match producer_emission_receipt_from_oracle_row(row: row) { - Present { value: canonical } => - producer_emission_receipt_eq(left: canonical, right: receipt) - && producer_emission_oracle_probe_is_enrolled(row: row) - && match module_behavioral_transport_config_for(module_path: row.module_path) { - Present { value: _ } => true - Absent => false - } - Absent => false - } - } - ) -} - -fn producer_emission_oracle_authorizes_row( - module_path: String, - receipt: ProducerEmissionReceipt, - executed: ProducerEmissionExecutedGreenReceipt -) -> Bool { - match receipt.build_result { - BuildGreen => - any( - xs: producer_emission_oracle_row_for_module(module_path: module_path), - predicate: fn(row) { - match producer_emission_canonical_receipt_for_executed_verdict(row: row, executed: executed) { - Present { value: canonical } => - producer_emission_receipt_eq(left: canonical, right: receipt) - && match module_behavioral_transport_config_for(module_path: row.module_path) { - Present { value: _ } => true - Absent => false - } - Absent => false - } - } - ) - BuildRefused { cause: _ } => false - } -} - -fn producer_emission_oracle_authorization_requires_executed_verdict_holds() -> Bool { - let row = producer_emission_oracle_row_body_producer - let fabricated = fabricated_v1_seed_producer_receipt(module_path: row.module_path) - let executed = ProducerEmissionExecutedGreenReceipt { - module_path: row.module_path, - behavioral_probe_entry: row.behavioral_probe_entry, - behavioral_probe_function: row.behavioral_probe_function, - wet_execution_digest: content_hash_atom(value: row.behavioral_probe_entry) - } - !producer_emission_oracle_authorizes_row( - module_path: row.module_path, - receipt: fabricated, - executed: executed - ) -} - -data authorized_emitter_produced_disposition_note: String = "Reviews 44485/44487/44504/44509/44570: SelfHostFrontierDisposition.EmitterProduced carries authorization_binding in the variant — unauthorized tag-only rows are unrepresentable (review 44570). Mint path: mint_emitter_produced_frontier_promotion. Derivation: authorization_token from (module_path, provenance digests, executed wet_execution_digest); census requires mint_consistent per EmitterProduced roster row. Residual substrate limit: .dag records remain freely constructible if someone authors a forged binding literal — mint_consistent + authorize gates refuse at use. Live roster emitter_produced_baseline=0 and promotions empty at baseline." - -fn authorized_emitter_produced_authorization_token( - module_path: String, - provenance: ProducerEmissionReceipt, - executed_verdict: ProducerEmissionExecutedGreenReceipt -) -> Hash { - combine_hash( - a: symbol_identity_digest(sym: ^authorized_emitter_produced_disposition), - b: combine_hash( - a: content_hash_atom(value: module_path), - b: combine_hash( - a: provenance.module_source_digest, - b: combine_hash( - a: provenance.emitted_source_digest, - b: executed_verdict.wet_execution_digest - ) - ) - ) - ) -} - -type AuthorizedEmitterProducedDisposition { - authorization_token: Hash - provenance: ProducerEmissionReceipt - executed_verdict: ProducerEmissionExecutedGreenReceipt -} - -type EmitterProducedAuthorizationBinding { - module_path: String - authorization: AuthorizedEmitterProducedDisposition -} - -data emitter_produced_authorization_binding_note: String = "Review 44504/44509/44570: authorization_binding lives inside EmitterProduced disposition (frontier.dag). Promotions store minted frontier rows only; the registry is a derived projection — never a parallel hand-edited authority. Dissolve-on: witness-realization appends promotions atomically with roster flips via mint_emitter_produced_frontier_promotion." - -fn authorized_emitter_produced_disposition_mint_consistent( - module_path: String, - authorization: AuthorizedEmitterProducedDisposition -) -> Bool { - authorized_emitter_produced_authorization_token( - module_path: module_path, - provenance: authorization.provenance, - executed_verdict: authorization.executed_verdict - ) == authorization.authorization_token - && producer_emission_oracle_authorizes_row( - module_path: module_path, - receipt: authorization.provenance, - executed: authorization.executed_verdict - ) -} - -fn authorized_emitter_produced_provenance( - authorization: AuthorizedEmitterProducedDisposition -) -> ProducerEmissionReceipt { - authorization.provenance -} - -fn authorized_emitter_produced_executed_verdict( - authorization: AuthorizedEmitterProducedDisposition -) -> ProducerEmissionExecutedGreenReceipt { - authorization.executed_verdict -} - -fn mint_authorized_emitter_produced_disposition( - module_path: String, - provenance: ProducerEmissionReceipt, - executed_verdict: ProducerEmissionExecutedGreenReceipt -) -> Optional { - if producer_emission_oracle_authorizes_row( - module_path: module_path, - receipt: provenance, - executed: executed_verdict - ) { - optional_present( - value: AuthorizedEmitterProducedDisposition { - authorization_token: authorized_emitter_produced_authorization_token( - module_path: module_path, - provenance: provenance, - executed_verdict: executed_verdict - ), - provenance: provenance, - executed_verdict: executed_verdict - } - ) - } else { - optional_absent() - } -} - -fn mint_emitter_produced_authorization_registry_binding( - module_path: String, - provenance: ProducerEmissionReceipt, - executed_verdict: ProducerEmissionExecutedGreenReceipt -) -> Optional { - match mint_authorized_emitter_produced_disposition( - module_path: module_path, - provenance: provenance, - executed_verdict: executed_verdict - ) { - Present { value: authorization } => - optional_present( - value: EmitterProducedAuthorizationBinding { - module_path: module_path, - authorization: authorization - } - ) - Absent => optional_absent() - } -} - -fn producer_emission_binding_only_does_not_authorize_holds() -> Bool { - let row = producer_emission_oracle_row_body_producer - match producer_emission_build_result_for_oracle_row(row: row) { - BuildGreen => false - BuildRefused { cause: _ } => true - } -} - -fn producer_emission_executed_verdict_minting_refused_at_baseline_holds() -> Bool { - let row = producer_emission_oracle_row_body_producer - let executed = ProducerEmissionExecutedGreenReceipt { - module_path: row.module_path, - behavioral_probe_entry: row.behavioral_probe_entry, - behavioral_probe_function: row.behavioral_probe_function, - wet_execution_digest: content_hash_atom(value: row.behavioral_probe_entry) - } - match producer_emission_canonical_receipt_for_executed_verdict(row: row, executed: executed) { - Absent => true - Present { value: _ } => false - } -} - -fn producer_emission_oracle_authorization_promotion_path_holds() -> Bool { - fold_list( - xs: producer_emission_oracle_rows, - empty: true, - cons: fn(ok, row) { - ok && match producer_emission_canonical_receipt_for_oracle_row(row: row) { - Present { value: _ } => false - Absent => true - } - } - ) -} - -fn producer_emission_enrollment_entry_has_oracle_row( - probe_entry: String, - probe_function: String -) -> Bool { - any( - xs: producer_emission_oracle_rows, - predicate: fn(row) { - (row.behavioral_probe_entry == probe_entry) - && (row.behavioral_probe_function == probe_function) - } - ) -} - -fn producer_emission_oracle_rows_match_enrollment_holds() -> Bool { - fold_list( - xs: producer_emission_oracle_rows, - empty: true, - cons: fn(ok, row) { ok && producer_emission_oracle_probe_is_enrolled(row: row) } - ) && fold_list( - xs: seed_emitter_behavioral_wet_known_red_entries, - empty: true, - cons: fn(ok, entry) { - ok && producer_emission_enrollment_entry_has_oracle_row( - probe_entry: entry.entry, - probe_function: entry.function - ) - } - ) -} - -fn producer_emission_oracle_rows_all_enrolled_holds() -> Bool { - fold_list( - xs: producer_emission_oracle_rows, - empty: true, - cons: fn(ok, row) { ok && producer_emission_oracle_probe_is_enrolled(row: row) } - ) -} - -fn producer_emission_oracle_row_count() -> Int { - length(xs: producer_emission_oracle_rows) -} - -fn producer_emission_flip_wave_module_has_oracle_row(module_path: String) -> Bool { - length(xs: producer_emission_oracle_row_for_module(module_path: module_path)) > 0 -} - -fn producer_emission_flip_wave_reverted_modules_lack_oracle_holds() -> Bool { - fold_list( - xs: producer_emission_flip_wave_reverted_module_paths, - empty: true, - cons: fn(ok, path) { ok && !producer_emission_flip_wave_module_has_oracle_row(module_path: path) } - ) -} - fn fabricated_v1_seed_producer_receipt(module_path: String) -> ProducerEmissionReceipt { ProducerEmissionReceipt { module_path: module_path, @@ -1036,249 +528,3 @@ fn mint_v2_interpreted_receipt_with_seed_closure_refuses( Present { value: _ } => false } } - -fn hand_forged_emitter_produced_authorization_fails_mint_consistency_holds() -> Bool { - let row = producer_emission_oracle_row_body_producer - let fabricated = fabricated_v1_seed_producer_receipt(module_path: row.module_path) - let executed = ProducerEmissionExecutedGreenReceipt { - module_path: row.module_path, - behavioral_probe_entry: row.behavioral_probe_entry, - behavioral_probe_function: row.behavioral_probe_function, - wet_execution_digest: content_hash_atom(value: row.behavioral_probe_entry) - } - let forged = AuthorizedEmitterProducedDisposition { - authorization_token: content_hash_atom(value: "hand_forged_emitter_produced_authorization"), - provenance: fabricated, - executed_verdict: executed - } - !authorized_emitter_produced_disposition_mint_consistent( - module_path: row.module_path, - authorization: forged - ) -} - -fn hand_forged_matching_token_unauthorized_still_fails_mint_consistency_holds() -> Bool { - let row = producer_emission_oracle_row_body_producer - let fabricated = fabricated_v1_seed_producer_receipt(module_path: row.module_path) - let executed = ProducerEmissionExecutedGreenReceipt { - module_path: row.module_path, - behavioral_probe_entry: row.behavioral_probe_entry, - behavioral_probe_function: row.behavioral_probe_function, - wet_execution_digest: content_hash_atom(value: row.behavioral_probe_entry) - } - let forged = AuthorizedEmitterProducedDisposition { - authorization_token: authorized_emitter_produced_authorization_token( - module_path: row.module_path, - provenance: fabricated, - executed_verdict: executed - ), - provenance: fabricated, - executed_verdict: executed - } - !authorized_emitter_produced_disposition_mint_consistent( - module_path: row.module_path, - authorization: forged - ) -} - -fn mint_authorized_emitter_produced_disposition_refused_at_baseline_holds() -> Bool { - let row = producer_emission_oracle_row_body_producer - let fabricated = fabricated_v1_seed_producer_receipt(module_path: row.module_path) - let executed = ProducerEmissionExecutedGreenReceipt { - module_path: row.module_path, - behavioral_probe_entry: row.behavioral_probe_entry, - behavioral_probe_function: row.behavioral_probe_function, - wet_execution_digest: content_hash_atom(value: row.behavioral_probe_entry) - } - match mint_authorized_emitter_produced_disposition( - module_path: row.module_path, - provenance: fabricated, - executed_verdict: executed - ) { - Absent => true - Present { value: _ } => false - } -} - -type ProducerQualifiedCountAxis - = ProducerCountSeedBehavioralGreen - | ProducerCountV2InterpretedBehavioralGreen - | ProducerCountV2NativeBehavioralGreen - | ProducerCountV2ProductionRouted - -data producer_qualified_count_axis_note: String = "Canonical query surface for producer-qualified census (review 44350 predicate-dissolution): classify once via producer_qualified_count_axis_for_receipt, count via count_oracle_rows_with_qualified_axis — not a family of hand-rolled producer_emission_row_is_* predicates." - -fn producer_qualified_count_axis_eq( - left: ProducerQualifiedCountAxis, - right: ProducerQualifiedCountAxis -) -> Bool { - match left { - ProducerCountSeedBehavioralGreen => - match right { - ProducerCountSeedBehavioralGreen => true - ProducerCountV2InterpretedBehavioralGreen => false - ProducerCountV2NativeBehavioralGreen => false - ProducerCountV2ProductionRouted => false - } - ProducerCountV2InterpretedBehavioralGreen => - match right { - ProducerCountSeedBehavioralGreen => false - ProducerCountV2InterpretedBehavioralGreen => true - ProducerCountV2NativeBehavioralGreen => false - ProducerCountV2ProductionRouted => false - } - ProducerCountV2NativeBehavioralGreen => - match right { - ProducerCountSeedBehavioralGreen => false - ProducerCountV2InterpretedBehavioralGreen => false - ProducerCountV2NativeBehavioralGreen => true - ProducerCountV2ProductionRouted => false - } - ProducerCountV2ProductionRouted => - match right { - ProducerCountSeedBehavioralGreen => false - ProducerCountV2InterpretedBehavioralGreen => false - ProducerCountV2NativeBehavioralGreen => false - ProducerCountV2ProductionRouted => true - } - } -} - -fn producer_qualified_count_axis_for_receipt( - receipt: ProducerEmissionReceipt -) -> Optional { - match receipt.build_result { - BuildRefused { cause: _ } => optional_absent() - BuildGreen => - match receipt.producer { - V1SeedEmitter => - if emission_qualifications_list_contains( - xs: receipt.qualifications, - wanted: BehavioralEquivalent - ) { - optional_present(value: ProducerCountSeedBehavioralGreen) - } else { - optional_absent() - } - V2EmitterInterpreted => - if emission_qualifications_list_contains( - xs: receipt.qualifications, - wanted: BehavioralEquivalent - ) { - optional_present(value: ProducerCountV2InterpretedBehavioralGreen) - } else { - optional_absent() - } - V2EmitterNative { generation: _ } => - if emission_qualifications_list_contains( - xs: receipt.qualifications, - wanted: BehavioralEquivalent - ) { - optional_present(value: ProducerCountV2NativeBehavioralGreen) - } else if emission_qualifications_list_contains( - xs: receipt.qualifications, - wanted: ProductionRouted - ) { - optional_present(value: ProducerCountV2ProductionRouted) - } else { - optional_absent() - } - } - } -} - -fn producer_qualified_count_axis_for_row( - row: ProducerEmissionOracleRow -) -> Optional { - match producer_emission_canonical_receipt_for_oracle_row(row: row) { - Present { value: receipt } => - producer_qualified_count_axis_for_receipt(receipt: receipt) - Absent => optional_absent() - } -} - -fn count_oracle_rows_with_qualified_axis(axis: ProducerQualifiedCountAxis) -> Int { - fold_list( - xs: producer_emission_oracle_rows, - empty: 0, - cons: fn(count, row) { - match producer_qualified_count_axis_for_row(row: row) { - Present { value: row_axis } => - if producer_qualified_count_axis_eq(left: row_axis, right: axis) { - count + 1 - } else { - count - } - Absent => count - } - } - ) -} - -data seed_emitter_behavioral_green_baseline: Int = 0 - -data seed_emitter_behavioral_quarantine_baseline: Int = 6 - -data v2_interpreted_emitter_behavioral_green_baseline: Int = 0 - -data v2_native_emitter_behavioral_green_baseline: Int = 0 - -data v2_emitter_production_routed_baseline: Int = 0 - -fn seed_emitter_behavioral_quarantine_count() -> Int { - fold_list( - xs: producer_emission_oracle_rows, - empty: 0, - cons: fn(count, row) { - if producer_emission_oracle_probe_is_known_red_quarantine(row: row) { - count + 1 - } else { - count - } - } - ) -} - -fn seed_emitter_behavioral_green_count() -> Int { - count_oracle_rows_with_qualified_axis(axis: ProducerCountSeedBehavioralGreen) -} - -fn v2_interpreted_emitter_behavioral_green_count() -> Int { - count_oracle_rows_with_qualified_axis(axis: ProducerCountV2InterpretedBehavioralGreen) -} - -fn v2_native_emitter_behavioral_green_count() -> Int { - count_oracle_rows_with_qualified_axis(axis: ProducerCountV2NativeBehavioralGreen) -} - -fn v2_emitter_production_routed_count() -> Int { - count_oracle_rows_with_qualified_axis(axis: ProducerCountV2ProductionRouted) -} - -fn seed_emitter_behavioral_quarantine_baseline_holds() -> Bool { - seed_emitter_behavioral_quarantine_count() == seed_emitter_behavioral_quarantine_baseline -} - -fn seed_emitter_behavioral_green_baseline_holds() -> Bool { - seed_emitter_behavioral_green_count() == seed_emitter_behavioral_green_baseline -} - -fn v2_interpreted_emitter_behavioral_green_baseline_holds() -> Bool { - v2_interpreted_emitter_behavioral_green_count() == v2_interpreted_emitter_behavioral_green_baseline -} - -fn v2_native_emitter_behavioral_green_baseline_holds() -> Bool { - v2_native_emitter_behavioral_green_count() == v2_native_emitter_behavioral_green_baseline -} - -fn v2_emitter_production_routed_baseline_holds() -> Bool { - v2_emitter_production_routed_count() == v2_emitter_production_routed_baseline -} - -fn producer_qualified_baselines_holds() -> Bool { - seed_emitter_behavioral_green_baseline_holds() - && seed_emitter_behavioral_quarantine_baseline_holds() - && v2_interpreted_emitter_behavioral_green_baseline_holds() - && v2_native_emitter_behavioral_green_baseline_holds() - && v2_emitter_production_routed_baseline_holds() -} diff --git a/src/v2/compiler/self_host/frontier.dag b/src/v2/compiler/self_host/frontier.dag deleted file mode 100644 index 246e6122e8d..00000000000 --- a/src/v2/compiler/self_host/frontier.dag +++ /dev/null @@ -1,1647 +0,0 @@ -module v2.compiler.self_host.frontier - -import v2.compiler.self_host.frontier_band_a_emit_readiness { - BandAEmitReadinessRow, - compiler_frontier_band_a_emit_readiness_core_holds, - compiler_frontier_band_a_emit_readiness_roster -} -import v2.compiler.self_host.emitter_producer_provenance { - EmitterProducer, - EmitterProducedAuthorizationBinding, - ProducerEmissionOracleRow, - ProducerEmissionReceipt, - ProducerEmissionExecutedGreenReceipt, - authorized_emitter_produced_disposition_mint_consistent, - authorized_emitter_produced_provenance, - mint_emitter_produced_authorization_registry_binding, - producer_emission_oracle_enrolls_row, - producer_emission_oracle_row_03_normalize, - producer_emission_oracle_row_body_producer, - producer_emission_oracle_row_07_target_carriers, - producer_emission_oracle_row_discovery_enumeration, - producer_emission_oracle_row_parse_engine_hooks, - producer_emission_oracle_row_use_site_verdict, - producer_emission_oracle_row_count, - producer_emission_oracle_rows, - emitter_produced_baseline, - producer_qualified_baselines_holds, - seed_emitter_behavioral_green_baseline, - seed_emitter_behavioral_green_count, - seed_emitter_behavioral_quarantine_baseline, - seed_emitter_behavioral_quarantine_count -} -import v2.compiler.self_host.frontier_probe_survey { - frontier_probe_survey_blocker_partition_totality_holds, - frontier_probe_survey_roster_bidirectional_totality_holds -} -import v2.compiler.self_host.frontier_probe_types { - EmitSurfaceGap, - FrontierBlockerClass, - FrontierProbeDetailAbsent, - FrontierProbeReceipt, - FrontierProbeStage, - NoFrontierProbeDetail, - NameResolutionGap, - ProbeStageAssemble, - ProbeStageSemanticDerivation, - ProbeStageEmit, - RealizationGap, - SelfEmitReady, - UnknownProbeCause, - FixtureCemented, - UpstreamSemanticRefusal, - curated_cargo_probe_namespace_qualified_rust_emit_reason, - curated_cargo_probe_import_closure_cargo_refuse_reason, - curated_cargo_probe_emit_assemble_refuse_reason, - curated_cargo_probe_generic_type_render_reason, - curated_cargo_probe_type_ref_import_missing_reason, - gate_a_flip_probe_unresolved_compiler_error_reason, - upstream_semantic_compiler_error_class, - frontier_blocker_class_matches, - frontier_probe_blocker_rank, - frontier_probe_located_stage_for_blocker, - frontier_located_reason_is_stale_knowledge_attributed, - frontier_probe_receipt_module_path -} -import v2.lens.common.construction_justification { ConstructionJustification, WallAfterGrounding } -import std.disposition { RealizationDispatch } -import v2.compiler.source_authority { - ModuleStorageIndex, - module_storage_module_for_path -} -import v2.std.diagnostic { - Accepted, - Diagnostic, - ExternalContractUnknown, - Outcome, - Rejected, - Unavailable, - bind_outcome, - outcome_accepted, - outcome_rejected, - port_locus -} -import v2.std.qualified_name { QualifiedName, qualified_name_to_dotted_string } -import v2.std.algebra { fold_list, length, list_snoc_item } -import v2.std.collection { - List -} -import v2.std.optional { - Absent, - Optional, - Present, - optional_absent, - optional_present -} -import v2.std.logic { Bool } -import v2.std.node { Symbol } -import v2.std.text { String } -import extdeps.languages.rust.emit { rust_qualified_module_mod_basename } - -type FrontierQualifiedModuleBinding { - module_path: String - qualified_module: String -} - -type CompilerFrontierAttributedDebt { - dissolution_trigger: Symbol -} - -type CompilerFrontierCensusAttribution - = KnowledgeAttributed { dissolution_trigger: Symbol } - | ExecutionMeasured { - probe_kernel_receipt: Symbol, - wave_label: Symbol, - blocker_class_distribution: CompilerFrontierAttributedDebt, - gap_clustering: CompilerFrontierAttributedDebt - } - -data compiler_frontier_blocker_class_distribution_attribution: CompilerFrontierAttributedDebt = CompilerFrontierAttributedDebt { - dissolution_trigger: ^migrate_when_frontier_per_module_probe_receipt_binds -} - -data compiler_frontier_gap_clustering_attribution: CompilerFrontierAttributedDebt = CompilerFrontierAttributedDebt { - dissolution_trigger: ^migrate_when_frontier_located_reason_survey_binds -} - -data compiler_frontier_census_attribution: CompilerFrontierCensusAttribution = ExecutionMeasured { - probe_kernel_receipt: ^frontier_classify_unlisted_reason_refuses_holds, - wave_label: ^wave2_post_resolver_6451_body_stage_a_6443, - blocker_class_distribution: compiler_frontier_blocker_class_distribution_attribution, - gap_clustering: compiler_frontier_gap_clustering_attribution -} - -data compiler_frontier_probe_kernel_receipt_note: String = "probe_kernel_receipt binds the fail-closed classifier RED control (frontier_classify_unlisted_reason_refuses_holds), not per-module frontier_probe_emit_from_ingest execution. Structural census invariants are compiler_frontier_structural_census_invariants_holds; per-module receipts deferred via CompilerFrontierAttributedDebt dissolution triggers." - -type SelfHostFrontierDisposition - = EmitterProduced { authorization_binding: EmitterProducedAuthorizationBinding } - | SeedRetained { reason: Symbol, migration_trigger: Symbol } - -type CompilerModuleFrontierRow { - module_path: String - disposition: SelfHostFrontierDisposition - measured_probe: FrontierProbeReceipt - tractability_rank: Int -} - -type EmitterProducedFrontierPromotion { - frontier_row: CompilerModuleFrontierRow -} - -data emitter_produced_frontier_promotions_note: String = "Review 44509/44570 single authority: EmitterProduced roster rows carry authorization_binding in the disposition variant (unauthorized tag-only rows unrepresentable). Rows are minted via mint_emitter_produced_frontier_promotion and stored here — never as parallel hand-edited authorities. The authorization registry is a derived projection (emitter_produced_authorization_registry_from_promotions). Baseline empty until witness-realization appends promotions atomically with roster flips." - -fn emitter_produced_frontier_promotions() -> List { - [] -} - -fn empty_emitter_produced_authorization_bindings() -> List { - [] -} - -data compiler_frontier_producer_qualified_baseline_note: String = "Producer-qualified progress ratchets (calm-badger-682 ruling 2026-07-29): replaces compiler_frontier_self_emitted_baseline. seed_emitter_behavioral_green_count is the independent floor for V1SeedEmitter + BehavioralEquivalent rows; v2_* counters start at zero and derive from producer-identified executing receipts, never source location. Retired SelfEmitted vocabulary atomically with this ratchet set — reclassifying the six rows to V1SeedEmitter without retiring the old baseline would trip the guard." - -data compiler_frontier_binding_hand_rows_note: String = "THE SECOND AUTHORITY, still live for ONE consumer and gated because of it. These 27 rows no longer serve the witness path — that projects off the derived ModuleStorageIndex — but they still feed the crate-layout EMITTER, which cannot be handed a host index without polluting an unrelated 18-variant dispatch (frontier_emitter_hand_row_debt_note has the full reasoning and the count). - -So two representations of the path⇄module fact are live at once, which §3 forbids in general. What makes this an honest interim rather than a fork is that they are PARITY-GATED: transition_parity_host_index_agrees_with_hand_rows is a STANDING witness on the wet cadence (promoted from one-time transition receipt, parent ruling 2026-07-19) asserting that the derived index and these rows answer identically for every path the rows name. If they ever drift, that witness REDS. - -That promotion is the point. As a one-time switchover check it would have proven the two agreed at a moment and said nothing afterwards, leaving a silent fork behind it. As a standing check it IS the §3 protection for as long as the duality lives — the mechanism that makes 'both exist' safe rather than merely admitted. - -It still catches both original failures — a projection bug (derivation disagrees with a known-good table) and hand-row drift (the table went stale and the derivation is right) — told apart by inspecting which side is wrong. - -dissolve-on: host-driven generation of the crate-layout artifact with the index supplied at the boundary. At that point this block, FrontierQualifiedModuleBinding, the _hand_rows fn family, and the parity witness are DELETED together — keeping any of them 'just in case' would restore the fork the parity gate exists to police." - -data compiler_frontier_qualified_module_bindings: List = [ - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/00_compile.dag", qualified_module: "v2.compiler.compile" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/01_tokenize.dag", qualified_module: "v2.compiler.tokenize" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/02_parse.dag", qualified_module: "v2.compiler.parse" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/03_body_producer.dag", qualified_module: "v2.compiler.body_producer" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/03_ingest.dag", qualified_module: "v2.compiler.ingest" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/03_name_resolve.dag", qualified_module: "v2.compiler.name_resolve" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/03_normalize.dag", qualified_module: "v2.compiler.normalize" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/03_resolve.dag", qualified_module: "v2.compiler.resolve" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/04_infer.dag", qualified_module: "v2.compiler.infer" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/05_emit.dag", qualified_module: "v2.compiler.emit" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/05_emit_orchestration.dag", qualified_module: "v2.compiler.emit_orchestration" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/05_eval.dag", qualified_module: "v2.compiler.eval" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/06_translate.dag", qualified_module: "v2.compiler.translate" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/07_target_carriers.dag", qualified_module: "v2.compiler.target_carriers" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/discovery_enumeration.dag", qualified_module: "v2.compiler.discovery_enumeration" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/emit_host.dag", qualified_module: "v2.compiler.emit_host" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/emit_module.dag", qualified_module: "v2.compiler.emit_module" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/emit_produced.dag", qualified_module: "v2.compiler.emit_produced" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/emit_semantic_decl.dag", qualified_module: "v2.compiler.emit_semantic_decl" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/fold_lowering.dag", qualified_module: "v2.compiler.fold_lowering" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/materialization_carriers.dag", qualified_module: "v2.compiler.materialization_carriers" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/parse_engine_hooks.dag", qualified_module: "v2.compiler.parse_engine_hooks" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/program_assembly.dag", qualified_module: "v2.compiler.program_assembly" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/program_partition.dag", qualified_module: "v2.compiler.program_partition" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/self_host.dag", qualified_module: "v2.compiler.self_host" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/source_authority.dag", qualified_module: "v2.compiler.source_authority" }, - FrontierQualifiedModuleBinding { module_path: "src/v2/compiler/use_site_verdict.dag", qualified_module: "v2.compiler.use_site_verdict" } -] - -data compiler_frontier_crate_layout_note: String = "Single crate-organization authority (Wave 2 derived layout): self-emitted stage0 mod basenames derive from compiler_frontier_roster SelfEmitted rows via qualified_module bindings + rust_qualified_module_mod_basename (extdeps.languages.rust.emit). Seed-retained intrinsic kernel + pilot scaffolds compose via hand_maintained_pub_mod_basenames derived from SeedRetainedIntrinsicRegistration rows (single row per intrinsic; pub_mod / stage0_file projections), while nested hand-retained support dirs are a separate countable frontier. v1 consumers read gunbc.stage0_crate_layout_generated (frontier-derived committed artifact; regen via generated_artifact_gate main_wet; drift wall = byte-identical gate + crate_layout_witness_test RED controls). Dissolve-on: layer boundary lifts and v1 regen closure imports frontier directly." - -data compiler_frontier_crate_linkage_unit_generalization_trigger: String = "Rust realization of the agnostic linkage-unit / unit-of-separate-compilation concept (crate = C translation-unit = Go package = .NET assembly). Kept Rust-specific until a 2nd target realization staffs (full-C-target frontier row, eager-ferret lane, anti-fork constraint recorded there). GENERALIZES-WHEN: a 2nd realization exists — factor the agnostic CompilationUnit/TargetLinkageUnit shape then, with per-realization axes (acyclicity, monomorphization-boundary) NOT averaged away; partition POLICY is workflow-derived, not baked here." - -data compiler_frontier_rust_linkage_unit_axis_acyclic_crates: String = "Rust-specific axis (not universal): crate graph must be acyclic; separate-compilation unit = one Cargo crate." - -data compiler_frontier_rust_linkage_unit_axis_monomorphization_boundary: String = "Rust-specific axis (not universal): crate boundary = monomorphization / codegen partition boundary (generics instantiated per crate)." - -fn measured_stage_for_blocker(blocker: FrontierBlockerClass) -> FrontierProbeStage { - frontier_probe_located_stage_for_blocker(blocker: blocker) -} - -fn tractability_rank_for(closure_reads: Int, blocker: FrontierBlockerClass) -> Int { - let base = frontier_probe_blocker_rank(blocker: blocker) * 1000 - base + closure_reads -} - -data compiler_frontier_self_emitted_tractability_rank_note: String = "At SelfEmitted flip, tractability_rank retains the pre-flip blocker band (not recomputed from measured_probe.blocker_class SelfEmitReady) so compiler_frontier_sweep_order rank monotonicity is unchanged. SelfEmitReady rank would be closure_reads alone (e.g. 9), breaking sweep order vs neighboring EmitSurfaceGap rows (e.g. 1002, 1012)." - -fn self_emitted_tractability_rank_at_flip(closure_reads: Int, pre_flip_blocker: FrontierBlockerClass) -> Int { - tractability_rank_for(closure_reads: closure_reads, blocker: pre_flip_blocker) -} - -fn execution_measured_seed_retained_row( - module_path: String, - closure_reads: Int, - measured_blocker: FrontierBlockerClass, - located_stage: FrontierProbeStage, - located_reason: Symbol, - migration_trigger: Symbol -) -> CompilerModuleFrontierRow { - CompilerModuleFrontierRow { - module_path: module_path, - disposition: SeedRetained { - reason: located_reason, - migration_trigger: migration_trigger - }, - measured_probe: FrontierProbeReceipt { - module_path: module_path, - blocker_class: measured_blocker, - located_stage: located_stage, - located_reason: located_reason, - detail: FrontierProbeDetailAbsent, - assemble_detail: NoFrontierProbeDetail - }, - tractability_rank: tractability_rank_for(closure_reads: closure_reads, blocker: measured_blocker) - } -} - -fn execution_measured_seed_retained_row_from_probe_receipt( - closure_reads: Int, - receipt: FrontierProbeReceipt, - migration_trigger: Symbol -) -> CompilerModuleFrontierRow { - execution_measured_seed_retained_row( - module_path: receipt.module_path, - closure_reads: closure_reads, - measured_blocker: receipt.blocker_class, - located_stage: receipt.located_stage, - located_reason: receipt.located_reason, - migration_trigger: migration_trigger - ) -} - -data execution_measured_emitter_produced_row_note: String = "Construction wall (emitter_producer_provenance, reviews 44362/44480/44485/44487/44504/44509/44570): EmitterProduced carries authorization_binding in the disposition variant — unauthorized tag-only rows are unrepresentable. Mint path: mint_emitter_produced_frontier_promotion. Static oracle derivation is enrollment-only. producer_emission_executed_digest_is_execution_measured is false at baseline until witness-realization. Live roster emitter_produced_baseline=0; promotions empty." - -fn emitter_produced_authorization_bindings_from_promotions( - promotions: List -) -> List { - fold_list( - xs: promotions, - empty: empty_emitter_produced_authorization_bindings(), - cons: fn(acc, promotion) { - match promotion.frontier_row.disposition { - EmitterProduced { authorization_binding: binding } => - list_snoc_item(xs: acc, item: binding) - SeedRetained { reason: _, migration_trigger: _ } => acc - } - } - ) -} - -fn emitter_produced_authorization_registry_from_promotions() -> List { - emitter_produced_authorization_bindings_from_promotions( - promotions: emitter_produced_frontier_promotions() - ) -} - -fn emitter_produced_authorization_for_module_in_promotions( - module_path: String, - promotions: List -) -> Optional { - fold_list( - xs: promotions, - empty: optional_absent(), - cons: fn(found, promotion) { - match found { - Present { value: authorization } => optional_present(value: authorization) - Absent => - match promotion.frontier_row.disposition { - EmitterProduced { authorization_binding: binding } => - if binding.module_path == module_path { - optional_present(value: binding.authorization) - } else { - optional_absent() - } - SeedRetained { reason: _, migration_trigger: _ } => optional_absent() - } - } - } - ) -} - -fn emitter_produced_frontier_promotions_mint_consistent_holds( - promotions: List -) -> Bool { - fold_list( - xs: promotions, - empty: true, - cons: fn(ok, promotion) { - match promotion.frontier_row.disposition { - EmitterProduced { authorization_binding: binding } => - ok - && authorized_emitter_produced_disposition_mint_consistent( - module_path: binding.module_path, - authorization: binding.authorization - ) - SeedRetained { reason: _, migration_trigger: _ } => false - } - } - ) -} - -fn emitter_produced_unauthorized_disposition_unrepresentable_holds() -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: true, - cons: fn(ok, row) { - ok && match row.disposition { - EmitterProduced { authorization_binding: binding } => - binding.module_path == row.module_path - && authorized_emitter_produced_disposition_mint_consistent( - module_path: row.module_path, - authorization: binding.authorization - ) - SeedRetained { reason: _, migration_trigger: _ } => true - } - } - ) - && (length(xs: emitter_produced_frontier_promotions()) == 0) -} - -fn emitter_produced_frontier_promotions_registry_coherent_holds() -> Bool { - fold_list( - xs: emitter_produced_frontier_promotions(), - empty: true, - cons: fn(ok, promotion) { - ok && match promotion.frontier_row.disposition { - EmitterProduced { authorization_binding: binding } => - binding.module_path == promotion.frontier_row.module_path - && authorized_emitter_produced_disposition_mint_consistent( - module_path: binding.module_path, - authorization: binding.authorization - ) - SeedRetained { reason: _, migration_trigger: _ } => false - } - } - ) -} - -fn mint_emitter_produced_frontier_promotion( - module_path: String, - measured_probe: FrontierProbeReceipt, - tractability_rank: Int, - provenance: ProducerEmissionReceipt, - executed_verdict: ProducerEmissionExecutedGreenReceipt -) -> Optional { - match mint_emitter_produced_authorization_registry_binding( - module_path: module_path, - provenance: provenance, - executed_verdict: executed_verdict - ) { - Present { value: binding } => - optional_present( - value: EmitterProducedFrontierPromotion { - frontier_row: CompilerModuleFrontierRow { - module_path: module_path, - disposition: EmitterProduced { authorization_binding: binding }, - measured_probe: measured_probe, - tractability_rank: tractability_rank - } - } - ) - Absent => optional_absent() - } -} - -fn mint_compiler_frontier_emitter_produced_row( - module_path: String, - measured_probe: FrontierProbeReceipt, - tractability_rank: Int, - provenance: ProducerEmissionReceipt, - executed_verdict: ProducerEmissionExecutedGreenReceipt -) -> Optional { - match mint_emitter_produced_frontier_promotion( - module_path: module_path, - measured_probe: measured_probe, - tractability_rank: tractability_rank, - provenance: provenance, - executed_verdict: executed_verdict - ) { - Present { value: promotion } => optional_present(value: promotion.frontier_row) - Absent => optional_absent() - } -} - -fn quarantine_seed_retained_row_from_oracle( - oracle_row: ProducerEmissionOracleRow, - closure_reads: Int, - pre_flip_blocker: FrontierBlockerClass -) -> CompilerModuleFrontierRow { - execution_measured_seed_retained_row( - module_path: oracle_row.module_path, - closure_reads: closure_reads, - measured_blocker: pre_flip_blocker, - located_stage: measured_stage_for_blocker(blocker: pre_flip_blocker), - located_reason: ^cssl_harness_assemble_red, - migration_trigger: ^migrate_when_cssl_assemble_wet_receipt_greens - ) -} - -fn knowledge_attributed_blocker_class_seed_retained_row( - module_path: String, - closure_reads: Int, - measured_blocker: FrontierBlockerClass, - migration_trigger: Symbol -) -> CompilerModuleFrontierRow { - execution_measured_seed_retained_row( - module_path: module_path, - closure_reads: closure_reads, - measured_blocker: measured_blocker, - located_stage: measured_stage_for_blocker(blocker: measured_blocker), - located_reason: ^frontier_located_reason_execution_unbound, - migration_trigger: migration_trigger - ) -} - -data compiler_frontier_measured_upstream_unresolved_blocker: FrontierBlockerClass = UpstreamSemanticRefusal { - diagnostic_class: upstream_semantic_compiler_error_class, - diagnostic_name: gate_a_flip_probe_unresolved_compiler_error_reason -} - -data compiler_frontier_row_00_compile: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/00_compile.dag", - closure_reads: 102, - measured_blocker: NameResolutionGap, - located_stage: ProbeStageAssemble, - located_reason: ^resolve_module_not_found, - migration_trigger: ^migrate_when_namespace_only_resolution_lands -) - -data compiler_frontier_row_01_tokenize: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/01_tokenize.dag", - closure_reads: 17, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_02_parse: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/02_parse.dag", - closure_reads: 65, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_03_body_producer: CompilerModuleFrontierRow = quarantine_seed_retained_row_from_oracle( - oracle_row: producer_emission_oracle_row_body_producer, - closure_reads: 36, - pre_flip_blocker: NameResolutionGap -) - -data compiler_frontier_row_03_ingest: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/03_ingest.dag", - closure_reads: 104, - measured_blocker: NameResolutionGap, - located_stage: ProbeStageAssemble, - located_reason: ^resolve_module_not_found, - migration_trigger: ^migrate_when_namespace_only_resolution_lands -) - -data compiler_frontier_row_03_name_resolve: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/03_name_resolve.dag", - closure_reads: 44, - measured_blocker: EmitSurfaceGap, - located_stage: ProbeStageEmit, - located_reason: curated_cargo_probe_namespace_qualified_rust_emit_reason, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_03_normalize: CompilerModuleFrontierRow = quarantine_seed_retained_row_from_oracle( - oracle_row: producer_emission_oracle_row_03_normalize, - closure_reads: 37, - pre_flip_blocker: EmitSurfaceGap -) - -data compiler_frontier_row_03_resolve: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/03_resolve.dag", - closure_reads: 39, - measured_blocker: EmitSurfaceGap, - located_stage: ProbeStageEmit, - located_reason: curated_cargo_probe_type_ref_import_missing_reason, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_04_infer: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/04_infer.dag", - closure_reads: 44, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_05_emit: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/05_emit.dag", - closure_reads: 52, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_05_emit_orchestration: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/05_emit_orchestration.dag", - closure_reads: 55, - measured_blocker: EmitSurfaceGap, - located_stage: ProbeStageEmit, - located_reason: curated_cargo_probe_namespace_qualified_rust_emit_reason, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_05_eval: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/05_eval.dag", - closure_reads: 51, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_06_translate: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/06_translate.dag", - closure_reads: 51, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_07_target_carriers: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/07_target_carriers.dag", - closure_reads: 36, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_cssl_assemble_wet_receipt_greens -) - -data compiler_frontier_row_discovery_enumeration: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/discovery_enumeration.dag", - closure_reads: 12, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_cssl_assemble_wet_receipt_greens -) - -data compiler_frontier_row_emit_host: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/emit_host.dag", - closure_reads: 61, - measured_blocker: EmitSurfaceGap, - located_stage: ProbeStageEmit, - located_reason: curated_cargo_probe_type_ref_import_missing_reason, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_emit_module: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/emit_module.dag", - closure_reads: 53, - measured_blocker: EmitSurfaceGap, - located_stage: ProbeStageEmit, - located_reason: curated_cargo_probe_type_ref_import_missing_reason, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_emit_produced: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/emit_produced.dag", - closure_reads: 61, - measured_blocker: EmitSurfaceGap, - located_stage: ProbeStageEmit, - located_reason: curated_cargo_probe_namespace_qualified_rust_emit_reason, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_emit_semantic_decl: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/emit_semantic_decl.dag", - closure_reads: 59, - measured_blocker: EmitSurfaceGap, - located_stage: ProbeStageEmit, - located_reason: curated_cargo_probe_type_ref_import_missing_reason, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_fold_lowering: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/fold_lowering.dag", - closure_reads: 36, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_materialization_carriers: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/materialization_carriers.dag", - closure_reads: 35, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_parse_engine_hooks: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/parse_engine_hooks.dag", - closure_reads: 2, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_cssl_assemble_wet_receipt_greens -) - -data compiler_frontier_row_program_assembly: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/program_assembly.dag", - closure_reads: 90, - measured_blocker: NameResolutionGap, - located_stage: ProbeStageAssemble, - located_reason: curated_cargo_probe_emit_assemble_refuse_reason, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_program_partition: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/program_partition.dag", - closure_reads: 58, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_closure_self_emits_cargo_green -) - -data compiler_frontier_row_self_host: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/self_host.dag", - closure_reads: 28, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_frontier_harness_repurposed -) - -data compiler_frontier_row_source_authority: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/source_authority.dag", - closure_reads: 87, - measured_blocker: NameResolutionGap, - located_stage: ProbeStageAssemble, - located_reason: ^resolve_module_not_found, - migration_trigger: ^migrate_when_namespace_only_resolution_lands -) - -data compiler_frontier_row_use_site_verdict: CompilerModuleFrontierRow = execution_measured_seed_retained_row( - module_path: "src/v2/compiler/use_site_verdict.dag", - closure_reads: 9, - measured_blocker: RealizationGap, - located_stage: ProbeStageAssemble, - located_reason: ^parse_grammar_choice_overlap_residue, - migration_trigger: ^migrate_when_cssl_assemble_wet_receipt_greens -) - -data compiler_frontier_roster: List = [ - compiler_frontier_row_00_compile, - compiler_frontier_row_01_tokenize, - compiler_frontier_row_02_parse, - compiler_frontier_row_03_body_producer, - compiler_frontier_row_03_ingest, - compiler_frontier_row_03_name_resolve, - compiler_frontier_row_03_normalize, - compiler_frontier_row_03_resolve, - compiler_frontier_row_04_infer, - compiler_frontier_row_05_emit, - compiler_frontier_row_05_emit_orchestration, - compiler_frontier_row_05_eval, - compiler_frontier_row_06_translate, - compiler_frontier_row_07_target_carriers, - compiler_frontier_row_discovery_enumeration, - compiler_frontier_row_emit_host, - compiler_frontier_row_emit_module, - compiler_frontier_row_emit_produced, - compiler_frontier_row_emit_semantic_decl, - compiler_frontier_row_fold_lowering, - compiler_frontier_row_materialization_carriers, - compiler_frontier_row_parse_engine_hooks, - compiler_frontier_row_program_assembly, - compiler_frontier_row_program_partition, - compiler_frontier_row_self_host, - compiler_frontier_row_source_authority, - compiler_frontier_row_use_site_verdict -] - -data compiler_frontier_sweep_order: List = [ - "src/v2/compiler/03_normalize.dag", - "src/v2/compiler/03_resolve.dag", - "src/v2/compiler/03_name_resolve.dag", - "src/v2/compiler/emit_module.dag", - "src/v2/compiler/05_emit_orchestration.dag", - "src/v2/compiler/emit_semantic_decl.dag", - "src/v2/compiler/emit_host.dag", - "src/v2/compiler/emit_produced.dag", - "src/v2/compiler/03_body_producer.dag", - "src/v2/compiler/source_authority.dag", - "src/v2/compiler/program_assembly.dag", - "src/v2/compiler/00_compile.dag", - "src/v2/compiler/03_ingest.dag", - "src/v2/compiler/parse_engine_hooks.dag", - "src/v2/compiler/use_site_verdict.dag", - "src/v2/compiler/discovery_enumeration.dag", - "src/v2/compiler/01_tokenize.dag", - "src/v2/compiler/self_host.dag", - "src/v2/compiler/materialization_carriers.dag", - "src/v2/compiler/07_target_carriers.dag", - "src/v2/compiler/fold_lowering.dag", - "src/v2/compiler/04_infer.dag", - "src/v2/compiler/05_eval.dag", - "src/v2/compiler/06_translate.dag", - "src/v2/compiler/05_emit.dag", - "src/v2/compiler/program_partition.dag", - "src/v2/compiler/02_parse.dag" -] - -fn compiler_frontier_roster_count() -> Int { - length(xs: compiler_frontier_roster) -} - -fn count_rows_with_module_path(xs: List, target: String) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, row) { - if row.module_path == target { count + 1 } else { count } - } - ) -} - -fn count_emitter_produced_rows_with_module_path( - xs: List, - target: String -) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, row) { - if row.module_path == target { - match row.disposition { - EmitterProduced { authorization_binding: _ } => count + 1 - SeedRetained { reason: _, migration_trigger: _ } => count - } - } else { - count - } - } - ) -} - -fn count_seed_retained_rows_with_module_path( - xs: List, - target: String -) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, row) { - if row.module_path == target { - match row.disposition { - SeedRetained { reason: _, migration_trigger: _ } => count + 1 - EmitterProduced { authorization_binding: _ } => count - } - } else { - count - } - } - ) -} - -fn compiler_frontier_quarantine_oracle_modules_seed_retained_holds() -> Bool { - fold_list( - xs: producer_emission_oracle_rows, - empty: true, - cons: fn(ok, oracle_row) { - ok - && (count_seed_retained_rows_with_module_path( - xs: compiler_frontier_roster, - target: oracle_row.module_path - ) == 1) - && (count_emitter_produced_rows_with_module_path( - xs: compiler_frontier_roster, - target: oracle_row.module_path - ) == 0) - } - ) -} - -fn compiler_frontier_roster_paths_unique_holds() -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: true, - cons: fn(ok, row) { - ok && (count_rows_with_module_path(xs: compiler_frontier_roster, target: row.module_path) == 1) - } - ) -} - -fn count_emitter_produced_frontier_rows(xs: List) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, row) { - match row.disposition { - EmitterProduced { authorization_binding: _ } => count + 1 - SeedRetained { reason: _, migration_trigger: _ } => count - } - } - ) -} - -fn count_seed_retained_frontier_rows(xs: List) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, row) { - match row.disposition { - EmitterProduced { authorization_binding: _ } => count - SeedRetained { reason: _, migration_trigger: _ } => count + 1 - } - } - ) -} - -fn compiler_frontier_emitter_produced_count() -> Int { - count_emitter_produced_frontier_rows(xs: compiler_frontier_roster) -} - -fn compiler_frontier_producer_qualified_baselines_holds() -> Bool { - producer_qualified_baselines_holds() -} - -fn compiler_frontier_emitter_produced_oracle_count_matches_baseline_holds() -> Bool { - producer_emission_oracle_row_count() == seed_emitter_behavioral_quarantine_baseline - && compiler_frontier_emitter_produced_count() == emitter_produced_baseline - && seed_emitter_behavioral_green_count() == seed_emitter_behavioral_green_baseline -} - -fn compiler_frontier_seed_retained_count() -> Int { - count_seed_retained_frontier_rows(xs: compiler_frontier_roster) -} - -fn compiler_frontier_known_module_path_exactly_once_holds() -> Bool { - count_rows_with_module_path( - xs: compiler_frontier_roster, - target: "src/v2/compiler/00_compile.dag" - ) == 1 -} - -fn compiler_frontier_phantom_module_path_absent_holds() -> Bool { - count_rows_with_module_path( - xs: compiler_frontier_roster, - target: "src/v2/compiler/not_a_real_module.dag" - ) == 0 -} - -fn frontier_located_reason_is_class_projection(reason: Symbol) -> Bool { - reason == ^measured_probe_self_emit_ready - || reason == ^measured_probe_name_resolution_gap - || reason == ^measured_probe_emit_surface_gap - || reason == ^measured_probe_realization_gap -} - -fn compiler_frontier_roster_all_classified_holds() -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: true, - cons: fn(ok, row) { - ok && match row.measured_probe.blocker_class { - UnknownProbeCause { reason: _ } => false - FixtureCemented => false - SelfEmitReady => true - UpstreamSemanticRefusal { diagnostic_class: _, diagnostic_name: _ } => true - NameResolutionGap => true - EmitSurfaceGap => true - RealizationGap => true - } - } - ) -} - -fn compiler_frontier_roster_stale_located_reason_count_holds() -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: 0, - cons: fn(count, row) { - if frontier_located_reason_is_stale_knowledge_attributed( - symbol: row.measured_probe.located_reason - ) { - count + 1 - } else { - count - } - } - ) == 0 -} - -fn compiler_frontier_roster_module_paths() -> List { - fold( - compiler_frontier_roster, - init: [], - f: fn(acc, row) { - list_snoc_item(xs: acc, item: row.module_path) - } - ) -} - -fn compiler_frontier_receipt_totality_wall_holds(survey: List) -> Bool { - compiler_frontier_roster_stale_located_reason_count_holds() - && frontier_probe_survey_blocker_partition_totality_holds( - receipts: survey, - module_count: compiler_frontier_roster_count() - ) - && frontier_probe_survey_roster_bidirectional_totality_holds( - survey: survey, - roster_paths: compiler_frontier_roster_module_paths(), - roster_count: compiler_frontier_roster_count() - ) -} - -fn compiler_frontier_roster_located_reason_not_class_projection_holds() -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: true, - cons: fn(ok, row) { - ok && match row.disposition { - EmitterProduced { authorization_binding: _ } => true - SeedRetained { reason: _, migration_trigger: _ } => - !frontier_located_reason_is_class_projection(reason: row.measured_probe.located_reason) - } - } - ) -} - -fn compiler_frontier_emitter_produced_located_reason_holds() -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: true, - cons: fn(ok, row) { - ok && match row.disposition { - EmitterProduced { authorization_binding: _ } => - frontier_blocker_class_matches( - blocker: row.measured_probe.blocker_class, - target: SelfEmitReady - ) - && (row.measured_probe.located_reason == ^measured_probe_self_emit_ready) - SeedRetained { reason: _, migration_trigger: _ } => true - } - } - ) -} - -fn compiler_frontier_emitter_produced_oracle_enrolled_holds() -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: true, - cons: fn(ok, row) { - ok && match row.disposition { - EmitterProduced { authorization_binding: binding } => - binding.module_path == row.module_path - && producer_emission_oracle_enrolls_row( - module_path: row.module_path, - receipt: authorized_emitter_produced_provenance(authorization: binding.authorization) - ) - SeedRetained { reason: _, migration_trigger: _ } => true - } - } - ) -} - -fn compiler_frontier_emitter_produced_oracle_backed_holds() -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: true, - cons: fn(ok, row) { - ok && match row.disposition { - EmitterProduced { authorization_binding: binding } => - binding.module_path == row.module_path - && authorized_emitter_produced_disposition_mint_consistent( - module_path: row.module_path, - authorization: binding.authorization - ) - SeedRetained { reason: _, migration_trigger: _ } => true - } - } - ) -} - -fn compiler_frontier_emitter_produced_registry_count_matches_roster_holds() -> Bool { - (length(xs: emitter_produced_authorization_registry_from_promotions()) == compiler_frontier_emitter_produced_count()) - && (length(xs: emitter_produced_frontier_promotions()) == compiler_frontier_emitter_produced_count()) -} - -fn compiler_frontier_emitter_produced_authorization_mint_consistent_holds() -> Bool { - emitter_produced_unauthorized_disposition_unrepresentable_holds() - && emitter_produced_frontier_promotions_mint_consistent_holds( - promotions: emitter_produced_frontier_promotions() - ) - && emitter_produced_frontier_promotions_registry_coherent_holds() - && compiler_frontier_emitter_produced_oracle_backed_holds() - && compiler_frontier_emitter_produced_registry_count_matches_roster_holds() -} - -fn compiler_frontier_roster_probe_paths_match_holds() -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: true, - cons: fn(ok, row) { - ok && (row.module_path == row.measured_probe.module_path) - } - ) -} - -fn compiler_frontier_blocker_class_distribution_knowledge_attributed_holds() -> Bool { - match compiler_frontier_census_attribution { - ExecutionMeasured { - probe_kernel_receipt: _, - wave_label: _, - blocker_class_distribution: blocker_class_distribution, - gap_clustering: _ - } => - blocker_class_distribution.dissolution_trigger == ^migrate_when_frontier_per_module_probe_receipt_binds - KnowledgeAttributed { dissolution_trigger: _ } => false - } -} - -fn compiler_frontier_gap_clustering_knowledge_attributed_holds() -> Bool { - match compiler_frontier_census_attribution { - ExecutionMeasured { - probe_kernel_receipt: _, - wave_label: _, - blocker_class_distribution: _, - gap_clustering: gap_clustering - } => - gap_clustering.dissolution_trigger == ^migrate_when_frontier_located_reason_survey_binds - KnowledgeAttributed { dissolution_trigger: _ } => false - } -} - -fn compiler_frontier_execution_measured_attribution_holds() -> Bool { - match compiler_frontier_census_attribution { - ExecutionMeasured { - probe_kernel_receipt: probe_kernel_receipt, - wave_label: wave_label, - blocker_class_distribution: _, - gap_clustering: _ - } => - probe_kernel_receipt == ^frontier_classify_unlisted_reason_refuses_holds - && wave_label == ^wave2_post_resolver_6451_body_stage_a_6443 - && compiler_frontier_blocker_class_distribution_knowledge_attributed_holds() - && compiler_frontier_gap_clustering_knowledge_attributed_holds() - && compiler_frontier_roster_all_classified_holds() - && compiler_frontier_roster_probe_paths_match_holds() - KnowledgeAttributed { dissolution_trigger: _ } => false - } -} - -fn compiler_frontier_tractability_rank_for_path(target: String) -> Int { - fold_list( - xs: compiler_frontier_roster, - empty: -1, - cons: fn(rank, row) { - if row.module_path == target { row.tractability_rank } else { rank } - } - ) -} - -type CompilerFrontierSweepRankWalkState { - ok: Bool - prev_rank: Int -} - -data compiler_frontier_sweep_rank_walk_initial: CompilerFrontierSweepRankWalkState = CompilerFrontierSweepRankWalkState { - ok: true, - prev_rank: -1 -} - -fn compiler_frontier_sweep_rank_walk_step( - state: CompilerFrontierSweepRankWalkState, - path: String -) -> CompilerFrontierSweepRankWalkState { - let rank = compiler_frontier_tractability_rank_for_path(target: path) - CompilerFrontierSweepRankWalkState { - ok: state.ok && ((state.prev_rank < 0) || (rank >= state.prev_rank)), - prev_rank: rank - } -} - -fn compiler_frontier_sweep_order_paths_in_roster_holds() -> Bool { - fold_list( - xs: compiler_frontier_sweep_order, - empty: true, - cons: fn(ok, path) { - ok && (count_rows_with_module_path(xs: compiler_frontier_roster, target: path) == 1) - } - ) -} - -fn compiler_frontier_sweep_order_rank_nondecreasing_holds() -> Bool { - fold_list( - xs: compiler_frontier_sweep_order, - empty: compiler_frontier_sweep_rank_walk_initial, - cons: fn(state, path) { - compiler_frontier_sweep_rank_walk_step(state: state, path: path) - } - ).ok -} - -fn compiler_frontier_sweep_order_matches_tractability_rank_holds() -> Bool { - compiler_frontier_sweep_order_complete_holds() - && compiler_frontier_sweep_order_paths_in_roster_holds() - && compiler_frontier_sweep_order_rank_nondecreasing_holds() -} - -fn compiler_frontier_sweep_order_complete_holds() -> Bool { - length(xs: compiler_frontier_sweep_order) == compiler_frontier_roster_count() -} - -fn band_a_emit_readiness_roster_row_trigger_matches( - module_path: String, - trigger: Symbol, - row: CompilerModuleFrontierRow -) -> Bool { - if module_path == row.module_path { - match row.disposition { - SeedRetained { reason: _, migration_trigger: expected } => trigger == expected - EmitterProduced { authorization_binding: _ } => false - } - } else { - false - } -} - -fn band_a_emit_readiness_module_is_emitter_produced(module_path: String) -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: false, - cons: fn(matched, row) { - if row.module_path == module_path { - match row.disposition { - EmitterProduced { authorization_binding: _ } => true - SeedRetained { reason: _, migration_trigger: _ } => false - } - } else { - matched - } - } - ) -} - -fn band_a_emit_readiness_other_gate_matches_frontier_row(row: BandAEmitReadinessRow) -> Bool { - match row.gate { - FlippableNow => true - BodyProducerGated => false - OtherGate { migration_trigger: trigger } => - band_a_emit_readiness_module_is_emitter_produced(module_path: row.module_path) - || band_a_emit_readiness_roster_row_trigger_matches( - module_path: row.module_path, - trigger: trigger, - row: compiler_frontier_row_use_site_verdict - ) - || band_a_emit_readiness_roster_row_trigger_matches( - module_path: row.module_path, - trigger: trigger, - row: compiler_frontier_row_materialization_carriers - ) - || band_a_emit_readiness_roster_row_trigger_matches( - module_path: row.module_path, - trigger: trigger, - row: compiler_frontier_row_self_host - ) - } -} - -fn compiler_frontier_band_a_other_gate_triggers_match_holds() -> Bool { - fold_list( - xs: compiler_frontier_band_a_emit_readiness_roster, - empty: true, - cons: fn(ok, row) { - ok && band_a_emit_readiness_other_gate_matches_frontier_row(row: row) - } - ) -} - -fn compiler_frontier_band_a_emit_readiness_holds() -> Bool { - compiler_frontier_band_a_emit_readiness_core_holds() - && compiler_frontier_band_a_other_gate_triggers_match_holds() -} - -fn frontier_roster_row_blocker_matches_probe( - row: CompilerModuleFrontierRow, - receipt: FrontierProbeReceipt -) -> Bool { - (row.module_path == receipt.module_path) - && frontier_blocker_class_matches( - blocker: row.measured_probe.blocker_class, - target: receipt.blocker_class - ) -} - -fn compiler_frontier_row_for_path_matches_probe( - target: String, - receipt: FrontierProbeReceipt -) -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: false, - cons: fn(matched, row) { - if row.module_path == target { - frontier_roster_row_blocker_matches_probe(row: row, receipt: receipt) - } else { - matched - } - } - ) -} - -fn compiler_frontier_roster_matches_survey_holds(survey: List) -> Bool { - fold_list( - xs: survey, - empty: true, - cons: fn(ok, receipt) { - ok && compiler_frontier_row_for_path_matches_probe( - target: frontier_probe_receipt_module_path(receipt: receipt), - receipt: receipt - ) - } - ) -} - -data frontier_binding_projection_note: String = "Task 3 of docs/plans/module-identity-storage-binding-design.md: the path→module lookup is a PROJECTION off the derived binding authority (v2.compiler.source_authority ModuleStorageIndex), not a read of a hand table. The 27 hand FrontierQualifiedModuleBinding rows were the second authority §3 forbids; they survive in this PR only as the transition-parity oracle below and are deleted with it. - -The index arrives as a PARAMETER rather than an import, and that is forced by the layer DAG: the live rows are host-supplied through v2.test.workflow.host_module_binding_manifest, and no src/v2/compiler module may import v2.test.* (imports point toward std, §3). So the compiler layer owns the pure lookup and the test layer supplies the index. - -The distinction that decides whether this is a real dissolution or a relocated ledger is WHAT FLOWS IN, not the arity: passing a pure constant hand index would satisfy the signature and still be a parallel ledger. The live callers pass host_module_bindings." - -data frontier_binding_refusal_note: String = "Two DISTINCT located causes, never one. The prior lookup returned \"\" on miss — a sentinel meaning BOTH 'no binding for this path' AND 'the module name is empty' (state-space conflation, a named recurring failure mode). Projected off an unavailable index that sentinel becomes actively dangerous: every lookup returns \"\", and rust_qualified_module_mod_basename would fabricate a basename from the empty string SILENTLY, so a gate reading an EMPTY carrier would report on names it invented (§5 fabricated plausible output — structurally the coverage_complete-over-Empty shape). - -^frontier_binding_index_unavailable says the projection could not be computed (⊤-as-ignorance). ^frontier_binding_path_unbound says it was computed and this path genuinely has no module (a real answer). Their remedies differ — supply the index vs fix the roster or the tree — which is exactly why they are not one arm." - -fn frontier_binding_diagnostic(reason: Symbol) -> Diagnostic { - Diagnostic { - reason: reason, - at: port_locus(port: ^compiler_frontier_binding_port), - correction: Unavailable { reason: ExternalContractUnknown } - } -} - -data frontier_emitter_hand_row_debt_note: String = "TYPED, COUNTED DEBT — the emit path still reads the hand rows, and this is the one place that says so out loud. - -WHY IT SURVIVES: dag/gunbc/stage0_crate_layout_emit.dag generates stage0_crate_layout_generated.dag, and it is reached through generated_artifact_emit.dag's dispatch — ONE match over ~18 artifact variants, every one a zero-arg generator returning String. Supplying a ModuleStorageIndex there would force 17 unrelated generators to accept a host artifact they cannot use — the same coupling refused when the layout conjunct left compiler_frontier_census_holds (frontier_census_layout_relocation_note). Refusing it in one direction and accepting it in the other would be incoherent. - -COUNT: exactly ONE consumer chain — expected_stage0_crate_layout_generated_dag / _rs via hand_maintained_pub_mod_basenames, hand_maintained_stage0_filenames, emit_hand_maintained_pub_mod_block. Any NEW caller of the _hand_rows family is a regression, not a use. - -WHY THIS IS AN HONEST INTERIM RATHER THAN THE FORK §3 FORBIDS: the two authorities are not merely both present, they are PARITY-GATED. transition_parity_host_index_agrees_with_hand_rows is a STANDING witness on the wet cadence (promoted from transition artifact, parent ruling 2026-07-19) that REDS the moment the derived index and the hand rows disagree. A marked, parity-gated, trigger-bound duality is an interim; the same duality without the standing witness is a silent fork. - -dissolve-on: host-driven generation of the crate-layout artifact with the index supplied at the boundary (only host boundaries project paths, §2/§3) — its own designed lane, not a patch, because it touches the generated-artifact source and the same-PR regen discipline of the drift-gate chain. When it lands, this family, the 27 hand rows, FrontierQualifiedModuleBinding, and the parity witness are deleted TOGETHER." - -fn frontier_hand_rows_qualified_module_for_path(target: String) -> String { - fold_list( - xs: compiler_frontier_qualified_module_bindings, - empty: "", - cons: fn(found, binding) { - if found != "" { - found - } else if binding.module_path == target { - binding.qualified_module - } else { - "" - } - } - ) -} - -fn frontier_hand_rows_row_stage0_mod_basename(row: CompilerModuleFrontierRow) -> String { - rust_qualified_module_mod_basename( - qualified_module: frontier_hand_rows_qualified_module_for_path(target: row.module_path) - ) -} - -fn frontier_hand_rows_emitter_produced_row_basename(row: CompilerModuleFrontierRow) -> List { - match row.disposition { - EmitterProduced { authorization_binding: _ } => [frontier_hand_rows_row_stage0_mod_basename(row: row)] - SeedRetained { reason: _, migration_trigger: _ } => [] - } -} - -fn compiler_frontier_emitter_produced_stage0_mod_basenames() -> List { - fold( - compiler_frontier_roster, - init: [], - f: fn(acc, row) { - concat(acc, frontier_hand_rows_emitter_produced_row_basename(row: row)) - } - ) -} - -fn compiler_frontier_qualified_module_for_path( - index: ModuleStorageIndex, - target: String -) -> Outcome { - if length(xs: index) == 0 { - outcome_rejected(d: frontier_binding_diagnostic(reason: ^frontier_binding_index_unavailable)) - } else { - match module_storage_module_for_path(index: index, file_path: target) { - Present { value: v } => outcome_accepted(value: v) - Absent => outcome_rejected(d: frontier_binding_diagnostic(reason: ^frontier_binding_path_unbound)) - } - } -} - -fn compiler_frontier_qualified_module_dotted_for_path( - index: ModuleStorageIndex, - target: String -) -> Outcome { - bind_outcome( - o: compiler_frontier_qualified_module_for_path(index: index, target: target), - f: fn(qn) { outcome_accepted(value: qualified_name_to_dotted_string(qn: qn)) } - ) -} - -fn compiler_frontier_qualified_module_bindings_unique_holds(index: ModuleStorageIndex) -> Bool { - fold_list( - xs: compiler_frontier_roster, - empty: true, - cons: fn(ok, row) { - ok - && (match compiler_frontier_qualified_module_for_path(index: index, target: row.module_path) { - Accepted { value: _, diagnostics: _ } => true - Rejected { diagnostics: _ } => false - }) - && (count_rows_with_module_path(xs: compiler_frontier_roster, target: row.module_path) == 1) - } - ) -} - -fn frontier_row_stage0_mod_basename( - index: ModuleStorageIndex, - row: CompilerModuleFrontierRow -) -> Outcome { - bind_outcome( - o: compiler_frontier_qualified_module_dotted_for_path(index: index, target: row.module_path), - f: fn(dotted) { - outcome_accepted(value: rust_qualified_module_mod_basename(qualified_module: dotted)) - } - ) -} - -data frontier_basename_refusal_drop_note: String = "A row whose basename cannot be projected contributes NOTHING to this list, and the caller detects that by COUNT, not by a sentinel entry. compiler_frontier_crate_layout_holds asserts the produced length equals compiler_frontier_emitter_produced_count(), so a refused projection shortens the list and REDS the gate — it cannot pass with an invented name in place of a real one. - -That count assertion is load-bearing rather than incidental: dropping a refusal silently is exactly the absorbing-drop shape section 5 forbids (the pre-Phase-1 derivation made a failed module invisible to every downstream lookup), and the length check is what converts the drop back into a loud, counted failure. Do not weaken it to a subset test." - -fn emitter_produced_frontier_row_stage0_mod_basename( - index: ModuleStorageIndex, - row: CompilerModuleFrontierRow -) -> List { - match row.disposition { - EmitterProduced { authorization_binding: _ } => { - match frontier_row_stage0_mod_basename(index: index, row: row) { - Accepted { value: b, diagnostics: _ } => [b] - Rejected { diagnostics: _ } => [] - } - } - SeedRetained { reason: _, migration_trigger: _ } => [] - } -} - -fn compiler_frontier_emitter_produced_stage0_mod_basenames_from_index(index: ModuleStorageIndex) -> List { - fold( - compiler_frontier_roster, - init: [], - f: fn(acc, row) { - concat(acc, emitter_produced_frontier_row_stage0_mod_basename(index: index, row: row)) - } - ) -} - -type SeedRetainedIntrinsicRegistration { - basename: String - has_pub_mod: Bool - is_dir: Bool -} - -type SeedRetainedScaffoldRegistration { - basename: String -} - -type SeedRetainedSupportDirRegistration { - basename: String -} - -data seed_retained_intrinsic_registrations: List = [ - SeedRetainedIntrinsicRegistration { basename: "v1_interpreter", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "bounded_shell_host_drain", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "ci_control_plane", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "cli_run", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "coproduct_reflection", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "data_initializer_identity", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "resolved_graph_cache", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "shared_typecheck_store", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "recorded_fixture", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "main", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "phase_profile", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "pre_push", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "census_exclude_derive", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "derived_realization_schedule", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "memory_governor", has_pub_mod: true, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "std_lens_verdict", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "module_path_index", has_pub_mod: true, is_dir: true }, - SeedRetainedIntrinsicRegistration { basename: "v2_compiler_body_producer", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "v2_compiler_normalize", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "v2_compiler_target_carriers", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "v2_compiler_discovery_enumeration", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "v2_compiler_parse_engine_hooks", has_pub_mod: false, is_dir: false }, - SeedRetainedIntrinsicRegistration { basename: "v2_compiler_use_site_verdict", has_pub_mod: false, is_dir: false } -] - -data data_initializer_identity_seed_retained_note: String = "SeedRetained hand-Rust for resolved data-initializer projection marshaling (decl_facts initializer identity lane, PR #7924). Reason: marshal requires InterpContext typechecked subjects, inferred Node stamps, and owning type-item lookup not yet modeled in .dag. Migration trigger: v2.std.data_initializer_identity projection carriers self-emit and coproduct_reflection routes through the modeled marshal surface; then this module deletes with its SeedRetainedIntrinsicRegistration row. Frontier row schema lacks reason/trigger fields — this note is the counted scaffold until the schema lands." - -data seed_retained_support_dir_registrations: List = [ - SeedRetainedSupportDirRegistration { basename: "cli_run" } -] - -data seed_retained_quarantine_scaffold_stage0_files_note: String = "Review 44472: six quarantine modules (SeedRetained, emitter_produced_baseline=0) retain emitted .rs on disk for wet re-flip without pub mod — listed in HAND_MAINTAINED_STAGE0_FILES (has_pub_mod: false) so crate layout authority matches filesystem. Dissolve-on: witness-realization enables EmitterProduced and rows return to generated pub mod roster." -data seed_retained_scaffold_registrations: List = [ - SeedRetainedScaffoldRegistration { basename: "usv_pilot_v2_std_algebra" }, - SeedRetainedScaffoldRegistration { basename: "usv_pilot_v2_std_collection" }, - SeedRetainedScaffoldRegistration { basename: "usv_pilot_v2_std_node" }, - SeedRetainedScaffoldRegistration { basename: "v2_compiler_resolve" }, - SeedRetainedScaffoldRegistration { basename: "v2_compiler_program_partition" }, - SeedRetainedScaffoldRegistration { basename: "v2_compiler_tokenize" }, - SeedRetainedScaffoldRegistration { basename: "v2_compiler_infer" }, - SeedRetainedScaffoldRegistration { basename: "v1_interpreter_dispatch_generated" } -] - -fn intrinsic_pub_mod_basename_from_row(row: SeedRetainedIntrinsicRegistration) -> List { - if row.has_pub_mod { - [row.basename] - } else { - [] - } -} - -fn intrinsic_stage0_filename_from_row(row: SeedRetainedIntrinsicRegistration) -> List { - if row.is_dir { - [] - } else { - [concat(row.basename, ".rs")] - } -} - -fn intrinsic_stage0_dir_from_row(row: SeedRetainedIntrinsicRegistration) -> List { - if row.is_dir { - [row.basename] - } else { - [] - } -} - -fn seed_retained_intrinsic_pub_mod_basenames() -> List { - fold( - seed_retained_intrinsic_registrations, - init: [], - f: fn(acc, row) { - concat(acc, intrinsic_pub_mod_basename_from_row(row: row)) - } - ) -} - -fn seed_retained_intrinsic_stage0_files() -> List { - fold( - seed_retained_intrinsic_registrations, - init: [], - f: fn(acc, row) { - concat(acc, intrinsic_stage0_filename_from_row(row: row)) - } - ) -} - -fn seed_retained_scaffold_pub_mod_basenames() -> List { - fold( - seed_retained_scaffold_registrations, - init: [], - f: fn(acc, row) { - concat(acc, [row.basename]) - } - ) -} - -fn seed_retained_scaffold_stage0_files() -> List { - fold( - seed_retained_scaffold_registrations, - init: [], - f: fn(acc, row) { - concat(acc, [concat(row.basename, ".rs")]) - } - ) -} - -fn seed_retained_support_stage0_dirs() -> List { - fold( - seed_retained_support_dir_registrations, - init: [], - f: fn(acc, row) { - concat(acc, [row.basename]) - } - ) -} - -fn hand_maintained_stage0_dirs() -> List { - concat( - fold( - seed_retained_intrinsic_registrations, - init: [], - f: fn(acc, row) { - concat(acc, intrinsic_stage0_dir_from_row(row: row)) - } - ), - seed_retained_support_stage0_dirs() - ) -} - -fn basename_to_pub_mod_decl(basename: String) -> String { - concat("pub mod ", basename, ";") -} - -fn dispatch_generated_macro_use_pub_mod_decl() -> String { - "#[macro_use]\npub mod v1_interpreter_dispatch_generated;" -} - -fn pub_mod_decl_lines_for_basename(basename: String) -> List { - if basename == "v1_interpreter" { - [ - dispatch_generated_macro_use_pub_mod_decl(), - basename_to_pub_mod_decl(basename: basename), - ] - } else if basename == "v1_interpreter_dispatch_generated" { - [] - } else { - [basename_to_pub_mod_decl(basename: basename)] - } -} - -fn format_pub_mod_declarations(basenames: List) -> String { - let lines = basenames |> flat_map(basename => pub_mod_decl_lines_for_basename(basename: basename)) - concat("\n", lines |> join(separator: "\n")) -} - -fn basename_to_stage0_filename(basename: String) -> String { - concat(basename, ".rs") -} - -fn basenames_to_stage0_filenames(basenames: List) -> List { - basenames |> map(basename_to_stage0_filename) -} - -data frontier_hand_maintained_arity_note: String = "These three keep their ORIGINAL zero-arity shape and read the hand rows, deliberately — they are the emit path described in frontier_emitter_hand_row_debt_note, and their caller (generated_artifact_emit.dag's ~18-variant dispatch) has no index to give them. Changing their arity is what broke this lane once: dag/gunbc and dag/test/claim callers compile CLEAN at a stale arity because .dag does not arity-check these cross-module sites, so the breakage surfaces only at run time." - -fn hand_maintained_pub_mod_basenames() -> List { - concat( - concat(seed_retained_intrinsic_pub_mod_basenames(), seed_retained_scaffold_pub_mod_basenames()), - compiler_frontier_emitter_produced_stage0_mod_basenames() - ) -} - -fn emit_hand_maintained_pub_mod_block() -> String { - format_pub_mod_declarations(basenames: hand_maintained_pub_mod_basenames()) -} - -fn hand_maintained_stage0_filenames() -> List { - concat( - concat(seed_retained_intrinsic_stage0_files(), seed_retained_scaffold_stage0_files()), - basenames_to_stage0_filenames( - basenames: compiler_frontier_emitter_produced_stage0_mod_basenames() - ) - ) -} - -fn compiler_frontier_crate_layout_holds(index: ModuleStorageIndex) -> Bool { - compiler_frontier_qualified_module_bindings_unique_holds(index: index) - && (length(xs: compiler_frontier_emitter_produced_stage0_mod_basenames_from_index(index: index)) == compiler_frontier_emitter_produced_count()) -} - -fn compiler_frontier_census_holds() -> Bool { - compiler_frontier_roster_paths_unique_holds() - && compiler_frontier_producer_qualified_baselines_holds() - && compiler_frontier_emitter_produced_oracle_enrolled_holds() - && compiler_frontier_emitter_produced_authorization_mint_consistent_holds() - && compiler_frontier_emitter_produced_oracle_count_matches_baseline_holds() - && compiler_frontier_execution_measured_attribution_holds() - && compiler_frontier_blocker_class_distribution_knowledge_attributed_holds() - && compiler_frontier_gap_clustering_knowledge_attributed_holds() - && compiler_frontier_sweep_order_complete_holds() - && compiler_frontier_sweep_order_matches_tractability_rank_holds() - && compiler_frontier_roster_all_classified_holds() - && compiler_frontier_roster_located_reason_not_class_projection_holds() - && compiler_frontier_emitter_produced_located_reason_holds() - && compiler_frontier_roster_probe_paths_match_holds() - && compiler_frontier_band_a_emit_readiness_holds() -} - -data frontier_census_layout_relocation_note: String = "SCOPE CHANGE, stated loudly because it NARROWS this gate: compiler_frontier_crate_layout_holds is no longer a conjunct of compiler_frontier_census_holds. It is RELOCATED, not deleted, and the relocation lands in the same PR as this removal — never a removal now and an enrollment later, which would leave a window where nothing checks it. - -WHY it cannot stay here: the layout gate now requires a ModuleStorageIndex, and the live index is host-supplied through v2.test.workflow.host_module_binding_manifest. compiler_frontier_census_holds is a pure zero-arity gate on the FAST lane with no way to obtain one, and the layer DAG forbids a compiler module importing v2.test.* to reach it. Threading an index through the whole census — whose other ~12 conjuncts have nothing to do with bindings — would make every unrelated census check depend on a host artifact, which is a worse coupling than the one being removed. - -WHERE it went: v2.test.claim.self_host.crate_layout_witness_test, enrolled on the WET cadence (module_binding_supply_transport), where the real index exists. The fast-lane census keeps every conjunct that does not need one, so this narrows the fast lane by exactly one check and widens what that check can actually see — from 27 hand rows to the whole-tree derived index. - -The honest cost: a PR that touches only the frontier roster no longer gets layout coverage in the fast lane; it gets it on the wet cadence instead. That is a real latency increase for that one signal, accepted deliberately rather than papered over." - -data construction_justification: ConstructionJustification = ConstructionJustification { - class: WallAfterGrounding { dissolves_to: RealizationDispatch } -} diff --git a/src/v2/compiler/self_host/frontier_band_a_emit_readiness.dag b/src/v2/compiler/self_host/frontier_band_a_emit_readiness.dag deleted file mode 100644 index f28052a2772..00000000000 --- a/src/v2/compiler/self_host/frontier_band_a_emit_readiness.dag +++ /dev/null @@ -1,146 +0,0 @@ -module v2.compiler.self_host.frontier_band_a_emit_readiness - -import v2.std.algebra { fold_list, length } -import v2.std.collection { List } -import v2.std.logic { Bool } -import v2.std.node { Symbol } -import v2.std.text { String } - -type BandAWave1EmitReadiness - = FlippableNow - | BodyProducerGated - | OtherGate { migration_trigger: Symbol } - -type BandAEmitReadinessRow { - module_path: String - gate: BandAWave1EmitReadiness -} - -data compiler_frontier_band_a_emit_readiness_note: String = "Band A Wave-1-pre-flip recon: FlippableNow = no dependency on Wave 1 gates 1-3 (general body producer ingest, namespace SymbolIndex, FLAG D). Program policy sequences Band A after Wave 1 gate 4 (weak self-host behavioral receipt). BodyProducerGated count must remain 0 on this roster. OtherGate cites the matching compiler_frontier_row_* migration_trigger. Gate-4 follow-up (swift-lynx-212): pure-decl modules are NOT flippable before gate 4 — Rust Track A6 data_decl emit is absent (rust.dag has no data_decl rows; parse_engine_hooks is 100% data Symbol=^atom), frontier_probe_emit_from_ingest is unstaged (#6464), and no per-module SeedRetained->SelfEmitted receipt path exists today. TWO OF THOSE THREE BLOCKERS ARE STALE as of 2026-08-12, verified by resolving each symbol rather than by re-reading this note: v2.compiler.self_host.candidate_generation observe_provenanced_rust_emission_from_ingest exists and drives ingest through assemble, infer, rust emission candidate and artifact mint, so the emit-from-ingest probe is staged; and v2.compiler.self_host.emitter_producer_provenance mint_producer_emission_receipt together with v2.compiler.self_host.frontier mint_emitter_produced_frontier_promotion are the per-module receipt-to-promotion path this note says does not exist. The FIRST blocker still holds and was re-verified the same way: v2.extdeps.languages.rust rust_semantic_decl_surface_projection carries record and coproduct layouts only, with no value-declaration surface, so a module that is entirely `data : Symbol = ^atom` has nothing to emit through. STAGE CORRECTION (2026-08-12, SH-A control): that surviving blocker is REAL but LATENT, and the sentence this replaces — that readiness turns on that one capability — was wrong. A module-level data declaration never reaches emission. SH-A measured it with a control holding wiring, artifact, compilation unit, module name and admission identical and varying only the declaration inside the module: a fn declaration reaches EmissionRejected with infer_grounding_not_derived, while a data declaration stops at ASSEMBLY with parse_grammar_choice_overlap_residue. The refusal fires two stages before the missing renderer would run, so building value-declaration emission now would produce a renderer that cannot execute once.\n\nThe binding constraint is therefore the grammar refusal, and it is already owned: v2.workflow.compile_door_ledger known_frontier_causes carries parse_grammar_choice_overlap_residue as MigrationOwned, dissolving by construction at phase-3 import-grammar deletion in the namespace-only resolution lane. Opening a second lane against it forks scheduled work. The row above already said this — its located_stage is ProbeStageAssemble and its located_reason is that cause — which is the point worth keeping: the stage was recorded correctly and was read past, so a reader who takes the missing-capability sentence as the schedule will price and sequence the wrong work. Wave 2 use_site_verdict pilot follow-up: wrap_decision_gate landed (#6776) and 06_translate routes through it (#6775); UseSiteVerdict enrolled in rust_sg_rc_use_site_ownership_catalog (owned-at-all-sites). Remaining FlippableNow rows (parse_engine_hooks, discovery_enumeration) still gated on rustc-green behavioral receipts and Track B body emit — not the ownership gate alone." - -data compiler_frontier_band_a_row_parse_engine_hooks: BandAEmitReadinessRow = BandAEmitReadinessRow { - module_path: "src/v2/compiler/parse_engine_hooks.dag", - gate: FlippableNow -} - -data compiler_frontier_band_a_row_use_site_verdict: BandAEmitReadinessRow = BandAEmitReadinessRow { - module_path: "src/v2/compiler/use_site_verdict.dag", - gate: FlippableNow -} - -data compiler_frontier_band_a_row_discovery_enumeration: BandAEmitReadinessRow = BandAEmitReadinessRow { - module_path: "src/v2/compiler/discovery_enumeration.dag", - gate: FlippableNow -} - -data compiler_frontier_band_a_row_self_host: BandAEmitReadinessRow = BandAEmitReadinessRow { - module_path: "src/v2/compiler/self_host.dag", - gate: OtherGate { migration_trigger: ^migrate_when_frontier_harness_repurposed } -} - -data compiler_frontier_band_a_row_materialization_carriers: BandAEmitReadinessRow = BandAEmitReadinessRow { - module_path: "src/v2/compiler/materialization_carriers.dag", - gate: OtherGate { migration_trigger: ^migrate_when_closure_self_emits_cargo_green } -} - -data compiler_frontier_band_a_row_07_target_carriers: BandAEmitReadinessRow = BandAEmitReadinessRow { - module_path: "src/v2/compiler/07_target_carriers.dag", - gate: FlippableNow -} - -data compiler_frontier_band_a_emit_readiness_roster: List = [ - compiler_frontier_band_a_row_parse_engine_hooks, - compiler_frontier_band_a_row_use_site_verdict, - compiler_frontier_band_a_row_discovery_enumeration, - compiler_frontier_band_a_row_self_host, - compiler_frontier_band_a_row_materialization_carriers, - compiler_frontier_band_a_row_07_target_carriers -] - -fn compiler_frontier_band_a_body_producer_gated_count() -> Int { - fold_list( - xs: compiler_frontier_band_a_emit_readiness_roster, - empty: 0, - cons: fn(count, row) { - match row.gate { - BodyProducerGated => count + 1 - _ => count - } - } - ) -} - -fn compiler_frontier_band_a_flippable_now_count() -> Int { - fold_list( - xs: compiler_frontier_band_a_emit_readiness_roster, - empty: 0, - cons: fn(count, row) { - match row.gate { - FlippableNow => count + 1 - _ => count - } - } - ) -} - -fn compiler_frontier_band_a_other_gate_count() -> Int { - fold_list( - xs: compiler_frontier_band_a_emit_readiness_roster, - empty: 0, - cons: fn(count, row) { - match row.gate { - OtherGate { migration_trigger: _ } => count + 1 - _ => count - } - } - ) -} - -fn compiler_frontier_band_a_emit_readiness_core_holds() -> Bool { - let gate_total = compiler_frontier_band_a_flippable_now_count() + compiler_frontier_band_a_other_gate_count() + compiler_frontier_band_a_body_producer_gated_count() - compiler_frontier_band_a_paths_unique_holds() - && (compiler_frontier_band_a_body_producer_gated_count() == 0) - && (compiler_frontier_band_a_flippable_now_count() == 4) - && (compiler_frontier_band_a_other_gate_count() == 2) - && (gate_total == length(xs: compiler_frontier_band_a_emit_readiness_roster)) -} - -fn count_band_a_emit_readiness_rows_with_path( - xs: List, - target: String -) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, row) { - if row.module_path == target { count + 1 } else { count } - } - ) -} - -fn compiler_frontier_band_a_paths_unique_holds() -> Bool { - count_band_a_emit_readiness_rows_with_path( - xs: compiler_frontier_band_a_emit_readiness_roster, - target: "src/v2/compiler/parse_engine_hooks.dag" - ) == 1 - && count_band_a_emit_readiness_rows_with_path( - xs: compiler_frontier_band_a_emit_readiness_roster, - target: "src/v2/compiler/use_site_verdict.dag" - ) == 1 - && count_band_a_emit_readiness_rows_with_path( - xs: compiler_frontier_band_a_emit_readiness_roster, - target: "src/v2/compiler/discovery_enumeration.dag" - ) == 1 - && count_band_a_emit_readiness_rows_with_path( - xs: compiler_frontier_band_a_emit_readiness_roster, - target: "src/v2/compiler/self_host.dag" - ) == 1 - && count_band_a_emit_readiness_rows_with_path( - xs: compiler_frontier_band_a_emit_readiness_roster, - target: "src/v2/compiler/materialization_carriers.dag" - ) == 1 - && count_band_a_emit_readiness_rows_with_path( - xs: compiler_frontier_band_a_emit_readiness_roster, - target: "src/v2/compiler/07_target_carriers.dag" - ) == 1 -} diff --git a/src/v2/compiler/self_host/frontier_probe_survey.dag b/src/v2/compiler/self_host/frontier_probe_survey.dag deleted file mode 100644 index f6b1ade283a..00000000000 --- a/src/v2/compiler/self_host/frontier_probe_survey.dag +++ /dev/null @@ -1,430 +0,0 @@ -module v2.compiler.self_host.frontier_probe_survey - -import std.dissolution { DissolutionCondition, unbound_dissolution } - -import v2.compiler.self_host.frontier_probe { - frontier_probe_emit_from_ingest -} -import v2.compiler.self_host.frontier_probe_types { - EmitSurfaceGap, - FrontierBlockerClass, - FrontierProbeReceipt, - FrontierSurveyManifest, - FrontierSurveySubject, - NameResolutionGap, - RealizationGap, - SelfEmitReady, - UnknownProbeCause, - FixtureCemented, - UpstreamSemanticRefusal, - frontier_blocker_class_matches, - frontier_survey_commit_tree_binding_holds, - frontier_survey_executable_sha256_holds, - frontier_survey_source_roots_digest_holds, - frontier_probe_policy_revision, - frontier_probe_receipt_blocker_class, - frontier_probe_receipt_located_reason, - frontier_probe_receipt_module_path -} -import std.realization_schedule { scoped_witness_exact_head_text_holds } -import std.content_hash { ContentHash, compare_content_hash, ContentHashEqual } -import v2.compiler.name_resolve { Admission } -import v2.compiler.source_authority { SourceRootIngest } -import v2.std.algebra { Cons, Empty, fold_list, length } -import v2.std.collection { List } -import v2.std.logic { Bool } -import v2.std.node { Symbol } -import v2.std.text { String } - -type FrontierGapClusterVerdict - = CommonRoot { - dominant_located_reason: Symbol, - dominant_module_count: Int, - module_count: Int - } - | HeterogeneousGaps { - distinct_located_reason_count: Int, - module_count: Int - } - -fn frontier_probe_receipt_located_reason_eq(left: Symbol, right: Symbol) -> Bool { - left == right -} - -fn count_receipts_with_located_reason( - xs: List, - target: Symbol -) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, receipt) { - if frontier_probe_receipt_located_reason_eq( - left: frontier_probe_receipt_located_reason(receipt: receipt), - right: target - ) { - count + 1 - } else { - count - } - } - ) -} - -fn count_receipts_with_blocker( - xs: List, - target: FrontierBlockerClass -) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, receipt) { - if frontier_blocker_class_matches( - blocker: frontier_probe_receipt_blocker_class(receipt: receipt), - target: target - ) { - count + 1 - } else { - count - } - } - ) -} - -data frontier_probe_survey_has_unclassified_dispatch_note: String = "frontier_probe_survey_has_unclassified survives predicate dissolution because it is the existential UnknownProbeCause witness gate (any receipt still in the host-deferred / unclassified bucket), not a variant nickname for a single arm. The long-lane survey witness requires !has_unclassified before roster binding; dissolves when measured receipts eliminate the host UnknownProbeCause residue or the gate reads a typed survey-completeness carrier." - -fn frontier_probe_receipt_is_unknown_probe_cause(receipt: FrontierProbeReceipt) -> Bool { - match frontier_probe_receipt_blocker_class(receipt: receipt) { - UnknownProbeCause { reason: _ } => true - _ => false - } -} - -fn frontier_probe_receipt_is_upstream_semantic_refusal(receipt: FrontierProbeReceipt) -> Bool { - match frontier_probe_receipt_blocker_class(receipt: receipt) { - UpstreamSemanticRefusal { diagnostic_class: _, diagnostic_name: _ } => true - _ => false - } -} - -fn frontier_probe_survey_has_unclassified(xs: List) -> Bool { - fold_list( - xs: xs, - empty: false, - cons: fn(found, receipt) { - found || frontier_probe_receipt_is_unknown_probe_cause(receipt: receipt) - } - ) -} - -fn frontier_probe_receipt_for_module( - module_path: String, - ingest: SourceRootIngest, - admission: Admission -) -> FrontierProbeReceipt { - frontier_probe_emit_from_ingest( - module_path: module_path, - ingest: ingest, - admission: admission - ) -} - -fn count_upstream_semantic_refusal_receipts(xs: List) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, receipt) { - if frontier_probe_receipt_is_upstream_semantic_refusal(receipt: receipt) { - count + 1 - } else { - count - } - } - ) -} - -fn count_unknown_probe_cause_receipts(xs: List) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, receipt) { - if frontier_probe_receipt_is_unknown_probe_cause(receipt: receipt) { - count + 1 - } else { - count - } - } - ) -} - -fn count_fixture_cemented_receipts(xs: List) -> Int { - count_receipts_with_blocker(xs: xs, target: FixtureCemented) -} - -data frontier_probe_receipt_totality_wall_note: String = "Receipt-totality wall (Lane E still-dove-191): every survey receipt must partition the module count across the closed FrontierBlockerClass vocabulary; survey module paths must be unique, non-empty, and match the frontier roster exactly once each way. Stale located_reason symbols on knowledge-attributed rows (e.g. gate_a_flip_probe_witness_std_dup after the 2026-07-23 extinction receipt) must be zero — the wall is what stops the next cleanup pass from reintroducing mislocated EmitSurfaceGap rows. Vocabulary + wall land before a second measurement pass rewrites the 27 roster rows.\n\nSILENT-NARROW REFUSAL (operator still-bat-561, 2026-08-04): if a closure exceeds a transport cap and the ingest manifest elides rows to Empty, the survey receipt must REFUSE with a typed counted diagnostic — never attribute a downstream stage failure (e.g. NameResolutionGap / ^resolve_module_not_found) as though the measurement succeeded. Lane 3 (#7762) fixes the MANIFEST_INLINE_LIST_MAX instance; this wall states the general property: the survey cannot silently narrow (⊥-as-ignorance conflated with ⊥-as-answer). A receipt that reports a blocker class without proving the full closure was admitted is a fabricated attribution." - -data frontier_roster_measurement_status_vocabulary_note: String = "STATUS VOCABULARY (operator correction still-bat-561, 2026-08-04): do not use Closed/Open/Surveyed for frontier rows — those words misread as SelfEmitReady or EmitterProduced. Four orthogonal axes, each with its head when execution-measured:\n\nROSTER POPULATION (27): every module in compiler_frontier_sweep_order.\n\nEXECUTION MEASUREMENT: a frontier_probe_emit_from_ingest receipt at a pinned FrontierSurveySubject, recorded in host_frontier_probe_survey_manifest with matching subject identity on every row. Count without a head is unreportable. Prior dated receipt at 9f978aa8df counted 17 modules (zero self_emit_ready=yes); it is superseded, not combinable with a later head.\n\nNO EXECUTION MEASUREMENT: roster row whose measured_probe is knowledge-attributed or oracle-derived without a manifest receipt at the current pinned head — not 'open', not 'closed'.\n\nSELF_EMIT_READY (probe readiness): measured_probe.blocker_class == SelfEmitReady at the pinned head — this exact module reached and passed the self-emit readiness bar on the probe slice. Distinct from execution measurement (a measured row can still be SeedRetained) and from roster disposition. Live count: 0 at every head measured to date.\n\nEMITTER_PRODUCED (authorized roster promotion): disposition == EmitterProduced via mint_emitter_produced_frontier_promotion only — the roster disposition was atomically authorized. The direct door can hold SourceProduced, CargoGreen, and BehavioralEquivalent without any frontier row becoming EmitterProduced; that separation is why these axes exist. Live count: 0 (emitter_produced_frontier_promotions is empty).\n\nDo not round an unmeasured row to any blocker class. Do not report a count without its head." - -data frontier_roster_measurement_census_at_9f978aa8df_note: String = "Dated census at source_head 9f978aa8df only (receipt TSV deleted 2026-08-16 (operator ruling: delete anything not actively derived); probe pre-#7762 — three NameResolutionGap rows are suspect manifest-elision artifacts, not name-resolution facts). Probe invocation used --source-root src/v2 only; authoritative closeout uses src/v2 + dag (different source_roots_digest even at the same commit). At that head: execution_measurement=17, no_execution_measurement=10, self_emit_ready=0, emitter_produced=0. All 27 rows remain SeedRetained disposition. Not combinable with any later head or changed source-root set; superseded by post-#7762 27/27 rerun." - -data frontier_probe_exact_head_closeout_note: String = "Lane 1 exact-current-head closeout (sleek-pike-668): LAST of four — #7776 vocabulary, #7762 final, and #7767 assemble diagnostic payloads are merged on main; authoritative 27/27 remains on operator hold (not predecessor blockers). ADMISSION CONTRACT FOR THE AUTHORITATIVE SURVEY (operator ruling, 2026-08-06). Stated as CONDITIONS ON THE TREE, deliberately naming no PR number, no head SHA, no draft state and no control tally. A receipt that names those is a second mutable copy of the board: it is wrong again every time the board moves, and it has to be patched by hand each time — which is the SAME defect class frontier_roster_provenance_constructor_inflation_note files one layer down, a claim asserted in a place that cannot check it. So this note does not commit it. THE AUTHORITATIVE SURVEY MAY START ONLY WHEN ALL FOUR HOLD: (1) whole-tree hard diagnostics equals zero; (2) ConstructorReferenceAdmission has ONE authority and NO known-red control; (3) all seven partition crates are continuously checked; (4) FrontierEvidenceProvenance is CONSTRUCTION-ENFORCED. Each is decidable against whatever head is current, so the contract stays true as heads move and changes land. For WHICH change currently carries which condition, read the board — not this receipt. Two conditions are easy to under-read and are therefore spelled out. Condition (2) is not discharged by a de-fork landing while a control remains inverted: one authority AND no known-red are both required, because a partially admitted constructor authority means a survey measures a tree in which a sealed constructor is reachable without admission. Condition (4) is what stops the survey writing all 27 roster rows through the provenance-conflating constructor; it is a construction wall to be BUILT, and this receipt does not build it — this receipt RECORDS the provenance defect, and the separate FrontierEvidenceProvenance change FIXES it.\n\nEXECUTION MODEL — 27 INDEPENDENT JOBS, NOT ONE PROCESS (operator ruling, superseding any single-process retry): one pinned survey subject; 27 independent module jobs; ONE RECEIPT ARTIFACT PER MODULE; one final exact-subject aggregator. A killed module job yields an interrupted ROW and is rerun independently — twenty-six completed rows must not be lost because the twenty-seventh receives SIGKILL. This is designed out of the failure this receipt records: the monolithic run lost everything each time it died, six times. Do NOT retry a monolithic 27-module process in the same opaque session envelope; the ancestor killer is still there and still unobservable from inside, so the response is independent jobs with a visible kill boundary, never a bigger cap. Every receipt carries the same exact subject and a killed job is RERUN, never hand-reconciled into the manifest — reconciling a job that ran against a different subject is what turns a partial survey into a fabricated one.\n\nREQUIRED OUTPUT SHAPE: frontier population 27; exact-head measured 27; SelfEmitReady N; EmitterProduced 0; blocker groups BY DETAILED CAUSE. The last is load-bearing and is not a table of high-level reason strings: the 14 modules that shared ^parse_grammar_choice_overlap_residue at 9f978aa8df must have their detailed causes separated, because the next phase picks the lowest-cost module in the largest DETAILED group on the premise that one root governs many. A high-level grouping cannot rank that. #7762 ref-population gap closed on main — do not forge subjects on today's probe. Definitive run: clean detached worktree; build receipt binding commit, tree, compiler sources, probe executable digest, source-root set, and probe-policy revision; every shard carries complete FrontierSurveySubject; all 27 subjects must compare exactly equal before aggregation. Prior interim audit at 9f978aa8df recorded execution_measurement=17, no_execution_measurement=10, self_emit_ready=0, emitter_produced=0 at that head only. Closeout completes when host_frontier_probe_survey_manifest is a well-formed FrontierSurveyManifest with 27 receipts at one subject, frontier.dag rows hand-authored from that manifest, compiler_frontier_per_module_probe_survey_holds greens, and the offline claim_batch recipe passes." - -data frontier_probe_run_interruption_note: String = "EXECUTED RECEIPT OF AN INTERRUPTED RUN, rehearsal at source_head 2be88489b1303357a10b135dd90704103ea93b0e (tidy-bee-50, 2026-08-06; receipt docs/probes/frontier_probe_run_interrupted_2026-08-06.md). The authoritative 27/27 did NOT run and this note carries no frontier counts. frontier_probe_emit_from_ingest was SIGKILLed before emitting a receipt for ANY module: six invocations, six kills, zero receipts — one-shot over all 27 (killed during module 1 of 27), plus 03_normalize, 03_resolve and 01_tokenize individually at --source-root src/v2 + dag, plus 03_normalize at --source-root src/v2 alone, plus a later 01_tokenize retry under low host load that survived to 3.5 minutes at about 2.0 GB before being killed anyway. Host cgroup memory.max = 33578549248 (31.3 GiB). Every death is located identically: immediately after the per-module probe begins, inside the interpreted evaluation, with the ingest closure already read to completion — so it is not an ingest or discovery failure.\n\nINSTRUMENT CONTROL, AND THE MISATTRIBUTION IT CAUGHT. cgroup memory.events oom_kill incremented 1 through 5, one per killed run, in exact lockstep — which establishes these were real kernel kills of processes in this cgroup, and establishes NOTHING about what killed them. The full counter set: memory.max 33578549248 (31.3 GiB), memory.peak 9136902144 (8.5 GiB), memory.events max 0 / oom 0 / oom_kill 8. max 0 means allocation NEVER reached memory.max; oom 0 means the CGROUP oom killer was never invoked; and in cgroup v2 oom_kill also counts tasks reaped by the GLOBAL killer. The cgroup never exceeded 27 percent of its cap at any point. THEREFORE these kills came from host-level pressure on a shared machine, not from this cgroup limit and not from the probe working set — the probe was killed at or below 8.5 GiB cgroup-wide, which is not a runaway signature.\n\nTWO CLAIMS WITHDRAWN AS REFUTED, both asserted by an earlier revision of this note: (1) that the probe requires more than 31 GiB — refuted by memory.peak 8.5 GiB; (2) that this host cannot cold-build v1-compiler — refuted by an independent same-fleet control under a byte-identical memory.max of 33578549248, which cold-built the crate (sccache cache hits 0, 1 compilation, 163s rustc) in 2m59s at a 3.26 GiB peak with oom_kill 0. The crate needs about 3.3 GiB, not 31. The oom_kill counter is a sound control for 'was this a kill' and a worthless one for 'what hit the limit'; memory.events max/oom and memory.peak answer the second and were available throughout.\n\nTWO HYPOTHESES REFUTED BY EXECUTION, both plausible, neither reported as a cause. (a) 'the 10 never-measured modules are the memory-bound ones' — refused by 01_tokenize, which is one of the 17 that DID measure at 9f978aa8df and OOMs now. (b) 'the widened src/v2 + dag root set is the cause' — refused by 03_normalize OOMing at src/v2 alone. Cause is neither module identity nor root set, and remains OPEN.\n\nREGRESSION-VS-CAPACITY UNRESOLVED, CAUSE IS CONTENTION NOT CAPACITY: the discriminating run (build the probe at 9f978aa8df, where 17 modules measured cleanly, and probe here) did not complete — three builds at that head were killed under sccache (Compiler killed by signal 9): release at CARGO_BUILD_JOBS=15 (oom_kill 6), release at CARGO_BUILD_JOBS=1 (oom_kill 7), debug profile (oom_kill 9 incl. a later gunbc compile). Those three are VICTIMS, NOT DIAGNOSES: none reached this cgroup limit, and the same-cap control above cold-builds the crate at 3.26 GiB, so they died to host pressure they did not cause and say nothing about the crate. The tempting inference — one rustc died, therefore one rustc needs the whole cap — is invalid, because a process reaped by an EXTERNAL oom killer reports the machine at that moment, not itself. The condition is retryable rather than blocking; per operator direction it is reported, not chased, and the probe is not trimmed to fit. Preserve the distinction when assessing: 15 parallel rustc processes collectively reaching the cap is ordinary; ONE probe process reaching it for ONE module is not, and only the second is evidence about the probe.\n\nCANDIDATE, NOT A DIAGNOSIS: #7762 closed the manifest-elision silent-narrow, so the probe now admits the full closure where it previously elided rows. Closing a narrowing that implicitly bounded memory would produce this shape (DESIGN precedent: removing the scan-all-keys fail-open exposed 8 deficits its silence had hidden). Untested; to be assessed by that change's owner, not diagnosed from outside.\n\nCONSEQUENCE, STATED AT THE SCOPE THE EVIDENCE SUPPORTS: 27/27 DID NOT COMPLETE in this window on either documented path — the one-shot or the per-module fallback docs/probes/run_frontier_probe_survey_per_module.sh — but 'unreachable' is NOT established and an earlier revision of this note wrongly said so. Since no run reached the cgroup limit, nothing here shows the probe cannot fit; the runs were interrupted by external pressure. Retry under low host load before concluding anything about probe cost, and treat any per-module cost claim as unmeasured until a run completes or a kill is attributable to this cgroup. Operator direction: the probe must NOT be trimmed to fit the host; a probe shrunk to fit a box measures a different question. Dissolve-on, BOTH conditions: the probe emits a receipt for at least one module at a pinned FrontierSurveySubject AND roster row provenance becomes structural — then this note and its receipt delete together. Both are required because the bound receipt also carries frontier_roster_provenance_constructor_inflation_note as an additional work, so the emit condition alone would delete a finding that is still live; this matches the dissolution on the HandAuthoredDocBind for slug frontier_probe_run_interrupted_2026-08-06 in gunbc.doc_graph_roots, which is the single authority for when that doc deletes." - -data frontier_roster_provenance_constructor_inflation_note: String = "RUNG INFLATION in the roster carrier itself (DESIGN 4b), found 2026-08-06 (tidy-bee-50), independent of the run interruption above and not caused by it. v2.compiler.self_host.frontier declares knowledge_attributed_blocker_class_seed_retained_row — the constructor whose name honestly marks a row knowledge-attributed rather than measured — and it has ZERO call sites: repo-wide the only occurrence of that symbol is its own definition. Meanwhile all 10 roster modules never execution-measured at any head are authored through execution_measured_seed_retained_row, whose name asserts execution measurement: 8 directly, and 03_normalize plus 03_body_producer via quarantine_seed_retained_row_from_oracle, which itself delegates to it. The 10, derived by joining compiler_frontier_sweep_order against the interim TSV module column: 03_body_producer, 03_name_resolve, 03_normalize, 03_resolve, 05_emit_orchestration, emit_host, emit_module, emit_produced, emit_semantic_decl, program_assembly.\n\nMECHANISM MATTERS MORE THAN THE COUNT: execution_measured_seed_retained_row takes measured_blocker, located_stage and located_reason as ordinary parameters, so it CANNOT distinguish a measured row from an attributed one — the constructor NAME asserts a provenance the TYPE does not carry, and no care at the call site can make that claim checkable. This is why a carrier reading 'execution_measured' is not evidence of measurement, and why a status report derived from constructor names overstates the frontier. The DESIGN 5 construction fix is a provenance carrier making an attributed row unrepresentable as measured; the honest-constructor-plus-discipline approach has already been tried here and produced zero adoption in the live roster.\n\nNAMED SUCCESSOR (operator-authored, 2026-08-06) — FrontierEvidenceProvenance = ExecutionMeasured { subject: FrontierSurveySubject, receipt: FrontierProbeReceipt } | KnowledgeAttributed { source: DeclarationRef, dissolution: unbound_dissolution(description: DeclarationRef)} | OracleDerived { oracle: DeclarationRef }. The load-bearing detail is that ExecutionMeasured requires a TYPED SUBJECT AND A TYPED RECEIPT rather than free-form fields, and the row constructor must CONSUME the variant — so a row cannot claim execution-measured provenance without carrying the receipt that proves it. Operator words: a constructor named execution_measured_* that accepts ordinary caller-provided blocker fields is a name-level claim, not evidence. That is exactly the defect above, made unwritable rather than merely documented, and it lands BEFORE the authoritative survey so the survey cannot rewrite the 27 rows through the conflating constructor.\n\nNO roster row is edited by this note — frontier.dag is load-bearing and the successor is a model change, flagged for routing rather than landed here. Dissolve-on: FrontierEvidenceProvenance lands, row provenance becomes structural, and the unused knowledge-attributed constructor deletes with the transition." - -fn frontier_survey_probe_policy_revision_holds(revision: ContentHash) -> Bool { - match compare_content_hash(left: revision, right: frontier_probe_policy_revision()) { - ContentHashEqual => true - _ => false - } -} - -fn frontier_survey_subject_well_formed_holds(subject: FrontierSurveySubject) -> Bool { - scoped_witness_exact_head_text_holds(head: subject.source_commit) - && frontier_survey_executable_sha256_holds(digest: subject.survey_executable) - && frontier_survey_source_roots_digest_holds(digest: subject.source_roots_digest) - && frontier_survey_probe_policy_revision_holds(revision: subject.probe_policy_revision) - && frontier_survey_commit_tree_binding_holds(commit: subject.source_commit, tree: subject.source_tree) -} - -fn frontier_survey_manifest_receipts_nonempty_holds(manifest: FrontierSurveyManifest) -> Bool { - length(xs: manifest.receipts) > 0 -} - -fn frontier_survey_manifest_well_formed_holds(manifest: FrontierSurveyManifest) -> Bool { - frontier_survey_subject_well_formed_holds(subject: manifest.subject) - && frontier_survey_manifest_receipts_nonempty_holds(manifest: manifest) -} - -fn frontier_survey_manifest_blocker_partition_totality_holds(manifest: FrontierSurveyManifest) -> Bool { - frontier_survey_manifest_well_formed_holds(manifest: manifest) - && frontier_probe_survey_blocker_partition_totality_holds( - receipts: manifest.receipts, - module_count: length(xs: manifest.receipts) - ) -} - -fn frontier_survey_manifest_roster_bidirectional_totality_holds( - manifest: FrontierSurveyManifest, - roster_paths: List, - roster_count: Int -) -> Bool { - frontier_survey_manifest_well_formed_holds(manifest: manifest) - && frontier_probe_survey_roster_bidirectional_totality_holds( - survey: manifest.receipts, - roster_paths: roster_paths, - roster_count: roster_count - ) -} - -fn frontier_probe_survey_blocker_partition_totality_holds( - receipts: List, - module_count: Int -) -> Bool { - let ready = count_receipts_with_blocker(xs: receipts, target: SelfEmitReady) - let upstream = count_upstream_semantic_refusal_receipts(xs: receipts) - let emit = count_receipts_with_blocker(xs: receipts, target: EmitSurfaceGap) - let name = count_receipts_with_blocker(xs: receipts, target: NameResolutionGap) - let real = count_receipts_with_blocker(xs: receipts, target: RealizationGap) - let fixture = count_fixture_cemented_receipts(xs: receipts) - let unknown = count_unknown_probe_cause_receipts(xs: receipts) - (ready + upstream + emit + name + real + fixture + unknown) == module_count -} - -fn frontier_probe_survey_module_paths_unique_holds(xs: List) -> Bool { - fold_list( - xs: xs, - empty: true, - cons: fn(ok, receipt) { - ok - && (frontier_probe_receipt_module_path(receipt: receipt) != "") - && (count_receipts_with_module_path( - xs: xs, - target: frontier_probe_receipt_module_path(receipt: receipt) - ) == 1) - } - ) -} - -fn count_receipts_with_module_path( - xs: List, - target: String -) -> Int { - fold_list( - xs: xs, - empty: 0, - cons: fn(count, receipt) { - if frontier_probe_receipt_module_path(receipt: receipt) == target { - count + 1 - } else { - count - } - } - ) -} - -fn frontier_probe_survey_roster_bidirectional_totality_holds( - survey: List, - roster_paths: List, - roster_count: Int -) -> Bool { - (length(xs: survey) == roster_count) - && frontier_probe_survey_module_paths_unique_holds(xs: survey) - && frontier_probe_survey_receipt_paths_match(xs: survey) - && frontier_probe_survey_every_roster_path_has_receipt_holds( - survey: survey, - roster_paths: roster_paths - ) - && frontier_probe_survey_every_receipt_in_roster_holds( - survey: survey, - roster_paths: roster_paths - ) -} - -fn frontier_probe_survey_every_roster_path_has_receipt_holds( - survey: List, - roster_paths: List -) -> Bool { - fold_list( - xs: roster_paths, - empty: true, - cons: fn(ok, path) { - ok && (count_receipts_with_module_path(xs: survey, target: path) == 1) - } - ) -} - -fn frontier_probe_survey_every_receipt_in_roster_holds( - survey: List, - roster_paths: List -) -> Bool { - fold_list( - xs: survey, - empty: true, - cons: fn(ok, receipt) { - ok && roster_contains_module_path( - paths: roster_paths, - target: frontier_probe_receipt_module_path(receipt: receipt) - ) - } - ) -} - -fn roster_contains_module_path(paths: List, target: String) -> Bool { - fold_list( - xs: paths, - empty: false, - cons: fn(found, path) { - found || (path == target) - } - ) -} - -fn frontier_probe_survey_receipt_paths_match( - xs: List -) -> Bool { - fold_list( - xs: xs, - empty: true, - cons: fn(ok, receipt) { - ok && (frontier_probe_receipt_module_path(receipt: receipt) != "") - } - ) -} - -data frontier_gap_clustering_derivation_note: String = "The dominant reason is READ OFF the receipts, never supplied by the branch that fired. Before this, clustering counted blocker CLASSES and then wrote a hardcoded located_reason literal per branch (^parse_grammar_choice_overlap_residue for the realization branch, and so on), so a verdict reported a reason no receipt had to carry: two modules whose measured refusals differ were indistinguishable, and the one measured survey to date carries ^tokenize_lex_e1_unrecognized_char, which no branch could ever name. count_receipts_with_located_reason existed with zero callers throughout. CommonRoot now requires UNANIMITY rather than a plurality: any plurality bar is a threshold, and a threshold is the smuggled heuristic a closed system never needs — a survey where one reason covers every receipt has a common root, and one where it does not is heterogeneous with its true distinct count. An empty survey has no measured reason, so it cannot be a CommonRoot; it reports a distinct count of zero, which says exactly that. Cost: distinct reasons are collected in one pass and counted once each, so the fold is d*n over the distinct set rather than n*n over the receipts. The tally runs only on the unanimous arm, where its result is consumed; the heterogeneous arm needs the distinct count alone and computing a tally it discards would be a cost-shape defect regardless of how small the survey is (review 51421)." - -type FrontierReasonTally = ReasonTally { reason: Symbol, count: Int } - -fn symbol_list_contains(xs: List, target: Symbol) -> Bool { - fold_list( - xs: xs, - empty: false, - cons: fn(found, s) { found || (s == target) } - ) -} - -fn distinct_located_reasons(xs: List) -> List { - fold_list( - xs: xs, - empty: Empty, - cons: fn(seen, receipt) { - let reason = frontier_probe_receipt_located_reason(receipt: receipt) - if symbol_list_contains(xs: seen, target: reason) { - seen - } else { - Cons { head: reason, tail: seen } - } - } - ) -} - -fn dominant_located_reason_tally(xs: List) -> FrontierReasonTally { - fold_list( - xs: distinct_located_reasons(xs: xs), - empty: ReasonTally { reason: ^frontier_survey_no_measured_reason, count: 0 }, - cons: fn(best, reason) { - let c = count_receipts_with_located_reason(xs: xs, target: reason) - if c > best.count { - ReasonTally { reason: reason, count: c } - } else { - best - } - } - ) -} - -fn common_root_from_tally(top: FrontierReasonTally, module_count: Int) -> FrontierGapClusterVerdict { - CommonRoot { - dominant_located_reason: top.reason, - dominant_module_count: top.count, - module_count: module_count - } -} - -fn frontier_gap_clustering_from_receipts( - xs: List, - module_count: Int -) -> FrontierGapClusterVerdict { - let distinct_count = length(xs: distinct_located_reasons(xs: xs)) - if distinct_count == 1 { - common_root_from_tally( - top: dominant_located_reason_tally(xs: xs), - module_count: module_count - ) - } else { - HeterogeneousGaps { - distinct_located_reason_count: distinct_count, - module_count: module_count - } - } -} - -fn frontier_wave2_realization_module_count(receipts: List) -> Int { - count_receipts_with_blocker(xs: receipts, target: RealizationGap) -} - -fn frontier_wave2_emit_surface_module_count(receipts: List) -> Int { - count_receipts_with_blocker(xs: receipts, target: EmitSurfaceGap) -} - -fn frontier_wave2_name_resolution_module_count(receipts: List) -> Int { - count_receipts_with_blocker(xs: receipts, target: NameResolutionGap) -} - -fn frontier_wave2_upstream_semantic_module_count(receipts: List) -> Int { - count_upstream_semantic_refusal_receipts(xs: receipts) -} - -fn frontier_wave2_self_emit_ready_module_count(receipts: List) -> Int { - count_receipts_with_blocker(xs: receipts, target: SelfEmitReady) -} - -data frontier_probe_survey_dissolution_note: String = "Per-module receipts bind via host_frontier_probe_survey manifest generated by frontier_probe_survey bin; roster rows migrate from knowledge_attributed to execution_measured_seed_retained_row_from_probe_receipt when survey witness compiler_frontier_per_module_probe_survey_holds is green." - -data frontier_probe_survey_blocker_variant_emit_rust_gate_note: String = "HAND-RUST GATE receipt (review 46941 / v1.00_core compiler_diagnostic_seed_projection_note class): Lane E adds `UpstreamSemanticRefusal` to `FrontierBlockerClass`, which forces one new arm in `frontier_probe_survey.rs` `blocker_variant_emit` (+12 LOC mechanical coproduct exhaustiveness for manifest serialization). This arm deletes when the bin deletes on `^migrate_when_frontier_per_module_probe_receipt_binds`; no separate dissolution schedule." - -data frontier_probe_survey_transport_scaffold_note: String = "SCAFFOLD (§7 seed-retained HAND-RUST, P5 gate): `frontier_probe_survey` seed bin is the host-effect loop that runs `frontier_probe_emit_from_ingest` per `compiler_frontier_sweep_order` entry (single authority on `frontier.dag`, not a parallel Rust roster). CHECKABLE RECEIPT — census before=27 knowledge-attributed roster rows (`compiler_frontier_roster_count` on `frontier.dag`); census after shrink=0 hand-Rust LOC when all 27 rows bind execution-measured `FrontierProbeReceipt` via `host_frontier_probe_survey_manifest` (witness `compiler_frontier_per_module_probe_survey_holds` on `v2.test.long.compiler_frontier_per_module_probe`). Bin footprint: origin/main@821 LOC → 1088 LOC on this PR (+267 LOC: `assemble_detail_emit` / `assemble_rejection_cause_emit`, `overlap_roster_detail_from_assemble_detail`, `rejection_chain_from_assemble_detail`, `non_empty_grammar_rows_emit` / `grammar_choice_ambiguity_row_emit`, dual `detail` + `assemble_detail` manifest emission and TSV columns — measured `wc -l` on `src/v1/stage0/src/bin/frontier_probe_survey.rs` at merge-base vs HEAD). Prior main history was 546→821 (+275) before this Lane 2 increment. The +12 `UpstreamSemanticRefusal` serialize arm is an earlier Lane E slice already on main (see `frontier_probe_survey_blocker_variant_emit_rust_gate_note`). CONCRETE DEFERRAL ROW — `gunbc.plans.wave2_prep_design` §2.3 census ratchet discipline + `gunbc.plans.v2_self_hosting` LANDED mechanism (#6464); dissolution trigger `^migrate_when_frontier_per_module_probe_receipt_binds` on `compiler_frontier_blocker_class_distribution_attribution`. Then delete this bin and fold transport into floor-enrolled `v2.workflow.frontier_probe_survey_transport` or a self-emitted survey kernel." - -data frontier_probe_survey_dissolve_on: DissolutionCondition = unbound_dissolution(description: "every roster row migrates from knowledge_attributed to execution_measured_seed_retained_row_from_probe_receipt, i.e. the survey witness executes for each module and the host_frontier_probe_survey manifest binds every per-module receipt") diff --git a/src/v2/compiler/self_host/seed_emitter_behavioral_wet_module_bindings.dag b/src/v2/compiler/self_host/seed_emitter_behavioral_wet_module_bindings.dag index d9d99a029b8..70abbbcda07 100644 --- a/src/v2/compiler/self_host/seed_emitter_behavioral_wet_module_bindings.dag +++ b/src/v2/compiler/self_host/seed_emitter_behavioral_wet_module_bindings.dag @@ -11,7 +11,7 @@ import v2.std.optional { } import v2.std.text { String } -data seed_emitter_behavioral_wet_module_bindings_note: String = "Cycle-free leaf for restored SelfHostWetReceiptBinding rows (review 44453/44455/44460/44468): shared by wet_receipt_enrollment for nightly green wet roster enrollment only. Authorization does NOT derive from this list — producer_emission_canonical_receipt_for_executed_verdict is unwritable at baseline until witness-realization + frontier_probe_survey." +data seed_emitter_behavioral_wet_module_bindings_note: String = "Cycle-free leaf for restored SelfHostWetReceiptBinding rows (review 44453/44455/44460/44468): shared by wet_receipt_enrollment for nightly green wet roster enrollment only. Authorization does NOT derive from this list — producer_emission_canonical_receipt_for_executed_verdict is unwritable at baseline until witness-realization lands. (This condition used to name frontier_probe_survey as a second requirement; that probe and the self-host frontier roster it surveyed are deleted, so witness-realization is now the whole trigger rather than half of it.)" type SelfHostWetReceiptBinding { module_path: String @@ -19,7 +19,7 @@ type SelfHostWetReceiptBinding { function: String } -data falsifier_self_host_wet_module_bindings_revocation_note: String = "2026-07-25: the six SelfEmitted wet bindings were RED on cadence run 30126573464. Dissolve-on (reviews 44441/44453/44455/44460/44468): local wet receipt greens → restore SelfHostWetReceiptBinding here for nightly re-enrollment → witness-realization enables producer_emission_canonical_receipt_for_executed_verdict with execution-measured verdict digests. Frontier rows stay SeedRetained until that path is host-wired." +data falsifier_self_host_wet_module_bindings_revocation_note: String = "2026-07-25: the six SelfEmitted wet bindings were RED on cadence run 30126573464. Dissolve-on (reviews 44441/44453/44455/44460/44468): local wet receipt greens → restore SelfHostWetReceiptBinding here for nightly re-enrollment → witness-realization enables producer_emission_canonical_receipt_for_executed_verdict with execution-measured verdict digests. The frontier rows this clause used to gate on are gone with the self-host frontier roster; what remains gating is the binding itself, which stays absent until that path is host-wired." data falsifier_self_host_wet_module_bindings: List = [] diff --git a/src/v2/compiler/self_host/stage0_crate_layout.dag b/src/v2/compiler/self_host/stage0_crate_layout.dag new file mode 100644 index 00000000000..4dea8e112d0 --- /dev/null +++ b/src/v2/compiler/self_host/stage0_crate_layout.dag @@ -0,0 +1,215 @@ +module v2.compiler.self_host.stage0_crate_layout + +import v2.lens.common.construction_justification { ConstructionJustification, WallAfterGrounding } +import std.disposition { RealizationDispatch } +import v2.std.collection { List } +import v2.std.logic { Bool } +import v2.std.text { String } + +// The stage0 crate's module layout, authored as registration rows. +// +// This module was carved out of v2.compiler.self_host.frontier when the +// 27-row self-host frontier roster was deleted (see +// stage0_crate_layout_carve_out_note). Crate layout is a separate concept +// from self-host progress; it lived in the frontier module only because the +// roster was once expected to contribute basenames to it, and by the time of +// the deletion it contributed none. + +data stage0_crate_layout_carve_out_note: String = "CARVED OUT of v2.compiler.self_host.frontier at that module's deletion, and the carve-out is smaller than the old wiring because the roster term was provably empty. hand_maintained_pub_mod_basenames formerly appended compiler_frontier_emitter_produced_stage0_mod_basenames(), a fold over the roster admitting only EmitterProduced rows. All 27 roster rows were SeedRetained, so that fold returned the empty list at every call — the roster contributed nothing to crate layout on the day it was deleted, and dropping the term changes no emitted byte. The same argument retires hand_maintained_stage0_filenames' roster term and compiler_frontier_crate_layout_holds, whose one non-trivial conjunct counted EmitterProduced basenames against a baseline of zero. What survives here is what actually produced bytes: the intrinsic, scaffold and support-dir registration rows and their pub-mod / filename / dir projections." + +type SeedRetainedIntrinsicRegistration { + basename: String + has_pub_mod: Bool + is_dir: Bool +} + +type SeedRetainedScaffoldRegistration { + basename: String +} + +type SeedRetainedSupportDirRegistration { + basename: String +} + +data seed_retained_intrinsic_registrations: List = [ + SeedRetainedIntrinsicRegistration { basename: "v1_interpreter", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "bounded_shell_host_drain", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "ci_control_plane", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "cli_run", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "coproduct_reflection", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "data_initializer_identity", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "resolved_graph_cache", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "shared_typecheck_store", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "recorded_fixture", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "main", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "phase_profile", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "pre_push", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "census_exclude_derive", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "derived_realization_schedule", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "memory_governor", has_pub_mod: true, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "std_lens_verdict", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "module_path_index", has_pub_mod: true, is_dir: true }, + SeedRetainedIntrinsicRegistration { basename: "v2_compiler_body_producer", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "v2_compiler_normalize", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "v2_compiler_target_carriers", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "v2_compiler_discovery_enumeration", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "v2_compiler_parse_engine_hooks", has_pub_mod: false, is_dir: false }, + SeedRetainedIntrinsicRegistration { basename: "v2_compiler_use_site_verdict", has_pub_mod: false, is_dir: false } +] + +data data_initializer_identity_seed_retained_note: String = "SeedRetained hand-Rust for resolved data-initializer projection marshaling (decl_facts initializer identity lane, PR #7924). Reason: marshal requires InterpContext typechecked subjects, inferred Node stamps, and owning type-item lookup not yet modeled in .dag. Migration trigger: v2.std.data_initializer_identity projection carriers self-emit and coproduct_reflection routes through the modeled marshal surface; then this module deletes with its SeedRetainedIntrinsicRegistration row. Frontier row schema lacks reason/trigger fields — this note is the counted scaffold until the schema lands." + +data seed_retained_support_dir_registrations: List = [ + SeedRetainedSupportDirRegistration { basename: "cli_run" } +] + +data seed_retained_quarantine_scaffold_stage0_files_note: String = "Review 44472: six quarantine modules (SeedRetained, emitter_produced_baseline=0) retain emitted .rs on disk for wet re-flip without pub mod — listed in HAND_MAINTAINED_STAGE0_FILES (has_pub_mod: false) so crate layout authority matches filesystem. Dissolve-on: witness-realization enables EmitterProduced and rows return to generated pub mod roster." +data seed_retained_scaffold_registrations: List = [ + SeedRetainedScaffoldRegistration { basename: "usv_pilot_v2_std_algebra" }, + SeedRetainedScaffoldRegistration { basename: "usv_pilot_v2_std_collection" }, + SeedRetainedScaffoldRegistration { basename: "usv_pilot_v2_std_node" }, + SeedRetainedScaffoldRegistration { basename: "v2_compiler_resolve" }, + SeedRetainedScaffoldRegistration { basename: "v2_compiler_program_partition" }, + SeedRetainedScaffoldRegistration { basename: "v2_compiler_tokenize" }, + SeedRetainedScaffoldRegistration { basename: "v2_compiler_infer" }, + SeedRetainedScaffoldRegistration { basename: "v1_interpreter_dispatch_generated" } +] + +fn intrinsic_pub_mod_basename_from_row(row: SeedRetainedIntrinsicRegistration) -> List { + if row.has_pub_mod { + [row.basename] + } else { + [] + } +} + +fn intrinsic_stage0_filename_from_row(row: SeedRetainedIntrinsicRegistration) -> List { + if row.is_dir { + [] + } else { + [concat(row.basename, ".rs")] + } +} + +fn intrinsic_stage0_dir_from_row(row: SeedRetainedIntrinsicRegistration) -> List { + if row.is_dir { + [row.basename] + } else { + [] + } +} + +fn seed_retained_intrinsic_pub_mod_basenames() -> List { + fold( + seed_retained_intrinsic_registrations, + init: [], + f: fn(acc, row) { + concat(acc, intrinsic_pub_mod_basename_from_row(row: row)) + } + ) +} + +fn seed_retained_intrinsic_stage0_files() -> List { + fold( + seed_retained_intrinsic_registrations, + init: [], + f: fn(acc, row) { + concat(acc, intrinsic_stage0_filename_from_row(row: row)) + } + ) +} + +fn seed_retained_scaffold_pub_mod_basenames() -> List { + fold( + seed_retained_scaffold_registrations, + init: [], + f: fn(acc, row) { + concat(acc, [row.basename]) + } + ) +} + +fn seed_retained_scaffold_stage0_files() -> List { + fold( + seed_retained_scaffold_registrations, + init: [], + f: fn(acc, row) { + concat(acc, [concat(row.basename, ".rs")]) + } + ) +} + +fn seed_retained_support_stage0_dirs() -> List { + fold( + seed_retained_support_dir_registrations, + init: [], + f: fn(acc, row) { + concat(acc, [row.basename]) + } + ) +} + +fn hand_maintained_stage0_dirs() -> List { + concat( + fold( + seed_retained_intrinsic_registrations, + init: [], + f: fn(acc, row) { + concat(acc, intrinsic_stage0_dir_from_row(row: row)) + } + ), + seed_retained_support_stage0_dirs() + ) +} + +fn basename_to_pub_mod_decl(basename: String) -> String { + concat("pub mod ", basename, ";") +} + +fn dispatch_generated_macro_use_pub_mod_decl() -> String { + "#[macro_use]\npub mod v1_interpreter_dispatch_generated;" +} + +fn pub_mod_decl_lines_for_basename(basename: String) -> List { + if basename == "v1_interpreter" { + [ + dispatch_generated_macro_use_pub_mod_decl(), + basename_to_pub_mod_decl(basename: basename), + ] + } else if basename == "v1_interpreter_dispatch_generated" { + [] + } else { + [basename_to_pub_mod_decl(basename: basename)] + } +} + +fn format_pub_mod_declarations(basenames: List) -> String { + let lines = basenames |> flat_map(basename => pub_mod_decl_lines_for_basename(basename: basename)) + concat("\n", lines |> join(separator: "\n")) +} + +fn basename_to_stage0_filename(basename: String) -> String { + concat(basename, ".rs") +} + +fn basenames_to_stage0_filenames(basenames: List) -> List { + basenames |> map(basename_to_stage0_filename) +} + +data stage0_crate_layout_arity_note: String = "These three keep their zero-arity shape deliberately. Their caller is generated_artifact_emit.dag's ~18-variant dispatch, one match whose every arm is a zero-arg generator returning String; giving them a parameter would force seventeen unrelated generators to accept an argument they cannot use. Changing their arity broke this lane once: dag/gunbc and dag/test/claim callers compile CLEAN at a stale arity because .dag does not arity-check these cross-module sites, so the breakage surfaces only at run time." + +fn hand_maintained_pub_mod_basenames() -> List { + concat(seed_retained_intrinsic_pub_mod_basenames(), seed_retained_scaffold_pub_mod_basenames()) +} + +fn emit_hand_maintained_pub_mod_block() -> String { + format_pub_mod_declarations(basenames: hand_maintained_pub_mod_basenames()) +} + +fn hand_maintained_stage0_filenames() -> List { + concat(seed_retained_intrinsic_stage0_files(), seed_retained_scaffold_stage0_files()) +} + +data construction_justification: ConstructionJustification = ConstructionJustification { + class: WallAfterGrounding { dissolves_to: RealizationDispatch } +} diff --git a/src/v2/compiler/self_host/wet_receipt_enrollment.dag b/src/v2/compiler/self_host/wet_receipt_enrollment.dag index de67b2665b6..c7ac81f009d 100644 --- a/src/v2/compiler/self_host/wet_receipt_enrollment.dag +++ b/src/v2/compiler/self_host/wet_receipt_enrollment.dag @@ -8,10 +8,6 @@ import v2.compiler.self_host.seed_emitter_behavioral_wet_module_bindings { SelfHostWetReceiptBinding, find_wet_receipt_binding } -import v2.compiler.self_host.frontier { - CompilerModuleFrontierRow, - compiler_frontier_roster -} import v2.std.algebra { length } import v2.std.collection { List @@ -182,31 +178,10 @@ fn schedule_entry_from_binding(b: SelfHostWetReceiptBinding) -> ScheduleWitnessE self_host_wet_entry(entry: b.entry, f: b.function) } -fn frontier_row_wet_entries_if_enrolled(row: CompilerModuleFrontierRow) -> List { - match find_wet_receipt_binding(module_path: row.module_path) { - Present { value: b } => [schedule_entry_from_binding(b: b)] - Absent => [] - } -} +data wet_enrollment_roster_term_deleted_note: String = "The frontier-enrolled term is gone with the self-host frontier roster, and it was already empty. falsifier_self_host_wet_entries formerly appended a fold over the roster that admitted a row only when find_wet_receipt_binding matched its module_path; no row matched, which is precisely what falsifier_self_host_wet_template_only_holds asserted by requiring that term to have length zero. So the wet falsifier lane ran on template entries alone before the deletion and runs on template entries alone after it, with no entry added, removed or reordered. -fn falsifier_self_host_wet_frontier_enrolled_entries() -> List { - fold( - compiler_frontier_roster, - init: [], - f: fn(acc, row) { - concat(acc, frontier_row_wet_entries_if_enrolled(row: row)) - } - ) -} +That gate is retired rather than weakened: it claimed the roster enrolls nothing, and there is no roster left to enroll anything. What survives is the binding lookup itself (find_wet_receipt_binding, schedule_entry_from_binding), which is keyed on a module path and needs no roster to be asked." fn falsifier_self_host_wet_entries() -> List { - concat( - falsifier_self_host_wet_template_entries, - falsifier_self_host_wet_frontier_enrolled_entries() - ) -} - -fn falsifier_self_host_wet_template_only_holds() -> Bool { - length(xs: falsifier_self_host_wet_frontier_enrolled_entries()) == 0 - && length(xs: falsifier_self_host_wet_entries()) == length(xs: falsifier_self_host_wet_template_entries) + falsifier_self_host_wet_template_entries } diff --git a/src/v2/compiler/self_host/witness_bulk_routing.dag b/src/v2/compiler/self_host/witness_bulk_routing.dag index f2771cbf2f6..40da752b349 100644 --- a/src/v2/compiler/self_host/witness_bulk_routing.dag +++ b/src/v2/compiler/self_host/witness_bulk_routing.dag @@ -101,13 +101,6 @@ data witness_bulk_routing_sample_roster: List = [ dissolution: unbound_dissolution(description: "native_routing_frontier flips the owning family to NativeRouted with a warm per-PR agreement receipt; entry-grain row then derives NativeRouted from family membership") } }, - WitnessEntryRoutingRow { - entry: "src/v2/test/claim/self_host/compiler_frontier_census_test.dag", - disposition: InterpretedRetained { - reason: BulkFlipPendingCensusIncomplete, - dissolution: unbound_dissolution(description: "744-entry srvN sweep receipt names this entry's measured first-error class; row flips to NativeRouted or EmitIneligible in the bulk flip PR (ROADMAP 2a section 3), never before the in-PR agreement receipt") - } - }, WitnessEntryRoutingRow { entry: "src/v2/test/claim/witness_admission_test.dag", disposition: InterpretedRetained { diff --git a/src/v2/compiler/source_authority.dag b/src/v2/compiler/source_authority.dag index 85c441d56c4..56a229acae5 100644 --- a/src/v2/compiler/source_authority.dag +++ b/src/v2/compiler/source_authority.dag @@ -677,7 +677,7 @@ fn source_root_ingest_from_source_refs(refs: List) -> Outcome Diagno } } + +fn wrap_decision_position_disagreement_diagnostic(source_carrier: Node) -> Diagnostic { + Diagnostic { + reason: ^wrap_decision_position_disagreement, + at: node_locus(node: source_carrier), + correction: Unavailable { reason: ExternalContractUnknown } + } +} + +fn wrap_decision_gates_agree( + producer: WrapDecisionGate, + consumer: WrapDecisionGate +) -> Bool { + match producer { + WrapGateInapplicable => + match consumer { + WrapGateInapplicable => true + WrapGateDecided { decision: _ } => false + } + WrapGateDecided { decision: p } => + match consumer { + WrapGateInapplicable => false + WrapGateDecided { decision: c } => wrap_decisions_equal(a: p, c: c) + } + } +} + +fn wrap_decisions_equal(a: WrapDecision, c: WrapDecision) -> Bool { + match a { + WrapByValue => + match c { + WrapByValue => true + WrapByReference { layer: _ } => false + } + WrapByReference { layer: al } => + match c { + WrapByValue => false + WrapByReference { layer: cl } => al == cl + } + } +} + +// R1's construction half. wrap_decision_gate answers ONE position at a time, and every consumer of +// it — here and in v1's seed emitter — then acts on that answer alone. A value does not live at +// one position: it is produced at one and consumed at another, and when the two answers differ the +// emitted program carries a type error that no compiler stage located, because no stage ever +// compared them. Measured on the emitted corpus that defect is ten types and fourteen occurrences, +// every one wrapped at every signature occurrence and bare at one or more field occurrences, and +// it produces BOTH error directions from one inconsistency: a producer's Rc assigned into a +// bare consumer is the over-wrap, a bare producer read into an Rc consumer is the under-wrap. +// So the flow, not the position, is the unit that has to be decided. wrap_decision_flow_gate is +// that unit: it projects the SAME authority at both ends — one function over one catalog, so no +// second OPINION exists to drift — and refuses, typed and located, when that one authority's +// answers for the two positions differ. Stated precisely because the loose form is an overclaim +// worth not making: this is two traversals of one catalog, not one traversal, and what it rules +// out is a divergent authority rather than a repeated read. The repeated read is a real cost shape +// — two folds over the row list where a per-carrier policy built once would serve both ends — and +// it is named here rather than dismissed as small, per DESIGN section 6's rule that a proven cost +// shape is fixed regardless of the realized n. It is not fixed in this change because the policy +// carrier is the same carrier change the next rung needs, and building half of it here to save one +// fold would fork the thing the transition work has to own; the trigger is that carrier landing. +// RUNG (DESIGN 4b), stated honestly because the distance to the ceiling is the point: this moves +// the class from silent wrongness (outside the ladder — emitted, compiled, wrong, discovered only +// if rustc happens to catch it downstream) to MITIGATABLE — the line stops with a located refusal +// naming the carrier. It does NOT reach structural impossibility and must not be read as doing so: +// the invalid state is still writable, because a catalog may still legitimately state different +// layers at two positions and this function's only answer to that is to refuse the flow. The next +// rung is a modeled layer TRANSITION — the value expression carrying its current layer, and a +// total raise/lower/refuse function over (from, to) — at which point an agreeing flow is derived +// rather than checked and this refusal narrows to the genuinely unconvertible pairs. That is +// deliberately not built here: it needs TargetValueExpression to carry its layer, which is a +// carrier change, and DESIGN's model-before-implement discipline puts that ahead of the pipeline +// edit rather than inside it. NOT WIRED INTO 06_translate BY THIS CHANGE: the seams that would +// consume it are the ones the ruling scoped, and wiring them is a separate motion with its own +// emitted-corpus evidence. What lands here is the authority and its executing controls in both +// directions. +fn wrap_decision_flow_gate( + target: TargetModel, + source_carrier: Node, + producer_site: TargetOwnershipUseSite, + consumer_site: TargetOwnershipUseSite +) -> Outcome { + bind_outcome( + o: wrap_decision_gate( + target: target, + source_carrier: source_carrier, + use_site: producer_site + ), + f: fn(producer_gate) { + bind_outcome( + o: wrap_decision_gate( + target: target, + source_carrier: source_carrier, + use_site: consumer_site + ), + f: fn(consumer_gate) { + if wrap_decision_gates_agree( + producer: producer_gate, + consumer: consumer_gate + ) { + outcome_accepted(producer_gate) + } else { + outcome_rejected( + wrap_decision_position_disagreement_diagnostic( + source_carrier: source_carrier + ) + ) + } + } + ) + } + ) +} + fn wrap_decision_sg_rc_bundle_apply_disposition( target: TargetModel, source_carrier: Node diff --git a/src/v2/test/claim/ci_spec_witness_test.dag b/src/v2/test/claim/ci_spec_witness_test.dag index 70fc76ea0bc..da5a480d8d4 100644 --- a/src/v2/test/claim/ci_spec_witness_test.dag +++ b/src/v2/test/claim/ci_spec_witness_test.dag @@ -231,7 +231,6 @@ test fn witness_floor_build_verify_script_matches_pack() -> Bool { artifact_paths: map(ci_floor_required_artifact_names(), name => artifact_shell_path(name: name)) ) && string_contains(s: script, pattern: "cssl_assemble") - && string_contains(s: script, pattern: "frontier_probe_survey") } test fn witness_scheduler_uses_release_binary() -> Bool { diff --git a/src/v2/test/claim/long/compiler_frontier_measured_roster_test.dag b/src/v2/test/claim/long/compiler_frontier_measured_roster_test.dag deleted file mode 100644 index db5becf456f..00000000000 --- a/src/v2/test/claim/long/compiler_frontier_measured_roster_test.dag +++ /dev/null @@ -1,56 +0,0 @@ -module v2.test.long.compiler_frontier_measured_roster - -import v2.compiler.self_host.frontier { - compiler_frontier_census_holds, - compiler_frontier_roster, - compiler_frontier_roster_all_classified_holds, - compiler_frontier_roster_count, - compiler_frontier_roster_probe_paths_match_holds, - compiler_frontier_row_00_compile, - compiler_frontier_row_01_tokenize, - compiler_frontier_row_parse_engine_hooks, - compiler_frontier_sweep_order, - compiler_frontier_sweep_order_matches_tractability_rank_holds -} -import v2.compiler.self_host.frontier_probe_types { - EmitSurfaceGap, - NameResolutionGap, - SelfEmitReady -} -import v2.std.algebra { length } -import v2.std.logic { Bool } - -test fn compiler_frontier_structural_census_invariants_holds() -> Bool { - compiler_frontier_census_holds() - && compiler_frontier_roster_all_classified_holds() - && compiler_frontier_roster_probe_paths_match_holds() -} - -test fn compiler_frontier_measured_parse_engine_hooks_self_emit_ready_holds() -> Bool { - match compiler_frontier_row_parse_engine_hooks.measured_probe.blocker_class { - SelfEmitReady => true - _ => false - } -} - -test fn compiler_frontier_measured_tokenize_emit_surface_holds() -> Bool { - match compiler_frontier_row_01_tokenize.measured_probe.blocker_class { - EmitSurfaceGap => true - _ => false - } -} - -test fn compiler_frontier_measured_compile_emit_surface_holds() -> Bool { - match compiler_frontier_row_00_compile.measured_probe.blocker_class { - EmitSurfaceGap => true - _ => false - } -} - -test fn compiler_frontier_sweep_order_has_expected_length_holds() -> Bool { - length(xs: compiler_frontier_sweep_order) == compiler_frontier_roster_count() -} - -test fn compiler_frontier_measured_sweep_order_matches_tractability_rank_holds() -> Bool { - compiler_frontier_sweep_order_matches_tractability_rank_holds() -} diff --git a/src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag b/src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag deleted file mode 100644 index 6b3e2870850..00000000000 --- a/src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag +++ /dev/null @@ -1,111 +0,0 @@ -module v2.test.long.compiler_frontier_per_module_probe - -import v2.compiler.self_host.frontier { - compiler_frontier_receipt_totality_wall_holds, - compiler_frontier_roster, - compiler_frontier_roster_all_classified_holds, - compiler_frontier_roster_count, - compiler_frontier_roster_located_reason_not_class_projection_holds, - compiler_frontier_roster_module_paths, - compiler_frontier_row_for_path_matches_probe, - compiler_frontier_roster_matches_survey_holds -} -import v2.compiler.self_host.frontier_probe_survey { - CommonRoot, - HeterogeneousGaps, - frontier_gap_clustering_from_receipts, - frontier_probe_survey_blocker_partition_totality_holds, - frontier_probe_survey_has_unclassified, - frontier_probe_survey_roster_bidirectional_totality_holds, - frontier_survey_manifest_well_formed_holds, - frontier_wave2_name_resolution_module_count, - frontier_wave2_realization_module_count, - frontier_wave2_self_emit_ready_module_count -} -import v2.compiler.self_host.frontier_probe_types { - NameResolutionGap, - RealizationGap, - SelfEmitReady -} -import v2.test.workflow.host_frontier_probe_survey_manifest { - host_frontier_probe_survey_manifest -} -import v2.std.algebra { length } -import v2.std.logic { Bool } -import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } - -data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree - -data compiler_frontier_per_module_probe_note: String = "Fixture-FREE per-module emit-frontier probe over all 27 compiler modules via frontier_probe_survey bin (real ingest, no injected derisk fixtures). Validates roster blocker classes against execution-measured receipts; answers common-root (blocker-class clustering) vs heterogeneous located-reason gaps. TERMINATING one-shot (witness_deferral_freeze TERMINATING specimen): runs once at a pinned head, then row + scaffold delete via dissolve_on — no per-PR cadence. CI ENROLLMENT: NOT in per-PR discovery — witness_discovery_scan_dirs omits src/v2/test/claim/long/; WitnessExclusionRow excludes test/claim/long/ and this file at OfflineLocalRecipe grain; not in falsifier_substrate_long_lane_entries or commit_gate_roster. Per-PR CI never executes these seven functions; green CI does not assert survey coverage. Local recipe RED on stub manifest (receipts Empty) is offline-only until the authoritative survey runs — not a CI failure shape. Local recipe authority: compiler_frontier_per_module_probe_exclusion_note in gunbc.ci_layer_roots." - -data compiler_frontier_wave2_self_emit_ready_zero_note: String = "ready_count == 0 in wave2 sizing witnesses is green-by-construction on this probe slice: frontier_probe_emit_from_ingest never returns SelfEmitReady (emit-accept → UnknownProbeCause{^probe_emit_accept_self_host_bar_unbound}). Not a discriminating SelfEmitReady RED until the fixture-free emit→compile→run→equivalent bar is inhabited; honest deferral per ^probe_emit_accept_self_host_bar_unbound, not fabrication." - -test fn compiler_frontier_per_module_probe_survey_holds() -> Bool { - frontier_survey_manifest_well_formed_holds(manifest: host_frontier_probe_survey_manifest) - && compiler_frontier_roster_matches_survey_holds(survey: host_frontier_probe_survey_manifest.receipts) - && (length(xs: host_frontier_probe_survey_manifest.receipts) == compiler_frontier_roster_count()) - && !frontier_probe_survey_has_unclassified(xs: host_frontier_probe_survey_manifest.receipts) - && compiler_frontier_roster_all_classified_holds() - && compiler_frontier_roster_located_reason_not_class_projection_holds() -} - -data compiler_frontier_gap_clustering_empty_stub_note: String = "This claim requires a NONEMPTY survey before it reads the verdict, and the requirement is the point rather than a guard. Against the checked-in stub (receipts Empty) it previously passed: clustering asked self_emit_ready_count == module_count, both were 0, and it answered CommonRoot with dominant_located_reason ^probe_stage_emit_ok — a survey with no receipts reporting that every module reached emit. That is the vacuous green this lane exists to prevent, and it sat inside the one claim whose subject is the clustering verdict. Receipt-derived clustering now answers HeterogeneousGaps for an empty survey (empty_survey_is_never_a_common_root_holds pins it per-PR), so this claim reds on the stub — the same state its siblings were already in, since compiler_frontier_per_module_probe_survey_holds compares the receipt count against the 27-row roster and 0 is not 27. Red-on-stub is the file's declared offline condition, not a CI failure shape; the length check makes THIS claim's red say so explicitly rather than leaving it to be read as a clustering disagreement." - -test fn compiler_frontier_gap_clustering_common_root_at_blocker_class_holds() -> Bool { - clustering_survey_is_nonempty() && clustering_verdict_is_common_root() -} - -fn clustering_survey_is_nonempty() -> Bool { - length(xs: host_frontier_probe_survey_manifest.receipts) > 0 -} - -fn clustering_verdict_is_common_root() -> Bool { - match frontier_gap_clustering_from_receipts( - xs: host_frontier_probe_survey_manifest.receipts, - module_count: length(xs: host_frontier_probe_survey_manifest.receipts) - ) { - CommonRoot { - dominant_located_reason: _, - dominant_module_count: _, - module_count: _ - } => true - HeterogeneousGaps { - distinct_located_reason_count: _, - module_count: _ - } => false - } -} - -test fn compiler_frontier_wave2_blocker_partition_totality_holds() -> Bool { - frontier_probe_survey_blocker_partition_totality_holds( - receipts: host_frontier_probe_survey_manifest.receipts, - module_count: length(xs: host_frontier_probe_survey_manifest.receipts) - ) -} - -test fn compiler_frontier_roster_bidirectional_totality_live_survey_holds() -> Bool { - frontier_probe_survey_roster_bidirectional_totality_holds( - survey: host_frontier_probe_survey_manifest.receipts, - roster_paths: compiler_frontier_roster_module_paths(), - roster_count: compiler_frontier_roster_count() - ) -} - -test fn compiler_frontier_receipt_totality_wall_live_survey_holds() -> Bool { - compiler_frontier_receipt_totality_wall_holds(survey: host_frontier_probe_survey_manifest.receipts) -} - -data compiler_frontier_wave2_sizing_band_a_leaf_count_note: String = "Closeout band: realization_count >= 20 applies when host_frontier_probe_survey_manifest binds all 27 execution_measurement receipts at one pinned source_head. Prior interim audit at 9f978aa8df (#7697) had execution_measurement=17 (14 RealizationGap + 3 NameResolutionGap at ProbeStageAssemble, self_emit_ready=0); superseded — not combinable with a later head." - -test fn compiler_frontier_wave2_emit_surface_dominates_holds() -> Bool { - let realization_count = frontier_wave2_realization_module_count(receipts: host_frontier_probe_survey_manifest.receipts) - let name_count = frontier_wave2_name_resolution_module_count(receipts: host_frontier_probe_survey_manifest.receipts) - frontier_wave2_self_emit_ready_module_count(receipts: host_frontier_probe_survey_manifest.receipts) == 0 - && realization_count >= name_count -} - -test fn compiler_frontier_wave2_sizing_band_a_leaf_count_holds() -> Bool { - let realization_count = frontier_wave2_realization_module_count(receipts: host_frontier_probe_survey_manifest.receipts) - frontier_wave2_self_emit_ready_module_count(receipts: host_frontier_probe_survey_manifest.receipts) == 0 - && realization_count >= 20 -} diff --git a/src/v2/test/claim/self_host/compiler_frontier_census_test.dag b/src/v2/test/claim/self_host/compiler_frontier_census_test.dag deleted file mode 100644 index bea738dfe8d..00000000000 --- a/src/v2/test/claim/self_host/compiler_frontier_census_test.dag +++ /dev/null @@ -1,72 +0,0 @@ -module v2.test.self_host.compiler_frontier_census - -import v2.compiler.self_host.frontier_band_a_emit_readiness { - FlippableNow, - OtherGate, - compiler_frontier_band_a_row_parse_engine_hooks, - compiler_frontier_band_a_row_use_site_verdict -} -import v2.compiler.self_host.frontier { - compiler_frontier_band_a_emit_readiness_holds, - compiler_frontier_blocker_class_distribution_knowledge_attributed_holds, - compiler_frontier_census_holds, - compiler_frontier_execution_measured_attribution_holds, - compiler_frontier_gap_clustering_knowledge_attributed_holds, - compiler_frontier_known_module_path_exactly_once_holds, - compiler_frontier_phantom_module_path_absent_holds, - compiler_frontier_roster_all_classified_holds, - compiler_frontier_roster_paths_unique_holds, - compiler_frontier_roster_probe_paths_match_holds, - compiler_frontier_emitter_produced_located_reason_holds, - compiler_frontier_emitter_produced_oracle_enrolled_holds, - compiler_frontier_emitter_produced_oracle_backed_holds, - compiler_frontier_sweep_order_complete_holds -} -import v2.std.logic { Bool } -import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } - -data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree - -test fn compiler_frontier_roster_paths_are_unique() -> Bool { - compiler_frontier_roster_paths_unique_holds() -} - -test fn compiler_frontier_duplicate_path_red_refuses() -> Bool { - compiler_frontier_known_module_path_exactly_once_holds() - && compiler_frontier_phantom_module_path_absent_holds() -} - -test fn compiler_frontier_execution_measured_attribution_test() -> Bool { - compiler_frontier_execution_measured_attribution_holds() - && compiler_frontier_blocker_class_distribution_knowledge_attributed_holds() - && compiler_frontier_gap_clustering_knowledge_attributed_holds() - && compiler_frontier_sweep_order_complete_holds() - && compiler_frontier_roster_all_classified_holds() - && compiler_frontier_roster_probe_paths_match_holds() - && compiler_frontier_emitter_produced_located_reason_holds() - && compiler_frontier_emitter_produced_oracle_enrolled_holds() - && compiler_frontier_emitter_produced_oracle_backed_holds() -} - -test fn compiler_frontier_census_composite_test() -> Bool { - compiler_frontier_census_holds() - && compiler_frontier_execution_measured_attribution_holds() -} - -test fn compiler_frontier_band_a_emit_readiness_roster_holds() -> Bool { - compiler_frontier_band_a_emit_readiness_holds() -} - -test fn compiler_frontier_band_a_parse_engine_hooks_flipped_discriminator_holds() -> Bool { - match compiler_frontier_band_a_row_parse_engine_hooks.gate { - FlippableNow => true - _ => false - } -} - -test fn compiler_frontier_band_a_use_site_verdict_flipped_discriminator_holds() -> Bool { - match compiler_frontier_band_a_row_use_site_verdict.gate { - FlippableNow => true - _ => false - } -} diff --git a/src/v2/test/claim/self_host/compiler_frontier_upstream_semantic_probe_test.dag b/src/v2/test/claim/self_host/compiler_frontier_upstream_semantic_probe_test.dag deleted file mode 100644 index 64dd722f7e6..00000000000 --- a/src/v2/test/claim/self_host/compiler_frontier_upstream_semantic_probe_test.dag +++ /dev/null @@ -1,93 +0,0 @@ -module v2.test.self_host.compiler_frontier_upstream_semantic_probe - -import v2.compiler.self_host.frontier { - compiler_frontier_roster_stale_located_reason_count_holds -} -import v2.compiler.self_host.frontier_probe_survey { - frontier_probe_survey_blocker_partition_totality_holds -} -import v2.compiler.self_host.frontier_probe_types { - EmitSurfaceGap, - NameResolutionGap, - ProbeStageAssemble, - ProbeStageEmit, - ProbeStageSemanticDerivation, - UpstreamSemanticRefusal, - UnknownProbeCause, - gate_a_flip_probe_unresolved_compiler_error_reason, - frontier_classify_rejection_reason, - frontier_probe_located_stage_for_assemble_outcome, - frontier_probe_located_stage_for_blocker, - frontier_probe_located_stage_for_emit_outcome, - upstream_semantic_compiler_error_class -} - -data compiler_frontier_upstream_semantic_probe_note: String = "Lane E vocabulary + receipt-totality wall witnesses (still-dove-191): UpstreamSemanticRefusal is NOT EmitSurfaceGap; UNRESOLVED marker classifies to semantic derivation stage. Stale located_reason wall is merge-blocking via compiler_frontier_roster_stale_located_reason_count_holds." - -test fn frontier_classify_unresolved_marker_is_upstream_semantic_holds() -> Bool { - match frontier_classify_rejection_reason( - reason: gate_a_flip_probe_unresolved_compiler_error_reason - ) { - UpstreamSemanticRefusal { - diagnostic_class: diagnostic_class, - diagnostic_name: diagnostic_name - } => - (diagnostic_class == upstream_semantic_compiler_error_class) - && (diagnostic_name == gate_a_flip_probe_unresolved_compiler_error_reason) - _ => false - } -} - -test fn frontier_classify_unresolved_marker_not_emit_surface_red_control() -> Bool { - match frontier_classify_rejection_reason( - reason: gate_a_flip_probe_unresolved_compiler_error_reason - ) { - EmitSurfaceGap => false - NameResolutionGap => false - UnknownProbeCause { reason: _ } => false - _ => true - } -} - -test fn frontier_upstream_semantic_located_stage_is_semantic_derivation_holds() -> Bool { - match frontier_classify_rejection_reason( - reason: gate_a_flip_probe_unresolved_compiler_error_reason - ) { - UpstreamSemanticRefusal { diagnostic_class: _, diagnostic_name: _ } => - frontier_probe_located_stage_for_blocker(blocker: UpstreamSemanticRefusal { - diagnostic_class: upstream_semantic_compiler_error_class, - diagnostic_name: gate_a_flip_probe_unresolved_compiler_error_reason - }) == ProbeStageSemanticDerivation - _ => false - } -} - -test fn compiler_frontier_stale_located_reason_wall_holds() -> Bool { - compiler_frontier_roster_stale_located_reason_count_holds() -} - -test fn compiler_frontier_empty_survey_blocker_partition_totality_holds() -> Bool { - frontier_probe_survey_blocker_partition_totality_holds(receipts: [], module_count: 0) -} - -test fn frontier_emit_accept_unbound_located_stage_is_emit_holds() -> Bool { - frontier_probe_located_stage_for_emit_outcome( - blocker: UnknownProbeCause { reason: ^probe_emit_accept_self_host_bar_unbound } - ) == ProbeStageEmit -} - -test fn frontier_emit_surface_gap_located_stage_is_emit_holds() -> Bool { - frontier_probe_located_stage_for_emit_outcome(blocker: EmitSurfaceGap) == ProbeStageEmit -} - -test fn frontier_assemble_unknown_located_stage_is_assemble_holds() -> Bool { - frontier_probe_located_stage_for_assemble_outcome( - blocker: UnknownProbeCause { reason: ^frontier_probe_runtime_error } - ) == ProbeStageAssemble -} - -test fn frontier_blocker_projection_unknown_still_maps_assemble_red_control() -> Bool { - frontier_probe_located_stage_for_blocker( - blocker: UnknownProbeCause { reason: ^probe_emit_accept_self_host_bar_unbound } - ) == ProbeStageAssemble -} diff --git a/src/v2/test/claim/self_host/crate_layout_witness_test.dag b/src/v2/test/claim/self_host/crate_layout_witness_test.dag index 1407bcb6e45..346bc1466cf 100644 --- a/src/v2/test/claim/self_host/crate_layout_witness_test.dag +++ b/src/v2/test/claim/self_host/crate_layout_witness_test.dag @@ -6,118 +6,56 @@ import gunbc.stage0_crate_layout_generated { generated_stage0_dirs, generated_stage0_filenames } -import v2.compiler.self_host.frontier { - CompilerModuleFrontierRow, - FrontierQualifiedModuleBinding, - EmitterProduced, - SeedRetained, - compiler_frontier_crate_layout_holds, - compiler_frontier_qualified_module_dotted_for_path, - compiler_frontier_qualified_module_bindings, - compiler_frontier_row_parse_engine_hooks, - compiler_frontier_row_discovery_enumeration, - compiler_frontier_row_use_site_verdict, - compiler_frontier_emitter_produced_count, - compiler_frontier_emitter_produced_stage0_mod_basenames_from_index, +import v2.compiler.self_host.stage0_crate_layout { emit_hand_maintained_pub_mod_block, - frontier_row_stage0_mod_basename, hand_maintained_pub_mod_basenames, hand_maintained_stage0_dirs, hand_maintained_stage0_filenames } -import v2.compiler.source_authority { ModuleStorageIndex } -import v2.test.workflow.host_module_binding_manifest { host_module_bindings } -import v2.std.diagnostic { Accepted, Rejected } -import std.algebra { Empty } import v2.std.algebra { any, fold_list, length } import v2.std.collection { List } import v2.std.logic { Bool } import v2.std.text { String } -data witness_red_control_note: String = "Discriminating RED (both directions): (1) OMIT — drop v2_compiler_parse_engine_hooks or v2_compiler_use_site_verdict from generated_pub_mod_basenames while frontier row stays SelfEmitted → witness_generated_includes_every_self_emitted_basename_holds false; (2) INCLUDE — append phantom_module to generated_pub_mod_basenames absent from frontier hand_maintained_pub_mod_basenames → witness_generated_has_no_phantom_registration_holds false. Byte drift RED: generated_artifact_drift_gate perturb suffix on dag/gunbc/stage0_crate_layout_generated.dag." +data witness_red_control_note: String = "Discriminating RED, both directions: (1) OMIT — drop a basename from generated_pub_mod_basenames while its registration row stands, and witness_generated_basenames_match_registrations_holds goes false on the length comparison; (2) INCLUDE — append phantom_module to generated_pub_mod_basenames with no registration row, and witness_generated_has_no_phantom_registration_holds goes false. A third RED sits outside this file: perturb a suffix in dag/gunbc/stage0_crate_layout_generated.dag and the generated-artifact drift gate reds on bytes." -data witness_wet_cadence_note: String = "These witnesses are WET as of task 3: they read host_module_bindings, which the committed stub declares Empty and the module_binding_supply_transport overlays with the real whole-tree index at run time. Run by name in the fast lane they REFUSE (index unavailable), and that refusal is correct rather than a regression — it is the projection reporting that it has no authority to answer from, instead of the previous behaviour of answering from a hand table that could silently disagree with the tree. +data witness_roster_half_deleted_note: String = "SEVEN WITNESSES WERE DELETED FROM THIS FILE with the self-host frontier roster, and none of them could fail. Three asked whether a specific roster row's basename was registered, each guarded by a match on that row's disposition whose EmitterProduced arm was unreachable — every row was SeedRetained, so all three took the other arm and returned true without consulting the layout at all. Three more compared an emitter-produced basename projection against the emitter-produced count; both sides derived from the same empty projection, so each compared zero with zero. The seventh opened with `if compiler_frontier_emitter_produced_count() == 0 { true }` and had therefore never evaluated its body. -The layout conjunct was removed from compiler_frontier_census_holds in the same change for this reason (see frontier_census_layout_relocation_note); this file is where it now lives." +The parity witness transition_parity_host_index_agrees_with_hand_rows is deleted too, and that one WAS load-bearing while it stood: it reds the moment a derived module index and the hand-authored qualified-module bindings disagree. Its subject was the duality between those two authorities, and the deletion removed one side of it — there is no hand-row table left to disagree with the index, so the claim is retired rather than dropped. Same for projection_refuses_on_absent_index, whose subject was that projection's refusal arm. -fn layout_index() -> ModuleStorageIndex { - host_module_bindings -} +What remains is the part that was never about self-host progress: the committed generated artifact must match the registration rows it is generated from, on basenames, filenames, directories and the rendered pub-mod block." fn string_list_contains(xs: List, needle: String) -> Bool { - any(xs, x => x == needle) + xs |> any(x => x == needle) } fn lists_have_same_members(a: List, b: List) -> Bool { - length(xs: a) == length(xs: b) - && fold_list(xs: a, empty: true, cons: fn(ok, item) { ok && string_list_contains(xs: b, needle: item) }) - && fold_list(xs: b, empty: true, cons: fn(ok, item) { ok && string_list_contains(xs: a, needle: item) }) -} - -fn row_basename_is_registered(row: CompilerModuleFrontierRow) -> Bool { - match frontier_row_stage0_mod_basename(index: layout_index(), row: row) { - Accepted { value: b, diagnostics: _ } => - string_list_contains( - xs: compiler_frontier_emitter_produced_stage0_mod_basenames_from_index(index: layout_index()), - needle: b - ) - Rejected { diagnostics: _ } => false - } + (length(xs: a) == length(xs: b)) + && fold_list(xs: a, empty: true, cons: fn(ok, x) { ok && string_list_contains(xs: b, needle: x) }) } -fn witness_parse_engine_hooks_derived_from_frontier_holds() -> Bool { - match compiler_frontier_row_parse_engine_hooks.disposition { - EmitterProduced { authorization_binding: _ } => row_basename_is_registered(row: compiler_frontier_row_parse_engine_hooks) - SeedRetained { reason: _, migration_trigger: _ } => true - } -} - -fn witness_use_site_verdict_derived_from_frontier_holds() -> Bool { - match compiler_frontier_row_use_site_verdict.disposition { - EmitterProduced { authorization_binding: _ } => row_basename_is_registered(row: compiler_frontier_row_use_site_verdict) - SeedRetained { reason: _, migration_trigger: _ } => true - } -} - -fn witness_discovery_enumeration_derived_from_frontier_holds() -> Bool { - match compiler_frontier_row_discovery_enumeration.disposition { - EmitterProduced { authorization_binding: _ } => row_basename_is_registered(row: compiler_frontier_row_discovery_enumeration) - SeedRetained { reason: _, migration_trigger: _ } => true - } -} - -fn witness_generated_pub_mod_block_matches_frontier_holds() -> Bool { +fn witness_generated_pub_mod_block_matches_registrations_holds() -> Bool { generated_pub_mod_block == emit_hand_maintained_pub_mod_block() } -fn witness_generated_basenames_match_frontier_holds() -> Bool { +fn witness_generated_basenames_match_registrations_holds() -> Bool { lists_have_same_members( a: generated_pub_mod_basenames, b: hand_maintained_pub_mod_basenames() ) } -fn witness_generated_filenames_match_frontier_holds() -> Bool { +fn witness_generated_filenames_match_registrations_holds() -> Bool { lists_have_same_members( a: generated_stage0_filenames, b: hand_maintained_stage0_filenames() ) } -fn witness_generated_dirs_match_frontier_holds() -> Bool { +fn witness_generated_dirs_match_registrations_holds() -> Bool { lists_have_same_members(a: generated_stage0_dirs, b: hand_maintained_stage0_dirs()) } -fn witness_generated_includes_every_self_emitted_basename_holds() -> Bool { - fold_list( - xs: compiler_frontier_emitter_produced_stage0_mod_basenames_from_index(index: layout_index()), - empty: true, - cons: fn(ok, basename) { - ok && string_list_contains(xs: generated_pub_mod_basenames, needle: basename) - } - ) -} - fn witness_generated_has_no_phantom_registration_holds() -> Bool { fold_list( xs: generated_pub_mod_basenames, @@ -128,91 +66,10 @@ fn witness_generated_has_no_phantom_registration_holds() -> Bool { ) } -fn witness_hand_maintained_filenames_include_self_emitted_holds() -> Bool { - if compiler_frontier_emitter_produced_count() == 0 { - true - } else { - string_list_contains( - xs: generated_stage0_filenames, - needle: "v2_compiler_parse_engine_hooks.rs" - ) - && string_list_contains( - xs: generated_stage0_filenames, - needle: "v2_compiler_discovery_enumeration.rs" - ) - && string_list_contains( - xs: generated_stage0_filenames, - needle: "v2_compiler_use_site_verdict.rs" - ) - } -} - -fn witness_self_emitted_count_matches_derived_basenames_holds() -> Bool { - length(xs: compiler_frontier_emitter_produced_stage0_mod_basenames_from_index(index: layout_index())) == compiler_frontier_emitter_produced_count() -} - -fn witness_no_orphan_self_emitted_basename_holds() -> Bool { - fold_list( - xs: compiler_frontier_emitter_produced_stage0_mod_basenames_from_index(index: layout_index()), - empty: true, - cons: fn(ok, basename) { - ok && string_list_contains(xs: hand_maintained_pub_mod_basenames(), needle: basename) - } - ) -} - -data standing_parity_witness_note: String = "STANDING WITNESS — not a one-time switchover receipt (promoted, parent ruling 2026-07-19), and the reason for the promotion is the whole point. - -Two representations of the path⇄module fact are live at once: the derived index serves the witness path here, and the 27 hand rows still feed the crate-layout EMITTER, which cannot be handed a host index without polluting an unrelated 18-variant dispatch (frontier_emitter_hand_row_debt_note). §3 forbids that duality in general. THIS WITNESS IS WHAT MAKES IT HONEST: it asserts, on every wet run, that the derived index and the hand rows answer identically for every path the rows name — so a drift between the two authorities REDS instead of silently diverging. - -As a one-time receipt it would have proven agreement at a single moment and said nothing afterwards, leaving exactly the silent fork it was meant to prevent. As a standing check it is the §3 protection for as long as the duality lives. - -It catches two failures with one comparison: a PROJECTION BUG (derivation disagrees with a known-good table) and HAND-ROW DRIFT (the table went stale and the derivation is right). Both surface as the same red, told apart by inspecting which side is wrong. - -dissolve-on: host-driven generation of the crate-layout artifact with the index supplied at the boundary — at which point this witness, FrontierQualifiedModuleBinding, the 27-row block, and the _hand_rows fn family are deleted TOGETHER." - -fn parity_row_agrees(row: FrontierQualifiedModuleBinding) -> Bool { - match compiler_frontier_qualified_module_dotted_for_path(index: layout_index(), target: row.module_path) { - Accepted { value: dotted, diagnostics: _ } => dotted == row.qualified_module - Rejected { diagnostics: _ } => false - } -} - -test fn transition_parity_host_index_agrees_with_hand_rows() -> Bool { - (length(xs: compiler_frontier_qualified_module_bindings) > 0) - && fold_list( - xs: compiler_frontier_qualified_module_bindings, - empty: true, - cons: fn(ok, row) { ok && parity_row_agrees(row: row) } - ) -} - -data index_absent_red_control_note: String = "The RED control for the projection's fail-closed arm, proven by EXECUTION rather than asserted. An Empty index must REFUSE — not return an empty string, and not fabricate a basename from one. This is the control that would have caught the old \"\"-sentinel behaviour: under the previous lookup an Empty carrier produced \"\" for every path, rust_qualified_module_mod_basename turned that into a basename, and a gate could report on names nobody declared. - -It asserts refusal on a LOCALLY CONSTRUCTED Empty index rather than on host_module_bindings, deliberately: the host carrier is Empty in the fast lane and populated on the wet cadence, so asserting against it would pass for the wrong reason in one lane and fail in the other. A literal Empty is the same input in both." - -test fn projection_refuses_on_absent_index() -> Bool { - match compiler_frontier_qualified_module_dotted_for_path( - index: Empty, - target: "src/v2/compiler/00_compile.dag" - ) { - Accepted { value: _, diagnostics: _ } => false - Rejected { diagnostics: _ } => true - } -} - test fn crate_layout_witnesses() -> Bool { - compiler_frontier_crate_layout_holds(index: layout_index()) - && witness_parse_engine_hooks_derived_from_frontier_holds() - && witness_use_site_verdict_derived_from_frontier_holds() - && witness_discovery_enumeration_derived_from_frontier_holds() - && witness_generated_pub_mod_block_matches_frontier_holds() - && witness_generated_basenames_match_frontier_holds() - && witness_generated_filenames_match_frontier_holds() - && witness_generated_dirs_match_frontier_holds() - && witness_generated_includes_every_self_emitted_basename_holds() + witness_generated_pub_mod_block_matches_registrations_holds() + && witness_generated_basenames_match_registrations_holds() + && witness_generated_filenames_match_registrations_holds() + && witness_generated_dirs_match_registrations_holds() && witness_generated_has_no_phantom_registration_holds() - && witness_hand_maintained_filenames_include_self_emitted_holds() - && witness_self_emitted_count_matches_derived_basenames_holds() - && witness_no_orphan_self_emitted_basename_holds() } diff --git a/src/v2/test/claim/self_host/emitter_producer_provenance_witness_test.dag b/src/v2/test/claim/self_host/emitter_producer_provenance_witness_test.dag index 61b2a0b4541..f5466bc470d 100644 --- a/src/v2/test/claim/self_host/emitter_producer_provenance_witness_test.dag +++ b/src/v2/test/claim/self_host/emitter_producer_provenance_witness_test.dag @@ -1,194 +1,23 @@ -module v2.test.claim.self_host.emitter_producer_provenance_witness_test +module v2.test.claim.self_host.emitter_producer_provenance_witness import v2.compiler.self_host.emitter_producer_provenance { - BuildGreen, - BuildRefused, - ProducerEmissionExecutedGreenReceipt, - emitter_produced_baseline, - fabricated_v1_seed_producer_receipt, - fabricated_v2_interpreted_producer_receipt, - hand_forged_emitter_produced_authorization_fails_mint_consistency_holds, - hand_forged_matching_token_unauthorized_still_fails_mint_consistency_holds, - mint_authorized_emitter_produced_disposition_refused_at_baseline_holds, mint_v2_interpreted_receipt_with_seed_closure_refuses, - producer_emission_canonical_receipt_for_executed_verdict, - producer_emission_canonical_receipt_for_oracle_row, - producer_emission_flip_wave_reverted_module_paths, - producer_emission_flip_wave_reverted_modules_lack_oracle_holds, - producer_emission_binding_only_does_not_authorize_holds, - producer_emission_executed_verdict_minting_refused_at_baseline_holds, - producer_emission_oracle_authorization_promotion_path_holds, - producer_emission_oracle_authorization_requires_executed_verdict_holds, - producer_emission_oracle_authorizes_row, - producer_emission_oracle_enrolls_row, - producer_emission_receipt_from_oracle_row, - producer_emission_oracle_row_00_compile_flip_wave_red, - producer_emission_oracle_row_body_producer, - producer_emission_oracle_row_count, - producer_emission_oracle_rows_all_enrolled_holds, - producer_emission_oracle_rows_match_enrollment_holds, - producer_emission_oracle_rows_match_transport_roster_holds, - producer_qualified_baselines_holds, - seed_emitter_behavioral_green_baseline, - seed_emitter_behavioral_green_count, - seed_emitter_behavioral_quarantine_baseline, - seed_emitter_behavioral_quarantine_count, - v2_interpreted_emitter_behavioral_green_count, - v2_native_emitter_behavioral_green_count, - v2_emitter_production_routed_count -} -import v2.compiler.self_host.frontier { - compiler_frontier_census_holds, - compiler_frontier_emitter_produced_oracle_backed_holds, - compiler_frontier_emitter_produced_authorization_mint_consistent_holds, - compiler_frontier_emitter_produced_oracle_enrolled_holds, - compiler_frontier_emitter_produced_oracle_count_matches_baseline_holds, - compiler_frontier_emitter_produced_count, - compiler_frontier_producer_qualified_baselines_holds, - compiler_frontier_quarantine_oracle_modules_seed_retained_holds, - emitter_produced_unauthorized_disposition_unrepresentable_holds + v2_interpreted_emitter_closure_seed_free_holds } import v2.compiler.self_host.seed_emitter_behavioral_wet_known_red_entries { - schedule_witness_entry_cited, schedule_witness_entries_structurally_equal, seed_emitter_behavioral_wet_known_red_entries } import v2.compiler.self_host.wet_receipt_enrollment { falsifier_self_host_wet_known_red_entries } -import v2.std.algebra { fold_list } -import v2.std.optional { Absent, Present } import v2.std.logic { Bool } -import v2.std.text { String } -import std.content_hash { content_hash_atom } - -data emitter_producer_provenance_witness_note: String = "Producer/qualification construction wall witnesses (session valiant-crab-382): oracle enrollment binds minted BuildRefused quarantine receipts; frontier authorization routes ONLY through producer_emission_canonical_receipt_for_executed_verdict (review 44480). Static oracle derivation never mints BuildGreen. PRIMARY RED: V2EmitterInterpreted unwritable when v1.compiler.emit_rust is in closure. SECONDARY RED: flip-wave dishonest claim replay." - -fn witness_fabricated_executed_verdict( - module_path: String, - behavioral_probe_entry: String, - behavioral_probe_function: String -) -> ProducerEmissionExecutedGreenReceipt { - ProducerEmissionExecutedGreenReceipt { - module_path: module_path, - behavioral_probe_entry: behavioral_probe_entry, - behavioral_probe_function: behavioral_probe_function, - wet_execution_digest: content_hash_atom(value: behavioral_probe_entry) - } -} - -test fn witness_oracle_rows_all_enrolled_holds() -> Bool { - producer_emission_oracle_rows_all_enrolled_holds() -} - -test fn witness_live_roster_emitter_produced_oracle_enrolled_holds() -> Bool { - compiler_frontier_emitter_produced_oracle_enrolled_holds() -} - -test fn witness_live_roster_emitter_produced_oracle_backed_holds() -> Bool { - compiler_frontier_emitter_produced_oracle_backed_holds() -} - -test fn witness_oracle_authorization_promotion_path_holds() -> Bool { - producer_emission_oracle_authorization_promotion_path_holds() - && producer_emission_binding_only_does_not_authorize_holds() - && producer_emission_oracle_authorization_requires_executed_verdict_holds() - && mint_authorized_emitter_produced_disposition_refused_at_baseline_holds() - && hand_forged_emitter_produced_authorization_fails_mint_consistency_holds() - && hand_forged_matching_token_unauthorized_still_fails_mint_consistency_holds() -} - -data witness_hand_forged_emitter_produced_authorization_red_note: String = "Review 44487 RED: hand-constructed AuthorizedEmitterProducedDisposition (wrong or derivable-matching token) must fail authorized_emitter_produced_disposition_mint_consistent — derivation+authorize, not record opacity." - -test fn witness_hand_forged_emitter_produced_authorization_fails_mint_consistency_reds() -> Bool { - hand_forged_emitter_produced_authorization_fails_mint_consistency_holds() - && hand_forged_matching_token_unauthorized_still_fails_mint_consistency_holds() -} - -data witness_emitter_produced_unauthorized_disposition_red_note: String = "Review 44570 RED: EmitterProduced disposition requires authorization_binding in the variant — roster rows must be mint-consistent; promotions empty at baseline." - -test fn witness_emitter_produced_unauthorized_disposition_unrepresentable_reds() -> Bool { - emitter_produced_unauthorized_disposition_unrepresentable_holds() - && compiler_frontier_emitter_produced_authorization_mint_consistent_holds() -} - -data witness_restored_binding_without_executed_receipt_red_note: String = "Review 44455/44460 RED: roster edits and static oracle derivation cannot mint BuildGreen — authorization requires witness-realization mint with admissible wet_execution_digest." -test fn witness_restored_binding_without_executed_receipt_does_not_authorize_reds() -> Bool { - producer_emission_binding_only_does_not_authorize_holds() -} +data witness_roster_half_deleted_note: String = "TWENTY-FIVE WITNESSES WERE DELETED FROM THIS FILE with the self-host frontier roster, and the deletion is a retirement rather than a coverage loss, for one reason: every one of them had the roster's promotion state as its subject. They asked whether an oracle row was enrolled, whether an enrolled row authorized an EmitterProduced disposition, whether a hand-forged authorization token failed mint consistency, whether the executed-verdict mint refused at a baseline of zero, and whether the producer-qualified counts matched their baselines. With no roster there is no row to promote, no disposition to authorize, and no baseline to count against — the invalid states those witnesses guarded have no representation left, which is the highest rung DESIGN section 4b describes and the one place it permits the evidence to go with the machinery. -data witness_executed_verdict_minting_refused_at_baseline_red_note: String = "Review 44468 RED: producer_emission_canonical_receipt_for_executed_verdict is unwritable at baseline — no synthesizable executed receipt from declarative oracle fields can mint BuildGreen." - -test fn witness_executed_verdict_minting_refused_at_baseline_reds() -> Bool { - producer_emission_executed_verdict_minting_refused_at_baseline_holds() -} +TWO CLAIMS SURVIVED THE DELETION and keep their controls, which is why this file still exists. The first is the closure wall: a V2Emitter receipt cannot be minted when v1.compiler.emit_rust is in its realized closure, so a claim that the v2 emitter produced a module cannot be made while the seed emitter is what actually ran. That wall is independent of any roster — it constrains the receipt, not the row — and mint_v2_interpreted_receipt_with_seed_closure_refuses is its executing RED. The second is that the wet known-red entries are one shared authority rather than two drifting copies. -data witness_synthesizable_executed_digest_refused_red_note: String = "Review 44477 RED: declarative-input wet_execution_digest (content_hash_atom of probe entry) is refused before execution_measured admissibility — synthesizable digest cannot mint BuildGreen even when row identity matches." - -test fn witness_synthesizable_executed_digest_refused_reds() -> Bool { - let row = producer_emission_oracle_row_body_producer - let executed = ProducerEmissionExecutedGreenReceipt { - module_path: row.module_path, - behavioral_probe_entry: row.behavioral_probe_entry, - behavioral_probe_function: row.behavioral_probe_function, - wet_execution_digest: content_hash_atom(value: row.behavioral_probe_entry) - } - match producer_emission_canonical_receipt_for_executed_verdict(row: row, executed: executed) { - Absent => true - Present { value: _ } => false - } -} - -data witness_quarantine_enrolled_build_refused_does_not_authorize_red_note: String = "Review 44385 RED: quarantine oracle mint enrolls via producer_emission_receipt_from_oracle_row (BuildRefused) but authorization requires BuildGreen canonical — enrollment and authorization are split (review 44393)." - -test fn witness_quarantine_enrolled_build_refused_does_not_authorize_reds() -> Bool { - let oracle = producer_emission_oracle_row_body_producer - match producer_emission_receipt_from_oracle_row(row: oracle) { - Present { value: receipt } => - producer_emission_oracle_enrolls_row(module_path: oracle.module_path, receipt: receipt) - && !producer_emission_oracle_authorizes_row( - module_path: oracle.module_path, - receipt: receipt, - executed: witness_fabricated_executed_verdict( - module_path: oracle.module_path, - behavioral_probe_entry: oracle.behavioral_probe_entry, - behavioral_probe_function: oracle.behavioral_probe_function - ) - ) - Absent => false - } -} - -test fn witness_quarantine_oracle_modules_seed_retained_holds() -> Bool { - compiler_frontier_quarantine_oracle_modules_seed_retained_holds() -} - -test fn witness_producer_qualified_baselines_holds() -> Bool { - compiler_frontier_producer_qualified_baselines_holds() - && producer_qualified_baselines_holds() - && (producer_emission_oracle_row_count() == seed_emitter_behavioral_quarantine_baseline) - && (seed_emitter_behavioral_quarantine_count() == seed_emitter_behavioral_quarantine_baseline) - && (compiler_frontier_emitter_produced_count() == emitter_produced_baseline) - && (seed_emitter_behavioral_green_count() == seed_emitter_behavioral_green_baseline) - && (v2_interpreted_emitter_behavioral_green_count() == 0) - && (v2_native_emitter_behavioral_green_count() == 0) - && (v2_emitter_production_routed_count() == 0) -} - -test fn witness_emitter_produced_oracle_count_matches_baseline_holds() -> Bool { - compiler_frontier_emitter_produced_oracle_count_matches_baseline_holds() -} - -test fn witness_census_includes_producer_backing_holds() -> Bool { - compiler_frontier_census_holds() -} - -test fn witness_flip_wave_reverted_modules_lack_oracle_holds() -> Bool { - producer_emission_flip_wave_reverted_modules_lack_oracle_holds() -} - -data witness_seed_emit_rust_poison_structural_refusal_note: String = "PRIMARY discriminating RED (calm-badger-682 ruling 2026-07-29): mint_producer_emission_receipt must refuse V2EmitterInterpreted when cssl_harness_realized_closure contains v1.compiler.emit_rust. Harness poison proves the wall fires; the wall is structural in the mint path." +ONE DELETED WITNESS DESERVES ITS OWN SENTENCE because it looked like a real control and was not reachable as one. witness_v2_producer_claim_with_seed_closure_unauthorized_reds fabricated a v2 receipt over a seed closure and asserted the oracle refused to authorize it. Its subject was the authorization fold, which is gone; the underlying claim — that such a receipt is illegitimate — is now enforced one rung higher, at the mint, where the receipt cannot be constructed at all. The refusal it tested still holds; it holds by construction instead of by validation, and the mint control below is what proves it." test fn witness_seed_emit_rust_poison_structural_refusal_reds() -> Bool { mint_v2_interpreted_receipt_with_seed_closure_refuses( @@ -196,132 +25,8 @@ test fn witness_seed_emit_rust_poison_structural_refusal_reds() -> Bool { ) } -test fn witness_v2_producer_claim_with_seed_closure_unauthorized_reds() -> Bool { - let fabricated = fabricated_v2_interpreted_producer_receipt( - module_path: "src/v2/compiler/03_body_producer.dag" - ) - !producer_emission_oracle_authorizes_row( - module_path: fabricated.module_path, - receipt: fabricated, - executed: witness_fabricated_executed_verdict( - module_path: fabricated.module_path, - behavioral_probe_entry: "fabricated", - behavioral_probe_function: "fabricated" - ) - ) -} - -data witness_flip_wave_secondary_red_note: String = "SECONDARY regression (2026-07-20 flip-wave): dishonest V1SeedEmitter claim for flip-wave module without oracle row must refuse authorization." - -test fn witness_flip_wave_dishonest_v1_claim_reds() -> Bool { - let path = "src/v2/compiler/00_compile.dag" - let fabricated = fabricated_v1_seed_producer_receipt(module_path: path) - !producer_emission_oracle_authorizes_row( - module_path: path, - receipt: fabricated, - executed: witness_fabricated_executed_verdict( - module_path: path, - behavioral_probe_entry: "fabricated", - behavioral_probe_function: "fabricated" - ) - ) -} - -test fn witness_flip_wave_all_six_dishonest_claims_red() -> Bool { - fold_list( - xs: producer_emission_flip_wave_reverted_module_paths, - empty: true, - cons: fn(ok, path) { - ok && !producer_emission_oracle_authorizes_row( - module_path: path, - receipt: fabricated_v1_seed_producer_receipt(module_path: path), - executed: witness_fabricated_executed_verdict( - module_path: path, - behavioral_probe_entry: "fabricated", - behavioral_probe_function: "fabricated" - ) - ) - } - ) -} - -test fn witness_oracle_rows_match_transport_roster_holds() -> Bool { - producer_emission_oracle_rows_match_transport_roster_holds() -} - -test fn witness_synthetic_oracle_row_not_in_live_registry_reds() -> Bool { - let red_row = producer_emission_oracle_row_00_compile_flip_wave_red - match producer_emission_canonical_receipt_for_oracle_row(row: red_row) { - Present { value: receipt } => - !producer_emission_oracle_authorizes_row( - module_path: red_row.module_path, - receipt: receipt, - executed: witness_fabricated_executed_verdict( - module_path: red_row.module_path, - behavioral_probe_entry: red_row.behavioral_probe_entry, - behavioral_probe_function: red_row.behavioral_probe_function - ) - ) - Absent => true - } -} - -data witness_baseline_oracle_row_quarantine_does_not_authorize_red_note: String = "Review 44350 RED: live oracle row enrolled on assemble-red quarantine must not authorize BuildGreen EmitterProduced until wet execution greens." - -test fn witness_baseline_oracle_row_quarantine_does_not_authorize_reds() -> Bool { - let oracle = producer_emission_oracle_row_body_producer - match producer_emission_canonical_receipt_for_oracle_row(row: oracle) { - Present { value: receipt } => - !producer_emission_oracle_authorizes_row( - module_path: oracle.module_path, - receipt: receipt, - executed: witness_fabricated_executed_verdict( - module_path: oracle.module_path, - behavioral_probe_entry: oracle.behavioral_probe_entry, - behavioral_probe_function: oracle.behavioral_probe_function - ) - ) - Absent => true - } -} - -data witness_absent_from_known_red_without_green_does_not_authorize_red_note: String = "Review 44441 RED: static oracle derivation never mints BuildGreen — a row absent from known-red still receives BuildRefused (not_executed), so authorization cannot be fabricated by roster edits." - -test fn witness_absent_from_known_red_without_green_does_not_authorize_reds() -> Bool { - let synthetic = producer_emission_oracle_row_00_compile_flip_wave_red - match producer_emission_receipt_from_oracle_row(row: synthetic) { - Present { value: receipt } => - match receipt.build_result { - BuildGreen => false - BuildRefused { cause: _ } => - !producer_emission_oracle_authorizes_row( - module_path: synthetic.module_path, - receipt: receipt, - executed: witness_fabricated_executed_verdict( - module_path: synthetic.module_path, - behavioral_probe_entry: synthetic.behavioral_probe_entry, - behavioral_probe_function: synthetic.behavioral_probe_function - ) - ) - } - Absent => false - } -} - -data witness_fabricated_build_green_same_module_producer_red_note: String = "Reviews 44328/44350 RED: fabricated BuildGreen receipt must NOT authorize against a quarantine-enrolled oracle row." - -test fn witness_fabricated_build_green_same_module_producer_reds() -> Bool { - let oracle = producer_emission_oracle_row_body_producer - let fabricated = fabricated_v1_seed_producer_receipt(module_path: oracle.module_path) - !producer_emission_oracle_authorizes_row( - module_path: oracle.module_path, - receipt: fabricated, - executed: witness_fabricated_executed_verdict( - module_path: oracle.module_path, - behavioral_probe_entry: oracle.behavioral_probe_entry, - behavioral_probe_function: oracle.behavioral_probe_function - ) - ) +test fn witness_v2_interpreted_closure_is_seed_free() -> Bool { + v2_interpreted_emitter_closure_seed_free_holds() } test fn witness_wet_known_red_entries_is_shared_authority() -> Bool { @@ -330,17 +35,3 @@ test fn witness_wet_known_red_entries_is_shared_authority() -> Bool { right: falsifier_self_host_wet_known_red_entries ) } - -test fn witness_oracle_rows_bidirectional_enrollment_holds() -> Bool { - producer_emission_oracle_rows_match_enrollment_holds() -} - -test fn witness_probe_entries_length_only_parity_would_fail_on_mismatch_red() -> Bool { - let mismatched_function = "fabricated_flip_wave_all_holds" - let cited = schedule_witness_entry_cited( - probe_entry: producer_emission_oracle_row_body_producer.behavioral_probe_entry, - probe_function: mismatched_function, - entries: seed_emitter_behavioral_wet_known_red_entries - ) - !cited -} diff --git a/src/v2/test/claim/self_host/frontier_gap_clustering_measured_test.dag b/src/v2/test/claim/self_host/frontier_gap_clustering_measured_test.dag deleted file mode 100644 index 286584d1a4d..00000000000 --- a/src/v2/test/claim/self_host/frontier_gap_clustering_measured_test.dag +++ /dev/null @@ -1,101 +0,0 @@ -module v2.test.claim.self_host.frontier_gap_clustering_measured - -import v2.compiler.self_host.frontier_probe_survey { - CommonRoot, - HeterogeneousGaps, - frontier_gap_clustering_from_receipts -} -import v2.compiler.self_host.frontier_probe_types { - FrontierProbeDetailAbsent, - FrontierProbeReceipt, - NoFrontierProbeDetail, - ProbeStageAssemble, - RealizationGap, - UnknownProbeCause -} -import v2.std.algebra { Cons, Empty } -import v2.std.collection { List } -import v2.std.logic { Bool } -import v2.std.node { Symbol } -import v2.std.text { String } - -data frontier_gap_clustering_measured_note: String = "Discriminating controls for the clustering verdict's dominant reason. The verdict used to count blocker CLASSES and then write a hardcoded reason literal into the arm that fired, so a survey of modules refusing for ^tokenize_lex_e1_unrecognized_char — the reason the one real survey to date actually measured — would have reported ^parse_grammar_choice_overlap_residue, a symbol no receipt carried. These fixtures pin the reason to what the receipts say: a unanimous survey reports THAT reason and counts it, and a mixed survey reports its true distinct count rather than the module count. Fixtures, not a pipeline walk, so they cost milliseconds. RED: asserting the previously hardcoded literal on the unanimous case fails, which is the exact substitution these claims exist to catch." - -fn receipt_with_reason(reason: Symbol) -> FrontierProbeReceipt { - FrontierProbeReceipt { - module_path: "src/v2/compiler/clustering_probe_fixture.dag", - blocker_class: UnknownProbeCause { reason: reason }, - located_stage: ProbeStageAssemble, - located_reason: reason, - detail: FrontierProbeDetailAbsent, - assemble_detail: NoFrontierProbeDetail - } -} - -fn unanimous_receipts() -> List { - Cons { - head: receipt_with_reason(reason: ^tokenize_lex_e1_unrecognized_char), - tail: Cons { - head: receipt_with_reason(reason: ^tokenize_lex_e1_unrecognized_char), - tail: Empty - } - } -} - -fn mixed_receipts() -> List { - Cons { - head: receipt_with_reason(reason: ^tokenize_lex_e1_unrecognized_char), - tail: Cons { - head: receipt_with_reason(reason: ^parse_grammar_choice_overlap_residue), - tail: Cons { - head: receipt_with_reason(reason: ^tokenize_lex_e1_unrecognized_char), - tail: Empty - } - } - } -} - -fn unanimous_dominant_reason() -> Symbol { - match frontier_gap_clustering_from_receipts(xs: unanimous_receipts(), module_count: 2) { - CommonRoot { dominant_located_reason: r, dominant_module_count: _, module_count: _ } => r - HeterogeneousGaps { distinct_located_reason_count: _, module_count: _ } => - ^clustering_reported_heterogeneous - } -} - -fn unanimous_dominant_count() -> Int { - match frontier_gap_clustering_from_receipts(xs: unanimous_receipts(), module_count: 2) { - CommonRoot { dominant_located_reason: _, dominant_module_count: c, module_count: _ } => c - HeterogeneousGaps { distinct_located_reason_count: _, module_count: _ } => 0 - 1 - } -} - -fn mixed_distinct_count() -> Int { - match frontier_gap_clustering_from_receipts(xs: mixed_receipts(), module_count: 3) { - CommonRoot { dominant_located_reason: _, dominant_module_count: _, module_count: _ } => 0 - 1 - HeterogeneousGaps { distinct_located_reason_count: d, module_count: _ } => d - } -} - -fn empty_distinct_count() -> Int { - match frontier_gap_clustering_from_receipts(xs: Empty, module_count: 0) { - CommonRoot { dominant_located_reason: _, dominant_module_count: _, module_count: _ } => 0 - 1 - HeterogeneousGaps { distinct_located_reason_count: d, module_count: _ } => d - } -} - -test fn unanimous_survey_reports_the_measured_reason_holds() -> Bool { - unanimous_dominant_reason() == ^tokenize_lex_e1_unrecognized_char -} - -test fn unanimous_survey_counts_the_receipts_carrying_it_holds() -> Bool { - unanimous_dominant_count() == 2 -} - -test fn mixed_survey_reports_its_true_distinct_count_holds() -> Bool { - mixed_distinct_count() == 2 -} - -test fn empty_survey_is_never_a_common_root_holds() -> Bool { - empty_distinct_count() == 0 -} diff --git a/src/v2/test/claim/self_host/wave1_gate1_general_body_producer_witness_test.dag b/src/v2/test/claim/self_host/wave1_gate1_general_body_producer_witness_test.dag deleted file mode 100644 index a420e61d223..00000000000 --- a/src/v2/test/claim/self_host/wave1_gate1_general_body_producer_witness_test.dag +++ /dev/null @@ -1,20 +0,0 @@ -module v2.test.claim.self_host.wave1_gate1_general_body_producer_witness - -import v2.compiler.compile { always_required_lenses } -import v2.compiler.self_host.frontier { - compiler_frontier_row_03_body_producer, - compiler_frontier_row_03_normalize -} -import v2.std.algebra { length } -import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } -import v2.std.logic { Bool } - -data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree - -data wave1_gate1_witness_note: String = "Wave 1 exit gate 1 fast-lane witness (compile-gate + roster): import-closure resolution of 03_body_producer and 03_normalize. Full ingest execution proofs (add Transform, classical_not Match via tokenize→parse_module→normalize) live in long/wave1_gate1_general_body_producer_witness_test.dag. Stage D MVP subsumption receipts: self_host/wave1_gate1_d_mvp_subsumption_witness_test.dag. Not proven here: frontier probe per-module receipts or FLAG E dissolution of body_lowering_fold.dag." - -test fn wave1_gate1_body_producer_modules_import_resolve_holds() -> Bool { - (length(xs: always_required_lenses()) == 3) - && (compiler_frontier_row_03_body_producer.module_path == "src/v2/compiler/03_body_producer.dag") - && (compiler_frontier_row_03_normalize.module_path == "src/v2/compiler/03_normalize.dag") -} diff --git a/src/v2/test/claim/self_host/wave1_gate2_namespace_symbol_index_witness_test.dag b/src/v2/test/claim/self_host/wave1_gate2_namespace_symbol_index_witness_test.dag deleted file mode 100644 index 0cbb4bd4bcc..00000000000 --- a/src/v2/test/claim/self_host/wave1_gate2_namespace_symbol_index_witness_test.dag +++ /dev/null @@ -1,42 +0,0 @@ -module v2.test.claim.self_host.wave1_gate2_namespace_symbol_index_witness - -import v2.compiler.compile { always_required_lenses } -import v2.compiler.self_host.frontier { - compiler_frontier_row_00_compile, - compiler_frontier_row_01_tokenize, - compiler_frontier_row_03_body_producer -} -import v2.std.algebra { length } -import v2.std.logic { Bool } -import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } -import v2.test.claim.symbol_index.containment { - symbol_index_flat_index_false_accept_discriminator_holds, - symbol_index_lexical_lookup_unique_variant_holds, - symbol_index_lexical_lookup_chain_shadow_refuses_holds, - symbol_index_lexical_lookup_variant_alias_shadow_refuses_holds, - symbol_index_lookup_miss_red_control_holds, - symbol_index_unique_variant_without_alias_red_control_holds, - symbol_index_variant_visibility_equivalence_holds -} - -data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree - -data wave1_gate2_witness_note: String = "Wave 1 exit gate 2 verification (namespace SymbolIndex / containment-tree resolution) by execution. Proven here: symbol_index_fill + symbol_index_lexical_lookup via containment_test greens (symbol_index_lexical_lookup_unique_variant_holds, symbol_index_variant_visibility_equivalence_holds) and named RED controls (lookup_miss, flat_index_false_accept, unique_variant_without_alias). Import-closure resolution of 00_compile, 01_tokenize, 03_body_producer is compile-gated (symbols import or the witness module does not resolve). Not proven here: frontier probe blocker_class rows, 03_name_resolve/03_resolve end-to-end ingest wire (variant_visibility_test.dag; normalize-stage debt)." - -test fn wave1_gate2_symbol_index_containment_substrate_holds() -> Bool { - symbol_index_lexical_lookup_unique_variant_holds() - && symbol_index_variant_visibility_equivalence_holds() -} - -test fn wave1_gate2_symbol_index_containment_red_controls_holds() -> Bool { - symbol_index_lookup_miss_red_control_holds() - && symbol_index_flat_index_false_accept_discriminator_holds() - && symbol_index_unique_variant_without_alias_red_control_holds() -} - -test fn wave1_gate2_name_resolution_gap_modules_import_resolve_holds() -> Bool { - (length(xs: always_required_lenses()) == 3) - && (compiler_frontier_row_00_compile.module_path == "src/v2/compiler/00_compile.dag") - && (compiler_frontier_row_01_tokenize.module_path == "src/v2/compiler/01_tokenize.dag") - && (compiler_frontier_row_03_body_producer.module_path == "src/v2/compiler/03_body_producer.dag") -} diff --git a/src/v2/test/claim/self_host/wet_receipt_enrollment_witness_test.dag b/src/v2/test/claim/self_host/wet_receipt_enrollment_witness_test.dag deleted file mode 100644 index f4b5ed9fde0..00000000000 --- a/src/v2/test/claim/self_host/wet_receipt_enrollment_witness_test.dag +++ /dev/null @@ -1,101 +0,0 @@ -module v2.test.claim.self_host.wet_receipt_enrollment_witness_test - -import v2.compiler.self_host.frontier { - compiler_frontier_row_03_body_producer, - compiler_frontier_row_06_translate, - compiler_frontier_row_07_target_carriers, - compiler_frontier_row_parse_engine_hooks, - compiler_frontier_row_discovery_enumeration, - compiler_frontier_row_use_site_verdict, -} -import v2.compiler.self_host.wet_receipt_enrollment { - falsifier_self_host_wet_entries, - falsifier_self_host_wet_template_entries, - falsifier_self_host_wet_frontier_enrolled_entries, - frontier_row_wet_entries_if_enrolled, - find_wet_receipt_binding -} -import v2.std.algebra { length } -import v2.std.collection { Absent, Present } -import v2.std.logic { Bool } -import v2.std.text { String } - -data wet_binding_revocation_witness_note: String = "2026-07-25: module wet bindings revoked (empty list) after cadence run 30126573464 showed the six SelfEmitted wet receipts RED. Witnesses below pin the revoked state — rows enroll nothing without a binding; nightly = template-only. Review 44453: enrollment keys on binding presence, not EmitterProduced disposition. Re-arm each binding witness when that module's wet receipt greens." - -test fn witness_seed_retained_row_enrolls_no_wet_entry() -> Bool { - length(xs: frontier_row_wet_entries_if_enrolled(row: compiler_frontier_row_06_translate)) == 0 -} - -test fn witness_unbound_module_row_enrolls_no_wet_entry() -> Bool { - length(xs: frontier_row_wet_entries_if_enrolled(row: compiler_frontier_row_06_translate)) == 0 -} - -test fn witness_parse_engine_hooks_self_emitted_enrolls_no_wet_while_revoked() -> Bool { - length(xs: frontier_row_wet_entries_if_enrolled(row: compiler_frontier_row_parse_engine_hooks)) == 0 -} - -test fn witness_use_site_verdict_self_emitted_enrolls_no_wet_while_revoked() -> Bool { - length(xs: frontier_row_wet_entries_if_enrolled(row: compiler_frontier_row_use_site_verdict)) == 0 -} - -test fn witness_discovery_enumeration_self_emitted_enrolls_no_wet_while_revoked() -> Bool { - length(xs: frontier_row_wet_entries_if_enrolled(row: compiler_frontier_row_discovery_enumeration)) == 0 -} - -test fn witness_target_carriers_self_emitted_enrolls_no_wet_while_revoked() -> Bool { - length(xs: frontier_row_wet_entries_if_enrolled(row: compiler_frontier_row_07_target_carriers)) == 0 -} - -test fn witness_body_producer_self_emitted_enrolls_no_wet_while_revoked() -> Bool { - length(xs: frontier_row_wet_entries_if_enrolled(row: compiler_frontier_row_03_body_producer)) == 0 -} - -data wet_template_entry_count_note: String = "Twelve template rows: the Gate-4 std/logic per-module self-host receipt, the Gate-1 emit-class import-closure receipt (namespace_import_closure_witness_test), the seven emit-on-demand family aggregates (kernel, field_access, complement, match_loop_fold, meet_join, variant_construct, classical_not_ingested — the 2026-07-21 nightly Wet enrollment; complement + meet_join are pure-receipt residues after the family-grain migration), the family-crate aggregate (emit_on_demand_family_crate_witness_test — the executing consumer for the migrated complement/meet_join native legs, enrolled so the migration cannot orphan them), the Kernel-D native-only-verdict real compile-and-run witness (emit_host_native_only_verdict_test.dag — KERNEL-D TESTING RE-STEER, 2026-07-24: moved off per-PR CommitCheckEnrollment onto this nightly wet cadence, the same lane as the other module-agnostic rows here), and the R1 real-crate roster<->handler bijection receipt (interpreter_dispatch_bijection_real_roster_witness_test.dag — Lane D, gunbc#7825). The non-Gate-4 rows are module-agnostic — no frontier row flips to gate them; they enroll as template rows rather than SelfHostWetReceiptBinding rows. See falsifier_self_host_wet_emit_class_note." - -test fn witness_nightly_enrollment_is_template_only_while_bindings_revoked() -> Bool { - (length(xs: falsifier_self_host_wet_template_entries) == 12) - && (length(xs: falsifier_self_host_wet_frontier_enrolled_entries()) == 0) - && (length(xs: falsifier_self_host_wet_entries()) == 12) -} - -test fn witness_parse_engine_hooks_binding_absent_while_revoked() -> Bool { - match find_wet_receipt_binding(module_path: "src/v2/compiler/parse_engine_hooks.dag") { - Absent => true - Present { value: _ } => false - } -} - -test fn witness_use_site_verdict_binding_absent_while_revoked() -> Bool { - match find_wet_receipt_binding(module_path: "src/v2/compiler/use_site_verdict.dag") { - Absent => true - Present { value: _ } => false - } -} - -test fn witness_discovery_enumeration_binding_absent_while_revoked() -> Bool { - match find_wet_receipt_binding(module_path: "src/v2/compiler/discovery_enumeration.dag") { - Absent => true - Present { value: _ } => false - } -} - -test fn witness_target_carriers_binding_absent_while_revoked() -> Bool { - match find_wet_receipt_binding(module_path: "src/v2/compiler/07_target_carriers.dag") { - Absent => true - Present { value: _ } => false - } -} - -test fn witness_body_producer_binding_absent_while_revoked() -> Bool { - match find_wet_receipt_binding(module_path: "src/v2/compiler/03_body_producer.dag") { - Absent => true - Present { value: _ } => false - } -} - -test fn witness_unbound_module_path_has_no_binding() -> Bool { - match find_wet_receipt_binding(module_path: "src/v2/compiler/06_translate.dag") { - Absent => true - Present { value: _ } => false - } -} diff --git a/src/v2/test/claim/workflow/host_frontier_probe_survey_manifest.dag b/src/v2/test/claim/workflow/host_frontier_probe_survey_manifest.dag deleted file mode 100644 index 51c80d6fbb9..00000000000 --- a/src/v2/test/claim/workflow/host_frontier_probe_survey_manifest.dag +++ /dev/null @@ -1,38 +0,0 @@ -module v2.test.workflow.host_frontier_probe_survey_manifest - -import extdeps.git.object_store { GitSha1ObjectId } -import std.content_hash { - ContentHash, - Fnv1a64, - Fnv1a64Structural, - Sha1Digest, - Sha256Digest, - structural_content_hash -} -import v2.compiler.self_host.frontier_probe_types { - FrontierSurveyManifest, - FrontierSurveySubject, - frontier_probe_policy_revision -} -import v2.std.algebra { Empty } -import v2.std.collection { List } -import v2.std.text { String } - -data host_frontier_probe_survey_manifest: FrontierSurveyManifest = FrontierSurveyManifest { - subject: FrontierSurveySubject { - source_commit: "", - source_tree: GitSha1ObjectId { - digest: Sha1Digest { - hex: "0000000000000000000000000000000000000000" - } - }, - survey_executable: Sha256Digest { - hex: "0000000000000000000000000000000000000000000000000000000000000000" - }, - source_roots_digest: Fnv1a64Structural { - digest: "0000000000000000" - }, - probe_policy_revision: frontier_probe_policy_revision() - }, - receipts: Empty -} diff --git a/src/v2/test/claim/wrap_decision_predicate_test.dag b/src/v2/test/claim/wrap_decision_predicate_test.dag index 2b5a630283c..04a4c8c0f8a 100644 --- a/src/v2/test/claim/wrap_decision_predicate_test.dag +++ b/src/v2/test/claim/wrap_decision_predicate_test.dag @@ -1,7 +1,7 @@ module v2.test.claim.wrap_decision_predicate import v2.compiler.translate { translate_apply_use_site_ownership_to_projected_boundary } -import v2.compiler.wrap_decision { wrap_decision_gate } +import v2.compiler.wrap_decision { wrap_decision_gate, wrap_decision_flow_gate } import v2.extdeps.languages.rust { rust_named_edge, rust_sg2_type_expr_target_model, @@ -15,6 +15,7 @@ import v2.std.compilers.target_model { TargetReferenceLayer, TargetTypeExprAtom, TargetTypeExprInstantiation, + OwnershipAtBindingProjection, OwnershipAtFunctionParameter, OwnershipAtFunctionReturn, OwnershipAtStructField, @@ -46,7 +47,7 @@ import v2.std.node_query { node_positional_child_targets } import v2.std.optional { Absent, Present } import v2.std.text { String } -data wrap_decision_predicate_note: String = "Derisk witnesses for rc-ownership-wrap-decision-design.md: wrap_decision_gate is the single authority for Rc/Box/owned type wrapping at emit sites. UseSiteVerdict enrolled (owned-at-all-sites). RED: omit Diagnostics param row -> param witness rejects; add silent default wrap on WrapGateInapplicable -> bundle_absent witness fails." +data wrap_decision_predicate_note: String = "Derisk witnesses for rc-ownership-wrap-decision-design.md: wrap_decision_gate is the single authority for Rc/Box/owned type wrapping at ONE emit position, and wrap_decision_flow_gate is the single authority over a producer/consumer PAIR, refusing disagreement. UseSiteVerdict enrolled (owned-at-all-sites). RED, position surface: omit Diagnostics param row -> param witness rejects; add silent default wrap on WrapGateInapplicable -> bundle_absent witness fails. RED, flow surface (measured, non-uniform): force wrap_decision_gates_agree to true -> over_wrap, under_wrap and distinct_reference_layers witnesses red while missing_row and both accept controls stay green; make wrap_decisions_equal layer-blind -> distinct_reference_layers alone reds. A witness set that reds together says less than one whose profile names which witness guards which arm." fn wrap_decision_sg_rc_target() -> TargetModel { rust_sg2_type_expr_target_model() @@ -248,6 +249,138 @@ test fn wrap_decision_node_struct_field_is_box() -> Bool { ) } + +// R1's two-direction controls. The acceptance condition for R1 is that a fix moves BOTH error +// directions, because the measured defect is ONE inconsistency producing opposite signs — a +// producer's Rc reaching a bare consumer over-wraps, a bare producer reaching an Rc consumer +// under-wraps — so a control drawn from one direction alone cannot distinguish the right fix from +// the position-based fix that moves half the population and worsens the other half. Both +// directions are drawn from the LIVE rust catalog rather than a synthetic fixture, by varying only +// the flow's direction over one carrier whose rows already disagree by position: Diagnostics is +// ReferenceLayerRc at OwnershipAtBindingProjection and ReferenceLayerOwned at +// OwnershipAtFunctionParameter, so binding-to-param is the over shape and param-to-binding is the +// under shape. wrap_decision_flow_gate must refuse BOTH; today's per-position gate accepts both +// and emits the producer's layer, which is the silent wrongness. The layer-discrimination control +// is the one that keeps wrap_decisions_equal honest: Node is ReferenceLayerRc at binding and +// ReferenceLayerBox at struct field, two DIFFERENT reference layers, and an implementation +// comparing only by-value against by-reference would call that agreement and pass every other +// control here. RED, executed rather than asserted, and the profile is reported exactly as +// measured because it is not uniform. Mutation one, wrap_decision_gates_agree forced to true: the +// over-wrap, under-wrap and distinct-layer witnesses all go RED; the missing-row witness and both +// accept witnesses stay GREEN. So the missing-row witness does NOT discriminate this +// reconciliation — it is a regression control proving an underlying catalog miss still propagates +// through the flow gate rather than being swallowed by it, and saying it discriminates +// disagreement would be inflation. Mutation two, wrap_decisions_equal made layer-blind so any two +// WrapByReference count as equal: ONLY the distinct-layer witness goes RED, which is what earns +// that witness its place — Rc against Box is a real disagreement that a by-value-versus-by- +// reference comparison calls agreement, and every other witness here passes under that bug. The +// agreement and inapplicable witnesses are the positive controls that stop a refuse-always +// implementation from earning a degenerate pass on the refusal half. +fn wrap_decision_flow_rejects( + target: TargetModel, + source_carrier: Node, + producer_site: TargetOwnershipUseSite, + consumer_site: TargetOwnershipUseSite +) -> Bool { + match wrap_decision_flow_gate( + target: target, + source_carrier: source_carrier, + producer_site: producer_site, + consumer_site: consumer_site + ) { + Rejected { diagnostics: _ } => true + Accepted { value: _, diagnostics: _ } => false + } +} + +fn wrap_decision_flow_is_by_value( + target: TargetModel, + source_carrier: Node, + producer_site: TargetOwnershipUseSite, + consumer_site: TargetOwnershipUseSite +) -> Bool { + match wrap_decision_flow_gate( + target: target, + source_carrier: source_carrier, + producer_site: producer_site, + consumer_site: consumer_site + ) { + Accepted { value: WrapGateDecided { decision: WrapByValue }, diagnostics: _ } => true + _ => false + } +} + +fn wrap_decision_flow_is_inapplicable( + target: TargetModel, + source_carrier: Node, + producer_site: TargetOwnershipUseSite, + consumer_site: TargetOwnershipUseSite +) -> Bool { + match wrap_decision_flow_gate( + target: target, + source_carrier: source_carrier, + producer_site: producer_site, + consumer_site: consumer_site + ) { + Accepted { value: WrapGateInapplicable, diagnostics: _ } => true + _ => false + } +} + +test fn wrap_decision_flow_over_wrap_direction_refuses() -> Bool { + wrap_decision_flow_rejects( + target: wrap_decision_sg_rc_target(), + source_carrier: target_carrier_diagnostics_node(), + producer_site: OwnershipAtBindingProjection, + consumer_site: OwnershipAtFunctionParameter + ) +} + +test fn wrap_decision_flow_under_wrap_direction_refuses() -> Bool { + wrap_decision_flow_rejects( + target: wrap_decision_sg_rc_target(), + source_carrier: target_carrier_diagnostics_node(), + producer_site: OwnershipAtFunctionParameter, + consumer_site: OwnershipAtBindingProjection + ) +} + +test fn wrap_decision_flow_distinct_reference_layers_refuse() -> Bool { + wrap_decision_flow_rejects( + target: wrap_decision_sg_rc_target(), + source_carrier: target_carrier_node_node(), + producer_site: OwnershipAtBindingProjection, + consumer_site: OwnershipAtStructField + ) +} + +test fn wrap_decision_flow_missing_row_refuses() -> Bool { + wrap_decision_flow_rejects( + target: wrap_decision_sg_rc_target(), + source_carrier: target_carrier_probe_heap_node(), + producer_site: OwnershipAtFunctionReturn, + consumer_site: OwnershipAtFunctionParameter + ) +} + +test fn wrap_decision_flow_agreeing_sites_accept() -> Bool { + wrap_decision_flow_is_by_value( + target: wrap_decision_sg_rc_target(), + source_carrier: target_carrier_use_site_verdict_node(), + producer_site: OwnershipAtFunctionReturn, + consumer_site: OwnershipAtFunctionParameter + ) +} + +test fn wrap_decision_flow_bundle_absent_inapplicable() -> Bool { + wrap_decision_flow_is_inapplicable( + target: wrap_decision_bundle_absent_target(), + source_carrier: target_carrier_diagnostics_node(), + producer_site: OwnershipAtBindingProjection, + consumer_site: OwnershipAtFunctionParameter + ) +} + data wrap_decision_composite_note: String = "Discriminates the wrap_decision_predicate caller-side bypass (v1_deletion_plan.dag ^wrap_decision_predicate, RE-OPENED 2026-07-24): translate_apply_use_site_ownership_to_projected_boundary must recurse ownership-wrap into TargetTypeExprInstantiation-kind wires (Option/Rc/List shapes) instead of returning the composite unwrapped via the _ => outcome_accepted(projected) arm." fn wrap_decision_composite_projected_arg() -> Node { diff --git a/src/v2/workflow/frontier_probe_survey_transport.dag b/src/v2/workflow/frontier_probe_survey_transport.dag deleted file mode 100644 index ff7f8e47c09..00000000000 --- a/src/v2/workflow/frontier_probe_survey_transport.dag +++ /dev/null @@ -1,69 +0,0 @@ -module v2.workflow.frontier_probe_survey_transport - -import extdeps.shell -import extdeps.git -import extdeps.git.inspect -import extdeps.gunbc -import gunbc.ci_layer_roots { witness_layer_roots } -import std.logic { Bool } -import tools.host_prelude { - ClaimRun, - WitnessBinReady, - WitnessBinRefused, - run_gunbc_claims, - witness_bin, - witness_bin_ensure_built_typed, - witness_bin_release_path -} - -data survey_source_root: String = "src/v2" -data survey_dag_source_root: String = "dag" -data survey_manifest_dir: String = "target/frontier-probe-survey" -data survey_manifest_path: String = "target/frontier-probe-survey/host_frontier_probe_survey_manifest.dag" -data survey_test_entry: String = "src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag" -data survey_witness: String = "compiler_frontier_per_module_probe_survey_holds" -data survey_gap_witness: String = "compiler_frontier_gap_clustering_common_root_at_blocker_class_holds" - -data frontier_probe_survey_transport_scaffold_note: String = "SCAFFOLD — see v2.compiler.self_host.frontier_probe_survey::frontier_probe_survey_transport_scaffold_note. Host bin reads `compiler_frontier_sweep_order` from frontier.dag; dissolves on `^migrate_when_frontier_per_module_probe_receipt_binds` (gunbc.plans.wave2_prep_design census carrier)." - -fn survey_manifest_emit_args(manifest_path: String) -> List { - [ - "--source-root", survey_source_root, - "--source-root", survey_dag_source_root, - "--emit-survey-manifest", manifest_path, - "--survey-dir", survey_manifest_dir - ] -} - -func run_frontier_probe_survey_gate_ready(root: String) -> Bool { - let target_ready = shell.Mkdir.Parents(path: concat(root, concat("/", survey_manifest_dir))) - if target_ready.success { - let emitted = gunbc.WitnessBin.Run( - workdir: root, - bin_path: witness_bin_release_path(root: root, bin_name: "frontier_probe_survey"), - args: survey_manifest_emit_args(manifest_path: survey_manifest_path) - ) - if emitted.success { - run_gunbc_claims( - source_roots: concat(witness_layer_roots, [survey_manifest_dir]), - claims: [ - ClaimRun { entry: survey_test_entry, function: survey_witness }, - ClaimRun { entry: survey_test_entry, function: survey_gap_witness } - ] - ) - } else { - false - } - } else { - false - } -} - -func run_frontier_probe_survey_gate() -> Bool { - let root = git.Inspect.Toplevel() - let survey_bin = witness_bin(var_name: "FRONTIER_PROBE_SURVEY", bin_name: "frontier_probe_survey") - match witness_bin_ensure_built_typed(root: root.path, bin: survey_bin) { - WitnessBinRefused { bin_name: _, path: _, reason: _ } => false - WitnessBinReady { path: _ } => run_frontier_probe_survey_gate_ready(root: root.path) - } -} diff --git a/src/v2/workflow/module_binding_supply_transport.dag b/src/v2/workflow/module_binding_supply_transport.dag index 8f5bfba2c26..2d6dccc960e 100644 --- a/src/v2/workflow/module_binding_supply_transport.dag +++ b/src/v2/workflow/module_binding_supply_transport.dag @@ -34,7 +34,7 @@ data mbs_layout_claims_note: String = "The crate-layout witnesses run HERE, in t They were removed from compiler_frontier_census_holds in the same change (frontier_census_layout_relocation_note): the census is a pure zero-arity fast-lane gate that cannot obtain a host index, and the layer DAG forbids a compiler module importing v2.test.* to reach one. Enrolling them here is the other half of that removal, not a follow-on — a removal without this enrollment would leave a window where nothing checks crate layout at all. -projection_refuses_on_absent_index is included deliberately even though it passes in either lane: it asserts the fail-closed arm on a LOCALLY constructed Empty index, so running it beside the populated-index witnesses proves both arms of the same projection in one place — the refusal is not merely an artifact of the fast lane having no data." +Two rows were removed here with the self-host frontier roster cut: projection_refuses_on_absent_index and transition_parity_host_index_agrees_with_hand_rows. The parity witness asserted that the derived index and the hand-authored qualified-module bindings answer identically, and the hand rows are gone, so its subject is retired rather than dropped; the refusal witness guarded the projection those rows reached. crate_layout_witnesses still needs the real index and still runs here." fn mbs_claim_source_roots(overlay_dir: String) -> List { concat(witness_layer_roots, [overlay_dir]) @@ -68,8 +68,6 @@ func run_module_binding_supply_gate_ready(root: String) -> Bool { ClaimRun { entry: mbs_entry, function: "module_binding_host_manifest_is_populated" }, ClaimRun { entry: mbs_entry, function: "module_binding_host_resolves_a_known_compiler_module" }, ClaimRun { entry: mbs_entry, function: "module_binding_host_agrees_with_parse_oracle" }, - ClaimRun { entry: mbs_layout_entry, function: "projection_refuses_on_absent_index" }, - ClaimRun { entry: mbs_layout_entry, function: "transition_parity_host_index_agrees_with_hand_rows" }, ClaimRun { entry: mbs_layout_entry, function: "crate_layout_witnesses" } ] ) diff --git a/src/v2/workflow/rust_crate_partition.dag b/src/v2/workflow/rust_crate_partition.dag index 550860cdb40..e21ee06ba70 100644 --- a/src/v2/workflow/rust_crate_partition.dag +++ b/src/v2/workflow/rust_crate_partition.dag @@ -127,14 +127,18 @@ type TypeDefinitionsMapNotFrontierGrounded { dissolve_target: DeclarationRef } -data rust_crate_partition_interface_deferred_note: String = "Interim: ModuleDag.exports + type_definitions carry per-module keys with empty lists (structural scaffold for partition_fold only). R3 render uses Stage0PartitionCrateRow.modules + reexport_packages wildcard pub-use chain — not CompilationUnit.interface Nodes. Full Node-carrier exports blocked on stage0 module ingest (frontier-grounding dependency)." +data rust_crate_partition_interface_deferred_note: String = "Interim: ModuleDag.exports + type_definitions carry per-module keys with empty lists (structural scaffold for partition_fold only). R3 render uses Stage0PartitionCrateRow.modules + reexport_packages wildcard pub-use chain — not CompilationUnit.interface Nodes. Full Node-carrier exports blocked on stage0 module ingest supplying them through the path-module binding index (see stage0_grounding_target_repointed_note)." data rust_crate_partition_r4_by_value_type_cycle_note: String = "Rust R4 primary refusals on current main: SccSplit + UnitGraphCycle (LinkageCycle permissive). ByValueTypeCycle arm lands with #6744 rebase — refuse type-layout cycles via ByValueTypeCycle { detail } ONLY, never SccSplit. Exhaustive PartitionR4ValidityCause matches must add the 4th arm on rebase." +data stage0_grounding_target_repointed_note: String = "REPOINTED, and the old target was wrong before it was deleted. This debt's dissolution used to name v2.compiler.self_host.frontier compiler_frontier_roster, on the premise that the self-host roster would eventually carry each module's exports and type definitions. It never could: a roster row carried a module path and a self-host disposition and nothing else, so the pointer named an authority that was not going to supply the fact even in principle. The roster is deleted, which is what surfaced the mispointing rather than causing it. + +The real dependency is the path-module binding authority, which is where module identity is DERIVED at parse rather than authored — v2.compiler.source_authority module_storage_binding_authority_note states that the hand-authored qualified-module rows project from it, not the other way round. So the interface maps ground when stage0 module ingest supplies real Node-carrier exports through that index." + fn stage0_frontier_grounding_target() -> DeclarationRef { DeclarationRef { - module_path: "v2.compiler.self_host.frontier" as NonEmptyStr, - decl_name: "compiler_frontier_roster" as NonEmptyStr, + module_path: "v2.compiler.source_authority" as NonEmptyStr, + decl_name: "ModuleStorageIndex" as NonEmptyStr, field: WholeDeclaration, } }