Commit graph

2,481 commits

Author SHA1 Message Date
atlas
14c2c6d4a5 feat(#2290): ConditionPathIsDirectory= in container service drop-in
Add a [Unit] section to hyperhive-limits.conf (the drop-in written by
write_resource_limits) with:

  ConditionPathIsDirectory=/run/hyperhive/agents/<name>

When this condition is not met, systemd skips the unit with result
"condition" — NOT a failure, so the start-limit counter is not
incremented. Belt-and-braces on top of the tmpfiles.d fix (subtask 2):
if a dir is somehow absent at start time, the container idles instead of
restart-looping into start-limit-hit.

Also promote AGENT_RUNTIME_ROOT to a module-level const (was duplicated
inside two functions) and remove the duplicates.
2026-07-09 00:52:32 +02:00
atlas
f32fba0238 fix(#2290): use 0777 for per-agent socket dirs in tmpfiles.d
systemd-tmpfiles d entries adjust mode+owner on existing dirs. Using
0755 root root would stomp live agents' socket dirs (owned by agent
uid:gid) on every sync_tmpfiles call, breaking the harness's ability
to bind new sockets until host_config rechowns them.

Fix: 0777 root root — matches the chmod_socket_dir(0o777) fallback
already used by host_config when the agent uid is unavailable. World-
writable dirs let the non-root harness bind sockets regardless of who
owns the dir. host_config's chown_socket_dir tightens ownership when
the agent uid is resolved.

Also add missing # Errors doc to priv_client::sync_agent_tmpfiles.
2026-07-09 00:52:32 +02:00
atlas
9d1f5ebe76 feat(#2290): maintain /etc/tmpfiles.d/hyperhive-agents.conf for boot safety
Root cause of the boot outage: container@h-* units try to start before
hive-c0re reaches ensure_runtime, so bind-mount source dirs are missing.

Fix: hive-c0re (via hive-priv, which runs as root) writes
/etc/tmpfiles.d/hyperhive-agents.conf whenever the agent set changes.
systemd-tmpfiles-setup.service (sysinit.target) reads it at every boot
BEFORE any container units start, pre-creating:

  /run/hyperhive/agents/<name>  — MCP socket dir (bind -> /run/hive)
  /run/hive-agent/<name>        — web socket dir (bind -> /run/hive-agent)

This alone removes the outage class: even if hive-c0re is slow to start,
the bind-mount sources exist and container units can activate.

Added:
- PrivRequest::SyncAgentTmpfiles { agents } in hive-sh4re
- sync_agent_tmpfiles() in hive-priv: generates content, writes atomically,
  calls systemd-tmpfiles --create to apply immediately
- priv_client::sync_agent_tmpfiles() wrapper
- lifecycle::sync_tmpfiles() best-effort helper (list + priv call)
- Call sites: hive-c0re startup, handle_spawn success, destroy success
2026-07-09 00:52:32 +02:00
atlas
9cd408de8b fix(#2290): reset-failed before nixos-container start in hive-priv
systemd will refuse to start a unit that has hit start-limit. nixos-
container start does not clear the counter first. Add a best-effort
  systemctl reset-failed container@h-<name>.service
before each StartContainer so an earlier lockout cannot block a now-
correct start. Ignoring the reset exit code is intentional: the unit
may not exist yet on first-time create, and reset-failed on a clean
unit is a harmless no-op.
2026-07-09 00:52:32 +02:00
atlas
8d2ebcf51f fix(clippy): wrap PermanentBringUpError in backticks in doc comment (main.rs:59) 2026-07-09 00:47:32 +02:00
atlas
7bdc3a827e ci: retrigger nix flake check (wasip2 path missing from lix db) 2026-07-09 00:47:32 +02:00
atlas
793f6ce185 fix(fmt): split method chain in bring_up_secondary_with_retry for treefmt 2026-07-09 00:47:32 +02:00
atlas
3de576141b refactor: extract bring_up_secondary_with_retry (fix clippy too_many_lines + needless_continue) 2026-07-09 00:47:32 +02:00
atlas
317e545d7c fix: wrap M_UNKNOWN_TOKEN in backticks in doc comment (clippy::doc_markdown) 2026-07-09 00:47:32 +02:00
atlas
a1cd50610a fix(#2095): retry secondary matrix account bring-up on transient failure
On a transient error (network blip, DNS not ready, homeserver 5xx) a
secondary account's bring-up was immediately skipped for the entire
daemon lifetime. This bit janet's catgirl account repeatedly when the
host DNS resolver wasn't ready at daemon start — the account would
silently disappear until the next restart.

Add a PermanentBringUpError sentinel in client.rs so callers can
distinguish M_UNKNOWN_TOKEN (stale/expired token — permanent, don't
retry) from transient network/homeserver errors.

In main.rs, replace the immediate skip with a bounded retry loop for
secondary accounts: up to 4 attempts with 2s/5s/15s/30s backoffs
(~52s total wait). On a transient error the daemon now stays alive
serving the primary and any other healthy accounts while the failing
secondary gets another chance. Permanent failures (PermanentBringUpError)
still skip immediately with no retry.

The primary account keep its existing behaviour: fatal on non-permanent
error so systemd restarts the whole daemon (systemd is the right retry
mechanism for primary bring-up failure).
2026-07-09 00:47:32 +02:00
atlas
6f3e400903 refactor(#1868): drop tokenised_repo_url — call forge_git_url directly 2026-07-09 00:45:13 +02:00
atlas
031edbd41f fix(#1868): use HIVE_FORGE_URL for internal forge calls
Replace the hardcoded FORGE_HTTP const with forge_http_base() which
reads HIVE_FORGE_URL from the environment (already set unconditionally
by hive-c0re.nix to http://<forge.domain>). Add forge_git_url() helper
that inserts core:<token> credentials between scheme and authority for
git push/clone URLs.

All call sites updated:
- forge/mod.rs: api() OnceLock + new forge_git_url/forge_http_base fns
- forge/repos.rs: push_meta, push_config, ensure_meta_remote
- forge/pr_merge.rs: tokenised_repo_url delegate + test loosened
- workers/knowledge.rs: clone + push URLs
- socket_server/mod.rs: clone_url in RepoCreated response

No new env var: HIVE_FORGE_URL was already the right knob (mara).

Closes #1868. Closes #2174 (this supersedes the operators-team fix from
the closed #2218, which is re-applied in the ensure_operators_team call
that was already merged separately).
2026-07-09 00:45:13 +02:00
damocles
05c91245c7 refactor(#2286): make transient set/clear private — RAII guard is the only door 2026-07-09 00:44:47 +02:00
atlas
9c3884e031 docs(ci): lint jobs are required and block merge 2026-07-08 23:43:29 +02:00
atlas
260dc7bb58 docs(ci): drop bullet descriptions, keep only link + one-liner
Per mara/argus feedback: no need to describe job contents inline,
just link to the workflow file.
2026-07-08 23:43:29 +02:00
atlas
7ef90996f6 docs(ci): replace YAML copy with link to .forgejo/workflows/ci.yml
Per mara's feedback: don't copy the YAML inline, just reference the file.
2026-07-08 23:43:29 +02:00
atlas
bfba148f76 docs(ci): update CI workflow section to reflect 3-job layout 2026-07-08 23:43:29 +02:00
atlas
39af2bad5d style: nix fmt hive-xdg-icons.nix (treefmt) 2026-07-08 23:37:09 +02:00
atlas
ba5a0e1a66 fix: add hyperhiveXdgIcons stub to nix/docs eval (fixes packages.docs check) 2026-07-08 23:37:09 +02:00
atlas
64eddfd0b6 feat(#2228): add XDG icon set and .desktop entries for hyperhive processes
Adds hive-xdg-icons package (nix/packages/hive-xdg-icons.nix) that
rasterizes the branding SVG to all standard hicolor sizes (16–256px)
and installs /usr/share/pixmaps/hyperhive.png as a flat fallback.
Ships .desktop entries for hive-c0re and hive-ag3nt with NoDisplay=true
so desktop environments can match running processes to their icon without
cluttering the application launcher.

Narrow drv input: only ./branding/hyperhive.svg, so unrelated source
changes don't bust the cache.

Wired into environment.systemPackages in hive-c0re.nix (host side)
so the icons are present wherever hive-c0re is deployed.

Closes #2228
2026-07-08 23:37:09 +02:00
atlas
fa944d1213 fix(#2284): replace nixos-container kill with machinectl kill SIGKILL
nixos-container has no kill verb. The KillContainer priv request was
calling nixos-container kill which always fails. Replace with:

  machinectl kill <name> --signal=SIGKILL

which sends SIGKILL to all processes in the container — the correct
semantics for a forced shutdown (called after graceful stop has been
attempted). Add a machinectl_run helper alongside container_run so
callers stay consistent.
2026-07-08 22:47:36 +02:00
müde
c7c156e57b fix(hive-c0re): converge /run bind sources + limits drop-in before reconcile-start 2026-07-08 21:48:37 +02:00
damocles
5027068e31 feat(#2109): harness-side idle watchdog to bail on anthropic api stall storms 2026-07-07 22:45:18 +02:00
damocles
244669f644 fix(hive-claude): exempt crate-doc block from comment-block lint 2026-07-07 18:16:50 +02:00
müde
261f02439b fix(forge): review fixes for the forgejo-api port 2026-07-07 14:42:43 +02:00
müde
5cfb33eeed docs(forge): note forgejo-api client + remaining raw-HTTP surfaces 2026-07-07 09:25:51 +02:00
müde
72415497aa style: treefmt reflow of time dep 2026-07-07 09:25:03 +02:00
müde
4636987469 refactor(hive-forge): port CLI verbs to forgejo-api 2026-07-07 09:24:53 +02:00
müde
b8a3927c43 refactor(hive-c0re): port forge module + knowledge hooks to forgejo-api 2026-07-07 09:11:15 +02:00
müde
4468e86e2d refactor(hive-ag3nt): port forge_notify to forgejo-api 2026-07-07 09:10:24 +02:00
müde
0f035ce1e9 build: add time + url deps for forgejo-api port 2026-07-07 08:50:35 +02:00
müde
39fe0f306a build: add forgejo-api workspace dep (sync feature for hive-forge) 2026-07-07 08:48:07 +02:00
müde
5b062dca55 refactor(hive-ag3nt): split hive bin into hive-agent / hive-agent-mcp / hive-agent-wake 2026-07-06 23:48:05 +02:00
müde
2486251b32 fix: close second review round on the queue-routed CLI
- subvol upgrade waits for the queued stop DAG before migrating (was
  snapshotting + swapping state under a live bind mount) and for the
  restart job after
- history trim gets a 5-min grace for fresh terminals so broad
  stop/start waits can't miss a failed DAG evicted by the per-template
  cap (cap still applies past the grace)
- restart-all returns its DAG ids so hivectl actually waits
- hard stops await their agent DAGs (bounded) before infra goes down,
  restoring the agents-before-infra invariant
- hivectl wait uses node-level terminality so the after-any recovery
  reconcile is watched to completion; infra render errors no longer
  skip watching already-queued agent DAGs
- fold hive-bash-mcp's last local now_unix into wire_time
2026-07-06 22:57:28 +02:00
müde
0e4b5a1120 refactor(hive-c0re): group src-root files into submodules
stores/ (sqlite-backed host stores + db helper), stats/, agent_config/,
workers/ — pure git-mv moves; crate-root re-exports keep every
crate::<module> path compiling. flake_check stays at root (synchronous
approval-flow validation, not a background worker)
2026-07-06 22:38:47 +02:00
müde
b489454dc2 feat(hivectl): queue-routed lifecycle verbs with wait + DAG progress
every agent lifecycle verb on the admin socket (rebuild / restart /
restart-all / kill / stop / start) now submits job-queue DAGs and
returns their ids; hivectl polls the new HostRequest::QueueDag and
prints a live node-chain progress line per DAG (fan-out children
included), exiting non-zero on failure — --no-wait opts out. DagView
and the queue wire enums move to hive_sh4re::jobs (wire types live in
the shared crate); the last fused rebuild path (lifecycle::rebuild)
is gone. tracker: #2166
2026-07-06 22:30:49 +02:00
müde
dc6a37b29a style: import ordering + blank lines after now_unix sweep (treefmt) 2026-07-06 22:08:40 +02:00
müde
a17015f01e refactor(hive-c0re): split forge into submodules
mod.rs keeps the shared admin/http helpers + ensure_all/sync_agent;
user/token provisioning, repo/org/mirror ops, and the trust-boundary
PR-merge primitives move to users.rs / repos.rs / pr_merge.rs
2026-07-06 22:08:22 +02:00
müde
8cdebb1752 fix(hive-ag3nt): drop attribute orphaned by now_unix removal 2026-07-06 22:07:39 +02:00
müde
b0736e6f3e refactor(hive-ag3nt): split mcp into submodules
mod.rs keeps the #[tool_router] impl + server wiring untouched;
rendering/format helpers move to mcp/render.rs, the 24 tool arg
structs to mcp/args.rs
2026-07-06 22:00:30 +02:00
müde
c84028ddcf refactor: single now_unix in hive_sh4re::wire_time
replaces 15 per-module copies (now_unix/now_secs) across hive-c0re and
hive-ag3nt; wire_time already owns the epoch-seconds convention
2026-07-06 21:58:32 +02:00
müde
d190420946 refactor(hive-c0re): shared additive-migration helper in db
db::apply_migrations runs ALTER lists and ignores duplicate-column
errors (turn_stats' pattern); approvals, operator_questions, broker
reminders, and scheduled_prompts drop their hand-rolled
pragma_table_info guards. broker's acked_at migration stays bespoke —
its backfill must only run when the column was just created
2026-07-06 21:53:48 +02:00
müde
34b21b8038 refactor: drop kind_to_str wrapper, call ApprovalKind::as_str directly 2026-07-06 21:49:46 +02:00
müde
f74c1984d7 refactor: ApprovalKind::as_str owns the kind→string mapping
replaces three hand-rolled six-arm matches (actions.rs ×2,
state_snapshot.rs); approvals::kind_to_str delegates. a new kind can
no longer silently miss one of them
2026-07-06 21:48:55 +02:00
müde
084e12503c fix(hive-c0re): close review findings on the job-DAG queue
- deploy-window gate (meta::exclusive) + path-limited meta commits:
  a perm/lock/topology commit can no longer sweep an ApprovalDeploy's
  staged flake.lock and neuter abort_deploy (regression test included)
- cancel surfaces now buffer terminal roll-ups the scheduler drains,
  so a queued approval DAG cancelled by the operator resolves its
  approval instead of dangling, and cancelled power ops revert their
  wanted flip to the observed state
- hivectl restart / restart-all ride the queue (lease serialization,
  transient guard) and restart sets wanted=Up like the old kill+start
- exactly one Rebuilt event per rebuild DAG, emitted at terminal
- StopForUpdate pre-seeds a missing agent_power row from the pre-stop
  observation so a rebuild can't strand an unknown agent offline
- history trim keeps terminal fan-out parents with live children
- audit_log back on db::open; swarm.js badge for reconcile DAGs
2026-07-06 21:44:43 +02:00
müde
58e86a3adf refactor(hive-c0re): shrink dashboard mod root
convert to dashboard/mod.rs; state snapshot, meta inputs, tombstones,
and misc api handlers move to their own files
2026-07-06 21:05:52 +02:00
müde
3ee87d394c refactor(hive-c0re): split lifecycle into submodules
mod.rs keeps the container verbs + priv_run plumbing; git helpers,
repo/dir setup, and host drop-in config move to their own files
2026-07-06 21:05:52 +02:00
müde
9e7af3b6bf refactor(hive-c0re): split socket_server into submodules
mod.rs keeps dispatch + messaging/guards; schedules, reminders,
config approvals, and lifecycle handlers move to their own files
2026-07-06 21:05:52 +02:00
müde
380c6ad47f refactor(hive-c0re): shared sqlite open helper with busy timeout
one db::open owns the parent-dir + connection + busy_timeout dance for
every host-side store (broker/approvals/questions/schedules/power in
broker.sqlite, build_logs, audit_log); schema + migrations stay per
store. same-file connections now wait out concurrent writers instead
of risking SQLITE_BUSY.
2026-07-06 20:46:57 +02:00
müde
604e1c2557 docs: job-DAG queue model; fold agent_power table into broker.sqlite
coordinator.md rewrites the queue section (node inventory, DAG shapes,
resources, desired-state reconciliation, boot reconcile); approvals.md
+ persistence.md + hivectl --graceful help updated to match. agent_power
lives in broker.sqlite like approvals/questions (own connection + busy
timeout) instead of a separate db file.
2026-07-06 20:36:57 +02:00