diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b577d9f02a..ee02962a3e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -704,22 +704,88 @@ jobs:
         # The Windows-only bash resolver lives in buzz-dev-mcp; its unit tests
         # only gate if this crate is tested ON Windows.
         run: cargo test -p buzz-dev-mcp --target $env:TARGET
-      # The bundled-bash staging (PortableGit download, SFX extract, mingw64 drop)
-      # runs only in release.yml on tag — so without this step the agent's only
-      # Windows transport would ship UNEXERCISED until a tagged release hits users.
-      # Stage the tree and spawn the staged bash on a real coreutils pipeline: this
-      # gates the SFX `-o` POSIX-path extraction, that bash.exe still spawns after
-      # mingw64/ is dropped, and that the lazily-loaded MSYS DLL closure (msys-2.0.dll,
-      # coreutils) survives — the exact behaviors unconfirmable off a non-Windows host.
-      - name: Smoke-test bundled bash staging
+      # The bundled-bash staging (PortableGit download + SFX extract of the WHOLE
+      # tree, including mingw64/) runs only in release.yml on tag — so without this
+      # step the agent's only Windows transport would ship UNEXERCISED until a
+      # tagged release hits users. Stage the tree and spawn the LAUNCHER bash
+      # (bin/bash.exe, the entry the resolver now uses) to prove all of: the SFX
+      # `-o` POSIX-path extraction works; the launcher spawns and sets up
+      # MSYSTEM/PATH; the lazily-loaded MSYS DLL closure survives; and — the whole
+      # point of bundling the full toolchain — git/jq/curl resolve from the bundled
+      # mingw64/bin and git is functional (a real commit round-trips). The launcher
+      # prepending mingw64/bin to PATH under `-c` is the load-bearing behavior that
+      # only a real Windows host can confirm; this gate is where it gets proven.
+      # (End-to-end nostr-SIGNED commits compose build_git_env's GIT_CONFIG_* with
+      # the git-sign-nostr helper — covered by buzz-dev-mcp unit tests + a bare-host
+      # check, not here, since this job stages only empty sidecar placeholders.)
+      - name: Smoke-test bundled bash + git toolchain staging
         shell: bash
         run: |
           set -euo pipefail
           stage_dir="$RUNNER_TEMP/git-bash"
           scripts/stage-windows-bash.sh "$stage_dir"
-          out=$("$stage_dir/usr/bin/bash.exe" -c 'echo hello | tr a-z A-Z')
+          launcher="$stage_dir/bin/bash.exe"
+          [[ -f "$launcher" ]] || { echo "launcher bash missing: $launcher" >&2; exit 1; }
+
+          # Faithfulness to the agent: shell.rs spawns the launcher with PATH set
+          # wholesale to the shim PATH (shim tempdir + the MCP process's inherited
+          # PATH). We strip PATH down to just the Windows system dir before
+          # spawning — stricter than a bare host (ambient PATH stripped to force
+          # resolution through the launcher). This stops the runner's ambient
+          # git/jq from masking the launcher's own mingw64/bin prepend, so anything
+          # that resolves had to come from the launcher itself. The fidelity gap is
+          # benign: the real shim tempdir only ever holds rg/tree/buzz and the two
+          # nostr helpers, never git/jq/curl, so a richer real PATH cannot shadow
+          # mingw64/bin for these three tools.
+          win_root="${SYSTEMROOT:-${SystemRoot:-C:\\Windows}}"
+          bare_path="$win_root\\System32;$win_root"
+
+          # Coreutils pipeline through the launcher (the resolver's entry point).
+          out=$(PATH="$bare_path" "$launcher" -c 'echo hello | tr a-z A-Z')
           [[ "$out" == "HELLO" ]] || { echo "staged bash pipeline failed: got '$out'" >&2; exit 1; }
