From f41c8bfd97d0b9276aade0589369663321ebe74c Mon Sep 17 00:00:00 2001 From: santoshkumarradha Date: Fri, 6 Nov 2026 10:15:23 -0500 Subject: [PATCH] test: settle setup before measuring idle release The vague fixture opener can finish its intent naming after the turn ends. Its final title and intent_name records then publish another head inside the idle counting window, before the expected release row. Name the fixture before sending, join its completed capture, and wait for that exact head on the peer before opening the window. Keep the exact change-count and lease assertions unchanged. Co-Authored-By: Claude Opus 5.5 --- cmd/codeaf/app_idle_release_test.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/cmd/codeaf/app_idle_release_test.go b/cmd/codeaf/app_idle_release_test.go index 90664185ea..37911be137 100644 --- a/cmd/codeaf/app_idle_release_test.go +++ b/cmd/codeaf/app_idle_release_test.go @@ -12,7 +12,9 @@ import ( "time" "github.com/Agent-Field/codeaf/internal/appwire" + "github.com/Agent-Field/codeaf/internal/cell" "github.com/Agent-Field/codeaf/internal/cell/celltest" + "github.com/Agent-Field/codeaf/internal/cellstore" "github.com/Agent-Field/codeaf/internal/config" "github.com/Agent-Field/codeaf/internal/home" "github.com/Agent-Field/codeaf/internal/session" @@ -177,19 +179,38 @@ func appIdleReleaseI1I2(t *testing.T, viewed bool, stopped ...bool) { if err != nil { t.Fatal(err) } + // Naming a vague opener may finish after its turn and publish another head. + // Give this idle-release fixture its name before the turn starts. + if _, err := a.Rename(agent.ID, "Idle release fixture"); err != nil { + t.Fatal(err) + } turn, err := a.Send(agent.ID, "! echo before-idle", "") if err != nil { t.Fatal(err) } appTurnDoneFor(t, rec, turn) own := appSyncOwn(t) - row := idleReleaseRow(t, wire, agent.ID, func(r appwire.ChatRow) bool { return r.Seen.Head != "" }) appSyncWait(t, "I1 idle turn settled", func() bool { var idle bool a.locked(func() { idle = a.agents[agent.ID].live != nil && !a.agents[agent.ID].live.running }) return idle }) var transcript string + a.locked(func() { transcript = a.agents[agent.ID].transcript }) + chat, err := cell.OpenAt(session.DirOf(transcript), agent.ID) + if err != nil { + t.Fatal(err) + } + // A completed turn can still be saving. Baseline the peer only after that + // capture is finished and its exact head has reached the directory. + if err := cellstore.WaitCapture(t.Context(), chat); err != nil { + t.Fatal(err) + } + head, err := cellstore.Head(chat) + if err != nil || head == nil { + t.Fatalf("idle setup head = %v, %v", head, err) + } + row := idleReleaseRow(t, wire, agent.ID, func(r appwire.ChatRow) bool { return r.Seen.Head == head.Turn.ID }) if leftover { // Model the old engine's mismatch after its final checkpoint: the // stopped job is in tasks.json, but its process file still says running.