Skip to content

fix(ci): Publish multi-test flaky causes to one issue - #20333

Open
Ankit Jain (radical) wants to merge 3 commits into
microsoft:mainfrom
radical:fix-ci-cause-issue-tracking
Open

Ankit Jain (radical) wants to merge 3 commits into
microsoft:mainfrom
radical:fix-ci-cause-issue-tracking

Conversation

@radical

@radical Ankit Jain (radical) commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Summary

CI failure tracking treated the test that happened to fail as the durable
identity of the failure. That breaks when one mechanism affects several tests,
or later appears under a different test or job.

Before: failing test name → cause ID → tracking issue

After:  failure mechanism → stable cause ID → tracking issue
        exact {test name, numeric job ID} → evidence for each occurrence

Tests and jobs now describe where a failure was observed. The underlying
mechanism identifies the long-lived cause and issue.

What broke

#19455 correctly made CI attribution and publication fail closed, but left one
scalar test_name serving as both cause identity and display text.

That model could not represent two valid cases:

  1. Several tests fail because of the same underlying mechanism.
  2. The same mechanism recurs later under a different test or job.

When analysis grouped several browser-debugger timeouts, publication looked for
one test with the combined display name and stopped:

Flaky-test cause must reference a validated flaky test

The run received neither its expected issue occurrence nor its analysis
comment. A later recurrence under another test could also create a duplicate
cause issue instead of extending the existing one.

Why this model

Decision Reason
A cause ID represents the failure mechanism. Test and job names can change between occurrences, but the issue should remain attached to the same underlying problem.
Each occurrence stores exact test and numeric job evidence. Publication can authenticate what actually failed without turning that observation into permanent identity.
The analyzer decides whether diagnostics match an existing mechanism. An exact fingerprint would split legitimate recurrences; fuzzy publisher matching could merge unrelated failures.
Persisted memory owns occurrence history. Issue text is editable and retries can happen after partial failures, so publication must be reproducible from trusted stored evidence.

The publisher therefore verifies trusted evidence, unique ownership, and stored
identity. It does not guess whether two similar failures share a root cause.

Legacy data

Existing cause history is preserved rather than rewritten into the new
shape.

  • Stored cause IDs, diagnostics, issue links, occurrence dates, and
    operator-authored notes remain intact.
  • Legacy records without an attempt retain their run-only link until trusted
    replay evidence identifies the attempt. Known attempts use exact
    /attempts/N links, including attempt 1, so later retries cannot change what
    a historical row points to.
  • Historical test_name and job labels remain descriptive evidence. They are
    not promoted into new verified identity or assigned invented numeric job IDs.
  • Historical rows can recover a missing main scope only from the matching
    trusted run summary. Otherwise missing context renders as unavailable;
    editable issue text is not used to guess it.
  • Authenticated main scope wins over stale legacy PR metadata. Invalid cached
    contexts such as #0 are rebuilt rather than preserved.
  • Older issue tables migrate on the next publication. When old data lacks the
    new display fields, rows are derived deterministically from stored legacy
    evidence, never from editable issue text or fresh analyzer output.
  • Ambiguous legacy issue layouts fail closed rather than risking deletion of
    human-authored content.

This keeps existing tracking issues useful while allowing future occurrences to
use the stronger evidence model.

Issue history and recovery

The issue body is a projection, not a second occurrence database. Rebuilding it
from persisted history means retries can repair stale, edited, missing,
duplicate, or previously trimmed rows without changing the underlying evidence.

Text outside the managed occurrence section remains operator-owned. Pull-request
code failures also remain PR-comment-only; this change does not turn them into
persistent cause issues.

Regression coverage

The 427 passing workflow tests cover:

  • mechanism grouping, distinct-cause isolation, and exact test/job ownership;
  • legacy enrichment, immutable replay, partial-publication recovery, and issue
    recreation from stored history;
  • exact attempt links, trusted historical scope recovery, bounded rendering,
    operator-note preservation, and deterministic fallback for malformed legacy
    context.

The generated workflow was regenerated with the repository-pinned gh-aw v0.88.7
compiler. No action pin changed.

Fixes #20332

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 20333

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 20333"