-          echo "staged bash spawned and ran a coreutils pipeline"
+
+          # The full-toolchain payoff: git/jq/curl must resolve from the bundle's
+          # mingw64/bin or usr/bin. Use NON-login `-c` to match the agent's actual
+          # invocation (shell.rs spawns `bash -c`): if the launcher only fixes PATH
+          # under a login shell, `-lc` would pass here while the real agent stays
+          # broken — the exact green-but-broken trap this gate guards.
+          #
+          # Anchor to the ACTUAL staged tree, not a mount-shape: command -v reports
+          # the MSYS mount path (/mingw64/bin/git), so we cygpath -m it back to the
+          # real Windows location and assert it sits under $stage_dir. A bare
+          # `/mingw64/*` shape check would pass for any /mingw64-rooted mount; the
+          # cygpath round-trip proves the tool is literally inside the bundle we
+          # just staged. cygpath ships in the bundle's usr/bin (MSYS2 core, same
+          # tier as the `tr` proven above), so it resolves under the launcher.
+          #
+          # curl is the one tool of the three with a System32 twin
+          # (C:\Windows\System32\curl.exe, on $bare_path) — if a future PortableGit
+          # ever drops curl from mingw64/bin, the launcher would resolve the
+          # System32 twin and this REDs on a non-bug; git/jq have no such twin.
+          stage_m=$("$launcher" -c "cygpath -m '$stage_dir'")
+          for tool in git jq curl; do
+            located=$(PATH="$bare_path" "$launcher" -c "command -v $tool >/dev/null 2>&1 && cygpath -m \"\$(command -v $tool)\"" || true)
+            [[ -n "$located" ]] || { echo "$tool did not resolve in bundled bash" >&2; exit 1; }
+            case "$located" in
+              "$stage_m"/*) ;;
+              *) echo "$tool resolved outside the staged bundle: $located (stage: $stage_m)" >&2; exit 1 ;;
+            esac
+            echo "$tool -> $located"
+          done
+
+          # git is not just present but functional: a real commit round-trips,
+          # again through non-login `-c` with the bare PATH. Single-quoted on
+          # purpose — this script body runs in the launcher's shell, not ours.
+          # shellcheck disable=SC2016
+          PATH="$bare_path" "$launcher" -c '
+            set -euo pipefail
+            repo=$(mktemp -d)
+            cd "$repo"
+            git init -q
+            git -c user.name=ci -c user.email=ci@example.com commit -q --allow-empty -m smoke
+            git log -1 --format=%s | grep -qx smoke
+          ' || { echo "bundled git failed a commit round-trip" >&2; exit 1; }
+          echo "staged launcher bash spawned; git/jq/curl resolve from the bundle; git commit works"
       - name: Check (Tauri crate)
         run: cargo check --manifest-path desktop/src-tauri/Cargo.toml --target $env:TARGET
         env:
diff --git a/crates/buzz-dev-mcp/src/shell.rs b/crates/buzz-dev-mcp/src/shell.rs
index 0b27b160d1..76aec2c77a 100644
--- a/crates/buzz-dev-mcp/src/shell.rs
+++ b/crates/buzz-dev-mcp/src/shell.rs
@@ -314,20 +314,21 @@ pub async fn run(
 ///   2. `desktop/scripts/build-release-config.mjs` — emits the Windows-only
 ///      `bundle.resources` Map `{ "binaries/git-bash": "git-bash" }`, whose TARGET
 ///      (`git-bash`) is what Tauri's NSIS/MSI installer stages next to the exe.
-///   3. this resolver — joins `current_exe().parent()` + `git-bash\usr\bin\bash.exe`.
+///   3. this resolver — joins `current_exe().parent()` + `git-bash\bin\bash.exe`.
 ///
 /// Drift between (2)'s target and this string ships a working bundle but a broken
 /// runtime path. Keep all three in lockstep.
 ///
-/// The bundled constant points at `usr\bin\bash.exe` (the real MSYS2 bash, which
-/// boots from its co-located `msys-2.0.dll` and needs only `usr/`, no `mingw64/`)
-/// — NOT the `bin\bash.exe` launcher shim, which refuses to start without a sibling
-/// `mingw64\bin` marker the bundle deliberately drops. The installed-Git branch
-/// below stays on `bin\bash.exe` on purpose: a real Git-for-Windows install has
-/// `mingw64/`, so its launcher is the correct entry and sets up MSYSTEM/PATH.
-/// Different tree shape -> different correct entry point.
+/// The bundled constant points at `bin\bash.exe` — the git-for-windows launcher,
+/// NOT `usr\bin\bash.exe`. The bundle now ships the WHOLE PortableGit tree
+/// (including `mingw64/`), so it has the sibling `mingw64\bin` the launcher needs:
+/// the launcher is the correct entry because it sets `MSYSTEM=MINGW64` and prepends
+/// `mingw64\bin` to the in-shell PATH, which is what makes `git`/`jq`/`curl` resolve
+/// inside the agent's shell with no Rust-side PATH injection. The installed-Git
+/// branch below uses the SAME `bin\bash.exe` entry for the same reason — same tree
+/// shape, same correct entry point.
 #[cfg(windows)]
-const BUNDLED_BASH_REL: &str = r"git-bash\usr\bin\bash.exe";
+const BUNDLED_BASH_REL: &str = r"git-bash\bin\bash.exe";
 
 /// Resolve a genuine, non-WSL bash to an absolute path so we spawn it directly
 /// instead of letting `Command::new("bash")` re-enter PATH search — on Windows
diff --git a/desktop/scripts/build-release-config.mjs b/desktop/scripts/build-release-config.mjs
index 1eea02ad05..71ea2c7946 100644
--- a/desktop/scripts/build-release-config.mjs
+++ b/desktop/scripts/build-release-config.mjs
@@ -52,16 +52,18 @@ const releaseConfig = {
   },
 };
 
-// Windows-only: bundle the PortableGit bash runtime as a resource so the MCP shell
-// tool always has a genuine, non-WSL bash to spawn on a bare host (the app must
-// be self-contained — we cannot assume Git for Windows is installed).
+// Windows-only: bundle the full PortableGit toolchain (bash runtime + git +
+// curl/coreutils in mingw64/, plus a vendored standalone jq.exe) as a resource so
+// the MCP shell tool always has a genuine, non-WSL bash AND a real dev toolchain
+// to spawn on a bare host (the app must be self-contained — we cannot assume Git
+// for Windows is installed).
 //
 // This is emitted ONLY on the Windows runner because the static tauri.conf.json
 // uses `targets: "all"` with a shared bundle block — a bare `resources` entry
-// there would ship the ~184MB tree into the macOS .dmg and Linux packages too.
-// The release build runs THIS generator on each platform's own runner and merges
-// the output via --config, so guarding on process.platform keeps the tree off
-// mac/Linux.
+// there would ship the (now ~350MB+) tree into the macOS .dmg and Linux packages
+// too. The release build runs THIS generator on each platform's own runner and
+// merges the output via --config, so guarding on process.platform keeps the tree
+// off mac/Linux.
 //
 // PATH CONTRACT (keep byte-identical across three files):
 //   - source `binaries/git-bash` (relative to src-tauri/) is staged by
diff --git a/scripts/bundle-sidecars.sh b/scripts/bundle-sidecars.sh
index 3db194a13a..1240591704 100755
--- a/scripts/bundle-sidecars.sh
+++ b/scripts/bundle-sidecars.sh
@@ -39,10 +39,10 @@ for bin in "${SIDECARS[@]}"; do
 done
 echo "Sidecars bundled for $TARGET"
 
-# Windows-only: stage a genuine, non-WSL bash next to the sidecars so the MCP
-# shell tool works on a bare host. The download/extract/drop logic lives in a
-# self-contained script (no release-binary precondition) so CI can call it
-# directly to exercise this path on a real Windows runner — see
+# Windows-only: stage a genuine, non-WSL bash plus the full git toolchain next to
+# the sidecars so the MCP shell tool works on a bare host. The download/extract
+# logic lives in a self-contained script (no release-binary precondition) so CI can
+# call it directly to exercise this path on a real Windows runner — see
 # scripts/stage-windows-bash.sh for the full rationale and the PATH CONTRACT.
 if [[ "$TARGET" == *windows* ]]; then
     "$(dirname "$0")/stage-windows-bash.sh" "$BINARIES_DIR/git-bash"
diff --git a/scripts/stage-windows-bash.sh b/scripts/stage-windows-bash.sh
index ece5d08bfb..1bdc172fc6 100755
--- a/scripts/stage-windows-bash.sh
+++ b/scripts/stage-windows-bash.sh
@@ -3,33 +3,37 @@ set -euo pipefail
 
 # Stage a genuine, non-WSL bash for the Windows MCP shell tool. The app is
 # self-contained — we cannot assume Git for Windows is installed — so we bundle
-# bash rather than probing for an install.
+# the full toolchain rather than probing for an install.
 #
 # There is no standalone "bash for Windows" upstream: working Windows bash ships
-# only inside git-for-windows. We download PortableGit and keep ONLY the MSYS2
-# bash runtime (`usr/` + `bin/`), dropping the `mingw64/` git-program subtree as
-# one separable unit (~200MB of git.exe etc. the MCP shell never invokes). We do
-# NOT trim INSIDE `usr/`: bash loads `msys-2.0.dll` and other libraries lazily,
-# and load-bearing pieces (terminfo, gawk libs) live alongside the docs there, so
-# a hand-trimmed copy can pass an existence check yet fail mid-command with a
-# cryptic error — exactly the bug class this fixes. The retained runtime is the
-# untouched, complete closure git-for-windows maintains.
+# only inside git-for-windows. We download PortableGit and keep the WHOLE tree —
+# the MSYS2 bash runtime (`usr/` + `bin/`) AND the `mingw64/` subtree that carries
+# `git.exe` plus `curl`/full `sed`/`awk`/`grep`/`find` — so a bare host gets a
+# real dev env, not just bash + coreutils. `jq` is NOT in PortableGit, so we
+# additionally vendor a pinned standalone `jq.exe` into `mingw64/bin` (see below).
+# We do NOT trim INSIDE the tree: bash and git load `msys-2.0.dll` and other
+# libraries lazily, and load-bearing pieces (terminfo, gawk libs in `usr/`; git
+# templates, certs, DLLs in `mingw64/`) live alongside the docs, so a hand-trimmed
+# copy can pass an existence check yet fail mid-command with a cryptic error —
+# exactly the bug class this avoids. The retained runtime is the untouched,
+# complete closure git-for-windows maintains.
 #
 # Self-contained (no release-binary precondition) so CI can call it directly to
-# exercise the download/extract/drop path on a real Windows runner — the only
+# exercise the download/extract path on a real Windows runner — the only
 # automated gate on this logic before it ships to users.
 #
-# Single arg: the destination dir for the staged tree (the real MSYS2 bash lands
-# at <dest>/usr/bin/bash.exe). Idempotent: a `.stage-complete` marker, written last,
-# proves a whole prior stage and skips the re-download; a partial stage lacks it
-# and re-extracts cleanly.
+# Single arg: the destination dir for the staged tree (the launcher bash lands at
+# <dest>/bin/bash.exe; git lands at <dest>/mingw64/bin/git.exe). Idempotent: a
+# versioned `.stage-complete-v2` marker, written last, proves a whole prior stage
+# and skips the re-download; a partial stage (or a stale v1 marker from the old
+# mingw64-dropped layout) lacks it and re-extracts cleanly.
 #
 # PATH CONTRACT (keep byte-identical across three files):
 #   - dest `git-bash` (== desktop/src-tauri/binaries/git-bash) is the
 #     `bundle.resources` SOURCE in desktop/scripts/build-release-config.mjs.
 #   - that resource's TARGET `git-bash` is staged next to the exe by Tauri's
 #     Windows installer, and crates/buzz-dev-mcp/src/shell.rs resolves
-#     `git-bash\usr\bin\bash.exe` relative to its own executable at runtime.
+#     `git-bash\bin\bash.exe` relative to its own executable at runtime.
 
 GIT_BASH_DIR=${1:?usage: stage-windows-bash.sh <dest-dir>}
 PORTABLEGIT_VERSION="2.54.0"
@@ -37,7 +41,16 @@ PORTABLEGIT_TAG="v${PORTABLEGIT_VERSION}.windows.1"
 PORTABLEGIT_EXE="PortableGit-${PORTABLEGIT_VERSION}-64-bit.7z.exe"
 PORTABLEGIT_URL="https://github.com/git-for-windows/git/releases/download/${PORTABLEGIT_TAG}/${PORTABLEGIT_EXE}"
 
-STAGE_MARKER="$GIT_BASH_DIR/.stage-complete"
+# jq is NOT shipped in PortableGit (it is an independent MSYS2 package, not a git
+# component), but agents need it for JSON piping, so we vendor the standalone
+# static jq.exe (single binary, no DLL closure) into the bundle's mingw64/bin so
+# it resolves alongside git/curl through the launcher. Pinned by SHA-256 — never
+# an unpinned fetch.
+JQ_VERSION="1.8.1"
+JQ_URL="https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/jq-windows-amd64.exe"
+JQ_SHA256="23cb60a1354eed6bcc8d9b9735e8c7b388cd1fdcb75726b93bc299ef22dd9334"
+
+STAGE_MARKER="$GIT_BASH_DIR/.stage-complete-v2"
 if [[ -f "$STAGE_MARKER" ]]; then
     echo "PortableGit bash already staged at $GIT_BASH_DIR"
     exit 0
@@ -54,20 +67,40 @@ curl -fsSL "$PORTABLEGIT_URL" -o "$tmp_sfx"
 chmod +x "$tmp_sfx"
 "$tmp_sfx" -y "-o$extract_dir"
 
-# Keep the bash runtime whole, drop the separable git-program subtree.
-rm -rf "$extract_dir/mingw64"
+# Keep the whole extracted tree — bash runtime AND the mingw64/ git+toolchain
+# subtree — so the bundle is a real self-contained dev env.
 rm -rf "$GIT_BASH_DIR"
 mkdir -p "$GIT_BASH_DIR"
 cp -a "$extract_dir/." "$GIT_BASH_DIR/"
 
-rm -rf "$tmp_dir"
-trap - EXIT
-[[ -f "$GIT_BASH_DIR/usr/bin/bash.exe" ]] || {
-    echo "Error: PortableGit extracted but $GIT_BASH_DIR/usr/bin/bash.exe is missing" >&2
+# Vendor the pinned standalone jq.exe into mingw64/bin (alongside git/curl) so it
+# resolves through the launcher. Verify the SHA-256 before it lands — a checksum
+# mismatch fails the stage so a tampered/wrong binary never reaches the bundle.
+echo "Downloading jq ${JQ_VERSION}..."
+jq_tmp="$tmp_dir/jq.exe"
+curl -fsSL "$JQ_URL" -o "$jq_tmp"
+actual_sha=$(sha256sum "$jq_tmp" | cut -d' ' -f1)
+[[ "$actual_sha" == "$JQ_SHA256" ]] || {
+    echo "Error: jq.exe SHA-256 mismatch: got $actual_sha, expected $JQ_SHA256" >&2
     exit 1
 }
-# Written last, only after cp -a and the integrity check both succeed, so it is
+cp "$jq_tmp" "$GIT_BASH_DIR/mingw64/bin/jq.exe"
+
+rm -rf "$tmp_dir"
+trap - EXIT
+# Assert the load-bearing entry points landed: the launcher bash we resolve at
+# runtime, git.exe in mingw64/ (the binary the whole restore exists to ship), and
+# the vendored jq.exe. A stale or partial extract that lacks any must fail the
+# gate, not write the marker — otherwise the idempotency skip would lock in a
+# broken tree.
+for required in bin/bash.exe mingw64/bin/git.exe mingw64/bin/jq.exe; do
+    [[ -f "$GIT_BASH_DIR/$required" ]] || {
+        echo "Error: PortableGit extracted but $GIT_BASH_DIR/$required is missing" >&2
+        exit 1
+    }
+done
+# Written last, only after cp -a and the integrity checks all succeed, so it is
 # positive proof the whole tree landed. An interrupted stage never writes it, so
 # the idempotency skip falls through to a clean re-extract.
 touch "$STAGE_MARKER"
-echo "PortableGit bash staged at $GIT_BASH_DIR (mingw64/ dropped)"
+echo "PortableGit full toolchain staged at $GIT_BASH_DIR (bash + git + jq + coreutils)"
