Skip to content

feat(cli): add Java support and update related tests#13

Open
lcmetzger wants to merge 2 commits intocompozy:mainfrom
lcmetzger:feat_kb_java_support
Open

feat(cli): add Java support and update related tests#13
lcmetzger wants to merge 2 commits intocompozy:mainfrom
lcmetzger:feat_kb_java_support

Conversation

@lcmetzger
Copy link
Copy Markdown

@lcmetzger lcmetzger commented Apr 15, 2026

  • Add Java adapter support to parsing, scanning, and generation flow.
  • Expand unit and integration tests across adapters, CLI, lint, and generate paths.
  • Add Java ingest workflow artifacts (PRD, TechSpec, ADRs, tasks, and rollout docs).

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Java as a supported language for code analysis and semantic relation extraction.
    • Implemented Java module detection for Gradle and Maven projects with dependency mapping.
    • Added Java diagnostic governance with configurable parse error and fallback resolution thresholds.
    • Enabled cross-file Java method call and import relation discovery.
  • Chores

    • Updated CLI and linting tools to support Java language workflows.

- Add Java adapter support to parsing, scanning, and generation flow.
- Expand unit and integration tests across adapters, CLI, lint, and generate paths.
- Add Java ingest workflow artifacts (PRD, TechSpec, ADRs, tasks, and rollout docs).

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 15, 2026

Warning

Rate limit exceeded

@lcmetzger has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 8 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 16 minutes and 8 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c264a3fe-b436-4954-a5a3-443313c5c6ce

📥 Commits

Reviewing files that changed from the base of the PR and between 179995c and 6a46277.

📒 Files selected for processing (8)
  • internal/adapter/java_adapter.go
  • internal/adapter/java_adapter_test.go
  • internal/adapter/treesitter_test.go
  • internal/cli/generate_test.go
  • internal/cli/java_portfolio_playbook_integration_test.go
  • internal/generate/benchmark_policy_test.go
  • internal/generate/generate_integration_test.go
  • internal/scanner/scanner_test.go

Walkthrough

This PR adds comprehensive Java language support across the codebase, including a tree-sitter-based JavaAdapter for parsing Java source files, semantic and syntactic resolution for imports and method calls with fallback mechanisms, Java diagnostics governance for parse errors and fallback warnings, CLI flags, benchmark policies, and vault rendering for Java diagnostic summaries.

Changes

Cohort / File(s) Summary
Dependency Management
go.mod
Added tree-sitter-java v0.23.5 and promoted tree-sitter-rust to direct dependency.
Java Adapter Core Implementation
internal/adapter/java_adapter.go, internal/adapter/treesitter.go
Implemented full JavaAdapter with tree-sitter parsing, package/class/method extraction, import resolution, module metadata discovery from Gradle/Maven, two-phase resolution (deep semantic, syntactic fallback), and diagnostic aggregation for parse errors and unresolved references.
Java Adapter Unit Tests
internal/adapter/java_adapter_test.go
Comprehensive unit tests for JavaAdapter language support, parsing, imports, resolution phases, nested types, wildcard handling, metadata discovery, deterministic output, and diagnostic truncation.
Java Adapter Integration Tests
internal/adapter/java_adapter_integration_test.go
Integration tests validating cross-file relations, wildcard imports, nested type resolution, partial metadata resilience, ambiguous import stability, module hints disambiguation, and enterprise regression scenarios.
Supported Language Model Updates
internal/models/models.go, internal/models/models_test.go
Added LangJava constant to supported languages list and updated tests.
Lint Issue Kind Model
internal/models/kb_models.go, internal/models/kb_models_test.go
Added LintIssueKindJavaDiagnosticGovernance constant for Java diagnostic governance linting.
Java File Scanner
internal/scanner/scanner.go, internal/scanner/scanner_test.go
Extended file path scanner to recognize .java files and updated tests with Java file discovery.
Language Support Adapter Tests
internal/adapter/go_adapter_test.go, internal/adapter/rust_adapter_test.go, internal/adapter/ts_adapter_test.go, internal/adapter/treesitter_test.go
Updated adapter language rejection tests to include Java; added Java language initialization and parsing tests for tree-sitter.
CLI Help and Contract Tests
internal/cli/generate_test.go, internal/cli/ingest_test.go
Updated CLI help tests to assert Java in help output; added JSON contract validation tests for codebase ingest command.
Lint Command with Java Governance
internal/cli/lint.go, internal/cli/lint_test.go
Added CLI flags --java-max-parse-errors and --java-max-fallback-warnings for Java diagnostic thresholds; threaded options through to lint engine.
Java Portfolio Playbook
internal/cli/java_portfolio_playbook_test.go, internal/cli/java_portfolio_playbook_integration_test.go
Added test suite validating Java adoption playbook documentation and CLI integration test for end-to-end Java codebase ingestion workflow.
Generate/Telemetry Core
internal/generate/generate.go, internal/generate/generate_test.go
Registered JavaAdapter in runner defaults; added Java-specific parse telemetry fields (java_parse_duration_millis, java_files_processed, java_resolver_mode, java_fallback_count, java_unresolved_count) to parse stage completion events.
Benchmark Policy Framework
internal/generate/benchmark_policy.go, internal/generate/benchmark_policy_test.go
Introduced Java benchmark profiles (single-module library, Spring service, multi-module enterprise) with policy, fixture definitions, and utilities for median duration calculation.
Generate Integration Testing
internal/generate/generate_integration_test.go
Added integration tests for Java adapter selection in mixed workspaces, Java vault generation, performance budget validation, and high-volume diagnostic truncation; added corresponding benchmark fixtures.
Lint Governance Engine
internal/lint/lint.go, internal/lint/lint_test.go
Implemented Java diagnostics governance with LintOptions and JavaDiagnosticsGovernancePolicy to evaluate parse error and fallback warning counts against thresholds; added LintWithOptions variant.
Workflow Integration & Helpers
internal/cli/workflow_integration_test.go, internal/cli/workflow_test_helpers_test.go
Added comprehensive workflow integration tests for Java codebase ingestion validation, JSON contract helpers, multi-module fixture generation, and semantic summary validation.
Vault Rendering
internal/vault/render.go
Added Java diagnostic aggregation from graph diagnostics and rendering to per-language raw index with diagnostic counts in frontmatter and body summary sections.