@github-actions github-actions Bot added the area-engineering-systems infrastructure helix infra engineering repo stuff label Sep 22, 2026
@aspire-repo-bot
aspire-repo-bot Bot requested a balanced review from Copilot September 22, 2026 23:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The critical job-identity flaw and moderate legacy-rendering issue must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 High severity

Open (1)
What changed in this PR

Updates CI failure analysis to group multiple verified flaky tests under stable causes while preserving occurrence history and distinct run attempts.

Changes:

  • Validates unique {test, job} cause assignments.
  • Stores and renders verified tests per occurrence.
  • Adds regression coverage and regenerates workflow metadata.
  • Critical: Validation relies on non-unique job display names, potentially persisting PR-caused failures as flaky issues.
  • Moderate: Legacy causes omit verified tests from rendered occurrence rows because the renderer lacks the existing fallback.
File Description
tests/​Infrastructure.Tests/​WorkflowScripts/​AnalyzeCiFailureWorkflowTests.cs Adds validation, persistence, rendering, and attempt regression tests.
docs/​ci/​analyze-ci-failure.md Documents grouped cause behavior.
.github/​workflows/​analyze-ci-failure.md Updates publishing logic and agent instructions.
.github/​workflows/​analyze-ci-failure.lock.yml Regenerates the compiled workflow.
.github/​workflows/​analyze-ci-failure-validation.sh Validates observations; contains the critical job-identity issue.
.github/​workflows/​analyze-ci-failure-persistence.sh Persists occurrences; contains the moderate legacy-rendering issue.
.github/​workflows/​analyze-ci-failure-issue.sh Renders verified tests in issues.
.github/​aw/​actions-lock.json Updates gh-aw version metadata.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/analyze-ci-failure-validation.sh
@radical

Copy link
Copy Markdown
Member Author

[automated] Addressed the scalar-form occurrence-row finding from Copilot review in cc5bf4c. When a current-run flaky cause uses the supported test_name format, the new issue row now displays that verified test under each trusted job. Historical labels are still not used as evidence. Added a two-job regression test.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Legacy flaky causes can omit test names from issue occurrence rows.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Restore legacy tests fallback in cause-job-names

.github/​workflows/​analyze-ci-failure-persistence.sh:1177

cause-job-names is called on the current cause file before add-occurrence, but this expression only reads .tests. The validator still accepts legacy flaky files without tests (the fallback at validation lines 503-504), and add-occurrence converts their test_name/job_ids into verified occurrence tests; therefore a valid legacy cause produces an issue occurrence row with only the job name and drops the test name. Build the legacy $tests fallback here as well so all issue rows show the verified tests.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Two moderate issues can omit or leave stale verified test evidence in issue output.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

Comment thread .github/workflows/analyze-ci-failure-persistence.sh Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Two moderate publication and evidence-rendering issues remain unresolved.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Update legacy issue rows when enriching replay occurrences

.github/​workflows/​analyze-ci-failure.md:1006

When an attempt-1 replay enriches a legacy occurrence, OCCURRENCE_URL is the same base URL that the old run-only row already contains. This branch therefore skips the issue edit, so the persistent occurrence gains the verified tests but the linked issue continues to show the stale row without that evidence. Treat a matching legacy row as an enrichment/update (while still skipping an already-modern row), and add a publication regression test for this path.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@radical

Copy link
Copy Markdown
Member Author

[automated] Addressed the legacy issue-row migration finding in d87e8f1. Legacy attempt-1 enrichment now persists a refresh marker until the stale managed issue row is successfully replaced or a new issue is created. Replay reconstructs the row from persisted observations, preserves the original observation time, avoids duplicate edits when already current, retains the marker on unsupported bodies, and keeps modern occurrences immutable. Added end-to-end lifecycle and maximum-boundary coverage.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Two moderate issue-rendering and persistence defects remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (1)

Comment thread .github/workflows/analyze-ci-failure-issue.sh Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Three moderate validation and persistence issues remain unresolved.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Replay rendering uses mutable data instead of stored occurrence

.github/​workflows/​analyze-ci-failure-persistence.sh:1270

Only the legacy issue_row_needs_refresh path switches SOURCE_CAUSE_FILE to stored occurrence data. For an already-modern occurrence, merge-cause deliberately ignores a replay, but if memory was pushed and issue publication failed before its row existed, this default renders from the replay's CAUSE_FILE observations and date. A changed agent result can therefore publish an issue row that disagrees with the immutable stored occurrence; select the matching stored {run_id, run_attempt} occurrence for every replay when building display data, and add a missing-row regression.

