AAYMA
RU
Войти

Career Quest

Платформа Career Quest: профиль сотрудника с дефицитом навыков и готовностью к следующему грейду, объяснимые рекомендации 1–3 активностей…

Рабочий MVP
Команда «Ctrl AI» 3💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Ctrl AI
Кейс HackAlem.ai: Менеджмент — Halyk Bank · кейс 1
Стадия: Рабочий MVP

Задача кейса: «Career Quest»: AI-навигатор, связывающий навыки сотрудника с шагами развития

Суть

Платформа Career Quest: профиль сотрудника с дефицитом навыков и готовностью к следующему грейду, объяснимые рекомендации 1–3 активностей, «Лаборатория выбора» с прогнозом, HR-аналитика и импорт данных.

Как устроено

Датасет (employees/events/skills/activity_history) валидируется по JSON-схемам, движок считает skill gap и взвешенную готовность к грейду, ранжирует активности с учётом грейда, требований и истории пропусков/отказов. Симуляция показывает эффект активности до выполнения; выполнение применяет gain/max_level и пишет историю в SQLite. Опциональный GPT-выбор делает выбор среди допустимых активностей, без ключа работает локальный алгоритм. Фронтенд React работает с mock (MSW) или реальным API по bearer-токену.

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

  • skill gap analysis
  • weighted readiness
  • explainable ranking
  • what-if simulation
  • atomic JSON/CSV import
  • idempotent completion
  • MSW mocks
  • GitHub Actions container CI

Метрики

87 backend-тестов пройдено; демо: готовность E001 81.73% → 86.54% после EV002

Особенности

Объяснение конфликтующих факторов (низкий навык не определяет выбор, если в истории пропуски и отказы), «Лаборатория выбора» для сравнения вариантов без записи в БД, CI с проверкой сохранения прогресса после перезапуска контейнера.

Стек

Python · FastAPI · Pydantic 2 · SQLite · React · Vite · TypeScript · Tailwind · Docker · Docker Compose · Render

Модели

OpenAI gpt-4o-mini


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

README

README.md

Career Quest — команда Ctrl AI

hack-f746c068-ctrl-ai — командный репозиторий Ctrl AI для кейса Career Quest хакатона HackAlem AI (трек Halyk Bank). Career Quest помогает сотруднику увидеть карьерную траекторию и выбрать полезный шаг развития, а HR — понять, какие компетенции проседают. Репозиторий команды.

Текущее состояние проекта: реализованы загрузка и проверка датасета, расчёт дефицита навыков и готовности к следующему грейду, объяснимый выбор 1–3 активностей, прогноз результата и сравнение вариантов, а также HTTP API с выполнением активностей, сохранением прогресса, HR-аналитикой и импортом. Доступ сотрудника и HR проверяется по локальным демо-токенам. Стек backend: Python 3.11+, Pydantic 2, FastAPI, SQLite. Frontend поддерживает два режима: автономный mock на MSW и подключение к реальному HTTP API по bearer-токену. Маршруты и форматы FastAPI подключены через слой адаптеров. Необязательный GPT-выбор доступен в профиле и через backend API при наличии серверного ключа; без него действует локальный алгоритм. Публичная развёрнутая версия пока не указана.

Источник требований — техническое задание Career Quest, раздел «КЕЙС: CAREER QUEST». Стартовый кит организаторов с официальной схемой данных в проект ещё не добавлен.

Что можно проверить в приложении

ВозможностьГде проверитьЧто происходит
Профиль и карьерная траектория/employee/E001Роль, грейд, навыки, требования следующего уровня и готовность
Объяснимые рекомендацииПрофиль сотрудникаДо 3 шагов с учётом грейда, разрывов, требований и истории участия
Выбор с GPTКнопка «Подобрать с GPT» в реальном режимеМодель выбирает допустимую активность; интерфейс показывает источник результата
Прогноз и сравнение«Лаборатория выбора»Изменения навыков и готовности до выполнения, без записи в базу
Выполнение активностиКнопка выполнения в профилеПрименение gain/max_level, запись истории и пересчёт рекомендаций
История/employee/E001/historyЗавершения, пропуски, отказы и другие статусы участия
HR-аналитика/hr с токеном HRСредняя готовность, дефициты по навыкам и ролям, участие и сотрудники без следующего шага
Новые данные жюриSwagger → POST /dataset/import с токеном HRПроверка и атомарный импорт профилей и истории JSON/CSV

