Ë
    ;ƒÉj›  ã                   óh   — d Z ddlZddlZddlZddlZdZdZdZdZd„ Z	d„ Z
d	„ Zd
„ Zd„ Zd„ Zd„ Zd„ Zy)a6  Cards: one JSON per asset version at cards/<kind>/<group>/<class>/<slug>/v<N>.json.

The RELEASE hash is what a game pins: the fields a game reads at run time + the file hashes + the dependency graph.
Names, tags, summaries, status and quality can be edited without a new release; anything a game uses cannot.
é    N)ÚidÚversionÚframeÚsizeÚboundsÚ	placementÚsocketsÚnodesÚpaintÚrigÚ
animationsÚgameplayÚfilesÚdeps)r   r   ÚnameÚsummaryÚstyleÚstatusr   r   r   ÚrenderÚ
provenanceÚlicenceÚqualityr   Úrelease)ÚdraftÚ	candidateÚapprovedÚlegacyÚ
deprecated)r
   r	   r   r   r   r   c                 ó4   — t        j                  | ddd¬«      S )NT)ú,ú:F)Ú	sort_keysÚ
separatorsÚensure_ascii)ÚjsonÚdumps)Úos    ú7/home/claude-agent/forge-build/forge-assets/lib/card.pyÚ	canonicalr)      s   € Ü�:‰:�a 4°JÈUÔSÐSó    c                 óÊ   — dt        j                  t        t        D �ci c]  }|| j	                  |«      “Œ c}«      j                  «       «      j                  «       z   S c c}w )Nzsha256:)ÚhashlibÚsha256r)   ÚRUNTIMEÚgetÚencodeÚ	hexdigest)ÚcardÚks     r(   Úrelease_hashr4      sG   € Ø”w—~‘~¤iÌÖ0QÀA°°D·H±H¸Q³K±Ò0QÓ&R×&YÑ&YÓ&[Ó\×fÑfÓhÑhÐhùÒ0Qs   žA c                 ó¨   — |d   j                  dd«      \  }}t        j                  j                  | dg|j                  d«      ¢|‘d|d   › d�‘­Ž S )	Nr   ú/é   Úcardsú.Úvr   z.json)ÚsplitÚosÚpathÚjoin)Úrootr2   ÚclsÚslugs       r(   Úpath_ofrB      sW   € Ø�T‘
× Ñ   aÓ(�I€CˆÜ�7‰7�<‰<˜˜gÐY¨¯	©	°#«ÐY¸ÐYÀÀ$ÀyÁ/ÐARÐRWÐ>XÒYÐYr*   c                 óÂ  — t         D �cg c]  }|| vsŒd|› �‘Œ }}| j                  dd«      j                  d«      d   j                  d«      }t        |«      dk7  r#|j	                  d| j                  d«      › �«       | j                  d	«      t
        vr#|j	                  d
| j                  d	«      › �«       | j                  d«      r"| d   t        | «      k7  r|j	                  d«       | j                  d«      xs i }|j                  d«      s|j	                  d«       | j                  d	«      dk(  r"|j                  d«      s|j	                  d«       |S c c}w )Nzmissing r   Ú r6   r   r9   é   z"id must be kind.group.class/slug: r   zbad status r   z.release hash does not match the runtime fieldsr   Úevidencezlicence without evidencer   Úgame_usez"approved but not cleared for games)ÚREQUIREDr/   r;   ÚlenÚappendÚSTATUSr4   )r2   r3   Úerrsr@   Úlics        r(   ÚvalidaterN      s*  € Ü$,Ö>˜q°¸²ˆh�q�cŠNÐ>€DÐ>Ø
�(‰(�4˜Ó
×
"Ñ
" 3Ó
'¨Ñ
*×
0Ñ
0°Ó
5€CÜ
ˆ3ƒx�1‚}Ø�‰Ð8¸¿¹À$»Ð8HÐIÔJØ‡x�x�Ó¤Ñ'Ø�‰�k $§(¡(¨8Ó"4Ð!5Ð6Ô7Ø‡x�x�	Ô˜t I™´,¸tÓ2DÒDØ�‰ÐDÔEØ
�(‰(�9Ó
Ò
# €CØ�7‰7�:ÔØ�‰Ð.Ô/Ø‡x�x�Ó˜ZÒ'°·±¸
Ô0CØ�‰Ð8Ô9Ø€Kùò ?s
   ‰	E“Ec                 óF  — t        |«      }|rt        |j                  d«      › d|› �«      ‚t        | |«      }t	        j
                  t        j                  j                  |«      d¬«       t        |d«      j                  t        j                  |dd¬«      d	z   «       |S )
Nr   z: T)Úexist_okÚwr7   F)Úindentr$   ú
)rN   Ú
ValueErrorr/   rB   r<   Úmakedirsr=   ÚdirnameÚopenÚwriter%   r&   )r?   r2   rL   Úps       r(   rX   rX   /   s   € Ü�D‹>€DÙÜ˜DŸH™H T›NÐ+¨2¨d¨VÐ4Ó5Ð5Ü��dÓ€AÜ‡K�K”—‘—‘ Ó"¨TÕ2ÜˆˆCƒL×Ñ”t—z‘z $¨q¸uÔEÈÑLÔMØ€Hr*   c                 óV  — i }t        j                   t        j                  j                  | ddd«      d¬«      D ]D  }t	        j
                  t        |«      «      }|j                  |d   g «      j                  |«       ŒF |j                  «       D ]  }|j                  d„ ¬«       Œ |S )	z+{id: [card v1, v2, ...]} sorted by version.r8   z**zv*.jsonT)Ú	recursiver   c                 ó   — | d   S )Nr   © )Úcs    r(   ú<lambda>zload_all.<locals>.<lambda>@   s
   € ˜Q˜y™\€ r*   )Úkey)Úglobr<   r=   r>   r%   ÚloadrW   Ú
setdefaultrJ   ÚvaluesÚsort)r?   ÚoutrY   r^   r:   s        r(   Úload_allrg   9   sŽ   € à
€CÜ�Y‰Y”r—w‘w—|‘| D¨'°4¸ÓCÈtÔTò .ˆÜ�I‰I”d˜1“gÓˆØ�‰�q˜‘w Ó#×*Ñ*¨1Õ-ð.ð �Z‰Z‹\ò +ˆØ	�‰Ñ)ˆÕ*ð+à€Jr*   c                 ó¾   — | D �cg c]  }|j                  d«      sŒ|‘Œ }}|r|d   S | D �cg c]  }|j                  d«      dvsŒ|‘Œ }}|xs | d   S c c}w c c}w )zÜThe version games get (the index row): the one marked `active`, else the newest that is not a draft or withdrawn.
    A lighter copy is written as a draft, so it never reaches a game until someone presses 'Use in games'.Úactiveéÿÿÿÿr   )r   r   )r/   )Úversionsr^   ÚmarkedÚreals       r(   ri   ri   D   sl   € ð "Ö5�A Q§U¡U¨8¥_ŠaÐ5€FÐ5ÙØ�b‰zÐØÖR�! 1§5¡5¨£?Ð:QÒ#QŠAÐR€DÐRØÒ�H˜bÑ!Ð!ùò	 6ùò Ss   …AœA­AÁAc           	      ó    — t         D �cg c]:  }t        | j                  |«      «      t        |j                  |«      «      k7  sŒ9|‘Œ< c}S c c}w )N)ÚBREAKINGr)   r/   )ÚoldÚnewr3   s      r(   Úbreaking_changerr   N   s7   € ÜÖR�!¤9¨S¯W©W°Q«ZÓ#8¼IÀcÇgÁgÈaÃjÓ<QÓ#QŠAÒRÐRùÒRs   ‰:AÁA)Ú__doc__ra   r,   r%   r<   r.   rH   rK   ro   r)   r4   rB   rN   rX   rg   ri   rr   r]   r*   r(   ú<module>rt      sV   ðñ÷
 × ð(€ð6€à	C€à@€òTòiòZò
ò"òò"óSr*   