@radical

Copy link
Copy Markdown
Member Author

[automated] Addressed the replay-publication inconsistency in aa07555e492.

Publication now reads the matching stored occurrence's date, URL, context, test evidence, and persisted job ordering. A retry after memory has been pushed can no longer render a different issue row for the same immutable run attempt. Historical non-flaky occurrences without numeric job IDs retain a safe fallback, and the replay/migration contracts cover both missing and existing managed rows.

The same commit disables gh-aw's per-run failed custom-job issue reporter for Analyze CI Failure and PR Documentation Check. This prevents duplicate [aw] Failed jobs issues such as #20352 and #20353 while retaining gh-aw's category-based agent failure reporting.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Three moderate issues remain in legacy-label validation and replay-history ordering.

Review effort: Balanced
Findings: None

@aspire-repo-bot
aspire-repo-bot Bot requested a balanced review from Copilot September 23, 2026 05:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Persistence replay can alter legacy display labels and does not validate run attempts against run URLs.

Review effort: Balanced
Findings: None

Resolved since last review (2)

@radical

Copy link
Copy Markdown
Member Author

[automated] Followed up on the latest Copilot review overview in 20fe33cad5d.

  • Issue recreation now retains the authoritative historical grouped job label after the refresh marker is cleared.
  • Legacy enrichment preserves valid stored PR context and run scope.
  • Stored run ID, attempt, and URL must identify the same attempt. Only an absent legacy attempt defaults to attempt 1; malformed explicit values fail before merge persistence.

The live memory branch contains 143 cause files and 471 occurrences; all existing rows remain compatible with the stricter validation. The full workflow contract suite passes: 391 tests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Three moderate legacy persistence and rendering issues must be addressed before approval.

Review effort: Balanced
Findings: None

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

PR context validation and legacy scope reconstruction do not consistently fail closed.

Review effort: Balanced
Findings: None

Previously missed (1)

In code that hasn't changed since last review

Medium severity Reject string pr_number values during legacy reconstruction

.github/​workflows/​analyze-ci-failure-persistence.sh:1016

The fallback has the same jq type-coercion bug: a legacy pr_number stored as the string "41" satisfies > 0 and is emitted as a valid-looking #41 context instead of unavailable. This lets malformed persisted context survive issue-row reconstruction; validate the JSON type and integer range before rendering it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Two moderate legacy-context projection issues must be corrected before approval.

Review effort: Balanced
Findings: None

@radical

Copy link
Copy Markdown
Member Author

[automated] Addressed the latest Copilot review finding in 4576a2abf54.

Legacy PR context now accepts only positive integral JSON numbers in occurrence
backfill, stored-row reconstruction, and replay publication. Strings, nulls,
booleans, zero, negatives, fractions, and collection values are treated as
missing context, preserving the authenticated main or unavailable fallback
instead of rendering a valid-looking PR reference or blocking publication.

Positive and negative coverage now exercises all three paths. The workflow
contract suite passes: 409 tests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Three moderate issues can publish incorrect or unauthenticated run and PR context.

Review effort: Balanced
Findings: None

CI failure issues previously treated a test label as durable cause
identity, so grouped failures and legacy issue rows could be split,
overwritten, or reconstructed from editable issue text.

Persist stable cause IDs separately from occurrence evidence, rebuild
managed rows from authenticated memory, validate canonical run-attempt
URLs, and preserve verified legacy display and context metadata during
replay.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add contract coverage for grouped failures, canonical occurrence
validation, immutable replay metadata, legacy row recovery, malformed
persisted data, and failure-side effects.

The positive and negative cases verify that valid history is preserved
while untrusted or ambiguous data fails closed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Document the distinction between durable cause identity and occurrence
evidence, the persisted-memory trust boundary, canonical history format,
and legacy recovery and fallback behavior.

This captures the invariants future workflow changes must preserve.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The extensive persistence, legacy migration, and external issue-publication changes warrant final human review despite comprehensive regression coverage.

Review effort: Balanced
Findings: None

@radical

