topology: drop the parent field and the hierarchy it fed
`topology.json` was a map of `name -> parent | null`, and that value fed the whole agent hierarchy: `<parent>` / `<children>` recipient sentinels, the reparenting API (CLI verb, wire verb, dashboard endpoints, DAG node), the dashboard tree, the rebuild depth sort, and an unconditional bind-mount grant giving every agent RW on its direct children's state. Per the operator's ruling the field goes, and with it all of the above. The file survives as what remains once the value is gone: the roster of agent names, which is the set `ManageRootAgent` grants mounts over. It is now a JSON array; `read` still accepts the old map shape and keeps its keys, so a hive that upgrades across this does not blank its roster (and so no capability holder loses its mounts for the length of that window). Two sites kept their behaviour under a different recipient rather than losing it. Both addressed `<parent>`, which the broker already resolved to `operator` for a root agent, and every agent is now what that fallback called a root: - the harness's turn-failure / plugin-failure notification (`Surface::send_to_parent` -> `send_to_operator`), and - the send allow-list's always-permitted escape hatch, so an agent with a restrictive allow-list still has a way to say it is stuck. What is NOT preserved, deliberately: an agent with no capability no longer sees any other agent's dirs. `ManageRootAgent`'s own grant is unchanged -- still every agent in the roster, still state RW + config RO, still no `harness`. The dashboard's reparenting control (the M0V3 picker) is deleted with its CSS. The tree rendering that reads `ContainerView.parent` is left for the frontend owner -- it degrades to a flat list with the field gone.
This commit is contained in:
parent
392f16cbc0
commit
d94bc2188d
28 changed files with 236 additions and 1513 deletions
|
|
@ -870,81 +870,6 @@ impl Coordinator {
|
|||
}
|
||||
}
|
||||
|
||||
/// Apply topology reparent(s) + fan the resulting notifications out to
|
||||
/// the affected agents. Applies all moves under a single `META_LOCK`
|
||||
/// acquisition (one git commit — a single-move call is just a
|
||||
/// one-element slice) then, for each move that actually changed
|
||||
/// topology, drops a one-line system message into the inbox of:
|
||||
///
|
||||
/// 1. The **old parent** (if any) — `"{child} moved out of your
|
||||
/// subtree to {new_parent_or_root}"`.
|
||||
/// 2. The **new parent** (if any) — `"{child} just moved into
|
||||
/// your subtree (was previously under
|
||||
/// {old_parent_or_root})"`.
|
||||
/// 3. The **moved agent** — `"your parent changed from
|
||||
/// {old_parent_or_root} to {new_parent_or_root}"`.
|
||||
///
|
||||
/// `_or_root` resolves to the literal string `"<root>"` when the
|
||||
/// slot is `None`, keeping the wording consistent with the
|
||||
/// `<parent>` sentinel's "root → operator" routing (see
|
||||
/// `docs/process/conventions.md::Recipient sentinels`). The
|
||||
/// notifications fire as ordinary broker messages with
|
||||
/// `from = hive_sh4re::manager::SYSTEM_SENDER` so the dashboard renders
|
||||
/// them under the existing system-source styling.
|
||||
///
|
||||
/// First validation failure aborts the whole batch with no disk writes.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Propagates any error returned by [`crate::meta::bulk_commit_topology`]
|
||||
/// (validation failure or topology-file write error).
|
||||
pub async fn reparent_bulk_with_notify(
|
||||
self: &Arc<Self>,
|
||||
moves: &[(&str, Option<&str>)],
|
||||
) -> std::result::Result<(), String> {
|
||||
if moves.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
// bulk_commit_topology applies all set_parent calls under one lock
|
||||
// and returns (child, old_parent) for every move that changed.
|
||||
let changed = crate::meta::bulk_commit_topology(moves).await?;
|
||||
|
||||
// Send per-agent notifications for each changed move.
|
||||
for (child, old_parent) in &changed {
|
||||
// Find the new parent from the moves slice.
|
||||
let new_parent = moves
|
||||
.iter()
|
||||
.find(|(c, _)| *c == child)
|
||||
.and_then(|(_, np)| *np);
|
||||
let old_label = old_parent.as_deref().unwrap_or("<root>");
|
||||
let new_label = new_parent.unwrap_or("<root>");
|
||||
if let Some(op) = old_parent.as_deref() {
|
||||
let _ = self.broker.send(&hive_sh4re::inbox::Message {
|
||||
from: hive_sh4re::manager::trusted_sender(hive_sh4re::manager::SYSTEM_SENDER),
|
||||
to: op.to_owned(),
|
||||
body: format!("{child} moved out of your subtree to {new_label}"),
|
||||
in_reply_to: None,
|
||||
});
|
||||
}
|
||||
if let Some(np) = new_parent {
|
||||
let _ = self.broker.send(&hive_sh4re::inbox::Message {
|
||||
from: hive_sh4re::manager::trusted_sender(hive_sh4re::manager::SYSTEM_SENDER),
|
||||
to: np.to_owned(),
|
||||
body: format!(
|
||||
"{child} just moved into your subtree (was previously under {old_label})"
|
||||
),
|
||||
in_reply_to: None,
|
||||
});
|
||||
}
|
||||
let _ = self
|
||||
.broker
|
||||
.send_coalescing_reparent(child, old_label, new_label);
|
||||
}
|
||||
|
||||
self.rescan_containers_and_emit().await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Read-only snapshot of the last cached container view. Used by
|
||||
/// `/api/state` to cold-load page-open clients without re-running
|
||||
/// `nixos-container list` themselves; the
|
||||
|
|
|
|||
Loading…
Reference in a new issue