The PO is itself a project using the agent-orchestrator harness (engine/ submodule pinned at v0.1.0). Adds: agents.toml (one persistent fleet-management agent) + prompts/; fleet.toml (the sole project<->harness<->ref registry) + docs/fleet-registry.md; scripts/ (fleet.py + create/start/stop/update-project.sh); docs/manage-projects.md + docs/bootstrap.md; flake.nix/.lock devShell (python311+tmux+git); README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
118 lines
4.2 KiB
Bash
Executable File
118 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# create-project.sh — scaffold a NEW project that uses a harness.
|
|
#
|
|
# Produces a self-contained project repo: the chosen harness vendored as the `engine/` submodule at
|
|
# a pinned ref, plus a harness config scaffolded by the harness's own `init`. The project contains
|
|
# NO project-orchestrator / fleet metadata — knowledge is one-directional (PO → project). Registering
|
|
# the project in the PO's fleet.toml is a SEPARATE, PO-side step (use --register, or edit fleet.toml
|
|
# by hand); nothing about the fleet ever lands inside the project repo.
|
|
#
|
|
# Usage:
|
|
# scripts/create-project.sh <name> [options]
|
|
#
|
|
# Options:
|
|
# --dir <parent> parent directory to create the project under (default: ./projects)
|
|
# --engine-url <url> harness repo to vendor as engine/ (default: the agent-orchestrator repo)
|
|
# --ref <ref> harness ref to pin the submodule at (default: v0.1.0)
|
|
# --prefix <prefix> session_prefix to write into the project's config (default: <name>-)
|
|
# --register also append a [[project]] entry to this PO's fleet.toml (PO-side only)
|
|
# --no-commit leave the project tree uncommitted (default: make an initial commit)
|
|
#
|
|
# Drive it by hand afterwards, exactly like any project:
|
|
# cd <parent>/<name> && python3 engine/agents.py status
|
|
set -euo pipefail
|
|
|
|
die() { echo "create-project: $*" >&2; exit 1; }
|
|
|
|
[ $# -ge 1 ] || die "usage: create-project.sh <name> [--dir P] [--engine-url U] [--ref R] [--prefix X] [--register] [--no-commit]"
|
|
NAME="$1"; shift
|
|
[[ "$NAME" =~ ^[a-z0-9][a-z0-9-]*$ ]] || die "name must be kebab-case (got: $NAME)"
|
|
|
|
PO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
PARENT="$PO_ROOT/projects"
|
|
ENGINE_URL="https://git.autonomic.zone/recipe-maintainers/agent-orchestrator.git"
|
|
REF="v0.1.0"
|
|
PREFIX=""
|
|
REGISTER=0
|
|
COMMIT=1
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--dir) PARENT="$2"; shift 2;;
|
|
--engine-url) ENGINE_URL="$2"; shift 2;;
|
|
--ref) REF="$2"; shift 2;;
|
|
--prefix) PREFIX="$2"; shift 2;;
|
|
--register) REGISTER=1; shift;;
|
|
--no-commit) COMMIT=0; shift;;
|
|
*) die "unknown option: $1";;
|
|
esac
|
|
done
|
|
PREFIX="${PREFIX:-${NAME}-}"
|
|
|
|
command -v git >/dev/null || die "git not on PATH"
|
|
command -v python3 >/dev/null || die "python3 not on PATH"
|
|
|
|
DEST="$PARENT/$NAME"
|
|
[ -e "$DEST" ] && die "$DEST already exists — refusing to overwrite"
|
|
mkdir -p "$PARENT"
|
|
|
|
echo "create-project: scaffolding '$NAME' at $DEST (engine $ENGINE_URL @ $REF)"
|
|
git init -q -b main "$DEST"
|
|
cd "$DEST"
|
|
|
|
# 1) vendor the harness as a pinned submodule under engine/
|
|
git -c protocol.version=2 submodule add -q "$ENGINE_URL" engine
|
|
( cd engine && git fetch -q --tags origin && git checkout -q "$REF" )
|
|
git add .gitmodules engine
|
|
|
|
# 2) scaffold the harness config + prompts via the harness's OWN init (no PO/fleet metadata)
|
|
python3 engine/agents.py init . >/dev/null
|
|
# stamp the chosen session_prefix into the scaffolded config (keeps namespaces unique per project)
|
|
python3 - "$PREFIX" <<'PY'
|
|
import re, sys, pathlib
|
|
prefix = sys.argv[1]
|
|
p = pathlib.Path("agents.toml")
|
|
txt = p.read_text()
|
|
txt = re.sub(r'session_prefix\s*=\s*"[^"]*"', f'session_prefix = "{prefix}"', txt, count=1)
|
|
p.write_text(txt)
|
|
PY
|
|
|
|
# 3) ignore runtime state; the project knows nothing about any PO
|
|
cat > .gitignore <<'EOF'
|
|
# runtime state + logs (never committed)
|
|
.ao-state/
|
|
*.log
|
|
__pycache__/
|
|
*.pyc
|
|
result
|
|
EOF
|
|
|
|
git add agents.toml prompts .gitignore 2>/dev/null || true
|
|
|
|
if [ "$COMMIT" -eq 1 ]; then
|
|
git -c user.name="project-orchestrator" -c user.email="po@localhost" \
|
|
commit -q -m "init: scaffold $NAME (engine @ $REF)"
|
|
fi
|
|
|
|
echo "create-project: done — $DEST"
|
|
echo " engine pinned at: $(cd engine && git rev-parse HEAD) ($REF)"
|
|
echo " config: agents.toml (session_prefix = $PREFIX)"
|
|
echo " verify it: ( cd $DEST && python3 engine/agents.py status )"
|
|
|
|
if [ "$REGISTER" -eq 1 ]; then
|
|
echo "create-project: registering '$NAME' in $PO_ROOT/fleet.toml"
|
|
cat >> "$PO_ROOT/fleet.toml" <<EOF
|
|
|
|
[[project]]
|
|
name = "$NAME"
|
|
location = "$DEST"
|
|
harness = "agent-orchestrator"
|
|
ref = "$REF"
|
|
enabled = false
|
|
secrets = ".env"
|
|
config = "agents.toml"
|
|
notes = "Created by scripts/create-project.sh"
|
|
EOF
|
|
python3 "$PO_ROOT/scripts/fleet.py" --file "$PO_ROOT/fleet.toml" validate
|
|
fi
|