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
This commit is contained in:
parent
ed5d1f9014
commit
6744d40fb8
@ -28,7 +28,7 @@
|
||||
settings.json как сейчас (хуки workspace, разрешения)
|
||||
roles/<r>.md проектный слой ролей (dev — файл; admin/analyst/qa — симлинки в репозитории направлений)
|
||||
agents/<name>.md симлинки на агентов из репозиториев направлений
|
||||
agent-memory/<name>/ симлинки на память агентов в репозиториях направлений
|
||||
agent-memory/<name>/ симлинки на память агентов (не работает, см. раздел 11)
|
||||
<code repos>/ роль dev
|
||||
docs/ витрина: контекст, модель, контракты, гайды, инструкции. Читают все, пишут через PR
|
||||
admin/ → arm-ka-admin кухня admin: Jira, Гант, спринты, документы заказчику, notes/, .claude/
|
||||
@ -47,7 +47,7 @@
|
||||
.claude/role имя роли по умолчанию (одна строка) — для будущего режима запуска из репозитория
|
||||
.claude/roles/<r>.md проектный слой роли
|
||||
.claude/agents/<name>.md агенты роли
|
||||
.claude/agent-memory/<name>/MEMORY.md память агентов (коммитится)
|
||||
.claude/agent-memory/<name>/MEMORY.md память агентов (коммитится; см. раздел 11: симлинк не работает, применяется запасной вариант)
|
||||
notes/ уроки, решения владельца, рецепты роли (markdown, коммитится)
|
||||
<рабочие каталоги>
|
||||
```
|
||||
@ -183,7 +183,7 @@ SDD-контроллер и implementer-ы остаются описанием
|
||||
### 6.5 Память агентов через симлинк
|
||||
|
||||
`memory: project` пишет в `<cwd-проект>/.claude/agent-memory/<name>/`. Чтобы память оказалась в git репозитория направления,
|
||||
`<workspace>/.claude/agent-memory/<name>` — симлинк в `<dir>/.claude/agent-memory/<name>`. Проверяется первой (раздел 9).
|
||||
`<workspace>/.claude/agent-memory/<name>` — симлинк в `<dir>/.claude/agent-memory/<name>`. Проверяется первой (раздел 9). (см. раздел 11: симлинк не работает; применяется запасной вариант)
|
||||
Запасной вариант: поле `memory` не используется, промпт агента велит читать `<dir>/notes/agent-memory.md` при старте и дописывать в конце.
|
||||
|
||||
## 7. Память
|
||||
@ -233,7 +233,7 @@ SDD-контроллер и implementer-ы остаются описанием
|
||||
| `skills/role/SKILL.md` | новый, раздел 5 |
|
||||
| `agents/briefing.md` | новый, 6.1 |
|
||||
| `hooks/role-hint.sh` + `hooks/settings.hooks.json` | новый SessionStart-хук; слияние блока в install.sh как у harness-check |
|
||||
| `link-roles.sh` | новый: по таблице репозиториев в `CLAUDE.md` workspace (или по аргументам) создаёт симлинки `.claude/roles`, `.claude/agents`, `.claude/agent-memory`; идемпотентно; печатает, что сделано |
|
||||
| `link-roles.sh` | новый: по таблице репозиториев в `CLAUDE.md` workspace (или по аргументам) создаёт симлинки `.claude/roles`, `.claude/agents` (и `.claude/agent-memory`, см. раздел 11: симлинк не работает, в реализации не создаётся); идемпотентно; печатает, что сделано |
|
||||
| `install.sh` | ставит `roles/`, `skills/role`, `agents/briefing.md`, `hooks/role-hint.sh`, `link-roles.sh` в `~/.claude/harness/`; `--check` проверяет их наличие |
|
||||
| `project-template/` | `.claude/roles/*.md` заготовки; `role-repo/` шаблон репозитория направления (CLAUDE.md, `.claude/role`, `notes/README.md`) |
|
||||
| `adopt-project.sh` / `new-project.sh` | режим `--workspace`: создать `CLAUDE.md` workspace, `.claude/roles/`, вызвать `link-roles.sh`; существующий режим не меняется |
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# claude-harness: симлинки из <workspace>/.claude/ в репозитории направлений (роли, агенты, память агентов).
|
||||
# claude-harness: симлинки из <workspace>/.claude/ в репозитории направлений (роли и агенты; память агентов симлинком не работает, спека раздел 11).
|
||||
# Запуск: bash link-roles.sh [workspace] [--map <dir>=<role> ...]
|
||||
# Источник пар «каталог → роль»: таблица | Каталог | Репозиторий | Роль | в <workspace>/CLAUDE.md (роли admin|analyst|qa)
|
||||
# и/или пары --map. Идемпотентно. Обычные файлы на месте ссылок не трогает (ПРОПУЩЕН).
|
||||
@ -7,7 +7,7 @@ set -euo pipefail
|
||||
WS="."; MAPS=()
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--map) MAPS+=("$2"); shift 2 ;;
|
||||
--map) [ $# -ge 2 ] || { echo "link-roles: --map требует <dir>=<role>" >&2; exit 2; }; MAPS+=("$2"); shift 2 ;;
|
||||
*) WS="$1"; shift ;;
|
||||
esac
|
||||
done
|
||||
@ -29,7 +29,7 @@ PY
|
||||
fi
|
||||
pairs+=("${MAPS[@]+"${MAPS[@]}"}")
|
||||
[ ${#pairs[@]} -gt 0 ] || { echo "link-roles: нет пар каталог=роль (таблица в CLAUDE.md или --map)"; exit 0; }
|
||||
mkdir -p .claude/roles .claude/agents .claude/agent-memory
|
||||
mkdir -p .claude/roles .claude/agents
|
||||
|
||||
link() { # $1 = путь ссылки (относительно WS), $2 = цель (относительно каталога ссылки)
|
||||
local l="$1" t="$2"
|
||||
@ -55,7 +55,5 @@ for p in "${pairs[@]}"; do
|
||||
[ -f "$a" ] || continue
|
||||
n=$(basename "$a" .md)
|
||||
link ".claude/agents/$n.md" "../../$d/.claude/agents/$n.md"
|
||||
mkdir -p "$d/.claude/agent-memory/$n"
|
||||
link ".claude/agent-memory/$n" "../../$d/.claude/agent-memory/$n"
|
||||
done
|
||||
done
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# {{DIR}} — репозиторий направления {{ROLE}}
|
||||
|
||||
Кухня роли `{{ROLE}}` проекта {{PROJECT_NAME}}: рабочие материалы, `notes/` (уроки, решения владельца, рецепты),
|
||||
`.claude/roles/{{ROLE}}.md` (проектный слой роли), `.claude/agents/` (агенты роли), `.claude/agent-memory/` (их память, коммитится).
|
||||
`.claude/roles/{{ROLE}}.md` (проектный слой роли), `.claude/agents/` (агенты роли), память агентов — `notes/agent-memory.md` (спека 6.5; коммитится).
|
||||
Сессии запускаются из корня workspace; этот файл загружается при чтении файлов отсюда. Публикация в витрину `docs/` — через PR.
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
{{Одним абзацем: что за проект, для кого, что сейчас делается.}}
|
||||
|
||||
## Репозитории
|
||||
Сессии запускаются из этого каталога. Роль сессии выбирается через `/role <r>` (подсказка хука по заголовку сессии `claude -n "<роль> …"`); правила роли — в `~/.claude/roles/<r>.md` (общие) и `.claude/roles/<r>.md` (проектные). Ссылки на проектные файлы ролей, агентов и их память создаёт `~/.claude/harness/link-roles.sh` по этой таблице.
|
||||
Сессии запускаются из этого каталога. Роль сессии выбирается через `/role <r>` (подсказка хука по заголовку сессии `claude -n "<роль> …"`); правила роли — в `~/.claude/roles/<r>.md` (общие) и `.claude/roles/<r>.md` (проектные). Ссылки на проектные файлы ролей и агентов создаёт `~/.claude/harness/link-roles.sh` по этой таблице.
|
||||
|
||||
| Каталог | Репозиторий | Роль |
|
||||
|---|---|---|
|
||||
|
||||
@ -90,7 +90,7 @@ elif [ -f "$DIR/CLAUDE.md" ] && grep -q '^| Каталог | Репозитор
|
||||
ws=$(cd "$DIR" && pwd)
|
||||
info "workspace (не git): $ws"
|
||||
n=$(wc -c < "$ws/CLAUDE.md" | tr -d ' '); [ "$n" -le 5120 ] && ok "CLAUDE.md workspace $n Б (≤ 5 КБ)" || warn "CLAUDE.md workspace $n Б > 5 КБ"
|
||||
for kind in roles agents agent-memory; do
|
||||
for kind in roles agents; do
|
||||
for l in "$ws/.claude/$kind"/*; do
|
||||
[ -e "$l" ] || [ -L "$l" ] || continue
|
||||
name="$kind/$(basename "$l")"
|
||||
|
||||
@ -22,8 +22,7 @@ assert_symlink "roles/admin.md → admin/" "$W/.claude/roles/admin.md"
|
||||
assert_symlink "roles/qa.md → qa/ (без завершающего /)" "$W/.claude/roles/qa.md"
|
||||
assert_eq "roles/admin.md относительный" "$(readlink "$W/.claude/roles/admin.md")" "../../admin/.claude/roles/admin.md"
|
||||
assert_symlink "agents/jira-admin.md" "$W/.claude/agents/jira-admin.md"
|
||||
assert_symlink "agent-memory/jira-admin" "$W/.claude/agent-memory/jira-admin"
|
||||
assert_file "целевой каталог памяти создан" "$W/admin/.claude/agent-memory/jira-admin"
|
||||
assert_eq "agent-memory не создаётся (спека, раздел 11)" "$([ -e "$W/.claude/agent-memory" ] || [ -e "$W/admin/.claude/agent-memory" ] && echo есть || echo нет)" "нет"
|
||||
assert_eq "dev не линкуется" "$(ls "$W/.claude/roles" | grep -c dev)" "0"
|
||||
assert_eq "docs/source пропущены" "$(ls "$W/.claude/roles" | wc -l | tr -d ' ')" "2"
|
||||
assert_grep "печатает 'создан'" 'создан' <(printf '%s' "$out")
|
||||
@ -31,18 +30,12 @@ out2=$(bash "$L" "$W" 2>&1); rc=$?
|
||||
assert_eq "второй запуск: exit 0" "$rc" "0"
|
||||
assert_eq "второй запуск: ничего не создано" "$(printf '%s' "$out2" | grep -c 'создан')" "0"
|
||||
assert_grep "второй запуск: 'есть'" 'есть' <(printf '%s' "$out2")
|
||||
assert_eq "второй запуск: ссылка прежняя" "$(readlink "$W/.claude/agent-memory/jira-admin")" "../../admin/.claude/agent-memory/jira-admin"
|
||||
assert_eq "второй запуск: ссылка прежняя" "$(readlink "$W/.claude/agents/jira-admin.md")" "../../admin/.claude/agents/jira-admin.md"
|
||||
# чужой обычный файл на месте ссылки не затирается
|
||||
rm "$W/.claude/roles/qa.md"; echo 'мой файл' > "$W/.claude/roles/qa.md"
|
||||
out3=$(bash "$L" "$W" 2>&1)
|
||||
assert_eq "обычный файл сохранён" "$(cat "$W/.claude/roles/qa.md")" "мой файл"
|
||||
assert_grep "обычный файл → ПРОПУЩЕН" 'ПРОПУЩЕН' <(printf '%s' "$out3")
|
||||
# обычный каталог на месте ссылки памяти тоже не затирается
|
||||
rm "$W/.claude/agent-memory/jira-admin"; mkdir "$W/.claude/agent-memory/jira-admin"
|
||||
out5=$(bash "$L" "$W" 2>&1); rc=$?
|
||||
assert_eq "каталог на месте ссылки: exit 0" "$rc" "0"
|
||||
assert_eq "каталог на месте ссылки: не симлинк" "$([ -L "$W/.claude/agent-memory/jira-admin" ] && echo link || echo dir)" "dir"
|
||||
assert_grep "каталог на месте ссылки → ПРОПУЩЕН" 'ПРОПУЩЕН' <(printf '%s' "$out5")
|
||||
# --map без CLAUDE.md
|
||||
W2="$TMP/ws2"; mkdir -p "$W2/an/.claude/roles"; echo x > "$W2/an/.claude/roles/analyst.md"
|
||||
bash "$L" "$W2" --map an=analyst >/dev/null 2>&1
|
||||
@ -56,3 +49,8 @@ assert_grep "нет файла роли: WARN" 'WARN' <(printf '%s' "$out4")
|
||||
# CLAUDE.md без таблицы и без --map: не падает
|
||||
W4="$TMP/ws4"; mkdir -p "$W4"; echo '# пусто' > "$W4/CLAUDE.md"
|
||||
bash "$L" "$W4" >/dev/null 2>&1; assert_eq "нет пар: exit 0" "$?" "0"
|
||||
# --map без значения: русская ошибка и exit 2
|
||||
W5="$TMP/ws5"; mkdir -p "$W5"
|
||||
err=$(bash "$L" "$W5" --map 2>&1 >/dev/null); rc=$?
|
||||
assert_eq "--map без значения: exit 2" "$rc" "2"
|
||||
assert_grep "--map без значения: сообщение" 'link-roles: --map требует <dir>=<role>' <(printf '%s' "$err")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user