From 244abdf98346d8eddb5b87fc08b54df433202801 Mon Sep 17 00:00:00 2001
From: bntvllnt <32437578+bntvllnt@users.noreply.github.com>
Date: Sun, 27 Sep 2026 19:49:40 +0200
Subject: [PATCH] feat: use the vllnt logo as the Claude plugin icon
(0.1.0-canary.4)
Claude-Session: https://claude.ai/code/session_01QibzbuYP9NMPNKJdURfxfE
---
CHANGELOG.md | 4 ++++
README.md | 2 +-
VERSION | 2 +-
assets/claude-icon.svg | 10 ----------
assets/vllnt-logo.png | Bin 0 -> 21408 bytes
plugins/claude/.claude-plugin/icon.svg | 11 +----------
plugins/claude/.claude-plugin/plugin.json | 2 +-
plugins/claude/SOURCE.json | 4 ++--
plugins/codex/SOURCE.json | 2 +-
plugins/codex/plugin.json | 2 +-
plugins/cursor/.cursor-plugin/plugin.json | 2 +-
plugins/cursor/SOURCE.json | 2 +-
scripts/sync.py | 19 +++++++++++++++++--
tests/test_sync.py | 9 +++++++++
14 files changed, 40 insertions(+), 31 deletions(-)
delete mode 100644 assets/claude-icon.svg
create mode 100644 assets/vllnt-logo.png
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1e1b322..7207dd1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+## 0.1.0-canary.4
+
+- Use the vllnt logo as the Claude plugin icon: `assets/vllnt-logo.png` is wrapped by the generator into `.claude-plugin/icon.svg`.
+
- Remove distribution version numbers from the README so routine version bumps need no README edits; `VERSION` and this changelog remain the version records.
- Record the `v0.1.0-canary.3` GitHub prerelease.
diff --git a/README.md b/README.md
index 81ea789..d89b144 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ Then start a new chat and invoke a namespaced skill such as `/vstack:plan-work`.
| `upstream.lock.json` | Trusted upstream repository and immutable commit |
| `VERSION` | Shared distribution version |
| `scripts/sync.py` | Standard-library generator and read-only drift check |
-| `assets/claude-icon.svg` | Claude plugin icon, copied into the Claude package as `.claude-plugin/icon.svg` |
+| `assets/vllnt-logo.png` | vllnt logo; the generator wraps it as the Claude package's `.claude-plugin/icon.svg` |
| `plugins/claude/` | Generated Claude Code native plugin |
| `plugins/codex/` | Generated portable Agent Plugin for Codex |
| `plugins/cursor/` | Generated Cursor native plugin and principles rule |
diff --git a/VERSION b/VERSION
index 6cf7a46..cc9a41d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.0-canary.3
+0.1.0-canary.4
diff --git a/assets/claude-icon.svg b/assets/claude-icon.svg
deleted file mode 100644
index 1f4882c..0000000
--- a/assets/claude-icon.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-
diff --git a/assets/vllnt-logo.png b/assets/vllnt-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..10b7149ac2eca1c97c8c58f9200d8cd92b74b117
GIT binary patch
literal 21408
zcmeHvg;!N=w=XINDk3Ea3MwffAl)L;-QC@Sbc-M%NQZQHry?Opcc*|L9nxKQuJ`-S
zch0^4!5!l`hQpz5*4}$P&ok$*=JJ=86hgmEa2o{$1zkk=jVubvl`iD>tsC$!%9Al4
zQBdTJMBebpJI1e1p~>SY9q?|c4SU|YmF?&0M}YqO>Wkln+gS`xzcx3$!TyuY&`B!z
zi;)pPK1q
zw@W^i-O4?YsnVpaqVW?Zhc~Aemao17e==Xeg1>rVhS0;`0zJLaP*Ai{NyXuRNS^3i
zMM1&8f`*NP^5d3p4E&Set437#(X0RaBmaBH{&&Otzvm^}&-n8|kZ10~pFjLWL`1Sb
zKcZjfyFdST>ieCC4xC38j3($aFM&dp_DuY0n}N(}cj
zrl_c>+HAD22BY?5HP5S%=iuu_>q$&jR@Sdvg}nMbYzf}d^706H1?^gZ$w^E>L4kUa
zCO02;o>n~%v&q1G=w&pyM67ggBDc@-vT+9Q4aXa(&%z=tQRNGIc`xG$SS`E4)g2wb
zvb|drzkU05>SIoOVYnKu3eC%xVK?sLKhdgp*ZB4AT~^Q7$^P1L&Ft*#4%{E_t*y6q
zpB~W4`}p{f20Sw`G7>9Lt-#8XN|Lmy+5Xt0?C8iQ5zFMST472?t5W(VAD@uJma;&r
zK9O8J=2cPc0m00DjcQx}`1tsvO`Xk>F+43-zBm?()O(LPLR1Sz9^ScocYc?}xX;tD
zD<);HRl71%{7Y(`{YLESkN4O1R`ZIm*7&(y4(1soX7t?x$;6{5nca3PMm4di4@$1z
zdC&&C09%<@walG!h?Q-@Hu8
z1W`OXO;Q&Z7pIfG71>}SZh5$U@@oM>kJx3K7dHkn?o58qlFO3xuXQ<$g0=1yjBA8l
z;G_;9D@yfR3joH;yMHyNic)=c3IPjmZjwj
z!i7&X&nr!b0~#9}%Na&kRfs1mE#l%66JHpgED903kt(d~Wl1Ka@?M^WD-(wqs2CBu
zh+qD33k-U)ySwYNbDr)>tml7lcD&1>7t3RRw58MD-!C)NBp8U_5S?>&DJCi!5D^(k
z=DyW%bFZBuiSkV3l>&bw6JG+SgCQY)7^y!Im!mWTxqyIx|APk)B9fBm?sz@ndeOon
zFDWT0Yj4jo*(W0@d5@iq?fxWXsWR-Lw()V5j^188>XxyhY`Ls^Gt0leJ8aT191KrP
z#9H(n34W?j!PXn|3$w@%`1I+x6hFXZqGL{}NHg+aW74~xez+0XA&N}%ai__t6
z@v(pgQWZMkz!?zos3@7Q3}mdrNs##*6qGSPuiw$pk*e4FS;YKW%d{S0T1*T+Qe})`
z4RIbnrd|7FvKaLF^P=zYtA}o<2L>WO6k=9ZRs_86TvEd3=~*jr`N0X?E{ZQ^Snc*p
zyu7Ze4EpZvm$V}1VeGSVv%72^amm-Zm`vnV2ch_<;{lg+u%RQyN*}SkeIsZlj^;5I%H&
z>RUM0T{;3*o~Rp77YVQ5V>mcAG&0)V{BFOITNeCq)gzW?ac!+r=+nZf
zNHdQiWsCWA&6h)7iS=2@=fNfyT4OtGoSfmGKHZTj)mEj6utbrsCE|AWqiH`rIT5A#
z))mhl&U3oX$j-zhule1+V0m`70mIjAe^}{^YJ6j|YAw*DFpS&%>}xrcu5R2wT^*gL
z_1DQ58RbmJOEcK?TJCl$1bFx-uvvR)k;Nq>bQgsc;Jd69RHc7=w-ms~$0u9we%=J%
zaxgcorQBe>hX>yvYo`WT-iFY-rJhI%iP)y1FgJMD#N5jg
zo{?|wj8fpty*`FR6kKw7MN3NyX(!aQw7AroWO*tNx-Z4x{>@|X9KC8$D9uD8&P6-f
z^tkNoT~n`fRnfoPay!{eDbZ^U(D-hTtL3u6%(J?8c!)Vryr%}^a_lhTQD69lG
zFX3Iy;lWe$SD~a!vS~Y==}U>E~T`!w@1n%
z67~iF)gptLnOXbbpd1s93$$LRd}xq+jd$q$XuhymO~*sCJ96FL-aaz|xX=_BcsIvs
zcTu-F=E<%3g@uf2yS1o%>K0ApJaan}5)$fex;Qy)^Q+}cn3w;apC>Jr`BY!eTOStH
zk1HlD{Ck&!jcrQ?g;H;t*S{Pj%B-Pf7)fU|7iP<50toV{>@mP7D1hb)1*Qk
z@-vK0{?^Zr2gh59MlZ+KA|fK{_riDF0xSH_YYL%2lzauy#nN&@?NSd7QB#wsUMoDv
zKJwyG^6D%i+ACjKetLIay@rFS;;y}z2U~t
zT>}ev_VF)3tGfQSo}NWCe+!zEgN@E!z8g1heyY|*I`wAV>1PX+>l!7`Czr^ER>%ZZ&7>=a!PRPJYDxq45}nwYmg~090P%-$z^8Z{8ym;B
zI;W=-4>8dHg`d)P+~kyq-`Uv>A3Sw)Tem(B-e-u)ralPYIj5wflN!Mr++!G--a)!s
z;;+ujdSzAB9fR$I1H~N@Pa{;k^O$640mwnjPEPh57#J9W5=Rvk2vB=DQb}_*x~Z&o
z4hke1RixAf~uw2R&d2f$Is
z8`j(A-Mese3ybD}5`Y3bJ1#vvJv(s!yaN~j*|)c}2-;d(&sGH%v*6+4w!_t)5k4*s
zBAPTaBFuuG>2DE&%GdWWPvd)K@)xBH*?uYB^CniyyQkmE%b9rQ42#0U!sg*!)CErO
zLM7V`bI2$DJ67_ceiRBNQX*czdE@Fn
zQ3mhHHf7QTpP$S8V0@zYvS4Mmmp8h~eEb<;Wz9qui&)piu7^%%N83ByajY2t7TZpW
z(S3Nnef#FD7m169m&F?O<;$^r2^3NU^$gbWy#4L@tISAhV=YH6i|T^?%j#aR#~J_T
zlFj9XTWyKacxz%M@xuU(8b=u`8VU-b?cOVL!%}RdW?l#D<0Jw?LU#aOgu@apceBn!
zm<{I&@cZ72jAJ&-1PC?hGLltZzNf+*9sO{yRXXl&Gc1eA-g5uMsKrFNOm94U8CHR}
z(T2(agUEmfde7iN$=R7}ErZ1H6M9-`l9Vhgid~(ZB)q)5I&l1k%1z{Sj<#kI2w7=0
zGfiWeX>V(*-zjDO=DdeGn2(}WGd=xQQBg6J!hh3%@Hz@J7FH%&2OKEhDjORcN)8Uy
zY9JCEw6sCGy1M!|Z{95X%DWDHvE1d*^7h@kH~`JN*WMQ@mw0h;b2r01r<~$K$$lR~
zFVP1Z)alAqme`4EJ8D1-N_HoECKu|B!Mqn^G(5YopWNd-1z*4R0@#U-^4lc&?R&J<
ziHbb=dUrPlc;B=0!#`us)l`LcY0vKjQOScn>tE1hatlRJ?ny5`^4nrU_ARfgahp4tCTG-_otoEi7-DM
z85yZTVIkCzif5B4E-6Vd?2gUR)ze!6X2f5A)05&OW+s|ymF43i)3ESxl6wS9eq+LB
z%>lT&OFaoI0P_tQN;}%xLZp&-X!kZIqbDjYsL9F5`kO!D<+vRF9mtf3YXUAqHT4E1
zTcXUuU|`O-;LVDqDu+!ng!*qwtLT
zDJ{TmKf2nzuz~Jto&>i@#IbR(vH78e$&{sA!`+0pj8m4CZLF`fm{eR@OIzv%g#P
zyLay%$C623@_P<$ZjB{&NtLMMv@qL};$m$QRrkxR7l1Doch{)#pysrA_`ZN&5wWo+
zO$-NBro*|-Nu6yI3o9$_GrgUiatMzuFD*@tq*mIwZewS+fPul|xRu;9b3NF`-kux-
z1LNZD4iL=#{k75KlT+j-^0=M&g^{k*Vx5|t;;-?;+H#zZ{W&4#rU{}5sBXRa@dWeq
zJ5VbQJu)&foQDr{7^9Msil!^fqE*!Cv@LPyj6ba$OGv5VbHb;$$}ff8zSjaLJCW)E
zCZ^7o)kj}nv(a|ItW-&C)~~mFGc(2E%ZGpX@F63VL`W1A2qm)-Ed<7V{mQl<@m#KB
zufQSWBqn9%y!@P!nOR}G_v+wo!du}7U9$T6=?C;1@a2sE{`%Izl6}KJD9E7wwefH+
zZtZRlXK7pn7z_4!0Ru3wK@2(2im-gp{aMZ@lrwXrE>(`~wi5P=yvWo7*O
zSQa=fE13!|U%q^K4Lz0Fd`#N$e1Ej!`h`#+eo9AI7wNm_TNsNs;inZ%O>;S3ypTNQ
z;N?x~N#LZQp2#Lh2Gmyb^^(}*j1SHjc6aR$-WUv0ae6VJI{Im%!*FPTT}lqbGMiEI
z@FW7EO*zfQ?gKFKAR{Yl*TqdLfrG5da!U2&cqu6Z`1JtjE%UG<+F94cvHt!7xng{7szwW4~-8Q0w)d1>h%LK2#qngc2PzVsZAEeTiSH#5Mj9F(9zGy}>PQ{}9~n-t@#fF+s;Vp~Kh%@S1aIC&uD6F%_&{Tg7|VA3
zH_EBReg@JHs;_dTC^^pBRC%~M61lrD>-}VV05DA5;7S-Io}(U
z!V(LE_LF9F{lZ%KfjCx=j#pHjYTRCN=3<#_mgHlWXZ_zoD=I5TIFo{cf~Lp*+`D7{
z_m|4v!9gal|G@xU>LV9Kplb;xmP&Fvc)0QF+u#w@TXuGKq}M2b9CS3?vb)%wHuc@1
z^Ym~tTCqSiBbLb|Y}$#ImUh48uG>hYLY^XREd&2~+wic0yYf3il;+Xypx|H(DXi+d
zk2xYh{3~KqR9DY;_@Jn&DhfwmVL~zpfRQQGi5_Klcb@U_@s&UgIPYq2HSqYa&kPO>
zIPzKc6+i{G-I*7uwPqO@icY@UjPSir*}Qi?x>u#RM?^;pH8eErB=ddn2GD{ajJL2?
zQ2CPK3#I<3{?c%3unSpZsp?|V6gr(!)HIAw+1jI%#mbYP&}Pm0v|T+tqe8~49J#b
zXZy{RHeoHo-y5-^0>$$V9-T<%wg*n78XXzQYtPgI(H2{>J6*;Sh6klEcB0eQYiQtGaxJ9^f3jS!U2MNGab^VA*sdkN
zpx`+tr`l4@N71owU%yI2iR+0;k#*mzKS`0*(Mjncp)s#R$YE$`XlhgM{(t)CbR3!Twsden;f(r52}$h(n03cFqa
z932gsbQF`+y>G6^FS`>sl~xS79iU&9>-@Y?M^vc(O*d*y`}dFcXCY~VupmQ#&6wIJ
za)6c(YyQ|htiMcH9m*m3gGQEo=N^TpqPclKJ}z!^@3^KXJNQ*@J|4z9Y}gq^yTiFzL-OtW_dHFf1zdNrW{`0rEj1%|
zwzhuv3Qbj*;T@lzhDS$7)4Lp)$Fjf69FX{6dV@s#=o6e#J9YJVdnRjug6=$nzevf+
zMPm~>09tc6{EZ(E;`%Sx>j3+vfDHCm_+-B!N!QL&2O$Xjy>d|z5tI`zvfXibUj*hj
zi^E-s^aW((21Jk+M6*N>E6F8#Mn=YpwUjds`YgD&Qb^ycSR>`&h)r5^`Bfcm_M5%y
z+Rb~}@G7!{a{y=afT=9*F3~eYCW%{0VJ2!q;T{H&DU7*jYHDiOs{XvPG)UGnG7{Hh
z3!R&vPZQ2TLwNuGlku@JX-msOdZ5Ss9UY?LQc_CQD$?j*#It-m
zIzelN0xfg+cWNbEiYN5W?b`^t-dl{b>JY8kZ~`qGAw@x~(@(lN-a0r$UmW*(#CAIa
z-zKW>johFI(Lz-pEkmWuFc&=9)k41{{Os!KiGuTT6m6$1i9N}8bTDZ(9BXF-$XMi^R%TAZ
zPe8abS(%wToAscDI-MSDOf0mpi;FK%z<#H7aB!&fEg1RbYXWx;D6(R;N^b&Xzz{(2
zI-)MS$Djw@0eN!bXRkTMGjj44QVgM``FX$CJe@y({$#+Brk*0rZo%oDh{+uts&RU!
zIV`X{(b_8XG7HmCR#x_*+Fz(qCZq3bYiph1&;)p}^qQTV?e-p5e|6d=FS1Q}h*k8p6(Yh~ZUJt$2{
z8dX}Wpen{pOOjgre1nf4XNnT!F-hhw?)vRg_%m?#o
zuUxwk0@&o>-QSUdxPz;7;Iv&ZKY#B3Lj7xU0tJ-NgqRrPtwU8+)zzSfxtnSaKc1j*
zXG+iAB4AMf8iMpep+LWwhMiVhlA8LgmVt#p=43Y~7ok)(u%m`!
zM+sTXL%!RtG}d3jj@m1P+De44UiI;WUsE%&!6_*!#r+xYqTf|QzWTiZF>{Rw#6vQ~
zUfTp-9eRF#J}l}X8I#-V{Vrw;52UbkCtWmbTwJodkJv&c%1zSTdcl{OD$x@wMQ8c=s$1-J}}`UyZNOhIe_?fE#NF9mR2x#@?LCX*d6bN(=ip_2@#;VPROg0F}v93*u7TQ%%AnBO`m1<>hg}11qyq02=`J
zC)@3ts>^q^aWpCfu3fz_5A
zh8`$X%1A$FU|_IucIF^vDGid$uWG`F;Lydi~ZE(;2iiX!V(
z$47y8e^BzC?}eXDIn0OvY{3!?CXz7fi4XnY<<<7{C;$F{7~S(JF2~!jVzO0cqo2Vc
z5Q~1Hft4i@*J3p{Q}0nfAaN}_3UE3lhS?|6)6Sn0sU0l0shZ(Fl~+^@*IAC_k28J~
z!ulcqJA?+`0J_^=ug66=78aJ{w{lNU6ow~HJV7Qoasf$634olp^WJj9rw4nh!=Ef?
z>Lij}chG>1g^%k?9<}l=>kN~-|J?y!
zNTyl@WjJiBSdhq*5A?hF#YI8zMQq&N>-y3~urJ)Ltr>ELO+WbLGB=OgMaJtfu$0WC
zb%NM%G&3S_A2rNiYHCzE@WMe@#ma;WWIvG7#Fu)~Nk#Uc@(Tkv!5KdT2w85wq3Q%D
zg2{e;j9~vL4~mg29A2k}eK5c@P5S_*NWqKKp^UA>OW_Epgpt;Eni`*%)XQDazx6rZ
zJMih)!(Id*3K2UT-Kt#W&eWyUCPW-RM$2+a>{?X>w{ztl~~ic{$I+wP~B3}!a^
zVUoxLF=jIEOEyySA)+D!uS}uN@Gme0d1$j_L)|_U!1hoQUjY!w0Y&@l7_na)%S{H2
zw|+O^5DRH14Z$cjEsyZE2b?ROftm5;gYF4KbQpi{u1O$BB8P0{*YecdOtU(>uyk-l$5l-
zzD~3GZ<&mzBhb$;Wa`(i2+L>7zh`GtMgnQBUAxu{yEpW+k=9jw0Onh$G_fF52(nz}F+2#I@mt}3ikw|%?&1?r8ice1e0;B{SF)^_UfyKc=gai!TXCu9`
zg_@tAe`J9Vs9=Y>sODMk7e-$)DW}D*F9V}m9tF0$uYzGCl(>c-!&wI*=<4n6pV)kj
zsE$_wTbzaD*VotI2X7TTE}$JDS*6n-HdhVALAdK-boZva;xMfp&8@t2}V{Q!&t
z-w-;POBmp`<&BMQv1|WW;geSNIycK>0pv%YHREaBG7l*R2RXpsKjrdliC2{Mjw$}x
zhihC{`0kITzo4QD!+6X=3VvT7i0F>}JK+3g#NBj$#OtoUJe-FI6)U3dY)34S#?8%5
zh7~XI78bdDY(~ZcEQDaJH}NyU6Nb7KW3fqc9xuC9=&iB~U?YcY!9a1o@}Vc7IISH?pv>(Cz61j}Qd-mgSUgenyShTdt#jnP1C}Kv@
zUmjG|n`mJ?Vv~OIY`FenpHA~icJ&ulDwubOKW3oA2!JFJSyc|eEK50hcg~ay+4K)Kut*o?{+0HGAe2(
z&u5>Z{PW9~FYkWVOd5ex)dn`p0L>D}L_;9I^fwp8-_`1tn+j3z{-f=df~
z73M%>#p|Fm0%C6rAnoc}xVZ|Tlt{~GF(}BQ!Hoq(ccBn=;gCxSP*T5WJdr1nJv$y`
zPT5zlP!ibReFT4>@&OLct#w8!T3RwVMd8QV@O{W4w0dBD0TvFvpe8i9D*pgEvk3{0
zL6MT9qNe_Hz2FPDcad5h^}uJqjhCtRH(Z0r3Vem|ANIzG@^%qo22K$Vcc&M2ubQZ6
z2T5l;dACjJinR|7O5l4~{Y(&CW@au!>ky-(J%Xi;dDtJDqUm^dNldRLFa><$kni6)
z=}7yb!G=$SqTRdqV7%vxAv@?^y}{1LQOqB)4K#2*6DkaJk>;{zZm1OX~((1j)7Xlf@7gS1mkc9U?hu$~pmEJDRQ`kBJ)b0>s8g{m!vUZI&ZAe9SHjnFh9
zmt*m-3^BZY*eJuLG@WUJL1CW)0_Nd1c0ioU00g-+H@AO4K8SUf@(ko8B>YzSU%wvZ
z=t8lC)L5DPMJ=@CNRv7bNXR6f8eu(rcr3q$7+qHDaG;&_g4KkaoSbefG3!G!4z9Ua
zP76+l-g9vd_w5CujzHIr0$)>eBvs(fH;DU`1_uZK%9J1+@9vh6J-NIl*PTS)=uP$W
zV4l@tVz12wUP}%^Lk1R>s2RLbNGcp}RLwka-d`m{Ctwl=6{xu3HVwRG`sRo)$ho!5
zV(86G+YmQd3*>g(@(jjFVnT#V1oAUC*M2#ib}5>8U_t*+K|8wsy4twVd!)6G1B$?G
z@M{+W+#*}Ijfzp!Za-#D&bY>(KaUTcZyUsP;Wi{cidXV7Dg?(@DH8gv4%!vaOi!{+1Qlvxt+_~*N@ABjyCHrdwOSq<4QJT
z8LO*5>IRZfbS*pn4&Do{Qp?~+?2SVCA8w$_R-0&(gGG_}4epyPAZl;GF1xc8}wf!qo~6#RT#h=lA5UisVSH(At3?r>TDo282EUoV|!~$
zI#R0&Oog+z7jUCLoVw0_dqwfV=r1^)XQJc4t3)WI64Svr83eonrm-ZG?Xq+@J87Pd
ziHQir7e+NjIc(;IFZ^h;YXa7yR)A=???25>456R>0)dx>g+0cGriX
z+N85iJMwdG0-;V%PJYtS-kviQnrKyb{4t4oqc7zjpn~{bbgI204M?#pduj*pW=vRR
z=GZ_6$3P@(?=K3MH&qx=f`0U0GSVafzt-#LrQ9
zfZw!FOjHl76di1vPg|$0IasYI!iYEcjBJ1}XM@OSgM+*zg(-N6|adWcsl3_2gwE=`-}0>adK@o&JT{8Fu0`~3v$s*CeY52e*#YOh~kr3(y+
zj~9o0`q{yqgGlhIzZPO7=RVQ#N>#Q|FEb1}uzUNq80;gXuqy4l`1HR+f2JY%*Sp+h
zgUZCNTknsyTZzNLm&{kpJ5EssHS6L`n1X^LTs;~^^v7Qc%8se2gwK!IpS73Ll=d(F
z^qQCh?x1oNd=7;GGGV^^N4Sl!bRZp3z}ju=-h(3`b?(9o&i`>+C`luzaVxNXHpa%3
z9&F{50p{}5%PuIaC|nOo#ib*_OQ_U7hVLl#Zn10DmjdJ=$A%payVaO3nGnFq{Xobe
zHRkm4yY-(Ny!C95jzYrJQf|rzgHpV>AoryM9rQ;u93YBlG-ze@GSbr8FV`?$nH(8;
znZ76Mfy&hxJDRClTm$JEuMZ!Hzg;psdzLD@L@yLf)E#aJ?9}aaqpC@;0REll}%vyF6M%423KNvSl6wcN2f2N!vl2!5RK)t*7a&QJ}cX9|;F!P9%&h6!!1)
zsT!*Naib*vRLTJ$QcmnuU|8;k8h~iNGS~bGZYb34amkOXQ15FRCFSKK=2urcE=S-9
z@lAq%tDfd9Zb2Le)xKE>)74Un#4!|L
zzt+~5q8{ak4t3zJn<2{ZV`LYD%0R$u8len6hf<;XEVKBE2VPqn7%uk#K4m#*M(Kl$
zsUI32Ps3_9vhLqYohyH0h6+m0PW4ydIA{9+%7|~HqesFb2>>XBeCL83MHd7uLV!O1
zURV&ol`4aM#yh;}s(5$!&;Y!r71#yCb?&f!CV&FYPGPk~*n&_+UpJx(;68W|0Oeq$
z?uF7lDK49NzXqqW($Z|c4>wNSiyCA|#ri5thX)>tiHKnC;Szal{eC}vJhnLm38o0c
z-o*2^8y-+1QtPg6DKz&v)8lluwLO6@mcStLQr)7rk3*M}9bzf{oSTh4cNXACm^mnd
zs{G?lA+NVSTEOd@sE+p_S2ogBQCccn78;caar>u@m-6{lonZ#BeiNgkc+A#(*5FL`
zhJpm2CKN36dCHXN+Ko%OlIg!-Rta!b-^sm3D(<=TDvZ>k`xm@or$0Q?^6yPz*JMD{
zK>_>rppazLgZ=T^)s+j@;2s+GZ+30MOGIH&mXW&=Tx$qZ8_>`yo(4SA5{k{URiMHJ
zu0v3heEYW(qHEk6yW!CuMplEW4F%cpss^NBmY0_)A?i%Lv_y0QP^BOjeA0T|n4m@o
z0#gVI3WkB%J%ahK_k!t?^zA>byrtWl(D!FuXuHIlciscY*H5!C&wFLP?2XdYVh
zN_QfCG@aIq(tbH@?PN%F3Bda`ZnyYCX?(TNc@q>;U&OlsF|80#9*nd(5{(%n0y*^Y
zgLRd}N53!4rfZH#dN<8MNf4Zowm`I`n^chjN({1j!!@62&Nt_XOCUUogNy64`wj!i
zlTgXvAQp;iLKirD_)Nz4A)BE6`28G=NhPL%a2u15Ww}J4N?2N2T2BHGI0~W?62qt8H`dqp
zMpS5DyjZleu>0>&kPttEgqOY+)E0>avw2lzWj|2)(!m_ta54AZ2a4GVHSp}v4!DzA
z%msvUQ(=SVz{MQbp?nTNh&j=b8$aNo>P^sb5N~%n!GeD+1vY6kFGPZuijb@ZBGWW4
zuguc2t{Wke1L(M-!u$C!_V{ypa6J1DQnf%c7mQc;NJm
zneo3q82US%=<8h=PzBY@(+IG!f3lV$(EX0r58}|_S{H|gK5RPEXO-`y
z-PvK;j?ewfRlwXF1|5N>->;NrSLl7o{0VqITLaF_Xlj)Z`#=jLl>sS3+Fd1gGOZ28
zR>n2v6Iys7fF_YdUXKfs&FeRAbx5Wu$h*U`h!Pd&GHEppdd`>rnNEXwQ$*JX~J-jcC18pr6^cA$!>;kpv|3eqc0hn(*VghE*I_(M4icbpQ`(rCK_
z+n#WNnyZ5Ir%>58p6G>{p&_{x6Yi%<;AXOrc~eZyi8KU?0Zn-1g|UR@1A4lEB;jUn
zkx^)URGUD`G%jjEU6ekpeXg;GO+<9jR(g4|R%C-rG91Er4g;Ys_k4U*(?ufT%ac}h+iAYT)^J|R
zOJdc_YjrVCVr%~WsgVkRh_1wSlO=jLr6NF5$5kv;7lDB`2FE(FaPvJ(fpZPe@fLFy
z8F9*r>D7J0Xrp0vOij{svXb^XDykpsbCgz;t=@kC(%$wPQ)87R7DMC5
z#-=r^ddA$v3CTc2H02x+C)Yry6OWiUIL{zuLhhgKm?DBB;Pg+v7Bt<(L*sk+^sheq
z`}aqwsKF@331YSI{w@Cf=N@%SOUr5yh%>wjG<0;m+AdTi&!3A}t(#yxB~%5kk&Awe
zh=1)V1b&IwZPK{_;*JBN_2@;E1m;t&g!uR&(L+}8m^}%~x_iTkq#~edl5ea*Olr3X
zNV6;_2S@4bJ>s2ms~OFF7|U84lUG(2jy=V@Yt&^VxmuL1R{g0J%Im
zAqx(K6JCS$Iw$pGYi9=wLaZ6KgD5{>9`AL~62Jt2oTGJMSC*u1TtOKG-++0qTl#-~a{o^-@6K)Z*il~$;!If66xF*ZT-aZiZ<^*qc@=}-
z(b(A7*FnQWqCdt424tC8S=3WZDD-^z@W%VdKmss}++LnjaW2QLC-qh($eaR*FI4||
zQH4=2Q9Fpi@r*|IAnGCa<_#)z;|}QTEbT&`S3FBW$ssUdjMWH>`zSG_vpPXso&-ieJgnAbsmpl%JJWgb
zY6bQm*qqD&!BOO&i-bAmGy-`Rq@tuuR;#iMg;Hp{-1n4JJiA|dugPKb|6CrTh3;(j;L!}h1kvq#_cDP3>GY=xu=)Pi^<{8!K$1D*5eL=X
zbgH^yK;mjP7GOx}3>c=M1e5~Ql>%`iHQkR5qS%mVDr`SbQNViP^ANkHFO*%OGg_UW
zPiKYVdMwZ2W~Y*Om9TjQypUaaIE$V^Pl#K8{sceSi?n+UOin~UPjBtHB^@-IN=*Nc
z3G)XgZk)=Xb+tiQ1n0qn7A-gxoe)6o-H4A(dA-GqcooC&f4NBP61>X{FxNB?qUi$)
z0|BRf{t0xTT%&zAuGF}^q`=bq(|HU;e~3W8l?KYcN>5T2Fp1Zoc4
z)V??x#+NVmE~b&HrI4SVJ}(k``DSNlXAjAuB~iiFD>eX*UL4>CqfF_lI0D-RRnu6|
zeR2RP*+@%=ghWO*C&}f8#>G+pov7%{UbvE72)94n78JKS#^trOJV^6c23k+Y)1|&X9Zn87qUQ^no
zq~(@z8}@xI;(!92A*;03ssry}MUWZ@?B?Ch!3~D`@`D)GoKj#b}6Go0~tW3Mc2fv>}
z+9w=gbpIo|u!1J3ob=7iI>R!M@sQc?n{|U8
zXfI!(f8@5L7lEau;rqW*3|JK4)V+t<@pRi=Q>G|-=n#}opYmNm)B>4!j)ejzmb}yT
zg)svJdes&3t6bQ^G1>#jglj-h&@j<6aC?7abJfBsZt<7?JCxiET8VTLkDKxOSP3#(
zk5qqT(}}Q=-XS*`&Q(~2)0_*DhEB}@I3$01_3xsiD^#11&&~?)hCv4OXzmjo{7I2S
zDv}C1uC~x4aS&KyNI{0`hjjI6H5_h8Q70S6iTh+^kckB#f!kT&kPAwWi&V-!!lqw_
z&&+j0I{*?Ar2EVLA7&=#-A-&zU@`;Aea&vx1FiUqQ5FU(u?#|*ER1HDz;Cbb-@li;
z9@|($?5Rm`2h6x=p0h3fz?Tj4AjOF2kq}i{kH#0leCzBcomO2u%mY!w2fhPDA_IbY
zkdvHi2L(3-5{Id~he*04Au+LVmr9zSK_zOR+!P`Wkg~Z~Pbm`pPt64#*sew8Dz%nE
z7T3Qhh})d9uI{sq@iJdc$Jy%_9MsfelA@wmuCA`x5T87OneirAYtiS=pCidF*u9@*
zO-yp|A3Pv$&s4m5|M$}a;=mqsLnDB(HUKt!5G#6b!mMaJmllDF
z0QU(9D!u^cSOzlt3ZTchHj#;7fkE4b5nLBTDOF*wj~m4mI+jP
zAvOjK!yH(CB(pnFtaA+jVgMAOR;$PmgD>vq`$}b!Q41g@x5Lj5SyI69M1qnqAC!C_
z$>D>q+W~PxM9#_)2`7i46cWgK_yGqwgY?xK{SjZ{&FNY(FcC7L_I(1;`b;+mYL^@o
zoaM#EOxs-)ocEaIF&XLUq&l#*%R#~w0TpP;;N<8C0q*BBm*+|2ms;r=8ST)Q`|BiO
zb_`M~DaLUq5g*|v$yh{TR)`v=%437+9X6+Fks-T0{l||VFTg&G+t(R~E`J+r4;}zy
zqSda)rAXd6uiAFy8L%^d7&Bu%eOIHM*yS!o&?N_odc9B?NXWVn)e=kgA{9B~$^>T#
zJ^?&=VoOb5o+?t?z#v1H6C1WD?yzY^Y;Bh9DN2MV@+A;`;ojiPOcKO`j@$wvgO-F*&y2u%8#KFAqYzIzIkL_oPj*C!Y75Tr_8VH(y`pf4hX6n+Y9NNIQo
z$FW}-%(7&tv>)nFTMbtr1H1!t%Nsa!Hi$X$5I6~g
zd^2Uhvsxe)h8}JGU<%^N8KrH)eZCD3O#nfWl7hk)h)&KwOMqMi0vU7Adnids-)N_G
zK}1j*bUj|uQ>b05+&hg}rV6c8oshh?0-tgAm^k_nrr!>s9MGW<+UcU+TND*|
z^De>?^~bI~U|3N}$;`1a<$qG!Ak)9ym|(7UKj(mqUKkLA=Vkr!rlwTLgfiLfr!QW7
z4*rTHr9crdAfX+HkVq8hA~0U88sO)5p9zlp3J}o0lw;@}svmm#mR}
zlON`p5sVQmfTy>em2ekadN$|1>^=CjpFsRf1)aBTFiR?0@bjY_T{Ohkisi7&bp$s^
z2n;KomvJytuLMRT=IP!F2{Al$V0os#9x-iF0K;RQ510!%5N*+89gX`Ok>({p_Qi|u>b#LB#Bn{KRInZYj
zbkKywjB@5NCWe~*h
zMHisTFwJ=J7~=iiC1eRiQgM1P$2Op)8|wsmSeKCH`k{}vcc05i?p?@w
z?ocEwe}V{tg5mCMuUE0kkoWvC@fae6<|=c4{v5xofqs)}sDccP38tp|ml(J$B{(?d
zgHAmbdLtVJ4LjKjLc_-pDO&Kg0O@4~o?-y`yqCPK?Si`Ciu^fzs|hK8d`82-A$aNm
z98z32PywhUfTl^#86~-qBe@Wm;O&Zo$8W5Ibq>R=B!px;)Q-WAImyfPA*bJU=N4=O
z4J-4Je3hm}1B=ln*s_vEH9G-J1|2vTd$>`km-|H?n1s*GqB5Z1H$}-|>vcNA1Qbym
z*rMrsODNJ)5GVA!2PsVRA;c&^gCqyY>D81_z#*j#pc?P&>}($DX9qw691xI2fYL^h
zJbRW77tB#Mha0>DeC-XK_&Mlfwk^=#o0ed%Ft{9g%~QZ0#T69`OT3_*r9%n&1{E?F
zoV69`mdJy9Y+Dw4lX?X+8v%(*fK}i|$^r_x6SP692e2fEq*3z%GV=lipkTj&-AX30
zzBT)E?hakelQPtvsCO`7Yv@ry|H=uVHm>VlzYt8U#l2nVz&!?Ud!LAW=GN&0;f%tJfadJqcPOpWNM7_fg$5EMY3>
z^85Ac*SWqSbmgBB512vi*d)pD#bYc{mXQe!iHj41J-q0v`33$EU0*^nn5D%s28M>2
zEG_QDpYn!H-v_yZCtB2Yax=RSC=C^x#|0N$R0NrD)6md3W_$uD?Wh1r{GP?@>Fbk<
zCeRIgm~!7Ufs1Yc`TEQ|45EGEt^CyfHW)5(-O505+)am-Kso1Imy!$TV*bu$#}z;K57?G@T=nk_fEL@+S-^L7tZb6Hz#^@TebaYwKq&bUZwo
z`n)8!uAY9U0onY8xoX5o)=%fwrlzt31bH
zdG`A8pgw^_>X&zkg?UR|AC|Iv|2jP=8r`|DkA27b$zgP*x^M<&4(y?-vo70zzpOU0
zhfMBY`GmN*Jl+I|c-6AQQcj&a1Cg!XE$@OGIs6MAG@=4p4Y5&LFHosr2|+StC^9)E
zR35u9iQEmLfjAHWqCzS?VkM-cMuqJ;60{5<#rzN^&vL%Koo$?`{RW*$%Ox7NAM*mY
zN1a@i>|7>f2dxAMGv%zFOA3eZmF#D@Lac`1|zGng^sb%ckwoI;T&2(PqIqJYP8
z0Yfy7j*40>U^fs@YCHs&5Ua2O6j>wCY3SM6$DxmYPLKevxfiBV%koig%E`%DsQ6S`
za2^4}`wdzCgoTBL6UG%tyRC+XSeGH#aCi<#@kel=HR8CPcG79fKoUMVf1y=ZGqHKt
z=`!T7vhTd$#2HIVN9O>1MxO2!r3|eH#*wcCFMZ3hayv5deqi~lBn&2NSb!Ls6={4Q
zc?6s|pGXNH?BD6y$wV$En=L3TJzy)f_6W9$!pCEbNld(0P;Q5276(R3A!xB*-vLga
zg*(XsM-QKq6XsTopd1ike6v{)O#t?*uWM*%xS`w*^VxB5(=kA}*1W^+91WGVGHo2t
zDQB%_Zwc1XwFYkn$Vh4g8$mj@97Yk0A&$4Y3&0QEWJc
z--uB0?*Zi~4sHZ9)BruBbN708d)ULp#l?N&P*$cwU4RQ!+raagtajmc>J*Kdb*}Eg
zBK-5(!UvaiAFV7Z!Ld7lPx2G0TIGUM)ntLvR?u`wjhM>tXF~%Y6~#2NOoM}!L5c?N
zq+8@DsOBeEJUz9qzIsJ}<;jy6l>7I^QEnmsj*5+P)e8;fN(1Wu{`dbMx8(w!zj=9C
Zmpp-H{YrWQo@0q3A|Uyu@U^zr{{fu8zXt#S
literal 0
HcmV?d00001
diff --git a/plugins/claude/.claude-plugin/icon.svg b/plugins/claude/.claude-plugin/icon.svg
index 1f4882c..e112555 100644
--- a/plugins/claude/.claude-plugin/icon.svg
+++ b/plugins/claude/.claude-plugin/icon.svg
@@ -1,10 +1 @@
-
+
diff --git a/plugins/claude/.claude-plugin/plugin.json b/plugins/claude/.claude-plugin/plugin.json
index 204a497..8564a6a 100644
--- a/plugins/claude/.claude-plugin/plugin.json
+++ b/plugins/claude/.claude-plugin/plugin.json
@@ -13,5 +13,5 @@
"license": "MIT",
"name": "vstack",
"repository": "https://github.com/vllnt/stack",
- "version": "0.1.0-canary.3"
+ "version": "0.1.0-canary.4"
}
diff --git a/plugins/claude/SOURCE.json b/plugins/claude/SOURCE.json
index 7cf958e..29fb7a8 100644
--- a/plugins/claude/SOURCE.json
+++ b/plugins/claude/SOURCE.json
@@ -1,7 +1,7 @@
{
"files": {
- ".claude-plugin/icon.svg": "dc3b420724330eed1296c63c5c6d3290fa031d0eceb39180a2258f6992c76108",
- ".claude-plugin/plugin.json": "ff44d6e276f70392c84dcfa3cf86f33ce5001ab864781dae8adbadbc90102689",
+ ".claude-plugin/icon.svg": "0b4b639f6df841b4904ec0cd9f6d38131c6373ce4a52a1e7fe6452a37598d7f1",
+ ".claude-plugin/plugin.json": "4808262e4a7a3e327124bfd2b6e23590f33502b981cfcc4e893be02674ab4a53",
"LICENSE": "24ba061a4603738ddd5105ef4abc198eeded5ac7efce23b360561816f4dd6559",
"skills/build-landing-page/README.md": "46a280eadac8962180cf3f0c42eb0e845a3b0156a644569182d932881e1d51f8",
"skills/build-landing-page/SKILL.md": "b08e4963d6149f3647b28a0d9dccdc8793812abab95a1d081d93699e142de0f0",
diff --git a/plugins/codex/SOURCE.json b/plugins/codex/SOURCE.json
index ce064ad..f10d7d2 100644
--- a/plugins/codex/SOURCE.json
+++ b/plugins/codex/SOURCE.json
@@ -1,7 +1,7 @@
{
"files": {
"LICENSE": "24ba061a4603738ddd5105ef4abc198eeded5ac7efce23b360561816f4dd6559",
- "plugin.json": "aea0fdbea75ce7f02be70116bf560bcffc31258b6def32b79d302f2aee307dd4",
+ "plugin.json": "789b793f660535ffddadde5268e5d776ea9a76db6b4809014eb71537d877f235",
"skills/build-landing-page/README.md": "46a280eadac8962180cf3f0c42eb0e845a3b0156a644569182d932881e1d51f8",
"skills/build-landing-page/SKILL.md": "b08e4963d6149f3647b28a0d9dccdc8793812abab95a1d081d93699e142de0f0",
"skills/build-landing-page/references/copywriting-formulas.md": "6d19f6166e1badcfdda0af4f8b303160e94ee6e6149321157e12849654cc013e",
diff --git a/plugins/codex/plugin.json b/plugins/codex/plugin.json
index 9569b5b..ab43f83 100644
--- a/plugins/codex/plugin.json
+++ b/plugins/codex/plugin.json
@@ -6,5 +6,5 @@
"description": "Evidence-led engineering workflows to plan, build, review, and ship software with AI agents. Part of the vllnt universe: open, sovereign tools for freedom by design (vllnt.com).",
"license": "MIT",
"name": "vstack",
- "version": "0.1.0-canary.3"
+ "version": "0.1.0-canary.4"
}
diff --git a/plugins/cursor/.cursor-plugin/plugin.json b/plugins/cursor/.cursor-plugin/plugin.json
index d93bf60..8dcbac1 100644
--- a/plugins/cursor/.cursor-plugin/plugin.json
+++ b/plugins/cursor/.cursor-plugin/plugin.json
@@ -5,5 +5,5 @@
"description": "Evidence-led engineering workflows to plan, build, review, and ship software with AI agents. Part of the vllnt universe: open, sovereign tools for freedom by design (vllnt.com).",
"license": "MIT",
"name": "vstack",
- "version": "0.1.0-canary.3"
+ "version": "0.1.0-canary.4"
}
diff --git a/plugins/cursor/SOURCE.json b/plugins/cursor/SOURCE.json
index b2c3d24..2c247bb 100644
--- a/plugins/cursor/SOURCE.json
+++ b/plugins/cursor/SOURCE.json
@@ -1,6 +1,6 @@
{
"files": {
- ".cursor-plugin/plugin.json": "3fbf8954a01a9f6a73fec13119d07eaa08e465fb3ac59c27cf711685cdd860f3",
+ ".cursor-plugin/plugin.json": "b4325fd2a33221ef271b6b92d621c9c62052b6bd6f468b567d47401fe35ee2ea",
"LICENSE": "24ba061a4603738ddd5105ef4abc198eeded5ac7efce23b360561816f4dd6559",
"rules/vstack-principles.mdc": "5234bc0506e0a328d6163cd83785d2f37dd1fc23ef84287d71e03b92459e064a",
"skills/build-landing-page/README.md": "46a280eadac8962180cf3f0c42eb0e845a3b0156a644569182d932881e1d51f8",
diff --git a/scripts/sync.py b/scripts/sync.py
index 6320550..dd6dac1 100644
--- a/scripts/sync.py
+++ b/scripts/sync.py
@@ -3,6 +3,7 @@
from __future__ import annotations
import argparse
+import base64
import gzip
import hashlib
import io
@@ -12,6 +13,7 @@
import re
import selectors
import shutil
+import struct
import subprocess
import tarfile
import tempfile
@@ -24,7 +26,7 @@
HOMEPAGE = "https://vllnt.com"
DESCRIPTION = ("Evidence-led engineering workflows to plan, build, review, and ship software with AI agents. "
"Part of the vllnt universe: open, sovereign tools for freedom by design (vllnt.com).")
-CLAUDE_ICON = ROOT / "assets" / "claude-icon.svg"
+CLAUDE_ICON = ROOT / "assets" / "vllnt-logo.png"
HOSTS = ("claude", "codex", "cursor")
PRINCIPLES = tuple(f"vllnt-{name}-principles" for name in ("thinking", "orchestration", "collaboration"))
MAX_ARCHIVE = 32 * 1024 * 1024
@@ -217,6 +219,19 @@ def payload(files: dict[str, bytes]) -> tuple[dict[str, bytes], bytes]:
return skills, rule.encode()
+def icon_svg(png: bytes) -> bytes:
+ """Wrap a square PNG in the SVG file Claude's plugin directory looks for."""
+ if png[:8] != b"\x89PNG\r\n\x1a\n":
+ raise Invalid("Claude icon must be a PNG")
+ width, height = struct.unpack(">II", png[16:24])
+ if width != height or width < 128:
+ raise Invalid("Claude icon must be square and at least 128px")
+ data = base64.b64encode(png).decode()
+ return (f'\n').encode()
+
+
def build(files: dict[str, bytes], lock: dict, version: str) -> dict[str, bytes]:
if not re.fullmatch(r"\d+\.\d+\.\d+(?:-[a-zA-Z0-9.-]+)?", version):
raise Invalid("VERSION must contain a semantic version")
@@ -235,7 +250,7 @@ def build(files: dict[str, bytes], lock: dict, version: str) -> dict[str, bytes]
"cursor": ".cursor-plugin/plugin.json"}[host]
package = {**skills, "LICENSE": files["LICENSE"], manifest_path: encoded(manifest)}
if host == "claude":
- package[".claude-plugin/icon.svg"] = CLAUDE_ICON.read_bytes()
+ package[".claude-plugin/icon.svg"] = icon_svg(CLAUDE_ICON.read_bytes())
if host == "cursor":
package["rules/vstack-principles.mdc"] = rule
package["SOURCE.json"] = encoded({"upstream": lock, "files": {
diff --git a/tests/test_sync.py b/tests/test_sync.py
index 081f8b3..0f36d2c 100644
--- a/tests/test_sync.py
+++ b/tests/test_sync.py
@@ -4,6 +4,7 @@
import io
import json
from pathlib import Path
+import struct
import subprocess
import tarfile
import tempfile
@@ -54,6 +55,7 @@ def test_deterministic_standalone_packages_and_provenance(self):
self.assertEqual("rules/vstack-principles.mdc" in package, host == "cursor")
self.assertEqual(package["LICENSE"], files["LICENSE"])
self.assertEqual(".claude-plugin/icon.svg" in package, host == "claude")
+ self.assertIn(b"data:image/png;base64,", first["plugins/claude/.claude-plugin/icon.svg"])
claude = json.loads(first[".claude-plugin/marketplace.json"])
codex = json.loads(first[".agents/plugins/marketplace.json"])
cursor = json.loads(first[".cursor-plugin/marketplace.json"])
@@ -70,6 +72,13 @@ def test_deterministic_standalone_packages_and_provenance(self):
self.assertNotIn("repository", manifests["codex"])
self.assertNotIn("repository", manifests["cursor"])
+ def test_claude_icon_requires_square_png(self):
+ png = lambda w, h: b"\x89PNG\r\n\x1a\n" + b"\0\0\0\rIHDR" + struct.pack(">II", w, h)
+ self.assertIn(b'viewBox="0 0 256 256"', sync.icon_svg(png(256, 256)))
+ for bad in (png(256, 128), png(64, 64), b"" + bytes(32)):
+ with self.assertRaises(sync.Invalid):
+ sync.icon_svg(bad)
+
def test_added_and_removed_workflows(self):
files = source()
files["workflows/another-task/SKILL.md"] = skill("another-task")