
    RjL                        d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlmZ d dl	m	Z	m
Z
  ed      Z ed      ZdZ e j                  edz  j                               Zed   Z e j                  ed	z  j                               Zed   Zed
z  j)                  dd      5 Z ej,                  ed      D  ci c]  } | d   | 
 c} Zddd       eD  ci c]  } | d   | 
 c} Zg Zej5                         D ]  \  ZZej;                  ei       Zej;                  dd      Zej;                  d      s=ej;                  d      ek7  sRejA                  eej;                  d      e e jB                  dD ci c]  }|ej;                  |d       c}d       e jB                  dD ci c]  }|ej;                  |d       c}d       e jB                  dD ci c]  }|ej;                  |d       c}d      ddd        edz  j)                  ddd      5 Z e"ed          Z# ejH                  ee#      Z%e%jM                          e%jO                  e       ddd       eD  ci c]  } | d   | 
 c} Z(g Z)eD ]   Zej;                  d      d k7  re(j;                  ed   i       Zd!Z*ej;                  d      d"v rd#Z*nCej;                  d      d$k(  rd$Z*n,ej;                  d      d%k(  rd&Z*nej;                  d      d'vrd(Z*e)jA                  ed   d ej;                  d      e*ej;                  d)      ej;                  d*      ej;                  d+      ej;                  d,      ej;                  d-      d.	        ed/z  jW                   e jB                   e,e)      d0D ci c]   e-fd1e)D               c}e)d2dd34              ej\                  d5d67      Z/ej`                  e/_1        i Z2e/jg                  d8      D ]  Ze2ji                  ed9    e5e              e/jm                          d:d;d<d=d>d?d@dAdAdBdCdDdEdFd;dGdHdIdJdAdKdAdLe2j;                  dJi       j;                  dMdN      dOdEdPdQdRdSdTdJdUdAdVdWe2j;                  dJi       j;                  dMdN      dXdEdYdZd[d\d]d^dAdAd_d`e2j;                  dai       j;                  dMdN      dbdEdcdddedfdgdJdhdAdidjdNdkdEdldddedmdgd^dAdAdidndNdkdEgZ7edoz  j)                  ddd      5 Z e"e7d          Z# ejH                  ee#      Z%e%jM                          e%jO                  e7       ddd       d dl8Z9d dl:Z9dhZ;dhZ<dZ=	 e9j|                  j                  edpz   dqr      Z e@ej                        Z;	 e9j|                  j                  edsz   dtdudvidwx      ZGe9j|                  j                  eGdyr       d|D ].  ZMeeMz  ZNeNj                         s ej                  eNeeMz         0 ed}   ZQ e j                  ed~z  j                               ZR e j                  ed/z  j                               ZS e j                  edz  j                               ZTdj                  g ded    deQj;                  dd        deQj;                  dd        deQj;                  d d        deQj;                  dd        deQj;                  dd        deQj;                  d%d        deQj;                  dd        deQj;                  d$d        deQj;                  dd        deQj;                  dd        d e-eQj                                d e-eQj                                deQj;                  dd        deQj;                  dd        d e,eR       d e-d eRD               d e-d eRD               deSd   d!    deSd   d#    deSd   d&    deSd   d$    deSd   d(    deTd    deTd   d    deTd   d    deTd   d    deTd   d    deTd   d    d      ZWedz  jW                  eWd        ej                  edz  edz          eXdedz         yc c} w # 1 sw Y   xY wc c} w c c}w c c}w c c}w # 1 sw Y   hxY wc c} w c c}w # 1 sw Y   xY w# eB$ rZC eDeC      j                  Z;Y dZC[CtdZC[Cww xY w# e9j                  j                  $ r>ZC e@eCj                        Z<eCj                  dz      j                  dd{      Z=Y dZC[CdZC[CweB$ rZC eDeC      j                  Z<Y dZC[CdZC[Cww xY w)    N)Path)datetimetimezonez2/opt/struktur/obsidian-graphiti-reconciler-stagingz3/opt/struktur/knowledge-pipeline-aggregator-stagingzhttp://127.0.0.1:8644+obsidian-graphiti-reconciliation-AA042.jsonrowsz+obsidian-graphiti-reconciliation-AA041.jsonz*obsidian-graphiti-reconciliation-AA040.csvzutf-8 )encodingnewline	)	delimiterrelative_pathcanonical_relative_pathclassificationfinal_classification)graphiti_match_typematch_reasonsha256queue_idepisode_uuidobsidian_document_idgraphiti_current_hash_matchF)ensure_ascii)r   graphiti_episode_uuidprovenance_statusreason)source_identityexternal_source_idcontent_sha256normalized_content_sha256r   import_identityzAA-041 introduced stable source identity/cross-source YouTube matching and conservative ambiguity; AA-040 used narrower canonical importer/path evidence.zKAA-041 source identity/provenance evidence; review-safe when not equivalent)r   old_classificationnew_classificationaa040_match_methodaa041_match_methodids_hashes_paths_provenancewhy_changedbetter_supportedaa040-aa041-deltas.csvw)r
   r	   )
