Files
gitea-axi/.claude/tasks/0047-flake-check-hm-module-composition.md
alexion 534097121d
All checks were successful
CI / test (22) (pull_request) Successful in 52s
CI / test (true, 24) (pull_request) Successful in 1m4s
CI / flake (pull_request) Successful in 3s
CI / test (22) (push) Successful in 48s
CI / test (true, 24) (push) Successful in 1m2s
CI / flake (push) Successful in 3s
feat(nix): install the CLI unconditionally, gate context per harness (task 0046)
Reshape the home-manager module so `programs.gitea-axi.enable` installs the
binary always, and the Claude Code context follows the harness. The two
per-artefact toggles and their assertion are replaced by one per-harness
toggle, `enableClaudeCodeIntegration` (default true); its artefacts land only
when `programs.claude-code.enable` is also on, silently absent otherwise.

The Agent Skill is now written through home.file into Claude Code's skills
directory, rather than contributed to `programs.claude-code.skills`, so it
composes with both the attribute-set and whole-directory forms of an operator's
own skills option. The Skill write is gated on `claude-code.enable` explicitly
(keeping package realisation lazy); the hook keeps its sibling-module gate for
free, and the asymmetry is commented. Supersedes three decisions of ADR 0020;
recorded in ADR 0021.

INSTALL.md is updated to the new option surface and the path-form limitation
paragraph removed. Adds the parent spec and the follow-up task 0047 (the flake
check proving composition, implemented separately).
2026-07-20 19:50:44 -04:00

3.0 KiB

spec, blocked-by
spec blocked-by
hm-module-harness-integration 0046-reshape-hm-module-per-harness-toggle

What to build

Add the first automated proof of the module's composition, so that a change in home-manager or the Claude Code module that breaks the way the Skill is declared fails nix flake check rather than a maintainer rebuild weeks later.

A home-manager input is added to the flake, with its own nixpkgs following the flake's nixpkgs, so the module is checked against the same nixpkgs-and-home-manager pairing a consumer following this flake would get.

A flake check evaluates the actual module through home-manager's standalone configuration entry point and builds the resulting home files derivation under several configurations, asserting on the tree it produces. Building the home files derivation is sufficient — it is the file-linkage layer that actually decides whether two declarations collide — and needs neither the Claude Code binary nor a running agent. The check asserts on which files a generation contains, never on module internals (option values, store paths, the shape of the file mechanism).

The configurations exercised:

  • An operator declaring their own skills as an attribute set: the module's Skill lands alongside the operator's, each at its own name.
  • An operator declaring their own skills as a whole directory (path form): the module's Skill lands alongside the operator's directory contents. This is the case that guards the recursive-install coupling; a regression to a non-recursive path-form install fails here as a build-time file collision.
  • Claude Code disabled: no gitea-axi Skill entry is written. This guards the explicit sibling-enable gate introduced in the reshape.
  • The hook merges into an operator's own SessionStart hook list rather than replacing it.

This adds a module check alongside the existing package check in the flake's checks output rather than introducing a new kind of verification surface.

Acceptance criteria

  • The flake has a home-manager input whose nixpkgs follows the flake's nixpkgs; flake.lock is updated.
  • A new check under the flake's checks output evaluates the real module through home-manager's standalone configuration entry point and builds the home files derivation — no Claude Code binary or running agent required.
  • The attribute-set-skills configuration asserts the module's Skill and the operator's skill both land, each at its own name.
  • The whole-directory-skills (path form) configuration asserts the module's Skill lands alongside the operator's directory contents; a non-recursive path-form install would fail this as a build-time collision.
  • The Claude-Code-disabled configuration asserts no gitea-axi Skill entry is written.
  • A configuration with an operator's own SessionStart hook asserts the module's hook merges into that list rather than replacing it.
  • The check asserts on the generation's file tree only, not on option values or store paths.
  • nix flake check runs the new check across the flake's systems and passes.