claude-harness/tests/test-workspace.sh
andrey.epifantsev 00b496d6da feat: worktree в <repo>/.claude/worktrees/ через EnterWorktree, вход без подтверждения (#25, 0.5.1)
С Claude Code 2.1.206 вход в worktree вне .claude/worktrees/ спрашивает
подтверждение при любых allow-правилах. EnterWorktree с именем создаёт
worktree в <repo>/.claude/worktrees/<slug> на ветке worktree-<slug> от
origin/main и входит без вопроса; ветка переименовывается в
feat/<id>-<slug>.

- roles/dev.md: «Исполнение» — EnterWorktree с именем; п. 1 закрытия —
  archive-<id>; п. 4 — ExitWorktree (keep) снимает блокировку сессии,
  затем git worktree remove и branch -D.
- .claude/worktrees/ в .gitignore: adopt-project.sh, project-template,
  этот репозиторий; doctor.sh — WARN, если не игнорируется.
- Спека hook-guards: сценарии «worktree внутри репозитория» для
  guard-main и require-plan; тесты закрепляют уже верное поведение.
- HARNESS.md (шаг 4, п. 4, подтверждения), SKILL.md, CHANGELOG 0.5.1,
  CLAUDE.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 00:20:35 +04:00

56 lines
4.4 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Шаблоны 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")
assert_grep "new-project: .claude/worktrees/ в .gitignore (#25)" '^\.claude/worktrees/$' "$P/.gitignore"
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 нет)" "нет"
assert_grep "adopt: .claude/worktrees/ в .gitignore (#25)" '^\.claude/worktrees/$' "$A/.gitignore"