返回 DeepSeek-Reasonix
child.go
根目录 / internal / evidence / child.go
1 package evidence
2
3 import "sort"
4
5 // ChildEvidenceSummary is the ordered, host-observable evidence a sub-agent
6 // produced. Parents merge these receipts so delegated writes, reads, commands,
7 // verifications, and structured reviews count toward delivery gates without
8 // treating the meta tool call itself as a mutation.
9 type ChildEvidenceSummary struct {
10 Receipts []Receipt
11 }
12
13 // HasMutation reports whether any successful receipt is a real state change.
14 func (s ChildEvidenceSummary) HasMutation() bool {
15 for _, r := range s.Receipts {
16 if r.Success && r.Mutation {
17 return true
18 }
19 }
20 return false
21 }
22
23 // MutationPaths returns distinct production paths written by the child.
24 func (s ChildEvidenceSummary) MutationPaths() []string {
25 seen := map[string]bool{}
26 var out []string
27 for _, r := range s.Receipts {
28 if !r.Success || !r.Mutation {
29 continue
30 }
31 for _, p := range r.Paths {
32 if p == "" || seen[p] {
33 continue
34 }
35 seen[p] = true
36 out = append(out, p)
37 }
38 }
39 sort.Strings(out)
40 return out
41 }
42
43 // Summary returns a snapshot of every receipt recorded this turn in order.
44 func (l *Ledger) Summary() ChildEvidenceSummary {
45 if l == nil {
46 return ChildEvidenceSummary{}
47 }
48 l.mu.Lock()
49 defer l.mu.Unlock()
50 out := make([]Receipt, len(l.receipts))
51 copy(out, l.receipts)
52 return ChildEvidenceSummary{Receipts: out}
53 }
54
55 // MergeChild appends successful child receipts into the parent ledger. Failed
56 // child receipts are retained for auditability with Success=false so they never
57 // satisfy host matchers.
58 func (l *Ledger) MergeChild(summary ChildEvidenceSummary) {
59 if l == nil || len(summary.Receipts) == 0 {
60 return
61 }
62 for _, r := range summary.Receipts {
63 // Drop nested bookkeeping that the parent already owns.
64 switch r.ToolName {
65 case "todo_write", "complete_step", "ask":
66 continue
67 }
68 l.Record(r)
69 }
70 }
71
72 // MergeChildren merges multiple child summaries in the given order.
73 func (l *Ledger) MergeChildren(summaries ...ChildEvidenceSummary) {
74 for _, s := range summaries {
75 l.MergeChild(s)
76 }
77 }
78
78 lines GO