Son of Anton Docs
Operator

Cost and Traces

Inspect parity trace details, distinguish missing telemetry from zero cost, and interpret bounded PR averages.

The trace producer is in son-of-anton-review on feat/cloudflare-native, the deployed-engine lineage. The API described below is in son-of-anton-operator-parity on unmerged feat/greptile-operator-parity, with the corresponding UI in anton-ui-trace-parity. Native ingress does not expose those API routes.

A trace is a recorded execution attempt, not proof that every webhook, retry or failed startup left complete telemetry. Multiple trace IDs can share a review key. Observability and cost explains tracing and persistence limits.

Open a trace in the parity dashboard

  1. Open Analytics → Observability. This view fetches the latest 50 trace summaries. Its list KPIs are trace count, failed runs, average duration and P95 duration, not cost or token totals.
  2. Select a row. The client requests /api/traces/:traceId; the BFF maps it to /operator/api/traces/:traceId.
  3. Inspect the header, waterfall and a selected span. The inspector has Attributes and Events tabs. There is no Input/Output tab in this UI.

The list's duration metrics exclude null, invalid and nonpositive durations. A failed-runs count is derived from trace status. The detail error badge instead counts spans with an error status or error message, including the root if it carries one. These are not interchangeable counts.

Sources: UI src/views/Analytics.tsx:152-154; src/components/TraceObservability.tsx:30-105,107-165,177-219,321-388; src/lib/observability.ts:61-107,122-140; src/lib/api.ts:131-142; worker/proxy-utils.js:41-56.

API contract

For a parity Worker base URL in OPERATOR_URL, list traces with the read token:

curl --fail-with-body -sS \
  -H "Authorization: Bearer $GILF_OPERATOR_READ_TOKEN" \
  "$OPERATOR_URL/operator/api/traces?repo=owner/name&prNumber=123&limit=5"

Then use a URL-encoded returned trace ID in /operator/api/traces/:traceId. The list response is ok plus traces. Detail is ok, trace and sibling spans, not spans nested inside trace. An unknown ID returns 404 not_found.

Summary rows contain traceId, rootSpanId, review/PR identity, timing, status and attributes. They omit top-level token/cost totals and span counts. Detail spans use spanId, parentSpanId, kind, inputTokens, outputTokens, costUsd, firstTokenLatencyMs, attributes and events.

The API requires route-appropriate bearer authorization, or a dynamic key with the allowed read scope. The browser instead authenticates through the BFF's session cookie.

Sources: parity cloudflare/src/review-state-api.js:876-899; cloudflare/src/review-trace-queries.js:14-64,73-132; cloudflare/src/worker.js:80,117-133; UI worker/bff-sessions.js:69-75.

Read phases without assuming a fixed span set

Common phase names include repo.prepare, context.load, context.graph, chat.primary, validation.cf-sandbox, validation.e2b and native publish, beneath agent.workflow. Optional paths add hypothesis, shadow-chat and model-price spans.

Not every healthy attempt has every phase: a policy skip, early refusal, docs-only path or reuse of durable analysis changes what executes. A publish span records the service stage; its presence or ok status is not by itself proof of a new live GitHub review. Inspect its publication attributes, run state and ledger.

ObservationInterpretation and next check
No traceCould be no recorded attempt, tracing disabled on a non-native path, initialization failure or lost telemetry. Check run state and logs.
No chat.primaryCould be a skipped/early-failed path or reuse of stored analysis. Inspect the run before treating it as a tracing defect.
Validation unavailable with null passedNo usable verdict for that lane. Inspect the refusal/error and executor configuration.
Shadow validation error with timeoutPrimary findings are not replaced by shadow output. Publication may still have waited for the remaining shadow timeout, and compute may still cost money.
publish error or uncertain ledger actionDo not blindly replay. Inspect remote publication evidence and native ledger state.

Sources: engine src/codex-review-runner.js:34-60,2534-2539,2711-2714; cloudflare-native/container/entrypoint.mjs:95-176; src/validation-executor.js:213-245,435-464; cloudflare-native/src/state-transport.js:490-524.

Cost and tokens

The parity trace header sums non-null cost and token values from detail spans. If no value is reported, the total remains null and cost renders as a dash. If only one lane reports cost, the displayed total is partial; it is not the complete cost of the review.

Model cost uses configured GILF_MODEL_PRICES or built-in provider prices and reported usage. OpenRouter's built-in table is empty. Validation uses wall-clock estimates with CPU, memory and disk rates. Neither is an invoice. Worker, database, storage and other orchestration charges are not added by these formulas.

A numeric zero is not always a proven free operation: provider arithmetic treats missing numeric components as zero, and validation telemetry can coerce explicit null values to zero. Inspect the raw attributes and price configuration when a zero is surprising.

Sources: UI src/lib/observability.ts:64-78,122-140,274-276; engine src/model-provider.js:44-93; src/validation-executor.js:146-245.

PR averages are a bounded sample

The parity PR drawer loads up to five recent trace details for that PR. Its averages cover those loaded details, not all reviews in the database. Each optional metric averages only the runs reporting it. Phase/kind totals exclude roots and divide by the count of loaded details.

Nested phases and concurrent lanes overlap. Summing their durations is not a partition of wall-clock time. The minimum reported span first-token latency displayed in the header is likewise not necessarily elapsed time from the beginning of the whole review.

The separate Node API does have /operator/api/trace-stats?repo=...&number=..., and returns all traces supplied by its PR trace-store query. It exposes runCount, nullable averages, phases[] keyed by phase and spanTypes[] keyed by type. Do not call that endpoint on the parity Worker or describe the parity drawer as using it.

Sources: UI src/lib/api.ts:149-158; src/lib/observability.ts:122-140,228-272; engine src/operator-dashboard.js:326-402,659-668.

Raw native storage

Native D1 tables are review_traces and review_trace_spans. These read-only SQL examples target the native schema; use your configured database tooling and authorization rather than assuming the parity API's binding points to the same database.

SELECT trace_id, review_key, status, duration_ms, cost_usd
FROM review_traces
ORDER BY started_at DESC
LIMIT 5;

-- Replace the bound parameter with the selected trace ID through your SQL client.
SELECT name, kind, status, duration_ms, input_tokens, output_tokens, cost_usd, error
FROM review_trace_spans
WHERE trace_id = ?1
ORDER BY seq;

SELECT COALESCE(SUM(cost_usd), 0) AS used
FROM review_trace_spans
WHERE name = 'validation.e2b';

The last query is the native E2B gate's all-time estimate. It does not filter by role, repository or date, and it ignores null costs. The Test Lab ceiling is not a billing cap.

Re-flushing a trace upserts its row and replaces its spans. No age-based trace pruning was found in the audited native trace path or Node trace store; this is not a retention SLA or confirmation of account-level policies. The native mapper can persist input/output JSON, attributes and events even though parity detail omits input/output. Protect the database accordingly.

Sources: engine cloudflare-native/schema.sql:187-250; cloudflare-native/src/state-transport.js:417-451; cloudflare-native/src/trace-buffer.js:104-117; cloudflare-native/src/container-env.js:100-141.

No live trace, database or dashboard was queried during this audit. Missing spans, deployment state and actual billed cost remain runtime questions for consolidated verification.

On this page