Class: Rubino::Tools::ReadTracker

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/tools/read_tracker.rb

Overview

Tracks which files the model has Read during the current session so Edit and MultiEdit can refuse to write to a file the model never opened. Without this, the model is free to “remember” the contents of a file from training-time priors and edit a string that isn’t actually there, corrupting the file silently when the gsub goes through anyway because the match happens to occur by accident.

The tracker also stashes the mtime at the moment of read so the edit path can detect “file changed under us” — the user saving from a separate editor, or another tool mutating the file after the read.

Lifecycle: one instance PER SESSION (see .for_session), shared by every turn’s ToolExecutor in this process — a read in turn 1 still satisfies the gate in turn 2 while the file is unchanged on disk; any mtime bump forces a re-read (#151). Resume in a NEW process does NOT carry the tracker — the model must re-read after a resume before editing. That’s the conservative call: the file may have changed on disk in the gap.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeReadTracker

Returns a new instance of ReadTracker.



43
44
45
46
# File 'lib/rubino/tools/read_tracker.rb', line 43

def initialize
  @reads   = {}
  @windows = Hash.new(0)
end

Class Method Details

.for_session(session_id) ⇒ Object



31
32
33
34
35
36
# File 'lib/rubino/tools/read_tracker.rb', line 31

def for_session(session_id)
  key = session_id.to_s
  return new if key.empty?

  @registry_mutex.synchronize { @registry[key] ||= new }
end

.reset!Object



38
39
40
# File 'lib/rubino/tools/read_tracker.rb', line 38

def reset!
  @registry_mutex.synchronize { @registry = {} }
end

Instance Method Details

#mtime_at_read(path) ⇒ Object



76
77
78
79
80
81
# File 'lib/rubino/tools/read_tracker.rb', line 76

def mtime_at_read(path)
  key = canonical(path)
  return nil unless key

  @reads[key]
end

#register(path, mtime) ⇒ Object



48
49
50
51
52
53
# File 'lib/rubino/tools/read_tracker.rb', line 48

def register(path, mtime)
  key = canonical(path)
  return unless key

  @reads[key] = mtime
end

#register_window(path, offset, limit, mtime) ⇒ Object

Records a read of an exact (path, offset, limit, mtime) window and returns how many times that identical window has now been requested in this session. >1 means the model is re-reading bytes it already has in context — ReadTool uses this to return a [DUPLICATE READ] nudge instead of re-emitting the same content. Keyed on mtime so a real edit between reads (mtime bump) is NOT treated as a duplicate.



61
62
63
64
65
66
67
# File 'lib/rubino/tools/read_tracker.rb', line 61

def register_window(path, offset, limit, mtime)
  key = canonical(path)
  return 1 unless key

  sig = [key, offset.to_i, limit.to_i, mtime]
  @windows[sig] += 1
end

#seen?(path) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
72
73
74
# File 'lib/rubino/tools/read_tracker.rb', line 69

def seen?(path)
  key = canonical(path)
  return false unless key

  @reads.key?(key)
end