opencode-config/docs/decisions/049-pr-112-add-repo-readme-skill-and-tool.md
Sergey 7ea12b982d
feat(skills): add repo-readme skill and create-readme tool (#112)
* feat(tools): add create-readme tool

* feat(skills): add repo-readme skill

* docs(handoff): add handoff and ADR

* docs(handoff): set PR number

* docs(project-map): update after structural changes

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-29 01:04:51 +03:00

4.2 KiB
Raw Blame History

ADR-049: create-readme tool + repo-readme skill for standardized README

Статус

Accepted (2026-07-28)

Контекст

Витрина slaid098.dev парсит README.md из каждого репозитория: скачивает raw файл и извлекает фрагмент между разделителями <!-- summary-en:start/end --> и <!-- summary-ru:start/end -->. До сих пор 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, которого нет в конфиге).