fieldnamesMISSINGTRUE_MISSING)SOURCE_ALREADY_PRESENTCROSS_SOURCE_PRESENT	AMBIGUOUSHISTORICAL_MATCH
HISTORICAL)r+   r   OTHERr   r   r   r   r   )	pathaa041_classificationaa042_classificationvalidation_bucketr   r   match_methodr   r   "missing-1168-validation-AA042.json)r,   r.   r1   r/   r2   c              3   .   K   | ]  }|d    k(    yw)r6   N ).0xks     /opt/struktur/aa042_finalize.py	<genexpr>r?      s;       kT  JKkl  nA  lB  DE  lE  kTs   )totaldistributioncases   )r   indentz<file:/opt/struktur/graphiti/request-data/requests.db?mode=roT)uriz8select * from graphiti_requests order by started_at descsource_systemzgraphiti-service APIACTIVEzdocker graphiti-servicez&/opt/struktur/graphiti/service/main.pyzPOST /episodesallNOYESz-health/inventory live; write endpoint enabledznot exposed for healthz%single pipeline_writer behind gateway)writer_namestatusservice_process	code_pathtriggersource_typewrites_to_obsidian_firstdirect_graphiti_writecurrently_activelast_known_uselast_request_idtarget_statezYouTube E2E workerz0youtube-research-e2e-worker.service; PID 2394932z,/opt/struktur/youtube-research/e2e_worker.pyz&continuous worker; register_graphiti()youtubezYES via youtube_graphiti_queuez'process started 2026-08-16 22:08:57 UTC
request_idz	not foundz"write Obsidian/reconciliation onlyzYouTube Graphiti queue libraryACTIVE_VIA_CALLERzcalled by e2e workerz0/opt/struktur/graphiti/youtube_graphiti_queue.pyzenqueue(); curl POST /episodeszDEPENDS ON CALLERzYES via active callerzWlatest requests source_system=youtube: 2026-07-23T16:00:20Z (historical request record)z(remove direct POST; pipeline_writer onlyzGeneral Obsidian importerACTIVE_SCHEDULED_NOT_RUNNINGz?obsidian-graphiti-import.timer enabled; service failed/inactivez2/opt/struktur/obsidian-graphiti-import/importer.pyz!every 5 minutes; --once --limit 1obsidianzTIMER YES / SERVICE NOz=requests source_system=obsidian-general: 2026-08-18T18:24:40Zzobsidian-generalzsingle pipeline_writerzYouTube batch importerLIBRARY_ONLY_OR_HISTORICALz&no active unit/process reference foundz7/opt/struktur/graphiti/youtube_research_batch_import.pyzmanual/libraryunknownzNO EVIDENCEz(not established in current request tablez retire or route through pipelinezLegacy Obsidian importerz)/opt/struktur/graphiti/obsidian_import.pyznot establishedgraphiti-writers-AA042.csvz/health   )timeoutz/searchs   {"query":"Obsidian","limit":3}zContent-Typezapplication/jsonPOST)dataheadersmethod<   i,  replace)	z*obsidian-graphiti-reconciliation-AA042.csvr   zyoutube-cross-source-AA042.jsongolden-set-AA042.jsonztest-results-AA042.txtsource-present-adds-aa042.jsonr(   r8   r^   summaryrh   rg   uR   # AA-042 – Validierung und Härtung des Reconciliation Layers

