The forgejo-sandbox / reforge harness, lifted out of the machine config into a host-agnostic, generic engine anyone can consume with Nix. Two layers: - engine (this repo) — nixosModules.reforge stands up the sandbox forge, provisions role accounts + tokens, enforces branch protection, and puts the reforge-* CLI + forgejo-mcp on PATH. Carries no project specifics. - run config — per-project manifest/charter/agenda/issues an adopter fills in; scaffold one with the `reforge` flake template. Portability fixes vs the in-config version: - forgejo-mcp resolved from $REFORGE_MCP_BIN or PATH, never a named host (kills the nixosConfigurations.omni hardcode). - all instance data + paths parameterized via REFORGE_* env, baked into the reforge-scripts wrappers from module options (configDir, agentsDir, refsDir, org, port, tokenOwner, ...). - option namespace neutral (reforge.* not omni.packs.*); settings policies carry no absolute /etc/nixos paths. - role briefs + orchestrator playbook genericized: all project specifics point at the charter; refs corpus optional. Validated: nix flake check (eval) + builds of forgejo-mcp, reforge-scripts, and a module-eval check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
126 lines
4.8 KiB
Nix
126 lines
4.8 KiB
Nix
{
|
|
description = "reforge — a local Forgejo sandbox that runs a role-isolated agent team to rebuild a software stack from pinned bases to a declared target, coordinating entirely through the forge (issues, PRs, gated review).";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
};
|
|
|
|
outputs =
|
|
{ self, nixpkgs }:
|
|
let
|
|
systems = [
|
|
"x86_64-linux"
|
|
"aarch64-linux"
|
|
];
|
|
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
|
|
|
|
appNames = [
|
|
"reforge-seed"
|
|
"reforge-reset"
|
|
"reforge-compare"
|
|
"reforge-smoke"
|
|
"reforge-kickoff"
|
|
"reforge-role"
|
|
"reforge-orchestrator"
|
|
"reforge-fetch-targets"
|
|
];
|
|
in
|
|
{
|
|
# The NixOS module. Import it, set `reforge.enable = true` and
|
|
# `reforge.configDir`, rebuild — you get the sandbox forge, the
|
|
# provisioned role accounts + tokens, and the reforge-* CLI on PATH.
|
|
# See docs/architecture.md.
|
|
nixosModules.reforge = import ./modules/reforge.nix;
|
|
nixosModules.default = self.nixosModules.reforge;
|
|
|
|
# Fill-in-the-blank run config: `nix flake init -t <this>#reforge`
|
|
# drops a manifest/charter/agenda/issues scaffold plus a consumer
|
|
# flake.nix that wires this engine in. Edit the four data files and
|
|
# you have your own run.
|
|
templates.reforge = {
|
|
path = ./templates/reforge;
|
|
description = "A reforge run: manifest + charter + agenda stubs and a consumer flake wiring the engine as a NixOS module.";
|
|
};
|
|
templates.default = self.templates.reforge;
|
|
|
|
packages = forAllSystems (pkgs: {
|
|
forgejo-mcp = pkgs.callPackage ./packages/forgejo-mcp.nix { };
|
|
|
|
# Standalone build of the CLI, with sandbox defaults and the
|
|
# bundled template as the config dir — enough for `nix run` to work
|
|
# against a manually-run forge. On NixOS the module builds its own
|
|
# copy with your host's real defaults baked in.
|
|
reforge-scripts = pkgs.callPackage ./packages/reforge-scripts.nix {
|
|
forgejoMcp = pkgs.callPackage ./packages/forgejo-mcp.nix { };
|
|
forgeUrl = "http://localhost:3030";
|
|
org = "sandbox-team";
|
|
adminUser = "sandbox-admin";
|
|
tokensDir = "/var/lib/forgejo-sandbox/tokens";
|
|
stateDir = "/var/lib/forgejo-sandbox";
|
|
configDir = ./templates/reforge;
|
|
};
|
|
|
|
default = self.packages.${pkgs.system}.reforge-scripts;
|
|
});
|
|
|
|
# `nix run <this>#reforge-seed`, etc.
|
|
apps = forAllSystems (
|
|
pkgs:
|
|
nixpkgs.lib.genAttrs appNames (name: {
|
|
type = "app";
|
|
program = "${self.packages.${pkgs.system}.reforge-scripts}/bin/${name}";
|
|
})
|
|
);
|
|
|
|
checks = forAllSystems (
|
|
pkgs:
|
|
{
|
|
# Package derivations build (validates the wrapper + that agents/
|
|
# and settings/ are present and shipped).
|
|
forgejo-mcp = self.packages.${pkgs.system}.forgejo-mcp;
|
|
reforge-scripts = self.packages.${pkgs.system}.reforge-scripts;
|
|
}
|
|
// nixpkgs.lib.optionalAttrs (pkgs.stdenv.hostPlatform.isLinux) {
|
|
# Lightweight module-eval check: evaluate a NixOS system that
|
|
# imports the module with enable=true, then build only (a) the
|
|
# provisioning script the systemd unit runs and (b) the
|
|
# reforge-scripts CLI as the module wires it (with cfg.configDir
|
|
# etc. baked in). This forces the module's options, assertions,
|
|
# and both derivations to evaluate without building a full system
|
|
# toplevel.
|
|
module-eval =
|
|
let
|
|
sys = nixpkgs.lib.nixosSystem {
|
|
system = pkgs.system;
|
|
modules = [
|
|
self.nixosModules.reforge
|
|
{
|
|
boot.loader.grub.enable = false;
|
|
fileSystems."/" = {
|
|
device = "nodev";
|
|
fsType = "ext4";
|
|
};
|
|
system.stateVersion = "24.11";
|
|
reforge.enable = true;
|
|
reforge.configDir = ./templates/reforge;
|
|
}
|
|
];
|
|
};
|
|
execStart = sys.config.systemd.services.reforge-provision.serviceConfig.ExecStart;
|
|
cliFromModule = builtins.filter (
|
|
p: (p.pname or "") == "reforge-scripts"
|
|
) sys.config.environment.systemPackages;
|
|
in
|
|
pkgs.runCommand "reforge-module-eval" { } (
|
|
''
|
|
mkdir -p "$out"
|
|
ln -sn ${execStart} "$out/provision-script"
|
|
''
|
|
+ nixpkgs.lib.concatMapStrings (p: ''ln -sn ${p} "$out/cli"'' + "\n") cliFromModule
|
|
);
|
|
}
|
|
);
|
|
|
|
formatter = forAllSystems (pkgs: pkgs.nixfmt-rfc-style);
|
|
};
|
|
}
|