Sequence Diagram

sequenceDiagram
    actor CLI
    participant JavaAdapter
    participant TreeSitter
    participant ModuleMetadataLoader
    participant DeepResolver
    participant SyntacticResolver
    participant DiagnosticsBuilder

    CLI->>JavaAdapter: ParseFiles(files, rootPath)
    JavaAdapter->>TreeSitter: Parse Java source file
    TreeSitter-->>JavaAdapter: Tree + symbols (class, method, import)
    JavaAdapter->>ModuleMetadataLoader: Discover modules from Gradle/Maven
    ModuleMetadataLoader-->>JavaAdapter: Module dependency map
    
    JavaAdapter->>DeepResolver: Resolve imports & calls (Phase 1: Semantic)
    DeepResolver->>DeepResolver: Lookup FQN in global context
    DeepResolver-->>JavaAdapter: Resolved relations + failures
    
    JavaAdapter->>SyntacticResolver: Resolve failures (Phase 2: Syntactic)
    SyntacticResolver->>SyntacticResolver: Fallback pattern matching
    SyntacticResolver-->>JavaAdapter: Additional relations + remaining unresolved
    
    JavaAdapter->>DiagnosticsBuilder: Build diagnostics from unresolved & metadata
    DiagnosticsBuilder-->>JavaAdapter: Warnings & errors (truncated if needed)
    
    JavaAdapter-->>CLI: ParsedFile{nodes, relations, diagnostics}
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding Java support to the CLI and updating related tests, which is reflected across the entire changeset including the new JavaAdapter, scanner extensions, and comprehensive test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (10)
internal/generate/benchmark_policy_test.go (1)

92-95: Prefer t.TempDir() over hardcoded /tmp in tests.

Using t.TempDir() keeps the test environment isolated and portable.

Suggested change
- options := benchmarkGenerateOptions("/tmp/canonical-repo")
- if options.RootPath != "/tmp/canonical-repo" {
- 	t.Fatalf("RootPath = %q, want /tmp/canonical-repo", options.RootPath)
- }
+ rootPath := t.TempDir()
+ options := benchmarkGenerateOptions(rootPath)
+ if options.RootPath != rootPath {
+ 	t.Fatalf("RootPath = %q, want %q", options.RootPath, rootPath)
+ }

