Skip to content

fix(otlp): always emit gen_ai.response.finish_reasons; use GITHUB_SHA as service.version fallback#33528

Merged
mnkiefer merged 2 commits into
mainfrom
copilot/reliability-daily-review-2026-05-20
May 20, 2026
Merged

fix(otlp): always emit gen_ai.response.finish_reasons; use GITHUB_SHA as service.version fallback#33528
mnkiefer merged 2 commits into
mainfrom
copilot/reliability-daily-review-2026-05-20

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 20, 2026

Two P1 observability gaps identified in the 2026-05-20 Daily Reliability Review left 5,187 spans with no finish-reason classification and no version anchor for regression correlation.

gen_ai.response.finish_reasons — always present on agent spans

Previously emitted only when the engine wrote a type: "result" entry to agent-stdio.log. Copilot and Codex do not emit this entry, so 5/7 of the failed runs had no finish-reason at all — impossible to distinguish model truncation from runner termination.

Priority order is now: engine stop_reason"timeout" (timed-out conclusion) → "unknown" (sentinel for engines that never emit a result entry).

// before
const effectiveStopReason = runtimeMetrics.stopReason || (isAgentTimedOut ? "timeout" : undefined);
if (effectiveStopReason) {
  attributes.push(buildArrayAttr("gen_ai.response.finish_reasons", [effectiveStopReason]));
}

// after — always present on agent spans
const effectiveStopReason = runtimeMetrics.stopReason || (isAgentTimedOut ? "timeout" : "unknown");
attributes.push(buildArrayAttr("gen_ai.response.finish_reasons", [effectiveStopReason]));

service.versionGITHUB_SHA as final fallback

Both the setup and conclusion span paths fell through to "unknown" when no gh-aw release tag was available; buildOTLPResourceAttributes explicitly skips "unknown", so Sentry's release field was never populated. GITHUB_SHA is now the last resort before "unknown", giving Sentry a commit anchor for every run.

// conclusion span (setup span mirrors the same pattern)
const version =
  awInfo.agent_version || awInfo.version ||
  process.env.GH_AW_INFO_VERSION ||
  awInfo.cli_version || process.env.GH_AW_INFO_CLI_VERSION ||
  process.env.GITHUB_SHA ||   // ← new
  "unknown";

…SHA as service.version fallback

- gen_ai.response.finish_reasons: always present on agent conclusion spans.
  Previously omitted when the engine didn't write a `stop_reason` to
  agent-stdio.log (copilot, codex). Now falls back to "unknown" so
  length-truncation is always queryable in Sentry/dashboards.

- service.version: add GITHUB_SHA as a final fallback in both the setup
  and conclusion span paths. When no gh-aw release tag is available the
  commit SHA is used, enabling Sentry to populate `release` and surface
  per-commit regressions.

Addresses P1 findings from the 2026-05-20 Daily Reliability Review.

Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com>
@mnkiefer mnkiefer marked this pull request as ready for review May 20, 2026 12:36
Copilot AI review requested due to automatic review settings May 20, 2026 12:36
Copilot AI changed the title [WIP] Update daily reliability review for 2026-05-20 fix(otlp): always emit gen_ai.response.finish_reasons; use GITHUB_SHA as service.version fallback May 20, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates OTLP span emission to improve reliability telemetry completeness by ensuring gen_ai.response.finish_reasons is always present on agent-related spans and by providing a deterministic service.version fallback when a gh-aw version isn’t available.

Changes:

  • Always emit gen_ai.response.finish_reasons on agent spans, defaulting to "unknown" when stop_reason is not available (and "timeout" for timed-out runs).
  • Fall back to GITHUB_SHA for service.version/scope.version in both job setup and job conclusion spans when gh-aw version sources are absent.
  • Update and add tests covering the new fallbacks and the “unknown” finish-reason behavior.
Show a summary per file
File Description
actions/setup/js/send_otlp_span.cjs Adds GITHUB_SHA version fallback for setup/conclusion payload scope/resource versioning; ensures finish reasons are always emitted for agent jobs.
actions/setup/js/send_otlp_span.test.cjs Adds/updates tests validating service.version fallback to GITHUB_SHA and finish_reasons=["unknown"] behavior when stop_reason is missing.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 0

