diff --git a/docs/coordinator.md b/docs/coordinator.md index 4fc39040..454f17ee 100644 --- a/docs/coordinator.md +++ b/docs/coordinator.md @@ -241,10 +241,10 @@ On startup, `auto_update::run` classifies every agent by rev freshness (the per-agent `.{name}.hyperhive-rev` marker under `/var/lib/hyperhive/applied/` vs the current flake path) and persisted `wanted` intent, then: -1. **Config path** — when *any* marker is stale, submit one `StartupSweep` - DAG: a `MetaLock` (hyperhive input bump, non-fatal) that fans out `Rebuild` - children for the stale agents whose `wanted = Up` (topology-sorted, parents - first). Stale but wanted-offline agents get no boot-time nix work — their +1. **Config path** — when *any* marker is stale, submit one `Boot` + DAG: a `MetaLock` (hyperhive input bump, non-fatal) that grows an in-DAG + `Rebuild` subgraph for each stale agent whose `wanted = Up` (topology-sorted, + parents first). Stale but wanted-offline agents get no boot-time nix work — their rebuild happens on their next start (the start submit path upgrades a stale start to rebuild+start), which is also why the lock bump runs even when every stale agent is offline: those later start-upgrades must build diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index 85c9b405..2cbcd685 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -207,9 +207,9 @@ One operation runs at a time; the worker drains FIFO. Each row shows a state glyph (`⏸` queued / `▶` running / `✔` done / `✖` failed / `⊘` cancelled), kind glyph + verb (`↻ rebuild`, `◆ meta_update`, `✨ spawn`, `🗑 destroy`, `↺ restart`, -`⚡ startup_sweep`, `🔑 perm_change`, `⏹ graceful_stop`, `▶ start`, +`⚡ boot`, `🔑 perm_change`, `⏹ graceful_stop`, `▶ start`, `■ stop`), agent name, -source chip (`manual | meta_update | auto_update | startup_sweep | crash_recover | approval` +source chip (`manual | meta_update | auto_update | crash_recover | approval` — green for operator-approved config changes), timing, and an optional reason / error. A multi-step op is a single DAG: its per-agent subgraphs and sub-steps (a meta-update cascade's per-agent diff --git a/frontend/packages/dashboard/src/builds.js b/frontend/packages/dashboard/src/builds.js index cab99c11..2d03aaf6 100644 --- a/frontend/packages/dashboard/src/builds.js +++ b/frontend/packages/dashboard/src/builds.js @@ -126,7 +126,7 @@ const QUEUE_KIND_GLYPH = { spawn: '✨', destroy: '🗑', restart: '↺', - startup_sweep: '⚡', + boot: '⚡', perm_change: '🔑', graceful_stop: '⏹', start: '▶', diff --git a/frontend/packages/dashboard/src/system-sections.css b/frontend/packages/dashboard/src/system-sections.css index 0f44070b..899d6f46 100644 --- a/frontend/packages/dashboard/src/system-sections.css +++ b/frontend/packages/dashboard/src/system-sections.css @@ -128,7 +128,6 @@ .rqe-source-manual { color: var(--cyan); border-color: var(--cyan); } .rqe-source-meta_update { color: var(--purple); border-color: var(--purple); } .rqe-source-auto_update { color: var(--muted); } -.rqe-source-startup_sweep { color: var(--muted); } .rqe-source-crash_recover { color: var(--amber); border-color: var(--amber); } .rqe-source-approval { color: var(--green); border-color: var(--green); } .rqe-when { color: var(--muted); font-size: 0.85em; } diff --git a/hive-c0re/src/job_queue/exec.rs b/hive-c0re/src/job_queue/exec.rs index 99b7bfc2..f2ec537c 100644 --- a/hive-c0re/src/job_queue/exec.rs +++ b/hive-c0re/src/job_queue/exec.rs @@ -98,9 +98,6 @@ pub(super) async fn run_node(coord: &Arc, claim: &Claim) -> Result< NodeKind::WriteDropin => run_write_dropin(coord, claim).await, NodeKind::WritePermFile => run_write_perm_file(coord, claim, &ctx).await, NodeKind::ApprovalDeploy => run_approval_deploy(coord, claim).await, - // A pure grouping anchor (boot root): no work, completes immediately so - // its child DAGs settle it and the boot tree resolves. - NodeKind::Noop => Ok(NodeOutput::default()), NodeKind::SetWanted { up } => run_set_wanted(coord, claim, *up), } } diff --git a/hive-c0re/src/job_queue/model.rs b/hive-c0re/src/job_queue/model.rs index 60f7f21b..cf088df9 100644 --- a/hive-c0re/src/job_queue/model.rs +++ b/hive-c0re/src/job_queue/model.rs @@ -115,11 +115,6 @@ pub enum NodeKind { /// deploy stays inside `actions.rs` in v1 — deliberately not /// modeled as scheduler nodes (see the design doc §9). ApprovalDeploy, - /// No-op anchor that completes immediately with no work. Vestigial since - /// the boot sweep became one in-DAG graph (no `boot_root` anchor / child - /// DAGs) — slated for removal with the other `StartupSweep` residuals. - /// Holds no lease and no build slot. - Noop, /// Write the agent's durable power intent (`wanted = Up` when `up`, else /// `Offline`) as a first-class DAG node, at the head of a power-op /// template so the downstream `Reconcile` reads it. Replaces the old @@ -154,7 +149,6 @@ impl NodeKind { NodeKind::WriteDropin => "write_dropin", NodeKind::WritePermFile => "write_perm_file", NodeKind::ApprovalDeploy => "approval_deploy", - NodeKind::Noop => "noop", NodeKind::SetWanted { .. } => "set_wanted", } } diff --git a/hive-c0re/src/job_queue/templates.rs b/hive-c0re/src/job_queue/templates.rs index 73ec92d3..31b2693c 100644 --- a/hive-c0re/src/job_queue/templates.rs +++ b/hive-c0re/src/job_queue/templates.rs @@ -210,11 +210,10 @@ pub fn meta_update( } } -// The boot is now assembled inline in `workers/auto_update.rs::submit_boot_tree` -// as ONE DAG (a sweep `MetaLock` root that grows rebuild subgraphs in-DAG, plus -// a `Reconcile` root per drifted agent) — no `boot_root` Noop anchor, no -// `startup_sweep` parent template, no per-agent child DAGs. The old single-use -// `boot_root` / `startup_sweep` builders were inlined there and removed. +// The boot is assembled inline in `workers/auto_update.rs::submit_boot_tree` +// as ONE `Boot` DAG (a sweep `MetaLock` root that grows rebuild subgraphs +// in-DAG, plus a `Reconcile` root per drifted agent) — no anchor node and no +// per-agent child DAGs. /// Validate a spec before it enters the queue: node ids are dense /// (index = id), deps reference existing nodes, and the dep graph is diff --git a/hive-c0re/src/workers/auto_update.rs b/hive-c0re/src/workers/auto_update.rs index 23c2283d..d115e232 100644 --- a/hive-c0re/src/workers/auto_update.rs +++ b/hive-c0re/src/workers/auto_update.rs @@ -1,7 +1,7 @@ //! Boot reconcile: on `hive-c0re serve` boot, (a) run the config path -//! for agents whose per-agent rev marker is stale — a `StartupSweep` -//! DAG (meta hyperhive lock bump) fanning out `Rebuild` children for -//! the stale agents whose `wanted` power intent is `Up` — and (b) +//! for agents whose per-agent rev marker is stale — one `Boot` DAG +//! (meta hyperhive lock bump) that grows a `Rebuild` subgraph for each +//! stale agent whose `wanted` power intent is `Up` — and (b) //! converge every other drifted agent to its persisted `wanted` via //! `Reconcile` DAGs. Two rules keep boot-time nix work minimal: //! @@ -194,10 +194,10 @@ pub fn topology_sort( } /// Boot reconcile (see the module doc): classify every agent by rev -/// freshness + persisted `wanted` intent, submit one `StartupSweep` -/// DAG (hyperhive lock bump → fan-out rebuilds for stale wanted-up -/// agents) when anything is stale, and `Reconcile` DAGs for agents -/// whose observed power state drifted from `wanted`. Returns Ok even +/// freshness + persisted `wanted` intent, submit one `Boot` DAG +/// (hyperhive lock bump growing an in-DAG rebuild subgraph per stale +/// wanted-up agent) when anything is stale, and `Reconcile` DAGs for +/// agents whose observed power state drifted from `wanted`. Returns Ok even /// if some submissions failed. pub async fn run(coord: Arc) -> Result<()> { let containers = match lifecycle::list().await { @@ -287,8 +287,8 @@ pub async fn run(coord: Arc) -> Result<()> { Ok(()) } -/// Submit this boot's work as **one DAG** (no `boot_root` Noop anchor, no -/// per-agent child DAGs). Node 0 is the sweep `MetaLock` (only when +/// Submit this boot's work as **one DAG** (no anchor node, no per-agent +/// child DAGs). Node 0 is the sweep `MetaLock` (only when /// something is stale) — its executor bumps the hyperhive lock, then grows /// one rebuild subgraph per stale agent into *this same* DAG (rooted on the /// `MetaLock`, so they build against the post-bump lock; see diff --git a/hive-sh4re/src/jobs.rs b/hive-sh4re/src/jobs.rs index 9a85432f..d060a1ba 100644 --- a/hive-sh4re/src/jobs.rs +++ b/hive-sh4re/src/jobs.rs @@ -17,16 +17,13 @@ pub enum Template { /// Rebuild one agent's container (prebuild → stop → profile-swap → /// reconcile). Rebuild, - /// Bump meta flake locks; child `Rebuild` DAGs fan out on - /// completion for every affected agent. + /// Bump meta flake locks; grows a rebuild subgraph per affected + /// agent into the same DAG on completion. MetaUpdate, /// First-deploy spawn (approval-driven). Spawn, /// Reserved for a future destroy integration. Destroy, - /// Boot-time config sweep (hyperhive lock bump + stale-agent - /// rebuild fan-out). - StartupSweep, /// Mechanical stop + converge to `wanted = Up` (a restart). Restart, /// Signal → drain → mechanical stop → converge to `wanted = Up` — a @@ -45,9 +42,9 @@ pub enum Template { /// Bare converge of observed power state to the persisted intent /// (boot reconcile). Reconcile, - /// Boot-time root anchor: a single no-op node that groups this boot's - /// `StartupSweep` + per-agent `Reconcile` child DAGs under one tree, so the - /// dashboard renders the whole boot as one entry instead of N+1 rows. + /// Boot-time config sweep as one DAG: a hyperhive lock bump that grows + /// a rebuild subgraph per stale agent, plus a `Reconcile` per drifted + /// agent — all in a single DAG (no anchor node, no child DAGs). Boot, } @@ -59,7 +56,6 @@ impl Template { Template::MetaUpdate => "meta_update", Template::Spawn => "spawn", Template::Destroy => "destroy", - Template::StartupSweep => "startup_sweep", Template::Restart => "restart", Template::GracefulRestart => "graceful_restart", Template::PermChange => "perm_change", @@ -79,12 +75,10 @@ impl Template { pub enum Source { /// Operator action (dashboard button, CLI, manager tool). Manual, - /// Cascade child of a `MetaUpdate` DAG's fan-out. + /// Meta-update cascade rebuild (grown into the meta-update DAG). MetaUpdate, - /// Boot-time submission (sweep parent, boot reconciles). + /// Boot-time submission (the boot sweep DAG + boot reconciles). AutoUpdate, - /// Cascade child of a `StartupSweep` DAG's fan-out. - StartupSweep, /// Crash recovery path (future use). CrashRecover, /// Operator approved a pending `Approval` row; `approval_id` on @@ -99,7 +93,6 @@ impl Source { Source::Manual => "manual", Source::MetaUpdate => "meta_update", Source::AutoUpdate => "auto_update", - Source::StartupSweep => "startup_sweep", Source::CrashRecover => "crash_recover", Source::Approval => "approval", }