[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6PJ54H068MZF2WD2JDKCVDC":3,"skill-same:01M6PJ54H068MZF2WD2JDKCVDC":81},{"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":45,"linkOnly":46,"markdownContent":47,"markdownBody":48,"frontMatter":49,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":54,"repositoryHtmlUrl":55,"repositoryHomepageUrl":56,"ownerHtmlUrl":57,"ownerBlogUrl":58,"ownerDescription":59,"updatedAt":60,"install":61,"resources":74},"01M6PJ54H068MZF2WD2JDKCVDC","pipeline-test-triage",null,"Triage test failures in an Azure DevOps pipeline run for Fluid Framework. Use when the user shares an ADO build\u002Fpipeline URL or build ID and wants failures analyzed, when they ask \"why did this pipeline fail\", \"summarize the test failures\", \"is this test flaky or a real bug\", \"compare these runs\", or wants bugs filed for genuine failures. Covers the Real Service End to End Tests pipeline as the worked example but applies to any FF test pipeline.","microsoft\u002FFluidFramework","microsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6154722?v=4","01M698VYDXZ6JW5WH3CRV650R8","Microsoft","01M69AG0BQKNGBJQ5YNG09HXXW",4947,"MIT","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fpipeline-test-triage\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],"test","triage","pipeline test triage","pipeline test","test triage","pipeline","when","bugs","for","URL","ado","test pipeline","as","end","but","bug","ask","why","framework","run","azure devops","2026-11-10 10:12:30",false,"---\nname: pipeline-test-triage\ndescription: >\n  Triage test failures in an Azure DevOps pipeline run for Fluid Framework. Use when the\n  user shares an ADO build\u002Fpipeline URL or build ID and wants failures analyzed, when they\n  ask \"why did this pipeline fail\", \"summarize the test failures\", \"is this test flaky or a\n  real bug\", \"compare these runs\", or wants bugs filed for genuine failures. Covers the Real\n  Service End to End Tests pipeline as the worked example but applies to any FF test pipeline.\nlicense: MIT\n---\n\n# Pipeline Test Triage\n\nAnalyze test failures for a given ADO pipeline run, classify them (service flakiness vs.\ninfra\u002Fharness vs. deterministic product\u002Ftest bug), compare against adjacent runs to tell\n**flaky from deterministic**, and optionally file well-formed ADO bugs for the real ones.\n\nOrg: `fluidframework` · Project: **`internal`** (work items *and* pipelines) · Repo on GitHub: `microsoft\u002FFluidFramework`.\n\n---\n\n## Prefer the cheapest source that answers the question\n\nReach for the smallest, most-structured source first, and escalate only when it can't answer the\nquestion. A single Real Service E2E run has ~660 logs and tens of MB, almost all of which are\n*passing* \"Container\" logs — so **bulk-downloading logs works but is the slow, expensive option;\ntreat it as a last resort, not a first move.**\n\n| Tier | Source | Gets you | Auth | Use when |\n|------|--------|----------|------|----------|\n| **1 (primary)** | **Playwright on the Tests tab** | Grouped failures + error\u002Fstack + per-test run **history** | Signed-in browser (one-time) | Almost always — start here |\n| **2 (fallback)** | **ADO MCP** (`ado-pipelines_*`) | Failing leg names + targeted report-log parsing | Pre-authed MCP (zero setup) | No browser session, or need raw log context (npm exit codes, infra) |\n| **3 (optional)** | **Test Results \u002F Timeline REST** | Failed-tests-only + per-test history + exact failing `log.id` + **retried-attempt failures** | MCP tool if exposed; else `az` token (**verified working**) | Bulk multi-run history, pinpoint the failing log, or surface failures hidden in retried attempts |\n| **4 (last resort)** | **Bulk log download** (MCP `build_log get_content`) | Everything, unstructured | Pre-authed MCP | Nothing above resolved it — targeted fetches missed, or you need to search across many logs |\n\nDescend a tier only when the one above can't answer the question. Tier 2 already lets you fetch just\nthe *relevant* report log(s); Tier 4 (grab many\u002Fall logs and grep) is fine when targeting fails —\njust know it's the costly path, so exhaust cheaper options first.\n\n---\n\n## Mental model: the failure taxonomy\n\nEvery failure sorts into one of three buckets. Classification *is* the deliverable.\n\n1. **Service flakiness** — real backing service was unhappy. Ignore \u002F no bug (or a service bug, not a code bug).\n   Signatures (FF Real Service E2E): FRS `Document not found` \u002F service degradation; `[r11s-frs]` `stashed ops` blob-upload **timeouts**; `[t9s]` (tinylicious) `Timeout of 5000ms exceeded`; undici `Cannot destructure property 'socket' of 'parser.deref(...)'`; sporadic connect\u002Fsocket errors. These usually differ run-to-run and often pass on auto-rerun.\n2. **Infra \u002F harness** — the run's plumbing broke: `Npm failed with return code: N`, container\u002Fdocker setup, artifact\u002Fpublish steps. The npm rc on a leg is a *symptom* — find the actual failing test inside that leg.\n3. **Deterministic product \u002F test bug** — the **same test** fails with the **same assertion\u002Fstack** across adjacent runs. This is the high-value find. File a bug.\n\n> **Green builds hide failures too.** A test can fail on Attempt 1 and pass on the auto-retry, leaving the build\n> **green** and `resultsbybuild` reporting **0 failures** — yet the Tests tab still shows the Attempt-1 failure.\n> Never conclude \"no failures\" from a green status alone; check for retried attempts (Tier 3 recipe).\n\n**Driver awareness (critical for FF):** the same spec runs per driver and is prefixed in the report:\n`[odsp]`, `[r11s-frs]`, `[r11s-docker]`, `[t9s]`, `[local]`. A test may be `pending` (skipped, shown as `-`)\non some drivers and only actually execute on one. When comparing runs you must match the **same task**\n(e.g. `test:realsvc:odsp:report --compatVersion=0 --tenantIndex=0`), not just the test name.\n\n---\n\n## Tier 1 — Playwright on the Tests tab (primary)\n\nPrereq: a browser signed into `dev.azure.com\u002Ffluidframework` (same one the `loop`\u002F`expense-report`\nskills use). If auth is missing you'll land on a login page — pause and let the user sign in, then continue.\n\n### Single-run triage\n1. `playwright-browser_navigate` →\n   `https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_build\u002Fresults?buildId={ID}&view=ms.vss-test-web.build-test-results-tab`\n2. `playwright-browser_snapshot` to read the summary. Filter\u002Fclick **Outcome = Failed**. The tab groups\n   failures and flags each **New \u002F Existing \u002F Fixed** vs. prior runs — that flag alone hints flaky vs. regression.\n3. For each failed test, click it to expand the **error message + stack**. Capture: full test name (with `[driver]`\n   prefix), the assertion\u002Ferror, top 2–3 stack frames, and the owning file. `playwright-browser_take_screenshot`\n   for the record if filing a bug.\n4. Note the **leg\u002Fstage** (e.g. \"Run Non-compat\") and the driver — the tab shows these per result.\n\n### Flaky vs. deterministic (the key question)\n- Open the failed test's **history** (the per-test view has a pass\u002Ffail sparkline across recent runs), or use\n  the pipeline's **Analytics → Test results trend** \u002F the \"failing since\" column. Read whether this exact test\n  has been failing on **consecutive** runs (deterministic) or intermittently (flaky).\n- If the history view is awkward to read, drop to Tier 2\u002F3 to compare the specific runs directly.\n\n### Notes\n- ADO tabs render lazily and paginate — always `snapshot` before clicking; don't assume off-screen rows exist.\n- Prefer reading grouped\u002Fexpanded panels over scraping; screenshot anything you'll cite in a bug.\n\n---\n\n## Tier 2 — ADO MCP fallback (zero setup, always works)\n\nUse when there's no browser session, or you need raw log context the Tests tab doesn't show. This is the\napproach used in the reference triage; it works but is heavier, so stay surgical.\n\n### Step 1 — find the failing legs (cheap)\n`ado-pipelines_build action=get_status buildId={ID} project=internal` → the **Issues** section lists failing\ntask names + error summaries, e.g. `Run Non-compat … Npm failed with return code: 2`. This tells you *which\nlegs* failed without reading a single big log.\n\n### Step 2 — locate the right report log (don't guess by size)\n`ado-pipelines_build_log action=list buildId={ID} project=internal`. Report-step logs are separate from the\njob \"Container\" aggregate and start with `##[section]Starting: [test] test:realsvc:\u003Cdriver>:report …`.\nFor each failing leg, the driver-specific report log is a **medium** log (~2.5–4k lines), *not* the biggest\n(the biggest are usually passing job aggregates). Fetch a few medium candidates and match on the first line \u002F\nthe `test:realsvc:\u003Cdriver>:report` command rather than trusting size.\n\n> Gotcha proven in practice: the odsp Non-compat failure lived in a ~3.4k-line report log, while the 15–19k-line\n> logs were all *passing* legs. Biggest ≠ failing.\n\n### Step 3 — parse the failing report log\nFetch the matched log's content and run the helper (handles the get_content temp-file JSON, ANSI\u002Ftimestamp\nstripping, and pulls the mocha summary + numbered failure block):\n\n```\nscripts\u002FParse-AdoTestLog.ps1 -Path \u003Ctemp-file-from-get_content> [-Context 30]\n```\n\nOr inline: `Get-Content \u003Cfile> -Raw | ConvertFrom-Json` → strip `\\u001b\\[[0-9;]*m` and leading `^.*?Z ` →\ngrep `^\\s*\\d+ (passing|failing|pending)` and the `N)` numbered failure entries. The 1-based array index is the\nlog line number (use it to build a direct link).\n\n### Step 4 — compare across adjacent runs (flaky vs. deterministic)\n1. `ado-pipelines_build action=list definitionId={DEF} project=internal top=100` → **filter client-side by\n   `definitionId`** (the MCP param does *not* reliably filter) and by branch. For Real Service E2E: `definitionId = 56`.\n2. Take the previous few runs (include `PartiallySucceeded`, not just `Failed` — a real failure can still leave a\n   run \"partially succeeded\"). For each, find the **same** report task (Step 2) and re-parse (Step 3).\n3. Verdict:\n   - **Deterministic** if the same test + same assertion\u002Fstack fails in **every** run where that task actually executed.\n   - **Flaky** if it appears in some runs and not others, or the errors are timeouts\u002Fservice errors that vary.\n\n---\n\n## Tier 3 — Test Results \u002F Timeline (the high-payoff endpoints)\n\nThese endpoints return *exactly* the relevant rows (a few KB, no MB log downloads) and are the right\npath when they're reachable. **All are verified working** (see the auth block for the exact token recipe):\n- **Failed tests only (fast, modern host):** use the **`vstmr.dev.azure.com`** Test Results Management host, not\n  the legacy `dev.azure.com\u002F...\u002Ftest\u002Fruns` path (that one hangs):\n  - `GET https:\u002F\u002Fvstmr.dev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Ftestresults\u002Fresultsbybuild?buildId={ID}&outcomes=Failed&api-version=7.1-preview.1`\n  - Summary\u002Fcounts: `…\u002Ftestresults\u002Fresultsummarybybuild?buildId={ID}&api-version=7.1-preview.1`\n  - **Gotcha:** these require **`-preview.1`** in the api-version — plain `7.1` returns HTTP 400 `VssInvalidPreviewVersionException`.\n- **Per-test history across builds** (direct flaky-vs-deterministic answer, avoids re-parsing N runs):\n  `POST https:\u002F\u002Fvstmr.dev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Ftestresults\u002Fresults\u002Ftesthistory?api-version=7.1-preview.1`\n  with a body carrying the test's `automatedTestName` (`{ \"automatedTestName\": \"…\", \"groupBy\": \"branch\", … }`).\n- **Timeline** — maps each failing task to its **exact `log.id`** *and* yields the job\u002Ftask GUIDs for deep links:\n  `GET https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Fbuild\u002Fbuilds\u002F{ID}\u002Ftimeline?api-version=7.1` — filter\n  `records[]` to `result == 'failed'`. This removes the Tier-2 \"which of ~660 logs is the failing report?\" guessing.\n\n> **⚠️ Green builds can still hide failures (retried attempts).** `resultsbybuild` and the **default** timeline only\n> report the **latest attempt**. A test that failed on Attempt 1 and passed on the auto-retry (Attempt 2) shows\n> **0 failures** in both — the build is green, yet the Tests tab still surfaces the Attempt-1 failure. To find these,\n> see **\"Finding failures hidden in retried attempts\"** below. Always check for retries before declaring a build clean.\n\n**Preferred access — via the ADO MCP, if it exposes these.** The MCP is already authenticated (zero setup), but\ntoday its surface only covers build\u002Flog listing + raw log content, *not* test-results or timeline. If\u002Fwhen the\nMCP gains timeline or test-results reader tools, **use those** — no token needed. Re-check the available\n`ado-*` tools before assuming you must go direct.\n\n**Fallback access — direct REST with your own token.** Needed only because calling these URLs yourself (outside\nthe MCP) has no credential attached — the MCP's credential can't be borrowed for endpoints it doesn't implement.\nProbe for a token; if none exists, stay on Tier 1\u002F2 rather than prompting for setup mid-task:\n\n```powershell\n# AAD token via Azure CLI (preferred: no stored secret, short-lived, auto-refreshed).\n# NOTE the ADO resource ID below — this exact GUID works against the fluidframework org.\n$tok = az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query accessToken -o tsv\n$headers = @{ Authorization = \"Bearer $tok\" }\n# — or — least-privilege PAT (Build:Read + Test:Read) from an env var:\n$pat = $env:AZURE_DEVOPS_EXT_PAT\n$headers = @{ Authorization = \"Basic \" + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(\":$pat\")) }\n\nInvoke-RestMethod \"https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Fbuild\u002Fbuilds\u002F$ID\u002FTimeline?api-version=7.1\" -Headers $headers\n```\n\nNever print the token\u002FPAT; read it only from `az`\u002Fenv. See **\"Enabling REST auth\"** below for one-time setup.\n\n> **Auth gotchas (both verified in practice):**\n> - **Resource ID must be `499b84ac-1321-427f-aa17-267ca6975798`.** The commonly-cited well-known ADO GUID\n>   (`499b84ac-1332-4a5e-9d67-b18d6c8a1c66`) returns `AADSTS500011: resource principal … not found in tenant` here.\n> - If the token call errors or returns an HTML sign-in page, the shell is on the wrong tenant — run\n>   `az login --tenant 72f988bf-86f1-41af-91ab-2d7cd011db47 --allow-no-subscriptions` first\n>   (the `fluidframework` org is backed by the corp tenant `72f988bf…`, confirmed via the `X-VSS-ResourceTenant` header).\n> - The Azure CLI may not be on `PATH`; call it by full path if needed\n>   (`\"$env:ProgramFiles\\Microsoft SDKs\\Azure\\CLI2\\wbin\\az.cmd\"`). Each PowerShell call is a fresh process.\n\n### Timeline → deep link recipe\n1. `GET …\u002Fbuilds\u002F{ID}\u002Ftimeline?api-version=7.1` → `records[]`, each with `id` (GUID), `parentId`, `type`\n   (`Stage`\u002F`Phase`\u002F`Job`\u002F`Task`), `name`, `result`, and (Task records) `log: { id }`.\n2. Failing **Task** record (`result=='failed'`, `name` matches the report step): its `id` = **`t`**, its `log.id`\n   = the exact log to read.\n3. Walk `parentId` up to the enclosing **Job** record: its `id` = **`j`**.\n4. `l` = failing line number (from parsing that log — grep the log for the mocha `● …` \u002F `N failing` \u002F\n   `FAIL \u003Cspec>` marker; the 1-based line index is `l`).\n5. Assemble: `…\u002F_build\u002Fresults?buildId={ID}&view=logs&j={j}&t={t}&l={l}`.\n   Param names drift across ADO versions (older builds used `lineStart`\u002F`lineEnd`), so keep the raw-log-range URL\n   as the always-safe fallback.\n\n### Finding failures hidden in retried attempts (green build, but Tests tab shows a failure)\nWhen the build is green and `resultsbybuild?outcomes=Failed` returns **0**, but a failure is still visible, an\nearlier **attempt** failed and the auto-retry passed. The failing job\u002Ftask GUIDs live in a **separate sub-timeline**,\nnot the main one. Recipe (verified on build 409208 — a JestTest failure hidden in Attempt 1 of a green build):\n1. `GET …\u002Fbuilds\u002F{ID}\u002Ftimeline?api-version=7.1` (main timeline).\n2. Find records with a non-empty **`previousAttempts`** array (these were retried); each entry has a\n   **`timelineId`** pointing at the earlier attempt's sub-timeline. Collect the distinct `timelineId`s.\n3. For each: `GET …\u002Fbuilds\u002F{ID}\u002Ftimeline\u002F{timelineId}?api-version=7.1` → filter `records[]` to `result == 'failed'`.\n   *That* sub-timeline holds the real failing `Task` (→ `t`, `log.id`) and its parent `Job` (→ `j`).\n4. Fetch that `log.id`, grep for the failure marker to get `l`, and build the deep link as above.\n\n```powershell\n$base = \"https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Fbuild\u002Fbuilds\u002F$ID\"\n$main = Invoke-RestMethod -Headers $headers \"$base\u002Ftimeline?api-version=7.1\"\n$retryTimelines = $main.records | ForEach-Object { $_.previousAttempts.timelineId } | Sort-Object -Unique\nforeach ($tid in $retryTimelines) {\n  $sub = Invoke-RestMethod -Headers $headers \"$base\u002Ftimeline\u002F$tid`?api-version=7.1\"\n  $sub.records | Where-Object result -eq 'failed' |\n    Select-Object type,name,@{n='logId';e={$_.log.id}},id,parentId\n}\n```\n\n### Enabling REST auth (one-time; optional but high payoff)\nThe gain is large exactly where this task is slowest: a full triage (~dozens of log fetches, tens of MB) collapses\nto ~3 REST calls, and cross-run flakiness becomes **one** Test History call instead of re-parsing N runs. To enable:\n- **Preferred — `az login`:** install Azure CLI, run `az login` once. No stored secret; tokens are short-lived and\n  the CLI refreshes them silently for weeks. The skill mints a fresh token per call.\n- **Fallback — PAT:** create a **least-privilege** PAT (Build **Read** + Test Management **Read** only), short\n  expiry, scoped to the `fluidframework` org; store it in the `AZURE_DEVOPS_EXT_PAT` user env var (not the repo,\n  not shell history). Rotate on expiry.\n- Prefer `az` (AAD) over PAT: short-lived and no secret at rest. Either way, the skill must read the credential\n  only from `az`\u002Fenv and must never echo it.\n\n---\n\n## Building direct links (put these in the summary \u002F bug)\n\n- **Tests tab:** `…\u002F_build\u002Fresults?buildId={ID}&view=ms.vss-test-web.build-test-results-tab`\n- **Raw log line range** (constructible without auth; opening it needs a signed-in session):\n  `https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Fbuild\u002Fbuilds\u002F{ID}\u002Flogs\u002F{LOG}?startLine={A}&endLine={B}`\n- **Nice UI log deep link** (needs Timeline job\u002Ftask GUIDs — Tier 3):\n  `…\u002F_build\u002Fresults?buildId={ID}&view=logs&j={jobGuid}&t={taskGuid}&l={line}`\n\n---\n\n## Filing bugs (when a failure is a real, deterministic bug)\n\nConfirm scope with the user first (project, tag, assignee). Defaults that have been used: project **`internal`**,\ntag **`Flaky Test`** *(reconsider this tag if the failure is deterministic — say so)*, unassigned.\n\n- Create: `ado-wit_work_item_write action=create` with a `fields` array. **Bugs in `internal` REQUIRE\n  `System.Description`.** This ADO instance does **not** display the Repro Steps field — put everything in\n  **Description** (Markdown), not `Microsoft.VSTS.TCM.ReproSteps`.\n- Update: `ado-wit_work_item_write action=update` with an **`updates`** array of JSON-Patch ops\n  (`{op:\"Replace\", path:\"\u002Ffields\u002FSystem.Description\", value:…}`, `format:\"Markdown\"`). Do **not** use `fields` for update.\n- **GitHub link gotcha:** in ADO text a bare `#12345` (and `AB#12345`) auto-links to a *work item*, not a GitHub\n  PR\u002Fissue. Always use a full URL, e.g. `[PR #27637](https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fpull\u002F27637)`.\n- **Angle-bracket gotcha:** ADO strips `\u003C...>` tokens as HTML even inside Markdown code fences — a stack frame like\n  `at Object.\u003Canonymous> (…)` loses the `\u003Canonymous>`. HTML-escape them in the source: write `&lt;anonymous&gt;`\n  (renders as `\u003Canonymous>`). Same for any `\u003CT>` \u002F html-ish text in error output.\n\n### Description template\n```markdown\n## Summary\n\u003Cone line: which leg\u002Fdriver, what consistently fails, deterministic vs. flaky>\n\n## Failing test\n`\u003Cfull test name including [driver] prefix>`\n- Task: `test:realsvc:\u003Cdriver>:report --compatVersion=\u003Cn> --tenantIndex=\u003Cn>`\n- Driver: \u003Cdriver> only (pending\u002Fskipped elsewhere, if applicable)\n\n## Error\n```\n\u003Ctrimmed error + top stack frames>\n```\n\n## Reproducibility\n\u003Ctable of the runs checked, each row linking to the error line>\n| Build | Date | Result | Error line |\n|-------|------|--------|-----------|\n| 409255 | … | Failed | [log 400](…\u002Flogs\u002F400?startLine=…&endLine=…) |\n\n## Suspected root cause\n\u003C1–2 concrete hypotheses; link suspect PRs with full GitHub URLs>\n\n## Links\n- [Build … – test results](…&view=ms.vss-test-web.build-test-results-tab)\n```\n\n---\n\n## Output contract (what to hand back)\n\n1. **Failure-mode summary** — grouped and classified (service-flakiness \u002F infra \u002F deterministic), with counts and\n   which legs\u002Fdrivers, not a raw dump.\n2. **Flaky-vs-deterministic verdict** for anything ambiguous, backed by the specific runs compared.\n3. **Recommended actions** — ignore (flaky\u002Fservice), retry, or file a bug; and for bugs, a ready-to-paste\n   Description with direct error-line links.\n\nKeep the narrative tight; lean on links for depth.\n\n---\n\n## Reference specifics — Real Service End to End Tests\n- Pipeline **definitionId 56** (\"Real Service End to End Tests\"), runs on `main` (and release branches) on a schedule.\n- Legs (matrix, one job per driver): **Run** (default), **Oldest-Compatible-Version**, **N-2ToLTS+1-back-compat**,\n  **Non-compat**, **N-1**, **Cross-Client**. Each leg fans out across drivers via `test:realsvc:\u003Cdriver>:report`.\n- Known flaky signatures to discount: FRS `Document not found`; `[r11s-frs]` stashed-ops blob-upload timeouts;\n  `[t9s]` 5000ms timeouts; undici `parser.deref(...)` socket destructure.\n- The mocha report per driver ends with `N passing \u002F N pending \u002F N failing` followed by a numbered failure list —\n  that block is the payload; everything above it is noise.\n","# Pipeline Test Triage\n\nAnalyze test failures for a given ADO pipeline run, classify them (service flakiness vs.\ninfra\u002Fharness vs. deterministic product\u002Ftest bug), compare against adjacent runs to tell\n**flaky from deterministic**, and optionally file well-formed ADO bugs for the real ones.\n\nOrg: `fluidframework` · Project: **`internal`** (work items *and* pipelines) · Repo on GitHub: `microsoft\u002FFluidFramework`.\n\n---\n\n## Prefer the cheapest source that answers the question\n\nReach for the smallest, most-structured source first, and escalate only when it can't answer the\nquestion. A single Real Service E2E run has ~660 logs and tens of MB, almost all of which are\n*passing* \"Container\" logs — so **bulk-downloading logs works but is the slow, expensive option;\ntreat it as a last resort, not a first move.**\n\n| Tier | Source | Gets you | Auth | Use when |\n|------|--------|----------|------|----------|\n| **1 (primary)** | **Playwright on the Tests tab** | Grouped failures + error\u002Fstack + per-test run **history** | Signed-in browser (one-time) | Almost always — start here |\n| **2 (fallback)** | **ADO MCP** (`ado-pipelines_*`) | Failing leg names + targeted report-log parsing | Pre-authed MCP (zero setup) | No browser session, or need raw log context (npm exit codes, infra) |\n| **3 (optional)** | **Test Results \u002F Timeline REST** | Failed-tests-only + per-test history + exact failing `log.id` + **retried-attempt failures** | MCP tool if exposed; else `az` token (**verified working**) | Bulk multi-run history, pinpoint the failing log, or surface failures hidden in retried attempts |\n| **4 (last resort)** | **Bulk log download** (MCP `build_log get_content`) | Everything, unstructured | Pre-authed MCP | Nothing above resolved it — targeted fetches missed, or you need to search across many logs |\n\nDescend a tier only when the one above can't answer the question. Tier 2 already lets you fetch just\nthe *relevant* report log(s); Tier 4 (grab many\u002Fall logs and grep) is fine when targeting fails —\njust know it's the costly path, so exhaust cheaper options first.\n\n---\n\n## Mental model: the failure taxonomy\n\nEvery failure sorts into one of three buckets. Classification *is* the deliverable.\n\n1. **Service flakiness** — real backing service was unhappy. Ignore \u002F no bug (or a service bug, not a code bug).\n   Signatures (FF Real Service E2E): FRS `Document not found` \u002F service degradation; `[r11s-frs]` `stashed ops` blob-upload **timeouts**; `[t9s]` (tinylicious) `Timeout of 5000ms exceeded`; undici `Cannot destructure property 'socket' of 'parser.deref(...)'`; sporadic connect\u002Fsocket errors. These usually differ run-to-run and often pass on auto-rerun.\n2. **Infra \u002F harness** — the run's plumbing broke: `Npm failed with return code: N`, container\u002Fdocker setup, artifact\u002Fpublish steps. The npm rc on a leg is a *symptom* — find the actual failing test inside that leg.\n3. **Deterministic product \u002F test bug** — the **same test** fails with the **same assertion\u002Fstack** across adjacent runs. This is the high-value find. File a bug.\n\n> **Green builds hide failures too.** A test can fail on Attempt 1 and pass on the auto-retry, leaving the build\n> **green** and `resultsbybuild` reporting **0 failures** — yet the Tests tab still shows the Attempt-1 failure.\n> Never conclude \"no failures\" from a green status alone; check for retried attempts (Tier 3 recipe).\n\n**Driver awareness (critical for FF):** the same spec runs per driver and is prefixed in the report:\n`[odsp]`, `[r11s-frs]`, `[r11s-docker]`, `[t9s]`, `[local]`. A test may be `pending` (skipped, shown as `-`)\non some drivers and only actually execute on one. When comparing runs you must match the **same task**\n(e.g. `test:realsvc:odsp:report --compatVersion=0 --tenantIndex=0`), not just the test name.\n\n---\n\n## Tier 1 — Playwright on the Tests tab (primary)\n\nPrereq: a browser signed into `dev.azure.com\u002Ffluidframework` (same one the `loop`\u002F`expense-report`\nskills use). If auth is missing you'll land on a login page — pause and let the user sign in, then continue.\n\n### Single-run triage\n1. `playwright-browser_navigate` →\n   `https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_build\u002Fresults?buildId={ID}&view=ms.vss-test-web.build-test-results-tab`\n2. `playwright-browser_snapshot` to read the summary. Filter\u002Fclick **Outcome = Failed**. The tab groups\n   failures and flags each **New \u002F Existing \u002F Fixed** vs. prior runs — that flag alone hints flaky vs. regression.\n3. For each failed test, click it to expand the **error message + stack**. Capture: full test name (with `[driver]`\n   prefix), the assertion\u002Ferror, top 2–3 stack frames, and the owning file. `playwright-browser_take_screenshot`\n   for the record if filing a bug.\n4. Note the **leg\u002Fstage** (e.g. \"Run Non-compat\") and the driver — the tab shows these per result.\n\n### Flaky vs. deterministic (the key question)\n- Open the failed test's **history** (the per-test view has a pass\u002Ffail sparkline across recent runs), or use\n  the pipeline's **Analytics → Test results trend** \u002F the \"failing since\" column. Read whether this exact test\n  has been failing on **consecutive** runs (deterministic) or intermittently (flaky).\n- If the history view is awkward to read, drop to Tier 2\u002F3 to compare the specific runs directly.\n\n### Notes\n- ADO tabs render lazily and paginate — always `snapshot` before clicking; don't assume off-screen rows exist.\n- Prefer reading grouped\u002Fexpanded panels over scraping; screenshot anything you'll cite in a bug.\n\n---\n\n## Tier 2 — ADO MCP fallback (zero setup, always works)\n\nUse when there's no browser session, or you need raw log context the Tests tab doesn't show. This is the\napproach used in the reference triage; it works but is heavier, so stay surgical.\n\n### Step 1 — find the failing legs (cheap)\n`ado-pipelines_build action=get_status buildId={ID} project=internal` → the **Issues** section lists failing\ntask names + error summaries, e.g. `Run Non-compat … Npm failed with return code: 2`. This tells you *which\nlegs* failed without reading a single big log.\n\n### Step 2 — locate the right report log (don't guess by size)\n`ado-pipelines_build_log action=list buildId={ID} project=internal`. Report-step logs are separate from the\njob \"Container\" aggregate and start with `##[section]Starting: [test] test:realsvc:\u003Cdriver>:report …`.\nFor each failing leg, the driver-specific report log is a **medium** log (~2.5–4k lines), *not* the biggest\n(the biggest are usually passing job aggregates). Fetch a few medium candidates and match on the first line \u002F\nthe `test:realsvc:\u003Cdriver>:report` command rather than trusting size.\n\n> Gotcha proven in practice: the odsp Non-compat failure lived in a ~3.4k-line report log, while the 15–19k-line\n> logs were all *passing* legs. Biggest ≠ failing.\n\n### Step 3 — parse the failing report log\nFetch the matched log's content and run the helper (handles the get_content temp-file JSON, ANSI\u002Ftimestamp\nstripping, and pulls the mocha summary + numbered failure block):\n\n```\nscripts\u002FParse-AdoTestLog.ps1 -Path \u003Ctemp-file-from-get_content> [-Context 30]\n```\n\nOr inline: `Get-Content \u003Cfile> -Raw | ConvertFrom-Json` → strip `\\u001b\\[[0-9;]*m` and leading `^.*?Z ` →\ngrep `^\\s*\\d+ (passing|failing|pending)` and the `N)` numbered failure entries. The 1-based array index is the\nlog line number (use it to build a direct link).\n\n### Step 4 — compare across adjacent runs (flaky vs. deterministic)\n1. `ado-pipelines_build action=list definitionId={DEF} project=internal top=100` → **filter client-side by\n   `definitionId`** (the MCP param does *not* reliably filter) and by branch. For Real Service E2E: `definitionId = 56`.\n2. Take the previous few runs (include `PartiallySucceeded`, not just `Failed` — a real failure can still leave a\n   run \"partially succeeded\"). For each, find the **same** report task (Step 2) and re-parse (Step 3).\n3. Verdict:\n   - **Deterministic** if the same test + same assertion\u002Fstack fails in **every** run where that task actually executed.\n   - **Flaky** if it appears in some runs and not others, or the errors are timeouts\u002Fservice errors that vary.\n\n---\n\n## Tier 3 — Test Results \u002F Timeline (the high-payoff endpoints)\n\nThese endpoints return *exactly* the relevant rows (a few KB, no MB log downloads) and are the right\npath when they're reachable. **All are verified working** (see the auth block for the exact token recipe):\n- **Failed tests only (fast, modern host):** use the **`vstmr.dev.azure.com`** Test Results Management host, not\n  the legacy `dev.azure.com\u002F...\u002Ftest\u002Fruns` path (that one hangs):\n  - `GET https:\u002F\u002Fvstmr.dev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Ftestresults\u002Fresultsbybuild?buildId={ID}&outcomes=Failed&api-version=7.1-preview.1`\n  - Summary\u002Fcounts: `…\u002Ftestresults\u002Fresultsummarybybuild?buildId={ID}&api-version=7.1-preview.1`\n  - **Gotcha:** these require **`-preview.1`** in the api-version — plain `7.1` returns HTTP 400 `VssInvalidPreviewVersionException`.\n- **Per-test history across builds** (direct flaky-vs-deterministic answer, avoids re-parsing N runs):\n  `POST https:\u002F\u002Fvstmr.dev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Ftestresults\u002Fresults\u002Ftesthistory?api-version=7.1-preview.1`\n  with a body carrying the test's `automatedTestName` (`{ \"automatedTestName\": \"…\", \"groupBy\": \"branch\", … }`).\n- **Timeline** — maps each failing task to its **exact `log.id`** *and* yields the job\u002Ftask GUIDs for deep links:\n  `GET https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Fbuild\u002Fbuilds\u002F{ID}\u002Ftimeline?api-version=7.1` — filter\n  `records[]` to `result == 'failed'`. This removes the Tier-2 \"which of ~660 logs is the failing report?\" guessing.\n\n> **⚠️ Green builds can still hide failures (retried attempts).** `resultsbybuild` and the **default** timeline only\n> report the **latest attempt**. A test that failed on Attempt 1 and passed on the auto-retry (Attempt 2) shows\n> **0 failures** in both — the build is green, yet the Tests tab still surfaces the Attempt-1 failure. To find these,\n> see **\"Finding failures hidden in retried attempts\"** below. Always check for retries before declaring a build clean.\n\n**Preferred access — via the ADO MCP, if it exposes these.** The MCP is already authenticated (zero setup), but\ntoday its surface only covers build\u002Flog listing + raw log content, *not* test-results or timeline. If\u002Fwhen the\nMCP gains timeline or test-results reader tools, **use those** — no token needed. Re-check the available\n`ado-*` tools before assuming you must go direct.\n\n**Fallback access — direct REST with your own token.** Needed only because calling these URLs yourself (outside\nthe MCP) has no credential attached — the MCP's credential can't be borrowed for endpoints it doesn't implement.\nProbe for a token; if none exists, stay on Tier 1\u002F2 rather than prompting for setup mid-task:\n\n```powershell\n# AAD token via Azure CLI (preferred: no stored secret, short-lived, auto-refreshed).\n# NOTE the ADO resource ID below — this exact GUID works against the fluidframework org.\n$tok = az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query accessToken -o tsv\n$headers = @{ Authorization = \"Bearer $tok\" }\n# — or — least-privilege PAT (Build:Read + Test:Read) from an env var:\n$pat = $env:AZURE_DEVOPS_EXT_PAT\n$headers = @{ Authorization = \"Basic \" + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(\":$pat\")) }\n\nInvoke-RestMethod \"https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Fbuild\u002Fbuilds\u002F$ID\u002FTimeline?api-version=7.1\" -Headers $headers\n```\n\nNever print the token\u002FPAT; read it only from `az`\u002Fenv. See **\"Enabling REST auth\"** below for one-time setup.\n\n> **Auth gotchas (both verified in practice):**\n> - **Resource ID must be `499b84ac-1321-427f-aa17-267ca6975798`.** The commonly-cited well-known ADO GUID\n>   (`499b84ac-1332-4a5e-9d67-b18d6c8a1c66`) returns `AADSTS500011: resource principal … not found in tenant` here.\n> - If the token call errors or returns an HTML sign-in page, the shell is on the wrong tenant — run\n>   `az login --tenant 72f988bf-86f1-41af-91ab-2d7cd011db47 --allow-no-subscriptions` first\n>   (the `fluidframework` org is backed by the corp tenant `72f988bf…`, confirmed via the `X-VSS-ResourceTenant` header).\n> - The Azure CLI may not be on `PATH`; call it by full path if needed\n>   (`\"$env:ProgramFiles\\Microsoft SDKs\\Azure\\CLI2\\wbin\\az.cmd\"`). Each PowerShell call is a fresh process.\n\n### Timeline → deep link recipe\n1. `GET …\u002Fbuilds\u002F{ID}\u002Ftimeline?api-version=7.1` → `records[]`, each with `id` (GUID), `parentId`, `type`\n   (`Stage`\u002F`Phase`\u002F`Job`\u002F`Task`), `name`, `result`, and (Task records) `log: { id }`.\n2. Failing **Task** record (`result=='failed'`, `name` matches the report step): its `id` = **`t`**, its `log.id`\n   = the exact log to read.\n3. Walk `parentId` up to the enclosing **Job** record: its `id` = **`j`**.\n4. `l` = failing line number (from parsing that log — grep the log for the mocha `● …` \u002F `N failing` \u002F\n   `FAIL \u003Cspec>` marker; the 1-based line index is `l`).\n5. Assemble: `…\u002F_build\u002Fresults?buildId={ID}&view=logs&j={j}&t={t}&l={l}`.\n   Param names drift across ADO versions (older builds used `lineStart`\u002F`lineEnd`), so keep the raw-log-range URL\n   as the always-safe fallback.\n\n### Finding failures hidden in retried attempts (green build, but Tests tab shows a failure)\nWhen the build is green and `resultsbybuild?outcomes=Failed` returns **0**, but a failure is still visible, an\nearlier **attempt** failed and the auto-retry passed. The failing job\u002Ftask GUIDs live in a **separate sub-timeline**,\nnot the main one. Recipe (verified on build 409208 — a JestTest failure hidden in Attempt 1 of a green build):\n1. `GET …\u002Fbuilds\u002F{ID}\u002Ftimeline?api-version=7.1` (main timeline).\n2. Find records with a non-empty **`previousAttempts`** array (these were retried); each entry has a\n   **`timelineId`** pointing at the earlier attempt's sub-timeline. Collect the distinct `timelineId`s.\n3. For each: `GET …\u002Fbuilds\u002F{ID}\u002Ftimeline\u002F{timelineId}?api-version=7.1` → filter `records[]` to `result == 'failed'`.\n   *That* sub-timeline holds the real failing `Task` (→ `t`, `log.id`) and its parent `Job` (→ `j`).\n4. Fetch that `log.id`, grep for the failure marker to get `l`, and build the deep link as above.\n\n```powershell\n$base = \"https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Fbuild\u002Fbuilds\u002F$ID\"\n$main = Invoke-RestMethod -Headers $headers \"$base\u002Ftimeline?api-version=7.1\"\n$retryTimelines = $main.records | ForEach-Object { $_.previousAttempts.timelineId } | Sort-Object -Unique\nforeach ($tid in $retryTimelines) {\n  $sub = Invoke-RestMethod -Headers $headers \"$base\u002Ftimeline\u002F$tid`?api-version=7.1\"\n  $sub.records | Where-Object result -eq 'failed' |\n    Select-Object type,name,@{n='logId';e={$_.log.id}},id,parentId\n}\n```\n\n### Enabling REST auth (one-time; optional but high payoff)\nThe gain is large exactly where this task is slowest: a full triage (~dozens of log fetches, tens of MB) collapses\nto ~3 REST calls, and cross-run flakiness becomes **one** Test History call instead of re-parsing N runs. To enable:\n- **Preferred — `az login`:** install Azure CLI, run `az login` once. No stored secret; tokens are short-lived and\n  the CLI refreshes them silently for weeks. The skill mints a fresh token per call.\n- **Fallback — PAT:** create a **least-privilege** PAT (Build **Read** + Test Management **Read** only), short\n  expiry, scoped to the `fluidframework` org; store it in the `AZURE_DEVOPS_EXT_PAT` user env var (not the repo,\n  not shell history). Rotate on expiry.\n- Prefer `az` (AAD) over PAT: short-lived and no secret at rest. Either way, the skill must read the credential\n  only from `az`\u002Fenv and must never echo it.\n\n---\n\n## Building direct links (put these in the summary \u002F bug)\n\n- **Tests tab:** `…\u002F_build\u002Fresults?buildId={ID}&view=ms.vss-test-web.build-test-results-tab`\n- **Raw log line range** (constructible without auth; opening it needs a signed-in session):\n  `https:\u002F\u002Fdev.azure.com\u002Ffluidframework\u002Finternal\u002F_apis\u002Fbuild\u002Fbuilds\u002F{ID}\u002Flogs\u002F{LOG}?startLine={A}&endLine={B}`\n- **Nice UI log deep link** (needs Timeline job\u002Ftask GUIDs — Tier 3):\n  `…\u002F_build\u002Fresults?buildId={ID}&view=logs&j={jobGuid}&t={taskGuid}&l={line}`\n\n---\n\n## Filing bugs (when a failure is a real, deterministic bug)\n\nConfirm scope with the user first (project, tag, assignee). Defaults that have been used: project **`internal`**,\ntag **`Flaky Test`** *(reconsider this tag if the failure is deterministic — say so)*, unassigned.\n\n- Create: `ado-wit_work_item_write action=create` with a `fields` array. **Bugs in `internal` REQUIRE\n  `System.Description`.** This ADO instance does **not** display the Repro Steps field — put everything in\n  **Description** (Markdown), not `Microsoft.VSTS.TCM.ReproSteps`.\n- Update: `ado-wit_work_item_write action=update` with an **`updates`** array of JSON-Patch ops\n  (`{op:\"Replace\", path:\"\u002Ffields\u002FSystem.Description\", value:…}`, `format:\"Markdown\"`). Do **not** use `fields` for update.\n- **GitHub link gotcha:** in ADO text a bare `#12345` (and `AB#12345`) auto-links to a *work item*, not a GitHub\n  PR\u002Fissue. Always use a full URL, e.g. `[PR #27637](https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fpull\u002F27637)`.\n- **Angle-bracket gotcha:** ADO strips `\u003C...>` tokens as HTML even inside Markdown code fences — a stack frame like\n  `at Object.\u003Canonymous> (…)` loses the `\u003Canonymous>`. HTML-escape them in the source: write `&lt;anonymous&gt;`\n  (renders as `\u003Canonymous>`). Same for any `\u003CT>` \u002F html-ish text in error output.\n\n### Description template\n```markdown\n## Summary\n\u003Cone line: which leg\u002Fdriver, what consistently fails, deterministic vs. flaky>\n\n## Failing test\n`\u003Cfull test name including [driver] prefix>`\n- Task: `test:realsvc:\u003Cdriver>:report --compatVersion=\u003Cn> --tenantIndex=\u003Cn>`\n- Driver: \u003Cdriver> only (pending\u002Fskipped elsewhere, if applicable)\n\n## Error\n```\n\u003Ctrimmed error + top stack frames>\n```\n\n## Reproducibility\n\u003Ctable of the runs checked, each row linking to the error line>\n| Build | Date | Result | Error line |\n|-------|------|--------|-----------|\n| 409255 | … | Failed | [log 400](…\u002Flogs\u002F400?startLine=…&endLine=…) |\n\n## Suspected root cause\n\u003C1–2 concrete hypotheses; link suspect PRs with full GitHub URLs>\n\n## Links\n- [Build … – test results](…&view=ms.vss-test-web.build-test-results-tab)\n```\n\n---\n\n## Output contract (what to hand back)\n\n1. **Failure-mode summary** — grouped and classified (service-flakiness \u002F infra \u002F deterministic), with counts and\n   which legs\u002Fdrivers, not a raw dump.\n2. **Flaky-vs-deterministic verdict** for anything ambiguous, backed by the specific runs compared.\n3. **Recommended actions** — ignore (flaky\u002Fservice), retry, or file a bug; and for bugs, a ready-to-paste\n   Description with direct error-line links.\n\nKeep the narrative tight; lean on links for depth.\n\n---\n\n## Reference specifics — Real Service End to End Tests\n- Pipeline **definitionId 56** (\"Real Service End to End Tests\"), runs on `main` (and release branches) on a schedule.\n- Legs (matrix, one job per driver): **Run** (default), **Oldest-Compatible-Version**, **N-2ToLTS+1-back-compat**,\n  **Non-compat**, **N-1**, **Cross-Client**. Each leg fans out across drivers via `test:realsvc:\u003Cdriver>:report`.\n- Known flaky signatures to discount: FRS `Document not found`; `[r11s-frs]` stashed-ops blob-upload timeouts;\n  `[t9s]` 5000ms timeouts; undici `parser.deref(...)` socket destructure.\n- The mocha report per driver ends with `N passing \u002F N pending \u002F N failing` followed by a numbered failure list —\n  that block is the payload; everything above it is noise.\n",{"name":5,"license":15,"description":50},"Triage test failures in an Azure DevOps pipeline run for Fluid Framework. Use when the user shares an ADO build\u002Fpipeline URL or build ID and wants failures analyzed, when they ask \"why did this pipeline fail\", \"summarize the test failures\", \"is this test flaky or a real bug\", \"compare these runs\", or wants bugs filed for genuine failures. Covers the Real Service End to End Tests pipeline as the worked example but applies to any FF test pipeline.\n","main","8809386f7af487f40be7dcbea5d0e4afc37efd0a",".github\u002Fskills\u002Fpipeline-test-triage",590,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework","https:\u002F\u002Ffluidframework.com","https:\u002F\u002Fgithub.com\u002Fmicrosoft","https:\u002F\u002Fopensource.microsoft.com","Open source projects and samples from Microsoft","2026-11-12 03:12:28",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add microsoft\u002FFluidFramework --skill pipeline-test-triage",{"tool":67,"command":68},"bunx","bunx skills add microsoft\u002FFluidFramework --skill pipeline-test-triage",{"tool":70,"command":71},"pnpm","pnpm dlx skills add microsoft\u002FFluidFramework --skill pipeline-test-triage","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fpipeline-test-triage\u002FSKILL.md",true,[75],{"path":76,"resourceType":77,"resourceTypeDesc":78,"sizeBytes":79,"sourceHtmlUrl":80},"scripts\u002FParse-AdoTestLog.ps1","SCRIPT","脚本",3859,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fpipeline-test-triage\u002Fscripts\u002FParse-AdoTestLog.ps1",[82,100,135,158,176,200],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":45},"01M6PJ5SAHYFZFWDG5Y4RW56EP","trigger-pipelines-for-copilot-pr","Trigger ADO pipelines for a Copilot-created PR by posting \u002Fazp run comments. Use when the user asks to trigger CI pipelines for a specific PR.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Ftrigger-pipelines-for-copilot-pr\u002FSKILL.md",[],[89,90,32,91,92,93,34,94,43,95,96,97,33,98,99,30],"pr","trigger pipelines for copilot pr","trigger","copilot","pipelines","posting","ci","use","number","comments","user",{"skillNo":101,"name":102,"nameZh":6,"description":103,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":117,"publishedAt":45},"01M6PJ5M4ZG7E78C4GM4041HEP","review","Review changes relative to a prior state, such as a diff, pull request, branch, commit, or working-tree changes. Use for change-focused code review and regression analysis. Do not use to assess an existing file, API, design, implementation, or other artifact without a comparison; if the request is ambiguous, ask whether the user wants a change review and what prior state to compare against.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Freview\u002FSKILL.md",[106,109,112],{"categoryNo":107,"categoryName":108,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000007","代码审查",{"categoryNo":110,"categoryName":111,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":113,"categoryName":114,"taxonomyType":115,"taxonomyTypeDesc":116},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[102,118,119,120,121,40,122,123,124,125,126,127,128,129,130,36,131,132,32,133,134],"branch","regression","code review","design","analysis","code","commit","api","change","artifact","request","pull","tree","do","diff","assess","ambiguous",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":144,"publishedAt":45},"01M6PJ5E3PCBDS319FFMHPFACN","review-pr-local","The authority on pulling a pull request — Azure DevOps or GitHub — into an isolated local worktree so a human can review it in their editor, and on posting human-controlled review comments back to the PR (ADO via the ado PR-thread MCP tools or the Azure DevOps REST API, GitHub via the gh CLI). Auto-detects the platform and all identifiers from the PR URL; not tied to any specific repository. The AI assists an interactive human review and only ever posts comments the human explicitly requests. If you find yourself checking out a PR branch over the user's own working tree, or posting AI-authored review prose the human did not ask for, invoke this skill instead.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Freview-pr-local\u002FSKILL.md",[141],{"categoryNo":142,"categoryName":143,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[145,102,89,146,147,148,118,149,150,151,152,153,154,44,33,155,40,125,156,157],"local","review pr local","review pr","back","posts","only","MCP","authority","auto","invoke","you","cli","worktree",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":162,"categories":163,"keywords":164,"publishedAt":45},"01M6PJ5AVZAS0AEBPCYJZ9ZMMD","policy-check","This skill should be used when the user asks to \"run policy check\", \"check policy\", \"policy-check\", or needs to validate package compliance. Provides guidance on running policy checks for specific packages or the entire repository.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Fpolicy-check\u002FSKILL.md",[],[165,166,167,168,169,32,43,170,171,172,173,99,174,30,175],"policy check","policy","check","packages","compliance","repository","guidance","validate","package","running","entire",{"skillNo":177,"name":178,"nameZh":6,"description":179,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":180,"categories":181,"keywords":182,"publishedAt":45},"01M6PJ4ZJASDV2CGQTG1JWKBFE","fluid-release","Fluid Framework client release group — minor releases, patch releases, and post-release type test updates. Covers release prep, branching, version bumps, changelogs, release notes, and type test baselines. In autonomous mode, auto-detects state from the repo, attempts to execute, and falls back to a GitHub issue on failure. Triggers on \"release\", \"do the release\", \"release status\", version bump, release notes, changelog, release branch, or release engineering.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Ffluid-release\u002FSKILL.md",[],[183,184,185,148,118,186,187,188,189,190,153,191,192,193,194,195,196,197,198,199],"release","fluid release","fluid","bump","mode","autonomous","release notes","release status","updates","patch","notes","changelog","release prep","releases","status","issue","branching",{"skillNo":201,"name":202,"nameZh":6,"description":203,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":204,"categories":205,"keywords":206,"publishedAt":45},"01M6PJ4VZB32S8YG8RBKRZ4GP2","fluid-pr","Use when creating a pull request in the Fluid Framework repo. Composes a PR title and body following Fluid Framework conventions, proposes them to the user, then pushes the branch and creates the PR on GitHub. Triggers on \"create a PR\", \"make a PR\", \"open a PR\", \"submit a PR\", or \"push and create a PR\".","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FFluidFramework\u002Fblob\u002Fmain\u002F.github\u002Fskills\u002Ffluid-pr\u002FSKILL.md",[],[89,185,207,129,118,208,209,210,211,212,213,96,214,215,216,217,218,128,219,220,30],"fluid pr","push","submit","repo","triggers","pr title","open","fluid framework","create","title","github","pull request","conventions","body"]