v0.23.0
Added
- 测评用例科学性 v1(对标 HELM / MMLU-Pro / Construct Validity 三件套 / HF Dataset Cards 行业共识):
Sampleschema 加 4 个可选元数据字段(capability/difficulty/construct/provenance),纯文档/诊断用,完全不参与 grading / judge / verdict / Report 顶层 schema(测量学不变量保护,跨版本 verdict / Δ 完全可比,跟 v0.22 strict-baseline 那次的 breaking-comparability 区分开)。- Sample 元数据(
src/types/eval.ts):capability?: string[]— 该用例覆盖的能力维度(如['api-selection', 'error-diagnosis']),归一时大小写/短横线/驼峰/下划线不敏感difficulty?: 'easy' | 'medium' | 'hard'— 难度分层(强枚举,防错)construct?: string— 该用例测的 construct 类型,suggested values:'necessity'(测必要性,baseline-vs-skill)/'quality'(测 skill 写得好不好,skill-v1-vs-skill-v2)/'capability'(测某具体能力);free-form string 允许自定义provenance?: 'human' | 'llm-generated' | 'production-trace'— 数据来源
load-samples.ts新增 enum 校验:difficulty/provenance非法值含sample_id定位的错误信息(形如samples[3] (s007) invalid difficulty: 'easy?', expected one of [easy, medium, hard]);capability必须是 string[];construct接受任意 string。bench diagnose加 2 类新 issue:rubric_clarity_low(info):rubric < 20 字符 AND 不含任何评分级别词(中英 22 词清单)→ static rubric quality signal,跟现有ambiguous_rubric(runtime/judge stddev)互补capability_thin(warning):某 capability 只 ≤max(2, N*0.2)个 sample 撑(总 N≥10 才检测,小 N 自动跳过避免全报)- fine-grained discrimination signal(IRT 风格)留 follow-up
bench diagnoseCLI 加 sample design coverage 块:capability / difficulty / construct / provenance 分桶呈现(ASCII),数据从report.analysis.sampleQuality取(分桶聚合)或 fresh 加载 samples 算Report.analysis.sampleQuality:新增SampleQualityAggregate子结构,纯文档聚合(capabilityCoverage/difficultyDistribution/constructDistribution/provenanceBreakdown/avgRubricLength/sampleCountWith*)。不破老报告兼容:不传 samples 时不挂此字段,老 reader 读取仍正常。bench gen-samples自动注入provenance: 'llm-generated':SYSTEM_PROMPT加可选 hint 段(LLM 如能判断顺便填 capability / difficulty / construct,无法判断省略不强制)- 新建
docs/sample-design-spec.md:行业 8 条 gap 引用 + omk v1 映射 + 完整 yaml example + 11 条用例设计自检 checklist + verdict 解读跟 construct 配合 + §八 Schema 扩展候选(v2 路线 source_ids / status / 拒绝清单 tags / expected_facts / owner / risk_level 含理由) - HTML report 暂不显示 sample design coverage(只 CLI
bench diagnose),HTML 渲染留 follow-up — 用户跑 HTML 报告需要看 coverage 时,从report.json的analysis.sampleQuality读 - R11 防御测试:
test/grading/judge-prompt-isolation.test.ts锁住 judge prompt 不含任何 sample 元数据 token('capability:'/'difficulty:'等),防未来 refactor 把元数据意外注入 judge prompt 破坏 construct validity - 软兼容性 callout:如果用户之前用 sample.capability 作为自由 unknown 字段(string / object / 其它),v1 起此字段是
string[],类型校验会拒掉非数组值(此前 omk 没 publicize 过 capability 名字,概率极低)。provenanceenum 简化:'evolved'/'mixed'留 follow-up 跟 evolver 升级一起做。
- Sample 元数据(
Fixed
VariantSummary.toolDistribution修真实 call count:之前 aggregate 阶段按result.toolNames(per-sample dedup 列表)累加,语义是"出现该 tool 的 sample 数",跟字段名"工具调用分布"不符 — 用户读 summary 看到Read: 5以为模型调了 5 次 Read,实际是"5 个样本里出现过 Read"。修法:VariantResult加 per-sampletoolDistribution(从toolCallsreduce 得到真实 call count map),aggregate 时 sum per-sample 字段。旧报告 result 没toolDistribution字段时 fallback 到老toolNames语义保兼容。
Changed
-
⚠️ BREAKING:report server URL 从/run/<id>改为/reports/<id>:命名跟 codebase 内一致语义(Report类型 /~/.oh-my-knowledge/reports/目录 /omk bench reportCLI 命令)对齐。/run/是 omk 内部把 "evaluation run" 当 entity 的旧叫法,但用户打开 URL 是来"看报告"的——/reports/直接匹配心智。同步改:/api/run/<id>→/api/reports/<id>,/api/runs→/api/reports。直接删旧路径,不留兼容 alias(omk 0-1 阶段)。已有书签需要更新。 -
⚠️ BREAKING-COMPARABILITY:bench run/bench gate默认对 baseline-kind variant 启用 skill isolation(--strict-baselinedefault true)。这是 omk 测量学严谨性的根本承诺补全:之前 baseline 通过三条 channel(SDK skill auto-discovery / subagent Skill 工具 / cwd 文件系统)拿到~/.claude/skills/全部 skill,导致 baseline-vs-skill 比较 construct invalid——baseline 跟 treatment 看到的是同一份 skill 内容,Δ 接近 0 是必然结果。本版默认三堵(main session skills + subagent Skill 工具 + cwd 切到 isolated empty dir),baseline 真正干净。改动范围:
- CLI flag:新增
--strict-baseline(default true) /--no-strict-baseline(显式 opt-out 逃生口)。bench run+bench gate同步支持。pre-flight 在--no-strict-baseline+~/.claude/skills/非空时 stderr 显式提醒。 - eval.yaml schema:新增
variants[].allowedSkills?: string[]显式声明,优先级高于 CLI flag。undefined= 默认 /[]= 完全隔离 /[name1, name2]= 白名单。YAMLallowedSkills:不写值会被 parse 成 null,显式 reject(语义不清)。 - executor 行为:claude-sdk 注入
skills+disallowedTools:['Skill'];claude-cli 等价(--disable-slash-commands+--disallowedTools Skill,文档说前者就是 "Disable all skills"),任意非空白名单 throw 提示改 sdk(CLI 没暴露 partial whitelist);script 仅 stderr warn 不参与 isolation。 - cache key 升级
v2:prefix + 含 allowedSkills:旧 cache 一次性失效(避免 strict / non-strict 切换时误命中污染结果)。同 prompt 不同 isolation 必拿不同 cache key。 - report.meta.skillIsolation:新字段记录每个 variant 的 allowedSkills 快照(undefined → null),供跨报告对比。
--resume时 isolation 状态不一致 stderr warn 不阻塞。 - 隔离覆盖(三条 channel):
- main session skills(SDK
options.skills):skills:[]关 SDK 内部 skill 发现 - subagent Skill 工具(SDK
options.disallowedTools):disallowedTools:['Skill']关 SDK 内置 task subagent 调 Skill 工具 - cwd 文件系统访问(切到 isolated empty dir):baseline 默认 cwd 是
process.cwd()(用户评测工作目录),那里通常有skills/<name>/symlink 给 treatment 用 — baseline 用 Glob/Read 直接顺 symlink 读 SKILL.md 就完全绕过 SDK 隔离。strict 模式 + 用户没显式 cwd 时切到~/.oh-my-knowledge/isolated-cwd/(空目录),Glob/Read 探索不到任何 skill 文件。这条是真正 load-bearing 的 channel — 仅堵 SDK 两条时 baseline 输出仍含被测 skill 的私有 token,加 cwd 隔离后才真正干净。
- main session skills(SDK
- MCP servers:已默认堵(SDK
settingSources默认[]+ omk 不传mcpServers)。 - 已知 limit:
AgentDefinition.skills白名单精确控制留 follow-up(白名单场景 subagent 仍能调 Skill 工具,但 v1 用户主要用[]完全隔离,影响小)。
breaking-comparability 标记:旧报告(无
meta.skillIsolation)与新报告 verdict / Δ 不可跨版本对比——等同 judge prompt bump 一档;CHANGELOG 显式 callout。迁移指南:- 已有 baseline-vs-skill 评测脚本无需改 flag 即享受 default strict;旧报告作为"污染基线"留存,新跑作为"干净基线"。
- 需要老行为(测 baseline 走默认 skill 发现的效果)显式加
--no-strict-baseline。 - 跨版本对比 verdict / Δ 前先看
meta.skillIsolation是否一致。
设计 spec 见 docs/terminology-spec.md §七 Skill Isolation。
- CLI flag:新增
Internal
- 新增
buildSdkIsolationOptions(allowedSkills)(纯函数,可测) +buildIsolationWarnings(artifacts, strictBaseline)pre-flight helper。 resolveArtifacts(skillDir, variants, opts)新增opts: { strictBaseline?, variantAllowedSkills? },旧 caller 0 改动(opts 全 optional)。cacheKey()signature 加allowedSkills?: string[]入参,旧 caller 不传时退化到默认行为(但 prefix 升级到v2:,旧 cache 一次性失效)。- 单测覆盖:resolveArtifacts 三种优先级 / cache key 不同 isolation 不同键 + 顺序不敏感 / SDK option 形态契约 / claude-cli throw 非空白名单 / eval-config schema reject null + 非数组 / report.meta.skillIsolation populate / pre-flight isolation warning 触发条件。
- lint 严格化三层防御:(1)
yarn lint加--max-warnings 0,任何 warning 都让 CI /yarn ci红;(2) 新加husky+lint-stagedpre-commit hook,commit 前对 staged TS 文件跑eslint --max-warnings 0,本地拦住坏 commit;(3).claude/settings.json加Stophook,Claude Code 协作时每次 turn 结束自动跑yarn lint(只在 src/test TS 文件有改动时跑,避免无用 IO),AI 编辑出 warning 立刻被 feedback 回来。前置清掉 4 个 pre-existing unused-var warning(summary.ts 没用的 levelIcon helper;grader.test.ts 两处{ dirname, join }解构里 join 没用;trace-adapter.test.ts 没用的 TestSession type alias)。 src/cli模块化重构:src/cli.ts(1956 行单文件)→src/cli/index.ts(1583 行 entry + dispatcher) + 抽parse-run-config.ts/progress.ts/update-check.ts/coverage-renderer.ts(后者从src/analysis/搬过来,本质 CLI 渲染)。修 sibling-folder 反模式(src/cli.ts与src/cli/同级)。package.jsonbin 路径同步:dist/src/cli.js→dist/src/cli/index.js。纯 file move + 路径调整,不动逻辑。- Reconcile main → develop:0.22.0 release 走的是从更早 develop 切出的
release/0.22.0,跟 PR #26(sample-design v1)并行,release prep 两处代码改动没回到 develop。本次补到 cli refactor 后的位置:checkUpdate5 层向上找package.json落到src/cli/update-check.ts(兼容dist/src/cli/这条新路径);handleRun的blind: { type: 'boolean' }+if (values.blind !== undefined)守门(避免 CLI default 覆盖eval.yaml的blind: true)已通过 git rename detection 自动 merge 到src/cli/index.ts。同时把[0.22.0]CHANGELOG section 两处描述对齐到中性表述,跟 GitHub Release v0.22.0 notes 同步。
What's Changed
- feat(sample-design): 测评用例科学性 v1 — 4 字段元数据 + 2 新诊断 + 行业 8 gap 映射 by @lizhiyao in #26
- chore(reconcile): merge main → develop + 中性化 [0.22.0] CHANGELOG 描述 by @lizhiyao in #28
- chore(release): 0.23.0 by @lizhiyao in #29
Full Changelog: v0.22.0...v0.23.0