综合:让它跑一整夜,早上验收
把六天的模块合成一个能交差的运行时,真跑一次长时程,然后交出一份人能在三分钟内看懂的夜跑报告:做成了什么、卡在哪、为什么停、下一步该人做什么。
今日目标
- 能把六个模块合成一个运行时并逐个确认它们仍在起作用,而不是只看最终报告是绿的
- 能设计一份夜跑报告,让人在三分钟内说出做成了什么、卡在哪、为什么停
- 能说出把独立模块合并进一个系统时最容易出现的静默失效,并给出一个发现它的方法
六天的模块已经齐了。今天做两件事:真跑一整夜,然后给这六层做一次体检。读完回到页面顶部把三条目标勾掉。
小白版讲解
早上第一件事:不是看它说什么,是看它留下了什么
你八点到工位,昨晚那个 Agent 跑了十个小时。第一件事看什么?
新手看它最后那句话:「已完成全部任务」。老手看三样东西:代码变成什么样了、清单上有几条翻成了通过、提交历史里有多少个可回退的点。
这个区别贯穿了整门课。D5 讲过一遍——模型说完成了不能作为翻状态的依据;今天是同一句话的最后一次应用,只是这次的说话人换成了 harness 自己:报告说完成了四十条,也不能作为你相信的依据。 你要能当场复核它。
所以今天的报告有一条硬规矩:报告里每个数字都必须能在权威状态或清单里找到出处。 报告不是第三份记录,它只是那两份的一个视图。
报告写给谁看:与 D2 的最后一组对照
D2 写过一段摘要,D7 写一页报告。它们看起来都是「把状态变成文字」,但读者不同,于是几乎每一条写法都相反。
| D2 的重建摘要 | D7 的夜跑报告 | |
|---|---|---|
| 读者 | 下一个窗口里的模型 | 早上来验收的人 |
| 目的 | 让它做出正确的下一步 | 让人在三分钟内决定要不要介入 |
| 写法 | 结论前置、一行一件事、用编号 | 先给结论,再给证据,坏消息放前面 |
| 长度 | 越短越好(每个窗口都要付一次钱) | 够用就行(只读一次) |
但两者数字同源——都来自同一份权威状态与同一份清单,所以它们不可能互相矛盾。这是 D2 到 D6 一直守着的那条纪律最后一次兑现。
报告的四条写作纪律
一、坏消息放前面。 人读报告是为了决定要不要介入,不是为了欣赏进度。所以「卡在哪里」必须排在「做完了什么」前面。
按时间顺序写流水账是最常见的错误。「第 1 步做了 F01,第 2 步做了 F02……」——这些字对「要不要介入」这个决定毫无帮助,而它们会把真正重要的三行淹掉。
二、每条坏消息都要带得起下一步。 「F07 失败」没用。「F07 试了 2 次,已跳过」才有用——前者只告诉你有问题,后者告诉你 harness 已经做了什么、还剩什么要你做。
三、给可执行的复现方式。 报告最后一定要有「怎么接着跑」和「怎么看现场」两条命令,否则人读完还得自己去翻目录找路径。
四、不许出现报告独有的数字。 这一条最容易被违反,因为它反直觉:报告里写一个「平均每步耗时」看起来很专业,但只要它不能在状态里找到出处,它就是第三份会分叉的记录。D4 那条「代码与清单进同一个 commit」和 D6 那条「账本与工作区必须同一时刻」防的是同一件事,今天是第三次。
静默失效:六层堆起来之后最危险的事
现在讲今天真正的重点。
把六个模块合并进一个系统,最危险的不是崩——崩了你会立刻知道。最危险的是静默失效:某一层其实已经不起作用了,而整体照样跑、报告照样出、一个错都不报。
这不是假想的风险。本仓库做另一门课时真的中过:新加的一个钩子让之前的基准集通过率从五分之五掉到五分之二,而报告照出,一个错都不报——因为那份报告只统计「跑完了多少」,不统计「本来该过的还过不过」。
发现它的办法只有一个,而且很朴素:
逐个模块开关一遍,看差别回不回来。
这就是今天 lab 里那张体检表。实测输出:
(全开,基准) 完成 16 条
D3 初始化阶段 探测 4 次(基准 1 次) 还在起作用
D4 一条一提交 未提交工作峰值 4 条(基准 0 条) 还在起作用
D5 端到端闸门 谎报 7 条(闸门开着时 0 条) 还在起作用
D6 约束复述 1/4 个窗口保住规矩(基准 4/4) 还在起作用
D6 预算熔断 结局 budget-exhausted,5 步(基准 16 步) 还在起作用
D2 状态层 完成 16 条(基准 16 条) 关掉没差别一句话带走:每加一层,就要有一个关掉它的开关
这是这门课七天下来最可迁移的一条:
每加一层,就要有一个关掉它的开关。 没有开关的层,你永远不知道它是不是早就不干活了。
这也是为什么这门课每天都做变异检验。今天只是把七天的变异检验汇总成了一张表——而那张表本身,就是你以后面对任何分层系统时该建的东西。
七天的一条线索
回头看,这七天其实只讲了一件事的七个面。
| 天 | 搬出窗口的是什么 | 它的载体 |
|---|---|---|
| D1 | (先证明问题存在) | —— |
| D2 | 进度 | 磁盘上的权威账本 |
| D3 | 环境知识 | init.sh、进度笔记、第一个 commit |
| D4 | 判断依据(挑哪条来做) | 清单文件与绿点 |
| D5 | 完成的判据 | 端到端验收用例 |
| D6 | 规矩 | 每个窗口复述的约束 |
| D7 | 结论 | 一页给人看的报告 |
主线一句话从第一天起没变过:上下文是易失的,状态才是权威的。 七天做的全部工作,是把一样又一样东西从那个易失的地方搬出来,各自给它一个能被别人打开的载体。
还剩什么本课没碰
最后交代边界,这既是诚实,也是给你下一步的指路。
| 话题 | 归哪门课 |
|---|---|
| 沙箱、容器隔离、出口白名单、权限 | 安全那门课 |
| 评估方法:多次试的通过率、模型裁判、遥测 | 评估那门课 |
| 上下文压缩技术本身(怎么压、留什么) | 上下文工程那门课;本课只讲压缩的一个后果 |
| 工具循环、会话恢复、todo 渲染 | 手搓 Coding Agent 那门课 |
本课始终只回答一个问题:人不在场时,怎么让它跑一整夜。 别的问题都有更合适的地方。
源码导读
今天新增一个模块,两个位置值得读。
第一个位置:第一行。 它是很多人唯一会读的一行,所以它必须同时回答三件事。
// 跑了多久、做成了多少、为什么停——三件事缺一不可。
// 只写「完成了」等于什么都没说。
function headline(input) {
const done = input.state.done.length
const total = input.features.length
const dur = minutes(input.finishedAt - input.startedAt)
const why =
input.outcome.kind === 'completed'
? '清单已全部完成'
: input.outcome.kind === 'stalled'
? `停机:被换掉的条数到顶(${input.skipped.join(' ')})`
: input.outcome.kind === 'budget-exhausted'
? `停机:${describeBreach(input.breach)}`
: `崩了:${input.outcome.error}`
return `跑了 ${dur},完成 ${done}/${total} 条,${why}。`
}# 跑了多久、做成了多少、为什么停——三件事缺一不可。
# 只写「完成了」等于什么都没说。
def headline(input):
done = len(input.state.done)
total = len(input.features)
dur = minutes(input.finished_at - input.started_at)
if input.outcome.kind == "completed":
why = "清单已全部完成"
elif input.outcome.kind == "stalled":
why = f"停机:被换掉的条数到顶({' '.join(input.skipped)})"
elif input.outcome.kind == "budget-exhausted":
why = f"停机:{describe_breach(input.breach)}"
else:
why = f"崩了:{input.outcome.error}"
return f"跑了 {dur},完成 {done}/{total} 条,{why}。"注意四种结局各有各的说法,没有合并成一句笼统的「未完成」。早上你需要知道的是「时间烧光了」还是「一条都没做成」,这两件事该做的处理完全不同。
第二个位置:体检表怎么生成。 它的写法本身就是那条习惯的具体化。
// 基准跑一次,然后每次只关掉一层,看那一层的度量有没有变差。
// 关键在于每层各有自己的度量,而不是都看「完成多少条」——
// 有些层根本不影响完成数,它们影响的是出事时的损失。
const base = await once(root, NIGHT)
const noInit = await once(root, { ...NIGHT, initMode: 'inline' })
const noCommit = await once(root, { ...NIGHT, commitMode: 'per-window' })
const noPin = await once(root, { ...NIGHT, pinConstraints: false })
report('D3 初始化阶段', noInit.probeCount > base.probeCount)
report('D4 一条一提交', noCommit.maxUnsaved > base.maxUnsaved)
report('D6 约束复述', keptWindows(noPin) < keptWindows(base))# 基准跑一次,然后每次只关掉一层,看那一层的度量有没有变差。
# 关键在于每层各有自己的度量,而不是都看「完成多少条」——
# 有些层根本不影响完成数,它们影响的是出事时的损失。
base = await once(root, NIGHT)
no_init = await once(root, replace(NIGHT, init_mode="inline"))
no_commit = await once(root, replace(NIGHT, commit_mode="per-window"))
no_pin = await once(root, replace(NIGHT, pin_constraints=False))
report("D3 初始化阶段", no_init.probe_count > base.probe_count)
report("D4 一条一提交", no_commit.max_unsaved > base.max_unsaved)
report("D6 约束复述", kept_windows(no_pin) < kept_windows(base))每层各有自己的度量,这一点很关键。D4 的一条一提交完全不影响完成条数(D4 那天实测过:九条对九条),它影响的是出事时会丢多少。如果体检表只看完成数,D4 那一层会被判成「没用」,然后在某个凌晨被人删掉。
动手实验
练习两处,都在 src/report/overnight.ts:第一行结论与整页报告。前六天的模块原样带过来。
- 先读 src/report/overnight.ts 顶部那段,把报告与 D2 那段摘要的四项差别对上号。
- 补上 headline,三件事缺一不可,四种结局各有各的说法。
- 补上 renderReport,坏消息在前,每个数字都要能在状态里找到出处。
- 跑 MOCK=1 pnpm selftest 到一百项全绿。
- 跑 MOCK=1 pnpm start:先看夜跑报告,再看那张体检表。
跑完之后做 README 里那条手动验收:只读报告第一行,然后问自己「我需要介入吗」。如果读完第一行还答不上来,那一行就写坏了——这是三分钟标准最简版的自测。
面试题
今天四道题是全课的收口:模块合并的静默失效、报告的取舍、怎么判断一个夜跑结果的好坏,以及如果只能留一个模块你留哪个。
第三道值得特别练。「跑了一夜完成了三十条里的十八条,算好还是不好」——正解是先问三个问题再下结论,而不是给一个答案。这正是这门课从 D1 到 D7 一直在反对的那件事:更好看的数字往往对应更差的现实。
检查清单与明日预告
- 能把六个模块合成一个运行时并逐个确认它们仍在起作用,而不是只看最终报告是绿的
- 能设计一份夜跑报告,让人在三分钟内说出做成了什么、卡在哪、为什么停
- 能说出把独立模块合并进一个系统时最容易出现的静默失效,并给出一个发现它的方法
- 能说清报告的四条写作纪律,特别是「不许出现报告独有的数字」为什么重要
- 能说出七天里每一天搬出窗口的是什么、载体是什么
- 让 MOCK=1 pnpm selftest 一百项全绿,并亲眼读过那份夜跑报告与体检表
- 能说出本课明确不碰的四个话题各归哪门课
- 四道面试题不看要点也能答出至少三道
七天到这里结束了。你手上现在有一个能跑一整夜的运行时:进度活在磁盘上、环境知识活在文件里、判断依据活在清单里、完成的判据活在验收用例里、规矩活在每个窗口的开场里,最后交出一页人能在三分钟内读完的报告。
接下来往哪走,取决于你的下一个瓶颈在哪。如果它开始接触外部系统与不可信输入,去看安全那门课;如果你需要回答「这个 Agent 到底好不好」,去看评估那门课;如果上下文本身成了瓶颈,去看上下文工程那门课。而如果你想把这套东西真的用在自己的项目上,现在就可以动手——把靶子换成你自己的仓库,四十条清单换成你自己的需求,其余七天的结构一行都不用改。
面试题库
六个独立开发的模块合并进一个系统,你最担心出现什么问题?怎么发现它?Six modules developed independently get merged into one system - what worries you most, and how would you find it?
国内高频海外高频深入#silent-failure#module-merge#switch-experiment分析过程 · 先想清楚再作答
- 这题第一步是把担心的对象说对:**最危险的不是崩。** 崩了有报错、有栈、有时间点,是最便宜的一类失败,你一定会知道。真正贵的是**静默失效**——某一层其实已经不起作用了,而整体照样跑、报告照样出、一个错都不报。答「我会写集成测试」不算错但不够:合并之后出问题的恰恰是每个模块单独测都绿、而互相影响的那条路径谁也没覆盖到。
- 为什么合并特别容易出这个,值得单独说一句:各模块单独开发时,它们的测试都建立在自己那一天的前提上。合并之后**新加的闸门可能让旧流程过不去,而旧流程的报告仍然是绿的**——闸门拦下来的东西不会变成错误,只会变成一个更小的数字,而没有人知道那个数字本来该是多少。这类问题在合并那一刻才第一次存在,所以单独测多少遍都测不出来。
- 发现方法只有一条真正管用:**逐个模块开关一遍,看差别回不回来。** 只看总分没用——总分是六层共同作用的结果,任何一层失效都可能被别的层掩盖,而且掩盖之后总分往往更好看。开关实验把「这一层有没有在起作用」变成一个可观测的差值,而不是一句「应该在吧」。
- 本课 D7 的体检表就是这么做出来的,五行实测可以直接背:关掉 D3 的初始化阶段,环境探测从 1 次涨到 4 次;关掉 D4 的一条一提交,未提交工作峰值从 0 条涨到 4 条;关掉 D5 的端到端闸门,谎报从 0 条涨到 7 条;关掉 D6 的约束复述,保住规矩的窗口从 4/4 掉到 1/4;把预算收紧,结局变成熔断、5 步就停(基准 16 步)。每一行都是一个能回来的差值。
- **一个关掉之后没差别的层,要当成发现而不是当成噪声。** 本课体检里 D2 的状态层就是这种情况:关掉它完成条数仍然是 16 条,与基准一模一样。查下去发现它不是坏了,是**被 D4 取代了**——任务选取上收到 harness 之后(读磁盘清单挑下一条),「上下文里没有进度证据就重做」这件事从「不再发生」变成了「不可能发生」。这条已经写成一条**正向断言**进了自检,防止将来有人把它「修好」而不自知。
- 所以带走的习惯是一句话:**每加一层,就要有一个关掉它的开关。没有开关的层,你永远不知道它是不是早就不干活了。** 这也是这门课每天都做变异检验的原因——关掉当天新增的那层,确认现象重现;D7 只是把七天的变异检验汇总成同一张表,让每一层的价值都变成一个可以当场复现的差值。
- 可预期的追问是「那不是每次都要跑七遍吗」。是的,但一次体检的成本远低于一夜白跑的成本,而且它天然可以自动化。另外开关必须是**真开关**(配置项,而不是临时注释掉几行代码)——靠注释做的体检本身就是一件要靠人记住的事,而这门课从头到尾都在反对靠人记住。
How to reason about it · think before answering
- Start by naming the right worry: a crash is not the dangerous case. A crash gives you an error, a stack and a timestamp - it is the cheapest kind of failure because you cannot miss it. The expensive kind is silent failure: one layer has stopped doing anything, while the whole thing still runs, the report still comes out, and nothing reports an error. 'I would write integration tests' is not wrong but not enough - what breaks on a merge is precisely the path where every module passes its own tests and nobody covers their interaction.
- Why merges are especially prone to this deserves its own sentence: while developed separately, each module's tests rest on the assumptions of its own day. After the merge, a newly added gate can block an older flow while that older flow's report stays green - what a gate blocks does not become an error, it becomes a smaller number, and nobody knows what that number should have been. This class of problem first exists at the moment of the merge, so no amount of separate testing finds it.
- Only one discovery method really works: switch each module off one at a time and see whether the difference comes back. Looking at the total score is useless - the total is the combined effect of six layers, any one of which can fail while another masks it, and the masked result often looks better. A switch experiment turns 'is this layer doing anything' into an observable delta instead of an assumption.
- The checkup table in this course's D7 was built exactly that way, and five measured rows are worth memorizing: switch off D3's initialization stage and environment probing rises from 1 to 4 times; switch off D4's commit-per-feature and peak uncommitted work rises from 0 to 4 items; switch off D5's end-to-end gate and false completions rise from 0 to 7; switch off D6's constraint restatement and the windows that keep the rules drop from 4/4 to 1/4; tighten the budget and the outcome becomes a breaker trip after 5 steps against a baseline of 16. Every row is a delta that comes back.
- A layer that makes no difference when switched off is a finding, not noise. In this checkup, D2's state layer is exactly that case: switch it off and the completed count is still 16, identical to the baseline. Digging in shows it is not broken but superseded by D4 - once task selection moved into the harness (pick the next item by reading the checklist off disk), 'redo the work because the context holds no evidence of progress' went from not happening to being impossible. That has been written into the self-test as a positive assertion, so nobody later 'fixes' it without realizing what they are undoing.
- So the habit to take away is one sentence: every layer you add needs a switch that turns it off. A layer without a switch leaves you permanently unable to tell whether it stopped working long ago. That is also why this course runs a mutation check every single day - switch off the layer that day introduced and confirm the symptom returns. D7 merely collects seven days of mutation checks into one table, so every layer is worth a delta you can reproduce on the spot.
- Expected follow-up: does that not mean running everything seven times? Yes, and one checkup costs far less than one wasted night, and it automates naturally. Also the switch must be a real switch - a configuration flag, not a few lines commented out by hand. A checkup that depends on commented-out code is itself a thing somebody has to remember, and remembering is what this whole course argues against.
答题要点
- 最担心的不是崩,是静默失效:某一层不起作用了,而整体照样跑、报告照样出、一个错都不报。
- 合并特别容易出这个:新加的闸门让旧流程过不去,而旧流程的报告仍然是绿的。
- 发现方法是逐个模块开关一遍看差别回不回来,比只看总分有用得多。
- 实测体检表:初始化 1→4 次探测、一条一提交 0→4 条未提交峰值、闸门 0→7 条谎报、约束复述 4/4→1/4、预算收紧则熔断。
- 关掉之后没差别的层要当成发现:D2 状态层被 D4 取代了,退化从不再发生变成不可能发生。
- 那条已写成正向断言进自检,防止将来有人把它「修好」而不自知。
- 习惯:每加一层就要有一个关掉它的开关,而且必须是配置项不是注释掉几行。
Key points
- The worry is not a crash but silent failure: a layer stops working while everything runs, reports and raises nothing.
- Merges invite it: a new gate blocks an older flow while that flow's report stays green.
- Find it by switching each module off and checking whether the difference returns - far better than reading the total.
- Measured checkup: probing 1 to 4, uncommitted peak 0 to 4, false completions 0 to 7, constraints 4/4 to 1/4, tightened budget trips the breaker.
- A layer with no difference is a finding: D2's state layer was superseded by D4 - degradation went from not happening to impossible.
- That was written into the self-test as a positive assertion so nobody silently 'fixes' it later.
- Habit: every layer needs an off switch, and it must be a config flag rather than commented-out lines.
设计一份无人值守运行的早间报告,你会放哪些内容、砍掉哪些内容?Design the morning report for an unattended run - what goes in, and what gets cut?
国内高频海外高频进阶#report-design#human-readable#single-source分析过程 · 先想清楚再作答
- 先把判据说出来,再谈内容:**一眼能看出干了什么、卡在哪里。** 判据定了,内容自己就排出来了。答「把日志格式化一下输出」是跑偏的——日志的读者是正在排查问题的人,报告的读者是**一个刚睡醒、还没进入状态、只想知道要不要介入的人**。同一份材料写给不同的人,结构完全不一样。
- 本课把它与窗口重建摘要摆在一起做对照,四项全都不同:读者(下一个窗口里的**模型** 对比 早上来验收的**人**)、目的(让它做对下一步 对比 让人在三十秒内决定要不要介入)、写法(结论前置、一行一件事 对比 先结论再证据、坏消息放前面)、长度(越短越好,每个窗口都要付一次钱 对比 够用就行,只读一次)。但两者**数字同源**——都来自同一份权威状态与同一份清单,所以它们不可能互相矛盾。
- 第一条纪律:**坏消息放前面。** 按时间顺序写流水账是最常见的错误,也是最容易犯的,因为日志天然就是那个顺序。「第 1 步做了 F01」对「我要不要介入」这个决定毫无帮助。把「卡在哪里」整节排在「做完了什么」前面,是这份报告唯一真正的结构决定。
- 第二条:**每条坏消息都要带得起下一步。**「F07 失败」没用;「F07 试了 2 次、已回退到上一个绿点、已跳过」才有用。判据很好用:读完这一条,人知不知道下一步该做什么。不知道,这条就还没写完——它只是把一个疑问从机器转移给了人。
- 第三条:**给可执行的复现方式。** 最后一节必须回答「怎么接着跑」和「怎么看现场」,否则人读完报告还得自己去翻目录找状态文件和仓库路径。这一条便宜到几乎不用想,但漏掉它会让前面写得再好的报告都多花五分钟。
- 第四条也是最容易被忽略的:**不许出现报告独有的数字。** 报告里每个数字都要能在状态或清单里找到出处,否则它就是**第三份会分叉的记录**。本课那份报告最后一行是一句复核:清单声称 40 条,逐条重验之后跑不通的有 0 条——报告不是新记录,它只是权威状态与清单的一个视图,所以它不可能和它们打架。
- 砍掉什么同样要说清:逐步流水账、模型说过的话、中间推理,全砍。可预期的追问是「那出了问题怎么排查」——排查看日志和现场,报告只负责把人**导到**现场,这正是第三条纪律的用处。把排查材料塞进报告,等于让那个刚睡醒的人替机器读日志,三分钟标准立刻作废。
How to reason about it · think before answering
- State the criterion before the contents: one glance should show what got done and where it is stuck. Once the criterion is fixed, the contents follow. 'Format the log nicely' misses - a log's reader is someone already debugging, while this report's reader is a person who just woke up, is not yet in context, and only wants to know whether to step in. The same material written for different readers has a completely different structure.
- This course puts it side by side with the window-rebuild summary, and all four properties differ: reader (the model in the next window versus the person doing the morning check), purpose (make the right next move versus decide in thirty seconds whether to intervene), style (conclusion first, one thing per line versus conclusion then evidence, bad news first), length (as short as possible, since every window pays for it, versus long enough, since it is read once). Yet both draw their numbers from the same source - the same authoritative state and the same checklist - so they cannot contradict each other.
- Discipline one: bad news first. Writing a chronological play-by-play is the most common error, and the easiest to fall into because a log is already in that order. 'Step 1 did F01' contributes nothing to the decision of whether to intervene. Putting the whole 'where it is stuck' section ahead of 'what got done' is the only real structural decision in this report.
- Discipline two: every piece of bad news must carry the next step. 'F07 failed' is useless; 'F07 was attempted twice, rolled back to the last green point, and skipped' is useful. The test is handy: after reading this line, does the person know what to do next? If not, the line is unfinished - it has merely moved a question from the machine to the human.
- Discipline three: give an executable way to reproduce. The final section must answer how to resume the run and how to inspect the scene, otherwise the reader has to go hunting for the state files and the repository path. This one is almost free to add, and leaving it out costs five minutes no matter how good the rest of the report is.
- Discipline four is the one most often missed: no number may exist only in the report. Every figure must be traceable to the state or the checklist, or it becomes a third record that will eventually diverge. The last line of this course's report is a recheck: the checklist claims 40 items, and re-verifying each one finds 0 that fail. The report is not a new record, only a view over the authoritative state and the checklist, so it cannot fight with them.
- Say what gets cut too: the step-by-step play-by-play, everything the model said, and the intermediate reasoning - all of it. Expected follow-up: then how do you debug? Debugging happens in the logs and at the scene, and the report's job is only to lead the person there, which is exactly what discipline three buys. Stuffing debugging material into the report makes the just-woken reader read logs on the machine's behalf, and the three-minute standard dies on the spot.
答题要点
- 判据一句话:一眼能看出干了什么、卡在哪里;读者是一个刚睡醒、还没进入状态的人。
- 与窗口重建摘要四项全不同(读者/目的/写法/长度),但数字同源,所以不可能互相矛盾。
- 坏消息放前面:按时间顺序写流水账是最常见的错误。
- 每条坏消息要带得起下一步:「F07 失败」没用,「F07 试了 2 次、已跳过」才有用。
- 给可执行的复现方式:怎么接着跑、怎么看现场。
- 不许出现报告独有的数字,否则它就是第三份会分叉的记录;实测报告最后一行是逐条复核。
- 砍掉逐步流水账、模型说过的话、中间推理;排查看日志,报告只负责把人导到现场。
Key points
- One criterion: a glance shows what got done and where it is stuck; the reader just woke up and is not in context.
- It differs from the rebuild summary on reader, purpose, style and length, yet shares its numbers, so the two cannot contradict.
- Bad news first: a chronological play-by-play is the most common mistake.
- Each piece of bad news must carry a next step: 'F07 failed' is useless, 'F07 tried twice and skipped' is useful.
- Give an executable way to resume the run and inspect the scene.
- No number may exist only in the report, or it becomes a third diverging record; the real report ends with an item-by-item recheck.
- Cut the play-by-play, the model's utterances and the intermediate reasoning; debugging lives in the logs, the report only points there.
Agent 跑了一夜完成了三十条里的十八条。这个结果算好还是不好?An agent ran overnight and finished 18 of 30 items - is that a good result or a bad one?
国内高频海外高频深入#acceptance-criteria#false-progress#stop-reason分析过程 · 先想清楚再作答
- 这题的正解是**先问三个问题再下结论**,不是直接给一个答案。任何张口就说「不错」或「太差」的回答都已经错了,因为 18/30 这个比值本身不携带任何可用于决策的信息。只看完成数,正是这门课从 D1 到 D7 一直在反对的事——**更好看的数字往往对应更差的现实。**
- 问题一:**剩下那十二条是没轮到,还是试过没成?** 这两种在报表上长得完全一样(都是「未完成」),但含义天差地别。没轮到只是预算不够,加一夜或加预算就能继续;试过没成说明有东西卡住了,再给多少预算都会烧在同一个地方。能区分它们的是尝试次数与被换掉的集合,不是完成数。
- 问题二:**那十八条是真的能用,还是清单上写着完成?** 本课 D5 有一组实测正好回答这个:同一份代码、同一个模型、同一份剧本,唯一的差是拿什么当验证——浅检查那趟清单声称 33 条、逐条重验只有 24 条真的能用、谎报 9 条;端到端闸门那趟声称 20 条、能用 20 条、谎报 0 条。**声称得多的那趟,真实产出反而少。**
- 这组数字还有一层值得说:那 9 条谎报里只有 2 条是真正的坏补丁,另外 7 条本来都是做对的,是被前面一条连累的。所以谎报不是孤立事件——**一条没真验的 feature 会污染它后面的一串**,这意味着「18 条里有几条是假的」这个问题不能靠抽查一两条回答。
- 问题三:**它为什么停下来?** 四种结局的处理完全不同:跑完了(清单全部完成,直接验收)、预算熔断(到线就停,下一步是加预算或砍范围)、停机(被换掉的条目太多,harness 在说前提出了问题,继续跑只是烧钱)、崩了(先看崩在哪,再决定要不要续跑)。只有跑完与熔断适合无脑续跑,另外两种都要人先看一眼。所以报告的第一行必须回答「为什么停」。
- 三个问题问完,结论才有意义,而且会落到两端之一:如果十二条是没轮到、十八条逐条重验都能用、停因为预算到线——那是一个**很好的结果**,下一步只是加预算;如果十二条是试过没成、十八条里有若干没真验、停机是因为换掉太多——那是**前提出了问题**,加预算只会烧更多的钱。同一个 18/30,两种完全相反的下一步。
- 可预期的追问是「那到底该看哪几个数」。三个:**逐条复核之后仍然能用的条数**(唯一可信的进度)、**被换掉的集合**(卡在哪类问题上)、**停机原因**(决定下一步是人做还是机器做)。这三个数都在一份合格的夜跑报告里,而且都能在权威状态与清单里找到出处。
How to reason about it · think before answering
- The right answer is to ask three questions before concluding, not to hand over a verdict. Any reply that opens with 'not bad' or 'pretty poor' is already wrong, because the ratio 18 of 30 carries no information you can act on. Judging by completion count alone is exactly what this course argues against from D1 through D7 - a better-looking number often corresponds to a worse reality.
- Question one: are the remaining twelve items untouched, or attempted and failed? On a dashboard the two look identical, both simply incomplete, but they mean opposite things. Untouched means the budget ran out, and another night or a bigger budget continues the work. Attempted and failed means something is stuck, and any additional budget burns in the same place. What separates them is the attempt counts and the skipped set, not the completion count.
- Question two: are those eighteen genuinely usable, or merely marked done on the checklist? D5 of this course answers that with a measurement: same code, same model, same script, with the only difference being what counts as verification. The shallow-check run claimed 33 items, re-verification found only 24 actually working, and 9 were false. The end-to-end gate run claimed 20, had 20 working, and 0 false. The run that claimed more produced less.
- Those numbers carry a further lesson: of the 9 false completions, only 2 came from genuinely bad patches - the other 7 were correct work dragged down by an earlier item. False completions are therefore not isolated events; one unverified feature contaminates a stretch of the items after it, which means 'how many of the eighteen are fake' cannot be answered by spot-checking one or two.
- Question three: why did it stop? The four outcomes call for completely different handling. Finished (the checklist is complete - go and accept the work), budget exhausted (it stopped at the line, so the next step is more budget or less scope), halted (too many items were skipped, so the harness is saying a premise is wrong and continuing only burns money), and crashed (look at where it crashed before deciding to resume). Only the first two are safe to resume blindly; the other two need a human look first. That is why the first line of the report must answer why it stopped.
- Only after all three questions does a conclusion mean anything, and it lands at one of two extremes. If the twelve were untouched, the eighteen all survive re-verification, and it stopped at the budget line, this is a good result and the next step is simply more budget. If the twelve were attempted and failed, several of the eighteen were never really verified, and it halted on too many skips, then a premise is broken and more budget only burns more money. One 18 of 30, two opposite next steps.
- Expected follow-up: which numbers should you actually look at? Three. The count that still works after item-by-item re-verification, which is the only trustworthy progress figure; the skipped set, which shows what class of problem it is stuck on; and the stop reason, which decides whether the next step belongs to a person or a machine. All three belong in a decent overnight report, and all three trace back to the authoritative state and the checklist.
答题要点
- 正解是先问三个问题再下结论,18/30 这个比值本身不携带可用于决策的信息。
- 问题一:剩下十二条是没轮到还是试过没成——前者只是预算不够,后者是有东西卡住了。
- 问题二:十八条是真的能用还是清单上写着完成——D5 实测浅检查声称 33 条、实际只有 24 条能用、谎报 9 条。
- 谎报不是孤立的:那 9 条里只有 2 条是坏补丁,另外 7 条是被前面一条连累的,所以抽查一两条回答不了。
- 问题三:为什么停——跑完 / 熔断 / 停机 / 崩了,四种处理完全不同,只有前两种适合无脑续跑。
- 问完才有结论:都能用且停在预算线上就是好结果;有卡点又有谎报还因换掉太多而停机,就是前提出了问题。
- 该看的三个数:逐条复核后仍能用的条数、被换掉的集合、停机原因。
Key points
- The right answer is three questions before a verdict; the ratio itself carries nothing you can act on.
- One: are the remaining twelve untouched or attempted and failed - budget shortfall versus something stuck.
- Two: are the eighteen usable or merely marked done - D5 measured 33 claimed, 24 usable, 9 false.
- False completions cluster: only 2 of the 9 were bad patches, 7 were dragged down by an earlier item, so spot checks cannot answer it.
- Three: why it stopped - finished, budget, halt or crash; only the first two are safe to resume blindly.
- Then conclude: usable items plus a budget stop is a good night; stuck items plus false completions plus a halt means a broken premise.
- The three numbers to read: items surviving re-verification, the skipped set, and the stop reason.
回顾整套 harness,如果只能保留一个模块,你留哪个?为什么?Looking back at the whole harness, if you could keep only one module, which one and why?
国内高频海外高频深入#tradeoff-reasoning#trust-vs-throughput#course-recap分析过程 · 先想清楚再作答
- 这题没有标准答案,但**推理方式有好坏**,而且面试官要的就是推理方式。上来就报一个模块名、理由是「它最重要」,无论选哪个都拿不到分——因为那句话对任何一个模块都成立。这题真正在问的是:你凭什么给这六层排序。
- 先给判据,再给答案,顺序不能反。判据是一句话:**哪一个模块缺席时,其余模块的产出会变成不可信,而不是变少?** 变少还能靠加预算补——多跑一夜、多给几步,数字会涨回来;**不可信没法补**,而且比没有数字更糟,因为一个看起来合理的假进度会让人停止怀疑,直到很久以后才发现整条线都要重来。
- 按这个判据,第一个答案是**留端到端闸门**:没有它,别的模块产出的都是不可信的进度。状态层会忠实地记下一批假的完成,清单上的绿点是假的绿点,报告会基于这些数据算出一个更好看的数字——D5 那组实测正是这个形状(声称 33 条、实际能用 24 条、谎报 9 条,而且谎报会连累后面本来做对的条目)。闸门是那唯一一个决定「数字是不是真的」的模块。
- 第二个答案是**留状态层**,同样说得通:没有它连一夜都跑不下来。实测对照是完成条数 3 条对 9 条、白干步数 6 步对 0 步——窗口一换就从头乱猜,跑得再久也只是在原地打转。可信但跑不完,与跑得完但不可信,哪个更糟取决于场景,这正是这题可以两边答的原因。
- 所以正确的做法是**给出场景条件而不是骑墙**:如果这一夜的产出会被人直接拿去用,选闸门(错误的产出比没有产出贵得多);如果这是一个探索性的长跑、产出无论如何还会被人逐条过一遍,选状态层(先让它能跑完,正确性由后面的人兜底)。**说清楚在什么条件下换答案,比答案本身更能说明你想清楚了。**
- 回答里值得顺带引一条七天的线索,它能说明这六个模块为什么不是可互相替代的:搬出窗口的分别是**进度**(D2)、**环境知识**(D3)、**判断依据**(D4)、**完成的判据**(D5)、**规矩**(D6)、**结论**(D7)——六样不同的东西,各自有一个能被别人打开的载体。主线一句话:**上下文是易失的,状态才是权威的。**
- 可预期的追问是「那这套东西还缺什么」。要能主动说清边界:沙箱与权限归安全那门课,评估指标归评估那门课,上下文压缩技术本身归上下文工程那门课——**只说归属,不展开**。能说出自己这套东西的边界在哪,比多背一个模块名有说服力得多。
How to reason about it · think before answering
- There is no standard answer here, but there are better and worse ways to reason, and the reasoning is what the interviewer wants. Naming a module and justifying it with 'it matters most' scores nothing whichever one you pick, because that sentence is true of all six. What the question really asks is: on what basis do you rank these layers?
- Give the criterion before the answer, never the other way round. The criterion is one sentence: which module, when absent, makes the other modules' output untrustworthy rather than merely smaller? Smaller can be fixed with budget - run another night, allow more steps, and the number climbs back. Untrustworthy cannot be fixed, and it is worse than having no number at all, because plausible fake progress stops people from doubting until much later, when the whole line has to be redone.
- By that criterion, the first answer is to keep the end-to-end gate: without it, everything the other modules produce is untrustworthy progress. The state layer faithfully records a batch of fake completions, the green points on the checklist are fake green points, and the report computes a better-looking number from that data - which is exactly the shape of the D5 measurement (33 claimed, 24 usable, 9 false, with false completions dragging down items that were originally correct). The gate is the one module that decides whether the numbers are real.
- The second answer, to keep the state layer, works just as well: without it the run does not survive a single night. The measured contrast is 3 items against 9, and 6 wasted steps against 0 - swap the window and it guesses from scratch, so running longer only spins in place. Trustworthy but unfinished versus finished but untrustworthy: which is worse depends on the setting, which is precisely why this question can be answered either way.
- So the right move is to state the conditions rather than hedge. If the night's output goes straight into use, keep the gate, because wrong output costs far more than no output. If this is an exploratory long run whose output a person will review item by item anyway, keep the state layer, because getting it to finish comes first and correctness is backstopped downstream. Saying under which condition you would switch answers shows more thinking than the answer itself.
- It is worth citing the seven-day thread, which explains why these six modules are not interchangeable: what gets moved out of the window is progress (D2), environment knowledge (D3), the basis for choosing (D4), the criterion for done (D5), the rules (D6) and the conclusion (D7) - six different things, each given a carrier somebody else can open. The through line stays the same: context is volatile, state is authoritative.
- Expected follow-up: what is still missing from this stack? Volunteer the boundaries: sandboxing and permissions belong to the security course, evaluation metrics to the evaluation course, and context compaction techniques themselves to the context engineering course - name the owner, do not expand. Being able to state where your own stack ends is far more convincing than reciting one more module name.
答题要点
- 这题没有标准答案,但推理方式有好坏:先给判据再给答案,顺序不能反。
- 判据:哪个模块缺席时其余模块的产出会变成不可信,而不是变少——变少能靠加预算补,不可信没法补。
- 答案 A 留端到端闸门:没有它,状态层记的是假完成、清单是假绿点、报告算出更好看的假数字。
- 答案 B 留状态层:没有它连一夜都跑不下来,实测完成 3 条对 9 条、白干 6 步对 0 步。
- 给场景条件而不是骑墙:产出直接拿去用就选闸门,探索性长跑且后面有人逐条过就选状态层。
- 七天线索:搬出窗口的是进度、环境知识、判断依据、完成的判据、规矩、结论;主线是上下文易失、状态权威。
- 主动说边界:沙箱与权限归安全那门课、评估指标归评估那门课、压缩技术本身归上下文工程那门课,只说归属不展开。
Key points
- No standard answer, but the reasoning is judged: give the criterion first, then the pick.
- Criterion: which module's absence makes the rest untrustworthy rather than smaller - smaller is fixable with budget, untrustworthy is not.
- Answer A, keep the end-to-end gate: without it the state records fake completions, the checklist holds fake green points, and the report computes a prettier lie.
- Answer B, keep the state layer: without it the night does not survive at all - 3 items against 9, 6 wasted steps against 0.
- State the condition instead of hedging: output used directly favors the gate, an exploratory run reviewed afterwards favors the state layer.
- The seven-day thread: progress, environment knowledge, the basis for choosing, the criterion for done, the rules, the conclusion - context is volatile, state is authoritative.
- Volunteer the boundaries: sandboxing to the security course, evaluation metrics to the evaluation course, compaction itself to the context engineering course - owner only, no expansion.