AAYMA
RU
Войти

Аким на 5 часов

Городской симулятор: игрок выбирает 5 из 14 мер в бюджете 100 у.е., детерминированный движок считает Astana Quality of Life Score по районам, а…

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

О проекте

Команда: Hahatun
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Доведённый продукт

Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам

Суть

Городской симулятор: игрок выбирает 5 из 14 мер в бюджете 100 у.е., детерминированный движок считает Astana Quality of Life Score по районам, а консилиум AI-агентов объясняет результат и выносит резолюцию. Есть лидерборд, городские шоки, песочница с собственным датасетом и озвучка резолюции.

Как устроено

Валидатор проверяет 8 правил кейса, движок считает Score с лагами, синергиями, весами и штрафами, затем генерируются пронумерованные факты F1…Fn. Оптимизатор полным перебором всех 694 395 валидных наборов находит глобальный оптимум, перцентиль и улучшения заменой одной меры. Консилиум: 6 LLM-экспертов параллельно → синтезатор → ревизоры C1–C6 (C1–C2 кодом сверяют числа) до 2 кругов → арбитр; прогресс идёт по SSE. Числа LLM не считает, это проверяется кодом.

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

  • мультиагентный консилиум
  • полный перебор 694k наборов
  • grounding через ID фактов
  • проверка чисел кодом
  • structured outputs (zod strict)
  • SSE-стриминг
  • OpenAI TTS

Метрики

базовый Score 52.56, пример организаторов 56.54 воспроизведён золотым тестом; глобальный оптимум 57.24; перебор 694 395 наборов за ~0.4 с

Особенности

Принцип «код считает, LLM говорит»: всё количественное детерминировано, LLM ссылается на ID фактов, а ревизоры кодом сверяют числа в тексте. Полный перебор пространства решений даёт честный разрыв с оптимумом. Таймлайн 8 кварталов с лагами мер, неожиданные события с пересчётом, песочница со своим датасетом, 3D-Байтерек на лендинге.

Стек

TypeScript · Next.js · React · Tailwind CSS · shadcn/ui · Recharts · three.js · Vercel AI SDK · Zod · Vitest · Playwright · Docker

Модели

gpt-5-mini · gpt-5 · gpt-5.4-mini · gpt-5.5 · gpt-4o-mini-tts


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

README

README.md

Аким на 5 часов

AI-симулятор управления городом для кейса HackAlem AI: бюджет, пять решений по районам Астаны, Astana Quality of Life Score и консилиум AI-агентов, который объясняет результат и выносит резолюцию.

Как играть за минуту. Вы аким. У вас 100 условных единиц и 14 мер по пяти направлениям. Выбираете ровно пять, движок сразу показывает Score, консилиум объясняет и выносит резолюцию.

Словарь. Score — Astana Quality of Life Score по формуле кейса, 0–100. Консилиум — цепочка AI-агентов: шесть экспертов по направлениям, синтезатор заключения, ревизоры и арбитр. Ревизоры — шесть проверок заключения (C1–C6), первые две делает код: числа в тексте совпадают с расчётом, рекомендация валидна. Арбитр — итоговая резолюция: утвердить, утвердить с условиями, вернуть. Фолбэк — режим без ключа OpenAI, тексты из заготовки, числа те же.

1. Краткое описание

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

Для кого. Городской управленец, аналитик или пользователь симулятора (формулировка кейса), а также студенты и участники деловых игр, которым нужно быстро прогнать сценарий, увидеть его цену и услышать аргументы «за» и «против».

Принцип. Код считает, LLM говорит. Валидация, Score, дельты по районам, поиск улучшений и исход резолюции считаются детерминированно. Языковая модель получает пронумерованные факты и объясняет их, спорит и пишет резолюцию. Ни одно число не приходит из модели, и это проверяется кодом. Так требует сам кейс, раздел «Роль ИИ» датасета: «LLM получает результат расчёта (дельты по районам и показателям, вклад каждой меры) и объясняет его, сравнивает наборы, советует. Числа он не считает и не придумывает».

Соответствие кейсу

Must have из задания:

Требование кейсаКак закрыто
Единый виртуальный бюджет для всех пользователей100 у.е. и одинаковые исходные данные для всех команд, константы в src/lib/types.ts и src/lib/data/
Решения по 5 направлениям: транспорт, озеленение, социальная инфраструктура, безопасность, городской сервискаталог из 14 мер датасета, сгруппированный по пяти направлениям; ровно 5 решений, не больше 2 на направление
Автоматический контроль превышения бюджетавалидатор блокирует отправку набора дороже 100 у.е., полоса бюджета краснеет и показывает перерасход
AI-анализ принятых решенийконсилиум: 6 экспертов, синтезатор, ревизоры, арбитр (OpenAI API)
Расчёт итогового Astana Quality of Life Scoreдетерминированный движок по формуле датасета, живой пересчёт в кабинете
Объяснение сильных сторон, рисков и возможных последствийчерновик заключения с разделами «сильные стороны / риски / последствия» и резолюция арбитра

