From 499d031fe9cfb4b033c0fad7929bf9b813b42341 Mon Sep 17 00:00:00 2001 From: chengluyu <2239547+chengluyu@users.noreply.github.com> Date: Wed, 22 Jul 2026 19:16:02 +0800 Subject: [PATCH] fix(fs): list files inside untracked directories in git status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git status --porcelain defaults to untracked-files=normal, which collapses untracked directories to their directory entry — a new file inside an untracked dir (e.g. docs/new.md) never surfaced in the Changes panel. Pass --untracked-files=all so entries are reported per file. --- .changeset/git-status-untracked-all.md | 5 +++++ packages/agent-core-v2/src/app/git/gitService.ts | 6 ++++-- .../agent-core-v2/test/app/git/gitService.test.ts | 12 +++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 .changeset/git-status-untracked-all.md diff --git a/.changeset/git-status-untracked-all.md b/.changeset/git-status-untracked-all.md new file mode 100644 index 0000000000..30897c4d43 --- /dev/null +++ b/.changeset/git-status-untracked-all.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/agent-core-v2": patch +--- + +Fix git status collapsing untracked directories: files created inside an untracked directory now appear individually in the Changes panel instead of being hidden behind the directory entry. diff --git a/packages/agent-core-v2/src/app/git/gitService.ts b/packages/agent-core-v2/src/app/git/gitService.ts index 3b38cb25e5..e85de2abbc 100644 --- a/packages/agent-core-v2/src/app/git/gitService.ts +++ b/packages/agent-core-v2/src/app/git/gitService.ts @@ -2,7 +2,9 @@ * `git` domain (L1) — `IGitService` implementation. * * Runs `git status` / `git diff` (and `gh pr view`) against a repository on - * the local disk. Process spawning goes through the App-scope + * the local disk; status passes `--untracked-files=all` so files inside + * untracked directories surface individually instead of collapsing into the + * directory entry. Process spawning goes through the App-scope * `IHostProcessService` from `os/interface`, and the single path-existence * probe in `diff` goes through `IHostFileSystem`; no Node platform API is * imported directly. Bound at App scope — it owns no Session dependency, so @@ -45,7 +47,7 @@ export class GitService implements IGitService { throw this.gitUnavailable(cwd, inside.stderr.trim() || `git rev-parse exit ${inside.exitCode}`); } - const porc = await this.runCommand('git', ['status', '--porcelain=v1', '--branch'], cwd); + const porc = await this.runCommand('git', ['status', '--porcelain=v1', '--branch', '--untracked-files=all'], cwd); if (porc.exitCode !== 0) { throw this.gitUnavailable(cwd, porc.stderr.trim() || `git status exit ${porc.exitCode}`); } diff --git a/packages/agent-core-v2/test/app/git/gitService.test.ts b/packages/agent-core-v2/test/app/git/gitService.test.ts index ca7a569a03..ca28767029 100644 --- a/packages/agent-core-v2/test/app/git/gitService.test.ts +++ b/packages/agent-core-v2/test/app/git/gitService.test.ts @@ -1,5 +1,5 @@ import { execFileSync } from 'node:child_process'; -import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; @@ -92,6 +92,16 @@ describe('GitService', () => { expect(result.entries).toEqual({ 'a.txt': 'modified' }); }); + it('lists files inside untracked directories individually', async () => { + writeFileSync(join(repo, 'a.txt'), 'a\n'); + commitAll('init'); + mkdirSync(join(repo, 'newdir'), { recursive: true }); + writeFileSync(join(repo, 'newdir', 'b.txt'), 'b\n'); + + const result = await service.status(repo); + expect(result.entries).toEqual({ 'newdir/b.txt': 'untracked' }); + }); + it('throws FS_GIT_UNAVAILABLE when not a repo', async () => { const notRepo = mkdtempSync(join(tmpdir(), 'not-repo-')); try {