Class: Rubino::Tools::ReadTracker
- Inherits:
-
Object
- Object
- Rubino::Tools::ReadTracker
- 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
-
#initialize ⇒ ReadTracker
constructor
A new instance of ReadTracker.
- #mtime_at_read(path) ⇒ Object
- #register(path, mtime) ⇒ Object
-
#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.
- #seen?(path) ⇒ Boolean
Constructor Details
#initialize ⇒ ReadTracker
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
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 |