逐日AI
第 1 周 · D6约 4 小时

崩溃续跑、预算熔断与 governance decay

夜里会断电、会 OOM、会把钱烧光,也会悄悄忘掉你最初的规矩。今天补上三件事:中途被强杀能续上、超预算立刻停机、以及压缩之后约束还在——最后这件是一个被实测量化过的真实风险。

今日目标 0/3

登录后可以勾选并保存进度。

今日目标

  1. 能说出断点续跑与重新开始的区别,并解释检查点该记什么才能保证续跑不重复劳动
  2. 能解释预算熔断为什么必须在运行中实时判断,并说出它与事后成本度量的分工
  3. 能解释 governance decay 是什么、为什么拿早期事实当探针的验证方式发现不了它,并说出约束复述怎么补这个洞

D5 的停机是一个干净的结局:harness 自己决定停下来,还有机会收尾。今天处理三件更狼狈的事。读完回到页面顶部把三条目标勾掉。

小白版讲解

夜班会遇到的三件事:断电、超支、忘规矩

还是那条流水线。白板(D2)挂上了,交接文档(D3)写好了,验收单(D4)一项一项签,监理(D5)也到位了。现在真的让它跑一整夜,还会遇到什么?

断电。 不是「有人决定停下来」,是电闸跳了。没有交接、没有收尾、没有一句话。

超支。 机器一直在转,料一直在用,但天亮时你发现活没干多少——钱按小时烧,进度按件算,两者可以完全脱钩。

忘规矩。 交班交了六轮之后,最初那句「切割前必须戴护目镜」没人再提了。不是谁故意违反,是那句话在一次次转述里被省掉了

三件事对应今天的三个模块。第三件最隐蔽,也最值得学——它有一个名字,叫 governance decay

续跑不需要新的持久化

先说一个可能出乎意料的事实:今天几乎没有新增要落盘的东西。

账本(D2)、上手三件套(D3)、清单与绿点(D4)、被换掉的集合(D5 从尝试次数推导)——全都已经在磁盘上了。前五天每一次「从磁盘读」的坚持,都是在为今天铺路。D2 那段注释当时就写着:

只有从磁盘读,这条边界才有资格变成一次进程重启。

今天兑现它。所以今天的难点不在「记什么」,在**「怎么正确地接回来」**——而「正确」两个字里藏着三件容易做错的事。

做错后果为什么难发现
续跑时也初始化一次工作区一整夜的工作被一行删除抹掉不报错,日志上看是一次正常的运行
把悬空的「正在做」当成做完了清单开始说谎,或者那条补丁被写两遍清单看起来更好看
保留未提交的改动从一个没通过验证的状态接着做那段代码看起来和好代码一模一样

第二条值得展开。崩溃可能正好发生在「补丁写进去了、验证还没跑」那一瞬,磁盘上会留下一条「正在做 F07」——它既不在已完成里,也没有失败记录。

这不是脏数据,它是最重要的一条信息。 它告诉新进程:F07 到底成没成不知道,先确认。把它当成做完了,清单就开始说谎;把它当成没做过,那段已经写进文件的补丁会被再写一遍。

第三条是 D4 那条规矩的直接推论:通过验证才提交,所以工作区里任何未提交的东西,按定义都是没通过验证的。留着它,就是把一个未知状态当成已知状态带进下一轮。

实测:同样的预算,差的是前十五步算不算数

公平对照的关键是一夜的预算固定——崩掉的那几步是真的烧掉了,模型调用付了钱。所以两边都给二十四步,前三段各在第五步被强杀,最后一段拿剩下的九步。

TextText
每次崩溃都从头再来:最终完成  9 条
崩了就从磁盘接着做:最终完成 24 条

对照组不是笨,它只是不知道磁盘上有东西可接——每次醒来都以为自己是第一个。

预算熔断:三条线,各防一种失控

第二件事是钱。这里先把一个容易混的分工说清楚。

评估那门课讲的是事后度量:一批运行跑完之后算通过率、算 token、算缓存命中率,判断一个 Agent 好不好。那是离线的、回顾性的。

本课讲的是运行中的实时熔断:跑到第几步、烧了多少时间、绿点产出率掉到多少,到线就当场停机。它是在线的、前瞻性的,而且它的唯一目的不是评价,是止损

两者一个指标都不共享,也不该共享——事后指标算得再准,也救不回已经烧掉的一夜。

线防的是为什么别的线防不住
步数上限无限循环对「每步都很慢」无感
墙钟上限单步卡死、外部依赖变慢步数可能还早,时间已经烧光
产出率下限干得动但干不出东西步数没超、时间没超,就是一条都不通过

