code2llm 0.5.55__tar.gz → 0.5.57__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.
Files changed (120) hide show
  1. {code2llm-0.5.55 → code2llm-0.5.57}/PKG-INFO +13 -17
  2. {code2llm-0.5.55 → code2llm-0.5.57}/README.md +12 -16
  3. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/__init__.py +1 -1
  4. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/cli_commands.py +1 -1
  5. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/cli_exports/formats.py +2 -2
  6. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/cli_exports/orchestrator.py +1 -1
  7. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/cli_exports/prompt.py +18 -15
  8. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/cli_parser.py +9 -9
  9. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/__init__.py +1 -1
  10. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/index_generator.py +105 -3
  11. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/map_exporter.py +101 -12
  12. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/project_yaml_exporter.py +1 -1
  13. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/readme_exporter.py +14 -22
  14. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/report_generators.py +1 -1
  15. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/toon/__init__.py +1 -15
  16. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/toon/metrics.py +6 -6
  17. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/nlp/__init__.py +1 -1
  18. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm.egg-info/PKG-INFO +13 -17
  19. {code2llm-0.5.55 → code2llm-0.5.57}/pyproject.toml +1 -1
  20. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_format_quality.py +12 -10
  21. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_prompt_txt.py +3 -2
  22. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_toon_v2.py +22 -16
  23. {code2llm-0.5.55 → code2llm-0.5.57}/LICENSE +0 -0
  24. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/__main__.py +0 -0
  25. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/__init__.py +0 -0
  26. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/call_graph.py +0 -0
  27. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/cfg.py +0 -0
  28. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/coupling.py +0 -0
  29. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/data_analysis.py +0 -0
  30. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/dfg.py +0 -0
  31. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/pipeline_detector.py +0 -0
  32. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/side_effects.py +0 -0
  33. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/smells.py +0 -0
  34. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/analysis/type_inference.py +0 -0
  35. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/api.py +0 -0
  36. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/cli.py +0 -0
  37. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/cli_analysis.py +0 -0
  38. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/cli_exports/__init__.py +0 -0
  39. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/cli_exports/code2logic.py +0 -0
  40. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/__init__.py +0 -0
  41. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/analyzer.py +0 -0
  42. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/config.py +0 -0
  43. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/__init__.py +0 -0
  44. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/file_analyzer.py +0 -0
  45. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/file_cache.py +0 -0
  46. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/file_filter.py +0 -0
  47. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/__init__.py +0 -0
  48. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/base.py +0 -0
  49. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/cpp.py +0 -0
  50. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/csharp.py +0 -0
  51. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/generic.py +0 -0
  52. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/go_lang.py +0 -0
  53. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/java.py +0 -0
  54. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/php.py +0 -0
  55. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/ruby.py +0 -0
  56. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/rust.py +0 -0
  57. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/lang/typescript.py +0 -0
  58. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/core/refactoring.py +0 -0
  59. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/gitignore.py +0 -0
  60. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/large_repo.py +0 -0
  61. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/models.py +0 -0
  62. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/repo_files.py +0 -0
  63. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/streaming/__init__.py +0 -0
  64. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/streaming/cache.py +0 -0
  65. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/streaming/incremental.py +0 -0
  66. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/streaming/prioritizer.py +0 -0
  67. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/streaming/scanner.py +0 -0
  68. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/streaming/strategies.py +0 -0
  69. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/streaming_analyzer.py +0 -0
  70. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/core/toon_size_manager.py +0 -0
  71. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/article_view.py +0 -0
  72. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/base.py +0 -0
  73. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/context_exporter.py +0 -0
  74. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/context_view.py +0 -0
  75. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/evolution_exporter.py +0 -0
  76. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/flow_constants.py +0 -0
  77. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/flow_exporter.py +0 -0
  78. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/flow_renderer.py +0 -0
  79. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/html_dashboard.py +0 -0
  80. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/json_exporter.py +0 -0
  81. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/llm_exporter.py +0 -0
  82. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/mermaid_exporter.py +0 -0
  83. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/toon/helpers.py +0 -0
  84. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/toon/module_detail.py +0 -0
  85. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/toon/renderer.py +0 -0
  86. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/toon.py +0 -0
  87. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/toon_view.py +0 -0
  88. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/validate_project.py +0 -0
  89. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/exporters/yaml_exporter.py +0 -0
  90. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/generators/__init__.py +0 -0
  91. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/generators/llm_flow.py +0 -0
  92. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/generators/llm_task.py +0 -0
  93. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/generators/mermaid.py +0 -0
  94. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/nlp/config.py +0 -0
  95. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/nlp/entity_resolution.py +0 -0
  96. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/nlp/intent_matching.py +0 -0
  97. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/nlp/normalization.py +0 -0
  98. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/nlp/pipeline.py +0 -0
  99. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/patterns/__init__.py +0 -0
  100. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/patterns/detector.py +0 -0
  101. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/refactor/__init__.py +0 -0
  102. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm/refactor/prompt_engine.py +0 -0
  103. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm.egg-info/SOURCES.txt +0 -0
  104. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm.egg-info/dependency_links.txt +0 -0
  105. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm.egg-info/entry_points.txt +0 -0
  106. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm.egg-info/requires.txt +0 -0
  107. {code2llm-0.5.55 → code2llm-0.5.57}/code2llm.egg-info/top_level.txt +0 -0
  108. {code2llm-0.5.55 → code2llm-0.5.57}/setup.cfg +0 -0
  109. {code2llm-0.5.55 → code2llm-0.5.57}/setup.py +0 -0
  110. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_advanced_analysis.py +0 -0
  111. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_analyzer.py +0 -0
  112. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_deep_analysis.py +0 -0
  113. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_edge_cases.py +0 -0
  114. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_flow_exporter.py +0 -0
  115. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_multilanguage_e2e.py +0 -0
  116. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_nlp_pipeline.py +0 -0
  117. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_nonpython_cc_calls.py +0 -0
  118. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_pipeline_detector.py +0 -0
  119. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_prompt_engine.py +0 -0
  120. {code2llm-0.5.55 → code2llm-0.5.57}/tests/test_refactoring_engine.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code2llm