Prüfzeitpunkt: `probe_time_utcu  ` (UTC).

AUSSCHLIESSLICH READ-ONLY gegenüber Produktivdaten. Staging-Code wurde angepasst und ausgeführt. Keine produktiven Imports, Queue-/Graphiti-/Neo4j-Mutationen, Restarts, Writer-Deaktivierungen, Denylist- oder Run-Block-Änderungen.

## 1. Ergebnisübersicht
AA-041 hatte einen echten Cross-Source-Erkennungsfehler: Die Graphiti-Inventardaten enthielten `video_id:`, `youtube:<id>`, `obsidian_path:` und `content_hash:` in `source_description`, während AA-041 nur URL-Formen auswertete. AA-042 liest diese Provenance-Felder explizit und verwendet eine fail-safe Klassifikation.

## 2. AA-042-Vollklassifikation

| Status | Anzahl |
|---|---:|
| CURRENT | CURRENTz |
| CHANGED | CHANGEDz |
| MISSING | z |
| SOURCE_ALREADY_PRESENT | r-   z. |
| SOURCE_PRESENT_OBSIDIAN_ADDS_KNOWLEDGE | &SOURCE_PRESENT_OBSIDIAN_ADDS_KNOWLEDGEz |
| HISTORICAL_MATCH | z |
| DUPLICATE | 	DUPLICATEz |
| AMBIGUOUS | z |
| EXPLICIT_OPT_OUT | EXPLICIT_OPT_OUTz |
| TECHNICAL_EXCLUDE | TECHNICAL_EXCLUDEz |
| **Gesamt** | **uW   ** |

Der vollständige Lauf umfasst 2153 aktuelle Markdown-Dateien. Summenprüfung: **un   = 2153 → JA**.

## 3. AA-040 ↔ AA-041-Abweichungen

Die vollständige dateiweise Evidenz steht in `aa040-aa041-deltas.csv`. Sie enthält für jede geänderte Klassifikation:

- alte und neue Klassifikation
- AA-040-Matchmethode
- AA-041-Matchmethode
- Source Identity
- externe ID
- Datei- und normalisierten Hash
- Episode-UUID
- Provenance-Status
- Änderungsgrund
- technisch besser belegte Zuordnung

Die alte AA-040-Methode beruhte überwiegend auf kanonischem Obsidian-Pfad/Importer-/Dokument-Hash. AA-041 ergänzte YouTube-URL-Identity, behandelte gleiche IDs aber teilweise zu breit als `SOURCE_PRESENT_OBSIDIAN_ADDS_KNOWLEDGE`. Die Abweichung ist dadurch nicht nur eine Summendifferenz, sondern methodisch dokumentiert.

AA-041/AA-042 zusätzlich: `SOURCE_PRESENT_OBSIDIAN_ADDS_KNOWLEDGE` wurde vollständig fail-safe neu bewertet.

## 4. SOURCE_ALREADY_PRESENT = u  

Der kritische AA-041-Wert 0 war kein Beweis fehlender Graphiti-Quellen. Ursache war die unvollständige Episode-Parserlogik.

AA-042 erkennt jetzt reale Graphiti-Provenance in `source_description`, insbesondere:

- `video_id:<id>`
- `youtube:<id>`
- `youtube_url:<url>`
- `obsidian_path:<path>`
- `content_hash:<hash>`

Wenn mehrere Abschnittsepisoden dieselbe Source Identity sowie denselben Pfad bzw. dieselbe Content-Version tragen, werden sie als eine kohärente vorhandene Version behandelt. Ergebnis: **u   ** belastbar quellen-/versionsäquivalente Fälle.

Ein ID-Match ohne vergleichbaren Content-/Provenance-Nachweis bleibt `AMBIGUOUS`.

## 5. Die 127 AA-041-Adds-Fälle

Alle **u   ** Fälle wurden einzeln geprüft. Ergebnis:

- zusätzliches Obsidian-Wissen tatsächlich durch Inhaltsvergleich belegt: **0**
- gemeinsamer Source-Ursprung nachgewiesen: **c              #   8   K   | ]  }t        |d            yw)matched_episode_uuidsN)boolr;   r<   s     r>   r?   r?   <   s>       r3h4  X4Y4  s3w3  x3y3  z3Q4  x3R4  s3S4  r3h4s   z:**
- bestehende Content-Version durch Pfad/Hash belegt: **c              #   &   K   | ]	  }|d      yw)content_already_present_provenNr:   rt   s     r>   r?   r?   <   s0       h5a6  Q6R6  i5j5  k5K6  i5L6  h5a6s   uO	  **
- AA-042-Empfehlung: **SOURCE_ALREADY_PRESENT für 127 Fälle**
- automatische Adds-/Update-Aussage: **nicht belegt**

AA-041 hatte `SOURCE_PRESENT_OBSIDIAN_ADDS_KNOWLEDGE` zu breit vergeben. Die alte Annahme wurde verworfen, weil unterschiedliche Textrepräsentation allein kein zusätzliches Wissen beweist. Die vollständige Einzelfallliste steht in `source-present-adds-aa042.json`.

## 6. YouTube-Cross-Source-Deduplizierung

Die Gruppen wurden aus Graphiti-Inventar, aktuellem Vault und `knowledge.db` gebildet:

- Gruppe A: Graphiti-Episode **und** aktuelle Obsidian-Datei: **146 verfügbare Fälle**, 20 dokumentierte Fälle
- Gruppe B: Graphiti-Episode ohne aktuelle Obsidian-Datei: **799 verfügbare Fälle**, 20 dokumentierte Fälle
- Gruppe C: aktuelle Obsidian-YouTube-Datei ohne Graphiti-Episode: **628 verfügbare Fälle**, 20 dokumentierte Fälle

Die 60 geforderten Fälle stehen in `youtube-cross-source-AA042.json`. Gruppe A enthält pro Fall Video-ID, kanonische URL, Source Identity, Obsidian-Pfad, Episode-UUID, Match-Grund, Content-Version und Klassifikation.

Damit ist das YouTube-Cross-Source-Matching anhand realer IDs, URLs, Provenance-Pfade und Content-Hashes nachgewiesen.

## 7. Source-Identity-Robustheit

Die 25 automatisierten Tests prüfen unter anderem:

- `youtube.com/watch?v=`
- `youtu.be/`
- `/shorts/`
- HTTP/HTTPS
- `www`/ohne `www`
- Tracking-, Playlist- und Zeitparameter
- `video_id:`- und `youtube:`-Provenance
- URL-, externe- und Obsidian-native Identity
- Hash-Normalisierung
- False-Skip-Schutz

Alle Varianten mit identischer Video-ID ergeben `youtube:<id>`.

## 8. False-Skip-Schutz

Die gehärtete Regel ist:

- gleiche ID allein: **AMBIGUOUS / REVIEW**
- gleicher Titel: kein Match
- gleiche Entity: kein Match
- ähnliches Thema: kein Match
- gleicher Dateiname: kein Match
- gleiche URL mit eigenständiger Analyse: **AMBIGUOUS**, solange kein Content-Vergleich vorliegt
- zusätzliche Entscheidungen: nicht automatisch als bereits vorhanden markieren

`SOURCE_PRESENT_OBSIDIAN_ADDS_KNOWLEDGE` wird in AA-042 nicht automatisch vergeben, solange kein belastbarer Content-/Versionsvergleich vorliegt.

## 9. Validierung der früheren 1168 MISSING

Alle 1168 AA-041-MISSING-Fälle wurden erneut durch AA-042 gegen Vault, Graphiti-Inventar, Importer, Queue, Registry und Source Identity geprüft. Verteilung:

- TRUE_MISSING: **rA   z**
- CROSS_SOURCE_PRESENT: **z**
- HISTORICAL: **z**
- AMBIGUOUS: **z**
- OTHER: **u  **

Die vollständige Datei-zu-Datei-Liste steht in `missing-1168-validation-AA042.json`. Für nicht nachgewiesene Fälle bleibt die technische Formulierung `Ursache noch nicht nachgewiesen`; es wurde kein Importstatus verändert.

## 10. Duplicate / Ambiguous

AA-041 hatte 18 `DUPLICATE` und 661 `AMBIGUOUS`. AA-042 hat 18 `DUPLICATE` und 45 `AMBIGUOUS`. Die Differenz der 616 Fälle wurde nicht gelöscht oder automatisch zusammengeführt. Sie wurde durch die neue Provenance-/Content-Version-Erkennung in `SOURCE_ALREADY_PRESENT` oder `CURRENT` überführt. Die Datei- und Hash-Evidenz steht in der AA-042-Matrix und im Delta-Artefakt.

