Initialize repository with harness code and assets
Initial import of all source code, config, and README assets: the packages workspace (cli, core, server, web, docs, landing, skills), build scripts, tooling config, and CI workflows. Includes the data-layout revision made on this branch: the local data root defaults to ~/.penguin/data (PENGUIN_HOME still overrides; the installer keeps its binaries in ~/.penguin), and every Agent lives under <project>/agents/<agent>/ — path helpers, the three agent-enumeration scans, the system prompt, built-in Skills, tests and docs all follow the new layout. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ihk8iQuo3kv2aPjAYEPuR
This commit is contained in:
1 parent
056bed7aeb
commit
45bfae6e94
543 files changed
+92949
No files matched your search
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Unit tests for benchmark-metrics.ts: metric switching on the evaluation-center
|
||||
* chart (score / cost / duration) — value extraction (missing -> null), gap
|
||||
* segmentation (skipped points: connect within a segment, break between
|
||||
* segments, a lone point still forms its own segment), and the y-axis max.
|
||||
*/
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
lineSegments,
|
||||
metricMax,
|
||||
metricValues,
|
||||
modelSeries,
|
||||
seriesValues,
|
||||
} from "../src/features/benchmark/benchmark-metrics";
|
||||
|
||||
const evaluations = [
|
||||
{ score: 6, cost: 0.12, durationMs: 90_000 },
|
||||
{ score: 7.5 }, // legacy record: no cost / durationMs
|
||||
{ score: 8.5, cost: 0.2, durationMs: 60_000 },
|
||||
];
|
||||
|
||||
describe("metricValues(按指标取值,缺失为 null)", () => {
|
||||
it("score 恒有", () => {
|
||||
expect(metricValues(evaluations, "score")).toEqual([6, 7.5, 8.5]);
|
||||
});
|
||||
|
||||
it("cost / duration 缺失给 null(跳点)", () => {
|
||||
expect(metricValues(evaluations, "cost")).toEqual([0.12, null, 0.2]);
|
||||
expect(metricValues(evaluations, "duration")).toEqual([90_000, null, 60_000]);
|
||||
});
|
||||
|
||||
it("非有限值(NaN / Infinity)按缺失对待", () => {
|
||||
expect(metricValues([{ score: 1, cost: Number.NaN }], "cost")).toEqual([null]);
|
||||
expect(metricValues([{ score: 1, durationMs: Infinity }], "duration")).toEqual([null]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("lineSegments(缺口切段)", () => {
|
||||
it("无缺口:单段全量(下标连续)", () => {
|
||||
expect(lineSegments([6, 7.5, 8.5])).toEqual([
|
||||
[
|
||||
{ index: 0, value: 6 },
|
||||
{ index: 1, value: 7.5 },
|
||||
{ index: 2, value: 8.5 },
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it("中间缺口断开为两段(单点段照样成段:只画点不画线)", () => {
|
||||
expect(lineSegments([0.12, null, 0.2])).toEqual([
|
||||
[{ index: 0, value: 0.12 }],
|
||||
[{ index: 2, value: 0.2 }],
|
||||
]);
|
||||
expect(lineSegments([null, 1, 2, null, 3])).toEqual([
|
||||
[
|
||||
{ index: 1, value: 1 },
|
||||
{ index: 2, value: 2 },
|
||||
],
|
||||
[{ index: 4, value: 3 }],
|
||||
]);
|
||||
});
|
||||
|
||||
it("全缺失 / 空列表:无段", () => {
|
||||
expect(lineSegments([null, null])).toEqual([]);
|
||||
expect(lineSegments([])).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("metricMax(纵轴上界)", () => {
|
||||
it("取有值点的最大值(忽略 null)", () => {
|
||||
expect(metricMax([0.12, null, 0.2])).toBe(0.2);
|
||||
});
|
||||
|
||||
it("全缺失 / 全零给极小正数(坐标系不除零)", () => {
|
||||
expect(metricMax([null, null])).toBe(1e-9);
|
||||
expect(metricMax([0, 0])).toBe(1e-9);
|
||||
});
|
||||
});
|
||||
|
||||
describe("modelSeries / seriesValues(曲线按模型分系列)", () => {
|
||||
const mixed = [
|
||||
{ score: 6, provider: "deepseek", modelId: "deepseek-v4-flash" },
|
||||
{ score: 7 }, // legacy record: no model tagged -> trailing gray series
|
||||
{ score: 7.5, provider: "deepseek", modelId: "deepseek-v4-pro" },
|
||||
{ score: 8.5, provider: "deepseek", modelId: "deepseek-v4-pro" },
|
||||
];
|
||||
|
||||
it("按 (provider, modelId) 分组,首次出现顺序排列,未标注归末尾无名系列", () => {
|
||||
const series = modelSeries(mixed);
|
||||
expect(series.map((s) => s.modelId)).toEqual([
|
||||
"deepseek-v4-flash",
|
||||
"deepseek-v4-pro",
|
||||
undefined,
|
||||
]);
|
||||
expect(series.map((s) => s.indices)).toEqual([[0], [2, 3], [1]]);
|
||||
expect(series[2]!.key).toBe("");
|
||||
});
|
||||
|
||||
it("同名 modelId 跨 provider 各成一系列(成对分组,不做拼接语义)", () => {
|
||||
const dup = [
|
||||
{ score: 1, provider: "moonshot", modelId: "kimi-k2.6" },
|
||||
{ score: 2, provider: "siliconflow", modelId: "kimi-k2.6" },
|
||||
];
|
||||
const series = modelSeries(dup);
|
||||
expect(series).toHaveLength(2);
|
||||
expect(series.map((s) => s.provider)).toEqual(["moonshot", "siliconflow"]);
|
||||
});
|
||||
|
||||
it("seriesValues:非本系列下标为 null(跳点),沿用全局时间轴", () => {
|
||||
const series = modelSeries(mixed);
|
||||
expect(seriesValues(mixed, series[1]!, "score")).toEqual([null, null, 7.5, 8.5]);
|
||||
expect(seriesValues(mixed, series[2]!, "score")).toEqual([null, 7, null, null]);
|
||||
});
|
||||
|
||||
it("全部未标注:只有一条无名系列(旧数据单系列照画)", () => {
|
||||
const series = modelSeries([{}, {}]);
|
||||
expect(series).toHaveLength(1);
|
||||
expect(series[0]!.key).toBe("");
|
||||
expect(series[0]!.indices).toEqual([0, 1]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user