# AGENTS.md — правила для ИИ-ассистентов (Claude, Cursor, Copilot и др.)

> **Этот файл перезаписывается при обновлении движка.** Свои дополнения и заметки
> по конкретному сайту пишите в `AGENTS.local.md` — его движок никогда не трогает.

## TL;DR (English — read this first)

1. **NEVER edit `core/`, `modules/`, `config/`, `bin/`, `docs/`, `public/assets/`** — these are overwritten on every engine update; your changes WILL be lost.
2. **Customize ONLY via your own plugin** (`plugins/<your-slug>/`) **or your own theme** (`templates/<your-theme>/`).
3. Never edit bundled plugins (`leads`, `shop`, `analytics`, `handbook`) or bundled themes (`default`, `admin`, `commerce`) in place — copy a theme under a new name first.
4. After ANY change to a `.tpl` file run `php bin/celena cache:clear` (or delete `storage/cache/tpl/*`) — mtime-based cache invalidation is unreliable.
5. After changing CSS/JS bump the `?v=` version in the `<link>`/`<script>` include.
6. SQL must work on BOTH PostgreSQL and MySQL (`DB_DRIVER`): no backticks, no `LIMIT x,y`, no `ON DUPLICATE KEY UPDATE`, no `ILIKE`, no `RETURNING`, no `::casts`.
7. Table names ONLY via `$conn->table('x')` / `$conn->builder('x')` — never hardcode the `cl_` prefix; schema changes ONLY via `Blueprint` migrations; queries ONLY via prepared statements.
8. No PHP in `.tpl` templates (it is escaped as text); every `[if]`/`[foreach]` must be closed; never put `*}` inside a `{* comment *}`.
9. No external CDNs — CSP in `.htaccess` blocks them; ship all assets locally inside your theme/plugin.
10. Site settings live in `.env` and the admin panel — NOT in `config/*.php`; never touch `storage/`, `public/uploads/`, `install.lock`.
11. Before editing any red-zone file: STOP and propose an alternative (hook / plugin / theme fork) to the user instead.

---

## 0. Что это за движок

**Celena CMS** — лёгкая модульная PHP-CMS без сторонних фреймворков: PHP 8.3+, PDO,
собственный шаблонизатор (`.tpl`), собственный роутер, хуки в стиле WordPress.
Версия движка — константа `CELENA_VERSION` (определяется в `core/bootstrap.php`).

Автозагрузка по неймспейсам:

| Неймспейс | Каталог |
|---|---|
| `Celena\Core\*` | `core/` |
| `Celena\Module\<Name>\*` | `modules/<Name>/` |
| `Celena\Plugin\<Slug>\*` | `plugins/<slug>/src/` |

Точки входа: `index.php` (фронт), `admin.php` (панель `/admin`), CLI — `php bin/celena`.

---

## 1. Карта каталогов: светофор зон

Главное правило движка. Обновление ядра выполняется **копированием файлов поверх**
(см. `ОБНОВЛЕНИЕ.md`), поэтому часть каталогов при каждом обновлении полностью
заменяется новой версией.

### 🔴 КРАСНАЯ зона — НЕ редактировать (перезаписывается при обновлении)

Любая правка здесь будет молча потеряна при следующем обновлении движка:

- `core/` — ядро (Kernel, роутер, шаблонизатор, БД, безопасность)
- `modules/` — встроенные модули (News, Pages, Users, Settings и др.)
- `config/` — конфиги-обёртки над `.env`
- `bin/` — CLI и служебные скрипты
- `docs/` — документация движка
- `public/assets/` — ассеты ядра и скопированные ассеты плагинов
- `index.php`, `admin.php`, `install.php`, `.htaccess`
- корневые `README.md`, `CHANGELOG.md`, `УСТАНОВКА.md`, `ОБНОВЛЕНИЕ.md`, `AGENTS.md`, `CLAUDE.md`
- **штатные плагины**: `plugins/leads`, `plugins/shop`, `plugins/analytics`, `plugins/handbook`
- **штатные темы**: `templates/default`, `templates/admin`, `templates/commerce`

Если кажется, что «нужно поправить одну строчку в ядре» — это почти всегда решается
хуком, плагином или переопределением шаблона (см. раздел 2).

### 🟡 ЖЁЛТАЯ зона — можно, но осторожно

- `.env` — настройки установки (БД, URL, ключи). При обновлении **сохраняется**.
  Держать права `chmod 600`. Не коммитить в публичные репозитории.
- Форк штатной темы — только **копией под своим именем**
  (`templates/default/` → `templates/mytheme/`, поправить `theme.json`).
  Правка `default`/`commerce` на месте будет затёрта обновлением.

### 🟢 ЗЕЛЁНАЯ зона — ваше пространство, обновление её не трогает

- `plugins/<свой-слаг>/` — свои плагины
- `templates/<своя-тема>/` — свои темы
- `AGENTS.local.md` — свои правила и заметки для ИИ-ассистентов (движок его никогда не перезапишет)