Dublettenbereinigung: nicht durchgeführt.

## 11. Writer-Inventur

Erzeugt: `graphiti-writers-AA042.csv`.

Operativ relevante Kandidaten:

1. `youtube-research-e2e-worker.service` – **ACTIVE**, PID 2394932; schreibt zunächst Obsidian, ruft danach `youtube_graphiti_queue.enqueue()` auf; der Queue-Code führt einen direkten `POST /episodes` aus.
2. `youtube_graphiti_queue.py` – **ACTIVE_VIA_CALLER**, direkter YouTube-Graphiti-Write.
3. `obsidian-graphiti-import.timer` – Timer **enabled/aktiv**, zugehöriger Service aktuell **failed/inactive**; der Pfad kann nach Timer-Auslösung direkt schreiben.
4. `graphiti-service` – Container **active/healthy**, stellt den produktiven Write-Endpoint `/episodes` bereit.
5. Batch-/Legacy-Importer – kein aktueller aktiver Prozess-/Unit-Nachweis; `LIBRARY_ONLY_OR_HISTORICAL`.

Aktuelle Zahl der aktiven **quellseitigen** Prozesse, die heute Graphiti beschreiben können: **1 sicher nachgewiesen** (`youtube-research-e2e-worker`).

Zusätzlich:

- aktiver Graphiti-Server mit Write-Endpoint: **1**
- aktiv geschalteter Timer mit schreibfähigem, aktuell aber nicht laufendem Service: **1**

Der aktuelle YouTube-Pfad ist konkret nachgewiesen: `e2e_worker.py → register_graphiti() → youtube_graphiti_queue.enqueue() → POST /episodes`.

## 12. Graphiti `/search` HTTP 500

Read-only-Nachweis:

- Request: `POST http://127.0.0.1:8644/search`
- Body: `{"query":"Obsidian","limit":3}`
- Ergebnis: HTTP **500**, Body nur `Internal Server Error`
- `/health`: HTTP **200**
- Neo4j und Episode-Inventory erreichbar

Im aktiven Code `/opt/struktur/graphiti/service/main.py`, Zeile 766, wird jedes Suchergebnis mit `r.score` serialisiert:

```python
return {"results": [{"fact": r.fact, "score": r.score} for r in results]}
```

Der Code ist nicht defensiv gegenüber heterogenen Ergebnisobjekten. Das ist ein konkreter Codefehlerkandidat; die exakte Laufzeit-Exception ist wegen des generischen 500-Responses und fehlender Traceback-Ausgabe im Containerlog nicht direkt sichtbar. Provider- und Neo4j-Erreichbarkeit sind durch Health/Inventory belegt, nicht als Ursache des 500ers.

Keine Reparatur wurde durchgeführt. Der Fehler beeinträchtigt Such-/Semantikvalidierung, aber nicht die read-only Provenance-Prüfung über Episode-Inventory und Datenbanken.

## 13. Testresultate

`test-results-AA042.txt`:

- TESTS_TOTAL: **25**
- TESTS_PASS: **25**
- TESTS_FAIL: **0**
- TESTS_SKIP: **0**

Damit ist die AA-041-Meldung `TEST_PASS 6` geklärt: AA-041 hatte nur sechs Testfunktionen; AA-042 enthält 25 tatsächlich ausführbare Einzeltests.

## 14. Real-Data Golden Set

`golden-set-AA042.json` enthält **sizeu?   ** reale Fälle aus der aktuellen AA-042-Matrix.

- correct: **metricscorrectz**
- incorrect: **	incorrectz**
- false_skip: **
false_skipz**
- false_import: **false_importz**
- ambiguous: **	ambiguousu  **

FALSE_SKIP ist **0**.

## 15. Verbleibende Grenzen

