返回 DeepSeek-Reasonix
summary.go
根目录 / internal / autoresearch / summary.go
1 package autoresearch
2
3 import "path/filepath"
4
5 func (s *Store) Summary(taskID string) (*Summary, error) {
6 task, err := s.LoadTask(taskID)
7 if err != nil {
8 return nil, err
9 }
10 storeRoot, taskRel, err := s.openTaskRoot(taskID)
11 if err != nil {
12 return nil, err
13 }
14 defer storeRoot.Close()
15 var progress Progress
16 if err := readJSONFile(storeRoot, filepath.Join(taskRel, "state", "progress.json"), &progress); err != nil {
17 return nil, err
18 }
19 findings, err := s.Findings(taskID, 0)
20 if err != nil {
21 return nil, err
22 }
23 lastHeartbeat, _, err := s.LastHeartbeat(taskID)
24 if err != nil {
25 return nil, err
26 }
27 accepted := acceptedFindingIDs(findings)
28 openCriteria := make([]CriterionSummary, 0)
29 for _, criterion := range task.Spec.SuccessCriteria {
30 count := countAcceptedEvidence(criterion.EvidenceIDs, accepted)
31 status := "satisfied"
32 if criterion.Required && count == 0 {
33 status = "open"
34 }
35 if status == "open" {
36 openCriteria = append(openCriteria, CriterionSummary{
37 ID: criterion.ID,
38 Description: criterion.Description,
39 Required: criterion.Required,
40 EvidenceCount: count,
41 Status: status,
42 })
43 }
44 }
45 summary := &Summary{
46 TaskID: task.ID,
47 Goal: task.Spec.Goal,
48 Status: progress.Status,
49 Iteration: progress.Iteration,
50 CurrentDirection: progress.CurrentDirection,
51 StaleCount: progress.StaleCount,
52 PivotCount: progress.PivotCount,
53 PivotRequired: progress.StaleCount >= 2,
54 LastHeartbeatAt: lastHeartbeat.CreatedAt,
55 FindingCount: len(findings),
56 OpenCriteria: openCriteria,
57 Blocker: progress.BlockedReason,
58 TaskPath: task.Root,
59 NextRequiredAction: nextRequiredAction(progress),
60 }
61 return summary, nil
62 }
63
64 func nextRequiredAction(progress Progress) string {
65 if progress.Status == StatusBlocked {
66 return "resolve blocker before continuing"
67 }
68 if progress.StaleCount >= 4 {
69 return "ask for the smallest external input needed"
70 }
71 if progress.StaleCount >= 2 {
72 return "make a structural pivot before continuing"
73 }
74 return "continue with the next evidence-producing step"
75 }
76
77 func acceptedFindingIDs(findings []Finding) map[string]bool {
78 accepted := make(map[string]bool, len(findings))
79 for _, finding := range findings {
80 if finding.Accepted {
81 accepted[finding.ID] = true
82 }
83 }
84 return accepted
85 }
86
87 func countAcceptedEvidence(ids []string, accepted map[string]bool) int {
88 count := 0
89 for _, id := range ids {
90 if accepted[id] {
91 count++
92 }
93 }
94 return count
95 }
96
96 lines GO