Module: KairosMcp::Daemon::EditKernel

Defined in:
lib/kairos_mcp/daemon/edit_kernel.rb

Overview

EditKernel — pure-function string replacement + hash computation.

Design (P3.2 v0.2 §3):

Shared by ProposedEdit (simulate) and apply path. No I/O —
caller provides content bytes. This eliminates divergence risk
between simulation and actual write.

Defined Under Namespace

Classes: AmbiguousError, NotFoundError

Class Method Summary collapse

Class Method Details

.compute(content, old_string:, new_string:, replace_all: false) ⇒ Hash

Compute a string replacement and return pre/post hashes.

Parameters:

  • content (String)

    original file bytes (binread)

  • old_string (String)

    text to find

  • new_string (String)

    replacement text

  • replace_all (Boolean) (defaults to: false)

    replace all occurrences

Returns:

  • (Hash)

    { new_content:, occurrences:, pre_hash:, post_hash: }

Raises:



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/kairos_mcp/daemon/edit_kernel.rb', line 26

def self.compute(content, old_string:, new_string:, replace_all: false)
  raise ArgumentError, 'old_string must not be empty' if old_string.nil? || old_string.empty?
  raise ArgumentError, 'old_string == new_string (no-op)' if old_string == new_string

  occurrences = content.scan(old_string).size
  raise NotFoundError, 'old_string not found in content' if occurrences.zero?
  if occurrences > 1 && !replace_all
    raise AmbiguousError,
          "old_string not unique (#{occurrences} occurrences); pass replace_all: true"
  end

  new_content = replace_all ? content.gsub(old_string, new_string) : content.sub(old_string, new_string)
  {
    new_content: new_content,
    occurrences: occurrences,
    pre_hash:    hash_bytes(content),
    post_hash:   hash_bytes(new_content)
  }
end

.hash_bytes(bytes) ⇒ String

Content-addressed hash of raw bytes.

Parameters:

  • bytes (String)

Returns:

  • (String)

    “sha256:<hex>”



49
50
51
# File 'lib/kairos_mcp/daemon/edit_kernel.rb', line 49

def self.hash_bytes(bytes)
  "sha256:#{Digest::SHA256.hexdigest(bytes)}"
end