claude-harness/adopt-project.sh
2026-10-12 00:34:12 +04:00

79 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# claude-harness: подключение обвязки к СУЩЕСТВУЮЩЕМУ репозиторию.
# Запуск из терминала (не из Claude Code): bash adopt-project.sh [папка] [--no-merge] [--push]
# Делает всё на ветке chore/harness-init и по умолчанию вливает её в main fast-forward.
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
# Режим workspace (каталог не git, рядом репозитории направлений): bash adopt-project.sh --workspace [папка]
if [ "${1:-}" = "--workspace" ]; then
cd "${2:-.}"; NAME="$(basename "$(pwd)")"
if [ -f CLAUDE.md ]; then echo "CLAUDE.md: есть, не трогаю"
else sed "s/{{PROJECT_NAME}}/$NAME/g" "$HERE/project-template/workspace/CLAUDE.md" > CLAUDE.md; echo "CLAUDE.md: создан из шаблона workspace — заполни {{...}} и таблицу репозиториев"; fi
mkdir -p .claude/roles
if [ -e .claude/roles/dev.md ]; then echo ".claude/roles/dev.md: есть, не трогаю"
else sed "s/{{PROJECT_NAME}}/$NAME/g" "$HERE/project-template/workspace/roles/dev.md" > .claude/roles/dev.md; echo ".claude/roles/dev.md: заготовка"; fi
bash "$HERE/link-roles.sh" "$(pwd)"
cat <<MSG
Workspace $NAME подключён. Дальше:
1. Заполни таблицу репозиториев в CLAUDE.md и перезапусти: bash $HERE/link-roles.sh $(pwd)
2. Разреши агенту удалять ветки на сервере (чеклист закрытия, п. 4) — строка в .claude/settings.json → permissions.allow:
"Bash(git push origin --delete:*)"
3. Сессии: claude -n "dev …" | "admin …" | "qa …" | "analyst …" из этого каталога.
MSG
exit 0
fi
DIR="."; MERGE=1; PUSH=0
for a in "$@"; do case "$a" in --no-merge) MERGE=0;; --push) PUSH=1;; *) DIR="$a";; esac; done
cd "$DIR"
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { echo "ERR: $DIR — не git-репозиторий"; exit 1; }
[ -z "$(git status --porcelain)" ] || { echo "ERR: рабочее дерево не чистое — закоммить или спрячь изменения"; exit 1; }
NAME="$(basename "$(git rev-parse --show-toplevel)")"
BASE="$(git branch --show-current)"
[ -n "$BASE" ] || { echo "ERR: detached HEAD"; exit 1; }
BR=chore/harness-init
git switch -c "$BR" >/dev/null
# CLAUDE.md: свой — дописать секцию харнеса; нет — из шаблона
if [ -f CLAUDE.md ]; then
grep -q '^## OpenSpec и superpowers' CLAUDE.md || { printf '\n' >> CLAUDE.md; cat "$HERE/project-template/CLAUDE.harness-section.md" >> CLAUDE.md; echo "CLAUDE.md: добавлена секция «OpenSpec и superpowers»"; }
else
sed "s/{{PROJECT_NAME}}/$NAME/" "$HERE/project-template/CLAUDE.md" > CLAUDE.md
echo "CLAUDE.md: создан из шаблона — заполни {{...}} (или попроси агента описать проект по коду на отдельной ветке)"
fi
[ -f ARCHITECTURE.md ] || { cp "$HERE/project-template/ARCHITECTURE.md" ARCHITECTURE.md; echo "ARCHITECTURE.md: заготовка"; }
# .gitignore: только строки обвязки
touch .gitignore
for line in '.superpowers/' '.bounded' '.DS_Store'; do
grep -qxF "$line" .gitignore || echo "$line" >> .gitignore
done
mkdir -p docs/superpowers/plans && touch docs/superpowers/plans/.gitkeep
if command -v openspec >/dev/null 2>&1; then
[ -d openspec ] || openspec init --tools claude 2>/dev/null || openspec init
else echo "WARN: openspec не установлен (npm i -g @fission-ai/openspec)"; fi
if command -v codegraph >/dev/null 2>&1; then
[ -d .codegraph ] || codegraph init >/dev/null 2>&1 || echo "WARN: codegraph init не удался"
else echo "WARN: codegraph не установлен"; fi
git add -A
if git diff --cached --quiet; then
echo "Нечего менять: обвязка уже подключена"; git switch "$BASE" >/dev/null; git branch -d "$BR" >/dev/null; exit 0
fi
git commit -qm "chore: claude harness bootstrap"
if [ "$MERGE" = 1 ]; then
git switch "$BASE" >/dev/null && git merge --ff-only "$BR" >/dev/null && git branch -d "$BR" >/dev/null
echo "Влито в $BASE fast-forward."
[ "$PUSH" = 1 ] && git push origin "$BASE"
else
echo "Ветка $BR оставлена, в $BASE не влита."
[ "$PUSH" = 1 ] && git push -u origin "$BR"
fi
cat <<MSG
Проект $NAME подключён к обвязке. Дальше:
cd $(pwd) && claude
«Опиши проект в CLAUDE.md по коду: разделы «Что это», «Стек», «Архитектура», «Команды». Bounded-задача.»
MSG