fix(artifacts): the run's own output is not an input (#207) - #216
Merged
Merged
Conversation
`discover_artifacts` walked the project with no idea where the run writes, so `-o` (or `-c`) inside `-i` made run N ingest run N-1's `analysis.json` whole and embed it in its own output. Each run squared the last until the analyzer was SIGKILLed decoding tens of GB of its own output -- which reads as a flaky, load-sensitive test suite and had been misdiagnosed as one more than once. `core.analyze` now hands discovery the paths this run writes: the output and cache directories, plus the output files inside them. Matching is on resolved paths, so a relative, `..`-laden or symlinked target excludes the same tree and a target outside the project excludes nothing. A *directory* exclusion that holds the project itself is refused -- it would empty the inventory -- and the file entries cover that degenerate case, so `-o <project root>` and a `--emit neo4j` `graph.cypher` written to the working directory are stable too. `analysis.json` and `graph.cypher` are named once in `codeanalyzer/options` now, so discovery and the writers cannot drift apart.
This was referenced Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #207.
The bug
discover_artifactsreceived onlyproject_dir, so nothing told it where the run writes. With-oinside-i, run N ingested run N−1'sanalysis.jsonas an artifact and embedded it verbatim, squaring the payload each time. The visible symptom was aSIGKILLwhile decoding, which reads as a flaky test suite — the checked-out tree had accumulated 207 GB across five fixtures, including a 97 GBanalysis.jsongrown from a 4 KB fixture.The fix
core.analyzepassesdiscover_artifactsthe paths this run writes (Codeanalyzer._own_output_paths): the output and cache directories, plus the output files inside them. Discovery resolves them and skips any walked file that is, or sits inside, one of them...-laden, and symlinked targets exclude the same tree; a target outside the project excludes nothing.-o <project root>and a--emit neo4jgraph.cypherin the working directory are stable too, at the cost of one file each rather than the whole tree.analysis.jsonandgraph.cypherare now named once incodeanalyzer/options, so discovery and the writers cannot drift apart.Definition of done
-oinside-iproduce the same-sizeanalysis.json(test_cli.py::test_output_dir_inside_input_does_not_grow_across_runs; failed at[2192, 4959]before the fix).-opaths resolve to the same exclusion.test_cli.pykeeps writing into the fixture directory; suite green.du -sk test/fixturesstable across three consecutive full-suite runs: 32456 KB baseline → 68208 → 68212 → 68216 KB. The 4 KB/run wobble is not growth — a per-file manifest across a fourth run shows changes in both directions (flask −30 B, requests +45 B, xarray −3900 B), i.e. run-to-run jitter in the whole-application fixtures.Manual checks, three consecutive runs each:
-oin a nested.outputstable at 55902 B;-oat the project root stable at 2000 B with the siblingnotes.mdstill inventoried;--emit neo4jwith no-oand cwd inside the project stable at 5949 B.Gates, re-run on 7bb7fc1
512 passed, 11 skipped(506 before, +6 new tests)schema_version=2.0.0at L1–L4; each validates againstAnalysis-a 4runs byte-identical (126592 B)Caveats
-oinside-i: that output no longer appears inapplication.artifacts. No schema shape change — no node, edge, or field added or altered;schema_versionstays2.0.0.-oat the project root keeps the whole inventory and skips onlyanalysis.json/graph.cypher, so an unrelated file a user happens to nameanalysis.jsonthere is dropped when it is also the run's own target path.Propagation
The same bug class exists in two siblings; follow-on issues to be filed:
codeanalyzer-typescript—inventoryArtifacts(opts.input, opts, …)walks with name-onlySKIP_DIRSand captures text whole, with no byte cap. Identical exponential blowup for any-onot coincidentally namedout/dist/build.codeanalyzer-java—ArtifactDiscovery.discover(Paths.get(input), …)gets no output path andIGNOREDis name-only.artifactTextMaxBytes = 262144caps each capture, so it grows linearly rather than squared: a wrong inventory, not aSIGKILL.Checked and not affected:
codeanalyzer-iac(only classified IaC templates become candidates); the other analyzers have no artifact layer.