Сотрудник имеет доступ к своему профилю и истории. HR может открыть список сотрудников, любой профиль, аналитику и импорт. Проверка ролей выполняется в API. В контейнере все API-маршруты имеют префикс /api; Swagger доступен в /api/docs.

Демонстрация для жюри за 3–5 минут

  1. Запустите приложение по инструкции ниже и войдите значением token из записи с role: "employee" в access.json. На свежем демонстрационном наборе он относится к E001.
  2. Откройте профиль: Middle Backend Engineer → Senior. Готовность — 81.73%, System Design — 2 из 4. В обычных рекомендациях первый шаг — EV002 / Architecture Mentoring.
  3. Раскройте объяснение: низкий Public Speaking сам по себе не определяет выбор. Для следующего грейда критичен System Design, а история public speaking содержит два пропуска и отказ. Посмотрите прогноз EV002 без изменения профиля.
  4. Выполните EV002: System Design станет 3, готовность — 86.54%, в истории появится завершение, первой обычной рекомендацией станет EV006. Обновите страницу и убедитесь, что результат сохранён.
  5. Выйдите и войдите токеном записи с role: "hr". Откройте /hr: пересчитаны средняя готовность, разрывы и участие. Для исходного набора число завершений меняется 120 → 121.
  6. Для проверки нового сотрудника откройте /api/docs, нажмите Authorize, вставьте HR-токен и выполните POST /dataset/import: режим append, файл employees в JSON и при необходимости activity_history в CSV. Используйте новые идентификаторы и существующие роли/навыки/события. Затем откройте новый профиль под HR и проверьте рекомендации. Контракт импорта.

Числа относятся к свежей базе из backend/data/ и обычным рекомендациям. Повторное выполнение меняет состояние; отдельный GPT-выбор может предложить другой допустимый шаг. При запуске frontend в mock-режиме набор и проценты другие.

Публикация для жюри и запуск всего приложения

Frontend и API собираются в один Docker-контейнер и работают по одному адресу. Для публикации используйте готовую конфигурацию Render и краткую инструкцию. Конфигурация создаёт платный Web Service с постоянным диском для SQLite и токенов; перед созданием Render показывает стоимость. Сайт опубликован только после успешного развёртывания со статусом Live.

Для этого варианта нужен запущенный Docker с Docker Compose. Python, Node.js и зависимости устанавливаются внутри контейнера. После клонирования репозитория из его корня выполните одну команду:

docker compose up --build -d

Сайт: http://localhost:8000; API: http://localhost:8000/api/docs. Готовность сервера: http://localhost:8000/api/health возвращает {"status":"ok"}. Логи запуска: docker compose logs --tail=100 web. Токены для входа доступны владельцу окружения:

docker compose exec web cat /var/data/access.json

Передайте жюри ссылку и токены сотрудника и HR по закрытому каналу. Не публикуйте токены в репозитории.

Если Render сообщает cannot access the following repo, подключите GitHub App Render к организации, владеющей приватным репозиторием. Запрос на установку может требовать одобрения владельца организации; установка только в личный аккаунт не предоставляет доступ к репозиторию организации. После одобрения повторите создание Blueprint. Готовый render.yaml сам по себе сайт не публикует.

Для включения GPT задайте OPENAI_API_KEY в окружении Docker Compose или локальном .env и выполните docker compose up -d --force-recreate. Ключ не обязателен для запуска. Модель задаётся через CAREER_QUEST_OPENAI_MODEL (по умолчанию gpt-4o-mini). Настройки ключа на Render и проверка описаны в docs/DEPLOY.md. Прогресс и токены сохраняются в томе /var/data: пересборка и обычный docker compose down не удаляют их. docker compose down -v удаляет том вместе с данными — для обновления приложения эта команда не нужна.

Проверки и текущие ограничения

При проверке кода 4e0cdbe от 23.09.2026 прошли 87 backend-тестов:

python -m unittest discover -s backend/tests -v

Проверка TypeScript (npx tsc -b из frontend/ после установки зависимостей) на этой версии также прошла.

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

Container verification настроен на backend-тесты, сборку и запуск Docker, проверку HTTP-сценария и сохранения прогресса после перезапуска. Результаты конкретного запуска доступны во вкладке Actions.

  • Публичный сайт: подтверждённый URL пока не добавлен. Перед сдачей нужен успешный deploy, проверка входа по внешней ссылке и сама ссылка в материалах жюри.
  • Данные: используется собственный синтетический набор; совместимость с официальным стартовым китом ещё нужно проверить по его фактической схеме.
  • Вход: API использует демо-токены. При первом запуске создаются HR и один сотрудник; самостоятельной регистрации и входа по паролю в реальном API нет. Импорт нового профиля не создаёт ему учётную запись, но HR видит этот профиль.
  • Импорт: доступен через API/Swagger; формы загрузки в HR-интерфейсе пока нет. Максимум 5 MiB на файл; append дополняет набор, replace требует все 4 файла.
  • Пропуски и отказы: учитываются из импортированной истории. Кнопки записи этих действий работают только в mock-режиме; в реальном режиме они скрыты.
  • Прогресс: отражает заданный эффект активности, а не результат независимой оценки навыка. Достижение требований не повышает грейд автоматически.

Запуск для разработки

Клонируйте репозиторий и создайте окружение из его корня:

git clone https://github.com/BAITC-Hacks/hack-f746c068-ctrl-ai.git
cd hack-f746c068-ctrl-ai
python -m venv .venv

Активация в PowerShell: .venv\Scripts\Activate.ps1. В Linux/macOS: source .venv/bin/activate.

python -m pip install -r backend/requirements-dev.txt
python -m backend validate
python -m backend gaps E001
python -m backend readiness E001
python -m backend recommend E001 --limit 3
python -m unittest discover -s backend/tests -v

Запуск HTTP API одной командой после установки зависимостей:

python -m backend.api

Swagger: http://127.0.0.1:8000/docs. При первом запуске создаются рабочая SQLite-база и локальные демо-токены в backend/runtime/. Для доступа нажмите Authorize и используйте токен из backend/runtime/access.json. Подробный контракт, роли, импорт и пример проверки — в docs/API.md. Для запуска без тестов достаточно зависимостей из backend/requirements.txt.

Инструкция запуска frontend находится в frontend/README.md. Для автономного демо оставьте VITE_USE_MOCK=true. Для работы с backend укажите VITE_USE_MOCK=false, настройте VITE_API_URL, разрешите origin frontend через CAREER_QUEST_CORS_ORIGINS и войдите токеном из backend/runtime/access.json. Frontend проверит токен через GET /auth/me и добавит его в последующие запросы.

В реальном режиме frontend использует GET /employees/{id} вместо mock-маршрута /profile, извлекает историю из объединённого ответа, читает HR-сводку через GET /hr/dashboard и преобразует snake_case-ответы в модели интерфейса адаптерами из frontend/src/api/adapters.ts. При завершении активности клиент создаёт UUID для заголовка Idempotency-Key. Backend пока не имеет маршрутов skip/decline: кнопки пропуска и отказа работают только в mock-режиме, но такие статусы из загруженной истории отображаются и при работе с FastAPI.

Проверка своего набора и расчёт на нём:

python -m backend --data-dir path/to/dataset validate
python -m backend --data-dir path/to/dataset gaps E001
python -m backend --data-dir path/to/dataset readiness E001
python -m backend --data-dir path/to/dataset recommend E001 --limit 3

Успех возвращает JSON в stdout и exit code 0. Ошибка возвращает JSON в stderr и exit code 1. Загрузка не возвращает частично валидный набор.

Устройство текущей версии

