Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .understand-anything/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Regenerable / local-only Understand-Anything artifacts
fingerprints.json
intermediate/
tmp/
diff-overlay.json
62 changes: 62 additions & 0 deletions .understand-anything/.understandignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# .understandignore — Aspid.MVVM (Unity) tuned excludes
# Goal: graph the C# framework code + docs/configs, drop Unity binary/noise.
# Scanner uses `git ls-files -co --exclude-standard`, so Library/Temp/obj are
# already dropped via .gitignore; these are belt-and-suspenders + tracked noise.

# --- Unity caches / generated project files ---
Library/
Temp/
Obj/
Logs/
UserSettings/
MemoryCaptures/
Build/
Builds/
.vs/
.idea/
.claude/
.understand-anything/
*.csproj
*.sln
*.unityproj
*.user
*.rsp

# --- Unity meta files (3103 of them — pure noise) ---
*.meta

# --- Unity binary/serialized assets (not code architecture) ---
*.unity
*.prefab
*.asset
*.mat
*.anim
*.controller
*.physicMaterial
*.physicsMaterial2D
*.unitypackage

# --- Shader assets (no tree-sitter grammar) ---
*.shader
*.shadergraph
*.cginc
*.hlsl
*.compute

# --- Committed build artifacts (generator/analyzer DLLs) ---
*.dll
*.pdb
*.xml
NonUnityBuild/

# --- Media / fonts / binaries ---
*.png
*.jpg
*.jpeg
*.tga
*.psd
*.gif
*.ttf
*.otf
*.fon
*.zip
1 change: 1 addition & 0 deletions .understand-anything/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"outputLanguage":"en"}
1 change: 1 addition & 0 deletions .understand-anything/knowledge-graph.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions .understand-anything/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"lastAnalyzedAt": "2026-06-01T00:43:28Z",
"gitCommitHash": "fd79935291c747db1c6a60b7ee8943fbd4a056a2",
"version": "1.0.0",
"analyzedFiles": 1951
}
130 changes: 130 additions & 0 deletions docs/understand-anything-evaluation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Understand-Anything vs aspid-wiki — сравнение на кодовой базе Aspid.MVVM

