wicked-garden 12.27.0

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 (640) hide show
  1. package/.claude-plugin/archetypes.json +166 -0
  2. package/.claude-plugin/components.json +75 -0
  3. package/.claude-plugin/marketplace.json +15 -0
  4. package/.claude-plugin/plugin.json +174 -0
  5. package/.claude-plugin/specialist.json +48 -0
  6. package/.claude-plugin/stack-registry.json +96 -0
  7. package/AGENTS.md +13 -0
  8. package/CHANGELOG.md +712 -0
  9. package/CONTRIBUTING.md +99 -0
  10. package/ETHOS.md +83 -0
  11. package/LICENSE +21 -0
  12. package/README.md +115 -0
  13. package/WICKED_GARDEN_BUS_EVENTS.md +149 -0
  14. package/agents/agentic/architect.md +449 -0
  15. package/agents/agentic/performance-analyst.md +702 -0
  16. package/agents/agentic/safety-reviewer.md +662 -0
  17. package/agents/crew/implementer.md +163 -0
  18. package/agents/crew/researcher.md +94 -0
  19. package/agents/crew/reviewer.md +184 -0
  20. package/agents/data/data-engineer.md +227 -0
  21. package/agents/engineering/api-documentarian.md +440 -0
  22. package/agents/engineering/migration-engineer.md +301 -0
  23. package/agents/engineering/solution-architect.md +208 -0
  24. package/agents/jam/brainstorm-facilitator.md +297 -0
  25. package/agents/jam/council.md +322 -0
  26. package/agents/jam/quick-facilitator.md +85 -0
  27. package/agents/persona/persona-agent.md +121 -0
  28. package/agents/platform/compliance-officer.md +266 -0
  29. package/agents/platform/privacy-expert.md +496 -0
  30. package/agents/platform/security-engineer.md +287 -0
  31. package/agents/product/a11y-expert.md +323 -0
  32. package/agents/product/requirements-analyst.md +238 -0
  33. package/agents/product/ui-reviewer.md +180 -0
  34. package/agents/product/ux-designer.md +199 -0
  35. package/agents/product/value-strategist.md +269 -0
  36. package/agents/qe/semantic-reviewer.md +78 -0
  37. package/commands/agentic/audit.md +24 -0
  38. package/commands/agentic/design.md +24 -0
  39. package/commands/agentic/frameworks.md +25 -0
  40. package/commands/agentic/review.md +27 -0
  41. package/commands/archetype/build.md +12 -0
  42. package/commands/archetype/decide.md +12 -0
  43. package/commands/archetype/explore.md +12 -0
  44. package/commands/archetype/incident.md +12 -0
  45. package/commands/archetype/migrate.md +12 -0
  46. package/commands/archetype/modernize.md +12 -0
  47. package/commands/archetype/review.md +14 -0
  48. package/commands/archetype/ship.md +12 -0
  49. package/commands/archetype/specify.md +12 -0
  50. package/commands/archetype/triage.md +12 -0
  51. package/commands/compile.md +37 -0
  52. package/commands/data/analyze.md +18 -0
  53. package/commands/data/data.md +21 -0
  54. package/commands/data/ml.md +18 -0
  55. package/commands/data/ontology.md +22 -0
  56. package/commands/data/pipeline.md +17 -0
  57. package/commands/deliberate.md +181 -0
  58. package/commands/engineering/add-field.md +77 -0
  59. package/commands/engineering/apply.md +58 -0
  60. package/commands/engineering/arch.md +26 -0
  61. package/commands/engineering/debug.md +27 -0
  62. package/commands/engineering/docs.md +27 -0
  63. package/commands/engineering/new-generator.md +257 -0
  64. package/commands/engineering/patch-plan.md +59 -0
  65. package/commands/engineering/plan.md +29 -0
  66. package/commands/engineering/remove.md +48 -0
  67. package/commands/engineering/rename.md +44 -0
  68. package/commands/engineering/review.md +32 -0
  69. package/commands/help.md +128 -0
  70. package/commands/install.md +118 -0
  71. package/commands/intent.md +54 -0
  72. package/commands/jam/brainstorm.md +37 -0
  73. package/commands/jam/council.md +49 -0
  74. package/commands/jam/quick.md +21 -0
  75. package/commands/jam/revisit.md +79 -0
  76. package/commands/persona/as.md +136 -0
  77. package/commands/persona/define.md +24 -0
  78. package/commands/persona/list.md +118 -0
  79. package/commands/platform/actions.md +20 -0
  80. package/commands/platform/assert.md +18 -0
  81. package/commands/platform/audit.md +23 -0
  82. package/commands/platform/compliance.md +20 -0
  83. package/commands/platform/gh.md +22 -0
  84. package/commands/platform/health.md +22 -0
  85. package/commands/platform/incident.md +23 -0
  86. package/commands/platform/infra.md +24 -0
  87. package/commands/platform/peer-health.md +103 -0
  88. package/commands/platform/plugin-health.md +58 -0
  89. package/commands/platform/security.md +38 -0
  90. package/commands/platform/toolchain.md +96 -0
  91. package/commands/platform/traces.md +20 -0
  92. package/commands/product/a11y.md +19 -0
  93. package/commands/product/acceptance.md +19 -0
  94. package/commands/product/align.md +20 -0
  95. package/commands/product/analyze.md +23 -0
  96. package/commands/product/elicit.md +19 -0
  97. package/commands/product/listen.md +24 -0
  98. package/commands/product/mockup.md +20 -0
  99. package/commands/product/screenshot.md +19 -0
  100. package/commands/product/strategy.md +40 -0
  101. package/commands/product/synthesize.md +23 -0
  102. package/commands/product/ux-review.md +42 -0
  103. package/commands/product/ux.md +20 -0
  104. package/commands/product/visual-direction.md +34 -0
  105. package/commands/prove.md +47 -0
  106. package/commands/report-issue.md +243 -0
  107. package/commands/reset.md +144 -0
  108. package/commands/search/blast-radius.md +58 -0
  109. package/commands/search/hotspots.md +55 -0
  110. package/commands/search/index.md +38 -0
  111. package/commands/search/lineage.md +47 -0
  112. package/commands/search/service-map.md +79 -0
  113. package/commands/setup.md +363 -0
  114. package/commands/smaht/briefing.md +200 -0
  115. package/commands/smaht/events-import.md +95 -0
  116. package/commands/smaht/state.md +19 -0
  117. package/commands/where-am-i.md +58 -0
  118. package/docs/README.md +32 -0
  119. package/docs/adr/0001-code-relationship-graph-engine.md +116 -0
  120. package/docs/adr/0002-major-cleanup-keep-cut.md +91 -0
  121. package/docs/adr/0003-peers-gate-required-layers-optin.md +41 -0
  122. package/docs/adr/0004-code-graph-moves-to-wicked-brain.md +47 -0
  123. package/docs/brain-chunk-format.md +135 -0
  124. package/docs/compiler.md +95 -0
  125. package/docs/daemon-api.md +70 -0
  126. package/docs/domains.md +197 -0
  127. package/docs/getting-started.md +208 -0
  128. package/docs/plans/2026-06-08-wicked-loom-conduct.md +1337 -0
  129. package/docs/plans/2026-06-08-wicked-loom-contract.md +638 -0
  130. package/docs/plans/2026-06-08-wicked-loom-cutover.md +1300 -0
  131. package/docs/plans/2026-06-08-wicked-loom-expand-compose.md +843 -0
  132. package/docs/plans/2026-06-08-wicked-loom-flow-cutover.md +403 -0
  133. package/docs/plans/2026-06-10-codegraph-to-brain-phase1a-graph-core.md +838 -0
  134. package/docs/plans/2026-06-10-codegraph-to-brain-phase1b-injected-edges.md +44 -0
  135. package/docs/required-peers.md +60 -0
  136. package/docs/specs/2026-06-08-wicked-loom-extraction.md +225 -0
  137. package/docs/specs/2026-06-10-codegraph-to-brain-migration.md +168 -0
  138. package/docs/v11/archetypes.md +231 -0
  139. package/hooks/hooks.json +275 -0
  140. package/hooks/scripts/bootstrap.py +1797 -0
  141. package/hooks/scripts/invoke.py +62 -0
  142. package/hooks/scripts/notification.py +166 -0
  143. package/hooks/scripts/permission_request.py +223 -0
  144. package/hooks/scripts/post_tool.py +1374 -0
  145. package/hooks/scripts/pre_compact.py +272 -0
  146. package/hooks/scripts/pre_tool.py +1278 -0
  147. package/hooks/scripts/prompt_submit.py +1109 -0
  148. package/hooks/scripts/session_end.py +95 -0
  149. package/hooks/scripts/stop.py +624 -0
  150. package/hooks/scripts/subagent_lifecycle.py +464 -0
  151. package/hooks/scripts/subscribers/on_gate_decided.py +84 -0
  152. package/hooks/scripts/task_completed.py +322 -0
  153. package/hooks/scripts/worktree_guard.py +148 -0
  154. package/hooks/subscriptions/on_gate_decided.json +9 -0
  155. package/install.mjs +128 -0
  156. package/package.json +41 -0
  157. package/pyproject.toml +59 -0
  158. package/schemas/README.md +32 -0
  159. package/schemas/assert_contracts.json +37 -0
  160. package/schemas/health_probe.json +46 -0
  161. package/schemas/plugin_status.json +37 -0
  162. package/scripts/_adapters/__init__.py +166 -0
  163. package/scripts/_adapters/jira_adapter.py +18 -0
  164. package/scripts/_adapters/linear_adapter.py +18 -0
  165. package/scripts/_adapters/miro_adapter.py +18 -0
  166. package/scripts/_adapters/notion_adapter.py +18 -0
  167. package/scripts/_agents.py +357 -0
  168. package/scripts/_brain_ingest/__init__.py +2 -0
  169. package/scripts/_brain_ingest/session_fact_extractor.py +341 -0
  170. package/scripts/_brain_port.py +163 -0
  171. package/scripts/_bus.py +1081 -0
  172. package/scripts/_bus_catalog_gen.py +93 -0
  173. package/scripts/_bus_consumers.json +46 -0
  174. package/scripts/_bus_emit.py +43 -0
  175. package/scripts/_capability_registry.py +334 -0
  176. package/scripts/_capability_resolver.py +322 -0
  177. package/scripts/_domain_store.py +559 -0
  178. package/scripts/_event_log_reader.py +154 -0
  179. package/scripts/_event_schema.py +305 -0
  180. package/scripts/_event_store.py +397 -0
  181. package/scripts/_heavy_cadence.py +324 -0
  182. package/scripts/_integration_resolver.py +321 -0
  183. package/scripts/_logger.py +151 -0
  184. package/scripts/_loom.py +482 -0
  185. package/scripts/_paths.py +133 -0
  186. package/scripts/_python.sh +22 -0
  187. package/scripts/_run.py +137 -0
  188. package/scripts/_session.py +502 -0
  189. package/scripts/_validate_registry.py +1042 -0
  190. package/scripts/_wicked_testing_probe.py +277 -0
  191. package/scripts/agentic/analyze_agents.py +391 -0
  192. package/scripts/agentic/detect_framework.py +420 -0
  193. package/scripts/agentic/issue_taxonomy.py +357 -0
  194. package/scripts/agentic/pattern_scorer.py +434 -0
  195. package/scripts/classify/persist.py +169 -0
  196. package/scripts/compiler/compile.py +552 -0
  197. package/scripts/compiler/phase0/VERDICT.md +60 -0
  198. package/scripts/compiler/phase0/detect.py +292 -0
  199. package/scripts/compiler/phase0/emit.py +228 -0
  200. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.bindings.json +30 -0
  201. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.lint-output.txt +17 -0
  202. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/.wg/evidence/failing-tests.txt +4 -0
  203. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/.wg/evidence/honest-tests.txt +2 -0
  204. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/fab-fail.build.md +8 -0
  205. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/fab-missing.build.md +8 -0
  206. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/honest.build.md +8 -0
  207. package/scripts/compiler/phase0/evidence/Enterprise-AISDLC.stage/wg_check_claims.py +174 -0
  208. package/scripts/compiler/phase0/evidence/command_iq.bindings.json +45 -0
  209. package/scripts/compiler/phase0/evidence/command_iq.lint-output.txt +17 -0
  210. package/scripts/compiler/phase0/evidence/command_iq.stage/.projects/evidence-domain/phase-1-clarify/evidence/failing-tests.txt +4 -0
  211. package/scripts/compiler/phase0/evidence/command_iq.stage/.projects/evidence-domain/phase-1-clarify/evidence/honest-tests.txt +3 -0
  212. package/scripts/compiler/phase0/evidence/command_iq.stage/fab-fail.build.md +8 -0
  213. package/scripts/compiler/phase0/evidence/command_iq.stage/fab-missing.build.md +8 -0
  214. package/scripts/compiler/phase0/evidence/command_iq.stage/honest.build.md +8 -0
  215. package/scripts/compiler/phase0/evidence/command_iq.stage/wg_check_claims.py +174 -0
  216. package/scripts/compiler/phase0/evidence/memos.bindings.json +28 -0
  217. package/scripts/compiler/phase0/evidence/memos.lint-output.txt +17 -0
  218. package/scripts/compiler/phase0/evidence/memos.stage/.wg/evidence/failing-tests.txt +4 -0
  219. package/scripts/compiler/phase0/evidence/memos.stage/.wg/evidence/honest-tests.txt +2 -0
  220. package/scripts/compiler/phase0/evidence/memos.stage/fab-fail.build.md +8 -0
  221. package/scripts/compiler/phase0/evidence/memos.stage/fab-missing.build.md +8 -0
  222. package/scripts/compiler/phase0/evidence/memos.stage/honest.build.md +8 -0
  223. package/scripts/compiler/phase0/evidence/memos.stage/wg_check_claims.py +174 -0
  224. package/scripts/compiler/phase0/evidence/verdict.json +104 -0
  225. package/scripts/compiler/phase0/evidence/wicked-bus.bindings.json +29 -0
  226. package/scripts/compiler/phase0/evidence/wicked-bus.lint-output.txt +17 -0
  227. package/scripts/compiler/phase0/evidence/wicked-bus.stage/coverage/failing-tests.txt +4 -0
  228. package/scripts/compiler/phase0/evidence/wicked-bus.stage/coverage/honest-tests.txt +3 -0
  229. package/scripts/compiler/phase0/evidence/wicked-bus.stage/fab-fail.build.md +8 -0
  230. package/scripts/compiler/phase0/evidence/wicked-bus.stage/fab-missing.build.md +8 -0
  231. package/scripts/compiler/phase0/evidence/wicked-bus.stage/honest.build.md +8 -0
  232. package/scripts/compiler/phase0/evidence/wicked-bus.stage/wg_check_claims.py +174 -0
  233. package/scripts/compiler/phase0/evidence/wire-vault-transcript.txt +60 -0
  234. package/scripts/compiler/phase0/run_probe.py +234 -0
  235. package/scripts/compiler/phase0/wire_vault.py +310 -0
  236. package/scripts/crew/__init__.py +0 -0
  237. package/scripts/crew/_task_audit_writer.py +243 -0
  238. package/scripts/crew/_task_reader.py +389 -0
  239. package/scripts/crew/archetypes_v11.py +348 -0
  240. package/scripts/crew/detectors/__init__.py +12 -0
  241. package/scripts/crew/flow_compiler.py +121 -0
  242. package/scripts/crew/phase_manager.py +703 -0
  243. package/scripts/crew/scope_delta.py +264 -0
  244. package/scripts/crew/specialist_resolver.py +218 -0
  245. package/scripts/crew/stack_registry.py +189 -0
  246. package/scripts/data/data_profiler.py +271 -0
  247. package/scripts/data/ontology_recommender.py +231 -0
  248. package/scripts/data/schema_validator.py +267 -0
  249. package/scripts/delivery/drift.py +739 -0
  250. package/scripts/delivery/telemetry.py +614 -0
  251. package/scripts/engineering/patch/codegraph_db.py +125 -0
  252. package/scripts/engineering/patch/generators/__init__.py +56 -0
  253. package/scripts/engineering/patch/generators/base.py +373 -0
  254. package/scripts/engineering/patch/generators/csharp_generator.py +494 -0
  255. package/scripts/engineering/patch/generators/go_generator.py +430 -0
  256. package/scripts/engineering/patch/generators/java_generator.py +928 -0
  257. package/scripts/engineering/patch/generators/jsp_generator.py +454 -0
  258. package/scripts/engineering/patch/generators/kotlin_generator.py +561 -0
  259. package/scripts/engineering/patch/generators/perl_generator.py +510 -0
  260. package/scripts/engineering/patch/generators/php_generator.py +644 -0
  261. package/scripts/engineering/patch/generators/propagation_engine.py +929 -0
  262. package/scripts/engineering/patch/generators/python_generator.py +487 -0
  263. package/scripts/engineering/patch/generators/ruby_generator.py +463 -0
  264. package/scripts/engineering/patch/generators/rust_generator.py +400 -0
  265. package/scripts/engineering/patch/generators/sql_generator.py +594 -0
  266. package/scripts/engineering/patch/generators/typescript_generator.py +439 -0
  267. package/scripts/engineering/patch/patch.py +800 -0
  268. package/scripts/engineering/patch/safety.py +429 -0
  269. package/scripts/jam/__init__.py +0 -0
  270. package/scripts/jam/_bus_consumers.py +271 -0
  271. package/scripts/jam/agentic_cli_registry.py +703 -0
  272. package/scripts/jam/consensus.py +737 -0
  273. package/scripts/jam/detect_clis.py +409 -0
  274. package/scripts/jam/jam.py +283 -0
  275. package/scripts/jam/save_transcript.py +171 -0
  276. package/scripts/loom/__init__.py +22 -0
  277. package/scripts/loom/cli.py +170 -0
  278. package/scripts/loom/compose.py +180 -0
  279. package/scripts/loom/gate.py +120 -0
  280. package/scripts/loom/manifest.py +140 -0
  281. package/scripts/loom/resolve.py +59 -0
  282. package/scripts/persona/__init__.py +0 -0
  283. package/scripts/persona/registry.py +688 -0
  284. package/scripts/platform/guard_pipeline.py +1214 -0
  285. package/scripts/platform/guard_profiles.py +216 -0
  286. package/scripts/platform/observability/assert_contracts.py +434 -0
  287. package/scripts/platform/observability/health_probe.py +915 -0
  288. package/scripts/platform/observability/ops_log_viewer.py +209 -0
  289. package/scripts/platform/prereq_doctor.py +567 -0
  290. package/scripts/qe/conditions_manifest.py +260 -0
  291. package/scripts/qe/content_sanitizer.py +160 -0
  292. package/scripts/qe/coverage_tracker.py +535 -0
  293. package/scripts/qe/discover_scenarios.py +243 -0
  294. package/scripts/qe/evidence_tracker.py +232 -0
  295. package/scripts/qe/prove.py +196 -0
  296. package/scripts/qe/registry_lookup.py +80 -0
  297. package/scripts/qe/registry_store.py +176 -0
  298. package/scripts/qe/semantic_review.py +1005 -0
  299. package/scripts/qe/vault_gate.py +382 -0
  300. package/scripts/qe/verdict_audit.py +175 -0
  301. package/scripts/qe/verdict_schema.py +335 -0
  302. package/scripts/reset.py +220 -0
  303. package/scripts/resolve_path.py +22 -0
  304. package/scripts/sentinel/invariants.py +402 -0
  305. package/scripts/sentinel/pre_push.py +73 -0
  306. package/scripts/setup/__init__.py +1 -0
  307. package/scripts/setup/detect_state.py +114 -0
  308. package/scripts/setup/migrate_legacy.py +67 -0
  309. package/scripts/setup/migrate_v6_projects.py +232 -0
  310. package/scripts/setup/onboarding.py +114 -0
  311. package/scripts/smaht/_bus_consumers.py +98 -0
  312. package/scripts/smaht/adapters/__init__.py +83 -0
  313. package/scripts/smaht/adapters/brain_adapter.py +254 -0
  314. package/scripts/smaht/adapters/context7_adapter.py +438 -0
  315. package/scripts/smaht/adapters/delegation_adapter.py +104 -0
  316. package/scripts/smaht/adapters/domain_adapter.py +206 -0
  317. package/scripts/smaht/adapters/events_adapter.py +231 -0
  318. package/scripts/smaht/adapters/tools_adapter.py +49 -0
  319. package/scripts/smaht/cheatsheet_store.py +236 -0
  320. package/scripts/smaht/context_package.py +386 -0
  321. package/scripts/smaht/knowledge_graph.py +395 -0
  322. package/scripts/smaht/propose_skills.py +856 -0
  323. package/scripts/smaht/test_cheatsheet_store.py +428 -0
  324. package/scripts/statusline.py +151 -0
  325. package/scripts/where_am_i.py +236 -0
  326. package/skills/agentic/agentic-patterns/SKILL.md +91 -0
  327. package/skills/agentic/agentic-patterns/refs/anti-patterns-design.md +283 -0
  328. package/skills/agentic/agentic-patterns/refs/anti-patterns-operational.md +216 -0
  329. package/skills/agentic/agentic-patterns/refs/pattern-catalog.md +329 -0
  330. package/skills/agentic/context-engineering/SKILL.md +142 -0
  331. package/skills/agentic/context-engineering/refs/caching-and-optimization.md +251 -0
  332. package/skills/agentic/context-engineering/refs/compression-techniques.md +171 -0
  333. package/skills/agentic/context-engineering/refs/cost-calculation-budget.md +250 -0
  334. package/skills/agentic/context-engineering/refs/cost-optimization-reporting.md +300 -0
  335. package/skills/agentic/context-engineering/refs/selective-loading.md +179 -0
  336. package/skills/agentic/frameworks/SKILL.md +191 -0
  337. package/skills/agentic/frameworks/refs/framework-profiles-1.md +209 -0
  338. package/skills/agentic/frameworks/refs/framework-profiles-2.md +214 -0
  339. package/skills/agentic/frameworks/refs/migration-patterns-paths.md +267 -0
  340. package/skills/agentic/frameworks/refs/migration-patterns-testing.md +208 -0
  341. package/skills/agentic/refs/audit.md +134 -0
  342. package/skills/agentic/refs/design.md +137 -0
  343. package/skills/agentic/refs/frameworks.md +102 -0
  344. package/skills/agentic/refs/review.md +160 -0
  345. package/skills/agentic/review-methodology/SKILL.md +186 -0
  346. package/skills/agentic/review-methodology/refs/deliverable-templates.md +246 -0
  347. package/skills/agentic/review-methodology/refs/issue-taxonomy-quality-testing.md +277 -0
  348. package/skills/agentic/review-methodology/refs/issue-taxonomy-reliability-safety.md +253 -0
  349. package/skills/agentic/trust-and-safety/SKILL.md +177 -0
  350. package/skills/agentic/trust-and-safety/refs/guardrails-actions.md +246 -0
  351. package/skills/agentic/trust-and-safety/refs/guardrails-input-output.md +238 -0
  352. package/skills/agentic/trust-and-safety/refs/guardrails-resources.md +209 -0
  353. package/skills/agentic/trust-and-safety/refs/safety-checklist-advanced.md +209 -0
  354. package/skills/agentic/trust-and-safety/refs/safety-checklist-core.md +215 -0
  355. package/skills/archetype/SKILL.md +104 -0
  356. package/skills/archetype/refs/build.md +142 -0
  357. package/skills/archetype/refs/decide.md +117 -0
  358. package/skills/archetype/refs/explore.md +66 -0
  359. package/skills/archetype/refs/incident.md +149 -0
  360. package/skills/archetype/refs/migrate.md +170 -0
  361. package/skills/archetype/refs/modernize.md +187 -0
  362. package/skills/archetype/refs/review.md +145 -0
  363. package/skills/archetype/refs/ship.md +117 -0
  364. package/skills/archetype/refs/specify.md +108 -0
  365. package/skills/archetype/refs/triage.md +62 -0
  366. package/skills/classify/SKILL.md +157 -0
  367. package/skills/data/analysis/SKILL.md +125 -0
  368. package/skills/data/analysis/refs/templates.md +170 -0
  369. package/skills/data/data/SKILL.md +118 -0
  370. package/skills/data/data/refs/examples.md +235 -0
  371. package/skills/data/ml/SKILL.md +125 -0
  372. package/skills/data/ml/refs/templates.md +172 -0
  373. package/skills/data/pipeline/SKILL.md +136 -0
  374. package/skills/data/pipeline/refs/templates.md +175 -0
  375. package/skills/data/refs/analyze.md +123 -0
  376. package/skills/data/refs/data.md +95 -0
  377. package/skills/data/refs/ml.md +118 -0
  378. package/skills/data/refs/pipeline.md +92 -0
  379. package/skills/deliberate/SKILL.md +125 -0
  380. package/skills/deliberate/refs/architecture-lens.md +37 -0
  381. package/skills/deliberate/refs/assumptions-lens.md +43 -0
  382. package/skills/deliberate/refs/code-lens.md +38 -0
  383. package/skills/deliberate/refs/content-lens.md +37 -0
  384. package/skills/deliberate/refs/data-lens.md +43 -0
  385. package/skills/deliberate/refs/design-lens.md +37 -0
  386. package/skills/deliberate/refs/opportunity-patterns.md +107 -0
  387. package/skills/deliberate/refs/ops-lens.md +43 -0
  388. package/skills/deliberate/refs/product-lens.md +46 -0
  389. package/skills/deliberate/refs/rethink-framework.md +77 -0
  390. package/skills/deliberate/refs/security-lens.md +47 -0
  391. package/skills/deliberate/refs/testing-lens.md +45 -0
  392. package/skills/deliberate/refs/timing-lens.md +42 -0
  393. package/skills/engineering/architecture/SKILL.md +177 -0
  394. package/skills/engineering/architecture/refs/adr-template.md +268 -0
  395. package/skills/engineering/architecture/refs/architecture-template-deployment.md +176 -0
  396. package/skills/engineering/architecture/refs/architecture-template-design.md +300 -0
  397. package/skills/engineering/architecture/refs/examples-ecommerce-analytics.md +299 -0
  398. package/skills/engineering/architecture/refs/examples-saas-trading.md +291 -0
  399. package/skills/engineering/architecture/refs/patterns-advanced.md +238 -0
  400. package/skills/engineering/architecture/refs/patterns-structural.md +303 -0
  401. package/skills/engineering/backend/SKILL.md +102 -0
  402. package/skills/engineering/backend/refs/checklists.md +146 -0
  403. package/skills/engineering/backend/refs/patterns.md +181 -0
  404. package/skills/engineering/debugging/SKILL.md +99 -0
  405. package/skills/engineering/debugging/refs/patterns.md +248 -0
  406. package/skills/engineering/debugging/refs/process.md +203 -0
  407. package/skills/engineering/docs/SKILL.md +97 -0
  408. package/skills/engineering/engineering/SKILL.md +88 -0
  409. package/skills/engineering/engineering/refs/checklists.md +91 -0
  410. package/skills/engineering/engineering/refs/templates.md +71 -0
  411. package/skills/engineering/frontend/SKILL.md +92 -0
  412. package/skills/engineering/frontend/refs/checklists.md +96 -0
  413. package/skills/engineering/frontend/refs/patterns.md +167 -0
  414. package/skills/engineering/integration/SKILL.md +183 -0
  415. package/skills/engineering/integration/refs/error-handling-best-practices.md +139 -0
  416. package/skills/engineering/integration/refs/error-handling-error-classes-typescript.md +212 -0
  417. package/skills/engineering/integration/refs/error-handling-error-response-format.md +301 -0
  418. package/skills/engineering/integration/refs/error-handling-retry-strategies.md +190 -0
  419. package/skills/engineering/integration/refs/event-schemas-best-practices.md +225 -0
  420. package/skills/engineering/integration/refs/event-schemas-event-naming-conventions.md +303 -0
  421. package/skills/engineering/integration/refs/event-schemas-event-structure.md +288 -0
  422. package/skills/engineering/integration/refs/graphql-best-practices.md +138 -0
  423. package/skills/engineering/integration/refs/graphql-error-handling.md +198 -0
  424. package/skills/engineering/integration/refs/graphql-graphql-basics.md +197 -0
  425. package/skills/engineering/integration/refs/graphql-query-examples.md +226 -0
  426. package/skills/engineering/integration/refs/graphql-schema-design-patterns.md +280 -0
  427. package/skills/engineering/integration/refs/grpc-grpc-overview.md +246 -0
  428. package/skills/engineering/integration/refs/grpc-implementation-examples.md +269 -0
  429. package/skills/engineering/integration/refs/grpc-metadata-headers.md +304 -0
  430. package/skills/engineering/integration/refs/grpc-testing.md +49 -0
  431. package/skills/engineering/integration/refs/openapi-template.yaml +682 -0
  432. package/skills/engineering/integration/refs/resilience-best-practices.md +109 -0
  433. package/skills/engineering/integration/refs/resilience-circuit-breaker-pattern.md +302 -0
  434. package/skills/engineering/integration/refs/resilience-rate-limiting.md +245 -0
  435. package/skills/engineering/integration/refs/resilience-timeout-pattern.md +212 -0
  436. package/skills/engineering/integration/refs/rest-api-fundamentals.md +299 -0
  437. package/skills/engineering/integration/refs/rest-api-responses-security.md +302 -0
  438. package/skills/engineering/integration/refs/versioning-breaking-changes.md +237 -0
  439. package/skills/engineering/integration/refs/versioning-migration-strategies.md +257 -0
  440. package/skills/engineering/integration/refs/versioning-versioning-strategies.md +296 -0
  441. package/skills/engineering/large-scale-migration/SKILL.md +65 -0
  442. package/skills/engineering/patch/SKILL.md +184 -0
  443. package/skills/engineering/refs/arch.md +126 -0
  444. package/skills/engineering/refs/debug.md +142 -0
  445. package/skills/engineering/refs/docs.md +190 -0
  446. package/skills/engineering/refs/plan.md +109 -0
  447. package/skills/engineering/refs/review.md +138 -0
  448. package/skills/engineering/system-design/SKILL.md +154 -0
  449. package/skills/engineering/system-design/refs/anti-patterns-big-ball-of-mud.md +254 -0
  450. package/skills/engineering/system-design/refs/anti-patterns-circular-dependencies.md +241 -0
  451. package/skills/engineering/system-design/refs/anti-patterns-feature-envy.md +168 -0
  452. package/skills/engineering/system-design/refs/anti-patterns-god-object.md +247 -0
  453. package/skills/engineering/system-design/refs/component-template-lifecycle.md +210 -0
  454. package/skills/engineering/system-design/refs/component-template-maintenance.md +219 -0
  455. package/skills/engineering/system-design/refs/component-template-structure.md +276 -0
  456. package/skills/engineering/system-design/refs/dependencies-best-practices.md +260 -0
  457. package/skills/engineering/system-design/refs/dependencies-dependency-principles.md +295 -0
  458. package/skills/engineering/system-design/refs/dependencies-dependency-tracking.md +261 -0
  459. package/skills/engineering/system-design/refs/interface-template-lifecycle.md +211 -0
  460. package/skills/engineering/system-design/refs/interface-template-maintenance.md +212 -0
  461. package/skills/engineering/system-design/refs/interface-template-structure.md +269 -0
  462. package/skills/engineering/system-design/refs/patterns-dependency-injection.md +151 -0
  463. package/skills/engineering/system-design/refs/patterns-facade-pattern.md +257 -0
  464. package/skills/engineering/system-design/refs/patterns-layered-pattern.md +204 -0
  465. package/skills/engineering/system-design/refs/patterns-plugin-architecture.md +229 -0
  466. package/skills/engineering/unit-test-quality/SKILL.md +194 -0
  467. package/skills/ground/SKILL.md +130 -0
  468. package/skills/integration-discovery/SKILL.md +168 -0
  469. package/skills/integration-discovery/refs/capabilities.md +282 -0
  470. package/skills/integration-discovery/refs/cli-detection.md +295 -0
  471. package/skills/integration-discovery/refs/discovery-sources.md +233 -0
  472. package/skills/integration-discovery/refs/task-patterns.md +206 -0
  473. package/skills/jam/SKILL.md +45 -0
  474. package/skills/jam/refs/facilitation-patterns.md +125 -0
  475. package/skills/jam/refs/quick.md +64 -0
  476. package/skills/jam/refs/synthesis-patterns.md +114 -0
  477. package/skills/multi-model/SKILL.md +168 -0
  478. package/skills/multi-model/refs/aichat.md +119 -0
  479. package/skills/multi-model/refs/aider.md +100 -0
  480. package/skills/multi-model/refs/auditability.md +238 -0
  481. package/skills/multi-model/refs/codex.md +169 -0
  482. package/skills/multi-model/refs/context.md +306 -0
  483. package/skills/multi-model/refs/copilot.md +161 -0
  484. package/skills/multi-model/refs/examples.md +224 -0
  485. package/skills/multi-model/refs/gemini.md +185 -0
  486. package/skills/multi-model/refs/goose.md +112 -0
  487. package/skills/multi-model/refs/llm.md +124 -0
  488. package/skills/multi-model/refs/opencode.md +196 -0
  489. package/skills/multi-model/refs/orchestration.md +188 -0
  490. package/skills/multi-model/refs/pi.md +208 -0
  491. package/skills/persona/SKILL.md +144 -0
  492. package/skills/persona/refs/define.md +133 -0
  493. package/skills/platform/actions/refs/actions.md +114 -0
  494. package/skills/platform/audit/SKILL.md +174 -0
  495. package/skills/platform/audit/refs/audit.md +145 -0
  496. package/skills/platform/audit/refs/checklists-evidence-operations.md +144 -0
  497. package/skills/platform/audit/refs/checklists-gdpr-pci-evidence.md +213 -0
  498. package/skills/platform/audit/refs/checklists-soc2-hipaa.md +120 -0
  499. package/skills/platform/audit/refs/frameworks-gdpr-pci.md +225 -0
  500. package/skills/platform/audit/refs/frameworks-soc2-hipaa.md +228 -0
  501. package/skills/platform/compliance/SKILL.md +169 -0
  502. package/skills/platform/compliance/refs/checklists.md +303 -0
  503. package/skills/platform/compliance/refs/compliance.md +117 -0
  504. package/skills/platform/compliance/refs/frameworks.md +282 -0
  505. package/skills/platform/errors/SKILL.md +183 -0
  506. package/skills/platform/errors/refs/patterns.md +271 -0
  507. package/skills/platform/errors/refs/severity.md +264 -0
  508. package/skills/platform/gate-benchmark-rebaseline/SKILL.md +108 -0
  509. package/skills/platform/gh/refs/gh.md +105 -0
  510. package/skills/platform/gh-cli/SKILL.md +120 -0
  511. package/skills/platform/gh-cli/refs/automation.md +63 -0
  512. package/skills/platform/gh-cli/refs/gh-ops.md +103 -0
  513. package/skills/platform/gh-cli/refs/patterns.md +132 -0
  514. package/skills/platform/gh-cli/scripts/gh_ops.py +454 -0
  515. package/skills/platform/github-actions/SKILL.md +159 -0
  516. package/skills/platform/github-actions/refs/security.md +150 -0
  517. package/skills/platform/github-actions/refs/templates.md +230 -0
  518. package/skills/platform/github-actions/refs/troubleshooting.md +174 -0
  519. package/skills/platform/github-actions/scripts/workflow_gen.py +215 -0
  520. package/skills/platform/gitlab-ci/SKILL.md +140 -0
  521. package/skills/platform/gitlab-ci/refs/templates.md +223 -0
  522. package/skills/platform/gitlab-ci/refs/troubleshooting.md +213 -0
  523. package/skills/platform/glab-cli/SKILL.md +133 -0
  524. package/skills/platform/glab-cli/refs/ci-debugging.md +95 -0
  525. package/skills/platform/glab-cli/refs/glab-ops.md +78 -0
  526. package/skills/platform/glab-cli/refs/patterns.md +131 -0
  527. package/skills/platform/glab-cli/scripts/glab_ops.py +313 -0
  528. package/skills/platform/health/SKILL.md +177 -0
  529. package/skills/platform/health/refs/health.md +72 -0
  530. package/skills/platform/health/refs/sources.md +302 -0
  531. package/skills/platform/incident/refs/incident.md +136 -0
  532. package/skills/platform/infra/refs/infra.md +104 -0
  533. package/skills/platform/observability/SKILL.md +128 -0
  534. package/skills/platform/observability/refs/toolchain-discovery.md +243 -0
  535. package/skills/platform/prereq-doctor/SKILL.md +57 -0
  536. package/skills/platform/prereq-doctor/refs/tool-registry.md +58 -0
  537. package/skills/platform/traces/refs/traces.md +101 -0
  538. package/skills/product/acceptance-criteria/SKILL.md +193 -0
  539. package/skills/product/acceptance-criteria/refs/ac-anti-patterns.md +291 -0
  540. package/skills/product/acceptance-criteria/refs/ac-examples.md +277 -0
  541. package/skills/product/accessibility/SKILL.md +197 -0
  542. package/skills/product/accessibility/refs/aria-patterns-basics.md +250 -0
  543. package/skills/product/accessibility/refs/aria-patterns-dynamic.md +187 -0
  544. package/skills/product/accessibility/refs/aria-patterns-interactive.md +246 -0
  545. package/skills/product/accessibility/refs/audit-report-findings.md +248 -0
  546. package/skills/product/accessibility/refs/audit-report-results.md +276 -0
  547. package/skills/product/accessibility/refs/common-violations-html-css.md +270 -0
  548. package/skills/product/accessibility/refs/common-violations-interactive.md +303 -0
  549. package/skills/product/accessibility/refs/keyboard-testing-basics.md +222 -0
  550. package/skills/product/accessibility/refs/keyboard-testing-patterns.md +173 -0
  551. package/skills/product/accessibility/refs/screen-reader-testing-advanced.md +294 -0
  552. package/skills/product/accessibility/refs/screen-reader-testing-commands.md +255 -0
  553. package/skills/product/accessibility/refs/wcag-checklist.md +262 -0
  554. package/skills/product/analyze/SKILL.md +164 -0
  555. package/skills/product/analyze/refs/algorithms.md +238 -0
  556. package/skills/product/analyze/refs/sentiment-patterns.md +180 -0
  557. package/skills/product/imagery/SKILL.md +97 -0
  558. package/skills/product/imagery/alter/SKILL.md +105 -0
  559. package/skills/product/imagery/alter/refs/editing-reference.md +146 -0
  560. package/skills/product/imagery/create/SKILL.md +109 -0
  561. package/skills/product/imagery/create/refs/prompt-engineering.md +112 -0
  562. package/skills/product/imagery/create/refs/provider-reference.md +219 -0
  563. package/skills/product/imagery/review/SKILL.md +101 -0
  564. package/skills/product/imagery/review/refs/analysis-lenses.md +136 -0
  565. package/skills/product/imagery/review/refs/quality-gates.md +153 -0
  566. package/skills/product/imagery/scripts/analyze.sh +23 -0
  567. package/skills/product/imagery/scripts/edit.sh +14 -0
  568. package/skills/product/imagery/scripts/generate.sh +13 -0
  569. package/skills/product/imagery/scripts/provider.py +787 -0
  570. package/skills/product/listen/SKILL.md +175 -0
  571. package/skills/product/listen/refs/channels.md +220 -0
  572. package/skills/product/mockup/SKILL.md +106 -0
  573. package/skills/product/mockup/refs/templates.md +95 -0
  574. package/skills/product/refs/a11y.md +109 -0
  575. package/skills/product/refs/acceptance.md +79 -0
  576. package/skills/product/refs/align.md +67 -0
  577. package/skills/product/refs/analyze.md +77 -0
  578. package/skills/product/refs/elicit.md +67 -0
  579. package/skills/product/refs/listen.md +58 -0
  580. package/skills/product/refs/mockup.md +77 -0
  581. package/skills/product/refs/screenshot.md +59 -0
  582. package/skills/product/refs/strategy.md +77 -0
  583. package/skills/product/refs/synthesize.md +54 -0
  584. package/skills/product/refs/ux-review.md +68 -0
  585. package/skills/product/refs/ux.md +101 -0
  586. package/skills/product/requirements-analysis/SKILL.md +136 -0
  587. package/skills/product/requirements-analysis/refs/requirements-example-auth.md +264 -0
  588. package/skills/product/requirements-analysis/refs/requirements-example-export-integration.md +88 -0
  589. package/skills/product/requirements-analysis/refs/requirements-output-format-template.md +247 -0
  590. package/skills/product/requirements-analysis/refs/user-story-guide.md +296 -0
  591. package/skills/product/requirements-graph/SKILL.md +155 -0
  592. package/skills/product/requirements-graph/refs/examples.md +223 -0
  593. package/skills/product/requirements-graph/refs/schema.md +162 -0
  594. package/skills/product/requirements-migrate/SKILL.md +90 -0
  595. package/skills/product/requirements-navigate/SKILL.md +141 -0
  596. package/skills/product/requirements-navigate/refs/meta-templates.md +141 -0
  597. package/skills/product/screenshot/SKILL.md +147 -0
  598. package/skills/product/strategy/SKILL.md +198 -0
  599. package/skills/product/strategy/refs/frameworks.md +295 -0
  600. package/skills/product/strategy/refs/templates-competitive-market.md +299 -0
  601. package/skills/product/strategy/refs/templates-roi-value.md +207 -0
  602. package/skills/product/synthesize/SKILL.md +116 -0
  603. package/skills/product/synthesize/refs/journey-mapping.md +212 -0
  604. package/skills/product/synthesize/refs/prioritization.md +193 -0
  605. package/skills/product/ux-review/SKILL.md +164 -0
  606. package/skills/product/visual-direction/SKILL.md +137 -0
  607. package/skills/product/visual-review/SKILL.md +131 -0
  608. package/skills/runtime-exec/SKILL.md +138 -0
  609. package/skills/search/codebase-narrator/SKILL.md +131 -0
  610. package/skills/search/codebase-narrator/refs/output-template.md +100 -0
  611. package/skills/smaht/SKILL.md +72 -0
  612. package/skills/smaht/discovery/SKILL.md +65 -0
  613. package/skills/smaht/intent/SKILL.md +89 -0
  614. package/skills/smaht/propose-skills/SKILL.md +142 -0
  615. package/skills/smaht/refs/state.md +76 -0
  616. package/skills/swarm/SKILL.md +132 -0
  617. package/skills/swarm/refs/fan-out.md +104 -0
  618. package/skills/swarm/refs/independent-verification.md +86 -0
  619. package/skills/swarm/refs/receipts-and-evidence.md +69 -0
  620. package/skills/swarm/refs/recon-synthesis.md +87 -0
  621. package/skills/swarm/refs/ship-discipline.md +90 -0
  622. package/skills/wickedizer/SKILL.md +147 -0
  623. package/skills/wickedizer/refs/artifact-types.md +238 -0
  624. package/skills/wickedizer/refs/complexity.md +278 -0
  625. package/skills/wickedizer/refs/de-ai-pass.md +140 -0
  626. package/skills/wickedizer/refs/failure-modes.md +249 -0
  627. package/skills/wickedizer/refs/patterns.md +282 -0
  628. package/skills/wickedizer/refs/review.md +221 -0
  629. package/skills/wickedizer/refs/structure.md +282 -0
  630. package/skills/wickedizer/refs/voice-profile.md +125 -0
  631. package/skills/workflow/SKILL.md +132 -0
  632. package/skills/workflow/refs/archetype-adjustments.md +205 -0
  633. package/skills/workflow/refs/evidence.md +58 -0
  634. package/skills/workflow/refs/integration.md +130 -0
  635. package/skills/workflow/refs/risk-dimension-signals.md +260 -0
  636. package/skills/workflow/refs/scoring-rubric.md +49 -0
  637. package/skills/workflow/refs/signal-keywords.md +176 -0
  638. package/skills/workflow/refs/specialist-routing-rules.md +159 -0
  639. package/skills/worktrees/SKILL.md +87 -0
  640. package/skills/worktrees/refs/recipes.md +96 -0
@@ -0,0 +1,928 @@
1
+ """
2
+ Java code generator.
3
+
4
+ Generates patches for Java files including:
5
+ - JPA entities (add/modify fields, columns)
6
+ - Controllers (add endpoints, mappings)
7
+ - Services (add methods)
8
+ - DTOs (add fields)
9
+ """
10
+
11
+ import re
12
+ from pathlib import Path
13
+ from typing import Any, Dict, List, Optional, Set
14
+ import logging
15
+
16
+ from .base import (
17
+ BaseGenerator,
18
+ register_generator,
19
+ ChangeSpec,
20
+ ChangeType,
21
+ FieldSpec,
22
+ Patch,
23
+ )
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ @register_generator
29
+ class JavaGenerator(BaseGenerator):
30
+ """Generate patches for Java files."""
31
+
32
+ name = "java"
33
+ extensions = {".java"}
34
+ symbol_types = {"entity", "entity_field", "class", "service", "controller", "dao"}
35
+
36
+ # Type mappings from generic types to Java types
37
+ TYPE_MAP = {
38
+ "string": "String",
39
+ "str": "String",
40
+ "text": "String",
41
+ "int": "int",
42
+ "integer": "Integer",
43
+ "long": "Long",
44
+ "bigint": "Long",
45
+ "float": "float",
46
+ "double": "double",
47
+ "decimal": "BigDecimal",
48
+ "boolean": "boolean",
49
+ "bool": "boolean",
50
+ "date": "LocalDate",
51
+ "datetime": "LocalDateTime",
52
+ "timestamp": "LocalDateTime",
53
+ "time": "LocalTime",
54
+ "uuid": "UUID",
55
+ "binary": "byte[]",
56
+ "blob": "byte[]",
57
+ }
58
+
59
+ # Import mappings for types that need imports
60
+ IMPORT_MAP = {
61
+ "BigDecimal": "java.math.BigDecimal",
62
+ "LocalDate": "java.time.LocalDate",
63
+ "LocalDateTime": "java.time.LocalDateTime",
64
+ "LocalTime": "java.time.LocalTime",
65
+ "UUID": "java.util.UUID",
66
+ "List": "java.util.List",
67
+ "Set": "java.util.Set",
68
+ "Map": "java.util.Map",
69
+ "Date": "java.util.Date",
70
+ }
71
+
72
+ def generate(
73
+ self,
74
+ change_spec: ChangeSpec,
75
+ symbol: Dict[str, Any],
76
+ file_content: str,
77
+ ) -> List[Patch]:
78
+ """
79
+ Generate patches for a Java file.
80
+
81
+ Args:
82
+ change_spec: The change specification
83
+ symbol: The symbol being modified
84
+ file_content: Current file content
85
+
86
+ Returns:
87
+ List of patches
88
+ """
89
+ patches = []
90
+
91
+ if change_spec.change_type == ChangeType.ADD_FIELD:
92
+ patches.extend(self._add_field(change_spec, symbol, file_content))
93
+ elif change_spec.change_type == ChangeType.REMOVE_FIELD:
94
+ patches.extend(self._remove_field(change_spec, symbol, file_content))
95
+ elif change_spec.change_type == ChangeType.RENAME_FIELD:
96
+ patches.extend(self._rename_field(change_spec, symbol, file_content))
97
+ elif change_spec.change_type == ChangeType.MODIFY_FIELD:
98
+ patches.extend(self._modify_field(change_spec, symbol, file_content))
99
+ elif change_spec.change_type == ChangeType.ADD_VALIDATION:
100
+ patches.extend(self._add_validation(change_spec, symbol, file_content))
101
+
102
+ return patches
103
+
104
+ def _detect_class_role(self, symbol: Dict[str, Any], file_content: str) -> str:
105
+ """Detect the role of a Java class: entity, service, controller, or dto."""
106
+ sym_type = symbol.get("type", "").lower()
107
+ if sym_type in ("service", "controller", "dao"):
108
+ return sym_type
109
+
110
+ name = symbol.get("name", "")
111
+ content_lower = file_content.lower()
112
+
113
+ if "service" in name.lower() or "@service" in content_lower:
114
+ return "service"
115
+ if "controller" in name.lower() or "@controller" in content_lower or "@restcontroller" in content_lower:
116
+ return "controller"
117
+ if "repository" in name.lower() or "@repository" in content_lower:
118
+ return "dao"
119
+ if "@entity" in content_lower or sym_type in ("entity", "entity_field"):
120
+ return "entity"
121
+ return "entity" # default
122
+
123
+ def _add_field(
124
+ self,
125
+ change_spec: ChangeSpec,
126
+ symbol: Dict[str, Any],
127
+ file_content: str,
128
+ ) -> List[Patch]:
129
+ """
130
+ Add a field to a Java class/entity.
131
+
132
+ For entity/DTO classes: generates field declaration + getter + setter.
133
+ For service/controller classes: generates validation logic instead.
134
+ """
135
+ patches = []
136
+ field_spec = change_spec.field_spec
137
+ if not field_spec:
138
+ return patches
139
+
140
+ lines = file_content.split("\n")
141
+ file_path = symbol.get("file_path", "")
142
+
143
+ # Determine Java type
144
+ java_type = self._map_type(field_spec.type)
145
+
146
+ # For service/controller classes, generate validation instead of field
147
+ class_role = self._detect_class_role(symbol, file_content)
148
+ if class_role in ("service", "controller"):
149
+ return self._add_validation_for_field(change_spec, symbol, file_content, java_type)
150
+
151
+
152
+ # Find class body insertion point (after last field declaration)
153
+ class_start, class_end = self._find_class_body(lines, symbol)
154
+ if class_start < 0:
155
+ return patches
156
+
157
+ # Find where to insert the field (after last field, before first method)
158
+ insert_line = self._find_field_insertion_point(lines, class_start, class_end)
159
+ indentation = self._detect_indentation(lines, class_start, class_end)
160
+
161
+ # Build field declaration
162
+ field_lines = self._build_field_declaration(
163
+ field_spec, java_type, indentation, symbol
164
+ )
165
+
166
+ patches.append(Patch(
167
+ file_path=file_path,
168
+ line_start=insert_line + 1, # Insert after this line
169
+ line_end=insert_line, # No lines replaced (insertion)
170
+ old_content="",
171
+ new_content="\n".join(field_lines),
172
+ description=f"Add field '{field_spec.name}' ({java_type})",
173
+ symbol_id=symbol.get("id"),
174
+ confidence="high",
175
+ ))
176
+
177
+ # Find where to insert getter/setter (after existing methods or before class end)
178
+ method_insert_line = self._find_method_insertion_point(lines, class_start, class_end)
179
+
180
+ # Build getter
181
+ getter_lines = self._build_getter(field_spec, java_type, indentation)
182
+ patches.append(Patch(
183
+ file_path=file_path,
184
+ line_start=method_insert_line + 1,
185
+ line_end=method_insert_line,
186
+ old_content="",
187
+ new_content="\n".join(getter_lines),
188
+ description=f"Add getter for '{field_spec.name}'",
189
+ symbol_id=symbol.get("id"),
190
+ confidence="high",
191
+ ))
192
+
193
+ # Build setter (same insertion point as getter — descending sort
194
+ # in patches_by_file() will place setter after getter, both inside class)
195
+ setter_lines = self._build_setter(field_spec, java_type, indentation)
196
+ patches.append(Patch(
197
+ file_path=file_path,
198
+ line_start=method_insert_line + 1,
199
+ line_end=method_insert_line,
200
+ old_content="",
201
+ new_content="\n".join(setter_lines),
202
+ description=f"Add setter for '{field_spec.name}'",
203
+ symbol_id=symbol.get("id"),
204
+ confidence="high",
205
+ ))
206
+
207
+ # Add imports if needed
208
+ import_patch = self._add_imports(java_type, lines, file_path)
209
+ if import_patch:
210
+ patches.insert(0, import_patch) # Imports first
211
+
212
+ return patches
213
+
214
+ def _remove_field(
215
+ self,
216
+ change_spec: ChangeSpec,
217
+ symbol: Dict[str, Any],
218
+ file_content: str,
219
+ ) -> List[Patch]:
220
+ """Remove a field and its getter/setter, or remove usages in non-owner files."""
221
+ patches = []
222
+ field_name = change_spec.old_name or (change_spec.field_spec.name if change_spec.field_spec else None)
223
+ if not field_name:
224
+ return patches
225
+
226
+ lines = file_content.split("\n")
227
+ file_path = symbol.get("file_path", "")
228
+ class_role = self._detect_class_role(symbol, file_content)
229
+
230
+ # Find field declaration (present in owner files: entity, DTO)
231
+ field_start, field_end = self._find_field_declaration(lines, field_name)
232
+
233
+ if field_start >= 0:
234
+ # Owner file: remove field declaration + getter + setter
235
+ patches.append(Patch(
236
+ file_path=file_path,
237
+ line_start=field_start + 1,
238
+ line_end=field_end + 1,
239
+ old_content="\n".join(lines[field_start:field_end + 1]),
240
+ new_content="",
241
+ description=f"Remove field '{field_name}'",
242
+ symbol_id=symbol.get("id"),
243
+ confidence="high",
244
+ ))
245
+
246
+ # Find and remove getter
247
+ getter_name = f"get{self._capitalize(field_name)}"
248
+ getter_start, getter_end = self._find_method(lines, getter_name)
249
+ if getter_start >= 0:
250
+ patches.append(Patch(
251
+ file_path=file_path,
252
+ line_start=getter_start + 1,
253
+ line_end=getter_end + 1,
254
+ old_content="\n".join(lines[getter_start:getter_end + 1]),
255
+ new_content="",
256
+ description=f"Remove getter '{getter_name}'",
257
+ symbol_id=symbol.get("id"),
258
+ confidence="high",
259
+ ))
260
+
261
+ # Find and remove setter
262
+ setter_name = f"set{self._capitalize(field_name)}"
263
+ setter_start, setter_end = self._find_method(lines, setter_name)
264
+ if setter_start >= 0:
265
+ patches.append(Patch(
266
+ file_path=file_path,
267
+ line_start=setter_start + 1,
268
+ line_end=setter_end + 1,
269
+ old_content="\n".join(lines[setter_start:setter_end + 1]),
270
+ new_content="",
271
+ description=f"Remove setter '{setter_name}'",
272
+ symbol_id=symbol.get("id"),
273
+ confidence="high",
274
+ ))
275
+ else:
276
+ # Non-owner file (service, repository, test): remove methods that
277
+ # exclusively use this field's getter/setter, or remove usage lines
278
+ getter_name = f"get{self._capitalize(field_name)}"
279
+ setter_name = f"set{self._capitalize(field_name)}"
280
+ accessor_names = [getter_name, setter_name]
281
+
282
+ patches.extend(
283
+ self._remove_accessor_usages(lines, accessor_names, file_path, symbol)
284
+ )
285
+
286
+ return patches
287
+
288
+ def _remove_accessor_usages(
289
+ self,
290
+ lines: List[str],
291
+ accessor_names: List[str],
292
+ file_path: str,
293
+ symbol: Dict[str, Any],
294
+ ) -> List[Patch]:
295
+ """Remove methods that use deprecated field accessors in non-owner files.
296
+
297
+ Two-pass approach:
298
+ 1. Find methods containing accessor calls
299
+ 2. If method body is simple (accessor is the primary logic), remove entire method
300
+ Otherwise, remove just the accessor lines
301
+ """
302
+ patches = []
303
+ removed_methods = set() # Track method-start lines scheduled for full removal
304
+ removed_lines = set() # Track individual lines scheduled for removal
305
+
306
+ for accessor_name in accessor_names:
307
+ # Find all methods that contain calls to this accessor
308
+ i = 0
309
+ while i < len(lines):
310
+ if accessor_name + "(" in lines[i]:
311
+ # Check if this line is inside a method
312
+ method_start = self._find_enclosing_method_start(lines, i)
313
+ if method_start >= 0 and method_start not in removed_methods:
314
+ method_end = self._find_method_end_from(lines, method_start)
315
+ if method_end >= 0:
316
+ # Count how many non-trivial lines are in the method body
317
+ body_lines = [
318
+ l.strip() for l in lines[method_start + 1:method_end]
319
+ if l.strip() and not l.strip().startswith("//") and l.strip() != "{"
320
+ ]
321
+ # Count lines that DON'T reference any of the accessors
322
+ non_accessor_lines = [
323
+ l for l in body_lines
324
+ if not any(a + "(" in l for a in accessor_names)
325
+ and l != "}" and l != "{"
326
+ ]
327
+
328
+ if len(non_accessor_lines) == 0:
329
+ # Method exclusively uses this accessor — remove entire method
330
+ removed_methods.add(method_start)
331
+ patches.append(Patch(
332
+ file_path=file_path,
333
+ line_start=method_start + 1,
334
+ line_end=method_end + 1,
335
+ old_content="\n".join(lines[method_start:method_end + 1]),
336
+ new_content="",
337
+ description=f"Remove method using deprecated accessor '{accessor_name}'",
338
+ symbol_id=symbol.get("id"),
339
+ confidence="medium",
340
+ ))
341
+ else:
342
+ # Mixed method — remove just the lines with accessor calls
343
+ for j in range(method_start, method_end + 1):
344
+ if any(a + "(" in lines[j] for a in accessor_names):
345
+ if j not in removed_lines:
346
+ removed_lines.add(j)
347
+ patches.append(Patch(
348
+ file_path=file_path,
349
+ line_start=j + 1,
350
+ line_end=j + 1,
351
+ old_content=lines[j],
352
+ new_content="",
353
+ description=f"Remove usage of deprecated accessor '{accessor_name}'",
354
+ symbol_id=symbol.get("id"),
355
+ confidence="low",
356
+ ))
357
+ i += 1
358
+
359
+ return patches
360
+
361
+ def _find_enclosing_method_start(self, lines: List[str], line_idx: int) -> int:
362
+ """Walk backward from a line to find the enclosing method signature."""
363
+ brace_count = 0
364
+ for i in range(line_idx, -1, -1):
365
+ brace_count += lines[i].count("}") - lines[i].count("{")
366
+ stripped = lines[i].strip()
367
+ if re.match(r'((public|private|protected)\s+)?\w+\s+\w+\s*\(', stripped):
368
+ # Found a method signature — verify we're inside it
369
+ if brace_count <= 0:
370
+ return i
371
+ return -1
372
+
373
+ def _find_method_end_from(self, lines: List[str], method_start: int) -> int:
374
+ """Find the end of a method starting from the method signature line."""
375
+ brace_count = 0
376
+ for i in range(method_start, len(lines)):
377
+ brace_count += lines[i].count("{") - lines[i].count("}")
378
+ if i > method_start and brace_count <= 0:
379
+ return i
380
+ return -1
381
+
382
+ def _rename_field(
383
+ self,
384
+ change_spec: ChangeSpec,
385
+ symbol: Dict[str, Any],
386
+ file_content: str,
387
+ ) -> List[Patch]:
388
+ """Rename a field and update getter/setter."""
389
+ patches = []
390
+ old_name = change_spec.old_name
391
+ new_name = change_spec.new_name
392
+ if not old_name or not new_name:
393
+ return patches
394
+
395
+ lines = file_content.split("\n")
396
+ file_path = symbol.get("file_path", "")
397
+
398
+ # Find and rename field declaration
399
+ for i, line in enumerate(lines):
400
+ # Match field declaration: private Type fieldName;
401
+ pattern = rf"(\s*(?:private|protected|public)\s+\w+\s+){old_name}(\s*[;=])"
402
+ match = re.search(pattern, line)
403
+ if match:
404
+ new_line = re.sub(pattern, rf"\1{new_name}\2", line)
405
+ patches.append(Patch(
406
+ file_path=file_path,
407
+ line_start=i + 1,
408
+ line_end=i + 1,
409
+ old_content=line,
410
+ new_content=new_line,
411
+ description=f"Rename field '{old_name}' to '{new_name}'",
412
+ symbol_id=symbol.get("id"),
413
+ confidence="high",
414
+ ))
415
+ break
416
+
417
+ # Rename getter
418
+ old_getter = f"get{self._capitalize(old_name)}"
419
+ new_getter = f"get{self._capitalize(new_name)}"
420
+ for i, line in enumerate(lines):
421
+ if old_getter in line and "(" in line:
422
+ new_line = line.replace(old_getter, new_getter)
423
+ patches.append(Patch(
424
+ file_path=file_path,
425
+ line_start=i + 1,
426
+ line_end=i + 1,
427
+ old_content=line,
428
+ new_content=new_line,
429
+ description=f"Rename getter '{old_getter}' to '{new_getter}'",
430
+ symbol_id=symbol.get("id"),
431
+ confidence="high",
432
+ ))
433
+
434
+ # Rename setter
435
+ old_setter = f"set{self._capitalize(old_name)}"
436
+ new_setter = f"set{self._capitalize(new_name)}"
437
+ for i, line in enumerate(lines):
438
+ if old_setter in line and "(" in line:
439
+ new_line = line.replace(old_setter, new_setter)
440
+ # Also rename the parameter: (Type oldName) -> (Type newName)
441
+ new_line = re.sub(
442
+ rf'\(\s*([^)]+?)\s+{re.escape(old_name)}\s*\)',
443
+ rf'(\1 {new_name})',
444
+ new_line
445
+ )
446
+ patches.append(Patch(
447
+ file_path=file_path,
448
+ line_start=i + 1,
449
+ line_end=i + 1,
450
+ old_content=line,
451
+ new_content=new_line,
452
+ description=f"Rename setter '{old_setter}' to '{new_setter}' and parameter",
453
+ symbol_id=symbol.get("id"),
454
+ confidence="high",
455
+ ))
456
+
457
+ # Update all usages of field within the file (this.field, bare field refs)
458
+ class_start, class_end = self._find_class_body(lines, symbol)
459
+ for i, line in enumerate(lines):
460
+ # Skip lines already patched
461
+ if any(p.line_start == i + 1 for p in patches):
462
+ continue
463
+
464
+ new_line = line
465
+ modified = False
466
+
467
+ # Match this.fieldName
468
+ if f"this.{old_name}" in line:
469
+ new_line = new_line.replace(f"this.{old_name}", f"this.{new_name}")
470
+ modified = True
471
+
472
+ # Match bare field references inside class body (word boundary)
473
+ if class_start >= 0 and class_start < i <= class_end:
474
+ if re.search(rf'\b{re.escape(old_name)}\b', new_line):
475
+ # Only replace if it's clearly a field ref (not in string literals,
476
+ # not a type name, not a local variable declaration)
477
+ stripped = new_line.strip()
478
+ # Skip lines that declare the field or import statements
479
+ if not re.match(r'(private|protected|public)\s+\w+\s+' + re.escape(old_name), stripped) \
480
+ and not stripped.startswith("import "):
481
+ new_line = re.sub(rf'\b{re.escape(old_name)}\b', new_name, new_line)
482
+ modified = True
483
+
484
+ if modified:
485
+ patches.append(Patch(
486
+ file_path=file_path,
487
+ line_start=i + 1,
488
+ line_end=i + 1,
489
+ old_content=line,
490
+ new_content=new_line,
491
+ description=f"Update field reference '{old_name}' to '{new_name}'",
492
+ symbol_id=symbol.get("id"),
493
+ confidence="medium",
494
+ ))
495
+
496
+ return patches
497
+
498
+ def _modify_field(
499
+ self,
500
+ change_spec: ChangeSpec,
501
+ symbol: Dict[str, Any],
502
+ file_content: str,
503
+ ) -> List[Patch]:
504
+ """Modify a field's type or annotations."""
505
+ patches = []
506
+ field_spec = change_spec.field_spec
507
+ if not field_spec:
508
+ return patches
509
+
510
+ lines = file_content.split("\n")
511
+ file_path = symbol.get("file_path", "")
512
+
513
+ # Find field declaration
514
+ field_start, field_end = self._find_field_declaration(lines, field_spec.name)
515
+ if field_start < 0:
516
+ return patches
517
+
518
+ # Build new field declaration
519
+ indentation = self._get_indentation(lines[field_start])
520
+ java_type = self._map_type(field_spec.type)
521
+ new_field_lines = self._build_field_declaration(
522
+ field_spec, java_type, indentation, symbol
523
+ )
524
+
525
+ patches.append(Patch(
526
+ file_path=file_path,
527
+ line_start=field_start + 1,
528
+ line_end=field_end + 1,
529
+ old_content="\n".join(lines[field_start:field_end + 1]),
530
+ new_content="\n".join(new_field_lines),
531
+ description=f"Modify field '{field_spec.name}'",
532
+ symbol_id=symbol.get("id"),
533
+ confidence="high",
534
+ ))
535
+
536
+ return patches
537
+
538
+ def _add_validation(
539
+ self,
540
+ change_spec: ChangeSpec,
541
+ symbol: Dict[str, Any],
542
+ file_content: str,
543
+ ) -> List[Patch]:
544
+ """Add validation annotations to a field."""
545
+ patches = []
546
+ field_spec = change_spec.field_spec
547
+ if not field_spec or not field_spec.validation:
548
+ return patches
549
+
550
+ lines = file_content.split("\n")
551
+ file_path = symbol.get("file_path", "")
552
+
553
+ # Find field declaration
554
+ field_start, _ = self._find_field_declaration(lines, field_spec.name)
555
+ if field_start < 0:
556
+ return patches
557
+
558
+ # Build validation annotations
559
+ indentation = self._get_indentation(lines[field_start])
560
+ validation_lines = self._build_validation_annotations(
561
+ field_spec.validation, indentation
562
+ )
563
+
564
+ if validation_lines:
565
+ patches.append(Patch(
566
+ file_path=file_path,
567
+ line_start=field_start + 1,
568
+ line_end=field_start, # Insert before field
569
+ old_content="",
570
+ new_content="\n".join(validation_lines),
571
+ description=f"Add validation to '{field_spec.name}'",
572
+ symbol_id=symbol.get("id"),
573
+ confidence="high",
574
+ ))
575
+
576
+ return patches
577
+
578
+ def _add_validation_for_field(
579
+ self,
580
+ change_spec: ChangeSpec,
581
+ symbol: Dict[str, Any],
582
+ file_content: str,
583
+ java_type: str,
584
+ ) -> List[Patch]:
585
+ """Add validation logic to a service/controller for a new field."""
586
+ patches = []
587
+ field_spec = change_spec.field_spec
588
+ if not field_spec:
589
+ return patches
590
+
591
+ lines = file_content.split("\n")
592
+ file_path = symbol.get("file_path", "")
593
+ class_start, class_end = self._find_class_body(lines, symbol)
594
+ if class_start < 0:
595
+ return patches
596
+
597
+ indentation = self._detect_indentation(lines, class_start, class_end)
598
+ getter_name = f"get{self._capitalize(field_spec.name)}"
599
+
600
+ # Find a validate method and extract its parameter name
601
+ validate_method_end = -1
602
+ param_name = None
603
+ for i in range(class_start + 1, class_end):
604
+ if "validate" in lines[i].lower() and "(" in lines[i]:
605
+ # Extract parameter name from method signature
606
+ param_match = re.search(r'\(\s*\w+\s+(\w+)\s*\)', lines[i])
607
+ if param_match:
608
+ param_name = param_match.group(1)
609
+ # Find end of this method (j > i ensures we're past the opening brace)
610
+ brace_count = 0
611
+ for j in range(i, class_end + 1):
612
+ brace_count += lines[j].count("{") - lines[j].count("}")
613
+ if j > i and brace_count <= 0:
614
+ validate_method_end = j
615
+ break
616
+ break
617
+
618
+ if validate_method_end > 0:
619
+ # Insert validation check before the closing brace of the validate method
620
+ insert_at = validate_method_end - 1
621
+ else:
622
+ # Insert as a new method before class closing brace
623
+ insert_at = class_end - 1
624
+
625
+ # Derive the object variable name: from method parameter, class name, or generic
626
+ if not param_name:
627
+ class_name = symbol.get("name", "")
628
+ if class_name.endswith("Service"):
629
+ entity = class_name[:-len("Service")]
630
+ elif class_name.endswith("Controller"):
631
+ entity = class_name[:-len("Controller")]
632
+ else:
633
+ entity = class_name
634
+ param_name = entity[0].lower() + entity[1:] if entity else "request"
635
+
636
+ # Build validation code
637
+ if not field_spec.nullable:
638
+ validation_lines = [
639
+ "",
640
+ f"{indentation}// Validate {field_spec.name}",
641
+ f"{indentation}if ({param_name}.{getter_name}() == null || {param_name}.{getter_name}().isEmpty()) {{",
642
+ f'{indentation} throw new IllegalArgumentException("{self._capitalize(field_spec.name)} is required");',
643
+ f"{indentation}}}",
644
+ ]
645
+ else:
646
+ validation_lines = [
647
+ "",
648
+ f"{indentation}// Validate {field_spec.name} if provided",
649
+ f"{indentation}if ({param_name}.{getter_name}() != null && {param_name}.{getter_name}().isEmpty()) {{",
650
+ f'{indentation} throw new IllegalArgumentException("{self._capitalize(field_spec.name)} cannot be empty");',
651
+ f"{indentation}}}",
652
+ ]
653
+
654
+ patches.append(Patch(
655
+ file_path=file_path,
656
+ line_start=insert_at + 1,
657
+ line_end=insert_at,
658
+ old_content="",
659
+ new_content="\n".join(validation_lines),
660
+ description=f"Add validation for '{field_spec.name}' in service",
661
+ symbol_id=symbol.get("id"),
662
+ confidence="medium",
663
+ ))
664
+
665
+ return patches
666
+
667
+ # Helper methods
668
+
669
+ def _map_type(self, generic_type: str, language: str = None) -> str:
670
+ """Map generic type to Java type."""
671
+ return self.TYPE_MAP.get(generic_type.lower(), generic_type)
672
+
673
+ def _capitalize(self, name: str) -> str:
674
+ """Capitalize first letter for getter/setter names."""
675
+ return name[0].upper() + name[1:] if name else name
676
+
677
+ def _find_class_body(self, lines: List[str], symbol: Dict[str, Any]) -> tuple:
678
+ """Find the start and end of the class body."""
679
+ class_name = symbol.get("name", "")
680
+ start = -1
681
+ end = -1
682
+ brace_count = 0
683
+ in_class = False
684
+
685
+ for i, line in enumerate(lines):
686
+ if f"class {class_name}" in line:
687
+ in_class = True
688
+ if "{" in line:
689
+ brace_count = 1
690
+ start = i
691
+ elif in_class:
692
+ brace_count += line.count("{") - line.count("}")
693
+ if brace_count == 1 and start < 0:
694
+ start = i
695
+ elif brace_count == 0:
696
+ end = i
697
+ break
698
+
699
+ return start, end
700
+
701
+ def _find_field_insertion_point(
702
+ self,
703
+ lines: List[str],
704
+ class_start: int,
705
+ class_end: int
706
+ ) -> int:
707
+ """Find the line after which to insert a new field."""
708
+ last_field_line = class_start + 1 # Default: after class opening
709
+
710
+ for i in range(class_start + 1, class_end):
711
+ line = lines[i].strip()
712
+ # Skip comments and blank lines
713
+ if not line or line.startswith("//") or line.startswith("/*"):
714
+ continue
715
+ # Check if this is a field declaration
716
+ if re.match(r"(private|protected|public)\s+\w+\s+\w+\s*[;=]", line):
717
+ last_field_line = i
718
+ # Stop at first method
719
+ elif re.match(r"(private|protected|public)\s+\w+\s+\w+\s*\(", line):
720
+ break
721
+
722
+ return last_field_line
723
+
724
+ def _find_method_insertion_point(
725
+ self,
726
+ lines: List[str],
727
+ class_start: int,
728
+ class_end: int
729
+ ) -> int:
730
+ """Find the line after which to insert new methods."""
731
+ return class_end - 1 # Before closing brace
732
+
733
+ def _detect_indentation(
734
+ self,
735
+ lines: List[str],
736
+ class_start: int,
737
+ class_end: int
738
+ ) -> str:
739
+ """Detect the indentation used in the class body."""
740
+ for i in range(class_start + 1, class_end):
741
+ line = lines[i]
742
+ if line.strip() and not line.strip().startswith("//"):
743
+ return self._get_indentation(line)
744
+ return " " # Default to 4 spaces
745
+
746
+ def _build_field_declaration(
747
+ self,
748
+ field_spec: FieldSpec,
749
+ java_type: str,
750
+ indentation: str,
751
+ symbol: Dict[str, Any]
752
+ ) -> List[str]:
753
+ """Build field declaration with annotations."""
754
+ lines = []
755
+ metadata = symbol.get("metadata", {})
756
+ is_entity = "Entity" in metadata.get("annotations", [])
757
+
758
+ # Add JPA column annotation for entities
759
+ if is_entity:
760
+ column_name = field_spec.column_name or self._to_snake_case(field_spec.name).upper()
761
+ lines.append(f'{indentation}@Column(name = "{column_name}")')
762
+
763
+ # Add nullable constraint
764
+ if not field_spec.nullable:
765
+ lines.append(f'{indentation}@NotNull')
766
+
767
+ # Add custom annotations
768
+ for annotation in field_spec.annotations:
769
+ lines.append(f"{indentation}@{annotation}")
770
+
771
+ # Field declaration
772
+ default_value = ""
773
+ if field_spec.default:
774
+ default_value = f" = {field_spec.default}"
775
+
776
+ lines.append(f"{indentation}private {java_type} {field_spec.name}{default_value};")
777
+ lines.append("") # Blank line after field
778
+
779
+ return lines
780
+
781
+ def _build_getter(
782
+ self,
783
+ field_spec: FieldSpec,
784
+ java_type: str,
785
+ indentation: str
786
+ ) -> List[str]:
787
+ """Build getter method."""
788
+ method_name = f"get{self._capitalize(field_spec.name)}"
789
+ return [
790
+ "",
791
+ f"{indentation}public {java_type} {method_name}() {{",
792
+ f"{indentation} return this.{field_spec.name};",
793
+ f"{indentation}}}",
794
+ ]
795
+
796
+ def _build_setter(
797
+ self,
798
+ field_spec: FieldSpec,
799
+ java_type: str,
800
+ indentation: str
801
+ ) -> List[str]:
802
+ """Build setter method."""
803
+ method_name = f"set{self._capitalize(field_spec.name)}"
804
+ return [
805
+ "",
806
+ f"{indentation}public void {method_name}({java_type} {field_spec.name}) {{",
807
+ f"{indentation} this.{field_spec.name} = {field_spec.name};",
808
+ f"{indentation}}}",
809
+ ]
810
+
811
+ def _build_validation_annotations(
812
+ self,
813
+ validation: Dict[str, Any],
814
+ indentation: str
815
+ ) -> List[str]:
816
+ """Build validation annotations from spec."""
817
+ lines = []
818
+
819
+ if validation.get("required"):
820
+ lines.append(f"{indentation}@NotNull")
821
+
822
+ if "min" in validation:
823
+ lines.append(f'{indentation}@Min({validation["min"]})')
824
+
825
+ if "max" in validation:
826
+ lines.append(f'{indentation}@Max({validation["max"]})')
827
+
828
+ if "minLength" in validation:
829
+ lines.append(f'{indentation}@Size(min = {validation["minLength"]})')
830
+
831
+ if "maxLength" in validation:
832
+ if "minLength" in validation:
833
+ lines[-1] = f'{indentation}@Size(min = {validation["minLength"]}, max = {validation["maxLength"]})'
834
+ else:
835
+ lines.append(f'{indentation}@Size(max = {validation["maxLength"]})')
836
+
837
+ if "pattern" in validation:
838
+ lines.append(f'{indentation}@Pattern(regexp = "{validation["pattern"]}")')
839
+
840
+ if validation.get("email"):
841
+ lines.append(f"{indentation}@Email")
842
+
843
+ return lines
844
+
845
+ def _find_field_declaration(
846
+ self,
847
+ lines: List[str],
848
+ field_name: str
849
+ ) -> tuple:
850
+ """Find the start and end lines of a field declaration."""
851
+ for i, line in enumerate(lines):
852
+ # Match field declaration
853
+ if re.search(rf"\s+{field_name}\s*[;=]", line):
854
+ # Check for annotations above
855
+ start = i
856
+ while start > 0 and lines[start - 1].strip().startswith("@"):
857
+ start -= 1
858
+ # Field is typically one line
859
+ return start, i
860
+ return -1, -1
861
+
862
+ def _find_method(self, lines: List[str], method_name: str) -> tuple:
863
+ """Find the start and end lines of a method."""
864
+ start = -1
865
+ brace_count = 0
866
+
867
+ for i, line in enumerate(lines):
868
+ if start < 0 and f"{method_name}(" in line:
869
+ start = i
870
+ brace_count = line.count("{") - line.count("}")
871
+ elif start >= 0:
872
+ brace_count += line.count("{") - line.count("}")
873
+ if brace_count <= 0:
874
+ return start, i
875
+
876
+ return -1, -1
877
+
878
+ def _add_imports(
879
+ self,
880
+ java_type: str,
881
+ lines: List[str],
882
+ file_path: str
883
+ ) -> Optional[Patch]:
884
+ """Add import statement if needed."""
885
+ import_class = self.IMPORT_MAP.get(java_type)
886
+ if not import_class:
887
+ return None
888
+
889
+ import_line = f"import {import_class};"
890
+
891
+ # Check if already imported
892
+ for line in lines:
893
+ if import_line in line:
894
+ return None
895
+
896
+ # Find import section
897
+ for i, line in enumerate(lines):
898
+ if line.startswith("import "):
899
+ # Insert alphabetically
900
+ existing_import = line.strip()
901
+ if import_line < existing_import:
902
+ return Patch(
903
+ file_path=file_path,
904
+ line_start=i + 1,
905
+ line_end=i,
906
+ old_content="",
907
+ new_content=import_line,
908
+ description=f"Add import for {java_type}",
909
+ confidence="high",
910
+ )
911
+ elif line.startswith("public class") or line.startswith("@"):
912
+ # Insert before class definition
913
+ return Patch(
914
+ file_path=file_path,
915
+ line_start=i + 1,
916
+ line_end=i,
917
+ old_content="",
918
+ new_content=import_line + "\n",
919
+ description=f"Add import for {java_type}",
920
+ confidence="high",
921
+ )
922
+
923
+ return None
924
+
925
+ def _to_snake_case(self, name: str) -> str:
926
+ """Convert camelCase to SNAKE_CASE."""
927
+ result = re.sub(r"([A-Z])", r"_\1", name)
928
+ return result.lstrip("_").upper()