
    +PjT                     L   d Z ddlZddlZddlZddlZddlZej                  d   j                  d      Z	ej                  j                  dd      Zej                  j                  dd      Zej                  j                  d	d
      j                  d      Zej                  d   Zej                  j                  dd      Zej                  j                  dd      dk(  Zd$dZd%dZdZdZdZdZdZdZd Zd Zd Zd&dZd Zd&dZd Zd&d Z d&d!Z!d" Z"e#d#k(  r e"        yy)'u  Nightly reflection engine — the proactive brain (runs on a Railway cron).

Reads the shared memory graph over the memory API, asks DeepSeek V4 Pro to reason
over the whole thing — spotting OPPORTUNITIES (non-obvious money/growth moves),
OBSERVATIONS (patterns or risks Ahmed might miss), and NUDGES (open commitments
needing action) — and posts each finding back as an :Insight so any device can
surface it. No agent, no Claude Code: just DeepSeek + HTTP. Dependency-free.

On top of the insight pass it also, each night:
  - Pass 2: writes a tight current-state summary onto the top entities.
  - Pass 3: extracts Ahmed's open commitments into tasks.
  - Pass 4: consolidates near-duplicate memories (retires the stale copies).
  - Pass 5: writes a psychological "read" onto the top people/companies.
  - Pass 6: refines Ahmed's north-star value model.

Every generative pass is threaded with Ahmed's stated preferences/feedback so
the whole reflection aligns to what he's told Jarvis to do (or stop doing).

Env: MEMORY_API_URL, MEMORY_API_KEY, DEEPSEEK_API_KEY
     (optional) REFLECT_MODEL (default deepseek-v4-pro), MEMORY_GROUP,
     REFLECT_DRY=1 to print findings instead of storing them.
    NMEMORY_API_URL/MEMORY_API_KEY MEMORY_GROUPahmedDEEPSEEK_URLzhttps://api.deepseek.comDEEPSEEK_API_KEYREFLECT_MODELzdeepseek-v4-proREFLECT_DRY01c                    |#t        j                  |      j                         nd }t        j                  j                  t        |z   ||       }t        r|j                  ddt                |j                  dd       t        j                  j                  ||      5 }|j                         }|rt        j                  |      ni cd d d        S # 1 sw Y   y xY w)N)datamethodAuthorizationBearer Content-Typeapplication/jsontimeout)jsondumpsencodeurllibrequestRequestMEMMEM_KEY
add_headerurlopenreadloads)r   pathbodyr   r   reqrraws           reflection-service/reflect.pymemr*   &   s    (,(84::d""$dD
..
 
 t$v
 
FC''(;<NN>#56			W		5ffh"%tzz#2 
6	5	5s   #)CCc           	         t        j                  t        dd|d| dgd      j                         }t        j
                  j                  t        dz   |ddt         d	
      }t        j
                  j                  |d      5 }t        j                  |j                               }d d d        j                  d      xs i gd   j                  d      xs i j                  dd      j                         S # 1 sw Y   SxY w)Ng?Fuser)rolecontent)modeltemperaturestream
max_tokensmessagesz/chat/completionsr   r   )r   r   )r   headersi,  r   choicesr   messager.   r   )r   r   MODELr   r   r   r   DS_URLDS_KEYr!   r#   r"   getstrip)promptr2   r%   r&   r'   os         r)   deepseekr>   1   s    ::cU%/-3$G#HJ KKQ68 	 ..
 
 $$4!3$+F8"46 ! 7C 
		S		1QJJqvvx  
2UU9%"q)--i8>BCCIrRXXZZ 
2	1s   $C<<Du  You are Jarvis's reflection engine — a sharp chief-of-staff reasoning over everything Ahmed's assistant knows about his work and life. Below is his entire memory. Think hard and surface only GENUINELY valuable, non-obvious findings a great advisor would raise unprompted.

Produce up to 6 findings across three kinds:
- opportunity: a non-obvious move that could make money or advance a goal (a client/partner fit, an intro to make, an upsell, a reusable asset).
- observation: a pattern or risk he might miss (leads going cold, over-reliance on one client, a bottleneck, a contradiction).
- nudge: an open commitment or goal that needs action soon.

Be SPECIFIC — name the people, companies, and numbers. Skip anything obvious, generic, or low-value. Quality over quantity; 0 findings is fine if nothing is worth his attention.

