/
ump-team
/
ump-infra
Обзор
Документация
Войти
/
ump-team
/
ump-infra
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
dev/test
scripts/worktree-init.sh
217 строк
9 KB
Dmitry Kochenov
init v0.0.2
19 июл 2026, 19:11
19 июл 2026, 19:11
13d6d0b
Код
Авторство
О чём код?
#!/usr/bin/env bash # ============================================================================= # worktree-init.sh — создание изолированного git worktree для sub-agent # ============================================================================= # Назначение: # Создаёт изолированное git worktree для одного parallel sub-agent. # Каждый sub-agent работает в собственном рабочем дереве — это safety guard №1 # из правила .agent/rules/18-parallel-subagents.md. # Использование: # ./scripts/worktree-init.sh <step_id> <phase> <subagent_id> # ./scripts/worktree-init.sh 1.6 CODE_REVIEW security-agent # ./scripts/worktree-init.sh 2.3 TESTING pkg-auth # Создаёт: # ../.worktrees/<step_id>/<phase>/<subagent_id>/ # ветка: worktree/<step_id>/<phase>/<subagent_id> # Поведение: # 1. Проверяет аргументы (3 обязательных) # 2. Проверяет что phase ∈ parallel_eligible_phases # (TESTING, CODE_REVIEW, FINAL_TESTING, FINAL_REVIEW) # 3. Создаёт git worktree с новой веткой # 4. Копирует .env из основного репо (если есть) # 5. Запускает setup (pnpm install, pip install -e .) — если применимо # 6. Выводит путь к worktree в stdout (для использования sub-agent'ом) # 7. Логирует в _meta/agent.log # Источники: # - https://medium.com/google-cloud/run-multiple-coding-agents-safely-with-git-worktrees-c2d237dbd6b2 # - https://blog.kilo.ai/p/agent-manager-run-multiple-agents # - .agent/rules/18-parallel-subagents.md # - _meta/rules-constants.yaml → parallel_config # Выходы: # 0 — успех, путь к worktree в stdout # 1 — ошибка аргументов # 2 — phase не eligible для parallel # 3 — worktree уже существует # 4 — git worktree add упал # 5 — setup упал (non-fatal: warning, но worktree создан) # ============================================================================= set -euo pipefail # ----------------------------------------------------------------------------- # 0. Константы и пути # ----------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" BASE_DIR="$(cd "$REPO_ROOT/.." && pwd)" WORKTREE_BASE="$BASE_DIR/.worktrees" LOG_FILE="$REPO_ROOT/_meta/agent.log" # parallel_eligible_phases из _meta/rules-constants.yaml → parallel_config ELIGIBLE_PHASES="TESTING CODE_REVIEW FINAL_TESTING FINAL_REVIEW" # ----------------------------------------------------------------------------- # 1. Логирование # ----------------------------------------------------------------------------- log() { # $1 — type (subagent/guardrail/action), $2 — prefix, $3+ — message local type="$1" local prefix="$2" shift 2 local msg="$*" local ts ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" echo "$ts [PARALLEL] type=$type prefix=$prefix $msg" >> "$LOG_FILE" } log_subagent() { log "subagent" "[PARALLEL]" "$*"; } log_guardrail() { log "guardrail" "[GUARDRAIL]" "$*"; } log_action() { log "action" "[MERGE]" "$*"; } # ----------------------------------------------------------------------------- # 2. Проверка аргументов # ----------------------------------------------------------------------------- if [ "$#" -ne 3 ]; then cat >&2 <<'EOF' ОШИБКА: worktree-init.sh требует ровно 3 аргумента. Использование: ./scripts/worktree-init.sh <step_id> <phase> <subagent_id> Пример: ./scripts/worktree-init.sh 1.6 CODE_REVIEW security-agent EOF exit 1 fi STEP_ID="$1" PHASE="$2" SUBAGENT_ID="$3" # Валидация формата step_id (упрощённая: digits.digits) if ! [[ "$STEP_ID" =~ ^[0-9]+\.[0-9]+[a-z]?$ ]]; then echo "ОШИБКА: step_id '$STEP_ID' не соответствует формату X.Y (или X.Ya)" >&2 exit 1 fi # Валидация subagent_id (только lowercase буквы, цифры, дефисы) if ! [[ "$SUBAGENT_ID" =~ ^[a-z0-9][a-z0-9-]*$ ]]; then echo "ОШИБКА: subagent_id '$SUBAGENT_ID' должен быть lowercase, начинаться с буквы/цифры" >&2 exit 1 fi # ----------------------------------------------------------------------------- # 3. Проверка eligible phase # ----------------------------------------------------------------------------- if ! echo " $ELIGIBLE_PHASES " | grep -q " $PHASE "; then cat >&2 <<EOF ОШИБКА: phase '$PHASE' не eligible для parallel execution. parallel_eligible_phases: $ELIGIBLE_PHASES parallel_forbidden_phases: TASK_LIST PREFLIGHT PHASE1 IMPLEMENTATION PHASE2A PHASE2B FINALIZATION См. _meta/rules-constants.yaml → parallel_config и .agent/rules/18-parallel-subagents.md. EOF log_guardrail "REJECT phase=$PHASE not_eligible step=$STEP_ID subagent=$SUBAGENT_ID" exit 2 fi # ----------------------------------------------------------------------------- # 4. Пути к worktree # ----------------------------------------------------------------------------- WORKTREE_PATH="$WORKTREE_BASE/$STEP_ID/$PHASE/$SUBAGENT_ID" BRANCH_NAME="worktree/$STEP_ID/$PHASE/$SUBAGENT_ID" # Проверка: worktree уже существует? if [ -d "$WORKTREE_PATH" ]; then echo "ОШИБКА: worktree уже существует: $WORKTREE_PATH" >&2 echo "Если это перезапуск — сначала удалите: rm -rf $WORKTREE_PATH && git worktree prune" >&2 log_guardrail "REJECT worktree_exists path=$WORKTREE_PATH" exit 3 fi # Проверка: ветка уже существует? if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME" 2>/dev/null; then echo "ОШИБКА: ветка '$BRANCH_NAME' уже существует. Удалите: git branch -D $BRANCH_NAME" >&2 log_guardrail "REJECT branch_exists branch=$BRANCH_NAME" exit 3 fi # ----------------------------------------------------------------------------- # 5. Создание worktree # ----------------------------------------------------------------------------- mkdir -p "$(dirname "$WORKTREE_PATH")" log_subagent "START step=$STEP_ID phase=$PHASE subagent=$SUBAGENT_ID branch=$BRANCH_NAME" cd "$REPO_ROOT" if ! git worktree add "$WORKTREE_PATH" -b "$BRANCH_NAME" 2>/tmp/wt-init.err; then echo "ОШИБКА: git worktree add упал:" >&2 cat /tmp/wt-init.err >&2 log_guardrail "FAIL worktree_add step=$STEP_ID subagent=$SUBAGENT_ID error=$(cat /tmp/wt-init.err | tr '\n' ' ')" rm -f /tmp/wt-init.err exit 4 fi rm -f /tmp/wt-init.err log_action "WORKTREE_CREATED path=$WORKTREE_PATH branch=$BRANCH_NAME" # ----------------------------------------------------------------------------- # 6. Копирование .env (если есть) # ----------------------------------------------------------------------------- if [ -f "$REPO_ROOT/.env" ]; then if cp "$REPO_ROOT/.env" "$WORKTREE_PATH/.env" 2>/dev/null; then log_subagent "ENV_COPIED step=$STEP_ID subagent=$SUBAGENT_ID" else echo "ПРЕДУПРЕЖДЕНИЕ: не удалось скопировать .env в worktree" >&2 fi fi # ----------------------------------------------------------------------------- # 7. Setup окружения (pnpm install, pip install -e .) # Non-fatal: warning, но worktree уже создан # ----------------------------------------------------------------------------- cd "$WORKTREE_PATH" # pnpm install — только если package.json существует if [ -f "package.json" ]; then if command -v pnpm >/dev/null 2>&1; then if pnpm install --frozen-lockfile >/tmp/wt-setup-pnpm.log 2>&1; then log_subagent "SETUP_PNPM_OK step=$STEP_ID subagent=$SUBAGENT_ID" else echo "ПРЕДУПРЕЖДЕНИЕ: pnpm install упал (non-fatal). См. /tmp/wt-setup-pnpm.log" >&2 log_guardrail "WARN pnpm_install_failed step=$STEP_ID subagent=$SUBAGENT_ID" fi else echo "ПРЕДУПРЕЖДЕНИЕ: pnpm не установлен, пропускаю pnpm install" >&2 fi fi # pip install -e . — только если pyproject.toml существует if [ -f "pyproject.toml" ]; then if command -v pip >/dev/null 2>&1 || command -v uv >/dev/null 2>&1; then if command -v uv >/dev/null 2>&1; then SETUP_CMD="uv pip install -e ." else SETUP_CMD="pip install -e ." fi if $SETUP_CMD >/tmp/wt-setup-pip.log 2>&1; then log_subagent "SETUP_PIP_OK step=$STEP_ID subagent=$SUBAGENT_ID cmd=$SETUP_CMD" else echo "ПРЕДУПРЕЖДЕНИЕ: $SETUP_CMD упал (non-fatal). См. /tmp/wt-setup-pip.log" >&2 log_guardrail "WARN pip_install_failed step=$STEP_ID subagent=$SUBAGENT_ID cmd=$SETUP_CMD" fi else echo "ПРЕДУПРЕЖДЕНИЕ: pip/uv не установлен, пропускаю pip install -e ." >&2 fi fi # ----------------------------------------------------------------------------- # 8. Финал: вывести путь к worktree + лог # ----------------------------------------------------------------------------- log_subagent "FINISH step=$STEP_ID phase=$PHASE subagent=$SUBAGENT_ID path=$WORKTREE_PATH" # Вывод в stdout — для использования sub-agent'ом echo "$WORKTREE_PATH" exit 0