Copilot AI requested a review from mnkiefer May 20, 2026 12:40
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

PR Code Quality Reviewer completed the code quality review.

No action needed: PR #33528 was already merged before this review. Code quality is excellent - no issues found. Changes properly address P1 observability gaps with comprehensive test coverage.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🧪 Test Quality Sentinel completed test quality analysis.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #33528 does not have the 'implementation' label and has 0 new lines of code in default business logic directories (≤100 threshold).

@mnkiefer mnkiefer merged commit d86310a into main May 20, 2026
123 checks passed
@mnkiefer mnkiefer deleted the copilot/reliability-daily-review-2026-05-20 branch May 20, 2026 12:54
@github-actions github-actions Bot mentioned this pull request May 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

PR Code Quality Reviewer completed the code quality review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #33528 does not have the 'implementation' label and has 0 new lines of code in default business logic directories (threshold: 100).

@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 90/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All tests verify behavioral contracts with strong edge case coverage.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /diagnose and /tdd based on this being an observability bug fix with strong test coverage.

Key Themes

Strengths:

  • Root cause properly addressed: The fix directly tackles the conditional emission that left 5,187 spans without finish_reasons
  • Sentry regression correlation: Adding GITHUB_SHA fallback provides the missing commit anchor
  • Test coverage is excellent: New tests for GITHUB_SHA fallback on both setup and conclusion spans
  • Test names are descriptive: Clear intent (e.g., "falls back to GITHUB_SHA for service.version when no gh-aw version is available")
  • Regression prevention: Updated existing test to verify "unknown" is emitted, preventing future regressions

Opportunities:

  1. Sentinel value clarity: "unknown" is generic — consider "no_result_entry" to make dashboards more actionable
  2. Edge case testing: Add test for when GITHUB_SHA itself is unavailable (local dev, non-GitHub runners)
  3. Sentry readability: Consider truncating GITHUB_SHA to 7-8 chars for cleaner Sentry release displays
  4. Test documentation: Add comments distinguishing agent vs conclusion span assertions in the updated test

/diagnose Highlights

This fix follows the discipline loop well:

  • Reproduce: Daily reliability review identified the gap (5,187 missing spans)
  • Root cause: Copilot/Codex engines don't emit result entries
  • Fix: Changed conditional logic to always-emit with sentinel
  • Regression test: Tests now verify the attribute is always present

One gap: No test for the final fallback ("unknown") when all env vars are missing — this would complete the regression coverage.

/tdd Highlights

Test structure is clean and follows best practices:

  • ✅ Descriptive names that read as specifications
  • ✅ Arrange-Act-Assert structure is clear
  • ✅ Tests verify both positive and negative cases
  • ⚠️ Missing edge case: GITHUB_SHA unavailable (see inline comment)

Verdict

APPROVED — This is a solid observability fix with excellent test coverage. The inline suggestions are refinements, not blockers. The fix directly addresses the P1 gaps and provides strong regression protection.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · ● 4.5M

const agentFinishAttr = agentSpan.attributes.find(a => a.key === "gen_ai.response.finish_reasons");
expect(agentFinishAttr).toBeDefined();
expect(agentFinishAttr.value.arrayValue.values).toEqual([{ stringValue: "unknown" }]);

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.

[/tdd] The test verifies that gen_ai.response.finish_reasons is present with value ["unknown"], but it does not verify the conclusion span behavior when stop_reason is absent.

The PR description mentions this affected "5/7 of the failed runs" — the test should validate both the agent span and the conclusion span independently to ensure they both emit the attribute. Currently, lines 3084-3087 test the conclusion span, but consider adding a comment clarifying which span is under test.

Suggestion: Add an explicit assertion comment:

// Agent span should always emit finish_reasons, even when stop_reason is absent
const agentFinishAttr = agentSpan.attributes.find(a => a.key === "gen_ai.response.finish_reasons");

// Conclusion span should mirror the same behavior
const conclusionFinishAttr = conclusionSpan.attributes.find(a => a.key === "gen_ai.response.finish_reasons");

