AAYMA
RU
Войти

Граф денег

AML-система: по трём Parquet-файлам строит граф транзакций, определяет роли, сообщества и приоритеты узлов.

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

О проекте

Команда: Tovarish.Sanechka
Кейс HackAlem.ai: Финансы — Freedom
Стадия: Доведённый продукт

Задача кейса: «Граф денег»: восстановить структуру организованной группы по сети транзакций (AML)

Суть

AML-система: по трём Parquet-файлам строит граф транзакций, определяет роли, сообщества и приоритеты узлов. Интерфейс на React/Cytoscape: маршруты, проверка хронологии, досье, AI-ассистент.

Как устроено

Python-пакет (starter.py и scoring.py) валидирует Parquet и строит DiGraph. Считаются потоки, достижимость от seed, дневные признаки, PageRank и betweenness, Louvain на ненаправленной проекции. Роли назначаются правилами с порогами из config.toml, приоритет независим от роли: 35% охват seed, 40% структура, 25% оборот. Дополнительно строятся кратчайшие пути, сценарии устойчивости (исключение top-N) и чувствительность ролей при порогах ±10%. Результат экспортируется в 3 CSV и analysis.json. React-клиент ищет общих участников и проверяет хронологию дат по путям. Ассистент через Alem GPT OSS только переводит вопрос в 1–3 разрешённые операции.

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

  • NetworkX
  • Louvain
  • PageRank
  • betweenness
  • reachability
  • shortest paths
  • temporal path validation
  • sensitivity analysis
  • rule-based roles
  • intent parsing LLM

Особенности

Хронология путей проверяется: сначала ищется строго возрастающая последовательность дат, потом неубывающая, с поиском альтернативного маршрута при конфликте. Healthcheck сверяет SHA-256 опубликованных файлов. LLM не считает факты, только выбирает разрешённую команду. CSV побайтово воспроизводимы.

Стек

Python 3.12 · pandas · PyArrow · NetworkX · SciPy · React 19 · TypeScript · Vite · Cytoscape.js · Docker Compose · uv · pytest · Playwright

Модели

GPT OSS via Alem


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

README

README.md

Граф денег · HackAlem

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

«Граф денег» — локальная система анализа транзакционной сети, которая помогает AML-аналитику определить, каких участников проверять первыми и почему. Она преобразует три Parquet-файла в направленный граф, рассчитывает признаки, гипотезы ролей, сообщества и приоритеты, затем публикует согласованные CSV-выгрузки и данные для браузера. Решение рассчитано на пакетную обработку обезличенной выборки: 2 248 узлов, 3 119 связей и 4 840 операций за июль 2026.

Роли — проверяемые гипотезы. Баллы не являются вероятностью нарушения или доказательством виновности.

Быстрый запуск из корня репозитория: docker compose up -d --build --wait --wait-timeout 360, затем открыть http://localhost:8080. Для основных функций .env и API-ключ не нужны; первая сборка требует сети. Готовые CSV и схема решения лежат в submission/, сценарий демонстрации — в DEMO.md.

2. Технический стек

КатегорияТехнологииОтветственность
CorePython 3.12.13; React 19.3, TypeScript 7.0, Vite 8.3Пакетный расчёт, HTTP-сервер с API ассистента, браузерный клиент
DataParquet, pandas 3.0.6, PyArrow 25.0.1, NumPy 2.5.3Валидация, агрегация, признаки и сериализация
Графовая аналитика / AI/MLNetworkX 3.7, SciPy 1.18.1PageRank, betweenness, достижимость, Louvain, объяснимые правила ролей; обучаемых моделей для ролей нет; опциональный GPT OSS через Alem распознаёт вопросы
ВизуализацияCytoscape.js 3.34.3Направленные подграфы и маршруты из результатов расчёта
InfraDocker, Docker Compose, uv 0.11.21Multi-stage build, фиксированное окружение, запуск и healthcheck
Проверкиpytest 9.1.1, Playwright 1.63.0, TypeScriptАналитические инварианты, контракт данных, браузерные сценарии и проверка типов

Python-зависимости зафиксированы в pyproject.toml и uv.lock, frontend — в package.json и package-lock.json. Базовые образы в Dockerfile закреплены версиями и digest. PostgreSQL, Redis и отдельный API-сервис не используются.

