pnd8_rasp/AGENTS.md

16 KiB
Raw Permalink Blame History

AGENTS.md — рабочие инструкции pnd8_app

Версия: 2026-08-10
Кодировка: UTF-8

Назначение

  • Этот файл — входная карта проекта для AI-ассистентов и разработчиков.
  • Перед нетривиальной правкой сначала изучить затрагиваемый модуль, соседний модуль того же типа и связанные XML/шаблоны/миграции.
  • Новые устойчивые правила проекта добавлять сюда. Не превращать файл в журнал реализации отдельных задач.
  • Не удалять и не откатывать чужие изменения в dirty worktree без явного запроса.
  • Не хранить в этом файле пароли, токены, API-ключи и другие секреты.

Контекст проекта

pnd8_app — веб-приложение для поиска участка обслуживания ПНД по адресу и показа врачей с расписанием приёма.

Основной пользовательский сценарий:

  1. Пользователь вводит адрес на публичной странице.
  2. Яндекс Карты определяют координаты.
  3. Приложение находит содержащий точку полигон pnd_zone_geometry.
  4. Через zone_id загружаются участок pnd_zones и врачи pnd_doctors.
  5. Расписание врача читается из JSON-поля schedule и отображается/печатается.

Данные врачей, участков и расписаний синхронизируются из внешней старой МИС cron-скриптом. FAQ, документы и статические страницы управляются через собственный движок и админку.

Стек

  • PHP 7.4 FPM и Composer 2.
  • Собственный legacy PHP-фреймворк: module, cat, cobject, XML-компоновка, legacy .htm и BladeOne.
  • MariaDB 10.6.21 в текущем docker-compose.yml; слой доступа к БД — собственный db/cobject поверх mysqli.
  • Nginx 1.24, Docker Compose, phpMyAdmin.
  • Публичный frontend: Bootstrap 4, jQuery 3.4.1, Font Awesome 5, Яндекс Карты и Suggest API.
  • PHP CS Fixer подключён как Composer-зависимость; автоматизированного тестового набора в репозитории сейчас нет.

Не применять синтаксис и API PHP 8.x. Не обновлять версии runtime, Composer-зависимостей или frontend-библиотек попутно с прикладной задачей.

Карта проекта

  • app/ — код приложения; в контейнерах монтируется в /var/www/html.
  • app/public_html/ — фактический web root и публичная точка входа index.php.
  • app/public_html/admin/ — точка входа админки.
  • app/public_html/assets/ — публичные CSS, JS, SCSS, шрифты и генератор статических include-файлов.
  • app/engine/bootstrap.php — общая загрузка конфигурации, БД, ядра и BladeOne.
  • app/engine/core/ — ядро, cobject, БД, формы, фильтры, роутинг и типы атрибутов.
  • app/engine/www/modules/ — контроллеры публичной части.
  • app/engine/www/bladetpl/ — Blade-шаблоны публичной части.
  • app/engine/www/tpls/ — legacy-шаблоны и XML include-файлы публичной части.
  • app/engine/www/xml/ — XML-компоновка публичных категорий.
  • app/engine/admin/modules/, bladetpl/, tpls/, xml/ — соответствующие части админки.
  • app/engine/migrations/ — плоский каталог SQL-миграций и исполнитель _migrate.php.
  • app/engine/cron/data_sync/ — импорт врачей, участков и расписания из внешней МИС.
  • app/config/ — конфигурация и подключения приложения; считать содержимое чувствительным.
  • config/, docker/, docker-compose.yml — инфраструктура контейнеров.
  • db/, logs/, sessions/ — runtime-данные; не редактировать и не добавлять в Git.
  • Договор/, архивы и дампы в корне — не код приложения; не открывать и не изменять без прямой необходимости задачи.

README унаследован от Bambolo и местами устарел: в этом репозитории web root называется public_html, а текущий Compose содержит только php, nginx, mariadb и phpmyadmin. Проверять фактическую конфигурацию, а не слепо следовать README или deploy.cmd.

Архитектурные правила

  • Сначала искать аналогичный существующий модуль и сохранять принятый проектом паттерн.
  • У модуля параметры запроса явно перечислять в $_get_vars, $_post_vars и $_loc_vars; внутри action использовать $this->имяПараметра.
  • Action этого движка реализуются методами _on_*/_ajax_*; не смешивать несвязанные action и представления в одном шаблоне.
  • Для Blade использовать общий $blade через global $blade и $blade->run($this->getBladeTempl(...), $data).
  • Для текущей категории использовать global $cat и $cat->cat, для редиректа — _redirect().
  • Не использовать $GLOBALS[...] и не добавлять новый прямой доступ к $_REQUEST.
  • Бизнес-вычисления и SQL готовить в PHP-модуле; в Blade оставлять преимущественно отображение. При доработке существующего шаблона постепенно выносить сложную подготовку данных, если это входит в задачу.
  • Не вводить новый фреймворк, ORM или сборщик ради локальной правки.
  • Сохранять обратную совместимость публичных URL, XML-категорий и связки module -> XML/category -> template.

