oh-my-knowledge 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -9
- package/README.zh.md +11 -9
- package/dist/analysis/saturation.d.ts +8 -0
- package/dist/analysis/saturation.d.ts.map +1 -1
- package/dist/analysis/saturation.js +12 -4
- package/dist/analysis/saturation.js.map +1 -1
- package/dist/authoring/evolver.d.ts +43 -2
- package/dist/authoring/evolver.d.ts.map +1 -1
- package/dist/authoring/evolver.js +91 -8
- package/dist/authoring/evolver.js.map +1 -1
- package/dist/authoring/generator.d.ts +29 -1
- package/dist/authoring/generator.d.ts.map +1 -1
- package/dist/authoring/generator.js +113 -0
- package/dist/authoring/generator.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +22 -3
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/eval/index.d.ts.map +1 -1
- package/dist/cli/commands/eval/index.js +3 -2
- package/dist/cli/commands/eval/index.js.map +1 -1
- package/dist/cli/commands/evolve.d.ts +1 -0
- package/dist/cli/commands/evolve.d.ts.map +1 -1
- package/dist/cli/commands/evolve.js +16 -0
- package/dist/cli/commands/evolve.js.map +1 -1
- package/dist/cli/commands/observe/index.d.ts.map +1 -1
- package/dist/cli/commands/observe/index.js +6 -2
- package/dist/cli/commands/observe/index.js.map +1 -1
- package/dist/cli/commands/sample.d.ts +2 -0
- package/dist/cli/commands/sample.d.ts.map +1 -1
- package/dist/cli/commands/sample.js +98 -6
- package/dist/cli/commands/sample.js.map +1 -1
- package/dist/cli/lib/cmd-flags.d.ts +5 -0
- package/dist/cli/lib/cmd-flags.d.ts.map +1 -1
- package/dist/cli/lib/i18n-dict/common.d.ts +1 -1
- package/dist/cli/lib/i18n-dict/common.d.ts.map +1 -1
- package/dist/cli/lib/i18n-dict/common.js +18 -2
- package/dist/cli/lib/i18n-dict/common.js.map +1 -1
- package/dist/cli/lib/i18n-dict/evolve.d.ts +1 -1
- package/dist/cli/lib/i18n-dict/evolve.d.ts.map +1 -1
- package/dist/cli/lib/i18n-dict/evolve.js +8 -0
- package/dist/cli/lib/i18n-dict/evolve.js.map +1 -1
- package/dist/cli/lib/parse-run-config/variant-resolution.d.ts +8 -3
- package/dist/cli/lib/parse-run-config/variant-resolution.d.ts.map +1 -1
- package/dist/cli/lib/parse-run-config/variant-resolution.js +16 -10
- package/dist/cli/lib/parse-run-config/variant-resolution.js.map +1 -1
- package/dist/cli/lib/resolve-skill-input.d.ts.map +1 -1
- package/dist/cli/lib/resolve-skill-input.js +7 -5
- package/dist/cli/lib/resolve-skill-input.js.map +1 -1
- package/dist/cli/lib/update-check.d.ts +65 -0
- package/dist/cli/lib/update-check.d.ts.map +1 -1
- package/dist/cli/lib/update-check.js +220 -31
- package/dist/cli/lib/update-check.js.map +1 -1
- package/dist/cli/lib/update-fetch-worker.d.ts +2 -0
- package/dist/cli/lib/update-fetch-worker.d.ts.map +1 -0
- package/dist/cli/lib/update-fetch-worker.js +35 -0
- package/dist/cli/lib/update-fetch-worker.js.map +1 -0
- package/dist/doctor/health/load-custom-dimensions.d.ts +2 -0
- package/dist/doctor/health/load-custom-dimensions.d.ts.map +1 -0
- package/dist/doctor/health/load-custom-dimensions.js +31 -0
- package/dist/doctor/health/load-custom-dimensions.js.map +1 -0
- package/dist/eval-core/bootstrap.d.ts +8 -0
- package/dist/eval-core/bootstrap.d.ts.map +1 -1
- package/dist/eval-core/bootstrap.js +11 -3
- package/dist/eval-core/bootstrap.js.map +1 -1
- package/dist/eval-core/evaluation-reporting.d.ts.map +1 -1
- package/dist/eval-core/evaluation-reporting.js +4 -4
- package/dist/eval-core/evaluation-reporting.js.map +1 -1
- package/dist/eval-core/verdict.d.ts +21 -3
- package/dist/eval-core/verdict.d.ts.map +1 -1
- package/dist/eval-core/verdict.js +54 -4
- package/dist/eval-core/verdict.js.map +1 -1
- package/dist/eval-workflows/evaluation-preparation.d.ts.map +1 -1
- package/dist/eval-workflows/evaluation-preparation.js +39 -11
- package/dist/eval-workflows/evaluation-preparation.js.map +1 -1
- package/dist/eval-workflows/run-evaluation.d.ts +1 -1
- package/dist/eval-workflows/run-evaluation.d.ts.map +1 -1
- package/dist/eval-workflows/run-evaluation.js +7 -7
- package/dist/eval-workflows/run-evaluation.js.map +1 -1
- package/dist/inputs/eval-config.d.ts.map +1 -1
- package/dist/inputs/eval-config.js +1 -0
- package/dist/inputs/eval-config.js.map +1 -1
- package/dist/inputs/skill-loader.d.ts +22 -0
- package/dist/inputs/skill-loader.d.ts.map +1 -1
- package/dist/inputs/skill-loader.js +171 -12
- package/dist/inputs/skill-loader.js.map +1 -1
- package/dist/observability/skill-health-analyzer.d.ts +13 -0
- package/dist/observability/skill-health-analyzer.d.ts.map +1 -1
- package/dist/observability/skill-health-analyzer.js +17 -2
- package/dist/observability/skill-health-analyzer.js.map +1 -1
- package/dist/renderer/layout.d.ts.map +1 -1
- package/dist/renderer/layout.js +2 -0
- package/dist/renderer/layout.js.map +1 -1
- package/dist/renderer/skill-detail-renderer.d.ts.map +1 -1
- package/dist/renderer/skill-detail-renderer.js +98 -19
- package/dist/renderer/skill-detail-renderer.js.map +1 -1
- package/dist/renderer/skill-health-renderer.d.ts.map +1 -1
- package/dist/renderer/skill-health-renderer.js +33 -4
- package/dist/renderer/skill-health-renderer.js.map +1 -1
- package/dist/renderer/skill-list-renderer.d.ts.map +1 -1
- package/dist/renderer/skill-list-renderer.js +18 -6
- package/dist/renderer/skill-list-renderer.js.map +1 -1
- package/dist/renderer/summary.d.ts.map +1 -1
- package/dist/renderer/summary.js +20 -8
- package/dist/renderer/summary.js.map +1 -1
- package/dist/server/report-server.d.ts.map +1 -1
- package/dist/server/report-server.js +9 -2
- package/dist/server/report-server.js.map +1 -1
- package/dist/server/skill-index.d.ts.map +1 -1
- package/dist/server/skill-index.js +3 -0
- package/dist/server/skill-index.js.map +1 -1
- package/dist/server/skill-insights.d.ts.map +1 -1
- package/dist/server/skill-insights.js +33 -5
- package/dist/server/skill-insights.js.map +1 -1
- package/dist/types/eval.d.ts +1 -0
- package/dist/types/eval.d.ts.map +1 -1
- package/dist/types/skill-index.d.ts +3 -0
- package/dist/types/skill-index.d.ts.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
**English** | [简体中文](./README.zh.md)
|
|
10
10
|
|
|
11
11
|
**Did your prompt actually get better?**
|
|
12
|
-
A/B test your prompts and skills with statistical rigor — bootstrap CI
|
|
12
|
+
A/B test your prompts and skills with statistical rigor — bootstrap CI and length-debias on by default, Krippendorff α the moment you add a gold set.
|
|
13
13
|
|
|
14
14
|