Опционально:

Опция кейсаСтатус
Сравнение результатов нескольких командесть: лидерборд /leaderboard по сохранённым прогонам
Визуализация изменений показателей районовесть: схема районов Астаны с цветом по оценке района, радар «до / после», таблица показателей со стрелками
AI-рекомендации по улучшению сценарияесть: улучшения считает оптимизатор, арбитр оформляет их в поручения, блок «Что сделать дальше» с кнопкой «Применить»
Неожиданные городские событияесть: после вердикта событие бьёт по показателю района, Score пересчитывается тем же набором, предлагается лучшая замена и кнопка «Перераспределить бюджет»
Генерация краткой презентации решенияесть: «Скачать краткую презентацию (.md)» на странице вердикта

Критерии проверки из кейса и где их увидеть:

  1. Одинаковый бюджет и исходные данные: брифинг / показывает базу 52.56 и бюджет 100 для любой команды.
  2. Бюджет нельзя превысить: в /play набор дороже 100 у.е. не отправляется, причина названа (п. 7 ниже).
  3. Решения влияют на показатели: вердикт показывает изменения каждого показателя по районам и вклад каждой меры.
  4. Понятное объяснение и компромиссы: зал заседаний (эксперты, споры, резолюция с обоснованием).
  5. Другой набор даёт другой Score: замена одной меры в кабинете сразу меняет Score (п. 7 ниже).

2. Что реализовано

  • Единый бюджет 100 и синтетический датасет организаторов: 5 районов, 10 показателей, 14 мер с ценой, лагом и эффектами, 3 синергии, 3 несовместимости.
  • Валидатор восьми правил кейса, возвращает все нарушения списком: ровно 5 решений, бюджет, повторы, район для локальных мер, не более 2 мер на направление, конфликты.
  • Движок Score по формуле датасета: лаг, синергии, обрезка 0..100, веса, штраф за критические значения. Золотой тест воспроизводит базу 52.56 и пример организаторов 56.54.
  • Факты с ID (F1…Fn): каждое изменение показателя, вклад каждой меры, слабейший район, критические значения, остаток бюджета.
  • Оптимизатор: полный перебор всех 694 395 валидных наборов за ~0.4 с с кэшем на диске. Даёт глобальный оптимум (57.24), перцентиль набора среди всех валидных и до трёх улучшений заменой одной меры.
  • Консилиум из восьми стадий: 6 экспертов (транспорт, экология, соцсфера, безопасность, сервисы, финансы) параллельно → синтезатор → ревизоры (6 условий, порог 5 из 6, до 2 кругов пересмотра) → арбитр с резолюцией «утвердить / утвердить с условиями / вернуть».
  • Стриминг прогресса по SSE, сохранение прогона в JSON, страница результата открывается по ссылке.
  • Режим без ключа OpenAI: движок и оптимизатор работают, консилиум отвечает детерминированным фолбэком с пометкой.
  • Внезапное городское событие после вердикта: шок по показателю района (авария теплосетей, смог, паводок и др.), пересчёт Score и предложение перераспределить одну меру.
  • Экспорт краткой презентации решения команды в markdown одной кнопкой.
  • Таймлайн 8 кварталов на вердикте: ползунок показывает, как растут показатели и Score по мере срабатывания лагов (линия ЛРТ с лагом 4 ничего не даёт до пятого квартала). Считается той же моделью, на 8-м квартале совпадает с итогом.
  • Разрыв с оптимумом: под Score видно лучший возможный набор, на сколько он выше и какими заменами отличается, кнопка «Открыть оптимум».
  • Песочница: импорт своего датасета в формате кейса на странице /sandbox. Шаблон public/dataset-hackalem.json это данные кейса; можно поменять показатели и доли районов, цены, лаги и эффекты мер, веса, синергии и конфликты. Файл проверяется схемой (значения 0–100, сумма весов и долей населения 1, все 5 районов и 14 мер). Весь конвейер, включая полный перебор и консилиум, работает на загруженных данных. Прогоны песочницы помечены и не попадают в лидерборд, поэтому соревнование остаётся на одинаковых данных для всех команд.
  • Озвучка резолюции: кнопка «Озвучить резолюцию» читает постановление арбитра голосом (OpenAI TTS, gpt-4o-mini-tts), аудио кэшируется на прогон.
  • Интерфейс: брифинг со схемой районов, кабинет решений с живым Score, экран заседания со стадиями по мере готовности, вердикт с залом заседаний, лидерборд команд.

