Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dag/gunbc/heal_publication.dag
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import extdeps.github.workflow_run_event {
import extdeps.git.object_store { git_object_id_wire_hex, git_sha1_object_id, git_encode_tree_mode, git_tree_mode_object_type }
import extdeps.github.github { Repository }
import gunbc.repository { gunbc_repository }
import gunbc.generated_artifact { artifact_path, WitnessFloorYamlArtifact }
import gunbc.generated_artifact { artifact_path, WitnessFloorYamlArtifact, HealWorkflowYamlArtifact }
import gunbc.generated_artifact_registry { committed_generated_artifact_paths }
import gunbc.heal_candidate { blob_id_of, BlobIdComputed, BlobIdRefused }
import gunbc.heal_publication_boundary {
Expand Down Expand Up @@ -69,7 +69,7 @@ type HealPublicationSubject {
fn public_heal_publication_subject() -> HealPublicationSubject {
HealPublicationSubject {
repository: gunbc_repository,
candidate_producer_workflow_path: artifact_path(a: WitnessFloorYamlArtifact),
candidate_producer_workflow_path: artifact_path(a: HealWorkflowYamlArtifact),
committed_artifact_paths: committed_generated_artifact_paths(),
}
}
Expand Down
24 changes: 17 additions & 7 deletions dag/gunbc/heal_workflow.dag
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,25 @@ import gunbc.heal_publication_boundary { heal_repair_candidate_artifact_name }
// IT HOLDS NO WRITE AUTHORITY AND PUSHES NOTHING. Until this cut, this job checked out the branch,
// regenerated, committed and pushed with the Actions job credential -- and GitHub holds the
// pull_request run that such a push causes (docs: a push made with GITHUB_TOKEN creates workflow runs
// in an approval-required state), so every healed head waited for a human. The repair now leaves as a
// CANDIDATE ARTIFACT, and gunbc.heal_publisher_workflow publishes it from the default branch under an
// App installation token, whose pushes run without approval.
// in an approval-required state), so every healed head waited for a human. The repair leaves as a
// CANDIDATE ARTIFACT, which gunbc.heal_publisher_workflow published from the default branch under an
// App installation token, whose pushes ran without approval.
//
// WHY A SEPARATE WORKFLOW RATHER THAN A LANE OF `witnesses`. The publisher is triggered by
// FROZEN SINCE 2026-10-09 (operator ruling, the v1 withdrawal): the publisher workflow is DELETED
// with the required lanes that sealed candidates for it, so a candidate this workflow seals and
// uploads has NO PUBLICATION CONSUMER -- a dispatch of it produces an artifact nobody reads. The
// route is not deleted with the publisher because its subject, a repair candidate for a regenerated
// projection, returns the day a native regen instrument joins the required path and a publisher
// row stands beside it; until then it is frozen in the DESIGN section 3 sense -- no new investment,
// no new rows on its growth surfaces -- and the loss is declared, not silent: it is a member of
// gunbc.rung_drop v1_required_lanes_withdrawn's population, which also names the publisher's
// revalidation hook (`expected_healed_sha` on witnesses.yml) as unused for the same reason.
//
// WHY IT WAS A SEPARATE WORKFLOW RATHER THAN A LANE OF `witnesses`. The publisher was triggered by
// workflow_run on THIS workflow's completion, and a workflow_run fires when the whole run finishes.
// Left inside `witnesses`, publication would wait for the required floor of a head the repair is
// about to supersede. Heal was never a required lane -- it remediates, the build lane's
// generated-artifact phase adjudicates -- so nothing of the gate moves with it.
// Left inside `witnesses`, publication would have waited for the required floor of a head the
// repair was about to supersede. Heal was never a required lane -- it remediated, the build lane's
// generated-artifact phase adjudicated -- so nothing of the gate moved with it.
//
// THE CHECKOUT IS THE EXACT HEAD, NOT THE BRANCH NAME. The candidate describes the commit it was
// derived from, and the publisher refuses any candidate whose expected head is not the branch's
Expand Down
3 changes: 2 additions & 1 deletion dag/gunbc/rung_drop/v1_required_lanes_withdrawn.dag
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ import gunbc.guarantee_rung { Mitigatable, MechanicallyPreventable }

data v1_required_lanes_withdrawn_population: List<String> = [
"every claim the `floor` lane folded on a pull request or a merge_group: the prepared subject of `v2.workflow.required_floor` `required_gate_prefixes` with its seeds, plus the changed-witness and touched-entry selection. `claim_executor --required-ci --required-lane witnesses` is run by no job",
"the stage0 mirrors equal one emission by the seed built from them, and the registry-rostered generated artifacts (`gunbc.generated_artifact_registry` `committed_generated_artifacts`) equal one emission of their authorities: `claim_executor --required-ci --required-lane build` is run by no job. That population includes `.github/workflows/witnesses.yml` and `DESIGN.md`, so the gate's own workflow file is compared with `gunbc.compiler_gate_workflow` by nothing; the heal publisher workflow that published repair candidates was deleted with the lanes (nothing sealed one), and its WIF pool (`gunbc.auth.heal_publisher_federation`) stands dead until retired by hand -- an external-estate obligation, not a drop",
"the stage0 mirrors equal one emission by the seed built from them, and the registry-rostered generated artifacts (`gunbc.generated_artifact_registry` `committed_generated_artifacts`) equal one emission of their authorities: `claim_executor --required-ci --required-lane build` is run by no job. That population includes `.github/workflows/witnesses.yml` and `DESIGN.md`, so the gate's own workflow file is compared with `gunbc.compiler_gate_workflow` by nothing; the heal publisher workflow that published repair candidates was deleted with the lanes (nothing on the required path seals one any more), and its WIF pool (`gunbc.auth.heal_publisher_federation`) stands dead until retired by hand -- an external-estate obligation, not a drop",
"the manual repair route that survives the publisher: `gunbc.heal_workflow` (`.github/workflows/heal.yml`, workflow_dispatch) still checks out a pull request head, seals a repair candidate (`gunbc.heal_candidate`) and uploads it as the artifact the deleted publisher consumed, so a dispatch of it produces a candidate nobody publishes. It stands FROZEN (DESIGN section 3: no new investment, no new rows on its growth surfaces) rather than cut, because its subject -- a repair candidate for a regenerated projection -- returns with a native regen instrument on the required path and a publisher row beside it; the publisher's revalidation hook, the `expected_healed_sha` workflow_dispatch input of `witnesses.yml`, is unused for the same reason and for the same span",
"the lint: `cargo clippy --all-targets -- -D warnings` (`gunbc.repo_self_build` `repo_self_clippy_command`), the only command that compiles the integration-test and example targets",
"the v1 unit tests: `cargo test --release -p v1-compiler --lib` (`gunbc.repo_self_build` `repo_self_test_command`), which ran on merge_group and workflow_dispatch",
"module resolution: every module the source-root ingestion admits under dag/ and src/v2/ that is outside the import closures of `gunbc.instrument_targets` `self_host_entry` and `v2_native_cli_entry` is handed to a compiler by no required step, so it can stop resolving on main with the required context green. Enumerated BY IDENTITY, not by count, by `gunbc test //gunbc/instruments:required-lane-resolution-census` (`gunbc.required_lane_resolution_census_live`), which from this change does not hold by design",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ test fn fci1_context_derives_the_runner_workload_envelope() -> Bool {
Absent => false
}
&& context.checkout_root == "/tmp/fci1 checkout"
&& context.envelope_basis.module_path == "gunbc.runner_slot_allocation"
&& context.envelope_basis.module_path == "gunbc.runner_slot_desired"
&& context.envelope_basis.decl_name == "gunbc_runner_slot_desired"
_ => false
}
Expand Down
2 changes: 1 addition & 1 deletion dag/test/claim/heal_publication_boundary_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ fn observations_with(
PublisherObservations {
repository_full_name: "gunb-ai/gunbc",
default_branch: "main",
candidate_producer_workflow_path: ".github/workflows/witnesses.yml",
candidate_producer_workflow_path: ".github/workflows/heal.yml",
run: run,
pull_request: pull,
branch_head_sha: branch_head,
Expand Down
2 changes: 1 addition & 1 deletion docs/design-rung-drops.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ the behaviours the deleted v1 integration tests exercised (required-floor runner

### The four v1-judged required lanes (`floor`, `generated`, `rust-unit-tests`, `seed`) as a merge gate — declared 2026-10-09

The four v1-judged required lanes (`floor`, `generated`, `rust-unit-tests`, `seed`) as a merge gate: RUNG DROP, mechanically preventable -> mitigatable (replacement staged: a binary built from an emission of v2 judging this population on the required path, admitted to the gate as rows of `gunbc.emitted_subject_build_gate` `emitted_subject_build_rows`. No such row covers any member of this population at declaration). Population: every claim the `floor` lane folded on a pull request or a merge_group: the prepared subject of `v2.workflow.required_floor` `required_gate_prefixes` with its seeds, plus the changed-witness and touched-entry selection. `claim_executor --required-ci --required-lane witnesses` is run by no job, the stage0 mirrors equal one emission by the seed built from them, and the registry-rostered generated artifacts (`gunbc.generated_artifact_registry` `committed_generated_artifacts`) equal one emission of their authorities: `claim_executor --required-ci --required-lane build` is run by no job. That population includes `.github/workflows/witnesses.yml` and `DESIGN.md`, so the gate's own workflow file is compared with `gunbc.compiler_gate_workflow` by nothing; the heal publisher workflow that published repair candidates was deleted with the lanes (nothing sealed one), and its WIF pool (`gunbc.auth.heal_publisher_federation`) stands dead until retired by hand -- an external-estate obligation, not a drop, the lint: `cargo clippy --all-targets -- -D warnings` (`gunbc.repo_self_build` `repo_self_clippy_command`), the only command that compiles the integration-test and example targets, the v1 unit tests: `cargo test --release -p v1-compiler --lib` (`gunbc.repo_self_build` `repo_self_test_command`), which ran on merge_group and workflow_dispatch, module resolution: every module the source-root ingestion admits under dag/ and src/v2/ that is outside the import closures of `gunbc.instrument_targets` `self_host_entry` and `v2_native_cli_entry` is handed to a compiler by no required step, so it can stop resolving on main with the required context green. Enumerated BY IDENTITY, not by count, by `gunbc test //gunbc/instruments:required-lane-resolution-census` (`gunbc.required_lane_resolution_census_live`), which from this change does not hold by design, the consumers of those lanes' products: no merge_group run uploads a compiler pair candidate, so `gunbc.fleet_desired_admission_workflow` builds the pair itself; and `gunbc.fleet_revision_acceptance` admits a revision on a required-CI success that carries the `witnesses` job's emit-and-build verdict alone, under the contract epoch `gunbc.required_ci_contract_epoch` moved to with this change, NOT ENUMERATED HERE, and named so the gap is not read as empty: every `gunbc.recurring_failure_mode` row and every standing `gunbc.rung_drop` row whose stated current rung is held by a step of the four lanes. Those rows are not amended by this change, and each now sits no higher than this row's temporary rung. Restored when: THE CAPABILITY: on every landing revision, a binary built from an emission of v2 -- the seed's emission today, v2's own after the generation transition -- judges this population on the required path with a discriminating red. Member by member: (1) every claim the floor folded is executed by such a binary, or its subject has been deleted; (2) every module the source-root ingestion admits is resolved, observed as `gunbc test //gunbc/instruments:required-lane-resolution-census` holding against the workflow as emitted; (3) every committed generated artifact, `.github/workflows/witnesses.yml` included, is compared with one emission of its authority; (4) for the three members whose subject is v1's own Rust -- the stage0 mirrors, the lint and the v1 unit tests -- a change to the seed's sources cannot land with the required context green unless a required step judged it, or the seed no longer exists. WHAT THAT MUST BE SUFFICIENT FOR: no member of this population can regress with the required context green. WHAT DOES NOT RETIRE THIS ROW, stated because each is the likely mistake: returning any of the four lanes, or any step that hands the corpus to the v1 interpreter, because the ruling withdraws that authority; a native row that judges part of the population, which narrows this row member by member and retires nothing; a manual or dispatched run off the required path; and a count of claims or modules standing where the identity join belongs. The TEMPORARY rung is Mitigatable only while the seed's own runners for these members exist at head, so a change that deletes one of them owes its own declaration.
The four v1-judged required lanes (`floor`, `generated`, `rust-unit-tests`, `seed`) as a merge gate: RUNG DROP, mechanically preventable -> mitigatable (replacement staged: a binary built from an emission of v2 judging this population on the required path, admitted to the gate as rows of `gunbc.emitted_subject_build_gate` `emitted_subject_build_rows`. No such row covers any member of this population at declaration). Population: every claim the `floor` lane folded on a pull request or a merge_group: the prepared subject of `v2.workflow.required_floor` `required_gate_prefixes` with its seeds, plus the changed-witness and touched-entry selection. `claim_executor --required-ci --required-lane witnesses` is run by no job, the stage0 mirrors equal one emission by the seed built from them, and the registry-rostered generated artifacts (`gunbc.generated_artifact_registry` `committed_generated_artifacts`) equal one emission of their authorities: `claim_executor --required-ci --required-lane build` is run by no job. That population includes `.github/workflows/witnesses.yml` and `DESIGN.md`, so the gate's own workflow file is compared with `gunbc.compiler_gate_workflow` by nothing; the heal publisher workflow that published repair candidates was deleted with the lanes (nothing on the required path seals one any more), and its WIF pool (`gunbc.auth.heal_publisher_federation`) stands dead until retired by hand -- an external-estate obligation, not a drop, the manual repair route that survives the publisher: `gunbc.heal_workflow` (`.github/workflows/heal.yml`, workflow_dispatch) still checks out a pull request head, seals a repair candidate (`gunbc.heal_candidate`) and uploads it as the artifact the deleted publisher consumed, so a dispatch of it produces a candidate nobody publishes. It stands FROZEN (DESIGN section 3: no new investment, no new rows on its growth surfaces) rather than cut, because its subject -- a repair candidate for a regenerated projection -- returns with a native regen instrument on the required path and a publisher row beside it; the publisher's revalidation hook, the `expected_healed_sha` workflow_dispatch input of `witnesses.yml`, is unused for the same reason and for the same span, the lint: `cargo clippy --all-targets -- -D warnings` (`gunbc.repo_self_build` `repo_self_clippy_command`), the only command that compiles the integration-test and example targets, the v1 unit tests: `cargo test --release -p v1-compiler --lib` (`gunbc.repo_self_build` `repo_self_test_command`), which ran on merge_group and workflow_dispatch, module resolution: every module the source-root ingestion admits under dag/ and src/v2/ that is outside the import closures of `gunbc.instrument_targets` `self_host_entry` and `v2_native_cli_entry` is handed to a compiler by no required step, so it can stop resolving on main with the required context green. Enumerated BY IDENTITY, not by count, by `gunbc test //gunbc/instruments:required-lane-resolution-census` (`gunbc.required_lane_resolution_census_live`), which from this change does not hold by design, the consumers of those lanes' products: no merge_group run uploads a compiler pair candidate, so `gunbc.fleet_desired_admission_workflow` builds the pair itself; and `gunbc.fleet_revision_acceptance` admits a revision on a required-CI success that carries the `witnesses` job's emit-and-build verdict alone, under the contract epoch `gunbc.required_ci_contract_epoch` moved to with this change, NOT ENUMERATED HERE, and named so the gap is not read as empty: every `gunbc.recurring_failure_mode` row and every standing `gunbc.rung_drop` row whose stated current rung is held by a step of the four lanes. Those rows are not amended by this change, and each now sits no higher than this row's temporary rung. Restored when: THE CAPABILITY: on every landing revision, a binary built from an emission of v2 -- the seed's emission today, v2's own after the generation transition -- judges this population on the required path with a discriminating red. Member by member: (1) every claim the floor folded is executed by such a binary, or its subject has been deleted; (2) every module the source-root ingestion admits is resolved, observed as `gunbc test //gunbc/instruments:required-lane-resolution-census` holding against the workflow as emitted; (3) every committed generated artifact, `.github/workflows/witnesses.yml` included, is compared with one emission of its authority; (4) for the three members whose subject is v1's own Rust -- the stage0 mirrors, the lint and the v1 unit tests -- a change to the seed's sources cannot land with the required context green unless a required step judged it, or the seed no longer exists. WHAT THAT MUST BE SUFFICIENT FOR: no member of this population can regress with the required context green. WHAT DOES NOT RETIRE THIS ROW, stated because each is the likely mistake: returning any of the four lanes, or any step that hands the corpus to the v1 interpreter, because the ruling withdraws that authority; a native row that judges part of the population, which narrows this row member by member and retires nothing; a manual or dispatched run off the required path; and a count of claims or modules standing where the identity join belongs. The TEMPORARY rung is Mitigatable only while the seed's own runners for these members exist at head, so a change that deletes one of them owes its own declaration.

### The v2 native frontier (the ratchet over the emitted-native route's refusals) runs on no merge candidate and on no schedule until the required native-route lane is live — declared 2026-09-23

Expand Down