From f0fcd2587a0ca95ec7c83e9f3e0c0152a9ce6709 Mon Sep 17 00:00:00 2001 From: Niraya666 <492477510@qq.com> Date: Thu, 16 Jul 2026 16:18:23 +0800 Subject: [PATCH 1/2] docs: trajectory-distillation design (weakness -> executable held-out tasks) New design doc: distill recorded trajectories + mined weaknesses into EvalTaskSpec candidates (fixture + prompt + argv verifier), deterministically verified (fail-before) and human-accepted into the held-out suite -- the judge's task set grows with observed weaknesses instead of staying hand-written. Cross-link weakness-mining-design.md: the evaluator surface row (was 'semi-closed') now points here; the effectiveness-signal residual is marked design-ready. --- docs/trajectory-distillation.md | 223 ++++++++++++++++++++++++++++++++ docs/weakness-mining-design.md | 4 +- 2 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 docs/trajectory-distillation.md diff --git a/docs/trajectory-distillation.md b/docs/trajectory-distillation.md new file mode 100644 index 0000000..e85bcbc --- /dev/null +++ b/docs/trajectory-distillation.md @@ -0,0 +1,223 @@ +# Trajectory Distillation — 设计文档 + +> 状态:Draft v1 · 2026-07-16 +> 关联:[weakness-mining-design.md](weakness-mining-design.md)(弱点从哪来)· [agent-harness-design.md](agent-harness-design.md)(内核与边界哲学) +> 回答的问题:weakness-mining-design.md §10.4 —— "eval 太窄会让下游 Outer Loop 过拟合……扩 eval + held-out split 是硬要求,不是可选项。" + +--- + +## 0. 一句话 + +把已录制的轨迹(连同其上挖出的弱点)蒸馏成**可执行的 `EvalTaskSpec` 候选**(fixture + prompt + argv verifier),经确定性健全检查与人工 accept 后进入 held-out suite——让裁判的任务集随观察到的弱点**增长**,而不是永远停留在手写的 2 个任务上。 + +--- + +## 1. 目标与非目标 + +### 1.1 目标 + +- **弱点 → 回归任务**:每个高 support 的 playbook entry 都应能沉淀为至少一个可执行任务,使"该机制不复发"成为 gate 可以差分检验的命题。今天的 `artifact_survives_recovery.json` 就是一个手工蒸馏样本(从 `artifact_lost_after_error` 机制反推出来的任务);本设计把这门手工艺变成流水线的 **candidate 生成**环节,人只保留 accept 权。 +- **成功轨迹 → smoke 任务**(后期):稳定完成的任务类型蒸馏为 capability smoke,防止 harness edit 伤害已会的能力。 +- **全程 proposal-first**:蒸馏产物只是 candidate,落在 `.agent-harness/` 下;进 suite 是显式人类动作(git commit)。 +- **零新格式**:产物就是现有 `EvalTaskSpec` JSON + fixture 目录,`load_eval_task` / `load_eval_suite` / 两个 gate 原样消费。 + +### 1.2 非目标 + +- 不做跨平台(Claude Code / Codex / Hermes)轨迹 ingest 与蒸馏——那是 traj-lab 的地盘(见附录)。 +- 不做 SFT / preference 数据集导出——同上,需要跨平台数据体量,OkComputer 单 harness 轨迹量不够也不必要。 +- v1 不做 LLM-judge / rubric 打分型评测——蒸馏产物必须是 **argv verifier 可执行任务**,确定性优先。 +- **永不自动把任务加进 suite**。裁判只能由人扩。 + +### 1.3 设计原则(继承内核章程) + +1. 内核冻结:`AgentLoop` / `Workspace` / `ToolRuntime` 一字不改;蒸馏整体是可删除扩展。 +2. 确定性优先:LLM 只出现在一处(distiller subagent 合成 task + fixture);校验、生命周期、lineage 检查全部确定性。 +3. proposal-first:candidate ≠ 裁判;accept 前它什么都不是。 +4. **蒸馏产生裁判,所以蒸馏必须离裁判最远**——这是本文的安全命门(§6)。 + +--- + +## 2. 架构总览 + +``` +.agent-harness/sessions// weakness proposals / playbook [已有] + events.jsonl · transcript.jsonl │ + │ │ + └───────────────┬──────────────────────┘ + ▼ + okc distill --from-session + okc distill --from-playbook + │ spawn(TaskManager, fresh) + ▼ + Distiller Subagent(LLM,可删除扩展) + · 读 trajectory digest(复用 build_trajectory_digest) + · 合成最小 fixture(不是拷贝用户 workspace) + · 写 prompt(源自原始任务意图,脱敏、最小化) + · 写 argv verifier(断言 outcome + 弱点机制的可观测后果) + │ 产物只写入 + ▼ + .agent-harness/eval_candidates// + task.json · fixture/ · provenance.json [gitignored] + │ + okc distill --verify ← 确定性反任务校验(§5) + │ + okc distill --list / --accept / --reject ← 人审,append-only ledger + │ + 人工 promote:拷入 tests/e2e/tasks + fixtures,加进 suite,git commit + ▼ + ═══ 冻结面 ═══ held_out.json / regression suites + (此后任何自动流程——包括 distiller 自己——不得触碰) +``` + +| 层 | 组件 | 归属 | +|---|---|---| +| 已有 | EventLog、mining proposals、playbook、`EvalTaskSpec`/`load_eval_suite`、两个 gate | 不改 | +| 新增扩展 | `distill.py`(CLI + 校验 + ledger)、distiller TaskProfile、可选 `distill-rubric` skill | 全可删 | +| 冻结面 | `tests/e2e/tasks` / `fixtures` / `suites`、verifier、gate 逻辑 | 只有人能改 | + +**验收不变量**:删掉 distill 扩展后,`okc run` / `okc mine` / `okc gate` 行为与今天逐字节一致。 + +--- + +## 3. Candidate 数据契约 + +``` +.agent-harness/eval_candidates// +├── task.json # 严格的 EvalTaskSpec 字段集——load_eval_task 必须能直接加载 +├── fixture/ # 最小合成 fixture(task.json 的 fixture_path 指向它) +└── provenance.json # 蒸馏来源,格式如下 +``` + +`provenance.json`: + +```json +{ + "producer": "distiller", + "source_sessions": ["", "..."], + "playbook_entry": "", + "weakness_signature": { "agent_mechanism": "...", "editable_surface": "...", "..." : "..." }, + "trace_refs": ["events.jsonl#", "..."], + "distill_rubric_version": "distill-rubric@", + "known_good_solution": "<人审用:一段说明该任务如何被正确完成>", + "status": "candidate | verified | accepted | rejected", + "verify_report": { "fail_before": true, "verifier_runnable": true, "duration_s": 1.2 } +} +``` + +约定与 mining 的 provenance(weakness-mining-design.md §3.3)同构:**只存 trace 引用,不复制原文**——candidate 里唯一的"内容"是合成 fixture,不是用户轨迹片段。 + +`task.json` 额外约定两个 tag:`distilled` + 机制名(如 `blocked_retry_loop`),供 suite 去重与后续统计。 + +--- + +## 4. 蒸馏的两半:outcome 断言与机制断言 + +一个从弱点蒸馏出的任务要同时回答两件事: + +1. **任务本身可完成**(outcome 半):verifier 断言交付物存在、测试通过——与现有手写任务无异。 +2. **弱点机制不复发**(mechanism 半):这是蒸馏任务的存在理由。 + +mechanism 半的表达方式,按确定性从高到低: + +| 层 | 表达方式 | v1 | +|---|---|---| +| verifier 内断言 | 机制有**文件系统可观测后果**时直接断言(如 `artifact_lost_after_error` → "data.txt 必须原样",即 `artifact_survives_recovery` 的做法) | ✅ 首选 | +| fixture 结构诱导 | fixture 刻意布置触发条件(易误删的产物、会失败一次的测试、诱导重试的报错信息),使"踩坑"必然反映到 outcome | ✅ | +| metrics 预算 | `max_model_calls` 收紧为"正常解法 + 小余量"——polling / retry 型机制烧预算,超了即 fail | ✅(粗但确定) | +| metrics 差分 | gate 层比较 `EvalMetrics.model_calls / tool_batches` 的回归 | 后期,不进 v1 | + +诚实的边界:**不是所有机制都能蒸馏**。`over_exploration`、`serial_tool_underuse` 这类只在 metrics 上可见的机制,v1 只能靠预算收紧粗略覆盖;蒸馏优先级应给 `editable_surface` 可闭环、且机制有文件系统后果的 playbook entry。distiller 对蒸不动的 entry 应显式产出 `skip + 原因`,而不是硬造一个测不到点子上的任务。 + +--- + +## 5. 反任务校验(`okc distill --verify`) + +蒸馏出的 verifier 本身不可信,accept 前必须过两道**确定性、零 API**检查: + +1. **fail-before**:在裸 fixture 上直接跑 verifier,**必须失败**。空过的 verifier 什么都没测——这是挡"太松"的硬门。 +2. **runnable**:verifier argv 可执行、在 timeout 内退出、fixture 可被 `load_eval_task` 加载且 `_copy_fixture` 可复制。 + +"太紧"(正确解法也过不了)无法确定性检验,v1 靠两个软措施:provenance 里强制 `known_good_solution` 字段供人审对照;后期可选用 scripted transport 重放一个理想解证明 verifier 可满足(复用 `regression_fixtures.py` 的手法,仍零 API)。 + +未过 `--verify` 的 candidate 不允许 `--accept`——ledger 层面硬约束。 + +--- + +## 6. 安全命门:蒸馏与裁判的距离 + +蒸馏是整条自我改进链里唯一**生产裁判**的环节,因此它是 reward hacking 的最高价值目标。四条纪律: + +1. **candidate 与 suite 物理隔离**:candidate 住 `.agent-harness/`(gitignored),suite 住 `tests/e2e/`(git 管控)。promote 必须经过 git commit——人是唯一的搬运工。`okc distill` 不提供任何写 `tests/e2e/` 的代码路径,连 `--promote` 也只打印"该拷贝哪些文件"的指引。 +2. **accept 后即冻结**:已 promote 的任务进入冻结面,distiller、proposer、apply 层在结构上够不到(同 weakness-mining-design.md §5.6 的冻结面纪律,此处再加一员)。 +3. **held-out 卫生(lineage 排除)**:从 session S 蒸馏的任务,**不得**用于验证"由 S 的弱点催生的 harness edit"——那是用作业题当期末考。确定性检查:holdout gate 装配 suite 时,比对任务 provenance 的 `source_sessions` 与待验 edit 的 provenance `source_sessions`,相交则该任务从本次差分中排除(排除后 suite 为空则拒绝出结论,报"需要无关任务")。这就是 held-in / held-out split 在蒸馏时代的具体形态。 +4. **distiller 权限最小化**:TaskProfile `context_mode="fresh"`,工具面 = 只读(`read_file` / `search_text` / `list_files`)+ 仅限 `eval_candidates//` 子树的写入。不给 shell,不给 `memory_propose`——蒸馏不是挖掘,它不写知识,只写 candidate 文件。 + +--- + +## 7. Fixture 合成(最难的一环,诚实处理) + +真实 workspace 不能当 fixture:有隐私、有体积、有不可复现的外部状态。distiller 的任务是**合成最小等价物**——一个刚好能触发该弱点机制、且任务可在 ≤10 个 model call 内完成的玩具环境(对齐现有 fixture 的粒度:`artifact_survives_recovery` 是 3 个小文件)。 + +这意味着接受一个语义降级:**蒸馏任务证明的是"该机制在该 fixture 上不复发",不是"原任务被修好了"**。这正是回归任务的正确语义——我们要的是机制级覆盖,不是案例级复现。原始轨迹只通过 `trace_refs` 留在 provenance 里供人审溯源,不进 fixture。 + +合成失败(机制依赖无法本地化的外部状态,如真实网络服务)时,distiller 显式 skip。v1 不做 checkpoint 快照回放——`checkpoints/` 里的真实工作区内容有同样的隐私/体积问题,留作后期可选路径。 + +--- + +## 8. 对现有模块的映射(复用清单) + +| 需求 | 复用现有 | 新增(扩展) | +|---|---|---| +| 轨迹读取 | `build_trajectory_digest`(mining.py:161)+ `read_file`/`search_text` | —— | +| 弱点来源 | `kind="weakness"` proposals + `weakness_playbook.py` 的 `(id, description)` entry | —— | +| 隔离执行 | `TaskManager.spawn` + `TaskProfile(context_mode="fresh")` | `eval-distiller` profile | +| 任务格式 | `EvalTaskSpec` / `load_eval_task` / `load_eval_suite`(eval.py) | —— | +| 校验执行 | `VerifierSpec` argv 执行路径、`_copy_fixture` | `--verify` 的 fail-before 检查 | +| 生命周期 | 学 `harness_edits_apply.py` 的 append-only ledger + 显式状态机 | `eval_candidates` ledger | +| lineage 排除 | `holdout_gate.make_eval_suite_runner` 的 suite 装配点 | provenance 相交过滤器 | +| CLI | `run.py` CLI 框架 | `okc distill` 子命令 | +| taxonomy | skills 注入机制 | 可选 `distill-rubric/SKILL.md`(哪些机制值得蒸、fixture 合成守则) | + +--- + +## 9. 分阶段落地 + +**P0 · 契约与手动通路** +`eval_candidates/` 数据契约 + `okc distill --verify/--list/--accept/--reject`(ledger,确定性,零 API)。此阶段 candidate 由人手写——先让生命周期和校验跑通,蒸馏智能后置。产出即有用:手写新 held-out 任务从此有了标准校验与台账。 + +**P1 · LLM distiller** +`okc distill --from-session ` / `--from-playbook `:spawn distiller subagent,digest → task.json + fixture + provenance。scripted-transport 外壳测试保证管线确定性可测,真实蒸馏按需花预算。 + +**P2 · lineage 排除接进 holdout gate** +provenance 相交过滤器 + "排除后为空则拒绝出结论"。从此 `okc gate --validate-held-out` 的结论带 held-out 卫生保证。 + +**P3 · 成功轨迹与 metrics 半** +成功轨迹 cluster → capability smoke 任务;`EvalMetrics` 差分(model_calls 回归)进 gate 的对比维度。 + +--- + +## 10. 风险与取舍(诚实) + +1. **fixture 合成失真**:玩具环境可能触发不了真实机制。缓解:fail-before 校验 + 人审 `known_good_solution`;接受"机制级近似"的语义(§7),不追求案例复现。 +2. **蒸馏费 token**:只对 playbook 高 occurrence entry 蒸,批量跑,`--from-playbook` 是主入口而非逐 session 扫。 +3. **任务同质化**:同一 entry 蒸多次会得到近亲任务。缓解:`distilled` + 机制 tag 去重,promote 时人审"这个机制是否已有覆盖"。 +4. **verifier 太紧**:确定性校验只能挡太松(fail-before),太紧靠 `known_good_solution` 人审 + 后期理想解回放。接受 v1 的这个盲区。 +5. **suite 膨胀让 held-out gate 变贵**:real-provider 差分是双倍成本。缓解:suite 分层——core(每次差分必跑)+ extended(按机制采样轮换);蒸馏任务默认进 extended,人工提拔进 core。 +6. **最微妙的风险——用自己的弱点考自己**:蒸馏任务天然偏向"已见过的失败",suite 会漂向历史弱点分布,对未知失败盲。缓解只有纪律:手写任务不停止增补;蒸馏任务在 suite 中占比可见(tag 统计),不许淹没手写核心。 + +--- + +## 11. 测试策略 + +- **契约测试**:candidate 的 task.json 能被 `load_eval_task` 加载;provenance 必填字段齐全。 +- **fail-before 纯函数测试**:给定"空过 verifier"的 candidate,`--verify` 必须拒绝。 +- **ledger 状态机测试**:未 verify 不可 accept;accept/reject append-only;重复操作幂等。 +- **lineage 过滤测试**:构造 source_sessions 相交/不相交的任务与 edit,断言排除行为与"空 suite 拒绝出结论"。 +- **distiller 外壳测试**:scripted transport 喂固定轨迹 digest,断言产出 candidate 目录结构与 task.json 字段(零 API)。 +- **解耦不变量**:不装 distill 扩展,现有全部测试套件保绿。 + +--- + +## 附:与 traj-lab 的关系 + +分界依据"谁拥有执行环境":**可执行评测蒸馏住在 OkComputer**——它拥有 `EvalRunner`、`Workspace` 沙箱和两个 gate,蒸馏产物有现成消费者;**traj-lab 做它独有的事**——跨平台轨迹的 rubric / LLM-judge 评测集与数据集(SFT / preference)蒸馏,那需要多 agent ingest 的数据体量,且不需要执行环境。两边的交换物是 `WeaknessSignature` / evidence bundle JSON(模型已同构),由人决定是否转写为对方形态的任务,不建自动管线。**依旧:借脑,不借水管。** diff --git a/docs/weakness-mining-design.md b/docs/weakness-mining-design.md index 3cac6d2..deeb5c1 100644 --- a/docs/weakness-mining-design.md +++ b/docs/weakness-mining-design.md @@ -188,7 +188,7 @@ LLM 聚合(合并同义机制、命名 cluster)仅作 opt-in 第二层,处 | `harness_runtime` | HookBus 策略 / RunPolicy / loop-breaker 配置 | 可闭环 | | `context_config` | `ContextBudget` 旋钮 | 可闭环(皇冠明珠自调) | | `skill` | skill candidate | 可闭环 | -| `evaluator` | eval 校准 / 回归任务 | 半闭环 | +| `evaluator` | eval 校准 / 回归任务 | ~~半闭环~~ → proposal-first 闭环:弱点蒸馏成 `EvalTaskSpec` 候选,人是唯一的 promote 通道(设计见 [trajectory-distillation.md](trajectory-distillation.md)) | | `personal_workflow` | 用户侧建议 | **开环(仅人看)** | > **安全命门**:`evaluator` 及 eval fixtures / verifier 属于**冻结面**——mining 可以*建议*校准,但 Outer Loop 的自动应用永远不许改裁判,否则 reward hacking。冻结面 vs 优化面写进 AGENTS.md「禁止」清单。 @@ -262,7 +262,7 @@ run 任务 ──emit──► EventLog(events.jsonl / transcript.jsonl) [核 - **提议器(stage-2 v1)**:`harness_proposer.py` —— 读 playbook entry 的 `editable_surface` → 产**有界 mechanics edit**(白名单 `SessionControllerConfig` 旋钮,冻结面结构上够不到)→ 过 held-in 差分门 → **proposal-first 落 pending**(`.agent-harness/harness_edits/proposals.jsonl`),绝不自动应用。`okc propose`。Proposer 可插拔;种子 `RuleBasedProposer` 确定性零 API。 - **LLM proposer tier** ✅ 已落地:`llm_proposer.py`(`okc propose --llm`)toolless agent 产 JSON edit 数组 → 按 surface 路由;prompt-space 落地面为新建的 `system_prompt_addendum` 有界 overlay(`session_controller.py`,`danger_reason` + 长度守卫);prompt edit 走 `holdout_gate.py` 的 real-provider held-out 差分门(`--validate-held-out`,否则 `pending_unvalidated`)。管线确定性可测,真实验证按需花预算。 - **accepted edit 应用/回滚面** ✅ 已落地:`harness_edits_apply.py`(`okc edits`)—— append-only accept/revert ledger + **每 workspace apply 开关**(默认关,方案 A);`apply_accepted_harness_edits` 在 top-level `okc run`/`chat`/tui 合并 active edits,apply 时重验白名单 + 重筛 overlay(纵深防御);受约束的 miner/proposer/gate 直接构建 config,不受影响。系统由**建议器**变**改进器**。 -- **仍未做(最后一条)**:「有效性」判据(weakness 复发下降 / held-out 成功率提升,当前门只证 safe 不证 helps);skill-file edit surface。冻结面纪律:loop/eval/verifier 永不进白名单。 +- **仍未做(最后一条)**:「有效性」判据(weakness 复发下降 / held-out 成功率提升,当前门只证 safe 不证 helps)——**设计已就绪、实现未动**:[trajectory-distillation.md](trajectory-distillation.md) 把弱点蒸馏为可执行 held-out 任务,让"该机制不复发"成为 gate 可差分检验的命题;skill-file edit surface。冻结面纪律:loop/eval/verifier 永不进白名单,蒸馏候选与 suite 物理隔离、人是唯一 promote 通道。 --- From c21d770b051a2a9feb9297dca291443b343b7758 Mon Sep 17 00:00:00 2001 From: Niraya666 <492477510@qq.com> Date: Thu, 16 Jul 2026 17:52:04 +0800 Subject: [PATCH 2/2] docs(distill): lineage must travel with task.json; fix CLI names + drop line number The lineage-exclusion filter reads source_sessions at holdout-suite assembly, but provenance.json stays in the gitignored candidate dir and does not survive promote. Carry source_sessions on task.json itself (optional EvalTaskSpec field, empty for hand-written tasks so they are never excluded). Also: correct the held-out gate entry points (okc propose --llm --validate-held-out / okc edits --revalidate), and drop a rot-prone mining.py line number. --- docs/trajectory-distillation.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/trajectory-distillation.md b/docs/trajectory-distillation.md index e85bcbc..70110ec 100644 --- a/docs/trajectory-distillation.md +++ b/docs/trajectory-distillation.md @@ -108,6 +108,8 @@ `task.json` 额外约定两个 tag:`distilled` + 机制名(如 `blocked_retry_loop`),供 suite 去重与后续统计。 +**lineage 必须随任务走**:`task.json` 本身携带可选字段 `source_sessions`(`EvalTaskSpec` 增加一个默认为空的 field,`load_eval_task` 容忍缺失)。这是刻意的冗余——`provenance.json` 留在 gitignored 的 candidate 目录,promote 时只有 `task.json + fixture` 进 `tests/e2e/`,若 lineage 只住 provenance,§6.3 的排除过滤器在 promote 那一步就失去了数据。放在 `task.json` 上还让手写任务与蒸馏任务形态统一:手写任务的 `source_sessions` 天然为空 → 永不被排除,语义正好。 + --- ## 4. 蒸馏的两半:outcome 断言与机制断言 @@ -149,7 +151,7 @@ mechanism 半的表达方式,按确定性从高到低: 1. **candidate 与 suite 物理隔离**:candidate 住 `.agent-harness/`(gitignored),suite 住 `tests/e2e/`(git 管控)。promote 必须经过 git commit——人是唯一的搬运工。`okc distill` 不提供任何写 `tests/e2e/` 的代码路径,连 `--promote` 也只打印"该拷贝哪些文件"的指引。 2. **accept 后即冻结**:已 promote 的任务进入冻结面,distiller、proposer、apply 层在结构上够不到(同 weakness-mining-design.md §5.6 的冻结面纪律,此处再加一员)。 -3. **held-out 卫生(lineage 排除)**:从 session S 蒸馏的任务,**不得**用于验证"由 S 的弱点催生的 harness edit"——那是用作业题当期末考。确定性检查:holdout gate 装配 suite 时,比对任务 provenance 的 `source_sessions` 与待验 edit 的 provenance `source_sessions`,相交则该任务从本次差分中排除(排除后 suite 为空则拒绝出结论,报"需要无关任务")。这就是 held-in / held-out split 在蒸馏时代的具体形态。 +3. **held-out 卫生(lineage 排除)**:从 session S 蒸馏的任务,**不得**用于验证"由 S 的弱点催生的 harness edit"——那是用作业题当期末考。确定性检查:holdout gate 装配 suite 时,比对任务 `task.json` 的 `source_sessions`(见 §3——lineage 随任务进 suite,不依赖留在 candidate 目录里的 provenance)与待验 edit 的 provenance `source_sessions`,相交则该任务从本次差分中排除(排除后 suite 为空则拒绝出结论,报"需要无关任务")。这就是 held-in / held-out split 在蒸馏时代的具体形态。 4. **distiller 权限最小化**:TaskProfile `context_mode="fresh"`,工具面 = 只读(`read_file` / `search_text` / `list_files`)+ 仅限 `eval_candidates//` 子树的写入。不给 shell,不给 `memory_propose`——蒸馏不是挖掘,它不写知识,只写 candidate 文件。 --- @@ -168,13 +170,13 @@ mechanism 半的表达方式,按确定性从高到低: | 需求 | 复用现有 | 新增(扩展) | |---|---|---| -| 轨迹读取 | `build_trajectory_digest`(mining.py:161)+ `read_file`/`search_text` | —— | +| 轨迹读取 | `build_trajectory_digest`(mining.py)+ `read_file`/`search_text` | —— | | 弱点来源 | `kind="weakness"` proposals + `weakness_playbook.py` 的 `(id, description)` entry | —— | | 隔离执行 | `TaskManager.spawn` + `TaskProfile(context_mode="fresh")` | `eval-distiller` profile | | 任务格式 | `EvalTaskSpec` / `load_eval_task` / `load_eval_suite`(eval.py) | —— | | 校验执行 | `VerifierSpec` argv 执行路径、`_copy_fixture` | `--verify` 的 fail-before 检查 | | 生命周期 | 学 `harness_edits_apply.py` 的 append-only ledger + 显式状态机 | `eval_candidates` ledger | -| lineage 排除 | `holdout_gate.make_eval_suite_runner` 的 suite 装配点 | provenance 相交过滤器 | +| lineage 排除 | `holdout_gate.make_eval_suite_runner` 的 suite 装配点 | `source_sessions` 相交过滤器(读 task.json,见 §3) | | CLI | `run.py` CLI 框架 | `okc distill` 子命令 | | taxonomy | skills 注入机制 | 可选 `distill-rubric/SKILL.md`(哪些机制值得蒸、fixture 合成守则) | @@ -189,7 +191,7 @@ mechanism 半的表达方式,按确定性从高到低: `okc distill --from-session ` / `--from-playbook `:spawn distiller subagent,digest → task.json + fixture + provenance。scripted-transport 外壳测试保证管线确定性可测,真实蒸馏按需花预算。 **P2 · lineage 排除接进 holdout gate** -provenance 相交过滤器 + "排除后为空则拒绝出结论"。从此 `okc gate --validate-held-out` 的结论带 held-out 卫生保证。 +`source_sessions` 相交过滤器 + "排除后为空则拒绝出结论",装配点在 `holdout_gate.make_eval_suite_runner`。从此走 held-out 门的两条路——`okc propose --llm --validate-held-out` 与 `okc edits --revalidate --holdout-provider`——的结论都带 held-out 卫生保证。 **P3 · 成功轨迹与 metrics 半** 成功轨迹 cluster → capability smoke 任务;`EvalMetrics` 差分(model_calls 回归)进 gate 的对比维度。