AAYMA
RU
Войти

Alem — практические задачи бизнеса

Платформа, где бизнес с помощью AI-конструктора оформляет карточку задачи и публикует её в каталоге.

Рабочий MVP
Команда «Cyber​​Shield» 4💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Cyber​​Shield
Кейс HackAlem.ai: Образование — AI Sana
Стадия: Рабочий MVP

Задача кейса: Challenge Hub: превратить задачу бизнеса в задание для студенческих команд

Суть

Платформа, где бизнес с помощью AI-конструктора оформляет карточку задачи и публикует её в каталоге. Студенческие команды откликаются предложениями с PDF, бизнес вручную выбирает команды; добавлена геймификация: баллы, награды, виртуальная комната.

Как устроено

FastAPI backend хранит данные в SQLite. Модуль quality.py оценивает готовность карточки объяснимой формулой: конкретность полей, измеримость критериев успеха; от оценки зависит порядок в каталоге. AI-конструктор (OpenAI, по умолчанию gpt-4.1-mini) задаёт уточняющие вопросы, готовит неподтверждённые поля с источниками, переформулирует описание. Отдельная модель проверяет смысл перед публикацией; без ключа работает явно обозначенный локальный резервный режим. Frontend на Next.js 16 / React 19 / Tailwind 4 с редактором из 4 шагов, откликами и наградами.

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

  • формула рейтинга готовности задачи
  • семантическая AI-проверка описания
  • уточняющие вопросы AI
  • резервный режим без ключа
  • геймификация (баллы, награды)

Особенности

Рейтинг готовности задачи и баллы команд независимы. AI только предлагает поля, а подтверждает их человек. Есть аудит соответствия всем критериям HackAlem (CRITERIA_AUDIT.md), 5-минутный демо-сценарий и видеозапись демо (summary.mp4, 3:23) в репозитории.

Стек

Python · FastAPI · Pydantic · SQLite · Next.js 16 · React 19 · TypeScript · Tailwind CSS 4 · shadcn/ui

Модели

gpt-4.1-mini


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

README

README.md

Alem — практические задачи бизнеса

Локальный MVP для кейса HackAlem / AI Sana: бизнес составляет карточку задачи, подтверждает сведения и публикует её в каталоге. Студенты просматривают все опубликованные задачи, сохраняют интересные и отправляют предложения от команды. Бизнес сравнивает отклики и вручную выбирает одну, несколько или ни одной команды. Готовность описания определяет рейтинг и порядок в каталоге.

Работает сценарий до подтверждения завершённого проекта и награды команды. Доступны редактор, публикация, рейтинг, каталог, квесты, отклики с PDF и ручные решения бизнеса. За подтверждённый результат команда получает 100 баллов и обменивает их на фоны профиля и предметы виртуальной комнаты. Рейтинг готовности задачи и баллы команды независимы. AI-конструктор готовит вопросы и карточку, а подключённый AI отдельно оценивает смысл описания перед публикацией. Без ключа доступны явно обозначенные локальные проверки.

Оформление вдохновлено страницей AI Sana: крупный центрированный заголовок, светлый фон, просторный поиск и округлые карточки. Используются собственное название Alem и цвета #5b6bc4, #1a2250, #f7f8fc.

Материалы для сдачи

Исходный код: BAITC-Hacks/hack-615e4e31-cyber-shield, ветка main. При необходимости архив можно скачать на странице репозитория через Code → Download ZIP. Синтетические данные и тестовый PDF включены в папку fixtures.

Что нужно проверяющемуГде находится
Быстро запустить MVP и попробовать две ролиПростая инструкция — скачивание, две команды, адрес приложения и остановка
Разобраться в установке, настройках и диагностикеПодробная инструкция — требования, AI, база данных, отдельные сервисы, сборка и проверки
Понять устройство приложенияАрхитектура
Проверить геймификацию бизнесаФормула рейтинга задачи и правила каталога и квестов
Воспроизвести основные действияТестовые сценарии и автоматические проверки
Провести обязательную демонстрацию до пяти минутСценарий на одной задаче пекарни и готовые синтетические тексты
Посмотреть запись демонстрацииsummary.mp4 — 3:23, 1280 × 720; файл включён в репозиторий

MVP запускается локально на компьютере проверяющего. Адрес 127.0.0.1:5173 доступен после запуска; это не ссылка на публичный сайт. В чистой копии API-ключ не требуется: предусмотрен явно обозначенный резервный режим. Для внешнего AI проверяющий использует собственный серверный ключ. Полноценная регистрация и production-аутентификация в этот демонстрационный MVP не входят.

Быстрый запуск

Проверенное окружение: macOS, Python 3.13.9, Node.js 25.8.0. Приложение требует Python 3.11+, а frontend объявляет Node.js 22.13.0+. Другие версии и ОС не проверены этим прогоном. Нужны python3, node и npm в PATH; первоначальная установка использует интернет. Общий скрипт запуска рассчитан на macOS/Linux.

Для новой копии сначала получите исходники (если проект уже скачан, перейдите сразу к установке из его корня):

git clone https://github.com/BAITC-Hacks/hack-615e4e31-cyber-shield.git Hakaton
cd Hakaton

Установка и запуск в корне репозитория:

python3 scripts/setup.py
python3 scripts/dev.py

Установка создаёт backend/.venv, устанавливает версии из backend/requirements.txt и запускает npm ci по frontend/package-lock.json. Глобальные Python-пакеты не меняются. Для повторной установки используется та же команда; перед её выполнением остановите свои запущенные сервисы.

После сообщения Ready откройте приложение. Документация API доступна по адресу 127.0.0.1:8000/docs, проверка сервера — 127.0.0.1:8000/api/health.

Ctrl-C останавливает оба сервиса и их дочерние процессы. Если один сервис завершится, скрипт остановит второй. При занятых портах 8000 или 5173 запуск отменяется: чужие процессы не завершаются. Скрипт не выполняет публичное развёртывание.

Проверки без установки и запуска:

python3 scripts/setup.py --check
python3 scripts/dev.py --check

