# Manus OP query contract

## Current design

| Capability | Canonical source | Read path |
|---|---|---|
| `vida` metrics | Grafana datasource named `vida` | Grafana datasource API, then Prometheus `query_range` proxy |
| `monica` metrics | Dedicated Prometheus endpoint | Direct Prometheus `query_range` |
| Logs | TiDB Dashboard log search | topology discovery, task-group create/poll, preview |
| TopSQL | TiDB Dashboard TopSQL | one explicit instance, then summary |
| Slow query | TiDB Dashboard slow-query API | available fields, then slow-query list |
| SQL statements | TiDB Dashboard statements API | statements list |

The public OP aliases redirect to Manus-specific hosts. `data/targets.json` stores the final direct endpoints so the client does not depend on browser redirects.

## Risks

- Queries from a non-allowlisted egress IP return an IP allowlist error.
- Wide windows and high-cardinality PromQL can overload the bounded read path
  or return a gateway timeout.
- Choosing a default or fuzzy-matched Grafana datasource can silently query the wrong cluster.
- Wide TopSQL, slow-query, statement, and log windows can be expensive or time out.
- Dashboard credentials and tokens must not leak through command arguments, stdout, or evidence.
- Log search is asynchronous and necessarily creates temporary task state in Dashboard.

## Target contract and invariants

- Target configuration is the only endpoint source. `vida` uses its exact
  Grafana datasource; `monica` uses its exact direct Prometheus endpoint.
- Reads never rewrite target configuration.
- There is no fallback to Clinic, another cluster, or Grafana's default datasource.
- Dashboard credentials come only from target-specific environment variables.
  `vida` and `monica` never share or fall back across credential scopes.
  Passwords are RSA PKCS#1 v1.5 encrypted before login; tokens remain in memory.
- The client uses direct HTTPS from the auto-oncall process; it has no kubectl, browser, copied-cURL, or proxy fallback.
- Stdout is compact JSON. Raw payloads are written only when `--output-dir` is explicit.
- OP provider commands never run concurrently. An auto-oncall Evidence Agent
  submits one bounded batch plan; the runner-owned Provider Executor invokes
  the provider helper, which executes its queries and
  bounded retries strictly serially and writes one atomic compact batch result.
  The default metric window is 20 minutes; for a known incident time, callers
  use the 10 minutes before and after it.
- TopSQL requires one exact instance selected from time-aligned metrics for
  that component and returns its Top 10 Digests by default. It never treats the
  first discovered Dashboard instance as top.
- A metric timeout or HTTP 504 triggers at most one same-target, same-PromQL
  retry over the centered half-window. The client never widens the request,
  changes target, removes label matchers, or starts the retry before the
  original attempt has failed. Duplicate retries for the same timed-out
  PromQL never run concurrently.
- Successful metric reads remain valid evidence when another dimension fails.
  A failed bounded retry marks only that metric `unverified`, not the whole
  provider unavailable.
- After deterministic provider retries, an executed-query semantic failure is
  returned to the same Evidence Agent thread. The Agent may replace the failed
  load-bearing objective with a changed bounded plan at most four times per
  query in the same acquisition round. It never re-executes an unchanged plan
  and may stop when the objective is non-load-bearing or has no supported
  repair.
- A successful query with no matching rows is complete execution and remains an
  explicit gap. It does not make the batch partial by itself.
- The TiKV pending scheduler command metric is the historically misspelled
  `tikv_scheduler_contex_total`; `tikv_scheduler_pending_commands` does not
  exist on the supported Manus target.
- Slow Query first intersects its safe core plus the query's ordered, at-most-12
  `handoffFields` with `/api/slow_query/available_fields`, then sends the
  selected `fields` to the list API. Missing fields are unavailable and must
  not be interpreted as zero.
- Always-preserved identity/time facts do not consume `handoffFields`. Select
  only the mechanism-discriminating timing, Cop/address, stats, scan, backoff,
  memory/disk, resource-control, or RocksDB facts needed by the current
  Scenario Diagnostic Agent question. Large plan payloads remain opt-in.
- Log target IP/port data comes from live Dashboard topology. TiDB uses `status_port`; stores and PD use `port`.
- Log search performs only create, poll, and preview. It does not automatically retry, cancel, or delete.

## Compatibility and non-goals

- No dependency on Wetech's Perimeter81, Playwright profile, datasource map, cookies, copied-cURL workflow, Clinic, or a kubectl relay.
- No compatibility fallback for old workspace files or legacy target names.
- No deployment, Kubernetes secret creation, whitelist mutation, or production operation.
- No customer-facing SQL/log redaction beyond compact preview limits; callers decide whether durable evidence is appropriate.

## Verification checklist

- `python3 -m unittest discover -s tests -v`
- Skill structure passes `quick_validate.py`.
- `health --target vida` resolves datasource `vida` exactly.
- `health --target monica` verifies the direct Prometheus build-info endpoint
  and the `monica` Dashboard login.
- A live metrics query returns at least one numeric series.
- A simulated empty-body HTTP 504 is classified as a timeout and retries once
  over the centered half-window without changing the target or PromQL.
- Live Slow Query output records requested and unsupported fields and returns
  non-default scan/timing values when the selected rows contain them.
- Live TopSQL, slow-query, and statements requests return HTTP 200 with parseable payloads.
- A narrow live log search reaches a terminal task state and returns a parseable preview.
- Repository search finds no embedded password, bearer token, cookie, Clinic fallback, or Wetech runtime import.