// use "unknown" as a sentinel for engines (e.g. copilot, codex) that do not emit
// a result entry at all, so that gen_ai.response.finish_reasons is always present
// and length-truncation is always queryable in Sentry/dashboards.
const effectiveStopReason = runtimeMetrics.stopReason || (isAgentTimedOut ? "timeout" : "unknown");
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.

[/diagnose] The fix correctly addresses the root cause by making gen_ai.response.finish_reasons always present. However, the sentinel value "unknown" is now conflated with two distinct scenarios:

  1. Engines that never emit a result entry (Copilot, Codex)
  2. Edge cases where the span is emitted before the agent writes a result entry

Consider: Would "no_result_entry" be a more specific sentinel than "unknown"? This would make dashboards more actionable — "unknown" could mean many things, while "no_result_entry" explicitly identifies the Copilot/Codex engine limitation.

Alternative: Document in a comment that "unknown" specifically means "engine did not emit result entry", distinguishing it from other potential unknown states.

const readFileSpy = vi.spyOn(fs, "readFileSync").mockImplementation(() => {
throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
});

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.

[/tdd] This test validates the GITHUB_SHA fallback by mocking readFileSync to simulate missing aw_info.json. Excellent regression coverage!

Edge case to consider: What happens when GITHUB_SHA itself is undefined or empty? This could occur in local development or non-GitHub-hosted runners.

Suggestion: Add a test case:

it("falls back to 'unknown' for service.version when GITHUB_SHA is also unavailable", async () => {
  const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
  vi.stubGlobal("fetch", mockFetch);

  process.env.GH_AW_OTLP_ENDPOINTS = JSON.stringify([{ url: "(traces.example.com/redacted)" }]);
  delete process.env.GITHUB_SHA;
  delete process.env.GH_AW_INFO_VERSION;
  delete process.env.GH_AW_INFO_CLI_VERSION;
  
  const readFileSpy = vi.spyOn(fs, "readFileSync").mockImplementation(() => {
    throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
  });

  await sendJobConclusionSpan("gh-aw.job.conclusion");
  readFileSpy.mockRestore();

  const body = JSON.parse(mockFetch.mock.calls[0][1].body);
  const resourceAttrs = body.resourceSpans[0].resource.attributes;
  expect(resourceAttrs).toContainEqual({ key: "service.version", value: { stringValue: "unknown" } });
});

This ensures the fallback chain is fully tested.