backend/data_loader.py загружает и проверяет все четыре файла как единый набор. backend/models.py задаёт поля и ограничения, backend/schemas/ содержит JSON-схемы, backend/engine/skill_gap.py считает разрывы, backend/engine/grade_progress.py — готовность, а backend/engine/recommendation.py выбирает активности. backend/__main__.py предоставляет команды validate, gaps, readiness и recommend. Генератор и тесты находятся в backend/scripts/ и backend/tests/. backend/engine/progress.py применяет завершение активности, backend/engine/simulation.py без записи показывает эффект активности и сравнивает два варианта по тем же правилам ранжирования, backend/engine/hr.py собирает HR-показатели, backend/api/ предоставляет HTTP API, backend/storage.py сохраняет рабочий снимок и ключи повторных запросов в SQLite.

Основной сценарий из ТЗ — профиль → рекомендация с объяснением → выполнение активности → обновлённый прогресс → срез для HR — реализован в API и подключён во frontend. Алгоритм рекомендаций детерминированный по умолчанию; отдельный endpoint может выбрать первый шаг через GPT из допустимых локальных вариантов. CLI считает исходные JSON/CSV, API использует отдельную SQLite-базу: завершённые через HTTP активности не переписывают демо-файлы.

Этап 1: данные и импорт

В backend/data/ находится воспроизводимый демонстрационный набор:

ФайлСодержание
employees.json48 синтетических профилей; роль, грейд, стаж, текущие навыки
skills.json16 навыков, 4 карьерных трека, порядок грейдов и требования
events.json26 активностей, целевые роли, предполагаемый прирост и предел уровня
activity_history.csv235 записей участия с датой и статусом

Все профили, названия активностей, история, требования и веса созданы командой для демонстрации. Реальные персональные данные и внешние классификаторы не использованы. Это не официальный датасет организаторов и не подтверждённая HR-матрица. При появлении официальной схемы потребуется адаптер к внутреннему контракту.

Контракт версии 1.0 определён в backend/models.py; машиночитаемые схемы находятся в backend/schemas/. JSON Schema описывает структуру, а Python-валидатор дополнительно проверяет уникальность, ссылки и ограничения между файлами. Для CSV схема history описывает записи после разбора; точный заголовок:

record_id,employee_id,event_id,status,event_date

Правила:

  • JSON и CSV читаются как UTF-8; BOM допускается. Даты — YYYY-MM-DD.
  • ID уникальны в пределах сущности. Все ссылки на навыки, роли, сотрудников и события должны существовать.
  • Уровни — целые числа 0–5; требования, gain и max_level — 1–5.
  • Каталог может ограничить отдельный навык меньшим max_level; импорт проверяет это ограничение.
  • Роль задаёт собственный упорядоченный список уникальных грейдов.
  • У каждого грейда есть непустые требования и хотя бы один обязательный навык.
  • Requirement содержит level, importance (0 < вес <= 1), mandatory.
  • Неизвестные поля, повторяющиеся JSON-ключи, неверные статусы и даты отклоняются.
  • Статусы истории: invited, enrolled, completed, skipped, declined.
  • Пустая история и пустой каталог событий допустимы; профили и матрица навыков обязательны.

История описывает отдельные участия, поэтому один event_id может повторяться у сотрудника в разные даты. Архивные события сохраняются для целостности истории. Текущие навыки — готовый снимок: загрузчик не начисляет повторно gain из истории. Gain — условный ожидаемый эффект демо, а не доказательство освоения навыка.

Генератор использует фиксированный seed 42 и не обращается к сети:

python -m backend.scripts.generate_demo_data --output demo-copy

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

python -m backend.scripts.generate_demo_data --force --schemas backend/schemas

Этап 2: Skill Gap Engine

calculate_skill_gaps(employee, career_track) — чистая функция. get_employee_skill_gaps(dataset, employee_id) находит профиль и его трек. На границе приложения используется только полностью проверенный Dataset.

Следующий грейд берётся из порядка в треке. Для каждого требования этого грейда:

gap = max(required - current, 0)
normalized_gap = gap / required
weighted_gap = normalized_gap * importance
fulfilled = gap == 0

Отсутствующий навык считается уровнем 0 — это явное допущение демонстрационного контракта, а не вывод о способностях реального сотрудника. В реальной системе неизмеренный уровень стоит хранить отдельно и запрашивать оценку.