База данных и миграции

  • Перед изменением сущности проверить таблицу, _sys_datatypes, использующие её модули и предыдущие миграции.
  • Любое изменение схемы или системных метаданных оформлять новым .sql в app/engine/migrations/; уже применённые миграции не переписывать.
  • Имена новых миграций продолжать в существующем формате YYYYMMDD-HHMM-description.sql и обеспечивать уникальность имени.
  • Исполнитель миграций примитивно делит SQL по ; перед переводом строки. Не добавлять процедуры, триггеры или конструкции с внутренними ; без предварительной доработки/проверки runner.
  • SQL строить с приведением числовых значений через (int)/intval() и экранированием строк через db_escape_string(). Предпочитать методы cobject, когда они покрывают операцию.
  • Не использовать REPLACE INTO; для upsert применять INSERT ... ON DUPLICATE KEY UPDATE либо явные UPDATE/INSERT.
  • Геометрия зон хранится как MySQL spatial POLYGON. Сохранять действующий порядок координат и замыкать контур; проверять поиск точки через ST_WITHIN.
  • Не запускать миграции на production и не импортировать дампы без явного запроса.

Синхронизация с МИС

  • sync_doctors_and_zones.php — потенциально разрушительная операция: она создаёт временные таблицы, очищает основные pnd_zones/pnd_doctors, переносит данные и удаляет временные таблицы.
  • Не запускать этот скрипт автоматически для проверки. Сначала использовать режим dry-run или отдельную тестовую БД и явно проверить подключения.
  • После миграции МИС рабочие слоты врачей находятся в SimpleSchedule; старую цепочку Event/Action/ActionProperty_Time для расписания не использовать.
  • Рабочее время дня вычислять по всем действующим слотам присутствия врача в учреждении (amb, external, internal) независимо от ticket; заполненные номерки тоже расширяют диапазон активности. Исключать удалённые, отключённые и нулевые слоты, а также строки с absence_reason.
  • Интервалы SimpleSchedule.schedule_type = 'home' относятся к работе на дому и не должны входить в отображаемый диапазон присутствия врача.
  • SimpleSchedule.ticket ссылается на TicketInfo.id; NULL означает свободный слот. Для синхронизации только рабочих часов TicketInfo не читать и пациентские данные не переносить.
  • ID врачей и участков сейчас совпадают с внешними ID старой МИС. Не менять эту семантику без миграционного плана.
  • Поле pnd_doctors.schedule содержит JSON вида YYYY-MM-DD => {start, end} либо null; при изменениях сохранять обратную совместимость формата.
  • Расписание формируется на 10 дней, включая текущий. Проверять границы дат, отсутствие приёма и часовой пояс Europe/Moscow.
  • Не добавлять новые реквизиты подключения в код. Обнаруженные hardcoded-пароли и API-ключи не копировать в логи, ответы, документацию или новые файлы; при отдельной задаче переносить их в переменные окружения.

UI и шаблоны

  • Админка и публичная часть используют Bootstrap 4; не применять классы и data-bs-* из Bootstrap 5.
  • Использовать существующие jQuery/Bootstrap/Font Awesome 5 и визуальные паттерны соседних шаблонов.
  • Сохранять адаптивность крупного адресного поля, списка подсказок, модального результата и печати.
  • Для изменений карты проверять оба сценария: выбор адреса по координатам и клик по полигону.
  • Пользовательские и внешние строки не конкатенировать в HTML без экранирования. В Blade по умолчанию использовать {{ ... }}, а {!! ... !!} — только для заранее подготовленного доверенного содержимого.
  • Не коммитить скомпилированные файлы из app/engine/*/bladetpl/cache/, если задача прямо не требует обновления уже отслеживаемых артефактов.
  • После изменения перечня CSS/JS или исходной статики пересобрать include-файлы соответствующим static_optimization.php и проверить diff сгенерированных файлов.

Кодировка и стиль

  • Все новые и изменённые текстовые файлы сохранять в UTF-8 без порчи русских строк.
  • В старых файлах уже встречается повреждённая кириллица. Не распространять её копированием и не делать массовое исправление кодировки вне отдельной задачи.
  • Следовать стилю ближайшего файла; не проводить широкий форматирующий рефакторинг вместе с функциональной правкой.
  • PHP-файлы проверять на синтаксис под PHP 7.4. Форматтер запускать только для файлов в области задачи и внимательно просматривать diff.

Рабочие команды

Из корня проекта:

docker compose up -d
docker compose ps
docker compose logs --tail=100 php
docker compose exec php composer install
docker compose exec php php -l engine/www/modules/site_index.php
docker compose exec php sh -lc "cd engine/migrations && php _migrate.php"

Последнюю команду запускать только когда задача действительно требует применения миграций к выбранной локальной БД.

Проверка синтаксиса всех изменённых PHP-файлов должна выполняться адресно. app/php-cs-fixer.cmd с fix изменяет много файлов, поэтому не запускать его по всему проекту без отдельного согласования.

Минимальная проверка перед завершением

  • Просмотреть git status --short и git diff; убедиться, что изменены только файлы задачи.
  • Для каждого изменённого PHP-файла выполнить php -l в PHP 7.4 контейнере.
  • Для SQL проверить совместимость с MariaDB 10.6.21 и ограничения _migrate.php.
  • Для изменений публичного сценария вручную проверить: загрузку карты, подсказки адресов, поиск зоны, карточки врачей, пустое расписание, модальное окно и печать.
  • Для изменений полигонов проверить создание/редактирование/удаление в админке и попадание точки внутрь зоны на публичной странице.
  • Для cron сначала проверить dry-run/тестовую БД; убедиться, что временные таблицы и основные данные остаются согласованными при ошибке.
  • После массовых замен отдельно проверить русские строки на «кракозябры».
  • Не считать отсутствие автоматических тестов основанием пропустить адресную проверку.