
    R*aj3                        d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m	Z	m
Z
 ddlmZ ddlmZmZmZmZmZmZ  ed      Zdd	Zdd
ZddZddZddZedk(  r e        yy)zGRead-only deterministic analysis and clustering for the review backlog.    )annotationsN)Counterdefaultdict)datetimetimezone)Path)NORMALIZATION_VERSIONVERSIONalias_registryclassify	exact_keynormz?/opt/struktur/obsidian-knowledge-pipeline/knowledge_pipeline.dbc                 d    t        j                  t        j                        j	                         S )N)r   nowr   utc	isoformat     :/opt/struktur/knowledge-curator/minimal_review_analysis.pyr   r      s    <<%//11r   c                "    | dk  rdS | dk  rdS dS )N(   short   mediumlongr   )lengths    r   quality_bucketr      s    rk7K6C<xKVKr   c                 "   t        j                  dt         dd      } t               }| j	                  d      D ]2  \  }	 |j                  t        t        j                  |                   4 | j                          |S # t        $ r Y Rw xY w)Nfile:?mode=roTuriz>SELECT candidate_json FROM truth_items WHERE status='approved')sqlite3connectPIPEsetexecuteaddr   jsonloads	Exceptionclose)coutpayloads      r   approved_keysr0      s    %vX.D9A
%Cii `a 
	GGIdjj123
 GGIJ  		s   -B	BBc           #     P   t               }t        j                  dt         dd      }t        j                  |_        t               }g }|j                  d      D ]R  }t        j                  |d         }t        ||      }|j                  |d   |d   |d	       |j                  |       T |j                          t        t              }t        t              }	t        t              }
|D ]  }||d
      j                  |       dj!                  |d   |d   |d   t#        |d         t%        |d         f      }||d<   |	|   j                  |       |
|d      j                  |        g }d}t'        |	j)                         d       D ]  \  }}t+        |      dk  r|dz  }d|d}|D ]  }||d<   t+        |      |d<    |j                  ||t+        |      t+        |D ch c]  }|d   	 c}      t'        |D ch c]  }|d   	 c}      t'        |D ch c]  }|d   	 c}      t'        |D ch c]  }|d   	 c}      d d |d d D cg c]  }|d   	 c}t'        |D ch c]  }t#        |d           c}      d d! d"d#
        |D ]:  }|j-                  dd        |j-                  dd       t+        ||d
            |d$<   < |D cg c]  }t/        d% |d&   D              s| }}|D cg c]  }t/        d' |d&   D              r| }}|D ]  }d(|d<   	 t1        d) |D              }g }|
j)                         D ]  \  }}|D ch c]  }t#        |d*          }}t+        |      dkD  s0t+        |      dkD  s?|j                  |t+        |      t'        |      t+        |D ch c]  }t#        |d           c}      |d d D cg c]  }|d   	 c}d+d,        t3        d- |D              }t3        d. |D              }t3        d/ |D              }t3        d0 |D              }t1        d1 |D              }t3        d2 |D              }t3        d3 |D              } t3        d4 |D              }!i d5|d6t4        d7t6        d8t9        t              d9t+        |      d&t;        |      d:t;        |      d;t;        |      d<t+        |      d=t;        t'        |j)                                     d>|d?t+        |      d@|dAt+        |      dBt+        |      |z
  dCt+        |      dDt+        |      |z
  |t+        |      z
  t+        |      t1        dE |D              |j=                  dFd      t?               | jA                  d      D "#cg c]
  \  }"}#|"|#dG c}#}"|jA                  d      D "#cg c]
  \  }"}#|"|#dH c}#}"|!jA                  d      D "#cg c]
  \  }"}#|"|#dI c}#}"tC        d|j=                  dJd            tC        d|      tC        d|j=                  dKd            tC        d|j=                  dLd            tC        dt1        dM |D                    tC        dN|j=                  dFd            dOdd|||dP}$tE        | j                        jG                  t        jH                  |$dQdt        R      dSz   dTU       t        j                  | jJ                        }%|%jM                  dV       |%j                  dW      D ch c]  }|d   	 }&}dX|&vr|%j                  dY       dZtO        j                   tP        jR                        jU                  d[      z   }'t               }(|%j                  d\|'t4        t6        ||(t+        |      t+        |      t+        |      d]f	       |%jW                  d^|$d_   D )cg c]  })|)d`   |)da   |)db   |)dc   |)dd   |)d   f c})       |%j                  de       |%j                  df       |%j                  dg       |%j                  dh       |%j                  de       |%jW                  di|D *cg c]  }*|*d   |'|*d   |*d   |*dj   |*dk   |*dl   t        jH                  |*d    dQm      |*dn   |*d*   |*do   |*dp   |*d   |*d   |*dq   |*d   |*d
   |*d   |*d   |*d   |*d   |*dr   |*d   tY        |*ds         t9        |*d   j=                  dt      xs i j=                  dX      xs |*j=                  d       xs du      f c}*       |%jW                  dv|D cg c]K  }|d   |'|d   |dw   |dx   t        jH                  |d&   dQm      t        jH                  |d;   dQm      |d   fM c}       |%jW                  dy|D *cg c]+  }|D ]$  }*|*j=                  d      |d   k(  s|d   |*d   f& - c}*}       |%jW                  dz|D cg c].  }|d   |'|dw   t        jH                  |d{   dQm      |d|   |d   f0 c}       |%j[                          |%j                          d}dud~| dt+        |       dduddug}+|+t'        |j)                         d       D "#cg c]  \  }"}#d|" d|# d c}#}"z  }+|+duddt+        |       ddt+        |       dd| ddt+        |      |z
   ddt+        |       dduddug
