The single module-eval derivation forced ~62 full nixosSystem fixtures live at once to compute its cases list: 10.6GB peak RSS / 5m25s to evaluate, by far the dominant cost in nix flake check. Splits it into 21 independent checks.module-eval-* derivations (1-7 fixtures each) sharing builders/helpers via module-eval/lib.nix, so no single derivation needs more than a handful of fixtures live at once. A few cases spanning two clusters carry a small duplicated fixture rather than threading shared state through lib.nix.
89 lines
3.2 KiB
Nix
89 lines
3.2 KiB
Nix
# `checks.module-eval-agent-plugins` — see ./lib.nix for the shared
|
|
# rationale (why this suite exists, naming convention, "evaluates
|
|
# not executes").
|
|
{
|
|
pkgs,
|
|
lib,
|
|
self,
|
|
nixosSystem,
|
|
}:
|
|
let
|
|
inherit
|
|
(import ./lib.nix {
|
|
inherit
|
|
pkgs
|
|
lib
|
|
self
|
|
nixosSystem
|
|
;
|
|
})
|
|
agent
|
|
runGroup
|
|
;
|
|
|
|
# `claudePlugins`'s additive-merge shape: a plain per-agent
|
|
# definition must ADD to the module's own base-set definition rather than
|
|
# replacing it, while `lib.mkForce` must still replace the whole list
|
|
# outright — the two arms below plus the unset default (read directly off
|
|
# `bare`-shaped `agent { }`, no fixture of its own needed) are the three
|
|
# cases that shape has to hold.
|
|
agentPluginsDefault = agent { };
|
|
|
|
agentPluginsAdded = agent { claudePlugins = [ "foo@bar" ]; };
|
|
|
|
agentPluginsForced = agent { claudePlugins = lib.mkForce [ "foo@bar" ]; };
|
|
|
|
# The de-dup arm: an agent that names a base-set entry explicitly must not
|
|
# get it installed twice.
|
|
agentPluginsDuplicate = agent { claudePlugins = [ "base@hyperhive" ]; };
|
|
|
|
agentPlugins = machine: machine.services.hyperhive.agent.claudePlugins;
|
|
cases = [
|
|
{
|
|
# Case 1 of the additive-merge shape: an agent that declares
|
|
# nothing gets exactly the module's base set, no more and no less.
|
|
name = "an agent with no claudePlugins definition gets exactly the base set";
|
|
ok =
|
|
agentPlugins agentPluginsDefault == [
|
|
"skill-creator@claude-plugins-official"
|
|
"base@hyperhive"
|
|
];
|
|
}
|
|
{
|
|
# Case 2: a plain per-agent definition ADDS to the base set (list-typed
|
|
# options at equal priority concatenate) rather than replacing it —
|
|
# the property the operator ruling asked for instead of `mkDefault`.
|
|
# Sorted before comparing: concatenation order between two same-
|
|
# priority definitions is a module-system implementation detail this
|
|
# case isn't about — membership and count are.
|
|
name = "an agent's own claudePlugins definition adds to the base set";
|
|
ok =
|
|
builtins.sort builtins.lessThan (agentPlugins agentPluginsAdded) == [
|
|
"base@hyperhive"
|
|
"foo@bar"
|
|
"skill-creator@claude-plugins-official"
|
|
];
|
|
}
|
|
{
|
|
# Case 3: `lib.mkForce` is still the escape hatch — an operator who
|
|
# wants the base set gone, not extended, can still say so outright.
|
|
name = "an agent's mkForce claudePlugins replaces the base set outright";
|
|
ok = agentPlugins agentPluginsForced == [ "foo@bar" ];
|
|
}
|
|
{
|
|
# De-dup arm: an agent that names a base-set entry itself must not get
|
|
# it installed twice — `lib.unique` at the JSON-render site, not the
|
|
# option's merge (the merge is a plain concatenation on purpose, so
|
|
# the un-deduped list stays readable for `agentPlugins` above).
|
|
name = "an agent repeating a base-set plugin does not get it installed twice";
|
|
ok =
|
|
builtins.sort builtins.lessThan (
|
|
builtins.fromJSON agentPluginsDuplicate.environment.etc."hyperhive/claude-plugins.json".text
|
|
) == [
|
|
"base@hyperhive"
|
|
"skill-creator@claude-plugins-official"
|
|
];
|
|
}
|
|
];
|
|
in
|
|
runGroup "agent-plugins" cases
|