Output ONLY a JSON array:
[{{"type":"opportunity|observation|nudge","title":"short label","detail":"1-2 specific sentences","entities":["names"]}}]

ENTITIES (by how often they come up):
{ents}

FACTS:
{facts}

JSON:u  You are Jarvis's memory summarizer. Below are all the facts the assistant knows about "{name}". Write a TIGHT current-state summary in 2-4 sentences: who or what they are, current status, key numbers, the latest development, and any open items. Plain prose only — no markdown, no bullet points, no preamble, no surrounding quotes. If the facts are thin, keep it to one honest sentence.

FACTS about {name}:
{facts}

SUMMARY:u[  You are Jarvis's chief-of-staff. Scan ALL of Ahmed's memory below and extract his OPEN, actionable COMMITMENTS — concrete things HE said he WILL DO, ideally with a deadline (e.g. "call Bloom Well by end of July", "send Al Temimi the proposal Thursday").

Be CONSERVATIVE: only real commitments he actually made and that are still open — NOT vague intentions, wishes, ideas, or things already done. If nothing qualifies, return [].

Output ONLY a JSON array, each item an imperative task:
[{{"text":"imperative task phrased as an action","due":"ISO datetime or empty string"}}]

FACTS:
{facts}

JSON:u  You are Jarvis's memory-consolidation engine. Below are Ahmed's memory facts, each on its own line as "id: text". Find GROUPS of facts that are near-duplicates — they say essentially the SAME thing (e.g. three separate "Ahmed is at home" facts, or two phrasings of the same single fact).

Only group GENUINE duplicates. Do NOT group facts that are merely related, on the same topic, sequential, or complementary — those must stay separate. When unsure, leave them out. Returning [] is fine.

Output ONLY a JSON array of groups; each group is an array of ids that duplicate each other:
[["id1","id2"], ["id7","id8","id9"]]

FACTS:
{facts}

JSON:u  You are Jarvis's read-the-room engine. Below are all the facts the assistant knows about "{name}". Produce a TIGHT psychological READ, in 2-4 sentences, that models THEM for Ahmed's benefit — not a summary of events but an assessment of the person/company: what they seem to WANT and VALUE, how they make decisions, the current temperature of Ahmed's relationship with them, and how Ahmed should APPROACH them next. Ground every claim in the facts and flag uncertainty ("seems", "likely") — do NOT invent traits or details that aren't there. If the facts are too thin to read them, say so honestly in one sentence. Plain prose only — no markdown, no bullet points, no preamble, no surrounding quotes.

FACTS about {name}:
{facts}

READ:u  You are Jarvis's model of Ahmed himself. From everything the assistant knows about him below, infer his NORTH STAR: his real priorities, what he chases, what he avoids or dislikes, and how he weighs tradeoffs (e.g. margin vs volume, growth vs quick cash, time vs money, risk vs safety, autonomy vs delegation).

Write a tight profile — 4 to 8 sentences or short lines of plain prose. No markdown, no bullet points, no preamble, no surrounding quotes. If a PRIOR PROFILE is given below, this is an UPDATE that REFINES it: keep what still holds, adjust only what the facts now contradict, and fold in what's genuinely new — do NOT wipe it and start fresh.
{prior}
FACTS about Ahmed:
{facts}

PROFILE:c            	          t        ddt        j                  j                  t        dd      z         j                  dg       } t        ddt        j                  j                  dt        i      z         }i }|j                  dg       D ]X  }t        |j                  d	d
            j                  d      s.|d   t        |d         j                  dd
      dd||d	   <   Z |j                  dg       D ]>  }|j                  d      dk(  s|j                  d      |v s,||d      dxx   dz  cc<   @ dj                  d | D              }dj                  d t        |j                         d       D              }||t        |       fS )NGET
/memories?  grouplimitmemories/graph?rD   nodesidr   ent:textkindzentity:r   )namerL   degedgestypementionstorN      
c              3   f   K   | ])  }d |d    |j                  d      r	d|d    dndz    + yw)- facttonez  [said ]r   N)r:   .0fs     r)   	<genexpr>z build_context.<locals>.<genexpr>   sA      A QvYKquuV}hqyk3"Ms   /1c              3   V   K   | ]!  }|d    dkD  rd|d    d|d    d|d     d # yw)	rN   r   rV   rM   z (rL   z, in z facts)N )r[   es     r)   r]   z build_context.<locals>.<genexpr>   sD      Q?A1U8a< QvYKr!F)E!E(7;?s   ')c                     | d    S NrN   r_   xs    r)   <lambda>zbuild_context.<locals>.<lambda>   s
    ahY    key)r*   r   parse	urlencodeGROUPr:   str
