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
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module gunbc.recurring_failure_mode.a_build_replaces_the_executable_that_is_running_it

import std.types { NonEmptyStr }
import gunbc.recurring_failure_mode { RecurringFailureMode }

data a_build_replaces_the_executable_that_is_running_it: RecurringFailureMode = RecurringFailureMode {
identity: "a_build_replaces_the_executable_that_is_running_it" as NonEmptyStr,

receipts: [
"INVALID STATE: a process builds the very binary it is running from, and the build relinks that path, so the process continues as the OLD image while the disk holds the NEW one. Anything the process then does in its own image (an emit, a measurement) speaks for a seed the build did not produce.",
"SPECIMEN: `claim_executor --regen-round-cost` ran `round.seed_build` (cargo build --release --bin claim_executor) and refused on its first remote run with 'the seed build replaced the running executable' (the historical refusal was an untyped Err(String), not a typed cause); the author-side workaround was to run it twice in one dispatch, which is the DESIGN section 5 workaround (an absorbing fallback executed by the author).",
"DISTINGUISHING FACTS: the refusal (an untyped Err(String)) was correct but fired on a precondition the flag itself manufactured (build output path == running image path); the second run succeeds only because the build is then up to date. The earliest unjustified boundary is the build step's choice of output path, not the digest comparison.",
"RUNG: found at 1 (runtime mitigation: an untyped Err(String) refusal). CURRENT rung 1 still: the build re-execs the built binary exactly once, carrying the pre-handoff seed-build cost, the built-artifact digest and a source identity (HEAD plus the uncommitted tracked diff digest plus length-framed path+content digests of untracked non-ignored files; built_exe is the BUILD-OUTPUT digest, and the descriptor opened for the exec must match it (OpenedTargetNotBuildOutput) before the exec, never overwriting the carry, and the receiving image digests the running image through /proc/self/exe (not the installed path) and refuses on a mismatch with the carried digest; a rewrite of the inode between hash and exec is detected after the fact, not prevented; marker GUNBC_REGEN_ROUND_COST_REEXEC), and the receiving image refuses with the typed SeedHandoffRefusal on a wrong artifact, a changed source, a second replacement, or a ledger without exactly one round.seed_build row; the invalid state stays writable. CEILING 3, reached only by execution of the admitted build artifact with complete, or explicitly unavailable, accounting. RECOGNITION RULE: a step that builds X and then relies on running-process X must re-exec or build elsewhere; 'run it twice' is the tell.",
"NEXT TRIGGER: model the seed-build step in .dag so the admitted build artifact is a declared fact and is the thing executed, with its cost accounting complete or explicitly unavailable; until then the re-exec lives in required_regen_host.rs run_regen_round_cost, a v1 seed-growth item tracked beside gunbc.regen_round_cost_instrument_seed_growth and dissolved when that modeled path lands."
],
evidence: []
}
9 changes: 7 additions & 2 deletions dag/gunbc/regen_round_cost_instrument_seed_growth.dag
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ data regen_round_cost_instrument_seed_growth_justification: SeedGrowthJustificat
hand_authored_declarations: [
DeclarationRef { module_path: "v1_compiler.target_invocation_host", decl_name: "run_regen_round_cost_instrument", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.target_invocation_host", decl_name: "REGEN_ROUND_COST_PROBE_MIRROR", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.required_regen_host", decl_name: "run_regen_one_mirror_emit_probe", field: WholeDeclaration }
DeclarationRef { module_path: "v1_compiler.required_regen_host", decl_name: "run_regen_one_mirror_emit_probe", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.required_regen_host", decl_name: "SeedHandoff", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.required_regen_host", decl_name: "SeedHandoffRefusal", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.required_regen_host", decl_name: "decide_seed_handoff", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.required_regen_host", decl_name: "compose_seed_build_cost", field: WholeDeclaration },
DeclarationRef { module_path: "v1_compiler.required_regen_host", decl_name: "admit_exec_target", field: WholeDeclaration }
],

reason: "The producer arm for gunbc.target_binding RegenRoundCostProducer, so the existing priced regen round (claim_executor --regen-round-cost, gunbc.regen_round_cost) can run by label on a memory-bounded fleet slot through instrument-dispatch. It adds no second emit path: the round is the existing run_regen_round_cost, and the one-mirror discriminator is the existing run_required_regen_scoped with an Affected scope of one member, its trace ledger drained and printed. Both callees are host Rust in the seed, so their caller is too. It adds no flag and no mode that skips a check; it is on-demand only and no required job reaches it.",
reason: "ALSO the single re-exec handoff in run_regen_round_cost (SeedHandoff, SeedHandoffRefusal, decide_seed_handoff, compose_seed_build_cost, admit_exec_target): the seed build replaces the running claim_executor, so the built image is handed the pre-handoff seed-build cost, the built-artifact digest and a source identity (HEAD, tracked diff, length-framed untracked non-ignored files; built_exe is the build-output digest checked against the exec'd descriptor, checked against the running image via /proc/self/exe), refuses on a wrong artifact, changed source or other than one seed_build row, and composes them into the receipt once; it dissolves when the seed build is modeled in .dag so the admitted build artifact is what executes, with complete or explicitly unavailable accounting (gunbc.recurring_failure_mode a_build_replaces_the_executable_that_is_running_it). The producer arm for gunbc.target_binding RegenRoundCostProducer, so the existing priced regen round (claim_executor --regen-round-cost, gunbc.regen_round_cost) can run by label on a memory-bounded fleet slot through instrument-dispatch. It adds no second emit path: the round is the existing run_regen_round_cost, and the one-mirror discriminator is the existing run_required_regen_scoped with an Affected scope of one member, its trace ledger drained and printed. Both callees are host Rust in the seed, so their caller is too. It adds no flag and no mode that skips a check; it is on-demand only and no required job reaches it.",

owning_dissolution_lane: "v1-hand-queue-drain" as RoadmapNodeId,

Expand Down
Loading
Loading