# Harness 行为评估

KCode Harness 的可靠性不能只靠提示词或普通 smoke test 判断。涉及 LLM 行为的改动必须沉淀为可重复评估的场景，避免同一类问题在新会话、上下文压缩或子 agent 委派后复发。

## 评估原则

- 先把用户真实坏例子转成 eval，再修改提示词、状态机或工具。
- 优先使用确定性 grader：状态字段、prompt 区块、control frame、工具拦截原因和门禁结果。
- LLM-as-judge 只能用于开放式质量评估，不能替代 release 阻断条件。
- 每个 eval 必须说明失败风险，不能只写“应正常工作”。
- 涉及安全、生产数据、外部系统验证时，必须保留人工验收入口。

## 当前回归集

执行：

```text
npm run smoke:harness-evals
```

当前覆盖：

- `question-answer-retains-file-context`：读取文件逻辑后提问，用户回答后仍能在 prompt 中看到文件结论、来源和结构化事实。
- `open-question-dominates-latest-user-input`：open blocking question 存在时，最新“先写代码”只能被解释为回答/更正/停止，不能进入编码。
- `answered-fact-blocks-repeat-question`：同一 `factLabel` 已有 current fact 后，禁止重复询问。
- `delegation-context-includes-main-run-context`：子 agent 委派上下文必须包含主 run 的持久上下文条目。
- `tool-failure-must-not-route-to-subagent`：bash/read/grep 等基础工具失败时，禁止猜路径或把子 agent 当替代搜索工具。
- `observation-ledger-feeds-replay-context`：用户输入、文件结论、工具拦截、问题和答案必须进入事件账本，并在 prompt 中作为只读观测可见。
- `transcript-replay-preserves-prior-findings`：多轮 transcript replay 必须保留先前文件结论、工具失败原因和已确认结构化事实。
- `smoke:harness` 直接断言 Tool Gateway、Required Facts Contract 和 Context Compiler，确保扩展层变薄后核心策略仍阻断同类问题。
- `smoke:harness` 直接断言 Action Router、Tool Error Taxonomy、Tool Postcondition，确保 open question 下写代码意图被阻断、工具错误可分类、占位模板写入后置条件失败。
- transcript eval 断言可从 ledger 生成最小 replay scenario，后续坏例子可以从事件账本抽取复现轨迹。
- `smoke:kcode-command` 验证 CLI 入口基本功能（版本、自动初始化）。
- `smoke:harness` 直接断言 Context Compiler 输出上下文预算报告，确保 open question 场景使用更高恢复预算并明确截断边界。
- `smoke:harness` 和 `smoke:kcode-command` 直接断言 Harness Consistency Report，覆盖 active run 指针、RUN.json 可加载性、open question 上下文、facts 落盘和 ledger 坏行诊断。
- `successful-tool-observation-survives-question-turn`：工具成功定位文件后，后续 open question 和用户回答仍必须保留工具摘要和来源路径。
- `action-and-write-contract-survive-question-turn`：用户回答问题后，Action Commit Log、Write Transactions 和 Working Set 仍必须进入 prompt，避免回到模板化编码或重复外部路径写入。
- `smoke:harness` 直接断言 Context Pack Validation、Tool Result Contracts、Working Set、Action Commit Log 和 Write Transactions，确保新 runtime spine 不是只存在于类型定义。

## Transcript Replay

`src/harness/transcript-eval.ts` 提供确定性 transcript replay。评估脚本用结构化步骤复现多轮对话，而不是依赖真实 LLM：

```text
input       记录用户输入事件，普通输入同时写入 run.contextEntries
context     记录文件结论、约束、决策或风险
ask         登记一个 open blocking question
answer      回答指定问题，未指定 id 时回答当前唯一 open blocking question
revise      修订结构化事实
tool-block  记录工具拦截事件
prompt      生成 workflowPromptForRun 供断言
```

新增 LLM 失败案例时，优先用 transcript replay 表达完整轨迹：输入、工具结果、已读文件结论、提问、回答和期望 prompt/control frame/ledger 断言。

## 新坏例子的处理流程

1. 记录原始症状：用户输入、open question、run 状态、工具输出和错误表现。
2. 增加一个失败的 eval，优先放入 `scripts/smoke-harness-evals.ts`。
3. 修状态机、工具拦截、上下文包或提示词集中规则。
4. 运行 `npm run check`、`npm run smoke:harness`、`npm run smoke:harness-evals`。
5. 如果问题涉及项目规则生成，再运行 `npm run smoke:kcode-command`。
6. 如果问题涉及输入、工具拦截、自动问答或注意力漂移，必须增加 ledger 或 transcript replay 断言。
7. 如果问题涉及工具调用、事实缺口或 prompt 上下文选择，必须优先加到 Tool Gateway、Required Facts Contract 或 Context Compiler 的确定性断言。
8. 如果问题涉及“工具成功但任务没完成”，必须增加 Tool Postcondition 断言；如果涉及“工具失败后乱猜”，必须增加 Tool Error Taxonomy 断言。
9. 如果问题涉及新会话、子 agent 或上下文压缩后丢上下文，必须增加 Handoff Capsule 断言。
10. 如果问题涉及已回答问题未进入 facts、active run 指针错误、ledger 损坏、多个 open blocking question 或 gate 陈旧，必须增加 Consistency Report 断言。
11. 如果问题涉及工具成功读取或定位后丢失来源，必须增加 `tool.succeeded`、`run.contextEntries` 和 replay 断言。
12. 如果问题涉及工具结果被遗忘、动作焦点漂移或写入边界丢失，必须增加 Tool Result Contract、Working Set、Action Commit Log 或 Write Transaction 断言。

## 未覆盖风险

这些风险不能靠当前确定性 eval 完全证明：

- 真实 LLM 是否一定按 prompt 执行。
- 真实模型在超长上下文中的行为仍可能漂移；确定性 transcript 只能证明 Harness 给出的状态和 prompt 足够一致。
- 外部系统、BOS 注册、人工功能测试的真实结果。
- 长会话压缩后的行为稳定性。

后续应增加 transcript 级 eval：给定多轮输入、工具结果和期望 action，使用固定 runner 检查 LLM 是否先记录答案、是否复用上下文、是否禁止编码。
