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.
Files changed (109) hide show
  1. {sourcecode-1.35.26 → sourcecode-1.35.28}/PKG-INFO +5 -3
  2. {sourcecode-1.35.26 → sourcecode-1.35.28}/README.md +4 -2
  3. {sourcecode-1.35.26 → sourcecode-1.35.28}/pyproject.toml +1 -1
  4. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/__init__.py +1 -1
  5. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/cli.py +244 -3
  6. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/explain.py +3 -0
  7. sourcecode-1.35.28/src/sourcecode/file_chunker.py +397 -0
  8. sourcecode-1.35.28/src/sourcecode/rename_refactor.py +351 -0
  9. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/repository_ir.py +77 -8
  10. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_model.py +2 -0
  11. {sourcecode-1.35.26 → sourcecode-1.35.28}/.github/workflows/build-windows.yml +0 -0
  12. {sourcecode-1.35.26 → sourcecode-1.35.28}/.gitignore +0 -0
  13. {sourcecode-1.35.26 → sourcecode-1.35.28}/.ruff.toml +0 -0
  14. {sourcecode-1.35.26 → sourcecode-1.35.28}/CHANGELOG.md +0 -0
  15. {sourcecode-1.35.26 → sourcecode-1.35.28}/CONTRIBUTING.md +0 -0
  16. {sourcecode-1.35.26 → sourcecode-1.35.28}/LICENSE +0 -0
  17. {sourcecode-1.35.26 → sourcecode-1.35.28}/SECURITY.md +0 -0
  18. {sourcecode-1.35.26 → sourcecode-1.35.28}/raw +0 -0
  19. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/adaptive_scanner.py +0 -0
  20. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/architecture_analyzer.py +0 -0
  21. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/architecture_summary.py +0 -0
  22. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/ast_extractor.py +0 -0
  23. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/cache.py +0 -0
  24. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/canonical_ir.py +0 -0
  25. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/cir_graphs.py +0 -0
  26. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/classifier.py +0 -0
  27. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/code_notes_analyzer.py +0 -0
  28. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/confidence_analyzer.py +0 -0
  29. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/context_scorer.py +0 -0
  30. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/context_summarizer.py +0 -0
  31. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/contract_model.py +0 -0
  32. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/contract_pipeline.py +0 -0
  33. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/coverage_parser.py +0 -0
  34. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/dependency_analyzer.py +0 -0
  35. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/__init__.py +0 -0
  36. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/base.py +0 -0
  37. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/csproj_parser.py +0 -0
  38. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/dart.py +0 -0
  39. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/dotnet.py +0 -0
  40. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/elixir.py +0 -0
  41. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/go.py +0 -0
  42. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/heuristic.py +0 -0
  43. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/hybrid.py +0 -0
  44. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/java.py +0 -0
  45. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/jvm_ext.py +0 -0
  46. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/nodejs.py +0 -0
  47. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/parsers.py +0 -0
  48. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/php.py +0 -0
  49. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/project.py +0 -0
  50. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/python.py +0 -0
  51. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/ruby.py +0 -0
  52. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/rust.py +0 -0
  53. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/systems.py +0 -0
  54. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/terraform.py +0 -0
  55. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/detectors/tooling.py +0 -0
  56. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/doc_analyzer.py +0 -0
  57. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/entrypoint_classifier.py +0 -0
  58. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/env_analyzer.py +0 -0
  59. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/error_schema.py +0 -0
  60. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/file_classifier.py +0 -0
  61. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/flow_analyzer.py +0 -0
  62. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/fqn_utils.py +0 -0
  63. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/git_analyzer.py +0 -0
  64. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/graph_analyzer.py +0 -0
  65. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/license.py +0 -0
  66. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/__init__.py +0 -0
  67. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/__init__.py +0 -0
  68. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/applier.py +0 -0
  69. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/backup.py +0 -0
  70. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/detector.py +0 -0
  71. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/onboarding/planner.py +0 -0
  72. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/orchestrator.py +0 -0
  73. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/registry.py +0 -0
  74. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/runner.py +0 -0
  75. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp/server.py +0 -0
  76. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/mcp_nudge.py +0 -0
  77. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/metrics_analyzer.py +0 -0
  78. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/migrate_check.py +0 -0
  79. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/output_budget.py +0 -0
  80. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/path_filters.py +0 -0
  81. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/pr_comment_renderer.py +0 -0
  82. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/pr_impact.py +0 -0
  83. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/prepare_context.py +0 -0
  84. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/progress.py +0 -0
  85. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/ranking_engine.py +0 -0
  86. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/redactor.py +0 -0
  87. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/relevance_scorer.py +0 -0
  88. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/repo_classifier.py +0 -0
  89. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/ris.py +0 -0
  90. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/runtime_classifier.py +0 -0
  91. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/scanner.py +0 -0
  92. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/schema.py +0 -0
  93. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/semantic_analyzer.py +0 -0
  94. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/serializer.py +0 -0
  95. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_event_topology.py +0 -0
  96. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_findings.py +0 -0
  97. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_impact.py +0 -0
  98. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_security_audit.py +0 -0
  99. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_semantic.py +0 -0
  100. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/spring_tx_analyzer.py +0 -0
  101. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/summarizer.py +0 -0
  102. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/__init__.py +0 -0
  103. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/config.py +0 -0
  104. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/consent.py +0 -0
  105. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/events.py +0 -0
  106. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/filters.py +0 -0
  107. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/telemetry/transport.py +0 -0
  108. {sourcecode-1.35.26 → sourcecode-1.35.28}/src/sourcecode/tree_utils.py +0 -0
  109. {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.26
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
- ![Version](https://img.shields.io/badge/version-1.35.26-blue)
43
+ ![Version](https://img.shields.io/badge/version-1.35.28-blue)
44
44
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
45
45
 
46
46
  ---
@@ -114,7 +114,9 @@ pipx install sourcecode
114
114
 
115
115
  ```bash
116
116
  sourcecode version
117
- # sourcecode 1.35.26
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
- ![Version](https://img.shields.io/badge/version-1.35.26-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.35.28-blue)
6
6
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
7
7
 
8
8
  ---
@@ -76,7 +76,9 @@ pipx install sourcecode
76
76
 
77
77
  ```bash
78
78
  sourcecode version
79
- # sourcecode 1.35.26
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.26"
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"
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Deterministic codebase context maps for AI coding agents."""
2
2
 
3
- __version__ = "1.35.26"
3
+ __version__ = "1.35.28"
@@ -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
- _cs_keys = {"status", "git_head", "stacks", "entry_points",
5163
- "key_dependencies", "project_type", "project_summary",
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 = (