startswithreplacejoinsortedvalueslen)factsgraphentsnr`   	facts_txtents_txts          r)   build_contextry      sv   |fll&<&<#&'( ( )),Z)< 
y6<<#9#97E:J#KKLEDYYw#quuT2**62%&vY%(6^%;%;Ir%J$%'D4M $
 YYw#55=J&155;$+>4M% A%  $ 		  I yy Q+>?Q QH hE
**rf   c                 @   t        | xs d      j                         } | j                  d      r<t        j                  dd|       } t        j                  dd|       j                         } t        |       dk\  r%| d   dv r| d   | d   k(  r| d	d j                         } | S )
zLTrim a model reply down to plain prose (drop code fences / wrapping quotes).r   z```z^```[a-zA-Z]*\n?z\n?```$   r   z"'rS   )rl   r;   rm   resubrr   )ss    r)   _clean_textr      s    AGA||EFF&A.FF:r1%++-
1v{qtu}2!A$aGMMOHrf   c                      g } dD ]  }	 t        ddt        j                  j                  t        |dd      z         }|j                  dg       D ]?  }t        |j                  dd            j                         }|s/| j                  |       A  t               g }}| D ]9  }|j                         }||v r|j                  |       |j                  |       ; |syd	j                  d
 |D              }	d|	z   d	z   S # t        $ r Y w xY w)aB  Ahmed's stated preferences (kind=feedback + kind=preference) as a prompt block.

    Returns a short "RESPECT THESE" block to PREPEND onto every generative pass so
    the whole reflection aligns to what he's told Jarvis. Returns "" when he's
    stated none (a safe no-op to prepend anywhere). Computed once per run.
    )feedback
preferencer@   rA      )rD   rL   rE   rF   rW   r   rT   c              3   &   K   | ]	  }d |   ywrV   Nr_   )r[   ts     r)   r]   z!feedback_block.<locals>.<genexpr>   s     -11#h   uU   

AHMED'S STATED PREFERENCES — RESPECT THESE (things he's told you to do or stop):
)r*   r   ri   rj   rk   r:   rl   r;   append	Exceptionsetloweraddro   )
itemsrL   resmtxtseenuniqr   kliness
             r)   feedback_blockr      s    E*	e\FLL,B,B;-= = >CWWZ,!%%+,224LL% -	 + $DGGI9A  II---E "'(*./ 0  		s   A4D >D  	DDc           
          t        ddt        j                  j                  dt        i      z         }i }|j                  dg       D ]^  }t        |j                  dd            }|j                  d      s0t        |j                  dd            j                         d	d
