О проекте
Команда: Tessera
Кейс HackAlem.ai: Логистика — Электрокомплект · ekt.kz
Стадия: Прототип
Задача кейса: Автоматический расчёт заказов поставщикам для пополнения склада, с утверждением менеджером
Суть
Рабочее место менеджера закупок: импорт XLSX с продажами, остатками и поставками в пути, детерминированный прогноз спроса и расчёт заказов с группировкой по поставщикам, правкой количества и утверждением менеджером.
Как устроено
XLSX и manifest загружаются в приватное S3, проверяются (SHA-256, нормализация, отчёт качества) и публикуются как неизменяемая версия набора данных в PostgreSQL. Фоновые задачи Trigger.dev (validate-import, calculate-procurement) считают прогноз с сезонностью, устойчивым трендом, stockout-коррекцией и отделением разовых продаж, затем заказ: потребность на срок поставки и период пересмотра плюс страховой запас, минус свободный остаток и поставки в пути, с округлением до шага. Количества считаются без LLM: модель OpenAI/NVIDIA только выбирает ссылки на проверенные факты, при сбое используется шаблонное объяснение. По README интерфейс пока работает на синтетическом демо и не подключён к серверному расчёту.
Ключевые решения
- детерминированный прогноз спроса с сезонностью и трендом
- stockout-коррекция
- safety stock / review period
- Trigger.dev фоновые задачи
- Drizzle ORM
- verified-fact LLM explanations
- XLSX-импорт с manifest и SHA-256
Особенности
LLM не генерирует текст напрямую: он выбирает ссылки на разрешённые факты, а приложение собирает объяснение из исходных данных. Намерения отправки задач хранятся в PostgreSQL, отдельный восстановитель повторяет недоставленные. Интеграционные тесты запускают настоящий временный PostgreSQL через embedded-postgres. В README честно описано, что уже реализовано, а что нет.
Стек
TypeScript · Next.js 16 · React 19 · Tailwind CSS 4 · shadcn/ui · Zod · PostgreSQL · Drizzle ORM · AWS S3 · Clerk · Liveblocks · Trigger.dev · Docker
Модели
OpenAI Responses API (модель через OPENAI_MODEL) · NVIDIA nemotron-3-nano-30b-a3b (опционально)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-86eb72c7-tessera.
README
README.mdTessera — рабочее место менеджера закупок
Проект хакатона HACKALEM AI по кейсу ТОО «Электрокомплект»: подготовка обоснованных заказов для пополнения склада.
Статус на 23.09.2026: реализованы демонстрационный интерфейс, серверная модель данных, XLSX-импорт, детерминированные прогноз/пополнение и фоновые задачи Trigger.dev. Перед публикацией коммита
8979ed6прошли 215 тестов, TypeScript, ESLint и production-сборка. Интерфейс пока не подключён к серверному расчётному сценарию; живые облачные интеграции не проверены. Демо работает на синтетических данных без аккаунтов внешних сервисов.
Старый маршрут /workspace сохранён для совместимости; основной адрес — /.
Быстрый маршрут для жюри: установка → / → сценарии проверки.
1. Название проекта
Tessera — рабочее название решения для поддержки менеджера закупок. Исходный кейс и требования партнёра: techtask/TECHTASK.md.
2. Какую проблему решаем и для кого
Менеджеру закупок приходится сводить продажи, остатки, товары в пути и условия поставщиков из нескольких Excel-файлов. Простое усреднение продаж может завысить потребность из-за разового крупного заказа или занизить её из-за периода отсутствия товара.
Tessera проектируется как единое рабочее место: проверить качество исходных данных, получить объяснимую рекомендацию по каждому артикулу, сгруппировать позиции по поставщикам и оставить окончательное решение человеку. Целевая аудитория — менеджеры закупок и специалисты по планированию складских запасов. Экономия времени и точность прогноза пока не измерялись.
3. Что реализовано
| Компонент | Возможности текущей версии |
|---|---|
| Рабочее место | / без параметров показывает синтетическое демо с локальными правками и предпросмотром. /projects и /?projectId=UUID — защищённый путь к реальному проекту; его UI и интеграционная приёмка продолжаются. Демо-утверждение не создаёт запись в БД. |
| Авторизация | Страницы входа/регистрации Clerk, серверная проверка сессии и проверка владельца в сервисах. Без настроенного Clerk доступно демо, но API закрыт ответом 503. |
| Данные и хранение | PostgreSQL, SQL-миграции, Drizzle-схема и репозитории: проекты, источники, попытки импорта, неизменяемые версии наборов, запуски и рекомендации. Модель проверки и утверждения есть, но производственный сценарий ещё не подключён. Проверяются принадлежность проекту, атомарность и повторные запросы. |
| Импорт XLSX | Проверка manifest — описания источников и колонок; SHA-256; ограниченный разбор XLSX/XML; нормализация; отчёт качества с происхождением строк. CLI для локальной проверки и генератор синтетического примера. Серверная публикация поддержанных данных выполняется транзакционно. |
| API проектов и загрузки | Проекты владельца, подписанный PUT в приватное S3, подтверждение через HEAD, попытки исправления manifest и списки наборов. Финализация сохраняет намерение фоновой проверки; задача сверяет байты, формирует приватный отчёт и атомарно публикует поддержанный набор. |
| Детерминированный расчёт | Прогноз с сезонностью, устойчивым трендом, stockout-коррекцией и обработкой разовых продаж; заказ с учётом свободного остатка, поставок в пути, срока поставки, периода пересмотра и страховки. Количества и числовое обоснование рассчитываются без ИИ. |
| Фоновые задачи и API запусков | Отдельные задачи calculate-procurement и validate-import; устойчивое намерение отправки в PostgreSQL, ограниченные повторы, история запусков, отмена и постраничное чтение сохранённых рекомендаций. Восстановитель запускается отдельно от веб-сервера. |
| ИИ и статусы | Серверные адаптеры OpenAI/NVIDIA с проверкой ответов и шаблонным резервным объяснением; компоненты доступа/публикации статусов Liveblocks и контроллер обновлений. Их подключение к реальному расчётному сценарию не завершено. |
Это частичная реализация, а не заявление о выполнении всех требований кейса. Подробный статус: трекер прогресса.
4. Как работает решение
Пользовательский сценарий
Целевой путь: файлы → проверка и сопоставление → версия данных → расчёт → рекомендации по поставщикам → правки менеджера → утверждение → экспорт.
Сейчас доступны три отдельных способа проверки:
- Интерфейс: открыть готовый синтетический результат, изучить обоснования, изменить количество с причиной, проверить поставщиков и утвердить локальный снимок. Кнопка расчёта имитирует этапы и использует заранее подготовленные рекомендации.
- Импорт: передать локальный XLSX и manifest в CLI. Проверяются структура и контрольная сумма; результат —
ready,needs_mappingилиinvalidи диагностический отчёт. CLI не записывает данные в БД и не отправляет файлы внешним сервисам. - Серверный расчёт: выполнить
npm run test:jobs. Синтетический интеграционный тест публикует набор в настоящую временную PostgreSQL, создаёт диагностический запуск, выполняет детерминированные этапы и читает сохранённые рекомендации. Повтор не создаёт дубликаты. Это проверка серверных сервисов, не браузерного пути или живого Trigger.
Серверный путь импорта: сессия Clerk → проект владельца → подписанный PUT → загрузка в S3 → finalize → сохранённые попытка и намерение отправки → validate-import → отчёт и, при успешной проверке, версия данных. Расчёт запускается отдельным явным запросом; импорт сам его не запускает.
Принцип объяснимости
Количества определяет детерминированный алгоритм, не LLM. Ядро прогноза отделяет регулярный спрос от разовых продаж, учитывает подтверждённую экспозицию, интервалы отсутствия товара, сезонность и устойчивый тренд. Неизвестные данные не превращаются в нули; ограничения отражаются в предупреждениях и полноте результата.
Ядро пополнения считает потребность на срок поставки и период пересмотра, добавляет прогноз страховки, вычитает свободный остаток и допустимые поставки в пути, затем округляет вверх до разрешённого шага. Исходные вклады сохраняются в обосновании. Методика и ограничения: прогноз, пополнение.
В существующих ИИ-адаптерах модель выбирает ссылки на разрешённые факты и предупреждения. Приложение проверяет ссылки и формирует текст из исходных фактов. При ошибке провайдера используется шаблонное объяснение; модель не утверждает и не отправляет заказ.
5. Технологии
| Область | Используется в коде |
|---|---|
| Языки | TypeScript, SQL, JavaScript для части тестов и инструментов |
| Приложение | Next.js 16.3.6, App Router, React 19.2.8 |
| Интерфейс | Tailwind CSS 4, shadcn/ui на Base UI, Lucide |
| Контракты | Zod; канонические десятичные строки в DTO, numeric(30,8) в PostgreSQL |
| Данные | PostgreSQL, Drizzle ORM, pg; явные SQL-миграции |
| Файлы | AWS SDK v3, приватное S3; yauzl и fast-xml-parser для XLSX, ExcelJS для генерации тестовой книги |
| Доступ | Clerk и русская локализация |
| ИИ | OpenAI Responses API и NVIDIA Chat Completions API через серверный fetch |
| Обновления | Liveblocks SDK и локальный контроллер статусов; интеграция со сквозным сценарием ожидается |
| Фоновые задачи | Trigger.dev SDK/CLI 4.6.4, две очереди задач, устойчивые намерения отправки в PostgreSQL |
| Проверки | node:test, TypeScript, ESLint; embedded-postgres запускает настоящий временный PostgreSQL для тестов |
AI-модели не зафиксированы по умолчанию: идентификаторы задаются через OPENAI_MODEL и NVIDIA_MODEL. Для nvidia/nemotron-3-nano-30b-a3b в адаптере предусмотрена отдельная настройка запроса; это не подтверждение использования модели в развёрнутом приложении. Для локального демо модели и API-ключи не требуются.
Живой smoke Trigger/S3/RDS требует аккаунтов и не заявляется. AWS RDS выбран как целевое размещение PostgreSQL; облачные ресурсы проектом не создаются автоматически.
Полный состав и зафиксированные версии зависимостей: package.json, package-lock.json.
6. Архитектура проекта
Браузер / ──→ демо-данные и локальная проверка заказа
(пока отдельно от серверного API)
HTTP /api/* ──→ Clerk + проверка владельца + валидация
├─→ PostgreSQL: попытки, версии данных, запуски, dispatch
└─→ приватное S3: загрузка исходных файлов
Сохранённый dispatch ──→ Trigger.dev
├─→ validate-import ──→ S3 → проверка/нормализация → приватный отчёт
│ └─→ атомарная версия в PostgreSQL
└─→ calculate-procurement ──→ прогноз → пополнение → рекомендации в PostgreSQL
Восстановитель ──→ повтор недоставленных намерений и подтверждение отмен
HTTP /api/runs/* ──→ сохранённые состояния и рекомендации PostgreSQL
Локальный XLSX + manifest ──→ CLI → отчёт без записи в БД
ИИ-адаптеры и Liveblocks ──→ отдельные модули; сквозное подключение ожидается
| Каталог | Ответственность |
|---|---|
app/, proxy.ts | Страницы, авторизация, тонкие HTTP-обработчики |
components/editor/, components/procurement/, components/ui/ | Оболочка, предметный интерфейс и UI-примитивы |
lib/procurement/ | Синтетические данные и состояние проверки заказа |
lib/contracts/ | Схемы DTO, статусов, входных данных и ошибок |
lib/domain/forecast/, lib/domain/replenishment/ | Чистые функции прогноза и расчёта заказа |
lib/server/db/, drizzle/ | Схема PostgreSQL, репозитории, миграции |
lib/server/imports/ | Разбор, нормализация, публикация, жизненный цикл загрузки |
lib/server/projects.ts, lib/server/project-data-*.ts | Сервисы и HTTP-граница проектов/импортов |
lib/server/runs*.ts, lib/server/calculation-execution.ts | API запусков, этапы и атомарное сохранение результата |
trigger/, trigger.config.ts, lib/server/dispatch.ts | Фоновые задачи, отправка, повторы и отмена |
lib/ai/, lib/realtime/, hooks/ | Адаптеры объяснений и статусов |
scripts/, tests/ | Миграции, генератор примера, CLI и проверки |
context/, techtask/ | Архитектура, спецификации, прогресс и задание партнёра |
PostgreSQL хранит бизнес-состояние и остаётся источником истины, S3 — исходные объекты и приватные отчёты. ID выполнения Trigger не заменяет ID бизнес-операции. Версии опубликованных данных неизменяемы. Проверка доступа выполняется рядом с ресурсом, а не только в Proxy. Подробнее: архитектурный контекст, импорт, API.
7. Установка и запуск
Требования
- Git, Node.js 24 и npm. Локальная сборка ранее проверялась на Node.js 24.19.0/macOS arm64; другие окружения требуют отдельной проверки.
- Интернет для установки пакетов; приложение использует
next/font/google, поэтому загрузка шрифтов при сборке также может требовать сети. - Для демо и CLI не нужны PostgreSQL, S3, Clerk или платные AI-сервисы. Тесты БД самостоятельно запускают временный PostgreSQL.
Шаг 1. Получить код
git clone --branch 01-agent https://github.com/BAITC-Hacks/hack-86eb72c7-tessera.git tessera
cd tessera
npm ci
Шаг 2. Проверить зафиксированные зависимости
Зависимости данных, импорта и Trigger закреплены в package.json и package-lock.json: достаточно npm ci, дополнительных установок --no-save нет. Если политика npm блокирует install scripts, для локальных PostgreSQL-тестов после просмотра скрипта восстановите штатные ссылки пакета:
(cd node_modules/@embedded-postgres/linux-x64 && node scripts/hydrate-symlinks.js)
Это настройка Linux x64 тестового пакета, не создание облачной базы данных.
Шаг 3. Настроить окружение и открыть демо
Команды приведены для Bash. Существующий файл с ключами не перезаписывается:
test -f .env.local || cp .env.example .env.local
npm run dev
Открыть http://localhost:3000/ для синтетического демо. Для своего проекта настройте Clerk/PostgreSQL/S3, войдите, откройте /projects, затем /?projectId=UUID. Для демо внешние ключи оставьте пустыми. Не выполняйте вызовы OpenAI без отдельного разрешения пользователя.
Проверка production-сборки и запуск сервера (Webpack проверен в окружении B; стандартный Turbopack ранее ограничивался запуском процессов/портов):
npx next build --webpack
npm start
Локальный запуск в Docker
Docker Desktop должен быть запущен. Файлы .env.local и .env.docker исключены из Git и Docker-образа. Для новой копии один раз создайте отдельный пароль локальной базы; существующие файлы не перезаписываются:
python3 - <<'PY'
from pathlib import Path
import secrets
local = Path('.env.local')
if not local.exists():
local.write_text(Path('.env.example').read_text())
local.chmod(0o600)
docker = Path('.env.docker')
if not docker.exists():
docker.write_text('TESSERA_DB_PASSWORD=' + secrets.token_hex(24) + '\nTESSERA_PORT=3000\n')
docker.chmod(0o600)
PY
docker compose -p tessera-local --env-file .env.local --env-file .env.docker up --build -d
Открыть http://localhost:3000/. Compose ждёт готовности PostgreSQL18, применяет миграции отдельным контейнером, затем запускает Next.js от пользователя node. Порт сайта опубликован только на127.0.0.1, порт БД наружу не опубликован. Данные БД сохраняются в отдельном томе. Если3000 занят, измените только TESSERA_PORT в .env.docker.
Clerk без ключей остаётся недоступным; синтетическое демо работает. Только публичный NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY передаётся при сборке, секреты — во время запуска. После изменения публичного ключа повторите команду с --build. Этот запуск сам по себе не разворачивает workers Trigger.dev, S3 или Clerk и не разрешает вызовы OpenAI.
docker compose -p tessera-local --env-file .env.local --env-file .env.docker ps -a
docker compose -p tessera-local --env-file .env.local --env-file .env.docker stop
Остановка сохраняет базу; не удаляйте том при обычном перезапуске.
Исходники партнёра в этой локальной копии сохранены в исключённом из Git каталоге .agent-loop/source-data: оба ZIP и все 12 Excel-книг, 14 листов. Контрольные суммы всех файлов проверены также внутри контейнера. Compose подключает каталог только для чтения как /app/local-source-data; в образ и публичные файлы сайта эти данные не входят. В новой копии репозитория исходники нужно передать отдельно.
Состояние набора — preserved_unmapped: сохранение файлов не является публикацией данных для расчёта. В локальной БД пока нет проектов, импортов и версий набора. Сопоставление полей, проверка бизнес-семантики и полный путь импорта ещё не выполнены. Детальная сверка: инвентаризация данных.
Серверные интеграции вне Docker
Для работы API проектов заполните Clerk-ключи, задайте DATABASE_URL доступной PostgreSQL и примените миграции до работы с API:
node --env-file=.env.local --conditions=react-server --import tsx scripts/migrate-data-model.ts
Миграции не выполняются автоматически при сборке. Проверки БД проведены на PostgreSQL 18.4. Для импорта через HTTP дополнительно нужны приватный bucket, настройки S3 и разрешённый CORS для вашего приложения; облачная конфигурация здесь не разворачивается.
Переменные из .env.example | Назначение |
|---|---|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY | Вход и проверенная серверная сессия |
NEXT_PUBLIC_CLERK_*_URL | Маршруты входа/регистрации и возврата; для перехода после входа можно задать fallback / |
DATABASE_URL | Строка подключения PostgreSQL |
S3_BUCKET, S3_REGION | Хранилище загрузок; обязательны для API импорта |
S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY | Пара серверных ключей; если оба отсутствуют, SDK использует стандартную цепочку учётных данных окружения |
S3_ENDPOINT | Необязательный endpoint; совместимость конкретного S3-совместимого сервиса отдельно не проверена |
OPENAI_API_KEY, OPENAI_MODEL, OPENAI_BASE_URL | Настройка адаптера; допустимый базовый адрес в коде — https://api.openai.com/v1 |
NVIDIA_API_KEY, NVIDIA_MODEL, NVIDIA_BASE_URL | Настройка адаптера; допустимый адрес — https://integrate.api.nvidia.com/v1 |
LIVEBLOCKS_SECRET_KEY | Серверный адаптер Liveblocks |
TRIGGER_SECRET_KEY, TRIGGER_PROJECT_REF | Серверный доступ Trigger и идентификатор проекта для задач |
RUN_CURSOR_SECRET | Отдельный стабильный секрет подписи курсоров API расчётов, не менее 32 символов |
Одного заполнения переменных AI/Liveblocks/Trigger недостаточно для подключения их к демо. OpenAI live-вызовы сейчас запрещены. Секреты храните только в окружении или .env.local, не в Git и не в клиентских NEXT_PUBLIC_* переменных.
Фоновые задачи и восстановление
Примените миграции, настройте PostgreSQL/S3/Clerk и переменные Trigger из таблицы выше. Next.js и задачи Trigger запускаются отдельно. Для локального CLI можно явно загрузить .env.local:
node --env-file=.env.local node_modules/trigger.dev/dist/esm/index.js dev
# Развёртывание — только в заранее настроенном аккаунте и среде:
# node --env-file=.env.local node_modules/trigger.dev/dist/esm/index.js deploy
Команды выше обращаются напрямую к локальному CLI установленной версии. Для развёрнутых задач задайте серверные секреты в среде Trigger отдельно; локальная .env.local сама по себе не настраивает облако. Не передавайте секреты через аргументы команд или Git.
Восстановитель обрабатывает одну ограниченную партию и завершается:
node --env-file=.env.local --conditions=react-server --import tsx scripts/recover-dispatch.ts
# При уже настроенном окружении: npm run jobs:recover
Запускайте его при старте и регулярно отдельным планировщиком, например раз в минуту. Это не автоматический перерасчёт: процесс доставляет уже сохранённые намерения и подтверждает отмену. Без планировщика нельзя полагаться на восстановление после остановки HTTP. Детали: отправка и отмена.
Начальные лимиты для синтетической проверки: 600 секунд на задачу, по 2 параллельных выполнения каждой очереди, до 3 попыток задачи и до 5 попыток отправки. Импорт ограничен 8 уникальными объектами и 100 MiB суммарно, при 25 MiB на объект и дополнительных пределах парсера. Это не согласованная промышленная политика.
8. Как проверить решение
Сценарий А: рабочее место менеджера без ключей
- Откройте
/: начальное состояние — «Расчёт готов». На широком экране поставщик выбирается слева от таблицы, на телефоне — селектором; четыре иконки внизу открывают закупки, данные, историю и параметры. На экране обозначено: «Демо». - Проверьте две группы поставщиков и раскройте обоснование позиции: показаны спрос, сезонность, тренд, отсутствие товара, остатки и товары в пути. Это демонстрационные показатели, не результат расчёта по вашему файлу.
- Измените количество в колонке «К заказу» с учётом шага позиции, заполните «Причина правки», нажмите «Сохранить». Исходная рекомендация остаётся отдельной.
- Отметьте «Проверено» у каждого поставщика. Нажмите «Утвердить», затем «Подтвердить».
- Откройте «Предпросмотр заказа». Ожидается предпросмотр утверждённых строк с вашими правками, без скачивания и отправки.
- Обновите страницу: правки сбросятся. Через «Параметры → Сценарий просмотра» можно отдельно проверить состояния «Ошибки данных», «Связь потеряна» и «ИИ-пояснение недоступно».
Сценарий Б: настоящий разбор синтетического XLSX
В новом терминале из корня репозитория:
DEMO_DIR=$(mktemp -d)
node --conditions=react-server --import tsx scripts/generate-import-fixture.ts "$DEMO_DIR"
node --conditions=react-server --import tsx scripts/import-dataset.ts \
--manifest "$DEMO_DIR/manifest.json" \
"20000000-0000-4000-8000-000000000001=$DEMO_DIR/synthetic.xlsx"
Ожидаемый результат: status: "ready", checkedRows: 37, acceptedRows: 37, rejectedRows: 0, unresolvedRows: 0, код выхода 0.
Создаётся книга с 12 ролями источников: артикул 000123, обычные продажи и крупная разовая продажа, месячная история, остаток 0, поставка в пути, явный интервал отсутствия товара, сезонные индексы и справочники. Контрольная сумма рассчитывается для сгенерированного файла.
Это dry-run: отчёт доказывает работу парсера и нормализации, но не точность прогноза, не сохранение в БД и не публикацию полного набора. В частности, материальная ведомость принимается в диагностический черновик, но ещё не поддерживается SQL-публикацией. ready здесь означает структурную проверку, не готовность всех алгоритмов.
Автоматические проверки
npm run test:auth
npm run test:workspace
npm run test:ai
npm run test:realtime
npm run test:forecast
npm run test:replenishment
npm run test:jobs
node --conditions=react-server --import tsx --test --test-concurrency=1 \
tests/contracts/*.test.ts tests/server/*.test.ts \
tests/imports/*.test.mjs tests/imports/*.test.ts tests/project-data/*.test.ts
npx next typegen
npx tsc --noEmit
npm run lint
npm run build
Не запускайте несколько наборов PostgreSQL-тестов одновременно. Тестам нужны возможность запуска локальных процессов и свободные TCP-порты; запускайте их от обычного пользователя, не root.
Перед публикацией 8979ed6 на 23.09.2026 прошли 215/215 тестов, tsc, ESLint и production-сборка. Проверены установленные зависимости (npm ls --depth=0) и согласованность lock-файла (npm ci --dry-run --ignore-scripts). Распределение тестов:
| Набор | Пройдено |
|---|---|
| Прогноз | 40 |
| Пополнение | 70 |
| Контракты, сервер, миграции, HTTP и хранилище | 38 |
| Парсер, нормализация и публикация XLSX | 23 |
| Авторизация, UI-состояние, ИИ и realtime | 31 |
| Расчётные задачи, импорт, dispatch и API-сервисы запусков | 13 |
CLI-пример (37/37 строк), /workspace → 200 и API без Clerk → 503 AUTH_UNAVAILABLE проверялись при предыдущей приёмке импорта; новый браузерный прогон для задач Trigger не заявляется.
Если на Linux x64 embedded-postgres сообщает об отсутствии libpq.so.5 после пропущенного install-скрипта, восстановите штатные символические ссылки пакета и повторите тесты:
(cd node_modules/@embedded-postgres/linux-x64 && node scripts/hydrate-symlinks.js)
Тесты покрывают контракты, изоляцию владельцев, миграции, атомарную публикацию, повторы, ошибки XLSX, HTTP-границы, локальную проверку заказа и резервное поведение адаптеров. PostgreSQL настоящий временный; S3, транспорт Trigger, Clerk-сессии и ответы AI в тестах имитируются. Это не браузерная E2E-проверка и не проверка живых облачных аккаунтов.
9. Данные и интеграции
Источники данных
Поддерживаемые роли manifest: продажи по операциям, месячные продажи, остатки, поставки в пути, интервалы отсутствия товара, поставщики, сроки поставки, категории, прогноз прироста, сезонность, сопоставление товаров и материальная ведомость.
В текущем checkout используются синтетические данные из lib/procurement/mock-workspace.ts и генератора scripts/generate-import-fixture.ts. Они независимы друг от друга. Исходные XLSX/ZIP партнёра не входят в публикуемую версию; инвентаризация — исследовательский документ, не доказательство поддержки всех реальных файлов.
Артикулы сохраняются как строки с ведущими нулями; отсутствие данных не подменяется нулём. Формулы и макросы не исполняются, внешние связи и опасные архивные структуры отклоняются. Политика обезличивания реальных клиентских данных требует отдельного согласования: синтетические anon_* не подтверждают анонимность чужой выгрузки. Не загружайте персональные данные в демонстрацию.
HTTP API
Все маршруты требуют проверенную сессию и доступ владельца. Ответы имеют форму { data: ... } либо { error: { code, message, requestId, ... } }.
| Метод и путь | Назначение |
|---|---|
GET /api/projects, POST /api/projects | Список и создание проектов |
GET /api/projects/:projectId, PATCH /api/projects/:projectId | Чтение, переименование, архивирование |
GET /api/projects/:projectId/imports, POST /api/projects/:projectId/imports | Список импортов, создание попытки и подписанной загрузки |
GET /api/projects/:projectId/imports/:importId | Состояние попытки |
POST /api/projects/:projectId/imports/:importId/finalize | Фиксация manifest и намерения фоновой проверки; новая работа — 202, повтор — 200 |
POST /api/projects/:projectId/imports/:importId/attempts | Исправленный manifest и новая фоновая попытка без изменения предыдущей |
GET /api/projects/:projectId/datasets | Список опубликованных версий |
POST /api/projects/:projectId/runs | Создание расчёта: 202; повтор того же ключа/тела — 200, конфликт — 409 |
GET /api/projects/:projectId/runs | История запусков с подписанным курсором |
GET /api/runs/:runId | Сохранённые статус, этапы, конфигурация, предупреждения и полнота |
POST /api/runs/:runId/cancel | Отмена незавершённого расчёта; без тела запроса |
GET /api/runs/:runId/recommendations | Рекомендации после успеха; до него — 409; курсор, limit, supplierId, q, urgency |
Схемы запросов: проекты и импорт, расчёты. Создание расчёта требует datasetVersionId, scope, configuration и idempotencyKey. Конфигурация включает явные политики прогноза/пополнения и parametersHash; алгоритм этой версии — 1. Диагностический запуск не разрешает утверждение; готовность набора не означает полноту всех требований. Лимит исходного файла — 25 MiB, подписанной ссылки — 300 секунд. Для браузерного PUT необходимо передавать требуемые подписанные заголовки; завершающий HTTP-запрос не заменяет проверку содержимого импортёром.
10. Ограничения текущей версии
- UI ещё не связан со сквозным сценарием: прогноз, пополнение и серверные задачи реализованы; демонстрационный интерфейс пока не читает их через API. Облачная проверка и интеграция UI остаются отдельными этапами.
- Нет производственного утверждения/экспорта: демо хранит правки в памяти, не скачивает файл и не отправляет заказ. Коннектор 1С и совместимый формат обмена не подтверждены. Автоматическая отправка поставщику не входит в объём решения.
- Импорт неполон: реализован XLSX, но не CSV и не внешний ZIP с несколькими книгами. Не завершены числовая сверка месячной/транзакционной истории, полный путь конверсий единиц и разрешение конфликтов приоритетов. SQL-публикация отклоняет материальную ведомость и частичные месяцы, а не молча теряет данные.
- API подготовки требует доработки: начальное несопоставленное описание источника требует согласования. Финализация сохраняет намерение фонового импорта; отчёт попытки читается из приватного S3 после проверки владельца. Вызовы S3 при подготовке загрузки пока удерживают транзакционную блокировку; нет уборки просроченных загрузок и распределённого ограничения частоты запросов.
- Восстановление после длительного сбоя БД: если PostgreSQL недоступен до завершения обработчика
onFailure, операция может остаться незавершённой в БД и требует отдельной сверки; восстановитель dispatch не сверяет терминальное состояние Trigger. - Интеграции не приняты в облаке: реальные Trigger/S3/RDS/Clerk/Liveblocks/AI и передача данных партнёра отдельно не проверены. Модели, бюджет, права передачи и сроки хранения требуют настройки и согласования.
- Поставка ещё интегрируется: зависимости закреплены в package/lock; metadata snapshot Drizzle после SQL-миграций 0001/0002 ещё не обновлён. Используйте отслеживаемые SQL-миграции, не автоматическую генерацию изменений схемы.
- Аудит зависимостей: при проверке установки 23.09.2026 npm сообщил о 19 уязвимостях: 12 moderate, 6 high, 1 critical; high/critical находятся в транзитивном дереве CLI Trigger (включая tar/ws/deepmerge-ts). Их разбор и совместимое обновление зависимостей остаются отдельной задачей перед эксплуатацией; автоматический
audit fix --forceне применялся.
Следующие шаги — закрыть пробелы импорта/API, подключить детерминированное ядро и фоновые задачи, затем связать интерфейс с сохранёнными результатами. Полный план: context/feature-specs/00-build-plan.md.
11. Развёрнутая версия
Публичный URL развёрнутого приложения в репозитории не указан. Проверить решение можно локально: http://localhost:3000/workspace.
Репозиторий: BAITC-Hacks / Tessera, текущая ветка поставки — feat/09-09a-trigger-import.
Авторы коммитов
История коммитов
- 2026-09-23 18:00Merge pull request #15 from BAITC-Hacks/change-readmeanrssnbv
- 2026-09-23 18:00Merge branch 'main' into change-readmeanrssnbv
- 2026-09-23 17:59docs: update README for calculation and import jobsanrssnbv
- 2026-09-23 17:58Record Docker verification after main integrationShynggys
- 2026-09-23 17:57Merge pull request #14 from BAITC-Hacks/01-agentShynggys
- 2026-09-23 17:56Implement light minimalism redesign and supporting workflowsShynggys
- 2026-09-23 17:52Merge pull request #13 from BAITC-Hacks/feature/14-14a-reviewShynggys
- 2026-09-23 17:52Merge main accepting current PR conflict versionsShynggys
Все коммиты (64)
- 2026-09-23 17:52merge: resolve main conflicts keeping review-export changesanrssnbv
- 2026-09-23 17:51Merge pull request #12 from BAITC-Hacks/feat/09-09a-trigger-importShynggys
- 2026-09-23 17:50Merge main into PR 12 and resolve integration conflictsShynggys
- 2026-09-23 17:47fix(review): persist validated edits and connect approval workspaceanrssnbv
- 2026-09-23 17:46Remove starter favicon and record final integration checksShynggys
- 2026-09-23 17:42feat(jobs): add durable calculation runs and import validationanrssnbv
- 2026-09-23 17:42Merge remote-tracking branch 'origin/main' into 01-agentShynggys
- 2026-09-23 17:41Run local Docker workspace and preserve partner source filesShynggys
- 2026-09-23 17:40Merge commit 'b06db95027abc0737bc7641c27eb5dd8d6e81fba' into feature/14-14a-reviewanrssnbv
- 2026-09-23 17:40omx(team): checkpoint worker-5 shutdown changesanrssnbv
- 2026-09-23 17:40Merge commit 'b43608aee5d3e1cb99a92504dad97a2abf4b2cb9' into feature/14-14a-reviewanrssnbv
- 2026-09-23 17:40omx(team): checkpoint worker-4 shutdown changesanrssnbv
- 2026-09-23 17:40Merge commit 'f6439c6939906a30042fcc6b5b5024ae82e1be19' into feature/14-14a-reviewanrssnbv
- 2026-09-23 17:39omx(team): checkpoint worker-2 shutdown changesanrssnbv
- 2026-09-23 17:39Merge commit '074be340690eb3ded43e436aa0bc0638d0873149' into feature/14-14a-reviewanrssnbv
- 2026-09-23 17:39omx(team): checkpoint worker-3 shutdown changesanrssnbv
- 2026-09-23 17:39Merge commit 'a602d5c26e368dac5cf67704defb80c4385dc58b' into feature/14-14a-reviewanrssnbv
- 2026-09-23 17:39feat: add review contracts and consistent owner-scoped snapshot readsanrssnbv
- 2026-09-23 17:30Merge pull request #11 from BAITC-Hacks/feature/07-demand-forecastanrssnbv
- 2026-09-23 17:30Merge branch 'main' into feature/07-demand-forecastanrssnbv
- 2026-09-23 17:28fix(calculation): integrate forecast and replenishment safelyanrssnbv
- 2026-09-23 17:24Merge pull request #10 from BAITC-Hacks/01-agentanrssnbv
- 2026-09-23 17:18Merge main calculations and verify Agent B integrationShynggys
- 2026-09-23 17:00Merge pull request #9 from BAITC-Hacks/feat/08-replenish-engineanrssnbv
- 2026-09-23 17:00Merge branch 'main' into feat/08-replenish-engineanrssnbv
- 2026-09-23 17:00docs: report verified spec status and integration gapsShynggys
- 2026-09-23 16:58merge: integrate project data API with verified 02A workspaceShynggys
- 2026-09-23 16:58Merge pull request #8 from BAITC-Hacks/feature/07-demand-forecastanrssnbv
- 2026-09-23 16:57feat(forecast): implement deterministic demand forecastinganrssnbv
- 2026-09-23 16:57feat(replenishment): implement deterministic order recommendationsanrssnbv
- 2026-09-23 16:54ui: compact completed calculation progressShynggys
- 2026-09-23 16:52feat(ui): apply 02A procurement navigation and mobile layoutShynggys
- 2026-09-23 16:37Merge pull request #7 from BAITC-Hacks/feat/08-replenish-engineanrssnbv
- 2026-09-23 16:37chore: add shared calculation contract and track feature 08anrssnbv
- 2026-09-23 16:25Merge pull request #6 from BAITC-Hacks/feature/05-data-importanrssnbv
- 2026-09-23 16:23feat: add project data API and Russian hackathon READMEanrssnbv
- 2026-09-23 16:18ui: simplify procurement copy and record 02A refinementsShynggys
- 2026-09-23 16:14merge: integrate validated data import core and pinned dependenciesShynggys
- 2026-09-23 16:09docs: record selected 02A design and full page reviewShynggys
- 2026-09-23 15:58Merge pull request #5 from BAITC-Hacks/feature/05-data-importanrssnbv
- 2026-09-23 15:57feat: add validated data import core and regression testsanrssnbv
- 2026-09-23 15:51fix: align AI evidence decimals with shared data contractShynggys
- 2026-09-23 15:48merge: integrate data model with verified agent B foundationShynggys
- 2026-09-23 15:38Merge pull request #4 from BAITC-Hacks/feature/04-data-modelanrssnbv
- 2026-09-23 15:38Merge branch 'main' into feature/04-data-modelanrssnbv
- 2026-09-23 15:38feat: add bounded client transport and request scope isolationShynggys
- 2026-09-23 15:37feat: implement data model and private storageanrssnbv
- 2026-09-23 15:34Merge pull request #3 from BAITC-Hacks/01-agentShynggys
- 2026-09-23 15:29feat: add private realtime adapters and resilient status pollingShynggys
- 2026-09-23 15:06feat: add verified-fact OpenAI and NVIDIA adaptersShynggys
- 2026-09-23 14:57feat: add Clerk boundary and light procurement demoShynggys
- 2026-09-23 14:03Merge pull request #2 from BAITC-Hacks/fear/initial_setupanrssnbv
- 2026-09-23 14:02docs: split hackathon work into parallel tracksanrssnbv
- 2026-09-23 13:51Merge pull request #1 from BAITC-Hacks/fear/initial_setupanrssnbv
- 2026-09-23 13:51chore: add editor scaffold and project planning docsanrssnbv
- 2026-09-23 13:10chore: checkpoint existing app scaffoldanrssnbv
Структура репозитория (258 файлов)
.dockerignore .env.example .gitignore AGENTS.md CLAUDE.md Dockerfile README.md app/api/liveblocks-auth/route.ts app/api/projects/[projectId]/datasets/route.ts app/api/projects/[projectId]/imports/[importId]/attempts/route.ts app/api/projects/[projectId]/imports/[importId]/finalize/route.ts app/api/projects/[projectId]/imports/[importId]/route.ts app/api/projects/[projectId]/imports/route.ts app/api/projects/[projectId]/route.ts app/api/projects/[projectId]/runs/route.ts app/api/projects/route.ts app/api/runs/[runId]/approve/route.ts app/api/runs/[runId]/cancel/route.ts app/api/runs/[runId]/export/route.ts app/api/runs/[runId]/recommendations/route.ts app/api/runs/[runId]/review/route.ts app/api/runs/[runId]/route.ts app/globals.css app/layout.tsx app/page.tsx app/projects/page.tsx app/sign-in/[[...sign-in]]/page.tsx app/sign-up/[[...sign-up]]/page.tsx app/workspace/page.tsx app/workspace/review/page.tsx components.json components/editor/README.md components/editor/editor-navbar.tsx components/editor/project-sidebar.tsx components/procurement/agent-progress.tsx components/procurement/calculation-controls.tsx components/procurement/data-readiness-panel.tsx components/procurement/order-review-dialog.tsx components/procurement/persisted-review.tsx components/procurement/procurement-workspace.tsx components/procurement/project-selection.tsx components/procurement/project-switcher.tsx components/procurement/real-project-workspace.tsx components/procurement/real-projects.tsx components/procurement/recommendation-details.tsx components/procurement/recommendation-table.tsx components/procurement/run-history.tsx components/procurement/workspace-navigation.tsx components/providers/run-room-provider.tsx components/ui/button.tsx components/ui/card.tsx components/ui/dialog.tsx components/ui/input.tsx components/ui/scroll-area.tsx components/ui/tabs.tsx components/ui/textarea.tsx compose.yaml context/ai-workflow-rules.md context/architecture-context.md context/architecture.md context/b-handoff.md context/b-integration-handoff.md context/code-standards.md context/data-inventory.md context/feature-specs/00-build-plan.md context/feature-specs/01-design-system.md context/feature-specs/02-editor.md context/feature-specs/03-clerk-auth.md context/feature-specs/04-data-model-decisions.md context/feature-specs/04-data-model.md context/feature-specs/05-data-import.md context/feature-specs/06-project-data-api.md context/feature-specs/07-demand-forecast.md context/feature-specs/08-replenishment-engine.md context/feature-specs/09-trigger-runs.md context/feature-specs/09a-import-jobs.md context/feature-specs/10-openai-explanations.md context/feature-specs/11-liveblocks-agent-status.md context/feature-specs/12-procurement-workspace-ui.md context/feature-specs/13-workspace-integration.md context/feature-specs/14-review-approval-export-api.md context/feature-specs/14a-review-export-integration.md context/feature-specs/15-acceptance-and-demo.md context/feature-specs/README.md context/feature-specs/_templates/generate-spec-prompt.md context/feature-specs/_templates/spec-backend.md context/feature-specs/_templates/spec-data-model.md context/feature-specs/_templates/spec-frontend.md context/feature-specs/_templates/spec-integration.md context/feature-specs/_templates/spec-setup.md context/feature-specs/_templates/spec-universal.md context/feature-specs/parallel-work-plan.md context/progress-tracker.md context/project-overview.md context/provider-policy.md context/spec-report-2026-09-23.md context/ui-context.md drizzle.config.ts drizzle/0000_data_model.sql drizzle/0001_project_data_api.sql drizzle/0001_review_quantity_policy.sql drizzle/0002_trigger_jobs.sql drizzle/meta/0000_snapshot.json drizzle/meta/_journal.json eslint.config.mjs hooks/use-run-status.ts lib/ai/explain-recommendations-core.ts lib/ai/explain-recommendations.ts lib/ai/explanation-context.ts lib/ai/explanation-schema.ts lib/ai/provider-transport.ts lib/ai/supplier-attention-core.ts lib/ai/supplier-attention.ts lib/client/procurement-api.ts lib/client/project-data-api.ts lib/client/request-scope.ts lib/contracts/api.ts lib/contracts/calculation-policies.ts lib/contracts/calculation.ts lib/contracts/datasets.ts lib/contracts/imports.ts lib/contracts/primitives.ts lib/contracts/project-data.ts lib/contracts/projects.ts lib/contracts/recommendations.ts lib/contracts/review.ts lib/contracts/runs.ts lib/domain/forecast/README.md lib/domain/forecast/coverage.ts lib/domain/forecast/evaluate.ts lib/domain/forecast/index.ts lib/domain/forecast/math.ts lib/domain/forecast/model.ts lib/domain/forecast/prepare.ts lib/domain/forecast/types.ts lib/domain/replenishment/README.md lib/domain/replenishment/calculate.ts lib/domain/replenishment/dates.ts lib/domain/replenishment/decimal.ts lib/domain/replenishment/forecast-sum.ts lib/domain/replenishment/inbound.ts lib/domain/replenishment/index.ts lib/domain/replenishment/urgency.ts lib/procurement/mock-workspace.ts lib/procurement/review-client.ts lib/procurement/review-state.ts lib/realtime/auth-route.ts lib/realtime/authorize.ts lib/realtime/contracts.ts lib/realtime/ownership.ts lib/realtime/publish-run-status.ts lib/realtime/server.ts lib/realtime/status-controller.ts lib/server/approvals.ts lib/server/auth-policy.ts lib/server/auth.ts lib/server/calculation-execution.ts lib/server/db/README.md lib/server/db/index.ts lib/server/db/migrate.ts lib/server/db/pool.ts lib/server/db/schema.ts lib/server/dispatch-README.md lib/server/dispatch.ts lib/server/exports.ts lib/server/imports/README.md lib/server/imports/adapters.ts lib/server/imports/audit.ts lib/server/imports/commit.ts lib/server/imports/dispatch.ts lib/server/imports/index.ts lib/server/imports/job.ts lib/server/imports/lifecycle.ts lib/server/imports/parser.ts lib/server/imports/private-storage.ts lib/server/imports/service.ts lib/server/imports/upload-storage.ts lib/server/project-data-README.md lib/server/project-data-errors.ts lib/server/project-data-http.ts lib/server/project-data-runtime.ts lib/server/projects.ts lib/server/review-http.ts lib/server/reviews.ts lib/server/runs-http.ts lib/server/runs-runtime.ts lib/server/runs.ts lib/server/storage-README.md lib/server/storage.ts lib/server/trigger-transport.ts lib/utils.ts next.config.ts package-lock.json package.json postcss.config.mjs proxy.ts public/file.svg public/globe.svg public/next.svg public/vercel.svg public/window.svg scripts/data-import-dependencies.json scripts/data-model-dependencies.json scripts/generate-import-fixture.ts scripts/import-dataset.ts scripts/migrate-data-model.ts scripts/recover-dispatch.ts techtask/TECHTASK.md tests/ai/adapters.test.mjs tests/ai/load-typescript.mjs tests/auth/auth-boundary.test.mjs tests/client/procurement-api.test.mjs tests/components/workspace-state.test.mjs tests/contracts/feature04.test.ts tests/domain/calculation/README.md tests/domain/calculation/forecast-sum.test.mjs tests/domain/calculation/integration.test.mjs tests/domain/forecast/edge.test.mjs tests/domain/forecast/math.test.mjs tests/domain/forecast/model.test.mjs tests/domain/forecast/monthly.test.mjs tests/domain/forecast/readiness.test.mjs tests/domain/load-typescript.mjs tests/domain/replenishment/core.test.mjs tests/domain/replenishment/edge.test.mjs tests/domain/replenishment/helpers.test.mjs tests/fixtures/forecast/README.md tests/fixtures/forecast/index.mjs tests/fixtures/replenishment/base.mjs tests/helpers/postgres.ts tests/imports/behavior.test.mjs tests/imports/commit.test.mjs tests/imports/commit.test.ts tests/imports/parser.test.mjs tests/project-data/http.test.ts tests/project-data/lifecycle.test.ts tests/project-data/projects.test.ts tests/project-data/upload-storage.test.ts tests/realtime/auth-route.test.mjs tests/realtime/load-typescript.mjs tests/realtime/ownership-db.test.ts tests/realtime/server.test.mjs tests/realtime/status-controller.test.mjs tests/server/boundaries.test.ts tests/server/db.test.ts tests/server/migrations.test.ts tests/server/schema-parity.test.ts tests/server/storage.test.ts tests/trigger/calculation-e2e.test.ts tests/trigger/calculation.test.ts tests/trigger/dispatch.test.ts tests/trigger/fixtures.ts tests/trigger/import-job.test.ts tests/trigger/runs.test.ts trigger.config.ts trigger/calculate-procurement.ts trigger/validate-import.ts tsconfig.json
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.