#!/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 </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' '.claude/worktrees/' '.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 <