docs: Add docs/infra.md and reference it in GEMINI.md

Document the pinned infra toolchain setup (infra/env_setup.sh and
infra/env_setup.fish) and instruct agents and developers to use the
infra versions of the toolchain and run cargo fmt instead of rustfmt.

Change-Id: I55269847d768efeec34ba6046b37f1c16a6a6964
Reviewed-on: https://bluetooth-review.googlesource.com/c/bluetooth/+/4240
diff --git a/GEMINI.md b/GEMINI.md
index 6628610..b7c7006 100644
--- a/GEMINI.md
+++ b/GEMINI.md
@@ -5,4 +5,7 @@
 ## Guidelines
 
 ### Commit Messages
-When asked to write or suggest a commit message, strictly follow the rules in [Commit message style](./docs/commit_messages.md).
\ No newline at end of file
+When asked to write or suggest a commit message, strictly follow the rules in [Commit message style](./docs/commit_messages.md).
+
+### Toolchain and Formatting
+When compiling, testing, or formatting code in this repository, use the `infra` toolchain (`infra/env_setup.sh` or `infra/env_setup.fish`) and run `cargo fmt` instead of `rustfmt`. See [Toolchain and Infrastructure](./docs/infra.md) for details.
diff --git a/docs/infra.md b/docs/infra.md
new file mode 100644
index 0000000..43cda3a
--- /dev/null
+++ b/docs/infra.md
@@ -0,0 +1,71 @@
+# Toolchain and Infrastructure
+
+This repository uses a pinned, hermetic toolchain managed via CIPD
+([`infra/cipd.ensure`](../infra/cipd.ensure)) for compiling, testing, and
+formatting code. The toolchain versions (Rust, Clang/LLVM, GCC, and `bindgen`)
+are kept in sync with the `fuchsia.git` toolchain.
+
+## Setting Up the Environment
+
+Before compiling, testing, or formatting code in this repository, always set up
+the shell environment to use the `infra` versions of the toolchain rather than
+system-installed or `rustup` (`~/.cargo/bin`) tools:
+
+* **Bash / Zsh**:
+  ```bash
+  source infra/env_setup.sh
+  ```
+* **Fish**:
+  ```fish
+  source infra/env_setup.fish
+  ```
+
+Sourcing these scripts ensures the CIPD packages are present in
+`infra/packages` and prepends `infra/packages/bin` and `infra/packages` to
+`PATH`.
+
+> **Note for AI Agents:** Always ensure `infra/env_setup.sh` is sourced (or
+> `infra/packages/bin` is prepended to `PATH`) before running `cargo` or other
+> build/test commands so that you use the `infra` versions of the toolchain.
+
+## Building and Testing Rust Crates
+
+The Rust workspace is located in the [`rust/`](../rust/) directory. When running
+`cargo` commands from the repository root, pass `--manifest-path rust/Cargo.toml`
+(or run `cargo` from within the `rust/` directory):
+
+```bash
+cargo build --manifest-path rust/Cargo.toml
+cargo test --manifest-path rust/Cargo.toml
+```
+
+## Formatting Code (`cargo fmt`)
+
+Always use **`cargo fmt`** instead of invoking `rustfmt` directly in this
+repository:
+
+```bash
+# From the repository root:
+cargo fmt --manifest-path rust/Cargo.toml
+
+# Or from within the rust/ directory:
+cargo fmt
+```
+
+To check formatting without modifying files (as done in presubmit):
+
+```bash
+cargo fmt --manifest-path rust/Cargo.toml -- --check
+```
+
+### Why `cargo fmt` instead of `rustfmt`?
+
+* **Toolchain consistency:** `cargo fmt` (when run with the `infra` versions of
+  the toolchain) uses the pinned `rustfmt` binary from `infra/packages/bin`
+  rather than a host `rustup` binary.
+* **Configuration discovery:** `cargo fmt` automatically locates and applies
+  [`rust/rustfmt.toml`](../rust/rustfmt.toml), which configures edition `2024`
+  and nightly formatting options (`wrap_comments = true`,
+  `use_small_heuristics = "Max"`, etc.) that match downstream repositories.
+  Running `rustfmt` directly on individual files can miss these settings or fail
+  on unstable options if the wrong binary is invoked.