code2llm 0.5.141__tar.gz → 0.5.143__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.
- {code2llm-0.5.141/code2llm.egg-info → code2llm-0.5.143}/PKG-INFO +13 -10
- {code2llm-0.5.141 → code2llm-0.5.143}/README.md +12 -9
- code2llm-0.5.143/VERSION +1 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/__init__.py +1 -1
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/analyzer.py +45 -11
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/config.py +71 -2
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/file_analyzer.py +10 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/persistent_cache.py +127 -14
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/nlp/__init__.py +1 -1
- {code2llm-0.5.141 → code2llm-0.5.143/code2llm.egg-info}/PKG-INFO +13 -10
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm.egg-info/SOURCES.txt +3 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/pyproject.toml +1 -1
- code2llm-0.5.143/tests/test_cache_invalidation_e2e.py +113 -0
- code2llm-0.5.143/tests/test_declarative_collection.py +204 -0
- code2llm-0.5.143/tests/test_file_analyzer_tagging.py +69 -0
- code2llm-0.5.143/tests/test_persistent_cache.py +386 -0
- code2llm-0.5.141/VERSION +0 -1
- code2llm-0.5.141/tests/test_persistent_cache.py +0 -182
- {code2llm-0.5.141 → code2llm-0.5.143}/LICENSE +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/MANIFEST.in +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/__main__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/call_graph.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/cfg.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/coupling.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/data_analysis.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/dfg.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/pipeline_classifier.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/pipeline_detector.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/pipeline_resolver.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/side_effects.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/smells.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/type_inference.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/utils/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/analysis/utils/ast_helpers.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/api.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_analysis.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_commands.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_exports/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_exports/code2logic.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_exports/formats.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_exports/orchestrator.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_exports/orchestrator_chunked.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_exports/orchestrator_constants.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_exports/orchestrator_handlers.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_exports/prompt.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/cli_parser.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/ast_registry.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/export_pipeline.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/file_cache.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/file_filter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/gitignore.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/incremental.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/base.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/cpp.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/csharp.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/generic.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/go_lang.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/java.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/php.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/ruby.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/rust.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/ts_extractors.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/ts_parser.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/lang/typescript.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/large_repo.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/models.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/refactoring.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/repo_files.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/streaming/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/streaming/cache.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/streaming/incremental.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/streaming/prioritizer.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/streaming/scanner.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/streaming/strategies.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/streaming_analyzer.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/core/toon_size_manager.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/article_view.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/base.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/context_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/context_view.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/dashboard_data.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/dashboard_renderer.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/evolution/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/evolution/computation.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/evolution/constants.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/evolution/exclusion.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/evolution/render.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/evolution/yaml_export.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/evolution_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/flow_constants.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/flow_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/flow_renderer.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/html_dashboard.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/index_generator/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/index_generator/renderer.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/index_generator/scanner.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/index_generator.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/json_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/llm_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/map/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/map/alerts.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/map/details.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/map/header.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/map/module_list.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/map/utils.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/map/yaml_export.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/map_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid/calls.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid/classic.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid/compact.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid/flow_compact.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid/flow_detailed.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid/flow_full.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid/utils.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/mermaid_flow_helpers.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/project_yaml/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/project_yaml/constants.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/project_yaml/core.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/project_yaml/evolution.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/project_yaml/health.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/project_yaml/hotspots.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/project_yaml/modules.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/project_yaml_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/readme/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/readme/content.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/readme/files.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/readme/insights.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/readme/sections.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/readme_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/report_generators.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon/helpers.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon/metrics.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon/metrics_core.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon/metrics_duplicates.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon/metrics_health.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon/module_detail.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon/renderer.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/toon_view.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/validate_project.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/exporters/yaml_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/_utils.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/llm_flow/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/llm_flow/analysis.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/llm_flow/cli.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/llm_flow/generator.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/llm_flow/nodes.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/llm_flow/parsing.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/llm_flow/utils.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/llm_flow.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/llm_task.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/mermaid/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/mermaid/fix.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/mermaid/png.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/mermaid/validation.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/generators/mermaid.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/nlp/config.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/nlp/entity_resolution.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/nlp/intent_matching.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/nlp/normalization.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/nlp/pipeline.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/parsers/toon_parser.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/patterns/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/patterns/detector.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/refactor/__init__.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm/refactor/prompt_engine.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm.egg-info/dependency_links.txt +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm.egg-info/entry_points.txt +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm.egg-info/requires.txt +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/code2llm.egg-info/top_level.txt +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/setup.cfg +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/setup.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_advanced_analysis.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_analyzer.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_calls_toon_export.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_deep_analysis.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_edge_cases.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_flow_exporter.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_format_quality.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_multilanguage_e2e.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_nlp_pipeline.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_nonpython_cc_calls.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_orchestrator_cache_mtime.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_pipeline_detector.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_project_toon_export.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_prompt_engine.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_prompt_txt.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_refactoring_engine.py +0 -0
- {code2llm-0.5.141 → code2llm-0.5.143}/tests/test_toon_v2.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.143
|
|
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
|
|
@@ -67,16 +67,18 @@ Dynamic: requires-python
|
|
|
67
67
|
|
|
68
68
|
## AI Cost Tracking
|
|
69
69
|
|
|
70
|
-
     