Первая проверяет инструменты и файлы зависимостей; вторая — установленное окружение и свободные порты. Если приложение уже запущено, вторая проверка ожидаемо сообщит о занятых портах.

Запуск отдельно и проверка сборки

Можно открыть два терминала в корне проекта. В первом:

backend/.venv/bin/python -m uvicorn app.main:app --app-dir backend --host 127.0.0.1 --port 8000

Во втором:

npm --prefix frontend run dev

Next.js принимает запросы /api/* и перенаправляет их на FastAPI по адресу http://127.0.0.1:8000. Интерфейс и API слушают только локальный адрес 127.0.0.1.

Для локального запуска собранного приложения сначала остановите текущий запуск, затем выполните:

npm --prefix frontend run build
python3 scripts/dev.py --production

Для отдельного запуска собранного frontend предусмотрен npm --prefix frontend run start; FastAPI должен быть запущен во втором терминале. После изменений backend общий скрипт нужно перезапустить; автоматическая перезагрузка Uvicorn в нём не включена.

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

FastAPI автоматически загружает .env в корне проекта при запуске. Создайте его по .env.example, если файла ещё нет, и вставьте ключ в OPENAI_API_KEY=.... Не перезаписывайте существующий файл. Переменные окружения процесса имеют приоритет. .env исключён из Git и не передаётся в frontend.

ПеременнаяПо умолчаниюНазначение
APP_DB_PATHbackend/data/hackalem.sqlite3Путь к SQLite; для другой базы рекомендуется абсолютный путь
OPENAI_API_KEYНе заданаНеобязательный серверный ключ; без него AI работает в явно обозначенном резервном режиме
OPENAI_MODELgpt-4.1-miniМодель для внешнего AI-адаптера
OPENAI_RATING_MODELЗначение OPENAI_MODELНеобязательная отдельная модель для проверки смысла и рейтинга
BACKEND_URLhttp://127.0.0.1:8000Адрес API для Next.js при отдельном запуске; общий скрипт всегда устанавливает локальный адрес

Для production-сборки frontend задавайте нужный BACKEND_URL до npm run build: маршруты перенаправления входят в сборку. Настройка AI описана в docs/AI.md. Ключ остаётся на сервере и не включается в frontend или Git.

После изменения .env перезапустите backend или общий скрипт. Проверка настройки без вывода ключа:

backend/.venv/bin/python scripts/check_ai.py
# Один реальный запрос с синтетическим описанием, расходует лимит API:
backend/.venv/bin/python scripts/check_ai.py --request

Ключ создаётся в OpenAI API; порядок настройки описан в официальном руководстве. В редакторе кнопка «Проверить смысл с AI» активна при заданном ключе. Само наличие ключа ещё не подтверждает доступность модели или лимита аккаунта.

Архитектура

Приложение состоит из двух локальных процессов и SQLite-файла. Backend — Python / FastAPI / Pydantic; frontend — TypeScript / Next.js 16 / React 19 / Tailwind CSS 4. Установленные версии фиксируются в requirements.txt и package-lock.json.

flowchart LR
    User["Бизнесмен / Студент"] --> Web["Next.js · 127.0.0.1:5173"]
    Web -->|"/api/*"| API["FastAPI · 127.0.0.1:8000"]
    API --> Rules["Расчёт рейтинга"]
    API --> Store["Хранение и правила каталога"]
    Store --> DB[(SQLite)]
    Fixtures["Синтетические данные"] -->|"первичная загрузка"| Store
    API --> AI["AI-конструктор"]
    AI --> Stub["Локальная заглушка"]
    AI -.->|"при наличии ключа"| External["Внешняя модель"]
КомпонентОтветственность
frontend/app/page.tsxКаталог, фильтры, тестовые роли и профили, сохранённые задачи и окна квестов
frontend/components/tasksРедактор из четырёх шагов, разбивка баллов, просмотр карточки, AI-помощник с источниками
frontend/lib/api.tsHTTP-клиент, заголовок тестовой роли, обработка ошибок и тайм-аут запросов
backend/app/main.py, models.pyМаршруты API, проверка типов, размеров и допустимых полей, проверка тестовой роли
backend/app/domain.py, quality.pyФормула рейтинга и объяснимая проверка конкретности полей и измеримости критериев успеха; без сетевых вызовов
backend/app/store.pyТранзакции SQLite, версии карточек, сортировка, подбор квестов и решения студентов
backend/app/seed.pyПовторяемый импорт исходного набора без дублирования записей
backend/app/ai.pyУточняющие вопросы, подготовка неподтверждённых полей, проверка источников и резервный режим
backend/app/description_expansion.py, DescriptionExpander.tsxПереформулировка описания, отдельная проверка смысла и редактируемое предложение с ручным применением
backend/app/proposals.py, frontend/components/proposalsКоманды, отправка предложений, сравнение откликов и ручные решения бизнеса
backend/app/rewards.py, frontend/components/rewardsПодтверждение завершения, журнал баллов, покупки и оформление комнаты
backend/app/semantic_quality.pyОценка смысла внешней моделью, проверка структуры и цитат, кэш успешных ответов

В таблице tasks хранятся текущий черновик (draft_json) и последний опубликованный снимок (published_json). profiles содержит тестовые профили студентов; quest_decisions — сохранение или пропуск задачи для конкретного профиля. teams и proposals хранят команды и рабочие отклики с решениями бизнеса; proposal_attachments — PDF в виде BLOB внутри той же базы. reward_transactions хранит журнал начислений и покупок, reward_equipment — выбранное оформление команды. fixture_records сохраняет исходные записи набора, metadata — версии наполнения и расчёта рейтинга. Запросы к SQLite параметризованы. AI-модуль не записывает данные в эти таблицы.

Основные маршруты:

МаршрутНазначение
GET /api/tasksОпубликованные карточки; фильтры q, topic, readiness
GET /api/tasks?view=businessТекущие версии карточек тестового бизнеса, включая неопубликованные
POST /api/tasks, PUT /api/tasks/{id}Создать или сохранить черновик
POST /api/tasks/{id}/confirm, POST /api/tasks/{id}/publishПодтвердить текущую версию, затем опубликовать её
POST /api/rating/previewРассчитать потенциальные баллы без сохранения и подтверждения
GET /api/profiles, PUT /api/profiles/{id}/skillsПолучить профили и изменить навыки
GET /api/quests?profileId={id}Получить до трёх рекомендаций
POST /api/quests/{id}/decision, GET /api/saved?profileId={id}Сохранить/пропустить задачу, получить сохранённые
POST /api/ai/analyze, POST /api/ai/build-cardПолучить вопросы и предварительную карточку с источниками
POST /api/ai/expand-descriptionПолучить более развёрнутую формулировку описания и отдельные вопросы; без сохранения
GET /api/teams, POST /api/tasks/{id}/proposalsПолучить команды и отправить предложение на опубликованную задачу
GET /api/proposals?teamId={id} или ?taskId={id}Отклики команды для студента или предложения на задачу для бизнеса
PUT /api/proposals/{id}/decisionРучное решение бизнеса: выбрать, отклонить или вернуть на рассмотрение
POST /api/tasks/{id}/proposals/uploadОтправить предложение с одним PDF через multipart/form-data
GET /api/proposals/{id}/attachments/{attachmentId}Скачать PDF с проверкой тестовой роли и команды/владельца
GET /api/demo-dataИсходный синтетический набор и соответствие идентификаторов

Форматы запросов доступны в Swagger UI запущенного сервера. Работа с черновиками, AI и решениями по откликам требует X-Demo-Role: business; изменение навыков, решения по квестам и отправка предложений — X-Demo-Role: student. Это демонстрационные ограничения, а не авторизация пользователей.

Данные и тестовые роли

Первый запуск создаёт SQLite-базу backend/data/hackalem.sqlite3 и синтетические данные: 5 опубликованных задач, 5 неопубликованных черновиков, 5 индивидуальных профилей, 5 команд и 5 откликов на рассмотрении. Рейтинги опубликованных примеров из пользовательского набора: 100, 90, 75, 50 и 20. Первый профиль имеет навыки Python, SQL и «Аналитика». При обычном повторном запуске данные сохраняются, примеры не дублируются.

Другую базу можно указать переменной окружения. Например, для отдельной демонстрации, сохранив рабочую базу:

APP_DB_PATH=/tmp/hackalem-demo.sqlite3 python3 scripts/dev.py

Если файла ещё нет, в нём появятся стартовые примеры. Если он уже существует, приложение продолжит работу с его данными. Базы, виртуальное окружение, node_modules, секреты и результаты сборки исключены через .gitignore и не должны попадать в коммиты.

Переключатели «Бизнесмен» и «Студент» — тестовые роли, а не регистрация и аутентификация. API проверяет заголовок X-Demo-Role для изменения данных, но любой клиент может его передать. Этот режим предназначен для локальной демонстрации с синтетическими данными. CORS также не заменяет аутентификацию.

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

Баллы команды и оформление

В разделе «Комната и награды» студент выбирает тестовую команду и видит её баланс, прогресс, историю и коллекцию. Бизнес вручную подтверждает успешное завершение выбранного проекта — это отдельное действие после выбора отклика. Команда получает 100 баллов один раз за задачу. Простой выбор команды баллов не даёт.

Монстера стоит 40 баллов, утренний фон, постеры и лампа — по 60, ночной фон — 80. Покупка добавляет предмет в коллекцию; применение и снятие бесплатны. Баланс и оформление сохраняются в SQLite. Реальные подписки и денежные платежи не подключены. Правила, API и сценарий 100 → 60 → 0: REWARDS.md.

Формула рейтинга задачи

При наличии API-ключа смысл проверяет модель: связность контекста и потребности, конкретность результата, доступность материалов и проверяемость критериев приёмки. Короткие ответы из 1–3 букв не получают баллы даже при ошибочном одобрении модели. Во время ввода показывается предварительная локальная оценка; отдельная кнопка запускает AI без сохранения. Подтверждение перед публикацией обязательно использует AI при настроенном ключе. При ошибке AI во время публикации текущие правки остаются сохранёнными как неподтверждённый черновик; подтверждение и новая публикация не выполняются, прежний опубликованный снимок сохраняется. Успешная локальная проверка не выдаётся за AI-результат. Подробности и примеры входа/выхода: SEMANTIC_RATING.md.

Главная геймификация направлена на бизнес: полнота и конкретность подтверждённого описания конкретной задачи повышают её рейтинг и позицию в каталоге. Известность компании, число сохранений и откликов на баллы не влияют. Автоматическая проверка содержания находит расплывчатые формулировки и непроверяемые критерии успеха; достоверность исходных сведений подтверждает человек.

ПоказательПоля APIМаксимум
Контекст и потребностьcontext — 10, need — 1020
Данные и материалыdata20
Ожидаемый результатexpectedResult15
Критерии успехаsuccessCriteria15
Ограниченияconstraints10
Пользователиusers10
Связь с бизнесомcontact — 5, interactionFormat — 510
Всего100

Для каждого поля f задаются вес w(f) и индикатор c(f):

c(f) = 1, если текущая версия подтверждена,
          поле заполнено содержимым, отличным от явной заглушки,
          проверка содержания дала полю статус ready,
          и поле входит в confirmedFields, когда этот список задан;
       0 — иначе.

R = Σ w(f) × c(f),  0 ≤ R ≤ 100

R = 10·c(context) + 10·c(need) + 20·c(data)
  + 15·c(expectedResult) + 15·c(successCriteria)
  + 10·c(constraints) + 10·c(users)
  + 5·c(contact) + 5·c(interactionFormat)

Поле получает весь свой вес или ноль. Например, только контекст даёт 10 из 20 баллов группы «Контекст и потребность». Название, компания, направление, навыки и отдельное поле feedbackProcess («Дополнительные договорённости») баллов не дают. Для связи с бизнесом оцениваются контакт и поле «Консультации и обратная связь».

Пустые строки, явные заглушки, шум, повторяющиеся универсальные фразы и недостаточно конкретные сведения баллов не дают. Каждое оцениваемое поле получает статус missing, needs_work или ready с объяснением и подсказкой. Проверяются признаки текущего процесса, потребности, аудитории, материалов, результата, ограничений и контакта. Для критериев успеха нужны наблюдаемый результат и измерение/порог либо воспроизводимая проверка с однозначным исходом; одно число само по себе недостаточно.

Например, «Всё должно работать хорошо» не даёт 15 баллов за критерии успеха. «100 строк импортируются без потерь; фильтр отвечает до 1 секунды» проходит проверку. Подсказки показываются рядом с полями и в панели рейтинга. Описание правил и их границ — docs/QUALITY.md. Это локальная проверка по правилам, работающая без API-ключа; она может ошибаться на необычных формулировках и не доказывает истинность текста.

Предварительная оценка рассчитывается по заполнению и качеству формы так, как если бы её подтвердили. Она помогает увидеть возможный результат, но не начисляет баллы и не меняет каталог. У сохранённого неподтверждённого черновика рейтинг равен 0. При импорте учитывается список confirmed_fields из исходного набора.

БаллыУровень APIЗначение в интерфейсе и каталоге
0–39draftНужно уточнить; опубликованная задача доступна студентам
40–69workableРабочая; может попасть в рекомендации при совпадении профиля
70–89readyГотовая; располагается выше задач с меньшим рейтингом
90–100priorityПриоритетная; дополнительно выделяется оформлением

Название уровня draft характеризует готовность описания, а не факт публикации. Например, опубликованная задача с 20 баллами видна всем. Уровень от 90 баллов также не означает, что заполнено абсолютно каждое поле: все веса набираются только при 100 баллах.

Подтверждение и публикация

  1. Бизнес заполняет форму и сохраняет черновик. Каждое сохранение существующей карточки через PUT создаёт новую ревизию и сбрасывает подтверждение всей текущей версии, даже если значения совпали.
  2. На последнем шаге бизнес проверяет сведения и ставит отметку «Я проверил(а) сведения в карточке». Одна отметка ничего не отправляет на сервер.
  3. Кнопка «Опубликовать задачу» или «Обновить публикацию» последовательно сохраняет форму, подтверждает текущую версию и публикует её. Для публикации нужны подтверждение и непустое название; минимального рейтинга нет.
  4. Каталог получает новый снимок и пересортировывается. После следующих правок старые опубликованные поля и баллы остаются видимыми до нового подтверждения и публикации.

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

Правила каталога и квестов

Общий каталог

  • Видны все опубликованные снимки, включая задачи с рейтингом 0–39. Неопубликованные черновики доступны только в тестовом режиме бизнеса.
  • Порядок: рейтинг по убыванию, при одинаковом рейтинге — внутренний UUID по возрастанию. Дата публикации, название компании и число сохранений порядок не меняют.
  • В интерфейсе есть фильтры по направлению (topic) и уровню готовности. Поиск без учёта регистра проверяет название, компанию, потребность и требуемые навыки. Фильтрация выполняется в браузере и сохраняет серверный порядок.
  • API также поддерживает фильтры q, topic, readiness. Его поиск q шире интерфейсного: все текстовые поля карточки, компания, тема и навыки. Отрасль не входит в поиск. Сервер обрезает пробелы поисковой строки и сравнивает тему без учёта регистра; UI выбирает точную тему из списка.
  • Студент может открыть, сохранить и отправить отклик на любую опубликованную задачу независимо от рейтинга и совпадения навыков. Фильтры пользователь выбирает сам; рекомендации не сокращают общий каталог.

Персональные квесты

Рекомендации вычисляются обычными правилами, без обращения к внешней модели:

  1. Берутся опубликованные задачи с рейтингом от 40, которые этот профиль ещё не сохранил и не пропустил.
  2. Если requiredSkills заполнен, все требуемые навыки должны присутствовать в профиле. Сравнение не учитывает регистр; совпадение интереса не отменяет отсутствующий обязательный навык.
  3. Если навыки задачи не указаны, нужен интерес профиля, точно совпавший без учёта регистра с темой или отраслью задачи. В исходных пяти карточках навыки отсутствуют, поэтому для них действует именно это правило.
  4. API возвращает первые три подходящие задачи в порядке общего каталога. Интерфейс показывает одно окно за раз с причиной рекомендации — навыками или интересом.

«Сохранить квест» добавляет задачу в «Мои квесты»; «Пропустить» сохраняет отказ от рекомендации. Оба решения хранятся в SQLite отдельно для каждого профиля и исключают повторную рекомендацию этой задачи. Крестик только закрывает окно: после перезагрузки страницы такой квест может появиться снова. В течение текущей страницы повторный показ уже увиденного окна также подавляется.

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

Отклики и ручной выбор бизнеса

Студент явно выбирает тестовую команду, указывает идею решения, шаги плана, срок в календарных днях, ссылку на прототип и при необходимости допущения. К предложению можно приложить один PDF до 10 МиБ. Отправленный отклик получает статус submitted. Число откликов не ограничено; одной команде разрешено предложить несколько вариантов.

Бизнес открывает предложения по своей задаче и сравнивает навыки и технологии команды, идею, план, срок, ссылку и допущения. Только бизнес меняет статус на accepted или rejected, может оставить комментарий и вернуть отклик в submitted. После подтверждения успешного завершения проекта решение зафиксировано: отклонить этот отклик или вернуть его на рассмотрение нельзя. Решение по одному отклику не изменяет остальные: допустимо выбрать одну, несколько или ни одной команды. Студент видит решения в разделе откликов своей команды.

Срок — целое число от 1 до 365 дней; ссылка допускает только HTTP/HTTPS. Адреса из исходного набора помечены как демонстрационные, наличие настоящего прототипа не заявляется. Сервер не открывает и не проверяет внешнюю ссылку. PDF и отклик сохраняются одной транзакцией; файл доступен для скачивания бизнесу и отправившей его команде. Размер, расширение и сигнатура проверяются до сохранения; это базовая проверка формата, не антивирусная экспертиза. Контракт и сценарий демонстрации — docs/PROPOSALS.md.

Исходный набор и AI-конструктор

В fixtures/hackalem_synthetic_data.json и fixtures/README_hackalem.md находятся точные копии присланных файлов: 5 черновиков, 5 карточек, 5 команд и 5 откликов. Все 20 исходных записей сохраняются в fixture_records и доступны через GET /api/demo-data. Карточки, команды и отклики также импортируются в рабочие сущности и доступны через интерфейс. Решение по отклику меняет рабочую запись, а исходный JSON остаётся неизменным. Пять индивидуальных профилей /api/profiles служат для демонстрации квестов; выбор команды для отправки предложения выполняется отдельно.

Внутренние UUID карточек/черновиков получаются стабильно из исходных ID; поля sourceId/sourceDraftId и apiIds в /api/demo-data сохраняют связь с оригиналом. null преобразуется в пустое поле формы и не даёт баллов. Импорт использует confirmed_fields и самостоятельно пересчитывает рейтинг. CSV, упомянутые в описаниях, не входят в исходный набор и не выдаются за существующие файлы.

При обновлении базы с начальных примеров до версии 2 добавляются присланные записи; прежние карточки, правки и сохранения сохраняются. Поэтому в ранее запущенной базе записей может быть больше, чем в чистой установке. Формула рейтинга обновляется без изменения текстов.

При подключении проверки качества версия формулы хранится отдельно. Миграция пересчитывает производные оценки черновика и опубликованного снимка по их собственным полям, сохраняя тексты, ревизии, подтверждения и решения. Импорт команд и откликов идемпотентен и не сбрасывает уже принятые бизнесом решения.

fixtures/proposal_demo.pdf — дополнительный синтетический файл для проверки загрузки. Он создан для проекта отдельно от присланного исходного набора. Загруженные файлы хранятся в локальной SQLite-базе и не попадают в Git.

В конструкторе задачи откройте AI-помощника, введите исходное описание, получите вопросы и ответьте на них. Проверьте предварительную карточку и цитаты-источники, затем нажмите «Перенести в карточку». Перенос не сохраняет, не подтверждает и не публикует задачу: это отдельные действия бизнеса.

Кнопка «Расписать подробнее с ИИ» доступна у исходного описания в помощнике и у поля «Что происходит сейчас». Она открывает исходник и редактируемый предложенный вариант. AI разворачивает и упорядочивает уже сообщённые сведения; недостающие детали предлагает уточнить отдельными вопросами. Текст меняется только после «Использовать этот текст», затем остаётся обычная ручная проверка и публикация. Если API недоступен или предложение не прошло проверку источника, сохраняется исходный текст с явным сообщением. Контракт и проверки — DESCRIPTION_EXPANSION.md.

Настройка внешней модели, точный промпт, форматы API, проверки ответов и резервный режим описаны в docs/AI.md. Ключ задаётся только на сервере через OPENAI_API_KEY; без него приложение полностью запускается локально. Сам API-ключ не требуется для демонстрации формы и резервного сценария.

Тестовые сценарии

Точные числовые примеры ниже проверены для локального режима rules-v2, без ключа. При подключённом API модель может иначе оценить содержание; ручное подтверждение и фиксированные веса сохраняются. Сценарии наград приведены в REWARDS.md, проверки API — в SEMANTIC_RATING.md.

Для воспроизводимой демонстрации остановите свой текущий запуск и укажите новый, ещё не существующий путь APP_DB_PATH. Например, если файл ниже ещё не существует:

ALEM_LOAD_ENV=0 OPENAI_API_KEY='' APP_DB_PATH=/tmp/hackalem-demo-offline.sqlite3 python3 scripts/dev.py

Команда создаёт отдельную базу без удаления рабочей и отключает внешний AI на время этого запуска, даже если ключ есть в .env или окружении терминала. При повторном запуске с тем же путём данные сохраняются. Для нового чистого показа выберите другое имя файла. Для проверки позиций очищайте поиск и фильтры. Описанные ниже результаты — критерии проверки; история первых прогонов приведена в docs/PART1_VERIFICATION.md. Сам набор в Git содержит только синтетические данные.

1. Начальное наполнение и порядок

Откройте каталог на новой базе. Ожидаются пять опубликованных карточек в таком порядке:

Исходный IDНазваниеБаллыУровень
task_005Панель контроля статусов доставки100Приоритетная
task_004Контроль минимальных остатков товара90Приоритетная
task_003Журнал посещаемости и отчёт по учебным группам75Готовая
task_002Расписание записи в автосервис50Рабочая
task_001Единый список предзаказов для пекарни20Нужно уточнить

В режиме бизнеса дополнительно доступны пять неопубликованных черновиков. В /api/demo-data — пять исходных черновиков, пять карточек, пять команд и пять откликов. В интерфейсе откликов доступны пять импортированных предложений со статусом «На рассмотрении»; для задачи доставки есть два предложения, которые можно сравнить.

2. Рост рейтинга и перемещение в каталоге

  1. В роли «Бизнесмен» создайте задачу «Тест: список заказов». Заполните только контекст: «Заказы записываем в тетрадь» и потребность: «Нужен единый список заказов». Остальные оцениваемые поля оставьте пустыми. Предварительная оценка — 20.
  2. Нажмите «Сохранить черновик». В «Моих задачах» начислено 0, в общем каталоге новой задачи нет.
  3. Откройте её снова, перейдите к четвёртому шагу, проверьте сведения, поставьте отметку и опубликуйте. В каталоге рейтинг 20; задача находится ниже автосервиса с 50. Порядок между двумя задачами с 20 определяется UUID.
  4. Добавьте данные: «Есть тестовая таблица из 30 заказов» и ожидаемый результат: «Веб-список заказов с поиском». Предварительная оценка — 55: 10 + 10 + 20 + 15. Сохраните черновик. В каталоге по-прежнему 20 и старые поля; текущая версия бизнеса не подтверждена.
  5. Снова откройте редактор, подтвердите сведения и нажмите «Обновить публикацию». Теперь рейтинг 55: задача выше автосервиса с 50, но ниже журнала посещаемости с 75.
  6. Для проверки защиты замените данные на TBD: предварительная оценка станет 35. Верните исходный текст или выйдите без сохранения. Изменение только компании, названия или навыков предварительные баллы не увеличивает.

Это основной сценарий демонстрации геймификации бизнеса. Точный номер позиции зависит от других добавленных задач, поэтому сравнивайте относительный порядок и баллы.

3. Низкий рейтинг не закрывает каталог

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

4. Подбор по навыкам и решение студента

  1. У задачи из сценария 2 с рейтингом 55 выберите требуемые навыки Python и SQL, подтвердите и обновите публикацию. Баллы остаются 55.
  2. В роли студента выберите профиль Тимур. На новой базе у него «Дизайн» и Figma: тестовая задача остаётся в общем каталоге, но в рекомендации ему не проходит.
  3. В профиле добавьте Python и SQL, нажмите «Сохранить навыки» и перезагрузите страницу, чтобы исключить подавление уже показанных окон. Снова выберите роль «Студент» и профиль «Тимур». На исходном наборе тестовая задача подходит по обоим навыкам и появляется как квест; причина содержит Python и SQL.
  4. Нажмите «Сохранить квест», перезагрузите страницу и снова выберите студента Тимура: задача остаётся в «Моих квестах» и больше не рекомендуется этому профилю.
  5. Для проверки пропуска выберите профиль Дана: на исходном наборе ей подходит журнал посещаемости с 75 баллами по интересу «Образование». Нажмите «Пропустить», перезагрузите страницу и снова выберите Дану. Эта рекомендация не должна вернуться, но задача остаётся в общем каталоге.

Проверять изменение навыков только на исходных пяти карточках недостаточно: у них нет требований к навыкам, и подбор использует интересы. При наличии дополнительных пользовательских задач рекомендация может уступать место более высоким по рейтингу; точный список доступен в /api/quests?profileId={id}.

5. AI без внешнего API и подтверждение человеком

Запустите приложение командой без внешнего AI из начала этого раздела, откройте новую задачу и AI-помощника. Введите «Заказы записываем в тетрадь. Нужен единый список заказов». Запросите вопросы, ответьте на часть из них и соберите карточку.

Ожидаемый результат: явно показан резервный режим; для неполной карточки возвращаются 3–6 вопросов. В предложении видны источники, ответы перенесены в соответствующие поля, неизвестное остаётся пустым. В локальном режиме исходное описание переносится в контекст, если он был пуст. Если все поля уже заполнены, вопросов может быть ноль — с объяснением.

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

Ошибочный JSON, отказ модели, недопустимые цитаты, тайм-ауты и HTTP-ошибки проверяются тестами backend/tests/test_ai.py с имитацией внешнего API. Ожидается обозначенный переход в local_stub с предупреждением, сохранением пользовательских сведений и без публикации или начисления баллов. Промпт, вход и выход приведены в docs/AI.md.

6. Обязательные действия и защита от потери ввода

  • На последнем шаге редактора без отметки проверки кнопка публикации недоступна. Если название пустое, попытка публикации после отметки возвращает к названию с ошибкой.
  • Измените поле после отметки подтверждения: отметка сбрасывается. При выходе из редактора или смене роли с несохранённым вводом показывается предупреждение; можно продолжить редактирование.
  • Через Swagger UI отправьте запрос публикации неподтверждённой карточки с ролью бизнеса: API должен отказать. Запрос изменения карточки без заголовка роли или с ролью студента возвращает 403. Демонстрационный заголовок можно подставить вручную — это не проверка личности.

7. Сохранность после перезапуска

Остановите приложение через Ctrl-C и запустите его с тем же APP_DB_PATH или с той же базой по умолчанию. Опубликованные правки, черновики, сохранённые навыки и решения по квестам должны остаться; начальные данные не должны продублироваться. После обновления страницы снова выберите нужную роль и тот же профиль для сравнения. Оба локальных сервиса должны снова стать доступны на портах 5173 и 8000.

8. Качество критериев влияет на баллы

В задаче из сценария 2 добавьте критерий «Всё должно работать хорошо». Ожидаются статус «нужно уточнить», объяснение и отсутствие дополнительных баллов. Замените на «100 строк импортируются без потерь; фильтр отвечает до 1 секунды»: предварительная оценка увеличится на 15, с 55 до 70. До подтверждения и обновления публикации каталог показывает прежние 55. После публикации — 70. Число в посторонней фразе, например «Нашей компании 10 лет», не должно засчитываться как критерий успеха.

9. Отклик на слабую задачу и ручное решение

  1. В роли студента откройте пекарню с 20 баллами, выберите команду и отправьте идею, план, срок 7 дней и демонстрационную ссылку https://example.com/orders-demo. Прикрепите fixtures/proposal_demo.pdf. Отклик появляется в разделе предложений этой команды со статусом «На рассмотрении» и доступным для скачивания PDF; команда автоматически не выбирается.
  2. Переключитесь на бизнес, откройте предложения пекарни, сравните новый отклик с исходным предложением Qadam Web. Выберите новый отклик и оставьте комментарий. В студенческом режиме для той же команды видны решение и комментарий.
  3. Выберите ещё один отклик на эту задачу: первый выбор остаётся. Отклоните любой из них или верните на рассмотрение — остальные статусы не меняются. Перезапустите приложение и убедитесь, что решения сохранены.
  4. Попробуйте отправить пустую идею, срок 0, ссылку javascript:alert(1), файл другого формата или PDF больше 10 МиБ: запрос не должен сохраниться. На неопубликованный черновик отклик отправить нельзя. Сохранение квеста не создаёт предложение автоматически.

10. Сквозная демонстрация до пяти минут

Один подготовленный пример «Предзаказы пекарни без потерь» проходит путь: слабое описание → предварительные 20 → 70 → 100 → ручное подтверждение и публикация → самостоятельное предложение Qadam Web → ручной выбор бизнеса. Пошаговый порядок, тексты для вставки и реплики для защиты находятся в DEMO_5_MIN.md; исходные данные — в demo_presentation.json.

23 сентября 2026 года этот путь пройден в интерфейсе работающего MVP. От первого ввода до ручного выбора прошло 2 минуты 32 секунды, до показа решения студенту — 2 минуты 42 секунды, без времени подготовки окна. Опубликованная карточка получила 100 баллов после реальной AI-проверки. Пользовательская запись добавлена в проект: summary.mp4, длительность 3 минуты 23 секунды. Длительность видео отличается от замера действий в интерфейсе; обе укладываются в пять минут. PDF, генерация вопросов и сборка карточки не входили в этот короткий показ и проверялись отдельно.

Автоматические проверки

Команды выполняются из корня после установки зависимостей:

backend/.venv/bin/python -m pytest backend/tests -q
backend/.venv/bin/python -m pip check
npm --prefix frontend run typecheck
npm --prefix frontend run lint
npm --prefix frontend run build

Перед сборкой остановите запущенный Next.js, чтобы процессы не использовали одновременно одну папку .next. Backend-тесты создают отдельные временные базы и не меняют рабочие данные. Проверки внешнего AI используют httpx.MockTransport и не требуют ключа или платных вызовов.

Последний полный прогон от 23 сентября 2026 года: 297 backend-тестов пройдены, TypeScript, ESLint и production-сборка успешны. Есть одно предупреждение Starlette об устаревающем httpx в TestClient. Новое расширение описания проверено как с имитацией ошибок провайдера, так и реальными запросами к gpt-4.1-mini: переформулировка, сохранение ограничений и атрибуции чужого примера, отказ от сомнительного варианта. В браузере проверены обе кнопки расширения, отмена, ручное редактирование, применение к одному полю и сброс прежнего подтверждения. Результаты и ограничения — DESCRIPTION_EXPANSION.md.

Предыдущие прогоны наград (начисление 100 баллов, покупки, сохранность после обновления, мобильная комната), pip check и проверки короткого бессмысленного ввода описаны в STAGE3_VERIFICATION.md; PDF и отклики — в STAGE2_VERIFICATION.md. Сопоставление всех обязательных модулей с кейсом и оставшиеся замечания — CRITERIA_AUDIT.md.

При подготовке комплекта сдачи отдельно проверена чистая установка из исходников без .env, базы и готовых зависимостей: setup.py, pip check, npm ci и production-сборка прошли. Проверены исходное наполнение новой базы, отсутствие дублей после повторного старта и резервный AI-режим. Подробности, версия кода и границы этой проверки — в подробной инструкции запуска.

Структура

backend/app/          FastAPI, модели, рейтинг, SQLite и стартовые данные
backend/tests/        интеграционные проверки API
frontend/app/         Next.js, основной интерфейс
frontend/components/ компоненты интерфейса
frontend/lib/         общие TypeScript-типы и API-клиент
fixtures/             присланный набор из 20 записей, его описание и тестовый PDF
scripts/              установка и локальный запуск
docs/                 контракт и описание проверок

Подробности: отклики и PDF, проверка качества, последняя проверка расширения описания, отчёт этапа наград, исторический контракт первой части, исторический план первой части.

Если запуск не удался

  • Порт занят: проверьте уже открытые терминалы с Next.js/Uvicorn. Остановите свой предыдущий запуск через Ctrl-C или воспользуйтесь уже работающим приложением. Скрипт не освобождает порты принудительно.
  • Нет Python, Node.js или npm: установите требуемые инструменты и повторите python3 scripts/setup.py --check.
  • Модули не найдены: повторите python3 scripts/setup.py; для backend используйте Python именно из backend/.venv.
  • Интерфейс не получает данные: проверьте /api/health на порту 8000 и вывод обоих сервисов. Next.js должен обращаться к локальному FastAPI.
  • Нет production-сборки: сначала выполните npm --prefix frontend run build, затем запускайте режим --production.
  • Предупреждение Starlette про httpx: текущие тесты проходят; зависимость предупреждает о будущем переходе TestClient на httpx2. Это не ошибка запуска приложения.
Звёзды
⭐ 0
Форки
0
Язык
TypeScript
Последний push
в прошлом месяце
Коммиты
9
Авторы
1
Файлы
169
Ветки
1

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

Ruslan Zagidullin 9

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

  • 2026-09-23 17:42docs: add recorded demo and reproducible presentation scenarioRuslan Zagidullin
  • 2026-09-23 17:16docs: prepare submission with quick and detailed launch guidesRuslan Zagidullin
  • 2026-09-23 17:07feat(ai): add reviewed description expansion for business tasksRuslan Zagidullin
  • 2026-09-23 16:47docs: audit all HackAlem criteria and verify live AI workflowRuslan Zagidullin
  • 2026-09-23 16:21feat: add team reward rooms and semantic AI task scoringRuslan Zagidullin
  • 2026-09-23 15:56feat: add team proposals with PDF and quality-based readinessRuslan Zagidullin
  • 2026-09-23 15:16docs: document launch architecture rating and test scenariosRuslan Zagidullin
  • 2026-09-23 15:06feat: build task marketplace with readiness scoring and AI assistantRuslan Zagidullin
Все коммиты (9)
  • 2026-09-23 13:46docs: add MVP plan and scheduled progress syncRuslan Zagidullin
Структура репозитория (169 файлов)
.env.example
.gitattributes
.gitignore
DEVELOPMENT_PLAN.md
README.md
backend/app/__init__.py
backend/app/ai.py
backend/app/config.py
backend/app/description_expansion.py
backend/app/domain.py
backend/app/main.py
backend/app/models.py
backend/app/proposal_models.py
backend/app/proposals.py
backend/app/quality.py
backend/app/reward_models.py
backend/app/rewards.py
backend/app/seed.py
backend/app/semantic_quality.py
backend/app/store.py
backend/app/uploads.py
backend/requirements.txt
backend/tests/conftest.py
backend/tests/test_ai.py
backend/tests/test_config.py
backend/tests/test_demo_data.py
backend/tests/test_description_expansion.py
backend/tests/test_part1_api.py
backend/tests/test_proposals.py
backend/tests/test_quality.py
backend/tests/test_rating_workflow.py
backend/tests/test_rewards.py
backend/tests/test_semantic_quality.py
backend/tests/test_uploads.py
backend/tests/test_workflow.py
docs/AI.md
docs/CRITERIA_AUDIT.md
docs/DEMO_5_MIN.md
docs/DESCRIPTION_EXPANSION.md
docs/PART1_CONTRACT.md
docs/PART1_VERIFICATION.md
docs/PROPOSALS.md
docs/QUALITY.md
docs/QUICKSTART.md
docs/REWARDS.md
docs/RUNBOOK.md
docs/SEMANTIC_RATING.md
docs/STAGE2_VERIFICATION.md
docs/STAGE3_VERIFICATION.md
fixtures/README_hackalem.md
fixtures/demo_presentation.json
fixtures/hackalem_synthetic_data.json
fixtures/proposal_demo.pdf
frontend/.gitignore
frontend/.npmrc
frontend/AGENTS.md
frontend/CLAUDE.md
frontend/README.md
frontend/app/globals.css
frontend/app/layout.tsx
frontend/app/page.tsx
frontend/app/reference-theme.css
frontend/components.json
frontend/components/proposals/ProposalCard.tsx
frontend/components/proposals/ProposalForm.tsx
frontend/components/proposals/ProposalsList.tsx
frontend/components/proposals/ProposalsPage.tsx
frontend/components/proposals/TeamPicker.tsx
frontend/components/proposals/proposals.css
frontend/components/rewards/ProjectCompletionDialog.tsx
frontend/components/rewards/RewardsPage.tsx
frontend/components/rewards/RoomScene.tsx
frontend/components/rewards/completion.module.css
frontend/components/rewards/rewards.module.css
frontend/components/tasks/AIAssistant.tsx
frontend/components/tasks/DescriptionExpander.tsx
frontend/components/tasks/QualityReview.tsx
frontend/components/tasks/RatingPanel.tsx
frontend/components/tasks/TaskDetails.tsx
frontend/components/tasks/TaskEditor.tsx
frontend/components/tasks/description-expander.module.css
frontend/components/tasks/quality.module.css
frontend/components/tasks/tasks.css
frontend/components/ui/accordion.tsx
frontend/components/ui/alert-dialog.tsx
frontend/components/ui/alert.tsx
frontend/components/ui/aspect-ratio.tsx
frontend/components/ui/attachment.tsx
frontend/components/ui/avatar.tsx
frontend/components/ui/badge.tsx
frontend/components/ui/breadcrumb.tsx
frontend/components/ui/bubble.tsx
frontend/components/ui/button-group.tsx
frontend/components/ui/button.tsx
frontend/components/ui/calendar.tsx
frontend/components/ui/card.tsx
frontend/components/ui/carousel.tsx
frontend/components/ui/chart.tsx
frontend/components/ui/checkbox.tsx
frontend/components/ui/collapsible.tsx
frontend/components/ui/combobox.tsx
frontend/components/ui/command.tsx
frontend/components/ui/context-menu.tsx
frontend/components/ui/dialog.tsx
frontend/components/ui/direction.tsx
frontend/components/ui/drawer.tsx
frontend/components/ui/dropdown-menu.tsx
frontend/components/ui/empty.tsx
frontend/components/ui/field.tsx
frontend/components/ui/form.tsx
frontend/components/ui/hover-card.tsx
frontend/components/ui/input-group.tsx
frontend/components/ui/input-otp.tsx
frontend/components/ui/input.tsx
frontend/components/ui/item.tsx
frontend/components/ui/kbd.tsx
frontend/components/ui/label.tsx
frontend/components/ui/marker.tsx
frontend/components/ui/menubar.tsx
frontend/components/ui/message-scroller.tsx
frontend/components/ui/message.tsx
frontend/components/ui/native-select.tsx
frontend/components/ui/navigation-menu.tsx
frontend/components/ui/pagination.tsx
frontend/components/ui/popover.tsx
frontend/components/ui/progress.tsx
frontend/components/ui/radio-group.tsx
frontend/components/ui/resizable.tsx
frontend/components/ui/scroll-area.tsx
frontend/components/ui/select.tsx
frontend/components/ui/separator.tsx
frontend/components/ui/sheet.tsx
frontend/components/ui/sidebar.tsx
frontend/components/ui/skeleton.tsx
frontend/components/ui/slider.tsx
frontend/components/ui/sonner.tsx
frontend/components/ui/spinner.tsx
frontend/components/ui/switch.tsx
frontend/components/ui/table.tsx
frontend/components/ui/tabs.tsx
frontend/components/ui/textarea.tsx
frontend/components/ui/toggle-group.tsx
frontend/components/ui/toggle.tsx
frontend/components/ui/tooltip.tsx
frontend/eslint.config.mjs
frontend/hooks/use-mobile.ts
frontend/lib/api.ts
frontend/lib/contracts.ts
frontend/lib/utils.ts
frontend/next.config.ts
frontend/package-lock.json
frontend/package.json
frontend/postcss.config.mjs
frontend/public/favicon.svg
frontend/scripts/build-verified.sh
frontend/scripts/execution-profile.mjs
frontend/scripts/install-ci.mjs
frontend/scripts/install-ci.sh
frontend/scripts/install-pnpm.sh
frontend/scripts/npm-install.mjs
frontend/scripts/pnpm-install.mjs
frontend/scripts/run-framework.mjs
frontend/scripts/sites-env.mjs
frontend/scripts/sites-env.sh
frontend/tsconfig.json
scripts/check_ai.py
scripts/dev.py
scripts/setup.py
summary.mp4

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

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

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