Skip to content
Merged
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
3 changes: 2 additions & 1 deletion dag/gunbc/runner_host_deploy.dag
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ type RunnerHostDeploy {
runner_count: Int
}

data srv4_runner_count_disk_cap_note: String = "srv4's historical five-slot pin is RETIRED (operator ruling 2026-08-06). runner_count on srv4_runner_host_deploy now names the materialization target width (6 after the 2026-08-17 16GiB ruling, matching srv3), and disk binding moves to APPLY-TIME preflight in gunbc.runner_lifecycle runner_width_disk_preflight — not a silent row pin and never an absorbing fallback to 5 when disk is unobservable.\n\nFACT unchanged: NVMe is a Samsung 970 EVO 500GB against 2TB on srv1-3; every ephemeral runner keeps a _work tree plus caches. gunbc.runner_lifecycle runner_slot_disk_budget_per_slot (~38GB per slot; the charge is per-slot, so the total demanded at apply falls with the 2026-08-17 move from width 7 to 6) is the conservative charge used at apply; sufficient observed headroom proceeds, insufficient REFUSES, unobservable REFUSES.\n\ngunbc.ci_runner_placement still models RAM only for solver admission; memory admits 6 for srv4 at the 16GiB slot (7 at the superseded 14GiB slot). The disk gate is no longer this note or host_disk_admitted_width reading runner_count as a cap — it is the observed preflight arm vivid-eagle-131's apply_wet path must invoke before slot ADD."
data srv4_runner_count_disk_cap_note: String = "srv4's historical five-slot pin is RETIRED (operator ruling 2026-08-06) and runner_count on srv4_runner_host_deploy names the materialization target, DERIVED from gunbc_runner_slots_per_host rather than authored here. Disk binding lives in APPLY-TIME preflight in gunbc.runner_lifecycle runner_width_disk_preflight -- not a silent row pin, and never an absorbing fallback to 5 when disk is unobservable.\n\nTHE WIDTH AND THE DISK ARITHMETIC IN THIS NOTE WERE BOTH SIX AND ARE NOW TWENTY-ONE, AND THE SECOND CHANGE IS NOT COSMETIC. The prior text sized the per-slot disk charge at width 6 (~38GB per slot against a 500GB class disk) and read as reassurance. At the width the CPU axis committed on 2026-08-23 the same charge is 21 x 40.96 GB, about 860 GB, against a Samsung 970 EVO 500GB -- so runner_width_disk_preflight is EXPECTED TO REFUSE srv4 at its committed width. srv1-3 carry 2TB and are unaffected.\n\nSO THIS ROW NO LONGER RECORDS A MARGIN; IT RECORDS AN EXPECTED REFUSAL. That is the apply-time gate doing exactly what the 2026-08-06 ruling built it to do, and it means srv4 currently has a committed width it cannot materialize. Nothing here lowers the commitment to hide that -- absorbing to a width the disk happens to permit is the fallback that ruling removed.\n\nWHETHER THE REFUSAL IS REAL IS UNRESOLVED, because the charge is circular. gunbc.runner_lifecycle runner_slot_disk_budget_per_slot_note derives 40.96 GB from \"about 38GB per slot at width 7 on 500GB class disk\" -- disk size divided by desired width, so the number was computed FROM a width and is now used to constrain one. A live observation of per-slot usage under an active reclaimer came in near 2.5 GB, two orders of magnitude off. A circular charge refusing a derived width is two unmeasured numbers meeting, and neither side of that refusal is currently evidence.\n\nEvery ephemeral runner keeps a _work tree plus caches, so the real figure is not zero and the question is genuinely open. DISSOLVE-ON: a measured per-slot disk series on srv4."