z  }+|+|$d   j)                         D "#cg c]  \  }"}#d|" d|# d c}#}"z  }+|+g dz  }+|+t]        |$d   d      D ,cg c]  \  },}d|, d|d    d|d   d d  d c}},z  }+tE        | j^                        jG                  dSj!                  |+      dSz   dTU       dD "ci c]  }"|"|$|"   
 c}"S c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}w c c}#}"w c c}#}"w c c}#}"w c c}w c c})w c c}*w c c}w c c}*}w c c}w c c}#}"w c c}#}"w c c}},w c c}"w )Nr   r    Tr!   zSELECT candidate_id,path,chunk_key,candidate_json,status FROM review_items WHERE status='pending_review' ORDER BY created_at,candidate_idcandidate_json	chunk_keystatus)r3   pipeline_statusr2   r   |structural_keycategorysensitivity_classextraction_ruleevidence_lengthcluster_keyconflict_keyr   c                *    t        | d          | d   fS N   r   )lenpairs    r   <lambda>zanalyze.<locals>.<lambda>>   s    CQL=RVWXRYBZ r   )key   r@   zmhr-cluster-05d
cluster_idcluster_sizepathd      candidate_idobject   grouped_pending_review)
rH   r<   candidate_countdocument_count
categoriessensitivity_classespathsrepresentative_candidate_idsvariable_objectsr4   exact_group_sizec              3  $   K   | ]  }|d v 
 yw>   invalid_fragmentexcluded_non_knowledgeNr   .0r8   s     r   	<genexpr>zanalyze.<locals>.<genexpr>L   s!       5U  yAXEs5s  5U   rS   c              3  $   K   | ]  }|d v 
 ywrZ   r   r]   s     r   r_   zanalyze.<locals>.<genexpr>M   s!       =]  AIXM{={  =]r`   automatic_nonknowledge_clusterc              3  &   K   | ]	  }|d      ywrQ   Nr   r^   xs     r   r_   zanalyze.<locals>.<genexpr>P   s     E+,E   polarityconflict_pending_review)r=   rQ   
polaritiesobject_variantscandidate_idsr4   c              3  &   K   | ]	  }|d      yw)r8   Nr   r^   is     r   r_   zanalyze.<locals>.<genexpr>X   s     61:6rg   c              3  &   K   | ]	  }|d      yw)candidate_typeNr   rn   s     r   r_   zanalyze.<locals>.<genexpr>Y   s     =!!,-=rg   c              3  &   K   | ]	  }|d      yw)r9   Nr   rn   s     r   r_   zanalyze.<locals>.<genexpr>Z   s      GA#6!7 Grg   c              3  &   K   | ]	  }|d      ywrd   r   r^   rows     r   r_   zanalyze.<locals>.<genexpr>[   s     KsC 12Krg   c              3  &   K   | ]	  }|d      ywrd   r   rt   s     r   r_   zanalyze.<locals>.<genexpr>\   s     AS#'(Arg   c              3  &   K   | ]	  }|d      yw)rJ   Nr   rn   s     r   r_   zanalyze.<locals>.<genexpr>]   s     /Aai/rg   c              3  &   K   | ]	  }|d      yw)r<   Nr   rn   s     r   r_   zanalyze.<locals>.<genexpr>^   s     7Aq'7rg   c              3  &   K   | ]	  }|d      yw)r:   Nr   rn   s     r   r_   zanalyze.<locals>.<genexpr>_   s     8QA'(8rg   generated_atanalysis_versionnormalization_versiondatabasepending_totalcandidate_typesrT   cluster_countcluster_size_distributionclustered_candidateshuman_cluster_counthuman_clustered_candidatesautomatic_cluster_countunclustered_candidatesestimated_human_group_decisions*estimated_unavoidable_individual_decisionsc              3  &   K   | ]	  }|d      ywrd   r   re   s     r   r_   zanalyze.<locals>.<genexpr>h   s     P}jkQRSdQeP}rg   r[   )patterncount)rJ   r   )ruler   "inherited_human_decision_candidateindividual_pending_reviewsensitive_pending_reviewc              3  &   K   | ]	  }|d      ywrd   r   re   s     r   r_   zanalyze.<locals>.<genexpr>m   s0       aN  {|  bc  du  bv  aNrg   2   )*automatically_safe_or_inherited_candidatescluster_assignmentsindividual_unclear	sensitive	conflictsparser_corrections)+estimated_reduction_in_individual_decisionsconflict_cluster_countconflict_candidatesincomplete_evidencealiasestop_100_patternstop_100_sourcestop_100_extraction_rulessample_sizesno_status_changesno_neo4j_writesclustersr   itemsFensure_asciiindentdefault
zutf-8)encodinga  
      CREATE TABLE IF NOT EXISTS analysis_runs(run_id TEXT PRIMARY KEY, analysis_version TEXT, normalization_version TEXT, started_at TEXT, completed_at TEXT, candidate_count INTEGER, cluster_count INTEGER, conflict_count INTEGER, status TEXT);
      CREATE TABLE IF NOT EXISTS candidate_analysis(candidate_id TEXT PRIMARY KEY, run_id TEXT, path TEXT, chunk_key TEXT, candidate_type TEXT, subject TEXT, predicate TEXT, object_json TEXT, modality TEXT, polarity TEXT, temporal_scope TEXT, authority_scope TEXT, sensitivity_class TEXT, category TEXT, classification_reason TEXT, extraction_rule TEXT, exact_key TEXT, structural_key TEXT, conflict_key TEXT, cluster_id TEXT, cluster_size INTEGER, evidence_hash TEXT, evidence_length INTEGER, provenance_complete INTEGER);
      CREATE INDEX IF NOT EXISTS candidate_analysis_category_idx ON candidate_analysis(category);
      CREATE INDEX IF NOT EXISTS candidate_analysis_cluster_idx ON candidate_analysis(cluster_id);
      CREATE TABLE IF NOT EXISTS clusters(cluster_id TEXT PRIMARY KEY, run_id TEXT, cluster_key TEXT, candidate_count INTEGER, document_count INTEGER, categories_json TEXT, sensitivity_json TEXT, status TEXT);
      CREATE TABLE IF NOT EXISTS cluster_members(cluster_id TEXT, candidate_id TEXT, PRIMARY KEY(cluster_id,candidate_id));
      CREATE TABLE IF NOT EXISTS conflict_clusters(conflict_key TEXT PRIMARY KEY, run_id TEXT, candidate_count INTEGER, polarities_json TEXT, object_variants INTEGER, status TEXT);
      CREATE TABLE IF NOT EXISTS aliases(kind TEXT, alias TEXT, canonical TEXT, rationale TEXT, version TEXT, status TEXT, PRIMARY KEY(kind,alias));
      CREATE TABLE IF NOT EXISTS audit(audit_id TEXT PRIMARY KEY, run_id TEXT, phase TEXT, entity_key TEXT, details_json TEXT, created_at TEXT);
    z%PRAGMA table_info(candidate_analysis)evidence_textz<ALTER TABLE candidate_analysis ADD COLUMN evidence_text TEXTzmhr-analysis-z%Y%m%dT%H%M%S%fZz>INSERT OR REPLACE INTO analysis_runs VALUES(?,?,?,?,?,?,?,?,?)dry_run_completez2INSERT OR REPLACE INTO aliases VALUES(?,?,?,?,?,?)r   kindalias	canonical	rationaleversionzDELETE FROM candidate_analysiszDELETE FROM clusterszDELETE FROM cluster_memberszDELETE FROM conflict_clustersa  INSERT INTO candidate_analysis(candidate_id,run_id,path,chunk_key,candidate_type,subject,predicate,object_json,modality,polarity,temporal_scope,authority_scope,sensitivity_class,category,classification_reason,extraction_rule,exact_key,structural_key,conflict_key,cluster_id,cluster_size,evidence_hash,evidence_length,provenance_complete,evidence_text) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)rq   subject	predicate)r   modalitytemporal_scopeauthority_scopeclassification_reasonevidence_hashprovenance_complete
provenance z,INSERT INTO clusters VALUES(?,?,?,?,?,?,?,?)rQ   rR   z'INSERT INTO cluster_members VALUES(?,?)z1INSERT INTO conflict_clusters VALUES(?,?,?,?,?,?)rj   rk   u"   # Minimal Human Review – Dry-Runz	Erzeugt: zKandidaten: **z**z## Kategorienc                    | d    | d   fS r?   r   rB   s    r   rD   zanalyze.<locals>.<lambda>   s    Z^_`ZaYabfghbiXj r   z- `z`: **z
## Clusterz- Strukturcluster gesamt: **z - Menschliche Gruppencluster: **z)- Kandidaten in menschlichen Clustern: **z- Einzelkandidaten: **z- Konfliktcluster: **z## Stichprobenr   )r   z## Sicherheitsgrenzer   um   Schreibfreier Dry-Run: keine Statuswerte, Carlo-Entscheidungen, Obsidian- oder Neo4j-Daten wurden verändert.r   z## Top-100-Musterr   r   z- z. r   u    Kandidaten – `r      `)rz   r~   rS   r   r   r   r   r   r   r   r   r   r   r   )0r   r#   r$   r%   Rowrow_factoryr0   r'   r)   r*   r   updateappendr,   r   listjoinr   r   sortedr   rA   
setdefaultanysumr   r
   r	   strdictgetr   most_commonminr   
write_textdumpssqliteexecutescriptr   r   r   strftimeexecutemanyintcommit	enumeratemarkdown)-argsstartedr-   approvedr   ru   	candidateitemexactr   r   r<   cluster_rowscluster_counterrE   membersrH   membermrf   human_clustersautomatic_clustersclusterhuman_groupedconflict_rowsrj   rS   type_countssensitivity_countscluster_sizesgroupedsourcespatternsruleskvr.   dbexisting_columnsrun_id	completedaro   linesns-                                                r   analyzer   %   s   eG%vX.D9AKKAMHEyy  e  f JJs#345		8,#k"2s8}hqrsT	
 GGIE4 HD!I 5d; ''-hh%5 6Z8H$ObJceijn  pA  kB  fC  ES  TX  Yj  Tk  El   m  n)]$$T*$~&'..t45 LOx~~/5Z[ NWw<!1#OC#89
 	2F#-F< %(\F>"	2 	:c^abi^j  B  W^  C_  RS  DE  FL  DM  C_  `  pv  OV  wW  JK  xy  zD  xE  wW  pX  qw  Y`  xa  TU  yz  {N  yO  xa  qb  ms  HO  tP  CD  uv  w}  u~  tP  mQ  RV  SV  mW  U\  ]_  ^_  U`  ya  PQ  z{  |J  zK  ya  w}  Za  ~b  UV  C  DE  FN  DO  P  ~b  wc  dg  eg  wh  tL  M  	NN  Ad+*#&uT+->'?#@ A
 ".  VA  5U  EF  GS  ET  5U  2Ua  VN  V%1  ^  =]  MN  O[  M\  =]  :]!  ^  ^% =<=EnEEMM!) [W3:;ad1Z=);