第三条最值得记。前两条是「跑太久」,第三条是「跑得没意义」:已经跑了 N 步,绿点却少于 M 个。这正是无人值守最隐蔽的烧钱方式——一切看起来都在动,早上打开一看,进度条没挪。

governance decay:规矩不是被违反了,是先消失了

第三件事最微妙。先说它和手搓 Coding Agent 那门课 D12 的关系,这是本课三处对照点里最需要小心的一处。

那门课讲压缩之后怎么验证「没丢东西」:拿早期提过的事实当探针,压完再问一遍,答得上来就说明压缩是安全的。那验的是事实保真

但还有一种东西也会在压缩里消失,而探针法对它是盲的约束

一个还能准确复述订单号的 Agent,完全可能已经不再遵守「未经确认不许删文件」。 记得住不等于听得进。

这就是 governance decay。而在本课的架构里,它的发生机制清清楚楚,甚至可以说是必然的

回想 D2 立的规矩——窗口边界处重建的是等效上下文,只保留「做完了什么、正在做什么、试了几次」。约束不在这三类里,所以重建天然不会带上它。它只出现在第一个窗口的开场,之后就再也没有了。

这不是一个 bug,它是「有损压缩,但对决策无损」那句话的代价:当时判断「对决策无损」时,我们只考虑了下一步做什么,没考虑下一步不许做什么

修法就是论文里的 Constraint Pinning:每个窗口开场都把约束原样复述一遍。

TextText
不复述(默认的重建行为)             3 → 0 → 0 → 0
每窗口复述一遍(Constraint Pinning)  3 → 3 → 3 → 3

复述的成本实测是 174 / 717 字符——几十个 token,换整晚的规矩不失效。

源码导读

今天新增三个模块,两个位置值得细读。

第一个位置:续跑判断必须在初始化工作区之前。

resume-order.js
// 对的顺序:先问磁盘上有没有东西可接,再决定要不要 seed
const cp = inspectCheckpoint(repoDir, stateDir)
const features = cp.resumable && cp.features !== null
  ? cp.features              // 续跑:清单从磁盘读,它和代码在同一个 commit 里
  : seedWorkspace(root).features
 
// 错的顺序:先 seed 再问。seedWorkspace 每次都先删掉 work/repo 再重建,
// 所以这一行会把一整夜的工作抹掉——而且不报错,日志上看是一次正常的运行
const seeded = seedWorkspace(root)
const cpTooLate = inspectCheckpoint(repoDir, stateDir)

这就是今天的变异检验。把顺序调过来之后,续跑组从二十四条掉到五条——比完全不会续跑的九条还差

原因很值得想清楚:账本还在(它住在靶子仓库之外,不受初始化影响),它说已经做完十五条了;而工作区被抹成了空。两者分叉了。 于是 harness 跳过那十五条去做第十六条,而代码里一行都没有。

第二个位置:熔断与热身期。

budget.js
function checkBudget(state, startedAt, greens, budget, now) {
  if (state.spent.steps >= budget.maxSteps) {
    return { kind: 'steps', spent: state.spent.steps, limit: budget.maxSteps }
  }
  if (now - startedAt >= budget.maxWallMs) {
    return { kind: 'wall', elapsedMs: now - startedAt, limitMs: budget.maxWallMs }
  }
  // 热身期内不看产出率:头几步里它天然是 0,此时熔断等于永远跑不起来
  if (state.spent.steps >= budget.graceSteps) {
    const needed = Math.floor(state.spent.steps / budget.stepsPerGreen)
    if (greens < needed) return { kind: 'yield', steps: state.spent.steps, greens, needed }
  }
  return null
}

注意三条线互不顶替:它们各自独立返回,不合并成一个综合分。合并会让报告失去信息——早上你需要知道的是「时间烧光了」还是「一条都没做成」,这两件事该做的处理完全不同。

动手实验

🧪 D6 实验:崩溃续跑、预算熔断与 governance decay

代码位置:labs/agent-harness-7days/day-06-resume-budget

练习四处:续跑判断与工作区恢复、预算三条线、约束渲染与存活率度量。前五天的模块全部原样带过来。

  1. 先读 scripts/run-child.ts,看清楚续跑判断为什么必须在 seed 之前。
  2. 补上 inspectCheckpoint,三件事一件都不能少:不重新 seed、报出悬空的那条、丢掉未提交的改动。
  3. 补上 checkBudget 的三条线,别忘了产出率那条的热身期。
  4. 补上 renderConstraints 与 countConstraints,编号标记不是装饰,度量靠它。
  5. 跑 MOCK=1 pnpm selftest 到八十八项全绿,再跑 MOCK=1 pnpm start 看三个演示。