data runner_count_derives_from_committed_width_note: String = "runner_count IS DERIVED, NOT AUTHORED, AND THAT CLOSES A FORK THAT WOULD HAVE SILENTLY EATEN A WIDTH CHANGE. These rows carried a literal 6 while gunbc.runner_slot_allocation gunbc_runner_slots_per_host independently answered the same question -- how many slots does this host carry -- so one concept had two authorings and the deploy side was the one nobody re-derived. The cost was not hypothetical: the 2026-08-23 CPU-axis change moved committed width to 21 on srv3 and srv4, and with the literal in place PROVISIONING WOULD STILL HAVE STOOD UP SIX. The allocation model and the materialization path would have disagreed about the fleet with no diagnostic anywhere, which is exactly the roster-versus-prose failure gunbc.runner_slot_allocation width_is_a_minimum_over_axes_note records for srv4.\n\nTHE DIRECTION IS DELIBERATE. Width is decided by the conservation and admission axes and materialization CONSUMES that decision; a deploy row is not a place to re-decide it. The disk question that the old srv4 note worried about is unaffected and still lives where it belongs -- apply-time gunbc.runner_lifecycle runner_width_disk_preflight refuses on insufficient or unobservable headroom rather than lowering the count here.\n\nsrv1 AND srv2 STILL HAVE NO DEPLOY ROW AT ALL. That is pre-existing and is NOT closed by this change: only srv3 and srv4 are modeled for materialization, so srv1's move from five slots to twenty-one has no provisioning path in this module even after this correction. Recorded here rather than left to be discovered, because a reader seeing two derived rows may reasonably assume the fleet is covered."

Expand Down
2 changes: 1 addition & 1 deletion dag/gunbc/runner_lifecycle.dag
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ fn runner_slot_dir_path(slot: RunnerSlotIdentity) -> NonEmptyStr {
join([actions_runner_base_dir, "/", runner_slot_instance_name(slot: slot)], "") as NonEmptyStr
}

data runner_slot_disk_budget_per_slot_note: String = "Conservative per-slot disk charge for width preflight on srv4 (operator 2026-08-06): seven slots on 500GB NVMe cannot silently fall back to the historical five-slot pin. Derived from srv4_runner_count_disk_cap_note arithmetic (~38GB per slot at width 7 on 500GB class disk). Unobservable disk REFUSES; insufficient headroom REFUSES — never absorbs to width 5."
data runner_slot_disk_budget_per_slot_note: String = "Conservative per-slot disk charge for width preflight on srv4 (operator 2026-08-06): a host cannot silently fall back to the historical five-slot pin. Unobservable disk REFUSES; insufficient headroom REFUSES — never absorbs to a width the disk happens to permit.\n\nTHE NUMBER IS CIRCULAR AND THAT IS RECORDED HERE RATHER THAN IN THE ROWS THAT CITE IT. This note previously read 'derived from srv4_runner_count_disk_cap_note arithmetic (~38GB per slot at width 7 on 500GB class disk)' as if that were a provenance. It is not: 500GB class disk divided by the width of the day IS the derivation, so the charge was computed FROM a desired width and is now used to CONSTRAIN one. Nothing was measured. A separate observation of live per-slot usage under an active reclaimer came in near 2.5 GB, two orders of magnitude below this row.\n\nWHAT THAT COSTS NOW, at the width the CPU axis committed on 2026-08-23: runner_width_disk_preflight charges 21 x 40.96 GB, about 860 GB, against srv4's 500 GB NVMe, and is EXPECTED TO REFUSE. So a circular charge is refusing a derived width -- two unmeasured numbers meeting -- and neither the refusal nor a hypothetical pass would be evidence about srv4's real disk. The refusal is still correct behaviour: refusing on an unreliable charge is the fail-closed arm, and lowering the charge to make the width fit would be fitting the measurement to the answer.\n\nWHAT IS NOT CLAIMED: that srv4 cannot hold 21 slots. Every ephemeral runner keeps a _work tree plus caches so the true figure is not 2.5 GB either, and the question is open in both directions. DISSOLVE-ON: a measured per-slot disk series on srv4 replacing this row, at which point the preflight either refuses on evidence or stops refusing."

data runner_slot_disk_budget_per_slot: ByteSize = byte_size(40960000000)