|
|
71
|
+
  
|
|
72
72
|
|
|
73
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
74
|
-
- 👤 **Human dev:** ~$
|
|
73
|
+
- 🤖 **LLM usage:** $7.5000 (195 commits)
|
|
74
|
+
- 👤 **Human dev:** ~$6974 (69.7h @ $100/h, 30min dedup)
|
|
75
75
|
|
|
76
|
-
Generated on 2026-04-
|
|
76
|
+
Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
80
|
+
|
|
81
|
+
|
|
80
82
|
This directory contains the complete analysis of your project generated by `code2llm`. Each file serves a specific purpose for understanding, refactoring, and documenting your codebase.
|
|
81
83
|
|
|
82
84
|
## 📁 Generated Files Overview
|
|
@@ -88,6 +90,7 @@ When you run `code2llm ./ -f all`, the following files are created:
|
|
|
88
90
|
| File | Format | Purpose | Key Insights |
|
|
89
91
|
|------|--------|---------|--------------|
|
|
90
92
|
| `evolution.toon.yaml` | **YAML** | **📋 Refactoring queue** - Prioritized improvements | 0 refactoring actions needed |
|
|
93
|
+
| `map.toon.yaml` | **YAML** | **🗺️ Structural map + project header** - Modules, imports, exports, signatures, stats, alerts, hotspots, trend | Project architecture overview |
|
|
91
94
|
|
|
92
95
|
### 🤖 LLM-Ready Documentation
|
|
93
96
|
|
|
@@ -404,10 +407,10 @@ code2llm ./ -f yaml --separate-orphans
|
|
|
404
407
|
---
|
|
405
408
|
|
|
406
409
|
**Generated by**: `code2llm ./ -f all --readme`
|
|
407
|
-
**Analysis Date**: 2026-04-
|
|
408
|
-
**Total Functions**:
|
|
409
|
-
**Total Classes**:
|
|
410
|
-
**Modules**:
|
|
410
|
+
**Analysis Date**: 2026-04-21
|
|
411
|
+
**Total Functions**: 2150
|
|
412
|
+
**Total Classes**: 245
|
|
413
|
+
**Modules**: 369
|
|
411
414
|
|
|
412
415
|
For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
|
|
413
416
|
|
|
@@ -3,16 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
## AI Cost Tracking
|
|
5
5
|
|
|
6
|
-
     
|
|
7
|
+
  