||<   ` |j                  dg       D ]>  }|j                  d      dk(  s|j                  d      |v s,||d      dxx   dz  cc<   @ t        |j                         d       D cg c]  }|d   dk\  r|d   r| c}dd }d	}|D ]<  }|d   }	 t        ddt        j                  j                  |t        d      z         }	g }
|	j                  dg       D ]V  }|j                  dg       D ]?  }t        |j                  dd            j                         }|s/|
j                  |       A X |
sdj                  d |
D              }t        t        | t        j!                  ||      z   d             }t#        |      dk  rt$        rt'        d!| d"| d#$       |dz  }#t        d%d&||t        d'       |dz  }? |S c c}w # t(        $ r Y Sw xY w)(u   Pass 2 — write a current-state summary onto the top ~10 entities.

    Picks entity nodes by incoming `mentions` count (skip <2 facts), pulls each
    entity's full fact set, and upserts a DeepSeek summary via POST /summary.
    r@   rG   rD   rH   rI   r   rJ   rK   r   rM   rN   rO   rP   rQ   rR   rN   rS   c                     | d    S rb   r_   rc   s    r)   re   z pass_summaries.<locals>.<lambda>  
    1U8)rf   rg   r{   rM   N
   /entity?rM   rD   entitiesrs   rW   rT   c              3   &   K   | ]	  }d |   ywr   r_   r[   rd   s     r)   r]   z!pass_summaries.<locals>.<genexpr>       :	11#h	r   rM   rs   rB   r2   z  [summary] : TflushPOSTz/summaryrM   rK   rD   )r*   r   ri   rj   rk   r:   rl   rm   r;   rp   rq   r   ro   r   r>   SUMMARY_PROMPTformatrr   DRYprintr   )r   rt   ru   rv   nidr`   topdonerM   r   	ent_factsentr\   r   blocksummarys                   r)   pass_summariesr      s    y6<<#9#97E:J#KKLEDYYw#!%%b/">>&!!$QUU62%6!7!=!=!?JDI $ YYw#55=J&155;$+>4M% A%  $ T[[]0CD +Dh!m&	 D ++.B0CDy	eZ&,,*@*@.+0 0 1CIwwz2."-AaeeFB/0668C!((- . /
 II:	::E!(>00d%0HH#  !G 7|b TF"WI6dC	
w?AAID3 8 K?+:  		s2   I;B
J J &AJ <J J  	JJc                    | j                         j                         }|syt        j                  d|      D ch c]  }t	        |      dkD  s| }}|D ]  }t        |      j                         j                         }|s-||v s||v r yt        j                  d|      D ch c]  }t	        |      dkD  s| }}|sl|sot	        ||z        t        t	        |      t	        |            z  dk\  s y yc c}w c c}w )zTTrue if `text` is already represented in `existing` (list of lowercased task texts).Tz\w+   g333333?F)r   r;   r}   findallrr   rl   min)rK   existingr   wtwr`   ews          r)   	_dup_taskr   &  s    

AZZ*	9*c!fqj!*B	9FLLN  "6Q!VFA.=.A#a&1*a.="R"WCGSW(==D   
: >s   C:C:%C?9C?c           	      X   t        |t        j                  |       z         }t        j                  d|t        j
                        }	 |r$t        j                  |j                  d            ng }|D cg c]  }t        |t              s| }}	 t        ddt        j                  j                  dt         i      z         j#                  dg       }|D cg c].  }t        |t              st%        |j#                  dd	            0 }}d}	|D ]  }t%        |j#                  dd	            j'                         }
t%        |j#                  d
d	            j'                         }t)        |
      dk  st+        |
|      rpt,        r/t/        d|
 d|xs d dd       |j1                  |
       |	dz  }	|
t         d}|r||d
<   	 t        dd|       |j1                  |
       |	dz  }	 |	S # t        $ r g }Y w xY wc c}w # t        $ r g }Y ?w xY wc c}w # t        $ r Y w xY w)uM   Pass 3 — extract open commitments and create tasks (deduped vs open tasks).rs   \[.*\]r   r@   z/tasks?rD   tasksrK   r   due   z	  [goal] z (due none)Tr   rS   rK   rD   r   z/task)r>   GOALS_PROMPTr   r}   searchDOTALLr   r#   rD   r   
isinstancedictr*   r   ri   rj   rk   r:   rl   r;   rr   r   r   r   r   )rw   r   r(   r   goalsg
open_tasksr   r   createdrK   r   r%   s                r)   
pass_goalsr   8  s   
8l11	1BB
CC
		)S")),A*+

1771:& 51At!4QE5	FLL,B,Be- ! "s7B/ 	 1;R
1jD>QAEE&"%&
HRG155$%++-!%%r"#))+t9q=IdH5IdV6#-:$GOOD!qLGu-DK	&OOD!qLG! & N;  5  
R&  		sO   	(G. 5H H AH H.H#H.G=<G=HH	H)(H)c            	         t        ddt        j                  j                  t        dd      z         j                  dg       } | D cg c]6  }t        |t              r$|j                  d      |j                  d      r|8 } }t        |       d	k  ry
| D ci c]  }t        |d         | c}dj                  d | D              }t        t        j                  |            }t        j                  d|t        j                         }	 |r$t#        j$                  |j'                  d
            ng }d
}|D ]  }t        |t*              s|D cg c]  }t        |      v st        |       }	}t+        t        j-                  |	            }	t        |	      d	k  rg|	j/                  fd       |	d   |	dd }}
t0        r1t3        d|
 ddj                  |       d       |t        |      z  }|D ]"  }	 t        dd|   d   t        d       |dz  }$  |S c c}w c c}w # t(        $ r g }Y w xY wc c}w # t(        $ r Y Uw xY w)uL   Pass 4 — retire near-duplicate memories, keeping the newest of each group.r@   rA   rB   rC   rF   rI   NrW   r{   r   rT   c              3   6   K   | ]  }|d     d|d      yw)rI   r   rW   Nr_   rZ   s     r)   r]   z#pass_consolidate.<locals>.<genexpr>g  s$     A5a1T7)2ai[15s   r   r   c                 @    t        |    j                  dd            S )N
created_atr   )rl   r:   )iby_ids    r)   re   z"pass_consolidate.<locals>.<lambda>w  s    s58<<b#ABrf   rg   r|   z  [consolidate] keep z retire , Tr   r   z/retire)rI   rD   rS   )r*   r   ri   rj   rk   r:   r   r   rr   rl   ro   r>   CONSOLIDATE_PROMPTr   r}   r   r   r   r#   rD   r   listfromkeyssortr   r   )rs   r\   listingr(   r   groupsretiredgrprd   idskeepdropr   r   s                @r)   pass_consolidater   ^  s9   |fll&<&<#&'( ( )),Z)< 
 S11d#d(?AEE&M E S
5zA~&+,eS4\1_e,EiiA5AAG
%,,7,;
<C
		)S")),A+,AGGAJ'" G#t$"6s!c!fos1vs64==%&s8a<BCWc#2hd)$x		$7HIs4y GAFIeAhtnu'MN1  * NES -   7   s<   	;H#H((H- H?&H?>I-H<;H<	IIc           
         t        ddt        j                  j                  dt        i      z         }i }|j                  dg       D ]  }t        |j                  dd            }t        |j                  dd            }|j                  d      sK|j                  d	      s|j                  d
      snt        |j                  dd            j                         dd||<    |j                  dg       D ]>  }|j                  d      dk(  s|j                  d      |v s,||d      dxx   dz  cc<   @ t        |j                         d       D cg c]  }|d   dk\  r|d   r| c}dd }d}|D ]H  }|d   }		 t        ddt        j                  j                  |	t        d      z         }
g }|
j                  dg       D ]V  }|j                  dg       D ]?  }t        |j                  dd            j                         }|s/|j                  |       A X t        |      dk  rdj                  d  |D              }t        t        | t         j#                  |	|!      z   d"#            }t        |      d$k  rt$        rt'        d%|	 d&| d'(       |dz  }/t        d)d*|	|t        d+       |dz  }K |S c c}w # t(        $ r Y _w xY w),u  Pass 5 — write a psychological READ onto the top ~8 people/companies.

    Like pass_summaries, but scoped to entity nodes whose type is person or
    company, picked by incoming `mentions` count. For each it pulls the entity's
    facts and asks DeepSeek to model what they want/value and how Ahmed should
    approach them, then upserts via POST /read. Models THEM for Ahmed's benefit.
    r@   rG   rD   rH   rI   r   rL   rJ   zentity:personzentity:companyrK   r   r   rO   rP   rQ   rR   rN   rS   c                     | d    S rb   r_   rc   s    r)   re   zpass_reads.<locals>.<lambda>  r   rf   rg   r{   rM   N   r   r   r   rs   rW   rT   c              3   &   K   | ]	  }d |   ywr   r_   r   s     r)   r]   zpass_reads.<locals>.<genexpr>  r   r   r   i  r   r   z	  [read] r   Tr   r   z/readr   )r*   r   ri   rj   rk   r:   rl   rm   r;   rp   rq   r   rr   ro   r   r>   READS_PROMPTr   r   r   r   )r   rt   ru   rv   r   rL   r`   r   r   rM   r   r   r   r\   r   r   r"   s                    r)   
