Describe the bug
CodeAnalyzer.java:570 calls ArtifactDiscovery.discover(Paths.get(input), …) — discovery gets the input path and nothing else, and its IGNORED set (.git, .hg, .svn, target, build, out, bin, .gradle, .mvn, .idea, .settings, node_modules, .codeanalyzer, _library_dependencies) is matched by directory name. So when -o points inside -i, the run ingests the previous run's analysis.json as an artifact.
Unlike the Python and TypeScript analyzers, java caps captured text at artifactTextMaxBytes = 262144, so the payload grows linearly, not squared — there is no OOM kill. The damage is a wrong inventory and a payload polluted with up to 256 KB of the analyzer's own previous output per run, silently, on any -o not coincidentally named out, build, bin, or target.
To Reproduce
Run twice with -o <project>/.output; the second run's application.artifacts contains .output/analysis.json, with the first run's output as its text (truncated to the cap).
Expected behavior
Ported from codellm-devkit/codeanalyzer-python#207 (fix: codellm-devkit/codeanalyzer-python#216).
Additional context
Scope boundary
In scope: threading the resolved output path (and the cache directory, if it can sit inside the project) from CodeAnalyzer into ArtifactDiscovery.discover, and skipping it during the walk. Out of scope: the text cap, the classification rules, and IGNORED for unrelated names.
Goals
- A run whose
-o sits inside -i never inventories its own output.
- The exclusion derives from resolved paths, not from hardcoded directory names.
-o outside the project is unaffected — no artifact silently dropped.
Caveats and known risks
- An output directory that is the project root cannot be skipped wholesale without emptying the inventory; excluding the output file covers that case at the cost of one file.
- A pre-existing file living in the chosen output directory becomes invisible.
- The artifact inventory changes for anyone who had
-o inside -i — payload content, no schema shape change.
Describe the bug
CodeAnalyzer.java:570callsArtifactDiscovery.discover(Paths.get(input), …)— discovery gets the input path and nothing else, and itsIGNOREDset (.git, .hg, .svn, target, build, out, bin, .gradle, .mvn, .idea, .settings, node_modules, .codeanalyzer, _library_dependencies) is matched by directory name. So when-opoints inside-i, the run ingests the previous run'sanalysis.jsonas an artifact.Unlike the Python and TypeScript analyzers, java caps captured text at
artifactTextMaxBytes = 262144, so the payload grows linearly, not squared — there is no OOM kill. The damage is a wrong inventory and a payload polluted with up to 256 KB of the analyzer's own previous output per run, silently, on any-onot coincidentally namedout,build,bin, ortarget.To Reproduce
Run twice with
-o <project>/.output; the second run'sapplication.artifactscontains.output/analysis.json, with the first run's output as its text (truncated to the cap).Expected behavior
-oinside-iand asserts the output directory never appears inapplication.artifactswhile a sibling file still does.-opaths resolve to the same exclusion.Ported from codellm-devkit/codeanalyzer-python#207 (fix: codellm-devkit/codeanalyzer-python#216).
Additional context
Scope boundary
In scope: threading the resolved output path (and the cache directory, if it can sit inside the project) from
CodeAnalyzerintoArtifactDiscovery.discover, and skipping it during the walk. Out of scope: the text cap, the classification rules, andIGNOREDfor unrelated names.Goals
-osits inside-inever inventories its own output.-ooutside the project is unaffected — no artifact silently dropped.Caveats and known risks
-oinside-i— payload content, no schema shape change.