Результат содержит все целевые навыки, включая выполненные и дополнительные (mandatory=false), в стабильном порядке skill_id. Навыки сотрудника вне требований не включаются и не компенсируют дефицит других навыков. Счётчики различают общее число навыков с gap и число обязательных навыков с gap. Это не рейтинг активностей.

Для E001, Middle Backend Engineer → Senior:

НавыкТекущийТребуетсяGapВесWeighted gap
System Design2421.00.5
Python3411.00.25
Public Speaking1210.40.2
Communication3300.80
SQL4401.00
Testing4401.00

Public Speaking здесь дополнительный, остальные навыки обязательные. Всего 6 целевых навыков, 3 выполнены, 3 имеют gap, из них 2 обязательные. История E001 содержит два пропуска и отказ от public speaking; она не влияет на gap, но учитывается в рекомендациях.

Этап 3: рекомендации активностей

get_recommendations(dataset, employee_id, limit=3) возвращает до трёх активных событий для роли сотрудника. Оно использует текущий грейд, требования следующего грейда, дефицит и важность навыков, а также историю участия. Подходят только активности, которые действительно сокращают хотя бы один разрыв с учётом gain и max_level. Расчёт прогнозирует эффект, но пока не изменяет профиль.

Для каждого затронутого навыка вклад равен (сокращение разрыва / требуемый уровень) × importance × коэффициент обязательности. Коэффициент обязательности равен 1.5 для mandatory=true и 1 для дополнительного навыка. Вклады суммируются. Множитель истории равен clamp(1 + 0.05 × completed − 0.15 × skipped − 0.25 × declined − 0.10 × same_event_completed, 0.25, 1.25). История учитывается по событиям, развивающим те же навыки; повтор уже завершённой активности получает дополнительное снижение. Итоговая оценка — произведение суммы вкладов и множителя истории. При равной оценке порядок определяется event_id. Коэффициенты — явная эвристика демо, а не обученная модель или утверждённая HR-политика.

Ответ содержит использованные значения и текстовое объяснение. Для E001 первым выбирается Architecture Mentoring: System Design 2/4 для перехода Middle → Senior, после активности прогнозируется 3/4; ранее по навыку было одно завершение. Public Speaking имеет уровень 1/2, но это дополнительное требование, а история содержит два пропуска и отказ. Поэтому минимальный навык не определяет выбор. Статусы без рекомендаций: top_grade, no_skill_gaps, no_matching_activity.

Необязательный GPT-слой

POST /employees/{id}/ai/recommendations (Swagger: /docs) может выбрать первый шаг среди максимум 12 подходящих активностей. В модель передаются только роль, грейды, ID вариантов, измеренные разрывы, возможные приросты и агрегированные счётчики участия — без имени, ID сотрудника, дат и отдельных записей истории. Backend проверяет возвращённый ID и строит фактическое объяснение из своих расчётов. Модель не изменяет навыки и состояние. Остальные до двух шагов берутся из локального ранжирования. Вызов использует store=false и тайм-аут 7 секунд.

Для включения задайте OPENAI_API_KEY в окружении процесса backend (не в репозитории и не в браузере); при необходимости задайте CAREER_QUEST_OPENAI_MODEL, по умолчанию gpt-4o-mini. Ключ лучше задать через защищённые настройки запуска или менеджер секретов. Не вставляйте действующий ключ в чат, README или исходники. Каждый вызов может расходовать лимит организации. При отсутствии ключа или ошибке внешнего API endpoint автоматически возвращает локальный топ-3 с source=rules и причиной в fallback_reason; обычный GET /recommendations всегда локальный. В профиле настоящего API есть кнопка Подобрать с GPT: запрос отправляется только по нажатию, результат показывает источник (GPT или правила), объяснение и выбранную активность. Можно посмотреть прогноз и выполнить этот шаг. Альтернативная проверка — Swagger (/api/docs в контейнере). Подробности ответа и прав доступа — в docs/API.md.

Этап 4: готовность к следующему грейду

calculate_grade_readiness(employee, career_track) использует результат Skill Gap Engine. Для каждого навыка целевого грейда рассчитывается доля освоения с пределом 100%:

skill_progress = min(current / required, 1)
readiness_percent = 100 × Σ(skill_progress × importance) / Σ(importance)

