|
|
98d67559d1
|
fix(scheduler): 补齐 M3 与设计稿的两处语义偏离(发现即修)
两处都不是风格差异,而是真的偏离设计语义(其一为回归),
已按“先写判据确认失败、再修”的方式处理,判据保留为回归测试。
1. 空闲时到达的中断永远不会被处理(设计 §5.1 ③ 未落地)
调度器空闲时只阻塞在 select{InputChan, selfInputCh, ctx.Done},
而 pendingInterrupts 不是 channel——interceptLoop 把中断入队后
没有任何东西唤醒调度器,中断要等“下一条输入”才被看到。
修复:调度器加 wake channel,enqueueInterrupt 非阻塞 signalWake,
空闲分支增加 wake 分支。
2. 临界区内只“不让位”却仍被“取消”(设计 §4.3/§5.2)
requestPreempt 不判临界区,interceptLoop 照常 cancelLLM,
于是正在流式的记忆整理被中断,stepLLM 以 error 提前结束——
整理任务被砍掉一半,而设计要求的是“请求排队等它结束”。
修复:scheduler 增加原子 critical 标志(帧仍只由调度器读写),
runInputTask 在 prepare 后设置、结束(含挂起)时清除;
requestPreempt 在临界区内不 arm、不取消,中断只入队。
- 新增 scheduler_regression_test.go 2 项(先失败后通过)
- 验收:agent 全量 + -race;全仓 vet 通过
|
2026-09-13 06:10:44 +08:00 |
|
|
|
4e4e0ad656
|
feat(scheduler): M6 任务级回执 + 断链点统一为终态事件
设计依据 docs/zh/input-scheduler-design.md §7(I5)、§11.3(X1/X2/X4)。
- 新增 emitSkippedReply:跳过路径(去重命中、空输入)给同步调用方一个
skipped 终态,但**不发 agent_output 事件**(避免 WebUI 聊天记录凭空多出
空消息)。修复前 cli/clawhubadapter 这类无超时的同步注入在去重命中时永久挂起
- 回执按任务归属:中断任务的回执只写自己的 ResponseCh,绝不误投给被挂起的等待者;
被挂起任务恢复并结束后才拿到自己的回执
- 新增 task_terminal_test.go 3 项:X1 回执不误投、X2 空输入有 skipped 终态、
X4 无超时同步调用方 1s 内拿到终态(回归判据)
- 更新 M3a 去重用例:由「不得回执」改为「必须有 skipped 终态」
- 验收:agent 全量 + -race;全仓 build/vet 通过
|
2026-09-13 00:39:56 +08:00 |
|
|
|
a971fc8877
|
feat(scheduler): M5 饥饿防护(抢占计数提升有效级 + 抢占冷却)
设计依据 docs/zh/input-scheduler-design.md §9、§11.5(G1/G2)。
- Task 增加 PreemptCount / LastPreemptAt;effectiveLevel(t) =
min(L4, Level + min(PreemptCount, 2)):被抢占越多越“值钱”,
逐步追上抢占它的流,但封顶 L4 因而抢不过真正的紧急输入
- 选择函数 taskBefore 改用有效级;requestPreempt 与 preemptGrantedFor
同样以有效级比较
- 抢占冷却 preemptCooldown=2s:刚被抢占的任务期内不再被抢占,
避免同一任务被反复打断到永不完结
- 新增 scheduler_starvation_test.go 4 项:提升与封顶、冷却期内不得再抢占、
提升后同级不得抢占而更高可、选择函数确实用有效级
- 验收:agent 全量 + -race;全仓 build/vet 通过
|
2026-09-13 00:38:30 +08:00 |
|
|
|
7565248f61
|
feat(scheduler): M4 临界区显式化 + 清掉被 pendingInterrupts 取代的 interceptCh
设计依据 docs/zh/input-scheduler-design.md §4.3、§11.1(P5/P6)。
- 临界区语义显式化:让位检查**只在 step 之间**做,执行中的 step
(工具 RPC / ONNX / CAS 落盘)天然不可抢占;_consolidation_ 整任务
经 inCriticalSection() 判为不可抢占(它直接改图库)
- 删除 interceptCh 与 drainInterrupts:M3b 起中断一律走 pendingInterrupts,
旧的「同行注入 + 三处 drain + 批次放弃」已无写入者,属死代码
- 新增 scheduler_critical_test.go 3 项:
P5/P6 工具执行中 arm 了让位信号也不得挂起、必须等工具返回后的安全点;
_consolidation_ 判为临界区;无抢占时同批工具必须全部执行(新语义回归)
- 验收:agent 全量 + -race;全仓 build/vet 通过
|
2026-09-13 00:34:39 +08:00 |
|
|
|
c69a1f11af
|
feat(scheduler): M3a+M3b 任务生命周期重构 + 四级优先级抢占
设计依据 docs/zh/input-scheduler-design.md §3–§8、§14。
M3a(行为等价的所有权重构):
- processInput 拆为 prepareInputTask / runTaskSteps / finishInputTask,
帧覆盖 prepare→step…→finish;提交与回执只在 finish 段发生一次,
为安全点挂起做准备(挂起不重复提交)
- process() 不再持 a.mu(挂起不能持锁),a.mu 字段随之移除
- TaskFrame 增加任务层现场(Evt/CleanInput/IsInterrupt/StartedAt/Terminal/
Level/SeedMsgs)与 taskTerminal / outcomeSuspended
- 新增 task_lifecycle_test.go 5 项:正常恰好一次终态、去重 skipped、
on_input 短路、错误终态、consolidation 路由
M3b(优先级与抢占):
- interceptLoop 重写:只做「收中断 → 定级 → requestPreempt → 必要时取消
LLM」,绝不触碰帧(不变量 I2);三条降级路径与 interceptCh 兜底退场,
改为统一的 pendingInterrupts
- scheduler:pendingInterrupts / suspendPool / 让位信号,nextRef 在三集合上
按统一排序键取值;深度上限 4(canSuspend 在安全点拦下)
- 抢占判据 incoming.level > running.level;相等与更低只入队
- 安全点只在 step 之间;执行中的 step(工具 RPC/ONNX/CAS)天然不可抢占;
_consolidation_ 整任务视为临界区
- 恢复走 resumeTask:从 frame.Step 继续,不重跑 prepare
- D1=A:suspend 把被打断任务的只读前缀交给抢占比它的中断任务(SeedMsgs)
- 新增 scheduler_preempt_test.go 5 项:抢占-挂起-恢复(含 R1/R5)、同级更低
不抢占、深度上限、空闲中断不丢、seed 路径不污染标志位
验收:agent 全量 + -race 通过;全仓 build/vet 通过
|
2026-09-13 00:25:52 +08:00 |
|
|
|
9a588780b9
|
refactor(scheduler): M1 把 process() 拆成 step 状态机 + TaskFrame(行为等价)
设计依据 docs/zh/input-scheduler-design.md §14 M1。
- 新增 task.go:Step 游标、TaskFrame,以及 stepPrepare/stepLLM/
stepToolBegin/stepToolExec/stepToolAfter/stepTurnEnd 六个 step;
原函数内嵌的 provider 回退/重试抽为 resolveProviders + callLLMWithFallback
- process() 改为驱动状态机的薄壳:签名不变,调用方(processInput/
processConsolidation/测试)零改动
- StepToolExec 显式标注为临界区:工具副作用不可回滚,执行中不是安全点
- 步数上限护栏:转移缺失时以错误退出而非死循环
- 新增 task_test.go:R3(工具往返结果与配对正确)、X3(多轮必然终止)、
批中途中断必须放弃剩余工具、未知 step 必须失败退出
- 验收:既有 agent 全量测试通过;-race 通过(TMPDIR 指向真实磁盘,
/tmp tmpfs 已 98% 满会导致链接失败,与代码无关)
|
2026-09-12 23:47:12 +08:00 |
|