Skip to content

Setup agents vendor already-present Solidity dependencies, putting megabytes of third-party source into workspace patches #839

Closed

Description

@aviggiano

Summary

Setup agents vendor a second copy of dependencies that are already present in their worktree. Every untracked file is captured into workspace.patch, so the copy becomes megabytes of third-party source in an audit artifact — which then fails the artifact secret gate and kills the node.

This happened on three consecutive runs of one campaign, each time under a different directory name:

lib/vendored      (505 files, 4.9 MB)
lib/vendor        (505 files, 4.9 MB)
lib-vendor        (505 files, 4.9 MB)

Because the name changes every time, path-based exclusion does not fix it — including the lib/ exclusion in #833/#834, which lib-vendor/ sidesteps by being a sibling rather than a child.

The dependencies were already there

This is not a missing-dependency workaround. In the failing worktree:

lib/forge-std/src/Base.sol          <- present and populated
lib-vendor/forge-std/...            <- agent's duplicate copy

The submodules are materialized before the agent runs. It copied them anyway.

Why the agent does it

The worktree-isolation preamble injected ahead of the task prompt says:

Dependencies (node_modules) may be absent here. Install them fresh inside the worktree (e.g. pnpm install at the worktree root)

That is JavaScript-specific guidance, but it is the only statement about dependencies the agent sees, and nothing tells it that lib/ is already populated. A Solidity agent generalises "dependencies may be absent, install them here" to its own ecosystem and defensively vendors lib/.

Why it is expensive

verify:setup-foundry is continueOnFail. The run does not stop — it keeps reporting healthy node counts while node:base-test-setup, which depends on that verifier non-optionally, never runs. The Foundry test-harness foundation is silently absent from a run that finishes "successfully".

The existing size ceiling does not catch it either: MAX_PATCH_BYTES is 16 MB and these patches are ~5 MB, so the measured-overflow exclusion path never triggers.

Fix in this PR

State it in the setup prompt: lib/ is already materialized, the preamble's "dependencies may be absent" note describes JavaScript packages, and no dependency tree may be copied or vendored under any name — with the reason attached, so the instruction is not arbitrary.

Recommended follow-up (not in this PR)

A prompt is advisory to a model, and this behaviour has recurred three times. A robust guard belongs in capture: treat a single untracked top-level directory contributing an unusually large number of files or bytes as a bulk contributor and exclude it, recording it in the manifest the way git-diff-overflow exclusions already are. That is name-agnostic and reuses machinery that exists, but it is a policy decision about capture semantics rather than a bug fix, so it is proposed here rather than assumed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions