sourcecode 1.2.0__tar.gz → 1.3.0__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.
- {sourcecode-1.2.0 → sourcecode-1.3.0}/PKG-INFO +1 -1
- {sourcecode-1.2.0 → sourcecode-1.3.0}/pyproject.toml +1 -1
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/ast_extractor.py +89 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/cli.py +22 -3
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/contract_pipeline.py +10 -2
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/dependency_analyzer.py +16 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/doc_analyzer.py +76 -1
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/entrypoint_classifier.py +3 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/graph_analyzer.py +1 -1
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/metrics_analyzer.py +16 -1
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/prepare_context.py +27 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/serializer.py +11 -3
- {sourcecode-1.2.0 → sourcecode-1.3.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/.gitignore +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/.ruff.toml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/CONTRIBUTING.md +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/LICENSE +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/README.md +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/SECURITY.md +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/docs/privacy.md +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/docs/schema.md +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/raw +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/run_cli.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/__init__.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/conftest.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/lcov.info +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_architecture_summary.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_ast_extractor.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_block1_reliability.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_block2_coverage.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_block5_quality.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_classifier.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_cli.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_context_scorer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_contract_pipeline.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_coverage_parser.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_cross_consistency.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_dependency_analyzer_node_python.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_dependency_schema.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_detector_dotnet.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_detector_python.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_detectors_base.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_graph_schema.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_hybrid_inference.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration_dependencies.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration_detection.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration_docs.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration_lqn.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration_metrics.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration_multistack.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration_semantics.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_integration_universal.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_java_spring_integration.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_packaging.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_phase1_improvements.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_pipeline_integrity.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_real_projects.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_redactor.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_scanner.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_schema.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_schema_normalization.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_semantic_schema.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_signal_hierarchy.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_summarizer.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_telemetry.py +0 -0
- {sourcecode-1.2.0 → sourcecode-1.3.0}/tests/test_workspace_analyzer.py +0 -0
|
@@ -79,6 +79,7 @@ _LANGUAGE_MAP: dict[str, str] = {
|
|
|
79
79
|
".jsx": "jsx",
|
|
80
80
|
".mjs": "javascript",
|
|
81
81
|
".cjs": "javascript",
|
|
82
|
+
".java": "java",
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
_REACT_HOOKS: frozenset[str] = frozenset({
|
|
@@ -938,6 +939,92 @@ def _extract_python(path: str, source: str) -> FileContract:
|
|
|
938
939
|
)
|
|
939
940
|
|
|
940
941
|
|
|
942
|
+
# ---------------------------------------------------------------------------
|
|
943
|
+
# Minimal Java extraction (regex-based, no AST)
|
|
944
|
+
# ---------------------------------------------------------------------------
|
|
945
|
+
|
|
946
|
+
_JAVA_CLASS_DECL_RE = re.compile(
|
|
947
|
+
r'public\s+(?:(?:abstract|final|static)\s+)*(class|interface|enum)\s+(\w+)'
|
|
948
|
+
r'(?:\s+extends\s+([\w.]+))?(?:\s+implements\s+([\w.,\s]+?))?(?=\s*[\{<])',
|
|
949
|
+
re.MULTILINE,
|
|
950
|
+
)
|
|
951
|
+
_JAVA_METHOD_SIG_RE = re.compile(
|
|
952
|
+
r'^\s{0,12}public\s+[^\{]+\(',
|
|
953
|
+
re.MULTILINE,
|
|
954
|
+
)
|
|
955
|
+
_JAVA_IMPORT_RE = re.compile(r'^import\s+(?:static\s+)?([^;\s]+)\s*;', re.MULTILINE)
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
def _extract_java(path: str, source: str) -> FileContract:
|
|
959
|
+
exports: list[ExportRecord] = []
|
|
960
|
+
types: list[TypeDefinition] = []
|
|
961
|
+
functions: list[FunctionSignature] = []
|
|
962
|
+
imports: list[ImportRecord] = []
|
|
963
|
+
|
|
964
|
+
# Class / interface / enum declarations
|
|
965
|
+
for m in _JAVA_CLASS_DECL_RE.finditer(source):
|
|
966
|
+
name = m.group(2)
|
|
967
|
+
extends_str = m.group(3)
|
|
968
|
+
implements_str = m.group(4)
|
|
969
|
+
all_extends: list[str] = []
|
|
970
|
+
if extends_str:
|
|
971
|
+
all_extends.append(extends_str.strip())
|
|
972
|
+
if implements_str:
|
|
973
|
+
all_extends.extend(i.strip() for i in implements_str.split(",") if i.strip())
|
|
974
|
+
types.append(TypeDefinition(name=name, kind="class", fields=[], extends=all_extends))
|
|
975
|
+
exports.append(ExportRecord(name=name, kind="class"))
|
|
976
|
+
|
|
977
|
+
class_names = {t.name for t in types}
|
|
978
|
+
|
|
979
|
+
# Public method signatures (one-line heuristic)
|
|
980
|
+
seen_methods: set[str] = set()
|
|
981
|
+
for m in _JAVA_METHOD_SIG_RE.finditer(source):
|
|
982
|
+
sig_text = m.group(0).strip()
|
|
983
|
+
name_match = re.search(r'(\w+)\s*\($', sig_text)
|
|
984
|
+
if not name_match:
|
|
985
|
+
name_match = re.search(r'(\w+)\s*\(', sig_text)
|
|
986
|
+
if not name_match:
|
|
987
|
+
continue
|
|
988
|
+
mname = name_match.group(1)
|
|
989
|
+
if mname in class_names or mname in seen_methods or mname in {"if", "for", "while", "switch"}:
|
|
990
|
+
continue
|
|
991
|
+
seen_methods.add(mname)
|
|
992
|
+
functions.append(FunctionSignature(
|
|
993
|
+
name=mname,
|
|
994
|
+
signature=sig_text,
|
|
995
|
+
async_=False,
|
|
996
|
+
exported=True,
|
|
997
|
+
return_type=None,
|
|
998
|
+
))
|
|
999
|
+
|
|
1000
|
+
# Import statements
|
|
1001
|
+
seen_sources: set[str] = set()
|
|
1002
|
+
for m in _JAVA_IMPORT_RE.finditer(source):
|
|
1003
|
+
full_import = m.group(1).strip()
|
|
1004
|
+
if full_import not in seen_sources:
|
|
1005
|
+
seen_sources.add(full_import)
|
|
1006
|
+
imports.append(ImportRecord(source=full_import, kind="named", symbols=[]))
|
|
1007
|
+
|
|
1008
|
+
# External deps: top-2 package segments, skip java.* / javax.*
|
|
1009
|
+
deps = sorted({
|
|
1010
|
+
".".join(imp.source.split(".")[:2])
|
|
1011
|
+
for imp in imports
|
|
1012
|
+
if not imp.source.startswith("java.") and not imp.source.startswith("javax.")
|
|
1013
|
+
and len(imp.source.split(".")) >= 2
|
|
1014
|
+
})
|
|
1015
|
+
|
|
1016
|
+
return FileContract(
|
|
1017
|
+
path=path,
|
|
1018
|
+
language="java",
|
|
1019
|
+
exports=exports,
|
|
1020
|
+
imports=sorted(imports, key=lambda i: i.source)[:30],
|
|
1021
|
+
functions=sorted(functions, key=lambda f: f.name)[:20],
|
|
1022
|
+
types=sorted(types, key=lambda t: t.name),
|
|
1023
|
+
dependencies=deps[:20],
|
|
1024
|
+
extraction_method="heuristic",
|
|
1025
|
+
)
|
|
1026
|
+
|
|
1027
|
+
|
|
941
1028
|
# ---------------------------------------------------------------------------
|
|
942
1029
|
# Role detection
|
|
943
1030
|
# ---------------------------------------------------------------------------
|
|
@@ -1048,6 +1135,8 @@ class AstExtractor:
|
|
|
1048
1135
|
|
|
1049
1136
|
if language == "python":
|
|
1050
1137
|
contract = _extract_python(rel_path, source)
|
|
1138
|
+
elif language == "java":
|
|
1139
|
+
contract = _extract_java(rel_path, source)
|
|
1051
1140
|
else:
|
|
1052
1141
|
if self._ensure_ts():
|
|
1053
1142
|
lang_obj = _get_ts_lang(language)
|
|
@@ -1270,10 +1270,24 @@ def main(
|
|
|
1270
1270
|
and d.scope not in {"dev"}
|
|
1271
1271
|
]
|
|
1272
1272
|
|
|
1273
|
-
|
|
1273
|
+
_JAVA_SEMANTIC_PRIORITY: dict[str, int] = {
|
|
1274
|
+
"spring-boot": 0, "spring-security": 1, "mybatis": 2,
|
|
1275
|
+
"poi": 3, "pdfbox": 4, "jackson": 5, "jjwt": 6,
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
def _java_priority(d: Any) -> int:
|
|
1279
|
+
if d.ecosystem != "java":
|
|
1280
|
+
return 99
|
|
1281
|
+
art = (d.name.split(":")[-1] if ":" in d.name else d.name).lower()
|
|
1282
|
+
for key, pri in _JAVA_SEMANTIC_PRIORITY.items():
|
|
1283
|
+
if key in art:
|
|
1284
|
+
return pri
|
|
1285
|
+
return 50
|
|
1286
|
+
|
|
1287
|
+
def _dep_sort_key(d: Any) -> tuple[int, int, int, str]:
|
|
1274
1288
|
role_order = _ROLE_PRIORITY.get(d.role or "runtime", 5)
|
|
1275
1289
|
eco_order = 0 if d.ecosystem == primary_ecosystem else 1
|
|
1276
|
-
return (role_order, eco_order, d.name.lower())
|
|
1290
|
+
return (role_order, eco_order, _java_priority(d), d.name.lower())
|
|
1277
1291
|
|
|
1278
1292
|
_seen_dep_names: set[str] = set()
|
|
1279
1293
|
_deduped_deps: list[Any] = []
|
|
@@ -1281,7 +1295,7 @@ def main(
|
|
|
1281
1295
|
if d.name not in _seen_dep_names:
|
|
1282
1296
|
_seen_dep_names.add(d.name)
|
|
1283
1297
|
_deduped_deps.append(d)
|
|
1284
|
-
sm.key_dependencies = _deduped_deps
|
|
1298
|
+
sm.key_dependencies = _deduped_deps # no cap — all direct deps included
|
|
1285
1299
|
|
|
1286
1300
|
# LQN-02: deterministic NL summary
|
|
1287
1301
|
sm.project_summary = ProjectSummarizer(target).generate(sm)
|
|
@@ -1384,6 +1398,7 @@ def main(
|
|
|
1384
1398
|
|
|
1385
1399
|
# Contract pipeline — runs for mode=contract|standard|deep|hybrid (skip for raw)
|
|
1386
1400
|
_is_contract_mode = mode in ("contract", "standard")
|
|
1401
|
+
_pipeline_error = False
|
|
1387
1402
|
if _is_contract_mode:
|
|
1388
1403
|
from sourcecode.contract_pipeline import ContractPipeline
|
|
1389
1404
|
from sourcecode.contract_model import ContractSummary as _ContractSummary
|
|
@@ -1408,6 +1423,7 @@ def main(
|
|
|
1408
1423
|
)
|
|
1409
1424
|
except Exception as _exc:
|
|
1410
1425
|
typer.echo(f"[error] contract pipeline failed: {_exc}", err=True)
|
|
1426
|
+
_pipeline_error = True
|
|
1411
1427
|
_contracts = []
|
|
1412
1428
|
_contract_summary = _ContractSummary(
|
|
1413
1429
|
mode=mode,
|
|
@@ -1518,6 +1534,9 @@ def main(
|
|
|
1518
1534
|
# 6. Write output (CLI-04)
|
|
1519
1535
|
write_output(content, output=output)
|
|
1520
1536
|
|
|
1537
|
+
if _pipeline_error:
|
|
1538
|
+
raise typer.Exit(code=2)
|
|
1539
|
+
|
|
1521
1540
|
# 7. Clipboard copy (--copy / -c)
|
|
1522
1541
|
if copy and output is None:
|
|
1523
1542
|
_trimmed = content.strip()
|
|
@@ -370,7 +370,15 @@ class ContractPipeline:
|
|
|
370
370
|
"""
|
|
371
371
|
candidates = _find_symbol_files(root, symbol, known_paths, engine)
|
|
372
372
|
if not candidates:
|
|
373
|
-
return []
|
|
373
|
+
return [], {
|
|
374
|
+
"symbol": symbol,
|
|
375
|
+
"definers_found": 0,
|
|
376
|
+
"importers_found": 0,
|
|
377
|
+
"importers_returned": 0,
|
|
378
|
+
"references_found": 0,
|
|
379
|
+
"total_returned": 0,
|
|
380
|
+
"truncated": False,
|
|
381
|
+
}
|
|
374
382
|
|
|
375
383
|
extra: list[FileContract] = []
|
|
376
384
|
for rel_path in candidates[:300]: # cap to prevent excessive extraction
|
|
@@ -577,7 +585,7 @@ def _find_symbol_files(
|
|
|
577
585
|
"grep", "-rl",
|
|
578
586
|
"--include=*.ts", "--include=*.tsx",
|
|
579
587
|
"--include=*.js", "--include=*.jsx",
|
|
580
|
-
"--include=*.py",
|
|
588
|
+
"--include=*.py", "--include=*.java",
|
|
581
589
|
symbol, ".",
|
|
582
590
|
],
|
|
583
591
|
cwd=str(root),
|
|
@@ -127,6 +127,22 @@ def _infer_role(name: str, ecosystem: str, scope: str) -> str:
|
|
|
127
127
|
return "infra"
|
|
128
128
|
return "runtime"
|
|
129
129
|
|
|
130
|
+
if ecosystem == "java":
|
|
131
|
+
artifact = n.split(":")[-1] if ":" in n else n
|
|
132
|
+
if any(x in artifact for x in ("spring-boot", "spring-security")):
|
|
133
|
+
return "runtime"
|
|
134
|
+
if any(x in artifact for x in ("spring-web", "spring-mvc", "spring-core", "spring-context")):
|
|
135
|
+
return "runtime"
|
|
136
|
+
if any(x in artifact for x in ("mybatis", "hibernate", "jpa", "druid", "datasource")):
|
|
137
|
+
return "infra"
|
|
138
|
+
if any(x in artifact for x in ("jackson", "gson", "fastjson")):
|
|
139
|
+
return "serialization"
|
|
140
|
+
if any(x in artifact for x in ("poi", "pdfbox", "itext", "openpdf")):
|
|
141
|
+
return "parsing"
|
|
142
|
+
if any(x in artifact for x in ("jjwt", "nimbus-jose")):
|
|
143
|
+
return "runtime"
|
|
144
|
+
return "devtool" if is_dev else "runtime"
|
|
145
|
+
|
|
130
146
|
return "devtool" if is_dev else "runtime"
|
|
131
147
|
|
|
132
148
|
|
|
@@ -174,6 +174,14 @@ class DocAnalyzer:
|
|
|
174
174
|
limitations.extend(file_limitations)
|
|
175
175
|
if file_records:
|
|
176
176
|
languages.add(lang)
|
|
177
|
+
elif suffix == ".java":
|
|
178
|
+
file_records, file_limitations = self._analyze_java_file(
|
|
179
|
+
norm_path, content, depth, workspace, entry_points
|
|
180
|
+
)
|
|
181
|
+
records.extend(file_records)
|
|
182
|
+
limitations.extend(file_limitations)
|
|
183
|
+
if file_records:
|
|
184
|
+
languages.add("java")
|
|
177
185
|
else:
|
|
178
186
|
# Unsupported language — D-04: no emitir DocRecord, solo registrar limitation
|
|
179
187
|
limitations.append(f"docs_unavailable:{norm_path}:language={lang}")
|
|
@@ -182,7 +190,7 @@ class DocAnalyzer:
|
|
|
182
190
|
# NO records.append() here
|
|
183
191
|
|
|
184
192
|
# Build language_coverage: explicit per-language support status
|
|
185
|
-
_SUPPORTED_LANGS = {"python", "javascript", "typescript"}
|
|
193
|
+
_SUPPORTED_LANGS = {"python", "javascript", "typescript", "java"}
|
|
186
194
|
lang_coverage: dict[str, str] = {}
|
|
187
195
|
for lang in languages:
|
|
188
196
|
if lang in _SUPPORTED_LANGS:
|
|
@@ -225,6 +233,73 @@ class DocAnalyzer:
|
|
|
225
233
|
)
|
|
226
234
|
return records, summary
|
|
227
235
|
|
|
236
|
+
# Javadoc: /** ... */ block followed by class/method declaration
|
|
237
|
+
_JAVADOC_RE = re.compile(r'/\*\*(.*?)\*/', re.DOTALL)
|
|
238
|
+
_JAVA_CLASS_AFTER_RE = re.compile(
|
|
239
|
+
r'(?:public\s+)?(?:abstract\s+)?(?:final\s+)?(?:class|interface|enum)\s+(\w+)',
|
|
240
|
+
)
|
|
241
|
+
_JAVA_METHOD_AFTER_RE = re.compile(
|
|
242
|
+
r'public\s+[\w<>\[\],\s]+?\s+(\w+)\s*\(',
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
def _clean_javadoc(self, raw: str) -> str:
|
|
246
|
+
lines = raw.strip().splitlines()
|
|
247
|
+
cleaned: list[str] = []
|
|
248
|
+
for line in lines:
|
|
249
|
+
line = re.sub(r'^\s*\*\s?', '', line).strip()
|
|
250
|
+
if line.startswith('@'):
|
|
251
|
+
continue
|
|
252
|
+
if line:
|
|
253
|
+
cleaned.append(line)
|
|
254
|
+
result = ' '.join(cleaned)
|
|
255
|
+
if len(result) > self._DOCSTRING_MAX_CHARS:
|
|
256
|
+
result = result[:self._DOCSTRING_MAX_CHARS] + self._TRUNCATION_SUFFIX
|
|
257
|
+
return result
|
|
258
|
+
|
|
259
|
+
def _analyze_java_file(
|
|
260
|
+
self,
|
|
261
|
+
path: str,
|
|
262
|
+
content: str,
|
|
263
|
+
depth: "DocsDepth",
|
|
264
|
+
workspace: "str | None",
|
|
265
|
+
entry_points: "list[str] | None",
|
|
266
|
+
) -> "tuple[list[DocRecord], list[str]]":
|
|
267
|
+
records: list[DocRecord] = []
|
|
268
|
+
for jd_match in self._JAVADOC_RE.finditer(content):
|
|
269
|
+
lookahead = content[jd_match.end():jd_match.end() + 400].lstrip()
|
|
270
|
+
# Class-level Javadoc
|
|
271
|
+
class_m = self._JAVA_CLASS_AFTER_RE.match(lookahead)
|
|
272
|
+
if class_m:
|
|
273
|
+
name = class_m.group(1)
|
|
274
|
+
doc_text = self._clean_javadoc(jd_match.group(1))
|
|
275
|
+
records.append(DocRecord(
|
|
276
|
+
path=path,
|
|
277
|
+
workspace=workspace,
|
|
278
|
+
kind="class",
|
|
279
|
+
name=name,
|
|
280
|
+
doc_text=doc_text,
|
|
281
|
+
importance=self._infer_importance(path, "class", entry_points),
|
|
282
|
+
))
|
|
283
|
+
continue
|
|
284
|
+
# Method-level Javadoc (only when depth != "module")
|
|
285
|
+
if depth == "module":
|
|
286
|
+
continue
|
|
287
|
+
method_m = self._JAVA_METHOD_AFTER_RE.match(lookahead)
|
|
288
|
+
if method_m:
|
|
289
|
+
name = method_m.group(1)
|
|
290
|
+
if name in {"if", "for", "while", "switch", "return", "new"}:
|
|
291
|
+
continue
|
|
292
|
+
doc_text = self._clean_javadoc(jd_match.group(1))
|
|
293
|
+
records.append(DocRecord(
|
|
294
|
+
path=path,
|
|
295
|
+
workspace=workspace,
|
|
296
|
+
kind="function",
|
|
297
|
+
name=name,
|
|
298
|
+
doc_text=doc_text,
|
|
299
|
+
importance=self._infer_importance(path, "function", entry_points),
|
|
300
|
+
))
|
|
301
|
+
return records, []
|
|
302
|
+
|
|
228
303
|
def merge_summaries(self, summaries: Iterable[DocSummary]) -> DocSummary:
|
|
229
304
|
"""Agrega multiples DocSummary en uno.
|
|
230
305
|
|
|
@@ -67,6 +67,9 @@ def runtime_relevance(ep: EntryPoint, classification: Classification | None = No
|
|
|
67
67
|
classification = classification or classify_entry_point(ep)
|
|
68
68
|
if classification != "production":
|
|
69
69
|
return "low"
|
|
70
|
+
# Annotation-detected HTTP controllers are the primary runtime surface
|
|
71
|
+
if ep.source == "annotation" and ep.kind in {"rest_controller", "mvc_controller"}:
|
|
72
|
+
return "high"
|
|
70
73
|
reason = (ep.reason or "").lower()
|
|
71
74
|
if ep.source == "package.json#bin" or reason == "bin" or reason in _PRODUCTION_SCRIPT_REASONS:
|
|
72
75
|
return "high"
|
|
@@ -137,7 +137,7 @@ def _mccabe(func_node: ast.FunctionDef | ast.AsyncFunctionDef) -> int:
|
|
|
137
137
|
class MetricsAnalyzer:
|
|
138
138
|
"""Analiza metricas de calidad de codigo: LOC, simbolos y complejidad ciclomatica."""
|
|
139
139
|
|
|
140
|
-
_MAX_FILES =
|
|
140
|
+
_MAX_FILES = 2000
|
|
141
141
|
_MAX_FILE_SIZE = 500_000 # bytes
|
|
142
142
|
|
|
143
143
|
# ---------------------------------------------------------------------------
|
|
@@ -159,6 +159,21 @@ class MetricsAnalyzer:
|
|
|
159
159
|
# Keep only paths that are actual files (not directories)
|
|
160
160
|
file_paths = [p for p in all_paths if (root / p).is_file()]
|
|
161
161
|
|
|
162
|
+
# Sort: JVM source first, then other source, then config, then dotfiles
|
|
163
|
+
# Prevents the 500-file cap from cutting all Java files when dotfiles sort first.
|
|
164
|
+
def _sort_key(p: str) -> tuple[int, str]:
|
|
165
|
+
if Path(p).suffix.lower() in {".java", ".kt", ".scala"}:
|
|
166
|
+
return (0, p)
|
|
167
|
+
if Path(p).suffix.lower() in {".py", ".go", ".rs", ".ts", ".js", ".tsx", ".jsx"}:
|
|
168
|
+
return (1, p)
|
|
169
|
+
if Path(p).suffix.lower() in {".xml", ".yaml", ".yml", ".json", ".toml", ".properties"}:
|
|
170
|
+
return (2, p)
|
|
171
|
+
if Path(p).name.startswith("."):
|
|
172
|
+
return (4, p)
|
|
173
|
+
return (3, p)
|
|
174
|
+
|
|
175
|
+
file_paths.sort(key=_sort_key)
|
|
176
|
+
|
|
162
177
|
limitations: list[str] = []
|
|
163
178
|
|
|
164
179
|
# Guard: max files
|
|
@@ -760,6 +760,33 @@ class TaskContextBuilder:
|
|
|
760
760
|
elif self._is_source(path) and not content_reasons:
|
|
761
761
|
content_boost += 0.5
|
|
762
762
|
|
|
763
|
+
# Task-specific boosts for differentiated file weighting
|
|
764
|
+
path_lower = path.lower()
|
|
765
|
+
if task_name == "fix-bug":
|
|
766
|
+
if any(x in path_lower for x in ("exception", "error", "handler", "advice")):
|
|
767
|
+
content_boost += 1.5
|
|
768
|
+
content_reasons.append("exception handler — high risk area")
|
|
769
|
+
elif task_name == "generate-tests":
|
|
770
|
+
stem = Path(path).stem.lower()
|
|
771
|
+
has_test = any(
|
|
772
|
+
stem in Path(tp).stem.lower() or Path(tp).stem.lower() in stem
|
|
773
|
+
for tp in test_set
|
|
774
|
+
)
|
|
775
|
+
if not has_test and self._is_source(path):
|
|
776
|
+
content_boost += 1.0
|
|
777
|
+
content_reasons.append("no test pair found")
|
|
778
|
+
elif task_name == "onboard":
|
|
779
|
+
if path in runtime_entry_set:
|
|
780
|
+
content_boost += 2.0
|
|
781
|
+
content_reasons.append("runtime entry point")
|
|
782
|
+
if any(x in path_lower for x in ("config", "application.yml", "application.properties", "settings", "bootstrap")):
|
|
783
|
+
content_boost += 1.0
|
|
784
|
+
content_reasons.append("configuration class")
|
|
785
|
+
elif task_name == "explain":
|
|
786
|
+
if "controller" in path_lower and path in runtime_entry_set:
|
|
787
|
+
content_boost += 1.5
|
|
788
|
+
content_reasons.append("DDD module controller")
|
|
789
|
+
|
|
763
790
|
total = fs.score + content_boost
|
|
764
791
|
if total <= 0:
|
|
765
792
|
continue
|
|
@@ -35,7 +35,7 @@ _FILE_RELEVANCE_MIN_COMBINED = 0.40 # minimum combined score — must earn incl
|
|
|
35
35
|
_PROD_DEPS_CAP = 10 # max production dependencies shown
|
|
36
36
|
_SECONDARY_DEPS_CAP = 5 # max per dev/test/build dependency group
|
|
37
37
|
_MONOREPO_PKGS_CAP = 8 # max workspace/runtime packages shown
|
|
38
|
-
_KEY_DEPS_CAP =
|
|
38
|
+
_KEY_DEPS_CAP = 50 # max key dependencies shown
|
|
39
39
|
_CODE_NOTES_CAP = 15 # max code notes in default output
|
|
40
40
|
_ENV_MAP_CAP = 15 # max env var entries in default output
|
|
41
41
|
|
|
@@ -223,6 +223,11 @@ def _file_relevance(sm: SourceMap, *, limit: int = _FILE_RELEVANCE_LIMIT) -> lis
|
|
|
223
223
|
semantic_hub_scores[p] = h.get("importance_score", 0.0) / max_importance
|
|
224
224
|
|
|
225
225
|
entry_paths = {ep.path for ep in sm.entry_points}
|
|
226
|
+
# REST/MVC controllers are HTTP surface — surface before @Transactional services
|
|
227
|
+
_rest_ctrl_paths = {
|
|
228
|
+
ep.path for ep in sm.entry_points
|
|
229
|
+
if getattr(ep, "kind", "") in {"rest_controller", "mvc_controller"}
|
|
230
|
+
}
|
|
226
231
|
scored: list[tuple[float, dict[str, Any]]] = []
|
|
227
232
|
|
|
228
233
|
for path in sm.file_paths:
|
|
@@ -241,6 +246,9 @@ def _file_relevance(sm: SourceMap, *, limit: int = _FILE_RELEVANCE_LIMIT) -> lis
|
|
|
241
246
|
# Semantic hub bonus: normalised call-graph centrality adds up to +0.30
|
|
242
247
|
sem_hub = semantic_hub_scores.get(path, 0.0) * 0.30
|
|
243
248
|
combined = fs.score + content_rel + sem_hub
|
|
249
|
+
# REST controller boost: surface above @Transactional service files
|
|
250
|
+
if path in _rest_ctrl_paths:
|
|
251
|
+
combined += 2.0
|
|
244
252
|
|
|
245
253
|
# Visibility threshold: require meaningful combined signal.
|
|
246
254
|
# Exception: high/medium-confidence files with strong content relevance
|
|
@@ -1586,8 +1594,8 @@ def write_output(content: str, output: Optional[Path]) -> None:
|
|
|
1586
1594
|
output: Destination file path. None = stdout.
|
|
1587
1595
|
"""
|
|
1588
1596
|
if output is None:
|
|
1589
|
-
sys.stdout.write(content)
|
|
1597
|
+
sys.stdout.buffer.write(content.encode("utf-8"))
|
|
1590
1598
|
if not content.endswith("\n"):
|
|
1591
|
-
sys.stdout.write("\n")
|
|
1599
|
+
sys.stdout.buffer.write(b"\n")
|
|
1592
1600
|
else:
|
|
1593
1601
|
output.write_text(content, encoding="utf-8")
|
{sourcecode-1.2.0 → sourcecode-1.3.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md
RENAMED
|
File without changes
|
{sourcecode-1.2.0 → sourcecode-1.3.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md
RENAMED
|
File without changes
|
{sourcecode-1.2.0 → sourcecode-1.3.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sourcecode-1.2.0 → sourcecode-1.3.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|