Per mara's go-ahead on hyperhive#3902 ("getting started is good, but
terminal rendering does not go in there i think"):
Moved 21 top-level docs/*.md files into 7 new topic subdirectories
(existing web-ui/, turn-loop/, swarm/, tools/, crates/ untouched):
getting-started/ setup.md
agent-lifecycle/ agent-hierarchy.md, approvals.md, persistence.md
trust-boundary/ boundary.md, security.md
integrations/ forge.md, matrix.md, github.md, knowledge.md
networking/ gateway.md, network.md, snapshot-store.md
scheduler/ jobq.md, coordinator.md, ci.md, observability.md
process/ conventions.md, gotchas.md, pr-review-gate.md
web-ui/ terminal-rendering.md (moved into the EXISTING dir,
per mara's correction to the original getting-started
guess -- it's UI implementation detail, not onboarding)
The physical layout now matches docs/README.md's own topical headers,
which already amounted to this taxonomy -- see the scoping comment on
the issue for the two findings that motivated this (a genuine
duplication between CLAUDE.md's old "Reading paths" list and
docs/README.md's grouped one, since drifted out of sync with each
other; and the flat layout not matching the grouping we already had).
Fixed every cross-reference this moved across the whole repo (~120
files: docs/ internal links at every depth, Rust doc comments, nix
module option docs, crate READMEs) -- verified two ways: a grep sweep
confirming zero remaining references to any old path, and a script
that resolves every markdown link in docs/**/*.md + CLAUDE.md +
README.md against the filesystem and reports anything that doesn't
exist (zero broken links).
Collapsed CLAUDE.md's "Reading paths" section (the duplicate) down to
a pointer at docs/README.md, now the single index. Rewrote
docs/README.md itself to use the new subdirectory paths and added the
one doc it was missing that CLAUDE.md's old copy had (pr-review-gate.md).
Classified all 22 docs/*.md files first via a haiku subagent (mara's
suggestion) on two axes -- proposed grouping and operator-vs-
implementation focus -- before finalizing the taxonomy; spot-checked
the report and found internal inconsistencies (its classification
table disagreed with its own summary section for a few files), so this
taxonomy is my original proposal + the one correction mara gave
directly, not a blind application of the subagent's table. The
operator-focus data it gathered is still useful for a follow-up
content pass (docs skewing 'mixed' rather than pure operator-facing),
not addressed in this PR -- structure only.
nix fmt clean, both pre-push lints clean.
209 lines
9.7 KiB
Nix
209 lines
9.7 KiB
Nix
# Top-level, cross-cutting hyperhive options: the master enable
|
|
# switch, the hive's identity (domain + display names), and hive-wide
|
|
# feature toggles read by several subsystem modules. Imported by the
|
|
# ./default.nix aggregator.
|
|
{
|
|
lib,
|
|
config,
|
|
options,
|
|
...
|
|
}:
|
|
let
|
|
hiveCfg = config.services.hyperhive;
|
|
in
|
|
{
|
|
# The swarm's display name moved under `swarm` when the swarm-global
|
|
# settings were consolidated; the hive's own name and domain stayed put,
|
|
# because they describe this hive rather than the swarm it joins.
|
|
imports = [
|
|
(lib.mkRenamedOptionModule
|
|
[ "services" "hyperhive" "swarmName" ]
|
|
[ "services" "hyperhive" "swarm" "name" ]
|
|
)
|
|
];
|
|
|
|
# Top-level hyperhive enable flag. When true, automatically enables
|
|
# hive-c0re and the on-by-default hyperhive subsystems.
|
|
options.services.hyperhive.enable = lib.mkEnableOption "hyperhive — the agent swarm coordinator";
|
|
|
|
# Canonical hive DNS domain shared by every subsystem that needs a
|
|
# stable hostname. Typed nullOr (default null) so the option always
|
|
# exists, but it's REQUIRED whenever hyperhive is enabled — an
|
|
# assertion in hive-network.nix fails eval when it's unset, since
|
|
# matrix bakes it in on first boot and the gateway/forge/agent URLs all
|
|
# derive from it (no safe default). Full identity-surface
|
|
# context (HYPERHIVE_HIVE_DOMAIN / HIVE_NAME / SWARM_NAME env-var
|
|
# chain → identity.rs → claude prompt): docs/process/conventions.md::
|
|
# Hive identity (label + domain + display names).
|
|
options.services.hyperhive.domain = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
# Read out of the swarm directory rather than derived here. The
|
|
# directory is what every OTHER hive reads this hive's address from,
|
|
# so deriving it separately gave two homes for one value with
|
|
# nothing asserting they agreed — and a disagreement surfaces as
|
|
# "the other hives can't reach me", on a machine other than the
|
|
# misconfigured one.
|
|
#
|
|
# ⚠️ The `<hiveName>.<swarm.domain>` formula did NOT move here from
|
|
# there and back: it lives once, on `hives.<name>.domain`, which
|
|
# this reads. Restoring a direct fallback here would recreate the
|
|
# second path (and, since that default reads `swarm.domain` too, a
|
|
# value that can differ from the directory's).
|
|
default =
|
|
if hiveCfg.hiveName != null && hiveCfg.swarm.hives ? ${hiveCfg.hiveName} then
|
|
hiveCfg.swarm.hives.${hiveCfg.hiveName}.domain
|
|
else
|
|
null;
|
|
defaultText = lib.literalExpression "services.hyperhive.swarm.hives.\${hiveName}.domain, or null when there is no entry for this hive";
|
|
example = "darkest.space";
|
|
description = ''
|
|
Canonical host domain for hyperhive subsystems that need a
|
|
stable name (currently: `services.hyperhive.swarm.matrix.serverName`
|
|
derives from this, defaulting to
|
|
`matrix.''${services.hyperhive.domain}` when `serverName` is
|
|
null). **Required** when `services.hyperhive.enable` — eval fails
|
|
with a helpful message if it's unset (it's baked into matrix on
|
|
first boot and drives the gateway/forge/agent URLs, with no safe
|
|
default; changing it later is destructive). Exposed to agents as
|
|
`HYPERHIVE_HIVE_DOMAIN`; consumed by
|
|
`hive-agent::identity::hive_domain()` for `<name>@<domain>`
|
|
qualified labels.
|
|
|
|
**Deprecated as a place to write.** It is read from this hive's
|
|
own entry in `services.hyperhive.swarm.hives`, whose `domain`
|
|
defaults to `<hiveName>.<swarm.domain>` — so a conventional hive
|
|
states nothing at all, and a non-conventional one states its
|
|
address in the directory every other hive reads. Setting it here
|
|
still wins and still works, with a warning: the directory is
|
|
shared, this option is not, so a value written only here is
|
|
invisible to the rest of the swarm.
|
|
'';
|
|
};
|
|
|
|
# Deprecation warning for the shorthand above, fired on PRIORITY.
|
|
#
|
|
# ⚠️ Not `isDefined`, and not `files`: the module system injects an
|
|
# option's own `default` as a definition attributed to the declaring
|
|
# file, so both say "defined, in hyperhive.nix" for a config that set
|
|
# nothing — measured, after this warning fired on the conventional
|
|
# case. `mkOptionDefault` is priority 1500, so anything lower is a
|
|
# definition someone actually wrote (100 plain, 1000 mkDefault).
|
|
config.warnings =
|
|
lib.optional (hiveCfg.enable && options.services.hyperhive.domain.highestPrio < 1500)
|
|
''
|
|
services.hyperhive.domain is set explicitly and is deprecated. This
|
|
hive's address belongs in the swarm directory, which every hive in
|
|
the swarm shares a copy of:
|
|
|
|
services.hyperhive.swarm.hives."${toString hiveCfg.hiveName}".domain = "${toString hiveCfg.domain}";
|
|
|
|
(Or drop the value entirely if it is the conventional
|
|
`<hiveName>.<swarm.domain>` — that is the directory entry's own
|
|
default.)
|
|
|
|
Setting it here still wins, so nothing is broken right now. What it
|
|
does not do is tell the other hives: they read this hive's address
|
|
out of their copy of the directory, so a value written only here
|
|
leaves them pointing somewhere else with nothing detecting it.
|
|
'';
|
|
|
|
# Where the swarm lives. Declared beside the hive's own identity
|
|
# because it is what that identity is derived FROM — every hive in a
|
|
# swarm is a sub-domain of it. Unlike the renamed options nearby, this
|
|
# is genuinely new: nothing moved here, so there is no alias.
|
|
options.services.hyperhive.swarm.domain = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
example = "darkest.space";
|
|
description = ''
|
|
DNS domain of the wider swarm this hive belongs to. Each hive
|
|
occupies its own sub-domain of it, which is why every entry in
|
|
`services.hyperhive.swarm.hives` defaults its `domain` to
|
|
`<name>.<swarm.domain>` — set this plus
|
|
`services.hyperhive.hiveName`, list the hives by name, and no
|
|
hive in the swarm states an address at all.
|
|
|
|
**Required** when `services.hyperhive.enable`, and deliberately
|
|
not defaulted: there is no fallback worth having. A guessed
|
|
swarm domain is a wrong hostname that evaluates cleanly and
|
|
deploys, which is worse than an eval failure telling an
|
|
operator to write down the one address their swarm answers to.
|
|
Upgrading past this costs one line, once.
|
|
'';
|
|
};
|
|
|
|
# Human display name for this hive. Distinct from the DNS domain
|
|
# above (machine-readable) — see docs/process/conventions.md::Hive identity
|
|
# for the domain-vs-name-vs-swarm distinction + the env-var
|
|
# propagation chain. The swarm's display name is
|
|
# `services.hyperhive.swarm.name`, one level out: this hive is named
|
|
# here, the swarm it belongs to is named there.
|
|
options.services.hyperhive.hiveName = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
example = "pr1ma";
|
|
description = ''
|
|
Human-readable name of this single-host hive instance.
|
|
**Required** when `services.hyperhive.enable`. Distinct from
|
|
`services.hyperhive.domain` (the machine-addressable DNS name)
|
|
but no longer merely cosmetic: a hive occupies
|
|
`<hiveName>.<swarm.domain>`, so this is the label the hive is
|
|
*addressed* by as well as the one it is called. Exposed to
|
|
agents as `HYPERHIVE_HIVE_NAME`; surfaced in the dashboard
|
|
chrome and per-agent system prompt.
|
|
'';
|
|
};
|
|
|
|
# The one hive-level option that describes something ABOVE the hive,
|
|
# which is why it sits under `swarm` with the swarm-global services
|
|
# rather than beside `hiveName`.
|
|
options.services.hyperhive.swarm.name = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
example = "constellat1on";
|
|
description = ''
|
|
Human-readable name of the wider swarm this hive belongs to.
|
|
Hives at different DNS domains can share a swarm name when
|
|
they federate together. Exposed to agents as
|
|
`HYPERHIVE_SWARM_NAME`; surfaced in the dashboard chrome and
|
|
per-agent system prompt when set.
|
|
'';
|
|
};
|
|
|
|
# `singleHostSwarm` is declared in ./local-defaults.nix, with
|
|
# the values it asserts. It is a deployment mode rather than a setting
|
|
# this module's options read, so it lives with its consequences.
|
|
|
|
# Whether this hive runs "ruthless" — with no root/manager agent at
|
|
# all. Some hives don't want a root agent — see issue tracker
|
|
# "scope concept: special agents".
|
|
options.services.hyperhive.ruthless = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
example = true;
|
|
description = ''
|
|
Run this hive "ruthless" — with no root (manager) agent at all (no
|
|
ruth). When `true`, hive-c0re skips the root-agent auto-management
|
|
sweep entirely (it otherwise creates the root agent's container when
|
|
missing and restarts it when present but stopped). Defaults to
|
|
`false` (the root agent is auto-managed as required
|
|
infrastructure). Exposed to hive-c0re as `HYPERHIVE_RUTHLESS`.
|
|
'';
|
|
};
|
|
|
|
options.services.hyperhive.github.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
example = false;
|
|
description = ''
|
|
Hive-wide switch for the per-agent GitHub integration (the `gh` CLI
|
|
wrapper + git credential helper, per `hyperhive.github.enable`). On by
|
|
default: every agent gets the integration, inert until a PAT is
|
|
provisioned via the dashboard credentials tab or `hivectl github
|
|
set-token`. Set `false` to turn it off for the whole hive --- the
|
|
meta-flake renderer (`hive-c0re/src/meta.rs`) then injects
|
|
`hyperhive.github.enable = false` into every agent. Exposed to hive-c0re
|
|
as `HYPERHIVE_GITHUB_DISABLED` (set only when the integration is off).
|
|
'';
|
|
};
|
|
}
|