Career Quest
Laravel-приложение: личный кабинет сотрудника с разрывами навыков до следующего грейда и рекомендациями активностей, плюс HR-аналитика и импорт…
О проекте
Команда: Silver Chariot
Кейс HackAlem.ai: Менеджмент — Halyk Bank · кейс 1
Стадия: Доведённый продукт
Задача кейса: «Career Quest»: AI-навигатор, связывающий навыки сотрудника с шагами развития
Суть
Laravel-приложение: личный кабинет сотрудника с разрывами навыков до следующего грейда и рекомендациями активностей, плюс HR-аналитика и импорт данных.
Как устроено
Датасет кейса (200 сотрудников, 40 активностей, 2743 записи истории) импортируется в SQLite. RecommendationEngine подбирает 1–3 будущие активности с учётом навыков, карьерной цели, расписания и истории, опционально через внешний LLM (LlmService), иначе детерминированный fallback с обоснованием. Отметка «выполнено» пересчитывает навыки (с ограничениями по gain/max_level) и готовность к грейду; HR видит проседающие навыки и сотрудников без следующего шага.
Ключевые решения
- deterministic recommendation engine
- skill gap analysis
- grade readiness
- LLM with fallback
- role-based access control
Особенности
Фиксированная дата среза данных (2026-10-01) для воспроизводимой проверки жюри; разграничение доступа сотрудник/HR с проверками 403/404; импорт с откатом всего пакета при ошибке. Команда активно использовала агентные скиллы (.claude/.agents) для Laravel.
Стек
PHP 8.4 · Laravel 13 · SQLite · Blade · Tailwind CSS · Docker · Docker Compose
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-f129848b-silver-chariot.
README
README.mdCareer Quest
AI-навигатор развития сотрудника: показывает разрывы в навыках, рекомендует следующий шаг и пересчитывает прогресс после завершения активности. HR видит аналитику команды и может загружать проверочные данные.
Для жюри: начните с запуска через Docker, создайте два аккаунта и пройдите сценарий проверки. Внешний AI-ключ для демонстрации не требуется.
Дата демонстрации — 1 октября 2026 года (
2026-10-01). Для рекомендаций и пересчёта прогресса используется дата среза данных, а не текущая дата компьютера. Менять системную дату не нужно.
Быстрый запуск для жюри — Docker
Нужны Docker с командой docker compose и свободный порт 8000. Выполняйте команды в корне скачанного репозитория, где находится docker-compose.yml. PHP, Node.js и базу данных отдельно устанавливать не нужно.
1. Запустите приложение
cp .env.example .env
docker compose up --build -d
docker compose logs -f app
Копируйте .env.example только при первом запуске; если .env уже настроен, сохраните его. Дождитесь сообщения о запуске сервера, затем нажмите Ctrl+C, чтобы выйти из просмотра логов. Приложение продолжит работать в фоне.
При первом запуске автоматически создаётся SQLite-база, применяются миграции и загружается стартовый набор: 200 сотрудников, 40 активностей и 2743 записи истории. Вручную импортировать стартовые данные не нужно.
2. Создайте аккаунты сотрудника и HR
В том же терминале выполните по очереди:
docker compose exec app php artisan users:create [email protected] --employee=E0001
docker compose exec app php artisan users:create [email protected] --name="HR Administrator" --hr
Каждая команда запросит Password. Придумайте и сохраните пароль для соответствующего аккаунта: не менее 12 символов, не более 72 байт. При вводе символы не отображаются — это нормально. Не добавляйте к этим командам --no-interaction.
Готовых аккаунтов и общих паролей нет. Эти команды создают доступ только в вашей установке. Роль HR назначается из серверной консоли; посетитель сайта не может выдать её себе.
3. Откройте форму входа
Откройте http://localhost:8000/login и используйте созданные данные:
| Что проверить | Пароль | |
|---|---|---|
| Личный кабинет сотрудника E0001 | [email protected] | Заданный первой командой |
| HR: все профили, аналитика и импорт | [email protected] | Заданный второй командой |
Без API-ключа рекомендации работают через детерминированный движок: учитывают навыки, карьерную цель и историю, содержат обоснование и пометку fallback. Чтобы проверить внешний LLM, задайте ключ и провайдера в .env по разделу AI-слой, затем выполните docker compose up -d.
Сценарий проверки для жюри
Как читать даты: будущие сессии активностей определяются относительно 1 октября 2026 года, включая сам этот день. Например, сессия 2026-10-07 считается предстоящей независимо от дня запуска приложения. При нажатии «Отметить выполненной» в историю записывается дата завершения 2026-10-01. Это позволяет проверять исходный набор данных в одинаковых условиях в любой день.
1. Развитие сотрудника
Войдите как [email protected] и откройте свой профиль E0001 (/employees/E0001). На странице видны карьерная лестница Junior → Lead, текущие навыки, разрывы до Middle и история активностей.
- Нажмите «Получить рекомендацию». Появятся до трёх активностей с объяснением выбора и факторами, связанными с профилем. Перезагрузите страницу — рекомендации сохранятся.
- На одной карточке нажмите «Отметить выполненной». Проверьте изменение навыков, готовности к следующему грейду и запись в истории.
- Получите рекомендации ещё раз: подбор учитывает обновлённый прогресс. Завершённая активность не предлагается повторно, кроме повторяемого клуба EV_036.
2. HR-аналитика
Нажмите «Выйти» и войдите как [email protected]. Откроется режим HR со всеми сотрудниками.
- В разделе «Сотрудники» проверьте поиск и фильтры по роли и грейду, откройте любой профиль.
- В «HR-аналитика» (
/hr) посмотрите проседающие навыки, сотрудников без рекомендованного шага и участие в активностях. - В «Активности» (
/hr/events) доступны поиск, фильтры, создание и редактирование активностей.
Режим определяется назначенной ролью аккаунта при входе. Для просмотра команды используйте HR-аккаунт, для личного профиля — аккаунт сотрудника.
3. Проверочные данные жюри
Войдя как HR, откройте «Импорт данных» (/admin/upload) и загрузите employees.json и/или activity_history.csv. Образцы формата находятся в docs/case_1/career_quest_dataset/:
- JSON содержит объект
{"employees": [...]}. - CSV содержит заголовок и столбцы как в стартовом файле истории.
После загрузки появится число импортированных записей. Найдите проверочного сотрудника в списке, откройте профиль и получите рекомендацию. Повторная загрузка обновляет записи по их ID; ошибка в одном из файлов отменяет весь импорт. Импорт профиля заменяет его оценки навыков и сбрасывает сохранённые рекомендации затронутых сотрудников.
Для просмотра загруженного профиля из HR новый аккаунт не нужен. Если хотите проверить вход от имени этого сотрудника, создайте отдельный аккаунт командой users:create с его --employee=ID.
4. Разграничение доступа
| Действие | Ожидаемый результат |
|---|---|
Выйти и открыть /employees | Перенаправление на форму входа |
Войти сотрудником E0001 и открыть /employees/E0002 | 404 — чужой профиль скрыт |
Тем же сотрудником открыть /hr или /admin/upload | 403 — доступ запрещён |
| Проверить шапку личного кабинета сотрудника | Переключателя в HR нет |
| Войти HR и открыть список сотрудников и импорт | Доступ разрешён |
Права и привязка к профилю хранятся в аккаунте на сервере. Режим интерфейса и старые демонстрационные сессии не выдают HR-права.
Повторный запуск и частые вопросы
docker compose stop # остановить приложение, сохранив данные
docker compose up -d # снова запустить
Аккаунты, импортированные данные и прогресс сохраняются в томе sqlite_data. Повторно создавать аккаунты не нужно.
| Ситуация | Что сделать |
|---|---|
| Страница пока не открывается | Посмотреть docker compose logs --tail=100 app и дождаться запуска сервера |
| Порт 8000 занят | Освободить порт либо изменить левую часть 8000:8000 в docker-compose.yml и открыть новый порт |
| При вводе пароля ничего не видно | Продолжить ввод и нажать Enter: пароль скрыт |
| Команда сообщает, что email или профиль уже занят | Использовать ранее созданный аккаунт; для нового нужен свободный email и ещё не привязанный профиль |
| HR видит личный кабинет вместо списка сотрудников | Выйти и снова войти под HR-аккаунтом, чтобы обновить режим сессии |
| После частых попыток входа появился ответ 429 | Подождать минуту и повторить вход с верным паролем |
У рекомендации стоит fallback | Это рабочий подбор без внешнего LLM; ключ для проверки основного сценария не нужен |
Запуск без Docker
Нужны PHP 8.4+ с SQLite, Composer, Node.js 22.12+ и npm. В корне проекта выполните:
./setup.sh
php artisan users:create [email protected] --employee=E0001
php artisan users:create [email protected] --name="HR Administrator" --hr
php artisan serve
Команды создания аккаунтов запрашивают пароли так же, как в Docker. Откройте /login на адресе, который выведет php artisan serve, и пройдите тот же сценарий для жюри.
setup.sh устанавливает зависимости, создаёт конфигурацию, применяет миграции, импортирует данные и собирает интерфейс. Используйте его для первоначальной установки: повторный импорт обновляет оценки навыков из исходного набора. Для последующих запусков достаточно php artisan serve. После изменений интерфейса выполните npm run build.
При обновлении установки без Docker после добавления авторизации выполните php artisan migrate --force. Старые пользователи не получают HR-права и профиль автоматически. Один профиль можно привязать только к одному аккаунту; HR также можно создать с личным профилем через --employee=ID.
Для ручного импорта каталога или отдельных файлов:
php artisan data:import --path=/path/to/jury-data
php artisan data:import --path=/path/to/employees.json
php artisan data:import --path=/path/to/activity_history.csv
В Docker добавляйте перед php artisan префикс docker compose exec app.
Технические детали и API
Стек: Laravel 13 / PHP 8.4+, SQLite, Blade + Tailwind. Дата среза данных: 2026-10-01; подбор будущих активностей считается относительно неё.
- Именованные роуты:
employees.index,employees.show,employees.recommendations,employees.complete,hr.index,admin.upload,admin.upload.store,session.role. - POST complete принимает
event_id, возвращает ровно контракт из PLAN.md. Повторное завершение запрещено с 422, кроме EV_036. Прирост ограничен gain, max_level и 5; уже достигнутый уровень не снижается. Для Lead следующего грейда нет:grade: null, covered: 0, total: 0. - POST recommendations возвращает 200 с 1–3 рекомендациями и
source=llm|fallback; без доступного полезного шага —{"recommendations": []}. Последний ответ сохраняется в БД и заменяется при новом запросе; complete очищает устаревшие рекомендации. HrAnalyticsService::employeesWithoutNextStep()использует тот же движок, что и рекомендации, включая расписание, историю и положительный вклад в навыки. Внешний LLM для HR не вызывается.- GET списка, профиля и HR поддерживают
Accept: application/json. Список принимаетsearch,role,grade, сохраняет фильтры при пагинации. Ключи профиля:employee,gaps,grade_readiness,history,skills,events,recommendations; HR:skill_gaps,employees_without_next_step,participation. Вeventsпрофиля остаются события, которые можно отметить завершёнными; сохранённыеrecommendationsсодержат связанноеevent. - Поля multipart-загрузки:
employees,activity_history. Ответ JSON:{"imported": {"employees": 2, "activity_records": 3}}с ключами фактически загруженных файлов. - Все POST используют стандартную CSRF-защиту Laravel: cookie сессии +
X-CSRF-TOKENиз meta-тега страницы либо поле_token. POST/loginпринимаетemailиpasswordи ограничен по частоте; POST/logoutзакрывает сессию. Маршруты с данными требуют входа (перенаправление для HTML, 401 для JSON). POST/session/roleпринимаетrole=employee|hr, но переход в HR требует назначенной сервером роли, иначе возвращается 403. - JSON-поля skills/required_skills — карты
skill_id → level. Eloquent-связи:activityRecords,recommendations,manager,reports,employee,event. Для составного ключа роли используются методыEmployee::roleProfile()иnextGradeProfile(), возвращающие модель или null. - Клиентский сценарий использует
fetchс CSRF-токеном иAccept: application/json. Повторная отправка блокируется на время запроса; ошибки и пустой результат показаны на странице. После завершения обновляется серверный HTML профиля, поэтому шкалы и история используют тот же расчёт, что и API.
Проверка
php artisan test --compact
npm run build
Стартовые количества: 60 skills, 32 role_profiles, 200 employees, 40 events, 2743 activity_records. Тесты используют отдельную SQLite in-memory базу; проверяют повторный импорт, частичный merge, откат ошибочной загрузки, прогресс, повторные завершения, роли, HTTP-контракты и HR-агрегации.
AI-слой
Проверка на стартовом датасете без Docker и базы (нужны PHP 8.4+ и composer install):
php artisan ai:recommend E0028 --offline
Команда возвращает JSON по контракту PLAN.md. Другая папка с данными:
php artisan ai:recommend E0028 --dataset=path/to/dataset --offline.
Без --offline команда обращается к выбранному LLM-провайдеру.
В локальном .env задаются LLM_DRIVER=openai, OPENAI_API_KEY,
OPENAI_BASE_URL, OPENAI_MODEL=gpt-4o-mini, LLM_TIMEOUT=8.
Для Anthropic: LLM_DRIVER=anthropic и соответствующие ANTHROPIC_*.
LLM_DRIVER=disabled полностью отключает сеть. Ключи не должны попадать в Git.
Для OpenAI-compatible сервера без JSON Schema: OPENAI_STRUCTURED_OUTPUTS=false;
локальная проверка ответа сохраняется. Повторных запросов нет, таймаут ограничен
8 секундами даже при большем значении в .env.
Контракт сервисов
$result = app(\App\Services\LlmService::class)->recommend(
employee: $employeeData,
events: $eventRows,
roleProfiles: $roleProfileRows,
history: $activityRows,
skillCatalog: $skillRows,
asOf: '2026-10-01',
skillsAlreadyCurrent: false,
);
// $result === ['recommendations' => [...]]
Все аргументы — массивы, поля совпадают с JSON/CSV датасета; для моделей
используйте toArray() с приведёнными к массивам JSON-полями.
Сервисы ничего не записывают в БД. Контроллер сохраняет ответ и обеспечивает
доступ сотрудника только к своему профилю.
skillsAlreadyCurrent=false означает исходные навыки на last_review_date:
SkillProjector добавляет завершения после этой даты в хронологическом порядке,
не меняя исходный профиль. Завершения, уже включённые ProgressService в
сохранённые навыки, помечаются внутренним skills_applied=true и пропускаются
при начислении. Поле не входит в CSV. Повторный импорт оценки сотрудника
сбрасывает эти отметки, чтобы проекция строилась от новой оценки.
Для внешнего вызова с полностью актуальными навыками можно передать
skillsAlreadyCurrent=true. История всё равно используется для фильтров и скоринга.
При наличии completed_at используется эта дата; иначе — date из датасета.
Для HR можно вызвать RecommendationEngine::analyze() с теми же аргументами:
он вернёт актуальные навыки, разрывы, сводку истории и полный список кандидатов.
Пустой список означает отсутствие доступного полезного шага; искусственные
рекомендации для заполнения трёх карточек не создаются.
Правила выбора и объяснения
- Исключаются обязательные, неподходящие по роли/грейду, недоступные по
prerequisites, завершённые (кроме
EV_036) и уже начатые активности. - У событий по расписанию должна быть сессия не раньше даты среза;
self_pacedдоступен всегда. Исключаются события без полезного прироста к требованиям следующего грейда или карьерной цели. - Реальный прирост:
max(0, min(gain, max_level - current, 5 - current)). Для Lead используются требования Lead, без вымышленного следующего грейда. - Вес закрытия разрыва — 4 за уровень, критичного навыка — дополнительно 3,
карьерной цели — дополнительно 2. Штрафы за
no_show/declined/dropped: 4 за то же событие, 2 за другое с общими навыками, 0.5 только за общий тип. Одна запись получает только один штраф; обязательные события не штрафуют. - Завершённые добровольные события с общими навыками дают до 1 балла,
подтверждённые завершения в срок — до 0.5. Последнее требует
completed_atиdue_date: CSV не даёт оснований считать дату зачисления датой завершения. - Доступность даёт 1 балл для
self_paced, иначе1 / (1 + days / 30). При равенстве баллов порядок определяетсяevent_id. - LLM получает обезличенный профиль, разрывы, сводку истории и топ-8. Первый кандидат движка обязателен; LLM выбирает до двух дополнительных. Для каждого шага выбираются минимум три проверяемых фактора: грейд, разрыв и история; критичный навык также обязателен, если он есть.
- Обоснование собирается из точных русских фраз выбранных факторов.
Локальная проверка отклоняет выдуманные числа, неизвестные события,
дубликаты, пропущенные факторы, отказ модели и обрезанный JSON.
При любой ошибке провайдера возвращается топ-3 движка с
source=fallback.
OpenAI использует Structured Outputs, Anthropic — Messages API с инструментом. В журнал пишутся только категория сбоя и HTTP-статус, без ключей и ответов провайдера.
Проверка AI-слоя
php artisan test --compact tests/Unit/RecommendationEngineTest.php tests/Feature/LlmServiceTest.php tests/Feature/RecommendEmployeeCommandTest.php tests/Feature/RecommendationIntegrationTest.php
Тесты отключают реальную сеть. Покрыты антипример из ТЗ, граничные условия, оба провайдера, невалидные ответы, ошибки связи и все 200 профилей стартового кита. Реальный OpenAI-запрос отдельно проверен на искусственном примере без данных из стартового кита; Anthropic проверен через имитацию HTTP-ответов.
Авторы коммитов
История коммитов
- 2026-09-23 17:51Remove role switcher from application headerKzamirtay
- 2026-09-23 17:47Fix employee login redirect to unauthorized HR pagesKzamirtay
- 2026-09-23 17:34docs: keep only Career Quest in specificationKzamirtay
- 2026-09-23 17:31Merge pull request #9 from BAITC-Hacks/frontend/employee-profile-home-v2AZA
- 2026-09-23 17:30docs: format Career Quest specification as MarkdownKzamirtay
- 2026-09-23 17:26Merge main and preserve employee profile routingatokhtar-creator
- 2026-09-23 17:26Merge pull request #8 from BAITC-Hacks/fix-importKzamirtay
- 2026-09-23 17:26Merge pull request #10 from BAITC-Hacks/docs/jury-quickstartKzamirtay
Все коммиты (36)
- 2026-09-23 17:22Clarify jury setup, demo accounts, and fixed snapshot dateKzamirtay
- 2026-09-23 17:20Open employee profile by defaultatokhtar-creator
- 2026-09-23 17:18Validate imported career goals against role profilesDamirSyzdykov7
- 2026-09-23 17:16Merge pull request #7 from BAITC-Hacks/deranged-skunkKzamirtay
- 2026-09-23 17:14Require trusted accounts for employee and HR accessKzamirtay
- 2026-09-23 17:10Open employee profile by defaultatokhtar-creator
- 2026-09-23 16:59Merge pull request #5 from BAITC-Hacks/spotty-meerkatKzamirtay
- 2026-09-23 16:54Add HR activity catalog managementKzamirtay
- 2026-09-23 16:20Merge pull request #4 from BAITC-Hacks/cranky-hedgehogKzamirtay
- 2026-09-23 16:18Connect Career Quest frontend to backend and complete integration planKzamirtay
- 2026-09-23 15:57Build Career Quest frontend experienceatokhtar-creator
- 2026-09-23 15:45Merge pull request #2 from BAITC-Hacks/damirDamirSyzdykov7
- 2026-09-23 15:41Implement participant B AI recommendations and backend integrationDamirSyzdykov7
- 2026-09-23 15:19README: docker compose up reads keys from .envKzamirtay
- 2026-09-23 15:10Remove English and Kazakh dataset READMEsKzamirtay
- 2026-09-23 15:09Fix dockerignore: exclude bootstrap/cache (dev providers), verify container E2EKzamirtay
- 2026-09-23 15:09Remove .DS_Store from documentationKzamirtay
- 2026-09-23 15:06Add Docker deployment (multi-stage build, auto migrate+import)Kzamirtay
- 2026-09-23 14:56docs: restore track plan and original architectureKzamirtay
- 2026-09-23 14:55Merge track A backend while preserving main architecture and planKzamirtay
- 2026-09-23 14:51docs: restore original architecture versionKzamirtay
- 2026-09-23 14:45feat: implement track A data import, progress, HR and role-protected pagesKzamirtay
- 2026-09-23 14:45chore: install Laravel Boost and project agent guidelinesKzamirtay
- 2026-09-23 14:38docs: expand architecture and project planAZA
- 2026-09-23 14:32Scaffold Laravel 13 + SQLite + Tailwind, LLM config, setup.sh (M0)Kzamirtay
- 2026-09-23 14:31fix filesKzamirtay
- 2026-09-23 14:27Add architecture, work plan and agent rulesKzamirtay
- 2026-09-23 13:44Add docsKzamirtay
Структура репозитория (197 файлов)
.agents/mcp_config.json .agents/skills/deploying-to-cloud/SKILL.md .agents/skills/deploying-to-cloud/reference/checklists.md .agents/skills/infer-conventions/SKILL.md .agents/skills/infer-conventions/references/checklist.md .agents/skills/laravel-best-practices/SKILL.md .agents/skills/laravel-best-practices/rules/advanced-queries.md .agents/skills/laravel-best-practices/rules/architecture.md .agents/skills/laravel-best-practices/rules/blade-views.md .agents/skills/laravel-best-practices/rules/caching.md .agents/skills/laravel-best-practices/rules/collections.md .agents/skills/laravel-best-practices/rules/config.md .agents/skills/laravel-best-practices/rules/db-performance.md .agents/skills/laravel-best-practices/rules/eloquent.md .agents/skills/laravel-best-practices/rules/error-handling.md .agents/skills/laravel-best-practices/rules/events-notifications.md .agents/skills/laravel-best-practices/rules/http-client.md .agents/skills/laravel-best-practices/rules/mail.md .agents/skills/laravel-best-practices/rules/migrations.md .agents/skills/laravel-best-practices/rules/queue-jobs.md .agents/skills/laravel-best-practices/rules/routing.md .agents/skills/laravel-best-practices/rules/scheduling.md .agents/skills/laravel-best-practices/rules/security.md .agents/skills/laravel-best-practices/rules/style.md .agents/skills/laravel-best-practices/rules/validation.md .agents/skills/tailwindcss-development/SKILL.md .agents/skills/testing-best-practices/SKILL.md .agents/skills/testing-best-practices/rules/assertions.md .agents/skills/testing-best-practices/rules/endpoint-tests.md .agents/skills/testing-best-practices/rules/finding-features.md .agents/skills/testing-best-practices/rules/isolation.md .agents/skills/testing-best-practices/rules/naming.md .agents/skills/testing-best-practices/rules/performance.md .agents/skills/testing-best-practices/rules/review.md .agents/skills/testing-best-practices/rules/security.md .agents/skills/testing-best-practices/rules/test-data.md .claude/skills/deploying-to-cloud/SKILL.md .claude/skills/deploying-to-cloud/reference/checklists.md .claude/skills/infer-conventions/SKILL.md .claude/skills/infer-conventions/references/checklist.md .claude/skills/laravel-best-practices/SKILL.md .claude/skills/laravel-best-practices/rules/advanced-queries.md .claude/skills/laravel-best-practices/rules/architecture.md .claude/skills/laravel-best-practices/rules/blade-views.md .claude/skills/laravel-best-practices/rules/caching.md .claude/skills/laravel-best-practices/rules/collections.md .claude/skills/laravel-best-practices/rules/config.md .claude/skills/laravel-best-practices/rules/db-performance.md .claude/skills/laravel-best-practices/rules/eloquent.md .claude/skills/laravel-best-practices/rules/error-handling.md .claude/skills/laravel-best-practices/rules/events-notifications.md .claude/skills/laravel-best-practices/rules/http-client.md .claude/skills/laravel-best-practices/rules/mail.md .claude/skills/laravel-best-practices/rules/migrations.md .claude/skills/laravel-best-practices/rules/queue-jobs.md .claude/skills/laravel-best-practices/rules/routing.md .claude/skills/laravel-best-practices/rules/scheduling.md .claude/skills/laravel-best-practices/rules/security.md .claude/skills/laravel-best-practices/rules/style.md .claude/skills/laravel-best-practices/rules/validation.md .claude/skills/tailwindcss-development/SKILL.md .claude/skills/testing-best-practices/SKILL.md .claude/skills/testing-best-practices/rules/assertions.md .claude/skills/testing-best-practices/rules/endpoint-tests.md .claude/skills/testing-best-practices/rules/finding-features.md .claude/skills/testing-best-practices/rules/isolation.md .claude/skills/testing-best-practices/rules/naming.md .claude/skills/testing-best-practices/rules/performance.md .claude/skills/testing-best-practices/rules/review.md .claude/skills/testing-best-practices/rules/security.md .claude/skills/testing-best-practices/rules/test-data.md .dockerignore .editorconfig .env.example .gitattributes .gitignore .mcp.json .npmrc AGENTS.md ARCHITECTURE.md CLAUDE.md Dockerfile PLAN.md README.md app/Console/Commands/CreateUser.php app/Console/Commands/ImportDataset.php app/Console/Commands/RecommendEmployee.php app/Http/Controllers/AuthenticatedSessionController.php app/Http/Controllers/CompletionController.php app/Http/Controllers/Controller.php app/Http/Controllers/EmployeeController.php app/Http/Controllers/EventController.php app/Http/Controllers/HrController.php app/Http/Controllers/RecommendationController.php app/Http/Controllers/SessionRoleController.php app/Http/Controllers/UploadController.php app/Http/Middleware/EnsureEmployeeAccess.php app/Http/Middleware/EnsureHrRole.php app/Http/Requests/SaveEventRequest.php app/Models/ActivityRecord.php app/Models/Employee.php app/Models/Event.php app/Models/Recommendation.php app/Models/RoleProfile.php app/Models/Skill.php app/Models/User.php app/Providers/AppServiceProvider.php app/Services/DatasetImporter.php app/Services/HrAnalyticsService.php app/Services/LlmService.php app/Services/ProgressService.php app/Services/RecommendationEngine.php app/Services/SkillProjector.php artisan boost.json bootstrap/app.php bootstrap/cache/.gitignore bootstrap/providers.php composer.json composer.lock config/app.php config/auth.php config/cache.php config/database.php config/filesystems.php config/logging.php config/mail.php config/queue.php config/services.php config/session.php database/.gitignore database/factories/UserFactory.php database/migrations/0001_01_01_000000_create_users_table.php database/migrations/0001_01_01_000001_create_cache_table.php database/migrations/0001_01_01_000002_create_jobs_table.php database/migrations/2026_09_23_093708_create_career_quest_tables.php database/migrations/2026_09_23_102330_add_skills_applied_to_activity_records_table.php database/migrations/2026_09_23_120413_add_access_fields_to_users_table.php database/seeders/DatabaseSeeder.php docker-compose.yml docker/entrypoint.sh docs/HackAlem AI_ Career Quest - платформа геймификации жизненного цикла сотрудника.md docs/HackAlem AI_ Career Quest - платформа геймификации жизненного цикла сотрудника.txt docs/case_1/career_quest_dataset/README.ru.md docs/case_1/career_quest_dataset/activity_history.csv docs/case_1/career_quest_dataset/employees.json docs/case_1/career_quest_dataset/events.json docs/case_1/career_quest_dataset/skills.json opencode.json package-lock.json package.json phpunit.xml public/.htaccess public/favicon.ico public/index.php public/robots.txt resources/css/app.css resources/js/app.js resources/js/events.js resources/views/admin/upload.blade.php resources/views/auth/login.blade.php resources/views/employees/index.blade.php resources/views/employees/show.blade.php resources/views/events/_session-row.blade.php resources/views/events/_skill-row.blade.php resources/views/events/form.blade.php resources/views/events/index.blade.php resources/views/hr/index.blade.php resources/views/layout.blade.php resources/views/welcome.blade.php routes/console.php routes/web.php setup.sh storage/app/.gitignore storage/app/private/.gitignore storage/app/public/.gitignore storage/framework/.gitignore storage/framework/cache/.gitignore storage/framework/cache/data/.gitignore storage/framework/sessions/.gitignore storage/framework/testing/.gitignore storage/framework/views/.gitignore storage/logs/.gitignore tests/Feature/AuthenticationTest.php tests/Feature/CareerQuestTest.php tests/Feature/CreateUserCommandTest.php tests/Feature/EventManagementTest.php tests/Feature/ExampleTest.php tests/Feature/FrontendIntegrationTest.php tests/Feature/LlmServiceTest.php tests/Feature/RecommendEmployeeCommandTest.php tests/Feature/RecommendationIntegrationTest.php tests/Fixtures/career_quest.php tests/TestCase.php tests/Unit/ExampleTest.php tests/Unit/RecommendationEngineTest.php vite.config.js
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.