- apply.sh: direct-run guard (only curl | bash allowed) - apply.sh: DEV_ROOT passed as explicit arg from bootstrap - apply.sh: .ai/ copied to dev root as real folder; projects symlink there - apply.sh: counters + detailed summary (version prev→new, templated, refreshed, no-docs) - apply.sh: find errors silenced, no crash on empty dev root - .ai-superpower: added warning comment about deletion side effects - .gitignore: .ai-instructions.conf → .ai-superpower.version - scripts/: removed (hello.sh, scan-projects-with-git.sh, verify-docs-folder.sh, add-ai-context-to-docs-folder.sh) - templates: monorepo sections split into AI instructions + developer instructions - README.md: rewritten to match current architecture and behaviour - docs/apply-requirements.md: FR-2.4, FR-3, FR-5, FR-6, FR-7, FR-8 updated - docs/apply-usecases.md: full detailed Mermaid flowchart replacing placeholder
143 lines
5.9 KiB
Bash
Executable File
143 lines
5.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
REPO_URL="https://gitea.nikos-dev.keskikuja.site/niko/ai-superpower.git"
|
|
REPO_NAME="ai-superpower"
|
|
RAW_URL="https://gitea.nikos-dev.keskikuja.site/niko/ai-superpower/raw/branch/main/apply.sh"
|
|
|
|
# ── Bootstrap mode (curl | bash) ─────────────────────────────────────────────
|
|
# BASH_SOURCE[0] is empty when piped through bash
|
|
if [[ -z "${BASH_SOURCE[0]:-}" ]]; then
|
|
DEV_ROOT="$PWD" # capture before exec replaces the process
|
|
TARGET="$DEV_ROOT/$REPO_NAME"
|
|
if [[ -d "$TARGET" ]]; then
|
|
echo "→ updating $REPO_NAME ..."
|
|
git -C "$TARGET" pull || { echo "✗ git pull failed"; exit 1; }
|
|
else
|
|
echo "→ cloning $REPO_NAME into $TARGET ..."
|
|
git clone "$REPO_URL" "$TARGET" || { echo "✗ git clone failed"; exit 1; }
|
|
fi
|
|
# Pass DEV_ROOT explicitly — local mode must not guess it from script location
|
|
exec bash "$TARGET/apply.sh" --bootstrapped "$DEV_ROOT"
|
|
fi
|
|
|
|
# ── Guard — block direct invocation ──────────────────────────────────────────
|
|
if [[ "${1:-}" != "--bootstrapped" ]]; then
|
|
echo "✗ do not run this script directly."
|
|
echo " run from your dev root folder:"
|
|
echo ""
|
|
echo " curl -fsSL $RAW_URL | bash"
|
|
echo ""
|
|
exit 1
|
|
fi
|
|
|
|
# ── Local mode ────────────────────────────────────────────────────────────────
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
DEV_ROOT="${2:?DEV_ROOT not passed — re-run via curl}"
|
|
AI_TARGET="$DEV_ROOT/.ai"
|
|
TEMPLATE_MARKER="<!-- ai-superpower:template"
|
|
|
|
# Counters
|
|
cnt_found=0
|
|
cnt_no_docs=0
|
|
cnt_templated=0
|
|
cnt_refreshed=0
|
|
|
|
# ── Install .ai/ into dev root (real folder, refreshed on every run) ─────────
|
|
echo "→ installing .ai/ into $DEV_ROOT ..."
|
|
rm -rf "$AI_TARGET"
|
|
cp -r "$SCRIPT_DIR/.ai" "$AI_TARGET"
|
|
if ! grep -qxF '.ai' "$DEV_ROOT/.gitignore" 2>/dev/null; then
|
|
echo '.ai' >> "$DEV_ROOT/.gitignore"
|
|
fi
|
|
|
|
setup_project() {
|
|
local project="$1"
|
|
local name
|
|
name="$(basename "$project")"
|
|
echo ""
|
|
echo "▸ $name"
|
|
|
|
# FR-3: symlink
|
|
local ai_link="$project/.ai"
|
|
if [[ -L "$ai_link" && "$(readlink "$ai_link")" == "$AI_TARGET" ]]; then
|
|
: # correct — skip silently
|
|
else
|
|
ln -sfn "$AI_TARGET" "$ai_link"
|
|
echo " ✓ .ai symlinked"
|
|
fi
|
|
|
|
# FR-4: .gitignore
|
|
local gitignore="$project/.gitignore"
|
|
if ! grep -qxF '.ai' "$gitignore" 2>/dev/null; then
|
|
echo '.ai' >> "$gitignore"
|
|
echo " ✓ .ai added to .gitignore"
|
|
fi
|
|
|
|
# FR-5 + FR-6: docs
|
|
local docs="$project/docs"
|
|
if [[ ! -d "$docs" ]]; then
|
|
echo " ⚠ no docs/ folder — skipping context setup"
|
|
(( cnt_no_docs++ )) || true
|
|
return
|
|
fi
|
|
|
|
local got_template=0
|
|
|
|
if [[ ! -f "$docs/ai-context.md" ]]; then
|
|
cp "$SCRIPT_DIR/templates/ai-context.md" "$docs/ai-context.md"
|
|
echo " ✓ created docs/ai-context.md"
|
|
got_template=1
|
|
elif head -1 "$docs/ai-context.md" | grep -qF "$TEMPLATE_MARKER"; then
|
|
cp "$SCRIPT_DIR/templates/ai-context.md" "$docs/ai-context.md"
|
|
echo " ✓ refreshed docs/ai-context.md (was factory template)"
|
|
(( cnt_refreshed++ )) || true
|
|
fi
|
|
|
|
if [[ ! -f "$docs/architecture.md" ]]; then
|
|
cp "$SCRIPT_DIR/templates/architecture.md" "$docs/architecture.md"
|
|
echo " ✓ created docs/architecture.md"
|
|
got_template=1
|
|
elif head -1 "$docs/architecture.md" | grep -qF "$TEMPLATE_MARKER"; then
|
|
cp "$SCRIPT_DIR/templates/architecture.md" "$docs/architecture.md"
|
|
echo " ✓ refreshed docs/architecture.md (was factory template)"
|
|
(( cnt_refreshed++ )) || true
|
|
fi
|
|
|
|
(( got_template )) && (( cnt_templated++ )) || true
|
|
}
|
|
|
|
# ── Scan and run ──────────────────────────────────────────────────────────────
|
|
echo "→ scanning $DEV_ROOT for projects ..."
|
|
|
|
while IFS= read -r gitdir; do
|
|
project="$(cd "$(dirname "$gitdir")" && pwd)"
|
|
[[ -f "$project/.ai-superpower" ]] && continue
|
|
setup_project "$project"
|
|
(( cnt_found++ )) || true
|
|
done < <(find "$DEV_ROOT" -mindepth 2 -maxdepth 4 -name ".git" -type d 2>/dev/null || true)
|
|
|
|
# ── Summary ───────────────────────────────────────────────────────────────────
|
|
COMMIT="$(git -C "$SCRIPT_DIR" rev-parse --short HEAD 2>/dev/null || echo "unknown")"
|
|
PREV_COMMIT="$(grep '^commit:' "$DEV_ROOT/.ai-superpower.version" 2>/dev/null | awk '{print $2}' || echo "")"
|
|
|
|
echo ""
|
|
echo "────────────────────────────────────────"
|
|
if [[ -n "$PREV_COMMIT" && "$PREV_COMMIT" != "$COMMIT" ]]; then
|
|
echo " version: $PREV_COMMIT → $COMMIT"
|
|
elif [[ -n "$PREV_COMMIT" ]]; then
|
|
echo " version: $COMMIT (no change)"
|
|
else
|
|
echo " version: $COMMIT (first run)"
|
|
fi
|
|
echo " projects: $cnt_found found"
|
|
(( cnt_no_docs > 0 )) && echo " no docs/: $cnt_no_docs project(s) skipped (no docs/ folder)" || true
|
|
(( cnt_templated > 0 )) && echo " templated: $cnt_templated project(s) received new docs templates" || true
|
|
(( cnt_refreshed > 0 )) && echo " refreshed: $cnt_refreshed template file(s) updated (were still factory default)" || true
|
|
echo "────────────────────────────────────────"
|
|
(( cnt_found > 0 )) && echo "✅ done" || echo "⚠ no projects found — are you in the right directory?"
|
|
|
|
# FR-8: write version file
|
|
printf '# Written by apply.sh on every run — shows when it was last run and which version of ai-superpower was used.\ndate: %s\ncommit: %s\n' \
|
|
"$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$COMMIT" > "$DEV_ROOT/.ai-superpower.version"
|