claude-harness/link-roles.sh
Andrey Epifancev 6744d40fb8 fix: согласовать шаблоны и link-roles со спайком памяти агентов
link-roles.sh больше не создаёт симлинки agent-memory (спека, раздел 11:
симлинк делает память read-only), doctor не проверяет их; шаблоны
workspace и role-repo описывают запасной вариант 6.5 (notes/agent-memory.md).
В спеке разделы 2, 6.5, 8 получили указатель на раздел 11. Заодно --map
без значения даёт русскую ошибку и exit 2.

Refs #2

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MzkPQWjfA7RpqYWkjnqJwt
2026-10-12 00:47:47 +04:00

60 lines
2.6 KiB
Bash
Executable File
Raw Permalink 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.

#!/usr/bin/env bash
# claude-harness: симлинки из <workspace>/.claude/ в репозитории направлений (роли и агенты; память агентов симлинком не работает, спека раздел 11).
# Запуск: bash link-roles.sh [workspace] [--map <dir>=<role> ...]
# Источник пар «каталог → роль»: таблица | Каталог | Репозиторий | Роль | в <workspace>/CLAUDE.md (роли admin|analyst|qa)
# и/или пары --map. Идемпотентно. Обычные файлы на месте ссылок не трогает (ПРОПУЩЕН).
set -euo pipefail
WS="."; MAPS=()
while [ $# -gt 0 ]; do
case "$1" in
--map) [ $# -ge 2 ] || { echo "link-roles: --map требует <dir>=<role>" >&2; exit 2; }; MAPS+=("$2"); shift 2 ;;
*) WS="$1"; shift ;;
esac
done
cd "$WS"; WS="$(pwd)"
pairs=()
if [ -f CLAUDE.md ]; then
while IFS= read -r line; do pairs+=("$line"); done < <(
python3 - CLAUDE.md <<'PY'
import sys
for line in open(sys.argv[1], encoding="utf-8"):
if not line.startswith("|"): continue
cells = [c.strip() for c in line.strip().strip("|").split("|")]
if len(cells) < 3: continue
d, role = cells[0].rstrip("/"), cells[2]
if role in ("admin", "analyst", "qa") and d and not d.startswith("-"):
print(f"{d}={role}")
PY
)
fi
pairs+=("${MAPS[@]+"${MAPS[@]}"}")
[ ${#pairs[@]} -gt 0 ] || { echo "link-roles: нет пар каталог=роль (таблица в CLAUDE.md или --map)"; exit 0; }
mkdir -p .claude/roles .claude/agents
link() { # $1 = путь ссылки (относительно WS), $2 = цель (относительно каталога ссылки)
local l="$1" t="$2"
if [ -L "$l" ]; then
if [ "$(readlink "$l")" = "$t" ]; then echo " есть $l"; return 0; fi
rm "$l"
elif [ -e "$l" ]; then
echo " ПРОПУЩЕН $l — обычный файл/каталог, не симлинк; убери его вручную, если нужна ссылка"; return 0
fi
ln -s "$t" "$l"; echo " создан $l → $t"
}
for p in "${pairs[@]}"; do
d=${p%%=*}; r=${p#*=}; d=${d%/}
echo "$d ($r)"
[ -d "$d" ] || { echo " WARN каталог $d не найден"; continue; }
if [ -f "$d/.claude/roles/$r.md" ]; then
link ".claude/roles/$r.md" "../../$d/.claude/roles/$r.md"
else
echo " WARN нет $d/.claude/roles/$r.md — проектный файл роли не слинкован"
fi
for a in "$d"/.claude/agents/*.md; do
[ -f "$a" ] || continue
n=$(basename "$a" .md)
link ".claude/agents/$n.md" "../../$d/.claude/agents/$n.md"
done
done