agents: add shell scripting rule and artifact staging/Starlark rules (#4308)

Capture review feedback from cross-building Linux release artifacts so
agents avoid repeating shell, workflow, and Starlark pitfalls.

Codify guidelines for flat artifact staging across Bazel split
transitions, safe manifest iteration and `elif` usage in shell scripts,
and dedicated providers, explicit `for` loops, and minimal `BUILD`
exports in Starlark.
diff --git a/.agents/rules/github_actions_workflows.md b/.agents/rules/github_actions_workflows.md
index d8fabb8..85ff59c 100644
--- a/.agents/rules/github_actions_workflows.md
+++ b/.agents/rules/github_actions_workflows.md
@@ -47,6 +47,12 @@
   binary directly from `bazel-bin/<pkg>/<target>` instead of `bazel run`,
   explicitly include `//<pkg>:<target>` in `bazel build` so its `.runfiles` tree
   is materialized.
+* **Flat Staging for `actions/upload-artifact` Across Split Transitions**:
+  `actions/upload-artifact` strips only the longest common parent directory of
+  all matched `path` entries. When uploading files from multiple Bazel
+  configurations (`bazel-out/<cfg-1>/...`, `bazel-out/<cfg-2>/...`), stage them
+  into a single flat directory first (reading paths from the rule's `.txt`
+  manifest) so `<cfg>/...` subdirectories are not preserved in the artifact.
 
 ## Workflow Scripts & Testing
 * **Separate Script Files (No Inline Scripts)**: Factor non-trivial scripts
diff --git a/.agents/rules/shell.md b/.agents/rules/shell.md
new file mode 100644
index 0000000..015a0a2
--- /dev/null
+++ b/.agents/rules/shell.md
@@ -0,0 +1,13 @@
+---
+trigger: glob
+description: Shell / Bash scripting style and portability rules
+globs: "*.sh"
+---
+
+# Shell Scripting Rules
+
+* Use `elif` instead of nesting `if` inside an `else` block.
+* When reading file paths from a manifest or list file, iterate line-by-line
+  with `while IFS= read -r file; do ...; done < "$manifest"`. Do not use
+  unquoted command substitution (`$(cat "$manifest")`) or suppress ShellCheck
+  `SC2046` assuming paths lack spaces.
diff --git a/.agents/rules/starlark.md b/.agents/rules/starlark.md
index a0213ad..97ed3d2 100644
--- a/.agents/rules/starlark.md
+++ b/.agents/rules/starlark.md
@@ -60,6 +60,10 @@
   fields must be immutable when `depset()` is called (eager check before rule
   freeze). Use `tuple[T]` or `depset[T]` in providers placed into depsets; do
   not use mutable `list[T]`.
+* **Dedicated Providers over Filtering `DefaultInfo.files`**: When a rule needs
+  a subset of a dependency's outputs (e.g., binaries without a sibling `.txt`
+  manifest), return a dedicated provider (e.g., `_ReleaseFilesInfo`) instead of
+  filtering `DefaultInfo.files` by filename or extension.
 
 ## Repository Rules & Code Generation
 * **Structured Attributes**: Pass separate typed attributes (`attr.string_list`,
@@ -76,6 +80,10 @@
   introduced in Bazel 8.3.0.
 
 ## Code Style & Conventions
+* **Do Not Export `BUILD` Files Unnecessarily**: Do not add `BUILD` or
+  `BUILD.bazel` to `exports_files(...)` unless strictly required.
+* **No Nested List Comprehensions**: Do not write nested list comprehensions
+  (`[x for y in ... for x in ...]`). Use explicit `for` loops instead.
 * **Direct Attribute Access**: Use normal attribute access (`x.field`) instead
   of `getattr(x, "field", default)` for fields defined on a provider or struct
   schema. When an object may be one of multiple provider/struct variants with