3. Как работает решение

  1. Брифинг (/): 3D-модель Байтерека, схема районов Астаны с цветом по оценке района, пять карточек районов, базовый Score 52.56, два критических провала Нуры (школы 38, поликлиники 35). Команда вводит название.
  2. Кабинет решений (/play): каталог мер по пяти направлениям, выбор района, бюджетная полоса, лимиты по направлениям, живой Score прямо в браузере тем же движком. Невалидный набор блокирует отправку и называет причины.
  3. Заседание (/result/live): восемь стадий пайплайна отмечаются построчно по мере событий SSE, карточки экспертов, ревизия и резолюция появляются по ходу. По событию done открывается вердикт.
  4. Вердикт (/result/[runId]): Score и дельта, перцентиль, схема районов и радар района до и после, таблица показателей, блок «Как считалось» с формулой, консилиум: эксперты, «Ревизия: N из 6 условий», «Черновики заключения» (отклонённые фразы подсвечены), резолюция и «Споры и поручения арбитра». Блок «Что сделать дальше» с кнопкой «Применить» подставляет улучшение в кабинет для нового прогона. Ниже карточка внезапного события и ссылка на презентацию.
  5. Лидерборд (/leaderboard): все сохранённые прогоны на данных кейса, выше тот, чей набор дал больший Score.
  6. Песочница (/sandbox): скачать шаблон, изменить данные, загрузить файл, посмотреть превью районов и базового Score, играть на своих данных. Плашка «Песочница» видна в кабинете и на вердикте.
БрифингКабинет решенийВердикт
БрифингКабинетВердикт

Полная страница вердикта с залом заседаний: docs/screenshots/verdict-full.png.

Сценарий → Валидатор → Движок + Факты → Оптимизатор
        → 6 экспертов (LLM, параллельно) → Синтезатор (LLM)
        → Ревизоры: C1, C2 код · C3–C6 LLM ──┐ провал, круг ≤ 2
                 ↑___________________________│
        → Таблица исходов (код) → Арбитр (LLM) → Запись прогона → SSE done

4. Технологии

  • Next.js 16.3 (App Router, route handlers, SSE), React 19.2, TypeScript 5
  • Tailwind 4 + shadcn/ui, Recharts 3, lucide-react, three.js (3D-Байтерек на главной, грузится лениво только на /)
  • Vercel AI SDK 7 + @ai-sdk/openai 4, structured outputs через zod 4 (strict JSON schema)
  • OpenAI API через OPENAI_EXPERT_MODEL и OPENAI_JUDGE_MODEL: по умолчанию gpt-5-mini и gpt-5; прогоны и числа в этом README сделаны на gpt-5.4-mini (эксперты) и gpt-5.5 (синтезатор, ревизоры, арбитр)
  • Vitest 5, Docker (standalone-сборка Next)

5. Архитектура

src/lib/data/        датасет как константы (районы, меры, веса, синергии, конфликты)
src/lib/engine/      validator, engine (Score), facts (факты с ID), optimizer — чистые функции
src/lib/consilium/   llm (единая точка вызовов), experts, synthesizer, reviewers, arbiter, pipeline
src/lib/store/       прогоны в JSON: data/runs/<id>.json
src/app/api/run      POST → поток событий ConsiliumEvent (SSE)
src/app/api/runs     GET список, GET по id, GET /event (событие), GET /pitch (презентация .md), GET /voice (озвучка .mp3)
src/app/             брифинг, кабинет, заседание, вердикт, лидерборд
src/components/      экраны UI: briefing, play, live, result, consilium, map, leaderboard, landing (3D-Байтерек), shell, ui
src/lib/ui/          форматтеры, разбор SSE, сборка прогона из событий
src/lib/types.ts     контракт между UI и бэком
fixtures/            полный образец прогона для разработки UI
ЧтоКто делаетПочему
Валидация, Score, дельты, вклад меркодвоспроизводимость, критерии 2, 3, 5 кейса
Поиск улучшений, глобальный оптимум, перцентилькод, полный перебор694 395 наборов за 0.4 с, детерминированно и воспроизводимо
Мнения экспертов, черновик, споры, резолюцияLLMнужен язык, а не арифметика
Проверка чисел в тексте (C1), валидность рекомендации (C2)кодLLM не проверяет сам себя там, где может код
Полнота и честность текста (C3–C6)LLM-ревизорусловия, а не «оценка уверенности»
Исход резолюциикод, таблица условийодин ответ на вопрос «почему утвердили»

6. Установка и запуск

git clone https://github.com/BAITC-Hacks/hack-4fbaf6fd-hahatun.git
cd hack-4fbaf6fd-hahatun
yarn install
cp .env.example .env        # вписать OPENAI_API_KEY, без него работает фолбэк
yarn dev                    # http://localhost:3000

Docker:

cp .env.example .env
docker compose up --build   # http://localhost:3000, прогоны в volume runs

Проверки: yarn test (движок, валидатор, ревизоры, пайплайн), yarn typecheck, yarn lint. Приёмка в браузере: npx playwright install chromium один раз, затем yarn test:e2e при запущенном yarn dev (брифинг → кабинет → консилиум → вердикт → лидерборд → презентация → событие, 5 тестов, около минуты с ключом).

