返回 DeepSeek-Reasonix
recovery_preference.go
根目录 / internal / agent / recovery_preference.go
1 package agent
2
3 import (
4 "fmt"
5 "sort"
6 )
7
8 // SetRecoveryPreferred records exactly one explicit preferred lineage member.
9 // Clearing old choices first can only fall back to an unresolved group; an
10 // interrupted update can never leave two canonical choices.
11 func SetRecoveryPreferred(paths []string, chosenPath string) error {
12 chosenPath = canonicalSessionSavePath(chosenPath)
13 if chosenPath == "" {
14 return fmt.Errorf("empty preferred recovery path")
15 }
16 unique := map[string]struct{}{}
17 for _, path := range paths {
18 if path = canonicalSessionSavePath(path); path != "" {
19 unique[path] = struct{}{}
20 }
21 }
22 if _, ok := unique[chosenPath]; !ok {
23 return fmt.Errorf("preferred recovery path is outside the lineage")
24 }
25 ordered, err := validatedRecoveryPreferenceMembers(unique)
26 if err != nil {
27 return err
28 }
29 for _, path := range ordered {
30 if err := UpdateBranchMeta(path, false, clearRecoveryPreference); err != nil {
31 return err
32 }
33 }
34 chosen, err := LoadSession(chosenPath)
35 if err != nil || chosen == nil || chosen.normalizedDirty || chosen.eventLogDamaged {
36 return fmt.Errorf("could not fingerprint preferred recovery branch")
37 }
38 digest, err := digestSessionMessages(chosen.Snapshot())
39 if err != nil {
40 return err
41 }
42 return UpdateBranchMeta(chosenPath, false, func(meta *BranchMeta) error {
43 meta.RecoveryPreferred = true
44 meta.RecoveryPreferredDigest = digestString(digest)
45 return nil
46 })
47 }
48
49 func validatedRecoveryPreferenceMembers(unique map[string]struct{}) ([]string, error) {
50 ordered := make([]string, 0, len(unique))
51 recoveredMembers, normalMembers := 0, 0
52 for path := range unique {
53 meta, ok, err := LoadBranchMeta(path)
54 if err != nil || !ok {
55 return nil, fmt.Errorf("invalid recovery lineage member")
56 }
57 if meta.Recovered {
58 recoveredMembers++
59 } else {
60 normalMembers++
61 }
62 ordered = append(ordered, path)
63 }
64 if recoveredMembers == 0 || normalMembers > 1 {
65 return nil, fmt.Errorf("invalid recovery lineage members")
66 }
67 sort.Strings(ordered)
68 return ordered, nil
69 }
70
71 func clearRecoveryPreference(meta *BranchMeta) error {
72 meta.RecoveryPreferred = false
73 meta.RecoveryPreferredDigest = ""
74 return nil
75 }
76
76 lines GO