pass_readsr     s    y6<<#9#97E:J#KKLEDYYw#!%%b/"155$%>>&!0??#34!$QUU62%6!7!=!=!?JDI $ YYw#55=J&155;$+>4M% A%  $ T[[]0CD +Dh!m&	 D ++-A/CDy	eZ&,,*@*@.+0 0 1CIwwz2."-AaeeFB/0668C!((- . /
 9~!II:	::Ex<..D.FF   !D 4y2~	$r$0=	$u!MNAID1 6 K=+8  		s2   KB
K
#K
0AK
K
&K

	KKc           	         d}	 t        ddt        j                  j                  dt        i      z         }t        |j                  dd            j                         }|rd|z   dz   }t        t        |t        j                  ||       z   d	
            }t        |      dk  ryt        rt        d| d       y	 t        dd|t        d       y# t        $ r d}Y ww xY w# t        $ r Y yw xY w)u?  Pass 6 — infer/refine Ahmed's north-star value model (singleton /values).

    One DeepSeek call over all of Ahmed's facts + his existing /values text (if
    any) + his stated preferences. Refines the prior profile rather than wiping
    it, then upserts via POST /values. Returns True if a profile was written.
    r   r@   z/values?rD   rK   z-
PRIOR PROFILE (refine this, don't wipe it):
rT   )priorrs   i  r   r   Fz  [values] Tr   r   z/valuesr   )r*   r   ri   rj   rk   rl   r:   r;   r   r   r>   VALUES_PROMPTr   rr   r   r   )rw   r   r   cur	prior_txtrK   s         r)   pass_valuesr     s    E%fll&<&<gu=M&NNO+,224	F !#'(E x=''e9'EE D 4y2~
D6"$/FIu=>     s$   A%C >C$ C! C!$	C0/C0c                  .   t               \  } }}|dk(  rt        dd       y 	 t               }t	        |t
        j                  ||       z         }t        j                  d|t        j                        }	 |r$t        j                  |j                  d            ng }|D cg c]  }t        |t              s| }}d}|D ]  }t        |j!                  dd            j#                         }	t        |j!                  d	d            j#                         }
