Commit Graph

242 Commits

Author SHA1 Message Date
wasrusgen
7865b3f699 feat(6.12): dispatcher cabinet — shipment → arrival → dispatch pipeline
- dispatcher_dashboard.js: 3-step pipeline UI (shipped/arrived/scheduled)
- Assemblies: +shipment_date, packages_count, arrival_date, arrival_packages_count, arrival_confirmed_by_tg_id
- /api/dispatcher_inbox: full assembly list sorted by pipeline stage
- /api/assembly_set_shipment: fixes factory shipment date + package count → status=shipped
- /api/assembly_set_arrival: confirms warehouse receipt, alerts manager on package mismatch → status=arrived
- /api/assembly_assign_dispatch: sets date + expeditor, notifies both → status=scheduled
- app.js: dispatcher role routing (#/dispatcher), capability flag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 14:30:08 +03:00
wasrusgen
02f8dba469 feat: expeditor cabinet, electronic signature (OTP+canvas), invoice room picker
New modules:
- expeditor_dashboard.js: route list (date-grouped) + act detail + signature screen
- invoice.js: 3-col chip room picker, 2500₽ base + 1000₽ extra logic
- act4.js, measurer_dashboard.js, finance_summary.js, client_timeline.js, feedback.js, staff_roster.js

Backend:
- /api/expeditor_inbox: filtered assembly list for expeditor role
- /api/act4_request_otp: 6-digit OTP via Telegram, 10-min expiry
- /api/act4_verify_otp: validates code, marks act as signed
- /api/act4_save_signature: saves base64 canvas signature
- Act4s sheet: added signature_b64, otp_code, otp_expires_at columns

Tests:
- tests/expeditor_scenarios.md: 11 manual test scenarios

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 14:11:20 +03:00
wasrusgen
44379576f2 feat: date scheduling flow for assembler/measurer
Backend:
- _assembly_columns: +date_range, +confirm_by, +confirmed_at
- _handle_assembly_create: sets confirm_by = now+3h when assigned_to_tg_id provided
- /api/assembly_schedule: staff confirms exact datetime → status→scheduled
  + gcal event create/update + bot notify manager "Лид закреплён 🎯"
- /api/measurement_schedule: same for measurers
- staff_clients: return date_range/confirm_by/confirmed_at per assembly,
  preferred_date/preferred_time_of_day per measurement

Frontend (staff_clients.js):
- Assembly cards: show date_range hint, confirm_by countdown timer
- "📞 Подтвердить дату после созвона" button (only when status=created, no scheduled_at)
- Measurement cards: show preferred_date from client, confirm button
- _openScheduleOverlay: datetime-local picker + note → POST assembly/measurement_schedule
  → reload client list on success

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 13:11:07 +03:00
wasrusgen
e8b9c68c5c feat: staff client list for assembler/measurer (#/master/clients)
- /api/staff_clients — returns clients grouped by client, filtered by role
  (assembler sees assemblies, measurer sees measurements, both if combined)
  Supports filter: active | done | all
- staff_clients.js — client list with status tags + detail card view
  (phone link, assembly cards → AssemblyDetailScreen, measurement cards)
- app.js — route #/master/clients, button "👥 Мои клиенты" for assembler+measurer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 13:05:16 +03:00
wasrusgen
21fd0ff3e5 feat: assembler dashboard, contracts module (Act №3), assembly rates
Frontend:
- assembler_dashboard.js — personal earnings screen for assemblers (#/master/dashboard)
- contracts.js — Act №3 preview + edit + SignRequest ПЭП (#/assembly/:id/contract)
- assembly_detail.js — add "📄 Акт сдачи-приёмки" button
- app.js — routes for #/master/dashboard and #/assembly/:id/contract

Backend:
- main.py — /api/assembler_earnings (fuzzy name match vs Excel)
- main.py — /api/contract_preview, /api/contract_save (Contracts sheet)
- main.py — _ensure_contracts_sheet(), _name_match_score()
- assembler_parser.py — fix tuple index out of range on short rows (2021 sheet)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 12:23:44 +03:00
wasrusgen
76fce9ec58 feat(analytics): assembler schedule parser + analytics screen
Backend:
- assembler_parser.py: parse Excel «Таблица занятости сборщиков»
  - Handles both row-order variants (2026: dates row1; 2025-: dates row2)
  - Extracts amount from end of cell text, supports compound "6030+20100"
  - aggregate(): by_assembler×month + by_month totals
  - In-memory cache with mtime invalidation
- main.py: /api/assembler_analytics — local file first, Drive fallback
  - LOCAL: /app/data/assembler_schedule.xlsx (mounted volume)
  - Config: ASSEMBLER_SCHEDULE_PATH env var override
- config.py: assembler_schedule_file_id for Drive fallback
- docker-compose.yml: /opt/zov-tech/data → /app/data:ro volume

Frontend:
- assembler_analytics.js: year filter, monthly table, assembler ranking
  with progress bars, per-order average, last-6-months breakdown
- app.js: route #/admin/assembler-analytics + "Аналитика" button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 09:44:34 +03:00
wasrusgen
12dec17ed1 fix(podbor): HTML format + sticky header + home button at report bottom
- _ai(): markdown→HTML fallback (**, *, _, `) when no HTML tags found
- podbor-header: position:sticky so back/home always visible while scrolling
- renderReport(): footer with "← Главное меню" + "+ Новый подбор" buttons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 09:26:07 +03:00
wasrusgen
3e7ae7764a feat(assembly): configurable assembly rates + admin panel
Backend:
- Sheet "Assembly_Rates": rules by assembler_tg_id + scope
- _resolve_rates(): priority matching (specific > wildcard)
- Default: client 10%, assembler 9% (1% margin)
- _calc_assembly_prices(): role-aware field set in detail API
- Endpoints: assembly_rates_list, assembly_rate_save, assembly_rate_delete
- Cache TTL 120s, auto-seeded default rule on first run

Frontend:
- assembly_detail.js: shows client rate %, assembler payout % (role-aware)
- admin_rates.js: list/add/edit/deactivate rules with live margin preview
- app.js: route #/admin/rates + "Ставки сборки" button in manager dashboard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 09:20:03 +03:00
wasrusgen
f473f1dc03 feat(podbor): copy report as plain text for messengers
- New button "📋 Скопировать текст" in report export panel
- _copyReportText(): formats structured text (brand, price, pros/cons, links)
- _stripHtml(): strips HTML tags for clean clipboard output
- Clipboard API with execCommand fallback for Telegram WebApp
- Button shows " Скопировано!" feedback for 2.2s

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 08:32:52 +03:00
wasrusgen
f1b7f71337 fix(podbor): HTML AI output + home button on all steps
- AI prompt: use HTML tags (b, em, br, li) instead of markdown
- renderReport: _ai() helper renders AI text as innerHTML (safe, backend-controlled)
- Header: added podbor-home button (top-right) → goes to main menu from any step
- After successful submit: show "← Вернуться в главное меню" button immediately
- Fixes: no way to leave podbor after result was received

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 08:02:09 +03:00
wasrusgen
3f1531f7ca feat: add MasterTools assembler cheat-sheets (#/master/tools)
- Rail spacing calculator (gap formula from Excel)
- Shelf holder calculator (step/drop formula from Excel)
- Interactive price list (70+ items, 9 sections, transport formula)
- Entry point button in staff screen (assembler only)
- Routes: #/master/tools, /rails, /shelves, /price

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:43:23 +03:00
wasrusgen
67ca6e4b26 fix: добавить @app.post('/api/managers_list') — пропустили FastAPI-роут
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-18 23:33:33 +03:00
wasrusgen
5ed11c00fa feat: заявка на замер — поиск по клиентам + передача менеджеру
Frontend (request.js):
- Поиск клиентов из списка менеджера (autocomplete dropdown)
  по имени или цифрам телефона, макс. 6 результатов
- Режимы: search → selected (карточка + редактируемый адрес)
  или → new (ручной ввод ФИО/тел/адрес)
- «Создать нового клиента» всегда в конце dropdown
- Выпадающий список замерщиков (existing)
- Новый select «Передать менеджеру» — передаёт заявку коллеге
- Platform.initData / Platform.initDataUnsafe вместо tg?.

Backend (main.py):
- _handle_managers_list: список всех менеджеров кроме себя
- _handle_measurement_request: поддержка target_manager_tg_id
  (заявка создаётся от имени целевого менеджера + уведомление)
- Роут managers_list добавлен в handlers dict

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-18 23:32:16 +03:00
wasrusgen
bd85b30aa5 feat: SignRequest — цифровая подпись акта сборки (ФЗ-63 ПЭП)
Backend:
- _handle_sign_request_create: генерирует 6-значный OTP (72ч TTL),
  отправляет клиенту в Telegram для code-режима
- _handle_sign_request_submit: canvas (PNG→PHOTOS_DIR), code (OTP-верификация),
  proxy (представитель), absent (без подписи + причина)
- Assemblies sheet: +sign_token, sign_token_expires_at, signed_via,
  signed_by_tg_id, signed_by_phone
- assembly_detail: возвращает signed_via, client_tg_id, signed_by_phone

Frontend:
- signrequest.js: overlay-bottom-sheet, 4 таба (canvas/code/proxy/absent),
  canvas с touch-events, OTP-ввод, submit с валидацией
- assembly_detail.js: кнопка «Подписать акт» если не подписано,
  блок подписи с методом (VIA_LABELS) и перезагрузкой после подписания
- styles.css: .signreq-* компоненты

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-18 23:12:34 +03:00
wasrusgen
ef51ebcb85 feat: platform.js — адаптер Telegram WebApp для миграции на VK Max
- platform.js: глобальный Platform (initData, initDataUnsafe, startParam,
  colorScheme, ready, expand, haptic, showAlert, onThemeChange, enableClosingConfirmation)
- tg остаётся глобальным для backward-совместимости модулей
- app.js: setupTelegram() и haptic() делегируют в Platform,
  все tg?.initData/initDataUnsafe → Platform.initData/initDataUnsafe
- index.html: platform.js грузится первым (перед icons.js)
- VK Max Phase 2: заменить platform.js, остальной код не трогать

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-18 18:06:03 +03:00
wasrusgen
cb4bbfce70 docs: стратегия платформ — Telegram сейчас, VK Max отдельно после
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:40:14 +03:00
wasrusgen
6f846603a9 feat: kitchen_price в сборках + срочный замер push
- main.py: kitchen_price в assembly_list + assembly_detail
- main.py: /api/assembly_set_kitchen_price — менеджер задаёт стоимость кухни
- main.py: measurement urgent=True → bot push замерщику(ам)
- sheets.py: find_users_by_role(role) — поиск пользователей по роли
- assembly_detail.js: показывает стоимость кухни + стоимость сборки (9%)
- index.html: версии → v20260518m

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:38:44 +03:00
wasrusgen
7a47739e77 docs: мультиплатформа VK Max, ПЭП в договоре, агент Юрий в команду
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:26:07 +03:00
wasrusgen
c3e09effdb docs: SignRequest — два метода подписи: canvas (палец) + code (Telegram/SMS)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:21:31 +03:00
wasrusgen
4430340038 docs: SignRequest — платформенный модуль подписи для актов, водителей, удалённых клиентов
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 17:20:51 +03:00
wasrusgen
8cf60887bc docs: ROADMAP P2б — договоры, дашборд сборщика, акты, прайс доп.работ
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 16:51:11 +03:00
wasrusgen
4533e48167 docs: business_rules — стоимость сборки 10%, выплата сборщику 9% от кухни
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 16:00:21 +03:00
wasrusgen
6ba6489873 docs: ROADMAP — P2 закрыт, калькулятор отложен
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 15:37:28 +03:00
wasrusgen
042dc1a5d3 feat: детальная карточка сборки + цена замера везде
- assembly_detail.js: экран #/c/assembly/:id — статус, адрес, фото, подпись, gcal
- orders.js: сборки кликабельны → #/c/assembly/:id
- app.js: маршрут #/c/assembly/
- selfmeasure.js: цена 2500₽ + 40₽/км за КАД на шаге 1 и шаге 5
- cabinet.js: цена под кнопкой самозамера

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 15:35:21 +03:00
wasrusgen
b75f24e4d7 feat: история заказов #/c/orders — таймлайн подборов и сборок
- orders.js: единый таймлайн proposal_list + assembly_list, сортировка по дате
- cabinet.js: кнопка «📋 История заказов» → #/c/orders
- app.js: маршрут #/c/orders, версия l
- styles.css: классы orders-timeline, .block, .block-head, .assembly-card
- memory/business_rules.md: замер 2500₽ + 40₽/км за КАД СПб

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 15:19:20 +03:00
wasrusgen
e71ac3a5a8 fix: selfmeasure — читаемое сообщение при HTTP 4xx/5xx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:49:53 +03:00
wasrusgen
78e332dd95 feat: самозамер #/c/selfmeasure — 5-шаговый мастер для клиента
- selfmeasure.js: тип кухни (SVG-карточки) → стены → коммуникации → фото → контакт+отправка
- cabinet.js: кнопка «📐 Самозамер кухни» → #/c/selfmeasure
- app.js: маршрут #/c/selfmeasure, guard _hashListenerAdded
- index.html: подключение selfmeasure.js v20260518k
- backend: /api/self_measure_submit (hot-patch на VPS)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:40:50 +03:00
wasrusgen
ea04e042df feat: staging-окружение (Docker Compose + Caddy + deploy-script)
docker-compose.staging.yml — backend-staging на порту 8001.
.env.staging.example — шаблон с отдельным SHEET_ID.
Caddyfile.staging.snippet — staging.api.wasrusgen1.pro.
scripts/deploy-staging.sh — один скрипт для деплоя staging.
app.js: BACKEND_URL читается из ?backend= параметра URL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:22:01 +03:00
wasrusgen
6616d48c0a test: mock-фикстура карточки клиента в smoke-тесте
page.route() перехватывает /api/clients и возвращает тестового клиента.
Карточка клиента теперь открывается и проверяется без реальных данных.
17 чеков, 0 пропущено.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:43:09 +03:00
wasrusgen
7df9cc3901 refactor: аудит роутера app.js — устранены 3 edge case
1. Дублирование: init() теперь вызывает routeByHash() вместо копии логики.
   #/master, #/me, #/c/cabinet теперь работают при прямом переходе по ссылке.
2. Множественные hashchange listeners: guard _hashListenerAdded.
3. #/picker → #/c/proposal в cabinet.js и me.js (неверный роут).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:39:23 +03:00
wasrusgen
c773adf05e fix: Content-Type: application/json во всех fetch-хелперах
measurements, assembly, request, me, inbox, proposals —
6 модулей, 6 хелперов (_fetchWithTimeout / apiFetch / _api).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:35:20 +03:00
wasrusgen
e934576e5c feat: клиентский кабинет #/c/cabinet
cabinet.js — дашборд клиента: профиль, менеджер, подборы, сборки.
Параллельная загрузка: /api/me + /api/proposal_list + /api/assembly_list.
Backend: assembly_list теперь поддерживает роль client (client_tg_id фильтр).
me.js: кнопка «Мой кабинет» → #/c/cabinet для роли client.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:25:49 +03:00
wasrusgen
f397747a34 ci: UI Playwright smoke после деплоя Pages (workflow_run)
Тригер: Deploy MiniApp to GitHub Pages → completed + success.
Скриншот сохраняется как артефакт при провале.
workflow_dispatch с опциональным SMOKE_URL для ручного запуска.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:33:35 +03:00
wasrusgen
f7a1c3e4c0 test: smoke-тест на локальном сервере (npx serve), убран chicken-and-egg
Сервер поднимается через spawn + HTTP polling.
SMOKE_URL=... для тестирования произвольного URL.
15 чеков: +inbox, +me, +titles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:30:11 +03:00
wasrusgen
864e70f39b test: добавлены проверки #/inbox и #/me в ui_smoke.js
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:24:50 +03:00
wasrusgen
3741657fb6 feat: экран #/inbox — входящие задачи менеджера
InboxScreen.mount() — список замеров без решения по подбору.
Три действия: начать подбор / отложить / не нужен.
Роутинг #/inbox добавлен в routeByHash() и init().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:22:07 +03:00
wasrusgen
bdbdf4b259 feat: экран #/me — Мой профиль для всех ролей
manager: статус доступа, салон, быстрые переходы
staff: роли-чипы, кнопки на замеры/сборки
client: менеджер, кнопки подбора и сборок

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:17:52 +03:00
wasrusgen
be79f5447b docs: feature-status — #/master реализован 2026-05-18 12:08:33 +03:00
wasrusgen
b43087a4b4 feat: маршрут #/master — экран входящих задач замерщика/сборщика
- routeByHash: #/master → renderStaff(window.__zovMe)
- таймаут 15с на fetch в renderStaff и renderStaffAssemblies
- app.js v=20260518g

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:08:20 +03:00
wasrusgen
64292cef8e fix: права доступа по ролям — сборщик/клиент
- measurement_detail: любой мастер (measurer+assembler) видит фото замера
- assembly_list: клиент видит все свои сборки (по client_tg_id)
- assembly_detail: клиент видит детальную карточку сборки

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 11:59:16 +03:00
wasrusgen
4386779ea6 docs: структура ролей и взаимодействий (ROLES.md)
4 роли: manager / measurer / assembler / client
Цикл сделки, доступ по экранам, правило совместного подбора техники.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 11:42:38 +03:00
wasrusgen
542f96aaa0 docs: экономия токенов — правило краткости в CLAUDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 11:18:27 +03:00
wasrusgen
2d0246a5b5 feat: система идентификации агентов — бейдж в каждом ответе
Каждый агент обязан начинать ответ с бейджа роли:
🤖 КООРДИНАТОР / 🔧 DEV / ⚙️ DEVOPS / 🎨 DESIGN / 🧩 FEATURE / 🧪 TEST / 🔍 REVIEW

Правило прописано в CLAUDE.md и в каждом агент-файле.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 11:17:58 +03:00
wasrusgen
7b874e0195 feat: система активных агентов — ROADMAP, статусы, команда /project:review
- ROADMAP.md — единый роадмап продукта (реализовано / в работе / бэклог)
- agents/dev-status.md — состояние кода, долг, следующий шаг
- agents/devops-status.md — VPS, блокеры, инфра-бэклог
- agents/design-status.md — компоненты, нереализованные экраны
- agents/feature-status.md — таблица функционала, приоритизированный бэклог
- agents/test-status.md — покрытие, пробелы, следующий шаг
- .claude/commands/review.md — мастер-команда: сводный отчёт по всем агентам
- Все агенты обновлены: читают и пишут свой status.md в начале/конце работы

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 11:16:27 +03:00
wasrusgen
ff35dd769f ci: добавить pre-push hook (CSS-линтер + UI Playwright)
Блокирует push при JS-ошибках в интерфейсе или CSS-нарушениях.
API-тесты в хук не включены — зависят от VPS/Drive, запускать вручную.
Активируется через: git config core.hooksPath .githooks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:30:36 +03:00
wasrusgen
0fb0597b8d fix: добавить 15-секундный таймаут fetch во все модули (measurements, assembly, proposals, request)
Кнопки больше не зависают бесконечно при медленном или недоступном бэкенде.
AbortController + дружелюбное сообщение «Сервер не отвечает — попробуйте ещё раз».

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:27:53 +03:00
wasrusgen
40e2275949 test: добавить Playwright UI smoke-тест (10 проверок JS-ошибок по экранам)
- tests/ui_smoke.js — headless Chromium с mock Telegram.WebApp, проверяет
  загрузку, список клиентов, форму нового клиента, замеры, сборки
- package.json — playwright devDependency
- .claude/commands/test.md — добавлен Шаг 4 (UI Playwright) в агент тестировщика

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 08:53:58 +03:00
wasrusgen
6f74d05184 fix: таймаут 15с на все fetch в clients.js — кнопки больше не висят
- _fetchWithTimeout() — единый fetch с AbortController
- saveClientNote, fetchClientNote, fetchClients, fetchMeasurements
  теперь через таймаут вместо бесконечного ожидания
- При таймауте показывает 'Сервер не отвечает — попробуйте ещё раз'
- Версия clients.js: 20260518e
2026-05-18 08:35:42 +03:00
wasrusgen
a9aa704950 fix: добавить escAttr — ReferenceError в карточке клиента
escAttr использовалась в 11 местах (карта, форма редактирования)
но не была объявлена в clients.js — отсюда пустая карточка.
Версия clients.js: 20260518d
2026-05-18 08:31:27 +03:00
wasrusgen
ad6c8b9205 feat: добавить команды агентов — dev, devops, design, feature, test
/project:dev     — разработчик (Python/JS/бот)
/project:devops  — деплой и обслуживание VPS
/project:design  — CSS, темы, WCAG, open-design
/project:feature — новый функционал, флоу, роутинг
/project:test    — тестировщик (все 3 теста + сводный отчёт)
2026-05-18 08:29:43 +03:00