Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
51 lines
1.8 KiB
TypeScript
51 lines
1.8 KiB
TypeScript
import type { NavigationMetrics } from './types'
|
|
|
|
export interface MetricComparison {
|
|
baseline: number | null
|
|
candidate: number | null
|
|
delta: number | null
|
|
ratio: number | null
|
|
}
|
|
|
|
export interface NavigationComparison {
|
|
displayFrameP95Ms: MetricComparison
|
|
displayFrameP99Ms: MetricComparison
|
|
renderP95Ms: MetricComparison
|
|
inputToRenderP95Ms: MetricComparison
|
|
zoomAnchorDriftMaxPx: MetricComparison
|
|
maximumJumpPx: MetricComparison
|
|
finalInputToCrispMs: MetricComparison
|
|
longTaskTotalMs: MetricComparison
|
|
}
|
|
|
|
function compare(baseline: number | null, candidate: number | null): MetricComparison {
|
|
return {
|
|
baseline,
|
|
candidate,
|
|
delta: baseline === null || candidate === null ? null : candidate - baseline,
|
|
ratio: baseline === null || candidate === null || baseline === 0 ? null : candidate / baseline
|
|
}
|
|
}
|
|
|
|
export function compareNavigationMetrics(
|
|
baseline: NavigationMetrics,
|
|
candidate: NavigationMetrics
|
|
): NavigationComparison {
|
|
return {
|
|
displayFrameP95Ms: compare(
|
|
baseline.displayFrameIntervalsMs.p95,
|
|
candidate.displayFrameIntervalsMs.p95
|
|
),
|
|
displayFrameP99Ms: compare(
|
|
baseline.displayFrameIntervalsMs.p99,
|
|
candidate.displayFrameIntervalsMs.p99
|
|
),
|
|
renderP95Ms: compare(baseline.renderDurationsMs.p95, candidate.renderDurationsMs.p95),
|
|
inputToRenderP95Ms: compare(baseline.eventToRenderEndMs.p95, candidate.eventToRenderEndMs.p95),
|
|
zoomAnchorDriftMaxPx: compare(baseline.zoomAnchorDriftPx.max, candidate.zoomAnchorDriftPx.max),
|
|
maximumJumpPx: compare(baseline.maximumJumpPx, candidate.maximumJumpPx),
|
|
finalInputToCrispMs: compare(baseline.finalInputToCrispMs, candidate.finalInputToCrispMs),
|
|
longTaskTotalMs: compare(baseline.longTasks.totalMs, candidate.longTasks.totalMs)
|
|
}
|
|
}
|