From b37407874dee282afe9af7808738bf4737dcb68e Mon Sep 17 00:00:00 2001 From: Godopu Date: Wed, 24 Jun 2026 10:43:08 +0900 Subject: [PATCH] Harden installer: partial-install detection, complete runtime docs, explicit copy checks --- deploy/install.sh | 57 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/deploy/install.sh b/deploy/install.sh index 6fed379..474e264 100644 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -57,18 +57,35 @@ cd "$TARGET_DIR" 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" -# 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 # 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 # 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 -# always wins. We key off lib.sh (a file), not the .agents/skills directory, so -# an empty/partial dir can't masquerade as a valid install. -if [ ! -f ".agents/skills/lib.sh" ]; then - echo "📥 Orchestration skills not found. Fetching from Gitea repository..." +# always wins. +if ! check_assets_present "."; then + echo "📥 Orchestration skills not found or incomplete. Fetching from Gitea repository..." STAGE_DIR="$(mktemp -d)" trap 'rm -rf "$STAGE_DIR"' EXIT @@ -84,8 +101,8 @@ if [ ! -f ".agents/skills/lib.sh" ]; then fi # Verify the staged tree before we trust and copy from it. - if [ ! -f "$STAGE_DIR/.agents/skills/lib.sh" ]; then - echo "❌ Error: fetched source is missing '.agents/skills/lib.sh'. Aborting (no files copied)." >&2 + if ! check_assets_present "$STAGE_DIR"; then + echo "❌ Error: fetched source is missing core runtime assets. Aborting (no files copied)." >&2 exit 1 fi @@ -99,14 +116,20 @@ if [ ! -f ".agents/skills/lib.sh" ]; then dest=".agents/${rel#./}" if [ ! -e "$dest" ]; then 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 done - if [ -f "$STAGE_DIR/AGENT.md" ] && [ ! -e "AGENT.md" ]; then - cp "$STAGE_DIR/AGENT.md" . - fi + + # Copy non-dev documents if they don't already exist. + # 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 - cp "$STAGE_DIR/.env.example" . + cp "$STAGE_DIR/.env.example" . || { echo "❌ Error: Failed to copy .env.example" >&2; exit 1; } fi rm -rf "$STAGE_DIR" @@ -114,10 +137,10 @@ if [ ! -f ".agents/skills/lib.sh" ]; then echo "✅ Skills staged into workspace (existing files preserved)." fi -# Sanity check: verify a FILE, not just the directory — an empty .agents/skills -# would otherwise pass and yield a silently broken install. -if [ ! -f ".agents/skills/lib.sh" ]; then - echo "❌ Error: '.agents/skills/lib.sh' missing after setup. Target layout might be invalid." >&2 +# Sanity check: verify all core files, not just a single one — an empty or +# incomplete layout would yield a silently broken install. +if ! check_assets_present "."; then + echo "❌ Error: Core runtime assets missing after setup. Target layout might be invalid." >&2 exit 1 fi echo "✅ Orchestration skills present."