Copy link
Copy Markdown
Member Author

[automated] Extended CI confidence requires action.

Reviewer actions

  • Required before merge: run the final Analyze CI Failure workflow in a safe trial repository.
    Done when: the run uses PR head e36b4fed7e45af370e19335e1389dcb241a940ad, groups multiple tests under one cause, replays stored history correctly, rejects mismatched evidence, and records the run link on fix(ci): Publish multi-test flaky causes to one issue #20333.
Ready-to-use pr-testing prompt

Use the pr-testing skill to test PR #20333. Focus on representative execution of the final Analyze CI Failure agentic workflow in a safe trial repository. Exercise one failure mechanism observed in multiple tests/jobs, immutable replay and legacy migration, and a negative case with untrusted or mismatched test/job evidence. Verify the published safe outputs create or update one cause issue, preserve stored occurrence history, and fail closed for invalid evidence. Do not mutate microsoft/aspire.

Change classification

  • Agentic CI workload: .github/workflows/analyze-ci-failure.md and its generated lock change analyzer instructions and publication behavior.
  • Workflow persistence and publication: three shell helpers now authenticate multi-test/job observations, preserve legacy history, and rebuild managed issue rows.
  • Contract coverage: AnalyzeCiFailureWorkflowTests.cs adds extensive positive, replay, migration, malformed-input, and fail-closed cases.

Confidence at a glance

🔴 Agentic workflow execution — No representative final-head run
  • Why it applies: The changed agent instructions decide cause identity, associate trusted test/job evidence, and drive issue comments, issue creation, and memory-branch persistence. These are load-bearing mutation and fail-closed behaviors.
  • Evidence: No Analyze CI Failure workflow run exists for the PR branch or final head. Its workflow_run trigger is restricted to main, so normal PR CI cannot execute the changed workflow.
  • Gap or disposition: The tests validate scripts, fixtures, schemas, and generated wiring, but do not prove that the agent makes the intended semantic grouping decision or emits the correct safe output.
  • Action: Run the trial-repository scenario described above. The upstream workflow has real issue and branch side effects and should not be dispatched merely for validation.
🟢 Workflow contract and script tests — Final-head coverage passed
  • Why it applies: The PR changes validation, persistence, issue rendering, replay, and legacy migration scripts.
  • Evidence: Final-head CI run 36024774769 tested SHA e36b4fed7e45af370e19335e1389dcb241a940ad.
  • Observed result: All 1,465 Infrastructure.Tests cases passed, including all 427/427 AnalyzeCiFailureWorkflowTests cases. The downloaded TRX reports zero failures.
  • Coverage: Includes multi-test ownership, distinct-cause isolation, immutable replay, issue recreation, legacy migration, malformed rows and URLs, operator-content preservation, and invalid evidence rejection.
🟢 Agentic workflow compilation — Final source and lock are synchronized
  • Why it applies: Both the gh-aw Markdown source and generated .lock.yml changed.
  • Evidence: In a disposable checkout at the exact PR head, repository-pinned gh aw v0.88.7 successfully ran gh aw compile --validate and gh aw compile analyze-ci-failure.
  • Observed result: Recompilation produced an empty lock-file diff and a clean working tree.
  • Disposition: Compiler warnings were pre-existing advisory checks; none indicated lock drift or compilation failure.
🟢 CI graph, gating, and dependency pins — No silent coverage loss found
  • Why it applies: Changed helpers feed the Analyze CI Failure workflow and its issue/memory publication path.
  • Evidence: Consumer tracing found the changed helpers are consumed by the workflow source/generated lock and their Infrastructure test harnesses. No artifact name, downstream workflow contract, trigger, permission, if:, needs:, or continue-on-error change was introduced.
  • Coverage-loss audit: The workflow remains main-only for automatic workflow_run execution and retains manual workflow_dispatch; this PR did not narrow existing coverage.
  • Action pins: No uses: pin changed against the PR merge base, so no new action-provenance or allow-list validation is required.
⚪ Internal pipeline, outerloop, and deployment validation — Not applicable
  • Evidence: The diff does not change or feed internal Azure DevOps build/signing/publishing infrastructure, outerloop tests or execution plumbing, or deployment E2E scenarios and runtime inputs.
  • Disposition: No definition-1602, outerloop, or deployment run is required for this PR.

