Harden installer: partial-install detection, complete runtime docs, explicit copy checks
This commit is contained in:
+40
-17
@@ -57,18 +57,35 @@ cd "$TARGET_DIR"
|
|||||||
REPO_URL="https://git.godopu.com/tmpl/multi-agent-mux.git"
|
REPO_URL="https://git.godopu.com/tmpl/multi-agent-mux.git"
|
||||||
ARCHIVE_URL="https://git.godopu.com/tmpl/multi-agent-mux/archive/main.tar.gz"
|
ARCHIVE_URL="https://git.godopu.com/tmpl/multi-agent-mux/archive/main.tar.gz"
|
||||||
|
|
||||||
# Fetch the orchestration assets if missing (for curl one-liner installs).
|
# Helper to verify presence of all core runtime files.
|
||||||
|
# Keying off a set of core files helps detect and recover from partial/interrupted installations.
|
||||||
|
check_assets_present() {
|
||||||
|
local dir="${1:-.}"
|
||||||
|
local core_files=(
|
||||||
|
".agents/skills/lib.sh"
|
||||||
|
".agents/skills/multi-agent-mux-create/scripts/create_session.sh"
|
||||||
|
".agents/skills/multi-agent-mux-delegate-job/scripts/registry.py"
|
||||||
|
".agents/skills/multi-agent-mux-status/scripts/status.sh"
|
||||||
|
)
|
||||||
|
for f in "${core_files[@]}"; do
|
||||||
|
if [ ! -f "$dir/$f" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch the orchestration assets if missing or incomplete (for curl one-liner installs).
|
||||||
#
|
#
|
||||||
# Safety model (FW-D1): we NEVER extract the repo archive directly into the
|
# Safety model (FW-D1): we NEVER extract the repo archive directly into the
|
||||||
# target. Running inside an existing project must not overwrite the target's
|
# target. Running inside an existing project must not overwrite the target's
|
||||||
# own files (README.md, FUTURE_WORKS.md, …) or litter it with this repo's
|
# own files (README.md, FUTURE_WORKS.md, …) or litter it with this repo's
|
||||||
# development docs. Instead we stage the download into a throwaway temp dir,
|
# development docs. Instead we stage the download into a throwaway temp dir,
|
||||||
# verify it, then copy ONLY the runtime assets (.agents/, AGENT.md, .env.example)
|
# verify it, then copy ONLY the runtime assets (.agents/, documents, .env.example)
|
||||||
# into the target with per-file no-clobber guards so a pre-existing target file
|
# into the target with per-file no-clobber guards so a pre-existing target file
|
||||||
# always wins. We key off lib.sh (a file), not the .agents/skills directory, so
|
# always wins.
|
||||||
# an empty/partial dir can't masquerade as a valid install.
|
if ! check_assets_present "."; then
|
||||||
if [ ! -f ".agents/skills/lib.sh" ]; then
|
echo "📥 Orchestration skills not found or incomplete. Fetching from Gitea repository..."
|
||||||
echo "📥 Orchestration skills not found. Fetching from Gitea repository..."
|
|
||||||
STAGE_DIR="$(mktemp -d)"
|
STAGE_DIR="$(mktemp -d)"
|
||||||
trap 'rm -rf "$STAGE_DIR"' EXIT
|
trap 'rm -rf "$STAGE_DIR"' EXIT
|
||||||
|
|
||||||
@@ -84,8 +101,8 @@ if [ ! -f ".agents/skills/lib.sh" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Verify the staged tree before we trust and copy from it.
|
# Verify the staged tree before we trust and copy from it.
|
||||||
if [ ! -f "$STAGE_DIR/.agents/skills/lib.sh" ]; then
|
if ! check_assets_present "$STAGE_DIR"; then
|
||||||
echo "❌ Error: fetched source is missing '.agents/skills/lib.sh'. Aborting (no files copied)." >&2
|
echo "❌ Error: fetched source is missing core runtime assets. Aborting (no files copied)." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -99,14 +116,20 @@ if [ ! -f ".agents/skills/lib.sh" ]; then
|
|||||||
dest=".agents/${rel#./}"
|
dest=".agents/${rel#./}"
|
||||||
if [ ! -e "$dest" ]; then
|
if [ ! -e "$dest" ]; then
|
||||||
mkdir -p "$(dirname "$dest")"
|
mkdir -p "$(dirname "$dest")"
|
||||||
cp "$STAGE_DIR/.agents/$rel" "$dest"
|
cp "$STAGE_DIR/.agents/$rel" "$dest" || { echo "❌ Error: Failed to copy $rel" >&2; exit 1; }
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [ -f "$STAGE_DIR/AGENT.md" ] && [ ! -e "AGENT.md" ]; then
|
|
||||||
cp "$STAGE_DIR/AGENT.md" .
|
# Copy non-dev documents if they don't already exist.
|
||||||
fi
|
# We skip dev-specific docs like README.md, DONE.md, and FUTURE_WORKS.md.
|
||||||
|
for doc in AGENT.md AGENT.ko.md MESSAGING.md BOOTSTRAP.md BOOTSTRAP.ko.md INSTRUCTION.md; do
|
||||||
|
if [ -f "$STAGE_DIR/$doc" ] && [ ! -e "$doc" ]; then
|
||||||
|
cp "$STAGE_DIR/$doc" . || { echo "❌ Error: Failed to copy $doc" >&2; exit 1; }
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
if [ -f "$STAGE_DIR/.env.example" ] && [ ! -e ".env.example" ]; then
|
if [ -f "$STAGE_DIR/.env.example" ] && [ ! -e ".env.example" ]; then
|
||||||
cp "$STAGE_DIR/.env.example" .
|
cp "$STAGE_DIR/.env.example" . || { echo "❌ Error: Failed to copy .env.example" >&2; exit 1; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$STAGE_DIR"
|
rm -rf "$STAGE_DIR"
|
||||||
@@ -114,10 +137,10 @@ if [ ! -f ".agents/skills/lib.sh" ]; then
|
|||||||
echo "✅ Skills staged into workspace (existing files preserved)."
|
echo "✅ Skills staged into workspace (existing files preserved)."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Sanity check: verify a FILE, not just the directory — an empty .agents/skills
|
# Sanity check: verify all core files, not just a single one — an empty or
|
||||||
# would otherwise pass and yield a silently broken install.
|
# incomplete layout would yield a silently broken install.
|
||||||
if [ ! -f ".agents/skills/lib.sh" ]; then
|
if ! check_assets_present "."; then
|
||||||
echo "❌ Error: '.agents/skills/lib.sh' missing after setup. Target layout might be invalid." >&2
|
echo "❌ Error: Core runtime assets missing after setup. Target layout might be invalid." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "✅ Orchestration skills present."
|
echo "✅ Orchestration skills present."
|
||||||
|
|||||||
Reference in New Issue
Block a user