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>
72 lines
2.8 KiB
Bash
72 lines
2.8 KiB
Bash
#!/usr/bin/env bash
|
|
# Launch the reforge ORCHESTRATOR session (docs/reforge.md, autonomous
|
|
# mode). The agent drives the whole run: schedules role turns, routes work
|
|
# by issue/PR number, judges convergence, checkpoints — the job the human
|
|
# operator otherwise does. It launches fresh headless role sessions (via
|
|
# reforge-role) and coordinates only through the forge; it never reviews or
|
|
# implements itself, and the review gate stays inviolable (its policy denies
|
|
# curl/push/reset — it can only merge already-approved PRs via MCP).
|
|
#
|
|
# reforge-orchestrator [agent args...]
|
|
#
|
|
# Interactive (watch it work): reforge-orchestrator
|
|
# Then tell it e.g. "Drive Phase A to completion, stopping at the A->B
|
|
# boundary." For unattended operation, add your own -p/--permission-mode
|
|
# args or wrap in a loop — but read the risk notes in docs/reforge.md first
|
|
# (nested sessions, cost, model-nondeterminism per run).
|
|
#
|
|
# Prepares $REFORGE_TEAM_DIR/orchestrator/ fresh each launch:
|
|
# .claude/settings.json <- $REFORGE_SETTINGS_DIR/orchestrator-settings.json
|
|
# .mcp.json forge MCP wired to the ADMIN token
|
|
# CLAUDE.md <- $REFORGE_AGENTS_DIR/orchestrator.md (the playbook)
|
|
set -euo pipefail
|
|
|
|
FORGE_URL=${REFORGE_FORGE_URL:-http://localhost:3030}
|
|
ORG=${REFORGE_ORG:-sandbox-team}
|
|
ADMIN_USER=${REFORGE_ADMIN_USER:-sandbox-admin}
|
|
TOKENS_DIR=${REFORGE_TOKENS_DIR:-/var/lib/forgejo-sandbox/tokens}
|
|
AGENTS_DIR=${REFORGE_AGENTS_DIR:?set REFORGE_AGENTS_DIR to the agent briefs dir}
|
|
SETTINGS_DIR=${REFORGE_SETTINGS_DIR:?set REFORGE_SETTINGS_DIR to the permission-policy dir}
|
|
TEAM_DIR=${REFORGE_TEAM_DIR:-$HOME/sandbox-team}
|
|
AGENT_CMD=${REFORGE_AGENT_CMD:-claude}
|
|
|
|
TOKEN_FILE=${REFORGE_ADMIN_TOKEN_FILE:-$TOKENS_DIR/${ADMIN_USER}.token}
|
|
if [ ! -r "$TOKEN_FILE" ]; then
|
|
echo "reforge-orchestrator: no readable admin token at $TOKEN_FILE — is the sandbox provisioned?" >&2
|
|
exit 1
|
|
fi
|
|
|
|
MCP_BIN=${REFORGE_MCP_BIN:-$(command -v forgejo-mcp || true)}
|
|
if [ -z "$MCP_BIN" ]; then
|
|
echo "reforge-orchestrator: no forgejo-mcp — set REFORGE_MCP_BIN or put forgejo-mcp on PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
WORKDIR="$TEAM_DIR/orchestrator"
|
|
mkdir -p "$WORKDIR/.claude"
|
|
|
|
cp "$SETTINGS_DIR/orchestrator-settings.json" "$WORKDIR/.claude/settings.json"
|
|
sed -e "s|@FORGE_URL@|$FORGE_URL|g" \
|
|
-e "s|@ORG@|$ORG|g" \
|
|
-e "s|@TOKENS_DIR@|$TOKENS_DIR|g" \
|
|
"$AGENTS_DIR/orchestrator.md" >"$WORKDIR/CLAUDE.md"
|
|
|
|
cat >"$WORKDIR/.mcp.json" <<EOF
|
|
{
|
|
"mcpServers": {
|
|
"forgejo-sandbox": {
|
|
"type": "stdio",
|
|
"command": "bash",
|
|
"args": [
|
|
"-c",
|
|
"FORGEJO_ACCESS_TOKEN=\$(cat $TOKEN_FILE) FORGEJO_URL=$FORGE_URL exec $MCP_BIN --transport stdio"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
|
|
echo "→ launching orchestrator session in $WORKDIR"
|
|
echo " (it drives role turns via reforge-role; gate stays enforced)"
|
|
cd "$WORKDIR"
|
|
exec "$AGENT_CMD" "$@"
|