sourcecode 1.35.26__tar.gz → 1.35.28__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.35.26 → sourcecode-1.35.28}/PKG-INFO +5 -3
- {sourcecode-1.35.26 → sourcecode-1.35.28}/README.md +4 -2
- {sourcecode-1.35.26 → sourcecode-1.35.28}/pyproject.toml +1 -1
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/__init__.py +1 -1
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/cli.py +244 -3
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/explain.py +3 -0
- sourcecode-1.35.28/src/sourcecode/file_chunker.py +397 -0
- sourcecode-1.35.28/src/sourcecode/rename_refactor.py +351 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/repository_ir.py +77 -8
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_model.py +2 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/.gitignore +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/.ruff.toml +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/CHANGELOG.md +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/CONTRIBUTING.md +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/LICENSE +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/SECURITY.md +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/raw +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/architecture_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/ast_extractor.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/cache.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/canonical_ir.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/cir_graphs.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/classifier.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/contract_pipeline.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/error_schema.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/flow_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/fqn_utils.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/license.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/__init__.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/applier.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/backup.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/detector.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/planner.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/orchestrator.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/registry.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/runner.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/server.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp_nudge.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/migrate_check.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/output_budget.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/path_filters.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/pr_comment_renderer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/pr_impact.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/progress.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/redactor.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/ris.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/scanner.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/schema.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/serializer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_event_topology.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_findings.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_impact.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_security_audit.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_semantic.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_tx_analyzer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/workspace.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sourcecode
|
|
3
|
-
Version: 1.35.
|
|
3
|
+
Version: 1.35.28
|
|
4
4
|
Summary: Persistent structural context and ultra-fast repeated analysis for AI coding agents
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Keywords: agents,ai,codebase,context,developer-tools,llm
|
|
@@ -40,7 +40,7 @@ Description-Content-Type: text/markdown
|
|
|
40
40
|
|
|
41
41
|
**Persistent structural context and ultra-fast repeated analysis for AI coding agents.**
|
|
42
42
|
|
|
43
|
-

|
|
44
44
|

|
|
45
45
|
|
|
46
46
|
---
|
|
@@ -114,7 +114,9 @@ pipx install sourcecode
|
|
|
114
114
|
|
|
115
115
|
```bash
|
|
116
116
|
sourcecode version
|
|
117
|
-
# sourcecode 1.35.
|
|
117
|
+
# sourcecode 1.35.28
|
|
118
|
+
|
|
119
|
+
**v1.35.28** — 7 bug fixes: `rename-class` cross-package disambiguation (BUG-4), `rename-class` collision detection (BUG-2), `find_java_files` false positive on `com/test/` package paths (BUG-1), `cold-start --compact` correct key names (BUG-6), `@EnableMethodSecurity` no longer suppresses SEC-001 (BUG-3), `explain` @Entity stereotype detection (BUG-5), XML+annotation mixed security retagging (BUG-7).
|
|
118
120
|
```
|
|
119
121
|
|
|
120
122
|
---
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Persistent structural context and ultra-fast repeated analysis for AI coding agents.**
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|

