AAYMA
RU
Войти

Собрано

Веб-приложение подбора до трёх event-подрядчиков из каталога 66 анкет с проверяемыми объяснениями.

Доведённый продукт
Команда «Volga Production» 4💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Volga Production
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Доведённый продукт

Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор

Суть

Веб-приложение подбора до трёх event-подрядчиков из каталога 66 анкет с проверяемыми объяснениями. Для ведущих есть отдельное AI-сравнение и чат для уточнений. Приложение развёрнуто на Railway.

Как устроено

Форма проходит серверную валидацию Zod, затем применяются строгие фильтры: город и категория, дата, цена, формат, язык, длительность. Смысловая близость формата и пожеланий считается эмбеддингами text-embedding-3-small, после сортировки остаётся максимум три подрядчика. LLM (gpt-5.6-sol) выбирает цитату из анкеты, код проверяет, что она есть в исходном тексте, и формирует фактическое объяснение с источником и причинами исключения. Эмбеддинги и ответы кешируются в Docker-томе, при сбое API явно показывается резервный режим.

Ключевые решения

  • строгая фильтрация по ограничениям
  • эмбеддинг-ранжирование
  • проверка цитат LLM по источнику
  • кеширование ответов
  • Playwright e2e

Особенности

Подтверждение цитат: модель только выбирает фрагмент анкеты, а код проверяет его наличие в источнике, поэтому объяснения можно сверить с анкетой. Есть публичный деплой для жюри, smoke-скрипт проверки повторяемости и сохранённые свидетельства проверки в docs/evidence.

Стек

TypeScript · Next.js · React · Mantine · Zod · csv-parse · OpenAI Responses API · Docker Compose · Railway · Playwright

Модели

gpt-5.6-sol · text-embedding-3-small


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-875e970e-volga-production.

README

README.md

Собрано — умный подбор event-подрядчиков

