autosetup: pick the build system and the artifact directory from artifacts on disk - #169
Draft
shellygr wants to merge 2 commits into
Draft
autosetup: pick the build system and the artifact directory from artifacts on disk#169shellygr wants to merge 2 commits into
shellygr wants to merge 2 commits into
Conversation
A project shipping both a foundry.toml and a Hardhat config gave no say to which one built the tree: detection always answered Foundry, so a Hardhat project whose foundry.toml only governs a forge test harness had its empty out/ read and yielded no contracts. Detection now breaks that tie on the artifacts present, with Foundry keeping it whenever it has artifacts of its own and when neither side has any. The extractor had the same shape of problem one level down: it read the build system's default artifact directory whenever that directory existed, so a project configuring out = "out/foundry" had its bare out/ read — a directory that exists only as the parent of the real one. The default now counts only while it holds artifacts, and the config's own answer decides otherwise. Both rules ask the same question, "does this directory hold artifacts", which each manager answers from its own layout, and the per-build-system artifact directory helpers in project_dir are now shared with the detector instead of copied. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Hardhat's evidence test accepted a bare `artifacts/contracts` or `artifacts/build-info` directory, which a configured-but-never-run build also leaves behind, while Foundry and Truffle both require a file. That asymmetry could hand the tie to Hardhat for a tree only Foundry had built. The unreadable-artifacts error now names the directory the config declares rather than the build system's default, and distinguishes a path that is absent from one that is present but not a directory. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Draft — the tie-break half needs a paired builder change before it earns its keep; see What this
actually fixes today.
Two defects, both surfacing as "no contracts"
A. The Foundry/Hardhat tie is broken by config order, not by evidence. When a directory holds both
a
foundry.tomland a Hardhat config, detection always answered Foundry and loggedBoth Foundry and Hardhat detected, defaulting to Foundry. If Hardhat is what built the tree, itsoutput is under
artifacts/whileout/is empty or absent, so the extractor reads nothing and therun dies with
No project-local logic contracts found in FoundryManager build output— 12 contractrows across 6 projects in the last corpus sweep. Detection now prefers the build system whose artifact
directory actually holds artifacts. Foundry keeps the tie when it has artifacts of its own and when
neither side has any (an unbuilt tree offers nothing to rank by), and
--build-systemstill winsoutright.
B. A configured artifact directory was ignored when the default name existed as a parent. The
extractor tested
out/for existence, so a project without = "out/foundry"found the (empty)parent and reported that the build produced nothing. It now takes the default only while it holds
artifacts, else the directory the config names.
Evidence is one predicate per build system —
holds_artifacts— and all of it requires a file, nota directory: a
*.sol/dir for Foundry, a*.jsonundercontracts/orbuild-info/for Hardhat, aflat
*.jsonfor Truffle. A configured-but-never-run build leaves the directories behind, sodirectory existence is not evidence that a build happened.
What this actually fixes today
Measured in the fleet image against the real clones:
reconcopy-mitosis:rc=1 No project-local logic contracts→rc=0, 39 contracts found inout/foundry).builder only ever runs
forge buildthere, so Hardhat never gets a chance to leave any. A is theprecondition for fixing that on the builder side; on its own it changes no corpus project's answer
(measured across all 314 clones: 87 hold both configs, 0 flip).
sales-compound-multiplier) fails for an unrelated reason — itsnode_modules/isempty, so
forge buildproduced a single interface with no bytecode. No detection change canrecover that.
Known limits, deliberately not fixed here
outfrom[profile.default], so a tree built under a non-defaultFOUNDRY_PROFILEwith a differentoutreads as having no artifacts. Documented in the docstring.foundry.tomlgoverns a forge test harness looks like Foundry the momentthat harness is compiled. Also documented.
find_build_config_dirstill ranks Foundry first for a directory holding both configs, so it candisagree with
detect()on a monorepo package that only Hardhat built. Worth closing, separately.Tests
tests/test_build_system_choice.py— 15 cases: every single-build-system path unchanged (built andunbuilt), both-configs-with-Foundry-artifacts unchanged, both-unbuilt unchanged, the tie-break itself,
empty artifact directories rejected on both sides, evidence read from a configured
out,--build-systemstill authoritative, plus the extractor's resolution and error-message cases.pytest -m "not expensive": 759 passed, 9 skipped.pyright: 0 errors.