code2llm 0.5.151__tar.gz → 0.5.152__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.151/code2llm.egg-info → code2llm-0.5.152}/PKG-INFO +5 -5
- {code2llm-0.5.151 → code2llm-0.5.152}/README.md +4 -4
- code2llm-0.5.152/VERSION +1 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/__init__.py +1 -1
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_exports/orchestrator.py +12 -2
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/config.py +9 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/file_analyzer.py +4 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/file_filter.py +10 -1
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/gitignore.py +21 -17
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/generic.py +4 -1
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/models.py +2 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/repo_files.py +8 -1
- code2llm-0.5.152/code2llm/core/source_classifier.py +185 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/streaming/scanner.py +6 -1
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/nlp/__init__.py +1 -1
- {code2llm-0.5.151 → code2llm-0.5.152/code2llm.egg-info}/PKG-INFO +5 -5
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm.egg-info/SOURCES.txt +2 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/pyproject.toml +1 -1
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_declarative_collection.py +68 -0
- code2llm-0.5.152/tests/test_export_cache_flags.py +27 -0
- code2llm-0.5.151/VERSION +0 -1
- {code2llm-0.5.151 → code2llm-0.5.152}/LICENSE +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/MANIFEST.in +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/__main__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/call_graph.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/cfg.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/coupling.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/data_analysis.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/dfg.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/pipeline_classifier.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/pipeline_detector.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/pipeline_resolver.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/side_effects.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/smells.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/type_inference.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/utils/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/analysis/utils/ast_helpers.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/api.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_analysis.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_commands.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_exports/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_exports/code2logic.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_exports/formats.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_exports/orchestrator_chunked.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_exports/orchestrator_constants.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_exports/orchestrator_handlers.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_exports/prompt.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/cli_parser.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/analyzer.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/ast_registry.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/export_pipeline.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/file_cache.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/incremental.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/base.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/cpp.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/csharp.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/go_lang.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/java.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/php.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/ruby.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/rust.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/ts_extractors.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/ts_parser.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/lang/typescript.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/large_repo.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/persistent_cache.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/refactoring.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/streaming/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/streaming/cache.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/streaming/incremental.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/streaming/prioritizer.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/streaming/strategies.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/streaming_analyzer.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/core/toon_size_manager.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/article_view.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/base.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/context_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/context_view.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/dashboard_data.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/dashboard_renderer.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/evolution/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/evolution/computation.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/evolution/constants.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/evolution/exclusion.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/evolution/render.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/evolution/yaml_export.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/evolution_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/flow_constants.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/flow_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/flow_renderer.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/html_dashboard.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/index_generator/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/index_generator/renderer.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/index_generator/scanner.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/index_generator.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/json_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/llm_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/map/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/map/alerts.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/map/details.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/map/header.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/map/module_list.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/map/utils.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/map/yaml_export.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/map_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid/calls.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid/classic.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid/compact.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid/flow_compact.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid/flow_detailed.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid/flow_full.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid/utils.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/mermaid_flow_helpers.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/project_yaml/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/project_yaml/constants.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/project_yaml/core.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/project_yaml/evolution.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/project_yaml/health.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/project_yaml/hotspots.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/project_yaml/modules.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/project_yaml_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/readme/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/readme/content.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/readme/files.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/readme/insights.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/readme/sections.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/readme_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/report_generators.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon/helpers.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon/metrics.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon/metrics_core.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon/metrics_duplicates.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon/metrics_health.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon/module_detail.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon/renderer.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/toon_view.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/validate_project.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/exporters/yaml_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/_utils.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/llm_flow/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/llm_flow/analysis.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/llm_flow/cli.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/llm_flow/generator.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/llm_flow/nodes.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/llm_flow/parsing.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/llm_flow/utils.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/llm_flow.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/llm_task.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/mermaid/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/mermaid/fix.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/mermaid/png.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/mermaid/validation.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/generators/mermaid.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/nlp/config.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/nlp/entity_resolution.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/nlp/intent_matching.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/nlp/normalization.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/nlp/pipeline.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/parsers/toon_parser.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/patterns/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/patterns/detector.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/refactor/__init__.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm/refactor/prompt_engine.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm.egg-info/dependency_links.txt +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm.egg-info/entry_points.txt +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm.egg-info/requires.txt +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/code2llm.egg-info/top_level.txt +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/setup.cfg +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/setup.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_advanced_analysis.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_analyzer.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_cache_invalidation_e2e.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_calls_toon_export.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_deep_analysis.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_edge_cases.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_file_analyzer_tagging.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_flow_exporter.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_format_quality.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_multilanguage_e2e.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_nlp_pipeline.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_nonpython_cc_calls.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_orchestrator_cache_mtime.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_persistent_cache.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_pipeline_detector.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_project_toon_export.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_prompt_engine.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_prompt_txt.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/tests/test_refactoring_engine.py +0 -0
- {code2llm-0.5.151 → code2llm-0.5.152}/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.152
|
|
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
|
|
@@ -66,11 +66,11 @@ Dynamic: requires-python
|
|
|
66
66
|
|
|
67
67
|
## AI Cost Tracking
|
|
68
68
|
|
|
69
|
-
     
