opencode-config/docs/decisions/028-pr-67-project-map-contract.md
Sergey f06d36140b
feat(pipeline): add check_project_map to DOCS phase (#67)
* feat(pipeline): add check_project_map to DOCS phase

* test(pipeline): add check_project_map unit tests + update check_docs tests

* docs(adr): add ADR-028 project map contract

* docs(project-map): mention check_project_map guard in Update Protocol

* docs(handoff): add PR handoff for check_project_map

* docs(handoff): set PR number 67

* docs(review): fix PR#66 to PR#67 typo in project map and handoff

* fix(ci): ruff lint errors in pipeline-status and project map test

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-26 00:07:13 +03:00

5.1 KiB
Raw Permalink Blame History

ADR-028: Project map contract (mandatory README.md, aspirational modules)

Статус

Accepted (2026-07-25)

Контекст

Контракт docs/project-map/ в репо slaid098/opencode-config размазан по 3 файлам с внутренними несоответствиями:

  • .opencode/agents/docs-reviewer.md:158-159,191 — обязывает docs-reviewer обновлять карту при структурных изменениях и предлагает один commit message.
  • .opencode/skills/get-project-map/SKILL.md:25-27 — описывает структуру карты (README.md + модульные файлы per module) и frontmatter last_updated.
  • .opencode/agents/reviewer.md:199-205 — требует от code-reviewer проверять актуальность карты и предлагает другой commit message для той же операции (несоответствие с docs-reviewer.md).

Фактическое состояние карты: только README.md (~140 строк, ASCII-дерево структуры репо) без frontmatter и без модульных файлов. Полный контракт (модульные файлы per module) никогда не соблюдался — aspirational документ, не enforcement.

pipeline-status.py:check_docs (DOCS phase) валидировал handoff (4 секции), ADR (filename pattern) и docs-reviewer comment (heading ## Docs Review Summary), но не валидировал docs/project-map/. Это позволяло PR проходить DOCS-фазу даже при «тихом провале» docs-reviewer (забыл обновить карту при структурных изменениях) — детерминированный guard отсутствовал. Зафиксировано в memory technical/pipeline-status-no-project-map-check.md.

Решение

Минимальный guard в pipeline-status.py — новая функция check_project_map() проверяет существование docs/project-map/README.md (через PROJECT_MAP_DIR.exists() + README.md.exists()). Встроена в check_docs между check_adr и _check_docs_reviewer_comment (short-circuit на NOT_DONE). Mandatory для pipeline-driven репо: docs-reviewer автосоздаёт initial README.md при отсутствии каталога (docs-reviewer.md:82-84), поэтому guard не блокирует первый PR и не требует ручной bootstrap-операции.

Контракт ослаблен под фактическое состояние:

  • README.md обязателен — единственное, что проверяется детерминированно. Возвращает DONE с размером файла в detail, либо NOT_DONE с указанием что docs-reviewer должен создать (с ссылками на строки docs-reviewer.md).
  • Модульные файлы per module и frontmatter last_updated — aspirational, НЕ enforced. Полный контракт остаётся в get-project-map/SKILL.md как рекомендация для docs-reviewer, но не блокирует пайплайн.

Возвращает только DONE/NOT_DONE (без AMBIGUOUS) — проверка файловой системы детерминирована, нет внешних API вызовов.

Альтернативы

  • Полный контракт (модульные файлы per module) — отклонено: потребовало бы создания ~12 новых файлов (по одному на модуль) для существующего репо, блокируя пайплайн до их создания. Фактическое состояние никогда не соответствовало этому контракту — enforcement сломал бы все открытые PR.

  • Опциональность через env-flag OPENCODE_REQUIRE_PROJECT_MAP — отклонено: docs-reviewer уже автосоздаёт initial README.md при отсутствии каталога (docs-reviewer.md:82-84), feature-flag избыточен — guard никогда не блокирует корректно настроенный pipeline-driven репо. Env-flag добавил бы конфигурационную поверхность без выгоды.

  • Diff-based проверка (карта обновлена в PR через gh pr view --json files) — отклонено: сложнее в реализации (парсинг diff, фильтр по путям), не гарантирует валидность содержимого (файл может быть изменён, но остаться пустым/устаревшим). Существование README.md — более сильный guard (файл присутствует), diff-based — слабее (файл изменён, но может быть невалиден).