chore(claude): agents view readiness — cleanup script, worktreeinclude, workflow rules
Подготовка к переходу на 'claude agents' dashboard как daily driver:
- scripts/cleanup-merged-worktrees.sh: removes worktrees whose branch is
ancestor of forgejo/main. Run weekly via cron or manually after merge
bursts. Safe — skips unmerged branches and current worktree.
- .worktreeinclude: copies .env files + .mcp.json into every new worktree
(otherwise backend/frontend/MCP fail to start in fresh worktrees Claude
creates for background sessions).
- .claude/rules/git-pr.md:
- new MANDATORY workflow: default 'claude --bg --name X' background
session (auto worktree, auto baseRef=fresh) vs foreground fallback
- session naming convention (--name kebab-case)
- polling section: preferred (agents view row status ●) vs foreground
fallback (Skill loop)
- new 'Multi-session workflow (Agent View)' section: parallelism budget,
Ctrl+T pin, deprecated 'manual git worktree add', weekly cleanup ref
Local-only (not in this PR):
- .claude/settings.json: worktree.{baseRef:fresh, bgIsolation:worktree}
(gitignored as personal preference)
Pre-cleanup state: 102 worktrees / 14GB. After: 99 / 14GB — only 3 squash-
merged branches removed via safe --is-ancestor check; 99 retained as
unmerged WIP. Aggressive cleanup (by age + Forgejo PR check) — future PR.
This commit is contained in:
parent
643064ee0c
commit
bc259b8024
3 changed files with 127 additions and 5 deletions
|
|
@ -11,19 +11,34 @@ paths:
|
||||||
|
|
||||||
## Branch + PR (MANDATORY)
|
## Branch + PR (MANDATORY)
|
||||||
|
|
||||||
|
**Default workflow — background session через `claude --bg`:**
|
||||||
|
|
||||||
```
|
```
|
||||||
1. git fetch forgejo && git checkout -b feat/<scope> forgejo/main # или fix/ refactor/ docs/ chore/ perf/
|
1. claude --bg --name "feat-<scope>" "task description"
|
||||||
|
→ supervisor создаёт worktree от forgejo/main автоматически
|
||||||
|
(settings worktree.baseRef=default, bgIsolation=git)
|
||||||
|
2. Session работает: код → commit → push → mcp__forgejo__create_pull_request
|
||||||
|
3. PR URL появляется в agent view как row с зелёной/жёлтой/красной ● status dot
|
||||||
|
4. User делает review через external Claude window (post-push)
|
||||||
|
5. После merge — `Ctrl+X dwa раза` в agent view = удаление session + worktree
|
||||||
|
```
|
||||||
|
|
||||||
|
**Foreground workflow** (когда нужен интерактив, ad-hoc fixes):
|
||||||
|
|
||||||
|
```
|
||||||
|
1. git fetch forgejo && git checkout -b feat/<scope> forgejo/main
|
||||||
2. [worker делает код, staged]
|
2. [worker делает код, staged]
|
||||||
3. code-reviewer subagent на staged changes (pre-push)
|
3. code-reviewer subagent на staged changes (pre-push)
|
||||||
4. main session: git commit -m "feat(scope): ..."
|
4. main session: git commit -m "feat(scope): ..."
|
||||||
5. git push -u forgejo feat/<scope>
|
5. git push -u forgejo feat/<scope>
|
||||||
6. mcp__forgejo__create_pull_request (или curl POST $REPO/pulls)
|
6. mcp__forgejo__create_pull_request
|
||||||
7. Вернуть PR URL пользователю (https://git.gendsgn.ru/lekss361/gendesign/pulls/<N>)
|
7. Вернуть PR URL пользователю
|
||||||
8. СРАЗУ Skill loop polling (см. Polling loop)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Никаких direct push в main.** Только через PR merge через Forgejo. `gh` CLI bypassed (2026-05-16) — все PR-операции через `mcp__forgejo__*` или curl + `$FORGEJO_TOKEN`.
|
**Никаких direct push в main.** Только через PR merge через Forgejo. `gh` CLI bypassed (2026-05-16) — все PR-операции через `mcp__forgejo__*` или curl + `$FORGEJO_TOKEN`.
|
||||||
|
|
||||||
|
**Session naming MANDATORY** для background spawn: `--name "<type>-<scope>-<detail>"` (kebab-case, ≤30 chars). Примеры: `feat-tradein-cron`, `fix-nominatim-rate-limit`, `chore-claude-config`. Resume: `claude --resume feat-tradein-cron`. Filter в agent view: type `feat-tradein` в input.
|
||||||
|
|
||||||
## Commit messages
|
## Commit messages
|
||||||
|
|
||||||
- **Conventional**: `feat(scope): ...` / `fix(scope): ...` / `refactor/docs/chore/perf`
|
- **Conventional**: `feat(scope): ...` / `fix(scope): ...` / `refactor/docs/chore/perf`
|
||||||
|
|
@ -49,7 +64,15 @@ Closes #N
|
||||||
|
|
||||||
## Polling loop
|
## Polling loop
|
||||||
|
|
||||||
После `mcp__forgejo__create_pull_request` — СРАЗУ `Skill loop` (self-paced, 90-120s) или background Bash poll:
|
**Preferred (background session):** dispatch'нул через `claude --bg --name "feat-X"` → session сама делает PR + monitor. В `claude agents` row показывает:
|
||||||
|
- 🟡 yellow ● = waiting on checks/review
|
||||||
|
- 🟢 green ● = merged
|
||||||
|
- 🔴 red ● = checks failed
|
||||||
|
- ⚫ grey ● = draft/closed
|
||||||
|
|
||||||
|
Не нужно отдельный polling loop — supervisor сам обновляет row каждые 15s. Peek (`Space`) для контекста, attach (`Enter`) если нужен fixup.
|
||||||
|
|
||||||
|
**Foreground fallback** — если работаешь без agents view: `Skill loop` (self-paced, 90-120s) или background Bash poll:
|
||||||
|
|
||||||
1. `mcp__forgejo__get_pull_request` (или `curl -sH "$H" "$REPO/pulls/<N>"`) → читай `state`, `mergeable`, `head.sha`
|
1. `mcp__forgejo__get_pull_request` (или `curl -sH "$H" "$REPO/pulls/<N>"`) → читай `state`, `mergeable`, `head.sha`
|
||||||
2. `state == merged` → stop polling
|
2. `state == merged` → stop polling
|
||||||
|
|
@ -94,6 +117,19 @@ Issues ≥ 1.5 day → 3-4 sub-PRs: **Foundation → Schema → Workers → Inte
|
||||||
- **Pre-push** (локально): spawn `code-reviewer` subagent на staged changes → lint pass (security, correctness, conventions). Блокирует push при 🔴 критикал.
|
- **Pre-push** (локально): spawn `code-reviewer` subagent на staged changes → lint pass (security, correctness, conventions). Блокирует push при 🔴 критикал.
|
||||||
- **Post-push** (внешнее окно Claude): делает review после PR create, постит комменты от `lekss361`. Main session НЕ дублирует — только acting on review comments (fixup commits).
|
- **Post-push** (внешнее окно Claude): делает review после PR create, постит комменты от `lekss361`. Main session НЕ дублирует — только acting on review comments (fixup commits).
|
||||||
|
|
||||||
|
## Multi-session workflow (Agent View)
|
||||||
|
|
||||||
|
**Default daily driver:** одно окно с `claude agents` всегда открыто. Все задачи dispatch'аются оттуда через type prompt + Enter — каждая создаёт background session с собственной worktree.
|
||||||
|
|
||||||
|
- **Параллелизм**: 3-5 sessions одновременно (>5 = bottleneck на review, не на Claude per Anthropic метрика)
|
||||||
|
- **Pin (`Ctrl+T`)** для long-running sessions (scraper monitors, deploy watchers) — supervisor не убьёт через 1h idle
|
||||||
|
- **Cleanup**: `Ctrl+X dwa раза` после merge → session + worktree удалены атомарно
|
||||||
|
- **NEVER** parallel sessions на one file — каждая ест в own worktree, last-merge wins (используй sequential PR rule выше)
|
||||||
|
|
||||||
|
**Manual `git worktree add` deprecated** — используй `claude --bg --name X`, supervisor сам isolation делает с `baseRef: default` (свежая ветка от main, не от твоей stale-сессии).
|
||||||
|
|
||||||
|
**Worktree cleanup** (cron weekly): `scripts/cleanup-merged-worktrees.sh` — удаляет worktrees для merged branches. Запускать вручную или weekly cron.
|
||||||
|
|
||||||
## Запреты
|
## Запреты
|
||||||
|
|
||||||
- ❌ `git push forgejo main` / direct push в main
|
- ❌ `git push forgejo main` / direct push в main
|
||||||
|
|
|
||||||
15
.worktreeinclude
Normal file
15
.worktreeinclude
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Files copied into every new Claude Code worktree (despite being gitignored).
|
||||||
|
#
|
||||||
|
# `claude --bg` / `claude --worktree` / `claude agents` create fresh worktrees
|
||||||
|
# from a clean tree. Without these files copied, backend won't start (missing
|
||||||
|
# .env), frontend won't connect to API, MCP servers won't authenticate.
|
||||||
|
#
|
||||||
|
# Only gitignored files matched by these patterns are copied — tracked files
|
||||||
|
# are never duplicated.
|
||||||
|
#
|
||||||
|
# Reference: https://code.claude.com/docs/en/worktrees#copy-gitignored-files
|
||||||
|
|
||||||
|
backend/.env
|
||||||
|
backend/.env.runtime
|
||||||
|
frontend/.env.local
|
||||||
|
.mcp.json
|
||||||
71
scripts/cleanup-merged-worktrees.sh
Executable file
71
scripts/cleanup-merged-worktrees.sh
Executable file
|
|
@ -0,0 +1,71 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Cleanup merged Claude Code background-session worktrees.
|
||||||
|
#
|
||||||
|
# `claude agents` / `claude --bg` создают `.claude/worktrees/agent-*` для
|
||||||
|
# каждой background session. После merge PR worktree остаётся locked
|
||||||
|
# и не удаляется автоматически — за неделю накапливаются десятки.
|
||||||
|
#
|
||||||
|
# Скрипт сравнивает branch каждого worktree с `forgejo/main`; если branch
|
||||||
|
# полностью в main (merged) — удаляет worktree с `--force` (worktree
|
||||||
|
# заперт супервизором). Затем `git worktree prune` чистит references.
|
||||||
|
#
|
||||||
|
# Запускать вручную или через cron (weekly recommended):
|
||||||
|
# 0 9 * * MON cd /path/to/gendesign && ./scripts/cleanup-merged-worktrees.sh
|
||||||
|
#
|
||||||
|
# Safe:
|
||||||
|
# - Не трогает unmerged branches (in-progress work, PR ещё не merged)
|
||||||
|
# - Не трогает worktree.lock с твоими running sessions (force нужен только
|
||||||
|
# потому что Claude Code ставит lock автоматически)
|
||||||
|
# - Логи action — каждый удалённый branch выводится отдельной строкой
|
||||||
|
#
|
||||||
|
# Reference: https://code.claude.com/docs/en/worktrees#clean-up-worktrees
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
cd "$REPO_ROOT"
|
||||||
|
|
||||||
|
echo "Fetching forgejo/main..."
|
||||||
|
git fetch forgejo main --quiet
|
||||||
|
|
||||||
|
BEFORE=$(git worktree list | wc -l)
|
||||||
|
SIZE_BEFORE=$(du -sh .claude/worktrees/ 2>/dev/null | awk '{print $1}')
|
||||||
|
|
||||||
|
echo "Scanning $((BEFORE - 1)) worktrees (skip main)..."
|
||||||
|
|
||||||
|
REMOVED=0
|
||||||
|
KEPT=0
|
||||||
|
|
||||||
|
# Parse `git worktree list --porcelain` into "path branch" pairs.
|
||||||
|
git worktree list --porcelain | awk '/^worktree/{w=$2} /^branch/{b=$2} /^$/{print w" "b}' | \
|
||||||
|
while read path branch; do
|
||||||
|
# Skip main worktree (no branch field) and detached HEADs.
|
||||||
|
[ -z "$branch" ] && continue
|
||||||
|
|
||||||
|
short="${branch#refs/heads/}"
|
||||||
|
|
||||||
|
# Don't touch the worktree we're standing in.
|
||||||
|
if [ "$path" = "$REPO_ROOT" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if git merge-base --is-ancestor "$short" forgejo/main 2>/dev/null; then
|
||||||
|
if git worktree remove --force "$path" 2>/dev/null; then
|
||||||
|
echo " removed: $short"
|
||||||
|
REMOVED=$((REMOVED + 1))
|
||||||
|
else
|
||||||
|
echo " failed: $short ($path)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
KEPT=$((KEPT + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
git worktree prune
|
||||||
|
|
||||||
|
AFTER=$(git worktree list | wc -l)
|
||||||
|
SIZE_AFTER=$(du -sh .claude/worktrees/ 2>/dev/null | awk '{print $1}')
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Before: $((BEFORE - 1)) worktrees, $SIZE_BEFORE"
|
||||||
|
echo "After: $((AFTER - 1)) worktrees, $SIZE_AFTER"
|
||||||
Loading…
Add table
Reference in a new issue