Expand Down
4 changes: 2 additions & 2 deletions dag/gunbc/runner_slot_allocation.dag
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ fn gunbc_runner_slot_desired() -> RunnerSlotDesired {

data gunbc_runner_slots_per_host_unknown_note: String = "Unknown hosts refuse rather than defaulting. A width is a claim about a specific machine's RAM, and handing an unclassified host the width the measured hosts reached (21 as of 2026-08-23) would be the same borrowed-premise failure the fixed-overhead fallback carries (gunbc.ci_floor_measurement gunbc_ci_host_fixed_overhead_unknown_host_note) — worse here, because width multiplies the per-slot ceiling. Zero slots is the fail-closed answer: gunbc.ci_runner_placement's any_unfit arm already refuses a plan that admits zero runners on an enrolled host, so an unclassified host produces a located PlanUnsound rather than a silent five."

data width_is_a_minimum_over_axes_note: String = "A HOST'S WIDTH AT ALLOCATION IS THE MINIMUM OVER ALLOCATION-TIME CONSTRAINTS. Until this row existed gunbc_runner_slots_per_host returned the MEMORY verdict under a name that read as the full commitment — the defect that made srv4's roster and prose disagree when a disk row-pin silently lowered allocation to 5 while runner_host_deploy named seven slots.\n\nCollapsing 'one constraint admits this width' into 'this host should run this width' is the same conflation gunbc.ci_floor_measurement refuses for overhead: an axis nobody resolved is not an axis that permits everything. Memory admission and disk admission remain separate answers at allocation; gunbc_runner_slots_per_host takes their minimum when disk admits a numeric cap, otherwise memory alone.\n\nsrv4's historical five-slot disk row-pin is retired (operator 2026-08-06): host_disk_admitted_width returns DiskWidthUnconstrained citing apply-time gunbc.runner_lifecycle runner_width_disk_preflight, so srv4 commits 6 at allocation like srv3 (7 before the 2026-08-17 16GiB ruling) — disk no longer derives a lower minimum here. Insufficient or unobservable disk at apply refuses rather than absorbing to width 5 (gunbc_runner_slot_allocation_srv4_admission_note).\n\nHONEST RESIDUAL: srv1-3 still have DiskWidthUnconstrained without a measured disk width — status quo, not a new widen. Dissolve-on for allocation-time disk on all hosts is a per-host disk-headroom term folded into runner_deployment_plan; srv4's apply-time gate remains even after that lands."
data width_is_a_minimum_over_axes_note: String = "A HOST'S WIDTH AT ALLOCATION IS THE MINIMUM OVER ALLOCATION-TIME CONSTRAINTS. Until this row existed gunbc_runner_slots_per_host returned the MEMORY verdict under a name that read as the full commitment — the defect that made srv4's roster and prose disagree when a disk row-pin silently lowered allocation to 5 while runner_host_deploy named seven slots.\n\nCollapsing 'one constraint admits this width' into 'this host should run this width' is the same conflation gunbc.ci_floor_measurement refuses for overhead: an axis nobody resolved is not an axis that permits everything. Memory admission and disk admission remain separate answers at allocation; gunbc_runner_slots_per_host takes their minimum when disk admits a numeric cap, otherwise memory alone.\n\nsrv4's historical five-slot disk row-pin is retired (operator 2026-08-06): host_disk_admitted_width returns DiskWidthUnconstrained citing apply-time gunbc.runner_lifecycle runner_width_disk_preflight, so srv4 commits 21 at allocation like srv3 (6 before the 2026-08-23 CPU axis, 7 before the 2026-08-17 16GiB ruling) — disk no longer derives a lower minimum here. Insufficient or unobservable disk at apply refuses rather than absorbing to width 5 (gunbc_runner_slot_allocation_srv4_admission_note).\n\nHONEST RESIDUAL: srv1-3 still have DiskWidthUnconstrained without a measured disk width — status quo, not a new widen. Dissolve-on for allocation-time disk on all hosts is a per-host disk-headroom term folded into runner_deployment_plan; srv4's apply-time gate remains even after that lands."

data host_memory_admitted_width_moved_on_measurement_note: String = "THESE FOUR NUMBERS MOVED BECAUSE THE MACHINES DID, and the arithmetic that produces them is unchanged. Each is the largest slot count gunbc.ci_runner_placement's conservation wall passes for that host at the 16 GiB slot, charging that host's fixed overhead, its sessions slice, and the OOMD actuation floor against its OS-USABLE RAM. The 2026-08-22 DIMM upgrade and the /proc/meminfo reads that followed changed the usable-RAM input on three of the four hosts, so the outputs moved with it:\n\n srv1 5 -> 27 (usable 125 GiB bound -> 502.24 GiB measured 2026-08-23)\n srv2 5 -> 5 (bound 134217728000 -> measured 134314512384; the upgrade failed training here and was reverted, so the population is unchanged and the width with it)\n srv3 6 -> 29 (bound -> 502.25 GiB measured 2026-08-22)\n srv4 6 -> 29 (bound -> 502.25 GiB measured 2026-08-22)\n\nTWENTY-NINE IS NOT A COMMITMENT AND MUST NOT BE READ AS ONE. This function answers what MEMORY admits and nothing else; the committed width is gunbc_runner_slots_per_host, which takes the minimum over memory, CPU and disk and lands on 21 for srv1/srv3/srv4 because 128 cores at 6 per slot is the binding axis now. The CPU axis landed in the SAME change as these literals for exactly that reason -- with no CPU term the minimum degenerates to memory alone and 29 would commit 29. Neither half of that pair is safe to carry without the other.\n\nTHESE ARE STILL AUTHORED LITERALS AND THAT IS STILL DEBT. test.claim.host_allocation_conservation derived_width_reproduces_every_authored_literal re-runs the arithmetic and joins it to each number here, which is validation standing where construction was available (DESIGN 5): the wall concedes the bad state is writable and catches it afterwards. The construction fix is for this function to CALL that derivation rather than restate its result, and it is blocked on an import cycle -- gunbc.ci_floor_measurement imports this module for the slot shape, so this module cannot import the measurement. Breaking it means moving the slot shape to its own authority, which is a separate change across roughly twenty-five files. Correcting these literals does NOT dissolve the second representation; it leaves a corrected copy where an uncorrected one stood."

Expand Down Expand Up @@ -173,7 +173,7 @@ data gunbc_runner_slot_allocation_srv3: HostRunnerSlotAllocation = gunbc_committ
host: operator_host_srv3
)

