summaryrefslogtreecommitdiffhomepage
path: root/frontend-metrics-pass2-handoff.md
diff options
context:
space:
mode:
Diffstat (limited to 'frontend-metrics-pass2-handoff.md')
-rw-r--r--frontend-metrics-pass2-handoff.md67
1 files changed, 0 insertions, 67 deletions
diff --git a/frontend-metrics-pass2-handoff.md b/frontend-metrics-pass2-handoff.md
deleted file mode 100644
index adf0404..0000000
--- a/frontend-metrics-pass2-handoff.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# FE handoff — persisted replay metrics (Pass 2) + metrics endpoint
-
-> **Courier doc** (backend → `../frontend`, via the user). Per ORCHESTRATOR §7
-> the backend does NOT write the FE repo; the FE orchestrator applies this delta
-> on its side (regenerate the in-repo `.dispatch/*.reference.md` snapshots + bump
-> the `file:` dep). `lsp references` does not span the two repos. Backend commit:
-> `6db12ff`.
-
-## Versions
-- `@dispatch/wire` `0.3.0 → 0.4.0` (additive)
-- `@dispatch/transport-contract` `0.3.0 → 0.4.0` (additive)
-
-Pure-type, additive change — no breaking edits to existing types.
-
-## New wire types (`@dispatch/wire`, re-exported by `@dispatch/transport-contract`)
-
-```ts
-interface StepMetrics {
- stepId: StepId; // `<turnId>#<index>`, join key to the live stream
- usage: Usage; // { inputTokens, outputTokens, cacheReadTokens?, cacheWriteTokens? }
- ttftMs?: number; // time to first token (optional — clock + first-token gated)
- decodeMs?: number; // first token → stream end
- genTotalMs?: number; // stream start → end (== ttftMs + decodeMs when a first token was seen)
-}
-
-interface TurnMetrics {
- turnId: string; // plain wire turn id, join key to AgentEvents
- usage: Usage; // aggregate across all steps
- durationMs?: number; // turn wall-clock (optional — clock gated)
- steps: readonly StepMetrics[]; // per-step, in step order
-}
-```
-
-These are the **persisted, replayable** counterparts of the live `usage` /
-`step-complete` / `done` events (which remain transient and unchanged).
-
-## New read endpoint
-
-`GET /conversations/:id/metrics` → `ConversationMetricsResponse`:
-
-```ts
-interface ConversationMetricsResponse { turns: readonly TurnMetrics[] }
-```
-
-Semantics:
-- `turns` = every **sealed** turn's `TurnMetrics`, in **turn-append order**.
-- A turn appears only **after seal** (post-persist); an in-flight/unsealed turn is absent.
-- This is a **separate axis** from `GET /conversations/:id?sinceSeq=` (which returns
- seq-cursor chunk CONTENT). Metrics are keyed per **turn**, not per chunk, so they are
- **not** seq-filtered — hence a sibling route, not a field on the history response.
-- Unknown / metric-less conversation → `{ turns: [] }`.
-- CORS: same wildcard as the other routes.
-
-## Suggested FE consumption
-On (re)opening a conversation, the chat feature can `GET /conversations/:id/metrics`
-once alongside the history hydrate (`?sinceSeq=`), then render historical
-tokens/latency per turn (and per step via `stepId`) — identical fields to what it
-already routes from the live `step-complete` / `usage` / `done` stream. TPS is
-still derived FE-side (`usage.outputTokens / decodeMs`); context-size proxy =
-`usage.inputTokens`.
-
-## Invariants (confirmed live)
-- Persisted `TurnMetrics.usage` / `durationMs` and each `StepMetrics`
- (`stepId` + `usage` + `ttftMs`/`decodeMs`/`genTotalMs`) **byte-match** what the
- live stream emitted for the same turn (verified end-to-end against flash).
-- `stepId` is the SAME value on the live `step-complete`/`usage` events, the persisted
- `StepMetrics`, and the tool chunks — one grouping key across live + replay.