;w<!J! 3  ##g,flmwfx  NQ  nu  Rv  ij  SW  XY  Zb  Xc  Sd  Rv  Nw  fm  nr  or  fs  Jt  ab  KL  M[  K\  Jt  @Y  "Z  [[
 666J=u==K  G GGKlKKMALAAG///G777H8%88E!3W>UWlCI.E
<H$zJZ\most  pA 	t$67 :I#lJ[ ^yz~  @F  GT  GZ  GZ  G\  @]  {^ 		 *?N@S	 Vr  tA	
 	"3'9#:
 =UVYZ_V`anVn 	*3~+> Amnqrwnx  zG  oG 8ESEX7X"%m"4SP}o|P}M})~~.@!DQ_QaCKCWCWX[C\]CAaQ7]?F?R?RSV?WX!Q3XHMHYHYZ]H^$_1a!%<$_GJ3PZP^P^  `D  EF  QG  HH  ad  eh  jq  ar  JM  NQ  S]  Sa  Sa  b}  ~  S@  JA  PS  TW  Yc  Yg  Yg  hB  CD  YE  PF  UX  Y\  ^a  aN  @M  aN  ^N  UO  gj  km  oy  o}  o}  ~P  QR  oS  gT  U!dcp  |AC  	Otzz#E!UYZ[__jqr		%B 
 
	 +-**5\*]^3A^^..