|
|
7
7
|
|
|
8
8
|
---
|
|
@@ -76,7 +76,9 @@ pipx install sourcecode
|
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
78
|
sourcecode version
|
|
79
|
-
# sourcecode 1.35.
|
|
79
|
+
# sourcecode 1.35.28
|
|
80
|
+
|
|
81
|
+
**v1.35.28** — 7 bug fixes: `rename-class` cross-package disambiguation (BUG-4), `rename-class` collision detection (BUG-2), `find_java_files` false positive on `com/test/` package paths (BUG-1), `cold-start --compact` correct key names (BUG-6), `@EnableMethodSecurity` no longer suppresses SEC-001 (BUG-3), `explain` @Entity stereotype detection (BUG-5), XML+annotation mixed security retagging (BUG-7).
|
|
80
82
|
```
|
|
81
83
|
|
|
82
84
|
---
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sourcecode"
|
|
7
|
-
version = "1.35.
|
|
7
|
+
version = "1.35.28"
|
|
8
8
|
description = "Persistent structural context and ultra-fast repeated analysis for AI coding agents"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -242,6 +242,10 @@ _SUBCOMMANDS: frozenset[str] = frozenset(
|
|
|
242
242
|
"explain",
|
|
243
243
|
# Spring Boot 2→3 migration readiness
|
|
244
244
|
"migrate-check",
|
|
245
|
+
# Native file rename (BLOCKER-A)
|
|
246
|
+
"rename-class",
|
|
247
|
+
# Large file semantic chunking (BLOCKER-B)
|
|
248
|
+
"chunk-file",
|
|
245
249
|
}
|
|
246
250
|
)
|
|
247
251
|
|
|
@@ -5009,6 +5013,240 @@ def modernize_cmd(
|
|
|
5009
5013
|
_copy_to_clipboard(output)
|
|
5010
5014
|
|
|
5011
5015
|
|
|
5016
|
+
# ── rename-class ──────────────────────────────────────────────────────────────
|
|
5017
|
+
|
|
5018
|
+
@app.command("rename-class")
|
|
5019
|
+
def rename_class_cmd(
|
|
5020
|
+
path: Path = typer.Argument(
|
|
5021
|
+
Path("."),
|
|
5022
|
+
help="Repository root to operate on (default: current directory)",
|
|
5023
|
+
),
|
|
5024
|
+
old_name: str = typer.Option(
|
|
5025
|
+
..., "--from", "-f",
|
|
5026
|
+
help="Current class name (PascalCase, e.g. ServiceA)",
|
|
5027
|
+
),
|
|
5028
|
+
new_name: str = typer.Option(
|
|
5029
|
+
..., "--to", "-t",
|
|
5030
|
+
help="New class name (PascalCase, e.g. ServiceB)",
|
|
5031
|
+
),
|
|
5032
|
+
dry_run: bool = typer.Option(
|
|
5033
|
+
False, "--dry-run",
|
|
5034
|
+
help="Compute changes but do not write any files or rename on disk.",
|
|
5035
|
+
),
|
|
5036
|
+
no_tests: bool = typer.Option(
|
|
5037
|
+
False, "--no-tests",
|
|
5038
|
+
help="Exclude test files from the rename (src/main only).",
|
|
5039
|
+
),
|
|
5040
|
+
output_path: Optional[Path] = typer.Option(
|
|
5041
|
+
None, "--output", "-o",
|
|
5042
|
+
help="Write change audit JSON to a file instead of stdout.",
|
|
5043
|
+
),
|
|
5044
|
+
copy: bool = typer.Option(
|
|
5045
|
+
False, "--copy", "-c",
|
|
5046
|
+
help="Copy output to clipboard after a successful run.",
|
|
5047
|
+
),
|
|
5048
|
+
format: str = typer.Option(
|
|
5049
|
+
"json", "--format",
|
|
5050
|
+
help="Output format: json (default) or yaml.",
|
|
5051
|
+
),
|
|
5052
|
+
) -> None:
|
|
5053
|
+
"""Rename a Java class throughout the repository (BLOCKER-A fix).
|
|
5054
|
+
|
|
5055
|
+
\b
|
|
5056
|
+
Renames a Java class safely:
|
|
5057
|
+
- Updates class/interface/enum declaration
|
|
5058
|
+
- Updates constructor name
|
|
5059
|
+
- Updates all import statements
|
|
5060
|
+
- Updates all type references (fields, params, return types)
|
|
5061
|
+
- Updates extends / implements
|
|
5062
|
+
- Updates generics, casts, Spring @Qualifier names
|
|
5063
|
+
- Renames the physical .java file
|
|
5064
|
+
- Emits a structured change audit trail (BLOCKER-C)
|
|
5065
|
+
|
|
5066
|
+
\b
|
|
5067
|
+
Examples:
|
|
5068
|
+
sourcecode rename-class . --from ServiceA --to ServiceB
|
|
5069
|
+
sourcecode rename-class /path/to/repo --from OrderManager --to OrderService
|
|
5070
|
+
sourcecode rename-class . --from OldName --to NewName --dry-run
|
|
5071
|
+
sourcecode rename-class . --from OldName --to NewName --output rename-audit.json
|
|
5072
|
+
"""
|
|
5073
|
+
import json as _json
|
|
5074
|
+
from sourcecode.rename_refactor import rename_class
|
|
5075
|
+
|
|
5076
|
+
root = path.resolve()
|
|
5077
|
+
if not root.is_dir():
|
|
5078
|
+
_emit_error_json(
|
|
5079
|
+
INVALID_INPUT_CODE,
|
|
5080
|
+
f"'{root}' is not a valid directory.",
|
|
5081
|
+
path=str(root),
|
|
5082
|
+
hint="Pass an existing repository directory.",
|
|
5083
|
+
expected="A directory path.",
|
|
5084
|
+
)
|
|
5085
|
+
raise typer.Exit(1)
|
|
5086
|
+
|
|
5087
|
+
result = rename_class(
|
|
5088
|
+
root,
|
|
5089
|
+
old_name,
|
|
5090
|
+
new_name,
|
|
5091
|
+
dry_run=dry_run,
|
|
5092
|
+
include_tests=not no_tests,
|
|
5093
|
+
)
|
|
5094
|
+
|
|
5095
|
+
if result.errors:
|
|
5096
|
+
_emit_error_json(
|
|
5097
|
+
"RENAME_ERROR",
|
|
5098
|
+
result.errors[0],
|
|
5099
|
+
errors=result.errors,
|
|
5100
|
+
old_name=old_name,
|
|
5101
|
+
new_name=new_name,
|
|
5102
|
+
)
|
|
5103
|
+
raise typer.Exit(1)
|
|
5104
|
+
|
|
5105
|
+
result_dict = result.to_dict()
|
|
5106
|
+
|
|
5107
|
+
if format == "yaml":
|
|
5108
|
+
from sourcecode.serializer import to_yaml as _to_yaml
|
|
5109
|
+
output = _to_yaml(result_dict)
|
|
5110
|
+
else:
|
|
5111
|
+
output = _json.dumps(result_dict, indent=2, ensure_ascii=False)
|
|
5112
|
+
|
|
5113
|
+
if output_path:
|
|
5114
|
+
output_path.write_text(output, encoding="utf-8")
|
|
5115
|
+
action = "dry-run simulated" if dry_run else "applied"
|
|
5116
|
+
typer.echo(
|
|
5117
|
+
f"[rename-class] {action}: {old_name} → {new_name} "
|
|
5118
|
+
f"({result.files_modified} file(s) changed). "
|
|
5119
|
+
f"Audit written to {output_path}",
|
|
5120
|
+
err=True,
|
|
5121
|
+
)
|
|
5122
|
+
else:
|
|
5123
|
+
try:
|
|
5124
|
+
sys.stdout.buffer.write(output.encode("utf-8"))
|
|
5125
|
+
sys.stdout.buffer.write(b"\n")
|
|
5126
|
+
sys.stdout.buffer.flush()
|
|
5127
|
+
except AttributeError:
|
|
5128
|
+
sys.stdout.write(output + "\n")
|
|
5129
|
+
|
|
5130
|
+
if copy:
|
|
5131
|
+
_copy_to_clipboard(output)
|
|
5132
|
+
|
|
5133
|
+
if not dry_run and not output_path:
|
|
5134
|
+
action = "Renamed"
|
|
5135
|
+
typer.echo(
|
|
5136
|
+
f"[rename-class] {action}: {old_name} → {new_name} "
|
|
5137
|
+
f"({result.files_modified} file(s) updated, file renamed to {result.new_file})",
|
|
5138
|
+
err=True,
|
|
5139
|
+
)
|
|
5140
|
+
|
|
5141
|
+
|
|
5142
|
+
# ── chunk-file ────────────────────────────────────────────────────────────────
|
|
5143
|
+
|
|
5144
|
+
@app.command("chunk-file")
|
|
5145
|
+
def chunk_file_cmd(
|
|
5146
|
+
file: Path = typer.Argument(
|
|
5147
|
+
...,
|
|
5148
|
+
help="Java file to chunk (absolute or relative path)",
|
|
5149
|
+
),
|
|
5150
|
+
max_lines: int = typer.Option(
|
|
5151
|
+
500, "--max-lines", "-n",
|
|
5152
|
+
help="Target max lines per chunk (default: 500). Methods > max_lines emit size_warning.",
|
|
5153
|
+
),
|
|
5154
|
+
chunk_id: Optional[int] = typer.Option(
|
|
5155
|
+
None, "--chunk", "-c",
|
|
5156
|
+
help="Return only this chunk by ID (1-based). Omit to return all chunks.",
|
|
5157
|
+
),
|
|
5158
|
+
metadata_only: bool = typer.Option(
|
|
5159
|
+
False, "--metadata-only",
|
|
5160
|
+
help="Return chunk boundaries and metadata without file content.",
|
|
5161
|
+
),
|
|
5162
|
+
output_path: Optional[Path] = typer.Option(
|
|
5163
|
+
None, "--output", "-o",
|
|
5164
|
+
help="Write output to a file instead of stdout.",
|
|
5165
|
+
),
|
|
5166
|
+
format: str = typer.Option(
|
|
5167
|
+
"json", "--format",
|
|
5168
|
+
help="Output format: json (default) or yaml.",
|
|
5169
|
+
),
|
|
5170
|
+
copy: bool = typer.Option(
|
|
5171
|
+
False, "--copy",
|
|
5172
|
+
help="Copy output to clipboard after a successful run.",
|
|
5173
|
+
),
|
|
5174
|
+
) -> None:
|
|
5175
|
+
"""Split a large Java file into semantic chunks for AI agent consumption (BLOCKER-B fix).
|
|
5176
|
+
|
|
5177
|
+
\b
|
|
5178
|
+
Splits a Java file at method/class boundaries so AI agents can read
|
|
5179
|
+
large files (10K–25K+ lines) in context-sized pieces without timeout
|
|
5180
|
+
or fragmented analysis.
|
|
5181
|
+
|
|
5182
|
+
Each chunk includes:
|
|
5183
|
+
- chunk_id, start_line, end_line, chunk_type, symbol name
|
|
5184
|
+
- context_header: package + class + imports summary
|
|
5185
|
+
- content: source lines for that chunk
|
|
5186
|
+
- size_warning: True if chunk > max_lines (cannot split mid-method)
|
|
5187
|
+
|
|
5188
|
+
\b
|
|
5189
|
+
Examples:
|
|
5190
|
+
sourcecode chunk-file NominasCalculoService.java
|
|
5191
|
+
sourcecode chunk-file BigService.java --max-lines 300
|
|
5192
|
+
sourcecode chunk-file BigService.java --chunk 5 # read chunk 5 only
|
|
5193
|
+
sourcecode chunk-file BigService.java --metadata-only # sizes/boundaries only
|
|
5194
|
+
"""
|
|
5195
|
+
import json as _json
|
|
5196
|
+
from sourcecode.file_chunker import chunk_java_file
|
|
5197
|
+
|
|
5198
|
+
abs_file = file.resolve()
|
|
5199
|
+
if not abs_file.is_file():
|
|
5200
|
+
_emit_error_json(
|
|
5201
|
+
INVALID_INPUT_CODE,
|
|
5202
|
+
f"'{abs_file}' is not a valid file.",
|
|
5203
|
+
path=str(abs_file),
|
|
5204
|
+
hint="Pass an existing Java source file.",
|
|
5205
|
+
expected="A .java file path.",
|
|
5206
|
+
)
|
|
5207
|
+
raise typer.Exit(1)
|
|
5208
|
+
|
|
5209
|
+
result = chunk_java_file(abs_file, max_lines=max_lines, include_content=not metadata_only)
|
|
5210
|
+
|
|
5211
|
+
if chunk_id is not None:
|
|
5212
|
+
# Return single chunk
|
|
5213
|
+
matching = [c for c in result.chunks if c.chunk_id == chunk_id]
|
|
5214
|
+
if not matching:
|
|
5215
|
+
_emit_error_json(
|
|
5216
|
+
INVALID_INPUT_CODE,
|
|
5217
|
+
f"Chunk {chunk_id} not found. File has {result.total_chunks} chunks.",
|
|
5218
|
+
chunk_id=chunk_id,
|
|
5219
|
+
total_chunks=result.total_chunks,
|
|
5220
|
+
)
|
|
5221
|
+
raise typer.Exit(1)
|
|
5222
|
+
result_dict = matching[0].to_dict()
|
|
5223
|
+
else:
|
|
5224
|
+
result_dict = result.to_dict()
|
|
5225
|
+
|
|
5226
|
+
if format == "yaml":
|
|
5227
|
+
from sourcecode.serializer import to_yaml as _to_yaml
|
|
5228
|
+
output = _to_yaml(result_dict)
|
|
5229
|
+
else:
|
|
5230
|
+
output = _json.dumps(result_dict, indent=2, ensure_ascii=False)
|
|
5231
|
+
|
|
5232
|
+
if output_path:
|
|
5233
|
+
output_path.write_text(output, encoding="utf-8")
|
|
5234
|
+
typer.echo(
|
|
5235
|
+
f"[chunk-file] {result.total_chunks} chunks written to {output_path}",
|
|
5236
|
+
err=True,
|
|
5237
|
+
)
|
|
5238
|
+
else:
|
|
5239
|
+
try:
|
|
5240
|
+
sys.stdout.buffer.write(output.encode("utf-8"))
|
|
5241
|
+
sys.stdout.buffer.write(b"\n")
|
|
5242
|
+
sys.stdout.buffer.flush()
|
|
5243
|
+
except AttributeError:
|
|
5244
|
+
sys.stdout.write(output + "\n")
|
|
5245
|
+
|
|
5246
|
+
if copy:
|
|
5247
|
+
_copy_to_clipboard(output)
|
|
5248
|
+
|
|
5249
|
+
|
|
5012
5250
|
# ── version ───────────────────────────────────────────────────────────────────
|
|
5013
5251
|
|
|
5014
5252
|
@app.command("activate")
|
|
@@ -5159,10 +5397,13 @@ def cold_start_cmd(
|
|
|
5159
5397
|
result = _gcs(target)
|
|
5160
5398
|
if compact:
|
|
5161
5399
|
# P1-C: cap at ~10K tokens — keep only fields essential for orientation.
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
"validation", "_meta"}
|
|
5400
|
+
# BUG-6 fix: use actual RIS key names (summary/entrypoints, not stacks/entry_points)
|
|
5401
|
+
_cs_keys = {"status", "git_head", "summary", "entrypoints", "endpoints",
|
|
5402
|
+
"project_type", "validation", "_meta"}
|
|
5165
5403
|
result = {k: v for k, v in result.items() if k in _cs_keys}
|
|
5404
|
+
# Truncate endpoints to first 30 to stay within ~10K token budget
|
|
5405
|
+
if isinstance(result.get("endpoints"), list):
|
|
5406
|
+
result["endpoints"] = result["endpoints"][:30]
|
|
5166
5407
|
result["_meta"] = {**(result.get("_meta") or {}), "compact_mode": True,
|
|
5167
5408
|
"full_available": "sourcecode cold-start (without --compact)"}
|
|
5168
5409
|
_out = _json.dumps(result, indent=2, ensure_ascii=False)
|
|
@@ -28,6 +28,9 @@ _STEREOTYPE_DESC: dict[str, str] = {
|
|
|
28
28
|
"component": "Spring @Component — general-purpose bean",
|
|
29
29
|
"configuration": "Spring @Configuration — bean factory / config",
|
|
30
30
|
"bean": "Spring @Bean — managed component",
|
|
31
|
+
"entity": "JPA @Entity — persistent domain object mapped to a database table",
|
|
32
|
+
"mappedsuperclass": "JPA @MappedSuperclass — base class sharing persistent state with subclasses",
|
|
33
|
+
"embeddable": "JPA @Embeddable — value object embedded in owning entity table",
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
_SECURITY_ANNOTATION_PREFIXES = (
|