opencode-config/docs/handoff/pr-67-check-project-map.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

6.6 KiB
Raw Blame History


pr: 67 title: feat(pipeline): add check_project_map to DOCS phase

Что сделано

  • .opencode/scripts/pipeline-status.py — 3 точечные правки:
    • Константа PROJECT_MAP_DIR = REPO_ROOT / "docs" / "project-map" (после ADR_DIR, строка 54).
    • Функция check_project_map() (после check_adr) — проверяет PROJECT_MAP_DIR.exists() + README.md.exists(), возвращает DONE/NOT_DONE (без AMBIGUOUS, чисто файловая система). Шаблон по образцу check_adr.
    • В check_docs вставлен вызов между check_adr и _check_docs_reviewer_comment (short-circuit на NOT_DONE). Docstring check_docs обновлён (теперь 5 детерминированных проверок).
  • tests/test_pipeline_status_project_map.py — новый файл, 3 unit-теста (по образцу test_pipeline_status_adr.py):
    • test_project_map_exists — README.md есть → DONE, "README.md" в detail.
    • test_project_map_dir_missing — директория отсутствует → NOT_DONE, "директория" в detail.
    • test_project_map_readme_missing — директория есть, README.md нет → NOT_DONE, "README.md не найден" в detail. Загрузка скрипта под уникальным module name pipeline_status_project_map (не коллидирует с pipeline_status из других тестов).
  • tests/test_pipeline_status.py — критическая правка существующих тестов:
    • Добавлен helper make_project_map(tmp_path) рядом с make_handoff — создаёт tmp_path/project-map/README.md.
    • Во все 10 test_check_docs_* тестов добавлен monkeypatch.setattr(ps, "PROJECT_MAP_DIR", make_project_map(tmp_path)). Без этого новая под-проверка возвращала NOT_DONE и ломала assertions (7 тестов с валидным ADR доходили до check_project_map).
  • ADR-028 (docs/decisions/028-pr-67-project-map-contract.md) — фиксирует контракт project-map: README.md обязателен (mandatory, enforced), модульные файлы и frontmatter last_updated — aspirational (не enforced). Альтернативы: полный контракт (отклонено — блокирует пайплайн, ~12 файлов), env-flag (отклонено — docs-reviewer автосоздаёт), diff-based (отклонено — сложнее, не гарантирует валидность).
  • docs/project-map/README.md — секция Update Protocol дополнена строкой про новый guard; tree обновлён (новый тест-файл + тег PR#67 на pipeline-status.py).

Почему

Детерминированный guard для project-map отсутствовал — pipeline-status.py:check_docs проверял handoff, ADR и docs-reviewer comment, но не валидировал docs/project-map/. Это позволяло PR проходить DOCS-фазу даже при «тихом провале» docs-reviewer (забыл обновить карту при структурных изменениях). Memory technical/pipeline-status-no-project-map-check.md зафиксировала эту дыру.

Контракт карты был размазан по 3 файлам (docs-reviewer.md, get-project-map/SKILL.md, reviewer.md) с несоответствиями (2 разных commit message для одной операции). Фактическое состояние — только README.md без frontmatter и модульных файлов. ADR-028 ослабляет контракт под фактическое состояние (README.md mandatory, модульные файлы aspirational) и фиксирует единый source of truth. Полный контракт остаётся в get-project-map/SKILL.md как рекомендация.

Локальная верификация: 404 теста прошли, coverage 89.19% ≥ 80% (pipeline-status.py покрыт на 88%).

Pending

  • После merge: фаза MEMORY — обновить memory technical/pipeline-status-no-project-map-check.md секцией Closure (guard добавлен в PR#67, контракт зафиксирован в ADR-028).
  • ADR filename переименован с placeholder <PR-NUMBER> на 028-pr-67-project-map-contract.md после create_pr (коммит docs(handoff): set PR number).

Watch out

  • 10 существующих тестов правленыtest_check_docs_* в test_pipeline_status.py теперь требуют make_project_map(tmp_path) + monkeypatch PROJECT_MAP_DIR. Если добавить новый test_check_docs_* без этого — упадёт на NOT_DONE от check_project_map. Паттерн: копируй строку monkeypatch.setattr(ps, "PROJECT_MAP_DIR", make_project_map(tmp_path)) из соседнего теста.
  • Уникальный module name в новом тестеpipeline_status_project_map (не pipeline_status). Если использовать pipeline_status, произойдёт коллизия с test_pipeline_status.py/test_pipeline_status_adr.py которые грузят скрипт под тем же именем — sys.modules уже занят, тесты конфликтуют. Шаблон: новый test-файл для под-проверки → уникальный module name.
  • Контракт ослаблен намеренно — ADR-028 явно фиксирует что модульные файлы и frontmatter last_updated НЕ enforced. Если будущий PR захочет ужесточить контракт (полный enforcement) — это будет breaking change, требующий создания ~12 файлов для существующего репо. См. альтернативу в ADR-028.
  • scaffold-handoff.sh нумерация — скрипт считает ls docs/decisions | grep -E '^[0-9]{3}-' | wc -l + 1. Если ADR-028 уже существует, следующий вызов даст 029. При создании ADR вручную + через scaffold в одном PR — scaffold создаст дубликат с +1 номером (нужно удалить вручную).