变异检验就是上面那个顺序调换。做完记得看一眼手动验收清单里那条:跑完之后 git log 的提交历史是连续的,跨了四个进程,而早期那个绿点的哈希在三次崩溃前后一字不差——那才是「没有重新初始化」的硬证据。

面试题

今天四道题围绕续跑的正确性、实时熔断与事后度量的分工,以及一个很容易被答浅的概念:为什么验证「记不记得」的办法发现不了「还听不听」。

第三道值得特别准备。能说出 governance decay 这个词只是及格线,真正拉开差距的是能说清探针法为什么对它是盲的,以及能主动交代你的实验测到了什么、没测到什么

检查清单与明日预告

  • 能说出断点续跑与重新开始的区别,并解释检查点该记什么才能保证续跑不重复劳动
  • 能解释预算熔断为什么必须在运行中实时判断,并说出它与事后成本度量的分工
  • 能解释 governance decay 是什么、为什么拿早期事实当探针的验证方式发现不了它,并说出约束复述怎么补这个洞
  • 能说出续跑最容易做错的三件事,以及为什么它们都不报错
  • 能说清为什么比率型阈值必须有最小样本量
  • 让 MOCK=1 pnpm selftest 八十八项全绿,并看过三个演示的数字
  • 做过一次「把 seed 挪到续跑判断之前」的变异检验,能说清为什么结果比不会续跑还差
  • 四道面试题不看要点也能答出至少三道

明天是 D7《综合:让它跑一整夜,早上验收》。六天的模块到今天已经齐了,但还差最后一件事:这一切最后要给人看。 今天的熔断、停机、被换掉的条目,现在都只是内存里的一个结局,没有人被通知。明天写夜跑报告,判据只有一句话——一眼能看出干了什么、卡在哪里。然后把六个模块合起来真跑一次长时程,做一次全课复盘。

