Files
InfoRSI/tests/ledger-helpers.ts
T
iomgaa 716f4b88a5 feat: 账本 ledger 模块(任务书 03)
一张只追加的表(序号、种类、内容、哈希),禁改禁删两条触发器。
有自己编号、只发生一次的 8 种记录加部分唯一索引,重复就报错:阶段开、阶段关、运行登记、
确认启动(确认没启动的结果也算这一条,防止同一次运行既扣次又退还)、运行结果、模型调用开始、结束、消融结算。
写入时只查四种拒收:只收开着的阶段的提交;替换必须接本人同一阶段、同一对象、同一种提交的最新一版,实现与核验类不能替换;
结果先于确认启动(没启动除外);本轮消融已有格启动后不能关解释阶段。
写提案时作者自评拆成封存。提供打开(核对表结构版本,非账本库不改动)、追加、同步事务、读取、未完成的动作。
第一版的可见性、截止序号、通用唯一键、jev 记录和多余的前提检查已按新版任务书清掉。
三轮全新上下文审阅;flow 传错参数一类的意见按 CLAUDE.md"罕见情况怎么办"第 2 条只记录不加代码。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 06:37:47 -04:00

104 lines
3.6 KiB
TypeScript

import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import type { TestContext } from "node:test";
import { Ledger } from "../src/ledger/index.ts";
import type { ModelUsage, ProcessResult, Range, RunDefinition, Stage, Submission } from "../src/vocab/index.ts";
// ledger 测试共用:每个测试在自己的临时目录里建一个真实的数据库文件,测试结束时连目录一起删掉。
export function tempDir(t: TestContext): string {
const dir = mkdtempSync(join(tmpdir(), "inforsi-ledger-"));
t.after(() => rmSync(dir, { recursive: true, force: true }));
return dir;
}
export function freshLedger(t: TestContext): { ledger: Ledger; path: string } {
const path = join(tempDir(t), "ledger.db");
const ledger = Ledger.open(path);
t.after(() => ledger.close());
return { ledger, path };
}
export const range = (q1: number, q5: number, q9: number): Range => ({ q1, q5, q9 });
export function proposal(estimate: Range, body = "提案正文"): Submission<"proposal"> {
return {
factors: [{ name: "换优化器", method: "把 SGD 换成 Adam", keySettings: "学习率 0.01", continues: null }],
safeguards: [],
metrics: { defined: [], reused: [] },
authorEstimate: estimate,
body,
};
}
export const prediction = (r: Range): Submission<"firstPrediction"> => ({ range: r, body: "理由" });
export const critique = (body = "挑刺内容"): Submission<"critique"> => ({ target: "whole", body });
export const wrapUp = (body = "收尾"): Submission<"wrapUp"> => ({ body });
export const implementation = (body = "无"): Submission<"implementation"> => ({
factorLocations: [{ factor: "p1", locations: ["solve.py:10-20"] }],
safeguardLocations: [],
unassigned: [],
concerns: "无",
body,
});
export const definition: RunDefinition = {
command: ["python", "solve.py"],
workdir: "/work",
image: { digest: `sha256:${"0".repeat(64)}`, runtime: "runc" },
wallSeconds: 120,
cores: 1,
inheritEnv: false,
env: {},
};
export const exited: ProcessResult = {
ending: "exited",
exitCode: 0,
cpuSeconds: { status: "measured", value: 100 },
wallSeconds: { status: "measured", value: 101 },
peakMemoryBytes: { status: "measured", value: 1e8 },
};
export const notStarted: ProcessResult = { ending: "notStarted", reason: "启动前取消" };
/** 开一个阶段,返回开阶段那条记录的序号。 */
export function openStage(
ledger: Ledger,
stageId: string,
stage: Stage,
round: number,
roster: string[] = ["r1", "r2"],
): number {
return ledger.append("stageOpen", { stageId, stage, round, roster }).seq;
}
export function closeStage(ledger: Ledger, stageId: string): number {
return ledger.append("stageClose", { stageId }).seq;
}
/** 登记一次运行。 */
export function planRun(ledger: Ledger, run: string, purpose: "baseline" | "forward" | "ablation", round: number): number {
return ledger.append("runPlanned", { run, purpose, round, object: purpose === "baseline" ? null : `obj-${run}`, definition }).seq;
}
/** 一次模型调用的开始记录,materials 是这次任务的全部材料。 */
export const callStart = (call: string, actor = "r1", stageId: string | null = null) => ({
call,
actor,
stageId,
model: "glm-5.3",
materials: { firstMessage: "任务说明……", tools: ["read", "submit"] },
});
const unknownCount = { status: "unmeasured" as const, reason: "服务没报" };
export const usage: ModelUsage = {
inputTokens: unknownCount,
cacheReadTokens: unknownCount,
cacheWriteTokens: unknownCount,
outputTokens: unknownCount,
cost: unknownCount,
};