3
- Version: 0.5.55
3
+ Version: 0.5.57
4
4
  Summary: High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries
5
5
  Home-page: https://github.com/wronai/stts
6
6
  Author: STTS Project
@@ -60,7 +60,7 @@ When you run `code2llm ./ -f all`, the following files are created:
60
60
 
61
61
  | File | Format | Purpose | Key Insights |
62
62
  |------|--------|---------|--------------|
63
- | `analysis.toon` | **TOON** | **🔥 Health diagnostics** - Complexity, god modules, coupling | 68 critical functions, 0 god modules |
63
+ | `analysis.toon` | **TOON** | **🔥 Health diagnostics** - Health, LAYERS, COUPLING | 69 critical functions, 0 god modules |
64
64
 
65
65
  ### 🤖 LLM-Ready Documentation
66
66
 
@@ -144,8 +144,8 @@ cat evolution.toon
144
144
  grep "NEXT" evolution.toon
145
145
  ```
146
146
 
147
- ### `flow.toon` - Data Flow Analysis
148
- **Purpose**: Understand data movement through the system
147
+ ### `flow.toon` - Legacy Data Flow Analysis
148
+ **Purpose**: Understand data movement through the system (legacy / explicit opt-in)
149
149
  **Key sections**:
150
150
  - **PIPELINES**: Data processing chains
151
151
  - **CONTRACTS**: Function input/output contracts
@@ -160,12 +160,13 @@ grep "PIPELINES" flow.toon
160
160
  grep "SIDE_EFFECTS" flow.toon
161
161
  ```
162
162
 
163
- ### `map.toon` - Structural Map
164
- **Purpose**: High-level architecture overview
163
+ ### `map.toon` - Structural Map + Project Header
164
+ **Purpose**: High-level architecture overview plus compact project header
165
165
  **Key sections**:
166
166
  - **MODULES**: All modules with basic stats
167
167
  - **IMPORTS**: Dependency relationships
168
- - **SIGNATURES**: Public API functions
168
+ - **e:** Public API exports and signatures
169
+ - **HEADER**: Stats, alerts, hotspots, evolution trend
169
170
 
170
171
  **Example usage**:
171
172
  ```bash
@@ -173,17 +174,12 @@ grep "SIDE_EFFECTS" flow.toon
173
174
  cat map.toon | head -50
174
175
 
175
176
  # Find public APIs
176
- grep "SIGNATURES" map.toon
177
+ grep "^ e:" map.toon
177
178
  ```
178
179
 
179
- ### `project.toon` - Project Logic (Code2Logic)
180
+ ### `project.toon` - Legacy Project Logic (Deprecated)
180
181
  **Purpose**: Compact module view generated by code2logic integration
181
- **Key sections**:
182
- - **Modules list**: All project modules with file sizes
183
- - **Imports**: Dependency information
184
- - **Classes/Functions**: Summary counts
185
-
186
- **When to use**: When you need a lightweight project overview combined with code2llm analysis
182
+ **Status**: Deprecated — the lightweight project overview is now merged into `map.toon` header
187
183
 
188
184
  **Example usage**:
189
185
  ```bash
@@ -373,8 +369,8 @@ code2llm ./ -f yaml --separate-orphans
373
369
  ---
374
370
 
375
371
  **Generated by**: `code2llm ./ -f all --readme`
376
- **Analysis Date**: 2026-03-21
377
- **Total Functions**: 887
372
+ **Analysis Date**: 2026-03-25
373
+ **Total Functions**: 891
378
374
  **Total Classes**: 106
379
375
  **Modules**: 121
380
376
 
@@ -10,7 +10,7 @@ When you run `code2llm ./ -f all`, the following files are created:
10
10
 
11
11
  | File | Format | Purpose | Key Insights |
12
12
  |------|--------|---------|--------------|
13
- | `analysis.toon` | **TOON** | **🔥 Health diagnostics** - Complexity, god modules, coupling | 68 critical functions, 0 god modules |
13
+ | `analysis.toon` | **TOON** | **🔥 Health diagnostics** - Health, LAYERS, COUPLING | 69 critical functions, 0 god modules |
14
14
 
15
15
  ### 🤖 LLM-Ready Documentation
16
16
 
@@ -94,8 +94,8 @@ cat evolution.toon
94
94
  grep "NEXT" evolution.toon
95
95
  ```
96
96
 
97
- ### `flow.toon` - Data Flow Analysis
98
- **Purpose**: Understand data movement through the system
97
+ ### `flow.toon` - Legacy Data Flow Analysis
98
+ **Purpose**: Understand data movement through the system (legacy / explicit opt-in)
99
99
  **Key sections**:
100
100
  - **PIPELINES**: Data processing chains
101
101
  - **CONTRACTS**: Function input/output contracts
@@ -110,12 +110,13 @@ grep "PIPELINES" flow.toon
110
110
  grep "SIDE_EFFECTS" flow.toon
111
111
  ```
112
112
 
113
- ### `map.toon` - Structural Map
114
- **Purpose**: High-level architecture overview
113
+ ### `map.toon` - Structural Map + Project Header
114
+ **Purpose**: High-level architecture overview plus compact project header
115
115
  **Key sections**:
116
116
  - **MODULES**: All modules with basic stats
117
117
  - **IMPORTS**: Dependency relationships
118
- - **SIGNATURES**: Public API functions
118
+ - **e:** Public API exports and signatures
119
+ - **HEADER**: Stats, alerts, hotspots, evolution trend
119
120
 
120
121
  **Example usage**:
121
122
  ```bash
@@ -123,17 +124,12 @@ grep "SIDE_EFFECTS" flow.toon
123
124
  cat map.toon | head -50
124
125
 
125
126
  # Find public APIs
126
- grep "SIGNATURES" map.toon
127
+ grep "^ e:" map.toon
127
128
  ```
128
129
 
129
- ### `project.toon` - Project Logic (Code2Logic)
130
+ ### `project.toon` - Legacy Project Logic (Deprecated)
130
131
  **Purpose**: Compact module view generated by code2logic integration
131
- **Key sections**:
132
- - **Modules list**: All project modules with file sizes
133
- - **Imports**: Dependency information
134
- - **Classes/Functions**: Summary counts
135
-
136
- **When to use**: When you need a lightweight project overview combined with code2llm analysis
132
+ **Status**: Deprecated — the lightweight project overview is now merged into `map.toon` header
137
133
 
138
134
  **Example usage**:
139
135
  ```bash
@@ -323,8 +319,8 @@ code2llm ./ -f yaml --separate-orphans
323
319
  ---
324
320
 
325
321
  **Generated by**: `code2llm ./ -f all --readme`
326
- **Analysis Date**: 2026-03-21
327
- **Total Functions**: 887
322
+ **Analysis Date**: 2026-03-25
323
+ **Total Functions**: 891
328
324
  **Total Classes**: 106
329
325
  **Modules**: 121
330
326
 
@@ -8,7 +8,7 @@ Includes NLP Processing Pipeline for query normalization, intent matching,
8
8
  and entity resolution with multilingual support.
9
9
  """
10
10
 
11
- __version__ = "0.5.55"
11
+ __version__ = "0.5.57"
12
12
  __author__ = "STTS Project"
13
13
 
14
14
  # Core analysis components (lightweight, always needed)
@@ -24,7 +24,7 @@ def handle_report_command(args_list) -> int:
24
24
  """Generate views from an existing project.yaml.
25
25
 
26
26
  Usage:
27
- code2llm report --format toon # → project.toon
27
+ code2llm report --format toon # → project.toon (legacy)
28
28
  code2llm report --format context # → context.md
29
29
  code2llm report --format article # → status.md
30
30
  code2llm report --format html # → dashboard.html
@@ -1,4 +1,4 @@
1
- """Format export functions — toon, map, flow, context, yaml, json, mermaid, evolution, project-yaml."""
1
+ """Format export functions — toon, map, context, yaml, json, mermaid, evolution, and legacy project-yaml/flow exports."""
2
2
 
3
3
  import os
4
4
  import sys
@@ -101,7 +101,7 @@ def _export_simple_formats(args, result, output_dir: Path, formats):
101
101
  """Export toon, map, flow, context, yaml, json, project-yaml formats."""