|
|
70
|
+
  
|
|
71
71
|
|
|
72
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
73
|
-
- 👤 **Human dev:** ~$
|
|
72
|
+
- 🤖 **LLM usage:** $7.5000 (204 commits)
|
|
73
|
+
- 👤 **Human dev:** ~$7584 (75.8h @ $100/h, 30min dedup)
|
|
74
74
|
|
|
75
75
|
Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
76
76
|
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## AI Cost Tracking
|
|
4
4
|
|
|
5
|
-
     
|
|
6
|
+
  
|
|
7
7
|
|
|
8
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
9
|
-
- 👤 **Human dev:** ~$
|
|
8
|
+
- 🤖 **LLM usage:** $7.5000 (204 commits)
|
|
9
|
+
- 👤 **Human dev:** ~$7584 (75.8h @ $100/h, 30min dedup)
|
|
10
10
|
|
|
11
11
|
Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
12
12
|
|
code2llm-0.5.152/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.5.152
|
|
@@ -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.152"
|
|
12
12
|
__author__ = "STTS Project"
|
|
13
13
|
|
|
14
14
|
# Core analysis components (lightweight, always needed)
|
|
@@ -85,6 +85,15 @@ def _show_dry_run_plan(formats: List[str], output_dir: Path, is_chunked: bool, r
|
|
|
85
85
|
print(f"\n✅ Dry-run complete. Use without --dry-run to export.\n")
|
|
86
86
|
|
|
87
87
|
|
|
88
|
+
def _should_skip_export_cache(args, is_chunked: bool) -> bool:
|
|
89
|
+
"""Return True when this run must not read or write export cache."""
|
|
90
|
+
return (
|
|
91
|
+
is_chunked
|
|
92
|
+
or getattr(args, 'no_cache', False)
|
|
93
|
+
or getattr(args, 'force', False)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
88
97
|
def _run_exports(args, result, output_dir: Path, source_path: Optional[Path] = None):
|
|
89
98
|
"""Export analysis results in requested formats.
|
|
90
99
|
|
|
@@ -102,8 +111,9 @@ def _run_exports(args, result, output_dir: Path, source_path: Optional[Path] = N
|
|
|
102
111
|
_show_dry_run_plan(formats, output_dir, is_chunked, result)
|
|
103
112
|
return
|
|
104
113
|
|
|
105
|
-
# Skip cache for chunked or
|
|
106
|
-
|
|
114
|
+
# Skip cache for chunked runs or explicit cache bypass flags. --force is
|
|
115
|
+
# documented as a --no-cache alias, so it must bypass export cache too.
|
|
116
|
+
skip_cache = _should_skip_export_cache(args, is_chunked)
|
|
107
117
|
|
|
108
118
|
if not skip_cache and source_path:
|
|
109
119
|
cache = PersistentCache(str(source_path))
|
|
@@ -119,6 +119,15 @@ class FilterConfig:
|
|
|
119
119
|
"*poetry.lock", "*Pipfile.lock", "*Cargo.lock", "*composer.lock",
|
|
120
120
|
"*.terraform.lock.hcl", "*.tfstate", "*.tfstate.backup",
|
|
121
121
|
"*.min.js", "*.min.css", "*.map",
|
|
122
|
+
# code2llm / analysis artefacts. These are useful outputs, but feeding
|
|
123
|
+
# them back into the next run makes reports rank generated files above
|
|
124
|
+
# real source files.
|
|
125
|
+
"*analysis.toon*", "*map.toon.yaml", "*evolution.toon*",
|
|
126
|
+
"*validation.toon.yaml", "*duplication.toon.yaml",
|
|
127
|
+
"*project.toon*", "*calls.yaml", "*calls.toon.yaml", "*calls.mmd",
|
|
128
|
+
"*compact_flow.mmd", "*flow.mmd", "*flow_detailed.mmd",
|
|
129
|
+
"*flow_full.mmd", "*mermaid.export", "*defscan-*.md",
|
|
130
|
+
"*SUMD.md", "*SUMR.md",
|
|
122
131
|
])
|
|
123
132
|
include_patterns: List[str] = field(default_factory=list)
|
|
124
133
|
min_function_lines: int = 1
|
|
@@ -11,6 +11,7 @@ from .models import ClassInfo, FlowEdge, FlowNode, FunctionInfo, ModuleInfo
|
|
|
11
11
|
from code2llm.analysis.dfg import DFGExtractor
|
|
12
12
|
from code2llm.analysis.call_graph import CallGraphExtractor
|
|
13
13
|
from .file_filter import FastFileFilter
|
|
14
|
+
from .source_classifier import classify_source_path
|
|
14
15
|
from .lang import (
|
|
15
16
|
analyze_typescript_js, analyze_go, analyze_rust, analyze_java,
|
|
16
17
|
analyze_cpp, analyze_csharp, analyze_php, analyze_ruby, analyze_generic,
|
|
@@ -76,6 +77,9 @@ class FileAnalyzer:
|
|
|
76
77
|
return {}
|
|
77
78
|
|
|
78
79
|
result = self._route_to_language_analyzer(content, file_path, module_name, ext)
|
|
80
|
+
if result and result.get('module'):
|
|
81
|
+
result['module'].line_count = len(content.splitlines())
|
|
82
|
+
result['module'].source_kind = classify_source_path(file_path)
|
|
79
83
|
|
|
80
84
|
# Tag result with its source file so downstream callers
|
|
81
85
|
# (e.g. PersistentCache in ProjectAnalyzer._store_to_persistent_cache)
|
|
@@ -5,6 +5,11 @@ import re
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from .config import FilterConfig
|
|
7
7
|
from .gitignore import load_gitignore_patterns
|
|
8
|
+
from .source_classifier import (
|
|
9
|
+
ARCHIVE_DIR_NAMES,
|
|
10
|
+
GENERATED_OUTPUT_DIR_NAMES,
|
|
11
|
+
is_generated_artifact,
|
|
12
|
+
)
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
_SKIP_DIR_NAMES = frozenset({
|
|
@@ -19,13 +24,14 @@ _SKIP_DIR_NAMES = frozenset({
|
|
|
19
24
|
'lib', 'lib64', 'site-packages', 'include', 'bin', 'share',
|
|
20
25
|
'.code2llm_cache',
|
|
21
26
|
'tests', 'test',
|
|
27
|
+
'coverage', '.nyc_output',
|
|
22
28
|
# Backup and auto-generated directories that often contain venvs
|
|
23
29
|
'.algitex', '.backup', 'backups', '.bak', 'bak',
|
|
24
30
|
# Additional venv patterns
|
|
25
31
|
'virtualenv', '.virtualenv', 'envs', '.envs', 'venv-', '.venv-',
|
|
26
32
|
# CI/CD and deployment artifacts
|
|
27
33
|
'.terraform', '.serverless', '.netlify', '.vercel',
|
|
28
|
-
})
|
|
34
|
+
}) | ARCHIVE_DIR_NAMES | GENERATED_OUTPUT_DIR_NAMES
|
|
29
35
|
|
|
30
36
|
|
|
31
37
|
class FastFileFilter:
|
|
@@ -99,6 +105,9 @@ class FastFileFilter:
|
|
|
99
105
|
path_lower = file_path.lower()
|
|
100
106
|
basename_lower = Path(file_path).name.lower()
|
|
101
107
|
|
|
108
|
+
if is_generated_artifact(file_path, self.project_path):
|
|
109
|
+
return False
|
|
110
|
+
|
|
102
111
|
return (
|
|
103
112
|
self._passes_gitignore(file_path) and
|
|
104
113
|
self._passes_excludes(path_lower, basename_lower) and
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Gitignore support for code2llm file filtering."""
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import List
|
|
4
|
+
from typing import Iterable, List
|
|
5
5
|
import re
|
|
6
6
|
|
|
7
7
|
|
|
@@ -118,21 +118,25 @@ class GitIgnoreParser:
|
|
|
118
118
|
return ignored
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
def
|
|
122
|
-
"""
|
|
123
|
-
|
|
124
|
-
Searches up the directory tree from project_path until it finds a .gitignore file
|
|
125
|
-
or reaches the filesystem root. This ensures that gitignore rules are properly applied
|
|
126
|
-
even when analyzing subdirectories of a larger project.
|
|
127
|
-
"""
|
|
121
|
+
def _nearest_ignore_files(project_path: Path, names: Iterable[str]) -> List[Path]:
|
|
122
|
+
"""Find nearest ignore files while walking upward from project_path."""
|
|
128
123
|
current_path = project_path.resolve()
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return GitIgnoreParser(gitignore_path)
|
|
124
|
+
while current_path != current_path.parent:
|
|
125
|
+
found = [current_path / name for name in names if (current_path / name).exists()]
|
|
126
|
+
if found:
|
|
127
|
+
return found
|
|
134
128
|
current_path = current_path.parent
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
129
|
+
return [current_path / name for name in names if (current_path / name).exists()]
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def load_gitignore_patterns(project_path: Path) -> GitIgnoreParser:
|
|
133
|
+
"""Load .gitignore and .code2llmignore patterns from the nearest parent.
|
|
134
|
+
|
|
135
|
+
.code2llmignore is loaded after .gitignore so project-specific analysis
|
|
136
|
+
rules can add exclusions or negations without changing version-control
|
|
137
|
+
ignores.
|
|
138
|
+
"""
|
|
139
|
+
parser = GitIgnoreParser()
|
|
140
|
+
for ignore_path in _nearest_ignore_files(project_path, ('.gitignore', '.code2llmignore')):
|
|
141
|
+
parser._load_gitignore(ignore_path)
|
|
142
|
+
return parser
|
|
@@ -4,6 +4,7 @@ import re
|
|
|
4
4
|
from typing import Dict
|
|
5
5
|
|
|
6
6
|
from code2llm.core.models import ClassInfo, FunctionInfo, ModuleInfo
|
|
7
|
+
from code2llm.core.source_classifier import is_structural_only_file
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def analyze_generic(content: str, file_path: str, module_name: str,
|
|
@@ -19,7 +20,9 @@ def analyze_generic(content: str, file_path: str, module_name: str,
|
|
|
19
20
|
|
|
20
21
|
# Count lines as basic metric
|
|
21
22
|
lines = content.split('\n')
|
|
22
|
-
|
|
23
|
+
if is_structural_only_file(file_path):
|
|
24
|
+
stats['files_processed'] += 1
|
|
25
|
+
return result
|
|
23
26
|
|
|
24
27
|
# Try to detect function-like patterns
|
|
25
28
|
func_patterns = [
|
|
@@ -100,6 +100,8 @@ class ModuleInfo(BaseModel):
|
|
|
100
100
|
name: str
|
|
101
101
|
file: str
|
|
102
102
|
is_package: bool = False
|
|
103
|
+
source_kind: str = "source"
|
|
104
|
+
line_count: int = 0
|
|
103
105
|
imports: List[str] = field(default_factory=list)
|
|
104
106
|
functions: List[str] = field(default_factory=list)
|
|
105
107
|
classes: List[str] = field(default_factory=list)
|
|
@@ -5,6 +5,11 @@ from typing import List, Tuple, Optional
|
|
|
5
5
|
|
|
6
6
|
from functools import lru_cache
|
|
7
7
|
from .gitignore import load_gitignore_patterns, GitIgnoreParser
|
|
8
|
+
from .source_classifier import (
|
|
9
|
+
ARCHIVE_DIR_NAMES,
|
|
10
|
+
GENERATED_OUTPUT_DIR_NAMES,
|
|
11
|
+
is_generated_artifact,
|
|
12
|
+
)
|
|
8
13
|
|
|
9
14
|
# Directories to skip during analysis
|
|
10
15
|
SKIP_DIRS = {
|
|
@@ -14,7 +19,7 @@ SKIP_DIRS = {
|
|
|
14
19
|
'build', 'dist', 'egg-info', '.eggs',
|
|
15
20
|
'htmlcov', '.coverage', '.cache',
|
|
16
21
|
'lib', 'lib64', 'site-packages', 'include', 'bin', 'share', # venv internals
|
|
17
|
-
}
|
|
22
|
+
} | ARCHIVE_DIR_NAMES | GENERATED_OUTPUT_DIR_NAMES
|
|
18
23
|
|
|
19
24
|
# Patterns that indicate a file should be skipped
|
|
20
25
|
SKIP_PATTERNS = [
|
|
@@ -42,6 +47,8 @@ def should_skip_file(file_str: str, project_path: Optional[Path] = None,
|
|
|
42
47
|
lower_path = file_str.lower()
|
|
43
48
|
if any(pattern in lower_path for pattern in SKIP_PATTERNS):
|
|
44
49
|
return True
|
|
50
|
+
if is_generated_artifact(file_str, project_path):
|
|
51
|
+
return True
|
|
45
52
|
|
|
46
53
|
# Check gitignore if parser provided
|
|
47
54
|
if gitignore_parser and project_path:
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""Source path classification and default noise filtering.
|
|
2
|
+
|
|
3
|
+
The analyzer intentionally tracks some non-code files so export caches are
|
|
4
|
+
invalidated when project manifests or docs change. Those files should not be
|
|
5
|
+
treated the same as production source, and generated code2llm artefacts should
|
|
6
|
+
not be fed back into the next analysis run.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
CODE_EXTENSIONS = {
|
|
16
|
+
".py", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".go", ".rs",
|
|
17
|
+
".java", ".cpp", ".cc", ".cxx", ".hpp", ".hh", ".h", ".c", ".cs",
|
|
18
|
+
".rb", ".rbw", ".php", ".swift", ".kt", ".kts", ".scala", ".r",
|
|
19
|
+
".m", ".sh", ".bash", ".zsh", ".dart", ".ex", ".exs", ".clj",
|
|
20
|
+
".cljs", ".hs", ".lua", ".pl", ".pm", ".raku", ".rakumod",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
DOC_EXTENSIONS = {".md", ".mdx", ".markdown", ".rst", ".adoc", ".asciidoc", ".txt"}
|
|
24
|
+
|
|
25
|
+
STRUCTURAL_ONLY_EXTENSIONS = {
|
|
26
|
+
".yaml", ".yml", ".toml", ".ini", ".cfg", ".conf", ".properties",
|
|
27
|
+
".xml", ".json", ".json5", ".jsonc", ".env", ".proto", ".graphql",
|
|
28
|
+
".gql", ".avsc", ".prisma", ".tf", ".tfvars", ".hcl", ".bicep",
|
|
29
|
+
".nix",
|
|
30
|
+
*DOC_EXTENSIONS,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
ARCHIVE_DIR_NAMES = frozenset({
|
|
34
|
+
"_archive", "archive", "archives", "_archives", "legacy", "old",
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
GENERATED_OUTPUT_DIR_NAMES = frozenset({
|
|
38
|
+
".code2llm_cache",
|
|
39
|
+
"code2llm_output",
|
|
40
|
+
"output_toon",
|
|
41
|
+
"output_all",
|
|
42
|
+
"output_comparison",
|
|
43
|
+
"output_modes",
|
|
44
|
+
"analysis_all",
|
|
45
|
+
"compare",
|
|
46
|
+
"calls_output",
|
|
47
|
+
"refactor_output",
|
|
48
|
+
"playwright-report",
|
|
49
|
+
"test-results",
|
|
50
|
+
"html-report",
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
GENERATED_EXACT_FILENAMES = frozenset({
|
|
54
|
+
"analysis.toon",
|
|
55
|
+
"analysis.toon.yaml",
|
|
56
|
+
"analysis_toon.yaml",
|
|
57
|
+
".code2llm_incremental.json",
|
|
58
|
+
"map.toon",
|
|
59
|
+
"map.toon.yaml",
|
|
60
|
+
"evolution.toon",
|
|
61
|
+
"evolution.toon.yaml",
|
|
62
|
+
"validation.toon.yaml",
|
|
63
|
+
"duplication.toon.yaml",
|
|
64
|
+
"calls.toon.yaml",
|
|
65
|
+
"calls.yaml",
|
|
66
|
+
"calls.mmd",
|
|
67
|
+
"compact_flow.mmd",
|
|
68
|
+
"flow.mmd",
|
|
69
|
+
"flow_detailed.mmd",
|
|
70
|
+
"flow_full.mmd",
|
|
71
|
+
"mermaid.export",
|
|
72
|
+
"project.toon",
|
|
73
|
+
"project.toon.yaml",
|
|
74
|
+
"project.toon.txt",
|
|
75
|
+
"defscan-classes-py.md",
|
|
76
|
+
"defscan-classes-ts.md",
|
|
77
|
+
"sumd.md",
|
|
78
|
+
"sumr.md",
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
GENERATED_PREFIXES = ("defscan-",)
|
|
82
|
+
|
|
83
|
+
GENERATED_SNIFF_FILENAMES = frozenset({
|
|
84
|
+
"context.md",
|
|
85
|
+
"readme.md",
|
|
86
|
+
"index.html",
|
|
87
|
+
"prompt.txt",
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
GENERATED_MARKERS = (
|
|
91
|
+
"generated by: `code2llm`",
|
|
92
|
+
"generated by code2llm",
|
|
93
|
+
"code2llm - generated analysis files",
|
|
94
|
+
"<title>code2llm analysis results</title>",
|
|
95
|
+
"# system architecture analysis\n<!-- generated",
|
|
96
|
+
"use the attached/generated files as the authoritative context.",
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _relative_parts(path: Path, project_root: Optional[Path]) -> tuple[str, ...]:
|
|
101
|
+
"""Return normalized relative path parts for classification."""
|
|
102
|
+
try:
|
|
103
|
+
if project_root:
|
|
104
|
+
rel = path.resolve().relative_to(project_root.resolve())
|
|
105
|
+
else:
|
|
106
|
+
rel = path
|
|
107
|
+
except (OSError, ValueError, RuntimeError):
|
|
108
|
+
rel = path
|
|
109
|
+
return tuple(part.lower() for part in rel.parts)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _looks_like_generated_content(path: Path) -> bool:
|
|
113
|
+
"""Cheap content sniff for generic generated filenames such as README.md."""
|
|
114
|
+
try:
|
|
115
|
+
text = path.read_text(encoding="utf-8", errors="ignore")[:4096].lower()
|
|
116
|
+
except (OSError, UnicodeDecodeError):
|
|
117
|
+
return False
|
|
118
|
+
return any(marker in text for marker in GENERATED_MARKERS)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _has_code2llm_output_manifest(path: Path) -> bool:
|
|
122
|
+
"""Return True if a directory looks like a code2llm output folder."""
|
|
123
|
+
return (
|
|
124
|
+
(path / "analysis.toon.yaml").exists()
|
|
125
|
+
or (path / "analysis.toon").exists()
|
|
126
|
+
or (path / "map.toon.yaml").exists()
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def is_generated_artifact(path: str | Path, project_root: Optional[Path] = None) -> bool:
|
|
131
|
+
"""Return True when *path* is a generated analysis/report artefact."""
|
|
132
|
+
p = Path(path)
|
|
133
|
+
parts = _relative_parts(p, project_root)
|
|
134
|
+
if any(part in GENERATED_OUTPUT_DIR_NAMES for part in parts[:-1]):
|
|
135
|
+
return True
|
|
136
|
+
|
|
137
|
+
if project_root:
|
|
138
|
+
rel_parts = parts[:-1]
|
|
139
|
+
for idx, part in enumerate(rel_parts):
|
|
140
|
+
if part != "project":
|
|
141
|
+
continue
|
|
142
|
+
candidate = Path(project_root).joinpath(*parts[: idx + 1])
|
|
143
|
+
if _has_code2llm_output_manifest(candidate):
|
|
144
|
+
return True
|
|
145
|
+
|
|
146
|
+
name = p.name.lower()
|
|
147
|
+
if name in GENERATED_EXACT_FILENAMES:
|
|
148
|
+
return True
|
|
149
|
+
if any(name.startswith(prefix) for prefix in GENERATED_PREFIXES):
|
|
150
|
+
return True
|
|
151
|
+
if name in GENERATED_SNIFF_FILENAMES and _looks_like_generated_content(p):
|
|
152
|
+
return True
|
|
153
|
+
|
|
154
|
+
# The default code2llm output folder is commonly named "project". Avoid
|
|
155
|
+
# treating arbitrary project/ directories as generated unless the filename
|
|
156
|
+
# itself is a known code2llm artefact.
|
|
157
|
+
if "project" in parts[:-1] and name in GENERATED_EXACT_FILENAMES:
|
|
158
|
+
return True
|
|
159
|
+
|
|
160
|
+
return False
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def classify_source_path(path: str | Path, project_root: Optional[Path] = None) -> str:
|
|
164
|
+
"""Classify a path for reporting and filtering."""
|
|
165
|
+
p = Path(path)
|
|
166
|
+
parts = _relative_parts(p, project_root)
|
|
167
|
+
if is_generated_artifact(p, project_root):
|
|
168
|
+
return "generated"
|
|
169
|
+
if any(part in ARCHIVE_DIR_NAMES for part in parts[:-1]):
|
|
170
|
+
return "archive"
|
|
171
|
+
if any(part in {"tests", "test", "testing", "__tests__"} for part in parts[:-1]):
|
|
172
|
+
return "test"
|
|
173
|
+
ext = p.suffix.lower()
|
|
174
|
+
if ext in DOC_EXTENSIONS:
|
|
175
|
+
return "docs"
|
|
176
|
+
if ext in STRUCTURAL_ONLY_EXTENSIONS:
|
|
177
|
+
return "config"
|
|
178
|
+
if ext in CODE_EXTENSIONS:
|
|
179
|
+
return "source"
|
|
180
|
+
return "other"
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def is_structural_only_file(path: str | Path) -> bool:
|
|
184
|
+
"""Return True for tracked non-code text files that should emit no symbols."""
|
|
185
|
+
return Path(path).suffix.lower() in STRUCTURAL_ONLY_EXTENSIONS
|
|
@@ -5,6 +5,7 @@ from pathlib import Path
|
|
|
5
5
|
from typing import Dict, List, Optional, Tuple
|
|
6
6
|
|
|
7
7
|
from code2llm.core.models import ClassInfo, FlowNode, FunctionInfo, ModuleInfo
|
|
8
|
+
from code2llm.core.source_classifier import classify_source_path, is_generated_artifact
|
|
8
9
|
|
|
9
10
|
from .cache import StreamingFileCache
|
|
10
11
|
from .prioritizer import FilePriority
|
|
@@ -45,7 +46,9 @@ class StreamingScanner:
|
|
|
45
46
|
result = {
|
|
46
47
|
'module': ModuleInfo(
|
|
47
48
|
name=priority.module_name,
|
|
48
|
-
file=priority.file_path
|
|
49
|
+
file=priority.file_path,
|
|
50
|
+
source_kind=classify_source_path(priority.file_path),
|
|
51
|
+
line_count=len(content.splitlines()),
|
|
49
52
|
),
|
|
50
53
|
'functions': {},
|
|
51
54
|
'classes': {},
|
|
@@ -187,6 +190,8 @@ class StreamingScanner:
|
|
|
187
190
|
|
|
188
191
|
if any(x in file_str.lower() for x in ['__pycache__', '.venv', 'venv']):
|
|
189
192
|
continue
|
|
193
|
+
if is_generated_artifact(py_file, project_path):
|
|
194
|
+
continue
|
|
190
195
|
|
|
191
196
|
# Calculate module name
|
|
192
197
|
rel_path = py_file.relative_to(project_path)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.152
|
|
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
|
|
@@ -66,11 +66,11 @@ Dynamic: requires-python
|
|
|
66
66
|
|
|
67
67
|
## AI Cost Tracking
|
|
68
68
|
|
|
69
|
-
     
|
|
70
|
+
  
|
|
71
71
|
|
|
72
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
73
|
-
- 👤 **Human dev:** ~$
|
|
72
|
+
- 🤖 **LLM usage:** $7.5000 (204 commits)
|
|
73
|
+
- 👤 **Human dev:** ~$7584 (75.8h @ $100/h, 30min dedup)
|
|
74
74
|
|
|
75
75
|
Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
76
76
|
|
|
@@ -54,6 +54,7 @@ code2llm/core/models.py
|
|
|
54
54
|
code2llm/core/persistent_cache.py
|
|
55
55
|
code2llm/core/refactoring.py
|
|
56
56
|
code2llm/core/repo_files.py
|
|
57
|
+
code2llm/core/source_classifier.py
|
|
57
58
|
code2llm/core/streaming_analyzer.py
|
|
58
59
|
code2llm/core/toon_size_manager.py
|
|
59
60
|
code2llm/core/lang/__init__.py
|
|
@@ -178,6 +179,7 @@ tests/test_calls_toon_export.py
|
|
|
178
179
|
tests/test_declarative_collection.py
|
|
179
180
|
tests/test_deep_analysis.py
|
|
180
181
|
tests/test_edge_cases.py
|
|
182
|
+
tests/test_export_cache_flags.py
|
|
181
183
|
tests/test_file_analyzer_tagging.py
|
|
182
184
|
tests/test_flow_exporter.py
|
|
183
185
|
tests/test_format_quality.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.152"
|
|
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"
|
|
@@ -20,6 +20,7 @@ from code2llm.core.config import (
|
|
|
20
20
|
ALL_EXTENSIONS, ALL_FILENAMES, DECLARATIVE_EXTENSIONS, Config,
|
|
21
21
|
LANGUAGE_FILENAMES,
|
|
22
22
|
)
|
|
23
|
+
from code2llm.core.file_analyzer import FileAnalyzer
|
|
23
24
|
from code2llm.core.persistent_cache import PersistentCache
|
|
24
25
|
|
|
25
26
|
|
|
@@ -202,3 +203,70 @@ def test_lockfiles_excluded_by_default(iac_project, tmp_path):
|
|
|
202
203
|
assert "Cargo.lock" not in names
|
|
203
204
|
# But the non-lock package.json stays.
|
|
204
205
|
assert "package.json" in names
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def test_generated_analysis_artifacts_are_excluded_by_default(tmp_path):
|
|
209
|
+
"""code2llm outputs must not be fed back into the next analysis run."""
|
|
210
|
+
p = tmp_path / "proj"
|
|
211
|
+
p.mkdir()
|
|
212
|
+
(p / "app.py").write_text("def run():\n return 1\n")
|
|
213
|
+
out = p / "project"
|
|
214
|
+
out.mkdir()
|
|
215
|
+
(out / "analysis.toon.yaml").write_text("# code2llm\nHEALTH[0]: ok\n")
|
|
216
|
+
(out / "map.toon.yaml").write_text("# generated map\n")
|
|
217
|
+
(out / "index.html").write_text("<title>code2llm Analysis Results</title>\n")
|
|
218
|
+
batch = out / "batch_1"
|
|
219
|
+
batch.mkdir()
|
|
220
|
+
(batch / "context.md").write_text("# System Architecture Analysis\n<!-- generated in 0.01s -->\n")
|
|
221
|
+
(p / ".code2llm_incremental.json").write_text("{}\n")
|
|
222
|
+
(p / "SUMD.md").write_text("# generated summary\n")
|
|
223
|
+
(p / "defscan-classes-py.md").write_text("class Noise:\n pass\n")
|
|
224
|
+
|
|
225
|
+
cfg = Config()
|
|
226
|
+
cfg.performance.parallel_enabled = False
|
|
227
|
+
files = ProjectAnalyzer(cfg, p)._collect_files(p)
|
|
228
|
+
names = {str(Path(fp).relative_to(p)) for fp, _ in files}
|
|
229
|
+
|
|
230
|
+
assert "app.py" in names
|
|
231
|
+
assert "project/analysis.toon.yaml" not in names
|
|
232
|
+
assert "project/map.toon.yaml" not in names
|
|
233
|
+
assert "project/index.html" not in names
|
|
234
|
+
assert "project/batch_1/context.md" not in names
|
|
235
|
+
assert ".code2llm_incremental.json" not in names
|
|
236
|
+
assert "SUMD.md" not in names
|
|
237
|
+
assert "defscan-classes-py.md" not in names
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def test_code2llmignore_is_applied(tmp_path):
|
|
241
|
+
"""Project-local .code2llmignore should refine analysis scope."""
|
|
242
|
+
p = tmp_path / "proj"
|
|
243
|
+
p.mkdir()
|
|
244
|
+
(p / ".code2llmignore").write_text("docs/\n")
|
|
245
|
+
(p / "app.py").write_text("def run():\n return 1\n")
|
|
246
|
+
docs = p / "docs"
|
|
247
|
+
docs.mkdir()
|
|
248
|
+
(docs / "README.md").write_text("# Docs\n")
|
|
249
|
+
|
|
250
|
+
cfg = Config()
|
|
251
|
+
cfg.performance.parallel_enabled = False
|
|
252
|
+
files = ProjectAnalyzer(cfg, p)._collect_files(p)
|
|
253
|
+
names = {Path(fp).name for fp, _ in files}
|
|
254
|
+
|
|
255
|
+
assert "app.py" in names
|
|
256
|
+
assert "README.md" not in names
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def test_markdown_and_config_do_not_emit_fake_symbols(iac_project):
|
|
260
|
+
"""Tracked docs/config invalidate cache but should not create classes/functions."""
|
|
261
|
+
cfg = Config()
|
|
262
|
+
analyzer = FileAnalyzer(cfg)
|
|
263
|
+
|
|
264
|
+
markdown = analyzer.analyze_file(str(iac_project / "README.md"), "README")
|
|
265
|
+
yaml_result = analyzer.analyze_file(str(iac_project / "k8s.yaml"), "k8s")
|
|
266
|
+
|
|
267
|
+
assert markdown["functions"] == {}
|
|
268
|
+
assert markdown["classes"] == {}
|
|
269
|
+
assert yaml_result["functions"] == {}
|
|
270
|
+
assert yaml_result["classes"] == {}
|
|
271
|
+
assert markdown["module"].source_kind == "docs"
|
|
272
|
+
assert yaml_result["module"].source_kind == "config"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from types import SimpleNamespace
|
|
2
|
+
|
|
3
|
+
from code2llm.cli_exports.orchestrator import _should_skip_export_cache
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_force_skips_export_cache():
|
|
7
|
+
args = SimpleNamespace(no_cache=False, force=True)
|
|
8
|
+
|
|
9
|
+
assert _should_skip_export_cache(args, is_chunked=False) is True
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_no_cache_skips_export_cache():
|
|
13
|
+
args = SimpleNamespace(no_cache=True, force=False)
|
|
14
|
+
|
|
15
|
+
assert _should_skip_export_cache(args, is_chunked=False) is True
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_chunked_skips_export_cache():
|
|
19
|
+
args = SimpleNamespace(no_cache=False, force=False)
|
|
20
|
+
|
|
21
|
+
assert _should_skip_export_cache(args, is_chunked=True) is True
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_standard_run_can_use_export_cache():
|
|
25
|
+
args = SimpleNamespace(no_cache=False, force=False)
|
|
26
|
+
|
|
27
|
+
assert _should_skip_export_cache(args, is_chunked=False) is False
|
code2llm-0.5.151/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.5.151
|
|
File without changes
|
|
File without changes
|