О проекте
Команда: STNDZ MAIN
Кейс HackAlem.ai: Финансы — Freedom
Стадия: Доведённый продукт
Задача кейса: «Граф денег»: восстановить структуру организованной группы по сети транзакций (AML)
Суть
AML-инструмент: по сети переводов из 2 248 узлов рассчитывает признаки, назначает объяснимые роли, выделяет сообщества и формирует топ-30 для проверки, с веб-интерфейсом графа и AI-копилотом.
Как устроено
run_pipeline.py сверяет рёбра с транзакциями и считает признаки узлов: степени, суммы, pass_through, ext_inflow, seed_reach2, взвешенный PageRank, точный betweenness, временные fast_share и sync_in_max. Роли назначаются по правилам с порогами, откалиброванными по распределениям, от первого совпавшего (coordinator первым; отдельная роль boundary для узлов 4-го колена). Priority считается как взвешенная сумма перцентилей. На выходе CSV и graph.json, которые показывает интерфейс на React + react-force-graph-2d через FastAPI. Копилот использует graph tools (node_card) и отвечает через локальную Ollama или OpenAI-совместимый API, без LLM работает на правилах.
Ключевые решения
- NetworkX
- взвешенный PageRank
- betweenness centrality
- community detection
- rule-based роли с калиброванными порогами
- временные признаки (окно 0–2 дня)
- взвешенный приоритет по перцентилям
- tool calling копилота
Метрики
Полный пайплайн ≈5 с (лимит 5 мин); роли: 15 coordinator, 49 distributor, 69 consolidator, 67 transit, 1158 terminal, 444 boundary, 446 peripheral; побайтный детерминизм выгрузок
Особенности
Введена роль boundary: 444 узла 4-го колена без исходящих не считаются ложными terminal, так как обход на них обрывался. Seed не может быть transit из-за неполных входящих. Интеграционные тесты проверяют требования ТЗ и побайтную воспроизводимость, а для ревью логики используются собственные Claude Code агенты (aml-logic-reviewer, spec-compliance-checker).
Стек
Python · pandas · NumPy · NetworkX 3.7 · SciPy · FastAPI · React 19 · Vite · react-force-graph-2d · Docker Compose · pytest
Модели
Ollama (локальная LLM) · OpenAI-совместимый API
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-71881218-stndz-main.
README
README.mdГраф денег — MoneyGraph AI
Решение команды STNDZ MAIN для HackAlem AI. По обезличенной сети переводов инструмент помогает AML-аналитику ответить: «кого смотреть первым и почему?» Движок рассчитывает структурные и временные признаки, назначает объяснимую роль каждому из 2 248 узлов, выделяет сообщества и формирует топ-30 для проверки. Веб-интерфейс показывает направления переводов, роли, карточку и связи найденного клиента; опциональный AI-ассистент отвечает на вопросы по графу. Результат — гипотезы по наблюдаемым данным, а не утверждения о виновности.
Сценарий защиты: docs/DEMO_SCRIPT.md. Текущая схема передачи данных и проверки: docs/DELIVERY_STATUS.md.
Быстрый старт
Команды выполняются из корня репозитория. Нужен Python 3.12+ (проверенная среда: 3.12.10; проверить: python --version): networkx зафиксирован на 3.7 ради воспроизводимых кластеров, а эта версия не ставится на Python 3.11 и более ранних версиях. Для интерфейса — Node.js 22.12+ и npm. В data/ должны лежать три исходных .parquet. Аналитика и интерфейс работают локально; LLM, GPU и интернет не требуются.
1. От исходных данных до всех выгрузок — одна команда
Для Bash или PowerShell 7:
python -m pip install -r requirements.txt && python run_pipeline.py
Для Windows PowerShell 5.1 (без поддержки &&):
python -m pip install -r requirements.txt; if ($LASTEXITCODE -eq 0) { python run_pipeline.py }
Рекомендуется предварительно создать виртуальную среду: python -m venv .venv, затем source .venv/bin/activate (Bash) или .venv\Scripts\Activate.ps1 (PowerShell). Без активации используйте .venv/Scripts/python.exe (Windows) или .venv/bin/python (Linux/macOS).
Команда за ≈ 5 секунд (лимит ТЗ — 5 минут) создаёт в output/: nodes_roles.csv, clusters.csv, top_nodes.csv и graph.json. Три CSV из последнего прогона уже лежат в репозитории — их можно посмотреть без запуска; повторный прогон воспроизводит их побайтно. Параметры: --data-dir (по умолчанию data), --output-dir (по умолчанию output).
2. Запустить приложение одной командой
Один раз установите зависимости API и интерфейса:
python -m pip install -r backend/requirements.txt
npm --prefix frontend ci
python start_dev.py
start_dev.py пересчитывает официальные выгрузки, запускает FastAPI на http://127.0.0.1:8000, дожидается готовности API и запускает интерфейс на http://127.0.0.1:5173. Ctrl+C останавливает оба сервера. Если порты заняты, задайте другие: python start_dev.py --api-port 8001 --web-port 5175. Скрипт использует тот же Python, которым запущен; активируйте виртуальную среду заранее.
Для раздельного запуска после python run_pipeline.py откройте два терминала:
# Терминал 1
python -m uvicorn backend.main:app --host 127.0.0.1 --port 8000
# Терминал 2
npm --prefix frontend run dev
Интерфейс получает граф через /api/graph. При недоступном API открывается локальная копия с явным индикатором состояния: граф, поиск, кластеры, топ, история и CSV остаются доступны; для серверной карточки с рекомендациями, устойчивости и ассистента нужен FastAPI. Перед dev и build скрипт sync-data копирует все четыре файла из output/ в frontend/public/data/. Если какого-то файла нет, запуск завершается с указанием выполнить python run_pipeline.py.
После нового расчёта перезапустите API, выполните npm --prefix frontend run sync-data и обновите страницу. Сборка для показа: npm --prefix frontend run build, затем npm --prefix frontend run preview (обычно http://localhost:4173). API должен работать и при preview; оба сервера Vite проксируют /api на http://127.0.0.1:8000. Для другого адреса задайте API_PROXY перед запуском Vite; общий launcher делает это сам.
Детали frontend: frontend/README.md.
3. Проверить результат
python -m pip install -r backend/requirements.txt
python -m pytest tests -v
tests/analytics/ — модульные проверки движка (признаки, роли, кластеры, приоритет, временные признаки, контракт выгрузки). tests/integration/ запускает run_pipeline.py с нуля во временные каталоги и проверяет требования ТЗ: 2 248 строк, роли из словаря, скоры в [0, 1], evidence с числами и не длиннее 200 символов, ни один узел среза на 4-м колене не terminal, ни один seed не transit, кластеры покрывают все узлы, топ ≥ 20 и отсортирован, побайтный детерминизм двух прогонов, время < 300 с; а также API и ассистента. Рабочая папка output/ при этом не перезаписывается.
Схема решения
Файл схемы: docs/solution_scheme.svg, подходит и как слайд для защиты.
| Часть | Где | Технологии |
|---|---|---|
| Движок | analytics/, run_pipeline.py | Python, pandas, NumPy, NetworkX 3.7, SciPy |
| Интерфейс | frontend/ | React 19, Vite, react-force-graph-2d |
| API и ассистент | backend/ | FastAPI; опциональная LLM через OpenAI-совместимый API или ответы на правилах |
Пороги и константы движка собраны в analytics/config.py; решения с обоснованием — docs/GRAPH_DECISIONS.md.
Входные данные
| Файл | Строк | Поля |
|---|---|---|
data/nodes.parquet | 2 248 | gid, depth, is_seed |
data/edges.parquet | 3 119 | src, dst, sum_kzt, n_tx, depth |
data/transactions.parquet | 4 840 | src, dst, date, sum_kzt |
81 seed, период 1–31 июля 2026, сумма рёбер 365 890 012,01 KZT. Ребро направлено от плательщика к получателю. Перед расчётом движок сверяет рёбра с транзакциями (пары, суммы, число переводов), проверяет, что все 444 узла 4-го колена без исходящих, и добавляет в граф все 2 248 узлов, включая 19 изолированных. Стартовый код организаторов — в starter/, полное ТЗ — в context/TASK.md.
gid — идентификатор, а не число: в JSON и API он передаётся строкой. При чтении CSV задавайте строковый тип (pd.read_csv(path, dtype={"gid": "string"})); табличные редакторы и JavaScript number теряют младшие разряды 18-значного идентификатора.
Признаки узла
| Признак | Расчёт | Зачем |
|---|---|---|
in_deg, out_deg | число разных плательщиков / получателей | сбор / веерная раздача |
in_kzt, out_kzt, in_tx, out_tx | суммы и число переводов | сумма и частота — разные сигналы |
pass_through | out_kzt / in_kzt (нет при in_kzt = 0) | транзит ≈ 1 |
retention | 1 − pass_through | удержание средств |
ext_inflow | max(0, out_kzt − in_kzt) | отдал больше, чем получил от наблюдаемых клиентов: источник вне выборки |
seed_payers | seed среди прямых плательщиков | прямой сбор с известных клиентов |
seed_reach2 | разные seed на входящих обходах длиной 1–2 | сходимость денег seed |
pagerank | PageRank с весом sum_kzt по направлению переводов | влияние по деньгам |
betweenness | точная, на направленном графе | посредничество |
fast_share | доля исходящих сумм с наблюдаемым входящим переводом в окне 0–2 дня | временное совпадение потоков |
sync_in_max | максимум разных плательщиков за один календарный день | синхронный сбор |
fast_share не доказывает, что отправлены именно полученные деньги; дата без времени не позволяет установить порядок переводов внутри дня. seed_reach2 при двухшаговом цикле может учитывать seed самого узла — это число seed на коротких входящих обходах, а не число независимых источников.
Роли: первое совпавшее правило побеждает
| Порядок | Роль | Условие | Узлов |
|---|---|---|---|
| 1 | coordinator | in_deg ≥ 5 и out_deg ≥ 10 | 15 |
| 2 | distributor | out_deg ≥ 10 | 49 |
| 3 | consolidator | in_deg ≥ 5; или in_deg ≥ 3 и seed_reach2 ≥ 3; или in_deg ≥ 3 и in_kzt ≥ 613 779 KZT (p95) | 69 |
| 4 | transit | не seed; in_deg > 0, out_deg > 0, 0.8 ≤ pass_through ≤ 1.2 | 67 |
| 5 | terminal | depth < 4, in_deg > 0, retention ≥ 0.8 | 1 158 |
| 6 | boundary (расширение словаря) | колено 4 и out_deg = 0 | 444 |
| 7 | peripheral | ни одно правило не сработало | 446 |
Пороги откалиброваны по распределениям данных: ≥ 5 плательщиков — топ-2% узлов, ≥ 10 получателей — топ-3%.
- Почему
coordinatorпроверяется первым. Главные сборщики в данных одновременно раздают средства (например, 19 плательщиков → 61 получатель): правило «много входящих и мало исходящих» их бы пропустило. - Почему
boundary— отдельная роль. Обход выгрузки остановился на 4-м колене, исходящие этих узлов не собирались. Наивное «нет исходящих ⇒ деньги осели» дало бы 444 ложных конечных получателя. На коленах 1–3 обход продолжался, поэтому отсутствие исходящих там — наблюдаемый факт, иterminalобоснован. - Почему seed не бывает
transit. Граф собран от seed по исходящим, их входящие извне выборки не видны,pass_throughдля них некорректен.
role_score ∈ [0,5; 1] показывает, насколько узел превышает порог своей роли (например, для distributor — out_deg / 60, приведённый к диапазону); это эвристика, а не вероятность нарушения. evidence — до 200 символов, всегда с числами, например: «Признаки координации: 5 плательщиков → 99 получателей; оборот 24 млн KZT; достижимы seed-клиенты: 3 в пределах 2 шагов». У seed evidence отдельно предупреждает о неполноте входящих данных.
Приоритет: кого смотреть первым
Каждая компонента приведена к [0, 1]; первые три — перцентильные ранги по всем узлам:
priority = 0.25 · flow перцентиль max(in_deg, out_deg)
+ 0.20 · structure среднее перцентилей pagerank и betweenness
+ 0.20 · volume перцентиль log(1 + in_kzt + out_kzt)
+ 0.10 · seed_conv min(1, seed_reach2 / 3)
+ 0.15 · external min(1, ext_inflow / 1 000 000)
+ 0.10 · temporal max(fast_share, min(1, sync_in_max / 3))
× 0.8 для seed — они уже известны, цель — новые узлы выше по цепочке
не выше 0.3 для boundary, peripheral и изолированных
top_nodes.csv — 30 узлов с наибольшим приоритетом; поле why объясняет позицию числами. Первое место текущей выгрузки — 100000000331309100 (coordinator): 5 плательщиков → 99 получателей, получено 0,98 млн KZT, отправлено 23 млн KZT.
Кластеры
Louvain с weight="sum_kzt" и seed=42 на NetworkX 3.7 даёт 91 сообщество, 8 из них содержат более одного seed; все 19 изолированных узлов — отдельные кластеры. Кластеризация работает на неориентированной проекции: вес пары равен сумме переводов в обоих направлениях. Простой G.to_undirected() здесь неприменим: он терял одно из встречных значений. Узлы и рёбра добавляются в фиксированном порядке, поэтому перестановка строк parquet не меняет результат (D-015). Направление денег учитывается в ролях. sum_kzt_internal — сумма направленных рёбер с обоими концами внутри кластера, top_gids — до пяти узлов с наибольшим приоритетом.
hypothesis — первое сработавшее правило по составу ролей:
| Условие | Гипотеза |
|---|---|
≥ 2 seed и есть consolidator | признаки сбора средств нескольких seed |
есть coordinator и distributor | признаки распределительной сети |
> 50% узлов — terminal | признаки конечного оседания средств |
> 50% узлов — boundary | граница выгрузки, структура неполна |
| иначе | выраженная функция не выявлена |
Выгрузки
| Файл | Содержание |
|---|---|
output/nodes_roles.csv | 2 248 строк: обязательные gid, role, role_score, cluster_id, priority_score, evidence и признаки узла |
output/clusters.csv | cluster_id, n_nodes, n_seed, sum_kzt_internal, top_gids, hypothesis; top_gids через ; |
output/top_nodes.csv | 30 строк: rank, gid, role, priority_score, why |
output/graph.json | данные интерфейса и API: meta, nodes (gid, признаки в metrics, флаги в flags), edges (src, dst), clusters и реальные transactions |
Контракт graph.json и словарь флагов (truncated_by_depth, seed_inflow_incomplete, outflow_exceeds_inflow, isolated, external_funding) — docs/GRAPH_DATA_CONTRACT.md.
Интерфейс аналитика
Рабочий сценарий: открыть топ-30 → выбрать клиента → изучить его направленные связи и evidence → посмотреть кластер, входящие и исходящие транзакции → скачать CSV. Поиск принимает полный строковый gid, включая изолированных клиентов. Цвет узла показывает роль, размер — приоритет; направление перевода отмечено стрелкой. Ограничения отображения графа указаны рядом со схемой, выбранный узел сохраняется при переходах.
Карточка запрашивает /api/nodes/{gid}/card и показывает наблюдаемые потоки, причины роли, пробелы данных и следующий запрос аналитика. История использует реальные транзакции из официального экспорта; отсутствие операций явно отделено от ошибки загрузки. Кластеры содержат размер, число seed, внутренний оборот и гипотезу. Топ показывает все 30 строк с объяснениями. Моделирование изъятия узлов вызывает /api/resilience; ассистент — /api/ask, ссылки на GID открывают соответствующего клиента.
Ограничения данных и метода
- Обход только по исходящим на четыре колена. У 444 узлов 4-го колена исходящие не собирались — роль
boundary, вывод об оседании не делается. - Неполные входящие, особенно у seed.
in_kzt − out_kzt— сальдо внутри выборки, не банковский баланс.ext_inflowпоказывает, что источник средств не виден, но не доказывает его характер. - Порог 5 000 KZT, один банк, один месяц. Дробление ниже порога, межбанковские переводы и операции за пределами июля невидимы. Даже
terminal— гипотеза в этих пределах. - Нет клиентских атрибутов и размеченных ролей. Пороги эвристические; качество оценивается обоснованностью правил, а не accuracy.
- Перцентильный приоритет относителен. Он ранжирует узлы внутри этой выгрузки и меняется при изменении выборки.
- Воспроизводимость. Louvain с
seed=42, NetworkX 3.7 и фиксированным порядком графа дают одинаковые выгрузки. Тесты сравнивают CSV побайтно при повторном запуске и перестановке всех входных строк; JSON совпадает за исключением времени генерации. На другой версии NetworkX число кластеров может отличаться.
Масштабирование до ~1 млн узлов
Это план развития, а не заявленный результат бенчмарка. Требования к памяти и времени зависят также от числа рёбер и транзакций.
| Компонент сейчас | Изменение на большом графе |
|---|---|
| pandas, загрузка всего набора | Polars lazy / DuckDB, чтение нужных колонок Parquet, агрегирование по частям; степени и суммы — за O(V + E) |
| NetworkX и Python-объекты | компактные индексы/CSR, igraph либо nx-cugraph на GPU при наличии ресурсов; соответствие строковых gid внутренним индексам |
| Точная betweenness | приближённая по выборке k источников с фиксированным seed; проверить стабильность топа при разных k |
| Louvain | Leiden; заново проверить качество сообществ |
| Перцентили приоритета | приближённые квантили (t-digest) вместо полной сортировки |
Полный graph.json в памяти API и браузера | хранилище узлов/рёбер с индексами по gid, src, dst; постраничные запросы, окрестности по требованию |
| Отрисовка подграфа | только окрестности и топ-N, агрегированные узлы кластеров, жёсткие лимиты выдачи |
Перед переносом: заменить проверку «ровно 2 248 строк» на покрытие входного множества узлов, измерить время и пик памяти на синтетических графах нескольких размеров, сравнить топы и роли с малым эталоном. GPU — возможная оптимизация, а не обязательное условие запуска.
API и опциональный AI-ассистент
python -m pip install -r backend/requirements.txt
python -m uvicorn backend.main:app --port 8000
В другом терминале: curl http://localhost:8000/api/health (в Windows при необходимости curl.exe). Ожидаются status: "ok", source: "output/graph.json", nodes: 2248, links: 3119. Swagger: http://localhost:8000/docs.
API ничего не пересчитывает: при старте читает готовый graph.json и строит индексы. Официальный источник — output/graph.json; файл можно задать явно через MONEYGRAPH_GRAPH_JSON. start_dev.py всегда закрепляет этот источник абсолютным путём. После нового прогона движка перезапустите сервер. Единственная точка расчёта — run_pipeline.py; устаревшая альтернативная реализация удалена.
| Endpoint | Данные для интерфейса |
|---|---|
GET /api/health | доступность и источник набора |
GET /api/graph | полный официальный снимок графа со строковыми GID |
GET /api/nodes/{gid}/card | карточка, ограничения и следующий запрос |
GET /api/nodes/{gid}/transactions | реальные операции выбранного узла |
GET /api/exports/{filename} | официальные CSV и graph.json |
GET /api/resilience?n=10 | сравнение связности до и после изъятия топ-N |
POST /api/ask | ответ ассистента со ссылками на узлы |
Карточка узла и оценка полноты: GET /api/nodes/{gid}/card
Справка по клиенту: роль и evidence, потоки, топ-3 плательщика и получателя по сумме, блок «на что обратить внимание» и пробелы в данных с рекомендуемым следующим запросом:
| Условие | Пробел | Следующий запрос |
|---|---|---|
| колено 4 без исходящих | исходящие не собирались | исходящие переводы клиента |
| seed-клиент | входящие извне выборки не видны | все входящие, включая межбанковские |
| не seed, отправил ≥ 2× и на ≥ 1 млн KZT больше, чем получил | источник разницы не виден | входящие, включая межбанковские |
| нет переводов в выгрузке | переводов от 5 000 KZT нет | полная выписка, включая < 5 000 KZT |
| всегда | переводы < 5 000 KZT и межбанковские не видны | операции ниже порога при признаках дробления |
Неизвестный gid — 404.
Устойчивость сети: GET /api/resilience?n=10
Изымает n (1–100) узлов с наибольшим priority_score и сравнивает связность сети до и после: число компонент, размер крупнейшей, seed в ней (без учёта направления переводов). Если приоритет не рассчитан, используется betweenness; поле ranked_by показывает, что использовано. На текущей выгрузке изъятие топ-10 разбивает сеть с 35 до 242 компонент, крупнейшая сокращается с 1 877 до 1 534 узлов.
Ассистент: POST /api/ask
Без настройки LLM работает разбор типовых вопросов по правилам. Локальная модель Ollama работает в режиме llm без ключа — см. ниже. Пример в Bash:
curl -sS http://localhost:8000/api/ask -H 'Content-Type: application/json' -d '{"question":"Топ 5 по priority_score","selected_gid":null}'
В PowerShell:
Invoke-RestMethod -Method Post -Uri http://localhost:8000/api/ask -ContentType 'application/json; charset=utf-8' -Body '{"question":"Топ 5 по priority_score","selected_gid":null}'
Поддерживаются карточка узла, входящие/исходящие соседи, общие прямые получатели указанных узлов, топ по метрике и направленный путь.
Для LLM с OpenAI-совместимым Chat Completions и tool calling задайте переменные перед запуском сервера или запишите их в локальный backend/.env (исключён из Git); переменные процесса важнее файла:
| Переменная | Значение |
|---|---|
LLM_PROVIDER | openai (по умолчанию) или ollama для локальной модели без ключа |
LLM_BASE_URL | базовый URL API с префиксом, например https://api.openai.com/v1; приложение добавляет /chat/completions |
LLM_API_KEY | ключ внешнего провайдера; для Ollama пустой. В режиме openai пустой ключ включает разбор по правилам |
LLM_MODEL | идентификатор модели у провайдера |
LLM_TIMEOUT_SECONDS | лимит времени на один вопрос, по умолчанию 30 секунд |
LLM только выбирает функции get_node, neighbors, common_collectors, top_by, path, node_card (пробелы в данных и следующий запрос). Ссылки на gid разрешены только из вопроса, выбранного узла или полученных результатов. Итоговые суммы, связи и карточки строятся серверными шаблонами из результатов функций; свободный текст модели в ответ не попадает. При ошибке провайдера срабатывает фолбэк на правилах.
Запрос: {"question": "...", "selected_gid": null | "<gid>"}; явные gid в вопросе важнее выделения. Ответ: answer, gids (строковые идентификаторы упомянутых существующих узлов), mode (llm или rules). Подробный контракт и примеры вопросов — docs/COPILOT_API.md.
Локальная LLM без API-ключа
Установите Ollama, затем из корня репозитория:
ollama pull qwen3:4b
ollama create moneygraph-qwen3:4b -f backend/ollama.Modelfile
Скопируйте backend/.env.example в backend/.env, если локального файла ещё нет, и перезапустите FastAPI. Профиль использует Ollama на http://127.0.0.1:11434/v1, API-ключ не нужен. Данные не покидают машину.
Проверить именно LLM, а не фолбэк:
python -m backend.check_copilot --all
Команда проверяет шесть типов вопросов и завершается ошибкой при mode="rules". Установка, настройки, диагностика — docs/OLLAMA_SETUP.md. Ollama опциональна: без неё ассистент отвечает по правилам, а движок, выгрузки и интерфейс от LLM не зависят.
Авторы коммитов
История коммитов
- 2026-09-23 17:55Skip symlink export test where the OS forbids symlinksnicr0s
- 2026-09-23 17:51Merge origin/main into codex/ali-frontendBenjAmineDrunklean
- 2026-09-23 17:50Rebuild frontend: new graph canvas, data views and API layerBenjAmineDrunklean
- 2026-09-23 17:37Updatebaidar-10
- 2026-09-23 17:36Fixbaidar-10
- 2026-09-23 17:31Merge final clean-machine checknicr0s
- 2026-09-23 17:30Merge latest delivery and Copilot updatesnicr0s
- 2026-09-23 17:30Record final clean-machine checknicr0s
Все коммиты (46)
- 2026-09-23 17:27Merge latest graph engine fixesnicr0s
- 2026-09-23 17:25Commit final CSV outputs as a deliverablenicr0s
- 2026-09-23 17:24Copilot: readable numbers and node_card toolnicr0s
- 2026-09-23 17:15Update demo cluster id after reciprocal-flow clustering fixnicr0s
- 2026-09-23 17:13Merge remote-tracking branch 'origin/main' into feature/delivery-prepnicr0s
- 2026-09-23 17:13Merge local Ollama copilot from feature/backendnicr0s
- 2026-09-23 17:10Merge local Ollama supportnicr0s
- 2026-09-23 17:08fix: preserve reciprocal flow and deterministic graph exportsBenjAmineDrunklean
- 2026-09-23 16:58Switch README to the engine and refresh docsnicr0s
- 2026-09-23 16:52Add local Ollama copilotnicr0s
- 2026-09-23 16:47test: verify graph export contractBenjAmineDrunklean
- 2026-09-23 16:42feat: implement temporal priority analysisBenjAmineDrunklean
- 2026-09-23 16:40Integrate investigation UI with graph enginebaidar-10
- 2026-09-23 16:32Add node card, data gaps and network resilience APInicr0s
- 2026-09-23 16:23Add 5-minute demo scriptnicr0s
- 2026-09-23 16:19Add solution scheme diagramnicr0s
- 2026-09-23 16:10Merge remote-tracking branch 'origin/main' into feature/delivery-prepnicr0s
- 2026-09-23 16:06feat: implement graph communitiesBenjAmineDrunklean
- 2026-09-23 16:05Switch backend and tests to run_pipeline enginenicr0s
- 2026-09-23 16:01Record clean-machine check in delivery statusnicr0s
- 2026-09-23 15:56Prepare switch between pipelines, pin networkxnicr0s
- 2026-09-23 15:56feat(analytics): implement phase 03 role analysisBenjAmineDrunklean
- 2026-09-23 15:43docs: add graph engine progress to READMEBenjAmineDrunklean
- 2026-09-23 15:39feat(analytics): add graph foundation and P0 featuresBenjAmineDrunklean
- 2026-09-23 15:34Merge backend delivery and project guidenicr0s
- 2026-09-23 15:25Add graph copilot and delivery documentationnicr0s
- 2026-09-23 15:13Updatebaidar-10
- 2026-09-23 14:47Fix AML Desk tree interaction: stable root, role filters, no timeline.baidar-10
- 2026-09-23 14:39Add backend skeleton and output integration testsnicr0s
- 2026-09-23 14:36Improve AML Desk graph readability with tree layout and RU/EN i18n.baidar-10
- 2026-09-23 14:30Initialbaidar-10
- 2026-09-23 14:06Add AML money-graph pipeline and Vite UI.baidar-10
- 2026-09-23 14:03Add team plan v2 with data-calibrated role rulesnicr0s
- 2026-09-23 13:52Add task title to READMEBenjAmineDrunklean
- 2026-09-23 13:40Stop tracking .venv; keep it ignored locally.baidar-10
- 2026-09-23 13:38Data addedbaidar-10
- 2026-09-23 13:36Data addedbaidar-10
- 2026-09-23 13:28Initial commitbaidar-10
Структура репозитория (102 файлов)
.claude/agents/aml-logic-reviewer.md .claude/agents/graph-data-auditor.md .claude/agents/spec-compliance-checker.md .claude/hooks/git-remote-status.sh .dockerignore .gitignore README.md analytics/CLAUDE.md analytics/__init__.py analytics/clusters.py analytics/config.py analytics/evidence.py analytics/export.py analytics/features.py analytics/graph.py analytics/loader.py analytics/priority.py analytics/roles.py analytics/temporal.py backend/.env.example backend/.gitignore backend/Dockerfile backend/__init__.py backend/check_copilot.py backend/copilot.py backend/graph_tools.py backend/insights.py backend/main.py backend/ollama.Modelfile backend/requirements.txt backend/settings.py backend/store.py compose.yaml context/TASK.md data/edges.parquet data/nodes.parquet data/transactions.parquet docs/CODEX_HANDOFF_PROMPT.md docs/COPILOT_API.md docs/DELIVERY_STATUS.md docs/DEMO_SCRIPT.md docs/GRAPH_DATA_CONTRACT.md docs/GRAPH_DECISIONS.md docs/GRAPH_ENGINE_PLAN.md docs/GRAPH_ENGINE_PROGRESS.md docs/HACKALEM_TEAM_PLAN.md docs/OLLAMA_SETUP.md docs/PROJECT_EXPLAINED.md docs/solution_scheme.svg frontend/.gitignore frontend/.oxlintrc.json frontend/Dockerfile frontend/README.md frontend/index.html frontend/package-lock.json frontend/package.json frontend/public/data/clusters.csv frontend/public/data/graph.json frontend/public/data/nodes_roles.csv frontend/public/data/top_nodes.csv frontend/public/favicon.svg frontend/public/freedom-logo.svg frontend/scripts/sync-engine-data.mjs frontend/src/App.css frontend/src/App.jsx frontend/src/CopilotPanel.jsx frontend/src/DataViews.jsx frontend/src/GraphCanvas.css frontend/src/GraphCanvas.jsx frontend/src/NodeInspector.jsx frontend/src/api.js frontend/src/components.jsx frontend/src/dataContract.test.js frontend/src/format.js frontend/src/graphAdapter.js frontend/src/graphModel.js frontend/src/graphModel.test.js frontend/src/index.css frontend/src/main.jsx frontend/vite.config.js output/READINESS_AUDIT.md output/clusters.csv output/nodes_roles.csv output/top_nodes.csv requirements.txt run_pipeline.py start_dev.py starter/README.md starter/requirements.txt starter/starter.py tests/__init__.py tests/analytics/test_clusters.py tests/analytics/test_contract.py tests/analytics/test_features.py tests/analytics/test_priority.py tests/analytics/test_roles.py tests/analytics/test_temporal.py tests/integration/__init__.py tests/integration/test_api.py tests/integration/test_data_api.py tests/integration/test_insights.py tests/integration/test_outputs.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.