Commit graph

3 commits

Author SHA1 Message Date
6d52b3c623 provisioning-reconciler-demo: wire-announce readiness + --docker node kind
Replace the per-attempt key-file side channel (DEMO_NODE_KEY_FILE,
read_key_report, JoinCheck) with a control-plane announce: node roles
send a tagged gossip frame {attempt, logical_node, key_hex,
endpoint_addr_json} after joining and every heartbeat thereafter.

- iroh-driver: IrohDriver::send_tagged_gossip — fire-and-forget
  tag-routed gossip egress for bridge-less clients (reuses cached/join
  connections, dials with backoff).
- provisioning: BootstrapMsg::Announce — first delivery while
  bootstrapping completes the attempt (collector + exactly-once
  Bootstrapped report); duplicates, misrouted attempts, and
  terminal-phase announces drop. Unit-tested.
- xtask demo: AnnounceActor decodes the tag-routed frame and forwards
  by attempt to the owning bootstrap actor; last_announce_ms is the
  wire heartbeat. LocalProcessLogic keeps only process lifecycle.
- --docker: DockerProcessLogic (kind "docker") — attached
  "docker run --rm" child on a per-run labeled bridge network
  (foreign-node masking: per-container IPs, gateway-dialed
  supervisor). Standalone scratch image from the static-musl xtask
  binary (37MB), staged one-file build context. The container is
  force-removed on every terminal path so a SIGKILLed docker CLI
  cannot orphan a running container.
- Cleanup: no volumes/mounts; label-filtered exit sweep (SIGINT and
  SIGTERM both drain first) + startup sweep of stale demo resources;
  images persist per run token.

Verified live: process kind (kill -> replacement in 3.4s, provision/
remove/kill waves, zero orphans) and docker kind (8-node abuse waves
across docker kill, mid-provision control kills, CLI SIGKILL orphans
force-removed, SIGKILL-crash leftovers swept on restart, clean exits
leave zero containers/networks/CLIs). provisioning 22 + iroh-driver
13 tests pass.
2026-08-16 20:34:15 +04:00
1926e73064 feat(dashboard): Segment Mask visual world and merged Fleet Control
Fleet page: drop the aggregate totals row and bar skeletons — cards carry
identity, liveness, and runtime summary; hardware detail stays one click
down. Stream descriptors (origin/label) now ride FrameEvents into the
fleet view, so the orchestrator renders as a full-width amber-framed
module pinned above the grid. Cards are real links; roster rows are
keyboard-operable.

Fleet Control: /view/reconciler folds into /view/demo-control as one
control bench — ghost-segment ready/desired counter, generation digit,
unified node rows (reconciler stage + pid + state + kill), activity feeds
demoted to a collapsed tail. The standalone reconciler page is retired;
its API stays live to feed the merge.

Visual world (both themes, nav toggle, persisted, prefers-color-scheme
default): dark = Bloomberg night housing (black ground, navy panels,
amber data register); light = Atom One Light. 2px corners, monospace
data, outline chips for states, cyan as the only interactive voice,
ghost-eight segments for counters, blink reserved for unresolved states,
depressing controls, reduced-motion collapse.
2026-08-16 15:16:30 +04:00
d19dd91324 feat(xtask): provisioning-reconciler-demo with live fleet control
`cargo xtask provisioning-reconciler-demo [--port n] [--nodes n]` boots a
lightweight orchestrator for visual, human-checked E2E confirmation of the
provisioning reconciler: swactor engine + real ClusterDriver + demo
provider, with node children re-exec'ing the same xtask binary in node
role and joining the supervisor over real iroh connections.

- supervisor actor owns driver/provider/shape on a 250ms wall-clock tick,
  mirroring the production ClusterReconciler poll semantics; emits
  prov.reconciler.events/snapshot plus per-node lifecycle/status streams
- k8s-styled reconciler view: ready/desired header, node stage cards,
  commands-out and events-in feeds
- dashboard `demo-control` feature: POST /control/{kill,provision,remove}
  + Fleet Control view; regular builds compile none of it (symbol-verified)
- fleet cards fold proc.<node>.lifecycle and node.status heartbeats into
  per-node pid/state pills that stay live
- hardening: exe resolution survives binary replacement by rebuilds,
  spawn failures feed back as BootstrapFailed so the reconciler retries
  instead of wedging at SshReady, teardown skips exit waits for
  never-started children

Verified in-browser: boot 3/3 converged with real joins; dashboard kill
dips and fully recovers with a replacement; provision +1 → 4/4; remove −2
graceful teardown → 2/2; child process count matches reconciler nodes.
2026-08-15 18:11:33 +04:00