# Metric Empty Trust And Bounded Repair

<!-- auto-oncall-optimization-record
{
  "schemaVersion": "auto-oncall-optimization-record-v1",
  "optimizationId": "metric-empty-trust-repair-2026-08-13",
  "problems": [
    {
      "problemId": "metric-empty-conflates-valid-absence-with-selector-gap",
      "summary": "A successful metric query with no series was always treated as one generic complete gap, so a normal sparse absence and an expected baseline hidden by a wrong selector could not be distinguished or repaired before diagnosis.",
      "status": "optimized_unverified",
      "applicability": "Clinic, Wetech, or Manus metric acquisition where an existing metric family returns no series and the Evidence Agent must classify the absence or perform the one bounded expected-baseline selector or label validation before Scenario Diagnostic Agent judgment.",
      "issueKeys": ["APID-29259"],
      "sourceRefs": ["https://tidb.atlassian.net/browse/APID-29259#problem:metric-empty-selector-ambiguity"],
      "signalTextIncludesAny": ["metric empty", "wrong label", "wrong selector", "unexplained empty", "APID-29259"],
      "observedThrough": "2026-08-14",
      "effectiveAt": "2026-08-13T16:21:27.000Z",
      "verifiedAt": null,
      "attemptedAction": "Require every metric plan to declare expected baseline, trusted sparse, or unknown empty semantics; materialize one queryCoverage classification; and give an expected baseline exactly one same-round same-family selector or label validation before Scenario Diagnostic Agent load-bearing judgment.",
      "evidenceUrl": "https://github.com/tidbcloud/aisupport/pull/897"
    }
  ]
}
-->

- Owner: auto-oncall-services Evidence Agent and Provider Executor contracts
- Source: APID-29259 metric-empty investigation
- Implementation status: merged and effective in staging
- Effectiveness status: `optimized_unverified`

## Bounded problem

The provider already distinguishes a rejected or nonexistent metric family as
failed. When an existing metric family returns no series, however, the same
empty shape can mean either a valid absence of a sparse event or a wrong
selector/label on a baseline that should be present. Treating both as one
generic complete gap can suppress a useful repair or let diagnosis read a query
mistake as negative evidence.

## Change

- The Evidence Agent declares one empty expectation for every metric plan:
  expected baseline, trusted sparse event, or unknown.
- The Provider Executor materializes that declaration once in `queryCoverage`
  as `unexplained_empty`, `verified_empty`, or `unclassified_empty`; no parallel
  diagnosis field is added.
- An unexplained expected-baseline empty receives one minimal same-family
  selector/label validation in the same acquisition round. A second empty
  remains unexplained. Sparse and unknown empties are not automatically retried.
- All empty classes remain transport-complete. Provider rejection remains
  failed. Scenario Diagnostic Agent decides only whether the resulting gap is
  load-bearing and never selects provider syntax.

## Deployment and verification

Local contract tests cover all three empty classes, preservation of a failed
metric-family query as failed, propagation through Clinic/Wetech/Manus helpers,
and exactly one same-round validation before scenario diagnosis.

The implementation merged in
[aisupport PR #897](https://github.com/tidbcloud/aisupport/pull/897) as
`dc09e37c265b1c51ec0b2c376fafa4048710b74d`. The staging deploy workflow
[run 31716790562](https://github.com/tidbcloud/aisupport/actions/runs/31716790562)
completed successfully, and
[app-delivery PR #77263](https://github.com/tidbcloud/app-delivery/pull/77263)
merged the staging registration. Staging now runs the valid successor image
`fb13c641f6e5defe650d7072dfb544dccf547bab`. After the Clinic PVC publication,
the bundled, PVC, and installed `clinic-api/SKILL.md` all read back as
`7c4524b18d47f982ab84c3d3ddada8687d3131c8781c11e505799bc8601bf016`.
The replacement Pod became Ready at `2026-08-13T16:21:27.000Z`; this is the
effective timestamp for the complete cross-provider change.

Post-change read-only evidence:

- APID-29259 run `1fb2d313-5133-41b8-8911-c077bdad2e02` passed the
  expected-non-empty control: empty TiKV process CPU and quota queries remained
  `unexplained_empty`, received the bounded same-family presence validation,
  and were retained as gaps rather than negative evidence.
- APID-29338 run `77e9c2c8-ac59-451a-a9bb-9777dae00fe9` passed the core
  empty regression: non-empty queries remained `complete`, while empty metric
  results remained explicit `unclassified_empty` gaps without becoming a
  provider failure. No query declared `sparse_allowed`, so the
  `sparse_allowed -> verified_empty` path was **not covered**.
- APID-29274 run `f60162a3-f935-4308-9df0-6d9461fa8461` passed the mixed
  empty/non-empty control: non-empty metric queries remained `complete` and
  empty controls remained `unclassified_empty`. The overall case still failed
  because of two independent pre-existing defects: `comparison_window` labels
  were dropped between compact report and Scenario input, and benign Scenario
  prose matched the SQL-sensitive-text validator. That case failure is not
  attributed to this empty-result optimization and does not create a new
  optimization record here.

These runs prove the deployed classification behavior but do not cover a real
trusted sparse empty, and the applicable Jira internal comment refresh and
readback remain incomplete. This record therefore remains
`optimized_unverified`, not `optimized_verified`.

## Unresolved gap and next action

Exercise one real metric plan whose provider contract justifies
`sparse_allowed`, and verify that an empty result materializes exactly once as
`verified_empty` without a repair attempt. Separately complete the applicable
historical owner-job Jira internal comment refresh and read back the same
`public=false` comment ID. Track the APID-29274 comparison-label and sensitive-
text defects independently; they must not be folded into this optimization or
used to mark its empty-result behavior ineffective.
