Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
11c398e
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
08167c2
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
9aafd12
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
3bb4543
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
4a85d81
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
cb46d14
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
b8bed9f
Fix fleet-converge emit drift and decouple floor spawn cap from burst…
Jul 1, 2026
0bfcf4c
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
dcb1bfa
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
dccfd7e
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
c8d89da
Fix CI compile error, systemd $HOME trap, and swap accounting semantics.
Jul 1, 2026
461882e
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
70f03ed
Wire fabric predicates into plan consumer path and fix placement witn…
Jul 1, 2026
04b058f
Rename fabric_memory_accounting_sound to admissible.
Jul 1, 2026
de06b91
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
ff22fe2
Dissolve lifecycle map fork; lift operator identity to fleet_intent.
Jul 1, 2026
6ed0ae2
Tighten timer emit scaffold to shared bash-emit dissolution trigger.
Jul 1, 2026
21a2ce0
Address composer REQUEST_CHANGES: dedupe overhead, fix dispositions.
Jul 1, 2026
1bddae3
Merge remote-tracking branch 'origin/main' into session/merry-carp-25…
Jul 1, 2026
7789551
Rebind runner memory contract scaffold to compute_fabric dissolve tar…
Jul 1, 2026
2bdb7a7
Fix fabric admissibility gate and roster timer emit shell debt.
Jul 1, 2026
a870ab4
WIP: Fleet runner deployment process: idempotent host-self-selecting …
Jul 1, 2026
84ca10e
Gate deploy job off until srv1 deploy runner is live.
Jul 1, 2026
08f25d6
Collapse deploy readiness gate to vars.GUNBC_DEPLOY_RUNNER_READY only.
Jul 1, 2026
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
1 change: 1 addition & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ fresh_artifact_path() {
DESIGN.md*) return 0 ;;
.githooks/pre-push*) return 0 ;;
.github/fleet-converge.sh*) return 0 ;;
.github/fleet-converge-timer-upsert.sh*) return 0 ;;
docs/plans/idea-machine.md*) return 0 ;;
docs/plans/algebraic-rewrite-optimization.md*) return 0 ;;
docs/plans/dsl-v2-defork-audit.md*) return 0 ;;
Expand Down
39 changes: 39 additions & 0 deletions .github/fleet-converge-timer-upsert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -euo pipefail
# GENERATED by dsl/gunbc/fleet_converge_timer_emit.dag (gunbc.fleet_converge_timer_emit). DO NOT HAND-EDIT.
# Idempotent per-host upsert: write service+timer units, daemon-reload, enable timer.
# The converge script self-selects via $(hostname -s); no SSH star required for steady-state.

svc_path="/etc/systemd/system/gunbc-fleet-converge.service"
timer_path="/etc/systemd/system/gunbc-fleet-converge.timer"
mkdir -p "$(dirname "$svc_path")"

cat > "$svc_path" <<'GUNBC_FLEET_CONVERGE_SERVICE_EOF'
[Unit]
Description=gunbc fleet converge (host-self-selecting reconcile)
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
User=briansrls
ExecStart=/usr/bin/bash /home/briansrls/ctrl/third_party/gunbc/.github/fleet-converge.sh
RemainAfterExit=no
GUNBC_FLEET_CONVERGE_SERVICE_EOF

cat > "$timer_path" <<'GUNBC_FLEET_CONVERGE_TIMER_EOF'
[Unit]
Description=gunbc fleet converge periodic reconcile

[Timer]
OnBootSec=120s
OnUnitActiveSec=600s
Unit=gunbc-fleet-converge.service

[Install]
WantedBy=timers.target
GUNBC_FLEET_CONVERGE_TIMER_EOF

systemctl daemon-reload
systemctl enable --now gunbc-fleet-converge.timer
printf 'fleet-converge-timer-receipt host=%s verdict=converged\n' "$(hostname -s 2>/dev/null || echo unknown)"
30 changes: 18 additions & 12 deletions .github/fleet-converge.sh
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,12 @@ emit_sessions_membership() {
}

