返回 DeepSeek-Reasonix
failure_survives_folds_test.go
根目录 / internal / agent / failure_survives_folds_test.go
1 package agent
2
3 import (
4 "context"
5 "fmt"
6 "strings"
7 "testing"
8
9 "reasonix/internal/event"
10 "reasonix/internal/provider"
11 "reasonix/internal/tool"
12 )
13
14 // goTestFailure is shaped like a real failing `go test` result so the test
15 // verifies that structured failures enter the ordinary summary prefix.
16 func goTestFailure() string {
17 lines := make([]string, 0, 40)
18 for i := range 40 {
19 if i == 20 {
20 lines = append(lines, "--- FAIL: TestCanary (0.01s)")
21 continue
22 }
23 lines = append(lines, fmt.Sprintf("=== RUN TestCase%03d", i))
24 }
25 return strings.Join(lines, "\n")
26 }
27
28 // Deprecated KeepErrors must not pin the failure verbatim. The full failure is
29 // summarized while canonical storage and local execution metadata stay intact.
30 func TestRecordedFailureEntersSummaryAndCanonicalStaysIntact(t *testing.T) {
31 bulk := strings.Repeat("work output line with detail. ", 250)
32 sess := &Session{Messages: []provider.Message{
33 {Role: provider.RoleSystem, Content: "sys"},
34 {Role: provider.RoleUser, Content: "task"},
35 }}
36 a := New(&fakeProvider{reply: "digest"}, tool.NewRegistry(), sess,
37 Options{ContextWindow: 8000, CompactRatio: 0.85, RecentKeep: 2,
38 KeepPolicy: KeepErrors, ArchiveDir: t.TempDir()}, event.Discard)
39
40 exit := 1
41 sess.Add(provider.Message{Role: provider.RoleAssistant, Content: "running tests",
42 ToolCalls: []provider.ToolCall{{ID: "canary", Name: "bash", Arguments: "{}"}}})
43 sess.Add(provider.Message{Role: provider.RoleTool, ToolCallID: "canary", Name: "bash",
44 Content: goTestFailure(), ToolExecution: &provider.ToolExecution{ExitCode: &exit}})
45
46 for round := 1; round <= 1; round++ {
47 sess.Add(provider.Message{Role: provider.RoleAssistant, Content: bulk})
48 sess.Add(provider.Message{Role: provider.RoleUser, Content: fmt.Sprintf("continue %d", round)})
49 if err := a.compact(context.Background(), "manual", "", true); err != nil {
50 t.Fatalf("round %d compact: %v", round, err)
51 }
52
53 if !strings.Contains(joinContents(a.svc.prov.(*fakeProvider).got), "TestCanary") {
54 t.Fatalf("round %d: failure did not enter summary input", round)
55 }
56 for _, m := range provider.ModelMessages(visibleContext(a)) {
57 if m.ToolExecution != nil {
58 t.Fatalf("round %d: local shell metadata reached the provider request", round)
59 }
60 }
61 }
62 if !strings.Contains(joinContents(sess.Snapshot()), "TestCanary") {
63 t.Fatal("canonical transcript lost the failure")
64 }
65 }
66
66 lines GO