Прототип команды Volga Production для кейса «Умный подбор подрядчиков (#79-lite)». Заказчик задаёт условия мероприятия и получает до трёх карточек с проверяемыми объяснениями из предоставленного каталога Казахстана.

Для жюри: приложение уже развёрнуто

  1. Откройте готовое приложение: sobrano-production.up.railway.app. Установка, регистрация и собственный API-ключ для проверки по этой ссылке не нужны.
  2. Нажмите «Найти совпадения» с исходными параметрами формы. Ожидаемый результат — три карточки ведущих для корпоратива в Алматы на 15.10.2026 с бюджетом 1 000 000 ₸. В каждой карточке указаны условия и основание выбора; раскройте источник, чтобы сверить цитату с анкетой.
  3. Проверьте примеры под формой: «Другая дата», «Флористы», «Малый бюджет», «Нет категории». После выбора примера снова нажмите «Найти совпадения». Ожидаются соответственно изменившаяся подборка, два флориста, объяснение несовпадения условий и сообщение об отсутствии категории.
  4. Для независимого локального запуска выполните инструкцию Docker Compose ниже. Она также подходит, если публичное демо недоступно.

На публичном сайте работает серверный AI-подбор. Повторные запросы могут возвращаться из кеша. При сбое внешнего API приложение явно обозначает резервный режим. Продукт не бронирует подрядчиков и не отправляет заявки; пустая выдача — отдельный объяснённый результат.

Текущая версия опубликована и проверена 23.09.2026: шесть API-сценариев с повтором, AI-ответы по ведущим и 16 браузерных тестов. Историческая проверка сохранения результатов после перезапуска описана отдельно. Подробности и свидетельства проверки.

Чат по ведущим и восстановление страницы доступны в опубликованной версии. Пуш в GitHub сам по себе не запускает деплой Railway; текущий выпуск загружен через CLI.

Локальный запуск через Docker Compose

Этот способ запускает всё приложение одной командой. Node.js и npm на компьютере устанавливать не требуется.

Требования

  • Docker Desktop (Windows/macOS) или Docker Engine с Docker Compose v2+ (Linux); Docker запущен.
  • Копия репозитория. Для команды клонирования ниже нужны Git и доступ к репозиторию организаторов; можно также скачать и распаковать ZIP через GitHub.
  • Свободный порт 3000.
  • Доступ к интернету: при сборке — Docker Hub и npm; при новых AI-запросах — api.openai.com.
  • OpenAI API-ключ с балансом и доступом к gpt-5.6-sol и text-embedding-3-small.
  • Исходный файл data/hackathon_dataset_anonymized.csv включён в репозиторий; 66 профилей, отдельная БД не нужна. Каталог data/ хранит данные, которые приложение читает во время работы; размещать CSV в public/ не нужно.

1. Получите проект

git clone https://github.com/BAITC-Hacks/hack-875e970e-volga-production.git
cd hack-875e970e-volga-production

Если проект уже скачан, откройте терминал в его корневой папке — там находятся Dockerfile, compose.yaml и .env.example. Все следующие команды выполняются из этой папки.

2. Настройте окружение

Создайте .env из примера, если .env ещё нет:

cp .env.example .env

В Windows PowerShell можно использовать Copy-Item .env.example .env. Откройте .env в текстовом редакторе и вставьте свой ключ в OPENAI_API_KEY. Не коммитьте ключ. Пример конфигурации без секрета:

OPENAI_API_KEY=вставьте_свой_ключ
OPENAI_MODEL=gpt-5.6-sol
OPENAI_EMBEDDING_MODEL=text-embedding-3-small
CACHE_DIR=.cache/sobrano

Новые AI-запросы используют баланс вашего OpenAI API-аккаунта. Без ключа можно проверить интерфейс и строгую фильтрацию: оставьте OPENAI_API_KEY= пустым. Приложение будет явно показывать резервный режим; это не проверка полноценного AI-сценария.

3. Соберите и запустите приложение

docker compose up --build -d
docker compose ps

Дождитесь окончания сборки и статуса healthy у сервиса app в выводе docker compose ps. Первый запуск включает загрузку образа и npm-зависимостей. Ход работы можно посмотреть командой docker compose logs --tail=50 app.

Откройте http://localhost:3000. Для проверки сервера откройте http://localhost:3000/api/health в браузере или выполните:

curl --fail http://localhost:3000/api/health

Ожидаемый ответ: {"status":"ok","profiles":66}. Health проверяет загрузку каталога; доступность OpenAI проверяется следующим шагом.

4. Проверьте основной сценарий

Нажмите «Найти совпадения» с исходными параметрами формы и пройдите примеры из первого раздела README. Таблица ожидаемых результатов приведена ниже. Повторите одинаковый запрос: состав и порядок карточек должны сохраниться.

Данные уже включены в репозиторий: импортировать CSV, создавать БД или запускать миграции не нужно. При первом AI-запросе эмбеддинги 66 анкет создаются автоматически и сохраняются в Docker-томе selection-cache. Если API недоступен или не уложился в срок, появится явно обозначенный резервный режим. Причины и действия описаны в разделе устранения проблем.

Для категории «Ведущий» после карточек отдельно загружается сравнение и открывается чат для уточнений. После обновления страницы в той же вкладке восстанавливаются форма, карточки, ответы и черновик вопроса через sessionStorage. Изменение условий сбрасывает подборку и диалог. Сохранение зависит от доступности хранилища браузера и ограничено сессией вкладки.

5. Остановите или запустите повторно

Остановка:

docker compose down

Повторный запуск с сохранённым кешем:

docker compose up -d

После изменения кода или .env снова выполните docker compose up --build -d.

Кеш сохраняется после остановки. docker compose down -v удаляет только тома этого Compose-проекта, включая сохранённые результаты; после этого AI-запросы оплачиваются заново. Используйте эту команду только для намеренного сброса/проверки чистого запуска.

Переменные окружения

ПеременнаяНазначение
OPENAI_API_KEYСерверный ключ OpenAI; без него работает явно обозначенный резервный подбор
OPENAI_MODELМодель выбора цитат и ответа в чате, по умолчанию gpt-5.6-sol
OPENAI_EMBEDDING_MODELМодель смыслового поиска, по умолчанию text-embedding-3-small
CACHE_DIRЛокально .cache/sobrano; Compose задаёт /app/.cache/sobrano

Ключ не попадает в клиентский JavaScript, образ Docker или ответы API. .env исключён из Git и Docker-контекста. В OpenAI передаются описания анонимизированных анкет и параметры запроса; не вводите персональные данные в пожелания. Для Responses используется store: false. Локальный кеш содержит параметры запросов и результаты, без ключей.

Разработка без Docker

Node.js 22+, npm; зависимости закреплены package-lock.json.

npm ci
# Подготовьте .env по инструкции выше.
npm run prepare:data
npm run dev

Откройте http://localhost:3000. prepare:data проверяет каталог и создаёт эмбеддинги заранее; это опционально. Для production: npm run build, затем npm start.

КомандаЧто проверяет / делает
npm testФильтры, данные, валидация, смысловое ранжирование, сбои, подтверждение цитат и кеш
npm run typecheckТипы TypeScript
npm run buildProduction-сборка Next.js
npx playwright install chromiumОднократная установка тестового браузера
npm run test:e2eБраузерные проверки; приложение должно работать на порту 3000
node --import tsx scripts/smoke.tsРеальные API-запросы, повторяемость; сохраняет результаты в docs/evidence/smoke.json
node --import tsx scripts/verify-runtime.tsСравнивает 24 параллельных ответа с сохранённым smoke-прогоном; запускать после него, в том числе после перезапуска контейнера

APP_URL позволяет smoke-скрипту и Playwright проверять другой адрес. Тесты npm test используют явно заданные тестовые сервисы и не расходуют API. Smoke и часть браузерных сценариев обращаются к настоящему API приложения; при настроенном ключе новые запросы могут расходовать API. Проверки восстановления вкладки, часть контролов и чата используют явно заданные ответы/перехват запросов и не подтверждают работу модели.

Smoke/runtime и браузерные скриншоты перезаписывают файлы в docs/evidence/. Для нового аудита сохраняйте результаты отдельно, чтобы не заменить исторические AI-свидетельства резервным прогоном. scripts/production-* воспроизводят исторический production-регресс, содержат фиксированный публичный адрес и не учитывают APP_URL.

Устройство решения

Форма → серверная валидация → город + категория
                              ↓
          дата + цена + формат + язык + длительность
                              ↓
     эмбеддинги: смысловая близость формата и пожеланий
                              ↓
            сортировка → максимум 3 подрядчика
                              ↓
  AI выбирает цитату → код проверяет её в исходной анкете
                              ↓
       фактическое объяснение + источник + причины исключения
                              ↓
    Для ведущих: карточки видны сразу → отдельный AI-ответ → уточнения в чате
  • app/: интерфейс, стили и HTTP-маршруты; lib/: каталог, фильтрация, OpenAI, кеш и подбор.
  • tests/: автоматические проверки; scripts/: подготовка данных и реальные проверочные прогоны.
  • docs/: принятые решения и результаты технической проверки; public/ пока содержит только .gitkeep, сохраняющий каталог для Docker-сборки. Иконка приложения — app/icon.svg.
  • Next.js App Router + React + TypeScript; CSV разбирает csv-parse, вход и ответ модели проверяет Zod. Отдельной БД, векторного сервера и дообучения нет.

Фильтрация и ранжирование

Город и категория проверяются по структурированным полям. Описание о выездах не отменяет фильтр города. Цена «от» должна быть не выше бюджета. Занятые на дату исключаются всегда. Если язык или часы заданы, они также обязательны. max_hours = null означает «присутствие не применимо»; не ноль и не неизвестную длительность. Список категорий разбирается как массив.

Семантический запрос содержит категорию, формат и пожелания; без пожеланий ищется опыт соответствующего формата. Косинусное сходство округляется до шести знаков, затем равенство разрешается по цене и id. Сходство не показываем как процент качества или вероятность успеха.

AI выбирает конкретную дословную цитату и тип особенности. Сервер проверяет идентификаторы и наличие цитаты в description, затем сам формирует текст с датой, форматом, бюджетом и выбранной особенностью. Свободные обещания модели в карточки не попадают. Под раскрываемым блоком доступен полный источник. Перед выбором цитаты применяется консервативный набор признаков конкретной услуги или способа работы (например, инструменты, состав, репертуар, оборудование, вместимость). Общие рекламные фразы не используются как индивидуальное основание. Если подходящий фрагмент не найден или не отличается от уже выбранных, подрядчик остаётся в выдаче с честным сообщением о нехватке конкретики; полная анкета доступна для проверки. Это эвристика для текущего каталога, а не полная оценка смысла: необычно сформулированные полезные сведения могут быть пропущены. Смысловая релевантность цитаты всё равно требует оценки человеком.

Для категории «Ведущий» модель gpt-5.6-sol с reasoning.effort=low также пишет связный ответ по не более чем трём уже отфильтрованным анкетам. Карточки возвращаются отдельным первым запросом и не ждут генерации текста. Первый вариант выделен как первый по смысловой близости; если смысловой этап недоступен, подпись честно меняется на «первый по начальной цене». Это порядок ранжирования, а не гарантия качества подрядчика. Сервер проверяет принадлежность переданных моделью mentionedIds текущей подборке. Форму нельзя изменить текстом чата; вопросы о другой категории и попытки переопределить правила получают ответ с предложением изменить форму. Ответы чата являются интерпретацией анкет и могут ошибаться, поэтому рядом остаются карточки с исходными сведениями. Инструкция модели требует опираться на анкеты и отделять предположения от сведений каталога. Для других категорий остаётся обычный подбор без чата.

Детерминизм и сбои

Кеш содержит версию алгоритма, хеш CSV, модели и нормализованные параметры. Он хранит эмбеддинги, подборки и ответы чата; одновременные одинаковые запросы внутри одного процесса объединяются. Запись атомарная. Один и тот же запрос при неизменной версии данных сохраняет порядок и текст первого ответа после перезапуска благодаря постоянному тому.

На внешние этапы подбора карточек выделено суммарно 8 секунд, автоматических повторов SDK нет. Генерация ответа чата имеет отдельный лимит 8,5 секунды. Прямой запрос /api/chat без готового кеша сначала выполняет подбор: общего серверного лимита 10 секунд у него нет. Интерфейс показывает карточки до сравнения и ждёт каждый запрос до 10 секунд; сеть и операции с диском не входят в лимит внешних этапов. Если смысловой этап недоступен, остаются строгие фильтры и сортировка по цене/ID. AI-цитаты проверяются на принадлежность анкете, содержательность и повтор между карточками по детерминированным правилам. Если выбор цитат недоступен или не проходит проверку, резервный режим выбирает отличающиеся фрагменты анкет с конкретными сведениями либо явно сообщает, что отличительная особенность не выделена. Это проверено на исходном каталоге по календарю и ценовым порогам; смысловую полезность всех формулировок всё равно нужно оценивать человеку. Резервный режим явно указан и тоже кешируется, чтобы повтор не менял порядок. Для его намеренного пересчёта нужно очистить соответствующий кеш; не делайте этого между проверками детерминизма.

Гарантия относится к одному экземпляру приложения с сохранённым кешем и неизменными данными/версиями. Для нескольких серверов понадобятся общий кеш и распределённая блокировка. Удаление кеша или изменение моделей/данных — новый расчёт.

HTTP API

POST /api/recommendations, Content-Type: application/json:

{
  "city": "Алматы",
  "date": "2026-10-15",
  "format": "корпоратив",
  "category": "Ведущий",
  "budget": 1000000,
  "language": "английский",
  "hours": 5,
  "wishes": "Спокойная подача для делового вечера"
}

Обязательны первые пять полей. Возвращаются status, cards (0–3), query, total, eligible, excluded, message, ranking, explanationMode и warnings. AI-текст не задерживает этот ответ.

Для вступительного сравнения ведущих отправьте POST /api/chat с JSON вида { "query": { ...поля формы... }, "message": "", "history": [] }. Для уточнения укажите вопрос в message, например «Кто спокойнее и почему?». Маршрут доступен только для категории «Ведущий» и после заполнения всех обязательных полей. Сервер заново проверяет условия формы и подбирает кандидатов; текст вопроса и переданная история не могут менять город, дату, бюджет или категорию. Для контекста используются только три последние реплики пользователя; ответы ассистента из браузера игнорируются как недоверенные данные. При сбое модели возвращается явно обозначенный резервный ответ; карточки и строгие фильтры остаются доступными.

У карточки evidenceStatus равен specific для выбранной цитаты или insufficient, когда конкретная отличительная особенность не выделена. Во втором случае evidence — пустая строка, а explanation объясняет ограничение; полный description сохраняется. explanationMode=ai означает, что AI использован для доступных цитат, и не исключает карточки с insufficient.

  • matched: хотя бы один подходящий профиль.
  • category_absent: в этом городе нет такой категории.
  • no_match: категория есть, но никто не проходит все ограничения.

В excluded счётчики причин пересекаются: один профиль может быть занят и одновременно дороже бюджета. Ошибочный ввод → 400 с полями; слишком большой запрос → 413; недоступный каталог/кеш → 503. Отсутствие результатов возвращает 200.

Проверка основного сценария

ПримерЧто ожидать до выбора тройки
Алматы, ведущий, корпоратив, 15.10.2026, 1 млн ₸6 подходящих из 10; выдача до 3
Те же условия, 16.10.20264 подходящих; изменившийся календарь меняет выдачу
Алматы, флорист, свадьба, 15.10.2026, 500 тыс. ₸2 подходящих, оба показаны
Алматы, ведущий, корпоратив, 15.10.2026, 100 тыс. ₸no_match, причины видны
Астана, декораторcategory_absent

Убедитесь, что занятых нет; повторите запрос и сравните порядок; раскройте источники. Результаты реальных запросов сохранены в docs/evidence/smoke.json; скриншоты проверки интерфейса — в той же папке. Это технические свидетельства проверок, не подмена работы приложения.

Реализация и история проверок

Реализованы полный подбор, AI-сопоставление пожеланий, проверяемые цитаты, три исхода, чат по ведущим, восстановление результата после обновления страницы и явные резервные режимы.

Повторный аудит кода 8295740 от 23.09.2026: 25/25 модульных и 16/16 браузерных тестов, TypeScript и production-сборка прошли. Текущая версия запущена через Compose с новым пустым томом; после перезапуска совпали 24/24 повторных ответа. Этот свежий прогон выполнен без API-ключа, в явном резервном режиме. После локального аудита текущая версия опубликована и проверена отдельно: результаты production.

Результаты проверок и разбор файлов. Карта реализации требований. Официальное ТЗ получено и сверено; сводка и ссылка на источник.

Исторические результаты: обновление объяснений и production-регресс.

Ниже — исторический прогон локальной ветки с чатом до слияния улучшений конкретности объяснений из main. Приложение было собрано и запущено через Docker Compose с новым пустым томом кеша; эти результаты не заменяют свежую проверку AI текущей версии. Свежий чистый запуск в резервном режиме описан выше.

  • 19 автоматических тестов логики и кеша — пройдены, включая ограничения чата и проверку различимости резервных объяснений.
  • 12 браузерных проверок Docker-версии — пройдены, включая ширины 375, 414, 768, 1024 и 1440 px, показ карточек до завершения AI-сравнения, диалог, оба пустых исхода, раскрытие источников и повтор после сетевой ошибки.
  • TypeScript и production-сборка — пройдены; .env внутри образа отсутствует.
  • 24 параллельных ответа новой версии полностью совпали с сохранёнными ответами того же контейнера. Результат — docs/evidence/runtime.json.
  • Ниже фактические измерения последовательного прогона нового контейнера с первоначально пустым томом. ms — время выдачи карточек; chatMs — отдельное вступительное сравнение. Это не нагрузочный тест и не гарантия задержки на другом оборудовании или сети.
ЗапросКарточкиСравнениеРанжирование / объяснения / ответ
autumn5662 мс8285 мсsemantic / ai / ai
next-date5063 мс8517 мсsemantic / facts / fallback
rare5398 мс—semantic / ai / —
no-match7 мс—none / none / —
absent5 мс—none / none / —
wishes3654 мс5047 мсsemantic / ai / ai

Соответствие критериям ТЗ

Таблица подтверждена по официальному заданию и отличается от общей таблицы AGENTS.md; для кейса используем её.

КритерийГотовое доказательствоОставшееся ограничение
Работоспособность — 25Реальные запросы, три исхода, смена даты и повторяемостьКаталог ограничен исходными 66 профилями
Техническая реализация — 25Разделённые фильтры/AI, проверка источников, тесты, постоянный кешОдин экземпляр; нет ограничения публичных запросов и мониторинга расходов
README и воспроизводимость — 25Compose, пример окружения, команды; текущий чистый запуск проверен без ключаПубличный AI-прогон выполнен; для новых локальных AI-запросов нужны ключ, баланс и сеть
Ценность — 15До трёх вариантов с различимыми основаниямиПользовательская польза ещё не измерялась исследованием
Развитие и оригинальность — 10Выбор с источниками и честным отказом; описан путь к управляемому каталогуАдминистрирование каталога и подтверждение календарей/цен пока не реализованы

Ограничения и дальнейшее развитие

  • Каталог — 66 анонимизированных профилей, включая 13 синтетических от организаторов; 18 цен и 8 городов проставлены при подготовке. Это обозначено на карточках.
  • Календарь только 23.09–31.12.2026. «Свободен» означает отсутствие занятости в предоставленном календаре, не подтверждение подрядчика.
  • Цена «от» не гарантирует итоговую стоимость, пожелания не гарантируют наличие услуги; рекламные заявления не проверены независимо.
  • Пользовательских исследований, измерений экономии времени и доказанного превосходства над альтернативами пока нет.
  • Следующий этап развития — закрытый интерфейс для администратора каталога: добавление, исправление и снятие с публикации анкет без редактирования файла в коде. Потребуются постоянное хранилище, проверка обязательных полей, разграничение доступа и обновление AI-индекса/кеша при изменении опубликованных данных. Массовый импорт CSV/XLSX можно добавить позже как инструмент администратора; произвольные файлы посетителей не входят в текущий сценарий.
  • Для актуальности сведений одного интерфейса недостаточно: понадобится дата последнего подтверждения и процесс проверки цен и занятости с подрядчиками. Пользу следующего этапа следует проверить с организаторами; сравнение подборок с сортировкой по цене пока не проводилось.
  • Для публичной эксплуатации затем понадобятся общий кеш, ограничение запросов и мониторинг расходов.
  • Публичное демо развёрнуто на Railway в одном экземпляре с постоянным кешем. Для длительной публичной эксплуатации нужны ограничение расходов и запросов. Настройки и повторный деплой.

Типичные проблемы

  • Docker daemon недоступен: запустите Docker Desktop; проверьте docker info.
  • Не найден .env: скопируйте .env.example в .env в корне проекта. Файл необходим для Compose, даже если ключ оставлен пустым.
  • Порт 3000 занят: остановите локальный npm run dev либо измените левый порт в Compose на 3001:3000, повторите docker compose up -d и откройте http://localhost:3001.
  • Сайт не открывается после запуска: проверьте docker compose ps и docker compose logs --tail=50 app. Если сервис ещё запускается, дождитесь healthy; если он завершился, устраните ошибку из журнала и повторите запуск.
  • Резервный режим вместо AI: проверьте ключ, баланс, доступ к обеим моделям и сеть. После исправления используйте новый запрос либо намеренно сбросьте кеш; сохранённые резервные ответы не пересчитываются автоматически.
  • prepare:data сообщает 401/403/429: проверьте ключ/права/лимиты у провайдера. Секреты в логи не выводятся.
  • 503 при подборе: проверьте наличие CSV и права записи в каталог кеша; docker compose logs --tail=50 app.
  • Не собирается образ: проверьте доступ к npm/Docker Hub, повторите docker compose build. Для первого запуска нужен интернет.
Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
22
Авторы
2
Файлы
238
Ветки
3

Авторы коммитов

konstantin.volkov 14Mikhail Mironov 8

История коммитов

  • 2026-09-23 17:48Record successful production release and verificationkonstantin.volkov
  • 2026-09-23 17:41Refresh project documentation and verification recordskonstantin.volkov
  • 2026-09-23 17:21Add host selection chat and preserve results on reload (#2)Mikhail Mironov
  • 2026-09-23 17:19Merge origin/main into host selection chat branchMikhail Mironov
  • 2026-09-23 17:16Add host selection chat and preserve results on reloadMikhail Mironov
  • 2026-09-23 17:07chore: remove unused code and consolidate project documentationkonstantin.volkov
  • 2026-09-23 16:46Record successful production deployment and verificationkonstantin.volkov
  • 2026-09-23 16:42Fix generic contractor explanations and record production regressionkonstantin.volkov
Все коммиты (22)
  • 2026-09-23 16:15Add jury deployment guide, Railway evidence and brand faviconkonstantin.volkov
  • 2026-09-23 15:48Merge branch 'main' of https://github.com/BAITC-Hacks/hack-875e970e-volga-productionkonstantin.volkov
  • 2026-09-23 15:38final checkskonstantin.volkov
  • 2026-09-23 15:34Merge pull request #1 from BAITC-Hacks/refactor/unified-form-componentsMikhail Mironov
  • 2026-09-23 15:32Update session context for dataset relocationMikhail Mironov
  • 2026-09-23 15:30Move catalog dataset into data directoryMikhail Mironov
  • 2026-09-23 15:21futurekonstantin.volkov
  • 2026-09-23 15:21Unify event form controls with MantineMikhail Mironov
  • 2026-09-23 14:52change modelkonstantin.volkov
  • 2026-09-23 14:47Merge branch 'main' of https://github.com/BAITC-Hacks/hack-875e970e-volga-productionkonstantin.volkov
  • 2026-09-23 14:47Add spec-to-code compliance skillkonstantin.volkov
  • 2026-09-23 14:45Fix distinct fallback explanations for contractor recommendationskonstantin.volkov
  • 2026-09-23 14:21Edit READMEMikhail Mironov
  • 2026-09-23 13:59first iterationkonstantin.volkov
Структура репозитория (238 файлов)
.agents/skills/frontend-design/SKILL.md
.agents/skills/frontend-responsive-design-standards/SKILL.md
.agents/skills/llm-council/SKILL.md
.agents/skills/llm-council/references/architecture.md
.agents/skills/llm-council/references/cli-notes.md
.agents/skills/llm-council/references/data-contracts.md
.agents/skills/llm-council/references/prompts.md
.agents/skills/llm-council/references/schemas/council_plan.schema.json
.agents/skills/llm-council/references/schemas/final_plan.schema.json
.agents/skills/llm-council/references/schemas/judge_input.schema.json
.agents/skills/llm-council/references/schemas/judge_output.schema.json
.agents/skills/llm-council/references/schemas/task_spec.schema.json
.agents/skills/llm-council/references/task-spec.example.json
.agents/skills/llm-council/references/templates/judge.md
.agents/skills/llm-council/references/templates/plan.md
.agents/skills/llm-council/scripts/llm_council.py
.agents/skills/llm-council/scripts/ui/app.js
.agents/skills/llm-council/scripts/ui/index.html
.agents/skills/llm-council/scripts/ui/styles.css
.agents/skills/llm-council/scripts/ui_server.py
.agents/skills/llm-council/scripts/ui_state.py
.agents/skills/llm-council/setup.bat
.agents/skills/llm-council/setup.ps1
.agents/skills/llm-council/setup.sh
.agents/skills/markdown-url/SKILL.md
.agents/skills/markdown-url/scripts/markdown-url.js
.agents/skills/openai-docs-skill/SKILL.md
.agents/skills/openai-docs-skill/scripts/openai-docs-mcp.sh
.agents/skills/planner/SKILL.md
.agents/skills/read-github/SKILL.md
.agents/skills/read-github/scripts/gitmcp.py
.agents/skills/spec-to-code-compliance/SKILL.md
.agents/skills/spec-to-code-compliance/agents/openai.yaml
.agents/skills/spec-to-code-compliance/assets/trail-of-bits-mark.svg
.agents/skills/spec-to-code-compliance/resources/ANALYSIS_FORMAT.md
.agents/skills/spec-to-code-compliance/resources/DIVERGENCE_RUBRIC.md
.agents/skills/spec-to-code-compliance/resources/DOMAIN_NOTES.md
.agents/skills/spec-to-code-compliance/resources/WORKED_EXAMPLE.md
.agents/skills/ui-ux-pro-max/SKILL.md
.agents/skills/ui-ux-pro-max/data/app-interface.csv
.agents/skills/ui-ux-pro-max/data/catalog-summary.json
.agents/skills/ui-ux-pro-max/data/charts.csv
.agents/skills/ui-ux-pro-max/data/colors.csv
.agents/skills/ui-ux-pro-max/data/data-provenance.json
.agents/skills/ui-ux-pro-max/data/google-font-licenses.json
.agents/skills/ui-ux-pro-max/data/google-fonts.csv
.agents/skills/ui-ux-pro-max/data/icons.csv
.agents/skills/ui-ux-pro-max/data/landing.csv
.agents/skills/ui-ux-pro-max/data/motion.csv
.agents/skills/ui-ux-pro-max/data/phosphor-icons-upstream.json
.agents/skills/ui-ux-pro-max/data/products.csv
.agents/skills/ui-ux-pro-max/data/react-performance.csv
.agents/skills/ui-ux-pro-max/data/stacks/angular.csv
.agents/skills/ui-ux-pro-max/data/stacks/astro.csv
.agents/skills/ui-ux-pro-max/data/stacks/avalonia.csv
.agents/skills/ui-ux-pro-max/data/stacks/flutter.csv
.agents/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv
.agents/skills/ui-ux-pro-max/data/stacks/javafx.csv
.agents/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv
.agents/skills/ui-ux-pro-max/data/stacks/laravel.csv
.agents/skills/ui-ux-pro-max/data/stacks/nextjs.csv
.agents/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv
.agents/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv
.agents/skills/ui-ux-pro-max/data/stacks/react-native.csv
.agents/skills/ui-ux-pro-max/data/stacks/react.csv
.agents/skills/ui-ux-pro-max/data/stacks/shadcn.csv
.agents/skills/ui-ux-pro-max/data/stacks/svelte.csv
.agents/skills/ui-ux-pro-max/data/stacks/swiftui.csv
.agents/skills/ui-ux-pro-max/data/stacks/threejs.csv
.agents/skills/ui-ux-pro-max/data/stacks/uno.csv
.agents/skills/ui-ux-pro-max/data/stacks/uwp.csv
.agents/skills/ui-ux-pro-max/data/stacks/vue.csv
.agents/skills/ui-ux-pro-max/data/stacks/winui.csv
.agents/skills/ui-ux-pro-max/data/stacks/wpf.csv
.agents/skills/ui-ux-pro-max/data/styles.csv
.agents/skills/ui-ux-pro-max/data/typography.csv
.agents/skills/ui-ux-pro-max/data/ui-reasoning.csv
.agents/skills/ui-ux-pro-max/data/ux-guidelines.csv
.agents/skills/ui-ux-pro-max/references/pro-rules.md
.agents/skills/ui-ux-pro-max/references/quick-reference.md
.agents/skills/ui-ux-pro-max/scripts/core.py
.agents/skills/ui-ux-pro-max/scripts/design_system.py
.agents/skills/ui-ux-pro-max/scripts/reasoning_contract.py
.agents/skills/ui-ux-pro-max/scripts/search.py
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-api.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-catalog.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-existing.csv
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-metadata.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-overrides.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/icons-curated.csv
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/phosphor-core.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/phosphor-package.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/phosphor-react-exports.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/phosphor-react-package.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/relevance-baseline.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/relevance-cases.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/relevance-thresholds.json
.agents/skills/ui-ux-pro-max/scripts/tests/test_catalog_refresh.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_catalog_summary_line_endings.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_core.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_core_data_quality.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_data_contracts.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_design_system_mode.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_design_system_stack.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_native_desktop_stack_freshness.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_relevance_evaluator.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_skill_script_paths.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_style_taxonomy.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_text_layout_resilience.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_web_stack_freshness.py
.agents/skills/ui-ux-pro-max/scripts/validate_data.py
.agents/skills/vercel-react-best-practices/AGENTS.md
.agents/skills/vercel-react-best-practices/README.md
.agents/skills/vercel-react-best-practices/SKILL.md
.agents/skills/vercel-react-best-practices/rules/_sections.md
.agents/skills/vercel-react-best-practices/rules/_template.md
.agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md
.agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md
.agents/skills/vercel-react-best-practices/rules/async-api-routes.md
.agents/skills/vercel-react-best-practices/rules/async-defer-await.md
.agents/skills/vercel-react-best-practices/rules/async-dependencies.md
.agents/skills/vercel-react-best-practices/rules/async-parallel.md
.agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md
.agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md
.agents/skills/vercel-react-best-practices/rules/bundle-conditional.md
.agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md
.agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md
.agents/skills/vercel-react-best-practices/rules/bundle-preload.md
.agents/skills/vercel-react-best-practices/rules/client-event-listeners.md
.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md
.agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md
.agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md
.agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md
.agents/skills/vercel-react-best-practices/rules/js-cache-storage.md
.agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md
.agents/skills/vercel-react-best-practices/rules/js-early-exit.md
.agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md
.agents/skills/vercel-react-best-practices/rules/js-index-maps.md
.agents/skills/vercel-react-best-practices/rules/js-length-check-first.md
.agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md
.agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md
.agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md
.agents/skills/vercel-react-best-practices/rules/rendering-activity.md
.agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md
.agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md
.agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md
.agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md
.agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md
.agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md
.agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md
.agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md
.agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md
.agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md
.agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md
.agents/skills/vercel-react-best-practices/rules/rerender-memo.md
.agents/skills/vercel-react-best-practices/rules/rerender-transitions.md
.agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md
.agents/skills/vercel-react-best-practices/rules/server-cache-lru.md
.agents/skills/vercel-react-best-practices/rules/server-cache-react.md
.agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md
.agents/skills/vercel-react-best-practices/rules/server-serialization.md
.dockerignore
.env.example
.gitignore
.railwayignore
AGENTS.md
Dockerfile
README.md
app/api/chat/route.ts
app/api/health/route.ts
app/api/recommendations/route.ts
app/finder.tsx
app/globals.css
app/icon.svg
app/layout.tsx
app/page.tsx
compose.yaml
data/hackathon_dataset_anonymized.csv
docs/audit-2026-09-23.md
docs/case-requirements.md
docs/concrete-explanations-fix.md
docs/evidence/audit-2026-09-23/playwright.json
docs/evidence/audit-2026-09-23/runtime.json
docs/evidence/audit-2026-09-23/smoke.json
docs/evidence/concrete-explanations-fix.json
docs/evidence/concrete-explanations-production.json
docs/evidence/railway-runtime.json
docs/evidence/railway-smoke.json
docs/evidence/regression-2026-09-23/api.json
docs/evidence/regression-2026-09-23/chromium-mobile.png
docs/evidence/regression-2026-09-23/existing-suite-375.png
docs/evidence/regression-2026-09-23/exploration.json
docs/evidence/regression-2026-09-23/firefox-mobile.png
docs/evidence/regression-2026-09-23/webkit-keyboard.json
docs/evidence/regression-2026-09-23/webkit-mobile.png
docs/evidence/release-2026-09-23/deployment.json
docs/evidence/release-2026-09-23/playwright.json
docs/evidence/release-2026-09-23/smoke.json
docs/evidence/runtime.json
docs/evidence/selection-1440.png
docs/evidence/selection-375.png
docs/evidence/selection-main-1440.png
docs/evidence/selection-main-375.png
docs/evidence/smoke.json
docs/frontend-components-refactor-session.md
docs/hackathon-plan.md
docs/host-selection-ai-chat-context.md
docs/production-regression-2026-09-23.md
docs/railway-deployment.md
lib/ai.ts
lib/cache.ts
lib/catalog.ts
lib/chat.ts
lib/filter.ts
lib/finder-session.ts
lib/recommend.ts
lib/types.ts
next-env.d.ts
next.config.ts
package-lock.json
package.json
playwright.config.ts
public/.gitkeep
scripts/prepare.ts
scripts/production-browser-regression.mjs
scripts/production-exploration.mjs
scripts/production-regression.ts
scripts/smoke.ts
scripts/verify-runtime.ts
skills-lock.json
spec-compliance/REPORT.md
tests/browser/controls.spec.ts
tests/browser/finder.spec.ts
tests/browser/persistence.spec.ts
tests/cache.test.ts
tests/chat.test.ts
tests/core.test.ts
tsconfig.json
Ветки (3)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.