host_begin "srv1"
converge_gunbc_pinned_tree "srv1" "gunbc" "pinned_tree_sha" "existing_host_quiescent" "skip_process_pin_coherent_and_marker" "GUNBC_ROOT" "$HOME/.local/share/gunbc/pinned" "defer_submodule" "third_party/gunbc" "$HOME/ctrl" "ghcr.io/gunb-ai/gunbc/bootstrap" "sha256:BOOTSTRAP_DIGEST_PLACEHOLDER" "gunbc" "scripts/session-dashboard/container/read-gunbc-pin.sh" ".dashboard/converge-green-place.marker" "pin=" "first_green_at=" "scripts/session-dashboard/bin/gunbc-pin-quiescent-reload.mjs"
converge_slice_property "srv1" "runner" "runner_slice_cap_bytes" "system-actions-runner.slice" "MemoryMax" "85899345920" "85899345920" "85899345920"
converge_per_slot_cap "srv1" "runner" "per_slot_memory_max_bytes" "/etc/systemd/system/actions-runner@.service.d/20-fleet-width.conf" "actions-runner@srv1-*.service" "MemoryMax" "8589934592"
converge_per_slot_cap "srv1" "runner" "per_slot_memory_swap_max_bytes" "/etc/systemd/system/actions-runner@.service.d/30-fleet-swap.conf" "actions-runner@srv1-*.service" "MemorySwapMax" "0"
converge_gunbc_pinned_tree "srv1" "gunbc" "pinned_tree_sha" "existing_host_quiescent" "skip_process_pin_coherent_and_marker" "GUNBC_ROOT" "/home/briansrls/.local/share/gunbc/pinned" "defer_submodule" "third_party/gunbc" "/home/briansrls/ctrl" "ghcr.io/gunb-ai/gunbc/bootstrap" "sha256:BOOTSTRAP_DIGEST_PLACEHOLDER" "gunbc" "scripts/session-dashboard/container/read-gunbc-pin.sh" ".dashboard/converge-green-place.marker" "pin=" "first_green_at=" "scripts/session-dashboard/bin/gunbc-pin-quiescent-reload.mjs"
converge_slice_property "srv1" "runner" "runner_slice_cap_bytes" "system-actions-runner.slice" "MemoryMax" "111669149696" "111669149696" "111669149696"
converge_per_slot_cap "srv1" "runner" "per_slot_memory_max_bytes" "/etc/systemd/system/actions-runner@.service.d/20-fleet-width.conf" "actions-runner@srv1-*.service" "MemoryMax" "25769803776"
converge_per_slot_cap "srv1" "runner" "per_slot_memory_swap_max_bytes" "/etc/systemd/system/actions-runner@.service.d/30-fleet-swap.conf" "actions-runner@srv1-*.service" "MemorySwapMax" "8589934592"
converge_per_slot_cap "srv1" "runner" "per_slot_memory_high_bytes" "/etc/systemd/system/actions-runner@.service.d/40-fleet-high.conf" "actions-runner@srv1-*.service" "MemoryHigh" "15032385536"
converge_slice_property "srv1" "runner" "oom_pressure_auto" "system-actions-runner.slice" "ManagedOOMMemoryPressure" "auto" "auto" "true"
converge_slice_property "srv1" "runner" "cpu_weight" "system-actions-runner.slice" "CPUWeight" "100" "100" "100"
converge_jobserver_tokens "srv1" "runner" "build_tokens" "/etc/default/ctrl-jobserver" "CTRL_JOBSERVER_TOKENS" "ctrl-jobserver.service" "128"
converge_runner_width "srv1" "runner" "runner_count" "actions-runner@srv1-*.service" "10"
Expand All @@ -288,10 +290,12 @@ converge_slice_property "srv1" "sessions" "cpu_weight" "sessions.slice" "CPUWeig
emit_sessions_membership "srv1" "/sys/fs/cgroup/sessions.slice" "/sys/fs/cgroup/system.slice"
host_summary "srv1"
host_begin "srv2"
converge_gunbc_pinned_tree "srv2" "gunbc" "pinned_tree_sha" "existing_host_quiescent" "skip_process_pin_coherent_and_marker" "GUNBC_ROOT" "$HOME/.local/share/gunbc/pinned" "defer_submodule" "third_party/gunbc" "$HOME/ctrl" "ghcr.io/gunb-ai/gunbc/bootstrap" "sha256:BOOTSTRAP_DIGEST_PLACEHOLDER" "gunbc" "scripts/session-dashboard/container/read-gunbc-pin.sh" ".dashboard/converge-green-place.marker" "pin=" "first_green_at=" "scripts/session-dashboard/bin/gunbc-pin-quiescent-reload.mjs"
converge_slice_property "srv2" "runner" "runner_slice_cap_bytes" "system-actions-runner.slice" "MemoryMax" "85899345920" "85899345920" "85899345920"
converge_per_slot_cap "srv2" "runner" "per_slot_memory_max_bytes" "/etc/systemd/system/actions-runner@.service.d/20-fleet-width.conf" "actions-runner@srv2-*.service" "MemoryMax" "8589934592"
converge_per_slot_cap "srv2" "runner" "per_slot_memory_swap_max_bytes" "/etc/systemd/system/actions-runner@.service.d/30-fleet-swap.conf" "actions-runner@srv2-*.service" "MemorySwapMax" "0"
converge_gunbc_pinned_tree "srv2" "gunbc" "pinned_tree_sha" "existing_host_quiescent" "skip_process_pin_coherent_and_marker" "GUNBC_ROOT" "/home/briansrls/.local/share/gunbc/pinned" "defer_submodule" "third_party/gunbc" "/home/briansrls/ctrl" "ghcr.io/gunb-ai/gunbc/bootstrap" "sha256:BOOTSTRAP_DIGEST_PLACEHOLDER" "gunbc" "scripts/session-dashboard/container/read-gunbc-pin.sh" ".dashboard/converge-green-place.marker" "pin=" "first_green_at=" "scripts/session-dashboard/bin/gunbc-pin-quiescent-reload.mjs"
converge_slice_property "srv2" "runner" "runner_slice_cap_bytes" "system-actions-runner.slice" "MemoryMax" "111669149696" "111669149696" "111669149696"
converge_per_slot_cap "srv2" "runner" "per_slot_memory_max_bytes" "/etc/systemd/system/actions-runner@.service.d/20-fleet-width.conf" "actions-runner@srv2-*.service" "MemoryMax" "25769803776"
converge_per_slot_cap "srv2" "runner" "per_slot_memory_swap_max_bytes" "/etc/systemd/system/actions-runner@.service.d/30-fleet-swap.conf" "actions-runner@srv2-*.service" "MemorySwapMax" "8589934592"
converge_per_slot_cap "srv2" "runner" "per_slot_memory_high_bytes" "/etc/systemd/system/actions-runner@.service.d/40-fleet-high.conf" "actions-runner@srv2-*.service" "MemoryHigh" "15032385536"
converge_slice_property "srv2" "runner" "oom_pressure_auto" "system-actions-runner.slice" "ManagedOOMMemoryPressure" "auto" "auto" "true"
converge_slice_property "srv2" "runner" "cpu_weight" "system-actions-runner.slice" "CPUWeight" "100" "100" "100"
converge_jobserver_tokens "srv2" "runner" "build_tokens" "/etc/default/ctrl-jobserver" "CTRL_JOBSERVER_TOKENS" "ctrl-jobserver.service" "128"
converge_runner_width "srv2" "runner" "runner_count" "actions-runner@srv2-*.service" "10"
Expand All @@ -303,10 +307,12 @@ converge_slice_property "srv2" "sessions" "cpu_weight" "sessions.slice" "CPUWeig
emit_sessions_membership "srv2" "/sys/fs/cgroup/sessions.slice" "/sys/fs/cgroup/system.slice"
host_summary "srv2"
host_begin "srv3"
converge_gunbc_pinned_tree "srv3" "gunbc" "pinned_tree_sha" "fresh_standup" "skip_process_pin_coherent_and_marker" "GUNBC_ROOT" "$HOME/.local/share/gunbc/pinned" "defer_submodule" "third_party/gunbc" "$HOME/ctrl" "ghcr.io/gunb-ai/gunbc/bootstrap" "sha256:BOOTSTRAP_DIGEST_PLACEHOLDER" "gunbc" "scripts/session-dashboard/container/read-gunbc-pin.sh" ".dashboard/converge-green-place.marker" "pin=" "first_green_at=" "scripts/session-dashboard/bin/gunbc-pin-quiescent-reload.mjs"
converge_slice_property "srv3" "runner" "runner_slice_cap_bytes" "system-actions-runner.slice" "MemoryMax" "85899345920" "85899345920" "85899345920"
converge_per_slot_cap "srv3" "runner" "per_slot_memory_max_bytes" "/etc/systemd/system/actions-runner@.service.d/20-fleet-width.conf" "actions-runner@srv3-*.service" "MemoryMax" "8589934592"
converge_per_slot_cap "srv3" "runner" "per_slot_memory_swap_max_bytes" "/etc/systemd/system/actions-runner@.service.d/30-fleet-swap.conf" "actions-runner@srv3-*.service" "MemorySwapMax" "0"
converge_gunbc_pinned_tree "srv3" "gunbc" "pinned_tree_sha" "fresh_standup" "skip_process_pin_coherent_and_marker" "GUNBC_ROOT" "/home/briansrls/.local/share/gunbc/pinned" "defer_submodule" "third_party/gunbc" "/home/briansrls/ctrl" "ghcr.io/gunb-ai/gunbc/bootstrap" "sha256:BOOTSTRAP_DIGEST_PLACEHOLDER" "gunbc" "scripts/session-dashboard/container/read-gunbc-pin.sh" ".dashboard/converge-green-place.marker" "pin=" "first_green_at=" "scripts/session-dashboard/bin/gunbc-pin-quiescent-reload.mjs"
converge_slice_property "srv3" "runner" "runner_slice_cap_bytes" "system-actions-runner.slice" "MemoryMax" "111669149696" "111669149696" "111669149696"
converge_per_slot_cap "srv3" "runner" "per_slot_memory_max_bytes" "/etc/systemd/system/actions-runner@.service.d/20-fleet-width.conf" "actions-runner@srv3-*.service" "MemoryMax" "25769803776"
converge_per_slot_cap "srv3" "runner" "per_slot_memory_swap_max_bytes" "/etc/systemd/system/actions-runner@.service.d/30-fleet-swap.conf" "actions-runner@srv3-*.service" "MemorySwapMax" "8589934592"
converge_per_slot_cap "srv3" "runner" "per_slot_memory_high_bytes" "/etc/systemd/system/actions-runner@.service.d/40-fleet-high.conf" "actions-runner@srv3-*.service" "MemoryHigh" "15032385536"
converge_slice_property "srv3" "runner" "oom_pressure_auto" "system-actions-runner.slice" "ManagedOOMMemoryPressure" "auto" "auto" "true"
converge_slice_property "srv3" "runner" "cpu_weight" "system-actions-runner.slice" "CPUWeight" "100" "100" "100"
converge_jobserver_tokens "srv3" "runner" "build_tokens" "/etc/default/ctrl-jobserver" "CTRL_JOBSERVER_TOKENS" "ctrl-jobserver.service" "128"
converge_runner_width "srv3" "runner" "runner_count" "actions-runner@srv3-*.service" "10"
Expand Down
2 changes: 2 additions & 0 deletions dsl/extdeps/os/systemd.dag
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ data systemd_memory_max_property: NonEmptyStr = "MemoryMax"

