[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M69AWWNGM4S4DDN6MSXMJ1XY":3,"skill-same:01M69AWWNGM4S4DDN6MSXMJ1XY":74},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":46,"linkOnly":47,"markdownContent":48,"markdownBody":49,"frontMatter":50,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":54,"repositoryHtmlUrl":55,"repositoryHomepageUrl":6,"ownerHtmlUrl":56,"ownerBlogUrl":57,"ownerDescription":58,"updatedAt":59,"install":60,"resources":73},"01M69AWWNGM4S4DDN6MSXMJ1XY","skill-fedora-mirror-injections",null,"[Skill] Diagnose Azure Linux Stage 1 (bootstrap-mirror) BuildRequires resolution failures and backfill missing RPMs into the prod Fedora updates mirror via the azl-infra injections file. Use when triaging stage-1 \u002F azl4-bootstrap-mirror build failures, finding dependency gaps in the Fedora mirror, deciding whether a failure is a real mirror gap vs a transient timeout or a spec bug, adding entries to azl4-stage1-injections.yaml, or opening a PR with mirror injections. Triggers: bootstrap-mirror, stage 1 build failure, fedora mirror gap, missing BuildRequires, nothing provides crate, no match for argument, injections file, azl4-stage1-injections, mirror injection.","microsoft\u002Fazurelinux","microsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6154722?v=4","01M698VYDXZ6JW5WH3CRV650R8","Microsoft","01M69AVY9Y3D59ZBRVNKRJ851E",5364,"MIT","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux\u002Fblob\u002F4.0\u002F.agents\u002Fskills\u002Fskill-fedora-mirror-injections\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"mirror","skill fedora mirror injections","fedora","infra","when","backfill","for","updates","argument","missing","triggers","entries","spec","bug","dependency","use","injection","bootstrap","pr","azure","diagnose","linux","2026-11-10 10:12:30",false,"---\nname: skill-fedora-mirror-injections\ndescription: \"[Skill] Diagnose Azure Linux Stage 1 (bootstrap-mirror) BuildRequires resolution failures and backfill missing RPMs into the prod Fedora updates mirror via the azl-infra injections file. Use when triaging stage-1 \u002F azl4-bootstrap-mirror build failures, finding dependency gaps in the Fedora mirror, deciding whether a failure is a real mirror gap vs a transient timeout or a spec bug, adding entries to azl4-stage1-injections.yaml, or opening a PR with mirror injections. Triggers: bootstrap-mirror, stage 1 build failure, fedora mirror gap, missing BuildRequires, nothing provides crate, no match for argument, injections file, azl4-stage1-injections, mirror injection.\"\n---\n\n# Fedora Mirror Injections (AzL4 Stage 1 dependency gaps)\n\nDiagnose `BuildRequires` resolution failures in AzL4 Stage 1\n(`*-bootstrap-mirror`) builds, decide which are real prod-mirror gaps, and\nbackfill the missing RPMs via `azl4-stage1-injections.yaml` in `azl-infra`.\n\nValidated on the `mirror_bootstrap0623` round (draft PR #27888; 34-package\nretest all passed).\n\n## Repos You Need\n\n- **`azl-infra`** — holds the injections file and mirror tooling. Clone from:\n  `https:\u002F\u002Fdev.azure.com\u002Fmariner-org\u002Fpolar\u002F_git\u002Fazl-infra`\n  (Azure DevOps org `mariner-org`, project `polar`). The relevant tree is\n  `scripts\u002Ffedora_mirror\u002F`.\n- **`azurelinux`** — the package specs (for spec-fix cases). Clone from:\n  `https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux.git` (branch `4.0`).\n\n## When to Use This Skill\n\nUse when the user asks to:\n- Triage a stage-1 \u002F `azl4-bootstrap` build failure or triage summary.\n- Find what RPMs are missing from the prod Fedora updates mirror.\n- Add \u002F verify entries in the injections file.\n- Decide if a failure needs a mirror injection, a retest, or a spec fix.\n- Open a PR adding entries to the injections file.\n\n## Mental Model — a resolution failure IS a mirror gap\n\nStage 1 (`azl4-bootstrap-mirror`) builds resolve **all** `BuildRequires`\nfrom the prod Fedora mirror alone (`kojifedoramirror.blob.core.windows.net`).\nKoji-built RPMs from the same build set are **not** used as build deps, so\n**build ordering is irrelevant** — a resolution failure means the mirror\nlacks that exact NVR\u002Fcrate version, even if the provider built fine in the\nsame run. Do not dismiss these as build-order races.\n\nRepo split: `fedora-43-everything` (base release) is frozen and consumed\n**live** from upstream; `fedora-43-updates` **drifts** and is what gets\nmirrored into blob snapshots — so it is what needs injections.\n\n## The Eviction Pattern (root cause)\n\n1. A build pulled NVR `X` from `fedora-43-updates`.\n2. Fedora bumped to a newer major\u002Fminor `Y`; `X` demoted from `updates` repodata.\n3. `X` never entered the frozen `releases\u002F43\u002FEverything`.\n4. `X` is still recoverable from **kojipkgs** (Fedora's build archive).\n\nThe spec's `BuildRequires` upper bound (`>= X \u003C next~`) can't accept `Y` →\ninject `X` back from kojipkgs.\n\n## Procedure\n\n### 1. Scan the triage summary for resolution signatures\n```python\nimport json, re\nd = json.load(open('triage-summary-*.json'))\npat = re.compile(r'nothing provides|No match for argument|Could NOT find|missing:', re.I)\nfor b in d['buckets']:\n    for t in b['tasks']:\n        if pat.search(t['shortSummary']):\n            print(b['name'], t['taskID'], t['package'])\n```\nCheck **all** buckets — gaps hide outside the obvious one.\n\n### 2. Get EXACT pins from koji root.log (never trust summary ranges)\n```bash\ncurl -sk \"https:\u002F\u002F\u003Ckoji-host>\u002Fkoji\u002Fgetfile?taskID=\u003CchildID>&name=root.log&offset=0\" \\\n  | grep -iE \"nothing provides|No match for argument|conflicting requests\"\n```\n`crate(icu_collections) >= 2.1.1 \u003C 2.2.0~` proves the mirror has the name at\n2.2.0 but not the needed version (the eviction signature).\n\n### 3. Classify (not everything is injectable)\n| Signature | Class | Action |\n|---|---|---|\n| `nothing provides ... \u003C X~` \u002F `No match for argument: crate = X` | Real mirror gap | Inject `X` from kojipkgs |\n| `Curl error (28): Timeout` from the blob mirror | Transient infra | Retest, don't inject |\n| `Could NOT find \u003CLIB>` at `%build`, lib IS in mirror | Spec bug | Fix the azurelinux spec (`BuildRequires`) |\n| Needs version requiring a whole-stack realignment | Version skew | Upstream owner fix |\n\n0623 exclusions: **grpc** (`libpfm-devel` current, just add\n`BuildRequires: libpfm-devel`), **qt6-qthttpserver** (`qt6-qtbase-private-devel\n= 6.10.2` vs mirror qtbase 6.9.2 → qt6 stack realignment).\n\n### 4. Find the NVR + full subpackage fan-out on kojipkgs\nRust: SRPM is `rust-\u003Ccrate>`; binaries are `rust-\u003Ccrate>-devel`,\n`rust-\u003Ccrate>+\u003Cfeature>-devel` — all **noarch**, one shared NVR. Inject\n**every** subpackage of the NVR.\n```bash\n# versions\ncurl -s \"https:\u002F\u002Fkojipkgs.fedoraproject.org\u002Fpackages\u002F\u003Cname>\u002F\" | grep -oE '>[0-9][^\u003C]*\u002F\u003C' | sed -E 's\u002F>\u002F\u002F;s\u002F\\\u002F\u003C\u002F\u002F' | sort -V\n# releases for a version\ncurl -s \"https:\u002F\u002Fkojipkgs.fedoraproject.org\u002Fpackages\u002F\u003Cname>\u002F\u003Cver>\u002F\" | grep -oE '>[0-9][^\u003C]*\\.fc[0-9]+\u002F\u003C' | sed -E 's\u002F>\u002F\u002F;s\u002F\\\u002F\u003C\u002F\u002F'\n# noarch subpackages for the NVR\ncurl -s \"https:\u002F\u002Fkojipkgs.fedoraproject.org\u002Fpackages\u002F\u003Cname>\u002F\u003Cver>\u002F\u003Crel>\u002Fnoarch\u002F\" | grep -oE 'href=\"[^\"]+\\.noarch\\.rpm\"' | sed -E 's\u002Fhref=\"\u002F\u002F;s\u002F\"\u002F\u002F' | sort\n```\n\n### 5. Verify the transitive closure (avoid peeling the onion)\n```bash\nrpm -qp --requires \u003Crpm> | grep -E 'crate\\(' | grep '\u003C'   # upper-bounded deps\nrpm -qp --provides \u003Crpm> | grep -E '^crate\\('\n```\nConfirm each `\u003C X~` dep is satisfied by the injected set or current mirror\n(e.g. siblings bounded `\u003C 3.0.0~` are fine against a 2.2.0 mirror; only\n`\u003C 2.2.0~` pins need injecting). Iterate to a fixpoint. For masked gaps\n(downstream packages that never reached builddep), run a full-set offline\ndepsolve against `mirror + injections` before rerunning. Note Rust\n`%generate_buildrequires` produces BRs at build time — a static depsolve\nmisses them.\n\n### 6. Add entries to the injections file\nFile: `azl-infra\u002Fscripts\u002Ffedora_mirror\u002Finjections\u002Fazl4-stage1-injections.yaml`\n```yaml\n- {source: rust-icu_collections, name: rust-icu_collections-devel, version: 2.1.1, release: 5.fc43, arch: noarch}\n```\n- `source` = SRPM, `name` = binary RPM (set `source` whenever they differ —\n  always for rust crates; binaries live under the SRPM dir on kojipkgs).\n- `noarch` fans out to x86_64 + aarch64; arch-specific binaries get one entry per arch.\n- File is sorted by `(source, name, arch)`, `+feature-devel` before bare\n  `-devel`. Insert in place; **do not append**. Keep entries **comment-free**\n  (rationale goes in the PR\u002Fcommit).\n\n### 7. Pre-flight validation (offline, no Azure)\nNo standalone `--dry-run`; reuse the script's own functions:\n```python\nimport yaml, inject_packages as ip, logging\nlogging.disable(logging.CRITICAL)\ninj = yaml.safe_load(open('injections\u002Fazl4-stage1-injections.yaml'))\nrepos = yaml.safe_load(open('repos.yaml'))\nnew = [p for p in ip.expand_packages(inj, repos) if p['source_name'] in {'rust-...'}]\nprint('HEAD failures:', sum(0 if ip.head_check(p['url'])[0] else 1 for p in new))  # want 0\n```\n\n### 8. Know how the run behaves\n`inject_packages.py` is **add-only + idempotent** (dedup by dest path,\nSKIPs existing). **No delete path.** Storage: account `kojifedoramirrorsa`,\ncontainer `fedora-mirror`; blob path\n`snapshots\u002F\u003Csnap>\u002F\u003Crepo>\u002F\u003Carch>\u002FPackages\u002F\u003Cfirst-letter>\u002F\u003Cfile>.rpm`.\n**Snapshot caveat:** the injection only helps if it lands in the snapshot the\ntarget consumes — confirm the file's `snapshot:` matches before running.\n\n### 9. Open the PR\nCommit the injection entries on a branch off `azl-infra` `main` and open the\nPR — this is the deliverable.\n- **Branch:** `\u003Cuser>\u002F\u003Ctask>-\u003Cdate>` off latest `origin\u002Fmain`.\n- **Diff:** additions-only to `azl4-stage1-injections.yaml` (no existing lines\n  touched), entries comment-free and in the correct alphabetical slot.\n- **PR description** carries the rationale: the eviction pattern, exact NVRs,\n  which failing package(s) each entry unblocks, closure notes, the target\n  `snapshot:`, and any packages deliberately **excluded** (spec bugs \u002F version\n  skew) with why.\n- **Evidence:** paste the Step 7 offline HEAD-check result (want 0 failures).\n- Open as **draft** first if you want review before it's merge-ready.\n\n> **After merge (optional):** once the injection lands in the prod snapshot,\n> retest the affected packages (include the transient-timeout ones; exclude\n> spec\u002Fversion-skew) with a body like:\n> ```json\n> {\n>   \"repoUri\": \"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux.git\",\n>   \"branch\": \"4.0\",\n>   \"commitSha\": \"\",\n>   \"packageTarget\": \"azl4-bootstrap-mirror\",\n>   \"packages\": [\"rust-icu_normalizer\", \"rust-rkyv\", \"...\"],\n>   \"isScratchBuild\": true\n> }\n> ```\n\n## Transient timeout vs. real gap\n\nA burst of `Curl error (28): Timeout` is usually a time-windowed blob outage,\nnot a bad package. Confirm: (1) same RPM failing across many packages →\nsystemic; (2) failures pack into a short window (0623: 29 in ~78 min) →\ntransient; (3) most other builds in that window succeeded (0623: 97%) →\nmirror was up. If all three hold, **retest** — do not inject.\n\n## Gotcha — version float (pin the spec, don't delete)\n\nWhen old + new both exist (old in frozen base, new in updates\u002Fmirror), dnf\npicks the highest and an old-API spec fails (e.g. `rust-uucore` 0.0.27 vs\n0.7.0). Deleting from the mirror is the wrong lever (sync re-adds it, no\ndelete tooling, diverges from upstream). **Fix:** pin the spec's\n`crate(uucore) = 0.0.27` (+ lockstep siblings `uucore_procs`,\n`uuhelp_parser`). Since 0.0.27 lives in the frozen live base repo, the pin\nneeds zero mirror changes.\n\n## Reference\n\n- Repo `azl-infra`: `https:\u002F\u002Fdev.azure.com\u002Fmariner-org\u002Fpolar\u002F_git\u002Fazl-infra`\n- Injections file: `azl-infra\u002Fscripts\u002Ffedora_mirror\u002Finjections\u002Fazl4-stage1-injections.yaml`\n- Schema\u002Ftemplate: `...\u002Finjections\u002Fexample.yaml`\n- Tooling: `...\u002Ffedora_mirror\u002F{inject_packages,snapshot_repos}.py`, `repos.yaml`, `_common.py`\n- kojipkgs archive: `https:\u002F\u002Fkojipkgs.fedoraproject.org\u002Fpackages\u002F`\n- Prod mirror: `https:\u002F\u002Fkojifedoramirrorsa.blob.core.windows.net\u002Ffedora-mirror\u002F`\n- Worked example: draft PR #27888 in `azl-infra`\n","# Fedora Mirror Injections (AzL4 Stage 1 dependency gaps)\n\nDiagnose `BuildRequires` resolution failures in AzL4 Stage 1\n(`*-bootstrap-mirror`) builds, decide which are real prod-mirror gaps, and\nbackfill the missing RPMs via `azl4-stage1-injections.yaml` in `azl-infra`.\n\nValidated on the `mirror_bootstrap0623` round (draft PR #27888; 34-package\nretest all passed).\n\n## Repos You Need\n\n- **`azl-infra`** — holds the injections file and mirror tooling. Clone from:\n  `https:\u002F\u002Fdev.azure.com\u002Fmariner-org\u002Fpolar\u002F_git\u002Fazl-infra`\n  (Azure DevOps org `mariner-org`, project `polar`). The relevant tree is\n  `scripts\u002Ffedora_mirror\u002F`.\n- **`azurelinux`** — the package specs (for spec-fix cases). Clone from:\n  `https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux.git` (branch `4.0`).\n\n## When to Use This Skill\n\nUse when the user asks to:\n- Triage a stage-1 \u002F `azl4-bootstrap` build failure or triage summary.\n- Find what RPMs are missing from the prod Fedora updates mirror.\n- Add \u002F verify entries in the injections file.\n- Decide if a failure needs a mirror injection, a retest, or a spec fix.\n- Open a PR adding entries to the injections file.\n\n## Mental Model — a resolution failure IS a mirror gap\n\nStage 1 (`azl4-bootstrap-mirror`) builds resolve **all** `BuildRequires`\nfrom the prod Fedora mirror alone (`kojifedoramirror.blob.core.windows.net`).\nKoji-built RPMs from the same build set are **not** used as build deps, so\n**build ordering is irrelevant** — a resolution failure means the mirror\nlacks that exact NVR\u002Fcrate version, even if the provider built fine in the\nsame run. Do not dismiss these as build-order races.\n\nRepo split: `fedora-43-everything` (base release) is frozen and consumed\n**live** from upstream; `fedora-43-updates` **drifts** and is what gets\nmirrored into blob snapshots — so it is what needs injections.\n\n## The Eviction Pattern (root cause)\n\n1. A build pulled NVR `X` from `fedora-43-updates`.\n2. Fedora bumped to a newer major\u002Fminor `Y`; `X` demoted from `updates` repodata.\n3. `X` never entered the frozen `releases\u002F43\u002FEverything`.\n4. `X` is still recoverable from **kojipkgs** (Fedora's build archive).\n\nThe spec's `BuildRequires` upper bound (`>= X \u003C next~`) can't accept `Y` →\ninject `X` back from kojipkgs.\n\n## Procedure\n\n### 1. Scan the triage summary for resolution signatures\n```python\nimport json, re\nd = json.load(open('triage-summary-*.json'))\npat = re.compile(r'nothing provides|No match for argument|Could NOT find|missing:', re.I)\nfor b in d['buckets']:\n    for t in b['tasks']:\n        if pat.search(t['shortSummary']):\n            print(b['name'], t['taskID'], t['package'])\n```\nCheck **all** buckets — gaps hide outside the obvious one.\n\n### 2. Get EXACT pins from koji root.log (never trust summary ranges)\n```bash\ncurl -sk \"https:\u002F\u002F\u003Ckoji-host>\u002Fkoji\u002Fgetfile?taskID=\u003CchildID>&name=root.log&offset=0\" \\\n  | grep -iE \"nothing provides|No match for argument|conflicting requests\"\n```\n`crate(icu_collections) >= 2.1.1 \u003C 2.2.0~` proves the mirror has the name at\n2.2.0 but not the needed version (the eviction signature).\n\n### 3. Classify (not everything is injectable)\n| Signature | Class | Action |\n|---|---|---|\n| `nothing provides ... \u003C X~` \u002F `No match for argument: crate = X` | Real mirror gap | Inject `X` from kojipkgs |\n| `Curl error (28): Timeout` from the blob mirror | Transient infra | Retest, don't inject |\n| `Could NOT find \u003CLIB>` at `%build`, lib IS in mirror | Spec bug | Fix the azurelinux spec (`BuildRequires`) |\n| Needs version requiring a whole-stack realignment | Version skew | Upstream owner fix |\n\n0623 exclusions: **grpc** (`libpfm-devel` current, just add\n`BuildRequires: libpfm-devel`), **qt6-qthttpserver** (`qt6-qtbase-private-devel\n= 6.10.2` vs mirror qtbase 6.9.2 → qt6 stack realignment).\n\n### 4. Find the NVR + full subpackage fan-out on kojipkgs\nRust: SRPM is `rust-\u003Ccrate>`; binaries are `rust-\u003Ccrate>-devel`,\n`rust-\u003Ccrate>+\u003Cfeature>-devel` — all **noarch**, one shared NVR. Inject\n**every** subpackage of the NVR.\n```bash\n# versions\ncurl -s \"https:\u002F\u002Fkojipkgs.fedoraproject.org\u002Fpackages\u002F\u003Cname>\u002F\" | grep -oE '>[0-9][^\u003C]*\u002F\u003C' | sed -E 's\u002F>\u002F\u002F;s\u002F\\\u002F\u003C\u002F\u002F' | sort -V\n# releases for a version\ncurl -s \"https:\u002F\u002Fkojipkgs.fedoraproject.org\u002Fpackages\u002F\u003Cname>\u002F\u003Cver>\u002F\" | grep -oE '>[0-9][^\u003C]*\\.fc[0-9]+\u002F\u003C' | sed -E 's\u002F>\u002F\u002F;s\u002F\\\u002F\u003C\u002F\u002F'\n# noarch subpackages for the NVR\ncurl -s \"https:\u002F\u002Fkojipkgs.fedoraproject.org\u002Fpackages\u002F\u003Cname>\u002F\u003Cver>\u002F\u003Crel>\u002Fnoarch\u002F\" | grep -oE 'href=\"[^\"]+\\.noarch\\.rpm\"' | sed -E 's\u002Fhref=\"\u002F\u002F;s\u002F\"\u002F\u002F' | sort\n```\n\n### 5. Verify the transitive closure (avoid peeling the onion)\n```bash\nrpm -qp --requires \u003Crpm> | grep -E 'crate\\(' | grep '\u003C'   # upper-bounded deps\nrpm -qp --provides \u003Crpm> | grep -E '^crate\\('\n```\nConfirm each `\u003C X~` dep is satisfied by the injected set or current mirror\n(e.g. siblings bounded `\u003C 3.0.0~` are fine against a 2.2.0 mirror; only\n`\u003C 2.2.0~` pins need injecting). Iterate to a fixpoint. For masked gaps\n(downstream packages that never reached builddep), run a full-set offline\ndepsolve against `mirror + injections` before rerunning. Note Rust\n`%generate_buildrequires` produces BRs at build time — a static depsolve\nmisses them.\n\n### 6. Add entries to the injections file\nFile: `azl-infra\u002Fscripts\u002Ffedora_mirror\u002Finjections\u002Fazl4-stage1-injections.yaml`\n```yaml\n- {source: rust-icu_collections, name: rust-icu_collections-devel, version: 2.1.1, release: 5.fc43, arch: noarch}\n```\n- `source` = SRPM, `name` = binary RPM (set `source` whenever they differ —\n  always for rust crates; binaries live under the SRPM dir on kojipkgs).\n- `noarch` fans out to x86_64 + aarch64; arch-specific binaries get one entry per arch.\n- File is sorted by `(source, name, arch)`, `+feature-devel` before bare\n  `-devel`. Insert in place; **do not append**. Keep entries **comment-free**\n  (rationale goes in the PR\u002Fcommit).\n\n### 7. Pre-flight validation (offline, no Azure)\nNo standalone `--dry-run`; reuse the script's own functions:\n```python\nimport yaml, inject_packages as ip, logging\nlogging.disable(logging.CRITICAL)\ninj = yaml.safe_load(open('injections\u002Fazl4-stage1-injections.yaml'))\nrepos = yaml.safe_load(open('repos.yaml'))\nnew = [p for p in ip.expand_packages(inj, repos) if p['source_name'] in {'rust-...'}]\nprint('HEAD failures:', sum(0 if ip.head_check(p['url'])[0] else 1 for p in new))  # want 0\n```\n\n### 8. Know how the run behaves\n`inject_packages.py` is **add-only + idempotent** (dedup by dest path,\nSKIPs existing). **No delete path.** Storage: account `kojifedoramirrorsa`,\ncontainer `fedora-mirror`; blob path\n`snapshots\u002F\u003Csnap>\u002F\u003Crepo>\u002F\u003Carch>\u002FPackages\u002F\u003Cfirst-letter>\u002F\u003Cfile>.rpm`.\n**Snapshot caveat:** the injection only helps if it lands in the snapshot the\ntarget consumes — confirm the file's `snapshot:` matches before running.\n\n### 9. Open the PR\nCommit the injection entries on a branch off `azl-infra` `main` and open the\nPR — this is the deliverable.\n- **Branch:** `\u003Cuser>\u002F\u003Ctask>-\u003Cdate>` off latest `origin\u002Fmain`.\n- **Diff:** additions-only to `azl4-stage1-injections.yaml` (no existing lines\n  touched), entries comment-free and in the correct alphabetical slot.\n- **PR description** carries the rationale: the eviction pattern, exact NVRs,\n  which failing package(s) each entry unblocks, closure notes, the target\n  `snapshot:`, and any packages deliberately **excluded** (spec bugs \u002F version\n  skew) with why.\n- **Evidence:** paste the Step 7 offline HEAD-check result (want 0 failures).\n- Open as **draft** first if you want review before it's merge-ready.\n\n> **After merge (optional):** once the injection lands in the prod snapshot,\n> retest the affected packages (include the transient-timeout ones; exclude\n> spec\u002Fversion-skew) with a body like:\n> ```json\n> {\n>   \"repoUri\": \"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux.git\",\n>   \"branch\": \"4.0\",\n>   \"commitSha\": \"\",\n>   \"packageTarget\": \"azl4-bootstrap-mirror\",\n>   \"packages\": [\"rust-icu_normalizer\", \"rust-rkyv\", \"...\"],\n>   \"isScratchBuild\": true\n> }\n> ```\n\n## Transient timeout vs. real gap\n\nA burst of `Curl error (28): Timeout` is usually a time-windowed blob outage,\nnot a bad package. Confirm: (1) same RPM failing across many packages →\nsystemic; (2) failures pack into a short window (0623: 29 in ~78 min) →\ntransient; (3) most other builds in that window succeeded (0623: 97%) →\nmirror was up. If all three hold, **retest** — do not inject.\n\n## Gotcha — version float (pin the spec, don't delete)\n\nWhen old + new both exist (old in frozen base, new in updates\u002Fmirror), dnf\npicks the highest and an old-API spec fails (e.g. `rust-uucore` 0.0.27 vs\n0.7.0). Deleting from the mirror is the wrong lever (sync re-adds it, no\ndelete tooling, diverges from upstream). **Fix:** pin the spec's\n`crate(uucore) = 0.0.27` (+ lockstep siblings `uucore_procs`,\n`uuhelp_parser`). Since 0.0.27 lives in the frozen live base repo, the pin\nneeds zero mirror changes.\n\n## Reference\n\n- Repo `azl-infra`: `https:\u002F\u002Fdev.azure.com\u002Fmariner-org\u002Fpolar\u002F_git\u002Fazl-infra`\n- Injections file: `azl-infra\u002Fscripts\u002Ffedora_mirror\u002Finjections\u002Fazl4-stage1-injections.yaml`\n- Schema\u002Ftemplate: `...\u002Finjections\u002Fexample.yaml`\n- Tooling: `...\u002Ffedora_mirror\u002F{inject_packages,snapshot_repos}.py`, `repos.yaml`, `_common.py`\n- kojipkgs archive: `https:\u002F\u002Fkojipkgs.fedoraproject.org\u002Fpackages\u002F`\n- Prod mirror: `https:\u002F\u002Fkojifedoramirrorsa.blob.core.windows.net\u002Ffedora-mirror\u002F`\n- Worked example: draft PR #27888 in `azl-infra`\n",{"name":5,"description":7},"4.0","431ad36a7a827e8ec414e96ae75517ec1ded115d",".agents\u002Fskills\u002Fskill-fedora-mirror-injections",714,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux","https:\u002F\u002Fgithub.com\u002Fmicrosoft","https:\u002F\u002Fopensource.microsoft.com","Open source projects and samples from Microsoft","2026-11-15 02:36:52",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":72},[62,65,68],{"tool":63,"command":64},"npx","npx skills add microsoft\u002Fazurelinux --skill skill-fedora-mirror-injections",{"tool":66,"command":67},"bunx","bunx skills add microsoft\u002Fazurelinux --skill skill-fedora-mirror-injections",{"tool":69,"command":70},"pnpm","pnpm dlx skills add microsoft\u002Fazurelinux --skill skill-fedora-mirror-injections","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux\u002Fblob\u002F4.0\u002F.agents\u002Fskills\u002Fskill-fedora-mirror-injections\u002FSKILL.md",true,[],[75,98,119,143,164,181],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":82,"publishedAt":46},"01M69AX4PP9MJPS4TE3XDW93NJ","skill-metrics","[Skill] metrics, azure-monitor, aks - Query Azure Monitor metrics for Koji AKS node CPU, memory, disk usage, and pod readiness.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux\u002Fblob\u002F4.0\u002F.agents\u002Fskills\u002Fskill-metrics\u002FSKILL.md",[81],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[83,84,85,43,86,87,88,89,90,91,92,93,94,95,96,97,30],"skill metrics","metrics","memory","monitor","azure-monitor","aks","disk","node","query","azure monitor","false","readiness","CPU","disk usage","usage",{"skillNo":99,"name":100,"nameZh":6,"description":101,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":102,"categories":103,"keywords":105,"publishedAt":46},"01M69AX2WT9YWZTVMMQ6QWHG3Y","skill-mass-triage","[Skill] Batch-triage build failures from a JSON results file — diagnose with parallel sub-agents, bucketize by root cause, and produce a consolidated summary. Use when asked to triage a Koji results file. Triggers: batch triage, mass triage, triage results file, bucketize failures.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux\u002Fblob\u002F4.0\u002F.agents\u002Fskills\u002Fskill-mass-triage\u002FSKILL.md",[104],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[106,107,44,108,109,110,111,112,113,39,114,115,34,116,117,118,28],"triage","skill mass triage","produce","batch","file","json","parallel","results","build","summary","with","root","root cause",{"skillNo":120,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":129,"publishedAt":46},"01M69AX11X7RJS8A0GBJV2X0WD","skill-kql-queries","[Skill] kql, queries, log analytics, container logs - KQL query templates for Koji container logs, pod errors, restarts, Kubernetes events, build job activity, and node resource usage via Log Analytics.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux\u002Fblob\u002F4.0\u002F.agents\u002Fskills\u002Fskill-kql-queries\u002FSKILL.md",[125,128],{"categoryNo":126,"categoryName":127,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[130,131,132,133,134,135,136,90,137,138,114,91,93,139,140,141,142,97,30],"skill kql queries","kql","queries","kubernetes","analytics","logs","templates","container","log","events","via","activity","errors",{"skillNo":144,"name":145,"nameZh":6,"description":146,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":147,"categories":148,"keywords":150,"publishedAt":46},"01M69AWYRJY05J3N3K9PZ0X38H","skill-koji-triage","[Skill] Examine Koji builds, fetch task info and logs from the Koji Web UI, identify failures, and provide root cause analysis. Use when triaging Koji build failures, investigating failed tasks, downloading build logs, or searching for broken packages. Triggers: koji failure, koji build failed, koji task, koji log, koji triage, build failure analysis.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux\u002Fblob\u002F4.0\u002F.agents\u002Fskills\u002Fskill-koji-triage\u002FSKILL.md",[149],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[106,151,152,153,154,155,156,135,157,158,159,39,138,160,161,34,162,163,30,118,28],"skill koji triage","web","root cause analysis","tasks","packages","ui","analysis","broken","fetch","task","info","failure analysis","web ui",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":168,"categories":169,"keywords":171,"publishedAt":46},"01M69AWTVNFMTX4KQVR6EK62C0","skill-deployment-context","[Skill] deployment context, aks, azure, koji - Resolve Koji AKS deployment context -- resource group, cluster name, subscription, Log Analytics workspace, and monitoring resource names from deployment_summary.yaml when available, or discover them dynamically from Azure.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux\u002Fblob\u002F4.0\u002F.agents\u002Fskills\u002Fskill-deployment-context\u002FSKILL.md",[170],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[172,173,174,134,43,175,176,88,177,138,115,178,93,179,180,28],"skill deployment context","deployment","context","yaml","monitoring","workspace","discover","name","cluster",{"skillNo":182,"name":183,"nameZh":6,"description":184,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":185,"categories":186,"keywords":188,"publishedAt":46},"01M69AWS0NN17EN4JDDKYBNY6X","skill-aks-health","[Skill] aks, aks health, cluster health, node pool, activity logs - Inspect Koji AKS cluster health, node pool status, autoscaling, activity logs, deployment failures, and Azure control-plane operations.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fazurelinux\u002Fblob\u002F4.0\u002F.agents\u002Fskills\u002Fskill-aks-health\u002FSKILL.md",[187],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[189,88,190,191,43,173,135,192,90,193,194,93,195,180,141,196,197,198,199],"skill aks health","health","status","control-plane","operations","control","cluster health","plane","inspect","pool","autoscaling"]