As per coding guidelines, **/*_test.go: "Default to table-driven tests with focused helpers and t.TempDir() for filesystem isolation".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/generate/benchmark_policy_test.go` around lines 92 - 95, Replace the
hardcoded "/tmp/canonical-repo" test input with a t.TempDir()-based path: call
tmp := t.TempDir(), build the repo path with filepath.Join(tmp,
"canonical-repo"), pass that into benchmarkGenerateOptions and assert
options.RootPath equals that joined path; also ensure the test imports
"path/filepath" if not already present and remove the hardcoded "/tmp" usage.
internal/cli/ingest_test.go (1)

443-568: Consolidate duplicated contract tests into a single table-driven subtest suite.

Line 443 and Line 506 repeat almost the same setup/assertions. This is a good candidate for one table-driven test with t.Run("Should ...") cases for dryRun=true/false.

♻️ Suggested refactor
-func TestIngestCodebaseCommandJSONContractRequiredKeysFullRun(t *testing.T) {
-    // ...
-}
-
-func TestIngestCodebaseCommandJSONContractRequiredKeysDryRun(t *testing.T) {
-    // ...
-}
+func TestIngestCodebaseCommandJSONContractRequiredKeys(t *testing.T) {
+    testCases := []struct {
+        name   string
+        dryRun bool
+    }{
+        {name: "Should validate codebase ingest JSON contract for full run", dryRun: false},
+        {name: "Should validate codebase ingest JSON contract for dry run", dryRun: true},
+    }
+
+    for _, testCase := range testCases {
+        testCase := testCase
+        t.Run(testCase.name, func(t *testing.T) {
+            restoreIngestGlobals(t)
+            // shared stubs...
+            // args include --dry-run only when testCase.dryRun
+            // decode + shape + semantics assertions using testCase.dryRun
+        })
+    }
+}

As per coding guidelines, **/*_test.go: Default to table-driven tests with focused helpers and t.TempDir() and MUST use t.Run("Should...") pattern for ALL test cases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cli/ingest_test.go` around lines 443 - 568, The two tests
TestIngestCodebaseCommandJSONContractRequiredKeysFullRun and
TestIngestCodebaseCommandJSONContractRequiredKeysDryRun duplicate setup and
assertions; convert them into a single table-driven test that iterates over
cases for dryRun true/false using t.Run("Should ...") subtests, use t.TempDir()
instead of hard-coded /tmp paths, and factor common setup (overriding
runIngestTopicInfo and runGenerate) into a helper or closure; keep calls to
newRootCommand(), decodeJSONMap(), assertCodebaseIngestContractShape(), and
assertCodebaseIngestContractSemantics() but call them per-case with the
appropriate dryRun flag so runGenerate returns the correct GenerationSummary for
each case.
internal/generate/generate.go (1)

69-77: Centralize default adapter registration to avoid drift.

The default adapter slice is duplicated in both constructors. Extracting a single helper for default adapters will prevent future mismatch bugs when adding/removing languages.

♻️ Suggested refactor
+func defaultLanguageAdapters() []models.LanguageAdapter {
+	return []models.LanguageAdapter{
+		adapter.TSAdapter{},
+		adapter.GoAdapter{},
+		adapter.RustAdapter{},
+		adapter.JavaAdapter{},
+	}
+}
+
 func newRunner() runner {
 	return runner{
 		scanWorkspace: scanner.ScanWorkspace,
-		adapters: []models.LanguageAdapter{
-			adapter.TSAdapter{},
-			adapter.GoAdapter{},
-			adapter.RustAdapter{},
-			adapter.JavaAdapter{},
-		},
+		adapters: defaultLanguageAdapters(),
 		// ...
 	}
 }
 
 func (r runner) withDefaults() runner {
 	if len(r.adapters) == 0 {
-		r.adapters = []models.LanguageAdapter{
-			adapter.TSAdapter{},
-			adapter.GoAdapter{},
-			adapter.RustAdapter{},
-			adapter.JavaAdapter{},
-		}
+		r.adapters = defaultLanguageAdapters()
 	}

Also applies to: 373-379

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/generate/generate.go` around lines 69 - 77, Extract the duplicated
default adapters slice into a single helper function (e.g.,
defaultLanguageAdapters) that returns []models.LanguageAdapter and replace the
inline literal in newRunner (which sets runner.adapters) and the other
constructor that currently duplicates the slice (the one around lines ~373-379)
to call this helper; update the runner struct initialization to use
defaultLanguageAdapters() so all constructors share the same source of truth and
prevent drift when adding/removing adapters.
internal/lint/lint_test.go (1)

197-325: Refactor Java governance tests into a single table-driven t.Run("Should...") suite.

These four tests validate adjacent policy permutations and can share setup/assertions with per-case expectations to reduce drift and make future governance changes easier to maintain.