data gunbc_runner_slot_allocation_srv4_admission_note: String = "srv4 commits 6 slots at the memory axis (7 before the 2026-08-17 16GiB ruling) (no interactive sessions, per gunbc_runner_slot_width_ruling_note). Disk binding is NOT folded into gunbc_runner_slots_per_host anymore: the historical five-slot row pin is retired, and apply-time disk preflight in gunbc.runner_lifecycle refuses insufficient or unobservable headroom rather than absorbing to width 5. srv4_runner_host_deploy.runner_count and this roster both name 6 as the materialization target; vivid-eagle-131's apply_wet path must run runner_width_disk_preflight before ADD on srv4."
data gunbc_runner_slot_allocation_srv4_admission_note: String = "srv4 MEMORY-ADMITS 29 AND COMMITS 21, THE CPU AXIS BINDING (2026-08-23). This row said 'srv4 commits 6 slots at the memory axis' and that srv4_runner_host_deploy.runner_count and this roster 'both name 6 as the materialization target'. Both sentences were true when written and were falsified by the CPU axis landing; they are replaced rather than annotated, because two accounts of one width is what this module exists to prevent. Neither number is authored here: memory admission and the committed minimum are both derived, and runner_count on the deploy row derives from gunbc_runner_slots_per_host, so there is one authoring and this note is a reading of it.\n\nDISK BINDING IS STILL NOT FOLDED INTO gunbc_runner_slots_per_host. The historical five-slot row pin stays retired; host_disk_admitted_width returns DiskWidthUnconstrained and apply-time preflight in gunbc.runner_lifecycle refuses insufficient or unobservable headroom rather than absorbing to a lower width.\n\nAND AT WIDTH 21 THAT PREFLIGHT IS EXPECTED TO REFUSE srv4, WHICH IS A REAL CONSEQUENCE AND NOT A HYPOTHETICAL. runner_slot_disk_budget_per_slot is 40.96 GB, so the preflight charges 21 x 40.96 = about 860 GB against srv4's 500 GB NVMe. Recorded here because the allocation axis CANNOT see it -- disk is unconstrained at allocation by the 2026-08-06 ruling -- so this module commits a width whose materialization the actuator is expected to stop. That is the fail-closed arm working, and it means srv4 has a committed width it cannot currently reach.\n\nTHE 40.96 GB IS NOT A MEASUREMENT AND THE REFUSAL ABOVE INHERITS THAT. runner_slot_disk_budget_per_slot_note derives it from 'about 38GB per slot at width 7 on 500GB class disk' -- disk size divided by the desired width, so the charge was computed FROM the width it is now used to constrain. A separate observation of live per-slot usage under an active reclaimer came in near 2.5 GB, two orders off. So whether srv4 genuinely cannot hold 21 slots is UNRESOLVED, and the honest statement is that the model cannot currently tell: a circular charge refusing a derived width is two unmeasured numbers meeting. DISSOLVE-ON: a measured per-slot disk series on srv4, at which point either the preflight refusal is real and the committed width must answer for it, or the charge was an artifact and the refusal disappears."

data gunbc_runner_slot_allocation_srv4: HostRunnerSlotAllocation = gunbc_committed_host_runner_slot_allocation(
host: operator_host_srv4
Expand Down
Loading