@radical

Copy link
Copy Markdown
Member Author

[automated] PR testing report

PR Testing Report

PR Information

Artifact Version Verification

  • Expected Commit: e36b4fed7e45af370e19335e1389dcb241a940ad
  • Tested Source: Detached worktree at the exact PR head
  • Live Workflow: PR-head analyze-ci-failure.md, recompiled with gh-aw v0.88.7
  • Trial-only adaptation: Changed the repository-owner activation gate from
    microsoft to radical; the analysis, validation, persistence, issue, and
    safe-output logic was unchanged.
  • Status: ✅ Verified

Changes Analyzed

Files Changed

  • .github/workflows/analyze-ci-failure-issue.sh
  • .github/workflows/analyze-ci-failure-persistence.sh
  • .github/workflows/analyze-ci-failure-validation.sh
  • .github/workflows/analyze-ci-failure.lock.yml
  • .github/workflows/analyze-ci-failure.md
  • docs/ci/analyze-ci-failure.md
  • tests/Infrastructure.Tests/WorkflowScripts/AnalyzeCiFailureWorkflowTests.cs

Change Categories

  • GitHub Actions / gh-aw agentic workflow
  • Safe-output validation and publication
  • Cause persistence and issue rendering
  • Focused infrastructure tests
  • Product CLI, hosting, dashboard, component, or template changes

Static and Automated Validation

Focused Infrastructure.Tests

Command:

dotnet test --project tests/Infrastructure.Tests/Infrastructure.Tests.csproj \
  --no-launch-profile -- \
  --filter-class '*.AnalyzeCiFailureWorkflowTests' \
  --filter-not-trait 'quarantined=true' \
  --filter-not-trait 'outerloop=true'

Result: ✅ Passed, 427/427 tests in 2m 01s.

gh-aw Compilation

Command:

gh aw compile analyze-ci-failure --validate --actionlint --shellcheck
git --no-pager diff --exit-code -- \
  .github/workflows/analyze-ci-failure.lock.yml

Result: ✅ Compilation, actionlint, and shellcheck passed. Recompilation
produced no lock-file diff. The compiler emitted only existing advisory
warnings about the shared dispatch conclusion concurrency group and
actions/checkout@v6.0.3.

Test Scenarios Executed

Scenario 1: One mechanism across multiple tests and jobs

Objective: Verify three failed tests in two jobs with the same browser
debugger timeout are grouped into one recurring cause and one cause issue.

Coverage Type: Happy path / representative live execution

Status: ✅ Passed

Runs:

Observed trusted evidence:

  • Trial.Tests.FirstTimeout in SharedMechanismA (ubuntu-latest)
  • Trial.Tests.SecondTimeout in SharedMechanismA (ubuntu-latest)
  • Trial.Tests.ThirdTimeout in SharedMechanismB (ubuntu-latest)
  • All three contained the same trusted error and stack:
    Browser debugger timed out waiting for the DevTools endpoint.

Published result:

Trial fixture note: The first automatic analysis run
https://github.com/radical/aspire-ci-failure-trial-20333/actions/runs/36190146998
reached the final publisher but failed because the empty trial repository did
not yet contain the expected test-failure label. Adding that repository
fixture and replaying the same immutable CI attempt completed successfully.
This was a trial-repository setup gap, not a PR failure.

Scenario 2: Immutable replay

Objective: Replay the same run and attempt after the occurrence had already
been persisted.

Coverage Type: Replay / idempotency

Status: ✅ Passed

Steps:

  1. The first publisher attempt persisted run 36190131954, attempt 1.
  2. The workflow was manually dispatched again for run 36190131954.
  3. The replay completed successfully.

Result:

  • The stored cause still contained exactly one occurrence for
    (run_id=36190131954, run_attempt=1).
  • The occurrence retained its attempt-specific URL, trusted job IDs, tests,
    issue table projection, and main context.
  • The cause issue was created from the stored occurrence without duplicating
    history.

Scenario 3: Legacy migration and occurrence preservation

Objective: Verify the publisher migrates a legacy occurrence table while
retaining memory-authoritative history and human operator notes.

Coverage Type: Legacy migration / update path

Status: ✅ Passed

Runs:

