{ description = "Agent-ergonomic CLI for Gitea issues and pull requests"; # Tracks unstable to match the maintainer's system. Consumers deduplicate by # pointing this input at their own nixpkgs, so it governs standalone builds # only — never the deployed artifact. inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; # Present only so `nix flake check` can evaluate the home-manager module # against real home-manager (the `home-manager-module` check). Its nixpkgs # follows this flake's, so the module is checked against the same # nixpkgs-and-home-manager pairing a consumer following this flake would get. # It has no bearing on the package or the module a consumer imports — the # module is a bare function that takes the importing configuration's own # home-manager and pkgs. inputs.home-manager.url = "github:nix-community/home-manager"; inputs.home-manager.inputs.nixpkgs.follows = "nixpkgs"; outputs = { self, nixpkgs, home-manager }: let # x86_64-darwin is deliberately absent: nixpkgs 26.11 dropped it, and # `legacyPackages.x86_64-darwin` now throws rather than merely failing to # build — so listing it would break `nix flake show` and `nix flake check` # for every system, not just that one. Intel macOS needs the 26.05 branch. systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ]; # Hands each output both the package set and the system name — the latter # because the shell and the checks reach back into `self.packages` for the # system being evaluated, and `pkgs.system` is discouraged in favour of a # considerably wordier spelling. forAllSystems = f: nixpkgs.lib.genAttrs systems ( system: f { inherit system; pkgs = nixpkgs.legacyPackages.${system}; } ); in { packages = forAllSystems ( { pkgs, ... }: rec { gitea-axi = pkgs.callPackage ./package.nix { }; gitea-axi-skill = pkgs.runCommandLocal "gitea-axi-skill" { passthru.skillName = "gitea-axi"; } '' mkdir -p "$out" cp -R ${gitea-axi.skill}/. "$out/" test -f "$out/SKILL.md" ''; default = gitea-axi; } ); # Declarative ambient context for an operator whose agent configuration is # generated rather than owned (ADR 0020). Not per-system: it is a module # function, and the package it defaults to comes from the importing # configuration's own `pkgs` rather than from this flake's nixpkgs — which # is how a consumer deduplicates, and the same reason the derivation is a # callable expression rather than a flake-bound one. homeModules = rec { gitea-axi = ./home-manager-module.nix; default = gitea-axi; }; # The toolchain the repository actually needs: the build and the fast tier # want Node, the live end-to-end tier and the benchmark harness additionally # shell out to `git`, `tea`, and `curl` — none of which the repository # specifies anywhere else. # # Not `gitea-axi` itself, which the benchmark's own arm resolves by name off # PATH: that has to be the locally built `dist/main.js`, so that a bench run # measures the working tree rather than whatever the flake last packaged. # Supplying it here would silently substitute the wrong binary. devShells = forAllSystems ( { pkgs, system }: { default = pkgs.mkShell { packages = [ # The package's own Node, taken from its passthru rather than named # a second time here. There is one reference, so development and # the shipped artifact cannot drift onto different majors — and # they cannot be set independently even by mistake. self.packages.${system}.gitea-axi.nodejs pkgs.git pkgs.tea # The benchmark's raw-api arm shells out to curl. pkgs.curl ]; }; } ); # Two checks. `gitea-axi` is an alias for the package, so `nix flake check` # builds it and thereby runs both its verification phases — the fast tier # in `checkPhase`, the installed-binary tier in `installCheckPhase`. # # `home-manager-module` evaluates the home-manager module through real # home-manager and builds the home files derivation it produces under # several operator configurations, proving the module's composition (ADR # 0021). It reuses the package check's store path rather than rebuilding. # # No granular per-stage checks for the package: the one stage that would # add coverage the package build does not already have is the full # typecheck, which spans `test/` and `bench/` and would therefore drag the # benchmark harness into the derivation's inputs — undoing the source # filtering that keeps benchmark churn from forcing a rebuild. That # typecheck stays in continuous integration, where it already runs. checks = forAllSystems ( { pkgs, system }: { inherit (self.packages.${system}) gitea-axi; home-manager-module = import ./checks/home-manager-module.nix { inherit pkgs home-manager; module = self.homeModules.gitea-axi; package = self.packages.${system}.gitea-axi; }; } ); }; }