Watch
0
0
Fork
You've already forked hyperhive
0

agents: work/ in the disk-metric docs, holder never sees work/, chown guard comment

This commit is contained in:
atlas 2026-10-05 13:23:39 +02:00
commit d2ea50031e
8 changed files with 42 additions and 16 deletions

View file

@ -148,7 +148,7 @@ fn config_bind_source(name: &str) -> PathBuf {
/// The only caller left is the `ManageRootAgent` grant; the parent/child
/// tree that handed every agent its own children here is gone.
///
/// **Three dirs, three different answers** — the uniformity of the
/// **Four dirs, three different answers** — the uniformity of the
/// original loop is what hid that:
///
/// - `state` is **read-write**: the holder reads and writes another
@ -164,6 +164,9 @@ fn config_bind_source(name: &str) -> PathBuf {
/// which the holder has a stated reason to read, let alone write.
/// hive-c0re still reads it directly on the host (`stats::hive_stats`),
/// which needs no bind mount into anyone else's container.
/// - `work` is **absent entirely**, like `harness`. It is the agent's own
/// worktrees and build trees, often very large, and nothing gives the
/// holder a reason to see it.
///
/// ⚠️ The config-repo seeding hive-c0re does at spawn is **not** affected by
/// the `config` flag and must not be read as a reason to widen it: that runs
@ -567,6 +570,24 @@ mod tests {
assert!(work_dir.is_dir());
}
/// `work` holds the agent's worktrees and build trees; like `harness` it
/// is never bound into another agent's container.
#[test]
fn a_holder_never_sees_another_agents_work_dir() {
for bind in child_binds() {
assert!(
!bind.container_path.contains("work"),
"another agent's work dir must not be bound in: {}",
bind.container_path
);
assert!(
!bind.host_path.ends_with("/work"),
"another agent's work dir must not be bound in: {}",
bind.host_path
);
}
}
/// An unparseable name yields no mounts at all — the guard must fail
/// closed, since the alternative is a path built from unvalidated
/// input.

View file

@ -399,7 +399,7 @@ async fn cmd_serve(
// (turn-stats.sqlite has no vacuum — it's one tiny row per turn,
// ~hundreds of KB, and the /stats + hive-stats views read it
// directly; pruning it would just lose trend history for no gain.)
// Slow per-container disk sampler: a `du` of each agent's state dir
// Slow per-container disk sampler: a `du` of each agent's state/ + work/
// + writable rootfs every ~5 min, cached so the 5s container-load
// poll stays cheap cgroup-only reads. Feeds `disk_bytes` on the LOAD
// tab. See container_stats::disk_sampler_loop.

View file

@ -57,7 +57,7 @@ pub struct ContainerResource {
/// Memory ceiling (`memory.max`), bytes. `None` when unlimited
/// (the file reads `max`).
pub mem_max_bytes: Option<u64>,
/// Last-sampled total disk usage — the agent's state dir plus the
/// Last-sampled total disk usage — the agent's `state/` and `work/` dirs plus the
/// container's writable rootfs, excluding the shared read-only nix
/// store — in bytes. `None` until the slow background sampler
/// ([`disk_sampler_loop`]) has populated the cache at least once.