@@ -35,6 +35,7 @@ def perform(source_document)
3535 created_commitments = create_commitments ( deduped , source_document . government , source , policy_areas , departments )
3636
3737 set_parent_relationships ( created_commitments , deduped )
38+ reconcile_commitments ( created_commitments , source_document , source )
3839
3940 source_document . update! (
4041 status : :extracted ,
@@ -128,6 +129,7 @@ def create_commitments(extracted, government, source, policy_areas, departments)
128129 cs . reference = data [ "source_reference" ]
129130 cs . excerpt = data [ "original_text" ] &.truncate ( 500 )
130131 end
132+ update_commitment_if_drifted ( commitment , data , source )
131133 created [ data [ "title" ] ] = commitment
132134 next
133135 end
@@ -176,4 +178,70 @@ def set_parent_relationships(created, extracted)
176178 child . update! ( parent : parent ) unless child . parent_id == parent . id
177179 end
178180 end
181+
182+ def update_commitment_if_drifted ( commitment , data , source )
183+ tracked_fields = %w[ title description original_text ]
184+ changes = { }
185+
186+ tracked_fields . each do |field |
187+ new_value = data [ field ]
188+ next if new_value . blank?
189+ next if commitment . send ( field ) == new_value
190+ changes [ field ] = new_value
191+ end
192+
193+ return if changes . empty?
194+
195+ old_values = {
196+ title : commitment . title ,
197+ description : commitment . description ,
198+ original_text : commitment . original_text
199+ }
200+ new_values = old_values . merge ( changes . symbolize_keys )
201+
202+ summarizer = CommitmentDriftSummarizer . create! ( record : commitment )
203+ summarizer . extract! ( summarizer . prompt ( old_values , new_values ) )
204+
205+ commitment . drift_source = source
206+ commitment . drift_change_summary = summarizer . change_summary
207+ commitment . update! ( changes )
208+ end
209+
210+ def reconcile_commitments ( created_commitments , source_document , source )
211+ created_ids = created_commitments . values . map ( &:id )
212+ active_commitments = Commitment . where ( government : source_document . government )
213+ . where . not ( id : created_ids )
214+ . where . not ( status : :abandoned )
215+
216+ return if active_commitments . empty?
217+
218+ reconciler = CommitmentReconciler . create! ( record : source_document )
219+ reconciler . extract! ( reconciler . prompt ( created_commitments . values , active_commitments ) )
220+
221+ ( reconciler . update_existing || [ ] ) . each do |entry |
222+ existing = Commitment . find_by ( id : entry [ "existing_commitment_id" ] )
223+ new_commitment = created_commitments . values . find { |c | c . title == entry [ "new_commitment_title" ] }
224+ next unless existing && new_commitment
225+
226+ data = {
227+ "title" => new_commitment . title ,
228+ "description" => new_commitment . description ,
229+ "original_text" => new_commitment . original_text
230+ }
231+ update_commitment_if_drifted ( existing , data , source )
232+
233+ new_commitment . commitment_sources . update_all ( commitment_id : existing . id )
234+ new_commitment . destroy!
235+ created_commitments . delete ( entry [ "new_commitment_title" ] )
236+ end
237+
238+ ( reconciler . abandoned || [ ] ) . each do |entry |
239+ next unless entry [ "confidence" ] . to_f >= 0.6
240+ commitment = Commitment . find_by ( id : entry [ "commitment_id" ] )
241+ next unless commitment
242+
243+ commitment . abandonment_reason = entry [ "reason" ]
244+ commitment . update! ( status : :abandoned )
245+ end
246+ end
179247end
0 commit comments