# HONTI Analyzer 0.1

Автономное браузерное приложение для исследования зависимостей. Встроен в `/analyzer/`, отдельный адрес — `/analyzer/demo/`. Подключения к SAP и серверного хранения нет.

## Возможности

- Граф и таблица объектов; поиск по ключу, названию и описанию; фильтр типов. При скрытии типа направленные связи перестраиваются между ближайшими оставшимися объектами. Пунктирная связь показывает свёрнутый путь; её свойства содержат промежуточные объекты и исходные связи. Поиск выделяет найденные объекты, а остальные объекты их цепочки показывает точками, сохраняя поток.
- Свойства объектов и связей, прямые связи, upstream/downstream выбранного объекта.
- Шесть демонстрационных снимков: воспроизведение, выбор даты, подсветка добавлений, изменений и удалений.
- Расположение рассчитано по объединению снимков и сохраняется при переключении дат. Перетаскивание узлов также сохраняется до загрузки другого набора.
- Загрузка локального JSON. Содержимое не отправляется на сервер и не сохраняется после закрытия страницы.

## Данные

Встроенные имена, описания, даты и события вымышлены. Исходная топология сохранена для проверки разветвлений, изолированных объектов и петли. Демонстрация не отражает историю какой-либо SAP-системы.

Можно выбрать одновременно `Groups.json`, `Nodes.json`, `Lines.json` старого формата. Адаптер убирает пробелы в кодах типов и повторные пары from/to. Для старого формата поддержаны key/group/title/description и from/to; другие поля пока не переносятся. Создаётся один неполный снимок с датой импорта; история не выдумывается.

Новый формат — один файл:

```json
{
  "schemaVersion": 1,
  "title": "Мой ландшафт",
  "synthetic": false,
  "types": {"ADSO": "Хранилище"},
  "snapshots": [{
    "id": "scan-1",
    "capturedAt": "2026-01-01T00:00:00Z",
    "scope": "system-A/full",
    "complete": true,
    "label": "Первое сканирование",
    "nodes": [{"id": "a", "type": "ADSO", "label": "Объект", "attributes": {"Версия": 1}}],
    "edges": []
  }]
}
```

Связь: `{"id":"e1","source":"a","target":"b","type":"dependency"}`; оба объекта должны существовать. Идентификаторы стабильны между снимками, не используются одновременно для узлов и связей. При смене концов связи рекомендуется новый id. Даты идут строго по возрастанию.

Сравниваются только соседние **полные** снимки с одинаковым непустым `scope`. Отсутствие объекта в неполной выгрузке не считается удалением. Подсветка относится к предыдущему хронологическому снимку, независимо от направления переключения. Счётчик графа включает видимые удалённые объекты, если включено их отображение.

## Архитектура

`model.js` — независимые от интерфейса валидация, сравнение, обход, фильтрация и адаптер старого формата.
`app.js` — состояние интерфейса, Cytoscape, раскладка ELK и локальный импорт.
`demo.json` — набор снимков, заменяемый будущим адаптером источника данных.
`app.css` и `index.html` — оболочка приложения.

Библиотеки поставляются локально: Cytoscape.js 3.33.1 (MIT), ELK.js 0.10.0 (EPL-2.0). Исходники ELK: https://github.com/kieler/elkjs/tree/0.10.0 ; полный текст лицензии в `vendor/ELK-LICENSE.txt`. MIT-текст Cytoscape сохранён в начале файла библиотеки. Библиотеки не модифицированы.

## Запуск и проверка

Из корня репозитория: `python -m http.server 8765`, затем http://localhost:8765/analyzer/demo/ . Открытие через file:// не поддерживается.

`npm test` проверяет модель, шесть снимков, настоящую раскладку ELK и headless-графы Cytoscape.

До публикации нужна браузерная проверка: граф/таблица, выбор свойств, фокус, поиск без результата, все даты, play/pause, удалённые объекты, импорт, ширины 390 и 1440 px, встраивание в лендинг. В среде подготовки Chromium установить не удалось; автоматические проверки не заменяют эту визуальную проверку.

## Ограничения приложения

Без коллектора, авторизации, сервера, долговременного хранения и выгрузки результатов. Нет оценки бизнес-критичности зависимостей. Импорт до 8 МБ, до 100 снимков, объединённый граф до 3000 объектов / 10000 связей: это защитные ограничения, не подтверждённая производительность. ELK пока работает в основном потоке; большие наборы могут задерживать интерфейс. Следующий этап — Worker, источник реальных снимков, профилирование и выделение модулей приложения.

При нескольких скрытых маршрутах между одной парой видимых объектов показывается один свёрнутый переход с кратчайшей найденной цепочкой в свойствах. Прямые связи не сворачиваются. Скрытые начальные и конечные объекты без второй видимой точки не изображаются как отдельные концы маршрута.

## Сценарии для посетителей

Встроены два сценария на вымышленных демоданных:

- **Что затронет изменение источника?** Выбирает «Источник 02» в исходном снимке и подсвечивает все направленные зависимости до двух отчётов. Остальной ландшафт остаётся на экране, но приглушается. Число зависимых объектов и список отчётов рассчитываются из графа. Это техническая зависимость, а не прогноз сбоя.
- **Что изменилось?** Запускает шесть снимков с сохранением расположения объектов. Пояснение раздельно считает добавленные, изменённые и удалённые объекты и связи относительно предыдущего снимка. Воспроизведение можно приостановить или продолжить.

Кнопка «Завершить сценарий» возвращает обычное исследование текущего снимка. Ручные фильтры тоже завершают сценарий; выбор объекта только ставит историю на паузу. Запуск сценария сбрасывает фильтры и открывает исходный снимок демо. Для импортированных файлов сценарии отключены, даже если JSON содержит synthetic:true. Возврат к демоданным выполняется только отдельной кнопкой.

Рядом с пояснением размещена ссылка «Разобрать мой ландшафт»: открывает письмо на info@honti-it.ru. Данные графа в письмо не добавляются и автоматически не отправляются.

`npm test` включает проверку сценариев и событий интерфейса с настоящим Cytoscape в headless-режиме и минимальным DOM. Эта проверка не заменяет визуальную проверку в браузере.