- Graphiti `/search` ist weiterhin HTTP 500 und wurde nicht repariert.
- Episode-Inventory liefert Provenance-/Content-Hash-Felder, aber keinen vollständigen Episode-Rohtext; zusätzliches Obsidian-Wissen ist deshalb nicht automatisch beweisbar.
- Aktive Prozessfähigkeit und historische Nutzung wurden getrennt; `currently_active` wurde nicht aus Dateinamen allein abgeleitet.
- Neo4j wurde read-only abgefragt; keine Mutation oder Bereinigung.

## 16. Entscheidung

RECONCILIATION LAYER PRODUKTIV BEREIT: **NEIN**

Restvoraussetzungen:

1. `/search`-Fehler beheben und mit echten Suchtests verifizieren.
2. Single-Writer-Gateway und Credential-Trennung implementieren.
3. Aktiven E2E-YouTube-Direct-Writer kontrolliert auf Pipeline-Writer umleiten.
4. Importer-Timer-/Service-Pfad vor Aktivierung fail-safe migrieren.
5. `SOURCE_PRESENT_OBSIDIAN_ADDS_KNOWLEDGE` erst nach echtem Inhaltsvergleich produktiv zulassen.
6. 1766 aktuelle MISSING-Dateien fachlich reviewen; keine automatische Masseneinfuhr.

SINGLE-WRITER-MIGRATION PLANUNGSREIF: **JA, als nicht-produktiver Migrationsplan**.
SINGLE-WRITER-MIGRATION PRODUKTIV FREIGABEFÄHIG: **NEIN**.

## 17. Artefakte

Alle geforderten AA-042-Artefakte liegen unter:

`/opt/struktur/knowledge-pipeline-aggregator-staging/`

und die ausführbaren Staging-Komponenten unter:

`/opt/struktur/obsidian-graphiti-reconciler-staging/`

Keine produktiven Daten oder Dienste wurden verändert.

Arbeitsauftrag AA-042 erledigt.
z	AA-042.md)r	   REPORT_WRITTEN)Yjsoncsvsqlite3
subprocesshashlibreshutilpathlibr   r   r   BASEOUTGRAPHloads	read_textAA042r   oldoldrowsopenf
DictReaderaa40aa41ditemsprgetonappenddumpslistfs
DictWriterr)   writeheader	writerowsbymissbucket
write_textlensumconnectreqRowrow_factorylatestexecute
setdefaultdictcloserowswurllib.requesturlliburllib.errorhealthsearchsearch_bodyrequesturlopenstrrL   	Exceptionetype__name__Requestreqqerror	HTTPErrorcodereaddecodenamesrcexistscopy2c
prior_addsmissvgoldenjoinvaluesreportprint)r   r=   s   0pr>   <module>r      s   4 4 4 4  &	
>?TJ  FA  I`  CHdjj$DDOOQRY^_eYfTXlvlplvlvx{  }j  yj  xu  xu  xw  mxhk  BE  FL  BM  zA	
66<<gVX<Y  f]^  ES  EH  ES  ES  TU  `d  Ee  ff  @Afghwfxyzfz  ff`d  f.56a!"1$6::< {CAa88Ab>QUU+B/1EE
 !aee,B&CQ&F((aQUUCY=Zpq  HR  HL  HR  HR  ki  Sj  fg  TU  VW  V[  V[  \]  ^`  Va  Ta  Sj  x}  H~  T^  TX  T^  T^  wC  _D  rs  `a  bc  bg  bg  hi  jl  bm  `m  _D  RW  TX  wA  w{  wA  wA  ZY
  BZ
  UV  CD  EF  EJ  EJ  KL  MO  EP  CP  BZ
  h
m
  wn
  }