Общий процент учитывает все требования, включая дополнительные навыки. Отдельный mandatory_readiness_percent рассчитывается той же формулой только по обязательным навыкам. meets_mandatory равен true, когда закрыт каждый обязательный навык; его нельзя определять по округлённому проценту. Оба процента возвращаются без округления, а интерфейс при необходимости округляет их только для отображения. Процент не означает автоматического повышения: решение о грейде остаётся за HR.

Для E001 общий взвешенный результат: 100 × 4.25 / 5.2 ≈ 81.73%, обязательная часть: 100 × 4.05 / 4.8 = 84.375%. System Design даёт 2/4 = 50%, Python — 3/4 = 75%. Так как оба навыка обязательны и имеют дефицит, meets_mandatory=false. У сотрудника на последнем грейде нет следующей цели: статус top_grade, readiness_percent=null, meets_mandatory=null.

Этап 5: выполнение активности и HR-сводка

Общая функция complete_activity(dataset, employee_id, event_id, record_id, completed_on) возвращает новый проверенный Dataset и CompletionResult: изменения навыков, готовность и рекомендации до и после. Прирост ограничен формулой new = max(old, min(old + gain, max_level)). В историю добавляется completed; старые завершения не начисляются повторно. Повтор с тем же record_id возвращает already_completed без прироста; другой сотрудник или событие с этим ID дают ошибку. Разные ID могут обозначать повторное прохождение. Грейд автоматически не повышается.

Для E001 выполнение EV002 меняет System Design 2 → 3, готовность 81.73% → 86.54% и первый рекомендуемый шаг с EV002 на EV006. API преобразует доменный результат в HTTP-контракт через backend/api/presenters.py и сохраняет его вместе с состоянием в SQLite. Идемпотентность HTTP определяется заголовком Idempotency-Key, а не передаваемым клиентом ID истории. Frontend генерирует для новой попытки UUID v4 через crypto.randomUUID() (или безопасный fallback на crypto.getRandomValues()), передаёт его в этом заголовке и адаптирует ответ завершения к своей модели прогресса.

get_hr_summary(dataset) возвращает частые дефициты, срез по ролям, сотрудников без шага с причиной и признаком необходимости действия, а также участие по событиям и статусам. Считаются записи истории и уникальные сотрудники. Средняя готовность исключает сотрудников на последнем грейде. Представление get_hr_dashboard(dataset) в backend/api/presenters.py адаптирует эту сводку к HTTP-контракту и сохраняет average_readiness_percent и role_skill_deficits. Доступ к нему разрешён только HR.

Дополнительный блок: прогноз и сравнение вариантов

simulate_activity(dataset, employee_id, event_id) рассчитывает гипотетическое завершение через тот же complete_activity, что использует настоящий запрос. Оно возвращает изменения каждого навыка с gain и max_level, разрывы и готовность до/после, а также рекомендации после предполагаемого завершения. Новый снимок датасета отбрасывается: история и навыки в SQLite не меняются. Прогноз включает влияние гипотетической записи completed на последующие рекомендации; грейд автоматически не меняется.

compare_activities сопоставляет две активные и полезные для следующего грейда активности одной роли. Используется тот же полный список оценённых кандидатов, из которого выбираются первые три рекомендации, поэтому сравнить можно и вариант вне топ-3. Ответ показывает оценку, сокращение взвешенного разрыва, множитель истории, изменения готовности для каждого варианта и объяснение выбора. При равенстве оценок действует стабильный порядок event_id. Маршруты доступны только самому сотруднику или HR: GET /employees/{id}/simulate/{event_id} и GET /employees/{id}/compare?first_event_id=A&second_event_id=B. Список всех допустимых альтернатив для выбора даёт GET /employees/{id}/comparison-options.

Это отдельный необязательный блок принятия решения, а не автоматическое начисление навыков. Лаборатория выбора работает как с mock-обработчиками, так и с реальными маршрутами backend; численные оценки разных режимов могут отличаться, поскольку mock использует локальный демонстрационный расчёт.

Проверочные профили

