返回 DeepSeek-Reasonix
snapshot_same_revision.go
根目录 / internal / control / snapshot_same_revision.go
1 package control
2
3 import (
4 "errors"
5
6 "reasonix/internal/agent"
7 )
8
9 // persistSessionSnapshot writes path with snapshot semantics, escalating to an
10 // owned rewrite when mid-turn reshape or same-revision divergence is detected.
11 // Authority-bound rewrites stay on the canonical path; missing/stale authority
12 // is returned as a typed error so callers rebind instead of forking recovery.
13 func persistSessionSnapshot(s *agent.Session, path string, forceRewrite bool) (error, bool) {
14 return persistSessionSnapshotMode(s, path, forceRewrite, false)
15 }
16
17 func persistSessionSnapshotMode(s *agent.Session, path string, forceRewrite, checkpoint bool) (error, bool) {
18 if s == nil {
19 return nil, forceRewrite
20 }
21 forceRewrite = forceRewrite || s.NeedsRewriteSave()
22 var err error
23 if checkpoint {
24 err = s.SaveToolCheckpoint(path, forceRewrite)
25 } else if forceRewrite {
26 return s.SaveRewrite(path), true
27 } else {
28 err = s.SaveSnapshot(path)
29 }
30 if authoritySaveError(err) {
31 return err, forceRewrite
32 }
33 if !errors.Is(err, agent.ErrSessionSnapshotConflict) {
34 return err, forceRewrite
35 }
36 // Auto-compaction may rewrite between the decision and the write.
37 if s.NeedsRewriteSave() {
38 return s.SaveRewrite(path), true
39 }
40 // Same-revision diverged: prefer rewrite over a recovery fork when this
41 // session still holds a live write authority for path.
42 if err2, ok := retrySameRevisionDivergedRewrite(s, path, err); ok {
43 return err2, true
44 }
45 return err, false
46 }
47
48 func retrySameRevisionDivergedRewrite(s *agent.Session, path string, err error) (error, bool) {
49 kind, ok := agent.SnapshotConflictKind(err)
50 if !ok || kind != agent.SessionSnapshotConflictDiverged {
51 return err, false
52 }
53 var conflict *agent.SessionSnapshotConflictError
54 if !errors.As(err, &conflict) || conflict == nil || conflict.BaseRevision != conflict.DiskRevision {
55 return err, false
56 }
57 // SaveRewrite itself requires digest ownership or a live authority; a
58 // process lease alone cannot claim the current bytes.
59 return s.SaveRewrite(path), true
60 }
61
61 lines GO