+ var restarted atomic.Bool
+
+ server.reply = func(w http.ResponseWriter, call ModelFakeCall) {
+ switch {
+ case subagentTestCall(call) && !restarted.Load():
+ arrived <- struct{}{}
+
+ <-release
+ case subagentTestCall(call):
+ modelWriteEvents(w, modelCompletedEvent([]any{modelMessageItem("Built.")}, 100, 0, 5))
+ default:
+ modelWriteEvents(w, modelCompletedEvent([]any{modelMessageItem("Noted.")}, 100, 0, 5))
+ }
+ }
+
+ agent, err := openAgent(t.TempDir())
+ require.NoError(t, err)
+
+ first := &TurnEventRecorder{}
+ loop, _, stop := subagentTestStart(t, agent, server, first, discardLog())
+ _, err = loop.runs.Spawn(t.Context(), []string{"Build the project."}, nil)
+ require.NoError(t, err)
+
+ <-arrived
+
+ name := first.Last("subagent")
+
+ stop()
+ require.Zero(t, first.Count("work"))
+
+ data, err := os.ReadFile(filepath.Join(agent.dir, subagentWorkFileName))
+ require.NoError(t, err)
+ require.JSONEq(t, `{"running": ["`+name+`"]}`, string(data))
+
+ restarted.Store(true)
+
+ second := &TurnEventRecorder{}
+ loop, memory, stop := subagentTestStart(t, agent, server, second, discardLog())
+ defer stop()
+
+ second.WaitFor(t, "idle", 1)
+
+ note := "The daemon restarted, cutting " + name + "; nothing was lost: go on."
+ log := subagentTestChat(t, memory)
+ require.Equal(t, []string{
+ "note: " + note,
+ "work: " + subagentReport(name, []string{"Built."}),
+ "reply: Noted.",
+ }, log[len(log)-3:])
+
+ subagent, err := loop.runs.subagents.Get(t.Context(), name)
+ require.NoError(t, err)
+
+ text, err := subagent.Show()
+ require.NoError(t, err)
+ require.Equal(t, "0|note: subagent\n\n1|user: Build the project.\n\n2|user: "+note+"\n\n3|reply: Built.", text)
+
+ data, err = os.ReadFile(filepath.Join(agent.dir, subagentWorkFileName))
+ require.NoError(t, err)
+ require.JSONEq(t, `{"running": []}`, string(data))
+}
+
+func TestRestartReportsASubagentThatCannotGoOn(t *testing.T) {
+ server := newModelFake(t)
+ agent, err := openAgent(t.TempDir())
+ require.NoError(t, err)
+ require.NoError(t, os.WriteFile(filepath.Join(agent.dir, subagentWorkFileName), []byte(`{"running": ["BlueFox"]}`), 0o600))
+
+ events := &TurnEventRecorder{}
+ logs := &SyncBuffer{}
+ _, memory, stop := subagentTestStart(t, agent, server, events, daemonTestLogger(logs))
+ defer stop()
+
+ events.WaitFor(t, "idle", 1)
+ require.Equal(t, []string{
+ "note: The daemon restarted, cutting BlueFox; nothing was lost: go on.",
+ "work: " + subagentReport("BlueFox", []string{"failed: no agent BlueFox"}),
+ "reply: a line",
+ }, subagentTestChat(t, memory))
+
+ require.Equal(t, subagentFailed, events.LastEvent("work").Status)
+ require.Equal(t, "<3>subagent lost at restart name=BlueFox: no agent BlueFox\n", logs.String())
+
+ data, err := os.ReadFile(filepath.Join(agent.dir, subagentWorkFileName))
+ require.NoError(t, err)
+ require.JSONEq(t, `{"running": []}`, string(data))