3. Архитектура и поток данных

Системная схема

flowchart TB
    INPUT["nodes / edges / transactions.parquet"] --> VALIDATE["Проверка схем и согласованности операций"]
    CONFIG["config.toml: пороги, веса, random_seed"] --> ANALYSIS
    subgraph APP["Docker Compose: сервис app"]
        subgraph ANALYSIS["Python: пакетный расчёт"]
            VALIDATE --> GRAPH["DiGraph: все узлы, включая изоляты"]
            GRAPH --> FEATURES["Потоки, структура, достижимость, дневные признаки"]
            FEATURES --> CLUSTERS["Louvain и признаки соседних сообществ"]
            CLUSTERS --> SCORING["Правила ролей и независимый приоритет"]
            GRAPH --> PATHS["Кратчайшие направленные пути"]
            SCORING --> RESILIENCE["Исключение топ-N и контрольные сценарии"]
            SCORING --> EXPORT["Проверка выходного контракта и запись"]
            PATHS --> EXPORT
            RESILIENCE --> EXPORT
        end
        EXPORT --> FILES["3 CSV + analysis.json v3"]
        FILES --> HTTP["run.py: файлы + API ассистента"]
        ASSETS["React build из Docker build-стадии"] --> HTTP
        HEALTH["healthcheck.py: run_id, SHA-256, схемы"] --> HTTP
    end
    HTTP --> BROWSER["Браузер: роли, маршруты по датам, досье"]
    BROWSER --> QUESTION["Вопрос + идентификаторы контекста"]
    QUESTION --> API["assistant.py: проверка запросов"]
    API --> ALEM["Alem GPT OSS: распознавание намерения"]
    ALEM --> API
    API --> VALID["Проверенный JSON-запрос"]
    VALID --> BROWSER
    SCORING --> SENS["Три сценария порогов"]
    SENS --> EXPORT
    BROWSER --> SEARCH["Общий поиск и проверка дат выбранных путей"]
    BROWSER --> URL["URL: контекст расследования"]
    BROWSER --> LOCAL["localStorage: решения и заметки"]

Границы компонентов

КомпонентЧто делаетПочему отдельно
starter.pyЧитает и проверяет Parquet; строит граф, признаки, сообщества, пути и сценарии устойчивости; формирует результатыЕдиный расчёт для CSV и браузера исключает расхождение ролей и рейтингов
scoring.pyПрименяет правила ролей и нормализует компоненты приоритетаПравила можно проверить по признакам и конфигурации без запуска интерфейса
run.pyЗапускает расчёт; после успешного завершения обслуживает каталог результата, frontend и два endpoint ассистентаHTTP не открывается до проверки данных; Parquet и исходный код не публикуются
assistant.pyЧитает серверные настройки Alem, распознаёт вопрос через GPT OSS и проверяет допустимость командыМодель не вычисляет факты; ключ и полный граф не передаются браузеру и провайдеру соответственно
healthcheck.pyСравнивает локальный и HTTP-манифесты запуска, хеши файлов, схемы и число строкГотовность означает доступность согласованных результатов, а не только открытый порт
web/srcЗагружает и валидирует analysis.json, выполняет интерактивные обходы графа и проверку датРоли и приоритеты не пересчитываются в браузере; запросы аналитика не требуют нового Python-процесса

Входящие и исходящие суммы сохраняют направление переводов. Для Louvain строится отдельная ненаправленная проекция: встречные потоки суммируются, самопереводы исключаются из кластеризации. Изолированные узлы остаются в полном графе и получают собственные кластеры. При фиксированных входных данных и конфигурации повторный расчёт даёт побайтово одинаковые CSV и JSON; идентификатор запуска run_id при этом меняется.

Объяснимая аналитика

Пороговые правила находятся в config.toml; обоснование порогов и формулы — в ANALYTICS.md. Исходный клиент (seed) — один из 81 участников, от которых собиралась выгрузка.