data systemd_memory_swap_max_property: NonEmptyStr = "MemorySwapMax"

data systemd_memory_high_property: NonEmptyStr = "MemoryHigh"

data systemd_cpu_weight_property: NonEmptyStr = "CPUWeight"

fn parse_systemd_unit_active_state(raw: String) -> SystemdUnitActiveState? {
Expand Down
65 changes: 64 additions & 1 deletion dsl/gunbc/bmc_onboarding.dag
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@ module gunbc.bmc_onboarding
import std.bmc { BmcEndpoint, Redfish }
import std.credentials { FactoryLogin, CredentialFlow, Stored }
import std.os.types { OperatingSystemProduct, UbuntuOs, NobleNumbat2404Lts }
import std.types { NonEmptyStr, Int, List }
import std.types { NonEmptyStr, Int, List, Map }
import std.logic { Bool }
import std.disposition { Disposition, Scaffold, SingleAuthority, Terminal }
import std.decl_ref { DeclarationRef, WholeDeclaration }
import product.placement_supply { HostIdentity }
import gunbc.fleet_intent_network {
operator_host_srv1,
operator_host_srv2,
operator_host_srv3,
}
import extdeps.bmc.types { RedfishBootSourceOverrideTarget, BootTargetPxe, RedfishAccountRole, AccountRoleAdministrator }
import extdeps.bmc.openbmc { openbmc_factory_login }
import extdeps.boards.asrock_rack { asrock_altrad8ud_redfish_system_id }
Expand Down Expand Up @@ -232,3 +240,58 @@ fn bmc_credential_probe_to_phase(probe: BmcCredentialProbeResult) -> BmcOnboardi
CredentialStateUnknown { reason: _ } => Absent
}
}

