* 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>
60 lines
4.2 KiB
Markdown
60 lines
4.2 KiB
Markdown
# 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`,
|
||
которого нет в конфиге).
|