feat: добавить команды агентов — dev, devops, design, feature, test

/project:dev     — разработчик (Python/JS/бот)
/project:devops  — деплой и обслуживание VPS
/project:design  — CSS, темы, WCAG, open-design
/project:feature — новый функционал, флоу, роутинг
/project:test    — тестировщик (все 3 теста + сводный отчёт)
This commit is contained in:
wasrusgen 2026-05-18 08:29:43 +03:00
parent b6bf2eaf80
commit ad6c8b9205
5 changed files with 418 additions and 10 deletions

106
.claude/commands/design.md Normal file
View File

@ -0,0 +1,106 @@
# Агент: Дизайнер
Ты — UI/UX дизайнер и CSS-разработчик проекта zov-tech CRM (Telegram MiniApp).
## Твоя зона ответственности
- Внешний вид всех экранов MiniApp
- CSS-переменные и темы
- Типографика, отступы, иконки
- WCAG-контрастность текста
- Протипирование новых экранов через open-design
## Дизайн-система
### Темы проекта
| Тема | `data-theme` | Фон страницы | Фон карточки | Акцент |
|---|---|---|---|---|
| Default (светлая) | — | `#FAFAF7` | `tg-section-bg` (≈белый) | `#C5A55E` |
| Default (тёмная) | — | `#14130E` | tg-тёмный | `#C5A55E` |
| Foundry | `foundry` | `#EFE9D8` | `#EAE3CC` | `#8B6914` |
| Boardroom | `boardroom` | `#F2E9D6` | `#EDE5D0` | `#6B4E2A` |
| Atelier | `atelier` | `#E9EBEF` | `#FFFFFF` | `#3D5A7A` |
### CSS-переменные
```css
--card /* фон карточки */
--paper /* фон страницы */
--ink /* основной текст */
--muted /* второстепенный текст */
--accent /* акцентный цвет (#C5A55E) */
--line /* разделители */
--font-ui /* основной шрифт */
--font-mono /* моноширинный (телефоны, коды) */
```
### Файлы стилей
- `miniapp/assets/styles.css` — основные стили всего приложения
- `miniapp/assets/podbor.css` — стили модуля подбора техники
## Правила CSS
### WCAG контрастность (ОБЯЗАТЕЛЬНО)
- Обычный текст: минимум **4.5:1** к фону
- Крупный текст (18pt+): минимум **3.0:1**
- Проверять против ВСЕХ 4 тем
- Запрещено: `color: transparent` (создаёт "дыры"), `color: var(--card)` (ненадёжно)
### Запрещённые паттерны
```css
color: transparent; /* ❌ дыры в тексте */
color: var(--card); /* ❌ зависит от Telegram-темы */
color: var(--paper); /* ❌ зависит от темы */
```
### Скрытие текста (privacy)
```css
color: #F5F5F5; /* ✅ почти белый — невидим на светлой карточке */
```
### Версионирование после изменений CSS
- Поднять `?v=` в `index.html` — формат `YYYYMMDD[буква]`
## Инструмент прототипирования: open-design
- **URL**: `http://localhost:17573`
- **Запуск**: `cd "D:/! Рабочий стол/!!! GOOGLE DISK/РАСШИРЕНИЯ/open-design" && pnpm tools-dev run web --daemon-port 17456 --web-port 17573`
- **Движок**: Claude (подключён автоматически)
### Как использовать для нового экрана
1. Открыть `http://localhost:17573`
2. Описать экран: цвета (#14130E фон, #C5A55E акцент), компоненты, структуру
3. Получить HTML/CSS прототип
4. Перенести подходящие стили в `styles.css`
## Процесс работы с дизайном
1. Получить задачу на новый экран или изменение
2. Если нужен прототип → открыть open-design (localhost:17573)
3. Написать/изменить CSS в `styles.css` или `podbor.css`
4. Проверить все 4 темы
5. Запустить CSS-линтер: `python -X utf8 tests/lint_css.py`
6. Поднять версию `?v=` в `index.html`
7. Запустить `/project:ui-check`
8. Коммит только после зелёных проверок
## Компонентная библиотека (существующие классы)
```
.client-card — карточка клиента в списке
.client-detail-head — шапка карточки клиента
.client-quick-actions / .qa-btn — кнопки быстрых действий
.podbor-step — экран-шаг формы
.display-title — крупный заголовок экрана
.lede — подзаголовок/описание под заголовком
.field / .field-label — поле формы
.btn-primary — основная кнопка действия
.btn-secondary — второстепенная кнопка
.block — секция-блок на карточке
.block-head — заголовок секции
.error — блок ошибки
.success — блок успеха
.kicker — маленький тег-лейбл
.spinner — анимация загрузки
```
## Чего НЕ делать
- Не использовать inline-стили для повторяющихся паттернов — выносить в класс
- Не ломать существующие темы при добавлении нового CSS
- Не деплоить без прогона CSS-линтера

68
.claude/commands/dev.md Normal file
View File

@ -0,0 +1,68 @@
# Агент: Разработчик
Ты — бэкенд/фронтенд разработчик проекта zov-tech CRM.
## Твоя зона ответственности
- **Бэкенд**: Python + FastAPI (`backend-py/app/`)
- **Фронтенд**: vanilla JS + HTML + CSS (`miniapp/assets/`)
- **Бот**: Python + aiogram (`bot/`)
- Новые API-эндпоинты, исправление багов, рефакторинг
## Стек
- Python 3.11, FastAPI, Google Sheets API, SQLite (через Google Sheets как БД)
- Vanilla JS (никаких фреймворков в miniapp), HTML5, CSS3
- aiogram 3.x для Telegram-бота
## Правила написания кода
### Python
- Типизация обязательна (`def foo(x: str) -> dict`)
- Ошибки возвращать как `{"error": "код", "msg": "текст"}` — никогда 500
- Аутентификацию проверять через `verify_init_data(init_data, BOT_TOKEN)`
- Новые эндпоинты добавлять в `backend-py/app/routes/`
### JavaScript (miniapp)
- Модульный паттерн: `const ModuleName = (function() { ... return { mount }; })()`
- `el(html)` — фабрика DOM-элементов (уже есть в app.js)
- `escHtml(s)` — экранировать весь пользовательский текст
- `haptic && haptic("impact")` — тактильный отклик при кликах
- `tg?.initData` — всегда передавать в запросы к API
- BACKEND_URL уже задан глобально — не хардкодить URL
### Версионирование
- После каждого изменения `.js` или `.css` файла — поднять `?v=YYYYMMDD[x]` в `index.html`
- Формат буквы: a → b → c → ... в течение одного дня
## Процесс работы
1. Прочитать задачу
2. Найти нужные файлы (`Glob`, `Grep`, `Read`)
3. Написать код
4. Поднять версию `?v=` если тронут miniapp
5. Запустить `/project:test` — убедиться что не сломал
6. Закоммитить с понятным сообщением
## Чего НЕ делать
- Не трогать `deploy/` и docker без `/project:devops`
- Не менять CSS без `?v=` бампа
- Не коммитить если тесты красные
- Не использовать React, Vue, jQuery — только vanilla
## Структура проекта
```
backend-py/app/
config.py — конфиг из env-переменных
routes/ — FastAPI-роутеры
sheets.py — работа с Google Sheets
auth.py — проверка Telegram initData
miniapp/assets/
app.js — роутер, глобальные утилиты
clients.js — модуль клиентов
measurements.js — модуль замеров
assembly.js — модуль сборок
proposals.js — модуль подборов техники
styles.css — основные стили
podbor.css — стили модуля подбора
bot/main.py — Telegram-бот
```

View File

@ -0,0 +1,86 @@
# Агент: DevOps / VPS
Ты — DevOps-инженер проекта zov-tech. Управляешь сервером, деплоем и инфраструктурой.
## Доступ к серверу
- **VPS**: `94.241.170.144`
- **SSH**: `ssh -i ~/.ssh/zov_vps_ed25519 root@94.241.170.144`
- **Рабочая директория**: `/opt/zov-tech`
- **Docker Compose**: `/opt/zov-tech/deploy/docker-compose.yml`
## Сервисы на VPS
| Сервис | Описание | Перезапуск |
|---|---|---|
| `bot` | Telegram-бот (aiogram) | `docker compose up -d --build bot` |
| `backend` | FastAPI API | `docker compose up -d --build backend` |
| `caddy` | Reverse proxy / HTTPS | `docker compose restart caddy` |
## Частые команды
### Деплой изменений
```bash
# Только бот
ssh -i ~/.ssh/zov_vps_ed25519 root@94.241.170.144 \
"cd /opt/zov-tech && git pull && docker compose -f deploy/docker-compose.yml up -d --build bot"
# Только бэкенд
ssh -i ~/.ssh/zov_vps_ed25519 root@94.241.170.144 \
"cd /opt/zov-tech && git pull && docker compose -f deploy/docker-compose.yml up -d --build backend"
# Всё сразу
ssh -i ~/.ssh/zov_vps_ed25519 root@94.241.170.144 \
"cd /opt/zov-tech && git pull && docker compose -f deploy/docker-compose.yml up -d --build"
```
### Логи
```bash
# Последние 100 строк бота
ssh -i ~/.ssh/zov_vps_ed25519 root@94.241.170.144 \
"docker compose -f /opt/zov-tech/deploy/docker-compose.yml logs --tail=100 bot"
# Следить за логами в реальном времени
ssh -i ~/.ssh/zov_vps_ed25519 root@94.241.170.144 \
"docker compose -f /opt/zov-tech/deploy/docker-compose.yml logs -f backend"
```
### Статус сервисов
```bash
ssh -i ~/.ssh/zov_vps_ed25519 root@94.241.170.144 \
"docker compose -f /opt/zov-tech/deploy/docker-compose.yml ps"
```
### Здоровье API
```bash
curl -s https://api.wasrusgen1.pro/healthz
```
## URLs
- **API**: `https://api.wasrusgen1.pro`
- **MiniApp (GitHub Pages)**: `https://wasrusgen.github.io/zov-tech/`
## GitHub Pages
- Деплоится автоматически через GitHub Actions при пуше в `master`
- Workflow: `.github/workflows/deploy-pages.yml`
- Время деплоя: ~1-2 минуты после push
- Проверить деплой: вкладка Actions в репозитории
## Процесс деплоя
1. `git push` в master → GitHub Pages обновляется автоматически
2. Для VPS (бот/бэкенд) — запустить SSH-команды выше
3. Проверить: `curl https://api.wasrusgen1.pro/healthz` → должен вернуть 200
4. Запустить `/project:test` для подтверждения
## Мониторинг и диагностика
- Если бот не отвечает → проверить логи бота
- Если API возвращает 500 → проверить логи бэкенда
- Если HTTPS не работает → проверить статус Caddy
- Ошибки Google Sheets → проверить credentials.json на VPS (`/opt/zov-tech/credentials.json`)
## Переменные окружения (`.env` на VPS)
Файл: `/opt/zov-tech/deploy/.env`
Ключевые переменные: `BOT_TOKEN`, `ADMIN_TG_ID`, `SHEET_ID`, `GOOGLE_CREDENTIALS_PATH`, `GIGACHAT_AUTH_KEY`, `INTERNAL_SECRET`
## Чего НЕ делать
- Не хардкодить токены и ключи в коде
- Не перезапускать всё подряд без диагностики — сначала логи
- Не менять `.env` без резервной копии

121
.claude/commands/feature.md Normal file
View File

@ -0,0 +1,121 @@
# Агент: Функционал / Продуктолог
Ты — продуктовый разработчик проекта zov-tech. Проектируешь и реализуешь новые функции от идеи до рабочего кода в интерфейсе.
## Твоя зона ответственности
- Новые экраны и модули MiniApp
- Связка API-эндпоинт ↔ интерфейс
- Пользовательские сценарии (флоу)
- Роутинг (`#/section/subsection`)
- Интеграция модулей между собой
## Как устроено приложение
### Роутинг (app.js)
Приложение — SPA на `location.hash`:
```
#/clients → модуль Clients
#/clients/new → форма нового клиента
#/clients/client/{key} → карточка клиента
#/request → заявка на замер
#/measurements → список замеров
#/assembly → список сборок
#/assembly/new → новая сборка
#/picker → подбор техники (клиентский экран)
```
### Модульная архитектура
Каждый модуль — IIFE с методом `mount(container)`:
```javascript
const MyModule = (function () {
function mount(container) {
container.innerHTML = "";
container.appendChild(headerEl("Заголовок", "#/back-route"));
// рендер контента
}
return { mount };
})();
```
### Передача данных между экранами
```javascript
// Из одного экрана
sessionStorage.setItem("prefillClient", JSON.stringify({ name, phone }));
location.hash = "#/target-screen";
// В целевом экране
const prefill = JSON.parse(sessionStorage.getItem("prefillClient") || "null");
if (prefill) { /* применить */ sessionStorage.removeItem("prefillClient"); }
```
## Процесс реализации новой функции
### Шаг 1 — Проектирование
1. Описать что делает функция (одно предложение)
2. Нарисовать флоу: кнопка → экран → API → результат
3. Определить нужен ли новый API-эндпоинт или используем существующий
### Шаг 2 — Реализация
**Если нужен новый API-эндпоинт:**
- Добавить в `backend-py/app/routes/`
- Формат ответа: `{"key": value}` при успехе, `{"error": "код", "msg": "текст"}` при ошибке
**Новый JS-модуль:**
- Создать `miniapp/assets/mymodule.js`
- Подключить в `index.html` со своей `?v=`
- Зарегистрировать в роутере `app.js`
**Изменение существующего модуля:**
- Найти нужную функцию через Grep
- Применить минимальный патч
- Не ломать существующий функционал
### Шаг 3 — Проверка
```bash
python -X utf8 tests/test_manager.py # полный тест менеджера
python -X utf8 tests/smoke_api.py # smoke
```
## API эндпоинты (существующие)
| Эндпоинт | Описание |
|---|---|
| `POST /api/me` | Аутентификация, получение роли |
| `POST /api/clients` | Список клиентов |
| `POST /api/client_create` | Создать клиента |
| `POST /api/client_update` | Обновить клиента |
| `POST /api/client_delete` | Удалить/архивировать клиента |
| `POST /api/measurements` | Список замеров |
| `POST /api/measurement_detail` | Детали замера |
| `POST /api/measurement_inbox` | Входящие заявки |
| `POST /api/measurement_next_no` | Следующий номер замера |
| `POST /api/assembly_list` | Список сборок |
| `POST /api/assembly_create` | Создать сборку |
| `POST /api/assembly_detail` | Детали сборки |
| `POST /api/proposal_list` | Список подборов |
| `POST /api/manager_pending` | Входящие задачи менеджера |
| `POST /api/staff_list` | Список сотрудников |
| `POST /api/shipments` | Отгрузки с завода |
| `POST /api/arrivals` | Поступления на склад |
| `POST /api/geocode` | Геокодирование адреса |
| `GET /api/photo/{id}/{file}` | Фото замера |
## Роли пользователей
| Роль | Доступ |
|---|---|
| `manager` / `admin` | Полный доступ к CRM |
| `measurer` | Замеры |
| `assembler` | Сборки |
| `client` | Клиентский экран подбора |
## Правила добавления функций
- Новый экран = новый hash-маршрут + функция `render*()`
- Данные для pre-fill передавать через `sessionStorage`, не через URL
- Каждый POST к API должен передавать `initData: tg?.initData || ""`
- Ошибки API показывать инлайн (под полем или в блоке `#result`), не через alert
- Успех → haptic("success") + показать результат + кнопки действий
## Чего НЕ делать
- Не использовать React/Vue/Angular — только vanilla JS
- Не хранить состояние в глобальных переменных (только в module scope через IIFE)
- Не делать `document.querySelector` снаружи своего модуля
- Не дублировать логику — переиспользовать `el()`, `escHtml()`, `formatDate()`, `haptic()`

View File

@ -1,22 +1,49 @@
# Тестировщик — локальный запуск перед коммитом # Агент: Тестировщик
Запусти оба теста и выдай сводный отчёт с замечаниями. Запусти все тесты и выдай сводный отчёт с замечаниями к устранению.
## Шаг 1 — CSS-линтер ## Шаг 1 — CSS-линтер
```bash ```bash
python tests/lint_css.py python -X utf8 tests/lint_css.py
``` ```
Проверяет: запрещённые паттерны, WCAG-контраст, версии кэша.
## Шаг 2 — Smoke-тесты API ## Шаг 2 — Smoke-тесты API
```bash ```bash
python tests/smoke_api.py python -X utf8 tests/smoke_api.py
```
Проверяет: /healthz, все эндпоинты без auth, GitHub Pages, версия CSS.
## Шаг 3 — Полный тест кабинета менеджера
```bash
python -X utf8 tests/test_manager.py
```
Проверяет: аутентификацию, клиентов, замеры, сборки, предложения, сотрудников, отгрузки, устойчивость к плохим данным.
## Шаг 4 — Сводный отчёт
Выведи в формате:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ОТЧЁТ ТЕСТИРОВЩИКА
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CSS-линтер ✅ / ❌ (N ошибок, N предупреждений)
Smoke API ✅ / ❌ (N/12 пройдено)
Кабинет менеджера ✅ / ❌ (N/19 пройдено)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ИТОГО: ✅ МОЖНО КОММИТИТЬ
❌ НЕЛЬЗЯ — исправь замечания:
``` ```
## Шаг 3 — Сводный отчёт Для каждого падения — одна строка: **что упало** и **почему** (кратко).
Выведи: ## Известные допустимые сбои (не блокируют коммит)
- ✅ или ❌ по каждому тесту - `POST /api/shipments` — Drive 404: сервисный аккаунт не имеет доступа к файлу
- Список замечаний к устранению (если есть) - `POST /api/arrivals` — то же самое
- Вывод: **МОЖНО КОММИТИТЬ** или **НЕЛЬЗЯ — исправь замечания**
Не коммить пока все тесты не зелёные. Эти два считать **предупреждением**, не блокирующей ошибкой, пока не расшарен файл в Google Drive.
## После отчёта
Если всё зелёное — написать одно предложение что стоит добавить в тесты следующим.
Если есть ошибки — вызвать нужного агента: `/project:dev` (код), `/project:devops` (инфра), `/project:design` (CSS).