### ⛔ НЕ ТРОГАТЬ РУКАМИ (служебные данные)

- `storage/` — кэш, логи, сессии, бэкапы. Чистить только через `php bin/celena cache:clear`.
- `public/uploads/` — загруженные пользователем файлы.
- `install.lock` — маркер установленной CMS; удаление откроет установщик заново.

### Отдельно про `config/`

`config/*.php` — **не место для настроек сайта**: это тонкие обёртки, читающие `.env`
через `env()`, и они перезаписываются при обновлении. Настройки окружения — в `.env`,
настройки сайта (название, тема, почта и т.п.) — в админке (`/admin` → Настройки).

---

## 2. Как кастомизировать правильно

Вся кастомизация — через **свой плагин** или **свою тему**. Ядро самодостаточно:
плагин только расширяет его через хуки и роуты, никогда не модифицирует.

### Хуки

`Celena\Core\Plugin\Hook` — actions (`Hook::on` + `Hook::action`) и filters
(`Hook::addFilter` + `Hook::filter`). Ключевые фильтры ядра:

| Хук | Что делает |
|---|---|
| `template.globals` | добавить/изменить переменные, доступные во всех шаблонах |
| `template.output` | пост-обработка готового HTML страницы |
| `theme.active` | подменить активную тему на лету |
| `admin.sidebar` | добавить пункты в меню админки |
| `admin.notifications` | добавить уведомления в шапку админки |
| `admin.dashboard.sections` | добавить секции на дашборд |

Полный список хуков и их аргументов — `docs/PLUGIN_SDK.md`, раздел «Хуки».

### Свой плагин

Структура: `plugins/<slug>/` с обязательными `manifest.json` и `plugin.php`
(роуты через `$container->make(Router::class)`, хуки, async-блоки, свои теги),
PHP-классы в `src/` (PSR-4 `Celena\Plugin\<Slug>\*`), схема БД — в `migrations/`,
шаблоны — в `templates/`, ассеты — в `assets/` (копируются в
`public/assets/plugins/<slug>/` автоматически). Готовый скелет и примеры —
`docs/PLUGIN_SDK.md`.

### Своя тема

Скопировать `templates/default/` под новым именем, поправить `theme.json`,
активировать в админке (Настройки → Шаблоны). Плагин может переопределять свои
шаблоны в активной теме — см. `docs/PLUGIN_SDK.md`, раздел «Переопределение шаблонов».

---

## 3. Шаблонизатор и его грабли

Шаблоны — `.tpl`-файлы. **PHP в них невозможен**: `<?php` и `<?=` экранируются
как текст. Весь вывод **автоматически экранируется** (auto-escape); доверенный HTML
выводится явно через `|raw`.

```html
{title}  {user.name}  {news.body|raw}

[if {user.role}="admin"] ... [else if {user.role}="editor"] ... [else] ... [/if]
[if {is_published}] ... [/if]            <!-- truthy-проверка -->
[if {a.id}={b.id}] ... [/if]             <!-- сравнение двух переменных -->

[foreach var="news" as="n"]
  {n.title} — {_index}/{_total}
[/foreach]

{include file="_partials/head.tpl"}
{csrf}            {csrf format="meta"}
{lang key="hello.world"}
{icon name="check"}
{* комментарий — в вывод не попадает *}
```

Правила:

- **Каждый `[if]` и `[foreach]` обязан быть закрыт** (`[/if]`, `[/foreach]`) —
  незакрытый блок ломает компиляцию шаблона.
- Операторы сравнения: `=`, `!=`, `>`, `<`, `>=`, `<=` (`>`/`<` — числовые).
- Пустой массив в `[foreach]` просто не рендерит тело; «пустое состояние» —
  отдельным флагом из контроллера.
- Инлайн `<style>`/`<script>` в шаблоне безопасны: движок матчит только `{слово}`
  без спецсимволов.

### ⚠️ Ловушка: комментарии `{* ... *}`

Комментарий вырезается **нежадным** регулярным выражением: сканирование
останавливается на **первом** встреченном `*}`. Любое `*}` внутри комментария
(например, закомментированный код с `{p.*}` или вложенный `{* ... *}`) обрывает
его раньше времени — весь «хвост» комментария становится **живым кодом шаблона**
(включая случайные `{include}` — риск рекурсии). Не помещайте `*}` внутрь
комментариев; большие куски кода лучше не комментировать, а удалять.

Полная документация шаблонизатора — `docs/TEMPLATES.md`.

---

## 4. КЭШ — читать обязательно

Три независимых слоя кэша, из-за которых «я поправил файл, но ничего не изменилось»:

1. **Скомпилированные шаблоны** — `storage/cache/tpl/*.php`. Инвалидация по mtime
   исходника **ненадёжна**, когда файлы копируются поверх, заливаются по FTP или
   восстанавливаются из бэкапа (mtime может не измениться или уехать в прошлое).
   **После КАЖДОЙ правки `.tpl`:**
   ```bash
   php bin/celena cache:clear      # или удалить storage/cache/tpl/*
   ```