102
102
  format_map = {
103
103
  'toon': ('analysis.toon', ToonExporter, 'TOON (diagnostics)'),
104
- 'map': ('map.toon', MapExporter, 'MAP (structure)'),
104
+ 'map': ('map.toon', MapExporter, 'MAP (structure + header)'),
105
105
  'flow': ('flow.toon', FlowExporter, 'FLOW (data-flow)'),
106
106
  'context': ('context.md', ContextExporter, 'CONTEXT (LLM narrative)'),
107
107
  }
@@ -25,7 +25,7 @@ def _run_exports(args, result, output_dir: Path, source_path: Optional[Path] = N
25
25
  """
26
26
  formats = [f.strip() for f in args.format.split(',')]
27
27
  if 'all' in formats:
28
- formats = ['toon', 'map', 'flow', 'context', 'code2logic', 'yaml', 'json', 'mermaid', 'evolution', 'project-yaml']
28
+ formats = ['toon', 'map', 'context', 'yaml', 'json', 'mermaid', 'evolution']
29
29
 
30
30
  is_chunked = args.chunk if hasattr(args, 'chunk') else False
31
31
 
@@ -78,9 +78,9 @@ def _get_prompt_paths(source_path: Optional[Path], output_dir: Path) -> Tuple[st
78
78
 
79
79
  _MAIN_FILES = [
80
80
  ('analysis.toon', 'Health diagnostics - complexity metrics, god modules, coupling issues, refactoring priorities'),
81
+ ('map.toon', 'Structural map - files, sizes, imports, exports, signatures, project header'),
81
82
  ('context.md', 'LLM narrative - architecture summary, key entry points, process flows, public API surface'),
82
83
  ('evolution.toon', 'Refactoring queue - ranked actions by impact/effort, risks, metrics targets, history'),
83
- ('project.toon', 'Project logic - compact module view from code2logic, file sizes, dependencies overview'),
84
84
  ('README.md', 'Documentation - complete guide to all generated files, usage examples, interpretation'),
85
85
  ]
86
86
 
@@ -121,7 +121,7 @@ def _format_size(size_bytes: int) -> str:
121
121
 
122
122
  def _get_missing_files(output_dir: Path) -> List[str]:
123
123
  """Return names of expected main files that are missing."""
124
- return [name for name, _ in _MAIN_FILES if name != 'project.toon' and not (output_dir / name).exists()]
124
+ return [name for name, _ in _MAIN_FILES if not (output_dir / name).exists()]
125
125
 
126
126
 
127
127
  def _build_subprojects_section(subprojects: list, output_dir: Path, output_rel_path: str) -> List[str]:
@@ -169,9 +169,9 @@ def _analyze_generated_files(output_dir: Path, subprojects: list = None) -> dict
169
169
  """Analyze which files were generated and determine appropriate focus areas."""
170
170
  analysis = {
171
171
  'has_analysis_toon': (output_dir / 'analysis.toon').exists(),
172
+ 'has_map_toon': (output_dir / 'map.toon').exists(),
172
173
  'has_context_md': (output_dir / 'context.md').exists(),
173
174
  'has_evolution_toon': (output_dir / 'evolution.toon').exists(),
174
- 'has_project_toon': (output_dir / 'project.toon').exists(),
175
175
  'has_readme': (output_dir / 'README.md').exists(),
176
176
  'has_yaml': (output_dir / 'analysis.yaml').exists(),
177
177
  'has_json': (output_dir / 'analysis.json').exists(),
@@ -194,15 +194,15 @@ def _build_dynamic_focus_areas(file_analysis: dict) -> List[str]:
194
194
 
195
195
  if file_analysis['has_analysis_toon']:
196
196
  focus_areas.append("1. **Code Health Analysis** - Review complexity metrics, god modules, coupling issues from analysis.toon")
197
+
198
+ if file_analysis['has_map_toon']:
199
+ focus_areas.append("2. **Structural Map** - Use map.toon to inspect imports, exports, signatures, and the project header")
197
200
 
198
201
  if file_analysis['has_evolution_toon']:
199
- focus_areas.append("2. **Refactoring Priorities** - Examine ranked refactoring actions and risk assessment from evolution.toon")
202
+ focus_areas.append("3. **Refactoring Priorities** - Examine ranked refactoring actions and risk assessment from evolution.toon")
200
203
 
201
204
  if file_analysis['has_context_md']:
202
- focus_areas.append("3. **Architecture Overview** - Understand main flows, entry points, and public API from context.md")
203
-
204
- if file_analysis['has_project_toon']:
205
- focus_areas.append("4. **Project Structure** - Analyze module organization and dependencies from project.toon")
205
+ focus_areas.append("4. **Architecture Overview** - Understand main flows, entry points, and public API from context.md")
206
206
 
207
207
  if file_analysis['has_yaml'] or file_analysis['has_json']:
208
208
  focus_areas.append("5. **Structured Data** - Use machine-readable formats for automated analysis and metrics extraction")
@@ -222,20 +222,23 @@ def _build_dynamic_focus_areas(file_analysis: dict) -> List[str]:
222
222
  def _build_dynamic_tasks(file_analysis: dict) -> List[str]:
223
223
  """Build tasks based on available files."""
224
224
  tasks = [
225
- "- Summarize the architecture and main flows.",
225
+ "- Summarize the architecture, main flows, and structural dependencies.",
226
226
  "- Identify the highest-risk areas and propose a refactoring plan.",
227
227
  "- If you suggest changes, keep behavior backward compatible and provide concrete steps.",
228
228
  ]
229
229
 
230
230
  if file_analysis['has_analysis_toon']:
231
- tasks.append("- Highlight critical functions (CC ≥ 10) and god modules from analysis.toon.")
231
+ tasks.append("- Highlight critical functions (CC ≥ 10) and top problem areas from analysis.toon.")
232
+
233
+ if file_analysis['has_map_toon']:
234
+ tasks.append("- Cross-check imports, exports, and signatures against map.toon before proposing splits.")
232
235
 
233
236
  if file_analysis['has_evolution_toon']:
234
237
  tasks.append("- Prioritize refactoring actions by impact/effort ratio from evolution.toon.")
235
238
 
236
239
  if file_analysis['has_context_md']:
237
240
  tasks.append("- Validate entry points and public API surface match the architecture described.")
238
-
241
+
239
242
  if file_analysis['is_chunked']:
240
243
  tasks.append("- Analyze cross-chunk dependencies and suggest consolidation strategies.")
241
244
 
@@ -267,12 +270,12 @@ def _build_prompt_footer(chunked: bool = False, file_analysis: dict = None) -> L
267
270
  if file_analysis['file_count'] > 0:
268
271
  lines.append("")
269
272
  lines.append("Analysis Strategy:")
270
- if file_analysis['has_analysis_toon'] and file_analysis['has_evolution_toon']:
271
- lines.append("- Start with analysis.toon for health metrics, then evolution.toon for action priorities")
273
+ if file_analysis['has_analysis_toon'] and file_analysis['has_map_toon']:
274
+ lines.append("- Start with analysis.toon for health metrics, then map.toon for structure and signatures")
275
+ if file_analysis['has_evolution_toon']:
276
+ lines.append("- Finish with evolution.toon for action priorities and next steps")
272
277
  elif file_analysis['has_context_md']:
273
278
  lines.append("- Use context.md as the primary reference for architectural understanding")
274
- elif file_analysis['has_project_toon']:
275
- lines.append("- Begin with project.toon for structural overview")
276
279
 
277
280
  if file_analysis['has_yaml']:
278
281
  lines.append("- Reference analysis.yaml for precise metrics and programmatic data")
@@ -14,10 +14,10 @@ def create_parser() -> argparse.ArgumentParser:
14
14
  epilog='''
15
15
  Examples:
16
16
  code2llm ./ # Default: TOON diagnostics + README
17
- code2llm ./ -f all -o ./docs # All formats to ./docs/
18
- code2llm ./ -f toon,map,flow # Diagnostics + structure + data-flow
17
+ code2llm ./ -f all -o ./docs # Core formats to ./docs/
18
+ code2llm ./ -f toon,map,evolution # Consolidated diagnostics + structure + roadmap
19
19
  code2llm ./ -f context # LLM narrative (context.md)
20
- code2llm ./ --streaming --strategy deep -f all # Deep streaming analysis, all outputs
20
+ code2llm ./ --streaming --strategy deep -f all # Deep streaming analysis, core outputs
21
21
  code2llm ./ --strategy quick -f toon # Fast overview
22
22
  code2llm ./ --refactor # AI refactoring prompts
23
23
  code2llm ./ --refactor --smell god_function # Filter by smell type
@@ -27,23 +27,23 @@ Examples:
27
27
  code2llm ./ -m static -v -o ./analysis # Static mode, verbose
28
28
  code2llm ./ --no-readme # Disable README generation
29
29
  code2llm ./ -f project-yaml # Unified project.yaml (single source of truth)
30
- code2llm report --format toon # Generate view from project.yaml
30
+ code2llm report --format toon # Generate legacy project.toon from project.yaml
31
31
  code2llm report --format all # All views from project.yaml
32
32
  code2llm llm-flow # Generate LLM flow summary
33
33
  code2llm llm-context ./ # Generate LLM context only
34
34
 
35
35
  Format Options (-f):
36
36
  toon — Health diagnostics (analysis.toon) [default]
37
- map — Structural map (map.toon) — modules, imports, signatures
38
- flow Data-flow analysis (flow.toon) — pipelines, contracts, types
37
+ map — Structural map (map.toon) — modules, imports, exports, signatures, project header
38
+ evolution Refactoring queue (evolution.toon)
39
39
  context — LLM narrative (context.md) — architecture summary
40
- code2logic — Generate project logic (project.toon) via external code2logic
41
40
  yaml — Standard YAML format
42
41
  json — Machine-readable JSON
43
42
  mermaid — Flowchart diagrams (flow.mmd, calls.mmd, compact_flow.mmd)
44
- evolution Refactoring queue (evolution.toon)
43
+ flow Data-flow analysis (flow.toon) — legacy, explicit opt-in
44
+ code2logic — Generate project logic (legacy project.toon) via external code2logic
45
45
  project-yaml — Unified project.yaml (single source of truth) + generated views
46
- all — Generate all formats (including project-yaml)
46
+ all — Generate core formats (analysis.toon, map.toon, evolution.toon, context, yaml, json, mermaid)
47
47
 
48
48
  Strategy Options (--strategy):
49
49
  quick — Fast overview, fewer files analyzed
@@ -2,7 +2,7 @@
2
2
 
3
3
  Available exporters:
4
4
  - ToonExporter → analysis.toon (health diagnostics)
5
- - MapExporter → project.map (structural map)
5
+ - MapExporter → map.toon (structural map + project header)
6
6
  - FlowExporter → flow.toon (data-flow: pipelines, contracts, types)
7
7
  - EvolutionExporter → evolution.toon (ranked refactoring queue)
8
8
  - ContextExporter → context.md (LLM narrative)
@@ -84,6 +84,9 @@ class IndexHTMLGenerator:
84
84
  # Limit size
85
85
  if len(content) > 100000:
86
86
  content = content[:100000] + '\n\n... [truncated - file too large]'
87
+ # Don't escape markdown - it will be rendered as HTML
88
+ if file_type == 'markdown':
89
+ return content
87
90
  return self._escape_html(content)
88
91
  return '[Binary file]'
89
92
  except Exception as e:
@@ -116,6 +119,7 @@ class IndexHTMLGenerator:
116
119
  <meta charset="UTF-8">
117
120
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
118
121
  <title>code2llm Analysis Results</title>
122
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
119
123
  <style>
120
124
  :root {{
121
125
  --bg: #0f172a;
@@ -418,6 +422,101 @@ class IndexHTMLGenerator:
418
422
  word-break: break-word;
419
423
  }}
420
424
 
425
+ /* Markdown rendered content styles */
426
+ .markdown-content {{
427
+ line-height: 1.6;
428
+ max-width: 100%;
429
+ }}
430
+
431
+ .markdown-content h1, .markdown-content h2, .markdown-content h3,
432
+ .markdown-content h4, .markdown-content h5, .markdown-content h6 {{
433
+ margin-top: 1.5rem;
434
+ margin-bottom: 0.75rem;
435
+ font-weight: 600;
436
+ line-height: 1.3;
437
+ }}
438
+
439
+ .markdown-content h1 {{ font-size: 1.75rem; border-bottom: 2px solid var(--border); padding-bottom: 0.5rem; }}
440
+ .markdown-content h2 {{ font-size: 1.5rem; border-bottom: 1px solid var(--border); padding-bottom: 0.4rem; }}
441
+ .markdown-content h3 {{ font-size: 1.25rem; }}
442
+ .markdown-content h4 {{ font-size: 1.1rem; }}
443
+
444
+ .markdown-content p {{
445
+ margin-bottom: 1rem;
446
+ }}
447
+
448
+ .markdown-content ul, .markdown-content ol {{
449
+ margin-bottom: 1rem;
450
+ padding-left: 1.5rem;
451
+ }}
452
+
453
+ .markdown-content li {{
454
+ margin-bottom: 0.25rem;
455
+ }}
456
+
457
+ .markdown-content code {{
458
+ background: var(--surface);
459
+ padding: 0.2rem 0.4rem;
460
+ border-radius: 0.25rem;
461
+ font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
462
+ font-size: 0.875em;
463
+ }}
464
+
465
+ .markdown-content pre code {{
466
+ background: none;
467
+ padding: 0;
468
+ }}
469
+
470
+ .markdown-content blockquote {{
471
+ border-left: 4px solid var(--accent);
472
+ padding-left: 1rem;
473
+ margin-left: 0;
474
+ margin-bottom: 1rem;
475
+ color: var(--text-muted);
476
+ }}
477
+
478
+ .markdown-content table {{
479
+ border-collapse: collapse;
480
+ width: 100%;
481
+ margin-bottom: 1rem;
482
+ }}
483
+
484
+ .markdown-content th, .markdown-content td {{
485
+ border: 1px solid var(--border);
486
+ padding: 0.5rem 0.75rem;
487
+ text-align: left;
488
+ }}
489
+
490
+ .markdown-content th {{
491
+ background: var(--surface);
492
+ font-weight: 600;
493
+ }}
494
+
495
+ .markdown-content tr:nth-child(even) {{
496
+ background: var(--surface-hover);
497
+ }}
498
+
499
+ .markdown-content a {{
500
+ color: var(--accent);
501
+ text-decoration: none;
502
+ }}
503
+
504
+ .markdown-content a:hover {{
505
+ text-decoration: underline;
506
+ }}
507
+
508
+ .markdown-content img {{
509
+ max-width: 100%;
510
+ height: auto;
511
+ border-radius: 0.5rem;
512
+ }}
513
+
514
+ .markdown-content hr {{
515
+ border: none;
516
+ border-top: 1px solid var(--border);
517
+ margin: 1.5rem 0;
518
+ }}
519
+
421
520
  /* Mobile responsive */
422
521
  @media (max-width: 768px) {{
423
522
  .container {{
@@ -568,9 +667,12 @@ class IndexHTMLGenerator:
568
667
 
569
668
  // Content
570
669
  const body = document.getElementById('contentBody');
571
- if (file.type === 'markdown' || file.type === 'html') {{
572
- // For markdown, show formatted but also offer raw view
573
- body.innerHTML = `<pre>${{file.content}}</pre>`;
670
+ if (file.type === 'markdown') {{
671
+ // Render markdown as HTML using marked.js
672
+ body.innerHTML = `<div class="markdown-content">${{marked.parse(file.content)}}</div>`;
673
+ }} else if (file.type === 'html') {{
674
+ // For HTML files, show in iframe for safety
675
+ body.innerHTML = `<iframe src="${{file.rel_path}}" style="width:100%;height:100%;border:none;border-radius:0.5rem;"></iframe>`;
574
676
  }} else if (file.type === 'json') {{
575
677
  try {{
576
678
  const json = JSON.parse(file.content.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&'));
@@ -1,14 +1,16 @@
1
1
  """Map Exporter — generates map.toon (structural map).
2
2
 
3
- Produces a compact key:value format showing modules, imports, signatures,
4
- and type information. Formerly the project.toon format.
3
+ Produces a compact project header plus a key:value structural map showing
4
+ modules, imports, exports, and signatures.
5
5
 
6
6
  Purpose: "what exists and how it's connected"
7
- Format: M[] module list, D: details with i: imports, e: exports, signatures
7
+ Format: header summary + M[] module list, D: details with i: imports,
8
+ e: exports, signatures
8
9
  """
9
10
 
10
11
  from collections import defaultdict
11
12
  from datetime import datetime
13
+ import re
12
14
  from pathlib import Path
13
15
  from typing import Any, Dict, List, Optional, Set, Tuple
14
16
 
@@ -25,15 +27,16 @@ EXCLUDE_PATTERNS = {
25
27
 
26
28
 
27
29
  class MapExporter(Exporter):
28
- """Export to map.toon — structural map with modules, imports, signatures.
30
+ """Export to map.toon — structural map with a compact project header.
29
31
 
30
- Keys: M=modules, D=details, i=imports, c=classes, f=functions, m=methods
32
+ Keys: M=modules, D=details, i=imports, e=exports, c=classes, f=functions,
33
+ m=methods
31
34
  """
32
35
 
33
36
  def export(self, result: AnalysisResult, output_path: str, **kwargs) -> None:
34
37
  """Export analysis result to .map format."""
35
38
  lines: List[str] = []
36
- lines.extend(self._render_header(result))
39
+ lines.extend(self._render_header(result, output_path))
37
40
  lines.extend(self._render_module_list(result))
38
41
  lines.extend(self._render_details(result))
39
42
 
@@ -44,16 +47,32 @@ class MapExporter(Exporter):
44
47
  # ------------------------------------------------------------------
45
48
  # header
46
49
  # ------------------------------------------------------------------
47
- def _render_header(self, result: AnalysisResult) -> List[str]:
48
- nfiles = len(result.modules)
50
+ def _render_header(self, result: AnalysisResult, output_path: str) -> List[str]:
51
+ project_name = Path(result.project_path).name if result.project_path else "project"
49
52
  total_lines = self._count_total_lines(result)
50
53
  langs = self._detect_languages(result)
51
- lang_str = ",".join(f"{lang}:{count}" for lang, count in langs.items())
54
+ lang_str = ",".join(f"{lang}:{count}" for lang, count in langs.items()) or "unknown"
55
+
56
+ included_files = [mi for mi in result.modules.values() if not self._is_excluded(mi.file)]
57
+ included_funcs = [fi for fi in result.functions.values() if not self._is_excluded(fi.file)]
58
+ included_classes = [ci for ci in result.classes.values() if not self._is_excluded(ci.file)]
59
+
60
+ cc_scores = [fi.complexity.get("cyclomatic_complexity", 0) for fi in included_funcs]
61
+ avg_cc = round(sum(cc_scores) / len(cc_scores), 1) if cc_scores else 0.0
62
+ critical_count = len([cc for cc in cc_scores if cc >= 15])
63
+ cycles = len(result.metrics.get("project", {}).get("circular_dependencies", []))
64
+
65
+ alerts = self._build_alerts(included_funcs)
66
+ hotspots = self._build_hotspots(included_funcs)
67
+ trend = self._load_evolution_trend(Path(output_path).with_name("evolution.toon"), avg_cc)
52
68
 
53
69
  lines = [
54
- f"# {Path(result.project_path).name if result.project_path else 'project'}"
55
- f" | {nfiles}f {total_lines}L | {lang_str}",
56
- "# Keys: M=modules, D=details, i=imports, c=classes, f=functions, m=methods",
70
+ f"# {project_name} | {len(included_files)}f {total_lines}L | {lang_str} | {datetime.now().strftime('%Y-%m-%d')}",
71
+ f"# stats: {len(included_funcs)} func | {len(included_classes)} cls | {len(included_files)} mod | CC̄={avg_cc} | critical:{critical_count} | cycles:{cycles}",
72
+ f"# alerts[{len(alerts)}]: {'; '.join(alerts) if alerts else 'none'}",
73
+ f"# hotspots[{len(hotspots)}]: {'; '.join(hotspots) if hotspots else 'none'}",
74
+ f"# evolution: {trend}",
75
+ "# Keys: M=modules, D=details, i=imports, e=exports, c=classes, f=functions, m=methods",
57
76
  ]
58
77
  return lines
59
78
 
@@ -235,3 +254,73 @@ class MapExporter(Exporter):
235
254
  if ext:
236
255
  langs[ext.lstrip('.')] += 1
237
256
  return dict(langs)
257
+
258
+ @staticmethod
259
+ def _build_alerts(funcs: List[FunctionInfo]) -> List[str]:
260
+ """Build a compact list of top alerts for the header."""
261
+ alerts: List[Tuple[int, int, str]] = []
262
+ for fi in funcs:
263
+ display = fi.name if not fi.class_name else f"{fi.class_name}.{fi.name}"
264
+ cc = fi.complexity.get("cyclomatic_complexity", 0)
265
+ if cc >= 15:
266
+ severity = 0 if cc >= 25 else 1
267
+ alerts.append((severity, cc, f"CC {display}={cc}"))
268
+
269
+ fan_out = len(set(fi.calls))
270
+ if fan_out >= 10:
271
+ severity = 0 if fan_out >= 20 else 1
272
+ alerts.append((severity, fan_out, f"fan-out {display}={fan_out}"))
273
+
274
+ alerts.sort(key=lambda item: (item[0], -item[1], item[2]))
275
+ return [label for _, _, label in alerts[:5]]
276
+
277
+ @staticmethod
278
+ def _build_hotspots(funcs: List[FunctionInfo]) -> List[str]:
279
+ """Build a compact list of top fan-out hotspots for the header."""
280
+ spots: List[Tuple[int, str]] = []
281
+ for fi in funcs:
282
+ fan_out = len(set(fi.calls))
283
+ if fan_out >= 5:
284
+ display = fi.name if not fi.class_name else f"{fi.class_name}.{fi.name}"
285
+ spots.append((fan_out, f"{display} fan={fan_out}"))
286
+
287
+ spots.sort(key=lambda item: item[0], reverse=True)
288
+ return [label for _, label in spots[:5]]
289
+
290
+ @staticmethod
291
+ def _load_evolution_trend(evolution_path: Path, current_cc: float) -> str:
292
+ """Summarize the latest CC trend from the previous evolution.toon file."""
293
+ previous_cc = MapExporter._read_previous_cc_avg(evolution_path)
294
+ if previous_cc is None:
295
+ return "baseline"
296
+
297
+ delta = round(current_cc - previous_cc, 1)
298
+ if delta < 0:
299
+ direction = "improved"
300
+ elif delta > 0:
301
+ direction = "regressed"
302
+ else:
303
+ direction = "flat"
304
+
305
+ sign = "+" if delta > 0 else ""
306
+ return f"CC̄ {previous_cc:.1f}→{current_cc:.1f} ({direction} {sign}{delta:.1f})"
307
+
308
+ @staticmethod
309
+ def _read_previous_cc_avg(evolution_path: Path) -> Optional[float]:
310
+ """Read the previous CC average from an existing evolution.toon file."""
311
+ if not evolution_path.exists():
312
+ return None
313
+
314
+ try:
315
+ content = evolution_path.read_text(encoding="utf-8")
316
+ except Exception:
317
+ return None
318
+
319
+ for line in content.splitlines():
320
+ match = re.search(r"CC̄:\s*([0-9]+(?:\.[0-9]+)?)\s*→", line)
321
+ if match:
322
+ try:
323
+ return float(match.group(1))
324
+ except ValueError:
325
+ return None
326
+ return None
@@ -35,7 +35,7 @@ GOD_MODULE_LINES = 500
35
35
  class ProjectYAMLExporter(Exporter):
36
36
  """Export unified project.yaml — single source of truth for diagnostics.
37
37
 
38
- Combines data from analysis.toon, project.toon, context.md, and evolution.toon
38
+ Combines data from analysis.toon, map.toon, context.md, and evolution.toon
39
39
  into one machine-parseable YAML file.
40
40
  """
41
41