Close the squad P1 gaps the audit listed for this batch
Why: parallel groups dropped a hold, HITL timeouts were unused, the planner failed closed on any model error, and event sequence numbers restarted at 1. Evidence: GOWORK=off go test -count=1 -race ./squad/ ./squadintent/ ./store/ ./platform/ passed, including TestR2ExpiredDecisionUsesCancel, TestR2IntentStepSkipsRoleRegistry, TestR2PlannerFallsBackAndCapsSteps, TestR2TaskFileUsesLatestBlackboard, TestR2FanoutCancelDoesNotPanic, TestR2EventSeqContinuesAfterRestart, TestR2JournalModeWAL, and TestR2GateReloadSeesNewIntent. Impact: a failed or held parallel sibling cancels the rest; expired requests synthesize cancel or fail; the intent gate follows Registry.Reload. Refs: Q6, Q10, Q11, Q12, Q13, Q17, Q18, Q19, I9 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -58,6 +59,7 @@ func (s *FileEventSink) Emit(ev squad.Event) {
|
||||
}
|
||||
f = fp
|
||||
s.files[ev.RunID] = f
|
||||
s.seqs[ev.RunID] = lastEventSeq(filepath.Join(dir, "events.jsonl"))
|
||||
}
|
||||
s.seqs[ev.RunID]++
|
||||
line := persistedEvent{Seq: s.seqs[ev.RunID], Type: ev.Type, StepID: ev.StepID,
|
||||
@@ -72,6 +74,23 @@ func (s *FileEventSink) Emit(ev squad.Event) {
|
||||
_, _ = f.Write(append(data, '\n'))
|
||||
}
|
||||
|
||||
func lastEventSeq(path string) int64 {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
defer f.Close()
|
||||
var last int64
|
||||
sc := bufio.NewScanner(f)
|
||||
for sc.Scan() {
|
||||
var line persistedEvent
|
||||
if err := json.Unmarshal(sc.Bytes(), &line); err == nil && line.Seq > last {
|
||||
last = line.Seq
|
||||
}
|
||||
}
|
||||
return last
|
||||
}
|
||||
|
||||
// Close 关闭全部文件句柄。
|
||||
func (s *FileEventSink) Close() {
|
||||
s.mu.Lock()
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"agent-squad/squad"
|
||||
)
|
||||
|
||||
func TestR2EventSeqContinuesAfterRestart(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
run := "run_1"
|
||||
path := filepath.Join(dir, "runs", run)
|
||||
if err := os.MkdirAll(path, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(path, "events.jsonl"), []byte("{\"seq\":7,\"type\":\"phase\"}\n"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sink := NewFileEventSink(dir, nil)
|
||||
sink.Emit(squad.Event{Type: "phase", RunID: run, Text: "next"})
|
||||
sink.Close()
|
||||
if got := lastEventSeq(filepath.Join(path, "events.jsonl")); got != 8 {
|
||||
t.Fatalf("seq %d", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user