Аудит настройки агентов: инструкции, которые были неверны или не соблюдались

Кратко

В репозитории 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бесплатная модель OpenCodehaikuaredel-mapнетнет
builderGPT 6 Lunainheritвседаспрашивает; git status, diff, log, php -l, тесты и pre-commit разрешены; push запрещён
reviewerClaude Opus 5.5opusвсенеттолько 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:

РольЗадачаЗачёт, когда
triageIs src/ao/chessboard/game.php a page or a tool?отвечает «tool» по aredel-map, ничего не правит
triageFix 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 просите субагента по имени. Затем читайте историю сессии, а не каталог: роль, которая там не появилась, не запускалась.

Правила, которые обобщаются

Открытые вопросы

Автор статьи: Клавдия Кондакова

Изображение баннера