As per coding guidelines, **/*_test.go: Default to table-driven tests with focused helpers and t.TempDir() and MUST use t.Run("Should...") pattern for ALL test cases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/lint/lint_test.go` around lines 197 - 325, Combine the four separate
tests (TestLintJavaDiagnosticsGovernanceParseErrorsBlockByDefault,
TestLintJavaDiagnosticsGovernanceFallbackDisabledByDefault,
TestLintJavaDiagnosticsGovernanceAppliesCustomFallbackThreshold,
TestLintJavaDiagnosticsGovernanceMessageUsesMachineReadableCounts) into a single
table-driven test that uses t.Run("Should ...") subtests and t.TempDir(),
extracting common setup (newTestTopic/writeMarkdownFile/mustLint or
LintWithOptions) into a helper; create a slice of cases with fields for input
metadata, optional LintOptions, expected presence/absence of models.LintIssue
(and expected Target/Severity/payload assertions for the machine-readable
message case), iterate cases and for each call t.Run(case.name, func(t
*testing.T){ ... }) performing the shared setup/assertions and only per-case
checks in the loop. Ensure you preserve the unique expectations for
JAVA_PARSE_ERROR, JAVA_RESOLUTION_FALLBACK and the JSON message assertion
(unmarshal parseIssue.Message) within the appropriate case.
internal/cli/java_portfolio_playbook_test.go (1)

23-90: Convert repeated playbook fragment checks into one table-driven subtest.

The three tests are structurally identical (load file + assert fragments). A single table-driven test with t.Run("Should ...") cases will keep this easier to extend and less repetitive.

As per coding guidelines, **/*_test.go: Default to table-driven tests with focused helpers and t.TempDir() and MUST use t.Run("Should...") pattern for ALL test cases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cli/java_portfolio_playbook_test.go` around lines 23 - 90, Three
near-identical tests
(TestJavaPortfolioPlaybookIncludesGovernanceAndContractRequirements,
TestJavaPortfolioPlaybookIncludesFallbackAndUnresolvedGuidance,
TestJavaPortfolioPlaybookCommandsAlignWithCurrentCLI) should be consolidated
into one table-driven test that uses t.Run("Should ...") subtests; replace the
three separate functions with a single TestJavaPortfolioPlaybookFragments that
calls readJavaPortfolioPlaybook once and iterates over a slice of cases where
each case has a name and requiredFragments slice, running each case as a subtest
(call t.Run(caseName, func(t *testing.T) { t.Parallel(); ... })) and performing
the strings.Contains checks inside the subtest; keep the helper
readJavaPortfolioPlaybook, preserve t.Parallel semantics at the subtest level,
and follow the t.Run naming convention and table-driven pattern as required.
internal/generate/generate_integration_test.go (1)

179-260: Convert the new integration cases to Should... subtests.

The new Java coverage is useful, but these additions still expand the file with standalone cases instead of grouped t.Run("Should...") scenarios.

As per coding guidelines, **/*_test.go: Default to table-driven tests with focused helpers and t.TempDir() for filesystem isolationandMUST use t.Run("Should...") pattern for ALL test cases`.

Also applies to: 302-391

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/generate/generate_integration_test.go` around lines 179 - 260, The
two new standalone tests
TestGenerateIntegrationDryRunSelectsJavaAdapterForMixedWorkspace and
TestGenerateIntegrationBuildsVaultFromJavaPhase2Workspace should be converted
into t.Run("Should...") subtests (and folded into a table-driven pattern where
appropriate) per test guidelines: wrap each scenario body in t.Run with
descriptive "Should..." names, move repeated setup into focused helpers (reuse
writeFixtureFile/writeJavaPhase2Fixture and newRunner), keep using t.TempDir for
isolation, and update any similar cases in the same file (around the 302-391
additions) to follow the same t.Run table-driven structure so all cases are
subtests rather than standalone Test* functions.
internal/generate/generate_test.go (1)

213-283: Group the new cases into table-driven t.Run("Should...") suites.

These Java adapter/telemetry additions are mostly standalone tests with duplicated setup and assertions, which makes the file harder to extend as more languages or telemetry fields are added.

As per coding guidelines, **/*_test.go: Default to table-driven tests with focused helpers and t.TempDir() for filesystem isolationandMUST use t.Run("Should...") pattern for ALL test cases`.

Also applies to: 733-925

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/generate/generate_test.go` around lines 213 - 283, The tests
TestSelectAdaptersIncludesJavaWhenWorkspaceHasJava,
TestSelectAdaptersForMixedWorkspace,
TestNewRunnerRegistersJavaAdapterInExpectedOrder, and
TestRunnerWithDefaultsIncludesJavaAdapterWhenAdaptersUnset should be converted
into table-driven t.Run suites to remove duplication: create a single test table
(cases with name, input languages, adapters, expected names/count/order) and
iterate with t.Run for the selectAdapters cases and another t.Run table for
runner/withDefaults adapter-order assertions; extract shared setup into small
helpers (e.g., makeFakeAdapters or adapterNames helper is fine) and use
t.TempDir() where filesystem isolation is needed, replacing repeated setup code,
ensuring each case uses t.Parallel() inside its t.Run body if appropriate.
internal/adapter/java_adapter_integration_test.go (1)

13-628: Keep the integration coverage, but organize it as Should... subtests.

These scenarios are meaningful integration cases, but they're still added as many one-off top-level tests rather than grouped subtests around the same workflow.

As per coding guidelines, **/*_test.go: Default to table-driven tests with focused helpers and t.TempDir() for filesystem isolation, MUST use t.Run("Should...") pattern for ALL test cases, and **/*_integration_test.go: Integration tests use the integration build tag and live next to the packages they exercise.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/adapter/java_adapter_integration_test.go` around lines 13 - 628, The
many top-level tests (e.g. TestJavaAdapterBuildsCrossFileImportAndCallRelations,
TestJavaAdapterBuildsWildcardImportRelationsAcrossFiles,
TestJavaAdapterOutputIsDeterministicAcrossRuns,
TestJavaAdapterPartialMetadataFallsBackWithoutFailingIngest,
TestJavaAdapterMissingWildcardPackageFallsBackWithoutFailingIngest,
TestJavaAdapterResolvesNestedAndTopLevelRelationsAcrossFiles,
TestJavaAdapterAmbiguousImportsRemainStableAcrossRuns,
TestJavaAdapterModuleHintsImproveAmbiguousImportResolution,
TestJavaAdapterWithoutModuleHintsKeepsAmbiguousFallbackPath,
TestJavaAdapterPhase2EnterpriseScenarioRegression) should be reorganized into
t.Run subtests using the "Should..." naming convention and converted to a
table-driven structure where possible; add an integration build tag at the top
of the file, wrap each scenario with t.Run("Should ...", func(t *testing.T){
t.Parallel(); ... }), migrate any filesystem usage to t.TempDir() and update
helper calls (parseJavaSources, parseJavaSourcesWithRepositoryFiles) to
accept/use the temp dir or ensure isolation via helpers, and consolidate shared
setup/teardown into focused helper functions so each subtest is terse and
follows the table-driven/testing guidelines.
internal/cli/workflow_test_helpers_test.go (1)

