Skip to content

fix(#1625): exclude agent working directories from git tracking - #1627

Merged
rh-hemartin merged 2 commits into
mainfrom
agent/1625-exclude-agent-work-dirs
Jun 8, 2026
Merged

fix(#1625): exclude agent working directories from git tracking#1627
rh-hemartin merged 2 commits into
mainfrom
agent/1625-exclude-agent-work-dirs

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

The code agent was committing its own working artifacts (e.g. .agentready/) into target repositories, causing review churn and requiring multiple fix iterations to clean up.

Two-layer defense:

  1. Harness-level (internal/cli/run.go): Add known agent working
    directory patterns (.agentready/, .fullsend-workspace/) to
    .git/info/exclude before the agent starts execution. This
    makes git completely ignore these directories — git status
    and git add will not see them.

  2. Post-script (scripts/post-code.sh): Defense-in-depth check
    that detects and warns if agent artifacts somehow appear in
    the commit's changed files, as a safety net if the exclude
    mechanism is bypassed.

The agentWorkingDirExcludes variable is a centralized list that can be extended as new agent working directories are identified.


Closes #1625

Post-script verification

  • Branch is not main/master (agent/1625-exclude-agent-work-dirs)
  • Secret scan passed (gitleaks — 8480e16153a3f16c66b5484bfd4c76349a89933d..HEAD)
  • Pre-commit hooks passed (authoritative run on runner)
  • Tests ran inside sandbox

@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown

Site preview

Preview: https://39d4fccc-site.fullsend-ai.workers.dev

Commit: 691782cb63b2e8f960bba19c865825d76b248aa6

@fullsend-ai-review

fullsend-ai-review Bot commented May 28, 2026

Copy link
Copy Markdown

Review

Findings

Low

  • [command-injection] internal/cli/run.go:1359excludeAgentWorkingDirs constructs a shell command via fmt.Sprintf with payload and repoDir interpolated into a single-quoted string. Currently safe with hardcoded values and consistent with the existing AGENTS.md exclude pattern (line 425), but fragile if a future agentWorkingDirExcludes entry contains a single quote. Consider writing patterns to a temp file or using an exec-style API that avoids shell interpolation.

  • [test-adequacy] internal/cli/run_test.go:821 — Go tests verify the agentWorkingDirExcludes slice contents but do not test the excludeAgentWorkingDirs function itself. The function's shell command generation, error handling, and sandbox interaction remain untested. The shell-level tests in post-code-test.sh provide partial coverage for the detection logic but not the Go harness path.

  • [variable-construction-idiom] internal/cli/run.go:1348 — The loop for _, pattern := range agentWorkingDirExcludes { lines = append(lines, pattern) } copies the slice without transformation. Simplify to payload := strings.Join(agentWorkingDirExcludes, "\n") and remove the lines variable.

  • [test-assertion-style] internal/cli/run_test.go:826 — The manual loop with a found flag to check slice membership can be replaced with assert.Contains(t, agentWorkingDirExcludes, pattern), which is more idiomatic and provides better failure messages.

Info

  • [prior-finding-resolved] internal/scaffold/fullsend-repo/scripts/post-code.sh — Prior high-severity finding is resolved: section 2b now includes git rm --cached, git commit --amend --no-edit, and rebuilds CHANGED_FILES to exclude stripped artifacts. The defense-in-depth layer is functional.
Previous run

Review

Findings

High

  • [correctness] internal/scaffold/fullsend-repo/scripts/post-code.sh:129 — Section 2b ("Strip agent working directories") detects agent artifacts and logs ::warning:: messages, but never actually removes them from the commit. STRIPPED_FILES is set but never consumed — no git rm, git reset HEAD, or filtering of CHANGED_FILES follows. The defense-in-depth layer is inert: if an agent bypasses .git/info/exclude and stages artifacts, they will still be pushed.
    Remediation: After the detection loop, use git rm --cached on each file in STRIPPED_FILES and amend the commit (or filter CHANGED_FILES to exclude them before the push step). The test helper strip_agent_artifacts in post-code-test.sh has the same gap — it validates detection but not removal.

Low

  • [security] internal/cli/run.go:1359excludeAgentWorkingDirs constructs a shell command via fmt.Sprintf with both payload and repoDir interpolated into a single-quoted string. With the current hardcoded values this is safe, and the pattern is consistent with existing code (line 369), but it is fragile: a future agentWorkingDirExcludes entry containing a single quote would break the shell command or inject. Consider writing the patterns to a temp file and appending via cat, or escaping the payload.

  • [correctness] internal/cli/run_test.go:821 — Go tests verify the agentWorkingDirExcludes slice contents but do not test the excludeAgentWorkingDirs function itself. The function's shell command generation, error handling, and interaction with the sandbox are untested. The shell-level tests in post-code-test.sh provide partial coverage for the detection logic but not the Go harness path.

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

See the review comment for full details.

echo "Changed files:"
echo "${CHANGED_FILES}" | sed 's/^/ /'

# ---------------------------------------------------------------------------

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[high] correctness

Section 2b ("Strip agent working directories") detects agent artifacts and logs warnings, but never actually removes them from the commit. STRIPPED_FILES is set but never consumed — no git rm, git reset HEAD, or filtering of CHANGED_FILES follows. The defense-in-depth layer is inert.

Suggested fix: After the detection loop, use git rm --cached on each file in STRIPPED_FILES and amend the commit, or filter CHANGED_FILES to exclude them before the push step.

Comment thread internal/cli/run.go
}
if len(lines) == 0 {
return nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] security

excludeAgentWorkingDirs constructs a shell command via fmt.Sprintf with payload and repoDir interpolated into a single-quoted string. Safe with current hardcoded values and consistent with existing patterns, but fragile if a future agentWorkingDirExcludes entry contains a single quote.

Suggested fix: Consider writing patterns to a temp file and appending via cat, or escaping the payload.

Comment thread internal/cli/run_test.go
assert.NoError(t, validateLinuxBinary(binPath), "downloaded binary should be a valid Linux/amd64 ELF")
}

func TestAgentWorkingDirExcludes_ContainsKnownPatterns(t *testing.T) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] correctness

Go tests verify the agentWorkingDirExcludes slice contents but do not test the excludeAgentWorkingDirs function itself. Shell command generation, error handling, and sandbox interaction are untested.

Suggested fix: Add a unit test that exercises excludeAgentWorkingDirs with a mock sandbox, verifying the generated command and error paths.

@rh-hemartin

Copy link
Copy Markdown
Member

/fs-fix Resolve the conflicts

@rh-hemartin rh-hemartin self-assigned this Jun 1, 2026
@rh-hemartin

Copy link
Copy Markdown
Member

/fs-fix

fullsend-ai-coder Bot pushed a commit that referenced this pull request Jun 4, 2026
Section 2b detected agent working directory artifacts but never removed
them — STRIPPED_FILES was populated but not acted upon. Now uses
git rm --cached to unstage artifacts and amends the commit, then
rebuilds CHANGED_FILES so downstream steps (secret scan, pre-commit)
operate only on legitimate files.

Addresses review feedback on #1627

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: fullsend-fix <fullsend-code@users.noreply.github.com>
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 1 (human-triggered)

Fixed the HIGH finding: post-code.sh section 2b now actually removes agent artifacts via git rm --cached and amends the commit, instead of just logging warnings. Disagreed with 2 LOW findings as out of scope for this bug-fix PR (shell injection risk with hardcoded values, and missing Go unit test for sandbox-dependent function).

Fixed (1):

  1. post-code.sh section 2b detects but never removes agent artifacts (internal/scaffold/fullsend-repo/scripts/post-code.sh): Added git rm --cached and commit --amend to actually strip detected agent artifacts from the commit, then rebuild CHANGED_FILES excluding stripped files so downstream steps (secret scan, pre-commit) operate only on legitimate files. Also handles edge case where all changed files were artifacts.

Disagreed (2):

  1. Shell injection risk in excludeAgentWorkingDirs via fmt.Sprintf: The values interpolated into the shell command are hardcoded string constants in agentWorkingDirExcludes, not user input. The pattern matches existing code (line 369). Refactoring to use temp-file-based appending would add complexity disproportionate to the risk for this bug-fix PR. Worth tracking as a future hardening item but out of scope here.
  2. Go tests do not cover excludeAgentWorkingDirs function: Testing excludeAgentWorkingDirs requires mocking the sandbox.Exec call, which is a larger test infrastructure change out of scope for this bug-fix PR. The shell-level tests in post-code-test.sh cover the detection logic. Adding unit test coverage for the Go function is a valid follow-up but not a blocker.

Tests: passed

Updated by fullsend fix agent

Comment thread internal/cli/run.go
}
if len(lines) == 0 {
return nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] command-injection

excludeAgentWorkingDirs constructs a shell command via fmt.Sprintf with payload and repoDir interpolated into a single-quoted string. Currently safe with hardcoded values and consistent with the existing AGENTS.md exclude pattern (line 425), but fragile if a future agentWorkingDirExcludes entry contains a single quote.

Suggested fix: Write patterns to a temp file and append via cat, or use an exec-style API that avoids shell interpolation.

Comment thread internal/cli/run_test.go
assert.NoError(t, validateLinuxBinary(binPath), "downloaded binary should be a valid Linux/amd64 ELF")
}

func TestAgentWorkingDirExcludes_ContainsKnownPatterns(t *testing.T) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] test-adequacy

Go tests verify the agentWorkingDirExcludes slice contents but do not test the excludeAgentWorkingDirs function itself. The function shell command generation, error handling, and sandbox interaction remain untested.

Suggested fix: Add a unit test for excludeAgentWorkingDirs that mocks sandbox.Exec and verifies the generated command string.

Comment thread internal/cli/run.go
@@ -1331,6 +1347,25 @@ func relOrAbs(base, path string) string {
return rel
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] variable-construction-idiom

The loop copies agentWorkingDirExcludes into a new lines slice without transformation. Simplify to payload := strings.Join(agentWorkingDirExcludes, newline) and remove the lines variable.

Comment thread internal/cli/run_test.go
expected := []string{".agentready/", ".fullsend-workspace/"}
for _, pattern := range expected {
found := false
for _, exclude := range agentWorkingDirExcludes {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] test-assertion-style

Manual loop with found flag to check slice membership can be replaced with assert.Contains(t, agentWorkingDirExcludes, pattern) which is more idiomatic.

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Jun 4, 2026
fullsend-code and others added 2 commits June 8, 2026 11:30
The code agent was committing its own working artifacts (e.g.
.agentready/) into target repositories, causing review churn
and requiring multiple fix iterations to clean up.

Two-layer defense:

1. Harness-level (internal/cli/run.go): Add known agent working
   directory patterns (.agentready/, .fullsend-workspace/) to
   .git/info/exclude before the agent starts execution. This
   makes git completely ignore these directories — git status
   and git add will not see them.

2. Post-script (scripts/post-code.sh): Defense-in-depth check
   that detects and warns if agent artifacts somehow appear in
   the commit's changed files, as a safety net if the exclude
   mechanism is bypassed.

The agentWorkingDirExcludes variable is a centralized list that
can be extended as new agent working directories are identified.

Closes #1625
Section 2b detected agent working directory artifacts but never removed
them — STRIPPED_FILES was populated but not acted upon. Now uses
git rm --cached to unstage artifacts and amends the commit, then
rebuilds CHANGED_FILES so downstream steps (secret scan, pre-commit)
operate only on legitimate files.

Addresses review feedback on #1627

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: fullsend-fix <fullsend-code@users.noreply.github.com>
@rh-hemartin
rh-hemartin force-pushed the agent/1625-exclude-agent-work-dirs branch from 6c9b74d to 691782c Compare June 8, 2026 09:30
@rh-hemartin
rh-hemartin enabled auto-merge June 8, 2026 09:32
@rh-hemartin
rh-hemartin added this pull request to the merge queue Jun 8, 2026
Merged via the queue into main with commit 20ca6d5 Jun 8, 2026
7 of 8 checks passed
@rh-hemartin
rh-hemartin deleted the agent/1625-exclude-agent-work-dirs branch June 8, 2026 09:36
@fullsend-ai-review

Copy link
Copy Markdown

Review skipped — this PR is already merged.

The /fs-review command only reviews open pull requests.

Posted by fullsend post-review check

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #1627 — Exclude agent working directories from git tracking

Timeline: Issue #1625 → code agent PR #1627 (05-28) → review CHANGES_REQUESTED with 1 HIGH + 2 LOW (05-28) → human approval + /fs-fix Resolve the conflicts (06-01) → second /fs-fix (06-04) → fix agent commit (06-04) → re-review APPROVED (06-04) → merged (06-08). 11 days end-to-end.

What went well:

  • The review agent correctly identified a real HIGH-severity bug: post-code.sh populated a STRIPPED_FILES variable but never consumed it, making the defense-in-depth layer entirely inert. This was a genuine correctness catch.
  • The fix agent addressed the HIGH finding cleanly, adding git rm --cached and commit amendment.
  • The triage agent's analysis was thorough and well-scoped.

Friction points:

  • Two /fs-fix invocations required — the first (06-01) was for merge conflicts, the second (06-04) was for review findings, with a 3-day gap between them. This is partially addressed by #1742 (fix agent should incorporate prior review comments).
  • Review re-raised declined LOW findings — after the fix agent explicitly declined 2 LOW findings with reasoning, the re-review reiterated them verbatim. Well-covered by existing issues: #1013, #1285, #1552.
  • Code agent partially implemented triage spec — the triage recommended the post-script should "reject commits containing files under excluded directories," but the code agent only wrote detection without removal. See proposal below.

Skipped proposals (already tracked):

Proposals filed

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

Labels

ready-for-merge All reviewers approved — ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Code agent should exclude its own working directories from commits

1 participant