docs(coordinator): a DAG is declared, not described

The submit-time petgraph `toposort` this described is gone — a cycle
needs an edge pointing at a node declared later, and a handle only
exists for a node already declared. Say why the validation pass is
absent rather than leaving a description of one that isn't there.

`templates.rs`'s module doc was 35 lines and over the comment-block
lint's max; it now points here for the reasoning instead of restating
it, and drops the power-op paragraph that `submit.rs` already owns.
This commit is contained in:
atlas 2026-08-02 13:06:01 +02:00 committed by mara
commit ec16b80415
2 changed files with 19 additions and 26 deletions

View file

@ -23,9 +23,15 @@ dashboard group; the **node** is the unit of scheduling / execution /
build-log. Deps are intra-DAG edges only (`AfterOk` by default:
the dep must succeed, a failed/cancelled dep cancels the dependent —
cancel-downstream). Cross-DAG ordering comes from the per-agent lease,
never from edges between DAGs. Submit-time validation (petgraph `toposort`)
rejects cyclic specs outright, fixing the old queue's "circular dep silently
deadlocks" caveat.
never from edges between DAGs.
A DAG is **declared, not described**: a template builds it through
`hive_jobq::JobBuilder`, naming each node it depends on via the handle
`b.node(kind)` handed back, and the builder inserts the nodes itself. A handle
only exists for a node already declared, so every edge points backwards and a
cycle cannot be written down — there is no submit-time validation pass, because
there is no malformed spec to reject. (The old queue had a petgraph `toposort`
here, guarding against the positional indices that used to express edges.)
### Node inventory (primitives)

View file

@ -1,19 +1,7 @@
//! DAG shape builders — every operation as a template over the shared
//! node primitives.
//!
//! Every node carries its own `agent` (there is no DAG-level agent) — the
//! [`node`] helper stamps each node's agent and declares the resources that
//! node's kind needs. This module holds the *pure* shape builders (no I/O).
//! The hive-wide **power ops** (`stop` / `start` / `restart`) are NOT here:
//! their per-agent shape depends on each agent's live running state (an async
//! `lifecycle::is_running` read), so they are assembled dynamically in
//! `submit.rs` out of the shared pure primitives this module exports
//! ([`node`], [`rebuild_nodes`]) — one independent per-agent subgraph each,
//! concurrent on its own lease, ONE DAG for the whole hive-wide op.
//! `stop`/`start` write the durable `wanted` intent via a head `SetWanted(w)`
//! node (holding the agent lease, so intent+reconcile is atomic per-agent);
//! `restart` writes no intent — it bounces the container and lets the tail
//! `Reconcile` converge to the agent's existing `wanted`.
//! node primitives. Pure (no I/O); each node carries its own `agent` (there is
//! no DAG-level agent), stamped by the [`node`] helper along with the
//! resources that node's kind needs.
//!
//! ```text
//! rebuild(a): MetaSync(a) → Prebuild(a) → StopForUpdate(a) → Swap(a) →(ok) PostSwap(a) →(any) Reconcile(a)
@ -24,15 +12,14 @@
//! reparent(moves): Reparent(moves) [no rebuild — topology.json is read live]
//! ```
//!
//! Nodes are **named, not counted**: a template declares a node and holds the
//! handle it gets back, so an edge says which node it waits on instead of
//! computing where that node landed. There is no submit-time cycle validation
//! left to do — `hive_jobq`'s builder inserts in declaration order and rejects
//! a reference to a node declared later, so every edge points backwards and a
//! cycle is unrepresentable rather than merely rejected.
//! Nodes are **named, not counted** — a template holds the handle
//! [`Job::node`] hands back, so an edge says which node it waits on. Why that
//! removes submit-time cycle validation: `docs/coordinator.md`.
//!
//! For the dynamic power-op shapes (`stop` / `start` / `restart`, built from
//! live online/offline state), see `submit.rs`.
//! The hive-wide **power ops** (`stop` / `start` / `restart`) are NOT here:
//! their per-agent shape depends on live running state (an async
//! `lifecycle::is_running` read), so `submit.rs` assembles them out of the
//! primitives this module exports ([`node`], [`rebuild_nodes`]).
use hive_jobq::TerminalState;