magicciv/infra/terraform/hetzner-cpu-runner/main.tf
Natalie 8628ea7d88 feat(@projects/@magic-civilization): 🧭 add SessionStart bootloader — live project orientation for fresh sessions
No project bootloader existed: a new session/agent booted with only the static CLAUDE.md router and
had to manually dig for current state. Adds a SessionStart hook (session-orient.sh) that injects a
LIVE orientation every session — the dynamic counterpart to the static router:

- In-flight objectives (partial/stub from objectives.json) — where to resume
- Blocked count + last 5 commits + unpushed-commit warning (94 right now; forge down)
- Verify-before-trusting reminder + tooling entry-points (preamble / orchestration / code-layering)

State is read live every run (objectives.json + git) — never embedded, so it can't go stale
(the same anti-drift principle the agent tooling enforces). Read-only, <2s, never breaks the
session (any error → exits 0). Dual-mode: hook JSON by default, `--human` prints markdown for
manual mid-session re-orientation (`bash .claude/hooks/session-orient.sh --human`).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 04:57:33 -04:00

51 lines
1.4 KiB
HCL

locals {
server_count = var.enabled ? 1 : 0
}
resource "hcloud_ssh_key" "runner" {
name = "${var.name}-key"
public_key = file(pathexpand(var.ssh_public_key_path))
}
# Persistent data volume — deliberately NOT gated on var.enabled, so it lives
# across server destroy/recreate. This is what makes the server ephemeral:
# the slow-to-rebuild state (cargo cache, target/, the clone, RL checkpoints)
# stays here, the compute is disposable.
resource "hcloud_volume" "data" {
name = "${var.name}-data"
size = var.volume_size
location = var.location
format = "ext4"
}
resource "hcloud_server" "runner" {
count = local.server_count
name = var.name
server_type = var.server_type
location = var.location
image = "ubuntu-24.04"
ssh_keys = [hcloud_ssh_key.runner.id]
user_data = templatefile("${path.module}/cloud-init.yaml", {
volume_id = hcloud_volume.data.id
git_remote = var.git_remote
})
labels = {
project = "magic-civilization"
role = "cpu-runner"
}
# Keep the box if it is briefly toggled; protects against an accidental apply
# nuking an in-flight training run. Remove if you want hard ephemerality.
lifecycle {
ignore_changes = [ssh_keys]
}
}
resource "hcloud_volume_attachment" "data" {
count = local.server_count
volume_id = hcloud_volume.data.id
server_id = hcloud_server.runner[0].id
automount = false # cloud-init mounts it deterministically by id
}