type HostOnboardingLifecycleRow {
identity: HostIdentity
phase: BmcOnboardingPhase
}

data fleet_host_onboarding_lifecycle_disposition: Disposition = Scaffold {
dissolves_to: SingleAuthority,
bind: DeclarationRef {
module_path: "gunbc.bmc_onboarding",
decl_name: "fleet_host_onboarding_lifecycle",
field: WholeDeclaration
}
}

data srv1_bmc_lifecycle_phase: BmcOnboardingPhase = OsInstalled

data srv2_bmc_lifecycle_phase: BmcOnboardingPhase = OsInstalled

data srv3_bmc_lifecycle_phase: BmcOnboardingPhase = CredentialsRotated

data fleet_host_onboarding_lifecycle: List<HostOnboardingLifecycleRow> = [
HostOnboardingLifecycleRow { identity: operator_host_srv1, phase: srv1_bmc_lifecycle_phase },
HostOnboardingLifecycleRow { identity: operator_host_srv2, phase: srv2_bmc_lifecycle_phase },
HostOnboardingLifecycleRow { identity: operator_host_srv3, phase: srv3_bmc_lifecycle_phase },
]

fn fleet_host_lifecycle_phase_map_derived(rows: List<HostOnboardingLifecycleRow>) -> Map<String, BmcOnboardingPhase> {
rows |> fold(init: empty_map(), f: (acc, row) => map_insert(acc, row.identity, row.phase))
}

fn host_onboarding_lifecycle_row(host: HostIdentity) -> HostOnboardingLifecycleRow? {
match map_get(fleet_host_lifecycle_phase_map_derived(rows: fleet_host_onboarding_lifecycle), host) {
Present { value: phase } =>
Present { value: HostOnboardingLifecycleRow { identity: host, phase: phase } }
Absent => Absent
}
}

fn host_onboarding_lifecycle_phase(host: HostIdentity) -> BmcOnboardingPhase? {
map_get(fleet_host_lifecycle_phase_map_derived(rows: fleet_host_onboarding_lifecycle), host)
}

data bmc_phase_is_pre_os_installed_disposition: Disposition = Terminal {
reason: "Canonical exhaustive partition on closed BmcOnboardingPhase ladder: FactoryDefault|CredentialsRotated are pre-OsInstalled; OsInstalled|FabricJoined are installed+. FreshStandup apply boundary in host_converge.gunbc_apply_mode_for_host mirrors this match — not a nickname predicate."
}

fn bmc_phase_is_pre_os_installed(phase: BmcOnboardingPhase) -> Bool {
match phase {
FactoryDefault => true
CredentialsRotated => true
OsInstalled => false
FabricJoined => false
}
}
8 changes: 7 additions & 1 deletion dsl/gunbc/ci_deploy_access.dag
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ type DeployAccess {

data gunbc_deploy_sudoers_dropin: NonEmptyStr = "/etc/sudoers.d/gunbc-deploy"

data ci_deploy_runner_principal: NonEmptyStr = "runner"
data gunbc_deploy_runner_principal: NonEmptyStr = "gunbc-deploy"

data ci_deploy_runner_principal: NonEmptyStr = gunbc_deploy_runner_principal

fn deploy_access_command_paths(access: DeployAccess) -> List<NonEmptyStr> {
map(access.privileged_commands, cmd => cmd.path)
}

fn srv1_live_deploy_privileged_commands() -> List<PrivilegedCommand> {
[
Expand Down
Loading
Loading