7. Как проверить решение

Через интерфейс

  1. Открыть /play, собрать пример организаторов: M7 Нура, M8 Нура, M10 Нура, M12, M5 Сарыарка. Стоимость 95, живой Score показывает 56.54 (в документе кейса ≈ 56.5). Тот же набор открывается ссылкой /play?s=M7.nura,M8.nura,M10.nura,M12,M5.saryarka.
  2. Заменить M5 на M3 (ЛРТ) в Нуре: Score меняется на 57.21. Убрать одну меру: кнопка «На консилиум» блокируется, панель набора показывает «4 из 5» и причину «Нужно ровно 5 решений, сейчас 4». Выбрать вместе M1 и M3: причина «„Выделенные полосы для автобусов“ и „Линия ЛРТ / расширение“ несовместимы» (в кабинете меры названы по имени, коды остаются в API и презентации).
  3. Превысить бюджет: в примере заменить M12 на M3 в Нуре (/play?s=M7.nura,M8.nura,M10.nura,M3.nura,M5.saryarka). Стоимость 111, полоса бюджета красная с подписью «перерасход на 11 у.е.», причина «Бюджет 100 превышен: стоимость набора 111», отправка заблокирована.
  4. Нажать «На консилиум». На экране заседания стадии отмечаются по мере готовности, затем на вердикте появляются шесть экспертов, черновик, ревизия и резолюция. С ключом прогон занимает 30–60 секунд и стоит около 4 центов; без ключа около секунды, тексты помечены как фолбэк.

Через API

Сервер на 3000:

curl -N -X POST http://localhost:3000/api/run -H 'Content-Type: application/json' \
  -d '{"teamName":"Демо","scenario":{"decisions":[{"measureId":"M7","districtId":"nura"},{"measureId":"M8","districtId":"nura"},{"measureId":"M10","districtId":"nura"},{"measureId":"M12"},{"measureId":"M5","districtId":"saryarka"}]}}'

Ожидаемый поток: stage validate/engine/optimize, событие engine со score: 56.54 и 32 фактами, optimizer с улучшением «M5 Сарыарка → M3 Линия ЛРТ, Нура, 57.21», шесть событий expert, draft, review (с ключом обычно 6 из 6), resolution с исходом approve и поручением, done с runId. Затем GET /api/runs/<runId> возвращает сохранённый прогон, GET /api/runs/<runId>/event — внезапное событие с пересчётом, GET /api/runs/<runId>/pitch — презентацию в markdown. Реальный прогон с LLM сохранён как образец в fixtures/live-run.json.

Три сида с ожидаемыми результатами

Движок детерминирован, числа совпадут; тексты LLM и ревизия могут отличаться от прогона к прогону.

НаборСтоимостьScoreКрит. значенийИсход арбитра
M7 Нура, M8 Нура, M10 Нура, M12, M5 Сарыарка (пример кейса)9556.540утвердить
M2, M3 Нура, M8 Нура, M9 Нура, M14 (глобальный оптимум)9857.240утвердить, перцентиль 100%
M9 Нура, M11 Есиль, M10 Нура, M12, M4 Сарыарка (самый дешёвый)6155.171 (Нура S2)утвердить с условиями, поручение заменить меру на M8 Нура

Тесты: yarn test — 141 тест, среди них золотой тест формулы (база 52.56, пример 56.54, синергия M10+M12), валидатор по каждому правилу, проверка чисел ревизора C1, цикл пересмотра с cap 2, хранилище с защитой от path traversal.

8. Данные и интеграции

  • Синтетический датасет организаторов (docs/source/dataset.md), перенесён в код без изменений. Персональных данных нет.
  • OpenAI API через Vercel AI SDK. Ключ только в .env, в репозитории его нет.
  • Внешних БД и сервисов нет, прогоны хранятся файлами.
  • Защита командного ключа от расхода: не более 3 одновременных прогонов и пауза 5 секунд между запусками с одного адреса (429), тело запроса ограничено, порт в Docker слушает только localhost. Секреты только в .env, yarn audit без уязвимостей.

9. Ограничения

  • Кэш перебора data/optimum.json (5.5 МБ) создаётся при первом прогоне, это добавляет около секунды к первому запросу.
  • Ревизия ограничена двумя кругами, после них результат отдаётся с бейджем «проверено N из 6».
  • Один город, один датасет, без авторизации и мультиплеера. Лидерборд показывает прогоны, сохранённые на этом сервере.
  • Мобильная вёрстка не приоритет, целевой экран от 1024px.

