Skip to content

Exclude the Solidity dependency root from untracked workspace-patch capture - #834

Merged
aviggiano merged 1 commit into
mainfrom
fix/workspace-patch-swallows-solidity-dependency-root
Aug 25, 2026
Merged

aviggiano merged 1 commit into
mainfrom
fix/workspace-patch-swallows-solidity-dependency-root

Conversation

@aviggiano

@aviggiano aviggiano commented Aug 25, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #833.

Change

const WORKSPACE_DEPENDENCY_ROOTS = ["lib"] as const;

Applied to the untracked listing only, alongside the existing generated-root exclusions.

node_modules was already excluded as a runtime root. lib — the Foundry and dapptools convention for Solidity dependencies — was not, in a harness that targets Solidity.

Why it bites

Setup prompts tell the agent that dependencies may be absent from the worktree and to install them there. An agent that vendors Solidity dependencies under lib/<name> had the whole tree captured — 505 files, ~4.9 MB — into one workspace.patch. It happened twice in one campaign under two different directory names (lib/vendored, then lib/vendor), so path-specific exclusion is not a fix.

The damage is not the size. Third-party sources legitimately contain credential-shaped text — forge-std's StdChains.sol ships a placeholder Infura RPC URL — so the patch failed the artifact secret gate, which is fail-closed and does not rewrite bytes.

And it failed quietly: verify:setup-foundry is continueOnFail, so the run kept going and kept reporting healthy node counts, while node:base-test-setup — which depends on that verifier non-optionally — never ran. The Foundry test-harness foundation was silently absent from a run that would have reported success.

Untracked-only is deliberate

This follows the reasoning already documented in stageableWorkspacePaths: staging runs after read-tree <baseline>, so excluding a tracked path leaves the baseline blob in the index, the authored edit never reaches the patch, and applyWorkspacePatch verifies both trees under the same exclusions — every check passes and the downstream node silently sees stale content.

lib normally holds tracked submodule gitlinks. Vendored copies are untracked by definition, so untracked-only catches exactly the problem and nothing else.

Verification

Two new tests, one per direction:

  • excludes a vendored Solidity dependency tree but keeps tracked lib edits — untracked lib/vendor/** is gone from the manifest and the patch, while an authored test/foundry file is still captured
  • still captures an edit to a tracked file under lib — guards against exactly the silent data loss above

55/55 workspace-handoff, 31/31 workspace-patch replay and supersede, lint and format:check clean.

Related

Third in a series where a rule calibrated for one kind of text meets another: #819/#820 (secret gate heuristics vs. audit prose) and #822/#823 (ak-/as- vendor pattern vs. kebab-case English). This one is upstream of both — the artifact should never have contained third-party source in the first place.

Greptile Summary

The PR excludes untracked Solidity dependency trees beneath lib/ from workspace-patch capture while preserving tracked edits there.

  • Adds lib to the dependency-root exclusions used by the untracked Git listing.
  • Adds coverage for omitted vendored dependencies and retained tracked dependency edits.
  • The blanket exclusion conflicts with setup prompts that deliberately make vendored dependencies patch-visible for downstream nodes.

Confidence Score: 4/5

The PR should not merge until vendored dependencies required to remain patch-visible can reach downstream workspaces without reintroducing oversized third-party captures.

The new blanket untracked lib/** filter silently omits dependencies that setup agents are explicitly instructed to vendor for downstream use, while patch and tree validation still succeed.

Files Needing Attention: packages/runtime/src/workspace-handoff.ts, packages/runtime/test/workspace-handoff.test.ts

Important Files Changed

Filename Overview
packages/runtime/src/workspace-handoff.ts Adds an untracked-only lib/** exclusion that preserves tracked edits but silently drops prompt-required, patch-visible vendored dependencies.
packages/runtime/test/workspace-handoff.test.ts Adds focused tests for the intended exclusion and tracked-edit preservation, but does not cover the existing patch-visible vendoring contract.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Setup agent vendors forge-std under lib] --> B[Untracked ls-files excludes lib/**]
    B --> C[Dependency omitted from patch and manifest]
    C --> D[Patch validation succeeds]
    D --> E[Downstream workspace lacks dependency]
    E --> F[Foundry import or compilation fails]
Loading

Fix all with Greploop Fix All in Claude Code

Prompt To Fix All With AI
### Issue 1
packages/runtime/src/workspace-handoff.ts:511
**Patch-visible dependencies are discarded**

When a setup agent follows the repository prompts and vendors a missing dependency such as `forge-std` as ordinary files under `lib/`, this exclusion removes those files before staging and overflow recovery, so the validated patch silently leaves downstream workspaces without the dependency and their Foundry imports or compilation fail.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "fix(runtime): exclude the Solidity depen..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

…ch capture

Closes #833.

stageWorkspaceTree excludes node_modules but not lib, the Foundry convention for
Solidity dependencies -- the dependency root that actually matters here. Setup
prompts tell the agent dependencies may be absent and to install them in the
worktree, so an agent that vendors them under lib/<name> had the whole tree
captured: 505 files and 4.9 MB of third-party source in one workspace patch,
twice in one campaign under two different directory names.

Size was not the real problem. Third-party sources carry credential-shaped text
-- forge-std's StdChains.sol ships a placeholder Infura URL -- so the patch
failed the fail-closed artifact secret gate and killed the node. Quietly:
verify:setup-foundry is continueOnFail, so the run continued reporting healthy
counts while node:base-test-setup, which depends on it non-optionally, never
ran.

Untracked-only, for the reason stageableWorkspacePaths already documents:
staging runs after read-tree <baseline>, so excluding a tracked path leaves the
baseline blob in the index and the authored edit vanishes with a manifest that
still validates. lib normally holds tracked submodule gitlinks; vendored copies
are untracked by definition.

Verified both directions -- untracked lib/vendor/** excluded while an authored
test/foundry file is kept, and an edit to a tracked lib/ file still captured.
55/55 workspace-handoff, 31/31 replay and supersede.
// case-variant and slash-less generated paths are handled by measured overflow recovery instead.
...WORKSPACE_GENERATED_ROOTS.map((root) => `:(exclude)${root}/**`)
...WORKSPACE_GENERATED_ROOTS.map((root) => `:(exclude)${root}/**`),
...WORKSPACE_DEPENDENCY_ROOTS.map((root) => `:(exclude)${root}/**`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Patch-visible dependencies are discarded

When a setup agent follows the repository prompts and vendors a missing dependency such as forge-std as ordinary files under lib/, this exclusion removes those files before staging and overflow recovery, so the validated patch silently leaves downstream workspaces without the dependency and their Foundry imports or compilation fail.

Knowledge Base Used:

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/runtime/src/workspace-handoff.ts
Line: 511

Comment:
**Patch-visible dependencies are discarded**

When a setup agent follows the repository prompts and vendors a missing dependency such as `forge-std` as ordinary files under `lib/`, this exclusion removes those files before staging and overflow recovery, so the validated patch silently leaves downstream workspaces without the dependency and their Foundry imports or compilation fail.

**Knowledge Base Used:**
- [Match generated corpus directories by safe prefixes](https://app.greptile.com/monad-foudnation/-/custom-context/knowledge-base/monad-developers/ultrafuzz/-/reverts/incident-mitigation_375-20260807-generated-corpus-prefix-0088f80.md)
- [Exclude generated fuzzing output from workspace patches](https://app.greptile.com/monad-foudnation/-/custom-context/knowledge-base/monad-developers/ultrafuzz/-/reverts/incident-mitigation_305-20260806-generated-corpus-patch-62aaef1.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code

@aviggiano aviggiano left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@aviggiano
aviggiano merged commit a95a759 into main Aug 25, 2026
7 checks passed
@aviggiano
aviggiano deleted the fix/workspace-patch-swallows-solidity-dependency-root branch August 25, 2026 11:07
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.

Workspace patch captures vendored Solidity dependencies: lib/ is not excluded the way node_modules is

1 participant