+
    Xj                    ^  a  0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIHtH	t	 ^ RI
Ht ]! ]4      P                  4       P                  P                  t]R,          R,          t^dt]P$                  ! 4       t. sR]R&   R	sR
 R ltR R ltR R ltRR R lltR R ltR R ltR R ltR# )u  Durable pending-notification store — so a worker's "btw…" survives a crash.

WHY (2026-07-16): worker results/flags land on the engine's in-RAM inbox
(asyncio.Queue) and are announced when Ahmed is quiet. But if Jarvis restarts
or crashes BEFORE the master found a moment to say it, the note evaporated —
Jarvis came back remembering the conversation (it resumes the session) but
having forgotten the important flag. That asymmetry is the bug.

This store persists every outbound note the instant it's created and only drops
it once it's been DELIVERED and acknowledged — not merely dequeued. On boot the
un-acked notes are reloaded so the master delivers them after the restart:
"Sir — before the restart, that email turned out wrong."

A note isn't done when it's spoken-attempt-started; it's done when `ack()` runs
after it actually reached Ahmed. Storage is one atomic JSON file
(control/pending.json), same style as the task ledger.

priority:  "fyi"    — weave in at a natural pause (default)
           "urgent" — worth breaking in for (about to do the wrong thing)
The priority is persisted for the delivery layer to use; this module just
guarantees the note is never silently lost.
)annotationsN)datetimetimezone)Pathcontrolzpending.json
list[dict]_itemsFc                   V ^8  d   QhRR/# )   returnstr )formats   "voice/pending.py__annotate__r   *   s     D Dc D    c                 j    \         P                  ! \        P                  4      P	                  R R7      # )seconds)timespec)r   nowr   utc	isoformatr   r   r   _nowr   *   s#    <<%///CCr   c                   V ^8  d   QhRR/# r
   r   Noner   )r   s   "r   r   r   .   s     
A 
A 
Ar   c                 N    \         P                  P                  R R7       \         P                  R4      p \         Uu. uF  qP                  R4      '       d   K  VNK  	  pp\         Uu. uF  qP                  R4      '       g   K  VNK  	  up\        ) R pV P                  \        P                  ! W#,           R^ R7      4       \        P                  ! V \         4       R# u upi u upi   \         d+   p\        R\        T4      R,           R	24        Rp?R# Rp?ii ; i)
T)exist_okz	.json.tmpackedNF)ensure_asciiindentz       [pending: write failed: Nx   N])STOREparentmkdirwith_suffixr   getMAX_KEEP
write_textjsondumpsosreplace	Exceptionprintr   )tmpiunackedr   es        r   _persist_lockedr5   .   s    	AD),$;fEE'N11f;"5FqeeGnF5xijAtzz'/aPQ


3 <5  A/At~Q?@@AsA   =C/ C%C%"
C/ ,C*	C*AC/ %
C/ /D$:DD$c                   V ^8  d   QhRR/# r   r   )r   s   "r   r   r   ;   s      d r   c            	        \         ;_uu_ 4        \        '       d    R R R 4       R #  \        P                  4       '       dK   \        P
                  ! \        P                  4       ;'       g    R4      p \        V \        4      '       d   V s	RsR R R 4       R #   \         d,   p\        R\        T4      R,           R24       . s	 R p?L=R p?ii ; i  + '       g   i     R # ; i)Nz[]z       [pending: load failed: r!   r#   T)_lock_loadedr$   is_filer+   loads	read_text
isinstancelistr   r/   r0   r   )datar4   s     r   loadr@   ;   s    	7 
	}}zz%//"3";";t<dD))!F  
  	23q6$<.BCF	 
s@   CB*B-BCC#!C	C	CCC"	c               $    V ^8  d   QhRRRRRR/# )r
   textr   priorityr   r   )r   s   "r   r   r   K   s!      c S S r   c                   R\         P                  ! 4       P                  R,          ,           p\        ;_uu_ 4        \        P                  RVRV RVR\        4       RR/4       \        4        R	R	R	4       V#   + '       g   i     T# ; i)
z4Persist an outbound note (un-acked). Returns its id.p_:N
   NidrB   rC   createdr   FN)uuiduuid4hexr8   r   appendr   r5   )rB   rC   pids   && r   addrN   K   sk    
!!#&
&C	tS&$
H $&'5: 	; 
 J	 
 Js   2A88B		c                   V ^8  d   QhRR/# )r
   r   r   r   )r   s   "r   r   r   U   s     ? ? ?r   c                     \         ;_uu_ 4        \         U u. uF&  q P                  R4      '       d   K  \        V 4      NK(  	  up uuRRR4       # u up i   + '       g   i     R# ; i)uB   Notes still awaiting delivery — reloaded into the inbox on boot.r   N)r8   r   r(   dict)r2   s    r   r3   r3   U   s;    	!'>AuuW~Q> 
> 
s!   	AAAAAA'	c                    V ^8  d   QhRRRR/# )r
   textsz	list[str]r   r   r   )r   s   "r   r   r   [   s      y T r   c                P   V '       g   R# \         ;_uu_ 4        RpV  FV  p\         FI  pVP                  R4      '       d   K  VP                  R4      V8X  g   K4  RVR&   \        4       VR&   Rp KT  	  KX  	  V'       d   \	        4        RRR4       R#   + '       g   i     R# ; i)zMark notes delivered. Matches by exact text (oldest un-acked first), so
the same rail that carried plain strings needs no id plumbing.NFr   rB   T	deliveredr8   r   r(   r   r5   )rS   changedtxtr2   s   &   r   ackrY   [   sw     	CuuW~~!%%-3*>!%AgJ%)VAkN"G    
s   %BB$B 
BB%	c                   V ^8  d   QhRR/# r   r   )r   s   "r   r   r   m   s     	 	 	r   c                     \         ;_uu_ 4        R p \         F0  pVP                  R4      '       d   K  RVR&   \        4       VR&   Rp K2  	  V '       d   \	        4        RRR4       R#   + '       g   i     R# ; i)Fr   TrU   NrV   )rW   r2   s     r   ack_allr\   m   sS    	A55>>!'
!%+	 
  
s    A(A(
A((A9	)fyi)__conditional_annotations____doc__
__future__r   r+   r-   	threadingrI   r   r   pathlibr   __file__resolver%   PROJECTr$   r)   Lockr8   r   __annotations__r9   r   r5   r@   rN   r3   rY   r\   )r^   s   @r   <module>rh      s   . #  	   ' 
x.
 
 
"
)
)
0
0)n,
 
D
A ?$	r   