/** * Aggregation math for the Factory Overview page. * * Pure functions over `work_items` rows — throughput, lead time, in-flight * count, demand mix and per-stage agent coverage, all read from the * server-appended `stageHistory` log. Keeping this DB-free makes the math unit * testable and lets the route stay a thin shell. * * Everything windowed is counted as an event that happened inside the window, * never as "the state the board happens to be in now", so re-querying a past * window always returns the same numbers. */ import type { WorkItemRow } from './base.js'; /** Default window span (days) when the request omits or malforms the range. */ export declare const DEFAULT_METRICS_WINDOW = 30; /** Hard cap on the range span (days) — bounds the gap-filled throughput array. */ export declare const MAX_METRICS_WINDOW = 366; /** * Flow metrics over the cards the Factory ran ({@link hasFactoryRun}) — synced * upstream issues and PRs nobody started a run on are not the Factory's work * and are excluded from every field below. */ export interface FactoryMetrics { /** * Days the series covers: the requested window clipped to the board's life. * Days before the first card could hold no completion, so counting them would * drag the per-day rate toward zero on a young board. */ daysCovered: number; /** Entries into `done` per UTC day, gap-filled across the covered days. */ throughput: { date: string; count: number; }[]; /** Card creation → `done` for every completion that landed in the window. */ leadTime: { medianMs: number | null; p90Ms: number | null; samples: number; }; /** Distinct cards in a pipeline stage — past intake, not yet terminal. */ wipTotal: number; /** Cards created in the window, by source. */ sourceMix: { source: string; count: number; }[]; /** Per-stage agent coverage over first visits that ended in the window. */ agentCoverage: { stage: string; /** * First visits to this stage that ended in the window. Repeat visits are * excluded from both sides: they are rework, already reported as such, and * counting them in the denominator alone caps a fully agent-run stage below * 100%. */ passes: number; /** * Of those: passes an agent finished (`exitedBy` is an agent actor). The * entry actor is not required — the rules engine is what queues a card into * a stage, so demanding both ends would report 0% for stages agents run * end to end. Missing `exitedBy` (entries written before exit stamping) * does not count. */ byAgent: number; /** * Outcomes of the agent-finished passes' items as of the window's end, * mutually exclusive, first match wins: `reworked` (a later visit to the * same stage — deliberately outranks `done`: a pass that needed a redo is a * failed pass even if the item eventually merged), then `done`, then * `canceled`, then `inFlight`. */ outcomes: { done: number; canceled: number; reworked: number; inFlight: number; }; }[]; } /** * Resolve untrusted `from`/`to` into a bounded half-open UTC window. A date-only * `to` covers the whole day; an open/future end resolves to the end of the * current UTC day (not `now`) so an event at this instant stays inside the * window instead of on its excluded edge. */ export declare function parseMetricsRange(fromParam: unknown, toParam: unknown, now: Date): { windowStart: number; windowEnd: number; }; type Window = { windowStart: number; windowEnd: number; }; export declare function computeFactoryMetrics(boardItems: WorkItemRow[], window: Window): FactoryMetrics; export {}; //# sourceMappingURL=metrics.d.ts.map