|
|
8
8
|
|
|
9
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
10
|
-
- 👤 **Human dev:** ~$
|
|
9
|
+
- 🤖 **LLM usage:** $7.5000 (195 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$6974 (69.7h @ $100/h, 30min dedup)
|
|
11
11
|
|
|
12
|
-
Generated on 2026-04-
|
|
12
|
+
Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
+
|
|
17
|
+
|
|
16
18
|
This directory contains the complete analysis of your project generated by `code2llm`. Each file serves a specific purpose for understanding, refactoring, and documenting your codebase.
|
|
17
19
|
|
|
18
20
|
## 📁 Generated Files Overview
|
|
@@ -24,6 +26,7 @@ When you run `code2llm ./ -f all`, the following files are created:
|
|
|
24
26
|
| File | Format | Purpose | Key Insights |
|
|
25
27
|
|------|--------|---------|--------------|
|
|
26
28
|
| `evolution.toon.yaml` | **YAML** | **📋 Refactoring queue** - Prioritized improvements | 0 refactoring actions needed |
|
|
29
|
+
| `map.toon.yaml` | **YAML** | **🗺️ Structural map + project header** - Modules, imports, exports, signatures, stats, alerts, hotspots, trend | Project architecture overview |
|
|
27
30
|
|
|
28
31
|
### 🤖 LLM-Ready Documentation
|
|
29
32
|
|
|
@@ -340,10 +343,10 @@ code2llm ./ -f yaml --separate-orphans
|
|
|
340
343
|
---
|
|
341
344
|
|
|
342
345
|
**Generated by**: `code2llm ./ -f all --readme`
|
|
343
|
-
**Analysis Date**: 2026-04-
|
|
344
|
-
**Total Functions**:
|
|
345
|
-
**Total Classes**:
|
|
346
|
-
**Modules**:
|
|
346
|
+
**Analysis Date**: 2026-04-21
|
|
347
|
+
**Total Functions**: 2150
|
|
348
|
+
**Total Classes**: 245
|
|
349
|
+
**Modules**: 369
|
|
347
350
|
|
|
348
351
|
For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
|
|
349
352
|
|
code2llm-0.5.143/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.5.143
|
|
@@ -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.
|
|
11
|
+
__version__ = "0.5.143"
|
|
12
12
|
__author__ = "STTS Project"
|
|
13
13
|
|
|
14
14
|
# Core analysis components (lightweight, always needed)
|
|
@@ -16,7 +16,11 @@ except ImportError:
|
|
|
16
16
|
|
|
17
17
|
logger = logging.getLogger(__name__)
|
|
18
18
|
|
|
19
|
-
from .config import
|
|
19
|
+
from .config import (
|
|
20
|
+
Config, FAST_CONFIG, ALL_EXTENSIONS, ALL_FILENAMES,
|
|
21
|
+
LANGUAGE_EXTENSIONS, LANGUAGE_FILENAME_PREFIXES,
|
|
22
|
+
DEFAULT_PROGRESS_BAR_THRESHOLD,
|
|
23
|
+
)
|
|
20
24
|
from .models import AnalysisResult, FlowEdge, FlowNode, Pattern
|
|
21
25
|
from code2llm.analysis.call_graph import CallGraphExtractor
|
|
22
26
|
|
|
@@ -89,6 +93,11 @@ class ProjectAnalyzer:
|
|
|
89
93
|
pcache = PersistentCache(str(project_path))
|
|
90
94
|
file_paths = [fp for fp, _ in files]
|
|
91
95
|
changed_paths, cached_paths = pcache.get_changed_files(file_paths)
|
|
96
|
+
# Drop manifest entries for files that vanished since the last
|
|
97
|
+
# run. Without this the export-level cache key (derived from the
|
|
98
|
+
# manifest) wouldn't shrink on delete and stale exports could
|
|
99
|
+
# be re-used.
|
|
100
|
+
removed = pcache.prune_missing(file_paths)
|
|
92
101
|
path_to_module = dict(files)
|
|
93
102
|
cached_results: List[Dict] = []
|
|
94
103
|
for fp in cached_paths:
|
|
@@ -100,6 +109,12 @@ class ProjectAnalyzer:
|
|
|
100
109
|
files_to_analyze = [(fp, path_to_module[fp]) for fp in changed_paths]
|
|
101
110
|
if self.config.verbose:
|
|
102
111
|
print(f" - Persistent cache: {len(cached_results)} hits, {len(files_to_analyze)} to analyze")
|
|
112
|
+
if removed:
|
|
113
|
+
print(f" - Persistent cache: {len(removed)} stale entries pruned (deleted files)")
|
|
114
|
+
for rel in removed[:10]:
|
|
115
|
+
print(f" • {rel}")
|
|
116
|
+
if len(removed) > 10:
|
|
117
|
+
print(f" ... and {len(removed) - 10} more")
|
|
103
118
|
return pcache, cached_results, files_to_analyze
|
|
104
119
|
except Exception as exc:
|
|
105
120
|
logger.debug("PersistentCache init failed, falling back: %s", exc)
|
|
@@ -119,16 +134,23 @@ class ProjectAnalyzer:
|
|
|
119
134
|
files_to_analyze: List[Tuple[str, str]],
|
|
120
135
|
fresh_results: List[Dict],
|
|
121
136
|
) -> None:
|
|
122
|
-
"""Persist fresh analysis results to cache; no-op when pcache is None.
|
|
123
|
-
|
|
137
|
+
"""Persist fresh analysis results to cache; no-op when pcache is None.
|
|
138
|
+
|
|
139
|
+
Note: we always attempt to save — even without fresh_results — so
|
|
140
|
+
that manifest pruning of deleted files (done in
|
|
141
|
+
_load_from_persistent_cache) is persisted. save() is a cheap no-op
|
|
142
|
+
when nothing is dirty.
|
|
143
|
+
"""
|
|
144
|
+
if pcache is None:
|
|
124
145
|
return
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
146
|
+
if fresh_results:
|
|
147
|
+
path_to_result = {r.get('file', ''): r for r in fresh_results if r}
|
|
148
|
+
for fp, _ in files_to_analyze:
|
|
149
|
+
if fp in path_to_result:
|
|
150
|
+
try:
|
|
151
|
+
pcache.put_file_result(fp, path_to_result[fp])
|
|
152
|
+
except Exception as exc:
|
|
153
|
+
logger.debug("put_file_result failed: %s", exc)
|
|
132
154
|
try:
|
|
133
155
|
pcache.save()
|
|
134
156
|
except Exception as exc:
|
|
@@ -183,6 +205,10 @@ class ProjectAnalyzer:
|
|
|
183
205
|
"""
|
|
184
206
|
files = []
|
|
185
207
|
ext_set = set(ALL_EXTENSIONS) # O(1) lookup
|
|
208
|
+
# Filename lookup uses a case-insensitive set. We lowercase once
|
|
209
|
+
# here so the hot loop only does a single lower() per file.
|
|
210
|
+
filename_set_lower = frozenset(n.lower() for n in ALL_FILENAMES)
|
|
211
|
+
filename_prefixes_lower = tuple(p.lower() for p in LANGUAGE_FILENAME_PREFIXES)
|
|
186
212
|
init_names = frozenset({'__init__.py', 'index.js', 'index.ts', 'mod.rs', 'lib.rs'})
|
|
187
213
|
seen = set() # guard against duplicate paths (e.g. .h in both c and cpp lists)
|
|
188
214
|
project_str = str(project_path)
|
|
@@ -195,8 +221,16 @@ class ProjectAnalyzer:
|
|
|
195
221
|
]
|
|
196
222
|
|
|
197
223
|
for filename in filenames:
|
|
224
|
+
filename_lower = filename.lower()
|
|
198
225
|
suffix = os.path.splitext(filename)[1].lower()
|
|
199
|
-
|
|
226
|
+
# Accept by extension, well-known filename
|
|
227
|
+
# (Dockerfile, Makefile, Jenkinsfile, ...), or known
|
|
228
|
+
# prefix (Dockerfile.dev, Dockerfile.prod, Makefile.am).
|
|
229
|
+
if (
|
|
230
|
+
suffix not in ext_set
|
|
231
|
+
and filename_lower not in filename_set_lower
|
|
232
|
+
and not filename_lower.startswith(filename_prefixes_lower)
|
|
233
|
+
):
|
|
200
234
|
continue
|
|
201
235
|
|
|
202
236
|
file_str = os.path.join(dirpath, filename)
|
|
@@ -99,6 +99,12 @@ class FilterConfig:
|
|
|
99
99
|
"*_test.py", "test_*.py", "conftest.py",
|
|
100
100
|
"*/tests/*", "*/test/*",
|
|
101
101
|
"*demo_langs/invalid*",
|
|
102
|
+
# Lockfiles and generated artefacts — declarative but noisy and
|
|
103
|
+
# auto-generated, keep them out of the manifest by default.
|
|
104
|
+
"*package-lock.json", "*yarn.lock", "*pnpm-lock.yaml",
|
|
105
|
+
"*poetry.lock", "*Pipfile.lock", "*Cargo.lock", "*composer.lock",
|
|
106
|
+
"*.terraform.lock.hcl", "*.tfstate", "*.tfstate.backup",
|
|
107
|
+
"*.min.js", "*.min.css", "*.map",
|
|
102
108
|
])
|
|
103
109
|
include_patterns: List[str] = field(default_factory=list)
|
|
104
110
|
min_function_lines: int = 1
|
|
@@ -238,8 +244,71 @@ LANGUAGE_EXTENSIONS = {
|
|
|
238
244
|
'raku': ['.raku', '.rakumod'],
|
|
239
245
|
}
|
|
240
246
|
|
|
241
|
-
#
|
|
242
|
-
|
|
247
|
+
# Declarative / IaC / config / docs extensions.
|
|
248
|
+
# These are NOT analyzed for call graphs or CC — they're routed to the
|
|
249
|
+
# generic analyzer. The point is to include them in the content-addressed
|
|
250
|
+
# manifest so the export cache is invalidated when they change (e.g.
|
|
251
|
+
# editing Dockerfile, terraform .tf, k8s manifests, pyproject.toml,
|
|
252
|
+
# README.md, openapi.yaml, ...).
|
|
253
|
+
DECLARATIVE_EXTENSIONS = {
|
|
254
|
+
# Infrastructure as Code
|
|
255
|
+
'terraform': ['.tf', '.tfvars', '.hcl'],
|
|
256
|
+
'bicep': ['.bicep'],
|
|
257
|
+
'nix': ['.nix'],
|
|
258
|
+
# (K8s/Helm/Ansible/Pulumi/CloudFormation/docker-compose all use
|
|
259
|
+
# yaml/json, matched below.)
|
|
260
|
+
# Config / serialization
|
|
261
|
+
'yaml': ['.yaml', '.yml'],
|
|
262
|
+
'toml': ['.toml'],
|
|
263
|
+
'ini': ['.ini', '.cfg', '.conf', '.properties'],
|
|
264
|
+
'xml': ['.xml'],
|
|
265
|
+
'json_config': ['.json', '.json5', '.jsonc'],
|
|
266
|
+
'env': ['.env'],
|
|
267
|
+
# Schema / IDL
|
|
268
|
+
'proto': ['.proto'],
|
|
269
|
+
'graphql': ['.graphql', '.gql'],
|
|
270
|
+
'avro': ['.avsc'],
|
|
271
|
+
'prisma': ['.prisma'],
|
|
272
|
+
# Documentation
|
|
273
|
+
'markdown': ['.md', '.mdx', '.markdown'],
|
|
274
|
+
'rst': ['.rst'],
|
|
275
|
+
'asciidoc': ['.adoc', '.asciidoc'],
|
|
276
|
+
'text': ['.txt'],
|
|
277
|
+
# Project DSLs (user-specific, low-friction to include)
|
|
278
|
+
'dsl': ['.doql', '.dsl'],
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
# Declarative files matched by FILENAME (no extension, or compound names).
|
|
282
|
+
# Case-insensitive matched against os.path.basename().
|
|
283
|
+
LANGUAGE_FILENAMES = {
|
|
284
|
+
'dockerfile': ['Dockerfile', 'Containerfile'],
|
|
285
|
+
'makefile': ['Makefile', 'GNUmakefile', 'BSDmakefile'],
|
|
286
|
+
'jenkins': ['Jenkinsfile'],
|
|
287
|
+
'vagrant': ['Vagrantfile'],
|
|
288
|
+
'rakefile': ['Rakefile'],
|
|
289
|
+
'gemfile': ['Gemfile'],
|
|
290
|
+
'procfile': ['Procfile'],
|
|
291
|
+
'caddyfile': ['Caddyfile'],
|
|
292
|
+
'pipfile': ['Pipfile'],
|
|
293
|
+
'brewfile': ['Brewfile'],
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
# Filename PREFIXES that indicate a declarative file even with arbitrary
|
|
297
|
+
# suffix — e.g. `Dockerfile.dev`, `Dockerfile.prod`, `Makefile.am`.
|
|
298
|
+
# The match is case-insensitive against the basename; a '.' suffix is
|
|
299
|
+
# required so we don't accidentally match e.g. `Dockerfiles/`.
|
|
300
|
+
LANGUAGE_FILENAME_PREFIXES = ('Dockerfile.', 'Containerfile.', 'Makefile.')
|
|
301
|
+
|
|
302
|
+
# All supported extensions flat list (programming languages + declarative)
|
|
303
|
+
ALL_EXTENSIONS = (
|
|
304
|
+
[ext for exts in LANGUAGE_EXTENSIONS.values() for ext in exts]
|
|
305
|
+
+ [ext for exts in DECLARATIVE_EXTENSIONS.values() for ext in exts]
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# Flat set of recognised filenames (case-insensitive compare at collection time).
|
|
309
|
+
ALL_FILENAMES = frozenset(
|
|
310
|
+
name for names in LANGUAGE_FILENAMES.values() for name in names
|
|
311
|
+
)
|
|
243
312
|
|
|
244
313
|
# Node types
|
|
245
314
|
NODE_TYPES = {
|
|
@@ -65,6 +65,8 @@ class FileAnalyzer:
|
|
|
65
65
|
cached = self.cache.get_fast(file_path)
|
|
66
66
|
if cached:
|
|
67
67
|
self.stats['cache_hits'] += 1
|
|
68
|
+
if 'file' not in cached:
|
|
69
|
+
cached['file'] = file_path
|
|
68
70
|
return cached
|
|
69
71
|
|
|
70
72
|
ext = path.suffix.lower()
|
|
@@ -75,6 +77,14 @@ class FileAnalyzer:
|
|
|
75
77
|
|
|
76
78
|
result = self._route_to_language_analyzer(content, file_path, module_name, ext)
|
|
77
79
|
|
|
80
|
+
# Tag result with its source file so downstream callers
|
|
81
|
+
# (e.g. PersistentCache in ProjectAnalyzer._store_to_persistent_cache)
|
|
82
|
+
# can match results back to file paths. Without this, the persistent
|
|
83
|
+
# manifest never gets populated and the export-level cache key
|
|
84
|
+
# collapses to md5("{}")[:12], causing stale exports to be reused.
|
|
85
|
+
if result:
|
|
86
|
+
result['file'] = file_path
|
|
87
|
+
|
|
78
88
|
if self.cache and self.config.performance.enable_cache and result:
|
|
79
89
|
self.cache.put_fast(file_path, result)
|
|
80
90
|
|
|
@@ -36,27 +36,26 @@ VERSION = 2
|
|
|
36
36
|
_DEFAULT_ROOT = os.path.expanduser("~/.code2llm")
|
|
37
37
|
_MAX_CACHE_MB = 500
|
|
38
38
|
_GC_THRESHOLD = 0.8
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
_DEFAULT_TTL_DAYS = 1.0
|
|
40
|
+
# Opt-out via env var: CODE2LLM_AUTO_CLEANUP=0 disables automatic TTL-based
|
|
41
|
+
# cleanup on PersistentCache initialisation. Override TTL via
|
|
42
|
+
# CODE2LLM_CACHE_TTL_DAYS (accepts fractional days, e.g. "0.5").
|
|
43
|
+
_ENV_AUTO_CLEANUP = "CODE2LLM_AUTO_CLEANUP"
|
|
44
|
+
_ENV_TTL_DAYS = "CODE2LLM_CACHE_TTL_DAYS"
|
|
46
45
|
|
|
47
46
|
def _pack(obj: Any) -> bytes:
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
# Always pickle: analysis results contain dataclasses (ModuleInfo,
|
|
48
|
+
# FunctionInfo, ...) and graph objects that msgpack cannot serialize
|
|
49
|
+
# natively. Falling back to pickle unconditionally keeps the cache
|
|
50
|
+
# correct; the speed/size delta is negligible for our payloads.
|
|
50
51
|
return pickle.dumps(obj, protocol=4)
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
def _unpack(data: bytes) -> Any:
|
|
54
|
-
if _HAS_MSGPACK:
|
|
55
|
-
return _msgpack.unpackb(data, raw=False)
|
|
56
55
|
return pickle.loads(data)
|
|
57
56
|
|
|
58
57
|
|
|
59
|
-
_EXT = "
|
|
58
|
+
_EXT = "pkl"
|
|
60
59
|
|
|
61
60
|
|
|
62
61
|
class PersistentCache:
|
|
@@ -67,7 +66,13 @@ class PersistentCache:
|
|
|
67
66
|
safe because entries are immutable once written (content-addressed).
|
|
68
67
|
"""
|
|
69
68
|
|
|
70
|
-
def __init__(
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
project_dir: str,
|
|
72
|
+
cache_root: Optional[str] = None,
|
|
73
|
+
auto_cleanup: Optional[bool] = None,
|
|
74
|
+
ttl_days: Optional[float] = None,
|
|
75
|
+
):
|
|
71
76
|
self._project_dir = os.path.realpath(project_dir)
|
|
72
77
|
self._root = Path(cache_root or _DEFAULT_ROOT)
|
|
73
78
|
self._project_hash = hashlib.md5(
|
|
@@ -85,6 +90,21 @@ class PersistentCache:
|
|
|
85
90
|
self._manifest: Dict[str, Any] = self._load_manifest()
|
|
86
91
|
self._dirty = False
|
|
87
92
|
|
|
93
|
+
# Resolve cleanup policy: explicit arg > env var > default.
|
|
94
|
+
if auto_cleanup is None:
|
|
95
|
+
auto_cleanup = os.environ.get(_ENV_AUTO_CLEANUP, "1") != "0"
|
|
96
|
+
if ttl_days is None:
|
|
97
|
+
try:
|
|
98
|
+
ttl_days = float(os.environ.get(_ENV_TTL_DAYS, _DEFAULT_TTL_DAYS))
|
|
99
|
+
except ValueError:
|
|
100
|
+
ttl_days = _DEFAULT_TTL_DAYS
|
|
101
|
+
if auto_cleanup:
|
|
102
|
+
try:
|
|
103
|
+
self.auto_cleanup(ttl_days=ttl_days)
|
|
104
|
+
except Exception as exc:
|
|
105
|
+
# Never let cleanup errors break analysis.
|
|
106
|
+
logger.debug("auto_cleanup failed: %s", exc)
|
|
107
|
+
|
|
88
108
|
# ------------------------------------------------------------------
|
|
89
109
|
# File-level cache
|
|
90
110
|
# ------------------------------------------------------------------
|
|
@@ -167,12 +187,43 @@ class PersistentCache:
|
|
|
167
187
|
|
|
168
188
|
return changed, cached
|
|
169
189
|
|
|
190
|
+
def prune_missing(self, current_filepaths: List[str]) -> List[str]:
|
|
191
|
+
"""Remove manifest entries for files not present in *current_filepaths*.
|
|
192
|
+
|
|
193
|
+
Keeps the manifest in sync with the real project state so that a
|
|
194
|
+
deleted source file invalidates the export-level cache (the
|
|
195
|
+
per-file cache key is content-addressed, but the export-level cache
|
|
196
|
+
key is derived from the manifest and therefore must shrink when
|
|
197
|
+
files disappear).
|
|
198
|
+
|
|
199
|
+
Returns the list of relative paths that were removed.
|
|
200
|
+
"""
|
|
201
|
+
current_rel = {
|
|
202
|
+
os.path.relpath(fp, self._project_dir) for fp in current_filepaths
|
|
203
|
+
}
|
|
204
|
+
files_index = self._manifest["files"]
|
|
205
|
+
stale = [rel for rel in files_index if rel not in current_rel]
|
|
206
|
+
if not stale:
|
|
207
|
+
return []
|
|
208
|
+
for rel in stale:
|
|
209
|
+
files_index.pop(rel, None)
|
|
210
|
+
self._dirty = True
|
|
211
|
+
return stale
|
|
212
|
+
|
|
170
213
|
# ------------------------------------------------------------------
|
|
171
214
|
# Export-level cache
|
|
172
215
|
# ------------------------------------------------------------------
|
|
173
216
|
|
|
174
217
|
def get_export_cache_dir(self, config_dict: Dict) -> Optional[Path]:
|
|
175
|
-
"""Return path to a complete cached export, or None if stale/absent.
|
|
218
|
+
"""Return path to a complete cached export, or None if stale/absent.
|
|
219
|
+
|
|
220
|
+
Safety: when the per-file manifest is empty we cannot reliably key
|
|
221
|
+
the run (hash collapses to md5("{}")), so we refuse to return a
|
|
222
|
+
cached export. This avoids propagating stale content from an earlier
|
|
223
|
+
run after the per-file cache was cleared or never populated.
|
|
224
|
+
"""
|
|
225
|
+
if not self._manifest.get("files"):
|
|
226
|
+
return None
|
|
176
227
|
run_hash = self._compute_run_hash(config_dict)
|
|
177
228
|
export_dir = self._exports_dir / run_hash
|
|
178
229
|
if export_dir.exists() and (export_dir / "_complete").exists():
|
|
@@ -231,6 +282,68 @@ class PersistentCache:
|
|
|
231
282
|
except OSError:
|
|
232
283
|
return 0.0
|
|
233
284
|
|
|
285
|
+
def auto_cleanup(self, ttl_days: float = _DEFAULT_TTL_DAYS) -> Dict[str, int]:
|
|
286
|
+
"""Remove stale cache artefacts older than *ttl_days*.
|
|
287
|
+
|
|
288
|
+
Runs automatically on `__init__` (opt-out via env var
|
|
289
|
+
`CODE2LLM_AUTO_CLEANUP=0`). Prevents unbounded disk growth while
|
|
290
|
+
keeping content-addressed file cache entries that are still
|
|
291
|
+
referenced by the manifest.
|
|
292
|
+
|
|
293
|
+
What is removed:
|
|
294
|
+
- Export directories with a `_complete` stamp older than TTL,
|
|
295
|
+
or export dirs never marked complete whose mtime is older
|
|
296
|
+
than TTL (dead/abandoned runs).
|
|
297
|
+
- File-level cache entries (`files/*.pkl`) whose mtime is older
|
|
298
|
+
than TTL AND whose hash is no longer referenced by the
|
|
299
|
+
manifest (orphaned). Referenced entries are kept regardless
|
|
300
|
+
of age — they represent content still present in the project.
|
|
301
|
+
|
|
302
|
+
Returns a dict summary `{"exports": n, "files": n}` for logging.
|
|
303
|
+
"""
|
|
304
|
+
cutoff = time.time() - (ttl_days * 86400)
|
|
305
|
+
removed = {"exports": 0, "files": 0}
|
|
306
|
+
|
|
307
|
+
# 1) Stale exports (complete or abandoned)
|
|
308
|
+
if self._exports_dir.exists():
|
|
309
|
+
for export_dir in list(self._exports_dir.iterdir()):
|
|
310
|
+
if not export_dir.is_dir():
|
|
311
|
+
continue
|
|
312
|
+
complete = export_dir / "_complete"
|
|
313
|
+
try:
|
|
314
|
+
if complete.exists():
|
|
315
|
+
ts = float(complete.read_text())
|
|
316
|
+
else:
|
|
317
|
+
ts = export_dir.stat().st_mtime
|
|
318
|
+
if ts < cutoff:
|
|
319
|
+
shutil.rmtree(export_dir, ignore_errors=True)
|
|
320
|
+
removed["exports"] += 1
|
|
321
|
+
except (ValueError, OSError):
|
|
322
|
+
pass
|
|
323
|
+
|
|
324
|
+
# 2) Orphaned file-level entries older than TTL
|
|
325
|
+
known = {v.get("hash") for v in self._manifest.get("files", {}).values()}
|
|
326
|
+
if self._files_dir.exists():
|
|
327
|
+
for f in list(self._files_dir.iterdir()):
|
|
328
|
+
if not f.is_file():
|
|
329
|
+
continue
|
|
330
|
+
if f.stem in known:
|
|
331
|
+
continue # still referenced
|
|
332
|
+
try:
|
|
333
|
+
if f.stat().st_mtime < cutoff:
|
|
334
|
+
f.unlink()
|
|
335
|
+
removed["files"] += 1
|
|
336
|
+
except OSError:
|
|
337
|
+
pass
|
|
338
|
+
|
|
339
|
+
if removed["exports"] or removed["files"]:
|
|
340
|
+
logger.debug(
|
|
341
|
+
"auto_cleanup: removed %d exports, %d orphan file entries "
|
|
342
|
+
"(ttl=%.1fd, project=%s)",
|
|
343
|
+
removed["exports"], removed["files"], ttl_days, self._project_dir,
|
|
344
|
+
)
|
|
345
|
+
return removed
|
|
346
|
+
|
|
234
347
|
def gc(self, max_age_days: int = 30, max_size_mb: int = _MAX_CACHE_MB) -> int:
|
|
235
348
|
"""Remove stale exports and orphaned file entries.
|
|
236
349
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.143
|
|
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
|
|
@@ -67,16 +67,18 @@ Dynamic: requires-python
|
|
|
67
67
|
|
|
68
68
|
## AI Cost Tracking
|
|
69
69
|
|
|
70
|
-
     
|
|
71
|
+
  
|
|
72
72
|
|
|
73
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
74
|
-
- 👤 **Human dev:** ~$
|
|
73
|
+
- 🤖 **LLM usage:** $7.5000 (195 commits)
|
|
74
|
+
- 👤 **Human dev:** ~$6974 (69.7h @ $100/h, 30min dedup)
|
|
75
75
|
|
|
76
|
-
Generated on 2026-04-
|
|
76
|
+
Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
80
|
+
|
|
81
|
+
|
|
80
82
|
This directory contains the complete analysis of your project generated by `code2llm`. Each file serves a specific purpose for understanding, refactoring, and documenting your codebase.
|
|
81
83
|
|
|
82
84
|
## 📁 Generated Files Overview
|
|
@@ -88,6 +90,7 @@ When you run `code2llm ./ -f all`, the following files are created:
|
|
|
88
90
|
| File | Format | Purpose | Key Insights |
|
|
89
91
|
|------|--------|---------|--------------|
|
|
90
92
|
| `evolution.toon.yaml` | **YAML** | **📋 Refactoring queue** - Prioritized improvements | 0 refactoring actions needed |
|
|
93
|
+
| `map.toon.yaml` | **YAML** | **🗺️ Structural map + project header** - Modules, imports, exports, signatures, stats, alerts, hotspots, trend | Project architecture overview |
|
|
91
94
|
|
|
92
95
|
### 🤖 LLM-Ready Documentation
|
|
93
96
|
|
|
@@ -404,10 +407,10 @@ code2llm ./ -f yaml --separate-orphans
|
|
|
404
407
|
---
|
|
405
408
|
|
|
406
409
|
**Generated by**: `code2llm ./ -f all --readme`
|
|
407
|
-
**Analysis Date**: 2026-04-
|
|
408
|
-
**Total Functions**:
|
|
409
|
-
**Total Classes**:
|
|
410
|
-
**Modules**:
|
|
410
|
+
**Analysis Date**: 2026-04-21
|
|
411
|
+
**Total Functions**: 2150
|
|
412
|
+
**Total Classes**: 245
|
|
413
|
+
**Modules**: 369
|
|
411
414
|
|
|
412
415
|
For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
|
|
413
416
|
|
|
@@ -173,9 +173,12 @@ code2llm/refactor/__init__.py
|
|
|
173
173
|
code2llm/refactor/prompt_engine.py
|
|
174
174
|
tests/test_advanced_analysis.py
|
|
175
175
|
tests/test_analyzer.py
|
|
176
|
+
tests/test_cache_invalidation_e2e.py
|
|
176
177
|
tests/test_calls_toon_export.py
|
|
178
|
+
tests/test_declarative_collection.py
|
|
177
179
|
tests/test_deep_analysis.py
|
|
178
180
|
tests/test_edge_cases.py
|
|
181
|
+
tests/test_file_analyzer_tagging.py
|
|
179
182
|
tests/test_flow_exporter.py
|
|
180
183
|
tests/test_format_quality.py
|
|
181
184
|
tests/test_multilanguage_e2e.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code2llm"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.143"
|
|
8
8
|
description = "High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|