
    hi7                     D   d Z ddlZddlZddlZddlZddlmZmZ ddlmZ  ed      Z	e	dz  dz  Z
e	dz  dz  Ze	d	z  d
z  Ze	d	z  dz  Z ed      Zedz  ZdZdZdZdefdZdefdZdefdZdefdZdefdZd ZdedededefdZdedefdZd Ze d k(  r e        yy)!uU  
Genesis Session Recovery Hook — SessionStart Hook
===================================================
Injects handoff context on session start to enable autonomous respawn.

Fires on: startup, resume, compact (all SessionStart events)

This is the CRITICAL MISSING PIECE of the auto-respawn system. It reads
the latest handoff files written by auto_respawn.py (at 65%/70% context)
and injects them as additionalContext so Claude immediately knows:
- What mission was active
- What agents were running
- Key decisions made
- Blockers and next actions

This enables the "zero re-orientation" respawn experience where Claude
resumes work autonomously without asking "what was I doing?"

Architecture:
  - Reads hive/progress/session_*_handoff.md (latest by mtime)
  - Reads hive/session_recovery/LATEST.md (heartbeat state)
  - Reads data/context_state/current.json (final session state)
  - Reads MEMORY.md war room status section (active mission)
  - Injects all as additionalContext
  - Clears respawn_requested.flag if present
  - Logs recovery event to observability

Author: Genesis Auto-Respawn System
    N)datetimetimezone)Pathz/mnt/e/genesis-systemhiveprogresssession_recoverydatacontext_stateobservabilityzI/home/authentic88/.claude/projects/-mnt-e-genesis-system/memory/MEMORY.mdzrespawn_requested.flagi  i  i  returnc                     	 t         j                  dd       t        t         j                  d      d d      } | ru| d   }|j	                  dd	      }t        j                  d
|j                        }|r|j                  d      nd}t        |      ||dt         t        |      t        kD  ddS 	 ddiS # t        $ r Y ddiS w xY w)z"Read the most recent handoff file.Tparentsexist_okzsession_*_handoff.mdc                 6    | j                         j                  S )N)statst_mtime)fs    =/mnt/e/genesis-system/.claude/hooks/session_recovery_start.py<lambda>z$get_latest_handoff.<locals>.<lambda>C   s    !&&(++     )keyreverser   utf-8replaceencodingerrorszsession_(\d+)_handoff\.md   ?N)filesession_numbercontent	truncatedfoundr%   F)HANDOFF_DIRmkdirsortedglob	read_textresearchnamegroupstrMAX_HANDOFF_CHARSlen	Exception)handoffslatestr#   session_matchsession_nums        r   get_latest_handoffr7   =   s    $634+

 a[F&&	&JGII&BFKKPM4A---a0sKF"-"#5$56 \,==   U  Us   B/B7 7	CCc                      	 t         dz  } | j                         r:| j                  dd      }t        |       |dt         t        |      t        kD  ddS 	 dd	iS # t        $ r Y dd	iS w xY w)
z5Read LATEST.md recovery document (session heartbeat).z	LATEST.mdr   r   r   NT)r!   r#   r$   r%   r%   F)RECOVERY_DIRexistsr*   r/   MAX_RECOVERY_CHARSr1   r2   )r4   r#   s     r   get_recovery_stater<   W   s    +==?&&	&JGF"#6$67 \,>>	   U  Us   AA 	A)(A)c                  `   	 t         dz  } | j                         rrt        | d      5 }t        j                  |      }ddd       j                  dd      |j                  dd      |j                  dd      |j                  d	d      d
dS 	 ddiS # 1 sw Y   VxY w# t        $ r Y ddiS w xY w)z,Read previous session's final context state.zcurrent.jsonrNused_percentager    cost_usdr   
session_id	timestampT)used_pctcostrA   rB   r%   r%   F)	STATE_DIRr:   openjsonloadgetr2   )
state_filer   states      r   get_previous_context_staterL   h   s    /
j#& %!		!% "II&7=		*a0#iic:"YY{C8   U% %  Us(   %B BAB BB 	B-,B-c                  \   	 t         j                         sddiS t         j                  dd      } t        j                  d| t        j
                  t        j                  z        }|r.|j                  d      }|dt         t        |      t        kD  d	d
