# ADR-049: create-readme tool + repo-readme skill for standardized README ## Статус Accepted (2026-07-28) ## Контекст Витрина slaid098.dev парсит `README.md` из каждого репозитория: скачивает raw файл и извлекает фрагмент между разделителями `` и ``. До сих пор README формировался агентом вручную через Write/Edit — это недетерминированно: разделители могли отсутствовать, секции Support/Quick Start/language switcher — расходиться со стандартом, из-за чего витрина не могла корректно отрендерить карточку. Issue #111 требует тулзу, гарантирующую структуру, и скилл, дающий агенту контекст. ## Решение Реализовать TS-плагин `create-readme` (`.opencode/tools/create-readme.ts`) с двумя режимами: - `create` — генерирует README по фиксированному шаблону через template literal, подставляя параметры. Структура (разделители, Support block, Quick Start, language switcher) зашита в тулзе, а не в агенте. - `validate` — проверяет существующий README на соответствие стандарту (6 проверок). Параметр `mode` = `tool.schema.enum(["create","validate"])` (zod через `tool.schema` = `typeof z`, подтверждено `tool.d.ts`). `tier` (flagship/utility) и `file_path` реализованы через `.optional()` + fallback в handler (`args.tier ?? "utility"`) вместо zod `.default()` — консистентно с существующими тулзами (они `.default()` не используют) и надёжно независимо от того, парсит opencode args через zod или передаёт raw. Локальный режим: `fs.writeFileSync`/`readFileSync`. Удалённый режим: `gh api` через `spawnSync` (GET для SHA, PUT с base64+content+message+sha) — как `create-issue.ts`/`commit.ts` используют `spawnSync` напрямую. `gh api -X PUT` помечен как destructive в `check-permissions.py`, но это правило проверяет bash allow-rules конфига, а не `spawnSync` внутри плагина — тулзе allow-rule не нужен. Скилл `repo-readme` описывает: когда вызывать create vs validate, tier system, GitHub metadata как отдельный шаг (`gh repo edit`, не в тулзе), workflow (create → ручные правки → validate), зачем разделители, шаблон как reference, независимость от repo-init. ## Альтернативы - **zod `discriminatedUnion("mode", [createSchema, validateSchema])`** — отвергнуто: `tool()` принимает `args: Args extends z.ZodRawShape` (plain object of zod schemas), а не `ZodDiscriminatedUnion`. Использована плоская schema с `mode: enum` + ручная валидация обязательных полей в handler. - **zod `.default()` для tier/file_path** — отвергнуто ради консистентности с существующими тулзами и независимости от того, вызывает opencode zod-parse. Использован `.optional()` + fallback `??`. - **Импорт zod напрямую** — отвергнут: `tool.schema` уже re-export'ит полный zod (`var schema: typeof z`), отдельный импорт и зависимость `zod` в package.json не нужны (его нет в dependencies, и существующие тулзы его не импортируют). - **Регистрация тулзы в `opencode.json` (agent.tools)** — не требуется: плагины авто-дискаверятся из `.opencode/tools/*.ts` (как `tunnel.ts`, которого нет в конфиге).