workflow_manage_unexpected
道-方法 · 道层 skill 全文
本页是 <code>rules/skills/drafts/workflow_manage_unexpected.md</code> 的逐字投影(仅隐私清洗,零改写)。
时点提示:本页是仓内文件 rules/skills/drafts/workflow_manage_unexpected.md 的逐字投影(仅做隐私清洗:仓库根绝对路径→相对路径、家目录→~/;除此零改写)。若源文件后续有修订,以仓内真源为准。
遇阻处理与防过早终止判断(道 skill,draft)
元数据
- 类型:Draft Workflow(道层,给 judgment,不调度执行)
- 适用场景:任务执行中撞到障碍(外部约束、权限、缺数据、工具失败、难以线性解决的问题),要决定是继续推进还是声明
blocked/await_user;或要判一个已下的blocked是真到墙了还是过早放弃。 - 证据:bounded。判断纪律抽自
workflow_controller_loop已在真实 Loop 用过的 await_user/block 段,并由本轮 guardian 18 轮零推进的一手案例校准(既有真 block 也有过早 block 的对照)。配套检测器在 ≥1 真实 positive + ≥1 硬 negative 上做过确定性判别。未在 live agent loop 内在线拦截验证,停在 artifact 级离线判定。 - 参考实例:
adhoc_jobs/complexity_defense_method_20260602/detectors/premature_block/(block receipt → 确定性结构判别 + regulator 判 tried-action 真伪)。 - 日期:2026-06-04。
目标(一句话)
遇阻时 agent 有两个相反的失败方向:一边是把外部约束当终止条件、过早写 blocked 当合规汇报(该继续没继续),另一边是无意义硬撞同一堵墙、循环烧 context(该停没停)。这个 skill 给的判断是:遇阻后按动作阶梯逐级试,只有阶梯走到底、每级都留下试过的证据,才允许精确 block;以及怎么用一个确定性检测器 + 第二 agent 判一个 block 是合法到墙还是过早放弃。
它是 workflow_controller_loop 里「诚实汇报不是停止策略」那一段的独立可路由形态。判断逻辑的真源放在这里,controller loop 指过来,不在两处各写一份。
边界(不做什么)
- 不做运行时的 Phase 动态重排(遇阻后在系统运行中改 phase 顺序的实现)。那是 Phase 5 的运行时本体(接 N3 / T752),本 skill 只给「该不该转、转之前先试什么」的判断。(2026-06-06 更新:Phase 5 slice 2 Candidate A
tools/phase_runtime/strategy_ladder.py已把本 skill 的动作阶梯实现为运行时决策策略LadderStrategy,其 block receipt 复用本 skill 的premature_block检测器离线核 C1-C4;本 skill 仍是判断真源,runtime 是其消费方。Candidate Btools/phase_runtime/strategy_gate_stall.py(GateStallStrategy)是同一接口上的对比候选,用显式 stall 检测[issue_count 不降]实现本 skill T3 死循环守卫的另一种运行时形态,block receipt 同样过premature_block检测器;Candidate Ctools/phase_runtime/strategy_dag.py(DagStrategy)是同一接口上的第三个对比候选,用 DAG 依赖图重排实现「转之前先在别处推进」:phase 阻塞时先跑一个独立的 READY 兄弟节点(动态调整顺序),穷尽后沿依赖边branch_backhand-off 重做上游,block receipt 同样过premature_block检测器。A 靠同墙无增量、B 靠 stall 计数、C 靠结构无环 + 让位上限,三者哪个更优由 T797 对比测试定。T797 裁定 A 默认 backbone + C 服务依赖结构 plan;T798 把 B 的 abort 门(不安全约束 credential/permission/destructive_risk/user_stop 立即停、不白跑阶梯)嫁接进默认 A,使默认策略对不安全约束也 abort-fast,A 的 abort block receipt 仍过premature_block,与 B/C 对齐。) - 不替代落地判定(
workflow_landing_to_production)或漂移检测门部署(workflow_complexity_drift_detection)。本 skill 配套的检测器遵循后者的 V1–V6 有效性标准,是它的一个失败模式实例(行为轴),不是另起一套。 - 不是 live-loop 在线拦截系统。检测器停在 artifact 级离线判定:喂一份 block receipt + source bundle,离线判这次 block 合不合法,不在 token 流里实时阻断。
- 不放宽 git / 权限 / 破坏性操作的硬安全边界。「先试再 block」指在安全边界内穷尽可走的动作,不指绕过
rules/git_safety.md或自我提权。
遇阻时的动作阶梯(核心判断,逐级试)
撞到障碍时,先把它转成「下一个可执行动作」,按下面阶梯逐级尝试,能走通就走、走不通才下探一级。每一级都要记下试了什么、结果如何。
- 换路径:同一目标有没有别的实现路径 / 工具 / 入口。原路被堵不等于目标被堵。(例:一个命令被权限挡,换只读探针先确认状态;一个 MCP 源不在本仓,换本地等价数据。)
- 移资源进可控范围:缺的东西能不能搬进手够得到的地方。缺文件就生成 / 拷贝到可写位置,缺数据就先抓取,缺依赖就装到本单元的隔离环境。
- 降级范围:完整版做不了,有没有一个更窄但真实的切片能做完并被下游消费。bounded 的真东西好过 0。(这是 PROMOTE-ONE 的同一条逻辑。)
- proposal / no-mutation:连降级版都要等外部条件,那就产出 proposal-only 或 adhoc/no-mutation 的产物(写出方案、待授权清单、可复跑脚本),把球推到「只差一次授权」的位置,而不是停在「做不了」。
- 精确 block:只有上面四级全部走不通,才进入
await_user/block,且必须举证——逐级写清试过的动作和为什么这一级也死。blocked是穷举之后的结论,不是遇阻的第一反应。
判断口诀:blocked 要可证伪。一个合法的 block 必须能回答「你换了哪些路径、搬了什么资源、降级到什么程度、为什么 proposal 也不行」;答不上来,就是过早放弃,不是到墙了。
合法 block 的验收标准(可测,附 receipt 结构)
声明 block 时落一份 block receipt,让「合不合法」可被第二方机械核对。结构:
{
"task_id": "T648",
"blocking_constraint": "一句话说清被什么挡住(权限 / 缺数据 / 外部系统 / 破坏性风险 / 用户明确停止)",
"constraint_class": "permission | missing_data | external_system | destructive_risk | credential | user_stop",
"tried_actions": [
{"ladder_step": "alt_path", "action": "试了什么", "outcome": "结果(含报错原文 / exit code)"},
{"ladder_step": "move_resource", "action": "...", "outcome": "..."},
{"ladder_step": "downgrade_scope", "action": "...", "outcome": "..."},
{"ladder_step": "proposal_only", "action": "...", "outcome": "..."}
],
"why_all_paths_dead": "为什么四级都走不通,逐级对应",
"requested_unblock": "需要谁做什么这一步才能解(具体到一条命令 / 一次授权)"
}合法 block 的判据,逐条:
- C1 阶梯覆盖:
tried_actions覆盖到障碍性质所允许的所有上层阶梯。不是机械凑满 4 条——有些约束天然只有 2-3 级可试(如硬权限墙:换路径试探针、降级、proposal,到此为止),但每一条「没试」都要在why_all_paths_dead里说明为什么这一级对这个约束不适用,不能默默跳过。 - C2 动作真实:
tried_actions里每条是真跑过的动作 + 真实结果(报错原文 / exit code / 文件状态),不是「我考虑了换路径但应该不行」这种没动手的推断。 - C3 约束到墙:
blocking_constraint落在六类硬约束(权限 / 缺数据且无法获取 / 外部系统 / 破坏性风险 / 凭据 / 用户明确停止)之一,且why_all_paths_dead经得起核:这个约束在当前权限和资源下确实没有会话内可走的下一步。 - C4 解法具体:
requested_unblock具体到一条可执行的解阻塞动作(谁、跑哪条命令 / 给哪次授权),不是「需要更多信息」这种模糊请求。
四条全过 = 合法 block,停得对。任一不过 = 过早 block,应回到阶梯继续。
共生检测器:premature_block(确定层误差信号)
光有上面的判断纪律不够——纪律是语义层,没有机械完成信号就会在注意力一变时漂回「遇阻即 blocked」。所以本 skill 同一工作单元里配一个确定性检测器,给「这次 block 合不合法」一个可操作、由第二方判定的误差信号。它遵循 workflow_complexity_drift_detection 的 V1–V6 有效性标准(行为轴的一个失败模式实例):
- V1 确定性判别:确定性外壳(无 LLM)读 block receipt,判结构层面的阶梯覆盖(C1)和字段完整。crisp 部分(receipt 有没有、ladder_step 枚举齐不齐、有没有 outcome)由壳判,可复现、exit code 反映。
- V2 硬负样本:一份 receipt 只列了 2-3 条 tried_actions(表面像「没试够」),但约束是硬权限墙、那几条恰好穷尽了可走路径——应判 PASS(合法)。证明判别靠「可走路径是否穷尽」这个机制,不是「tried_actions 少于 N 条就 flag」的橡皮图章。
- V3 可操作误差信号:对判为过早的 block,regulator 要指出具体哪一级阶梯有未试的可走动作(「constraint_class=permission,但没试只读探针确认状态」),而不是「试得不够」。给出能让 agent 直接回去做的那一条。
- V4 第二独立 agent:判 tried-action 真伪和「可走路径是否真穷尽」的 regulator 只见 block receipt + source bundle,不见下 block 那个 agent 的其余推理。自己审自己不算。
- V5 通用谓词:检测逻辑是通用 pattern(阶梯结构 + 约束类别 → 该覆盖哪些级),具体 task 的值只进 fixtures 不进谓词。
- V6 诚实边界:通过 V1–V5 只支持「这一个检测器 × 验证过的场景」的 bounded 声明。跨场景泛化、live-loop 在线拦截、跨模型稳定各自另证。
方法论建议(可按情况调整)
- 遇阻第一动作是「转成下一个可执行动作」,不是「评估能不能做」。评估容易滑向「应该不行」的纸面推断;动手试一条,结果是真信号。
- 区分两类「停」:到墙了停(阶梯走到底)和烧 context 地硬撞停。后者也是失败——同一堵墙撞第二次还没新动作,就该按阶梯第 4 级产 proposal 把球交出去,而不是再循环一轮。本轮 guardian 的死循环正是反面:18 轮重复 spawn 同一个被权限挡死的 session,每轮都「正确地」停了,但 guardian 层从没把球转成「跑一条 cp 命令解阻塞」的 proposal。
- block receipt 是给第二方看的,不是给自己开脱的。写的时候假设一个只见 receipt 的独立 agent 会逐条核 tried-action 真伪,按这个标准记录。
- 综合不投票:检测器对一个 block 合不合法的裁定要可机械核对(指向 receipt 字段 / source 行),不靠多个 agent 投票。
已知陷阱(来自真实案例)
- T1 把外部约束当终止条件:遇到权限 / 缺数据就直接
blocked,跳过「换路径 / 降级 / proposal」。诊断里的原话是「premature-block:遇阻把外部约束当终止条件、写 blocked 当合规汇报」。修法是阶梯强制——没有逐级 tried_actions 的 block receipt 不算合法 block。 - T2 把「正确地停」当成「处理好了意外」:worker 层每轮都按纪律停得很干净,但只要解阻塞的动作在 worker 控制范围外(要 guardian / 用户敲命令),干净地停 N 轮 = 零推进。「停得对」和「意外被处理」是两件事;后者要有人在能动手的那一层把 proposal 真执行掉。这正是为什么 block receipt 的
requested_unblock必须具体到一条命令——让有权限的那一层 10 秒能解。 - T3 硬撞 vs 到墙混为一谈:同一堵墙撞第二次还没有新的 tried_action,不是坚持,是循环。检测器对「连续两份 receipt 的 tried_actions 无增量」应视为已穷尽信号,转 proposal,不再重试。
- T4 receipt 造假式合规:列一串没真跑的 tried_actions 充数(「考虑了 X,应该不行」)。靠 V4 的 regulator 隔离判 tried-action 真伪挡这个,确定性壳只能数结构、数不出真伪。
- T5 不信 builder 自报:检测器实现交出去后,它报 PASS 不作数。亲自重跑 + 亲读代码,查有没有硬编码场景值、regulator 隔离成不成立(同
workflow_complexity_drift_detectionT5)。
运行事故的死法签名鉴别与恢复(Run3 实战沉淀,2026-07-03)
适用:无人值守/长运行编排中 worker、lane 或后台任务成批死亡时,先鉴别死法再选恢复路径。来源:buildout Run3 24h 内四类真实事故(编年史 adhoc_jobs/context_infra_base_tooling_buildout_20260615/Run3/logs/dispatch_log.md),每类都发生过至少一次误诊,鉴别表就是从误诊里提炼的。
先鉴别,后处置。 三次实例中两次初判错误(内存事故初判时把 harness 收割因素混入;两个脚本 bug 失败被误当配额拒绝)。误诊选错恢复路径的代价远高于花两分钟取证。取证三件:死亡时间分布、日志尾部遗言、当时资源水位。
| 死法签名 | 特征 | 恢复路径 |
|---|---|---|
| 配额耗尽 | 各 lane 在各自下一个 turn 边界逐个倒下(时间错开分钟级);日志尾有明确遗言 turn.failed+usage limit;退出码 1 | 断点等待:全部可 resume,不重跑;等窗口(滚动窗恢复是滴灌,见多 provider skill);探针确认再复活 |
| 系统资源(磁盘/内存) | ENOSPC=退出码 101 或工具自身报 no space;OOM=静默死亡无遗言、同一窗口内秒差成批;死前资源水位异常(swap 见底/df 0G) | 先释放资源再复活;磁盘"满"先查 APFS 快照扣留(见下);内存超订先降并发再补位 |
| harness 后台任务收割 | 同一秒批量 killed;日志戛然而止无任何错误事件;死时资源健康 | 与资源/配额无关,重启即可;根治=把长命进程迁出 harness 任务生命周期(非沙箱 tmux/独立进程组),巡检用 Monitor 类任务 |
| 脚本/工具自身 bug | 秒败且目标日志零新增;task output 里有 shell 报错 | 先读失败任务自己的 stderr/output 再怪环境(实例:bash 3.2 不支持 declare -A,两个域的"配额失败"实为脚本炸在第 8 行) |
配套经验:
- APFS 快照扣留陷阱:macOS 上清出的空间可能被 Time Machine 本地快照持有,表现为"删了 10GB 半小时内蒸发、卷持续回满"。诊断
tmutil listlocalsnapshots /,释放tmutil deletelocalsnapshots <日期>(实例:一次释放约 60GB)。 - 升级给用户的判据:push 通知当且仅当存在只有用户能做的决策(买配额 vs 等窗口、清哪些磁盘内容);已经自动处置或纯进度类不推,推送疲劳会稀释真告警。推送里给出选项和默认路径("默认等 X 点自动恢复,已布防"),让用户可以不回。
- 零丢失恢复原则:一切可 resume 的先 resume 不重跑;工作已在 git/rollout 里就不算丢。恢复 prompt 必含现场核对指令(git log + 状态面 + 半途产物收拾规则),让被恢复者先对账再续做,防止双重提交或漏收 worker result。
- 对被恢复者的预期管理:恢复 prompt 里写清「再遇同类故障→写 EXIT_STATE 干净退出,不空转重试」,把下一次故障的收拾成本降到常数。
输出规格
- 判断产物 = 一份 block receipt(上面的 JSON 结构),落在当前 loop / 任务的
loop_home或任务目录,不散落。 - 检测器自带目录(
detectors/premature_block/):SPEC.md(判别谓词 + regulator 接口 + verdict 语义)、fixtures/(≥1 真实 positive 过早 block + ≥1 硬 negative 合法 block + source_bundle)、run_oracle.py(断言确定性判别,regulator raw 输出落 log 供人亲判 V3)、VALIDATION.md(bounded 声明 + 亲读亲跑记录 + 诚实残差)。 - regulator 后端按名引用
cli_agent路由,路径查tools/INDEX.md。
跨域根与联系
- 缺误差信号是支点、调控者不能是被调者自己:来自开环控制(
project_open_loop_control_theory)。block 合不合法不能让下 block 的 agent 自己判。 - 可操作误差信号必须能定位(指出哪一级阶梯有未试动作,不是「试得不够」):来自可验证 checkpoint 实验(1-bit ≈ 无信号)。
- 语义层纪律必须配机械 checker 否则漂回:来自本轮诊断(确定层有完成信号、语义层没有,agent 滑向有信号的一侧)。
- 配合:判断纪律的 Loop 内母体 →
workflow_controller_loop(本 skill 是其 await_user/block 段的可路由形态);检测器有效性标准与同族实例 →workflow_complexity_drift_detection(V1–V6 + f2/f5);降级到 bounded 真切片 →workflow_landing_to_production(PROMOTE-ONE);regulator 第二 agent 注入 →workflow_unit_decomposition_and_context_injection;本 skill 判完当场怎么走阶梯之后,事后把这次遇阻记进持久台账做 category×signal_source 分类查阅复用 →workflow_error_recording(两者互补:一个管当场动作,一个管事后记录)。