S 	 ddiS # t        $ r Y ddiS w xY w)z/Extract WAR ROOM STATUS section from MEMORY.md.r%   Fr   r   r   z&## WAR ROOM STATUS.*?(?=\n## [A-Z]|\Z)r   NT)r#   r$   r%   )MEMORY_FILEr:   r*   r+   r,   DOTALL
IGNORECASEr.   MAX_WAR_ROOM_CHARSr1   r2   )r#   matchwar_rooms      r   extract_war_room_statusrT   {   s    !!#U##'''K 		5II%
 {{1~H#$7%78 ]-??   U  Us   B A<B 	B+*B+c                     g } 	 t         dz  }|j                         r,t        |d      5 }|j                  dd       |j	                         }t        |d      }|j                  t        d||z
               |j                         j                  dd      j                         j                  d	      }d
d
d
       dd
 D ]  }	 t        j                  |j                               }|j                  d      dk(  rK|j                  dd      }|j                  dd      }	|j                  dd      }
| j                  ||	|
d        | dd
 S # 1 sw Y   xY w# t        $ r Y w xY w# t        $ r Y +w xY w)z2Read recent agent spawn events from observability.events.jsonlrbr      iP  r   r   )r   
Ni
event_typeSubagentStartagent_idr    task_idrB   )r\   r]   rB   )
EVENTS_DIRr:   rF   seektellminmaxreaddecodestripsplitrG   loadsrI   appendr2   )agentsevents_filer   	file_size	read_sizelineslineeventr\   r]   rB   s              r   $get_active_agents_from_observabilityrq      sn   F >1k4( WAq!FFH		51	s1i)345	BHHJPPQUVW de  JJtzz|4Eyy./A#(99Z#="'))Is";$)IIk3$?	(0'.)2'   "#;3W W* !  sN   &E* BE5E* BEE* EE* 	E'$E* &E''E* *	E65E6c                  x    	 t         j                         rt         j                          y	 y# t        $ r Y yw xY w)z!Remove respawn flag if it exists.TF)RESPAWN_FLAGr:   unlinkr2    r   r   clear_respawn_flagrv      sC     ! !
   s   (- 	99sourcehandoff_foundrecovery_foundwar_room_foundc                 d   	 t         j                  dd       t        j                  t        j
                        j                         d| |||d}t         dz  }t        |d      5 }|j                  t        j                  |      dz          ddd       y# 1 sw Y   yxY w# t        $ r Y yw xY w)	z$Log recovery event to observability.Tr   r   )rB   rZ   rw   rx   ry   rz   rV   arY   N)r_   r'   r   nowr   utc	isoformatrF   writerG   dumpsr2   )rw   rx   ry   rz   rp   rk   r   s          r   log_recovery_eventr      s    5!hll3==?,*,,
 !>1+s# 	.qGGDJJu%,-	. 	. 	. s0   A$B# &(BB# B B#  B# #	B/.B/
hook_inputc           
      8
   | j                  dd      }| j                  dd      }t               }t               }t               }t	               }t               }|j                  d      xs4 |j                  d      xs! |j                  d      xs t        |      dkD  }|sdd|d	d
