Class: Ecoportal::API::GraphQL::Diff::Pairing::Ledger
- Inherits:
-
Object
- Object
- Ecoportal::API::GraphQL::Diff::Pairing::Ledger
- Defined in:
- lib/ecoportal/api/graphql/diff/pairing/ledger.rb
Overview
The LEARNING LEDGER — a first-class artifact that records CONFIRMED equivalences between objects that live in different id-spaces (UAT<->PROD, page<->template). Because MongoDB gives every object a distinct id and nothing is shared across counterparts, pairing is an equivalence / entity-resolution problem, not a lookup. Every decision the engine (or a human) makes is persisted here so pairing IMPROVES over time: on the next run the ledger is consulted FIRST and previously-resolved pairs auto-resolve, leaving only genuine novelty for the human to adjudicate.
An entry is keyed by (kind, source_id) and records the paired target_id plus HOW it was resolved (the method, the confidence, the signals, a timestamp). This log of how is the bridge data Product's Field-ID / template-entity-id effort needs.
ledger = Ledger.load('pairings.json') # or Ledger.new (in-memory) ledger.record(kind: :field, source_id: 'a', target_id: 'b', method: :genome, confidence: 0.98, signals: ...) ledger.lookup(:field, 'a') # => Entry or nil ledger.save # persist back to the same path
SAFETY — the ledger stores only decisions that were CONFIRMED (auto-accepted at high confidence, or human-adjudicated). Ambiguous/low-confidence candidates are never written; they are escalated. The ledger is thus a growing store of ground truth, never guesses.
Defined Under Namespace
Classes: Entry
Class Method Summary collapse
-
.load(path) ⇒ Object
Load a ledger from a JSON file.
Instance Method Summary collapse
- #entries ⇒ Object
-
#initialize(entries: [], path: nil) ⇒ Ledger
constructor
A new instance of Ledger.
-
#lookup(kind, source_id) ⇒ Object
The confirmed Entry for (kind, source_id), or nil if never resolved.
-
#record(kind:, source_id:, target_id:, matched_by:, confidence: nil, signals: nil) ⇒ Object
Record a CONFIRMED equivalence.
-
#save(path = @path) ⇒ Object
Persist to
path(or the load path). - #size ⇒ Object
-
#target_for(kind, source_id) ⇒ Object
The confirmed target id for (kind, source_id), or nil.
- #to_h ⇒ Object
Constructor Details
#initialize(entries: [], path: nil) ⇒ Ledger
Returns a new instance of Ledger.
43 44 45 46 47 |
# File 'lib/ecoportal/api/graphql/diff/pairing/ledger.rb', line 43 def initialize(entries: [], path: nil) @path = path @entries = {} Array(entries).each { |e| add_entry(coerce(e)) } end |
Class Method Details
.load(path) ⇒ Object
Load a ledger from a JSON file. A missing file yields an empty (still writable) ledger.
50 51 52 53 |
# File 'lib/ecoportal/api/graphql/diff/pairing/ledger.rb', line 50 def self.load(path) data = File.exist?(path) ? JSON.parse(File.read(path)) : {} new(entries: data['entries'] || [], path: path) end |
Instance Method Details
#entries ⇒ Object
78 79 80 |
# File 'lib/ecoportal/api/graphql/diff/pairing/ledger.rb', line 78 def entries @entries.values end |
#lookup(kind, source_id) ⇒ Object
The confirmed Entry for (kind, source_id), or nil if never resolved.
69 70 71 |
# File 'lib/ecoportal/api/graphql/diff/pairing/ledger.rb', line 69 def lookup(kind, source_id) @entries[[kind.to_sym, source_id]] end |
#record(kind:, source_id:, target_id:, matched_by:, confidence: nil, signals: nil) ⇒ Object
Record a CONFIRMED equivalence. matched_by names how it was resolved (:genome,
:label, :ledger, :human, ...). Later records for the same (kind, source_id) supersede
earlier ones (a human can correct an auto-accept). Returns the stored Entry.
58 59 60 61 62 63 64 65 66 |
# File 'lib/ecoportal/api/graphql/diff/pairing/ledger.rb', line 58 def record(kind:, source_id:, target_id:, matched_by:, confidence: nil, signals: nil) entry = Entry.new( kind: kind.to_sym, source_id: source_id, target_id: target_id, matched_by: matched_by&.to_sym, confidence: confidence, signals: signals, recorded_at: Time.now.utc.iso8601 ) add_entry(entry) entry end |
#save(path = @path) ⇒ Object
Persist to path (or the load path). Returns the path written.
91 92 93 94 95 96 |
# File 'lib/ecoportal/api/graphql/diff/pairing/ledger.rb', line 91 def save(path = @path) raise ArgumentError, 'no path to save the ledger to' if path.nil? File.write(path, JSON.pretty_generate(to_h)) path end |
#size ⇒ Object
82 83 84 |
# File 'lib/ecoportal/api/graphql/diff/pairing/ledger.rb', line 82 def size @entries.size end |
#target_for(kind, source_id) ⇒ Object
The confirmed target id for (kind, source_id), or nil.
74 75 76 |
# File 'lib/ecoportal/api/graphql/diff/pairing/ledger.rb', line 74 def target_for(kind, source_id) lookup(kind, source_id)&.target_id end |
#to_h ⇒ Object
86 87 88 |
# File 'lib/ecoportal/api/graphql/diff/pairing/ledger.rb', line 86 def to_h { entries: entries.map(&:to_h) } end |