+
    [WjO              	          R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t]P                  R,          P                  R4      t]P                  P                  RR4      t]P                  P                  RR4      t]P                  P                  RR	4      P                  R4      t]P                  R
,          t]P                  P                  RR4      t]P                  P                  RR4      R8H  t ]! ^]! ]P                  P                  RR4      4      4      tR>R ltR>R ltR?R ltR@R ltRtRtRtRtRt Rt!Rt"Rt#Rt$R t%R!t&R"t'R# t(R$ t)R% t*R& t+R' t,RAR( lt-RBR) lt.RCR* lt/R+ t0R, t1R?R- lt2R. t3R?R/ lt4R0 t5R?R1 lt6R?R2 lt7R3 t8R?R4 lt9R?R5 lt:RDR6 lt;R?R7 lt<R?R8 lt=R?R9 lt>R?R: lt?R; t@R< tA]BR=8X  d
   ]A! 4        R# R#   ] d    Rt Li ; i)Eu	  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 (ORDER matters):
  - 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.
  - Pass 7: entity hygiene — auto-dedup entities, adjudicate the ambiguous band,
            and flag mistyped "thing" entities (log-only, no retype endpoint).
  - Pass 8: pattern mining — recurring routines/cycles saved as kind="pattern".
  - Pass 9: synthesis — higher-level conclusions saved as kind="synthesis".
  - Pass 10: core block — refresh the pinned ~200-word profile (LAST, so it sees
             the night's cleanup) and POST /core.
  - Pass 11: archive sweep — retire stale, low-value, isolated observations/events.

The run is bracketed by a HEARTBEAT (POST /reflection_ran started → ok/error) so a
silent death is visible — this is why reflection quietly stopped before.

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).

Newer memory-service endpoints (added by a parallel effort) are called through
`mem_opt`, which logs-and-continues on a 404 so an un-deployed endpoint never
takes the whole run down: /reflection_ran, /core, /core_block,
/entities/dedup_backfill, /entities/merge. Memories may also now carry
importance / access_count / last_accessed / valid_from|to / refers_to — all read
defensively (they may be absent).

Env: MEMORY_API_URL, MEMORY_API_KEY, DEEPSEEK_API_KEY
     (optional) REFLECT_MODEL (default deepseek-v4-pro), MEMORY_GROUP,
     REFLECT_MAX_MEMORIES (context cap, default 800; paginated),
     REFLECT_DRY=1 to print findings instead of storing them (applies to EVERY
     pass, including the heartbeat and all the new passes).
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1REFLECT_MAX_MEMORIES800i   c                 
   Ve%   \         P                  ! V4      P                  4       MR p\        P                  P                  \        V,           W@R7      p\        '       d   VP                  RR\         24       VP                  RR4       \        P                  P                  WSR7      ;_uu_ 4       pVP                  4       pV'       d   \         P                  ! V4      M/ uuR R R 4       #   + '       g   i     R # ; i)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   &&&&    H/Users/ahmed/devFolder/Ultron/claude-voice/reflection-service/reflect.pymemr+   ?   s    (,(84::d""$dD
..
 
 t$
 