2. **Кэш браузера/веб-сервера для статики** — после правки `.css`/`.js` **бампить
   версию** в месте подключения (`?v=2` → `?v=3`), иначе посетители получат старый файл.
3. **OPcache PHP** — после правки `.php` на сервере с PHP-FPM может понадобиться
   перезагрузка пула (`systemctl reload php8.3-fpm` или аналог хостинга).

---

## 5. База данных: кросс-СУБД или ничего

`DB_DRIVER` в `.env` — `pgsql` **или** `mysql`. Один и тот же код работает у
клиентов на обеих СУБД, поэтому **любой SQL обязан быть кросс-СУБД**.

- **Префикс таблиц** `DB_PREFIX` (по умолчанию `cl_`) настраивается на каждой
  установке. Имя таблицы получать **только** через `$conn->table('x')` (вернёт
  `cl_x`) или строить запрос через `$conn->builder('x')`. Никогда не хардкодить `cl_`.
- **Запрещённый MySQL-диалект**: обратные кавычки `` ` ``, `LIMIT x,y`
  (только `LIMIT n OFFSET m`), `ON DUPLICATE KEY UPDATE`, `GROUP_CONCAT`, `IFNULL`,
  `AUTO_INCREMENT` в сыром DDL.
- **Запрещённый PostgreSQL-диалект**: `ILIKE`, `RETURNING`, `::cast`, `string_agg`,
  `SERIAL`.
- **Схема — только через `Blueprint`** в миграциях (`plugins/<slug>/migrations/`,
  см. `docs/PLUGIN_SDK.md`) — он сам генерирует правильный DDL под обе СУБД.
  Никакого сырого `CREATE TABLE`/`ALTER TABLE`.
- **Только prepared statements** — плейсхолдеры `?`, никакой конкатенации
  пользовательских данных в SQL.

---

## 6. Безопасность

- **CSP** в `.htaccess`: `default-src 'self'` — **внешние CDN (jQuery, unpkg,
  cdnjs и т.п.) заблокированы браузером**. Все ассеты класть локально:
  `templates/<тема>/assets/` или `plugins/<slug>/assets/`. Не «чинить» это
  ослаблением CSP.
- Никакого `eval()` и динамического исполнения строк.
- Никаких прав `777` на файлы и каталоги; `.env` — `600`.
- Никакой загрузки/создания `.php`-файлов в `public/uploads/` и вообще исполняемого
  кода в каталогах загрузок.
- Пароли — только через штатный `Celena\Core\Security\Auth` (ARGON2ID).
- Формы — с `{csrf}`; AJAX — токен из `{csrf format="meta"}`.

Подробнее — `docs/SECURITY.md`.

---

## 7. Обновление движка

Кнопки «обновить ядро в один клик» нет: ядро обновляется **копированием файлов
новой версии поверх** по инструкции `ОБНОВЛЕНИЕ.md` (панель лишь сообщает о выходе
новой версии). **Плагины и темы из маркетплейса** обновляются кнопкой «Обновить»
в панели. Миграции применяются автоматически при первом запросе.

Именно поэтому действует правило красной зоны:

> **Прежде чем править файл из красной зоны — ОСТАНОВИСЬ.** Объясни пользователю,
> что правка будет потеряна при обновлении, и предложи альтернативу: хук, свой
> плагин, переопределение шаблона или форк темы под своим именем. Правь красную
> зону только если пользователь явно понимает и принимает последствия.

---

## 8. Команды и отладка

```bash
php bin/celena migrate        # применить миграции ядра и всех плагинов
php bin/celena cache:clear    # очистить кэш шаблонов/данных/HTTP
php bin/celena route:list     # список зарегистрированных маршрутов
```

- `APP_DEBUG=true` в `.env` — **только локально**, на проде всегда `false`.
- Логи — `storage/logs/` (уровень задаёт `LOG_LEVEL` в `.env`).
- Быстрая самопроверка сайта: открыть главную и `/admin`, проверить свежие ошибки
  в `storage/logs/`.

---

## 9. Куда смотреть дальше

- `docs/ARCHITECTURE.md` — устройство ядра и жизненный цикл запроса
- `docs/TEMPLATES.md` — шаблонизатор и создание тем
- `docs/PLUGIN_SDK.md` — разработка плагинов: скелет, хуки, миграции, маркетплейс
- `docs/SECURITY.md` — модель безопасности
- `docs/AI_AGENT_GUIDE.md` — расширенный гайд для ИИ-агентов
- https://celena.io/docs/ — онлайн-документация
- https://celena.io/llms.txt — краткая выжимка для LLM

Свои правила для конкретного сайта (доступы, соглашения проекта, особенности
хостинга) — в `AGENTS.local.md` рядом с этим файлом.
