Skip to content

fix(autobuilder): Drop self-shadowing dependencies, resolve version conflicts - #306

Draft
misonijnik wants to merge 3 commits into
mainfrom
misonijnik/autobuilder-dependency-hygiene
Draft

fix(autobuilder): Drop self-shadowing dependencies, resolve version conflicts#306
misonijnik wants to merge 3 commits into
mainfrom
misonijnik/autobuilder-dependency-hygiene

Conversation

@misonijnik

Copy link
Copy Markdown
Member

No description provided.

misonijnik and others added 3 commits July 22, 2026 16:49
…onflicts

Two ways the project model handed the analyzer several copies of one
class and
left the choice to classpath lookup order.

Self-shadowing dependencies. A project routinely depends on an artifact
that
repackages its own modules — a client bundle, a shaded jar, an earlier
release of
the module. Conductor declares both `project(':conductor-common')` and
`org.conductoross:conductor-client`, and the latter ships 67 of common's
classes.
When lookup lands on the dependency copy, project code becomes
un-analyzable
library code and taint dies at every call into it. Drop any dependency
that ships
a class the project itself compiles: the project's own output already
provides it.
On conductor this removes both conductor-client jars, and no project
class
references any of the 468 classes that live only in them.

Version conflicts. Dependencies are collected from the dependency graph
across
every module and configuration, so an artifact survives at each version
any module
resolved — 225 artifacts at 2..9 versions on conductor, 428 redundant
jars holding
184918 classes. Keep one version per group:artifact, highest wins, the
way the
build tool resolves it.

Conductor model: 1178 -> 756 dependency jars, 1.8G -> 1.5G, with an
identical
finding set (14 taint + 2 syntactic). Note this is a correctness and
model-size
change, not a performance one: a single-rule probe moved 1020s/18.0GB ->
965s/17.9GB, i.e. noise. Analysis cost on that project is dominated by
container
access-path growth in the dataflow engine, not by model size.

Verified: autobuilder unit tests; rule-tests green on a model rebuilt
with this
autobuilder (falsePositive=falseNegative=skipped=0, success=338).
…a jar

Version-conflict resolution ran before jar resolution, so an artifact
whose
highest version has no artifact in the local caches lost its lower,
resolvable
versions and disappeared from the model entirely.

The dependency graph is resolved from metadata alone: a version no
configuration
ever compiled against leaves only a POM behind. Conductor's graph
carries
jackson-core at 2.14.2, 2.15.3, 2.17.0, 2.17.3 and 2.18.0, and only
2.18.0 has
no jar — the model lost jackson-core outright, which surfaced on CI as
"package com.fasterxml.jackson.core does not exist" while compiling the
project's dataflow approximations against the project dependencies.

Let only versions that resolve take part in the conflict resolution: the
highest
resolvable version wins, and an artifact drops out only when no version
resolves.
Replayed over conductor's dependency graph, this recovers 10 artifacts
(jackson-core, five other jackson modules, jersey-common, lz4-java,
reactor-test,
woodstox-core) and loses none: 758 -> 768 jars.

Verified: autobuilder unit tests, including the new fallback cases.
Version-conflict resolution kept the single highest version of every
group:artifact across the whole build. A multi-module build routinely resolves
several majors of one artifact, and those are not versions of one thing — they
are incompatible APIs the build deliberately keeps apart.

Conductor compiles os-persistence-v2 against opensearch-rest-client 2.18.0 and
os-persistence-v3 against 3.5.0, shading them so both can coexist.
RestClientBuilder's callbacks take Apache HttpClient 4 types (org.apache.http)
in 2.x and HttpClient 5 types (org.apache.hc.client5) in 3.x. Collapsing to
3.5.0 left every module on the 2.x line compiled against classes the model no
longer had, which surfaced on CI as "incompatible types:
org.apache.http.impl.nio.client.HttpAsyncClientBuilder cannot be converted to
org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder" while compiling
the project's dataflow approximations.

Collapse per major-version line instead: drift inside a line is the same API at
different patch levels, so the highest still stands in for all of them, while
distinct lines both reach the model. A version with no numeric major makes no
compatibility claim and is never collapsed into another.

Conductor model: 660 -> 736 dependency jars, both opensearch-rest-client jars
retained, still 235 fewer than the 971 an unresolved model carries. Findings on
that project are a superset of the pre-dedup model's: 7 vs 6, gaining an SSRF in
HttpTask.java:173 and losing none.

Verified: autobuilder unit tests, including the new major-line cases; conductor
scanned end to end under the regression bench's CI settings (JDK 21, 8G, 1200s)
to completion in 232s. Rule-tests were not re-run: this change only keeps more
jars than the model they were last verified against.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@misonijnik
misonijnik marked this pull request as draft July 23, 2026 16:15
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