FCw''(;<NN>#56					5	5ffh"%tzz#2 
6	5	5	5s   60C11D	c           
         \        WW#4      #   \        P                  P                   d-   p\	        RT  RT RTP
                   R2RR7        Rp?R# Rp?i\         d#   p\	        RT  RT RT R2RR7        Rp?R# Rp?ii ; i)	u  Like mem() but NEVER raises — returns None (and logs) on any error.

For the newer endpoints a parallel effort is adding (/reflection_ran, /core,
/core_block, /entities/*). If one 404s because it isn't deployed yet we just
log and keep going so the rest of the reflection still runs.z  [mem]  z	 -> HTTP z (skipping)TflushNz	 failed: )r+   r   error	HTTPErrorprintcode	Exception)r   r%   r&   r   es   &&&& r*   mem_optr6   J   s    M6//<<!! R$yDDQQ   M$y;?tLLMs&    B!AB!B"A??Bc           
        \        T;'       g    R4      R,          p\        '       d   \        RV  RV 2RR7       R#  \        RR	R
V RVR\        /4       R#   \
         d   p\        RT  RT 2RR7        Rp?R# Rp?ii ; i)u   Stamp POST /reflection_ran so a silent death is visible on the dashboard.

NEVER raises — a failing heartbeat must not take the run down. Honours
REFLECT_DRY (prints instead of writing).r   :Ni  Nz  [heartbeat] : Tr.   NPOSTz/reflection_ranstatusnotegroupz post failed: )strDRYr2   r+   GROUPr4   )r:   r;   r5   s   && r*   	heartbeatr@   Y   s    
 tzzr?5!D
svhb/t<FF%vvtWe<	> FvhnQC8EEFs   A B#A<<Bc                 f   \         P                  ! R \        RRRRRVRRRR	V /./4      P                  4       p\        P
                  P                  \        R
,           VRRRR\         2/R7      p\        P
                  P                  VRR7      ;_uu_ 4       p\         P                  ! VP                  4       4      pRRR4       XP                  R4      ;'       g    / .^ ,          P                  R4      ;'       g    / P                  R	R4      P                  4       #   + '       g   i     Lj; i)modeltemperatureg?streamF
max_tokensmessagesroleusercontentz/chat/completionsr   r   r   r   )r   headersi,  r   Nchoicesmessager   )r   r   MODELr   r   r   r   DS_URLDS_KEYr"   r$   r#   getstrip)promptrE   r&   r'   r(   os   &&    r*   deepseekrT   i   s   ::w}c8U#Z!VVY$G#HJ KKQ68 	 ..
 
 $$4!3 GF8"46 ! 7C 
		S		1	1QJJqvvx  
2UU9%%"q)--i8>>BCCIrRXXZZ 
2	1s   %D  D0	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:u  You are Jarvis's entity-resolution judge. Each PAIR below is two memory entities the system suspects are the SAME real-world entity (person, company, place, or product), with a similarity score and each side's facts. For every pair decide: are they truly the SAME entity that should be MERGED, or DIFFERENT and kept apart?

Be CONSERVATIVE — only merge when you're confident they name the identical real thing. Two different people who share a first name, a company vs. its founder, or a brand vs. one of its products are DIFFERENT. When unsure, keep.

Output ONLY a JSON array, one verdict per pair (use "keep" only when merging — it says which side's name to keep):
[{{"pair":1,"verdict":"merge|keep","keep":"A|B"}}]

PAIRS:
{pairs}

JSON:a  You are Jarvis's entity-type auditor. Each entity below is currently typed as a generic "thing", but its facts may reveal it's really a PERSON, COMPANY, PLACE, or PRODUCT. For each, only if the facts CLEARLY indicate a more specific type, say so; otherwise leave it out.

Output ONLY a JSON array (include ONLY entities that should be retyped):
[{{"name":"...","suggested":"person|company|place|product"}}]

ENTITIES:
{ents}

JSON:uJ  You are Jarvis's pattern miner. Below are Ahmed's memories, each as `id [date | re EVENTDATE]: text` — `date` is when it was recorded, `re EVENTDATE` (when present) is the real-world date it refers to. Mine RECURRING patterns: routines, cycles, and behaviours that REPEAT across time, each backed by specific evidence memories.

Good patterns: "Ahmed ships a feature then immediately starts the next with no break", "the scraper wedges roughly every N days", "Ahmed reworks Jarvis's voice stack every couple of weeks". Only report a pattern supported by at least TWO memories; cite their ids. Skip one-offs. Do NOT repeat anything in ALREADY-KNOWN.

Output ONLY a JSON array (MAX 5):
[{{"text":"Ahmed does X every Y (N times since DATE)","evidence":["id1","id2"]}}]

ALREADY-KNOWN PATTERNS (do NOT repeat):
{known}

MEMORIES:
{facts}

JSON:u#  You are Jarvis's synthesizer. Read Ahmed's recent memories below (each `id: text`) and infer 3-5 HIGHER-LEVEL CONCLUSIONS that logically FOLLOW from them but are NOT directly stated in any single memory — the connect-the-dots read a sharp analyst would draw. Each conclusion must be grounded in specific memories; cite their ids. Skip the obvious and anything in ALREADY-KNOWN.

Output ONLY a JSON array (MAX 5):
[{{"text":"the higher-level conclusion","sources":["id1","id2"]}}]

ALREADY-KNOWN (do NOT repeat):
{known}

MEMORIES:
{facts}

JSON:u   You are Jarvis's profile writer. Write a PINNED CORE PROFILE of Ahmed that is injected into EVERY Jarvis prompt — so it must be DENSE, CURRENT, and 200 WORDS MAX. Cover, in tight prose: who Ahmed is; each ACTIVE project with a one-line current state; the key people and companies and their role to him; his current priorities; and his standing preferences.

CRITICAL: include NOTHING stale or superseded. If a newer fact overrides an older one, keep ONLY the newer. Drop anything finished, abandoned, or out of date. No markdown, no bullet symbols, no preamble, no surrounding quotes — just prose (short lines are fine). HARD LIMIT 200 words.

{prior}ENTITY SUMMARIES (current state, refreshed tonight):
{summaries}

HIGH-SIGNAL FACTS (importance / recency / usage ranked):
{facts}

CORE PROFILE:av  You are Jarvis's memory archiver. Each CLUSTER below is a group of old, low-value memories about to be retired. For each, write ONE short factual sentence that preserves the durable gist so nothing important is lost. Plain prose, no markdown, no preamble.

Output ONLY a JSON array:
[{{"cluster":1,"text":"one-sentence summary of the cluster"}}]

CLUSTERS:
{clusters}

JSON:c                   . ^ r!\        V4      V 8  d   \        ^V \        V4      ,
          4      p\        RR\        P                  P                  R\        RVRV/4      ,           4      pT;'       g    / P                  R. 4       Uu. uF  p\        V\        4      '       g   K  VNK  	  ppV'       g   M6VP                  V4       \        V4      V8  d   MV\        V4      ,          pK  VRV  # u upi )u   Page through /memories up to `cap` (the service caps each page at ~200, so
a single request can't honour a big cap — we page by offset). Newest-first.GET
/memories?r<   limitoffsetmemoriesN)lenminr+   r   parse	urlencoder?   rP   
isinstancedictextend)capoutrY   wantresfbatchs   &      r*   _fetch_memoriesrh   W  s     a
c(S.3c#h'%(>(>eWdHf=)? ? @ YYBOOJ;S;qz!T?R;S

5u:#e*t9 Ts   C1%C1c            
         \        \        4      p \        V 4      \        8  d   \        V \        R R7      R\         p \        RR\        P                  P                  R\        /4      ,           4      p/ pVP                  R. 4       F  p\        VP                  RR4      4      P                  R	4      '       g   K5  R
VP                  RR4      R\        VP                  RR4      4      P                  RR4      R^ /W#R,          &   K  	  VP                  R. 4       FU  pVP                  R4      R8X  g   K  VP                  R4      V9   g   K3  W$R,          ,          R;;,          ^,          uu&   KW  	  RP                  R V  4       4      pRP                  R \        VP                  4       R R7       4       4      pWVW3# )TkeyreverseNrV   /graph?r<   nodesidr   ent:nametextkindzentity:degedgestypementionsto
c              3      "   T FE  pR VP                  RR4       2VP                  R4      '       d   RVR,           R2MR,           x  KG  	  R# 5i)- factr   tonez  [said ]N)rP   .0rf   s   & r*   	<genexpr> build_context.<locals>.<genexpr>}  sN      A QUU62 quuV}}hqyk$;RTUUs
   /AAc              3      "   T F5  qR ,          ^ 8  g   K  RVR,           RVR,           RVR ,           R2x  K7  	  R# 5i)rt   r{   rq    (rs   z, in z facts)N r   r5   s   & r*   r   r     sC      Q?AU8a< 	<"QvYKr!F)E!E(7;?s   ?)?c                     V R ,          ) # rt   r   xs   &r*   <lambda>build_context.<locals>.<lambda>  s
    ahY    rk   )rh   MAX_MEMORIESr[   sorted	_mem_rankr+   r   r]   r^   r?   rP   r=   
startswithreplacejoinvalues)factsgraphentsnr5   	facts_txtents_txts          r*   build_contextr   i  sv   L)E 5zL u)T:=LIy6<<#9#97E:J#KKLEDYYw#quuT2**622#QUU62%6#Svr):%;%C%CIr%R"A'D4M $
 YYw#55=J&155;$+>4M% A%  $ 		  I yy Q+>?Q QH ,,r   c                6   V P                  R4      p\        V\        \        34      '       d   \        V4      MRpV P                  R4      p\        V\        \        34      '       d   \        V4      MRpY\	        V P                  R4      ;'       g    R4      3# )u  Sort key (use reverse=True) preferring high-importance, then frequently-
accessed, then recent. All three fields are OPTIONAL (a parallel effort is
adding them; /memories doesn't return them yet) so they default safely — until
then this degrades gracefully to recency order.
importanceg      @access_countg        
created_atr   )rP   r_   intfloatr=   )mimpacs   &  r*   r   r     sw    
 %%
C"3e55%*3C	
~	B c5\22rBS|,22344r   c                     \         P                  P                  \        T ;'       g    R4      R,          4      #   \         d     R# i ; i)zAFirst-10-chars ISO date -> datetime.date, or None if unparseable.r   N
   NN)_dtdatefromisoformatr=   
ValueErrorss   &r*   _parse_dater     s=    xx%%c!''rl3&788 s   &; ; A
	A
c                .   \         P                  ! R\        T ;'       g    R4      \         P                  4      pV'       g   . #  \        P
                  ! VP                  ^ 4      4      p\        V\        4      '       d   V# . #   \         d    . u # i ; i)zBPull the first JSON array out of a model reply; [] on any failure.\[.*\]r   )
researchr=   DOTALLr   r$   r<   r_   listr4   )r)   r   vals   &  r*   _json_arrayr     sp    
		)S^RYY7A	jj$ d++s33 	s   <B B BBc                   . pV RV  F  pVP                  R4      \        VP                  RR4      4      P                  4       rTVe	   V'       g   KJ  \        VP                  R4      ;'       g    R4      R,          p\        VP                  R4      ;'       g    R4      P                  4       R,          pV'       d   VRV 2,          pVP                  V R	V R
V 24       K  	  RP	                  V4      # )um   `id [date | re EVENTDATE]: text` lines — timestamps in, for the pattern
miner. Capped to bound token spend.Nro   r|   r   r   r   	refers_toz | re z [z]: ry   rP   r=   rQ   appendr   )r   rb   linesrf   fidtxtstampreferss   &&      r*   _ts_listingr     s     E4C[55;AEE&"$5 6 < < >S;cAEE,'--2.s3QUU;'--2.446s;vfX&&EuBugS./  99Ur   c                    . pV RV  Fb  pVP                  R4      \        VP                  RR4      4      P                  4       rTVf   KB  V'       g   KL  VP                  V RV 24       Kd  	  RP	                  V4      # )z=`id: text` lines (newest-first slice) for the synthesis pass.Nro   r|   r   r8   ry   r   )r   rb   r   rf   r   r   s   &&    r*   _id_listingr     so    E4C[55;AEE&"$5 6 < < >S?ssLLC53%)  99Ur   c           
        V '       g   . #  \        RR\        P                  P                  RV R\        /4      ,           4      p. pT;'       g    / P                  R. 4       F`  pTP                  R. 4       FG  p\        TP                  RR4      4      P                  4       pT'       g   K6  TP                  T4       KI  	  Kb  	  TR	T #   \
         d    . u # i ; i)
zJUp to `cap` fact texts for an entity by name (memory API only, no tokens).rV   /entity?rq   r<   entitiesr   r|   r   N)
r+   r   r]   r^   r?   r4   rP   r=   rQ   r   )rq   rb   re   rc   entrf   ts   &&     r*   _entity_factsr     s    	%fll&<&<T7E*', , - C		rz2."%AAEE&"%&,,.Aq

1 & /
 t9  	s   8C CCc                   \        T ;'       g    R4      P                  4       p V P                  R4      '       d?   \        P                  ! RRV 4      p \        P                  ! RRV 4      P                  4       p \        V 4      ^8  d7   V ^ ,          R9   d)   V R,          V ^ ,          8X  d   V ^R P                  4       p V # )zLTrim a model reply down to plain prose (drop code fences / wrapping quotes).r   z```z^```[a-zA-Z]*\n?z\n?```$z"')r=   rQ   r   r   subr[   r   s   &r*   _clean_textr     s    AGGA||EFF&A.FF:r1%++-
1v{qtu}2!A$aGMMOHr   c                 n   . p R F  p \        RR\        P                  P                  R\        RVR^/4      ,           4      pVP                  R. 4       FG  p\        VP                  RR4      4      P                  4       pV'       g   K6  V P                  V4       KI  	  K  	  \        4       . reV  F=  pVP                  4       pW9   d   K  VP                  V4       VP                  V4       K?  	  V'       g   R# R	P                  R
 V 4       4      p	RV	,           R	,           #   \         d     EK.  i ; i)a2  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.
rV   rW   r<   rs   rX   rZ   r|   r   ry   c              3   ,   "   T F
  pR V 2x  K  	  R# 5ir{   Nr   r   r   s   & r*   r   !feedback_block.<locals>.<genexpr>  s     -11#h   uU   

AHMED'S STATED PREFERENCES — RESPECT THESE (things he's told you to do or stop):
)feedback
preference)r+   r   r]   r^   r?   rP   r=   rQ   r   r4   setloweraddr   )
itemsrs   re   r   r   seenuniqr   kr   s
             r*   feedback_blockr     s    E*	e\FLL,B,B%w;-= = >CWWZ,!%%+,2243LL% -	 + $GGI9A  II---E "'(*./ 0  		s   A=D$D$$D43D4c                h	   \        RR\        P                  P                  R\        /4      ,           4      p\        4       p \        P                  P                  \        P                  P                  4      \        P                  ! ^0R7      ,
          P                  4       p\        RR\        P                  P                  R\        R^/4      ,           4      P                  R. 4       FO  p\        VP                  RR	4      4      V8  g   K%  VP                  \        VP                  R
R	4      4      4       KQ  	  / pVP                  R. 4       Fh  p\        VP                  R
R	4      4      pVP%                  R4      '       g   K7  R\        VP                  RR	4      4      P'                  4       R^ RR/Wh&   Kj  	  VP                  R. 4       F  pVP                  R4      R8X  g   K  VP                  R4      V9   g   K3  WeR,          ,          R;;,          ^,          uu&   \        VP                  RR	4      4      V9   g   Kw  RWeR,          ,          R&   K  	  \)        VP+                  4       R R7      p	V	 Uu. uF%  qUR,          ^8  g   K  VR,          '       g   K#  VNK'  	  upR,          p
\-        R V
 4       4      p\#        R V R!\/        V
4      V,
           R"2RR7       ^ pV
 EFp  pVR,          p \        RR#\        P                  P                  RVR\        /4      ,           4      p. pVP                  R$. 4       F`  pVP                  R%. 4       FG  p\        VP                  R&R	4      4      P'                  4       pV'       g   K6  VP1                  V4       KI  	  Kb  	  V'       g   K  R'P3                  R( V 4       4      p\5        \7        V \8        P;                  VVR)7      ,           R*R+7      4      p\/        V4      ^
8  d   EK%  \<        '       d    \#        R,V R-V 2RR7       V^,          pEKP  \        R.R/RVRVR\        /4       V^,          pEKs  	  V#   \          d,   p\#        R\        T4      R,           2RR7        Rp?ELVRp?ii ; iu upi   \          d     EK  i ; i)0u  Pass 2 — write a current-state summary onto the entities that NEED one.

TOUCHED-FIRST selection (freshness scales with daily activity, not with
total graph size): every entity mentioned by a fact from the last 48h is
summarized first — a client signed today gets a fresh summary TONIGHT even
if some old heavyweight out-mentions it — then remaining slots fill by
all-time mention count. Skip <2 facts; upserts via POST /summary.rV   rm   r<   )hoursrW   rX   rZ   r   r   ro   z*  [summaries] recent-window fetch failed: :NP   NTr.   Nrn   rp   rq   rr   rt   touchedFru   rv   rw   rx   fromc                 <    \        V R ,          4      ) V R,          ) 3# )r   rt   )r   r   s   &r*   r    pass_summaries.<locals>.<lambda>  s    C)$5#5%y"Ar   r   :N   Nc              3   F   "   T F  qR ,          '       g   K  ^x  K  	  R# 5i)r   Nr   r   s   & r*   r   !pass_summaries.<locals>.<genexpr>   s     1SiLL!!Ss   !
!z  [summaries] z touched-recently + z top-degree selectedr   r   r   r|   ry   c              3   ,   "   T F
  pR V 2x  K  	  R# 5ir   r   r   r   s   & r*   r   r   1       :	11#h	r   rq   r   	  rE   z  [summary] r8   r9   z/summary)r+   r   r]   r^   r?   r   r   datetimenowtimezoneutc	timedelta	isoformatrP   r=   r   r4   r2   r   rQ   r   r   sumr[   r   r   r   rT   SUMMARY_PROMPTformatr>   )r   r   
recent_idscutoffr   r5   r   r   nidrankedtopn_touchdonerq   re   	ent_factsr   rf   r   blocksummarys   &                    r*   pass_summariesr    s    y6<<#9#97E:J#KKLEJ	,,""3<<#3#34MM+,-6Y[ 	UL6<<+A+A%#.,0 0 114Z1DEA155r*+v5s155r?34E DYYw#!%%b/">>&!!QUU62%6!7!=!=!?9e5DI $
 YYw#55=J&155;$+>4M% A% 155$%3+/tWi(	 $
 DKKMACF
<f%A1!F))11f
<S
AC1S11G	N7)#7X  46=ACDy	eZ&,,*@*@w.+0 0 1CIwwz2."-AaeeFB/0668Cs!((- . /
 II:	::E!(>00d%0HH#! "G 7|b sTF"WI6dC	
vw?AAID3 8 Kc  :3q6#;-H	 	  =>  		sc   C	Q# .Q# =RR"R:BR! R!4AR!R!R!< R!#R. RR!R10R1c                |   V P                  4       P                  4       pV'       g   R# \        P                  ! RV4       Uu0 uF  p\	        V4      ^8  g   K  VkK  	  ppV F  p\        V4      P                  4       P                  4       pV'       g   K4  W%9   g   WR9   d    R# \        P                  ! RV4       Uu0 uF  p\	        V4      ^8  g   K  VkK  	  ppV'       g   K  V'       g   K  \	        WF,          4      \        \	        V4      \	        V4      4      ,          R8  g   K   R# 	  R# u upi u upi )zTTrue if `text` is already represented in `existing` (list of lowercased task texts).Tz\w+g333333?F)r   rQ   r   findallr[   r=   r\   )rr   existingr   wtwr5   ews   &&     r*   	_dup_taskr  C  s    

AZZ*	9*c!fqj!!*B	9FLLN  "6QVFA.=.A#a&1*aa.=2""RWCGSW(==D   
: >s   D4D4?D9D9c           	        \        V\        P                  V R7      ,           4      p\        P                  ! RV\        P
                  4      p V'       d&   \        P                  ! VP                  ^ 4      4      M. pV Uu. uF  p\        V\        4      '       g   K  VNK  	  pp \        RR\        P                  P                  R\         /4      ,           4      P#                  R. 4      pV Uu. uF6  p\        V\        4      '       g   K  \%        VP#                  RR4      4      NK8  	  pp^ p	V F  p\%        VP#                  RR4      4      P'                  4       p
\%        VP#                  R	R4      4      P'                  4       p\)        V
4      ^8  g   \+        W4      '       d   Kx  \,        '       d;   \/        R
T
 RT;'       g    R R2RR7       VP1                  V
4       V	^,          p	K  RV
R\         /pV'       d   WR	&    \        RRV4       VP1                  V
4       V	^,          p	K  	  V	#   \         d    . p ELi ; iu upi   \         d    . p ELqi ; iu upi   \         d     EKC  i ; i)uM   Pass 3 — extract open commitments and create tasks (deduped vs open tasks).r   r   rV   z/tasks?r<   tasksrr   r   duez	  [goal] z (due none)Tr.   r9   z/task)rT   GOALS_PROMPTr   r   r   r   r   r$   r<   r4   r_   r`   r+   r   r]   r^   r?   rP   r=   rQ   r[   r  r>   r2   r   )r   r   r)   r   goalsg
open_tasksr   r  createdrr   r  r&   s   &&           r*   
pass_goalsr  U  s   
8l11	1BB
CC
		)S")),A*+

1771:& 51At!4QQE5	FLL,B,Be- ! "s7B/ 	 1;R
1jD>Q&AEE&"%&
HRG155$%++-!%%r"#))+t9q=Id553IdV6#--:$GOOD!qLGgu-K	&OOD!qLG! & N;  5  
R&  		sO   /H5 I	I	'AI 1I"I"'I'5IIII'I76I7c           
       a V  Uu. uFK  p\        V\        4      '       g   K  VP                  R4      f   K0  VP                  R4      '       g   KI  VNKM  	  p p\        V 4      ^8  d   ^ # V  Uu/ uF  p\	        VR,          4      VbK  	  upoRP                  R V  4       4      p\        \        P                  VR7      4      p\        P                  ! RV\        P                  4      p V'       d&   \        P                  ! VP                  ^ 4      4      M. p^ pV EF  p\        V\         4      '       g   K  V Uu. uF   p\	        V4      S9   g   K  \	        V4      NK"  	  p	p\!        \        P#                  V	4      4      p	\        V	4      ^8  d   Kx  V	P%                  V3R lR	7       V	R,          V	RR r\&        '       d7   \)        R
V
 RRP                  V4       2RR7       V\        V4      ,          pK  V F0  p \+        RRRSV,          R,          R\,        /4       V^,          pK2  	  EK  	  V# u upi u upi   \         d    . p EL8i ; iu upi   \         d     Kl  i ; i)u   Pass 4 — retire near-duplicate memories, keeping the newest of each group.

Reuses the corpus build_context already fetched (no extra memory read).ro   Nr|   ry   c              3   J   "   T F  qR ,           RVR,           2x  K  	  R# 5i)ro   r8   r|   Nr   r   s   & r*   r   #pass_consolidate.<locals>.<genexpr>  s!     A5aT7)2ai[15s   !#r
  r   c                 H   < \        SV ,          P                  R R4      4      # )r   r   )r=   rP   )iby_ids   &r*   r   "pass_consolidate.<locals>.<lambda>  s    s58<<b#ABr   r   z  [consolidate] keep z retire , Tr.   r9   /retirer<   r   )r_   r`   rP   r[   r=   r   rT   CONSOLIDATE_PROMPTr   r   r   r   r   r$   r<   r4   r   fromkeyssortr>   r2   r+   r?   )r   rf   listingr)   r   groupsretiredgrpr   idskeepdropr  r  s   &            @r*   pass_consolidater(  {  s     S11d# ()d DEEE&M QE S
5zA~&+,eS4\1_e,EiiA5AAG
%,,7,;
<C
		)S")),A+,AGGAJ'" G#t$$"6s!c!fovs1vs64==%&s8a<BCWc#2hd3)$x		$7HIs4y GAFIeAhtngu'MN1  * NES -   7   sK   H9H9H9H9/H>,/I ?II,IIII+*I+c                   \        RR\        P                  P                  R\        /4      ,           4      p/ pVP                  R. 4       F  p\        VP                  RR4      4      p\        VP                  RR4      4      pVP                  R4      '       g   KR  VP                  R	4      '       g   VP                  R
4      '       g   K  R\        VP                  RR4      4      P                  4       R^ /W$&   K  	  VP                  R. 4       FU  pVP                  R4      R8X  g   K  VP                  R4      V9   g   K3  W&R,          ,          R;;,          ^,          uu&   KW  	  \        VP                  4       R R7       Uu. uF&  pVR,          ^8  g   K  VR,          '       g   K$  VNK(  	  upR,          p^ pV EFw  pVR,          p	 \        RR\        P                  P                  RV	R\        /4      ,           4      p
. pV
P                  R. 4       F`  pVP                  R. 4       FG  p\        VP                  RR4      4      P                  4       pV'       g   K6  VP                  V4       KI  	  Kb  	  \        V4      ^8  d   K  RP                  R V 4       4      p\        \        V \         P#                  WR7      ,           RR7      4      p\        V4      ^
8  d   EK,  \$        '       d    \'        RV	 RV 2R R!7       V^,          pEKW  \        R"R#RV	RVR\        /4       V^,          pEKz  	  V# u upi   \(         d     EK  i ; i)$uv  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.
rV   rm   r<   rn   ro   r   rs   rp   zentity:personzentity:companyrq   rr   rt   ru   rv   rw   rx   c                     V R ,          ) # r   r   r   s   &r*   r   pass_reads.<locals>.<lambda>  s
    1U8)r   r   :N   Nr   r   r   r|   ry   c              3   ,   "   T F
  pR V 2x  K  	  R# 5ir   r   r   s   & r*   r   pass_reads.<locals>.<genexpr>  r   r   r   i  r   z	  [read] r8   Tr.   r9   z/read)r+   r   r]   r^   r?   rP   r=   r   rQ   r   r   r   r[   r   r   rT   READS_PROMPTr   r>   r2   r4   )r   r   r   r   r   rs   r5   r   r   rq   re   r   r   rf   r   r   r#   s   &                r*   
pass_readsr0    s    y6<<#9#97E:J#KKLEDYYw#!%%b/"155$%>>&!!00??#344QUU62%6!7!=!=!?JDI $ YYw#55=J&155;$+>4M% A%  $ T[[]0CD +Dh!m  !&		 1D ++-/CDy	eZ&,,*@*@w.+0 0 1CIwwz2."-AaeeFB/0668Cs!((- . /
 9~!II:	::Ex<..D.FF   !D 4y2~s	$r$0=	&$gu!MNAID1 6 K=+8  		sD   	MM/MBM()MAM/M;M MMMc           
     2   Rp \        RR\        P                  P                  R\        /4      ,           4      p\        VP                  RR4      4      P                  4       pV'       d   RV,           R,           p\        \        T\        P                  Y R7      ,           R	R
7      4      p\        T4      ^
8  d   R# \        '       d   \        RT 2RR7       R#  \        RRRTR\        /4       R#   \         d    Rp Li ; i  \         d     R# i ; i)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   rV   z/values?r<   rr   z-
PRIOR PROFILE (refine this, don't wipe it):
ry   )priorr   i  r   Fz  [values] Tr.   r9   z/values)r+   r   r]   r^   r?   r=   rP   rQ   r4   r   rT   VALUES_PROMPTr   r[   r>   r2   )r   r   r2  cur	prior_txtrr   s   &&    r*   pass_valuesr6    s    E%fll&<&<gu=M&NNO+,224	F !#'(E x=''e'EE D 4y2~
sD6"$/FIgu=>     s$   A7C4 D 4DDDDc                   \        V \        4      '       g   R# \        V P                  R4      \        4      '       d   V P                  R4      M/ p\        V P                  R4      \        4      '       d   V P                  R4      M/ pV P                  R4      ;'       gv    V P                  R4      ;'       g]    V P                  R4      ;'       gD    VP                  R4      ;'       g+    VP                  R4      ;'       g    VP                  R	4      pV P                  R
4      ;'       gv    V P                  R4      ;'       g]    V P                  R4      ;'       gD    VP                  R4      ;'       g+    VP                  R4      ;'       g    VP                  R	4      pV'       d	   V'       g   R# V P                  R4      ;'       gN    V P                  R4      ;'       g5    VP                  R	4      ;'       g    VP                  R4      ;'       g    TpV P                  R4      ;'       gN    V P                  R4      ;'       g5    VP                  R	4      ;'       g    VP                  R4      ;'       g    TpV P                  R4      ;'       g5    V P                  R4      ;'       g    V P                  R4      ;'       g    ^ p\        V4      \        V4      \        V4      \        V4      V3# )zBest-effort extraction of (key_a, name_a, key_b, name_b, score) from an
ambiguous-pair record whose exact shape the parallel service owns. Tolerates
both flat (*_key) and nested (a/b objects) layouts; None if unusable.Naba_keykey_akeep_keyrk   ro   rq   b_keykey_b	merge_keya_namename_arr   b_namename_bscore
similaritysim)r_   r`   rP   r=   )pr8  r9  r;  r>  rA  rC  rD  s   &       r*   _pair_fieldsrH    s]    a sT22c
A sT22c
AUU7^ = =quuW~ = =z1B = =e= = !d= =/0uuV} 
UU7^ = =quuW~ = ={1C = =e= = !d= =/0uuV} 
eeHo ( (x ( (AEE&M ( (v( ("' eeHo ( (x ( (AEE&M ( (v( ("' EE'NFFaeeL1FFQUU5\FFQEJFSZVeDDr   c                8   \        RR\        P                  P                  R\        /4      ,           4      p/ pVP                  R. 4       F  p\        VP                  RR4      4      pVP                  R4      '       g   K7  \        VP                  RR4      4      R	8X  g   KY  \        VP                  R
R4      4      P                  4       pV'       g   K  RVR^ /W$&   K  	  VP                  R. 4       FU  pVP                  R4      R8X  g   K  VP                  R4      V9   g   K3  W&R,          ,          R;;,          ^,          uu&   KW  	  \        VP                  4       R R7       Uu. uF  pVR,          ^8  g   K  VNK  	  upR,          pV'       g   R# . p	V FM  pRP                  \        VR,          ^4      4      ;'       g    Rp
V	P                  RVR,           RV
 24       KO  	  \        V \        P!                  RP                  V	4      R7      ,           RR7      p. p\#        V4       F  p\%        V\&        4      '       g   K  \        VP                  RR4      4      P                  4       p\        VP                  RR4      4      P                  4       P)                  4       pV'       g   K  VR#9   g   K  VP                  V RV 24       K  	  V'       g   R# RRP                  VR,          4      ,           p\+        R V 2R!R"7       V# u upi )$u   Batch-ask DeepSeek which generic "thing" entities are really a person/
company/place/product. LOG-ONLY — there is no retype endpoint — so it just
returns a short note string that lands in the run summary. ONE DeepSeek call.rV   rm   r<   rn   ro   r   rp   rs   zentity:thingrr   rq   rt   ru   rv   rw   rx   c                     V R ,          ) # r   r   r   s   &r*   r   %_flag_thing_retypes.<locals>.<lambda>  s
    QuXIr   r   N   N; 
(no facts)z- "z": ry   )r   r   r   	suggestedz->zretype: r  z  [retype] Tr.   )personcompanyplaceproduct)r+   r   r]   r^   r?   rP   r=   r   rQ   r   r   r   r   r   rT   THING_RETYPE_PROMPTr   r   r_   r`   r   r2   )r   r   thingsr   r   rq   r5   r   r   blocksfxr)   suggvr   r;   s   &               r*   _flag_thing_retypesr[    s    y6<<#9#97E:J#KKLEFYYw#!%%b/">>&!!c!%%*;&<&NquuVR()//1Dt%tUA6 $ YYw#55=J&155;&+@T7OE"a'" $ V]]_2EF Fh!m 1F  "CFYY}QvY23CC|AfI;c"./  8188dii>O8PP"$CD!T""155$%++-k2&'--/5574ABBKK4&1#'  		$s),,D	Kv
d+K-s   ,LLc                (   \        RRR\        R\        /4      p^ pVEe   VP                  R4      ;'       g    VP                  R4      ;'       g    . p. p\	        V\
        4      '       d   TM. R,           F)  p\        V4      pV'       g   K  VP                  V4       K+  	  V'       Ed   . p\        V^4       Fx  w  pw  rrpR	P                  \        V
^4      4      ;'       g    R
pR	P                  \        V^4      4      ;'       g    R
pVP                  RV RV RV
 RV RV RV R24       Kz  	  \        V \        P                  RP                  V4      R7      ,           RR7      p\        V4       EF?  p\	        V\        4      '       g   K   \!        VP                  R^ 4      4      ^,
          p^ Tu;8:  d   \'        T4      8  g   M K[  \)        TP                  RR4      4      P+                  4       P-                  4       R8w  d   K  TT,          w  rrp\)        TP                  RR4      4      P+                  4       P/                  4       pTR8X  d   Y3MY3w  pp\        '       d    \1        RT RT 2RR7       T^,          pEK  \        RR R!TR"T.R\        /4       f   EK6  T^,          pEKB  	  Rp \3        V 4      pVV3#   \"        \$        3 d     EKk  i ; i  \4         d   p\1        R#T 2RR7        Rp?TT3# Rp?ii ; i)$u  Pass 7 — entity hygiene.

(a) POST /entities/dedup_backfill (non-dry, or dry in REFLECT_DRY): the service
    auto-merges the confident (>=0.95) pairs and returns an 'ambiguous'
    0.80-0.95 band for us to judge.
(b) ONE batched DeepSeek call adjudicates the WHOLE band → POST /entities/merge
    for the pairs it confirms.
(c) Flags mistyped 'thing' entities (log-only) via _flag_thing_retypes.
Returns (merges_done, retype_note). Missing endpoints 404 → (0, "").r9   z/entities/dedup_backfilldry_runr<   N	ambiguouspairsrL  rN  rO  zPair z (score z): A="z" [z	]  |  B="r~   ry   )r_  i  r   pairverdictr   merger&  ABz  [entity-merge] keep z <- Tr.   z/entities/merger<  
merge_keysz  [retype] failed: )r6   r>   r?   rP   r_   r   rH  r   	enumerater   r   rT   MERGE_ADJUDICATE_PROMPTr   r   r`   r   	TypeErrorr   r[   r=   rQ   r   upperr2   r[  r4   )r   re   mergesbandr_  rG  pfrW  r  kanakbnbscfafbr)   rZ  idx	keep_sider<  r?  retype_noter5   s   &                       r*   pass_entity_hygienerw  6  s    &4c7E24CF
ww{#==swww'7==2$T400$b#>>AaBrR  ? 5F+4UA+>''BBBYY}R34DDYY}R34DDaSF2$c" F$$&4s2$a1 2 ,?
 8&=&D&Dii' 'E ') )59;C %!!T**aeeFA./!3C S-3u:-quuY+,224::<G%*3Z"fc 2399;AAC	2;s2Brh#)328*DL $&aKF6#4&,#U,-489 aKF- &. K5)(3 ;/ ":. *  5#A3't44;5s*   "KK) K&%K&)L4LLc                L   . p\        RR\        P                  P                  R\        RV RV/4      ,           4      pT;'       g    / P                  R. 4       FG  p\        VP                  RR4      4      P                  4       pV'       g   K6  VP                  V4       KI  	  V# )	zKFact texts of memories already stored under `kind` (dedup guard + context).rV   rW   r<   rs   rX   rZ   r|   r   )	r6   r   r]   r^   r?   rP   r=   rQ   r   )rs   rX   rc   re   r   r   s   &&    r*   _existing_kindry  r  s    
C
%(>(>	%w6)8 8 9CiiR__Z,fb!"((*1JJqM - Jr   c           	     p   \        R4      p\        V 4      pV'       g   ^ # RP                  R V 4       4      ;'       g    Rp\        V\        P                  WCR7      ,           RR7      pV  Uu0 uF1  qfP                  R4      f   K  \        VP                  R4      4      kK3  	  pp^ p\        V4       EFm  p	V^8  d    V# \        V	\        4      '       g   K&  \        V	P                  R	R
4      4      P                  4       p
\        V
4      ^
8  g   \        W4      '       d   Kr  V	P                  R4      ;'       g    .  Uu. uF   p\        V4      V9   g   K  \        V4      NK"  	  upR,          pV Uu. uF	  pRVRR/NK  	  pp\        '       dJ   \        RT
 RRP                  V4      ;'       g    R 2RR7       VP!                  V
4       V^,          pEK)  R	V
RRR\"        /pV'       d   WR&   \%        RRV4      f   EKS  VP!                  V
4       V^,          pEKp  	  V# u upi u upi u upi )u   Pass 8 — pattern mining. ONE DeepSeek call over the timestamped corpus;
saves up to 5 NEW kind='pattern' memories, each linked to 2-3 evidence ids,
deduped against the patterns already stored (passed in as 'already known').patternry   c              3   ,   "   T F
  pR V 2x  K  	  R# 5ir   r   r   s   & r*   r   pass_pattern.<locals>.<genexpr>       2EqBqc(Er   
(none yet)knownr     r   ro   rr   r   evidenceN   Nrx   rv   z  [pattern]   <- r  zno evidenceTr.   rs   r<   linksr9   	/remember)ry  r   r   rT   PATTERN_PROMPTr   rP   r=   r   r_   r`   rQ   r[   r  r>   r2   r   r?   r6   )r   r   r  r!  	known_txtr)   rf   validr  itrr   r   evr5   r  r&   s   &&              r*   pass_patternr  ~  s    9%E% G		2E22BBlI
8n33 4 ( (48:C',Hu!dStuEHG#a<( N' "d##266&"%&,,.t9r>Yt33!vvj177R7L7CFeOfc!f7LRP8:;1$6:.;3LeDIIbM,J,J]+KLLLqLGfi%@!M6;-9LLqLG+ , N1 I M;s   /H)H)H.H.8H3c           	     t   \        R4      p\        V ^R7      pV'       g   ^ # RP                  R V 4       4      ;'       g    Rp\        V\        P                  WCR7      ,           RR7      pV  Uu0 uF1  qfP                  R	4      f   K  \        VP                  R	4      4      kK3  	  pp^ p\        V4       EFm  p	V^8  d    V# \        V	\        4      '       g   K&  \        V	P                  R
R4      4      P                  4       p
\        V
4      ^
8  g   \        W4      '       d   Kr  V	P                  R4      ;'       g    .  Uu. uF   p\        V4      V9   g   K  \        V4      NK"  	  upR,          pV Uu. uF	  pRVRR/NK  	  pp\        '       dJ   \        RT
 RRP                  V4      ;'       g    R 2RR7       VP!                  V
4       V^,          pEK)  R
V
RRR\"        /pV'       d   WR&   \%        RRV4      f   EKS  VP!                  V
4       V^,          pEKp  	  V# u upi u upi u upi )u   Pass 9 — reflection-tree. ONE DeepSeek call inferring 3-5 higher-level
conclusions NOT directly stated, saved as kind='synthesis' linked to their
sources and deduped against the syntheses already stored. Cap 5.	synthesis)rb   ry   c              3   ,   "   T F
  pR V 2x  K  	  R# 5ir   r   r   s   & r*   r   !pass_synthesis.<locals>.<genexpr>  r~  r   r  r  r  r   ro   rr   r   sourcesr  rx   rv   sourcez  [synthesis] r  r  zno srcTr.   rs   r<   r  r9   r  )ry  r   r   rT   SYNTHESIS_PROMPTr   rP   r=   r   r_   r`   rQ   r[   r  r>   r2   r   r?   r6   )r   r   r  r!  r  r)   rf   r  r  r  rr   r   srcr   r  r&   s   &&              r*   pass_synthesisr    s    ;'E%S)G		2E22BBlI
8.55 6 ( (48:C',Hu!dStuEHG#a<( N' "d##266&"%&,,.t9r>Yt33 "y 1 7 7R 7L 7!CFeOvs1v 7LRP69:c$68,c:3N4&diin.H.H-IJLLqLGfk7EB!M6;-9LLqLG+ , N1 I M:s   1H+
H+H0H0:H5c                .	   \        V \        RR7      R,          p\        4       . rCW R,          ,            F  p\        VP	                  R4      4      pWc9   d   K%  VP                  V4       \        VP	                  RR4      4      P                  4       pV'       d1   TP                  RVP	                  R	4      ;'       g    R R
V 24       \        V4      ^78  g   K   M	  RP                  V4      p\        RR\        P                  P                  R\        /4      ,           4      p	/ p
V	P	                  R. 4       Ff  p\        VP	                  RR4      4      pVP                  R4      '       g   K7  R\        VP	                  RR4      4      P                  4       R^ /W&   Kh  	  V	P	                  R. 4       FU  pVP	                  R4      R8X  g   K  VP	                  R4      V
9   g   K3  WR,          ,          R;;,          ^,          uu&   KW  	  \        V
P!                  4       R R7       Uu. uF&  pVR,          ^8  g   K  VR,          '       g   K$  VNK(  	  upR,          p. pV F  p \        RR\        P                  P                  RVR,          R\        /4      ,           4      pT;'       g    / P	                  R. 4       FU  p\        TP	                  RR4      4      P                  4       pT'       g   K6  TP                  RTR,           RT 24        K  	  K  	  RP                  V4      ;'       g    R pRp\%        RR!\        P                  P                  R\        /4      ,           4      pV'       d4   \        T;'       g    / P	                  RR4      4      P                  4       MRpV'       d   R"V,           R#,           p\'        \)        V\*        P-                  VVVR$7      ,           R%R&7      4      p\        V4      ^8  d   R'# VP/                  4       p\        V4      ^8  d   R(P                  VR),          4      p\0        '       d   \3        R*V 2RR+7       R# \%        R,R-RVR\        /4      R.J# u upi   \"         d     EK*  i ; i)/u/  Pass 10 — refresh the pinned CORE PROFILE (<=200 words) that gets injected
into every Jarvis prompt. Built from the highest-value memories + tonight's
fresh entity summaries; runs LAST so it reflects the night's cleanup. ONE
DeepSeek call → POST /core. Returns True if a profile was written/printed.Trj   :N(   NrL  ro   r|   r   z- (rs   z) ry   rV   rm   r<   rn   rp   rq   rr   rt   ru   rv   rw   rx   c                     V R ,          ) # r   r   r   s   &r*   r   pass_core.<locals>.<lambda>  s
    %yr   r   :N   Nr   r   r   r{   r8   z(none)z/core_block?uL   PRIOR CORE (refresh it — keep what still holds, DROP anything now stale):
z

)r2  	summariesr   r   r   Fr-   :N   Nz	  [core] r.   r9   z/coreN)r   r   r   r=   rP   r   rQ   r   r[   r   r+   r   r]   r^   r?   r   r   r4   r6   r   rT   CORE_PROMPTr   splitr>   r2   )r   r   r   r   r   rf   r   r   facts_blockr   r   r   r   r5   top_ents	sum_linesr(   r   r   summaries_blockr2  r4  r5  rr   wordss   &&                       r*   	pass_corer    s    Ey$7<Fr#Cj  !%%+;!%%#$**,JJQUU6]44f5Ru=>s8r> ! ))C.Ky6<<#9#97E:J#KKLEDYYw#!%%b/">>&!!QUU62%6!7!=!=!?JDI $ YYw#55=J&155;$+>4M% A%  $ "$++-5HI 0IaU8q= %&vYY I 0035HI	E:(>(>6GU3)5 5 6A GG==R0CCGGIr*+113Aq  2ai[1#!67	 1  ii	*66hOE
%&,,*@*@'5AQ*RR
SC<?SYYBOOFB/0668RI!#,-/56x;%%E_,7 & 9 	9EIK LD 4y2~JJLE
5zCxxd$
s	$ -67VT7E$BC4OOC0  		s$   /Q?Q?Q?-?RRRc                  a! \         P                  P                  4       \         P                  ! ^ZR7      ,
          p\	        4       / rTVP                  R. 4       F  p\        VP                  RR4      4      \        VP                  RR4      4      VP                  R4      rpV	R8X  dE   VP                  R4      '       g,   VP                  V\	        4       4      P                  V4       K  K  VP                  R4      '       g   VP                  V4       VP                  R4      '       d   K  VP                  V4       K  	  . p
V  EF	  pVP                  R	4      pVf   K  \        VP                  R
4      ;'       g    R4      P                  4       R)9  d   KT  VP                  R4      p\        V\        \        34      '       d
   V^8  d   K  VP                  R4      p\        V\        \        34      '       d
   V^ 8  d   K  \        VP                  R4      4      pVe   W8  d   K  \        V4      V9   d   K  V
P                  V4       EK  	  V
'       g   ^ # V
R,          p
V
 Uu0 uF  p\        VP                  R	4      4      kK  	  ppV
 Uu/ uF  p\        VP                  R	4      4      VbK   	  upo!/ pV F=  pVP                  VR*4       F$  pVP                  V. 4      P                  V4       K&  	  K?  	  . \	        4       ppVP!                  4        FV  w  ppV Uu. uF  pVV9  g   K  VNK  	  pp\#        V4      ^8  g   K2  VP                  VV34       VP%                  V4       KX  	  V'       Ed   . p\'        V^4       F>  w  pw  ppRP)                  V!3R lV 4       4      pVP                  RV RV RV 24       K@  	  \+        V\,        P/                  RP)                  V4      R7      ,           RR7      p/ p\1        V4       Fa  p\        V\2        4      '       g   K   \        VP                  RR4      4      P5                  4       V\        VP                  R^ 4      4      &   Kc  	  \'        V^4       F  w  pw  ppVP                  VR4      p\#        V4      ^
8  d   K-  V Uu. uF	  pRVRR/NK  	  pp\:        '       d%   \=        RV RRP)                  V4       2RR7       Kr  \?        R R!RVR
R"R#\@        R$V/4       K  	  ^ p V
 F  p\:        '       dN   \=        R%VP                  R	4       R&\        VP                  R"R4      4      R',           2RR7       V ^,          p K\  \?        R R(R	VP                  R	4      R#\@        /4       f   K  V ^,          p K  	  V # u upi u upi u upi   \6        \8        3 d     EK  i ; iu upi )+u  Pass 11 — archive sweep. Retire memories that are ALL of: kind
observation|event, importance<=4 (or absent), access_count 0 (or absent),
created >90d ago, and NOT linked to another memory. Before retiring a CLUSTER
(>=3 sharing an entity), one summary fact (kind='fact') is saved first so the
gist survives. Cap 30 retirements/night. At most ONE DeepSeek call (only if
there are clusters). Returns the retired count.)daysru   r   r   rx   rv   rw   rp   ro   rs   r   r   r   :N   NrN  c              3      <"   T F5  p\        SV,          P                  R R4      4      P                  4       x  K7  	  R# 5i)r|   r   N)r=   rP   rQ   )r   r   r  s   & r*   r   pass_archive.<locals>.<genexpr>E  s1     PCqSqfb!9:@@BBCs   =A zCluster r   z): ry   )clustersr   r   rr   cluster
summary_ofz  [archive-summary] r  r  Tr.   r9   r  r|   r<   r  z  [archive] retire r8   :N<   Nr  )observationeventr   )!r   r   todayr   r   rP   r=   r   
setdefaultr   r   r_   r   r   r   r   r   r[   updaterf  r   rT   ARCHIVE_SUMMARY_PROMPTr   r   r`   rQ   rh  r   r>   r2   r6   r?   )"r   r   r   r   linkedmentr5   frrx   typvictimsrf   r   r   r   dvids
ent_groupsvidr   r  	clusteredr%  r  rW  r&   r)   r  r   summr   r  r#  r  s"   &&&                              @r*   pass_archiver    s    XX^^2 66F5"DYYw#!%%+,c!%%b/.BAEE&M*==((CE*..r2 ) ==((

2==((

2 $ GeeDk;quuV}""#))+3KKeeL!cC<((S1WUU>"b3,''BFl+,9s8vq# $ clG&-.gCdgD.*12'QStq '2EJ88C$C!!#r*11#6 %  ceiH$$&S4#Q)!3qq#4s8q=OOS#J'S!	 '
 x&x3MAzS99PCPPDMMHQCr#c$89 4 x"8"?"?YYv& #@ #( (48:	S!Aa&&69!%%:K6L6R6R6T	#aeeIq123	 " 'x3MAzS==B'D4y2~>ABcdAv|4cEBs,TF%		#7GH "FKT667E7ERT 4 G3'd}Bvr*+C013:>@qLG69!%%+w68?CDqLG  Nc /2 5" z*  Cs1   ,#V,$V1'	V65V60AV;6W;WWc                  	   \        4       w  rr#\        V4      pV^ 8X  d   \        RRR7       R#  \        4       p\        V\        P                  WR7      ,           4      p\        P                  ! RV\        P                  4      p V'       d&   \        P                  ! VP                  ^ 4      4      M. pV U	u. uF  p	\        V	\        4      '       g   K  V	NK  	  pp	^ p
V EF  p	\!        V	P#                  RR4      4      P%                  4       p\!        V	P#                  R	R4      4      P%                  4       p\!        V	P#                  R
R4      4      P%                  4       P'                  4       p\        V4      ^
8  d   K  V'       d   V RV 2MTp\(        '       d   \        RV RV 2RR7       V
^,          p
K  \+        RRRVRVRVR\,        /4      pVP#                  R4      '       g   EK  V
^,          p
EK  	  T
p^ p \/        V4      p^ p \1        W4      p^ p \3        V4      p^ p \5        V4      pRp \7        W4      p^ Rpp \9        V4      w  pp^ p \;        W%4      p^ p \=        W%4      pRp \?        W%4      p^ p \A        W#V4      pR!T R"T R#T R$V'       d   R%MR& R'T R(T R)T R*T R+T R,V'       d   R%MR& R-V 2V'       d   R.V 2MR,           \(        '       d   R/MR,           p\        R0V,           RR7       V#   \         d    Rp ELi ; i  \         d    . p ELvi ; iu up	i   \         d   p\        RT 2RR7        Rp?ELHRp?ii ; i  \         d   p\        RT 2RR7        Rp?ELcRp?ii ; i  \         d   p\        RT 2RR7        Rp?EL~Rp?ii ; i  \         d   p\        RT 2RR7        Rp?ELRp?ii ; i  \         d   p\        RT 2RR7        Rp?ELRp?ii ; i  \         d   p\        RT 2RR7        Rp?ELRp?ii ; i  \         d   p\        RT 2RR7        Rp?ELRp?ii ; i  \         d   p\        RT 2RR7        Rp?EL Rp?ii ; i  \         d   p\        RT 2RR7        Rp?ELRp?ii ; i  \         d   p\        R T 2RR7        Rp?EL5Rp?ii ; i)1    zreflection: no memories yetTr.   zno memories yetr   )r   r   r   titledetailrv   r  u    — z  [z] r9   z/insightrr   ityper<   r  z  [summary] pass failed: Nz  [goal] pass failed: z  [consolidate] pass failed: z  [read] pass failed: Fz  [values] pass failed: z  [hygiene] pass failed: z  [pattern] pass failed: z  [synthesis] pass failed: z  [core] pass failed: z  [archive] pass failed: z	insights z, summaries z, reads z	, values yr   z, goals z, consolidated z	, merges z, patterns z, synthesis z, core z, archived rN  z (dry)zreflection: )!r   r[   r2   r   r4   rT   PROMPTr   r   r   r   r   r$   r<   r_   r`   r=   rP   rQ   r   r>   r+   r?   r  r  r(  r0  r6  rw  r  r  r  r  )r   r   r   r   n_factsr   r)   r   findingsrf   r  r  r  r  rr   r(   
n_insightsn_summariesr5   n_goals	n_retiredn_reads	values_okn_mergesrv  
n_patternsn_synthcore_ok
n_archivedr;   s                                 r*   _runr  i  s   (5%I%jG!|+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3Cwb't4qLG
wwwNP55qLG  J K;$X.
 G8Y1
 I?$U+	
 G8X&
 I:	4	
 rkH; 3H =+
 J;!%2

 G= 1
 G8E,
 J;!%9
 
|<}HWI N&cC0	 B%;izZL Q 	S(A B"|	%
 &1K=!b: 3xB(D 
.4
t,KW    ;.  ;)!-T::;  8&qc*$778  ?-aS1>>?  8&qc*$778  :(,D99:  ;)!-T::;  ;)!-T::;  =+A3/t<<=  8&qc*$778  ;)!-T::;s  
L /L :L0L0L5 M N -N0 ;O P P+ *Q 8Q= R& LLL-,L-5M MMN)M??NN-N((N-0O;OOO?$O::O?P(P##P(+Q6QQQ:Q55Q:=R#RR#&S1SSc                     \        R4        \        4       p \        RT 4       R#   \         d+   p\        R\        T4      P                   RT 24       h Rp?ii ; i)u   Bracket the whole run in a heartbeat so a silent death is visible.

started → (all passes) → ok; on ANY fatal exception, stamp error then re-raise.
heartbeat() itself never raises, so the guard can't hide the real error.startedr0   r8   Nok)r@   r  r4   rv   __name__)r;   r5   s     r*   mainr    sY    
 iv dD  'd1g../r!56s   
% A%AA__main__)Nr  )r   )ip  )i  )   )   )d   )C__doc__r   r   r   osr   urllib.errorr   urllib.parseurllib.requestenvironrstripr   rP   r    r?   rN   rO   rM   r>   maxr   r   r   r+   r6   r@   rT   r  r   r  r  r/  r3  rg  rU  r  r  r  r  rh   r   r   r   r   r   r   r   r   r   r  r  r  r(  r0  r6  rH  r[  rw  ry  r  r  r  r  r  r  r  r   r   r*   <module>r     s  (R   	 	   jj!"))#.
**..)2
.


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


(9:jjnn]C(C/q#bjjnn-CUKLML
.F 
[
	:
	&	 &	"$	 (	 	.	 &(	 $-:	5	 $0@CL$#L&R2j>E,%P9x	#L#L>PB[|vr zF k%  Ls   3)G 	GG