> Оценка проведена 2026-05-31…06-01 на ветке `docs/understand-anything` (база `Version/Aspid.MVVM-1.1.0`, коммит `fd79935`).
> Цель: прогнать [Understand-Anything](https://github.com/Lum1104/Understand-Anything) на том же коде, что и собственный навык `aspid-wiki`, и решить, что использовать.

---

## TL;DR — вердикт

**Для Aspid.MVVM как продукта/документации — `aspid-wiki` остаётся основным инструментом.** Understand-Anything (UA) полезен как **разовая карта-ориентир для онбординга и визуального обзора**, но на этом конкретном проекте упирается в три фундаментальных ограничения, которые делают его непригодным как «источник правды» о фреймворке:

1. **Слепота к source-generated коду.** UA парсит только рукописный текст (tree-sitter). Весь публичный API, который генерирует Source Generator (`OutText`, `InputText`, `SetOutText`, события `*Changed`, `SayCommand`, реализация `IViewModel`), **отсутствует в графе как узлы**. А это и есть суть фреймворка.
2. **0 import-рёбер на C#.** Резолвер импортов UA рассчитан на module-path языки (JS/TS/Python). C# использует пространства имён без маппинга «файл = модуль», поэтому детерминированный «скелет» графа пуст; межфайловые связи держатся на догадках LLM и при батчинге массово теряются.
3. **45 % графа — чужой код.** Из 1941 файлового узла 877 (45 %) — вендорные сторонние библиотеки (Zenject, Unity Asset Store Tools, TextMesh Pro), а ядро фреймворка `Source/` — лишь 68 файлов. Сигнал фреймворка тонет в шуме.

**Рекомендация:** держать `aspid-wiki` как канон; UA — опционально, разово, для визуального дашборда и быстрого онбординга новичка, и только с агрессивным `.understandignore` (исключить `Plugins/`, вендорные `Packages/`).

---

## Что это за инструменты

| | **aspid-wiki** (наш навык) | **Understand-Anything** (плагин) |
|---|---|---|
| Тип | Кастомный Claude-навык | Маркетплейс-плагин (Claude/Cursor/Copilot/…) |
| Артефакт | Курируемый Obsidian-vault: markdown + `[[wikilinks]]` + YAML | `knowledge-graph.json` + интерактивный веб-дашборд (Astro/Vite/React Flow) |
| Метод | LLM пишет нарративные страницы по фиксированной таксономии | tree-sitter (структура) + LLM (семантика), 6–7 агентов |
| Модель данных | Страницы концепций/сущностей/потоков/рисков/категорий | Граф: узлы (file/class/function/…) + рёбра (imports/calls/inherits/…) + слои + tour |
| Языки контента | EN (канон) + RU (1:1 перевод) | EN/RU/ZH/JA/KO (через `--language`) |
| Объём здесь | **69 EN + 69 RU** страниц | **3904 узла, 3937 рёбер, 10 слоёв, 12 шагов tour** |
| Синхронизация | Инкрементальная по git-diff, **submodule-aware** | Инкрементальная по git-diff + fingerprints (auto-update hook) |
| Покрытие генераторов | Документирует генераторы (в сабмодулях) явно | **Не сканирует сабмодули** (обычный `git ls-files`) |

---

## Методология прогона

Прогон выполнен «как у конечного пользователя»: плагин установлен через `/plugin marketplace add Lum1104/Understand-Anything` + `/plugin install`, затем `/understand --full --language en` на **полном репозитории**.

Пройдены все 7 фаз пайплайна:
- **Phase 0–0.5** — preflight, сборка `@understand-anything/core`, тюнинг `.understandignore` (62 правила: исключены `*.meta` ×3103, сцены/префабы/ассеты, DLL генераторов, `Library/`).
- **Phase 1 SCAN** — 1951 файл к анализу (3492 отфильтровано), детект C#/Unity/Zenject/UniTask.
- **Phase 1.5 BATCH** — 86 батчей.
- **Phase 2 ANALYZE** — 86 агентов `file-analyzer` (tree-sitter + LLM).
- **Phase 3–7** — merge → слои → guided tour → валидация → сохранение графа + дашборд.

---

## Результаты UA на Aspid.MVVM (факты)

```
Файлов проанализировано : 1951 (отфильтровано .understandignore: 3492)
Узлы графа : 3904 (file 1823, class 1481, function 482, document 71, config 40, pipeline 7)
Рёбра графа : 3937 (contains 2005, exports 800, calls 346, depends_on 252,
related 236, inherits 164, implements 105, configures 20, … imports: 0)
Слои : 10 (Core Source 68, StarterKit 720, Unity 152, Samples 56,
Vendored:Zenject 539, Vendored:AssetStoreTools 293,
Vendored:TextMeshPro 45, Docs 55, CI/CD 7, Config 6)
Tour : 12 шагов (overview → контракты → bind modes → генерация → команды →
биндеры → View → StarterKit → HelloWorld → release)
Связность : 1.01 ребра/узел (для живого код-графа норма 2–5+); 242 узла-сироты (6 %)
```

Скриншоты дашборда: `Overview` (граф слоёв), `Deep Dive` (граф + панель статистики), `Learn` (граф + 12-шаговый tour).

---

## Глубокие находки

### 1. Слепое пятно к Source Generator (решающее)
Пример `SpeakerViewModel.cs` (HelloWorld). В исходнике: поля `_outText`/`_inputText`, метод `Say()`, конструктор, `Dispose()`. Source Generator добавляет `OutText`/`InputText` (свойства), `SetOutText`/`SetInputText`, события `OutTextChanged`/`InputTextChanged`, `SayCommand`, реализацию `IViewModel`.

- tree-sitter извлёк ровно рукописное: `Say`, `Dispose`, конструктор + приватные поля.
- В итоговом `knowledge-graph.json` **поиск по `OutText`/`SayCommand`/`SetOutText`/`InputText` даёт 0 совпадений** — сгенерированных членов нет ни как узлов, ни как рёбер.
- У `SpeakerViewModel` всего 6 рёбер, все generic (`contains`/`exports` себя + `calls` из `Bootstrap`). Связь View↔ViewModel через биндинги в граф не попала.

LLM-слой это **частично маскирует**: прозаические summary корректно пишут «Partial `[ViewModel]` exposing a Say relay command…», и даже шаг tour №5 называется «The Generation Attributes — … Source-Generated Members». То есть UA **рассказывает**, что генерация есть, но **показать/связать сгенерированный API не может** — навигация к `SayCommand` или «что биндится к `OutText`» невозможна. Это ровно та причина, по которой в прошлой сессии для aspid-wiki отвергли graphify.

### 2. Ноль import-рёбер на C#
Резолвер `extract-import-map.mjs` дал **0 внутренних рёбер на всех 1951 файле**. Он сопоставляет import-пути с файлами (модель JS/TS/Python); C# адресуется пространствами имён, без «файл = модуль». Последствия:
- Нет детерминированного скелета графа — структура держится на LLM-догадках рёбер.
- Семантический батчинг схлопнулся: 1875 «одиночек» слиты в 76 misc-батчей (по сути произвольная группировка по 25 файлов).
- При merge **массово дропнуты cross-batch рёбра** (вся иерархия `IBindableMember → IReadOnlyBindableMember → …`: `inherits`/`implements`/`contains` отброшены, т.к. целевые узлы оказались в других батчах). Итог — связность 1.01 ребра/узел: граф это в основном «файл → его собственные классы/методы», слабо связанный между файлами.

### 3. 45 % графа — вендорный код
Из 1941 файлового узла: ядро `Source/` — **68**, StarterKit (биндеры) — 720, Unity — 152, Samples — 56, а **Zenject 539 + Asset Store Tools 293 + TextMesh Pro 45 = 877 (45 %) — сторонний код**, который просто лежит в репозитории трекаемыми `.cs`. На дашборде 3 из 10 верхнеуровневых слоёв — вендор. Курируемая `aspid-wiki` не документирует ни строки этого. Лечится агрессивным `.understandignore` (`Plugins/`, `Packages/com.unity.*`), но «из коробки» UA топит фреймворк в шуме.

### 4. Масштабирование и надёжность на большом репозитории
- На 86 батчах прогон на слабой модели (Haiku-агенты) **ложно отрапортовал «86/86 ok», реально записав лишь 19 батчей** — мелкая модель возвращала однострочный summary, не вызывая инструменты. Потребовался перезапуск на Opus + добивание оставшихся прямыми вызовами с проверкой файлов на диске. Вывод: на больших кодовых базах пайплайну нужна сильная модель и внешняя верификация артефактов.
- LLM-ревьюеры (Phase 3 assemble-review, `--review`) **не масштабируются** на граф из 3900 узлов (файл 3.4 МБ ≈ слишком много для чтения одним агентом) — пришлось заменить детерминированной валидацией.

### 5. Трение окружения (UX установки)
- `pnpm` (≥10) обязателен; pnpm 11 **падает с ошибкой** на пропущенных native build-скриптах tree-sitter (хотя UA использует `.wasm` через web-tree-sitter — native-биндинги не нужны). Обошли прямой сборкой `tsc`.
- `merge-batch-graphs.py` использует синтаксис **Python 3.10+** (`X | None`) — **падает на системном Python 3.9** без понятной диагностики. Обошли shim'ом `from __future__ import annotations`.
- Сабмодули генераторов (`Aspid.MVVM.Generators` и др.) **не сканируются** обычным `git ls-files` — ядро генерации вне графа (а `aspid-wiki` submodule-aware).

### 6. Что UA делает действительно хорошо
- **Интерактивный дашборд** (React Flow): слои, дрилл-даун, поиск (fuzzy/semantic), мини-карта, экспорт, переключение Overview/Deep Dive/Learn/Diff — лучше любого статичного markdown для визуального обзора.
- **Авто-слои**: 10 слоёв размечены аккуратно, вендор честно отделён.
- **Guided tour**: 12 осмысленных педагогических шагов, выстроенных в нарратив — хорошо для онбординга.
- **Многоязычность и diff-impact** из коробки.
- **Нулевая ручная работа**: курировать таксономию не нужно.

---

## Когда что использовать

| Задача | Инструмент |
|---|---|
| Источник правды о фреймворке, точность по сгенерированному API | **aspid-wiki** |
| Публичная/командная документация, концепции, риски, «почему так» | **aspid-wiki** |
| Экономия токенов агента (читать вики вместо исходников) | **aspid-wiki** |
| Быстрый визуальный обзор архитектуры, онбординг нового человека | **UA (дашборд + tour)** |
| Карта «что где лежит», навигация по слоям | **UA** (с `.understandignore` на вендор) |
| Diff-impact визуально на PR | **UA** |
| Точные связи View↔ViewModel↔Binder, иерархии интерфейсов | **aspid-wiki** (UA их теряет) |

**Стоимость прогона UA здесь:** 86 агентов-анализаторов, порядка **6–7 млн токенов** и несколько часов wall-clock (с учётом перезапусков из-за ненадёжности на масштабе). `aspid-wiki` (69+69 страниц) — сопоставимо по разовой стоимости, но даёт переиспользуемый, точный, инкрементально-синхронизируемый канон.

---

## Артефакты и воспроизводимость

- Граф: `.understand-anything/knowledge-graph.json` (3.4 МБ), `meta.json`, `fingerprints.json`, `.understandignore`.
- Дашборд (локально): из каталога плагина `packages/dashboard/` →
`GRAPH_DIR=<project> npx vite --host 127.0.0.1` → открыть токенизированный URL.
Или навык: `/understand-dashboard`.
- Инкрементальное обновление: `/understand` (перечитает только изменённые файлы по git-diff + fingerprints).
- Сравниваемый канон: ветка `docs/aspid-wiki`, `docs/wiki/` (EN) + `docs/wiki-ru/` (RU), PR #115.

> Замечания по совместимости в этом окружении: для пересборки нужен Python ≥3.10 (или shim) и pnpm с обходом гейта native build-скриптов. На больших репозиториях запускать file-analyzer на сильной модели и проверять, что каждый `batch-<i>.json` реально записан.
Loading