mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 09:28:14 +00:00
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 通过
This commit is contained in:
@ -191,6 +191,10 @@ func (a *Agent) process(input string, stageCtx *sdk.StageContext) (response stri
|
||||
//
|
||||
// M3a 还没有抢占,因此 outcomeSuspended 只会由 M3b 的抢占检查产生。
|
||||
func (a *Agent) runInputTask(evt *agentIO.InputEvent, seed []agentAPI.Message) (*TaskFrame, stepOutcome) {
|
||||
// 临界区标记由调度器 goroutine 维护,任务结束(含挂起)即清。
|
||||
// interceptLoop 读它来决定“能不能取消”,因此必须是原子的。
|
||||
defer a.sched.setCritical(false)
|
||||
|
||||
f, term := a.prepareInputTask(evt)
|
||||
switch term {
|
||||
case terminalSkipped, terminalStageShortCircuit, terminalConsolidation:
|
||||
@ -234,6 +238,9 @@ func (a *Agent) prepareInputTask(evt *agentIO.InputEvent) (*TaskFrame, taskTermi
|
||||
if a.currentOutputChannel == "" {
|
||||
a.currentOutputChannel = evt.Source
|
||||
}
|
||||
// 进入本任务的临界区属性(记忆整理整任务不可抢占)。
|
||||
// 必须在 processConsolidation 之前设置——它就在下面同步执行。
|
||||
a.sched.setCritical(a.inCriticalSection())
|
||||
|
||||
if evt.OutputChannel == channelConsolidation {
|
||||
a.processConsolidation(evt, in.text)
|
||||
|
||||
Reference in New Issue
Block a user