Module: Textus::Etag

Defined in:
lib/textus/etag.rb

Class Method Summary collapse

Class Method Details

.contract_files(root) ⇒ Object

manifest.yaml, then every hook and schema file. Dir.glob already returns sorted paths (Ruby 3.0+), keeping the digest independent of FS order.



28
29
30
31
32
33
34
# File 'lib/textus/etag.rb', line 28

def self.contract_files(root)
  [
    File.join(root, "manifest.yaml"),
    *Dir.glob(File.join(root, "hooks", "**", "*.rb")),
    *Dir.glob(File.join(root, "schemas", "**", "*")).select { |f| File.file?(f) },
  ]
end

.for_bytes(bytes) ⇒ Object



5
6
7
# File 'lib/textus/etag.rb', line 5

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

.for_contract(root) ⇒ Object

The fingerprint of everything an agent’s boot orientation depends on: the manifest PLUS the executable contract — hooks and schemas. A mid-session edit to any of these makes the cached orientation stale, so the session must re-boot (ADR 0074). The composite is one digest over the sorted per-file listing, so it is order-stable.



18
19
20
21
22
23
24
# File 'lib/textus/etag.rb', line 18

def self.for_contract(root)
  listing = contract_files(root).map do |path|
    rel = path.delete_prefix(root).delete_prefix("/")
    "#{rel}:#{for_file(path)}"
  end.join("\n")
  for_bytes(listing)
end

.for_file(path) ⇒ Object



9
10
11
# File 'lib/textus/etag.rb', line 9

def self.for_file(path)
  for_bytes(File.binread(path))
end