Пересмотр решения владельца 2: allow-правила (git worktree, git branch -m/-D, push фичевых и chore-веток, push --delete, tea issues/pulls create/list/edit/comments) ставит install.sh в ~/.claude/settings.json, а не владелец руками. Список — global/permissions.json; merge и push в main в нём нет. Правила только дописываются, чужие не трогаются; копия списка — ~/.claude/harness/permissions.json для doctor.sh. - install.sh: шаг 5 — слияние permissions.allow; --no-permissions; неизвестный аргумент — ошибка; --check показывает permissions N/M. - doctor.sh, «Машина»: ok / WARN со списком недостающих / MISS. - adopt/new-project: строка push --delete — для --no-permissions. - harness-doctor: агент чинит install.sh --no-permissions, права ставит владелец (иначе обход отказа классификатора auto mode). - EnterWorktree не входит: вход в worktree вне .claude/worktrees/ спрашивает подтверждение при любых правилах (#25). - README, HARNESS.md, roles/dev.md, CLAUDE.md, ретро (пометка о пересмотре решения 2), CHANGELOG 0.5.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
78 lines
4.5 KiB
Bash
Executable File
78 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# claude-harness: каркас нового проекта под обвязку.
|
||
# Запуск: bash new-project.sh <папка> [ssh-url репозитория в Gitea]
|
||
set -euo pipefail
|
||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||
# Режим workspace: bash new-project.sh --workspace <папка> [--role admin] [--role qa] [--role analyst]
|
||
if [ "${1:-}" = "--workspace" ]; then
|
||
DIR="${2:?usage: new-project.sh --workspace <dir> [--role <r> ...]}"; shift 2
|
||
ROLES=()
|
||
while [ $# -gt 0 ]; do case "$1" in --role) ROLES+=("$2"); shift 2 ;; *) echo "ERR: неизвестный аргумент $1"; exit 1 ;; esac; done
|
||
mkdir -p "$DIR" && cd "$DIR"; NAME="$(basename "$(pwd)")"
|
||
[ -f CLAUDE.md ] || sed "s/{{PROJECT_NAME}}/$NAME/g" "$HERE/project-template/workspace/CLAUDE.md" > CLAUDE.md
|
||
mkdir -p .claude/roles
|
||
[ -e .claude/roles/dev.md ] || sed "s/{{PROJECT_NAME}}/$NAME/g" "$HERE/project-template/workspace/roles/dev.md" > .claude/roles/dev.md
|
||
for r in "${ROLES[@]+"${ROLES[@]}"}"; do
|
||
case "$r" in admin|analyst|qa) ;; *) echo "ERR: роль $r не из admin|analyst|qa"; exit 1 ;; esac
|
||
d="$r"; [ "$r" = analyst ] && d="analysis"
|
||
if [ -d "$d/.git" ]; then echo "$d/: уже git, не трогаю"; continue; fi
|
||
mkdir -p "$d/.claude/roles" "$d/notes"
|
||
sed -e "s/{{PROJECT_NAME}}/$NAME/g" -e "s/{{ROLE}}/$r/g" -e "s#{{DIR}}#$d#g" "$HERE/project-template/role-repo/CLAUDE.md" > "$d/CLAUDE.md"
|
||
sed -e "s/{{PROJECT_NAME}}/$NAME/g" -e "s/{{ROLE}}/$r/g" -e "s#{{DIR}}#$d#g" "$HERE/project-template/role-repo/ROLE.md" > "$d/.claude/roles/$r.md"
|
||
cp "$HERE/project-template/role-repo/notes/README.md" "$d/notes/README.md"
|
||
echo "$r" > "$d/.claude/role"
|
||
git -C "$d" init -q -b main && git -C "$d" add -A && git -C "$d" commit -qm "chore: репозиторий направления $r (claude-harness)"
|
||
# строка таблицы: заменить заготовку {{owner/repo-<r>}} на имя каталога, если заготовка есть
|
||
sed -i.bak "s#| $d/ | {{owner/repo-[a-z]*}} | $r |#| $d/ | <owner>/$NAME-$d | $r |#" CLAUDE.md && rm -f CLAUDE.md.bak
|
||
echo "$d/: репозиторий направления $r создан"
|
||
done
|
||
bash "$HERE/link-roles.sh" "$(pwd)"
|
||
cat <<MSG
|
||
|
||
Workspace $NAME готов. Дальше:
|
||
1. Заполни {{...}} в CLAUDE.md и в .claude/roles/dev.md; в репозиториях направлений — .claude/roles/<r>.md.
|
||
2. Заведи репозитории направлений в Gitea и добавь remote (tea repos create …; git remote add origin …).
|
||
3. Если обвязка ставилась с --no-permissions: разреши агенту удалять ветки на сервере (чеклист закрытия, п. 4) — строка в .claude/settings.json → permissions.allow:
|
||
"Bash(git push origin --delete:*)"
|
||
4. cd $(pwd) && claude -n "dev …"
|
||
MSG
|
||
exit 0
|
||
fi
|
||
DIR="${1:?usage: new-project.sh <dir> [git-remote-url]}"
|
||
REMOTE="${2:-}"
|
||
NAME="$(basename "$DIR")"
|
||
|
||
mkdir -p "$DIR" && cd "$DIR"
|
||
[ -d .git ] || git init -b main
|
||
sed "s/{{PROJECT_NAME}}/$NAME/" "$HERE/project-template/CLAUDE.md" > CLAUDE.md
|
||
cp "$HERE/project-template/ARCHITECTURE.md" ARCHITECTURE.md
|
||
cp "$HERE/project-template/gitignore" .gitignore
|
||
mkdir -p tests/fixtures docs/superpowers/plans
|
||
|
||
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 не удался"
|
||
fi
|
||
|
||
git add -A
|
||
git commit -qm "chore: bootstrap project skeleton (claude-harness)" || true
|
||
if [ -n "$REMOTE" ]; then
|
||
git remote get-url origin >/dev/null 2>&1 || git remote add origin "$REMOTE"
|
||
git push -u origin main
|
||
fi
|
||
|
||
cat <<MSG
|
||
|
||
Проект $NAME готов. Дальше:
|
||
1. Заполните {{...}} в CLAUDE.md и ARCHITECTURE.md.
|
||
2. Положите первые фикстуры в tests/fixtures/.
|
||
3. Если обвязка ставилась с --no-permissions: разрешите агенту удалять ветки на сервере (чеклист закрытия, п. 4) — строка в .claude/settings.json → permissions.allow:
|
||
"Bash(git push origin --delete:*)"
|
||
4. cd $DIR && claude
|
||
«Хочу сделать ... Описание и ограничения в CLAUDE.md. Давай начнём.»
|
||
MSG
|