10. Потенциал развития

  • Реальные данные районов и открытые источники акимата вместо синтетики.
  • Замена LLM-ревизоров быстрым классификатором (например, Laya на ModernBERT) после накопления размеченных вердиктов.
  • Импорт реальных данных акимата через песочницу с расширением схемы: новые меры и районы, а не только изменение значений.
  • Каталог событий шире шести штук и события в середине горизонта, а не после вердикта; экспорт презентации в PDF/PPTX.
  • Вход по ЭЦП через NCA Node для внедрения в акимате.

11. Развёрнутая версия

Пока нет, запуск локально или через Docker.

Команда

  • Амир Бауржанов — движок Score и полный перебор, консилиум (эксперты, синтезатор, ревизоры, арбитр), SSE API и хранилище, события и экспорт презентации, README, ревью и приёмка.
  • Мирас Есеналы — дизайн-система и оформление в стиле бланка акимата (DESIGN.md), 3D-Байтерек на three.js, брифинг со схемой районов, кабинет решений с живым Score, экран заседания и вердикт с консилиумом, лидерборд, клиент SSE и тесты UI-логики.
Звёзды
⭐ 0
Форки
0
Язык
TypeScript
Последний push
в прошлом месяце
Коммиты
86
Авторы
2
Файлы
223
Ветки
4

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

a.baurzhanov1 58miras 28

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

  • 2026-09-23 17:02merge: dataset-aware measure names and tie-aware leaderboard ranks (539aa24) into mainmiras
  • 2026-09-23 16:56fix(ui): measure names follow the run's dataset; tie-aware leaderboard ranksmiras
  • 2026-09-23 16:48docs: README markdown lint fixes (headings, fence languages), test counta.baurzhanov1
  • 2026-09-23 16:45fix(api): validate the dataset before rate limits tooa.baurzhanov1
  • 2026-09-23 16:44merge: validate body before rate limits (5ac4f1b) into maina.baurzhanov1
  • 2026-09-23 16:43merge: dataset import sandbox into maina.baurzhanov1
  • 2026-09-23 16:43fix: sandbox dataset hardening — fixed scope/direction, safe titles, small cache, leaderboard fallbacka.baurzhanov1
  • 2026-09-23 16:39fix(api): validate the run body before rate limitsmiras