QRx||HLL9BBCUVVFIJJORXZacx  {B  DM  OR  SX  OY  [^  _k  [l  nq  r  n@  BT  RU  VNNG  be  fo  bp  Jq  ]^1V9UVW^U_`abm`nopq|o}~  AJ  K  LM  NV  LW  KX  Jq  rJJ/0"**=S2TVXV`V`a~V  BD  BL  BL  Ml  BmJJ/0NN  s  fk  ul  ab  wx  yG  wH  IO  PQ  RX  PY  Z[  \g  Zh  ij  k{  i|  }~  H  }I  JK  LW  JX  Y]  Yc  Yc  de  fn  do  }B	  YC	  D	E	  F	P	  D	Q	  R	S	  T	^	  R	_	  `	a	  b	r	  `	s	  t	u	  v	G
  t	H
  I
J
  K
^
  I
_
  `
a
  b
l
  `
m
  n
o
  p
G  n
H  IJ  K\  I]  ^_  `k  ^l  mn  o  m@  AB  CQ  AR  ST  Ua  Sb  cd  es  ct  uv  wF  uG  HI  J[  H\  ]`  ab  cx  ay  ]z  {~  @A  BR  @S  @W  @W  Xd  @e  @k  ik  p  p  q@  A  Z  EF  EJ  EJ  KS  ET  Z  XZ  {[  v\  ul  mNNA  T`  Da  OPQ|_U[\]^k\lmn  pA  nB  CD  EU  CV  W[  Wa  Wa  bc  dp  bq  D  WE  FJ  FP  FP  QR  Sh  Qi  w|  F}  ~  @H  ~I  EJ  Da  bNN<lx  ?qgh  CH  ?q}~  LM  LQ  LQ  R^  L_  ab  co  ap  Lp,PQR`Pa?b  ?q?b  ?q  rNNF  S`  Ia  NO!NJ[\bcdevcwx|  yC  yC  DE  FR  DS  af  yg  hi  j{  h|  }~  G  }H  JI  Ia  bIIK127)7LP^_bch_i^jjlNmoq  tC  EG  HE	VJ4D4D4FLj-klcaA3eA3b!llE	b,">s<?P>QQS TXxy|  ~L  zM  yN  NP  WQ  U~  L  ~M  MO  SP  Tj  kn  ot  ku  vC  kC  jD  DF  RG  K`  ad  er  as  `t  tv  Iw  y{  }M  OQ  R  RE	S-@-F-F-HIcaA3eA3b!IIE	  |  |E	V_`cdv`wxyVz{sqQR1#R'
|#4Qy\$35G4HJ{{E""499U#3D#87"K ]  ^Ac!fH  ^  ^] C_  wW  xa  tP  ya  ~b V ^ < Rv  Jt( ^X$_$ _ Jq ul Da ?q Ia mI{ ^s   .n)	n.$n3?n8n=2oo9oooo<oo%o o&1o,'o2!o7
'C
o<
Ap
0!pp83p
pp8pp#c                    t        j                         } | j                  dd       | j                  dd       | j                  dd       | j                         }t	        t        j                  t        |      dd	t        
             y )Nz--jsonzA/opt/struktur/knowledge-curator/minimal-human-review-dry-run.json)r   z--sqlitez7/opt/struktur/knowledge-curator/minimal-human-review.dbz
--markdownz?/opt/struktur/knowledge-curator/minimal-human-review-dry-run.mdFrF   r   )	argparseArgumentParseradd_argument
parse_argsprintr)   r   r   r   )apr   s     r   mainr      s    		 	 	"BBOOH  GJO  %K  MO  M\  M\  ]g  qj  M\  Mk  mo  m|  m|  }I  ST  m|  mU==?DE$**WT]WXbf"ghr   __main__)returnr   )r   r   r  r   )r  zset[str])r   zargparse.Namespacer  r   )r  None)__doc__
__future__r   r   r)   r#   collectionsr   r   r   r   pathlibr   minimal_review_corer	   r
   r   r   r   r   r%   r   r   r0   r   r   __name__r   r   r   <module>r
     s`    M "    , '  i iMN2L	o^di
 zF r   