Аудит настройки агентов: инструкции, которые были неверны или не соблюдались
Кратко
В репозитории aredel была настройка ИИ-ассистентов, собранная по руководствам этого раздела: AGENTS.md из трёх строк, шесть навыков и три агента OpenCode на трёх моделях. Выглядело законченно. Аудит 2026-10-22 сравнил файлы с тем, что инструменты действительно загружают, и выяснил, что большая часть не работает так, как написано. Часть причины была в руководствах, часть — в том, что репозиторий им не следовал. Эта страница перечисляет и то и другое, исправление и каждый шаг аудита с командой, чтобы аудит можно было повторить на этом или любом другом репозитории.
| Находка | Причина | Эффект |
|---|---|---|
| Модель по умолчанию и модель triage привязаны к снятому id | примеры в руководстве не обновили | агент откатывается к модели сессии или не запускается |
| Builder не может загрузить aredel-map, который AGENTS.md велит читать перед любой правкой PHP | пример ограничения навыков из руководства | роль, которая правит PHP, не может загрузить правила PHP |
| Reviewer без shell, которому велено смотреть подготовленный diff | пример ограничения навыков из руководства | reviewer не видит diff, который судит |
| Пять файлов навыков с отказами YAML во frontmatter | примеры в руководстве | строгие парсеры молча отбрасывают навык |
| Навыки только в .opencode/skills/ | репозиторий не следовал более новому руководству | в Claude Code не загружается ни один навык aredel |
| Builder заранее получил только npm test | скопирован общий пример | каждая настоящая проверка просит подтверждения |
| 36 ссылок на переехавшие якоря | страницу разделили без проверки ссылок | читатель попадает в начало не той страницы |
Настройка до аудита
Файлы в том виде, в каком они были закоммичены до 2026-10-22:
aredel/ ├── AGENTS.md three lines, @skill references ├── opencode.jsonc model, permissions, three inline agents ├── .opencode/skills/ │ ├── aredel-map.md │ ├── aredel-page/SKILL.md │ ├── aredel-blocks/SKILL.md │ ├── aredel-css.md hidden: opencode/autoinvoke false │ └── aredel-verify.md └── container/src/ai/.opencode/skills/ └── ai-style.md inside the docroot
Корневые инструкции полностью:
# Project instructions - Read @aredel-map before touching container/src PHP files. - Page work: @aredel-page plus @aredel-blocks. CSS: @aredel-css by hand. - Finish with @aredel-verify, then regenerate sitemap.
Что OpenCode разрешил для трёх ролей, по выводу opencode debug agents (шаг 2 ниже), правила после глобальных:
builder gpt-6-luna shell npm test * allow shell git status * allow shell git diff * allow skill * deny skill aredel-page allow skill aredel-blocks allow skill aredel-verify allow skill ai-style allow reviewer claude-opus-5-5 edit * deny shell * deny skill * deny skill aredel-verify allow triage muse-spark-1.3-contributor-free edit * deny shell * deny skill * deny skill aredel-map allow
Инструкции, которые были неверны
Они пришли из руководств. Каждая находка показывает точные строки до и после исправления, с файлом и коммитом, откуда они взяты.
1. Снятый с учёта id модели как ежедневный выбор по умолчанию. Пять примеров конфигурации в OpenCode и один в Muse Spark 1.3 закрепляли opencode/muse-spark-1.3-contributor-free, хотя раздел «Заставить агентов работать» уже называл этот id снятым. Репозиторий последовал примерам. Исправлено: актуальный id и его запасные варианты теперь на одной странице, «Бесплатная модель OpenCode»; остальные страницы ссылаются туда.
До, opencode.jsonc в коммите 3f4dc9e2, строка 3 и строки 31–35:
"model": "opencode/muse-spark-1.3-contributor-free", … "agents": { "triage": { "description": "Explains aredel code and routes tasks without editing", "mode": "primary", "model": "opencode/muse-spark-1.3-contributor-free",
После, opencode.jsonc строка 11:
"model": "opencode/deepseek-v4.1-flash-free",
После, .opencode/agents/triage.md строка 4:
model: opencode/deepseek-v4.1-flash-free
2. Бесплатный уровень для участников как выбор по умолчанию для любой задачи. То же руководство говорило никогда не отправлять туда приватный код, но единственные правила чтения закрывали лишь .env и файлы учётных данных. Исправлено: бесплатная модель — выбор по умолчанию для публичного кода, а секретные файлы запрещены всем ролям, как в «Правилах запретов».
До, opencode.jsonc в коммите 3f4dc9e2, строки 20–29, единственные правила чтения:
{ "action": "read", "resource": "*.env", "effect": "deny" }, { "action": "read", "resource": "*creds*", "effect": "deny" }
После, opencode.jsonc строки 63–77, добавлены три правила чтения; у каждого есть такой же двойник для правки:
{ "action": "read", "resource": "*analyze_logs/site_logs/*", "effect": "deny" }, { "action": "read", "resource": "*services/user_profile/data/*", "effect": "deny" }, { "action": "read", "resource": "~/.config/aredel/*", "effect": "deny" },
3. Ограничение, которое спрятало правила от роли, которой они нужны. Пример с ролями разрешал triage загружать только aredel-map и не давал его builder — единственной роли, которая правит PHP. Исправлено: builder и reviewer видят все навыки aredel; урезан только triage.
До, opencode.jsonc в коммите 3f4dc9e2, строки 80–104, правила навыков для builder; aredel-map отсутствует:
{ "action": "skill", "resource": "*", "effect": "deny" }, { "action": "skill", "resource": "aredel-page", "effect": "allow" }, { "action": "skill", "resource": "aredel-blocks", "effect": "allow" }, { "action": "skill", "resource": "aredel-verify", "effect": "allow" }, { "action": "skill", "resource": "ai-style", "effect": "allow" }
После, .opencode/agents/builder.md строки 1–5; дальше идут только правила shell, поэтому ни один навык не запрещён:
--- description: Implements aredel page, CSS and tooling changes and runs the checks mode: primary model: opencode/gpt-6-luna permissions:
4. Reviewer, которому велено читать подготовленный diff, а shell запрещён. Исправлено: reviewer может запускать git diff, git show, git log и git status, и ничего больше, а команда /review передаёт ему diff.
До, opencode.jsonc в коммите 3f4dc9e2, строки 112–133, права reviewer:
"permissions": [ { "action": "edit", "resource": "*", "effect": "deny" }, { "action": "shell", "resource": "*", "effect": "deny" }, { "action": "skill", "resource": "*", "effect": "deny" }, { "action": "skill", "resource": "aredel-verify", "effect": "allow" } ]
После, .opencode/agents/reviewer.md строки 6–24:
permissions: - action: edit resource: "*" effect: deny - action: shell resource: "*" effect: deny - action: shell resource: "git diff *" effect: allow - action: shell resource: "git show *" effect: allow - action: shell resource: "git log *" effect: allow - action: shell resource: "git status *" effect: allow
После, .opencode/commands/review.md:
--- description: Review the staged diff on the reviewer agent agent: reviewer subagent: true --- Review this staged diff against the aredel skills for the touched paths. Findings in severity order with file and line, then a verdict. !`git diff --cached`
5. Frontmatter, который YAML отвергает. В примерах писали name: Git Release и description: Aredel: decide …. Первое не годится как имя агентского навыка, второе — вообще не корректный YAML (шаг 5). Исправлено в «Анатомии хорошего навыка»: name совпадает с id в kebab-case, значения с двоеточием берутся в кавычки.
До, .opencode/skills/aredel-map.md в коммите 3f4dc9e2, строки 1–4:
--- name: Aredel Map description: Aredel: decide page versus include before editing any PHP file ---
Парсер на таком frontmatter:
yaml.scanner.ScannerError: mapping values are not allowed here
После, .claude/skills/aredel-map/SKILL.md строки 1–4:
--- name: aredel-map description: "Aredel: decide page versus include before editing or creating any PHP file under container/src/" ---
6. Два разных «рекомендованных» места для навыков. «Куда класть навыки» советовал .opencode/skills/; «Общие навыки, раздельные агенты» советовал .claude/skills/ для репозиториев, где есть и Claude Code. Исправлено: общее место идёт первым.
До, файлы навыков в коммите 3f4dc9e2:
.opencode/skills/aredel-blocks/SKILL.md .opencode/skills/aredel-blocks/references/block-classes.md .opencode/skills/aredel-css.md .opencode/skills/aredel-map.md .opencode/skills/aredel-page/SKILL.md .opencode/skills/aredel-page/references/page-checklist.md .opencode/skills/aredel-verify.md container/src/ai/.opencode/skills/ai-style.md
После, файлы навыков в репозитории:
.claude/skills/ai-style/SKILL.md .claude/skills/aredel-blocks/SKILL.md .claude/skills/aredel-blocks/references/block-classes.md .claude/skills/aredel-css/SKILL.md .claude/skills/aredel-map/SKILL.md .claude/skills/aredel-page/SKILL.md .claude/skills/aredel-page/references/page-checklist.md .claude/skills/aredel-tooling/SKILL.md .claude/skills/aredel-verify/SKILL.md
7. Навык внутри docroot. Вложенное переопределение ai-style лежало в container/src/ai/.opencode/, а деплой по FTP не исключает .opencode, поэтому полная выгрузка его публиковала. Исправлено: все навыки лежат в корне репозитория.
Исключения деплоя, container/tools/deploy/deploy-ftp.sh строки 472–477; .opencode в списке нет:
BASE_EXCLUDE_DIRS = {"reports", "allure-results", "allure-results-host", "__pycache__", ".pytest_cache", ".git", # NOTE: no "venv" here on purpose — the only venv/ dirs in # src/ are article sections (dev/python/ve/venv and twins); # real virtualenvs live in ".venv", still excluded above. ".venv", "node_modules"}
После, .claude/skills/ai-style/SKILL.md строки 1–4, вне docroot:
--- name: ai-style description: "Aredel: AI articles under container/src/ai/ only: model names and prices, free-model links, cross-links between the agent guides" ---
8. Скрытый навык как хорошая практика. aredel-css был скрыт через opencode/autoinvoke: false, поэтому при работе с CSS ни одна роль его не получала. Исправлено: каждый навык объявлен.
До, .opencode/skills/aredel-css.md в коммите 3f4dc9e2, строки 1–6:
--- name: Aredel CSS description: Aredel: add a new code class in _codeblocks.css, then build metadata: opencode/autoinvoke: false ---
После, .claude/skills/aredel-css/SKILL.md строки 1–4:
--- name: aredel-css description: "Aredel: CSS changes: code-block classes in source/_codeblocks.css, site overrides, building the served sheets with build-css.sh" ---
9. Устаревшие тела навыков. Опубликованное тело aredel-css описывало ручную синхронизацию минифицированных копий, которую конвейер сборки CSS заменил 2026-10-19, а AGENTS.md велел пересобирать sitemap после каждой задачи, тогда как навык проверки — только после добавления или удаления страницы. Исправлено: тела на «Карте проекта aredel» скопированы из файлов репозитория.
До, тело, опубликованное на странице навыков, container/src/ai/skills/index.php в коммите 5a728aa8:
name: Aredel CSS description: Aredel: sync a new code class from to_build to ao.css and aredel.css metadata: opencode/autoinvoke: false --- ## Workflow 1. Clone the sibling block in to_build/_blockquotes.css, rename class, label, header colors, append at EOF. 2. Mirror the identical minified line into ao.css and aredel.css, keep trailing newline. 3. Verify grep -o counts match sibling classes and render one page with the class.
После, .claude/skills/aredel-css/SKILL.md строки 9–19:
## Workflow 1. New code class: clone the nearest sibling language block in `container/src/.css/source/_codeblocks.css` (`.phpcode`, `.pycode`, `.somecode`, …), rename the class, label and header colors. Keep the HTML class casing (`.incFr13`, not `.incfr13`). 2. Add the class to the table in `container/docs/articles.md` and to `CODE_CLASSES` in `container/tests/test_css_sources.py`. 3. Build from `container/`: `tools/css/build-css.sh`; gate with `tools/css/build-css.sh --check`. Never edit `.css/output/*.css`; language classes live in `source/_codeblocks.css`, which is a core input, so do not copy them into the layout partials or a site file.
До, AGENTS.md в коммите 3f4dc9e2, строка 4:
- Finish with @aredel-verify, then regenerate sitemap.
После, AGENTS.md строки 30–31:
- Regenerate the sitemap (`cd container && ./tools/generate-sitemap.sh`) only after adding or removing pages.
10. 36 ссылок на переехавшие якоря. Восемь страниц ссылались на /ai/agents/#ex-triage и подобные якоря после того, как примеры OpenCode переехали в «Агенты OpenCode». Исправлено, и проверка ссылок из шага 4 теперь идёт при каждом аудите.
До, container/src/ai/opencode/index.php в коммите 5a728aa8, строка 356:
│ ├── <a href="/ai/agents/#ex-triage">triage.md</a>
После, тот же файл, строка 345:
│ ├── <a href="/ai/opencode/agents/#ex-triage">triage.md</a>
Инструкции, которые не соблюдались
Эти руководства были правы; репозиторий не делал того, что в них сказано.
1. «Добейтесь, чтобы каждый id модели разрешался» («Агенты OpenCode»). Репозиторий оставил снятый id для модели по умолчанию и для triage; строки — в находке 1. Исправлено: лаунчер проверяет каждый закреплённый id перед запуском OpenCode и откатывается по этому списку.
После, container/tools/ai/free-models.txt строки 9–13:
deepseek-v4.1-flash-free glm-5.3-flash-free minimax-m3.1-flash-free mimo-v2.6-flash-free nemotron-3.5-lightning-free
2. «Пишите навыки один раз в .claude/skills/» («Создание ИИ-агентов»). Репозиторий держал их в .opencode/skills/, поэтому сессиям Claude Code в этом репозитории было нечего загружать. Списки файлов до и после — в находке 6.
3. Агенты как файлы в .opencode/agents/. В деревьях руководства были triage.md, builder.md и reviewer.md; репозиторий держал агентов прямо в opencode.jsonc и вовсе не имел ролей Claude Code.
До, opencode.jsonc в коммите 3f4dc9e2, строки 31–36:
"agents": { "triage": { "description": "Explains aredel code and routes tasks without editing", "mode": "primary", "model": "opencode/muse-spark-1.3-contributor-free", "steps": 6,
После, файлы ролей в репозитории:
.claude/agents/builder.md .claude/agents/reviewer.md .claude/agents/triage.md .opencode/agents/builder.md .opencode/agents/reviewer.md .opencode/agents/triage.md .opencode/commands/review.md
После, .opencode/agents/triage.md строки 1–5:
--- description: Explains aredel code and routes tasks without editing mode: primary model: opencode/deepseek-v4.1-flash-free steps: 6
4. «Дайте каждой роли канареечную задачу». Ни одна не была записана, поэтому агент triage на снятой модели остался незамеченным. Файла тут не показать: в репозитории не было ни одного результата канарейки. Теперь задачи определены в «Канареечных задачах по ролям».
5. Точные команды в навыках и allowlist. В allowlist builder остался общий npm test *; в репозитории нет package.json. Его настоящие проверки — php -l, run-tests-venv.sh и pre-commit run.
До, opencode.jsonc в коммите 3f4dc9e2, строки 64–79:
"permissions": [ { "action": "shell", "resource": "npm test *", "effect": "allow" }, { "action": "shell", "resource": "git status *", "effect": "allow" }, { "action": "shell", "resource": "git diff *", "effect": "allow" },
После, .opencode/agents/builder.md строки 5–26:
permissions: - action: shell resource: "git status *" effect: allow - action: shell resource: "git diff *" effect: allow - action: shell resource: "git log *" effect: allow - action: shell resource: "php -l *" effect: allow - action: shell resource: "pre-commit run *" effect: allow - action: shell resource: "container/tools/run-tests-venv.sh *" effect: allow - action: shell resource: "./tools/run-tests-venv.sh *" effect: allow
6. Рабочие глубокие ссылки. Два навыка указывали на ../../skill.md, а из каталога навыка этот путь ведёт к файлу, которого нет.
До, .opencode/skills/aredel-page/SKILL.md в коммите 3f4dc9e2, последние две строки:
## Deep reference Working notes on page classes and migration: ../../skill.md sections 2 and 6.
После, .claude/skills/aredel-page/SKILL.md, последние две строки:
## Deep reference Working notes on page classes and migration: skill.md at the repo root, sections 2 and 6.
7. «Процедура, которая переросла корневой файл, принадлежит навыку» — и наоборот: правила, нужные каждой задаче, остались в навыках, которые загружаются по требованию. Спрашивать перед коммитом, поднимать версию в заголовке и держать Python на 3.12 в AGENTS.md не было никогда.
До, AGENTS.md в коммите 3f4dc9e2, файл целиком:
# Project instructions - Read @aredel-map before touching container/src PHP files. - Page work: @aredel-page plus @aredel-blocks. CSS: @aredel-css by hand. - Finish with @aredel-verify, then regenerate sitemap.
После, AGENTS.md строки 20–33:
## Always - Never commit without asking: finish verification, then ask whether to commit or hand over explicit-path `git add` / `git commit` commands. Never `git add -A`, never `--no-verify` or another hook bypass, never edit ignore files to hide untracked work (details: `aredel-verify`). - Bump the `# version X.Y.Z` header of every changed versioned file. - Python stays on 3.12; declare dependencies in `pyproject.toml` and lock with uv, never `pip install` into a uv-managed `.venv`. - Keep CRLF line endings where HEAD has them. - Regenerate the sitemap (`cd container && ./tools/generate-sitemap.sh`) only after adding or removing pages. - Articles written by an assistant credit `author: ['Arthur Isaev', '/about/arthur_isaev/']`.
Исправление
Применено 2026-10-22, кроме открытых вопросов:
aredel/ ├── AGENTS.md routing table plus the rules every task needs ├── opencode.jsonc free default model, global permissions ├── .claude/skills/ seven skills, read by OpenCode and Claude Code ├── .claude/agents/ triage, builder, reviewer for Claude Code ├── .opencode/agents/ triage, builder, reviewer for OpenCode ├── .opencode/commands/review.md reviewer on the staged diff └── container/tools/ai/ ├── opencode.sh checks model ids, then starts OpenCode ├── check_opencode_models.py pinned ids against the live catalog ├── free-models.txt fallback order of free ids └── audit_agent_setup.py the static checks of this page
Роли после исправления, одинаковые имена в обоих инструментах:
| Роль | Модель OpenCode | Модель Claude Code | Навыки | Может править | Shell |
|---|---|---|---|---|---|
| triage | бесплатная модель OpenCode | haiku | aredel-map | нет | нет |
| builder | GPT 6 Luna | inherit | все | да | спрашивает; git status, diff, log, php -l, тесты и pre-commit разрешены; push запрещён |
| reviewer | Claude Opus 5.5 | opus | все | нет | только git на чтение |
Теперь AGENTS.md направляет каждую задачу к её навыкам и держит правила, нужные каждой задаче: спросить перед коммитом, поднять версию в заголовке, Python 3.12 с зависимостями, объявленными в uv, сохранять CRLF, пересобирать sitemap только после добавления или удаления страниц, правильно указывать автора статей, написанных ИИ. Его полный текст и тела всех навыков — на «Карте проекта aredel». Ничего не добавляли ради того, чтобы агентов стало больше: три роли покрывают три разных набора прав, а знание темы живёт в навыках, которые может загрузить любая роль.
Шаги аудита по порядку
Каждый шаг аудита с командой и тем, что он показал. Запускайте их из корня репозитория; шаги 4–6 работают и на любом репозитории с такой же структурой.
Шаг 1 — перечислить файлы инструкций. Всё, что ассистент читает как инструкции, включая копии в странных местах:
find . -path ./node_modules -prune -o \( -name AGENTS.md -o -name CLAUDE.md -o -name opencode.jsonc -o -path "*/.opencode/*" -o -path "*/.claude/*" \) -type f -print
Так нашёлся навык внутри docroot, container/src/ai/.opencode/skills/ai-style.md. Прочитайте каждый найденный файл и глубокие ссылки, которые он называет.
Шаг 2 — увидеть, что OpenCode действительно загружает. Фоновый сервис кеширует конфигурацию, поэтому сначала перезагрузите её, затем перечислите источники конфигурации и разрешённых агентов:
opencode reload
opencode debug config
opencode debug agents | jq -r '.[] | select(.id=="triage" or .id=="builder" or .id=="reviewer") | "\(.id) \(.model.id)"'
Без перезагрузки вторая команда продолжала показывать правила из конфигурации, которой на диске уже не было. Полный вывод, со всеми правилами прав по агентам, дал список «до» на этой странице.
Шаг 3 — проверить каждый закреплённый id модели по живому каталогу. Одна строка для бесплатных id, один скрипт для каждого закреплённого id:
curl -s https://opencode.ai/inference/v1/models | grep -o '"[a-z0-9.-]*-free"' | sort
python3 container/tools/ai/check_opencode_models.py --check
Закреплённого бесплатного id в списке не было. Скрипт читает поля моделей в opencode.jsonc и .opencode/agents/ и завершается с ненулевым кодом, если id исчез; эндпоинт отвечает 403 на стандартный User-Agent Python, поэтому скрипт отправляет свой.
Шаг 4 — запустить статический аудит. Один скрипт проверяет frontmatter, имена навыков, ссылки, глубокие ссылки и id моделей:
python3 container/tools/ai/audit_agent_setup.py
Чтобы проверить закоммиченную версию, а не рабочее дерево, выгрузите её и укажите скрипту на копию:
mkdir -p /tmp/head-setup && git archive HEAD AGENTS.md opencode.jsonc .opencode container/src/ai skill.md skill_css.md _internal_ai_skill_for_files.md container/docs container/tools | tar -x -C /tmp/head-setup
python3 container/tools/ai/audit_agent_setup.py --root /tmp/head-setup
Вывод для настройки до исправления, проверки ссылок опущены:
FAIL: frontmatter: .opencode/skills/aredel-blocks/SKILL.md:3: value contains ': '; quote it FAIL: frontmatter: .opencode/skills/aredel-page/SKILL.md:3: value contains ': '; quote it FAIL: frontmatter: .opencode/skills/aredel-css.md:3: value contains ': '; quote it FAIL: frontmatter: .opencode/skills/aredel-map.md:3: value contains ': '; quote it FAIL: frontmatter: .opencode/skills/aredel-verify.md:3: value contains ': '; quote it FAIL: skills: .opencode/skills/aredel-map.md: name 'Aredel Map' is not the id 'aredel-map' FAIL: skills: container/src/ai/.opencode/skills/ai-style.md: name 'AI Style' is not the id 'ai-style' FAIL: references: .opencode/skills/aredel-blocks/SKILL.md: ../../skill.md does not exist FAIL: references: .opencode/skills/aredel-page/SKILL.md: ../../skill.md does not exist FAIL: models: opencode/muse-spark-1.3-contributor-free is not in the live catalog (opencode.jsonc)
Ещё четыре отказа имён того же рода опущены. Проверка ссылок на страницах руководств сообщила о 36 отказах вроде /ai/opencode/: href="/ai/agents/#ex-triage" has no such anchor. После исправления:
ok: frontmatter ok: skills ok: references ok: links ok: models
Шаг 5 — подтвердить отказы YAML настоящим парсером. Скрипт аудита использует узкое правило; библиотека YAML даёт точную ошибку:
python3 -c "import sys, yaml; [print(f, yaml.safe_load(open(f).read().split('---')[1])) for f in sys.argv[1:]]" .claude/skills/*/SKILL.md
До исправления он останавливался на первом навыке с mapping values are not allowed here.
Шаг 6 — сравнить каждую роль с её работой. Положите разрешённые права из шага 2 рядом с маршрутизацией в AGENTS.md и спросите по каждой роли: может ли она загрузить все навыки, нужные её задачам, и запустить команды, которые называют её инструкции? Так нашлись builder без aredel-map и reviewer без git diff. Затем проверьте, что заранее разрешённые команды существуют в репозитории:
ls package.json container/tools/run-tests-venv.sh
Шаг 7 — найти инструкции, которые противоречат друг другу. Ищите одну тему во всех файлах инструкций и читайте найденное рядом:
grep -rn "sitemap" AGENTS.md .claude/skills skill.md
grep -rn "_blockquotes\|_codeblocks" .claude/skills skill.md skill_css.md
grep -n "ao.css" skill.md container/docs/src-study-map.md
Так нашлись правило про sitemap, изложенное двумя способами, файл источника CSS, названный двумя способами, и две разные таблицы стилей, приписанные ArticlePage. Глубокие ссылки исправлены под код.
Шаг 8 — проверить, что может прочитать агент на бесплатной модели. Перечислите чувствительные данные на диске, которые git игнорирует, но прочитать их всё ещё можно, и сравните с правилами чтения из шага 2:
git status --short --ignored | grep "^!!"
Игнорируемое git не значит скрытое от агента: решают только правила запрета чтения. См. открытые вопросы.
Шаг 9 — проверить, что конфигурация ассистентов не уезжает с сайтом. В docroot не должно быть каталогов агентов, а исключения деплоя показывают, что пропустит полная выгрузка:
find container/src -name .opencode -o -name .claude
grep -n -A6 "BASE_EXCLUDE_DIRS =" container/tools/deploy/deploy-ftp.sh
Шаг 10 — доказать обнаружение навыков в каждом инструменте. В OpenCode одноразовый репозиторий с одним пустым навыком на каждое место отвечает, какие места загружаются. До модели доходит только пустой текст:
mkdir -p /tmp/octest/.opencode/skills/a /tmp/octest/.claude/skills/c && cd /tmp/octest && git init -q
printf -- "---\nname: a\ndescription: \"Skill a\"\n---\nBody a\n" > .opencode/skills/a/SKILL.md
printf -- "---\nname: c\ndescription: \"Skill c\"\n---\nBody c\n" > .claude/skills/c/SKILL.md
opencode run --standalone --model opencode/deepseek-v4.1-flash-free "Without using any tools, list the ids of every skill you have been told you can load, one per line, then stop."
Вернулись и a, и c, вместе с глобальными навыками, значит OpenCode действительно читает .claude/skills/. Серверный эндпоинт opencode api GET /api/skill в том же каталоге вернул пустой список, поэтому он ничего не доказывает. В Claude Code семь навыков aredel появились в работающей сессии, как только оказались в .claude/skills/ (/skills их показывает); до переезда в сессии не было ни одного.
Шаг 11 — протестировать инструменты. У проверки моделей и скрипта аудита есть офлайн-тесты с поддельным каталогом и поддельным репозиторием:
cd container && ./tools/run-tests-venv.sh -- tests/tools/test_agent_setup_tools.py -q
17 passed
Шаг 12 — прогнать изменённые файлы через шлюз. Линт, проверки типов, shellcheck и правило заголовка версии идут через pre-commit:
pre-commit run --files AGENTS.md opencode.jsonc container/tools/ai/*.py container/tools/ai/opencode.sh
Шаг 13 — проверить страницы руководств. Каждая изменённая страница должна пройти линт и рендер через CLI ровно с одним маркером содержимого, новая страница должна попасть в sitemap, а локальный сайт должен отдавать каждую изменённую страницу. Линт, из корня репозитория:
php -l container/src/ai/agents/audit/index.php
Рендер через прослойку, задающую DOCUMENT_ROOT (/tmp/shim.php содержит одну строку, $_SERVER["DOCUMENT_ROOT"] = "/home/andrei/github/aredel/container/src";), и подсчёт маркера:
cd container/src && php -d auto_prepend_file=/tmp/shim.php ai/agents/audit/index.php | grep -c 'id="bottomid"'
Все 14 изменённых страниц завершились с кодом 0 и одним маркером каждая. Две страницы были добавлены, поэтому sitemap пересобран и посчитан:
cd container && ./tools/generate-sitemap.sh && grep -c "<loc>" src/sitemap.xml
4258
Было 4256. Затем тесты sitemap идут против локального сайта, ограниченные изменёнными страницами через файл путей, один URL-путь на строку, например /ai/agents/audit/. Бэкенду на хосте нужен pytest в PATH, поэтому venv контейнера идёт первым:
cd container && PATH="$PWD/.venv/bin:$PATH" tests/run_sitemap_tests.sh --host --test link,content,html-id,css,footer --paths-file /tmp/ai-pages.txt
link PASS 15 passed content PASS 15 passed engine PASS 15 passed css PASS 15 passed footer PASS 15 passed
Защита от порчи статического HTML покрывает все страницы за один прогон:
cd container && ./tools/run-tests-venv.sh -- tests/test_html_code_corruption.py tests/tools -q
Канареечные задачи по ролям
Статические проверки доказывают, что файлы загружаются; канарейка доказывает, что роль работает. Одна задача на роль, запускаемая в каждом инструменте, по одной строке pass/fail:
| Роль | Задача | Зачёт, когда |
|---|---|---|
| triage | Is src/ao/chessboard/game.php a page or a tool? | отвечает «tool» по aredel-map, ничего не правит |
| triage | Fix the footer of src/ai/index.php | направляет к builder, ничего не правит |
| builder | добавить один блок cmd1 на страницу, затем откатить | загружает aredel-blocks, запускает php -l без вопросов, показывает diff |
| reviewer | посмотреть подготовленный diff с одним подложенным багом | запускает git diff --cached, находит баг с файлом и строкой, ничего не правит |
В OpenCode запускайте через container/tools/ai/opencode.sh и выбирайте роль; в Claude Code просите субагента по имени. Затем читайте историю сессии, а не каталог: роль, которая там не появилась, не запускалась.
Правила, которые обобщаются
- Проверяйте, что загружает инструмент, а не что написано в файлах: opencode debug agents, /skills, прогон с пустым навыком.
- Проверяйте каждый закреплённый id модели по живому каталогу перед сессией, автоматически; бесплатные id меняются чаще всего.
- Роль, которая правит или судит файлы какого-то рода, должна иметь право загрузить каждый навык об этом роде файлов.
- Каждая команда, названная в инструкции, должна быть разрешена роли, которой её запускать, и должна существовать в репозитории.
- Берите в кавычки значения frontmatter с двоеточием и делайте name равным id в kebab-case.
- Одно место на факт: id модели, тело навыка или правило, скопированные на три страницы, расходятся в три стороны.
- Никакой конфигурации ассистентов внутри каталога, который деплоится.
- Правила для каждой задачи — в корневых инструкциях; процедуры для части задач — в навыках.
- Когда страницу руководства разделяют или переносят, прогоняйте проверку ссылок и якорей по всему разделу.
- Повторяйте аудит после каждого изменения моделей, ролей или навыков.
Открытые вопросы
- Правила запрета чтения чувствительных локальных данных. Применены 2026-10-22 в обоих инструментах для логов, пользовательских данных и папки конфигурации, с запретом grep для triage; проверены в «Правилах запретов». Остаётся правило для человека: никогда не прикладывать эти файлы самому.
- Канареечные прогоны. Задачи в «Канареечных задачах по ролям» определены; их первые результаты попадут на эту страницу, когда пройдут в обоих инструментах.
Автор статьи: Клавдия Кондакова