返回 DeepSeek-Reasonix
save_persist.go
根目录 / internal / agent / save_persist.go
1 package agent
2
3 import (
4 "crypto/sha256"
5 "os"
6
7 "reasonix/internal/provider"
8 "reasonix/internal/store"
9 )
10
11 func (s *Session) markPersisted(path string, digest [sha256.Size]byte, version uint64, revision int64, rewriteVersion int) {
12 // Recovery-lane writes stay unpaired so writer-tail CAS stays disarmed.
13 s.setPersistedBaseline(path, digest, version, revision, true, true, rewriteVersion, nil)
14 }
15
16 // markPersistedFromLoad anchors a loaded ledger. It is not write-verified, so
17 // it never arms the snapshot no-op. view is the on-disk transcript, or the
18 // pre-repair raw view when load-time normalization changed it.
19 func (s *Session) markPersistedFromLoad(path string, digest [sha256.Size]byte, version uint64, revision int64, rewriteVersion int, view []provider.Message) {
20 s.setPersistedBaseline(path, digest, version, revision, true, false, rewriteVersion, view)
21 }
22
23 // markPersistedRevisionUnknown records digest+version when the meta sidecar
24 // is unreadable. Revision CAS stays disarmed until a successful save.
25 func (s *Session) markPersistedRevisionUnknown(path string, digest [sha256.Size]byte, version uint64, rewriteVersion int, view []provider.Message) {
26 s.setPersistedBaseline(path, digest, version, 0, false, false, rewriteVersion, view)
27 }
28
29 func (s *Session) setPersistedBaseline(path string, digest [sha256.Size]byte, version uint64, revision int64, revisionKnown, saveVerified bool, rewriteVersion int, persistedView []provider.Message) {
30 s.mu.Lock()
31 s.persisted = sessionPersistState{
32 path: canonicalSessionSavePath(path),
33 digest: digest,
34 version: version,
35 revision: revision,
36 revisionKnown: revisionKnown,
37 saveVerified: saveVerified,
38 ok: true,
39 }
40 if rewriteVersion > s.persistedRewriteVersion {
41 s.persistedRewriteVersion = rewriteVersion
42 }
43 if persistedView != nil {
44 s.persistedMessages = append([]provider.Message(nil), persistedView...)
45 s.persistedViewPath = canonicalSessionSavePath(path)
46 } else {
47 s.persistedMessages = nil
48 s.persistedViewPath = ""
49 }
50 if saveVerified {
51 s.normalizedDirty = false
52 s.rawMessages = nil
53 s.eventLogDamaged = false
54 }
55 writer := s.writeWriterLocked()
56 logTail := int64(0)
57 if info, err := os.Stat(store.SessionEventLog(path)); err == nil {
58 logTail = info.Size()
59 }
60 s.mu.Unlock()
61 if writer != nil {
62 writer.RecordBaseline(path, revision, digestString(digest), revisionKnown, logTail)
63 }
64 }
65
66 // writeWriterLocked returns the SessionWriter behind the bound authority.
67 // Callers hold s.mu.
68 func (s *Session) writeWriterLocked() *SessionWriter {
69 if s.writeAuth == nil {
70 return nil
71 }
72 return s.writeAuth.writer
73 }
74
75 // syncWriterBaseline copies this session's persist ledger onto the bound
76 // writer so the first save after Bind can CAS against the event-log tail.
77 func (s *Session) syncWriterBaseline(path string) {
78 if s == nil {
79 return
80 }
81 st := s.persistState(path)
82 s.mu.RLock()
83 writer := s.writeWriterLocked()
84 s.mu.RUnlock()
85 if writer == nil || !st.ok || !st.revisionKnown {
86 return
87 }
88 logTail := int64(0)
89 if info, err := os.Stat(store.SessionEventLog(path)); err == nil {
90 logTail = info.Size()
91 }
92 writer.RecordBaseline(path, st.revision, digestString(st.digest), true, logTail)
93 }
94
94 lines GO