readmenator 1.3.2__tar.gz → 1.3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {readmenator-1.3.2 → readmenator-1.3.3}/PKG-INFO +64 -7
- {readmenator-1.3.2 → readmenator-1.3.3}/README.md +63 -6
- {readmenator-1.3.2 → readmenator-1.3.3}/pyproject.toml +1 -1
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/__init__.py +3 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/__main__.py +11 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_app.py +239 -30
- readmenator-1.3.3/readmenator/_bundlegraph.py +316 -0
- readmenator-1.3.3/readmenator/_bundlegraph_page.py +753 -0
- readmenator-1.3.3/readmenator/_components.py +1168 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_config.py +133 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_diagrams.py +1 -1
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_explorer.py +34 -2
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_forcegraph.py +24 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_forcegraph_page.py +142 -2
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_graphlayout.py +289 -69
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_linter.py +66 -5
- readmenator-1.3.3/readmenator/_ollama.py +128 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_pipeline.py +45 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_scanner.py +1 -0
- readmenator-1.3.3/readmenator/_sourceview.py +122 -0
- readmenator-1.3.3/readmenator/_symindex.py +438 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_video.py +641 -27
- readmenator-1.3.3/tests/test_bundlegraph.py +233 -0
- readmenator-1.3.3/tests/test_components.py +361 -0
- readmenator-1.3.3/tests/test_graphlayout.py +236 -0
- readmenator-1.3.3/tests/test_ollama.py +39 -0
- readmenator-1.3.3/tests/test_sourceview.py +129 -0
- readmenator-1.3.3/tests/test_symindex.py +94 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_video.py +65 -3
- readmenator-1.3.2/tests/test_graphlayout.py +0 -122
- {readmenator-1.3.2 → readmenator-1.3.3}/.gitignore +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/LICENSE +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_agent_injector.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_agent_output.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_analytics.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_analyzer.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_cache.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_category.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_concepts.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_cpg.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_cursorrules_generator.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_dataflow.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_dead_code.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_documentation.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_embed.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_exclusions.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_explain.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_exporter.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_gh_wiki.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_gitmeta.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_graphrag.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_hotspots.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_layer_rules.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_layers.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_mcp_server.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_memory.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_mermaid.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_models.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_projections.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_provenance.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_purpose.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_query.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_rank.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_readme_injector.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_refactorizer.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_resolver.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_rule_gen.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_sarif.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_scantext.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_security.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_skill_installer.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_skills/readmenator-ask/SKILL.md +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_skills/readmenator-change/SKILL.md +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_skills/readmenator-memory/SKILL.md +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_skills/readmenator-orient/SKILL.md +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_taint.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_uml.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_vendor/README.md +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_vendor/force-graph.min.js +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_watcher.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_wiki.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/_yaralite.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/__init__.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_assembly.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_base.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_c.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_csharp.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_dart.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_elixir.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_gdscript.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_go.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_java.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_javascript.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_kotlin.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_lua.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_nim.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_php.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_python.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_ruby.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_rust.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_scala.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_shell.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator/parsers/_swift.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/readmenator_orchestrator.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/__init__.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/features/taint_propagation.feature +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_agent_friendliness.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_agent_injector.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_agent_output.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_analyzer.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_cache.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_concepts.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_config.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_cpg.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_cursorrules.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_dataflow.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_dead_code.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_diagrams.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_documentation.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_exporter.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_gh_wiki.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_graphrag.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_hotspots.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_integration.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_interactive_graph.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_layer_rules.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_linter.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_mcp_server.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_memory.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_mermaid.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_models.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_parsers.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_parsers_new.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_parsers_property.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_query.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_ranking.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_readme_injector.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_refactorizer.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_resolver.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_rule_gen.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_sarif.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_scanner.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_security.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_taint.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_taint_bdd.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_uml.py +0 -0
- {readmenator-1.3.2 → readmenator-1.3.3}/tests/test_wiki.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: readmenator
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.3
|
|
4
4
|
Summary: Zero-token polyglot codebase knowledge graph generator
|
|
5
5
|
Project-URL: Homepage, https://github.com/grisuno/ReadMenator
|
|
6
6
|
Project-URL: Repository, https://github.com/grisuno/ReadMenator
|
|
@@ -95,6 +95,7 @@ python -m readmenator /path/to/project --svg # graph.svg (
|
|
|
95
95
|
python -m readmenator /path/to/project --graphml # graph.graphml (Gephi/yEd)
|
|
96
96
|
python -m readmenator /path/to/project obsidian # Obsidian vault (wikilinks)
|
|
97
97
|
python -m readmenator /path/to/project wiki # Agent wiki (index + community pages)
|
|
98
|
+
python -m readmenator /path/to/project components # Component diagrams (analysis.json + graph LR markdown + index.html)
|
|
98
99
|
python -m readmenator /path/to/project lint-wiki # Wiki health check
|
|
99
100
|
python -m readmenator /path/to/project lint # Architecture violations (exit 1 on errors)
|
|
100
101
|
python -m readmenator /path/to/project strip-dead-code # Orphaned symbol report
|
|
@@ -203,6 +204,49 @@ external in a 2D map or a 3D space:
|
|
|
203
204
|
`#path=<a>~<b>`, `#lens=cycles`, `#edge=<key>`. The page also exposes
|
|
204
205
|
`window.ReadmenatorExplorer` for console scripting.
|
|
205
206
|
|
|
207
|
+
The **Edge Bundle Explorer** (`readmenator-maps/graph-bundle.html`, its own gallery
|
|
208
|
+
card next to the force graph, `readmenator . bundles` to export it alone) is the
|
|
209
|
+
hierarchical edge bundling view from the video, live. It needs no network: one
|
|
210
|
+
canvas, no CDN.
|
|
211
|
+
|
|
212
|
+
- **Circle (2D).** Files sit on a ring grouped into community arcs (hubs first);
|
|
213
|
+
every resolved import is a B-spline routed through the community tree, so thick
|
|
214
|
+
bundles are the real seams between subsystems.
|
|
215
|
+
- **Sphere (3D).** The same hierarchy on a globe: each community owns a contiguous
|
|
216
|
+
cap sized by its file count, wires dive through the core between caps. Drag to
|
|
217
|
+
rotate, wheel to zoom, optional auto-rotate; selecting a file or community flies
|
|
218
|
+
the camera to face it.
|
|
219
|
+
- **Reading it.** Hover a file: cyan wires are what it imports, pink what imports it.
|
|
220
|
+
Click to pin it (imports and importers listed, one click to open it in the force
|
|
221
|
+
graph in 2D or 3D). Click an arc, cap label or legend row to focus a community
|
|
222
|
+
(inside/out/in counts, cohesion, top flows to other communities).
|
|
223
|
+
- **Controls.** Beta slider (0 straight chords, 1 fully bundled, recomputed live),
|
|
224
|
+
crossing-only filter, direction (both, imports, imported by), color by community,
|
|
225
|
+
layer or language, search, PNG export, light/dark theme. Deep links:
|
|
226
|
+
`#view=3d&node=<id>&group=<key>&beta=0.7&color=layer&dir=out&cross=1`; console API
|
|
227
|
+
`window.ReadmenatorBundles`.
|
|
228
|
+
|
|
229
|
+
### Component Diagrams
|
|
230
|
+
|
|
231
|
+
`readmenator-diagrams/` holds a component architecture map built with zero
|
|
232
|
+
tokens: `analysis.json` (components with key entities and file/line spans,
|
|
233
|
+
relations with method-level call evidence), `overview.md` with the `graph LR`
|
|
234
|
+
diagram, one page per expandable component, and `index.html` — the diagram
|
|
235
|
+
drawn as an offline interactive page in the readmenator dark theme (layered
|
|
236
|
+
left-to-right boxes enriched with key symbols, layer colors and PageRank hubs,
|
|
237
|
+
labeled arrows weighted by call/import evidence, hover descriptions,
|
|
238
|
+
click-to-component, pan/zoom, PNG export). The maps gallery links it with a
|
|
239
|
+
**Component Diagrams** card that opens a self-contained copy living inside the
|
|
240
|
+
maps directory itself, so the link never leaves the site (safe on GitHub Pages
|
|
241
|
+
project subpaths, where `../..` hrefs would escape the project). The docs site
|
|
242
|
+
ships the markdown in its reader. No external service needed: structure and
|
|
243
|
+
call evidence are pure static analysis; a local Ollama daemon only ever
|
|
244
|
+
enriches prose descriptions, and only when `OLLAMA_ENABLED` is set.
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
python -m readmenator /path/to/project components # rebuild only the diagrams
|
|
248
|
+
```
|
|
249
|
+
|
|
206
250
|
Serve the `docs/` directory directly with GitHub Pages (Settings -> Pages ->
|
|
207
251
|
Deploy from branch -> folder `docs/`). The gallery `index.html` links every map
|
|
208
252
|
with relative paths, works fully offline, and needs no build step.
|
|
@@ -213,13 +257,20 @@ gallery, every `--rebuild` refreshes it (video and docs included).
|
|
|
213
257
|
|
|
214
258
|
### Overview Video
|
|
215
259
|
|
|
216
|
-
`readmenator . video` renders a synthwave mp4 from real scan data in
|
|
260
|
+
`readmenator . video` renders a synthwave mp4 from real scan data in nine acts:
|
|
217
261
|
layers, god nodes, blast-radius tree, communities, **Emergence** (ForceAtlas2
|
|
218
262
|
LinLog with adaptive speed, animated from seeded chaos to convergence, nodes
|
|
219
|
-
sized by PageRank with random-surfer particles on the hottest edges), **
|
|
220
|
-
(
|
|
221
|
-
|
|
222
|
-
|
|
263
|
+
sized by PageRank with random-surfer particles on the hottest edges), **Orbit**
|
|
264
|
+
(the force graph laid out by ForceAtlas2 in 3D and flown by a camera: color by
|
|
265
|
+
community, layer and language in turn, a tour that zooms into the largest
|
|
266
|
+
communities with their cohesion and seams, then the 1-hop reach of the top hub),
|
|
267
|
+
**The Wiring** (Holten hierarchical edge bundling: files on a circle by community,
|
|
268
|
+
imports routed as B-splines through the community tree, a spotlight sweeping each
|
|
269
|
+
community and a live flow ranking), **The Sphere** (the 3D layout folds onto a globe
|
|
270
|
+
of community caps and every import bundles through its core), and code DNA. A
|
|
271
|
+
closing invitation shows both explorers spinning with their paths, so viewers know
|
|
272
|
+
where to go next. Set an act's duration (`VIDEO_ORBIT_S`, `VIDEO_SPHERE_S`,
|
|
273
|
+
`VIDEO_INVITE_S`, ...) to 0 to drop it with its card.
|
|
223
274
|
|
|
224
275
|
### GraphRAG for agents (zero tokens to build, cheap to query)
|
|
225
276
|
|
|
@@ -331,9 +382,15 @@ Supported target languages (12): C++, Java, C#, Python, Go, Rust, PHP, Kotlin, S
|
|
|
331
382
|
| Watcher | `_watcher.py` | Filesystem polling watcher for auto-rebuild |
|
|
332
383
|
| README Injector | `_readme_injector.py` | Auto-injects KB link into project README |
|
|
333
384
|
| GraphRAG | `_graphrag.py` | Entities, relationships, text units, community report hierarchy, local/global search |
|
|
334
|
-
| Graph layouts | `_graphlayout.py` | ForceAtlas2 snapshots and hierarchical edge bundling |
|
|
385
|
+
| Graph layouts | `_graphlayout.py` | ForceAtlas2 (2D/3D) snapshots, circular and spherical hierarchical edge bundling |
|
|
386
|
+
| Edge bundles | `_bundlegraph.py` | Circle + sphere bundle payload, settings, thumbnail |
|
|
387
|
+
| Bundle page | `_bundlegraph_page.py` | Self-contained canvas page: 2D circle, 3D sphere, live beta, focus panels |
|
|
335
388
|
| Force graph | `_forcegraph.py` | Heterogeneous explorer payload, settings, thumbnail |
|
|
336
389
|
| Explorer page | `_forcegraph_page.py` | 2D/3D explorer HTML: hit-testing, overlay glyphs, node and edge actions |
|
|
390
|
+
| Source viewer | `_sourceview.py` | Bounded per-file source texts for the explorer View drawer |
|
|
391
|
+
| Symbol index | `_symindex.py` | Definition spans, call sites with lines, BUILTIN/SAME_FILE/IMPORTED/UNIQUE/AMBIGUOUS/UNRESOLVED resolver |
|
|
392
|
+
| Component diagrams | `_components.py` | analysis.json, graph LR markdown, offline interactive index.html, gallery card |
|
|
393
|
+
| Local Ollama | `_ollama.py` | Optional localhost LLM client for prose only (bounded, never fatal) |
|
|
337
394
|
| Memory | `_memory.py` | MEMORY.md: declared rules, measured baselines, preserved session log |
|
|
338
395
|
| Skills | `_skill_installer.py` | Installs packaged agent skills from `_skills/` |
|
|
339
396
|
| Application | `_app.py` | Application orchestrator |
|
|
@@ -71,6 +71,7 @@ python -m readmenator /path/to/project --svg # graph.svg (
|
|
|
71
71
|
python -m readmenator /path/to/project --graphml # graph.graphml (Gephi/yEd)
|
|
72
72
|
python -m readmenator /path/to/project obsidian # Obsidian vault (wikilinks)
|
|
73
73
|
python -m readmenator /path/to/project wiki # Agent wiki (index + community pages)
|
|
74
|
+
python -m readmenator /path/to/project components # Component diagrams (analysis.json + graph LR markdown + index.html)
|
|
74
75
|
python -m readmenator /path/to/project lint-wiki # Wiki health check
|
|
75
76
|
python -m readmenator /path/to/project lint # Architecture violations (exit 1 on errors)
|
|
76
77
|
python -m readmenator /path/to/project strip-dead-code # Orphaned symbol report
|
|
@@ -179,6 +180,49 @@ external in a 2D map or a 3D space:
|
|
|
179
180
|
`#path=<a>~<b>`, `#lens=cycles`, `#edge=<key>`. The page also exposes
|
|
180
181
|
`window.ReadmenatorExplorer` for console scripting.
|
|
181
182
|
|
|
183
|
+
The **Edge Bundle Explorer** (`readmenator-maps/graph-bundle.html`, its own gallery
|
|
184
|
+
card next to the force graph, `readmenator . bundles` to export it alone) is the
|
|
185
|
+
hierarchical edge bundling view from the video, live. It needs no network: one
|
|
186
|
+
canvas, no CDN.
|
|
187
|
+
|
|
188
|
+
- **Circle (2D).** Files sit on a ring grouped into community arcs (hubs first);
|
|
189
|
+
every resolved import is a B-spline routed through the community tree, so thick
|
|
190
|
+
bundles are the real seams between subsystems.
|
|
191
|
+
- **Sphere (3D).** The same hierarchy on a globe: each community owns a contiguous
|
|
192
|
+
cap sized by its file count, wires dive through the core between caps. Drag to
|
|
193
|
+
rotate, wheel to zoom, optional auto-rotate; selecting a file or community flies
|
|
194
|
+
the camera to face it.
|
|
195
|
+
- **Reading it.** Hover a file: cyan wires are what it imports, pink what imports it.
|
|
196
|
+
Click to pin it (imports and importers listed, one click to open it in the force
|
|
197
|
+
graph in 2D or 3D). Click an arc, cap label or legend row to focus a community
|
|
198
|
+
(inside/out/in counts, cohesion, top flows to other communities).
|
|
199
|
+
- **Controls.** Beta slider (0 straight chords, 1 fully bundled, recomputed live),
|
|
200
|
+
crossing-only filter, direction (both, imports, imported by), color by community,
|
|
201
|
+
layer or language, search, PNG export, light/dark theme. Deep links:
|
|
202
|
+
`#view=3d&node=<id>&group=<key>&beta=0.7&color=layer&dir=out&cross=1`; console API
|
|
203
|
+
`window.ReadmenatorBundles`.
|
|
204
|
+
|
|
205
|
+
### Component Diagrams
|
|
206
|
+
|
|
207
|
+
`readmenator-diagrams/` holds a component architecture map built with zero
|
|
208
|
+
tokens: `analysis.json` (components with key entities and file/line spans,
|
|
209
|
+
relations with method-level call evidence), `overview.md` with the `graph LR`
|
|
210
|
+
diagram, one page per expandable component, and `index.html` — the diagram
|
|
211
|
+
drawn as an offline interactive page in the readmenator dark theme (layered
|
|
212
|
+
left-to-right boxes enriched with key symbols, layer colors and PageRank hubs,
|
|
213
|
+
labeled arrows weighted by call/import evidence, hover descriptions,
|
|
214
|
+
click-to-component, pan/zoom, PNG export). The maps gallery links it with a
|
|
215
|
+
**Component Diagrams** card that opens a self-contained copy living inside the
|
|
216
|
+
maps directory itself, so the link never leaves the site (safe on GitHub Pages
|
|
217
|
+
project subpaths, where `../..` hrefs would escape the project). The docs site
|
|
218
|
+
ships the markdown in its reader. No external service needed: structure and
|
|
219
|
+
call evidence are pure static analysis; a local Ollama daemon only ever
|
|
220
|
+
enriches prose descriptions, and only when `OLLAMA_ENABLED` is set.
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
python -m readmenator /path/to/project components # rebuild only the diagrams
|
|
224
|
+
```
|
|
225
|
+
|
|
182
226
|
Serve the `docs/` directory directly with GitHub Pages (Settings -> Pages ->
|
|
183
227
|
Deploy from branch -> folder `docs/`). The gallery `index.html` links every map
|
|
184
228
|
with relative paths, works fully offline, and needs no build step.
|
|
@@ -189,13 +233,20 @@ gallery, every `--rebuild` refreshes it (video and docs included).
|
|
|
189
233
|
|
|
190
234
|
### Overview Video
|
|
191
235
|
|
|
192
|
-
`readmenator . video` renders a synthwave mp4 from real scan data in
|
|
236
|
+
`readmenator . video` renders a synthwave mp4 from real scan data in nine acts:
|
|
193
237
|
layers, god nodes, blast-radius tree, communities, **Emergence** (ForceAtlas2
|
|
194
238
|
LinLog with adaptive speed, animated from seeded chaos to convergence, nodes
|
|
195
|
-
sized by PageRank with random-surfer particles on the hottest edges), **
|
|
196
|
-
(
|
|
197
|
-
|
|
198
|
-
|
|
239
|
+
sized by PageRank with random-surfer particles on the hottest edges), **Orbit**
|
|
240
|
+
(the force graph laid out by ForceAtlas2 in 3D and flown by a camera: color by
|
|
241
|
+
community, layer and language in turn, a tour that zooms into the largest
|
|
242
|
+
communities with their cohesion and seams, then the 1-hop reach of the top hub),
|
|
243
|
+
**The Wiring** (Holten hierarchical edge bundling: files on a circle by community,
|
|
244
|
+
imports routed as B-splines through the community tree, a spotlight sweeping each
|
|
245
|
+
community and a live flow ranking), **The Sphere** (the 3D layout folds onto a globe
|
|
246
|
+
of community caps and every import bundles through its core), and code DNA. A
|
|
247
|
+
closing invitation shows both explorers spinning with their paths, so viewers know
|
|
248
|
+
where to go next. Set an act's duration (`VIDEO_ORBIT_S`, `VIDEO_SPHERE_S`,
|
|
249
|
+
`VIDEO_INVITE_S`, ...) to 0 to drop it with its card.
|
|
199
250
|
|
|
200
251
|
### GraphRAG for agents (zero tokens to build, cheap to query)
|
|
201
252
|
|
|
@@ -307,9 +358,15 @@ Supported target languages (12): C++, Java, C#, Python, Go, Rust, PHP, Kotlin, S
|
|
|
307
358
|
| Watcher | `_watcher.py` | Filesystem polling watcher for auto-rebuild |
|
|
308
359
|
| README Injector | `_readme_injector.py` | Auto-injects KB link into project README |
|
|
309
360
|
| GraphRAG | `_graphrag.py` | Entities, relationships, text units, community report hierarchy, local/global search |
|
|
310
|
-
| Graph layouts | `_graphlayout.py` | ForceAtlas2 snapshots and hierarchical edge bundling |
|
|
361
|
+
| Graph layouts | `_graphlayout.py` | ForceAtlas2 (2D/3D) snapshots, circular and spherical hierarchical edge bundling |
|
|
362
|
+
| Edge bundles | `_bundlegraph.py` | Circle + sphere bundle payload, settings, thumbnail |
|
|
363
|
+
| Bundle page | `_bundlegraph_page.py` | Self-contained canvas page: 2D circle, 3D sphere, live beta, focus panels |
|
|
311
364
|
| Force graph | `_forcegraph.py` | Heterogeneous explorer payload, settings, thumbnail |
|
|
312
365
|
| Explorer page | `_forcegraph_page.py` | 2D/3D explorer HTML: hit-testing, overlay glyphs, node and edge actions |
|
|
366
|
+
| Source viewer | `_sourceview.py` | Bounded per-file source texts for the explorer View drawer |
|
|
367
|
+
| Symbol index | `_symindex.py` | Definition spans, call sites with lines, BUILTIN/SAME_FILE/IMPORTED/UNIQUE/AMBIGUOUS/UNRESOLVED resolver |
|
|
368
|
+
| Component diagrams | `_components.py` | analysis.json, graph LR markdown, offline interactive index.html, gallery card |
|
|
369
|
+
| Local Ollama | `_ollama.py` | Optional localhost LLM client for prose only (bounded, never fatal) |
|
|
313
370
|
| Memory | `_memory.py` | MEMORY.md: declared rules, measured baselines, preserved session log |
|
|
314
371
|
| Skills | `_skill_installer.py` | Installs packaged agent skills from `_skills/` |
|
|
315
372
|
| Application | `_app.py` | Application orchestrator |
|
|
@@ -29,6 +29,9 @@ from readmenator._diagrams import ( # noqa: F401
|
|
|
29
29
|
VisNetworkRenderer,
|
|
30
30
|
)
|
|
31
31
|
from readmenator._mcp_server import MCPServer # noqa: F401
|
|
32
|
+
from readmenator._components import ComponentDiagramBuilder, sanitize # noqa: F401
|
|
33
|
+
from readmenator._ollama import OllamaClient # noqa: F401
|
|
34
|
+
from readmenator._symindex import SymbolIndex # noqa: F401
|
|
32
35
|
from readmenator._concepts import ConceptExtractor, verb_for_relation # noqa: F401
|
|
33
36
|
from readmenator._models import ( # noqa: F401
|
|
34
37
|
AnalysisResult,
|
|
@@ -54,6 +54,8 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
54
54
|
" gh-wiki --dry-run Render GitHub wiki pages locally, no git calls\n"
|
|
55
55
|
" explorer Serve force-graph explorer locally\n"
|
|
56
56
|
" forcegraph Export force-graph explorer HTML (readmenator-maps/graph-force.html)\n"
|
|
57
|
+
" bundles Export edge bundle explorer HTML, circle + sphere (readmenator-maps/graph-bundle.html)\n"
|
|
58
|
+
" components Export component diagrams (analysis.json + graph LR markdown + index.html)\n"
|
|
57
59
|
" analytics Print corpus analytics JSON (funnel, layers, hotspots)\n"
|
|
58
60
|
" near <file|text> Nearest files by scan-text similarity (offline Jaccard)\n"
|
|
59
61
|
" scan-text Print synthesized scan-text blobs per file\n"
|
|
@@ -327,6 +329,15 @@ def main() -> None:
|
|
|
327
329
|
out = app.export_forcegraph(target)
|
|
328
330
|
print(out)
|
|
329
331
|
return
|
|
332
|
+
elif command == "bundles":
|
|
333
|
+
out = app.export_bundlegraph(target)
|
|
334
|
+
print(out)
|
|
335
|
+
return
|
|
336
|
+
elif command == "components":
|
|
337
|
+
written = app.export_components(target)
|
|
338
|
+
for kind, path in sorted(written.items()):
|
|
339
|
+
print(f"{kind}: {path}")
|
|
340
|
+
return
|
|
330
341
|
elif command == "analytics":
|
|
331
342
|
import json as _json
|
|
332
343
|
|