codeboarding 0.13.3__tar.gz → 0.13.4__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.
- {codeboarding-0.13.3/codeboarding.egg-info → codeboarding-0.13.4}/PKG-INFO +5 -1
- {codeboarding-0.13.3 → codeboarding-0.13.4}/PYPI.md +4 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/README.md +6 -2
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/incremental_agent.py +71 -11
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/relation_edges.py +93 -8
- {codeboarding-0.13.3 → codeboarding-0.13.4/codeboarding.egg-info}/PKG-INFO +5 -1
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding.egg-info/SOURCES.txt +2 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/diagram_generator.py +113 -41
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/scope_plan.py +4 -11
- codeboarding-0.13.4/diagram_analysis/tree_shape.py +122 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/checks/function_size.py +8 -8
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/runner.py +9 -8
- {codeboarding-0.13.3 → codeboarding-0.13.4}/output_generators/html_template.py +3 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/output_generators/markdown.py +1 -1
- {codeboarding-0.13.3 → codeboarding-0.13.4}/output_generators/sphinx.py +5 -1
- {codeboarding-0.13.3 → codeboarding-0.13.4}/pyproject.toml +1 -1
- {codeboarding-0.13.3 → codeboarding-0.13.4}/repo_utils/ignore.py +0 -16
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/cluster_relations.py +212 -8
- codeboarding-0.13.4/static_analyzer/internal_references.py +98 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/method_cluster_paths.py +21 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/reference_resolver.py +23 -24
- {codeboarding-0.13.3 → codeboarding-0.13.4}/telemetry/service.py +36 -6
- codeboarding-0.13.4/tests/test_telemetry_service.py +99 -0
- codeboarding-0.13.3/static_analyzer/internal_references.py +0 -72
- {codeboarding-0.13.3 → codeboarding-0.13.4}/LICENSE +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/abstraction_agent.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/agent.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/agent_responses.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/change_status.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/cluster_ids.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/cluster_methods_mixin.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/constants.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/content_hash.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/dependency_discovery.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/details_agent.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/file_index_models.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/incremental_results.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/llm_config.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/llm_errors.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/meta_agent.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/model_capabilities.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/planner_agent.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/prompts/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/prompts/abstract_prompt_factory.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/prompts/claude_prompts.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/prompts/deepseek_prompts.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/prompts/gemini_flash_prompts.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/prompts/glm_prompts.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/prompts/gpt_prompts.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/prompts/kimi_prompts.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/prompts/prompt_factory.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/repair.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/retry.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/scope_ids.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/base.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/component_bridge_edges.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/get_external_deps.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/get_method_invocations.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/list_git_changes.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/read_cfg.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/read_docs.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/read_file.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/read_file_structure.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/read_packages.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/read_source.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/read_structure.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/tools/toolkit.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/agents/validation.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/caching/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/caching/cache.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/caching/details_cache.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/caching/meta_cache.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding.egg-info/dependency_links.txt +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding.egg-info/entry_points.txt +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding.egg-info/requires.txt +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding.egg-info/top_level.txt +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_cli/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_cli/bootstrap.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_cli/commands/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_cli/commands/full_analysis.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_cli/commands/incremental_analysis.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_cli/commands/partial_analysis.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_cli/view_instructions.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_workflows/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_workflows/analysis.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_workflows/orchestration.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_workflows/rendering.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_workflows/sources/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_workflows/sources/local.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/codeboarding_workflows/sources/remote.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/constants.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/core/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/core/plugin_loader.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/core/protocols.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/core/registry.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/analysis_json.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/cluster_delta.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/cluster_snapshot.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/exceptions.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/file_coverage.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/file_index.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/io_utils.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/run_context.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/diagram_analysis/run_mode.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/github_action.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/checks/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/checks/circular_deps.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/checks/cohesion.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/checks/coupling.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/checks/god_class.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/checks/inheritance.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/checks/instability.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/checks/unused_code_diagnostics.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/config.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/health/models.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/install.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/logging_config.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/main.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/monitoring/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/monitoring/callbacks.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/monitoring/context.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/monitoring/mixin.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/monitoring/paths.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/monitoring/stats.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/monitoring/writers.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/output_generators/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/output_generators/html.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/output_generators/mdx.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/repo_utils/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/repo_utils/change_detector.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/repo_utils/errors.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/repo_utils/fingerprint_diff.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/repo_utils/git_ops.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/repo_utils/path_utils.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/setup.cfg +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/analysis_cache.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/analysis_result.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/cluster_helpers.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/constants.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/csharp_config_scanner.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/dotnet_sdk.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/adapters/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/adapters/csharp_adapter.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/adapters/go_adapter.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/adapters/java_adapter.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/adapters/php_adapter.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/adapters/python_adapter.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/adapters/rust_adapter.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/adapters/typescript_adapter.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/call_graph_builder.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/edge_build_context.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/edge_builder.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/hierarchy_builder.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/language_adapter.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/lsp_client.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/lsp_constants.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/models.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/progress.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/protocols.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/result_converter.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/source_inspector.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/symbol_table.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/engine/utils.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/graph.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/incremental_orchestrator.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/java_config_scanner.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/java_utils.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/language_results.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/leiden_utils.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/lsp_client/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/lsp_client/diagnostics.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/node.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/programming_language.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/scanner.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/static_analyzer/typescript_config_scanner.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/telemetry/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/telemetry/device_id.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/telemetry/events.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/telemetry/schemas.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_cli_parser.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_github_action.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_install.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_logging_config.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_main.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_pyproject_packages.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_registry_coverage.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_telemetry_events.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_tool_registry.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_user_config.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_view_instructions.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_vscode_constants.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_windows_compatibility.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tests/test_windows_encoding.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tool_registry/__init__.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tool_registry/installers.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tool_registry/manifest.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tool_registry/paths.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/tool_registry/registry.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/user_config.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/utils.py +0 -0
- {codeboarding-0.13.3 → codeboarding-0.13.4}/vscode_constants.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codeboarding
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.4
|
|
4
4
|
Summary: Interactive Diagrams for Code
|
|
5
5
|
Author: CodeBoarding Team
|
|
6
6
|
License-Expression: MIT
|
|
@@ -73,6 +73,7 @@ Dynamic: license-file
|
|
|
73
73
|
# CodeBoarding
|
|
74
74
|
|
|
75
75
|
[](https://codeboarding.org)
|
|
76
|
+
[](https://app.codeboarding.org)
|
|
76
77
|
[](https://discord.gg/T5zHTJYFuy)
|
|
77
78
|
[](https://github.com/CodeBoarding/CodeBoarding)
|
|
78
79
|
|
|
@@ -130,6 +131,9 @@ codeboarding full --local /path/to/repo
|
|
|
130
131
|
codeboarding full https://github.com/user/repo
|
|
131
132
|
```
|
|
132
133
|
|
|
134
|
+
To explore the result interactively, open the [web platform](https://app.codeboarding.org) and load the
|
|
135
|
+
generated `.codeboarding/analysis.json` — it is parsed in your browser, nothing is uploaded.
|
|
136
|
+
|
|
133
137
|
### Python API
|
|
134
138
|
|
|
135
139
|
```python
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# CodeBoarding
|
|
2
2
|
|
|
3
3
|
[](https://codeboarding.org)
|
|
4
|
+
[](https://app.codeboarding.org)
|
|
4
5
|
[](https://discord.gg/T5zHTJYFuy)
|
|
5
6
|
[](https://github.com/CodeBoarding/CodeBoarding)
|
|
6
7
|
|
|
@@ -58,6 +59,9 @@ codeboarding full --local /path/to/repo
|
|
|
58
59
|
codeboarding full https://github.com/user/repo
|
|
59
60
|
```
|
|
60
61
|
|
|
62
|
+
To explore the result interactively, open the [web platform](https://app.codeboarding.org) and load the
|
|
63
|
+
generated `.codeboarding/analysis.json` — it is parsed in your browser, nothing is uploaded.
|
|
64
|
+
|
|
61
65
|
### Python API
|
|
62
66
|
|
|
63
67
|
```python
|
|
@@ -4,7 +4,7 @@ See what your AI is building before it breaks.
|
|
|
4
4
|
|
|
5
5
|
CodeBoarding gives developers and coding agents a visual map of a codebase. It combines static analysis with LLM reasoning to generate architecture diagrams, component-level documentation, and navigable outputs you can use in your IDE, CI, and docs.
|
|
6
6
|
|
|
7
|
-
[Website](https://codeboarding.org) <img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=0855d476-b2d0-44cc-b93d-69b47504719c" width="0" height="0" /> · [Open VSX extension](https://open-vsx.org/extension/CodeBoarding/codeboarding) <img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=ce87464c-2792-46b0-9ea2-87eefe853d7e" width="0" height="0" /> · [Explore examples](https://codeboarding.org/diagrams) · [VS Code extension](https://marketplace.visualstudio.com/items?itemName=Codeboarding.codeboarding) <img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=8a3d26e0-6f6b-49c0-8482-114445de56a5" width="0" height="0" /> · [GitHub Action](https://github.com/marketplace/actions/codeboarding-action) ·[Discord](https://discord.gg/T5zHTJYFuy)
|
|
7
|
+
[Website](https://codeboarding.org) <img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=0855d476-b2d0-44cc-b93d-69b47504719c" width="0" height="0" /> · [Web platform](https://app.codeboarding.org) · [Open VSX extension](https://open-vsx.org/extension/CodeBoarding/codeboarding) <img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=ce87464c-2792-46b0-9ea2-87eefe853d7e" width="0" height="0" /> · [Explore examples](https://codeboarding.org/diagrams) · [VS Code extension](https://marketplace.visualstudio.com/items?itemName=Codeboarding.codeboarding) <img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=8a3d26e0-6f6b-49c0-8482-114445de56a5" width="0" height="0" /> · [GitHub Action](https://github.com/marketplace/actions/codeboarding-action) · [Discord](https://discord.gg/T5zHTJYFuy)
|
|
8
8
|
|
|
9
9
|
[](https://open-vsx.org/extension/CodeBoarding/codeboarding) <img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=ce87464c-2792-46b0-9ea2-87eefe853d7e" width="0" height="0" />
|
|
10
10
|
|
|
@@ -91,7 +91,9 @@ codeboarding-setup
|
|
|
91
91
|
codeboarding full --local /path/to/repo
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
Output is written to `/path/to/repo/.codeboarding/`.
|
|
94
|
+
Output is written to `/path/to/repo/.codeboarding/`. To explore it interactively, open the
|
|
95
|
+
[web platform](https://app.codeboarding.org) and drop in the generated `analysis.json` — it stays
|
|
96
|
+
in your browser, nothing is uploaded. (The CLI prints this reminder after every successful run.)
|
|
95
97
|
|
|
96
98
|
`python install.py` and `codeboarding-setup` download language server binaries to `~/.codeboarding/servers/`, shared across projects. Node.js (and its bundled `npm`) is required for the Python, TypeScript, JavaScript, and PHP language servers; if neither `node` nor `CODEBOARDING_NODE_PATH` is set, setup downloads a pinned Node.js runtime into `~/.codeboarding/servers/nodeenv/` automatically.
|
|
97
99
|
|
|
@@ -150,6 +152,7 @@ python main.py full https://github.com/pytorch/pytorch
|
|
|
150
152
|
## Where to use it
|
|
151
153
|
|
|
152
154
|
- [CLI](https://github.com/CodeBoarding/CodeBoarding) for local analysis, automation, and CI workflows.
|
|
155
|
+
- [Web platform](https://app.codeboarding.org) to explore any analysis in the browser — open a public repo, load an `analysis.json`, or review an architecture diff on a pull request.
|
|
153
156
|
- [VS Code extension](https://marketplace.visualstudio.com/items?itemName=Codeboarding.codeboarding) <img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=8a3d26e0-6f6b-49c0-8482-114445de56a5" width="0" height="0" /> for in-editor visual architecture.
|
|
154
157
|
- [GitHub Action](https://github.com/marketplace/actions/codeboarding-action) to keep diagrams updated in CI.
|
|
155
158
|
|
|
@@ -163,6 +166,7 @@ python main.py full https://github.com/pytorch/pytorch
|
|
|
163
166
|
- Visualized 800+ open-source repositories.
|
|
164
167
|
- Browse generated examples in [GeneratedOnBoardings](https://github.com/CodeBoarding/GeneratedOnBoardings).
|
|
165
168
|
- Try the hosted explorer at [codeboarding.org/diagrams](https://codeboarding.org/diagrams) <img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=0855d476-b2d0-44cc-b93d-69b47504719c" width="0" height="0" />.
|
|
169
|
+
- Open any public repo that has a committed `.codeboarding/analysis.json` at [app.codeboarding.org](https://app.codeboarding.org) — no install, no login. This repo included: [app.codeboarding.org/CodeBoarding/CodeBoarding](https://app.codeboarding.org/CodeBoarding/CodeBoarding).
|
|
166
170
|
|
|
167
171
|
## Telemetry
|
|
168
172
|
|
|
@@ -40,6 +40,11 @@ from agents.prompts import (
|
|
|
40
40
|
get_system_message,
|
|
41
41
|
)
|
|
42
42
|
from agents.relation_edges import index_relation_endpoints, preserve_unchanged_relations
|
|
43
|
+
from static_analyzer.cluster_relations import (
|
|
44
|
+
build_node_to_component_map,
|
|
45
|
+
build_owner_index,
|
|
46
|
+
prune_ungrounded_edges,
|
|
47
|
+
)
|
|
43
48
|
from agents.scope_ids import ROOT_SCOPE_ID
|
|
44
49
|
from agents.validation import ValidationContext, validate_relations
|
|
45
50
|
from diagram_analysis.file_index import build_files_index
|
|
@@ -137,12 +142,9 @@ class IncrementalAgent(ClusterMethodsMixin, CodeBoardingAgent):
|
|
|
137
142
|
continue
|
|
138
143
|
if operation.action == ScopeOperationAction.NOOP:
|
|
139
144
|
component = components_by_id.get(operation.component_id or "")
|
|
140
|
-
if component is
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
)
|
|
144
|
-
if component.component_id:
|
|
145
|
-
refresh_ids.add(component.component_id)
|
|
145
|
+
if component is None:
|
|
146
|
+
continue
|
|
147
|
+
self._sync_noop_component_cluster_ids(scope_id, component, operation, refresh_ids)
|
|
146
148
|
continue
|
|
147
149
|
|
|
148
150
|
component = components_by_id.get(operation.component_id or "")
|
|
@@ -209,6 +211,20 @@ class IncrementalAgent(ClusterMethodsMixin, CodeBoardingAgent):
|
|
|
209
211
|
new_component_ids.add(component.component_id)
|
|
210
212
|
components_by_id[component.component_id] = component
|
|
211
213
|
|
|
214
|
+
def _sync_noop_component_cluster_ids(
|
|
215
|
+
self,
|
|
216
|
+
scope_id: str,
|
|
217
|
+
component: Component,
|
|
218
|
+
operation: ScopeOperation,
|
|
219
|
+
refresh_ids: set[str],
|
|
220
|
+
) -> None:
|
|
221
|
+
merged_cluster_ids = CodeBoardingClusterIds.sort(
|
|
222
|
+
set(component.source_cluster_ids) | set(_operation_source_cluster_ids(scope_id, operation))
|
|
223
|
+
)
|
|
224
|
+
if merged_cluster_ids != component.source_cluster_ids and component.component_id:
|
|
225
|
+
refresh_ids.add(component.component_id)
|
|
226
|
+
component.source_cluster_ids = merged_cluster_ids
|
|
227
|
+
|
|
212
228
|
@trace
|
|
213
229
|
def detail_new_components(self, components: list[Component]) -> None:
|
|
214
230
|
"""Replace new components' provisional names and descriptions in one LLM call."""
|
|
@@ -383,6 +399,17 @@ class IncrementalAgent(ClusterMethodsMixin, CodeBoardingAgent):
|
|
|
383
399
|
for relation in scope.components_relations
|
|
384
400
|
if relation.src_id and relation.dst_id
|
|
385
401
|
}
|
|
402
|
+
# Also keyed by NAME. Ids are assigned per run by `assign_relation_ids`, so a
|
|
403
|
+
# re-partition can hand the same two components different numbers; the id lookup then
|
|
404
|
+
# misses and the pair is treated as brand new, which re-rolls its wording. Measured on
|
|
405
|
+
# `referenced-symbol-deleted`: 9 statically-backed relations whose call set was
|
|
406
|
+
# byte-identical came back re-worded for exactly this reason. Names survive
|
|
407
|
+
# renumbering, so they are the fallback identity.
|
|
408
|
+
baseline_by_names = {
|
|
409
|
+
(relation.src_name, relation.dst_name): relation.model_copy(deep=True)
|
|
410
|
+
for relation in scope.components_relations
|
|
411
|
+
if relation.src_name and relation.dst_name
|
|
412
|
+
}
|
|
386
413
|
|
|
387
414
|
if context.changed_ids:
|
|
388
415
|
cluster_analysis = _cluster_analysis_for_scope(scope, scope_name, context.cluster_results)
|
|
@@ -404,20 +431,52 @@ class IncrementalAgent(ClusterMethodsMixin, CodeBoardingAgent):
|
|
|
404
431
|
|
|
405
432
|
if baseline_by_pair:
|
|
406
433
|
live_ids = {component.component_id for component in scope.components if component.component_id}
|
|
434
|
+
# A relation is ADDED or REMOVED because code changed, not because a partitioner
|
|
435
|
+
# moved untouched methods around. `context.changed_ids` carries both — it is the
|
|
436
|
+
# right scope to re-derive, and the wrong reason to change the edge set — so the
|
|
437
|
+
# preservation gate sees only components the COMMIT reached. Components that are
|
|
438
|
+
# new or gone keep their ids here: they are changes the commit does account for.
|
|
439
|
+
changed_component_ids = {
|
|
440
|
+
component.component_id
|
|
441
|
+
for component in scope.components
|
|
442
|
+
if component.component_id
|
|
443
|
+
and any(
|
|
444
|
+
method.qualified_name in (changed_members or set())
|
|
445
|
+
for group in component.file_methods
|
|
446
|
+
for method in group.methods
|
|
447
|
+
)
|
|
448
|
+
}
|
|
449
|
+
commit_changed = changed_component_ids | (set(context.changed_ids) - live_ids)
|
|
407
450
|
live_qnames = {
|
|
408
451
|
qualified_name
|
|
409
452
|
for cluster_result in context.cluster_results.values()
|
|
410
453
|
for members in cluster_result.clusters.values()
|
|
411
454
|
for qualified_name in members
|
|
412
455
|
}
|
|
456
|
+
for relation in scope.components_relations:
|
|
457
|
+
# Carry the baseline forward when regenerated component ids changed but names did not.
|
|
458
|
+
pair = (relation.src_id, relation.dst_id)
|
|
459
|
+
if pair not in baseline_by_pair:
|
|
460
|
+
by_name = baseline_by_names.get((relation.src_name, relation.dst_name))
|
|
461
|
+
if by_name is not None:
|
|
462
|
+
baseline_by_pair[pair] = by_name
|
|
413
463
|
scope.components_relations = preserve_unchanged_relations(
|
|
414
464
|
scope.components_relations,
|
|
415
465
|
baseline_by_pair,
|
|
416
|
-
|
|
466
|
+
commit_changed,
|
|
417
467
|
live_ids,
|
|
418
468
|
live_qnames,
|
|
419
469
|
changed_members,
|
|
420
470
|
)
|
|
471
|
+
# Preservation runs after the grounding filters and re-injects baseline edges, so
|
|
472
|
+
# the assembled list is filtered once more — otherwise a baseline's invented or
|
|
473
|
+
# mis-attributed edges survive every update that leaves their methods alone.
|
|
474
|
+
scope.components_relations = prune_ungrounded_edges(
|
|
475
|
+
scope.components_relations,
|
|
476
|
+
build_owner_index(build_node_to_component_map(scope)),
|
|
477
|
+
self.reference_resolver.keep_relation_edge,
|
|
478
|
+
changed_members or set(),
|
|
479
|
+
)
|
|
421
480
|
rels = scope.components_relations
|
|
422
481
|
return rels
|
|
423
482
|
|
|
@@ -793,6 +852,7 @@ def _scrub_one_analysis(analysis: AnalysisInsights, live_files: set[str]) -> set
|
|
|
793
852
|
"""Drop dead-file references in one analysis and return dropped paths."""
|
|
794
853
|
dropped: set[str] = set()
|
|
795
854
|
for component in analysis.components:
|
|
855
|
+
had_methods = any(group.methods for group in component.file_methods)
|
|
796
856
|
kept_groups = []
|
|
797
857
|
for group in component.file_methods:
|
|
798
858
|
if group.file_path in live_files:
|
|
@@ -805,6 +865,8 @@ def _scrub_one_analysis(analysis: AnalysisInsights, live_files: set[str]) -> set
|
|
|
805
865
|
for key_entity in component.key_entities
|
|
806
866
|
if key_entity.reference_file is None or key_entity.reference_file in live_files
|
|
807
867
|
]
|
|
868
|
+
if had_methods and not any(group.methods for group in component.file_methods):
|
|
869
|
+
component.source_cluster_ids = []
|
|
808
870
|
dropped |= {file_path for file_path in analysis.files if file_path not in live_files}
|
|
809
871
|
analysis.files = {file_path: entry for file_path, entry in analysis.files.items() if file_path in live_files}
|
|
810
872
|
return dropped
|
|
@@ -813,17 +875,15 @@ def _scrub_one_analysis(analysis: AnalysisInsights, live_files: set[str]) -> set
|
|
|
813
875
|
def prune_empty_components(
|
|
814
876
|
root_analysis: AnalysisInsights,
|
|
815
877
|
sub_analyses: dict[str, AnalysisInsights],
|
|
816
|
-
protected_empty_ids: set[str] | None = None,
|
|
817
878
|
) -> set[str]:
|
|
818
|
-
"""Remove components with
|
|
879
|
+
"""Remove components with neither members nor live cluster lineage."""
|
|
819
880
|
removed_ids: set[str] = set()
|
|
820
|
-
protected_empty_ids = protected_empty_ids or set()
|
|
821
881
|
|
|
822
882
|
def has_methods(component: Component) -> bool:
|
|
823
883
|
return (
|
|
824
884
|
any(group.methods for group in component.file_methods)
|
|
825
885
|
or bool(component.key_entities)
|
|
826
|
-
or bool(component.
|
|
886
|
+
or bool(component.source_cluster_ids)
|
|
827
887
|
)
|
|
828
888
|
|
|
829
889
|
def collect_empty(analysis: AnalysisInsights) -> None:
|
|
@@ -55,7 +55,8 @@ def index_relation_endpoints(analysis: AnalysisInsights, repo_dir: Path) -> None
|
|
|
55
55
|
def _is_internal_self_relation(relation: Relation) -> bool:
|
|
56
56
|
"""A component related to itself by concrete intra-component calls.
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
Its supporting calls — the concrete method-to-method calls stored under the relation —
|
|
59
|
+
are real CFG calls whose endpoints currently fall in the same
|
|
59
60
|
component, so at this granularity there is no cross-component connection to draw — the
|
|
60
61
|
loop is the residue of a rollup that collapsed a cross-child edge onto its shared parent.
|
|
61
62
|
The CFG still holds every such edge, so expanding the component re-materialises it across
|
|
@@ -76,7 +77,7 @@ def drop_internal_self_relations(relations: list[Relation]) -> list[Relation]:
|
|
|
76
77
|
def _relation_backing_survives(relation: Relation, live_qnames: set[str]) -> bool:
|
|
77
78
|
"""Whether a baseline relation's static backing still exists in live code.
|
|
78
79
|
|
|
79
|
-
A relation
|
|
80
|
+
A relation is supported by concrete method-to-method calls; restoring it verbatim keeps them. If the only edges connecting the two
|
|
80
81
|
components pointed at a symbol since deleted, restoring the relation resurrects an edge
|
|
81
82
|
citing code that is gone — a phantom. A relation with no static edge at all is a
|
|
82
83
|
runtime/config relation with nothing to invalidate, so it is left alone.
|
|
@@ -90,6 +91,7 @@ def _relation_backing_survives(relation: Relation, live_qnames: set[str]) -> boo
|
|
|
90
91
|
|
|
91
92
|
|
|
92
93
|
def _backing_edge_pairs(relation: Relation) -> set[tuple[str, str]]:
|
|
94
|
+
"""The (source, target) method pairs supporting this relation — the calls under the arrow."""
|
|
93
95
|
edges = relation.all_edges or relation.key_edges
|
|
94
96
|
return {(edge.source.qualified_name, edge.target.qualified_name) for edge in edges}
|
|
95
97
|
|
|
@@ -107,7 +109,65 @@ def _relation_edges_unmoved(rebuilt: Relation, previous: Relation) -> bool:
|
|
|
107
109
|
|
|
108
110
|
|
|
109
111
|
def _edge_touches_changed_method(edge: RelationEdge, changed_members: set[str]) -> bool:
|
|
110
|
-
return edge.source.qualified_name in changed_members
|
|
112
|
+
return edge.source.qualified_name in changed_members
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _restore_baseline_orientation(relation: Relation, baseline_by_pair: dict) -> Relation:
|
|
116
|
+
"""Put an ungrounded relation back the way round the reader last saw it.
|
|
117
|
+
|
|
118
|
+
Why only ungrounded ones: a statically-backed relation takes its direction from real CFG
|
|
119
|
+
edges, so the arrow means something and must not be touched. A runtime/config relation has
|
|
120
|
+
no call to fix it, so the model picks an orientation afresh each run — and a swap keyed on
|
|
121
|
+
the ordered pair reads as one relation deleted and another added. On the reported case
|
|
122
|
+
(CodeBoarding-action#65) two of the five changed edges were exactly that: the same two
|
|
123
|
+
component pairs with their arrows reversed and relabelled.
|
|
124
|
+
|
|
125
|
+
Applied only when the fresh relation carries no backing edges at all, because an edge is
|
|
126
|
+
what would make the direction a claim rather than a phrasing — flipping a relation that has
|
|
127
|
+
one would point its edges the wrong way.
|
|
128
|
+
"""
|
|
129
|
+
if relation.is_static or relation.all_edges or relation.key_edges:
|
|
130
|
+
return relation
|
|
131
|
+
flipped = baseline_by_pair.get((relation.dst_id, relation.src_id))
|
|
132
|
+
if flipped is None or flipped.is_static or flipped.all_edges or flipped.key_edges:
|
|
133
|
+
return relation
|
|
134
|
+
return relation.model_copy(
|
|
135
|
+
update={
|
|
136
|
+
"src_id": flipped.src_id,
|
|
137
|
+
"dst_id": flipped.dst_id,
|
|
138
|
+
"src_name": flipped.src_name,
|
|
139
|
+
"dst_name": flipped.dst_name,
|
|
140
|
+
"relation": flipped.relation,
|
|
141
|
+
"evidence": flipped.evidence,
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _filter_edges_touched_by_change(relation: Relation, changed_members: set[str]) -> Relation:
|
|
147
|
+
"""Keep only the edges a code change can account for, for a pair with no baseline.
|
|
148
|
+
|
|
149
|
+
Why: a call lives in its source method's body, so an edge can only appear when one of its
|
|
150
|
+
endpoints changed. ``_reconcile_unchanged_edges`` enforces that by falling back to the
|
|
151
|
+
baseline, but re-clustering invents component-pairs that have no baseline to fall back to —
|
|
152
|
+
there every re-attributed edge would otherwise enter as if the commit had written it.
|
|
153
|
+
"""
|
|
154
|
+
return relation.model_copy(
|
|
155
|
+
update={
|
|
156
|
+
"all_edges": [e for e in relation.all_edges if _edge_touches_changed_method(e, changed_members)],
|
|
157
|
+
"key_edges": [e for e in relation.key_edges if _edge_touches_changed_method(e, changed_members)],
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _commit_deleted_the_backing(rebuilt: Relation, previous: Relation, changed_members: set[str]) -> bool:
|
|
163
|
+
"""Return whether a changed source removed every baseline backing edge.
|
|
164
|
+
|
|
165
|
+
A call belongs to its source method, so only lost edges from changed sources prove deletion.
|
|
166
|
+
"""
|
|
167
|
+
baseline_edges = previous.all_edges or previous.key_edges
|
|
168
|
+
if not baseline_edges or rebuilt.all_edges or rebuilt.key_edges or rebuilt.evidence.strip():
|
|
169
|
+
return False
|
|
170
|
+
return any(_edge_touches_changed_method(edge, changed_members) for edge in baseline_edges)
|
|
111
171
|
|
|
112
172
|
|
|
113
173
|
def _reconcile_unchanged_edges(fresh: Relation, previous: Relation, changed_members: set[str]) -> Relation:
|
|
@@ -160,6 +220,9 @@ def preserve_unchanged_relations(
|
|
|
160
220
|
their inter-component edges are byte-identical. Gating on the pair's own edges instead of
|
|
161
221
|
on its endpoints' change flags is what keeps those untouched connections stable.
|
|
162
222
|
|
|
223
|
+
A pair whose changed source lost every baseline call is dropped unless the rebuild supplies
|
|
224
|
+
alternate runtime/config evidence.
|
|
225
|
+
|
|
163
226
|
A baseline relation between two unchanged, still-live components that regeneration
|
|
164
227
|
dropped is restored — but only when its backing edges still exist in live code. The
|
|
165
228
|
deterministic rebuild drops a pair when the code connecting the two components was
|
|
@@ -176,6 +239,8 @@ def preserve_unchanged_relations(
|
|
|
176
239
|
kept: list[Relation] = []
|
|
177
240
|
rebuilt_pairs: set[tuple[str, str]] = set()
|
|
178
241
|
for relation in rebuilt_relations:
|
|
242
|
+
if (relation.src_id, relation.dst_id) not in baseline_by_pair:
|
|
243
|
+
relation = _restore_baseline_orientation(relation, baseline_by_pair)
|
|
179
244
|
pair = (relation.src_id, relation.dst_id)
|
|
180
245
|
rebuilt_pairs.add(pair)
|
|
181
246
|
previous = baseline_by_pair.get(pair)
|
|
@@ -183,8 +248,14 @@ def preserve_unchanged_relations(
|
|
|
183
248
|
# No baseline for this pair. A genuinely new connection into a changed area is
|
|
184
249
|
# kept; a fresh edge invented between two untouched components is a re-attribution
|
|
185
250
|
# artifact and is dropped.
|
|
186
|
-
if touches_change(*pair):
|
|
187
|
-
|
|
251
|
+
if not touches_change(*pair):
|
|
252
|
+
continue
|
|
253
|
+
if changed_members is not None:
|
|
254
|
+
relation = _filter_edges_touched_by_change(relation, changed_members)
|
|
255
|
+
# Nothing survived and nothing else is claimed: the pair asserts no connection.
|
|
256
|
+
if not relation.all_edges and not relation.key_edges and not relation.evidence.strip():
|
|
257
|
+
continue
|
|
258
|
+
kept.append(relation)
|
|
188
259
|
continue
|
|
189
260
|
# Every edge between two byte-identical methods is taken from the baseline; only edges
|
|
190
261
|
# that touch a changed/added/deleted method come from the fresh rebuild. This stops
|
|
@@ -192,9 +263,23 @@ def preserve_unchanged_relations(
|
|
|
192
263
|
# pairs alike.
|
|
193
264
|
if changed_members is not None:
|
|
194
265
|
relation = _reconcile_unchanged_edges(relation, previous, changed_members)
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
266
|
+
if _commit_deleted_the_backing(relation, previous, changed_members):
|
|
267
|
+
continue
|
|
268
|
+
# Keep the reader's wording unless this pair's own supporting calls moved.
|
|
269
|
+
#
|
|
270
|
+
# The supporting calls are the concrete method-to-method calls under the relation — the
|
|
271
|
+
# ones that show WHERE one component reaches the other. They are the only evidence that
|
|
272
|
+
# the connection itself changed, so they are what decides whether it may be re-worded.
|
|
273
|
+
# Gating on the endpoint components' change flags instead re-words far more: a component
|
|
274
|
+
# is flagged for any edit to a file it merely co-owns, so deleting one function re-worded
|
|
275
|
+
# 17 of the relations in `referenced-symbol-deleted` whose calls had not moved at all.
|
|
276
|
+
# A pair with no supporting calls has nothing that could have moved, so its wording is
|
|
277
|
+
# kept too — an edgeless runtime relation is prose, and re-rolling prose is the churn.
|
|
278
|
+
if (
|
|
279
|
+
not touches_change(*pair)
|
|
280
|
+
or _relation_edges_unmoved(relation, previous)
|
|
281
|
+
or (not _backing_edge_pairs(relation) and not relation.evidence.strip())
|
|
282
|
+
):
|
|
198
283
|
relation = relation.model_copy(update={"relation": previous.relation, "evidence": previous.evidence})
|
|
199
284
|
kept.append(relation)
|
|
200
285
|
for pair, relation in baseline_by_pair.items():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codeboarding
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.4
|
|
4
4
|
Summary: Interactive Diagrams for Code
|
|
5
5
|
Author: CodeBoarding Team
|
|
6
6
|
License-Expression: MIT
|
|
@@ -73,6 +73,7 @@ Dynamic: license-file
|
|
|
73
73
|
# CodeBoarding
|
|
74
74
|
|
|
75
75
|
[](https://codeboarding.org)
|
|
76
|
+
[](https://app.codeboarding.org)
|
|
76
77
|
[](https://discord.gg/T5zHTJYFuy)
|
|
77
78
|
[](https://github.com/CodeBoarding/CodeBoarding)
|
|
78
79
|
|
|
@@ -130,6 +131,9 @@ codeboarding full --local /path/to/repo
|
|
|
130
131
|
codeboarding full https://github.com/user/repo
|
|
131
132
|
```
|
|
132
133
|
|
|
134
|
+
To explore the result interactively, open the [web platform](https://app.codeboarding.org) and load the
|
|
135
|
+
generated `.codeboarding/analysis.json` — it is parsed in your browser, nothing is uploaded.
|
|
136
|
+
|
|
133
137
|
### Python API
|
|
134
138
|
|
|
135
139
|
```python
|
|
@@ -97,6 +97,7 @@ diagram_analysis/io_utils.py
|
|
|
97
97
|
diagram_analysis/run_context.py
|
|
98
98
|
diagram_analysis/run_mode.py
|
|
99
99
|
diagram_analysis/scope_plan.py
|
|
100
|
+
diagram_analysis/tree_shape.py
|
|
100
101
|
health/__init__.py
|
|
101
102
|
health/config.py
|
|
102
103
|
health/models.py
|
|
@@ -189,6 +190,7 @@ tests/test_main.py
|
|
|
189
190
|
tests/test_pyproject_packages.py
|
|
190
191
|
tests/test_registry_coverage.py
|
|
191
192
|
tests/test_telemetry_events.py
|
|
193
|
+
tests/test_telemetry_service.py
|
|
192
194
|
tests/test_tool_registry.py
|
|
193
195
|
tests/test_user_config.py
|
|
194
196
|
tests/test_view_instructions.py
|