@claude-flow/embeddings
Version:
V3 Embedding Service - OpenAI, Transformers.js, Agentic-Flow (ONNX), Mock providers with hyperbolic embeddings, normalization, and chunking
117 lines • 5.05 kB
TypeScript
/**
* ADR-121 Phase 22 — Ledger analyzer + regression detection.
*
* The witness ledger from Phase 18 stores N historical benchmark
* runs as a tamper-evident hash chain. Until now it served only as
* provenance — "I observed these numbers at this commit." This phase
* adds the missing layer: **using the chain to detect performance
* regressions** on every new run.
*
* Pattern:
* 1. Read the ledger.
* 2. For each benchmark name, pull every historical entry that
* ran the same benchmark.
* 3. Extract a named metric path (e.g. "results.summary.adaptive.meanRecallAt5").
* 4. Compare the current value to the baseline (most recent prior
* entry, or the best, or a rolling window) and report the delta.
* 5. Fail CI if the delta exceeds the configured threshold.
*
* Because the ledger is hash-chained (Phase 18), an attacker can't
* silently rewrite a historical baseline to make a regression look
* like an improvement — the chain verification would catch the
* tamper before the regression check ran.
*/
import type { BenchmarkLedger, LedgerEntry } from './witness-ledger.js';
/**
* Extract a value at a dotted path from a nested object. Returns
* `undefined` if any segment is missing or the final value is not
* numeric.
*/
export declare function getMetricAtPath(obj: unknown, path: string): number | undefined;
export interface BaselineSelection {
/**
* Which baseline to compare against:
* - 'latest' — most recent prior entry with the same benchmark name
* - 'best' — the entry with the maximum (or minimum, see direction) metric value
* - 'first' — the earliest entry (genesis-of-this-benchmark)
*/
readonly strategy: 'latest' | 'best' | 'first';
/**
* Optimization direction: 'higher' means larger metric values are
* better (recall, nDCG). 'lower' means smaller is better (latency,
* embeds, cost). Default 'higher'.
*/
readonly direction?: 'higher' | 'lower';
}
export interface RegressionCheckOptions {
/**
* Maximum allowed regression. Interpreted as a fractional change
* vs baseline (e.g. 0.05 = 5%). For 'higher-is-better' metrics, a
* regression means current < baseline. For 'lower-is-better'
* metrics, a regression means current > baseline.
* Default 0.10 (10%).
*/
readonly threshold?: number;
/** Baseline selection — defaults to { strategy: 'latest', direction: 'higher' }. */
readonly baseline?: BaselineSelection;
}
export interface RegressionCheckResult {
readonly benchmark: string;
readonly metricPath: string;
readonly currentValue: number;
/** Baseline value used for the comparison, or null if no prior runs exist. */
readonly baselineValue: number | null;
/** Which historical entry the baseline came from (sequence + timestamp). */
readonly baselineFrom: {
sequence: number;
timestamp: string;
} | null;
/** Absolute delta = current - baseline. */
readonly delta: number;
/**
* Fractional change = delta / baseline. Positive when current is
* larger than baseline (regardless of optimization direction).
*/
readonly percentChange: number;
/** True if the check passed (no major regression). */
readonly passed: boolean;
/** Human-readable reason. */
readonly reason: string;
}
/**
* Collect all ledger entries with a given benchmark name, in chain
* order (oldest first). Useful for building plots, computing
* rolling-window stats, etc.
*/
export declare function entriesForBenchmark(ledger: BenchmarkLedger, benchmarkName: string): ReadonlyArray<LedgerEntry>;
/**
* Pick the baseline value from a ledger for a (benchmark, metric)
* pair under the supplied strategy. Returns null when the chain has
* no entries with both a matching benchmark name AND a numeric value
* at the metric path.
*/
export declare function pickBaseline(ledger: BenchmarkLedger, benchmarkName: string, metricPath: string, selection: BaselineSelection): {
value: number;
entry: LedgerEntry;
} | null;
/**
* Check whether the current value regressed against the ledger
* baseline. Returns a structured result with the delta and reason.
*/
export declare function checkRegression(ledger: BenchmarkLedger, benchmarkName: string, metricPath: string, currentValue: number, options?: RegressionCheckOptions): RegressionCheckResult;
/**
* Run multiple regression checks at once. Returns the per-check
* results plus an aggregate `allPassed` flag.
*/
export interface RegressionBatchInput {
readonly benchmark: string;
readonly metricPath: string;
readonly currentValue: number;
readonly options?: RegressionCheckOptions;
}
export interface RegressionBatchResult {
readonly allPassed: boolean;
readonly checks: ReadonlyArray<RegressionCheckResult>;
}
export declare function checkRegressionBatch(ledger: BenchmarkLedger, inputs: ReadonlyArray<RegressionBatchInput>): RegressionBatchResult;
//# sourceMappingURL=ledger-analyzer.d.ts.map