О проекте
Команда: NextQ
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Доведённый продукт
Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам
Суть
Городской симулятор: команда делает ровно пять решений из 14 мер и распределяет бюджет 100 между пятью направлениями и пятью районами Астаны, серверная модель считает Astana Quality of Life Score, AI объясняет компромиссы и генерирует новые варианты условий (зима, жара, рост).
Как устроено
Чистая доменная модель на TypeScript считает эффекты мер с лагом (8−лаг)/8 за восемь кварталов, фиксированные синергии, клиппинг 0–100 и Score = 0.7×взвешенное по населению среднее + 0.3×слабейший район − число показателей ниже 40. Route Handlers Next.js валидируют решения; AI-адаптер (NVIDIA NIM или OpenAI) генерирует только ограниченный blueprint кейса, который проверяется, восстанавливается по доверенному каталогу цен и подписывается HMAC, и пишет объяснение отчёта. Интерфейс на React с процедурной 3D-сценой Three.js, сохранением отчётов и сравнением.
Ключевые решения
- deterministic scoring model
- lag and synergy effects
- HMAC-signed case generation
- JSON validation
- rate limiting
Метрики
Контрольный план: Score 56.54307 (база 52.55768), расход 95, критических показателей 0; 99 unit/integration-тестов и 8 E2E
Особенности
AI не может менять score, цены и бюджеты: сгенерированный кейс подписывается HMAC и перепроверяется сервером. Есть Docker, Kubernetes-манифесты с kubeconform и smoke-проверка развёртывания.
Стек
TypeScript · Next.js · React · Three.js · pnpm · Docker · Kubernetes · Playwright · GitHub Actions
Модели
NVIDIA NIM · OpenAI
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-efc8a833-nextq.
README
README.mdQala Lab
«Аким на 5 часов» — AI-симулятор управления городом от Qala Lab. За пять решений команда распределяет общий виртуальный бюджет между транспортом, зелёными зонами, социальной инфраструктурой, безопасностью и городскими сервисами.
Каждая команда начинает с одинаковых синтетических данных и бюджета. Система проверяет стоимость выбранных мероприятий, рассчитывает изменение показателей и формирует Astana Quality of Life Score (AQoL) с AI-объяснением сильных сторон, рисков и компромиссов.
Главная страница — Qala Lab: пять районов Астаны, десять показателей, 14 мер, ровно пять решений и бюджет 100. AI создаёт новые условия и объясняет последствия; численный результат считает серверная модель. Для честного сравнения команды выбирают один кейс и версию правил. Горизонт фиксирован: восемь кварталов.
| Режим | Что проверяет |
|---|---|
/ — Qala Lab | Исходный датасет Астаны и варианты зимы, жары, роста; лаги, синергии, критические показатели и рекомендации |
/sandbox — базовый раунд | Пять решений при общем бюджете 100 и контрольных исходных данных |
/challenge — городское событие | Исходный план, воздействие события и ответное перераспределение |

Запуск
Требуется Node.js 22.x и pnpm 10.34.5. Версии зависимостей закреплены в package.json и lockfile.
corepack enable
pnpm install --frozen-lockfile
pnpm dev
Откройте http://localhost:3000.
Production-сборка:
pnpm build
pnpm start
Проверки модели, HTTP, AI-адаптеров и браузерного сценария:
pnpm test
pnpm lint
pnpm build
pnpm exec playwright install chromium
pnpm test:e2e
Браузерные тесты запускают production-сервер на порту 3210. Они используют подмену ответа AI и не расходуют ключи; реальный провайдер проверяется отдельно после настройки окружения.
Qala Lab: экономика и AI-кейсы
Основной кейс astana точно воспроизводит предоставленную таблицу: Есиль, Алматы, Сарыарка, Байконур и Нура. Дополнительные winter, heat, growth — учебные вариации. Во всех случаях одинаковы каталог мер и правила: 100 единиц, ровно 5 уникальных мер, максимум 2 одного направления. Районные меры требуют один район, городские действуют во всех пяти. Несовместимые сочетания отклоняются.
Реализованная доля каждого эффекта — (8 − лаг) / 8, включая отрицательные эффекты. Синергии фиксированы, лагом не масштабируются. После суммирования показатели ограничиваются диапазоном 0–100. Оценка района — взвешенная сумма десяти показателей. Score = 0.7 × среднее с весами населения + 0.3 × слабейший район − число показателей строго ниже 40.
| Контроль | Расход | Score | Критических показателей |
|---|---|---|---|
| Исходные данные | — | 52.55768 | 2 |
| M7, M8, M10 в Нуре; M12 по городу; M5 в Сарыарке | 95 | 56.54307 | 0 |
Исходный Score — справочная точка, а не допустимый пустой план. Отчёт показывает районные изменения, вклад мер с учётом лага, синергии, штраф и до трёх улучшений. Рекомендации пересчитываются с полной валидацией. До 12 сохранений доступны в этом браузере: после перезагрузки можно открыть полный отчёт. При восстановлении сохранённого отчёта та же чистая модель локально перепроверяет данные; новый расчёт и AI-разбор проходят через сервер. Сравнение требует одинакового кейса и версии. Доступны JSON-экспорт, печать и необязательная процедурная 3D-схема с HTML-альтернативой.
AI создаёт только ограниченный blueprint: тему, описание и исходные районные показатели. Сервер проверяет структуру, восстанавливает доверенный каталог цен и подписывает кейс HMAC. Подпись действует семь дней; изменение данных клиентом отклоняется. В production для генерации нужен постоянный CASE_SIGNING_SECRET длиной минимум 32 символа. Без AI-ключа все готовые кейсы и расчёты доступны.
Граница реализма: названия районов реальные, но входные индексы и коэффициенты — предоставленные условия учебной модели, не подтверждённая статистика и не прогноз Астаны. Доля населения затронутых районов не равна числу доказанных благополучателей. Методика, полный датасет и правила, контракт релиза.
Архитектура
flowchart LR
UI[React: кейсы и решения] --> HTTP[Route Handlers: валидация]
HTTP --> DOMAIN[Чистая модель: AQoL, сроки, бюджеты]
HTTP --> CASES[Доверенный каталог / подписанный blueprint]
HTTP --> AI[AI-адаптер NVIDIA / OpenAI]
AI --> VALIDATE[Проверка JSON и ограничений]
VALIDATE --> CASES
DOMAIN --> REPORT[Факты и рекомендации]
REPORT --> UI
REPORT --> AI
src/domain не зависит от React, HTTP и провайдеров. src/data задаёт версионированные правила, src/application связывает исходный сценарий с моделью. src/infrastructure содержит HTTP-схемы, подпись и AI-адаптеры; src/app/api — транспорт, src/components — интерфейс. Секреты не попадают в клиент, AI не может менять score, цены или бюджеты.
Docker и Kubernetes
Production-образ использует Next.js standalone, работает от непривилегированного пользователя и слушает порт 3000. Проверка готовности: GET /api/health. Ключ AI передаётся при запуске контейнера.
docker build -t akim-city:local .
docker run --rm --name akim -p 3000:3000 akim-city:local
В другом терминале выполните pnpm smoke:deploy: проверяются health, страница, статический файл и контрольный расчёт /api/challenge. Для AI добавьте --env-file .env.local перед именем образа.
Для локального Kubernetes с доступом к образу akim-city:local:
pnpm check:k8s
kubectl apply -k deploy/k8s
kubectl -n akim rollout status deployment/akim --timeout=180s
kubectl -n akim port-forward service/akim 3000:80
Проверка манифестов требует kubectl, Go 1.24+ и сеть для kubeconform и схем. Для удалённого кластера требуется загрузить образ в registry и указать его адрес. Контракт образа, Secret, настройка registry и остановка описаны в docs/runtime-contract.md. CI проверяет схемы Kubernetes и запускает тот же smoke в собранном Docker-образе.
API Qala Lab
| Endpoint | Назначение |
|---|---|
GET /api/cases | Готовые кейсы и доступность генерации |
POST /api/cases/evaluate | Проверка пяти решений и детерминированный отчёт |
POST /api/cases/analyze | Повторный серверный расчёт и AI-объяснение |
POST /api/cases/generate | Генерация условий, валидация, подписанный кейс |
Контрольный расчёт без ключа:
curl http://localhost:3000/api/cases/evaluate \
-H 'Content-Type: application/json' \
-d '{"caseId":"astana","decisions":[{"measureId":"M7","districtId":"nura"},{"measureId":"M8","districtId":"nura"},{"measureId":"M10","districtId":"nura"},{"measureId":"M12"},{"measureId":"M5","districtId":"saryarka"}]}'
Ожидаются evaluation.result.spent=95, finalAqol=56.54307 (с погрешностью машинной арифметики), criticalCount=0. Для сгенерированного кейса добавляется caseToken, возвращённый генерацией. Клиентские цены, эффекты, score и лишние поля не принимаются. Невалидный набор возвращает причину и не получает score.
Генерация принимает {"brief":"Описание условий нового кейса не короче 20 символов","theme":"winter"}. Возможные темы: baseline, winter, heat, growth, mobility. Полный датасет, веса и правила — в контракте astana-1. Дополнительные /sandbox, /challenge и их API описаны в учебных режимах; у них отдельная прежняя модель.
AI-анализ
Скопируйте .env.example в .env.local. Для NVIDIA задайте AI_PROVIDER=nvidia и NVIDIA_API_KEY, для OpenAI — AI_PROVIDER=openai и OPENAI_API_KEY. Настройки моделей — NVIDIA_MODEL / OPENAI_MODEL. Ключ читается только сервером. В production также задайте CASE_SIGNING_SECRET (например, результат openssl rand -hex 32); один секрет должен использоваться всеми репликами.
Без ключа, при таймауте или ошибке провайдера система показывает недоступность AI, сохраняя детерминированный AQoL. AI-вызовы ограничены по частоте и параллелизму внутри процесса; для публичного многорепличного сервиса нужны общая квота и контроль доступа на входе. Базовый /sandbox использует исходный NVIDIA-адаптер.
Статус
Проект реализуется спринтами. Спецификация находится в docs/design/, пошаговые планы — в docs/superpowers/plans/, параллельные дорожки команды — в docs/sprint-workstreams.md.
Релиз Qala Lab проверен 23 сентября 2026: 99 unit/integration-тестов, 8 Chromium E2E, lint, production build, Docker и локальный Kubernetes. Реальные генерация и анализ OpenAI прошли через браузер; NVIDIA проверен mock-тестами. Протокол проверки, демо на три минуты, структура презентации.
GitHub Actions пока не запускается из-за блокировки аккаунта организации по биллингу. После восстановления доступа нужно повторить CI; приведённые результаты получены локально.
Иконки — Lucide (ISC), процедурная сцена — Three.js (MIT). Внешние 3D-модели и изображения не загружаются; скриншот получен из работающего приложения.
Авторы коммитов
История коммитов
- 2026-09-23 16:46chore: name the project Qala LabCMPNION
- 2026-09-23 16:35Merge pull request #3: release Astana City LabNorkin Dmitriy
- 2026-09-23 16:34docs: record GitHub Actions billing limitationCMPNION
- 2026-09-23 16:32test: verify release flows in Chromium Docker and KubernetesCMPNION
- 2026-09-23 16:32docs: publish Astana methodology demo and release evidenceCMPNION
- 2026-09-23 16:28feat: ship city lab workspace with restorable reports and comparisonCMPNION
- 2026-09-23 16:25feat: render accessible procedural district sceneCMPNION
- 2026-09-23 16:24feat: implement exact Astana scoring and validated case variantsCMPNION
Все коммиты (36)
- 2026-09-23 16:24feat: generate signed city cases with OpenAI and NVIDIACMPNION
- 2026-09-23 16:15build: pin dependencies and prepare release verificationCMPNION
- 2026-09-23 16:15feat: define supplied Astana dataset and exact scoring contractCMPNION
- 2026-09-23 15:58docs: define city lab release contracts and simulation scopeCMPNION
- 2026-09-23 15:51merge: add interactive event challengeCMPNION
- 2026-09-23 15:47merge: add Docker and Kubernetes runtimeCMPNION
- 2026-09-23 15:41docs: document city challenge flow and control scenarioCMPNION
- 2026-09-23 15:41feat: add interactive city event challenge workflowCMPNION
- 2026-09-23 15:40feat: add standalone Docker and Kubernetes runtimeCMPNION
- 2026-09-23 15:40ci: verify deployment manifests and container smokeCMPNION
- 2026-09-23 15:26merge: integrate Ayim quality gates from mainCMPNION
- 2026-09-23 15:26docs: assign sprint three release workstreamsCMPNION
- 2026-09-23 15:25Merge pull request #2 from BAITC-Hacks/feat/ayim-quality-gatesaiympangerey1703
- 2026-09-23 15:25merge: integrate sprint two city event simulationCMPNION
- 2026-09-23 15:25feat: add deterministic city event challengesCMPNION
- 2026-09-23 15:23merge: integrate Sabina district visualizationCMPNION
- 2026-09-23 15:23merge: integrate Ayim quality gatesCMPNION
- 2026-09-23 15:22Merge pull request #1 from BAITC-Hacks/feat/sabina-district-visualssabinazzz
- 2026-09-23 15:17feat: visualize district score changes and document hackathon demoSabina Zhumagaliyeva
- 2026-09-23 15:16test: add catalog quality gates and verification CIa1ymsss
- 2026-09-23 15:03feat: complete five-decision simulation flowCMPNION
- 2026-09-23 15:01docs: add three-way sprint workstreamsCMPNION
- 2026-09-23 14:59feat: explain scenarios with NVIDIA NIMCMPNION
- 2026-09-23 14:48feat: add validated scenario endpointCMPNION
- 2026-09-23 14:42feat: add deterministic city scenario engineCMPNION
- 2026-09-23 14:34feat: scaffold city simulation appCMPNION
- 2026-09-23 14:18docs: plan sprint one implementationCMPNION
- 2026-09-23 14:05docs: specify Akim city simulationCMPNION
Структура репозитория (103 файлов)
.dockerignore .env.example .github/workflows/verify.yml .gitignore .nvmrc AGENTS.md CLAUDE.md Dockerfile README.md deploy/k8s/configmap.yaml deploy/k8s/deployment.yaml deploy/k8s/kustomization.yaml deploy/k8s/namespace.yaml deploy/k8s/service.yaml docs/assets/city-lab.png docs/demo-script.md docs/design/akim-na-5-chasov.md docs/design/astana-dataset.md docs/design/release-city-lab.md docs/legacy-demo-script.md docs/legacy-simulator.md docs/model-assumptions.md docs/presentation.md docs/release-verification.md docs/runtime-contract.md docs/sprint-workstreams.md docs/superpowers/plans/2026-09-23-akim-sprint-1.md docs/superpowers/plans/2026-09-23-akim-sprint-2.md docs/testing.md e2e/city-lab.spec.ts eslint.config.mjs next-env.d.ts next.config.ts package.json playwright.config.ts pnpm-lock.yaml postcss.config.mjs scripts/deploy-smoke.mjs scripts/test.mjs scripts/validate-k8s.sh src/app/api/cases/analyze/route.ts src/app/api/cases/evaluate/route.ts src/app/api/cases/generate/route.ts src/app/api/cases/route.ts src/app/api/challenge/route.test.ts src/app/api/challenge/route.ts src/app/api/health/route.ts src/app/api/scenario/route.test.ts src/app/api/scenario/route.ts src/app/challenge/page.tsx src/app/globals.css src/app/layout.tsx src/app/page.tsx src/app/sandbox/page.tsx src/application/run-event-challenge.ts src/application/run-scenario.ts src/application/scenario-narrator.ts src/components/city-lab/case-report.tsx src/components/city-lab/case-workspace.tsx src/components/city-lab/city-lab.module.css src/components/city-lab/city-lab.tsx src/components/city-lab/city-scene.tsx src/components/city-lab/lab-state.test.ts src/components/city-lab/lab-state.ts src/components/city-lab/scene/city-scene.module.css src/components/simulation/budget-meter.tsx src/components/simulation/challenge-builder.tsx src/components/simulation/challenge-report.tsx src/components/simulation/challenge-state.test.ts src/components/simulation/challenge-state.ts src/components/simulation/challenge.module.css src/components/simulation/district-score-bars.module.css src/components/simulation/district-score-bars.tsx src/components/simulation/initiative-picker.tsx src/components/simulation/presentation.ts src/components/simulation/scenario-builder.tsx src/components/simulation/scenario-report.tsx src/data/astana-catalog.ts src/data/city-cases.ts src/data/city-v1.test.ts src/data/city-v1.ts src/data/events-v1.ts src/domain/astana-metrics.ts src/domain/city-case.ts src/domain/evaluate-city-case.test.ts src/domain/evaluate-city-case.ts src/domain/evaluate-scenario.test.ts src/domain/evaluate-scenario.ts src/domain/events.ts src/domain/model.ts src/domain/run-event-challenge.test.ts src/infrastructure/cases/cases.test.ts src/infrastructure/cases/handlers.ts src/infrastructure/cases/http.ts src/infrastructure/cases/limiter.ts src/infrastructure/cases/provider.ts src/infrastructure/cases/schemas.ts src/infrastructure/cases/tokens.ts src/infrastructure/http/challenge-schema.ts src/infrastructure/http/scenario-schema.ts src/infrastructure/nvidia-scenario-narrator.test.ts src/infrastructure/nvidia-scenario-narrator.ts tsconfig.json
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.