diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000000..b0e1cfa3aef
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,43 @@
+version: 2
+
+updates:
+ # Python tooling dependencies — keep pip-installed scripts patched.
+ # `directories` (plural) supports globbing, so new requirements.txt files
+ # under these paths are picked up automatically without editing this file.
+ # `directory` (singular) does NOT support globbing.
+ - package-ecosystem: pip
+ directories:
+ - /scripts/**
+ schedule:
+ interval: weekly
+ open-pull-requests-limit: 5
+ labels:
+ - dependencies
+ - python
+ # Wait until a release has been public for a few days before opening a PR,
+ # so yanked/broken releases get caught upstream first. Majors wait longer.
+ cooldown:
+ default-days: 7
+ semver-major-days: 14
+ # Bundle all python tooling bumps into a single PR per run.
+ groups:
+ python:
+ patterns:
+ - "*"
+
+ # GitHub Actions used by PR-check workflows.
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: weekly
+ open-pull-requests-limit: 5
+ labels:
+ - dependencies
+ - github-actions
+ # github-actions cooldown only supports a flat default-days (no semver granularity).
+ cooldown:
+ default-days: 7
+ groups:
+ actions:
+ patterns:
+ - "*"
diff --git a/.github/instructions/ado-pipeline.instructions.md b/.github/instructions/ado-pipeline.instructions.md
index f72bbf479a9..2c07de5c78f 100644
--- a/.github/instructions/ado-pipeline.instructions.md
+++ b/.github/instructions/ado-pipeline.instructions.md
@@ -1,16 +1,16 @@
---
-applyTo: ".github/workflows/ado/*.yml,.github/workflows/ado/templates/*.yml,.github/workflows/scripts/**"
-description: "Authoring and maintenance rules for Azure DevOps YAML pipelines under .github/workflows/ado/ (wrappers + raw stage templates under templates/) and their helper scripts under .github/workflows/scripts/ that run as GitHub PR checks or in the merge queue. Apply when creating or modifying any pipeline in that folder, or any script invoked by one — covers the wrapper/raw split, required OneBranch templates (Official vs NonOfficial), Workload Identity Federation service connections, Control Tower audience URIs, internal-only dependency sources (Go / Python / container images), Python-over-shell scripting, and security hardening."
+applyTo: ".github/workflows/ado/*.yml,.github/workflows/ado/templates/*.yml,scripts/ci/**"
+description: "Authoring and maintenance rules for Azure DevOps YAML pipelines under .github/workflows/ado/ (wrappers + raw stage templates under templates/) and their helper scripts under scripts/ci/ that run as GitHub PR checks or in the merge queue. Apply when creating or modifying any pipeline in that folder, or any script invoked by one — covers the wrapper/raw split, required OneBranch templates (Official vs NonOfficial), Workload Identity Federation service connections, Control Tower audience URIs, internal-only dependency sources (Go / Python / container images), Python-over-shell scripting, and security hardening."
---
# Azure DevOps Pipelines (PR check & merge queue)
-These instructions cover ADO YAML pipelines under `.github/workflows/ado/` that run as GitHub PR checks or in the merge queue, plus their helper scripts under `.github/workflows/scripts/`. Follow every MUST below — they encode internal Microsoft policy plus security hardening for this repo.
+These instructions cover ADO YAML pipelines under `.github/workflows/ado/` that run as GitHub PR checks or in the merge queue, plus their helper scripts under `scripts/ci/`. Follow every MUST below — they encode internal Microsoft policy plus security hardening for this repo.
-Helper scripts invoked from these pipelines MUST live under `.github/workflows/scripts//`. Two layouts are supported:
+Helper scripts invoked from these pipelines MUST live under `scripts/ci//`. Two layouts are supported:
1. **Per-pipeline** — `/` is a logical area or pipeline name (e.g. `control-tower/`, `render-specs-check/`). The default.
-2. **Cross-pipeline shared** — `/` = `components/`. Helpers here are deliberately consumed by multiple pipelines (GitHub Actions PR gates AND the ADO Control Tower pipeline). See [`.github/workflows/scripts/components/README.md`](../workflows/scripts/components/README.md) for the caller contract. A regression in this area breaks multiple gates at once, so changes need extra care.
+2. **Cross-pipeline shared** — `/` = `components/`. Helpers here are deliberately consumed by multiple pipelines (GitHub Actions PR gates AND the ADO Control Tower pipeline). See [`scripts/ci/components/README.md`](../../scripts/ci/components/README.md) for the caller contract. A regression in this area breaks multiple gates at once, so changes need extra care.
In either case, keep helpers self-contained and follow the same security hardening rules as the pipeline YAML itself.
@@ -159,7 +159,7 @@ The authoritative list and rules live at https://eng.ms/docs/more/containers-sec
## Scripting
-Avoid shell scripts beyond the smallest possible wiring (env exports, `##vso[...]` log commands, single-command tool invocations). For anything more complex — argument parsing, control flow, JSON/YAML handling, HTTP, branch-name/SHA parsing — write a **Python script** under `.github/workflows/scripts//` and invoke it from the pipeline:
+Avoid shell scripts beyond the smallest possible wiring (env exports, `##vso[...]` log commands, single-command tool invocations). For anything more complex — argument parsing, control flow, JSON/YAML handling, HTTP, branch-name/SHA parsing — write a **Python script** under `scripts/ci//` and invoke it from the pipeline:
```yaml
- task: AzureCLI@2
@@ -170,7 +170,7 @@ Avoid shell scripts beyond the smallest possible wiring (env exports, `##vso[...
scriptLocation: inlineScript
inlineScript: |
set -euo pipefail
- python3 .github/workflows/scripts//