|
|
15
15
|
|
|
@@ -23,6 +23,8 @@ omk eval --control code-review-v1 --treatment code-review-v2
|
|
|
23
23
|
|
|
24
24
|
That's it — no editing required. `omk init` scaffolds two skill variants and three sample cases; `omk eval` runs the controlled A/B and opens an HTML report with a one-line verdict in about five minutes.
|
|
25
25
|
|
|
26
|
+
> The CLI notifies you when a newer version is available (at most once per 20h); set `OMK_SKIP_UPDATE_CHECK=1` to silence it permanently.
|
|
27
|
+
|
|
26
28
|
Walkthrough: [5-minute quickstart guide](docs/quickstart-skill-eval.md) (recommended for first-time users).
|
|
27
29
|
|
|
28
30
|
Deeper: [CLI reference](docs/reference/cli.md) · [how it works](docs/explanation/architecture.md) · [eval sample format](docs/reference/eval-sample-format.md) · [executors & artifact layout](docs/reference/executors.md)
|
|
@@ -62,7 +64,7 @@ Teams doing knowledge engineering produce lots of knowledge artifacts (skills to
|
|
|
62
64
|
| | omk | promptfoo | DeepEval | LangSmith |
|
|
63
65
|
|--|--|--|--|--|
|
|
64
66
|
| Bootstrap CI | ✓ default | ✗ | ✗ | ✗ |
|
|
65
|
-
| Krippendorff α (judge ↔ human) | ✓
|
|
67
|
+
| Krippendorff α (judge ↔ human) | ✓ with gold set | ✗ | ✗ | ✗ |
|
|
66
68
|
| Length-debias judge prompt | ✓ default | ✗ | ✗ | ✗ |
|
|
67
69
|
| Saturation curve | ✓ | ✗ | ✗ | ✗ |
|
|
68
70
|
| Three-layer scoring isolation | ✓ | ✗ | partial | ✗ |
|
|
@@ -70,7 +72,7 @@ Teams doing knowledge engineering produce lots of knowledge artifacts (skills to
|
|
|
70
72
|
| Native Claude Code skill | ✓ | ✗ | ✗ | ✗ |
|
|
71
73
|
| Hosted SaaS dashboard | ✗ | ✗ | ✓ | ✓ |
|
|
72
74
|
|
|
73
|
-
omk's moat is **default-on safety net** — Bootstrap CI
|
|
75
|
+
omk's moat is **default-on safety net** — Bootstrap CI and length-debias aren't advanced flags; they're the default, and judge ↔ human α comes free the moment you add a gold set. Other tools let you opt into confidence intervals; omk makes them unavoidable. Need a hosted SaaS dashboard? Choose LangSmith. Want quick local prompt iteration without statistics? Choose promptfoo. **Shipping to production and someone will ask "why should I trust this number?" Choose omk.**
|
|
74
76
|
|
|
75
77
|
RAG-specific evals: see RAGAS (separate niche, complementary to omk). Full comparison with 7 tools across 25+ dimensions: [docs/reference/comparison.md](docs/reference/comparison.md).
|
|
76
78
|
|
|
@@ -80,9 +82,9 @@ RAG-specific evals: see RAGAS (separate niche, complementary to omk). Full compa
|
|
|
80
82
|
|---|---|
|
|
81
83
|
| **One-line verdict** | `omk eval` six-tier verdict + ship recommendation + exit-code routing; HTML pill shares the same rules |
|
|
82
84
|
| **Six-dim evaluation** | Fact / Behavior / LLM-judge / Cost / Efficiency / Stability shown independently |
|
|
83
|
-
| **Multi-executor** | Claude CLI / Claude SDK / Codex CLI / Codex SDK / OpenAI / Gemini / any custom command |
|
|
84
|
-
| **
|
|
85
|
-
| **Statistical rigor** | Bootstrap CI /
|
|
85
|
+
| **Multi-executor** | Claude CLI / Claude SDK / Codex CLI / Codex SDK / OpenAI / Gemini / Anthropic API / any custom command |
|
|
86
|
+
| **30+ assertion types** | substring, regex, JSON Schema, ROUGE/BLEU/Levenshtein similarity, agent tool-call assertions, semantic similarity, custom JS |
|
|
87
|
+
| **Statistical rigor** | Bootstrap CI / length-debias / saturation curve on by default; Krippendorff α auto-computed with a gold set. [Details →](docs/explanation/statistical-rigor.md) |
|
|
86
88
|
| **RAG metrics** | `faithfulness` / `answer_relevancy` / `context_recall` — anti-hallucination + answer relevance + context coverage |
|
|
87
89
|
| **LLM health audit** | `omk doctor` grades 7 builtin dimensions; `--static-only` runs offline without an LLM |
|
|
88
90
|
| **Production observability** | parse Claude Code session JSONL traces; measure per-skill failure rate / latency / cost / knowledge-gap signals |
|
|
@@ -100,7 +102,7 @@ RAG-specific evals: see RAGAS (separate niche, complementary to omk). Full compa
|
|
|
100
102
|
## Documentation
|
|
101
103
|
|
|
102
104
|
- **[How it works](docs/explanation/architecture.md)** — interleaved scheduling, variant resolution, dual-channel scoring, six-dim report
|
|
103
|
-
- **[Eval sample format](docs/reference/eval-sample-format.md)** — sample schema, scoring formulas,
|
|
105
|
+
- **[Eval sample format](docs/reference/eval-sample-format.md)** — sample schema, scoring formulas, 30+ assertion types, custom JS assertions
|
|
104
106
|
- **[CLI reference](docs/reference/cli.md)** — all seven commands with bash examples and flag tables
|
|
105
107
|
- **[Executors & artifact layout](docs/reference/executors.md)** — built-in / custom executors, agent evaluation, common model configs (Claude / OpenAI / GLM / Qwen / DeepSeek / Moonshot / Ollama)
|
|
106
108
|
- **[Quickstart](docs/quickstart-skill-eval.md)** — first-time five-minute walkthrough
|
|
@@ -117,9 +119,9 @@ RAG-specific evals: see RAGAS (separate niche, complementary to omk). Full compa
|
|
|
117
119
|
|
|
118
120
|
## Requirements
|
|
119
121
|
|
|
120
|
-
- Node.js >=
|
|
122
|
+
- Node.js >= 22
|
|
121
123
|
- `claude` CLI (for the default executor and LLM judge; see [Claude Code](https://claude.ai/code))
|
|
122
|
-
- not needed if you use other executors (openai / gemini) with `--no-judge`
|
|
124
|
+
- not needed if you use other executors (openai-api / anthropic-api / gemini) with `--no-judge`
|
|
123
125
|
|
|
124
126
|
## Security notice
|
|
125
127
|
|
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[English](./README.md) | **简体中文**
|
|
10
10
|
|
|
11
11
|
**你改完 prompt,真的变好了吗?**
|
|
12
|
-
用统计严谨性 A/B 测试你的 prompt 和 skill —— Bootstrap
|
|
12
|
+
用统计严谨性 A/B 测试你的 prompt 和 skill —— Bootstrap 置信区间、长度去偏默认开,配一份人工 gold 就自动算 Krippendorff α。
|
|
13
13
|
|
|
14
14
|

|
|
15
15
|
|
|
@@ -23,6 +23,8 @@ omk eval --control code-review-v1 --treatment code-review-v2
|
|
|
23
23
|
|
|
24
24
|
不用改任何文件 —— `omk init` 帮你脚手架两版 skill 和三条评测用例;`omk eval` 跑控制变量 A/B,5 分钟内出 HTML 报告 + 一行 verdict。
|
|
25
25
|
|
|
26
|
+
> 命令行有新版本时会自动提示(每 20 小时最多一次);想永久关闭该提醒,设环境变量 `OMK_SKIP_UPDATE_CHECK=1` 即可。
|
|
27
|
+
|
|
26
28
|
手把手教程:[5 分钟快速上手](docs/zh/quickstart-skill-eval.md)(推荐第一次跑评测的用户)。
|
|
27
29
|
|
|
28
30
|
深入:[CLI 参考](docs/zh/reference/cli.md) · [工作原理](docs/zh/explanation/architecture.md) · [评测样本格式](docs/zh/reference/eval-sample-format.md) · [执行器与 artifact 布局](docs/zh/reference/executors.md)
|
|
@@ -62,7 +64,7 @@ omk sample skills/my-skill.md
|
|
|
62
64
|
| | omk | promptfoo | DeepEval | LangSmith |
|
|
63
65
|
|--|--|--|--|--|
|
|
64
66
|
| Bootstrap 置信区间 | ✓ 默认 | ✗ | ✗ | ✗ |
|
|
65
|
-
| Krippendorff α(评委 ↔ 人工) | ✓
|
|
67
|
+
| Krippendorff α(评委 ↔ 人工) | ✓ 加 gold 即开 | ✗ | ✗ | ✗ |
|
|
66
68
|
| 长度去偏的评委 prompt | ✓ 默认 | ✗ | ✗ | ✗ |
|
|
67
69
|
| 饱和曲线 | ✓ | ✗ | ✗ | ✗ |
|
|
68
70
|
| 三层独立评分 | ✓ | ✗ | 部分 | ✗ |
|
|
@@ -70,7 +72,7 @@ omk sample skills/my-skill.md
|
|
|
70
72
|
| 原生 Claude Code skill | ✓ | ✗ | ✗ | ✗ |
|
|
71
73
|
| 托管 SaaS 看板 | ✗ | ✗ | ✓ | ✓ |
|
|
72
74
|
|
|
73
|
-
omk 的护城河是 **default-on 安全网** —— Bootstrap CI /
|
|
75
|
+
omk 的护城河是 **default-on 安全网** —— Bootstrap CI / 长度去偏不是 advanced flag,是默认行为;评委 ↔ 人工 α 只要给一份 gold 集就自动算。其他工具让你**手动**接置信区间;omk 让你**默认无法忽略**它。需要 SaaS 看板?选 LangSmith。要快速 prompt 迭代不要统计层?选 promptfoo。**要发到生产且会被问「为什么应该相信这个数字」?选 omk。**
|
|
74
76
|
|
|
75
77
|
RAG 专项评测请看 RAGAS(独立 niche,跟 omk 互补)。完整对比(7 个工具 × 25+ 维度): [docs/zh/reference/comparison.md](docs/zh/reference/comparison.md)
|
|
76
78
|
|
|
@@ -80,9 +82,9 @@ RAG 专项评测请看 RAGAS(独立 niche,跟 omk 互补)。完整对比
|
|
|
80
82
|
|------|------|
|
|
81
83
|
| **Verdict 一行结论** | `omk eval` 六档判定 + ship 建议 + exit code 路由,与 HTML 报告 verdict pill 共享规则 |
|
|
82
84
|
| **六维评估** | 事实 / 行为 / LLM 评价 / 成本 / 效率 / 稳定性独立展示 |
|
|
83
|
-
| **多执行器** | 支持 Claude CLI / Claude SDK / Codex CLI / Codex SDK / OpenAI / Gemini 及自定义命令 |
|
|
84
|
-
| **
|
|
85
|
-
| **统计严谨性** | Bootstrap CI /
|
|
85
|
+
| **多执行器** | 支持 Claude CLI / Claude SDK / Codex CLI / Codex SDK / OpenAI / Gemini / Anthropic API 及自定义命令 |
|
|
86
|
+
| **30+ 种断言** | 包含子串、正则、JSON Schema、ROUGE/BLEU/Levenshtein 相似度、Agent 工具调用、语义相似度、自定义函数等 |
|
|
87
|
+
| **统计严谨性** | Bootstrap CI / 长度去偏 / 饱和曲线默认开,Krippendorff α 提供 gold 集即自动计算。[详情 →](docs/zh/explanation/statistical-rigor.md) |
|
|
86
88
|
| **RAG metrics** | `faithfulness` / `answer_relevancy` / `context_recall` 三 metric — 反幻觉 + 切题度 + context 覆盖 |
|
|
87
89
|
| **LLM 健康度审计** | `omk doctor` 给 7 个内置维度独立打分;`--static-only` 可离线无 LLM 调用 |
|
|
88
90
|
| **线上 session 观测** | 解析 Claude Code session JSONL,测量各 skill 的失败率、耗时、token 成本、知识缺口信号 |
|
|
@@ -100,7 +102,7 @@ RAG 专项评测请看 RAGAS(独立 niche,跟 omk 互补)。完整对比
|
|
|
100
102
|
## 文档
|
|
101
103
|
|
|
102
104
|
- **[工作原理](docs/zh/explanation/architecture.md)** —— 交错调度、variant 解析、双通道评分、六维报告
|
|
103
|
-
- **[评测样本格式](docs/zh/reference/eval-sample-format.md)** —— sample schema、评分公式、
|
|
105
|
+
- **[评测样本格式](docs/zh/reference/eval-sample-format.md)** —— sample schema、评分公式、30+ 断言类型、自定义 JS 断言
|
|
104
106
|
- **[CLI 参考](docs/zh/reference/cli.md)** —— 7 个命令的 bash 示例和 flag 表
|
|
105
107
|
- **[执行器与 artifact 布局](docs/zh/reference/executors.md)** —— 内置 / 自定义执行器、Agent 评测、常见模型配置(Claude / OpenAI / GLM / 通义 / DeepSeek / Moonshot / Ollama)
|
|
106
108
|
- **[快速上手](docs/zh/quickstart-skill-eval.md)** —— 第一次跑评测的 5 分钟教程
|
|
@@ -117,9 +119,9 @@ RAG 专项评测请看 RAGAS(独立 niche,跟 omk 互补)。完整对比
|
|
|
117
119
|
|
|
118
120
|
## 系统要求
|
|
119
121
|
|
|
120
|
-
- Node.js >=
|
|
122
|
+
- Node.js >= 22
|
|
121
123
|
- `claude` CLI(默认执行器和 LLM 评委需要,参考 [Claude Code](https://claude.ai/code))
|
|
122
|
-
- 如果使用其它执行器(openai / gemini)+ `--no-judge` 则可不需要
|
|
124
|
+
- 如果使用其它执行器(openai-api / anthropic-api / gemini)+ `--no-judge` 则可不需要
|
|
123
125
|
|
|
124
126
|
## 安全说明
|
|
125
127
|
|
|
@@ -28,6 +28,14 @@
|
|
|
28
28
|
* that look like convergence but aren't.
|
|
29
29
|
*/
|
|
30
30
|
export type SaturationMethod = 'slope' | 'bootstrap-ci-width' | 'plateau-height';
|
|
31
|
+
/** Default consecutive-window run length required before declaring saturation. */
|
|
32
|
+
export declare const DEFAULT_SATURATION_WINDOW_SIZE = 3;
|
|
33
|
+
/**
|
|
34
|
+
* Default `bootstrap-ci-width` cutoff: declare saturation when the relative
|
|
35
|
+
* CI-width shrink per checkpoint stays under 5%. Single source of truth for
|
|
36
|
+
* the documented threshold; guarded by `doc-constants-drift.test.ts`.
|
|
37
|
+
*/
|
|
38
|
+
export declare const DEFAULT_CI_WIDTH_SHRINK_THRESHOLD = 0.05;
|
|
31
39
|
/**
|
|
32
40
|
* One observation in a saturation curve. `n` is the cumulative sample
|
|
33
41
|
* count at this checkpoint; `mean` and (optional) `ciWidth` come from
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"saturation.d.ts","sourceRoot":"","sources":["../../src/analysis/saturation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,oBAAoB,GAAG,gBAAgB,CAAC;AAEjF;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,oFAAoF;IACpF,SAAS,EAAE,OAAO,CAAC;IACnB,kFAAkF;IAClF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,iFAAiF;IACjF,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,wCAAwC;IACxC,MAAM,EAAE,gBAAgB,CAAC;IACzB,sBAAsB;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,KAAK,EAAE,KAAK,CAAC;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,MAAM,EAAE,EAAE,EAC5B,MAAM,GAAE,gBAAuC,EAC/C,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,
|
|
1
|
+
{"version":3,"file":"saturation.d.ts","sourceRoot":"","sources":["../../src/analysis/saturation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,oBAAoB,GAAG,gBAAgB,CAAC;AAEjF,kFAAkF;AAClF,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAEhD;;;;GAIG;AACH,eAAO,MAAM,iCAAiC,OAAO,CAAC;AAEtD;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,oFAAoF;IACpF,SAAS,EAAE,OAAO,CAAC;IACnB,kFAAkF;IAClF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,iFAAiF;IACjF,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,wCAAwC;IACxC,MAAM,EAAE,gBAAgB,CAAC;IACzB,sBAAsB;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,KAAK,EAAE,KAAK,CAAC;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,MAAM,EAAE,EAAE,EAC5B,MAAM,GAAE,gBAAuC,EAC/C,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,SAAiC,EAC3C,gBAAgB,SAA4B,EAC5C,IAAI,CAAC,EAAE,MAAM,GACZ,gBAAgB,CA4GlB;AAUD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAQlE"}
|
|
@@ -27,7 +27,15 @@
|
|
|
27
27
|
* window run-of-success is required. This guards against random dips
|
|
28
28
|
* that look like convergence but aren't.
|
|
29
29
|
*/
|
|
30
|
-
import { bootstrapMeanCI } from '../eval-core/bootstrap.js';
|
|
30
|
+
import { bootstrapMeanCI, DEFAULT_BOOTSTRAP_ALPHA, DEFAULT_BOOTSTRAP_SAMPLES } from '../eval-core/bootstrap.js';
|
|
31
|
+
/** Default consecutive-window run length required before declaring saturation. */
|
|
32
|
+
export const DEFAULT_SATURATION_WINDOW_SIZE = 3;
|
|
33
|
+
/**
|
|
34
|
+
* Default `bootstrap-ci-width` cutoff: declare saturation when the relative
|
|
35
|
+
* CI-width shrink per checkpoint stays under 5%. Single source of truth for
|
|
36
|
+
* the documented threshold; guarded by `doc-constants-drift.test.ts`.
|
|
37
|
+
*/
|
|
38
|
+
export const DEFAULT_CI_WIDTH_SHRINK_THRESHOLD = 0.05;
|
|
31
39
|
/**
|
|
32
40
|
* Compute saturation from a sequence of cumulative score arrays.
|
|
33
41
|
*
|
|
@@ -44,13 +52,13 @@ import { bootstrapMeanCI } from '../eval-core/bootstrap.js';
|
|
|
44
52
|
* @param bootstrapSamples Used only by 'bootstrap-ci-width' (default 1000).
|
|
45
53
|
* @param seed Optional seed for reproducible CIs.
|
|
46
54
|
*/
|
|
47
|
-
export function findSaturationPoint(cumulativeScores, method = 'bootstrap-ci-width', threshold, windowSize =
|
|
55
|
+
export function findSaturationPoint(cumulativeScores, method = 'bootstrap-ci-width', threshold, windowSize = DEFAULT_SATURATION_WINDOW_SIZE, bootstrapSamples = DEFAULT_BOOTSTRAP_SAMPLES, seed) {
|
|
48
56
|
const trace = [];
|
|
49
57
|
const checkpoints = [];
|
|
50
58
|
for (const scores of cumulativeScores) {
|
|
51
59
|
if (scores.length === 0)
|
|
52
60
|
continue;
|
|
53
|
-
const ci = bootstrapMeanCI(scores,
|
|
61
|
+
const ci = bootstrapMeanCI(scores, DEFAULT_BOOTSTRAP_ALPHA, bootstrapSamples, seed);
|
|
54
62
|
checkpoints.push({
|
|
55
63
|
n: scores.length,
|
|
56
64
|
mean: ci.estimate,
|
|
@@ -151,7 +159,7 @@ export function findSaturationPoint(cumulativeScores, method = 'bootstrap-ci-wid
|
|
|
151
159
|
function defaultThreshold(method) {
|
|
152
160
|
switch (method) {
|
|
153
161
|
case 'slope': return 0.005;
|
|
154
|
-
case 'bootstrap-ci-width': return
|
|
162
|
+
case 'bootstrap-ci-width': return DEFAULT_CI_WIDTH_SHRINK_THRESHOLD;
|
|
155
163
|
case 'plateau-height': return 0.1;
|
|
156
164
|
}
|
|
157
165
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"saturation.js","sourceRoot":"","sources":["../../src/analysis/saturation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"saturation.js","sourceRoot":"","sources":["../../src/analysis/saturation.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,28 @@ interface WeakSample {
|
|
|
15
15
|
none?: string;
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
|
-
export declare function extractWeakSamples(report: Report, variantKey: string, count?: number): WeakSample[];
|
|
18
|
+
export declare function extractWeakSamples(report: Report, variantKey: string, count?: number, sampleIdFilter?: Set<string>): WeakSample[];
|
|
19
|
+
/** A train / holdout partition of a sample set. */
|
|
20
|
+
interface HoldoutSplit {
|
|
21
|
+
trainIds: Set<string>;
|
|
22
|
+
holdoutIds: Set<string>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Deterministically split sample ids into train / holdout by `ratio` (fraction
|
|
26
|
+
* held out). Holdout members are picked at an even stride so the partition is
|
|
27
|
+
* representative of the ordering, and the split is stable across rounds and runs
|
|
28
|
+
* (no RNG). Returns null when ratio ≤ 0 or either side would drop below
|
|
29
|
+
* MIN_HOLDOUT_SUBSET — the caller then scores on the full set.
|
|
30
|
+
*/
|
|
31
|
+
export declare function splitHoldout(sampleIds: string[], ratio: number): HoldoutSplit | null;
|
|
32
|
+
/**
|
|
33
|
+
* A view of `report` whose results are restricted to `sampleIds`. Used to keep the
|
|
34
|
+
* holdout split out of the sample-fixer: under an active holdout, only training-split
|
|
35
|
+
* samples may enter the --auto-fix-samples prompt or be rewritten — otherwise the
|
|
36
|
+
* skill's samples get tuned to the very samples that decide acceptance, reintroducing
|
|
37
|
+
* the leak holdout exists to prevent.
|
|
38
|
+
*/
|
|
39
|
+
export declare function restrictReportToSamples(report: Report, sampleIds: Set<string>): Report;
|
|
19
40
|
export declare function allNonTripwireAssertionsPass(report: Report, variantKey: string): boolean;
|
|
20
41
|
export declare function buildImprovementPrompt(skillContent: string, score: number, weakSamples: WeakSample[]): string;
|
|
21
42
|
/** @deprecated Use ProgressCallback from evaluation-core.ts */
|
|
@@ -61,15 +82,26 @@ interface EvolveOptions {
|
|
|
61
82
|
noDiagnostic?: boolean;
|
|
62
83
|
/** 跳过 doctor 健康检查门禁。默认 false。 */
|
|
63
84
|
skipDoctor?: boolean;
|
|
85
|
+
/** Fraction of samples held out for the accept decision (0..1). Default 0 = off.
|
|
86
|
+
* When > 0, a candidate is accepted on its **holdout** composite rather than the
|
|
87
|
+
* training composite, and weak-sample extraction only sees the training split —
|
|
88
|
+
* so the skill is never tuned to the samples that judge it. Too small a split
|
|
89
|
+
* (either side < MIN_HOLDOUT_SUBSET) falls back to full-set scoring + a warning. */
|
|
90
|
+
holdoutRatio?: number;
|
|
64
91
|
onProgress?: ProgressCallback | null;
|
|
65
92
|
onRoundProgress?: ((progress: EvolveRoundProgressInfo) => void) | null;
|
|
66
93
|
}
|
|
67
94
|
interface TrajectoryEntry {
|
|
68
95
|
round: number;
|
|
96
|
+
/** Accept-decision score: holdout composite when holdout is active, else full-set. */
|
|
69
97
|
score: number;
|
|
70
98
|
delta: number;
|
|
71
99
|
accepted: boolean;
|
|
72
100
|
costUSD: number;
|
|
101
|
+
/** Present when holdout is active: the training-split composite (improvement signal). */
|
|
102
|
+
trainScore?: number;
|
|
103
|
+
/** Present when holdout is active: the holdout-split composite (== score). */
|
|
104
|
+
holdoutScore?: number;
|
|
73
105
|
}
|
|
74
106
|
export interface EvolveResult {
|
|
75
107
|
startScore: number;
|
|
@@ -86,6 +118,15 @@ export interface EvolveResult {
|
|
|
86
118
|
reusedBaselineReportId?: string;
|
|
87
119
|
/** False = 任一轮的 exec / judge 不报 cost → totalCostUSD 是 lower-bound 而非真值。 */
|
|
88
120
|
costReported?: boolean;
|
|
121
|
+
/** Holdout split summary when `--holdout-ratio` > 0. `disabled` is true when the
|
|
122
|
+
* split was too small and evolve fell back to full-set scoring (CLI formats the
|
|
123
|
+
* user-facing message bilingually). */
|
|
124
|
+
holdout?: {
|
|
125
|
+
ratio: number;
|
|
126
|
+
trainCount: number;
|
|
127
|
+
holdoutCount: number;
|
|
128
|
+
disabled?: boolean;
|
|
129
|
+
};
|
|
89
130
|
trajectory: TrajectoryEntry[];
|
|
90
131
|
bestSkillPath: string;
|
|
91
132
|
allVersions: string[];
|
|
@@ -97,6 +138,6 @@ export interface RoundReport {
|
|
|
97
138
|
report: Report;
|
|
98
139
|
}
|
|
99
140
|
export declare function mergeEvolveReports(roundReports: RoundReport[], skillName: string, totalCostUSD: number, samples?: Sample[], skillPath?: string): Report;
|
|
100
|
-
export declare function evolveSkill({ skillPath, samplesPath, rounds, target, stopOnAssertionsPass, autoFixSamples, sampleFixMaxAttempts, reuseLatestEval, model, judgeModels, improveModel, improveMode, executorName, concurrency, timeoutMs, skipConnectivity, effort, noDiagnostic, skipDoctor, onProgress, onRoundProgress, }: EvolveOptions): Promise<EvolveResult>;
|
|
141
|
+
export declare function evolveSkill({ skillPath, samplesPath, rounds, target, stopOnAssertionsPass, autoFixSamples, sampleFixMaxAttempts, reuseLatestEval, model, judgeModels, improveModel, improveMode, executorName, concurrency, timeoutMs, skipConnectivity, effort, noDiagnostic, skipDoctor, holdoutRatio, onProgress, onRoundProgress, }: EvolveOptions): Promise<EvolveResult>;
|
|
101
142
|
export {};
|
|
102
143
|
//# sourceMappingURL=evolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evolver.d.ts","sourceRoot":"","sources":["../../src/authoring/evolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"evolver.d.ts","sourceRoot":"","sources":["../../src/authoring/evolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import { persistReport, DEFAULT_OUTPUT_DIR, generateRunId, hashString } from '..
|
|
|
6
6
|
import { createFileStore } from '../server/report-store.js';
|
|
7
7
|
import { analyzeResults } from '../analysis/report-diagnostics.js';
|
|
8
8
|
import { loadSamples } from '../inputs/load-samples.js';
|
|
9
|
+
import { buildVariantSummary } from '../eval-core/schema.js';
|
|
9
10
|
import { fixSamples } from './sample-fixer.js';
|
|
10
11
|
const IMPROVE_SYSTEM_PROMPT = `你是一个 AI 提示词改进专家。你的任务是分析评测结果中的薄弱环节,针对性地改进 skill(系统提示词),使其在评测中获得更高的分数。
|
|
11
12
|
|
|
@@ -121,9 +122,11 @@ function readSkillName(skillPath) {
|
|
|
121
122
|
return null;
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
|
-
export function extractWeakSamples(report, variantKey, count = 5) {
|
|
125
|
+
export function extractWeakSamples(report, variantKey, count = 5, sampleIdFilter) {
|
|
125
126
|
const weakSamples = [];
|
|
126
127
|
for (const r of report.results) {
|
|
128
|
+
if (sampleIdFilter && !sampleIdFilter.has(r.sample_id))
|
|
129
|
+
continue;
|
|
127
130
|
const v = r.variants[variantKey];
|
|
128
131
|
if (!v || typeof v.compositeScore !== 'number')
|
|
129
132
|
continue;
|
|
@@ -153,6 +156,60 @@ export function extractWeakSamples(report, variantKey, count = 5) {
|
|
|
153
156
|
.sort((a, b) => a.compositeScore - b.compositeScore)
|
|
154
157
|
.slice(0, count);
|
|
155
158
|
}
|
|
159
|
+
/** Below this many samples on either side, a holdout split is too small to be
|
|
160
|
+
* meaningful — evolve falls back to full-set scoring and warns. */
|
|
161
|
+
const MIN_HOLDOUT_SUBSET = 3;
|
|
162
|
+
/**
|
|
163
|
+
* Deterministically split sample ids into train / holdout by `ratio` (fraction
|
|
164
|
+
* held out). Holdout members are picked at an even stride so the partition is
|
|
165
|
+
* representative of the ordering, and the split is stable across rounds and runs
|
|
166
|
+
* (no RNG). Returns null when ratio ≤ 0 or either side would drop below
|
|
167
|
+
* MIN_HOLDOUT_SUBSET — the caller then scores on the full set.
|
|
168
|
+
*/
|
|
169
|
+
export function splitHoldout(sampleIds, ratio) {
|
|
170
|
+
if (!(ratio > 0) || sampleIds.length === 0)
|
|
171
|
+
return null;
|
|
172
|
+
const holdoutCount = Math.round(sampleIds.length * ratio);
|
|
173
|
+
const trainCount = sampleIds.length - holdoutCount;
|
|
174
|
+
if (holdoutCount < MIN_HOLDOUT_SUBSET || trainCount < MIN_HOLDOUT_SUBSET)
|
|
175
|
+
return null;
|
|
176
|
+
const stride = sampleIds.length / holdoutCount;
|
|
177
|
+
const holdoutIds = new Set();
|
|
178
|
+
for (let k = 0; k < holdoutCount; k++) {
|
|
179
|
+
holdoutIds.add(sampleIds[Math.floor(k * stride)]);
|
|
180
|
+
}
|
|
181
|
+
const trainIds = new Set(sampleIds.filter((id) => !holdoutIds.has(id)));
|
|
182
|
+
return { trainIds, holdoutIds };
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Mean composite over the subset of a report's results whose sample_id is in
|
|
186
|
+
* `ids`, using the same aggregation as the full-run summary
|
|
187
|
+
* (`buildVariantSummary`) so train / holdout scores stay comparable to the
|
|
188
|
+
* headline composite. Returns 0 when the subset has no scorable entries.
|
|
189
|
+
*/
|
|
190
|
+
function subsetCompositeScore(report, variantKey, ids) {
|
|
191
|
+
const entries = [];
|
|
192
|
+
for (const r of report.results) {
|
|
193
|
+
if (!ids.has(r.sample_id))
|
|
194
|
+
continue;
|
|
195
|
+
const v = r.variants[variantKey];
|
|
196
|
+
if (v)
|
|
197
|
+
entries.push(v);
|
|
198
|
+
}
|
|
199
|
+
if (entries.length === 0)
|
|
200
|
+
return 0;
|
|
201
|
+
return buildVariantSummary(entries).avgCompositeScore ?? 0;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* A view of `report` whose results are restricted to `sampleIds`. Used to keep the
|
|
205
|
+
* holdout split out of the sample-fixer: under an active holdout, only training-split
|
|
206
|
+
* samples may enter the --auto-fix-samples prompt or be rewritten — otherwise the
|
|
207
|
+
* skill's samples get tuned to the very samples that decide acceptance, reintroducing
|
|
208
|
+
* the leak holdout exists to prevent.
|
|
209
|
+
*/
|
|
210
|
+
export function restrictReportToSamples(report, sampleIds) {
|
|
211
|
+
return { ...report, results: report.results.filter((r) => sampleIds.has(r.sample_id)) };
|
|
212
|
+
}
|
|
156
213
|
export function allNonTripwireAssertionsPass(report, variantKey) {
|
|
157
214
|
for (const entry of report.results) {
|
|
158
215
|
const variant = entry.variants[variantKey];
|
|
@@ -401,7 +458,7 @@ export function mergeEvolveReports(roundReports, skillName, totalCostUSD, sample
|
|
|
401
458
|
report.analysis = analyzeResults(report, { samples });
|
|
402
459
|
return report;
|
|
403
460
|
}
|
|
404
|
-
export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target = null, stopOnAssertionsPass = false, autoFixSamples = false, sampleFixMaxAttempts = 2, reuseLatestEval = false, model = DEFAULT_MODEL, judgeModels, improveModel = DEFAULT_MODEL, improveMode = 'agent', executorName = 'claude', concurrency = 1, timeoutMs, skipConnectivity = false, effort, noDiagnostic, skipDoctor, onProgress = null, onRoundProgress = null, }) {
|
|
461
|
+
export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target = null, stopOnAssertionsPass = false, autoFixSamples = false, sampleFixMaxAttempts = 2, reuseLatestEval = false, model = DEFAULT_MODEL, judgeModels, improveModel = DEFAULT_MODEL, improveMode = 'agent', executorName = 'claude', concurrency = 1, timeoutMs, skipConnectivity = false, effort, noDiagnostic, skipDoctor, holdoutRatio = 0, onProgress = null, onRoundProgress = null, }) {
|
|
405
462
|
if (judgeModels && judgeModels.length > 1) {
|
|
406
463
|
throw new Error('evolveSkill does not support multi-judge ensemble (received '
|
|
407
464
|
+ `${judgeModels.length} judges). Pass a single-judge array, e.g. `
|
|
@@ -421,6 +478,28 @@ export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target =
|
|
|
421
478
|
if (!existsSync(absSamplesPath))
|
|
422
479
|
throw new Error(`samples file not found: ${absSamplesPath}`);
|
|
423
480
|
mkdirSync(evolveDir, { recursive: true });
|
|
481
|
+
// Holdout split (opt-in). Computed once over the canonical sample order so it's
|
|
482
|
+
// stable across rounds. When active, accept decisions use the holdout composite
|
|
483
|
+
// and weak-sample extraction only sees the training split — the skill is never
|
|
484
|
+
// tuned to the samples that decide whether it's accepted.
|
|
485
|
+
const allSampleIds = loadSamples(absSamplesPath).samples.map((s) => s.sample_id);
|
|
486
|
+
const holdoutSplit = splitHoldout(allSampleIds, holdoutRatio);
|
|
487
|
+
const holdoutInfo = holdoutRatio > 0
|
|
488
|
+
? {
|
|
489
|
+
ratio: holdoutRatio,
|
|
490
|
+
trainCount: holdoutSplit?.trainIds.size ?? allSampleIds.length,
|
|
491
|
+
holdoutCount: holdoutSplit?.holdoutIds.size ?? 0,
|
|
492
|
+
...(holdoutSplit ? {} : { disabled: true }),
|
|
493
|
+
}
|
|
494
|
+
: undefined;
|
|
495
|
+
// Accept-decision score for a report's variant: holdout composite when the split
|
|
496
|
+
// is active, otherwise the full-set composite (legacy behavior).
|
|
497
|
+
const decisionScore = (report, key) => holdoutSplit
|
|
498
|
+
? subsetCompositeScore(report, key, holdoutSplit.holdoutIds)
|
|
499
|
+
: (report.summary[key]?.avgCompositeScore ?? 0);
|
|
500
|
+
const trainScoreOf = (report, key) => holdoutSplit ? subsetCompositeScore(report, key, holdoutSplit.trainIds) : undefined;
|
|
501
|
+
// Per-round trajectory tail: train / holdout breakdown, only when split active.
|
|
502
|
+
const splitScores = (report, key, decision) => holdoutSplit ? { trainScore: trainScoreOf(report, key), holdoutScore: decision } : {};
|
|
424
503
|
// Save original as r0
|
|
425
504
|
let currentBest = readFileSync(absSkillPath, 'utf-8').trim();
|
|
426
505
|
const r0Path = join(evolveDir, `${skillName}.r0.md`);
|
|
@@ -461,13 +540,13 @@ export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target =
|
|
|
461
540
|
});
|
|
462
541
|
}
|
|
463
542
|
const baselineVariantKey = Object.keys(baselineReport.summary)[0];
|
|
464
|
-
bestScore = baselineReport
|
|
543
|
+
bestScore = decisionScore(baselineReport, baselineVariantKey);
|
|
465
544
|
const baselineCost = baselineReused ? 0 : baselineReport.meta.totalCostUSD;
|
|
466
545
|
totalCostUSD += baselineCost;
|
|
467
546
|
const baselineCostReported = baselineReused || !reportHasUnreportedCost(baselineReport);
|
|
468
547
|
if (!baselineCostReported)
|
|
469
548
|
totalCostReported = false;
|
|
470
|
-
trajectory.push({ round: 0, score: bestScore, delta: 0, accepted: true, costUSD: baselineCost });
|
|
549
|
+
trajectory.push({ round: 0, score: bestScore, delta: 0, accepted: true, costUSD: baselineCost, ...splitScores(baselineReport, baselineVariantKey, bestScore) });
|
|
471
550
|
roundReports.push({ round: 0, accepted: true, report: baselineReport });
|
|
472
551
|
if (onRoundProgress)
|
|
473
552
|
onRoundProgress({ round: 0, totalRounds: rounds, phase: 'baseline', score: bestScore, costUSD: baselineCost, costReported: baselineCostReported, reused: baselineReused });
|
|
@@ -487,6 +566,7 @@ export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target =
|
|
|
487
566
|
...(sampleFixes.length > 0 && { sampleFixes }),
|
|
488
567
|
...(reusedBaselineReportId && { reusedBaselineReportId }),
|
|
489
568
|
...(totalCostReported ? {} : { costReported: false }),
|
|
569
|
+
...(holdoutInfo ? { holdout: holdoutInfo } : {}),
|
|
490
570
|
trajectory,
|
|
491
571
|
bestSkillPath: allVersions[bestRound],
|
|
492
572
|
allVersions,
|
|
@@ -513,7 +593,7 @@ export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target =
|
|
|
513
593
|
totalCostReported = false;
|
|
514
594
|
}
|
|
515
595
|
const lastVariantKey = Object.keys(lastReport.summary)[0];
|
|
516
|
-
const weakSamples = extractWeakSamples(lastReport, lastVariantKey);
|
|
596
|
+
const weakSamples = extractWeakSamples(lastReport, lastVariantKey, 5, holdoutSplit?.trainIds);
|
|
517
597
|
// Generate improvement
|
|
518
598
|
const candidatePath = join(evolveDir, `${skillName}.r${round}.md`);
|
|
519
599
|
const basePrompt = buildImprovementPrompt(currentBest, bestScore, weakSamples);
|
|
@@ -575,7 +655,9 @@ export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target =
|
|
|
575
655
|
const sampleFix = await autoFixSamplesAfterSkillRound({
|
|
576
656
|
samplesPath: absSamplesPath,
|
|
577
657
|
skillContent: candidateContent,
|
|
578
|
-
|
|
658
|
+
// Under an active holdout, the sample-fixer may only see training-split samples —
|
|
659
|
+
// never the holdout samples that drive the accept decision (leak guard).
|
|
660
|
+
report: holdoutSplit ? restrictReportToSamples(lastReport, holdoutSplit.trainIds) : lastReport,
|
|
579
661
|
treatmentKey: lastVariantKey,
|
|
580
662
|
executorName,
|
|
581
663
|
model: improveModel,
|
|
@@ -593,7 +675,7 @@ export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target =
|
|
|
593
675
|
samplesPath: absSamplesPath, skillDir, model, judgeModels: effectiveJudgeModels, executorName, concurrency, timeoutMs, skipConnectivity, effort, noDiagnostic, skipDoctor, onProgress,
|
|
594
676
|
});
|
|
595
677
|
const candidateVariantKey = Object.keys(candidateReport.summary)[0];
|
|
596
|
-
const candidateScore = candidateReport
|
|
678
|
+
const candidateScore = decisionScore(candidateReport, candidateVariantKey);
|
|
597
679
|
const roundCost = improveCostUSD + preEvalSampleFixCost + candidateReport.meta.totalCostUSD;
|
|
598
680
|
const roundCostReported = improveCostReported && !reportHasUnreportedCost(candidateReport);
|
|
599
681
|
if (!roundCostReported)
|
|
@@ -612,7 +694,7 @@ export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target =
|
|
|
612
694
|
if (accepted)
|
|
613
695
|
roundReports.push({ round, accepted, report: candidateReport });
|
|
614
696
|
const roundDelta = candidateScore - trajectory[trajectory.length - 1].score;
|
|
615
|
-
trajectory.push({ round, score: candidateScore, delta: roundDelta, accepted, costUSD: roundCost });
|
|
697
|
+
trajectory.push({ round, score: candidateScore, delta: roundDelta, accepted, costUSD: roundCost, ...splitScores(candidateReport, candidateVariantKey, candidateScore) });
|
|
616
698
|
if (onRoundProgress)
|
|
617
699
|
onRoundProgress({ round, totalRounds: rounds, phase: 'done', score: candidateScore, delta: roundDelta, accepted, costUSD: roundCost, costReported: roundCostReported });
|
|
618
700
|
// Early stop
|
|
@@ -652,6 +734,7 @@ export async function evolveSkill({ skillPath, samplesPath, rounds = 5, target =
|
|
|
652
734
|
...(sampleFixes.length > 0 && { sampleFixes }),
|
|
653
735
|
...(reusedBaselineReportId && { reusedBaselineReportId }),
|
|
654
736
|
...(totalCostReported ? {} : { costReported: false }),
|
|
737
|
+
...(holdoutInfo ? { holdout: holdoutInfo } : {}),
|
|
655
738
|
trajectory,
|
|
656
739
|
bestSkillPath: allVersions[bestRound],
|
|
657
740
|
allVersions,
|