mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-11 03:13:24 +00:00
* feat(collaboration): isolate delegated artifacts and child runs Isolate delegated inputs and outputs behind secure artifact exchange lifecycles. Scope Agent Link tasks by tenant and root agent, and enforce delegation spawn-tree boundaries. Add process-wide child-run admission and preserve logical media paths across native, MCP, and sandbox execution. * fix(collaboration): harden delegated task isolation Enforce tenant and root-agent task scope across migrations and stores. Add exactly-once async completion delivery, delegated sandbox boundaries, and confined artifact and media recovery across runtime surfaces. * fix(collaboration): recover interrupted async tasks * fix(collaboration): normalize persisted child-run status --------- Co-authored-by: ntduc <ntduc@cpp.ai.vn>
53 lines
1.3 KiB
Go
53 lines
1.3 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/orchestration"
|
|
"github.com/nextlevelbuilder/goclaw/internal/store"
|
|
)
|
|
|
|
func TestDrainChildRunsWithRetryReturnsTypedFailure(t *testing.T) {
|
|
admission := orchestration.NewChildRunAdmission(1, 2)
|
|
started := make(chan struct{})
|
|
release := make(chan struct{})
|
|
ticket, err := admission.Enqueue(context.Background(), orchestration.ChildRunConstraints{
|
|
TenantID: store.MasterTenantID,
|
|
TaskID: uuid.NewString(),
|
|
}, func(context.Context, *orchestration.ChildRunLease) {
|
|
close(started)
|
|
<-release
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := ticket.Activate(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
select {
|
|
case <-started:
|
|
case <-time.After(time.Second):
|
|
t.Fatal("child run did not start")
|
|
}
|
|
|
|
err = drainChildRunsWithRetry(admission, 10*time.Millisecond, 10*time.Millisecond)
|
|
if !errors.Is(err, orchestration.ErrChildRunDrainTimeout) {
|
|
t.Fatalf("drain error = %v, want typed timeout", err)
|
|
}
|
|
|
|
close(release)
|
|
select {
|
|
case <-ticket.Done():
|
|
case <-time.After(time.Second):
|
|
t.Fatal("child run did not finish after forced termination signal")
|
|
}
|
|
if err := admission.Close(context.Background()); err != nil {
|
|
t.Fatalf("final drain: %v", err)
|
|
}
|
|
}
|