IDСценарий
E001Точные разрывы и выбор с учётом истории
E002Нет измеренных навыков и истории; все целевые навыки считаются нулевыми
E003Требования превышены; gap остаётся нулевым, повышения автоматически нет
E004Последний грейд; status=top_grade, target_grade=null, gaps={}
E005Единственный gap — Testing; подходящей активности в демо-каталоге нет

Последний грейд отличается от выполненных требований: он не означает готовность 100%. Неизвестный сотрудник даёт employee_not_found; невалидная роль или грейд отклоняются при импорте. Пустые требования — ошибка данных.

Тесты проверяют импорт и связи, воспроизводимость, ошибки файлов, точные расчёты, пропущенные и избыточные навыки, изменение процента готовности после роста навыка, конфликтующие факторы рекомендаций, новый профиль и его историю, ограничения активности по роли, статусу и max_level, отсутствие подходящих шагов, последний грейд, отсутствие мутации входа и инварианты всех 48 профилей.

API-тесты дополнительно проверяют права доступа, выполнение и пересчёт, идемпотентность запросов, сохранение после перезапуска, конкурентные изменения, добавление нового профиля с историей и откат невалидного импорта. HR-показатели считают записи участия; последний грейд и закрытые требования помечаются отдельными причинами отсутствия рекомендаций, а не признаками низкой вовлечённости.

Звёзды
⭐ 0
Форки
2
Язык
Python
Последний push
в прошлом месяце
Коммиты
26
Авторы
4
Файлы
118
Ветки
2

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

gostevandrey9-bit 10vwgit 8Kavkaz228 6Vadim 2

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

  • 2026-09-23 17:59docs: add jury walkthrough and verified project statusvwgit
  • 2026-09-23 17:50feat: package GPT-enabled app for deployment and verify container in CIgostevandrey9-bit
  • 2026-09-23 17:47merge: integrate shared container deployment and frontend APIgostevandrey9-bit
  • 2026-09-23 17:46feat: add optional GPT recommendations with safe fallbackgostevandrey9-bit
  • 2026-09-23 17:41Add single-service Render deployment for Career Questvwgit
  • 2026-09-23 17:27feat(frontend): integrate authenticated backend API and idempotent completionKavkaz228
  • 2026-09-23 16:35Expose HR readiness and role deficitsvwgit
  • 2026-09-23 16:22feat: add career activity decision labgostevandrey9-bit
Все коммиты (26)
  • 2026-09-23 16:08feat(frontend): вход и регистрация, роли HR/сотрудник, зелёно-золотая палитраKavkaz228
  • 2026-09-23 15:47feat(frontend): фронтенд Career Quest на моковом API Сделан фронтенд Career Quest (React + Vite + TypeScript + Tailwind). Добавлено: Список сотрудников по разделам (44 человека в 5 разделах) с поискоKavkaz228
  • 2026-09-23 15:47feat(frontend): дизайн, смягчение цветовKavkaz228
  • 2026-09-23 15:38Merge team progress and frontend changes with API integrationgostevandrey9-bit
  • 2026-09-23 15:35Add authenticated API with transactional progress and dataset importgostevandrey9-bit
  • 2026-09-23 15:16Test imported profile activity progressvwgit
  • 2026-09-23 15:14Add activity progress and HR summariesvwgit
  • 2026-09-23 15:04CommitKavkaz228
  • 2026-09-23 15:00Add Career Quest frontendKavkaz228
  • 2026-09-23 14:38Add explainable activity recommendationsvwgit
  • 2026-09-23 14:30Add weighted next-grade readiness calculationgostevandrey9-bit
  • 2026-09-23 14:12Merge repository requirements and Career Quest implementationgostevandrey9-bit
  • 2026-09-23 14:10Combine local and repository README contentgostevandrey9-bit
  • 2026-09-23 13:59docs: add Career Quest agent instructionsvwgit
  • 2026-09-23 13:57Document dataset validation and skill gap enginegostevandrey9-bit
  • 2026-09-23 13:32Merge pull request #1 from BAITC-Hacks/caseVadim
  • 2026-09-23 13:30Добавил файл с кейсомVadim
  • 2026-09-23 13:18docs: add Russian project READMEvwgit
