ci-analysis: structured output, MCP integration, and deep investigation guides#124240
ci-analysis: structured output, MCP integration, and deep investigation guides#124240lewing merged 45 commits intodotnet:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the ci-analysis Copilot skill to follow the “data vs. reasoning boundary” pattern by having the script emit a structured JSON summary block ([CI_ANALYSIS_SUMMARY]) and moving recommendation synthesis into the agent guidance in SKILL.md.
Changes:
- Added Helix ListFiles-based work item file retrieval to avoid broken artifact URIs from the Details endpoint.
- Replaced the script’s canned recommendation
if/elseifchain with a structured[CI_ANALYSIS_SUMMARY]JSON block (including correlation and hint fields). - Updated
SKILL.mdto instruct agents to generate recommendations from the JSON summary (decision table + nuance guidance).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| .github/skills/ci-analysis/scripts/Get-CIStatus.ps1 | Adds Helix ListFiles workaround and emits [CI_ANALYSIS_SUMMARY] JSON instead of canned recommendation prose. |
| .github/skills/ci-analysis/SKILL.md | Documents the new workflow: parse JSON summary + agent-generated recommendations, with decision logic guidance. |
243fffa to
c0fc5fe
Compare
6cd308e to
d10ea41
Compare
… reasoning Apply the Data vs. Reasoning Boundary pattern: - Script emits [CI_ANALYSIS_SUMMARY] JSON block with structured facts (totalFailedJobs, failedJobNames, knownIssues, prCorrelation, recommendationHint) - Removed 47-line if/elseif recommendation chain producing canned prose - Added 'Generating Recommendations' section to SKILL.md with decision table - Updated 'Presenting Results' to reference JSON summary flow - Agent now reasons over structured data instead of parroting script output Tested with Claude Sonnet 4 and GPT-5 against PR dotnet#124232 — both rated JSON completeness 4/5 and generated better recommendations than the old heuristic.
…before-claiming - Add Step 0: Gather Context section with PR type classification table (code, flow, backport, merge, dependency update) that determines interpretation framework - Add Step 3: Verify before claiming - systematic checklist before labeling failures as infrastructure/transient/PR-related - Add structured output format (summary verdict, failure details, recommended actions) - Replace 'main branch' with 'target branch' throughout - backports and release-branch PRs need comparison against their actual base, not main - Remove redundant tip (covered by Step 0)
…, fix base/target terminology
When ListFiles returns an empty array (0 files), the empty array is falsy in PowerShell, causing fallback to the Details endpoint's broken URIs. Use \ -ne check instead.
f264d86 to
9a3194c
Compare
…coded path, update Three Modes table
cf462f6 to
5cf7c95
Compare
… ~3.3K tokens Move 'Deep Investigation with Azure CLI' section (97 lines) and detailed 'Recovering Results from Canceled Jobs' steps to references/. Content already exists in references/azure-cli.md. Remove duplicate 'Canceled != Failed' callout. SKILL.md is now ~3.3K tokens, within the 2K-4K target for script-driven skills.
When a user asks about a job/error/cancellation that doesn't appear in the current build results, the agent should ask if they're referring to a prior build rather than silently missing context. Added Step 2 item 5 with concrete triggers: empty canceledJobNames when user mentions cancellations, green build when user says CI is failing, missing job names. Offers to re-run with -BuildId for the earlier build.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
.github/skills/ci-analysis/scripts/Get-CIStatus.ps1:2140
- In the non-Helix (build failure) path,
jobDetail.errorCategoryis only set tobuild-errorwhenExtract-BuildErrorsfinds matches. If extraction returns 0 errors (pattern miss, truncated logs, etc.), the JSON will reportunclassifiedwith an empty snippet even though the job is clearly a build failure. Consider settingerrorCategorytobuild-erroras soon as you enter the non-Helix branch, and populatingerrorSnippetwith something deterministic (e.g., failed task name and/or a short tail of the task log) when no errors are extracted.
# No Helix tasks - this is a build failure, extract actual errors
$buildTasks = $timeline.records | Where-Object {
$_.parentId -eq $job.id -and $_.result -eq "failed"
}
foreach ($task in $buildTasks | Select-Object -First 3) {
Write-Host " Failed task: $($task.name)" -ForegroundColor Red
# Fetch and parse the build log for actual errors
if ($task.log) {
$logUrl = "https://dev.azure.com/$Organization/$Project/_build/results?buildId=$currentBuildId&view=logs&j=$($job.id)&t=$($task.id)"
Write-Host " Log: $logUrl" -ForegroundColor Gray
$logContent = Get-BuildLog -Build $currentBuildId -LogId $task.log.id
if ($logContent) {
$buildErrors = Extract-BuildErrors -LogContent $logContent
if ($buildErrors.Count -gt 0) {
# Collect for PR correlation
$allFailuresForCorrelation += @{
TaskName = $task.name
JobName = $job.name
Errors = $buildErrors
HelixLogs = @()
FailedTests = @()
}
$jobDetail.errorCategory = "build-error"
if (-not $jobDetail.errorSnippet) {
$snippet = ($buildErrors | Select-Object -First 2) -join "; "
$jobDetail.errorSnippet = $snippet.Substring(0, [Math]::Min(200, $snippet.Length))
}
# Extract Helix log URLs from the full log content
$helixLogUrls = Extract-HelixLogUrls -LogContent $logContent
if ($helixLogUrls.Count -gt 0) {
Write-Host " Helix failures ($($helixLogUrls.Count)):" -ForegroundColor Red
foreach ($helixLog in $helixLogUrls | Select-Object -First 5) {
Write-Host " - $($helixLog.WorkItem)" -ForegroundColor White
Write-Host " Log: $($helixLog.Url)" -ForegroundColor Gray
}
if ($helixLogUrls.Count -gt 5) {
Write-Host " ... and $($helixLogUrls.Count - 5) more" -ForegroundColor Gray
}
}
else {
Write-Host " Build errors:" -ForegroundColor Red
foreach ($err in $buildErrors | Select-Object -First 5) {
Write-Host " $err" -ForegroundColor White
}
if ($buildErrors.Count -gt 5) {
Write-Host " ... and $($buildErrors.Count - 5) more errors" -ForegroundColor Gray
}
}
# Search for known issues
Show-KnownIssues -ErrorMessage ($buildErrors -join "`n") -IncludeMihuBot:$SearchMihuBot
}
else {
Write-Host " (No specific errors extracted from log)" -ForegroundColor Gray
}
}
…ool name examples
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
.github/skills/ci-analysis/scripts/Get-CIStatus.ps1:2150
$allFailedJobDetails += $jobDetailis executed only on the success path. If an exception is thrown while processing a failed job and-ContinueOnErroris set, that job will be missing fromfailedJobDetailseven though it’s still infailedJobNames, and the missing entry will also affectfailedJobDetailsTruncated. Consider appending a best-effortjobDetailin afinallyblock (and populatingerrorSnippetfrom the exception) so the JSON remains structurally complete.
$allFailedJobDetails += $jobDetail
$processedJobs++
}
catch {
$errorCount++
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
.github/skills/ci-analysis/scripts/Get-CIStatus.ps1:2011
Extract-HelixUrlsis called even when$logContentis$null(it’s outside theif ($logContent)block).Extract-HelixUrlsdoes regex matching on the content and can throw on null input, which will abort processing this job/build. Move the Helix URL extraction inside the$logContentguard (or makeExtract-HelixUrlsreturn an empty array when$LogContentis null/empty).
# Extract and optionally fetch Helix URLs
$helixUrls = Extract-HelixUrls -LogContent $logContent
|
This looks like a banger. |
…natives (#124359) Follow-up to #124240 with three improvements to the ci-analysis skill: ### Changes **MSBuild cross-platform guidance** (build-progression-analysis.md) - Added anti-pattern warning about MSBuild property path separator differences (`;` vs `:`) when comparing binlogs across Windows/Linux Helix queues - This is a common false positive in build progression analysis **Merge commit shortcut for target SHA extraction** (build-progression-analysis.md) - Added Step 2b shortcut: `gh api repos/{owner}/{repo}/git/commits/{sourceVersion} --jq '.parents[0].sha'` - Extracts target branch HEAD from the merge commit's first parent — much simpler than parsing checkout logs - Noted caveat: only works for the latest build (GitHub recomputes merge ref on each push) - Added `get_commit` MCP tool as alternative when available **Inline MCP tool alternatives** (all 4 files) - Added `pull_request_read` as alternative to `gh pr checks` in SKILL.md - Added `search_issues` MCP note in azdo-helix-reference.md - Added `get_commit` MCP note in build-progression-analysis.md - Reframed azure-cli.md with one-sentence MCP-first preamble All changes are minimal inline additions — no structural changes to the skill.
ci-analysis: structured output, MCP integration, and deep investigation guides
Changes to
Get-CIStatus.ps1(+216/-132)[CI_ANALYSIS_SUMMARY]JSON block — structured summary emitted at end of script with all key facts (builds, failed jobs, known issues, PR correlation, recommendation hint)recommendationHintfield in JSON (one of:BUILD_SUCCESSFUL,KNOWN_ISSUES_DETECTED,LIKELY_PR_RELATED,POSSIBLY_TRANSIENT,REVIEW_REQUIRED,MERGE_CONFLICTS,NO_BUILDS)failedJobDetailsto JSON — per-joberrorCategory(test-failure, build-error, test-timeout, crash, tests-passed-reporter-failed, unclassified),errorSnippet, andhelixWorkItemsfailedJobDetailsTruncated— boolean flag indicating when-MaxJobscap meansfailedJobDetailsis incomplete vsfailedJobNamesknownIssuesfrom Build Analysis (not per-job — Build Analysis reports at the PR level, not per-job)Format-TestFailure— catchesTimed Out (timeoutthat was previously invisibletotalFailedJobs,totalLocalFailures,lastBuildJobSummary)continuepaths that skipped itif ($listFiles)→ proper count checkmergeable_statetrimming —gh api --jqoutput trimmed to prevent whitespace comparison failuresWrite-VerboseChanges to
SKILL.md(+97/-144, net reduction)failedJobDetails— per-failure error categories in Interpreting Resultshlx_statushlx_batch_status,hlx_files,hlx_download_urlto recover results from crashed Helix work itemsNew reference files
references/azure-cli.md— Azure CLI deep investigation guidereferences/binlog-comparison.md— binlog comparison workflowreferences/delegation-patterns.md— subagent delegation patterns (5 patterns including parallel artifact extraction and canceled job recovery)references/build-progression-analysis.md— commit-to-build correlation usingtriggerInfo.pr.sourceSha, SQL-based progression tracking, MCP-first with AzDO MCP tools as primaryUpdated reference files
references/manual-investigation.md— fix nonexistentmsbuild-mcp analyzetool refs, use realmcp-binlog-tool-*toolsDesign principles
get_builds,get_build_log_by_id) and Helix MCP tools (hlx_status,hlx_logs) positioned as primary, CLI/script as fallback.references/.Testing
hlx_status,hlx_logs,get_builds,get_build_log_by_idall work