О проекте
Команда: KM
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Доведённый продукт
Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам
Суть
Веб-симулятор «Аким на 5 часов»: пользователь распределяет 100 единиц бюджета по решениям для 5 районов на GIS-карте Астаны и сравнивает последствия на горизонте 8 кварталов; AI-агент объясняет результаты и предлагает изменения.
Как устроено
Детерминированный расчёт сценария (CalculateScenario, CompareScenarios, FindScenarioAlternatives) на учебном датасете astana-v1 работает без AI. Поверх него агенты Laravel AI SDK (ScenarioAnalysisAgent, ScenarioChatAgent) через ToolBroker вызывают инструменты EvaluateScenario, ProposeScenario, ProposeNote, SearchNotes; предложения агента применяются только после подтверждения пользователем. GIS-слои (ArcGIS-клиент, векторные тайлы) хранятся в PostGIS с офлайн-seed, AI-запуски идут через очередь; есть демо-режим AGENT_DRIVER=demo без ключа.
Ключевые решения
- детерминированная модель сценария
- tool calling (EvaluateScenario/ProposeScenario)
- human-in-the-loop подтверждение
- PostGIS векторные тайлы
- ArcGIS импорт слоёв
- очереди Laravel
- RBAC (аким/аналитик/админ)
Особенности
Реальная GIS-карта Астаны с компактным офлайн-архивом слоёв; расчёты полностью детерминированы и работают без LLM, а агент только объясняет и предлагает изменения, которые применяются после явного подтверждения. Роли пользователей и серверная проверка прав, демо-рантайм без ключа.
Стек
PHP 8.4 · Laravel 13 · PostgreSQL 18 · PostGIS · React 19 · Inertia 3 · TypeScript · Tailwind 4 · Filament 5 · Vite
Модели
OpenAI (через Laravel AI SDK)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-64a7eb6b-km.
README
README.mdHACKALEM.AI
«Аким на 5 часов» — учебный AI-симулятор управления городом с GIS-картой Астаны. Выберите пять решений для пяти районов учебного сценария, распределите 100 единиц бюджета и сравните последствия через восемь кварталов. Расчёты и сохранение сценариев работают без AI; агент объясняет результаты и предлагает изменения, которые применяются только после подтверждения пользователя.
Демо доступно по ссылке: ha-demo.5n.kz.
Стек: PHP 8.4+, Laravel 13, PostgreSQL 18 с PostGIS, React 19, Inertia 3, TypeScript, Tailwind 4, Filament 5, Vite 8 / Vite+. Laravel AI SDK управляет обращениями к моделям и инструментам; Laravel Boost предоставляет инструменты разработчикам.
Требования
- PHP 8.4+ с
pdo_pgsql,intl,bcmath,mbstring,dom,xml,zip,gd,pcntl,curl,openssl,zlib. Для Windows используйте WSL2: процессы очередей требуютpcntl. - Composer 2, Node.js 22.12+ и npm. Версии зависимостей зафиксированы в
composer.lockиpackage-lock.json. - PostgreSQL 18 и установленный для этой версии сервера PostGIS. Расширение нужно в обеих базах:
hackalemиhackalem_testing. Локальное окружение проверено с PostGIS 3.6. - Доступ на запись в
storage/иbootstrap/cache/; свободное место для PostgreSQL и GIS-файлов вstorage/app/private/gis/.
Очереди, сессии и кэш по умолчанию хранятся в PostgreSQL. Redis для стандартного запуска не нужен. Установка зависимостей требует интернета; комплектный GIS-архив импортируется без запросов к внешнему GIS API.
Первая установка
git clone https://github.com/BAITC-Hacks/hack-64a7eb6b-km.git hackalem
cd hackalem
# Один раз, после установки и запуска PostgreSQL с PostGIS.
createdb -h 127.0.0.1 -U postgres hackalem
createdb -h 127.0.0.1 -U postgres hackalem_testing
psql -h 127.0.0.1 -U postgres -d hackalem -c 'CREATE EXTENSION IF NOT EXISTS postgis;'
psql -h 127.0.0.1 -U postgres -d hackalem_testing -c 'CREATE EXTENSION IF NOT EXISTS postgis;'
# Только для новой установки: не перезаписывайте существующий .env.
cp .env.example .env
Перед следующей командой настройте .env: параметры DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD должны соответствовать вашим базам и пользователю. Команды выше предполагают локального пользователя postgres; при другом пользователе измените -U и назначьте ему необходимые права на базы. GIS-миграция также выполняет CREATE EXTENSION IF NOT EXISTS postgis: установите расширение заранее с правами администратора либо обеспечьте эти права пользователю миграций.
Для первого запуска без обращений к моделям задайте:
APP_ENV=local
APP_DEBUG=true
APP_URL=http://localhost:8000
SERVER_PORT=8000
DEMO_ADMIN_ENABLED=true
DB_CONNECTION=pgsql
QUEUE_CONNECTION=database
DB_QUEUE_RETRY_AFTER=240
CACHE_STORE=database
SESSION_DRIVER=database
AGENT_DRIVER=demo
OPENAI_API_KEY=
В .env.example указан AGENT_DRIVER=auto: он включает реальный AI при наличии ключа выбранного провайдера. demo принудительно оставляет локальный режим, даже если ключ уже задан.
composer setup
php artisan app:doctor --no-interaction
composer dev
composer setup выполняет composer install, создаёт .env, если его нет, вызывает app:prepare, затем npm ci и npm run build. app:prepare:
- Создаёт
APP_KEY, только если ключ ещё не задан. - Применяет миграции без очистки базы.
- Создаёт локальные демо-учётные записи при включённом
DEMO_ADMIN_ENABLED. - Загружает учебный датасет
astana-v1и комплектный GIS-архив.
app:prepare разрешён только в local / testing. Существующий ключ и сохранённые сценарии остаются на месте. Повторная загрузка GIS seed пропускается, если в базе уже есть общие GIS-слои. Не используйте migrate:fresh для обновления базы приложения.
Локальный запуск
composer dev запускает пять процессов и останавливает остальные, если один из них завершился:
| Процесс | Назначение |
|---|---|
php artisan serve --host=127.0.0.1 | Laravel HTTP-сервер |
php artisan queue:work --queue=agents,default --tries=1 --timeout=180 | AI- и демо-задачи, очередь default |
php artisan queue:listen --queue=gis --tries=4 --timeout=190 --memory=1024 | Импорт GIS в отдельном процессе |
php artisan schedule:work | Планировщик |
npm run dev -- --host=127.0.0.1 | Vite, обновление frontend и SSR в разработке |
По умолчанию приложение открывается на http://localhost:8000. Если порт занят, задайте одинаковый порт в APP_URL и SERVER_PORT, например 8007, и перезапустите composer dev. Vite использует локальный HTTP без автоматического сертификата Herd. Отдельный inertia:start-ssr в режиме разработки не требуется.
Если HTTP-сервер уже предоставляет Herd или другой сервер, запустите оставшиеся четыре команды из таблицы в отдельных терминалах. Простого php artisan serve недостаточно для обработки очередей и расписания.
| Путь | Что открывается |
|---|---|
/ или /login | Вход |
/map | Карта и симулятор; сюда перенаправляет после входа |
/scenarios | Сохранённые сценарии |
/scenarios/create | Создание сценария |
/dashboard | Список сценариев |
/admin | Filament: управление доступом и просмотр запусков и сценариев |
Пользовательские страницы требуют входа и подтверждённого email. Отдельной страницы GET /runs сейчас нет: AI-запуски отображаются в сценариях и на карте.
Вход и права
При APP_ENV=local и DEMO_ADMIN_ENABLED=true подготовка проекта создаёт три учётные записи с подтверждённым email:
| Роль | Пароль | Права по умолчанию | |
|---|---|---|---|
super_admin | [email protected] | admin | Пользовательское приложение и Filament |
| Аналитик | [email protected] | analyst | Просмотр, без создания запусков и подтверждения изменений |
| Аким (Городской управленец) | [email protected] | akim | Создание сценариев и запусков, отмена и подтверждение своих предложений |
Это локальные демо-данные. Подсказки на странице входа отображаются только для доступных учётных записей с исходными паролями. db:seed повторно создаёт недостающие демо-записи; существующие аккаунты аналитика и акима не перезаписываются. Демо-администратор восстанавливает исходный пароль и роль также при открытии /admin/login.
DEMO_ADMIN_ENABLED=false отключает автоматическое создание и подсказки, но не удаляет уже созданные аккаунты. В production создание демо-пользователей и подсказки выключены независимо от флага; существующие записи при этом также сохраняются.
Для личной локальной учётной записи есть интерактивная команда со скрытым вводом пароля от 12 символов:
php artisan app:user [email protected] --name=Developer --admin
Без --admin назначается роль акима. Команда работает только при APP_ENV=local. Обычная регистрация тоже доступна; при MAIL_MAILER=log ссылки подтверждения email находятся в storage/logs/laravel.log.
В Filament допускается только super_admin с подтверждённым email. Пользователей и роли можно редактировать, а запуски и снимки сценариев доступны только для просмотра. Системная роль и демо-администратор защищены; последнего супер-администратора нельзя удалить или лишить доступа. Новым пользователям назначается роль акима. Права проверяются сервером: даже super_admin не получает доступ к чужим сценариям и предложениям через пользовательские маршруты.
Очереди и расписание
Для стандартной конфигурации оставьте QUEUE_CONNECTION=database и DB_QUEUE_RETRY_AFTER=240. Значение retry_after должно быть больше всех таймаутов задач и процессов: AI job — 180 секунд, GIS job — 170 секунд, GIS listener — 190 секунд. app:doctor проверяет порог только относительно 180 секунд; не уменьшайте интервал до значения ниже GIS-таймаута.
AI- и демо-запуски используют одну очередь agents. Без её worker задача останется в queued. Автоматические повторы AI отключены (tries=1); повтор через интерфейс создаёт новый запуск. Не используйте массовый queue:retry all для повторения AI-запусков: завершённая задача повторно не исполняется. GIS допускает до четырёх попыток при временных сетевых сбоях, с задержками 15, 60 и 180 секунд.
Расписание находится в routes/console.php:
- Каждую минуту
agents:expire-runsзавершает ошибкой запуски вrunningстарше пяти минут и вqueuedстарше часа. - Ежедневно в 03:00 по Asia/Almaty
gis:syncобнаруживает внешние слои и ставит их импорт в очередьgis.schedule:listможет показывать время в часовом поясе приложения.
После изменения PHP-кода или конфигурации перезапустите процессы. Для локального composer dev проще остановить его через Ctrl+C, при изменении .env выполнить php artisan config:clear --no-interaction, затем снова запустить composer dev. Команда queue:restart завершает постоянные workers после текущей задачи; сама она новые процессы не запускает. В связке concurrently --kill-others завершение worker остановит и остальные процессы.
Диагностика без обработки задач:
php artisan app:doctor --no-interaction
php artisan migrate:status --no-interaction
php artisan schedule:list --no-interaction
php artisan queue:failed --no-interaction
php artisan gis:status --no-interaction
Ошибки AI смотрите также в карточке запуска и storage/logs/laravel.log: runtime фиксирует неудачный запуск сам, поэтому запись не обязательно появится в queue:failed. app:doctor не вызывает AI и не проверяет доступность всех внешних GIS-источников или полноту архива.
GIS-данные
Комплектный архив находится в database/seeders/data/gis-astana/. GisDatasetSeeder проверяет целостность файлов и восстанавливает объекты в PostgreSQL, а файлы карты — в storage/app/private/gis/blobs/. Повторная установка сохраняет существующий общий архив. GIS_SEED_ENABLED=false позволяет пропустить загрузку GIS seed.
Компактный seed ограничен 50 МБ: он содержит выбранные слои и базовые векторные тайлы до zoom 13, а не полную копию внешнего портала. Слои могут иметь состояния seeded или not_seeded; отсутствие объекта в неполном снимке не означает его удаления. Полноту и версии показывает gis:status --json. Учебные показатели пяти районов синтетические и не заменяют географические данные GIS.
Для обновления из внешнего источника нужен интернет и работающий процесс очереди gis:
# Новый импорт обнаруженных слоёв.
php artisan gis:sync --no-interaction
# Продолжить незавершённый импорт, включая слои с ошибками.
php artisan gis:sync --resume --no-interaction
# Импортировать только векторные и табличные слои.
php artisan gis:sync --vectors --no-interaction
php artisan gis:status --json --no-interaction
Это отдельные варианты запуска: не выполняйте все три команды синхронизации подряд без необходимости. gis:sync ставит задания в очередь, а не ждёт окончания загрузки. Полный архив, особенно растры и подробные тайлы, может занимать существенно больше места, чем seed. История внешних данных начинается с первого наблюдения.
Экспорт переносимого seed выполняется в новый, ещё не существующий каталог:
php artisan gis:seed-export --path=/tmp/hackalem-gis-seed --no-interaction
По умолчанию экспорт компактный; --full включает полный архив. Для фиксации скачанных частей незавершённого импорта предусмотрен --freeze-incomplete: сначала остановите GIS workers и исключите запуск новой синхронизации. Эта опция меняет состояние неполных версий в базе.
AI: демо и реальный провайдер
AGENT_DRIVER | Поведение |
|---|---|
demo | Локальные ответы и настоящие инструменты приложения без вызовов моделей |
auto | AI при непустом ключе выбранного провайдера, иначе демо; значение в .env.example |
laravel | Обязательный реальный провайдер; отсутствие ключа считается ошибкой |
Демо использует PostgreSQL, очередь, расчёты, журнал и подтверждения. Оно объясняет бюджет, районы, риски, сроки эффекта и синергии, сравнивает варианты и учитывает последние шесть успешных пар сообщений сценария. Свободный диалог с языковой моделью оно не заменяет.
Для реального AI добавьте ключ только в игнорируемый .env или хранилище секретов окружения. Не публикуйте его в Git, логах или сообщениях. Настройки провайдера по умолчанию:
AGENT_DRIVER=auto
AGENT_PROVIDER=openai
AGENT_MODEL=gpt-5.4-nano
Ключ задаётся переменной OPENAI_API_KEY. Модель должна быть доступна вашему аккаунту и поддерживать инструменты. Другие провайдеры настраиваются в config/ai.php.
После изменения режима, модели или ключа очистите локальный кэш конфигурации, выполните app:doctor и перезапустите процессы. В production пересоберите config:cache и перезапустите workers через менеджер процессов.
Режим, провайдер, модель, версия prompt и лимиты сохраняются при постановке задачи. Старый демо-запуск не станет платным после добавления ключа. Принудительный demo блокирует выполнение ранее поставленных live-задач; удаление ключа приводит к ошибке уже поставленного live-запуска. Ошибки ключа, квоты и соединения не подменяются демо.
Лимиты из config/agents.php:
| Переменная | По умолчанию | Допустимые границы |
|---|---|---|
AGENT_MAX_STEPS | 5 | 1–10 |
AGENT_MAX_TOKENS | 2048 | 128–8192 выходных токенов на один вызов модели |
AGENT_MAX_TOOL_CALLS | 8 | 1–20 |
AGENT_TIMEOUT | 120 | 10–150 секунд на запрос |
Эти ограничения не являются денежным бюджетом. Одновременно допускаются до трёх активных запусков на пользователя, не более одного разбора и одного диалога на сценарий. Любое предложение записи проходит через ToolBroker и отдельное подтверждение владельца после успешного завершения запуска. Отменённый или неуспешный запуск не может применить предложение.
Проверка городского сценария
- Войдите как аким или администратор, откройте
/scenarios→ «Новый сценарий» → «Пример из задания». - Проверьте расчёт: Score 56,54307, расходы 95. Исходный Score города — 52,55768; интерфейс может округлять отображение.
- Сохраните сценарий: расчёт, матрица показателей, синергии и до трёх лучших замен доступны сразу, независимо от AI.
- Нажмите «Получить разбор». Затем спросите: «Как распределён бюджет?», «Покажи варианты улучшения», «Сравни второй вариант», «Подготовь его».
- Проверьте пять решений и Score в предложении. «Создать этот вариант» сохраняет отдельный сценарий; «Отклонить» оставляет исходный.
- Сравните два сценария одной версии датасета и калькулятора.
Сервер проверяет ровно пять разных мер, максимум две в направлении, бюджет ≤100, корректность районов и несовместимости. Неиспользованный бюджет бонуса не даёт. Расчёт ведётся с точностью BCMath; AI не определяет итоговый Score.
Обновление существующей локальной установки
Сделайте резервную копию PostgreSQL и storage/app/private/gis/, остановите composer dev, получите нужную версию кода и выполните из корня проекта:
composer install --no-interaction
npm ci
php artisan config:clear --no-interaction
php artisan app:prepare --no-interaction
npm run build
php artisan app:doctor --no-interaction
composer dev
Сохраняйте .env и APP_KEY; не копируйте .env.example поверх своей конфигурации. Новые переменные переносите вручную. app:prepare применяет миграции и seed без очистки базы; для загрузки только учебного датасета есть php artisan db:seed --class=SimulationDatasetSeeder --no-interaction. Существующая версия astana-v1 не перезаписывается — изменения данных оформляются новой версией.
Тесты и проверки
Тестам нужна отдельная PostgreSQL-база hackalem_testing с PostGIS. При необходимости скопируйте .env.testing.example в .env.testing, настройте подключение и локальный APP_KEY. PHPUnit принудительно задаёт имя тестовой базы, AGENT_DRIVER=demo, пустой OPENAI_API_KEY и отключает автоматический GIS seed. Базовый TestCase проверяет имя базы до её очистки и запрещает непредусмотренные HTTP-запросы. Не запускайте несколько наборов тестов одновременно против одной базы.
composer test:agents # AgentRuntimeTest: жизненный цикл, инструменты, approvals
php artisan test --compact --filter='SimulationCalculationTest|SimulationScenarioTest|ScenarioAiTest' --no-interaction
php artisan test --compact --filter=Gis --no-interaction
composer test # Весь PHP-набор на PostgreSQL
composer types:check # Larastan, level 7
php artisan wayfinder:generate --with-form --no-interaction
npm run types:check
npm run check # Frontend lint и форматирование
npm run test:simulator
composer ci:check # Pint, Larastan, frontend checks, PHP-тесты и production build
git diff --check
Полная проверка комплектного GIS-архива включается отдельно; обычный прогон её пропускает:
GIS_VERIFY_SEED=true php artisan test --compact --filter=test_bundled_dataset --no-interaction
SDK-тесты используют fake()->preventStrayPrompts() и не вызывают платные API. Fake не исполняет цикл инструментов: ToolBroker и подтверждения проверяются отдельно. Сгенерированные resources/js/actions, resources/js/routes и resources/js/wayfinder не редактируются вручную; их создают Wayfinder, сборка и composer ci:check.
В .github/workflows/tests.yml настроен composer ci:check с PostgreSQL 18. Для GIS-тестов CI также нужен PostGIS: в текущем workflow указан образ postgres:18 без отдельного шага установки расширения; это окружение необходимо дополнить PostGIS перед запуском GIS-миграций.
Запуск на сервере
composer setup, app:prepare и app:user предназначены для локальной подготовки. Для production нужны HTTPS, APP_ENV=production, APP_DEBUG=false, корректный APP_URL, постоянный APP_KEY, настроенная почта, PostgreSQL с PostGIS и резервное копирование базы вместе с GIS-файлами. Корень web-сервера — public/; PHP должен иметь доступ на запись в storage/ и bootstrap/cache/. Перед публикацией базы из локального окружения замените известные демо-пароли и проверьте права: production-флаг сам по себе эти аккаунты не удаляет.
Основные команды подготовки релиза после настройки окружения:
composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction
npm ci
php artisan config:clear --no-interaction
php artisan migrate --force --no-interaction
php artisan db:seed --class=AccessControlSeeder --force --no-interaction
php artisan db:seed --class=SimulationDatasetSeeder --force --no-interaction
php artisan db:seed --class=GisDatasetSeeder --force --no-interaction
npm run build
php artisan config:cache --no-interaction
php artisan route:cache --no-interaction
php artisan view:cache --no-interaction
php artisan queue:restart --no-interaction
Запускайте эти шаги как часть релиза с резервной копией и согласованным переключением процессов. Создание первоначального production-администратора выполняется вашим процессом управления доступом; локальная команда app:user там недоступна.
Supervisor, systemd или менеджер процессов платформы должен поддерживать два отдельных worker:
php artisan queue:work --queue=agents,default --tries=1 --timeout=180 --no-interaction
php artisan queue:work --queue=gis --tries=4 --timeout=190 --memory=1024 --no-interaction
Настройте автоматический перезапуск после queue:restart, достаточное время для завершения текущей задачи и общий постоянный кэш для web и workers. Для расписания достаточно одного cron-вызова в минуту; замените /path/to/hackalem на каталог релиза:
* * * * * cd /path/to/hackalem && php artisan schedule:run --no-interaction >> /dev/null 2>&1
Для production SSR предусмотрены npm run build:ssr и отдельный управляемый процесс php artisan inertia:start-ssr --no-interaction; после смены сборки его также нужно перезапустить. composer dev не заменяет процессы production-сервера.
Частые проблемы
| Симптом | Что проверить |
|---|---|
| Миграция сообщает, что PostGIS недоступен или не хватает прав | Установку PostGIS для нужной версии PostgreSQL и расширение в выбранной базе |
AI-задача остаётся в queued | Worker очереди agents, соединение с БД, логи и scheduler |
| GIS-импорт не движется | Отдельный worker gis, gis:status, свободное место и доступ к внешнему источнику |
После изменения .env остался прежний режим | Кэш конфигурации и перезапуск процессов; старые задачи сохраняют снимок настроек |
| Изменения интерфейса не видны или отсутствует Vite manifest | Работающий npm run dev либо новая сборка npm run build |
| При входе нет доступа к карте или админпанели | Подтверждение email, роль и разрешения пользователя |
Инструменты разработки и устройство проекта
Пользовательские страницы находятся в resources/js/pages, симулятор — в pages/scenarios и components/simulator, GIS — в app/Actions/Gis, AI runtime — в app/Ai, жизненный цикл задач — в app/Actions/AgentRuns и app/Jobs. Filament использует собственный Livewire UI.
AGENTS.md, CLAUDE.md, .agents/skills, .claude/skills, .codex/config.toml, .mcp.json и boost.json содержат инструкции и настройки coding-агентов. Обновление и запуск Boost:
composer boost:refresh
php artisan boost:mcp
Вторая команда запускает STDIO-сервер для MCP-клиента из корня проекта. Boost — dev dependency с инструментами разработчика; его не следует подключать к пользовательскому AI runtime или публиковать как внешний сервис. composer boost:refresh меняет сгенерированные инструкции и настройки, поэтому проверяйте diff после запуска.
Подробности: разработка, архитектура и ограничения, оценка и расширение. Коммиты, push и deployment выполняются только по явной команде пользователя.
Источники
- Laravel React starter kit, основа из snapshot
717b8f55aefd82d25d4119eaebdc8e3a72b8d7e5. - Laravel AI SDK и Laravel Boost.
- Очереди Laravel и планировщик.
- Inertia 3: SSR и Filament 5.
Авторы коммитов
История коммитов
- 2026-09-23 17:51feat: refine simulator UI and enforce light themeKuat Mustafin
- 2026-09-23 17:40feat: add automatic AI runtime and scenario demo chatKuat Mustafin
- 2026-09-23 17:03feat: add Astana GIS map with compact offline seedKuat Mustafin
- 2026-09-23 15:28chore: update dashboard navigationKuat Mustafin
- 2026-09-23 14:31feat: add city simulation scenarios and AI advisorKuat Mustafin
- 2026-09-23 13:37feat: initialize HACKALEM.AI agent workspaceKuat Mustafin
Структура репозитория (612 файлов)
.agents/skills/ai-sdk-development/SKILL.md .agents/skills/filament-development/SKILL.md .agents/skills/fortify-development/SKILL.md .agents/skills/inertia-react-development/SKILL.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 .agents/skills/wayfinder-development/SKILL.md .claude/skills/ai-sdk-development/SKILL.md .claude/skills/filament-development/SKILL.md .claude/skills/fortify-development/SKILL.md .claude/skills/inertia-react-development/SKILL.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 .claude/skills/wayfinder-development/SKILL.md .codex/config.toml .editorconfig .env.example .env.testing.example .gitattributes .github/dependabot.yml .github/workflows/tests.yml .gitignore .mcp.json .node-version .npmrc AGENTS.md CLAUDE.md README.md app/Actions/Access/DeleteRole.php app/Actions/Access/DeleteUser.php app/Actions/Access/SaveRole.php app/Actions/Access/SaveUser.php app/Actions/AgentRuns/CreateRun.php app/Actions/AgentRuns/CreateScenarioRun.php app/Actions/AgentRuns/ResolveApproval.php app/Actions/AgentRuns/StopRun.php app/Actions/EnsureDemoAdmin.php app/Actions/EnsureDemoUsers.php app/Actions/Fortify/CreateNewUser.php app/Actions/Fortify/ResetUserPassword.php app/Actions/Gis/ArcGisClient.php app/Actions/Gis/DiscoverGisLayers.php app/Actions/Gis/EditGisFeature.php app/Actions/Gis/GisArchive.php app/Actions/Gis/GisFeatures.php app/Actions/Gis/GisSeedPackage.php app/Actions/Gis/GisSeedSelection.php app/Actions/Gis/GisTiles.php app/Actions/Gis/GisVectorTile.php app/Actions/Gis/ImportGisLayer.php app/Actions/Simulations/CalculateScenario.php app/Actions/Simulations/CompareScenarios.php app/Actions/Simulations/CreateScenario.php app/Actions/Simulations/FindScenarioAlternatives.php app/Actions/Simulations/ScenarioFacts.php app/Actions/Simulations/ValidateScenario.php app/Ai/Agents/ScenarioAnalysisAgent.php app/Ai/Agents/ScenarioChatAgent.php app/Ai/Agents/WorkspaceAgent.php app/Ai/Runtime/AgentRuntime.php app/Ai/Runtime/DemoRuntime.php app/Ai/Runtime/LaravelAiRuntime.php app/Ai/Runtime/RunResult.php app/Ai/Runtime/RuntimeConfiguration.php app/Ai/Runtime/ScenarioDemoRuntime.php app/Ai/ToolBroker.php app/Ai/Tools/EvaluateScenario.php app/Ai/Tools/ProposeNote.php app/Ai/Tools/ProposeScenario.php app/Ai/Tools/SearchNotes.php app/Concerns/PasswordValidationRules.php app/Concerns/ProfileValidationRules.php app/Console/Commands/ApplicationDoctor.php app/Console/Commands/CreateApplicationUser.php app/Console/Commands/ExpireAgentRuns.php app/Console/Commands/ExportGisSeed.php app/Console/Commands/GisStatus.php app/Console/Commands/PrepareApplication.php app/Console/Commands/SyncGis.php app/Enums/AccessPermission.php app/Enums/RunStatus.php app/Filament/Pages/Auth/Login.php app/Filament/Resources/AgentRuns/AgentRunResource.php app/Filament/Resources/AgentRuns/Pages/ListAgentRuns.php app/Filament/Resources/AgentRuns/Pages/ViewAgentRun.php app/Filament/Resources/AgentRuns/Schemas/AgentRunInfolist.php app/Filament/Resources/AgentRuns/Tables/AgentRunsTable.php app/Filament/Resources/Permissions/Pages/ListPermissions.php app/Filament/Resources/Permissions/PermissionResource.php app/Filament/Resources/Permissions/Tables/PermissionsTable.php app/Filament/Resources/Roles/Pages/CreateRole.php app/Filament/Resources/Roles/Pages/EditRole.php app/Filament/Resources/Roles/Pages/ListRoles.php app/Filament/Resources/Roles/Pages/ViewRole.php app/Filament/Resources/Roles/RoleResource.php app/Filament/Resources/Roles/Schemas/RoleForm.php app/Filament/Resources/Roles/Schemas/RoleInfolist.php app/Filament/Resources/Roles/Tables/RolesTable.php app/Filament/Resources/SimulationScenarios/Pages/ListSimulationScenarios.php app/Filament/Resources/SimulationScenarios/Pages/ViewSimulationScenario.php app/Filament/Resources/SimulationScenarios/Schemas/SimulationScenarioInfolist.php app/Filament/Resources/SimulationScenarios/SimulationScenarioResource.php app/Filament/Resources/SimulationScenarios/Tables/SimulationScenariosTable.php app/Filament/Resources/Users/Pages/CreateUser.php app/Filament/Resources/Users/Pages/EditUser.php app/Filament/Resources/Users/Pages/ListUsers.php app/Filament/Resources/Users/Pages/ViewUser.php app/Filament/Resources/Users/Schemas/UserForm.php app/Filament/Resources/Users/Schemas/UserInfolist.php app/Filament/Resources/Users/Tables/UsersTable.php app/Filament/Resources/Users/UserResource.php app/Http/Controllers/AgentRunController.php app/Http/Controllers/Controller.php app/Http/Controllers/GisFeatureController.php app/Http/Controllers/GisLayerController.php app/Http/Controllers/GisMapStateController.php app/Http/Controllers/ScenarioAiController.php app/Http/Controllers/Settings/ProfileController.php app/Http/Controllers/Settings/SecurityController.php app/Http/Controllers/SimulationScenarioController.php app/Http/Controllers/ToolApprovalController.php app/Http/Middleware/HandleInertiaRequests.php app/Http/Requests/PreviewScenarioRequest.php app/Http/Requests/ScenarioMessageRequest.php app/Http/Requests/Settings/PasswordUpdateRequest.php app/Http/Requests/Settings/ProfileDeleteRequest.php app/Http/Requests/Settings/ProfileUpdateRequest.php app/Http/Requests/Settings/TwoFactorAuthenticationRequest.php app/Http/Requests/StoreAgentRunRequest.php app/Http/Requests/StoreGisFeatureRequest.php app/Http/Requests/StoreScenarioRequest.php app/Jobs/ExecuteAgentRun.php app/Jobs/SyncGisLayer.php app/Models/AgentRun.php app/Models/GisAsset.php app/Models/GisFeatureContent.php app/Models/GisImport.php app/Models/GisLayer.php app/Models/GisLayerVersion.php app/Models/GisMapState.php app/Models/Note.php app/Models/Permission.php app/Models/Role.php app/Models/RunEvent.php app/Models/SimulationDataset.php app/Models/SimulationScenario.php app/Models/ToolApproval.php app/Models/User.php app/Policies/AgentRunPolicy.php app/Policies/GisLayerPolicy.php app/Policies/PermissionPolicy.php app/Policies/RolePolicy.php app/Policies/SimulationScenarioPolicy.php app/Policies/UserPolicy.php app/Providers/AppServiceProvider.php app/Providers/Filament/AdminPanelProvider.php app/Providers/FortifyServiceProvider.php artisan boost.json bootstrap/app.php bootstrap/cache/.gitignore bootstrap/providers.php components.json composer.json composer.lock config/agents.php config/ai.php config/app.php config/auth.php config/cache.php config/database.php config/demo.php config/filesystems.php config/fortify.php config/gis.php config/inertia.php config/logging.php config/mail.php config/permission.php config/queue.php config/services.php config/session.php database/.gitignore database/factories/GisLayerFactory.php database/factories/RoleFactory.php database/factories/SimulationDatasetFactory.php database/factories/SimulationScenarioFactory.php 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/2025_08_14_170933_add_two_factor_columns_to_users_table.php database/migrations/2026_09_22_000001_create_agent_tables.php database/migrations/2026_09_22_185204_create_agent_conversations_table.php database/migrations/2026_09_22_200155_create_permission_tables.php database/migrations/2026_09_22_200245_replace_admin_flag_with_roles.php database/migrations/2026_09_22_203055_add_workspace_permissions.php database/migrations/2026_09_23_014002_restrict_admin_access_to_super_admin.php database/migrations/2026_09_23_084531_create_simulation_datasets_table.php database/migrations/2026_09_23_084532_create_simulation_scenarios_table.php database/migrations/2026_09_23_084533_add_simulation_context_to_agent_runs_table.php database/migrations/2026_09_23_092705_create_gis_archive_tables.php database/migrations/2026_09_23_101850_add_manifest_to_gis_imports_table.php database/migrations/2026_09_23_103507_replace_default_roles_with_city_roles.php database/migrations/2026_09_23_105504_create_demo_users_for_all_roles.php database/seeders/AccessControlSeeder.php database/seeders/DatabaseSeeder.php database/seeders/DemoAdminSeeder.php database/seeders/DemoUsersSeeder.php database/seeders/GisDatasetSeeder.php database/seeders/SimulationDatasetSeeder.php database/seeders/data/astana-v1.json database/seeders/data/gis-astana/blobs/024bbac0d0b1648d66476f7224fd3f9f016cfe784523ef9d77f51b260e00dcab database/seeders/data/gis-astana/blobs/0285c22a1cc6ce7960bc82bbc161b68ac2f5327e9b380c885301f211728cdd03 database/seeders/data/gis-astana/blobs/04262c503601b2b5047088e14b0ef2e097b7d5341552eaf11ad4dbf181622be0 database/seeders/data/gis-astana/blobs/04879967d93b77b5a6277abfe7a47f1cb2ea504abf24b7b146b3596e317132e5 database/seeders/data/gis-astana/blobs/05a3cf285bf06210043dc29423d50a8ed8aee94cb4f2be5bf34fc9dd64663eca database/seeders/data/gis-astana/blobs/076645f6ee25406feaf15a8185ab9fe5ea12afb10173ad972f9ed48d81ebd694 database/seeders/data/gis-astana/blobs/0816039d4de694f30be38a3d31d755c5a3bc523501ba395b84fe01865f92b7ce database/seeders/data/gis-astana/blobs/082b3cadb49c4e042e5d17e5bff96c016889890c91cfa1f9a56ec2bfa1746c9a database/seeders/data/gis-astana/blobs/0cdce1ee7e9badf5f5a095a512b136150e2e0a4b99c23d4dda38642b552fa70b database/seeders/data/gis-astana/blobs/0fb283108fa6c36450415801ce96bfa8dc495258c85e8c23ae048fc430fc2088 database/seeders/data/gis-astana/blobs/0fe0d5b2a40678cc8ee5283d8097bf911cb44be41b65925efc2c50557556e75d database/seeders/data/gis-astana/blobs/12eee11830a582f0eee101c3224d56185dd02ff008bb451e6d8d82a608e04e54 database/seeders/data/gis-astana/blobs/155ed69a142c13db70dd5d2d682972869d96c4ba85fccc8f96bb5e7a9c536d68 database/seeders/data/gis-astana/blobs/19e6b89df107810f07f2a184d6ab08c2070b05a3c4e0d18efd49be6f32d6a85f database/seeders/data/gis-astana/blobs/1a3b2b34cdc730df08ff0cf2fd39eabc92d5a4bbccc08b992c3766051a13c1b3 database/seeders/data/gis-astana/blobs/1ba04362143fb2bf7c1724e875ad75de52bf4f22da6f4d645fa1a9022a3c0647 database/seeders/data/gis-astana/blobs/1ece20df5cfa83e250904918a3a90c87e76ecd3b50b2226d98a7e0517b48b877 database/seeders/data/gis-astana/blobs/1f4c5864b664c5cfefe79d01e411b1be220f3790c5b66d3646e86d28d61ac8b8 database/seeders/data/gis-astana/blobs/1f82a1ea2e61bd059b1b9b3e9499c5e24cd7b1a087f0e1ad9ce1f509b84d819f database/seeders/data/gis-astana/blobs/205f3c7237bfcdc836291dfbec44775a25da9018a058faf67545c44f65471683 database/seeders/data/gis-astana/blobs/232c7ad25a95e7307e05b6f8ea13d0f58dd61b936ac3cb45a5208b3c8f6e4708 database/seeders/data/gis-astana/blobs/236180d99b6a88e76547a952f8374d74c473f30cbda97819b08d5099e2aa0e2b database/seeders/data/gis-astana/blobs/264f3170b73004a9ac119d205f39e74786fc10b1ae0288bcab536799923ecf7f database/seeders/data/gis-astana/blobs/29364b0e1bcdb8ed41a44190f45a01ab92561d2931e5445929221903b4d89f7b database/seeders/data/gis-astana/blobs/29ce15ca7d8b48988d487cb62a7baf25891e025f259875e1649bf18f0b204a41 database/seeders/data/gis-astana/blobs/29edfd246b58a0e64e36bb6af00f41193baa14d29e21310f80a421f52932596e database/seeders/data/gis-astana/blobs/2a6f6f2d6e77cd65439fb8fd5f765e543df84437b8cfec00e6d32d900eee96a9 database/seeders/data/gis-astana/blobs/2c97d40de1a4c18b079375371c4842aea27521ea2b603129b946394ba34d7704 database/seeders/data/gis-astana/blobs/2ef4b941da29e502f2b25a042cb46333ac6eed0f836b4e3342e5cadb6db98214 database/seeders/data/gis-astana/blobs/2f49736d24302764bf1f8f2831230584e80da9fe1b86b544aa3f248cc8fdb119 database/seeders/data/gis-astana/blobs/302db041e5a27eed4a600956e993b47ee9ad034546cb6ce4b703b88f9c022d37 database/seeders/data/gis-astana/blobs/30db94550107d147f90359fa4f0f937d3673e07b5f4f29fde0384bf04267d65a database/seeders/data/gis-astana/blobs/32dbd08924a198331f8e3eb2ebc2de75d269152ac9a155283e24b77e0112eaba database/seeders/data/gis-astana/blobs/33577876da5a8229e3cb689e210db9b4ad08d36e8beea40a39d57130adffebdb database/seeders/data/gis-astana/blobs/33c0255682b74d7a9f0a98c47a04d4d7b1df869037f348f548880b46890d9701 database/seeders/data/gis-astana/blobs/34a96afbf1269a3ddcd48ca84ddc0f4cec23a881acfdacb6bbe7ae9e7871d5fa database/seeders/data/gis-astana/blobs/365fd90c79fc111885b1645d0af89c1300115f888b7ef2f07b12e80160ec5a2d database/seeders/data/gis-astana/blobs/383154b1d50ceb5292ea921609a58873d5752c2310ba805ddcb737d838e4ad3f database/seeders/data/gis-astana/blobs/3cf950fa4b1879f22016e508b49b5b3f553d3167e1a98040e6ac30749b491293 database/seeders/data/gis-astana/blobs/4551fcb51711f6896d3836b4e5a907ca8d447c3401aa90b1649cb291eace19fa database/seeders/data/gis-astana/blobs/4915fbdbc574e76c48a8ca71c68595abe0dbfcd6c040b48353c6fdc9fbf10cd8 database/seeders/data/gis-astana/blobs/4e188fd1edec36b3e0b6377e70e6838ce5ef85e3b3d642e8a32ce05d6d714aa9 database/seeders/data/gis-astana/blobs/50128847f9adf7bc1f4d5471add680b871aeca68245436be7962cbb77726dec2 database/seeders/data/gis-astana/blobs/5086c6d8e19ef06dd0aeebcb796e6f9cc0136f381e1d880be86b2651501aa58c database/seeders/data/gis-astana/blobs/52e667c9712733340ac3091f0805970ea6357ae3c6906c0c35691733626f8bc7 database/seeders/data/gis-astana/blobs/5567e9952ebce55929256902c968d49e846ce0a8c111a89d17aba918ca9539d8 database/seeders/data/gis-astana/blobs/55fa768e149794b1ebb24973313a728ff5e2488fac073cff4c142346cf049701 database/seeders/data/gis-astana/blobs/56dbe48873f748bb2a030ccd2adcb2789f8df4cc081f29d089fffadc03b66983 database/seeders/data/gis-astana/blobs/57b7c3a96ca44d76838f654fb51680848609c2160fd80b3259b6380f7170522e database/seeders/data/gis-astana/blobs/58590fa67b64ec3522a4182c3598c0bee528fdef2a45d3891a71364925426ce3 database/seeders/data/gis-astana/blobs/58de8b31e272aa5f3f3d1ff4593ed7a99f88046eaa3c9358efc29de262c1b4a6 database/seeders/data/gis-astana/blobs/591ae9d3c94510388d6014c59faa58e15328bccacdd1f4e73afba156f36584ef database/seeders/data/gis-astana/blobs/5db719aa4a1eb6ee0f7fbb3f4d00cd31bcd1d840edb29e4ebe0a3f4e191b085a database/seeders/data/gis-astana/blobs/5ec0360f1f08dadde67f20f104fa052d212dae12e23de43bfc8611ab152f3717 database/seeders/data/gis-astana/blobs/5eee5a57449ecd81db09a14775b71f9b87e5a3e08fa0019bb889c3b933706f78 database/seeders/data/gis-astana/blobs/5f356aff603872e284d7b223ac350232c6a4fd108e2e7cd6c45d5c58337c7ac7 database/seeders/data/gis-astana/blobs/5fb71e747ce3cb3a63ffff8830074910ca1a58a20dc57fd19742dc8d44f6adc8 database/seeders/data/gis-astana/blobs/6355982ee6e7945f8621247f39460e7dd6188932981db8d68ada7e21520ae9a6 database/seeders/data/gis-astana/blobs/658fed1577c7d54289639b4afd389ce15852150fac869e7d044a3c2f01b97736 database/seeders/data/gis-astana/blobs/67605bf5121defacb759a71e8807d64d2081fe581381043d3fe50918bb9149c1 database/seeders/data/gis-astana/blobs/68abc7e3f282ad7f63dd60d8bb93d64f0c5deea4ee58f31dbd4f6805c7499164 database/seeders/data/gis-astana/blobs/6afa50816181b95f48595720f0e7c8aa87dc8908ee9bacd387eecc1e469a875e database/seeders/data/gis-astana/blobs/6b886607ede365dfa07dec594105e8cbb82c50393ae46a1b446e95489e3ab1aa database/seeders/data/gis-astana/blobs/734c0ad28cbadd478dcd327811fe38f0ada60a98f7967838eb8f2519a6136c7f database/seeders/data/gis-astana/blobs/73779deaad683a9883046135a51148bd3dbcabbd939c27273f0b6336eefd7138 database/seeders/data/gis-astana/blobs/73b7ff7fbf30e4c8ef9c6c5bc4745d7e806b53e1ba5a10ba80bd19a0ea8c63e4 database/seeders/data/gis-astana/blobs/73f30761907dab5c49f821c8792c279d44de3750c27026b67210a2fbd9cf5fed database/seeders/data/gis-astana/blobs/745eccf33d33843965bd2bbfc9e9499004cad9224f9515240f57f97d6359a13c database/seeders/data/gis-astana/blobs/755641451742889fc360fc2bae9a79bed34073b79c70044164821eb1d4695d82 database/seeders/data/gis-astana/blobs/75d6792aa413ee18374fce9ffc092adfe44964e0a4e8f3b28118e4436eaf8c4e database/seeders/data/gis-astana/blobs/76bbeaed82b7bf6c101ffc5e7ce1c3b1049d5e9dbc81ac49d3d6f0612f29be3d database/seeders/data/gis-astana/blobs/77cdf91fc0259f666d9906badc7d5f08066b64b95422288eb3a005b122c983cc database/seeders/data/gis-astana/blobs/7fdab75f4e0c5f6cf1930a745c30efdb804899fc7a2a3dfe62b17e437ef4f451 database/seeders/data/gis-astana/blobs/8044668d7825d7835ca2769dadd5d504fb96390244137435a7b7c9863988524e database/seeders/data/gis-astana/blobs/80f799e24d894aefae01990315b73bb0dfe9096948ce8dc6022c5b3461ae37d0 database/seeders/data/gis-astana/blobs/82e889514328832a0fe813006dea9f84c48f23f3fdea02df86863f1bf03e21aa database/seeders/data/gis-astana/blobs/830e7b3f508d5ef3069d46c84c7dbbe5ab20318e64f931c85ae145d7904e34f0 database/seeders/data/gis-astana/blobs/88ac04d7a37e78ed627c636f86d3af6c99377151bad11142d11caebb739541ff database/seeders/data/gis-astana/blobs/89dc187faa10c9ae8ee1b00713afc62d20f0ba5ac5028bd6fb2a236e76bc3ef5 database/seeders/data/gis-astana/blobs/8b53d926b6a4691aeede826406b841c1be3dd88f024b949a7f9f490126aabed3 database/seeders/data/gis-astana/blobs/8b5c4e16c99ba200060b1ca4975299dc686cdc9e194df78104f2cc31c46e1a0e database/seeders/data/gis-astana/blobs/8c12b2e3ba3cbe21a6c8313bb438b2d2397e09a41dc7858218b309739f9e8743 database/seeders/data/gis-astana/blobs/8cfe82283229a9102da64f78bb5cd77bee24a05c39a2d5d49ea3f48da1c783d8 database/seeders/data/gis-astana/blobs/8d210c6a65bf4b89007423b02a2c6abf8f48d58cab51023e3b8ab92f731746a0 database/seeders/data/gis-astana/blobs/8d77bb0e4ff39f0f17878f6a1a0ee929b10245b94b7a6af19b4f43ce94989e8f database/seeders/data/gis-astana/blobs/8e1d675282209e6f2176bfb241c9273545ee1584c9fbdb2cdddca1ed28f225f0 database/seeders/data/gis-astana/blobs/8ee8d54097f3fae20083bf332d0681f395588a9c30243e29e76cb9a39142072f database/seeders/data/gis-astana/blobs/908cd463355055899a95a7cafeb01a4898d3b9848012d38548caab890b646b76 database/seeders/data/gis-astana/blobs/90eacc1d9ea9aa083c75320e82e2482a6fd280e9adb0fea8bccec4b6f42275bb database/seeders/data/gis-astana/blobs/93ca94d2c834dd9fbf2a78c42665d60fe39bd9998b0c77094f4bb84541ca728e database/seeders/data/gis-astana/blobs/93eb0b0ab8c7e9b576809afdf1bccb046801adb008826eacc97332489419d7a9 database/seeders/data/gis-astana/blobs/944cd933c3100a9219f094ec744fd8912c0a472fa1e6f7ac0c76a12abe428b11 database/seeders/data/gis-astana/blobs/944d9032760cb8252a0ccee2962014deddeffe22df9fe42947c12522293502e3 database/seeders/data/gis-astana/blobs/986cab043db78415d063160251aa21901163ff7931b5a8c943cb27d2df1615f3 database/seeders/data/gis-astana/blobs/98e74bc142a50cc64636f1be2d238e6e02c735c6f8c6654b383eee592d3324e9 database/seeders/data/gis-astana/blobs/992993b6e9df00535aea93e3b183d21663e3cc982257c9ad1d755ca041303a4b database/seeders/data/gis-astana/blobs/9a124be20f1245cd41292e763e0c42b9fa0e64e692cac6f3917a8d5818f3ef8f database/seeders/data/gis-astana/blobs/9a377db03c5b128ac3ece3c73839b0789fea95c22ebbab6c345ea4eaa7627fa1 database/seeders/data/gis-astana/blobs/9c2ccefac2b012a73daf3d825d8c618bfcb989e2f30d0afd5cc9dc7b03a7e3cf database/seeders/data/gis-astana/blobs/9cd9c6ceb98bce70174f2f1adc48505578271d058e23f9c04c2178ffd3ba0afb database/seeders/data/gis-astana/blobs/9ddddc5410fc900a7ccd07fbf97ae78c40aec354ed18f515deb594fa11574c74 database/seeders/data/gis-astana/blobs/9f516f14a3ce112848ca537f340c13b046ecbe9242671bc6b77caf64666feda7 database/seeders/data/gis-astana/blobs/a26ba43100858c7d84410dbd3411c49604dd4a3a4c2d791a9deee831b3449da5 database/seeders/data/gis-astana/blobs/a39465f3ec4c07c28419ca6e4d11a1ec73573f4139d2b1623f8ed9ee440818d2 database/seeders/data/gis-astana/blobs/a3db5ea26dda178d7ae331ea00bdcddbe2e16c692a62f7e50e7b36e0e98836e4 database/seeders/data/gis-astana/blobs/aa534777740f7f29eac51ad90eceee25bb5f433acd5c298801da442a6aa15362 database/seeders/data/gis-astana/blobs/af0fa943989095891efd96344cdf81b4fb75e88aaca0e5ba25b6e989dc3a6c82 database/seeders/data/gis-astana/blobs/af26291f005abe8654722e6d22e6207722973313b62f73edbc350a16b4aa8b93 database/seeders/data/gis-astana/blobs/af313b86dde04fe2e2fddbf3e1fdd5512d9c5ac559c9afde5ab050a046ec3d39 database/seeders/data/gis-astana/blobs/b21b7a6c9be6a657174b793aa12887cd29628eae126b6bfc0c32e99c4b84055e database/seeders/data/gis-astana/blobs/b7da1c4a266e579c6587ead8f6b4d9261a1f2d5b9a7c8691e8da487e814d2a59 database/seeders/data/gis-astana/blobs/b9905a617b90697d3a61d78ae9d38b693476a709f605e71a95f2484bc27189ac database/seeders/data/gis-astana/blobs/bac960c7ce78288e36e58912838f6451c7edadc216e3252f6fa01e26d82e5c74 database/seeders/data/gis-astana/blobs/bcc1f9973333f3ea9ac87c455650513b58020b97e79b0fa81b40914be5aacea3 database/seeders/data/gis-astana/blobs/c01a1cbd45d7b1c76fec23308710a70f2a7edcc6bddc8d1056c07a22bdfedbcc database/seeders/data/gis-astana/blobs/c0a2d34e15ae44346b989c732e558a8296e905254c2581a46d9219be2996dc0a database/seeders/data/gis-astana/blobs/c1a92ee3c20379c7e35b466962e8a661f7c5df2cb6dfc0ca90876125a32cff95 database/seeders/data/gis-astana/blobs/c21971f2fb968be0d6f870563577a965b0a683d9ceae0b9cc974e895be138345 database/seeders/data/gis-astana/blobs/c2d43e6da0eae18dfdbd3b588f861d111543bedaecfcb4a62e51774b88bf62ee database/seeders/data/gis-astana/blobs/c40aa8cfa399506a59640a9a7ae5e46c4f74f77012686afae785bf3dad2e9063 database/seeders/data/gis-astana/blobs/c525eacdf3eef54a02c04eaad4c64a0fb84880edd249526cce225c5259735dd5 database/seeders/data/gis-astana/blobs/ca01869793c07950c8bbdca4ef370ab0b79fc198453e53bc94f6432c84a0cd95 database/seeders/data/gis-astana/blobs/d364e98f3abb95735aafb2fbd8a3ede2c8c7a481caf7c7003f298e37f2b7163d database/seeders/data/gis-astana/blobs/d472489ea5ae48c1afb19e69684dab8f18d97e939303dc30b324ea13b2a731cf database/seeders/data/gis-astana/blobs/d4c387d4d387b3d90afc1e8588688be76fc96a3e3882c865b2d795e8879bede8 database/seeders/data/gis-astana/blobs/d605803f2ef1a5c9ae99d928e3776d832ed638f756c9c42b31bebaab4127efef database/seeders/data/gis-astana/blobs/d623485cbc78ce861248a4849e0e27747582234d4042e68f172c26c4f471b2a1 database/seeders/data/gis-astana/blobs/d7fd5a81fe41e684679103b80dbe2917e636af72c1d0c77c8e442ab9a9b58fd3 database/seeders/data/gis-astana/blobs/d8a991945c87d5c014230fb9bb6cd6782732ab8b82618361c5dad0902f9a8a2b database/seeders/data/gis-astana/blobs/d9ccddad817cefa6e6c9c70442eeb732603de9d501b8004d97e35e2d00b1e3d7 database/seeders/data/gis-astana/blobs/da00926808656131c11259435899abc805b8f498cd70ac179da22ae8b83ee620 database/seeders/data/gis-astana/blobs/dac2fbc2e6965e4f51857f4c32dbef30fc5f6f9dd42332e1c283e6e4511308d7 database/seeders/data/gis-astana/blobs/df0940d57be81b3e3d94aeef58ce11b403ca3ad80c1dd4e74553e1737b15001c database/seeders/data/gis-astana/blobs/e25cd2dbb25638fea1ba3a629e34d13ada4065f3c5858d3f5be215b57eb65a81 database/seeders/data/gis-astana/blobs/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 database/seeders/data/gis-astana/blobs/e3cda9b89cec0ead8be872e4d49e895bc4b3e47ee5f57a5e40e5277a040f53d3 database/seeders/data/gis-astana/blobs/e4466a33124b6b7c0caa2fccccae04c6b3c2ebe796a9893d606db7760df66b90 database/seeders/data/gis-astana/blobs/e55ff350bd8376fe5ba9e8696f60d028ecea3cabb8ca47c7208494ad68a3b349 database/seeders/data/gis-astana/blobs/e5c81d6f7cb7cd6eace270e19c4ec4ce5521eaee8a48deaff91fbdf13206adb2 database/seeders/data/gis-astana/blobs/e5f1420396691d97ae57aa7de2be75da65cce5a0eef40b1f753881ed80742169 database/seeders/data/gis-astana/blobs/e90c54cfc2408412a8a58395905f84421c73c745b9f94acc1ffd6ec824d6c162 database/seeders/data/gis-astana/blobs/e97fdf208c671d7c749c0e856aa994fbe70aa76d4757137fccc7c39df500cac5 database/seeders/data/gis-astana/blobs/eb00b0497899fb6753c674912922b52255b82ee6a7f78d59dd23b3ab69e66475 database/seeders/data/gis-astana/blobs/eea3ae85c8786229d2dba8b885b224b8bf8fb9d507365151c97e4a2c825453c2 database/seeders/data/gis-astana/blobs/f399d7c8bbe7b8f5485fd33d2732b7344fbd9d9c34541e8afe5ef847741d8fb0 database/seeders/data/gis-astana/blobs/f49d84a361596a70e834861c595863c1ed78f861a27a185979512de714cb8998 database/seeders/data/gis-astana/blobs/f6afe7b3e78489c60685b2a4b5c054e09973d80dc4f679b3a80bc1e440a2b137 database/seeders/data/gis-astana/blobs/f7c6f4371aa0531e880cbdd62bfe59f7d45d2a31e372668cd58e26830feed276 database/seeders/data/gis-astana/blobs/f91e377c391153043d7a56987a3628e235b1a5c36f31512646ad24d803501aca database/seeders/data/gis-astana/blobs/fa8ca0a7b4d864b80170c1af3b6239443fa9e6758e268d1a5a4ce320690a741f database/seeders/data/gis-astana/blobs/fb078a6035af65de229f974ca158b62d762d15a3c5f87bada52528ca92bb1bd6 database/seeders/data/gis-astana/blobs/fe871fcb85fd3c8a17281d646a304374486f1820971f3edbfe4cb09feb410d0b database/seeders/data/gis-astana/data/gis_assets-0.ndjson.gz database/seeders/data/gis-astana/data/gis_feature_contents-0.ndjson.gz database/seeders/data/gis-astana/data/gis_feature_contents-1.ndjson.gz database/seeders/data/gis-astana/data/gis_feature_contents-2.ndjson.gz database/seeders/data/gis-astana/data/gis_feature_contents-3.ndjson.gz database/seeders/data/gis-astana/data/gis_feature_contents-4.ndjson.gz database/seeders/data/gis-astana/data/gis_feature_contents-5.ndjson.gz database/seeders/data/gis-astana/data/gis_feature_contents-6.ndjson.gz database/seeders/data/gis-astana/data/gis_imports-0.ndjson.gz database/seeders/data/gis-astana/data/gis_layer_versions-0.ndjson.gz database/seeders/data/gis-astana/data/gis_layers-0.ndjson.gz database/seeders/data/gis-astana/data/gis_version_assets-0.ndjson.gz database/seeders/data/gis-astana/data/gis_version_features-0.ndjson.gz database/seeders/data/gis-astana/manifest.json docs/architecture.md docs/development.md docs/evaluation.md package-lock.json package.json phpstan.neon phpunit.xml pint.json pnpm-workspace.yaml public/.htaccess public/apple-touch-icon.png public/favicon.ico public/favicon.svg public/index.php public/robots.txt resources/css/app.css resources/js/app.tsx resources/js/components/alert-error.tsx resources/js/components/app-content.tsx resources/js/components/app-header.tsx resources/js/components/app-logo-icon.tsx resources/js/components/app-logo.tsx resources/js/components/app-shell.tsx resources/js/components/app-sidebar-header.tsx resources/js/components/app-sidebar.tsx resources/js/components/breadcrumbs.tsx resources/js/components/delete-user.tsx resources/js/components/heading.tsx resources/js/components/input-error.tsx resources/js/components/manage-two-factor.tsx resources/js/components/nav-footer.tsx resources/js/components/nav-main.tsx resources/js/components/nav-user.tsx resources/js/components/password-input.tsx resources/js/components/simulation/results.tsx resources/js/components/simulation/scenario-assistant.tsx resources/js/components/simulator/assistant-panel.tsx resources/js/components/simulator/decisions-editor.tsx resources/js/components/simulator/district-map.tsx resources/js/components/simulator/gis-map.tsx resources/js/components/simulator/simulator-header.tsx resources/js/components/text-link.tsx resources/js/components/two-factor-recovery-codes.tsx resources/js/components/two-factor-setup-modal.tsx resources/js/components/ui/alert.tsx resources/js/components/ui/avatar.tsx resources/js/components/ui/badge.tsx resources/js/components/ui/breadcrumb.tsx resources/js/components/ui/button.tsx resources/js/components/ui/card.tsx resources/js/components/ui/checkbox.tsx resources/js/components/ui/collapsible.tsx resources/js/components/ui/dialog.tsx resources/js/components/ui/dropdown-menu.tsx resources/js/components/ui/icon.tsx resources/js/components/ui/input-otp.tsx resources/js/components/ui/input.tsx resources/js/components/ui/label.tsx resources/js/components/ui/navigation-menu.tsx resources/js/components/ui/placeholder-pattern.tsx resources/js/components/ui/select.tsx resources/js/components/ui/separator.tsx resources/js/components/ui/sheet.tsx resources/js/components/ui/sidebar.tsx resources/js/components/ui/skeleton.tsx resources/js/components/ui/sonner.tsx resources/js/components/ui/spinner.tsx resources/js/components/ui/toggle-group.tsx resources/js/components/ui/toggle.tsx resources/js/components/ui/tooltip.tsx resources/js/components/user-info.tsx resources/js/components/user-menu-content.tsx resources/js/hooks/use-clipboard.ts resources/js/hooks/use-current-url.ts resources/js/hooks/use-flash-toast.ts resources/js/hooks/use-initials.tsx resources/js/hooks/use-mobile-navigation.ts resources/js/hooks/use-mobile.tsx resources/js/hooks/use-permissions.ts resources/js/hooks/use-two-factor-auth.ts resources/js/layouts/app-layout.tsx resources/js/layouts/app/app-header-layout.tsx resources/js/layouts/app/app-sidebar-layout.tsx resources/js/layouts/auth-layout.tsx resources/js/layouts/auth/auth-card-layout.tsx resources/js/layouts/auth/auth-simple-layout.tsx resources/js/layouts/auth/auth-split-layout.tsx resources/js/layouts/settings/layout.tsx resources/js/lib/city-simulator.ts resources/js/lib/gis-map-style.ts resources/js/lib/gis-simulator-districts.ts resources/js/lib/utils.ts resources/js/pages/access-denied.tsx resources/js/pages/auth/confirm-password.tsx resources/js/pages/auth/forgot-password.tsx resources/js/pages/auth/login.tsx resources/js/pages/auth/register.tsx resources/js/pages/auth/reset-password.tsx resources/js/pages/auth/two-factor-challenge.tsx resources/js/pages/auth/verify-email.tsx resources/js/pages/scenarios/compare.tsx resources/js/pages/scenarios/create.tsx resources/js/pages/scenarios/index.tsx resources/js/pages/scenarios/show.tsx resources/js/pages/settings/profile.tsx resources/js/pages/settings/security.tsx resources/js/pages/welcome.tsx resources/js/types/agents.ts resources/js/types/auth.ts resources/js/types/gis.ts resources/js/types/global.d.ts resources/js/types/index.ts resources/js/types/navigation.ts resources/js/types/simulation.ts resources/js/types/ui.ts resources/js/types/vite-env.d.ts resources/views/app.blade.php resources/views/filament/auth/demo-credentials.blade.php routes/console.php routes/gis.php routes/settings.php routes/web.php 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 stubs/agent-middleware.stub stubs/agent.stub stubs/structured-agent.stub stubs/tool.stub tests/Feature/Admin/AccessManagementTest.php tests/Feature/Admin/CityRolesTest.php tests/Feature/Admin/SuperAdminAccessTest.php tests/Feature/AgentRuntimeConfigurationTest.php tests/Feature/Agents/AgentRuntimeTest.php tests/Feature/Auth/AuthenticationTest.php tests/Feature/Auth/DemoAdminTest.php tests/Feature/Auth/DemoUsersTest.php tests/Feature/Auth/EmailVerificationTest.php tests/Feature/Auth/PasswordConfirmationTest.php tests/Feature/Auth/PasswordResetTest.php tests/Feature/Auth/RegistrationTest.php tests/Feature/Auth/TwoFactorChallengeTest.php tests/Feature/Auth/VerificationNotificationTest.php tests/Feature/Authorization/WorkspacePermissionsTest.php tests/Feature/DashboardTest.php tests/Feature/ExampleTest.php tests/Feature/GisArchiveTest.php tests/Feature/GisDiscoveryTest.php tests/Feature/GisRasterTest.php tests/Feature/GisSeedTest.php tests/Feature/GisVectorTileTest.php tests/Feature/LightThemeTest.php tests/Feature/MapTest.php tests/Feature/ScenarioAiTest.php tests/Feature/ScenarioDemoChatTest.php tests/Feature/Settings/ProfileUpdateTest.php tests/Feature/Settings/SecurityTest.php tests/Feature/SimulationScenarioTest.php tests/Frontend/city-simulator.test.mjs tests/Frontend/gis-simulator-districts.test.mjs tests/TestCase.php tests/Unit/.gitkeep tests/Unit/SimulationCalculationTest.php tsconfig.json vite.config.ts
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.