Структура репозитория (118 файлов)
.dockerignore
.env.example
.github/workflows/container.yml
.gitignore
AGENTS.md
Dockerfile
HackAlem AI_ Career Quest - платформа геймификации жизненного цикла сотрудника..md
README.md
backend/__init__.py
backend/__main__.py
backend/api/__init__.py
backend/api/__main__.py
backend/api/ai.py
backend/api/app.py
backend/api/auth.py
backend/api/imports.py
backend/api/presenters.py
backend/data/activity_history.csv
backend/data/employees.json
backend/data/events.json
backend/data/skills.json
backend/data_loader.py
backend/engine/__init__.py
backend/engine/grade_progress.py
backend/engine/hr.py
backend/engine/progress.py
backend/engine/recommendation.py
backend/engine/simulation.py
backend/engine/skill_gap.py
backend/models.py
backend/requirements-dev.txt
backend/requirements.txt
backend/schemas/dataset.schema.json
backend/schemas/employees.schema.json
backend/schemas/events.schema.json
backend/schemas/history.schema.json
backend/schemas/skills.schema.json
backend/scripts/__init__.py
backend/scripts/generate_demo_data.py
backend/scripts/smoke_container.py
backend/storage.py
backend/tests/__init__.py
backend/tests/test_ai_recommendations.py
backend/tests/test_api.py
backend/tests/test_cli.py
backend/tests/test_dataset.py
backend/tests/test_grade_progress.py
backend/tests/test_hr.py
backend/tests/test_hr_dashboard.py
backend/tests/test_progress.py
backend/tests/test_progress_response.py
backend/tests/test_recommendation.py
backend/tests/test_simulation.py
backend/tests/test_skill_gap.py
backend/tests/test_storage.py
backend/tests/test_web.py
backend/web.py
compose.yaml
docs/API.md
docs/DEPLOY.md
frontend/.env.development
frontend/.env.production
frontend/.gitignore
frontend/.oxlintrc.json
frontend/README.md
frontend/index.html
frontend/package-lock.json
frontend/package.json
frontend/postcss.config.js
frontend/public/favicon.svg
frontend/public/icons.svg
frontend/public/mockServiceWorker.js
frontend/src/api/adapters.ts
frontend/src/api/auth.ts
frontend/src/api/client.ts
frontend/src/api/endpoints.ts
frontend/src/api/mock/auth.ts
frontend/src/api/mock/browser.ts
frontend/src/api/mock/data/employees.ts
frontend/src/api/mock/data/events.ts
frontend/src/api/mock/data/skills.ts
frontend/src/api/mock/engine.ts
frontend/src/api/mock/handlers.ts
frontend/src/auth/AuthContext.tsx
frontend/src/auth/guards.tsx
frontend/src/auth/session.ts
frontend/src/components/hr/ActivityParticipationTable.tsx
frontend/src/components/hr/GapHeatmap.tsx
frontend/src/components/hr/StatusFunnel.tsx
frontend/src/components/hr/TopGapsChart.tsx
frontend/src/components/hr/UncoveredTable.tsx
frontend/src/components/labels.ts
frontend/src/components/layout/AppLayout.tsx
frontend/src/components/profile/GapList.tsx
frontend/src/components/profile/ProfileHeader.tsx
frontend/src/components/profile/SkillGapChart.tsx
frontend/src/components/progress/CompleteModal.tsx
frontend/src/components/recommendations/AiRecommendation.tsx
frontend/src/components/recommendations/DecisionLab.tsx
frontend/src/components/recommendations/RecommendationCard.tsx
frontend/src/components/recommendations/ScoreBreakdown.tsx
frontend/src/components/ui/index.tsx
frontend/src/hooks/queries.ts
frontend/src/index.css
frontend/src/main.tsx
frontend/src/pages/AuthPage.tsx
frontend/src/pages/EmployeesPage.tsx
frontend/src/pages/HistoryPage.tsx
frontend/src/pages/HrPage.tsx
frontend/src/pages/ProfilePage.tsx
frontend/src/router.tsx
frontend/src/types/index.ts
frontend/tailwind.config.js
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vite.config.ts
render.yaml
Ветки (2)

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

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

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