Seeded legacy state:

  • A pre-attempt occurrence with no run_attempt
  • Legacy scalar test_name and grouped job label
  • An issue body with the old PR occurrence-table header and no managed
    occurrence markers
  • An operator note:
    [automated] Preserve this trial operator note during legacy migration.

Result:

  • The cause issue was updated in place; no second cause issue was created.
  • The legacy table was replaced by the canonical managed occurrence section.
  • All three histories were retained:
    1. Seeded legacy occurrence
    2. Original immutable occurrence
    3. New CI occurrence
  • The operator note was preserved unchanged.
  • Modern occurrences retained exact trusted {test, job_id} evidence.
  • The legacy occurrence remained explicitly unavailable for context rather
    than being reconstructed from editable issue text.

Scenario 4: Mismatched and untrusted test/job evidence

Objective: Verify invalid agent-supplied cause observations fail before
publication or persistence.

Coverage Type: Negative / trust boundary

Status: ✅ Passed

Cases:

  1. Rebound the real Trial.Tests.FirstTimeout test from its trusted job to the
    other failed job's ID.
  2. Added an untrusted Attacker.Tests.Injected observation to a real failed
    job ID.

Result:

Both exact PR-head validator executions exited 1 with:

::error::Cause browser-debugger-timeout.json references an unknown or incompatible failed job or test

The trial repository state was unchanged after both attempts:

  • Memory branch remained at
    edf18f8911521842fc1900e1056af1082167e30e
  • Cause issue updatedAt remained 2026-09-25T21:30:54Z
  • Cause-issue count remained exactly 1

CI Infrastructure Validation

What runs on the Aspire PR: The focused
AnalyzeCiFailureWorkflowTests class ran in PR CI and was also rerun locally
against the exact PR head.

Manual/live validation: The gh-aw workflow was compiled and executed in a
private trial repository because the production workflow is intentionally
owner-gated and performs real issue and memory-branch mutations. No workflow or
issue was created in microsoft/aspire.

Results validation: Verified the final publisher's observable outputs, not
only run status:

  • Trusted TRX artifacts were selected by job/artifact naming contract.
  • The agent emitted one cause covering all exact test/job pairs.
  • Safe-output validation passed for valid evidence.
  • The publisher created and updated one cause issue.
  • Memory retained immutable and legacy occurrence history.
  • Invalid evidence failed before any remote mutation.

Dependency graph: Synthetic CI push failure → workflow_run activation →
trusted collection and artifact extraction → agent analysis → safe-output
validation → memory branch push → cause issue create/update.

gh-aw: compile --validate --actionlint --shellcheck passed and the PR lock
file regenerated without drift.

Failure-mode scan:

  • Repository-owner gate was adapted only in the private trial.
  • Required issue labels were provisioned in the otherwise empty repository.
  • Workflow-run analysis used the default-branch compiled workflow.
  • Test artifacts were uniquely selected per failed job and attempt.
  • Same-run replay did not duplicate the occurrence.
  • Mismatched and injected evidence failed closed.
  • Issue text was not used as trusted history during migration.

Summary

Scenario Status Notes
Focused Infrastructure.Tests ✅ Passed 427/427
gh-aw lock regeneration ✅ Passed No diff
Multi-test/multi-job shared cause ✅ Passed One cause issue
Immutable replay ✅ Passed One occurrence for the same attempt
Legacy migration ✅ Passed Three rows and operator note preserved
Mismatched test/job evidence ✅ Passed Rejected before publication
Untrusted test evidence ✅ Passed Rejected before publication

Overall Result

✅ PR VERIFIED

PR #20333's final workflow grouped multiple verified failures from different
jobs into one cause issue, preserved immutable and legacy occurrence history,
migrated the issue safely, and rejected invalid evidence without mutating
published state.

Artifacts

  • pr20333-evidence/cause-issue.json
  • pr20333-evidence/stored-cause.json
  • pr20333-evidence/runs.json
  • pr20333-evidence/mismatched-test-job-validation.log
  • pr20333-evidence/untrusted-test-validation.log
  • pr20333-evidence/initial-fixture-failure.log

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-engineering-systems infrastructure helix infra engineering repo stuff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[automated] CI failure analysis rejects grouped flaky causes and skips issue updates

2 participants