t        |j!                  d
d            j#                         j%                         }t'        |
      dk  r|	r|	 d|
 n|
}t(        rt        d| d| d       |dz  }t+        dd||	|t,        d      }|j!                  d      s|dz  } |}d}	 t/        |      }d}	 t1        | |      }d}	 t3               }d}	 t5        |      }d}	 t7        | |      }t        d| d| d| d|rdnd  d!| d"| d#t(        rd$ndz   d       y # t        $ r d}Y w xY w# t        $ r g }Y w xY wc c}w # t        $ r}t        d| d       Y d }~d }~ww xY w# t        $ r}t        d| d       Y d }~d }~ww xY w# t        $ r}t        d| d       Y d }~d }~ww xY w# t        $ r}t        d| d       Y d }~d }~ww xY w# t        $ r}t        d| d       Y d }~d }~ww xY w)%Nr   zreflection: no memories yetTr   r   )ru   rs   r   titledetailrP   observationr   u    — z  [z] rS   r   z/insight)rK   r   ityperD   r   z  [summary] pass failed: z  [goal] pass failed: z  [consolidate] pass failed: z  [read] pass failed: Fz  [values] pass failed: zreflection: z insights, z summaries, z reads, values yesnor   z goals, z retiredz (dry))ry   r   r   r   r>   PROMPTr   r}   r   r   r   r#   rD   r   r   rl   r:   r;   r   rr   r   r*   rk   r   r   r   r   r   )rw   rx   n_factsr   r(   r   findingsr\   r   r   r   r   rK   r'   
n_insightsn_summariesr`   n_goals	n_retiredn_reads	values_oks                        r)   mainr     sB   #0? Ix!|+48!#
 8fmmmKK
LC
		)S")),A-.4::aggaj)B $;8az!T':8H;GAEE'2&'--/QUU8R()//1AEE&-01779??Av;*/%fX&VCwb't4qLG
NP55qLG  J K;$X.
 G8Y1
 I?$&	
 G8X&
 I:	84	 
LK}LI_iUT$B"IXi[2 X"& .23A    ;.  ;)!-T::;  8&qc*$778  ?-aS1>>?  8&qc*$778  :(,D99:s   
H/ 6(I "I8I;I 	I> 
J$ %K
 3K0 /H>=H>II	I;!I66I;>	J!JJ!$	K-KK
	K-K((K-0	L9LL__main__)N<   )ip  )r   )$__doc__r   osr}   urllib.parser   urllib.requestenvironrstripr   r:   r   rk   r8   r9   r7   r   r*   r>   r   r   r   r   r   r   ry   r   r   r   r   r   r   r   r   r   __name__r_   rf   r)   <module>r
     s>  ,  	 	  jj!"))#.
**..)2
.


~w/	(B	C	J	J3	O	&	'


(9:jjnn]C(C/.
[
	:
	&	 &	"$+20@.b$#L&R2j>M3` zF rf   