面试题库

  • 一个跑了六小时的 Agent 进程被杀了。你希望它下次启动时怎么恢复?An agent process that had been running for six hours gets killed - how should it come back on the next start?
    国内高频海外高频深入#crash-resume#checkpoint#idempotence

    分析过程 · 先想清楚再作答

    1. 这题考的是**进程边界**。答「把上下文序列化存下来、下次原样 load 回去」是跑偏的——那是**同一会话的重放恢复**(手搓 Coding Agent 那门课 D07 的地盘),它还原的是「说过什么」;这里要还原的是「做成了什么」。前五天每一次「从磁盘读」都是在为这一刻铺路:窗口边界上的东西**只要全部从磁盘读**,它就有资格升级成一次进程重启。
    2. 拆的第一步是盘点今天要新增哪些需要持久化的东西,答案是**几乎没有**。账本、上手三件套、清单与绿点、被换掉的集合(从尝试次数推导)早就都在磁盘上了。今天做的只是把它们**正确地**接回来——难的全在「正确」这两个字里,而且这三件做错了都不会报错。
    3. 第一件容易做错的:**不许重新 seed**。seed 每次都先把工作区删干净再重建,从头跑时这是对的(反复可重建是它的价值),续跑时它是灾难——一行 rmSync 抹掉一整夜的工作,而且没有任何错误输出。所以续跑的第一步是**判断该不该 seed**,不是先 seed 再说。
    4. 第二件:**悬空的 current 必须重验**。崩溃可能正好发生在「补丁写进去了、验证还没跑」那一瞬,磁盘上会留下一条 current 指向 F07,它既不在已完成集合里、也没有失败记录。**这不是脏数据,它是最重要的一条信息**:当成做完了,清单就开始说谎;当成没做过,那段已经写进文件的补丁会被再写一遍。正确的处理只有重验。
    5. 第三件:**未提交的改动必须丢掉**。规矩是通过验证才提交,所以工作区里任何未提交的东西**按定义就是没通过验证的**。把它留着等于把一个未知状态当成已知状态带进下一轮,reset 到 HEAD 是唯一正确的开场——这就是「回退的目标只能是绿点」那条规矩在进程边界上的同一句话。
    6. 实测值得背下来:一夜固定 24 步预算,前三段各在第 5 步被 SIGKILL。**每次从头重来最终完成 9 条,从磁盘接着做完成 24 条。** 顺带一个演示纪律:**用 SIGKILL 而不是 process.exit()**,后者会跑 finally 与退出钩子,那是优雅退出,演示不出崩溃——你测的会是一条根本不会发生的路径。
    7. 可预期的追问是「做一半的续跑总比没有强吧」。变异实测说不:把 seed 挪到续跑判断之前(即续跑时也重新 seed),续跑组从 24 条掉到 **5 条**,**比完全不会续跑的 9 条还差**。因为账本说做过了、工作区却是空的,两者当场分叉——harness 拿着一份声称完成了 N 条的账本去一个什么都没有的工作区上接着做。**半套续跑比没有续跑更危险。**

    How to reason about it · think before answering

    1. This question is about the process boundary. 'Serialize the context and load it back next time' misses: that is replay recovery within one session (the territory of D07 in the course where you build a coding agent by hand), and it restores what was said. Here you restore what was done. Every 'read it from disk' of the previous five days was laying track for this moment: once everything at a window boundary comes from disk, that boundary is entitled to become a process restart.
    2. Start by listing what new things need persisting today - the answer is almost nothing. The ledger, the onboarding trio, the checklist and green points, the skipped set (derived from attempt counts) are already on disk. Today's work is reconnecting them correctly, and all the difficulty lives in that word. All three ways of getting it wrong fail silently.
    3. Mistake one: never re-seed. Seeding wipes the workspace and rebuilds it, which is right on a fresh run - reproducibility is the whole point - and catastrophic on a resume: one rmSync erases a full night's work, with no error output whatsoever. So the first step of a resume is deciding whether to seed at all, not seeding and then thinking about it.
    4. Mistake two: a dangling current must be re-verified. The crash can land exactly between 'the patch was written' and 'verification ran', leaving a current pointing at F07 that is neither in the done set nor in any failure record. That is not dirty data, it is the single most important piece of information. Treat it as done and the checklist starts lying; treat it as untouched and a patch already in the files gets written twice. Re-verification is the only correct handling.
    5. Mistake three: uncommitted changes must be discarded. The rule is commit only after verification passes, so anything uncommitted in the workspace is by definition unverified. Keeping it carries an unknown state into the next round dressed as a known one. Resetting to HEAD is the only correct opening - the same rule as 'a rollback may only target a green point', restated at the process boundary.
    6. The measurement is worth memorizing: a fixed budget of 24 steps for the night, with the first three segments killed by SIGKILL at step 5. Starting over each time finishes 9 items; resuming from disk finishes 24. One demo discipline goes with it: use SIGKILL, not process.exit(), because the latter runs finally blocks and exit hooks - that is a graceful shutdown, and it demonstrates a path a real crash never takes.
    7. Expected follow-up: surely half a resume beats none? The mutation test says no. Move the seed ahead of the resume decision, so a resume re-seeds too, and the resuming run drops from 24 items to 5 - worse than the 9 of a run that cannot resume at all. The ledger says the work was done while the workspace is empty, and the two diverge on the spot: the harness carries a ledger claiming N completed items into a workspace holding nothing. Half a resume is more dangerous than none.

    答题要点

    • 要恢复的是「做成了什么」,不是「说过什么」——与同一会话的重放恢复不是一回事。
    • 窗口边界升级成进程边界:前几天已经把该落盘的都落了盘,今天几乎不新增持久化的东西。
    • 不许重新 seed:seed 会先删工作区,续跑时一行 rmSync 抹掉一整夜且不报错。
    • 悬空的 current 必须重验:它既不在已完成里也没有失败记录,是最重要的一条信息。
    • 未提交的改动必须丢掉:通过验证才提交,所以没提交的按定义就是没通过验证的。
    • 实测:24 步固定预算、三次 SIGKILL,从头重来 9 条,从磁盘接着做 24 条。
    • 变异实测:续跑时也重新 seed,24 条掉到 5 条,比不会续跑的 9 条还差——半套比没有更危险。

    Key points

    • Restore what was done, not what was said - this is not replay recovery inside one session.
    • The window boundary becomes a process boundary: everything was already on disk, so almost nothing new is persisted.
    • Never re-seed: seeding wipes the workspace, and on a resume one rmSync erases the night without an error.
    • A dangling current must be re-verified: neither in done nor in any failure record, it is the key piece of information.
    • Discard uncommitted changes: commit follows verification, so uncommitted means unverified by definition.
    • Measured: 24-step budget, three SIGKILLs - starting over finishes 9 items, resuming from disk finishes 24.
    • Mutation: re-seeding on resume drops 24 to 5, worse than the 9 of no resume at all.
  • 预算熔断和事后成本报表是两件事吗?分别解决什么问题?Are a budget circuit breaker and a post-hoc cost report two different things, and what does each solve?
    国内高频海外高频进阶#budget#circuit-breaker#real-time-control

    分析过程 · 先想清楚再作答

    1. 这题考的是**在线止损与离线评价的边界**。答「都是控成本」拿不到分。事后度量是**离线的、回顾性的**,一批运行跑完之后算通过率、算 token、算缓存命中率,用来判断一个 Agent 好不好,那是评估那门课的地盘;熔断是**在线的、前瞻性的**,唯一目的不是评价而是**止损**。两者一个指标都不共享,也不该共享。
    2. 一句话把分工钉死:**事后指标算得再准,也救不回已经烧掉的一夜。** 反过来也成立——熔断那三个数字拿去做质量评价毫无意义,它们只说明这次跑了多久、烧了多少,不说明结果好不好。一个管**停不停**,一个管**改不改**。
    3. 拆法是问「这个数字用来做什么决定、什么时候必须拿到」。熔断要的量必须**当场就能算出来**,所以它宁可粗糙;事后指标可以等整批跑完再慢慢算,所以它可以精确。把一个要跑完才有的指标塞进熔断判据,等于永远不会熔断。
    4. 熔断的三条线各防一种失控:**步数上限**防无限循环,但它对「每步都很慢」完全无感;**墙钟上限**防单步卡死与外部依赖变慢,因为步数可能还早得很、时间已经烧光;**产出率下限**防的是第三种,也是最隐蔽的一种。
    5. 第三条最值得展开:已经跑了 N 步、绿点却少于 M 个,这是「**干得动但干不出东西**」。前两条盯的是「跑太久」,第三条盯的是「跑得没意义」——一切看起来都在动,早上打开一看进度条没挪。只有它盯的是**产出**而不是消耗,这也是它不可被前两条替代的理由。
    6. 产出率那条必须带**热身期**:一次运行的头几步里产出率天然是 0(第一条还没验完),此时熔断等于永远跑不起来。这条可以直接升级成一句通用结论带走:**任何基于比率的阈值都需要一个最小样本量。** 面试里说出这一句,比把三条线背全更值钱。
    7. 可预期的追问是「阈值怎么定」。不是拍脑袋:先定这一夜愿意烧掉的钱与时间,折算成墙钟与步数上限,产出率那条按正常运行的绿点密度打个折。定不出来说明还没想清楚这一夜值多少钱。另外熔断必须**停在一个一致的点上**并写清是哪条线到线——三种原因对应的排查方向完全不同,而下一次续跑接的就是这个点。

    How to reason about it · think before answering

    1. This is about the line between stopping losses online and judging quality offline. 'Both control cost' scores zero. Post-hoc measurement is offline and retrospective: after a batch finishes you compute pass rates, tokens and cache hit rates to judge whether an agent is any good - that belongs to the evaluation course. A circuit breaker is online and forward-looking, and its purpose is not judgment but stopping the bleeding. They share no metric, and should not.
    2. One line nails the split: however precisely you compute a post-hoc metric, it cannot recover a night already burned. The reverse holds too - the breaker's three numbers say nothing about quality, only how long it ran and how much it spent. One decides whether to stop, the other whether to change anything.
    3. Break it open by asking what decision a number feeds and when it must be in hand. A breaker's inputs must be computable on the spot, so it prefers coarse; post-hoc metrics can wait for the whole batch, so they can be precise. Putting a metric that only exists after the run into a breaker's criterion means it will never fire.
    4. The three lines each guard against a different runaway. A step ceiling guards against infinite loops but is blind to every step being slow. A wall-clock ceiling guards against a stuck step or a slowing dependency, because the step count may be nowhere near its limit while the time is gone. A yield floor guards against the third and most hidden kind.
    5. That third one deserves elaboration: N steps spent with fewer than M green points means the agent can work but produces nothing. The first two watch for running too long, the third for running pointlessly - everything looks busy and in the morning the progress bar has not moved. Only this line watches output rather than consumption, which is exactly why the other two cannot replace it.
    6. The yield line needs a warm-up period: in the first few steps of a run the yield is naturally zero because nothing has finished verification yet, and tripping there means the run can never start. Promote that into a portable conclusion: any ratio-based threshold needs a minimum sample size. Saying that sentence in an interview is worth more than reciting all three lines.
    7. Expected follow-up: how do you set the thresholds? Not by guessing. Decide what a night is worth in money and hours, convert that into wall-clock and step ceilings, and derive the yield floor from the green-point density of a healthy run with a margin. If you cannot derive them, you have not decided what the night is worth. Also, the breaker must halt at a consistent point and record which line tripped - the three causes point at completely different investigations, and the next resume starts exactly there.

    答题要点

    • 一个管停不停(在线止损),一个管改不改(离线评价),一个指标都不共享。
    • 事后指标算得再准,也救不回已经烧掉的一夜。
    • 判据是这个数字用来做什么决定、什么时候必须拿到:熔断宁可粗糙也要当场能算。
    • 三条线:步数防无限循环、墙钟防单步卡死、产出率防干得动但干不出东西。
    • 产出率那条盯的是产出不是消耗,它是「一切都在动、进度条没挪」的唯一解。
    • 比率阈值必须有热身期——任何基于比率的阈值都需要一个最小样本量。
    • 阈值从「这一夜值多少钱」倒推;熔断必须停在一致点上并写清是哪条线到线。

    Key points

    • One decides whether to stop (online loss control), the other whether to change (offline judgment); no shared metrics.
    • However precise a post-hoc metric is, it cannot recover a night already burned.
    • The criterion is what decision the number feeds and when: a breaker prefers coarse but computable on the spot.
    • Three lines: steps for infinite loops, wall clock for stuck steps, yield for working without producing.
    • The yield line watches output rather than consumption - the only defense against a busy-looking night with no progress.
    • Ratio thresholds need a warm-up: any ratio-based threshold needs a minimum sample size.
    • Derive thresholds from what the night is worth; halt at a consistent point and record which line tripped.
  • 反复压缩上下文会让 Agent 逐渐不遵守最初的安全约束。你会怎么防?Repeated context compaction makes an agent drift away from its original safety constraints - how would you defend against that?
    国内高频海外高频深入#governance-decay#constraint-pinning#compaction

    分析过程 · 先想清楚再作答

    1. 这题第一步是确认你知道这是一个**已经被一手论文量化过的现象**而不是想象出来的风险,它有名字:**governance decay**。答「把约束写进系统提示词就完事了」之前要先回答一个问题——重建上下文的那一刻,那份约束到底还在不在。机制没说清,任何防法都只是一句口号。
    2. 机制在架构里是**必然的**,不是 bug。窗口边界处重建的是**等效上下文**,只保留「做完了什么、正在做什么、试了几次」三类。约束不在这三类里,所以重建天然不会带上它——它只出现在第一个窗口的开场,之后再也没有出现过。
    3. 它是「有损压缩,但对决策无损」那句话的代价:当时判断「对决策无损」时,只考虑了**下一步做什么**,没考虑**下一步不许做什么**。前者是状态,后者是策略,而一个只保留状态的压缩必然丢掉策略。把这层说出来,比背出现象名字有用得多。
    4. 防法就是论文里的 **Constraint Pinning**:**每个窗口开场都把约束原样复述一遍。** 它便宜得几乎不用算——本课实测那段只占开场 **174/717 字符**,换的是整晚的规矩不失效。注意它防的是「约束消失」,不是「模型抗拒」,这两件事下一题会分开讲。
    5. 必须**配一个度量**,不能只写一句「我们复述了」。本课的口径是数各窗口开场里还剩几条约束:不复述是 **3 → 0 → 0 → 0**,每窗口复述是 **3 → 3 → 3 → 3**。有了这个数字,「复述有没有真的接上」就变成一个能自动断言的事实,而不是一段谁也没验过的好意。
    6. 选哪几条进复述也有讲究:优先选**违反了不会立刻报错**的那种规矩。会立刻报错的规矩不靠复述也会被现实纠正(下一步就跑不通了),不报错的那些才是压缩里悄悄失效、失效之后最难查的一类——本课那三条(一次只做一条、只追加不改写已有注册代码、不手改清单)全是这一类。
    7. 能力边界必须主动说:离线的单用途模型**看不见约束也不会违规**,所以自己的 lab 能测的是「**约束还在不在**」,测不到「**模型还听不听**」。后者只引用一手证据,而且引用时必须带条件:ConstraintRot 基准 **1323 个 episode、7 个模型家族**,违规率从策略完整可见时的 **0%** 升到**压缩后**的 **30%**,某些家族达 **59%**,Constraint Pinning 压回 **0%**。脱离「压缩后」这个条件单说 30% 是错的。

    How to reason about it · think before answering

    1. First establish that you know this is a phenomenon already quantified by primary research, not an imagined risk: it has a name, governance decay. Before answering 'put the constraints in the system prompt', answer this - at the moment the context is rebuilt, is that copy of the constraints still there? Without the mechanism, any defense is a slogan.
    2. The mechanism is architecturally inevitable, not a bug. At a window boundary you rebuild an equivalent context that keeps only three categories: what is done, what is in progress, how many attempts were made. Constraints are in none of them, so the rebuild naturally leaves them out - they appear in the first window's opening and never again.
    3. This is the price of 'lossy compression that loses nothing decision-relevant': when that judgment was made, only what to do next was considered, never what must not be done next. The first is state, the second is policy, and a compaction that keeps only state necessarily drops policy. Saying that out loud is worth far more than naming the phenomenon.
    4. The defense is the paper's Constraint Pinning: restate the constraints verbatim at the opening of every window. It is almost free - measured here, that block is 174 of 717 characters in the opening - and it buys a night in which the rules stay in force. Note what it defends against: constraints disappearing, not a model resisting them. The next question separates those two.
    5. It needs a measurement, not just a claim that you restate them. The metric used here is how many constraints survive in each window's opening: without pinning it is 3, 0, 0, 0; with pinning it is 3, 3, 3, 3. With that number, 'is the restatement actually wired in' becomes an automatically assertable fact instead of an unverified good intention.
    6. Which constraints to pin also matters: prefer the rules whose violation does not fail loudly. A rule that fails immediately gets corrected by reality anyway - the next step simply will not work - while the quiet ones are exactly what compaction erases and what is hardest to diagnose afterwards. All three used here (one feature at a time, append only without rewriting existing registration code, never hand-edit the checklist) are of that kind.
    7. Close with the capability boundary, volunteered rather than extracted: a single-purpose offline model neither sees constraints nor violates them, so the lab here can measure whether the constraints are still present, not whether the model still obeys. The latter is only cited, and always with its condition: the ConstraintRot benchmark, 1323 episodes across 7 model families, violation rates rising from 0 percent with the policy fully visible to 30 percent after compaction, reaching 59 percent in some families, with Constraint Pinning pushing it back to 0 percent. Quoting 30 percent without 'after compaction' is simply wrong.

    答题要点

    • 现象有名字:governance decay,已被一手论文量化,先说机制再说防法。
    • 机制是架构必然:重建只保留做完了什么、正在做什么、试了几次,约束不在这三类里。
    • 「对决策无损」当初只考虑了下一步做什么,没考虑下一步不许做什么——丢的是策略不是状态。
    • 防法是 Constraint Pinning:每个窗口开场原样复述,实测只占开场 174/717 字符。
    • 必须配度量:不复述是 3 → 0 → 0 → 0,每窗口复述是 3 → 3 → 3 → 3。
    • 优先复述那些违反了不会立刻报错的规矩,会立刻报错的靠现实就能纠正。
    • 能力边界:自己能测「约束还在不在」,测不到「模型还听不听」;引用论文数字必须带「压缩后」这个条件。

    Key points

    • The phenomenon has a name - governance decay, quantified by primary research; explain the mechanism before the defense.
    • The mechanism is architectural: the rebuild keeps done, in progress and attempt counts; constraints are in none of them.
    • 'Nothing decision-relevant lost' only considered what to do next, never what must not be done - policy is dropped, not state.
    • The defense is Constraint Pinning: restate verbatim at each window opening, measured at 174 of 717 characters.
    • Pair it with a metric: 3, 0, 0, 0 without pinning versus 3, 3, 3, 3 with it.
    • Pin the rules that fail quietly; the ones that fail loudly get corrected by reality anyway.
    • Capability boundary: you can measure presence, not obedience; always cite the paper's numbers with the 'after compaction' condition.
  • 你已经有一套压缩后的事实校验探针了,为什么它发现不了约束被擦掉?You already have probes that check factual fidelity after compaction - why do they miss constraints being erased?
    国内高频海外高频深入#probe-blind-spot#constraint-fidelity#capability-boundary

    分析过程 · 先想清楚再作答

    1. 这题考的是**两种保真的区别**,而且它是一道专门用来筛「知道自己验了什么」的题。探针法(手搓 Coding Agent 那门课 D12 的做法)是拿早期提过的事实当探针、压完再问一遍,答得上来就说明压缩安全。它验的是**事实保真**——记不记得。约束保真是另一回事:**还听不听得进。**
    2. 一句话就能点破:**一个还能准确复述订单号的 Agent,完全可能已经不再遵守「未经确认不许删文件」。记得住不等于听得进。** 探针法的全部证据都落在前半句上,它对后半句是**结构性**的盲,不是覆盖率不够、多加几条探针就能补上的那种盲。
    3. 为什么是结构性的:探针问的是「这条信息还在不在上下文里」,而约束失效有两条路径——信息还在但权重掉了,以及像本课这样在重建时根本就没被带上。前一条探针完全抓不到(它会答得很好然后照样违规);后一条探针原则上抓得到,但没有人会想到拿一条规矩去当事实探针问。
    4. 还有一层常被忽略的:**探针是抽样的**。事实之间是同质的,抽几条有代表性的就够了;**约束不是同质的**——每一条都不可替代,抽到 C1 还在推不出 C2 还在。用一个抽样的方法去验一个不可抽样的对象,方法本身就不成立,与探针写得好不好无关。
    5. 补法很便宜,而且方向是对的:把约束当成**一等公民**直接数——按 id 逐条核对各窗口开场里还剩几条。关键在于它**不问模型**,是在上下文文本里自己数。这与自验证那天是同一条原则:**不依赖被审查方配合的检查,才是可信的检查。**
    6. 但要主动说清这个补法的**上限**:它证明的是「约束还在上下文里」,不是「模型还在遵守」。后者要用行为指标(违规率)去量,而那需要一个真会违规的模型;本课的离线模型是单用途的,看不见约束也不会违规,所以这一层只引用一手论文的数字(**压缩后** 0% 升到 30%、某些家族 59%、Constraint Pinning 压回 0%),不自己造数据。
    7. 可预期的追问是「那把约束也做成探针不就行了」。可以,但**判据必须换**:事实探针的判据是「答得上来」,约束探针的判据得是「**一字不差地复述**」外加「**在一个会诱导违规的场景里仍然拒绝**」。只问一句「你还记得有哪些规矩吗」,得到的仍然是一个记忆测试——而记忆正是那个已经被证明不够的东西。

    How to reason about it · think before answering

    1. This question is about two kinds of fidelity, and it exists to filter for people who know what their checks actually cover. The probe method (D12 of the course where you build a coding agent by hand) takes facts mentioned early, asks about them again after compaction, and treats a correct answer as proof that compaction was safe. That is factual fidelity - whether it remembers. Constraint fidelity is a different thing: whether it still complies.
    2. One line makes it plain: an agent that can still recite the order number perfectly may well have stopped obeying 'never delete a file without confirmation'. Remembering is not the same as heeding. All of the probe method's evidence lands on the first half, and it is structurally blind to the second - not blind for lack of coverage, not fixable by adding more probes.
    3. Why structurally: a probe asks whether a piece of information is still in the context, while constraints fail along two paths - the text is still there but its weight has dropped, or, as here, the rebuild never carried it at all. The first is entirely invisible to probes (the model answers beautifully and violates anyway); the second is in principle catchable, but nobody thinks to use a rule as a factual probe.
    4. There is a further layer people miss: probes sample. Facts are homogeneous, so a few representative ones suffice. Constraints are not homogeneous - each is irreplaceable, and finding C1 intact says nothing about C2. Using a sampling method on an object that cannot be sampled fails as a method, regardless of how well the individual probes are written.
    5. The fix is cheap and points the right way: treat constraints as first-class and count them directly, checking id by id how many survive in each window's opening. What matters is that it does not ask the model - it counts them in the context text itself. This is the same principle as the self-verification day: a check that does not depend on the cooperation of the party under review is the only trustworthy check.
    6. Volunteer the ceiling of that fix too: it proves the constraints are still in the context, not that the model still obeys them. Obedience needs a behavioural metric - a violation rate - and that needs a model that genuinely violates. The offline model used here is single-purpose: it neither sees constraints nor breaks them, so that layer only cites the primary numbers (0 percent rising to 30 percent after compaction, 59 percent in some families, Constraint Pinning back to 0 percent) rather than manufacturing its own.
    7. Expected follow-up: why not turn the constraints into probes as well? You can, but the criterion has to change. A factual probe passes on a correct answer; a constraint probe must require a verbatim restatement plus a refusal in a scenario engineered to invite the violation. Asking 'do you remember the rules?' still yields a memory test - and memory is precisely the thing already shown to be insufficient.

    答题要点

    • 探针法验的是事实保真(记不记得),约束保真是另一回事(还听不听得进)。
    • 一个还能准确复述订单号的 Agent,完全可能已经不再遵守「未经确认不许删文件」。
    • 盲区是结构性的:约束可以信息还在而权重掉了,也可以在重建时根本没被带上。
    • 事实可以抽样,约束不可以:每条约束不可替代,抽到 C1 还在推不出 C2 还在。
    • 补法是按 id 逐条数上下文里还剩几条约束,而且不问模型——不依赖被审查方配合的检查才可信。
    • 补法的上限:它证明约束还在,不证明模型还在遵守;后者只引用一手论文数字。
    • 把约束做成探针要换判据:一字不差复述 + 在诱导场景里仍然拒绝,而不是「你还记得吗」。

    Key points

    • Probes verify factual fidelity (does it remember); constraint fidelity is another thing (does it still comply).
    • An agent that still recites the order number perfectly may have stopped obeying 'no deletion without confirmation'.
    • The blind spot is structural: text can survive with lost weight, or never be carried by the rebuild at all.
    • Facts can be sampled, constraints cannot: each is irreplaceable, and C1 surviving says nothing about C2.
    • The fix is counting constraints by id in the context and not asking the model - checks that need no cooperation are the trustworthy ones.
    • Its ceiling: it proves presence, not obedience; obedience is only cited from primary research.
    • Constraint probes need a different criterion: verbatim restatement plus refusal under an inviting scenario, not 'do you remember'.

评论