@@ -1627,7 +1627,7 @@ async function sendJobConclusionSpan(spanName, options = {}) {
const effectiveTokens = rawET ? parseInt(rawET, 10) : NaN;
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.

[/diagnose] The GITHUB_SHA fallback correctly provides a commit anchor for Sentry. One observability enhancement to consider:

Current behavior: GITHUB_SHA is a 40-character full commit hash. Sentry release identifiers are typically shorter for readability in dashboards.

Suggestion: Consider truncating to the first 7-8 characters when using GITHUB_SHA as a fallback:

const gitShaFallback = process.env.GITHUB_SHA?.substring(0, 8);
const version = 
  awInfo.agent_version || awInfo.version || 
  process.env.GH_AW_INFO_VERSION || 
  awInfo.cli_version || 
  process.env.GH_AW_INFO_CLI_VERSION || 
  gitShaFallback || 
  "unknown";

This would make Sentry releases more readable while still providing a unique commit anchor. However, full SHAs are also valid — document the decision either way.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🧪 Test Quality Sentinel completed test quality analysis.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Code Quality Review

This PR delivers clean observability improvements with excellent test coverage. Both changes address real gaps in telemetry data collection.

Strengths:

  • Clear problem statement with concrete impact (5,187 spans missing finish-reason)
  • Comprehensive test coverage for both changes
  • Consistent fallback pattern applied across setup and conclusion spans
  • Well-documented rationale in comments

No blocking issues identified. The code is production-ready.

Note: Reviewed post-merge as PR was already merged at review time.

🔎 Code quality review by PR Code Quality Reviewer · ● 2.6M

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /diagnose and /tdd based on this P1 observability bug fix.

Key Themes

Root cause properly addressed: The fix targets the actual problem (Copilot/Codex not emitting type: "result" entries) rather than symptoms

Strong test coverage: Added 2 new tests for GITHUB_SHA fallback behavior and updated existing tests to reflect new "always present" behavior for finish_reasons

Clear instrumentation: Inline comments explain the priority fallback chain and why "unknown" exists as a sentinel value

Positive Highlights

  • ✅ Test naming is descriptive and reads like specifications (e.g., "emits gen_ai.response.finish_reasons=[unknown] on the agent span when stop_reason is absent")
  • ✅ Assertions are precise — using .find() and .toBeDefined() rather than indirect checks
  • ✅ Both code paths (setup span + conclusion span) are validated for the GITHUB_SHA fallback
  • ✅ The PR description clearly documents the impact (5,187 spans affected) and the fix priority

Minor Suggestion (Optional)

I posted one inline comment suggesting a priority order validation test to document the stopReason → timeout → unknown fallback chain in executable form. This is a nice-to-have, not a blocker — the current tests already cover each case individually.

/diagnose Perspective

This fix demonstrates the disciplined debugging loop well:

  1. Reproduce: Identified 5,187 spans missing the attribute
  2. Minimize: Narrowed to Copilot/Codex engines specifically
  3. Hypothesize: Engines don't emit type: "result" entries
  4. Fix: Add "unknown" sentinel as final fallback
  5. Regression test: Updated existing test + added new GITHUB_SHA tests

/tdd Perspective

Test quality is excellent:

  • Tests follow Arrange/Act/Assert pattern consistently
  • Mock setup is clear and isolated per test case
  • Assertions check both the attribute presence and its exact structure
  • Test names are self-documenting

Verdict

No blocking issues. This is a well-executed observability fix with strong test coverage and clear documentation. The optional suggestion is a refinement, not a requirement. Ready to merge once the [WIP] tag is removed.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · ● 3.4M

});

it("omits gen_ai.response.finish_reasons from the agent span when stop_reason is absent in agent-stdio.log", async () => {
it("emits gen_ai.response.finish_reasons=[unknown] on the agent span when stop_reason is absent from agent-stdio.log", async () => {
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.

[/tdd] Consider adding a test that explicitly validates the documented priority order for finish_reasons: stopReason"timeout""unknown". Currently, each case is tested in isolation, but the fallback chain isn't verified in a single test.

Example:

it("applies finish_reasons priority: stopReason → timeout → unknown", async () => {
  const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
  vi.stubGlobal("fetch", mockFetch);

  process.env.GH_AW_OTLP_ENDPOINTS = JSON.stringify([{ url: "(traces.example.com/redacted)" }]);

  // Case 1: stop_reason present (highest priority)
  const stdio1 = JSON.stringify({ type: "result", result: { stop_reason: "end_turn" } }) + "\n";
  fs.writeFileSync("/tmp/gh-aw/test/agent-stdio.log", stdio1, "utf-8");
  await sendJobConclusionSpan("gh-aw.job.conclusion");
  let finishAttr = JSON.parse(mockFetch.mock.calls[0][1].body)
    .resourceSpans[0].scopeSpans[0].spans[0].attributes
    .find(a => a.key === "gen_ai.response.finish_reasons");
  expect(finishAttr.value.arrayValue.values).toEqual([{ stringValue: "end_turn" }]);

  // Case 2: timeout (no stop_reason, agent timed out)
  fs.writeFileSync("/tmp/gh-aw/test/agent-stdio.log", "", "utf-8");
  process.env.GITHUB_AW_AGENT_TIMEOUT_TRIGGERED = "true";
  await sendJobConclusionSpan("gh-aw.job.conclusion");
  finishAttr = JSON.parse(mockFetch.mock.calls[1][1].body)
    .resourceSpans[0].scopeSpans[0].spans[0].attributes
    .find(a => a.key === "gen_ai.response.finish_reasons");
  expect(finishAttr.value.arrayValue.values).toEqual([{ stringValue: "timeout" }]);

  // Case 3: unknown (no stop_reason, not timed out)
  delete process.env.GITHUB_AW_AGENT_TIMEOUT_TRIGGERED;
  await sendJobConclusionSpan("gh-aw.job.conclusion");
  finishAttr = JSON.parse(mockFetch.mock.calls[2][1].body)
    .resourceSpans[0].scopeSpans[0].spans[0].attributes
    .find(a => a.key === "gen_ai.response.finish_reasons");
  expect(finishAttr.value.arrayValue.values).toEqual([{ stringValue: "unknown" }]);
});

This would serve as executable documentation of the fallback chain and catch regressions if the priority order ever changes unintentionally.

@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 90/100

Excellent test quality

Metric Value
New/modified tests analyzed 3
✅ Design tests (behavioral contracts) 3 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 3 (100%)
Duplicate test clusters 0
Test inflation detected Yes (5.5:1 ratio)
🚨 Coding-guideline violations 0

Test Classification Details

Test File Classification Issues Detected
falls back to GITHUB_SHA for service.version when no gh-aw version is available actions/setup/js/send_otlp_span.test.cjs:~1825 ✅ Design None
emits gen_ai.response.finish_reasons=[unknown] on the agent span when stop_reason is absent from agent-stdio.log actions/setup/js/send_otlp_span.test.cjs:~3056 ✅ Design None
falls back to GITHUB_SHA for service.version on conclusion span when no gh-aw version is available actions/setup/js/send_otlp_span.test.cjs:~3955 ✅ Design None

Analysis

All three test changes in this PR are high-quality design tests that verify behavioral contracts:

✅ Test 1: GITHUB_SHA fallback for service.version (setup span)

What design invariant does this test enforce?
When both GH_AW_INFO_VERSION and GH_AW_INFO_CLI_VERSION environment variables are unavailable, the system must fall back to GITHUB_SHA for the service.version attribute in OTLP spans.

What would break if deleted?
A regression where the fallback to GITHUB_SHA doesn't work would go undetected, causing spans to report "unknown" as the version even when GITHUB_SHA is available.

Why it's a design test:
Verifies observable OTLP span attributes (the API contract with observability systems), not internal implementation details.

✅ Test 2: gen_ai.response.finish_reasons always present

What design invariant does this test enforce?
The gen_ai.response.finish_reasons attribute must ALWAYS be present on agent and conclusion spans. When stop_reason is absent from agent-stdio.log, the system should emit ["unknown"] as a sentinel value (not omit the attribute).

What would break if deleted?
A regression where finish_reasons becomes optional again, breaking observability queries that depend on this attribute always being present for length-truncation analysis.

Why it's a design test:
This test was updated to match a behavioral change in the production code. The previous behavior (omitting the attribute) was incorrect for observability; the new behavior (always present with "unknown" sentinel) is now the contract.

✅ Test 3: GITHUB_SHA fallback for service.version (conclusion span)

What design invariant does this test enforce?
Conclusion spans must also fall back to GITHUB_SHA for service.version when version information is unavailable (including when aw_info.json is missing).

What would break if deleted?
A regression in the conclusion span version fallback logic would go undetected, potentially causing inconsistent version reporting between setup and conclusion spans.

Why it's a design test:
Verifies the same behavioral contract as Test 1 but for a different span type, ensuring consistency across the telemetry API.


Test Inflation Note

⚠️ Test inflation detected: 5.5:1 ratio (44 test lines added / 8 production lines added)

While this exceeds the 2:1 threshold (resulting in a 10-point penalty), the inflation is contextually justified:

  • Production changes are minimal (adding process.env.GITHUB_SHA to fallback chains)
  • Test coverage is comprehensive (both setup and conclusion span types, plus edge cases like missing files)
  • All tests are high-value design tests with no duplication
  • The ratio reflects thorough coverage of behavioral changes, not wasteful test generation

Language Support

Tests analyzed:

  • 🟨 JavaScript (*.test.cjs): 3 tests (vitest)

Verdict

Check passed. 0% of tests are implementation tests (threshold: 30%). All tests verify behavioral contracts with proper edge case coverage.


📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

🧪 Test quality analysis by Test Quality Sentinel · ● 9.6M ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 90/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All tests verify behavioral contracts with proper edge case coverage.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[reliability] Daily Reliability Review - 2026-05-20

3 participants