324-508: Align the helper tests with the repo's required subtest pattern.

The new helper coverage is fine, but these cases still rely on top-level one-offs and t.Run(testCase.name, ...) names that don't follow the required Should... convention.

As per coding guidelines, **/*_test.go: Default to table-driven tests with focused helpers and t.TempDir() for filesystem isolationandMUST use t.Run("Should...") pattern for ALL test cases`.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cli/workflow_test_helpers_test.go` around lines 324 - 508, Update
the tests to use the required "Should..." subtest naming pattern: in
TestValidateJavaCodebaseSummary change the existing t.Run(testCase.name, ...) to
t.Run("Should "+testCase.name, ...) so every table-driven case is named "Should
..."; also wrap the single-case TestAssertJavaCodebaseSummaryPassesForValidInput
body inside a t.Run("Should pass for valid input", func(t *testing.T){ ... }) to
follow the MUST use t.Run("Should...") convention; keep existing use of
t.Parallel() and t.TempDir().
internal/adapter/java_adapter_test.go (1)

15-1389: Restructure this suite into grouped t.Run("Should...") tables.

The coverage is valuable, but dozens of top-level tests for closely related resolver branches make the suite harder to scan and maintain than it needs to be.

As per coding guidelines, **/*_test.go: Default to table-driven tests with focused helpers and t.TempDir() for filesystem isolationandMUST use t.Run("Should...") pattern for ALL test cases`.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/adapter/java_adapter_test.go` around lines 15 - 1389, Group the many
related branch checks into table-driven subtests using t.Run for each logical
suite (e.g., consolidate TestResolveJavaDeepImport,
TestResolveJavaDeepCallTargetBranches, TestResolveJavaCallTargetBranches,
TestResolveJavaSyntacticImport and their subcases) by creating a slice of test
cases with name, inputs, expected outputs and iterating over them calling
t.Run(tc.name, func(t *testing.T) { ... }); keep the existing helper calls to
resolveJavaDeepImport, resolveJavaDeepCallTarget, resolveJavaCallTarget,
resolveJavaSyntacticImport and assertions but move per-branch setup into each
table entry, reuse t.TempDir()/parse helpers as needed, and ensure deterministic
ordering by sorting case keys if necessary so the semantics of existing
assertions remain identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/adapter/java_adapter.go`:
- Around line 1796-1806: The artifactId extraction in parseMavenModulePomSignals
incorrectly returns the first <artifactId> (often the parent); update
parseMavenModulePomSignals to scope the lookup to the module's own artifactId by
ignoring any <artifactId> inside a <parent> block (or by extracting the
<artifactId> that is a direct child of <project>). Concretely: before applying
javaMavenArtifactPattern, strip or skip the substring corresponding to the
<parent>...</parent> block (or use a non-greedy regex that matches
<project.*?>.*?<artifactId>...</artifactId> at the project level) so artifactID
reflects the module's own <artifactId> (keep references to
parseMavenModulePomSignals and javaMavenArtifactPattern).

In `@internal/adapter/treesitter_test.go`:
- Around line 37-40: Test case names for the Java subtests do not follow the
repository convention requiring t.Run("Should...") naming; update the test
entries that currently use name: "java" (and the other Java entries around lines
99-104) so that their t.Run invocations use descriptive "Should..." names (e.g.,
"Should parse Java constructs") when calling the subtests, and keep the same
load: func() *tree_sitter.Language { return javaLanguage() } and other fields
unchanged; ensure the t.Run string follows the exact "Should..." prefix for all
Java-related subtests.

In `@internal/cli/generate_test.go`:
- Around line 230-233: The test currently checks for the raw substring "java"
which can yield false positives; update the assertion in generate_test.go so it
looks for an exact token match instead (e.g. use a word-boundary regex like
`\bjava\b` or check for newline/delimiter-wrapped token such as "\njava\n") when
inspecting stdout.String() instead of the plain "java" fragment, keeping the
other fragments (supportedCodebaseLanguagesHelp(), "--dry-run") unchanged.

In `@internal/cli/java_portfolio_playbook_integration_test.go`:
- Around line 13-96: The test
TestCLIIntegrationJavaPortfolioPlaybookCommandsAndSemantics duplicates existing
Java contract/telemetry/lint assertions; remove or narrow the redundant checks
(the dry-run/full-run contract asserts via
assertCodebaseIngestContractShape/assertCodebaseIngestContractSemantics, the
parse telemetry checks using findJSONStageCompletedEvent/eventFieldInt, and the
lint assertion) and instead keep only playbook-specific behavior or delegate to
the shared workflow integration path; update the test to call the shared helper
(or remove the duplicate blocks around runCLIJSON/runCLIWithStreams, the
json.Unmarshal into codebaseIngestResult, assertJavaCodebaseSummary,
parseCompletedDryRun/parseCompletedFullRun checks, and the final lint run) so
this file only verifies playbook-specific commands and semantics.

In `@internal/generate/benchmark_policy_test.go`:
- Around line 9-114: Rename the subtests and wrap single-case tests to follow
the "Should..." t.Run pattern: in TestMedianDurationFromSamples change each
subtest Run name to "Should return middle for odd sample count", "Should return
midpoint average for even sample count", and "Should fail on empty samples"
(keep using medianDurationFromSamples); for the other top-level tests
(TestCanonicalJavaBenchmarkFixtures, TestBenchmarkGenerateOptions,
TestCanonicalJavaBenchmarkPolicy) wrap their assertion blocks inside
t.Run("Should ...") subtests (e.g., TestCanonicalJavaBenchmarkFixtures ->
t.Run("Should return canonical Java benchmark fixtures") checking
canonicalJavaBenchmarkFixtures(), TestBenchmarkGenerateOptions -> t.Run("Should
build benchmark generate options") checking benchmarkGenerateOptions(), and
TestCanonicalJavaBenchmarkPolicy -> t.Run("Should return canonical Java
benchmark policy") checking canonicalJavaBenchmarkPolicy()), preserving
t.Parallel() where present and all existing assertions.

In `@internal/generate/generate_integration_test.go`:
- Around line 262-300: The integration test
TestGenerateIntegrationJavaIngestPerformanceBudget currently enforces a
wall-clock overhead budget that can flake on shared CI; make the budget
assertion opt-in by guarding the fail path with an environment flag or testing
condition (e.g., check os.Getenv("ENABLE_PERF_BUDGET") == "1" or skip when
testing.Short() is true) so the test still measures durations and logs the
overhead but only calls t.Fatalf when the opt-in flag is set; update the
function (and references to policy/overhead logic) so it always computes and
t.Logf the results but only enforces policy.OverheadBudget when the opt-in
condition is met.

In `@internal/scanner/scanner_test.go`:
- Around line 248-257: The subtest names in the table-driven tests (the slice
with entries like name: "go", "rust", etc.) must follow the t.Run("Should...")
naming convention; update each test case's name field (and the corresponding
t.Run invocation) to a descriptive "Should ..." phrase (e.g., "Should detect Go
files", "Should detect Rust files", "Should return unsupported for dts", "Should
return unsupported for README") so all t.Run calls use the required pattern;
apply the same renaming to the additional table entries referenced around the
other block (the cases at lines ~261-273) to keep names consistent across
scanner_test.go and ensure assertions remain unchanged.

---

Nitpick comments:
In `@internal/adapter/java_adapter_integration_test.go`:
- Around line 13-628: The many top-level tests (e.g.
TestJavaAdapterBuildsCrossFileImportAndCallRelations,
TestJavaAdapterBuildsWildcardImportRelationsAcrossFiles,
TestJavaAdapterOutputIsDeterministicAcrossRuns,
TestJavaAdapterPartialMetadataFallsBackWithoutFailingIngest,
TestJavaAdapterMissingWildcardPackageFallsBackWithoutFailingIngest,
TestJavaAdapterResolvesNestedAndTopLevelRelationsAcrossFiles,
TestJavaAdapterAmbiguousImportsRemainStableAcrossRuns,
TestJavaAdapterModuleHintsImproveAmbiguousImportResolution,
TestJavaAdapterWithoutModuleHintsKeepsAmbiguousFallbackPath,
TestJavaAdapterPhase2EnterpriseScenarioRegression) should be reorganized into
t.Run subtests using the "Should..." naming convention and converted to a
table-driven structure where possible; add an integration build tag at the top
of the file, wrap each scenario with t.Run("Should ...", func(t *testing.T){
t.Parallel(); ... }), migrate any filesystem usage to t.TempDir() and update
helper calls (parseJavaSources, parseJavaSourcesWithRepositoryFiles) to
accept/use the temp dir or ensure isolation via helpers, and consolidate shared
setup/teardown into focused helper functions so each subtest is terse and
follows the table-driven/testing guidelines.

In `@internal/adapter/java_adapter_test.go`:
- Around line 15-1389: Group the many related branch checks into table-driven
subtests using t.Run for each logical suite (e.g., consolidate
TestResolveJavaDeepImport, TestResolveJavaDeepCallTargetBranches,
TestResolveJavaCallTargetBranches, TestResolveJavaSyntacticImport and their
subcases) by creating a slice of test cases with name, inputs, expected outputs
and iterating over them calling t.Run(tc.name, func(t *testing.T) { ... }); keep
the existing helper calls to resolveJavaDeepImport, resolveJavaDeepCallTarget,
resolveJavaCallTarget, resolveJavaSyntacticImport and assertions but move
per-branch setup into each table entry, reuse t.TempDir()/parse helpers as
needed, and ensure deterministic ordering by sorting case keys if necessary so
the semantics of existing assertions remain identical.

In `@internal/cli/ingest_test.go`:
- Around line 443-568: The two tests
TestIngestCodebaseCommandJSONContractRequiredKeysFullRun and
TestIngestCodebaseCommandJSONContractRequiredKeysDryRun duplicate setup and
assertions; convert them into a single table-driven test that iterates over
cases for dryRun true/false using t.Run("Should ...") subtests, use t.TempDir()
instead of hard-coded /tmp paths, and factor common setup (overriding
runIngestTopicInfo and runGenerate) into a helper or closure; keep calls to
newRootCommand(), decodeJSONMap(), assertCodebaseIngestContractShape(), and
assertCodebaseIngestContractSemantics() but call them per-case with the
appropriate dryRun flag so runGenerate returns the correct GenerationSummary for
each case.

In `@internal/cli/java_portfolio_playbook_test.go`:
- Around line 23-90: Three near-identical tests
(TestJavaPortfolioPlaybookIncludesGovernanceAndContractRequirements,
TestJavaPortfolioPlaybookIncludesFallbackAndUnresolvedGuidance,
TestJavaPortfolioPlaybookCommandsAlignWithCurrentCLI) should be consolidated
into one table-driven test that uses t.Run("Should ...") subtests; replace the
three separate functions with a single TestJavaPortfolioPlaybookFragments that
calls readJavaPortfolioPlaybook once and iterates over a slice of cases where
each case has a name and requiredFragments slice, running each case as a subtest
(call t.Run(caseName, func(t *testing.T) { t.Parallel(); ... })) and performing
the strings.Contains checks inside the subtest; keep the helper
readJavaPortfolioPlaybook, preserve t.Parallel semantics at the subtest level,
and follow the t.Run naming convention and table-driven pattern as required.

In `@internal/cli/workflow_test_helpers_test.go`:
- Around line 324-508: Update the tests to use the required "Should..." subtest
naming pattern: in TestValidateJavaCodebaseSummary change the existing
t.Run(testCase.name, ...) to t.Run("Should "+testCase.name, ...) so every
table-driven case is named "Should ..."; also wrap the single-case
TestAssertJavaCodebaseSummaryPassesForValidInput body inside a t.Run("Should
pass for valid input", func(t *testing.T){ ... }) to follow the MUST use
t.Run("Should...") convention; keep existing use of t.Parallel() and
t.TempDir().

In `@internal/generate/benchmark_policy_test.go`:
- Around line 92-95: Replace the hardcoded "/tmp/canonical-repo" test input with
a t.TempDir()-based path: call tmp := t.TempDir(), build the repo path with
filepath.Join(tmp, "canonical-repo"), pass that into benchmarkGenerateOptions
and assert options.RootPath equals that joined path; also ensure the test
imports "path/filepath" if not already present and remove the hardcoded "/tmp"
usage.

In `@internal/generate/generate_integration_test.go`:
- Around line 179-260: The two new standalone tests
TestGenerateIntegrationDryRunSelectsJavaAdapterForMixedWorkspace and
TestGenerateIntegrationBuildsVaultFromJavaPhase2Workspace should be converted
into t.Run("Should...") subtests (and folded into a table-driven pattern where
appropriate) per test guidelines: wrap each scenario body in t.Run with
descriptive "Should..." names, move repeated setup into focused helpers (reuse
writeFixtureFile/writeJavaPhase2Fixture and newRunner), keep using t.TempDir for
isolation, and update any similar cases in the same file (around the 302-391
additions) to follow the same t.Run table-driven structure so all cases are
subtests rather than standalone Test* functions.

In `@internal/generate/generate_test.go`:
- Around line 213-283: The tests
TestSelectAdaptersIncludesJavaWhenWorkspaceHasJava,
TestSelectAdaptersForMixedWorkspace,
TestNewRunnerRegistersJavaAdapterInExpectedOrder, and
TestRunnerWithDefaultsIncludesJavaAdapterWhenAdaptersUnset should be converted
into table-driven t.Run suites to remove duplication: create a single test table
(cases with name, input languages, adapters, expected names/count/order) and
iterate with t.Run for the selectAdapters cases and another t.Run table for
runner/withDefaults adapter-order assertions; extract shared setup into small
helpers (e.g., makeFakeAdapters or adapterNames helper is fine) and use
t.TempDir() where filesystem isolation is needed, replacing repeated setup code,
ensuring each case uses t.Parallel() inside its t.Run body if appropriate.

In `@internal/generate/generate.go`:
- Around line 69-77: Extract the duplicated default adapters slice into a single
helper function (e.g., defaultLanguageAdapters) that returns
[]models.LanguageAdapter and replace the inline literal in newRunner (which sets
runner.adapters) and the other constructor that currently duplicates the slice
(the one around lines ~373-379) to call this helper; update the runner struct
initialization to use defaultLanguageAdapters() so all constructors share the
same source of truth and prevent drift when adding/removing adapters.

In `@internal/lint/lint_test.go`:
- Around line 197-325: Combine the four separate tests
(TestLintJavaDiagnosticsGovernanceParseErrorsBlockByDefault,
TestLintJavaDiagnosticsGovernanceFallbackDisabledByDefault,
TestLintJavaDiagnosticsGovernanceAppliesCustomFallbackThreshold,
TestLintJavaDiagnosticsGovernanceMessageUsesMachineReadableCounts) into a single
table-driven test that uses t.Run("Should ...") subtests and t.TempDir(),
extracting common setup (newTestTopic/writeMarkdownFile/mustLint or
LintWithOptions) into a helper; create a slice of cases with fields for input
metadata, optional LintOptions, expected presence/absence of models.LintIssue
(and expected Target/Severity/payload assertions for the machine-readable
message case), iterate cases and for each call t.Run(case.name, func(t
*testing.T){ ... }) performing the shared setup/assertions and only per-case
checks in the loop. Ensure you preserve the unique expectations for
JAVA_PARSE_ERROR, JAVA_RESOLUTION_FALLBACK and the JSON message assertion
(unmarshal parseIssue.Message) within the appropriate case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4ecfe5a8-e19d-41dd-9fa9-01aa05ec2146

📥 Commits

Reviewing files that changed from the base of the PR and between 9e2d1d9 and 179995c.

⛔ Files ignored due to path filters (55)
  • .agents/skills/compozy/SKILL.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/compozy/references/cli-reference.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/compozy/references/config-reference.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/compozy/references/skills-reference.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/compozy/references/workflow-guide.md is excluded by !**/*.md, !.agents/**
  • .compozy/tasks/java-ingest-adapter/_automation-json-contract.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/_java-portfolio-adoption-playbook.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/_meta.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/_phase3-benchmark-baseline.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/_prd.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/_rollout-mvp-signoff.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/_tasks.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/_techspec.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/adrs/adr-001.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/adrs/adr-002.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/adrs/adr-003.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/adrs/adr-004.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/adrs/adr-005.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/adrs/adr-006.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/MEMORY.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_01.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_02.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_03.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_04.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_05.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_06.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_07.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_08.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_09.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_10.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_11.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_12.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_13.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_14.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_15.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_16.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/memory/task_17.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_01.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_02.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_03.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_04.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_05.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_06.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_07.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_08.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_09.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_10.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_11.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_12.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_13.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_14.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_15.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_16.md is excluded by !**/*.md
  • .compozy/tasks/java-ingest-adapter/task_17.md is excluded by !**/*.md
  • internal/generate/testdata/java-benchmark-corpus/README.md is excluded by !**/*.md
📒 Files selected for processing (31)
  • go.mod
  • internal/adapter/go_adapter_test.go
  • internal/adapter/java_adapter.go
  • internal/adapter/java_adapter_integration_test.go
  • internal/adapter/java_adapter_test.go
  • internal/adapter/rust_adapter_test.go
  • internal/adapter/treesitter.go
  • internal/adapter/treesitter_test.go
  • internal/adapter/ts_adapter_test.go
  • internal/cli/generate_test.go
  • internal/cli/ingest_test.go
  • internal/cli/java_portfolio_playbook_integration_test.go
  • internal/cli/java_portfolio_playbook_test.go
  • internal/cli/lint.go
  • internal/cli/lint_test.go
  • internal/cli/workflow_integration_test.go
  • internal/cli/workflow_test_helpers_test.go
  • internal/generate/benchmark_policy.go
  • internal/generate/benchmark_policy_test.go
  • internal/generate/generate.go
  • internal/generate/generate_integration_test.go
  • internal/generate/generate_test.go
  • internal/lint/lint.go
  • internal/lint/lint_test.go
  • internal/models/kb_models.go
  • internal/models/kb_models_test.go
  • internal/models/models.go
  • internal/models/models_test.go
  • internal/scanner/scanner.go
  • internal/scanner/scanner_test.go
  • internal/vault/render.go

Comment thread internal/adapter/java_adapter.go
Comment thread internal/adapter/treesitter_test.go
Comment thread internal/cli/generate_test.go Outdated
Comment thread internal/cli/java_portfolio_playbook_integration_test.go
Comment thread internal/generate/benchmark_policy_test.go
Comment thread internal/generate/generate_integration_test.go
Comment thread internal/scanner/scanner_test.go Outdated
- Implement logic to ignore parent artifact ID in Maven POM parsing.
- Add unit test for parsing Maven module POM signals.
- Update existing tests for clarity and consistency in naming conventions.
- Improve performance budget enforcement in integration tests for Java ingestion.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant