Skip to content

feat(extensions): diff untracked files in project.gitDiff - #468

Merged
almogdepaz merged 8 commits into
mainfrom
feat/extension-untracked-diff
Oct 28, 2026
Merged

almogdepaz merged 8 commits into
mainfrom
feat/extension-untracked-diff

Conversation

@almogdepaz

@almogdepaz almogdepaz commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

context.project.gitDiff() now also returns untracked: every untracked, non-ignored regular file in the repository diffed as a new file (git diff --no-index -- /dev/null <path>), next to the existing staged and unstaged sections. The field is optional in the contract, the control-api schema and the SDK types, so existing callers and older extensions are unaffected.

Bounds: at most 32 untracked files of up to 128 KiB each, and the serialized untracked section is capped at 48 KiB (cut at a line boundary) so the full envelope (96 + 96 + 48 KiB) still fits EXTENSION_PEER_LIMITS.project. Symlinks, directories (including nested repositories), unreadable or oversized files, and files past the 32nd are skipped; any cut or skip sets the existing truncated flag. Untracked listing uses git ls-files --others --exclude-standard -z --full-name -- :/, the top level comes from rev-parse --show-cdup (validated as (../)*), and the physical project path (realpath) is used for the lstat/access checks so a symlinked project path checks the same files Git reads. The per-file diff runs under the same hardened fixed argv as the tracked diffs and shares their 2 s deadline.

Commits: reader (8d1f882), schema + SDK types (8f81af8), docs (accc0ad), route test (2e927d8), physical-path fix (17770a2), docs/comment follow-ups (d5a51a9, 0b20277), regenerated embedded public assets for the SDK change (d31a8d2).

Motivation and scope

The Changes context view (wolfpack-extension-changes) showed status rows for untracked files but could not open a diff for them: git diff / git diff --cached never include untracked content, and extensions have no git or filesystem access of their own by design. Adding the section host-side keeps git execution host-owned and read-only instead of exposing paths or arguments to extensions. wolfpack-extension-changes@0.1.1 (published) renders this section when present and shows "This host does not diff untracked files." on hosts without it.

Out of scope: a separate truncation flag for the untracked section (the single truncated flag is kept), and any change to the staged/unstaged caps or argv.

Validation

  • bun test tests/unit/project-git-diff.test.ts: 12 pass, 0 fail (covers untracked diffs across subdirectories, ignore rules, nested repositories, symlinks, count/size caps, a project reached through a symlink, a file that vanishes between listing and diffing, and the serialized-size bound).
  • tests/integration/extension-routes.test.ts and tests/integration/extension-peer-proxy.test.ts updated for the new field (worst-case 96 + 96 + 48 KiB envelope accepted by the peer limit).
  • bun run scripts/gen-assets.ts regenerated src/public-assets.ts with the same hashes CI computes (app.bundle.js 4edf9ebb94a216b5, ASSET_VERSION 9484a71fdf3031dc); the first CI run failed only on that stale generated file.
  • bun run typecheck, bun run check:bundle-budgets (app.bundle.js gzip 104992 of 105500, +24 B), bun run check:context: exit 0.
  • Full bun test on this machine: 4 failures only from the missing local broker/target/release/wolfpack-broker binary, plus timing-sensitive tests that pass alone; extensions-frontend.e2e.ts passed, other e2e failures were environmental (missing webkit, broker binary).
  • Consumer checks from the extensions repo against this branch at d5a51a9: strict APIv1 host-types, host-compat and isolated archive install gates passed; 13 Playwright UI tests pass for the extension.
  • Independent read-only review (two rounds): no blockers. The reviewer probed git diff --no-index on symlinks: links to regular/outside/dangling targets are emitted as new file mode 120000 without following; only a link to a named pipe is read through and would block, which is why only regular files are diffed.
  • Not tested: a very large untracked tree. ls-files --others reads every file in untracked, non-ignored directories, so such a tree can hit the shared 2 s deadline and make gitDiff unavailable (documented).

User, security, and compatibility impact

  • User: context views can show new-file diffs for untracked files; truncated now also reports skipped untracked entries, so a truncation notice can appear while staged/unstaged diffs are complete.
  • Security: no caller-supplied paths or arguments; same fixed argv, env stripping, disabled hooks/pager/fsmonitor/filters and deadline as tracked diffs; .gitignore is honored; symlinks and nested repositories are never read; the peer proxy re-validates untracked through the schema (maxLength 49152).
  • Compatibility: additive optional field; parseProjectGitDiff accepts responses without it; no change for callers that ignore it.

Documentation

  • docs/extensions.md: untracked section, caps, skip rules, truncated semantics, large-tree timeout risk.
  • docs/generated/control-api.schema.json, sdk/types/*.d.ts, src/extensions/sdk.ts: regenerated/updated for the optional field and MAX_GIT_DIFF_UNTRACKED_BYTES.

Checklist

  • This change is focused and excludes unrelated refactors.
  • Public text, screenshots, logs, and fixtures contain no secrets or private machine, network, project, path, or session data.

@netlify

netlify Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for lustrous-tiramisu-75059c ready!

Name Link
🔨 Latest commit d31a8d2
🔍 Latest deploy log https://app.netlify.com/projects/lustrous-tiramisu-75059c/deploys/6ae11a30b19a3b0d22d8b6c7
😎 Deploy Preview https://deploy-preview-468--lustrous-tiramisu-75059c.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@almogdepaz
almogdepaz merged commit 5f0d2c1 into main Oct 28, 2026
6 checks passed
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.

1 participant