Все коммиты (86)
  • 2026-09-23 16:38docs: README sandbox import sectiona.baurzhanov1
  • 2026-09-23 16:37feat: dataset import sandbox — core threading, UI, leaderboard filter, e2ea.baurzhanov1
  • 2026-09-23 16:37merge: main into feat/importa.baurzhanov1
  • 2026-09-23 16:33merge: UI polish for timeline and voice (a06571e) into maina.baurzhanov1
  • 2026-09-23 16:29feat: sandbox dataset contract, schema and case dataset template (import)a.baurzhanov1
  • 2026-09-23 16:28fix(ui): polish the wow wave to DESIGN.mdmiras
  • 2026-09-23 16:21docs: backlog statuses after wow wavea.baurzhanov1
  • 2026-09-23 16:20merge: wow wave (timeline, optimum gap, voice) into maina.baurzhanov1
  • 2026-09-23 16:20fix: voice text hard-cut fallback, hide provider error detailsa.baurzhanov1
  • 2026-09-23 16:19docs: README and env for timeline, optimum gap, voicea.baurzhanov1
  • 2026-09-23 16:18feat: quarter timeline slider on the verdict (W2)a.baurzhanov1
  • 2026-09-23 16:18merge: main (round 5) into feat/wowa.baurzhanov1
  • 2026-09-23 16:16docs: overspend label wordinga.baurzhanov1
  • 2026-09-23 16:16merge: UI review fixes (round 5) into maina.baurzhanov1
  • 2026-09-23 16:13feat: voice of the resolution via OpenAI TTS with per-run cache (W3)a.baurzhanov1
  • 2026-09-23 16:12feat(ui): plain header, review fixes from Амирmiras
  • 2026-09-23 16:12feat: per-quarter timeline helper for the verdict (W1)a.baurzhanov1
  • 2026-09-23 16:10docs: wow wave plan (timeline, voice, optimum gap) in feat/wowa.baurzhanov1
  • 2026-09-23 16:07docs: screenshots refreshed for the round-4 UIa.baurzhanov1
  • 2026-09-23 16:06docs: README aligned with round-4 UI wording, dedupe intro, trim team sectiona.baurzhanov1
  • 2026-09-23 16:01docs: README jury audit fixes - test count, optimum cost, model defaults, glossarya.baurzhanov1
  • 2026-09-23 16:00merge: UI round 4 + WebGL fallback into maina.baurzhanov1
  • 2026-09-23 15:59fix(ui): survive WebGL renderer failure on the landing, show decisions countera.baurzhanov1
  • 2026-09-23 15:55merge: UI round 4 (Baiterek v2, lighter verdict, human measure names) into maina.baurzhanov1
  • 2026-09-23 15:52feat(ui): no measure codes for players - short names instead of M1..M14miras
  • 2026-09-23 15:49refactor(ui): lighter cabinet and verdict - one job, one next stepmiras
  • 2026-09-23 15:36Merge remote-tracking branch 'origin/main' into feat/uimiras
  • 2026-09-23 15:33merge: UI round 3 + security and review fixes into maina.baurzhanov1
  • 2026-09-23 15:32fix: run throttling and body cap, localhost port, partial LLM status in UI and pitch, e2e for event/pitch/usagea.baurzhanov1
  • 2026-09-23 15:28docs(readme): Baiterek v2 descriptionmiras
  • 2026-09-23 15:28feat(ui): Baiterek v2 - detailed model and "Подъём на Байтерек" intromiras
  • 2026-09-23 15:27merge: UI round 3 (event card, pitch button, usage panel) into maina.baurzhanov1
  • 2026-09-23 15:22test: Playwright acceptance for the full jury patha.baurzhanov1
  • 2026-09-23 15:21fix(ui): flag runs where the LLM did not answer; README options are implementedmiras
  • 2026-09-23 15:18feat(ui): real city event and pitch export on the verdictmiras
  • 2026-09-23 15:16Merge remote-tracking branch 'origin/main' into feat/uimiras
  • 2026-09-23 15:16fix: keep public/ so the Docker build can copy ita.baurzhanov1
  • 2026-09-23 15:14docs: three verification seeds with expected resultsa.baurzhanov1
  • 2026-09-23 15:12fix(ui): leaderboard fits 1024-1280px, team names wrap within a min widthmiras
  • 2026-09-23 15:12docs: backlog statuses, plan addendum for optimizer, events, pitcha.baurzhanov1
  • 2026-09-23 15:11docs: cite the dataset's AI role requirement in READMEa.baurzhanov1
  • 2026-09-23 15:10fix: optimizer cache keyed by dataset hash, finite-score guard, event EPS, pitch newline safety, turbopack ignorea.baurzhanov1
  • 2026-09-23 15:07docs: test counta.baurzhanov1
  • 2026-09-23 15:07docs: README and backlog for full optimizer, events, pitch exporta.baurzhanov1
  • 2026-09-23 15:06feat: full optimizer with cache (694k sets), city events, pitch export, empty DATA_DIR fallback, run durationa.baurzhanov1
  • 2026-09-23 15:01feat(ui): shock event card and LLM usage panel on the verdictmiras
  • 2026-09-23 14:59chore: turbopack ignore for run store paths, CityEvent contract, refreshed screenshotsa.baurzhanov1
  • 2026-09-23 14:58merge: UI round 2 (leaderboard, heat map, design pass) into maina.baurzhanov1
  • 2026-09-23 14:57feat(ui): landing hero with interactive 3D Baiterek (three.js)miras
  • 2026-09-23 14:55docs(readme): team section with Мирас Есеналы and UI contributionsmiras
  • 2026-09-23 14:55style(ui): anti-slop polish pass and DESIGN.mdmiras
  • 2026-09-23 14:54docs(readme): map features to the case brief, fix surname, update UI scopemiras
  • 2026-09-23 14:50merge: main (consilium backend, integration fixes) into feat/uimiras
  • 2026-09-23 14:47docs: README screenshots of the three screensa.baurzhanov1
  • 2026-09-23 14:46feat(ui): schematic Astana district heat map on briefing and verdict (M9)miras
  • 2026-09-23 14:46fix(ui): read runs from store, surface API errors, recover after SSE drop via early runId, non-fatal stage errorsa.baurzhanov1
  • 2026-09-23 14:46merge: UI + integration fixes into maina.baurzhanov1
  • 2026-09-23 14:41merge: UI (feat/ui) into maina.baurzhanov1
  • 2026-09-23 14:41feat(ui): leaderboard page and runs list API (M8)miras
  • 2026-09-23 14:40docs: README verification section with live numbers, plan sync, live run fixturea.baurzhanov1
  • 2026-09-23 14:40merge: consilium backend (A5-A11) into maina.baurzhanov1
  • 2026-09-23 14:39fix: strict schemas, reasoning effort, LLM fallbacks for reviewer/arbiter, arbiter number guard (review findings)a.baurzhanov1
  • 2026-09-23 14:38feat(ui): live consilium page with stage progress and demo replay (M7, M6)miras
  • 2026-09-23 14:37feat(ui): decision cabinet with live score and mandate prefill (M3, M6 prefill)miras
  • 2026-09-23 14:36docs: backlog statuses after consilium builda.baurzhanov1
  • 2026-09-23 14:35feat(ui): briefing, cabinet components, verdict and council hall (M1, M2, M4, M5)miras
  • 2026-09-23 14:35feat: consilium pipeline — optimizer, experts, synthesizer, reviewers, arbiter, SSE API, JSON store (A5-A11)a.baurzhanov1
  • 2026-09-23 14:34Merge remote-tracking branch 'origin/main' into feat/uimiras
  • 2026-09-23 14:33fix: track src/lib/data (gitignore matched any data/ dir)a.baurzhanov1
  • 2026-09-23 14:32fix: track src/lib/data (gitignore matched any data/ dir)a.baurzhanov1
  • 2026-09-23 14:30chore: Dockerfile, compose, README draft; drop SQLite in favour of JSON runsa.baurzhanov1
  • 2026-09-23 14:26Merge remote-tracking branch 'origin/main' into feat/uimiras
  • 2026-09-23 14:26feat(ui): app shell, letterhead theme and route stubs (M0)miras
  • 2026-09-23 14:25feat: llm wrapper and consilium module stubsa.baurzhanov1
  • 2026-09-23 14:22feat: dataset, validator, engine and facts with golden tests (A2-A4)a.baurzhanov1
  • 2026-09-23 14:19feat: shared types contract and sample run fixture (A1)a.baurzhanov1
  • 2026-09-23 14:15chore: scaffold Next.js 16 app with shadcn, vitest and data deps (A0)a.baurzhanov1
  • 2026-09-23 13:58docs: MVP spec, backlog and Claude Code scaffold for HackAlema.baurzhanov1
Структура репозитория (223 файлов)
.claude/agents/code-reviewer.md
.claude/agents/codebase-explorer.md
.claude/agents/ui-reviewer.md
.claude/commands/handoff.md
.claude/commands/review.md
.claude/commands/task.md
.claude/hooks/check-console-log.py
.claude/project/conventions.md
.claude/project/tech-stack.md
.claude/settings.json
.dockerignore
.env.example
.gitignore
AGENTS.md
CLAUDE.md
DESIGN.md
Dockerfile
README.md
components.json
docker-compose.yml
docs/DECISIONS.md
docs/README.md
docs/adr/README.md
docs/backlog.md
docs/plan.md
docs/research.md
docs/screenshots/briefing.png
docs/screenshots/cabinet.png
docs/screenshots/leaderboard.png
docs/screenshots/verdict-full.png
docs/screenshots/verdict.png
docs/source/brief.md
docs/source/dataset.md
e2e/acceptance.spec.ts
eslint.config.mjs
fixtures/README.md
fixtures/live-run.json
fixtures/sample-run.json
next.config.ts
package.json
playwright.config.ts
postcss.config.mjs
public/.gitkeep
public/dataset-hackalem.json
src/app/api/run/route.ts
src/app/api/runs/[id]/event/route.ts
src/app/api/runs/[id]/pitch/route.ts
src/app/api/runs/[id]/route.ts
src/app/api/runs/[id]/voice/route.ts
src/app/api/runs/route.ts
src/app/favicon.ico
src/app/globals.css
src/app/layout.tsx
src/app/leaderboard/page.tsx
src/app/page.tsx
src/app/play/page.tsx
src/app/result/[runId]/page.tsx
src/app/result/live/page.tsx
src/app/sandbox/page.tsx
src/components/briefing/DistrictGrid.tsx
src/components/briefing/DistrictTile.tsx
src/components/briefing/TeamForm.tsx
src/components/consilium/ArbiterResolution.tsx
src/components/consilium/ConditionRow.tsx
src/components/consilium/ConsiliumHall.tsx
src/components/consilium/DisputeItem.tsx
src/components/consilium/DraftHistory.tsx
src/components/consilium/DraftList.tsx
src/components/consilium/DraftText.tsx
src/components/consilium/DraftView.tsx
src/components/consilium/ExpertCard.tsx
src/components/consilium/ExpertDetails.tsx
src/components/consilium/ExpertLine.tsx
src/components/consilium/ExpertPendingCard.tsx
src/components/consilium/ExpertTable.tsx
src/components/consilium/FactChip.tsx
src/components/consilium/HallSection.tsx
src/components/consilium/MandateItem.tsx
src/components/consilium/ResolutionBrief.tsx
src/components/consilium/ResolutionDetails.tsx
src/components/consilium/ReviewRound.tsx
src/components/consilium/ReviewerBoard.tsx
src/components/consilium/conditions.ts
src/components/consilium/highlight.ts
src/components/landing/BaiterekCanvas.tsx
src/components/landing/BaiterekScene.tsx
src/components/landing/BaiterekSilhouette.tsx
src/components/landing/HeightReadout.tsx
src/components/landing/baiterek-base.ts
src/components/landing/baiterek-camera.ts
src/components/landing/baiterek-dims.ts
src/components/landing/baiterek-model.ts
src/components/landing/baiterek-post.ts
src/components/landing/baiterek-sphere.ts
src/components/landing/baiterek-stage.ts
src/components/landing/baiterek-trunk.ts
src/components/landing/spin-controls.ts
src/components/leaderboard/LeaderboardRow.tsx
src/components/leaderboard/LeaderboardTable.tsx
src/components/live/LiveHall.tsx
src/components/live/LiveMessage.tsx
src/components/live/LiveRun.tsx
src/components/live/StageList.tsx
src/components/live/useLiveRun.ts
src/components/map/DistrictHeatMap.tsx
src/components/map/DistrictShape.tsx
src/components/map/HeatLegend.tsx
src/components/map/geometry.ts
src/components/map/heat.test.ts
src/components/map/heat.ts
src/components/play/BudgetBar.tsx
src/components/play/Cabinet.tsx
src/components/play/DistrictPicker.tsx
src/components/play/LiveScore.tsx
src/components/play/MandateNotice.tsx
src/components/play/MeasureCatalog.tsx
src/components/play/MeasureDetails.tsx
src/components/play/MeasureRow.tsx
src/components/play/RowNotes.tsx
src/components/play/SetPanel.tsx
src/components/play/SlotList.tsx
src/components/play/ValidationErrors.tsx
src/components/play/useCabinet.ts
src/components/result/DeltaValue.tsx
src/components/result/Disclosure.tsx
src/components/result/DistrictComparison.tsx
src/components/result/DistrictSwitcher.tsx
src/components/result/HowCalculated.tsx
src/components/result/IndicatorTable.tsx
src/components/result/MeasureContributions.tsx
src/components/result/NextSteps.tsx
src/components/result/OutcomeStamp.tsx
src/components/result/QuarterSlider.tsx
src/components/result/ScoreRadar.tsx
src/components/result/ShockEventCard.tsx
src/components/result/UsagePanel.tsx
src/components/result/VerdictSummary.tsx
src/components/result/VoiceButton.tsx
src/components/sandbox/DatasetPreview.tsx
src/components/sandbox/SandboxImport.tsx
src/components/sandbox/SandboxNotice.tsx
src/components/sandbox/useSandbox.ts
src/components/shell/AppMark.tsx
src/components/shell/AppShell.tsx
src/components/shell/MainNav.tsx
src/components/shell/PageHeader.tsx
src/components/shell/SiteHeader.tsx
src/components/ui/badge.tsx
src/components/ui/button.tsx
src/components/ui/card.tsx
src/components/ui/progress.tsx
src/components/ui/separator.tsx
src/components/ui/tabs.tsx
src/lib/consilium/arbiter.test.ts
src/lib/consilium/arbiter.ts
src/lib/consilium/experts.test.ts
src/lib/consilium/experts.ts
src/lib/consilium/fallback.ts
src/lib/consilium/llm.ts
src/lib/consilium/numbers.test.ts
src/lib/consilium/numbers.ts
src/lib/consilium/pipeline.test.ts
src/lib/consilium/pipeline.ts
src/lib/consilium/prompts.ts
src/lib/consilium/reviewers.test.ts
src/lib/consilium/reviewers.ts
src/lib/consilium/synthesizer.ts
src/lib/data/data.test.ts
src/lib/data/districts.ts
src/lib/data/index.ts
src/lib/data/measures.ts
src/lib/data/synergies.ts
src/lib/data/weights.ts
src/lib/dataset.test.ts
src/lib/dataset.ts
src/lib/engine/engine.test.ts
src/lib/engine/engine.ts
src/lib/engine/events.test.ts
src/lib/engine/events.ts
src/lib/engine/facts.ts
src/lib/engine/index.ts
src/lib/engine/optimizer.test.ts
src/lib/engine/optimizer.ts
src/lib/engine/sandbox.test.ts
src/lib/engine/timeline.test.ts
src/lib/engine/timeline.ts
src/lib/engine/validator.ts
src/lib/fixture.test.ts
src/lib/pitch/pitch.test.ts
src/lib/pitch/pitch.ts
src/lib/smoke.test.ts
src/lib/store/runs.test.ts
src/lib/store/runs.ts
src/lib/types.ts
src/lib/ui/cabinet.test.ts
src/lib/ui/cabinet.ts
src/lib/ui/format.test.ts
src/lib/ui/format.ts
src/lib/ui/humanize.test.ts
src/lib/ui/humanize.ts
src/lib/ui/labels.ts
src/lib/ui/llm-status.test.ts
src/lib/ui/llm-status.ts
src/lib/ui/pending-run.ts
src/lib/ui/replay.test.ts
src/lib/ui/replay.ts
src/lib/ui/run-source.test.ts
src/lib/ui/run-source.ts
src/lib/ui/run-stream.test.ts
src/lib/ui/run-stream.ts
src/lib/ui/sandbox.ts
src/lib/ui/scenario.test.ts
src/lib/ui/scenario.ts
src/lib/ui/team.ts
src/lib/ui/timeline.test.ts
src/lib/ui/timeline.ts
src/lib/ui/verdict.test.ts
src/lib/ui/verdict.ts
src/lib/utils.ts
src/lib/voice/voice.ts
tsconfig.json
vitest.config.ts
yarn.lock
Ветки (4)

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

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

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