Пересмотр решения владельца 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>
54 lines
4.2 KiB
Bash
54 lines
4.2 KiB
Bash
# Шаблоны workspace/role-repo и режим --workspace в adopt-project.sh / new-project.sh.
|
||
T="$ROOT/project-template"
|
||
assert_file "workspace/CLAUDE.md" "$T/workspace/CLAUDE.md"
|
||
assert_max_bytes "workspace/CLAUDE.md ≤ 5 КБ" "$T/workspace/CLAUDE.md" 5120
|
||
assert_grep "workspace/CLAUDE.md: таблица репозиториев" '^\| Каталог \| Репозиторий \| Роль \|' "$T/workspace/CLAUDE.md"
|
||
assert_grep "workspace/CLAUDE.md: роли → /role" '/role' "$T/workspace/CLAUDE.md"
|
||
assert_file "workspace/roles/dev.md" "$T/workspace/roles/dev.md"
|
||
assert_grep "workspace/roles/dev.md: строка 1" '^# Роль: dev ' "$T/workspace/roles/dev.md"
|
||
assert_file "role-repo/CLAUDE.md" "$T/role-repo/CLAUDE.md"
|
||
assert_file "role-repo/ROLE.md" "$T/role-repo/ROLE.md"
|
||
assert_file "role-repo/notes/README.md" "$T/role-repo/notes/README.md"
|
||
# new-project.sh --workspace
|
||
W="$TMP/ws"
|
||
out=$(bash "$ROOT/new-project.sh" --workspace "$W" --role admin --role qa 2>&1); rc=$?
|
||
assert_eq "new-project --workspace: exit 0" "$rc" "0"
|
||
assert_file "ws CLAUDE.md" "$W/CLAUDE.md"
|
||
assert_grep "ws CLAUDE.md: имя подставлено" "$(basename "$W")" "$W/CLAUDE.md"
|
||
assert_grep "ws CLAUDE.md: строка admin в таблице" '^\| admin/ \| .* \| admin \|' "$W/CLAUDE.md"
|
||
assert_file "ws .claude/roles/dev.md" "$W/.claude/roles/dev.md"
|
||
assert_eq "admin/ — git на main" "$(git -C "$W/admin" branch --show-current)" "main"
|
||
assert_eq "admin/.claude/role" "$(cat "$W/admin/.claude/role")" "admin"
|
||
assert_grep "admin/.claude/roles/admin.md: строка 1" '^# Роль: admin ' "$W/admin/.claude/roles/admin.md"
|
||
assert_file "admin/notes/README.md" "$W/admin/notes/README.md"
|
||
assert_eq "admin: коммит есть" "$(git -C "$W/admin" log --oneline | wc -l | tr -d ' ')" "1"
|
||
assert_symlink "ws .claude/roles/admin.md слинкован" "$W/.claude/roles/admin.md"
|
||
assert_symlink "ws .claude/roles/qa.md слинкован" "$W/.claude/roles/qa.md"
|
||
assert_eq "workspace сам не git" "$([ -d "$W/.git" ] && echo git || echo no)" "no"
|
||
assert_grep "new-project --workspace: печатает allow-правило (B3)" '"Bash\(git push origin --delete:\*\)"' <(printf '%s' "$out")
|
||
# adopt-project.sh --workspace на существующем каталоге без CLAUDE.md
|
||
W2="$TMP/ws2"; mkdir -p "$W2/qa/.claude/roles"; echo '# Роль: qa — x' > "$W2/qa/.claude/roles/qa.md"
|
||
out=$(bash "$ROOT/adopt-project.sh" --workspace "$W2" 2>&1); rc=$?
|
||
assert_eq "adopt --workspace: exit 0" "$rc" "0"
|
||
assert_file "adopt: CLAUDE.md создан" "$W2/CLAUDE.md"
|
||
assert_file "adopt: .claude/roles/dev.md создан" "$W2/.claude/roles/dev.md"
|
||
assert_grep "adopt: печатает allow-правило" 'git push origin --delete' <(printf '%s' "$out")
|
||
echo 'моё' > "$W2/.claude/roles/dev.md"
|
||
bash "$ROOT/adopt-project.sh" --workspace "$W2" >/dev/null 2>&1
|
||
assert_eq "adopt повторно: dev.md не затёрт" "$(cat "$W2/.claude/roles/dev.md")" "моё"
|
||
# старые режимы не затронуты
|
||
P="$TMP/oldp"
|
||
out=$(bash "$ROOT/new-project.sh" "$P" 2>&1); rc=$?
|
||
assert_eq "new-project (старый режим): exit 0" "$rc" "0"
|
||
assert_eq "new-project (старый режим): git" "$([ -d "$P/.git" ] && echo git || echo no)" "git"
|
||
assert_file "new-project (старый режим): ARCHITECTURE.md" "$P/ARCHITECTURE.md"
|
||
assert_grep "new-project (старый режим): печатает allow-правило (B3)" '"Bash\(git push origin --delete:\*\)"' <(printf '%s' "$out")
|
||
out=$(bash "$ROOT/adopt-project.sh" "$TMP/notgit" 2>&1); rc=$?
|
||
assert_eq "adopt (старый режим): не git → exit 1" "$rc" "1"
|
||
A="$TMP/adopt"; git init -q -b main "$A" && git -C "$A" commit -q --allow-empty -m init
|
||
out=$(bash "$ROOT/adopt-project.sh" "$A" 2>&1); rc=$?
|
||
assert_eq "adopt (старый режим): git-репозиторий → exit 0" "$rc" "0"
|
||
assert_grep "adopt (старый режим): печатает allow-правило (B3)" '"Bash\(git push origin --delete:\*\)"' <(printf '%s' "$out")
|
||
assert_grep "adopt: строка — для установки с --no-permissions (#24)" 'no-permissions' <(printf '%s' "$out")
|
||
assert_eq "adopt (старый режим): settings.json не создаёт" "$([ -e "$A/.claude/settings.json" ] && echo есть || echo нет)" "нет"
|