Files
orquestra/scripts/install.sh
rikrdo 70ff54cfa3 refactor: reinforce harness to prevent contract violations
- verify.sh: validate prohibited dirs, gate nomenclature, feature schema, runtime consistency
- orquestra-status: block direct writes to backlog/features.json
- install.sh: add build artifacts to .gitignore template
- AGENTS.md: document prohibited dirs, gate nomenclature, feature schema
- Reset runtime-status to idle state
2026-08-17 18:59:39 +02:00

190 lines
4.9 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
banner() {
cat <<'EOF'
___ ____ ___ _ _ _____ ____ _____ ____ _
/ _ \| _ \ / _ \| | | | ____/ ___|_ _| _ \ / \
| | | | |_) | | | | | | | _| \___ \ | | | |_) | / _ \
| |_| | _ <| |_| | |_| | |___ ___) || | | _ < / ___ \
\___/|_| \_\\__\_\\___/|_____|____/ |_| |_| \_\/_/ \_\
sequential orchestration runtime
EOF
}
usage() {
cat <<'EOF'
Usage: ./scripts/install.sh /path/to/project-repo
Install or update Orquestra from this source checkout into a target project repo.
Project-owned progress files are created only when missing and are never overwritten.
EOF
}
fail() {
printf '[FAIL] %s\n' "$1" >&2
exit 1
}
warn() {
printf '[WARN] %s\n' "$1" >&2
}
info() {
printf '[OK] %s\n' "$1"
}
copy_file_update() {
local src=$1
local dst=$2
mkdir -p "$(dirname "$dst")"
cp "$src" "$dst"
}
copy_file_if_missing() {
local src=$1
local dst=$2
mkdir -p "$(dirname "$dst")"
if [ ! -e "$dst" ]; then
cp "$src" "$dst"
fi
}
copy_dir_update() {
local src=$1
local dst=$2
mkdir -p "$dst"
cp -R "$src"/. "$dst"/
}
copy_dir_if_missing_contents() {
local src=$1
local dst=$2
local dir file rel
mkdir -p "$dst"
if [ -d "$src" ]; then
find "$src" -type d | while IFS= read -r dir; do
rel=${dir#"$src"}
mkdir -p "$dst$rel"
done
find "$src" -type f | while IFS= read -r file; do
rel=${file#"$src"/}
copy_file_if_missing "$file" "$dst/$rel"
done
fi
}
append_gitignore_block() {
local gitignore=$1
touch "$gitignore"
if ! grep -q '^# BEGIN ORQUESTRA$' "$gitignore"; then
cat >>"$gitignore" <<'INNEREOF'
# BEGIN ORQUESTRA
__pycache__/
*.pyc
.pytest_cache/
.codegraph/
.atl/
# Build artifacts
.next/
dist/
build/
*.log
# Dependencies
node_modules/
# Environment
.env
.env.local
.env.*.local
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# END ORQUESTRA
INNEREOF
fi
}
if [ "$#" -ne 1 ]; then
usage >&2
exit 2
fi
banner
command -v pi >/dev/null 2>&1 || fail "pi is required in PATH before installing Orquestra"
command -v python3 >/dev/null 2>&1 || fail "python3 is required in PATH before installing Orquestra"
SOURCE_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)
TARGET_ARG=$1
TARGET_DIR=$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$TARGET_ARG")
if [ "$TARGET_DIR" = "$SOURCE_DIR" ]; then
fail "target repo must be different from the Orquestra source repo"
fi
mkdir -p "$TARGET_DIR"
if [ ! -d "$TARGET_DIR/.git" ]; then
git -C "$TARGET_DIR" init >/dev/null
info "Initialized git repo in $TARGET_DIR"
fi
# Harness-owned files: update on every run.
for file in AGENTS.md README.md HOWTO.md CHECKPOINTS.md; do
copy_file_update "$SOURCE_DIR/$file" "$TARGET_DIR/$file"
done
copy_dir_update "$SOURCE_DIR/harness" "$TARGET_DIR/harness"
copy_dir_update "$SOURCE_DIR/platforms/pi" "$TARGET_DIR/platforms/pi"
copy_dir_update "$SOURCE_DIR/docs" "$TARGET_DIR/docs"
for file in scripts/verify.sh scripts/agent_status.py scripts/new_ticket.py scripts/pi_orquestra.sh scripts/run_stage.py scripts/commit_feature.sh scripts/close_feature.py scripts/install.sh; do
copy_file_update "$SOURCE_DIR/$file" "$TARGET_DIR/$file"
done
append_gitignore_block "$TARGET_DIR/.gitignore"
# Project-owned/state files: create only when missing.
copy_dir_if_missing_contents "$SOURCE_DIR/project" "$TARGET_DIR/project"
copy_file_if_missing "$SOURCE_DIR/backlog/features.json" "$TARGET_DIR/backlog/features.json"
copy_dir_if_missing_contents "$SOURCE_DIR/spec" "$TARGET_DIR/spec"
copy_file_if_missing "$SOURCE_DIR/work/current.md" "$TARGET_DIR/work/current.md"
copy_file_if_missing "$SOURCE_DIR/work/history.md" "$TARGET_DIR/work/history.md"
copy_file_if_missing "$SOURCE_DIR/work/runtime-status.json" "$TARGET_DIR/work/runtime-status.json"
mkdir -p "$TARGET_DIR/work/artifacts"
if [ -f "$SOURCE_DIR/work/artifacts/.gitkeep" ] && [ ! -e "$TARGET_DIR/work/artifacts/.gitkeep" ]; then
cp "$SOURCE_DIR/work/artifacts/.gitkeep" "$TARGET_DIR/work/artifacts/.gitkeep"
fi
# Pi project-local runtime extensions.
mkdir -p "$TARGET_DIR/.pi/extensions"
copy_dir_update "$SOURCE_DIR/platforms/pi/extensions/orquestra-status" "$TARGET_DIR/.pi/extensions/orquestra-status"
copy_file_update "$SOURCE_DIR/platforms/pi/extensions/orquestra-web-fetch.ts" "$TARGET_DIR/.pi/extensions/orquestra-web-fetch.ts"
if [ -d "$TARGET_DIR/.pi/subagents" ] || [ -f "$TARGET_DIR/.pi/subagents.json" ]; then
warn "Found .pi/subagents or .pi/subagents.json in target. Orquestra does not delete user Pi config automatically; remove Orquestra-owned stale subagent files manually before running verify.sh."
fi
chmod +x "$TARGET_DIR/scripts/verify.sh" "$TARGET_DIR/scripts/pi_orquestra.sh" "$TARGET_DIR/scripts/run_stage.py" "$TARGET_DIR/scripts/install.sh"
cat <<EOF
Orquestra installed/updated safely in: $TARGET_DIR
Next steps:
cd "$TARGET_DIR"
./scripts/verify.sh
./scripts/pi_orquestra.sh
EOF