S g }	|	j                  d       |	j                  d       |	j                  d       |	j                  d|        |	j                  d|        |	j                  d       |j                  d      r0|	j                  d|d    d|d   dd       |	j                  d       |j                  d      rX|	j                  d       |	j                  |d          |j                  d      r|	j                  d       |	j                  d       |j                  d      r_|	j                  d|d    d       |	j                  |d          |j                  d      r|	j                  d       |	j                  d       |j                  d      rX|	j                  d       |	j                  |d          |j                  d      r|	j                  d       |	j                  d       |rt|	j                  d       |D ]+  }
|	j                  d|
d    dd!  d"|
d#   dd!  d$|
d%           - |	j                  d       |	j                  d&       |	j                  d       |	j                  d       |	j                  d'       |	j                  d       |	j                  d       |	j                  d(       |	j                  d       |	j                  d)       |	j                  d*       |	j                  d       |	j                  d+       |	j                  d,       |	j                  d-       |	j                  d.       |	j                  d/       |	j                  d       |	j                  d0       |	j                  d1       |	j                  d2|r|d   d    dd! nd3 d4       |	j                  d5       |	j                  d       |	j                  d6       |	j                  d7       |	j                  d       |	j                  d8       |	j                  d       d9j                  |	      }|d:||j                  d      |j                  d      |j                  d      t        |      d;d
S )<z
    Build the recovery context to inject into Claude's session.

    Returns a dict with:
      - additionalContext: The recovery context string
      - metadata: Details about what was found
    rw   unknownrA   r    r%   r   NF)has_recovery_datarw   )additionalContextmetadatau   ═══════════════════════════════════════════════════════════════zSESSION RECOVERY ACTIVATEDzSource: zSession ID:  zPrevious session: rC   z% context used, $rD   z.2fz costu4   ═══ WAR ROOM STATUS (from MEMORY.md) ═══r#   r$   z(... truncated for brevity ...)u"   ═══ LATEST HANDOFF (session r"   u   ) ═══u.   ═══ RECOVERY STATE (heartbeat) ═══u+   ═══ RECENTLY SPAWNED AGENTS ═══z- Agent r\      z (task r]   z) @ rB   zXCheck agent output files: /tmp/claude-1000/-mnt-e-genesis-system/tasks/<agent_id>.outputzRECOVERY INSTRUCTIONSz0YOU HAVE RESPAWNED. This is AUTONOMOUS RECOVERY.z<DO NOT ask 'what's the mission?' or 'did you retain memory?'z)DO NOT request re-orientation from Kinan.zIMMEDIATELY:z71. Resume the active mission from WAR ROOM STATUS abovez*2. Check on any running agents (if listed)z%3. Continue the highest-priority workzF4. THEN greet Kinan with a status update of what you are ALREADY doingzCORRECT greeting example:z;  "Session 9 online. Resumed building Memory Vault backend.z	   Agent acd355ez# is writing auth.py and billing.py.z/   Next: deploy landing page with new pricing."zWRONG greeting example:zG  "What should I work on?" or "Do you have memory of our last session?"z%ZERO RE-ORIENTATION. PURE CONTINUITY.rY   T)r   rw   rx   ry   rz   agents_count)	rI   r7   r<   rL   rT   rq   r1   ri   join)r   rw   rA   handoffrecoveryprev_ctxrS   rj   has_datapartsagentcontexts               r   build_recovery_contextr      s    ^^Hi0Fc2J !"G!#H)+H&(H13F G$ 9W(= 9W%9),Vq   "&%* 
 	
 E 
LL  Q  S	LL-/	LL  Q  S	LL8F8$%	LL<
|,-	LL ||G)(:*>)??PQYZ`QabePffklmR ||GKMXi()<<$LL:;R {{79'BR:S9TT_`aWY'(;;{#LL:;R ||GEGXi()<<$LL:;R BD 	rELL8E*$5bq$9#:'%	BRSUTUBVAWW[\abm\n[opq	rRopR 
LL  Q  S	LL(*	LL  Q  S	LL	LLCD	LL	LLOP	LL<=	LL	LL 	LLJK	LL=>	LL89	LLYZ	LL	LL,-	LLNP	LL9&VAYz22A6iPPstu	LLBD	LL	LL*+	LLZ[	LL	LL89	LL  Q  RiiG %!%$[[1&ll73&ll73K

 
r   c            	      D   	 t        j                  t        j                  j	                               } | j                  dd      }t        |       }t               }|j                  di       }t        ||j                  dd      |j                  dd      |j                  dd             |j                  d	      st        t        j                  i              y d
|d
   i}t        t        j                  |             y # t         j
                  t        f$ r i } Y w xY w)Nrw   r   r   rx   Fry   rz   )rw   rx   ry   rz   r   r   )rG   rh   sysstdinrd   JSONDecodeErrorr2   rI   r   rv   r   printr   )r   rw   r   flag_clearedr   results         r   mainr   Y  s    ZZ		 01
 ^^Hi0F &j1H &'L ||J+Hll?E:||$4e<||$4e<	 <<+,djjn 	X&9:F 
$**V
=   ), 
s   1D DD__main__)!__doc__r   rG   osr+   r   r   pathlibr   GENESIS_ROOTr&   r9   rE   r_   rN   rs   r0   r;   rQ   dictr7   r<   rL   rT   listrq   rv   r/   boolr   r   r   __name__ru   r   r   <module>r      s'  <   	 	 '  +,V#j0f$'996!O3	F"_4
^_33    D 4D "D & 6d Ds 4  _c .xt x x~!H zF r   