@@ -193,41 +193,50 @@ def _persist(
193193) -> bool :
194194 doc_id = doc_dict .get ("document_id" ) or _doc_id (path )
195195
196- # Skip if already in DB
197- existing = session .query (Document ).filter (Document .document_id == doc_id ).first ()
198- if existing :
196+ existing_doc = (
197+ session .query (Document ).filter (Document .document_id == doc_id ).first ()
198+ )
199+ existing_analysis = (
200+ session .query (Analysis ).filter (Analysis .document_id == doc_id ).first ()
201+ if existing_doc
202+ else None
203+ )
204+
205+ # Fully processed already — skip
206+ if existing_doc and existing_analysis :
199207 return False
200208
201- doc_row = Document (
202- document_id = doc_id ,
203- title = path . stem . replace ( "_" , " " ). replace ( "-" , " " ). title ()[: 200 ] ,
204- document_type = path .suffix . lstrip ( "." ). lower () ,
205- jurisdiction = jurisdiction ,
206- created_at = datetime . now ( UTC ) ,
207- updated_at = datetime .now (UTC ),
208- )
209- session .add (doc_row )
210- session .flush ()
209+ if not existing_doc :
210+ doc_row = Document (
211+ document_id = doc_id ,
212+ title = path .stem . replace ( "_" , " " ). replace ( "-" , " " ). title ()[: 200 ] ,
213+ document_type = path . suffix . lstrip ( "." ). lower () ,
214+ jurisdiction = jurisdiction ,
215+ updated_at = datetime .now (UTC ),
216+ )
217+ session .add (doc_row )
218+ session .flush ()
211219
212220 analysis_row = Analysis (
213221 document_id = doc_id ,
214- scalar_score = 1.0 - min (len (findings ) * 0.02 , 0.5 ),
215- created_at = datetime .now (UTC ),
222+ anomaly_count = len (findings ),
223+ scalar_score = round (1.0 - min (len (findings ) * 0.02 , 0.5 ), 4 ),
224+ engine_version = "3.6.0" ,
216225 )
217226 session .add (analysis_row )
218227 session .flush ()
219228
220229 for f in findings :
221- anomaly_row = Anomaly (
222- analysis_id = analysis_row .id ,
223- anomaly_id = f .get ("id" , "unknown" ),
224- issue = f .get ("issue" , "" )[:500 ],
225- severity = f .get ("severity" , "low" ),
226- layer = f .get ("layer" , "unknown" ),
227- details_json = json .dumps (f .get ("details" , {})),
228- created_at = datetime .now (UTC ),
230+ session .add (
231+ Anomaly (
232+ analysis_id = analysis_row .id ,
233+ anomaly_id = f .get ("id" , "unknown" ),
234+ issue = f .get ("issue" , "" )[:500 ],
235+ severity = f .get ("severity" , "low" ),
236+ layer = f .get ("layer" , "unknown" ),
237+ details_json = json .dumps (f .get ("details" , {})),
238+ )
229239 )
230- session .add (anomaly_row )
231240
232241 session .commit ()
233242 return True
@@ -238,7 +247,7 @@ def _persist(
238247# ---------------------------------------------------------------------------
239248
240249
241- def _ingest_folder (
250+ def _ingest_folder ( # noqa: C901
242251 folder : Path ,
243252 jurisdiction : str ,
244253 dry_run : bool ,
@@ -265,49 +274,52 @@ def _ingest_folder(
265274
266275 logger .info (" %s → '%s': %d files" , folder .name , jurisdiction , len (files ))
267276
268- with get_db () as session :
269- for i , path in enumerate (files , 1 ):
270- label = f"[{ i } /{ len (files )} ] { path .name [:60 ]} "
271- print (f" { label } " , end = "\r " , flush = True )
272-
273- raw_text = _extract_text (path )
274- if not raw_text or not raw_text .strip ():
275- stats ["skipped_empty" ] += 1
276- if verbose :
277- logger .debug ("Empty text: %s" , path .name )
278- continue
279-
280- doc_dict : dict [str , Any ] = {
281- "document_id" : _doc_id (path ),
282- "title" : path .stem ,
283- "raw_text" : raw_text ,
284- "jurisdiction" : jurisdiction ,
285- "sections" : [{"section_id" : "main" , "content" : raw_text }],
286- }
287-
288- if dry_run :
289- result = analyze_document (doc_dict )
290- n = result .get ("count" , 0 )
277+ def _run_one (path : Path , session : Any | None ) -> None :
278+ print (
279+ f" [{ files .index (path ) + 1 } /{ len (files )} ] { path .name [:60 ]} " ,
280+ end = "\r " ,
281+ flush = True ,
282+ )
283+ raw_text = _extract_text (path )
284+ if not raw_text or not raw_text .strip ():
285+ stats ["skipped_empty" ] += 1
286+ return
287+ doc_dict : dict [str , Any ] = {
288+ "document_id" : _doc_id (path ),
289+ "title" : path .stem ,
290+ "raw_text" : raw_text ,
291+ "jurisdiction" : jurisdiction ,
292+ "sections" : [{"section_id" : "main" , "content" : raw_text }],
293+ }
294+ result = analyze_document (doc_dict )
295+ if dry_run :
296+ stats ["processed" ] += 1
297+ stats ["findings" ] += result .get ("count" , 0 )
298+ if verbose :
299+ logger .info (
300+ "DRY-RUN %s → %d findings" , path .name , result .get ("count" , 0 )
301+ )
302+ return
303+ try :
304+ findings = result .get ("anomalies" , [])
305+ if _persist (session , doc_dict , findings , jurisdiction , path ):
291306 stats ["processed" ] += 1
292- stats ["findings" ] += n
293- if verbose :
294- logger .info ("DRY-RUN %s → %d findings" , path .name , n )
295- continue
296-
297- try :
298- result = analyze_document (doc_dict )
299- findings = result .get ("anomalies" , [])
300- inserted = _persist (session , doc_dict , findings , jurisdiction , path )
301- if inserted :
302- stats ["processed" ] += 1
303- stats ["findings" ] += len (findings )
304- else :
305- stats ["skipped_dup" ] += 1
306- except Exception as exc : # noqa: BLE001
307- stats ["errors" ] += 1
308- logger .warning ("Error on %s: %s" , path .name , exc )
309- if verbose :
310- traceback .print_exc ()
307+ stats ["findings" ] += len (findings )
308+ else :
309+ stats ["skipped_dup" ] += 1
310+ except Exception as exc : # noqa: BLE001
311+ stats ["errors" ] += 1
312+ logger .warning ("Error on %s: %s" , path .name , exc )
313+ if verbose :
314+ traceback .print_exc ()
315+
316+ if dry_run :
317+ for path in files :
318+ _run_one (path , None )
319+ else :
320+ with get_db () as session :
321+ for path in files :
322+ _run_one (path , session )
311323
312324 print () # clear \r line
313325 return stats
0 commit comments