From f63f604c33bcfec6cfb07be737aa8676674d68bb Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 00:22:12 +0000 Subject: [PATCH 01/11] WIP: cleanup2 --- dag/extdeps/git/git.dag | 4 ++++ dag/extdeps/github/actions.dag | 12 ++++++++++++ dag/gunbc/repo_identity.dag | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 dag/gunbc/repo_identity.dag diff --git a/dag/extdeps/git/git.dag b/dag/extdeps/git/git.dag index 7192efdc375..36f2377edc6 100644 --- a/dag/extdeps/git/git.dag +++ b/dag/extdeps/git/git.dag @@ -241,6 +241,10 @@ fn git_remote_ref_parts(ref: GitRef) -> GitRemoteRefParts { } } +fn git_remote_ref(parts: GitRemoteRefParts) -> GitRef { + concat(concat(parts.remote, "/"), parts.ref_name) as GitRef +} + fn git_shell_join_argv(argv: List) -> String { fold(argv, init: "", f: (acc, token) => if acc == "" { token } else { concat(concat(acc, " "), token) }) } diff --git a/dag/extdeps/github/actions.dag b/dag/extdeps/github/actions.dag index 5d941160a36..03f32afd786 100644 --- a/dag/extdeps/github/actions.dag +++ b/dag/extdeps/github/actions.dag @@ -33,6 +33,18 @@ data github_actions_runtime: GitHubActionsRuntime = { oidc_request_token_env: "ACTIONS_ID_TOKEN_REQUEST_TOKEN" } +data github_ci_event_surface_note: String = "GITHUB_EVENT_NAME and GITHUB_BASE_REF are default environment variables GitHub Actions sets on every job (docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables, read 2026-07-24). GITHUB_EVENT_NAME carries the wire name of the triggering event (the runtime projection of WorkflowTrigger: push / pull_request / workflow_dispatch / schedule / merge_group). GITHUB_BASE_REF carries the base (target) branch name of a pull request — set ONLY on pull_request / pull_request_target events, empty for every other event. extdeps owns these names (the shape GitHub provides); the policy that maps them to a diff baseline is a workflow-layer fact (gunbc.diff_baseline), not modeled here (extdeps must not depend upward — DESIGN §3(c))." + +data github_event_name_env: NonEmptyStr = "GITHUB_EVENT_NAME" + +data github_base_ref_env: NonEmptyStr = "GITHUB_BASE_REF" + +data github_event_name_push: String = "push" + +data github_event_name_pull_request: String = "pull_request" + +data github_event_name_workflow_dispatch: String = "workflow_dispatch" + type Workflow { name: String on: List diff --git a/dag/gunbc/repo_identity.dag b/dag/gunbc/repo_identity.dag new file mode 100644 index 00000000000..aefcc13799c --- /dev/null +++ b/dag/gunbc/repo_identity.dag @@ -0,0 +1,19 @@ +module gunbc.repo_identity + +import std.types { String, GitRef } +import extdeps.git { GitRemoteRefParts, git_remote_ref, default_remote } + +data repo_identity_authority_note: String = "The single authority for this repo's default-branch and default-remote facts (DESIGN §3). Before this carrier the merge-target ref origin/main was a String literal forked across four workflow sites (gunbc.ci_diff_defaults.ci_merge_base_ref, gunbc.roadmap_dispatch_actuator.dispatch_git_remote_ref, and — transitively — gunbc.ci_spec.diff_policy.base and gunbc.merge_admission_produce.merge_admission_merge_base_ref), the doctrine's own flagship policy-as-literal tell (§3(c): 'a literal it should receive as a parameter — origin/main...HEAD'). All four now read gunbc_merge_target_ref here; the branch name reads gunbc_default_branch_name (gunbc.ci_workflow Push/PullRequest branch filters and gunbc.merge_admission gunbc_repo_standard.default_branch). Perturbing gunbc_default_branch_name moves every consumer — the anti-fork oracle (ci_spec_witness_test.witness_repo_identity_single_authority_perturbation)." + +data repo_identity_carrier_shape_note: String = "The composed ref is grounded on GitRemoteRefParts { remote, ref_name } — the exact structured subset git_remote_ref_parts already PRODUCES and git_fetch_no_tags_shell already CONSUMES — not on full extdeps.git GitBranch × GitRemote, which would force fabricated url / fetch_refspec / is_head / upstream fields no consumer reads (§2 anemic-inflation; §6 model just-in-time). git_remote_ref completes the §4 bidirectional parts↔ref relation (the forward reading of the same rows git_remote_ref_parts reads backward)." + +data gunbc_default_remote_name: String = default_remote + +data gunbc_default_branch_name: String = "main" + +data gunbc_merge_target: GitRemoteRefParts = GitRemoteRefParts { + remote: gunbc_default_remote_name, + ref_name: gunbc_default_branch_name, +} + +data gunbc_merge_target_ref: GitRef = git_remote_ref(parts: gunbc_merge_target) From 0ad253793a553270ccf5ccf41c6ae9d35c825eed Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 00:33:13 +0000 Subject: [PATCH 02/11] WIP: cleanup2 --- dag/gunbc/ci_diff_defaults.dag | 3 - dag/gunbc/ci_spec.dag | 6 +- dag/gunbc/ci_workflow.dag | 5 +- dag/gunbc/diff_baseline.dag | 102 +++++++++++++++++ dag/gunbc/merge_admission.dag | 3 +- dag/gunbc/merge_admission_produce.dag | 4 +- dag/gunbc/repo_identity.dag | 2 + dag/gunbc/roadmap_dispatch_actuator.dag | 3 +- dag/test/claim/diff_baseline_witness_test.dag | 106 ++++++++++++++++++ src/v2/test/claim/ci_spec_witness_test.dag | 23 +++- .../floor_diff_observe_witness_test.dag | 22 +--- src/v2/workflow/floor_diff_observe.dag | 99 +++++++++++----- 12 files changed, 321 insertions(+), 57 deletions(-) delete mode 100644 dag/gunbc/ci_diff_defaults.dag create mode 100644 dag/gunbc/diff_baseline.dag create mode 100644 dag/test/claim/diff_baseline_witness_test.dag diff --git a/dag/gunbc/ci_diff_defaults.dag b/dag/gunbc/ci_diff_defaults.dag deleted file mode 100644 index 63370d5762b..00000000000 --- a/dag/gunbc/ci_diff_defaults.dag +++ /dev/null @@ -1,3 +0,0 @@ -module gunbc.ci_diff_defaults - -data ci_merge_base_ref: String = "origin/main" diff --git a/dag/gunbc/ci_spec.dag b/dag/gunbc/ci_spec.dag index ec9df572d6a..073abbd0ecc 100644 --- a/dag/gunbc/ci_spec.dag +++ b/dag/gunbc/ci_spec.dag @@ -23,7 +23,7 @@ import gunbc.commit_workflow { project_ci_floor_witness_entries } import std.realization_schedule { ScheduleWitnessEntry } -import gunbc.ci_diff_defaults { ci_merge_base_ref } +import gunbc.repo_identity { gunbc_merge_target_ref } import gunbc.generated_artifact { committed_generated_artifact_paths } import gunbc.ci_failure_class { infra_retry_grep_alternation } import gunbc.ci_deploy_access { DeployAccess, ci_deploy_srv1_access } @@ -131,7 +131,7 @@ data gunbc_ci_spec: CiSpec = { witness_entries: gunbc_ci_floor_witness_entries, discovery_scan_dirs: witness_discovery_scan_dirs, diff_policy: { - base: ci_merge_base_ref, + base: gunbc_merge_target_ref as String, head: "HEAD", mode: DiffMergeBase }, @@ -144,7 +144,7 @@ data gunbc_ci_regen_spec: CiSpec = { witness_entries: [], discovery_scan_dirs: [], diff_policy: { - base: ci_merge_base_ref, + base: gunbc_merge_target_ref as String, head: "HEAD", mode: DiffMergeBase }, diff --git a/dag/gunbc/ci_workflow.dag b/dag/gunbc/ci_workflow.dag index 6619edabc8e..e02636025e9 100644 --- a/dag/gunbc/ci_workflow.dag +++ b/dag/gunbc/ci_workflow.dag @@ -39,6 +39,7 @@ import v2.workflow.ci_release_build_emit { ci_release_build_script } import std.disposition { Disposition, RealizationDispatch, Scaffold, SingleAuthority, Terminal } import std.decl_ref { DeclarationRef, WholeDeclaration } import std.types { Duration } +import gunbc.repo_identity { gunbc_default_branch_name } import extdeps.github.actions { Workflow, Job, Step, RunStep, UsesStep, WorkflowTrigger, Push, PullRequest, WorkflowDispatch, MergeGroup, @@ -633,9 +634,9 @@ data ci_workflow: Workflow = { name: "ci", on: [ WorkflowDispatch { inputs: [] }, - Push { branches: ["main"], paths: [] }, + Push { branches: [gunbc_default_branch_name], paths: [] }, PullRequest { - branches: ["main"], + branches: [gunbc_default_branch_name], types: [Opened, Synchronize, Reopened, ReadyForReview] }, MergeGroup diff --git a/dag/gunbc/diff_baseline.dag b/dag/gunbc/diff_baseline.dag new file mode 100644 index 00000000000..3d22e9663df --- /dev/null +++ b/dag/gunbc/diff_baseline.dag @@ -0,0 +1,102 @@ +module gunbc.diff_baseline + +import std.types { String, GitRef } +import std.logic { Bool } +import extdeps.git { GitRemoteRefParts, git_remote_ref } +import extdeps.github.actions { + github_event_name_pull_request, + github_event_name_push, + github_event_name_workflow_dispatch +} + +data diff_baseline_law: String = "DiffBaseline is the typed answer to 'what does the affected-set diff observe HEAD against?' — the de-fork of the origin/main policy-as-literal (DESIGN §3(c)). Three arms, no fourth default: MergeTarget (the PR's actual base, derived from the CI event's GITHUB_BASE_REF), PushParent (today's policy — the repo's default merge target, for push / workflow_dispatch / the local-or-bootstrap window with no CI event), OperatorOverride (the typed GUNBC_CI_DIFF_BASE arm, used by the falsifier's HEAD~20 cold control and manual runs). resolve_diff_baseline is PURE over the observed event facts (CiDiffEvent) so its arms are RED-testable without live git; the effectful env read lives in the caller (v2.workflow.floor_diff_observe.floor_observe_ci_diff_event)." + +data diff_baseline_fail_closed_law: String = "A CI event this resolver cannot map to a base REFUSES (BaselineRefused) — it never substitutes a constant. The refusal propagates through floor_diff_observe's UnifiedDiffFail / NameStatusDiffFail to the affected-set runner's DiffObservationFailClosed, whose every witness row is a per-row-counted Refused that RUNS the witness — i.e. widen-to-whole-tree, loud and counted, the floor's already-declared fail-closed arm (DESIGN §5: a failure arm refuses, never silently widens to a wrong constant). merge_group (queue ref, no base — ci_merge_group_trigger_note already declares 'falls through to the full floor') and any future/unknown event name land here. This is the exact defect being deleted (a silent origin/main constant standing where the true base was unknown), now typed." + +data diff_baseline_bootstrap_arm_note: String = "The empty-event-name arm ('' — no GITHUB_EVENT_NAME) is an EXPLICIT recognized state, not the catch-all: it is the local / pre-CI-bootstrap window where there is no GitHub event at all, and its correct baseline is the repo's default merge target (PushParent), which is exactly today's behavior for a bare local floor_diff_observe invocation (DiffPolicy.base = origin/main). It is grouped with push / workflow_dispatch because all three mean 'observe against the default branch'. The catch-all (a RECOGNIZED CI context carrying an event we have no arm for — ⊤-as-ignorance, genuinely not-knowing the base) is the final else → BaselineRefused. Conflating the two would be the absorbing fallback DESIGN §5 forbids; keeping them distinct keeps 'no CI event' (a known state) apart from 'CI event we cannot map' (real ignorance)." + +type DiffBaseline + = MergeTarget { ref: GitRef } + | PushParent { ref: GitRef } + | OperatorOverride { ref: GitRef } + +type CiDiffEvent { + override_ref: String? + event_name: String + base_ref: String? +} + +type DiffBaselineResolution + = BaselineSelected { baseline: DiffBaseline } + | BaselineRefused { reason: String } + +fn diff_baseline_ref(b: DiffBaseline) -> GitRef { + match b { + MergeTarget { ref: r } => r + PushParent { ref: r } => r + OperatorOverride { ref: r } => r + } +} + +fn resolve_merge_target(base_ref: String?, default_remote_name: String) -> DiffBaselineResolution { + match base_ref { + Present { value: b } => + if b == "" { + BaselineRefused { reason: "pull_request event but GITHUB_BASE_REF is empty — cannot derive merge target; widening to whole-tree" } + } else { + BaselineSelected { + baseline: MergeTarget { + ref: git_remote_ref(parts: GitRemoteRefParts { remote: default_remote_name, ref_name: b }) + } + } + } + Absent => + BaselineRefused { reason: "pull_request event but GITHUB_BASE_REF is unset — cannot derive merge target; widening to whole-tree" } + } +} + +fn resolve_diff_baseline_by_event( + event_name: String, + base_ref: String?, + push_parent_ref: GitRef, + default_remote_name: String +) -> DiffBaselineResolution { + if event_name == github_event_name_pull_request { + resolve_merge_target(base_ref: base_ref, default_remote_name: default_remote_name) + } else if event_name == github_event_name_push + || event_name == github_event_name_workflow_dispatch + || event_name == "" { + BaselineSelected { baseline: PushParent { ref: push_parent_ref } } + } else { + BaselineRefused { + reason: concat(concat("unrecognized CI event '", event_name), "' for diff-baseline selection — widening to whole-tree") + } + } +} + +fn resolve_diff_baseline( + event: CiDiffEvent, + push_parent_ref: GitRef, + default_remote_name: String +) -> DiffBaselineResolution { + match event.override_ref { + Present { value: r } => + if r == "" { + resolve_diff_baseline_by_event( + event_name: event.event_name, + base_ref: event.base_ref, + push_parent_ref: push_parent_ref, + default_remote_name: default_remote_name + ) + } else { + BaselineSelected { baseline: OperatorOverride { ref: r as GitRef } } + } + Absent => + resolve_diff_baseline_by_event( + event_name: event.event_name, + base_ref: event.base_ref, + push_parent_ref: push_parent_ref, + default_remote_name: default_remote_name + ) + } +} diff --git a/dag/gunbc/merge_admission.dag b/dag/gunbc/merge_admission.dag index 828be5675d3..ed69b3d0d92 100644 --- a/dag/gunbc/merge_admission.dag +++ b/dag/gunbc/merge_admission.dag @@ -25,6 +25,7 @@ import gunbc.ci_gate { import std.content_hash { content_hash_atom, content_hash_combine, content_hash_tagged } import std.disposition { Disposition, Scaffold, SingleAuthority } import std.decl_ref { DeclarationRef, WholeDeclaration } +import gunbc.repo_identity { gunbc_default_branch_name } type MergeStrategy = SquashMerge @@ -53,7 +54,7 @@ type AdmissionPolicy | KeyedReceipt data gunbc_repo_standard: RepoStandard = RepoStandard { - default_branch: "main", + default_branch: gunbc_default_branch_name, allowed_strategies: [SquashMerge], require_up_to_date: false, merge_queue_required: false, diff --git a/dag/gunbc/merge_admission_produce.dag b/dag/gunbc/merge_admission_produce.dag index b6d62e3de42..9b186ba2e30 100644 --- a/dag/gunbc/merge_admission_produce.dag +++ b/dag/gunbc/merge_admission_produce.dag @@ -3,7 +3,7 @@ module gunbc.merge_admission_produce import std.types { ContentHash, CommitSha, String, Int, List, Bool, GitRef } import std.disposition { Disposition, Scaffold, SingleAuthority } import std.decl_ref { DeclarationRef, WholeDeclaration } -import gunbc.ci_diff_defaults { ci_merge_base_ref } +import gunbc.repo_identity { gunbc_merge_target_ref } import extdeps.git import extdeps.github.checks { CheckConclusion, @@ -20,7 +20,7 @@ import gunbc.merge_admission { } import gunbc.ci_layer_roots { witness_layer_roots, witness_layer_source_flags, witness_layer_source_flags_rooted } -data merge_admission_merge_base_ref: String = ci_merge_base_ref +data merge_admission_merge_base_ref: String = gunbc_merge_target_ref as String data merge_admission_receipt_schema: String = "gunbc.merge_admission_receipt.v1" diff --git a/dag/gunbc/repo_identity.dag b/dag/gunbc/repo_identity.dag index aefcc13799c..d3ddda390fb 100644 --- a/dag/gunbc/repo_identity.dag +++ b/dag/gunbc/repo_identity.dag @@ -7,6 +7,8 @@ data repo_identity_authority_note: String = "The single authority for this repo' data repo_identity_carrier_shape_note: String = "The composed ref is grounded on GitRemoteRefParts { remote, ref_name } — the exact structured subset git_remote_ref_parts already PRODUCES and git_fetch_no_tags_shell already CONSUMES — not on full extdeps.git GitBranch × GitRemote, which would force fabricated url / fetch_refspec / is_head / upstream fields no consumer reads (§2 anemic-inflation; §6 model just-in-time). git_remote_ref completes the §4 bidirectional parts↔ref relation (the forward reading of the same rows git_remote_ref_parts reads backward)." +data repo_identity_section_3c_discharge_note: String = "DISCHARGED 2026-07-24: DESIGN §3(c)'s own flagship policy-as-literal tell — the forked origin/main merge-base String, gunbc.ci_diff_defaults deleted — was consolidated onto this single authority. The remaining origin/main literals in the tree are prose (this note, DESIGN §3(c)'s doctrinal example) and test oracles (roadmap_dispatch_actuator_witness / affected_set_floor_runner_test expected values), which are history and value-oracles, not carriers. The recorded mark IS the carrier per §6 (no parallel-ledger intake doc). Displaced cost: #7129's probe branch, cut off a PR head, could not get an ordinary-diff run because the base was a constant origin/main instead of the PR's true base; gunbc.diff_baseline's MergeTarget arm derives it from the CI event (this PR is the enabling dependency for that probe)." + data gunbc_default_remote_name: String = default_remote data gunbc_default_branch_name: String = "main" diff --git a/dag/gunbc/roadmap_dispatch_actuator.dag b/dag/gunbc/roadmap_dispatch_actuator.dag index f2a48492505..87ca4acb8cd 100644 --- a/dag/gunbc/roadmap_dispatch_actuator.dag +++ b/dag/gunbc/roadmap_dispatch_actuator.dag @@ -46,6 +46,7 @@ import extdeps.llm.cli { shape_claude_invoke_argv } import std.disposition { Disposition, Scaffold, RealizationDispatch } import std.decl_ref { DeclarationRef, WholeDeclaration } import gunbc.host_layout { srv1_dispatch_worktree_root } +import gunbc.repo_identity { gunbc_merge_target_ref } data dispatch_tmux_process_fingerprint_observation_dissolution_trigger: Disposition = Scaffold { dissolves_to: RealizationDispatch, @@ -61,7 +62,7 @@ data dispatch_repo: String = "gunbc" data dispatch_worktree_root_note: String = "PROJECTION of gunbc.host_layout.srv1_dispatch_worktree_root — the single path authority shared with the live_deploy membership that provisions the directory (DESIGN §3; its former private copy deleted, belt-B lane 2026-07-20)." data dispatch_worktree_root: String = srv1_dispatch_worktree_root as String -data dispatch_git_remote_ref: String = "origin/main" +data dispatch_git_remote_ref: String = gunbc_merge_target_ref as String data dispatch_tmux_session_prefix: String = "gunbc-dispatch-" data dispatch_claude_process_fingerprint: NonEmptyStr = "claude" as NonEmptyStr data claude_skip_permission_settings_json: String = "{\"skipDangerousModePermissionPrompt\":true}" diff --git a/dag/test/claim/diff_baseline_witness_test.dag b/dag/test/claim/diff_baseline_witness_test.dag new file mode 100644 index 00000000000..82ee66e307a --- /dev/null +++ b/dag/test/claim/diff_baseline_witness_test.dag @@ -0,0 +1,106 @@ +module test.claim.diff_baseline_witness + +import std.logic { Bool } +import std.types { String, GitRef } +import gunbc.diff_baseline { + CiDiffEvent, + DiffBaseline, + DiffBaselineResolution, + MergeTarget, + PushParent, + OperatorOverride, + BaselineSelected, + BaselineRefused, + resolve_diff_baseline, + diff_baseline_ref +} +import gunbc.repo_identity { gunbc_merge_target_ref, gunbc_default_remote_name } +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +fn resolve_case(override_ref: String?, event_name: String, base_ref: String?) -> DiffBaselineResolution { + resolve_diff_baseline( + event: CiDiffEvent { override_ref: override_ref, event_name: event_name, base_ref: base_ref }, + push_parent_ref: gunbc_merge_target_ref, + default_remote_name: gunbc_default_remote_name + ) +} + +fn arm_tag(res: DiffBaselineResolution) -> String { + match res { + BaselineSelected { baseline: MergeTarget { ref: _ } } => "merge_target" + BaselineSelected { baseline: PushParent { ref: _ } } => "push_parent" + BaselineSelected { baseline: OperatorOverride { ref: _ } } => "operator_override" + BaselineRefused { reason: _ } => "refused" + } +} + +fn selected_ref(res: DiffBaselineResolution) -> String { + match res { + BaselineSelected { baseline: b } => diff_baseline_ref(b: b) as String + BaselineRefused { reason: _ } => "<>" + } +} + +fn witness_stacked_pr_selects_actual_base() -> Bool { + let res = resolve_case(override_ref: none, event_name: "pull_request", base_ref: Present { value: "feature/B" }) + arm_tag(res: res) == "merge_target" + && selected_ref(res: res) == "origin/feature/B" + && selected_ref(res: res) != "origin/main" +} + +fn witness_main_pr_equivalent_to_push_parent() -> Bool { + let res = resolve_case(override_ref: none, event_name: "pull_request", base_ref: Present { value: "main" }) + arm_tag(res: res) == "merge_target" + && selected_ref(res: res) == "origin/main" + && selected_ref(res: res) == (gunbc_merge_target_ref as String) +} + +fn witness_push_keeps_todays_policy() -> Bool { + let res = resolve_case(override_ref: none, event_name: "push", base_ref: none) + arm_tag(res: res) == "push_parent" + && selected_ref(res: res) == "origin/main" +} + +fn witness_workflow_dispatch_keeps_todays_policy() -> Bool { + let res = resolve_case(override_ref: none, event_name: "workflow_dispatch", base_ref: none) + arm_tag(res: res) == "push_parent" + && selected_ref(res: res) == "origin/main" +} + +fn witness_bootstrap_no_event_is_push_parent() -> Bool { + let res = resolve_case(override_ref: none, event_name: "", base_ref: none) + arm_tag(res: res) == "push_parent" + && selected_ref(res: res) == "origin/main" +} + +fn witness_operator_override_is_typed_arm() -> Bool { + let res = resolve_case(override_ref: Present { value: "HEAD~20" }, event_name: "schedule", base_ref: none) + arm_tag(res: res) == "operator_override" + && selected_ref(res: res) == "HEAD~20" +} + +fn witness_merge_group_refuses_to_whole_tree() -> Bool { + arm_tag(res: resolve_case(override_ref: none, event_name: "merge_group", base_ref: none)) == "refused" +} + +fn witness_pull_request_empty_base_refuses() -> Bool { + arm_tag(res: resolve_case(override_ref: none, event_name: "pull_request", base_ref: Present { value: "" })) == "refused" +} + +fn witness_pull_request_absent_base_refuses() -> Bool { + arm_tag(res: resolve_case(override_ref: none, event_name: "pull_request", base_ref: none)) == "refused" +} + +test fn diff_baseline_resolution_holds() -> Bool { + witness_stacked_pr_selects_actual_base() + && witness_main_pr_equivalent_to_push_parent() + && witness_push_keeps_todays_policy() + && witness_workflow_dispatch_keeps_todays_policy() + && witness_bootstrap_no_event_is_push_parent() + && witness_operator_override_is_typed_arm() + && witness_merge_group_refuses_to_whole_tree() + && witness_pull_request_empty_base_refuses() + && witness_pull_request_absent_base_refuses() +} diff --git a/src/v2/test/claim/ci_spec_witness_test.dag b/src/v2/test/claim/ci_spec_witness_test.dag index e6ec48f345f..7d1765c19b9 100644 --- a/src/v2/test/claim/ci_spec_witness_test.dag +++ b/src/v2/test/claim/ci_spec_witness_test.dag @@ -17,7 +17,12 @@ import gunbc.ci_spec { ci_documentation_only_floor_shortcut_retired_note, } import v2.workflow.ci_release_build_emit { gunbc_ci_run_script, ci_release_build_script } -import gunbc.ci_diff_defaults { ci_merge_base_ref } +import gunbc.repo_identity { + gunbc_merge_target_ref, + gunbc_default_remote_name, + gunbc_default_branch_name, +} +import extdeps.git { GitRemoteRefParts, git_remote_ref } import gunbc.ci_materialization { ci_floor_resolve_receipt_gate_script, ci_floor_materialization_receipt_gate_script, @@ -209,7 +214,20 @@ fn witness_documentation_only_floor_shortcut_retired() -> Bool { fn witness_merge_base_ref_single_authority() -> Bool { merge_admission_merge_base_ref == gunbc_ci_spec.diff_policy.base - && merge_admission_merge_base_ref == ci_merge_base_ref + && merge_admission_merge_base_ref == (gunbc_merge_target_ref as String) + && (gunbc_merge_target_ref as String) == "origin/main" +} + +fn witness_repo_identity_single_authority_perturbation() -> Bool { + let real = git_remote_ref( + parts: GitRemoteRefParts { remote: gunbc_default_remote_name, ref_name: gunbc_default_branch_name } + ) + let perturbed = git_remote_ref( + parts: GitRemoteRefParts { remote: gunbc_default_remote_name, ref_name: "develop" } + ) + (real as String) == (gunbc_merge_target_ref as String) + && (real as String) != (perturbed as String) + && (perturbed as String) == "origin/develop" } fn witness_documentation_only_gate_skip_prefix_dissolve_on_named() -> Bool { @@ -275,6 +293,7 @@ test fn ci_spec_witnesses() -> Bool { witness_floor_disposition_marker_init_dissolve_on_named() && witness_floor_disposition_marker_init_emits_dissolve_on_in_floor_runner() && witness_merge_base_ref_single_authority() && + witness_repo_identity_single_authority_perturbation() && witness_documentation_only_gate_skip_prefix_dissolve_on_named() && witness_documentation_only_gate_skip_emits_dissolve_on_in_runners() && witness_collapsed_run_script_is_build_plus_floor() && diff --git a/src/v2/test/claim/execution/floor_diff_observe_witness_test.dag b/src/v2/test/claim/execution/floor_diff_observe_witness_test.dag index 7e4d245acc6..3c4e8aaf0a2 100644 --- a/src/v2/test/claim/execution/floor_diff_observe_witness_test.dag +++ b/src/v2/test/claim/execution/floor_diff_observe_witness_test.dag @@ -1,7 +1,7 @@ module v2.test.execution.floor_diff_observe_witness import std.logic { Bool } -import gunbc.ci_spec { DiffPolicy, DiffMergeBase } +import gunbc.ci_spec { DiffMergeBase } import v2.workflow.floor_diff_observe { FloorUnifiedDiffResult, UnifiedDiffOk, @@ -9,9 +9,9 @@ import v2.workflow.floor_diff_observe { FloorNameStatusDiffResult, NameStatusDiffOk, NameStatusDiffFail, - floor_observe_git_diff_unified, + floor_run_git_diff_unified, + floor_run_git_diff_name_status, floor_observe_git_diff_unified_for_ci, - floor_observe_git_diff_name_status, floor_observe_git_diff_name_status_for_ci } import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } @@ -26,13 +26,7 @@ fn witness_ci_policy_observation_succeeds() -> Bool { } fn witness_invalid_base_fails_closed() -> Bool { - match floor_observe_git_diff_unified( - policy: DiffPolicy { - base: "__gunbc_invalid_diff_base__", - head: "HEAD", - mode: DiffMergeBase - } - ) { + match floor_run_git_diff_unified(base: "__gunbc_invalid_diff_base__", head: "HEAD", mode: DiffMergeBase) { UnifiedDiffFail { reason: _ } => true UnifiedDiffOk { text: _ } => false } @@ -46,13 +40,7 @@ fn witness_ci_policy_name_status_observation_succeeds() -> Bool { } fn witness_invalid_base_name_status_fails_closed() -> Bool { - match floor_observe_git_diff_name_status( - policy: DiffPolicy { - base: "__gunbc_invalid_diff_base__", - head: "HEAD", - mode: DiffMergeBase - } - ) { + match floor_run_git_diff_name_status(base: "__gunbc_invalid_diff_base__", head: "HEAD", mode: DiffMergeBase) { NameStatusDiffFail { reason: _ } => true NameStatusDiffOk { changed_paths: _, departed_paths: _ } => false } diff --git a/src/v2/workflow/floor_diff_observe.dag b/src/v2/workflow/floor_diff_observe.dag index dd751175070..89ec1329e96 100644 --- a/src/v2/workflow/floor_diff_observe.dag +++ b/src/v2/workflow/floor_diff_observe.dag @@ -7,7 +7,15 @@ import gunbc.ci_spec { DiffTwoDot, gunbc_ci_spec } -import std.types { String, NonEmptyStr } +import gunbc.diff_baseline { + CiDiffEvent, + DiffBaselineResolution, + BaselineSelected, + BaselineRefused, + resolve_diff_baseline, + diff_baseline_ref +} +import std.types { String, NonEmptyStr, GitRef } import std.logic { Bool } import extdeps.git import extdeps.git { @@ -20,8 +28,10 @@ import extdeps.git { git_diff_status_entries_touched_paths, git_diff_status_entries_departed_paths, git_diff_status_entries_any_unknown, - git_diff_name_status_field_separator + git_diff_name_status_field_separator, + git_remote_ref_parts } +import extdeps.github.actions { github_event_name_env, github_base_ref_env } import extdeps.shell type FloorUnifiedDiffResult @@ -40,8 +50,27 @@ fn floor_env_override_or(env_name: NonEmptyStr, default: String) -> String { } } -fn floor_resolved_base(policy: DiffPolicy) -> String { - floor_env_override_or(env_name: "GUNBC_CI_DIFF_BASE" as NonEmptyStr, default: policy.base) +fn floor_env_optional(env_name: NonEmptyStr) -> String? { + shell.Env.Get(name: env_name).value +} + +data floor_diff_baseline_law: String = "The affected-set base is RESOLVED from the CI event, not a constant (gunbc.diff_baseline; the de-fork of the origin/main policy-as-literal, DESIGN §3(c)). floor_observe_ci_diff_event reads the three env facts — GUNBC_CI_DIFF_BASE (the gunbc OperatorOverride channel, e.g. the falsifier's HEAD~20 cold control), GITHUB_EVENT_NAME, GITHUB_BASE_REF (the GitHub surface extdeps.github.actions owns) — and resolve_diff_baseline (pure) maps them: pull_request → MergeTarget against the PR's ACTUAL base (was silently origin/main — the stacked-PR over-selection defect #7129 hit); push / workflow_dispatch / local-bootstrap → PushParent (today's DiffPolicy.base, origin/main); GUNBC_CI_DIFF_BASE → OperatorOverride. An unmappable event (merge_group, unknown) yields BaselineRefused → UnifiedDiffFail / NameStatusDiffFail → the runner's DiffObservationFailClosed → per-row-counted whole-tree, loud (DESIGN §5). The PushParent ref carries its own remote, so the MergeTarget remote is derived from it (git_remote_ref_parts) rather than re-imported." + +fn floor_observe_ci_diff_event() -> CiDiffEvent { + CiDiffEvent { + override_ref: floor_env_optional(env_name: "GUNBC_CI_DIFF_BASE" as NonEmptyStr), + event_name: floor_env_override_or(env_name: github_event_name_env, default: ""), + base_ref: floor_env_optional(env_name: github_base_ref_env) + } +} + +fn floor_resolve_baseline(policy: DiffPolicy) -> DiffBaselineResolution { + let push_parent = policy.base as GitRef + resolve_diff_baseline( + event: floor_observe_ci_diff_event(), + push_parent_ref: push_parent, + default_remote_name: git_remote_ref_parts(ref: push_parent).remote + ) } fn floor_resolved_head(policy: DiffPolicy) -> String { @@ -55,20 +84,29 @@ fn floor_git_diff_range_of_mode(mode: DiffMode) -> GitDiffRange { } } +fn floor_run_git_diff_unified(base: String, head: String, mode: DiffMode) -> FloorUnifiedDiffResult { + let result = git.Core.DiffUnified0(base: base, head: head, range: floor_git_diff_range_of_mode(mode: mode)) + if result.success { + UnifiedDiffOk { text: result.diff } + } else { + UnifiedDiffFail { reason: "git diff -U0 exited nonzero: invalid ref or not a git repository" } + } +} + fn floor_observe_git_diff_unified(policy: DiffPolicy) -> FloorUnifiedDiffResult { let unified_injection = shell.Env.Get(name: "GUNBC_CI_DIFF_UNIFIED" as NonEmptyStr) match unified_injection.value { Present { value: injected } => UnifiedDiffOk { text: injected } - Absent => { - let base = floor_resolved_base(policy: policy) - let head = floor_resolved_head(policy: policy) - let result = git.Core.DiffUnified0(base: base, head: head, range: floor_git_diff_range_of_mode(mode: policy.mode)) - if result.success { - UnifiedDiffOk { text: result.diff } - } else { - UnifiedDiffFail { reason: "git diff -U0 exited nonzero: invalid ref or not a git repository" } + Absent => + match floor_resolve_baseline(policy: policy) { + BaselineRefused { reason: reason } => UnifiedDiffFail { reason: reason } + BaselineSelected { baseline: baseline } => + floor_run_git_diff_unified( + base: diff_baseline_ref(b: baseline) as String, + head: floor_resolved_head(policy: policy), + mode: policy.mode + ) } - } } } @@ -96,25 +134,34 @@ fn floor_decode_injected_name_status(injected: String) -> String { join(split(s: injected, delimiter: "\\000"), git_diff_name_status_field_separator) } +fn floor_run_git_diff_name_status(base: String, head: String, mode: DiffMode) -> FloorNameStatusDiffResult { + let result = git.Core.DiffNameStatus( + base: base, + head: head, + range: floor_git_diff_range_of_mode(mode: mode) + ) + if !result.success { + NameStatusDiffFail { reason: "git diff --name-status -z exited nonzero: invalid ref or not a git repository" } + } else { + floor_name_status_from_raw(raw: result.raw) + } +} + fn floor_observe_git_diff_name_status(policy: DiffPolicy) -> FloorNameStatusDiffResult { let name_status_injection = shell.Env.Get(name: "GUNBC_CI_DIFF_NAME_STATUS" as NonEmptyStr) match name_status_injection.value { Present { value: injected } => floor_name_status_from_raw(raw: floor_decode_injected_name_status(injected: injected)) - Absent => { - let base = floor_resolved_base(policy: policy) - let head = floor_resolved_head(policy: policy) - let result = git.Core.DiffNameStatus( - base: base, - head: head, - range: floor_git_diff_range_of_mode(mode: policy.mode) - ) - if !result.success { - NameStatusDiffFail { reason: "git diff --name-status -z exited nonzero: invalid ref or not a git repository" } - } else { - floor_name_status_from_raw(raw: result.raw) + Absent => + match floor_resolve_baseline(policy: policy) { + BaselineRefused { reason: reason } => NameStatusDiffFail { reason: reason } + BaselineSelected { baseline: baseline } => + floor_run_git_diff_name_status( + base: diff_baseline_ref(b: baseline) as String, + head: floor_resolved_head(policy: policy), + mode: policy.mode + ) } - } } } From aa8f8b930a356f3f603e643522a138fe38311d6b Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 00:55:21 +0000 Subject: [PATCH 03/11] WIP: cleanup2 --- src/v2/compiler/self_host/witness_entry_eligibility_census.dag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v2/compiler/self_host/witness_entry_eligibility_census.dag b/src/v2/compiler/self_host/witness_entry_eligibility_census.dag index 0dd57e8bfa8..2154b282332 100644 --- a/src/v2/compiler/self_host/witness_entry_eligibility_census.dag +++ b/src/v2/compiler/self_host/witness_entry_eligibility_census.dag @@ -36,7 +36,7 @@ data witness_entry_eligibility_census_histogram_path: String = "docs/probes/witn data witness_entry_eligibility_census_carrier_path_dissolve_on: String = "cli_run/emit HAND-RUST rel literals mirror these rows until load-time projection (review 41784); delete mirrors when wired" -data witness_entry_eligibility_census_entry_count: Int = 880 +data witness_entry_eligibility_census_entry_count: Int = 881 data witness_entry_eligibility_census_stamp: String = "2026-07-23T16:10Z" From 5ed7f8cfe8cc5753aaf457c03a333c1d4cf387f2 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 00:56:29 +0000 Subject: [PATCH 04/11] Register diff_baseline_witness_test in witness eligibility census MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New witness entry dag/test/claim/diff_baseline_witness_test.dag needs a census row (fail-closed registration wall, DESIGN §5). Bumped the count constant to 881 and regenerated the TSV + histogram from the .dag authority. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/probes/witness_entry_eligibility_census.tsv | 3 ++- docs/probes/witness_entry_eligibility_histogram.txt | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/probes/witness_entry_eligibility_census.tsv b/docs/probes/witness_entry_eligibility_census.tsv index 22ecd198491..abf70dcf33c 100644 --- a/docs/probes/witness_entry_eligibility_census.tsv +++ b/docs/probes/witness_entry_eligibility_census.tsv @@ -1,4 +1,4 @@ -# witness_entry_eligibility_census stamp=2026-07-23T19:48Z grain=entry_closure roots=witness_layer_roots(test.dag with test fn/data) +# witness_entry_eligibility_census stamp=2026-07-24T00:55Z grain=entry_closure roots=witness_layer_roots(test.dag with test fn/data) entry module_path subject_module subject_decl disposition retained_or_ineligible_reason first_error_class execution_leg dag/test/claim/accelerator_demo_execution_witness_test.dag test.claim.accelerator_demo_execution_witness test.claim.accelerator_demo_execution_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg dag/test/claim/accelerator_demo_gpu_witness_test.dag test.claim.accelerator_demo_gpu_witness test.claim.accelerator_demo_gpu_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg @@ -85,6 +85,7 @@ dag/test/claim/design_palette_witness_test.dag test.claim.design_palette_witness dag/test/claim/design_register_lift_parity_witness_test.dag test.claim.design_register_lift_parity_witness test.claim.design_register_lift_parity_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg dag/test/claim/dhcp_v4_mac_pinned_witness_test.dag test.claim.dhcp_v4_mac_pinned_witness test.claim.dhcp_v4_mac_pinned_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg dag/test/claim/diagnostics_test.dag test.claim.diagnostics_test test.claim.diagnostics_test witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg +dag/test/claim/diff_baseline_witness_test.dag test.claim.diff_baseline_witness test.claim.diff_baseline_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg dag/test/claim/dispatch_presentation_witness_test.dag test.claim.dispatch_presentation_witness test.claim.dispatch_presentation_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg dag/test/claim/doc_reachability_witness_test.dag test.claim.doc_reachability_witness test.claim.doc_reachability_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg dag/test/claim/docker_container_stats_witness_test.dag test.claim.docker_container_stats_witness test.claim.docker_container_stats_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg diff --git a/docs/probes/witness_entry_eligibility_histogram.txt b/docs/probes/witness_entry_eligibility_histogram.txt index 83625daeacd..ed51f488b4e 100644 --- a/docs/probes/witness_entry_eligibility_histogram.txt +++ b/docs/probes/witness_entry_eligibility_histogram.txt @@ -1,6 +1,6 @@ -# witness_entry_eligibility_histogram stamp=2026-07-23T19:48Z total_entries=880 +# witness_entry_eligibility_histogram stamp=2026-07-24T00:55Z total_entries=881 disposition reason count -InterpretedRetained BulkFlipPendingCensusIncomplete 700 +InterpretedRetained BulkFlipPendingCensusIncomplete 701 EmitIneligible OfflineLocalRecipe 82 EmitIneligible LongLaneScheduled 64 InterpretedRetained EmitOnDemandFamilyGrain 26 From 4d42762f931833328522f11530a6608ecb71485d Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 01:58:18 +0000 Subject: [PATCH 05/11] WIP: cleanup2 --- .../claim/self_host/witness_entry_eligibility_census_test.dag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v2/test/claim/self_host/witness_entry_eligibility_census_test.dag b/src/v2/test/claim/self_host/witness_entry_eligibility_census_test.dag index 356ba3b3869..e9b11f53cc0 100644 --- a/src/v2/test/claim/self_host/witness_entry_eligibility_census_test.dag +++ b/src/v2/test/claim/self_host/witness_entry_eligibility_census_test.dag @@ -12,11 +12,11 @@ import v2.compiler.self_host.witness_bulk_routing { } import v2.std.algebra { length } -data witness_entry_eligibility_census_test_note: String = "Census receipt: full witness_layer_roots roster (880 entry closures; floor >=600 via witness_entry_eligibility_census_meets_floor) strictly exceeds the 16-entry stratified sample. Discovery exclusions do not shrink the census carrier — explicit-roster grains (execution/, long/, etc.) still need leg rows. ROADMAP 2a 744 totality is the bulk-flip dissolve trigger, not this Lane B landing witness. COUNT 876 -> 880 (CI floor endgame, 2026-07-23): +1 for cheap_gate_pool_test.dag (this PR) AND +3 healing main's latent census drift — main declared 876 while its live find was 879, undetected because affected-set selection skips this witness on PRs that do not touch its closure; this plumbing PR's affected set is the first to run it against the drifted tree. The count lives in four hand-synced copies (this literal, the note, witness_entry_eligibility_census_entry_count, the committed TSV rows) — a §3 parallel-representation the emit transport reconciles at regen but no CI witness walls between regens; restructuring is main's carrier, out of this PR's scope." +data witness_entry_eligibility_census_test_note: String = "Census receipt: full witness_layer_roots roster (881 entry closures; floor >=600 via witness_entry_eligibility_census_meets_floor) strictly exceeds the 16-entry stratified sample. Discovery exclusions do not shrink the census carrier — explicit-roster grains (execution/, long/, etc.) still need leg rows. ROADMAP 2a 744 totality is the bulk-flip dissolve trigger, not this Lane B landing witness. COUNT 876 -> 880 (CI floor endgame, 2026-07-23): +1 for cheap_gate_pool_test.dag (this PR) AND +3 healing main's latent census drift — main declared 876 while its live find was 879, undetected because affected-set selection skips this witness on PRs that do not touch its closure; this plumbing PR's affected set is the first to run it against the drifted tree. The count lives in four hand-synced copies (this literal, the note, witness_entry_eligibility_census_entry_count, the committed TSV rows) — a §3 parallel-representation the emit transport reconciles at regen but no CI witness walls between regens; restructuring is main's carrier, out of this PR's scope. COUNT 880 -> 881 (gunbc#7146, 2026-07-24): +1 for diff_baseline_witness_test.dag, the diff-baseline modeling cleanup's RED-control witness." test fn witness_entry_eligibility_census_count_holds() -> Bool { witness_entry_eligibility_census_meets_floor() - && witness_entry_eligibility_census_entry_count == 880 + && witness_entry_eligibility_census_entry_count == 881 && witness_entry_eligibility_census_entry_count > witness_bulk_entry_count_expected && length(xs: witness_bulk_routing_sample_roster) == witness_bulk_entry_count_expected } From 330727cb2c6b1be68f34acbfa2d81c0680214356 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 02:13:35 +0000 Subject: [PATCH 06/11] Canonicalize census TSV/histogram to 882 after merge collision The merge auto-combined both PRs' TSV rows (882) but left the histogram at total_entries=881 (one side's stale header). Regenerated both canonically from the .dag authority: 882 entries, InterpretedRetained/CensusPending 701->702 for diff_baseline_witness_test. Constant, test literal, note, and TSV now all agree at 882. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/probes/witness_entry_eligibility_census.tsv | 2 +- docs/probes/witness_entry_eligibility_histogram.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/probes/witness_entry_eligibility_census.tsv b/docs/probes/witness_entry_eligibility_census.tsv index 459535b2f8c..30b5a318e58 100644 --- a/docs/probes/witness_entry_eligibility_census.tsv +++ b/docs/probes/witness_entry_eligibility_census.tsv @@ -1,4 +1,4 @@ -# witness_entry_eligibility_census stamp=2026-07-24T00:55Z grain=entry_closure roots=witness_layer_roots(test.dag with test fn/data) +# witness_entry_eligibility_census stamp=2026-07-24T02:09Z grain=entry_closure roots=witness_layer_roots(test.dag with test fn/data) entry module_path subject_module subject_decl disposition retained_or_ineligible_reason first_error_class execution_leg dag/test/claim/accelerator_demo_execution_witness_test.dag test.claim.accelerator_demo_execution_witness test.claim.accelerator_demo_execution_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg dag/test/claim/accelerator_demo_gpu_witness_test.dag test.claim.accelerator_demo_gpu_witness test.claim.accelerator_demo_gpu_witness witness_entry InterpretedRetained BulkFlipPendingCensusIncomplete CensusPending InterpretedLeg diff --git a/docs/probes/witness_entry_eligibility_histogram.txt b/docs/probes/witness_entry_eligibility_histogram.txt index ed51f488b4e..017302b1daa 100644 --- a/docs/probes/witness_entry_eligibility_histogram.txt +++ b/docs/probes/witness_entry_eligibility_histogram.txt @@ -1,6 +1,6 @@ -# witness_entry_eligibility_histogram stamp=2026-07-24T00:55Z total_entries=881 +# witness_entry_eligibility_histogram stamp=2026-07-24T02:09Z total_entries=882 disposition reason count -InterpretedRetained BulkFlipPendingCensusIncomplete 701 +InterpretedRetained BulkFlipPendingCensusIncomplete 702 EmitIneligible OfflineLocalRecipe 82 EmitIneligible LongLaneScheduled 64 InterpretedRetained EmitOnDemandFamilyGrain 26 From 38d95bd887d186e310423b2b8c89ecf3ac829015 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 02:31:22 +0000 Subject: [PATCH 07/11] WIP: cleanup2 --- dag/extdeps/github/actions.dag | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dag/extdeps/github/actions.dag b/dag/extdeps/github/actions.dag index 03f32afd786..5b09811e946 100644 --- a/dag/extdeps/github/actions.dag +++ b/dag/extdeps/github/actions.dag @@ -45,6 +45,8 @@ data github_event_name_pull_request: String = "pull_request" data github_event_name_workflow_dispatch: String = "workflow_dispatch" +data github_event_name_merge_group: String = "merge_group" + type Workflow { name: String on: List From d9e729f6abf1f4e66e75b57f41c1b2498b149d61 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 02:35:11 +0000 Subject: [PATCH 08/11] Fix merge_group regression + correct fail-closed prose (review 42072) Finding 1 (merge_group): resolve_diff_baseline sent merge_group to BaselineRefused, but the executor propagates a diff-observation refusal as an Err that HALTS the floor (cli_run.rs floor_git_diff_range '?' -> AFFECTED-SET REFUSAL: refuses every enrolled row rather than widening). Pre-PR, merge_group used DiffPolicy.base (origin/main = PushParent) so the floor RAN. So merge_group -> BaselineRefused was a regression that would hard-abort every merge-queue run. Routed merge_group to the PushParent arm (its queue tree diffs against the default branch), restoring pre-PR behavior. The else -> refuse now catches only genuinely-unrecognized (future) events. Finding 2 (prose): three law notes claimed the refusal 'RUNS the witness - widen-to-whole-tree'. That is wrong: the executor HALTS the floor (refuses every enrolled row, never widens; operator ruling 2026-07-05). Corrected the prose in diff_baseline (diff_baseline_law, _fail_closed_law, _bootstrap_arm_note) and floor_diff_observe (floor_diff_baseline_law). Witness: merge_group -> push_parent (origin/main); added unknown_event -> refuse. Co-Authored-By: Claude Opus 4.8 (1M context) --- dag/gunbc/diff_baseline.dag | 12 +++++++----- dag/test/claim/diff_baseline_witness_test.dag | 13 ++++++++++--- src/v2/workflow/floor_diff_observe.dag | 2 +- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/dag/gunbc/diff_baseline.dag b/dag/gunbc/diff_baseline.dag index 3d22e9663df..c63853db6c4 100644 --- a/dag/gunbc/diff_baseline.dag +++ b/dag/gunbc/diff_baseline.dag @@ -6,14 +6,15 @@ import extdeps.git { GitRemoteRefParts, git_remote_ref } import extdeps.github.actions { github_event_name_pull_request, github_event_name_push, - github_event_name_workflow_dispatch + github_event_name_workflow_dispatch, + github_event_name_merge_group } -data diff_baseline_law: String = "DiffBaseline is the typed answer to 'what does the affected-set diff observe HEAD against?' — the de-fork of the origin/main policy-as-literal (DESIGN §3(c)). Three arms, no fourth default: MergeTarget (the PR's actual base, derived from the CI event's GITHUB_BASE_REF), PushParent (today's policy — the repo's default merge target, for push / workflow_dispatch / the local-or-bootstrap window with no CI event), OperatorOverride (the typed GUNBC_CI_DIFF_BASE arm, used by the falsifier's HEAD~20 cold control and manual runs). resolve_diff_baseline is PURE over the observed event facts (CiDiffEvent) so its arms are RED-testable without live git; the effectful env read lives in the caller (v2.workflow.floor_diff_observe.floor_observe_ci_diff_event)." +data diff_baseline_law: String = "DiffBaseline is the typed answer to 'what does the affected-set diff observe HEAD against?' — the de-fork of the origin/main policy-as-literal (DESIGN §3(c)). Three arms, no fourth default: MergeTarget (the PR's actual base, derived from the CI event's GITHUB_BASE_REF), PushParent (today's policy — the repo's default merge target, for push / workflow_dispatch / merge_group / the local-or-bootstrap window with no CI event; a merge_group queue run has no base ref and its tree diffs against the default branch, exactly the pre-de-fork behavior), OperatorOverride (the typed GUNBC_CI_DIFF_BASE arm, used by the falsifier's HEAD~20 cold control and manual runs). resolve_diff_baseline is PURE over the observed event facts (CiDiffEvent) so its arms are RED-testable without live git; the effectful env read lives in the caller (v2.workflow.floor_diff_observe.floor_observe_ci_diff_event)." -data diff_baseline_fail_closed_law: String = "A CI event this resolver cannot map to a base REFUSES (BaselineRefused) — it never substitutes a constant. The refusal propagates through floor_diff_observe's UnifiedDiffFail / NameStatusDiffFail to the affected-set runner's DiffObservationFailClosed, whose every witness row is a per-row-counted Refused that RUNS the witness — i.e. widen-to-whole-tree, loud and counted, the floor's already-declared fail-closed arm (DESIGN §5: a failure arm refuses, never silently widens to a wrong constant). merge_group (queue ref, no base — ci_merge_group_trigger_note already declares 'falls through to the full floor') and any future/unknown event name land here. This is the exact defect being deleted (a silent origin/main constant standing where the true base was unknown), now typed." +data diff_baseline_fail_closed_law: String = "A CI event this resolver cannot map to a base REFUSES (BaselineRefused) — it never substitutes a constant. The refusal propagates through floor_diff_observe's UnifiedDiffFail / NameStatusDiffFail into the executor's diff observation (cli_run.rs floor_git_diff_range), which HALTS the floor with a typed AFFECTED-SET REFUSAL (cause=DiffObservationRefusal): 'refuses every enrolled row rather than widening to a full-corpus run' (operator ruling 2026-07-05). The ignorance state is a loud, located, HARD STOP — NOT a run-everything widen (an earlier draft of this note misdescribed it as widen-to-whole-tree; the executor refuses, it does not widen — DESIGN §5, the exact absorbing-fallback shape being avoided). Only a genuinely-unrecognized event name lands here: the four workflow triggers (push / pull_request / workflow_dispatch / merge_group) all map to a base arm, so a future-added trigger halts loudly until it is modeled, rather than silently defaulting to origin/main — the exact defect being deleted, now typed." -data diff_baseline_bootstrap_arm_note: String = "The empty-event-name arm ('' — no GITHUB_EVENT_NAME) is an EXPLICIT recognized state, not the catch-all: it is the local / pre-CI-bootstrap window where there is no GitHub event at all, and its correct baseline is the repo's default merge target (PushParent), which is exactly today's behavior for a bare local floor_diff_observe invocation (DiffPolicy.base = origin/main). It is grouped with push / workflow_dispatch because all three mean 'observe against the default branch'. The catch-all (a RECOGNIZED CI context carrying an event we have no arm for — ⊤-as-ignorance, genuinely not-knowing the base) is the final else → BaselineRefused. Conflating the two would be the absorbing fallback DESIGN §5 forbids; keeping them distinct keeps 'no CI event' (a known state) apart from 'CI event we cannot map' (real ignorance)." +data diff_baseline_bootstrap_arm_note: String = "The empty-event-name arm ('' — no GITHUB_EVENT_NAME) is an EXPLICIT recognized state, not the catch-all: it is the local / pre-CI-bootstrap window where there is no GitHub event at all, and its correct baseline is the repo's default merge target (PushParent), which is exactly today's behavior for a bare local floor_diff_observe invocation (DiffPolicy.base = origin/main). It is grouped with push / workflow_dispatch / merge_group because all four mean 'observe against the default branch'. The catch-all (a future GitHub trigger not yet modeled — ⊤-as-ignorance, genuinely not-knowing the base) is the final else → BaselineRefused, which HALTS the floor (never a silent origin/main). Conflating the two would be the absorbing fallback DESIGN §5 forbids; keeping them distinct keeps 'no CI event' (a known state, PushParent) apart from 'CI event we cannot map' (real ignorance, halt)." type DiffBaseline = MergeTarget { ref: GitRef } @@ -65,11 +66,12 @@ fn resolve_diff_baseline_by_event( resolve_merge_target(base_ref: base_ref, default_remote_name: default_remote_name) } else if event_name == github_event_name_push || event_name == github_event_name_workflow_dispatch + || event_name == github_event_name_merge_group || event_name == "" { BaselineSelected { baseline: PushParent { ref: push_parent_ref } } } else { BaselineRefused { - reason: concat(concat("unrecognized CI event '", event_name), "' for diff-baseline selection — widening to whole-tree") + reason: concat(concat("unrecognized CI event '", event_name), "' for diff-baseline selection — halting the floor (AFFECTED-SET REFUSAL)") } } } diff --git a/dag/test/claim/diff_baseline_witness_test.dag b/dag/test/claim/diff_baseline_witness_test.dag index 82ee66e307a..8619852dd80 100644 --- a/dag/test/claim/diff_baseline_witness_test.dag +++ b/dag/test/claim/diff_baseline_witness_test.dag @@ -81,8 +81,14 @@ fn witness_operator_override_is_typed_arm() -> Bool { && selected_ref(res: res) == "HEAD~20" } -fn witness_merge_group_refuses_to_whole_tree() -> Bool { - arm_tag(res: resolve_case(override_ref: none, event_name: "merge_group", base_ref: none)) == "refused" +fn witness_merge_group_uses_push_parent() -> Bool { + let res = resolve_case(override_ref: none, event_name: "merge_group", base_ref: none) + arm_tag(res: res) == "push_parent" + && selected_ref(res: res) == "origin/main" +} + +fn witness_unknown_event_refuses() -> Bool { + arm_tag(res: resolve_case(override_ref: none, event_name: "deployment_status", base_ref: none)) == "refused" } fn witness_pull_request_empty_base_refuses() -> Bool { @@ -100,7 +106,8 @@ test fn diff_baseline_resolution_holds() -> Bool { && witness_workflow_dispatch_keeps_todays_policy() && witness_bootstrap_no_event_is_push_parent() && witness_operator_override_is_typed_arm() - && witness_merge_group_refuses_to_whole_tree() + && witness_merge_group_uses_push_parent() + && witness_unknown_event_refuses() && witness_pull_request_empty_base_refuses() && witness_pull_request_absent_base_refuses() } diff --git a/src/v2/workflow/floor_diff_observe.dag b/src/v2/workflow/floor_diff_observe.dag index 89ec1329e96..840406b901f 100644 --- a/src/v2/workflow/floor_diff_observe.dag +++ b/src/v2/workflow/floor_diff_observe.dag @@ -54,7 +54,7 @@ fn floor_env_optional(env_name: NonEmptyStr) -> String? { shell.Env.Get(name: env_name).value } -data floor_diff_baseline_law: String = "The affected-set base is RESOLVED from the CI event, not a constant (gunbc.diff_baseline; the de-fork of the origin/main policy-as-literal, DESIGN §3(c)). floor_observe_ci_diff_event reads the three env facts — GUNBC_CI_DIFF_BASE (the gunbc OperatorOverride channel, e.g. the falsifier's HEAD~20 cold control), GITHUB_EVENT_NAME, GITHUB_BASE_REF (the GitHub surface extdeps.github.actions owns) — and resolve_diff_baseline (pure) maps them: pull_request → MergeTarget against the PR's ACTUAL base (was silently origin/main — the stacked-PR over-selection defect #7129 hit); push / workflow_dispatch / local-bootstrap → PushParent (today's DiffPolicy.base, origin/main); GUNBC_CI_DIFF_BASE → OperatorOverride. An unmappable event (merge_group, unknown) yields BaselineRefused → UnifiedDiffFail / NameStatusDiffFail → the runner's DiffObservationFailClosed → per-row-counted whole-tree, loud (DESIGN §5). The PushParent ref carries its own remote, so the MergeTarget remote is derived from it (git_remote_ref_parts) rather than re-imported." +data floor_diff_baseline_law: String = "The affected-set base is RESOLVED from the CI event, not a constant (gunbc.diff_baseline; the de-fork of the origin/main policy-as-literal, DESIGN §3(c)). floor_observe_ci_diff_event reads the three env facts — GUNBC_CI_DIFF_BASE (the gunbc OperatorOverride channel, e.g. the falsifier's HEAD~20 cold control), GITHUB_EVENT_NAME, GITHUB_BASE_REF (the GitHub surface extdeps.github.actions owns) — and resolve_diff_baseline (pure) maps them: pull_request → MergeTarget against the PR's ACTUAL base (was silently origin/main — the stacked-PR over-selection defect #7129 hit); push / workflow_dispatch / merge_group / local-bootstrap → PushParent (today's DiffPolicy.base, origin/main — a merge_group queue run has no base ref and diffs its tree against the default branch, matching the pre-de-fork behavior so the floor RUNS rather than aborting). GUNBC_CI_DIFF_BASE → OperatorOverride. A genuinely-unrecognized event yields BaselineRefused → UnifiedDiffFail / NameStatusDiffFail → the executor HALTS the floor with a typed AFFECTED-SET REFUSAL (refuses every enrolled row, never widens to a full-corpus run; operator ruling 2026-07-05). The PushParent ref carries its own remote, so the MergeTarget remote is derived from it (git_remote_ref_parts) rather than re-imported." fn floor_observe_ci_diff_event() -> CiDiffEvent { CiDiffEvent { From 543186b34ecdd7d7f4b496889be5ede1ab2d7826 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 02:49:28 +0000 Subject: [PATCH 09/11] WIP: cleanup2 --- dag/gunbc/diff_baseline.dag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dag/gunbc/diff_baseline.dag b/dag/gunbc/diff_baseline.dag index c63853db6c4..8e8051fa84f 100644 --- a/dag/gunbc/diff_baseline.dag +++ b/dag/gunbc/diff_baseline.dag @@ -43,7 +43,7 @@ fn resolve_merge_target(base_ref: String?, default_remote_name: String) -> DiffB match base_ref { Present { value: b } => if b == "" { - BaselineRefused { reason: "pull_request event but GITHUB_BASE_REF is empty — cannot derive merge target; widening to whole-tree" } + BaselineRefused { reason: "pull_request event but GITHUB_BASE_REF is empty — cannot derive merge target; halting the floor (AFFECTED-SET REFUSAL)" } } else { BaselineSelected { baseline: MergeTarget { @@ -52,7 +52,7 @@ fn resolve_merge_target(base_ref: String?, default_remote_name: String) -> DiffB } } Absent => - BaselineRefused { reason: "pull_request event but GITHUB_BASE_REF is unset — cannot derive merge target; widening to whole-tree" } + BaselineRefused { reason: "pull_request event but GITHUB_BASE_REF is unset — cannot derive merge target; halting the floor (AFFECTED-SET REFUSAL)" } } } From 5ddc9881156f1aff35dd7af849c1358a4634010f Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 03:04:26 +0000 Subject: [PATCH 10/11] WIP: cleanup2 --- dag/extdeps/github/actions.dag | 2 ++ dag/gunbc/diff_baseline.dag | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dag/extdeps/github/actions.dag b/dag/extdeps/github/actions.dag index 5b09811e946..1c18a151fd3 100644 --- a/dag/extdeps/github/actions.dag +++ b/dag/extdeps/github/actions.dag @@ -47,6 +47,8 @@ data github_event_name_workflow_dispatch: String = "workflow_dispatch" data github_event_name_merge_group: String = "merge_group" +data github_event_name_schedule: String = "schedule" + type Workflow { name: String on: List diff --git a/dag/gunbc/diff_baseline.dag b/dag/gunbc/diff_baseline.dag index 8e8051fa84f..80dad64552b 100644 --- a/dag/gunbc/diff_baseline.dag +++ b/dag/gunbc/diff_baseline.dag @@ -7,7 +7,8 @@ import extdeps.github.actions { github_event_name_pull_request, github_event_name_push, github_event_name_workflow_dispatch, - github_event_name_merge_group + github_event_name_merge_group, + github_event_name_schedule } data diff_baseline_law: String = "DiffBaseline is the typed answer to 'what does the affected-set diff observe HEAD against?' — the de-fork of the origin/main policy-as-literal (DESIGN §3(c)). Three arms, no fourth default: MergeTarget (the PR's actual base, derived from the CI event's GITHUB_BASE_REF), PushParent (today's policy — the repo's default merge target, for push / workflow_dispatch / merge_group / the local-or-bootstrap window with no CI event; a merge_group queue run has no base ref and its tree diffs against the default branch, exactly the pre-de-fork behavior), OperatorOverride (the typed GUNBC_CI_DIFF_BASE arm, used by the falsifier's HEAD~20 cold control and manual runs). resolve_diff_baseline is PURE over the observed event facts (CiDiffEvent) so its arms are RED-testable without live git; the effectful env read lives in the caller (v2.workflow.floor_diff_observe.floor_observe_ci_diff_event)." @@ -67,6 +68,7 @@ fn resolve_diff_baseline_by_event( } else if event_name == github_event_name_push || event_name == github_event_name_workflow_dispatch || event_name == github_event_name_merge_group + || event_name == github_event_name_schedule || event_name == "" { BaselineSelected { baseline: PushParent { ref: push_parent_ref } } } else { From fc5af66350cb3a76bc9e853ed41d12f1fe1dac9e Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 24 Jul 2026 03:06:02 +0000 Subject: [PATCH 11/11] Map schedule -> PushParent (falsifier cron consumer) (review 42089) resolve_diff_baseline_by_event mapped push/pull_request/workflow_dispatch/merge_group but let schedule fall through to BaselineRefused -> floor halt. The falsifier's native_cache_cold_control_step runs SelectionApplied on the schedule cadence and sets only GUNBC_CI_NATIVE_CACHE_COLD_CONTROL, not GUNBC_CI_DIFF_BASE, so every cron run would have hard-aborted (pre-PR it used origin/main = PushParent). Routed schedule to PushParent alongside push/workflow_dispatch/merge_group; the five live triggers (push/pull_request/workflow_dispatch/merge_group + schedule) now all map to a base arm, else -> refuse catches only future/unmodeled triggers. Witness added: schedule -> push_parent. Co-Authored-By: Claude Opus 4.8 (1M context) --- dag/gunbc/diff_baseline.dag | 6 +++--- dag/test/claim/diff_baseline_witness_test.dag | 7 +++++++ src/v2/workflow/floor_diff_observe.dag | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dag/gunbc/diff_baseline.dag b/dag/gunbc/diff_baseline.dag index 80dad64552b..d1501ed785d 100644 --- a/dag/gunbc/diff_baseline.dag +++ b/dag/gunbc/diff_baseline.dag @@ -11,11 +11,11 @@ import extdeps.github.actions { github_event_name_schedule } -data diff_baseline_law: String = "DiffBaseline is the typed answer to 'what does the affected-set diff observe HEAD against?' — the de-fork of the origin/main policy-as-literal (DESIGN §3(c)). Three arms, no fourth default: MergeTarget (the PR's actual base, derived from the CI event's GITHUB_BASE_REF), PushParent (today's policy — the repo's default merge target, for push / workflow_dispatch / merge_group / the local-or-bootstrap window with no CI event; a merge_group queue run has no base ref and its tree diffs against the default branch, exactly the pre-de-fork behavior), OperatorOverride (the typed GUNBC_CI_DIFF_BASE arm, used by the falsifier's HEAD~20 cold control and manual runs). resolve_diff_baseline is PURE over the observed event facts (CiDiffEvent) so its arms are RED-testable without live git; the effectful env read lives in the caller (v2.workflow.floor_diff_observe.floor_observe_ci_diff_event)." +data diff_baseline_law: String = "DiffBaseline is the typed answer to 'what does the affected-set diff observe HEAD against?' — the de-fork of the origin/main policy-as-literal (DESIGN §3(c)). Three arms, no fourth default: MergeTarget (the PR's actual base, derived from the CI event's GITHUB_BASE_REF), PushParent (today's policy — the repo's default merge target, for push / workflow_dispatch / merge_group / schedule / the local-or-bootstrap window with no CI event; a merge_group queue run has no base ref and its tree diffs against the default branch, and the falsifier's scheduled cold-control steps that do not set GUNBC_CI_DIFF_BASE land here too — exactly the pre-de-fork behavior), OperatorOverride (the typed GUNBC_CI_DIFF_BASE arm, used by the falsifier's HEAD~20 cold control and manual runs). resolve_diff_baseline is PURE over the observed event facts (CiDiffEvent) so its arms are RED-testable without live git; the effectful env read lives in the caller (v2.workflow.floor_diff_observe.floor_observe_ci_diff_event)." -data diff_baseline_fail_closed_law: String = "A CI event this resolver cannot map to a base REFUSES (BaselineRefused) — it never substitutes a constant. The refusal propagates through floor_diff_observe's UnifiedDiffFail / NameStatusDiffFail into the executor's diff observation (cli_run.rs floor_git_diff_range), which HALTS the floor with a typed AFFECTED-SET REFUSAL (cause=DiffObservationRefusal): 'refuses every enrolled row rather than widening to a full-corpus run' (operator ruling 2026-07-05). The ignorance state is a loud, located, HARD STOP — NOT a run-everything widen (an earlier draft of this note misdescribed it as widen-to-whole-tree; the executor refuses, it does not widen — DESIGN §5, the exact absorbing-fallback shape being avoided). Only a genuinely-unrecognized event name lands here: the four workflow triggers (push / pull_request / workflow_dispatch / merge_group) all map to a base arm, so a future-added trigger halts loudly until it is modeled, rather than silently defaulting to origin/main — the exact defect being deleted, now typed." +data diff_baseline_fail_closed_law: String = "A CI event this resolver cannot map to a base REFUSES (BaselineRefused) — it never substitutes a constant. The refusal propagates through floor_diff_observe's UnifiedDiffFail / NameStatusDiffFail into the executor's diff observation (cli_run.rs floor_git_diff_range), which HALTS the floor with a typed AFFECTED-SET REFUSAL (cause=DiffObservationRefusal): 'refuses every enrolled row rather than widening to a full-corpus run' (operator ruling 2026-07-05). The ignorance state is a loud, located, HARD STOP — NOT a run-everything widen (an earlier draft of this note misdescribed it as widen-to-whole-tree; the executor refuses, it does not widen — DESIGN §5, the exact absorbing-fallback shape being avoided). Only a genuinely-unrecognized event name lands here: the five live workflow triggers (push / pull_request / workflow_dispatch / merge_group from ci_workflow, schedule from falsifier_workflow) all map to a base arm, so a future-added trigger halts loudly until it is modeled, rather than silently defaulting to origin/main — the exact defect being deleted, now typed." -data diff_baseline_bootstrap_arm_note: String = "The empty-event-name arm ('' — no GITHUB_EVENT_NAME) is an EXPLICIT recognized state, not the catch-all: it is the local / pre-CI-bootstrap window where there is no GitHub event at all, and its correct baseline is the repo's default merge target (PushParent), which is exactly today's behavior for a bare local floor_diff_observe invocation (DiffPolicy.base = origin/main). It is grouped with push / workflow_dispatch / merge_group because all four mean 'observe against the default branch'. The catch-all (a future GitHub trigger not yet modeled — ⊤-as-ignorance, genuinely not-knowing the base) is the final else → BaselineRefused, which HALTS the floor (never a silent origin/main). Conflating the two would be the absorbing fallback DESIGN §5 forbids; keeping them distinct keeps 'no CI event' (a known state, PushParent) apart from 'CI event we cannot map' (real ignorance, halt)." +data diff_baseline_bootstrap_arm_note: String = "The empty-event-name arm ('' — no GITHUB_EVENT_NAME) is an EXPLICIT recognized state, not the catch-all: it is the local / pre-CI-bootstrap window where there is no GitHub event at all, and its correct baseline is the repo's default merge target (PushParent), which is exactly today's behavior for a bare local floor_diff_observe invocation (DiffPolicy.base = origin/main). It is grouped with push / workflow_dispatch / merge_group / schedule because all mean 'observe against the default branch'. The catch-all (a future GitHub trigger not yet modeled — ⊤-as-ignorance, genuinely not-knowing the base) is the final else → BaselineRefused, which HALTS the floor (never a silent origin/main). Conflating the two would be the absorbing fallback DESIGN §5 forbids; keeping them distinct keeps 'no CI event' (a known state, PushParent) apart from 'CI event we cannot map' (real ignorance, halt)." type DiffBaseline = MergeTarget { ref: GitRef } diff --git a/dag/test/claim/diff_baseline_witness_test.dag b/dag/test/claim/diff_baseline_witness_test.dag index 8619852dd80..7792be16855 100644 --- a/dag/test/claim/diff_baseline_witness_test.dag +++ b/dag/test/claim/diff_baseline_witness_test.dag @@ -87,6 +87,12 @@ fn witness_merge_group_uses_push_parent() -> Bool { && selected_ref(res: res) == "origin/main" } +fn witness_schedule_no_override_is_push_parent() -> Bool { + let res = resolve_case(override_ref: none, event_name: "schedule", base_ref: none) + arm_tag(res: res) == "push_parent" + && selected_ref(res: res) == "origin/main" +} + fn witness_unknown_event_refuses() -> Bool { arm_tag(res: resolve_case(override_ref: none, event_name: "deployment_status", base_ref: none)) == "refused" } @@ -107,6 +113,7 @@ test fn diff_baseline_resolution_holds() -> Bool { && witness_bootstrap_no_event_is_push_parent() && witness_operator_override_is_typed_arm() && witness_merge_group_uses_push_parent() + && witness_schedule_no_override_is_push_parent() && witness_unknown_event_refuses() && witness_pull_request_empty_base_refuses() && witness_pull_request_absent_base_refuses() diff --git a/src/v2/workflow/floor_diff_observe.dag b/src/v2/workflow/floor_diff_observe.dag index 840406b901f..5746854a0f0 100644 --- a/src/v2/workflow/floor_diff_observe.dag +++ b/src/v2/workflow/floor_diff_observe.dag @@ -54,7 +54,7 @@ fn floor_env_optional(env_name: NonEmptyStr) -> String? { shell.Env.Get(name: env_name).value } -data floor_diff_baseline_law: String = "The affected-set base is RESOLVED from the CI event, not a constant (gunbc.diff_baseline; the de-fork of the origin/main policy-as-literal, DESIGN §3(c)). floor_observe_ci_diff_event reads the three env facts — GUNBC_CI_DIFF_BASE (the gunbc OperatorOverride channel, e.g. the falsifier's HEAD~20 cold control), GITHUB_EVENT_NAME, GITHUB_BASE_REF (the GitHub surface extdeps.github.actions owns) — and resolve_diff_baseline (pure) maps them: pull_request → MergeTarget against the PR's ACTUAL base (was silently origin/main — the stacked-PR over-selection defect #7129 hit); push / workflow_dispatch / merge_group / local-bootstrap → PushParent (today's DiffPolicy.base, origin/main — a merge_group queue run has no base ref and diffs its tree against the default branch, matching the pre-de-fork behavior so the floor RUNS rather than aborting). GUNBC_CI_DIFF_BASE → OperatorOverride. A genuinely-unrecognized event yields BaselineRefused → UnifiedDiffFail / NameStatusDiffFail → the executor HALTS the floor with a typed AFFECTED-SET REFUSAL (refuses every enrolled row, never widens to a full-corpus run; operator ruling 2026-07-05). The PushParent ref carries its own remote, so the MergeTarget remote is derived from it (git_remote_ref_parts) rather than re-imported." +data floor_diff_baseline_law: String = "The affected-set base is RESOLVED from the CI event, not a constant (gunbc.diff_baseline; the de-fork of the origin/main policy-as-literal, DESIGN §3(c)). floor_observe_ci_diff_event reads the three env facts — GUNBC_CI_DIFF_BASE (the gunbc OperatorOverride channel, e.g. the falsifier's HEAD~20 cold control), GITHUB_EVENT_NAME, GITHUB_BASE_REF (the GitHub surface extdeps.github.actions owns) — and resolve_diff_baseline (pure) maps them: pull_request → MergeTarget against the PR's ACTUAL base (was silently origin/main — the stacked-PR over-selection defect #7129 hit); push / workflow_dispatch / merge_group / schedule / local-bootstrap → PushParent (today's DiffPolicy.base, origin/main — merge_group queue runs and the falsifier's scheduled cold-control steps have no base ref and diff their tree against the default branch, matching the pre-de-fork behavior so the floor RUNS rather than aborting). GUNBC_CI_DIFF_BASE → OperatorOverride. A genuinely-unrecognized event yields BaselineRefused → UnifiedDiffFail / NameStatusDiffFail → the executor HALTS the floor with a typed AFFECTED-SET REFUSAL (refuses every enrolled row, never widens to a full-corpus run; operator ruling 2026-07-05). The PushParent ref carries its own remote, so the MergeTarget remote is derived from it (git_remote_ref_parts) rather than re-imported." fn floor_observe_ci_diff_event() -> CiDiffEvent { CiDiffEvent {