16 KiB
AGENTS.md — рабочие инструкции pnd8_app
Версия: 2026-08-10
Кодировка: UTF-8
Назначение
- Этот файл — входная карта проекта для AI-ассистентов и разработчиков.
- Перед нетривиальной правкой сначала изучить затрагиваемый модуль, соседний модуль того же типа и связанные XML/шаблоны/миграции.
- Новые устойчивые правила проекта добавлять сюда. Не превращать файл в журнал реализации отдельных задач.
- Не удалять и не откатывать чужие изменения в dirty worktree без явного запроса.
- Не хранить в этом файле пароли, токены, API-ключи и другие секреты.
Контекст проекта
pnd8_app — веб-приложение для поиска участка обслуживания ПНД по адресу и показа врачей с расписанием приёма.
Основной пользовательский сценарий:
- Пользователь вводит адрес на публичной странице.
- Яндекс Карты определяют координаты.
- Приложение находит содержащий точку полигон
pnd_zone_geometry. - Через
zone_idзагружаются участокpnd_zonesи врачиpnd_doctors. - Расписание врача читается из 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/тестовую БД; убедиться, что временные таблицы и основные данные остаются согласованными при ошибке.
- После массовых замен отдельно проверить русские строки на «кракозябры».
- Не считать отсутствие автоматических тестов основанием пропустить адресную проверку.