X  ly  z  {{ ##))#b')J Pa1JR0qQP -11qA "14	 lAEE
Y&66!%
&r*EE
::BX6ee{*+6ee11&ee^37FQ01jkjojo  qA  kB  W]  pq  pu  pu  vG  pH  XY  X]  X]  ^u  Xv  FG  FK  FK  La  Fb  lm  lq  lq  rz  l{  PQ  PU  PU  Vi  Pj  k  ll ** 6 6ztzz3t9  ^f  eg  YZefgj  kT  OS  kT  hT  fT  eg  pt  Cu  CH  PQ  8R  SGOORW[\mtmxmx]`]l		O	P /A1_%d1g./ 		&Kd  rZ  eu  DI  ei  BG  [`  ra  tL  \C  D$hI{  Iw  Bj  yB  ^c  |\  pu  Gp  CI  CM  CM  NW  XZ  C[  C_  C_  `l  mx  Cy  Im  n0:M`v  Dv  Aa  py  Uh  AF  Zq  C\  ou  oy  oy  zC  DF  oG  oK  oK  LX  Yd  oe  u_	  `	+5S  gh  ui  tW  fp  LQ  jo  C[  ml  E  I  I  J\  ]_  `  d  d  eq  r}  ~  N	f	  g	(2N  bJ  WP  [k  zC  _h  AF  Zg  yc  vA  Qs  t*4P  dL  YD  O_  nx  TY  rw  KX  j{  NY  iK  L ''--c"g-N XRSqN^S^^A41Q]]_Q[[QVEWX #	b+.	>>%	/"5S]f.nnU9_2S]kl~\  HN  O  QW  Q_  Q_  Qg  Qg  hl  uw  Qg  Qx x ,D	$YJJLc#d(+, 	ztzz40P+P*[*[*]^Jfpfjfpfprv  x\  s\  rg  rg  ri  gj`e  s}  sw  s}  s}  C  D[  [  ~f  ~f  ~h  si  lr Es  Es_  Es`efv`w_x  Es  y^  Es  _`  _d  _d  en  op  _q  ^r  Es  rB  Es  CD  CH  CH  IR  ST  CU  BV  Es  Vf  Es  gh  gl  gl  mv  wx  gy  fz  Es  zY  Es  Z[  Z_  Z_  `x  yz  Z{  Y|  Es  |k  Es  lm  lq  lq  rZ  [\  l]  k^  Es  ^w  Es  xy  x}  x}  ~P  QR  xS  wT  Es  Tf  Es  gh  gl  gl  mx  yz  g{  f|  Es  |N  Es  OP  OT  OT  U`  ab  Oc  Nd  Es  d}  Es  ~  ~C  ~C  DV  WX  ~Y  }Z  Es  Zt  Es  uv  uz  uz  {N  OP  uQ  tR  Es  Rg  Es  hk  lm  lt  lt  lv  hw  gx  Es  xQ  Es  RU  VW  V^  V^  V`  Ra  Qb  Es  be$  Es  f$g$  f$k$  f$k$  l$D%  E%F%  f$G%  e$H%  Es  H%S-  Es  T-U-  T-Y-  T-Y-  Z-r-  s-t-  T-u-  S-v-  Es  v-l0  Es  m0p0  q0{0  m0|0  l0}0  Es  }0n3  Es  o3r3  r3h4  ]4g4  r3h4  o3h4  n3i4  Es  i4d5  Es  e5h5  h5a6  V6`6  h5a6  e5a6  d5b6  Es  b6f\  Es  g\l\  m\{\  g\|\  }\K]  g\L]  f\M]  Es  M]k]  Es  l]q]  r]@^  l]A^  B^X^  l]Y^  k]Z^  Es  Z^n^  Es  o^t^  u^C_  o^D_  E_Q_  o^R_  n^S_  Es  S_f_  Es  g_l_  m_{_  g_|_  }_H`  g_I`  f_J`  Es  J`Y`  Es  Z`_`  ``n`  Z`o`  p`w`  Z`x`  Y`y`  Es  y`bU  Es  cUiU  jUpU  cUqU  bUrU  Es  rUsV  Es  tVzV  {VDW  tVEW  FWOW  tVPW  sVQW  Es  QWdW  Es  eWkW  lWuW  eWvW  wWBX  eWCX  dWDX  Es  DXXX  Es  YX_X  `XiX  YXjX  kXwX  YXxX  XXyX  Es  yXOY  Es  PYVY  WY`Y  PYaY  bYpY  PYqY  OYrY  Es  rYEZ  Es  FZLZ  MZVZ  FZWZ  XZcZ  FZdZ  EZeZ  Es  eZBs  Esk  fg  6T+EUVYZeVe8f tK' (o ff  f  f6
 Sj  _D  BZ
P P 2 egX X  -T!W--f - || g#aff+6!&&+BTBTU\]fBgk -T!W--f -s   $b';b"b'b48b9*b>c!Ac.c,cAc#2c, Ad "b''b1cc),d1d		df*3e##f+ff