РольУсловия при конфигурации по умолчанию
consolidator≥3 плательщиков; достижимость от ≥2 исходных клиентов; доля крупнейшего плательщика ≤80%
distributor≥5 получателей; доля крупнейшего получателя ≤80%
transitНе исходный клиент; есть плательщики и получатели, отличные от самого узла; суммарные вход и выход ≥164 528 ₸; отношение выхода ко входу 0,7–1,4; доля выхода с поступлением в предшествующие 0–2 дня ≥69%
terminalНе исходный клиент и не обрыв на depth=4 без внешних получателей; есть другой плательщик; суммарный вход ≥164 528 ₸; отношение выхода ко входу ≤10%
coordinatorДостижимость от ≥9 исходных клиентов; ≥2 внешних соседних кластеров; betweenness ≥0,0001553
peripheralОстальные правила не выполнены

Выбирается роль с максимальным допустимым баллом; конкурирующая гипотеза снижает итоговый role_score. При равенстве применяется role_order из конфигурации. Приоритет рассчитывается независимо от выбранной роли: 35% охвата исходных клиентов + 40% структуры + 25% оборота, с логарифмической нормализацией признаков. Каждый вклад сохраняется отдельно, равенства разрешаются по числовому gid.

Браузерный поиск пересекает множества узлов, достижимых от 2–5 выбранных исходных клиентов, и исключает уже известных участников. Для каждого кандидата строятся кратчайшие направленные пути. Проверка дат сначала ищет строго возрастающую последовательность операций, затем неубывающую; результат различает согласованный порядок, неопределённость внутри дня и конфликт дат. Для конфликта или неизвестного порядка внутри дня доступен поиск альтернативы: сначала строго возрастающие даты, затем неубывающие; в каждом режиме выбирается путь с минимумом шагов. Исходный маршрут сохраняется для сравнения.

AI-ассистент через Alem переводит вопросы в одну–три разрешённые операции: карточка узла, общие участники, маршрут, чувствительность роли. Python проверяет команду, браузер выполняет её теми же функциями, что обычный интерфейс. Ответы — карточки с рассчитанными числами и переходами, без свободного пересказа модели. Промпт находится в assistant.py; агентного цикла нет.

Карточка сравнивает роли при шести порогах −10%, базовых и +10%. Приоритет остаётся базовым. «Сформировать досье» открывает документ одного участника: пути и операции, основания и ограничения, три сценария, решение и заметка; печать позволяет сохранить PDF. Все эти функции работают без AI.

Контракт, публикация и хранение

РезультатКонтракт
nodes_roles.csvВсе 2 248 узлов: gid, role, role_score, cluster_id, priority_score, evidence и дополнительные признаки; evidence ≤200 символов
clusters.csvcluster_id, n_nodes, n_seed, sum_kzt_internal, top_gids, hypothesis; на текущих данных 88 кластеров
top_nodes.csvВсе узлы по убыванию приоритета: rank, gid, role, priority_score, why
analysis.jsonschema_version=3; метаданные, конфигурация, узлы с тремя сценариями роли, связи с датами и исходными операциями, кластеры, рейтинг и сценарии связности
ready.jsonМанифест текущего HTTP-запуска: run_id, число узлов и SHA-256 опубликованных файлов

gid передаётся в JSON строкой: 64-битные идентификаторы нельзя безопасно преобразовывать в JavaScript number. В обязательных CSV идентификаторы записаны десятичными целыми; при импорте в электронную таблицу выбирайте текстовый тип столбца. top_gids и seed_path_gids в CSV — JSON-массивы строк; неопределённые дополнительные отношения представлены пустым значением в CSV и null в JSON. Обязательные поля заполнены, скоры в файлах лежат в диапазоне 0–1.

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

В Compose не настроены volumes: /app/out находится в файловом слое контейнера, при пересоздании результаты рассчитываются заново. Контекст расследования хранится в URL, а решения и заметки — в localStorage браузера с привязкой к периоду и gid. Сервер не принимает эти записи; передача решений выполняется CSV-выгрузкой, синхронизации между устройствами нет.

Архитектурные решения — ADR

  1. Пакетный расчёт и статическая публикация. Вход — конечная выгрузка, обновления в реальном времени не требуются. Один процесс расчёта и файловый контракт упрощают воспроизводимость и позволяют обходиться без БД, очередей и отдельного backend-сервиса. Компромисс: новые данные требуют полного пересчёта.
  2. Правила и графовые метрики вместо обученной модели. В датасете нет размеченных ролей. Явные пороги позволяют объяснить каждую гипотезу и проверить чувствительность результата; оценка accuracy без разметки не заявляется.
  3. Вычислительное ядро в Python, интерактивные запросы в браузере. Python формирует единую модель анализа, React работает с её снимком. Основные функции работают локально, внешний API нужен только для распознавания вопросов; компромисс — весь JSON загружается в память клиента и подходит текущему объёму, а не миллиону узлов.

Ограничения и масштабирование

Выборка включает только внутрибанковские операции ≥5 000 ₸ за июль 2026 и четыре шага исходящего обхода. Входящие исходных клиентов неполны; дальнейшие переводы 444 граничных узлов неизвестны. Поэтому отсутствие исходящих не используется как достаточное основание для terminal на границе. Достижимость и согласованные даты не доказывают движение одной суммы; оборот повторно учитывает деньги вдоль цепочек. Проверка устойчивости моделирует связность наблюдаемого графа, а не эффект реального блокирования счетов.

При росте до ~1 млн узлов потребуется заменить полный граф NetworkX и точную betweenness компактным графовым представлением и приближёнными метриками, выполнять агрегации пакетно, а подграфы и списки выдавать порционно через API. Браузеру следует передавать выбранную область сети вместо полного JSON. Эти изменения описывают направление развития и не входят в текущую реализацию.

Описание распределений — DATA_PROFILE.md, результаты проверок — VERIFICATION.md, навигация по документации — docs/README.md.

4. Установка, запуск и проверка

Docker Compose

Нужны Docker Engine с Compose и браузер. Команды выполняются из корня репозитория. Конфигурация находится в compose.yaml; в ней один сервис app. Файла docker-compose.yml и сервиса базы данных нет. Используется CLI docker compose.

  1. Проверьте конфигурацию. Аналитические параметры задаются в config.toml, исходные файлы лежат в case/data/. Для основных функций .env не нужен. Для AI задайте три переменные Alem, описанные ниже; Compose передаёт их только серверному процессу.

    docker compose config --quiet
    
  2. Соберите и запустите приложение. Docker собирает frontend, устанавливает Python-зависимости и запускает расчёт автоматически.

    docker compose up -d --build --wait --wait-timeout 360
    

    --wait ожидает готовности сервиса; параметры описаны в официальной документации Compose. Первая сборка требует доступа к реестрам образов и пакетов. После сборки основные функции работают без интернета; AI требует доступа к Alem; лимит ТЗ в пять минут относится к пересчёту данных, а не установке зависимостей.

  3. Проверьте статус и откройте приложение.

    docker compose ps
    docker compose exec -T app python healthcheck.py
    

    Адрес: http://localhost:8080. Контейнер слушает 0.0.0.0:8080, на хосте опубликован только 127.0.0.1:8080. Процесс работает от пользователя app с UID 10001. Приложение предназначено для локального использования: аутентификация и TLS не реализованы.

Для просмотра логов и остановки:

docker compose logs -f app
docker compose down

Если 8080 занят, замените публикацию в compose.yaml на 127.0.0.1:8081:8080 и откройте http://localhost:8081. После изменения Parquet или config.toml повторите команду запуска с --build: данные и конфигурация копируются в образ. Обычный restart пересчитывает данные, уже находящиеся в образе.

Настройка AI-ассистента

AI включается только при непустых всех трёх настройках ниже. Если .env отсутствует и переменные не заданы в окружении либо не хватает хотя бы одной настройки, расчёт и интерфейс запускаются как обычно. В панели ассистента появляется «AI не настроен. Основные функции доступны», отправка вопроса отключена. Роли, граф, общий поиск, маршруты по датам, досье и CSV доступны без AI.

В корневом .env или окружении серверного процесса задайте:

ALEM_API_KEY=ваш_ключ
ALEM_CHAT_URL=https://llm.alem.ai/v1/chat/completions
ALEM_MODEL=gpt-oss

Используйте полный рабочий URL из вашего сервиса Alem: инструкция указывает /v1/chat/completions, а примеры — /chat/completions. Приложение отправляет запрос ровно по ALEM_CHAT_URL, без автоматического переключения. Существующий .env не перезаписывайте.

При нативном запуске окружение процесса имеет приоритет над .env, в том числе пустое значение. Для запуска без AI задайте ALEM_API_KEY=. После изменения настроек перезапустите процесс; для Compose выполните docker compose up -d --force-recreate --wait.

Ключ остаётся на сервере; .env исключён из Git и Docker image. Провайдер получает вопрос, выбранный gid, до пяти исходных gid и до шести предыдущих вопросов. Полный граф, транзакции и заметки не отправляются. История сохраняется только в памяти вкладки. Отмена прекращает ожидание браузера; уже отправленный запрос провайдеру может завершиться до серверного тайм-аута.

Без настройки, сети или при ошибке Alem интерфейс показывает причину; ручной поиск, сценарии порогов и досье остаются доступны. Контракт и ограничения — ASSISTANT.md.

Проверить состояние без вывода ключа: открыть локальный статус ассистента. enabled=true подтверждает только наличие настроек; доступность Alem и действительность ключа проверяются при отправке вопроса. Ошибки чтения .env и проверки URL, обработанные приложением, отключают только AI. Ошибка синтаксиса .env на этапе чтения самим Compose может помешать запуску контейнера.

Сохранение CSV

В submission/ уже сохранены три CSV, рассчитанные на исходных данных с текущим config.toml, а также схема решения. Запуск пересчитывает файлы в /app/out контейнера или нативном out/; каталог submission/ автоматически не обновляется. После изменения данных или порогов используйте новые выгрузки.

Для сохранения результатов до удаления контейнера:

mkdir -p exports
docker compose cp app:/app/out/nodes_roles.csv ./exports/nodes_roles.csv
docker compose cp app:/app/out/clusters.csv ./exports/clusters.csv
docker compose cp app:/app/out/top_nodes.csv ./exports/top_nodes.csv

Разработка без Docker

Для проверенного окружения: Python 3.12.13, Node.js 24.20.0 и uv 0.11.21. Команды также выполняются из корня репозитория; нативный запуск использует POSIX-блокировку fcntl, на Windows используйте Docker или WSL.

uv sync --locked
npm --prefix web ci
npm --prefix web run build
uv run python run.py --data case/data --out out --serve

Без --serve выполняется только расчёт, сборка frontend не требуется. Параметры run.py:

ПараметрЗначение по умолчаниюНазначение
--data<корень проекта>/case/dataТри входных Parquet-файла
--out<корень проекта>/outКаталог публикации
--config<корень проекта>/config.tomlПороги и веса
--ui<корень проекта>/web/distСобранный frontend
--serveВыключенПосле расчёта запустить HTTP-сервер; без флага процесс завершится после экспорта
--host127.0.0.1Адрес HTTP при нативном запуске
--port8080Порт HTTP

Каталог --out нельзя пересчитывать, пока его обслуживает другой процесс. Для отдельного пробного расчёта выберите другой каталог через --out.

Проверки

uv run pytest -q
npm --prefix web run build
cd web
npx playwright install chromium
npm run test:e2e

Перед E2E запустите приложение отдельно на http://127.0.0.1:8080. При необходимости задайте переменные только для тестового процесса:

ПеременнаяЗначение по умолчаниюНазначение
APP_URLhttp://127.0.0.1:8080Адрес приложения для Playwright
CHROMIUM_PATHНе заданоПри отсутствии используется браузер Playwright; иначе путь к установленному Chromium
APP_OUTPUT/app/outКаталог манифеста только для healthcheck.py; не меняет каталог расчёта

Проверено: 70 Python-тестов, 27 Playwright-сценариев, TypeScript/build и Docker healthcheck. Полный расчёт в контейнере — 6,506 с. Условия и ограничения проверки зафиксированы в VERIFICATION.md.

Звёзды
⭐ 0
Форки
0
Язык
TypeScript
Последний push
в прошлом месяце
Коммиты
30
Авторы
1
Файлы
69
Ветки
1

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

hhhhhffd 30

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

  • 2026-09-23 17:34Present documentation as completed projecthhhhhffd
  • 2026-09-23 17:33Clarify submission docs, analytics and operation without AIhhhhhffd
  • 2026-09-23 17:15Document investigation workflow, Alem setup and verified demohhhhhffd
  • 2026-09-23 17:13Keep base application available with invalid AI settingshhhhhffd
  • 2026-09-23 17:12Complete temporal investigation, dossier and assistant workspacehhhhhffd
  • 2026-09-23 17:04Add validated Alem query interpretation APIhhhhhffd
  • 2026-09-23 16:56Add role sensitivity scenarios and transaction evidence schemahhhhhffd
  • 2026-09-23 16:42Add automated reviewer prompts in source commentshhhhhffd
Все коммиты (30)
  • 2026-09-23 16:35Refresh architecture documentation and archive obsolete planshhhhhffd
  • 2026-09-23 16:28Complete analyst workflow and resolve interface review findingshhhhhffd
  • 2026-09-23 15:58Record chronology and consolidation release verificationhhhhhffd
  • 2026-09-23 15:56Add investigation view for new consolidation candidateshhhhhffd
  • 2026-09-23 15:51Validate transaction chronology in observed pathshhhhhffd
  • 2026-09-23 15:37Record verification of updated local servicehhhhhffd
  • 2026-09-23 15:35Add common-seed investigation to analyst UIhhhhhffd
  • 2026-09-23 15:11Lead demo with discovered non-seed priority nodehhhhhffd
  • 2026-09-23 15:03Prepare competition submission artifacts and verified demohhhhhffd
  • 2026-09-23 14:53Show seed paths and resilience in analyst UIhhhhhffd
  • 2026-09-23 14:44Model observed network resilience with controlshhhhhffd
  • 2026-09-23 14:43Explain cluster hypotheses with observed flowshhhhhffd
  • 2026-09-23 14:39Add reproducible seed paths and follow-up checkshhhhhffd
  • 2026-09-23 14:16Deliver automatic Docker Compose runtime and verified demo documentationhhhhhffd
  • 2026-09-23 14:07Build interactive graph analysis interface with browser coveragehhhhhffd
  • 2026-09-23 13:58Implement explainable roles priorities and validated analysis exportshhhhhffd
  • 2026-09-23 13:52Compute seed reachability daily flow features and stable communitieshhhhhffd
  • 2026-09-23 13:50Validate transaction data and preserve isolated graph nodeshhhhhffd
  • 2026-09-23 13:45micro pravkahhhhhffd
  • 2026-09-23 13:44Require Docker Compose delivery and add coding agent prompthhhhhffd
  • 2026-09-23 13:40Document technical stack and implementation handoffhhhhhffd
  • 2026-09-23 13:36Add case materials and initial implementation planhhhhhffd
Структура репозитория (69 файлов)
.dockerignore
.gitignore
Dockerfile
README.md
assistant.py
case/HackAlem AI_ Граф денег_ восстановление финансовой структуры организованной группы по транзакционной сети.pdf
case/README.md
case/data/edges.parquet
case/data/nodes.parquet
case/data/transactions.parquet
case/starter/README.md
case/starter/requirements.txt
case/starter/scoring.py
case/starter/starter.py
compose.yaml
config.toml
docs/ANALYTICS.md
docs/ASSISTANT.md
docs/DATA_PROFILE.md
docs/DEMO.md
docs/README.md
docs/VERIFICATION.md
docs/archive/CODER_PROMPT.md
docs/archive/PLAN.md
docs/archive/README.md
docs/archive/STARTER_README.md
docs/archive/TECH_HANDOFF.md
docs/archive/VERIFICATION_HISTORY.md
docs/frontend/DESIGN.md
docs/frontend/UX_FIXES.md
healthcheck.py
pyproject.toml
run.py
submission/clusters.csv
submission/nodes_roles.csv
submission/overview.svg
submission/top_nodes.csv
tests/test_assistant.py
tests/test_scoring.py
tests/test_starter.py
uv.lock
web/e2e/app.spec.ts
web/e2e/assistant.spec.ts
web/e2e/chronology.spec.ts
web/e2e/consolidation.spec.ts
web/e2e/dossier.spec.ts
web/e2e/temporal.spec.ts
web/e2e/workspace.spec.ts
web/index.html
web/package-lock.json
web/package.json
web/playwright.config.ts
web/src/App.tsx
web/src/Assistant.tsx
web/src/ConvergenceSearch.tsx
web/src/Dossier.tsx
web/src/GraphView.tsx
web/src/Pagination.tsx
web/src/PathChronology.tsx
web/src/RoleRules.tsx
web/src/Sensitivity.tsx
web/src/TemporalRoute.tsx
web/src/graphQueries.ts
web/src/main.tsx
web/src/style.css
web/src/types.ts
web/src/vite-env.d.ts
web/src/workspace.ts
web/tsconfig.json

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

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

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