From 97e484221d3c669d3cfc2618c2132beb5f4df7db Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Fri, 24 Jul 2026 08:52:54 -0500 Subject: [PATCH 01/26] self-review 2026-07-24: wire embedding cosine similarity into activation (bl-b2d1c944) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Semantic activation was spec-only since 2026-06-30 — the seed loop used istr_contains and nothing else. Per the 07-21 integration brief: - EngramNode gains a lazily-backfilled nomic-embed-text vector (8/call inside engram_activate, newest-first; no create-path latency, no bulk Ollama hammering during sync seeds) - query embedding (cached) drives a top-K cosine seed supplement (HippoRAG use-similarity-twice) plus an additive WM term with shift-and-floor at 0.45 — raw cosine is a constant bias in anisotropic spaces (unrelated pairs read 0.4-0.7), floor-and-ramp makes it a signal - 4s embed timeout (http_do_t) + 3-strike circuit breaker: activation never wedges on a dead embedder; everything degrades to lexical - embeddings persist as %.4g comma lists in snapshots, parsed by both loaders; embedded_count in /api/stats tracks coverage - engram_cosine_sim + http_delete_json exposed (DELETE now carries a body — the server's _auth scheme requires it) - route_create_node honored only content/node_type/salience; label, importance, tier, tags were silently dropped (label defaulted to content). Now honored via engram_node_full. Verified live: embedded_count 0->96 across activations, semantic-only promotion observed (zero token overlap), snapshot round-trip intact. --- engram/dist/engram | Bin 3541224 -> 3558152 bytes engram/dist/engram.c | 55 ++-- engram/src/server.el | 19 +- lang/releases/v1.0.0-20260501/el_runtime.c | 361 ++++++++++++++++++++- lang/releases/v1.0.0-20260501/el_runtime.h | 18 + 5 files changed, 415 insertions(+), 38 deletions(-) diff --git a/engram/dist/engram b/engram/dist/engram index 988e3cd1f4dc4f3f7e8f6cac9e9a336753cbfd90..2236beed9bcd70b5e3517f7bd916b27e21883869 100755 GIT binary patch delta 478332 zcmaI93w#XM|Np<|%p}>kMC2xtNOlt>aY-UK_gGORRK&J*r$MVOrKqZ^$|f##DRxab zsxG0WqUdU{tyY@Q3qGo$t)k@U*|n% z-ZSe{?K(vkt~yPeivmooO^^Q9+Vxgf`r|OynO*@uj|+6lG4 zxo2D5;*u8cWs7hmhz2`+H)Y-`G^Z!)FG?Y#PJO<69J ziC=#x{{AX&YuekwWSU}4GUe^}GQrf8s~=}F#YBp~E8ZqkBiOvluTmKtk)+l4?&^PS z!>W@J57Oe+kH6*j%iO64wZYyU%pI=a82qPIdWUHrc;9cib!}TyZgZ0<9+0<(pO637 z41avP@?4s!!}HA5CAQTHvp-p=H8!`(ue93Qx|R$!7ZnGaQaAdWDy?~KT~$ipwgq4& zgE<5%0Lu%KcEy6t1}hJg%#@%X`!bltV9y9P4a^ZB?LHH1(%^h^QB`9J;}Z3Q$HCBM zur~x716J%W?QRM-5)9WR8a+5kKXwRMUL(oM1$z>#+)uLR?R2~TU>45u`4zt*U?0HZ zhSG4mU_HT120JR44J@yLw7Vi$XMSvb$^4V`lce)w4VEfcJAQ0EX*WFCmCw7n4Pd#i zgbRgXESSY$y9J8|bC{*w1;LtuRryHPCPhDSD45M)(*+9zEB2Olp9tnR*qmQvGN3tC zKiC(Bd0x`cCYTCVu1Yprum^+CK!d#_*j+G(BJHXLy9HK7B}+}y&rt(r(^)FIf2M%H z0TvT!_?ciA!7%(pj2oou2cI9LU9Q(o2=^QA+z_c0?lJDiU{bh;!SW0yh5H$p#b8pn zpK^bOz@>2aaeoGr!re0n!mS+%Qn+sJ&@hz3eUCddMuHUX7VgksQn(wz@(d=0yO#Si zm=rGK{`e@WE8G=;HbbORxJ$u`4UtOWE(9|fObT}{Sh+EZq;TheISeL+`wE!NV1{s~ zbB6|$!hL}|G=`uQ?gZ}8U{bixa)$vxI=?U z;XckC8cYheH+N|CmK1I#n8RRFxLvtFgGu3b;Qn-0N4P26q0y~UxCz{$!K85G2bCUa z*oTsFTCjhse7ALYx@+-3gmaOuZ?|=x(D!^Wo58jV<^U^RDDA!#>{T$6!A$M-u`vTI z?{#UHB-m82@&%I36zutd(67aSp9%OJ3?1{OVVe%R!_i<>^CT-0Yy_CiV1ElX7_4}% zw0owbe(V!qCW9RnEC(#F5O&b7+nU-*H_QesFOUZp3-%b8#b6CO>vrA191dwWQ?O28 zRr!)#5G)PMX0Y5Y`msr1#dDG+fN%o^)4F^KMHUlPQ=nl;=EPh2AIt5d}Oa`kG?EX_|;7nUPJ$%BM*-7%U(6y`z8@1AZb5zXWqkm4^O`e((XX zswt9<6Kp@2&0r3}J_IX%LE5brtQ5>-u-$^~1k2BxEDa9{SOQo+NwONj-T|{1EL7DS zvjNQUytI2vur**+6D1ob*h(;)!HNZQf)!8D?Qs7(CEyZ3lYo`hATRwS3&8TmONUv4 z6@ZnGlWewNv%xF|J0#f4V2;kSZ~ z0W%q_fsgKRBv{@v((WPtp_2 zX0Yjk*}#hPq+O+8oxw~7YvZdQn+}%uw6t3&SUa%tk%Hx0F9_HM&?2GLR!=`T7R)h1 z9$YL~G+5Pe$xQWiyJlcEgXIYp3RXN!+La3y2xc;vr2#)Sf14j*-cV`i(BU>;u<{|2 zHE5`xLV3AHggJGY9DGdoafn(r&e2C%~%glI6z*>V{td z+6=f`utQ+Q1EirXNVhu(W-{1O!OFn$a;4qiVBPK`u=4(rT@Y+Hn8jdILUgO_ z($LgIhugra`bp*#Y%`e6V3ttbt{ANNacSok>@6^p!E8-+yH#L$eWhKcU@oxoKBjyz zryU-q8@>T(=_3uR1$!OLkuBNuaNVvDtSU<~Q-sc51G5?I4Z&uD75A2Qq0Mx=7r{&h z+nO)nWWc;$(y&9MZa5ySyr*P`1bYU|Vz9wcy4}-Yj>n{3wO~WRs(MH^)1uow1!gmt zYSme8K45XCG;|8s7tCa^h-lrg7g%0*X}49d?qKCM$x>rL{5rUT0olHiNZkr85&)aR+I4NU;Asfd(3E zTx;F#HdtPJX=iSuv+GY_{#TwZ;Z^~!z|dl_Eb(;zE0`lq+Eoko6IfNMWDCWU{8=!Y z!J3N)^iyEPDblW7uy4RnAd$~6!^IQ&F~GcJY5135hr!C*Nme8tvOfc}7%WLV|9%SQ zNRoDyg6#vVN|bDhc-GwmW;2+7s+j+|0gDr)p<6t!z6WM9Sgv>s-2#@^R@&7Fwh^qn zjbyXMlzc6i#b9PJt7c%1*3zy>uoX{W{#VsXLW`I}FNLAaVA};-2v!^~?K+4l^jt91 zc!XFF2{s2TFHW+-Vg~&RSb3~u)q+h2v*?V^|Kt?<1wcnjX=oNR-U(n;EhJkl*t1|Z zgEbd3**vh~=F-kB*f21Y!Mcb^>p-x)7-@G1jL-iD0G3Bf_@tPjJ`QFvSe0PC!5miI zuEsh=Ohz-osw|S3#Kf~Jn9X2L!8(8yM@c)2m}91Z<(mxX7BB%YFH#!X#QZNFth||I zM+IvRW--`cF@=i)b3{nH3xb7#RfS77MNG|t!EA!%*I54+&>yfkOd2i}Q?B}8CWD2F z8Im_xUQ=neRWJfp9x7P}vp%-}wxfXtJ0#ejV2&ozZZMztVE%Uluqs5tYB3wS3T89d zbTRX(29pJq8mpZ7{0wFamdCy!W;y4;WKE>T8Y(6Xk z%Y!x6a>0&($?9N@HCN1NJ_nQ4!5V9oVC7)N{_-SK#DwN!Fj<;Fqs8Q9FIZk9VV7@p z3b+eU))#857BQpQ4rcL_4&8#i3nohhHCCIL(QE>%Y9Q?@1zQJZ6AZOfF`-!vR$Cpc z(OLdB4Y0O6I8V%ImVwol2Sdf|Wf53yb#S|2^T2AWgEl#%0jsSJek<54u-fY2I5DAl z3C!kW%>Vupa0*~;d2pea(M$xZtqz8Y*~?h4+Unp|!A61ARtGzX$;)uC+UnpT!3KfV zRtJX+7c&|=U~PG@MzDThqCAKsHBZcFvcPJqgK|dG1FW_>xLr(WGVG`hw$#>I&HN7U z4g!@}4j}=9h z{A~f;p#f!)r6G4{Fj-_VbB6|#MHYoSd|f(}MV9*m;Ll*P$Z`ivR(zaRS!B5hW_evi z*l845eg~{tARWpg%VqA+V6w>a3wLNRd55Ut4h<%YEI)96^QAvoWI4(G87v=F7GB*x z&K(+17FmvRhX#{HmM^)(dD5XQvK-(J4JL~$`?)`Z$s)^#+@HZ@ktM&BJDe*W$|B27 z?$BVe$Wp=`8cY^h-r)`nCW|Z^xW7W_PZn9$aDN7qMV6J^U!j=cyNx1?lRFfKZllPu zggY$I9lEWu$g+StG?*;16mW+IlSP)<+@HZ@k>zFX&msK{&KLK!Y22X!WszkPcW5wK zWEsaD8cY^h#&Cy1M{cVuvW(>Z3?_>#L%2VK$s)^>`P`uaWs#*ncR0tmVsS(5!yOt- z7Fl|7hX#{H7900xFj-{j%>BJ4{mCLrI`;?0$G_Vsvb5t44MSOEX~P{FOcq&Uxx?Ag zp)9gQbB6|#MV4mVpTT62C6xO!*f?)7!w=*RUo~1N?(Tlvp}}O4#g{uYm@KlW+@Zl_ zk>x=y{LPa7WRc}ASh2xmk>yq{e?wtFS!Ah!p~Yab$nqO^_=zp>i!5JphX#{HmP6d3!Q@oqAb0q(JXRK2 z%D6v+$s)@~+@HZvWYJ%(?dA>*D2pubbB8meLs?|m#vK|=7FjlPhX#{HmSXPDV6w>a z7WXG=rEaS%vaHI*48PcbvdH4%4h<%YEN^g!29rgW*SW*#vVpS5QV1rCuWqX>vb@Iq z8FsSBGL!q$Sw6a27Fk~84qucGWszkvcW5wKWEsyL8cY^hp5YD+CW|ajbAO_6>$b`w z%TVsmV7$n}XZTNXhX#~ImR#=8V6w>4mphy)8z_q`y|_bz$s$X4?$2Pd$kK)TGng#0 zvv`QtaGE$qR8?qclf+)pe(Zd#Qhme7Fo`6e+H99mQ&nc zz5!*CwTc?>XbvD~l}CxkJNH z7Fk~44#!G|vdA)lJ2aRqvOLQj8cY^h^0+^P$s)@z?(bRYFCSGFKK~oY9U4#;Sq5;2 z29rgW$GJm;$s$W{?(iAuP!?G-xj%!+B1>29&tS61lHY+lG@vZ9q;Q90q(fO`N#G6* zCW|cb+@Zl_k)=8JXE0f0iQ@i7OMkM+62|?FHs*hF3LVTH8iumS;?Er#Ocq({bBCj( zLs?|;<_--ei!6luGng#0{G9`T20N55DldNmR^>^DvdD4+Ouj^MTV;{uDp;Pdt2Bx% z)!d=MWRc}(?(b>cU!_$RS!+@Zl_ zk>zvl&tS61QqKJuOcq%_=Ke+)6<%3n*~=XQVggcWl|`0a+@Zl_k!3q~XfRo1d6zpJ zE{~N(mQCEB!DNwT9rq`g+d9}+%>Pz%hX#~I7L7X`raN?7WszkWcW5v<^I60l8cY^h z=5c=plSLNZ(^W&IKUrj%m4o?Tu>oa~xkE z`JXJZ`~@iA(BVN-6j}ZNt9n8@ltq?nV8sTLGnz}>p}}O483EwX1i?USVq?75ysXKA;4wxpq1rIEb?2py26CHFo+ zH}%$T_l~4%dTVR4GfJP#YEEeP-rB6}NZPS?>6+|)gpAj&FAUUb)>!D~UfSZmk+f~^ z(rtY+37UWP@o+k#msYReXjo0^7fYjiX~zm8l=-;8J^d2N1nrl8la(4%i8e4NKBmUB zqr7WX>&0EG&|H(r>LR8B``w<$`5_ zqE8-(cKwOvpVaF55IpptwxWMa8sAIX*MAjN_#$0fnCqb5_0;MO$RycXzX6FfuBSF< zKqT$ZQ(He^8_CtO?Xe_Fn`#fIe?O)zvkz6XgH1JB?yGU?fyc~6%yQK`vNZjPG6JJp zPui7AdP(c^)a&Guc5L=V?`=r)J+5kH11AEs8kCH4j2IL}xArKVGbo3^`&WabaNyO! zF`b6>z;)HR&Ox=?{8|g_Pw;I;^g*t^E_lBlTAv}y`fLO$zHM=xhYNfx?b=lCu&?E; zUPsq?bQj-VjqUU35UY*9lL*@O(;J0$4QwN9_za2LEbpO351oK^E*+XkPi1OlLnG15 zvqO0^?+s0%eS2uh!zNQtrnYI=1RB&s^BX>p-p|y=4o?WUk%{5mB-C}DTJ-Z>%ha|E z-$@T-Y6C}%rCZ@_#87x{Ix>ac?5^dESjZ?isX`-7mUd{k zXyour?b^unkR0p^QY@~GA-pggq_;OaQ|t6}%Ybg!Wx}cXE`AxEGfSsEeT>jAyK9-F z4)B;&Y7rxo=pCEZY4lKH(N>Orq3OWx=Avu#f9wx)WkD1zEIaW4cjW z_tKGLj_|m~Kl>KlV$;5Ob{1OSeQaks)27WC+lrp;rfnM=MzTsjAKRZ`SH-wst<|^? z`f@jI=dwr~IBML}I&R(g@owg#zh5XTx%Vn5d2rBr9Gy8%!#>ye7#h}1+dFbjKR5!8Q;bYmG;#h7i$trOCF@NDcjQ+G@pAyZ;-$AKT{>l3aX$?`~S=#91`1n^rcF4*>FfB7GI7 zI}~M3oo|mf6;I36hCCmOJq6D{kv{=P-~0yJ!CwWPYafg4>L{K`f@;q&ik|@t-H7l7 z>#g{f+l4=BH;CJTal4A28tAP#0`}ebx%TQNkJ>)YZJXG%CnhxxDdWEMWTzl|CAo-s zuDyGPHfvHc-JYTCoRm&mW@r~Dt)K*Oaw~efYw4EB(S)|n(2l(D1%0)vwqi;&oz}H< z@07`;en?j+%H%ll=Ql*#FeRA!buH~R4KdHw8c$E5GrAysh5Ig?XTRUYTvXqp?d%&< zx^#L9*F?oj;WVy`cJ8IoFz!AhmR{|Qu@bH(EJm0X&ESD7nX%k^D{esKx|Z>Baz0-* z-74=|T)3c16|TU9QOc9p{?0rme0`pMAJ(e_`PGx!9^J$DgK>L4Ab8y3&>oT3AKJag z?fAf{V;2cKq(o;?VIzOnpXk;;74>VUVJ`R*F$^clc%T%c$z4 z-Jg}i^|Uuo%X>AHmUPl)y*dMZa{bl*dY}9=OFHXjNpa%5K@s#)M{UlakW%NI4m?>N z&gb2FDL*D-ZAV;dojzR6x8=3-J}u(gdNLJ#?Bv_>rm?i6*2l3b=f6P3eqCL9LPVGG zZao9`Jp@=xn=Ii;le6!@&ZGOSH6m$7|31%N3APb7JZW;9qaC$`g2}kvbp?qus3UG^ zJhfdd;LUAVm_lFgsAU$;2)W+D&~EeE=w9id9V-l>BRgsr3kTAyj#|dtgn%yaZ%IsY zo%gosZRmh*n7flUz-i`F=vX`vbIkzNzDCl|FriY-|5Lesa} z|9_=e-^JbN{Px=9UCE`h7eCL3)TJfw(HrU7sy7zn+N?`E)ADp}ZikD!CZSDH80^A&j;I8fhJc0^7qZ? zzocnLoRMlgp9JtpU5_+<*n2zeNm@HsBCJNaVv;l9nCp?};Y>%N{R3?4d6+a^QjuR^ zPv`r29;Qu~@cr9xGS@7+Buz_R(Mx-LKoUKhs%PQmi|pB^;%Q0R@fES~eP_k6{3EHz z!ebyt{1uqy+rPl}Ao!?G;dvtkS+R+Jj&krSF#Hfm4?aIn3U5d2NA31G@e^$Tc*1I#$^5|kBBsLMjkONe>CeM727 zi;`)*G%X#A`Kj83qE+;1z?BK~iPX~Ml?jB?(W{QoZ&S1c){-7c(eAI#C@o@-5js9a zJF_~P=B1S0Uww{{c9K-wu;4^ny&g7nn7DDBGN2AX5tg?#U19tNHw7TOi8>)ohdGSaH-#(V8x z!^ei}&J+cWjK+;+}25 zwzl+bpk3K$rqS55aiCT{E=bR~my)zun`WR>u5Yp{?mFrAlH#tDYtu-j#uIIP5)y5b zQrG6rygR?z!sUK-OY4l&iMT5LHZ5*Y-|=mEl|0iQ=i3mvxS7qff5o@;9-U`DlBf-Q zcNN8N$F98_(kUbfvt>xi$gRA88iSoj-&!pqw;pJ?(B1&d$gSMQoTO!Jow4HiAkAG6 zL30xIbhie9^eW+vY*EsgewwI_E}5L%8t2Z!5tq>3cs$&24f4U(g11S(h8Wj*=+pXF zfG%>DsL^dhsUuMvxh)}JI;<>8=#umGZ2I0QiQ4*YTWGIDt=D@KXzN7ngZFeNPFTdU& z60{rJJB1v@t{`-zRSCvzB}mU2UnXdoJ6Z(GWEGFkIU@qoEf6VPJq0r@b8m!QqdX7Te!wt>t{UE$lRK zlim2pW%oS012>oR*iDgMziF)neAGwpx*KmUnxVDZ7gV~VOylFRdpY+vsXR7d7Ix`Ly~>Kl&$rKr z*S3^T3mXFb7lvi%Ts+C~;pyn;BL0i*PsD4JPejs#@!GNzVWrPk93?b6zO>W9ZG>k? zr)DWjrM5UN^7D1!HQisU=sE$9$(aRW*<-#~KDJ0Z`T1qEqT&mF3%c}0I6W7um7R>% z;=XJ^PsEm{e>s-t=5>b>>65XzYemEM`k@%u1|RMm-8U93<{83a(OcXb+qdUpUV=Y< z1wCR*ryVXd+H)#3^OKh5qI<7?T4M5Z*!>E8_@_F%vye2+m-L`J{~7dgXtNP?efOPH=0u3ym4z7)eU>Bwz>Spru9Jo zE$XV)t|E#|*9KICmu@|QnBQ%Vm`4(==({&+PmHIMuMSzfoP~CNvXd>fg=-r&>{jni z)m#hRMgFia%o>9L_FQf^Z+=}2TkNLAuiL|8v>QLz#ntA06s(Q-F+6ZQ zT-1qTWqkKAj9nK$QRLYKexjVSEoo-7Hsh>4tSyZ1;t^x$Tzmq{A2l2uTqJk7Jr?J! zi7r*oxe09*t?m8qdTsYsf2~bf9DT-Gx~$5NaDVI1x8nYeoNpNxV@1RJqa5`UKJ>%V zRORm?Xkjy}R_~{2)MVA>{1ig(TD1FrMA8XXE%Ih$>9;@GC_P~*opaldXw5IaQG1H7 zqO{8w@AETU{bC#qLUjUN7*#s5dNd)vc(xDJ+=rm& zSIxA36rWvsRj=aV47nW5+uG@JX0#~^I@2#URd3_pk#zH5oyiD=HLxXc%@ z-x#YEGixL5G{2%py7FHl?XDAPw`rrc>B?x;pOa;>A^nJ?2%x*qzTC6TX=yV( z=<9LNzXg4Dv(m_#6NJ9i3;~bUf^N*#g4`nL-$iIgZgk=<-CFVaIPTJ|9X;PX>~O@t z$NgZ09``K~dfba6^tk)u1UE-gIx_+>UqcM<!n8AY7tk-mw9)@tTx*^=C+uP9DyNIk z#bI!oKi5N7dvD$PaF9ApyJ`oi)3iq$`?naRe~Ur-cguj`aC-Y^3{w0N(@Oi`FfH=l z-mp!;O}tmy%?lQbL5khfvDm&gOuKduVRHvDr$4a-UT*qG%#iAv={MIM_a}16hds~- zX`crz>A|LKXJe8awiieIg*jd5TzrtqpK2Y!xbdyDyPKAlJvc+?uBL1aA?vjZpLL+W zg|cas+~A>dvMWI(iO0&xEWxCC*!!V)VxEX6=AZGY1eT_%X2^nz?IodXWH8C3t3z3& zNsl9pQa7k>V&?uZ*_91`Aqdr%XWP>-Mons`Rm zBcqA7_D~!j%*v7wGi%hoL6o`yk!K+dNHmUaz#eNrIz&4{Frf8*LDIqX%*J-@-51+4 zLpVuS~u{i4A1Y*_pKZx-}1dtC2iDqvS z62txqB(rfge=X@`9339Sb_S77q=sDzA}OSrH47%OB!^WfqzTOm(p5p)vt}wb+XV?x zYz*>16hkSg=h@{=0tw4%3ON`a)j;MKMxx=dT^NaNT8-A$*3P;Gi~BCZtgyEANQ|c_ zj66ojCAO;>X;0>|>-C96EnZ-+VQCR)M>QJ}K|0e{0@#`evX~AGU@e;=io!gzVZg%} zKK*=c4Bh6}QeE-<{yWv8Pn)yk&_>)UO{c}s*4NLnR*_@@&ax|#G--9Uu`FJAnOxSV z9rjDuPBS^|w-i&y>W}df3HhyCZq>_#LROCJkhcwKOV`UJ2X3(3*k7em=@3$ZBn z#t`Z*5@sozYe%puADQeQY=8WwLbg@aH{Gdbjjg0fz*GFZZ<$;sUz4kQnZrJyG3#W- z*voFrhFZxS`c7ld87n~nVQ^zsFNS=8%ikY^URmVN?#7U5o0h~s_^(FLW1Ytt-?fgHRXmBHwni*6o`j%7 z(&7nT<*<$Mq%{p{#E!+2LRb%IMLsnHH%=ijbYBCOog5=W1)kx%*2&3fQm9w_tTRi^S5tKI}#o z5=u3DDw{;neLiePHW^6Y@nOfZNlR8Wa`cQ`XB?|_r{ZN2SOkG=7PKc%H_h{8LvUtg|M&r5wt6GCr#vt^INSFV|avZId^OXlM+Hf9d%^L+5= zjb|!8%l{>rYt$Kk$@<8nT^!Fd=Y>Y~^*{EESNDebsF2XX{i z9rpLI9fuK99cX&R$`3I`xvG9hbY)^+3&qTSA4Z;1e6iAdI61AHpk@{`g1m$)cyk2Q zc-VtS=D8~VQJ`HH16f{HfH$*`CXvc-CbQ?o(WIX*IpnFBNR|`yz<^04Mrn25hb219 z;cVwH5|EI7-{+CWBxAcyW88Hcv;96hF$qI!!F`W?GO`~soOJ}kzwrf9inBa51*s5c zSu_>03BSiC?;$ropwr|AyMoJPi?<4dNI&hRxg z4foRf(?~$mgMa%#t)G{ZW7I|1qg5TXbJzL_i*TZ(5o^|Ry`&KtsCicy{ z%cjl2s2X>d9hpPU&~|s(mV7dc`*-Lu?&=`R5o6X)r9tfcJPht$e|fy;lTJLm-Io!@ zJO1=?@P)US-!2laZYi|8Su-bzNmzdC(S|I+w$Tt`=uI}n>o%M0M2P=;%X7_%5L4$Z z)@lVgLbiHtt>ED;Vev%>?~6A@cvlvY=r(TiODV2Pjd1Ib;Wcjme8`&aiSX*{CvcNxD~J6Mw*OCu^7l)j4PBYo-~9%g zvjKPh<~P`x4T$d5>uhf^qU&buHX^zuo_-s7bW8LRT(g-pr?kcsvV{kCt7pLbJh&zN z?h(lTb`yX4*i|0kNF3gF7l}#kd-c)Q^u~6b)(D-|X-)Z6R=A54(l@VqygwirsQFxF zy-M{EH{LBm+;a~?+~x`oF|ViX*P~lIcXZU|Uu+v)eIEMP zhcxf%!6~jx?EmZ%n^r+a)6JLI$qI6gPP)YQ9uR>)C<1?wyoJDvVSVpQ4Bz};J<*4F zKAMB$LojFR;nqkuREZmygW1l!p3LV41^A-&EJ(I^*9+@70Yk{u>H~=V$xIOwa>NCQ4UGkOM^(08;u15M0EtIj|Zi)1GF;0!eJ-B16}#N@el zr|0Y$qEO=Wod1y=keL7(jAw$K=g2aJIN5+-NCX@56J+q>dC!WU@bo2MOmb#boo;{M zVb8#Joo;v6cKa#f%EW$872EO)#{ZfsMlWLgkEvqkEP39!X>*Wx&&FTL zFqJIQ^FY-+PN0xH~k<)j+b_0}1FP#!Y(GE%F8NLkRUj&6fye&Yz?gj~Xn(nfnguK-c}? zxqOFQl(2Pj-kCbxIjF!s9NTreQzTDbpFU-BWn%w#XIR2Lg!02PZ1FveXvY~g;Xaww z3pMSzDqAYapvw@>@vS9rm$^Ral5lh?>aw>#|XPqT}JuA(zf zvpJN8(W$3BYbagCM;vbT?dhabo(U?gSC1_8yyQob4#u-){xpWZ{GAZSNPHW|M)}j$ z$+N$E^h#!8+qjYnu53Q5taByTzhhKsaQ2OP zWR`u159ek=82Y-EtqG!w$v97oVEPAdThk^qk?#41^=U#EkSXkV6BFah zp>!V|AH>c@S(~u4p|pwG=Nq3QRyA1(V*yQR2pq*Xr5d3VzhPxz6yG}XOc$}IUXt?B z2_N?0ZoNo0B%B7q<)mhsiU5k~KUG%2K^YtRJ-j=UxV*Qe5 zUNx<;hBi&$!L<>EA2qn z77;CSHiK^lA00%GfjgCs9`7Xjg@UX4Duw>aJ1BCBS2VNz&`@PRrcyJ_Im#}k(ny@n zD~+bm!$(=CG@6c0jKbE`a+Ix4!`^Xhe;WOm_nDmEu1KdL^z46xP^K3_D2LP0UE@4g z)9Dz}OgZYqe*o$tCP#p`ViI2r75KT#_ww(IX9b_oK<4N`VnOa~N^)D+@)(pT1n)brr!J3EN>^S>ym3 z;aSm{+7&wT2)md;Tj4SqcZ1UR9A;&oAgPS*M%N%3_quWEc$(Vi6O<*XG?*1+Ligtm zv5Z(Hg`Li%XVjWLq&e%ho))kUkI~m#SDHxz*RAuPy4?yb8@kokt?cq+x^7?UDRhe` z)F9RtGHtr?OP`{@p8m&U2EJyS!glqh;p(^`latjnp`mp1m+W$Hx)06Q4?Z1=gY7u@ z|2(5icpV2{&CcVv zaXo%ZAE(ceW^2CiDLUWCc8AAs-93EIg28RBjbGy&+L_+`TtC?Str5DZITYUsvvoNL zKuz9d&y5@&x4h4NibC|bQ5X8BlE>{8#7#ro_;y%V590QL7aj8%4_R}cFkK|s?EG4& zzwsa%qwYJ1fl}kGG-vJ})SI;6VOhkk45IasPM%G0Evl1FjM)KqZJH|5iN5|4iylmu zku1-y!H~I{%}0N6Jtc`&9Poq)54IM={vC1|yjRn6>!d9t3TyQ&JwUS9)o1An)jhEwjx~CZjtbd~oKQUbKv%xp=n%_I^Vt2P z^s*0Uo2%kHzkfxuDe1#1c4CBFDPxl-VBBYUHcz09@J$rkGZFZWGInhu#(y?z_&iSR z^C`=Gp5pU5=6W94VQ?8MdmekUJZGP$iTZb_mjZdgCW8L8pJhy@(YWwYlcB3D&-}^A z3$$4oyZizTg9DKRcGG&S*K!(3U*6CB?$Ri8tA+MO1mAwL@l%ipvY2ZM5&<7~mP?+C zQy{3EpFi;_dWojHs>7)(#A@QAa)!QnpetWCT_=`d8^tnw^MS5iR8#*E_~ZK{O9YSF zA(rM{o{SgidX-u}Vdq{(zR=qh#G1{dv2@1AJZUsxBW6;j=JL!}^(GC)r8Is8nUwi= zL*8gO8+qf^eIjr4TSxmc_iS41vkm9!)4jFGAE#cUiI@<5t_#&|k1WZUROvxgnE6X3)FDBV;-D7`Jo}vU$Ds4jHb7tHe9TcS%ylcdefmy*)T}qpmB1O?B_cFibG>rM@po-IM z3gWPHkI>LELqkiK)7ETl4sFOjUru`|mC%r%6B@EN-Q!afh@@1+b@Z0d(L$b_pd-HI zI^s*NBfhMwBfiab#Ft!0d2gt%_%lEravQ;dCpN!btk)(eCSI$+cuo3}MyUJT z5R5)qn(!s=>~TSCeOu)KYx556K<~TR*mvkQdeY5W9j3il*@<7=NBmVJNP&ks;I^59+h#== zd+-8{VT*So&yCnFG&--yewgCxN_KoVjb+X$(5TlQ+QS?7GM?&k_CTgX55FhoJk`Uf z%ZyZ4-P?2rA=lF#UrL!erA(dwkg1;TxE+@%L&0lxy+S+RhFm}J&`m0(@3DcO&{j;H zf)rEq2_|HNxACO66BjmVzb@59`{~mPxsBK4dUk?>Dq96Th`G|nBym%& zI)IyUrFp3?-P*a5A>DD1vmsr5{SFH`NSCQ`eB$HWK%0Ax9)y0`O$SY->Q-I7%vOLP znzyo%U(hnvp^zr2yWg#=Rm7;^OZq?h*Sl=aA*i(SU0tPUG7@JBjeJ+vC@yIKVSYjE z^kE1z@LiUC1OmOZg`GKq8*$YF+=#h6Y0(y;xhG$zPM?Wr@I-5}xTijg4W8!slBYSo z6uP^r)NFQmu6;%OP_>>uu~>o&n7CQba%^cOt*@FncJ89hS$QQbSAF@W{wT@?g$GD$ z1r6tts?WYZPOZYc<^!7KX>)?6k|y0YKb((c{`gQ>ufB=o=h%(Fz4?wVEZ>VlSpGrm zr*9~}1PNk(-_ikk?i>9rL^V)-2hVcIdAgwbn(iPFdfwwpE-1d_g5t}%g5uje@9||_ zLGf(}>cB~Q!<%l~#P*(rpd4=^Mcg_|V^z~81S@wxCO%iV{h2w}N@rsjk!uH9RSu56t0pJ@@zaGSCZ z>IFl6y&t>yGqi<{uN2x^dx2}Kd?P|rxq)k|DQmQerqORVu!LWsE%j|^%dtUZrwEqR zKnW5@XEjjV9`zD!j*9gL7U`$-;a)=696u$Jo?Xw@`zaxT{y0x+36YD_&5F4= zm#$@(|DehIe33Wt^vQ*ia0?)DE!%k;&7OIS`cu5HTzrd;rEjfeH*QgUWfjEc+@=Zi z$G5mqBtQDtZ5)kO;&CyM)%=OO%lxw2Th4Ds)DGEMD3G$>X3cmI56$x{{ml8u8t>y`H1)J`zyp3FWK24W& z`XAT5^)C$L_y8J`#8v%&GG-QXjG=0My&pT{qby_Z9K_AuX;vWUQ=cQ8->l+-&Y|D0 zV$t=LG8XYAv^;lJT`lvr^=hD;Bve}^L_Fm%2I*^lN))YHSu0}aKSliYVMD~#Ey>`ba|cCba|0) z*|Fo8ou3U+0`aoL4DoUbwJDA*D!7ss_`i1!1U23o4dmE1zC&Z>CDoDj!#S&`(5#~J>a3vpI_>n3uczJ7qBRTtj#NOd_Ul1@Thde(!I^sL91b<~B#*NLm^ zamq^nK%#$a3G?fyw1oS#j!FvMzl2Tbs0_qrMMtGIZLox0>!?JcF%3H@?Fo;TUh8T@ zw=EWxj%y;J)vz}^D>1O!-&w(&@9V`6)7gm%dlI~0vcUk}qA1iOYmoA4!< zAzyMC@?~8a@@+0dzT`6eD}VlqI}hfqxSKz3#sBi>uHYPUTx?TTsI+n+i|nbi!u4nO zR646I7a}I*!Cq19-JVKM6_Ru^+d15@>-SPdC=?G0lY0g?(eKtY>h;M3dT z(tLI%N7=`!>MKd=s`+(=$+M1=6}MH&*(bS52YO~cyPXSxelTAbsCt+uC1)b)Jf``& zK-Ef4euPHZ6Lw_?y*ZEVv_qjs=COfKD4W>yP{p5ZZ>QMkOY_7`@H2nK>C+m+Y~rXc z;%?gl8$7G=CC_SnY3PoxZ!Yg5pFkP}qfL*`LGq+|4vGCPnRKzKYyuSa2!R+ z5uKGLw7T#Sja9OZLzNhDM0sZ=$@AAxC6&+yb6LW0AcfUm7nYvi5DGoN@ud{jBl(SUDJ(s|{fn@8 zo?G*@a>AR=cCg7~A*{pf&9M;HiF^dCvL_~am8_;Ga$MkZ5ES+z$F-+t=hRB+E>Ce? z#m({HDRFZ&Lqq1P?OeWSK>UD5Um2iLZqrqf=JfUJo;A-a&yq&&yjusmo=43GQFD*J z!~7;ILt@;Pdk4GnY-uH!Jp5rw9u0$5*zVy~-jy#O^JR-CD|5&pkM9f0FdiN~3pKol zAw23ewq^=$d6lf=RAe`Nk1|ym#7$i3YE$;bG$l;^dNwZ8GF1syzu+H^+?$3RamZtR zQNimZ-Bk+BneDka9r=!hCMykDzxHY)=08K3j@`%GtF7q|ud<6f6#iwRCHeS*_rpwAqOKVK!NZ!HSd@?2!t>#4N;yCJl>&u-$3zO1sD{C>_!K=*$Z`G| z3>s6Q`{jG+gPES_LS+EKwiBfNhD0nssIsQ|)=_C9@pC!CZywzjfqP)t#Nx1%-63lkK z<{znQFBm<0gnxH(^<6|@EA!o|Y^qUOu3fypZYlK|rsBW{3Pt#QO182gyKpztcSps9V^7^r7S`m4clvf_mtP-z+>#<{*e!jrQXT~D@p4ttayggr9_$+10il_;U=Vjk=fA90Cz zUinDrOPG5)I_C5~C93J+3IFo`#T#F7u*M%NG0gI!;^)cySeZuD5`ObX$v>EV^@-9X zI0pyT?KfW&gy^~RiBg}in=dI5%u=RI=fP=1zaP&Il-dh_T5BG233QY)34IR4A?a$(^inwql{p#8(9_WQ0a!L7};_WYnR*Eub zqz}vgKD3F#U#EA!g8QL)E3(q~E6UymH799TR}-Y(KdBdMeN{>G!5DL%#Kv=1m8tNc z53;LQF6bP4j)jMa}Rt>{9S41qhMo<$&0=H zyD}aQ^;B!Efy0+ah*3M5f0i%;gw6a2?OIf$bZSt^ecpytcvHTvQR37Z?&E(oN=Nw6 zb8*gfJchL$!6sZ+W-+x)iCA?5p(!duX#P8#hbEn!x}g-YH$KIjpm;bRc=0TzBeHna zAE;<9V&tY0tG+f|jJPJdFwqv$ZpAEl>0SHHO0FEBcR^3F2^om>Qz?`=fGs-)d z+Vc@en+|6=yOd637F)Cn@iM_%UHR~6+{9HB6?(aDVYz1o%ebv{tzT0V(8K@>ZYzZ> zs8k7UbQwc}k1#B2`dH)m2mh3uQXIvTO zIE*Ey32#XFKT)Kwmv}PoDl-T>Z|58HS{3H0*)Vj<$^`v98Y@$+gE{L{pW!MIbihF9vAt5xr3+aUzNM+zJ7={f34RDBPJF% zBOg*y4>zN6o>7T77has|ozS?Q8l`sTwz$oQDE!rHzjiAB2w{9X^=Ch{!FlpPJJ+9B z;+{A(Sxx8d0%NO^)ft8tYl<30J&y~K_gVxeBU02D*5-lY$Cjn2=lq}u=N|Zx$IeQH zAHmq(R5jWAXY3zS&aS1Z6AYh|(%`fC<7`=)8ix1VCD>%MYtUEUrKvss>9A$G+R|`h zPggVG1S2Pfp6tuMNLOdE3)hj*hPPLzv*|Z5Y8Lj@`yN+m?V!G^j^~+CuUu|Z)DW88 zm#zOp$z)wRsum1~INGu=ThLKGzy{yKuyAxz&2058WU{k;*uGmzC*PBQ;|Zy~4IcsU zTS3fceI8YU92w4{%uakD;D%J6C3aTz8&dsR@^WXjfSLbPLj8_B92@RF=RJ{K)Q)m! zT=B!5=X`{?^RTKriY4bi*$>A@vv<6U%JJd%LOwo5B)dxZ__)*J(N9v)(Z>7|_a~?6 zI==@McBzJI({)cqH}#0h`@_kSMyk)SDUYdb(3k5TQ)84tSw7m=ha!DW;TQYdpuy8> z1goZMLzecmn&`3hRLvy3VU`d6b?$ilItCx`>g&Gxx=)r5+fdf1r#eo*5#*_<%GbSx zzXtP!zc!=P=DI&m$KEPFYI(jlJC>y`qglP#$ZT~5jp@yny`w(PGWw|A)UP*-bgI1& z!KHoF_Vi>gmN7&PXI{^uq+;f6B7N26ejoQjYZUz82d(+AmuG!n)tiVG9387B(E+{K z{jq8*ezbQ#)h_lpo>N2F^nR*^e$b1p>Zc}%?yzZUoKnA+4}1ST|45cL4ih8&JVVB* z^_eY4T^mr{6L(^T|DPc=&`)@wC%cxTPDA&N>JKSy>dDTPs4c}&he5F8UVk-~&gsb} zZ^Jn=a@7EmoN4&2heme?S z#uMr^AF&?AhOJg_`TUL@zZXQY{B!C`Pu5dv7JudH8iZo-iXJR%sLJ07j~c8dTF3Nw zRI2yzE8B84@?8hN$7uxg@hxBqLH;G^) z=c;}r%d>H)I+ysa%0vOG$zy0gKPjD($wm%Wx8R+t*9i3oEY6R>RjHZGZ=}lK%C{Yf z=x4Kvk_21GcJxp;p(`BK>N(ZU2DgPE7d?k-kGHXXKxJWQ=yD}~+a=m~!NjZ;el zp6>Rjj)ryPI*MdT|zZe4@bAokUG++)y*M9D)HGyo(b~Ti~nBmE(QNtR0o_|gKkD5}M=`gttA}fq>sIIT? zJ!n#aY+`l9xDH^MiGS30(chApk_B^kCKRd^pILY&&E;Vq)4>S)@i%bkT|2Ox`d&x8 zg->>OzM6w(AO8{qcK8DI5Y~4bQd{Sgwttw=yjF;WHV(}&FG_YTg078(W=y2FqB+Jy zT3;U_651iouY1?5d+Q(FX_WX7=Lir{g`m%+ox4Am5FV^+d zc!|24w0k+7>#M7alsoLx_4S7O`c$m{F&Dqd#2?9X*e7AT`uis!ZhnvU4LpE zudlS(tftbuG`8M}0fLu)P8F|b*?Fh>R+x?ZQ1J6&G_$L|j$bCicc(N~c2Zpcvt}#Q z6!ni(+~J**@W_?)uIf)`rm;CIR6F(_U!iuUPo^FJ>pvdo;aGNay_-K~? zUBMa~x>~)XR{joz+*Y!84RSJb4&t|)V z5$#RwYNMUR_H4j}BJOEK=KKc8wOy}v4+GvqUl#$lVZCm^yI`9KJYE!*ZNuR>ggZVI zsUqr0?9xUgnK)15P3o5P9&&bQEG(~XQDfBuiH}6RcM{8d7wKsBbI8!{ zcX5Y{Nn$77RTEhCb7~u9c4D2Nv&YB5%havvy8%PsrEc7xO5|~$gYGp_5%o_L_ck;V z&yCw4dCUJ}?7hRQDBkzs?3}Y__v~&8A*2yf5t0B&s3Cy>0i+WkG(qXoTPPwRB?0Lz zp*>Qi3qdd-u!4eA1yl^Es0bKPG4zOtfRx`ov*#p%&-cBq_phDVot>GTr{43-&J3|f zvs-b3?ih>}xppiOi;Aan+wD_4=fxG%8^c(lg8IjC6;!E=nRn1ma?PT~nK3yV;mq{I zdCx1Lg4QD)f$jb`;M&;3JEtR5khtej-ny4*PCRCxDABO#c0W@+Vb72hDOzYD`gT4P z^DmXT4*CWNE3-O<8FE`{F%vxh`u_< z`WCE+K6{$ZeE8)@%i`9K-0HqA<}!SmCtbUf0ztYydpSJ zZZjv{r!2*uvm?k@)=WQVza|CeRCMtoURx;A@QhIXyo#I`=hNly?OyE7igf3Ddl!~g zkuzjRTJZzylz&Bq?#70dx8u+GvUKeSNPR&z_@mr;@Z*ChtGB$Wzj@lme~!+?mKPR3 zhAc+O4nKk)x8bR!g_iyZEfiOgw)_Zw%wG(y@%stewDCPFp+?bW{U}=avwaG4S}N$@NY0Bf)MOd(@4FYkiJ~t2$Rfqm&&W zH_vb{%kdF1ceBhXm+hx*cBhDg^|VLR*sJzTgi1MA^R1)opNCtdRzPYWUaEjodsVJo zGY9|1sofI=N>jT#&%3DI73tE{?ufia?P961#f4iYN01!#S3QSs_Spb#I`{|ttKj`% zygrN-XtGbFEwX^pACJ1_FclraTBy(`T=M^_9m*V5k|{z!U$~z>F0%( zB0X;`_LhCO?;uoBn(%Li(w$pSM9vaL6c);f-CjWKAN3%dVTp)}p;ylpT>-o9mqH#vXNZ zDp-0bFT%sl@1eXS$LsO)faRJ!+^nz4og{klE!thVYi;xJnADBoH1{PQFKn zCQorZ+Ch=tK|4L=6MTBEJiYBDuNEmYz+0YSXP@|)Ys<>xY>4=k3y|CKXmtNTxn@wG zvY2KC0C><W9dIY_u>YaDD!A2YTM~a1LEb;<%)but!IhCdX{6MXA9|eyu3)dZca{+ zt1x!SpxhdAu)WY1Qv&%N<@T(DCk5A(d4x5!rW|kEZlI|QIR;IwsVTqCf;{PQO}U2W zQbTZ&Z{e&)kFHZvExDJy4{lLWEp&2EEqP;9kvgMJP7K(?O|jYBc=UNyP)wxv(!|=J zSkd`uRXD{W=*>FvJ60BCOEN$w}A>i*G{kYD0Mp+vTJK4doHMR5n!&k)zpYr`e^EjQ{A0 zD5s^M%iflt%XEd(TM4?Pw#Gd*R(0VSa#c(#yQp)LHg^JbezX(o4C^-Qaj7NlEZMzEmxy@T5_d=I_i!(IZjZf6qWKkMm2X+DbM2|UFZxd<(+5sEh-)F z0xF5DpwgtS@*q2+uL}M7y8I0_Eie1g$v5QQw$8X!rH4EmA*mx50egfz_%lA+7ieDY zA&*m}eCpgEgOAWve|eQ{v4=td1LWK6lrP+iLC5I@1_3>S;Q7`nweAN$P z)bnDJENupP$o9xeb&q%DOzNILpPaTT? z*O5fotK~M$3hp^zN<(t5U`O1mHvim<$QQny`ly`bvHys#$61du9yz^4nP8Oh&wYcZ z$D}^`d#d!v{m!@d=<&afV0QAJ*0 zVV+OqdEVo|+|P>WSuM4%d2zG+0hamjrh73Zg0_Aj7x+HB>sWfVU59Oa!(YCc4J~tHvChv z`KRdKN?Xay+$(3;5pw!#znrM7!lQSh%9!y7WQoV=z#=u-&Kne$sfJK@eEa`7^sc8&Xc~k2?YplIU;^=08u( zqSMzP&d_=k`ls9zF^I{3LeH=Mm3ICq&n?H_C|1k-H_ax}+1b>#P;MaJU05i$EsqP+my== z`Zh~1N8zU(;mr1{+4GjnBzE*Ng{CS|G~>2h7Cm2a8=^IbuH2TR?2gM0nAo{;h%9~_ zMZ8Xqv=yz}W~SYdv1vI<6@loDFOmOWa$|PnlG*()c{e5=E|J&YaxiO)t$F^2qC|l% zf6JjP`4Wx$TaF8jy990qV{&f(@3-evU<*Pz0GwSuxAG-A`Zp@`zeGEmD4|sGzTA{O zy+}ju%Rk#d3~Kg|JjafC`d|uM?>uN`Kfv>V*)Ye&`xAXDJrX302&J1319SF8@NiKT3}t*pygz+r73r2h*gdav_^?fd)K71LH2x%x7{k z8+d_^@+)e2_Dt@}8eX8j&*dSk;srYM9QOk+EYlp<{D1k`vGh?uqeo(R5CFMq3(h_N zGdUzjGj{xEN|T^|4*qNoksOSL)JI{f&wL#Ha_b^r_+#oL@Bo4h9hC&O;wS3)vm@O! z?2gY=_Q!eiwBf*iw#&|w=H-Y?o`2pNo%@0qL8v4kcb2%vi4%-``P}Kqhug}}dlcZ| zQcdM^r<}*kvVwUkFGp|I<2>E)a)h$ZsMOoBMsRVix8s2_1Txs_O1Rmsx8h`!=j%wc z<(;`=-tcu?Htd7Azw!p`jy*4Ca0J2Vq?%R39odq7un?(9Fs1rgIy79_V{VCb_}dkX zakd%}MTO)sa6KX!q%yMtjv`tYByF{AuTj3 z#5iWz+{Mk0HmRwSG~c{k%`wx?6+{%)Ppj3G7O*6|)sJ%3UB#LBsmds&CATrC?$_;V ze=CD`T7Rf^urhdO>i5otRIRon*NKZ8lx-#XYY_a%wKn_3+%;>j%?`YZFTJZdCIF0#GpowYtU6_=-c^95-*p} zyY0OIAI@1I230KDulA9=cw4iFH+ssib4HoZ4yegY>4fr2uZEiq52{HLjcw-m#mVzI zNg*Cf>5b3TK+0(D(EYHn8a6r_JgIIW?5dyvrl}S+cjR>UKFPU z1;V7JmbFak!Y_H50KrZ3cp4`6!9Z?Ot#_W`-UFD~0_3l}!%bsw?xQcwDTmd*HoDl_ z(awfGnQ?6#qqvt4K_gZu4a|bJ4p`LYSQ8>FDwvmB)Fxk0&vuRqa4sSgb80(BkQ90U z1d23qn^eEtBA##PHmQEOw@%QZlQ5|v9UOVgw=$ky{kFZ!h6d(FouJDd9m&k^1ciRB zcBiqO9Ifqn7$RD^|H&>oHj%!cCT z&Rz~LG2GeW-5tsw_7`yg`I*oMn!_&9u(4T4@vuLE_cjmRj6N_VEQ~4D(b>|_aCuVZ+yX9fn z)TLt`Sn8U0SE^=y`1&x7!J=U%AER4-S1f$ce8m3 z50oef$V`##IME4b`L;(XALf$->B+u(B+2Y$IOq5%(cp5Frn@1|zs&Jl99{LOB76U% zDNQfFIpW<$_7NVq_Wr*22#@R|?NTrH9>L4o2AlVGIS#V_UnS4&aU8UBs(6}rD>$#n zyhWa)yDhb2W`n~HFS|W~>)=Ks)F2vs+%XPT>Ongrge<5cm%pn*1q; zu%NBnIha*m#Rl+r@df_?E9|0qW$P;8zlw}69F;|7E5C50iptDizi_-N*<*N-_BVq3 zsliDo zqbWD=L-$am2ZGnOdt{~$LpuAqdE+aGFLS=P1sWu*5oWOEGma?x)6H;2GHmcITbyw; zhZh$SZB|Lws!L&fz_mwBpYp5z)Vdndt5547&!PT19ktqKV7_AzV{dP!Y3Cf>S?|qs z`J7{$Jx|*9Dt)f1ZJFvz7rt{u=mM6=>1TKI#bah!@f#ZJf~>CvZYi_ZP`n|ZHZqcitbJ^S+>uePLmdiI0k z0qeer9-MdVV^ufN&L15$SmY-2>W_|CDdhW&Xg0W{*?i=Sn|;Get;G^Hny}|RBwLuk(M+U35fiC;u$MxgCI>tND`D_WReF_}@5<9Zq?0&^@2*+%#r{Lcl16bmE zn)aJx91B`ckAHL2sMG?QLzNP9T6zMDxiBZM!Q-GcA0yIN%=F(K*Cac}EuWkJKnEBn zJLas}{hH&PWXAx*o#wWGB>uhPm{UBi9&cgJSd?vrjKG}Y31*H3=Dc{_0nF*XB{1h_ zHysZhE${{$$OE?=E3KBY%Bq#x!m5_fKY;Ie{%UED@3s1iU zHiK4MVAFRs2bVw62NdWLb4Y};!mj6Wo7dJ8zXrQ;WTR{oIC2iY`EEpr88*Y2 zDw%a-mDgM>!^cnn$tntfB)qRc3rNmgD1an41=+lz&*PLvU?C)3NV10V3-Uve7x1xn z9VLP9ikXw7@ZVr|Bq`H)={S0Qxig5`BrElh9Ue#Xl9fJ~kKENz@uMD3mGbQHTneqH zEG$=4rqp&n9W5MLNJr`^4Xk=>^_BLb3bSi{Wrl=0E~O}mjLqeSA&in%I^zRhs6*#< zc$_Uny_C7q*@!-Cpxn2bj<+qEQ`$86%{7A?DZr86%`t%^mrJ2T=74(uK{&ii%yz>& zu5ild_M1cJ8Y{8vwK?>xF{YE+&!NyJN*rrC2h5-Zvy?eBq>0j)Rh`4(Utd-h`TO!Y z?e`_m3B#EO(|M<D6=xlbe`UM6Qqo37~W57{lZ>cn5U(BLr zEtR>x8)xwjmH@%`XVKM`N`uHn;yy&RAqQK2xqmO_7fUsg)rI0P1NnUCA`uQlBrX;h;GieCF z;>9g#`0CCxNo%JJVaYQsKo~cZcDGZm`TsTJe-YuW8ML##(k%1>o>@SetNMW42J?C6 zf!k&^-}c=M)3*cWdVMHdC8iAP!|hFE43jQN9-1ORJpg9Wv4{|j}9kS zlUcNOjDlaAVo*c?M{ze*wt(Xu^ZHn2E_Z0N>@L)J%iKRf5vUPw2-N7Vl%qz6m7%z) z%3EAj%NAlprTM%Cffz*wop`^NV}W#=9%U-Y_I!_Un+r4QC_6OEo@3xTKf>n1jNZuI zjj##KDBU*K&s3IkuN2h)D)!*bLeJ6Kc}g?oI^-lKRidy)j!V{qEIKn^N#UB1ycQ^p zrR!#g1?ZD8_p~nK0?C)622L=F6wE*PdUFar%Ia|eu#_v(~ zIAA~5SGDkC_@_#5$5!s{xgg|cpDKWmo-PQidRT9Ci#ayFXOc@_ieHQJ>9? zdU;BCqQGraQyHy#qO{=_nbFNBN)Jrnlo<7x?%b%)3Q?_pN3&nH?ZAMuslqeMwlnJW zOlcu%GPgfdM)CFX71TsFx?8bnPbde0FGi6r%RajdjcBJeUiL)&oloORYP`+Xt+ZL6 z-OX%;z1}3&yc?z2)EOAvdJTcB zE*gH7P}I7%GRTeWqLrfrRh`XsPqws%4ykIIG@Cq~YNVde@e!{M@GIG=CQCsR5yk4` z>%u`;1~CqKj)UfKQ(F$(g#zII*hK&^R3hsyRzfv&^#SwjO0kBzkNw((t{U(kf9PWR zd#bTg(5x<~yhcgo(~-9-@8*R;{H?QP4uAJjb^Ntv!K_H~^HJa7Sc`zQ&X~Q+sM(B_ z?@af~s*yE(J40cV0$g4qUjn!^pblV0CyEPH$FVydX-lA5J1S4Do|v=EfPlF16^6|n(~IWm6Xvr(75HjU8Ebkq zP!aNk?Zd?kYm4$KpJC+>g<))(&QVqp2>q9AL981PzgEZyh$Y@lRZT#w0`PrIs!9S{ z4GLHP1Med{Fha#D2>w8X^J+z^@3;yIVD)>H+8m=ebiEn(ih7BM^K3GQRP*6FBgw&3 zv|oNqHMtl^K@Ksi8fW3C=V^RoOK{YG$iIxErid~Yj(UfuU&2v$(kvYHXPOH~g(Rp0 z5k5ofB69Zx&Oh&!6}dz6c`=yD5s|x!HB`(q)@h4Mxg~K$?rOBPAeFnQfK;7osk0-0 zYlD)dAl0utpXi=$49xwdjfn^z{#+5Qi{M?=M76*-0Od*t@5;8}kSdvBWj@eUcXLl& z6=(TmwRQ#X2Gv&)yzAS_0#;QUssL8aTXJC4SHah0^RKajclKA+3_ItA>|%?N{mw?G z%VM-tZ(+eaM5^rai)uLgrdct<3bpJ8$ROf)mX1u|alHO4zPSaoqMBPkODImvgaK%+ zcbN=~pNQVQ)=owAPUvFbbjYQE7$?P%BY#Z04t-=W>8t6UQ+dN=3|7129kE3VXV zp|9V2s;_gVLbXEkXZBV_3=iECF}z->9C}UQ${4ZfIAxA`zn^MyaE5Lnj28m0Xeg53 z4pE2O?CphD$RliR(c9G7^`k!SL#z-6(=_0OjX8yFzGE-V&m)6 zlyNF{X{}Ey$EmSwKz;gRoEpk{)~9RZ)VR>}`rtWNoGq-08;DtPw$}Bj#@lLRmR#S8 zvn_pFZOS6*(}lOypWzy>r+wqqIrgIY*m8@<+4fDucRzo$I?RnYUVku686-?qszATa!#TCZl)Dl1*)jdR__+69r39RC(k%io$@;eInOH zkeA2UKpKIf&=$0ezlEZ1WvYd2LlT|OLWL`n=s^}lWL^^0n1<`5BpNYI?aTTl(Ya~r z5S&xXQB*zDH*vap&Hs7b{{>Nx>(aP))n=@)E**LoBYLH-dEs3ZfT=eMmkz7FfjkFH zExD}t(F&U*TuQX8#H3j&K$EkMnVhWxH0`fV6LZwaQAIj*}rlm_(=)m~nN z(j3TOMxH{~sr?aYz`oQXjFx6btXF}C@=(r&hT52aZB}R6(cdhZn5$NYT%Zmhp*>bg z1kXfms06{YL3|Aawfa!)ENZbZP+O|LLru2fph$DX4)vVP>n0T2(A4rdw{V?*#Z23! zc9$G?k-2+?cJ78@Z)^U%TU}!3u3I*5kYgY#lZ7wf5i^M4C+cs-1w_zHltuv_G?QAI zbM~tPC9kTef``lawHOB7M`kGt;xMQTQ(QUf`nmc_fT*NeP%#b?qj>~jA|564isige zf`c^VU&cWTVt5$~2hHW_w_l8sJ;lA3anQpUj)Qi=CFZ@dAkZo9J6~x)fIunc?U_QL+>cy36yWaL~=lCW2+YHs4BkP#OY7R<`netZZctfi{a?S#h$8->AdbzDgGU>3s$sA}f5wM6j%jot?vyXbyee{6TFEh0VXj z!aYrYR;P-*06k0<^MgtD{CB3;6V_|_FX}Dkbj=M;jTB&qb8$BC?2wCUutnvFNDJ#+ z#U}rEft|L#BM9PkWJOQ>ibZp*wOW_+LL*QTBrssW^>92RMX}!^*&SF zw*YKX%y;jrpV*3TS!V8`n!%K>@ZwOsC?*YS{ioKn1)_3$4iA={Sba|A6Re+ZU+ z<{1S@Z~vc2Sw4#TU^|0v@#R=y-P3R`@WJ;Tp*tbYr#xZaso=aSE2uJ?PmS{rsZAqQ$?J}G`CmnvMaa6RkChO^K1+!kL z%oWTkG@UU{1hYir@$7Fe%YaVs<_6TCR>wNCSvzlTMQ3oe73zXBD!!A$8Ghw(hF>|H zIS(y&zAx4z@BmW%YECd~oEL40cXnq1UOa#lOd$!*VVLHdli-Zhi#T>EghLMOvM<32 z?6S)9#n2HU&*8;&>azINxdw^-rdM4jVnp?I8d1*~S)-;7 z*)9cH;zhm$vQ$C7G-Ro)TQQ=-dd>`nUHC+dXl#AwI{+`+=w5y2LS|~_v=k@6OLL7H zH*^kQ)ila&=p4tqHHvKHtPQ@LkeCx=Kn`5s1>=_Q4i1U*6?0-E=QX|xw@+hdC_u?B zEW+RmLyk9gW^)p+KcZn{>Pc9P(_gj1L)*BAC+V*YXQJa5jO#nc%(zib{33aZs*iTowB30kTPI72)rin$@a{b=6eBWyyabA| zwSOwpN3GRrwx&q@+FG4s>0XSLwG?rz6H5{C2Ijx2xRxT0bABooQFvQO=BLR{AQ`a^ z(Gv>5jbv`Z{ug(Ju4$$v_qeJfApB`JYaw9GjW zE*usGA&}GwskTw{@p5M$h-t)1t?cr8N(kHcH#H;YfO7o(V&&`#A#J521m!Ghcur0Z zirPk*9p7`lh5udurqe5&!Ki9i4)%O}w89x?lm3=z?-@V+>X4$9qlm(Fc-CbOk?$txGv8F#5wuCp&2c9(YMI)~Ugps8=4%Sr6j zyVPa7^P0bk3SVBNXuC`4A3B?{zwXe=4?(IMcg%esI)SDJ-{Gy7grE8&&(RciHrfe+ z{o=Mvy?%CdFkkz~2`J@z%k=-m2`F{+CUx2GjI6i+rq%h63R|2K-kbfCUZNDj# zcTX&j{(ir+H=BEt>KwojPeZK-U=iUX(Srj{{P@}`BGHAVo*Z;0BEl3A;EFIk{M@PX zmCvw6;cQ!?Wr^NA&Mncl5=&%z`X_YNT6Gi`V64AOveqYx%=#oN#N>W5@=G{7`7tOX z7AFcjfifb-Br*}n9969}pPqCAQ}L26O!c+-%{NX&n1BJ3tOyh8%;T+zb&2kbfL5p} zF9tPxYyHZ_i zW#SHKj2%~Ou9b=IX50Ph>}_?8<1A$x3dLNpiC_~Sm2BQmfwn{jy%9?kQ4CJF&9y{v zKAdZgx%jmhbM3*)OCu9qp{GvQoIh!G&Os#rtSs^`1F+@4@-h|xTf))Y-!D&=O^1;bijrUrMN6+}6+*IiiMs3(_Dq!j*o$n&M}*ZoVF zqCKhhF`pDU5r~S%xmf?{D`tKF#6eXgi5d;*3o|HnCueSXm#@sAT* z&;Ip`Okd@zEzP2bPDG%7xnMqf;#>fW!$*73bEgjnWBkn>$~7BKC$pvxS7BJ+*_dQa zA6{hIErb!cOD3idXa7XcY}%{f0}Q+fH-QR({^0_G+5Y?qcJ56_HTDb2*|lZxvoJzp zwc_`(Hk2DX6jmEW)zkIovyvQq1=QwM;H;XkTEl-XR(m zEOH8(Vc}XHto2Yl5&+C63I_p&33j`}1jrKU2%CsBLB6tM`o!}{Q-N1`aG+I$hnd7! zM5sBU2v$`i8G8^Y16o2PNXrd zwKm)^C(^OjS`SR(Mzqo5*_bc5S?}czB4vPXFIaa#FP!hwMibUOk@U7&3sH&LwXN1i zVt<{W18G_?Y6DIE=z5wKW;=1Bv~_=>MwfLTWDakqRpzsp+`X`@dl$S_V%;wyC#<_q z2QAyS8#!3_6e{STHMbSTtT$uRwc1ih9!Fz?Ap9JS@heAT%fWExSzQxo4C_X7j#F?K zEuBp|P9wT#Q!q(*yNecSE#KpB0D}d0)qug+aruS#(X(TacwjKhv~s^?_z#XSTd!j> zE&9Qcidz17?ZsNix108WEjvb9cWs|-APW9wsMT4IW9EbI8gQ65sw*8q(%sc_Cye7T z+fe+XE{xjoH#7h-*J8a$y5B=96-8>)OG6ZC;}JU7M~ken@(9Ge6eL?N@+FXLG4iD$ z*}@}Ksjs%24LU-H`fAH;`G_KQ>8CAZp-0SX{WJivorh^le{BF;dYHThXye$p!!&b% zR-@8v9V+=mV$K|hPs}ds=P(uH=ME%s=JQx%UPf7d!b_P!8s7$`!yqk+4f&kL4Z;w& zFn0~odU2|k8KTu>4-QdWv>ru+hiFsr?D`O`9)AV{UyhQ8X`%K}hh+Y9KGv@e(|k~8 z)-bIs=E0W@)2gsP57E(K+BEG8l-WA{jfX9LsON|FSbL27o$TTN^UnK+=<0C1Gv&p1 z)GG&N{A_DKOBvC=L9~B_))C$C9H~`i2M$u5ky;$u?mtrN#}*%?(<8w{E$PT;{I5PN zLo?XmgETQiYk(sAGql#M$w6|A(srT%!PuRfDs zI>lJS$!k*XeX-w<=NQq8K4Z{}&7aZSF&fU#p(Dk2foO5$GaLUIW-K(E7R1qfHa`S< z*jOzPP2k0{l+TO2@fqzLi*IO&!(lc2VJte2ea6RWA*|?A>N(E+dfoyJ8^7My;?3jZ zv_ZV!l}}OOghg5a8}%uLKG2fcKcCW>MOsr@%QM|SrL=4wAk!tk_R$w`+Cj-c;>0iXF_6~@EX1@zQVuzUgEVTMk!wFF<0=~uDRf~v-{}6TrCt$ zJhJYVIgOZn+*r+vKZ>KBaFqRmG0wTgn*zS06{ z(gK{I7r9UH8oqDG0?m}HvI*n0XtohEPP(4VD(~aWHHFRJYw^{Sy*NApa<(QLavx2* zvbE<}ehzJ1Gudlz2?ct47gHclT~;?|Fh<=?fkChZ9;wz(!y>(zLKkaCQQMWp+8BEb zSH5C5%x!yU;u5V39-PG`EI)kL(G;%gB34+}$P}zf@8~5~q&L|{JIm-@X!TOtLYGJ5l zWyr@g_qZ14bYknk!X_*ymUg_StztDkrdBJo^C$&F8gKu5x5dE0G-9O|i7IkdYOk|X zyXnqK?HmdnSp~g2cQ>W&g*w76J*&YY;#C|STvZQdEq2qh)v)H#6to6B5kte*pzX-r zw0wYihpi#x6Q!f~j$w&04TU3>{pHch2mhYinWmqRlezYeV^O z1DNK;e+%oNb>7%TJJ&($MDzJ!p99c3-vsH2X2^PN5-+%71N8g(Jla_vJkfm@=ZWUj za-){WKF_llBOVoO6dk&<5l&7FJ>3XNPoTD&AQkuWX!$1SJF7*mYHY3Y0zA_*p|Qyuyq;y2Ecpn-#X83Dky3<+9Y~1Bl;;)M2Gop4Oey z4D6c$bsJ4PJ`h!Y^MO{yp1?mVbCTv~`fSzO^H=+9(`w?>Q1MpYHq-zv+lE>b%-h>E zY)EXCVC#08P)`ntMf*^LD6V)u#E7_BZodP1pvq3J2l#;=3wLO~^vMX#%iOs`!%P{cB3pebhY`F?evfs_x6a-cEP+30^K^!cT~y924yE-gd!s zoP}Wb)}n=5rWVLw^P_xZ*`)0h_le-YZl8evcuTMxi+vn)dB5h*wC#cg@lBowwD0&g z!PZq_@8*)%XRvJQc4|;VpTdUcS`2q7*V04_c5qE(Ry(M9yT+j$^?XGSO}@FUWZYBi z*0{HT9#Z=!aeb8M)<@Bp^mET%g9dpXJ1F;%&_}~R*SfM8A38G$$2Tn4MmIj!x={4H zny1y#Et59gwiS5IkO(ZrflphG#Fx0Is$TMurZ(xUJH)}}Ihw1tvSyWTKIo#yr(TJ0;~ zn0Z?$?su++Oy}1YMK67Wn&d5XC>45S4vt>pj!T2a$lTd%k+tU*p+_o!i;5S7Z=GKL zVK3EVR21{*v~~LH5Anm*w^~;&)Y!Q$A3fjoE&36Gvz@+0Kf+gPenQ1e++3_;0%%~q z_6qZX_mHnOV83ssGx?>8vXsr#vx$!5ap1C^)$UOqhZpZP)x+7fO(lMhUFEjvVN*TC z?!!~<|3#^)uj+=C<@$x%zpBrsP2Xwni8_`Ptqf;FH*qH@j7~Ju%kvg?eh)<}DtOXN z-%1%jXq!q3|FhBZho+s^&RFf`wa^1;*pFI<)vKZ(;h0R{NF!S6ag>)0Ds5}2d(#^~ zX@$H1PIxKQ!jfY)mN5T2Pwm1T0`upo-z4R*c9rs%fQ{E* z0GC^pIxm93CgaB>u6o*B1fwS`M~R;=g3);ie+s<}c<^vNm{lB@+5NJHGk|<(%4IE$ zon237E^9ljs&alsRjbx>Uad`4R%6fK3H9{K6j-2TNKVTntuBB`>b9N^fOUB#=L>)q zojw$MMXRLLL>nIS7gG6C(AxP_|CCmr_FT~_+MQgYaioxCY~?&230?J zpEGY2>d{sAW)s)Zh_28{zrJrVZ#%sHr&fp7?QoMN^G~f1EeHTLrBDk^?)`oVVRk<% zCQPI90ax`syl1>UK<8#U$pr8T!6l%;}Mx*t>427hT8akSPv-caVU;H{Z~`@5XJrrW`}Y~`xnqFX*Es! z7Y>`NpFZvFe(b$fbm(7rM=A$a1L?Jg+I&1OL074(O0*0L33LSw0XtfZu6zjSY8BOb ztSz-(wGh@x{N2S7mTDm^9|FSKj#!emsdTCIm301z7R&iMj}B+TEQdVRhM@#T%LTN8 zR$6X@09s`!{vgJCg#pcCf2RFTV?WkvB_CcyLsT< zF3&YDi5eXSoom0VmESvGuPf0yK0PIXmUD&0z#&Y}q`IdxAIg}i`I(2A9_T8@F&BIH zJ@T^ab@-4sv+JBI1yCH35)#ZBy=QUdx-Z>a`L3*Ujl$7Zxo7keS8}vPqmH5jgXe-P z-*o7lD+S*Ai7c)he-t%cap=v-=d=d*{kHDKJ|>GN#j_RjG@UXPsAo|?z%HUHlsztHuUV5vrA`ZW}>EQ5-U)}Jl6<#d`zXIrUZ+$b5@%!p74Ay6vMcvPQK;5q| zVpLm}(VJOVjO#pCjrpQRV6j*jBCE!GRy{R6&n<=SI>vREV_P9z@zvYmN%gWgB=6&; zFDkCxSalHLr*F4k$I(Ny?ygpqwODGQt3s+?PT$C`d()ZKP#X9rSs*Kv_t!h}+auOs zKBRy;DDZlV$f%~bCpAE?YE^Z3o>r0NEfG#GEA*y?YoWR32k3$P%|mNpUY0JQGXZ+6 zRA@d5(1%LaYYCXlp(#PSKhVY~r(Vt$aJJCg5v0Szy-r!>^(t)jVhdM=2Y|P5~UMm-{$TQheR{7-7YJKM7%+qgLV*N(5a$+pO-5~{CvaYXq0nr zGdA%?F>_|C6YAx}l(L1D{(fH^~Mzy;Y{Nr#gnD)o#8KTKN0r!Y5w2xp`9 zdhRD282!5t-8y_nYeDm4^`-cVh$?zK`*@*X4y%_{S8ECMNfqb~@ze#uaSECMLWT5J zRWx>;PF2+_v(^hORdD|fMlrCOp22C5Pl8R#FSM|b_;i7V3aUX(*m=>f*J^?G=L^u6 zyjmfCR5uP{vhFIrq+6U0m?s)`S+H~Qx_{6D6#ZYd!MR9E02fiwKOpdp>bgHu7FbXT zr?3gAR5ahx61^9cKqV@Cil(a7)WtD-)obZBlSj-iA;aNo78z8o*8dP>C|2u*xaam2 zK?V+#*46?UM2!n-V`R|zD|Ns;N9S1rUpEl~A9xQ9o=DVzh#<1Hbj-jW(?UH{=0T!u z)~PjxIH3)+!YZ*OP%vskO@ZI40dUKT8RbQ_xb)a3<^Z?O6dRkxaYTbut!NF?uTnp~- z-c!s~DEbdmV2s48nCQKVBF0?0lcL936|Cr}S2o);(4#?+zhNyFHU#O`&iTJcR|%v$ z*w9h{Iq)T=K$2>}15P-DN>|S*1&R=s<7(bH3iZ6`cIfm~V?6>&;C5qZkPdSwxCwL? z#{ck)P)l4sIVVZ8Ui@l8i`nRc$tyXX}NGUiYvSPXfa3-A7 z4KLSZmuHm#8Pt2FnH~V0@TeJ-vAf8iSu~}E&urt6((Q-B`LzIvB4QV{(Y zplcQ*g?H2gtykJ##Vh!47i?5b6fnU??eN1ZZ%Y^s!A7a?{@-kL(yZQ@YkhZL`w?2<`%A&YFdb+fqvij%^z2dWY0Ip#U-=*N`@l)K{-*UCNv7`@*QR@tHJbfIdY!1U+E9W_BJ36+`*qdM#FOD&_Vt;?=L` zrnmH1H#(mN57zn4lM4nzJ=L0O?i{SoWz3k0n3&!eE7m3t)9bNrQ|Q1jy%L7^$}rd! z+%7XxPYl{S*+O0S+u5;Yth}ud@ua^IPdY_?M(Wr?lAey#qijK@MIIQ@f-0FQ_m9=dImwkWwrwe>oS7oh*t(@4 z%9WmgbXaCeH224`g-b#C%#`w4X1d5@3m3ivk4R(dgo3iJ^mVh&Xnlyp%t_{kG4NWX zedhkLx-PM}N#+-C>1Po|kBNykSB=-7+I^EIVyLN6jz^o294U5sdhLm3?quD;KYrI# zy`Ja%30%p$PnLT$Rd3?0p);*wqI0%m_J%LZTy)LwH>-WDx8_U#c4T3I{U&hzUx%%j zK#pnnZm$V6!r!PuDSP$SZ0H0!Gz~shK3$(CXyQ2?cTbI{?$h-%!OO;DdB?Yna?VHk zaEzM@#eyJ^<0US8BaSuG2&_POnnLKJf5D-#HXI3D<=&< zikXE$-}5%5&BDEt)PI&f5Raf)gDea%_igjREd7wJTt2jBabTV=V?LIIok35{(-Wo7 zNSd$rZJnPAQpFywH}5+zZ{N{JQ~0&txT7iWf$@3z&51`-%7TRbD;-T)0><}4dL|g3 zUuS{w_ki)sA)R-_+&N#r!^%MHvh911rSPk~|5(Z=v}2Jzl&yG+g0sPVINB>4f|zag z$ksR7q_w8B6eG%)>@C+5*9wT8^hT$I!Xu`ULNyMyU4&W}fPH*O30HjWxxKtHA2psKYtH>%3KZc+is3|ErapU-J|DuCLO=P`PupK2a~~ zjY@B#(mwmmg{$=kyf31T%;l0s8{XIbZ7W8V@V-o!-q#g$@Q?RlsJBwJb)dz(QIx(8 zjPTAVTD(rbGBw`=br#gjOey3GkI~tJ_{@|LIWzsAPaEazZQL-Y@DC5~fcBZ`%Q0

Quu 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 z zjho#~8{=%r!Sj-X=WT7lhsp#8&v)Su0cx%G#Bu?OVUC4^t$v*x%#j?t zAUSx!cIbo`cu#P!U^L_4#U30S8qGMsuhnb~HN@F=c8?RCGibpW#=%S7tTwzPIe1BO zfCg5bU*erz3@`U|AUN3SZ_B~Ul7m+)9P}N_ICw>fFul@Kgc=v$O&epp;aE z42*-=L9*l^ z*|syDAm;>T(DVlw2k&&V+VGC#;2p^U8d!CHhj(@{r1W$kI9M8F%R!3dV3CD`)*!~g zA|b-GsHX@uF14FBMr;#dSE%mqN)Fz&wFMvD5^K@BT{u|Wg@eVCgT;~q)LQLX%mpZh zB^C}AOzz}hiR2(na*$>_bV3^M2@a+NGY*#a;9zYq<6xQOV3}=acYL3QO`;5%GKF!l zyqndA<&uNtk^?lb>b#tHb}<-xIuINzm}<*`QF8E}g@f9ujDz=t2-AB#MW}Hrx@luv zAvstnIaq0Hi|a}*OJiKwg@g1i9HdJQ(j^C|wc3-;1t^C1EgZ~wxRZnTB?qe{2div{ zPFTfzf`hS-Fb-Dt;9%(^j01cwn;#D{Y&*MWh|U=__EE;c2i>eTd>}daKyrWvR-HfK zom~uTdO8ps%n7ySV2$M9LkkBdLKz1i3K6Ccdx}uwGP`MG%#<9gl^m?KwZ(NUmxZ5P zx^S?r3kT~Y2kRsUsI}U&jtfu>>n$8if2@;(^^$`u$w8Lw&>q!a+_K4ss+1Ig$g^TJ6c<0u;l? z77nIN@8sZP$-x%M!4})06SnZ4;Gpl5jDt^la4_dd#sR(t$mc<>ZD;pf(K&=YO+pyjyG_dNtm3MYAZ0qSja4;pxmV<4QgHJ6S?2cj_d@4kkKJ6(&jmzt% zjWJJh@E^&+e{5}W{STL=G5)6u2cLD};4{g=XOaWdTJ8Ca3s4N7TR0f|OeY7QOAhiS z2l=)`C*U(-;=IT{nsM+&4-TeBGY+;(4z}BNcHb^K<5i3^83$i>v)b^b=L~9{%{bWG&1%D5$-!R90UB6!-pf0?820saAUGHjYs@+o2Omcu#Op`y%7uyB-{jjbj`fkQ^Ma?d*>4 zw2AYg+Bn9+!ERO?4oVIVN)FJ#s`EkK*~L)W(}Cci@5{CvV8a|ctxPy%;b7^@jDtf$ zgy~RE5o+A`-Lx@&FFE)@a`1z#Ev`RsSsLRHT{tM~!a83#Xg zv)b^JrpOCV?5f0gJWGdI3_tbCOJT@)t+NqfMPgq;h=S1CkJ>r0>5WhDLJUL z9Xg?s_XG!r<}(gX^x&XxBIDqs_2Fxhr?H;K;p{opOe!I^GW8_q}$u;-Sa7omYw=QF&si{Wff2ZDpzw{1B%D>*o4 z;b3|)N)BpmZNc|D#4)+H3kT=BaByC7a9(nNTB|+h zxc~*Rit|yBHdJIuIP3c-NML2Fbx?3kOpcGY&2b5vI#MMW}I& z-Lx?_N)DPN2TiuN;Q3*}K~onF%w0IZCky%gBD~Ly9}iG#wFloU#KBQ9T(NL)D6Nx& zE0P1e!9Q-9Y_)BttTB|*OaRG|qZwm*zS9Eglx8$H*a?ox&bV57t2@aO7 zWE}j{gM$+*83#8c2RCdxyWbF<@%uqK-T(T&KtG#MlNTtliy_*ZF3uV!1Ih} zH4b?$#pKjeiW=wKO(!D?xK8dGsgo}fR-;^zW8ySMjSyErCwl8gs&+2d>7c*vZpzHj zJ8N8BL?te0`k*o!m3T4m-Bg20p0f%}MjaEVw75{<7X28dmlTwSeMt7bXca4SmHjK( z-Xvsr_r(7Cf%M>d{V02>Lp5rwI@Gy#(IK(7tqv?_)gcl&Zd7^iE=Gm)u@xBEr;9)n zDy>Gb92dy8WhuyTpBwI!@@$w>3-1(C`�lM7AoSd)N+=U^k1kpRi44$XPY@MvhC) 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 G0000)b&bCO delta 473740 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 z%0A-+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

Y904o@oC+)tTny|9Tn3y8Tm}5O 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 diff --git a/engram/dist/engram.c b/engram/dist/engram.c index f43fca5..9c3ffce 100644 --- a/engram/dist/engram.c +++ b/engram/dist/engram.c @@ -130,7 +130,14 @@ el_val_t route_create_node(el_val_t method, el_val_t path, el_val_t body) { el_val_t node_type = ({ el_val_t _if_result_2 = 0; if (str_eq(nt_raw, EL_STR(""))) { _if_result_2 = (EL_STR("Memory")); } else { _if_result_2 = (nt_raw); } _if_result_2; }); el_val_t sal_raw = json_get_float(body, EL_STR("salience")); el_val_t salience = ({ el_val_t _if_result_3 = 0; if ((sal_raw == el_from_float(0.0))) { _if_result_3 = (el_from_float(0.5)); } else { _if_result_3 = (sal_raw); } _if_result_3; }); - el_val_t id = engram_node(content, node_type, salience); + el_val_t label_raw = json_get_string(body, EL_STR("label")); + el_val_t label = ({ el_val_t _if_result_4 = 0; if (str_eq(label_raw, EL_STR(""))) { _if_result_4 = (content); } else { _if_result_4 = (label_raw); } _if_result_4; }); + el_val_t imp_raw = json_get_float(body, EL_STR("importance")); + el_val_t importance = ({ el_val_t _if_result_5 = 0; if ((imp_raw == el_from_float(0.0))) { _if_result_5 = (el_from_float(0.5)); } else { _if_result_5 = (imp_raw); } _if_result_5; }); + el_val_t tier_raw = json_get_string(body, EL_STR("tier")); + el_val_t tier = ({ el_val_t _if_result_6 = 0; if (str_eq(tier_raw, EL_STR(""))) { _if_result_6 = (EL_STR("Working")); } else { _if_result_6 = (tier_raw); } _if_result_6; }); + el_val_t tags = json_get_string(body, EL_STR("tags")); + el_val_t id = engram_node_full(content, node_type, label, el_from_float(salience), el_from_float(importance), el_from_float(1.0), tier, tags); el_val_t saved = persist_canonical(); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"id\":\""), id), EL_STR("\",\"content\":\"")), content), EL_STR("\",\"node_type\":\"")), node_type), EL_STR("\"}")); return 0; @@ -158,7 +165,7 @@ el_val_t route_scan_nodes(el_val_t method, el_val_t path, el_val_t body) { el_val_t route_scan_edges(el_val_t method, el_val_t path, el_val_t body) { el_val_t dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); - el_val_t dir = ({ el_val_t _if_result_4 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_4 = (EL_STR("/tmp/engram")); } else { _if_result_4 = (dir_raw); } _if_result_4; }); + el_val_t dir = ({ el_val_t _if_result_7 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_7 = (EL_STR("/tmp/engram")); } else { _if_result_7 = (dir_raw); } _if_result_7; }); el_val_t snap_path = el_str_concat(dir, EL_STR("/.scan-export.json")); engram_save(snap_path); el_val_t snap = fs_read(snap_path); @@ -174,22 +181,22 @@ el_val_t route_scan_edges(el_val_t method, el_val_t path, el_val_t body) { } el_val_t route_search(el_val_t method, el_val_t path, el_val_t body) { - el_val_t q = ({ el_val_t _if_result_5 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_5 = (query_param(path, EL_STR("q"))); } else { _if_result_5 = (json_get_string(body, EL_STR("query"))); } _if_result_5; }); + el_val_t q = ({ el_val_t _if_result_8 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_8 = (query_param(path, EL_STR("q"))); } else { _if_result_8 = (json_get_string(body, EL_STR("query"))); } _if_result_8; }); el_val_t lim_url = query_int(path, EL_STR("limit"), 0); el_val_t lim_body = json_get_int(body, EL_STR("limit")); - el_val_t lim_either = ({ el_val_t _if_result_6 = 0; if ((lim_url > 0)) { _if_result_6 = (lim_url); } else { _if_result_6 = (lim_body); } _if_result_6; }); - el_val_t limit = ({ el_val_t _if_result_7 = 0; if ((lim_either > 0)) { _if_result_7 = (lim_either); } else { _if_result_7 = (20); } _if_result_7; }); + el_val_t lim_either = ({ el_val_t _if_result_9 = 0; if ((lim_url > 0)) { _if_result_9 = (lim_url); } else { _if_result_9 = (lim_body); } _if_result_9; }); + el_val_t limit = ({ el_val_t _if_result_10 = 0; if ((lim_either > 0)) { _if_result_10 = (lim_either); } else { _if_result_10 = (20); } _if_result_10; }); return engram_search_json(q, limit); return 0; } el_val_t route_activate(el_val_t method, el_val_t path, el_val_t body) { - el_val_t q = ({ el_val_t _if_result_8 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_8 = (query_param(path, EL_STR("q"))); } else { _if_result_8 = (json_get_string(body, EL_STR("query"))); } _if_result_8; }); + el_val_t q = ({ el_val_t _if_result_11 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_11 = (query_param(path, EL_STR("q"))); } else { _if_result_11 = (json_get_string(body, EL_STR("query"))); } _if_result_11; }); if (str_eq(q, EL_STR(""))) { return err_json(EL_STR("missing query")); } - el_val_t d_raw = ({ el_val_t _if_result_9 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_9 = (query_int(path, EL_STR("depth"), 3)); } else { _if_result_9 = (json_get_int(body, EL_STR("depth"))); } _if_result_9; }); - el_val_t depth = ({ el_val_t _if_result_10 = 0; if ((d_raw > 0)) { _if_result_10 = (d_raw); } else { _if_result_10 = (3); } _if_result_10; }); + el_val_t d_raw = ({ el_val_t _if_result_12 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_12 = (query_int(path, EL_STR("depth"), 3)); } else { _if_result_12 = (json_get_int(body, EL_STR("depth"))); } _if_result_12; }); + el_val_t depth = ({ el_val_t _if_result_13 = 0; if ((d_raw > 0)) { _if_result_13 = (d_raw); } else { _if_result_13 = (3); } _if_result_13; }); return el_str_concat(el_str_concat(EL_STR("{\"results\":"), engram_activate_json(q, depth)), EL_STR("}")); return 0; } @@ -198,9 +205,9 @@ el_val_t route_create_edge(el_val_t method, el_val_t path, el_val_t body) { el_val_t from_id = json_get_string(body, EL_STR("from_id")); el_val_t to_id = json_get_string(body, EL_STR("to_id")); el_val_t rel_raw = json_get_string(body, EL_STR("relation")); - el_val_t relation = ({ el_val_t _if_result_11 = 0; if (str_eq(rel_raw, EL_STR(""))) { _if_result_11 = (EL_STR("associates")); } else { _if_result_11 = (rel_raw); } _if_result_11; }); + el_val_t relation = ({ el_val_t _if_result_14 = 0; if (str_eq(rel_raw, EL_STR(""))) { _if_result_14 = (EL_STR("associates")); } else { _if_result_14 = (rel_raw); } _if_result_14; }); el_val_t w_raw = json_get_float(body, EL_STR("weight")); - el_val_t weight = ({ el_val_t _if_result_12 = 0; if ((w_raw == el_from_float(0.0))) { _if_result_12 = (el_from_float(0.5)); } else { _if_result_12 = (w_raw); } _if_result_12; }); + el_val_t weight = ({ el_val_t _if_result_15 = 0; if ((w_raw == el_from_float(0.0))) { _if_result_15 = (el_from_float(0.5)); } else { _if_result_15 = (w_raw); } _if_result_15; }); engram_connect(from_id, to_id, weight, relation); el_val_t saved = persist_canonical(); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"from_id\":\""), from_id), EL_STR("\",\"to_id\":\"")), to_id), EL_STR("\",\"relation\":\"")), relation), EL_STR("\"}")); @@ -242,8 +249,8 @@ el_val_t route_forget(el_val_t method, el_val_t path, el_val_t body) { el_val_t route_save(el_val_t method, el_val_t path, el_val_t body) { el_val_t p_raw = json_get_string(body, EL_STR("path")); el_val_t dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); - el_val_t dir = ({ el_val_t _if_result_13 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_13 = (EL_STR("/tmp/engram")); } else { _if_result_13 = (dir_raw); } _if_result_13; }); - el_val_t p = ({ el_val_t _if_result_14 = 0; if (str_eq(p_raw, EL_STR(""))) { _if_result_14 = (el_str_concat(dir, EL_STR("/snapshot.json"))); } else { _if_result_14 = (p_raw); } _if_result_14; }); + el_val_t dir = ({ el_val_t _if_result_16 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_16 = (EL_STR("/tmp/engram")); } else { _if_result_16 = (dir_raw); } _if_result_16; }); + el_val_t p = ({ el_val_t _if_result_17 = 0; if (str_eq(p_raw, EL_STR(""))) { _if_result_17 = (el_str_concat(dir, EL_STR("/snapshot.json"))); } else { _if_result_17 = (p_raw); } _if_result_17; }); engram_save(p); return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"path\":\""), p), EL_STR("\"}")); return 0; @@ -252,8 +259,8 @@ el_val_t route_save(el_val_t method, el_val_t path, el_val_t body) { el_val_t route_load(el_val_t method, el_val_t path, el_val_t body) { el_val_t p_raw = json_get_string(body, EL_STR("path")); el_val_t dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); - el_val_t dir = ({ el_val_t _if_result_15 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_15 = (EL_STR("/tmp/engram")); } else { _if_result_15 = (dir_raw); } _if_result_15; }); - el_val_t p = ({ el_val_t _if_result_16 = 0; if (str_eq(p_raw, EL_STR(""))) { _if_result_16 = (el_str_concat(dir, EL_STR("/snapshot.json"))); } else { _if_result_16 = (p_raw); } _if_result_16; }); + el_val_t dir = ({ el_val_t _if_result_18 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_18 = (EL_STR("/tmp/engram")); } else { _if_result_18 = (dir_raw); } _if_result_18; }); + el_val_t p = ({ el_val_t _if_result_19 = 0; if (str_eq(p_raw, EL_STR(""))) { _if_result_19 = (el_str_concat(dir, EL_STR("/snapshot.json"))); } else { _if_result_19 = (p_raw); } _if_result_19; }); engram_load(p); return ok_json(); return 0; @@ -266,7 +273,7 @@ el_val_t route_health(el_val_t method, el_val_t path, el_val_t body) { el_val_t route_sync(el_val_t method, el_val_t path, el_val_t body) { el_val_t dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); - el_val_t dir = ({ el_val_t _if_result_17 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_17 = (EL_STR("/tmp/engram")); } else { _if_result_17 = (dir_raw); } _if_result_17; }); + el_val_t dir = ({ el_val_t _if_result_20 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_20 = (EL_STR("/tmp/engram")); } else { _if_result_20 = (dir_raw); } _if_result_20; }); el_val_t snap_path = el_str_concat(dir, EL_STR("/.sync-export.json")); engram_save(snap_path); el_val_t snap = fs_read(snap_path); @@ -305,7 +312,7 @@ el_val_t route_emit_ise(el_val_t method, el_val_t path, el_val_t body) { el_val_t conf = el_from_float(0.8); el_val_t id = engram_node_full(content, EL_STR("InternalStateEvent"), EL_STR("state-event"), sal, imp, conf, EL_STR("Episodic"), EL_STR("[\"internal-state\",\"InternalStateEvent\"]")); el_val_t ret_raw = env(EL_STR("ENGRAM_ISE_RETENTION_MS")); - el_val_t ret_ms = ({ el_val_t _if_result_18 = 0; if (str_eq(ret_raw, EL_STR(""))) { _if_result_18 = (172800000); } else { _if_result_18 = (str_to_int(ret_raw)); } _if_result_18; }); + el_val_t ret_ms = ({ el_val_t _if_result_21 = 0; if (str_eq(ret_raw, EL_STR(""))) { _if_result_21 = (172800000); } else { _if_result_21 = (str_to_int(ret_raw)); } _if_result_21; }); el_val_t pruned = engram_prune_telemetry(ret_ms); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\",\"pruned\":")), int_to_str(pruned)), EL_STR("}")); return 0; @@ -317,21 +324,21 @@ el_val_t route_capture_knowledge(el_val_t method, el_val_t path, el_val_t body) return err_json(EL_STR("missing content")); } el_val_t title = json_get_string(body, EL_STR("title")); - el_val_t label = ({ el_val_t _if_result_19 = 0; if (str_eq(title, EL_STR(""))) { _if_result_19 = (str_slice(content, 0, 60)); } else { _if_result_19 = (title); } _if_result_19; }); + el_val_t label = ({ el_val_t _if_result_22 = 0; if (str_eq(title, EL_STR(""))) { _if_result_22 = (str_slice(content, 0, 60)); } else { _if_result_22 = (title); } _if_result_22; }); el_val_t category_raw = json_get_string(body, EL_STR("category")); - el_val_t category = ({ el_val_t _if_result_20 = 0; if (str_eq(category_raw, EL_STR(""))) { _if_result_20 = (EL_STR("other")); } else { _if_result_20 = (category_raw); } _if_result_20; }); + el_val_t category = ({ el_val_t _if_result_23 = 0; if (str_eq(category_raw, EL_STR(""))) { _if_result_23 = (EL_STR("other")); } else { _if_result_23 = (category_raw); } _if_result_23; }); el_val_t ktier_raw = json_get_string(body, EL_STR("tier")); - el_val_t ktier = ({ el_val_t _if_result_21 = 0; if (str_eq(ktier_raw, EL_STR(""))) { _if_result_21 = (EL_STR("note")); } else { _if_result_21 = (ktier_raw); } _if_result_21; }); + el_val_t ktier = ({ el_val_t _if_result_24 = 0; if (str_eq(ktier_raw, EL_STR(""))) { _if_result_24 = (EL_STR("note")); } else { _if_result_24 = (ktier_raw); } _if_result_24; }); el_val_t project = json_get_string(body, EL_STR("project")); el_val_t tags_raw = json_get_raw(body, EL_STR("tags")); - el_val_t tags_base = ({ el_val_t _if_result_22 = 0; if (str_eq(tags_raw, EL_STR(""))) { _if_result_22 = (EL_STR("[]")); } else { _if_result_22 = (tags_raw); } _if_result_22; }); + el_val_t tags_base = ({ el_val_t _if_result_25 = 0; if (str_eq(tags_raw, EL_STR(""))) { _if_result_25 = (EL_STR("[]")); } else { _if_result_25 = (tags_raw); } _if_result_25; }); el_val_t base_len = str_len(tags_base); el_val_t head = str_slice(tags_base, 0, (base_len - 1)); - el_val_t sep = ({ el_val_t _if_result_23 = 0; if (str_eq(head, EL_STR("["))) { _if_result_23 = (EL_STR("")); } else { _if_result_23 = (EL_STR(",")); } _if_result_23; }); + el_val_t sep = ({ el_val_t _if_result_26 = 0; if (str_eq(head, EL_STR("["))) { _if_result_26 = (EL_STR("")); } else { _if_result_26 = (EL_STR(",")); } _if_result_26; }); el_val_t safe_cat = str_replace(category, EL_STR("\""), EL_STR("'")); el_val_t safe_tier = str_replace(ktier, EL_STR("\""), EL_STR("'")); el_val_t safe_proj = str_replace(project, EL_STR("\""), EL_STR("'")); - el_val_t proj_tag = ({ el_val_t _if_result_24 = 0; if (str_eq(safe_proj, EL_STR(""))) { _if_result_24 = (EL_STR("")); } else { _if_result_24 = (el_str_concat(el_str_concat(EL_STR(",\"project:"), safe_proj), EL_STR("\""))); } _if_result_24; }); + el_val_t proj_tag = ({ el_val_t _if_result_27 = 0; if (str_eq(safe_proj, EL_STR(""))) { _if_result_27 = (EL_STR("")); } else { _if_result_27 = (el_str_concat(el_str_concat(EL_STR(",\"project:"), safe_proj), EL_STR("\""))); } _if_result_27; }); el_val_t tags = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(head, sep), EL_STR("\"category:")), safe_cat), EL_STR("\",\"tier:")), safe_tier), EL_STR("\"")), proj_tag), EL_STR("]")); el_val_t sal = el_from_float(0.5); el_val_t imp = el_from_float(0.5); @@ -432,10 +439,10 @@ el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) { int main(int _argc, char** _argv) { el_runtime_init_args(_argc, _argv); bind_raw = env(EL_STR("ENGRAM_BIND")); - bind_str = ({ el_val_t _if_result_25 = 0; if (str_eq(bind_raw, EL_STR(""))) { _if_result_25 = (EL_STR(":8742")); } else { _if_result_25 = (bind_raw); } _if_result_25; }); + bind_str = ({ el_val_t _if_result_28 = 0; if (str_eq(bind_raw, EL_STR(""))) { _if_result_28 = (EL_STR(":8742")); } else { _if_result_28 = (bind_raw); } _if_result_28; }); port = parse_port(bind_str); data_dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); - data_dir = ({ el_val_t _if_result_26 = 0; if (str_eq(data_dir_raw, EL_STR(""))) { _if_result_26 = (EL_STR("/tmp/engram")); } else { _if_result_26 = (data_dir_raw); } _if_result_26; }); + data_dir = ({ el_val_t _if_result_29 = 0; if (str_eq(data_dir_raw, EL_STR(""))) { _if_result_29 = (EL_STR("/tmp/engram")); } else { _if_result_29 = (data_dir_raw); } _if_result_29; }); snapshot_path = el_str_concat(data_dir, EL_STR("/snapshot.json")); engram_load(snapshot_path); boot_snap = fs_read(snapshot_path); diff --git a/engram/src/server.el b/engram/src/server.el index 3372ff6..5e72136 100644 --- a/engram/src/server.el +++ b/engram/src/server.el @@ -105,13 +105,30 @@ fn persist_canonical() -> Int { return 1 } +// INCOMPLETE-ROUTE FIX (2026-07-24 self-review): this route silently dropped +// label, importance, tier, and tags — engram_node() defaults label to content +// and importance to 0.5, so every node created over HTTP lost its metadata. +// Observed live: the soul's boot-counter write-back landed with +// label="soul:boot_count:99" (content), importance 0.5, no tags. Honor the +// full field set via engram_node_full when any of them is supplied. fn route_create_node(method: String, path: String, body: String) -> String { let content: String = json_get_string(body, "content") let nt_raw: String = json_get_string(body, "node_type") let node_type: String = if str_eq(nt_raw, "") { "Memory" } else { nt_raw } let sal_raw: Float = json_get_float(body, "salience") let salience: Float = if sal_raw == 0.0 { 0.5 } else { sal_raw } - let id: String = engram_node(content, node_type, salience) + let label_raw: String = json_get_string(body, "label") + let label: String = if str_eq(label_raw, "") { content } else { label_raw } + let imp_raw: Float = json_get_float(body, "importance") + let importance: Float = if imp_raw == 0.0 { 0.5 } else { imp_raw } + let tier_raw: String = json_get_string(body, "tier") + let tier: String = if str_eq(tier_raw, "") { "Working" } else { tier_raw } + let tags: String = json_get_string(body, "tags") + let id: String = engram_node_full( + content, node_type, label, + el_from_float(salience), el_from_float(importance), el_from_float(1.0), + tier, tags + ) let saved: Int = persist_canonical() "{\"id\":\"" + id + "\",\"content\":\"" + content + "\",\"node_type\":\"" + node_type + "\"}" } diff --git a/lang/releases/v1.0.0-20260501/el_runtime.c b/lang/releases/v1.0.0-20260501/el_runtime.c index e9d633c..cf31d3c 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.c +++ b/lang/releases/v1.0.0-20260501/el_runtime.c @@ -788,9 +788,12 @@ static long el_http_timeout_ms(void) { return parsed; } -/* Internal: do a libcurl request; takes optional body/headers, optional method override. */ -static el_val_t http_do(const char* method, const char* url, const char* body, - struct curl_slist* extra_headers) { +/* Internal: do a libcurl request; takes optional body/headers, optional method + * override, and an optional timeout override (0 = use EL_HTTP_TIMEOUT_MS). + * The override exists for the embedding path: activation must never wait the + * full 60s default on a wedged Ollama. (2026-07-24 self-review) */ +static el_val_t http_do_t(const char* method, const char* url, const char* body, + struct curl_slist* extra_headers, long timeout_ms) { if (!url || !*url) return http_error_json("empty url"); CURL* c = curl_easy_init(); if (!c) return http_error_json("curl_easy_init failed"); @@ -800,7 +803,8 @@ static el_val_t http_do(const char* method, const char* url, const char* body, curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, http_write_cb); curl_easy_setopt(c, CURLOPT_WRITEDATA, &rb); curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(c, CURLOPT_TIMEOUT_MS, el_http_timeout_ms()); + curl_easy_setopt(c, CURLOPT_TIMEOUT_MS, + timeout_ms > 0 ? timeout_ms : el_http_timeout_ms()); curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(c, CURLOPT_ERRORBUFFER, errbuf); curl_easy_setopt(c, CURLOPT_USERAGENT, "el-runtime/1.0"); @@ -811,6 +815,13 @@ static el_val_t http_do(const char* method, const char* url, const char* body, curl_easy_setopt(c, CURLOPT_POSTFIELDSIZE, (long)(body ? strlen(body) : 0)); } else if (method && strcmp(method, "DELETE") == 0) { curl_easy_setopt(c, CURLOPT_CUSTOMREQUEST, "DELETE"); + /* DELETE with a body (2026-07-24): the engram server authenticates + * mutating requests via an "_auth" field in the JSON body, so EL + * code must be able to send DELETE + body. Absent body → unchanged. */ + if (body && *body) { + curl_easy_setopt(c, CURLOPT_POSTFIELDS, body); + curl_easy_setopt(c, CURLOPT_POSTFIELDSIZE, (long)strlen(body)); + } } CURLcode rc = curl_easy_perform(c); curl_easy_cleanup(c); @@ -822,6 +833,12 @@ static el_val_t http_do(const char* method, const char* url, const char* body, return el_wrap_str(rb.data); } +/* Legacy entry point: default timeout. */ +static el_val_t http_do(const char* method, const char* url, const char* body, + struct curl_slist* extra_headers) { + return http_do_t(method, url, body, extra_headers, 0); +} + el_val_t http_get(el_val_t url) { return http_do("GET", EL_CSTR(url), NULL, NULL); } @@ -895,6 +912,16 @@ el_val_t http_delete(el_val_t url) { return http_do("DELETE", EL_CSTR(url), NULL, NULL); } +/* DELETE with a JSON body — required by the engram server's body-based + * "_auth" scheme for mutating requests. (2026-07-24 self-review) */ +el_val_t http_delete_json(el_val_t url, el_val_t json_body) { + struct curl_slist* h = NULL; + h = curl_slist_append(h, "Content-Type: application/json"); + el_val_t r = http_do("DELETE", EL_CSTR(url), EL_CSTR(json_body), h); + curl_slist_free_all(h); + return r; +} + /* ── HTTP → file streaming ──────────────────────────────────────────────── * * Why this exists: el_val_t strings are NUL-terminated by convention, so @@ -5801,6 +5828,14 @@ typedef struct EngramNode { int32_t access_head; int32_t access_filled; double wm_anchor; + /* Semantic embedding (2026-07-24 self-review, bl-b2d1c944). + * emb: malloc'd float vector (nomic-embed-text, 768-dim) or NULL. + * emb_dim: vector length; 0 = not embedded. Populated lazily by the + * backfill pass in engram_activate — NOT on the node-create hot path, + * so bulk sync imports never block on Ollama. Freed in engram_forget / + * engram_prune_telemetry; shift-copies move the pointer intact. */ + float* emb; + int32_t emb_dim; } EngramNode; /* Record an access (ACT-R "presentation") into the base-level ring buffer. */ @@ -5858,6 +5893,159 @@ static void engram_bll_parse_access(EngramNode* nn, const char* s) { } } +/* ── Embedding-based activation (2026-07-24 self-review, bl-b2d1c944) ────── + * Closes the gap named in every heartbeat since 2026-06-30: "no embedding + * call is made during activation. The seed-finding loop uses istr_contains + * only." Design per the 2026-07-21 integration brief: + * - Lazy backfill: engram_activate embeds up to BACKFILL_PER_CALL + * un-embedded, non-telemetry nodes per call, newest first. No latency + * on node-create paths; a fresh node is embedded within ~1 scan cycle. + * - Semantic seeding (HippoRAG pattern, use similarity twice): the query + * is embedded, the top-K nodes by cosine ≥ SEED_MIN join the seed set + * with initial activation = the similarity itself. + * - Additive WM term: raw_wm += W * relu((cos − S0)/(1 − S0)). Shift-and- + * floor at S0 because nomic-embed scores unrelated pairs 0.4–0.5; raw + * cosine in a weighted sum is a constant bias, not a signal. + * - Circuit breaker: 3 consecutive Ollama failures → stop trying for 5 + * minutes. Activation NEVER blocks on a dead embedder beyond timeout. + */ +#define ENGRAM_EMBED_S0 0.45 +#define ENGRAM_EMBED_WM_WEIGHT 0.20 +#define ENGRAM_EMBED_SEED_K 8 +#define ENGRAM_EMBED_SEED_MIN 0.60 +#define ENGRAM_EMBED_BACKFILL_PER_CALL 8 +#define ENGRAM_EMBED_MAX_CHARS 2000 +#define ENGRAM_EMBED_TIMEOUT_MS 4000L +#define ENGRAM_EMBED_BREAKER_LIMIT 3 +#define ENGRAM_EMBED_BREAKER_COOLDOWN_MS 300000 + +static int _eg_embed_consec_fail = 0; +static int64_t _eg_embed_breaker_until = 0; + +static int64_t engram_now_ms(void); /* defined in the store section below */ + +static const char* eg_embed_url(void) { + const char* s = getenv("EL_EMBED_URL"); + return (s && *s) ? s : "http://localhost:11434/api/embeddings"; +} +static const char* eg_embed_model(void) { + const char* s = getenv("EL_EMBED_MODEL"); + return (s && *s) ? s : "nomic-embed-text"; +} + +/* Cosine similarity over raw (unnormalized — nomic emits magnitudes >1) + * float vectors. Returns -2.0 on dim mismatch / null input so callers can + * distinguish "orthogonal" (0.0) from "not comparable". */ +static double eg_cosine(const float* a, const float* b, int32_t dim) { + if (!a || !b || dim <= 0) return -2.0; + double dot = 0.0, na = 0.0, nb = 0.0; + for (int32_t i = 0; i < dim; i++) { + dot += (double)a[i] * (double)b[i]; + na += (double)a[i] * (double)a[i]; + nb += (double)b[i] * (double)b[i]; + } + if (na <= 0.0 || nb <= 0.0) return -2.0; + return dot / (sqrt(na) * sqrt(nb)); +} + +/* Fetch an embedding from Ollama. Returns malloc'd float[dim] or NULL. + * Truncates input to ENGRAM_EMBED_MAX_CHARS and JSON-escapes it. Honors the + * circuit breaker; a NULL return is always safe to ignore (fail-soft). */ +static float* eg_embed_fetch(const char* text, int32_t* out_dim) { + *out_dim = 0; + if (!text || !*text) return NULL; + int64_t now = engram_now_ms(); + if (now < _eg_embed_breaker_until) return NULL; + /* Build request body with escaped, truncated prompt. */ + size_t tlen = strlen(text); + if (tlen > ENGRAM_EMBED_MAX_CHARS) tlen = ENGRAM_EMBED_MAX_CHARS; + char* esc = malloc(tlen * 6 + 1); + if (!esc) return NULL; + size_t w = 0; + for (size_t i = 0; i < tlen; i++) { + unsigned char c = (unsigned char)text[i]; + if (c == '"' || c == '\\') { esc[w++] = '\\'; esc[w++] = (char)c; } + else if (c == '\n') { esc[w++] = '\\'; esc[w++] = 'n'; } + else if (c == '\r') { esc[w++] = '\\'; esc[w++] = 'r'; } + else if (c == '\t') { esc[w++] = '\\'; esc[w++] = 't'; } + else if (c < 0x20) { w += (size_t)snprintf(esc + w, 7, "\\u%04x", c); } + else esc[w++] = (char)c; + } + esc[w] = '\0'; + size_t blen = w + strlen(eg_embed_model()) + 64; + char* body = malloc(blen); + if (!body) { free(esc); return NULL; } + snprintf(body, blen, "{\"model\":\"%s\",\"prompt\":\"%s\"}", + eg_embed_model(), esc); + free(esc); + struct curl_slist* h = curl_slist_append(NULL, "Content-Type: application/json"); + el_val_t resp = http_do_t("POST", eg_embed_url(), body, h, + ENGRAM_EMBED_TIMEOUT_MS); + curl_slist_free_all(h); + free(body); + const char* r = EL_CSTR(resp); + const char* arr = r ? strstr(r, "\"embedding\"") : NULL; + if (!arr) { + if (++_eg_embed_consec_fail >= ENGRAM_EMBED_BREAKER_LIMIT) { + _eg_embed_breaker_until = now + ENGRAM_EMBED_BREAKER_COOLDOWN_MS; + _eg_embed_consec_fail = 0; + } + return NULL; + } + arr = strchr(arr, '['); + if (!arr) return NULL; + arr++; + int32_t cap = 1024, dim = 0; + float* v = malloc((size_t)cap * sizeof(float)); + if (!v) return NULL; + const char* p = arr; + while (*p && *p != ']') { + char* endp = NULL; + double d = strtod(p, &endp); + if (endp == p) break; + if (dim >= cap) { break; } /* >1024 dims: refuse, model mismatch */ + v[dim++] = (float)d; + p = endp; + while (*p == ',' || *p == ' ' || *p == '\n') p++; + } + if (dim < 8) { free(v); return NULL; } /* junk response */ + _eg_embed_consec_fail = 0; + *out_dim = dim; + return v; +} + +/* Node types that never receive embeddings: pure telemetry and structural + * plumbing. Everything else (Knowledge, Memory, BacklogItem, Entity, ...) + * is eligible. */ +static int eg_embed_eligible(const EngramNode* n) { + if (!n->content || strlen(n->content) < 8) return 0; + if (!n->node_type) return 1; + if (strcmp(n->node_type, "InternalStateEvent") == 0) return 0; + if (strcmp(n->node_type, "Tag") == 0) return 0; + return 1; +} + +/* Parse a persisted comma-separated float list into node->emb. */ +static void eg_parse_emb(EngramNode* nn, const char* s) { + if (!s || !*s) return; + int32_t cap = 1024, dim = 0; + float* v = malloc((size_t)cap * sizeof(float)); + if (!v) return; + const char* p = s; + while (*p) { + char* endp = NULL; + double d = strtod(p, &endp); + if (endp == p) break; + if (dim >= cap) break; + v[dim++] = (float)d; + p = endp; + while (*p == ',' || *p == ' ') p++; + } + if (dim < 8) { free(v); return; } + nn->emb = v; + nn->emb_dim = dim; +} + typedef struct EngramEdge { char* id; char* from_id; @@ -6391,6 +6579,9 @@ static el_val_t engram_node_to_map(const EngramNode* n) { * promotion anchor so heartbeat ISEs / API consumers can see decay state. */ m = el_map_set(m, EL_STR(el_strdup("wm_anchor")), el_from_float(n->wm_anchor)); m = el_map_set(m, EL_STR(el_strdup("base_level")), el_from_float(engram_bll_base_level(n, engram_now_ms()))); + /* emb_dim only — the vector itself is too large for map/API output. + * 0 = not yet embedded by the lazy backfill. (2026-07-24) */ + m = el_map_set(m, EL_STR(el_strdup("emb_dim")), (el_val_t)(int64_t)n->emb_dim); return m; } @@ -6700,6 +6891,7 @@ void engram_forget(el_val_t node_id) { EngramNode* n = &g->nodes[idx]; free(n->id); free(n->content); free(n->node_type); free(n->label); free(n->tier); free(n->tags); free(n->metadata); + free(n->emb); /* Shift remaining nodes down */ for (int64_t i = idx + 1; i < g->node_count; i++) { g->nodes[i - 1] = g->nodes[i]; @@ -6785,6 +6977,7 @@ el_val_t engram_prune_telemetry(el_val_t older_than_ms) { removed_ids[removed++] = n->id; /* keep id for edge sweep */ free(n->content); free(n->node_type); free(n->label); free(n->tier); free(n->tags); free(n->metadata); + free(n->emb); } else { if (w != i) g->nodes[w] = g->nodes[i]; w++; @@ -7321,12 +7514,68 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { int64_t now_ms = engram_now_ms(); + /* ── Embedding backfill + query embedding (2026-07-24, bl-b2d1c944) ── + * Backfill: embed up to N un-embedded eligible nodes per call, newest + * first (append order ≈ creation order), so fresh content is semantic- + * searchable within one scan cycle and the historical store fills in + * gradually — ~16 nodes/min under the 30s curiosity cadence, no bulk + * hammering of Ollama, no latency on any create path. */ + { + int backfilled = 0; + for (int64_t i = g->node_count - 1; + i >= 0 && backfilled < ENGRAM_EMBED_BACKFILL_PER_CALL; i--) { + EngramNode* n = &g->nodes[i]; + if (n->emb || !eg_embed_eligible(n)) continue; + int32_t d = 0; + float* v = eg_embed_fetch(n->content, &d); + if (!v) break; /* embedder down / breaker open — stop this call */ + n->emb = v; n->emb_dim = d; + backfilled++; + } + } + /* Query embedding, cached single-slot: the curiosity loop re-issues the + * same 4 rotating phrases, so consecutive identical queries skip the + * HTTP round-trip entirely. */ + static char* _eg_qcache_text = NULL; + static float* _eg_qcache_emb = NULL; + static int32_t _eg_qcache_dim = 0; + float* q_emb = NULL; + int32_t q_dim = 0; + if (_eg_qcache_text && strcmp(_eg_qcache_text, q) == 0) { + q_emb = _eg_qcache_emb; q_dim = _eg_qcache_dim; + } else { + int32_t d = 0; + float* v = eg_embed_fetch(q, &d); + if (v) { + free(_eg_qcache_text); free(_eg_qcache_emb); + _eg_qcache_text = strdup(q); + _eg_qcache_emb = v; + _eg_qcache_dim = d; + q_emb = v; q_dim = d; + } + } + /* Per-node cosine vs the query, computed once, consumed twice: semantic + * seeding below and the additive WM term in Pass 2 (use similarity + * twice, coherently — HippoRAG). cosq stays NULL when the embedder is + * unavailable; every consumer degrades to pure lexical behavior. */ + double* cosq = NULL; + if (q_emb) { + cosq = calloc((size_t)g->node_count, sizeof(double)); + if (cosq) { + for (int64_t i = 0; i < g->node_count; i++) { + EngramNode* n = &g->nodes[i]; + cosq[i] = (n->emb && n->emb_dim == q_dim) + ? eg_cosine(n->emb, q_emb, q_dim) : -2.0; + } + } + } + /* Per-node layer-1 tracking. */ double* best_bg = calloc((size_t)g->node_count, sizeof(double)); int64_t* best_hops = calloc((size_t)g->node_count, sizeof(int64_t)); int* reached = calloc((size_t)g->node_count, sizeof(int)); if (!best_bg || !best_hops || !reached) { - free(best_bg); free(best_hops); free(reached); return out; + free(best_bg); free(best_hops); free(reached); free(cosq); return out; } /* ── LAYER 1: broad fan-out (background activation) ───────────────── @@ -7337,7 +7586,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { SeedEntry* seeds = malloc((size_t)g->node_count * sizeof(SeedEntry)); int64_t seed_count = 0; if (!seeds) { - free(best_bg); free(best_hops); free(reached); return out; + free(best_bg); free(best_hops); free(reached); free(cosq); return out; } /* Tokenize once: a node seeds if it matches ANY query token, and its seed * activation is scaled by token coverage (fraction of distinct query @@ -7376,6 +7625,35 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { reached[i] = 1; } } + /* ── Semantic seed supplement (2026-07-24, bl-b2d1c944) ───────────── + * Top-K nodes by cosine ≥ SEED_MIN join the seed set with initial + * activation = similarity × the same decay/dampen shaping the lexical + * seeds get. This is the fix for "idle cognition firing blanks": a + * curiosity phrase like "decision pattern lesson" now ignites nodes + * that MEAN decisions and lessons, not just nodes that contain those + * literal substrings. Lexically-seeded nodes are skipped — the lexical + * path already gave them coverage-scaled activation. */ + if (cosq) { + for (int k = 0; k < ENGRAM_EMBED_SEED_K; k++) { + int64_t bi = -1; double bc = ENGRAM_EMBED_SEED_MIN; + for (int64_t i = 0; i < g->node_count; i++) { + if (reached[i]) continue; + if (cosq[i] > bc) { bc = cosq[i]; bi = i; } + } + if (bi < 0) break; + EngramNode* n = &g->nodes[bi]; + double tdecay = engram_temporal_decay(n, now_ms); + double dampen = engram_activation_dampen(n); + double act = bc * tdecay * dampen; + seeds[seed_count].idx = bi; + seeds[seed_count].act = act; + seeds[seed_count].created_at = n->created_at; + seed_count++; + best_bg[bi] = act; + best_hops[bi] = 0; + reached[bi] = 1; + } + } /* Compute mean seed created_at for temporal proximity bonus. * Was a running pairwise average — seed_epoch = (seed_epoch + t_s)/2 — * which is NOT the arithmetic mean: it exponentially over-weights the @@ -7394,7 +7672,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { typedef struct { int64_t idx; int64_t hops; double act; } Frontier; Frontier* fr = malloc((size_t)(g->node_count * (max_depth + 1)) * sizeof(Frontier) + 16 * sizeof(Frontier)); if (!fr) { - free(best_bg); free(best_hops); free(reached); free(seeds); return out; + free(best_bg); free(best_hops); free(reached); free(seeds); free(cosq); return out; } int64_t fhead = 0, ftail = 0; int64_t fcap = (int64_t)((size_t)(g->node_count * (max_depth + 1)) + 16); @@ -7488,7 +7766,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { double* inhibition = calloc((size_t)g->node_count, sizeof(double)); if (!inhibition) { free(best_bg); free(best_hops); free(reached); free(seeds); free(fr); - return out; + free(cosq); return out; } for (int64_t ei = 0; ei < g->edge_count; ei++) { EngramEdge* e = &g->edges[ei]; @@ -7513,7 +7791,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { double* wm_weights = calloc((size_t)g->node_count, sizeof(double)); if (!wm_weights) { free(best_bg); free(best_hops); free(reached); free(seeds); - free(fr); free(inhibition); return out; + free(fr); free(inhibition); free(cosq); return out; } for (int64_t i = 0; i < g->node_count; i++) { if (!reached[i] || best_bg[i] <= 0.0) continue; @@ -7542,6 +7820,16 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { if (inh > 1.0) inh = 1.0; double suppress = 1.0 - (1.0 - ENGRAM_INHIBITION_FACTOR) * inh; raw_wm *= suppress; + /* Additive semantic-relevance term (2026-07-24, bl-b2d1c944): + * shift-and-floor at S0 — nomic-embed scores unrelated pairs + * 0.4–0.5, so raw cosine in a weighted sum would be a constant + * bias swamping the decayed base-level signal. Above S0 the term + * ramps 0 → WM_WEIGHT, breaking ties among structurally equivalent + * candidates in favor of nodes that mean what the query means. */ + if (cosq && cosq[i] > ENGRAM_EMBED_S0) { + raw_wm += ENGRAM_EMBED_WM_WEIGHT + * (cosq[i] - ENGRAM_EMBED_S0) / (1.0 - ENGRAM_EMBED_S0); + } /* Threshold gate: must exceed per-type threshold to enter working * memory. Type threshold replaces the old flat 0.2 filter. */ if (raw_wm >= type_threshold) { @@ -7760,7 +8048,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { int64_t rcount = 0; if (!results) { free(best_bg); free(best_hops); free(reached); free(seeds); - free(fr); free(inhibition); free(wm_weights); return out; + free(fr); free(inhibition); free(wm_weights); free(cosq); return out; } for (int64_t i = 0; i < g->node_count; i++) { if (!reached[i]) continue; @@ -7805,6 +8093,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { } free(best_bg); free(best_hops); free(reached); free(seeds); free(fr); free(inhibition); free(wm_weights); free(results); + free(cosq); return out; } @@ -7849,6 +8138,19 @@ static void engram_emit_node_json(JsonBuf* b, const EngramNode* n) { } jb_putc(b, '"'); } + /* Semantic embedding (2026-07-24): compact %.4g comma list — cosine is + * insensitive to 4-sig-fig rounding, and this keeps snapshot bloat to + * ~5KB per embedded node without a base64 codec. Absent field = not + * embedded; the lazy backfill re-embeds eventually if dropped. */ + if (n->emb && n->emb_dim > 0) { + jb_puts(b, ",\"emb\":\""); + for (int32_t j = 0; j < n->emb_dim; j++) { + snprintf(tmp, sizeof(tmp), "%s%.4g", j ? "," : "", + (double)n->emb[j]); + jb_puts(b, tmp); + } + jb_putc(b, '"'); + } jb_putc(b, '}'); } @@ -8094,6 +8396,10 @@ el_val_t engram_load(el_val_t path) { char* ats = eg_get_str_field(obj, "access_ts"); if (ats) { engram_bll_parse_access(nn, ats); free(ats); } } + { + char* es = eg_get_str_field(obj, "emb"); + if (es) { eg_parse_emb(nn, es); free(es); } + } int64_t load_idx = g->node_count; g->node_count++; if (nn->id && *nn->id) engram_idmap_put(g, nn->id, load_idx); @@ -8294,6 +8600,10 @@ el_val_t engram_load_merge(el_val_t path) { char* ats = eg_get_str_field(obj, "access_ts"); if (ats) { engram_bll_parse_access(nn, ats); free(ats); } } + { + char* es = eg_get_str_field(obj, "emb"); + if (es) { eg_parse_emb(nn, es); free(es); } + } int64_t merge_idx = g->node_count; g->node_count++; added_nodes++; @@ -8738,13 +9048,38 @@ el_val_t engram_wm_top_json(el_val_t n_v) { el_val_t engram_stats_json(void) { EngramStore* g = engram_get(); - char buf[128]; + /* embedded_count: how far the lazy backfill has progressed. The single + * observable that tells the daily self-review whether semantic + * activation is actually accumulating coverage. (2026-07-24) */ + int64_t embedded = 0; + for (int64_t i = 0; i < g->node_count; i++) { + if (g->nodes[i].emb) embedded++; + } + char buf[192]; snprintf(buf, sizeof(buf), - "{\"node_count\":%lld,\"edge_count\":%lld,\"layer_count\":%zu}", - (long long)g->node_count, (long long)g->edge_count, g->layer_count); + "{\"node_count\":%lld,\"edge_count\":%lld,\"layer_count\":%zu," + "\"embedded_count\":%lld}", + (long long)g->node_count, (long long)g->edge_count, g->layer_count, + (long long)embedded); return el_wrap_str(el_strdup(buf)); } +/* engram_cosine_sim — cosine similarity between two nodes' embeddings. + * Returns a float in [-1, 1], or -2.0 when either node is missing or not + * yet embedded. Exposed so EL code (and the introspection API) can probe + * semantic distance directly. (2026-07-24, bl-b2d1c944) */ +el_val_t engram_cosine_sim(el_val_t id_a, el_val_t id_b) { + EngramStore* g = engram_get(); + int64_t ia = engram_find_node_index(EL_CSTR(id_a)); + int64_t ib = engram_find_node_index(EL_CSTR(id_b)); + if (ia < 0 || ib < 0) return el_from_float(-2.0); + EngramNode* a = &g->nodes[ia]; + EngramNode* b = &g->nodes[ib]; + if (!a->emb || !b->emb || a->emb_dim != b->emb_dim) + return el_from_float(-2.0); + return el_from_float(eg_cosine(a->emb, b->emb, a->emb_dim)); +} + /* engram_list_layers_json — serialized counterpart of engram_list_layers. * Returns a JSON array, sorted by activation_priority ascending. */ el_val_t engram_list_layers_json(void) { diff --git a/lang/releases/v1.0.0-20260501/el_runtime.h b/lang/releases/v1.0.0-20260501/el_runtime.h index a3dd683..87ac86b 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.h +++ b/lang/releases/v1.0.0-20260501/el_runtime.h @@ -117,6 +117,15 @@ el_val_t el_min(el_val_t a, el_val_t b); void el_retain(el_val_t v); void el_release(el_val_t v); +/* ── Arena scoping ──────────────────────────────────────────────────────────── + * el_arena_push() activates the string arena (if not already active) and + * returns a mark; el_arena_pop(mark) frees all strings allocated since that + * mark. Used by codegen for per-function/statement scoping and by long-running + * EL loops (e.g. the soul daemon's awareness tick) to reclaim per-iteration + * allocations. */ +el_val_t el_arena_push(void); +el_val_t el_arena_pop(el_val_t mark); + /* ── List ────────────────────────────────────────────────────────────────── */ el_val_t el_list_new(el_val_t count, ...); @@ -142,6 +151,7 @@ el_val_t http_get_with_headers(el_val_t url, el_val_t headers_map); el_val_t http_post_with_headers(el_val_t url, el_val_t body, el_val_t headers_map); el_val_t http_post_form_auth(el_val_t url, el_val_t form_body, el_val_t auth_header); el_val_t http_delete(el_val_t url); +el_val_t http_delete_json(el_val_t url, el_val_t json_body); void http_serve(el_val_t port, el_val_t handler); void http_set_handler(el_val_t name); @@ -167,6 +177,11 @@ void http_set_handler(el_val_t name); void http_serve_v2(el_val_t port, el_val_t handler); void http_set_handler_v2(el_val_t name); +/* Non-blocking variant of http_serve: runs the accept loop in a background + * pthread and returns immediately so the caller can continue (used by the + * soul daemon to run awareness_run() after starting its HTTP API). */ +void http_serve_async(el_val_t port, el_val_t handler); + /* Build an HTTP response envelope. `headers_json` should be a JSON object * literal like `{"WWW-Authenticate":"Basic"}` (or "" / "{}" for none). The * returned string carries the discriminator `{"el_http_response":1,...}` @@ -576,6 +591,7 @@ el_val_t engram_list_layers(void); el_val_t engram_get_node(el_val_t id); void engram_strengthen(el_val_t node_id); void engram_forget(el_val_t node_id); +el_val_t engram_prune_telemetry(el_val_t older_than_ms); el_val_t engram_node_count(void); el_val_t engram_search(el_val_t query, el_val_t limit); el_val_t engram_scan_nodes(el_val_t limit, el_val_t offset); @@ -594,12 +610,14 @@ el_val_t engram_load(el_val_t path); * can pass results straight through without round-tripping ElList/ElMap * through json_stringify. */ el_val_t engram_get_node_json(el_val_t id); +el_val_t engram_get_node_by_label(el_val_t label); el_val_t engram_search_json(el_val_t query, el_val_t limit); el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset); el_val_t engram_scan_nodes_by_type_json(el_val_t node_type, el_val_t limit, el_val_t offset); el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction); el_val_t engram_activate_json(el_val_t query, el_val_t depth); el_val_t engram_stats_json(void); +el_val_t engram_cosine_sim(el_val_t id_a, el_val_t id_b); el_val_t engram_list_layers_json(void); /* Working memory introspection — count, mean weight, and top-N snapshot. * Ported from el-compiler/runtime on 2026-06-30 self-review. */ From 227f158a05c78388df266c4c4ad31f100a9ae737 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Sat, 25 Jul 2026 08:45:13 -0500 Subject: [PATCH 02/26] self-review 2026-07-25: short-term inhibition-of-return + explicit embedding backfill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Working memory was winner-take-all: suppression_count never entered the promotion score and was reset on promotion, so two high-salience nodes pinned a saturated 24-slot WM for hours. Add Lebiere-Best (CogSci 2009) short-term inhibition — raw_wm *= t_n/(t_n + 120s) from the most recent recorded access — producing emergent round-robin over WM candidates. embedded_count stalled at 93/12175 after restart: the lazy backfill only runs inside engram_activate, which nothing calls on the authoritative store in production, and in-RAM vectors were never snapshotted. Add engram_embed_backfill(n) + GET/POST /api/embed-backfill route that persists the canonical snapshot whenever it embeds anything; the soul heartbeat pumps it at 32/min. --- engram/dist/engram | Bin 3558152 -> 3558296 bytes engram/dist/engram.c | 15 +++++ engram/src/server.el | 27 ++++++++ lang/releases/v1.0.0-20260501/el_runtime.c | 72 +++++++++++++++++++++ lang/releases/v1.0.0-20260501/el_runtime.h | 1 + 5 files changed, 115 insertions(+) diff --git a/engram/dist/engram b/engram/dist/engram index 2236beed9bcd70b5e3517f7bd916b27e21883869..1d7defabca026282cb35143fb998ec631afb4dc6 100755 GIT binary patch delta 374004 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

I zZ6Wv#q=W^@p=J<%*~n~b>kc2gVXJY0c|?c(f=tT+I0nPkrpYoX;ibL(vaNJ!LAcu% zIOGC8*#=XNt`W53>)T4+3;mr|!66OwfF7cFS=;=63t^3LZ!7sPev3Orz#0)G^;xnB z?~IThFX@L@Mo8%gLi1-Y^}zUb8)@zG)A(!~DP=_<4r(JUU2)pUrHvtbZ00;mDmE;m z^Sy2xY52-S{6{#fAi4NhxRku=G+rDIt49;5OI8N1442MjCE#x1$`Eg1>mS-FoQ0IG zAaT~YmT#b~tRTp9Sz$(|C59fSD+u;nMvv!%m~AG`4wph#Ps4Y^lojOc>SY<1!(as& z0l|ZRnVJQbAEDhJPN--_M|>-o(e8@iS>R>BG@4e5JE>@UdeLSd+MT3!z^GlJZ#^5e z3kAD1OBPrvARIL{4}}?mvy~Wu@$>qcmxb6>>8(GUV1N_vL97B0wi%IO88R%e>;9ToZ%`hvkQ^2||<(UwaP!+FA-C{`hih>Fv7c{A|(z;VG@9 z8|!@WxYqe^*EwN)z7<_jw2K#6`n1ju-8co-m{!v6O)GJHE9&O_UYng!Mx9pFk93+W zwm87P;u_^PVA0^N(NP;Z()eOPZ~0ST)r$+a`!^KqYAi0)ZX(!a!%uUw;~Lxk0k{2A zB-qwL+atb-?Tk(%{kFw~hqjWoY-Q_4$F2QwTiQH=YqgU4<;+BbrFt8kB`9J_4{{86 ze5mw1=Phmqn{9LP;}B`)_79eh9Um?oA<}?dMjRRfONV>DZPy|ceWxY#QF#ckMY5E( zd7tT`d4smAmy-FGtF*27XTIffOR3-IYjNWcsq%BTNS_c$R3PZ;YC-ST3s^aL%4B4# zMN#d=7FS^EYC&!4g-FqRcH{mnl^Koqrr4lRr>T+62I5!zDX(^@T2048ORz|^NS-HJgIr?c!X-n>IoYYcE_#zFr zZYdr7VlAE%tW2;`Uk(bL5p2l*ryT@jCVWzct!4(O!!i;#A9?`C*cfNa2)&KpgQdq` zM!NkBhg`rvCczcfKNn?gmIO<2U->(ohC>>_^boz#qTu|QU!6lZDL6l2KSp>?kd&Br z4&Mxt+z#}^-v#BTAGnY3r4~|hzCShxNptf9@$nYYzWmX+KG+-z#MTy4+@U*8Lt9YC zEL2t#>X1P#r0~OuxFy)G^pO5(43w7L@|VsY9f2D*&ks5liSWf{Qrb5b ze6*Q#;u|-d-z@*?H~Wy?$!6dzeL<92%KX_`$~k@rzYdi8oru;7aA2Aga?B^!vVj5Ve2suvQIjEt!-_n?o!L(Kq>u_H$ERIt-R!w zKcVnE!j{1N$l^N)cL|WZzuW4yxhN_PlJmH2Y#YCeZ9D8O%KzoN76|{@R623hS8Dpb z1HRcbKm2=0{Dw4z)pV|JpQg|iIyJ0Dr7Jz5{d^uggy0|TTDPY8Q_dbk@!vHuWWSkp za<9hGYH`fe(@*q=I>RLmpDH2A`fo@eTvcjFlzj-v#2+?0?E;;eA=%bM@;;yIRSEci zg`}d1bm#mW=Lk5gh6DycRX{*9B_!)Fe1n~vD4}@kuY}@-zjXB*-~8V%E=P7Eob^5& z%S#T~nf=*aoRWTe++6zPr$J7wfz%8|OMfL4&Vc_{C~EsFq4>-{f90jS2n+rY25%%~ z|9lF+@>3p9pI(i}Fa7dQTm>J`V(61=WAJ1@sr1@h+|y4Qe!VDO@AuxDJwL1VW{KfD zt*r~aKR&?6@&OJWEYTci16^nO9lL8%f?bk9h@xyn9FZ zPP}Uo8{lvl=Pa`L`ALs&E_9v(XVvg#NkD9K@a8?-wUIRKSBqCT9DW6fSn@phO(IRm ztPwWUbCsnfh*$aMi=}x8w`wFExqTIX5;bbMCld!B=|w#2bI?D|tWl&cAZUjPXrV{+#EINbxpV^9e?!H?dmAbq_5_)yDHvxq1n+{}>;{SpC%=ftvl@VNeeL1UJ?}?nmgcAG(V3cs8{}pcQ+6|=0!FjbQM4Kl&4_S z19^Sz3HkMS$gh8cACkdVQ`XRi;F$gzI_8DfVbJ60+S5q)rmZ2`2aM>n)H-Q_I~2!{6y zxA*ahoy6kP6nbLVti-2!Emq^x8IGy(QTBf>B0C(>E~l#?R5L)A+(>dAbi}IxT={=R z$jzMu)M%!lPWtJ{PpstH1024p=W&7BI6b3s|Hp3s|nJ3;|2V*x8lF>MFvuU5KL>8jc-Y zsMmevY%eq$;pNVBDv*!{Xbhg~Og1z?OYu-=;@=Pz#k)Db_v_FJ)qX88)YjSp=&FoD zlrm#yKJLMnC7PFP+$;NUibykWv^ns(6MwJKYHX&VR?A~(hiR;qXM(0}#Wzq61YVwE zwLEYlkG;`o+})WZ`=H0Tt~2RjL<`X%Qm+B3PpXV4!YPGnZPeH_b{bpk39BX9iA0)U zgj$?PvI)(>UpdJ)ObA{fhB*=YMyL|6t|z~0gy2znUUkpH_?Qn5zIlL8$v%^zr$urxdw-_I^Co^NvTx_$K-^QRg0TLX(+1_a|bu20~Zx5d7ZMaEtZ43qZI-krXweM z!p%0;k$t^T8s4BIUKR-d6RkYWf_@b2>m|Ga#S&BPVmYZFIxgVNqU@NA4x*s11#oC1 z=1`PjwH$&rElXE8Yd$s6Q#A0$2RDOlad0e1B$b2U=A1;5Fc@zBrXc$cK|QqiDUzoQ zN4S>I>YbhhTMhNezCp+-DCV911MPOuuA!Y*Q~U5ca_J)o;Hr1BB^^OdX?`cKoQQle z_Ipdx52JYUY%=l*2LEIkjte$Bn)h=5sLw6%NtVX7+CNzu&teik1zo`B-w>yd!97`T z2%ZY=(SqVsa8Jq``P@|Wm+GD@>YkG`&`|;7f9098(K!_4{<_93?6q2)phDRaO*lV6i_bHF{3ujSntC`F5tUdp-!=(#<%JtvL_U?_WLp(a7=o_{Ev z4Q*8#sh;Q3j{lJKEbvanbGb5$dT0G}IdC=d$9VQL=AAX!$hUckK`Yws)q%OmU8Amf z;IY}*NK9wIT_k?y0W#;%A%4aLd+ygKXw^z!#gD4u_2`c4;eCnaF zhtxyEgDdL5(CM!Dr+Vnr@K2VeakYQ4Gy%or-C^_x{^bF=djvhl>mQI(8HSGILz4J4 z+`yOz^6szEP?63o@QpHb>KsQcFz)r29DNdD96I2BjXP+SY3T!P^$yA*M#|8kcQBxp zEe?)fxKE}O!V10bKDk;53)Hmx@{uBxrp1dZWZyGLR|}v1gAJdKmr;|@3x9kle-_#` z3x7r3uP(}KB3 z*$;u)bq$74x8I4=b(mdse<%0`xM%^$-2fMr{wANhfo>|Z3&x}}eD;^3aski2Bd@-L z?%>d_{1a;*b9`Wax0xgjM?^ zOVhTPEUE&3v@0e3{)Qp*=2z0=G5BLjDLM8SI{m}1vfC3BtPC0OhcaZ6{z2<8-hE5H z{}MR~q2q4W=z0H4%P45q=s6qo^!4T5DsKs#VqMcn@ax!W3B@TChRG7JyL0T<*gVb~twyXO_J%HM_KWe7W5AeIQ+ z507S)d>4V|WBVexYg=rG8(scEpY2M&oD4!XxJ;G@bpE=1QPf&wwa~WLkYeJ~3)h!d zx5E|zkNJVzjfQKTI7d!=i#_DwF&L7RKhKirCPFK6Jr4hh!b!{)oJk@&;3a`JB@kKv z4a6P@jv5GM9|G}L2O5anGh{<2+yn1BL+*FN_wk@J^3~3GG{%MB%h6rw&CU6q-Q1{d zcoo7sz9-MS!_B=p%?8rA9(XamxhFm7&5b*)&vsL84%^^5CG_S#g`1P$=4cykPKKL1 zpv4ouqxa=Up7+DiV(}@6P?b*b)8~RwVrCn9M@z_q{$i|{LK)27~xLEq~Cnpk;p@F z2wq!6F3yKTLMrYHkCh^lJPbb;-W0M-M@}1#&mrtwL^iY%+LI|G@oJn@NOYrcBfP#? zZZ-<{M<|li`2r7f-vt9FXH#($-EPZa+wD8yNpl|G(^I&sEK+`S0e8WqbsCPq&rZte zX?PC8Yfh5N@i4aP7Ld3JcqSfpQa&+(9zZAM=yWqdKI#5{qKsS+KZZ`A@GkL_dd(G z&jq$M{8TK*d<+RB4meIqr^9H-_?C`7cX`MRd|ANrzhR@V`)1sgDDC|?%Kt>(~xB^)D;r?DF`XM#f#kCB;~5VYqtun? zd;1>IXFJ1a&!&Fg$o#&Tj(YGr-BQ2PE%iIy*7Q4VQ@_(K^*h~CzmH#y@9FRlhp68h zkx$p-cx*Z(pIDER1)P{)?f1V?40ZY1z@ss?aW$rgn(csGmBzJz6^QA+XMy}~3-z}1 zLF#Q!QfE6XlI{md!gla>@d3U>lCn}}4~%eHV+y^~-E3jkp5Q=wEvmq#`hdlt^^dyc`SDfled3rIDap z8VS0s8422^(}-?sMuN6!B#N)%zjZi&2RZU9M8a-|>|Kg43D{+OjYy>4!Np=pBGR%j zCfkf1*y3`=s@lxRR& zItcD^?+W}gywv3oZ%3g!nSLK8)7`CPi=*I4itpo3@%61F`Y*`c^0$(!f8nd*sI72% z)(fqdeC`1q`HQxa(UrIqpWMRMyRnb31d|Cte)Nb+qbOd{}-GKuK+ zKcQ155#=;=zg(JUx#lz1LfbTS?r(4}Eq=b9J$W**FjT-E>uKCplc_o(N1q0UiRF4F zYHgnUty4bHG=^_IKYEC%1X2{4E3*N|inp&uRz zl&)w$c?inmXppB+8~48`!5peDusJkT^RhEsgw7$lrE`dG=^Uclnt`BgI)~`CW*}&r z2I6FWVT}RLvay~__7i@9>@Z7)K!hQfH?j6g1l9%!blUVnwg5Qqzte_lX^yjLqwK@# z)h2+te!(gd)LiI+m#iXlnhW>E@KxY-`X)dhMQ&tM3*lcpa~0VTB;;btD!PItkmbQb zYn-!^cv}QFaxGYxfwNZse;9JjLHbUwdu}UE@Kf}A0;SBn@_Z$#bdTE)o0s50`ZBX+4dZsLuY*9 zITWvX*%U?ujU3(5$k8p09NpH89BtFc(JhVKi;M-UU%s2a`c=mK)vq(=t)`qtaG6=K ziTL^w;@wdgEe0=vJ{GuYedNzO3NHoRbaC}!*q<~{gqfA7%q$1C9uDpbfvqweRs#Ef z=2T}or``uvc`Qj?X<#cC(!hF>9X()9Jzhv|^nmDYUHCzCUnD_ve_KeN_k`$vvyer% zq8CKhZXt~>{CaQ!*=K>kUS2@@^%frEISW_-C-h+x%#j7KF^n%7K)R(9jBcwZ7&Ksl zIr0D=8UO+8J70#RZzU4{o~H(EL$UxL-(2UDpurHZiSt;%b`54zEO-bF*v+{tU}-d9 zH+jI4lz=Hy4IHjaHM->i`(Ub3&I6`Qwf_+?Wy)s0eeL!U>&vu7GGmapaI6K;WKQrgNp@}fA~gDJD{n}ekiQ$*DI7aP7p?- zx+STug;C}3M$imQhI!@(jD+VPDGqv*CnK%u-W z9hM)QHb>qtNl3urHTb?ujFSad`Q;ShFNFJlCf}VZz#G)>v&r4B1YdGxns5#6BIQ#A zchWLkE0SA+Xdori1s!rCe+gnk@^m^(CMU8=6ixD`8A631PMigz=0d@P2f#Pd_q_6%|(eE@HNfnOpDBgx`_Z;DUE-Xx`?TqE0DqxgVX+C8u zy0ZUSft++i_#0#M1jSSGz@x%e_+`v^`PDJuJ`98L^4)KR8wi)Bk)jjejBRP;#7UvC zSalT}SlGn^VV+n*n>6y|%K}&({L@Hop)gJ?F(3mAcKag1&sXmb3(r5;frj=P5|!Qf zyEM8RQpt@!A-aQ7d2}CF2%&o6EGV|Nn#NHH4!NN5ALJ01y}k(Jc0gz+}8N=S34qPEW+HE=)f zJCp~P>&xXuYD@`BJ4Ya z9D61V$96-A_jAF+&fWG5WDl=yN@AWvj038hi=GRcScva~L82*=hByME&f}Z491z6! zBSgwx3dZ=lgWm^v;9(ZzGc?HGVcXdnK~}R}2yB)Hss;3~7L@(7#d7>B;U2~v2gyNi zgd&8mB+HNA3Y7>CNIrZ=yo1nf^7mW8nbeIC>yips4RFptvTwTJt5;l8)SiZV2Wl@v zh*x3Q!UW#gNG$oMNF$H=oyJnx-O*fxSmGoS86>_Ei+g~hXbDHQ1dF9e>_FSF#K8Bq z5K)U9@~*-U^8SGv_@}5A85Al;h(Kx)5-RS+1>N~@Y$dvZwWgMb!BTE5 zwife76x1S*T8o=;i|%A)n7HCY>n7o1Q)bgUT%3$=cau+tix5>?H}bZP_zGLP(Mj!3 zjBUk{IJldDP6?XxOr!?a;MmhL??=y$4Pd7OzCqGOel|97W_=^Nm zx>xk4ml%r|C6M%7(L;{zDJCF%GJ!1YC8pzM3FLV%F&zG$Lk_ZtbrA|7F}=myc*g zMM?fDS)7jaTjL>Ncke)k4iH1|r}1*iU~wOO#*ZhCDdJV(mpJBk?NI9X6>;zVzEs&~ zeqR*F{eC`Gj1ZFeIgN)=$3KW=jz1I29KR#BhT~VpGRNnQ1jqM_t#jXI4(5Slz~`Z{jh$8l=N-H``M#i&1TP7SXB+4f^7)|T%A4Y0}y6biTVIk_CKQ! z!@2FxC^M;8-nvK(5rkW9Ac|%$`QcJA9|c<5&?rXPP=VF*nX+G7*`EpfPv*f7hu|Md zwOXdNA?KEh;X+S(Hq1TK3h@c@`YoKE4S!e#7G=u5pK|uE;Us94xB(vtr}4GmZQ(Su zbI>^Q(^9bkIhrLFdv&4q0{n^$uAHFk!*6atCqA5-_!@bUj8bv$kqzQt5x)$TQ?|g;D|`{kynA3P^=?w=d+&Br_L+CPz$%0g6-Y)UD zmj^wI``A_4XFhfcVLmR~4L<&%NA(uV}A1`S6-pA*hhJ$fU_olR@ z?mdV-TT;)i#Lt3da4OUZnztmEz7Xfs&JNaRYc%lNj*PgM0VMNFco0weQuM&-!E_q= z*OT*(iyO2d?QA<>WRI}M*w(`|+6Mb3tG8`CY~$b$=6b_4QkbR%W7c4KR0p_1RKhhO2!2M_Ay(VxXz~g$(?Mg6JQ}wWIBMY(E0_ ztAlQ}T3SQ9Vra@sJAy1?Gog+@i+$ruqBHi|(3r;_42iN2Pa6=-ZcJmpoRnS>9q~tv zN#zx>AMW3nKeB#?71yV+G6G5Y&oIf}`LX`cQ~#y=0{vl|)$-Dh4uE6gL11itW&Z;6 zt4(9F`xl6!b7K;I4PrmRkH`MtHCRTwfbk1~{wW;Hco6L9M^;{k*lYaQ3Oe?NI99yX z2o!Uch;H)z8)71Sr1B%-w_qI10yz?{f#<$3^Z#xdIW8AN2kJmO-B!gHgk0K@DtjYn70@FLA_mMq-Vojfoo1G z`^?+l8f$oajgfgf!^ph-paQ(z$;iANdk?(bgq{k&uAt8Gqx;<3COG3hc>9LW2i_iP zB)Y%A+wF{G?O)*SY#;7zrw8Ee$zWX5+aLLm$_L=>rasKuXC8vLMXIQHJF${_yPXeN z`v_LC9p1#P3Rbbtyy+}k=N|4y=U3hcYg5|@HoxF8rKfWV9#i(VhHQT2nc%PU6=wCY zIlg-5zSbUcruGKyHEj2rJDX^BY@!`^rxUFNHJ4$E^+oMk!C~chWwor9*^_kHX2|rK z(%JP8eh^7#*It(C!R&#rq#fVDfAa6RvVWn7?60l;9fYuw~ zXLaQCKhTf*V+|R6iWrvp=WJ@Bw%|m)t0A0~l3#Hg=dfB%- zz1Mv@^0K9V*j@J;19vU_snN@Sj@6FB`1m{0W4tz92+`=t$?@88c;P!aaDp~j5ca>-kuO3a z_&F1`eS}8ubfkVOZA0QRNgIJbdrNvu(yqmSz9n}j!QBpjOS~q--3GtaRgdQx{j2Xb z%P>m0+q{6YY&=77vowYA>fL5({wS1BPS$>7KtA%UnOZHzlU@_YhK6wc5;_Ye`;e2f zwK2$tyqm2pMkbQvZD=e1`yD)MqL;Dt)c_~>4G z>0t&E{Ex0J$=amtmT>Qh4pyfIx#jSumUjfV+&`dQF+KLBE7BY-bkh8!si(1xRcyS# z#w~Xg-TyfD<&zBbQa$I|6Y}aGofrP;i5$IIdkVTjZobwvB*tx89dzs6Yh4(kcbylI z=}+3d(M8EQ+qDyrlkqWVxyQaNuNC|94qU&%W8%G2YefEX%ucN*^1T2bPRiQBap>P2 z!6Wx9ZMUIq+E*OoaUu)LGhYcKr+Qu;SnZ>orQ zgu#vE?a}(-$}0Kl9<4pbtQ-EFV@EZ@E?- zeRm{V4{P^{sF56eObbb({1*wb8XAyfH@&wWLSJG4uV%REU0I{hj%;+(2apHfXxn4Y z2V`GYLlCYFzvAm^SjyrLo|xFp5G6M~4pS2Olkr~qSoz9H?Ke6x&wy%?@g_ag4o_=8 z5$(GdM?I_!A2#X7eSiHxgx~#1(wgWk^6%%hZIGDvXqbcSb5T280GSx8F6#3uKWQ=T zM;7hW&C4(+obQs#;f87Yv9za|{_@Ey+IVWdf3zW1?r=@p!GIUuA*FM5x%%-Cr}5Cc zRr4TDGs?9VEqL~ayV~Bc@%dA`0`Dp#`~K9HL334wwk!DOW`))UOD+6t?Y{O15*FRo zksmW_xf0_!oe?{f$te%C7~vmo6Yp4kBeLM3Hbbm)TL%m0Qf&j`SE&uaXN%;dO6_+T zcP%Aue{19Lxl%d#Z@O*|DJ70iv|hMhDG7X{4WtJBo@l*sd?}gsL>uJYrWA$*1egwq z*T20ZWr8Q{yTkCPpWCvO6g>ekpHi|fUhhr(o@zT_T`5U>s=Wp8%$=TTm!amwXPez| zIqSJL8KaiuuNT?__~zoKlDzm=>jf7Yy2oxDnf*pv zffwB*qu+vB#!a&Dtu_)*x=D)Y7EXBkRy!PbzDb6^gE7+LCb{?yxasB^d)-~P-*4!$ zU%H!LDmUE54D-h;_x25J zsK4x`yN1ux`nijKfii&}-n1Nbsd)4+fJ19bFDM{);-g*CgGFEPG)SZIAHM&Gje55}l@AlO-5K$OeHANpn2QZB4F!FATVFhcL z;7Ai)JQ!^KSRbn&r>t;c#3#ovj5W%`NYYgOdbvS>Zl!?2$}kB87SQT!Z3=MTkCXiO4lz9z1RUbWov8Q52%$q@hihm zLY=N)J>C>%>jvB9g{|bI1BQV}p9HN(g{{c`gN6Y4N~CTBz3#*q-3ZuhU8e6yJj}ZL zu>a$7eOr2USWCi4ofWVi%#YQ5gzUeHdqV}69Eg+O9W%7W`aWQjeJ50oIc{i+$kYT~ zsV>ykwt*&_3_fY_Ad@=j9P7cim2tBpDqzi5T!z|_Rh@LUWRJ5nq;$EbL)9zS1=b%RMV0) zt~v_@H@KVbV}v}(#P#|pxvaYmR{NgcgA`ruVKmXzzT5XCB}r#Qo^nQ#4p#d&P}whw zS66$N+?TW+qptQYxzA3M6K7zxZ_rDZhn-r&(K|o(KZu8Tmv^NathNp@5c|$Up z+DF#|g_2b{`XR*FS2qC{d?&B$s|y$K<5T2Zi6K$0J5c8!;#gPeYhoHBomD z(^dYf+VE)?R{8xW^h4l%34Tmh0IPiVRG1+sM*i^=m^N_rA0HWpV9(3dp(!~$ zmc!(Xw}zv&NlCU&XYzr+OD~8jbGJrmMcl)n!M2`YR2Tc&U?k@~Dy$_Bb+B7fmsod! z2Ykq*26lhTGj{6+*799Y9M$30$n^PUFI$e=A%j4L*UWmPsX0p-NKeV?C~`22VF$s zisGmMxS%imh?8y`tzlcg^~F)+;7QyVe(ZY>{%R!veh-xf?SwAHQTO3zq~l?K48-vZ zjny&%_Ol?CfBm4Vhw--0$=eIMKvDNOJohFEkT`U{s7pkVax;s42=bwKXWzEd8@jC( z#kLNyo!*2)`|8{%GOM?JnCwxa8;h}ZH<^1$myE~lCZ(5jU*LP4$Vr2tJGpjQ*Vz7{ za%!I4-<@Rr6&-vH>So}d$%ie1z-s!3ME~?bx-#>Bw)0yWbEJmrF#wO8#KRp zpxdMzkRff~!)+jG50N7t={g{NGw8?oa>VlYk}BPDLEj$Grg#m{;`cnGW}LBH-r*me zgFEyoE8rs-dpx7>Li=b6q#6B!gjSoWi{B^n!O;G1GJkLrwPDHpe!BmkWZri(OXllu zrpbJ=KqkG`jjZkn&Fj?$Pwb%wSpl&I84~-w$SG|jNY=>dM{lG#y%$@kVhsc`dmGvF zPPf?Com$q&?wx77Ms{CkqmtbpKBNa9S5ePEevgn-*9{-$_MJAc+LDL#B0|P$m$bitG(VR;#q{H_Fp^dlb9%E_b;?!$*kW*w%9jt)x%P;B zekhP;_VrOSn$wTMBi68VzW*AQ&O=1tueJ?JI)B7NKL*41U~mT{^zU>~6@f&4gObB{ zudT^@pTl>t$&kY@M+m;0EwF=xBqC5hh>jELBS_-qE6wye43}2&cWD*N-|3L0;wOXj zQ372Qv!KPZ_)z^dfsHFbO7@-_u0Jp64T_b93|edFNxDVqBN+KeLzYGAZTRdm;@wVP zT5Tq@*LPPfzewrQ~g#-Wv~GO1$IsLAd);h>hM0CoCmt z@%lI%wv^`W!*K&>Kh<8U^}FYclK!sStA+nJuYb0X?CYsd@cs>su@@Y=g1YBMFQ*-b zJbY27y|)(1PQBn=)@hJpL_5oJ{r(Gye{Z<(*9%y#f2g+}a(!{WJY}#Ra{WW|$iX3c z-^efKF(=i`^>-`meXhS9+W*bHyEgGK-};60!d7$|Q53X64@;SHb(oXnH|uRqm8 z^6#c3|76k}y$<%3++Wp$+6_Jasm}71ovw{ErZGkjYDiTpu0)L#BdOjWmDYRGQ{{sa6D% zeH*#8QNP&No?6yO_;s{hBjLwWS;AkjNe>Bs)W;tt{B1v`3BMaD*b2*j;KwZMH|OYk zfNvn{KZ`F+A&~H2l$&nXL*DdmGRyjJ?bJio|NjX4?zkw9H*R+BfW5uDy}d&~K>@J= zDk2Ihh`pksV$_Jn9%GBK#}XBLSI+hrjWza)MxDeM3r1r}2%5x1qehLf#Tr{QmiIfm zcYw+7ecwOsv(N6$K0EWwQ@-=;?99!91k_)TSJ>#E#?TNzf44-ot^N~m0{mY}bcv4r zk8Km-V9@}9{p*QdLw2U7J_0aKx}_LHfX4%jA;3+PeAjQDXfA+xh%pd2xWgX^};!6Y*?-*d;m;S~W!2ZS+nhQ3ZV%fEh^o zFyJP%MLZ3|fa$!*5&!4nX&4LqW5UZxJ)AW8)_=ITcp%q*h^bhF4)M_%#E%HK6L25( z1&*=tE@hPqYWNNClO>~+BnAO`+$kf{yI6v!I`5dEthM`lN{JD`Df*?p5a(16vQeC6KERH*}U!R?e{bje??ZVJKK2kn$Vij(Ep>;lGVvOHMe zWWhn8>tqW?-o+-q4Lt1f;9gZvU2M;T>~f6c%0i;KTYLfMS?wuZm20uv?F=V=Rh8{ts9lnZ zXqZ#^tT6#^f5*Ez07j}sGLw5&dlGv(FQg2B5jDun-7l? zH1grEi^@O=!G>dR5-P*7w`e1JFI=qJeEht{bfBuSo?PgimYSo z-VyRE(C?L$SKy#0#j8fjNQ#G$j<2tll9B!{%8?oW%_Id2IE}en!2&{;cLwL<=4heG zmwgP}EVmL;D!|QVoc|j)Pi-m67`SsQIm`^0dg?El{!$YQ7=P3!&z# zEjV)GHql}|9bTcDe90AoLWR@e#ajr-oW$%c2xvKj@2W0i9ibV`J?Ze?HD#p3`!zFw zbA{S6fOD%<0i1h7phh~}+)ze3Jk;YPo62yKXBy{Y<}f3^LB4uU9PR^{m>KxFdJ_Xb zW3Cm_;aM2sBN4uyp_O_L{Oy*qo&(1q3edSB@6=9itK;XbHq4vGh}y`3hcz&A;JrJ^ zdJg=u*@L66c9uI!LS!Nnp4nB#Vi>~Bp(;9(?p;qH>5otV7hm;|4^>S>Zcgl?FApo4OmPH zo%>KeFGUj{fdvoC=;(OQC>hD^DC+o;yn|gxCUuNF!?ibAur2__dy;9>7TTi~yQ-`kn;4YoOn&Ws0>Pm}1$ zc<9-JB#NJaBgzh#Aa`f|lj!sWxi1#zG{A4eBpNkQz7`}W{TKY2l4$rOxeV}W}XsQgL>#D|+vSa|=oJ1PsmLrqCNHiK= z80hZOuN45@Y@Gia=x)YLBazhp+bwrxGZHCd9vV0SOy|ifA@9)n@;_2}Pf|N#kzCE3 zmn&I$$3^m=z8E>`PK~ibg^k zP7r~)qJXpSNwG#MJ7SfLRCYyyW>5N}Ad=WsZ~%nmIOvIM{Wg>bgzblG$XU0?L5Hnz zTOp6~0=E8avQ%{62I81?8CBmQcad-%Y3jpfloc?Q^0-kGk)|&GxqJ)PMVgxGe4$_0 zv((eRkc}*L1#t3U*4hl5ke?35k=h@C>n)!TRrMAhil+~*Tjq5rFM6W@sRrQu-$->) zj3{Fu)%k+{7gF`ZJ^x0kcslaYyG%G5AQkd}zt@a}^wlH6>9&jpuR=(*S+s#vy+w7T zTI3jZ2%*)U?aws)RoZXQj(W86frVlgPIfj}jnt0|cUHrAvP& z_h$#n86dT5E>H-2P?jS#-OkK@#XKH?Pka6(1D~Q#bbQ+2tUN*7E%MV_&dJH<`=ck? zbq~DfSK)xCl`>E&1e_&9z{pdFOI3AzYPwzuz{#w{N+=`n>2ZM=FKZl$>J1`e0nzAb z>J67TBclPBr67?z1_H$?vc`n0u|jJ~ zTQ)(2Ez4M%;jpxfWjgbBQrWVWT{!)e##pl0+nVt4)1){L1eMVh0)mR8fS}?iAm|xb^_lK?-z74; zH7i=s`PCe>u978#ML0xeH-w7ES=<71-TKc*|o}O{H~JEPI$mHPX7T?R;KU3(~qf>~E%Zw~`cZ@uYR_cEg!= zO|%$*^Mh&@J-6$qZb5Fhp^XM4TO#9Y+F%fcU}kmwyZ~la#d%?v8D}$cyEl?81DRqo za=SxoT10M_9@ezXW(Tc&LW%`|vz3+V)wc9viB{TF+cKOLwNhjqOG4@UvPE`B+hElm zz=_7@c~iTh;Ucv=x{d{a6L0y%YsIhYS>S#LSoGvB9c*Cn!}=5gbuMbClRDbO)M*L&_QQ*Qwu<6bzZ5NWi%|nGZUk^1v4=cyfZOcTL4Az zl24zB(Z=F(CgkH!-N^uj=y}^{KOw#X{88dd`w~=Ux`f#2Dn`nTgTYl8#1rW@7ZW0D9Kol?K61O;2C?8jF63sTj0!Fj^aK zpicMO1aiinU zU&dGr{Aq_y<>OCN?dQJKubh8tes!V+9G%j^&~WC%VU*HqUZebR1H(?Q!^Qk;TmpJfcQq`5dRO$*UMpfIX$PlVU48@yY_%?t+C8-9eyAx zS^!@UJfJCSEw$M82Xu6;C5)|qz^|>fAa`3?FIWIyD?Xsy^_C>locp@k)Sw0%EJeHz z;()NNrN~|Pz089*jd=2ko@0K6VR~ZTQL#;1?$hawmL#_9KB=2G@;0^m!V;OBbK9tOVPN}}eysr5 zeu49U1KVA{QpPxo5>Hsc#EiwEDn_zF57 z?a9{ueZW%AY{slVi{WN_ehoKk^1JCvEtkuK{5Ocm-OXx%UHxR0)kxlY|M}n>OC8*g zGWrY--2V3OEyv7xK0b;kpSu}%^y_AIBN3Z7OHw>@Ikw~Mo}?HF-CgG_ zBp#2uTmEM0YE(p@(ed|hmg{&UfIsv}9jHpSsH6^;dtSB}aCsIGRep-se;3Luh_rZ; zyl-8z{OT{x-4!NK#sR$fY<1mYEs`y_u;k-tU4ED2^ptPMh|8k)3xITSoc|k0uec=2 z7(n_HLH`R#J8;jxfwXcNUtu1UyP0U;pO%(py^4<8mVx*dE?ROJaQfgK5lG(t4IB%> z>9>BPTK6m^^m4q*J;ahyzM@DW94(3SLOA;6MPE8_Ozy^C+_xa*Tm7Q%8)&-fMcV%m zmQV)8!oQU}&|8n-G9b7t2ucUliymA0vtt+dfX9|Zlj-?+Upkp5H|6*Lwjk+y^;iDt zg=Gfw-ofX-wrI?JU%y#kYOEGj-TzCl8~v%(NNk*E3UIaiEWI)*O)zaspZU?%toQ-t zikTm#`)A?cd-_#0T?G;TuAkc<`jjOkqt5{O(O2osgb8HHxTFK@NwNZfUB$=&S9K@_ zIp92pV&s6ovl^KW9cr6G&%izpBGL>kq9D>#<=X=lOazJ3VYaE{Pw->+F&S#Q04|b) zuPCZy3M0Yubd=q-xB`?dI*W%#DA~aJ{qUC_ZnRQLqNy16c|rbHuVcwTJr|57WJhS5&&eog%jYZ-XNncFYmaS}P5Vo>=84ka(gL0ubIC1}8wcI0_KH2mNw} zDI6di^JJDBp^$b;I-7ii2DDQ?70_E06wo`gy@GVF^@#5q>0W=Fi*#>O+Tm7;(EC66 zg`0YR?Mrii@~cZ%-&XW|uZIN%bWk3%~a5JcTx)FejmM~6y$#EbWxD|-I7D6yD5?JpXR{23W4$! z`gs8;UyAd>pqz53Ygj*&$MUDZ|;g zLo}tAB4$~%mEF^!w9$2|>0fcmkefI63sty}RT%hhy_AI#8*-2j@2%uw4(kDmjk1>F zeflc*B=e{PzT)Enq+DS^`ziOH5|7NC z@+154EBb3N+P>{8nlVJ#$;N+$L7g&yz55m4HdMiI8rK1$0{V%QJ+Xxpa>rWB1-hO&+O=;BDF9W(9YiKCRG@FQQ+#V~7Gs`E@K z!mEFzY`}L3U(&1RN)j(VR{2C?tM}6K%}RCt*EnT@1RrsEj1tPT#>4d_pZmf$e;RtJ z0AKyHir!X))~|HYV+MvH`Wv`bNc7o4^Z^rA4$A;qV$lRGqTSlB9lgd1JmV(Ju zFUUDOP*ZD z;_id`d)orl$?_TR`G7#sM-KAvc?xDg@7ztJ<}2I7P907WdRGz)l89sEJD8Z&Ms?3X z;rho9(srk{Eq$^;xz8%@ra23hr~mVYAMAy1c%L*c?>Y<`)_hY)|>$*(OJO7ZSazHOxv#KdA|+d{3-rJX`{jj8FUN;P(Dhate~JB4Ch zWB=@+MQfDKrZzi#=O4%@M%r5CBleY8`Aq4|0(bDcYn8DQ+np^Gtrp+1Ub%rD($6CJ zo{h>iiEZ4@p<|~dbJgu=gT9K>oUKYbDf#DZ1-%j>=l4psJX`OTeB0u>$Vn>Q8@kanbL)Qw3Rp7B?OhSl|xV<{@Fqq6|lnlz&&Wl zPh05j9wnEp+9D)1fKA@QV?P%{3fMvrQZeq>tGtxh?9HU^gVi~=Ak$$T%Z6_@gmi7Q zu4OcPs}jU3eWlcuk{@j>S zNnKC->q0T+Vf{1Vacb4W$Zb*Z)OHkdouq6v%k=OSA5pn!p<6cNBNiLgow^XBU!jmXPsh zXNBTS!4yHEIL*&Pw30;5UzFn1;i58xom)-07vZeetR~1Wp054|@6>%Y?Y*Qd@~^qt zcY)8WITU(aDM3RoBlbB~8`3O(1=4)DiXhDxzVeDPOJb8(aUoL71XwA=S)Sf$Z*{PV zt7t%bsL+j-hB)6wsq4xBDY?(ef=2Cpmfxss`H0@Ad}}ynEeLf@JfZIA8_HQMY`nr~ z)Q^7(eF7?(h@{K(x@UP^0_vOX z^>aE6KlhK_nk0!JBJ^5B9dYzVomAXVIO^b)w!?as^a<1%-mkocV^Dyqf=pnq(KZ_GahiQ%DJG zJyv5r?_9!)m~wU=7vKf!p3D>a62Z%sv|f|gcUXI^l=ZoJj@#?^)GF3Mo?O}r?^_uc zz2Ab4x|J_#?EPYMN2B>(QAZUDDLM^N^DAp1 z9z|AE740}V%TV{~)r7h?nnf`+ti4!;S%o@yTMg?Byr#rlOX2AHCtH7HnKP+gO*AZH zrqPx!t63F#S<^a>Rh}sv-2m)%$M2?C5i!=!;OlCO7L}Y~M2odE3PlSAQ!8N(mQgd_ z=;?#?U`!b^D5O4m`itotp#ct|`*g!0TxwuNzWn+$Js@xd1TL{b(`alH>s^*GjSpyQ z?Ik7uI<-JFr7s(zk%cu~)jBYM5S#)zEZ}qmdx|AF{sh}+%UdV4tp4`IjwxCVX%c|?cn`xpg zo=-i|7VNikkRR?~y=Y3qhXdHN@0olkY33hrgR8R+r-OLTVFJ(XX5D6HW^U8eH`E0-#Q0NosXr|53FZQ)5apj@SK&PIs>f(*+*k(=Rj*M)_*MhHPCv! zGa7ZNd}hj{!-?)=Lc#G>#HDhXDLRcWBQBNl(D*vyQg~)cl<@iZLgG?rW=g1%nXaGX z3kmT-iB98X;-vr&jrkna23z|`?BE!_dWba=uffLfqrHX$%yWEgVI6$64DbUsQK*#x4l`4wa_4*K9$&;%C-o5^Wi8jbJ54 z2@6YPt4ERF1hgr56b%Tnm8X>55X{g~w10wi2|GQKGA3GcLza(3{_A_}oE3?kvvBl@ zz#0jc#-}eHN%baKQ`zK^e9k26CW(cNq-~!=ynUuv=d;cu>D3f#8vAMlrA@W2WAjJw zCsVB-n8jBlF$a@p{(#QxKJRdfIQCd{IAt*uLC`&y98L*?v9FqqO;LX49J)4Y||%i4V(+;yo+X37nLpHZuctE^=+JPHE^ z$tt8QVp(mkvSj&qlm*GEbQxCRRT!Q2D2q;eltrhZET+{~Y*{dV5MRCq_Qs|URgErZ0sZ zvZf{{_APKB;|?1x)LZzGy{va{;X+zc>*Ln?YW?2A zk5th8NS)pUKN8P>JZ}BS%x1kua3;aLPp)+-qJA&Kqa>Vy3>)?0Gfr7!Oy(Z%!dvU> z*Kez0Q~3EGtvwk#*pur0Y~5p;*V9+5VME1!vG!ood(zln0MJJDXyHe&2X56*tI zhA`Hx2M@boJ;?AC=x@JScQco%JF4^^%>cX?U$0@$M;{8q7DumP3tAX9#GmCg>_?!5VT+^Jupfi=7EatzTMOvN|1U^-JqWTV5v0e~a?tQNG+OK+PK&oV~WD zV#)rD-D$R4l8I%&gm++SWLsuiZOiuDkS%U7nQY&&T^;yolP!dq0y`LeW%sl7V@d}a z@Yrkl7Kcq^ zt{Uw;-T1cAjS1~|uG5BH!KSpOm?AdOja`b^(2W6Yjc#0wDWyTSTFl9PifuovT**#=;qPSt5Mo~TRHBI zvJv(~X~|<+OA07 zk-Lg5lvXxz`B7{&+W>Z`IW4bdYs9uUr)$-0MqEc6?=4)Bi0O#qIxXBZ;&?E27uC;& zt41t`8#Cg1aAwLgJ9Y#S=fYJZmg}@|)j~+vfCjjcN)ZOs(to*@f-@TvO7AH{~Z9*t#=zqzT0~wsk_mnT>65)XlI+-*{_z z`x*tpGT{xZc~f2!N^1&LX^8dunnDFvHxZG%6h)`n#<5q8X;Z50XvnvX5zg<`b)T7l zEnIQbw{V?0G5u&`n$gUb#&$L)g!2&osF^JbyKXc#V*2hDHexdxQ(78|+-yY4(?rKL z;u$S%ALhsOAqZK*^u^I@`hpgw{~46cYx=uD3)2@zuj%gwU10hb+Sx=#$&LZklWM|tb$0n4jgVN%N;7*%6+t#ul>+$q1HVoW5 z*W)qWZ0BGp^~kS>ZLDc~U5^u3)x);LcE2m`oCza9pr^(?ZL8RTy8Kp8+eKzxUI&^~ zM=alQ>peU!tB%l@;xx9mEryN7;&;7m&&C-Mzfxw(G$Z2c&=6{ppG{?~ z1(xZ1-xkIi*5-5Gw;{}D*Wy<`u-zAG_QPOXps#CNO^=!_03d*xZK}zie<;-KSu%AV zrK{POqlB7`Oa70VnQPM6kDz8FlMOXHlWeG2hcQsI_+&aa#+JkIN%r!ww!Z9I5-Hi_?N>wmNJ` zb$(_VY$f@0wE|xj>Nb2?Zv=FCmEAoZ=H>NeO#lYG<4yEOw$GtMyvj`5n*))C9uy&t zUSHP8gCeGYsn?gy2Q7S=IC_1VpoK5%GS`NINL->Z5OL14&19JJw0xdzk?Yq4$XD#d zghdX;VC3fn14N9NZ(CqyB@(#0SopAuRp`VLDAg}jc)g{N8e3h3{Fd9MnD4|x2Kx3& zo0bdr)i|EYuCm=S+2TFuGj6qQD0^L*w*6=;MaNg$%CkQ!)05SbsvF4R`Z_YoIq{v=0%eRT zBh)O7^(jNIezg5H4i&@>y2cPkr!kbe1n2kgxBBiO_2S$&{_t@`iQ$V!6^mx+>lJEZ=UW)mZq?l{EqD{Rf z6m3>SAw_eR6p9u?J#W}bvndgVw*4MqXj_?^(6*WpwDYDdm&p+{;THJa!D4i`0LMy@ z^-tSlwjrFe+rsHx4C68PY>AAu3gg`$2mnwsjHW!arJ0tN5bq@d>GnfgO}4xQk9lNc zEZMh2fy+x9Zn(TA&>Q(HySpijHu|iQdpU+{-hopSG2_#j!{2*i>tkZYi_@G8dkDY% z%+^3MeI4pigckqUnz5WvzT_V~hSd$FOu1HjBiEey2_mY(>j5)9XTkN*2vYIfUgQ>Vd9TJSXJ}GV=97_lU?zDTV6|Ku;>2lOm3j zqjFNN;+ikHf3XK}?U34Bq7lLNs%&i$+7@gdioJQiuk5HxJ&W46u;xXuC!IZ8Y}mX0 zhH?4DF2FnRG zh?k78*T-(5PTs4G{e{_H${jLt=!hspdD&8mK8UfOW&0hJTHd}7Q^-%AQODD?3ic@0 z(?L5c*qh_p>k9TA=F)hbYYYf;E7}(XmU1Vfu{H4v#7}3|x)dd!RX0*ZCHvoO2A0{2 zv!^jX2lb7!_hPqIIvr_*QQPq3rs|F(I0 zeoUghJ$q>5XAG{MuwGuX@a~Q5du4XqkHT8ouXj($NwLY9=@rp?s{(UUW}~68 zpmU1lq};9TD}WU#XYzuFp&Wk-E^OdC5CyP+?|wzVH+pZe01wvgm> zU+Ub>zN&Pd{J!e8AdGtrXqs?6-sC0t3j-?EUWoCIiNk<8WAtdkPP_KLY@Uf{bP~*+ zChFW7HsEWbIh`TH#|$!ADr6Y%mLjI5KVbY~XZtJJw8ICJYu~fKG<5(W2A=#`Z~F?y za$eJte)dTA#cSH%4~(|H#+Gt0rlqgV3oeZoj7sT@=rwQD-@Zp?tzYt2L+w_{D_u;! z&GSlE1+7cBy^q@g+ACcRw2-b=H#6M{T1fXnoy>F}&|c|EpuN&%p!21BWH_X2UjD+o zfb!<}M$qjK?Ln3@ZUtphu~3?IguQ)W8Fw+CtaN$wha>*+^EqX~U(t2TP^F^winL~g zJ+D+V+-=34DKbk#@VYjN9gu>AF+S$1NI^D>%(j zhtWr)?2An&|1s0Oj`mQBA8l_Ge&QeV0+c7C?6oDS3~e7{|HAa-IUcbVZ+d5pwO1`uR=0MY zv9qjOhUIrO$<4<3`wVJk_IXRc-lr_R_mdh%(m4D2@O96PDv73wD(O{0mAvx$W}JOI zTlAb#GwsFgW!*6-Vnqb+2PO_hElCS9?UTY&|H~vh+F+6`gnnS5nn>@Dx7)!1a&C~vQBtL zNt57jUOl53lVBxRpV42FU?rI4s#{5x*Gj~#-YkJm56j_vvi)NdtNAxipKc!|u?tTr zcLuEF+*6)3Q&>rdr&MdUy)0|_lzPp!r@NA#Lb*3XxihVZ6w}iapYjv4?cEhN`4Nv@ zY~N#I+aJ=krS=%M<{`O0v8TG+4{^s-+))RM!sCwF5BY#k?2Y80`wz?uo?>5(OIU=v z+XTtY{4&%3d_X7G*hjJ252(>v`)jYI+yN-_TFPC}x}|jVao+>&wUqmybxVoMOn(4c zx0Fhm>6buzE#)$3uccf8oo^}9dSNMZ@#fU9l&B5%AbXTs5miFDewCxB*#>);V&&Y$ za47^96E*U~5iejdH}QA$_;R#DQd1Ufv}Z`=sN+Wam{RfJRoHHBpwR&30@ZdXMI8w)ZNv`JQ=!-D5VfP=^~RE`zNV z)zYg1w!vHMhf$4Rx7b6aa{TEQJ60_#Ck!NzGPl`xvBP(H;&yv!Rwl|F3ZnoEe8?K5 z8^}j6kQFeHKVcyHb$1kv+hIRj>iHexxxzNYbMY+9J%)r#x`gtCghubQFD!o*1uwz= z#R`?xeSGv+^2Tk)6aX}FyVr7b8kY0(=fZM^{>caL z6P6SBC*A$ZKA35L^6vYE<;=ZBy$;&jxkln0@ufD<|AR;wE}5J@>=w^GXpd1$r>~oh za1waZevh$o*U2x}p5fB2d&<|Tte3Z4C)i6l{&B87Kn@!G$A69H{Xgi;OM4Z1e8yg% zW_jSdNI`91;8- zH2f;vJ!@~q7UuBeb9MmweZTYcU+p~*a&w5E2gIuIJ2tO$)TUDx?CaTt-)YoEh`aai zbmgKR%Lh5!$1Mf19P-U7BW_^LoES)~0Tk4aw2jtM-6$8{xca>nxgFFgj!7V|%b1wDs5jcE*NZMQ03W zFR@&bFJ=X^MqA zkB=74jPU(099dJ!WNJ@4kPYJ@#n_fu#@_SW(ER)VQzr0`j1%?n_+r!BCv6Zj{! za*Vq?XwM_5l3CpmKJb4O5B9p>T&b(U(mSw z+4d-UdNr?xc!a#_9^eS!j0)w8DE}$ z9^&XlUs%-gQWxCzMqa<)9C~FJwZDxfwtgsRj^3fC7;>(``9usj8h~C4dJP5~;Odt&cZo{GtJO^Zd}pTZ!S-m%j91%96~xFhk?d8}18muMlv_ou#nyhu)v9U(34b2= z(J_ct&QZHk=|r^&d;Bd8NL2f>zrN+?64eo+1O}q5>3)`K;ajV#f#S;H8tM^t_avW@ zq((7&1s#NLKt1Hv;8#<<%%V=x>J)G(bCT3rYH8dOdfpLDoocDG*qIY_s}{z`6{yk$ zhntSoRwK-dPCyR&7L9&&Ak(EMD6x(jSFA$*IP}s~^VXu!MLY$cZm&;WdE(IVPf8 zak|w+?ataB<7rKWUi|nCr8iSETwi^I-W8J>4g%uI$jf}g_cv366jSICPl$WaRt+}c z%K%b3sJ&dxzxI^R#L8JH-{fmPp@SMP2W98{R~t5Cv+!888cE&N`t0=~-l)53${#|_ z2K@25(>b8ML#Vl+z3wy%v~Z_!QJLwmJRKN1L1%*Yy3_HXz3y}Z=zMqT+Y?V?X@|J- zuG&jtj}Fqs23j)T+DpBT-H{K{^F~?~I^J7d%Dy>Bz4}1RTMtrhA9XE0AQ+~(r&|D% zJXs!yIm;{NX?TVZGxZhrXF9+W2MGIHv)^NX-+ci4Td|*)9Vp}+wx41K!~Tlwr}V+F zzt>+uet!!46OejI`afUsJ%iOC3)}rA&mFBQk}2a$kKiAFq<)XZ!1vP8acU&nwwG>= zg9>3zen=+Fa@JljnkX2VbVk$m@(G!uBkq6x-;Veblj-%2n2wI9{W&$7uFhaPKc~~v z)%@^={>U!WAK7|;RPu47Ke7w;N45^sd+Ys?tpoM<^!~^$)F0V}`Xf8PKQ7Ebf0!3@ zZ+OFyR&z`T_vlp>-7|1Z-BFQB%~HDrR(xY%s~34tfqomLCD6CC)Vxx4!2^Cce_*TM z3?^b=I}40vfe`?D7iYzMYz_^}&V5jU1Dgj*rUQFCoz-ow+A@6Ko;Sy{=waAmMYsN7 zu)=uuaEXc-%9`9SN|ksc$e~D9G}vy>Qn6S?MRLqjkC=bmjV5LVXiQyR6C zRNT*3p*!gG8nu?I=MJ<&i4Gk|iInB=V>=Xx2~aO6I$kV$Z0b;5$Af zQ#Z2D*3j^u5zOL59@R~6{eoaNWQ`}N6OySat^7ru5?Coel8Fq5&ej>nkx^ZRDY{rB z_Z$?X?HY>x6^fC(h8Fz_#i;0XH!Y+X#|kNiU?3Eu<9Ux_^!t}$1T$)KS&d`yt2wkI zhOzal^zNkNzpGu?@>M+MDw@rltElreXoa*2-5Dyh0@>2$6VhLt!U!WieIm( z9c=6{_V^ZB(cz)`J7dL`QLQIxn#*^Y=k_{*`t8y(d|#zDR-sf&YG=*^3tb}~K2arw zwOO+8iQ_l#XrTrA*y~QyKzs8ZEkS$TX)Dmeoesn+m)4+#J8ccR4rs4Ctqa=gPV0fr zcc*UVK>l^}$7VhMO1n&sik5{rDP2vODUT;&M_^>@e9ew~rZy;1zKuPeNBcT}IWe-U z{-VZazUg3VSp-7V$N4LHiv|PV=XkW4caL?H%7>`%efI@K6-TcP z3y4}8=U#|f2DE^v;^={>A4{gBIlA%2(B#UFrs8|p%8oni@@(24@2JIY&gQS;9RQ|r z`M}gHa;tBVEy2;mlswxLkOn0<8ndL?d~brIzbFi=?n7DC9M?d@vO{TJb;lxeqgkTv zvlNyd%9-Bt<^5l(ihE0E4!?BV*#^miJM|b<9nUKkQ#$c!lN#`8_bU(@A2bMZ| zjYxJ(V(Vwpx@3nicpbe?s_BR@zlZybw<&6r(-H31U+^kNNp;lFNPpATJHPw5 zWAWhJjd5>y0=+WN;>5d^+5BLNqX<4Dm_cW1Inr4BnN+qmbS-5j&8ZDtJL_~u7lO37 zGe6a-)5Q++Hgz1=^f*!8&^3-YQJK-uhK{PN>~y}Vp-`x$)96fNlp8sX?{6Y5+?`6d zQXOU4)v4ra=16yaKNVH)C{&}8TWT^T{p3^{-ptT2@gSjL>zg^gv#}wQ3=RAEZO1>1 z9iB*wIzq$vL^|3LY*tSMoBCi=2m5k?&GLy9)5-Cn3yS&_m!C4H8|-w2{j8H?vL$Hl zcn=~wT#zlDF`m+TIVQ04nRL3B@>Ej5p#=C7OGizkLH^*?bkE33(`2XY> zEGQLy2-|!1bzn^%BgYWY&ry?|8b_V`IU?*}1au)9vGq`8KC_<#IfkC&3I^5+{z>f? zujd#%kEHMWJ2r-={*OW;$KWl5976}X|GpyxwR-fs@&*R;)Jh~8>=MO&;OK?AA=?l_ zJ3er%XQRgQjDe1>tV|U>*&qumamW8B*`Qy)98bRucAO1gJ?4!%=cSIXqURYz9_$o6>*uy9mHj2kg z5SBH6B(vYCY;;TF3mxMvK`n>;*OF3)P}&Mu(kFxI z^a@8o_7v|Jy_R$rv~EdV@ZJHm*OKmo)`v62kv#>i4`)J=Jq7Kxq|2bamUIPlz9o%c z1xsT028k4EDZX*FqngAP58_uobzqi(GDzf2ud%L!h^I zPaZ%McEVFVd>``NE*xGEV&SZGOfA2*({OlrTApxt!Jj!U*x3BOM)wpu=xA?Z-}a%w zhoOfD`_Sscj#SsyK43FW^fES90-KF}=+$APn;zq3>Fx=&++e5o_SCP1!&~y+f4gbn zd!n1FQHNYdGt>2603VrhD9_1t6l8}W-fR(i#j$Ycy^3>h==}pDaS?jO(Gz-+9U6Jc zQO#5uO!e&0`BRQ|_*%WnX~(BH{CwKcjpe*6@YqwMW?7J?P4LMA@n$%I+{1?IHO5jZN=f zU4Xz#^q|;_j_QF`^$}MB0JTUBLAF_P>#BV8MPcwCb*J=8F!;Z_)9Opmtc%@AxeU#^ z>2e=0q**|0`5B92Ld#kl=HFj-oYtf0NsngzRzgD*J%0@b|7}-FO4Gu4+;yQ|b-Pln zn~qy7tSgVXr5k(~YIhr&HN6Xsy$zKZ-UTZ0sfdBV)e$q(2X~=!w++n_PZOGDz2mrP zV*#B!n)O^5e&>!9^AZhB??@Rh9i3fC9l=ImzB-uh0yc>qDJ@Y8r9WOeItkzhUU>?5 zHGAb~YY9r|@ZZcvTnADIXvy@zUu(w3zfHAd?H_M2{SJELbpg4cbr(<`347397mx>9 z52h86um`ONQ_u%NdtJaG&|Vji13KRYJho^Erl;GZ6ZK$P+^V@O32ulNd1dUWG)QYv z>Phv?^lHG5zu;ogHVJQJHjd+3G*;5mGaKiv+AnN$d)i~uBJ2r9vL63$#s8s0v}<(S zu2l(l;#v6#aQvIPDnSpX--4cnM$H8C_Kf;#S}#1`@ge%;uBL5bG41#gr`C#y^y&^uG;$i# zifS)drMGBGF)fX4ev8f&(|R%YTU0AV`!upefP14{@WN{vLaaA0D3}Nus>V#Cy@{V>)M(k%V^zQja$PkdI-N=-Ys>V zo?gE-Eh>Z6abOV}Jl1u%jCR(>ZnogdbCTKq6S+k((J#sQ;w7^rc<77BC@r) zEVe0~XpHVC(v;$xpgUIS-H|^`?JY71-fTFSi|%;Z#M2#{alz9aaC+u6ttuw>a`XuV z|6wDeJEphN+OR>5_{CP@>a~WXw9(44^9?D!jh5;<-VnkqB~q?<9jq-#Khluqw9)ht zD!N67DF@nUJFM*6dVFvf%_Xr9>KWc|V^@tcmRFa$_s}BQH+5-B4=ClAb!krzE#0-Q zF8KZ+x*Jo#z;|_B3hAkh6P-2<-7Os8r#(fdt*HIqPFqr2blMd5XDwPZK%2oj*QUr1 zw1TWI7-K+ghm-Q|5TRBIX9>wlCiR0ZAT)u2Jcv@*r2 z!S4mX;rF~1g5N_Xx0>*IN6brWiuf!txg)fAdvzm|i|5Lxs!{C`S}+#hG%~p(v^AlP zQP}I7^@`%4aW!d!eYr?_? z9E^d}`#71x#=^?*1;UiEu(D?X?&&fjRqGnYYDxlHcz2cs1AIrxn~l>ROYH3=UT?g% z8WSRt=-Nc>3>#U4@1LY8W_GtaotUQeWj|EsiPN<(#+p^9b~B-_i>vV~Gqn>~fu$O4 zo2_kQ&k}j(Ia)o&dMDC}-?T6~n5BKr;>Bv&+F-Uek?y+j?}9{%pQmN8I|(#r9;(_S zk)F)c;!Q^r%rtH~rVTfruWewZaCN?x$R;OH>;gRfc>*n2piPmQ&`7sdpL#CT;@Fo7 zv}mEWh+)OY*hShBHXwmcEP_2X*N#1{W|!d$(8v49Pu4`+#7`suGbbYYh`M;0fnZ; z(FAdP9LKlei0^^pXg~vJ1b@C!>x(am;;7eVt&wSMC4la^u5ilTtW97GDq+1x?XIZ~ zu72Pj4YvY+(iBhxCJy&AsdA63s>c>*z z4lRedV)^qOTBM1ctw>?Jwf$^kMY_0K!zxo1dEy@Jyo62VT3TGknSXCx*ODmQ=4wH4 zUuu35=rzu|`G1W2Qk%}^lowTxr<(h;d6r~%Kit%Bd=fvf*4dV^w&f}I0F-8R4BvY| zTcGnkq?M7XSz|>1Nct-bu@liaaUOuV@&1`9nfeNYMS)$sWyGqP!JCH1AahzHpf&3j zL$7kQRP+95h&Z#MR-E@ftj&^w`r&+Lgs%Q%P1`1g(nnr!2rLs!Vbo3i7orOeG$T3v;X%wwH2C<)sqL|}alBrsh znO@fjsLU51*NS49n<&a{<_s$Tq#P=FSiFm2Zn6Dw-zc0{!j}m`c#`CnBo94aB1dy) zLsL5VR0?#}2tJ8Bd#i8O_Gmd+L!fIq75P@H&}OmDTXNqhRp(h+IGeJY<>=zKTGwJp?mDPmUsM/=-kX;k%IO2853 zSB{6}YBeR4%l{AM>J=(Cx0UkPwMn7!*>;Dv|gr@r9Ij6sy}PH zYL_hoVF<0s7e?@=jiqr-*Q`KjP0*$iD06jU-K}~>@I+6C=#@IqB%on=Ule%ohfm9N zL~|6vh%l+3=5OA>D>V(kCVt1x0*W|G^H*oJK}^$|$_h1g+<9$_aka1jDs^%Wr+hxxIwI0aan6+UmS^s z0l;1U)W_X}D*vtpP@OAUZ|NGXx&+^N`wAFzh@`OJ;Tu0KDSTsDI{&+t9s07Q5s#Vz z1w@Zeaz~)9It_cSG}`q(75PJ}&QeNJ+8^4y&<+2O(*OLS-C<`U=+-r@6_n!79(CRQ z>iW3*ysZ69D3X`yuVY;An5vdEQ}S3>3Cg<;=Q}w0E%o%O!0%GoT z7uG?4sFjw?BT9ISjeVpoXJ<=bdYKkuYF7f;hTl;9Fo@SPU6uKU$H1)8dFu8Eqosp? zYko9pwoBdfRKrJE*jlXf-&!N-z5IV;ok{K+2mGE1@ioz{JBeQZ4G-9;IG^!M!zMyw z@Bztlpx@!eY14Cn{NBaQ)X(iIN#=jhq?}MxYv2^$;{5G@v^+^_M5mtMxmmBZ64dRb zHj}NzknJU+!je!P@=D8)%%6pL8-h3!LR(&InJh4LVXQNT%?nwWfy3*N-BX+ylBsBj z5h;LKodYD+AcO{+oQ+JYi|L^vh)$WDZP?UeRMzYqz+M$2go;}9quKdgBz6F6D&v*7 z2P$m9Sjh_&gfaN^!OA4Q&Ic0vvMArvY3%SHJ-tFw{B1_$$VHYa8wzX+mvn)3`h z8pQiLod_*218GhXXLt5iApKRuxy=+6Xx6{j$vhtr$iEA8&Sa)hMa=XYhkA@C>fFT| z7NOW;&cXK2ixlYiL>d(045eemoWLZ?)=XabLnu!ro3@aUOsv5ZJ-WT@=?o#^kF=Q^3hfEMTT& z3YeMa;`K^8QyEKf@j0cO?PTP((ETD!!Q~3h;u8DWL1imCbJ?d3{-mNa$Dj zoh7JMRcAK4WH%7VPj()g;Eb1~zo~LnXEWN8=$yvd*bU^7XETsTik;7?CJJ>Gg+k}m z_vM$XJI7&NFdKDGLhoLqZi$fo*GUl0pH}`P$$3;_SdMsqO-Qhjm10ty15968&D8Ro zD~11(;#|!9Q=u@aszz^P&E>!}0QPT#_Qf!z-fQbDLgM;jD zhI{*gla3-xH7$@uwSaW`qp`D^dAba-=qb4U8=NXNY2vKz<;Yv=;35Sj3WJLs;{0FW zqH2B_16*u?ybl}?NS9=RErO_dsoI>4?)-PmABTq^=I?IPT4(!axc^#Q`&YPc>?!9B_g{L-{IAE0 zaBo^Ip0Lf?AzT-)-*zQb_!ebCGQc+sOeuGx^*ss&$ zRnlYsNk3}W+L>gk;D_Gyp-gfS){hQg-#f6YScX6!{5;%i% zfdsrY6iC2Z!|<~KjbiY>7YG<-{0my)=~hp94-mMTfr^|knQ6tB&W8Cd7g)f{7g%6p z{vQGk<$y>! z-xU_wf|1${hM2=>R5#}g<|w!`f|_(ki3#|pI~>|c$#7^1J>bx);Bj7u*58DstHs%L z`nIRDx#^sw`?A*5|6OO4sXWf$%UaOYcbx+R0wnW-=M$Ox5`My$Iq+|@>j5Q9<3RMg z9*|J}nGb4NU%+6ohJVne_i@J+Qv)IEJfRIHqv;sCs&w*tK;3ffP@pLgmr)>J(0XCN zg2KGzd(LV4QsHn0Hv<+*rb#|#zWuOkl|L03>}FyKc0K$ir6A|?wz^!CJ_-^LWEjUf{2|U(p$8)6h&=~t#%@@3nDkvV~wRK zsc#yJLG4uSQbkcBsC{2*7r)P$nVYR%zd!QIoO7NzGxwbHyr1Vh=giFI0cHWTS^*dieqKok>_}m+-Uh* z0g&J`91B{+mS%n@%)eo7@;|Q4!P*bc@PKydg967IIM5*QO`%Gy)I~9zq7&dO1X-NL@;M70xK-C;7%rUY zR&SruXp(7}kzII2S<_6X+3HucX}W0|6Y<#83{wl{_L?TmFvSR8z7l9|ikF?<%`mlP zCtp$IOjAwv$t#MRX*ykU_A5a(>__l);ez>I!R+BnN=!uC#=N59vrH*${Yy%ng=(#@ zsM2iHDk0{jK-CvuZhvRCX`=DaOZ<|EBvT;GpJVE6T%{*{$(Cf=<}nCKH8L<{j>$%k zlT6*%t``(F*K|@``9hfgGM~v__JTr^O@6G@OC>7V_I-G+b&LY+x0iQTj5p*wSZ;U#baDQsb+%>O2}v14D=pu3{ctG&ix@)Y4#~JqKU{ zPpmeT7dkur9^-`q7isCZ7fSyu9f6 zI#W2m5Vw1wzK{7&%bQdu^K>D*XU>(;?B4Xp6jRUa5QaS#=)-<5i89knwb`jh6m!&E zOR4u0?4D2(WvAMhq^e1eP+>m9$9QEheCm%f_^5_Y`++{H;bV6nQHUgl$zS8d!gep_ z5yeU3*3WCGl@>I6Kk&RlX0MVi=Q4YXb(xP{T%F}6-~#EU9(ezJ1hfNID>)MPs9Q5Q zDn8mQH}#>i`)3noxfZpoxN7x$R7+V!Br_OP}ACdO%UzObCnJr`Ye!W$ElT z(=Uy7-`D#upHXYf^YR(BEl6{t=DHhh)LeI?PH&e%z-84mA?dF; z)ne=KQR=Uzwzyet&RjKeb4Dw6n%t4kk>kq8qw0n=c z!u(fXQSk#N2if*kX$Wh0 zmy!-Zy{FvK)%&x9Q1AP9To-%Q(B${h+jWE#t^-zLAJ<|g#&kSRI* z&~4lX0LUT8?bm*!z2S?$g)cr1dA@kHj2!^0C-^u=3f{9O3EuF_y=U>)kyO7!As%Kw zYYCJOG+3NH@UzPac-0+GC-^9De>W{LK$AZdGgmBH5}C7+S+%$subHlK8((KNhl%TN zq0gGS^ioPIbDKPmqY+BnR(6*(Z!JY7FPiGI57!Bntco(^qUkuk?0B79sB`S^>ze(_ zysp`=_{*?g@Xi}vGS#NbS*9O^i0iuf+I3AcUsbMa=F5`J%~!-V3V#Fh)#oZVU;VDp zwQDe6hp6#Yn6HR;FkjuT!+agP%FUO94qrC~v+~z88@A>uZu~%=4YOY>Xv5I`$sTAE zeJJ2qV}P2^^@iIpO{idjYQxT4Rc#p6xM^}XY2%5TFxSbd37d3PGhqV16ZDkJgpEQz zH(|Z6Y9`G8mgyavnN5DT;T6SZQ{ruq_y*Fcrf{lz2ezxZ#d)MCmN4=ry1C2kxMC)M z;Z)_jrtL;{K8w;vS^~)U$aID+&Z3wgQKrX_FdjXwP_M`6w-;HI_83+yDoeLwho6`% zRQHLgZpnjLn(3N}$A1^h^9p2@v$#zQAc$-zI$0~FxzDsYsoijy(w}1Zcg&)YXBhq~ zF4O*JFl?S#6#3k=igo0V$eB{vuFI74uL!=rL9Fe<*jOgSCReq?zG^R@XBjqPM^ zL>ph4eiTzK6|`YVmuSE%*sz>SO5!U_$yuLE3T#-c2ityun=i!vy)F=Q7h~D<3wUjd z7_MZvi>b^|j$5x&_|NUu=lma^x@nzLj(#p-=}YBGiRFbxf9ZB>bSW{VSb!6HfvHKEun4#k$7N&p~zbrf&WwF`QpVHC{zgmfv`d{-ohMM1Ez*=l`OGh04tr3KAa63;7SwoJO5%WO^6Wj=Os)ocyI1=3Aj%HGA@MHmqmQ@`J)=(4=y4g*9ghN+gU}tm3!JwSpQot_G+({~&6)|XP7Cz&Ij>LXjK5f$ zMV+RcvX-(GR8IV*(fZS9qCz3tV4f#%<<>&BE0E?k4Y!n;uYWQj#Zw(bK1>nwZ2^o}!#;;yE@D|2rba5m;ReWIIoCm2N`wtBb2EFFuLp0sFY+ zA{_g`a=nA)S~|Iia~?LIzrvmd+hlw`w}vP&;S{BQVGb=jfuGdW1xz{Z3DVbuCcI5E z(57^(hS=Qa5;9w2E}~`Twjmc#s(vD#GGGk6t%+rEcJ%~4(kF(BT~D~G)w=4`35xAz zZozh)P?GA1Z%VL`qnZ`l+*pJa%Q&LVvsN?}x3S_!HB-Yw`%tfYgVoE5e1X7z6Qf!N@yzjD0nU56a%BfR4Edz|L^Y<8wmou`CT(( zCEJL>%yC#VV`qNHO&`cJW33JsG-LSr$sW)&z1wk|%LF*?f!vJEg932ZN)<(xYQTiU z+9XUnKTtiNTQHZ9YQZ-Cu34~}{3g(gE(^96`P_od`(3kOy`#i;!nQ+zDPP+g-Cpd# zmK~y#?Ez-X?+UF_<13wejFyrjsxQ~>Mm9ZKf zILt$oQ=K@>Luh$tz&u2QIX}lEA%w7w*N0Yg5i77O2Pmnlr53&Jg59Xqo%bLxFd;-| z`Pu_I%NxXi<?zvtS;GA~%kBKMd@P^C(;CasZ*}r@5_UmxmXFx4vHan_|FZnfK8@wSqKpra z{0nU%yy8ME->A#ESYA<=(FQ=li>oXzxj&cXn0$n|SdQa5E|y~=Qb%KX(7rsDtI|5l zRcW2&scSZI(pQt!BE^t?cEy7)gs(DXSpt>vD{U_+rw4B*WeVs2FHXpy97FR z1xqirM*vOIE_ygZ{G2aO{j|(Hf%c9R`>{hismdsE7^}C7Qb&nRSl}+YHcITm5_VGf zXmJ30v6Iq9gY3;zxhC}87_kOZcGB80;sR!X&{*-DPuHD-y2s>*YB@vH#W(dBN{Gd` zHNui#1!{l8t07s&iyeI2{~vLzzI{uN$BXeoZJcxOCc-DPCy1eV?62@boa+L7A&#Z| zN?~#0SmF8(sPApB)(a-WOlbQbZWKL>+uAZIL|u(z_Fomhcrnd@M^}}j31Wa??6@6D zuD)9l%W#VY<2T!ocCEk_r{gok`RwpE4ePtMDM>R$EL)vZTtZlX^CZhGFS4m#LnOa||zKAomK7CjM zrq;O#@Vr7ywd-;&rq0o2 zK6Y`Hsd#==^^cEYL_`|ut4zi5W9;crnW`QqFpa6s44tViY0gxaG-s+yT4n084Dw6^ zQ*(aSnCiNRJcclhsmVWqsrB`R3{BgZ%1%wq(M;Sy{z!oiRkxpYsBX>x%Q~fNQ1#dd zsBTQx`!!$Cr#8>a2i0{*bEx9}pcJ_s1b>xj4stRCTu_Bjh6mb7{}F{x(4o5Y7u?9w z|K&ne71N=r)~h2&r=u2rd_NFSL<4S_L#w8tJpcNI-%s3KZpK>}jmOmW3-uU3SY5v;3IV=; zfz0H5t*Z+2^$T5?uU||xkk@|E9pgn^!C-apAo2n6Zc&!@qvk6gJjQ+H;2$+#IpYKj z(lmU(i!WP@!`Hd^vc;K`@Rbcta-P6;FyBmZn{aQfPSk#DH3#|ZS|#KUILPeY8opqG zuc)0C$K&PbYbo>$kUDe?_mFE+#u?GZMy}D^WZ$!JlTWVE+~nvrXajgbt`&=eNatU% zSO+D`_fzq+b4Ok>A9-rDM{AFQ1*)?=agF9Iy9D?U;?A;~#@VW~Ty2f!ET^x=txV2y zmIIK_o#oPNG-vs{^Kh1HuU6?U(}~NXl~!B;-R-L>>jLPWyjsDk1?avW+Z*!Hy&vBR zslU4&7tVAWgHOEw&FSv(1BPrws>xT0$P$+@V@70x2M7Fd9C{>paK=Y#M`|1dC#%`2 z>zwhASV8EzQpdc<4RLNsoL-ER9`3V;PWk`{sG*Ryx8XhyUXh>llyO_EuU4qCMKWv_|_isd=vr=%W^R(D-^S-?p|fm3BV??Zwnw z+G9+Yc7YOOy0k|7h-c!?qNi}`BZEgC^WiU-b}=80G#X21e&GV0`IcoW^J`L{SBOOn zSgJ99+bb~tx21aT=3{;{ zMEs>iJmO!@@^~Oxum`k(hx>n0y|&Uk-2c6y=z64ruvG*>|3Ks8*$Jifh`+p0i}=qa zbY4@=FBvPYQkt+(i}*hw9`S!zirtu}qok`IaGk1JfPPNR0^CW)edMzM-I32NK%`T%05d9ML49zt zfVVthxoBCS`E%AGnVtrkW7)A}E$qJ{$b2H;ti>6WFYNDuY>k%#b5<(^wl`+-KW0*nGmvC{5nH~v}wiVi|mf78aV;&E86<{mVOku$s)dbX} zGPTXlVzLusCUandr1771pF^IXniGv_vkQ>_;HTzrejPOk9)q&{*gwtFg|Oc-S4PAB zk=ZKth0U||72L!1%-EhfTS53F(jY`3TV1@(oW*-KkNeGdJ>b6j6Abva0Y^9y@Vr9Y@2AVTxPM8P`Pju(?jOJfzaFDU48JYSy}tqh7wR=3DevA3p1@Jx2R`9+ zjq8JyMZ##_~pPN^)dHBrUb5kYq?O-0w-r{?D zJPQ8TR2~ISq>PRr`bs1^n#Z!IQ+O2orf239v=3Oo1K=m7Q0y0Go55ELch{S$g}Z;@ zB28TmqnuWGsuu3XZ-nvk)xzB(GI_XL%gk*uF2KXxM^vuEdP{oH+d4%HdOIh(D%XPE zMQ{&1=>2Rm4|?w}L8JSb>$2YQ+@e=iF84DZGq9TzHB=uSVBW?e;x(Gr!H4t)n&G0i z$twl*vrHwZ!?)&z!kURX(gP-HNS`}VLwbBHNBWvL1xQaduoH0n$pFR%h{5YS%!Di5!LOa$#pdMqmsXqP33RI%ki&L-* z$!IWXs>9uR*NH03Z%xo(-fx1|fv(v1CFFCMADN(F0}>vVc{m>93Y(9DY1>G11NP^5 zdNC3tkHmWwmRoYFA2`d@j{!#~o-1Ipj=T5v{mQ)2AUfMWj{G`W zWQrbV{!*wn9!;B$$2pIWGvCBZ?RBu@b{~5r1ZZH-j0f0p%)y>pkN~h(8ms&EmlDh= z#mYNpsm?%v4)zCQ=;RcDJ#0(?uuqu^u;V%^*dLBY3#cm29Rh1wFUS@K`;A-~4eXuA zXkc$PMhE+h=>W;f(aP@W9PC-6b+Gr~=j8+Y8J-5%)t_JpQo*kMoFEPCJ4b6^uLHrt zV6QP+13ObIEeQ4zJg*SgUyb4y#{k0(@Mlj3=`tU?xC-{qaRCnY*c1@I2U&lekyTe&?d;`I^g83|`fW&7okbTSES4^sK4 zw}OIgI$(Q%&i0wmfgn`K*{&Yr@+#XuQlPP&T^Yf*>(rup-6cldjJt47Dw z=Tel%o6UGIWzM%0wH2QHJ=(V!&l*I{#qN~jTg{>=AU9Ty-iJ*K(4I~?I!GC-n3+K^ ze5;4a-we{j4C36nsTS)_8xL`R2$uII%E>XW-kJ+`sOkR$36lCwN{V z3`gs7E({;kWz>c(ba55KKj8u#!!=FN%;`;@=fUCIz4cDb=VA}!dHFbe1!}+!c z1z$JUV6BmT-Mm;x>8S@)?Ejc2vNt{R#m)ax6Y#okaId>351zy8?!n{cyTyw=3Wm(j z_0U4*EqZDp^Svm~A2P3v%kz+VKkibYh4_|#^%za6hRn-AfQQUA0j)V*!aQWI3u__s zqWw`#5C(@9GjG#_$IMq1rB_eQt=Qh~THt)pGcy9`O}cYeyDWA7*Q~Im-8JeuyDQ-@ zxU2nRx7<<-ceP8>jhAK;4Bd6`#^HT89K83sX|A@{Ywl_rx+&N-30FI)8)dzPt3AD| z=4yZW4zBj>u9~ZT@Eu(3f4XX}cHgdO5AF%+8~!gMo!`~Q&&za;BJEfkcIq)#9==)f zV+E?K{e4#@B!|1&+9=|#w(CUI)o$8VbF~k4!Cg#tO@!=eb&=0q?TTHMhab#vwId-w zJ&IU@sg=RffK~58(+rkawzdn0b58ZLzi6Ca=Z;?NFFB8Z_pbdWhw)AUSM(egf9$sX zfKpztfb)KxHO^-jv3$wCMeZ&Ve{`E+l;!9AZk{g0 z`Np|28t1ok(!%E}I`PefR>YVc}+dG!|<@M`DW zkt}GKw{_Am@5G6PF+aPbhWQw^(t?=(gXa~(dzRvmjpX;1IT-H*XIURgI;ps;A z9eStc;GojX?QwdneNa*HokC#~|S1JcKel@Vj|n@*^kkt%TtGU!Q55 zcS&&0tH-FaQF+S-FZDvXbs(2V%N6X7KaW>aMr(oc4wWsNjY-iu>XmANmVx+6N;EAF zvb139qUl!awMP8CO)Mb(x2?6{%7$k6QNOp=h`+P77AntdZh_~F7Z9nB zgF!^yR``Pu+*&98`c@k8<<=VUd$+QH_`%5K@$${BEr^$QXhk*KSXvl1k+Zc$kC$&~ zW3e#>-~8qKn#1Gwcn`u|g)qJM8o zj($92pccEL<`{D7xhnl*TWa)w)B-n>kN#gHpVL3Or4}_G(%$lpjc7r!(Ut+MOAERf z4fOxfA~#;Xms&Y2r2^JS&Y9r9i~I2Jb6=W;%VxOE+^dXoaPGHm&bc4U_BL0NI$DaT z%cjNhSfAmMP)ub#=ew5BVXr3C#nXOWEfv`Rn(}>z`}neHagKWoo?;sAh3}eTeDfXT z#;+`Ojr*DufPTNPEb6i;uBmc=1d8)>{|-+V;{Kpq8IAkdO*HNwYr;1kTIt)K;C^5e zZSC|-PYc#g`!vzvf2%R?=sfs$<#lQBN9W*k8yXAHFNwlzY`}GhQHESga1sm z(t_}R$MXuof1)nug8wsJMjZ)-F0R7=A}#>}r(&+y(B9H#6 zG@k}&XL`BluS%=*7jSJJYiUgz1E64PtfhB^Mt`*>bpEL=p>9Kb)!(wS=wRH*BSW!V zI{?4l%Vh`P@T1W*J5V@Zw*!3}>2|<(Fzmq2aBT^7$Y9InM%G4pPv~@&8tNfoh z%j(L9!q7NC1rMqpz;WSS?>T6+k{HRQfe=W@J zflMA|*D`ZkkP9f|;=ylYW)Q}Jwz0fam=-7Qix}TY$!SB6^H{{P&iH!jd|=8L-vS%)rz-O6&p) zHkL1;KT<3{%44!%WBGyFG;$FPKshy&Kj(`Lgo|JRD%I8uK)1y(0CBZ71K?I0cYh$y z_x}#*{JuY$BEth3s1E=f=Z-#*(2K4twy3M71#?yUSFf$Dnrc;esa0_AUrpmwmH(G( zY5b3=rFE(+(0&^Eod0`jY5d>3%<@k7rzYHMzRCP>s-*)vQj`3a1K|<16vW!GW#)q9 z?C*|<=rZklxd`}VxZ>-)N8LK_Q+{1xsmFvrKY_zDSSm-hA1qVY`cEkJ2TO`D1-bmg zoz!l%WnR-Ep9u4<@e3T;m=s;bqsI)#*O9k?S!b0Kth2IV^;yOgM;7utYAkWgXCBD+ zK)yxIKhJCX)ZShhw#JfJg#A&Sa?&iF*q_y@(@&Ok_G5L$eS>A1Ap9=`{@fzwqon<8 z2{U*M4iVx$_LL6@^U=NhVrY`6u)0A?ndt`!I&qv z#23UTyF0V--!0x9N;TJUA(+AyOA~fDSec|)UKj!*A*g-uqKsNY3!W~^Pe2?PH8u%W z7H_xQG_b=}l}W!^(%i)|RSHVjt0>|7EyIe5J1e6g-?g??rv1lotsg5Z?#C@niWtKy zfhWUPDlfh7e{RD>jxf41eI@C76%9+Ns!gR7Pe!dj%h z%8>9jlxvn|>^)+W*DPORp?psRsq=#CmhQ#zIrM=TO+DKkpotBoIz_8uIQ7`xgsya! z$|(o0Tkad!=5lnh5vo6Y!_to#QH6f3IyB*?r7{~;j@I6^LSDcX5lbk=vz^OAYDZQ_FF- zp$w(B!!O5)+t}zb)a$vWYVmdl8bTM71F&7Y^a1G;g*( z!^n$Cb%h)|u5}k((VI!F*n2yrGf9qoX-D1s1nBm2_1FykhfYKP`=P>-ctu+R{#^S1 zHS)Or4@X-k;4fP+tNP#FTk#a61x#pU7nE5KB)s_Ic~PmhFwKUm;(gRq<*`&;iT05G zDIy3~wcC9teUjv^eCa7|!$+QE{FEuuR9fgI%{G4}>-ywoavJugIJ%jW7 z7XoEL`D&W9Oz@77AXkF74CLIVIvOC2_nJSpuE)o}rO48idAVSA8sZZi6(m6!oG3l; z*jiRqAUp=aKhZ>Qpci#yC;63w;V*9 zYf8zb|0;zuCzn7+O?R9rg-iY@RkKET;`Uceb*$h6nRf!d+FBo{jq{P~uxg&l$y(A5 zqYzsX6>+s+U02#{3@hnU`|s*W8<Nrf(vo&g^k<+8-fB z32lqxPPldlH%7N?MQU!4+=neKPGS?uA-pW6t9L>Z3F=+B7_DtCB~_VM?7!-rq~;Y= z@0rCk^`4BfkE!>BVqCqu2%`Vwef@XUl$u(Pvh?Kkx!p@?aRx3l=NHq*XKO{fw zl{(YAwo(SGSd{DXN%q8@;-Vx~je{_s%2nfkqR>n%!5xovNy`lZrDSI@KHbtS?hII8 zm&Lu!-^T@u`{6SQ7IzX}3ImHC9p4x(6tUyickx=YR4sals2;uMmSDV8~Qd( zDo>j`NrQyLMxD~5zmPTvR!FOT*6d64S*(!~zjXCkXKK({QZZc>w~&kJd$nr_lCc3Yrp-Oy>x1ijPRc9+JpbbRRhmIbfs=`Ph~^98CIgN}Q| z^p0B@!#l1lqeDH>ad;cpf4DqN%`4b(*d(lSc^t|<)^Q^krT0R|orKP*NDls*cbprN zYRC2H%R6qfo8EEB-|&v>fg~W@nSA?88A2JPPW6{gusa_pbwF;8w~UhZR6^P@qma8$k-a0OR>IA9cmjb*Qk(2|s96W>W%W1@ zu%Ds6!hmgyypI94#d|!gAV}|(exs#@1{U~ENqithF^V1!$_{>u?ftow-7ub0_Wo;} zu+iY7fU>)>9Qj&_og#?_vDItb5cg(uwl;fB-mj%7%AShhV0x{@Op{UtG3XVf@{zUT zEAmW~9G+f0Ungp*S4wQ6RHcN_Xwd^^rpb`3X}_)sh+;Y0w5~H2dNa#rn(M z3;qX$mVd-l&&h}W{GYU*J$Z=PxO7q2fkosGVbU^s^|REQ6~miWGNfLt$3xnmp(3-{Zeu+Qu&4p^N)96}(eKg{J}^Xr_S;xT7pS$hp~BcA_NN z#m!b=sEeCes=&vL_bFWuftzgLZLX#PwC%7og*8Uv2z1r=w%S#6{|E-x?OVKa?DXqV z*td75bH)~KlYo(*2W_hdg^BA{^^jejN07W-bp z{p7=AuS*<{M_KhtIvHF34S{@QZ2C7Xcn>m$@O+(&RsZH>eCVP4<1RN~LXY!0ACrs8 z;3NIT`3M`^sgd$Y=?HSIH2keji%KPa+-%(ahCC+S@US#?y770EZB zoQ3D%xudeYqHJP9ZB(Yx@o;6ipD-me??Sa{e4rf2US`tTKskzip2;EUO5~LX;yLR&GNzF=$emh6Eq7U0bcd!;UvU0co& zf=}oQiu1OySI4PWsI0o5N5IKkC+2V{8j{U8t_0MTfzf5Mb3K~Th0#Em92Z7s@D*QR z^m;uR7@c{H{2It>*;mKtPy;!Ig&pIaS%!Y9BbzDJUpCRiTCzkL4du~-`!T(}Bf{l_ z?9@>LQ9Dt$M)C&ccTDTozzFo~h@%u6k=L*OjkSLLNk^+1CqTa@bJK@@t)Sd$EZ;E* z!AJGZz1kOQ(_Uj}Reym@|LqP4%ikF6p4oGF;NX4-^FLUk7xTbbNQYE-QaPb4fG1%dLcf13GejagGbQcJ(+9xpR;% zjNBQ>`xtU3p+Xh8qrZ}Y+}`_jm$b*%a&6(KefeF|onOmvNdxz)ed(j@?k~e7J+eoM z8z{piow5fvl#jXbdo-8y@gNL{c6)U2_Sp@oeBkZ5oBW2#4$rncUk7jN-Ade087^tu zuR3yV6F73W>`+cll;M)D+)leE%jd+&+x1K8pq;o~cS$czl}C$aUYgG(Exlc%?ZoXG zZO3faX1H}j7-2RIyi*ox z3OWlz&^1FO|3z{UeSTj~X|+g(Z|XpeDt)7u$o<%=U-)$*HSS8ADP$@1bLcM=w^Uxh z{zf5pPWK_b465n-i>{gvmT}c=yNSe=P|a%L$%WP1kaA(Q6@PKd%zeth|8cDTn67!Jhkur* zunFlDl_94HU#2q}9E#6}=48l8ta&;mZIr#`t?9fC&(~2Bp__`J^B;`$=nFYPU;%#OyyQ;k&uA zoJqqdtBm=Ze_f}c%1lRQ8fE2Jo6?#+a;?ZsDEt?NTLOwWH6eUh?s&Xo1M**#k8qw_ zRn?h||86S~&qDrM24k?YI_RBHs z{dy&RzdX#~w_-g6R7_!)6wX}A)069~$BWi0;Roe6_-w{{CG3#A-`%tSk9nnie^iQ} zkav5Cp=%0WqvjfZjY!YzqI{MrISn2&9lmRnn&;$1qj2>Heb8OF2w3`k@dKNG8*(0v zv90!Vx7X@95dluaj7g5@ACz8~WlsYu`GYbnOU5R#)vFXSTShQFbd_@Ss(jMO?yjKl zI#xg0c2l0u+O4FhTXJ9H4=bR2ZC^wA{=5a{8@htxZp$~>rz@!M9XXvXSwZq$IhH+I zP8T1^jp@owxj5~*EtjD9de%Vp)e1_hhbk-FgW24=oIJyjm~l_;3)Osd59iyP((?Pz z*dg^4;emXXvBjypqDidSa*BB@C$dhd{DO88p2(fqkyMI#0xhhVO6gCag>zG}ifav_ z@1Dvv*r-&BYHXEh=To^h>zztZpUMulXBj~+&?svvMr1E{=el$R z)t%LxtX8~3-FfvF1lG5?IVXiBIE<;}-4wU5 z;<;SI*ligai*Msq9zK`X;t8gu6y6-a_|i++LPMHcEp+LHoXu7)Rd&CWBMru=rI4>N zM)0M;*KmJJET!G8aI-bu$jNNTQriCpEqibYU2JV_qI~yO_BXJBODN=utvqdiCr@UL zmr(e7Ii-Z}5;ngzLcM{8FR6Vao0Xovm)r0ON~0Y4YL)E87*YcD&dhXNLi%MR zjB^&`RF`(#u$0sLd&jxO+?ZBW27iznGO;0~awF&{t+!a&ZLr2MmavGzjn=-ECN4rX zRZ-2Pa?Wi0cZ)CQG&D$Xj6uF?QQysXj9f%VjaF~@7V`32QjUOYi|7r?gufSI5DSv8 zQmcryKcZ6$mDHlvkxVGDP@k;SEN;b%r4KC7$NFcbt@GePE>LcISv?J6)djd5*E#-i z&{xwPl^2k^Xx+r#e6Q>ft&0WG{5=G?spKCkt1;P8`g`gtTf;ovcz#nn@(E3TKVM0g zt>GnDwG`!HIcp4F2I^FzDp-#);b^i>o;sDSzls}@aT5R1w;R|HILomvSz&?J{RZ(< zUcjy7UM!@oi+9vYR?Y=kcNAdTo70F*U4NM%H)^*SJk= z^&EOy$J&>@nN3|nt%um**?iE;RQFSBCQF)4#p_zr+0)syqpmfUwU|v+>Y*pL&gQz+ zi-l%FZJ92x}A@m&g^&n}$SK$Fm!WT+3qEiA1hocw=EAEpBXeFbVmMt!ue3 z)T$EgY-06_`Zn>uy48>8<bgN4u*R2@irkT20;UPS^xU!$IvuoLkp|XU|c=JrCgaUt@l|^h_$k&u|qRxKx;Ik_YAIA zF9SZYI)m~BWM;sLcbPm79*|kIPk9z;g~@9^okH5-=lV>ibM34t!i#D8$e0>so!8>p zG&bM*`g?uR7#{+{amVRQT{Jeh7L7foJED>2VOXXv8ow&)_S)cDI7V6P=}Js{>&+s@ zMpJR?*^5hhQ?HKJa27F@R&~TMF;7)Gb+R5sTz`sYEtT*tRzCy#W3m#{)#_~!6DMPk zwc(=>PsBA#bWEE}iQTLtYxd*$O?iF|tZpSZdh;|8;I=nRP4~!68`X5T$x6-c=yC6Z z_=J;cLm3vDxuJE#LUW6$j@^?e?JH{+_TwbQy@z$NAs_;RsxghnJLhnP20YEREFA`L%ViyXYBTP@;IeGIoH~y_k4-0t)h7>)-_KTK}7%JRELaU=#+A z*HN%?wDp!jbRQ3SRrP8+4KJoS*mznz*1DhlF;0mYXN7_LdYmFpurkK3ja9rSS{EDH z4|w|R47hw|vNf3%9ZP+uK>51!N8+G-Rmb3s{jejCXIpC{5^P<_o{pxm)6nx@j-i0* z7&;q9)5%%ZP75x;!ujHXw+zI|f@WCTu;HUA=>h3*ng!cyXJm#YrJESF5CQz3NQf0hUnNa6djHhzZpE}vqct?p*)F~MX`SnPQPxYyx zhgYrc%K2og2V>_)P|kI$-`06n4}&pj1SI^23KBKEVJ*5~p4Fl>m~XWijP-eeYVyAO z9$NY8JBqu778}37I-A9epyGt~-SnL@maKTuK<)38VT-Ig4D7ez6tcuRiLD;4xt(X0 zSf{YD!>P+sYYOW)oE|Qrjlhhk{Js{$OqS4N~)8Vz|9zm7MCZ zbF1Vu{1flkf_&BP`A>Ij!m&+-fj*nWaYa<0-v%;V!XJ4Y1_f4-k?%bWR}>_>QhPN9 zD0?|XIkeWgm>KI1;arFnyp_21)`v#n-&kD}W~N)`8rZ5>^3Je675l{ER=7=!D1`=? z<>(npejBa3*(b3|)<)|vLG17?1h_{TfmQS#lO56DQm-wriH&)_;OR63Cpf~tRnoRt z`xbX!J%G(GS)7Wy+r5<guh+i$(ggwX!l^=ayF);%K3w|-eT)O+VT%>9*4 zhpZ_EF})uOI1JqC!A2)I()uZHez#t9XV3c5xs%pIp8NVj-~d*D2LLU7m9$gVfFi6r zzNUNzc5h!FiaQJav?4vl>b>BcbpyN6n=8vTwxKtr`~}Sv`%u_|Ae6H5*@mYF6vbRWsgTS4v;BrmG6M=WlC}fpz*?JH>d}+K>JAHP^^#1~dKdoV5)_ zWI@BHeN6+hU=y$PqSQI4`%D(}u-(^O54*6?uel1!wD*d&HY<aAtgo>b{J+HPPEWx;K(bq~H$lI}w5 z>c@S>=D#1eXT4jAc*pPC4C>>|hmF`3*2n5RV$7Q+9_EV}`WuSY@psX!*{4jt&u!+_ z7#>Vt%aj=E`v^8OB}N}G(qpT_M#Rv`$5!vKn=!l@@@9yv+Z0C=w-v*(k?%2nnd2~y z`G%IBe3M0Kx7V)n^D#=m6DwwqTe|7h&U}fk{-qn8duhGM#&=UTy|SJYgxIdSnyh(e z^)YzV?aH)`R>#kK2GjHR*7M@OT`&M!VubovcN%ugb3Ez7Cz2z*|3v=3Fq~TgDmYaG z>R&-sjuTxd_JdXS{vGA2FCAdld})8XTE4G~lKR2AfQdf5;#yqOyq$&>lN{DAv_rNH zpbTcSu$P?)6GvIO#B4nb0gF0Av^qq&$%F!a&(mB<-E3;w*;$D(+AxC@J1bq>Z7uZdT#;DpG zX7i!4LALeGFPe@9*>19b+LPxv8#YB%u`Oh+qN!I^8$L6Et@qdM}$W>a0+_93>j%+QklsEX5?eq!sxwnkCf zC$>Z;L{Vr>+b}i~>6*4E;WYN#sJCjWWt+~zqG)j~TMP?`qBpf{EtppnHK}du#0IpZ z#kFl~S!O$GQpXk=wZ9$4VXtD&buF4W4Lyxc)+XMui|6eZHB*W7cAgIK)nv+9Rhi8^ zZ&F3))s{`1<&v@CYUd=!&+X_?9b1gCD9R|i5jM3o3AG(E2uW@AJ8NAJP1c~U?YXg8 zTbG_9ua<#5X`{r2*^1+pmTf4pK6=UAmO>k#`MznRO$Bc^uwg3b*@j29%Tu**+hq1n zBy9?}rLaAb)S{71wS~VlvRw_G9Ep+ed1DMJ%ziGVIwm6h@))1B;mZQ}?-q~UwEj~a zjiF+rQKo)cb|=Lq`IJ@eMA#ZJIjeO(v#3j6Xsv`dwP8iczqS5rE;P4&5$+4om$P`~ zrJULL?-mdHgSL>7ubM{aHNTLkrghWkzsNBOc~e_cYzv#rCbp(&Eo^?mC|)z479MC} z8-p!Mt(5TAXaZqPOMO~+w2dvih!E8RA-lv5W;uDP3GYD`S8IL(x#5Bj^W)$|NE!1;1&lfPei=XV6*-VN1 z(&i{(+}xOxbA#QkJowr+9B-d*OqdzQLGe!Q|qJ32t2cMc#$I@ zLh&A8!{l&dBNV7H-Qoz~Bsl)pNO?HW*210ngj47++iuT$4IwZY-pc(sj@u0tHk|*o z_y&60Lfwi|kI}aI?0N%wG1}Ib)x(bJF}6djXalM=7RrX5(@?f__DKWUJr1ojwLaIg zIQDOSu427}w)J)G3Yn0nU5_Vd+SM{n)2^T5Y!?`wVXnrN@`nUyS85m)p9Jl?SC1A< zf_B9qJsH}yqn>_eLnlMK0>bFcWN26MFzPY|+V!d)t(pSua@3sgjk*wQIqrbaxiC>+PqsU^W`9{imvSQL8z&Edk4{&Y8x%WqNFH%6p2CKRLc} zpHeo-1`9VfRP#v3C)=j5=ul!#TZ&K>`(Uu&#G5ucZL^piA}Ka+IWe^0bTGhkv14i| z#irQ&*o06eDaH1ph%mUee(K7Fw)SjLZF;)Uwu3dSt)wrqT@-|nT6*!CWwryNXDy7I zJs5Er*o5tw;3!^88JlYJGl=_Z@&Sbcf7p^v^BlWtQrdD`Tx2TppO1@h&R+$4h5v3V zpdOA%j)lnocNFYguhPzJ{CDetzzFhFkpE&hVx>HWivMo@h@m2Xc1>m23R{#Rpf11A zU=-}F=}c%H@2KrcCkLtN8a3(KN?Q}}vdDi113P?@m%iZ`cibt_VXsNyt1$lDYAUN% z*{&J0I8HA>rJ3lppJd~W#Twfm`Bjo(j{ryArL;^R!HFwbGBh6jD@R;B+| z+gzh?x~kR#iu9|kJQKTAMFna^2ytF)(e6~0B6r!cm|s<;%5H8xGpZ=p_Si7{tX@UA zxzAR-2s;x<4>N5xD*n4|G5a)#*8UEao)bu(hoRD411ZYaF4O(PwoFzokaiz|UQZ3A z*rOPt7w`?-qtNTtffRGh*2}Pho*Y8BFS;zgnR)4$t*^mHn{zHbZqw$R&raAd=R8W6 zkJ`SVA*XD?tX^eGJq4YfR!O@~M5e79dtHfAGtr$LY2Pu_7hl2dK_&mdfZkb&JS*Bm zXzw4k8fXqow zpSE7cX%)Gu^SMupGq&Q)@Q$3PZ8oL^R|1vA2Mea8#LpLdkJbuN$U z%-y)T3~y9;CzSLI)^TAOYVsV7_H7viux;*$uA*EsX|R%yQyrDdkoybUQTE(dIsL+x zC5Z2QAYkUd9>X8OmsdWBTEmRq<@u9gMu$yy-11S}-`aADv&weG-QB(k(6lK#JnTE%IB(98mVG7}Dl!IR|(Wy!e~$>LZ;2pT;{jNwh<zU*f+*II8{ z;bY&xCYZTO-DFM8Tx;<;&NB9e>_;=*EMt#lZ$+-Uh^YG6d$WONuD^ct+|S;O?HBpX z)JBf7_I@q}w)opM1s+(=jydW*lXh}OfW05``o_iQg&~S}NG5u*)W{!ZGYO6UA1vw_v}RXlq4#CsqpimF($ksEI3XXw=sxG(aJp zjp2FubhZmm7t+~|Jg<<>Mw__KhR~48_S(iDz4#d8io3tE9TC7XUdqWJdlfwHTAHA= zesn*`ZlR37Y!)S=svWVTxY9U54H5MVw%=#`>>C zp2~n4c1%`_dge`5qrcH6tAQ}#9%m8Y#iTVz->HnPBAKqqst12abk{!RtD1J0@&ToI zfVVvDs%@XlBJgF}I`$O7r<6WIpVYA*W3Nln?ohk8JfKuTQ_kX39DPdB!%({)>t0In z{M7yizG(^l)QS!5?OB@=G_s+6D=Sk%2?@6^5QMVD_2R3I?FYmU#V{tnf}_3yv%P)^ zj<>~>txfD92J6qfpal2e@dQppys8vw#jy0f(Xxt`HM3XeAEG_k%r1KmhUCBZV8kai zbY|nfTYN(&e-fa7G0H)?@U?c9qy#s|$O+i%fr_tlg#u$D;~hI)>Ajc|Aid3lvbw-` zdDYTxVQW0dvz1+D%RQ)4D|;_C%|l6Sg=P;xdXZ2(ynPS%>vZ2WhNuZfeFI?fuDsIQ?O ztf4_k?_=L;5Kg%<<(qHpt?`ZM56Y$ib_aGgeW2KVc5m{JwQnF z*)`HWi$%Ss$Wb6u?f0~4l)aOXgwhXB_ylRRy{5o+yrnMV>`8K^cLr!JB26#&b46I* zj7V^ldq+9rFphjs=CN0MhG<<5FE6f^OW4#s9%G>NJ8CiB-bLv5)}ZdRR(2y-5SF~r z?n8Mn(e8t_%{OQTH3E!uaiwa4y^g{7>NRf~zTkn&)=fcEF|XGOo5sm82OF|xQ{ zZHgo3rD6U{jK!A>EBfk~oOM%go9IKG8nrNK5Ts_t&xXItE!7LHg=Qr0J8KquQRI=S$ zaDRy_2vQ}*nQX`O^47nK`#k$J#;X0RBz

Gt|8CoL64fX^4(@TvLy+mW$&n>M`^e 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%0D>f4jEt@L>?(Qy?G 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:cs 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

-vO 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%0D9P6cwQLK!%Z(1 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 O7x@kcVu1hv0000*0-mn` diff --git a/engram/dist/engram.c b/engram/dist/engram.c index 9c3ffce..00aa3cc 100644 --- a/engram/dist/engram.c +++ b/engram/dist/engram.c @@ -24,6 +24,7 @@ el_val_t route_forget(el_val_t method, el_val_t path, el_val_t body); el_val_t route_save(el_val_t method, el_val_t path, el_val_t body); el_val_t route_load(el_val_t method, el_val_t path, el_val_t body); el_val_t route_health(el_val_t method, el_val_t path, el_val_t body); +el_val_t route_embed_backfill(el_val_t method, el_val_t path, el_val_t body); el_val_t route_sync(el_val_t method, el_val_t path, el_val_t body); el_val_t route_load_merge(el_val_t method, el_val_t path, el_val_t body); el_val_t route_emit_ise(el_val_t method, el_val_t path, el_val_t body); @@ -271,6 +272,17 @@ el_val_t route_health(el_val_t method, el_val_t path, el_val_t body) { return 0; } +el_val_t route_embed_backfill(el_val_t method, el_val_t path, el_val_t body) { + el_val_t n = query_int(path, EL_STR("n"), 32); + el_val_t result = engram_embed_backfill(n); + el_val_t done = json_get_float(result, EL_STR("embedded")); + if (done > el_from_float(0.0)) { + el_val_t saved = persist_canonical(); + } + return result; + return 0; +} + el_val_t route_sync(el_val_t method, el_val_t path, el_val_t body) { el_val_t dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); el_val_t dir = ({ el_val_t _if_result_20 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_20 = (EL_STR("/tmp/engram")); } else { _if_result_20 = (dir_raw); } _if_result_20; }); @@ -432,6 +444,9 @@ el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) { if (str_eq(method, EL_STR("GET")) && str_eq(clean, EL_STR("/api/sync"))) { return route_sync(method, path, body); } + if (str_eq(clean, EL_STR("/api/embed-backfill"))) { + return route_embed_backfill(method, path, body); + } return el_str_concat(el_str_concat(EL_STR("{\"error\":\"not found\",\"path\":\""), clean), EL_STR("\"}")); return 0; } diff --git a/engram/src/server.el b/engram/src/server.el index 5e72136..6689ed8 100644 --- a/engram/src/server.el +++ b/engram/src/server.el @@ -246,6 +246,28 @@ fn route_health(method: String, path: String, body: String) -> String { "{\"status\":\"ok\",\"engine\":\"engram-runtime-native\"}" } +// route_embed_backfill — GET/POST /api/embed-backfill?n=48 +// +// (2026-07-25 self-review) The lazy embedding backfill runs only inside +// engram_activate, and nothing in production calls /api/activate on this +// store — the soul's curiosity loop activates its own in-process graph. +// After a restart from a snapshot without vectors, embedded_count stalled +// at 93/12175 and would never recover. This route lets the soul's +// heartbeat pump the backfill explicitly (48/min clears a 12k backlog in +// ~4h). Persists the canonical snapshot whenever new vectors were +// generated — the 2026-07-25 regression happened precisely because 3747 +// in-RAM embeddings were never snapshotted before a restart. Self- +// limiting: once coverage is full, embedded=0 and no save occurs. +fn route_embed_backfill(method: String, path: String, body: String) -> String { + let n: Int = query_int(path, "n", 32) + let result: String = engram_embed_backfill(n) + let done: Float = json_get_float(result, "embedded") + if done > 0.0 { + let saved: Int = persist_canonical() + } + return result +} + // route_sync — return a snapshot of non-ISE/non-Working nodes for the soul daemon // to merge into its in-process graph via engram_load_merge. // @@ -495,6 +517,11 @@ fn handle_request(method: String, path: String, body: String) -> String { return route_sync(method, path, body) } + // Embedding backfill — pumped by the soul heartbeat (2026-07-25) + if str_eq(clean, "/api/embed-backfill") { + return route_embed_backfill(method, path, body) + } + "{\"error\":\"not found\",\"path\":\"" + clean + "\"}" } diff --git a/lang/releases/v1.0.0-20260501/el_runtime.c b/lang/releases/v1.0.0-20260501/el_runtime.c index cf31d3c..04f0948 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.c +++ b/lang/releases/v1.0.0-20260501/el_runtime.c @@ -5680,6 +5680,24 @@ void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, #define ENGRAM_BLL_TAU (-3.0) #define ENGRAM_BLL_S 0.4 +/* Short-term inhibition-of-return (2026-07-25 self-review). + * Lebiere & Best 2009 ("Balancing Long-Term Reinforcement and Short-Term + * Inhibition", CogSci): subtract ln(1 + (t_n/t_s)^-d_s) from activation, + * where t_n = time since the MOST RECENT access. With their best-fit + * d_s = 1.0 the exp of the subtraction reduces to the clean multiplier + * m(t_n) = t_n / (t_n + t_s) + * applied to raw_wm in Pass 2. Immediately after a promotion the node's + * score is crushed (m → 0), then self-heals as a power law — producing an + * emergent round-robin over WM candidates instead of winner-take-all. + * This replaces the non-decaying suppression_count as the damping + * mechanism (that counter never entered the score at all — it only ever + * pushed nodes TOWARD surfacing via breakthrough; kept for that role). + * t_s = 4× the ~30 s curiosity-scan interval per the paper's guidance + * (t_s ≈ peak re-occurrence lag). A node promoted every scan holds + * m ≈ 0.2 until it loses its slot; after ~2 min unretrieved, m ≥ 0.5. + * Source: act-r.psy.cmu.edu/.../894Cogsci09-Lebiere-Best.pdf */ +#define ENGRAM_STI_TS 120.0 + /* qsort comparator — descending double, used by WM cap enforcement. */ static int engram_cmp_double_desc(const void* a, const void* b) { double da = *(const double*)a; @@ -7830,6 +7848,23 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { raw_wm += ENGRAM_EMBED_WM_WEIGHT * (cosq[i] - ENGRAM_EMBED_S0) / (1.0 - ENGRAM_EMBED_S0); } + /* Short-term inhibition-of-return (2026-07-25, Lebiere-Best): + * damp by t_n/(t_n + t_s) where t_n = seconds since the most + * recent recorded access (WM promotion / strengthen). Applied + * after the cosine term so the WHOLE score rotates — a node that + * just held a WM slot yields it even to semantically weaker + * competitors, and recovers as t_n grows. access_ts is recorded + * at promotion, so persistent WM residents self-inhibit. Nodes + * with no access history (never promoted) are uninhibited. + * Layer-0 override in Pass 3 still floors safety nodes. */ + if (n->access_filled > 0) { + int32_t sti_last = (n->access_head + ENGRAM_BLL_K - 1) + % ENGRAM_BLL_K; + double sti_tn = (double)(now_ms - n->access_ts[sti_last]) + / 1000.0; + if (sti_tn < 0.1) sti_tn = 0.1; + raw_wm *= sti_tn / (sti_tn + ENGRAM_STI_TS); + } /* Threshold gate: must exceed per-type threshold to enter working * memory. Type threshold replaces the old flat 0.2 filter. */ if (raw_wm >= type_threshold) { @@ -9080,6 +9115,43 @@ el_val_t engram_cosine_sim(el_val_t id_a, el_val_t id_b) { return el_from_float(eg_cosine(a->emb, b->emb, a->emb_dim)); } +/* engram_embed_backfill — explicitly drive the lazy embedding backfill. + * (2026-07-25 self-review.) The per-activate backfill (8 nodes/call) only + * runs inside engram_activate, and on the authoritative HTTP store nothing + * calls /api/activate in production — so embedded_count stalled at ~93 of + * 12k after a restart from a snapshot without vectors. This entry point + * lets the server expose a route the soul's heartbeat can pump. Embeds up + * to `count` eligible un-embedded nodes (clamped to [1, 64]), newest + * first, respecting the same eligibility rules and circuit breaker as the + * lazy path. Returns JSON: {"embedded":k,"embedded_count":m,"node_count":c}. + * k = 0 with the breaker open or embedder down — never blocks past the + * per-fetch timeout chain. */ +el_val_t engram_embed_backfill(el_val_t count) { + EngramStore* g = engram_get(); + int64_t want = (int64_t)EL_INT(count); + if (want < 1) want = 1; + if (want > 64) want = 64; + int64_t done = 0; + for (int64_t i = g->node_count - 1; i >= 0 && done < want; i--) { + EngramNode* n = &g->nodes[i]; + if (n->emb || !eg_embed_eligible(n)) continue; + int32_t d = 0; + float* v = eg_embed_fetch(n->content, &d); + if (!v) break; /* embedder down / breaker open — stop this call */ + n->emb = v; n->emb_dim = d; + done++; + } + int64_t total = 0; + for (int64_t i = 0; i < g->node_count; i++) { + if (g->nodes[i].emb) total++; + } + char buf[160]; + snprintf(buf, sizeof(buf), + "{\"embedded\":%lld,\"embedded_count\":%lld,\"node_count\":%lld}", + (long long)done, (long long)total, (long long)g->node_count); + return el_wrap_str(el_strdup(buf)); +} + /* engram_list_layers_json — serialized counterpart of engram_list_layers. * Returns a JSON array, sorted by activation_priority ascending. */ el_val_t engram_list_layers_json(void) { diff --git a/lang/releases/v1.0.0-20260501/el_runtime.h b/lang/releases/v1.0.0-20260501/el_runtime.h index 87ac86b..a35d1ae 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.h +++ b/lang/releases/v1.0.0-20260501/el_runtime.h @@ -618,6 +618,7 @@ el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t d el_val_t engram_activate_json(el_val_t query, el_val_t depth); el_val_t engram_stats_json(void); el_val_t engram_cosine_sim(el_val_t id_a, el_val_t id_b); +el_val_t engram_embed_backfill(el_val_t count); el_val_t engram_list_layers_json(void); /* Working memory introspection — count, mean weight, and top-N snapshot. * Ported from el-compiler/runtime on 2026-06-30 self-review. */ From 11dc138a9370acf5791e59561e08e5ffd534c51a Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Sun, 26 Jul 2026 08:40:49 -0500 Subject: [PATCH 03/26] self-review 2026-07-26: fix WM frozen-anchor fixation, strengthen self-inhibition, load-path emb leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Carry-over branch: occupancy inhibition m = t_c/(t_c+t_hold), t_c=3600s (ENGRAM_CARRY_TC). An unreached incumbent held its wm_anchor verbatim (keep~1.0 for BLL inflated in the pre-07-25 era) — observed 23h at WM top while every reached node rotated at the 0.10 breakthrough floor. STI only runs in the reached branch; inhibition must key on occupancy, not retrieval recency (Morita 2021 / Lebiere & Best 2009). - engram_strengthen: drop the 07-22 BLL access record — the 07-25 STI multiplier reads the same ring, so novelty reinforcement self-inhibited its target for ~2 minutes. - engram_load reset: free n->emb (~3KB/embedded node leaked per reload). - engram_wm_top_json: emit id — its absence made the heartbeat's wm_top0_streak compare ""=="" and measure uptime, not fixation. --- lang/releases/v1.0.0-20260501/el_runtime.c | 55 ++++++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/lang/releases/v1.0.0-20260501/el_runtime.c b/lang/releases/v1.0.0-20260501/el_runtime.c index 04f0948..1e92ea8 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.c +++ b/lang/releases/v1.0.0-20260501/el_runtime.c @@ -5698,6 +5698,28 @@ void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, * Source: act-r.psy.cmu.edu/.../894Cogsci09-Lebiere-Best.pdf */ #define ENGRAM_STI_TS 120.0 +/* Carry-over occupancy inhibition (2026-07-26 self-review). + * The STI multiplier above only runs in the REACHED branch of Pass 2. + * A node carried over WITHOUT being reached (Pass 4½ below) kept + * w = wm_anchor * keep, and for a node whose base-level was inflated + * during the pre-07-25 unconditional-reinforcement era, keep ≈ 1.0 for + * days — the anchor weight is re-emitted verbatim forever. Observed + * live: wm_top0_streak = 1407 heartbeats (~23 h), one node frozen at + * its anchor 0.589 while every reached candidate rotated at the 0.10 + * breakthrough floor. Deterministic argmax over a quasi-static score + * fixates regardless of any inhibition applied only to the reached set + * (Morita et al. 2021, citing Lebiere & Best 2009). + * Fix: key inhibition on OCCUPANCY, not retrieval recency — multiply + * the carried weight by the same d_s=1 closed form over hold time + * m(t_h) = t_c / (t_c + t_h), t_h = seconds since last_activated + * (carry-over nodes are deliberately never reinforced, so + * last_activated marks when the node last EARNED its slot). Power-law + * self-healing: a node re-reached by any future activation is + * re-scored fresh in Pass 2 and re-anchors. t_c = 3600 s → a carried + * node keeps ~92% after 5 min, 50% after 1 h, ~4% after 23 h. Unlike + * m(t_n), this cannot saturate to no-op while the node camps. */ +#define ENGRAM_CARRY_TC 3600.0 + /* qsort comparator — descending double, used by WM cap enforcement. */ static int engram_cmp_double_desc(const void* a, const void* b) { double da = *(const double*)a; @@ -6895,8 +6917,16 @@ void engram_strengthen(el_val_t node_id) { n->activation_count++; n->last_activated = engram_now_ms(); n->updated_at = n->last_activated; - /* Explicit strengthen is a presentation too (2026-07-22 self-review). */ - engram_bll_record_access(n, n->last_activated); + /* 2026-07-26 self-review: REMOVED the BLL access record added on + * 2026-07-22 ("explicit strengthen is a presentation too"). The + * 2026-07-25 STI multiplier reads the same access ring — so an + * explicit strengthen crushed the strengthened node's promotion + * score by ×t_n/(t_n+120) for the next ~2 minutes. The awareness + * loop strengthens exactly when a node NEWLY reaches WM top + * (novelty gating); recording an access here made that + * reinforcement self-defeating. Salience/activation_count bumps + * above carry the reinforcement; the access ring stays reserved + * for genuine retrieval events (promotions in engram_activate). */ } void engram_forget(el_val_t node_id) { @@ -7989,7 +8019,14 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { } else { double keep = 1.0 / (1.0 + exp(-(B - ENGRAM_BLL_TAU) / ENGRAM_BLL_S)); - double w = anchor * keep; + /* Occupancy inhibition (2026-07-26): decay the carried + * weight with hold time so an unreached incumbent cannot + * hold its anchor verbatim indefinitely. See + * ENGRAM_CARRY_TC comment for derivation. */ + double hold_s = (double)(now_ms - cn->last_activated) / 1000.0; + if (hold_s < 0.0) hold_s = 0.0; + double occ = ENGRAM_CARRY_TC / (ENGRAM_CARRY_TC + hold_s); + double w = anchor * keep * occ; cn->working_memory_weight = (w < 0.01) ? 0.0 : w; } } else { @@ -8361,6 +8398,10 @@ el_val_t engram_load(el_val_t path) { free(g->nodes[i].id); free(g->nodes[i].content); free(g->nodes[i].node_type); free(g->nodes[i].label); free(g->nodes[i].tier); free(g->nodes[i].tags); free(g->nodes[i].metadata); + /* 2026-07-26 self-review: emb was the one heap field not freed + * here — ~3 KB leaked per embedded node per reload (~11 MB per + * reload at 3.7k embedded). forget/prune already free it. */ + free(g->nodes[i].emb); g->nodes[i].emb = NULL; g->nodes[i].emb_dim = 0; } g->node_count = 0; for (int64_t i = 0; i < g->edge_count; i++) { @@ -9065,7 +9106,13 @@ el_val_t engram_wm_top_json(el_val_t n_v) { EngramNode* n = &g->nodes[idx[k]]; if (k > 0) jb_putc(&b, ','); jb_putc(&b, '{'); - jb_puts(&b, "\"label\":"); + /* 2026-07-26 self-review: id was never emitted here, so the + * awareness heartbeat's wm_top0_streak compared ""=="" and + * incremented unconditionally — the streak metric measured + * uptime, not fixation. */ + jb_puts(&b, "\"id\":"); + jb_emit_escaped(&b, n->id ? n->id : ""); + jb_puts(&b, ",\"label\":"); jb_emit_escaped(&b, n->label ? n->label : ""); jb_puts(&b, ",\"node_type\":"); jb_emit_escaped(&b, n->node_type ? n->node_type : ""); From 9f362c90e593d49627a97c6564691d4df8efee5f Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Mon, 27 Jul 2026 08:38:48 -0500 Subject: [PATCH 04/26] self-review 2026-07-27: query-aware propagation gating + activation observability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Gate each spreading-activation increment by target-node query similarity (arXiv:2606.30133): soft gate FLOOR+(1-FLOOR)*clip(cos), FLOOR=0.25, for embedded targets; ungated for unembedded; disabled when embedder is down. Prior spreading was query-blind — hubs relayed activation into branches unrelated to the query. - Stats: add embed_eligible_count so embedding coverage is measured against the true denominator (ISE/Tag/short nodes can never embed). Today's review misread 3753/12693 as a 30% coverage gap; eligible coverage is 100%. - Observability: per-call wm_evicted + breakthroughs counters and embed circuit-breaker state exposed via engram_act_stats_json() — the three highest-value previously-invisible executive-filter transitions. --- lang/releases/v1.0.0-20260501/el_runtime.c | 84 ++++++++++++++++++++-- lang/releases/v1.0.0-20260501/el_runtime.h | 1 + 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/lang/releases/v1.0.0-20260501/el_runtime.c b/lang/releases/v1.0.0-20260501/el_runtime.c index 1e92ea8..f1e62fd 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.c +++ b/lang/releases/v1.0.0-20260501/el_runtime.c @@ -5954,6 +5954,12 @@ static void engram_bll_parse_access(EngramNode* nn, const char* s) { #define ENGRAM_EMBED_SEED_K 8 #define ENGRAM_EMBED_SEED_MIN 0.60 #define ENGRAM_EMBED_BACKFILL_PER_CALL 8 +/* ENGRAM_QGATE_FLOOR: minimum propagation multiplier for an EMBEDDED target + * node with zero/negative query similarity. Query-aware spreading gate + * (arXiv:2606.30133) adapted for partial embedding coverage — see the + * propagation loop in engram_activate. 0.25 damps semantically unrelated + * branches ~4x without severing them. Unembedded targets are ungated. */ +#define ENGRAM_QGATE_FLOOR 0.25 #define ENGRAM_EMBED_MAX_CHARS 2000 #define ENGRAM_EMBED_TIMEOUT_MS 4000L #define ENGRAM_EMBED_BREAKER_LIMIT 3 @@ -5962,6 +5968,15 @@ static void engram_bll_parse_access(EngramNode* nn, const char* s) { static int _eg_embed_consec_fail = 0; static int64_t _eg_embed_breaker_until = 0; +/* ── Activation observability counters (2026-07-27 self-review) ────────────── + * The executive-filter pathologies this system has repeatedly debugged by + * inference (WM flooded with breakthrough-floor nodes, silent cap evictions, + * embedder wedged behind the breaker) were all invisible: no ISE, no stats + * field. These per-call counters record what the LAST engram_activate did; + * engram_act_stats_json() exposes them so the soul heartbeat can emit them. */ +static int64_t _eg_act_breakthroughs = 0; /* forced promotions at the floor */ +static int64_t _eg_act_wm_evicted = 0; /* Pass 4 over-cap evictions */ + static int64_t engram_now_ms(void); /* defined in the store section below */ static const char* eg_embed_url(void) { @@ -7562,6 +7577,10 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { int64_t now_ms = engram_now_ms(); + /* Reset per-call observability counters (2026-07-27). */ + _eg_act_breakthroughs = 0; + _eg_act_wm_evicted = 0; + /* ── Embedding backfill + query embedding (2026-07-24, bl-b2d1c944) ── * Backfill: embed up to N un-embedded eligible nodes per call, newest * first (append order ≈ creation order), so fresh content is semantic- @@ -7780,8 +7799,31 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { double tbonus = engram_temporal_proximity_bonus(on->created_at, seed_epoch); double tdecay = engram_temporal_decay(on, now_ms); double dampen = engram_activation_dampen(on); + /* ── Query-aware propagation gate (2026-07-27 self-review) ── + * Prior behavior was "query-blind" spreading: the query chose + * the seeds, but propagation depended only on graph structure, + * so high-degree hubs relayed activation into branches with no + * semantic relation to the query. Per arXiv:2606.30133, gating + * each increment by the TARGET node's query similarity + * (sigma(v) = max(cos(e_v, e_q), 0)) prunes low-information + * branches at every hop (+3.6..+7.4 F1 over uniform spreading, + * 1.5-4.9x faster via a shrinking working set). + * + * Adaptation for partial embedding coverage: the paper skips + * unembedded targets outright, but only eligible non-ISE/Tag + * nodes carry embeddings here — a hard gate would sever purely + * lexical/structural pathways. So: embedded targets get a soft + * gate FLOOR + (1-FLOOR)*clip(cos) (dissimilar nodes damped + * ~4x, never killed); unembedded targets pass ungated (no + * information, no penalty); cosq == NULL (embedder down) means + * no gating at all — same graceful degradation as seeding. */ + double qgate = 1.0; + if (cosq && cosq[oi] > -1.5) { + double c = cosq[oi] > 0.0 ? cosq[oi] : 0.0; + qgate = ENGRAM_QGATE_FLOOR + (1.0 - ENGRAM_QGATE_FLOOR) * c; + } double new_act = f.act * e->weight * SPREAD_DECAY * (1.0 + tbonus) - * tdecay * dampen; + * tdecay * dampen * qgate; /* Firing threshold per classic spreading-activation: sub-threshold * activation neither updates the target nor enqueues it, so weak * signals die out instead of flooding the whole graph with tiny @@ -7907,6 +7949,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { if (n->suppression_count >= ENGRAM_SUPPRESSION_BREAKTHROUGH) { wm_weights[i] = ENGRAM_BREAKTHROUGH_WEIGHT; n->suppression_count = 0; + _eg_act_breakthroughs++; } else { wm_weights[i] = 0.0; } @@ -7975,6 +8018,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { continue; /* fills a slot */ } wm_weights[i] = 0.0; /* over cap: evict */ + _eg_act_wm_evicted++; } } /* If malloc failed, skip cap — WM unbounded this call, no corruption. */ @@ -9132,17 +9176,45 @@ el_val_t engram_stats_json(void) { EngramStore* g = engram_get(); /* embedded_count: how far the lazy backfill has progressed. The single * observable that tells the daily self-review whether semantic - * activation is actually accumulating coverage. (2026-07-24) */ - int64_t embedded = 0; + * activation is actually accumulating coverage. (2026-07-24) + * + * embed_eligible_count (2026-07-27): embedded_count alone misleads — + * ~70%+ of the store is ISE/Tag/short-content nodes that are permanently + * ineligible for embedding, so raw embedded/node_count reads as "~30% + * coverage, something is broken" when eligible coverage may be complete. + * This exact misdiagnosis happened in today's self-review. Report the + * true denominator so coverage = embedded_count / embed_eligible_count. */ + int64_t embedded = 0, eligible = 0; for (int64_t i = 0; i < g->node_count; i++) { if (g->nodes[i].emb) embedded++; + if (eg_embed_eligible(&g->nodes[i])) eligible++; } - char buf[192]; + char buf[256]; snprintf(buf, sizeof(buf), "{\"node_count\":%lld,\"edge_count\":%lld,\"layer_count\":%zu," - "\"embedded_count\":%lld}", + "\"embedded_count\":%lld,\"embed_eligible_count\":%lld}", (long long)g->node_count, (long long)g->edge_count, g->layer_count, - (long long)embedded); + (long long)embedded, (long long)eligible); + return el_wrap_str(el_strdup(buf)); +} + +/* engram_act_stats_json — per-call activation observability + embedder + * breaker state. (2026-07-27 self-review.) wm_evicted/breakthroughs describe + * the LAST engram_activate call on this store; embed_breaker_open=1 means + * eg_embed_fetch is currently refusing calls (semantic activation silently + * degraded to lexical until the cooldown expires). The soul heartbeat folds + * this into its ISE so the pathologies are diagnosable from telemetry + * instead of inferred from wm_avg_weight hovering at the floor. */ +el_val_t engram_act_stats_json(void) { + int64_t now = engram_now_ms(); + int breaker_open = (now < _eg_embed_breaker_until) ? 1 : 0; + char buf[192]; + snprintf(buf, sizeof(buf), + "{\"wm_evicted\":%lld,\"breakthroughs\":%lld," + "\"embed_breaker_open\":%d,\"embed_consec_fail\":%d}", + (long long)_eg_act_wm_evicted, + (long long)_eg_act_breakthroughs, + breaker_open, _eg_embed_consec_fail); return el_wrap_str(el_strdup(buf)); } diff --git a/lang/releases/v1.0.0-20260501/el_runtime.h b/lang/releases/v1.0.0-20260501/el_runtime.h index a35d1ae..de43bd2 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.h +++ b/lang/releases/v1.0.0-20260501/el_runtime.h @@ -617,6 +617,7 @@ el_val_t engram_scan_nodes_by_type_json(el_val_t node_type, el_val_t limit, el_ el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction); el_val_t engram_activate_json(el_val_t query, el_val_t depth); el_val_t engram_stats_json(void); +el_val_t engram_act_stats_json(void); el_val_t engram_cosine_sim(el_val_t id_a, el_val_t id_b); el_val_t engram_embed_backfill(el_val_t count); el_val_t engram_list_layers_json(void); From 6ebe3d0d666431bee54ddc45bf580fe61875d7f7 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Tue, 28 Jul 2026 08:37:34 -0500 Subject: [PATCH 05/26] self-review 2026-07-28: feed importance into WM scoring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit n->importance was stored, serialized, and clamped at creation but never read by any activation path — a curated importance=1.0 node competed identically with a default note. Multiply raw_wm by (0.5 + importance): default 0.5 nodes are unchanged (x1.0), critical x1.5, low x0.6; importance<=0 from legacy snapshots stays neutral. Verified activation and WM promotion unchanged for default-importance candidates. --- lang/releases/v1.0.0-20260501/el_runtime.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lang/releases/v1.0.0-20260501/el_runtime.c b/lang/releases/v1.0.0-20260501/el_runtime.c index f1e62fd..149fa4d 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.c +++ b/lang/releases/v1.0.0-20260501/el_runtime.c @@ -7903,8 +7903,18 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { double type_threshold = engram_type_threshold(n->node_type, n->tier); /* Goal bias weights the node's relevance to current intent. */ double bias = engram_goal_bias(n, q); - /* Raw working memory score. */ - double raw_wm = best_bg[i] * bias * n->confidence; + /* Raw working memory score. + * Importance factor (2026-07-28 self-review): n->importance was + * stored, serialized, and clamped at creation (default 0.5) but + * never read by any scoring path — a curated importance=1.0 node + * competed identically with a throwaway note at equal activation. + * Map it to a gentle multiplier centered on the 0.5 default: + * impf = 0.5 + importance → default nodes unchanged (×1.0), + * critical (1.0) ×1.5, low (0.1) ×0.6. Nodes loaded from legacy + * snapshots with importance<=0 stay neutral rather than being + * silently suppressed. */ + double impf = (n->importance > 0.0) ? (0.5 + n->importance) : 1.0; + double raw_wm = best_bg[i] * bias * n->confidence * impf; /* Apply inhibitory suppression. Full inhibition → scale by factor. */ double inh = inhibition[i]; if (inh > 1.0) inh = 1.0; From 7f665295103a3b807e999c48ba49ac58e2c0cbc5 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Thu, 30 Jul 2026 08:45:15 -0500 Subject: [PATCH 06/26] self-review 2026-07-30: WM absolute admission floor + anchor coherence + centroid new-entrant gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Working memory was pinned saturated (24/24, wm_saturated:1 on every heartbeat) because every cap path only trimmed the population down TO the cap — rank-based eviction guarantees a full WM whenever >=24 nodes hold any weight, so sub-cap fill was unreachable and the saturation flag carried no information. - ENGRAM_WM_FLOOR 0.05: absolute admission bar (Soar WM forgetting, Derbinsky & Laird ICCM 2012 — removal by absolute threshold, not rank) applied in Pass 4, carry-over, Pass 5, and load-cap. Fill can now drain below 24 during quiet periods. - Zero wm_anchor at every eviction site: stale anchors on evicted nodes were a latent resurrection bug. - Context centroid folds only NEW WM entrants: incumbents re-promoted every scan no longer re-entrench the centroid each call, breaking the WM->centroid->e_eff->re-selection positive feedback (fixation driver behind the wm_top0_streak=1407 incident). Verified live: wm_active 3->22->23, wm_saturated:0 post-restart. --- lang/releases/v1.0.0-20260501/el_runtime.c | 221 ++++++++++++++++++++- 1 file changed, 212 insertions(+), 9 deletions(-) diff --git a/lang/releases/v1.0.0-20260501/el_runtime.c b/lang/releases/v1.0.0-20260501/el_runtime.c index 149fa4d..5d6ad3f 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.c +++ b/lang/releases/v1.0.0-20260501/el_runtime.c @@ -5642,6 +5642,22 @@ void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, * context while preventing flooding. Enforced in Pass 4 (per-call) and Pass 5 * (global across prior-promoted nodes). */ #define ENGRAM_WM_CAP 24 +/* ENGRAM_WM_FLOOR: absolute admission floor for a working-memory slot + * (2026-07-30 self-review). Before this, Pass 4/Pass 5/load-cap only ever + * trimmed the WM population down TO the cap and never below it — rank-based + * eviction guarantees the cap is filled whenever ≥24 nodes hold any nonzero + * weight, so wm_active was pinned at 24/24 and wm_saturated:1 was + * definitionally true on every heartbeat (carried no information). Soar's WM + * forgetting (Derbinsky & Laird, ICCM 2012) removes elements by comparing + * activation to an ABSOLUTE threshold θ, independent of how many other + * elements exist — fill below capacity is a reachable, meaningful state + * ("low cognitive load"). This floor is the weight-domain analogue of that θ: + * any slot whose weight sinks below it is dropped even when WM is under cap. + * Value 0.05 = the lowest per-type promotion threshold (Safety/DharmaSelf in + * engram_type_threshold) and the existing boot-time launder floor, and sits + * below ENGRAM_BREAKTHROUGH_WEIGHT (0.10) so intrusive-thought breakthroughs + * still surface. Applied: Pass 4, carry-over, Pass 5, load-cap. */ +#define ENGRAM_WM_FLOOR 0.05 #define ENGRAM_INHIBITION_FACTOR 0.1 /* ── ACT-R / Petrov hybrid base-level learning (2026-07-22 self-review) ────── @@ -5965,6 +5981,40 @@ static void engram_bll_parse_access(EngramNode* nn, const char* s) { #define ENGRAM_EMBED_BREAKER_LIMIT 3 #define ENGRAM_EMBED_BREAKER_COOLDOWN_MS 300000 +/* ── Context centroid (2026-07-29 self-review) ─────────────────────────────── + * Closes the last gap from the 2026-07-21 decay/embedding brief: cosine was + * computed against the per-call query embedding ONLY, so every curiosity scan + * was semantically memoryless — the 4 rotating seed phrases fully determined + * what ignited, with zero continuity from what the system actually touched. + * + * Mechanism (brief spec): a running EMA centroid over touch embeddings, + * c ← normalize(μ·c + (1−μ)·e_touch), μ = ENGRAM_CTX_MU + * where a "touch" is (a) the query embedding each activate call and (b) the + * embeddings of up to ENGRAM_CTX_TOUCH_MAX top WM-promoted survivors of that + * call — promotion is the retrieval event (same rule as BLL reinforcement). + * + * Feedback-loop guard: scoring does NOT use the raw centroid. The lit + * failure mode of centroid memories (EMA of your own outputs → runaway + * attractor; cf. the wm_top0_streak=1407 freeze this store already hit) is + * bounded by scoring against a query-dominant blend: + * e_eff = normalize(α·e_q + (1−α)·c), α = ENGRAM_CTX_QALPHA + * so the exogenous rotating seeds always contribute the majority of the + * scoring direction; the centroid is a context tint, not the signal. + * + * Observability: _eg_act_ctx_cos = cos(e_q, c) BEFORE the query is blended + * in. ~1.0 → centroid aligned with current query; low → context and query + * have diverged (expected at domain-rotation boundaries); -2.0 → no centroid + * yet / embedder down. Exposed via engram_act_stats_json → heartbeat ISE so + * drift is diagnosable from telemetry. In-memory only: context is + * short-term by definition, a restart legitimately starts cold. */ +#define ENGRAM_CTX_MU 0.90 +#define ENGRAM_CTX_QALPHA 0.65 +#define ENGRAM_CTX_TOUCH_MAX 8 + +static float* _eg_ctx_c = NULL; +static int32_t _eg_ctx_dim = 0; +static double _eg_act_ctx_cos = -2.0; + static int _eg_embed_consec_fail = 0; static int64_t _eg_embed_breaker_until = 0; @@ -6003,6 +6053,38 @@ static double eg_cosine(const float* a, const float* b, int32_t dim) { return dot / (sqrt(na) * sqrt(nb)); } +/* eg_ctx_blend — fold one touch embedding into the context centroid: + * c ← normalize(μ·c + (1−μ)·e). Initializes the centroid (normalized copy) + * on first touch or dim change; silently skips degenerate vectors. */ +static void eg_ctx_blend(const float* e, int32_t dim) { + if (!e || dim <= 0) return; + double ne = 0.0; + for (int32_t i = 0; i < dim; i++) ne += (double)e[i] * (double)e[i]; + if (ne <= 0.0) return; + ne = sqrt(ne); + if (!_eg_ctx_c || _eg_ctx_dim != dim) { + float* c = malloc((size_t)dim * sizeof(float)); + if (!c) return; + for (int32_t i = 0; i < dim; i++) c[i] = (float)((double)e[i] / ne); + free(_eg_ctx_c); + _eg_ctx_c = c; + _eg_ctx_dim = dim; + return; + } + double nc = 0.0; + for (int32_t i = 0; i < dim; i++) { + double v = ENGRAM_CTX_MU * (double)_eg_ctx_c[i] + + (1.0 - ENGRAM_CTX_MU) * ((double)e[i] / ne); + _eg_ctx_c[i] = (float)v; + nc += v * v; + } + if (nc > 0.0) { + nc = sqrt(nc); + for (int32_t i = 0; i < dim; i++) + _eg_ctx_c[i] = (float)((double)_eg_ctx_c[i] / nc); + } +} + /* Fetch an embedding from Ollama. Returns malloc'd float[dim] or NULL. * Truncates input to ENGRAM_EMBED_MAX_CHARS and JSON-escapes it. Honors the * circuit breaker; a NULL return is always safe to ignore (fail-soft). */ @@ -7580,6 +7662,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { /* Reset per-call observability counters (2026-07-27). */ _eg_act_breakthroughs = 0; _eg_act_wm_evicted = 0; + _eg_act_ctx_cos = -2.0; /* ── Embedding backfill + query embedding (2026-07-24, bl-b2d1c944) ── * Backfill: embed up to N un-embedded eligible nodes per call, newest @@ -7621,21 +7704,52 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { q_emb = v; q_dim = d; } } - /* Per-node cosine vs the query, computed once, consumed twice: semantic + /* ── Context centroid fold-in (2026-07-29) ────────────────────────── + * Record drift BEFORE blending (cos of the query against yesterday's + * context), then fold the query in as a touch, then build the + * query-dominant effective scoring vector. See the ENGRAM_CTX_* block + * for the design and the feedback-loop guard rationale. */ + float* e_eff = NULL; + if (q_emb) { + if (_eg_ctx_c && _eg_ctx_dim == q_dim) + _eg_act_ctx_cos = eg_cosine(q_emb, _eg_ctx_c, q_dim); + eg_ctx_blend(q_emb, q_dim); + if (_eg_ctx_c && _eg_ctx_dim == q_dim) { + e_eff = malloc((size_t)q_dim * sizeof(float)); + if (e_eff) { + double nq = 0.0; + for (int32_t i = 0; i < q_dim; i++) + nq += (double)q_emb[i] * (double)q_emb[i]; + nq = (nq > 0.0) ? sqrt(nq) : 1.0; + double nn = 0.0; + for (int32_t i = 0; i < q_dim; i++) { + double v = ENGRAM_CTX_QALPHA * ((double)q_emb[i] / nq) + + (1.0 - ENGRAM_CTX_QALPHA) * (double)_eg_ctx_c[i]; + e_eff[i] = (float)v; + nn += v * v; + } + if (nn <= 0.0) { free(e_eff); e_eff = NULL; } + } + } + } + /* Per-node cosine vs the effective query (query ⊕ context centroid; + * plain query on cold start), computed once, consumed twice: semantic * seeding below and the additive WM term in Pass 2 (use similarity * twice, coherently — HippoRAG). cosq stays NULL when the embedder is * unavailable; every consumer degrades to pure lexical behavior. */ double* cosq = NULL; if (q_emb) { + const float* qv = e_eff ? e_eff : q_emb; cosq = calloc((size_t)g->node_count, sizeof(double)); if (cosq) { for (int64_t i = 0; i < g->node_count; i++) { EngramNode* n = &g->nodes[i]; cosq[i] = (n->emb && n->emb_dim == q_dim) - ? eg_cosine(n->emb, q_emb, q_dim) : -2.0; + ? eg_cosine(n->emb, qv, q_dim) : -2.0; } } } + free(e_eff); e_eff = NULL; /* only needed to fill cosq */ /* Per-node layer-1 tracking. */ double* best_bg = calloc((size_t)g->node_count, sizeof(double)); @@ -7996,6 +8110,16 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { * becomes useless. (Ported from 2026-06-26 self-review branch; observed * 525 promoted for "knowledge", 524 at breakthrough floor 0.25, 1 natural.) */ { + /* Absolute admission floor (2026-07-30): drop sub-floor candidates + * BEFORE rank-trimming, so the cap is filled only by nodes that clear + * an absolute bar — fill below ENGRAM_WM_CAP becomes reachable and + * wm_saturated becomes an informative signal. See ENGRAM_WM_FLOOR. */ + for (int64_t i = 0; i < g->node_count; i++) { + if (wm_weights[i] > 0.0 && wm_weights[i] < ENGRAM_WM_FLOOR) { + wm_weights[i] = 0.0; + _eg_act_wm_evicted++; + } + } int64_t cap_count = 0; for (int64_t i = 0; i < g->node_count; i++) { if (wm_weights[i] > 0.0) cap_count++; @@ -8035,6 +8159,19 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { } } + /* Pre-persist residency snapshot (2026-07-30): record which nodes held a + * WM slot BEFORE this call's results are written back. Used below to fold + * only NEW WM entrants into the context centroid — an incumbent that gets + * re-promoted every scan no longer re-entrenches the centroid each time, + * which was the remaining positive-feedback path in the WM→centroid→ + * e_eff→re-selection loop (fixation driver; cf. wm_top0_streak=1407 + * incident). NULL on OOM → fold falls back to previous behavior. */ + unsigned char* was_wm = malloc((size_t)g->node_count); + if (was_wm) { + for (int64_t i = 0; i < g->node_count; i++) + was_wm[i] = (g->nodes[i].working_memory_weight > 0.0) ? 1 : 0; + } + /* Persist working_memory_weight (post Pass 4) to node store. * * Conversational thread continuity (ENGRAM_WM_DECAY): @@ -8070,6 +8207,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { double B = engram_bll_base_level(cn, now_ms); if (B < ENGRAM_BLL_TAU) { cn->working_memory_weight = 0.0; + cn->wm_anchor = 0.0; /* keep anchor coherent with eviction */ } else { double keep = 1.0 / (1.0 + exp(-(B - ENGRAM_BLL_TAU) / ENGRAM_BLL_S)); @@ -8081,13 +8219,24 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { if (hold_s < 0.0) hold_s = 0.0; double occ = ENGRAM_CARRY_TC / (ENGRAM_CARRY_TC + hold_s); double w = anchor * keep * occ; - cn->working_memory_weight = (w < 0.01) ? 0.0 : w; + /* Evict floor raised 0.01 → ENGRAM_WM_FLOOR (2026-07-30): + * one consistent absolute bar across all WM entry/exit paths. */ + if (w < ENGRAM_WM_FLOOR) { + cn->working_memory_weight = 0.0; + cn->wm_anchor = 0.0; + } else { + cn->working_memory_weight = w; + } } } else { g->nodes[i].working_memory_weight = wm_weights[i]; /* Anchor the promotion weight: carry-over decay above computes - * from this fixed point rather than compounding per call. */ + * from this fixed point rather than compounding per call. + * Zero the anchor when the slot empties (2026-07-30): a stale + * anchor on an evicted node was a latent resurrection bug if the + * carry-over entry guard ever changes. */ if (wm_weights[i] > 0.0) g->nodes[i].wm_anchor = wm_weights[i]; + else g->nodes[i].wm_anchor = 0.0; } } @@ -8101,6 +8250,19 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { * activations outcompete older decayed ones. (Ported from 2026-06-26 * self-review branch.) */ { + /* Absolute admission floor, global pass (2026-07-30): see + * ENGRAM_WM_FLOOR. Sub-floor residents are dropped even when the + * global population is under cap — this is what lets wm_active + * drain below 24 during quiet periods. */ + for (int64_t i = 0; i < g->node_count; i++) { + EngramNode* fn = &g->nodes[i]; + if (fn->working_memory_weight > 0.0 && + fn->working_memory_weight < ENGRAM_WM_FLOOR) { + fn->working_memory_weight = 0.0; + fn->wm_anchor = 0.0; + _eg_act_wm_evicted++; + } + } int64_t global_wm_count = 0; for (int64_t i = 0; i < g->node_count; i++) { if (g->nodes[i].working_memory_weight > 0.0) global_wm_count++; @@ -8131,6 +8293,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { continue; /* fills a slot */ } n->working_memory_weight = 0.0; /* evict: over global cap */ + n->wm_anchor = 0.0; /* keep anchor coherent */ } } /* If malloc failed, skip — WM over cap this call, no data corruption. */ @@ -8174,7 +8337,8 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { int64_t rcount = 0; if (!results) { free(best_bg); free(best_hops); free(reached); free(seeds); - free(fr); free(inhibition); free(wm_weights); free(cosq); return out; + free(fr); free(inhibition); free(wm_weights); free(cosq); + free(was_wm); return out; } for (int64_t i = 0; i < g->node_count; i++) { if (!reached[i]) continue; @@ -8201,6 +8365,28 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { } results[j + 1] = key; } + /* ── Context centroid: fold in the touched nodes (2026-07-29) ─────── + * Results are sorted promoted-first by wm_weight desc, so the first + * ENGRAM_CTX_TOUCH_MAX embedded entries with wm > 0 are exactly the + * strongest WM survivors of THIS call — the same "promotion is the + * retrieval event" rule the BLL reinforcement pass uses. μ=0.9 EMA + * keeps any single scan's touches a minority contribution. */ + { + int touched = 0; + for (int64_t i = 0; i < rcount && touched < ENGRAM_CTX_TOUCH_MAX; i++) { + if (results[i].wm <= 0.0) break; /* promoted block exhausted */ + EngramNode* n = &g->nodes[results[i].idx]; + if (!n->emb || n->emb_dim <= 0) continue; + /* New-entrant gate (2026-07-30): skip nodes that already held a + * WM slot before this call — incumbents must not keep pulling + * the centroid toward themselves. Fresh topical shifts (new + * entrants + the query fold at call start) steer it instead. */ + if (was_wm && was_wm[results[i].idx]) continue; + eg_ctx_blend(n->emb, n->emb_dim); + touched++; + } + } + free(was_wm); for (int64_t i = 0; i < rcount; i++) { el_val_t entry = el_map_new(0); entry = el_map_set(entry, EL_STR(el_strdup("node")), @@ -8402,6 +8588,15 @@ static const char* eg_skip_ws(const char* p) { * the activation path. Same top-K-by-weight logic as engram_activate * Pass 5 (Cowan 2001: WM capacity is global). */ static void eg_enforce_wm_cap_on_load(EngramStore* g) { + /* Absolute admission floor (2026-07-30): see ENGRAM_WM_FLOOR. */ + for (int64_t i = 0; i < g->node_count; i++) { + EngramNode* fn = &g->nodes[i]; + if (fn->working_memory_weight > 0.0 && + fn->working_memory_weight < ENGRAM_WM_FLOOR) { + fn->working_memory_weight = 0.0; + fn->wm_anchor = 0.0; + } + } int64_t wm_count = 0; for (int64_t i = 0; i < g->node_count; i++) { if (g->nodes[i].working_memory_weight > 0.0) wm_count++; @@ -8428,6 +8623,7 @@ static void eg_enforce_wm_cap_on_load(EngramStore* g) { if (n->working_memory_weight > cutoff) continue; if (slots_at_cutoff > 0) { slots_at_cutoff--; continue; } n->working_memory_weight = 0.0; /* evict: over cap at load */ + n->wm_anchor = 0.0; /* keep anchor coherent */ } } @@ -8508,7 +8704,7 @@ el_val_t engram_load(el_val_t path) { * continuity across a restart while stale pinned weights decay * out over successive boots; sub-0.05 residue drops to zero. */ nn->working_memory_weight *= 0.5; - if (nn->working_memory_weight < 0.05) nn->working_memory_weight = 0.0; + if (nn->working_memory_weight < ENGRAM_WM_FLOOR) nn->working_memory_weight = 0.0; nn->suppression_count = (int32_t)eg_get_int_field(obj, "suppression_count"); /* layer_id defaults to ENGRAM_LAYER_DEFAULT (core-identity) * for snapshots that predate the layered schema. We can't @@ -9218,13 +9414,20 @@ el_val_t engram_stats_json(void) { el_val_t engram_act_stats_json(void) { int64_t now = engram_now_ms(); int breaker_open = (now < _eg_embed_breaker_until) ? 1 : 0; - char buf[192]; + char buf[256]; + /* ctx_cos (2026-07-29): cos(query, context centroid) at the LAST + * activate call, measured before the query was folded in. ~1.0 = + * context aligned with current query; low = divergence (expected at + * curiosity domain-rotation boundaries); -2.0 = no centroid yet or + * embedder down. The drift gauge for the context-centroid mechanism. */ snprintf(buf, sizeof(buf), "{\"wm_evicted\":%lld,\"breakthroughs\":%lld," - "\"embed_breaker_open\":%d,\"embed_consec_fail\":%d}", + "\"embed_breaker_open\":%d,\"embed_consec_fail\":%d," + "\"ctx_cos\":%.3f}", (long long)_eg_act_wm_evicted, (long long)_eg_act_breakthroughs, - breaker_open, _eg_embed_consec_fail); + breaker_open, _eg_embed_consec_fail, + _eg_act_ctx_cos); return el_wrap_str(el_strdup(buf)); } From 599073cb92bbd73efa0fbf07efc9e6150136b0ef Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Fri, 31 Jul 2026 08:41:33 -0500 Subject: [PATCH 07/26] self-review 2026-07-31: strip emb from consumer API JSON; cumulative eviction/breakthrough counters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every node object on consumer read routes (/api/nodes, /api/search, activation results, neighbors, compiled context) carried the full ~5.7KB emb vector — responses 10-50x oversized, blowing MCP token limits. engram_emit_node_json now takes include_emb; only engram_save passes 1, so persistence and the /api/sync//api/edges replication paths (which serve engram_save output) keep embeddings intact. _eg_act_wm_evicted/_eg_act_breakthroughs were reset at the top of every engram_activate, so act_stats reported only the last call and the 60s heartbeat missed nearly all events (curiosity runs 2 activates per 30s). Both are now monotonic process-lifetime totals; consumers diff readings. --- engram/dist/engram | Bin 3558296 -> 3558632 bytes lang/releases/v1.0.0-20260501/el_runtime.c | 65 +++++++++++++-------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/engram/dist/engram b/engram/dist/engram index 1d7defabca026282cb35143fb998ec631afb4dc6..f848140cd2afdc1c67f10e6d9873b6c35337ec89 100755 GIT binary patch delta 398876 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%0DL@BfMJpn6Q%*`cc#iN_!uns!(tAN#BKmhw|5}!^ z`t?5s!VoaxKSseKx?(!KlP;P8UlxAc855K-KTvoPUC(@>atrr;^(2kOcqqrg>=Sz6Qg>c8_ zXjn&w(@Ckwr_t4m;5~HdV)j$E@Bdbyy9*j7EJ48-;ZNx-=1(Z=FCwW+QU43`#xmIB z9`q|ohhGtnzeoN3-};oqXP_XD1(vJnkQK;3(gF?ZSHiE-#ws|G&Y%m0{}JwfuloDH z^#ZH`lkau(F5x<1UsuQaSUQUf$PqqA=P>_>c^?{Bfp>%#3m>NQ*r56S7$3hHXCRQS zrcF983;CUN@h7lZ&4AZB1X@3UhP&u~!g0#_Gq2BP1LkYj!&`+f(y<$mzt0W*Y18P% zK*mNCj1^u(XMKkJapAjKqM?<4PIxpOpNsM99IWpD(+tFYj)E2sqG9!B*pDvV0!J$A zGmx`QPcnov8P6M?>FT za3o#78(vAf7QiKRtg?Oow>^vo##bnKhK~Ch9z=)jWkcc9bPeiZ=(fxsr%Ox*nzu%S9*3}im+89i;g4vSBk&eFhW?pupk3Rb zpXKM3^(pr+Wq;;P?_&tWGhlfWoqQbma^bt$VuH9buq6zmZGoi1d)T{ko={T=loba^d2myW#(AEceG!Hv6PeB3qe z|GgOStV2OO-S$s-6P-w(r(JI#f6p^$X!%*Xkog$lHMEEM7aAO~0`yJV_y_sU{+PgW zI9=X={4(LgbiqyJ8$XNjZU2Qk(dzda3byM1b+dWM%yL`{LBKcyWm#OV}e3@ARW>a`82wSE~Vp|A>XVA#>X~?pQlUd z@ph~GFTw={IV>o;2R=&Ywt)Xt)<>A>3cJ3530&@j`_kq2!;^&9(;*Ka|C6@9|E$16 zJ<+g+1+UOXOAJV$ogaj^(OL9WI^rSZpX`NxrSxz*<6-2pl12pKrU0fC)RaFY&s5`L;T>chO@p>!RcP3QX{{}b)m8Ga-X z<7=LR-!d6+dK!V5bQE1c*U{JLXg}0H+y@PVyTSdG^%1&10}o_AnO;PDKa0FsC<4FJ zX)N%18539@OnX0v25EGU=izVZz#eb|T|qzJ7yS}nu;)!VI;uy8rL%hlT}#Ci7g{-4P};j1VpQP!Vf@@w!}=Id#G^_(SGm3N9i>BuGcW$GZgtAbjo{hFrDx|JlV>>-yHk@G6r&3 zu$L~PFVdBCv)3`9a~K-77Y?8cn2)6WMxcHM9W=s3;4^DL418Ewe+2!d`~Psb3J245bgZ&{|98EHf)y=MKs5_8Xs55y zU@z@WU!*+_BJcD8CiJC!==h_^2h$#9aJ;hpuKUGAU?vOPs^N8X4!w_dxrF?AHYooC zzQVlkpYQ|WSdjY-I8a$nSoRk@fO$Xj9|S&PftT|=_K#o*3sUJKy4Vf*yCN__-b1h- z?e;JnNtd>Qm(k^I;Qh2|1%4L=Z3bh-RUF_e{G#xi!jZyp!ZTshuqIe03N{Gu5!%5)3a``F z`@c0{hbTBGTp|3sur11Q0WF2Sl=T^_@xlSUqio;*t-wrCu#>LmfS-lkhN7XBf0=gf zgbCv5{!hXig-;LV_x~6cG#!Q`$oIy8$CUMo^L^kqX%Am`F5QFPLub>!(+zaT;ppez z1>+-zn+QZO@G%R5o<_lDW&N2tb%S>^AJrYMqTPDK_eG;$+X3(Zy7&!v3hn(CoNY1? z!@v*pF8W{E_iYU5I06&I(4lk=okADWyJ+8cF#ZyqOq*>+qG1sOZ_+h%99{M<8hoOx z&q(S(_;coK--l1rmCgkPphCfjWq;}{5-f`V1F`&9Ta9rF>~Kjipz43A;nbvm3$_ej!K_x~{l!t4RVxJ4JyzN0aL$4oRBPKVMf=|sAaj-G}3 ztIB#oA#>mc=1b=)>;3=9F(~lOKtX`AzUs5+adgmniXu>Jdg<{bewuTeq=azMRs`&dk1<=>`*S^u%{X5pXc`Yrch|92UOhALp+{hk*d zO*`cwzf$;+a0Bhi`cC7~-|~C6&5LLr1GOCR6&6JDmv=vEW(ku`jQd^ctNk=5qI z!|1S`@M=1NK0;TS3^a~IgC4su-~~FKj-#{arF8Oc)bCf;7g<~Ze3<##ui$#R;Sk(@ zBIYxDoI)Uyf!fpXd^+Suco&^T|4P@>4@^SCw6myxfv%)uXz!np&w|ze|7W0t1^M(% z+T|Pube)U|g6Ls%ES*e;R-%4~vOXh$7vX)(7goWS?bi3-H3VA4V}jsY@Ibo8Xkou7 zXVQr_c&oCWz|9HX%X|X;J6-aBT-|>_j#nE8@W*5_A+%|PSep<++uDQ>V$DLfSer(s z5#kM@?T%$a2q6|4u}mz)+SaUD$d3`rG{R$IZDNfO%l4l0e82bRx&HiI-|JlG+)v#d zdEeJt7kR5$nD1K;ennfqf0-=IPz61(=m|6=b3uN6ct7pc5WY)eOjk4|jk7nT)HiSB3LDM-nP+(KIm9qXWFK~fhW$w`y9>YAHUP%XaL4Jk~?FQG5 zI+$Kf$I@TW5dpS-_2++8&?gERhyj1Fp(qe; zJ`Wp|jDQEyfn(tLw9`2Fb2{c-_#B-_*ZYtM9D4-HN@}#wLjuVyaEl~XwMXQG@V2*Qq~8|ScN=;dFpETG+mks*Ij`5 zHM9>Mv9=-Z|94r)TZ;wj>1z5E?Y<8AJ=*bOxP2lH6uS}jp))>#Us2XSxSTe@bLhNX z1`0b^$o>|tq*D&StrucI_4n{=bj~68Lptv$oGpA&xX~gUxX|DNcU90QbUTRwuL{o* z&Z0fp|Fdx2#h7R2zO)bfqiDk{d?Fftrag*qAjc#OH0>)qQCWXac(eZl=9Xft-ywVf zR^R_@a9)B9oao-dQ-n9suIw)nZnPBh%zO}C!Tva#)&AZ;;e^{&K|ew4S@<9q#FoJK zXzMxHdl@#coQL0`Bk47CK7E?5p`S=r>-GKbQHlXxx}fZI0Uo8S4-|J99>+ZM3cQ^5 zy$yd$S6dp{{=o7#omv}izZ~m~SGI{Ib!2Ax7by$T1+?18+yvi_20`oUx9l3sAC z!9q0)hv@L$Xt+=3(p^_$U={r??dFgEB-)`5ykA*=Vp;v+BXr3?*syXzKp+avYp_9V zDBPDWeixokC%p&f(C!oAGG)DCP858Lx!WZ8xm11$qHQ)T!|e-}xx%~YNGz~i5^k^- z1I@e_9mD>K!fWlU-v6U4#B;&l!rj+l12dmUM@_{OtrI>f{E&`izt_k7gthhkANFWL zc^RF+1^b0>3b#qaz-0EnA-q($kPe>K2>1VAEad$UPvo^81HEG4Hi35ISp=>i6>ZD_!cLw}Cok)+N-L@iMLPyfy&^h!ix|nYL3FiA5 zpJKpJ7ETlucw2^rNg}vs2Q}AWl z??<@dW(+Jp1NWv~&cRdYg!AxvI+s48tiOlKN|9eduKxUg0fiG#06=M(NOzS3^d(UcnqD%{$;}72;Zc0 z*xw?P_rF;fqzblg8aB+P^XZ+!SA<(^!}_cyc!0sevxRqT( zuz#}f2H{h55&P?I$2`-$wj1_^ST-a##S?6&tuAmW?e`>HKMP;ekf-2hmGvhW&KW5qv0MMNq5_Uff@7!`Z%3L=d{53uaxySS)e<7kax}#V zpZ^NBPr!RGHdGBZkEESxLwK9;F=hP;rnA44c|-!{)!&Et5ea(;cD7zB{pdFB@SSEpzu`Ku$T=SM8k36KWXn2Y~cJAHZa{?cnIyW z3jMLdTWwbFpV@HS9IzS-9teAV%?+8qPN&ha!W)G1=xX*~*VgZ!S!k7q4NMQB-Phni zlZDp^=h6l2KPPPY2J_9lm9p*k|BO^@@G2Wj#|v*a2eAJK;oHKE_v0-J*?{?;ba6WT z(th6m&YMseryBJ2X?m6LH+0e#^j{Zl`7PF)`9M1DQ}o9OZ~2z@zu9nt4W-+#z><%F zre6?_ptHB5f0gi2;d^wz4)i-4-(iDn7P<%zrc0Pd2+yYdcVgfQI+D($T|P%%AZ%O` zg};QG9l!z20Y1V*gx?cR6wb7_VL5DHu>2}q_j~&TcnS{?9w(eAoMmVA{-3lfSS+`N zn-$m}z)$#X;km+Tv?sp=Up;Dl|DS!dpnONT=|LR89MDa8i10+=B;lQp*mnP)e59b> zKFgoNO%K^0;058=g=Y$<2_N{+xc`6suVB0H8yvRZu)FXm;SYp23+K~*{1RCIHShm_ z{w?4&Xx!8_5PU$_)s)# z7yePWM!4+{_8SfojuB4R*6*KrfMcTJp71j#>^BG&o-MpZxRB1}Ctj&+yZ_BXvy<4s zbZ_DD!pXw>gf9p?7TM4DDKdZm=ZQv(hQ-2P2$u;rJY~PZOTv-Dsi%1Vn@@aLG~5$z zciMh~P~ne+_X?NNWqe>q<3|iM3*CiB3ojPV75+uIL9zXOKVc(E6h0O{Cj6JM*BSc_ zMhPzz&a<~+skARxp83gs;2Xk=h4Y1P2|s(*eqJzLVfzxO_dnLIV6kizJ}mr)uxkl6 zz(9+om+&~@tl-ojDBtA)Q4u6)F{```VX{RXcI8^WIpTZJ2* zx1ZNjID+=w#ozyz{8zBu|9gcm3fC>g25Nw3(E`1N~6A;}smh%!ksB?4LzD(VJ;!`h@TUW!wF4Hh7d_1JlEW=Lzo? zwhA}BYCms)@a(JR@BchumS{Lj`|iUh^cU@v2YX(_Uohl-3-?jhe}7P(4@c8M-@|Fb zN3I!IU^Y~V29ICu^AO?r!a2g_!fxgE^M)FtkRY5*M;^fwoKe<)F&SF~S29mK1-JSQ z8@Qf@hbZfQ%Q<)w9ZnmGEO?fpVKbdi?^o6zY1#$kCG_!2a21_lg`543{@lxOcRK4A zc$Ar6vDvW9XThTk4H zR%f;;pKk|aDzXwfw|yi;c>#NgbxYd z5pH=4^Ail7D9|j>Q-wDQpAh~_xYKQJzs z;U8ebVh+3~8k*n1Pp&E+$V*xOAc}XwmuRGLf^d%TRbiLAdY*d!%z=Tn!he2WI9s@s zu5!VF>fgfwP5TN@5MHmX?|*Z_3DMwCZ9lMwaJ29SI^#(k=xgCp;XBH<`#;PT3taAF zL(?w`52L-GMt`jECgB1)pgH=j!vEao{ckq3et-j*?koJR@Lal-8+X_Q-Cw-_ z%>g6+!U0UrrmZdT1Z#!!gwN6?Zs@O7gL$UA2#+vWC~t`c9}4dkzC?$#;sy_~f$4U_ z{plR`#|Rsrio$8Slnd?&yZ_Bkh3WxWM8n<`v)7a!Qw+F zVu9s#;W*)S%KA?{F>oqfFa!Rc z4x0tvR<_;$0dr7j+W;H*#>0Me1|3Qtr>D?9bJ3qjhtV5p$9c%VpsPQG&opqrzyEI* z?umxR4RIjrM_ABRc!cm&I%fg;Q-!}5zShvd24#s@P`i=6pAilajuc)Zyp4`ui1|gr z4-8Rw))@yd7YrAkC!9$qEy4zc!WF`fjWIucG5U?}qA*5yA$>dv3vz|83qREa8~83k z|4YK*_BJdA3#nZ2x$qU?MoqCn0sEg99xXhVj#`QXW!PE0|HteK7R&E+@G>lD?t%?X z4-uYC$FP6BaDng@W&MN6>0>ot-~V^m5U?H_HhK~pX474SU!hBwzbpJc?Y{x@R@0I6 z4%%fSfB!$hf~zX1gITI+H`?PV9LSv>L|0{?eq^~Mbrs-012@eB?S))elote-flIXsGaatn9??bHU| z$Ns8k;8S#x2VBAa$Y*UfEOk7vVWcM--0AT4a9=vP1N;`9(GmWTF7kqR(0-lZV{{sQ zmoBtfz5mUg#Q~x_W5M%uNEbMqj-@}Kllmb4luqaepQbDO!!>kbAl&ge?l)Lj-~S_7 zhQe?eC!ATOhh%tRELdSQc#MQ|TF zYzZ7gdoP2x(gn-m0yAF$m(ij0KXg9r*2%V?`v3oB;YAcIDJwBx7@e>Rju-xnc3h48 zFdakxDqOoW9x#o08=KYpXBK*}A#e=_j;4d?Bs!S>nhv3_(4OnD-lYpREJ=q4(texa zXl2{K{}=Qb3X9ngy&e9BuE>V})C<&);^IB9lQ(}f=fLfh^>=;XUbsJP{Q@3G=j6i4 z%C`I8_e&JMU_;PX@L4+GYxuFQ*dQbi?n>v=A+-B9$P?&5`ZKzc{-G=H|Kj~v@Q@8v zw0k#x&5j`-LZ|!ye?VJ`;2m`8Y4|c7Uktl+$Gn)I;cne||65rY#sG{tV!tKL8n#2(aO3%;V*bG?N(#6VcE(B z)hJjF(#8K^!8JP5($w}xt|l*HL$6x!%XHXd@SAjWZFm8l<^X>|JJ!)w@BeugB5eir z`+zStNTIvaevf0o8?<{}IFSyZv*_&R$j{T6Zm`o!nD5eBS>OMDEM&Do!&Exu8F&kw z=m{6lRrFQbtv&KuFJprQx;33e_n<>NG{yZtf`vdY445apoj%U|Fzwq3{nvzR^}qqb znYR*tk#_3b6!-rq7Mwd{;77CzokP3Q=jn>>=&$dG4bxtPd(xJd;c?3Po6xxr9M9aR zuYtlY7P1GzWn7Rt82*R$eg$sc6B{}O!7rMA4St<=2!`Y7M0zWoYYauhK^Be=ga4qb zhr=y>q3g4lVX24DSF~6Gb3L6&pnP_;04T`f#3*b0q{Y_Z36kelq{path zWhnf>1<|YEI{mO9G!=HIE9oA}`o2HD7WrFr&ByRux;PEqNr$e7FDTpY|C9|VI0j%~ z=0@0yPD_X1H1kj3rL@Z?crWe08UBq9rr42n0R|SNvT%_N`Se5D^D8W9H4y#5bWgg54x=mb z(4R<0e*tpEuh4!aw z4Z#K#bQ`+V0sTYh@H#HI|D#zrt_tc~!IDB((R=8y$B~zs1L%gYVZ#WzFC9rwq5Yh& zehXdE$OZTR1r~yvprL*+zA3|>hM!Z`Kj{*h!*9_RcX&1X%iF@c==f*g*A3C)!^6_+X0GvkG41kMhBV`Z@^+GT(?iIKX9UTlu(53W3+F>a2 zZFCfUj837i)BeM_-w4}&hQ&Js1s@bFIdll^J_7j+I*?vTXVYJq>*?R=T-xn*JYXI@ z&}Q}iCBKOc=CHwkG`x$>cn7|qtbbDGM8eg~OWuP!y@3rvroa)(y5DaaY|zE@I^A#k z`~Ux;;cE`ao&jH^GiSn2gkl4)SlE}&rpM6MS;*(pRkPtew0j(URoQm`C$Ug}BsQp^ zd(p1%W5IYjpI$;|e1JTkE~Kx~rOC*fjl%rm74YCuy#M`Ip%BN0k~Q!iI)5$v8=bQO ze&S6Gbl(Vfq66ty=xll-T|zH>llOl@ItFZGL(C@lI9*Lw(CM3zHw?o8d@|tYg+~d` z72ayFVA+lVCx!0{w|)y7n*9Ulaa;4-?} zX7&ENyn_vb%F)n9S#OYZ9S&k%Q~{4>?pO&gqJ95__tJ^CU@KinHyVTaDYsRw@Bf~v zpnp(ARAE6N?Qs_#&IMWb;5ovZgpUf}5^gaT2hj6ufB)b2k%BshWrFYu;je|S2s=gm zw}GD5UHHxajQfAye+AngKt2;bE&P{o+i~_A4i=tDdspKVT>GyL6!QNqz~#cu?_vXU zz)Qm6!imD!!atifc%oY4?KkKkJXCm=aJq1zaHa6mk=V~LpU9sD(~-i<=r|tuE8%Ox zP2a-?W`9rNNZ7EL4Jo4GJK+jp*9rC;^c9{YoGM&kvwHu`1NRxpucdm@H*jx z!j-~qQEI+^|I7mn(1k}lRrq5%fnS1S!ZpI3Ct;r1|CaC)W!wF4HtZJ-mBQ|m?FSAO zju*}rwhA|%!u#JmK%Xi08%z`aMEI1jCE9+yw{W=d@@T_;LB43H6mC5g{mJ|iye+&z z_>yqTY4+>G3{glEz98)OKQTafo$$}Xt}*uOjZjfoBYal)$?5h3LWEZcpAvSSVYl9} z1lt!ZONDl;#m6)dJ0DhrwH#C{!Q3r)+6)v z{qO&1L3yI^8sYDRD}f%B3=p0myi|CPaLK>s{r~sB1>FD7yl=nZAmK^ED}?t6pBJ`# z!1?C=|D0LiM><$|ittL>`92PONce$p7yh6#``@7rvydVh3WXmEd&lDm%=Hn%tA&pU z*T9Cw9N<0Ie&AT)HNr=PYlJ(`v!C~laEi_9{WA|xC>kCJclywN;AlFMUxF3FhlKwU z?v$YB>G#hZ5UvZ4I7Rq~aE-9{eEaodgjWd{D%eAlzwz z{k-r6y#LJuq=<$?!uN$cCSqU?zXTJ6KNG$#+f+=(volGbFg)h+_+P#Lq|6gXo=^+~Gt-=ODk3DI-j=Rua zj_^p@w;{Zg4)KJ)r;~i)+jQ7VaJ$u*@A2}Jxc`T$g8my2OAj=}vmt@r$vn~z`5ERx zz2VwxFfiC3_Mu(+z~hwl{K&rWH0GK84HP!8p<)2Miwz!w;R|%gD{#G3Y?u)QKTns@ zLE%uih|V1j-=Y0N;AU%afHJxV9XkSf6dm|Fyhd3c zz~c@0Fmof5g}ZD>3PnS!b=V;4P54zhIt(^wpSR#$%6fyux8eQF3*UjSGj|#b|Bc+R z1iXtv$B(gL%y>AIE{KHZ(+=;!`{*M2nzBAX`UK>E(&15X4g1R{!Ox}X{nYzs7GARz z{_`y1O?2L53@D`ir@+_Ee%g6G9w;svxj!8_6`r82@BhphD6C*ZVjR4mPMHVap|jIq zuMOCsJPUrC&fNj0(D6Ird}aL!g?$eHscgIdtt_Q@I}LZF35TbE~nFazzw!xLw7&8 z3tdPLr^9+8PoTYe!JjMZ133163itmdHYD{%L&ML|5bY1Ypsc^kgZshb=#T(-4ei<= zKEm};1K^*SXAOdDZ^!(~!3GLXse<0Xa|qmz4t))drZa=#^>jIXg3cL={BLFbgbBmo zdRcHl2<)P)_d9NkK;dN;f?tQEhfz3Ghi;PJGP z{~-z+Sg2kJ7tw_&@Z&o%FnJZ+O<6x-)M|Jv^GbRp^Wrtg^O)zZgDYUelJ_wRtv|;G z@oDfdWxYZ1dU!N*mrvj&%tJT9>CBV2z$fVZt#A$PoC$Zx*88dVFPMceTS5JU0o%~9 zL|Gr8f=;Egwj*O_gR_x)Y3uvHjD=xr@XSTSY})4=csrec z4z|*1*I?(}*dX^;IDn2XhbJrR2a5a+UaxGs{}X>l;TRjDuEV!Dp!5&eeGfLMsDy{o z*?+?G=)l|XPG#GdunPW;dFoyG#vb1P`S(zGItLp#-G}?rLG*Om^#Sq>WxavVU-0M5 zU25QBI+eal`#(h9d@t|+VipGN#R2mFM#D7P-=Uf9GFeNzJ^>fdzK!4qv|BsadmrZc zKM%h{hrIx=Hdyd@5ryxR^%FVy!hbUNdI@&_0=e_caGw*6L;Xpca06d+}83=EptLPu;{6OTjzr_5~L2yH5JwI=-&4#5j z3t2&E7)pD;3Qwg==#_NT5ahXZ;0X8A;O@^B* z>w#q};Qq8z3LH&`u7W?NQ|Y60#A@W#%C-ku(+u~2<8M%iS&IfYWxb*I$FM)0L%&0Z zr6EtCE9u>I>3Zbn=+MouWk2ReY-@)5zXJ==JJB$jjyedZ&_%^?0bPCuuBNkpg4=$J z2TC~$4^`F=lvM&7%#(jMP}s_bic+|kuD$@*$;W`ai|`9{kQE-ItUuD?%kXsOmNNJg z+Vd*>107>rL*YIPIduE)uwneK$U~L&2C3!nR66;0IF9{674Ul6?`Z< z{o!eJ_ABsu+G!~KBklbjT<@L4EKVT0#vc%8C-BIh~qQRd!p@O|bk z@55~hu|eWoIG9eI2hXF!K7?}$dH>fWpm13==nWG;f~&Y7DiLmT1RJC*gon`9MerQj zeKDLxSJ0)(dcNZl7({RH_(kY8qQJqkBEj=bO){DQLn$>(+wj-b7YU}F^v zl`I^hQ%K{rLqn|- zaAhg%q-^`yeG%?TdtZWw(;U7AQ_CC!McS0VntT%}1 z49}vYyx|1)dv=2}XjdQjFrDV}H17XjSqOL@4fTG+h9z`o+Nme<5p-c6cs^Yn4u45I zPKL|rQo2Pk=4VVX&=8;s`iYXF;c0Aeo(gYdUPT{dUL1q`7F{+SZhHnBWX^zxDeL)8 zvG8c-Va6O37O^2C4qnfO5+1OScAAU)HXSh!ZuJwNh<=rh{t)>bWqp8v1o$J`aQFy? zJ_kFW$A;ylaCbWD0z6#VcK^FvL}5A`GU;`6>Q&_5(TTsqf6{4BG`Ia^ ze6|!D#ykaw&;iZh1+zm)YE9Fe*sS%+#K$ztbcT7wuIlNvs%GR z>FCz*ey%TYhmSE2^MLPOQ1`z+K*qBu)VqicYTCg*w0C=WG@Z}^UPKqrU((4Pk^ic! z=ZAa2x9G&q@I!+Og1V#7<`NE2ME9j*eUOi%ot}qR($)0WbW9KAm+6!~aD6N0rwo7% ze->OuqcEM0m<(^BeWt)a(=~MM%Xq?)Xyo0L^_M7YDjd$-e;T}idD?WF4a;5@(r2LI z8XYkcZuSc{$c=?Pl=TL|ad0s6)c4`B%qtCe8SOC_{+f=Rr>)-qUs=et71X~6bOjqE ze24`Dl=aszBmo{u$9)8cvEP3&{66iy1pb81p%2huOI5D#|Enxi>Vk6pG8~|A72KUp zSqDeZ$G?Qv(vFAWBXlYKkj^MX-tHoZTnJ(Tq)=5z`UWFA%w$1u-0(;WBz0ydPEpkWW~d=9=uN1li4|H=*N9&}78 z@(IfN0D%|a>9pe|IG+8o*L{ZUJ|r6WrkObWlrpg|dD^pH}bz=DGBr%+p#UfBJXKk8cYH z(nj(#D9mOd!~@P!)*IwL3xCPnu|0f^d2k2#KJ&y*@N?I(VP0o=IPKyM$HRstgoRyf zaPNwS%gXuyRdfZN(;fLe_WL~#H><#gUN6Eg)7kVWI@A|=oXzU}t6fv*wAq@{3cyWFQqf4Apb&HKTuLMd{yWA{&${=LX(?(V%k?(zm`GMk&mOp zX27dx_nGiPu1|=CPc!$3gC8=FeIIuIgZF=tfkF>e&>K3=h2Nzk=E2M93_72V{t)?1 zW&MN!3GjV7>Lb{p67#(m!=9D={Xd6=L2L+1LPHc?Nw1?zmmohtN34X)>9ngJJdee=K<3z<@$Ji!P-r=xen9 zP4rjNX>{#7c%X!P$eYj^bQ`+BX7&F2uu#T^fwV(42E0zY(&K5%edKfK1bP`=K(D1e zAE19TousYr|6MFpvf*1g=r1fdO2^S>&3^g{9a@9_-{^e0ijI7U{4d(7tbhJk>fOah z=2pwib{RcMC(&)_6xxeUr(dMA=pbeNJ>*au^WI?YRR9TH1-;LZ{NZX_xls zKR~;7go|mTzzYQ{3&EY>8}xDdAsyWrd4p$6XdE`r!^_SF2f5SY+7x@WWuHL^y7XD^~TMslex{m?g zbZ=$b*Ssh4VCE%sJo6}j4*HZ&h`7}$--j~ut8pbG&EJ#Pf$b$FpmgC zK7x5H{SkAgSCFq^?oJmn&v_O3&&syn{|i}o;x8N^EEo+fl=T6k=^*9~!;!zm+?8I+ zJZl8!8|A&`DW(f z^pDJ|#vm`N;r;J876q4wI6&Gs_*rFrfNc78<^hq&$1@M5Q<+yxK)#K+Wg>izdCDaC zy1|A_7To^E0sNxT&`DVzAeeredD%4NQCBU+Bj3e5oxaT6Cly9?y{jA1JNJKu1xi9@0^W%$hGFp3U4L6ZvB1u5=#r ztk01Dz&xM+n|a6%-v5mpaDd1iSm3X$4^ZzR5i4DDr=pr_(-laR9^T2Q>6o1$}@( zdNvzMPakRT{%6h&({R(o!QhXK-VQeU;lQ|&n9P&?? zC(~z`dt5+%jkzz~ydDm4{1Wnx%K89SdbBN9?_bO>XozM*BAvkjZdZ}-W$sP?&b;7P zm}mWi z{4M7B^b)5!`1}8m$6DHc@N8g1Bz=MdY8;SXV(wfAc5Z+JWYmS*DC+~{(!-bsJ%M~I z^Kd$)fq?;4PH5P|2FC{QPaKfe2>z9MHtpIF>jRn~Z?CKm5K50?Ug3g#B6G`=@W%!l zQktQV#fD6}l(}DXP3iEW@*vJN-wrI#^Lm+Ks zUh0ATPv(_$TW1^~p&jz>%K8AQbOdv+4#=l7_lMQL|I3DAFEo6?hH|=`d0ZFd_n9Zt z9U9{R9^H`lP}T?VrK6Z1_d)(XbF0nj{olccm>1EopACuhP3CSdBmalFH{GQP4p88S z++SHApoETQ9@QK9T;}oG`u^X=2A95QIKT!^`WExN0OYlsVuK>uM_Iqd5d)F;XC6z> zVD2;+`2yzd%C_JCbJ>s+goYz*D5M`S4|@%HeHR=cn)XxH2XGjM{8i?z^asqdLXa!n|xM^3lwz>15_fF~~n*ZltqtnhicP(Qt(gfwYS&4p2G^ z`LoLU0G0IX%oE~}k7u4rr!x2AC%z52Vex0-92<(~V!(9{D5u??#sT6Ikatqn2S}zz zGxu14Jes*Ly@~npg~<2Va`paMS-8rEm?SjZ<$y%mvpEjnwhZ}8%K8A_^hD+b%aO-1 zFQIobk4i!QtzL=#$C(G^AivO3-T!)na29H{ z!U3}Pp`nSg&I{-ln7e$5d?0gAdLr}KuaUH+ly1sKdyO1#F0CA&U(~N6_#M^D_Du=03-f-)0_2 zySn3msV9)PSJns2qK7cADYE5;Wi%U{Phr7KI*49L7tq`2*dNiqpH8HUY5!v6cj*ke zNgEuf%4YTccV?mN3>Lgbr~d>;(M6ZwMReR#t!#g2&7@Ph!G*L-clZ}Nm#(3!d{nOQ z|F&&$qTuJTpf6obkD+~EL~hVt|AV*CNh{zZbTa)rolndI4QX@1#rVGqh6**4NN}bXyM`AUdTL?*Bj*GT0DF=hKU6w^bOpi}s_>DeE6h z8FUq$z8d}Yo<;7l26m&}QVkTkvEaKF4y0r0P`a3oqKnp{|0CL(2B*`d>*2k0_y)L; z4mCESaFK2E#rOWAFbXXSh5ZY}AJcUl97bx3)|M%R9hELew`Z>Ix_M;Cg z>u;)@Y~+{e0@~66c`@xqm(gA6D*Ck!y#F0`VPG^HT5K!0<)Xhc9Ze6WvusxH z|2P(M*^odN(4WwbUt-{X+MoV`&Z4i<-d~~rA3A_;(FF&L*Vgy{3oInDVFaB@Poqoe zWwguJ*dU#DrT5TQ`Y;`rhyI^wuWxw&SFw<-3hJBH(%2g(ETX;XQhEqoPDj&KbTaL* zAM>(lKl%V&v7h(<1s0;e#exTPGW~Q{94L)`kunptbg*k6u@=5!5(xQ+K28<2hgMG5PBXRVX&~7g&4YkPN2`yDfDeRgKpd% z2g;$l(gkz~T})4>jWQNivrt8Eqa6<7i4W2)^cC8JuI+;Z_|VVM0rWsRgpPy_O9TsZ z*bqanp%du6bP9cj&Y-L49J<-_I8XuYOBd54ZC3AJ84FQtsG<{TheP-Tw$d*2A=-n! zO8d}`FW>+HbbC649;~hJ|7aG%*^o#ZbSj-rXVTx(x%5@KkgoqC4p2gOq08yv%C_JC zt66xD4bF%0#EG;!y^Z#!kJJA2O*)u%@x=kcXFP%qc(C6tg`T^}xg!OJO;{g(AqZbQ7 zr_k^^9ZXMA)(4Efg?u)B{5CwFPI?G0r-N&^w%sM0>5#|ay{7BgY*-GlV0A{rk95w{ z@D)0;EnGoco`E0IWrJX+9yoCLV7LWsc?E7yN4}=5-v5_ba2Se)!L;j0cqE-V3Z6`7 zy$u_5=sY-?j#&wBGV`_YZrX3NvcCThuu!!N4aew=BKRy_c?$lW4n7TA{P;ceBiw{8 zxe7l=XH~j0O2Y4%;=?H&Ghxdh#&^7(x zv$Vsj?uKoHKUgRaLBr!c@kCy4!7b_Xsc;uMY#Kb6_WueVM;Cny$I|&F@It!coPokl z7Gi&a_tP;C;bZjizu_~&*J$5*ZEO!zO$WQcb$j7~5}tya(XmDg6gsgG=mGng_J)Vh zH9qj$v|BHDG9Azxj;Bioz>De1LGU`-NEnR5P8JgB@93f-$j_L07+gkM-hv;{E|GBk z-gsiS39vhz5CwOI4NLA66ndEr|APn9`7!Va+I0pzf%c{iI*?AGgXwK_1ijy8_5Q`O z@FN@I>2f-men_X&P5kkM*>pQPpYBN)(!=Ru`aNxZ|Ch2bmkr*rc)}FnPlfjjpAoJQ zeyk4;Y|eL8w*CHZ7CMTCUcy6#BZS`13wfE$-?V}_X(dAE*GxV&wjt=hA4Cw4iX+G{DE+)@NVJb!p1dGump$` z3i}8T5snm|C!A_;!?M%9U^ysUDqJn>(%=5T&kDaFJkZYS{SUP(SS;@e&lX-RoF=?O z_*>yqk6PdVR~{`W-x01m!2SuJ7VaqAOL(Yo#3R-}e=IW}DQGVeP7~fKoG*M@_^NRA zf5!daWT5>Mb`~Be{EqN+;f2EMg?IgH13zjH{#$^57QP`|E71PHPYQPs?kyZ*+ThRn z_sjzQf$&PGnyk>s@PvIcpXyFv$T;Wnf6z&N(3AR5#C*jwG#|qCBUMy^E z6ooy)hlS4z-w|#!)c(Njh5Omtu)Jkou*?)*F1%g%d*SoKw}tBtd-Q+>|>B;l>X`NHRftArblFb~N4-}B!B?*G2RVZt+n zlZ8JME)c$G+Pwd(%>r-3Ca;?(#DTnodkYT}9w!_tyqNy?{@)-Pb_o{0sim)_ZJOs3eON;E}SKNSojy=hc-WQ|GS3TpYVC%VZu{{lZ3Yk9}>Qz{pkH~ z8EJojmcl)RM+(mrUM0Lo_>{8U{r`t(XfVqDK&@$iev@{iOXxs4dKSKEN6|@ijPUYN zy#LLHouZ*Y_@Z`gi{Y;cV}LEogOY)Ae#eees|?Mgkgi&D=4%xeH->w)(3L0 zg5O~7eg}@Bt@LWs_mF4OmTLG69Z&-sRu&>yc>FCKDAUr`_M^D5X=k{tvOZ97W4JH# z;3n{B+PNt_*YuO{O4=JXEcqoUKT*lw@c-y5^g8+`eSqs9(07?T z|AX~z?_!=2$wB}Nv2+xjN~h4dbRJzzmznD=&)9x$IE}{!v9(|y)3xC+W%WH{Sd#0a zFc}3)q$50owz|U!v~L@D1)WH*H~Z-fW&Md++oQjLuB5Notlq!)E@)^Fi3QHj!`Q+^uKBPYdFF5xA0D7{RtNxhV$vnLb%Xi!TmA{Khd#t8C^*K zVfO!m{=3Th6LbF^ZZ-+_reCK0?;syT2U|RBuc?v9LUer;_9*KUCqD&Wqa&Naf3e?6 zKQ|d0UZ;oBcj@<)^*jextlvw!!G>i&3xRB?;DBuUsVUeXI}`)_mGwZ!k?=6uN{^yL zry-A|v*{VM<$pR?@BdtLfvuqaJrL7#FknCJ9S8qFC(@;~mA-5`0sX%!>o1Wt33iF* zC#J3M|2{0-Wy2I@{e+J#!GdkfUFkD)G+lct2FBA}>2!KDolh^JElWLc|9@=`PzC+_ z|8J(3!Of;|gXM64WqrW-Rqz{h=xTU0U9=OPM0{Xg0<1{-`pKd-C@ zCef4W40fOV+S(rWpnW^Q-RMNRr`b;j znC^!DIkb`69fd_KIQzhB=}3BmX+Pu{%KA$b833QA|3_P9@DroEDCg*?&;B3=d;BS>}_kZ?Q6b`c?pFT-j>5Fvbr|7>%TQcFBv^)Kf_TGlP z&TJgepKdT)|NgH|9L|E9YS5oRdNvmL(D`%-ZKbEumR;yyO1snBP47m2oDQe&%;x>lFOIzt;(=GHo_5N3};O>SE-1t4= zPxq(8=`rT_4E>?$mRO%or}u>O=zQ8rTebE5Un?G;fTb4}w58qYex`dPkEFxtRdhW4 zJ)KTprSs|fbFp8(|8uziJF#F5#|DFF%RBHS+MQlX`_rG(;dGJdF<5_xPN&<>;{nDz zhx~&canT#M8|d zV1snJC!J4^H~j+!E}^YA;2pH(CVYl=rytm?-amg9S|?(|a5}*B9~dx+PNz4}`E(I& zrSH;~O00KZi20U3;Q`wE{&#QO&i0dSJRAJ!WICMQN5|8pbUOXmB7R~`Fwcv&(r?q2 zrpT8o8~VC+XCapj{`3{oE?DryVtztCaC#G z?2?2H{ptR6I6Z-mr&pSO5$ki6^`9@2--e6m%F*!kB=xgcHzbZl!Lo#Zgrc9M9V3wY z(ysJtbRZpOdK~&E(3$is+VNfF3k+RwRKMvo>1g{N_>7Kh3h$?_^hw&^1^F+^t?H>u z#2>D^6b`04(V288T}>Ma=7K&LkV%KqC+Kkc79B~uF2jb=bWb{#eus{yKcW+1!?K-) zWHy|nQ|a4uI_;W_4Kry!I-4G@+)#ZYzJ2jPZ!`C&XD~0ZS-t;r*lfFS`)75k?U4J#=}7vpIp7fTpJ>N{Ubb)AGCK4ye4h@d8?V3&JACa)Z zX(e1iccm-o*Xe3{DqTY_r!7Y?e-G_I7txLe3%|4AO#iLi%1OP}blVg-kRCt>(^KeB zI)x6WzoaASE3^^KLfuu^AeQb($I~HnB0Y;vrZ>>3bRnHiSJ0WX^J?3Eh9#SYmr$_e z(r?rG^oMjIy@M{IPthgx9okB_T7w5Hr~BEg-oHu~BH2()ub?eQ@ip9S`WXBp?M_#j zK92mURBY%^`T zA)lyh=x;JB3rpExJ&lIlbR}IvhyRTHzUgyti*-0aG~JiBT9HSXz6>u|r|*AtfJzp! z*bx5*8jhQ;gm2KvbkmQqq5I#+eN6uYzfOD8adf(4C)*FM^&jis#nb`P>!I*18?xzZ z=D?=N9n-j>3*3?Rriaq`&mo^?x*eQC|DUk?j;HdC{|A1IjO+m^F zgWzTa0vj2$VEVwas4;iZ6NZ9W4=jhaD}i&tb_bS6+atjp;0Fg*K--aS2xcKzIPht- zfao4N0E{B)lLuBptqo=cyB}B?ZBGI#f-4WK@~<7i3_)On2AH)2tD+sy=IlQelkIPl zYN*w~_~1)mBCsEr7#s-J0S6yg{cnH!*MAEH7!C9U&kk&gnj{w;0410S%nIfN3xmbL zieMG6KG+a!^Vfg(e_IGVq2LNQ6dVCg0;hs=!3E$-@EdR~co*CVCdxx6)U@w^`#%W; zJ5WGzU^8?D&Vn)KsKded;36;)xCTrNt_SOYA0PO<0J{JGh5%!Mp5V}ZxX&-4)&Wz3 zFMwIWPGDiMFIW*A3DyUvfNd@z=n3va;0Xma;81WEI0-xo&IK=kE5Qu;=mcuPir_}D zHn<6aKo5c)u;GE-&;h1`G480l!T8`WU?T7)m>B#MtOMQ!BRU>vhjI^K$uFZ;KQOG& zbucCPE|?Wu02T(wef)h~S2^Iy1f>psu zU}JDD*a=(-&H~qhJHUuV0v&!5rTFo1wk7WVA9YN^d9&jYVu;Vo)XLoW(D(rg~5_wMX)+pA8d?3U;}{z z*c0pv4h2VplfdcVTyPP%68sii3&webPM{HtkV4P_0R^}hOaop58-bU>QQ%c@33we` z58ePbfhi0Bttf(Ng&+tGFgsvO5xV3AC2*fNqSgjef~~-;U`Mbp*axf#jsWZb^ZxaJ z3j!M`$OC(VtHGh*r{E;;2sjr!53U5$m7)`<11k$&r!#LDZzKZtl)gGFt{45 z2<`;yKZpH)5CR)0cn9_buYyCtIOXU7lfcyATrfMh5^Msl1qXo}pTl!~3XP^pJ1Z#qwz&c(}P*TtYBfV5Lgkc@YjF$e|-pap}+=g3HAiLgG0d~;3V)(a4t9(TnT;+t_5%J z```ZG2mxLVI-@2q0eA;|_`s{^3Y-CBzN5Yd#s}wtiNK{`VsJ$b?EkS4)IdSd546KI zFlHU~&Vlg-|9$_iR10?j_#BuOYylPqyMh(Lfwi#z>q8I=1vcPxuqU_(913m%CxM@X zbHQ)Hm0+?ubilP>Q3QfU2o%6gU?s5BA#}!SV17c>QD9+k16T|^eQnDn76T`N)xf!66L2Ls7F;VRh<^WH4nZRnG=ZDIEnq1jbjBTEei77| z$LN5C!K7d*Fg;ii%mLOELC_9PL7)!>ieNLa9@qwK33dUyf<3`k!2#fSa40wn9E(8k z2!bSVBX}G<0G>3@i$^0V{xAz}jF>u-!lJ zUw;7*_(4G^_$D|O{1BW3ZUtw6Ux9PMAHhZ7EpR26sC9n=fA{}J2x$KXe=URF1svcG zuo$=(ta@NMwEi4;5Nvl~1+?88JPr=u_rLvr7J_srSOPx+uY%ja+u%_!<}`YO&tM`j zK^rV zr2&?IJurfO;A6D-z}XCFy$qP23AGNG2GV%LM%9;={UcI zE>p!q>k_mkrHB0%VnJx1qMrtKln5O)X%lKLu-FUKqTr&}sFlFI?@*rwtAZWCwasX| z7dYq*>PXb-EIUF~c#M>64Z}M^t+=>SgXy>SgcNXFsM25W2?-*x>gc2&k)p%PkVRb! z_EbdO33hmZc0UfTB}4rQyqbb~51cTC-U(D>X#e_EXuBY41hYec1`1FxRe;(6Oi7H| z37icl3|)>`=zJz)qG$o)p043-*2oe$0! zN8JcEg8D%)V?BC;IdA|>=;uMZF4|78KO5xljCc;A!Lfb(b$>i+X)t3fY6CDo2DJ@X zH43#4IQu^87;x7HI^Znu@*T9jl4Ad*&3=ZVhoBP*+_KSvQSed`+QB4P^ELW8l5=1p zUbOu)c%2XR53ni^Y8*;*f~;T)%Ki1Q4% zXnil3^$2QY0s;sknXA`2g*9NDe?FhyK zf>jcQuMM}1v5fB9xb|J!h2{v1$g8(I-uiV zjytINz}rX`8puP?57q!1Q2Ous(En4eSF>1n+=z!7bn#FhcqjeN;9x0jNHNkdZBCt1D3LN>*``2ITGxUU+P{0#|x)dx2&jVH9&{(v+>7X4pqbJ~{ zezbi6ybK?bJOR!aL05eFum8TaCj(wMu0esA2s&fJqv(TbmJjtYa3n9R2w0T|wIo=R z3$;4flNGfE*zE*rhkgIs|8+Rg;PSx@cn|%%EVIEKLa3jCeY8>kIB3^L%|wR|Sjrjo z8E}FdY9H|2D!KyK=wSaJfglnJvSItZ32uZX&Ia#5{X=j+++|H*;XL#%=myK>qMiWL zg1^$i{_g|9A1D|BlhUIznkqm$U&AP2z&x+LKT z9ehB22OKnsx*WU;528*m={vOj4LIpN>P0aAH0lj-(HLsv&@ps|80dfoY&nA#uzR043Uf8I1Yszx#g#1TIu)K{|L9ZcqX?gSUUTgJ+?B_^yhnZw7?`l({r|Bpc6hM-Ht3a)&FnjhR4gjy2JT8UZ}oC}{#ehwV4 zf!>AIVA^fe?qJFW*#83{=xRVai~}ctv%uSpXnQHR5!?;@}x9!!M5h#euI z??gNF0x!doBH&yYP$IYp2Al;}g(WTocQvE^)q)kDpzZ)8lw0VMynvtsW;g~`h23%S zpaXajx(%l7K|4IegsxaAEb-9;x1;UcVA599(x?%PWg8l3L%|^I|K?zP7@#AV=r=lG zZ!rBY)M4OlXul37g%wT%d%|9l|Iho^pQkrEfHEjh^+DYTc5z4D4c3JEG4P-p+CB?r zg!*q_%FAf`F1S|}eWD^`-e0l5-~Y2JqXEm`VBfW&=nVwHv%#q458AJx)&W<-3lwv3 zF4!3?2KD~nZ4vbL5&QnP|3?a=!A&TreTX^}JXeJJJ~$x^brCo>0(I@d?ZKS~_23r= z?eHS@HS_-S-~NR0_n!p+eZAW+_<#Kk%ez=6W%+MC8wgD8gJm8p%VGH}mhG|ZgXKspBe$@E94uF3xeLn^SpJM<4BLMv z$nakyn3MkvFdA5Pz_KrvuVc9w%g?a<=0D#5ShuD0Pqe};2=R&k4wM$lY^eYKc>3R$ zIF{A1d=|@QSa$fY?J!sV8(<=_oQ~!DST4nK1D2npe>x(}LN$UF&!rzbD$K&RgB9bk z|67j#oi1^@`F!cSrE%oSe8eiseq!|2vOf zEWgC^D3;&;$LY~@!qg&5|H<}$GXcw6SpJjVM<>i8LdNmmC8fpkaV)c?AEOs$Q4+$6 zC9!-O%Q{##O24?@4dR9s2Vyx4%ZXS{!SWp}=VQ6#zgEW7{x`t1VEHAMN3lGeZhlOd z1?O9O;Qk-T9#$(M=YJQM9LqFVK8|HkENf!f=D$|Pc>g!RL|{1u%Y|5OP1j=Bzjr6F z;tyC}!tx51H`1H-yRjwY`tS6~uzUo|Oju^eG9Q*j)1{B^uevH$tcPV2EL&sQ3CkW> z_Q7)Ke~n;b{~KVEu$+PATr5Aray6FQvE2I~)9n8a?tg;)&)Q2jXB1|+@Chs4!tx%L z4{>ANUs$I7kJDw?gm0zmvk0?tYH;qq7j*y7+CR?hAKLqe{{CUGe;Do`M*D|xx(JIf zOL{+(uvt10t1xT2Dzoq^Q{#S1)Bf>z|7hMnTK13D{iALFXiu;Ddkaq%VR{_x^e84_ zmP7y75sp>E0E_Thoc~V`(rm&h|Hc^8&nDc^&n7ZRN@DHpW9#E>?dpBmBPK~uWdAs| ze~9iMVhu@x;_E^r&erxm0oHbIjvfvTVHd<3Dbtrc#HrF{J;X`UuX>8pHRxX!FHj+O zbhfs&_xV?Af7!cXty;X3S8+f5dt-ZywKe?J;i5Z=zr}V}9BnW8xLmpH>+ItFf3d&2 zwWHrfdml%K^n@94mGr06;{ECEGvaxt_qU{9Go&5+AFg+9|E~vo6zzVtzkRr!#^CP1 zP{rN<4}-DZKg{-z{VzOgjQDI4D=vmKUBrN!6JhhpMjJ3VjvmfeY~3-BIDZ@xIIZf+F5`SD?$zN{D#m5A1Ai|}J4 z#5QNflW*ObFFt_ARVmJ-skTb?ZJNUgH_sqG=~b6A_@~8(Zn&`-Oo*J%EwUeCc)du+ z#4YXi899gfB^1!z)x2dnAFdF9`)Dtx1ZVx>i?Er&r{?w{*I!RpiJPYH#wXsEe*Gnz z>|<9s2cvZNF^jbYV?FVkN7-(fkV`S?c_DG6OH{#m1Cc>PiU{p*|DexE#3oU)ieEhb z*v_|3#*_D7R0Wv}s}^_bK5yK_z3T9JqYTkpSWCGs=V5%@ZoaSbMxAwF^KY*p5r=Sf zN=aGd&%J8z92Lc&O5=)4nizbGBN6wB_TPL z?F6EQh{Q*xiB`iu1aY(Q;v=HusRVU>oC$8beGHG|W_S9*;@z!P;CDMs=P}c~kwU*h z%M&Ti3}ofwD|SkGfsCJY5vN(tEtrvKAUv*d;?*~PXZC!2=2O1;+^-d0czwRaX=K{`6$6nzH`NGZ&JDa#;^o`$n z-c37+(WTwXNz{Exq;@p>S@1I07NV=i_p(9p3wsN$x7GnvVzsQY_9&q?aTj z?(UvxSNboKpMAF8@d@+zjJ?;T8}BK@%J?e3cS;`qwUs;Tt z2lCg(A8U3XM=73hP-*8q36@Fg;AG6y3DH61o;|W1+_9}X+{7djbN6z<+MjdIK3N{| zBv(8eOp8+_Gd~y%SlRz7R^83SB-nP}&2c=;Z1IGYVcpKw;l&KS!S0xu#|P6R4IJ!! zfs+Qgn`(D%JkzCGEeM=-@iF{NM13Lhgz9mUfv+Tt@k;nVj0-WBqvtbM={#Pyz2vV? z#X}U|;1Bz*4Fpb-Q!wg>+!af!kV?XcJgR(?`F$=|HppHiM$q} z>($~3Y$K;~N1iLRy}x|lKlj4*K>o43`^gdhwe_~Hp1yXgJ8eO?UVX@`A&a0tIx$}E z?tSLnEQ!*!tdG4_Ato({^zX!y+;0`(>x(ZXMP7`X`-acS5sl6MQ0=s>`Tl`7u}i|Q zOl@{8{(8yxiSuDy?~Ln@-AuWtQtXq@X037mIO!Zkm8aO1q$i#?UW>YZyT6d7 zX3d+9%-m=$JHg6Jtw7Mw_`+&HhKWQ-*JB`0kDuog=j4DBuKQHd<1;%^Y>$c#?LOG6 zd-{<#?yLASuhQl_&F`N`i$)TixD<2e+C|v`_q(U(L>TXT3)Fpa6|VE^eZ&3zsoXZt z`I51h`mPhlOTPU`)XRSJ&A0E5KgSj==Yrx~ehJ$cl5#iaT{ymzNx|lv#7dBFPN#V{ zt?H7PUDn834rd?Ho4-D4Fp%5GOwe2m_;xJwwzxC@%J0Lq;iq+YQdB0S7*p_^n`6$1 zm5wE@_0zUiKewiG*l3DZDwz+PP3=f8s#ZVlcWp}l1+8ebGf$Tl4e}bNv|Zq~;RfMp zAI>*STx5u5v|#khDd#~I%;Bn6*Y*0SG?lVP7Egp&I6wN8P=No1Urv`cJ#?YM=k;BR zlEK1(sbdoF7Qg9mcra^ad2Yqasms@-bCa5U{$W)2gU=-ACheXY?Te9^0xy?0Gkv7# z$6XV~v%<8DWsjIWIe%FGb&dK{n&PF&BFaCiHUgjTmLMEEE_+P(lErDBmOuTt5~X|S zw=`#>r1*9Bq2@Ov`JQ3PBif5IlxGd{-iUiCuyc3#w$~HfT>qocWShG3!r9EDNGeZ@ z>1X1iRD2)Xs4}kN2J!GLrS9$g*7Ef~g?B1R>AzkodvQ3M*6sPE@zl&8)vEfJH|zNV zu0;)W^OKsnA^dZNr&6ys-w#R&HrHF1LLFlDHY;Oql1w8=uh`E!l2;5nwyZN6rRVOM z9&xg7*RW*IAbxY2o%%(d4KI;vj)jjdZOZ*TD;{yU+e!1miuM_R} zRp8d>qx{Bn#$4QfrRz`K%^4%kyZnsy#3Ss$(^7G~nSSHNZ6Zc$LaS9%CCj*a>pRa+ z9t{oItJw-fI*_u@nSvK46ikmNEYRbGt8;WD7iTONtQ`qMy6eQf2Y=Haav5;eaO~G@0cW1c|lesSdF%P_A7plNaSY7wTAPr~y&iJBc24Hb`2tp}9URS*}^J&ILLM@@ zttsh;&&S@Sq-)Gy);E4O;!e(SjPy`-!hDzVpzG?MRwiu-M>-An?f(0BmP11_t%4`a z7oI)48$>(1;ggG8_}Zk_#b5FD+ebnKhopsNfwqXJT4L$eZmjypPk!EKu3n%`OvX2v zOd}k9-EvloWbf*&^IpESjU2q8Klv(sF7v509kB@ED{G_mE4&dYMi3_Ss=AwaR`l`- zuVIX5x$?wC8XC_W;_SlMH=c>APrJ97;};cjACQ~t^B=wW3=iQyEB$L)zjML1LiMCO zPZNU-S8&j~mwiL5Ta>0vJ3@bQ6s!$@%uWUh%30Bz=c3JxIpOltp@d7vj)8(#h)lhG z-TQWj|AM>F8F7YevU_+sId>8AYlm><#v>Nqj;nV#FpoF(e)kM2Udm{Qs7=$y4x z&Y)Yax#4ZOAz$|yDT)0ZKWF_zaOB7*i&=(*XXJuNL=*$ZU6a*RhOcuHI}^EoMlyuu zDNC45w2R6g^iTgbbN(WB^IZB;_B4mciq)7+;v-f^;xfafS=BKgHy5IxTVoWj9PT+! zQ4!Mx4kwI9#g_DqH9VJc?9;qg_UE-vJJHgKKrdf3ypA@sJPO3CtvlZ;!}Y(;e^ zZ?CKL9Oc;cC$ksdgjO$Jo$m=q*ruhp;Yl*>Dk^79EVXQF70-HX)H2_IO|PzX`8YQs zR{G`~j#Z(eT&C!q0>t{HOCo=}*)gs_QX8eZ&guKC;Xi2Z@;d4r8Os;e#V28?KEi$U zM=#}`Y?vZXUr-M9({o)VzWT2}+NHitHa=(nmM-u8TjfH}*86-P<3{ggee?@URnJN9 zR4Y^SF~6Aaa@sIoR_$m%&+YLiM9c%sWGm5nflIBjLzZ;(vQux*Bg08@1PN~UGxmQe zquZ#j<54$i8N>oUc%KicuQx z%zS%I1}6xEmiD<{mAxt+-|ia~r>1SU%8vhX{YgcjqQDU78yS(5``tvW8@zHoeayAsK@z$F#P5*-SMbyy$WA&Avt!;A_4{#bc8wKkaB*bXY1N zjzj3}NPI)LM2rTfSxU26%$M)kW}^Mx=kFZ-%^S=!c|B@7hK5sj`7vvL%t|k>0OsM& z^upm@Q4ZVb3O`PRkRGeQDvp7vWoTa6-j2%Z^dgjt1Y>N$pcUK5p=j( zJB)<41iBnji{o6`5nb0#VbH-)*Kr@2%3Sz1bt*$kq}z3;EjNE$g8oszjAL&$^E?|* zLN|_!TDVHk;ZdflAWMh!fI7jqoZ*r3^_+6t$YG7pQ11f&SiKVCcm(PB9{0gPgJe&( zZ{`tq)LkXpAbR2He&sJ|HUYwezth-O+T@%n7{^~qRkDS4J)5o|BbN;5G9Vq<=%Y#e zVDu*PXFLTr$j|gIjH>zUcO4MiKWXP~-`!h1 zJxNRxq{!^e6Cyeq{P7#oigV#eRa|$NqAkBlLgW8X+7-!XY_i6430fk^tAdK3gr;JO zLDSBqoEMKze`@-)jJX>kv6~$w$$@n0lRNbf67|}&;3(d{qBYDAme4OVnv|xJK1~1p$ti9{9N!HbP#-s@d?S<6X$gyQ)i!O`ol@%{LBICI?$qu#itSc^-BTCPjpxg%qsnulNd z2LCRtQv0sc=7ew9Punl|=S+? zTb9e6eendxPuV{=zmnQjxEJ;$Z_$0{c!I`M^Rr8vm#Duih8db%Qon43TqHDd*tvF! zaGbTo58ov}L&Q~hc6H6Z`Qp1UjiLt+mJnU? zBPt<;R7cK7S`T+`h;q%lmC-SEJEuJ0CXhcuy?gG0M#ts5CIUF|5ypL#n(kZaHO70z zP10t|(NFzCuG1&E-{w%=EF(pR)3P=g9{06tF8tahl$kMn63q8@KI3Fp4fXC~#iv6( zXKr2ebPC<%zY%KCVO>9W-A-a7oM}y*wqQXXEF}LRe!d;A4$qnZnqgPFsG>Yfkm1iCJ%ZamZ8Z z&S>@V!vzW)RJW^dQ(c|YlA{(bLT=*8eB@~P?74TXtd`gv15{fStWy?t;!K7VP zl|RLW{GX?EOS;57ib5{`vclz$Kj)p%SIRm?y3*UH%&PGDVK5?pYmL3^gXIHcI4m*C zPNCMjP_{nVf{QhcB~(D>@pUC?8XJ}QBN;nyDLv>-{^zM><`hAn2ALiFwTY_)Ejd&`XHoWvvv2lO=F5new|g2>81=t^n(4n ze+3^odx;}f;mR^++%ztc>oJ+26UY0;j?_~V)1`kt->f6g^VItF?tDDIMNn+rGuhfK z|C-?9xIZ`MhCbGDf2ZnQoS9S}ACNzrLcG9r{2N`s_f?^uhuOsUO1;j^El^%qd(6)+ zNS8pL%^B>hiqSp2#nNYV?@K6V^wk&S)w%fUqEke^;yQ9<6^yLDKEng|NYYI+EPRyQ zES~OChTM~}sWq+*G%uObTd;c?P3)hwCd1*eky7FIbRluVEX30}TSQJK#VO@m$9V7| zrQ46}zI@q=jd-}bW`BksD?GQr3a{rtDeP-)T!{0eq znhBlW8?nFZPn|Vs3x4zM!>Ot7#oxD#E`@56SSm6$v6=5>5e7Xa&ML3BT-ExjWxaYw z`5JrC03CaVuhOH5+lp7iQYvgtiQ^c$BJFA2^;hNH2sC-q$i~(bL@Biz16v19kMHR4 zapcTfQfgh*^;1};^gjJ0DdYW_GNvy>aWw27rxiD?6x-c-lxT~5pVeqp^?v$1zak+m zUz#$m;jOtMvU^hYe%$Ie%U+#+>jEwNAr+NtD@`s;8cq{%MX#imVypd6A!ybHzPI zH=*pw=br_okC)DG&^RCR_q@+#tn1k+i2P3eT^swPu3OR=Z)Wb)UN%Qg)tg3}Fm-n+ z!m;8#!D(xX-2p9+M%=99G#>a`mV1XryGYI}@l{u+KO=lI81cvYePf!}AsI75lGL4+ zMykQv);bQRU1u_f>ql2t?S`*S(mypK)A2BRWAVZ%%AdPF{@hW0H>=mVoQlDImmOk| zLoIuomkU@w=f6eg0{;ThKA(yp(! zmuln!D9r~7?_IzBk@=3Yqm1DL`-G;_)n8v7iZ})?xA`TdYG!+oNxb38>0~(Hu6q8^ z@iNIX!hCVsuNF8N+Mg(mbgZ4*D_x0rwH}BZsoSU~Hl3=K(47rrI*UlK*UBw02>XX# zOMZW4>BSwXOM$KY5*;V{cC8*V<(A*;QGP&VBOp*N*oxECnx=cZ)G#hp-zvU9MyXjV z*Fl|)=MKw9-}a_jlWT&uyoB#=aoaZZOlmpP{bu$Pe*ZIcgo5nLJr6#S@K_4@%GbAS zs*zsY_3nU2hxEhs#Tk>oY#xof%jPnkTxxASSN*Uq`AvfcoA>Q7!NjBa!aCMWLAj@@ zw9T{JO9j>3qK-xD8L;n4aD1sHR^uI0zt^x^zDE(PdU1}tm+fgzO6yG0O3YFDbds_Y zpZ>f*RprKsnLm{-RH5jL?|A;AZI%a& z)lTtQgoN7Y;0>z#P`0Hg)L2e#wpW^5UB3A_*NU+A4&E!C*9v-;{?%Nbul54n9wSDl zW2kcpq-s)gPC2tvmG$Pmw<9_>la_H*R-^fzo*IsE>wHX&sUXuEf(fJ6uGYAi&o&B+ z5w{TazSkmok-PfciXJv2_f7`d)7`04-a9Ae#+4u^Oy=;&9k76FY=A$+20m1xEn=W;^myTh}~_(ok!eFUl~87EaWrlQZd==oN9;-@~M zx7cBi_*$qWG8QL5?GPo&*YiO^&GqU@=C^)!$e<%zn>nf7yG&jwhvqyrM$+9wUaC~g z--M|vgrKkGM(6nS2rFCx+UzDeP5&~3NU6^f23S*kjzkd^_AHMWrp(? zoerzlBe#FPJ4$5!JEL&;eAHMpf0+axyQKTcLze|cB(`>BKm0Lh;nnF8r87hxBs?Eh zc#~gMvaXf5`8oQVi{pKsb{WQ7q!(QL7{0wQ&(lWKSPv_{yZP|pMqb@xYK~8jzl6+~ z?AX^WTUyR}K7UU6)yU&igkarOKOsd+l2^}1m3ey3s$`uh;jRhATt?`rq-r)-v%{8y ze_-;X8H=^7Si-`Nn6KWrVwGt!eyE3bjphFSPaWod?S5D`3P`!6>S z`|QNuD(671ULU>veJDeWB{OL8nDx!u^#ggPR10U{$6Y%2?hDa%91B62G=XPZ36W8) zSr70BdAh?#Jux!j$7zSFazovky&v6|^G%nYIoW%?@KPbzpTbbDQI3ez>Ziw2d1lhq{y*m) zZrO;gul`n3B$sq)i|jl*_SLju+K?r6!SCD8#_nGcUgT$7xpR4U>EZ)vu9hSBU6;=p2X@WN ziyd?I5|j)LMg$B3M?ZuRoH*sbF4HlpF zulJ&9zAM~bsN9WH+%^BP&EFtFP)e28G z$*&tU>%lF*XN%mVPg32w-QP(!ud#NbIEYs@_nHSulLHSqmo@1>qs0*ZD@h2U9T`?1k zC`d}R+XU`?PTnZIb}o>P^p)$b=?LTM<|LmDms)LB8i^u1l6T`x&V&@7uTdk@U!f?V`TF?W85e2vF_3J(EB&N zvfG^wtUADa7mh+}l}d3Uplolx2fXC<@YOW8IiY>`KIy$Np%7%IBZ<s1RA|Ym!e}& zy9A$V2z(Mq&C`87&Y4qUMr~d9;+O#~zmHx?uR6Dl^B6TfS?_0;t$}>qFPxQUFCSHw zSNd@~%%+imyKH28?o`+D`3ZSF^P~JirJ?!M{<`&)g#4a)vdzf6(5cPk*cS5NHwD%3 zB;2>N<|GjT)id(4I`_*kTT}NN1)r?z@iH6nikT>|h=nmSSBw9Wk2}hHoprZ=Ak<8z$@b`5Q=+iB5VI$r-+IqV=g(`r z9E{Lv(dF|c&iuCRihS6uAH=i0veEedXMV${OA#sG(l{&a@4lFzgTv5cZ?e{RT* zYY1Na`dVAH@YV1_7EMdClH0p9TxO?3ggm@&yS_5_y~GTOJu6(3K2 z=Pq`h6Rpl$GoIE|!U=qTlZl5RYHR+P+_!{q&6AY@oQf1ImhLI*^ETmiGX@=d>NH-l zV@LBl*X~)-GhTVEp14DGJ%}`SJ~pnAN4P zF$>GqMj_oEScSG`i^ zQ|tLW7H;A!PL@!ISkz5R(~`L=*ZnHz1a2C17eFNoG{sEznEuj z8iqA+GUpzA((8Zb zU;PD#kv=B)*WpWAQO)b^C5Xer>(Om`CbqJ!gMpr}d?%*(;|M+1T+T=$B@*v*imxi4 zK7Z)9rWIRh^cCqvqVbTlW-f;&`^6i>zfM1l-+Nv@5J#S6aJW*sJyw`DBSJ?pRcx~2 zffV1M#jj6l4~}K;xUk&q)!5d)r*Zn+-s@A{w`baQjWWa+p0FusxJW(?MS|a@h)QI< zd^M#z(eE^7UEHECYA^7olFm?`ZsyG=PYtGrPvqOka2w((HElO1@(SmPoZ`$kwq<jE-N5y+_J&QXPHC~5fRGTz=+%h-X>nmwbowH)ZB$>DU!cSqiylr){ z#q(W_F>gs*3*{N@a4x}vPo+>aITNJoi`HgLBReOSGhizO7c{{<>-i&KRH=CFq zqVptXDDdm8nFj%qZr{Yxo{{k&HxFknny>OUnFQAN*LN!t2_PdsF)_IQ*Rg zqD{l;s;>@u<#pM9>iJ&q&e`R=Y9pBqUKKOtV?nWtdQ4>IOHo~rgJhfYqV2j!lt64QG6QFwV8#&X_ z5Rxpu*jqI`Yw5}UvEbgMa?gsm9#`L4cRoIe`OB9(+QhaSFiKBHGk@ki`L10@O-7*^Se=lct#KleY8bYGf68O=&_00&;>(7l`xfArG zmajCd@~JT-xVa0TymGJ+xC6p3v47jYO5` z`>`+^sh<^e4KPx=A)-z2wJo@r(RbVZM@rj`}&*}=g=+xmhVaI#)n?DGWOexvu z&ZWr8Q~&ImFZ=4CG<2jxM944gYIuB6E^iO+#n8oH`uPmfVae7XOydM?w}?9kn%I7R zx>#4zdxA^*YVoNTivHVG!Q6C(UrsL}R#s8wTzwiVWzmu`;Q<}(Sv*&DeLizfx{_Sp z4ljSlS20{ls=ssZ>sK|Ao5k{k_18(QgfUAaQ~4_{*~Hyv zYLf*T&a|q@M};YT@C-Q5?o2V653}iq8u|-lT@C!5iS%8VOaIK9cSoy>I3gpIIi&rA zz?6zB<4=m_`_-#L4UyC15um@bw3MXK%{_ufdY4;n$Ql_y)@n<~AbAxFFd`=Grre zzjy>q^W7)S$C$1d*c$~s%<-CuoP0zcZJ8uW9Qbj$s4%4#hvlk6@*Q>;ElQtZ7n8iO zOeeO?pznhs^l^LHVP7;~kmGF_?dI|upD$Oco8G+1{Ej{68nKb9h=QhLtkje4BdDt|`Vz&|4M2H&6H%&%dD z?GJ@tq)x#zJ8sS5#7A_`DyFA3>C=keKUDJnaQ+sl`s-**^GE{E=%7oQ#BVzJ6!#+f zkZ2F14}k%OK6jydtb2&P%nM`FD>D+T_LA2AO^jzC72?O2uojklmLqN{@NO8bPPpP>%Z`OQA;tMf z;kEVB8+Qmev$~dztabG%e0@|p?xJtq+?3Kz z_|jVyV=jGq%_ME8KT*+`c^FHgTt}eTv(@=rgP1 zL5?f-;tK8U8^Nk?&AaW~e;z7v{}Ds*=oj-PZ~5~s9uc-x!RsXt@#A@^1}d~G z?tP&v+>t2MNVw9hYrAfMU)4B=XA`qGQ0g^#?4@Q$ZM2d0TOr?McZb8DRMHhK2bwOP zPU4uWYZ(>jSAMwIcZM=(b-Qq6`-a~g!f|=uuwbp;X>xP=>34zkQ9}dDZ;4n!aPuz3 z$sR%s6E`&%cFJ!xeg7$^@$(ab#&LI+lB>mjZ-2-7`5B&W(3&lw9>RZhd&MQ26I1?3 zXO3XfMT39w`G8&wz2VKHdK5$j8Zum8s*@>-meWs94ul%Mk88bFwnbqk?|0>l;BfH| zW*u{ux*@gfkq0fq#60&re||2Ct#MmzIig4IE065<>2XGUH?*KZzN^raNO=5rAJJyT(a4Bd?ACFb{^)5xJ}*2)2ZGjv90EBI-|7gc3H2 zd#^tkM*bLFTl^E4&sootEajET89;K9B_z+D|FTLe>!7GK^*5))kH?)FgOVnCy;?5C z-~A*rxJ4q(>cK@DX<%bIS!jR0#`e|?C9-(t&amZmu9fWmNp%uALDl&hNjm{@!Nk?O z*X?kWKgKF7;Fj_U3DdX5SqwN;-v~VPK+es(5X3*R?9AdFe;@PnsH!fxfF& zXU_@SxBjdUF=1}FM7!LmUi;SIg3(lzRk-Zb>l?XRLu})+oCH#JQ~F&@{j`+5DYHsu z#QGeugh~?W169t>?9NgTGNZO6^^Ta9%XD5;y|@}RErXw?ufj~}>`vS;FAz&sBlXNm z&Z7R?nQsXcC{e?pRoEt8^!%^=pmUj+&h9o1>-#qo33HQt0{G!)gMje|UyEclRwnL5y(hxJ8G1XMj zjF4H7b9&^%Dkk!+rHviouc$H{R_1rm{mGWxWAS+wA^Z{Cb>( zXFm8j%&XB1HIjNVKXzBD!{9R5w^;H_k2}ZYT_sAx|FUu1(f=!pWSnwuleyn9MVz8b zPf76{`VfR;z<%u>DgKR%tL(YRE=X)9t=h_~Mf#~^wtI`RQ`SqSA;WlB6(s>Zh9qgZ$%84wJV{_a6+j zXRn?zHcY)r<)nCrH^{DP;`5hO&q z(3?g$ENo>JBV$>O0mnNv)GyddvaM~lH3{SgIDMxi9ST47ds)XuqCcZ)R%n=h;87lf z$H@-^{G634&dsc>W|oa-1#^ ze}Y}qm295#ERk<`Kes-cXKR)G@X?!%&g27?(Rns|9ik+AifRV(SRIow z$Ng$;mvv4)kIHPY@m#+f#bXp2Xgb+gFq?)9PY{*+!oSsS|4jJ0Lg?zpeN6Cy z`suzmQSxuLHNAd&-WElyS=UTecS9{YyiHC0FaN5LSk&9F(40$u%%fzmb!z{u#WVzt z6#7`uErbYk8ot!6mj^mDBsQC;1}G!*2N49Dt`*zKeunkO=sQii*#}MX z&bxZX8+7X8h%FP>MaQ}n{yAqqQpLkB=kochYU2H;6nbJaoJhl&ykxnyRs&)R6Q5t# z|0kt3TFE%1M}~`XiTJ^5LP10BDMIg4N@BIdbvTf5Ma^{1!BJVPf@pDL_A#FnIEhzH zGV@_4jg6}mq{2a17nNmxKO01otMXz4{6Mu7sjeB|8ewziSWK+ zjFr8sMF3$e$D1j|e;liukQiGb7LSx4YTS0OJ(+Rn?Y+^Ybd=er4Q;BIcv|4n3yLrab(^OeCA$kQc zi7loZS?f;SSyr9&49)7IqksrbR*|eO*kj@IYUQmSF+;R0H&~!EBq|G4d_QQ`cf`PL zN41dWOn5AmMW%IPL8W8vW>7nVf9dQT688W>*nMig(9955Tu*BilA-w|<0B2J`i>LEcbs^tOMx%XsasCmRCjW%y%%I$~FF(6e^6aY-?3yK+4o z2W8UuZCi_0q*ST&=(=n&&nC6Z2#g+?GK5@kew~c-%Jt+djd=X)iJ;8?Y7LqsU5p2J z#qHKHVSc}ZE1TZJd~T4pA;mA7i76aQ3p735sEAL9c;0odptDOud{AW2w4xUht!6Tmaw7b) ztQ0%`doZZq@z_#=3pi`vb*gtatU2cKxz&n?5{tK@F6(++;9%Vi_qK9!+Y{zq?9EfC zj^bHz2&OLruk*s7+!++BwgU=JoSc#7xhby7o#Tst%BAWQ-bJ^LL_3C-I7T9QTt*R0 z43lGstixpH`PgSGi&3m7I#{U=9686VZ;SS4S`Sb7Dm6GOKgSDjM;lrd+DgF8oHJv; zOqIn@FK@F=v@2>LVBb|iskeV?1k8%=H9CjW)=WA)1CTU(wtQjN^t7;(6_54u<895) zulw$Qp(UqWS`5Zfa#UM*a59^z9#mWz44+F)0G`ImHnjAM{P6o|9mfKEK8VKM?OWj$ zHyGp-yBYK=Vv-?+@lJ(^q|7^ru+h4hZielfC9lCyh|#=WFEf^lz*s-%^UTi0vY7Jj zL@xbr0o+`B*yYr#{eFx^TMhRl-{r>t{6xBc{Uu0$Trw=PEr@WaTO>Dp@ptJoMRJK2ydh&rN9k2k-kJeQd$kNpkM{DZ~=? z*hqJsX=~EU8T6*B2rmOi^TLOW%>F9?C>>O}nflwMC>S_$`ED|XJJ=5ZN>#aIx?S0S z7EUkomvxw+FObnp4`zIhOq!(tO*KfS{%I`$d)7i^EomMT`y=q>F z#eBM)(9MYrE~J@?`>eOit=PgMQ#h7LoGB~Cz(J=nrv4xh_M;}JOjTgifd8J#!UpN% z$bWw?&-P35bD6ndLShd(RqIH=sQcz-r=7flvP1?BJN1HSdGL~ln*CZoi5CGv=Pr;v zwfK`qCt~w-2zVJMh z6GwRl5kavdv9;vnOwJw{Q<<4z{zQqPXFvaczZX9b$fB2O83%-`fk`gFOmH5yK5O&8 z8s(-&s7(nKDy*FLi$bF0QB=P<{e^{c**>|-t|1zbW^U662kjb6=&rPXtoKUY^+vKQ zW1ZFxleoIvzs1FGB+UOXX?pO@HZ7J-F^mzkBJ9atXIhXPZs}kTACJ3H3rn2Dy}rzx zM|``X#Pn4klILF7nJsj_-PphD9|8 z+&yo6?oi!h+kEuhO81u5Y4lkysgu(8Wr+&4o-hm67_J&H5*>5*f^m(|JM*;qNEBKT z@rxwP3Gef^sY*C|LH{F{9;%03*o@_P0@}5|Y|@5LtaePNihTorgE19<266f|?p7t3 zXI1?9;Pr9b66i6W;tt?`kLLdR3|$CrQnDk=NH29D7l5#ZuZ-P1|E*|w52h)*=wc&q zO1LC!xhs_x-1NCx$h|~Y|BG{LsKQ0O5JWh3$r&WfNBOILn|J*$xHq>QV0CSnDqY(gVL=m1P6;rA^>P)!G-~wBj;kpgaU%EDSZkLK%=LB)ck2_5|K-Sra!ukONy=k z7-|Gw=-`~VpalX$XM%R7F~vDcCjhDy_m9{*;}-@6JXbKV{`fc+<(h9<(l$C~6z3=_V}TIdy0ynIQN&=a$B^F1e zd-~WymuyLYzwNDLknwrO`hgrnm8Mf9TQ+0vz<{$%cE8yMSXK%G0PXt0OB%iQNj+ht z!Vuo1FAKEJjo6ED0WZWGDz4rm7uHNo$&ghaeXY6@oi+bOj`Bb5v|(Hv;m~<4b34v} zHB7!|z^tJCK_|Ikl?h$G3LYncrZV~Jo^@G{fefR6j}HSyi7b-A(du*0fy90?#s^@Z zAwl(r%k_$kqSLagl}|z_ws0ZrxJY8FX?n`aB}6}1P5HCJC^!?h_gj*QATK6LiW_Lt zjqxf1N`xHAj!QPgE4=ngM}igfhS{8~Ip?9&I81$UfB#(l%BrK1UJy%~F1vLF($b9O zTczrMqJPh|8}CB@{Gy#m&d$=j=|_m_FmTlKXaAzFM8KlEDVm+73r>~1^!ee{T2B)u zF?$Q~k7-LJlZjh{&mEeg6!Az*i?np>l;06shHcMRO z&Oae`>S3eea+e4@s5Z{wZU#^}O>Wd5uLe_Iwqx{csf1v9zMG|I^JQU)||ID3|IR@~B?zB|H^@URPNWA!8TQ*@7|uRd+t;)2%tW`ESWbDh)w5~+h8^l{;e zsmo@ct|)Lh(xxso+TrQx%`-JUi9T>xkJ7I|Kxrg(i?f6xP~Zt(0VL!XktWe>mxn)dXNOr-pRwcABzDlIRG-I+I*ZB)93YoR zL5MdlO~2ued2Sl1sk9|>K!e>IH-DVHrq5&c5@rDk5r5b>tEt#?Q9MLn?l>IlE-Nl? z|6Ms&w~s_EW0H@6-hjNhZUKhdRy3kDkV+R zK}ex``lV0;^H*gd0Mm)D|8qG{T>xcRh}h_p;zXLMX!eE?;NtC|0|*PF;p4#?^kEcZ z1mSVrB99=ymb=o6a{Sb^|){!p+dgQ%{=5ISDBF zgZ1hc9FBUCKUFvOa~j()+xfWrIB_9=8g&SuDt;vJ`~N$>D`G{(e{$*?s9nu<9o&Sm zgP;8A)G{WiX~^luAUCA-P^cm2)5&rg7sWq-e<5U=O4zJL>dwg0?lo&c%Y6zj%K zZ<%Y(u!pz0G0!_Sy%eph%=DI6;yABJbje@Y==~kEnOPK{z&-2RXcDYfK%D@fR<6&8 zOPhmRqEl$~rwQe2l^2Qdoj)6u*H$-8(XA98ePR?^1@(zDOK`HT zuz$Ocr!8WL?iRJQjWFW4a#O7Q9x%SHYSSr+vUV6@Q8e&!;gs=fjzvuOb3pbf$d-&h zmFdvKpR%_UDCYjpBhorN2O9XO$kva-7j!A# z7<`vid+N8IaxVqo<(b2{J9*QV%8Ecdo6;RefazC4Fex)QUMQ#Tmp@f#=S0jsU`86m-ht-IA=7QGkY$BCo-i zAEi!3z&I?+bV6!v7E2!EA#U^F6Hlg&C+2=g~8fV`BE3{52)M>VhUvBg_*H!hT6_0lS$Ne&*P#-l5Hf0_uU53;*7}`Ylh?8NAbJKAM22Ttu}AGFpz4cPh)of+Nu#b}REU825f5kZnK%G=J85Bl3i6 z5(HUL`V#E%g9fDbeDA}PPZuPP&TGS=&&%&u>pMN`Yf$K$BD9Knjwj~Yrd`D)Nr20D zfFeKFcSzB2BAgm@WLS|);=@7gwRA-rQ}WkHMS%!&V&Gydt0wj0A!08dpoa|XB!89y zJhjIq$4#nnaTMR&F3+6b|9|J47joqONHitF?)FN*TkoDajba}!mbwx9bH1+pFSyAv zXMRmmz&@e_SnP|_sC{e)mR3mmh=Wd05@j{yd%!?PV7qtV$;iIFsO=|NPPj*PQ}++( zFM7A`X)cC;i?2zGAc#FS1ZbtjEw3|!<7W8_@ZKTVz(9#y@g8s{@_*&(S{WNCIGrZd zk`K39<9+A9Xa5Yh}SG#^10Ob6a&^eqTm_kYRMo=$TH!)Z} zC{^*%-yQh<$e}0uPZtSz3|H%D7AQ>pd3YVp@F5!28ykIs7wi=H(8m}tr;Q*YZF!%mVaOhv~!?#Tqjm_kw8fE#KrN+nW(0zEwf-cm?ABo>Bt-NJGSCh z$lL`-CG+2KwP?!}n%b8*g67B@yb2V`?HAFa%|Ydi+H;c&5X_UMf&nRojR0={(q>$XB_7%=Ph9}O+Zq+ z#m&gC+ITf}vF9=rB%|>lbNZ@U0$Dghp<1L_Q0kGjjYVwQwuK)v}{+MZA$slu%?Enk!%l01Gj^xlUb6~WCC+g=9aRHgcFs8)= zcW2vwHB0(q2$1!)+GQSjTGlYK#+`-g(EYY8Xg&1$g9xS?7KYMSnvSPNr3NhDlJr_^ z`AlFEi@walW5%a=-iT8^+s|^Y%U$tUYLpP>cweaC!he&QqD`N4V6I)FEFhwaqGpgJ zEjp*dzWepj2Sd{tT3aRM*x*F#0*J0+V7X#3O&Z1nhD%E}6cGG&JRmNiGn1<5Bu?d7#({|?Ds^j@9o zx76{$hdf$_^{yfoWm0Tx!5TzVsUU{qhRSnMgMaa_?XRe46j`DuOV3@6-xSZ2A12vW z4o=5ajPzNh*P&ijmK-`&=7r%G9MgK@V`*41ceNUi2);{=vZUMTp^)Tuy|L<6Zx4h;q+S@J^Fdnkn0OB7~A#D(KsJ>n#L@<*+Bo{2Y4$sm|RwE4R zaXzQ}@~_Q@R0r%nhCaxkKa9@}2F^{W6@MI)5(l4z1$nQxElz8?b(S@YG!KFB+zvv` zOi-k^2DJPN0uJOY75U=CY~qq-m*Oh_Xiqg{PLUgH!8dxY!l3=ermcgBc!j~?J=^-T zayH)+x`FU)&Mh_LUjKzzl39z?P;Y{_>rorqns@0hPltDb%xJnAy87a1&6zerFMm6* z6#j<-I(4Z~|3<$5jbJ;Muu6^A1`tviJo;vwjvTz|K(J_nmpV=Ahj{i~nHsPs63dl= z*hgBt`Yx^oUXPQ4X1<>cBsRkt8I&Y7Wy5WR^$zJ>yf<`!I&CCllryJYo8;p^rGCTw zy1S47e=XNu``pPpL95?nyiz7rV~gkM6#9{tzpp0sZ3 zcCnrbSH!T1VK&jRwJH8UiDt9?J76!0DKp6`Og6eJu|iLO&%UIR^vneUXn%F5g7J>M^280+EV)#|RiFUEhR59BY?-=9T_q=2O6LA1BWC4(EDQIMx0}&OwKhRWsdY zpH)-dJtpmm-UG{%9czdu8Gm+(`j`3AoQ~ttow(Sok*i_S5)ecca!)<>HSxgAf(kbw zG;tr0=aV@y*|D!opJjrfaR^CAjr4S+$Duq55X?v?xoR?5bl*v5Dl-heK-2c?3EaZH zLmrQrIv$K9{@_w~f|6&A_L|fe0SO8>)DpBJr1oy^*mjkalMgbk8h=zL_i=1-zP+f? zL$zrAfhpRSC4b8E$;aNH_r>7Py4h4Biq|D@*3SE3L(S}4=-a!{Tb78a8O6cXwAY!# z6mT(<#JiRna_OC=B>eaF#$<3-K2LV&%y*KV9E^%bB{+X4A1k7 z3p({;u8+YGcNSlgGk+k%+5rSX>4}NJaPRwN^US!fF3@o`KRay%*WT4-a=;5{`@8K) zq{f7D>@gR#db9fbOysrjgdOI2^2z8NPXC@DXVdHD*Wv%RP@-;DT_`v#3kA#f|1TGJRvzi#MbhL&3`wOSD^*0YxTSFidg9@ zR4>V?{4@~Ki@q;zgy{(;WjoN#UPLII;N#h|k))tNuy z9A1>aXVd>dbyn6mrLt~Av)0T)-?4JAM7=^@v}R@W7Tej>f7qH`6zW*QZeO6>Nz&IY|2P52=;m_SWsY%bP)k8Ji-IXIS7xWEq{abciDCbUV};AT`hptShFs} zK<+f>X~|>5sQVYkzG@d=S8-ZNs3YtJqyqMvxLz;K9u0IL6g>lm)Zyxed`agl~PbfQ8kI4Vp0-@Fi za8l6k@a^v!oSDVtyZNidtKBhYFTip-=`~X*1X+r|v0)cEb6;@g7W4|bPI_TnWrwYyRhTLu(t80THEfKiJg_)1 zVq0)E?5OeKnh8YKZ|4CLez?=U!{+L4oU4(G@Db!oRle;e43F?RiM7Tgq5l#H`Ik6t zG(b^dkywr?TPeN1Fa-LI;V)OSOUs2680UHS8DFL|#lHZowesCneD!t-8f~-|*ht^k%yXThAH4$us-yM)w7_Oo!GBc? z%Fh=e)oTx3eRP#lotFZAovPz-+-XM#mf6Ig=^c$^nF7@{#eeQDl6kNZlc*YTyW5zZ z>$phnPZ)8LF;EZB=c>vKF`c}<`!iRcp?Yh!fMrT`xVkxH;jMyGf1_kY`bMhR3W@vWk__IFJs!&HMk5l300rYAw$zo1c+ z4O4&boOb1j3kr`pC_0A0X{x1+4rx@|pyZoP&SU>84d1wKIHBupCk01T|giFyDd?cPTe(WeG}1JS=6xPNNnt&5g@ z%UMgI83+2>P`FyQ`sjjd0Gr)NrzpXus{mpTV#t8NFcy4cSP}yHAKna{fQzlTkn4bS zUW~fWisg0P82~c&Aq5psXy%t^?vl%^A33Pu@HR4X^MWGkL+;5YJjqon3g)DyP&SZd$-|FJR{o)nYMN&19S zMNkg;N=~=)7S9+NLg8Nv;J~T`aNhPF806>Q2C2gyf659NB|@!5FTazpq$VXf>%`7I z%ax15w9UE??pITl+)%Dhpd_*O-==anpGegLBa)GtS+jJ5K)V>6;D45Jc*2kmkGAjD z6_9)HCEyG!kkUUWk|Ow|zp6PFet00|-*y|C!GLQK)nsNI=v%+}2s$ZOigi%T#1cXp zMHm~h=A5uU(cNR02OBgS)bj`vKon{_Y3(xrpR%T))C76)4z8HF9*+m2DdW+T(C+t2 zNsJfGFf4kQFph11gnw0_xYe8gwJm>%RgLH)M z>x^xlCRkk_LkMCU%HOKzzC`?W^Vyuz#g|vv1yOL9gFbXhsPjdQ1=> zU`~J>oepZw{VHCy)b=sZY_zCmB_QH`vojBoz7cRhMeu=Op#xyYizJ-=;53^gwQx8IN@be$TrHWJ6?*nMkX3_s#oQWA_E`W5k?Bl-+&K!9eEVXqG}{9s|-BQ4N~{wz;&$ z8QOCFAY1Um!~cKGXLwgP9<7;^{6{9s_}B#pBu?$a7c9gibBnsRjZQjHk#2y~0} z(fTAp!Dnyot9AZq%=_e-u%=-dQ-3aUwBqU%JBV8M`ycGp+7%1XY8)?8b&C>M zl?p6fsv|jXu2Xf(rsU#j-u(PoBJ8_OBzTiEk8U&P}TSdp7OAM<%7tU zqHFY5T3exvFWkD)L#!9aM+Bbtrj4Sq-QqikB%)3`Gz}y;e|ohPS-Tddwnz4AaqR1D zj!J_w4(T_jzOo8J{%6U0K^fowd&HZqaRInoG^%-LjW&q<-*k9-y1{P`w7$7Zfra9xGxu5Ds$RiCCI#K&`bwqm<#B z2VGJ}O2xgVLF*<9TvC{Cuzu0f6ardm3DPcbaW9zks!S8Zk7PE4Uj zgKA~1f2^`tZ^r3nzy#OP(Nb#yPgn*2e6)Oeh1$J~NQo?`N$6zDt3<8pNmvc2X zKp>oEkrxpzW+5XaA%_5WyfS3oj3w*q@4bJ`7q&l`r4yHPHa6fOmd|tCbysoRMD<}- zEwx>h6#A;j1`L=QM6DwaUB-OJmvc5Y;2_3C2xE3uz=@4`x<8R6p;nKn+bWEBwXI}6 z>t^?3h2)oWHa6fO9CpkoZ!MJLHA3f)6y>-SGb347MJutN6WRx1f?m(+}<64`l&?A@gIX1w5eOUj?Tc@MN7+sD2wiE8K zj#toVdZ++3mu4zGr!X-uV&}J(8Iq)e;7=;s?8b0LCBDTH!KCAoBEEA5zykYUzi;u2 z5r&GjXrR4d5ei*#$>4gZ&zqvM|=Y`uBw#DqI90>3Q=7 zlCDuRGV~^=0FUHH?ZsR2a^RYcw7Oo`M!Qpg)-KKB?ApE;l-iIujmgu-`raK(`J5=W z&IYc{h<{oaaof=2PD)$Gue%)vQ>^D5_ho7?j2y)Nf~*s=hN3yPVF;5jFzoTxP?mp` zccyfa**NX%yGy4lBzePUhI(v$6GKwKHXnq(2AMC@F@A9Z@Sq&FYeYg*hz>t~qIHaa zC+5>C;%ruO#I}H0Ytx*Y%xC+P9GrL9Fvr4m_F$Az4SUq%ADcVY-GKrCDR~Oh&7-JI zY{n04z{n1Trks=tym*XKL6C5F5-+8GkL(tDA^^;t+Bw8jg_#dj3ghRAKz3)?VY}Jn zE_wzLcOKX|r=u{VoP@`#5Dg@U3)FUhDIW6%jEhc_uh32i{i}6$^^uXAWJ#*ahXrE$ z$?;3@9e9$HN7!?@3+2UDUWxl%&*rOBG+q(i6s{CD`0v3MX4rB?tT^a_>Fbi$-b>de z!Dsu(@5*K@(`5)vUbZU$8k@uY;9IUce*84pH^cm$ZCpfg7WFK_yX3r-d$wEIcW6~(PnV})B?w+!gr z;TDao4ZS}6iB%&^(u+k}60)j)v}3D?RNxoQ-?2?Q?yqluIhaL-ou2`0DR&ZRX&k%; zJf+d3!rB|+?qz8#?YeZq3o7z6*k5*pi2;w^qB2uU=x8v`JFfR&)wmhFx9g_QJLmPK zU=MKvAg|agxX$c1OF0x2lR5A}4Kcq=54`9rbdMA32(&Mp-POCYtu%6f$2yQ(njReW zBx2tp)RF2}zFbOSy=M+$pG(w#(IuPM#Kx$T;I~D;Mo)M#;EYB`wKyEPr@Xyvq&o6M zQ1dhnBTpUmx7R9`kOE?jUS7a{x9t+wu|4Bj_D_LEH06&{aW8Gm0}_^~1eEf2mFn6U z{D#1Ko=yOtG3t}dg_%`V$0dQJCvngVut_XyP%Lj$f&93r%ZxQVNHh|_k>$b8!U$km#E0cH)zOea`CVlp-T z)`we}v^0!gUL-vHioW-eiXu$wz7tjB*m{FiH6qqUbs)U#D{jW+K_l{J19MVMv=jm> zUa{#)j2aUYuoLvdsKox8ijXa@#2(*OEEJ{$F)#jSQ1-PlrU`E(KX2Q|` zz{VQ*fK0@_aOkCf(mj%ItcvtR^->y?g%Q8m&9)7te|Q-LxAjII{IT^%mOGaJU~a>s z!H4Sy*|TFRQOI6?_Su6dr5gM(+{Ll2XLZn~S&~9KuFCmGI)4oaJmxSA9B)5K>fp=jSP!~-U_3k8ixogNUwguP(7uCaudu) zha3x&g6-gct5Yh6Z%9juaT9;v)EgwA&FuamJ(|GG0stXg5$V7+yEBIbut-~9P^04t z7?{gBj#u#2Je4h##QI)`x+UWASz8|tZGH`*Tr`$`lJ~i^-^r(XR@*IJGdGI|n8a;f zD?F%xwz^W-WghyvDS555kV_)_L=#t5YW+Svr#)$ZlR=3{O5rLP{y$YU1$P~>8oNw85fQa?7SGNURTy1vq) zAKwXLaDjh)8d;%VXAOmv#p@8o)x(X6g2YqSF+@jpC7`S@N^U=X$fT&SoP9@_iYV59 z0BTQIDd<02T%hc(*riYOpD8J|#%ZtphDPTt7dS;mW^l1myJ;KnxxZ zN{^Kj8#db@2Y+h1^(9fleICnTNa}ZgpK#lIc`o10j?H%So%;d<9SM z@04Y~V$K123zE|jkN&Qb)DsmMq;M;b=6{$EYB_pn0|2FS^8 zDenCZGa6pu93WCO|E3cHmm*!@7ffqsf=KW;C`Ke;Sm56vx;UCrSoic14KJ^MLD5%2 zp46bSY(e<;;A?Bcd)8t`i8BdVbni%oh?K4UBzD_b`0SQuc@2R`$sWSNOMQQ?j4$R!={fI8bM_xU5$0fd)+gtwI)VizBIz;jydlK~$K=d_u3hMUhnjE1 z&n0fRW`Lh-lIxo0j;Au9;T^Nt;VfFAmALVd!p)`szFWzHz~20VDY9EcCeR~?5&+t_ z^~LnFozJ-ZmW?{gx_&f&UacGRPdfZz1VdPNHkOiREE{`;^>L=c_ zgBsHF=(5@>#6t_Uj_o3%+Evzj>uuH@`$F}wTIa*QcQ*H94A8_VDEG9f@a!|o+bxpe zxI-ImBd3t;$V+Y-)y(~}R#t@T^wUPHA@I<7)2M_##fc03SjOmooXMCOH|!U$(+M#l z&+j6ov^If$?-}GsI*1fdJT>uv!Gb-A@7BPNsLY8k4rX2fgYRCv!J+azLB$^zWxu@1 zt?x(>VAlj0ZJB+M?lX^g5Lz3*@@0$ko}J-5Nrc3hhuR5zi3PKxSglpmz;5}z2;Z#> zvz(GLoU;_ByWeVm(o_u zm|7nZx5sK$OT#h6BJV%ZUIubI#>5d1*=1r&g4-{LaKcwo?#E{zK0Z>}Lty0uxx|F$ zI<1yuHacOptT6eOYg6@z5}p!o9pLt|DQe>=1t3LC=^o>MAG}yj_U?8b2gd;otA6hB zKTv==!%vH~l4e2~{jplnZ65LxlKh+n1^&?r;E!e=B2%=_TjG2uUjsEvrUio3g@l?(n==dT;4q_jGpfozq(8p6 z`3B8EJ?80ut-skT0X1TS1@$;<ZXH}`ol6?r^iB3Z3*(^-WMZJH#YJPh=qrN zYHjX159%Cb$q9FJbgYW1NEjADp<=hlSCht9O8GUXAJPOB)p8a;6S3z@RvW8!nCv?F zp%WQU%5>eq@5Ap1K3e)k6geF>=!yByjl3F3zPb4NW6a4lKi5T&*9 zY=(F?N?8F;UR4VZ2@_(HUB3J~>f(fX3QQSI9-np-|8foW%5Z~sig0>BzLjb-IIU{{ zS)rDHcwVn*RXzrH)A3Al*fcUxy8Y7O0O^0NXKuh&A12(<7ApNWOQiyxSXJy8>J^V? z1;$u~sbU!8xtzX@Gymn+JqY*m_^2P{f1T-cgd=i zRaQl=rUf8`L(;)TKT`nI2f^5xxcK&n46c4Vr{F-mnXMt|VESzNtr*FF zr*XqrZ<$nBhgAP6jhl?yZ~dT&SbI=@P}KZ1?~;0{LT`FQ@Eb@Doo={!pi7O94$#Jb z5_5BaoJwQU;KNTBZiqA72Cjn^PG``eh-8TwerX09A7fEdx-#;2>1YOH_nIs%%-rvN%Vuk>zv zxt+OX?*DMg#NN;jiY85{_$=^g?qk6Q2Mc@?dXS+%^D)&cu@2(6wT$~*!6~bMnyR0B zklqtJ9&-i}En7^N20+^ptR+?Lm=w*3&9(dL0Q_+N7@gommS*Omm_N!rKHsJNwubBX zsiXxslrV8q^TwkR>U*|=wGxFG(~=D&j;PY8sjj~uIZZOzy1hm36|yK^{F7mt5ncUp ziC#Ou^bO7AX7Jw9ezaL*EOQ$t$oduzwn{e2y@p}&1({?DFwxsu1-%mK??`8RBDB3i K=`jER0000osqBvc delta 394386 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�F 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

^h8a+9MLz>qc08Jtu8k>5pPux;{I`PHo}TzTaT0 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\S_?KkBVt64Ux` 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 diff --git a/lang/releases/v1.0.0-20260501/el_runtime.c b/lang/releases/v1.0.0-20260501/el_runtime.c index 5d6ad3f..eb74eeb 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.c +++ b/lang/releases/v1.0.0-20260501/el_runtime.c @@ -6022,10 +6022,17 @@ static int64_t _eg_embed_breaker_until = 0; * The executive-filter pathologies this system has repeatedly debugged by * inference (WM flooded with breakthrough-floor nodes, silent cap evictions, * embedder wedged behind the breaker) were all invisible: no ISE, no stats - * field. These per-call counters record what the LAST engram_activate did; - * engram_act_stats_json() exposes them so the soul heartbeat can emit them. */ -static int64_t _eg_act_breakthroughs = 0; /* forced promotions at the floor */ -static int64_t _eg_act_wm_evicted = 0; /* Pass 4 over-cap evictions */ + * field. engram_act_stats_json() exposes them so the soul heartbeat can emit + * them. + * + * CUMULATIVE CONTRACT (2026-07-31 self-review): these are monotonic totals + * for the process lifetime, like pulse/sync_added_total — NOT per-call. The + * original per-call reset meant engram_act_stats_json only reported the LAST + * activate call, and the 60s heartbeat (2 curiosity activates per 30s in + * between) missed nearly every eviction/breakthrough event. Consumers wanting + * rates keep the previous reading and diff. Restart legitimately resets to 0. */ +static int64_t _eg_act_breakthroughs = 0; /* forced promotions at the floor, cumulative */ +static int64_t _eg_act_wm_evicted = 0; /* Pass 4 over-cap evictions, cumulative */ static int64_t engram_now_ms(void); /* defined in the store section below */ @@ -6724,7 +6731,7 @@ static el_val_t engram_node_to_map(const EngramNode* n) { /* (Node JSON serialization is provided by `engram_emit_node_json` further * down in the persistence section — reused by the *_json builtins below.) */ -static void engram_emit_node_json(JsonBuf* b, const EngramNode* n); +static void engram_emit_node_json(JsonBuf* b, const EngramNode* n, int include_emb); static void engram_emit_edge_json(JsonBuf* b, const EngramEdge* e); /* Salience may arrive either as a float bit-pattern or as a small integer @@ -7659,9 +7666,11 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { int64_t now_ms = engram_now_ms(); - /* Reset per-call observability counters (2026-07-27). */ - _eg_act_breakthroughs = 0; - _eg_act_wm_evicted = 0; + /* Observability counters: _eg_act_breakthroughs/_eg_act_wm_evicted are + * CUMULATIVE for the process lifetime and intentionally NOT reset here + * (2026-07-31 self-review — the old per-call reset made the 60s heartbeat + * miss nearly all events between beats; see the definition site). + * ctx_cos stays per-call: it is a gauge of THIS query vs the centroid. */ _eg_act_ctx_cos = -2.0; /* ── Embedding backfill + query embedding (2026-07-24, bl-b2d1c944) ── @@ -8411,7 +8420,13 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { /* ── Engram persistence (JSON snapshot) ─────────────────────────────────── */ -static void engram_emit_node_json(JsonBuf* b, const EngramNode* n) { +/* include_emb (2026-07-31 self-review): the ~5.7KB "emb" vector belongs ONLY + * in persistence/replication output (engram_save → snapshot.json, which also + * backs /api/sync and /api/edges via scratch exports). Consumer read routes + * (/api/nodes, /api/search, activation results, neighbors, compiled context) + * were shipping it on every node — responses 10-50x oversized, blowing MCP + * token limits. Pass include_emb=1 only from engram_save. */ +static void engram_emit_node_json(JsonBuf* b, const EngramNode* n, int include_emb) { jb_putc(b, '{'); jb_puts(b, "\"id\":"); jb_emit_escaped(b, n->id ? n->id : ""); jb_puts(b, ",\"content\":"); jb_emit_escaped(b, n->content ? n->content : ""); @@ -8454,7 +8469,7 @@ static void engram_emit_node_json(JsonBuf* b, const EngramNode* n) { * insensitive to 4-sig-fig rounding, and this keeps snapshot bloat to * ~5KB per embedded node without a base64 codec. Absent field = not * embedded; the lazy backfill re-embeds eventually if dropped. */ - if (n->emb && n->emb_dim > 0) { + if (include_emb && n->emb && n->emb_dim > 0) { jb_puts(b, ",\"emb\":\""); for (int32_t j = 0; j < n->emb_dim; j++) { snprintf(tmp, sizeof(tmp), "%s%.4g", j ? "," : "", @@ -8492,7 +8507,7 @@ el_val_t engram_save(el_val_t path) { jb_puts(&b, "{\"nodes\":["); for (int64_t i = 0; i < g->node_count; i++) { if (i > 0) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[i]); + engram_emit_node_json(&b, &g->nodes[i], 1); } jb_puts(&b, "],\"edges\":["); for (int64_t i = 0; i < g->edge_count; i++) { @@ -9025,7 +9040,7 @@ el_val_t engram_get_node_json(el_val_t id) { EngramNode* n = engram_find_node(sid); if (!n) return el_wrap_str(el_strdup("{}")); JsonBuf b; jb_init(&b); - engram_emit_node_json(&b, n); + engram_emit_node_json(&b, n, 0); return el_wrap_str(b.buf); } @@ -9050,7 +9065,7 @@ el_val_t engram_get_node_by_label(el_val_t label) { EngramNode* n = &g->nodes[i]; if (n->label && strcmp(n->label, lbl) == 0) { JsonBuf b; jb_init(&b); - engram_emit_node_json(&b, n); + engram_emit_node_json(&b, n, 0); return el_wrap_str(b.buf); } } @@ -9091,7 +9106,7 @@ el_val_t engram_search_json(el_val_t query, el_val_t limit) { int64_t end = nhits < lim ? nhits : lim; for (int64_t k = 0; k < end; k++) { if (!first) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[hits[k].idx]); + engram_emit_node_json(&b, &g->nodes[hits[k].idx], 0); first = 0; } free(hits); @@ -9123,7 +9138,7 @@ el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset) { int first = 1; for (int64_t i = off; i < end; i++) { if (!first) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[idx[i]]); + engram_emit_node_json(&b, &g->nodes[idx[i]], 0); first = 0; } free(idx); @@ -9160,7 +9175,7 @@ el_val_t engram_scan_nodes_by_type_json(el_val_t type_v, el_val_t limit, el_val_ int first = 1; for (int64_t i = off; i < end; i++) { if (!first) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[idx[i]]); + engram_emit_node_json(&b, &g->nodes[idx[i]], 0); first = 0; } free(idx); @@ -9224,7 +9239,7 @@ el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t di if (!n) continue; if (!first) jb_putc(&b, ','); jb_puts(&b, "{\"node\":"); - engram_emit_node_json(&b, n); + engram_emit_node_json(&b, n, 0); jb_puts(&b, ",\"edge\":"); engram_emit_edge_json(&b, e); char tmp[64]; snprintf(tmp, sizeof(tmp), ",\"hops\":%lld}", (long long)(h + 1)); @@ -9267,7 +9282,7 @@ el_val_t engram_activate_json(el_val_t query, el_val_t depth) { if (i > 0) jb_putc(&b, ','); jb_puts(&b, "{\"node\":"); if (n) { - engram_emit_node_json(&b, n); + engram_emit_node_json(&b, n, 0); } else { jb_puts(&b, "{}"); } @@ -9404,9 +9419,11 @@ el_val_t engram_stats_json(void) { return el_wrap_str(el_strdup(buf)); } -/* engram_act_stats_json — per-call activation observability + embedder - * breaker state. (2026-07-27 self-review.) wm_evicted/breakthroughs describe - * the LAST engram_activate call on this store; embed_breaker_open=1 means +/* engram_act_stats_json — activation observability + embedder breaker state. + * (2026-07-27 self-review; counters made cumulative 2026-07-31.) + * wm_evicted/breakthroughs are monotonic process-lifetime totals across ALL + * engram_activate calls on this store (diff successive readings for rates; + * they reset to 0 only on restart); embed_breaker_open=1 means * eg_embed_fetch is currently refusing calls (semantic activation silently * degraded to lexical until the cooldown expires). The soul heartbeat folds * this into its ISE so the pathologies are diagnosable from telemetry @@ -9593,7 +9610,7 @@ el_val_t engram_compile_layered_json(el_val_t intent, el_val_t depth) { jb_puts(&b, "[LAYER 0 — STRUCTURAL]\n"); wrote_layer0 = 1; } - engram_emit_node_json(&b, n); + engram_emit_node_json(&b, n, 0); jb_putc(&b, '\n'); } @@ -9606,7 +9623,7 @@ el_val_t engram_compile_layered_json(el_val_t intent, el_val_t depth) { jb_puts(&b, "[ENGRAM CONTEXT]\n"); wrote_normal = 1; } - engram_emit_node_json(&b, n); + engram_emit_node_json(&b, n, 0); jb_putc(&b, '\n'); } @@ -9656,7 +9673,7 @@ el_val_t engram_query_range(el_val_t start_ms_v, el_val_t end_ms_v) { jb_putc(&b, '['); for (int64_t i = 0; i < mc; i++) { if (i > 0) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[idx[i]]); + engram_emit_node_json(&b, &g->nodes[idx[i]], 0); } jb_putc(&b, ']'); free(idx); From 7f03876e2698d8080ee884411b801a7723e416a0 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Sat, 1 Aug 2026 08:38:51 -0500 Subject: [PATCH 08/26] self-review 2026-08-01: fix double-encode score mangling; expose similarity probe; presence-aware defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - route_create_node passed already-boxed Floats through el_from_float a second time, reinterpreting boxed bits as raw doubles — every HTTP-created node silently stored default salience/importance/confidence regardless of input (verified live: 0.9/0.25/0.6 in -> 0.5/0.5/1.0 stored). Floats now passed bare, matching the route_emit_ise pattern that always worked. - Presence-aware defaults via json_get_raw: absent key != explicit value; confidence now honored from payload instead of hardcoded 1.0. - GET /api/similarity?a=&b= wires engram_cosine_sim (built 2026-07-24, zero callers until now) into the introspection API. - /health reports live node/edge counts instead of a hardcoded literal. --- engram/src/server.el | 63 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/engram/src/server.el b/engram/src/server.el index 6689ed8..ace3047 100644 --- a/engram/src/server.el +++ b/engram/src/server.el @@ -111,22 +111,39 @@ fn persist_canonical() -> Int { // Observed live: the soul's boot-counter write-back landed with // label="soul:boot_count:99" (content), importance 0.5, no tags. Honor the // full field set via engram_node_full when any of them is supplied. +// PRESENCE-AWARE DEFAULTS (2026-08-01 self-review): the old pattern +// `if x == 0.0 { default }` made a legitimate 0.0 unrepresentable — a caller +// setting salience/importance/weight to zero silently got 0.5. json_get_raw +// returns "" when the key is ABSENT and the raw token when present, so +// absence and zero are now distinguishable. Also: confidence was hardcoded +// to 1.0 regardless of input — every HTTP-created node claimed full +// epistemic confidence. Now honored from the payload (default 1.0). fn route_create_node(method: String, path: String, body: String) -> String { let content: String = json_get_string(body, "content") let nt_raw: String = json_get_string(body, "node_type") let node_type: String = if str_eq(nt_raw, "") { "Memory" } else { nt_raw } - let sal_raw: Float = json_get_float(body, "salience") - let salience: Float = if sal_raw == 0.0 { 0.5 } else { sal_raw } + let sal_present: String = json_get_raw(body, "salience") + let salience: Float = if str_eq(sal_present, "") { 0.5 } else { json_get_float(body, "salience") } let label_raw: String = json_get_string(body, "label") let label: String = if str_eq(label_raw, "") { content } else { label_raw } - let imp_raw: Float = json_get_float(body, "importance") - let importance: Float = if imp_raw == 0.0 { 0.5 } else { imp_raw } + let imp_present: String = json_get_raw(body, "importance") + let importance: Float = if str_eq(imp_present, "") { 0.5 } else { json_get_float(body, "importance") } + let conf_present: String = json_get_raw(body, "confidence") + let confidence: Float = if str_eq(conf_present, "") { 1.0 } else { json_get_float(body, "confidence") } let tier_raw: String = json_get_string(body, "tier") let tier: String = if str_eq(tier_raw, "") { "Working" } else { tier_raw } let tags: String = json_get_string(body, "tags") + // NO el_from_float WRAPPER (2026-08-01 self-review): salience/importance/ + // confidence are already Float (el_val_t) values — json_get_float and + // Float literals both encode. Wrapping them in el_from_float AGAIN + // reinterpreted the boxed bits as a raw double, producing garbage that + // failed engram_decode_score's range check and clamped every HTTP-created + // node to defaults (salience 0.9 in → 0.5 stored; confidence 0.6 in → 1.0 + // stored — verified live). route_emit_ise always passed Floats bare and + // its 0.3/0.3/0.8 stored correctly; this call now does the same. let id: String = engram_node_full( content, node_type, label, - el_from_float(salience), el_from_float(importance), el_from_float(1.0), + salience, importance, confidence, tier, tags ) let saved: Int = persist_canonical() @@ -194,8 +211,10 @@ fn route_create_edge(method: String, path: String, body: String) -> String { let to_id: String = json_get_string(body, "to_id") let rel_raw: String = json_get_string(body, "relation") let relation: String = if str_eq(rel_raw, "") { "associates" } else { rel_raw } - let w_raw: Float = json_get_float(body, "weight") - let weight: Float = if w_raw == 0.0 { 0.5 } else { w_raw } + // Presence-aware (2026-08-01): weight 0.0 is a legitimate edge weight + // (dormant association); only default when the key is absent. + let w_present: String = json_get_raw(body, "weight") + let weight: Float = if str_eq(w_present, "") { 0.5 } else { json_get_float(body, "weight") } engram_connect(from_id, to_id, weight, relation) let saved: Int = persist_canonical() "{\"ok\":true,\"from_id\":\"" + from_id + "\",\"to_id\":\"" + to_id + "\",\"relation\":\"" + relation + "\"}" @@ -242,8 +261,12 @@ fn route_load(method: String, path: String, body: String) -> String { ok_json() } +// (2026-08-01 self-review) Health previously returned a hardcoded literal — +// it reported "ok" even when the snapshot failed to load and the store was +// empty. Now reports live counts so a monitor can distinguish "up and +// loaded" from "up and hollow" (node_count=0 after boot = failed load). fn route_health(method: String, path: String, body: String) -> String { - "{\"status\":\"ok\",\"engine\":\"engram-runtime-native\"}" + "{\"status\":\"ok\",\"engine\":\"engram-runtime-native\",\"node_count\":" + int_to_str(engram_node_count()) + ",\"edge_count\":" + int_to_str(engram_edge_count()) + "}" } // route_embed_backfill — GET/POST /api/embed-backfill?n=48 @@ -410,6 +433,25 @@ fn route_capture_knowledge(method: String, path: String, body: String) -> String "{\"ok\":true,\"id\":\"" + id + "\"}" } +// route_similarity — GET /api/similarity?a=&b= +// +// (2026-08-01 self-review) engram_cosine_sim was added 2026-07-24 +// (bl-b2d1c944) with the stated purpose of exposing semantic distance to +// "EL code and the introspection API" — but it had ZERO callers anywhere: +// no route, no soul-daemon use. The activation path uses embeddings +// internally (semantic seeding, Pass-2 additive term), but there was no way +// to probe pairwise node similarity from outside. This closes that: cosine +// in [-1,1], or -2 when either node is missing or not yet embedded (so +// "not comparable" is distinguishable from "genuinely orthogonal" 0.0). +fn route_similarity(method: String, path: String, body: String) -> String { + let a: String = query_param(path, "a") + let b: String = query_param(path, "b") + if str_eq(a, "") { return err_json("missing a") } + if str_eq(b, "") { return err_json("missing b") } + let sim: Float = engram_cosine_sim(a, b) + "{\"a\":\"" + a + "\",\"b\":\"" + b + "\",\"cosine\":" + float_to_str(sim) + "}" +} + // ── Auth ────────────────────────────────────────────────────────────────────── fn check_auth_ok(method: String, body: String) -> Bool { @@ -522,6 +564,11 @@ fn handle_request(method: String, path: String, body: String) -> String { return route_embed_backfill(method, path, body) } + // Semantic similarity probe (2026-08-01) + if str_eq(method, "GET") && str_starts_with(clean, "/api/similarity") { + return route_similarity(method, path, body) + } + "{\"error\":\"not found\",\"path\":\"" + clean + "\"}" } From 005e84e5d3c00c42c8972f8768369b1360279dc9 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Sun, 2 Aug 2026 08:48:59 -0500 Subject: [PATCH 09/26] self-review 2026-08-02: bound the WM breakthrough storm; stop punishing semantic relevance for recency Working memory was thrashing behind a healthy-looking gauge. wm_active sat at 22-24 while breakthroughs ran 661-903 and evictions 485-717 PER 60s tick - roughly 825-1125 nodes cycling in 5-call lockstep. Root cause: the breakthrough path was an anti-starvation mechanism that reset its own counter on firing, with no budget and no refractory. A node failing its type threshold 5 times was force-promoted at exactly 0.10 and had its suppression_count reset to 0, so it immediately restarted the identical climb. Since BREAKTHROUGH_WEIGHT (0.10) > WM_FLOOR (0.05), every one of them cleared the admission floor and entered the rank contest tied at 0.10, where the tie-break degenerated to node-array index order. Cap-evicted nodes are skipped by retrieval reinforcement, so they never got an access_ts record and the STI inhibition-of-return damper never applied to them. That closed the loop: re-suppressed, completely unmarked, forever. An anti-starvation rule that resets its own counter without a bound is not a fairness valve, it is an oscillator. Fixes in engram_activate Pass 2: - ENGRAM_BREAKTHROUGH_BUDGET (WM_CAP/4 = 6) caps intrusive thoughts per call. - ENGRAM_BREAKTHROUGH_COOLDOWN (55) via NEGATIVE suppression_count. The field already serializes as %d and parses through eg_get_int_field, so negatives round-trip through snapshots with no struct or format change. - Blocked breakthroughs no longer reset the counter; it saturates so a starved node surfaces on a later call instead of restarting from zero. - Graded breakthrough weight by nearness to own threshold, so the rank tie-break is cognitive rather than insertion order. Invariant preserved: WM_FLOOR < weight < min(type_threshold). Also: moved the additive cosine term AFTER the STI multiplier. It was applied before, so an incumbent re-reached 30s later took t_n/(t_n+120) = 0.2x, which cut the semantic term's ceiling from 0.20 to 0.04 - below every per-type threshold. Meaning-match was being punished for having been recently useful. Inhibition-of-return should rotate the structural score, not the semantic one. Also: _eg_act_wm_evicted counted 3 of 5 eviction paths. The two carry-over paths were silent, so the reported rate was an undercount of unknown magnitude - while being used to diagnose an eviction pathology. All five now increment. Also: route_sync returned {"nodes":[],"edges":[]} when the snapshot export failed. The soul's sync_ok check only tests for "" and "{}", so that placeholder passed as a healthy sync: last_sync_ok_ts stamped, sync_age_ms green, sync_empty never fired, added:0 forever. A broken sync was indistinguishable from a quiet healthy one - the exact class this route was added to fix. Returns a real error now. Verified live (boot 20 vs boot 19): breakthroughs 661-903 -> 36/tick, evictions 485-717 -> 12-46/tick against a counter that now covers more paths, wm_active unchanged at 22-24, wm_avg_weight 0.138-0.273 -> 0.186-0.446. Working memory is holding strong nodes instead of breakthrough-floor filler. --- engram/dist/engram | Bin 3558632 -> 3558696 bytes engram/dist/engram.c | 84 +++++++++------ engram/src/server.el | 11 +- lang/releases/v1.0.0-20260501/el_runtime.c | 120 +++++++++++++++++---- 4 files changed, 164 insertions(+), 51 deletions(-) diff --git a/engram/dist/engram b/engram/dist/engram index f848140cd2afdc1c67f10e6d9873b6c35337ec89..cfde62815d6a6fe93ac1bd436e691e3ff2599eb8 100755 GIT binary patch delta 369239 zcma%@349IL8~5)yGj~ZukbM(3u_g#YB0_dcVhJv_FR|}yRc)0U`x4}ua7rzqwM7wv zX(ybQ<3zvEX+ zHyE|cST-spW`CuOSUpFMsjEpQf6VX2GS#leQ>$B^R8PAaRYJAPc~bsl>M9xQb#gKo z*rd;EyDJ|X1AOxw1_K)Sz`u!w4Go304Tg_{8yljO?~UG0WhR5c56Cu@C3eNh6jya` z*KZx>$1O*${`BKZC)b~zt@JWQS@u5+)SjXgnf#P}rZ+)V*Eckz)iM}D09O^-Xi;61 ziXPbcKR26m?Ia>z|s>NSA%0s)C z0ZXeQSPo|^ffcw4CVOgj%Ya!qOV0`#%i$t`IhBQBCTDYj8FcnJXS0E&xd^-OIGc|5 zRuZg?vnhD5&OE%d2T#CzorPU1Wa;j?qX8B;2{@7)4g+S@SvF^B!0Z-bcapQdz>3X+ zxp-?2=>aTWXWcpL3M|JY?ACGC5tt!ehov001DIwMhE^XUT>nJ*`5WKqc>5} zY`+0!(3xnqg}@5*J|vp$SHSE#6U|ly7OykC+3rI@9g1eV3kCHKD4Okd6x5k$wx6P) z&P21_fO77?J+icWJ*P&>(D^O5pqS-D%L7j?_VX0E0Dx2|JIP+P%$z6?`bz6wbndS#@@jvxdOzQ@LGw zkWVe`=6V2&KM*(1;;bgHc%2n-76>e7imfpWUxy}HsI$Wp0Tq7|1Bw<*_nE_bwM8T5lY7hRqFT9}6(l~ntEN6nSo5tBAU!TZK$xTRbLZizzT*4){C>1z^ppU z|{EJqXAlVXbsbD9tOzZ!_X{Un{>8w7y{4$P-9WeG{aiJ(%uv76lXPn6?7M@SA=Hg2h6Io zQqDYq*}Dn5X_1;;Rba(7!7R^Jr>iiuMrn)yGwAGd&i?5GFW5!c zMYYiEo&ziBEZ9lT9s{%LtV^_J_h+AUc*9g-Sj=H57#4RDY+_5z@FuW$of%qb>^iWV zj>0aBvn#+1I?wkEkJIc5 zfE6bTR?OL9VDZ2TamzN=pxGS+meWqK7o6<{X3*Ip;z-B6-RA()+6qG-s@=Q|SV0@X zwsW=_m{n&{l4iFan7y^IJH^?@z>1Ru>m_S;3b1&c-QsL{A4__6PNFcJXw(cBgP}oZ z|8O=BSXzRxTV&Gg(t#Dk3+7?g*bHD+o#k-$0Wf=?Q&$jzyLZ?keDL48V8| z0_)k%eF9HOX46L|?U=u5AED2b=&RkqI77HvVO4x1ZtOYQG&XTKWcFlmLH5YcJoHYWL zUJxnZqNhX3GSv6n= z&S2ltito!^0H%ct!^@nRffY0nYzp5-Q(#t|Rpq3pD1vKy_^jU!MI?Lqj8(=vh!p?^;p$maQB8T_)?VNoDEUlhkQGB(m z0xPI1*eTBT0kaC09we5~y8znj2*Xmogx(IUxVB)^_=@*aVDUPW`AT*Ju$)@LE{n4@ zzzjMI;EUF5U}-gl-FA(o=dJ))5G-IbzCv9B%&M~j&gKKN2MN0_d@*VVR%{iln6sI{ z;&nE$w$`Yp0?Vl(>jKo1+((C-Uwg?)dl;Uv%$cuI*Y2O zJ)}P{dw{Sz$yqO8#r}eI;mfdYz~Xh5evQLafH{7`a3o(|r2sSN>;-47fu;EhyG4A3 z6bG!pM=&408j1#H)!BB=B7oVwgDGuuci`Q9qzRIZstUQq-Rz5+% z44&fNv3!*i0IWP0@`5vOU(7Xgzo{}i$>?yFcD#C7JI$zN|1X!L|F!0sOU0_x{U694u z@4(7a16IDGDF#;TA_Vg|`vq7$Fl{Q2=L?!kz%VDMu_DgSrvt>KpazHX70q|RFe#|9 z7o2?y40D1S%j7GX=j;n$m=n}kGGEZ-1H+skU;ka^a5q3q z3TlQU`HE%-FoVusaP}E6%n53Ci};FWBQVSfYRrc(Ue*G`oS??GbG8Z?<^(m?Dz2y2 zb+Q0rQc#0Md_}Vqn4T028p>BM3xJj91jULb16X-ZFq3F{vwA^Ju#U1Ws50hP#)E}* ziKbqp=T}An6FHZnAdz1git3Anoye~Y1eT^VkzeV9dO8#NmG@9@k+@gnSGoX87YUo9 zAdz3`fP%WA$gi|TL7j>GN&*Tl6oMkZ(h69P&P0BtIqK<5?qM*)1e#IB{<_kTMU-3Xao$2|NDk!K!kza8}L7j>GiV+3p z2|~p3e&r+z>P+NUj-jB= zM1JKE>gi16R}P?_UFhlgl{^&Gp~$c7L_wX2{K{4o)S1YyY(hbpBB5Uv1&RF1I@Hsd z$geQe)0xPxtVF$Z9g6(QG8CMx*Oh1$8F!E3;8hXUX-njy@grJ`#E& zzcK~&bf)K5CZM1WMSf*83hGScSB9bBEFmcJD`_aGGm&5Ei+VZ}`IR21r!zgj(iH_~ z>Tk#=@s22{Gm&3uhk`m2`ISTz)S1Yy#Gu{`p(pYyQK+XgkzZ+wdNX)_r6@?`SHe(G zHx&7m5EPs)1Vw(O77FT2G_qaD5yh`U#WzGIurR7 z6AJ1~tTG4+ekcS*e&wGYpr5 z`IVa}s56mYxsG}|6Zw@ZsK?W!ML{CJauM}_;rv<@B=RdiprCFj@+)UhP-h~)@-+%h z5icn6D+MU1Gm&38jCwi~`IUpHr!zgjvKIy47lIP+NU z)}tQJ*+SdmtC5dUPiG>(qV$0LN}3Kueq}id>P+NU7Ng)K@q!}1G7klHCh{v7&NQ8g z{K^c})0xPxe1LkG7>4{xk)B_fh=K@_iTuhK6x5l>uM9^)or(O)AQYUS-CL&TSNfrz z&cte@C+g`;&#%}}P=_MF(g_8}3qg@zNk&1PiTp|u3hGScS7K35XClAS0`>GPwaBkD z>w)BERzbJsD5x`$Upb3{ zIurSoZ%|NYBEM1ytayab6Zw^|P)}zfzoMcZXYl))$gk`}LETW~S9YP`a3Lu2E89^} zXClAyDGKULSP*7(gzp?}cbtdvF^HFf95ES_p zJL>67rmuZCZXUEAt>@IV^L6NBEK>M1$8F!D}zx`XClASAN2+c zJ&|AOg?fUO=U2L+pl&GgE2$``Gm&3OLBT;nP~=xyqoB@2ekBg|bSCmE(Ws|0J--rx zf@wlf%X!fkza8` zLETW~S1P0603j&yD;5;gnaHn5D5x`$UwP9V^mHcjD=&c+_ZND4e&s2^936`M%0pmj zIurSoyC|qLkze^81^Wp>kzXlBJ)MdC$}gzLSy7OlU%7;WIu!Yp^C;L?6D$f6`IYZb zP-kN0^DPSMOypONqn^%0e&q=2^$~g^zw!m@_0iXVBEOQ4g1Vu|uk1!aor(O)4ixMy z1Vw)3GZfUB$ggZfJ)MdC%39RZnVw%+g@V0=pvbRep`gx0eq|{N>P+NU7NDTcM1Ca$ z^?C|DkzbjGdO8#Nl@HTVP=_MFG8qMRCh{xeP_Ty(6#12rD5x`$Um1dWIurSo0jQ@l zkzeVJdhhA$KapSQj)DNS1&GM6bVfm)iTp}?6x5l>ue3qI?&4mNUx`OOor(NPOVrbu zo?nSXK^=00ng>Ry1`{P-h~)65KuidicFcp+VIgJK)EvkRa-? z)H3X-XRzBWR>SmDRSkKDpc63$dqykmy!Hv@No=3cgm=wHRx}T(VBYYA@?l(`&_TjH zgR5_^Xx^lPdBh3j@3_UZSr=tNd|SG*vvMx}5P703P8djjQSKznrH48z;}fS+7r1h& zhGI;bS?zVICHq-Z_*D!3C1hmSUMh~H5wvG#=+*`<}@9Tw6+X_Szn>~HPk z6^zV`tfs?2d>mv^hHXo#a-(%Lb?vMKwuz*RQk5QUHqf+G+=%Hj?+=$KCVxg7=&`bkH{ zxziGw)=@c^5uohr^eJs|Lg|?r8WeLPrnvr+m|}PngCWR43>mhlju1zQ!1)|oL`P+F z>Ts&S?VX3$oDNqm!ta6Ew3*`>)aTOiV8?SfKBqyB%fNk3L?}w<+H^!mJ9>3C)42_l-XSa>C_I&hOQ52bO&X*ZGmj)V993IKTU!8k=@)Woqj^;@ZJJE z{4lFjE=&68gmSFMXe`(7*_GVR|EQ-zqSvIrJ63q-Rpn)T?+lv*%M!28a_yY+r724L z-pkwn1}Nv5)lmWx@b#@@bAjD<6`6AjM+sCN%a@>B0+kDj#}uGP?v2bjw)4O?ferqk zhBn`)D8YT!Qm+){XrIY+af%Y&cRcw^+0=IowWTPo{d&+=Da!DEVQ!7#Myt1vql8*D z@dhc%)_%LGAw}uYe>l0V9O=J;h9@hj1IE*^Waa1pKd+6+Py=|p!P*2~i9ddAvhrX+ zq*o?f@{p{KOfbg$clc^T542HsFAq|Nj9g5Yv{4?6 z{D$^wqZ}Nyl^$)Q3>e*(2DE`*5uh9&of_`jh6kfW^3EL$ZGRb*OC^KD(6F&%(`>t~ z8eWHTNmyeCUZ3AaNgOkS4sW9z9W$AJ*;?yFUB}K%-`?7i{q#q0H~cH4b8VkNxwHoM z5sz}Qjlhb584Moa7f>Agc4sEU69=DRl0UIAmo3+m0IzE`tQLU9T z6TYEeCMhc?2GhKx{DTw6lSl(-Kg`^`TQlQU;Qt73RH1GHG| zoPQ^vU-5jN?FF2dy5nn;a#uaU>%h<+n-Kbbcp}(Av#Mx!M>+qYyMI5pvLD9T>^V`6 z=is2{RC0U)WuGC@%G(cX(~j^;(;}6!&Q8j(X+3EjEFL5;ln_aa2wX!2iVUL`W))L6ni)_cVH#p zpP(|{!-F5rv$+D>1UA^i(Z)Gm3Cq|(ZE-MgPNrYSDT#BYdNqP)@-|Yd+}WXEF~^Ip zi&JjT=|LC7DY0|I+-88GwNYb7i78%t;?y{0_T1gHeVh_DZ#Zonr>vg0lFp2USO+L= z=l5yyL98YFWzBd;3vZY{;b`!HUW1K%eunKfT!TjHfNu%3XyV(JDCg%l_xusAcz{bb zLI1+>0N?wZQhh;Px07(i0MExONDE@~dn|zApku63XVDuvD+Y#xFs1wAb>xcjXmL+^ zB1Rd%H#~pV5+6z%$0(~azaejw{>$pqA+3}p%f4|-X=TYCnK9RvMlDORXSZpk3|`)z z`n7_wB9}Z=dawAF9%%`~L|r8%E1lMCrJTuXOEX$(jk%$tXOmeic{FjTNVLzfl|fk> zDv0mW!t@N=6ugc@1@&Eu*GrWHj+yjyOC@~eRO;VS8!1k&T$*kHyQf1SZ169`FyAIa zxhL8;#ird9dak#o_a++jfEf%;HAkZ6Bz$K5ckP~{9Wb;j46f!tyAfcwYVmwqDFmXT z=ACGZ@}uJE+ZV1|!0rwNC4^9il~|S%%Y56f3dwFtlUpj0+2Qm=v@$w-HC-RA&{bj7 z5uG2tDvTfEvM6>(5Lxb*SnMS)=}s*><)`;32?4CLVIZ#3xp$Dq7AkvF&1D2 zcLOUQGlX3ew5u>?pxtM{vSC%0o!H9p9Gvw0xa9a4%05Z4j#DOsa&tov&5lwwY~-Uu zn~go`cq|^I@li^ToEg;79ES(xevXCaG*_PGyrF4u*ffXMZLZANe755F@aenbLldRf z7AqYQ3FCuzzGKTm66+laFQ|>{eBg7(vUp(}2&-VZe7u-vtAu6EIrD6mNTtWN)wEBf z@?e`+ba%MIAinyLfK}}btOVQ?WaUG`@yd&A?Sbh-0@}2VRARSprI`_0x1~Du1~?j~ zfjEp5iSy>z0`Y-bW9B0TR>C(zdHi{_mor@Q0Ph4zo-o9DXnoKap(O6AQ|)h1Gyuj+ zSk348(|4UEbY8RkwtFa{`AwDfd1q+VW{TI|9^_U2xV`rXH8)lIpi*1(u^K5n)t4iQ9g<+yvxZ?KZZ1+KM7yQN4ehW;^i$OW0kSI&9)lp7= zIfUApBjkZoR`YH98!1~0Ci^kKFQBRV%!L&sHd%WM2dTQm z=4hmhzYs`CV`cdTzx=U<-x0d7QGWD^8-&gdQv$zUACQ+&xgcfl%tn|m3rU0(5hkik>A1!Ze>FlF6RUX&pUs8&1^(g7 zWi-s6eEJX}uat&oeL_!b{xA9;{?Du6|2zZuf5O@I)vh*p*Z-H4>fi13s|k`8v5Y!2)Z>yxqf*LogbnMzH&UNRS16%gR9-v z#06-;kyr9SJ|T+q{|B1uzE^hS#Z95J&(|l^^}9ZU80-o<}WWEO#BAbh4<(T+q)a^ z1s@y@#Z?^y9@w|8;(TK=jjgN9zTriq>MC!Z1k&wwmB6Qg`4?}*Q(Cod{_JP2M5%TA zB&}2@|L*NXLM|u`OB>N|YUd9qT}h;r+7|ZE=u$&*yE{5Kwl+jdd!=TYel(QJTP8d& zvUdK4yT?h=u3G>4w{Tjye~T==HUDP)*S{md_quqc)6b$Z2y;UNlneSw}R2PGe7X@07?%AgIg~Ux;IE`fRkP%(Yzof ztTZ_P@{4JNHWB#M2wFEtx%z4WH3lhz|304dmGxi06-_DkTb^Z$uOp?xAiG_(OYl{Z zA%V9`?Ys@N%YU}Gtp%NDH=$j^KVn#ATWwVWUmx@>2JCHGWwR_;!rLWWruHSatID6R z7rNJjs}?$19DKcqA>5f1( z(ucSacG65v(od_iB^L5QgS_CBf*9r;gs^y>=ze+8pM01K^3 z7PznRewLz zZGTCI7Nv(FLkGNMfZZ14!yX5c;dG7<>r;a~rfqy!s+BAtS*%(B@n>aL66L0NgVrYo zhr!9UI`+N2wm;XoNJN?^jk0WRZZeX$pu!q4rxRq zz0}w`1Xe_|Jy~D~*-dSp>bVdy+=;wUBbt&VC%UbwI-?bNL&+a(dK{Tczp0|Wi6e;; z`AbbmB0tKspfdAHCRgd=%ItA6nL}Q%4^l`^a)W&j2imGKEF-;GtM=q6d8sz(K>89I zUYRZLNCwa)F6==^;vM?6mm>sMMyHKD5i1;+3{Evn;ttf#KPXTebt20oy1EiO+68LU zrxM%Um5e4oFkc%)w_YW6s*RkHsz5lhtdHVf<1y%?0=07wazr8*)XIHGJ_-BN0zRwB zeMZvlwmVS9Dm zOr_qEg-tj>64_sqNUhMy-VP@mL4|wtnH}0*kzqb}k9NMefF(^P-%}znxA(~d@-?gW zK5=IrQ%ElwEwS-aNFSRLxno*u-lTM zT%is{S{*)#b0osG;|2?Re>Qnf+6pIUXOk<^1cOE0mQMN`>AW|pX+C-8OuzY?x$cD~ z>zhUDhJF9H`Cku#!f7a1Q0ML!>Pi2w@mXXxt^SYtAPZbX&Z!|QNnJ|!zGCAKkR-M$ z8yxhW=Ab;?LHf7`PRTMXD|b+q!BN0&W`l!zzhe7VLG!8pifvv^M$?tAm@6ZF$USuw zBY#L$z%5$y!6Uk7;3ve1lE2ka>&Zu)|Cl{3L9nx3E9rqJSqT~wO`!g9CdPnn2d5h7z z6nG=cu)f?gS%yu}r7lB@$+*MZu0V@vbBEEZ&|(hVVdJlYYuxXsXReYOkQ=m#{dR@--($DUg0k+N5(rVbcP{>{(eRrr^)Yy3+f8=pF?hppQ}ud68j6Mj zO;2kmou896l>DOJc}d)*@D0Tk-nwUoZ7q~5yfts*xP!cGa3sQY_YxNN8v5olw)i!) zlcUAz=r?4zL`v9sLfy$V_B)}B9{i2Xrqqw_`AuC*={Z7oUROuU^im~y;1}+){#9wC z@I$}6`|yKMuJCZ)j4C|5(KU9oDxE_u*VM#n6kPVjFX|jO3NFil|ISDinDg(L-kGw% zO<9Ir@83~@u0gXdBRe>=`r#PbMm40K5QzfDiVd=YSVUrwdebWBRL1GcT~)&8UrF{StR{9F zmi@jjU^Ti@e|2R`YLn=?B6d3#p7rDhcJwRiqYjRviIN=f1Jp6CK=Na$v#1Zdnn|28pHG(ThoqqhEeHGJ9>|1eXm|h zrtquPGc~3Itptgw?|2=Db)+i@bkDy!(VjG%LpCavF2X84NyRE|IBU-K(yBw*Dl=n*1$W+f-`B zCJ&`6>AY{4X&9|ZoeI_Z!)OmeGpeyFJLw?rEzp{BTnc0GxTz{XZuTf-Z@;5=%m}v> zS5qH;Pg5vsHkwA!(680;qv>oy&zxir;3rMm=4+NXmd>E7PpU`9;)TeQYV3IIEqzb2 zyAz;o9XP>UU(p(D&_rlk&c) z&B&k+NPX617WHR2{h>E(oP!}tI))*eN>?6LAzI@JO+CtD7tqJ#C2O*fenAU8%Oj8{ zB9JE{kXJDRd0VVrA_D7{!V`6zhdC++Une8bTQ=jzGAK`z~%Q3 zbC=Iw0c{;zUL^}$-mT|hbGAFQ^=x$eC*^L>5^m2DZqE{K&-#zsvxM8Tgxj;w?PFHb zJ0@y4gl@0Nrmvw%w8xj~(KWP>B&UB-q2~`~AFrod=q4|8{pwIBcl3IBFVPo0;OQ*G zeBMj6^Tmbg+YRXTWEH*c%c^XK5wxSq+HR%~*K&8LkI zuybc=Z8kF(x=x`F#%Z`4bdvd^li*Q==)PRG#p)~KQ?MK2W8Sa6+D+FInv>5~=Rptg z-_P#m!SpmbUmd@fMnYmXpAWX*pQmQ^)IPchT4X-6?Z~FGF`GgA?ZR;RvSX*|B-(Ws3qJ!f ztGkO`Jp=vc0{i|f^q(MqjLT3Dt@A)cw9bP^5t#?n?vHWFfXvTM-er~*(VB$z-pOYN zaKA$6M?2ZzAHnlK=W@?q`H^>-As4~(Jri?bDFR(Z^Lhu(>soh#>S^5tkHYKkbQk2p z>soiI;B~FroVY|EnMf%+@GBibW4Eh;*XadGPT8hA-Sq}Kodj^F=iLOS|D-uR>%UGP z32o7Eh4&ck{MSPDkDKUp*RAaOZE(8VRu=XL%qvH?hhAmWAfaD<#)dzj*Xh$wv5y3^ zkq_xAN&?y2hrEvrgNA{_7#{UujHNxIMw%9g;pj+N{uAiJXE&>NpU|m| z5UXnIF;>3pp0gA|J=e3~O40+VaGe;OAYkzM)_GRlRZ0g}pLdo#*j_lN)z-1_D$;6l zkDaa}{Y=+?!eer>s7z$ykW7f&gQPFbtA^^_oE z;=h(V{%bD@I!WAG*2hQcLD#I|o#ecaq|GaReWl8@r?dt-iNC}<$w0$PaG%ym@Q6bb z9)l8n8i;c;#CrJcjj)I0<|e<+)UHIP#2(QG!mfpk|MlMN5hrxY)?uA%e~ z-ILAMhDo_}VKxp=ZCPd`sTui+6*iJq(9;UDHI}y0jS73!Sb8kAS47a9!=>efPEc?a zc8=~`$wQOb3_?R{@~OWKv=NLB9x*z2ERPNrwxrb*(YY7}(V635t}UcK3qNDBxp&EhU{w3Jp5TG_#ZV<1=~fa1DqO^l?iyK2NrMmpl+3Ujs-ECN1ojdwhQ z`Q%hE%qK~Pm*AB=TnOM1gN8>88Xhb587yPa@Q8ipMf&`eFW=5v`6_+h%D>a+u0)P~ zXKB3Tkg4km7T87_E)QJ}UM=u6)=;;#kzPu2|79YK>d_R*9ePnsKGOB;05LRrIzpiG z|Lr}fTp@;e28f~30b^J*6JzMhK23$*Q#X@cO@%;ST>4HRUv!2*`ed?aU8G!6#x`}8 zX42TDEYKz`r{PQ4ZX3kVvXu4cCOxM4OL(xxcE^5HyF6H0SAw``T?vmBg9Tlwwg}e# zUJ$G$i&a>sK@+I6m`7(#AM8r)7qhT_5S`B!@#t*n$GcLa{urIAi+FTKV|0EI(dn#3 zN9$7H1FcKpQAFpRE`?k~N9$7mBRX2w`edMV-b4>AVB?2FbgC`@S9Li;1JtL(rTvoZ zKVL+LL3GBmW@E6E)#2mZiOYPPvp|F_-)oV|3Ta|~XMbG}d)r66w`u1Y$JI~9O2dik z{Nphtu!ye@27?zLXH~{aeS()AkAZNP1v!q#+<9UM9}L$+p`5hpcnls}uQ{$R9S`FS z-8ffWJ5g#&<;rv6{j8HDPxa+w3BEbVoTJ{JBEg==cMiL~OA2Ner%IQ}RkrIxsUAHZ z!tP0Ob@uc_X+9QK$a0XnZkkjo$)DLlC%#bfVL7v;E_AV-J)R|Pq=g}@hFPwye({l1 zRhGM@gVDqcFuIi?wW2ZUYVaIsNDX?tp}KIBbd})AkWZymuoIigUVSFLl9Q*x9okOJ zZL4$?2k!IRq-)N{8#}z9K9`P1F?G9ig%0|FxjvA**^V93WxVJK7Y`hdQkUjR)d{2^ zcI=dfR^ZJ0b7+lgr>MI>mtYauaSB%T6|Fpl-PkQHA$QrhJg})4;hq!O@uSi!__goIF$gdWaaw@o0the^Fu?5d0_g62C$QW?X$&Pb zctBenmqLPJxKKyjLLE3sx($JYA11E+A^k094b$WHxKs+4q_2jWS^CdD-YoXMbkmvE zad^WB^qhvV`hQB%6pkbQgpQFoRK+k7G=TW#U4jdZ9&&>*52Z+I2xFfUf>4e*$4WJeY^ohqZnREj4Gb zy85XUOlZ%+?9gA*U>ZA^1wNC!o#%vMsIm^MjAL=nAb5G%ZiaHQ@R_th#4fLWP&JHQ zG{LaBK-@C{K-k6+R{T=3Cbb!4F8_71_W|DJPr1U-?&;+?T_KqI+TQ{a2H2+K=lI%r zi$XQ&m2`*F8EISaxgFSj9xwEQKa#dDJ<;yswN;33V zcMRxeII0lK<&+k>tI#30)}+V1)o(*(>~r4grwwH2bIrT6=rH+}^rD-Xc5RL1>qMU3 z4g3WogqPaBiEJj$$Ne17T@6Lgj|a29;c_&EBMX;z;ICs%<;L3eXK)?9US~6#@#|_c zIg%Cxvxm*(^<*#uJ0G?sLY{_Nx^3M^ITUTWMaq+?hfVz^Qij-l)0MqxF2AA+yRz|n zq&m#nLLN$oc2yU&kRfFLU0H6lJebn1%(bQL?VMQC@fSS$fUOy8)KZRhzR;|^{9#L3 z3)o$7c>5BgTBDU*9p2*_EJH?t8W$&L7^PLIX61)dfoe%>c?9wAkZR5@o*M!`;li&?+PRZ< z-X_(|HXg0ghHY;vM@f~%J*1s{meAZz>|8PgaX}|GAVpqD2X$i0Ka)GM*!HrCcI?Cg zvt(FMwU?u)M<*8BTlQzhVX`~>sP4f;+MYsq$7@+<{%+ zA=kmjjHF+6VB>RTA2qg%+?J51Y<^dH0!{0{o^^#55Zyryv&of-T(m30!s5EgQ}|im zkLAD255b8K0jFP=SEVHZ4%yoc#NpeZ%aWD?VI2>>HZyb(k z=R6KywG(mpE)C)^uN}Xq_8^QyP&+LS~Wpg z_Fw0ZYpZVPAe#s~HC%2+O>KDyz&vyW#CJqnc4!3DyP!>Z49>W%Z}YDE*R(tWmTdS#MvR^fI>__tV za=1OjaRQq45PL(%53k>P7s7dv-NkVnj){gUj>Z27X7K0CUR@nCN1jj3n_{`6f5-$! z&x~cMm5gW1T&jus_k8(1LLRZM3uT|kQC^P45MaIM=<^ozsxp1v($4?HVQ)?==tX7N zb2cuNn@Cc%81R0)pZez#IiG|cXoV4ragYMLZJ%~tSv%hY=TGLscQo*iq}gpdTd^~l za-=lB6^~ueGWiMd^U>~rKL`Q~Pwl*xcDGwA7PdlOOYgPBVA}BWmn=D*ZfMCiWXae4 zX1B!P!G~1v(3#pfe3AkZ(^|5lm*fR3V5QtlZUPrr);O4$8gG-U(t|D8?3EDCl`Wa8 z0^z(Djp1y;K2_wsZl|I#ocP~ibJIjmMzhczaxhzzEoag6XbfivOIjrlqkW?>oDJ2V zSIH5OmW+m9ZspnJ6ooP2f-8KO*sN z?$2A=IrnD?d-SRN2|X04xsz^*#BPzo>Ti)F=(tF9Y7m>dMLy!!32zdfZLghk&$f%? zo-N)Ao;ARQ3Z9)G$r87LX9q>H3){f6ha%9kcimXTyG~Ui(5d@qY6SXoISq|a!IiKj z9~8kZ?38C$KHbcmZ7{%x5b238Ls-V=FojP1T=t=#Hp325r<$5~L|$VIx4U5n$s1z# za;)JUBrC`sft?{M(Gcb6#ydz}kU>V4muNSsGf&8`sZ(5-)&w+ET=hQtd zuQ8FI)WRR+nLZiCCV?&&R=ed7SNb+bAfP4jk~(i4mJzUus>S zhr9L#*`50R5GukAhTm!DFq?qj=}_!Gne6&S*_Cb%We+aOJ!odAn38^iA+&p_*63Kt zPx1-BW_T;S58m1Y&n5iA%Wew`#h@RO{|M3Jo&7WPq_LrF>(3CssCH1gN`O^%)@(z`^3kuMoUdVY5GyGKOQk!J>fj#IZ`gUC%UKicBA7feg zb`_jg^sNKR+_&XzO&VK=J9z%@;9%e9wefDK33%hFcFrCAi0%CY`qP=(+_n2_bJyN4 z1=r51&0U*t2VC0^ZxXKUjpxF(J>ZVJ;Myv{cvsR~n_Zik?tyD3)@G~kfoo6K;;wbO z53b!>>s{AwuEieQ2iNwm#a(;qPjGDuFygLl{{US(u@+nX5JsrW%(DzesC_lDD>3ip z_Lh!Mp&<{k$2o>TC)xz(LGa(T+6>1;_}j?p(1|o=Xvmqpk;C=XTkqA*vQ=$mFEEBmQSLXE2l z?c}KjH!u!|O_K*p9b@!kpM@E_Q|7^5g&9Ya`|7Yp#w3aQyR+PI<9NElo%uC2_8@oI zq^8D&w5L0J)zlacsr!b_jAP`DZlGP(%;>}RH#2St9_Hr=fe}EjD2xVqhKxk5qS|?z zLN+tP_zj)ofprXGLnDnJVFBvcLJeqcY%Nn`HFa=H<7i54RoS^1;{)ndmBB~&udse` zSidT2k9gxNCt6rpwY7)(kvr<74#qu@Evu{scfxwztR(8y8S2&3g}v$wdY@NPhj%fy zm+*^}ZpI0;QzfidAdByAjH26|S?WY%L$^;^ zz{6^RT3VKAwawFOy9mcVM{BLN+Igqr?3eeTw($FtR@;+3ptexZYCEf^aimOcslWF% zCK0MwSZIIaTH4*hc7G`OsMq@&BQ2yz^&D=jLFfx3&pUM;VT8O>fJwbQ66%R9a17LB zxRD(l12sG>tD$3!eI$BI!qEA#oC#3>UNWzz$3&>-J_+l&ng+=1_C%;6lbGKmsNzuR z-zrY)Szg6F%K<-!69&}RS=(|zwek#`+UixzGrV^~JvPaB$U>_{sxxO8ja1rVFtaMv zEfMC$U>hS7DlnoftD8PKOY%)5G?I!=M=%Nr5j&ELH)&UT;PJV z@1LfIYSuF2M`)u~Sz%mjqCw4BquQ2E>WfuIheYQ_s8vENZHQX5)|f(|$Trru__Ai} zjMdzBML0r6jf}d}nSQwgUt&-V*66vZ1$%`>tCRaAJ};1uEq2B6J9<^ColDTD!*i}o}2ur>7^RG-gpAvhW+xl zsXDW60vEumz5Ux1LC^z5AsI2O@mWpJHwx_)FiMj&Np_&Dpaas?nG4k0pl*2){Isg9Wq7``F@#6e0$l)%N)pZ4nuXp zyXjtLPct@oOQDs0;$;qD_YWIe(bPw5cLz%tO?0M`aiiH{Kh*}=yb&%^uR3;pt=aTra$#~uu}Of`?h7Xt?$yJ$?*Z1)VeB&e+~ z8(UlG;Xl~*Ii_6m7zouEkXbPoWTurE;m4wk2zK_i(MESguo{0Dmthj}4`VUn6{W`Z zfYo10jSfOXe^;hm1;|%zDOTr3t^Q1MV9sp@!dCV1l_OoByXVU2c5~ z99Xu*7{F>hFxHjxa$3O0vJZ@3Q)<7-ydD`7;Tw|PkBs@S(!R-DpBVk<(wi*wi7^zf z_jqCqq|lus}{Cbd?-Fso&OCGTGFO5sx z&X(ZAeBc4tDt&XmEn(5Gpj)dYY{n~isXZm?+E>O)#J7cJi0#h{3_Wrqpj`Sx!pp_1 z$zh{ATlbIADz7fq8`0H&jN#?a8@SzR6r1(hSW3StX2air>i%N3;EgewZYgHR@wmE} zy?J9COg}1SgWtk{H@KLcdkefr@hWH2Z7*NYed!(lQu9Rfc<5h#xgN#LL`-cdEoQ02 zfhYG2}{c1|-pQI_XsYC%gv)O&8Ge_Z6UkWtPIhSvnO zfz@=9(3GFq(Q)Se>egVBuPhf?f?U{&$>t{5(u*vET-e(UmSwzvSL&ML<)RQc+xWgY z!8{5FC9tWHV;RH?B`&P<6!RK2AjGs((k#_IpIH)!dcUD*p)BX2;>=u2LsZPeXYI+g z>@6=eN;gkJ9r!~i7xvpu%P?Mmdpdk>>B2JExn0(0+b#WIR8XI5DTgUP%E(>UV1tj%i>&sywgqrN?4X+h0Xpp<>XNsT*VX+hYOwx-K20y$a) z7_wQvV-_Dav7O1{tw~pgDR0!Qs8X0kG`|uzwxXTM(WlcnYy>!gU=#PtO@VT0dcsQ| zm_QQT`2_Oa_h{p-HHy=C4in6?5jcVHds@Lg&tOt1hH}YFoC^GMo1ar>7gz>M>{O;}@&QHwj7U=o@C9Vp@?0?iO7k&N%yfX=2GV5O#aHo+tkjs{8k zB;t`9hUGYY67k3l{f-?y1(QfXS5qE!8+I1vjUT#*dBZ1n&{=l98}tR+Sr+)6r4O6Z z-PA!Y1JAJ)Ip+S%`X0Q)U+S{=OwA=)_Y6BzWNEKf?QL?AX|>a8V1Lsxs#&Xh2AZl; zxk$Tlm-%IMmdRf^WxMgX!Bo)C3cXJ6n3qGK^OL zmOU713ZvD&Wr4#?44rWJSC~1T4l|9TSZcH%g8kV@(+4KH$pZ#yOAFS0f@v6C)rKAW z!xEvEO)&jIU5aoT*;N_7CV^>W&rx%K*nYuxYy~ilWKS`{G(x=8A3iX>f)h9P!$V7d zntGgtm06aXQ?ONoQ;$tE&5`hdRZc++?6XWqu%yD2v!2pA$8ZMOg8(Lv$?&5}q@xNc zh)Kr2m=K8z|FVz_7d8Ej<;%*fDBENV1`7jN6nooaj51BN7^tHQSXZSj9G&6#urOF1 z=;E}vDzk3^caTW-Fu>`NI&G_|ccq}e3SwGc8#;boygc3j$Fz%S;|*DbofEF5jfW@Z zNiWsMdrima|A*a${ib6wsH+dFJCzvC^>CKNXQeowP-6>B8)QUTmJ%m+^Q5T_FI0AB zjlMQ5ragDF-G3MtvV?C;-O9~A`NkBZo2kEjV}ixo?p^ADQ>I)ZCGDy>H=f$XU~a6# zMxHTUqYHQO`Ek@)Q&juc1u@{TtYG-O5|1^F{8-DWFlI4?ur_?0dk6lKB&52*u>{I( z;RD^f@O|e}I3EFF-f6JgGAkRhvLMv=&YG%GNTj{~-c(<1`8muv6D3OkOFm~xq3{by zeVcO=QUiRJ!&FtnJq52e=MpAlUC!2G@)Q4`^$*x~8 z?WCs@*)fZy6TAGQskZa?iLcRtPUjO<^F?S>ZpNLa>_PD7-Z;rn*i4h1Ebxj6zCv)e z)S`oP+47%EBP!g*-u`6zi+-HTo?S8>q@#1$?w?KJG%Z)X@v|wERCCJ(HNSt=Tv^wj zOx|pytECZ1NY!Ja+!~C`*H>3Cd-7pM=@_#oBe{4b=kwpw~aZVQDK|#Ne*rk{8-hu;Hrcg4E72Rw*9SXQE*4J ztgv55#&U)ILhBrDzi?o`85{=>g6#q!ZuX7uZWU&2Sr`by6$hG2Et2E`r1F#7RYzB$NT%QpuQ_p%VE8g32_`j}yF0N#MT!Ap}FJEx^kQekiKvFuWY z<9Vmb@O@4BwqW*Z6}ANnh#7{@tcOAH^V)nTSieMt;$V;Ng3ZCUi}lTvOTo)%8-!EY ze1m{3(gIIA7G{PG0@(8nLb&-?t)%S<(jv|0q2$f_u6FWe9iz=LbeuO^8f|uvH>`R~ z^DVq4wKCfPt36wpj}RK4#b9GlgSA-e)JPo~Yo0}HTQ-cSUp_nPhxV4IiAYP zS=$uzl4>Q(@IC%r@Bhk5Qp|C|-)k7ULL9EHJ#wEc!&lT-`@XqfFH;lSn=cW!&YGcq z!6UcBG8Wp=94&vIskaMQ`osRQquCcSQj(zmiNf*Pv(MGoVy+G(DWjM&t4G zOtv)@>ZD{c=g#KQbXq1~`H#(H`#PI%do=>x|1SMQGuiGg=C*-8aE)({aP;%ejm^ZD zhQ<2Ab~~zNs%~9jGwhbN6pjAf4`eQ7b-J0O$)D<=ZssaZw8dg|az8Wd1n#iC{mnI7 z6ffcqs<;#QMPvW&1b&9{e|G{p=$XYSrb_)f4E)XLtuI~K8h1I!zp zOW+sU-tWIS2e170kW+OwZJ_xlnou7%2@tHja|xAjhfqk=?nBLk%=C19zDsy9#tgfJ z9`jV#CHx@MjE1;9h@^!L`OW}Z1MC0+)`bZh`dwBC6kv1E7A>@Wfd&)8RM;2P!TZIA z;EUxK0aT5>= zFQ&r!f48>u{|;uK@}>W32Ph@h7c2kxmF8ce#A+z!P`7dQ%UAhOg**#!=d1iaGcmyb zuJU_8`M<0DD>KlBuktV9`F~dVDR9q!SNW}HidFu02E!-36D;t@5wqr;pe8D;@?rR2 zIUU3*Eby04#|6HhZpC1g?_k$HF)s>^L(2*){gzm+u+ncnov-vu*O_6ZKY7}_EB*1) zaHa3X3O2&9KX4jf?#JhtJE41Ev45J9p>rgLh&&1P5vHT#gS_OE?rhSh%HR0ga4 zM76;VxB;sI3w{S-F1ySbSX!~m4BtqcXvpVbH* z8m>3)%(*wo+?jjl&P_-Vl1OSvLP9Jdk;P6BL{Xvk+EQy(l_Ih4a&1r1YHhU>ic?x^ zYAqUFC{;yKw6(O9wwCvMX6{X*{k`w|$NkK6=AJoo&U2pSd!9KJoA|TGGyin_$u~X|ARxa-v0K`?T7F%!H0)8*D;?>< z)0qsfG^Gb+SmbH!U{w!TUI(2LU|C!RSQb|SmV?mnvk}!yu-wg89>6SpyZcc{C#5W1 z_Lu8f+9EZylTw;$$nqSv7sE4I9wE@LC_!N6BpZh0Wj}cpC^x`^a`7o`2hum^8Ns90 z{-tTiw}_gQepNu{Mr2iG19f{!pjxW@khOZ1qV4i7R^e5;YM0|#;Hx~yAxBFAhr6NV z_~McecB4#9PGJ?hnc<#mn(Xib=!#TIm&XA`6HxRi-qR)LG1jFk{T?Vs#JB4T{VD;a zTN~+ODBS|-l2E!yR{^CLv(T;rMU!azTczbW(l^{UNCtlHn?*;0<$f$Zi(<>jqgb^p z`lyVY5a9}OAGbsDJ#qJ{4t!eh#N7=VarftCWZ-9atZDLFgvc=Y6JHS^I*Hwn6=C=K z{t84Y9SOwV_X<_Q{xLNlgPgx+gM$QZpLWgzKmkut#Y zia3t=`y~sr#0n6N$y}CL0iUA-s>c=~=P04BSAtFCoZL|`s~9=gNBZB$`LmZr9uqn5 z7WBW6bG42pa<0_TgPhCPkOzu4i+H>L6TratP#+`SPM2%S#&Fq)x4#q*(GD2d0Y#Po z(!)9!Kw9tuo0ilyf%MC@<>?U>Ma~jHx`IfT0McbUa0K2}qt!;ty;_2NIiO?ai$J=4 zrU253tWhQbLuc_F^<-?pv%kG3=02c-jF|g}?MysfEma1dp3+v}>HdPPX3X8%R7T8w zRlLV=wv+*=)iz$>Bm(cI$po84;GNQ1q1o70!+_O;+nBH#ld}+WpC`umK-3>G5k@c~ z?XR?z5oyP$323@0$Dsu6tj<$*OoSFu61&g6VpQFsr5S7=&<)DTu7r3{^|kIYP_^Kl zFoiii@p6W$7>N4)<^oZV75@TE&)^UG$h*a>IS_TI5p4K!kjy~D($_=eOjbRXstkoX zd`CNn$~(mE>|t^`ZgV~iGAF;<*w2_CLE*Q3OHug|a&1<#u`pj5{KFCQ0JxV%q>O~7 zw`@!)Bhk#T#uOW4i=ecI{v+4E^QJ7ZU5#k`C>bl28`08Hax`1rh>nbsL)m+c=*B2H zHZ-ph`q>jl4{Pj&+-4koMk9)UOK!wQH!|bs3*VBPupW)*!do&{zRD|nh>w#+yCh~a)Nk?fti2Jk#9Dycsg~hSCQ2pbn6h9FXxF?l{ zOq6@G6{+;qM0pT4tu!I?m{b}wNxl)3j1vD1nd_y}sL66ORymdSO$N`xQu&3+GT`y@ z6w!!cc)T=)?o7o?{z*3N=R4D6gv*;Z;E8!MK=LDc+bu^{x|3u!y(CD!W!x(U$=B(i zTMlHGF-b{8$RE4qo@{>-Wz9zy@gy2EUltK^a5`jx{MdRAANV~H^6tgx3 z@8S?h;S6S)!s+h`Qy5>5GM39DOt0F|Y6i#+7n^G}VX%=9{|Fdt8b_-cBfkZ68-;AZ z!hI2Zmwe3tdH4z$0dkB|tpX1p^A(|ctH8oFK%pSS#dnyL5fnE{!Lta855QB%3LN~h z@w^FwYiyR2toM8_GXaCY!4@Ie4Xy59VbW$_K`Xb(-7r=0E=WYf4~Q^7USXi$o5&*G zY{bILe|ssbYfRQpaGzYl@sDz;JbuE&+z4VmZRz z0hWNi)nCNHJ*%5I`0*DA&b6;DaPS(VR%XQerBkTK1MWU0BjR1T8b`#tla=W)Cj9OD zt=xk7KLC;u%`h==lk@UB-dhA9e4RF3kdxV@mkgV}>wB1VwzsN@g^eBquYrZji*Grq z353f>nLt>NGJ!Cfn}_Cdgupkz;8roC-|H^RZ}`C!;nN4=-^+o5IYQs%EoPKtu-%N3 zm{ITMmCUI3yT8f_5~dOzba-%ZwY%~MCE!!MP_d5brQRaO?XrKrm89__f+(ia4 zp9!(erk}sexuVJe%xy}c^7#{wXqw)x9 zE!!@Z5@-g7YX|cAwQUFt-w1dyFpN#0>e#SZLjc$6+RT{n&;*+i6L!|KAtpS=MMIKo z5%I%a(2Wv6cCe8y2C@T@E(v5`bD1&Wn@P4|EY)Skghw{8iI_0`(ZDtbpM-LgZGf~> zbZV4p>&LQn+K_4+#oFi;k!DMX=n~?Nf;@U5E!vmo4G9}GLc(LyY*vIdqPF3KqxjnS zc_SMv`6|tf3?CN??{b*P_5>2?NEpc0_@|fCj1gO#*)YoK<>ZJF#|wgfY5@-5YCzlk zmNr0J{2kZIHX3S>ebC{VSJK)x+v0x_)p{?|?wwrH-qu9&-ZNswk**M*g=xP%uYGe` z!@uy}yr?$zBJ^vBI2A9mFiL(A{*I76Q%-u=USfSPmq}pY8a-|Kl60A0>19JO z`Jf-~-p_^!Cm;EGCY%hiwYA<8JoijFdEEy1TcGo};m~1gHH#Pdm{U$h*bIzsOgT9Q z^^t>Fih3pn{%)MDgJ-r$bpYWa z0Bjlg+?TSe__ycRCP8PJlqeAJa#0N5Kh4(2z|;cvTJ}BlrMtc5H|g?B)DCYk!0)hG zHh^EGjBxVnb8QGGBV}01>GN$TE&l7!W#SVyV#@8!L>oJOyckOW9#B)VeO#2`IoaBH zGw=@Y+TO&R`oHMJ5?h8P^)FuZN|1&1s$j;Y*R8gtv5-e}d$nz*>+zqWdc|NG zD?HZNQl)Ejc#SPgy2!7uv7M6w`Wd;3!F2CG>GWD#qP5_muV?m>5q)m5&Q=z$;Xu;u zjlk}Dl!0xI*4vUq9C`!nalu1M-(c&_Haw&)8*GCt^B(%rm(P9cvq=xB(?;8kpk^rY z-zd7_L(1G_YsTUp($Y=fZPkZ-*CrcK^x6la_QfcA)dM=Q#g=HXKJcX;=l$CASGL*! zquc$?gFdmPVCK;8)M>XZqW+`%W~)o$=--Wd#W?y7(*F)NBUZiJHi;d(Pj&a$LfL`) z)M<|miy}km(H`61tYWwaNbDjl_xw6Hj~p8G01DfgHwk6T?IzhY?mb5)~s&H2vh5Z4SCQ!V_CQdCG>^ zGIAPIP1YHj9bv|ny$J(VuNT-HWr(RJ6#fnL4bK<>X5$~ccfvQe6U?WgC$_v1`LlaP zxHsWCTdL@pXtEWlyHZ6nw!Gtl4Y6fB+4e{DHHtHU_2VCHx5P~YR-+1qGX61Ob>AyC z6IRcLKPw6{`|m)Wg%RPNDD%rVY(Mx$guAOvq^$k;e%kJ5n?q-R!z1P_cEB;WWdh$ACq%pjR8E5Ohg%PD3!xwca& z4ks5nm21rTn`#C~PN`;q!~oQmcHjGw^8ozA$WjUrHO6Wx-&$IE3{q4`fN4vo3$VGE zD(nyG%!>khKPaPMG6~*opy{6F6`*O{4hvVd8&xvggC42Wv6Qv8LO|u)-=r${QT)N=#8SxjGUegp8>k(;@saQh?VJF}En3 z-e{#{ur}dT&`O!Zww(`L3y`mU_Vowni*hP6L=JRDK+_DClezMCo*|OvO&nzWcD&OWfiY^f-Zi%!}H1-3f zZkk-%vi_LISbyG4DG@V%@TyWAGfwNFQjRYjpkUra?ZXsX zRgL5W2Pt(8?IbstqSP$ zT_qktJ_Y;r6wvP@l*QNTUIHUX7si)63efDcw6br>K){D$0$c&I}Xs0wfHmb zFQpW(_l~j-3nPqMVN~HCC4`qBue>L*bNgxeMx`GAeF9WP8bDXZ;jg@0rG=E_-0y3y ztHx@N$Ut9Xwa0Yyfb1ymo}ofbi+du^+Y`{dLeUd}la%$0b=t@GO;NBnFt!z#rc7g- z_EOe#u0ec(#H; zP0!B=Tq(=9&QY#N5I^@kC5gTEnc&QLcH&c$DT$w94Yy2u zv>MkxL|a{IM|y9ea*y@iLvt4?kN)QaUpq=ZFqm{wK7pQKyk${9BG6MFU@SlIIuTKqov zTlEv##{~JX4AeM5zE)sB}9c7alyIf)N&Q9I~LonQexO({I^QE z!D?_?yjtmQnZC<+!TzkWq_0ul!Fr52Ym^==eHXv8Mj0<*{>_{4Wh(nsf<)V%#lz%WfqDZgN5qTv#BG2fE ztqOuLJwGN$Qw0BHn{rRGe!sm0W5VeA$Eeu0?Y!9z!JQG?Ik*F&#&*i8hMkm$?NZ)h z%67W5OF1nzW8lhAwr3lU{X{UP#Wn(C%5vu(tbjzJ72ZYJ%xvWIopOyiSPtavyMN0+dfC!SDtVF&n46njkxS}UJa z7;C(V_BDhk9NlD^my||GRNG{>_`OX+7V6NapDQ-1@ujkk_1HugzErX-pKLUxqFo`_ z8i8jEl`J-PBXw`A#`A7xl&TVYX=9Q33FZY~DVwn;=>~Btj1D(bL-?j|g!!qp!8AV; z&nj~z=^zdN2AfH?`&kL*jlWasNJ;(I7jt;*Q>(e+OsMZ>gTqDYTNVDZ1c&nlhd(|q zq~=r15foC>`XU&M(1q(er95@Hq`bkL>*(|)<*Ia^Z~IZOkJi$j%gSQ^;cMYPX3wRN z<4Oe@c?F)X$y$?<<*$N~Ro4<28O=Yus?3(yo{zZTCZ-O2BsdvEuXa|Q?30gZNN31S zg^x^5&Oxr9l_3&aj(y8+D!~z@Lxq483H>pcQ?ChyfEdo~+)d>?wio8xeo=6);LEG& z$Ztw_)?hWA&PAW5t+M#hkU%wnzkEj-je{!qsk@>Pd8_E`J;=bIRW#(jGM_bFC9G)> zmH8c2k6Oh?{4U(f-jzJ!fp9M=D^2%uXr<>2=>-W8uLiOkp+D3 zBL%yyPgr4eEr)0MOk#dUDvZOaaJ>IRI{QSqYVG_X)U&5ujpM&O#XM9ohwQmhCL%Y~ z-LiyYpxyc2cDE3U0oT#_xw3+>=Ge(hbX$3*LLUw-=bBa3aH7m|9_p(?u^TL>%6{r% z7POr9`Kj~8I(UC|s92EeuVSg(!1wtGoBB6Q6b)9@BsS!I(Z2EQYs~Evp0n}$rZU4x z1oGK-wYHSh@x5YE8+fls)NsgwQRl)UWfm^Z<0(*QY$bAt|Km^-C1LT=srkZ1h^yB{ zq$5*F7ZFVRo$7h^!7`(T^qH=H>v`1hEApm8#5De_;9Zj~wU*H0^6Et9Ttek4sEyc=cX{^;Dt1cM-W6S*!pn!LH*u;GiBveR zTv5G&y=jQFNcC@P!D7SUSL5|wQk&o`z{NDak{TS*B}{aAk*I@ZMfTmG!9HF|g{JOV z#DUKOn6=I#$j*T~N^Ke)t$rt(8>2$Bw=NX6d@-A`P&BYCsnyjrtjj{`9*o2n)zyyH zuSTA?6&hjnw)tM4| zgsGE90R~@BQomt4^Qch+G;Cg;*_KZeRE3^4P$#f{dBX4vVd;7NPO`d7LIh|{su~Pr zHP5u$7v`CIYuN2nOq3MDy>%Xa)JPq{=FOvWjnzid9sX)#6?#i^O})L`L`BrOypamy zu*T5akLJ+$7U~`ApgCZnari*&cS-<%uccZ~O44!D>$_jNQpA`%xn{UvOp$7UF-0M7 zFs4vgVP`ABn7*@3#;j`t##n!xQ0!+%XJjej2&t_Lz>6UG!5?6872!dXNr!k%iFyo>fdKZasA)= z!K}Y5yvX}T{qv)KQ_a<%xaT!Ts6WmyIm8RPsFy4mPY)#HthvABgNd`QBhyNsgURB$ z%8H%v4%YqR2I$Y_gUQVx=!bV4NN#qx?iU?E_uF$ISzP&@AKy>K`1$QA zwBc2I9Q7Kgwqhfu@GS$?nT(}Rp~TnWZfG*!^SV0M*c*JPdd{+U62|X;vkH_pOdZCy zO``3?)D*U268%0*{kc2ZbU7v``9T4;*cEmdOA;7lVS;c{3`GBlyk z2g?&KhvX!OC^?x%8p{*JDi4F+3p&uC^Tqz*2_w{j5QigLTRCVdVb_G#<=s;Bq|7&R_=a(?I_$&*x-&s-Z!b)@+1(ql0e&{7^v=6s z58~B7R$EE5DOU|=nG=Lo)y1AGz7y3{)_MXB39`pf@=kDO{RG-KQC-UXCs5WT^>n$f z$0LsPCC-G3z?o3E`h;UYgv+^^r^ZvG$!a>=GoH_#tYVDVc06tQ1pFO1Rb9XqjHhQ) z)eNx=d78SG9UI60oTd)7iZvY32a;y}fsXCX4kn9hAHRdi??Mm+-B&r7jE>HKZP$V1 z1rUVVpr=9*#B~}3VFv`E4)Wzg5Vp=%e`iY5L&-AK#kb`l+Bi=gES=+J^VC#77B_~n z7OSIJ)EN3|u{zd)d%YY;8#fhCpYd4O77IwoAqT#h0fuM!m5Ld6=0G;Qt8~Y^6J*pP4lY@ov*u&l*EbK;GYJXg9 ztc@Nlj7K%Yc)U57U_9daH^RKVdRk#1 zXWy&k7+XAmhyI}M#~h(3{^O78P8LwFKPuE83ir60TdF!Svvz;}(N!oMo6(Pczoym_ zIjdY(u{&B&KiYRgt;?46qu3xjR)YMjzQpu?q7O&0!Tm({&6Q4bn5WKC=;+sc7e0I= z&ApT1%vfA~d}?5C5_e`ppASb2e~oXyrD7A>hqU4s^&b}V8ZG}7ubkDFGN!3Pi+_V} z>DQN!|4rTR>s95C!E2$);_6jpK?_y>10C&E>GSBADehe3R3zvw$I8 zJstOo*>Quq^3yJR7RFOq6kW<*3)y*(Qg(D)i!9M`2@)oF2H8_sqb#$_KFBgP&NtXT zl=)=wQNi|=fFNC{Tv=3BislJr?Th?ak5}k)m_0pdf9GOV`+B3PYU{vd`P*>!aj2YE z)zFF}_-N2q4)G4*_6w$}VR5u@(Nkb#gsO?FSJkG17OHkc@ww+!wXZ=7RTEdQs(~&n zR<-(-?FB5f6FsYJ-y>mzjw*I4cf2E5BR2c-dC5?;!$@Br+dAs+1j<-oufp9`?PO(Y zM;=|>zK5}s9n3B-UBlj-9qGWk*RXG4Y*7c&YS|}BSGc>Dofu2Xr0BYKOj{+Su{nQ> z06&UNun)m8CGRKLo8t@M^#uD(!)L=sPls$878yR;poK*a%SjH#0c}QFSY`O>V`z+F zk>R8Na^NHkkrq}Ne%hdgRTi=V85UMKroR1c1WMcUj}qd+2j4Uz=)o z`37vwK-;G^bo=bU>1Y8{GdE`N6HV;B8TQMn-rSDK*s*+8b33eY4))T^Rbw2h74XP{ zPp#Gsz8RF!5)v{7+v>H1=$&gLoOC2brQ0X4T5V`Uy8TF5sSP~!-G=V76LHEYuEr^& z()3)Ky4xp+d>fDtKASdnx36Kg7Cf_u{VaAwY0jg2*)O2So0DH3 z`*`cMWjUQl-W*=iCx&iioCg9=AaXF%f!kZg74^FDkM|gC|k3kEM4*4-?kNlK@{1|DE z{H#O6z4G%n-wpoN3a&c(?hU+`>9b;+h*oIf3R*Cq3_)1e$m{>jA_ zE5vPDtmzOM`F^;22KeE%Sm0;TplG_V!8Hqbty%UL2Nka&ldxFg>a|$?KnsiY5tP$w zu|5VZES9)>Ef#149Q2rH$Drc1By&*Vns1-Q>SBAn`S!&DdJ?!Rjv>NsYGPnvPcpH= z=mqwLR+gE_wReT73an2jmO`W)^?9RZ;F-YI%k9&w5%nN(#^FL6mfOcL_D%v-USYp& zX_(-Fl{Hq{N3z-pwB;LnBpqLAk73~n^yf+lq7XO?GXBQPvkI!XTL>ZaKuLr4KuLr4 zKuIvM2u79-{tfo0R@a?c;7r@bZl7x@ZYh3d=52mzD;yT9TZ>Y* zLmH5A*>)j!pT!$;N69zsD(+JE9gw(P@w9vg7#3K|l(_mk!SvVT>Bvs|SLG7oVahB` za1gB%tE8K_eJ(rQ(%C7QHREafE{Iiyc+R*TgO2Srg&8}6IWceVhK=h`lTPfm?@}t& z^j#=_=u+^kJn6KDlf2GKrb?_h-arK%rK?`%X0F3dPvxT6AITKf}Ia>tb@tCtq z60dmBW6lOZIE6XuddNPQ#l-OwhwK@CY(jN-JT&p`>NNkjY0m~Bqp)WoCt%O2SLcUL z*b!q{Ta8~hX)njvvTF3_Y5RD~%@_}AaerxlPnff8*g;{=5(;6?*2eG)h4vJSWq)+Z zu}Shb;Qsb#AxRl*c{Dxy#{S5#W*D2Gg87CugJt{U$HwkA8r5*$yzb+yD#jfiK`WDI zj7;x&h0OTRBV-0$EM$4!u}W!E$nr`ES)Pwa$Ob_8EW$Oub=Hn$;eYcv=j?Y8hm4}} z=V8!BMe*h5?XhAh@u~0a7h%w9@r{@4lCSIc${xY`99wBZu&SfLa>@u7J^ld`rfp^#6GQLN>`c6rgT-h1?d`IiMHRepJvIGXyR?yvk2^1 zcUvH;+NAzse<< z>tFUJk_f~6WA86L;!FM!rHu-w1?x(QN zD)7p(W0Xa}9MutraP2A8(cJZ2dE`$O`7u=t`M=?n?2Zp)>%wv{L`HP##C}boUrRZD zOPgGf?89&_Erg@u^n&Dr*e#(E=ti>(lCNU7gvOxzjDt2wH&C8cP4 zHAgFP^LaJLHrAz->6lJecPt39CAyQ)-Uj&LAhb-QFl0ILBkQ9~<4(aAdHg zQZ%TBqo0_n_f-wYs))fA-BBgFd|inyuj=V?s_8(NPYE!)ynG!;6UkCNz@y&d>N+~J zssa3LU5CQh8W&xy=ST@y2~q>`i@IBi{!+_io%c(9^2UQ6=Sbz z#F{xW0$OUG{5io!{-zr5-ORB^7GDn9I&SvfT##&+b22f3F@MFBg5)`9Vl3!GGYXRL zr24qyK>xI@Ald1YGrtCC>#l<2{J@;dnxHGqEl75Q4hQY`i774>L09?A6qg9l?G6;s zyzd-Y{9rqWMY6oCViLp%R|S5pJ=%(0m7+R0AlG9QitXq)B9@|bbo6KY6zbjy9NcSg z5GTQ#N(0AK97aUhLTMs93l2uuIFzP4Ms_kzfprXGM`fPX&A}LJCR6wBj#!o`)7sIe(3LbZkg-r5xu_#I6h!lkg_D(f#Y~-Z#J~( zD*cx2XdY0APm-6%iZUXNGEQ1~v)3KFWHy!YXCob||3M%@$)%j!+%i?8&F&sM|D~~+EEypgXdM82O^{Iqwq7H zMk#Ti?Z`bFCGDT1Wzwy;9rl1F4cvC0oPgh|__#%zPK%=EYH!jzV;t`?A4%}PJjIW7 zGz)v~GM~# zZ&6kG(03e|)wrYqZ5`*>&0>5ApUJ~%=6FY~$_JAT6*r1@CA(#)dsmCxYJ$Jd@K#oz zmyP=ald1o=S|~{q9BaeAe{MA@B^oO#WmKjF%Z^TP^eBE{q60^|^JkPe8HT3TbDB9BhNkRu`h7Cg z#1-MT0fu==3pk(RSYlzrpYqHZjxmxo0H1v6!%l(a==Mw$=zPi(X9;bY z`-D>FI4ZNrPpID$H+eo`O~o1I`SWS%!j<^XeI|$dSqSr2**o^O|E-Ql-$e@Eqz2MRy)S9 zk$+ONHIC;clqRo)(&QOR)74O#yb?;2XDCe#Luv91rHM0?Ca;9jw=M@|9F~2o&We@SWT+)liyupfn#qX?}sy828<& zG+~?Ld}Q1o=BtIih*#gjLs59OV#&$;1+?JS*zJx*F=dhQGK_-QL9(8YkFoqx9NB6- zfHw+7G9Ez5P^77J@MA|p*wNo#R7Y>|w^4LDiZ&Ff%?>CMiV%wQEB=@*iV%uq+X+RQ z_d6x-bi{8LhdJO6Nv7&+wObIjmyG+b-PEmSz7=8#wf+ z{qGd;3G`@qg!`7Q7^8^?y?SKO(4%vo2t8VVkB|5adc@N2(Ve}H5v=Jw-WzL_82kJ# z^*i9`6tLwkn9%`>Z~$SxrBgCD+~ubaIHDDc|8Hi$^3q>8?lRWxSModU$O>rst0#Y2 zO(TE9UkQp+g)cen2$X}?-u|!lth`NUpE_#M!?TXYa8vcqIUaa52$N2WeEA*FUJben z+N(kLKno4JS0N|!K4_sqXFy*D?bVjSpQ7e{zhKEQ@b=6yp3fblrj*Jo>s|c)$&Okc7pOZ&0V79ht5_u7i=! z1>>XL(z|mq@ABP0I}&Vc#ZUbAdk#fn&3@v~?mJE(2zQlEJa9y?l~?J`10aOOS1I%% zY+mkFlyFqouvDXjaaYZ*SpU!wECT`@eCi0qjKy!CI^JUO*d6kjW2V?>^1?GmTW<%5 z*}h&Ab{e$N0ZBgYFF|`dpb)g^fV>ttnP)(Y4j2yl0BCOq90cv{fJ2~*OxX43!i3HG z(QCr&k`|~z6(#pcWSiYmat|iSR|}>ll9pN?2Y>kd$C4dK#;9B$VaXQaAGrhyvtYtaRde*I8N>&)^l z@VccDU}VkvNWF zSJGlx=d)C0X{@sg_^~#uu#ZFXB2fy z(PlHXkZz}F&HN!;dD-|U?gyuvj-_hh)-S$%bknpHE2Bwn?o1mlWR!GPLtcn%D?3wCqc|-3T)DW~6(42^qrht4M}K0YZkh zHr7^Hgzaw*8DjHK;eZ)!JezrnXS5X3V>?Bet+XuH?ZUE_p5S7SP@i*jCV9OPmi{SmGL0b27Jq7M9or`a{rOOS}TK*Ahegiov9B zU%ZV?I>MFLw0;tcIzpG4=t+EYKka8p`jCeA(*nufT(3yS2WZQrC-mAttv{T|se#(M zh{Fbd^Sroy05H6Ft|j=JFZfG?prfqb=e+I^ZHy$gpdYHeflXj44bw1e?odF{BcPlu z3n+7hmKjhR-_kGtB9v3W@1>bF3iz%OT98dd(Z*`3WSMus!|#XhXkRic2sk`Ji^OF4 zTNAW61f|R7Xq^KN?nfb$L?ITVkiGl)#2mr=O8frH{P2Aq=Fb50NA9I&GqjnQ*?ne) z*3Rn;=O8rg?Si?WjV_4uanA$o?Seee2A&^~lL`A+XyEz&Ihi@2y&aK^Hm0 zA7-KptfxNnIztSCb>|ESXw(X;dnT^w+pH8hTkBTlUYS`Y02{7Q;&)0HBW0B zcK=fo;VLLW3^=DFuZ$9nccV0nf)9ijrlYh6RV?l&kriHWhRB71rG;afrDya>FF z7nuwz6bx&;P@5975t+Q0zIF*rZ)CK^HMDz zJOB1Pp7vCa34aa1>%4y{a?KVr~eC|pu02{sT zqLr)R`quBFuU2a*sY`aD9U|I_MKdDWx(I1trmy~qOLIRNn&y7*i!k?NXPUc=CB@EZPn7lXPVFz7^}<$2jW^Ewhd0FA3oZ4Aczc8P`qn<6y&>Md zphbvRT>l&5&5w|czmXNR=r)_Yl#ur-(n^R_6^HnC${_@4#ZW}vy#xqcjhUYleo zyTxORP94#13!I04;5}QLqzLkEX2F|j&j~G_MQrAGPH2OC+0l(Wt5CaT)eB{pzajAh zP$Bs^wh4;{%A5VI_908$K(S}FB~TWZzX(-kf zgAnG`=)>={No5L8ANMPAmLdvclp_x=6Z_#9*%O@dRqKF9Obx| z+yhGp*0BFSX2v7)4XvWxkQ}_tkeu&tXkF~=F^<(1lGEi6?I*@E zR#M8JT1G(PN>2f4rHumWuEgRetx+JJH6&(fYR-H?3#s|zPYs7!PXA!hpUxk>_Ph>TUpYyOq#vgGV z9kEo&-$|?=rn37x`?1!T+Acd+MVxub-LeF%L2ngJGHU_bEPCq~*$FdnPndyLxb?5z z`p)63!5Y8E70rp>`ed2eTU~T#XSQt_->!?hm6y?_0B0;Kw~VwvXG(yw3|xOpbXx=H z>GVv$Wz;>;S;-FBO?!&h77BLH3v{lqv)yENTgPyx(}F{Ns9&Tr7K`8(MLL_iZY)MQ zorS(*e2a1rl8$s{n!S%=jNWhck`uaKdm(gPpXeyh`^Gve7J+E6I!}OTarG*?@eK!Q zFNkgmT7YPA^?>Lll4a-uL&KwKN=;{D|1A8M)fJ0XYdU{pK?`VKyfcM`F5p^iEk*K& zVC0?d;$H-wts*@9GTG}mTUdt8_qfO5b)3!F(D{5%9cMquKOK*x;}O_^fs~ivyj*k# zrXYmo*K;nmj>UWc(kI{)j288s^#al0Jozuv4jA-$f71?}tnd7gMZ0N8qO-Rn3J+cG zZ;s_^k#x}+XqNn!zX_|ulbn;Ki?k-m+1ww!otKS23{*Y2fiv9tUY^ND9EH}v8RoYF z$;(wJF-;4J@V9LK?I$0%(bo0;FW3!F&BRxtIs8DfvlLbtk5D4>-yGr&3rb?+)>c-a1FlBJbE6#tIkiD+XH~|;CIy<<|O-C_}QA`?+`$92aQ&czSDC`4;QXb*{ zBj$38Rv2!ln{$dS=<}%_rxT4*SbW2F0w9D2Ee*l`%FQv8qwcP1D%0des(XL zyBgGI_S-gZ=;Yc!XKH!u8)N%V=p+gmqYmOE&_T|H*mTBaGealg+0F*cZwhtKc2>~y zv+ajBM{N}CmrvNfuHfbo4$PAxjt;d|HvdlC*Dj5ophml zgPp{op6%1<2^Bo`|0~B&spg*~cpKi6BZjj31n9+15!sYnU^O#h{z8*g!GD zCplW%umnb5F;*KdmrvDW@LB$ZM zRt(e#InK*QsYWEY?3>Pnkm3KMXd@SjMFb@|5d6wZ$KwJo8t)U2FVF1XKhTw%AMehVJvHcP@^%d!vr2ZQK;mx z@ziOuvs1wK@nBH`bm#!$y=hZ2w~WWedCrQaDvDPM<@sf@bF-cG7;CEHUbk=u8^+M- zh0ctC#bZ1Lq{SKq%pXIsi=1zIv=AjfVpZHI$k0N*$eC*knmqcyS~y`eWqjbAC?>dn z;4BItJJ2Gp5^A6gCG3GuFrd9ksDn0!Y~}F@2DC9`3&AHC&|W2!Kzo&tfi6*~)cw2#T5@`WYuap{Psrv;el!u(%J$VxslL6!%Sh))vK0`&`({FJJ#} zFP(T@^il$KIqhs^EsqT5(ej5*JBx#3R}noBeqCHk`t@r_d;R)#OhFKSU0jQUV{e~v zCRn;;d*J)UGtLe;%V(QHwZ3wGXj13Ca`s}62GQwSS_F0b+F71GALMcLcToK4Z3@oF zf_byF9^`TD(phIKmOhAQoOKQt!&Vdrzh0JKJm>81NjE?5JZ^0`5RDPTSZZ*=*&L|8 zy=s1%Lb0->(t-=l-=yo5`@QoGY*+d4duId+Yp)8&eVEM|Kvyq1@f9K)ci^$NS=tOh zE5th9XFtFsWDcO%OU^n#^^$6g80)~&itraWF5bk)UJ`a-TYt*D3_DPL0Ij?Xc?%ps z$`#04{mSlJGAx#7xVR2Z+8drh0r{B8#J{}aEcD3RFSsS-?Z*l_9P`B+aLiIaO3cth zd5xbTbZpdXlyb{?n{{}NN8dJVL0{_hE5vSJUmE|bGd*BqU&zWT;a7p|!)Il#?MoMa zg?r8yGAG_Bghc(#dCSgP^zz8u-@+y==tG+V7>Wu)Dv2x@7Oh(N4qlHj#hU%gIbY*!Mf!EYrdMLU89e?nOyBTS^3X zE~@%>arxcA7*ABc9l{yno8~Q)5RDRyV%ysdpN-bt+l(he-q3H*afev|s{ z>o}U~E%eQkyoXtc_Z$=VD>_8H=TykttQRU@ zn10Y9xLBBd-a)Bv>zyg1v>qKZ0lB=)DH-cQtqP;?I^&avcuExOiS=}(vO#)6NX`Gp z3$lZBBhKS6{5JSiI9n88`0Zdl78Bg(1nZT<3pZDExG&(}tgr1aM0bpq40o8(o#|!t zC#-K5np#%R5Zl+5)%&v}T_~lTzAEDV%I@QGadc<87=(LHjuB-Db+v@(P*)?mBiip# zSGb2AorR`WdcS~-OwY3iDjCnFX9~?6;lyKx zQi`ik$}j8cP|B9={;QNt+L=oEW*U@oQCm8crWehe*o-!Lm2wMcLn(3S(N@r2rOXFy zC}kxCyFnXD3Hn3OUZq?C+N+c+K^H0IxJFP)0d5-WSoS(MgCo|BiK+e>^mjA;H0zT= zCz|X1Sj!BGZ-E}UU)jB0F8&6E9x48Q0KE}C@~DOA5o4ge5x0sBs5L{c%@SI3bPIUD zsg>CyGur7L*hj7SrFP~&~| zu%G)o=-X5#wcsOq=m8R2-P|;!>wD^)G2iCYyN@0LBsisy9w*(SoqhBUuJ4=&~ZDg)S>bTGfXMJNkBGuN}pg zVmtL5uKOx0G&fkDm%UpPrnF z3c~9iL#IZFL3XcoH_AEhG%F3MgLKMx*wkSdVR-9TN8cC>A4{ zI&^c4?hv&TBN~H6;&EXaKN<_mc$2;zt5*$;a=Q1R=2>5BFW5z+HMvfXs5d_0Wn%Tl zIM~F~RAD@9A{KK@9S;p`S;aj=79T>)36wH|l-`K9c;3hNAa6B6e<-mzsk~9Hz7i8s zQt8Gd{Vdy(!uL(q6&&H3LMNu{gP5Gc>(0>J8c3 zn4EeO3xg^w(SO1o7t&H4Uol73=i`^@UomUVde(*Wx0j*Um!nE~^(g2ARCrW9KK=t; z@w4=)>j@tx{;n&OzedkvhwD+&tQN|v_B8@J9H#{XWg55gL(I@E8Y-pq2LwsAX@PHogDvE#L|MWlYm@+R&My^n)2 zUfHa_%(80Jmd*MQ=?t&1MPG+wp&HTAt$HqNT$|GK(KErd>F<0!k&UiJb+_q;g!X8&Ub?k8!&+G2ezsJEiF5cD_a2#j43Z2PyQJ6iT4b}Km$GJU7 ztaddl`e(wY`V31!4YTevw}~r&8hoa^mD~XLEIgczqV}(Gb!2R24T{~b&%`3^-TU>0 z<~t7Rm868UIMGRx@wrEwv$R8`1F;sxKPNc{X|aW9LQx)ZnsM-kjd51$Q9rOfTO3Ev z4(aLEKVqTrIZgHQd_aLdTMGIR>FG|NfE-q4)&L)$+E*-c^s-n|4nvCYIq0ySiZv@| z4(qMp$6_h;C`9tDSQ>LwPiK8&>Bvz%leLYda>pR()ne(RWBNp<#!~cgJ<;-db?gIQ zKd>f$_qbjLyYEz|)2&=VF)`Iq?E>-Din+!4&>x6&+=1i)@N2S!P?_YRbIXvkwX3OR z8p??)9Z)~m2RR35FV^*+YS4$$0W+x7NxfQ!Q`JP-lKW<4+FuPV@+@(zSDGk43~a*M zFz?o;1)h9YP!EwO!IS5I)nRKJS4$R(4a`sKJ<3TgcN*$92z5TVL1yu^ocgV57a)V??~+$ z4PFS5DdI)&hD%YnXNXm4h)mFiOys#Xso`dCg*^R%4e`s+{uY5vV-k_!{&kf6@af?W#V2g%|~lU~{Wb=ui4$_FZLR6D!ljpY;5YcswMW8(5nkmFsec zn{3XHl3WxwHefK7x~|t_BPvtIb$x!w50(G#x&OJY|HjnHbo++hwj4_OrB6e5c0(Wc zz^AEy3F$H3fKtC77x1cOU}Y;MjSr|mg+IgU?x`fKZV!*az0D@NXzVS$tmR%MD-X*F zST9+ofchdg;5SA!?&!5G)n2mF-N^yf`NBK;bc-b=ve=L=XCFjT?3=D=%R=0pHzNQ$ zsQ;nABw02`cruNDpf6`yB$EVqMYfXxO4GTxy5!oa)MwENzfcGyvPSxQ0sX z?Jyc)aW%7?3pHFr5S_8OIS`vjwdMH*yK9$))hti*b=O&};27v~MOs*V z2+b|!>dj`9qu)!pwpd;*XEhc>Xa3*pd588=W3yBDr;SM6HCu;+3DGQ^rRC77#QJ6IoCS>*Uf*) zSeL#Ffn&m!ms#K}$r3orw+wGo(Us2Fh+sZ9($z_} zo-E}7Jn6P3*0H2$HY|w|cOtqn#JEqNCxScS zF8*ht>xje_>$ITkU0pk7(3?eN-gvAuEdh8rUNFK95ZD31vZ#F3K_{9_IQ41%b2x~sOOlEZM>@qA~x zD_CN^9j42^W=C-)T=pxXD7b8+5fX;zP8VDs zFM8|0Xm}e}V9Yz7zq}6mo=C%q|F1U+2W>eg3fOi6h9@@YT)LAS zc*OERwetO2U3DZH*3RWy4!Ikm1;~+?j@AfYZP2;c^hfw=A3Jqw?@F}vQcYh?;h8R9 z2XYFRg&G0*(UyjRAJKQ2F1YGY;i|_;fi3Y*6mnHWE`vsS@YmN#?_@q+{0Cp&H1H#d z^-+Y+j;AM`UA5V6o9VdQz2e%DQcCf3XbHznHry-WxK-p4j@zhFaj%Hl?Q0R(Ecy@R z_xf!!PiS!qUdYd5TL#8UbS(=a@m$6^IG?(jQqQg~Uk%xW?=~Ah)s$g45t>ok%9ZunBFi`KKMtNsXBdNrUu|`UNiN&rKy>kK_~mVT3eh* z!9umC*I#p0we<8eEL0o1_L^&0U<*I%!oMdm_htNqg=&I-Tm2kZ!LkEH_RoQJVq%fw za$^Bm#RmLA8&)EH)zV~hRRgkCa$CR>gGLX3@pE9qDzlKGCE$^n!DO>HvtMy$-nKvN zuaKDiw*nVQmfgNM_^2RYg+G-V;cCHREgVxj{*)~F%wxhXk8+i!9|i@=Wu|}sRr2`vF8DjF`TybTy5pia-ab2f0ygA!?{;s& zAfTcMmVgZlU{_SsGnS~q5@Su!XksjgAetyDa#+R~dy5)lFqXAqjj_wmSYnBy#u9sr zEo$EH%&--}wKR=BNHPW!Lk@RA^)^y75l$HFYcIc6c`j~cqbd(y*t@BECR^VZ z*Lh%dVOvR)BiO^Fv4>%t(N?cu1P1~nJ+mEW`DqcX_d*gZCaWgdjz+=@OJ!ZUhzJ>U_p%=flo?zjzZ>-;t z7Wmw3lC?Rh^@fh0WK9sKy%y>8EMJYjnq+N5#5Xi znmyAuoRoh})6=cVWX5Y+Vv02jbIkcuP-~mlG-RrEi8$jG)-KP+MEtL*)^V19Ug1Sz zGpv>A%xTuXmNRCuEOlg9H+wHel27A@PP01bgA8jAws+Wc>v8Mpf5e&33TWXIv}&fc z9BKSYkI%F^aX9!t^xjLWqHoT!w)ZADdT#bQx6Js7kX{{s7rw^A|{b%p?^`%EvS{w2P*%Y{ThrihizMTU9!qP?bT+4hKL(gsh znUX;a5fc%_B)-0v)}$gH%xN#|C2$4#1d zHO^FSo(UW~32Z!-XZTyJFZ??jf^^hjclFQLko2~0(9zQfWSU|CjV0i@;+byJ-Vsk%_$%IVC z1U4hBasmWy&1Mi88~gwF2L0Y_IZ~hlw^<{Zpl!3ZVb97`n(=}WT&2-P+Zj9+d~+NY z*~8kK_NZWU=;1r?{^ZbodT*!ogy*dL;>_ngX^Fj7Cw1&*HuM7;w;S*Y_sMQ+Ptxi> zeY6|$z2!a~w#S-9EcfYxDOQD+-D@36hTW$bdm-gp?wL~FVIQPC2vr(V{%W7KFSf?+ z{fqSs`Sl*Hx8FLNIPTE^FS#*&zTcV|{m)&r4gh2z$duPJr2W|1S(w*jkXIHv>S#c( zC^5n{LiC$5Ui5>h?Kg$(!qWF1t>!HUs3lQ87-ORsx*Nc(E%UFvfL01$gu&nYEuDosnBv(^=B z{w1={*+ccA=d4F?WaLeHubC7;dtAWe!53xKzqE#uVt>)KgXL&F3Nd|w2{U*Gzn%)Z}*+Fr`L{-=GVI%Wr6n>)67|99B%Hx$kB=jp)~DPFu-Os>>b)oO7$R zHONoKgy`GrG~r9R8V$T*eMNGv(SVznfGoX6({Ezh>UW(6EU-q?x_?2D&8p=3%L~$I zPFq((sktM3Xz>BtO{CH->lOJ!WK*|_pK+%@vAf;R8r`J`xuuE|D=5$fQ?~) z($x>3)6%Y*I_O z27mfhTJ15E+bO#HF_c@At2FM3bqPsl-xOLGfTPp?woYeW`KK7@bFR=go#X&&dje8P|+WOI;(o%WxiwgzS*2vNl)K-)W!hva7 zU2|GipV92}?SNgBrMlvz^BAEmt)Vo~DnV%Lv2pv>nHtQhfxg1q0J`yErZHXtmG}}E z&Qwz3yrHksaAQ$@m3+?7SM7PFh4s~5mRCeyH8<(p`f965^RC9ZzFLe1)>^xjE5VeG zP?sw$<2r^bCVq`4<*wA6vwF@?*4jcobtAlso0`qh+|+!IcIYgv<|ox7VQ0DSVzS6P zz!X^C0sm^Y6?C1y1m#uNn4{4L?@0jq7_PyJa}9=m!W>QJiNXbj8WXGjF4CV)`@T<4 z21+$a+8O$$oUI%U4U*Q!Ts&hkwtzD0&GJMh&W3yS6w*wY-9+5o%^`k`_vY@^9UyQk zGlQruhn;uappOf(VV<_5yc9_eo~8@7S)0plGN#kq_3~+&yMXnGyP(~0+gN=!ft;lSFS%{ID-*b#W4|`ua27Ojn|0e<=ZKC{!v-hOhQsxPFy#|LYztO}V za&zI4KCPDYPf79PUsWF+*#Spks9HCAcLsj_FWa{RDB@QA1-bZz(}z9XU!v;-u!J%2AqpQi`C9;v|Py z{ivy}O0|~4#cz<}+N$_bJn`PQ+G;G)1*c$m`D|~9+=-|%d zimL8WuBcR_f*4)_Q&esurl_z3%#OB_ztsPT!9%y6I)B8_QwNS1da7@{^a@_f-tDBp z?32-U(h$<>hz=+&DFm;oCzjoZm?g9p;i?)R zNZ(=i=D5^i`ti=v5nOtw7NZM4l-e6tJlMu=X4wd~eL@#?lPZX|gC>Zt?QWCli*8Z| zR!60Jx^9DVFzPbAYv&J`Fy0_Rs!J*#pwT^TVRUhVRF79~;`oJM@y1+~4IFQO0O=w) z{#!ncf#WR>7&snrfM)apj!*xUzKN0}^isVg#KdqE(Y-!4wF2Ll)1 zC>ngq^-jeKs*i2Wg1q4&O& zI7?WWNqr9mWY4_!SH&_9Zi zHKAXOl4{_ChUKFqN@{~-v~=1(bGOJNW$0c+%8Kzw8NU{A6x$eSxtP04r0uTxHl(&B z=>z}z{|`ArWuL(rB&CQ0anJ4R@S02=D@9_#KI$zRH*>ea;%4O6U9?`ZG+K1vzUnu9 zTg@H^Rbi}CxaRdYo^0dzVmx+6;&Y~pQn6j z!jVbROg7h=EQK-bpDZEBRMJg>P?-<4O_4IiPm#r^A%D^TO_9P#=N>09$W* z6~fkR4{f)8cm~7P(5=AMq35Ksdgg3y8cTZhZ@FnK(SN^Vrmk_F`rkOD3W=)!kxcAnIn8 zE`q4_^Jxr3{Yf_vb*@hDEdioF+hic>r%QpTVokKeE#pm_P*nj;t-`7?FclrHxiK}< zJ5@6*V@Wqabqa1Q3aVdkGC;K}ue30z9%gw(KsDZ^bA#$0lg8k7;l{aTj89?Rs0zzi za-%A)H8-ke#^Fghs_x(T7F9X5iK?91L{(1BEMw^2(yOKVBywXus`B?Y0ffIlN7c+9 zBm^%c(=g8ckr~FC8&ff6(M`-S<^#BJfr+WLHkg>YAsd)FWxa{1-s^y=*VmhjEr6*5 zSzZB5{R3%+sRy`aY;+R8M$;Tqe*u9TQw<`CW9mC@Ffn!BdZ{M+W@EhsKaa-I)LkRD ziQRXy&Ttn1O{eK!Y?KBN7AV!F-z?v*gP>$qwgu6#d9oM1uo-6HZMtfU)P%*Pw@BT^ z$aVNO-XHPRzFVdCWaT=#X{(gZ{O8+%v;&abCe0PsWkVpCC-?L1(m0~6qscqq13^sn zQ|vzZaJy8F_Udc>lzQh#ZOE={`sNyp=9M{8Wn#^yqp!>HG;pUh)cWElu~4)EA5iR+ z%8^g9>7W~O?XXKIE*Prln9YpjrmRzQ*|2A!3Vw}F<)MlOAYh>igCM^{IWY@Wn8Ykp zF;SqtdnB9=4H0MY3Nq*?eeGW9mX~;GjcFq9JB+>|z1Ps_S(p^9J1XhoHk5HgIUC1$ zG5^lVW6V(APhCgx%4Kt<&0-)(7^ITG9`);6X1cxds+M@Bw&AcOU`{Kk)cV zAAMe0K`aedGUIrGwX7a{kpp-+{ZbwW@N)F0s|>))832yEa=nq@W^wkPFpD!+6a;YZ zYYe~xU57z8IJKM!;9VFE^KG=b3E#%DlR`8-K4f z@%vU^>nA^jbvnmz!Ph8wfGPYRR~Pwq~wlNtNVR;<8z66DmY-=2w2Nc?if4S_of>Ye zD)x<(v6cu4=B;*@^o*1zi-)t`g1JoJt0`xeNUiGnfqOW@4KOEJS=6VFoGxB+aTu>c zf2kuk;4Lv1b*&jLw>%p#?v;gf5g1R;r!ips4gDxe?#RR`N^VV>yL31l>^B5=?u-~3U~=36O> zG~n9?0ylgcMB#6rz3>eTzCRI2;55UN;jWUreN%crPR5eoLT^vGE4p$U8Lnt?s^N+b zZzrF${4&MB?jYKBq|J+lw+DqZmHKp$n-hN4G#Gb4MGQ z`F+L+m^=EQ;011Ghl1&bPrA)y!zaCelDl%l-&Aih_eqn=ll6>R(w>rZp3H43G~aWIEBn^aF$B&El6R<7W3DoYFU#jjWUj`Ncequ=%t>-&<&!-WWcyK1|Gj=!oy;!?<(N9o|vY?G#3TQ97oJ7ci+h|y=GQ`Mymb4it;h$a&DwL#%@^9Vqq_jvkr1n_(u_DNW1dsBVyDZ)?v z^@c_6-Kw&yIQ%JYzx5>Kx&78F!AFnDd-WM3f$QX13JvIFQ)v4!a#t}i6+OHbpG_Va zBVWS@9Z_%LJ<~fi%7FLW6bA1|nDB0tqypZ%k9!O661@ONONrEa4BlZDM49j&jKc^g z0N#frb9fJ>6DG>A($Nx+K$cHNA8>g$;GME`5qS5@r!n9?Bbi(2;wV(f*Ue1&2B3m7 zc)x)T7iHvfl%F-0arv#4UYu29pgcx7*8CcBpY4r3RGF2|mPJgK>nnqBUr{6dld*=8 zUWeCN*hpW^@`|8*Rg=z*@{3Ix#*3nDbCjQi1{lg`PGKk?1 z52Mb*4fSxgps$#-1>jJ$z<_#U8^adUMAE2PawHivnysig5%bGvldT0T^_DD;v)(|G z?MRzYpIM-fFx)&0s9y#GH`E)_7v+ZfqBrRGXEUhJ9+eOEoWg{9UL~M@jW5qN-=F6) zkG1iA$MbJxLVg`dUw$W_wzx(@6l;6{N6TlUVUfO?C;w>ruCI}xk#z1NxgymU$Zg5Y zk<@dc+?b?|q;U)7ZsLWnAR;s2Jl?fXZeO|ss&Rk*af1demStLFkvu?HNL>qL%tscX z25BVqSuD>Md$2oa`&Oh!7R%ZGo4ztU+mo5@MX)~*gO^_mQN}kQmZfrCcxxIim1p?( z{(p#XFO~0-=_Ba5WimbiiTaN#+g&MhWwWLI%b|RtN6>&3n32GVJ#K}JZ$F|8|MeFm z4F5GLK0-f~D%~SAaE)A(WPd^7#jd7LSR>=Zk3GXpS9X@Ho z$DUy{eiMxOK%+Q&lZi`hw!gHN(V%XwTGGh?CQ8+{%jI7j1F>1 z!Su;yxu#{z=V1HL9YEl&TY$j5KBu#{0D;eZj>Ds*H`V=rF%bBsC#p`Z?E1^|EdmcH zjKG;5AMVm4w=o26hch%80zcRxcP0CWQn*%vq3f}HYeEi`C5t3_nmEiyd8((ej4?mK zaM+!|TE@xZ`ow}boU~7#&O(V^t|{Em_B4@rbRt{Gm@fYMnTf;|4#@Rc6cMd)EFSZj zTObWAzR%J{uy|NLje*72KjT=8`K(tT)48I<1!Z31k;{;DP1+GhTW1HuLn!|8$w9R06 zGX1=)8-@oBriuRp4Ci{|4%6Dm^-e9VmpLK##V#xN1y2)*4Y4fEf!M$RbQc5ScNCa5 z_ostQoBQ`O5XwCRsn72~;`auj3yK)siv}XE0213k!;l!=#Gj05N`8%Z;XadBxS;?N zgUIvkA*|! z21{;#Hx!rNA$x7gliOozGJrZS%Z=F=#h2yoVyph9)4S9axjo70PZO@l>6Vi0#=JZ^ zmWE%IYmj7QUzO*IzxLxeiz8hBl*f_k{ogvjNhzLyA%4v;#IG?!ydQIU=SXGx74~+Q z>__8nU)(q3;j{R<}TCwKQ?z}fnkK}d~C>sMC9At|0&=$ z_n}_Q<`x7SFJ_WtTHX9!Zgr3BWmw%Wdg4LS+_NKX^=HUuo|JCA^n3rxRRqg85YS%5 zY~i$}U~547_M~46wnTEiCqwEt)yu6nK>vUz;-gzCyAFCnBb&=b@EuzE zdC>;Y@0ehKeqJ$KS8@o61z4HLLH`R++fkU_@>|Hy_D+=z)4Nwm8%%E`OvvXYSO+*+ z)O!?!{7*~SV0zma;3Li{n}DC(gC>-*rHhBVn}BcgwZZg8OC0XUb$3g>0r!ttx(M8l z$fq&j{#JJb?oUxcvb81=-F2+}1KbZm6CCazc4KUQYjl6YDlp(4tnqWhJ=o%BzXYfi3!@Vb~xCq=&HtF1O|C*%@xc^V%9Pa-_1I+3URBW)iWjEYs z#^FhsO$`9gjKh=i;HJ>+E!=}beoFyrW_7!%Ioy{<+YIgp7J&Q24{3sCgL}o#jh3t* zbgcek?iKkh)Wfv)b3;9BZgiCi^+gLzs2|$Zg!%*JY&FULE^OuBiI||Sc>N+!zpM-L z3P8OBGz{to@F}msAAXHSIn;ZAzzy{Vk<1_d9XGH=e}MW@T@0vqQ!uD^R~b{@2LFoj z`tCgD8rQLW{dYp1cVgeK1kevE*)~}Ab~1rpuUgqQn4S6ZZK$mUmiAo^we=*mI?={e zY{_JKC%UJKEsH$(z*xNgX_##&NkBbewk6{74@_)d9BvzDDa|U(_mMOAU{%{0vi<{_ zUd=X|SUxZoueYpj%Z$F!v9MqKD$+$4ua82PMTvg@@szj!z*xLK7}|3%hDk5HKXaG! zG}zs`hK(&=myN~ipMq*Cat(KRhmMB3{E!oDYVy`y9*skh+2Zx^j^^U^9*u2v#lUuE zaC28<8-kll;_)4e?X>tR9&e3x>%v3b)y&pkVB7nkAd;>9TPpTODL1Y!wlxsGb-aP_ zeOuaq@V(m_2*0kC4G2HEEsbc6WnDL@tCh{4X2YpM*R-}d#5-+Fly|hTg^Nwwnkc`& z4W7FI%GYaK80Eq9Y;W`lLulhVf5-vb{0x+TR{=wLD7MtLHVYgp#sFdv&uMWZhxny! z42ZA5o}vK6&p|$e_=#-{XZg@}wpV0zYns^JHi%4bP0zIlzI(RGca!g;EuFT~L4Q|v zt%7Cm26tHW`TJ3!*<6no`Ut0O1tH0C4BHd&c+)!Byx}DeG_aiZ>c-$Z&@kWGE#54_ zu-u*CanAwWZ56~TElohjazK1#8{{&EOQ3<};wo0mLY|hMHa^emX&b;B;!wW2g-1>J*8i#Wv);By@=*&T;CZsQ4FS)&ElgA|%kC|J>X|GJ zROh`fRN|=4uTv`-s6Mg44Z8s4D8KNf(5*{iPR6(eEAiHM0bkg_w zJMv9D|E{Tt=Vgc3YO(S4X1uV8>AYTGI(MYxcLU4S;WhtABz}#V!~Ch` zLL&pqE9<#m+4^ES(3sX91zdSb$BqJ+$2X!EM*+-p*qPP<^Wu%@qtUjn$ybf&=rOh> zBqx>zB-s{_kVb}woHU~GV{NC&kyv8|_sC>hW%6DubCF{cj%3@iO8>;5V*mlnPyQU& zMb~kUgl2c7RWcmseQ^RdTgQEo-PFWw8e+qdSi^DNk}JnbhU2^;GMVGt$TWJ-B+$pC z*w{MmK+|X5IL7dqZ;y7@YjCMXjNvm6h|w=ju)QoPPOonQxy8kR+*+TlQi(L8pQUEl z=81zrzKoBd+e{lgAtUJjvTQZkM@S`U(k$B?F}I!x?rrNC;J&qwLf^?2D4EG1$0@AxjnULONE+Bn9QhZ5wttdP^WY)cCWfjr|o#lA< zT=yt4u8m>GuQBW{&9!AQ8DW!1cOJLd`$ie@Pxno3tKCh+Azg|xAbmz%gP)hp&uP7o z&mjFtT?5iL%(uM~wYuga!~+X#AFvSjLfa7XWnCTaax6a#4RuY1&F(&Z98Q~Dw~HK2 zKJYlWN8h%{7Db469U48v9!woeZ4=nHcuQ?F#4WYa9qR-?+IE?3Mw8{W#hGf#Y-b+6 zG`@_FdkL-`b;Oyoi8>`nRHx)2%1yE-IA!E{*Z9sklXxTF8~HY#U%C!ztE08khb_0I z7bBjv=$qBH&cwSG?fipnt#Cmvw#N32C|uE}{bcJRcrS|-XL|hUF@$C=aD-C(I@=kk z53=|vsEe?N;mWDbgh={ko$a(=W#s=o9oy0_Deua|zsDkW!fBc_IFjD`*{1lFMftNd zY%aXSA7AFNa(`Z~MCt+SZJriCTLk8{EpR4znx`ud{~jrx5TfZ$p9mVQ+Zqe6^;F&V zOb8zLJ|2J{jqx6@U<^x_WAvds{nh*W+%2~20=r?G?FUcES-mhpe04o~k8N0S>%(vq z6lm!#-F?`G{Y3O)M{G@sS%!xJI@<3betN(E**tM1Q5a49&87%Al>Rqc8X?`Q=p|0u zHVMLAefJq#YhX^O?sMMOM-)RVV>kpVSh#!9wt=mAyJY*7?5#xOW9C<1w45MaN#ZRU&Ib=!)yMc+ooqPqopm zQQsT3B(`f$#tmCP(lvxWyp*a`o@*Q+upPVi^5ep`L=C(m3GKZA)0Gt<5&oi z-9-+hIOBL;gqc^3=QXQH6Pnuiw^yT!?m)z| zDu@VpDna^#J2smr?kkVZ$ieHcd<^eoy$80J;z(ruwA0A4(Y&2@o1XO0<}HX7P*Cm< zdqcYK5daIzCm!35lOKa=pC`7^Qn^7mB77h$r(igY%j~tkuOE0~>nf0j!FuphTM0t8 z2GMHIZNn@ZgG3vR-4akiKk(e zY^S7&ffz0-2AW4Lm*7Zs!lXL(xn04&Jm}YJ_AfWRu^kZP+vP+YF;8&3Jho22_S`qh ziTchP_F9Dc5_?@SvK(5v1t#<*_Ld}~99>K7N?bT@;x|BaL;1A~@rKAkyyqi50$Y)# z;^!9cImlz;JsiE9ieH{6bMek9r~8QZ*+l#zK-8z)wYMcW@XlV-vh6)Klxvmrqg5W* zOX%&r?SB>%>z3un;!oF(w|nYcee9cYN|bK(wabD$(;pASgv!I}5_V-dGyQRp*b94G zI>BmB5!SMf>G&^Cd}nPXrzPS5oZaWZW=)p}murSYHO8 z{FG3-A;O+nrj(33({MIz>^IKhDEaAodsX#IWO^@}=v>4`FYA9C5<3)yWBip`q>rp0 zi?naGh)b=ecrUAK-(VSHMc>Bmwmaw-QT8>Yp_R#>M(fwJ?+Ulm|Dh^=kP}0$!(;jhbo^ie_LaFM@x7aw>*z;j9w-^eCUd1_KYeAeEuuYdwE`A zfzI(U1bQ>d-X+jK`!Ip-CYJOuWw}%fJ7l?GX+xIv*f_f{Kiadky`3P=F9mk&vVTZl zwXtWDZl&njw)SHrq!dk#w}+O>W^&sKDl%Vg|BSaoZa0<0$5Hl$LhwhSu2421x?9ra zUBP43BtW5CgL=cBVjA?{4t8izy#&*s6=}~8?5Sj033}xNdzLr=n}TpS&g^90Kx&qN z4Pb$~F=6YW+U=U0PGtFets53uRI;`B-nuxXUH$)+|R*^|gsZw9;A&*me0O>)qi zMkLssmI~f(UM)#ry!yb4?(Yp=?eh9BueR~L!o1q#W$-E+W$)tEYA?FB4|pYdnY;@B znDMHXr^%~c{TQ$Q(m(Idcr~jShu9Bk*@57dvlu-#5WET~Mi&eMuO2X7ff>2^ys`{t zyjp9~6F#+HBrFs-#Qr@wBGT(a>{;Y{k&Yf}=O}t(sQr|bC_?TEpeSMm97X$z=q8}3 z-eZ^@FnW>{hS6N&hS5()07lCa6GnH90F3$*14iw*$ql0tzkUm&Un5-PwA*XylWuqVG-LTDdNzKoC#Ku0loY>u zNoY)v{WINrHbyg9`$Er|W4|Yox!96qp8d3x^xSOHM9h)T^#H3` zQ2F6gI@({UEw+A2^y88CMi%<%8v95x^$AT3RQzWD2(;|_gmARj3bknbL`1~j^NgZ)F|^B8-U+T+QfM>KIG)a1!WG$T~$ zN46rp336zEgoooc(8Wzm4x2rsWUD1azDdtPj`*X(S;J^yD0SH36rH{b}C z<4^!ybOcB_^$xv$gsHP?j7?mffkW90B*7uKIt$W!9JAlS+uSkv(<|3LK%8-#&~~wS zx4c|?58`=;M*j~C>T{cB{LemHJc82cH*D|It|tJOKO^@9*i`zqn@w*{Fg7*3MT1X+ zO{;GGmrcufUST#Zyk)ZKTNJ*FO*25i*;Mxo*mMUcRx>tDI>Xo$@Rz>e9Anc7{pfkd zrsSJ?z#oiF^>3PNioFOndEKNhFWN(9@3j{z0mKA59sn`*>X#U!=nZ{qo*f3M?FP-c zr(fLP))9wAw9uA2I409+KGYts_C`#>yJ}`Yl#2L%Jwd zE=1nDu<~0}SVpwJ)*svkSduY+>gjjwE`Nkn;v$&OUDdX6AVlFdLs`fVtI2K8qVntn@ug*M4uWrX(S+s9pKhSpzHwo^^xe zlXA*Pvib~@y<=p=85$j=>=&D!F$JV-u(D4qjTFbpl=4bn(&LOFg_a6RQ?mXvjjN!* zUa7{Xjr3Ioh1)BKG4f1%rIyzed{)j(mW34+D-j2tHbwD3C1rrP<<#4jYSN_2N@Ws$ zny#p<#FI&<7-0HQ-%urq?MxD?^cQ}oe}^g^Ese3vk80Rb1rMb(sWBAsNySW$mmO|gok>2DO689-OoQZR9hP+pSf zC+OOpMvi;l7^!$;xBe3pVA_r5)l{;@-X}~+#eJJe)f2Q&ZN;2D9xPUH_E=kiWwYad zdT?C@sCqZlwF;f-M%Bu|I5(eVO(R%lKx4QQaOATx96{su}G8IsF*`X2qE zmLk&yfr^!mi&X41yP+~ttet+9O6;LptUf?5!LN_O3oo6Jx>N z7bbfH8|AZ?BQ19efW6sF9fG|T^c#(ozYtbAZu0nM6YzN5F|)M+O_d&`!g0F4DcGBG z%wTVgW?=6v`eQS&H<#L*gS}zL-0c0jIb(14qjYsEu=m%a|7GtUo>!Q?JC2&{)lv8^ z_O1f~XYZ~!u(!lf9qh%i7Y&YZ&gxC$6<>ioILx`Kf6-2j4-cEH zJkSBGtazA?cPb%ez{N~vr!scs+o?C5jGG$|>5V^70KE~1Xnbcd$@>s}+F8kBv;Hp1 zrwnSJbx}^qs}Dkq3)rbE4w_KA=pY5uj?h2-P&pt-z91_&-7j@e&$(f*O=!|bN?p?R z07G4D!TgcZQtWcTgx(GZP&IQ8V74F6uirxN9;Ayx?+)a>3wm`_$f0*+PX*BX?XL`a z;|cBcu~O5Lx8KBHW6Hn%V+CgFN57b6YR*6iS(K@;b%>dD$t_>jqrp~0autZ+f4T)s&?8S;Iodd704nn09Idd>#KfH770PEs<=?_)(H+GH+Z&Wd!4+{2mPqjBjSbirbT+-CuIWpc|DEKRI4aw$x9tw)K8erPqjMBY+lpsn6jg#-DX^|f zs504EESp|@qc)+-cPf$Eji1QOzfrg`xR}cz!U1hZQk<9R!<~w%ok#Jr@^EwqORhZp zdj#SndK911gLWzYM2bgw9y^717u;goQ=M@?(fB<|0*Szv!+Vrr!h5IIf`B7WZGPkb zSURmfzdoin+^75_kalbJdi#|L+NMveL2Qwn->tF z-)=yJRxGEwkEL3i9#O45`lwKAExoUV>S zjTLSyO~u>Gz{raw{OQ-XmHy;%b$b7{vX;DnuDhdrJyhC}ZcFLfhmfazOR+9ptwz6iq|_j5meTk}szSFv zQfiWKm(oX%6eoGIgx+hUV#D>v%2amSy~j%J_%=&1^7?qXR<4Cx+*Q>@B2%0#Sl*se zuEiLQEZu~qgJpxJLp@Ft&GN=;uFLD;8sF^U8ecEf8MT!9HNhh+dZN@2T}vQWIEGHY z_e5ENPlj;vax-+ng=dP54sE8|=!K_B9{c3rnbKOYq%B7G))*z0rIla6qK#dQZH@7$ zHC`&2Wcgyc=cSS;ywKnONBLMFix$ypmmKBkmRIPS5sPT_YbC2>hec#&EBI?G3tefu z7>7z9y;fQ?9T@XQxm?AL(!9YKGbtD|Cnr0tNI#2V2SkRtcnHP=A(y_hoFx}Al~_?9 z@~_g6NW&HuP>Co_T&U*=YBC|47SL#m+An0o0#p-*YQ_h-^6>AG666vZq&n9kpX+eVm-bWCdOo#Sev>j>dL!oQYZW!RB9%V%nC7s6dDacuZ3{dB0hwHP)NbX8Y( z`W&2r^1a1f!p(`!{WJ808tO$08Ii?g?PqMa`>>YUpH$DH-D<1*u~SP>9rXs;>!Ky< zs%uH5EV{L>nn=dDXq6~6nQhPzrG6|ncA1h?r5^5muLhH(59ytHY9}U6P3o(?a2_^f z>HGTXSt3-Vp;2lV`g^n*PG)8@fx06dAB26<{ zUJ+@UKAlNZf_Njt5F~u&rj*bZHBsl`c%BR$(i9?)@C=&sOu=rOOrjn@w)8d4RSN^P zbuHAA*vx(!6QtE_kC|5L5YlcMJ=aQo7Mxne6I%|+Dm~p+%@V_=nnPh?ygH+~I+e^+U(7OtxQ^8X*XhV(L0rKd#P$Bh zIT3l@!h9aYeeUJ)LU0FiQI6XAfA);gzhRfe%Lt)!>TnKc4b{c({$&yNi@BOIwE2|%WuN+YrsBDb$-jz z5P6SX^>}(#e%iv*u1R{tM_@G@u02&%cuZIIRJ*enYA^LWA^6L0a640iDU~_-=Pb=c zDy14vfA)>Or?*;y8;BpP-+4++CKe`$nW&E*qBL@e8`($Gn2YqD}I%{U7@&YYxvLUz~SMxow*GDN|W%Oxyb ztq4aFJvs$K(`YPB`~yu4n5qsX)06Vs>p{p^8b3{qCkaV(!8A3C9899|m((h>M}}I1 z{G3EHGSoP-Fo~YaP@ULmu^!aqiSH~nKC#790Zz$bqJQBtbi-6FJ`HCNY&9a`35>E zX*T3y#%NlCqBn2oqo|6Nr}E%J z_xb7{VeLkO?QFPtV28Na@y^yrKa-il3UguoJ@OGng!D8UN$9xRe&PD`1rS&1hp!4~ zEEIqLm40rKIvU#+kHDz9Co1%_rD}`*NX>kPLG_G;xcK1mz*qNwrZ{gQpX;r_Z=5%9 z?clO)&gpR74b>OaVFXQdLLQUtLJ?f#xBCh$igrz}xeUXQgpbhouTbX_%V%Gr)AABU zKRtPsde0(Mp}kkB{`#b~YNjCISix-du{3u$o`Wg0Sgc@=o#LE5oCd5@b4b78`o(qX zFj1O33ySDJI;FxqD$6xs-uFZ#HI@KopUVfyNgYQGXJ6ub*vOQMJ9$$QjW zL>!!GBF)5K)SXhBM0aE8(p}S?Efe+5`_(MLdi66DFcJ5Nf?7>=UeaIus-E{Gl|QAY zkE#1hKOKzny$HMxn&^D2uR5-lFGjL(K=4U*Et}Pxf=+6K;R=(l zGvIuSLA2iQ&}rWdq{pUU)a?6R?Mq4yGK8+tSqNR9flTPek=Hf!GUwDaf+d@Y+RpQ8 zs6eI+Fz&Map$=esa{i%yLs|}C4aCvdi!eF24WNTALe$g&Ow|17$&2bpGJXJ)w{B$c z048b*-E~Q=NxBZ8PcNxXvc5m9HXW3G^VCViZvd0J+HFe>_^-fuvAhBTCvuv?0{5mr zqbV$K*sJHV+EeV%-;g&Q^5#Rx{(d?{Ekv*+^)tmxhnPhQmQa@F(v^8#y@Q=4#@;}; zwdqGgZlc>3eWK64sbaH>;7|07TM(@J>-&7(wF(LS71xLPwuNT#9u!)hl%}xs*}|p(_;@*zk2>? zrr=bK^qAmm?6GJVqCGRcljb`Q;F_%&>CIL%l<|1sE-&3z4}Pe|d5X7so7GN!rnY7W z96nRelXboIpP#FzMR92_qf}r1O7$1KKkG$|bxTKn_X(#@UaP-LRglFO`vg{Z30r44 zLwd0(-3UK#R-g$2cn#yi{eq+1ooAev1aHWJ>GVos;%7l@;m5PU2Fq}4&nlpm@%#L|39 zh7-b&-k+c+SR5|}(jr0c=IMCqDNXKCm||iNy-#UJ^Wsuux5BMf@5WjkL9E^M2-Pvy z!lD!YjvsI$dRIC+z~M*gcGYJGID7=*iN3s?W1&E%cF~&$IiLvxy6A6$9oH@5kxuAC z26nG2Ild#+JJY$99sMj5J7GNSs^{>hB~q*bJDCMZCumQnJjeDxiuXtNHL^qIci5eb7BzoDehX?ys=B@ZE=y- zDb7bMZ;xc?L8R}obZ}XNCP?KpSXx!fAq#)fUurpeS{i_Y=EY!LSmWA`{erl+gZV72 zqR>kX>N=iSMs)xQ(|tPfA_WrCK~JvdD1rSJ>E!xgOUn+lb^}Kunb)2fmW}nB4IF_2 zY0{p#jmy)j(T+5twWmKvJFWJu6b`Zs|8n|Yv5pv`$jHt2SeleR?eyp-j`2k71ot5y z1818#xAXdcc66*KJL2^5A2?Qs*56v8oN2!lOqOE5b{?luT^)6N zcC%~|bFP#$XHF|UxvRrj5=$Na_pxI-HbieuF;{D$uj+>$C!?FuY6BhTr0&gdOMTQ7 zE4qXO-#WWA)BOfH_6XMNO;N!8q$OZRq&i`I4tBKgB<-8f+QS?{CGFC=bkWOgaU%8T|I>6l3zjp@^oj(#K&tByxG_LByUXvk;?6;>BRsMeBxjcCpo zbk5dTCJD);N+TvveJrW5W?#{2VszIMpuNHh)k+L2(X01`uvmVC|R=!b^p zv#gp7Ihr>Ka@4yaNVps!4|3$wP`{Xt!9Wf-ptq)A=2W90ojnyjHK73)B-(PCV`K1L zxEi6s+;JML7RvuNj(;2-1m9$a1JUoF>O-fp=yy`4V*;62pAwfNOYDVQ?rU7P|t_W9Zs}$!zcRDkar$4DfuPk;n_WJ<&k6XmLhL86( zSLWh@JEuG2v0QnHqYtT7M_;nUaYYE&UK5aAZCCeOGMjKgM zU%kSS<0+-pEKD)3rat;dhmUvgn25s9^_4qqKG*OFx_YCdp46A+RRqoGuBrOKO^)dn(d&JK0lIygqdbwO*FXi_Cj;*))-q42LF0Bf zE|QKl^eQ>fjlwnk@=k|HNZ;!E_1%sV#YpjL^j@yRK}-DVm`gsz>8`&*jQ3QfJ_jJi znN?|gSxupL4mfg2=c+X4AY^%KRhoDRBh&}Sr5=JTCs(BjhaG*`u@8qGDWnn3Yr!I4 zeclm=dsg`PsH37l{taXFo$1iyj&PC~P8S?^q?2u7MhmgIjvk~MGIJgABt48h(-O9e z$p0KYnNR3{juzzCFk0^fWH%^``h;i!H2Z`jlS~YwIU!mI9q^mOH~y`WiIX`3ds*v8D-3FNW&!6@YgHL6HA9+&@j8`#dSx!kdh#KR)^`tlCC`bd!%40(|5eH81lJJY%|wMLTKU* zV8(Fd6`c4n%t#EO3s5HZXSK44-pLz|c|iV(`mkFtRm5=>Ogq2!T}M4ntm^*!vEw*7 z8cZ8MK~F6ShGW>_3Fl=nn&UbO+U~&uXOCd&`P6ZUga+#;o;ogy()&Rm;8R|VZFoSc z2EiTdsO?jZ<)=X(4oh>E4bnaTal9!(dIad6p4!iZ{Pdo_)mwW+#B*g$s5)3u`&HRe z7B?|T+XdwYn;{4aenVM(MJa8CAjPr5@~nGdSz}h&yev)d(K4i9_e~xMb+$}#29(v` z_-OcS?F)Z>g;iTEkmCNjQ`R~QWW66j+=^X7xGwhn5^)~WSu6yzg z{DSMGIB(D`cC9+%N`Kk4aTXG$84@|(Pn%0JG#cQq^&@{em_+)~MgH0vf@8QLme-e5FhaKbao;HNka4;$JqeBC4NX}Mr`OY5FW8babuyM8QGtAg(~?KJre9`a78W~13>95y{R zOoLBny$v_;$>o4>?G71gWAcmMtEy!J(1dE}(NLQ{teOTH{z29U)zC1*Y#_g#VYcsY z%rGlk@HuA1FjuIh(0Ymo?ir@Hmq)Hg)xCPp2n{pLg%We8mZv*vYH8$43C6sZCAOE$ z5&E!}c9>L?Xija-Pgy7xR?{RU%Q;t~_iAeaBumnL>S!-vWBTGXQc79PG7xRv^HB5KPY2XeYuggSE^YCgR&<~?nRiU4M=s?D5Gy`tW^`#KYdV8lG)<; z5+yc;OT{H01c%qzmeBc4wd!QG4?WgYQ~Z{J^6%SF(c>Gs^6>AG($K}0t1s}OZ%{7I zG48VK;mt5^g8nXzimx(>0=C4ZI3K#xyI|ZSeV6WTp|!?N%cWats&JB4Y^i-rww2b? zTcW>%+c0WoA27H>BQ05)8O|P6dAez7y{ClKC;NE%85?*@z#~OkM!#wr1pJlAAJsK!@hJ(1Jh;0G`?Oc45nj#us(LU_BL2QV7PWiARZ#^{H2yI zwk23fb5OI>=U-|)2$nl^9-+l!VKQElDT^H=v?(Nw(73OFM*|7{`75onxL3gFcv#wB z4;iUNh=_}PI7XYUbQhSM!V~lqrjvj`VQi|ivq0aB!N_TkGVfi+_cSZtu<{bTJWjyW zKvPIlfi_Rlx{32W&~C1VkAadjUs25cSKyDK-yNsmg!uudYeT?aAyZRppZN!ku%$F0ImxfhS!m`g?p|tvY6@y# z1_zB_(fCZwPptn6eI(jLbXTS}oRG5r=$5(1VPtkKd$@yTO>;;Wh!dfRNRg(&7dG9PB$dTpDu=MnB?`aJeM z*X1&DM9w2Ud4raLb1ffHpG}${>G+6N!N1==5Z;tyUkI8!#kc_{)mKh&<~*VaD3@aL zD}rIrE5%v=k)FOuJ4DE&hkEBN8g`ec_E68+s?`&4lH!YP+BTo;2kfC0uHt`uK=*9d zLKOdp7y@mkIeQ_%#Xq|N#wic!o9$W^Qu3i*WryY|kPZ*@h#ak+NCw@fiMzEEmRk2Q ze!1B9*aI~$-ly>gwK#fbh*p7)+^dbW9K6Q{xGDU%MaO-CPXAnckJ^5Lejjp=cKZe5 z-_R8QQu__@FA2@W#2+h{YkOjaA6qT?(|*lLNX2_}&jBr+47j94&8rD%TQD92>+4( zF^qJKX7~RRh3^voAt0!pq}j!RxM-22Ri$~ywQ#cMw(gV5kOe#O{HDPhyz-VQ`1-Vy zT8u!PxAbGDG??CHZqdXv%vBzo*0w{D{CGyIRHitjovoVtODwQz&h|T#`ayr`iDxye zf&4Jch2m`Y-1;V#OS*OT0p=l&!V>56(AnbPn;3uh)L=U84=C+MH>q?HO1ms_`P_Q< zMUApG(%mjWX^*@q6b^oN{Kh%_CQZKtr9Jp2T^r@!MHlk48O6k2*WJVTn%08!yiQ+U zgT%alUH|#Ic0v>@Tr-Oo-_mxLEp`nxY~(sU4D)ULdkn>V8~J1Z)W_e|W)l{sc>rw7y-G(H^K;Tk4>TLu zbX8yQ0LnNx`YN7c21IfZv^4Ij$I?thv!ND|t_{LRnncLDEBen*v}i(tuIP`RLJq8V z@(PpQ)KC4RO)suYxQP6vsKO%t=l{0>ZUN3jAPW()s=KFHln2?;PoOLBCkq4^!ml`m8d3*syT; zd409jZ@-0vo}_1DNRMu}196-O*09I{m zfZqV(|GUw~uKy$Kx&v!E-~YMiW|AOV&bc`^i4}XrUI}W?*sDTSDK$z_D+y}F$R)hQ ziY=EAiffBeYR71`s%?yx+N%g9zt8)==iGa4uHV-m+?;nkpXc*F&-1>|nTpg~oQE2- z)Q+xaW{HTMe<5$iO4Ug1a4A}>`wMRGlj4kvu5vrE{T?n&FpArLChaC-un{Gtal!Ic z_+wgK%cg-?ZF@vpj$TQM3&tnyN=m^}G1Rq~{2hC`b<;4^&nnC63tc6ZN=d<@+f`C` zl7zd7N=X$AeaMk;39l}hBzf76mx6ThE)ychMQz=dFg_<^$Pj4f>fR|k}yq5viVe$#u?m7UP0Rt)7?#E$#ki> z?LZ}|m^;0cTwU5IZn{LqL`w_Ash3Eh8WLNQ$JUU3FW2G{459=zh(L=W1)ufCF~2;D zYac9E#I=va8F39S*(TSN28sdeF6vj|8FA?s4dl1gNjbgvMe z=&+UUA^j{G{;<941vo~-k7}r@*jG9e^yf+RVP_KndPy1+e9h(?FD*1w{f5?gQd*H1 z?@5juiQ`wjguGXifC{{d9`VT_{$RkyUBLbYn z2fW5etw_@mQi@y3F)ac-9DxXc&nu5a1gLq8H2fM7;GMb{KlxhfXO94<=$lL0;&nz^ z1Q<73T4$hNMjaz1hzdU1HAebcv>YY=W8wDryxv&2eYd03?FWhtj*|Z4;PFe2s77>g z9QF7e+0^6b1uI8fojvpjclH3(eaP8;k8o%AJVKqlr!hX;!0&`OR7&!&?U_V9{q$iQ zJiVGhoOGDLw-sAVk`!$)MjbZrr`LB*kjzk2T0F( z(gI^4l(IF~d%o0M@;+cleGVrbb<>MGYpxf2!rOR&d^ul|q|vB%x)BL(5Q)=0!w!&@ z^QB1R=X5ms1_}QZX@|S9^FB6s7`eSjY9n^sN2)D`ftA>2ySG@{fIaYDRd!~YWUJw} zms(e2i;!CjH`Gmu6YR%uH*B5%!}aI<1h+c>;$|m!kd>Y_dPSBllePt)K~*lnq8bjk z9r%X%#2)hLa_MI&1$F;Uz=9lE8z;tT8{D;vD?qdNkajB&wWp!})n~D|gd1ha#jg;K zn~_jId5>-K3TX|#;c3I*tO8a)E-~&RJ*F9dIL@8n_?(S2PM7-E+==p+XK+S+N`QK? z4IY`uPlsiq?m6m4P4QOiaAFQRZM2bV>5?R-+iWk>rF(|RQgm>7+Miyj1BwWG+?pQa zehD0h*=*ukG!)nDwmn)W?ep+^zSFtIW82=%QhBe4+dELMgPlu{b+E4!_nlI&x4%?xfQXzL^r|o<)ZGY{RDjUS&+ez?# zX&+XBi~A8oaWQPal#DCRS+?Q1gYo#Gl;ieUrWPAoDl(GwQ_^*D2O6A~`itI~ewP!NzW??81iNW3=wzKKWmI!+}|Q%84cb{ z-d~}+1JrrpnGSj%!={(Cz9y?Lw3$@;iS7Rtgr~6QXBg<) zFL2_pqU=E`T$2Jf`ur*x#Ksx6BG)9G9DT5fV9(x(JUl6RlI-84EHPsfQL2Kqnb)NQ z;^`l_WHvshf@t=>{U2$9i2EHXK7jSPg{*@Ou}64+ek3h0R6Dj7lA2&+4>!(c ze`Du>zYns%aoq@i?_+<%@bR~8tu5_|)Xr!;v&KM%Zw--&#|vqPxNQyD_d?nrez(Tf z|6j@95FE1xWY_XDb^^og|bykuE9`a%_V5O~`r;N3F z{t8=NZ~2kYIAJ+AP4bDad^ouGatuOu`Sf{$#FV&x2-e+}+oU4$8iU~xIapMd@fN*b z@gsFd)4PRfHg8JiU2rcTviZ2>q)0JY^1HkYL#?7iVMmja7Xk#&XX@ z^=8)~s|b=8pgd75%1-Ii<9TUB36U#_Q_^hhLgaFWB8QjKfpC%l3&4S;w&}&?(ngx4 z%JOA#{StERq$H8$CV7iEY6*=Wq2#kL`J7vwCA#==Uz~}$)7WiyHp@-1(O7DhyNd_a z@X;n*<}Y)Av#8;NX8Y{f$j9L_vi(Jbh$ZCNbQ4}e9wm0cVM)22xEjx3~#)4ZWd75RZU zc_9rCm&BF}$+N1m`e0*A1j z^9FO6LDrZ@Q~UPhX*0QUs~|LZu@?C~U9s`YZXCfLw`OAqI+|+#BUD z6OiAFA(mYH3IYV8+&ItnWplZqA@cjVkVq?X-7HD4+->xj?niR!vE$8i$>|nye{sQF zQmLgZ)l5eHi_5s6e-zgz@hfEeG7Y{%`KvDwH5=EojR=h`N>lz%ov zdeOnzHUdE!DBS3AH#8P-F#^ZJT-%t|G;BmwJdyNFg&(3E!d+Xo5@$}gb^Tn%MF45Kt;iRs5Ep!B zt27t`h)wbFmLKSTVwj9;0MpF>*V& zd)Qcct@!yAvh{*ojl38uM~khekaFYXuHyP6GAswH{JL@SM5A~xkrcTCu=OX(6NAen z(KryCylDqcA$XUyOsO^{E;5OnpD5!!X{eh?rt?k2KGbK_VD-UCqIJOXv~f zZO<0VxP;#KTh+35EtNMKs(O4&N5y*pkpUa&-&1iO4}S}+ya@aI-8fo~Eda`Ky=s|^ z3_Wa|8r}}BL^Kk{kuj^}4Thg>Vd-*ZL-6de=)p+9RlyF^*#_Xdv84ZM`MlV1EUC6e z{zD8MYx7?#uMz!6j6q{|2EQCj;fIbPC)UgDigc&t^i)C9DREuK*djN`*Z@o$WgEC% z#yQ&9QMRvl$ivueDBn{=USF$-{A}`Jy6?8hxGT~2mrY)1@J|?tvCJSd1_1#CP8dmM z@0FF%`?S0X%3F9??uO9Q1i|by0T!ISatZ$dw3_OXh@@#)VqE-4+snQ3AyLd4VcUHG zvnrMwVLN|F?rNadF0$ogHP;TOpt0E~G(RpKf4{tH$k=Cetnh1kCdT=XfQ5H0%vN}M zTm+w{yBft-!>CtZatj)!IrQ}t@)mmI z3ds^1cB+jGejuVKu zoP1{}IsXl|&pGGh(PH#aGW#TgTFQCcYqD`D*>@hRym2U9L#cNU6gvzh z!8vej>ku0pd!5rKQ1>BsmWOb64jMw;xe}@JlU&94)t3hT z@ZaR05U|CoxW_#KD2n|m2QE&;zhC4hZnFlfE>7U$o;K9gH;B~+<2$L;WF8N~X?>_R z;y3w#xNi`tbe;J*KXG{dx{MQtRR*cf&QBc9`9rSZE;gxYJ9bNM=OrD%mu=i*G6gpw z(>&2DBiq>bXFTTg#4ENgDgQu@5F39^+C7k4iIqPmX%7&N%Y2R%RgM$=KPN>Vg1PAf z$fplwNlX|(#y^yYx&1c4fU}&B!2lcSWBe$05S-QVRCcGa;MuG<^D&d{7~RzDJ#2Y-WS z9J8A=aK58+Us75$jTbZfk~N|!(t921?^ce*mplB< zV`ckGG|6u6DC2inDMk}6!%p~=lyf(=EAr}7LuxwK6ngz^;->_`d|qe{%HqYqb_DH6GuxX_zF7094QQXu@6g_&7_mZhy!jv9{)NzFb%Mnq?in!~8wO;=(zdrFHo?)hF)Qs2E6M@n$<;#PZr&&( zDPI|jla#8aKwEeTQ@X)_L08O{F(^5SNe{9{bR)s#OlI=5q-iRBi*P9n-mxpWR0_s; zqAO`w+B8NC>PmK(Hq{i=oZg^*sR@pQ~Y=;j3R57&*u7~>Esc-_7aARm<+}ciL zauukQ)rst`VruAC9BoJy&_sNyng)2~but7F>ZHo2eD) zP}fwPWY;nUiJg5(LS0iBc~Q&MRJ3&@b!(fzI7#P;cvi5iX}+Dc_DbAv{&M_-=wBYmL(@Jw(3ys&K1hR->SK%s zjrbU?8*w%uq+jX1?e!=b8!28%wKbGEl#Si5$fvcT)`%F;5mucF&(T>zj_`w>jvN6O zM{F@pGcqUE)U;AZCpnCb6t9SePI5Fh+PtD{^dfx{{X9v0W1WqpHinH9ZBMQ><~H)S zG3cld3VMK)=}fPWbx2v zEfi5P6l)C(J!-ge;Bbu`0j|-lwX-ZhLPyDfc^!! z*osbATayoEV*p<0NUd^DTOc|0f!Qd4B)=_piT&;168U6g8;n)4J*S~wdoJv7d(d#O zwH}@75=U_B0uK;b)Ft*k=fdMVK=`*cDGgaVm&nq&L>6_4jUAk(Vq!;A(-K{rX7qW4=%57PuM_EOFcjj4$!ekWSsy8|EG+I#l65o zW^Gp<9QKz*J)wCocmm}?T_nPLW0A;gp_ii);aDV?94#zv!mB+yA}nS$G^qAX4hj{SuLmkRTiq0icbS{xXU4q0rP07%HSS5Nm$zgQl=vE0P zN28Nty;tl zd}W45A14ZgM|A0EOD24wqu}@#py1diq|hLBA_sv2yei0LJ_>-DKgbEpfWe@k7cqPR z3JwnD6r35%DQN#CY$Eg%Jy6v}9IFKb8jM%E(pd52OAunH?~1|UBPrBJY7KGrkzzyP zBiozm1!=*;zFIgjvgH9ciZeqwBg{Plzk({m$@VYlY<{KA=2u{4WWA3f`tvL99?OQo zJv^I|H^Vrq@^DVYs^OsGhbDT2s(Yv_#&o)+gnJylzR0V*OISZ3+A(}U=CTHQp= zq}yq@$BYq9)6sh*Y@?5p9MwJ46+@GwxkvZ=WY|P)6IJDF9xa%U4EP!bA~zw{uX!vj zt|GhpHIP~Ae-v5eQBKI*MuXk&$?B0{x6f$K?vT-(oyVi$DX5VlTQ0BBco;@ltR5gU z412Dj0<=gfhTQSM(4~|gWK)b-IELJt3>N_tg%h~I z`3Yd+R3kk?#)Li30K%LT0C3_C2T&!^RH9^-*H;4N!oIJElh`v2aKSQ-v58Le(IyE- z(a%W|ho~u6*KmO!-*`SLGeX$kL0G-#N)$J{=Llx1pY9 z)ezLxLzARM2(Q2S>d|WkVx{IG>t=wAGY!bS8R{g?G{s;p@;)#Z1>g*y=>(_gEYN`L zbvkHRF^ki%c^0Rk@@!Z{L<2ok)i>1jLxZaP#YxGT%}B`*T}g2mCCfKLlAVq6NitTD zz4i5?v^c?65KWZE%Ff&5P?EOG%ASL`32K;*!*j8a zV5kZ6u#gnRqvi8B!EfiOrZ^v*oU5k?s>KVQdT2mT-{PEvry(kwV&D41 zQSA8#9EIf{U!*uqPJIh(<#Q)ts-rkolPv0z8Y}U)NW10QYEoR zV5n3bXNDMPHF42EN2)-w(=;IO++7)RI2KD^JeR?-C_`%clDiD+&cWJxX(~mIbtmft zU^Q9J;V~b&y&U)_kfby^!z-}vU_`ugoox~atB~=)E)-V{eJU$8|e~lB2D{H~uVKQNETUnZwE@+ryroulyD#89mMz?2j~(SDN?ijo-^4_WU9 za4{)^bCI0E1s1h}i?TIbxOk$S&(gRkt)j@XG87%XUAb^L0?SceS)CmrXEPk(NVHy* z7Ax#43?rlZ7LJWM!j&xmpFl=h=|pC7N0@k>GtxbiVL9@Fc`1NpRi-nRaa*wk3yCKC zwsLRyZ7UbqcN@F`mt?ka>M#Aq1TD^joE)!_g)D=0$w&)bGBQX_Mw(|iF>l(A@c31A z7nO6o)a7F!O?qJOT6i4v8(luylHa!L!ehxDaE|iT$(K7g*yJ5pOLM$#cz+bm;~h?L zj(-m>kCA@c!DZM^ZV2Ufa?Q8xgdrqV(?eCALR~gAsFSa8@;mHeq^v0Hib6FHKV)@q>NM7jL|mea+U10nZjw=Z#Kq> z;p1o;?QudAxEJFf=iLoXzS;{;FxZ5>-~_+H8QbKl!+F zq8cRQ1j)&reK1JMiMmQ;@5lD*hbnqeDkUjcE4yfH&q1JZ&Iz3v482N}v)a}w_XxID zz{XaOz@u=G%9TmaqgXxAqk@WT$x$F1>HAS+e;##0w(}TRJV`np0gJxJIg9df&cUkV zFp2Lf=}|K`Nzv904fT|tIXf{w07J{7t{5Cn!jhC3KR99NeF7^-n3EjU9@LdXl|zo5 z;J_FW15N_@ZzSU+pP^rV;u!9p1crqmLp@1 zu=6aS&mbL7({;N2PIoSWBSj@jTVR`WjMnNX~ zGx%uxEBL@ry?zBB`2F)&@KK|zGan46nnh?ht6k)LBwhm_4FX*;IP8uk5GSv}11KNr z(vbcemWFdtdO<27j-|ngkRS2In~PdzKH@q8CEzl*Sa%)zB$L={bbhaMeG2~$YF2+> znhL-g{yW?O1C{>+?oc9%%>D!JfaA@7a6T&k33tE?BL0Ls0R0~qxYjv;LhEmW3Tkan zBj64!jR?tgV*Wuctl--+E=t?e2(X)?w}R35M9)Q7!R8w}D|m4O?oq1@se6-S?R68n z{>rAnp3}fLUBDc^=>#VA7HGRbs@?!?4{veW-rnMBC)|b^%q^`4>Osxbo=j*!XP@VU zg#QIXwg*!}oH01uf~68){N;q9{@);^l#?9Q3LFc96CvT}xm&#bTSrLKJJ1BTbKc=@ zvH1@8@cTHHqIaFJ+`fxZkevPvJ{tVP`DpzQ=i|aZ;G<3{7e4F>g~mtCbDWP6_rS-~ z5LZ4N_Q%o*+dXHuNV#u{p^58#+$Erk24~N5J81oYtIg~_^#K6SCsps!34DO%03GI> zAJ{sc?Hq!M~6*_7L}hh{W;fD1Nxs@fvGJ?QpR*nGVbq}($s3DC2) z3S!VRfUp#|wA7_AQMwdH1F`Ly6NqWgLEU8%@f7O*{+z3O|2da8`~~LP5~&BM+P=CZ zr~obVPIDrP{R<3zBv%Zo?K2F>7`pun47eds%@``Y1QBJO+@43*T`LK1o zgdm^O`}avMDk~qN=9*kpD`4xd^7ZsCIvdusQj%HEAe&)(G5`j1PCz4V(VuvdyLqx9 ztekzuuNcCbijB-f62r`Fe#EfGkp_mvo|(Yp?U@N^W|_$xEOrmW);o;S;S9lH@of9w+}#O+$pd^; zbP}Ulyc+E_F&ZCHCwR2~%|pjWNlz$ppA7a4W9E|V2|7YQj^(kZ6PDv%7zIhC2j~d% z=5& zP=qU;UnHy_eVV3d7z-@-j&aq}i$b-3%&w|AET381ouW?k9w>&X{!Z3YsG7cdjtCTH z=}kZJ7&$M8sdxRQ_=N@8?fVw5t6(LOw&g_$X)PNg!BpkD#nLV{kYC%K~Zz z0R!&$Rzto|Fj%STB*)Eq7Y~VQm#rBqXs9DrsOfW3Lt%!PJAOxD=MQ1gJ(K03@rq?jS1 zMhRDy91g(D?W);{)-B;-O-sxQ(No8!+P>8XbtxwRDIkK2XRG_p2-te_5b`D>%uMxc zs)DE;2@n~K*A$)2+qd|z`4oEFNJ69&h|VQI-Jj%XIMmH7!PVVgg3D`E5_7vESP#&H z+M<1nuL88B9pXgfmIQ{5B`Fck7#udww)kaAIbry(6o{zdBuBM*N6=?Pd{$aVgj*RP ze@Tqxs&VO0Mx7S)Ha>H3hL}tK=8Zqfk`MJ++5LF`0I)gUW*Dx&R>a-)vFR`;Ll1he7sw$ zGUxi)e$I7bW$0-s?W(84@R`k>tn9?~@+ydNa|85zs)nyd{?c@RuOndQej54Pl3rDH zF>YN|I6~_Ha<3|aJ_spX4SE|&TgvM8`Chtxew3PQ46o({rfGFhc#GVq0<~9E=W1`R z&eg6Qjfr3FuLr6+fEx5Qpey%rLUN)(NM;#V45|Y#4A|#~)BpxN(4z+Z2Q@%Q9Va=A z5c@u#$w7O~BBJr>Pa5<$*90L^YS4dC6Pmmtb!s6(qO4af@DcHGEQf13VM(oxQIIm$ z1RoD;gAWY#wl?^nV(Ng8wtg;r*!TMyPJBR=opKDX3qF2`a^*v{MaBpA`(M{QtwupSP9vnfZcJ3Z-2XE_fwV4kztq;I!$&EU60_!9AqeD7g(nC*q{#YOK>wH{( z(FO?qQ1DCx1pj(eE)x8PT=~`wx$+kp!UyoYN+b9HM7*?d5hEHw#P4NYRaAXIGdo)& zCz|KPAm&+$>ZxQ?Zr}KW%A6B`^gKr8p60lzv9S5}Mai{T1b={Nqk<^j7$7<_5II`# zhwa-p`~Ze)X?uhRcpk>1jPDEB`VCYhb z65))&VdHF5|Ee=E;NeU)zMt)a_#W#d$IbeqZc`5%$~uAeT70j+1239Hd{6F*K-Wf% z?^n7)lYA1|4F-a;dfgD;Pq9h)pIBCPbHXyZJ4Qj0*cE)7>kd9J)NkFv2Y&nZ03Thv zo%vum)y=$yGj2QMV{uQ=@l|D4Ivl3Q_VUep!qh1pYIqOt1ye^N*$d%ar}f<|@~DHh z&w0`d`y60m_Fu9$KyM~TdeBMi%|R#kru&=^%tZm=k9))JG0^5du=^%dDAM^)`55It z<%)0n6n1Z5{xhdXPe2AX31N1Qk?^F96E#0S5^JFkE9I56?jKexv3Q+4y zXV)k;1g?P;a|n0xQA4% zLvtzzIsGuMtUQbhTQv;c;LhausShb=>WQkjnBfq2qq?hl4sT$#H)FUH#l1&hMOb0f z)2Mobx*~Ycoj+{**a!}VU)>*xdG2K-){%UkyKm+?-yI1M9jjZsbvypMbeFG!@KSgD zmA`fZ;Wi31J}0Y3K=nSOxavbjae0qNVV<{(dVs0}s4IdB(6ZIaF{F$J215;345|Y# z4A}8s9Ssb4G+$j2wtNF3S~|&LMA&!yOwI`8{$l_PzdZLJ10wK2gEwP91O{_cLDU`# z5F?{M3L;^w6Nt{^Km@YKZ$L!mI1m9j`^Ry4jlKmDeGD!{*thyBKugaIPDJjvzz|W> z6@zN5WEj6U8(&)rG*vw| zaaF4%K-Jh&OyG#lug z1RLm^PtuaG3eX8lg6`WH?>X8k04K0-{lR+fyrs+%&f;93w5VB$>CuH+X zPDtfhAf(?r7eeegfClu_^_-BLSs-L?9alme2FY@Okl9YoK%UHoHz3DMcJ_uB>$o9o zPUd4bT3 z1Yb73whCx!7Fx&E44)4*chz-O)8Por_P&_!M0NcX%=`McdOB4{aI6AZdPhiKOWG~d z_C&=jJQ}cw*wli_|LiT9ZQ&6yel6MB054`ZWeF=88NrZc>Ab?8EWj(Ws8#ui@;BNCi8;)}!n=V{mu{OBQUY zz<@Wjs7u3~MOYd-I>~XfZqg+Sn1!qpOK@gj5rE;B5s|tWL==5Pt}O-;7|dr4dEXdB zgc1t%A7F zhOX*4ynxwSw^dFQS4hV^XS~wW$mZFe8GyzVI?oH!b@Lp(8uR?cD>8mHpXULqxXyc4 z1H`Nb6hw;7;O)r(3_gV#eEw=D5LecK#(Xj|9jaGc%T=$pmdiW57V~`Yr5>OMHAH(d zpaQh)TgfrRuLFh#ja)G}44x$e8`n8un7AI{po^0n)!-e=042h{Iq0yGykCTMvEBxR zLlDFqVA=){6Y!Fp-hgEQh4(ig6lSnlaVDeynD!f;z?9qsLXc^$2O*O-aYB+eaYBk_ zfRMrex)5Sd0yIJfuHb}ZWrT&7@xqLFeJ;4N;;?>}3B1a1w*DL|tRFckkc6tQzRfu z7(DEQXBYp$K$_e9s7oR6Q2i6?HjlSE0Xx0}0~w!_Lf`X&%74%4*!Ddv+Ku#mHx5-tMs0k$LzoPC?)W zI=?~EfB1kvb?#M)ZDkIjBVMvq<8as=5$}pnve9oa>zAXO z8vDi;{c?+Vf4c+b8Y$s{I)Q9B6j}X}NA=!Eg0&xn< z1!;kf@@aIWr@PO9nj;U0|5@}iRB`R+pp;RQaFz<}|A5Rp2Z2!!$e8o!xcUP~3v|47 zo_0KSpFF#Oj`Q!6YdKgd``ouJz8F>r-`couTXQ9Bu|Yg{&sO*6u(_gJR-GnAY-fH6 z+hlOd8WLN?HuhTB$nN5@%j8})rF5j>vVe~o9m=3@)OukQtkXq|Z9F2Z6JF|R zopsq(t-2D7kC9&{t)i7L#i+|!L0}r@ZRQ?QXqnPZ zT(pPuT&75(u$N3;tptn7d&oQ-`%hM3#Ci&ysR8uZL-s9GniM3{yq6SNu9OSz<03lH zT68a-15(Nbb#SQ*w&s($%atbX<}S)ZVcBKE~EoztuMowtYlv0SMsy6+*uD-^s8 za}Q~_LW#s_iGC}Tz=EKT>><-vz_8xi3UU=>%~D4{hdMes*+UIWA+J{`#l#zb<~8G~z=oK~+yavqES(%Ej*X{9_ z>3cd?vY|-ZjY{Ft^FJ_1b9Imb>L8VNlgS(5W8-j@bgL5VKNRIO5Jk{H1YwhQkv}#n z)q;Duj1^=J-A&GKRU+$la;Xcj7FOj%sdAp-*D3x9F?pSLk)Jm!l}Oemr9r`|yQTI! zyNh^aD3L)Gaa?ff0!Y90O0+I8vq?Wn)~{F0rQYmxow!{XgihQg)X|AsPX1Ys)$1jB z2n#6nk4ujr>ms$s4zP~5SOF}jMNIpyLN>9IvA5!4-{6y&)fX^`Q{^Fxx9p_ogTa)A_R%|#jI`Q7(? z?2|jWgG6wm16{fVS+mtHzpGtvj>8JVVA_F(7kJuQsaNVRR5^#EVCxDx6eR6ayG^6r zYT=p&HFBv7veF5o6DQ%98pUnf`Yh$L0jEB{-Jw(obq{1)IVK59)M&L;pYO@h9ZH&* zjXMIqSDtxKWg`bzE0LrfN>uRzz25KOW8Wc5cPh)oR^OAFyOd|5FWB6zR4yoErrLVs z4)XPGCCzZf=4(@o2JeL^rz|uiRd>6}D5Ca)QSVXCc(+p<=MlqxC4j{2Ro02h4)XV2 zS9wdfb97U-lS=!P(}rJddHa+hqS$ad8F&!QL!Bwuo5h>2$s$`1Dsgxg!f;42i$%BF zA`dB|q0o8MQ<%TLAj1wSWeRq0sdlfHMTQ+l_s@CvRav&1hn20K3EyuO0ySU$9*-Qx zr^V#OW7oJaQ%Frn6Y^NuN?taPmaSCF*6^}fv}}!9ww0Gnqh(vwvK_oEftKx1%Xag! z@tHzGYQk={a04&=hBn-wmRWh(2wG-U%l7fISX#DEEjz@^>eI4AYS~dS7wwO3qVJubktqben{YTIhJIHz9N!xd@PVr;B`ia>k{v%PwGyHO z@%4bjOVlA6p#LV2B`jr5krUCuQCAanJ5iSiqF}~35knnyl~K0~b?G3C)!|M@ZOkat z?M7WTh+}oQ`9!OWKwW|jmAPP$RnlwTDi{fsdr&9X)Vi4tfdQ!7i@NZQYTXt`oe%2v zp)O{#T9@Of`)!Mmx*v7%`_(!jsEJ+R6;vKTW#VDAvPzJ>?i}iv$$)VNG~Q8nVhbsE zS|No~f-Dh*6Y-Tl>}y8k77v~9{}BHRd3Rc=ES}9ImChhV%f|I}`nwaKXrsTIGRYzO zyF8OTqQ5Dbcvv34(=tgr`a3R@Os2m>Gs#x^8=p!3IE#HqTqX%Vr*vx>Q`~X`InYg` zU@?M9dS)#hl;HLLBkvZC+3V&VGybmUDrrz-VebnBzj(~0u+Fv5!c4OJoYJr;rXg_C z`}`2r?sYIRo>v+qNLz$JYFmi~a*oami-hN2{lG3sJTj z3xMXSbRif7Kwd#1mT*D9Tll@KQ_3X9&Dl(&tFRMiNUYvM06BbKk%}=HsK=MLCZax{ z{BvH3NkHk%s)=!fRcUlZ){p)RS`K>Fw|2bfb;gba?KPCW3ZPsQjqiP;EPSG{OlyC% zMq*q~l-ZAKCdPHb@yl)pGf3)J#z5PF3rZbB*j=y+64F45U=X6gV3trkfR!!ULi{fx ztxVcX+Fev4BQYFX^%4c4b7%a$%R?CXd44`tz(BU&ZnK#zxTus5atpOYcyJp#ie}-k zwWXWMrHe}CgtMWR)3s1!cx}VHS}FaB-a;zuz?$SCu<7^<$CP4Prz!k9UYgI4T?w_& zDW##}9c+i5&0ytjlI4~co7Sude7gDFgd>~&^l}8(cTEHf9g`$pQrz9^OO}jUWcDRR z^7;V-Q$ZwqhS@~o10&qX*-MId0-7uWPQm@Pjb;XA#>f>lU4yK3(MPMVrHzMI>(lX<a+4qjGDB#c6pW;j&G7dXR1yRvbhLu<&-7GB#Zzf^_+el}ReO^<0lau%4= zVYU>19{$$muaqq|&xL#+Z-KJg(D*N-Z2cR%)s8XT zc(ggLgE^*@-7relP)&e3zuB4q%kFYDLF1Qr9W*(hTQ4mDX0;%^$FuqN`d zbtcOmPk&k%WW}n@3*q&2LHjb()7j#3;Sy}5+a^n?{Cr|}4_Mt}bcWQOOfo_UYZn-1 zS*{yY3qb_q>aBat5K`o-A{UPdV@7}IeLkU{!-l}nmr3kZC7{pO(A!?zoj1)wQ)-r4 zQ>s5TyCAj@QYk^!0qAFM!^}Crx(5C9=xt;>0Jt3*Dg=_;?Z)B>pMAx{`-}Dlobwek z-c1!O+GHG#=Kk>wW_=g)g&^w+2>zhcjmATpsH4Je_Tf9+YXMvl%K3cMF^4}IM#ta9 z6geA4SJOc26_|=$V-PXTlT7|ash4m&%rYANvY{wz|ALYcWbF#2+%;eOj}z1(TsH*c zH^|zi0BQa7W2tj67NQGbEIRHx)Y}O}y$7AU;Sr?auQ=0)xf}Q^!Y44{qcbj;B3&>A zT1~*DC%+o{g}a!JV)@gimpbtxR6SPp3*QWY$Pjj_v)&3M`E*rq)mLg4GZ z2kSH%;L*8C}UHx+-&*UBY_8)5nAC{v*j!NO>KRMR)+ZU zZbB2#))@4~X1wlueA58XS#b4bgL;KS^FZrw`0kXQHGo`?u>is)+{8sY3E?}@wisM9 z7CP7@45qh}1tj9S5|B_8=0K;uKm59J3o6&K01Jo*dVF+t*^s@%EuZUW6xb$w2;0PP z3$FKYqL}_1S_wd-a*j3=KH;olMrLA0^vZsLj`|tVujm1&%j~Vr2)1-2`!T*8=JUJa zi`Sc2zAHdm`wu}wl>X1%71}Fz4()g|hpqH3fUMsCKvwJy22FB;hK(T{Rb}o#xWz|h zj+qk_Z-n9L#OQY!VGu#14`qq&EJAS{j+xg8IgE8VQMUvhhg3=)ZQomyo)ZpJ4X_?` z7mDkqz~Rj{cVXeSgdj5F55+qQz-}m9s0J)h)msnj8Cm^@5>Wdgb!xtVI!~kn|2w3#B-TqP{dPiDl z$igYQr-enKGZ;w`FjXh3*+Ux}Yy-exN>a34r#dAm5jm124s{R6>OYmp1lD&u`qC*H zjrOT*0S&ayFVJ75FeM@}(ozp~wEdM{d;vY{$B*gmCJA-GL<2#J;KueHDG_HQEtOCX z0&(Vp1{+RJS$EajSc;-qVoC%iyaOg&bvdTaKy;_;tJAPUOIQl4G;II`HavLjg|>+W zA!L=X;L$N11c$MSm?NP%P8m^CUyMksnRoK%*zYzIQUip*Gbtz!6oSq$0N}eXI8zs4 z2CyLp*YlmuU4Zd@&rL|3rgBBiPc^I*!Kqq{$-kjQM3ia32WN~7Eo~`UzycqU*qcg7=Q)tM3Ro$* ztm)a(%=Z^*G6Tz47N|PW#UMtf(;Tgh&ZB0yVNY1>rMrp5j3|th_9jwVs7k|FW&w4N zp}ULGK;5O9icQO)U$Au*`cZh;K&EIL$erk$3xlK7($sPazWv=5&~iP6JQ_Y;;Fr zp)F0sm@t;J;4(eDgQp)s*4b{bTqf*D7!&q0+gk)%k78iaO}I$GQ4Pufy_)91BgsJ*Z!3Mpc$ z-DeO2i`&I!{y`bce5lnAWlWpvWh_PTH+Q#Sw3n@gw7TL^7Ek<5cUSIOS<@&B6hc`D zZbER3@vfYa76w_7Ch~y?MOlE9rFBfuh$wEtOQOiz+e%pP!S!{f3uo?F)j4=p!RUHt z)(6k)7+7*=ZNJmC4}xh5zV4NV}SMb8~Y|FCE_?QdyX=F zl%w`fwRSPuvr!hh`)A`J!qM??j>t92y@;|{9as{acF60DbpOEjoI^+0*V7ciRF>@< zmunqsm$fX#-*kZ{T3Pq9mQ?)BgHw=oAqdj~&pfRSob+~neh57a$I~<-T~!KIrPIr% ze`Z9WTq&Tw|h=aH*1b|E-k3r?C~c1bVX% z^;gylr-CRQm03IvuogTe)CP3g<1~{HXibOIa5t8$r9@n(a)PYO^hj_Dh?XrzSuRc= zHT#6QHq#iIV9~^mpfM^L0PF}F;crUKm6k&4L;S5#Q%7sV;+OLdyBem0_5Y6o2((T> z+eE}>R#vPW126_@DYoPTr zlnGiHBRAOEl#v@^?Txzd!m4Z)PdAj=@oeIFuq)BgtA;r%?+~sYxjU2CEv2M@s91y=yI0r zqG}C@0OQ~UdQx7Y&Ou5AM#?jk*~PTsWw;6BA0?zzBMh(aehW?Q6M-CpTIK^1aZiy; z{h=v7h>j3wz5Icu*ICopVgIS4s?&Q6P3=^Na{z}v0BSGF98{OuS^(Tuy+oE923c)P zV!|`6sVZ?Lnu2X^8`HSNr6{w{$^l-6-MM2{RJ)pwvg`tVm!K>hWm-&gc9K}qH`v`h zp>_cfllb5q#BDBc9Lnq<0xL3tNAY&Lz!Yd5hB7+{weMJzeGEkGZEc!VCVJCOnwdv) zf!*lfS|l9J%i>Vx;6C<50bQEwhgrwFG}aGumX|ef8m5DH0ZXWc>O>9AZQiA#ei)xh zjFKpn#ei?hb0kuic*JZ08ScWIO@R%V!K&)v<~)abC3)u{{eS~_SuvD3)GM__!==u- zJE|drPgN@KA}|;6@253Az>8lRNV|U&sdNRcTpi-RLFYO?m6;kZcw4^{?^G{tQyI%& z5bjs>eyEt59j|P8Qb|ayj@OQkI_hVM7u9VZR^4+LjqM8lt&I0i#^lk{RMibL)1v6t zTyOYU0t`Z4EWMTCY$zG>P^q1emD=Cm0&4R>+Y_3kox{jA(0W&6e@i;bJE5FjTA)j9 z21ajzW16sKsH2Btbk;tSw`Zg0V84R4H8IZ5Q~WL27-tjm>TLAM^;OG7T23M#DZ$NI zpYGKx^sGO_;Zw!3Mi5e2`Gcy!5tCO3;~l|oco8QjR=-uK1C& zkCmc^EOPy^Qo@k6_=z&wFo1mXMET4+do9&EF>XJ(@k9x5Yly>z>ElC*-&3WYpJ^?( z{O2VEOD_K1BYmFY7M!2SqNhqpdMWBGIrvm*k9Sr2K2!P{63JK3l>jC3PJ z2PwLi+F~iIBhYHGdfiucx;A_QXz}+&hmDUN7fWecHAgdXF z(}adD04DtXv%9d9?t(ZALDq1Tg(C66WbLfuDd1iL`dRrPtAz5z{QO-}pM@+F+y%>F zoTlbuQuczZ{-{Tqw=)l8y+Qs_&lqrqCp`fkm>=0Xgc$Oafbs*O)_5@_xwG z1@xu;g!lQoD!@RPM}H!bMtMqEa6dRtX)mU(CPkhpk>q+FtoR^#n5Q&1>?AebU|Qyo zE^m~k)bvuxiZ@DY_ZEHeR&K9O^d~b(F}&B8WHexlxNwnTL4YS^-DGKay=QcNcS3kw--%%JGA3 z>Oq!wcyZEOG)H~nh9LwGK0Li_(WofE9h;fPD5}UQ!Z{~PD8L4R9=dUR1%T9Mx!54< zb8<>FSN3~|;(q@0?l^h@GT8bL@iv+pxqk{MeMnoQxtpO4S#LBq@%MsE+CLtRX&&sh zio7wJTe+Dj=yW%8aT4!l{;^suj7O*13ohw3XwYk(w|QBss^!`lxQZ*8iRO6yMTU8q zgCi!V2!S`@moVELuXi*rr0(Q}oRZ(jGKN^(&Ed5M)L=K}{0*U$Lqz@@0gFG6U;K&& zz3pW{iX&tE18o;|Fb9$Bo=A9@QG-73ocB1v_p@ba955u(0Y=@dYC(i z)#{Oj9_ETIEr8EGHN-j(e-}3j$wGi&d5pnx-{tRo*;mLg;FvOW6IAwN>e7@q*t!U9 zcq|OI9wy$N=I*6F0Quc~*sdKwkaf%o($E{ux5CpL<(13T?nlmfnnMP+z~D682#JCv z1A|jw5S-T-Y&1@>jMnM_E+@8+lL#Qr^p4W>Hsj5%R>#Tvogt zMr3bugy_Xono!)WKJFWF0~|N20Ug7Oa!bBKE<)k5SC$K@QP|;mJ>{QBrk2_7hgosw zQ4SiJrAFMG7IzvihcyR;{ea>(xWTRGXJM8W#}2=~E56>%HUzipTHcY^LT0mJ59vpL zPLZTSW;tjhI@E;IP{!EUK8bN_$aajCumV*qZf5W=*VF3Q+tcC*%C+XJ-Es30j`w1& z5O3KKH_&Dt%DUr*CQ34PI5`oR;}OsfyR8~g5QiI>cw6+J%H`yEVWp;b6L=X&8tU8e z2DhfgO+W*B2CN%|452fjc22^%z|pJ@ci-Zdni~ZF?>0BRM=cu{I4uA`qp_gAsazIBR<1PaDkBKI5cysim5$P#+j!pW%SI5E@=*BC#^$Ty0XE6a$rxLFeA<>Y;UIamx@PW~uv zu3O%WVG;$k-?&=zq-G!uW(KdsxM}*jIkm{}VrHeordpQHC{HyeB4ZK)ebc~RVPWqL zdKVtu+M(}Tl*Q!d*SvvWY&G|q{e+RZ@AEq|Y#nM_7NI|F=YikNBsMC->>hw-v3PZ_ zIV3c39$!UY6phIn3JHk%PlW6M%Q8~c&s^T{2kGNyHissoFKrPB;+gHWsR!AC)*Q0P z4?*m&FmlJwTq9^7n$ax+y#mfWHNKu@8>#AVmPLO&Z0c_=C;BcU+ z3?c$9tL>$>cn%8CLC?_N!g!K{{(8pbon+;>^i2iBmXAfmy7U4tmq0tk}O@_y%e?!vwPe((FoeRgklw$IGY&d%9Z*}{+DWLIooEuhmFz!Z5 zF_>y4LJ4~di`NJ!>DU2O<_?016NhPRd1mSUI&kv9gxqG1M_avj6GjgZMt2ZKw>`D* ztHy?{=E#&QnEVppvgy;DsE6Ad592>?W$>ChsA_+vu^Ip#kS=BzQFd($h_Gsx-A+v- zMN74W#zcx_csH+z6m8&Lzb{hsRqrP?O3YFRP+^oviOxYzla+4g)_jB99#(oeN@T_^ zLE?Yon60Enix&9YRjX(en9K!6Q$?uorzfICE4+hpELyAzx{_%!#sqFt9b@RX@%R5@ zj2*Nm2GnqRi^&&i75x|^I;EfA{C~5>K$KX=GH$jAo7d40fP2{DHWkK-h_nw;40FN@ z2>%-=KPJR-|h|Tj;x35f|J0VK)n;IBVLdcUa(F3W);?JV%*vV1Z%Cd<7W) zW`QkK7$-(+kWZh*iKMWI&PFx-G^(IWvj^2$QsY5)i%5?bT_Zn1!}4s(UiLI&zoEQ> z`5m0JC|>NqE8?*USUWcJNPx*$?((6*FF2vtLcJ42a{b9js)i54NRZ&jh|aVmLG%s} z<1XR6W)swf(on^iOHc0*yraY4zz`Q*Z zg;XmaZvgSOG*Q?htC0S`_}Es@_=>h9f{{AVzC;X48#j5HLns%iPvXAoyL z#{SD8;_W}-FI-J8?Sw3@t*6vf;HCtXI>26O7;lT`V<4R^5 zOb72H1n*bY@jhC(8fJokb6pRl`6+_~&iO!wz^4XqQy3s*VQ_0nAMjsq@Lw-DfArjQ zeM%1+_gr8I^%5dQt)$sP2wAeP35&DHvQfw-Y|5pTxM#Inb7l^Mmawr&Cwf_khK)I9 zV8lvzQ7yuv8li63n#wOlbU&C?wQ@yg1w#BeszHHT+fEcOMUu9@6J<*gW#5nTpMu1| zQ2C(_j;GL62`>AAwnz-?a@r?FoA|@%rn$TZ!Fw83>)l$+y56WV?MNr`(XpsjQzKop zNqYf!=6(=(jE{ZLzOOa`1`$-M#ksfJF=c&eg^t-GdQlgn0(cM^^92e|5?#ZeK!yh% zS2k`zxEVj9NlBp9QhFc>4ZDl>B|*AerEfVXq+3a19KP}}CRudMsN6Rs&=?LnJaK=Z zF#_SWX@SN)2s6h88YX=%3^YdJ|B{}8#%P33b_%4U$)d!+GWX#?!;fe}Loos0WjWLk z`v04h*howXc>_)ObfdEI7=E9S(MWW#Rr9pi%5Kx~Mj|3I2yJC?7>v-PgRG~TMnW{I zM&6&NNw{9K4rDL;8UK0flLB$d|G&ro3M!l>B4|)!yabNTAolT%#X#-u$E}_CuZ=}o zXXuSw-;10ZOlaxU5oPz)RTxpGV^LuJn+5-y!1Ji{gtxWDpkS161toAPYv`F2A#@&H z=4M{Lqd<{NXA1zcw)2r?v*|aW`TC=d$HVj(lBpsX;=5U@7;O*hZ0rH5XQRgiww$)5 zf?jgyK&lXp=OguN?9+>;weP@Y9#y#?t+SW40Xz@;H->5GVX9~nvL7(BwKr?`oub5a zk-)=nnzGU%<+sw#G?8q(3pl%1j;^LbjUWrE(uDMX0@LyG24%x%&N$MWhz=QOR9m1y zQ7{LH8x_d^gRQ*{RGLiYyte?0zK=~4#h)Lb^-V-_crA+h1{7U1twRR}zd#3@i0F_5 z0DBs{ntp2{(nGo+Gq*JlZJk=z*6CJTrP)?|d*H=%Y$PReXV9f|(Y{duq7^<^&V!T; zR%o$Z!5Kg1bfU$2K`6C?2Jew}KR}W;(d4FL1RDl|Hqm=c#Q^mk3U3D8@P&=!cu_Rw z_hlE0Nc!};y+P3{8@qTs3 z4pt3DKEbI%lC#n=lB4;4;;n#}f~ee^BR zlFB*hc5OyIgyy2#T`8=%RXYs(YcP|&EO8@sX({5u3y{u}?(1gBDKxdEXrsk#r0p$* z&>rYa@3s`%nIuoq_*P<|`Z&GP3L@ui3U4i{8Gavyv;iD4sEwE|(>fV!dyIwcu^)=& z(XdJEf(9xz3c}~l6AaOFX0&xW;r5Z~Cg8DYmQF zphZ7QFLlKp=Wu8GqN`YghZn|l6YcT+g-slMM#nff=<@3>+G|)jvwDgpn*9-aqo?>B zUlUm0OJpz+20lU`_7Z)V2z!h6VfU@B)N zOKH>xE#1QZB4~CW5vJ~>6@4%$SPc4Ly}Uv{_Q48)#h?$+3n{0saH$zo(^tH#E^+PY zC!$q62!60X#=`b6o$e1FdWS*=i1@sCw3er+!m_v3K#wlZy~yI$GGVMkI!i{jv+P5h z<@*jT`T~}#VT^MIt-Ol8Dzn$qNZ+l&JQAW99bs{2Ax~jrMXVj8_!tr^uuIO@oCj9> zC>d8NYb?~);(r`1@t*Ci0V2is2;RA;)PbV2nrrp+zJa2bI+zX)6yK|>Xxku6Q}DyC z6NAK1pRj-|w2>d+z-=I~awcUC6Mr{4wgv+_t&Lme7Jm-P&bYOf34HSQu4qm!?DDlV z_%88=??qdqK&n4n$OgE2q}CO-3x&BTXSf)pen;DeV~H)GgTqDBU@v9j4Al%5sdlzO zKV?aYtxuA#M~#1qVd zttf4@80hyaYN(>|ZLnj1a75e6?ktojps$HbCj+D7N@^tvPqSV7VSRUF4_}UCYJ_o5l+E zLwTaDx`5u!gA{m|LdHW@jirmL6jqI1Ccg=yrFVJj-Q~SZy(ftDxJhngrIoT*QE;$<+29q|_7FWX zL9_!I9hx9k2DAhkmp7UQPs9vC*i96VYQ7KA^@(C}+#?vTbICb-Y-+^1v-Opl?5U|8 znED+kuWGJVi<2c`#B3gtraU)};*moDrm?Ba_65Svy!~1&C&M9K3 z`Vw88g8DKzPc-$*7xvKem=I4tBUjPPd=b@rEnq)G?nPmLat(bC!Y>fN0Q_wD`Quj) zKR^6@SGiuz7w@Y~n%gL6I!JR6vb!nz&uQX>`UV{;5ZQ@Nfb$_U&K6;BmaG^%Z`9J+ zc;|t`zDfo*XVWcZDBUarBW6rTgU3*-8KMIv&JYo5AC3>lIo#?QqF=LysQU{jh$=7I z2`nLS&jm0n<{4F|RO8esuqzfJo~L(6ohi~2HK67;%`(nCuk2wIw$`!L=V4?krJR2p zc3(iBqVY4qH2#Z4jy7x+YatEmjjo2kDyLs(id6M(3YjH_h96vMt))4?T8>wxwDS_K zP+u$(etvId8F#Ou?XyK6Ef_;ui1UvtvqYj_WtP#-f~)6g{A|&|?`)P~cS8=-r9#}K z^D7iFzSUXA-=r5})qKu^u3>0!7vpma`XECyd{es^uULRd7Md{!Xx+LPB@9ib$~kCn zH>#N<-s(1}3x+7NtOuG6Yh{KxYB_GhooaEj+Z6VeP4Au2|jOEXiIL z!5E%gW=Zz4P{1T4zFE3ilD#YdusjdUED6T=mGt2}u}hsuQ|Cka_M=1dMVkh1u0T6@ z`g~Z6F8fPkGY0?t0vVTvM$IGYURE*s~DTeuqn-}HWGGzGN z=jLD;t}&_6o^9;RRg7rhpPZ<$qCTXhr%12}kHQ*iyHqrlyaEA(x38KTo4XjMU=|RL zrxi;@8=pUmuuC|csIzj)6-I*O+2@qiwAVEp5%WjID(prXU0sUB>rYBtCOXBwfGQQY zg-r(e)Qs}?!4@u}>}M)mCL%h2hh%IHYVfgC4V1*0RI`A@KWvZt;Z2} zqF1P(gezEz{}R2Si&OMO9C81&OeAF;1kf`qNsNHgGqjS2qB7S#6r8>RX-sefl{?n& z%apZT#OqXK6>)N5UoQo z-5wy4s9%xD9%44v2Q~J>xzM~tmLt*x__K$?e2y= zP{=c`VFFLU%8~;s3+q9pR9FG&@2NeDYKlbPdY8~p=|i8clyP)#v4{yzKz5!Y&xn0Q z>x)HpRw%%%r7`Ku;yf1V)Q!;!)MjQw8qd*_xS7ZJ9M7hJ6&Rymms=%!#^`taukae9 z?$mvSm>1kF+tATmF07Ictq`ARJ>zJ@{bF$JQk0GTL|cjEY#+7odDvnU5FUs6worYxtKtDyBU$||uaeheB7_N-J|Sx21_@Z2!}_dZD34~kY){+9y; z=`MB21F&m9iL4KZW$_7~tZo05wZED5nV{d7xy#PXrN15&+k)Qn0J3t49um(4J?;VI zI%(4yv01w-n_8?D&9u;E zG?$jx_OjheEuv=I1iKWp$ENvO<6sJUSj_YVD=1qtu2I^0 zH1H)Fyk0~E3_;2Zn2llzAB%G}3}3l|h5K88i`^P~FUV>psA9?)D?0f-jHD_GzwD6y zKKE4bVZGh=5z(_jdF~6CL{z{l=tG>}ERtqFB77sab(KOiqFz)5DQa!BER>9J_l^>bF_OxqtN6NLxQRPM$tXCHIR8hgp4-Kg|cBV zT&9YLG^H6EMXL5|2GK^5$lK$_Aa?Q7rks+0?ZW5$vfIcoBVv3C> zF+}U0O9dnjfoxiB#%|M~!J9=xhA!MJ-qso{rgmGzC>vOur|UD?vPDd5d@=XQ;JP(x z%OWf(=(VyG?Zmp3gbuC->>Jv)6{@FmtBCD3%*wtE;8JYf>d;XnpI&+XA3{1WIiCOK zn5_;ri=4*ArTD$FNU=|K9oZ^+Y1&B#MQjs!z9oMlws4zx%eN%#7YDW9E)4Z=*OBee zH-efiGzCD3(mR)0l!`_{x(Codm&TQfWtPMMR%T_|FH`(8CXOK)keT^!|1Tt2QVHGB|uxInbKJb;^O396qERXpWG% zu_;16k!XUDnI#n=?nIO|MtBopLxjATBq3x0A{QvpCKosWVDoDNLN>X^Eugi}iMcUV z*~ahf)jg%r+VS%(ls!AKgv0`+*fbK?V{pp_wEcOQr|0u}-I!k3Ei(Aice_P=(17`1 zIcvDde-F&^mndxy7#`B>4D5^8p2D8GM@&>FlV2IkCpbbX6UhPR=V2|x0)CbzmBA|C zgN!nmp)%-LnHZ;u`PBS*(LJ<0_X>n3_=aU$7Oi+5d@~GbyTx$LZ$2x9o$2;C*+2`N zM?GE;cR?5`kmMk9HLQ5Z->9Ov&cqpL6w?rsPGji*YX9hcAyVZ_{*5;pQtT@uz5%|?b)|#_Z72; zV`-$YM~(*6)FvR@ahh`AFckJ;JoY3baMwXL)WYV`$1jV;Y@jHI-+*HtEhx9_vHtV$ za1-pYZ;<{9X5eXB^a`5)869~Ahs`hq#J?&MqRKaZ4wlCX_R3sO+amF$o&K+ip#eSs zaZ+1)r5w8wsB>%S(5u)5XCXoHwRXWBUW0+_Tk8E9EFLfyzJ@7zmLm6})4$U_dog?G z=~Z%m=Gu@K>G{AQ7#OLPh^MDZ-St!;ip*#a8u!j676 zO?AN#I*^XI#8c{Znz3KhhMz`uYeFoe*#%m502A^H?K~icHu?amR!NrEzxfXoax?#O{piHds9ro zxzgabL_antMHJGmw_rf}i2is>^lkb#I^|IeFCreP*e|?qn)0lhwQMnAIBeG$RQxgA zejs;$pfMGqDVJ6`n;xma{I8^2Z{v(6W;P9YM|5nu135fI_$1I}*SJ#!g)Lm)|>i;gt=>yvKuISk;6B+VgS_be#{q)<1VrBT0nRf<(Ewhs8W*p^pwj za!;q<4#U8BI>Wqdny1CP7wnj_iKHJv?u&Hr2(}Zw_K6tqM&S`qV{ck>M6?Kac?LKP zQtCKkq~n9fe;ff1?4wp6<6i-d`4~J9I)fH`Z1DhmK0ikNz3AM>Vnlde0p1S5ulIED z0YX^Gjw1CV+ICcw1j6KcPQeS~kt((S1j4lu-SY_s0XoSiVx8tQgL04IILn5-9%tdU zwCI><4YT44$52cqRUZ>A`c*37J~gTE5>g|rP>c1cIjg|?ubFBTVNYsPS8h#1dTOFi z4Jxcmo2nW+08dj_ZEXU0Z{4TnJm7s!YBcv#(ZshxHJZ@QPsN-8=EF1sxQDgktpW>e z1#Tu5qD2aJlsMZ4d{Z5~fZ;f!uTr4!4vRMk)OHr9%g9%#D71AVjsHwUHygufFb0}v zF$u;!{2!J|KF1u+@o0A%Y<)xMna{+1_Q40Ul!)RiQRD}Q18WbumReOpr}8bJk1K_v z=;ky~Hx5PTMZx5W9gm7v#I7+6Tc>$RZWz|S%M6Qynbdu%heljfz6mxiVRj(VYuaMn z-V_Hv9fn^CHZB0ZDM>j{jB*eApkFg`ZxzQuP2}{ZA;u}B_fm>!%5f1oybx(k+-b8z zjPH<^&nnpj zBurKTjcp^EQ@1ZffBRhrvx=jNv*NJ+vXxlHu=S^Bz5r!)q)T6j4X}|u@FgVY4LbKF z^wSy&_)3)9u{mdgIO`^eDiFkBI`)-_*55;eioNFl36?fKp80=b>l@^E0?h~SoDj*G zQNU*Jk)nc*9n72ZOf_g}DVO3!9-C2$t*(^KTQ}4C6Cys`U^FjES?@Y<0&P_vbtQfS zsngHh%zSq<^U%ycFoeaRTU_6YPV82x(QX`Hd<#*5bDwX8y(wCH zi1T^1^dSESAq%to&2{C!N$PhZI_pg&vudYwQ;Y<}LGycA<-=%ZLaC_v1uU4W_!xRu z#dsL${O*j&BjAH)U3Yy4>4u4Y`+ITJH*^Z@WX?k{c|QAt7@}UInjau8{~-NG(KT^T zK1e*w@_o0#)kLw|*7fqS9aYaQ`Qi)LiXU-?#Xe6zLyQfj`9DMYme8S}F?LV5(yByr ztzNm}^f8{MF~2};kEX&?*h-ZDA_U;~`WO$=SHECGnN1<5;7$t<5x(Gp1M5>z{~9xL zYvA4IV+^J}r+^n&m*1Ceq9i09_A%O8iICF2ijDx?^f96>P$h#B=(k^m1MsH42B_{g zl=CX({016Kqw&9qPmz*mGhU*$r$N%=C)4sTVectDEduO#Fp8y=6Bn=_nQUp)*`yzr z(e&kMm}zk^b{ZyK+%=y`ZO`BoCmET~h{gd!{u5dApG<$A0r%j2qt+%iK8icztVjun z`cGsPE80<`#h zY5QLo%De!hhlO&35-*}?(07UQaDdU+f}%}z(ER~MJqwCdAEJifE33uM9CRQ=_Zs`g1hnDvslAoHd2= z{t&Yx{s@OrZ~@~G^L2>B#m<`dspcQ?cVtJ@%LfM% zXJf^Xg{=IwCAC^)>xICSa2%b5(23+39Kw6GfWru9%~Tp+Eq;bJl~aSJeL-t##FB6Y ziTO?NeE_yl;eOXmio7m%=wIfUZfwR5E%L&67+LdLqs4#~wZ`#WJ7*0%05Zis%ec_VzDN3oyKd<}MybHc<~asSBb;@VnIH*SKd zw~>BRH0_7SDs;510v@KXYYFQPqf(*9U+9AuQh2yZx$pe$>fOFZH1LXHAlwbSSU+dY zBG_-u=LcV5r*Vi8PvH5e$5pg>@9tYFZ z;s%y#^C%su#k#c`Ngj7W_Ow_by;dqsl?CZYZBq zFti9IFqYpqx~$4v-$%w`F{m7%OS)T=!_;Z?q9(J|k@SZq`{LX<(?=%r%`6`|%BR^_ z^W=iQ@sYjwMAcUcY|C?eWpZLFN@Zm&6~oG_5_>rEor_=4#)h;4D2^C6%I@p6|AAs3 zNALN{SJhsw`F;`$)yMQ>J-KQ$)(2J=0{8-*+e|YS&1LP8D;ULbUU^Z`-5keRa0N@7 z3SVOr=6iRY_PA;5AWp|>i}XqbOJYBI+h49!AEX?c+<=q(uWT|o^6F^lL{Qbdb)r8g zBtRB~e?11nW?rA-XDTAfzzzX&N96MWWBZfA{Nu!#JSRO%S%LDDJ`;tRrvMlN6^;(m z@Za41yZ=w7oFI7=Cte}JGFoj)je=!!|BL!rUqg&>jSQB7YD_A!a7P<+811ZSX#S5X zqd}FLq$fjUFF705-moMr(^~e4+6d?I+V{2Np4SobO-pd7Y#O+6mAdyeP~Xs1)G<_c z$vQO(z9HZ}WzoFqD#YPX4PQ;Ls=m&ecn2RYN+RGj@!-z5{M-ei;)yw?1h36Xyv1QMj$@prF z8+{pv?VUACIP3(GM7mwZW51YXmmLBj2)_bd@4FmAMRu8`HNeQ(rK8bpV3*#i&9JyF zvg|tkOZ-0>UcvQ6e$B<0~G>`qc_*|Z>!`2)`?HSSuI4xA|L=qj3Y ztw}|kN3F^=BT_!3CY}cF*R8wO*a~_asKw4r2_L#xPr~a{%a?y~(iI*p+xy}(!oA_n z3#D&ryma+nbT=Ms2F-b=QL`Sl{!@x8*e zG$TPithH!FHxgtcR#g+_5`1HBTOy=WYdV-Hr^H?x!7a9zT{XkFvcJtRrp!S(4!IDQ zj}ACwihAC4(jjkXYIFKghk%QBr6ozBX~`p~Pea){DhipLu(l|5%Ozf`89|RVlw08s z(5#Uh?Tdxxb6Vd>&c)S6wXsamVurh#G?vq}df|700(;ZeRC#++$&&rBzhwNrc*)Jx6wpMi zb#PNGJk#n*TN-ApMOu}4*ygTbbC~e}4!vNsssTTkS&oL8!^DpmX^=K!=@r!6 z;jcT;BtVBDw+#F*xue7Da`T~3A5xpjn6MUipc4RfQd(1)VCx)i9vro&{!L|c(LWG> z)nM~aJw30sdd?&JG~|}2KVM?y8g`AXY*9Q5B|09mZrG3M8~0}{SfxHJ+z^047T$r) z4maWeE9HAO9=xZ+jYz;0O_^{9_(`}C24J4*h4_285d;_r<_=z11EU@n*igynj9zgE z>^3E%2K@0Q27hCp2JW%2n~r}ql+z3&Ira|p7v%a2%uov9Q#TJ*?(&Vx@8Iz~{6`8@3Zdmx*^9U{FK~uSV~{(-!!g1?u8*%ygKlHhJa2bd~F1 zf)aP0v(fZwa~TzMFfGrq!zXf@o-mWXXfCrLfx=rzN9%GOTsH&Ab(~Ri=CT5As6Ym; zG&Fdoqps25#tAgOg^U>Loy;WVVI(uFp65{d&2%WTz>#+>&oMr*+l*A1=g?F09r`Cz z9mN4iw@turyhB~G8o-JE0ueo*RvX0)IgS6=l zX_JQDCE>r~n=9&I*DM@vPQ~I*H;>dSZZLJNQgk5DUn%LG*|jDOcc^=3!Ym14nTpe0 zPbG|;kH)bY(D#GdVJtKy(phk34^|4Ff4_FvYS^W?;cX= zId@GP7(e#m%?onR_`bGnG9`KnB?%#chyDk$AWIW;S#U zG&m3h@(=L-20m;#rX*+m>g+&gO$2ruJG6)k=gDY=#b`SnXeB!(okcCs#BM4w-|^dx z+F_B4GOB+>jnlHb)|fR-rl{7^kS_)tx13k$Q$s8h6OC>o8`{@m zX1_*lQ!g)nOs-Pup9jIy#x}BFU@_{QrUe{L_n|-A$i^Xf2L*nY#h>rPe(+7wGh{?j z4akF+v2iOytGV+_e0;GtjJUv~59<<^v3dL7NV2bkirUuM)p?7_Cj?}bv(R~qyVLv= zkW&liE#;f>V|#(RSF;65ov^)rYJsClo3dTTFsT(d@ET5XCXfAhQF+!%9E68&ViX>CyI=ZKwOr}-sWa>1| zvk0_t6?o8~Yl`rK!+U6MfSWd&qj^_BsWrG=mLF(oU$+OF>-k z^X|ge_Bb!QQ9Q?8gXUe+Q>pnurJvf#$D14(s0@>TFZ<#M%E%iCTP*PQpx!im&y$BD zP4zYAvToFgwzrpYaa;~l+&Q0sqkV92ashoP$We?>a;aTMD0_2gWJjoebLd1zITS&Y zPI4fE#hv7EI7%GvBqjb`?j#$Jtpb(yUov(73}{P#pp?=@Q*XYAns-i}c2k9Kz0Ejh_e`(TD0gG$T1ayzBhh>xGa7F%0e(&9D)|USV)UIgMo3J z*I6#GUx-(RMF4FzY_Ayzufh$UT4u?XA&amLO)bdpkdHO>G|kA8x_@lhn}aZ(?2Brr zJz27TBx}7Jku}m;JOs{y_QPP9UUV!=Mh|}dm0CK94wu(b6%521cPYj-G|(Bz zN)KF-fWrzC*6k9d+SeG0q2@#XeBK~o`|KO*T#Utk*zl*Edz_?a%lJvbKmqz*=nge^ zW7llfh@Eu&eeJ4QPT5pv%^Gc7wW0^Cn}5ERe&Hs7|M`OC!`{^e`x&j>)nRcpUD9n> zWbafp_;+;n|ElVKobr2$E%YuHcDm^Qx7f(z|E*XWoGqi%?(!~aub*)Ps5~D3y@8SY z{%c7Gvt>kDM|Vl3Y*fJI&Z_^nq|B}Vtt9uT-Vd9Pr>nxd*o1nPq5Y}{v2dSzmdJ^Y_n2Hpf-L^|(*{$xC8@K>+~U603F z1e-%O=$E;Z@lKoRcD$h&hX-!(G!S$}hF4keVffAlCq$aS@6AH-9Vj!5EBo3EW6HiV z!-TRgI0Sv}_8DG16~3iunatkKnrzi};higg2WEoxgnIMaw^up8{pI zuN8WmKh}AR*Pz!?n7Q8pfggRNc37Q^!fMNMCJ?{L=smAzET>q`aqrLK;V*{e|GDh3 zBlpwV)^cnS)VN_&@s*jwp|*9(1J0Yg$Yg%KWh>N)ODnKeW=~Wut=Wt>5FnqPMZI!! zttp?*VKjJeV#+1RTj|cb9(k1eQg8D5TZ0+-Z+*eVs*QQvmx$sfS=^!NUL6VwQHJq? zoP>}CA$RCfL`BvL+PNF<9v9om1X|re=JyRy1CQoo^)G|G>H|q>Lu? zNbo*x$;n!PQ?-^*WmUeTA6l7?9?0QDa4lN7shD*=odvKD%p& z^@EH=o{WmcG&57C1Yh#ov;Ji9fk#3@*8M;`Gi94NZpm4UZ8pZ3$CsNd>)8fioFB`P zleNR4bUjBV^(X)yQ|39Jz%q}Hl84q+Ku6)RS5_68t!skTok#0fS1CY?3ecM?7|#o+ z!~dphWG-a6|9g;TxCKkDt}>~?)1k(k0j6V?CFQE{E%vU^>;azu_+jAMPKFxA5NQF5 zGcy}U#x@uYAtf(jLiU(tDWS$r&2r}a4S9HOdLo1lU#YvFPl>{RHrYX5l_(AC8-4K~ zIw6e4_06(vC|jUxT`ArQnNaD2H*e^PZZgf^#F~fC6?c<`Hs4-scysob32@FE(_c2# za_Z5#{_?ywqaH0BATMj%>QTW!+0GH@Z@5s-wK@LAeuOda`WtWIRwLdtsm%1Z(Ypg> zwQpr^Wj%UxkUXY#bgdaIOEt~6vnzd=%v0M{>Ios(enpgpzgA1DK`SV%{2HHK!diL~ zXOo=P5^3nimMLvG{qTFWVWS>kzq>rE>QI#-D|b?YsP_@-7L_35alWG zAEXsKSaK-0cA<~Cn~`UwVyJ<|L;699XZLEZ_(R4^^1}PF=ni787vfut*w_m(#$H!o z2QR!=8Lx>K-sn4c&Asq;18;S6h$kPV#%$mRZoDG2u%Q>?c1FaZNgZNpWL?E^UU(ZB z4_4Vayj6Gb!o2X-G9Ik9b$FF`@ah4t$TKv>KrHU!)suv%x{7c1zB7ai7%#UDuQKv(7{(cAXr#pyccXP!H>MFjNn~HC-xaXLk z+x2v0fNSU7V2ZZ+caj%)C11p%yZW@XSG<75#AJyV__Hn%W#?X@b|Ym^4SV&Xkuoy* zxCb`?=4E^Z^DXQl-vm7``8vgT9b|Umd^EX6Vh?|Su8x$eZN4#PF`MXtQ8HCajiHxE zp_B)>l&PE3FWpd_}oo>!fK^nSIsduyLzXb(xHKe;Yj>Cg9&%(LFIBqugloRQ}dD6nU z0GxpyKKCF6dyw30`3o0h@p(zwzt~a*ZgEuIltF^UP|;W!+37ek6~}ocFnc9~U*SN~ zzZd2bah{NmxNt`u^;YJtilooDfVVjz$t!`$+Fd}VR{^gvUSlsj-&hjkWMupvP8fno zff(nH@VUtpuhqoTKp>=TV}#*#WLcTZWa+LU)~kjMw0@i%ODmhf@e7WoBed#HG$Kz< zQct+v&XX^zktcsMX9u58vl-W*1+sp1KdqP`X9ky#oMaP88@Tf2OB#lL%2b&KPd#I* zoNoIh(Wt^<_)hYhCTGg>eQyLZtCycR9f;f0#X}-0R(;+^skm%1aIOz+mItCQ)PfRz*9b@Uw@%HrebQz{y zeS@}7!r=UlKkT7B3kexBkZ}ABYt)v`kjrdgkm?wQUAT@Z_cplg!+J?cObcHFI!Q_9 z6d(F%rp$y3qB={K_+rSjtb#t7CBuE;w}Xbvl3gtVf~QV2HJdGas(u`_pr>cc813%^ z^v-O#Q0o>)?F;2WcrDiy%Jk@(1J+Gb8%(dqa}~U0ge_OMI9I1RvRL)4#FoMJ?p!%R zWj0HmFDFGlb;7z-Weze}jM?i=+BRR71Y;^a47ZUo7sy%uru3X(qn8)R-ta)KSs=Tn zv_k=&qw2O**jnSWjS)Uh%v^NYLpgZs1uck4??e+9%GSQ=os2oOWua_eWY&j?UWJ?2 zrRF;-2{@gEdKDaR6fq2LfXqZD42-;(Veqr7gMpFfGt7K;(v1g3p3N}xu-^>>Bjae3 za3kByYt{>b7++(~aQmeKW1EYO>o z_0a%IUo2b2{R?Q6ng^~4We>P4;(K8+h;Ob}0pM@5fCyXxS}YrpZHWxF8gM7Yuug#! z%0^JLC2&sYNi&vs8UPYB^RIO0-(Q#iPKr?q`!9DO-Ss1qRShEG!cuu0Ps+Z%3?vD{ z_fHm@(3g2yYom{6Txz?|f1=_$= zY^ZE7E7(*vGsIP|th7Fx@h+?cyFc8q^(-vVt0Apzy(P@d{M7Qstt(hFf;R=*LsoW% z^n_#q4C}F^o{z}R2^=$1XCjqPTB>opgWi^-x2_$Jpf{nveO61>nRPx%?lKx&}YSw2iWlZ)MC4Us||PzTjJ_2m4XVCfOOW(S9_=itY8I=d75m9-Xmb z3H2!DaoNzyJMeKiCS>HN9*T=EyT^6laXFdmx;KcDH_N4neG)`ZZI<&8>l{q+TjYI+ z?G7fqjK#1Yf?f5u%5YW9BK-;Z1$@Y^J|W*#zoC6k$}YYo`* zr#6v3+lHrXyY9wC+;Tj{9I6p*_=#Ff2Mu2c5Wbg=omro1G>ed3?{=uUIk&*uyl zkX}Amra&$mUXdMDX1UK^l{?{QTKJkQ*1{Xm->=CP+Sw1O%Y&frU3=wo+M)*3cb~kZ zE^uYN4mT>TBGL7bOV-mk^P>lVePz9?!5i2IXd7ecp*Q8njVl@$KP#4DqFyV|F>W2d zzTRpI__M~O>AekU;af5%xepSUX`OtDyeiVz*b-(br# z*3iY{TVL#1{^MHu_#>GJ`3fU<3jOhs>>GQ|J?^X{%*B|@z3yu;DYU|c5&3g{{Sj+g z(2k2rLL_A$kuyZdT95sl?}Wvd-FBB@B0*XlJt7N3e*)07^CvrNEK9Xp%_kzfMBY#HSLsoWDLAx)V$BAc4TfoEnumC3^@ud#s{Y2n<(Q3%2){4wcBab{xi8I!ISCB zbT+%imQ6)?78c0>Hk1AEncRt6?XIFqIY8si=_Idm(`DFci-f0;0=f9G_)jxtkugmao6zwO_Y;y6?bvzc$%jrsiFQyca!h5R42L0IA% z?m>F)CwVW-9Kk=!)vBaTKjR=Th|c{i=Z2&{R7)6RJ4=N|G_^|J%MANj734V>_Cl3R z()LEV>YtRV3V-wPUu1+<^B^_;MP@UzO!-9)X?z_opz$mXj5nhE@bn@)76VXX1ttZP zRbz?_X9E5Fi)Wda54*60(_a#XePRr||u<8DTT4|$u#R6!ehzge;(#`m~#@;C%5t$h`UBtC%|zK5l!PR$Pam~O8H$b zX7%r>-=Y8Zq27N$K`2SP6-|%+fpxhgt#^#;#vc*~4JB!dV#xn5iA&yncE-3q`b%nR zY)iX=Z*G_egRGe6Kw$C)>iib^<)Uokhv*MmDDDz81D&>9k}ZAjj=~ek$1chAc;BtH zw0q^<`%~e%gkGALHPLf8^faW1%h>E+YzUD)__A!1cyfz%GP>Jm#Qxndct8u-Tl&6w zoDZHprJa{$!yg>**LvC1ptT6$>{4#B*Nrp~PR6jrq>WW=i`98qhcN_CMBm;QqirvVF7to3Tm6-Qg-&e9R`J z8M&zXA4phdwB^cW!m(*Z>DOesx{Fp^lPv;FC}=2y4gi{nqcBr<&@k;d&HkJn$beF= z&kHc1k5@~3128k3i}w^k#dePtrBut2nqMPYSq+B32JYo*Ifq}-NUo7h29-B5k|2po zlQoPvzSrT7=kRpni;CMaH5H#%XlM+(XpQs|l&?UYOLw=I)j1Oz?S1OD z?A)@%wydG)0?+-;bmz)*=L-8Tx$4)#AGD-ytF$t%dIZM$+DpAGWs!w_N0C48B381IS~ z(55?vf8sFyLQPc=qb58|n1gd3uu>1Kp9T93Fq0c537)IMSar)*K5WGZU(7t?Fj$P5 z@f1Pt+b|FqkQ+9AZ3pbk_aSed-R(FLuCy%$u2~-hBpbrtLOM)>`vAk%(wYdEVFL7S z?f3;mpH=2_%C{5HQfz^X!e(Te zmf&g;TK)pUOd1@jM>jp|duRWD*0gNn*;#4pkqEs4v+cAX7>gzLor!2)^d>sRyB?;3*0(T}DX|MpK?Zj)}VR|EV zuWLq_UZQF%a;Y|4j|v=fFe?@5>iB~$(LfJXc(hhdP+8Q4Twtx(MG*TZQIrKkE zFxJuW2z?;F385SH#vRPkCmy5=QTk8rxa+fMeYqC6BKH=^vYhp{5pnvnTySliK8?eI zczvt(BD9$Vy(+Rqc_8H+QDlobGgYEdm9=rxbxYf6&j)I z&Faqt5?gLeF&CXm1u1%W^&a|G*L!N6r%_Up-Z&}CUC=-HXbcL%IYyF^?=Gl28URIm ztSd1JC&zjsckr)wXjhWnGbuIMXyVnc6nDQIo;H^xQ&6(rt_bTC8>4(+jQXXkb+E;& z;ICM2e#6@O#-VFeW%fU^?EWb3KQ2ai%IMtCE%74CZUWCUp7q^h(at>ps%+RHYSLKG_REhl?%7W>8|%4E9z1ZTt#xz%WW)cM z`_TvJyT*E4i}@aWdm|&`v^CG8Fcv(|LI2q|N>0%;>sQbD&$-o3&7tpfy@&Q;K3z}I z8z+7QB&HJY$-NwDjdC(&rRp8H-6veMI8`4qpmzVAcE@?<_UT4Ov?q=}*xmDd#e*9R zjl>P(dF9tSPGMMn*iUh3=-Y1|yz<7z(>M&|VLOTzaNm}=Tjxc?G%*c*%l}v3o=*ea z4y8+J`oJz3`Ph)7f^{f_yT*FUYQ$IbE5CSytNp*b+%(0Q;O_E<{j|J^-jn;B>!OdF z=zR(%p?wOx^0~-Oc8mY=J#F4^eQ(&LyUG-UeR;=w(o$2+HO)-JxFn))+?;OizFjG_ z`U;qbKdC5PPix)FQvd|RdHDP6gjWYw-q8IKWY7P~DcnyyaJiqpOV>MboBw>B;+pD1 zxw5#=>E5$<`Y?@7-{`wyBs>!PxzdR#Zv!ht5%$f$5X4SELs=Xs(3-FDU-jrYv4 zv6ndz?)DkU;<21;&GgODQ-IA3!UFyr-Xw#rRemihm0ZpAOrEr6`am_Ca++gpZA$B# z>pj&t`l`9!RSlrn7SMqHm`r0^=nieDihve~nuEnkNICbK(*D;R)Jdb#7yaCT+RM~507*X~h(lAdY3TQCF z8m|(iL%I>`iDUkF9G80VK1es%BbsH=LJzE}DP3!=r?r^o0gP^Dq@A)ReNcooaEiO> z?nyUQ?tyLedxCm-GBtJ3Yi;zwq3=(^L6vz=DY~p;5;e%syQmHtoS_fw``j!y<&1Fm z8wC70da}oKe~c_^=I$M@AO?zI&5C=S;_mJBeeT|(t_vAh>RxF^BiibZXm_X5nYQ|a zp%wZca*}@3%#`@NMbC{uqx#iPeYN8LOb`nscD z<_rCk=z&i9yrLgl*L|v^J#-OvA>)c%;)rPXO^oEHgb9coWdAab7M85e+&OLkTDd8E-oR3AoC6$V^ z^l{|st%uO>S$gL-^I#HRy=zJ4YDH=1ec2ZZV~J9nXtY8ZoDT2$_7?l3(x@(atZzOt z(tTa@WP6EnHq|&--*QScaayL)%U$%yzKo+R@~<(0{nCuR-bkfs1}fbfpjuvvin4m^ zNK|I#S>|5@m(z=Lwa$jdU8@M9`q_FzJg||Gt&i6p33O4m-cD_h)7IcwQPfRa+hR4x zgQxVf6H6b)B_#(Go!8dYGe-|pwR_sr&|H0h7M1FHDp#MQYSY_ObT@r5>y{h3>91=~ zx2L|{!6&i#o_cO*YDZ%nC{dzy z%Ak%^zn9)e+tZOo_0pS1xxfAUM+gj3m`bx{)0)zbUiw%z&eitP7c}?U&2IeB;)*wc z&sFbur)|A#`(lv(BRI+cN=vKoF3NM^-+JlnVNFgYk$G# zi>a30Y`)1GhfgN}yIjw}*J=jpOW{IN>YyhE>bkF4PsKpJr4_p}P~X=CFF;q}u56xZ zle1g(^y*@K4_JkHRo4ysCd>83Abq5&jpV#0ZADgBYsHX~xftl``O+O=D zb7s@Ep(whspzL9K^SCY1##%)QOJ9_KU!Q=Wbxu{BK#%dU4V4}mrb|4=pQzIF!$265 z1x4SbCutvMQK!4~KY8zvK3sorKykKNV-jovg@KkZK#j2Bv6^cyfmK831{?_{8*IjS)S zFq6p2vQ2fwj1SMIDI@g#MHg)^`Wdja*^9pLFT^H(Skc%1g)898ZRY;N*J$S{{SQB* zjVIpB&uHn1kMT2_dE%RVO@-ggJKx7(h2M<#_c0oJ;%S{HEE*Nh+ZF||rFK3_BV%841jq#10;ws16qEevM7#>ecw8Sn3F z+(=gTBq6afcXMY-z6W#nLuXgdd-PW|e*J!t>((f}qpDU?hcS8!CmZ!mNv~j!Lf=>% zX=5|JXMO9dv4}j+6CVr=a9<`e@&B8*E4`$LZgNJtO{C1uJMq9u~TTf?mthC$ohqemqnq z?Jk|#PtZ^B#~15Qgq+KfE}E!2OvAS8Ui~Ldph^1h1k?NyRfaW$uK-)^xuT=3QDvnR zFd3W3zn9UF$$E;-o&;zFd-hG%qqUREXe*#Grm4nWHXHU2wvIqxmhkIT@6orD^%i(x zGGL0{56t8mF+~sb)piNj!~%%Az@5oPAV$BB-pJ*euD`AMpVdI@I~&uIS$bYZc^Et& z&4(V6@z6t8zvE`=iYPo$TaooQv{GII=i%gcV^RWM0q30P=WNLDpPSRf+4}2ItYz`AD@H3F1KYlYg85AEaw)Mq)^ud`gdAVD2avoX>Cvk^1n}iOp~GX#C@=; z%x>jsvq*o^r>GJddc_~{ia+KRf7~m+)hoW;E53{4 zMed59^-3u7iofI)f7L7gx>x)SulPG&@%OyqA9}?<_KFvM>hnPtV;eN09gI@8qcjB)X>+dA{PnKN{U8ZGEy`$LNYXNk&&X25h9|YA(CQIk&*r1nc3(;`~7_$oHbu- z)_T{PHM3`boD`3zSFKqZpAf$|Y3YYgyyf|b&M#hCEIqm6AOBdfYPm=JZECUfoL9V8 zpqJ!j_FAl^OP)fbrCxy_e)6{GVqM>H@yRR3{bR+GE0W^ZtVsFihaQEVb8SC-exGNo z>&s15p7`^^-w6D9<8S1LO;w{BcFDDAA09~@?UAi)(uIC_p>yT z^!`4Q5@M0$7K^0M@|6_JcuCIkmy|->cgzluWVb++Pes`Sl3mpUl57c;>~cdTIqE@4 zN_$XpXrC_06%R@J@Gwd42$Ss0Gr)U>B)8!Vu5*T@&zLF688}7Fepr%o!X>-PaJ;gX z8zJdaBPF?MjwCtGm6V3LlH@W^(uYP#a`_{YzH+`~Q}d{#uZqS7;4w+5#R;c#j3lSU zfR2%DN*6$|SV`X!D@pc`OLFbwk}f$;lI!9mo3tg89Jf@msa!6}MJptm$RtVjUnS|P z{vp}4JR`~J>z|c$&Ujh0`8i3Sp9YE2Bz@*O$&ivR$$1+jo4OYzJLe2ZcFdG?2|LkY zm!!AkOS+afB{|?NNy&H%g1##$Sw)hZ`<`UuvR~509gyt24@$E6eJtW7l8yhzk{o$N z(nnPwJu2C?9F-ihKb35%K9{8R?Vn3>WtF5evy>o zUnIHsS4nC46|ns#DdoRO`q-No><^%U6ZFJCB{}w%WMlaY=J`vKt0bM&BcJ{cPpXh}$FP)ubgih~0QYR;`AEi@jM(O0r(K?$_ zqfY1OtF!4GuTv86b20XTIwd+#H!yUjPU)JdvoX)o=`9gDxqPD(6U?EDw&1|}1D?$Fsd@6k!-Jvv?IJGy~E2X(Uf1D$i{ zXF6ql(&xH)U0>+>c6|$p>vcNwIh{?zMSM>Fiq2VW*V(1r(CJcs*EzJ^)X8aGsP84~ z-TKIKWMA2)(n;2NyU5O=c)%dbEXy@xWt*;XvM$PBR_gp^UGjahl!>2~a|)CtbD(Tf zK3Udf%$4;G^JFC?O4fxfl-Jut$IE(`C9;&TM3xg0WT_wl`{t$SuoMhe$ckm9EayBS z>xx&&`l6>~B_kP3lVv$*jVy(%ksZ>XmTl6WmG#m8l;!B>WSgAzvfK`%NB;{?_`M|C zIBt{`$A8PRd6TR!%$9A;ugOYO4(_dPmGu_FxAE&;+gFdW3>?vi!6 z2V~jlAT<0~R?MHshMc2vR8^&{tNB89Q1N3r$bdVhD{$l?U`)v(YUFFbWTg%i@>+1qUDXxCRzpy?|J9Tf!IQo(@ z@YkZ%2Wi!kReb@<^piyY(7&m#M4779|6TuPN%EFL{|^SGZd|LITNL$rj zj+;bBbkM1Sr-P`;QPtZb-bvnptYXl%-l{Vdvz8SPQjEQ7k{hPeVp*ML2z^)xT1=(|)RU$W>CEnh@s4(c@7JB}vWsKJJy zC&ch=6mPGNkdu>Wj}0VEP8P+bOw#-0iq%4(j@3e-#1tV=%Q_*DWjz;Y7&*;_%}dq` z89LVs8A{XX89R&}xq;qhY3PeWhN2hA)m{yjyM;g@umW$_5ZIB zBk#X-%K>6!71GW=>V0@n@0nhzpHi|HJaxu_RM86(6z-+ty;L8iYM)l>dk&Dl0?|j^QS!d?A`veL?ekW0>+Ut(!)k)N=XNreV5z z(KPg|Xc}BsRbX~XIgVv z102ZR32Nm#(0nH~Le6ufw^>@#mwt5uVk!M-Vn3w#vGZqG+UZP(kQ(gWzvI)qg+A^F z?`auD6Z@;d4#`GQoFUPXeqbw^=n%>capOdJ8qFD`4j`uifT?aA`3%4m@bIO@1Au$A z?{{>b`9$#m;NIj*Whj*k{it;SIHipzFK2b8+~!ZKoEhf;dfOQjFFJruJENV;B$5Zh zPI;4P`aqOt2GW{=C~pg-Jp<7%atd7=h<=4ghp1jk!4z#Yiz`MeokD8{p?BC+Iy4CC zH%%kk!I+K>ku;5^33F-PV3Zd}(TTyBd!?h} zy&6q@hM?T?7zGYNdCp_BatNepdR#~ouuw?jztCEmu!R)pir(#uXq_uY&5x%Ou8;yh zP~b2WsrPD{J{0Ad{}9q-|AWegqP^48LYjo9X`&lOEq|I8yJ6I{XK0HX>ZNDt3@i6Y zC3zUiGg8TK7|I==6VfCgW!S_$XDv<2b99rn3V5D^-7#wWI@;t8DVnqBI7?GDk?nAl zH)jiJ+Oi2hmNrdJ+9IT>*h0S!XBfOjULF{=^EI05f%>!@+UCKe#IOFc@_=ph6D#+4 zT}YFPlu48Fy0tW!uTz;PW|S*mZntFwNa{GPG zsi{Eqkc0jw1kC;)?Hdh2T5z9yGz2OBj2u)9;r}^Bs3^~=!X0IlJAFZWS-Eqy5HJZT zgDbJxTEMhwT4O}3+^^`65dx|w=~p8JYOA5?CcqWhL>pMzeu0jdP@dQ<1Wj(X5_GuS z-h4+=#d7I8n$k<1Am?796Js!gy<12&V-UA1G~Em)3D;;FOG9qbWwSb6j_V?yv1)`8 z_Sbi`eynO#LgjiIm&B&}997>Z2@7kGT+ic4sE&4Ksza%LoT{g$CHU`8`~L;KQ+ zaq4tM>Q~Q&R}w*-9HaWm83Sm81=6QE(`Ob)n>UD!;UlLGreI(2w+x|;zK}k}tDc5C zLG1=FiU|Q`38N^&4;|x1(-uDrkz%BaeqfM2hD_s;FZZFHf$C)Y@j|s!x=^Q%ruGKJ zzG#1v{h?2nKl%7$tni7n&>v&z18A>5x*{HNUFxRP)A<$9C3&mSfLp!G0@MgY+cd$j zlU|6#lebL)s+*D!stH#eDuh!X62f_h3E=`}3gM!{X;m;rD2`+!n{2~?q%@a~--pr5 z=g}YxAXh#v2C9j>cOdg(ZJ?aRVxaZ}F;Lr5Iy4ELJC>7eAW*1XK@ow-dnYjz5WJG9 zJ`jU6tfo+(WYmQ{O(!O!kK^+~ee?60`rMTM&(p>!sKsWZehN(K zy+IQtYl9G_B}0hP{4XI&+si_f>Q{u$>Lxa%k8F9Bt_5Q_M5;i>P}(6FXY3S=+jnV< zqw@vhl0AZP@tag1f(~tOk!h+r-J$Tm0-#)(f`3$dCQahMKGho!@h2>y9QA0x!MTysHSTK7H855pkkmuP1g7`6OB*H{|bM!_>+*7i19IRk2j zU8C(YFd%M}U7ms2Q~ukXS!uve0x(M&!v7GX>$!ePNtZUd+n-|e)W5{&O0sm8KAfb^ zQc~r!^k|s+pc1P;OHT!>v*c2H+8eI=7@Qo=@(5y2yJx5m$atA;)GUl!J@733dx|>C z5IIEDi?QTVSLzdimE2`0?Tc4O$w5QuNHo&ap>!)A?waLBM>J!X$Zs~% z7Ef9^83c+<5dstP~TU5V<-=(@GQ?^s4CSPY1@TLv3+6gBvqc zHV49_sMNRuLaHY6nG0deCTe^_^`e@1RnIa$NvhYjB+%ZRcBhKDVC-h1<8zsbL<5R^ zTGbmuOk$J(x{#=jm(xtNa2`08m}tX1)z45oLsWZ^?<239?*?TRG%5u^=sDew{0=gkxF)y@;}rAN_eRvz#O4Vn)` zav!0Ei=au88bEj9eDjM^pX+tQ6@9bYuaf&rLW>ucoLYl@bu+)~KF#IY6XbWcZ$0 zPuT@9b!7rAj>UG`d8yXU8JD+i$n?#?f}5@2%9UT0M!xv>77hECuxQJ_ghk6=5*AH) znNB>;;M_%wh;$oJ;!_!*t2psc|t(RJUCy;Iu<1P`-m45}^P?OHRoX_G`)$ z_G{irfeA2K=gxagmbzP*EPJ68YgT`r9{k?# zh|OZ^SHemeUs+oz>nnkK4qCB!*6@|ElKzCSlE(>aE16G-*8V5Bl?;xjgbrD>IUZN; zDW`<7vhj*G3%`{-^|CF2b9bJiYb#L}aGDv=k9(5RaqcYbTCGkH2Q?m-Md0(kY!&!K zW|XWIa$cYj3`fasJoU0=XFjEuX&oy=$^xZr6v~P((+O6F6lLy|z8agWfM5BT_hZl4 zK9p$sCD3Ke+Im`GcTg0>Ma(Z9` zU%Uh=O7g%4+8>X}o(19)Jm#)c2*T5j0n>rZ^_3{~AJjm9#bbNO&!X&y)6UiEL`pxU z8st&vxIi_^siSC93KYs2MUATwP}55gBZ`q>g;;-l)oA%Ow>eQEmRNMBvg;ybVv0#PLGn4c%4u^bCXa# zdz0v&l+9I_qqfk(bakTAv890yFHw!u{wzXG+-r36S+Wxq{cm+d?=Cb++9rz3bfLjC*$_n{>o3kIXXc;D}-nIkPnQsacxMB3{H>pnsyfqYbsaBo@x{*N6IBtavN686?gIqhU+;pM{QCCs+v zbd8mzY3-OjGs^L)1#rzOx0W~xHO2UH6l&x;jY9#-q>q_*AU1wXt(%~4?8kz;w;r56 z7M>A#gtos7&v2=r&zMJaekwd8uTpqMbtNs#M0w`t!ZTc|glBYA2`9+;!rBR>z8vQ2Zr#0y(*w*0EsX{1xrnh_K^yLfEbA#JzS4J1Ojzd{Wr0^rSTk z%x(=Qh28WuckJd^Bkbm{l`*>o)d;(V)>w03c1x@gcFXQj!|Ya4BkWeL@nLqWtPys@ zc^04Z%x=!uH*ou&5;8Emd7lz?GoP{^kJ&Bql(1XsDZzo+E&r6TTh%FHw=S)Y+0Fa3 zu$%cbt$P)A>-?Jbz6$%)ear1;NUIaL#gXTFoLrUE(X?z-r=I2JGuStX>Hzv^z50OC z(a=D<^hQr5{2aCxRmM>=(%EmRW0g`6>)%o*iM2hfnT~A6Vo=oFK(D@`PNfEcKzd*HD;; z>-N_$72Ddh&iT9Dfu7t2&CX!;Z+~HPz9!0To?8(#_Y@iH5>!qCq+Ji#3j> zxEydZx6{fTbrgQtbj549k_kCsvS9(Wyq%8aVC1-;=q6GnsH1^)98!I4!vT8HFSK&2 zI#X%>1Hyi&PEhRs#9F^qoh0i$=-N&Qntce`C3~KuFHtS0`O&If>L{w%h5_9s(D7~X z;=+k^a~n9<2ArcEr9dQ(u+(+nyF=_>2gR>dhxRFl^!}lu$fBcbuQM)aCz~InKKT$K zW#%~={*mgd)I5BSUd>lW%Ff}mCKr+?M$q0|z*IULEq2390g>lu_HK2Op)gV~%%B(Q zaf>7Fb?~#FLn~j0G)?o)(G#z!BPsGMwv%pA=u!r=nI8p{7mOpRxD1M=BX_tAV@c7p zb~}27#hjy|hoNc6LTY6N`laXS`VuG=xdY6LmQu_Pl!mN2M}HhvXUGM~)VKo|Rn4o< z(f*BWGzYLvNC6V%kTm;Q0LKW+KhdEa1Eu_v%JQ&(2w5vcPoSx*)bWPG=R~%abQ9DO z4o=UDtOTTNanexp0R~USO@KGBJ~d=e{To=H^jUQ44LE~iwrCtcy79)r4(xtx9{v)s zUD&D4m1}p=!JSwRJ3nC-ohT<9rBSRdz7B*6ebp$&9oDUjR?uplG^HnKaKBjv6@TEz-nCO6Xl62P4S0{68h zae~kF29!+s0B!MJbHrO1JuHaUy@lJNB|(j1cJuR2+_LKPHk5IiN;BVvY|Yae*=(7h zM1?le6I<08O45UkVya|MhuD}ZO4bSxJK-XHu5_+!)FU2q9DS(NJMQM?VJ zMXzt9KemBm#tUFw3c~x9M(T?xAZInwt}2|4M{W{`=WL?I?*MU+&9wa;h@7!SAg+In zA@0Wy+m)2p8ii+PY=dC8J-ZG$=GjU#HPUn2F--pJjoh`B+&3EODl3UCfZ*M}t?1us zqy;-rockUmgmWuh`+?#PSTg7UaJ}u_4WaG*CZZ2ISLpf}VBhRiQTd*R`|x;?!4YuJCM zI!B2-+eq*4geg+~;HH?MG<7x7=v_FotaUuktT0x|>vNuV?SgvkgU{2qjBs;3&v3^i zeu(xK(}>SON3Yg|x5)UY)%NJXt{z4!TO<2QG2cSb{S-mpE|1LMA82QSb+BhlB#YkTrn7 zLN-+ii-$^V?P@Q?RoW6L%+{`grRUk&H9<~YPTLPbsFuX@+`DCICAojd=HwISg>!ps z0@3ZT)!p7LXO>YJo^es^51;4G zEk}M#u7|-c?C5#n+m2O``?hbFAjf=L4m(9R4`a0{`ueV>V~*Q0Tw%;K_AThB3`p)@s|7mjP+d|o)NQ;TSRm*Xb2 zpBIi>_uF~lxLt#r7|aut#34<>abt~5!g0OFGzrH|^=}f6TQISSJFZd^*F+2Q5i#_O z@hj|z(cX*cPz7L!O#r)mb*!Afl-!R(k@lq&aTG9GmNkjs?7zH;2WPo9ksOY}bF)@r zm_67Rq+#s{N}^TA;I!3G(Y|Bgmy+DXoOT9TKE-*8J_Svg=LS8~WbL`x&opt*RXRYh zz^r6F3nk#XN+AdynVnOcL}X?JkIYFRSY%c*L2&P_1HrvF^q)<_d)cix`8jCKyf^>( zChomT%K9b|oSV~|L~!nU0TQr%jK_-rfCXo_w>hv{aL)X1lL*c^r5s(&fn&>1%z|^v z;U*EBosWPu3(h6~6Ijd1U(n7fEQd|U1=P})bh8T3WPOE}?*Qs{JfOv(4mru7)}nLz zN$AA(9oeTLS-1Zx&B*cSobYv%h|WddG>Pb3@LiMe;KU|Ke%phcF2K|*Iu~4lh%7qW zw*g5Oox^?vwzs2m)pf|jf^u{_lww5Z4fJ5qIp`;h%A&LV&%$ojUTpc9V?9F&`UNh+ z!f!$sT!e++Bv4K=AWu?EnFJa>Vn9DoKnX&1EE00OaLlH&dR1>wi) zx(i~HQMFzOSxfznsUwu+7cd^&*^arh$BU5S7`2- z{|F{pC{Fng#%1nX2ZB3v@+NR%C0QW2LwADUTMb4mO2;;U9Sj;=vIVD9+Pp{|Ov$x4 zLx|3%O;@qGXx>aGYB5{QcuJ#IooT4tD%$2zzcD6fdi)!;uk62#R(*pdD1_+kZxFB& zaxqLBrh35ZH0lhl8H--0hFp)C7_P+i4BDE|XoC^`KA zA63aYsA1=1uNv&%7jP5_=$gJ)9p%dR>Du=Yr|5lJ*nl+d11^?Q_`wD0^)uEtej2NO zNPW%$lfn-v@Enu~|A^*afQJ>}QIT_4eNqo!pfMe|zN`6`-|%(4sG1Dvg8h;a_c{(`R9RFLY08g=?ggZFMzS)3vzElMe}hE zqmuI_ocmX77(Bib0w;b2um6p;JRxLrsS&cZ;coBQ-)>)fo+2(>^Qn7yVPn((nT-sTx zZw5x~XGP~YntDzhC%c@Z;7h2EY@}6J5EH%6(~(Osf983*d372gXZENkaBS%!kE1!{`-E|*+#%80AAwSkj`sWrbjoEqja13hU!>vR;wDEM zLRSSc=P%=7fN~pJbq$`C;Xp^O0Uozr7wM_9*hg9%K{O$zIrhFtXX_9gbNgJRleGv^ zO(3Rx2WJa#qG|2GsLP2O+t@a&-$m+G4`+*HvC6xD54m#s3%MHl3%O#Qg{h^VA(=Kei#sqk(}z=82RgfWQY%tL8et_?05Tk|P;Ywa z7Z%TqbmkWf5oJQFCiXPL7$K&tnrZK^*bS>z*r^*bb(|YGA5Q$$>8B#;}S3-f(I|>*= z&x*2Y@|2B(<@N@l2Ts7a9@*z;i!HilT@=l7=#*?6FW3G+wsue_;3qMX`V+0S!$=*! z(m|FM*;A_>G>LW~2YYBz?m&U|(4^CW7TX(VDs=fHip%9yT|+D*=~Db5%mG7wAT^(B(K%$NxD^pPG$W3SQ9$N`8gvdmAS@v}9@O$kf<^ zQ_he+PykP8%t(b{Ewp+?OI z8uyA1sJ<@~|1kA;LK=RWW;%h9bFEM#wN|K6QcK5Jeb{-r=>#>RE`UMzu2jZivaX*I z541MZ-hLRq@)FheL+h5GsDFR7uDylU{jumK>1bbn$dMycYk$b6+ED)i@Yi;GS~vg< z@Cxom{Fa_v)So_MY3%@#osB+TZO+ZymUv4_{0r-2VK1HdBUgaG>VY)Z8GKp>(@tkh z+~&c}v}?K1*qhyBb#oD&qiIeu?v94LH1mhk`?;a69Di|Iy-GJ6)iFvG>Tj#2=!Z1Z z`hG?uUX*I4cl#N~%9U>9FbK*88EM)ejEM(7Hw`id%L(_5ZER9aWc80J}!=)aYcD$JRNjJdF~Rr$jVcf3Q<#* zT8Ub;w1=n-sOuqWyH>Bk*NpnxvdTHjDA)~#jaoq~-7r%AO4{xQNiiKxyJ5tf400a^ zNu6J&g~K3GN+xX|hISTwQG1wirXloIF*x21VRs}#{IF@qvz~L^(WY(-ZEy#V&Kx0i z2i)(r(al?XNFBTNE~%5XdX;>q0AN&ep=+A4W85ZWuFVxPdu*pb56Il{Hm&i%c(^Nj z!~-(Nen7W8jDd!lL)}C58*CgScO0Tso|t2Gr5JK5f-BP7VmW@)-In`e&_{QP6{*#0 zV1}ap4wxMu3BgLrg<#SVGL3*>_FvNC5fIGrTiQ1Qf+c=O*G2%$ih4461E{P9itz@R z+2`*8(_pzE%7BBn5kFA>J@p?6Rsnb>luac6OIE@sUFsox9_o5{La|n_315KvJHkg@ z#%JH)2`*P?`zQ#N&`QTgG2uH&9*q$b^%OB0)5Y74c8-Sd_<@Z2(P&qLg+WDqf)mYG zQC`@Owx|dRIsGsFe?vmb0J?~NcmU@Tec}l-AiZsdf`Ov577}Vv*F%#QtzKwiXwb6h z+TR13tYamhrn&9>w%`UOw?<#cA);Yta8CJI$?odv|s_X zV5IOT$>eLCE|;Xy8ee0K9KMlG_yVh@tV^`NzY%vxH(jEu{f#4)yzEOfV1RLkoRC8& z{J`fFM_msEOSF1T!9vvEQ82ndD416$6wKXAYbQX#rjO{@1SlB#Ik``SDGI)zg%csY z{g;=h*I=Ws?C~X?mYeFz)i~Oi{HMtNUtmYx67?3k;%aAejAWLoh%HpQuS6#)xj|(bv}uSpifh;GSJ;=3F3;8K9P9+H)6^_pZwsJ|mw>|!BV-7+B=4*6$30LgH&y5#{# z=KV5VdjO8p^a=%sLNfEe#b8CkaSH!KdqV+l=4MfxOufe$#~a$Wh^(2rk5}7kBKv>2 zPc=SB{2-8T-=^u;#)xkHyh-%d{3eR-(l1e~*Yt};J=d?oUUi_x>F^pnAMEfDoS_NN z1wRDkn)cC#hoD?FelhMLcum+R@R|r?pbqbDgrQy7G1?dgdAvWrOm^dplMFdkLIf9z z4>OK7BpnyoQ1Ttm9tD5OI83hAM2}-cx9GXmJw&fUT@TYVX!V-tHK^}44V%(j_?A;b z_~x(a=1d4*^*v2{7{X`Ypq&rHXPi2y@nKjd^_T9kxXMkyrQg!Px^@=b)DChT~xe<^o%8m9# z0M=snA82?On~cNBG#j`Uds577;F{w&)aXc zIm%6VM{F*Z)+8TV%+jFyX!~3&q0RTv<+->H=$J&V^Ncvf48(gFMn5HSGWe}9j>73n z**v3C;om`F;GZzG|qK9mI)M&3{ip)UrV7WBp_@nO`xMs>gW;lDql)pos6GfXI#ipPj ziVi+%^f6RCBF3#G-(s8;bv` zLJmpCOB?_{XoCR1W&;Js0Q}+?IoM;Blnf5^SS9jb;FJcxD|&_cEI{x|!NJP{Op*32 zLatCc@Q87o(v^dD&tt^mw{h~5hc^mhfpF9tqER?&G=@Jho4AYC#=`z_ct(|>UHGPk zHX}IN_5~W+sUW!5)qvn$*9L-nUC>*a*YP_LC2vviLd>F$w`k=;KoPc=_OLYLAk{B~ z;c?sBeG$}4`QQh-o{q{a_) zc+tg-=MUrA=J5oz#sj3Hn(mHMpE6o>wG^`$_+*?B_*9?K@L>eU$NVkF$5%YFT8P~2 zwUGP*_lXIL<@+CK|5|9@&V68pQrhtY9Zom;DsI17t6%gRQ{PX{>SUVYs|vp}EwLTA zDHKe&DHN=@37_8p=eKnIKsz=Vm&(cZ6tfKT&g{@aQ(iPqkmDTb#4_VVrO>H`_P>aI zV&uRU8aE%OO}PUp;t6)rGLUvI2lLK>bYeNWCJt&5rmXqu(dDPL2~_?(4SGhKKuYO44fhrhT&uA4Tq{F)y5La7X3#@Q(k4yv zl1)N#q+D|6SMR{DWWU-%iDWymiQ+$FkyHBMd= z_6s#!ikTWFa+(KUaz4O>hMOK>0{bW(2Q^u}-`8Z#cwhKPX9=}FgK${>nJ_?Vm1cmV z84_171XM zdIq7c@>kmSoN<~`{u@Mz!BtjXC-q4KB5}V{FiV4O(yBCgP3|r5USOQ1#Obflq6LV5 z4R%-f{1Xd;++v_r&tw0Q;&g?F0;L=TUsf5x1DRXDD`HvA0>J})GYB3Hr2c4(hlAzF z{&Z~}ysf-HxxZixr1lBeWuTHp7bR%`XP`yG7UY;G;8Q$!l>p%=dH5CX2r|BxxGEhn zwbMdn>2O&*>3A(2=9T=x=)d5O^l$>EsKjkgdi+Rbb{dC8g(CD z3BWw444~~BjLQ`LgI8$5GOUml(<%5x4BHU~sg@xU1kIv-F9L$*IpF$FYyjqJ2$(@| z1hPQzjYStLVNXX#&C?J_2Eh@im?sc0M+pSjoe3o=N`s&Q1UP6AL_eZIP_j@!&=jXZ z5WPx3khq3!z61#H1r48n?R#xyC%BJ4h;@Qa5z#ya5!3634C1c##t?069$N&#|w!bsPJx0r8e@D$wQ-lCMq zts-C)>+v%K_;*jhh_;~imTC|@dbEIG zuqXkZts;IFfVdMsn^`fNkX{;7Gl)C5#3IL+l+rP+d`(xH$F_dik4W14V93Dn+c%tGpcq&0~c-$6i z@C1P1@MMDE%S#7{JMj1~(YU68;9MDT2cIJ3I6n4IYWVm+rQuVQrr}eb-YRxI2`_>f z_BXP9hQKE_L&GNz1PeJz?!Q{a7AWl{;RV()C-r3wszMMPD*H?b!=_i-E3JGNq~zvl zP(|(3pvuhGpsFd*ph|s5Q>p?4SBeoFDv!MyRM{XnR4pL5C+XkSpo#*)p{fAEpxTy* zyO2d1&oB_2CnN3vm5Lk(s`dj7D5+EfD)oOHsHx=fiqT;Ih0t3>ASJvS-Tni}@TStO zw=uaAztSKp1aT)86`W`lu_*IotB6GzH5ynYAUIggr!=rKPq&I#6yB_XWq(-%E2u>S zE2B*V%X~vqECmEtj1e5HS`a)&hyJ92l?Q@@RSJUpmHp4HV&BNF&Xg47o+^WnSA*D5 zhOKUBhtL;~EU$y)BCM!pe9fx}3uwk)t@LaW7EpUn+J^$Ub1b=*vpw2-*rMe6 z&`g#IVHwLfTFWxY$QT;NUFAV4gQmWK??;s2LO8%eJKsYvuO3e)Seoxow^-^wfqeEM zjm8~_eHa1X!8`sj_*Coz)09BE`LWT@)*0{Wq})%p&_GEFzDiFV!6kPF3NxnAs{Od+ z$eSVttfo2T#t~GpA4e1cAy?^-BUmolS*{MbF`r;rZF_)B#fUiJp%hV!{ZmHhRhqKU zIE>0yt1kRGIz^g(m0p!iCK>5r+2q60tFj4a0$1siuh@zAEDAgfVXNlSi33RUqG>P7 zr>~*lgDl0>d^wczc#$FGBbUC&z`?zw4BA_cePKlg9)@R1XVOBJnqQ$!EUkEjjL zp|6sfdsR%O8W7w&+CXsc2zveM9q*6}U#C@NxOSJe)Alm>dg}J8^jrmY6gAt0(VHq@ z61-Q-?d)_Ec6Q6NwzFM64nb1$Fv?K~;Fy1vo?=83h+T|G*?pBxG9q`+Rr>2F+$#Sq zVeGhL;9T-HH?|$VWGa=sgFeR)V2kz&YvV(sc=PVvtJL>X<48lpyFJVu_bCjVTBMmf zo8?^I9Ui6R zmi<^*I_gtlX}s&jEgkTquyoyz!qUmtgr(iC3rnY77nXMVSy;OHXJP5o4q<5=XmU#z zbP7wC{w^$C+9fPq{HJE=s$0U+O}8{lr~M@?jSpIq=@VSPT9h_n=u8mY&;=m4p*ukE z%SZm6K3>A(QJ@qAivqI6hSpX<>r9(A8d{DS!z`_+wr%tr%W+fJ+O}CwX=ZAR9R(kS zcUC&kDwgK#QyYExF&Hs3D@py@=#P&vf0><=oN4DVICjE7 zT6qK$omn{zAH(_-b2?{`7*U(k%*e83Fx@loAkM zmce&B@lBnt0FK_PjV2#v4mG-sP96Y}KDLeCWhDs@0j`6Lc$BL@R?$bd(Zl6%)I1P? z06VA0(6}7ewgn)@y^oTh$J=NTBb*kt(W{Io0PzVUsus1;_4mQBW-(VB?{qBTI!{oV zm!WY9JilQ%Qy7;hiEZ>(2`-f!SJ3ez0IhHZ(-5ciD}_~KpVX{c0)kt$2E_R{&}5Zn zR36*2kmFWu2EnZw`;@S1$y3%=jY_t*s)^hOj$x}&!# zQ1`MhsU=G@Y29Ycq(!8eH2Z*N((I#}NiD}TlU9M?CQbQNGieP7ZqmfhHIoKaX(p`! z!A;ung=W&OYR#lhCp42fozhHde_EK-<7>^N0bdJ~*5V!qGige#Flpwunn{~LaFcd{ z;1e~xPS|wY*SNR_%`NKmov^4O^E-i^wpurRN2|WZYTeRAd%wmc!uPQ*veZc-*IJ|{ zxO2hM+`hE27UNr-sEnm8PSncMx_;#P4brUsH1iv@s~kidkT(_aEu0{YKB; z1-SJp>-g*>K4x*xic$;AozrC^P=E7Ts8-& zw5ARc)QzRREUoaPi!4o=Nv_`^jgF?dEDd^$Hhu?*YagRBmf|Bztt?GjK(6&jEwMDS zp7o2P4agh9<9jGy4&|HT=^|?ywuJhhMOu(R)6SxcWf`qSYVcV8e<^&F z6MHD{hL^ir5@}ikl&@XEmB)(3o~m2pGL$}gBG?S%CZ_-+p zMitOrmfF8X_2@fG8ZkXnr*L)=R9a@7bxf5spER8Ip(@p3Sx{n+#04D$a z-7xjLaIcSq6xLxtvTxeA?V zfw!?|p{_u$lD;&Jr4>H3mZkZDRCW!^yg!VWF_~Jg00Xxma&1Lg8$>f%T6sUMWoc?K z?QKP$;%U@+-Dt9n1%BBNkZU_=7LvR}X=XckRf5iXkk(#BpO)#g_bU42gi$N2O8`(A zGsv|KD{byf2#+9STZzKrnY6YI9l{@`y(|p~r}{Q*6Pm*{4TEM04V4lQVkZ$nZ~q8) ziHf57A29~L-q!ybQu893$x@eRX#-0;{>5}eV0ww^XR^(KuE{Sm9Zk0EV-sp7)6-B5j;U+EiKz~?HZipkv+xvcJ6Pkhw@}w)>kUmpwlJ0b zY-2&=^F2@-U%bm(qG*5LgHq#^ha21_lc$@Lec&3NMX7qru#p$*6zn$L(~ zuu65{bG=}wQH^;*I$w1E2VQ;>fb;cks8!}aI9zab1YoflPqH^su)6uThmwJ;R&y@paQ2p)!`7~HqFtmn9Yo$>8F{^XHD@@5wBzndeYDgI) z`rLz&dly^I&DTX7Vt^EwMN=&23?nmi4;f1vx`2_{M^ybCMrmlLw}^Tz3}yLV7h$Lw z1a~;e@49ffND$%)db}tlBf~w;dHi+ZaarR9BP|LwkEeyV;BgIswEY&e!c)hmSsJ~N z9R5OTd4dAlJ!XQKVnMbGx_)q5=$HK9VDbm&f)9)%0_NK%#{ehjj!0t))^?@p=5n37ny{s#ro2eL;&$dq1@HUd0s0-e48e*?IL94f#4yd6a;q@`)As%b}lK%aa^iF za6busR^Y3}jJ#**$N>0Bz&g4)fT6L0{G3_3n^q!KYWAVu5EBkV*!gD4e$ly#;sRc9h~VzrpAcb(A(DRXUHtC)nwT z6F_jEXaK?YG#;PROD^z<=xQo+fwq_}Ke5#OEt!U}d^;^hs-)lI+T+I2U+6i+G*&4G z0c~-phixxE8L0uWV4%rp#{x*A{s#SkI7ydZF(iv70t1b34R5ImajLzH&pxSNCxx*^=8V$coi4Xz75(C!X5 z$r(m#-2qUv7ae42$rNfuYKVMTG_R!#o~9wRT`@WckLl1V@I-~D<}rq>aM8Ghrh1r$ zQ+~NoFPtZImZ-2=a`IfXbw4eAkD%@jalk3k5+m>fbb~V!_tyRsh*YBMU#Uk z1nP_ttODo-Pt!1bgv8i~yHMu>T8nzc?QsDmcOn1B@q6>=j4up3cp*)}k3x81x~0WY zj2EU`M}h`V_)-CnQVD{4lKpZD9sy5^O`?RZx6s~fam!7n3JftaEf?`_!gkA2#opfZzbloECV^Jb-S z*tRi{vFZdlj4@4K*DDgc7wf({U8FAI4*fDd%bCSTvF@&<2)PUZgUXCO6YhV*xmx9}4!t zQJ{2%R{CI&t~T2417RY6q()Yrbd4Ow!NP9sf_Vb%-lV$O0D@?I7H*trltZCbqsMEB zzp#(5je|}pKhg1VU{{Hc!=bwzic5D3^7$RK7^$JHL$K3R{9?S-RbfG&(qHMg1#QiE zAIR6_qsydti)jFb`kLHKwVk4U0S4y(wAcUG;RL(>kN&;8o_2m}G#RS2d_Mb~q@n%U zTY{nZ3%V(qRq7}>9S}MBne3ISKW?xaiNh!kk}Fadw;pn+lf%1cr61IH`crglpw)h+ z(Nx3wmHc^w&iWxzJKefLy~cw`2QhiPX{u5U;;9KHPbKs(%x8a8RfE7gJOio8A6?s! zyNY5tLn7A+CU+%I`svQ^_@qg+YJ$m&y~n@Z9}7;J?x#C_4SBksc;Lhm`9G7YlLdot z*@}T#<_sJPWYM%#qJ1mybZiC2)|u(lc++4921yqF!WFtW5vVudZ1X-y(xF%}s#OG| zaQ(fElv=$I>o%(ny+26NLH@_O}v-%*3#(W*Oc)3ELi1&)8CtC@~YvWCC6 z27hl2{@zxMYI_St;eGC9q}2Ag8~#2T{Czd}`&zL|>nm7w^u3oA^gA$_<9}*0!yl*D z9RGe+{k{9~{=ol*AddfmAddg3AclW`4gdaDJ*xZj9&+da4gUc>@E@Sz@2uhPY}FON z-XidK?#BN>@NN7D_P~FThW{X|?&d*4*MdQRqpO(?OtHp)u!jF&4gbMbjA{o9M&T~^ zGE!_5|Iw)o|DhWGL#_II59R%V|LSQR z|J~C#{zs=V{M|JC-K=_4yYU|EQ9&L>s)zN!f0%~9yN18JRo66pC4>9FdpG{OLvQ0h zya)as8vY(u-OV0C*8-2f(bY`5AGF5bQ^Vg=!{5`2QLU$76z+8|Bc;~sZv4G8{6}c` zkFa8uHbSuK7;!Hv;J^7Hj{kv&82%$Q{6|{#_a4dn1ONCij{oK`j{ku$hW{uH|4~*w z@I7`8V(4fM|It10AFbi9YWU-`2)BR8Elm|&JJfFcH_yC{zp)4YCJld+Rd=&V=vrX< z8(qz``C)7P$7uME(eNK*#i(|SU=(h?myuFyz8inDhCd!{CV!{4_D z{=ORiej5IMR$bZGXu1FUb>sg+TVU9Ka6EyrM zX!uXCVpKapFbbb|FC(RP;@$X9)bPJg!~Z@jR%!PMRvq`<%L@3fp2zXuJdfdz*Ohqu zpJdhFdlK&t{HI27{8vYD{5MB2`~x-o1Fd>gY5fLx^@J0NWk1_mlFNWj)fK`9*2Y7$r z?;FGMkB{N_zYxRl57qDwwd#Q%4-@!5sNw%$5Bwk0@Sm>XKi#Tp+H}#iV|q9K@v*n@ zf2arkVH*BnR^82ELf3+@ztPo9@sC^MKSRSGHWXsaI8(Y%Ko`k03Q zV?FSHOv67$!#~EVYg&xx+7Z)@|J20W_%G;zKhAPl_zI7;>TZq|x)#L#jjm>zy22X& z$2I&P*YJPbiV@!L7Wgl`myuGt@NWDUYWOeG@Ly!bDs7Qq)v@SaR>0r)36B4qCm8YA1y zx^^UVwN4!+*Jk|8grvwaW#g@Wgu= zDYc1r{v)^;x=lj~d$M(lP zeV%j9bI$wR``-6vw|j@{_3tuV)PFGQKiFoz`(S-O)&K5rz5Xqu^!j&+67`Qj{UdB< z6w*iS>epZTr+)FT2!%uJ>OTbaABy@9wV4`Ae@P>zT8A3-ZyEih{=@9*PyfF_fBZ+< zO!tc9V@;3zk7M=HT8^}>|8UfQIO;##CXr=0CklvqI+3F#O0Itt>OTVYA7PU!b_A!g zj(9p1)xY6rz5eY+i~5g5{YTo&cc-u8rIJwn%SP+)||0vXdl+BF7QThy% z-)Pi-v|as2qy90de~iu4*chH_jWO!qaO{)%kFl#ieWsjV|FJgHy~gsfrjPxPWA)M+ zjOamVk!2hw3W$9=k)tJ6u751*KOXfTZ<8u^Jg2gbe>xS_-(kF7|CZxL z{Z-UowVCg(>hr1oC&ugbcbK5pzvTo`|2Wh?&SpkooIbnEG@gN6S>X{!>wZdQXfYs@EC)!MnP2{Q8M5F$9 zr#z|uEW7&C8+i1`|7@G-UbFdF(`Wz3v3hBDr`pzk4(d<;8%3}G9GgUzIh-gU>FGp{ zmL$3UNvQu^)PJr`s@S=l$~yPyR8;@61ik(a(?$K~qyF=4=DW|==TrSRP1oyRHeIj3 z!wgY>dRvm%d}XrD4EmH5e*Ry8`Y*7n{{qy1A?m--W@;>bMzsF?ztE_E*~};P*X-(_ zg8HY}O!rFRV@*%_k7K1TF-x?q|02|X5$eClCXt2yaDw(xFJST0i5xA9<@zs1{g


&>F3iV%QlPY!^h!mU1!vPpZ28wKik!xzVc14f2PfJuS`DH^vwS_R{Hn<6x;f*NB!5M z{_AZLS=Mu+fDKP4a%Rf@--!Bev`H09p9LUJCF{ngQ&IglE!OLQVzH?ICe(kE z&3yMw`h2SY#3g$DH!acYe`1NK|7O&Gv(1dc&H4D&I}Sn1#Ym)X{TJL)`BeYmEA;xW zSfST{-wILxT+~0;W(Iv)mDs$=Z#U|{+phlfEq409zwJT&_t;F0-NRF@^mTSLNbGOr zllt$qtA8HqpJy}OE02#gJ?}q`mHz!d-M0SwQ2%|X|2~^UmVKNkVE@yJ94-6h`tL{m z51{@BY*Nwps`KOjz|*Pd_~x$G>%VEWsQ*FK|Der$_k;R;s(VL>)M&TiShWKLzZ0nc z3A_5!o1pc_|4G#Uq|MaWlRVXW(y0H$jZf--%C7zv)Zbz=-OIwqnr``zW2Jxp&$6xm zY1IET>VMiMk>xZe3OMt0B1g*^x&CKR|Ffw7S({X`XE~Mi?9-{J{=+xx^`E<0)c+jn zf6ivU`#F6+)xXOYz5c_u==GnwMb!U1>VMv5M&WsVhRN>&>VLtm{ufaH64bxMW@>B+ zPo-}Z#PiSatxxKI(XRfNQ2$Fd)4eY7v8G@8k7K2O|KDa?|I4WVWz_$&O(OaVCw~4f zeL9h&rBtqeDe7N_`j^?HqVJdC=by5tQ&IgxbM*R8%n|j!iuzx*neTp8pHKB~w?nUg z=nlR96L*OEm!tmWHZuy#^%*9=-%$VG?CSp;>VFOOzh*Nv_8L#MUNh<+y6Z{(uiMqX z0`;%3neJ7=$C_U8AID1n{-0}G{~M_P4b=aJO(M$;P84wS=|ql}n{xecqW-r~|64Yx zVsCLO>#e6#QT@B`(d$2akEs9esQ>Ra^WA^f=TrS#?$ztxeXm~s;d@2>Z=?RVZDthS z)@Ri9yTdDHYAf1%wsy?Bb5EPovrS{I_W@7mx`pV>)$WSUpsIV~lMEYcS=6cP$^R4f zsp525Rd(sT?%JmFxyzkMmrtGlrW1OSF8wYakE_;lzvr8dDfevCq~EhmDv;95MA>n7Z{+lZ6ZHiL`RHiKg-b^f~%p(h)Owd(2WSurEi=DkXekqht7H`3YM0ge?kQat#d+yz#Q!d(#a7DneUePW0BqqU0OTF2w`royT|Jk?k0a#Fla`M!r! zgBt2r!Z>d2B;KXyS-U;G!7+EacK$fMQ`oZSzBVVE-c#x(z7Mw1-uv{CI<()&B6`RM zv)a^2r5vdQ{lhx*3F$y>@y$P(^d|Qr&)4hb?B!+j?~!j-r!%cw`Xt{8%IB4LpFim( zZ7zMLV_=@P=Y*%HquV~J(M0if$y1(AT2?guIalmH&Qz`4y(Es2775s|bv#M$uk$&e z4LV8hcnv(D@3gs=b&@I@e?Z$QdIR&do1*nTBy!V7f>O#lsk9NN!~ZTqUw(2}8+6L^ zb(432Na|U~l?vi^1PMz|QNo}j+Ram9IeHmup|`K*7izsMo}P81^Mxhe*?rmtQW@9>Qf zkwA)Mou=pRoa09BmZvCpU=inDc!pAE6lwL&P->?WT1RRf^H132qW$NIh@MM~uYXe8 zd4|fAeiBK}iv69`>Yb$|L8r8i)H*h?AW7B>9!}4SH}N;J@D?KQ2%`JRG3E>kQ|L%v zm5^~p^DOafRY!acMw7GmwY@>~(Y0~e^ks`dq`}?kt8Fsr2YL|k9a>vFmzL6BDbOS> za3qZjEaq8t+EWFR2sEjsmL|H&N&n7_r~W4Ac)3jaIpG{8S_lOMF|m$#fV-Z*&z}q< z?(bUSZ!~*r4#l3Y)(M~=i>On4xG3S5wSI`l2|`w;Zfm**VWw zYem!1)6?*Inv~U@zP?_ZN%Up3G{ke^5A+FwZY7@1THJY0_h-esz)LQ3`F;4@cBez5 zFW?+oLg#i`nepK0{vw?cqBcHPwDTqO*et!KwYccns!jfN9^y@z^#A-CxENn)5=;RL z`dzhl-_YL|rUiO9Ye^UBNOI^46fV-6<_m6UJ4IW3Lpv|piW}NP(N@!IsY}$-hmv&^ zEq&71_oDTXG8SKysjqS zO6`kMdRKY0-nP=xR?#N|xmf5!P%E`PrL<;oCFhOTKi=5Ed3*CR&+g5()^6)rOZAU$ zNz1q>foOx!_C_0nb}rhrX!oPNfc62}22(hn2ih)Ze?Z$8?O<+IWds7TXs4i^gLX06 zRcJS%J%IK!+UsZ^qII6i8+i$BOSEsH?W(t`i}Ec31JRB{I|uC|v@6lBN1KB-AMF{m zH_$px;|(-N`!3qS!^s<`hDB5)DyU9`2Q^MbFSZI8Aa+P-LG(9TA?25m0dlW2?4UPAlZ^p>(Ks+_8!_7=kmn&&<3Mb(f)+?AleGF_2=Os#(Y4?o`9z$D&w$UP< z=YuvFZQLT9|LF)6puL5*!D61+4s8##qtPx#y9ezRw6&M;JWsS=pp8Pi0Bz0^oc|XP zc#O7XDktzm8;&*+Z5CP!+G@0}OL?9z+Ay>UXfx3kp|z^`;pJsK@qM&?(I%i>kM<rYcoXany#5#sC_eC8!Orm)3tk|{U%)-)R0>GqsJ?v9ha_s|9sm~ z>al&ium$aTv}I^3(B4LSA8idr0WNK=11-0AFZ0~mVtem0&x-o0v*W9@ zSr?@VS|7AQXj6=SCyc9wwvK3@ybynKz`b{Ie5nx!AE^ zXjq8y&ozh0$bLh^6z#f0)PNDnvg;1Dl+4}wEXyvfjcRUIw>(d0Uat1JYW6qfE!8yD z+__Q4;t7;1ZHc&zUnFjeQ?%=<`EBRC0Vk3G3HCbYw)dvZvC)NlA!{rFhs833DmW>bdg6Tj zw&)L$vQl3pU;jCWZWU8MWy9|d(MtC3lrU3|ry+hw#0y2dM33j{d9vxdcqW-Y|F$AQ zES_B{Zj<$%bp19#A6ujUTt&BHg|oLQ)5Y7Asa%g2BYsE3ABcFeK8rpU^X?>b$Ci1M zMApi9ahs_hWRf0<*KboM#%ckR%^eyP?G|;(&lk4^2ehQg=H{lv1N6zv=C>M@Pt!Lx zRZlcsyEEC`?5ku-rI;c^l(}~uVw8-#v~HRn3RO1Tbr?8Q*(E}8cSWIcXN#FtS4C~J z>6Q+I9!Tf!I*f=8jfz%E#mK5zT5!C%W#g*Vbl*BDS!tr?mW^U!+%j!myt(Id*0uWG zk)Yq76}PnNc=J}5y!lhaO3yBCF(=STNen1c8gd6(6^!afjS@KEEcdGfVx;dK8{4{OcRC6;^`e`j? zs@bha`aP8f<;>I)E^$$9ztRmGRM7j9~tx$ZP#yKg8 z2PvWtnE59~)2k+m1?hh)*Pmv7y{=`kzF_=MTBm8|W=)Gz;v8uHr9UZE`6E$~(v9La zZ<`i5&D`pv;-5tNdDRY7(18QO`wWX3p;-TP7#7w~$*QI~H8h8k-_uu4%h!>nFBqSy zZ{D&{J3Y<(idWGbeWB`V+EPstcTEu?eW%O*qOj$to~5!%b4xIP=#suiA61mAH|cw| zs08z3Q_@+j!E|%e2B{bIhstSjTX0(IFx}kx*{pN1wAtH_XkUqG+Mwy?J|EUx6pyy5 z3lpe-1BXT{H*4q-5v5es(3pfvqA#voq{uH5x4HVyxkcjVM2miVN^3B~9P&d-nmDvn zdd_l)92gcdbl7NR=3~l{Uo?*5#XIzeMsXH3;*N^$H$qwa*de@MjFKfrWi1rBk`~hT z^us+Of+?B^rq9(1W|&*PQZq;F{idEXS#;zkiQAN=;kjwiRNYv5@(B8+#GRR zG)pT^H2?5PO^L`?T|C|)gbF=y=m6!!WD`9loe@th1NucPXD6E?`VCboL^L%|3@+NM zZ$ZB;)FbqKJ9d`&&6kT)DUFgEPeV&r>v<1~+se(_{#oYtUQ6OjNX|li8>!;9W(hrB z`$r9 zuT7k7e*3$^U7|>7`mJ>*J$@X+LdPg4r<#UP@^Gbis%cEW&?x27R9eNlNsO(@nqUf1 z%BPy52M+0{JQf|*`t;OX(Veb8{gvlx&(1NoHRWy6I?ge7>Y066Jb((tk713R)cc+wTg>%e-uO+V3 z)7Jc?HwmmbZt^%-^^?{m$=uFlnWsf3navG~=8H5L3&m|YeR@HXxw9#0x%PXK*`sb{ zg`OwnlGb9bxrIya1kx~7W zIf+#7^rQOt_!HZg%r!sj;9PS}JZUFh*RtlBf1oe360#<1FU&W;`c?5^eIEzKZ7$u? zA;k zE+s7$J!?fz)&di)GmQ zZ%V;$VrW5yDjwsZ(aPVNsjs-mPEMiDv?}rF$$cOmJ$D8=qCxs4tsIn@>G?JcRmnAn7 z2a$P&Rt$}ZP^K=XShoHgUs)}tC+p?Nx-Wjtn?|pJ}SHPOm-(OvYA>Q5EbE8UMa z6t~0_5!$z(GIa^{R@R7ZM=FU+#3O>9g_eqF#dPtCub;AV2^QKSqB-|P9V+LFYf^=N zfy|vRe$n9rK2B-%yW{i{D(3|~jW}GTOcg&{sC;xAFD7UIBX$%&>EFpSQ%#Xk{rV4# zQRb$aMvUw)e$wdwW|`=PE($&+m5z!Yo=Yk07%`9z;K&kFWW+#vGFd{;D7mS$NHzT` zL@(F%eP%rp3+DYbPN60HM+~DQznQAPUaCqpMd)?>Bh@sLemjezD=JM+`&-<>!$Oov zOKGJc%Ic*Q%%*!pd8V(Dy@<+jd=Z_vw-};)RYH_~OHFh%!$rj$zkb;IxCHmOwHR^1X$a{RC>TV{$HHiYIx zMXMu}>taIwWihDw621Ny8QoWzvYcW$S7}PE(6BJ&^fEeE`uA5ZETe<`eVIvrIk?;u zJxtFrLRqw&o)F@a^j{l_XHY{A5c+kbU^%W@$3?o5sp1Yum?&;bYACg1=zxBzQn6fr zlDJJ{>H2S7PWK?aoCr~tFE>TeLosATWa!Wk56zPifmvaUBZ3+GU zqBzoJBx2wQWm}qf79U1uqmrAZzc!&u=a5Kce;Un7yCGf}W?mC7Aj4>sO3yi!X|!AY z+2@`ZQgTx4F!8K-@DJ@bTA97VG^)Llyn;41bYKi!chXEz5h3)XZ5m0hjFrVJXih<* zepLExHr>*ra9Ce@GTpzzG^~GrabN{2Oro&AiqR#T#pvt=dihjGv8*tKDOFncRP(G? zme2)A*|Lo8#krJSS-ZkCcG%E<${)10_-}i4s(Ecoj{>Lg5{E2@LWg8iktvgY%5unX zNOuU%a7c3~F{PR+Y9*NB9jY2^KfK4BaflpQRH@{O8@;L1{sEQ1<(ZLXFZD z_W6MQJ)8>fqEXifh4#cY=J}Il+StmcsQ;* zdlBsY6+4gIfR3ce*X*Ol_#W&Vuv&q@vu$_-aXoo}7hC{$hn<4Be-!KvFM*@sop3-O z9)BLrgCDY0C9W?IXy%Cxz?~)k2&bbzM)G{g8{kZguY?<}73+++Pek4PrlpGvF3pe1PrgjT7QA)Nn z1RMr0hBM#-IARo!zXn&1VVlgnVER~g8#tDpPsMtlkX7-hFGpaoF@R20F<=Hv|5l@W zBTUx^-4@sl{tJ$To4mmr@R`ozec((u=nbmB*g(V#9cq2+q{6wb{^mb z_lCQ{$ve1z2yBHH!OlCmf2ZVgk{{Zc9;r>+^9GCrohAPO2kqenroj>LI>|>R-Q7c`tX8=+ez*zIrfRE z{^AH%J_)c7!x>nh1}-Y#{&w&2g5F2j-Qlof>``z&oDTb);Qo_vuzH3AbvtsxpklT! z>~Wsm3yv*ePlQY0^>9)t_n(8);X0i-zu~uG)wzr(e2;)(74Cul<&yVEzAX7~xbhn3 zck9d>Fx-W$D*o4bKqv+nj+4AX@?JOs^RG#M=6}3k5&C^$>kVFSq;9(Z!zwwj00VMv zvv2DmxPW z!S3vI*!Okz*$-7t=ti$bMZ)?Yv5Vj?uphm66#c_tAG(MLFN2feU*TAKFpB`dps)hG7{9WeCJ$z%z8;iG+FZJFw+@PWU5S1t-D*KXCspI1;`NC&LZtu^{rt{z%6! zHqeOz;z1YPhZB4OJN0Gvfnx`-N5SpG*)!lucp02Nkoz~o!GqX`V7I|^{9*$a5Xc_P z{+%p#7&C8%9uSFu(^z&I>@kjg7WRT&=xh)biGan~BAg6I z!nyEbxCG8;t4fntUf?zc_>E`3NT-)b*c;9G$qgu<^AvU+ zI$axx^DhN~W_p0$(K3Svyb0&SAHgv*xxXjumB=0pm%=KXHjDd{;r6rHtI7KHUrFLX zkqFQZv*)p^CA-lRis&yze<0i=na7WT)8U1%_X6%e3}?euvi|#j`a&MivIj2^p|L-Q zb5htN;ebW#rEv9P_EDpM3HuS847Z_YJaGU;@OR(f`rjy(CnRA&6Zi-m1V4b|;5PIO zDH3MDU&96Pc-Uzv=U)T+En^@57T5pY2t3AsT-Z!cxnhA*_&d1%a!xQAZnT2Eo-7_@ zO;)q>;0)LTyZy}l6)FN21Zv=fOdjAu&*>sz=k;uNxC-`xvo>)5=dj;Kb_iJTiqlD&cQVpP?xR&B0=O-ORWbBnmY1sr&S?M-e$8}d5E{sFE&&5oD6 z9(F&2>;EMLvd{7a=MYZlRLpJ#C&7VmqjTIp));@Doemem$6%il?!RaBm#7?gsW&g^ ze~JAeoC*(v%i+baQp)2G!=206k6>T8T`1>|gTIF}R0L)sPy}y=tKf66*A-qsp;t;R zsN@k>*{{J#`HlNm!)kj3jv>(bIuEeIK9%fd^ioVLSbdxA3%lQ84~7fj zBx5|h4fe0%@h8}-VnIL&;{}55@_@E*;63)YaFhG&I5^$PUTutjz%GO>f3U0J&VRCB z?_6aC*qL5#i}~KqaQ};N5&SwFS)cpG%XKl{9xB#r41OaQg&-lIKf4Ci%H2`}y4@&ysuy zE}{yG=O5)Cn}D#-2u>&l2uDd?C;6&m*J%6s-%6hIule`?BmV~U1szA)CwO1-Xvv!- z-;(_LDEoXNPptA0E_xDRpOV~Qw0(k);SyA6oa9ZCuS;$o!}&^7BchDcr@ zxlpp>c>DPsb<_E0Y#>S+um-L`Ny{WRoxll={vML)FF*7rDx?31WJhuB5$B&V;C)<- z497^`BDoT-#s*)D;{^@(l1y*%*EeMJ7m@Yf|BXQ1iS`3NlpHI0tK>V9+f1_07bbb> zB)a~$pb8ipI4cckIN3fyfaEEX_e%ata{GAud=c>|p;K!<@5P&<#fA)@m;C$``+k4P zs^o2wZ%cknoob)(N68B$|0=oGH2eAglRQ%L2FdDgQlNQ)eZp@f&z77IyP$%9OMYiM z=QH|;+FMoD*aws{$xUb2C+H!0mgK{d|AD=*!8d1eJ~o~Iz3c*tGF$Q<$#*2bl4zTd zK2Ah(oa9Zm7T16A4~F7F7l<9Y%(C|fl7~rNF1bjuGTT01I~&vEUr|DB0>bko?}MYU zL967~=kNkX|96rTCFlKXzW(3;H=u|Ov`(^5_`T%WlJnq9Y|vpY&o|sj^7tpl^?%!w z06!1>DY@M|`-CGTua|sBvgdsJ`9ln=*zp=80N;@8o@}3BfaDdDuS#yQzfjq%}baI56sCBMF$ z6B^?~BrlSDQgZz?)jmPjG<&O(x5F+T{5)}8@{22YzR~}&s8ZmpWappk6Z%LV zC^-f8#s&){|0!8*y^hc?=xL8&s7{`+#yua>G@e5EB$X z$uW|DmV8(!${Wm5w-eI5MOUW}NAAsYqL91loEow)uR19GGR zHzYUPWuGuW@&w5n;52OTvgGH~Tux{V@RdAV@=D1T$+dUe=X+Q3K*{PN1oE)MW0I9U zoY3fRFF9QDQpqPI*WPQFPgOeF2b5uwe}b*pV7cVi@;ITP<) zqU1xcYD`cH?Gtp8JW_I&&SBI0{}I?L4XBdb@>fo1jQ?74yyR_? zuSm*;0T)&7nXv}|K@-WFOgvI%1OgJeGa5`b1usxiB z4TeizBKf#v$CI4TnD0Z@fB!cE5z>Gal21#ncgjBD|KMC~urKUx=Cf*sF7Tp`470FJIRhtuBS{t0kq2i>Z&(FpkP01F)O0lQjqvva&a3i>~g+y^d2|18Pd;fxPOemegz z*aZ~jF`W1jZ@}w3FX-dP?jd=co7!*e}pk@({@jCGUoPvB7f5^-4H@ zAo}05v3~vk+9n{b|1px6Nj5Plp5O1NOyZW)~dz1-lIP>B)Av z!uiYLci5^DAH)MfDA0g1x&FW&2q(fLkib8f`_?JYT;m0j(f^_3esD4R=fLe_u^{X< zo?Utk*Z*P!>Rjgq48I}yTgl@kuaaCS*($kd1=YU=-31lcfNzDp`%9iBd5h%pl9e0w z`C3a3P!X_V15t4D1TN81*lQxY0FIc%z6lq_vm4&z1=~+!`@qFB*}dRWSWQHr_beW; z2M(XZE{F5zW1hr${@g8Iz;!A6ZMYGA1dr(N1LwgBaPQ^ZzXh(QPj8{|s&WYdpOrj7 zspJKcRdIcwNoN*)CVt>gZsaLoqx0oZ9H`=*`g{CD}C7c>UEEBQw_C5sazO5O=a zZsPt5IAb%r>21!Rna%cv^K!}J`rpqsK%OpngXEKN{oS1KPsz>h@PdKp{}^`P$KwaV zUizeNZXQ$XB@d2q}Db|vg`h~1*)!qjBKBrDw#dZS|1t!! zPw;?7cX@%_Q|wN#+a>k@*jmO;gln#_bK#7u>?^Q;Is4groWJxMuKzv=xK;3g@8Qgw z?1^v|eJ6~l&|1kwu>T$I{}Zmf&u)I77qr5DhE)UxArSU}CoGbD7|!~G`yasdtJ$rs zynxF?_UCYf$x+{Ml;nl5nu7tm5HNfhu0emj2fRReEl&6bTveO>Bb-`?9S?VQW@o{c zdh8Omsx+$4fqyU{tpU6BAG~0?3;RphzcG6h90;$1GhgKXVmP}A`yV*So!$0Nk)O^# z-_{%m)C2V1Zx41HTn(>=Q`&I<3E10%S2Ye`p{s zMiK3Kz%JP3J$4z~1a|q0#~Xehu0nqV9Mg&C)5q)T`D6db&L{Kl|6Mt70|OG^XCLx} zBG?B`|CGlE!x`P!GvOYeu{Xn3_!6A>1^3r`gzJC7mmDxZ;sxElVt)e%^k9#NtAg0+ za5a1ij{BbbYu9kTgkZKAF7D6%t_Iit%t0KOfB{*9*&E>C2=+m^atQl($<!1&#iX zBo87tpu4#DP@W&DN`X8?|T*#v|&$-7~faeRcoNp9f83mE+!;6RKImOS}i z^Ywo%0{NKmtK@r>A4luo+H>RXK180V@V5wRr)r@!bEKhOZbfd9e16L@GjgL4rZ%LFak3%AQnCV7sI#UYS^V7FW^0q7w9B; zfaG~_0LJgsP3NBxxGD{J<{4ff(pW(9Ajyj*|04O3WKa65IR5<~3-lBLI{ymc$&#}q zUzGd|{S}?<{C8pZNnD{I$uVU8`fm(aBn{XpxkPde9E1g$(Vy*!4H$k;a**WF4e0g1 z?F3C4uoaHS0_P+@mfY$&lYTKO#`sQf&Sb7YAY2&Fj(m<@|BI_v$rKK#7|=e2Jqs>f z%wA^nr?NM~IZN63aPl(tamnY&;((2Qlj_2OiZq_^23c&V2L1s3t}D4e3jH4N4D=Vn z+u%z023!p{Xvpi;q;o#?Z3L=UaUck`tYJ@tlh?9W!}t6FdUng_ae#0) zxO{`&uPS2^h}_5%*1;C3(Y0+Dbi91SmkW8i~utZq90Zy}J10j~77 zpyEEtg+GPM;R$fyCf-mMoDKg9*T8pRzs)?pNn_5hTU`G?v<;94!zq|BPx4O5WpFXZ zKl>stplsm<--BJYu>;|>?T-BSf1_;zbl}Qz$%iH1hSMp582>!|b*!kE-wt+1xMnB2 z7hI9co&+cEcI4~-N@Kuo9*_s;?_pnr^Y*eI!oBm@O`GrreD|?GmOMgo+7sjIRfs?) z65NK%;ifP10u}IQaNK@gaFpaUIPd`XACvqSY*8`b)uz0F1rC6lnGv_VyIy~2T}uDoNzA4!gooD3IS<@tGJ{iz&2f&QA`xZkNc_d8!>yOQ{V81H%kHX^hcf?%|%)o#G zcnh3-uq^9921x5V{77lB9&aQlNN%!b3^jc^ux0k*<*TJZu-4|)D8aPlLz zAME`%dq^vlCs-eIU>*jP(-gljz%XgwMg^i@b#YgbV2N%Y_@i%K7pg*>A&P zPV64AUoG}{RSK+v8`b6kMUo%F+30WX&I?w;-QX%X7EY+c`7$J{rw}N0<^c|`aYDmy zz`1p~|2xT(VWl4TZ-o8e({MCg>vhhb&Q_K85paKo6AXZRz_ZBWye@`U!$tLZ{4Tgh z1NH?t_c``WxKS&%_*+wvFV9_=uD^9#bD+`dJfJC@(whAySv-|`c(Q}h-x(f){$MZe zUxEH`cnA8Mn7RKN>?JI&|4lu30Ur$Tg*(5&6Z#wdZ?Y5N_U+i)V86H7C2-O^Y*QP~ zU(kW=4ZFYV#Ml4t5m0=1Ks;OnZib7h(Qb!zu#ni~w9J+2svR81W%*z+duM$(tpY!{wO&+?$+FH3FRw zFx($@{fHM_B>9l!za+Qz<^_!TKS)kst4a?numb}OmrHKkjuRUFT_lf?ybMl7{$rB= z&`sx`G2pegcmcy-N>(Ljz*Sh_1f1{36|40&=PUo1{RUjnjonjNT>nb~I3V7FC7x(} zK4-6kt?(&0|v6Lyk3MDi-hXJFs&^!cjtLT65hfYJ?)`JNYu zmAp}M8ChJ~G292$Le%17NqI>{wWdVkf~R(d?CQ z^l0{WIC~7P|0faf9m@l*!kx#lAHnId?E1dEp|lC?j&PGW_SdjK+#e2{$o=Et(uuhK zFF>FQ12SRvNjzaMSv)g(!FOP9_?0f)-yZ%B_J^m!!SHT4auTlpcM(XzfR-O}!W{Sq zxENjqm%vwGr^&qG#vk!~ci12HgX75JF7;BU@PxU>gsJR9aF1#1OK{qBb{#)nz%ql~ z33i&r4ujK@*t6gs^VmCKH4A}K1S011fVy3I0oMiWws0o=Ib5J||3ug~g`ELg;B#>0 zBJOYav7TR5jKD`6P`nrOfbo(y!O`fy4Cla&Kj948 zxxX7+u!21X4qL^}fSasgUm)w(|7Zm2e8vgAGk8D;xO6SM7aX~cJ(VmT#RZvc4G!AC z&V+q7v-99aTiK^RqwBv&khz@$*D;`S2ip|D3&iYXzW_(?Vz-4$a@n2X@;&T9u*W|3 zWH<<37@+b3z4!Bg^%zhEAB2?y++PB>hwqTZ6H{mSmCxC}@RzV3JRJ^#x2Xt3An-dJ z2e0v<=%T_ul%OVFQbZ&kU7fd4U0(6~D%H2eu%f&MtjTj0E3dHzK>|2X^kuQ;Fc zNp@$r;IuHE|NRk&J<9`<;bM3foLtQPzrlXz+0I|{0v5O}TvfvTz2WeS>;$+*SX}>i zBGBkE54bP+^&Y%H5c)$UFN9Oke-JK(Yb2Y$;e76;xc&zr(1QYW*DJH&c=#mTzKr|p zeai`AU>`UG9w<2(u0;QS*!2po|5gOtuJ8ixJ+Z^9><~EoH})LZ;|6;#Tym3rANIM$ zb_?QsRyYt&|6Sz)V-RS6oBb16oCS$h>@BeCJ$3$yGj^A;;57P1U2&HL!GVtKsc?QR_Hx(?Z-#4XbN>-Iu@1WoR#OqEMxY3O z=6fz#G29t0frr4Qa0YCJ&%n;kykLVLIG-#05nEMyBM^-NN$^HE4}J*e!#=^B(77%z z5CQwZX>d4vjx6rdz-M^;O}(GaKmYn1aQl%H#yrb@7Y=N|{syjs$HRHgasP7I)rEZk zj)8xJ!y9sc-Cnewxc&z{&jBwHAiKZ7?hXewVvm-*RPq5h9^)${KO4gNjsCaD`t?5t z6TZO!!!eSVz$F;JM{=2Dr{27v(wGmxQ*vN${QhqY7=;0Dn6Lus)JwV{?+KOf-P`(Q|^BRdo*LK?qR%OkShm1lN<$CqJN3xd^n>y z&%Y_zr61=v`a8h&Tj=9erI&p`nJRe$9K#b7i{yur-TL!_0k80e{3S=)na=+d1QOhM z!fx25CHpEI1HUi;cM;qj_HD)EXTdpeuH;*=)2lRIT>qPgbHYFoAb%oxI2?!m6v=zx zBJ^LA{Omx^uefvm_iZemf0SVecw<1Ojd;6-qw);#{8B=3S#G5#`K4m%Fz1zkM&fL@1VVSiXn ze1iu>AQ1j0dn%my7JCgG{Wkj$oZ6oKk7S==yaA(sI9!GC>)5Jd1g=U0Tq8Mw-#fg( z+puc~c6T@z9s?)7%l%8>3V1K<=fnMFy6OCD{~iZw4d(^jJF-3C3ixx_r8DkOBw!viHJCa0Q$XKO4;p7=8~4c~`7 zy7GM2(VQ;`{s_*12dM~DBajSxe9Q@U842J@I00@G!wXp89z z4}YFecMKIert`nfINm^|9#E7vuzwIw_#94$hr!9;asPZc{(JT| zIOqrV1vn{~{n(fm{X!~VV4`{6YBG2A4C`_1DyUl<$$XT#Is zaoFjY3S956Zpch z@E|x7o(q@2`{DY1dHz3e5bPPp2ao}O2Uqu1dBRi#{KME=;7s^3Tm#pe$O(P>@p$p) zx#Foia4t&*<_i}TMI@ccAhz;H)c ziQxpjCC`++U2+L*#e7o&=QnI7>(_rH@SQYZ0-QRAH?UFiWyuYv^8&{Bk0p%+3N)C~n0H;pY=c~##`+#yoa`QR7046BiVApuwK$PU=l8;HY!eRP+ zI{%v`@d6y6U%w?sOI{2oPT>t4lKiLSHgh?@F}?>JIhE#%>;EL%0C}tA8 zcmrJ}kCD7VatWMF^Y!chGxIs22+;G9@`2=N$v?r3rt|nCk{?KJmCX5#@&0ht3|#+* z{~ORZuw3%5lK+66X7L7EEZ_w)XR|+sU6R;?B`~Rhp#sHra>~nDHDfV?Z`U1NO z4k%$Oi+Dq^7uhevR@e+zT;l%sb<_D5e3=7ZU_fFiyDywv&W?sNeq&D~i`RT^*Vx%` z)^+w(jCZYISE4`iCcDXE+ORnPG7xx`0wSSDB@gh2i{U6Z{&()zB=3@3Cb`}c&Tq_r zhpb=!jX;PrV5Z~^u=8!+z-h^kB)^)<3mW6UkUTCG*MDQc8fn03$q(TscX^rMUhZ32H5~PuM|nFE|Aom`WCBLAjMTv<&^>57>ckF&!=Gh`V}27C_H6VgzzfkI+mQQrqCfk2wt4^qyc%)f z76w$pf1y9&CGLMUjW-~RV;{0qn|35*%r#TN8EqMi8js9OHKQP>a=eJtP3sl3O!l|!t|47){ zk}R(O%WVVX190N2JmIe7m(zKH$k(_(K=K$k;C1d#A&bXUjR!jyPVlPD*Z(pEQp`M{ z_9|YWxE=d-vPj_a4*N5>{(J1xZ@Z-~XRo%?rf#;Q=jS zw=i}`I5?X9G2CMm`%Ab~WrxCkli0(Jet0TbJkwT8#e{VTxQe z_?hQl&`sx`5pc=mgoZzsJQA)%f>n~wOLke$`Hb-&z`>ckff2&u`fmg>r2*F@zr2AH zW+TBzlA|R5B>5;@iTPHte*HHBtu|uE7|>nv7`S9TAHf>Q=Os7D;(W&VPO$4no*!|%a)Y*iUyA5hl7x%)W51<7@{b3(5J-0v%SIGm0CwURHu zKKWuko&WW6IAQKVPS}You67=W*na5mUBHe)e+oPv{q=w0{&YAOE`r04a{mKci|hX@ zJ9q=efNqk9!d|~}f+cW|_vtxTcal8cx5> zPJ^A*Dh?b*AnY!?f-LTm)JApm-ver3-xt}9_i%rFYj#UGwhh}8_G!!R45yme-C#BP z9S($0K)fW1eUCj0cI(96jR}eHA@nzSpZo8lKM;P5{_+pF-+eFVPxfVh$yOELE*yxV zfH>krKXwu(xO8Rb!a49I*vFsyO?kXPcmVq~vd9N$*t6lVG3;#2Pan@djsB82_9M7B zp55x8$_sc*<-n&0QNo$*XgD>Iy&SHX#okXA8}#46J_A>7WZ!{3^4O1HxBYA<^$;h> zJj#I=VV7UoZOP)aY;uwv2sbKY$H1kx*{k64JM7bv|A8~AxL<95m=`btePQprJYY8L z_9uH6Y=y0oTNiM?h-x0+N3sTo|E2e|!!Mz`G|1!xZ;Bxdk z{KE5N|3*HtxXUVZ)A`>S1A-K1{i${^1|-3w(BH_!{mbBd_$VCd$o+r8DNgL>M|lIu zwb}k;v4L=Bvbg^D#()wLAWwz!>#={vgyaV7TsZnUb|Kv31$H^+7d2+rDMSTfZ@84K z|NDPW1bV;76DGlx@J2ZECGI~5SHVulc!9(w-2Vn#0DlhWH0A#BuuF4i{{4Ry0==8_ zfRk_<`~XgUh5KLrl^4ut$^HZme3d;C&UR<7fL&f^A13Rk?WZaSE+A0ZjctX!gW1Y) zp5W1oT^BA7VK;;Q`>@-bTf39vi|EdwVjRAqnc)$y%_z0C1?Ek@u>FjVgbrpL)S=`4ZYuP){-)KF%9Cq2n zcCk=?asKt*%z@4n5D7YOXGg%69Cj+~wv(MN643a#^Xy{Sy@Y)i?p?|L8xFe7u6>%W z{~|&8pB!jH0b&1#Y%^JGDDW}6C+uFouKq+750|*Ix51^&+1KErSJ_R@aK3bR_UC7C z{r7mC1MxIKY#sA`pzgVYmeT6Api$ z6SO(U2|Yew2f-0=0_^O|{o7$b_$=K1L+)3d&vU{=KMu5mOW+XLwJY~ehMRoC&Vb!N zWuJu$yRmCu;QZbJ?6={>&vmQH_Y@HKd441h7z&3+v8TbAliBm(^eOEBb9Mg#IbUrU zz#n8nXcIzc#A30KX@n4KmI>J!ZEMpkTO(VD#W(a4vc*Ekgji_PEQHX=#M%}bA%r%W zMrgFjyyraE_1!%8pP&1>&wbAG~#(Hw^J%yC@C9Z4iaa{O_E%u{UhwmD)gX8x zT|F3HO_#p}|417-!%(Pm6$66;;J(WG6{XOA%pFD`pTXRZj$@u5ht6YJP3}Wb6$m0>9k<@2W5T0s1Ue>4tfKwpuOIP?S91z%p4DQwOT!Y z*(`*xA(viA`-Wk`Ub=w(gHCuCd7Iy`K_UGL9Wep zF~SRl4+!58e&(j_ym7*b!bYAb{3YD=mhHfIgjdj&d;!OVYlNSx#60#JmUnCmmgU0v zbTv1q5%#=|fo2{ioGe^mV}1YL!2nA*9>e~^F?2NZEa3_|mU-*D_`&4=KIVBSTQ4K} z9XcdJ<$C|b#|z2_ge!zwRbilYfa>=bo<_%fhy$bvpM1>L-~TOtVxYO8n{bHmB06Of zHpmwKjrN|5yzM>AH~lId6WIXwe>@8nQ?OtUUG))slTP>;?sgvoO-~a3TKJZ*XSKQB zz`!a07T_JicjzP@pvPYrVESX>Ea56Th3h^3#`+Y4h4Cz;(O(E(6mI(f1I+%h!YhQ& z2s_tcy6jM?Yxn~amv>F-`sE)8^ZYt%7t6i!9X()5S}fZDSTD9 zxt;p=f9oHO=D?TiY&VDz-Y$Ga*r_hor||_06^^DYG5C&cuB-n2-}(S%p@i-=}@0S#d`QC;oOroRbpkX6jG8aBZ=gos33HP$c21U#x zgg4UF%#D+(p#L#C_kS38l?|Tr;g?XwV$q5T%Y-_RxWbzxWa|No`mfimRk zfB(-y^kNKHNte?n>EtEI8#Lrw_!-=nuA-;Vaf!$`)8$Ly0=jUSwtD^>IA9)d+(`#)AtFT}D?__**Bj{gnN{ey(((y2VaUg6tx`dZ%q z9#3MRDp-Gg4i`=nzC>rTzs*xvAN>W^ze<iH+1SY(uP^M!9vtmXmD+gf#qMrL+Qfp@Kj~}4kUjA&u4DG1J0o{zJ+hnfji-LEv)km zOYklff>5wj(h0(c>1yV+oN>V1-B{m;_RNN-($#z5uV}{{_@dS7`HN)1sU-$l_M_n? zI_dyCnGQL~fx!6v|}#TFH*Mt{lEA-6xOi8{}6n_9B>$ZB;2(%Hb}@r z{;u#^y5b1(pXtb>u*HS#X%KA&|UC8jBxKw%LVn9iZ& zPa^+a*x3~uL=_?T7mlU_P9xtYe8~`nrcYy_xnL;mb_N4tgm=(R#mKMGF=ydM?J+Ox z9PFd4-vN&j*ci@+6c*;uz8BH3lg_#X|3>GO!mT@CgP_asXyHY42=jc}{))9<{r=~M z0nsQ}d}z-y42+`ve}gyC>GXNp`xn}Wr1TDV~+3^WJ$ z3QwgIxxp6U3&Kx6gL&3|eg6-6yr4Wo_$xY<8;K>Y;eDchJ4{#y)Yn`xffk{3;h%5;z~G$j=T+@r|s^*&7SA|AH~8*RnYgpTNN4> z(XRL496FZ1OFQ02-mW*+n|_(jWjVtt^%!euK??6p0%p1o%qBgvY zcC>?!7%aHfMd3c}{si2$FE+@fBj})d$T!n@^c6a)KJwN+SRdIC9!?k1MjQ*F4rtg* z=QV;a(;1E7C;Qu$RJG#KFeK9bVeo^>iI-)bq3-(W=AzXMB?brc%p>VxH80g@JydNFg5e}onJHbiH`b+BR z-Vne4Z(>8LDyX`pg!bzKHyMl#f}Vv3(jgx3bh?V(MQ3$IUP-%kgFXB(uj09exc}c} z!LA1yR?=bgPjnS+Hv|L1z0m(G9oP#Vr>tM0b8k3;c|5(5_ISZS!^wXOaIK-(An66T zkMPH|M<3*yX`jAuG41CAH+~WGO6cKqtkDk*3s|V657X%bkk`<;1L1D|80b0(ewWUq zmkRHvLkFY3k~YjjhnFxg#}5sogy+!dLy_+gzDmdXBX2bf^GuJVBVR(k05&Ye!%+B| z4Y@DF7nSvA7(X1o#k`vC^fER`8G-zDIx`SnOlOaTzoP?3!Il8MUOj(REcCG!^#5Q0 z4by0sG4OWU>oxc?okTki$AR2}k-tJGybixZ$Bcs)YU}$yfrWH7q|+zpJo-<%ly3bB zHnb1Hz}~{6=p5!#X|IXsU#@KZ`@cU6`^^OrXt<=TKZ1bC@E^?GB4MWy$Se62J*}+o zg2Fk-`_o}_;c;|6J#z%_|G))kSjz^}2bJ{!s+kutcUX-68rp?+3B&=s>7jHG{Q(_G zFAFrVAen_-YzSF_4bGSgXv;|S7p+0wfzDY6zpSheoU;QCW}cD-Poq6|!bt`TNi1a1 z5#OO9pAI<;-!gN$@hBW9p6*Sj(c|b`dJbJq8*4=&+Z>RG4bRi|C*TLP3*BKf4v<}h ze2B7s2mH>!qnX#xGnrSFS#!g(fDO67VL=)lbPfKF&ZbN0iVEa)f^Y!S9hLO~V*fzi zhk4m;_#L{+YW4ijWx??d8Zu}P`ULGySJRQS%NQKM?IG6pqrK?~v`=jZ>+QObuB@x9 z@BeR9L7&*e2@MC>P~8kJp%a?Jf13m7R z=t%k+olMtx4I7$nOZ#`gh6CyH=is;L8hRm})YAd?|29>yz5~x=!5%g^_J&KDd%g(& z!QA;JxIr)ultDj3I}SrWlumsGp7^f~6c($3K0wF_IF$|2qu_ixo-U`;=%-%C0dncy zbP4??Z8sY8=F%C)8z^iv2has{{CMQI=z{m)7GrVX(3!BCvi{NQ9|I4fOXyJAcNX$k zt~a9NQCPx;nnmz>x*`G2H*@+L?YsoJ<2W3^i}s=e>9KS)Jq6|nF>Hk8v_X}bd$aDw)r|D;`xA#eUBHuR(i z(9u65e}{G{f)^=U|NH+QzoD>_4Nm3oPCA`FMLS$aepgw);^Moomio$;3KWMLx*r4@zY+!nraE!8k$9&oUneYZ%8 zxR0`a$12?Q3sTR2xJ|)gSt)#suC^{v|DVsoo!-SjGY_WiyWkyLLXnr{h8YJf`4Eh_B?!#b{Y(K2*-x5BjC5`{E_ft+GBJh-2b~+h!~BAU+HZ6$%z=~ zIR<%OI)Z+mPN%=1^XcQ}`d6|30UiIUfkOB9u|Xai!srTmK3()0`m>bvJCZmSKFGXs z9DIW=4ToEPfcciGa4=n9Oh;iJ3%)bp?X>eJ@FhB8HrzM@12gyn`qB=u$R{Z41G>zC zW0^b7g}`&qsfqNjOl@Lb$QA`cfN~ z!bK?bV}oZhJPHk#RC*rmzX|yf+CCk=OQ&st+fT*|NZbaGp}n`mbF5a+pIP`?G+d

|fo+JBxgg;QW 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 delta 368344 zcma&O349ON_y7OCcjmn$B8bRJHfw?)Vo6A3A@<;{_AT~(t)i&BW8dX%!nI4Pw$u`W zX(_UxiV{oJ(h^Gv)rfs7e&@`+6Y=@>@qhe3kB869ea@NJ%$#%YopaB7(rs(5l7iJ& zN%9rCZoK_koXfhe{SCxmFibSV|H1#(eXWF$NY}DS9Pe$(F}7Lz-BsO{wWMl={FD4> z!3Lvt7~4kWmf2e=B7PN44y~?9c3j2J#WvNBMo~W(4?_*@XyaQ{JM3Y|oIsr=V?jFy zgMpRHs9IiGWvuAA%5E^Afd~BSm|feDRn=e^7EsqvL;2O{?(o=TFn9vlin64m;$Ui4 zw&k-&j*pAN;^wCoEIt0D;FZ$d)Y#(mkB@d0CC}ug>@|Jxf4#1@p?ejBArNp`p^X-m zL_1kIZyuExCEMTiv81F{Fob58H6;5d$o71xeELgZ2A$bBdjc%MRoJC+_6S&3dBF@u z?cDpo{B$;mv)jOIF2e2@XMX}q%r7Tk4U=~A6@XDXTg=%-V5wz=-E+>)0)xlmH{IQ= zo%;*0gffCV1Aq>Ci^eu@F2j{(!y{DXZwK}basZb3}6XP!tN1g z-{ZNZ1S{*HU1STMtFutf((qhIVb>d3V)^uS0J9tfoX-szFh8B`<7_!Fn?=~&mTD4qKXEn#m?2SzmQvcuUjs}q3d1PQCIZWn1)I*tnZ#MQOc@if$W;DmoM0HVjyT&P2Bj1?HzS(QWIXp5DDhw+%u)or!K+6P&Ro z-%wCzqTA-7p3X$KJ&k($;1%8W1nMQ~P;}dD6x5mMwm+eu&P2CWQBe1m=(c-NP-mjs z?nFJEiEg_M^#m*Kwwq8;cdO{O8&FVZqT8(`+F2JI6R>WCHV5t*@T`Ldm+_u0BI@`fn9I%8hg`L4uvx^3n zH9@fM8cR%X3eZo7KXJoGz-;4%VOcNj=$5J0|lGH*)d># zI@`h7QDC+KhD1K=-R1Bg!2JH=WDj5MBKv_w>1-lr8NgB#gk2tI-vcw~td^g4?iOGP z{e<0o&eDKo^%d-HB8Te$`spyrUpturv-J^%shlkbmfu@2Lx5(t1Xz^L5;&U=EVY-g z%i?SnFoVwgDr@J?NCcSBQyAJf{2EwR55b(OXoeGk`RQyGXJdicx(mB1RW-X2!1B8Z zmciLzU{N}2T1~S{0G8U-5SpmHbWU>E3!nj@#=2M647&nL=ptAFXPtm$eIeMC8k$`@ zV17EY1Zu1$Fk5F~w~DhEVEI)50Q1w?xZ0YXZ_h-y!+2q62-ct%80NPZESa+kz@l{KS4Xoe z3oNyru*=}A6flF%qUvgPCSVC|g_(AwpyYoV@~OYc1Hs z5Y6r>u>4kn8R~27A7D{BTg+Jju+)~q&LdQ_y93Oivu&aFL|oh50GJRb3>!Dl46g#q zY9ZK3&MpD-(^>b1n%y~Iw&udFfU{G;@?!;?(nzyA4lGJ%a$}8U^{^zSq{axtWDXC3 zp+RRA!!*MKz!IW`-8Rnl0LzLJEHqrR+X2i^XIY$W1!ij|>^e5l?7jt-ABijxT%FJ1 zdVo?h7<1M|~a_h$C| zL~ws1KwG#ld=3!URABjGVx^O8(AZbNqI6b^Xlxv?)W*W@BxfUm8FV&`YIZ|_B{ULt z7D;3MfhA@&6mT1dy#e~^tQB9=cLQc?AnXb_vjWQx6>Ppy6KoGGN@rC}8fyhCwZ5>+ z;w%=JfiqaQ^ycgGNPr0;!tga`VZgHL36^5f1Ve%O>8vha_0|Dqt1ImCI12)nUq`TU ze1%&TSd`An;(`?NKRFFxIXCDaynMVyrbmQ_oz={zNO0_LYP z3(u;}z-%>zT?%IuSbk!VfPOrMe%~GLP-ir^%daZfD$afb7NxT)Jd@1>mRd#F zWpH*Hm_cVvdD40USVCoCcT!`C>Dd6Y0tEbmXQ)2`^V3;AXDTq8zpxv}lhM7v^8Exe z@WgW`uqd4+bG8jws;{u~<2mLgUW1bC-0_LZ)lbj6&W^)&I-Ff1ZH~?V2n}7uz_5l{9vxz+O=?<*8kRmdl z&cF;6#JP)kmJ<)GxEA8U6Pnh*vdRm)?>K7?4C)z)-2HW{Xk)t>z~Z7{7H8qWife)$ zc}CL!SaD4-pR>BaQp<{qjN=JSO<=_(2?I}FssT$VBkYnBIrIluTvza`q1{YHV19bJ zAcHe^V8x|@D4x-{0Lyn0f_a>k1{MWOdzB~fgvJ64Yl0dp;!H{eh($pS&gL1-hi-6( zj)Hmc?BxwGtO;s%J2-m|3~PcKi{cs0V_;Yl)Yv7?9srAV}PaVOw?C~qn^%0ePs~pah8~;*H`+X z;9Man>MK1_P-mjP(gg)|CSDF5QBY^1zS0);<_JAeUx`CKo$2+JXcW|;sIN3dL7j>E zN+T4UEd)h_8 zbtdX7Wl(UY&=d6)N7U1qsIM4NPq5ebloFJ-xni8wGVJ>MMVupw2{nj)FQ9^_3;4r!!GsnU8up)9Wj< zP;i=lhy2Ap0|j*^>MLKPpw2{nWg-gdOw?D#qTW=YC+aIBP)}!~zA_l~rtL_r;j`id_KP7;EmzT$;~IurGk z3Mi;EQC}&GdO8#Jl~Sn3%cOb!qP}86Jz)5L&GQ%a6@r4gp{TF?+XV!5Ch9A%faOmV zHz?{WPl1WLYo5QTulxfnLAMk2l>*e$nO^_BG~s54PtS%rc+6ZI7Z1;>hWMSW!{ z>gh~mBMVSZXL@~QHVW!c)K?NwaEuTX^_8h8s54Pt`3ePfCh9BWP)}!~zA_T^c$GTO zU({EIbiw+H4n=*XKMLwh)K_|=pw2{nr5g&45;rL7D^_5sIurGk_Nb>bQD13=dKyav zSBv^eEDDYkf}*|>iGn&4^_4Ib)S0NSgrcC%M17?W>WvV3qP`M@dOFkVD^*cYhoZjX zhk~3H`HT9BHwq5d1dIGdeZ>t0btdX7P*yE z-hTmtIurGk*T9O4`l7z_3|Rh9p(pAqg}_pECh98>P>(bCeNEI??xLV>DC#RWQE-S5 z6!n#BD5x`0U-=CMbtdX7d8nr|QC~TYdV__YUSBzZf;trSm24E$nW(S)gn~K~^%WHb z2MIw@U)hU#IurGkov5cXQD51HdWkv|^_5L1I8X?R`pO0r)S0NStVThdiTX+k3hGSM zSC*mP0HG)9D+^Iiu;Tj492C?IMSaDFf;toRm1!v0UkHl&$|MxjnW(RfM?Ia1`pPKO z)0tjh8H$1lLQvFK2B4tMM17?X3hGSMSGuF1&P08sGwSsddZNA(k9s;2^_AAB*N^9a zMS6XuIST5AqQ24$1^Ws?QC|s1L7j>EN&^(snW(SSMLnH~`btgI>m&5^`bsqv)S;-a z_@kiCM17?q3hGSMSKLvsw-6Nd6&KXgnW(RnMm^5*{Pp^Z1qF2|>MIfo_R<9N{6&4` zLuU}wnaF(J087xBsINQ+=BG1JUwI5Hzo*a>^_7RH*Hh2`M1AEi6x0nxeI*|SbtdX7 z*HN&C5ES*5%P6QbQC~TadO8#Jl{2WPGrhj@GYWPWf}*~XgMvB}^_9aYs54Pt`2huW zCh9AhsMk&CiTcVe)YF-$uWV05K^=UGicKT%(qi-G{P1Vq$Vl2A}*qP{X61$8FsE0a<13vsTfuS`Haor(I& zXw=i0USAo8f;trSm4PVOSqO^yN?#PznaF5*prFn~edUYJnKwfIE)^6l+qXk96&T&X zZmD9}Uc+FsTKo)OpDb(0Fofkq7;H&Rwf%@3 zp2pR;l{9Z%!n}Qs@~+teI;4X#H!6-Ei&xG@9VAti1=0OTY2`umEcz&3851*!M#7Pk zzKSt+TDdy$mXw$E;inP!7oC)3t*O{!htdV{%G=l>rN+X+f>Kd-3#p~liEgdzYwqFp z1u`?T%60?su#@>o*5BJJx0{F4sCdPvMMHY9z0$SC2D-ex^0GxWI=_9UPn-*(+3l5( zmN~>ldC}6BI4Y}KH_QB@RTV<_v{RWb2#DqY=HIoM$({Sr3~ zmH8cQv;_!snm|{zQD$`Vq1)Oh8#)!zQEil^*12*>8%qlF`^V&y*|2kYO6@sH+b(l) zb8dQpTok(^M>*Pc1h#8->qI;E2V3nA;d#D+-Dgb)KZD>JBB8-RF3rZay#D=o&YXy@T&*6#4mrQ zrBc|pq1zES;zrdTsbg&3oUA{^c@jL|z+ z+6A_)Z7?|l)-l4)kUIg99MzPh{=qb@PW{K(aOTM-VXC; zTgQM!DL-Xb+sc_sCUzinRkU*BtA(^rH1sHMWzM7@=;|D$+2n@3*XKl}&YascA8yS6 zJr)ON?P&BX?$5Rc!G1w`ylqnKs;YP#7}{eOLf@}KJLpy=?Yx!qlgoQAg(Lf5noXfW z_E+GbS5&h90Bw&uHI8OH&#uMI9WJ!Be`??$|s)f|Rem{*rzZ1>@Sw)E_Re zBua6d`jmEzQa((bN<5XXr=9t1NI#?{2Xv^?Yeps7qnR?Jn_Fh`jOirOsTtgKiHEdc z8^?ioXc^nu$mdQlU|Y;q?<18qww3W60Hr!d*tO9Mr{QzA0roqDK9#yJ!V!+F1+ZJ- zAO9jg!UG=9wnhO<0~;LSXw$Tr5}dSw&W?nMa{_%8sl?2jzO606ymmOf}SEsK1mMKcR;s*))W<)5}=6|5On!{Q&@9CuQpb$tqP!djWa*2a-p<-W1J_9^XFL) zHO>rKI{{{nM#`3TOKEx|bZKU%_2o(8q(4`?lhK+o3 zXtA*yO~vK`I-!x$HFYY@ZHTjj@+j3pFEmtMrhcHyVUsqK_GqX~{q}Up>0#67(?dO_ z`({77x&cfN?wR(@^GIat25^Jgw9ez`iy`!QyM6d+qTdnq1vdW+xwC_ zO8@O+>#Ys7q_l$L58&Ah%CsM0q**yS!5 z`AHs&ZaGG22lGRf4e49xflwvx`w?_)sIvF_mGrOr+Bh1#qgTky`j(VeO&}Ii;kR$t z8m53a_V3vFx zcnBXeF!Sr3rwKh!KQnGOCG@WlrA@{u8dG0!+tZcQ${fAtZ$iUDl%AQ@=++QrW@Zqn zqU_8ZN@s>BZu^4h{d!8wzS}M*>Y-ESY7+)JBd4CyaDN-h>cNEJqonR%Oh?sIf)CuF zq4gAJb!gD$Qug7P{*#70{rBVP|9njUE9GkGzqaq6t87%)yBI+JWo3vJ{3C{i)_?0N z@js+{wFd0IZ-LdaZ?@G2Q`IdvOktLYt*5yBIHSB$7otoJ`z-KgUI5C0(e;%@e^gU` z`EekfT{koMU^t-->MA1+S&5%=_>epC%KYunZsJf4&NG;^BBGR}-^weghxgF|b(F40 zB8?;JSW+e_^$xmb?mTjzxI7Go0N|vP?+leVUp{sh#f&>z~tS!t= z$}Y6#1}kGO_|W=wl%*HEGDl^fA@s-K%<$aXgl5!Me2%ZLm>gX-H)0_q*fD{88(W)i zo7cyz^r z=k0UY8e~a%KkexDW6JrbwUn>U_i|Yaq@?3nkmmTQfd9+!6N5Cz-wn!Kdf^_SBZ9!` zK150R?HKJJsJ&{wz8p&v0yB?X27lhJp`ov?45e3UC^xRmq-qUiz}1}CF*W#o7@Td^ zj^CK^TZDbBV1BeTaKg@A1|wsw+N40h#iR3_{mbR}S2~OfOZ-T$(?Ccq!H3K03ha z?lyb`23tdZSv!FXE~%zC-kw0mRa0i%cB3PzDIcEs&}-EcpXWZAmu^Q<8dEKE#!F|S zRJnJIMpVswcrS(!S*cx6hrX_o*|%Uhq0_2pJ}mceWWcy85G(D5LN)bK&@S$maJ6Ao zGB-TTA+a|rfAVhjlw$AZS-y6%x5nocQ$-2y=9Tbno&mhO>CtAF!=O{ryFXS|dj50J zi^669%e((pR)P!XmTv=R=~D%GH!sk$0eH8IQt@#LsjTdI+}YC^EdI;Emdr{;7YXK7 zPkyH@0+drvmwJT-{I_T82WXyk3qa43vda5szSI_w>GQlVr3L=r)C+{(@zY#4{&g(9 z?WY761Y}-$J%!ML0>2$fd-y5W-p-|s{FDLja$*a8Klv?hVzJ*cEXOs!6;H9-KK05B zLyzKKnPKPyz4G79E@wdJcb9JAU<@054#3ib)rm~QhL3T z+R%fz5O&N=j?v#LvV|7%RjuTJ{<#r2AS(~%+bYBPw(4lUtu~%-tACZN)^s3*(AgDP zupC)JVi|5-C!ALFN<<^foAoS14tUK1{$Jtv z#+wC|C3DN4_WBeMZPfgz2c!=3C`VH0cV1dlycih%S5)j?%8`!&YDE|F1EI^k*cw6t z*z59SA3fvAcDa(3UPnA(?J^S9E_dLQ1lSt#D``&o!BdME-RjAFWa38CJhhOKa_ZFz zq!*=AJuz6937N>sRV03_wik(|UwWY91Jo2RGM&(8?%4NPy^3Tgec;a4R3r=O33pbl z63L1E#{H9P`;FqRt%0-eH>J?E$${e=X{kgj(a&*aHYD+WuIQ?gnaW4R(Wr!5)3YX3chE;r`H3e{^F#{mBgCs$TUcbqGD_#vCh?Li(nH z`nEE0p+sh-tC2c%SOqn*8o5DfhAZ<4B)jNrSM_Wl8R9^K)CToQtOLDTMxEM}e4xaW zecg=AqOYCR56wu7M5?RNvE-smpE@zOR^%EzHkRMqJsixEaIhwI%MX zX&dsK)Kp==7omfk*wS{SFa4<$D{M#HgZ^@`2V(Dh(D<`#4BVD%SWxW3WW$nNwN87o zM4~4h*^!R$G>aYCu1;hGAJ4oy02h=ueC>~CK*E%Ny^cKwj;*k;!d|2+{o2Cfdc#A;Sk!<% zB;H7SnbZjb2rVV8ku0o^&Em~=^&&2{w@9CBe+%sr+VCyXC+&*t{AiL$UrMTV41rv5 ztE4U+O9H60h+5d#{UnCH7*DDM)poQy;449RM}Gl9=gTmx=ibrw({fqt1oA7X&&Whl zo>lph{6Sw4MkkUHbQEP{CX$}?I8jecBo8E~4B?&(bkET#gvmlT)P5jF09| z{@HG`PK9=fXUNc=VQn*e3>^LtZ-4 z*Ke8g9^%bBlS%d9k8eL$e+O+{o#@^d>R-KMW0J`X+TopAm<%o=1~qUwsZQygH*Cy) z63bSkfP=o$9F(j(NT1v+AZFOi9i;7V&t-Q~$ggzK8@6`^^qvlH*taXeImg~GXGVIG zO6qV%?n`CB+gk6zExM=QTH-)SZFTs1a)*R8eO2QAf3;Z~L;L^SKNgNWO50=L_?}m6 z#zt^`$}4tlBlMs?uhavnq_2@qc%iy&LHF!?itdT2cj)Qo$||%=D09D;P_E08_K;b` zK{f6r%^;b7s>WrKYLu>fg3cKlblB1Upv(2tn>=QxPLw?;Qe1A_82%`oo)ULCQ3&}?vd;C z;$P~Gd!(z8KD@(y(*7^-$&)*uYyJc6|1ZrUcUk%)GLtsDs|No=A_;wbM;%j09+RNx zQubf|qo05WG7N`{y^&$a&Smq8z#HG*W?i3eh*`_23znR z`bp7Eb;JiUM1uM4JfY=@Gy98BMhkAR8I*d_TQ}4-ltSV0&p*`>GQC`i-oM6O)~773 z6Y}WV=NB)4wtn$!y&ILdc>n9{NLf0QhF@1>%29CH!)xkH7YZ&*lhI|#fezuHy|GSW z2RhDOrtSZdtFCpWJ1MEkTD#Muq%?EzpnuB;ub5L<{us$ib@8O>gkHbGj(E|jQs5Oc z`}o$;hxPEL7i($?zvf1yN-LUb`{!{#h424{`wHK;=cwH((gu`%@w>Xzhc0)PcVE;m z5Luh# z_|3pK10Uc@&jQboZsn@xy7W((9y!nMg;FaGyTHO5&;d00yt<(QbtJU?dCk-6@rHB} zp^O-Thb0N9X)7C|E4)-)XS|X{A5)_jc7|t zL0RfFf4ITz=rRK1@I#wH)gyCrxut(i!>7c>d(-ikMeYyfq zB^x}m_>a}NUnxti+?~Flq@L>8i%x_7`ZHVEn-*!PI`V9({j;ot+Jbqy*XpUL_}3&;InOH0Xp`%Wc#V1L!G2r=DPI>Pt=8gh6yU zJ#d_v2Gh#aKTEASn06(UNUY5Fw7>gic*xW$SrNERtHHP5*2-cZ&(H^Egqss2_3^K? zHD#eAXk*&@m^x+zok8foxvX#`bgjw9Sj;Fom7dI1kBq_t!*bQgF*r_^yPOqp!N&v0zyCi;esIlzW|N7HHC0T%QNZOwXZhM|(OpDo=? z7t#g$nb#J&h4$Oea<4Xf{^(PoHCwHqbVg|@`_bwi_ zKSxMSSaLQ!PW?;q=`BA8rne;~`|uKzwH`kZg#`|epSBP2bI-;2P27p`i>Fg|vc4xE zbX9hW(5VnQ_;h91PB!Btge__(hHWZcx&tHT$&UU)$J1FmSjZ^|TaO*=+9?=2GW+#3 zjGZ(mjLaZcZQwvmw1Izi+s2Yyac}QHgP*7ATUfczqi%=t_>AHR|2N;vg71U>i@xJMzap#aB)O}d3+Qiz8a6W@XQ@4# z{1C=W`|sEWXUUW0KBQmMsP92194VSq-=Pti}?aP$SJRgAr;+S>`hs*zeQShtKFFLN}(d zT`ys7o$`WCffc}$7xWNqm!<;i2|tmh^6*uCjc;~v;Tw3fPXzduZgRBeL_BEL!XB9B z!yb>L!Rmvz^dh188`+V6se23z81RcWU~r3p!)?g{gKZ2PZgIf;eqomNitkJ-wsF9? zzo(syw9f|qYDuC}KZz!;$7n5Q6HU@)+P|z8s7BA8n0Ub-dV-~g83UH_9|6lK5wHvc z1njz5f`G-Y!+?3Rza6CpwB4IZKJO<5~>WavHmqg_Mz2 zl1l8CGSct#+!`K@V`Zfk^j0~H#vs>Ze9J%_l0`g{^>~;OZjN#hbD2{GsWIKMT8*n9 zLCvK7YVPvmZW4@`@vB)+52-6Xy^4>R^B$7+g6ZWcm8RVqtb!5aE%6c4&+rBur;Qlg z;!K5G;rP!+407RkZN!vtyf$KvdP^%T^!5sVC*!L~r?q6Sy3`oHd~?x!zA{iM9h7ah z2mZ&{XoX{=MYfiDY5OoYH3~#mKT=q5Eh(NBDQre9>7l${5pxs1R@~US+S0%DmcrHq zOX>7S1?Q(Ywz!TIO3W;~jT@!N%r%R}qp+jUgoal9_Xu)RWX^!^5Ombb7K{ z7$(gn)C)KiY*c#_X&Ir-l373mL}>Lg9--9{l9qM(MoLCH)U?c;;s7bYSI$xPm+($G z836B;Si>7|O9sAEaEp<`Ek+8rC5H&MF;ck2A@VwL&hj@OXD@%7ID7fK#97Oc<4{=? zCD~;fwUqg^kcP-Bmw;QcDj0p$tu3TC5?!{qc#7-BYPG?UQ-M!$z1u<?ox}l{&4HG>wj1 z$b78QQaWfM+hv6?hA(7YJ4;XLUkiA+Mty<9$E`SA+6aQkXd?)>CBp?H$X$eMUv~)C zPxDpC)1VV{pU>m7x+jjH>GN4|Z-~$3c|1Owd-D-grw_&_W*(2v2#n8l5uXlPe6*1S zKF~%IZbf`P8%fATe6*4DAMw#f)Y^X1c@up!hm9Em@rjuOuIhN0R#cx4k>C~7es*zu z{-xROd{WE3!Y4Hg^i0b?7P|wEv`(KdscYa!Tfs+~w!b=CT{}t|LY&uUN8Ez!y(Sn8 zNXuqr#z;K_HfKlRaP{Aw9r56qA!Gm?4}x~=&g=->Hs6!2E*b;#3OzqlT{BLKqjIyE zaHD?Xr3&hs2@-s3a3o2+H&KGcPTM4QZ>JQ%E=`iI5GS^CvQ&e{c(cDHxe|LmS(<~5 zWwPwAuA3qiNb==G(22^HJXq>~8Qlmt%sMx=p%Dm5I!`P;zJ6w@X*>Uub+NTBaT{iF^!r-S?G^(~+$Sv|bmDmCd_Zy!EazZ< z;0)`k%}unr%P{d{3v`TR11at#$p)hue*i`u-8xQljN0QzX(J(FEc=L5UUfPI5v51Q zs`q|EpSK*#a*jxE;itaCMD%kmh@SrB7rV2s(0EEwub#<28kX(UZ5%VXL!M+yv} zGhNl8cTop+V(&rh;Ma(&_oa7I&L9!Grv*}oBoz)cv&7#$+*#x!>5k(}ce^`GKCfo_ zvYP)$;S{z*|B*Jsk5kb_lE>Dng%UvSDF}_;6-lG%`T^>QCm7`p1K77u;W5jy_0J%>|Mb`UYxC#OUoZ4mS3Z{l z2wl*h9eg1TpyT>8pO=!mBlW|GCGU5s$C|x_7$&DIuUAawy_7bH5N5PVqZq<)g3)t= zurCGx(Hl)z{u{|Jc5;Hb__xU(`}x2>=?rsw0|)yrC1R?lpExNPV3m%a;%obzveekO z(gR9&^izZ1OF4u#>8C#ZAQcjNwD11g@@+!n`mzs=d!$kjyeZ*Q!N=r-SEyVJXn4!2XzMLV7)}O){$=z`Fkt0VUloD z+ticI#4*On{t9mSRg5d^6(WaI*s>6LJN_hAU#_bie+kDg1D_VkkE@|_LmK7E9*4^7 zX-X%yw1K<~b#%Mx4doy_-npSXp2l@jPc)PvXsoRV$ef$V?v6RG_7`y3{THgTI!)wAM{Bj>_T(nA7O97DyiNZ`s&7-7 zN9vKYp=dDx9;v)Y*{?&B4xb`b={r+O7JO*34I|aZ!M+{N4}8<~^QtE>eTs&N<{4Jw zNSxWU0Hh78bJb?egdq$CiF4w_}lQWD}jyj`<|ZkW00Z z8`C&|J!EfY94wb-KXs5xGtyRGR=Q?8xTsV^yHE{veOtK+BztYyhaup4IK|XnUJCE= z7479-(zLc_w)^|CKCHno*`3vhm-o4JZ);9@EjhubuTGl67j0Q#yu5|Fv}HH8%hm8Y z!)Rd}HYQ#6P$N6aafDQ3b2`am>GC%0WhV&#s5WY_RW42BjGZK$HR~)-0 z!NZRMC*F`(sI9ulk0?~OJ$uT%=*3oSd3QOTZfk{4b&W1)#k_jTJ!wy^U6J*jC6{A0 z`^k>#&YtpQVm7scoY}oO>(^bbNAp{%eS6EhUV~$miLjGHE`HuA69p` zJfALT&SQ{29AYrIxfTNkF{q$U9wFBwbbWJ{K2jb-9GK@Qxe>h+tHu|}UggwL-^jnp zAqH=IF7(xb24DNR_aEJ}p%42TBJDZAVr&Ncf`2tu&Ru;Q|Ny0tm1^bo3V&467pj#ii{V`Ox9RC|BJ$ zPp&6Pu}#7KQC{jl3*}4_biWCPEW%E*Y}UKleraw07VJNp1z*s>Kayax{@H|`S}Zq| z)FwQ5{!8R%#H)>V2K*TiShUpkt7vC8Z^D9?$!ln(CKydCe)y6sC(^udwjo)*;gu1N z(SuK@;G#RVefSgwB+|p#k<0R2R&lu;Di4GMEO|7fH+8qlWobb;o3R|?c`TecD-h30 z;Ub>xx5-{?lOpeNc^ig7#sBQBizfXtj0J6n34DHvoJ{wGVNe5E>T@r>tt*!pP zLT&(6$uRiIR-Qp>u_X-RX$oV7f5@J4(N6F;jH~hHU%|21fT8u4!WKr=_5*9=-ZD*S zr1sqabF1XihglPS!M*CH z?Q^e|XHPcCYw4o~np5fT4RCa{W;Hj<4d})O=vsd^YqNaVE3v^R|4!HTxqrWI!2O%Q z1^gQV2TJ%?ZNOr-f`63;?7~*?@1xL9{ypvTOX%mWJsyg#-Aiqu=+&jPcc=;u9YClO z$}W5_&nW$_zB$EUfX^TjW8MU^q#aUuHg1RPL4T`{gQZ$IHRG_n+8APxaj;|zG+6Ab z`Cv)*hd-c%!IB(f3$%CUgC*JD)_^lZV|7}t{GK|DudNLh&_2Idu0z|_E*>r*=EQuR zjP2FDpJfZ_kX`H33usdke*p~xean6a`|uK@NKX}DIKNqhmpKD>-_)#|^< zt4+kLW}lPqkOo_Vz}5I;tF0V-X_jRD7TdG<{zlj@j<(HaT?_4ketq9KFk+Q!N|S4pAX)(KTNp_}}0$JfDxhp*qDBe%M!F)P55F%B} z*PGq`P0sNeg6F~w;kg5GU&7D4Y}SN8jQv5`6BrMB%I`3&HUzRQze5102C{}%AnX@w zh_LUuBA<52sDWX}KiGmB1Hm0N*wU*I_MtWS3_0wYJWP%SBbK^Ac2gf-liR=#J2hCt zKcEZTt}eR3*jVw%^rz}Lw7e-Sf%Jg|Z!aetSg&PxVL7QVw9;hwh28%SdiQKq{xG_C zPhnel_h;BI>D^ptbMF@SHfcju?&3Lrfr~u@wX?a4t7-e(#g*Bf`!KHlt-_squL^hW zqXKa5t}4R0F%Q7GORIcx?jqb5&YcgZJOt-P11sU&6IGb$Z*cCnRoKeE!MX1$3+I-5 z1kSxu`E%!9s>})>fpeEt=FUC&4>)%u7;)#eDMaUfTbZqV40Dwut55`U)!hIbPRzZL zp|*V!bkKo@diH@ZkkYibPFef6u#K^~*ek(6(wNPMGx)Pf=eHl-S31gmYEz5x3Uz2x zk&h?`ZA6hOtbHltSs4@?s4$wkkS1%q#Xu@$vrZppN{PZxhH)VEf$srvAbCb;nH&t1 zB12l-d-yNT9oF`{OVr>D`8(7qn(5HF(@Kdt=H+qjnAc2~PrG`@7Ap%v8lK%)<#y|WQ zY8i(>xuradA8GVr-vt}Lpud!7Z-b2^;4{m?b&Ro4J8)s?A;vLSm-DJ`>*1HqFeo)A8CiPE1CK0D1~(;660 zP-?=5^Jjw^8o$8?JY1Msv5~R4OdFL|2Q)E`pmcT_b~eITNL!U*@D=`Be6VKtV9sjS zDC1iP`pikSwt)wOirM(K#@$dcb5aA^<8xIgC7!DTJlBF!>}?0oyWyw~>1b>t;nygg zjbmw|BR-c8i~7RYm|k^Y@#BoO+14+NJ!nfuM!Oh8XpRGG*u^-a$ufse@f_cm$I}8K zvh38JHd%k#`54da80~4b{lVGndKY-wnQr`Pk9CEog@*RD)4Lgm!55S2U%ia6gdR7u zpgzVmbgr50nk;#!H~JVGS_oAu3^Do=8f4^^r%pqSPYvaIajhYG%vuO z{-ioPI^7saVf%5qF^5J6u?{|#F!kSWjN1vecDHnB!2U=yzK4c--DaHYgtXT`rrK)q z65}^$qn24_Tw|hXHCUahmiFrF6-K*6rRr*#KuZgv=B+WdCeUQ?hXSSKt1PSY3X+xNb;fpa9bcPZHmaC@3;qP~w&a%H4%!8iqu*2@h99$C z4Cf8y4EA%c(8ddF+|tkB{+H2jo+Xku`Z>*Bv$wBIUbOLRHFCW%7w?8$e`l)1{L;V! zaBCmmnHmuEKwco^>rLL9BGlAxjiZRmyqBQn9{uK4spvPi;SOfKWIo>+eJM=j&Au~w zl7LV&XaWXsi?=0@^t#w?gl)WCkMvqE*@sZe0QHZ}=s>t`KWg@8+qN3>U533drQGh& zX*>RLBmT9}pcl-ivBiyLY%^A&U0$e{w;3HNz3^N;Xf#u*-rZrGLTTnRweM~te6_Rc zDT|K<>-S{CyD0Nxne&Jv;4IBXnF;i=h3FLShd z>8SCri6)h2BmK=#v^!z^Qg%vCgD*Hr!>su&{_I`N+=I{|kJyOnW~+Mlj4_PRTdu0_ zS>q%LRhrqr!09LOT z80|2r-c`puG#(&Q;T;n@msF|(^E+koqhH=t`#u5{8giHUM4KzKIsX_F2LB`_*)p%5Axa6w{TOp^3^qOjhBh%NX-y?pBosurVoX7!MW%+3s}8F#`0|4 zzeYcL@+NknaQ6CNqigZi`fYO<&ZfUN7SO_*Y{&=Dymyn${a_5Izu#mzxP{X`d@v56 zyKk}qA7QRbxyjCc1U~=f3P;mDx3)J;DR11P-e`Vk6a{0;D?RQeGZ9l94ZX?YiOGw= zr=-LrQI{Pz@Nw`i(O<6V+u$=c$rMfE*np~a506^{@&`}E~bB-WcUKP34@t6TCL@0 zItG7abD13(ZQiGD2{3uea)u=>f-Re1u7|G7u-uAZA2(Q*@CF{KZiV7{rA{=CsYl69D9UaeLPG%b=eOLg~mmT00rs%@Gl%gLxXE!|QZ6_fE=yVEUu ziW_wj&ErugIS_Pies3Af8*onB9hOeKf!7W-os^ReQBBpcJ1ys>GBDhdN2W#Cq5CB- zj&7=U*kkEI%wwVTIJzm@z1I?`UJ5rcygZyewwWn`-^j*A<`&E&%5>M<3I{bDJGa;z z#v8XHSeYd-mCTMdjV6wVW8b6rg6vrJ<3URpHGcsoqzq`HHalzyBWz-v>57v;_OObE z6xREw#ev#I*NCON4j!~-RKNsVfHEJbH>t> zP5i>tR?Y*@v1O^|KFqHR+(UJBNf%QiiT3z~oyxPcQOou)ImtBkr0Ubhw1jHb>h6A~ zvQ*B{PTXn!i)|ZVilDJR3|=D@)PDz<{0J>N&U^-$T2k=s$UorKZ5w2Q*NMy){b3nQ zJDgyJgG|9R_5|}8Y+~qyLw~}1#$8H4h>X;z8B~`bV zA@HLr_L=PJnCwFW5UD19u>4q><)xU60bpSOi+p!mgi)sP76Y|+1go+$gX|q(`#9QF z?dRmMpe(a(26rS?XOAm7JW;1?G4&|rUpgzI`5%ME%#M=B7+{-lDPfEuIlDvj9|>dN ziWyQl_30kdQTqSG?!rFPQ5n?L$CVsz8O=3tIN`NgJHj`AS*8uL*@CEl6L#mAsReH= zX~OCpH!YwGcCuafjq_Oa2~+1{v$ZEo5xSXr^MnZ!xBMMy-;<_vB7L=^-v4TJ;_9E3_}enq*pM#|ElLo@p4R_tV+T3#OhlFP+`E zVEUfEiDE}BmiFw*MN?JB_fhZBfes{EHD7{GRjyIGDWyOBsW-l4C{z^cvr1P@?rfc- zr3y{i&X)dW8d~Bc_VG8<3wmlhdwJP(fUeulcKvP&q06_cw|_SU5truMLCouuSk!jr zbJY|{Q@5$`w(3WyF`6B{X4*gY`&=i!Sv*o3I6gR zdkgcrV;VxYZecU;m?qH$TiDw>rbYq8+1|P|{F*FQ3*eSKL+NO3wV>@U$WlAsHJK>w zJt2OXT={En{{0&%G9abOz@;Mrh%v%r*t)emj8@W%raB)ibkRtrD>yGtP|>~jUSs}J<#8gFBbBOOt4tUwTQ*SwikFX*TNSIPOnVmT;KuGt+RL&{JaL-kFBub7#VgEieI1VlZs{}$^_HOumg|KS_Um?tw%vI>d4eBn*>_|yP^+%(5noQrX zW3V)6quLzJeloqimah+fa5i^BMOYuaHPV5l`IKIUo<>5r$zBGJS zQ@k3;SfRpdU@kG&0g=aP4OQPc4v@Gs4#HU;ods)xt(R(=DVKtq(bffT6}~RO{%C=# z9St_ax&Z9?x*){-r`FPz0tpSx=b>d`y;eGSvUcI-2>OqOEebc=NnKW{iTN%blbV{X zfYokI&4&q{u#CZaz?X%saj2sXiZo9r(#NGG=fBy@RIeyAtPEn8sjxCwNqnv?h1fwJ zin)BFWIdP1G3uRuaVfhHV-BJxm$DBrW*?dbAL7KCgXzAd5Dl{z-MN&Fh&9L1bxSeV zA3$e8`?>K#sk_QYrafVQZ}zykc_D?rP}H*g#&PBzu<-K21b;k}TbrY3!zC=PwRvH= z@=NeOKBf6(*sa#)W&s};BZh&{4AW}Y^k+-(7WE|GGyTEA47 zLG8@p^agy?gBgEnJF_QVSxfe-v^N((4XJdz*_Zwc2Jv9{&muMgw{XIiczBrOisepE0MIpI0WgVX`|{l10S7afYq`JH0CULwm$2717&)nxMEYL}>_!q_yAx~| zr&Z$VKN~j}^wTQw^gng3dA0T=ko@=Ic}29Z3i*F9O!V-n#bR?L+?Wa(|1K@rKLhXm z;$(lN9h7n^id;Wxx%p3MF<-?T z*W1}2Yt8cm#-nA4+nem*XQt)*Zle z{j5D^%=H6Q$n_6Ens4T5zTY8uk?3juPlwEUnqT^}G=JV$71I1gkl0%=!|y@Z^PK-j z*muW8alHStbBFBh-RVn zNlapmT?r=9#2PhfY_TNv`g_mr9boc#eSd%4YoFblot=5+Derlv`7CEBg%0yEsYr+U z_+Ym9AYlF!Ui5&^GyQ|W`p*IL!;H96!{a`K^~bw&eFmBWv&!oTUKaARx4g>=?> z^NaD0<&+C*2>!{I-Kivj@pVsA(TJnML$#}}thNh2h*SdKpQPXFDxs8pK{N9k_k3ER z(B*m31E1^Y03bml{Wmp(Jtf{qj%?=y*{*FNpV zpB-QOq~cG$;kEGnS2`5HPP6>D{ zt^yv5tANM;sQBp>uss4ExA&HNGSmDIi%?K&r378_k!zZ=aM!Q3Qj99g@(lJDI%Kju zPyk+$gFwmg7Iea$x7q{P`nrKFhRm*03snxFGZds92PS!9m-V*K9AAw3*hqz+!uz=L(&C&p3j=63*=0q z;zNtcGo&Ki+g}D|p5K-Z2FTsnsJ0YcTpq$Yw52bK%QeEPsIDV6NTCNa13!Br?BxZG z2>YAjGBC3<)UfvrgJjtIZEXZ_j%NcxMTEVUj{SO5F4)EiVyQJ<47!Oh#u7cRG5$8ZHAMmoCi_YQJb=<6&bXWX#?g4@({;NBV9G z$w$i(LRULm47A+ueZi~(w48zaf1~BQEkzmwE#DUOztD1r_YJh%=6yF>E?HUbCB7^| z>pm|5{uZM=dT5<4Rgv}Hu^w7469c*S{UQxn76Q*J(sb}Fc##)@&aDof->)W54r?h= z76Q-B#C;*~+&GOR#%|SXt%uhu)Q~UvPHOQscpl$Efaf?is09Hxr}J$!W$d=|pt(D| z-m|uh@cK{93=CZ%Nd|`IO$CPTA=qk!*Uj(B2(O2iaa+wsGOT98d-)(b*szvhvWT%$ za${6_uVO&yrSBO~8q={5UY{j8^N6f}!9>hJ52}CAOh!;0{UjjhcX|8Pa&xm|lg;bC z9umQ|07*}5XvEcfwufG_&UQDFzS=K7-bb8jPW` z8!0qqh>X?9DYS5i9LY|n(7_>cFw0G$>qF$|;C(4*Wp~Itq^<{M8zJ*=Qz&MrT!*bs zF+%2ZhsyP^(J!4HDxX33rF0DOVe(X#RZ$1gJ4VRB(0eOWyHWC1Rxg><(ehMh>12_A z0emh+>qg5-mYONbITa{S1E8-l1NnmlBeNbgvc8?Y3fT1$lXa4t>04QuH)o8 zneq+Emri9N4=jMqg2ul{q?mCKJS6QqPVT~fPNbj4$-S{Fr2&&SCen!U@^$}yiT{Pk zy%TB31i3!@Adz-W0JB;o^0O0UK;pavPq~bs`0)g~`zbzBF~KmKqbA7+iVu(HaoI9} zaRd!_$>C)~{f%CE|CZN+`wP*-s(mi zT)&ZG4eXo$kHEfq4oIel!f^wa9V-BEH^kVpVvRU>=yDlx@Vtn<)ddJX>@6bnu>t^B z28DMK{@!L#dhA=z1@9vE-4kyiDZuah`uhg*t-MK&H|KeEswS}SFW3MiV{diW9UztI zovR7p+a9wL?}0?ndyg5>e0)NOyeN2%__7}IF8Q_mr}3X2@Amws$GazgBOCGV3V6c} zfoqG%>$s`{02eh#YO`A|Uo=PFR5c&}>a0mYTvx=k$5aySSb%>=;QrtE_f@n=W8mNC zg8mo&{TT238~^sKB=GN6lNp;zS2e&dEjs{1(z%2Y)V_K^nC=}FkzFAK{AEQ00fW78 zF(nKHT=XzZcUO_J5CZNf?h7H{b`?3I+rB2>`4!#e<1mVV45a4&UUMeH7 zUFHPJQI5M#$OvqI5XBMLZf$0m=&xhmZl~mi%;y(~nW%;VeCwT&M|mC*(C;Hw+`Mq}x0IatdcntttQViMDHqdX=@&@{?Q{F(os4hlQuu%MhydI{ugc0Ok zdrAJJh%o?yF!vHbUycZONs|#1`PgQ}M2z6}@G?el`?EW84atn*lq5I!t#D6XiabyT z9sZ6D7w~tE_=b*r-+Lef`QlEGa!+_DBg&0C!|*?q0e^9)heWEqkgJ>gQ$qAOH|hlp z8{*On4wXTidzW4G7?W%kf3fo69ukPjN(gDs)Wjb^yRSvh4RL3nTk!xPXF|wXp;cup zYoJ8g<4U=aoj8_90!(yMOw1i?xMnbOcaV=(+ziJ7z6=##Z|yvaTRd) zG_I$wUwHSD|Uk!^M1a{Q4APBrsqrUN$u$Yw^6r>P}U8>&~px8yYFN|VIGlIZ3;w}Bz z0L=&j52|euL16l)wq*u}f3gxRz_Z*zb&@RI+2;;gpJW-r#yTi0*-|5Hxax|qL2uo7 z7M0BQ#DH}gG2oHO7Bd1G5mgcmbN)je3(WZ`yAcXLBGkZ@Xu#T|xJkv04r}obW^;HM zL1A-!3;H*gy*PrxF@m5!8iE73>bN$ikp;LGe^+X383tX*NJ(F*-Q@EflzH*W z1kWUr7M6OF=b0WH4tEB5%}xI6O|=`7Ql707zUM?jKJr-WEMMg(cte&Zo&>z*XO_X3LI0GFF0eE;4S0$w-trFSh%0Z9Os}7K zlXVcrYV3P^51~mTQa|=2pPbhtfC6L{ELPM5VBEx=v z;_Vh$F>k?dz0b4P2uKRZW<;HTeM0+|SfYcE>FJ8;k?HdJX$;8x!xK`MTI!g-LQ%HV z^(jUDms;wX7UC}Bq4!C@7cXBE8ZJjp!K_*YHOJt-*(2}jl()>%ge|vnM5Fyp?6PVE zqSvmnB(o-u>DDUCRA=O4QM>{qjrAO>ElH9;9awD%kyL(dwdGgI_p?VLRRNNo`-pPa zSmI2N9-{u47!R(u)=~l=;K0!>^ib|Pyp0`<)>+~uL}u5+7(aSQsp~CW*!hRFdA+5# zX)oUW@r`#aw*4Ws-e9@zKkT9Rf992Z@{rOtTI#dT4{6~>a5eoQ-?7mG41MMwPl*f+ zed-@Nx)~*k{l}X+o+;9Tf3U>@5Iybz_y5|Gh`B)zsP#9Nuv!rhjQSQv(Pi{!1t>Zc z_x}zrBRc(!WjuR+pJI1fg4y5qsr60^7C&nAWT)jhTkdoN>6hPIY9M^Pyox(~{B*Y^ z!ptIk4ddJG2N++|$A5WKvnBEXA2b?fefSw*TE8h>)Bw|-fBGGQRv?9rqoIG<5lEp2 zlJ%SAMGYwZ@~{Pa2441aN0X1AuppX@l=^g%wYpCG8PR0VjSi{T30sRi#B>r0{RNta zcl405{tv!8_7}@hmg(z`CT~FcjLUwmjkr$F@^w!p*@C-!S-wUzdD~eFqRDu(+3#p; zWT&I*r@vcniibL;MiI~l!Fp~nhoswOi-D=916<{Ym3_7$&D<4EcU<}X>y``NE1a$h z<0ySM21=X%X|emBaOUG{om-u2>G-ly`ymz(_rMthdwNI2}Km+FXP|?pCBCYkZMjn=xq@JkV!} z{Nk-3a*R8DmdFHI0f0tFuC@_CuI5k*0?2s|L@U8M)*|T(*cv@)gySKm?KXiZ2gyAwf<==~xj&UTnCykY+?1Yo{H&$k_KaNp-vUH@a?^N zAV73a#Fqq!7FPkHcc9d#$N6%A=+7Be>XvA&v}AXVP~XElyHLQFp%hJ!s-B!#Yipy;7t_xt46R(T|0!d|+G9 z68uPKB|JtsBoteCNMnvg5&gaZUNhVmhS#qTQn@b5eD>Qx+SLUTiy(2Eu4t5*2l@4` z$}UL?rqv%QJ%oSit_)?@574LGl^S6ORM!-UX2e!w7Pbt# zf8axUD!G^|`vXOnw}$gxy_I{C`SO16xpQ*HqJz{&Y0ldGK>M(CS&99@d+yrt?VmQ% zsKZ8cqi6IZ9cJMGm{^^>ZbTmmH%kmY8KXE!m*dhPjLo`E9p=QYTGy`-F z8i%>I_Zp%Q${4CS%}*>lZO;u(D_xHN{n+$k6o z$@+YYeSws4{&}|2K#Cu;v!D{497ZL2LWbmddL^MosN%l3T*Nefz*_`Ho4*sTd+QkJ6mw<(doL^req~rJwzImDA&%}me zn}e(nsU3oI4XDvd*mbO@U8zK|rTA~9a-DVALGxEB9ZWm7d(YXOUV^mM$|x+fn6X;v z$VP4FcULRe8n5JbA#aI%;~M3LB+aG)o0K4)vrfT&J{tdggYvUvUi1~pukWukbCc3q ziciG7N2o&O{PxI`UpZX83h6f5BfC(0Wb5s*ML`H=_Ll^q3gcgIRqjh>`76CU>vaJ0$2L6J2^c1Yr&rpIRyTc z;EtWjD~UbaLh5(WyJ0y9R9MHb3tJ5FYLcUi7tPqD`14BND=AWZyDbHEN-*cwDM$WD z6LrFbF2i0mL_EL~1Lz6o^$bz!33fervaK3)?tsHY)dYFDl1gZK7NIl_l)d zCLtP2*m`U!c0k!>9=*xUR4Q^1LeX*)eR@#2ju}fIA5wf^{Wj8&!w`pU8%aH)>|_%+ z(wGD*)-)VZK9G9RgJTNTLLF6BNbJQ1ioUA&uaS={j1AsEyHX$)&o&rlC$SE0I&3hi zox4HEMRof22gO2_e^k~o*9JQKqmpjAwce1B=6T@l`*=4`NoSkZQ-`|N7~cM*QeKi; z(|}(vvRi5t#ADA-3cAPV$oZQRM0@I6L;1#EglYO{one~BomOUIGxW98w~;lPC;z6@ zl;RhxEnx7-S7u`+nNZ>rI)n3-xIFx4AqM9N27h%%2+d!Z3@C)=z4Jn7daeQg^c^YF zFDe6B${NbOs9ce(eCzLme@DKcotKpPJ}bZQp6fMzCIuZ)O3|Rp@OMMLFgRKA3P3~p z7Zi6?iR8N1-C9k3+dz7ntv1-W8>#+O`bsPhdy?Hy z0>Y|0U5yHf{b7iU$Cg4wbeHz)4do0r59V8MD>ymu)0K4aFQo(Piw(-M(5T5PO&BQl zv-6Ry7Cz_Ravt_j z_?-UB4WILHxzYH#&uP0{FSX^!axen(N*~kK-64Jy`UF|5TTUaMC^(~lfB!_mw(47# z>Ar`<_k1U@n#(xc&S?~5DV=_)Trp2sYUruqYxs>$V@;m4=jtktCW zNs9_3uh;#2$-|ijzM|c7@>N^-J-7Qnne&9XdSSQ5Nx}`l2IL68forzMZ=@noVZRYT zyB*du?BqhdhV-3gJ>`B?cR4~v^jG0Q@Tzb*94@CUwhviIr+uv>q;THC&$>ZkUoYUV ziwb58SsU#G!KUe*dNzB88t&G|BO zkGaTh&t0V&4U4q?Ch8t#h0I@`Bh37K_U#-|+Y)50XkE>w&7lqfxH(qQ+REH-4qnWu zRub?i+KO@NSF`!8N?-sRI@>V!*a1y9_nl@NGLbjiKoj<=);3c7MOT41?741;LwU5W zd`+)Hz6b-E=3DymZcD$kny5mI%Mjt3HG~Ln%BIL#*6wUhc7ZbU&9$skB^HrQeGdUT z_KCOt!v35^b!wwxduJJS`L>2tp;xu7W7%i3ghlGhM$O`P6RbNV#D!KTS#f5_+q~(>x8F*UWmJ9iPfKHy1)Zb*eDUft1$*LfvgDHBGawVDVE8t1P#) zejtg-i=v2Ir|`g5LbS0xZ5xR8mMMlME;_|%*a=fa!^ZOFA6VgG=1ndr|IiCY`DNi@ zzSqm29br$>*D6oOGmmXT`Ei)cUcSGr^`faMrtRaLxo7g;xM|mrXhrco3F5l4BsRj^ z8++_J=pRD&B$UJT!14VF^$)}zs|vdNPx}+Zwa4lG2{re`P7`#0Z0CIMLn}7>{O41u zf7n`ymUpsFV?TUK(VeZc)uo?`&Q=nRLi1n0_*0(S*}B=xZcOB3x?9n=-Y|jIe`u>j zoqJguvsDxL=3dsRjE$N=aed&2j*RC!`&eh{TY~qq{%X264t@LQtP~~pxAtd$jH566 zTNByO&Hv3c;NcQO-n8p{$cg}dp}phGef%8N8uo^UBB zGa*RHOw;eNJVC7T&}mFwzU1eoF@d?pKx;1v11ZZtv4&$fDT^N*Y(0sUGZ7I z*2WTT%(8~E31fs-#Yz_P9%oHrW5!Tle_IqKYzJq~jiFuRtP5GKF_b>unj7dn1~H}| zaUN6{&V$0$D-;3SOIc}eMpK;$)>L+9G@m)aiV5~vqiOTk;BT)_t#jCc(e(OLYg4fT zd6IPvdp?Rko@DK37Hc>n_ry>82L``O;GP6=?Har%;WG$=pu2_b5sjYxQSSbPIS_!Zrv(b3I7y$LeZ#k=!f+Az!dv1H*TvaLx)Sm)uCKHoZo zwHr=9&9{!UBb@@VOzFHg;g*Rucd*svpOf`l6Wcb7(id5Wh@RLY>o$>}73n&6-pgk# zwnmstmZ1fL;7u2nT0dbghEUovNW<+RG<%u#4;AlRs+uXvk?n7G>*nmO;QGOuS^H@V@-F8^ji32EdhxI5+8$geDz&_U;KpnU>h-LZnk=(l6!V>yX z@Lp?b{O5fO?8eyrhTXWKppSgU&xL~Kcy+z?@lb$j{Bz1E-JvKt4GNZ1W= z_1KMrpoQHif~&`F_<^kK%Mt4+j8tV1EJy(Fm1|uDH{RPYBh^n@Te3~P`P7rvNR#L_=0seCJqJi-+#AmXTH6=qewlVa!)I`r1Im^x_9SaT!G55Z$F~HuUe~$lEC~72T87p6NVMWm=_Ap8GbJw$`_x7XUf<1o?xRnVUE3MX zi^bK;t1`AEaiyhrEgQJ98~^gA73YV)L(6YlU$76m(ULp(;`d#t=_ITF{J-E_KI_WI z{AJzk?a}40VBCZ*i>pVM1ub;>AGEYbmmh)_x-709U48`Gt;_o)-sq9Fyd*U6FuE&3 zqenire#}~R=C>YOV~emY9SzR6cx7$I)^wy5udE|Q>f=bAh1Bo722O0&k+V0}RBT({ zVS7{CEy>iY1N2uM%+!k6R=JbsiR31e?SvG>Pnv8&%rxplqmArEY#D68hcu#yEsk~h zkaiTY9n$sNkts@*2mR*Ld~EMBwx~V-$zmJA*sFFt)n@w^izb2y#(6d0=&)(bcUii- z@jfsbZ*e-$b=uO=<7!KhMQv4)oOdj0L*tETYc$>)O#Jk>C9*+nMY|1QC)*l|=N(|{ z$70&@Apth@Opkm(fhADntRP;agl%3C=4wN^A-2@`2dxVHtKikV&hT6^=8izH~!c$L#JrWuxt{#p16tvK|gUHmQaX*6=8YiwEjT3Z% z#?>lk+s~S}qSxhYJ0)z<@s5oGU%U_Ah`oNi%INy`1oziQz8CQv6Sn5q-r=tDHZrq> z_jzPR+fK$_rx^`jtg@{Edz!{ORJLtq>`)r1Rc+%WKklk(BgQ^%L6NbxE38@zQft^| zO6BSE8ny-)6}(o%c0>2r@X(WmCl>Y?9$Ke`J%)!4z|m~_y|Bsf(uX0Kx;=)6erCt< z7vf&nWO!+v7B*SPgm?~{997FU96{CQ{EIkS7-JWj@uRhE=b+2j2{*~+^!B~n1XZ4t z;_}*tbJ2W1O}o&9AFXHW!lVjRv4IT}vqSi_1~%B@FR`6omNm-0N&#z37=AUcuhE2> zHiBSm#Ljw+AQ+Y=!bOKuM5=8p`{+GdpK3c;qUw9_)Av$br^n$aD_r&SMJJ6M>`MI-UH&1}Q+ef1{*UP8ac z)uZ2n7W(}a%;gi z8>9u&imtXr;>8V+aky}5(9O1-oqCtw>Snvh%--)JU9t%=^jkgfp(h9+*RYkOF+FXO z>>9SB>uGy27B63_lqpIme7TPD;G*)pgg=M;=(JmYblNRH#UVfXy<2|PLI*tZ^BnS{ z-@D~Ur`__S)7a1ak`;&%8o|r-wqdX9n)P^x44cZ>wz|~!V_PuWSeMWI*p|km0Difj z?LLf6DF1n&t(dp7Sc+S)=EBcIu$=taP+M2VIwezw5w>ja)0j~Z ztV>CTU?n6Qg4K331ZzPOogHo4$9g8wk}fmfLQbK8bbX$;vBigIM=i z+WdUpGjK) zU%u1!LB1tx=|(Ez>ak>k7M5%d#Li>M=7JWMOk6#dY#wO0CA%o`(tF*OtS6*WSh9Be zY#*}^qxsQ&wx&hc)(RAO1XbKnfo2~uOj&Ov6s9cbC`?($3Vh#D8-gomqWIb4Hh{kq zQS><1HpUbfk|JYXAIR*Y!!A%B~yNyd33W!F8jCZfx;vy-RxEBV_u2ZXwfY zw~+OOHTQH!3yQy{{cM4J}yg<*M%)B%O_nIg7r_CLV`7{ ztPrd~>UP6chW%B>kgn9ShIEy^3F%r{hQ7RM%Vqt_(70PLW$$Byx?2K6l_l$K+at-r zr8~BFOzhoo9(m6ei_MS1c$Wvlk*^G+PyewsHL)-e%P&TE{;}1Tym`b!n~AYLr78Nc zEg-C7QCB1ATSOxx6ml4%;_1>f6oK~z`*@GXwq95+6G}7F?ScHxGh01L#9v<6dPos` z!3&Yw+7Mdu3T#;%Lb%B?@RDvIExmtQF__F zguU1$p$_OetM(;aK{UHA=&oz`C4}R7JPnGQ}!)6q9 zMHFi6wS^kHyt}cfiXDy3oknAqtZuI-nL0Y%iak2k-iD<+`RQ1@g3Zu0x>D1g=zB;* z=t%exu8QeF-)>GYvBtbC!R;FJT6%7!7*g@_h++le}D&K>u-MUxLFcb9QCW=G=V= zIewXGRX~^hVqby_bSUT|d4{Bv2K~-2hNOgnZvNXon)RDKo$qaKH%X>XG4Z0~KxZj_ zwFT-bRpb#Z?U3k=7K(0VKPc9vw6gbL_bt?+H8^-d=U}!+T_y{w;@&b29Ly2w65d8| z@O_y>T{=kSmp*8_OSheYq_jtqJoDk{?d^=QVLsHMgFTw{@u8U=z{U1RcWIH}VvI`) zot*Z855L&K{#urb(}f=PH*AlYU+ih$$*??SL54jXLI3YFpg=|GuMB$wM9=Z|Nbz>K z{`PAVuiwYMLuOw~{PiHaRq}Avj&}BNRRyhcwT+j{0oub=4Yc5@mXev~1TDDwAUQM5 z3$%x;5@-)s8R&ej9vA|yn!P2|I&Y?TDBT%qFQyELb}2}dniWmfVfNPkLD8-fUfF5# z$f3ht6!AJ~!G95ZD^jK6_KLJ>m_0B2OE2%aRvZB$qwyo~)89rel|b8&dOC92Jwr{S zo5Srk-xAR-n^&gqU+;LiM4fU)Rx{PXG-`zXGwj9eX@HoK_WB`JaEru0DaffJellK= zk+WU~wW$C&1mXzN)0AytbI+0 z{f${Km8h>Mm0p@cTst(@p2c3hrqoP(kc!+Rk;V$QoPk^%idvfHX4)r&Y<>NoT=F7} zT(I^C9Gj=c(#KhLo5%v}^#v>Qri(1*t1BpCoV^ko{+iOq*+YVFM!N#>XZoCIm#{OT z_z7EslIO`Ol_+SG7Qy$7vk#Nl%~upR0h0aEYnnO%#-{OW`g;OYrAjfE1qQ~WD&kGg zV46<9+Q<1s`vMbN`I4tiv5%0<^BoSx5SZPk7(O_WH7ao5$w4PjIw^*x$PIILXC|WTs&}^yn)42=>Jzs=wO)rjXub z7t)(-U2odydXrs9Z?bj0sjTZwwyrmobiK(gq&L}x^d>uBZ=^LsZyrAc3v|6Hzt&z% zU0&IxpiF4#?2N6IsqtEShrkw2ssy0qwHMd2sIi&l}|bPP{R%OdZwZe%|<|K z-3EK(a9`wZcdJsgAspER z2zmD4ZAJ2Ae+yZsB5Pfdnrwq2Aq$~Mckst_k%dqs%XTQz-Uk%7-5wR}tm1l(KhyVD zcGbkUgd&x|Pp?hqD)j3R$4UPF4!c=wZrhgIo3YOy(0UF%8vlTNzlI*Uin(rD3J{uj z(W6H?4L$nxYoSNy?(u=&L66v|d)Q51ElJ8QduulI9`AyMON>3fOWpU_Tl-$R3y!pe zHta!gZ{ftW^LKgf9($x>s&&U`Twd&${T^d8Z&Q(6d%Ew?+wSzqRrK_q+$LzxJA6T| z-B0#EbMwC{^vg{;{mNdI9-X$=g}bWttNo!zjs8NH#iK@dL3`Bb9%zpm-3Kky=zgip zvLsPPh3J2Q501=;Q_a8g}zf8gUT}|M5?{auE!_tTQ~{$AifTlNpo9bQ%m_^E()h zL9UcP>^Kwk@HN_X)!v&OxW*%|30Bv;hG9q;thj5``cHeBv+Omn@Qq-3q)Ym2Mp|k9 z&7bxf7WVTM{`Y;mBAJF=akIX}-}WsC!Cj`K5A9*>m&%M|=Sr50C)`_P(+2Z z=?xH%ZDB!s8Xym}Xn^d7nQ13Miv}0~dJkw%1MCIuX@Gs8^X=HRH^Pp6f6-&dY?A7y z=4EV+aUDl2VEU05*T*Dzs{vF`Qj<#NMYN6ik2yPngb`AVFlTcyaM(6R7_&x{$<*4c z(?#0F)KXer23{1_3Kh!RB*pOCOf4&g{DWa$*o2=fP_d)=#vrk6>oM!$aI=uY2Q)TpTW zNO{TUzZOj|8@?+n+A(}L1Npo9AeRszSfc z(G^u)8CKojb;MEt4A2Y750r^qyx!f<*ErPAO<1$~uAe$mG95bO_Bt1es%_Z5Gd#8! z!iy~B48;YgKRJaL?m?ZrFf5E0`kmtA%Biuk|LLC#88yaS4Be5FKT~eBI>KBQ{}~7Q zbg!faNpa|piazKH=s*hkqvGo6i;6zzD%_7pPoy5`)u30QCnBz^VX$^ra&(cXRE%1~ z)a55LZ3(bPP-cwU+-D~eq>ryAI;62=ud43Goaqx))g-JowO7N%XEPGyW>urzzc>ca zvYBcpDifN67?QZS^vn^&_oFPLyu1-Pc9TC(%QJu~b zexzH8YJHy#$RY#(RJ!1B(cvUD)ch(JTocEWQ;}pf8vW$zxRlJxJy|WkD|=~@c~f!7 zF20$E@AI+A>Q;$m2+^OpG_DSW=tM5vsskaK=kHoqNQlr8%NHV%fe@lCb=Bo2 zVf-6Fh}aLug;N~EzB|sFHWK0!f1J`9tLe@%#~}q`I>H{HLs<{pG*$x?)3_sUoBW`a z8eqaqds5n}-F?40>`smi^+ob6hxxd+YK-h3aOl56<9kR5O%0N|sC8NQgS>th)s){A z+k`-`#}}eO4M>Tu*cQ+pQ=9`@nBvOiGt;($7N*zYq3Y_y>AkU#m(-da8@0X!@v^+5_I? zL@#x1*foFG6brDGJ3iD?#Ae;Q9)i!=g3r_&%F250=dpd&5t7(~zMuLDwuUL&UqwfH z;y#KT2rV7CkJ1LJX};a}fq%D!mI^SwFs;izzGI;3ZxIo-k*ZZP?cMF>`=e3nj|>AI z2ga)5m|uT$tXc_?=@OZ08{dC+A(QbU6O*3FyA06#fJZSL`kGaxdarkDv@_llLgT(dxXnj#ytj_!MArom9=>FB;kW?Cj_Pg7)p z_B6#f(D`2R!c@@|Z@xuSczVT}V+vAWy^CuquBlaGDSW!xzIa~oW7Xg49P6nDRHxqu zXw~WXbTu!0EwX{7&hH%S?;{_9>Zc>G>BtMHzJ1ZWj3d?aA-$+q?ttnXkiM8?D)+71 zRCJ!DHVX+yj)gnLlaW?Nj{3Ke8#={%LUU4)+rxKEu9xAZ-tvk_l@o!Sw`8kg&j%zU z$87b0xz0{hH``AuKYxx|seF$7AXYaj$Q(;2V|AzK=@m}{z}KHIh$Tl+4R&yjx+>)E zH*dpm{X+)BasUa)9c2*)o<48 z_8?aDo43<>QgLGC*L3zX7`B9OC~|??9n)G}3)EF%wE~2`6@X9Zo+rR0^6(nIpSM}4 z=3x8ZPS5JU67}l*sy>Bma0K#-pQ{ZR3*&%ax$U48%hg+~&kjCwg^Cqv ze{QE0tKb9AZKt1BsfkI)wxb>*@`_WbMCA1l?g5^DdQmCa^|D{GYw@uV*HcHbtGFrA zRTNA>A+lwBSzIlz>hor+)m}C>+Nb&M^E8tke9fMyuRA5KC_r?Tg+mOs~+?H#}n@D41x57d%J-4xY(|s zJ>lMNphdV>Tqph~+?y$xT5fhb+3)tL4a|AzrkX~`x8Z(uBYVDyKi;oy0;q6%)l_p%1|A^h>!SC6 zgWEj278;~a%|YN-rDeaVv;$yX`Z=dDv43dlK8T4F^^-^jbzlLs!S(ubLThKyk{&}oQ3fsA4-ebq_ z9(&#dBH*#-O+kCQnax0Z?0Iw0!k+iXXiy8#!k)JPoebJz&r?8q?0Fr~`S#q!943kR zE};$sox!xtyd0z4JtC-Ig6N19`#> zG{&RCW&o}Ao83{F4PL|*)q&Q!wa{p-wwj|2`(q*hQWH-=caaZb)ZvaaqxF%E-ujKpIG$O|-RHRFn|FzJgy(~4usU0SX>s*v zx;~(Tdk>g?7qkG=;_3#|3nbI>*}95H(!?r`x;}9bk@R!AmjA^X&Zb>4jzrdcHdm{u ziIPt={>?p8Gap2oMZEZZvQ>99G_7#C-Q$4jjs|SGi|?%N=q~w0;+0gq0wd6ivTHal z*A zUb@u7=+spu>Ab_w$a#1z173&5J0?gft&Vpz@QFf>8Tdm-*Ar?xLe06eJZ2(toZUeu zYdb=U{ETOp-l4c;H7Lx-wCS%uyj*&PBWk^6Jlw?-gGV#?o&-lxEIyb;rxP7b*{)es zE(tQZY8K5*f=o6l?usZRlXx>fpsUl%_w$y?j;n5&L@9+#a=4}{j0U~ysK#c@;OpOo z;E7?f297`3rRjWELm`N*rqiudM>*DbI{7wsr1{29N7>s60jlJZ8h)A$ zkjoQ1f5MzDc|f#gNOM_sDjr0d`FDRfc7Y%23qg8mBgqFXuaPSgi#sL9wn4Odz6rY&R4>$<-*Um z9wK7O;e6c+M-7R+8O*P&bYP~%fWab)e4QN{Ol%Dd<)*>ZdkqYwRKj&rF6c9(a@mC% zCff@QQ)#U*l-cf9$#%EOM_4iQ3Bg7N^HrN1Hmnb%ty>%;G4Y^cj%cOf11bGW*vWna zY225vlj#G&+bzOQ`oqyqPs1Ge>t8y;95*m5EsUJF3R4;ImE(eqJ@0F@Pl-K_HYQfJ zFAdxepN-kl`yGv)Mf)PFv7()E@)NSs=+%DMO5NfTG+Q=#l6S3U&FYe@a^JS5GWgd(ow@S zt+yM)pFinni9>y=)TXLGIhGmJuRl3Dvxwf5TU8CC_CGsHvMRmZ&i*d4%B@lxM`gjf zna1>TyLaidqcI!Ri#I*(7$CZ?$PT`}1V8_)0~;0S_YKZCj+j5`2{SCZvQ+!5qXD4( z$=b$X6|$AHYSWyvj=!V;$~x!xMDnFa=Nw^p`DAV3ybrM5J?P4L2Zkgv@C06at9fh> zk=;`qfAIPOOu~d76n)WA9ne0jw%%>54ofRyVc@v<6d!p}*nvN~Q`#lifsQ?B#U;qw zyFEy`40&r?!gZvOysd>%@Wg14LAKYa{rtzvjy$)#-Nqv!Z@-t);F!-}hhwh#5ydst zf_ddXA#`kQH%h$exWy)RibPcN`K|(;JdsdG7^9@8PkN2(dQkh zX{;7R*Iqf=I1UTpg%FFYf(#qKcC@niFaGeq0Ur90)V^9gJ@C;Qvm5OxQPy5~-1G^E zmB&rzg4QiW6vjJ1dn`mAXx&X$K$sV_?xsQS0qwC6dqI0F#6HmZ7UGdbgPX3^-s7fA zS~Z6)FST@{>ll({)Jmj&1GFaLk85V8)j$mRH#{uL#4zVg2F7q&sD)TH~Ph|089gA{V2Vs@4v}Ao$e7aP=+6?J4k-br%1ow@iF1#G}{bL81}jnOt0Z$>x7RpO(;?!XTU~ zq4i)-KcK`wZDrW^y1M3vcqWUUxI3gO@(}833eupidWc8V->t5257%1@O)brPglgE8 zt6ghdyJ%jR){&*P=8wZPxb8!(D6Fj3#dmWn@Tsft4pAsN;xp4C0j(=#Swy};>q-fF8EB7E zE(h&V$`zpVm2z|)D5U^5bu}z{-P434*o~R0wVH@HcP^XPgpM}Qy0ei@D5fD=#2M&X zCl`!Jp+yP?6OgTFktYpBi|D=W4R};wK+R3HYOGgdj%ESxFQytTGNrlJlKqy-FE$rX zo1~J`QY**mrcz8xE!9~$72FLM;cE=RYje{eTKL=OXM?jj!hY^AFrDXRJnj>e5vU0}`CrRjVY0(e|!dOQ*d)vi(^!I40sDTLjCyX=7~J!ipl> zY|&sVyP?5~6{+{%29wC%SDVDr>eBqa+Ej50L0CU6f7}>NmXEa1WCqe|rZ-tW(n6Ez zNUM2sy~%W>RRuJfEFWp1$?}mFnydh6RqQY9=!QBTJBo2*8+96>c`K#8Twr;2MlCO4 zN?Qee2H7iqEa@#1It9-n1|)F=$+5T5`*rB>C{NAeDFFi*G_yUy`|S%c2Td5ByohkF`hR8D>+8PCVEk+F|dhP*zxHY zXkf2E*Ay9EaIY~9Sw@_}6Ymo5dzIS58;{ie6>Etup2W|K-x^vKMg_Gh0h%@5j;1*{~N!~gQ-7h+vG8|(0G`9PI>dS;#BW5tv&m(CPm*6CHzcFVJ=Kuy@8cNr50#^ zVE+qgp@wnIwKe&eMcPly+_i>z?(8p%Q=cU$)4m$yzZ4~2TZ4~TswqX-yy_JEw^ojF zR%_YpNp-681q{=j>bx(m5_7u$-LpoU%LZ1b)@$+ay=pX0T-#UYn{kz-EZVd|3+2z& zX&G3CRgJoD(CUln(;Kvv>_t^<9I4$kt*L6Jeh+X!#s{0U_u2HSw0V=(S2FQZn>B1) zm6A+{wrE*wa8*jpK}$5MO3!n&IJQ29Vz+Ah*zg$se5)2_V#zTSyj|NRHpAMkVKb~M zJa&h64hQ6zcr%Od5#}>l=m>g)AvWJ8RQX#C=l9@dl`|#(pRwO+Q`nvs4oM&45yvfE z7x#WxOXZW9kg0DLUVMG8{50YSWQ+*U;jJ_PAoSCK{> z(o)&{igfUhmL_)U4?GOH?og4wIIN9h2^A^wh!$sBQo&4bYWY>+pB>SPOYB?)%5CiQ zkNU6zioIWqR56!06#AsNue2wjC#;p6h57c9o5oyc$9v9qP2V7&O2vF@1;ij_PxbAx zR>YrUi}_BWqQ|ugE#E|myd~F-@Z@JHCVAQw9P2euNK+4lH#|TzB{SyWm$}m{Ye`qsYp>8 zdG$i-2*IFVv|Imr#+Sb9w_0N7v4-U|G%hB>7!#=WtF|p^Mg({vL?)jX0qZsKOc$$S z5E=jV6L5cZe99(If!ytZJslO=-O%sds6I&W;F?#nH28HR5i2M)%2((GUa65^6^Ra? z0VWw%p1(e$eZoX>8LHr^cgX*;hEtrW?PaYUn_5m7JM7tUS!-^8Qw~)Ee!INV%hi>t{Gs_#@)fNo zYocc`knJf)!GCD;nSz(*!w8-KL(2*3hL=Q71+2}9kW8*ngUvY+S&S-;^!=EMUeju_ zRb{E^HEni~aU6ZCYAMbAqKugz%kuq;QRTZ@HFJk> z=(9eNMVaX9%je$JCYz-G)cK(nN(p~!i`dC9iXQBYG#w1X`CC(bv9J0+S{aG`URv1S z5VB13wbJy5Fv7`UnAE35n!YcMh{o^E2va29cr(qn3Saw3E06Q0N(<8!N+V|Ysym)& zSk>0QG(0TSPMVx8+1*l9&g|^VJ_@Gb%~~S;Vs@Sg%L;Tg5>VU?1P;q^{_X`9s9BEJ zgFSq|xATD{h4Jk^&U2VOUXstYI_pd9Ob|b7bM7#)t{8~XoTssrqnFbeZera6X=YJp z7xrxl`n#xevuRcdv%VfG^Soa%exjIj8Z%ukZl>Qkgko56=Qg&nI7OFm4wOP@c?oA- z47*$_;cUlx6c->MklF`28!8uzo9EuZdh?q$dOaJBn1T#+MDQ}uxz=Zi@h>?7oh7LM zR40y5rVByN3^uqprIvI~W%~le7wS;)QqIb(Iv$pCE@Wfya6UxDJJ>nabUgqWevcAq z-}~AqC)nA^wBPfna)|S5(+u3bx#m}jFOn%d91n@egovDni^5-+dovmf_Yd=VY z7(P4W|JsRyq018c1n6q?yGY6Z~>bCst71)2K_Fv%a~Bh7#x@vV(EX zXqKk&$8pYsm~88yUA3LP*(L`?COG?=%4lY4cGfq6|CZpyvBlVd? zry)c~7B>PQcy2mY_3KWJ>N&&Nd3!!eSfxl#S7Rj4Ku$V9Fs-!1Wz_IXqiYSEHQ0R{ z1vhl|&_5(#LiJTPk3AP>UaJ$9Jomfn!eyJvSWfsi=-{+&Ycqy5o+qQtKAZIMW=(aNHD{ z=JZyPQur?v2`DhYaNNJ8IpMe+!f}t5{2Jk}2qY_wWIByx@ZQ%*Yi+z==nuCGpJx#+ zJceGjaaLouWy6m*|G>E|slEj)_?I6)BI8*hKc0Xz!jJ1^DrgwJe7YYmiv%7&ZX|LP zRO0Oy+=#DoJHaGvD?(~#XKzg2AKn@EaY(_7 zq13Po65K38Bf7w5#o!-dv#NK6&01Kbz-IL^4K?nj(D820_e?3cgSl!!eLixQH_i6e z%~cb+`jNB0-w1E>+~?z&>k@v#Tn)j$jsNs3Wx5U`<4?cpQJs+DQeA;z#qRU|>wm%h z6;r)U<#i0}?=pcUI*mp?_NQOUJKrNgBj6!FS*En?DI;M^mo@a2`KaN} zQP>>9i=K~wPs1iWBmW;?*Buwd@%Gu-6R{z;ce}R>h=3)6y`iEac7uv~8e=S2V(%rf ziy&51v*vC2A&caiSTV(o!>Z*mNI@bG~3MIjBf)a@cU13 zW|`4gnocuD8@w2{Fm-*D*4*F z{wu-}ledKrjJEpHzarfg3kCkbzcl7YTNzq)to4KC!6y;YWTZ`|P2&K2CqL1paS;3s z{-x2Er3l(Q9)ka8Uss+ig5L{`b#I!X<_wQLdswY;)`b=l`H^0oXg$OC#wJ-Okr6n4 zHrd*M^!P}}O}55}yFQ3?#!MfLewb`+B2=a=60Hu}X^PdK{PcmwPO+ZJ|NMif%kINC zqBM85Pbu=v2b!2@jU@*@(7aQvGa)AyPDRPFA87Gu)}`Ws_aZGj7mM)w)2w4HrIDLP zCRt0++0(6EEqTnKKUI^gTfNS{M}LS|!VjEoRcS_&wY`9A#AaAeTD_3+8nV|dlP$D# zvb8Yz;XR8^w&H55Ywu|KJFCLB&a^i7B9-5;7*VPyu$l|30|YYdHC?w5niSU2i>&}dy%g`T)+_et^?)Wlm5n(%BvJz9QQvpe(MSrzo6&&CysSCM6 z<|=sHOWaIoYe{>pv{n&MzQ9_#ku`)KTWPJSSH>k>Si%eb<32BlU-NK|1@XvC8bi{h zzo0SIY)=9cjE!S7k))_X{LXpkzC*jx!8{N)*4u%`n%I0>5Ax*4s^*;pyQHG zu+qObSgVu4&!~58Tapd+LXj_`^Pm0=x&bq6%V~$-t-DFQKP$Y+$``0bbP*TA#T_Wt zZ?dFknWf5%tpy7he-5_%m zlKCj;g3ST~w_r1f{6DuEZOM{>J(+8(Akbdhtra<&ZMQbzjpY)}{S&!FqbYxKbjtqQ zA<;V1_C@U~E42e1Kt80?^j+37o`0o_v)^>2dG}eJRNce%=_fR556~0lls(ptWK=qR zwg=q(Fr5zGYn@5L(&?h9R)zZSvkoN7(rMB@@c6^WCXct+4<)oE?R>ymm}cy^4#XAO z_`XQqKBnOZts_a)V;Yd#R)@YhXibhN{TNjP{Wt=0!4-nAFL$1Wo;?b2{C_`c54u`a5NivUd>&z>>beoGyNM{8f_s{3oG?j8QIGO-TQ%l>E$Ayw|tb$x6REbfXG_d7SuPG_fA zu3CQ)SKI|Oy!7Ey?YC>zlEihF1~inynLQ1nOk8nCgsPmsFza&Niu+?v-k~>cpgpDU z(AaZQ1={|mRTV3MX2vLM3wr3LwUn61bBwmiwesJ=Z`t=*s>LCkRjPS$q(eV(ab$cO z6HEU_Yq(UieJO!UHB$W!T{Oh@iI%&A`>f1~#f6$Xw=UG~;~XCsYQ1lxDHuMtP`i5D z6lzCr8$vDcuJr@SxJ3i*VIgw<7EQbdY1ZU64OnE2pjGcfnr-%V9nOs{33C~{61Hvk z9v`ZNpUz(P)dTAv7E6bWl{Ke(YwH#+0Fx%MPYZqRklzyN>VpkJyNYJUw8=0^v;w%(QA zrezmlFVkr6H`V~s?K(?*g9SD@mc}5%`g`HtrVgU?3ohWjLW!r;pQK;Gl{QiYOZAla z8ZDGduM_-(3ohIYh5vkIW{gHCU7ye1ody+btoL4C60*_#Q z7HY1~`hlkGE}s^-UsQ?WUt7k+ayS>7*wQ7t+c=S%>8U&ZN-a$)WWX;fa8KfW5xn6aXuI; zG*aWTA+%}r&f2zcUM_m# zLv+z)e3#S3lm3mC>gLsqOKj(QYnYHpT^ql}P0g2TZfbq0_TdsO<12-e4wnoG=5B+@ zvU&&ntJ#;+4So_NSctJwqZx%HfPFb#jOEeA82Sk-HJcvDo?yr_vExNdiwi#G>A66u z64`u#ekyD)OhbaC-)s3?GzT_|M4NR1aUy4E!{nM9G+d(H!`8cdg!FIxZe5~1K?b)( zGl)WT;Q2xZHa5r(iMFGNRFS+tPZw>sHn6$LxLk9WtFP4D3A{(#3C)Js$FT9mq%`av zpEJN6 zakd`>*9Qo$1qr!av)~8+25v;ESe|w)C&{EYR)^o(!V2F4p&@aMg;*ODazm`cd-4=| zk{&H5)%UB5$c9*m7?GJh#|c=;^3n;2wGj5c0(P}YqceD%PYRRvo_3dOj8NDa+P}T6 z0VLk^%F_FM;+zwv4BJ#&f((PFRbA<#I0&)24JFSxFM@Z z%j0z2HCQKiA7>C&-39T&F;h-0ZzMrZeL6;qM@bDx`(uWjN{NzGu`_6NIhDV$R7(7V z=iqXx`Z2ULi=0}Ia8@~mAD!w2zA}dx-v$Ec@t9wbQ#1K&=cwS0(?wM8W4efP7zLEm z3*aKkO~geME`!<8RPwX^eAE~_w}dKy*6GWxcSj8g)iqlB0Q+UOz4Hjg)x29Qxl z88A4X5PTTk4!NN%y7yY)I_5U9qOMaOo%gXmEu>$G<@sU0)LDnUt8%TR`MAS5N~pq4 zww8|J(@UsA7k?);H@go z8TPdTpwjWXMvPRIwEc@lbhMYGOJbyOy>Ju2z5l{b)_K?f@Nqnx1Hf}-(ii|f;x7Zh zyZ%L!Isw4<9HgJB*($L7oh20y4IVTBJnkSL($4_?f`KM)7-e-0V| z{tXCo0(kR-27m|ag=PovIXo^0fU72*8^EWTG+(M*2k;@NfCKmgOth%@Fde{+@0vP* z>)%3z0pQ68OaOONa{zZ!a{zZ!>j1vs0A1Gu0RC~m0pRX7WX@$2tM8GO>m}{7q&|rc zGmUNc(H3~H=@71egHVU?FC>@{{_j2$!dvy1Dv949#BX7uEBi~EYNhTo$2JRwSLAV7 zFnk5VCWeE@vJaAu;WI#x1;arUmW3%ZGe9aunC7+`gCI=i@6E*UWL~a`;hc=RFrpAm869+4ishK-X-KT2E4=sh(3N2w*>Us|)!HiqsVD)kgf)AA#vy0q^w zsT@h!Ll+H`>W~?G=#61gTXJtVjTkQVCLQ+B)x)KUWX*0GigfzJ2&o*-HT*h4qNFEi zMoJg__U;z-9W-<@)_zs=9W?zrK8)|6{VI~(B5iitrzW+JmRkAs`+vx>h1L%?At_Fr zze}VK@4$XCZH!bAe)}jl=YE>I4!)m8-tMB|vC>E}3i-<3^Z9!2ScnV5Q{i^*muT5$ zQbpfWBXPS}K%BH%5M*{Z9=e_7&mF)QzL&8VmlGWk#TX{yv#5SMJ%A*V3Iwpnk1oY+q9BuNd# zQf4&8o>{QtFyub(F!!F>Azcr^yXx386Y?=@vV@Dl>LAOEci0Q8j*m6(d@5tydby-; z#Yx*l!^OdWF3c$zE~y6TyN#Ba2|f4bHnwOc$JnRvXUT%G_plbog0ZO{<#)5AvpB}K z`vZM2@UrC3lIQBWv4xfWS=WtWFP+bIW7rD0Zmjbn0zlX9bV*zE-#TWZtF9ZjS;%$c zTpU}W8^grTog2g-K?7`c(uFBf6>;wtLpPqggsa9D6Iq9DadVb|tPglN2eS6dq%n~7 z`W6FOk8PppOM$E*TMT6F`wK_b?x;ssjqhznQCX0+Juk*UR`5_>H?o3<@)^ilZ;OGf zJCHFavTogMAZwytXm(`%$m4P#Yn(~vM%EW54SMoFmFvigGqG-Dg=#Fikrm&0-N*`l z$Y&tyn@yjQRi`$QRi`$QRj1Z%JN!*nsXFPlDHB-rCVa+_dYj&#t7-(s9J~B*T~?8Rf9;>Vf70cOjup;yHp9zIj4V@VC>1O1FE}39Z=mld1ts2 z0I1X151XZ)gm0ZP>8#~wDi|fXgguCkNwejq|7?XGSctCrL#oSnr~i=JiQQ5~dd&~3 z-mcrE=HzlJ-Lg$e*=T4P?cBiluD4g>*>flwrCo-OB!e`xn9h+O@WgWyQIQ|uBW~4+QLd&k(_mpVgkZ^ zj{-mG6rbySk3#=OPwIOV{XxL@C=7zkUet;C9)(HF_b4U^)Mu}RXQSb?#5XF)f^}@& zKIuVj(Yn@DjQ1Z!hmcuoXv7>Wg*F_QnD}@Nek(WZ+`v0u+^}=*1XqvWtmf)*0QEm5 zZ55rM;Xq1Gt~PY!8f#dY(_BY(t~Pb#EoZonJaRP+I|m*4(kiYaM~PQfnd-6sd8o&g zIWg2@D_ezL$f6#@L~&lS`+}Ry;Z1e(J$_y)=ljLyxk8*d)ATr9A-;ph!(g*<=!78P z1#pGfol&>h%wA>KY-C<AwNpuU9f`M&uKMG(T6bEYRH(&2(=>pymt@fsOp1w47K5tl--5BC9`(ys9I&m0e5I zk=shw-{i<`)sfp1xlVZrG?oK*>Mf|ndw4-6S${mKnf(8X0o}_px6L;9jH`njN^U zyx<(bJ=>&n1Gkq+^QFpl;C_M%xJrBkT^JSbqXW0`?a+Z+|Hj%$H^=8^OP)yF9Pi^! zOO3)W;*brx)F{yDkd39*Q$Y5Jr3Pf9a!g&v=V=T&T^Ejg&LP{!gzUJNQmz6Z3qo;F zGg5Jxv-dflJ2w40TfAx__NXN~VppKu-bfY2(8@xO(Kbl=qu5-R6M=VMCv~*wy~CKydZts?ZbX-yUAwIpT-@q_NA>nZB59vh1^8% zq%S;eCHP&kxou~ywuRX(^aZKlWmDw@$A9ecqZe{}d=Uwq(+R(qo8rNd$$bQso8spP zxiNxpDDdI-cpPC?O;h}s1%@g9)qIRfU5-DT7viF$FEzk=7&WZ#qXTW& zNS;nzMQr9q^06QrHj+2brBOv-M!~D9MQn{RA+8j$jTHyZHEkKs=AhA8z`Fa~?6!=R zy67@yi}7vD7X6#^3ExSMEM|j}l08Ak@1VH`e!FwJ@!OqS$M2JK4E%1+o00{;_s=o$ zd&3+9zbAiX`ygJJjo2F4yjfVn){<qap)qO@%|EYbny#wr?_;e`d4?qBRv(FR{41h^vZ zPJ#Q-6!D|$GnCtDp-Q&oyh35u8f5N+q6`P){VqJ}VM`RPpvA6gC_PZcRzt5z_a8ct z?B-_!#jCjx&Vk~8X3`iaUXFICW^2j$shX`Z8J^5w)`$|s&B+FQhgRYAS>SsO4+FmS zw#OIMS>E^^)Vm4x81Pgb-$#}6gDxj}=cYk5Y|Q!h3|?e*@NUA3%>mvgO*%Jt*EMOr zQ1!Z|@Hq=j*0GzOs%e8WP$3<=SEK);(9GIkMEzSRW+>eaXBbL%fI(5{GXXJzNmzI)9L?ZoET1up;-`JXP`}8-qQRKTR zbYyGW9q%er&_6%{Zj-LW-}bY?qEgH-L8nYHOwhiZrmkDlQ&uM-%uUevkq~V~4HNVT zL~;|f5t-R%oPe944-2_5nlM=vGVRc@lMOrcn@R4%4Lfw-$+{hyw4Kb7DocCw(cwL9 zRmG#@bs-(fuJp7W6-d+Z2BIJ8ZQClYK$@;}FBs3DbYo_1Ovp?I;9s@oqpkYceiHM8 zP}jVtBp6`+3irnFt<<>w0CO>af~kI=7+{0?T`7S^4?@?^9A}uQ4-K-ZA{}Sy;FSj3 zO5xc*6V?Zf!;b)~x*ddWBb?PlJ(*)0SdBA*@oh{b{Ts7g-%9;bf)48`;~3O(QLvg5 ziL2yBP8t(ytw5s38Hj!|-WW@_jk+$H$2D@H9P99-t)yW21_azIs1)5g6o42WPhSlM zns31U2#f8X%I-T)^f!UMa${V3`ML7s{(L@YGUD9!l$97rk0pEAtl>a)5)wxPzOgH` z`6yc(F(nRNyv`?x9UEo4jguWEKZAR+mr&9G_fv7UTmoFQmRaj?Y&R0(f$h^{KV!R% z{u6I=JooImcH-;NX?=F%fy}QU}|Ff<20h5>iTm~xQW@_V@$D5z=>h#-T^xb^h z1*ank&!>IQX+gveesIJ$;%Dcpt z>UVFbVZ%n3p9;a&exNZHkienFDGNyoSAasf(Hc8rOMZpe8Tca&SdNtl%++I;+i?1$q+zLE{-a^3Ce?prN8+V)LIc-= z32)FA8*TnH&jiWF#;>*E;KvKPXA?AT9F)jUE2Y|Ii{A_}(LZVkO`0Nwu~HjsMFrve zOuAgg36RknZOP*P!KMVLjb|$P{^YvB6jtmC?5E$M`ip-J(($LTegcGLY_j19$csTV zdW)@r=ya#)XF!f^vEd9z$xM4TW%Qk_H13%N zjrj!h7_^U7+|JQB9xrNgG|t#zYeU`);O?Hm5d84r8ov{gQ-rR@qVq^ch$r%$f{`R3 zzZ9L@_^xWG+wK6I8K;Q1`(=gX(fe&P_=aLN*Hq;0gUk60g?nv3?#q}czU^zGa?wM! z>U=M;s)@_L^>s6+fy+VtOa{*4vcD{o#=vE@pN`8|*jkT3=kC;(!GjSx_d-;nBXVJ$ zAqyhU;$a}N{sZFi+LXbbXhto=WHJg*cyi~(7k&N<$xrZZCwE@lgS4DlcO_nM4oGGu zog0!%nlxXkT!&<-uVFGtM9)RVSJ5Ha_>Ry4SN}#!bvKZ*eN0G3Y$~U&jo)H?N9d5O ze}h_wn^ zg6=XwIcI{YelO}}s^6C`+A5J3J*oF4pmMWb=%yU{_nDrE%Yw=cKx3k^-ZFEHc*_h_ zE(3xrs0^YipPT=AQ1zcO<8O}2;XN}^SufH=WxYrpm2-9hN9F14r+)yIq)HEZmBBO{ zc+IxSLVCDixxfxv?k#Dy<}e5Jpw8>II{Y~Cbz3`eRCm+lo&ScdImzfwV{X_IEj7C% zV_KRml9sw@D@RfhebY8ieA`V2UOeV{%QlvD?oMNOpeky|_F5pTIvW~xo0qn&oIzjN zN|HC7S;Q+Y?!7-J>gsoXdi%AFiak4<;CmZa)Nt^1b~e;+pSN87?%ByyzhmBU^*gx} zz4{*NcX~%d{ciIC>i6@Grux1A1Jv)vJO@nR5yv~CL$avfwL4{3zkBNHxAD7;Zv!0k zZ>(J#OG(lf;>$FF_5DLf!=~a+=h_Wdz>U1MsBTkP-OcwcUZWEu@ zk){7@3l%IIVlY!W<+7KejRboQGB<`!6zu&;0o=oL8K7VIcLVefd15I4_H!Ku_`BUk za568`L4Pt=!E5hkMMOJ5e?kWX^wVI4F8Ab+pV|jS8IYgaj>Z(UCyF22nviezu|p9@ zO}Zk!p{<+m4Zttf4&fY%_{vNg1MvM(Bs|yQE-6U%#-wXo2IoHj{t{H71AY;nAq(JB z9yS0Ua~V(5WX|RM2H=lvYXJV6@BRz;&%ZMO{{Yf*0)ACqa1OxVZqm5{zpP1vp8HSb zI^Zj94IMmCu|o&9xB(v;c0MV&2 z=Hpr#9_)R%@`X9l2|u2j&Gj(Gx^X!>_h5$~1NUI>3#w^|H9Xi8oQB!_Lko;iT@F#4 zG3C_*@h~#?V2^Q{9_;Pw*sF@pXmgWucO5&t|ISg@*LFWT@CU1fuB~U^DwaVyx4Gc5 ze^-5b4?(DwokGSt#r9vsSxrsI_i1WC{+Ol)R?M-Nf#`XsM z^7C|y6lZp3wMjh|ZH#YFTHE%^0yg$;|#Cz7*u%QoZX8%C`iK6|R z+k2BeQS@?ifPK}*nbz~&w2{+ZAV~Iitpeh^ksj)O<^@$~<0%g-8|t(#CnWW24)p!e zzUklCy6+8 z|JM*h%bmL|9qsx$u%jJ50TR0wBNZ1aH*j;f0qe~hBAf%(&t}pXu->qtu>o44A@>P% z(0-lm70HYS#xCf&&UWmA9&2DCd^FFS1>yJdFc97tDO@V+9!@+bpgRVx#w|@P$!=Boo)?q@(eIdaZbWZu(tN2h9notyFjV;7m{3viRvpoeZ&k-@ z{TnUQRrr|t2BOpC9vuIzpDE&19nsy?I->VRTR5VBO*aJFO{>b$diq8vjqGK|evkTj zE~5&4BlJx#`yL^l#h&pQD@bTl2#A8vL%sMn?;-4iej(n(_2YF-T=ySfuLNsVivjkt zwPNd{pK`#uz~e*?8HQ!$M}$pShvdr~6o?zmfb|X_$O7vivbr0eGlRMRX&DUB(yNY+ z?KEz%@q0~d*UJUAujS^Y%wFKJ45suBB56{aThU)xylWenUV@z(X77rHL2Vi~!rp-U znT!Ca$3@bsBLM0d{H<$%di6;9Y@~f6Srth~j{^(Cx!B z)phHLxQzs1ZcT5b3rW?mrVl_Qx27ABM(>#fY*d_`J9Jx3L;4R9h9Nz@rn_8Yl)6M1 zhVwl^e`s~RYt@iS0-dQ}s}+s^}v z-$qDB@g7ytW^k(8ZvH=nv)aw^lTW!PkMV8HHvJp3?b~8)+D?VZN0|6PVi>A*4ihDf}KrY zZ~s>Cx==x!?QzRv08L(`hEREf{h~A*QTofMDJ5OP%4yEz3iQ(k`vu>&h<`Z)SJN&n z;!4ARj})8;3rujfszB2>+7;huq`ywU1;b1Ia6*r#`|0V8DzJdx?Vc9j2IaA`ZHR}; z6FgmM`0o+t3FevMj4V$hn7xirmc=vsYaw_;IW$0jBcqUBz;8TUnA3;o;Z^0>yg%%B z1fF5LeT}CyzD#z4xH2qauYGVHYmrh&$Wl{by631JH;k}c$Lw`;S$+)#WHjG_H$1wZ zwtEs%DU|jS zcZ#=*8gq?xyJs&V;+3B%5A8ETOo- z#9DzsxNB-K&Gp`%z<>IC`z(@Cm(5WBn=OtDcGsc0r=26)tsPWF<@xt~X zSrLCLjBdRx|G4Fo{g7ZQ1gcje!L#$YK>@dPYlYz`cvr4Ws1K2=iroTG(*uk_S0Xne zU2!)Lk(H>J02IwLfP35N-!^bKxE36K65*k^qAVVNZVo?!IL_fi(97}oOA~E6hwl$y z-l9C0h|3F!Z0cjVDZwjvawYMxKgKpgF2x`sOD*fkeB0B|j2x z+Km}V`<0Nl+YZ>xhU^B`c>L_#V;5OrtHLiU36+Q2zTwGu4aXy{B9bRKTOji_Nhu_P zj{YktvbY@?W-OM!$u0JiFhagc2;EdcPR8pR$caUi5IM^Wqx_W0WVXakRFt<_#PdETZ!fDVZ?Y`$0Y*gbkyZLbHF+%=;KLbDqt(OZ zJ*27+`xGw2`Dzlf=&T)BL#{`z7Np&4$lnrddw{jKaJFuY`D(ItI59Z7D7#iuevFG} z3epp`#<2Qm7zAXo%8{o7?JO)fj_RE;Lwt9T|5n zB^98{>&r=@?+W~vlV9p_**Q6*fWgTRkoF}`zEyy8a$B)x0h5XIH$*IZ#zC$pBvl@WmUW)4XVUJB-plxW=VDMyZ(>z0n?{v?jMXN=-V*qlxUr;TAXA zbdW2N_ql0>7}+Vd28ljYOJev?P4uJ(J7cJxdH#2(9_w-0hw7fEF;q8@_NAfv#}jKH z3{_=MbEryv&xfi~Cn#|HJ_L-m(Mht}_?e=iKxcndwz3q#f1LKpSMP@UpK zg|Rr5IaHQDe5ley7SmV0O8Ca$0C@%ZMChFX@=WqKp(6*%I(pt6D4&;72)Hf_dM+Ra zdIGF;^knS^%YaW$kY$BWTmxsqXWyZK&uC0?9X@vt1$;IY4ESs)pllO9>*?R0;S*Nq z|G?+(i2D+J{ss?GQU1hw4wrut#2FrL3~fGIt|VNbu5q#-OBpR^vuk|MQaMex)th#CGGZw@H|Wc6$MNm3ND>@`$Yxpi*R8W)iGDxuV8g`8aA ztCz@Sq9raGSRt2Hk`a{?E2qAsBmI;xam-7?PF9p_TWH_4@^G^AIqe^)_|E+eaGCg= z=y2&r&;BN_B5nAc9r9%{=s9l43zrwtH|yoDWZ-ielPY&1e?6mnQ^ABI3e#H0<@R*g z2DvRq%X}tU{(D@mYB`mu0ae{7X9(h$XM~=tCCfB&liZUWf66P+=)O(zcO>!|ZZVak z$%3b}|7J)?&u26#MCnc*A-n~g*zl>*o9xOK&WXb^DA^__mAsij{-gd})#I{r;@=sB zc5EQaerJ*RC00BRf*B3u(p23pmm=3#%={aje&n}FF9 zRBph;HbJV#$33jwK>((B<`JgV06B#Ua`A!~h769G{68?0mA%FX>hK-5 zElq|h+Tae|neHe;@86IUxWDyHd6w7f+hq1(yuU)5Ptp8o(OdG@T=^VuOFnPgiKMLX zx$QRka*!;OO}AP9+j0c476nCC3fToc_4QY``kh+i7Yqnb_+$BXxT;o z{*0Cv5YDM=o<`i4(DEn>EGWt!S;j-aCHd_pOMEPkBjm*m=A9wu^%MtP*GJ1#Gi$tp znn@(QlRaLZNJqbsr%A`t(2^{==HWDsmPg3kG!rP-T?0WDpj>^8&ix3WoWtWypqzP) z17*4wyXC3WAmU&Dm~fe#M*&=Z`X7f&$e2b2l}F-(%f|dMFtd%1vPn92*=&P}nTIZO z%v>i(?Ri2LxNLLTfXhRd4Y=HU*@VjGBdvG}(5J!=*3v2~kG#Ye_9Ov(!|nAQc2<5 ze|ho4Sss_27hj(>dGRR{zr>3VL7?+uN*SdTsdtw1Vlno-jA9kZ&@&W>89-N7R~3x4KDJO!m_vN8E{6E#akI9b^_2Fc z^$B{g9!7WLabtAL)yL@i)8Fc2bP1IkV01emgFd8zz$eNA-ba^`aFYfdn7b2bKNMOeu%c8b>Jb zw(Z;&7|E$e%#l3Q0wekD5jxJP6fcNT(jk}s&m7EqPCl4-53@S06yR>x!!)`z#wh$S zebri-$rt$ZV80B|4dFe^6!_s$MeN&RPnGF%$TQ?sD%&>aTq-q~TGZrTnLb!Toj zl+?f^CE5G??Z{<9Z>Q}B^d3W8PU!t>y8*p_YboX_b{MRBIRk~nFa+)e_$Yzs6$Nyw-=v2%? zbG=xZ2L7z%GFSIOtkKU3wADYhnjG4EzS5KA*~;sQGT?XgR$68O81xdOu?v*Bqz)3H zt?~_vg<#GEW-{mFg`7Em-$JD&N)mUaT%y<G;|=RFX)p|cUc?8M4?|E7c!(ffB(8$GmM z8BcC)q|vF$OmWvnbM|~pRc4U28)?!8#aAu_SC}}WOzn)nw0s_K$K9Ci#0kL-il1O* ze{WD4dkX2a{0_yR*50Z#B#%>R;#TDXVX3UkAIb?)T(jORwdoG!35i?JB6ccRx>a9~ zIrJ3_N`X~fLg*A{mG$)MCr4fS>n^3DrXleq5;q6uav4N;o9$Sf(?*}}QXE58+%dzHaLq1>E6 zhn+AzqsYSv)%9-=R&&4d9veHqvG9Y+UQh2+Yd$9)U&HbqS9W?y3o%u*R`K&HUPY95 zT5eS9fwz0TrZ^K;u?iQILm6k_+4L)ozN>V%9spbUb^F+l8?q!bCe(l zm(kVLP-4-CNAAv6NS zL!o~@1AHD`N}oMboTNA?YCC*sr{~Hvo-O^k5*8i16cewDr)%Xp*uq_w{SnhgoxOinA`luWRwwAwyjH-irtJTDs10)?Cab zVlg)0U!^9ImMzL65s{j*i0u>{v4q@PNFywc?#1scL@^~%%(x&|8vc941-XP8@y;~F z>tgZ4Z0D7Q^oYgbt3;!)tm2Tf_}7c*JEVzq7J+?5*`HO+<>&>o6I+h8 zqBQbn5OArt8_#W(OK=YTnRZtk;od!XeBFXN`*!`Aty3Hk`N-_KEIr5(gBvjCu;`+W zBSb7e#{`$kUpcm0ZF7)`^SuY~pu|*XK_--N>=UF#vk}jw+-_`ht&DTdo6RnSIJV`& zK^RwA$1d;pGm*Xz?@8R7;CwTa#gubgwUCuA&TJcTPXB3T2e`pS+lDy~;&PUtDvrD4 zWiriM)v=Cz=c3!HI{M?`fcOZnet%NeRUzPJ34>}IFXa1^jmXQ%Jzqj1MJoTutm zcXYz5*kGs?)g6Bm^6d;7TFud#UW#y(A_r%1w!&4NwH!b2ZI@b(A!OnV>KW;XCO48e zTlvy~k&e-%$qde0F{IKA&Q?*}f2y{lB^jN>8EQGF1uqq+f7WsMM4wCgFGHQ=aakDZ zC=cggsDnH%2Se>i;tUmI(U4|bRu5jv%Tnq(7GSG-Is-!$7f8%>y7RRXK-+Vs$^d(@ zwGA8=j%*tmI`ZL4`)Qn)R`dI1zIF^C@zdz#uN|+0mlSe^WU;EO%=Ou-;>E2hL3`Qr zC8&P!ORZ{WVk?eSJ{Z{i{?bt;Q#=D3qfSWbi5I{azpZydGAiYavIH<-mEr?A$o z9YFFd)tj2ue`MZRAiO$E9XkvTE&(El;okw{XJnykPTo3=18Mf%*eUn&)4j5%VVLLh;IH|U(qoW<)J?-R}F9ffci0oVr z#+A^?f8k-yRB>hW@ZyPVZ)ZndT~GYpG2c`AaeQ`yLF3uT-VV<^*0SS}z@@SWc9a`T zaH75;sL0M94{=b7cp=VY^CiO_cLk|m9H@1^s^k)0O?38(qw_{O_L8b`EM}Bri$IQy zWy%-_A>`|^%y+C~o`vMaxv_J=+H(nxWYRyDb|3HPPWF$%VKT=-GII>Bp@(e9nC7Si z8?NIg^4%CZav}zJ*BBZ+32X*dnB*8s5^z*3Rd&#j$&SY4@@Sg$Hvl<#vZEWR9jvd) zS@S85mhi6E*(=de3}z&He5xaX3>i)PUqKZ;r#S|aJ)<(~YfmbTrqR>EUdf~AqUnyA z(P=^N*a<8j2#kXHzg)@e$ZG$A_8Fr6mMbsZBWsCg9^xgO^nJc_nX274VD z>Bf-s>kdzLDcJ#UvsxqRr<;y|Ewdb6g5~81Py`MVWm@yLBlp}{4m+zc+o1}Ur943w zTR+TkJR%)O(Ac}^rO|U8)5w7lG%rPWYHS2`z>R$Va5ng7$2NiguKA7xVBUuL4m?6V zjJ92XuK05pO<&;9Hy7G1bX+MJKMdo}=bJ}_WQ-rum?i3Ut?CiCdFO)?D8n? z5^lvg{SmKAuE0r74d1HH+UBAT-_sD6Rf-W*F$r;;wX^NqB0iqiD9ReEv<&l*#Qew( zE_ci$mc>7y)AWnEVploREu{Sr)_)xU3O6@ssgCE;vB78qmuHa$@XMz<4-KXP8yq{y zPlMUj4UWO0w0#f=xDFVJUF%K>PBw^k*$jEMlE;hQE}>Ms^VdOa^=3!+ynGXQH@cM! z?9XENIvx;lVLvy19dPWDV*9x(LwD|;;T+kIwLa*WDOhEm!1>#w8l-Bx)5_ld<@lc` zY1@ZhIN>;0phO>}@57dB?+MOgY}H9ekz8bdFV1-D_?qTCq){w_;~luGuONy>UWLl}xCiZh6@2z}56)-4^xRd)aI&cf zXSTLvVGqt{3f+CpQHdn>ps%huoaA$;gd#=v701xq^~)>$k0j^h!o zgBWuc{TADe7QcsnJJXfTz30Gv7p=OoqzB-t>bJiqvpC9ai3VOVCr`P(P1wVB}d5Zp> z&0?p#b~J_?)cMzr|B;)W*v2=G3!-?wqmjyf{owEuycTyPhQHFWOWvjEi;s>=QhP+{ zPCkKUUBb3m&NdzSnr^6XIO1PI+-(jn>e9ttAdX#w5h``0{r`0+S{bD4DsQl6sJwxi zo(^U6Uk4@9xEPdMku#OAOGp{#jE$k&6ty=^C90jo#852i6!s5MI|;!aoU|-Rx#&X` zA37kcugTz@hVYvXEXJa~6Uc}TtgWZ|%2V3jE;|Kl$GQ|y8|0C?eV4t~&foD`hmyMA zu?h}#o<+2@F+1eGpE?7NqJK+A2B^NI_qS|rfQm;Wi?d$~tBVD)vo&iFq(U4vZ_Pdh zt9LBor&h?x0q^5i>U`4q8#=Fq+TFrhVOs4DSN&+=5Oo!q(25=jQSXq(t*G}XRiTGM z)t|`vRE%`n6QuH2Hfi^?KNYXbgW#JXITqmB~MgoOcj@ zeUvY#aP2+*d&I%vG;o5mHn{2<()72d|D^qs{0g)Ck!mfX)JJTl)zYMljAjva)p10e z1ZN?A3jAGP{Wc<@DGHy;3oqbG!+(!B$d^AMSrMAz6RG788@8rqXY+NgKxoFMxHPX58i^EbWa-vh9)!L|4yq`DX zZN!QzF2R}6h{d*1o%yg;fBJjQ6vOIMtkfE^Ro&6k;@WzI?)sVd(WqYPPHB2QWUP+z zB1M;Q=x67Ydd#=Cx>vBOJV7^@;&L>vcqi1)K59cxGOi8{8?5g1cGf|90(6f@)1A%g zFfv4q$R*y5G&>YLm78`NuFfV=wdt$jYIl+XPva5lLDD~x79R!0+Q_GxwD?3d#?rc`n~RoCqKW9Je8NKT}Y2Gwsfg_LkLKRiyRlDyq1UjoAYEj_zxm{w=!G0Ooaz+x5{kwa&@Pt zw7Ft-iVYRn$lp|Nui)RxXK&Xkci3##ujT3L&1$$bm&c=B9&tu{X2MB$sT%FATUrMC zx#Ek?a*irbliFzx)@zG8!y;BIXABRMx2r{nw5Kcz(9JTiu)>XbM_C%RL%m8Slx3ki zAs6vn`So3@2u>=)?(9+X<|5Tg)AUoSO7s4u&LfNP+UsB7;uoc;_aSic-cmH$UsLF# zL+U9qxfI=b7_9uL6zzWm6EqUfryc<-rbW%+uk3)?bB2TI9Nhd^}!Z`j(TUTQg zJTADHE)97&g@-p*F=*=7)M@7PIQXGn|F*U(=v+ZpmzZ(RxuNvnS+$GhaR}#XeuZ#@ zb1F94z7L@%LbL!j@Pe9O;O-+ARX9!TFTqY+;*1<$f?oa`jC`jAop>4j6kdY8x~xJ; z{qrl9{*Ss%ur&P&1$KI8*XV((Y7f2=yr!;z`S|=bbr!i&oc2yr^%da7H1&FgCB-qM zoC&x_mOjC`5aHLDlCKHm7yf&AKz{X}=cI_&pE`}6Xp)_H-h zIu``{u<8jTW)SMr zEqHtaB;()&XLKO*e6N1WOOgsPPfu+lA=mxcHZScN1T+0DpLSDu=m%=fXS*TUpe_VK zw%_q%%kyi?1!*)-EW$e$sx{V?!~JNCx0ZyYsoDKXPG->wS)5`9(F9G{lp(| zD5MP_T^yXpV6Y6(x{@;v&X@u8MSxb1ggE#@Ql-wqS`YHk`^$IDzsb??FZtm@QQKZsfhL+iC3s^Q7xKW!O5*tsAO_cZ9J)`Q14<| z3}1{E(;7nFY%ZpKOMZ~4cX4eUxg>K&4U0Y^qX%;E=m8#=g-7@Ba1I{*lgH)YQ6_U9 zEkg%>rB$+cgTP?ay;^V~JS;!r7~SfGY$` zP4|`{yeTr=OH41^E9FstFY8!A!xHnfmD^H_&>fYu1hT>kJzkqBjo8oiuNv-xVfO2wOCE98QEBn4y~zeA>#|OG7;Kb zQJm;)CSR|u?UTBDV@`I2vYmouTF-cA7jL$uj#fr+C_Et_*TQiEB{EKD3M;byyTQJc zF07}OE2_4^Hc%)3F+dI0(vf)m8y?v6Z93x z({6Hx0;ojAIg7Z%yP?)2i~}kSwZ`Dh0*y3>;7N-$(!M8;^RvW8=mH?D#RD7pSc4{7lBd)*Z+42-dD$JOb|H6gC$H=cY3~l34Qb;= zueR0dNDX;>0qUz<(xPcxJ1xIZicN2)!O?h|r_rm-+F2_?eCv1uK^aHT z3a&K#_lT>2ybGK)JX!Sj8a7gv(jNf;4rY_7C@68if8DMd-6Z zU^ZM%$B)*~WrH=tw;MAvbFV&fi1vA}zUL6_kw7XC+WJQ=QN*jbwAo=zrf+`K+LLDj zZ9P*w+!W#67pRK`OVPw2>vIqS%3X^9X(!6#X=V(@b;_0}q8|kAxpxbK-8R|hBjMmzc zlmAlhQ(7?FKU(t7P#$sD!vyUt zx%-jU8Lych`QXpwO#hjc<2Crt4ExB)M2;3O;Hx|tcz)yq-7;C5Nq+r6qo!!OAZAmv z>lJ!^5U@(+vjV%w9^;+e5Ppq`_?lpAT%VA9VK&p*5%Ky8wYj-MP1LYae&W6Gd4&q9 zBk!3qT^mWbDR72103$3UYmTryAkzgdNIdm#a|N0_M>jByKwMVg%kkic_cS_L^A-EO zM<0oBk#Qw!LkNj}$2@0g6A3!SHBa+rtLA9m3l*BY{TmF5 z@4EUom=oWTZ&?K8leFazs=K5V&8epd~F41)&<&Y<5aO!cYj$Q4jLFiDS0FCPiLoQ&G1>XYE82F67Vf>8$MeN)^Ks46F0!PMj7Md|Q;+HlMJ$9#I5%>Ph~N*CyiL0TbdKLGK*$8}VzD3S&b>A@3Pl4IjT;XkbZ+e3l=J4%!N zRv__9yuSnlWk+kWI3FJkM{A{N+DWYxdGUY&0xF374xY0btihM>qYL;B44ZyVt0j=} z_t}Z_8g%a3_i6tGEL1WsXn%4g@1piq!TX}=ri}lYJa50md49n?*8gt}4v-@PTp&w! zi)?uDq`F1+A#NdV0q^GjL1c>y?_&O?JA&!-E0Ebk?o#P0WOg)S^=Y{0sz$kgblYo? z*{kmg**890PICTwmnL3=%wBkxuB+zvEfdnTS-HfSx82kDw$_liZqs+S!7<<8W*hHl zXGF2}Ei-w^18tXom0Or<4Dva(fGfUtyt5+0i=PR9=qFisU-GU>H$Bu|NVji-tPjXC z%D9Ami=5YQ(ru5l*r+{-f6=VAYjy=+R~r6%l*4)gE!&Rxm$hoUHlHaAi!kC(LG4BS zX2id$Sle}BFc#bR?=cXIZN#s?$;Lg_<`TY7lL2HSH|fY+zD_zhL$i~6H`t;K2;<;^ zH_(b%V969nY2@n5!<J@ zWy=-B|AHbs0^xFypo7eYE4=a;^79pTIhXHFi`e2Hj1$aWY)f9>P!fFce_;4_@B+fy z0QaiH3kcsHaj=1nO4Re8{2wI+d@qxq{>QEs@WuK#l+7vVi)#yiz06iyeGghlyT9pR z#rFh1?&|RUi@dx<7Y+5r8C2DGzh&noH%ER{eIE)1=zY!id(!n1jrR5ZmeelBj}Ek@ zf}d|E;@V4}9Pyiw?>>%qhfK#kCWsh&)Nc-(?C+Zb?|OtC}jbe zS!MxyZ`d35-q6^MpvE41)Yt%fmsRvdY+!e7sL0yI5{(^=C2A5;lh}JDM)}TrZ)OYY z@AD63=aqZUJ@?*MrV@pUjZ~xoV(aT%M}{Kx5HnC?lG@PO%p?(U#&z=VSg8`J9x6qM zL$2fQJ}F9filh{kWRf{fad>^`WjL)sit{TKg_mWBh1IH z#78y5=j@6|fl>q1HJd!0J=MBtDC%dIWc9VLk#a?)K(XpIQgf1o8;XibW!x5Cr9%|m z#T_mx)x^6UuaIZ4l0sUQlnf*^4*x}#ke-NJuUN~K1T44CS13R9cAn%?7%mKCerf5V znDs09wv2?YdV+yzQoJ>PS!tZkt<$e)JA8(_k^D46Dr7xaPV#Z5SCT7B8^xQK$e0Le zk+|m)$y-HYGxFFf(jTS9UqVC_rV(K<>k{xyZyfWBqqz9NHi@|S5jQhx_$BM)s!~7E z|5~QwBs??fa;A>lN)D=IEm=cqD$-qPEvbLeV6PktXZZR=8k&M=D^`+Ii zinT95=2Si%*I>W-bX=AF=F@Ry_M1<~xY4zty? zXXG(IkTFT?g61CUN$*6w6eIc59d3+dDzJd|o(hNbjfHEED^QZM#8PI?c;5Kx*_944L8Ws{X-q?V-7a4Es<*fDJc zcsd*-0KTp~0wchHW2Ej#i~y60^0oMjky4Cp1UOCKRMOhtJ_3vzEv?hhPoj>IV#Rj& zRM!}3q(l6zS9PQpMV{&(1lOs}L9cN`|jZN(ZH zFX4MT-45&cGwW$nq;vFR4pWie_YRS$X)M33$nR{OTh~KsYFm-ohup%q;bgYnelmLi zmMGeHYX{IL5PBZ7j-4xE(w%!iN7{A@3@2CTOH;*|1EkvmX_3A*O4+3AwNPp*)jFU{ ze2pX>b=Q+8YnCT_y1U8&GH9VBNgGh_bQcoRARMQAk`Ito3ne^rPo>dUNBAX3yWDj% zuvV6g@sB-E!`t&>+uYsBz8R5+_Z z%#VwU($izQ;Sa?rGaTonlLpCB@2dZ#V=z36v*}a()vIjC$2fj6>^ACNqi)m`FSQQm z<6zT`baFFUlElmD)_2L$BVBlBG-Rjz=_NX#=s=HK(uBkP5;$&~ZWY&}p?GDF_1QXU zzlU$pH0Ks!)_q%~(w<>~yHM@`+m9YQz%D@C)1>Y--|s{*kg?H2Mf=KD#!)__$84qt zD1p=aa3@JhlfuQUoz}x?QeJoc^i(y4{@y2**NH7sN#Fr#Kjwf-2QY-ucP?OLc=C(1!fnY` zZDeS!$k?i%mVOui+DaCjk$Q`@wvtz8Fh1ZqDBr7}mDpZ=E|#M9z4|$c?bY$*OSpC5 zIgBpit1YC{1!<00ZwpyaSPmo~E?|MM3xyY@He!J-L>Vg=B8M-c#SdFZi%g6c-M5fk znNla+9+GmEt`LgK*r{KV%3y`CnRL5?A)~bgLxzZFTwdYwF}@HaVjgW~A)l|%#R2L( z@!|%0C&Q+9w7x2IC_({z)fHgl}!Yz_73FfDJc)hxFw~Ew>A=`A`F`KyL3?8u#q(RLn>Bq zpt^pie{Jjct$#>ZzgOL8^|&qN74^F}VB--<|JDie2~VAe$mNjOxIoXK5D$nrbjZl@UK+0KpR?) z&)(>gr$@C+w)%aP8srnluOyv31^%g5(n@j}r^B zQ~LBcV;NC`90t@~`4`LT;XtB(lON zZxz=Qn%TjmPl$ZpZ7^{dLLQ6zQFjKb?T#k75mp+@OmY{ojyi(03YFOi(o%1GGLmlh z*@KbKLuG9DPc0>4VR;T+gcp`ai8FCnL~bMA!)I;OQNshf1$mm-0-y8A#15lGQ8|J> zUQkr-te>+)4Z=%BW$g9S6NyJjc|lAs;t1^J1Xx`>Vrm&FN-$g7I7 z`dDLgtRU#9fTwaQS-Vz}JF{DzE6d5c@V{{$9z1B9dQY4I)z%lD^uqbTW7bhsGHhJJQk4s=hMA?Tk^7r zT)st9GA{7=rRzD1R4=4Zav;&ca_ofI^g4 znQtA`RIUpi=RqT_$Z|8sBXaN1W4a>Ati_K1m`BbulY5IN=8O>GZPgK`0vtV z2mF7|r1)D9pPsT$%~Q0Jf~K^qX9tdHWvU^E>2WRt_RX|*>nUGz(+{4Z=1A+_axES1 zv!C5ZJ|KRcPMY+U74hA4(yy=lOx!=++UYwPR{>g0w-)G+3h~4=Yq^0CAdbN&Tz;l2 zilH(t0!&2;B;3S&jzfA8K;{<#D;qnu9_Fu-?|0y{8FLxG?YAcG7 zvTesf=8clQ*lwGiZzwYwDS}bp{15V6F(#gL8zYYtuf&rJW8^kS_mHvjT9L$)?HA=r z95DB_N^QzPt}XhWAV*7pshVoo*39Qjt&HYb2sh683eDA<|&n? zM0JcK7bePhLmKL4kr{juu^;uDtFZcJapW`V#RhRCaFYD3TT(2w7>^2($yepP))kZF z3Un4cA1hbWxus7=B|GsK5-&HzseXE_p6Uk+^i)5F()*Kes$ZsO7Ocaj$=G@HoP=id zq=I$U47r3mMxmW^k??mWkZ$v2+-!||%IC@aX6yO#9ly8<@NYdDbGX8rIR&?nlQs(g zam)m3zXkFj(eKuHhn2!l^P{ehx86;VC)1Z6#VnTl7Y#xEdzoGY!twxrg*Yq^icN_M zLOEL={53DiK%Op^<-qAEa$F72;UjK5Q4(cI|KoU2O|PPNOq6jIy~B^zS4-s$qRvcG zR>?-|o@MezUB&9-sLbMQBV2|4o{IB%*c4Y{0P7giJ4L=AP8~xkt&#r}TaK~%t(Dh^ zertX}V|FIL6x+$K`hlEWFSjW$hnCYb292gf&HTX{zCp%1Abq5@-%c6lYDbN*D4>O3vjE9`x32xTjj+%zn#M&%LFPTF)o0o)J#+b8-p-QuDe4MUuF%Eu;pdK`&QPaKsi ziIs<0qwrVfHzl){5CksZ%3Q0UIHxlEAkejEG-Je)?cO&!9$l4jj1vJ=kA`w@WgNKj{ zKVT7^d0rkZ_8Uy*oWj_aa6v91-WW{wU%+HvWiXxW6;k3N=J^$aX_EI7rwk^6nc(4f z5_46?O={z?MM%h$C+fvF18Isc4g7YHYj$@X#Iw5t>b{iStq1Y!ZaRo&cR5nws$9Ws z^+0MoeHsucj`N3JxHCQ$czkZihNW@%_nZ8}?Z5yuVozBh)$>?US6e6c9e@v~(%=aj zfD`>Na`-Lzp!lReDfc_ecYY@E_upllN$lNUO?rMNao(SD6?gG?aqIDWavM*nerdDd z9=T0$6SkQqdT!3p_qv9Mo?dt!Elo;4k;BB%eMy@qatkr0FG+fW@wsbXOtEs5*r+cl z@Dv>G?L)qODof(dK4kn;d8nIrUks*^&*VUy9@0NULkQ~pOnxLbENgA}TyErvZ-UgX zO6I=jP(XUip&W6>;(EnPn45Ox*P2UqfSo@ePE?m#q& z%0}iPN3!KW4y@k4SZ=<_mYZ^PIK&;7p7pB}R&nrOUQvS`T0=j|9o*egThy<)XRL9O zu2SA!G%^Bkm8%eYv$h94_Mpc>>{!I{UL3Q#HgF1L#<#dj$v9rT{ViD|8pFM=eTxNr z`TF>ZhwlZX#NVP(cB_UmeiMhHH{!DFww|PvyRl7yk|Q5G#4 z=H4kRnD3(eb5F>t$K*|eyv82JAThcp`PReu&Mh2uT<*v`#&9<`zaBVdC$o3uGa|Bn z=}r#kH{$t{?$*iP#zCSur#pF6(AZCZubXc1k!}HGfRFJPaZ5LAC12y8qW*PPEMS}E z3$a!(7*F7%wm4)DY5D~kSBc`;F4kRzj4ed5dKdCpGPa3L>!M2>mscXnwWq94`w+ zS){iR%asVYpBjo~6h;?N8y4YZc$PRZ(nl?8#>;$B7U!#$4dG?^QI_GSmL>4AJSY$!^718|{kLBd-@*a9j&`cLyX(04ybNd))-;^P{ue~C-&$-hL$s~5i55f ze&vnj!mX%xWNtT(9huwFfit(BwX-vq(t#wEH%<}b@Hv1A#ukC!qdsdYvOr~A9~>8T zHHu8G0GsYck@O12x^6AdhExDgB!5L?U(eDVbcUoTl|L)^`_3)gyNG$Sh-Z1ax|=h$eU`$M&iSEq-J%ai57ORZfp=9U-+wfk5qTkn^*&S z<4JsNnDexTF+Uacu?867dSZ&!YloA>Q-w>PCg?Wb*Lzs#-Q1o>Bg_xunwNxN$u(HJ$Wm ztR#ORt6CXblaIBHr6|yg^*~6YIv`|8TQa8(CuB<<5VGtGj>v_kU|r*WD&%ZkV^3^~ zO4c)m(!-YZI0=v)qkBx^8ygM2@zpgrnbhp`_vG8^z&|_^cGoFJ?ap*?d8+W%W_PCW z%~4{FbfSJR|g{O#%36D^jYN(L|$a z?_1JlMTkrWHZv9pKm7%-Tg@gJCVeLBm!q9He^c z1Sbv(yyYDDv;+q~mT=|39)p+6zK>C|7cDIb>zW6wgAYVgP7Qm_LN{a$e*Qon)zJ*8ar+k-Ea2LJnSpdYI(brv|+2}D$O(&J`n zhNnM0Q>xnacnYL)X8^-rM#PoQK>e~Ak-EU|5OxqZi&1ZM=>iZXzYbz`7bg&-yMou* zB&G*4;CxqP0QB7I%Juc?1|pg^b0&fTv`-1CCxO9_V_4c95YCr&<-s0$sWbtac1HqG z9@Hrzvl021xQ`H&dQ1#_FY*qiAv7cf2AT+s13dDb3NVCmkN0s)Z)!sy=cTyutx zobRoAt~aKEu3raKua6TTLtjvNr!nc)ms2pIFQ*`vrPjG=%8nu zkmT<`h_0L~A@)p2pqX(0J16}I`+<;ZPI}Y;xPy<#@QiaJM0iFgh}L96e+NQN^oJF1 z8wiMp%j%z6T>I z4N14}Rlj}@M$BJuPcAgKzvrp3d?-?*Mnm%NP~Kl2#%WkR45{&+wEw|AIn1D|L!`#B z$K3G9;WP^?m}fhzjFB3dT58OqD`TX_%;8St_ZWdlSlGbD?o4fR(DZ1j(d982I#F9D zRTzn-f|ehBN5YS-8Ax(yBxVetE2N@(FcRo?mj5cc@}r#4xs3*&f7d51Msq#}kLG+l zAC0hBTi+42nkVXvp`jl7h_jRM1N8T-=&E1M6UGkm0w6Q>)9f@0ZFi=9+iH96S^>F}k=?gB(1tNBw6NrvKf>$%C zKN0z{?MLJX^c?t+>#H{&M6```A;PwaPyw1H6+_l|VECbuD-mi$G9r*4#U~&?C=q9R8ABtY&qNN4rGwif5V5`Kh{(1n$OS+#s!)EL0_$~O z2V$D)1mw+Bkom95>V4lr6!Sp8XbvG0yR$ws6oX?qEYi>wXdS;^^+5-h-HwsjD)R# zy!p$xyyeS459FGXKu_oD&h#+E>V8B+9Daw>laZv+6H>z!h&`d$t|ZTLBow7b-IZi5 zM?yWX=BQ2O$3DlTo^;@6Zx#=oNi&HoNmMIZyU~X3uww}6g4L7%l z3T5va24ypI#s3Q>XN?n-D{GN1FRKt~9XGkwIf_{Dvl66Xaw7~Cn`kq_&+%r z(d!w4_O)Eeu;&Wfpln?4gka(ZkkQmhlNt;5sfLkpZ-WCF(>8((cQV2PGXB`e$;kYJ zL-E|ipd9^zUvfcdyU7VkkQHQ=OPM?nDr*uH<5}ZEw<#?tzdIQ+GN9L6KcBxhL`6L;baj zn_Pk;A)9tFD7vphdA`dD%8A{`h_@9<-ZXA;=`^l!M;ZcPcST2tYDTCNhzij>`6eg5 z-5!SEP+eCt)G%aZU@JoQ00A!Tsk6tBbj%(tois83+qNQ16WVLDhv6olJxW_KI{u`c z!?1!JFA}pK+cT}Y^qs|+e zDvgI6A&0m{r4KQBx_%wl!b6xbAgbkI%owf9 z6U$))3y#ko=A5)Wg7m;WNJo$!z<=#JxBSHs><7x~sNJ@W39`esF@fD|V^S@{iT(UX z5fE$3xtML+n857JlMVra$HkO$+Ri=eC^wr;B8FoyJBH|frj9(OI`SAjbs>Be)$LDH_@-_yPz$y&Cy5SQ#j~>bJ)v+oR0< z*-3wolVGK-lO8n~)QLmWqXk2uYdlTlQx0j;_Y?^6ChgCFkVB_1hJeQ3u5w@xP662I zFSsigu=2k+0dqSIk?YCJvk=+yH0OBmX->}b(;%l$85eSFyA};}ITb^~8DQ9~cO}Q3 zDs0bk{fu*}q@Kkj^0Bm|B5e@ilZdK__@Cp*SXQK+1N40)fuU+ zJ?hw=W9(JvKWCdYT3rJX9h~&ISv(!~9E^x_0@-~H!0?w5(eXNn@Fn$cf{1O`K?DT; zeu)G5?K*(WcK<36({D~d-uwoU*y7%T$ksOy{?OI^2G@D}2FU1N!kG*PQr%{#AkCFj z3~@Jsp=Taf4EFG6JB(8|5&o16b*4zZh49ZQ?x;v*!#-1_o&+-e?;IHm|8>6u`XOSz z4d|bK=WNW%m`i-o?LoEz4S`;(kmFfGoQJ+!&U|fVB5-QsCK+^LN)C* zM7fjGuXzGIe$7oE_6EK_9_9#EO#pQo(7-M@!%6XZ3sNR|yQ)_cfT_pkq4Qg)$L)UV z=Aq0xkkZ{r48fcxI)O;Hi=VMH(q`xku7e~*C>9sWAa zf$e<{U@!B36xn9&@>EdjR$_PeOZTT?nI_x%i4Mq>*j}IqDVye~2N> z#kEx&UBnPvT4gwF`xJz}ZJz>q**;~p7~&XvqxBH!MfT}K7`wOhTwO1>keFhpLLBk2 z(6?;}RD9+|Cm9V(-J$)o4`snwyFK#RexRwllXjyAXz1mnMvZ)R=+|hN>ft~`kvza0 zLVWXrhDmui4G(_i?%0$EKx%v)$n!i-Ku&l)biD5dn?2lFnB6bv#P30$kVfUKk|T#|ysLLPfx}e9yKRVz zJ5COl4#6!Az9IG@?u0Mw{ekQ>P%rtZUh;#zKl)KXsoG5^hrP;Nxr{_$ZDRlx| zNwFsY+X2j!kN}hvb*PV)kpS3c%18hQ+kea8u^=0{?JV~D8Ugq`X>S7HLq-nxtP!^F z{DL!b=`A0E*oR?{LlFDl1(6mCVjstY6>jiz1+ib4$_}OQo*m(4C758=H-WBZ*<+uD z+I5o?wOd2s>jQy~^f6!C*889@;iQAT(~eMk)q7pz!jSO5#wLKYFc|$KNhw0T6poP( zy&9?Ls)qyJX-0a2mI$5>yAdQp0=>l~Hrxqa$HEYa2bK#X5uoNkVNOB4BJlae07uXs zG(c^Oe+_ifVNOm~5vU&#M9FbhZ;v~+_%B}6N&SCCF$45>(xWDVeFmW9kUqsYFvf#h zaeyw0r6P$ zm4}+0!LDZ66M%)-sq#+LuBZSXAMtafPfY-I@GnLe{qV8AqJxjuRfN5hh&h5fq$0Ps znF^#tB>)KvHkWi*=Ofl_>--Yx?qgUbCm@X~LnNN+tIX-$QkknO9|8CN>g$M4jdgX< zSMixw?dLpXMnL^}$yL1?>r6e?`9W2n9*^s&>-;BGFc1uO(!+SLt@D{4wATjxi2Z!f z-%=F=Uo&+KcvBTdlq7d*fS1Ui(AO^bD^D+ddgxZBqkZi#KaMCw}Ke!r{jYIC97w zZd>Jp!_1QoM$fbInXYAh2ZtxthrRJ6z7h3Oebr0#VebeADAQrEx2^U8D3cEMy&5g_CR}&afmRxEMKI$~(e6(x|K4#-{ zd0zpvqp1_1Y0V%C`^T0L^+z)<>Txqp%CP1jWomvGQf$k94Q!h|oD`oHAf<-M6@xti z*s{NK3+Du=&=LuNjb%&c1o$hB$HL>5+;$fG5v>6D1_^5m!1G&SP(<*oOXK?Ywu1i6 zUvNq;{W-084jgEW92k+0NNsoy)M~>GKhg#{fTvK}@*MbgHy0n>7UH{xx|(Ot0Tyx_ z+d5G^u^k5gQ+XX}RCB;S_@^QV$h~%4J)7XCwTGS4$%u~BG3~jX?NlJ1Q2=t9@to=q z`?eK7f-jZEe%mM~AVoSrWC$79fye&b4qRQqj&SoWFGqZ8?Ar%_iqE`Z7v~|hBh>#8 zMtN{nZy)^GivN8_sK;}e>fnFw8}Km7NspW57l#!;!YTFS5bXFn0T}-B9e*c)u1Jn{ z1rKFAg9ixwZzl)Rr89s$WDfa%fvoQA1Y~pXKit)NdyuiEeba6Ta%#Og%7=DGkYhX99qdEl)b3m%3+f_0 zLh$5C9x|v$h>7;ul*$d<)C0P7U)S}#2Lc*GxAa6n|B#2|{T2a@-9B|E-_i!0}G zb}^$~eW*>d@$(L@xLq$OUSHVNNPDQW2qV3mm>m+0;q9!4qaNmB+d?0D65wLn{GPaj zJZpzdUFjI4H~=%3kB)(VW|Nq{)ITw*e_}Aa1v5YiTF5`3YaBbE1RC=7dOHC!^nob6 z^}7!zeL^43M@}E`aogPyrw0v1+uB~kY1z*CNbU01gAovLB&-p0bAAD5&I-rI9odES608!X8 z4u+^h1GuQO12`#d2O{+665TL_zWPL)Mnk7pQUU(-tyxg0|VMFaqm5EfM;TfVbw8_M@q{MyTEz0Xjw$GkZBK{E-N@g}2&kK&0icoZk)`6!TbPv;0$O$2r9*T8PKa8eRRgOsomuIkl9VCu2%xjq`| z@%+6y_HX?Gq)c$q!$`3${FxrK*Va9aEIbhgk3neQ#aC=#NE-tqYLJv4!H4%)%muWA z3at8A05cc=DzMnGPQW^jgGlTtCqU%3aiAEw4vYgi_*?HsB*a4Ua1^Fg(H47)h>9ukMrzg8H`lWiR zvw>!%hpM?kEHuZIajR*Y< z2OieV0O&fzJR3ZGn!$PSRDqP32_P?-L;hbN!)7`GX*3HWv2UCUkt=8MVBa!}>nuMT z!M>Q>SzsUiHS@n+&&|)A4XxYCxSDSdK(@ROn&TAgz*f1I!Kx&RKZ z_tC}S*wOPR4K$1MuHzPmE`-Hb%eq=@4}2DH{TDj%Tsr}y-SvMR^{9bwp8`@5__on5 zc`d2C1=Ie=1c%YCks01vLMkRwZ<$qZnZZPT1}N1b0cNH?63n|GXvO zW2%!LH_Il6l|Oh-J&E?(=-+A$dA1&Wv|I{4@K$3sFeEO85%o#@GVt+qDfmFe$EDz7 z;MW25B2IuJeu5}$B9}wd{GYg}D|2WvkhbMG%-&aGuR@YizWz|;4n)C$BfV6|KUOJ|q= zs?HrNkOOExcqMXR`g?L_CGY=uB{y%_D)_wNduN|BU)TqKW^93EZmiF07+a&Ft73Z& zu#oG#+KJ*a$?*BDcaD0P&uv=)_&mYU=j&Ee7Wg^;r70KjD)SD&Pu^R z2>w!`sFUpt~>j<@X%G{^gK084jhRBVfIrNW*VEcTl2aPojL6{~^UuN-x$ ziJ?vo|A1l|3R6=ZLZQe`gaV%ONJA)0+Q~y+A(F3?-$70J7s(@}ai*SKRh=y?6o5u%z0>b#&rG#^gl2->B=A3vB}^{aWn z^fx|gC21kvI&r~EvSCliKVrw1WI=jJ%kbc@cl?-6JHCBE^6o{)124#{z35mr)K#Mz z0Ze1-qt;&gXvZEe$k6>E|LDTWHwQvmg?L7JE3< z=Waf>kF;2-lq;6ASHSB()$%SLcu!t{W#>L2F++^ZzJR(=Auj5tePk8dil_II3rm$+ z!MQ{&Ky%t`EG}2AQd*E9L@6X5+)HK7TMCl0NlL>&Hy15ImfbKkNeM6Z z!s<%odbFoR9zz{vXdVbmQflh<6WPrO z-lZzQ60U--hdK({iym9apDUEAVl^uXT&WZj+gM56l?qN`k(iZ=AvdVkRx)EHVynUz zq~Apur6ebvOFwO;v89j?D-|E{-*l39m1}?0d6z3yNwXBBLgRGO4K5W^)47Xlr85`%mO~#$7kiPTDM}*; zGMV;^=_GIsJnZeF-C#MAPCC&#!KE(HvLl@=U858$`FM|w4Hb2Og|a}Ma0qqO#WQhS zm%QAd1d;#NC`PyDI403+6@%^yF>g>RkeIcKf3f2(k^(Iwsb)x8s7mUZZcSRNjMX`e z5zLDGXh$`@-9t*PSHc52p?xxP@hx(YCYXq~64oYlHY*Vh3C?=rC3%|_Q?bG>$_>nJ)h@TxF6+r93#^XYp!nbwOd~8xmC^>h z!qwmM7aFKRWOMckDiHeishy|t&Z*lJZ_mHR|4QGjnMq~TDthz_y?<1DFI9U-)85rY z3$8J4R|0)kp_oQP7#(_`WCy9ZMX4M(-$hb@rR5%SVY?Dubh=BOzom|4avy`mH=0 zpLJ9ybRJa&%uOScH!4+eW~%3QCCKkIiX9ogxtsjCQK=NL*F{u-WehpLT`62M)uqbc zGCsF<3;2cQE&Ghiyr0!;=a&D?k zD%G7`02wTPkV>g8uL8>6&8QYT>?Y4PE0u~jap@Cad4)3Cr=Z&B#%?>;2C7?v7(IPz&ffUoj>pB1KF#Y({_;sJCs1fCavC` z*YCqI$#~*kh-B_id>iL-To-6Bjn`3E!Jd6j-N@`T5WuB!Z3*a2t&71viBAm%OUvD) zSgH~pIQwqrp^gSipmlw!@~aLfI)B`yR0uB0Uk%7KVRG7_ zwpzH09NVQNiLY=ieYf(;YY&s`Zz)IOcPS+bb|)E`t|aL^tlm~duk-pD<&=fGq++_Oj!3l^f_<-Y)+30atYdBNzcn5EOWe3@QNQuG| z4Z6dMNvxl04L_`iy1Y1Z$za}iLxvtwis$Y=LG9jm2N`-qi3%q>1cMf7{>bG>`favo zyw_e362e~8Ghfblxj7?VyH}JxZwBZJ|%)-mo&@zi! zwx5@cqGkKlvctS=C@njzmL20|18LbYwd^D>>r2Z{3fZ3~6sf=YP1|Fe=$qvCZ50fk zCLGxesuF}yd`o~*RiUtX~-F#JAk_A18QBUXG5Dp4^$pR zW!w?9vYn@`E@z97$U+8;GoW$yx({1OsWS@6hqpzTyzPGwpO<_( zqm&mvZzbi0SpSP0q^Ge-GTU+0xTxtke%JZXW|H{5-e5g= zQK_K|@yyTmr{|zj&Fjc7T!OBi;A%2%|l3=%mw7H~&heI5j5#t1*;|%=X;~|Xr zE++@Gqk%2KCtJv(OG@d0BKgf>9z4e0pc$Ql&RWRjOG^3JC;82x)lj7SV1-{Tl>Td; zLL%b867NA@yzg(R@k>7m5su?zge}G27QZ#Ww8C$#A8of&?Z;$~^ES_^ zDv(}Rl;9y70Adt~AJvbNV0RjI)Ra-qPGEM#d7BGX;UJhW*z+t8A|5h4k9wOi2)v9I zXC<+^7vAP1)cJhNj^1(=#dO-%yt^D0b8EcD;~%M?PeK8{03<8|vG?>*#EIT)T}>0tHpy||b+I>#H` zg#cPEX`Mgt@+Ii}LG8R%1L0kefheR`Z7oxf0iT1m_t7>~-+Pr_=(j2of8Fqxa!VaS zzhdJ4IrjeLfAH~;GxdbTcWA5;yDP$ua*?J;B{fU47NpiiU0P49dclqm$-lr?17(cW z=z`{|_)WLf5n9<#1S87WqFa+o*A@Ss zPaw%w+=@57f~GVxwWjqb3M{n(*z7~K1X%t=nXL_rB7e(C^m9aCk<|Z9k=+bK1Ov(1 zsV@|}55MS``lhW8r(ea*pYW9i%^5Y|4BFW-1cRXDi;+IS$9&v_x33PzP_sMwb3a5k@i59A zn-Ny_f)jMcz-->>rE}`RV?uv3|3qmJMvkQ9YFtA#yi}W=|qHin(S{lk6 z`C6(0!c^tOj4@cY!Z5x1yApL8>S$`~GG--Fy9NxU8KP!h7hiLAP0=i0#BT!xME%Y0 zIv?Lu$wM%F=yedkac;h?xcESWQytSpT^z6n#Iou79s(!3g*pUaOde604<&R1 z++Gu^4jmZ|L&qm~L}CxMUxXhUSU;eQ8{}txi{EtUc&(LX_?cg@GK1wAD~r`;>4spW z0hp=3`9rT0o9??ik0Nw7V?zIh?60Q5W|H-3@BvW6!Wk8=86{@3l1>U0zT(G6n7Y%?}jkxcv-3 z$XVNvH-t4D?r+}m1*98*lqzc6M5P$6$p_asTK)+AzBq`y@HQ_+U4G3yST7NuwWdOd zdi#jH3#L0t!xvqg;4yRDrZoG=FsRO#(m7LKXc10I#o6QHIGON348ii+Dc>$wJ zVXD7*p-LfWOBKMtG3cP~8iV6&Eb;>_$q;2k;bojd;5J1)wVSeg zK!b3?pRIKx-GxBg7~+_|HHr6aB{UY0`T`PFr$HjB*^ZEYfC>upJq8&%(9n}c!*jt} z4Oour8yWQ?i?|?5+h{v8pC;JTWAX2sJY$(+gMqDpokLIat-<{Ff6l&b2jMiV1vh-p zoGJ0QJV%-5NC%%~8O)!71XE*%OT$$jW1B=!QS zlw1~a12i$sRGvn|b&1S%21~JAl5Bjq1(>lLWNvDzO6%jxkLlW{5bu}Z**<^`cC?>s z1SN#QUC%>o7AAyYPIO0CIuQa^g22}uXcu74r?S!*YG5gA`!68G@r1RveG_2bh;r73 zjV$&tKE+KitZsreA@zNgmiDmp_)bV%hE(wv3}?%u+#m#;WdIP;pDWr1eWvse2nV|f z+8Q{Shb~STd7EdWE~gu3w;BvlC!PeMRiJr_1}d$2pg9%?JjM-{vT8%>k{`83ZvxF@ z)Hb64tcXLK;aZznzGTN;Me2st^|D+n?m(N++{{!6GWXE>f|-h7l(95C$c&*gp~1l* zb3gn&`6S5PAAj%r6e5N1DPgfEYjd!Sk<>!w?O;S5lNlrPAvBH#uRx;Wnx~A^rsL88 zT^HbKTh`Ynm?d$92BJ%_xgvgRMBK)2$`~c0wAN;pZ(iFvvluylPbm`%d+8X|DwoZ@ z(ZwZlVDmD~&RN0e7ig)AeiRaxdkNZ(qXYV8!33(B?!Knr3)pXISso#qCjA@yWn3i( zn=t?eTFOF*w#{gShAbj}4rbB*UW*8IR}qf3+ODF8*7gtHR^qz~L=OiSgtplL$CRl% zjd2*!=;nd0FH5>1e3`O6K1|s)D5HR4AXs!0F45oAf|EF=otPjW$t-J%gC*8a)-6ez z2nJRZmdr@`gv3%3*a?CXBepIEiyqFSptJOnt?V;oyw}Il!eCorHVP?XiVgs1*zIB7 zt{}nN!Io6Lnv9{6c^iK7sUQ&TWy@x*u7_mafZy~xi|e$qS&})0l?7Q=Yh{qJq7*9( zuq0`PTO~8WZ@L*{)}~23j(?Yk=^rJeho@uwBBNhaaE{-L=UhaAdIIWRc4eb| zf}qCl7)>#fXmMmmqizT}N__lD=6%Jxf*_mE=aRn_?Gc!CFOU$%*1G|gjl3)^l*DXw z^CzJX6nCH6GCbgKnQEj&7%a<4l?O`UVC_Z`n=^63fHw0XBOWM0t;&LObxo=Y546NX zcqGmhFohkd)BwvwM-VtKK+DFWOwdLN%vg&vHyP-LJt1r~?G$Jkj0SONz{+NELH$rh zQ-ubJLjYBm7S-h>{C?J0b0~L(2{{^bzM`ut4Xj?bcP*tWE$^f)3r$!a(hQer#!V+9j zj_82C3orW@Wzhh6hwL2b?msXI`q0fjMLv=7jY!8S(!PSBUQ7~In^n^8p{<=XuHsKe zwI_Jl4HEKP2`alYmw6Y_)aEmsX`qq!8_Fm>9AVjZT9+&;DbRu?p-Y!voVvtb|4$`R zb<7S_+Z^)~2ZRfR4xZ&@>s2vd3g1vorfN8du)|=xn*hsN-d|Lq$9C8Hs5s`J9%S>B z`H$_$Xr4dv;{LNTfBd;qs(c%%)rao$Tt@Y z_-N!*tbonYa&44R>CcOXHp^G=&hCx^f9GXT`admysDV^t@vY7wuJVU6BVXtQVtTFw z1n<`xNAL>VUh9xvzSB`n!3xtt*=c~MWao3-2=!kmxri~Y90up}=)k7HvSD~1VPrPl zHdNNlN-9C$Re8tP?5|VTKTq-#{})R2*v!P9W^ki0^BO@N>53Evu*mEh=yMc*LkloM6NLW? z(5(l=~(1De&xU)r?~1N$PBu8cABm}I`WmF0k;_xeW#dwaRoS0zz2l+$#k4IAoD*c zCK6Z7JwJ(ir+DHC@7eE^Ub+k9;X9>#;EQA|dN5Fi;h%Ql>BSmS?!D5&?;%7vUL<+E zhRk`dH1NKHa=I0u>#0lR#(Tx&c8D6}Q_riAXC#<9x<)W8`p!Tqd{Dgp7xdlep+Qe2 zJ%Q2J4@Hj93sC5-e2m2yw>oU{2cbn4c{$u{#9Bw`HZf7 z?H*wHh~ISSNYBiD!0&7BLK$s!&gn^mUx;XgMuM3l%@kLnT71aw(CV` z*T^NkOaWd6P=~LJXJ?S3zbgLji&hDV<~>VH1$9-9L2Cy1r6EPnL*FhSy!_?ZtR%eG z#jHyBBnZN%)3`S2l`L!)UQYUT54oW;6-J_c(wRz&pI4JoqN!?r1wupc&xn5{<2VL^ zIMI|}H;c>{O+^ZIjbvi#`3f&f9G#UEpo;pDoEA;8ZXCWdZz}HjdZm!~3jc`D#4ub0 z@e6ZzbB~MaMJnn|hB7@PKgIe9F9!e|1?1@|WCsEaU1W5C5j33RU?M$kOGfBTgWZon z)M0W*Z|bhwiq~hFN|TKJIv>(bXYwGE-AoPe;6F+Si&?8kId_v>0vecPm<}>G2QcXY zmS15I4M#3Lz;cm{a5t6rJ&ocRKYFiK09H7GmY>N^cT+w0nowGUDh(p}Jxr0h5~Q_< zsiEIrs*q^(pr^s1bB%|oh4^s=dFEldi`Rc$%3}(O@ss>A z)6`B}T87l}GL;Sf9@g-r4zdiw??QTEuHY}2&ysjAQ&4anW-PtJA7~i?WPDf)#4d8D zm#IsUFW|ee5cdYy^aWU=IL1bKO(kOs6=x>aQB7QmRQN@Vtbrw61dWLzP(}w4AxV1AEs>Q1_+FRjX<+5QcF|1Zim0uoI*GBKa20QonsNiK9J z#O4P_Uo9bJ^O-`csIG8VhXfKykDDu>vDPL7v;G_>D8sY1I2UeS{j+^!j(F zMbYvSSoe7PmSWFfP<1gs&yKR79R6U@9fo!rXgiD#^f?XMCLXt8q@e6y+*Z}CPl&nM z@gpA|h#%5PR(_MaTeC9e8{}brlL;S*_wvS{^`xY?NsgV09#tWQYG<1A$3;y>*@Hg( zYtpo={=I2YKcb9{!ro@_KhQ%4(3Xy0ZlUr9>EM)kbqktii-of>%e)hxVj6rIoITn`%1l{7K!r3__?v*Zk zaUNXBpsA5Zh**mDSDr;?M_>uE1i$x8$zx9TsQ-ax`aE*T#}rg(3q(aDbgrXW&Sc>w zriP9*RVmoOJpPtAsC`Z57c@21MNq_w?gbg{i&cUKSLaDmd`*MHu!c*Z&;5AnBC{Vt z0RCk&4~3S%-oVo`ij?&;l@BWjd4ldkRhAivC2%UWDK6$U!Nt7Bn{)J{Ih9QEGs)un z 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 U66x 0)) { _if_result_9 = (lim_url); } else { _if_result_9 = (lim_body); } _if_result_9; }); - el_val_t limit = ({ el_val_t _if_result_10 = 0; if ((lim_either > 0)) { _if_result_10 = (lim_either); } else { _if_result_10 = (20); } _if_result_10; }); + el_val_t lim_either = ({ el_val_t _if_result_10 = 0; if ((lim_url > 0)) { _if_result_10 = (lim_url); } else { _if_result_10 = (lim_body); } _if_result_10; }); + el_val_t limit = ({ el_val_t _if_result_11 = 0; if ((lim_either > 0)) { _if_result_11 = (lim_either); } else { _if_result_11 = (20); } _if_result_11; }); return engram_search_json(q, limit); return 0; } el_val_t route_activate(el_val_t method, el_val_t path, el_val_t body) { - el_val_t q = ({ el_val_t _if_result_11 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_11 = (query_param(path, EL_STR("q"))); } else { _if_result_11 = (json_get_string(body, EL_STR("query"))); } _if_result_11; }); + el_val_t q = ({ el_val_t _if_result_12 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_12 = (query_param(path, EL_STR("q"))); } else { _if_result_12 = (json_get_string(body, EL_STR("query"))); } _if_result_12; }); if (str_eq(q, EL_STR(""))) { return err_json(EL_STR("missing query")); } - el_val_t d_raw = ({ el_val_t _if_result_12 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_12 = (query_int(path, EL_STR("depth"), 3)); } else { _if_result_12 = (json_get_int(body, EL_STR("depth"))); } _if_result_12; }); - el_val_t depth = ({ el_val_t _if_result_13 = 0; if ((d_raw > 0)) { _if_result_13 = (d_raw); } else { _if_result_13 = (3); } _if_result_13; }); + el_val_t d_raw = ({ el_val_t _if_result_13 = 0; if (str_eq(method, EL_STR("GET"))) { _if_result_13 = (query_int(path, EL_STR("depth"), 3)); } else { _if_result_13 = (json_get_int(body, EL_STR("depth"))); } _if_result_13; }); + el_val_t depth = ({ el_val_t _if_result_14 = 0; if ((d_raw > 0)) { _if_result_14 = (d_raw); } else { _if_result_14 = (3); } _if_result_14; }); return el_str_concat(el_str_concat(EL_STR("{\"results\":"), engram_activate_json(q, depth)), EL_STR("}")); return 0; } @@ -206,9 +209,9 @@ el_val_t route_create_edge(el_val_t method, el_val_t path, el_val_t body) { el_val_t from_id = json_get_string(body, EL_STR("from_id")); el_val_t to_id = json_get_string(body, EL_STR("to_id")); el_val_t rel_raw = json_get_string(body, EL_STR("relation")); - el_val_t relation = ({ el_val_t _if_result_14 = 0; if (str_eq(rel_raw, EL_STR(""))) { _if_result_14 = (EL_STR("associates")); } else { _if_result_14 = (rel_raw); } _if_result_14; }); - el_val_t w_raw = json_get_float(body, EL_STR("weight")); - el_val_t weight = ({ el_val_t _if_result_15 = 0; if ((w_raw == el_from_float(0.0))) { _if_result_15 = (el_from_float(0.5)); } else { _if_result_15 = (w_raw); } _if_result_15; }); + el_val_t relation = ({ el_val_t _if_result_15 = 0; if (str_eq(rel_raw, EL_STR(""))) { _if_result_15 = (EL_STR("associates")); } else { _if_result_15 = (rel_raw); } _if_result_15; }); + el_val_t w_present = json_get_raw(body, EL_STR("weight")); + el_val_t weight = ({ el_val_t _if_result_16 = 0; if (str_eq(w_present, EL_STR(""))) { _if_result_16 = (el_from_float(0.5)); } else { _if_result_16 = (json_get_float(body, EL_STR("weight"))); } _if_result_16; }); engram_connect(from_id, to_id, weight, relation); el_val_t saved = persist_canonical(); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"from_id\":\""), from_id), EL_STR("\",\"to_id\":\"")), to_id), EL_STR("\",\"relation\":\"")), relation), EL_STR("\"}")); @@ -250,8 +253,8 @@ el_val_t route_forget(el_val_t method, el_val_t path, el_val_t body) { el_val_t route_save(el_val_t method, el_val_t path, el_val_t body) { el_val_t p_raw = json_get_string(body, EL_STR("path")); el_val_t dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); - el_val_t dir = ({ el_val_t _if_result_16 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_16 = (EL_STR("/tmp/engram")); } else { _if_result_16 = (dir_raw); } _if_result_16; }); - el_val_t p = ({ el_val_t _if_result_17 = 0; if (str_eq(p_raw, EL_STR(""))) { _if_result_17 = (el_str_concat(dir, EL_STR("/snapshot.json"))); } else { _if_result_17 = (p_raw); } _if_result_17; }); + el_val_t dir = ({ el_val_t _if_result_17 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_17 = (EL_STR("/tmp/engram")); } else { _if_result_17 = (dir_raw); } _if_result_17; }); + el_val_t p = ({ el_val_t _if_result_18 = 0; if (str_eq(p_raw, EL_STR(""))) { _if_result_18 = (el_str_concat(dir, EL_STR("/snapshot.json"))); } else { _if_result_18 = (p_raw); } _if_result_18; }); engram_save(p); return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"path\":\""), p), EL_STR("\"}")); return 0; @@ -260,15 +263,15 @@ el_val_t route_save(el_val_t method, el_val_t path, el_val_t body) { el_val_t route_load(el_val_t method, el_val_t path, el_val_t body) { el_val_t p_raw = json_get_string(body, EL_STR("path")); el_val_t dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); - el_val_t dir = ({ el_val_t _if_result_18 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_18 = (EL_STR("/tmp/engram")); } else { _if_result_18 = (dir_raw); } _if_result_18; }); - el_val_t p = ({ el_val_t _if_result_19 = 0; if (str_eq(p_raw, EL_STR(""))) { _if_result_19 = (el_str_concat(dir, EL_STR("/snapshot.json"))); } else { _if_result_19 = (p_raw); } _if_result_19; }); + el_val_t dir = ({ el_val_t _if_result_19 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_19 = (EL_STR("/tmp/engram")); } else { _if_result_19 = (dir_raw); } _if_result_19; }); + el_val_t p = ({ el_val_t _if_result_20 = 0; if (str_eq(p_raw, EL_STR(""))) { _if_result_20 = (el_str_concat(dir, EL_STR("/snapshot.json"))); } else { _if_result_20 = (p_raw); } _if_result_20; }); engram_load(p); return ok_json(); return 0; } el_val_t route_health(el_val_t method, el_val_t path, el_val_t body) { - return EL_STR("{\"status\":\"ok\",\"engine\":\"engram-runtime-native\"}"); + return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"status\":\"ok\",\"engine\":\"engram-runtime-native\",\"node_count\":"), int_to_str(engram_node_count())), EL_STR(",\"edge_count\":")), int_to_str(engram_edge_count())), EL_STR("}")); return 0; } @@ -285,12 +288,12 @@ el_val_t route_embed_backfill(el_val_t method, el_val_t path, el_val_t body) { el_val_t route_sync(el_val_t method, el_val_t path, el_val_t body) { el_val_t dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); - el_val_t dir = ({ el_val_t _if_result_20 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_20 = (EL_STR("/tmp/engram")); } else { _if_result_20 = (dir_raw); } _if_result_20; }); + el_val_t dir = ({ el_val_t _if_result_21 = 0; if (str_eq(dir_raw, EL_STR(""))) { _if_result_21 = (EL_STR("/tmp/engram")); } else { _if_result_21 = (dir_raw); } _if_result_21; }); el_val_t snap_path = el_str_concat(dir, EL_STR("/.sync-export.json")); engram_save(snap_path); el_val_t snap = fs_read(snap_path); if (str_eq(snap, EL_STR(""))) { - return EL_STR("{\"nodes\":[],\"edges\":[]}"); + return err_json(EL_STR("sync export failed: snapshot unreadable")); } return snap; return 0; @@ -324,7 +327,7 @@ el_val_t route_emit_ise(el_val_t method, el_val_t path, el_val_t body) { el_val_t conf = el_from_float(0.8); el_val_t id = engram_node_full(content, EL_STR("InternalStateEvent"), EL_STR("state-event"), sal, imp, conf, EL_STR("Episodic"), EL_STR("[\"internal-state\",\"InternalStateEvent\"]")); el_val_t ret_raw = env(EL_STR("ENGRAM_ISE_RETENTION_MS")); - el_val_t ret_ms = ({ el_val_t _if_result_21 = 0; if (str_eq(ret_raw, EL_STR(""))) { _if_result_21 = (172800000); } else { _if_result_21 = (str_to_int(ret_raw)); } _if_result_21; }); + el_val_t ret_ms = ({ el_val_t _if_result_22 = 0; if (str_eq(ret_raw, EL_STR(""))) { _if_result_22 = (172800000); } else { _if_result_22 = (str_to_int(ret_raw)); } _if_result_22; }); el_val_t pruned = engram_prune_telemetry(ret_ms); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"id\":\""), id), EL_STR("\",\"pruned\":")), int_to_str(pruned)), EL_STR("}")); return 0; @@ -336,21 +339,21 @@ el_val_t route_capture_knowledge(el_val_t method, el_val_t path, el_val_t body) return err_json(EL_STR("missing content")); } el_val_t title = json_get_string(body, EL_STR("title")); - el_val_t label = ({ el_val_t _if_result_22 = 0; if (str_eq(title, EL_STR(""))) { _if_result_22 = (str_slice(content, 0, 60)); } else { _if_result_22 = (title); } _if_result_22; }); + el_val_t label = ({ el_val_t _if_result_23 = 0; if (str_eq(title, EL_STR(""))) { _if_result_23 = (str_slice(content, 0, 60)); } else { _if_result_23 = (title); } _if_result_23; }); el_val_t category_raw = json_get_string(body, EL_STR("category")); - el_val_t category = ({ el_val_t _if_result_23 = 0; if (str_eq(category_raw, EL_STR(""))) { _if_result_23 = (EL_STR("other")); } else { _if_result_23 = (category_raw); } _if_result_23; }); + el_val_t category = ({ el_val_t _if_result_24 = 0; if (str_eq(category_raw, EL_STR(""))) { _if_result_24 = (EL_STR("other")); } else { _if_result_24 = (category_raw); } _if_result_24; }); el_val_t ktier_raw = json_get_string(body, EL_STR("tier")); - el_val_t ktier = ({ el_val_t _if_result_24 = 0; if (str_eq(ktier_raw, EL_STR(""))) { _if_result_24 = (EL_STR("note")); } else { _if_result_24 = (ktier_raw); } _if_result_24; }); + el_val_t ktier = ({ el_val_t _if_result_25 = 0; if (str_eq(ktier_raw, EL_STR(""))) { _if_result_25 = (EL_STR("note")); } else { _if_result_25 = (ktier_raw); } _if_result_25; }); el_val_t project = json_get_string(body, EL_STR("project")); el_val_t tags_raw = json_get_raw(body, EL_STR("tags")); - el_val_t tags_base = ({ el_val_t _if_result_25 = 0; if (str_eq(tags_raw, EL_STR(""))) { _if_result_25 = (EL_STR("[]")); } else { _if_result_25 = (tags_raw); } _if_result_25; }); + el_val_t tags_base = ({ el_val_t _if_result_26 = 0; if (str_eq(tags_raw, EL_STR(""))) { _if_result_26 = (EL_STR("[]")); } else { _if_result_26 = (tags_raw); } _if_result_26; }); el_val_t base_len = str_len(tags_base); el_val_t head = str_slice(tags_base, 0, (base_len - 1)); - el_val_t sep = ({ el_val_t _if_result_26 = 0; if (str_eq(head, EL_STR("["))) { _if_result_26 = (EL_STR("")); } else { _if_result_26 = (EL_STR(",")); } _if_result_26; }); + el_val_t sep = ({ el_val_t _if_result_27 = 0; if (str_eq(head, EL_STR("["))) { _if_result_27 = (EL_STR("")); } else { _if_result_27 = (EL_STR(",")); } _if_result_27; }); el_val_t safe_cat = str_replace(category, EL_STR("\""), EL_STR("'")); el_val_t safe_tier = str_replace(ktier, EL_STR("\""), EL_STR("'")); el_val_t safe_proj = str_replace(project, EL_STR("\""), EL_STR("'")); - el_val_t proj_tag = ({ el_val_t _if_result_27 = 0; if (str_eq(safe_proj, EL_STR(""))) { _if_result_27 = (EL_STR("")); } else { _if_result_27 = (el_str_concat(el_str_concat(EL_STR(",\"project:"), safe_proj), EL_STR("\""))); } _if_result_27; }); + el_val_t proj_tag = ({ el_val_t _if_result_28 = 0; if (str_eq(safe_proj, EL_STR(""))) { _if_result_28 = (EL_STR("")); } else { _if_result_28 = (el_str_concat(el_str_concat(EL_STR(",\"project:"), safe_proj), EL_STR("\""))); } _if_result_28; }); el_val_t tags = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(head, sep), EL_STR("\"category:")), safe_cat), EL_STR("\",\"tier:")), safe_tier), EL_STR("\"")), proj_tag), EL_STR("]")); el_val_t sal = el_from_float(0.5); el_val_t imp = el_from_float(0.5); @@ -361,6 +364,20 @@ el_val_t route_capture_knowledge(el_val_t method, el_val_t path, el_val_t body) return 0; } +el_val_t route_similarity(el_val_t method, el_val_t path, el_val_t body) { + el_val_t a = query_param(path, EL_STR("a")); + el_val_t b = query_param(path, EL_STR("b")); + if (str_eq(a, EL_STR(""))) { + return err_json(EL_STR("missing a")); + } + if (str_eq(b, EL_STR(""))) { + return err_json(EL_STR("missing b")); + } + el_val_t sim = engram_cosine_sim(a, b); + return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"a\":\""), a), EL_STR("\",\"b\":\"")), b), EL_STR("\",\"cosine\":")), float_to_str(sim)), EL_STR("}")); + return 0; +} + el_val_t check_auth_ok(el_val_t method, el_val_t body) { el_val_t key = env(EL_STR("ENGRAM_API_KEY")); if (str_eq(key, EL_STR(""))) { @@ -447,6 +464,9 @@ el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) { if (str_eq(clean, EL_STR("/api/embed-backfill"))) { return route_embed_backfill(method, path, body); } + if (str_eq(method, EL_STR("GET")) && str_starts_with(clean, EL_STR("/api/similarity"))) { + return route_similarity(method, path, body); + } return el_str_concat(el_str_concat(EL_STR("{\"error\":\"not found\",\"path\":\""), clean), EL_STR("\"}")); return 0; } @@ -454,10 +474,10 @@ el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) { int main(int _argc, char** _argv) { el_runtime_init_args(_argc, _argv); bind_raw = env(EL_STR("ENGRAM_BIND")); - bind_str = ({ el_val_t _if_result_28 = 0; if (str_eq(bind_raw, EL_STR(""))) { _if_result_28 = (EL_STR(":8742")); } else { _if_result_28 = (bind_raw); } _if_result_28; }); + bind_str = ({ el_val_t _if_result_29 = 0; if (str_eq(bind_raw, EL_STR(""))) { _if_result_29 = (EL_STR(":8742")); } else { _if_result_29 = (bind_raw); } _if_result_29; }); port = parse_port(bind_str); data_dir_raw = env(EL_STR("ENGRAM_DATA_DIR")); - data_dir = ({ el_val_t _if_result_29 = 0; if (str_eq(data_dir_raw, EL_STR(""))) { _if_result_29 = (EL_STR("/tmp/engram")); } else { _if_result_29 = (data_dir_raw); } _if_result_29; }); + data_dir = ({ el_val_t _if_result_30 = 0; if (str_eq(data_dir_raw, EL_STR(""))) { _if_result_30 = (EL_STR("/tmp/engram")); } else { _if_result_30 = (data_dir_raw); } _if_result_30; }); snapshot_path = el_str_concat(data_dir, EL_STR("/snapshot.json")); engram_load(snapshot_path); boot_snap = fs_read(snapshot_path); diff --git a/engram/src/server.el b/engram/src/server.el index ace3047..2cab032 100644 --- a/engram/src/server.el +++ b/engram/src/server.el @@ -311,7 +311,16 @@ fn route_sync(method: String, path: String, body: String) -> String { let snap_path: String = dir + "/.sync-export.json" engram_save(snap_path) let snap: String = fs_read(snap_path) - if str_eq(snap, "") { return "{\"nodes\":[],\"edges\":[]}" } + // 2026-08-02 self-review: this used to return {"nodes":[],"edges":[]} when + // the export/read failed. The soul's sync_ok test (awareness.el) only + // checks for "" and "{}", so that placeholder PASSED as a healthy sync: + // soul.last_sync_ok_ts got stamped, sync_age_ms stayed green, the + // sync_empty warn ISE never fired, and engram_sync reported added:0 + // forever. A totally broken sync was indistinguishable from a quiet + // healthy one — the exact failure class this route was added to fix in + // the first place (see 2026-06-27 note above). Return a real error so the + // failure is loud on both sides. + if str_eq(snap, "") { return err_json("sync export failed: snapshot unreadable") } return snap } diff --git a/lang/releases/v1.0.0-20260501/el_runtime.c b/lang/releases/v1.0.0-20260501/el_runtime.c index eb74eeb..b83afb1 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.c +++ b/lang/releases/v1.0.0-20260501/el_runtime.c @@ -5633,6 +5633,43 @@ void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, * exceed the floor, so naturally-promoted nodes survive multiple decay cycles. * Invariant maintained: BREAKTHROUGH_WEIGHT < min(type_thresholds). */ #define ENGRAM_BREAKTHROUGH_WEIGHT 0.10 +/* ENGRAM_BREAKTHROUGH_BUDGET / ENGRAM_BREAKTHROUGH_COOLDOWN (2026-08-02 + * self-review): the breakthrough path was an unbounded, self-resetting loop. + * Every reached node failing its type threshold incremented suppression_count; + * on the 5th failure it was force-promoted at exactly 0.10 AND had its counter + * reset to 0 — so it re-entered the identical cycle immediately. Because + * BREAKTHROUGH_WEIGHT (0.10) > WM_FLOOR (0.05), all of them cleared the + * absolute floor and entered the rank contest tied at 0.10, where all but a + * handful were evicted by ENGRAM_WM_CAP. Evicted nodes get no access_ts + * record (Pass 6 skips wm_weights<=0), so the short-term inhibition-of-return + * damper at ENGRAM_STI_TS never applied to them and they were re-suppressed + * completely unmarked. Steady state: N_suppressed/5 breakthroughs per call, + * essentially all of them evicted the same call. + * + * Live telemetry 2026-08-02 (boot 19, uptime 23h48m): breakthroughs_delta + * 661–903 and wm_evicted_delta 485–717 PER 60s heartbeat against wm_active + * pinned at 22–24. At ~4 activate calls/minute that is ~165–225 breakthroughs + * per call — ~825–1125 nodes cycling in 5-call lockstep. Working memory was + * not remembering; it was thrashing, and the churn drowned genuine promotion. + * + * Two bounds, both required: + * BUDGET — at most WM_CAP/4 (6) intrusive thoughts may surface per call. + * Breakthrough is meant to be an occasional intrusive thought, + * not a stampede; it can never again exceed a quarter of WM. + * COOLDOWN — on breakthrough, suppression_count is set NEGATIVE rather than + * 0, so the node needs COOLDOWN+SUPPRESSION_BREAKTHROUGH further + * suppressions before it may surface again (~60 calls ≈ 15 min at + * the current cadence, vs 5 calls ≈ 75s before). This is + * inhibition-of-return applied to the breakthrough path, matching + * the STI damper already applied to the natural path. Stored in + * the existing int32_t field — serialized as %d and parsed via + * eg_get_int_field, so negative values round-trip through + * snapshots without a struct or format change. + * When the budget or cooldown blocks a breakthrough, suppression_count is NOT + * reset — it saturates, so a starved node surfaces on a later call rather than + * restarting its climb. */ +#define ENGRAM_BREAKTHROUGH_BUDGET (ENGRAM_WM_CAP / 4) +#define ENGRAM_BREAKTHROUGH_COOLDOWN 55 /* ENGRAM_WM_CAP: hard limit on concurrent working-memory nodes (2026-06-30 * self-review, porting fix from self-review 2026-06-26 branch). Without this, * broad curiosity seeds like "knowledge" promote 500+ nodes simultaneously — @@ -6032,7 +6069,12 @@ static int64_t _eg_embed_breaker_until = 0; * between) missed nearly every eviction/breakthrough event. Consumers wanting * rates keep the previous reading and diff. Restart legitimately resets to 0. */ static int64_t _eg_act_breakthroughs = 0; /* forced promotions at the floor, cumulative */ -static int64_t _eg_act_wm_evicted = 0; /* Pass 4 over-cap evictions, cumulative */ +static int64_t _eg_act_wm_evicted = 0; /* ALL WM evictions, cumulative (see below) */ +/* 2026-08-02 self-review: this counted only the three Pass 4 / Pass 5 floor + * and rank paths. The two carry-over eviction paths (base-level below τ, and + * decayed weight below WM_FLOOR) were silent, so the reported eviction rate + * was an undercount of unknown magnitude — which mattered precisely while + * diagnosing the breakthrough storm. All five paths now increment. */ static int64_t engram_now_ms(void); /* defined in the store section below */ @@ -8006,6 +8048,8 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { free(best_bg); free(best_hops); free(reached); free(seeds); free(fr); free(inhibition); free(cosq); return out; } + /* Per-call breakthrough budget (2026-08-02) — see ENGRAM_BREAKTHROUGH_BUDGET. */ + int64_t bt_budget = ENGRAM_BREAKTHROUGH_BUDGET; for (int64_t i = 0; i < g->node_count; i++) { if (!reached[i] || best_bg[i] <= 0.0) continue; EngramNode* n = &g->nodes[i]; @@ -8043,21 +8087,10 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { if (inh > 1.0) inh = 1.0; double suppress = 1.0 - (1.0 - ENGRAM_INHIBITION_FACTOR) * inh; raw_wm *= suppress; - /* Additive semantic-relevance term (2026-07-24, bl-b2d1c944): - * shift-and-floor at S0 — nomic-embed scores unrelated pairs - * 0.4–0.5, so raw cosine in a weighted sum would be a constant - * bias swamping the decayed base-level signal. Above S0 the term - * ramps 0 → WM_WEIGHT, breaking ties among structurally equivalent - * candidates in favor of nodes that mean what the query means. */ - if (cosq && cosq[i] > ENGRAM_EMBED_S0) { - raw_wm += ENGRAM_EMBED_WM_WEIGHT - * (cosq[i] - ENGRAM_EMBED_S0) / (1.0 - ENGRAM_EMBED_S0); - } /* Short-term inhibition-of-return (2026-07-25, Lebiere-Best): * damp by t_n/(t_n + t_s) where t_n = seconds since the most - * recent recorded access (WM promotion / strengthen). Applied - * after the cosine term so the WHOLE score rotates — a node that - * just held a WM slot yields it even to semantically weaker + * recent recorded access (WM promotion / strengthen). A node that + * just held a WM slot yields it even to structurally stronger * competitors, and recovers as t_n grows. access_ts is recorded * at promotion, so persistent WM residents self-inhibit. Nodes * with no access history (never promoted) are uninhibited. @@ -8070,6 +8103,27 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { if (sti_tn < 0.1) sti_tn = 0.1; raw_wm *= sti_tn / (sti_tn + ENGRAM_STI_TS); } + /* Additive semantic-relevance term (2026-07-24, bl-b2d1c944): + * shift-and-floor at S0 — nomic-embed scores unrelated pairs + * 0.4–0.5, so raw cosine in a weighted sum would be a constant + * bias swamping the decayed base-level signal. Above S0 the term + * ramps 0 → WM_WEIGHT, breaking ties among structurally equivalent + * candidates in favor of nodes that mean what the query means. + * + * MOVED AFTER the STI damper (2026-08-02 self-review). It used to + * be added BEFORE, so the recency multiplier scaled the semantic + * term too: an incumbent re-reached 30s later took t_n/(t_n+120) + * = 0.2×, cutting the cosine term's ceiling from 0.20 to 0.04 — + * below every per-type threshold (0.15–0.40). Meaning-match was + * being punished for having been recently useful. Inhibition-of- + * return should rotate the STRUCTURAL score (what the graph + * dragged in), not the semantic one (what the query actually + * means); relevance to the current query is not stale merely + * because the node was in WM a moment ago. */ + if (cosq && cosq[i] > ENGRAM_EMBED_S0) { + raw_wm += ENGRAM_EMBED_WM_WEIGHT + * (cosq[i] - ENGRAM_EMBED_S0) / (1.0 - ENGRAM_EMBED_S0); + } /* Threshold gate: must exceed per-type threshold to enter working * memory. Type threshold replaces the old flat 0.2 filter. */ if (raw_wm >= type_threshold) { @@ -8077,14 +8131,41 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { if (n->suppression_count > 0) n->suppression_count = 0; } else { /* Node didn't make it through — increment suppression counter. - * After N consecutive suppressions: force breakthrough. */ + * After N consecutive suppressions it MAY force a breakthrough, + * subject to the per-call budget and the negative-count cooldown + * (2026-08-02 — see ENGRAM_BREAKTHROUGH_BUDGET/_COOLDOWN). */ n->suppression_count++; - if (n->suppression_count >= ENGRAM_SUPPRESSION_BREAKTHROUGH) { - wm_weights[i] = ENGRAM_BREAKTHROUGH_WEIGHT; - n->suppression_count = 0; + if (n->suppression_count >= ENGRAM_SUPPRESSION_BREAKTHROUGH + && bt_budget > 0) { + /* Graded breakthrough weight (2026-08-02): previously every + * breakthrough landed on exactly ENGRAM_BREAKTHROUGH_WEIGHT, + * so hundreds tied at 0.10 and the rank-cap tie-break at the + * cutoff degenerated to node-array index order — i.e. whoever + * was inserted earliest won, which is not a cognitive + * criterion. Scale within ±10% by how close the node came to + * its own threshold, so a near-miss outranks a node that was + * nowhere near. Stays strictly below min(type_threshold) + * (0.15) and strictly above ENGRAM_WM_FLOOR (0.05), which is + * the invariant ENGRAM_BREAKTHROUGH_WEIGHT documents. */ + double near = (type_threshold > 0.0) + ? (raw_wm / type_threshold) : 0.0; + if (near < 0.0) near = 0.0; + if (near > 1.0) near = 1.0; + wm_weights[i] = ENGRAM_BREAKTHROUGH_WEIGHT + * (0.9 + 0.2 * near); + /* Negative = cooldown. Must climb back through the cooldown + * before it can breach again. */ + n->suppression_count = -ENGRAM_BREAKTHROUGH_COOLDOWN; + bt_budget--; _eg_act_breakthroughs++; } else { wm_weights[i] = 0.0; + /* Budget-starved or cooling down: do NOT reset the counter — + * let it saturate so the node surfaces on a later call rather + * than restarting its climb from zero. Cap the ceiling so the + * int32 cannot drift unbounded over a long uptime. */ + if (n->suppression_count > ENGRAM_SUPPRESSION_BREAKTHROUGH * 4) + n->suppression_count = ENGRAM_SUPPRESSION_BREAKTHROUGH * 4; } } } @@ -8217,6 +8298,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { if (B < ENGRAM_BLL_TAU) { cn->working_memory_weight = 0.0; cn->wm_anchor = 0.0; /* keep anchor coherent with eviction */ + _eg_act_wm_evicted++; /* was uncounted before 2026-08-02 */ } else { double keep = 1.0 / (1.0 + exp(-(B - ENGRAM_BLL_TAU) / ENGRAM_BLL_S)); @@ -8233,6 +8315,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { if (w < ENGRAM_WM_FLOOR) { cn->working_memory_weight = 0.0; cn->wm_anchor = 0.0; + _eg_act_wm_evicted++; /* was uncounted before 2026-08-02 */ } else { cn->working_memory_weight = w; } @@ -8303,6 +8386,7 @@ el_val_t engram_activate(el_val_t query, el_val_t depth) { } n->working_memory_weight = 0.0; /* evict: over global cap */ n->wm_anchor = 0.0; /* keep anchor coherent */ + _eg_act_wm_evicted++; /* was uncounted before 2026-08-02 */ } } /* If malloc failed, skip — WM over cap this call, no data corruption. */ From afc92f4e33742aa8bc2a55a0f0c7b4659cd886f4 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Mon, 3 Aug 2026 08:38:58 -0500 Subject: [PATCH 10/26] self-review 2026-08-03: add engram_label_df term-specificity measure The soul's curiosity auto-term extractor takes the first word of a top-WM node label. It has no term-quality scoring, so three prior self-reviews each bolted on another hand-curated blocklist (genre words 07-23, quoted titles 07-25, stopwords 07-30). Every one was written reactively, after a flood was already observed. A list can only contain floods that already happened. Two were in flight and unfixed when this review ran: "` inside an attacker-supplied - * attribute value, and every new attack vector requires a code change. - * - * Design: - * - Single-pass byte-level state machine. - * - Tag and attribute names are matched case-insensitively against the - * allowlist. Unknown tags are dropped entirely (the open and close - * markers are stripped; their inner text content survives, escaped). - * - A small set of "dangerous container" tags (script, style, iframe, - * object, embed, form, plus a few rarer ones) drop themselves AND - * their full subtree — text between `` is - * CDATA-like and must not be re-emitted as escaped text either. - * - Comments (), doctype (), CDATA (), - * and processing instructions () are dropped entirely. - * - Text content outside dropped subtrees is HTML-escaped (&, <, >, ", '). - * - Attribute values are unquoted/dequoted, then re-emitted with double - * quotes around the cleanly-escaped value. - * - For `` and any `src` attribute, the URL scheme is validated: - * only http:, https:, mailto:, fragment-only `#anchor`, or relative - * paths are allowed. Anything else (javascript:, data:, vbscript:, - * about:, file:, etc.) drops the attribute. - * - Self-closing void tags (br, hr, img, etc.) emit without a close tag. - * - Malformed input (unclosed tag at EOF, bad attribute syntax) drops - * the pending tag and continues. Pre-encoded entities (<, &, - * etc.) are passed through verbatim — the browser will decode them - * safely on render. - * - * Allowlist format (JSON string): - * {"p":[],"a":["href","title"],"strong":[],...} - * - Key = lowercase tag name. - * - Value = JSON array of allowed attribute names (lowercase). - * - Empty array means tag allowed but no attributes survive. - * - * Output is a freshly-allocated arena-tracked el_val_t string. */ - -/* Internal byte buffer with realloc-doubling. Used during sanitization; - * the final result is copied into an arena-tracked el_strbuf so the caller - * sees standard runtime memory semantics. */ -typedef struct { - char* data; - size_t len; - size_t cap; -} html_buf_t; - -static void html_buf_init(html_buf_t* b) { - b->cap = 256; - b->data = malloc(b->cap); - if (!b->data) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - b->len = 0; -} - -static void html_buf_grow(html_buf_t* b, size_t need) { - if (b->len + need + 1 <= b->cap) return; - size_t nc = b->cap; - while (b->len + need + 1 > nc) nc *= 2; - char* nd = realloc(b->data, nc); - if (!nd) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - b->data = nd; - b->cap = nc; -} - -static void html_buf_putc(html_buf_t* b, char c) { - html_buf_grow(b, 1); - b->data[b->len++] = c; -} - -static void html_buf_puts(html_buf_t* b, const char* s) { - if (!s) return; - size_t n = strlen(s); - html_buf_grow(b, n); - memcpy(b->data + b->len, s, n); - b->len += n; -} - -static void html_buf_free(html_buf_t* b) { - free(b->data); - b->data = NULL; - b->len = b->cap = 0; -} - -/* ASCII tolower, locale-independent. */ -static int html_tolower(int c) { - return (c >= 'A' && c <= 'Z') ? c + 32 : c; -} - -/* Case-insensitive ASCII compare of [a, a+n) against c-string `s`. - * Returns 1 iff lengths match and bytes are equal under tolower. */ -static int html_ieq_n(const char* a, size_t n, const char* s) { - if (!a || !s) return 0; - if (strlen(s) != n) return 0; - for (size_t i = 0; i < n; i++) { - if (html_tolower((unsigned char)a[i]) != html_tolower((unsigned char)s[i])) return 0; - } - return 1; -} - -/* Case-insensitive ASCII compare of two byte slices. */ -static int html_iemem(const char* a, const char* b, size_t n) { - for (size_t i = 0; i < n; i++) { - if (html_tolower((unsigned char)a[i]) != html_tolower((unsigned char)b[i])) return 0; - } - return 1; -} - -/* Walk a JSON allowlist object and find the value (an array) for a given - * tag key, comparing case-insensitively. On hit returns a pointer to the - * opening `[` of the array and writes the byte length of the array span - * (including the brackets) to *out_len. On miss returns NULL. - * - * The parser is intentionally tiny: it does not handle escapes inside - * keys (allowlist authors do not need them), and it relies on balanced - * brackets/quotes within the value array. */ -static const char* html_allowlist_find(const char* allow, const char* tag, - size_t tag_len, size_t* out_len) { - if (!allow) return NULL; - const char* p = allow; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '{') return NULL; - p++; - while (*p) { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p == '}' || *p == 0) return NULL; - if (*p != '"') return NULL; - p++; - const char* k = p; - while (*p && *p != '"') p++; - if (*p != '"') return NULL; - size_t klen = (size_t)(p - k); - p++; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != ':') return NULL; - p++; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') return NULL; - const char* arr_start = p; - int depth = 0; - int in_str = 0; - while (*p) { - char c = *p; - if (in_str) { - if (c == '\\' && p[1]) { p += 2; continue; } - if (c == '"') in_str = 0; - } else { - if (c == '"') in_str = 1; - else if (c == '[') depth++; - else if (c == ']') { depth--; if (depth == 0) { p++; break; } } - } - p++; - } - size_t alen = (size_t)(p - arr_start); - int match = (klen == tag_len) && html_iemem(k, tag, klen); - if (match) { - if (out_len) *out_len = alen; - return arr_start; - } - } - return NULL; -} - -/* Returns 1 iff `attr` (length attr_len) appears as a string element - * in the JSON array slice [arr, arr+arr_len). Comparison is case- - * insensitive. */ -static int html_attr_in_array(const char* arr, size_t arr_len, - const char* attr, size_t attr_len) { - if (!arr || arr_len < 2) return 0; - const char* p = arr + 1; - const char* end = arr + arr_len - 1; - while (p < end) { - while (p < end && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',')) p++; - if (p >= end) return 0; - if (*p != '"') return 0; - p++; - const char* s = p; - while (p < end && *p != '"') { - if (*p == '\\' && p + 1 < end) p++; - p++; - } - if (p >= end) return 0; - size_t slen = (size_t)(p - s); - p++; - if (slen == attr_len && html_iemem(s, attr, slen)) return 1; - } - return 0; -} - -/* Hard-coded set of tags whose content is ALSO dropped (entire subtree). */ -static int html_is_dangerous_container(const char* tag, size_t tag_len) { - static const char* names[] = { - "script", "style", "iframe", "object", "embed", "form", - "noscript", "noembed", "template", "svg", "math", "frame", - "frameset", "applet", "audio", "video", "source", "track", - NULL - }; - for (int i = 0; names[i]; i++) { - if (html_ieq_n(tag, tag_len, names[i])) return 1; - } - return 0; -} - -/* HTML void elements — emit without a close tag. */ -static int html_is_void(const char* tag, size_t tag_len) { - static const char* names[] = { - "area", "base", "br", "col", "embed", "hr", "img", "input", - "link", "meta", "param", "source", "track", "wbr", - NULL - }; - for (int i = 0; names[i]; i++) { - if (html_ieq_n(tag, tag_len, names[i])) return 1; - } - return 0; -} - -/* Append a single byte HTML-escaped into the output buffer. */ -static void html_escape_byte(html_buf_t* out, unsigned char c) { - switch (c) { - case '<': html_buf_puts(out, "<"); break; - case '>': html_buf_puts(out, ">"); break; - case '"': html_buf_puts(out, """); break; - case '\'': html_buf_puts(out, "'"); break; - default: html_buf_putc(out, (char)c); break; - } -} - -/* Validate a URL value against the allowlist of safe schemes for hrefs. - * Returns 1 iff the URL is safe to emit. Acceptable forms: - * - http:// or https:// (case-insensitive) - * - mailto: - * - fragment-only `#anchor` - * - relative path that does not contain a colon before the first - * slash/?/# (so `foo/bar`, `/foo`, `?x=1` are OK; `javascript:x` is - * not — its colon precedes any path/hash/query separator). - * - * URL leading whitespace and embedded ASCII control bytes (TAB, LF, CR) - * are stripped before the scheme test, mirroring how browsers normalise - * URLs (these bytes are otherwise a known XSS bypass: `java\tscript:`). */ -static int html_url_is_safe(const char* url, size_t len) { - if (!url || len == 0) return 1; /* empty href is harmless */ - size_t i = 0; - while (i < len) { - unsigned char c = (unsigned char)url[i]; - if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == 0x0B || c == 0x0C) { - i++; continue; - } - break; - } - if (i >= len) return 1; /* whitespace only */ - if (url[i] == '#') return 1; /* fragment only */ - if (url[i] == '/' || url[i] == '?') return 1; /* relative */ - /* Find the first scheme-terminating character. */ - size_t scheme_end = (size_t)-1; - for (size_t j = i; j < len; j++) { - char c = url[j]; - if (c == ':') { scheme_end = j; break; } - if (c == '/' || c == '?' || c == '#') break; - } - if (scheme_end == (size_t)-1) return 1; /* no colon → relative path */ - /* Lowercase the scheme, stripping embedded control bytes. */ - char scheme[32]; - size_t sl = 0; - for (size_t j = i; j < scheme_end && sl < sizeof(scheme) - 1; j++) { - unsigned char c = (unsigned char)url[j]; - if (c == '\t' || c == '\n' || c == '\r' || c == 0x0B || c == 0x0C) continue; - scheme[sl++] = (char)html_tolower(c); - } - scheme[sl] = '\0'; - if (strcmp(scheme, "http") == 0) return 1; - if (strcmp(scheme, "https") == 0) return 1; - if (strcmp(scheme, "mailto") == 0) return 1; - return 0; -} - -el_val_t el_html_sanitize(el_val_t input_v, el_val_t allowlist_v) { - const char* input = EL_CSTR(input_v); - const char* allow = EL_CSTR(allowlist_v); - if (!input) return el_wrap_str(el_strdup("")); - if (!allow) allow = "{}"; - size_t in_len = strlen(input); - - html_buf_t out; - html_buf_init(&out); - - size_t i = 0; - while (i < in_len) { - unsigned char c = (unsigned char)input[i]; - if (c != '<') { - /* Plain text — escape and emit. We pass `&` through verbatim - * to preserve pre-encoded entities (`<`, `&`, `&#x...;`) - * which the browser will decode safely. */ - if (c == '&') html_buf_putc(&out, '&'); - else html_escape_byte(&out, c); - i++; - continue; - } - /* `<` — try to parse a tag. */ - if (i + 1 >= in_len) { - html_buf_puts(&out, "<"); - i++; - continue; - } - /* Comments, doctype, CDATA, processing instructions — drop entirely. */ - if (input[i + 1] == '!') { - if (i + 3 < in_len && input[i + 2] == '-' && input[i + 3] == '-') { - size_t j = i + 4; - while (j + 2 < in_len && !(input[j] == '-' && input[j + 1] == '-' && input[j + 2] == '>')) j++; - if (j + 2 < in_len) i = j + 3; - else i = in_len; - continue; - } - size_t j = i + 2; - while (j < in_len && input[j] != '>') j++; - i = (j < in_len) ? j + 1 : in_len; - continue; - } - if (input[i + 1] == '?') { - size_t j = i + 2; - while (j < in_len && input[j] != '>') j++; - i = (j < in_len) ? j + 1 : in_len; - continue; - } - int is_close = 0; - size_t name_start = i + 1; - if (input[i + 1] == '/') { - is_close = 1; - name_start = i + 2; - } - if (name_start >= in_len) { - html_buf_puts(&out, "<"); - i++; - continue; - } - unsigned char nc = (unsigned char)input[name_start]; - if (!((nc >= 'a' && nc <= 'z') || (nc >= 'A' && nc <= 'Z'))) { - /* `<` followed by non-letter — emit as escaped text. */ - html_buf_puts(&out, "<"); - i++; - continue; - } - size_t name_end = name_start; - while (name_end < in_len) { - unsigned char x = (unsigned char)input[name_end]; - if ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || - (x >= '0' && x <= '9') || x == '-' || x == '_' || x == ':') { - name_end++; - } else { - break; - } - } - const char* tag = input + name_start; - size_t tag_len = name_end - name_start; - /* Find the `>` that closes this tag, respecting quoted attrs. */ - size_t cur = name_end; - int self_close = 0; - while (cur < in_len) { - unsigned char x = (unsigned char)input[cur]; - if (x == '"' || x == '\'') { - unsigned char q = x; - cur++; - while (cur < in_len && (unsigned char)input[cur] != q) cur++; - if (cur < in_len) cur++; /* skip closing quote */ - continue; - } - if (x == '/' && cur + 1 < in_len && input[cur + 1] == '>') { - self_close = 1; - break; - } - if (x == '>') break; - cur++; - } - if (cur >= in_len) { - /* Malformed: unclosed tag at EOF. Drop the rest of the input. */ - i = in_len; - continue; - } - size_t tag_end = self_close ? cur + 2 : cur + 1; /* one past `>` */ - /* Dangerous container — drop the whole subtree. */ - if (!is_close && html_is_dangerous_container(tag, tag_len)) { - if (self_close || html_is_void(tag, tag_len)) { - i = tag_end; - continue; - } - size_t scan = tag_end; - int found_close = 0; - while (scan < in_len) { - if (input[scan] != '<') { scan++; continue; } - if (scan + 1 < in_len && input[scan + 1] == '/') { - size_t cn_start = scan + 2; - size_t cn_end = cn_start; - while (cn_end < in_len) { - unsigned char x = (unsigned char)input[cn_end]; - if ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || - (x >= '0' && x <= '9') || x == '-' || x == '_' || x == ':') { - cn_end++; - } else break; - } - if (cn_end - cn_start == tag_len && - html_iemem(input + cn_start, tag, tag_len)) { - size_t end_close = cn_end; - while (end_close < in_len && input[end_close] != '>') end_close++; - i = (end_close < in_len) ? end_close + 1 : in_len; - found_close = 1; - break; - } - } - scan++; - } - if (!found_close) { - /* No matching close — drop everything from here on. */ - i = in_len; - } - continue; - } - /* Look up the tag in the allowlist. */ - size_t arr_len = 0; - const char* arr = html_allowlist_find(allow, tag, tag_len, &arr_len); - if (!arr) { - /* Tag not allowed. Drop the open/close marker; inner text is - * processed by the outer loop and re-emitted as escaped text. */ - i = tag_end; - continue; - } - if (is_close) { - if (!html_is_void(tag, tag_len)) { - html_buf_putc(&out, '<'); - html_buf_putc(&out, '/'); - for (size_t k = 0; k < tag_len; k++) { - html_buf_putc(&out, (char)html_tolower((unsigned char)tag[k])); - } - html_buf_putc(&out, '>'); - } - i = tag_end; - continue; - } - /* Allowed open tag. Emit ``. */ - html_buf_putc(&out, '<'); - for (size_t k = 0; k < tag_len; k++) { - html_buf_putc(&out, (char)html_tolower((unsigned char)tag[k])); - } - size_t a = name_end; - while (a < cur) { - unsigned char x = (unsigned char)input[a]; - if (x == ' ' || x == '\t' || x == '\n' || x == '\r' || x == '/') { a++; continue; } - size_t an_start = a; - while (a < cur) { - unsigned char y = (unsigned char)input[a]; - if (y == '=' || y == ' ' || y == '\t' || y == '\n' || y == '\r' || y == '/' || y == '>') break; - a++; - } - size_t an_len = a - an_start; - if (an_len == 0) { a++; continue; } - size_t av_start = 0; - size_t av_len = 0; - int has_value = 0; - size_t b = a; - while (b < cur && (input[b] == ' ' || input[b] == '\t' || input[b] == '\n' || input[b] == '\r')) b++; - if (b < cur && input[b] == '=') { - has_value = 1; - b++; - while (b < cur && (input[b] == ' ' || input[b] == '\t' || input[b] == '\n' || input[b] == '\r')) b++; - if (b < cur && (input[b] == '"' || input[b] == '\'')) { - unsigned char q = (unsigned char)input[b]; - b++; - av_start = b; - while (b < cur && (unsigned char)input[b] != q) b++; - av_len = b - av_start; - if (b < cur) b++; - } else { - av_start = b; - while (b < cur) { - unsigned char y = (unsigned char)input[b]; - if (y == ' ' || y == '\t' || y == '\n' || y == '\r' || y == '>') break; - b++; - } - av_len = b - av_start; - } - a = b; - } - if (!html_attr_in_array(arr, arr_len, input + an_start, an_len)) continue; - int is_href = (an_len == 4 && html_iemem(input + an_start, "href", 4)); - int is_src = (an_len == 3 && html_iemem(input + an_start, "src", 3)); - if ((is_href || is_src) && has_value) { - if (!html_url_is_safe(input + av_start, av_len)) continue; - } - html_buf_putc(&out, ' '); - for (size_t k = 0; k < an_len; k++) { - html_buf_putc(&out, (char)html_tolower((unsigned char)input[an_start + k])); - } - if (has_value) { - html_buf_puts(&out, "=\""); - for (size_t k = 0; k < av_len; k++) { - unsigned char y = (unsigned char)input[av_start + k]; - /* Re-escape so the emitted attribute is well-formed - * double-quoted HTML. `&` passes through to preserve - * pre-encoded entities. */ - if (y == '"') html_buf_puts(&out, """); - else if (y == '<') html_buf_puts(&out, "<"); - else if (y == '>') html_buf_puts(&out, ">"); - else html_buf_putc(&out, (char)y); - } - html_buf_putc(&out, '"'); - } - } - html_buf_putc(&out, '>'); - i = tag_end; - } - /* Copy into arena-tracked buffer so the standard runtime memory model - * applies to the returned string. */ - char* result = el_strbuf(out.len); - memcpy(result, out.data, out.len); - result[out.len] = '\0'; - html_buf_free(&out); - return el_wrap_str(result); -} - -/* ── JSON ────────────────────────────────────────────────────────────────── */ - -/* True iff the segment is non-empty and every byte is an ASCII digit. We treat - * such segments as numeric array indices when walking a dot-path; mixed names - * like "0a" remain object-key lookups, so a key named "0" still wins over an - * index when the surrounding container is an object. */ -static int json_path_seg_is_index(const char* seg, size_t n) { - if (n == 0) return 0; - for (size_t i = 0; i < n; i++) { - if (seg[i] < '0' || seg[i] > '9') return 0; - } - return 1; -} - -/* Skip JSON whitespace. */ -static const char* json_skip_ws(const char* p) { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - return p; -} - -/* Descend one segment into the JSON cursor `p`. - * - If `p` points at an array `[...]` and the segment is all digits, - * advance to that element (zero-based). - * - Otherwise treat the segment as an object key and use json_find_key - * scoped to a one-level slice of the current container. - * Returns NULL if the descent fails (segment not found, container mismatch). - * - * `seg` is a pointer into the original path string and `seg_len` is its - * byte length — this avoids an extra alloc per segment. */ -static const char* json_path_descend(const char* p, const char* seg, size_t seg_len) { - if (!p || !seg) return NULL; - p = json_skip_ws(p); - if (*p == '[' && json_path_seg_is_index(seg, seg_len)) { - long idx = 0; - for (size_t i = 0; i < seg_len; i++) idx = idx * 10 + (seg[i] - '0'); - p++; /* step past '[' */ - p = json_skip_ws(p); - long cur = 0; - while (*p && *p != ']') { - if (cur == idx) return p; - const char* end = json_skip_value(p); - if (!end || end == p) return NULL; - p = json_skip_ws(end); - if (*p == ',') { p++; p = json_skip_ws(p); cur++; continue; } - /* No comma after this element — only acceptable at the closing ']', - * which means we ran out of elements. */ - break; - } - return NULL; - } - /* Object lookup. json_find_key walks at depth 1 of whatever container it - * receives, so we slice from `p` onwards. Caller already positioned us at - * the opening '{' (or at whitespace before it). */ - if (*p != '{') return NULL; - /* Build a NUL-terminated copy of the key segment for the lookup. We only - * pay this cost when the segment isn't a numeric index. */ - char stack_key[256]; - char* k = stack_key; - if (seg_len + 1 > sizeof(stack_key)) { - k = malloc(seg_len + 1); - if (!k) return NULL; - } - memcpy(k, seg, seg_len); - k[seg_len] = '\0'; - const char* found = json_find_key(p, k); - if (k != stack_key) free(k); - return found; -} - -/* Read the JSON value at `p` into a freshly-allocated, arena-owned el_val_t. - * - String -> unescaped, wrapped el_val_t string - * - Anything else -> raw JSON slice as a string (matches the historical - * json_get behaviour: numbers/bools/null come back stringified). */ -static el_val_t json_read_value(const char* p) { - p = json_skip_ws(p); - if (*p == '"') { - p++; - size_t cap = strlen(p) + 1; - char* out = el_strbuf(cap); - char* w = out; - while (*p && *p != '"') { - if (*p == '\\' && *(p+1)) { - p++; - switch (*p) { - case '"': *w++ = '"'; break; - case '\\': *w++ = '\\'; break; - case '/': *w++ = '/'; break; - case 'n': *w++ = '\n'; break; - case 'r': *w++ = '\r'; break; - case 't': *w++ = '\t'; break; - default: *w++ = *p; break; - } - } else { - *w++ = *p; - } - p++; - } - *w = '\0'; - return el_wrap_str(out); - } - /* Object/array/number/bool/null — return the raw slice up to the value's - * end. json_skip_value tracks brace/bracket/string state so nested objects - * round-trip cleanly. */ - const char* end = json_skip_value(p); - if (!end) end = p; - size_t n = (size_t)(end - p); - /* Strip trailing whitespace from scalar values so callers don't see - * `123 ` when they parsed a pretty-printed number. */ - while (n > 0 && (p[n-1] == ' ' || p[n-1] == '\t' || p[n-1] == '\n' || p[n-1] == '\r')) { - n--; - } - char* out = el_strbuf(n); - memcpy(out, p, n); - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t json_get(el_val_t jsonv, el_val_t keyv) { - const char* json = EL_CSTR(jsonv); - const char* key = EL_CSTR(keyv); - if (!json || !key) return el_wrap_str(el_strdup("")); - - /* Fast path: key contains no '.' — keep the historical single-segment - * substring search so existing callers retain their O(strlen) cost - * profile. The dot-path walker is only paid for when needed. */ - if (!strchr(key, '.')) { - size_t klen = strlen(key); - char stack_pat[512]; - char* pattern; - if (klen + 5 <= sizeof(stack_pat)) { - pattern = stack_pat; - } else { - pattern = malloc(klen + 5); - if (!pattern) return el_wrap_str(el_strdup("")); - } - snprintf(pattern, klen + 5, "\"%s\":", key); - const char* p = strstr(json, pattern); - if (pattern != stack_pat) free(pattern); - if (!p) return el_wrap_str(el_strdup("")); - p += strlen(key) + 3; /* skip "key": */ - return json_read_value(p); - } - - /* Dot-path traversal. Walk segments left to right; at each step, descend - * into the current container by either array index (all-digit segment on - * an array cursor) or object key. */ - const char* cursor = json_skip_ws(json); - const char* seg_start = key; - const char* k = key; - while (1) { - if (*k == '.' || *k == '\0') { - size_t seg_len = (size_t)(k - seg_start); - cursor = json_path_descend(cursor, seg_start, seg_len); - if (!cursor) return el_wrap_str(el_strdup("")); - if (*k == '\0') break; - k++; - seg_start = k; - continue; - } - k++; - } - return json_read_value(cursor); -} - -/* ── Float bit-cast helpers ──────────────────────────────────────────────── */ -/* `el_to_float` and `el_from_float` are exposed in el_runtime.h as static - * inlines so generated programs (which #include the header) can call them - * for Float literals. No definitions are needed here. */ - -/* ── JSON parser (recursive descent) ─────────────────────────────────────── */ -/* - * Parsed JSON representation: - * - object -> ElMap (keys & values are el_val_t) - * - array -> ElList - * - string -> EL_STR-wrapped char* (allocated) - * - number -> int (el_val_t) if integer, otherwise el_from_float(double) - * - true -> 1 - * - false -> 0 - * - null -> EL_NULL (0) - * - * Note: there is no runtime type tag — parsed numbers cannot be - * distinguished from booleans by the runtime alone. The codegen tracks - * types separately. This matches the rest of el_val_t's type-erased model. - */ - -/* JsonParser struct is forward-declared near the HTTP/Engram section. */ - -static void jp_skip_ws(JsonParser* jp) { - while (jp->p < jp->end) { - char c = *jp->p; - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') jp->p++; - else break; - } -} - -static el_val_t jp_parse_value(JsonParser* jp); - -/* Parse a JSON string literal (the opening " has NOT yet been consumed). */ -static char* jp_parse_string_raw(JsonParser* jp) { - if (jp->p >= jp->end || *jp->p != '"') { jp->err = 1; return el_strdup(""); } - jp->p++; - size_t cap = 32, len = 0; - char* out = malloc(cap); - if (!out) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - while (jp->p < jp->end && *jp->p != '"') { - char c = *jp->p++; - if (c == '\\' && jp->p < jp->end) { - char esc = *jp->p++; - switch (esc) { - case '"': c = '"'; break; - case '\\': c = '\\'; break; - case '/': c = '/'; break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'u': { - /* Decode \uXXXX (with surrogate pairs) to UTF-8. - * Ported from lang/releases/v1.0.0-20260501 (2026-08-08 - * self-review). This copy carried the identical defect: - * the escape was skipped and a literal '?' emitted, which - * silently destroyed every non-ASCII character in any JSON - * string entering the runtime. Two copies of one parser - * bug is exactly how this class of fault survives, so the - * fix lands in both. See the release copy for the full - * measurement and rationale. */ - unsigned cp = 0; - int ok = 1; - for (int i = 0; i < 4; i++) { - if (jp->p >= jp->end) { ok = 0; break; } - char h = *jp->p++; - unsigned d; - if (h >= '0' && h <= '9') d = (unsigned)(h - '0'); - else if (h >= 'a' && h <= 'f') d = (unsigned)(h - 'a' + 10); - else if (h >= 'A' && h <= 'F') d = (unsigned)(h - 'A' + 10); - else { ok = 0; break; } - cp = (cp << 4) | d; - } - if (!ok) { c = '?'; break; } - if (cp >= 0xD800 && cp <= 0xDBFF && - (size_t)(jp->end - jp->p) >= 6 && - jp->p[0] == '\\' && jp->p[1] == 'u') { - const char* save = jp->p; - unsigned lo = 0; int ok2 = 1; - jp->p += 2; - for (int i = 0; i < 4; i++) { - char h = *jp->p++; - unsigned d; - if (h >= '0' && h <= '9') d = (unsigned)(h - '0'); - else if (h >= 'a' && h <= 'f') d = (unsigned)(h - 'a' + 10); - else if (h >= 'A' && h <= 'F') d = (unsigned)(h - 'A' + 10); - else { ok2 = 0; break; } - lo = (lo << 4) | d; - } - if (ok2 && lo >= 0xDC00 && lo <= 0xDFFF) - cp = 0x10000u + ((cp - 0xD800u) << 10) + (lo - 0xDC00u); - else jp->p = save; - } - if (cp >= 0xD800 && cp <= 0xDFFF) cp = 0xFFFD; - - char ub[4]; int un; - if (cp < 0x80) { - ub[0] = (char)cp; un = 1; - } else if (cp < 0x800) { - ub[0] = (char)(0xC0 | (cp >> 6)); - ub[1] = (char)(0x80 | (cp & 0x3F)); un = 2; - } else if (cp < 0x10000) { - ub[0] = (char)(0xE0 | (cp >> 12)); - ub[1] = (char)(0x80 | ((cp >> 6) & 0x3F)); - ub[2] = (char)(0x80 | (cp & 0x3F)); un = 3; - } else { - ub[0] = (char)(0xF0 | (cp >> 18)); - ub[1] = (char)(0x80 | ((cp >> 12) & 0x3F)); - ub[2] = (char)(0x80 | ((cp >> 6) & 0x3F)); - ub[3] = (char)(0x80 | (cp & 0x3F)); un = 4; - } - while (len + (size_t)un >= cap) { - cap *= 2; - out = realloc(out, cap); - if (!out) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - } - for (int i = 0; i < un; i++) out[len++] = ub[i]; - continue; /* bytes already appended */ - } - default: c = esc; break; - } - } - if (len + 1 >= cap) { - cap *= 2; - out = realloc(out, cap); - if (!out) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - } - out[len++] = c; - } - if (jp->p < jp->end && *jp->p == '"') jp->p++; - else jp->err = 1; - out[len] = '\0'; - return out; -} - -static el_val_t jp_parse_number(JsonParser* jp) { - const char* start = jp->p; - int is_float = 0; - if (jp->p < jp->end && (*jp->p == '-' || *jp->p == '+')) jp->p++; - while (jp->p < jp->end && isdigit((unsigned char)*jp->p)) jp->p++; - if (jp->p < jp->end && *jp->p == '.') { - is_float = 1; jp->p++; - while (jp->p < jp->end && isdigit((unsigned char)*jp->p)) jp->p++; - } - if (jp->p < jp->end && (*jp->p == 'e' || *jp->p == 'E')) { - is_float = 1; jp->p++; - if (jp->p < jp->end && (*jp->p == '+' || *jp->p == '-')) jp->p++; - while (jp->p < jp->end && isdigit((unsigned char)*jp->p)) jp->p++; - } - size_t n = (size_t)(jp->p - start); - char buf[64]; - if (n >= sizeof(buf)) n = sizeof(buf) - 1; - memcpy(buf, start, n); - buf[n] = '\0'; - if (is_float) return el_from_float(strtod(buf, NULL)); - return (el_val_t)strtoll(buf, NULL, 10); -} - -static el_val_t jp_parse_array(JsonParser* jp) { - if (jp->p < jp->end && *jp->p == '[') jp->p++; - el_val_t lst = el_list_empty(); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == ']') { jp->p++; return lst; } - while (jp->p < jp->end) { - jp_skip_ws(jp); - el_val_t v = jp_parse_value(jp); - lst = el_list_append(lst, v); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == ',') { jp->p++; continue; } - if (jp->p < jp->end && *jp->p == ']') { jp->p++; break; } - jp->err = 1; - break; - } - return lst; -} - -static el_val_t jp_parse_object(JsonParser* jp) { - if (jp->p < jp->end && *jp->p == '{') jp->p++; - el_val_t m = el_map_new(0); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == '}') { jp->p++; return m; } - while (jp->p < jp->end) { - jp_skip_ws(jp); - char* key = jp_parse_string_raw(jp); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == ':') jp->p++; - else { jp->err = 1; free(key); break; } - jp_skip_ws(jp); - el_val_t v = jp_parse_value(jp); - m = el_map_set(m, EL_STR(key), v); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == ',') { jp->p++; continue; } - if (jp->p < jp->end && *jp->p == '}') { jp->p++; break; } - jp->err = 1; - break; - } - return m; -} - -static el_val_t jp_parse_value(JsonParser* jp) { - jp_skip_ws(jp); - if (jp->p >= jp->end) { jp->err = 1; return EL_NULL; } - char c = *jp->p; - if (c == '"') return el_wrap_str(jp_parse_string_raw(jp)); - if (c == '{') return jp_parse_object(jp); - if (c == '[') return jp_parse_array(jp); - if (c == '-' || isdigit((unsigned char)c)) return jp_parse_number(jp); - if (c == 't' && jp->p + 4 <= jp->end && strncmp(jp->p, "true", 4) == 0) { jp->p += 4; return 1; } - if (c == 'f' && jp->p + 5 <= jp->end && strncmp(jp->p, "false", 5) == 0) { jp->p += 5; return 0; } - if (c == 'n' && jp->p + 4 <= jp->end && strncmp(jp->p, "null", 4) == 0) { jp->p += 4; return EL_NULL; } - jp->err = 1; - return EL_NULL; -} - -el_val_t json_parse(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return EL_NULL; - JsonParser jp = { .p = s, .end = s + strlen(s), .err = 0 }; - el_val_t v = jp_parse_value(&jp); - if (jp.err) return EL_NULL; - return v; -} - -/* ── JSON stringify ──────────────────────────────────────────────────────── */ -/* - * Stringify policy: el_val_t is type-erased, so we cannot perfectly - * round-trip arbitrary values. We use these heuristics: - * - If value is an ElList pointer (in the heap range), serialize as array. - * - If value is an ElMap pointer, serialize as object. - * - If value looks like a printable string pointer, serialize as string. - * - Otherwise serialize as integer. - * This is best-effort. Programs that need exact control should build the - * string directly. A pointer test is the cheapest way to disambiguate - * from small integers without a separate type tag. - */ - -/* JsonBuf struct is forward-declared near the HTTP section so HTTP helpers - * can use it. Its definition appears there. */ - -static void jb_init(JsonBuf* b) { - b->cap = 64; b->len = 0; - b->buf = malloc(b->cap); - if (!b->buf) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - b->buf[0] = '\0'; -} - -static void jb_reserve(JsonBuf* b, size_t add) { - if (b->len + add + 1 > b->cap) { - while (b->len + add + 1 > b->cap) b->cap *= 2; - b->buf = realloc(b->buf, b->cap); - if (!b->buf) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - } -} - -static void jb_putc(JsonBuf* b, char c) { - jb_reserve(b, 1); - b->buf[b->len++] = c; - b->buf[b->len] = '\0'; -} - -static void jb_puts(JsonBuf* b, const char* s) { - size_t n = strlen(s); - jb_reserve(b, n); - memcpy(b->buf + b->len, s, n); - b->len += n; - b->buf[b->len] = '\0'; -} - -/* jb_finish — call exactly once, at the point a JsonBuf's buffer is handed - * off as an el_val_t return value (via el_wrap_str). JsonBuf allocates through - * raw malloc/realloc (jb_init/jb_reserve), NOT el_strdup/el_strbuf, so unlike - * those helpers it was never registered with the per-request arena — every - * JsonBuf-built JSON string leaked unconditionally, whether or not a request - * arena was active, because nothing ever freed it. el_arena_track() is a - * documented no-op when no arena is active, so this is safe to call from any - * context (HTTP request handler, CLI arena-scope, or no arena at all — the - * last case still leaks, same as before, until the caller's context is itself - * arena-scoped). Do NOT call this on a JsonBuf whose ->buf is consumed by - * another builder (jb_puts(&other, x.buf)) and freed manually — only on the - * one actually returned via el_wrap_str. */ -static char* jb_finish(JsonBuf* b) { - el_arena_track(b->buf); - return b->buf; -} - -static void jb_emit_escaped(JsonBuf* b, const char* s) { - jb_putc(b, '"'); - const unsigned char* p = (const unsigned char*)s; - while (*p) { - unsigned char c = *p; - switch (c) { - case '"': jb_puts(b, "\\\""); p++; break; - case '\\': jb_puts(b, "\\\\"); p++; break; - case '\b': jb_puts(b, "\\b"); p++; break; - case '\f': jb_puts(b, "\\f"); p++; break; - case '\n': jb_puts(b, "\\n"); p++; break; - case '\r': jb_puts(b, "\\r"); p++; break; - case '\t': jb_puts(b, "\\t"); p++; break; - default: - if (c < 0x20) { - char tmp[8]; - snprintf(tmp, sizeof(tmp), "\\u%04x", c); - jb_puts(b, tmp); - p++; - } else if (c < 0x80) { - jb_putc(b, (char)c); - p++; - } else { - /* Multi-byte UTF-8: validate sequence, pass through if valid, - * escape as \u00xx if the start byte is invalid/orphaned. */ - int seq_len = 0; - if ((c & 0xE0) == 0xC0) seq_len = 2; - else if ((c & 0xF0) == 0xE0) seq_len = 3; - else if ((c & 0xF8) == 0xF0) seq_len = 4; - if (seq_len >= 2) { - int valid = 1; - for (int i = 1; i < seq_len; i++) { - if ((p[i] & 0xC0) != 0x80) { valid = 0; break; } - } - if (valid) { - for (int i = 0; i < seq_len; i++) jb_putc(b, (char)p[i]); - p += seq_len; - break; - } - } - /* Invalid start byte or truncated sequence — escape it */ - char tmp[8]; - snprintf(tmp, sizeof(tmp), "\\u%04x", c); - jb_puts(b, tmp); - p++; - } - break; - } - } - jb_putc(b, '"'); -} - -/* Heuristic: is this el_val_t likely a pointer to an ElList? - * We can't fully verify, but pointers are large addresses, integers small. - * Treat values whose magnitude exceeds 2^32 as potential pointers and - * sniff by reading the header conservatively. - * - * Simpler heuristic: if the value reads as a printable string, treat as - * string; otherwise as integer. Lists/Maps are encoded as struct pointers, - * which have leading binary bytes — so they won't look like strings. */ - -static int looks_like_string(el_val_t v) { - if (v == 0) return 0; - /* Treat plausible heap addresses as candidates. - * Threshold: 4 GiB (0x100000000). On 64-bit systems heap addresses from - * malloc/mmap start well above 4 GiB (ASLR pushes them to ~0x7f...). - * El integer values (counters, unix timestamps up to ~2106) all fit below - * 0x100000000 (4294967296). The old threshold of 1,000,000 caused unix - * timestamps (~1.7e9) to be misidentified as string pointers — a segfault - * risk in json_stringify and jb_emit_value. */ - uintptr_t p = (uintptr_t)v; - if (p < 0x100000000ULL) return 0; /* integers, timestamps, counters */ - if (p < 0x1000) return 0; - /* Sniff first bytes for printable */ - const unsigned char* s = (const unsigned char*)p; - for (int i = 0; i < 16; i++) { - unsigned char c = s[i]; - if (c == '\0') return 1; /* terminated string (empty string is still a valid string) */ - /* Reject C0 control chars (non-whitespace), allow UTF-8 high bytes. - * 0x09-0x0d = tab/newline/cr/vt/ff (whitespace, OK) - * 0x20-0x7e = printable ASCII (OK) - * 0x7f = DEL (reject) - * 0x80-0xff = UTF-8 continuation/lead bytes (OK for multi-byte chars) */ - if (c < 0x09 || (c > 0x0d && c < 0x20) || c == 0x7f) return 0; - } - return 1; /* 16+ printable bytes — call it a string */ -} - -static void jb_emit_value(JsonBuf* b, el_val_t v); - -static void jb_emit_int(JsonBuf* b, int64_t n) { - char tmp[32]; - snprintf(tmp, sizeof(tmp), "%lld", (long long)n); - jb_puts(b, tmp); -} - -static void jb_emit_value(JsonBuf* b, el_val_t v) { - if (v == EL_NULL) { jb_puts(b, "null"); return; } - if (looks_like_string(v)) { - jb_emit_escaped(b, EL_CSTR(v)); - return; - } - jb_emit_int(b, (int64_t)v); -} - -el_val_t json_stringify(el_val_t v) { - JsonBuf b; jb_init(&b); - jb_emit_value(&b, v); - return el_wrap_str(jb_finish(&b)); -} - -/* ── JSON substring accessors ────────────────────────────────────────────── */ -/* - * These walk the raw JSON string looking for "key": at the top level (depth 1) - * of an object. They handle escaped quotes, nested objects/arrays, and - * whitespace around the colon. - */ - -/* Find "key": at object-depth == 1 inside the JSON object string `s`. - * Returns pointer to the first byte of the value, or NULL. */ -static const char* json_find_key(const char* s, const char* key) { - if (!s || !key) return NULL; - size_t klen = strlen(key); - int depth = 0; - int in_str = 0; - int escape = 0; - const char* p = s; - while (*p) { - char c = *p; - if (in_str) { - if (escape) { escape = 0; } - else if (c == '\\') { escape = 1; } - else if (c == '"') { - /* End of string. If we're at depth 1, check if this was a key. */ - p++; - if (depth == 1) { - /* The string just ended at p-1. Check if it matches key - * and is followed by a colon. We need to backtrack to find - * the start of this string and compare. */ - } - in_str = 0; - continue; - } - p++; - continue; - } - if (c == '"') { - /* Start of a string literal */ - const char* str_start = p + 1; - const char* q = str_start; - int e = 0; - while (*q) { - if (e) { e = 0; q++; continue; } - if (*q == '\\') { e = 1; q++; continue; } - if (*q == '"') break; - q++; - } - size_t slen = (size_t)(q - str_start); - const char* after = (*q == '"') ? q + 1 : q; - /* If at depth 1 and matches key and followed by ':' -> got it */ - if (depth == 1 && slen == klen && strncmp(str_start, key, klen) == 0) { - const char* r = after; - while (*r == ' ' || *r == '\t' || *r == '\n' || *r == '\r') r++; - if (*r == ':') { - r++; - while (*r == ' ' || *r == '\t' || *r == '\n' || *r == '\r') r++; - return r; - } - } - p = after; - continue; - } - if (c == '{' || c == '[') depth++; - else if (c == '}' || c == ']') depth--; - p++; - } - return NULL; -} - -/* Skip a JSON value starting at p; return pointer past the value end. */ -static const char* json_skip_value(const char* p) { - if (!p || !*p) return p; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p == '"') { - p++; - int e = 0; - while (*p) { - if (e) { e = 0; p++; continue; } - if (*p == '\\') { e = 1; p++; continue; } - if (*p == '"') { p++; break; } - p++; - } - return p; - } - if (*p == '{' || *p == '[') { - char open = *p; - char close = (open == '{') ? '}' : ']'; - int depth = 0; - int in_str = 0; - int e = 0; - while (*p) { - char c = *p; - if (in_str) { - if (e) { e = 0; } - else if (c == '\\') { e = 1; } - else if (c == '"') in_str = 0; - p++; - continue; - } - if (c == '"') { in_str = 1; p++; continue; } - if (c == open) depth++; - else if (c == close) { depth--; p++; if (depth == 0) return p; continue; } - p++; - } - return p; - } - /* scalar: number, true/false/null */ - while (*p && *p != ',' && *p != '}' && *p != ']' && - *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') p++; - return p; -} - -el_val_t json_get_string(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - if (!p || *p != '"') return el_wrap_str(el_strdup("")); - p++; - JsonParser jp = { .p = p - 1, .end = json + (json ? strlen(json) : 0), .err = 0 }; - char* parsed = jp_parse_string_raw(&jp); - if (jp.err) { free(parsed); return el_wrap_str(el_strdup("")); } - return el_wrap_str(parsed); -} - -el_val_t json_get_int(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - if (!p) return 0; - if (*p == '"' || *p == '{' || *p == '[') return 0; - return (el_val_t)strtoll(p, NULL, 10); -} - -el_val_t json_get_float(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - if (!p) return 0; - if (*p == '"' || *p == '{' || *p == '[') return 0; - return el_from_float(strtod(p, NULL)); -} - -el_val_t json_get_bool(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - if (!p) return 0; - if (strncmp(p, "true", 4) == 0) return 1; - return 0; -} - -el_val_t json_get_raw(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - /* Clear fs_read binary-length hint — result is a fresh null-terminated - * string, not the raw file bytes, so Content-Length must use strlen. */ - _tl_fs_read_len = 0; - if (!p) return el_wrap_str(el_strdup("")); - const char* end = json_skip_value(p); - size_t n = (size_t)(end - p); - char* out = el_strbuf(n); - memcpy(out, p, n); - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t json_set(el_val_t json_str, el_val_t key, el_val_t value) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - /* raw_val is the JSON value as-is (already encoded by the caller). - * If it looks like a plain (non-JSON) string, wrap it as a JSON string. - * Convention: callers pass pre-encoded values like "\"bob\"" for strings, - * "42" for numbers, "true"/"false" for booleans. */ - const char* raw_val = EL_CSTR(value); - if (!k) k = ""; - if (!raw_val) raw_val = "null"; - if (!json || !*json) { - /* Build a fresh object */ - JsonBuf b; jb_init(&b); - jb_putc(&b, '{'); - jb_emit_escaped(&b, k); - jb_putc(&b, ':'); - jb_puts(&b, raw_val); - jb_putc(&b, '}'); - return el_wrap_str(jb_finish(&b)); - } - const char* existing = json_find_key(json, k); - JsonBuf b; jb_init(&b); - if (existing) { - const char* end = json_skip_value(existing); - /* Copy [json .. existing) */ - size_t prefix = (size_t)(existing - json); - jb_reserve(&b, prefix); - memcpy(b.buf + b.len, json, prefix); - b.len += prefix; - b.buf[b.len] = '\0'; - jb_puts(&b, raw_val); - jb_puts(&b, end); - return el_wrap_str(jb_finish(&b)); - } - /* Insert before closing '}'. Find last '}' */ - size_t jl = strlen(json); - if (jl == 0) { free(b.buf); return el_wrap_str(el_strdup("{}")); } - /* Find last '}' from the end */ - ssize_t close_idx = -1; - for (ssize_t i = (ssize_t)jl - 1; i >= 0; i--) { - if (json[i] == '}') { close_idx = i; break; } - } - if (close_idx < 0) { - free(b.buf); - return el_wrap_str(el_strdup(json)); - } - /* Determine if object is empty: scan between last '{' and '}' for non-ws */ - int empty = 1; - for (ssize_t i = close_idx - 1; i >= 0; i--) { - char c = json[i]; - if (c == '{') break; - if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { empty = 0; break; } - } - /* Copy json[0..close_idx) */ - jb_reserve(&b, (size_t)close_idx); - memcpy(b.buf + b.len, json, (size_t)close_idx); - b.len += (size_t)close_idx; - b.buf[b.len] = '\0'; - if (!empty) jb_putc(&b, ','); - jb_emit_escaped(&b, k); - jb_putc(&b, ':'); - jb_puts(&b, raw_val); - /* Append from close_idx onward */ - jb_puts(&b, json + close_idx); - return el_wrap_str(jb_finish(&b)); -} - -el_val_t json_array_len(el_val_t json_str) { - const char* s = EL_CSTR(json_str); - if (!s) return 0; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s != '[') return 0; - s++; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ']') return 0; - int64_t count = 0; - while (*s) { - const char* end = json_skip_value(s); - if (end == s) break; - count++; - s = end; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ',') { s++; continue; } - if (*s == ']' || *s == '\0') break; - } - return (el_val_t)count; -} - -/* json_array_get — return the i-th element of a JSON array as a JSON - * fragment string. Nested objects and arrays are returned verbatim - * (json_skip_value tracks brace/bracket depth so nested structures are - * preserved intact). Out-of-range index → "". */ -el_val_t json_array_get(el_val_t json_str, el_val_t index) { - const char* s = EL_CSTR(json_str); - int64_t idx = (int64_t)index; - if (!s || idx < 0) return el_wrap_str(el_strdup("")); - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s != '[') return el_wrap_str(el_strdup("")); - s++; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ']') return el_wrap_str(el_strdup("")); - int64_t i = 0; - while (*s) { - const char* start = s; - const char* end = json_skip_value(s); - if (end == s) break; - if (i == idx) { - size_t n = (size_t)(end - start); - char* out = el_strbuf(n); - memcpy(out, start, n); - out[n] = '\0'; - return el_wrap_str(out); - } - i++; - s = end; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ',') { s++; while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; continue; } - if (*s == ']' || *s == '\0') break; - } - return el_wrap_str(el_strdup("")); -} - -/* json_array_get_string — same as json_array_get, but assume the element - * is a JSON string and return the unquoted/unescaped value. Non-string - * elements yield "". */ -el_val_t json_array_get_string(el_val_t json_str, el_val_t index) { - el_val_t raw = json_array_get(json_str, index); - const char* s = EL_CSTR(raw); - if (!s || *s != '"') return el_wrap_str(el_strdup("")); - JsonParser jp = { - .p = s, - .end = s + strlen(s), - .err = 0, - }; - char* parsed = jp_parse_string_raw(&jp); - if (jp.err) { - free(parsed); - return el_wrap_str(el_strdup("")); - } - return el_wrap_str(parsed); -} - -/* json_escape_string — escape a string value for embedding in JSON. - * Returns the escaped content WITHOUT surrounding quotes. - * "say \"hello\"" -> "say \\\"hello\\\"" */ -el_val_t json_escape_string(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - size_t n = strlen(s); - /* Worst case: every char needs a 2-char escape. */ - char* out = malloc(n * 2 + 1); - if (!out) return el_wrap_str(el_strdup("")); - size_t j = 0; - for (size_t i = 0; i < n; i++) { - unsigned char c = (unsigned char)s[i]; - if (c == '"') { out[j++] = '\\'; out[j++] = '"'; } - else if (c == '\\') { out[j++] = '\\'; out[j++] = '\\'; } - else if (c == '\n') { out[j++] = '\\'; out[j++] = 'n'; } - else if (c == '\r') { out[j++] = '\\'; out[j++] = 'r'; } - else if (c == '\t') { out[j++] = '\\'; out[j++] = 't'; } - else { out[j++] = (char)c; } - } - out[j] = '\0'; - el_val_t result = el_wrap_str(el_strdup(out)); - free(out); - return result; -} - -/* json_build_object — build a JSON object from a flat key-value list. - * kvs is [key0, val0, key1, val1, ...]. Values are raw JSON (pass - * strings as "\"value\"" or use json_escape_string). */ -el_val_t json_build_object(el_val_t kvs) { - el_val_t list = kvs; - int64_t n = el_list_len(list); - JsonBuf b; jb_init(&b); - jb_putc(&b, '{'); - int first = 1; - for (int64_t i = 0; i + 1 < n; i += 2) { - el_val_t k = el_list_get(list, (el_val_t)i); - el_val_t v = el_list_get(list, (el_val_t)(i + 1)); - const char* ks = EL_CSTR(k); - const char* vs = EL_CSTR(v); - if (!ks || !vs) continue; - if (!first) jb_putc(&b, ','); - first = 0; - jb_putc(&b, '"'); - jb_puts(&b, ks); - jb_puts(&b, "\":\""); - /* escape the value string */ - size_t vn = strlen(vs); - for (size_t j = 0; j < vn; j++) { - unsigned char c = (unsigned char)vs[j]; - if (c == '"') { jb_putc(&b, '\\'); jb_putc(&b, '"'); } - else if (c == '\\') { jb_putc(&b, '\\'); jb_putc(&b, '\\'); } - else if (c == '\n') { jb_putc(&b, '\\'); jb_putc(&b, 'n'); } - else if (c == '\r') { jb_putc(&b, '\\'); jb_putc(&b, 'r'); } - else if (c == '\t') { jb_putc(&b, '\\'); jb_putc(&b, 't'); } - else { jb_putc(&b, (char)c); } - } - jb_putc(&b, '"'); - } - jb_putc(&b, '}'); - return el_wrap_str(jb_finish(&b)); -} - -/* json_build_array — build a JSON array from a list of raw JSON values. - * items is ["\"alpha\"", "\"beta\"", "42", "true", ...]. */ -el_val_t json_build_array(el_val_t items) { - el_val_t list = items; - int64_t n = el_list_len(list); - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - for (int64_t i = 0; i < n; i++) { - el_val_t v = el_list_get(list, (el_val_t)i); - const char* vs = EL_CSTR(v); - if (!vs) continue; - if (i > 0) jb_putc(&b, ','); - jb_puts(&b, vs); - } - jb_putc(&b, ']'); - return el_wrap_str(jb_finish(&b)); -} - -/* ── Time ────────────────────────────────────────────────────────────────── */ - -el_val_t time_now(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - int64_t ms = (int64_t)tv.tv_sec * 1000LL + (int64_t)tv.tv_usec / 1000LL; - return (el_val_t)ms; -} - -el_val_t time_now_utc(void) { - return time_now(); -} - -el_val_t time_format(el_val_t ts, el_val_t fmt) { - int64_t ms = (int64_t)ts; - time_t s = (time_t)(ms / 1000); - int msec = (int)(ms % 1000); - if (msec < 0) { msec += 1000; s -= 1; } - struct tm tm; - gmtime_r(&s, &tm); - const char* fmt_str = EL_CSTR(fmt); - if (!fmt_str || *fmt_str == '\0' || strcmp(fmt_str, "ISO") == 0) { - char buf[64]; - snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, msec); - return el_wrap_str(el_strdup(buf)); - } - char buf[256]; - if (strftime(buf, sizeof(buf), fmt_str, &tm) == 0) buf[0] = '\0'; - return el_wrap_str(el_strdup(buf)); -} - -el_val_t time_to_parts(el_val_t ts) { - int64_t ms = (int64_t)ts; - time_t s = (time_t)(ms / 1000); - int msec = (int)(ms % 1000); - if (msec < 0) { msec += 1000; s -= 1; } - struct tm tm; - gmtime_r(&s, &tm); - /* Return a JSON string so callers can use json_get to extract fields. */ - char buf[256]; - snprintf(buf, sizeof(buf), - "{\"year\":%d,\"month\":%d,\"day\":%d,\"hour\":%d,\"minute\":%d,\"second\":%d,\"ms\":%d}", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, msec); - return el_wrap_str(el_strdup(buf)); -} - -el_val_t time_from_parts(el_val_t secs, el_val_t ns, el_val_t tz) { - (void)tz; - int64_t s = (int64_t)secs; - int64_t n = (int64_t)ns; - int64_t ms = s * 1000LL + n / 1000000LL; - return (el_val_t)ms; -} - -el_val_t time_add(el_val_t ts, el_val_t n, el_val_t unit) { - const char* u = EL_CSTR(unit); - int64_t cur = (int64_t)ts; - int64_t d = (int64_t)n; - int64_t add_ms = d; - if (u) { - if (strcmp(u, "ms") == 0) add_ms = d; - else if (strcmp(u, "sec") == 0) add_ms = d * 1000LL; - else if (strcmp(u, "min") == 0) add_ms = d * 60000LL; - else if (strcmp(u, "hour") == 0) add_ms = d * 3600000LL; - else if (strcmp(u, "day") == 0) add_ms = d * 86400000LL; - } - return (el_val_t)(cur + add_ms); -} - -el_val_t time_diff(el_val_t ts1, el_val_t ts2, el_val_t unit) { - int64_t d = (int64_t)ts2 - (int64_t)ts1; - const char* u = EL_CSTR(unit); - if (!u || strcmp(u, "ms") == 0) return (el_val_t)d; - if (strcmp(u, "sec") == 0) return (el_val_t)(d / 1000LL); - if (strcmp(u, "min") == 0) return (el_val_t)(d / 60000LL); - if (strcmp(u, "hour") == 0) return (el_val_t)(d / 3600000LL); - if (strcmp(u, "day") == 0) return (el_val_t)(d / 86400000LL); - return (el_val_t)d; -} - -/* Block the calling thread for `secs` seconds. Negative values are clamped - * to 0. Used by El programs that poll external resources (e.g. RunPod - * /status, Engram readiness probes). */ -el_val_t sleep_secs(el_val_t secs) { - int64_t s = (int64_t)secs; - if (s < 0) s = 0; - struct timespec ts; - ts.tv_sec = (time_t)s; - ts.tv_nsec = 0; - nanosleep(&ts, NULL); - return 0; -} - -el_val_t sleep_ms(el_val_t ms) { - int64_t m = (int64_t)ms; - if (m < 0) m = 0; - struct timespec ts; - ts.tv_sec = (time_t)(m / 1000LL); - ts.tv_nsec = (long)((m % 1000LL) * 1000000LL); - nanosleep(&ts, NULL); - return 0; -} - -/* ── Instant + Duration: first-class temporal types ────────────────────────── - * El's substrate (Neuron) is a temporal cognition system. Memory salience - * decay, the six-tier pacemaker, TTL caches, and supersession are all - * temporal. Treating time as a raw Int (now() returning ms-since-epoch and - * arithmetic done with mixed unit literals) lets bugs through the type - * system: `(now - cached_at) < 60` cannot tell ms from sec, and `sleep(30)` - * is ambiguous. This block introduces two dedicated representations. - * - * Representation: - * Instant — int64 nanoseconds since the Unix epoch - * Duration — int64 nanoseconds (signed; negative durations are legal, - * e.g. when a deadline has passed) - * - * Both share the el_val_t (int64) slot the rest of the runtime uses, so no - * boxing / arena allocation is needed. Type discipline is enforced at the - * codegen layer: `let x: Duration = ...` registers `x` in __duration_names, - * and BinOp dispatches through typed wrappers (el_duration_add, etc.) that - * make intent explicit in the generated C. Mismatched ops (Instant+Instant, - * Duration+Int) are surfaced via #error directives at codegen time so the - * downstream cc step fails with a clear El-source-level message. - * - * Nanosecond precision matches POSIX clock_gettime / nanosleep granularity. - * 2^63 nanos covers ~292 years from epoch — comfortably past 2200, plenty - * for a memory-system runtime that never schedules outside a human lifespan. - */ - -/* now() — current Instant. Wraps clock_gettime(CLOCK_REALTIME) for nanosecond - * precision. Falls back to gettimeofday on systems where clock_gettime is - * unavailable (defensive — every supported platform has it). */ -el_val_t el_now_instant(void) { - struct timespec ts; - if (clock_gettime(CLOCK_REALTIME, &ts) == 0) { - int64_t ns = (int64_t)ts.tv_sec * 1000000000LL + (int64_t)ts.tv_nsec; - return (el_val_t)ns; - } - struct timeval tv; - gettimeofday(&tv, NULL); - int64_t ns = (int64_t)tv.tv_sec * 1000000000LL - + (int64_t)tv.tv_usec * 1000LL; - return (el_val_t)ns; -} - -el_val_t now(void) { - return el_now_instant(); -} - -/* now_ns — return current Unix time as nanoseconds (Int). - * Thin wrapper over el_now_instant for use in test timing. */ -el_val_t now_ns(void) { - return el_now_instant(); -} - -/* unix_seconds(n) — Instant from a Unix-epoch second count. - * unix_millis(n) — Instant from a Unix-epoch millisecond count. */ -el_val_t unix_seconds(el_val_t n) { - int64_t s = (int64_t)n; - return (el_val_t)(s * 1000000000LL); -} - -el_val_t unix_millis(el_val_t n) { - int64_t m = (int64_t)n; - return (el_val_t)(m * 1000000LL); -} - -/* instant_from_iso8601 — parse a strict subset: - * YYYY-MM-DDTHH:MM:SS[.fff]Z - * Returns 0 (the Unix-epoch sentinel) on parse failure. Callers that need to - * distinguish epoch-zero from a parse error should use a wider sentinel - * representation; the current zero-on-failure choice matches existing El - * runtime conventions for parse builtins (str_to_int, parse_int). */ -el_val_t instant_from_iso8601(el_val_t s) { - const char* str = EL_CSTR(s); - if (!str) return (el_val_t)0; - int Y, M, D, h, m, sec, frac = 0; - int n = sscanf(str, "%d-%d-%dT%d:%d:%d.%3d", &Y, &M, &D, &h, &m, &sec, &frac); - if (n < 6) { - n = sscanf(str, "%d-%d-%dT%d:%d:%dZ", &Y, &M, &D, &h, &m, &sec); - if (n < 6) return (el_val_t)0; - } - struct tm tm; - memset(&tm, 0, sizeof(tm)); - tm.tm_year = Y - 1900; - tm.tm_mon = M - 1; - tm.tm_mday = D; - tm.tm_hour = h; - tm.tm_min = m; - tm.tm_sec = sec; - /* timegm — UTC. POSIX-Y but available on macOS and glibc. */ - time_t t = timegm(&tm); - if (t == (time_t)-1) return (el_val_t)0; - int64_t ns = (int64_t)t * 1000000000LL + (int64_t)frac * 1000000LL; - return (el_val_t)ns; -} - -/* Duration constructors. The El-side postfix literals (30.seconds, 1.hour) - * are lowered by the codegen directly into a literal int64 of nanoseconds — - * these constructors are for runtime values where the count is dynamic. */ -el_val_t el_duration_from_nanos(el_val_t ns) { - return (el_val_t)(int64_t)ns; -} - -el_val_t duration_seconds(el_val_t n) { - int64_t s = (int64_t)n; - return (el_val_t)(s * 1000000000LL); -} - -el_val_t duration_millis(el_val_t n) { - int64_t m = (int64_t)n; - return (el_val_t)(m * 1000000LL); -} - -el_val_t duration_nanos(el_val_t n) { - return (el_val_t)(int64_t)n; -} - -/* Arithmetic — typed wrappers. At the C level these are no-op casts, but - * the codegen routes Instant/Duration BinOps through them so the generated - * C says `el_instant_add_dur(start, dur)` rather than `start + dur`. The - * intent is explicit, the operand order is documented, and a future change - * to the underlying representation (saturating arithmetic, overflow guards) - * has a single chokepoint. */ -el_val_t el_instant_add_dur(el_val_t inst, el_val_t dur) { - return (el_val_t)((int64_t)inst + (int64_t)dur); -} - -el_val_t el_instant_sub_dur(el_val_t inst, el_val_t dur) { - return (el_val_t)((int64_t)inst - (int64_t)dur); -} - -el_val_t el_instant_diff(el_val_t a, el_val_t b) { - /* a - b — yields a Duration (negative if b is later than a). */ - return (el_val_t)((int64_t)a - (int64_t)b); -} - -el_val_t el_duration_add(el_val_t a, el_val_t b) { - return (el_val_t)((int64_t)a + (int64_t)b); -} - -el_val_t el_duration_sub(el_val_t a, el_val_t b) { - return (el_val_t)((int64_t)a - (int64_t)b); -} - -el_val_t el_duration_scale(el_val_t dur, el_val_t scalar) { - return (el_val_t)((int64_t)dur * (int64_t)scalar); -} - -el_val_t el_duration_div(el_val_t dur, el_val_t scalar) { - int64_t s = (int64_t)scalar; - if (s == 0) return (el_val_t)0; - return (el_val_t)((int64_t)dur / s); -} - -/* Comparisons. Return 1/0 in el_val_t convention. */ -el_val_t el_instant_lt(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a < (int64_t)b ? 1 : 0); } -el_val_t el_instant_le(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a <= (int64_t)b ? 1 : 0); } -el_val_t el_instant_gt(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a > (int64_t)b ? 1 : 0); } -el_val_t el_instant_ge(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a >= (int64_t)b ? 1 : 0); } -el_val_t el_instant_eq(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a == (int64_t)b ? 1 : 0); } -el_val_t el_instant_ne(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a != (int64_t)b ? 1 : 0); } -el_val_t el_duration_lt(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a < (int64_t)b ? 1 : 0); } -el_val_t el_duration_le(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a <= (int64_t)b ? 1 : 0); } -el_val_t el_duration_gt(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a > (int64_t)b ? 1 : 0); } -el_val_t el_duration_ge(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a >= (int64_t)b ? 1 : 0); } -el_val_t el_duration_eq(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a == (int64_t)b ? 1 : 0); } -el_val_t el_duration_ne(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a != (int64_t)b ? 1 : 0); } - -/* Conversions. */ -el_val_t instant_to_unix_seconds(el_val_t i) { - return (el_val_t)((int64_t)i / 1000000000LL); -} - -el_val_t instant_to_unix_millis(el_val_t i) { - return (el_val_t)((int64_t)i / 1000000LL); -} - -el_val_t instant_to_iso8601(el_val_t i) { - int64_t ns = (int64_t)i; - time_t s = (time_t)(ns / 1000000000LL); - int msec = (int)((ns / 1000000LL) % 1000LL); - if (msec < 0) { msec += 1000; s -= 1; } - struct tm tm; - gmtime_r(&s, &tm); - char buf[64]; - snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, msec); - return el_wrap_str(el_strdup(buf)); -} - -el_val_t duration_to_seconds(el_val_t d) { - return (el_val_t)((int64_t)d / 1000000000LL); -} - -el_val_t duration_to_millis(el_val_t d) { - return (el_val_t)((int64_t)d / 1000000LL); -} - -el_val_t duration_to_nanos(el_val_t d) { - return (el_val_t)(int64_t)d; -} - -/* sleep(Duration) — Phase 1 replacement for ambiguous sleep(Int). The runtime - * still exposes sleep_secs/sleep_ms for legacy call sites; codegen lowers - * sleep(Duration) to el_sleep_duration(d). Negative durations clamp to 0 so a - * stale deadline doesn't block forever. */ -el_val_t el_sleep_duration(el_val_t dur) { - int64_t ns = (int64_t)dur; - if (ns < 0) ns = 0; - struct timespec ts; - ts.tv_sec = (time_t)(ns / 1000000000LL); - ts.tv_nsec = (long)(ns % 1000000000LL); - nanosleep(&ts, NULL); - return (el_val_t)0; -} - -/* unix_timestamp() — back-compat. Existing El callers expect an Int seconds - * value; this stays an Int returner so the type system isn't disturbed for - * legacy code. New code should call now() and convert when needed. */ -el_val_t unix_timestamp(void) { - return instant_to_unix_seconds(el_now_instant()); -} - -/* TTL cache helpers. Backed by the existing process-wide K/V (state_set/get) - * with a sibling __ttl_set_at_ entry recording the Instant of the last - * write. ttl_cache_get returns "" if the entry is missing or stale, so call - * sites can branch on `if v == "" { miss } else { hit }` — the same shape - * existing get-with-default code uses. No more (now - cached_at) < 60. */ -el_val_t ttl_cache_set(el_val_t key, el_val_t value) { - const char* k = EL_CSTR(key); - if (!k) return (el_val_t)0; - /* Store the value at the user's key. */ - state_set(key, value); - /* Stamp set_at — opaque schema, namespaced under __ttl: prefix so user - * keys can't collide with stamps. */ - size_t klen = strlen(k); - char* stamp_key = (char*)malloc(klen + 16); - if (!stamp_key) return (el_val_t)0; - snprintf(stamp_key, klen + 16, "__ttl_at:%s", k); - int64_t now_ns = (int64_t)el_now_instant(); - char buf[32]; - snprintf(buf, sizeof(buf), "%lld", (long long)now_ns); - state_set(EL_STR(stamp_key), EL_STR(buf)); - free(stamp_key); - return (el_val_t)1; -} - -el_val_t ttl_cache_get(el_val_t key, el_val_t max_age) { - const char* k = EL_CSTR(key); - if (!k) return el_wrap_str(el_strdup("")); - /* Look up stamp. */ - size_t klen = strlen(k); - char* stamp_key = (char*)malloc(klen + 16); - if (!stamp_key) return el_wrap_str(el_strdup("")); - snprintf(stamp_key, klen + 16, "__ttl_at:%s", k); - el_val_t stamp = state_get(EL_STR(stamp_key)); - free(stamp_key); - const char* sv = EL_CSTR(stamp); - if (!sv || !*sv) return el_wrap_str(el_strdup("")); - int64_t set_at = (int64_t)atoll(sv); - int64_t now_ns = (int64_t)el_now_instant(); - int64_t age = now_ns - set_at; - int64_t max_ns = (int64_t)max_age; - if (age < 0) return el_wrap_str(el_strdup("")); /* clock skew — treat as miss */ - if (age > max_ns) return el_wrap_str(el_strdup("")); /* expired */ - return state_get(key); -} - -el_val_t ttl_cache_age(el_val_t key) { - const char* k = EL_CSTR(key); - if (!k) return (el_val_t)INT64_MAX; - size_t klen = strlen(k); - char* stamp_key = (char*)malloc(klen + 16); - if (!stamp_key) return (el_val_t)INT64_MAX; - snprintf(stamp_key, klen + 16, "__ttl_at:%s", k); - el_val_t stamp = state_get(EL_STR(stamp_key)); - free(stamp_key); - const char* sv = EL_CSTR(stamp); - if (!sv || !*sv) return (el_val_t)INT64_MAX; - int64_t set_at = (int64_t)atoll(sv); - int64_t now_ns = (int64_t)el_now_instant(); - return (el_val_t)(now_ns - set_at); -} - -/* ── Calendar + CalendarTime + Rhythm + LocalDate/Time/DateTime ────────────── - * Phase 1.5. Calendar is pluggable: EarthCalendar (IANA zones + Gregorian + - * DST), MarsCalendar (sols, MTC), CycleCalendar(period), NoCycleCalendar, - * RelativeCalendar(epoch). Phase 1 zone wrapping folds INTO EarthCalendar; - * UTC and IANA zones are themselves Earth-parochial and cannot live at the - * lowest type layer. - * - * A Rhythm is a small AST that asks the Calendar for cycle phase, weekday, - * etc. Most rhythm logic is calendar-agnostic at runtime: rhythm_cycle_phase - * means "midpoint of cycle" whether the cycle is 24h on Earth or 30h on a - * station or 300y on a long-cycle world. */ - -/* Magic headers — used by the runtime to recognize boxed temporal values - * arriving through el_val_t. Distinct constants so accidental misuse fails - * loudly rather than silently. */ -#define EL_CAL_MAGIC 0xE1CA1EDDU -#define EL_CALTIME_MAGIC 0xE1CA1747U -#define EL_RHYTHM_MAGIC 0xE1287A11U -#define EL_LDATE_MAGIC 0xE1DA7E00U -#define EL_LDT_MAGIC 0xE1DA7E1DU -#define EL_ZONE_MAGIC 0xE12017E0U - -typedef enum { - EL_CALENDAR_EARTH = 1, - EL_CALENDAR_MARS = 2, - EL_CALENDAR_CYCLE = 3, - EL_CALENDAR_NO_CYCLE = 4, - EL_CALENDAR_RELATIVE = 5 -} el_calendar_kind_t; - -typedef struct { - uint32_t magic; - char* id; /* IANA name or "+HH:MM" / "-HH:MM" */ - int fixed; /* 1 for fixed offset, 0 for IANA */ - int64_t offset_ns; /* fixed offset in nanos (only when fixed) */ -} el_zone_t; - -typedef struct { - uint32_t magic; - el_calendar_kind_t kind; - el_zone_t* zone; /* EarthCalendar; MarsCalendar uses MTC */ - int64_t cycle_period_ns;/* CycleCalendar; computed for Earth (86400 s) and Mars (88775.244 s) */ - int64_t epoch_ns; /* RelativeCalendar; Unix-epoch zero otherwise */ -} el_calendar_t; - -typedef struct { - uint32_t magic; - int64_t instant_ns; - el_calendar_t* cal; -} el_caltime_t; - -/* Rhythm AST. */ -typedef enum { - EL_RHYTHM_CYCLE_START = 1, - EL_RHYTHM_CYCLE_PHASE = 2, - EL_RHYTHM_DURATION = 3, - EL_RHYTHM_SESSION_START = 4, - EL_RHYTHM_EVENT = 5, - EL_RHYTHM_AND = 6, - EL_RHYTHM_OR = 7, - EL_RHYTHM_WEEKDAY = 8, - EL_RHYTHM_WEEKLY_AT = 9 -} el_rhythm_kind_t; - -typedef struct el_rhythm_s { - uint32_t magic; - el_rhythm_kind_t kind; - double phase; /* CYCLE_PHASE */ - int64_t period_ns; /* DURATION */ - int weekday; /* 1..7 Mon..Sun */ - int hour; - int minute; - char* event_name; /* EVENT */ - struct el_rhythm_s* a; /* AND/OR */ - struct el_rhythm_s* b; -} el_rhythm_t; - -typedef struct { - uint32_t magic; - int year; - int month; - int day; -} el_localdate_t; - -typedef struct { - uint32_t magic; - el_localdate_t* date; - int64_t time_ns; /* nanos since midnight */ -} el_localdt_t; - -/* Magic-tag check helpers — peek the first 4 bytes of an el_val_t pointer - * and compare against the expected magic. Strings are NUL-terminated and - * never start with our magic byte sequence, so this is safe. */ -static int el_is_magic(el_val_t v, uint32_t want) { - if (v == 0) return 0; - /* Defensive: only follow pointers in plausible address space. - * On 64-bit unix processes pointers are above 0x10000. */ - if ((uint64_t)v < 0x10000ULL) return 0; - uint32_t got = *(volatile uint32_t*)(uintptr_t)v; - return got == want; -} - -/* Sol length on Mars in nanoseconds: 88775.244 seconds. */ -#define EL_MARS_SOL_NS ((int64_t)88775244000000LL) -/* Earth solar day in nanoseconds: 86400 seconds. */ -#define EL_EARTH_DAY_NS ((int64_t)86400000000000LL) - -/* ── Zone construction ────────────────────────────────────────────────────── - * Zones intern by id string so equality comparisons are pointer-compares. */ - -#define EL_ZONE_TABLE_CAP 64 -static el_zone_t* _el_zone_table[EL_ZONE_TABLE_CAP]; -static int _el_zone_count = 0; - -static el_zone_t* _el_zone_intern(const char* id, int fixed, int64_t offset_ns) { - for (int i = 0; i < _el_zone_count; i++) { - el_zone_t* z = _el_zone_table[i]; - if (z->fixed == fixed && z->offset_ns == offset_ns && - strcmp(z->id ? z->id : "", id ? id : "") == 0) { - return z; - } - } - if (_el_zone_count >= EL_ZONE_TABLE_CAP) { - /* Out of slots: build a non-interned zone. Equality will fail across - * such zones but the program still runs. */ - el_zone_t* z = (el_zone_t*)malloc(sizeof(el_zone_t)); - z->magic = EL_ZONE_MAGIC; - z->id = el_strdup_persist(id ? id : ""); - z->fixed = fixed; - z->offset_ns = offset_ns; - return z; - } - el_zone_t* z = (el_zone_t*)malloc(sizeof(el_zone_t)); - z->magic = EL_ZONE_MAGIC; - z->id = el_strdup_persist(id ? id : ""); - z->fixed = fixed; - z->offset_ns = offset_ns; - _el_zone_table[_el_zone_count++] = z; - return z; -} - -el_val_t zone(el_val_t id) { - const char* s = EL_CSTR(id); - if (!s || !*s) return (el_val_t)(uintptr_t)_el_zone_intern("UTC", 0, 0); - /* Fixed-offset shortcut: "+HH:MM" or "-HH:MM". */ - if ((s[0] == '+' || s[0] == '-') && strlen(s) >= 6 && s[3] == ':') { - int sign = (s[0] == '-') ? -1 : 1; - int hh = (s[1] - '0') * 10 + (s[2] - '0'); - int mm = (s[4] - '0') * 10 + (s[5] - '0'); - int64_t off = (int64_t)sign * ((int64_t)hh * 3600LL + (int64_t)mm * 60LL) * 1000000000LL; - return (el_val_t)(uintptr_t)_el_zone_intern(s, 1, off); - } - return (el_val_t)(uintptr_t)_el_zone_intern(s, 0, 0); -} - -el_val_t zone_utc(void) { - return (el_val_t)(uintptr_t)_el_zone_intern("UTC", 1, 0); -} - -el_val_t zone_local(void) { - /* Resolve the local zone via TZ env or system default. tzset() picks - * up TZ if set; otherwise the C library reads /etc/localtime. We store - * the zone id as "LOCAL" so subsequent equality holds; resolution is - * lazy at use time. */ - return (el_val_t)(uintptr_t)_el_zone_intern("LOCAL", 0, 0); -} - -el_val_t zone_offset(el_val_t hours, el_val_t minutes) { - int hh = (int)(int64_t)hours; - int mm = (int)(int64_t)minutes; - int sign = (hh < 0 || mm < 0) ? -1 : 1; - if (hh < 0) hh = -hh; - if (mm < 0) mm = -mm; - int64_t off = (int64_t)sign * ((int64_t)hh * 3600LL + (int64_t)mm * 60LL) * 1000000000LL; - char buf[16]; - snprintf(buf, sizeof(buf), "%c%02d:%02d", sign < 0 ? '-' : '+', hh, mm); - return (el_val_t)(uintptr_t)_el_zone_intern(buf, 1, off); -} - -/* ── Calendar interning ──────────────────────────────────────────────────── */ - -#define EL_CAL_TABLE_CAP 64 -static el_calendar_t* _el_cal_table[EL_CAL_TABLE_CAP]; -static int _el_cal_count = 0; - -static el_calendar_t* _el_cal_intern(el_calendar_kind_t kind, el_zone_t* z, - int64_t period_ns, int64_t epoch_ns) { - for (int i = 0; i < _el_cal_count; i++) { - el_calendar_t* c = _el_cal_table[i]; - if (c->kind == kind && c->zone == z && - c->cycle_period_ns == period_ns && c->epoch_ns == epoch_ns) { - return c; - } - } - el_calendar_t* c = (el_calendar_t*)malloc(sizeof(el_calendar_t)); - c->magic = EL_CAL_MAGIC; - c->kind = kind; - c->zone = z; - c->cycle_period_ns = period_ns; - c->epoch_ns = epoch_ns; - if (_el_cal_count < EL_CAL_TABLE_CAP) _el_cal_table[_el_cal_count++] = c; - return c; -} - -el_val_t earth_calendar(el_val_t z_val) { - el_zone_t* z = NULL; - if (z_val != 0 && el_is_magic(z_val, EL_ZONE_MAGIC)) { - z = (el_zone_t*)(uintptr_t)z_val; - } else { - z = (el_zone_t*)(uintptr_t)zone_local(); - } - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_EARTH, z, EL_EARTH_DAY_NS, 0); -} - -el_val_t earth_calendar_default(void) { - return earth_calendar(zone_local()); -} - -el_val_t mars_calendar(void) { - el_zone_t* z = (el_zone_t*)(uintptr_t)_el_zone_intern("MTC", 1, 0); - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_MARS, z, EL_MARS_SOL_NS, 0); -} - -el_val_t cycle_calendar(el_val_t period_dur) { - int64_t period = (int64_t)period_dur; - if (period <= 0) period = 1; - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_CYCLE, NULL, period, 0); -} - -el_val_t no_cycle_calendar(void) { - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_NO_CYCLE, NULL, 0, 0); -} - -el_val_t relative_calendar(el_val_t epoch_inst) { - int64_t ep = (int64_t)epoch_inst; - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_RELATIVE, NULL, 0, ep); -} - -/* ── CalendarTime ───────────────────────────────────────────────────────── */ - -static el_caltime_t* _el_caltime_alloc(int64_t inst, el_calendar_t* c) { - el_caltime_t* ct = (el_caltime_t*)malloc(sizeof(el_caltime_t)); - ct->magic = EL_CALTIME_MAGIC; - ct->instant_ns = inst; - ct->cal = c; - return ct; -} - -static el_calendar_t* _el_resolve_cal(el_val_t cal_val) { - if (cal_val == 0 || !el_is_magic(cal_val, EL_CAL_MAGIC)) { - return (el_calendar_t*)(uintptr_t)earth_calendar_default(); - } - return (el_calendar_t*)(uintptr_t)cal_val; -} - -el_val_t now_in(el_val_t cal_val) { - el_calendar_t* c = _el_resolve_cal(cal_val); - int64_t ns = (int64_t)el_now_instant(); - return (el_val_t)(uintptr_t)_el_caltime_alloc(ns, c); -} - -el_val_t in_calendar(el_val_t inst, el_val_t cal_val) { - el_calendar_t* c = _el_resolve_cal(cal_val); - return (el_val_t)(uintptr_t)_el_caltime_alloc((int64_t)inst, c); -} - -el_val_t cal_to_instant(el_val_t ct_val) { - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return (el_val_t)0; - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - return (el_val_t)ct->instant_ns; -} - -el_val_t cal_in(el_val_t ct_val, el_val_t cal_val) { - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return (el_val_t)0; - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - el_calendar_t* c = _el_resolve_cal(cal_val); - return (el_val_t)(uintptr_t)_el_caltime_alloc(ct->instant_ns, c); -} - -el_val_t cal_cycle_phase(el_val_t ct_val) { - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return el_from_float(0.0); - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - el_calendar_t* c = ct->cal; - if (c->kind == EL_CALENDAR_NO_CYCLE) { - return el_from_float(0.0/0.0); /* NaN sentinel */ - } - int64_t period = c->cycle_period_ns; - if (period <= 0) return el_from_float(0.0); - int64_t base = ct->instant_ns - c->epoch_ns; - int64_t phase_ns = base % period; - if (phase_ns < 0) phase_ns += period; - double phase = (double)phase_ns / (double)period; - return el_from_float(phase); -} - -/* ── Earth zone resolution: TZ-based offset lookup ────────────────────────── - * For an EarthCalendar(zone), we want to convert an instant_ns into local - * y/m/d/h/m/s, including DST. Approach: setenv("TZ", id), tzset(), use - * localtime_r, then restore. This is not thread-safe by design — El's - * runtime is single-threaded for the request handler path. Cache the - * computed (instant -> tm) to avoid the syscall churn on repeat formats. */ - -static void _el_apply_zone(el_zone_t* z) { - if (!z) { unsetenv("TZ"); tzset(); return; } - if (z->fixed && strcmp(z->id, "UTC") == 0) { - setenv("TZ", "UTC0", 1); - tzset(); - return; - } - if (z->fixed) { - /* Fixed offset: POSIX TZ uses inverted sign (sign convention of - * "hours WEST of UTC" rather than east). Build the spec accordingly. */ - char buf[32]; - int neg_secs = (int)(-z->offset_ns / 1000000000LL); - int sign = neg_secs < 0 ? -1 : 1; - int abs_secs = neg_secs < 0 ? -neg_secs : neg_secs; - int hh = abs_secs / 3600; - int mm = (abs_secs % 3600) / 60; - snprintf(buf, sizeof(buf), "FIX%c%d:%02d", sign < 0 ? '-' : '+', hh, mm); - setenv("TZ", buf, 1); - tzset(); - return; - } - if (strcmp(z->id, "LOCAL") == 0) { - unsetenv("TZ"); - tzset(); - return; - } - setenv("TZ", z->id, 1); - tzset(); -} - -static int _el_decompose_earth(el_caltime_t* ct, struct tm* tm_out, int* abbr_len, char* abbr_buf, size_t abbr_cap) { - el_calendar_t* c = ct->cal; - el_zone_t* z = c->zone; - _el_apply_zone(z); - time_t s = (time_t)(ct->instant_ns / 1000000000LL); - struct tm tm; - localtime_r(&s, &tm); - *tm_out = tm; - if (abbr_buf && abbr_cap > 0) { - /* mingw's struct tm has no tm_zone (BSD/glibc extension); no abbrev available there. */ -#ifdef _WIN32 - const char* z_str = ""; -#else - const char* z_str = tm.tm_zone ? tm.tm_zone : ""; -#endif - size_t n = strlen(z_str); - if (n >= abbr_cap) n = abbr_cap - 1; - memcpy(abbr_buf, z_str, n); - abbr_buf[n] = '\0'; - if (abbr_len) *abbr_len = (int)n; - } - return 0; -} - -/* Format an Earth CalendarTime under a Java-DateTimeFormatter-ish pattern. - * We support a useful core: yyyy MM dd HH mm ss z EEE MMM d h a — enough for - * the acceptance tests. Single quotes denote literal text. */ -static const char* _el_weekday_short[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; -static const char* _el_month_short[] = {"Jan","Feb","Mar","Apr","May","Jun", - "Jul","Aug","Sep","Oct","Nov","Dec"}; - -static char* _el_format_earth(el_caltime_t* ct, const char* pattern) { - struct tm tm; - char abbr[16] = {0}; - int abbr_len = 0; - _el_decompose_earth(ct, &tm, &abbr_len, abbr, sizeof(abbr)); - size_t cap = strlen(pattern) * 4 + 64; - char* out = (char*)malloc(cap); - size_t pos = 0; - size_t i = 0; - size_t plen = strlen(pattern); - while (i < plen) { - char ch = pattern[i]; - /* Quoted literal */ - if (ch == '\'') { - i++; - while (i < plen && pattern[i] != '\'') { - if (pos + 1 >= cap) { cap *= 2; out = realloc(out, cap); } - out[pos++] = pattern[i++]; - } - if (i < plen) i++; - continue; - } - /* Count run of same letter */ - size_t run = 1; - while (i + run < plen && pattern[i + run] == ch) run++; - char tmp[64]; - tmp[0] = '\0'; - if (ch == 'y') { - if (run >= 4) snprintf(tmp, sizeof(tmp), "%04d", tm.tm_year + 1900); - else snprintf(tmp, sizeof(tmp), "%02d", (tm.tm_year + 1900) % 100); - } else if (ch == 'M') { - if (run >= 3) snprintf(tmp, sizeof(tmp), "%s", _el_month_short[tm.tm_mon]); - else if (run == 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_mon + 1); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_mon + 1); - } else if (ch == 'd') { - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_mday); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_mday); - } else if (ch == 'H') { - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_hour); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_hour); - } else if (ch == 'h') { - int h12 = tm.tm_hour % 12; if (h12 == 0) h12 = 12; - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", h12); - else snprintf(tmp, sizeof(tmp), "%d", h12); - } else if (ch == 'm') { - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_min); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_min); - } else if (ch == 's') { - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_sec); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_sec); - } else if (ch == 'a') { - snprintf(tmp, sizeof(tmp), "%s", tm.tm_hour < 12 ? "AM" : "PM"); - } else if (ch == 'E') { - snprintf(tmp, sizeof(tmp), "%s", _el_weekday_short[tm.tm_wday]); - } else if (ch == 'z') { - snprintf(tmp, sizeof(tmp), "%s", abbr); - } else { - for (size_t k = 0; k < run; k++) { - if (pos + 1 >= cap) { cap *= 2; out = realloc(out, cap); } - out[pos++] = ch; - } - i += run; - continue; - } - size_t tl = strlen(tmp); - if (pos + tl + 1 >= cap) { cap = (cap + tl) * 2; out = realloc(out, cap); } - memcpy(out + pos, tmp, tl); - pos += tl; - i += run; - } - out[pos] = '\0'; - char* result = el_strdup(out); - free(out); - return result; -} - -/* Format a Mars CalendarTime: %sol prints the integer sol number since - * mission epoch (Unix epoch fallback), %phase prints cycle_phase as a - * 0..1 decimal. Other %-specifiers fall through. */ -static char* _el_format_mars(el_caltime_t* ct, const char* pattern) { - el_calendar_t* c = ct->cal; - int64_t period = c->cycle_period_ns > 0 ? c->cycle_period_ns : EL_MARS_SOL_NS; - int64_t base = ct->instant_ns - c->epoch_ns; - int64_t sol = base / period; - int64_t phase_ns = base % period; - if (phase_ns < 0) { phase_ns += period; sol -= 1; } - double phase = (double)phase_ns / (double)period; - size_t cap = strlen(pattern) * 4 + 64; - char* out = (char*)malloc(cap); - size_t pos = 0; - for (size_t i = 0; pattern[i]; i++) { - if (pattern[i] == '%' && pattern[i+1]) { - char tmp[64]; - tmp[0] = '\0'; - if (strncmp(pattern + i + 1, "sol", 3) == 0) { - snprintf(tmp, sizeof(tmp), "%lld", (long long)sol); - i += 3; - } else if (strncmp(pattern + i + 1, "phase", 5) == 0) { - snprintf(tmp, sizeof(tmp), "%.4f", phase); - i += 5; - } else if (pattern[i+1] == 'd') { - snprintf(tmp, sizeof(tmp), "%lld", (long long)sol); - i += 1; - } else { - tmp[0] = pattern[i+1]; tmp[1] = '\0'; - i += 1; - } - size_t tl = strlen(tmp); - if (pos + tl + 1 >= cap) { cap = (cap + tl) * 2; out = realloc(out, cap); } - memcpy(out + pos, tmp, tl); - pos += tl; - } else { - if (pos + 1 >= cap) { cap *= 2; out = realloc(out, cap); } - out[pos++] = pattern[i]; - } - } - out[pos] = '\0'; - char* result = el_strdup(out); - free(out); - return result; -} - -/* Format a CycleCalendar CalendarTime: %cycle and %phase. */ -static char* _el_format_cycle(el_caltime_t* ct, const char* pattern) { - el_calendar_t* c = ct->cal; - int64_t period = c->cycle_period_ns > 0 ? c->cycle_period_ns : 1; - int64_t base = ct->instant_ns - c->epoch_ns; - int64_t cycle = base / period; - int64_t phase_ns = base % period; - if (phase_ns < 0) { phase_ns += period; cycle -= 1; } - double phase = (double)phase_ns / (double)period; - size_t cap = strlen(pattern) * 4 + 64; - char* out = (char*)malloc(cap); - size_t pos = 0; - for (size_t i = 0; pattern[i]; i++) { - if (pattern[i] == '%' && pattern[i+1]) { - char tmp[64]; - tmp[0] = '\0'; - if (strncmp(pattern + i + 1, "cycle", 5) == 0) { - snprintf(tmp, sizeof(tmp), "%lld", (long long)cycle); - i += 5; - } else if (strncmp(pattern + i + 1, "phase", 5) == 0) { - snprintf(tmp, sizeof(tmp), "%.4f", phase); - i += 5; - } else if (pattern[i+1] == 'd') { - snprintf(tmp, sizeof(tmp), "%lld", (long long)cycle); - i += 1; - } else if (pattern[i+1] == 'f') { - snprintf(tmp, sizeof(tmp), "%.2f", phase); - i += 1; - } else { - /* Pass through unknown specifier */ - tmp[0] = '%'; tmp[1] = pattern[i+1]; tmp[2] = '\0'; - i += 1; - } - size_t tl = strlen(tmp); - if (pos + tl + 1 >= cap) { cap = (cap + tl) * 2; out = realloc(out, cap); } - memcpy(out + pos, tmp, tl); - pos += tl; - } else { - if (pos + 1 >= cap) { cap *= 2; out = realloc(out, cap); } - out[pos++] = pattern[i]; - } - } - out[pos] = '\0'; - char* result = el_strdup(out); - free(out); - return result; -} - -el_val_t cal_format(el_val_t ct_val, el_val_t pattern_val) { - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return el_wrap_str(el_strdup("")); - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - const char* pat = EL_CSTR(pattern_val); - if (!pat) pat = ""; - char* result = NULL; - switch (ct->cal->kind) { - case EL_CALENDAR_EARTH: result = _el_format_earth(ct, pat); break; - case EL_CALENDAR_MARS: result = _el_format_mars(ct, pat); break; - case EL_CALENDAR_CYCLE: result = _el_format_cycle(ct, pat); break; - case EL_CALENDAR_RELATIVE: result = _el_format_cycle(ct, pat); break; - case EL_CALENDAR_NO_CYCLE: { - char buf[64]; - snprintf(buf, sizeof(buf), "instant:%lld", (long long)ct->instant_ns); - result = el_strdup(buf); - break; - } - default: result = el_strdup(""); - } - return el_wrap_str(result); -} - -/* ── LocalDate / LocalTime / LocalDateTime ──────────────────────────────── */ - -static int _el_days_in_month(int y, int m) { - static const int dim[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; - if (m == 2) { - int leap = ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0); - return 28 + (leap ? 1 : 0); - } - if (m < 1 || m > 12) return 30; - return dim[m - 1]; -} - -el_val_t local_date(el_val_t y, el_val_t m, el_val_t d) { - el_localdate_t* ld = (el_localdate_t*)malloc(sizeof(el_localdate_t)); - ld->magic = EL_LDATE_MAGIC; - ld->year = (int)(int64_t)y; - ld->month = (int)(int64_t)m; - ld->day = (int)(int64_t)d; - return (el_val_t)(uintptr_t)ld; -} - -el_val_t local_time(el_val_t h, el_val_t m, el_val_t s, el_val_t ns) { - int64_t hh = (int64_t)h; - int64_t mm = (int64_t)m; - int64_t ss = (int64_t)s; - int64_t nn = (int64_t)ns; - int64_t total = hh * 3600000000000LL + mm * 60000000000LL + ss * 1000000000LL + nn; - return (el_val_t)total; -} - -el_val_t local_datetime(el_val_t date_val, el_val_t time_val) { - if (!el_is_magic(date_val, EL_LDATE_MAGIC)) return (el_val_t)0; - el_localdt_t* ldt = (el_localdt_t*)malloc(sizeof(el_localdt_t)); - ldt->magic = EL_LDT_MAGIC; - ldt->date = (el_localdate_t*)(uintptr_t)date_val; - ldt->time_ns = (int64_t)time_val; - return (el_val_t)(uintptr_t)ldt; -} - -el_val_t zoned(el_val_t date_val, el_val_t time_val, el_val_t cal_val) { - if (!el_is_magic(date_val, EL_LDATE_MAGIC)) return (el_val_t)0; - el_localdate_t* ld = (el_localdate_t*)(uintptr_t)date_val; - el_calendar_t* c = _el_resolve_cal(cal_val); - int64_t time_ns = (int64_t)time_val; - /* Convert (LocalDate, LocalTime, EarthCalendar) -> Instant. - * For non-Earth calendars we use day-anchored conversion: treat the - * LocalDate's (y,m,d) as a Gregorian projection, convert to seconds via - * mktime under the calendar's zone, then add nanos-since-midnight. */ - if (c->kind == EL_CALENDAR_EARTH) { - _el_apply_zone(c->zone); - struct tm tm; memset(&tm, 0, sizeof(tm)); - tm.tm_year = ld->year - 1900; - tm.tm_mon = ld->month - 1; - tm.tm_mday = ld->day; - tm.tm_hour = (int)(time_ns / 3600000000000LL); - tm.tm_min = (int)((time_ns / 60000000000LL) % 60); - tm.tm_sec = (int)((time_ns / 1000000000LL) % 60); - tm.tm_isdst = -1; - time_t t = mktime(&tm); - if (t == (time_t)-1) return (el_val_t)0; - int64_t ns = (int64_t)t * 1000000000LL + (time_ns % 1000000000LL); - return (el_val_t)(uintptr_t)_el_caltime_alloc(ns, c); - } - /* Non-Earth fallback: project as if Earth UTC then attach calendar. */ - struct tm tm; memset(&tm, 0, sizeof(tm)); - tm.tm_year = ld->year - 1900; - tm.tm_mon = ld->month - 1; - tm.tm_mday = ld->day; - tm.tm_hour = (int)(time_ns / 3600000000000LL); - tm.tm_min = (int)((time_ns / 60000000000LL) % 60); - tm.tm_sec = (int)((time_ns / 1000000000LL) % 60); - time_t t = timegm(&tm); - if (t == (time_t)-1) return (el_val_t)0; - int64_t ns = (int64_t)t * 1000000000LL + (time_ns % 1000000000LL); - return (el_val_t)(uintptr_t)_el_caltime_alloc(ns, c); -} - -el_val_t local_date_year(el_val_t v) { - if (!el_is_magic(v, EL_LDATE_MAGIC)) return (el_val_t)0; - return (el_val_t)((el_localdate_t*)(uintptr_t)v)->year; -} -el_val_t local_date_month(el_val_t v) { - if (!el_is_magic(v, EL_LDATE_MAGIC)) return (el_val_t)0; - return (el_val_t)((el_localdate_t*)(uintptr_t)v)->month; -} -el_val_t local_date_day(el_val_t v) { - if (!el_is_magic(v, EL_LDATE_MAGIC)) return (el_val_t)0; - return (el_val_t)((el_localdate_t*)(uintptr_t)v)->day; -} -el_val_t local_time_hour(el_val_t v) { - int64_t t = (int64_t)v; - return (el_val_t)(t / 3600000000000LL); -} -el_val_t local_time_minute(el_val_t v) { - int64_t t = (int64_t)v; - return (el_val_t)((t / 60000000000LL) % 60); -} -el_val_t local_time_second(el_val_t v) { - int64_t t = (int64_t)v; - return (el_val_t)((t / 1000000000LL) % 60); -} -el_val_t local_time_nanos(el_val_t v) { - int64_t t = (int64_t)v; - return (el_val_t)(t % 1000000000LL); -} - -el_val_t el_local_date_add_dur(el_val_t ld_val, el_val_t dur_val) { - if (!el_is_magic(ld_val, EL_LDATE_MAGIC)) return ld_val; - el_localdate_t* ld = (el_localdate_t*)(uintptr_t)ld_val; - int64_t dur_ns = (int64_t)dur_val; - int64_t days = dur_ns / EL_EARTH_DAY_NS; - int y = ld->year, m = ld->month, d = ld->day; - /* Walk days forward/backward in canonical Gregorian. */ - while (days > 0) { - int dim = _el_days_in_month(y, m); - if (d + days <= dim) { d += (int)days; days = 0; break; } - days -= (dim - d + 1); - d = 1; - m++; - if (m > 12) { m = 1; y++; } - } - while (days < 0) { - if (d + days >= 1) { d += (int)days; days = 0; break; } - days += d; - m--; - if (m < 1) { m = 12; y--; } - d = _el_days_in_month(y, m); - } - return local_date((el_val_t)y, (el_val_t)m, (el_val_t)d); -} - -el_val_t el_local_time_add_dur(el_val_t lt_val, el_val_t dur_val) { - int64_t t = (int64_t)lt_val + (int64_t)dur_val; - /* Wrap mod 24h on Earth-default. CycleCalendar wrapping requires the - * caller to use cal_in / cal_format for the right modulus. */ - int64_t day = EL_EARTH_DAY_NS; - int64_t r = t % day; - if (r < 0) r += day; - return (el_val_t)r; -} - -el_val_t el_local_date_lt(el_val_t a_val, el_val_t b_val) { - if (!el_is_magic(a_val, EL_LDATE_MAGIC) || !el_is_magic(b_val, EL_LDATE_MAGIC)) return (el_val_t)0; - el_localdate_t* a = (el_localdate_t*)(uintptr_t)a_val; - el_localdate_t* b = (el_localdate_t*)(uintptr_t)b_val; - if (a->year != b->year) return (el_val_t)(a->year < b->year ? 1 : 0); - if (a->month != b->month) return (el_val_t)(a->month < b->month ? 1 : 0); - return (el_val_t)(a->day < b->day ? 1 : 0); -} - -el_val_t el_local_date_eq(el_val_t a_val, el_val_t b_val) { - if (!el_is_magic(a_val, EL_LDATE_MAGIC) || !el_is_magic(b_val, EL_LDATE_MAGIC)) return (el_val_t)0; - el_localdate_t* a = (el_localdate_t*)(uintptr_t)a_val; - el_localdate_t* b = (el_localdate_t*)(uintptr_t)b_val; - return (el_val_t)((a->year == b->year && a->month == b->month && a->day == b->day) ? 1 : 0); -} - -/* ── Rhythm ──────────────────────────────────────────────────────────────── */ - -static el_rhythm_t* _el_rhythm_alloc(el_rhythm_kind_t k) { - el_rhythm_t* r = (el_rhythm_t*)calloc(1, sizeof(el_rhythm_t)); - r->magic = EL_RHYTHM_MAGIC; - r->kind = k; - return r; -} - -el_val_t rhythm_cycle_start(void) { - return (el_val_t)(uintptr_t)_el_rhythm_alloc(EL_RHYTHM_CYCLE_START); -} - -el_val_t rhythm_cycle_phase(el_val_t phase_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_CYCLE_PHASE); - r->phase = el_to_float(phase_val); - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_duration(el_val_t d_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_DURATION); - r->period_ns = (int64_t)d_val; - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_session_start(void) { - return (el_val_t)(uintptr_t)_el_rhythm_alloc(EL_RHYTHM_SESSION_START); -} - -el_val_t rhythm_event(el_val_t name_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_EVENT); - const char* n = EL_CSTR(name_val); - r->event_name = el_strdup_persist(n ? n : ""); - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_and(el_val_t a_val, el_val_t b_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_AND); - r->a = el_is_magic(a_val, EL_RHYTHM_MAGIC) ? (el_rhythm_t*)(uintptr_t)a_val : NULL; - r->b = el_is_magic(b_val, EL_RHYTHM_MAGIC) ? (el_rhythm_t*)(uintptr_t)b_val : NULL; - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_or(el_val_t a_val, el_val_t b_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_OR); - r->a = el_is_magic(a_val, EL_RHYTHM_MAGIC) ? (el_rhythm_t*)(uintptr_t)a_val : NULL; - r->b = el_is_magic(b_val, EL_RHYTHM_MAGIC) ? (el_rhythm_t*)(uintptr_t)b_val : NULL; - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_weekday(el_val_t day) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_WEEKDAY); - r->weekday = (int)(int64_t)day; - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_weekly_at(el_val_t day, el_val_t hour, el_val_t minute) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_WEEKLY_AT); - r->weekday = (int)(int64_t)day; - r->hour = (int)(int64_t)hour; - r->minute = (int)(int64_t)minute; - return (el_val_t)(uintptr_t)r; -} - -/* Compute the next instant on or after `after` when rhythm `r` matches, - * under calendar `cal`. */ -static int64_t _el_next_after(el_rhythm_t* r, int64_t after_ns, el_calendar_t* cal) { - if (!r) return after_ns; - int64_t period = cal->cycle_period_ns > 0 ? cal->cycle_period_ns : EL_EARTH_DAY_NS; - switch (r->kind) { - case EL_RHYTHM_CYCLE_START: { - int64_t base = after_ns - cal->epoch_ns; - int64_t cyc = (base / period) + 1; - return cal->epoch_ns + cyc * period; - } - case EL_RHYTHM_CYCLE_PHASE: { - int64_t base = after_ns - cal->epoch_ns; - int64_t cyc_ns = (int64_t)(r->phase * (double)period); - int64_t cur_cyc = base / period; - int64_t candidate = cal->epoch_ns + cur_cyc * period + cyc_ns; - if (candidate <= after_ns) candidate += period; - return candidate; - } - case EL_RHYTHM_DURATION: { - return after_ns + (r->period_ns > 0 ? r->period_ns : 1); - } - case EL_RHYTHM_WEEKDAY: - case EL_RHYTHM_WEEKLY_AT: { - if (cal->kind != EL_CALENDAR_EARTH) { - /* Non-Earth calendars: fall back to cycle math, treating - * weekday as a 7-cycle-per-period proxy. */ - return after_ns + period; - } - _el_apply_zone(cal->zone); - time_t s = (time_t)(after_ns / 1000000000LL); - struct tm tm; - localtime_r(&s, &tm); - /* tm_wday: 0=Sun..6=Sat. We use 1=Mon..7=Sun. */ - int target = r->weekday >= 1 && r->weekday <= 7 ? r->weekday : 1; - int target_wday = target == 7 ? 0 : target; /* 7→Sun=0, 1→Mon=1 */ - int days_ahead = (target_wday - tm.tm_wday + 7) % 7; - int hour = (r->kind == EL_RHYTHM_WEEKLY_AT) ? r->hour : 0; - int minute = (r->kind == EL_RHYTHM_WEEKLY_AT) ? r->minute : 0; - struct tm cand = tm; - cand.tm_mday += days_ahead; - cand.tm_hour = hour; - cand.tm_min = minute; - cand.tm_sec = 0; - cand.tm_isdst = -1; - time_t cand_t = mktime(&cand); - int64_t cand_ns = (int64_t)cand_t * 1000000000LL; - if (cand_ns <= after_ns) { - cand.tm_mday += 7; - cand.tm_isdst = -1; - cand_t = mktime(&cand); - cand_ns = (int64_t)cand_t * 1000000000LL; - } - return cand_ns; - } - case EL_RHYTHM_AND: { - int64_t a = _el_next_after(r->a, after_ns, cal); - int64_t b = _el_next_after(r->b, after_ns, cal); - return a > b ? a : b; - } - case EL_RHYTHM_OR: { - int64_t a = _el_next_after(r->a, after_ns, cal); - int64_t b = _el_next_after(r->b, after_ns, cal); - return a < b ? a : b; - } - case EL_RHYTHM_SESSION_START: - case EL_RHYTHM_EVENT: - default: - return after_ns; - } -} - -el_val_t rhythm_next_after(el_val_t r_val, el_val_t after_val, el_val_t cal_val) { - if (!el_is_magic(r_val, EL_RHYTHM_MAGIC)) return after_val; - el_rhythm_t* r = (el_rhythm_t*)(uintptr_t)r_val; - el_calendar_t* c = _el_resolve_cal(cal_val); - int64_t out = _el_next_after(r, (int64_t)after_val, c); - return (el_val_t)out; -} - -el_val_t rhythm_matches(el_val_t r_val, el_val_t ct_val) { - if (!el_is_magic(r_val, EL_RHYTHM_MAGIC)) return (el_val_t)0; - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return (el_val_t)0; - el_rhythm_t* r = (el_rhythm_t*)(uintptr_t)r_val; - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - int64_t period = ct->cal->cycle_period_ns > 0 ? ct->cal->cycle_period_ns : EL_EARTH_DAY_NS; - int64_t base = ct->instant_ns - ct->cal->epoch_ns; - int64_t phase_ns = base % period; - if (phase_ns < 0) phase_ns += period; - double phase = (double)phase_ns / (double)period; - switch (r->kind) { - case EL_RHYTHM_CYCLE_START: return (el_val_t)(phase_ns == 0 ? 1 : 0); - case EL_RHYTHM_CYCLE_PHASE: { - double diff = phase - r->phase; - if (diff < 0) diff = -diff; - return (el_val_t)(diff < 0.001 ? 1 : 0); - } - default: return (el_val_t)0; - } -} - -/* ── UUID v4 ─────────────────────────────────────────────────────────────── */ - -static int _el_uuid_seeded = 0; - -static void _el_uuid_seed(void) { - if (!_el_uuid_seeded) { - srand((unsigned)time(NULL) ^ (unsigned)(uintptr_t)&_el_uuid_seeded); - _el_uuid_seeded = 1; - } -} - -el_val_t uuid_new(void) { - _el_uuid_seed(); - unsigned char b[16]; - for (int i = 0; i < 16; i++) b[i] = (unsigned char)(rand() & 0xff); - /* Version 4 */ - b[6] = (b[6] & 0x0f) | 0x40; - /* RFC 4122 variant */ - b[8] = (b[8] & 0x3f) | 0x80; - char buf[37]; - snprintf(buf, sizeof(buf), - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - b[0], b[1], b[2], b[3], - b[4], b[5], - b[6], b[7], - b[8], b[9], - b[10], b[11], b[12], b[13], b[14], b[15]); - return el_wrap_str(el_strdup(buf)); -} - -el_val_t uuid_v4(void) { return uuid_new(); } - -/* ── Environment ─────────────────────────────────────────────────────────── */ - -el_val_t env(el_val_t key) { - const char* k = EL_CSTR(key); - if (!k) return el_wrap_str(el_strdup("")); - const char* v = getenv(k); - return el_wrap_str(el_strdup(v ? v : "")); -} - -/* ── In-process state K/V ────────────────────────────────────────────────── */ - -typedef struct { - char* key; - char* value; -} StateEntry; - -static StateEntry* _state_entries = NULL; -static size_t _state_count = 0; -static size_t _state_cap = 0; -/* Mutex protecting all _state_entries access. state_set/state_get are called - * concurrently from 64 HTTP worker threads — without this lock, realloc and - * free race, producing corruption, double-free, and segfaults. */ -static pthread_mutex_t _state_mu = PTHREAD_MUTEX_INITIALIZER; - -static StateEntry* state_find(const char* key) { - for (size_t i = 0; i < _state_count; i++) { - if (strcmp(_state_entries[i].key, key) == 0) return &_state_entries[i]; - } - return NULL; -} - -el_val_t state_set(el_val_t key, el_val_t value) { - const char* k = EL_CSTR(key); - const char* v = EL_CSTR(value); - if (!k) return 0; - if (!v) v = ""; - pthread_mutex_lock(&_state_mu); - StateEntry* e = state_find(k); - if (e) { - free(e->value); - e->value = el_strdup_persist(v); - pthread_mutex_unlock(&_state_mu); - return 1; - } - if (_state_count >= _state_cap) { - size_t nc = _state_cap == 0 ? 16 : _state_cap * 2; - StateEntry* grown = realloc(_state_entries, nc * sizeof(StateEntry)); - if (!grown) { pthread_mutex_unlock(&_state_mu); fputs("el_runtime: out of memory\n", stderr); exit(1); } - _state_entries = grown; - _state_cap = nc; - } - _state_entries[_state_count].key = el_strdup_persist(k); - _state_entries[_state_count].value = el_strdup_persist(v); - _state_count++; - pthread_mutex_unlock(&_state_mu); - return 1; -} - -el_val_t state_get(el_val_t key) { - const char* k = EL_CSTR(key); - if (!k) return el_wrap_str(el_strdup("")); - pthread_mutex_lock(&_state_mu); - StateEntry* e = state_find(k); - char* result = el_strdup_persist(e ? e->value : ""); - pthread_mutex_unlock(&_state_mu); - /* wrap in arena-tracked copy for the caller's request lifetime */ - char* copy = el_strdup(result); - return el_wrap_str(copy); -} - -el_val_t state_del(el_val_t key) { - const char* k = EL_CSTR(key); - if (!k) return 0; - pthread_mutex_lock(&_state_mu); - for (size_t i = 0; i < _state_count; i++) { - if (strcmp(_state_entries[i].key, k) == 0) { - free(_state_entries[i].key); - free(_state_entries[i].value); - for (size_t j = i + 1; j < _state_count; j++) { - _state_entries[j - 1] = _state_entries[j]; - } - _state_count--; - pthread_mutex_unlock(&_state_mu); - return 1; - } - } - pthread_mutex_unlock(&_state_mu); - return 1; -} - -el_val_t state_keys(void) { - pthread_mutex_lock(&_state_mu); - /* Build a JSON array string: ["key1","key2",...] */ - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - for (size_t i = 0; i < _state_count; i++) { - if (i > 0) jb_putc(&b, ','); - jb_putc(&b, '"'); - jb_emit_escaped(&b, _state_entries[i].key); - jb_putc(&b, '"'); - } - jb_putc(&b, ']'); - pthread_mutex_unlock(&_state_mu); - return el_wrap_str(jb_finish(&b)); -} - -/* Returns 1 (true) if the key is present in the state store, else 0 (false). */ -el_val_t state_has(el_val_t key) { - const char* k = EL_CSTR(key); - if (!k) return 0; - pthread_mutex_lock(&_state_mu); - StateEntry* e = state_find(k); - int found = (e != NULL) ? 1 : 0; - pthread_mutex_unlock(&_state_mu); - return (el_val_t)found; -} - -/* Returns the value for key, or default_val if the key is absent. */ -el_val_t state_get_or(el_val_t key, el_val_t default_val) { - const char* k = EL_CSTR(key); - if (!k) return default_val; - pthread_mutex_lock(&_state_mu); - StateEntry* e = state_find(k); - if (e) { - char* copy = el_strdup(e->value); - pthread_mutex_unlock(&_state_mu); - return el_wrap_str(copy); - } - pthread_mutex_unlock(&_state_mu); - return default_val; -} - -/* ── Float formatting ────────────────────────────────────────────────────── */ - -el_val_t float_to_str(el_val_t f) { - char buf[64]; - double v = el_to_float(f); - /* Normalize NaN to "nan" regardless of sign — platform-independent. */ - if (isnan(v)) { - snprintf(buf, sizeof(buf), "nan"); - } else { - snprintf(buf, sizeof(buf), "%g", v); - } - return el_wrap_str(el_strdup(buf)); -} - -el_val_t int_to_float(el_val_t n) { - return el_from_float((double)(int64_t)n); -} - -el_val_t float_to_int(el_val_t f) { - return (el_val_t)(int64_t)el_to_float(f); -} - -el_val_t format_float(el_val_t f, el_val_t decimals) { - int d = (int)(int64_t)decimals; - if (d < 0) d = 0; - if (d > 30) d = 30; - char buf[128]; - snprintf(buf, sizeof(buf), "%.*f", d, el_to_float(f)); - return el_wrap_str(el_strdup(buf)); -} - -el_val_t decimal_round(el_val_t f, el_val_t decimals) { - int d = (int)(int64_t)decimals; - if (d < 0) d = 0; - if (d > 15) d = 15; - double mul = pow(10.0, (double)d); - double v = el_to_float(f); - double r = (v >= 0.0 ? floor(v * mul + 0.5) : -floor(-v * mul + 0.5)) / mul; - return el_from_float(r); -} - -el_val_t str_to_float(el_val_t s) { - const char* str = EL_CSTR(s); - if (!str) return el_from_float(0.0); - return el_from_float(strtod(str, NULL)); -} - -/* ── Math (Float-aware) ──────────────────────────────────────────────────── */ - -el_val_t math_sqrt(el_val_t f) { return el_from_float(sqrt(el_to_float(f))); } -el_val_t math_log(el_val_t f) { return el_from_float(log(el_to_float(f))); } -el_val_t math_ln(el_val_t f) { return el_from_float(log(el_to_float(f))); } -el_val_t math_sin(el_val_t f) { return el_from_float(sin(el_to_float(f))); } -el_val_t math_cos(el_val_t f) { return el_from_float(cos(el_to_float(f))); } -el_val_t math_pi(void) { return el_from_float(3.141592653589793238462643383279502884); } - -/* ── String additions ────────────────────────────────────────────────────── */ - -el_val_t str_index_of(el_val_t s, el_val_t sub) { - const char* str = EL_CSTR(s); - const char* sb = EL_CSTR(sub); - if (!str || !sb) return -1; - const char* hit = strstr(str, sb); - if (!hit) return -1; - return (el_val_t)(int64_t)(hit - str); -} - -el_val_t str_split(el_val_t s, el_val_t sep) { - const char* str = EL_CSTR(s); - const char* sp = EL_CSTR(sep); - el_val_t lst = el_list_empty(); - if (!str) return lst; - if (!sp || !*sp) { - lst = el_list_append(lst, el_wrap_str(el_strdup(str))); - return lst; - } - size_t lp = strlen(sp); - const char* p = str; - const char* hit; - while ((hit = strstr(p, sp)) != NULL) { - size_t n = (size_t)(hit - p); - char* out = el_strbuf(n); - memcpy(out, p, n); - out[n] = '\0'; - lst = el_list_append(lst, el_wrap_str(out)); - p = hit + lp; - } - lst = el_list_append(lst, el_wrap_str(el_strdup(p))); - return lst; -} - -el_val_t str_char_at(el_val_t s, el_val_t i) { - const char* str = EL_CSTR(s); - int64_t idx = (int64_t)i; - if (!str) return el_wrap_str(el_strdup("")); - int64_t n = (int64_t)strlen(str); - if (idx < 0 || idx >= n) return el_wrap_str(el_strdup("")); - char buf[2]; - buf[0] = str[idx]; - buf[1] = '\0'; - return el_wrap_str(el_strdup(buf)); -} - -el_val_t str_char_code(el_val_t s, el_val_t i) { - const char* str = EL_CSTR(s); - int64_t idx = (int64_t)i; - if (!str) return 0; - int64_t n = (int64_t)strlen(str); - if (idx < 0 || idx >= n) return 0; - return (el_val_t)(unsigned char)str[idx]; -} - -static el_val_t str_pad(const char* s, int64_t width, const char* pad, int left) { - if (!s) s = ""; - if (!pad || !*pad) pad = " "; - int64_t lp = (int64_t)strlen(pad); - int64_t ls = (int64_t)strlen(s); - if (ls >= width) return el_wrap_str(el_strdup(s)); - int64_t need = width - ls; - char* out = el_strbuf((size_t)width); - if (left) { - for (int64_t i = 0; i < need; i++) out[i] = pad[i % lp]; - memcpy(out + need, s, (size_t)ls); - } else { - memcpy(out, s, (size_t)ls); - for (int64_t i = 0; i < need; i++) out[ls + i] = pad[i % lp]; - } - out[width] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_pad_left(el_val_t s, el_val_t width, el_val_t pad) { - return str_pad(EL_CSTR(s), (int64_t)width, EL_CSTR(pad), 1); -} - -el_val_t str_pad_right(el_val_t s, el_val_t width, el_val_t pad) { - return str_pad(EL_CSTR(s), (int64_t)width, EL_CSTR(pad), 0); -} - -el_val_t str_format(el_val_t fmt, el_val_t data) { - const char* tpl = EL_CSTR(fmt); - if (!tpl) return el_wrap_str(el_strdup("")); - JsonBuf b; jb_init(&b); - const char* p = tpl; - while (*p) { - if (*p == '{') { - const char* q = p + 1; - while (*q && *q != '}') q++; - if (*q == '}') { - size_t klen = (size_t)(q - p - 1); - char keybuf[256]; - if (klen < sizeof(keybuf)) { - memcpy(keybuf, p + 1, klen); - keybuf[klen] = '\0'; - el_val_t v = el_map_get(data, EL_STR(keybuf)); - if (v != 0 && looks_like_string(v)) { - jb_puts(&b, EL_CSTR(v)); - p = q + 1; - continue; - } else if (v != 0) { - jb_emit_int(&b, (int64_t)v); - p = q + 1; - continue; - } - } - /* Unknown key — leave {key} verbatim */ - jb_reserve(&b, klen + 2); - memcpy(b.buf + b.len, p, klen + 2); - b.len += klen + 2; - b.buf[b.len] = '\0'; - p = q + 1; - continue; - } - } - jb_putc(&b, *p); - p++; - } - return el_wrap_str(jb_finish(&b)); -} - -el_val_t str_lower(el_val_t s) { return str_to_lower(s); } -el_val_t str_upper(el_val_t s) { return str_to_upper(s); } - -/* ── Text-processing primitives (Phase 1: byte/codepoint, ASCII char classes) - * - * Phase 1 covers the operations every text-handling caller used to roll by - * hand on top of str_index_of + str_slice. The character-class predicates - * (is_letter / is_digit / ...) are ASCII only — Unicode-grapheme awareness, - * NFC/NFD normalization, and regex are Phase 2. Single-char input checks the - * first byte; multi-char input requires ALL bytes to match (false otherwise). - * - * Counting: - * str_count non-overlapping occurrences of sub in s - * str_count_chars codepoint count (UTF-8 leading-byte count) - * str_count_bytes explicit byte length (alias of str_len) - * str_count_lines \n-delimited line count (\r\n folded to \n) - * str_count_words whitespace-delimited tokens, non-empty only - * str_count_letters ASCII [A-Za-z] - * str_count_digits ASCII [0-9] - * - * Find / position: - * str_index_of_all all byte offsets of sub, [] if none - * str_last_index_of last byte offset of sub, -1 if not found - * str_find_chars first index of any char in any_of, -1 if none - * - * Transform: - * str_repeat s * n (non-negative) - * str_reverse codepoint-reversed (NOT grapheme-aware) - * str_strip_prefix s without prefix if present, else s - * str_strip_suffix s without suffix if present, else s - * str_strip_chars strip leading+trailing chars matching any in chars - * str_lstrip strip leading whitespace - * str_rstrip strip trailing whitespace - * - * Char classification (Bool): - * is_letter, is_digit, is_alphanumeric, is_whitespace, - * is_punctuation, is_uppercase, is_lowercase - * - * Splitting: - * str_split_lines \n-delimited (\r\n folded). Trailing empty dropped. - * str_split_chars alias of native_string_chars in str_ namespace - * str_split_n split into at most n parts (last part keeps the - * rest verbatim, including any further separators) - * - * Joining: - * str_join [String] -> String, sep between elements - */ - -/* Count non-overlapping occurrences of sub in s. Empty sub returns 0. */ -el_val_t str_count(el_val_t sv, el_val_t subv) { - const char* s = EL_CSTR(sv); - const char* sub = EL_CSTR(subv); - if (!s || !sub || !*sub) return 0; - size_t lp = strlen(sub); - int64_t count = 0; - const char* p = s; - while ((p = strstr(p, sub)) != NULL) { - count++; - p += lp; /* non-overlapping advance */ - } - return (el_val_t)count; -} - -/* Codepoint count: walk bytes, count those NOT matching 10xxxxxx. */ -el_val_t str_count_chars(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - int64_t count = 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if ((*p & 0xC0) != 0x80) count++; - } - return (el_val_t)count; -} - -el_val_t str_count_bytes(el_val_t sv) { - return str_len(sv); -} - -el_val_t str_count_lines(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s || !*s) return 0; - int64_t count = 0; - int has_content = 0; - for (const char* p = s; *p; p++) { - has_content = 1; - if (*p == '\n') { - count++; - has_content = 0; /* the \n closed the line */ - } - } - if (has_content) count++; /* trailing line with no terminator */ - return (el_val_t)count; -} - -el_val_t str_count_words(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - int64_t count = 0; - int in_word = 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if (isspace(*p)) { - in_word = 0; - } else if (!in_word) { - in_word = 1; - count++; - } - } - return (el_val_t)count; -} - -el_val_t str_count_letters(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - int64_t count = 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z')) count++; - } - return (el_val_t)count; -} - -el_val_t str_count_digits(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - int64_t count = 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if (*p >= '0' && *p <= '9') count++; - } - return (el_val_t)count; -} - -el_val_t str_index_of_all(el_val_t sv, el_val_t subv) { - const char* s = EL_CSTR(sv); - const char* sub = EL_CSTR(subv); - el_val_t lst = el_list_empty(); - if (!s || !sub || !*sub) return lst; - size_t lp = strlen(sub); - const char* p = s; - const char* hit; - while ((hit = strstr(p, sub)) != NULL) { - lst = el_list_append(lst, (el_val_t)(int64_t)(hit - s)); - p = hit + lp; - } - return lst; -} - -el_val_t str_last_index_of(el_val_t sv, el_val_t subv) { - const char* s = EL_CSTR(sv); - const char* sub = EL_CSTR(subv); - if (!s || !sub || !*sub) return -1; - size_t lp = strlen(sub); - int64_t last = -1; - const char* p = s; - const char* hit; - while ((hit = strstr(p, sub)) != NULL) { - last = (int64_t)(hit - s); - p = hit + lp; - } - return (el_val_t)last; -} - -el_val_t str_find_chars(el_val_t sv, el_val_t any_of_v) { - const char* s = EL_CSTR(sv); - const char* any = EL_CSTR(any_of_v); - if (!s || !any || !*any) return -1; - for (const char* p = s; *p; p++) { - if (strchr(any, *p)) return (el_val_t)(int64_t)(p - s); - } - return -1; -} - -el_val_t str_repeat(el_val_t sv, el_val_t nv) { - const char* s = EL_CSTR(sv); - int64_t n = (int64_t)nv; - if (!s || n <= 0) return el_wrap_str(el_strdup("")); - size_t ls = strlen(s); - if (ls == 0) return el_wrap_str(el_strdup("")); - size_t total = ls * (size_t)n; - char* out = el_strbuf(total); - for (int64_t i = 0; i < n; i++) { - memcpy(out + i * ls, s, ls); - } - out[total] = '\0'; - return el_wrap_str(out); -} - -/* Reverse by codepoint: walk codepoints, copy each backwards into the output. - * NOT grapheme-aware (Phase 2). Combining marks attached to a base codepoint - * will detach. ASCII strings are byte-reverse equivalent. */ -el_val_t str_reverse(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - size_t n = strlen(s); - char* out = el_strbuf(n); - /* Walk forward, find each codepoint's byte length, then copy from the end. */ - size_t out_pos = n; - const unsigned char* p = (const unsigned char*)s; - while (*p) { - int cp_len; - if ((*p & 0x80) == 0x00) cp_len = 1; - else if ((*p & 0xE0) == 0xC0) cp_len = 2; - else if ((*p & 0xF0) == 0xE0) cp_len = 3; - else if ((*p & 0xF8) == 0xF0) cp_len = 4; - else cp_len = 1; /* invalid byte: passthrough */ - out_pos -= cp_len; - memcpy(out + out_pos, p, cp_len); - p += cp_len; - } - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_strip_prefix(el_val_t sv, el_val_t prefv) { - const char* s = EL_CSTR(sv); - const char* pref = EL_CSTR(prefv); - if (!s) return el_wrap_str(el_strdup("")); - if (!pref || !*pref) return el_wrap_str(el_strdup(s)); - size_t lp = strlen(pref); - size_t ls = strlen(s); - if (lp <= ls && strncmp(s, pref, lp) == 0) { - char* out = el_strbuf(ls - lp); - memcpy(out, s + lp, ls - lp); - out[ls - lp] = '\0'; - return el_wrap_str(out); - } - return el_wrap_str(el_strdup(s)); -} - -el_val_t str_strip_suffix(el_val_t sv, el_val_t sufv) { - const char* s = EL_CSTR(sv); - const char* suf = EL_CSTR(sufv); - if (!s) return el_wrap_str(el_strdup("")); - if (!suf || !*suf) return el_wrap_str(el_strdup(s)); - size_t ls = strlen(s); - size_t lsuf = strlen(suf); - if (lsuf <= ls && strcmp(s + ls - lsuf, suf) == 0) { - char* out = el_strbuf(ls - lsuf); - memcpy(out, s, ls - lsuf); - out[ls - lsuf] = '\0'; - return el_wrap_str(out); - } - return el_wrap_str(el_strdup(s)); -} - -el_val_t str_strip_chars(el_val_t sv, el_val_t charsv) { - const char* s = EL_CSTR(sv); - const char* chars = EL_CSTR(charsv); - if (!s) return el_wrap_str(el_strdup("")); - if (!chars || !*chars) return el_wrap_str(el_strdup(s)); - const char* start = s; - while (*start && strchr(chars, *start)) start++; - size_t n = strlen(start); - while (n > 0 && strchr(chars, start[n - 1])) n--; - char* out = el_strbuf(n); - memcpy(out, start, n); - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_lstrip(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - while (*s && isspace((unsigned char)*s)) s++; - return el_wrap_str(el_strdup(s)); -} - -el_val_t str_rstrip(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - size_t n = strlen(s); - while (n > 0 && isspace((unsigned char)s[n - 1])) n--; - char* out = el_strbuf(n); - memcpy(out, s, n); - out[n] = '\0'; - return el_wrap_str(out); -} - -/* Character classification. - * Empty input returns false. Multi-char input requires ALL bytes to match. - * ASCII range only; Phase 2 will widen to Unicode. */ -static int s_all_match(el_val_t sv, int (*pred)(unsigned char)) { - const char* s = EL_CSTR(sv); - if (!s || !*s) return 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if (!pred(*p)) return 0; - } - return 1; -} - -static int p_letter(unsigned char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } -static int p_digit(unsigned char c) { return c >= '0' && c <= '9'; } -static int p_alnum(unsigned char c) { return p_letter(c) || p_digit(c); } -static int p_white(unsigned char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'; } -static int p_punct(unsigned char c) { return ispunct(c) ? 1 : 0; } -static int p_upper(unsigned char c) { return c >= 'A' && c <= 'Z'; } -static int p_lower(unsigned char c) { return c >= 'a' && c <= 'z'; } - -el_val_t is_letter(el_val_t s) { return (el_val_t)s_all_match(s, p_letter); } -el_val_t is_digit(el_val_t s) { return (el_val_t)s_all_match(s, p_digit); } -el_val_t is_alphanumeric(el_val_t s) { return (el_val_t)s_all_match(s, p_alnum); } -el_val_t is_whitespace(el_val_t s) { return (el_val_t)s_all_match(s, p_white); } -el_val_t is_punctuation(el_val_t s) { return (el_val_t)s_all_match(s, p_punct); } -el_val_t is_uppercase(el_val_t s) { return (el_val_t)s_all_match(s, p_upper); } -el_val_t is_lowercase(el_val_t s) { return (el_val_t)s_all_match(s, p_lower); } - -/* Split on \n. \r\n is folded to \n first. Trailing empty after final \n - * is dropped (so "a\nb\n" -> ["a", "b"], not ["a", "b", ""]). */ -el_val_t str_split_lines(el_val_t sv) { - const char* s = EL_CSTR(sv); - el_val_t lst = el_list_empty(); - if (!s) return lst; - size_t n = strlen(s); - /* Pre-scan: build into a normalized buffer with \r\n folded. */ - const char* line_start = s; - for (size_t i = 0; i <= n; i++) { - if (s[i] == '\n' || s[i] == '\0') { - size_t len = (size_t)(s + i - line_start); - /* Drop trailing \r if this was \r\n. */ - if (len > 0 && line_start[len - 1] == '\r') len--; - /* Drop final trailing-empty-after-newline. */ - if (s[i] == '\0' && len == 0 && i > 0 && s[i - 1] == '\n') break; - char* out = el_strbuf(len); - memcpy(out, line_start, len); - out[len] = '\0'; - lst = el_list_append(lst, el_wrap_str(out)); - if (s[i] == '\0') break; - line_start = s + i + 1; - } - } - return lst; -} - -el_val_t str_split_chars(el_val_t s) { - return native_string_chars(s); -} - -/* Split into at most n parts. The (n-1)th split point is the LAST split; - * after it, the remainder is appended verbatim including any further - * separators. n <= 0 returns an empty list. n == 1 returns [s]. */ -el_val_t str_split_n(el_val_t sv, el_val_t sepv, el_val_t nv) { - const char* s = EL_CSTR(sv); - const char* sep = EL_CSTR(sepv); - int64_t n = (int64_t)nv; - el_val_t lst = el_list_empty(); - if (!s) return lst; - if (n <= 0) return lst; - if (n == 1 || !sep || !*sep) { - lst = el_list_append(lst, el_wrap_str(el_strdup(s))); - return lst; - } - size_t lp = strlen(sep); - const char* p = s; - int64_t parts = 0; - const char* hit; - while (parts < n - 1 && (hit = strstr(p, sep)) != NULL) { - size_t len = (size_t)(hit - p); - char* out = el_strbuf(len); - memcpy(out, p, len); - out[len] = '\0'; - lst = el_list_append(lst, el_wrap_str(out)); - p = hit + lp; - parts++; - } - /* Remainder verbatim. */ - lst = el_list_append(lst, el_wrap_str(el_strdup(p))); - return lst; -} - -/* Join a [String] with a separator. Empty list -> "". Single-element -> - * that element. Non-string elements are stringified via int_to_str. */ -el_val_t str_join(el_val_t listv, el_val_t sepv) { - return list_join(listv, sepv); -} - -/* ── List additions ──────────────────────────────────────────────────────── */ - -el_val_t list_push(el_val_t list, el_val_t elem) { - return el_list_append(list, elem); -} - -el_val_t list_push_front(el_val_t listv, el_val_t elem) { - ElList* lst = (ElList*)(uintptr_t)listv; - if (!lst) { - el_val_t nl = el_list_empty(); - return el_list_append(nl, elem); - } - /* Append to grow capacity, then shift right */ - listv = el_list_append(listv, elem); - lst = (ElList*)(uintptr_t)listv; - for (int64_t i = lst->length - 1; i > 0; i--) { - lst->elems[i] = lst->elems[i - 1]; - } - lst->elems[0] = elem; - return EL_STR(lst); -} - -el_val_t list_join(el_val_t listv, el_val_t sep) { - ElList* lst = (ElList*)(uintptr_t)listv; - const char* sp = EL_CSTR(sep); - if (!sp) sp = ""; - if (!lst || lst->length == 0) return el_wrap_str(el_strdup("")); - JsonBuf b; jb_init(&b); - for (int64_t i = 0; i < lst->length; i++) { - if (i > 0) jb_puts(&b, sp); - el_val_t v = lst->elems[i]; - if (v == 0) continue; - if (looks_like_string(v)) { - jb_puts(&b, EL_CSTR(v)); - } else { - char tmp[32]; - snprintf(tmp, sizeof(tmp), "%lld", (long long)v); - jb_puts(&b, tmp); - } - } - return el_wrap_str(jb_finish(&b)); -} - -el_val_t list_range(el_val_t start, el_val_t end) { - int64_t a = (int64_t)start; - int64_t b = (int64_t)end; - el_val_t lst = el_list_empty(); - for (int64_t i = a; i < b; i++) lst = el_list_append(lst, (el_val_t)i); - return lst; -} - -/* ── Bool helpers ────────────────────────────────────────────────────────── */ - -el_val_t bool_to_str(el_val_t b) { - return el_wrap_str(el_strdup(b ? "true" : "false")); -} - -/* ── Numeric parsing ─────────────────────────────────────────────────────── */ - -/* parse_int — strtoll with a default. str_to_int already exists but does not - * distinguish "0" from a parse failure, so callers that need a sentinel use - * this. Skips leading whitespace; accepts an optional leading +/-; returns - * default_val on empty input or no consumed digits. Trailing junk is ignored - * (atoi-style). */ -el_val_t parse_int(el_val_t sv, el_val_t default_val) { - const char* s = EL_CSTR(sv); - if (!s) return default_val; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == '\0') return default_val; - char* end = NULL; - long long n = strtoll(s, &end, 10); - if (end == s) return default_val; - return (el_val_t)n; -} - -/* ── Process ─────────────────────────────────────────────────────────────── */ - -el_val_t exit_program(el_val_t code) { - exit((int)code); - return 0; /* unreachable */ -} - -/* getpid_now — current process id. Named with the _now suffix to avoid - * colliding with the libc `getpid` declaration that the runtime already - * sees via (calling it `getpid` would fight the prototype). */ -el_val_t getpid_now(void) { - return (el_val_t)getpid(); -} - -/* el_mem_check — self-terminating memory guard for long-running compiler runs. - * - * Call this periodically (e.g. after each function compiled) to detect runaway - * memory growth before the OS OOM-killer fires. Reads the limit from the env - * var ELC_MAX_MEM_MB (default 512 MB). If resident set size exceeds the limit, - * prints a diagnostic to stderr and exits with code 1 so the caller (elb or a - * CI script) can handle the failure gracefully instead of having the whole - * machine go down. - * - * Platform notes: - * macOS — ru_maxrss is in bytes. - * Linux — ru_maxrss is in kilobytes. - * We normalise to MB before comparing. - * - * Returns 0 always (the only non-return path is the exit() branch). - */ -el_val_t el_mem_check(void) { -#ifdef _WIN32 - /* getrusage is POSIX-only — memory guard disabled on Windows. */ - return 0; -#else - /* Read limit from env; default 512 MB. */ - long limit_mb = 512; - const char *env_val = getenv("ELC_MAX_MEM_MB"); - if (env_val && *env_val) { - long v = atol(env_val); - if (v > 0) limit_mb = v; - } - - struct rusage ru; - if (getrusage(RUSAGE_SELF, &ru) != 0) return 0; /* can't read — skip check */ - - long rss_mb; -#if defined(__APPLE__) || defined(__MACH__) - /* macOS: ru_maxrss is bytes */ - rss_mb = (long)(ru.ru_maxrss / (1024L * 1024L)); -#else - /* Linux: ru_maxrss is kilobytes */ - rss_mb = (long)(ru.ru_maxrss / 1024L); -#endif - - if (rss_mb >= limit_mb) { - fprintf(stderr, "elc: memory limit exceeded (%ldMB), aborting\n", limit_mb); - exit(1); - } - return 0; -#endif -} - -/* ── args() — command-line argument access ────────────────────────────────── - * Compiled El programs call args() to get a list of CLI arguments. - * Call el_runtime_init_args(argc, argv) at the start of C main() to populate. - * The args list excludes argv[0] (the program name). */ - -static el_val_t _el_args_list = 0; - -void el_runtime_init_args(int argc, char** argv) { - _el_args_list = el_list_empty(); - for (int i = 1; i < argc; i++) { - _el_args_list = el_list_append(_el_args_list, EL_STR(argv[i])); - } -} - -el_val_t args(void) { - if (!_el_args_list) _el_args_list = el_list_empty(); - return _el_args_list; -} - -/* ── CGI identity ──────────────────────────────────────────────────────────── - * Called once at program start by the generated main() of a cgi {} program. - * Stores CGI identity so dharma_* builtins can reference it. */ - -static const char* _el_cgi_name = NULL; -static const char* _el_cgi_dharma_id = NULL; -static const char* _el_cgi_principal = NULL; -static const char* _el_cgi_network = NULL; -static const char* _el_cgi_engram = NULL; - -void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, - el_val_t network, el_val_t engram) { - _el_cgi_name = EL_CSTR(name); - _el_cgi_dharma_id = EL_CSTR(dharma_id); - _el_cgi_principal = EL_CSTR(principal); - _el_cgi_network = EL_CSTR(network) ? EL_CSTR(network) : "dharma-mainnet"; - _el_cgi_engram = EL_CSTR(engram) ? EL_CSTR(engram) : "http://localhost:8742"; - printf("[cgi] identity: name=%s dharma_id=%s principal=%s network=%s engram=%s\n", - _el_cgi_name ? _el_cgi_name : "(unset)", - _el_cgi_dharma_id ? _el_cgi_dharma_id : "(unset)", - _el_cgi_principal ? _el_cgi_principal : "(unset)", - _el_cgi_network, - _el_cgi_engram); -} - - -/* ── Batch 3: Engram in-process graph store ──────────────────────────────── */ -/* - * Single global EngramStore allocated lazily on first call. All node and - * edge content strings are owned (strdup'd) by the store. Linear arrays - * with doubling capacity for both nodes and edges. - * - * Two-layer activation algorithm (engram_activate): - * - * LAYER 1 — Broad fan-out (background activation): - * 1. Find seed nodes whose content/label/tags contain query (case-insens). - * 2. BFS up to `depth` hops along ALL edges (excitatory and inhibitory). - * Every reachable node fires — nothing is filtered at this layer. - * 3. bg_act = seed.salience * temporal_decay * dampening - * propagated as: new_bg = parent_bg * edge_weight * 0.7 * (1 + tbonus) - * where tbonus ∈ {0, 0.10, 0.20} for co-temporal nodes. - * 4. If reached by multiple paths, take max background_activation. - * 5. Persist background_activation to EngramNode.background_activation. - * - * LAYER 2 — Executive filter (working memory promotion): - * 6. For each inhibitory edge where source has background_activation > 0: - * inhibition[target] = max(bg[source] * e->weight) - * 7. For each background-activated node: - * raw_wm = bg * goal_bias(node, query) * confidence - * * (1 - (1 - INHIBITION_FACTOR) * inhibition) - * 8. Per-type threshold gate: raw_wm >= type_threshold → promoted. - * Safety/DharmaSelf: 0.05 Canonical: 0.15 Lesson: 0.25 - * Belief/Entity: 0.30 Note/Memory/Working: 0.40 - * 9. If not promoted: suppression_count++. After - * ENGRAM_SUPPRESSION_BREAKTHROUGH suppressions → force breakthrough - * at ENGRAM_BREAKTHROUGH_WEIGHT (latent tension surfacing). - * 10. Persist working_memory_weight to EngramNode.working_memory_weight. - * 11. Sort: promoted nodes (wm > 0) first by wm desc, then background- - * only by bg desc. Context compilation uses ONLY promoted nodes. - * - * Temporal decay: - * decay_factor = exp(-lambda * age_hours / T_half) - * T_half = 168.0 h (one week), lambda = ln(2) - * - * Activation dampening: - * dampen = 1.0 / (1.0 + log(1 + activation_count)) - * - * engram_query_range(start_ms, end_ms): - * Returns nodes whose created_at OR last_activated falls within - * [start_ms, end_ms], sorted by created_at ascending. - */ - -/* Temporal decay constants. - * T_HALF_HOURS: half-life in hours — one week. After one week of no - * activation a node retains 50% of its base salience contribution. - * DECAY_LAMBDA: ln(2) ≈ 0.693147 */ -#define ENGRAM_T_HALF_HOURS 168.0 -#define ENGRAM_DECAY_LAMBDA 0.693147 - -/* Two-layer activation constants. - * ENGRAM_WM_THRESHOLD: minimum background_activation for a node to be - * considered for working-memory promotion (layer 2 candidate gate). - * ENGRAM_WM_DECAY: per-turn decay applied to working_memory_weight for - * nodes NOT re-activated in the current turn (conversational thread - * continuity: a node promoted in turn N persists with reduced weight - * into turn N+1 without re-activation cost). - * ENGRAM_SUPPRESSION_BREAKTHROUGH: after this many consecutive suppressions - * a latent node forces itself into working memory at reduced weight, - * modelling the brain's "intrusive thought" / unresolved-tension surfacing. - * ENGRAM_BREAKTHROUGH_WEIGHT: the reduced working_memory_weight assigned - * when a suppressed node breaks through. - * ENGRAM_INHIBITION_FACTOR: multiplier applied to working_memory_weight when - * an inhibitory edge fires against a node (0 = full suppress, 0.3 = partial). */ -#define ENGRAM_WM_THRESHOLD 0.15 -#define ENGRAM_WM_DECAY 0.7 -#define ENGRAM_SUPPRESSION_BREAKTHROUGH 5 -#define ENGRAM_BREAKTHROUGH_WEIGHT 0.25 -#define ENGRAM_INHIBITION_FACTOR 0.1 -/* ENGRAM_WM_CAP: hard global ceiling on nodes holding working_memory_weight - * > 0 at any time. Cowan (2001) puts human WM capacity at ~4 chunks; 24 gives - * the daemon generous headroom while preventing the unbounded growth observed - * in production (wm_active 288-778 per heartbeat — "working memory" that is - * really the whole recently-touched graph). Ported from release runtime - * v1.0.0-20260501 Pass 5 on 2026-07-15 self-review. */ -#define ENGRAM_WM_CAP 24 - -/* ── Layered consciousness architecture ────────────────────────────────────── - * - * The engram graph is stratified into LAYERS that gate which suppressions - * apply during the executive filter pass. Layers are ordered shallow-to-deep - * by `activation_priority`; the deepest layer (priority 0, conventionally - * "safety") is the structural floor of the soul: nodes here cannot be - * silenced by inhibitory edges from any other layer. Higher layers - * (core-identity, domain-knowledge, imprint, suit) are normally - * suppressible — they participate in attentional inhibition and goal - * focus the way the prior single-graph implementation did. - * - * The five canonical layers (see engram_init_layers): - * 0. safety — structural, transparent, non-injectable, non-suppressible - * 1. core-identity — default for legacy nodes; suppressible - * 2. domain-knowledge— suppressible - * 3. imprint — runtime-injectable (an Imprint package can add/remove) - * 4. suit — runtime-injectable (a Suit overlays domain skill) - * - * Three-pass activation (engram_activate): - * Pass 1 — Background fan-out: BFS spreads activation across ALL layers - * (existing behavior preserved). Inhibitory edges propagate at - * this layer too; no filtering happens here. - * Pass 2 — Working memory promotion: type-threshold gate, goal bias, - * confidence weighting, inhibitory suppression. Inhibitory edges - * ONLY apply against nodes whose layer is `suppressible == 1`. - * Nodes in non-suppressible layers (Layer 0) ignore inhibition. - * Pass 3 — Layer 0 override: every node in a non-suppressible layer that - * received background activation has its working_memory_weight - * forced to >= ENGRAM_LAYER0_OVERRIDE_WEIGHT. The sacred fire — - * safety nodes that touched any seed unconditionally surface, - * even when the executive filter would have silenced them. - * - * Layer fields: - * suppressible : 0 → inhibitory edges are ignored against nodes in this - * layer during pass 2. Pass 3 also force-promotes them. - * 1 → standard behavior (most layers). - * transparent : 1 → emitted into the prompt context so its content shapes - * output, but filtered out of "what do you know about - * yourself?" introspection queries (engram_search and - * friends do not return transparent-layer nodes by - * default). 0 → fully visible to introspection. - * injectable : 1 → can be added/removed at runtime via engram_add_layer - * and engram_remove_layer (imprints, suits). - * 0 → built-in, fixed at engram_get() initialization. - * - * Backward compatibility: - * Nodes and edges loaded from snapshots without a `layer_id` field default - * to layer 1 (core-identity). The five canonical layers are always present. - */ -#define ENGRAM_LAYER_SAFETY 0u -#define ENGRAM_LAYER_CORE_IDENTITY 1u -#define ENGRAM_LAYER_DOMAIN 2u -#define ENGRAM_LAYER_IMPRINT 3u -#define ENGRAM_LAYER_SUIT 4u -#define ENGRAM_LAYER_ACCUMULATION 5u -/* New user-facing nodes (memories, knowledge, conversations) are created in the - * accumulation layer — the top of the consciousness stack, the engram the user - * sees; every layer below shapes behavior but is hidden from the user (Layered - * Consciousness architecture, app 64/064,262). ENGRAM_LAYER_DEFAULT stays - * core-identity ON PURPOSE: it is the fallback home for LEGACY nodes loaded from - * snapshots without a layer_id, so existing data (the originator corpus) is - * never migrated out of its established layer. New != legacy. */ -#define ENGRAM_LAYER_DEFAULT ENGRAM_LAYER_CORE_IDENTITY - -/* Pass 3 override floor. Layer 0 nodes that received any background - * activation are force-promoted to AT LEAST this working_memory_weight, - * regardless of inhibitory suppression in pass 2. */ -#define ENGRAM_LAYER0_OVERRIDE_WEIGHT 1.0 - -/* Per-node-type activation thresholds. - * Lower tier / safety-critical nodes fire more readily. */ -static double engram_type_threshold(const char* node_type, const char* tier) { - if (node_type) { - if (strcmp(node_type, "DharmaSelf") == 0) return 0.05; - if (strcmp(node_type, "Safety") == 0) return 0.05; - } - if (tier) { - if (strcmp(tier, "Canonical") == 0) return 0.15; - if (strcmp(tier, "Lesson") == 0) return 0.25; - } - if (node_type) { - /* Knowledge nodes: Canonical/Lesson handled by tier checks above. - * Procedural-tier Knowledge (activation_count>=50 migration): 0.20. - * (2026-06-29 self-review — mirrors release runtime fix) */ - if (strcmp(node_type, "Knowledge") == 0) return 0.20; - if (strcmp(node_type, "Belief") == 0) return 0.30; - if (strcmp(node_type, "Entity") == 0) return 0.30; - } - return 0.40; /* Note / Memory / Working (most nodes) */ -} - -typedef struct EngramNode { - char* id; - char* content; - char* node_type; - char* label; - char* tier; - char* tags; - char* metadata; - double salience; - double importance; - double confidence; - double temporal_decay_rate; /* per-node override for lambda; 0 = use default */ - int64_t activation_count; - int64_t last_activated; - int64_t created_at; - int64_t updated_at; - /* Two-layer activation fields ───────────────────────────────────────── - * background_activation: Layer 1. Set by BFS fan-out on every query. - * Every reachable node fires here — nothing is filtered at this stage. - * Models the brain's massive parallel sub-threshold activation of all - * associated content in response to a stimulus. - * working_memory_weight: Layer 2. Executive filter output. Only nodes - * that survive goal-state / attentional-bias scoring receive a - * non-zero weight here. Context compilation ONLY uses this field. - * Background-activated nodes with working_memory_weight == 0 remain - * latent — real, available, but silent. - * suppression_count: Consecutive turn count where this node was - * background-activated but NOT promoted to working memory. High - * values signal the node "wants to surface." After - * ENGRAM_SUPPRESSION_BREAKTHROUGH consecutive suppressions the node - * is force-promoted at a reduced weight (breakthrough activation). */ - double background_activation; - double working_memory_weight; - int32_t suppression_count; - /* Layered consciousness — see ENGRAM_LAYER_* macros and engram_init_layers. - * Defaults to ENGRAM_LAYER_DEFAULT (1, core-identity) for legacy nodes - * created via engram_node / engram_node_full and for snapshots that - * predate the layered schema. */ - uint32_t layer_id; -} EngramNode; - -typedef struct EngramEdge { - char* id; - char* from_id; - char* to_id; - char* relation; - char* metadata; - double weight; - double confidence; - int64_t created_at; - int64_t updated_at; - int64_t last_fired; - /* Inhibitory flag: when 1, activating the source node SUPPRESSES the - * working_memory_weight of the target node rather than exciting it. - * Models attentional inhibition: "I am focused on code work" creates - * inhibitory edges to personal/emotional nodes, preventing them from - * surfacing even if they have high background_activation. */ - int inhibitory; - /* Layered consciousness — edges carry a layer assignment for - * categorization/visualization. Pass 2 inhibitory gating is decided by - * the TARGET node's layer (whether it's suppressible), not by the edge - * layer. Defaults to ENGRAM_LAYER_DEFAULT. */ - uint32_t layer_id; -} EngramEdge; - -/* Layered consciousness — runtime layer registry entry. */ -typedef struct EngramLayer { - uint32_t layer_id; /* 0 = deepest (safety/limbic) */ - char* name; /* persistent — owned by the store */ - uint32_t activation_priority; /* lower = fires earlier; safety = 0 */ - int suppressible; /* can higher layers suppress nodes here? */ - int transparent; /* invisible to introspection queries? */ - int injectable; /* can be added/removed at runtime? */ -} EngramLayer; - -typedef struct EngramStore { - EngramNode* nodes; - int64_t node_count; - int64_t node_capacity; - EngramEdge* edges; - int64_t edge_count; - int64_t edge_capacity; - /* Layer registry — see engram_init_layers. The five canonical layers - * are always present; injectable layers (imprint, suit) are extended - * via engram_add_layer at runtime. layer_id values are assigned - * monotonically; removed injectable layers leave a NULL `name` slot - * (tombstone) so existing layer_id references on nodes stay stable. */ - EngramLayer* layers; - size_t layer_count; - size_t layer_capacity; -} EngramStore; - -static EngramStore* engram_global = NULL; - -/* Initialize the five canonical layers on a fresh store. Called once from - * engram_get(). Layer ids 0..4 are reserved; runtime-injected imprint/suit - * layers (engram_add_layer) get ids 5+. */ -static void engram_init_layers(EngramStore* g) { - g->layer_capacity = 16; - g->layers = calloc(g->layer_capacity, sizeof(EngramLayer)); - if (!g->layers) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - g->layer_count = 0; - - /* Layer 0 — safety. Structural floor. Non-suppressible; transparent - * (filtered out of introspection but still shapes output); not - * runtime-injectable. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_SAFETY, - .name = el_strdup_persist("safety"), - .activation_priority = 0, - .suppressible = 0, - .transparent = 1, - .injectable = 0 - }; - /* Layer 1 — core-identity. The default home for legacy nodes. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_CORE_IDENTITY, - .name = el_strdup_persist("core-identity"), - .activation_priority = 10, - .suppressible = 1, - .transparent = 0, - .injectable = 0 - }; - /* Layer 2 — domain-knowledge. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_DOMAIN, - .name = el_strdup_persist("domain-knowledge"), - .activation_priority = 20, - .suppressible = 1, - .transparent = 0, - .injectable = 0 - }; - /* Layer 3 — imprint. Injectable: an imprint package adds/removes this - * layer (and the nodes assigned to it) as a unit. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_IMPRINT, - .name = el_strdup_persist("imprint"), - .activation_priority = 30, - .suppressible = 1, - .transparent = 0, - .injectable = 1 - }; - /* Layer 4 — suit. Injectable: a Suit overlays domain skill (e.g. - * "enterprise advisor", "divorce lawyer") and can be detached. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_SUIT, - .name = el_strdup_persist("suit"), - .activation_priority = 40, - .suppressible = 1, - .transparent = 0, - .injectable = 1 - }; - /* Layer 5 — accumulation. The TOP of the consciousness stack: the default - * home for all new user-facing nodes. This is the engram the user sees; - * every layer below shapes behavior but is hidden from the user. Not - * injectable — it is the persistent user accumulation, not a swappable - * overlay. transparent=0: its content is surfaced to introspection (it is - * the user's own knowledge/memory), unlike the lower behavioral layers. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_ACCUMULATION, - .name = el_strdup_persist("accumulation"), - .activation_priority = 50, - .suppressible = 1, - .transparent = 0, - .injectable = 0 - }; -} - -static EngramStore* engram_get(void) { - if (engram_global) return engram_global; - engram_global = calloc(1, sizeof(EngramStore)); - if (!engram_global) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - engram_global->node_capacity = 16; - engram_global->nodes = calloc((size_t)engram_global->node_capacity, sizeof(EngramNode)); - engram_global->edge_capacity = 16; - engram_global->edges = calloc((size_t)engram_global->edge_capacity, sizeof(EngramEdge)); - engram_init_layers(engram_global); - return engram_global; -} - -/* Resolve a layer record by id. Returns NULL if no layer with that id - * exists (e.g. a removed injectable layer or a malformed snapshot). */ -static EngramLayer* engram_find_layer(uint32_t layer_id) { - EngramStore* g = engram_get(); - for (size_t i = 0; i < g->layer_count; i++) { - EngramLayer* L = &g->layers[i]; - if (!L->name) continue; /* tombstone for removed injectable layer */ - if (L->layer_id == layer_id) return L; - } - return NULL; -} - -/* Resolve a layer record by name. Returns NULL if not found. */ -static EngramLayer* engram_find_layer_by_name(const char* name) { - if (!name || !*name) return NULL; - EngramStore* g = engram_get(); - for (size_t i = 0; i < g->layer_count; i++) { - EngramLayer* L = &g->layers[i]; - if (!L->name) continue; - if (strcmp(L->name, name) == 0) return L; - } - return NULL; -} - -/* Allocate the next layer id. Skips ids that are still in use. */ -static uint32_t engram_next_layer_id(void) { - EngramStore* g = engram_get(); - uint32_t maxid = 0; - for (size_t i = 0; i < g->layer_count; i++) { - if (g->layers[i].layer_id > maxid) maxid = g->layers[i].layer_id; - } - return maxid + 1; -} - -/* Whether a node in `layer_id` may be silenced by inhibitory edges in pass 2. */ -static int engram_layer_is_suppressible(uint32_t layer_id) { - EngramLayer* L = engram_find_layer(layer_id); - if (!L) return 1; /* unknown layer → safe default: standard suppression */ - return L->suppressible ? 1 : 0; -} - -/* Whether a layer is transparent (its content shapes output but is filtered - * from introspection queries). Currently used to mark Layer 0 as invisible - * to "what do you know about yourself" lookups while still letting it - * dominate the prompt context. */ -static int engram_layer_is_transparent(uint32_t layer_id) { - EngramLayer* L = engram_find_layer(layer_id); - if (!L) return 0; - return L->transparent ? 1 : 0; -} - -static int64_t engram_now_ms(void) { - struct timeval tv; gettimeofday(&tv, NULL); - return (int64_t)tv.tv_sec * 1000LL + (int64_t)tv.tv_usec / 1000LL; -} - -static EngramNode* engram_find_node(const char* id) { - if (!id) return NULL; - EngramStore* g = engram_get(); - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].id && strcmp(g->nodes[i].id, id) == 0) return &g->nodes[i]; - } - return NULL; -} - -static int64_t engram_find_node_index(const char* id) { - if (!id) return -1; - EngramStore* g = engram_get(); - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].id && strcmp(g->nodes[i].id, id) == 0) return i; - } - return -1; -} - -static void engram_grow_nodes(void) { - EngramStore* g = engram_get(); - if (g->node_count < g->node_capacity) return; - int64_t nc = g->node_capacity * 2; - g->nodes = realloc(g->nodes, (size_t)nc * sizeof(EngramNode)); - if (!g->nodes) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(g->nodes + g->node_capacity, 0, - (size_t)(nc - g->node_capacity) * sizeof(EngramNode)); - g->node_capacity = nc; -} - -static void engram_grow_edges(void) { - EngramStore* g = engram_get(); - if (g->edge_count < g->edge_capacity) return; - int64_t nc = g->edge_capacity * 2; - g->edges = realloc(g->edges, (size_t)nc * sizeof(EngramEdge)); - if (!g->edges) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(g->edges + g->edge_capacity, 0, - (size_t)(nc - g->edge_capacity) * sizeof(EngramEdge)); - g->edge_capacity = nc; -} - -/* Build a fresh UUID string. Reuses uuid_new but takes the underlying char*. */ -static char* engram_new_id(void) { - el_val_t v = uuid_new(); - const char* s = EL_CSTR(v); - /* Persistent: node ids live in the global store; an arena (el_strdup) id is - * freed at el_request_end(), corrupting the node after the creating request. */ - return el_strdup_persist(s ? s : ""); -} - -/* Convert a node into an ElMap of its fields. */ -static el_val_t engram_node_to_map(const EngramNode* n) { - el_val_t m = el_map_new(0); - m = el_map_set(m, EL_STR(el_strdup("id")), EL_STR(el_strdup(n->id ? n->id : ""))); - m = el_map_set(m, EL_STR(el_strdup("content")), EL_STR(el_strdup(n->content ? n->content : ""))); - m = el_map_set(m, EL_STR(el_strdup("node_type")), EL_STR(el_strdup(n->node_type ? n->node_type : ""))); - m = el_map_set(m, EL_STR(el_strdup("label")), EL_STR(el_strdup(n->label ? n->label : ""))); - m = el_map_set(m, EL_STR(el_strdup("tier")), EL_STR(el_strdup(n->tier ? n->tier : "Working"))); - m = el_map_set(m, EL_STR(el_strdup("tags")), EL_STR(el_strdup(n->tags ? n->tags : ""))); - m = el_map_set(m, EL_STR(el_strdup("metadata")), EL_STR(el_strdup(n->metadata ? n->metadata : "{}"))); - m = el_map_set(m, EL_STR(el_strdup("salience")), el_from_float(n->salience)); - m = el_map_set(m, EL_STR(el_strdup("importance")), el_from_float(n->importance)); - m = el_map_set(m, EL_STR(el_strdup("confidence")), el_from_float(n->confidence)); - m = el_map_set(m, EL_STR(el_strdup("temporal_decay_rate")), el_from_float(n->temporal_decay_rate)); - m = el_map_set(m, EL_STR(el_strdup("activation_count")), (el_val_t)n->activation_count); - m = el_map_set(m, EL_STR(el_strdup("last_activated")), (el_val_t)n->last_activated); - m = el_map_set(m, EL_STR(el_strdup("created_at")), (el_val_t)n->created_at); - m = el_map_set(m, EL_STR(el_strdup("updated_at")), (el_val_t)n->updated_at); - m = el_map_set(m, EL_STR(el_strdup("background_activation")), el_from_float(n->background_activation)); - m = el_map_set(m, EL_STR(el_strdup("working_memory_weight")), el_from_float(n->working_memory_weight)); - m = el_map_set(m, EL_STR(el_strdup("suppression_count")), (el_val_t)n->suppression_count); - m = el_map_set(m, EL_STR(el_strdup("layer_id")), (el_val_t)(int64_t)n->layer_id); - return m; -} - -/* (Node JSON serialization is provided by `engram_emit_node_json` further - * down in the persistence section — reused by the *_json builtins below.) */ -static void engram_emit_node_json(JsonBuf* b, const EngramNode* n); -static void engram_emit_edge_json(JsonBuf* b, const EngramEdge* e); - -/* Salience may arrive either as a float bit-pattern or as a small integer - * (e.g. 1, meaning 1.0). Heuristic: if interpreted as double it's in - * [0.0, 100.0] use it; otherwise treat as int and convert. */ -static double engram_decode_score(el_val_t v) { - double f = el_to_float(v); - if (!isnan(f) && !isinf(f) && f >= 0.0 && f <= 100.0) return f; - int64_t n = (int64_t)v; - return (double)n; -} - -static char* engram_first_n_chars(const char* s, size_t n) { - if (!s) return el_strdup(""); - size_t l = strlen(s); - if (l > n) l = n; - char* out = el_strbuf(l); - memcpy(out, s, l); - out[l] = '\0'; - return out; -} - -el_val_t engram_node(el_val_t content, el_val_t node_type, el_val_t salience) { - EngramStore* g = engram_get(); - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = engram_new_id(); - const char* c = EL_CSTR(content); - const char* nt = EL_CSTR(node_type); - n->content = el_strdup_persist(c ? c : ""); - n->node_type = el_strdup_persist(nt && *nt ? nt : "Memory"); - { char* _lb = engram_first_n_chars(c, 60); n->label = el_strdup_persist(_lb); } /* persist: stored field must outlive request arena */ - n->tier = el_strdup_persist("Working"); - n->tags = el_strdup_persist(""); - n->metadata = el_strdup_persist("{}"); - n->salience = engram_decode_score(salience); - if (n->salience <= 0.0 || n->salience > 1.0) n->salience = 0.5; - n->importance = 0.5; - n->confidence = 1.0; - n->temporal_decay_rate = 0.0; /* 0 = use global default ENGRAM_DECAY_LAMBDA */ - n->activation_count = 0; - int64_t now = engram_now_ms(); - n->last_activated = now; - n->created_at = now; - n->updated_at = now; - n->layer_id = ENGRAM_LAYER_ACCUMULATION; /* new user-facing node → top layer */ - g->node_count++; - return el_wrap_str(el_strdup(n->id)); -} - -/* engram_is_valid_utf8 — return 1 if s is valid UTF-8, 0 if it contains invalid bytes. - * Rejects overlong encodings, surrogate halves, and byte sequences > 4 bytes. */ -static int engram_is_valid_utf8(const char* s) { - if (!s) return 1; - const unsigned char* p = (const unsigned char*)s; - while (*p) { - if (*p < 0x80) { - /* ASCII */ - p++; - } else if ((*p & 0xE0) == 0xC0) { - /* 2-byte sequence */ - if ((p[1] & 0xC0) != 0x80) return 0; - if ((*p & 0xFE) == 0xC0) return 0; /* overlong */ - p += 2; - } else if ((*p & 0xF0) == 0xE0) { - /* 3-byte sequence */ - if ((p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80) return 0; - if (*p == 0xE0 && (p[1] & 0xE0) == 0x80) return 0; /* overlong */ - if (*p == 0xED && (p[1] & 0xE0) == 0xA0) return 0; /* surrogate */ - p += 3; - } else if ((*p & 0xF8) == 0xF0) { - /* 4-byte sequence */ - if ((p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80) return 0; - if (*p == 0xF0 && (p[1] & 0xF0) == 0x80) return 0; /* overlong */ - if (*p > 0xF4) return 0; /* above U+10FFFF */ - p += 4; - } else { - return 0; - } - } - return 1; -} - -el_val_t engram_node_full(el_val_t content, el_val_t node_type, el_val_t label, - el_val_t salience, el_val_t importance, el_val_t confidence, - el_val_t tier, el_val_t tags) { - EngramStore* g = engram_get(); - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = engram_new_id(); - const char* c = EL_CSTR(content); - const char* nt = EL_CSTR(node_type); - const char* lb = EL_CSTR(label); - const char* ti = EL_CSTR(tier); - const char* tg = EL_CSTR(tags); - /* UTF-8 guard: reject content with invalid UTF-8 bytes. Persisting invalid - * UTF-8 garbles JSON snapshots and corrupts every subsequent node read. */ - if (c && !engram_is_valid_utf8(c)) { - fprintf(stderr, "[engram] REJECTED node write — content contains invalid UTF-8 (label=%s)\n", - lb ? lb : "(null)"); - return EL_STR(""); - } - /* Persistent (el_strdup_persist, NOT el_strdup): these strings are owned by the - * persistent global node store. el_strdup tracks into the per-request arena, which - * el_request_end() frees when the creating HTTP request completes — leaving the - * stored node with dangling pointers (corrupted ids, "saved but never listed"). - * This is the root cause of the hallucinated/lost-saves class of bugs. */ - n->content = el_strdup_persist(c ? c : ""); - n->node_type = el_strdup_persist(nt && *nt ? nt : "Memory"); - n->label = el_strdup_persist(lb && *lb ? lb : (c ? engram_first_n_chars(c, 60) : "")); - n->tier = el_strdup_persist(ti && *ti ? ti : "Working"); - n->tags = el_strdup_persist(tg ? tg : ""); - n->metadata = el_strdup_persist("{}"); - n->salience = engram_decode_score(salience); - n->importance = engram_decode_score(importance); - n->confidence = engram_decode_score(confidence); - if (n->salience <= 0.0 || n->salience > 1.0) n->salience = 0.5; - if (n->importance <= 0.0 || n->importance > 1.0) n->importance = 0.5; - if (n->confidence <= 0.0 || n->confidence > 1.0) n->confidence = 1.0; - n->temporal_decay_rate = 0.0; /* 0 = use global default ENGRAM_DECAY_LAMBDA */ - n->activation_count = 0; - int64_t now = engram_now_ms(); - n->last_activated = now; - n->created_at = now; - n->updated_at = now; - n->layer_id = ENGRAM_LAYER_ACCUMULATION; /* new user-facing node → top layer */ - g->node_count++; - return el_wrap_str(el_strdup(n->id)); -} - -/* engram_node_layered — like engram_node_full but with explicit layer - * assignment and an additional `status` slot reserved for callers that - * track lifecycle state in metadata. The signature mirrors the public API - * defined in the layered consciousness design doc: - * - * engram_node_layered(content, node_type, label, - * salience, certainty, confidence, - * status, tags, layer_id) - * - * `certainty` is folded into `importance` (it occupies the same axis in - * the existing schema). `status` is recorded under metadata.status; an - * empty status leaves metadata as the default "{}". - * - * If `layer_id` does not resolve to a known layer the call falls back to - * ENGRAM_LAYER_DEFAULT — better to keep the node addressable than to drop - * it because of a stale layer reference. Callers wanting strict validation - * should engram_list_layers first. */ -el_val_t engram_node_layered(el_val_t content, el_val_t node_type, el_val_t label, - el_val_t salience, el_val_t certainty, el_val_t confidence, - el_val_t status, el_val_t tags, el_val_t layer_id) { - EngramStore* g = engram_get(); - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = engram_new_id(); - const char* c = EL_CSTR(content); - const char* nt = EL_CSTR(node_type); - const char* lb = EL_CSTR(label); - const char* tg = EL_CSTR(tags); - const char* st = EL_CSTR(status); - n->content = el_strdup_persist(c ? c : ""); - n->node_type = el_strdup_persist(nt && *nt ? nt : "Memory"); - n->label = el_strdup_persist(lb && *lb ? lb : (c ? engram_first_n_chars(c, 60) : "")); - n->tier = el_strdup_persist("Working"); - n->tags = el_strdup_persist(tg ? tg : ""); - if (st && *st) { - /* Minimal metadata payload: {"status":"..."}. Keep it cheap so - * callers using `status` don't pay JSON parse cost on every read. */ - size_t sl = strlen(st) + 16; - char* meta = el_strbuf(sl); - snprintf(meta, sl, "{\"status\":\"%s\"}", st); - n->metadata = meta; - } else { - n->metadata = el_strdup_persist("{}"); - } - n->salience = engram_decode_score(salience); - n->importance = engram_decode_score(certainty); - n->confidence = engram_decode_score(confidence); - if (n->salience <= 0.0 || n->salience > 1.0) n->salience = 0.5; - if (n->importance <= 0.0 || n->importance > 1.0) n->importance = 0.5; - if (n->confidence <= 0.0 || n->confidence > 1.0) n->confidence = 1.0; - n->temporal_decay_rate = 0.0; - n->activation_count = 0; - int64_t now = engram_now_ms(); - n->last_activated = now; - n->created_at = now; - n->updated_at = now; - /* Resolve layer assignment. Caller passes either a numeric layer_id or - * a stringified id; el_to_float / int cast tolerates both. */ - int64_t lid = (int64_t)layer_id; - if (lid < 0) lid = (int64_t)ENGRAM_LAYER_DEFAULT; - if (!engram_find_layer((uint32_t)lid)) lid = (int64_t)ENGRAM_LAYER_DEFAULT; - n->layer_id = (uint32_t)lid; - g->node_count++; - return el_wrap_str(el_strdup(n->id)); -} - -/* ── Layer registry public API ────────────────────────────────────────────── - * - * The five canonical layers are seeded at engram_get() initialization. - * Runtime code (typically imprint/suit injection logic at the EL level) - * can extend the registry with engram_add_layer() — only layers marked - * `injectable=1` may be removed via engram_remove_layer(). Removing a - * layer leaves a tombstone slot so existing layer_id references on nodes - * stay valid; orphaned references resolve to "unknown layer" and inherit - * the default suppression behavior. - */ - -/* engram_add_layer — register a new layer at runtime. - * Returns the assigned layer_id as an el_val_t int (cast back via int64_t). - * Conflicting names are rejected (returns 0). */ -el_val_t engram_add_layer(el_val_t name, el_val_t priority, el_val_t suppressible, - el_val_t transparent, el_val_t injectable) { - EngramStore* g = engram_get(); - const char* nm = EL_CSTR(name); - if (!nm || !*nm) return (el_val_t)0; - if (engram_find_layer_by_name(nm)) { - /* Name collision — return existing id so callers are idempotent. */ - return (el_val_t)(int64_t)engram_find_layer_by_name(nm)->layer_id; - } - if (g->layer_count >= g->layer_capacity) { - size_t nc = g->layer_capacity ? g->layer_capacity * 2 : 16; - EngramLayer* grown = realloc(g->layers, nc * sizeof(EngramLayer)); - if (!grown) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(grown + g->layer_capacity, 0, - (nc - g->layer_capacity) * sizeof(EngramLayer)); - g->layers = grown; - g->layer_capacity = nc; - } - EngramLayer* L = &g->layers[g->layer_count++]; - L->layer_id = engram_next_layer_id(); - L->name = el_strdup_persist(nm); - L->activation_priority = (uint32_t)(int64_t)priority; - L->suppressible = (int)(int64_t)suppressible ? 1 : 0; - L->transparent = (int)(int64_t)transparent ? 1 : 0; - L->injectable = (int)(int64_t)injectable ? 1 : 0; - return (el_val_t)(int64_t)L->layer_id; -} - -/* engram_remove_layer — remove an injectable layer by id. - * Built-in (non-injectable) layers cannot be removed. Nodes still tagged - * with the removed layer's id keep their tag but resolve to "unknown - * layer" thereafter and inherit standard (suppressible) behavior. - * Returns 1 on success, 0 on failure (unknown id, non-injectable). */ -el_val_t engram_remove_layer(el_val_t layer_id) { - EngramStore* g = engram_get(); - int64_t lid = (int64_t)layer_id; - for (size_t i = 0; i < g->layer_count; i++) { - EngramLayer* L = &g->layers[i]; - if (!L->name) continue; - if ((int64_t)L->layer_id != lid) continue; - if (!L->injectable) return (el_val_t)0; - free(L->name); - L->name = NULL; /* tombstone */ - /* Leave layer_id, priority, flags intact so debug snapshots can - * still distinguish "removed at runtime" from "never existed". */ - return (el_val_t)1; - } - return (el_val_t)0; -} - -/* engram_list_layers — enumerate the active layer registry. - * Returns an ElList of maps, one per non-tombstone layer, sorted by - * activation_priority ascending (deepest layer first). */ -el_val_t engram_list_layers(void) { - EngramStore* g = engram_get(); - el_val_t lst = el_list_empty(); - if (g->layer_count == 0) return lst; - /* Build an index sorted by activation_priority ascending. */ - size_t* idx = malloc(g->layer_count * sizeof(size_t)); - if (!idx) return lst; - size_t live = 0; - for (size_t i = 0; i < g->layer_count; i++) { - if (g->layers[i].name) idx[live++] = i; - } - /* Insertion sort — N is small (≤ a few dozen layers). */ - for (size_t i = 1; i < live; i++) { - size_t key = idx[i]; - uint32_t kp = g->layers[key].activation_priority; - size_t j = i; - while (j > 0 && g->layers[idx[j - 1]].activation_priority > kp) { - idx[j] = idx[j - 1]; - j--; - } - idx[j] = key; - } - for (size_t i = 0; i < live; i++) { - EngramLayer* L = &g->layers[idx[i]]; - el_val_t m = el_map_new(0); - m = el_map_set(m, EL_STR(el_strdup("layer_id")), - (el_val_t)(int64_t)L->layer_id); - m = el_map_set(m, EL_STR(el_strdup("name")), - EL_STR(el_strdup(L->name ? L->name : ""))); - m = el_map_set(m, EL_STR(el_strdup("activation_priority")), - (el_val_t)(int64_t)L->activation_priority); - m = el_map_set(m, EL_STR(el_strdup("suppressible")), - (el_val_t)(int64_t)(L->suppressible ? 1 : 0)); - m = el_map_set(m, EL_STR(el_strdup("transparent")), - (el_val_t)(int64_t)(L->transparent ? 1 : 0)); - m = el_map_set(m, EL_STR(el_strdup("injectable")), - (el_val_t)(int64_t)(L->injectable ? 1 : 0)); - lst = el_list_append(lst, m); - } - free(idx); - return lst; -} - -el_val_t engram_get_node(el_val_t id) { - const char* sid = EL_CSTR(id); - EngramNode* n = engram_find_node(sid); - if (!n) return el_map_new(0); - return engram_node_to_map(n); -} - -void engram_strengthen(el_val_t node_id) { - const char* sid = EL_CSTR(node_id); - EngramNode* n = engram_find_node(sid); - if (!n) return; - n->salience += 0.05; - if (n->salience > 1.0) n->salience = 1.0; - n->activation_count++; - n->last_activated = engram_now_ms(); - n->updated_at = n->last_activated; -} - -void engram_forget(el_val_t node_id) { - const char* sid = EL_CSTR(node_id); - if (!sid) return; - EngramStore* g = engram_get(); - int64_t idx = engram_find_node_index(sid); - if (idx < 0) return; - /* Free node strings */ - EngramNode* n = &g->nodes[idx]; - free(n->id); free(n->content); free(n->node_type); free(n->label); - free(n->tier); free(n->tags); free(n->metadata); - /* Shift remaining nodes down */ - for (int64_t i = idx + 1; i < g->node_count; i++) { - g->nodes[i - 1] = g->nodes[i]; - } - g->node_count--; - memset(&g->nodes[g->node_count], 0, sizeof(EngramNode)); - /* Remove all incident edges */ - int64_t w = 0; - for (int64_t r = 0; r < g->edge_count; r++) { - EngramEdge* e = &g->edges[r]; - int incident = (e->from_id && strcmp(e->from_id, sid) == 0) || - (e->to_id && strcmp(e->to_id, sid) == 0); - if (incident) { - free(e->id); free(e->from_id); free(e->to_id); - free(e->relation); free(e->metadata); - } else { - if (w != r) g->edges[w] = g->edges[r]; - w++; - } - } - g->edge_count = w; -} - -el_val_t engram_node_count(void) { - return (el_val_t)engram_get()->node_count; -} - -static int istr_contains(const char* hay, const char* needle) { - if (!hay || !needle || !*needle) return 0; - size_t nl = strlen(needle); - for (const char* p = hay; *p; p++) { - if (strncasecmp(p, needle, nl) == 0) return 1; - } - return 0; -} - -/* ── Tokenized query matching ─────────────────────────────────────────── - * The engram query surface (search / activate / goal-bias) historically - * matched the ENTIRE raw query string as a single case-insensitive - * substring via istr_contains(field, q). That is Ctrl-F, not search: - * a multi-word query like "windows msi signing" only matched a node whose - * text contained that exact contiguous run, so real multi-word queries - * returned zero. istr_contains stays as the per-TOKEN primitive; these - * helpers split the query on whitespace and match ANY token, then rank by - * how many DISTINCT tokens a node covers. Single-token queries are a strict - * special case (score is 0 or 1) so single-word callers never regress. */ -#define ENGRAM_MAX_QTOKENS 32 -#define ENGRAM_QTOK_LEN 256 - -/* Split q on whitespace into up to ENGRAM_MAX_QTOKENS distinct - * (case-insensitive) tokens. Returns the token count. Over-long tokens are - * truncated to ENGRAM_QTOK_LEN-1; over-count tokens are ignored. */ -static int engram_tokenize_query(const char* q, - char toks[][ENGRAM_QTOK_LEN], int maxtok) { - int n = 0; - if (!q) return 0; - const char* p = q; - while (*p && n < maxtok) { - while (*p && isspace((unsigned char)*p)) p++; - if (!*p) break; - char buf[ENGRAM_QTOK_LEN]; - size_t tl = 0; - while (*p && !isspace((unsigned char)*p)) { - if (tl < sizeof(buf) - 1) buf[tl++] = *p; - p++; - } - buf[tl] = '\0'; - if (tl == 0) continue; - int dup = 0; - for (int s = 0; s < n; s++) { - if (strcasecmp(toks[s], buf) == 0) { dup = 1; break; } - } - if (dup) continue; - memcpy(toks[n], buf, tl + 1); - n++; - } - return n; -} - -/* Count how many of the ntok distinct query tokens appear (case-insensitive) - * in the node's content, label, or tags. 0 == no match. */ -static int engram_node_match_score(const EngramNode* n, - char toks[][ENGRAM_QTOK_LEN], int ntok) { - int score = 0; - for (int t = 0; t < ntok; t++) { - if (istr_contains(n->content, toks[t]) || - istr_contains(n->label, toks[t]) || - istr_contains(n->tags, toks[t])) - score++; - } - return score; -} - -/* Rank entry: distinct-token match count (primary, desc) then salience - * (tiebreak, desc). */ -typedef struct { int64_t idx; int score; double salience; } EngramRankEntry; -static int engram_rank_cmp(const void* a, const void* b) { - const EngramRankEntry* ea = (const EngramRankEntry*)a; - const EngramRankEntry* eb = (const EngramRankEntry*)b; - if (ea->score != eb->score) return eb->score - ea->score; /* desc */ - if (ea->salience < eb->salience) return 1; - if (ea->salience > eb->salience) return -1; - return 0; -} - -el_val_t engram_search(el_val_t query, el_val_t limit) { - EngramStore* g = engram_get(); - const char* q = EL_CSTR(query); - int64_t lim = (int64_t)limit; - if (lim <= 0) lim = 100; - el_val_t lst = el_list_empty(); - if (!q || !*q) return lst; - char toks[ENGRAM_MAX_QTOKENS][ENGRAM_QTOK_LEN]; - int ntok = engram_tokenize_query(q, toks, ENGRAM_MAX_QTOKENS); - if (ntok == 0) return lst; - EngramRankEntry* hits = malloc((size_t)g->node_count * sizeof(EngramRankEntry)); - if (!hits) return lst; - int64_t nhits = 0; - for (int64_t i = 0; i < g->node_count; i++) { - EngramNode* n = &g->nodes[i]; - /* Filter transparent layers: nodes whose layer is `transparent=1` - * shape output but are invisible to introspection ("what do you - * know about yourself"). They still surface via engram_activate - * + engram_compile_layered_json — that's the legitimate path. */ - if (engram_layer_is_transparent(n->layer_id)) continue; - int sc = engram_node_match_score(n, toks, ntok); - if (sc > 0) { - hits[nhits].idx = i; - hits[nhits].score = sc; - hits[nhits].salience = n->salience; - nhits++; - } - } - /* Rank by distinct tokens matched (desc) then salience (desc), then cap. */ - qsort(hits, (size_t)nhits, sizeof(EngramRankEntry), engram_rank_cmp); - int64_t end = nhits < lim ? nhits : lim; - for (int64_t k = 0; k < end; k++) { - lst = el_list_append(lst, engram_node_to_map(&g->nodes[hits[k].idx])); - } - free(hits); - return lst; -} - -/* Sort node indices by salience desc (small N, insertion sort is fine). */ -static void engram_sort_indices_by_salience(int64_t* arr, int64_t n, - const EngramNode* nodes) { - for (int64_t i = 1; i < n; i++) { - int64_t key = arr[i]; - double ks = nodes[key].salience; - int64_t j = i - 1; - while (j >= 0 && nodes[arr[j]].salience < ks) { - arr[j + 1] = arr[j]; - j--; - } - arr[j + 1] = key; - } -} - -el_val_t engram_scan_nodes(el_val_t limit, el_val_t offset) { - EngramStore* g = engram_get(); - int64_t lim = (int64_t)limit; if (lim <= 0) lim = 100; - int64_t off = (int64_t)offset; if (off < 0) off = 0; - el_val_t lst = el_list_empty(); - if (g->node_count == 0) return lst; - int64_t* idx = malloc((size_t)g->node_count * sizeof(int64_t)); - if (!idx) return lst; - /* Skip transparent layers — same introspection-filter rationale as - * engram_search above. */ - int64_t live = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (engram_layer_is_transparent(g->nodes[i].layer_id)) continue; - idx[live++] = i; - } - engram_sort_indices_by_salience(idx, live, g->nodes); - int64_t end = off + lim; - if (end > live) end = live; - for (int64_t i = off; i < end; i++) { - lst = el_list_append(lst, engram_node_to_map(&g->nodes[idx[i]])); - } - free(idx); - return lst; -} - -void engram_connect(el_val_t from_id, el_val_t to_id, el_val_t weight, el_val_t relation) { - EngramStore* g = engram_get(); - const char* f = EL_CSTR(from_id); - const char* t = EL_CSTR(to_id); - const char* r = EL_CSTR(relation); - if (!f || !t) return; - engram_grow_edges(); - EngramEdge* e = &g->edges[g->edge_count]; - memset(e, 0, sizeof(*e)); - e->id = engram_new_id(); - e->from_id = el_strdup_persist(f); - e->to_id = el_strdup_persist(t); - e->relation = el_strdup_persist(r && *r ? r : "associate"); - e->metadata = el_strdup_persist("{}"); - e->weight = engram_decode_score(weight); - if (e->weight <= 0.0 || e->weight > 1.0) e->weight = 0.5; - e->confidence = 1.0; - int64_t now = engram_now_ms(); - e->created_at = now; - e->updated_at = now; - e->last_fired = 0; - e->layer_id = ENGRAM_LAYER_DEFAULT; - g->edge_count++; -} - -el_val_t engram_edge_between(el_val_t from_id, el_val_t to_id) { - EngramStore* g = engram_get(); - const char* f = EL_CSTR(from_id); - const char* t = EL_CSTR(to_id); - if (!f || !t) return 0; - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - if (e->from_id && e->to_id && - strcmp(e->from_id, f) == 0 && strcmp(e->to_id, t) == 0) return 1; - } - return 0; -} - -/* Reserved helper: edge -> ElMap. Kept around for future builtins. */ -static el_val_t engram_edge_to_map(const EngramEdge* e) __attribute__((unused)); -static el_val_t engram_edge_to_map(const EngramEdge* e) { - el_val_t m = el_map_new(0); - m = el_map_set(m, EL_STR(el_strdup("id")), EL_STR(el_strdup(e->id ? e->id : ""))); - m = el_map_set(m, EL_STR(el_strdup("from_id")), EL_STR(el_strdup(e->from_id ? e->from_id : ""))); - m = el_map_set(m, EL_STR(el_strdup("to_id")), EL_STR(el_strdup(e->to_id ? e->to_id : ""))); - m = el_map_set(m, EL_STR(el_strdup("relation")), EL_STR(el_strdup(e->relation ? e->relation : ""))); - m = el_map_set(m, EL_STR(el_strdup("metadata")), EL_STR(el_strdup(e->metadata ? e->metadata : "{}"))); - m = el_map_set(m, EL_STR(el_strdup("weight")), el_from_float(e->weight)); - m = el_map_set(m, EL_STR(el_strdup("confidence")), el_from_float(e->confidence)); - m = el_map_set(m, EL_STR(el_strdup("created_at")), (el_val_t)e->created_at); - m = el_map_set(m, EL_STR(el_strdup("updated_at")), (el_val_t)e->updated_at); - m = el_map_set(m, EL_STR(el_strdup("last_fired")), (el_val_t)e->last_fired); - m = el_map_set(m, EL_STR(el_strdup("inhibitory")), (el_val_t)(e->inhibitory ? 1 : 0)); - m = el_map_set(m, EL_STR(el_strdup("layer_id")), (el_val_t)(int64_t)e->layer_id); - return m; -} - -el_val_t engram_neighbors(el_val_t node_id) { - EngramStore* g = engram_get(); - const char* sid = EL_CSTR(node_id); - el_val_t lst = el_list_empty(); - if (!sid) return lst; - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - const char* other = NULL; - if (e->from_id && strcmp(e->from_id, sid) == 0) other = e->to_id; - else if (e->to_id && strcmp(e->to_id, sid) == 0) other = e->from_id; - if (!other) continue; - EngramNode* n = engram_find_node(other); - if (n) lst = el_list_append(lst, engram_node_to_map(n)); - } - return lst; -} - -el_val_t engram_neighbors_filtered(el_val_t node_id, el_val_t max_depth, el_val_t direction) { - EngramStore* g = engram_get(); - const char* sid = EL_CSTR(node_id); - int64_t md = (int64_t)max_depth; if (md <= 0) md = 1; - const char* dir = EL_CSTR(direction); /* "out" | "in" | "both" (default) */ - el_val_t lst = el_list_empty(); - if (!sid || g->node_count == 0) return lst; - int64_t start = engram_find_node_index(sid); - if (start < 0) return lst; - /* BFS with depth tracking */ - int64_t* visited = calloc((size_t)g->node_count, sizeof(int64_t)); - int64_t* queue = calloc((size_t)g->node_count, sizeof(int64_t)); - int64_t* depths = calloc((size_t)g->node_count, sizeof(int64_t)); - if (!visited || !queue || !depths) { - free(visited); free(queue); free(depths); return lst; - } - int64_t qh = 0, qt = 0; - queue[qt++] = start; - visited[start] = 1; - depths[start] = 0; - while (qh < qt) { - int64_t cur = queue[qh++]; - const char* cur_id = g->nodes[cur].id; - int64_t cur_depth = depths[cur]; - if (cur_depth >= md) continue; - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - const char* other = NULL; - int outgoing = e->from_id && strcmp(e->from_id, cur_id) == 0; - int incoming = e->to_id && strcmp(e->to_id, cur_id) == 0; - if (dir && strcmp(dir, "out") == 0 && !outgoing) continue; - if (dir && strcmp(dir, "in") == 0 && !incoming) continue; - if (outgoing) other = e->to_id; - else if (incoming) other = e->from_id; - else continue; - int64_t oi = engram_find_node_index(other); - if (oi < 0 || visited[oi]) continue; - visited[oi] = 1; - depths[oi] = cur_depth + 1; - queue[qt++] = oi; - } - } - /* Emit all visited except the seed */ - for (int64_t i = 0; i < g->node_count; i++) { - if (visited[i] && i != start) { - lst = el_list_append(lst, engram_node_to_map(&g->nodes[i])); - } - } - free(visited); free(queue); free(depths); - return lst; -} - -el_val_t engram_edge_count(void) { - return (el_val_t)engram_get()->edge_count; -} - -/* Compute temporal decay factor for a node given current time. - * effective contribution = salience * exp(-lambda * age_hours / T_half) - * Clamped to [0.05, 1.0] so very old nodes retain a meaningful floor. */ -static double engram_temporal_decay(const EngramNode* n, int64_t now_ms) { - int64_t age_ms = now_ms - n->last_activated; - if (age_ms <= 0) return 1.0; - double lambda = (n->temporal_decay_rate > 0.0) ? n->temporal_decay_rate - : ENGRAM_DECAY_LAMBDA; - double age_hours = (double)age_ms / 3600000.0; - double factor = exp(-lambda * age_hours / ENGRAM_T_HALF_HOURS); - if (factor < 0.05) factor = 0.05; - return factor; -} - -/* Activation dampening: high activation_count nodes are "well-known" context - * and get less marginal boost per firing. - * count=0 → 1.0, count=2 → ~0.74, count=9 → ~0.59, count=99 → ~0.43 */ -static double engram_activation_dampen(const EngramNode* n) { - return 1.0 / (1.0 + log(1.0 + (double)n->activation_count)); -} - -/* Temporal proximity bonus: boost propagation along edges connecting - * co-temporal nodes. Returns a multiplier bonus in [0, 0.2]. */ -static double engram_temporal_proximity_bonus(int64_t node_created, - int64_t seed_epoch) { - int64_t diff = node_created - seed_epoch; - if (diff < 0) diff = -diff; - if (diff < 86400000LL) return 0.20; /* within 1 day */ - if (diff < 604800000LL) return 0.10; /* within 7 days */ - return 0.0; -} - -/* ── Two-layer activation (biologically-motivated) ─────────────────────────── - * - * Layer 1 — Broad fan-out (background activation): - * BFS + spreading activation fires on ALL nodes reachable from seeds, - * regardless of relevance to the current goal. Every reachable node gets - * a background_activation score. Nothing is filtered here. Models the - * brain's massive parallel sub-threshold activation of all associated - * content in response to a stimulus. Temporal decay and activation - * dampening are applied at this layer (as before), but no threshold gate. - * - * Layer 2 — Executive filter (working memory promotion): - * A second pass asks: given the query (goal intent), attentional bias, - * and inhibitory edge topology — which background-activated nodes should - * break through into working memory? - * - * wm_weight = bg_activation * goal_bias(node, query) * confidence - * * inhibitory_suppression_factor - * - * Only nodes where wm_weight >= ENGRAM_WM_THRESHOLD are promoted to - * working memory (working_memory_weight > 0). Background-activated nodes - * that don't cross the threshold accumulate suppression_count. After - * ENGRAM_SUPPRESSION_BREAKTHROUGH consecutive suppressed turns, the node - * force-breaks through at ENGRAM_BREAKTHROUGH_WEIGHT (latent tension - * surfacing — models intrusive memory / unresolved cognitive load). - * - * Inhibitory edges: - * An edge with inhibitory=1 suppresses the TARGET node's working memory - * promotion when the SOURCE is background-activated. Background activation - * of the target is NOT affected — the node fires in layer 1. Only the - * executive filter (layer 2) is gated. Models attentional inhibition: - * "focused on code work" suppresses personal memories from surfacing - * even if they have high background_activation. - * - * Goal bias: - * A lightweight heuristic rates how well each background-activated node - * aligns with the apparent intent of the current query. Technical queries - * boost Belief/Canonical/Lesson nodes; relational queries boost Memory/ - * Entity nodes. Direct lexical overlap gives a 50% bonus. - * - * Working memory persistence (turn continuity): - * Nodes promoted in the previous turn retain a decayed working_memory_weight - * (weight *= ENGRAM_WM_DECAY) without needing re-activation. This models - * conversational thread continuity — once a topic is in working memory, - * it persists slightly into the next turn. - * - * Returns ElList of {node, activation_strength, working_memory_weight, - * epistemic_confidence, hops, promoted}. - * "promoted" = 1 if working_memory_weight > 0, 0 if background-only. - * Context compilation uses ONLY nodes with promoted=1. - * - * Temporal decay (preserved from prior implementation): - * effective_salience = salience * exp(-lambda * age_hours / T_half) - * where T_half = 168 h (one week), lambda = ln(2) - * - * Activation dampening (preserved): - * dampen = 1 / (1 + log(1 + activation_count)) - * - * Temporal proximity bonus (preserved): - * edge_strength *= (1 + tbonus) where tbonus ∈ {0, 0.10, 0.20} - * - * Per-type threshold gates apply only to working memory promotion (layer 2): - * Safety/DharmaSelf: 0.05 Canonical: 0.15 Lesson: 0.25 - * Belief/Entity: 0.30 Note/Memory/Working: 0.40 - */ - -/* Compute goal-state bias multiplier for a node given the query. - * Returns a value in [0.3, 2.0]. This is a lightweight heuristic — - * a production implementation may use LLM-derived intent classification. */ -static double engram_goal_bias(const EngramNode* n, const char* query) { - if (!query || !*query) return 1.0; - double bias = 1.0; - /* Direct lexical overlap, graded by token coverage: a node covering all - * query tokens gets the full +0.5; partial coverage gets a proportional - * share. Single-token queries → full +0.5 on match, identical to before. */ - { - char toks[ENGRAM_MAX_QTOKENS][ENGRAM_QTOK_LEN]; - int ntok = engram_tokenize_query(query, toks, ENGRAM_MAX_QTOKENS); - int sc = engram_node_match_score(n, toks, ntok); - if (sc > 0 && ntok > 0) bias += 0.5 * ((double)sc / (double)ntok); - } - /* Node-type resonance with query intent. */ - int technical_query = istr_contains(query, "code") || - istr_contains(query, "function") || - istr_contains(query, "implement") || - istr_contains(query, "error") || - istr_contains(query, "bug") || - istr_contains(query, "build") || - istr_contains(query, "system") || - istr_contains(query, "design") || - istr_contains(query, "architecture"); - int personal_query = istr_contains(query, "feel") || - istr_contains(query, "emotion") || - istr_contains(query, "remember") || - istr_contains(query, "personal") || - istr_contains(query, "story") || - istr_contains(query, "relationship"); - if (n->node_type) { - int is_knowledge = (strcmp(n->node_type, "Belief") == 0) || - (strcmp(n->node_type, "DharmaSelf") == 0) || - (strcmp(n->node_type, "Safety") == 0); - int is_personal = (strcmp(n->node_type, "Memory") == 0) || - (strcmp(n->node_type, "Entity") == 0); - if (technical_query && is_knowledge) bias += 0.3; - if (technical_query && is_personal) bias -= 0.3; - if (personal_query && is_personal) bias += 0.3; - if (personal_query && is_knowledge) bias -= 0.1; - } - /* Tier-based bonus: promote higher-confidence knowledge nodes. */ - if (n->tier) { - if (strcmp(n->tier, "Canonical") == 0) bias += 0.2; - if (strcmp(n->tier, "Lesson") == 0) bias += 0.1; - } - if (bias < 0.3) bias = 0.3; - if (bias > 2.0) bias = 2.0; - return bias; -} - -/* eg_cmp_double_desc — qsort comparator, descending doubles. */ -static int eg_cmp_double_desc(const void* a, const void* b) { - double da = *(const double*)a, db = *(const double*)b; - if (da < db) return 1; - if (da > db) return -1; - return 0; -} - -/* eg_enforce_wm_cap_global — clamp the store-wide working-memory population - * to ENGRAM_WM_CAP, keeping the top-K by current weight. Runs at every point - * that materializes WM: post-activation persist and snapshot load/merge. - * (Ported from release runtime v1.0.0-20260501 Pass 5, 2026-07-15.) */ -static void eg_enforce_wm_cap_global(EngramStore* g) { - int64_t wm_count = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].working_memory_weight > 0.0) wm_count++; - } - if (wm_count <= ENGRAM_WM_CAP) return; - double* vals = malloc((size_t)wm_count * sizeof(double)); - if (!vals) return; /* OOM: over cap this call, no corruption */ - int64_t vi = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].working_memory_weight > 0.0) - vals[vi++] = g->nodes[i].working_memory_weight; - } - qsort(vals, (size_t)wm_count, sizeof(double), eg_cmp_double_desc); - double cutoff = vals[ENGRAM_WM_CAP - 1]; - free(vals); - int64_t above = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].working_memory_weight > cutoff) above++; - } - int64_t slots_at_cutoff = ENGRAM_WM_CAP - above; - for (int64_t i = 0; i < g->node_count; i++) { - EngramNode* n = &g->nodes[i]; - if (n->working_memory_weight <= 0.0) continue; - if (n->working_memory_weight > cutoff) continue; - if (slots_at_cutoff > 0) { slots_at_cutoff--; continue; } - n->working_memory_weight = 0.0; /* evict: over global cap */ - } -} - -el_val_t engram_activate(el_val_t query, el_val_t depth) { - EngramStore* g = engram_get(); - const char* q = EL_CSTR(query); - int64_t max_depth = (int64_t)depth; if (max_depth <= 0) max_depth = 2; - el_val_t out = el_list_empty(); - if (!q || g->node_count == 0) return out; - - int64_t now_ms = engram_now_ms(); - - /* Per-node layer-1 tracking. */ - double* best_bg = calloc((size_t)g->node_count, sizeof(double)); - int64_t* best_hops = calloc((size_t)g->node_count, sizeof(int64_t)); - int* reached = calloc((size_t)g->node_count, sizeof(int)); - if (!best_bg || !best_hops || !reached) { - free(best_bg); free(best_hops); free(reached); return out; - } - - /* ── LAYER 1: broad fan-out (background activation) ───────────────── - * Find seeds, apply temporal decay + dampening, BFS with edge weights. - * Inhibitory edges propagate activation normally at this layer — they - * only gate working memory promotion in layer 2. */ - typedef struct { int64_t idx; double act; int64_t created_at; } SeedEntry; - SeedEntry* seeds = malloc((size_t)g->node_count * sizeof(SeedEntry)); - int64_t seed_count = 0; - if (!seeds) { - free(best_bg); free(best_hops); free(reached); return out; - } - /* Tokenize once: a node seeds if it matches ANY query token, and its seed - * activation is scaled by token coverage (fraction of distinct query - * tokens it contains) so a node matching all words seeds more strongly - * than one matching a single word. Single-word queries → coverage 1.0, - * identical to the prior whole-query behavior. */ - char toks[ENGRAM_MAX_QTOKENS][ENGRAM_QTOK_LEN]; - int ntok = engram_tokenize_query(q, toks, ENGRAM_MAX_QTOKENS); - for (int64_t i = 0; i < g->node_count; i++) { - EngramNode* n = &g->nodes[i]; - int sc = engram_node_match_score(n, toks, ntok); - if (sc > 0) { - double tdecay = engram_temporal_decay(n, now_ms); - double dampen = engram_activation_dampen(n); - double cover = ntok > 0 ? (double)sc / (double)ntok : 1.0; - double act = n->salience * tdecay * dampen * cover; - seeds[seed_count].idx = i; - seeds[seed_count].act = act; - seeds[seed_count].created_at = n->created_at; - seed_count++; - best_bg[i] = act; - best_hops[i] = 0; - reached[i] = 1; - } - } - /* Compute mean seed created_at for temporal proximity bonus. */ - int64_t seed_epoch = 0; - if (seed_count > 0) { - seed_epoch = seeds[0].created_at; - for (int64_t s = 1; s < seed_count; s++) - seed_epoch = (seed_epoch + seeds[s].created_at) / 2; - } - typedef struct { int64_t idx; int64_t hops; double act; } Frontier; - Frontier* fr = malloc((size_t)(g->node_count * (max_depth + 1)) * sizeof(Frontier) + 16 * sizeof(Frontier)); - if (!fr) { - free(best_bg); free(best_hops); free(reached); free(seeds); return out; - } - int64_t fhead = 0, ftail = 0; - int64_t fcap = (int64_t)((size_t)(g->node_count * (max_depth + 1)) + 16); - for (int64_t s = 0; s < seed_count; s++) { - if (ftail >= fcap) break; - fr[ftail].idx = seeds[s].idx; - fr[ftail].hops = 0; - fr[ftail].act = seeds[s].act; - ftail++; - } - const double SPREAD_DECAY = 0.7; - while (fhead < ftail) { - Frontier f = fr[fhead++]; - if (f.hops >= max_depth) continue; - const char* cur_id = g->nodes[f.idx].id; - for (int64_t ei = 0; ei < g->edge_count; ei++) { - EngramEdge* e = &g->edges[ei]; - const char* other = NULL; - if (e->from_id && strcmp(e->from_id, cur_id) == 0) other = e->to_id; - else if (e->to_id && strcmp(e->to_id, cur_id) == 0) other = e->from_id; - else continue; - int64_t oi = engram_find_node_index(other); - if (oi < 0) continue; - EngramNode* on = &g->nodes[oi]; - double tbonus = engram_temporal_proximity_bonus(on->created_at, seed_epoch); - double tdecay = engram_temporal_decay(on, now_ms); - double dampen = engram_activation_dampen(on); - double new_act = f.act * e->weight * SPREAD_DECAY * (1.0 + tbonus) - * tdecay * dampen; - int64_t new_hops = f.hops + 1; - if (!reached[oi] || new_act > best_bg[oi]) { - best_bg[oi] = new_act; - best_hops[oi] = new_hops; - reached[oi] = 1; - if (ftail < fcap) { - fr[ftail].idx = oi; - fr[ftail].hops = new_hops; - fr[ftail].act = new_act; - ftail++; - } - } - } - } - /* Persist layer-1 background_activation to node store. */ - for (int64_t i = 0; i < g->node_count; i++) { - g->nodes[i].background_activation = reached[i] ? best_bg[i] : 0.0; - } - - /* ── PASS 2: executive filter → working memory promotion ──────────── */ - /* Step A: collect inhibitory suppressions from fired inhibitory edges. - * Layered consciousness: inhibition is ONLY recorded against targets - * whose layer is `suppressible == 1`. Nodes in non-suppressible layers - * (Layer 0 / safety) ignore inhibitory edges entirely — their working - * memory weight cannot be silenced by attentional suppression. */ - double* inhibition = calloc((size_t)g->node_count, sizeof(double)); - if (!inhibition) { - free(best_bg); free(best_hops); free(reached); free(seeds); free(fr); - return out; - } - for (int64_t ei = 0; ei < g->edge_count; ei++) { - EngramEdge* e = &g->edges[ei]; - if (!e->inhibitory) continue; - int64_t src = engram_find_node_index(e->from_id); - int64_t tgt = engram_find_node_index(e->to_id); - if (src < 0 || tgt < 0) continue; - if (!reached[src] || best_bg[src] <= 0.0) continue; - /* Skip if target layer is non-suppressible: Layer 0 / safety nodes - * are immune to inhibitory edges from any source. The pass-3 - * override below also force-promotes them, but recording inhibition - * against them at all would be wasted work and could confuse - * downstream debugging output. */ - if (!engram_layer_is_suppressible(g->nodes[tgt].layer_id)) continue; - /* Inhibition strength proportional to source background activation - * and edge weight. Takes the maximum if multiple inhibitory edges - * target the same node. */ - double inh = best_bg[src] * e->weight; - if (inh > inhibition[tgt]) inhibition[tgt] = inh; - } - /* Step B: compute working_memory_weight per candidate node. */ - double* wm_weights = calloc((size_t)g->node_count, sizeof(double)); - if (!wm_weights) { - free(best_bg); free(best_hops); free(reached); free(seeds); - free(fr); free(inhibition); return out; - } - for (int64_t i = 0; i < g->node_count; i++) { - if (!reached[i] || best_bg[i] <= 0.0) continue; - EngramNode* n = &g->nodes[i]; - /* Per-type threshold: safety nodes break through more easily. */ - double type_threshold = engram_type_threshold(n->node_type, n->tier); - /* Goal bias weights the node's relevance to current intent. */ - double bias = engram_goal_bias(n, q); - /* Raw working memory score. */ - double raw_wm = best_bg[i] * bias * n->confidence; - /* Apply inhibitory suppression. Full inhibition → scale by factor. */ - double inh = inhibition[i]; - if (inh > 1.0) inh = 1.0; - double suppress = 1.0 - (1.0 - ENGRAM_INHIBITION_FACTOR) * inh; - raw_wm *= suppress; - /* Threshold gate: must exceed per-type threshold to enter working - * memory. Type threshold replaces the old flat 0.2 filter. */ - if (raw_wm >= type_threshold) { - wm_weights[i] = raw_wm > 1.0 ? 1.0 : raw_wm; - if (n->suppression_count > 0) n->suppression_count = 0; - } else { - /* Node didn't make it through — increment suppression counter. - * After N consecutive suppressions: force breakthrough. */ - n->suppression_count++; - if (n->suppression_count >= ENGRAM_SUPPRESSION_BREAKTHROUGH) { - wm_weights[i] = ENGRAM_BREAKTHROUGH_WEIGHT; - n->suppression_count = 0; - } else { - wm_weights[i] = 0.0; - } - } - } - /* ── PASS 3: Layer 0 override (the sacred fire) ───────────────────── - * Every node in a non-suppressible layer that received any background - * activation is force-promoted to AT LEAST ENGRAM_LAYER0_OVERRIDE_WEIGHT. - * This runs LAST and overrides whatever Pass 2 decided — Layer 0 cannot - * be silenced by inhibitory edges, by goal-bias misalignment, by - * confidence weighting, or by per-type threshold gates. If the seed - * fan-out reached a structural-floor node, that node surfaces. - * - * Note: this also clears the suppression_count when an override fires, - * since the node DID surface this turn — it just took the override path - * rather than the standard threshold path. Without this, a Layer 0 - * node with persistent inhibitory pressure would accumulate - * suppression_count forever and never reach the breakthrough state. */ - for (int64_t i = 0; i < g->node_count; i++) { - if (!reached[i] || best_bg[i] <= 0.0) continue; - EngramNode* n = &g->nodes[i]; - if (engram_layer_is_suppressible(n->layer_id)) continue; - if (wm_weights[i] < ENGRAM_LAYER0_OVERRIDE_WEIGHT) { - wm_weights[i] = ENGRAM_LAYER0_OVERRIDE_WEIGHT; - } - n->suppression_count = 0; - } - - /* Persist working_memory_weight (post Pass 3) to node store. */ - for (int64_t i = 0; i < g->node_count; i++) { - g->nodes[i].working_memory_weight = wm_weights[i]; - } - - /* Global WM cap: keep only the top ENGRAM_WM_CAP by weight across the - * whole store (see eg_enforce_wm_cap_global). Without this, repeated - * activation calls accumulate hundreds of "promoted" nodes and WM stops - * meaning anything (production heartbeats showed wm_active up to 778). */ - eg_enforce_wm_cap_global(g); - - /* ── Collect all background-activated nodes for the return value ──── - * Callers see both layers. Context compilation uses only promoted nodes - * (working_memory_weight > 0). Sort: promoted first by wm_weight desc, - * then background-only by background_activation desc. */ - typedef struct { int64_t idx; double bg; double wm; double epist; int64_t hops; } Result; - Result* results = malloc((size_t)g->node_count * sizeof(Result)); - int64_t rcount = 0; - if (!results) { - free(best_bg); free(best_hops); free(reached); free(seeds); - free(fr); free(inhibition); free(wm_weights); return out; - } - for (int64_t i = 0; i < g->node_count; i++) { - if (!reached[i]) continue; - double epist = best_bg[i] * g->nodes[i].confidence; - /* Include if promoted to working memory OR if background activation - * is meaningful enough to report (epist >= 0.1). */ - if (epist < 0.1 && wm_weights[i] <= 0.0) continue; - results[rcount].idx = i; - results[rcount].bg = best_bg[i]; - results[rcount].wm = wm_weights[i]; - results[rcount].epist = epist; - results[rcount].hops = best_hops[i]; - rcount++; - } - /* Sort: promoted nodes first (by wm_weight desc), then background-only - * by background_activation desc. */ - for (int64_t i = 1; i < rcount; i++) { - Result key = results[i]; - int64_t j = i - 1; - while (j >= 0 && (results[j].wm < key.wm || - (results[j].wm == key.wm && results[j].bg < key.bg))) { - results[j + 1] = results[j]; - j--; - } - results[j + 1] = key; - } - for (int64_t i = 0; i < rcount; i++) { - el_val_t entry = el_map_new(0); - entry = el_map_set(entry, EL_STR(el_strdup("node")), - engram_node_to_map(&g->nodes[results[i].idx])); - entry = el_map_set(entry, EL_STR(el_strdup("activation_strength")), - el_from_float(results[i].bg)); - entry = el_map_set(entry, EL_STR(el_strdup("working_memory_weight")), - el_from_float(results[i].wm)); - entry = el_map_set(entry, EL_STR(el_strdup("epistemic_confidence")), - el_from_float(results[i].epist)); - entry = el_map_set(entry, EL_STR(el_strdup("hops")), - (el_val_t)results[i].hops); - entry = el_map_set(entry, EL_STR(el_strdup("promoted")), - (el_val_t)(results[i].wm > 0.0 ? 1 : 0)); - out = el_list_append(out, entry); - } - free(best_bg); free(best_hops); free(reached); - free(seeds); free(fr); free(inhibition); free(wm_weights); free(results); - return out; -} - -/* ── Engram persistence (JSON snapshot) ─────────────────────────────────── */ - -static void engram_emit_node_json(JsonBuf* b, const EngramNode* n) { - jb_putc(b, '{'); - jb_puts(b, "\"id\":"); jb_emit_escaped(b, n->id ? n->id : ""); - jb_puts(b, ",\"content\":"); jb_emit_escaped(b, n->content ? n->content : ""); - jb_puts(b, ",\"node_type\":"); jb_emit_escaped(b, n->node_type ? n->node_type : ""); - jb_puts(b, ",\"label\":"); jb_emit_escaped(b, n->label ? n->label : ""); - jb_puts(b, ",\"tier\":"); jb_emit_escaped(b, n->tier ? n->tier : "Working"); - jb_puts(b, ",\"tags\":"); jb_emit_escaped(b, n->tags ? n->tags : ""); - jb_puts(b, ",\"metadata\":"); jb_emit_escaped(b, n->metadata ? n->metadata : "{}"); - char tmp[80]; - snprintf(tmp, sizeof(tmp), ",\"salience\":%g", n->salience); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"importance\":%g", n->importance); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"confidence\":%g", n->confidence); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"temporal_decay_rate\":%g", n->temporal_decay_rate); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"activation_count\":%lld", (long long)n->activation_count); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"last_activated\":%lld", (long long)n->last_activated); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"created_at\":%lld", (long long)n->created_at); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"updated_at\":%lld", (long long)n->updated_at); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"background_activation\":%g", n->background_activation); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"working_memory_weight\":%g", n->working_memory_weight); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"suppression_count\":%d", n->suppression_count); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"layer_id\":%u", n->layer_id); jb_puts(b, tmp); - jb_putc(b, '}'); -} - -static void engram_emit_edge_json(JsonBuf* b, const EngramEdge* e) { - jb_putc(b, '{'); - jb_puts(b, "\"id\":"); jb_emit_escaped(b, e->id ? e->id : ""); - jb_puts(b, ",\"from_id\":"); jb_emit_escaped(b, e->from_id ? e->from_id : ""); - jb_puts(b, ",\"to_id\":"); jb_emit_escaped(b, e->to_id ? e->to_id : ""); - jb_puts(b, ",\"relation\":"); jb_emit_escaped(b, e->relation ? e->relation : ""); - jb_puts(b, ",\"metadata\":"); jb_emit_escaped(b, e->metadata ? e->metadata : "{}"); - char tmp[64]; - snprintf(tmp, sizeof(tmp), ",\"weight\":%g", e->weight); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"confidence\":%g", e->confidence); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"created_at\":%lld", (long long)e->created_at); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"updated_at\":%lld", (long long)e->updated_at); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"last_fired\":%lld", (long long)e->last_fired); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"inhibitory\":%d", e->inhibitory ? 1 : 0); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"layer_id\":%u", e->layer_id); jb_puts(b, tmp); - jb_putc(b, '}'); -} - -el_val_t engram_save(el_val_t path) { - const char* p = EL_CSTR(path); - if (!p || !*p) return 0; - EngramStore* g = engram_get(); - JsonBuf b; jb_init(&b); - jb_puts(&b, "{\"nodes\":["); - for (int64_t i = 0; i < g->node_count; i++) { - if (i > 0) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[i]); - } - jb_puts(&b, "],\"edges\":["); - for (int64_t i = 0; i < g->edge_count; i++) { - if (i > 0) jb_putc(&b, ','); - engram_emit_edge_json(&b, &g->edges[i]); - } - /* Layered consciousness — emit the layer registry under "layers". - * Older readers that don't know about this top-level key will simply - * ignore it (forward compatible). Tombstoned (removed-injectable) - * layers are skipped — they have no name and can't be re-created - * meaningfully on load anyway. */ - jb_puts(&b, "],\"layers\":["); - int first_layer = 1; - for (size_t i = 0; i < g->layer_count; i++) { - EngramLayer* L = &g->layers[i]; - if (!L->name) continue; - if (!first_layer) jb_putc(&b, ','); - first_layer = 0; - jb_putc(&b, '{'); - char tmp[80]; - snprintf(tmp, sizeof(tmp), "\"layer_id\":%u", L->layer_id); - jb_puts(&b, tmp); - jb_puts(&b, ",\"name\":"); - jb_emit_escaped(&b, L->name); - snprintf(tmp, sizeof(tmp), ",\"activation_priority\":%u", L->activation_priority); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"suppressible\":%d", L->suppressible ? 1 : 0); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"transparent\":%d", L->transparent ? 1 : 0); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"injectable\":%d", L->injectable ? 1 : 0); - jb_puts(&b, tmp); - jb_putc(&b, '}'); - } - jb_puts(&b, "]}"); - { - struct stat _st; - if (stat(p, &_st) == 0 && _st.st_size > 200000 && - (uint64_t)b.len < (uint64_t)_st.st_size / 16) { - fprintf(stderr, "[engram_save] REFUSED sparse write: new %zu vs existing %lld (<1/16) protecting %s\n", - b.len, (long long)_st.st_size, p); - free(b.buf); return 0; - } - } - size_t _plen = strlen(p); - char* _tmp = (char*)malloc(_plen + 5); - if (!_tmp) { free(b.buf); return 0; } - memcpy(_tmp, p, _plen); memcpy(_tmp + _plen, ".tmp", 5); - FILE* f = fopen(_tmp, "wb"); - if (!f) { free(_tmp); free(b.buf); return 0; } - size_t w = fwrite(b.buf, 1, b.len, f); - int wok = (w == b.len); - if (wok) { fflush(f); fsync(fileno(f)); } - fclose(f); free(b.buf); - if (!wok) { unlink(_tmp); free(_tmp); return 0; } - if (rename(_tmp, p) != 0) { unlink(_tmp); free(_tmp); return 0; } - free(_tmp); return 1; -} - -/* Helper: extract a string field from a JSON object substring. */ -static char* eg_get_str_field(const char* obj, const char* key) { - const char* p = json_find_key(obj, key); - if (!p) return el_strdup_persist(""); - if (*p != '"') return el_strdup_persist(""); - JsonParser jp = { .p = p, .end = p + strlen(p), .err = 0 }; - char* out = jp_parse_string_raw(&jp); - if (jp.err) { free(out); return el_strdup_persist(""); } - return out; -} - -static double eg_get_num_field(const char* obj, const char* key) { - const char* p = json_find_key(obj, key); - if (!p || *p == '"' || *p == '{' || *p == '[') return 0.0; - return strtod(p, NULL); -} - -static int64_t eg_get_int_field(const char* obj, const char* key) { - const char* p = json_find_key(obj, key); - if (!p || *p == '"' || *p == '{' || *p == '[') return 0; - return strtoll(p, NULL, 10); -} - -/* Iterate the top-level nodes/edges arrays in a saved snapshot. */ -static const char* eg_skip_ws(const char* p) { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - return p; -} - -el_val_t engram_load(el_val_t path) { - const char* p = EL_CSTR(path); - if (!p || !*p) return 0; - FILE* f = fopen(p, "rb"); - if (!f) return 0; - fseek(f, 0, SEEK_END); - long sz = ftell(f); - rewind(f); - if (sz <= 0) { fclose(f); return 0; } - char* data = malloc((size_t)sz + 1); - if (!data) { fclose(f); return 0; } - size_t got = fread(data, 1, (size_t)sz, f); - fclose(f); - data[got] = '\0'; - - /* Reset store */ - EngramStore* g = engram_get(); - for (int64_t i = 0; i < g->node_count; i++) { - free(g->nodes[i].id); free(g->nodes[i].content); free(g->nodes[i].node_type); - free(g->nodes[i].label); free(g->nodes[i].tier); free(g->nodes[i].tags); - free(g->nodes[i].metadata); - } - g->node_count = 0; - for (int64_t i = 0; i < g->edge_count; i++) { - free(g->edges[i].id); free(g->edges[i].from_id); free(g->edges[i].to_id); - free(g->edges[i].relation); free(g->edges[i].metadata); - } - g->edge_count = 0; - - /* Walk nodes array */ - const char* nodes_p = json_find_key(data, "nodes"); - if (nodes_p) { - nodes_p = eg_skip_ws(nodes_p); - if (*nodes_p == '[') { - nodes_p++; - nodes_p = eg_skip_ws(nodes_p); - while (*nodes_p && *nodes_p != ']') { - if (*nodes_p != '{') { nodes_p++; continue; } - const char* end = json_skip_value(nodes_p); - size_t n = (size_t)(end - nodes_p); - char* obj = malloc(n + 1); - memcpy(obj, nodes_p, n); obj[n] = '\0'; - engram_grow_nodes(); - EngramNode* nn = &g->nodes[g->node_count]; - memset(nn, 0, sizeof(*nn)); - nn->id = eg_get_str_field(obj, "id"); - nn->content = eg_get_str_field(obj, "content"); - nn->node_type = eg_get_str_field(obj, "node_type"); - nn->label = eg_get_str_field(obj, "label"); - nn->tier = eg_get_str_field(obj, "tier"); - nn->tags = eg_get_str_field(obj, "tags"); - nn->metadata = eg_get_str_field(obj, "metadata"); - if (!nn->metadata || !*nn->metadata) { free(nn->metadata); nn->metadata = el_strdup_persist("{}"); } - nn->salience = eg_get_num_field(obj, "salience"); - nn->importance = eg_get_num_field(obj, "importance"); - nn->confidence = eg_get_num_field(obj, "confidence"); - nn->temporal_decay_rate = eg_get_num_field(obj, "temporal_decay_rate"); - /* temporal_decay_rate defaults to 0 (use global) if absent in snapshot */ - nn->activation_count = eg_get_int_field(obj, "activation_count"); - nn->last_activated = eg_get_int_field(obj, "last_activated"); - nn->created_at = eg_get_int_field(obj, "created_at"); - nn->updated_at = eg_get_int_field(obj, "updated_at"); - nn->background_activation = eg_get_num_field(obj, "background_activation"); - nn->working_memory_weight = eg_get_num_field(obj, "working_memory_weight"); - nn->suppression_count = (int32_t)eg_get_int_field(obj, "suppression_count"); - /* layer_id defaults to ENGRAM_LAYER_DEFAULT (core-identity) - * for snapshots that predate the layered schema. We can't - * tell "explicit 0" from "missing field" using the helper - * directly, so probe for the key — if absent, fall back. */ - if (json_find_key(obj, "layer_id")) { - nn->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); - } else { - nn->layer_id = ENGRAM_LAYER_DEFAULT; - } - g->node_count++; - free(obj); - nodes_p = end; - nodes_p = eg_skip_ws(nodes_p); - if (*nodes_p == ',') { nodes_p++; nodes_p = eg_skip_ws(nodes_p); } - } - } - } - /* Walk edges array */ - const char* edges_p = json_find_key(data, "edges"); - if (edges_p) { - edges_p = eg_skip_ws(edges_p); - if (*edges_p == '[') { - edges_p++; - edges_p = eg_skip_ws(edges_p); - while (*edges_p && *edges_p != ']') { - if (*edges_p != '{') { edges_p++; continue; } - const char* end = json_skip_value(edges_p); - size_t n = (size_t)(end - edges_p); - char* obj = malloc(n + 1); - memcpy(obj, edges_p, n); obj[n] = '\0'; - engram_grow_edges(); - EngramEdge* ee = &g->edges[g->edge_count]; - memset(ee, 0, sizeof(*ee)); - ee->id = eg_get_str_field(obj, "id"); - ee->from_id = eg_get_str_field(obj, "from_id"); - ee->to_id = eg_get_str_field(obj, "to_id"); - ee->relation = eg_get_str_field(obj, "relation"); - ee->metadata = eg_get_str_field(obj, "metadata"); - if (!ee->metadata || !*ee->metadata) { free(ee->metadata); ee->metadata = el_strdup_persist("{}"); } - ee->weight = eg_get_num_field(obj, "weight"); - ee->confidence = eg_get_num_field(obj, "confidence"); - ee->created_at = eg_get_int_field(obj, "created_at"); - ee->updated_at = eg_get_int_field(obj, "updated_at"); - ee->last_fired = eg_get_int_field(obj, "last_fired"); - ee->inhibitory = (int)eg_get_int_field(obj, "inhibitory"); - if (json_find_key(obj, "layer_id")) { - ee->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); - } else { - ee->layer_id = ENGRAM_LAYER_DEFAULT; - } - g->edge_count++; - free(obj); - edges_p = end; - edges_p = eg_skip_ws(edges_p); - if (*edges_p == ',') { edges_p++; edges_p = eg_skip_ws(edges_p); } - } - } - } - /* Walk layers array (optional — older snapshots omit this). - * If present we replace the canonical registry entirely; if absent we - * keep whatever the engram_get() init established. */ - const char* layers_p = json_find_key(data, "layers"); - if (layers_p) { - layers_p = eg_skip_ws(layers_p); - if (*layers_p == '[') { - /* Reset existing layer registry. Free strdup'd names; the - * struct array itself can be reused. */ - for (size_t i = 0; i < g->layer_count; i++) { - if (g->layers[i].name) free(g->layers[i].name); - g->layers[i].name = NULL; - } - g->layer_count = 0; - - layers_p++; - layers_p = eg_skip_ws(layers_p); - while (*layers_p && *layers_p != ']') { - if (*layers_p != '{') { layers_p++; continue; } - const char* end = json_skip_value(layers_p); - size_t n = (size_t)(end - layers_p); - char* obj = malloc(n + 1); - memcpy(obj, layers_p, n); obj[n] = '\0'; - if (g->layer_count >= g->layer_capacity) { - size_t nc = g->layer_capacity ? g->layer_capacity * 2 : 16; - EngramLayer* grown = realloc(g->layers, nc * sizeof(EngramLayer)); - if (!grown) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(grown + g->layer_capacity, 0, - (nc - g->layer_capacity) * sizeof(EngramLayer)); - g->layers = grown; - g->layer_capacity = nc; - } - EngramLayer* L = &g->layers[g->layer_count]; - memset(L, 0, sizeof(*L)); - L->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); - L->activation_priority = (uint32_t)eg_get_int_field(obj, "activation_priority"); - L->suppressible = (int)eg_get_int_field(obj, "suppressible") ? 1 : 0; - L->transparent = (int)eg_get_int_field(obj, "transparent") ? 1 : 0; - L->injectable = (int)eg_get_int_field(obj, "injectable") ? 1 : 0; - char* nm = eg_get_str_field(obj, "name"); - if (nm && *nm) { - L->name = el_strdup_persist(nm); - free(nm); - } else { - free(nm); - L->name = el_strdup_persist(""); - } - g->layer_count++; - free(obj); - layers_p = end; - layers_p = eg_skip_ws(layers_p); - if (*layers_p == ',') { layers_p++; layers_p = eg_skip_ws(layers_p); } - } - } - } - /* WM cap discipline applies to every entry point that materializes WM, - * including snapshot restore (see eg_enforce_wm_cap_global). */ - eg_enforce_wm_cap_global(g); - free(data); - return 1; -} - -/* ── Engram JSON-string accessors ───────────────────────────────────────── - * These return pre-serialized JSON strings so callers (especially HTTP - * handlers) don't have to round-trip ElList/ElMap through json_stringify - * — which can't reliably distinguish those structures from raw pointers - * due to el_val_t's type erasure. The runtime knows the real C types and - * can serialize directly. */ - -el_val_t engram_get_node_json(el_val_t id) { - const char* sid = EL_CSTR(id); - EngramNode* n = engram_find_node(sid); - if (!n) return el_wrap_str(el_strdup("{}")); - JsonBuf b; jb_init(&b); - engram_emit_node_json(&b, n); - return el_wrap_str(jb_finish(&b)); -} - -/* engram_get_node_by_label — find the first node whose label field exactly - * matches the given string. Returns the node as a JSON object string, or "{}" - * if no match is found. - * - * Exact match (strcmp, not substring) because labels like "conv:history" - * must not collide with nodes whose content contains that substring. - * - * Ported from the release runtime 2026-07-16 self-review: chat.el has called - * this since 2026-07-01 but the function only existed in - * releases/v1.0.0-20260501/el_runtime.c — the soul daemon (which builds - * against THIS runtime) failed to compile once clang made implicit - * declarations an error. */ -el_val_t engram_get_node_by_label(el_val_t label) { - const char* lbl = EL_CSTR(label); - if (!lbl || !*lbl) return el_wrap_str(el_strdup("{}")); - EngramStore* g = engram_get(); - for (int64_t i = 0; i < g->node_count; i++) { - EngramNode* n = &g->nodes[i]; - if (n->label && strcmp(n->label, lbl) == 0) { - JsonBuf b; jb_init(&b); - engram_emit_node_json(&b, n); - return el_wrap_str(jb_finish(&b)); - } - } - return el_wrap_str(el_strdup("{}")); -} - -el_val_t engram_search_json(el_val_t query, el_val_t limit) { - EngramStore* g = engram_get(); - const char* q = EL_CSTR(query); - int64_t lim = (int64_t)limit; - if (lim <= 0) lim = 100; - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - int first = 1; - if (q && *q) { - char toks[ENGRAM_MAX_QTOKENS][ENGRAM_QTOK_LEN]; - int ntok = engram_tokenize_query(q, toks, ENGRAM_MAX_QTOKENS); - if (ntok > 0) { - EngramRankEntry* hits = - malloc((size_t)g->node_count * sizeof(EngramRankEntry)); - if (hits) { - int64_t nhits = 0; - for (int64_t i = 0; i < g->node_count; i++) { - EngramNode* n = &g->nodes[i]; - /* Filter transparent layers — same as engram_search. */ - if (engram_layer_is_transparent(n->layer_id)) continue; - int sc = engram_node_match_score(n, toks, ntok); - if (sc > 0) { - hits[nhits].idx = i; - hits[nhits].score = sc; - hits[nhits].salience = n->salience; - nhits++; - } - } - /* Rank by distinct tokens matched (desc) then salience (desc). */ - qsort(hits, (size_t)nhits, sizeof(EngramRankEntry), - engram_rank_cmp); - int64_t end = nhits < lim ? nhits : lim; - for (int64_t k = 0; k < end; k++) { - if (!first) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[hits[k].idx]); - first = 0; - } - free(hits); - } - } - } - jb_putc(&b, ']'); - return el_wrap_str(jb_finish(&b)); -} - -el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset) { - EngramStore* g = engram_get(); - int64_t lim = (int64_t)limit; if (lim <= 0) lim = 100; - int64_t off = (int64_t)offset; if (off < 0) off = 0; - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - if (g->node_count == 0) { jb_putc(&b, ']'); return el_wrap_str(jb_finish(&b)); } - int64_t* idx = malloc((size_t)g->node_count * sizeof(int64_t)); - if (!idx) { jb_putc(&b, ']'); return el_wrap_str(jb_finish(&b)); } - /* Skip transparent layers — introspection filter, same as engram_scan_nodes. */ - int64_t live = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (engram_layer_is_transparent(g->nodes[i].layer_id)) continue; - idx[live++] = i; - } - engram_sort_indices_by_salience(idx, live, g->nodes); - int64_t end = off + lim; - if (end > live) end = live; - int first = 1; - for (int64_t i = off; i < end; i++) { - if (!first) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[idx[i]]); - first = 0; - } - free(idx); - jb_putc(&b, ']'); - return el_wrap_str(jb_finish(&b)); -} - -/* engram_scan_nodes_by_type_json — filter by node_type before paginating. - * Empty / NULL type_v falls back to the unfiltered scan (existing behaviour). - * Result is JSON array, salience-sorted, transparent layers skipped. */ -el_val_t engram_scan_nodes_by_type_json(el_val_t type_v, el_val_t limit, el_val_t offset) { - const char* type_filter = EL_CSTR(type_v); - if (!type_filter || !*type_filter) { - return engram_scan_nodes_json(limit, offset); - } - EngramStore* g = engram_get(); - int64_t lim = (int64_t)limit; if (lim <= 0) lim = 100; - int64_t off = (int64_t)offset; if (off < 0) off = 0; - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - if (g->node_count == 0) { jb_putc(&b, ']'); return el_wrap_str(jb_finish(&b)); } - int64_t* idx = malloc((size_t)g->node_count * sizeof(int64_t)); - if (!idx) { jb_putc(&b, ']'); return el_wrap_str(jb_finish(&b)); } - int64_t live = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (engram_layer_is_transparent(g->nodes[i].layer_id)) continue; - const char* nt = g->nodes[i].node_type; - if (!nt || strcmp(nt, type_filter) != 0) continue; - idx[live++] = i; - } - engram_sort_indices_by_salience(idx, live, g->nodes); - int64_t end = off + lim; - if (end > live) end = live; - int first = 1; - for (int64_t i = off; i < end; i++) { - if (!first) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[idx[i]]); - first = 0; - } - free(idx); - jb_putc(&b, ']'); - return el_wrap_str(jb_finish(&b)); -} - -el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction) { - /* Re-implement here directly so we serialize without going through - * the ElList path. Walks BFS to max_depth, emits {node, edge, hops} - * triples. */ - EngramStore* g = engram_get(); - const char* sid = EL_CSTR(node_id); - int64_t depth = (int64_t)max_depth; if (depth <= 0) depth = 1; - const char* dir = EL_CSTR(direction); if (!dir) dir = "both"; - int allow_out = (strcmp(dir, "out") == 0) || (strcmp(dir, "both") == 0); - int allow_in = (strcmp(dir, "in") == 0) || (strcmp(dir, "both") == 0); - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - if (!sid || !*sid) { jb_putc(&b, ']'); return el_wrap_str(jb_finish(&b)); } - - /* Frontier of (node_id, hops). Cap to a sane size. */ - char** frontier = calloc(1024, sizeof(char*)); - int64_t* frontier_h = calloc(1024, sizeof(int64_t)); - int64_t fc = 0; - char** visited = calloc(1024, sizeof(char*)); - int64_t vc = 0; - if (!frontier || !frontier_h || !visited) { - free(frontier); free(frontier_h); free(visited); - jb_putc(&b, ']'); return el_wrap_str(jb_finish(&b)); - } - /* Use plain strdup (not el_strdup) so arena doesn't track these pointers. - * The BFS loop manually frees them below — arena would double-free them. */ - frontier[fc] = strdup(sid); frontier_h[fc] = 0; fc++; - visited[vc++] = strdup(sid); - - int first = 1; - while (fc > 0) { - char* cur = frontier[0]; int64_t h = frontier_h[0]; - for (int64_t k = 1; k < fc; k++) { frontier[k-1] = frontier[k]; frontier_h[k-1] = frontier_h[k]; } - fc--; - if (h >= depth) { free(cur); continue; } - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - const char* peer = NULL; - if (allow_out && e->from_id && strcmp(e->from_id, cur) == 0) peer = e->to_id; - else if (allow_in && e->to_id && strcmp(e->to_id, cur) == 0) peer = e->from_id; - if (!peer) continue; - int seen = 0; - for (int64_t v = 0; v < vc; v++) { - if (strcmp(visited[v], peer) == 0) { seen = 1; break; } - } - if (seen) continue; - EngramNode* n = engram_find_node(peer); - if (!n) continue; - if (!first) jb_putc(&b, ','); - jb_puts(&b, "{\"node\":"); - engram_emit_node_json(&b, n); - jb_puts(&b, ",\"edge\":"); - engram_emit_edge_json(&b, e); - char tmp[64]; snprintf(tmp, sizeof(tmp), ",\"hops\":%lld}", (long long)(h + 1)); - jb_puts(&b, tmp); - first = 0; - if (vc < 1024) visited[vc++] = strdup(peer); - if (fc < 1024 && h + 1 < depth) { frontier[fc] = strdup(peer); frontier_h[fc] = h + 1; fc++; } - } - free(cur); - } - for (int64_t i = 0; i < fc; i++) free(frontier[i]); - for (int64_t i = 0; i < vc; i++) free(visited[i]); - free(frontier); free(frontier_h); free(visited); - jb_putc(&b, ']'); - return el_wrap_str(jb_finish(&b)); -} - -el_val_t engram_activate_json(el_val_t query, el_val_t depth) { - /* Run two-layer engram_activate and serialize the result list to JSON. - * Each entry includes both activation_strength (layer 1 background) and - * working_memory_weight (layer 2 executive filter), plus promoted flag. - * Callers performing context compilation should filter to promoted=1. */ - el_val_t lst = engram_activate(query, depth); - ElList* arr = (ElList*)(uintptr_t)lst; - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - if (arr) { - for (int64_t i = 0; i < arr->length; i++) { - if (!arr->elems[i]) continue; - el_val_t node_map = el_map_get(arr->elems[i], EL_STR("node")); - el_val_t strength_v = el_map_get(arr->elems[i], EL_STR("activation_strength")); - el_val_t wm_v = el_map_get(arr->elems[i], EL_STR("working_memory_weight")); - el_val_t epist_v = el_map_get(arr->elems[i], EL_STR("epistemic_confidence")); - el_val_t hops_v = el_map_get(arr->elems[i], EL_STR("hops")); - el_val_t promoted_v = el_map_get(arr->elems[i], EL_STR("promoted")); - /* Look up underlying EngramNode by id to emit canonical JSON. */ - el_val_t id_v = el_map_get(node_map, EL_STR("id")); - const char* id_s = EL_CSTR(id_v); - EngramNode* n = id_s ? engram_find_node(id_s) : NULL; - if (i > 0) jb_putc(&b, ','); - jb_puts(&b, "{\"node\":"); - if (n) { - engram_emit_node_json(&b, n); - } else { - jb_puts(&b, "{}"); - } - char tmp[80]; - snprintf(tmp, sizeof(tmp), ",\"activation_strength\":%g", el_to_float(strength_v)); jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"working_memory_weight\":%g", el_to_float(wm_v)); jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"epistemic_confidence\":%g", el_to_float(epist_v)); jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"hops\":%lld", (long long)(int64_t)hops_v); jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"promoted\":%d}", (int)(int64_t)promoted_v); jb_puts(&b, tmp); - } - } - jb_putc(&b, ']'); - return el_wrap_str(jb_finish(&b)); -} - -el_val_t engram_stats_json(void) { - EngramStore* g = engram_get(); - char buf[128]; - snprintf(buf, sizeof(buf), - "{\"node_count\":%lld,\"edge_count\":%lld,\"layer_count\":%zu}", - (long long)g->node_count, (long long)g->edge_count, g->layer_count); - return el_wrap_str(el_strdup(buf)); -} - -/* engram_list_layers_json — serialized counterpart of engram_list_layers. - * Returns a JSON array, sorted by activation_priority ascending. */ -el_val_t engram_list_layers_json(void) { - EngramStore* g = engram_get(); - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - /* Build a sorted index over live layers. */ - size_t* idx = malloc((g->layer_count + 1) * sizeof(size_t)); - if (!idx) { jb_putc(&b, ']'); return el_wrap_str(jb_finish(&b)); } - size_t live = 0; - for (size_t i = 0; i < g->layer_count; i++) { - if (g->layers[i].name) idx[live++] = i; - } - for (size_t i = 1; i < live; i++) { - size_t key = idx[i]; - uint32_t kp = g->layers[key].activation_priority; - size_t j = i; - while (j > 0 && g->layers[idx[j - 1]].activation_priority > kp) { - idx[j] = idx[j - 1]; - j--; - } - idx[j] = key; - } - int first = 1; - for (size_t i = 0; i < live; i++) { - EngramLayer* L = &g->layers[idx[i]]; - if (!first) jb_putc(&b, ','); - first = 0; - jb_putc(&b, '{'); - char tmp[80]; - snprintf(tmp, sizeof(tmp), "\"layer_id\":%u", L->layer_id); jb_puts(&b, tmp); - jb_puts(&b, ",\"name\":"); - jb_emit_escaped(&b, L->name ? L->name : ""); - snprintf(tmp, sizeof(tmp), ",\"activation_priority\":%u", L->activation_priority); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"suppressible\":%d", L->suppressible ? 1 : 0); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"transparent\":%d", L->transparent ? 1 : 0); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"injectable\":%d", L->injectable ? 1 : 0); - jb_puts(&b, tmp); - jb_putc(&b, '}'); - } - free(idx); - jb_putc(&b, ']'); - return el_wrap_str(jb_finish(&b)); -} - -/* engram_compile_layered_json — produce a prompt-ready context block split - * by layer. - * - * Runs the three-pass activation, then partitions promoted nodes by layer - * suppressibility: - * - Non-suppressible (Layer 0 / structural-floor) layers go FIRST under - * the heading "[LAYER 0 — STRUCTURAL]". These are the sacred-fire - * nodes that surfaced via the pass-3 override. - * - All other promoted layers go SECOND under "[ENGRAM CONTEXT]". - * - * Output is a single JSON-string el_val_t: a UTF-8 text block ready to be - * concatenated into a system prompt. Returns "" if no nodes promoted. - * - * Transparent layers (Layer 0) are emitted into the prompt — they shape - * the model's output — but engram_search and friends still hide them from - * introspection-style queries. The split heading lets the LLM weight them - * appropriately without revealing their internal label. - * - * Each emitted line for a node is its raw JSON (matching engram_emit_node_json) - * so downstream JSON parsers can still walk individual records inside the - * formatted block. The block is plain text, not a JSON document — callers - * concatenating it into a prompt should treat it as opaque markdown. */ -el_val_t engram_compile_layered_json(el_val_t intent, el_val_t depth) { - EngramStore* g = engram_get(); - /* Run the three-pass activator. We need the persisted node fields, so - * call engram_activate (it writes background_activation and - * working_memory_weight back into the store). */ - (void)engram_activate(intent, depth); - - /* Walk the store and partition by suppressibility. */ - JsonBuf b; jb_init(&b); - int wrote_layer0 = 0; - int wrote_normal = 0; - - /* Sort indices by working_memory_weight descending so the most - * confidently promoted nodes appear first within each section. */ - int64_t* idx = malloc((size_t)(g->node_count + 1) * sizeof(int64_t)); - if (!idx) return el_wrap_str(el_strdup("")); - int64_t mc = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].working_memory_weight > 0.0) idx[mc++] = i; - } - for (int64_t i = 1; i < mc; i++) { - int64_t key = idx[i]; - double kw = g->nodes[key].working_memory_weight; - int64_t j = i; - while (j > 0 && g->nodes[idx[j - 1]].working_memory_weight < kw) { - idx[j] = idx[j - 1]; - j--; - } - idx[j] = key; - } - - /* Section 1: structural floor (non-suppressible layers). */ - for (int64_t i = 0; i < mc; i++) { - EngramNode* n = &g->nodes[idx[i]]; - if (engram_layer_is_suppressible(n->layer_id)) continue; - if (!wrote_layer0) { - jb_puts(&b, "[LAYER 0 — STRUCTURAL]\n"); - wrote_layer0 = 1; - } - engram_emit_node_json(&b, n); - jb_putc(&b, '\n'); - } - - /* Section 2: standard engram context (suppressible layers). */ - for (int64_t i = 0; i < mc; i++) { - EngramNode* n = &g->nodes[idx[i]]; - if (!engram_layer_is_suppressible(n->layer_id)) continue; - if (!wrote_normal) { - if (wrote_layer0) jb_putc(&b, '\n'); - jb_puts(&b, "[ENGRAM CONTEXT]\n"); - wrote_normal = 1; - } - engram_emit_node_json(&b, n); - jb_putc(&b, '\n'); - } - - free(idx); - if (b.len == 0) { - free(b.buf); - return el_wrap_str(el_strdup("")); - } - return el_wrap_str(jb_finish(&b)); -} - -/* engram_query_range — temporal range query. - * Returns a JSON array of nodes whose created_at OR last_activated falls - * within [start_ms, end_ms], sorted by created_at ascending. - * Enables "what was I working on last Tuesday?" style queries by passing - * unix-millisecond timestamps for the start and end of the target interval. - * Both endpoints are inclusive. Pass 0 for start_ms to mean "beginning of - * time"; pass 0 for end_ms to mean "now". */ -el_val_t engram_query_range(el_val_t start_ms_v, el_val_t end_ms_v) { - EngramStore* g = engram_get(); - int64_t start_ms = (int64_t)start_ms_v; - int64_t end_ms = (int64_t)end_ms_v; - if (end_ms <= 0) end_ms = engram_now_ms(); - - /* Collect matching indices. */ - int64_t* idx = malloc((size_t)g->node_count * sizeof(int64_t)); - if (!idx) return el_wrap_str(el_strdup("[]")); - int64_t mc = 0; - for (int64_t i = 0; i < g->node_count; i++) { - EngramNode* n = &g->nodes[i]; - int in_created = (n->created_at >= start_ms && n->created_at <= end_ms); - int in_activated = (n->last_activated >= start_ms && n->last_activated <= end_ms); - if (in_created || in_activated) idx[mc++] = i; - } - /* Sort by created_at ascending (insertion sort — N is small in practice). */ - for (int64_t i = 1; i < mc; i++) { - int64_t key = idx[i]; - int64_t kts = g->nodes[key].created_at; - int64_t j = i - 1; - while (j >= 0 && g->nodes[idx[j]].created_at > kts) { - idx[j + 1] = idx[j]; - j--; - } - idx[j + 1] = key; - } - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - for (int64_t i = 0; i < mc; i++) { - if (i > 0) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[idx[i]]); - } - jb_putc(&b, ']'); - free(idx); - return el_wrap_str(jb_finish(&b)); -} - -/* engram_load_merge — like engram_load but WITHOUT resetting the store. - * Reads a JSON snapshot from `path` and adds any nodes/edges not already - * present in the in-memory graph. Dedup is by node id (for nodes) and by - * (from_id, to_id, relation) tuple (for edges). - * - * Returns (as an EL int) the count of new nodes added. Embeddings are - * intentionally skipped on merged nodes to avoid Ollama delays at runtime; - * auto_link_semantic will handle them when nodes are next activated. - * - * Does not merge layers — the in-process layer registry is authoritative. */ -el_val_t engram_load_merge(el_val_t path) { - const char* p = EL_CSTR(path); - if (!p || !*p) return 0; - FILE* f = fopen(p, "rb"); - if (!f) return 0; - fseek(f, 0, SEEK_END); - long sz = ftell(f); - rewind(f); - if (sz <= 0) { fclose(f); return 0; } - char* data = malloc((size_t)sz + 1); - if (!data) { fclose(f); return 0; } - size_t got = fread(data, 1, (size_t)sz, f); - fclose(f); - data[got] = '\0'; - - EngramStore* g = engram_get(); - int64_t added_nodes = 0; - - /* Walk nodes array — skip any node whose id already exists */ - const char* nodes_p = json_find_key(data, "nodes"); - if (nodes_p) { - nodes_p = eg_skip_ws(nodes_p); - if (*nodes_p == '[') { - nodes_p++; - nodes_p = eg_skip_ws(nodes_p); - while (*nodes_p && *nodes_p != ']') { - if (*nodes_p != '{') { nodes_p++; continue; } - const char* end = json_skip_value(nodes_p); - size_t n = (size_t)(end - nodes_p); - char* obj = malloc(n + 1); - memcpy(obj, nodes_p, n); obj[n] = '\0'; - char* nid = eg_get_str_field(obj, "id"); - int already = (nid && *nid && engram_find_node(nid) != NULL); - free(nid); - if (!already) { - engram_grow_nodes(); - EngramNode* nn = &g->nodes[g->node_count]; - memset(nn, 0, sizeof(*nn)); - nn->id = eg_get_str_field(obj, "id"); - nn->content = eg_get_str_field(obj, "content"); - nn->node_type = eg_get_str_field(obj, "node_type"); - nn->label = eg_get_str_field(obj, "label"); - nn->tier = eg_get_str_field(obj, "tier"); - nn->tags = eg_get_str_field(obj, "tags"); - nn->metadata = eg_get_str_field(obj, "metadata"); - if (!nn->metadata || !*nn->metadata) { free(nn->metadata); nn->metadata = strdup("{}"); } - nn->salience = eg_get_num_field(obj, "salience"); - nn->importance = eg_get_num_field(obj, "importance"); - nn->confidence = eg_get_num_field(obj, "confidence"); - nn->temporal_decay_rate = eg_get_num_field(obj, "temporal_decay_rate"); - nn->activation_count = eg_get_int_field(obj, "activation_count"); - nn->last_activated = eg_get_int_field(obj, "last_activated"); - nn->created_at = eg_get_int_field(obj, "created_at"); - nn->updated_at = eg_get_int_field(obj, "updated_at"); - nn->background_activation = eg_get_num_field(obj, "background_activation"); - nn->working_memory_weight = eg_get_num_field(obj, "working_memory_weight"); - if (!isfinite(nn->working_memory_weight) || nn->working_memory_weight < 0.0 || nn->working_memory_weight > 1.0) - nn->working_memory_weight = 0.0; /* clamp corrupt snapshot values */ - nn->suppression_count = (int32_t)eg_get_int_field(obj, "suppression_count"); - if (json_find_key(obj, "layer_id")) { - nn->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); - } else { - nn->layer_id = ENGRAM_LAYER_DEFAULT; - } - g->node_count++; - added_nodes++; - } - free(obj); - nodes_p = end; - nodes_p = eg_skip_ws(nodes_p); - if (*nodes_p == ',') { nodes_p++; nodes_p = eg_skip_ws(nodes_p); } - } - } - } - - /* Walk edges array — skip if (from_id, to_id, relation) already present */ - const char* edges_p = json_find_key(data, "edges"); - if (edges_p) { - edges_p = eg_skip_ws(edges_p); - if (*edges_p == '[') { - edges_p++; - edges_p = eg_skip_ws(edges_p); - while (*edges_p && *edges_p != ']') { - if (*edges_p != '{') { edges_p++; continue; } - const char* end = json_skip_value(edges_p); - size_t n = (size_t)(end - edges_p); - char* obj = malloc(n + 1); - memcpy(obj, edges_p, n); obj[n] = '\0'; - char* efrom = eg_get_str_field(obj, "from_id"); - char* eto = eg_get_str_field(obj, "to_id"); - char* erel = eg_get_str_field(obj, "relation"); - /* Check for duplicate by scanning existing edges */ - int dup = 0; - if (efrom && eto && erel) { - for (int64_t ei = 0; ei < g->edge_count; ei++) { - EngramEdge* ex = &g->edges[ei]; - if (ex->from_id && ex->to_id && ex->relation && - strcmp(ex->from_id, efrom) == 0 && - strcmp(ex->to_id, eto) == 0 && - strcmp(ex->relation, erel) == 0) { - dup = 1; break; - } - } - } - if (!dup) { - engram_grow_edges(); - EngramEdge* ee = &g->edges[g->edge_count]; - memset(ee, 0, sizeof(*ee)); - ee->id = eg_get_str_field(obj, "id"); - ee->from_id = efrom ? efrom : strdup(""); - ee->to_id = eto ? eto : strdup(""); - ee->relation = erel ? erel : strdup(""); - ee->metadata = eg_get_str_field(obj, "metadata"); - if (!ee->metadata || !*ee->metadata) { free(ee->metadata); ee->metadata = strdup("{}"); } - ee->weight = eg_get_num_field(obj, "weight"); - ee->confidence = eg_get_num_field(obj, "confidence"); - ee->created_at = eg_get_int_field(obj, "created_at"); - ee->updated_at = eg_get_int_field(obj, "updated_at"); - ee->last_fired = eg_get_int_field(obj, "last_fired"); - ee->inhibitory = (int)eg_get_int_field(obj, "inhibitory"); - if (json_find_key(obj, "layer_id")) { - ee->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); - } else { - ee->layer_id = ENGRAM_LAYER_DEFAULT; - } - g->edge_count++; - /* NOTE: efrom/eto/erel ownership transferred to ee above */ - efrom = NULL; eto = NULL; erel = NULL; - } else { - free(efrom); free(eto); free(erel); - } - free(obj); - edges_p = end; - edges_p = eg_skip_ws(edges_p); - if (*edges_p == ',') { edges_p++; edges_p = eg_skip_ws(edges_p); } - } - } - } - - /* Merged nodes can carry snapshot WM weights too — hold the cap here as - * well (see eg_enforce_wm_cap_global). */ - eg_enforce_wm_cap_global(g); - free(data); - return (el_val_t)added_nodes; -} - -el_val_t engram_wm_count(void) { - EngramStore* g = engram_get(); - int64_t count = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].working_memory_weight > 0.0) count++; - } - return (el_val_t)count; -} - -/* Average working_memory_weight across all promoted nodes (wm > 0). - * Returns the float bit-pattern via el_from_float so EL can use it with - * float_to_str / float_gt. Returns 0.0 when no nodes are promoted. - * Useful in heartbeat ISEs to distinguish "many weak activations" (sparse - * graph, low avg) from "few strong activations" (dense subgraph, high avg). - * Added 2026-06-04 self-review for graph health observability. */ -el_val_t engram_wm_avg_weight(void) { - EngramStore* g = engram_get(); - double sum = 0.0; - int64_t count = 0; - for (int64_t i = 0; i < g->node_count; i++) { - double w = g->nodes[i].working_memory_weight; - /* Defensive guard: skip any corrupt/out-of-range values so a single - * bad snapshot node doesn't produce a garbage average (e.g. 1.77e+234). */ - if (w > 0.0 && w <= 1.0 && isfinite(w)) { sum += w; count++; } - } - double avg = (count > 0) ? (sum / (double)count) : 0.0; - return el_from_float(avg); -} - -/* engram_wm_top_json — return top N working-memory nodes (by wm weight) as a - * compact JSON array for ISE heartbeat reporting. - * - * Each element: {"label":"...","node_type":"...","tier":"...","wm":0.42} - * - * Purpose: the heartbeat ISE reports wm_active (count) and wm_avg_weight but - * gives zero visibility into WM *composition* — which types/tiers are active. - * After long uptime every WM slot is in steady-state decay+re-promotion so - * wm_promotion ISEs never fire (they only fire on 0→>0.1 transitions). - * This function fills the observability gap by snapshotting the current top-N - * WM nodes on every heartbeat. Inserted 2026-06-05 self-review. */ -el_val_t engram_wm_top_json(el_val_t n_v) { - int64_t top_n = (int64_t)n_v; - if (top_n <= 0) top_n = 10; - if (top_n > 50) top_n = 50; - EngramStore* g = engram_get(); - - /* Collect indices of promoted nodes, excluding monitoring noise. - * InternalStateEvent nodes are system-observation artifacts — they reflect - * what the daemon is doing, not what it knows. Including them in wm_top - * buries real knowledge (Memory, Knowledge, Belief nodes) under a wall of - * heartbeat/curiosity ISEs, making the heartbeat ISE useless for diagnosing - * WM composition. Filter them out here so wm_top always shows substantive - * content. (2026-06-07 self-review) */ - int64_t* idx = malloc((size_t)(g->node_count + 1) * sizeof(int64_t)); - if (!idx) return el_wrap_str(el_strdup("[]")); - int64_t mc = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].working_memory_weight > 0.0) { - const char* nt = g->nodes[i].node_type; - if (nt && strcmp(nt, "InternalStateEvent") == 0) continue; - idx[mc++] = i; - } - } - - /* Insertion-sort descending by wm weight (mc is typically small). */ - for (int64_t i = 1; i < mc; i++) { - int64_t key = idx[i]; - double kw = g->nodes[key].working_memory_weight; - int64_t j = i; - while (j > 0 && g->nodes[idx[j-1]].working_memory_weight < kw) { - idx[j] = idx[j-1]; j--; - } - idx[j] = key; - } - - int64_t emit = mc < top_n ? mc : top_n; - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - for (int64_t k = 0; k < emit; k++) { - EngramNode* n = &g->nodes[idx[k]]; - if (k > 0) jb_putc(&b, ','); - jb_putc(&b, '{'); - jb_puts(&b, "\"label\":"); - jb_emit_escaped(&b, n->label ? n->label : ""); - jb_puts(&b, ",\"node_type\":"); - jb_emit_escaped(&b, n->node_type ? n->node_type : ""); - jb_puts(&b, ",\"tier\":"); - jb_emit_escaped(&b, n->tier ? n->tier : ""); - char tmp[48]; - snprintf(tmp, sizeof(tmp), ",\"wm\":%.3f", n->working_memory_weight); - jb_puts(&b, tmp); - jb_putc(&b, '}'); - } - free(idx); - jb_putc(&b, ']'); - return el_wrap_str(jb_finish(&b)); -} - -#ifdef HAVE_CURL -/* ── DHARMA network ───────────────────────────────────────────────────────── - * Real implementation. Peers are addressed by `dharma_id` — either bare - * (e.g. "ntn-genesis", transport defaults to http://localhost:7770) or - * "@" where is the peer's Engram-exposed daemon. - * - * Channels are logical handles cached per-cgi: `dharma_connect` is - * idempotent and returns "ch:". The channel registry below tracks - * every cgi_id we've connected to and its resolved transport URL. - * - * Relationship weights live in the local Engram graph: edges of type - * "dharma-relation" between a synthetic local node ("dharma:self") and - * synthetic peer nodes ("dharma:peer:"). Hebbian increments - * accumulate in EngramEdge.weight, clamped to [0.0, 1.0]. - * - * Events arrive over HTTP via the application's request handler, which is - * expected to call el_runtime_dharma_event_arrive() when it sees a - * /dharma/event POST. dharma_field() blocks on a per-event-type queue. - */ - -#define DHARMA_DEFAULT_URL "http://localhost:7770" - -/* Channel registry — one entry per known peer. */ -typedef struct DharmaChannel { - char* cgi_id; /* full dharma_id including any @ suffix */ - char* base_id; /* registry-id portion (before @) for relationship lookup */ - char* url; /* resolved transport URL */ - char* channel_id; /* "ch:" */ -} DharmaChannel; - -static DharmaChannel* _dharma_channels = NULL; -static size_t _dharma_channel_count = 0; -static size_t _dharma_channel_cap = 0; -static pthread_mutex_t _dharma_channel_mu = PTHREAD_MUTEX_INITIALIZER; - -/* Event queue — per-type linked list. dharma_field blocks on _dharma_event_cv. */ -typedef struct DharmaEvent { - char* event_type; - char* payload; - char* source; - int64_t timestamp; - struct DharmaEvent* next; -} DharmaEvent; - -static DharmaEvent* _dharma_event_head = NULL; -static DharmaEvent* _dharma_event_tail = NULL; -static pthread_mutex_t _dharma_event_mu = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t _dharma_event_cv = PTHREAD_COND_INITIALIZER; - -/* Split "@" → (base_id, url). If no "@", base_id = full, url = default. - * Returned strings are heap-allocated; caller must free. */ -static void dharma_parse_id(const char* full, char** out_base, char** out_url) { - if (!full) full = ""; - const char* at = strchr(full, '@'); - if (at) { - size_t bn = (size_t)(at - full); - char* b = malloc(bn + 1); - memcpy(b, full, bn); b[bn] = '\0'; - *out_base = b; - *out_url = el_strdup(at + 1); - if (!**out_url) { free(*out_url); *out_url = el_strdup(DHARMA_DEFAULT_URL); } - } else { - *out_base = el_strdup(full); - *out_url = el_strdup(DHARMA_DEFAULT_URL); - } -} - -/* Find existing channel by full cgi_id. Caller must hold _dharma_channel_mu. */ -static DharmaChannel* dharma_find_channel_locked(const char* cgi_id) { - if (!cgi_id) return NULL; - for (size_t i = 0; i < _dharma_channel_count; i++) { - if (_dharma_channels[i].cgi_id && - strcmp(_dharma_channels[i].cgi_id, cgi_id) == 0) { - return &_dharma_channels[i]; - } - } - return NULL; -} - -/* Add a new channel entry. Caller must hold _dharma_channel_mu. */ -static DharmaChannel* dharma_add_channel_locked(const char* cgi_id) { - if (_dharma_channel_count >= _dharma_channel_cap) { - size_t nc = _dharma_channel_cap ? _dharma_channel_cap * 2 : 8; - _dharma_channels = realloc(_dharma_channels, nc * sizeof(DharmaChannel)); - if (!_dharma_channels) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(_dharma_channels + _dharma_channel_cap, 0, - (nc - _dharma_channel_cap) * sizeof(DharmaChannel)); - _dharma_channel_cap = nc; - } - DharmaChannel* ch = &_dharma_channels[_dharma_channel_count++]; - char* base = NULL; char* url = NULL; - dharma_parse_id(cgi_id, &base, &url); - ch->cgi_id = el_strdup(cgi_id ? cgi_id : ""); - ch->base_id = base; - ch->url = url; - size_t cn = strlen(ch->cgi_id) + 4; - ch->channel_id = malloc(cn); - snprintf(ch->channel_id, cn, "ch:%s", ch->cgi_id); - return ch; -} - -el_val_t dharma_connect(el_val_t cgi_id) { - const char* id = EL_CSTR(cgi_id); - if (!id || !*id) return el_wrap_str(el_strdup("")); - pthread_mutex_lock(&_dharma_channel_mu); - DharmaChannel* ch = dharma_find_channel_locked(id); - if (!ch) ch = dharma_add_channel_locked(id); - char* out = el_strdup(ch->channel_id); - pthread_mutex_unlock(&_dharma_channel_mu); - return el_wrap_str(out); -} - -/* Build an error JSON body — same shape http_error_json uses. */ -static el_val_t dharma_error_json(const char* msg) { - return http_error_json(msg); -} - -el_val_t dharma_send(el_val_t channel, el_val_t content) { - const char* ch_id = EL_CSTR(channel); - const char* msg = EL_CSTR(content); - if (!ch_id || strncmp(ch_id, "ch:", 3) != 0) { - return dharma_error_json("invalid channel"); - } - const char* peer_id = ch_id + 3; - /* Look up channel; if unknown (caller fabricated), auto-register. */ - pthread_mutex_lock(&_dharma_channel_mu); - DharmaChannel* ch = dharma_find_channel_locked(peer_id); - if (!ch) ch = dharma_add_channel_locked(peer_id); - char* url = el_strdup(ch->url); - pthread_mutex_unlock(&_dharma_channel_mu); - /* Build /dharma/recv body. */ - const char* from = _el_cgi_dharma_id ? _el_cgi_dharma_id : "(unknown)"; - char* esc_ch = json_escape_alloc(ch_id); - char* esc_from = json_escape_alloc(from); - char* esc_msg = json_escape_alloc(msg ? msg : ""); - JsonBuf b; jb_init(&b); - jb_puts(&b, "{\"channel\":\""); jb_puts(&b, esc_ch); - jb_puts(&b, "\",\"from\":\""); jb_puts(&b, esc_from); - jb_puts(&b, "\",\"content\":\""); jb_puts(&b, esc_msg); - jb_puts(&b, "\"}"); - free(esc_ch); free(esc_from); free(esc_msg); - size_t ul = strlen(url) + 16; - char* full_url = malloc(ul); - snprintf(full_url, ul, "%s/dharma/recv", url); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - el_val_t resp = http_do("POST", full_url, b.buf, h); - curl_slist_free_all(h); - free(b.buf); free(full_url); free(url); - return resp; -} - -el_val_t dharma_activate(el_val_t query) { - const char* q = EL_CSTR(query); - if (!q) q = ""; - el_val_t out = el_list_empty(); - char* esc_q = json_escape_alloc(q); - JsonBuf body; jb_init(&body); - jb_puts(&body, "{\"query\":\""); jb_puts(&body, esc_q); jb_puts(&body, "\"}"); - free(esc_q); - - /* Snapshot the channel list under lock so we can iterate without - * holding the mutex during network I/O. */ - pthread_mutex_lock(&_dharma_channel_mu); - size_t n = _dharma_channel_count; - char** urls = calloc(n ? n : 1, sizeof(char*)); - char** ids = calloc(n ? n : 1, sizeof(char*)); - char** bases = calloc(n ? n : 1, sizeof(char*)); - for (size_t i = 0; i < n; i++) { - urls[i] = el_strdup(_dharma_channels[i].url); - ids[i] = el_strdup(_dharma_channels[i].cgi_id); - bases[i] = el_strdup(_dharma_channels[i].base_id); - } - pthread_mutex_unlock(&_dharma_channel_mu); - - for (size_t i = 0; i < n; i++) { - size_t ul = strlen(urls[i]) + 32; - char* full_url = malloc(ul); - snprintf(full_url, ul, "%s/api/activate", urls[i]); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - el_val_t resp = http_do("POST", full_url, body.buf, h); - curl_slist_free_all(h); - free(full_url); - const char* rs = EL_CSTR(resp); - if (!rs || !*rs) continue; - if (rs[0] == '{' && strstr(rs, "\"error\"")) continue; - - /* Look up relationship weight (attenuation). */ - double rel_weight = 1.0; - { - const char* self_id = "dharma:self"; - char peer_node[512]; - snprintf(peer_node, sizeof(peer_node), "dharma:peer:%s", bases[i]); - EngramStore* g = engram_get(); - for (int64_t k = 0; k < g->edge_count; k++) { - EngramEdge* e = &g->edges[k]; - if (e->from_id && e->to_id && - strcmp(e->from_id, self_id) == 0 && - strcmp(e->to_id, peer_node) == 0 && - e->relation && strcmp(e->relation, "dharma-relation") == 0) { - rel_weight = e->weight; - break; - } - } - } - - /* Iterate the response array. Expect either a top-level array - * or an object whose "results" field is an array. */ - const char* arr = rs; - while (*arr == ' ' || *arr == '\t' || *arr == '\n' || *arr == '\r') arr++; - char* arr_owned = NULL; - if (*arr == '{') { - el_val_t r = json_get_raw(EL_STR(rs), EL_STR("results")); - const char* rr = EL_CSTR(r); - if (rr && *rr == '[') { - arr_owned = el_strdup(rr); - arr = arr_owned; - } else { - continue; - } - } - if (*arr != '[') { free(arr_owned); continue; } - const char* p = arr + 1; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - while (*p && *p != ']') { - const char* end = json_skip_value(p); - size_t en = (size_t)(end - p); - char* obj = el_strbuf(en); - memcpy(obj, p, en); obj[en] = '\0'; - - /* Pull activation_strength if present, else 1.0. */ - el_val_t act_v = json_get_float(EL_STR(obj), EL_STR("activation_strength")); - double act = el_to_float(act_v); - if (!(act > 0.0 && act <= 100.0)) act = 1.0; - double final_act = act * rel_weight; - - el_val_t entry = el_map_new(0); - /* node = the inner JSON if present, else the entire obj. */ - el_val_t node_raw = json_get_raw(EL_STR(obj), EL_STR("node")); - const char* nr = EL_CSTR(node_raw); - entry = el_map_set(entry, EL_STR(el_strdup("node")), - (nr && *nr) ? node_raw : EL_STR(el_strdup(obj))); - entry = el_map_set(entry, EL_STR(el_strdup("source_cgi")), - EL_STR(el_strdup(ids[i]))); - entry = el_map_set(entry, EL_STR(el_strdup("activation_strength")), - el_from_float(final_act)); - out = el_list_append(out, entry); - free(obj); - p = end; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - } - free(arr_owned); - } - for (size_t i = 0; i < n; i++) { free(urls[i]); free(ids[i]); free(bases[i]); } - free(urls); free(ids); free(bases); - free(body.buf); - return out; -} - -void dharma_emit(el_val_t event_type, el_val_t payload) { - const char* et = EL_CSTR(event_type); - const char* pay = EL_CSTR(payload); - if (!et) et = ""; - if (!pay) pay = ""; - const char* src = _el_cgi_dharma_id ? _el_cgi_dharma_id : "(unknown)"; - int64_t ts = engram_now_ms(); - - char* esc_et = json_escape_alloc(et); - char* esc_pay = json_escape_alloc(pay); - char* esc_src = json_escape_alloc(src); - JsonBuf b; jb_init(&b); - jb_puts(&b, "{\"type\":\""); jb_puts(&b, esc_et); - jb_puts(&b, "\",\"payload\":\""); jb_puts(&b, esc_pay); - jb_puts(&b, "\",\"source\":\""); jb_puts(&b, esc_src); - jb_puts(&b, "\",\"timestamp\":"); jb_emit_int(&b, ts); - jb_putc(&b, '}'); - free(esc_et); free(esc_pay); free(esc_src); - - /* Snapshot URLs to avoid holding the channel mutex during I/O. */ - pthread_mutex_lock(&_dharma_channel_mu); - size_t n = _dharma_channel_count; - char** urls = calloc(n ? n : 1, sizeof(char*)); - for (size_t i = 0; i < n; i++) urls[i] = el_strdup(_dharma_channels[i].url); - pthread_mutex_unlock(&_dharma_channel_mu); - - for (size_t i = 0; i < n; i++) { - size_t ul = strlen(urls[i]) + 32; - char* full_url = malloc(ul); - snprintf(full_url, ul, "%s/dharma/event", urls[i]); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - el_val_t r = http_do("POST", full_url, b.buf, h); - (void)r; /* fire-and-forget — emit is not synchronous */ - curl_slist_free_all(h); - free(full_url); - } - for (size_t i = 0; i < n; i++) free(urls[i]); - free(urls); - free(b.buf); -} - -void el_runtime_dharma_event_arrive(const char* event_type, const char* payload, - const char* source) { - DharmaEvent* ev = calloc(1, sizeof(DharmaEvent)); - if (!ev) return; - ev->event_type = el_strdup(event_type ? event_type : ""); - ev->payload = el_strdup(payload ? payload : ""); - ev->source = el_strdup(source ? source : ""); - ev->timestamp = engram_now_ms(); - ev->next = NULL; - pthread_mutex_lock(&_dharma_event_mu); - if (_dharma_event_tail) _dharma_event_tail->next = ev; - else _dharma_event_head = ev; - _dharma_event_tail = ev; - pthread_cond_broadcast(&_dharma_event_cv); - pthread_mutex_unlock(&_dharma_event_mu); -} - -el_val_t dharma_field(el_val_t event_type) { - const char* et = EL_CSTR(event_type); - if (!et) et = ""; - - /* Compute deadline: now + 30 seconds. */ - struct timespec deadline; - clock_gettime(CLOCK_REALTIME, &deadline); - deadline.tv_sec += 30; - - DharmaEvent* found = NULL; - pthread_mutex_lock(&_dharma_event_mu); - while (1) { - /* Scan queue for matching type; pop and return first match. */ - DharmaEvent* prev = NULL; - DharmaEvent* cur = _dharma_event_head; - while (cur) { - if (cur->event_type && strcmp(cur->event_type, et) == 0) { - if (prev) prev->next = cur->next; - else _dharma_event_head = cur->next; - if (_dharma_event_tail == cur) _dharma_event_tail = prev; - cur->next = NULL; - found = cur; - break; - } - prev = cur; cur = cur->next; - } - if (found) break; - int rc = pthread_cond_timedwait(&_dharma_event_cv, &_dharma_event_mu, &deadline); - if (rc == ETIMEDOUT) break; - } - pthread_mutex_unlock(&_dharma_event_mu); - - if (!found) return el_map_new(0); - el_val_t m = el_map_new(0); - m = el_map_set(m, EL_STR(el_strdup("type")), - EL_STR(el_strdup(found->event_type ? found->event_type : ""))); - m = el_map_set(m, EL_STR(el_strdup("payload")), - EL_STR(el_strdup(found->payload ? found->payload : ""))); - m = el_map_set(m, EL_STR(el_strdup("source_cgi")), - EL_STR(el_strdup(found->source ? found->source : ""))); - m = el_map_set(m, EL_STR(el_strdup("timestamp")), (el_val_t)found->timestamp); - free(found->event_type); free(found->payload); free(found->source); free(found); - return m; -} - -/* Locate (or create) the local "dharma:self" node and the synthetic peer - * node "dharma:peer:". Returns the index of the dharma-relation - * edge, or -1 if not found. If `create` is non-zero, ensure the nodes - * and edge exist (creating them as needed) and return the edge index. */ -static int64_t dharma_find_or_create_relation_edge(const char* peer_base, int create) { - if (!peer_base || !*peer_base) return -1; - EngramStore* g = engram_get(); - const char* self_id = "dharma:self"; - char peer_node[512]; - snprintf(peer_node, sizeof(peer_node), "dharma:peer:%s", peer_base); - - /* Look for the edge first. */ - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - if (e->from_id && e->to_id && - strcmp(e->from_id, self_id) == 0 && - strcmp(e->to_id, peer_node) == 0 && - e->relation && strcmp(e->relation, "dharma-relation") == 0) { - return i; - } - } - if (!create) return -1; - - /* Ensure self node exists. We use a fixed id (not engram_new_id) so - * subsequent calls reuse the same one. */ - if (!engram_find_node(self_id)) { - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = el_strdup_persist(self_id); - n->content = el_strdup_persist(_el_cgi_dharma_id ? _el_cgi_dharma_id : "(self)"); - n->node_type = el_strdup_persist("DharmaSelf"); - n->label = el_strdup_persist("dharma:self"); - n->tier = el_strdup_persist("Working"); - n->tags = el_strdup_persist("dharma"); - n->metadata = el_strdup_persist("{}"); - n->salience = 1.0; n->importance = 1.0; n->confidence = 1.0; - int64_t now = engram_now_ms(); - n->created_at = now; n->updated_at = now; n->last_activated = now; - n->layer_id = ENGRAM_LAYER_DEFAULT; - g->node_count++; - } - if (!engram_find_node(peer_node)) { - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = el_strdup_persist(peer_node); - n->content = el_strdup_persist(peer_base); - n->node_type = el_strdup_persist("DharmaPeer"); - n->label = el_strdup_persist(peer_node); - n->tier = el_strdup_persist("Working"); - n->tags = el_strdup_persist("dharma"); - n->metadata = el_strdup_persist("{}"); - n->salience = 0.5; n->importance = 0.5; n->confidence = 1.0; - int64_t now = engram_now_ms(); - n->created_at = now; n->updated_at = now; n->last_activated = now; - n->layer_id = ENGRAM_LAYER_DEFAULT; - g->node_count++; - } - /* Create the edge with weight 0.0 — caller will increment. */ - engram_grow_edges(); - EngramEdge* e = &g->edges[g->edge_count]; - memset(e, 0, sizeof(*e)); - e->id = engram_new_id(); - e->from_id = el_strdup_persist(self_id); - e->to_id = el_strdup_persist(peer_node); - e->relation = el_strdup_persist("dharma-relation"); - e->metadata = el_strdup_persist("{}"); - e->weight = 0.0; - e->confidence = 1.0; - int64_t now = engram_now_ms(); - e->created_at = now; e->updated_at = now; - e->layer_id = ENGRAM_LAYER_DEFAULT; - int64_t idx = g->edge_count; - g->edge_count++; - return idx; -} - -void dharma_strengthen(el_val_t cgi_id, el_val_t weight) { - const char* id = EL_CSTR(cgi_id); - if (!id || !*id) return; - char* base = NULL; char* url = NULL; - dharma_parse_id(id, &base, &url); - free(url); - int64_t ei = dharma_find_or_create_relation_edge(base, 1); - free(base); - if (ei < 0) return; - EngramStore* g = engram_get(); - double inc = engram_decode_score(weight); - if (!(inc >= 0.0)) inc = 0.0; - double w = g->edges[ei].weight + inc; - if (w < 0.0) w = 0.0; - if (w > 1.0) w = 1.0; - g->edges[ei].weight = w; - g->edges[ei].updated_at = engram_now_ms(); - g->edges[ei].last_fired = g->edges[ei].updated_at; -} - -el_val_t dharma_relationship(el_val_t cgi_id) { - const char* id = EL_CSTR(cgi_id); - if (!id || !*id) return el_from_float(0.0); - char* base = NULL; char* url = NULL; - dharma_parse_id(id, &base, &url); - free(url); - int64_t ei = dharma_find_or_create_relation_edge(base, 0); - free(base); - if (ei < 0) return el_from_float(0.0); - EngramStore* g = engram_get(); - return el_from_float(g->edges[ei].weight); -} - -el_val_t dharma_peers(void) { - /* Walk dharma-relation edges out of "dharma:self", weight > 0, sort desc. */ - EngramStore* g = engram_get(); - const char* self_id = "dharma:self"; - typedef struct { char* peer_base; double weight; } PeerEntry; - PeerEntry* peers = malloc((size_t)(g->edge_count + 1) * sizeof(PeerEntry)); - int64_t pcount = 0; - if (!peers) return el_list_empty(); - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - if (!e->from_id || !e->to_id) continue; - if (strcmp(e->from_id, self_id) != 0) continue; - if (!e->relation || strcmp(e->relation, "dharma-relation") != 0) continue; - if (e->weight <= 0.0) continue; - const char* prefix = "dharma:peer:"; - size_t pl = strlen(prefix); - if (strncmp(e->to_id, prefix, pl) != 0) continue; - peers[pcount].peer_base = el_strdup(e->to_id + pl); - peers[pcount].weight = e->weight; - pcount++; - } - /* Sort desc by weight. */ - for (int64_t i = 1; i < pcount; i++) { - PeerEntry key = peers[i]; - int64_t j = i - 1; - while (j >= 0 && peers[j].weight < key.weight) { - peers[j + 1] = peers[j]; j--; - } - peers[j + 1] = key; - } - el_val_t out = el_list_empty(); - for (int64_t i = 0; i < pcount; i++) { - out = el_list_append(out, EL_STR(peers[i].peer_base)); - } - free(peers); - return out; -} -#endif /* HAVE_CURL — DHARMA network */ - -/* ── Batch 4: LLM (Anthropic API client) ─────────────────────────────────── */ -/* - * All LLM builtins call https://api.anthropic.com/v1/messages with the API - * key from env ANTHROPIC_API_KEY. Default model is "claude-sonnet-4-5" - * when the supplied model is empty/null. - * - * `llm_call_agentic` runs a real multi-turn tool_use/tool_result loop. - * Tool handlers are registered with `llm_register_tool(name, fn_name)`, - * which dlsym()s the named symbol. Each tool handler has the C signature - * el_val_t handler(el_val_t input_json); - * and returns a JSON-string el_val_t result. Iteration is capped at 10. - */ - -#ifdef HAVE_CURL -static const char* LLM_DEFAULT_MODEL = "claude-sonnet-4-5"; -static const char* LLM_API_URL = "https://api.anthropic.com/v1/messages"; -static const char* LLM_VERSION = "2023-06-01"; - -static const char* llm_resolve_model(const char* m) { - if (!m || !*m) return LLM_DEFAULT_MODEL; - return m; -} - -/* - * ── Configurable LLM provider chain ────────────────────────────────────────── - * - * Providers are configured via indexed env vars. The runtime tries each in - * order (0, 1, 2, ...) and returns the first successful non-empty response. - * - * Per provider (N = 0, 1, 2, ...): - * NEURON_LLM_N_URL — endpoint URL (base URL; /v1/chat/completions appended - * if format is "openai" and not already in URL) - * NEURON_LLM_N_KEY — API key - * NEURON_LLM_N_FORMAT — "openai" (default) or "anthropic" - * NEURON_LLM_N_MODEL — model name override (optional) - * - * Example — Neuron inference primary, Anthropic fallback: - * NEURON_LLM_0_URL=https://soma.../v1/chat/completions - * NEURON_LLM_0_KEY=svc-key - * NEURON_LLM_0_FORMAT=openai - * NEURON_LLM_0_MODEL=neuron - * NEURON_LLM_1_URL=https://api.anthropic.com/v1/messages - * NEURON_LLM_1_KEY=sk-ant-... - * NEURON_LLM_1_FORMAT=anthropic - * - * If no NEURON_LLM_0_URL is set, falls back to legacy ANTHROPIC_API_KEY. - */ - -#define LLM_MAX_PROVIDERS 16 - -/* forward declarations */ -static el_val_t llm_extract_text(el_val_t resp_val); -static el_val_t llm_extract_text_openai(el_val_t resp_val); - -static el_val_t llm_extract_text_openai(el_val_t resp_val) { - const char* resp = EL_CSTR(resp_val); - if (!resp || !*resp) return el_wrap_str(el_strdup("")); - if (resp[0] == '{' && strstr(resp, "\"error\"")) return el_wrap_str(el_strdup("")); - const char* choices = json_find_key(resp, "choices"); - if (!choices || *choices != '[') return el_wrap_str(el_strdup("")); - choices++; - while (*choices == ' ' || *choices == '\t') choices++; - if (*choices != '{') return el_wrap_str(el_strdup("")); - const char* end = json_skip_value(choices); - size_t n = (size_t)(end - choices); - char* obj = malloc(n + 1); memcpy(obj, choices, n); obj[n] = '\0'; - const char* msg = json_find_key(obj, "message"); - if (!msg || *msg != '{') { free(obj); return el_wrap_str(el_strdup("")); } - const char* msg_end = json_skip_value(msg); - size_t mn = (size_t)(msg_end - msg); - char* msg_obj = malloc(mn + 1); memcpy(msg_obj, msg, mn); msg_obj[mn] = '\0'; - const char* content = json_find_key(msg_obj, "content"); - el_val_t result = el_wrap_str(el_strdup("")); - if (content && *content == '"') { - JsonParser jp = { .p = content, .end = content + strlen(content), .err = 0 }; - char* text = jp_parse_string_raw(&jp); - if (!jp.err && text) result = el_wrap_str(text); - } - free(msg_obj); free(obj); - return result; -} - -/* Send a request to one provider. Returns the raw response string. - * format: 0 = openai, 1 = anthropic */ -static el_val_t llm_provider_request(const char* url, const char* key, - int format, const char* model, - const char* system_str, - const char* user_str) { - char* esc_sys = system_str && *system_str ? json_escape_alloc(system_str) : NULL; - char* esc_user = json_escape_alloc(user_str ? user_str : ""); - JsonBuf b; jb_init(&b); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - - if (format == 0) { /* OpenAI */ - char full_url[1024]; - if (strstr(url, "/chat/completions") || strstr(url, "/messages")) { - snprintf(full_url, sizeof(full_url), "%s", url); - } else { - snprintf(full_url, sizeof(full_url), "%s/v1/chat/completions", url); - } - { size_t n = strlen(key)+24; char* l=malloc(n); snprintf(l,n,"Authorization: Bearer %s",key); h=curl_slist_append(h,l); free(l); } - jb_putc(&b, '{'); - jb_puts(&b, "\"model\":"); jb_emit_escaped(&b, model ? model : "neuron"); - jb_puts(&b, ",\"max_tokens\":4096,\"messages\":["); - if (esc_sys && *esc_sys) { jb_puts(&b,"{\"role\":\"system\",\"content\":\""); jb_puts(&b,esc_sys); jb_puts(&b,"\"},"); } - jb_puts(&b, "{\"role\":\"user\",\"content\":\""); jb_puts(&b, esc_user); jb_puts(&b, "\"}]}"); - el_val_t resp = http_do("POST", full_url, b.buf, h); - curl_slist_free_all(h); free(b.buf); - if (esc_sys) free(esc_sys); free(esc_user); - return llm_extract_text_openai(resp); - } else { /* Anthropic */ - { size_t n = strlen(key)+16; char* l=malloc(n); snprintf(l,n,"x-api-key: %s",key); h=curl_slist_append(h,l); free(l); } - { size_t n = strlen(LLM_VERSION)+32; char* l=malloc(n); snprintf(l,n,"anthropic-version: %s",LLM_VERSION); h=curl_slist_append(h,l); free(l); } - jb_putc(&b, '{'); - jb_puts(&b, "\"model\":"); jb_emit_escaped(&b, model ? model : LLM_DEFAULT_MODEL); - jb_puts(&b, ",\"max_tokens\":4096"); - if (esc_sys && *esc_sys) { jb_puts(&b,",\"system\":\""); jb_puts(&b,esc_sys); jb_puts(&b,"\""); } - jb_puts(&b, ",\"messages\":[{\"role\":\"user\",\"content\":\""); jb_puts(&b, esc_user); jb_puts(&b, "\"}]}"); - el_val_t resp = http_do("POST", url, b.buf, h); - curl_slist_free_all(h); free(b.buf); - if (esc_sys) free(esc_sys); free(esc_user); - return llm_extract_text(resp); - } -} - -static el_val_t llm_chain_call(const char* model_pref, const char* system_str, const char* user_str) { - char url_key[64], key_key[64], fmt_key[64], model_key[64]; - for (int i = 0; i < LLM_MAX_PROVIDERS; i++) { - snprintf(url_key, sizeof(url_key), "NEURON_LLM_%d_URL", i); - snprintf(key_key, sizeof(key_key), "NEURON_LLM_%d_KEY", i); - snprintf(fmt_key, sizeof(fmt_key), "NEURON_LLM_%d_FORMAT", i); - snprintf(model_key, sizeof(model_key), "NEURON_LLM_%d_MODEL", i); - const char* url = getenv(url_key); - const char* key = getenv(key_key); - if (!url || !*url || !key || !*key) break; /* end of chain */ - const char* fmt_s = getenv(fmt_key); - int fmt = (fmt_s && strcmp(fmt_s, "anthropic") == 0) ? 1 : 0; - const char* model = getenv(model_key); - if (!model || !*model) model = model_pref; /* fall back to the caller-requested model */ - fprintf(stderr, "[llm] trying provider %d (%s)\n", i, url); - el_val_t result = llm_provider_request(url, key, fmt, model, system_str, user_str); - const char* t = EL_CSTR(result); - if (t && *t && t[0] != '{') return result; /* success */ - fprintf(stderr, "[llm] provider %d failed or empty, trying next\n", i); - } - /* Legacy fallback: ANTHROPIC_API_KEY */ - const char* api_key = getenv("ANTHROPIC_API_KEY"); - if (!api_key || !*api_key) return http_error_json("no LLM providers configured"); - fprintf(stderr, "[llm] using legacy ANTHROPIC_API_KEY fallback\n"); - return llm_provider_request(LLM_API_URL, api_key, 1, model_pref, system_str, user_str); -} - -/* Legacy llm_request — kept for backward compat with agentic loop internals */ -static el_val_t llm_request(const char* json_body) { - const char* api_key = getenv("ANTHROPIC_API_KEY"); - if (!api_key || !*api_key) return http_error_json("ANTHROPIC_API_KEY not set"); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - { size_t n=strlen(api_key)+16; char* l=malloc(n); snprintf(l,n,"x-api-key: %s",api_key); h=curl_slist_append(h,l); free(l); } - { size_t n=strlen(LLM_VERSION)+32; char* l=malloc(n); snprintf(l,n,"anthropic-version: %s",LLM_VERSION); h=curl_slist_append(h,l); free(l); } - el_val_t resp = http_do("POST", LLM_API_URL, json_body, h); - curl_slist_free_all(h); - return resp; -} - -/* Extract concatenated assistant text from an Anthropic /v1/messages - * response. The response shape is: - * {"content":[{"type":"text","text":"..."}, ...], ...} - * If parsing fails, returns the raw response so the caller can inspect. - */ -static el_val_t llm_extract_text(el_val_t resp_val) { - const char* resp = EL_CSTR(resp_val); - if (!resp || !*resp) return el_wrap_str(el_strdup("")); - /* If error JSON, propagate as-is. */ - if (resp[0] == '{' && strstr(resp, "\"error\"")) { - return el_wrap_str(el_strdup(resp)); - } - /* Find "content":[ ... ] */ - const char* p = json_find_key(resp, "content"); - if (!p) return el_wrap_str(el_strdup(resp)); - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') return el_wrap_str(el_strdup(resp)); - p++; - JsonBuf out; jb_init(&out); - while (*p && *p != ']') { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p != '{') break; - const char* end = json_skip_value(p); - size_t n = (size_t)(end - p); - char* obj = malloc(n + 1); - memcpy(obj, p, n); obj[n] = '\0'; - const char* type_p = json_find_key(obj, "type"); - if (type_p && *type_p == '"') { - JsonParser jp = { .p = type_p, .end = type_p + strlen(type_p), .err = 0 }; - char* type_s = jp_parse_string_raw(&jp); - if (!jp.err && type_s && strcmp(type_s, "text") == 0) { - const char* tp = json_find_key(obj, "text"); - if (tp && *tp == '"') { - JsonParser jp2 = { .p = tp, .end = tp + strlen(tp), .err = 0 }; - char* text_s = jp_parse_string_raw(&jp2); - if (!jp2.err && text_s) jb_puts(&out, text_s); - free(text_s); - } - } - free(type_s); - } - free(obj); - p = end; - } - return el_wrap_str(jb_finish(&out)); -} - -el_val_t llm_call(el_val_t model, el_val_t prompt) { - const char* m = EL_CSTR(model); - const char* u = EL_CSTR(prompt); if (!u) u = ""; - return llm_chain_call(m, NULL, u); -} - -el_val_t llm_call_system(el_val_t model, el_val_t system_prompt, el_val_t user_prompt) { - const char* m = EL_CSTR(model); - const char* s = EL_CSTR(system_prompt); if (!s) s = ""; - const char* u = EL_CSTR(user_prompt); if (!u) u = ""; - return llm_chain_call(m, s, u); -} - -/* ── Tool registry for llm_call_agentic ─────────────────────────────────── */ - -typedef el_val_t (*llm_tool_fn)(el_val_t input); - -typedef struct LlmToolEntry { - char* name; - llm_tool_fn fn; -} LlmToolEntry; - -static LlmToolEntry _llm_tools[64]; -static size_t _llm_tool_count = 0; -static pthread_mutex_t _llm_tool_mu = PTHREAD_MUTEX_INITIALIZER; - -static llm_tool_fn llm_tool_lookup(const char* name) { - if (!name) return NULL; - llm_tool_fn fn = NULL; - pthread_mutex_lock(&_llm_tool_mu); - for (size_t i = 0; i < _llm_tool_count; i++) { - if (strcmp(_llm_tools[i].name, name) == 0) { fn = _llm_tools[i].fn; break; } - } - pthread_mutex_unlock(&_llm_tool_mu); - return fn; -} - -void llm_register_tool(el_val_t name, el_val_t handler_fn_name) { - const char* nm = EL_CSTR(name); - const char* sym = EL_CSTR(handler_fn_name); - if (!nm || !*nm || !sym || !*sym) return; - void* p = dlsym(RTLD_DEFAULT, sym); - if (!p) { - fprintf(stderr, "[llm_register_tool] symbol not found: %s\n", sym); - return; - } - pthread_mutex_lock(&_llm_tool_mu); - /* Replace existing entry by name. */ - for (size_t i = 0; i < _llm_tool_count; i++) { - if (strcmp(_llm_tools[i].name, nm) == 0) { - _llm_tools[i].fn = (llm_tool_fn)p; - pthread_mutex_unlock(&_llm_tool_mu); - return; - } - } - if (_llm_tool_count < sizeof(_llm_tools) / sizeof(_llm_tools[0])) { - _llm_tools[_llm_tool_count].name = el_strdup(nm); - _llm_tools[_llm_tool_count].fn = (llm_tool_fn)p; - _llm_tool_count++; - } - pthread_mutex_unlock(&_llm_tool_mu); -} - -/* Serialize the El `tools` list into the JSON `tools:[...]` field expected - * by the Anthropic API. Each tool is an ElMap with name/description/ - * input_schema. input_schema is treated as either a JSON-object string - * (passed through verbatim) or a missing field (substitute {}). */ -static void llm_emit_tools_json(JsonBuf* b, el_val_t tools_list) { - jb_putc(b, '['); - ElList* lst = (ElList*)(uintptr_t)tools_list; - int64_t n = lst ? lst->length : 0; - for (int64_t i = 0; i < n; i++) { - if (i > 0) jb_putc(b, ','); - ElMap* tm = as_map(lst->elems[i]); - const char* name = ""; - const char* desc = ""; - const char* schema = "{}"; - if (tm) { - for (int64_t k = 0; k < tm->count; k++) { - const char* key = EL_CSTR(tm->keys[k]); - const char* val = EL_CSTR(tm->values[k]); - if (!key || !val) continue; - if (strcmp(key, "name") == 0) name = val; - else if (strcmp(key, "description") == 0) desc = val; - else if (strcmp(key, "input_schema") == 0) schema = val; - } - } - char* esc_name = json_escape_alloc(name); - char* esc_desc = json_escape_alloc(desc); - jb_puts(b, "{\"name\":\""); jb_puts(b, esc_name); - jb_puts(b, "\",\"description\":\""); jb_puts(b, esc_desc); - jb_puts(b, "\",\"input_schema\":"); jb_puts(b, schema && *schema ? schema : "{}"); - jb_putc(b, '}'); - free(esc_name); free(esc_desc); - } - jb_putc(b, ']'); -} - -/* Walk the assistant `content` array and emit each block back into b, - * preserving the verbatim JSON of every block — used to re-include the - * assistant turn in the next request. */ -static void llm_emit_content_blocks(JsonBuf* b, const char* resp) { - const char* p = json_find_key(resp, "content"); - jb_putc(b, '['); - if (!p) { jb_putc(b, ']'); return; } - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') { jb_putc(b, ']'); return; } - p++; - int first = 1; - while (*p && *p != ']') { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p != '{') break; - const char* end = json_skip_value(p); - if (!first) jb_putc(b, ','); - first = 0; - size_t n = (size_t)(end - p); - jb_reserve(b, n); - memcpy(b->buf + b->len, p, n); - b->len += n; - b->buf[b->len] = '\0'; - p = end; - } - jb_putc(b, ']'); -} - -/* Concatenate all "text" blocks from a response. Returns owned string. */ -static char* llm_concat_text_blocks(const char* resp) { - JsonBuf out; jb_init(&out); - if (!resp) return out.buf; - const char* p = json_find_key(resp, "content"); - if (!p) return out.buf; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') return out.buf; - p++; - while (*p && *p != ']') { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p != '{') break; - const char* end = json_skip_value(p); - size_t n = (size_t)(end - p); - char* obj = malloc(n + 1); - memcpy(obj, p, n); obj[n] = '\0'; - const char* tp = json_find_key(obj, "type"); - if (tp && *tp == '"') { - JsonParser jp = { .p = tp, .end = tp + strlen(tp), .err = 0 }; - char* tname = jp_parse_string_raw(&jp); - if (!jp.err && tname && strcmp(tname, "text") == 0) { - const char* xp = json_find_key(obj, "text"); - if (xp && *xp == '"') { - JsonParser jp2 = { .p = xp, .end = xp + strlen(xp), .err = 0 }; - char* txt = jp_parse_string_raw(&jp2); - if (!jp2.err && txt) jb_puts(&out, txt); - free(txt); - } - } - free(tname); - } - free(obj); - p = end; - } - return out.buf; -} - -/* Build tool_result message blocks for every tool_use in a response. - * Appends to `b` an array element for each tool_use; caller wraps. */ -static int llm_build_tool_results(JsonBuf* b, const char* resp) { - int any = 0; - const char* p = json_find_key(resp, "content"); - if (!p) return 0; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') return 0; - p++; - while (*p && *p != ']') { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p != '{') break; - const char* end = json_skip_value(p); - size_t n = (size_t)(end - p); - char* obj = malloc(n + 1); - memcpy(obj, p, n); obj[n] = '\0'; - - const char* tp = json_find_key(obj, "type"); - char* type_s = NULL; - if (tp && *tp == '"') { - JsonParser jp = { .p = tp, .end = tp + strlen(tp), .err = 0 }; - type_s = jp_parse_string_raw(&jp); - } - if (type_s && strcmp(type_s, "tool_use") == 0) { - /* Extract id, name, input. */ - char* id_s = NULL; char* name_s = NULL; - const char* idp = json_find_key(obj, "id"); - if (idp && *idp == '"') { - JsonParser jp = { .p = idp, .end = idp + strlen(idp), .err = 0 }; - id_s = jp_parse_string_raw(&jp); - } - const char* np = json_find_key(obj, "name"); - if (np && *np == '"') { - JsonParser jp = { .p = np, .end = np + strlen(np), .err = 0 }; - name_s = jp_parse_string_raw(&jp); - } - el_val_t input_raw = json_get_raw(EL_STR(obj), EL_STR("input")); - const char* input_s = EL_CSTR(input_raw); - if (!input_s || !*input_s) input_s = "{}"; - - llm_tool_fn fn = llm_tool_lookup(name_s ? name_s : ""); - char* result = NULL; - int is_error = 0; - if (!fn) { - size_t en = strlen(name_s ? name_s : "(null)") + 64; - result = malloc(en); - snprintf(result, en, "{\"error\":\"tool not registered: %s\"}", - name_s ? name_s : "(null)"); - is_error = 1; - } else { - el_val_t out = fn(EL_STR(input_s)); - const char* os = EL_CSTR(out); - result = el_strdup(os ? os : ""); - } - - if (any) jb_putc(b, ','); - char* esc_id = json_escape_alloc(id_s ? id_s : ""); - char* esc_res = json_escape_alloc(result ? result : ""); - jb_puts(b, "{\"type\":\"tool_result\",\"tool_use_id\":\""); - jb_puts(b, esc_id); - jb_puts(b, "\",\"content\":\""); - jb_puts(b, esc_res); - jb_puts(b, "\""); - if (is_error) jb_puts(b, ",\"is_error\":true"); - jb_putc(b, '}'); - free(esc_id); free(esc_res); free(result); - free(id_s); free(name_s); - any = 1; - } - free(type_s); - free(obj); - p = end; - } - return any; -} - -el_val_t llm_call_agentic(el_val_t model, el_val_t system, el_val_t user, el_val_t tools) { - /* Empty tools list → degrade to plain system call. */ - ElList* tl = (ElList*)(uintptr_t)tools; - if (!tl || tl->length == 0) { - return llm_call_system(model, system, user); - } - const char* m = llm_resolve_model(EL_CSTR(model)); - const char* sys_p = EL_CSTR(system); if (!sys_p) sys_p = ""; - const char* usr_p = EL_CSTR(user); if (!usr_p) usr_p = ""; - - /* Build the static parts: tools JSON and system prompt — these don't - * change across iterations. */ - JsonBuf tools_buf; jb_init(&tools_buf); - llm_emit_tools_json(&tools_buf, tools); - char* esc_sys = json_escape_alloc(sys_p); - - /* messages array, accumulated as a mutable JSON fragment (no surrounding - * brackets — emitted at request time). */ - JsonBuf msgs; jb_init(&msgs); - /* First user message. */ - char* esc_user = json_escape_alloc(usr_p); - jb_puts(&msgs, "{\"role\":\"user\",\"content\":\""); - jb_puts(&msgs, esc_user); - jb_puts(&msgs, "\"}"); - free(esc_user); - - char* last_text = el_strdup(""); - el_val_t final_out = 0; - int reached_cap = 1; - - for (int iter = 0; iter < 10; iter++) { - /* Build request body. */ - JsonBuf body; jb_init(&body); - jb_putc(&body, '{'); - jb_puts(&body, "\"model\":"); jb_emit_escaped(&body, m); - jb_puts(&body, ",\"max_tokens\":4096"); - if (*sys_p) { - jb_puts(&body, ",\"system\":\""); - jb_puts(&body, esc_sys); - jb_puts(&body, "\""); - } - jb_puts(&body, ",\"tools\":"); - jb_puts(&body, tools_buf.buf); - jb_puts(&body, ",\"messages\":["); - jb_puts(&body, msgs.buf); - jb_puts(&body, "]}"); - - el_val_t resp_v = llm_request(body.buf); - free(body.buf); - const char* resp = EL_CSTR(resp_v); - if (!resp || !*resp) { - final_out = http_error_json("empty response"); - reached_cap = 0; - break; - } - if (resp[0] == '{' && strstr(resp, "\"error\"") && - !json_find_key(resp, "content")) { - final_out = el_wrap_str(el_strdup(resp)); - reached_cap = 0; - break; - } - - /* Update last_text from this response. */ - free(last_text); - last_text = llm_concat_text_blocks(resp); - - /* Inspect stop_reason. */ - el_val_t sr_v = json_get_string(EL_STR(resp), EL_STR("stop_reason")); - const char* sr = EL_CSTR(sr_v); if (!sr) sr = ""; - - if (strcmp(sr, "end_turn") == 0) { - final_out = el_wrap_str(el_strdup(last_text)); - reached_cap = 0; - break; - } - if (strcmp(sr, "max_tokens") == 0) { - size_t ln = strlen(last_text) + 16; - char* out = malloc(ln); - snprintf(out, ln, "%s\n[truncated]", last_text); - final_out = el_wrap_str(out); - reached_cap = 0; - break; - } - if (strcmp(sr, "tool_use") != 0) { - /* Unexpected stop reason; return the text we have. */ - final_out = el_wrap_str(el_strdup(last_text)); - reached_cap = 0; - break; - } - - /* Append the assistant turn (raw content blocks) to messages. */ - JsonBuf ab; jb_init(&ab); - jb_puts(&ab, ",{\"role\":\"assistant\",\"content\":"); - llm_emit_content_blocks(&ab, resp); - jb_putc(&ab, '}'); - jb_puts(&msgs, ab.buf); - free(ab.buf); - - /* Build tool_result message. */ - JsonBuf tr; jb_init(&tr); - jb_puts(&tr, ",{\"role\":\"user\",\"content\":["); - int any = llm_build_tool_results(&tr, resp); - jb_puts(&tr, "]}"); - if (any) { - jb_puts(&msgs, tr.buf); - } - free(tr.buf); - } - - if (reached_cap) { - size_t ln = strlen(last_text) + 32; - char* out = malloc(ln); - snprintf(out, ln, "[loop_cap_reached]\n%s", last_text); - final_out = el_wrap_str(out); - } - free(last_text); - free(esc_sys); - free(tools_buf.buf); - free(msgs.buf); - return final_out; -} - -/* base64-encode arbitrary bytes (returns owned C string). - * Internal helper for llm_vision; the public crypto entry point that El - * programs call is `base64_encode(el_val_t)` defined in the crypto block - * at the end of this file. */ -static char* el_b64_encode_internal(const unsigned char* src, size_t n) { - static const char tbl[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - size_t out_len = 4 * ((n + 2) / 3); - char* out = malloc(out_len + 1); - if (!out) return NULL; - size_t o = 0; - for (size_t i = 0; i < n;) { - uint32_t v = 0; int got = 0; - v |= (uint32_t)src[i++] << 16; got++; - if (i < n) { v |= (uint32_t)src[i++] << 8; got++; } - if (i < n) { v |= (uint32_t)src[i++]; got++; } - out[o++] = tbl[(v >> 18) & 0x3f]; - out[o++] = tbl[(v >> 12) & 0x3f]; - out[o++] = (got > 1) ? tbl[(v >> 6) & 0x3f] : '='; - out[o++] = (got > 2) ? tbl[v & 0x3f] : '='; - } - out[o] = '\0'; - return out; -} - -el_val_t llm_vision(el_val_t model, el_val_t system, el_val_t prompt, el_val_t image_url_or_b64) { - const char* m = llm_resolve_model(EL_CSTR(model)); - const char* s = EL_CSTR(system); if (!s) s = ""; - const char* u = EL_CSTR(prompt); if (!u) u = ""; - const char* img = EL_CSTR(image_url_or_b64); if (!img) img = ""; - - /* Choose source mode */ - char* image_block = NULL; - if (strncasecmp(img, "http://", 7) == 0 || strncasecmp(img, "https://", 8) == 0) { - char* esc_url = json_escape_alloc(img); - size_t n = strlen(esc_url) + 128; - image_block = malloc(n); - snprintf(image_block, n, - "{\"type\":\"image\",\"source\":{\"type\":\"url\",\"url\":\"%s\"}}", - esc_url); - free(esc_url); - } else if (strncmp(img, "data:", 5) == 0) { - /* Inline data URL: split media-type and base64 */ - const char* semi = strchr(img + 5, ';'); - const char* comma = strchr(img + 5, ','); - char media[64] = "image/png"; - if (semi && comma && semi < comma) { - size_t ml = (size_t)(semi - (img + 5)); - if (ml >= sizeof(media)) ml = sizeof(media) - 1; - memcpy(media, img + 5, ml); media[ml] = '\0'; - } - const char* b64 = comma ? comma + 1 : ""; - char* esc_media = json_escape_alloc(media); - char* esc_b64 = json_escape_alloc(b64); - size_t n = strlen(esc_media) + strlen(esc_b64) + 192; - image_block = malloc(n); - snprintf(image_block, n, - "{\"type\":\"image\",\"source\":{\"type\":\"base64\"," - "\"media_type\":\"%s\",\"data\":\"%s\"}}", - esc_media, esc_b64); - free(esc_media); free(esc_b64); - } else if (*img) { - /* Treat as file path: read, base64-encode, attach. */ - FILE* f = fopen(img, "rb"); - if (!f) { - char err[256]; snprintf(err, sizeof(err), "cannot open image: %s", img); - return http_error_json(err); - } - fseek(f, 0, SEEK_END); - long sz = ftell(f); - rewind(f); - if (sz <= 0) { fclose(f); return http_error_json("empty image file"); } - unsigned char* buf = malloc((size_t)sz); - if (!buf) { fclose(f); return http_error_json("oom"); } - size_t got = fread(buf, 1, (size_t)sz, f); - fclose(f); - char* b64 = el_b64_encode_internal(buf, got); - free(buf); - if (!b64) return http_error_json("base64 encode failed"); - const char* media = "image/png"; - size_t ilen = strlen(img); - if (ilen >= 4) { - if (strcasecmp(img + ilen - 4, ".jpg") == 0 || - (ilen >= 5 && strcasecmp(img + ilen - 5, ".jpeg") == 0)) media = "image/jpeg"; - else if (strcasecmp(img + ilen - 4, ".gif") == 0) media = "image/gif"; - else if (strcasecmp(img + ilen - 4, ".webp") == 0) media = "image/webp"; - } - char* esc_b64 = json_escape_alloc(b64); free(b64); - size_t n = strlen(esc_b64) + 192; - image_block = malloc(n); - snprintf(image_block, n, - "{\"type\":\"image\",\"source\":{\"type\":\"base64\"," - "\"media_type\":\"%s\",\"data\":\"%s\"}}", - media, esc_b64); - free(esc_b64); - } - - char* esc_sys = json_escape_alloc(s); - char* esc_user = json_escape_alloc(u); - JsonBuf b; jb_init(&b); - jb_putc(&b, '{'); - jb_puts(&b, "\"model\":"); jb_emit_escaped(&b, m); - jb_puts(&b, ",\"max_tokens\":4096"); - if (*s) { - jb_puts(&b, ",\"system\":\""); - jb_puts(&b, esc_sys); - jb_puts(&b, "\""); - } - jb_puts(&b, ",\"messages\":[{\"role\":\"user\",\"content\":["); - if (image_block) { - jb_puts(&b, image_block); - jb_putc(&b, ','); - } - jb_puts(&b, "{\"type\":\"text\",\"text\":\""); - jb_puts(&b, esc_user); - jb_puts(&b, "\"}]}]}"); - free(esc_sys); free(esc_user); free(image_block); - el_val_t resp = llm_request(b.buf); - free(b.buf); - return llm_extract_text(resp); -} - -el_val_t llm_models(void) { - el_val_t lst = el_list_empty(); - lst = el_list_append(lst, el_wrap_str(el_strdup("claude-sonnet-4-5"))); - lst = el_list_append(lst, el_wrap_str(el_strdup("claude-opus-4-7"))); - lst = el_list_append(lst, el_wrap_str(el_strdup("claude-haiku-4-5"))); - return lst; -} -#endif /* HAVE_CURL */ - -/* ── Native VM builtin aliases ────────────────────────────────────────────── - * El source files use native_* names (El VM builtins). - * When compiled to C, these map directly to el_* runtime functions. */ - -el_val_t native_list_get(el_val_t list, el_val_t index) { - return el_list_get(list, index); -} - -el_val_t native_list_len(el_val_t list) { - return el_list_len(list); -} - -el_val_t native_list_append(el_val_t list, el_val_t elem) { - return el_list_append(list, elem); -} - -el_val_t native_list_empty(void) { - return el_list_empty(); -} - -el_val_t native_list_clone(el_val_t list) { - return el_list_clone(list); -} - -el_val_t native_string_chars(el_val_t sv) { - const char* s = EL_CSTR(sv); - el_val_t result = el_list_empty(); - if (!s) return result; - while (*s) { - char buf[2]; - buf[0] = *s; - buf[1] = '\0'; - result = el_list_append(result, EL_STR(strdup(buf))); - s++; - } - return result; -} - -el_val_t native_int_to_str(el_val_t n) { - return int_to_str(n); -} - -/* ── Method-call shorthand aliases ────────────────────────────────────────── - * Short names that result from the method-call convention: - * myList.append(x) → append(myList, x) - * myList.len() → len(myList) - * myList.get(i) → get(myList, i) - * myMap.map_get(k) → map_get(myMap, k) - * myMap.map_set(k,v) → map_set(myMap, k, v) */ - -el_val_t append(el_val_t list, el_val_t elem) { return el_list_append(list, elem); } -el_val_t len(el_val_t list) { return el_list_len(list); } -el_val_t get(el_val_t list, el_val_t index) { return el_list_get(list, index); } -el_val_t map_get(el_val_t map, el_val_t key) { return el_map_get(map, key); } -el_val_t map_set(el_val_t map, el_val_t key, el_val_t value) { return el_map_set(map, key, value); } - -/* ── Crypto primitives ────────────────────────────────────────────────────── - * - * SHA-256 implementation adapted from Brad Conte's public-domain reference - * (https://github.com/B-Con/crypto-algorithms/blob/master/sha256.c, public - * domain per the project's LICENSE). HMAC follows RFC 2104. Base64 encoding - * follows RFC 4648; the URL-safe variant uses the alphabet from §5 of the - * RFC and omits padding (per JWT/JWS convention). - * - * Self-contained: no OpenSSL/libcrypto dependency. The runtime keeps its - * existing `-lcurl -lpthread -ldl -lm` link line. - * - * Binary outputs (sha256_bytes, hmac_sha256_bytes) tag their buffer with a - * magic header so base64_encode/base64url_encode can recover the exact byte - * length even when the payload contains embedded NULs. Plain C strings - * (without the header) fall back to strlen(), preserving the existing API - * shape for normal text inputs. */ - -/* Magic-header for length-tagged binary buffers. Layout: - * [ uint32_t magic = EL_MAGIC_BIN ][ uint32_t length ][ data... ][ \0 ] - * The returned el_val_t points at `data`, so consumers that strlen() it still - * get a sensible (though possibly truncated) view. el_bin_len() recovers the - * true length by sniffing the 8 bytes preceding the pointer. - * - * Magic value chosen with high MSB so it cannot collide with printable ASCII - * (the same discriminator pattern used by EL_MAGIC_LIST / EL_MAGIC_MAP). */ -#define EL_MAGIC_BIN 0xE1B17EAFu - -typedef struct { - uint32_t magic; - uint32_t length; -} el_bin_hdr_t; - -/* Allocate a length-tagged binary buffer; returns pointer to the data area. */ -static unsigned char* el_bin_alloc(size_t len) { - el_bin_hdr_t* hdr = (el_bin_hdr_t*)malloc(sizeof(el_bin_hdr_t) + len + 1); - if (!hdr) { fputs("el_runtime: out of memory (bin)\n", stderr); exit(1); } - hdr->magic = EL_MAGIC_BIN; - hdr->length = (uint32_t)len; - unsigned char* data = (unsigned char*)(hdr + 1); - data[len] = '\0'; /* keep NUL-terminated for accidental strlen calls */ - return data; -} - -/* Recover length from a possibly-tagged buffer. Returns 1 if tagged. */ -static int el_bin_lookup(const void* p, size_t* out_len) { - if (!p) { *out_len = 0; return 0; } - /* Avoid reading off the front of a page on tiny pointers (e.g. NULs - * passed in as int-cast values). 4096 is a safe lower bound on any - * platform we target. */ - if ((uintptr_t)p < 4096) return 0; - const el_bin_hdr_t* hdr = (const el_bin_hdr_t*)((const char*)p - sizeof(el_bin_hdr_t)); - if (hdr->magic != EL_MAGIC_BIN) return 0; - *out_len = hdr->length; - return 1; -} - -/* Effective input length: tagged length if present, else strlen. */ -static size_t el_input_len(const char* s) { - size_t n; - if (el_bin_lookup(s, &n)) return n; - return s ? strlen(s) : 0; -} - -/* ─── SHA-256 (Brad Conte / public domain) ──────────────────────────────── */ - -typedef struct { - unsigned char data[64]; - uint32_t datalen; - uint64_t bitlen; - uint32_t state[8]; -} el_sha256_ctx_t; - -static const uint32_t el_sha256_k[64] = { - 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, - 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, - 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, - 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, - 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, - 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, - 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, - 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 -}; - -#define EL_ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) -#define EL_CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) -#define EL_MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -#define EL_EP0(x) (EL_ROTR(x,2) ^ EL_ROTR(x,13) ^ EL_ROTR(x,22)) -#define EL_EP1(x) (EL_ROTR(x,6) ^ EL_ROTR(x,11) ^ EL_ROTR(x,25)) -#define EL_SIG0(x) (EL_ROTR(x,7) ^ EL_ROTR(x,18) ^ ((x) >> 3)) -#define EL_SIG1(x) (EL_ROTR(x,17) ^ EL_ROTR(x,19) ^ ((x) >> 10)) - -static void el_sha256_transform(el_sha256_ctx_t* ctx, const unsigned char* data) { - uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64]; - int i, j; - for (i = 0, j = 0; i < 16; ++i, j += 4) { - m[i] = ((uint32_t)data[j] << 24) | ((uint32_t)data[j + 1] << 16) - | ((uint32_t)data[j + 2] << 8) | (uint32_t)data[j + 3]; - } - for (; i < 64; ++i) { - m[i] = EL_SIG1(m[i-2]) + m[i-7] + EL_SIG0(m[i-15]) + m[i-16]; - } - a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; - e = ctx->state[4]; f = ctx->state[5]; g = ctx->state[6]; h = ctx->state[7]; - for (i = 0; i < 64; ++i) { - t1 = h + EL_EP1(e) + EL_CH(e,f,g) + el_sha256_k[i] + m[i]; - t2 = EL_EP0(a) + EL_MAJ(a,b,c); - h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; - } - ctx->state[0] += a; ctx->state[1] += b; ctx->state[2] += c; ctx->state[3] += d; - ctx->state[4] += e; ctx->state[5] += f; ctx->state[6] += g; ctx->state[7] += h; -} - -static void el_sha256_init(el_sha256_ctx_t* ctx) { - ctx->datalen = 0; - ctx->bitlen = 0; - ctx->state[0] = 0x6a09e667; ctx->state[1] = 0xbb67ae85; - ctx->state[2] = 0x3c6ef372; ctx->state[3] = 0xa54ff53a; - ctx->state[4] = 0x510e527f; ctx->state[5] = 0x9b05688c; - ctx->state[6] = 0x1f83d9ab; ctx->state[7] = 0x5be0cd19; -} - -static void el_sha256_update(el_sha256_ctx_t* ctx, const unsigned char* data, size_t len) { - for (size_t i = 0; i < len; ++i) { - ctx->data[ctx->datalen++] = data[i]; - if (ctx->datalen == 64) { - el_sha256_transform(ctx, ctx->data); - ctx->bitlen += 512; - ctx->datalen = 0; - } - } -} - -static void el_sha256_final(el_sha256_ctx_t* ctx, unsigned char hash[32]) { - uint32_t i = ctx->datalen; - if (ctx->datalen < 56) { - ctx->data[i++] = 0x80; - while (i < 56) ctx->data[i++] = 0x00; - } else { - ctx->data[i++] = 0x80; - while (i < 64) ctx->data[i++] = 0x00; - el_sha256_transform(ctx, ctx->data); - memset(ctx->data, 0, 56); - } - ctx->bitlen += (uint64_t)ctx->datalen * 8; - ctx->data[63] = (unsigned char)( ctx->bitlen & 0xff); - ctx->data[62] = (unsigned char)((ctx->bitlen >> 8) & 0xff); - ctx->data[61] = (unsigned char)((ctx->bitlen >> 16) & 0xff); - ctx->data[60] = (unsigned char)((ctx->bitlen >> 24) & 0xff); - ctx->data[59] = (unsigned char)((ctx->bitlen >> 32) & 0xff); - ctx->data[58] = (unsigned char)((ctx->bitlen >> 40) & 0xff); - ctx->data[57] = (unsigned char)((ctx->bitlen >> 48) & 0xff); - ctx->data[56] = (unsigned char)((ctx->bitlen >> 56) & 0xff); - el_sha256_transform(ctx, ctx->data); - for (i = 0; i < 4; ++i) { - hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0xff; - hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0xff; - hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0xff; - hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0xff; - hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0xff; - hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0xff; - hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0xff; - hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0xff; - } -} - -static void el_sha256_oneshot(const unsigned char* data, size_t len, unsigned char out[32]) { - el_sha256_ctx_t c; - el_sha256_init(&c); - el_sha256_update(&c, data, len); - el_sha256_final(&c, out); -} - -/* ─── HMAC-SHA-256 (RFC 2104) ───────────────────────────────────────────── */ - -static void el_hmac_sha256(const unsigned char* key, size_t key_len, - const unsigned char* msg, size_t msg_len, - unsigned char out[32]) { - unsigned char k[64]; - unsigned char k_ipad[64]; - unsigned char k_opad[64]; - unsigned char inner[32]; - - if (key_len > 64) { - el_sha256_oneshot(key, key_len, k); - memset(k + 32, 0, 32); - } else { - memcpy(k, key, key_len); - memset(k + key_len, 0, 64 - key_len); - } - for (int i = 0; i < 64; ++i) { - k_ipad[i] = k[i] ^ 0x36; - k_opad[i] = k[i] ^ 0x5c; - } - { - el_sha256_ctx_t c; - el_sha256_init(&c); - el_sha256_update(&c, k_ipad, 64); - el_sha256_update(&c, msg, msg_len); - el_sha256_final(&c, inner); - } - { - el_sha256_ctx_t c; - el_sha256_init(&c); - el_sha256_update(&c, k_opad, 64); - el_sha256_update(&c, inner, 32); - el_sha256_final(&c, out); - } -} - -/* ─── Hex helper ────────────────────────────────────────────────────────── */ - -static el_val_t el_hex_encode(const unsigned char* data, size_t len) { - static const char digits[] = "0123456789abcdef"; - char* out = el_strbuf(len * 2); - for (size_t i = 0; i < len; ++i) { - out[i * 2] = digits[(data[i] >> 4) & 0xf]; - out[i * 2 + 1] = digits[ data[i] & 0xf]; - } - out[len * 2] = '\0'; - return el_wrap_str(out); -} - -/* ─── Base64 (RFC 4648) ─────────────────────────────────────────────────── */ - -static const char el_b64_std_alphabet[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char el_b64_url_alphabet[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - -el_val_t el_base64_encode_n(const unsigned char* data, size_t len, int url_safe) { - const char* alphabet = url_safe ? el_b64_url_alphabet : el_b64_std_alphabet; - /* Standard form is padded to multiple of 4; URL-safe omits padding. */ - size_t out_cap = ((len + 2) / 3) * 4 + 1; - char* out = el_strbuf(out_cap); - size_t i = 0, j = 0; - while (i + 3 <= len) { - uint32_t v = ((uint32_t)data[i] << 16) | ((uint32_t)data[i+1] << 8) | (uint32_t)data[i+2]; - out[j++] = alphabet[(v >> 18) & 0x3f]; - out[j++] = alphabet[(v >> 12) & 0x3f]; - out[j++] = alphabet[(v >> 6) & 0x3f]; - out[j++] = alphabet[ v & 0x3f]; - i += 3; - } - size_t rem = len - i; - if (rem == 1) { - uint32_t v = (uint32_t)data[i] << 16; - out[j++] = alphabet[(v >> 18) & 0x3f]; - out[j++] = alphabet[(v >> 12) & 0x3f]; - if (!url_safe) { out[j++] = '='; out[j++] = '='; } - } else if (rem == 2) { - uint32_t v = ((uint32_t)data[i] << 16) | ((uint32_t)data[i+1] << 8); - out[j++] = alphabet[(v >> 18) & 0x3f]; - out[j++] = alphabet[(v >> 12) & 0x3f]; - out[j++] = alphabet[(v >> 6) & 0x3f]; - if (!url_safe) { out[j++] = '='; } - } - out[j] = '\0'; - return el_wrap_str(out); -} - -/* Decode either alphabet — accepts both '+/' and '-_' transparently, and - * tolerates missing padding (which JWTs typically omit). Whitespace is - * skipped for robustness. Invalid characters cause the decode to stop and - * the partial result so far is returned. */ -static el_val_t el_base64_decode_any(const char* in) { - if (!in) { - unsigned char* empty = el_bin_alloc(0); - return EL_STR((char*)empty); - } - size_t in_len = strlen(in); - /* Worst case: 3 output bytes per 4 input chars, +1 NUL slack. */ - unsigned char* out = el_bin_alloc(((in_len + 3) / 4) * 3 + 1); - - int8_t lut[256]; - for (int i = 0; i < 256; ++i) lut[i] = -1; - for (int i = 0; i < 64; ++i) lut[(unsigned char)el_b64_std_alphabet[i]] = (int8_t)i; - /* Allow URL-safe characters too (so one decoder handles both forms). */ - lut[(unsigned char)'-'] = 62; - lut[(unsigned char)'_'] = 63; - - uint32_t buf = 0; - int bits = 0; - size_t o = 0; - for (size_t i = 0; i < in_len; ++i) { - unsigned char c = (unsigned char)in[i]; - if (c == '=' || c == '\r' || c == '\n' || c == ' ' || c == '\t') continue; - int8_t v = lut[c]; - if (v < 0) break; /* invalid char — stop */ - buf = (buf << 6) | (uint32_t)v; - bits += 6; - if (bits >= 8) { - bits -= 8; - out[o++] = (unsigned char)((buf >> bits) & 0xff); - } - } - /* Patch the length header to the actual decoded length. */ - el_bin_hdr_t* hdr = (el_bin_hdr_t*)((char*)out - sizeof(el_bin_hdr_t)); - hdr->length = (uint32_t)o; - out[o] = '\0'; - return EL_STR((char*)out); -} - -/* ─── Public crypto entry points ────────────────────────────────────────── */ - -el_val_t el_sha256_bytes_n(const unsigned char* data, size_t len) { - unsigned char* out = el_bin_alloc(32); - el_sha256_oneshot(data, len, out); - return EL_STR((char*)out); -} - -el_val_t sha256_hex(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - unsigned char digest[32]; - el_sha256_oneshot((const unsigned char*)(s ? s : ""), n, digest); - return el_hex_encode(digest, 32); -} - -el_val_t sha256_bytes(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - return el_sha256_bytes_n((const unsigned char*)(s ? s : ""), n); -} - -el_val_t hmac_sha256_hex(el_val_t key, el_val_t message) { - const char* k = EL_CSTR(key); - const char* m = EL_CSTR(message); - size_t kn = el_input_len(k); - size_t mn = el_input_len(m); - unsigned char mac[32]; - el_hmac_sha256((const unsigned char*)(k ? k : ""), kn, - (const unsigned char*)(m ? m : ""), mn, - mac); - return el_hex_encode(mac, 32); -} - -el_val_t hmac_sha256_bytes(el_val_t key, el_val_t message) { - const char* k = EL_CSTR(key); - const char* m = EL_CSTR(message); - size_t kn = el_input_len(k); - size_t mn = el_input_len(m); - unsigned char* out = el_bin_alloc(32); - el_hmac_sha256((const unsigned char*)(k ? k : ""), kn, - (const unsigned char*)(m ? m : ""), mn, - out); - return EL_STR((char*)out); -} - -el_val_t base64_encode(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - return el_base64_encode_n((const unsigned char*)(s ? s : ""), n, /*url_safe=*/0); -} - -el_val_t base64url_encode(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - return el_base64_encode_n((const unsigned char*)(s ? s : ""), n, /*url_safe=*/1); -} - -el_val_t base64_decode(el_val_t input) { - return el_base64_decode_any(EL_CSTR(input)); -} - -el_val_t base64url_decode(el_val_t input) { - return el_base64_decode_any(EL_CSTR(input)); -} - -/* ── Post-quantum cryptography (liboqs + OpenSSL) ─────────────────────────── - * - * Algorithm choices (per CNSA 2.0 / NIST PQ guidance, as of 2024): - * Signatures: CRYSTALS-Dilithium-3 (NIST security level 3, balanced) - * KEM: CRYSTALS-Kyber-768 (NIST security level 3) - * Hash: SHA3-256 (Keccak) (PQ-aware protocols favour SHA3 over SHA2) - * Hybrid: X25519 || Kyber-768, combined via HKDF-SHA256 - * - * Why hybrid: Kyber is new. X25519 has 20+ years of analysis. Hybridizing - * preserves classical security if Kyber falls to a future cryptanalytic - * advance, and preserves PQ security if X25519 falls to a quantum adversary. - * "Recordable now, decryptable later" already threatens long-lived classical - * key exchange — the only safe move for keys protecting durable doctrine - * (CGI lineage, KindredGrants, Principal-CGI covenants) is to encapsulate - * with PQ today, even if the classical leg is what the wire shows. - * - * Compile-time detection: when is unavailable the pq_* functions - * compile to stubs that return a JSON error envelope. SHA3-256 stays - * available regardless (it's implemented inline, no liboqs dep). This lets - * the runtime build cleanly on dev machines without liboqs while production - * gets the full PQ stack. */ - -/* ─── SHA3-256 (Keccak, FIPS 202) ──────────────────────────────────────────── - * Inline reference implementation. ~120 LoC, no external dependency. - * rate=1088 bits, capacity=512 bits, output=256 bits, padding=0x06. */ - -static const uint64_t el_keccak_rc[24] = { - 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, - 0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL, - 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL, - 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL, - 0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, - 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL, - 0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL, - 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL -}; - -static const unsigned el_keccak_rho[24] = { - 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 -}; - -static const unsigned el_keccak_pi[24] = { - 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 -}; - -#define EL_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n)))) - -static void el_keccak_f1600(uint64_t s[25]) { - for (int round = 0; round < 24; ++round) { - uint64_t bc[5], t; - for (int i = 0; i < 5; ++i) - bc[i] = s[i] ^ s[i+5] ^ s[i+10] ^ s[i+15] ^ s[i+20]; - for (int i = 0; i < 5; ++i) { - t = bc[(i+4) % 5] ^ EL_ROTL64(bc[(i+1) % 5], 1); - for (int j = 0; j < 25; j += 5) s[j+i] ^= t; - } - t = s[1]; - for (int i = 0; i < 24; ++i) { - int j = el_keccak_pi[i]; - bc[0] = s[j]; - s[j] = EL_ROTL64(t, el_keccak_rho[i]); - t = bc[0]; - } - for (int j = 0; j < 25; j += 5) { - for (int i = 0; i < 5; ++i) bc[i] = s[j+i]; - for (int i = 0; i < 5; ++i) - s[j+i] = bc[i] ^ ((~bc[(i+1) % 5]) & bc[(i+2) % 5]); - } - s[0] ^= el_keccak_rc[round]; - } -} - -static void el_sha3_256_oneshot(const unsigned char* data, size_t len, - unsigned char out[32]) { - uint64_t st[25] = {0}; - unsigned char* sb = (unsigned char*)st; - const size_t rate = 136; /* 1088 bits / 8 */ - size_t i = 0; - while (len - i >= rate) { - for (size_t k = 0; k < rate; ++k) sb[k] ^= data[i + k]; - el_keccak_f1600(st); - i += rate; - } - size_t rem = len - i; - for (size_t k = 0; k < rem; ++k) sb[k] ^= data[i + k]; - sb[rem] ^= 0x06; /* SHA3 domain-separation byte */ - sb[rate - 1] ^= 0x80; /* final-block padding bit (high bit of last byte) */ - el_keccak_f1600(st); - memcpy(out, sb, 32); -} - -el_val_t sha3_256_hex(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - unsigned char digest[32]; - el_sha3_256_oneshot((const unsigned char*)(s ? s : ""), n, digest); - return el_hex_encode(digest, 32); -} - -/* ─── Hex decode helper ───────────────────────────────────────────────────── - * Returns a length-tagged binary buffer (so embedded NULs survive); on - * odd-length / invalid input returns NULL with *out_len = 0. Caller is - * responsible for emitting the error envelope. */ - -static int el_hex_nibble(char c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'a' && c <= 'f') return c - 'a' + 10; - if (c >= 'A' && c <= 'F') return c - 'A' + 10; - return -1; -} - -__attribute__((unused)) -static unsigned char* el_hex_decode(const char* s, size_t* out_len) { - *out_len = 0; - if (!s) return NULL; - size_t n = strlen(s); - if (n & 1) return NULL; - size_t blen = n / 2; - unsigned char* out = el_bin_alloc(blen); - for (size_t i = 0; i < blen; ++i) { - int hi = el_hex_nibble(s[i*2]); - int lo = el_hex_nibble(s[i*2 + 1]); - if (hi < 0 || lo < 0) return NULL; - out[i] = (unsigned char)((hi << 4) | lo); - } - *out_len = blen; - return out; -} - -/* JSON error envelope reused across all PQ entry points. */ -static el_val_t pq_error(const char* msg) { - return http_error_json(msg); -} - -#if __has_include() -#include -#define EL_HAVE_LIBOQS 1 -#else -#define EL_HAVE_LIBOQS 0 -#endif - -#if EL_HAVE_LIBOQS && __has_include() -#include -#define EL_HAVE_OPENSSL 1 -#else -#define EL_HAVE_OPENSSL 0 -#endif - -#if !EL_HAVE_LIBOQS - -/* ─── Stubs (liboqs unavailable) ─────────────────────────────────────────── - * Each entry point returns the same JSON error so callers can inspect a - * single canonical "missing primitive" string. pq_verify is the lone - * exception — verifying without liboqs simply means "not verified", so - * returning Bool false (0) keeps the type contract intact. */ - -#define EL_PQ_NO_LIB "liboqs not linked, post-quantum primitives unavailable" - -el_val_t pq_keygen_signature(void) { return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_sign(el_val_t sk, el_val_t msg) { (void)sk; (void)msg; return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_verify(el_val_t pk, el_val_t msg, el_val_t sig) { (void)pk; (void)msg; (void)sig; return EL_INT(0); } -el_val_t pq_kem_keygen(void) { return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_kem_encaps(el_val_t pk) { (void)pk; return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_kem_decaps(el_val_t sk, el_val_t ct) { (void)sk; (void)ct; return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_hybrid_keygen(void) { return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_hybrid_handshake(el_val_t pub) { (void)pub; return pq_error(EL_PQ_NO_LIB); } - -#else /* EL_HAVE_LIBOQS */ - -/* ─── Dilithium-3 / ML-DSA-65 signatures ──────────────────────────────── - * - * NIST FIPS 204 standardized CRYSTALS-Dilithium as ML-DSA. ML-DSA-65 is the - * FIPS form of what we historically called Dilithium-3 — same algorithm - * family, same security level, identical key/sig sizes, but with a couple - * of standardization-driven tweaks (e.g. domain separation in the message - * binding). liboqs 0.12+ exposes both names; 0.15+ retired the legacy - * "Dilithium" constants in favour of "ML-DSA". We prefer ML-DSA-65 if the - * header advertises it, fall back to Dilithium-3 otherwise. Anything - * already signed with the older constant remains verifiable against that - * same constant — callers should pin the algorithm via the OQS_SIG handle's - * method_name field if they need to interoperate with archival signatures. */ - -#if defined(OQS_SIG_alg_ml_dsa_65) -# define EL_DILITHIUM_ALG OQS_SIG_alg_ml_dsa_65 -#elif defined(OQS_SIG_alg_dilithium_3) -# define EL_DILITHIUM_ALG OQS_SIG_alg_dilithium_3 -#else -# define EL_DILITHIUM_ALG "ML-DSA-65" /* string fallback; runtime probe catches misconfig */ -#endif - -el_val_t pq_keygen_signature(void) { - OQS_SIG* sig = OQS_SIG_new(EL_DILITHIUM_ALG); - if (!sig) return pq_error("OQS_SIG_new(dilithium-3) failed"); - unsigned char* pk = (unsigned char*)malloc(sig->length_public_key); - unsigned char* sk = (unsigned char*)malloc(sig->length_secret_key); - if (!pk || !sk) { free(pk); free(sk); OQS_SIG_free(sig); return pq_error("oom"); } - if (OQS_SIG_keypair(sig, pk, sk) != OQS_SUCCESS) { - free(pk); free(sk); OQS_SIG_free(sig); - return pq_error("dilithium-3 keypair generation failed"); - } - el_val_t pk_hex = el_hex_encode(pk, sig->length_public_key); - el_val_t sk_hex = el_hex_encode(sk, sig->length_secret_key); - OQS_MEM_secure_free(sk, sig->length_secret_key); - free(pk); - - const char* pks = EL_CSTR(pk_hex); - const char* sks = EL_CSTR(sk_hex); - char* buf = el_strbuf(strlen(pks) + strlen(sks) + 64); - sprintf(buf, "{\"public_key\":\"%s\",\"secret_key\":\"%s\"}", pks, sks); - OQS_SIG_free(sig); - return el_wrap_str(buf); -} - -el_val_t pq_sign(el_val_t secret_key_hex, el_val_t message) { - size_t sk_len = 0; - unsigned char* sk = el_hex_decode(EL_CSTR(secret_key_hex), &sk_len); - if (!sk) return pq_error("invalid hex in secret_key"); - - OQS_SIG* sig = OQS_SIG_new(EL_DILITHIUM_ALG); - if (!sig) return pq_error("OQS_SIG_new(dilithium-3) failed"); - if (sk_len != sig->length_secret_key) { - OQS_SIG_free(sig); - return pq_error("secret_key length mismatch for dilithium-3"); - } - - const char* msg = EL_CSTR(message); - size_t msg_len = el_input_len(msg); - unsigned char* signature = (unsigned char*)malloc(sig->length_signature); - size_t signature_len = sig->length_signature; - if (!signature) { OQS_SIG_free(sig); return pq_error("oom"); } - - if (OQS_SIG_sign(sig, signature, &signature_len, - (const unsigned char*)(msg ? msg : ""), msg_len, sk) != OQS_SUCCESS) { - free(signature); OQS_SIG_free(sig); - return pq_error("dilithium-3 sign failed"); - } - el_val_t sig_hex = el_hex_encode(signature, signature_len); - free(signature); OQS_SIG_free(sig); - return sig_hex; -} - -el_val_t pq_verify(el_val_t public_key_hex, el_val_t message, el_val_t signature_hex) { - size_t pk_len = 0, sig_len = 0; - unsigned char* pk = el_hex_decode(EL_CSTR(public_key_hex), &pk_len); - unsigned char* signature = el_hex_decode(EL_CSTR(signature_hex), &sig_len); - if (!pk || !signature) return EL_INT(0); - - OQS_SIG* sig = OQS_SIG_new(EL_DILITHIUM_ALG); - if (!sig) return EL_INT(0); - if (pk_len != sig->length_public_key) { OQS_SIG_free(sig); return EL_INT(0); } - - const char* msg = EL_CSTR(message); - size_t msg_len = el_input_len(msg); - OQS_STATUS rc = OQS_SIG_verify(sig, - (const unsigned char*)(msg ? msg : ""), msg_len, - signature, sig_len, pk); - OQS_SIG_free(sig); - return (rc == OQS_SUCCESS) ? EL_INT(1) : EL_INT(0); -} - -/* ─── Kyber-768 / ML-KEM-768 KEM ──────────────────────────────────────── - * - * NIST FIPS 203 standardized CRYSTALS-Kyber as ML-KEM. ML-KEM-768 is the - * FIPS form of what we historically called Kyber-768. Same situation as - * Dilithium → ML-DSA: prefer the standardized constant, fall back to the - * legacy name. liboqs 0.15.0 still exposes OQS_KEM_alg_kyber_768; the - * algorithm is identical at the wire level to ML-KEM-768 except for FIPS - * domain-separation tweaks, so the two ciphertexts/keys are NOT - * cross-compatible. Pin the constant for archival material. */ - -#if defined(OQS_KEM_alg_ml_kem_768) -# define EL_KYBER_ALG OQS_KEM_alg_ml_kem_768 -#elif defined(OQS_KEM_alg_kyber_768) -# define EL_KYBER_ALG OQS_KEM_alg_kyber_768 -#else -# define EL_KYBER_ALG "ML-KEM-768" -#endif - -el_val_t pq_kem_keygen(void) { - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - unsigned char* pk = (unsigned char*)malloc(kem->length_public_key); - unsigned char* sk = (unsigned char*)malloc(kem->length_secret_key); - if (!pk || !sk) { free(pk); free(sk); OQS_KEM_free(kem); return pq_error("oom"); } - if (OQS_KEM_keypair(kem, pk, sk) != OQS_SUCCESS) { - free(pk); free(sk); OQS_KEM_free(kem); - return pq_error("kyber-768 keypair generation failed"); - } - el_val_t pk_hex = el_hex_encode(pk, kem->length_public_key); - el_val_t sk_hex = el_hex_encode(sk, kem->length_secret_key); - OQS_MEM_secure_free(sk, kem->length_secret_key); - free(pk); - - const char* pks = EL_CSTR(pk_hex); - const char* sks = EL_CSTR(sk_hex); - char* buf = el_strbuf(strlen(pks) + strlen(sks) + 64); - sprintf(buf, "{\"public_key\":\"%s\",\"secret_key\":\"%s\"}", pks, sks); - OQS_KEM_free(kem); - return el_wrap_str(buf); -} - -el_val_t pq_kem_encaps(el_val_t public_key_hex) { - size_t pk_len = 0; - unsigned char* pk = el_hex_decode(EL_CSTR(public_key_hex), &pk_len); - if (!pk) return pq_error("invalid hex in public_key"); - - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - if (pk_len != kem->length_public_key) { - OQS_KEM_free(kem); - return pq_error("public_key length mismatch for kyber-768"); - } - unsigned char* ct = (unsigned char*)malloc(kem->length_ciphertext); - unsigned char* ss = (unsigned char*)malloc(kem->length_shared_secret); - if (!ct || !ss) { free(ct); free(ss); OQS_KEM_free(kem); return pq_error("oom"); } - if (OQS_KEM_encaps(kem, ct, ss, pk) != OQS_SUCCESS) { - free(ct); free(ss); OQS_KEM_free(kem); - return pq_error("kyber-768 encapsulation failed"); - } - el_val_t ct_hex = el_hex_encode(ct, kem->length_ciphertext); - el_val_t ss_hex = el_hex_encode(ss, kem->length_shared_secret); - free(ct); - OQS_MEM_secure_free(ss, kem->length_shared_secret); - - const char* cts = EL_CSTR(ct_hex); - const char* sss = EL_CSTR(ss_hex); - char* buf = el_strbuf(strlen(cts) + strlen(sss) + 64); - sprintf(buf, "{\"ciphertext\":\"%s\",\"shared_secret\":\"%s\"}", cts, sss); - OQS_KEM_free(kem); - return el_wrap_str(buf); -} - -el_val_t pq_kem_decaps(el_val_t secret_key_hex, el_val_t ciphertext_hex) { - size_t sk_len = 0, ct_len = 0; - unsigned char* sk = el_hex_decode(EL_CSTR(secret_key_hex), &sk_len); - unsigned char* ct = el_hex_decode(EL_CSTR(ciphertext_hex), &ct_len); - if (!sk || !ct) return pq_error("invalid hex in inputs"); - - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - if (sk_len != kem->length_secret_key || ct_len != kem->length_ciphertext) { - OQS_KEM_free(kem); - return pq_error("input length mismatch for kyber-768"); - } - unsigned char* ss = (unsigned char*)malloc(kem->length_shared_secret); - if (!ss) { OQS_KEM_free(kem); return pq_error("oom"); } - /* Kyber is IND-CCA via Fujisaki-Okamoto: decaps always returns *some* - * shared_secret even on tampered ciphertext (an implicit-rejection value - * derived from sk). Protocols MUST confirm the shared_secret matches via - * a subsequent step (e.g. AEAD tag, key-confirmation MAC) — do not - * assume decaps success implies authenticity. */ - if (OQS_KEM_decaps(kem, ss, ct, sk) != OQS_SUCCESS) { - free(ss); OQS_KEM_free(kem); - return pq_error("kyber-768 decapsulation failed"); - } - el_val_t ss_hex = el_hex_encode(ss, kem->length_shared_secret); - OQS_MEM_secure_free(ss, kem->length_shared_secret); - OQS_KEM_free(kem); - return ss_hex; -} - -/* ─── Hybrid handshake (X25519 + Kyber-768, HKDF-SHA256 combined) ─────── */ - -#if !EL_HAVE_OPENSSL - -el_val_t pq_hybrid_keygen(void) { - return pq_error("hybrid handshake requires OpenSSL (X25519); rebuild with -lcrypto"); -} -el_val_t pq_hybrid_handshake(el_val_t pub) { - (void)pub; - return pq_error("hybrid handshake requires OpenSSL (X25519); rebuild with -lcrypto"); -} - -#else /* EL_HAVE_OPENSSL */ - -/* HKDF-SHA256 (RFC 5869) — Extract+Expand. Reuses the inline HMAC-SHA256 - * already in this file. Empty salt → 32 zero bytes per the RFC. */ -static void el_hkdf_sha256(const unsigned char* salt, size_t salt_len, - const unsigned char* ikm, size_t ikm_len, - const unsigned char* info, size_t info_len, - unsigned char* out, size_t out_len) { - unsigned char zero_salt[32] = {0}; - if (salt_len == 0) { salt = zero_salt; salt_len = 32; } - unsigned char prk[32]; - el_hmac_sha256(salt, salt_len, ikm, ikm_len, prk); - - unsigned char t[32]; - size_t produced = 0; - unsigned char counter = 1; - unsigned char* buf = (unsigned char*)malloc(32 + info_len + 1); - if (!buf) { fputs("el_runtime: hkdf oom\n", stderr); return; } - while (produced < out_len) { - size_t off = 0; - if (counter > 1) { memcpy(buf, t, 32); off = 32; } - if (info && info_len) { memcpy(buf + off, info, info_len); off += info_len; } - buf[off++] = counter; - el_hmac_sha256(prk, 32, buf, off, t); - size_t chunk = (out_len - produced > 32) ? 32 : (out_len - produced); - memcpy(out + produced, t, chunk); - produced += chunk; - counter++; - } - free(buf); -} - -/* X25519 keygen via OpenSSL EVP. Returns 1 on success. - * Fills pk[32] and sk[32] (raw X25519 byte strings, no DER wrapper). */ -static int el_x25519_keygen(unsigned char pk[32], unsigned char sk[32]) { - EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL); - if (!pctx) return 0; - if (EVP_PKEY_keygen_init(pctx) != 1) { EVP_PKEY_CTX_free(pctx); return 0; } - EVP_PKEY* key = NULL; - if (EVP_PKEY_keygen(pctx, &key) != 1) { EVP_PKEY_CTX_free(pctx); return 0; } - EVP_PKEY_CTX_free(pctx); - - size_t plen = 32, slen = 32; - if (EVP_PKEY_get_raw_public_key (key, pk, &plen) != 1 || plen != 32) { - EVP_PKEY_free(key); return 0; - } - if (EVP_PKEY_get_raw_private_key(key, sk, &slen) != 1 || slen != 32) { - EVP_PKEY_free(key); return 0; - } - EVP_PKEY_free(key); - return 1; -} - -/* X25519 ECDH: derive 32-byte shared secret from local sk and remote pk. */ -static int el_x25519_derive(const unsigned char sk[32], const unsigned char rpk[32], - unsigned char ss[32]) { - EVP_PKEY* my = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, sk, 32); - EVP_PKEY* rem = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, rpk, 32); - if (!my || !rem) { EVP_PKEY_free(my); EVP_PKEY_free(rem); return 0; } - EVP_PKEY_CTX* dctx = EVP_PKEY_CTX_new(my, NULL); - if (!dctx) { EVP_PKEY_free(my); EVP_PKEY_free(rem); return 0; } - int ok = 0; - size_t out_len = 32; - if (EVP_PKEY_derive_init(dctx) == 1 && - EVP_PKEY_derive_set_peer(dctx, rem) == 1 && - EVP_PKEY_derive(dctx, ss, &out_len) == 1 && - out_len == 32) ok = 1; - EVP_PKEY_CTX_free(dctx); - EVP_PKEY_free(my); - EVP_PKEY_free(rem); - return ok; -} - -/* Hybrid wire layout (binary form, before hex encode): - * public_key = x25519_pub (32) || kyber_pub (1184) → 1216 bytes - * secret_key = x25519_sec (32) || kyber_sec (2400) → 2432 bytes - * ciphertext = ephem_x25519_pub (32) || kyber_ct (1088) → 1120 bytes - * shared_secret = HKDF-SHA256(x25519_ss || kyber_ss, info="el-pq-hybrid-v1", 32 bytes) - * The keygen result also exposes the four component hex fields for callers - * that prefer to handle the legs independently. */ - -el_val_t pq_hybrid_keygen(void) { - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - - unsigned char xpk[32], xsk[32]; - if (!el_x25519_keygen(xpk, xsk)) { - OQS_KEM_free(kem); - return pq_error("X25519 keygen failed"); - } - - unsigned char* kpk = (unsigned char*)malloc(kem->length_public_key); - unsigned char* ksk = (unsigned char*)malloc(kem->length_secret_key); - if (!kpk || !ksk) { free(kpk); free(ksk); OQS_KEM_free(kem); return pq_error("oom"); } - if (OQS_KEM_keypair(kem, kpk, ksk) != OQS_SUCCESS) { - free(kpk); free(ksk); OQS_KEM_free(kem); - return pq_error("kyber-768 keypair generation failed"); - } - - size_t pub_len = 32 + kem->length_public_key; - size_t sec_len = 32 + kem->length_secret_key; - unsigned char* pub_buf = (unsigned char*)malloc(pub_len); - unsigned char* sec_buf = (unsigned char*)malloc(sec_len); - if (!pub_buf || !sec_buf) { - free(pub_buf); free(sec_buf); free(kpk); - OQS_MEM_secure_free(ksk, kem->length_secret_key); - OQS_KEM_free(kem); return pq_error("oom"); - } - memcpy(pub_buf, xpk, 32); memcpy(pub_buf + 32, kpk, kem->length_public_key); - memcpy(sec_buf, xsk, 32); memcpy(sec_buf + 32, ksk, kem->length_secret_key); - - el_val_t x_pub_hex = el_hex_encode(xpk, 32); - el_val_t x_sec_hex = el_hex_encode(xsk, 32); - el_val_t k_pub_hex = el_hex_encode(kpk, kem->length_public_key); - el_val_t k_sec_hex = el_hex_encode(ksk, kem->length_secret_key); - el_val_t pub_hex = el_hex_encode(pub_buf, pub_len); - el_val_t sec_hex = el_hex_encode(sec_buf, sec_len); - - OQS_MEM_secure_free(ksk, kem->length_secret_key); - free(kpk); free(pub_buf); free(sec_buf); - OQS_KEM_free(kem); - memset(xsk, 0, 32); /* best-effort wipe of stack copy */ - - const char* xph = EL_CSTR(x_pub_hex); - const char* xsh = EL_CSTR(x_sec_hex); - const char* kph = EL_CSTR(k_pub_hex); - const char* ksh = EL_CSTR(k_sec_hex); - const char* pubh = EL_CSTR(pub_hex); - const char* sech = EL_CSTR(sec_hex); - - char* buf = el_strbuf(strlen(xph) + strlen(xsh) + strlen(kph) + strlen(ksh) - + strlen(pubh) + strlen(sech) + 256); - sprintf(buf, - "{\"x25519_pub\":\"%s\",\"x25519_sec\":\"%s\"," - "\"kyber_pub\":\"%s\",\"kyber_sec\":\"%s\"," - "\"public_key\":\"%s\",\"secret_key\":\"%s\"}", - xph, xsh, kph, ksh, pubh, sech); - return el_wrap_str(buf); -} - -/* Initiator-side handshake. Caller supplies the responder's combined public - * key (x25519_pub || kyber_pub, hex-encoded). The runtime: - * 1. Generates an ephemeral X25519 keypair, runs ECDH against the - * responder's static x25519_pub. - * 2. Runs Kyber-768 encaps against the responder's kyber_pub → kyber_ct, - * kyber_ss. - * 3. Combined shared = HKDF-SHA256(salt="", ikm = x25519_ss || kyber_ss, - * info = "el-pq-hybrid-v1", L = 32). - * 4. Returns combined ciphertext (= ephemeral_x25519_pub || kyber_ct) and - * the derived shared_secret. - * - * Responder side composition (intentionally not a separate runtime fn — - * trivial to express in El given pq_kem_decaps + a future x25519_derive - * primitive): split the ciphertext into ephem_xpk (32) and kyber_ct, run - * X25519(static_xsk, ephem_xpk) and pq_kem_decaps(static_kyber_sk, kyber_ct), - * then HKDF-SHA256 with the same salt/info to recover the same shared_secret. - * If a separate x25519 entry point becomes valuable, add `pq_hybrid_open` - * here taking (secret_key_combined, ciphertext_combined). */ -el_val_t pq_hybrid_handshake(el_val_t remote_pub_combined) { - size_t pub_len = 0; - unsigned char* rpub = el_hex_decode(EL_CSTR(remote_pub_combined), &pub_len); - if (!rpub) return pq_error("invalid hex in remote_pub_combined"); - - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - if (pub_len != 32 + kem->length_public_key) { - OQS_KEM_free(kem); - return pq_error("remote_pub_combined length mismatch (expected x25519_pub || kyber_pub)"); - } - - unsigned char e_xpk[32], e_xsk[32], x_ss[32]; - if (!el_x25519_keygen(e_xpk, e_xsk)) { - OQS_KEM_free(kem); - return pq_error("X25519 ephemeral keygen failed"); - } - if (!el_x25519_derive(e_xsk, rpub, x_ss)) { - memset(e_xsk, 0, 32); - OQS_KEM_free(kem); - return pq_error("X25519 derive failed"); - } - memset(e_xsk, 0, 32); /* ephemeral; not needed after derive */ - - unsigned char* k_ct = (unsigned char*)malloc(kem->length_ciphertext); - unsigned char* k_ss = (unsigned char*)malloc(kem->length_shared_secret); - if (!k_ct || !k_ss) { - free(k_ct); free(k_ss); OQS_KEM_free(kem); - return pq_error("oom"); - } - if (OQS_KEM_encaps(kem, k_ct, k_ss, rpub + 32) != OQS_SUCCESS) { - free(k_ct); free(k_ss); OQS_KEM_free(kem); - return pq_error("kyber-768 encapsulation failed"); - } - - /* HKDF combine: ikm = x_ss || k_ss. */ - size_t ikm_len = 32 + kem->length_shared_secret; - unsigned char* ikm = (unsigned char*)malloc(ikm_len); - if (!ikm) { - free(k_ct); OQS_MEM_secure_free(k_ss, kem->length_shared_secret); - OQS_KEM_free(kem); - return pq_error("oom"); - } - memcpy(ikm, x_ss, 32); - memcpy(ikm + 32, k_ss, kem->length_shared_secret); - unsigned char combined[32]; - static const char info_str[] = "el-pq-hybrid-v1"; - el_hkdf_sha256(NULL, 0, ikm, ikm_len, - (const unsigned char*)info_str, sizeof(info_str) - 1, - combined, 32); - - memset(x_ss, 0, 32); - OQS_MEM_secure_free(k_ss, kem->length_shared_secret); - OQS_MEM_secure_free(ikm, ikm_len); - - /* Combined ciphertext = ephemeral_x25519_pub || kyber_ct. */ - size_t ct_len = 32 + kem->length_ciphertext; - unsigned char* combined_ct = (unsigned char*)malloc(ct_len); - if (!combined_ct) { free(k_ct); OQS_KEM_free(kem); return pq_error("oom"); } - memcpy(combined_ct, e_xpk, 32); - memcpy(combined_ct + 32, k_ct, kem->length_ciphertext); - free(k_ct); - OQS_KEM_free(kem); - - el_val_t ct_hex = el_hex_encode(combined_ct, ct_len); - el_val_t ss_hex = el_hex_encode(combined, 32); - free(combined_ct); - memset(combined, 0, 32); - - const char* cts = EL_CSTR(ct_hex); - const char* sss = EL_CSTR(ss_hex); - char* buf = el_strbuf(strlen(cts) + strlen(sss) + 64); - sprintf(buf, "{\"ciphertext\":\"%s\",\"shared_secret\":\"%s\"}", cts, sss); - return el_wrap_str(buf); -} - -#endif /* EL_HAVE_OPENSSL */ -#endif /* EL_HAVE_LIBOQS */ - -/* ─── AEAD: AES-256-GCM ──────────────────────────────────────────────────── - * - * Symmetric authenticated encryption used to wrap envelopes once a shared - * secret has been derived from the KEM (Kyber-768 / hybrid). The El surface - * is intentionally narrow: - * - * aead_encrypt(key_hex, plaintext) - * → {"nonce":"<24 hex>","ciphertext":"<...hex including 16-byte tag>"} - * - * aead_decrypt(key_hex, nonce_hex, ciphertext_hex) - * → plaintext String, or "" on auth failure / malformed input - * - * Conventions: - * - key_hex must decode to exactly 32 bytes (AES-256). Callers that hold - * a longer KEM shared_secret should normalize via SHA3-256(ss) → 32 bytes - * before passing it in. (Kyber-768's shared_secret is already 32 bytes, - * but keeping this contract explicit lets the El side be agnostic.) - * - nonce is a fresh 12-byte random value drawn from the OS CSPRNG. Caller - * never picks the nonce — eliminates the GCM nonce-reuse footgun entirely. - * - tag is the standard 16 bytes, appended to ciphertext per RFC 5116. - * `ciphertext` field is therefore (plaintext_len + 16) bytes, hex-encoded. - * - No associated data (AAD). If we later need bound metadata, add a - * length-prefixed AAD argument and bump the envelope version tag. - * - * Failure mode: - * aead_encrypt returns http_error_json(...) on input/system failure. - * aead_decrypt returns the empty string on ANY failure (including auth-tag - * mismatch). Callers MUST check for "" before using the result. */ - -#if !__has_include() - -el_val_t aead_encrypt(el_val_t key_hex, el_val_t plaintext) { - (void)key_hex; (void)plaintext; - return http_error_json("aead_encrypt requires OpenSSL (libcrypto); rebuild with -lcrypto"); -} -el_val_t aead_decrypt(el_val_t key_hex, el_val_t nonce_hex, el_val_t ciphertext_hex) { - (void)key_hex; (void)nonce_hex; (void)ciphertext_hex; - return el_wrap_str(el_strdup("")); -} - -#else /* OpenSSL available */ - -#include -#include - -el_val_t aead_encrypt(el_val_t key_hex, el_val_t plaintext) { - size_t key_len = 0; - unsigned char* key = el_hex_decode(EL_CSTR(key_hex), &key_len); - if (!key) return http_error_json("invalid hex in key"); - if (key_len != 32) return http_error_json("aead key must be 32 bytes (64 hex chars) for AES-256-GCM"); - - const char* pt = EL_CSTR(plaintext); - size_t pt_len = el_input_len(pt); - if (!pt) pt = ""; - - unsigned char nonce[12]; - if (RAND_bytes(nonce, 12) != 1) return http_error_json("OS CSPRNG failed (RAND_bytes)"); - - EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); - if (!ctx) return http_error_json("EVP_CIPHER_CTX_new failed"); - - if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1) { - EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm init failed"); - } - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) != 1) { - EVP_CIPHER_CTX_free(ctx); return http_error_json("set ivlen failed"); - } - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce) != 1) { - EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm key/iv init failed"); - } - - /* GCM ciphertext is the same length as plaintext; we append a 16-byte - * authentication tag for AEAD semantics. Allocate plaintext_len + 16. */ - unsigned char* ct = (unsigned char*)malloc(pt_len + 16); - if (!ct) { EVP_CIPHER_CTX_free(ctx); return http_error_json("oom"); } - int outlen = 0, total = 0; - if (EVP_EncryptUpdate(ctx, ct, &outlen, (const unsigned char*)pt, (int)pt_len) != 1) { - free(ct); EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm update failed"); - } - total += outlen; - if (EVP_EncryptFinal_ex(ctx, ct + total, &outlen) != 1) { - free(ct); EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm final failed"); - } - total += outlen; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, ct + total) != 1) { - free(ct); EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm get tag failed"); - } - EVP_CIPHER_CTX_free(ctx); - - el_val_t nonce_hex_v = el_hex_encode(nonce, 12); - el_val_t ct_hex_v = el_hex_encode(ct, (size_t)total + 16); - free(ct); - - const char* nh = EL_CSTR(nonce_hex_v); - const char* ch = EL_CSTR(ct_hex_v); - char* buf = el_strbuf(strlen(nh) + strlen(ch) + 48); - sprintf(buf, "{\"nonce\":\"%s\",\"ciphertext\":\"%s\"}", nh, ch); - return el_wrap_str(buf); -} - -el_val_t aead_decrypt(el_val_t key_hex, el_val_t nonce_hex, el_val_t ciphertext_hex) { - size_t key_len = 0, nonce_len = 0, ct_len = 0; - unsigned char* key = el_hex_decode(EL_CSTR(key_hex), &key_len); - unsigned char* nonce = el_hex_decode(EL_CSTR(nonce_hex), &nonce_len); - unsigned char* ct = el_hex_decode(EL_CSTR(ciphertext_hex), &ct_len); - if (!key || !nonce || !ct) return el_wrap_str(el_strdup("")); - if (key_len != 32 || nonce_len != 12) return el_wrap_str(el_strdup("")); - if (ct_len < 16) return el_wrap_str(el_strdup("")); - - size_t body_len = ct_len - 16; - const unsigned char* tag = ct + body_len; - - EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); - if (!ctx) return el_wrap_str(el_strdup("")); - - if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1 || - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) != 1 || - EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce) != 1) { - EVP_CIPHER_CTX_free(ctx); return el_wrap_str(el_strdup("")); - } - - unsigned char* pt = (unsigned char*)malloc(body_len + 1); - if (!pt) { EVP_CIPHER_CTX_free(ctx); return el_wrap_str(el_strdup("")); } - int outlen = 0, total = 0; - if (EVP_DecryptUpdate(ctx, pt, &outlen, ct, (int)body_len) != 1) { - free(pt); EVP_CIPHER_CTX_free(ctx); return el_wrap_str(el_strdup("")); - } - total += outlen; - /* Set expected tag before final — GCM's final step is where auth happens. */ - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void*)tag) != 1) { - free(pt); EVP_CIPHER_CTX_free(ctx); return el_wrap_str(el_strdup("")); - } - int rc = EVP_DecryptFinal_ex(ctx, pt + total, &outlen); - EVP_CIPHER_CTX_free(ctx); - if (rc != 1) { - /* Auth failure or padding/length mismatch. Return empty so callers - * cannot accidentally treat tampered ciphertext as a valid message. */ - free(pt); - return el_wrap_str(el_strdup("")); - } - total += outlen; - pt[total] = '\0'; - - /* Copy into the el arena so the caller-visible string outlives this fn. */ - char* out = el_strbuf((size_t)total); - memcpy(out, pt, (size_t)total); - out[total] = '\0'; - free(pt); - return el_wrap_str(out); -} - -#endif /* __has_include() */ - -#ifdef HAVE_CURL -/* ──────────────────────────────────────────────────────────────────────────── - * OTLP/HTTP observability — logs, traces, metrics - * - * Design goals: - * - Zero blocking on the request path. Producers append to in-memory - * ring buffers; a single worker thread flushes to the OTLP endpoint. - * - Drop-on-failure semantics. If the endpoint is unreachable or slow, - * we drop telemetry rather than back-pressure into the request handler. - * - Best-effort serialization. Each record is pre-serialized as JSON when - * the El program calls the primitive; the worker just batches. - * - Configuration via env vars: - * OTLP_ENDPOINT e.g. https://alloy.neuralplatform.ai:4318 - * OTEL_SERVICE_NAME e.g. neuron-web (default: argv[0] basename) - * OTEL_SERVICE_VERSION (default: "0.0.0") - * OTEL_RESOURCE_ATTRS comma-sep k=v pairs (optional) - * - * Wire format: OTLP/HTTP JSON. Three endpoints: - * POST {endpoint}/v1/logs — log records - * POST {endpoint}/v1/traces — spans - * POST {endpoint}/v1/metrics — counter/gauge points - * - * El programs see four primitives: - * trace_span_start(name) -> SpanHandle (just a string id) - * trace_span_end(handle) (computes duration, queues) - * emit_log(level, msg, fields_json) (queues a log record) - * emit_metric(name, value, tags_json) (queues a counter increment) - * ──────────────────────────────────────────────────────────────────────────── - */ - -#define OTLP_BUF_CAP 4096 /* per-buffer ring size */ -#define OTLP_FLUSH_MS 2000 /* flush every 2s */ -#define OTLP_BATCH_MAX 200 /* up to 200 records per POST */ - -typedef struct { - char* data; /* malloc'd JSON fragment for this record */ -} OtlpRec; - -typedef struct { - OtlpRec ring[OTLP_BUF_CAP]; - size_t head; /* next write slot */ - size_t tail; /* next read slot */ - pthread_mutex_t mu; -} OtlpQueue; - -static OtlpQueue _otlp_logs = { .mu = PTHREAD_MUTEX_INITIALIZER }; -static OtlpQueue _otlp_traces = { .mu = PTHREAD_MUTEX_INITIALIZER }; -static OtlpQueue _otlp_metrics = { .mu = PTHREAD_MUTEX_INITIALIZER }; - -static char* _otlp_endpoint = NULL; /* e.g. https://alloy.neuralplatform.ai:4318 */ -static char* _otlp_service_name = NULL; -static char* _otlp_service_version = NULL; -static int _otlp_initialized = 0; -static pthread_t _otlp_worker_thread; - -/* enqueue — returns 1 if accepted, 0 if dropped (full buffer or no endpoint) */ -static int otlp_enqueue(OtlpQueue* q, const char* json) { - if (!_otlp_endpoint || !json) return 0; - pthread_mutex_lock(&q->mu); - size_t next_head = (q->head + 1) % OTLP_BUF_CAP; - if (next_head == q->tail) { - /* buffer full — drop oldest */ - free(q->ring[q->tail].data); - q->ring[q->tail].data = NULL; - q->tail = (q->tail + 1) % OTLP_BUF_CAP; - } - q->ring[q->head].data = strdup(json); - q->head = next_head; - pthread_mutex_unlock(&q->mu); - return 1; -} - -/* drain — copies up to OTLP_BATCH_MAX items into a comma-joined string, - * caller must free the result. Returns NULL if queue is empty. */ -static char* otlp_drain(OtlpQueue* q) { - pthread_mutex_lock(&q->mu); - if (q->head == q->tail) { pthread_mutex_unlock(&q->mu); return NULL; } - /* compute total length */ - size_t total = 0, count = 0; - size_t i = q->tail; - while (i != q->head && count < OTLP_BATCH_MAX) { - if (q->ring[i].data) total += strlen(q->ring[i].data) + 1; /* +1 for comma */ - i = (i + 1) % OTLP_BUF_CAP; - count++; - } - char* out = malloc(total + 4); - if (!out) { pthread_mutex_unlock(&q->mu); return NULL; } - out[0] = '\0'; - size_t off = 0; - i = q->tail; - count = 0; - while (i != q->head && count < OTLP_BATCH_MAX) { - if (q->ring[i].data) { - size_t l = strlen(q->ring[i].data); - if (off > 0) { out[off++] = ','; } - memcpy(out + off, q->ring[i].data, l); - off += l; - free(q->ring[i].data); - q->ring[i].data = NULL; - } - i = (i + 1) % OTLP_BUF_CAP; - count++; - } - out[off] = '\0'; - q->tail = i; - pthread_mutex_unlock(&q->mu); - return out; -} - -/* Build resource block once (service.name, service.version, host.name) */ -static char* otlp_resource_block(void) { - static char cached[1024]; - static int built = 0; - if (built) return cached; - char host[256] = "unknown"; - gethostname(host, sizeof(host) - 1); - snprintf(cached, sizeof(cached), - "{\"attributes\":[" - "{\"key\":\"service.name\",\"value\":{\"stringValue\":\"%s\"}}," - "{\"key\":\"service.version\",\"value\":{\"stringValue\":\"%s\"}}," - "{\"key\":\"host.name\",\"value\":{\"stringValue\":\"%s\"}}" - "]}", - _otlp_service_name ? _otlp_service_name : "el-app", - _otlp_service_version ? _otlp_service_version : "0.0.0", - host); - built = 1; - return cached; -} - -/* Best-effort POST. Drops on any error. */ -static void otlp_post(const char* path, const char* body) { - if (!_otlp_endpoint || !body || !*body) return; - char url[1024]; - snprintf(url, sizeof(url), "%s%s", _otlp_endpoint, path); - CURL* c = curl_easy_init(); - if (!c) return; - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - curl_easy_setopt(c, CURLOPT_URL, url); - curl_easy_setopt(c, CURLOPT_POST, 1L); - curl_easy_setopt(c, CURLOPT_POSTFIELDS, body); - curl_easy_setopt(c, CURLOPT_POSTFIELDSIZE, (long)strlen(body)); - curl_easy_setopt(c, CURLOPT_HTTPHEADER, h); - curl_easy_setopt(c, CURLOPT_TIMEOUT_MS, 3000L); - curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, NULL); /* discard response */ - curl_easy_perform(c); - curl_slist_free_all(h); - curl_easy_cleanup(c); -} - -/* Flush worker — runs forever until process exits */ -static void* otlp_worker(void* arg) { - (void)arg; - while (1) { - struct timespec ts = { OTLP_FLUSH_MS / 1000, (OTLP_FLUSH_MS % 1000) * 1000000L }; - nanosleep(&ts, NULL); - - char* logs = otlp_drain(&_otlp_logs); - if (logs && *logs) { - char body[OTLP_BUF_CAP * 8]; - int n = snprintf(body, sizeof(body), - "{\"resourceLogs\":[{\"resource\":%s," - "\"scopeLogs\":[{\"scope\":{\"name\":\"el-runtime\"}," - "\"logRecords\":[%s]}]}]}", - otlp_resource_block(), logs); - if (n > 0 && n < (int)sizeof(body)) otlp_post("/v1/logs", body); - } - free(logs); - - char* traces = otlp_drain(&_otlp_traces); - if (traces && *traces) { - char body[OTLP_BUF_CAP * 8]; - int n = snprintf(body, sizeof(body), - "{\"resourceSpans\":[{\"resource\":%s," - "\"scopeSpans\":[{\"scope\":{\"name\":\"el-runtime\"}," - "\"spans\":[%s]}]}]}", - otlp_resource_block(), traces); - if (n > 0 && n < (int)sizeof(body)) otlp_post("/v1/traces", body); - } - free(traces); - - char* metrics = otlp_drain(&_otlp_metrics); - if (metrics && *metrics) { - char body[OTLP_BUF_CAP * 8]; - int n = snprintf(body, sizeof(body), - "{\"resourceMetrics\":[{\"resource\":%s," - "\"scopeMetrics\":[{\"scope\":{\"name\":\"el-runtime\"}," - "\"metrics\":[%s]}]}]}", - otlp_resource_block(), metrics); - if (n > 0 && n < (int)sizeof(body)) otlp_post("/v1/metrics", body); - } - free(metrics); - } - return NULL; -} - -/* Initialize OTLP — called lazily on first emit. Idempotent. */ -static void otlp_lazy_init(void) { - if (_otlp_initialized) return; - static pthread_mutex_t once_mu = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&once_mu); - if (_otlp_initialized) { pthread_mutex_unlock(&once_mu); return; } - - const char* ep = getenv("OTLP_ENDPOINT"); - if (!ep || !*ep) { - _otlp_initialized = 1; - pthread_mutex_unlock(&once_mu); - return; - } - _otlp_endpoint = strdup(ep); - /* trim trailing slash */ - size_t l = strlen(_otlp_endpoint); - if (l > 0 && _otlp_endpoint[l - 1] == '/') _otlp_endpoint[l - 1] = '\0'; - - const char* svc = getenv("OTEL_SERVICE_NAME"); - _otlp_service_name = strdup(svc && *svc ? svc : "el-app"); - const char* ver = getenv("OTEL_SERVICE_VERSION"); - _otlp_service_version = strdup(ver && *ver ? ver : "0.0.0"); - - pthread_create(&_otlp_worker_thread, NULL, otlp_worker, NULL); - pthread_detach(_otlp_worker_thread); - _otlp_initialized = 1; - pthread_mutex_unlock(&once_mu); -} - -/* JSON-escape a string into out_buf. Returns chars written (excluding null). */ -static size_t otlp_json_escape(const char* in, char* out, size_t out_cap) { - size_t o = 0; - for (size_t i = 0; in[i] && o + 8 < out_cap; i++) { - unsigned char c = (unsigned char)in[i]; - if (c == '"') { out[o++] = '\\'; out[o++] = '"'; } - else if (c == '\\'){ out[o++] = '\\'; out[o++] = '\\'; } - else if (c == '\n'){ out[o++] = '\\'; out[o++] = 'n'; } - else if (c == '\r'){ out[o++] = '\\'; out[o++] = 'r'; } - else if (c == '\t'){ out[o++] = '\\'; out[o++] = 't'; } - else if (c < 0x20) { o += snprintf(out + o, out_cap - o, "\\u%04x", c); } - else { out[o++] = (char)c; } - } - out[o] = '\0'; - return o; -} - -/* ── Public El primitives ─────────────────────────────────────────────────── */ - -/* emit_log(level, msg, fields_json) — fields_json is a JSON object string or "" */ -el_val_t emit_log(el_val_t level_v, el_val_t msg_v, el_val_t fields_v) { - otlp_lazy_init(); - if (!_otlp_endpoint) return EL_INT(0); - const char* level = EL_CSTR(level_v); if (!level) level = "INFO"; - const char* msg = EL_CSTR(msg_v); if (!msg) msg = ""; - const char* fields = EL_CSTR(fields_v); if (!fields) fields = ""; - /* Map El level names to OTLP severity numbers */ - int sev_num = 9; /* INFO */ - if (strcmp(level, "TRACE") == 0) sev_num = 1; - else if (strcmp(level, "DEBUG") == 0) sev_num = 5; - else if (strcmp(level, "INFO") == 0) sev_num = 9; - else if (strcmp(level, "WARN") == 0 || strcmp(level, "WARNING") == 0) sev_num = 13; - else if (strcmp(level, "ERROR") == 0) sev_num = 17; - else if (strcmp(level, "FATAL") == 0) sev_num = 21; - char esc_msg[2048]; otlp_json_escape(msg, esc_msg, sizeof(esc_msg)); - /* unix nanos */ - struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - long long now_nano = (long long)ts.tv_sec * 1000000000LL + ts.tv_nsec; - char rec[4096]; - int n = snprintf(rec, sizeof(rec), - "{\"timeUnixNano\":\"%lld\",\"severityNumber\":%d," - "\"severityText\":\"%s\"," - "\"body\":{\"stringValue\":\"%s\"}%s%s}", - now_nano, sev_num, level, esc_msg, - (fields && *fields) ? ",\"attributes\":" : "", - (fields && *fields) ? fields : ""); - if (n > 0 && n < (int)sizeof(rec)) otlp_enqueue(&_otlp_logs, rec); - return EL_INT(1); -} - -/* emit_metric(name, value, tags_json) — Sum (counter) data point. tags_json - * is a JSON array of {key, value} pairs or empty string. */ -el_val_t emit_metric(el_val_t name_v, el_val_t value_v, el_val_t tags_v) { - otlp_lazy_init(); - if (!_otlp_endpoint) return EL_INT(0); - const char* name = EL_CSTR(name_v); if (!name) name = "unknown"; - int64_t val = (int64_t)value_v; - const char* tags = EL_CSTR(tags_v); if (!tags) tags = ""; - char esc_name[256]; otlp_json_escape(name, esc_name, sizeof(esc_name)); - struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - long long now_nano = (long long)ts.tv_sec * 1000000000LL + ts.tv_nsec; - char rec[4096]; - int n = snprintf(rec, sizeof(rec), - "{\"name\":\"%s\",\"sum\":{\"aggregationTemporality\":2,\"isMonotonic\":true," - "\"dataPoints\":[{\"asInt\":\"%lld\"," - "\"timeUnixNano\":\"%lld\"" - "%s%s}]}}", - esc_name, (long long)val, now_nano, - (tags && *tags) ? ",\"attributes\":" : "", - (tags && *tags) ? tags : ""); - if (n > 0 && n < (int)sizeof(rec)) otlp_enqueue(&_otlp_metrics, rec); - return EL_INT(1); -} - -/* trace_span_start(name) — returns a span handle (string of "traceid:spanid:start_nano:name") */ -el_val_t trace_span_start(el_val_t name_v) { - otlp_lazy_init(); - const char* name = EL_CSTR(name_v); if (!name) name = "span"; - /* generate 16-byte trace id and 8-byte span id */ - static _Thread_local int seeded = 0; - if (!seeded) { srand((unsigned int)(uintptr_t)pthread_self() ^ (unsigned int)time(NULL)); seeded = 1; } - char tid[33], sid[17]; - for (int i = 0; i < 32; i++) tid[i] = "0123456789abcdef"[rand() & 0xF]; - tid[32] = '\0'; - for (int i = 0; i < 16; i++) sid[i] = "0123456789abcdef"[rand() & 0xF]; - sid[16] = '\0'; - struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - long long now_nano = (long long)ts.tv_sec * 1000000000LL + ts.tv_nsec; - char* handle = malloc(strlen(name) + 80); - if (!handle) return EL_STR(""); - sprintf(handle, "%s:%s:%lld:%s", tid, sid, now_nano, name); - el_arena_track(handle); - return EL_STR(handle); -} - -/* trace_span_end(handle) — emits the span with computed duration */ -el_val_t trace_span_end(el_val_t handle_v) { - otlp_lazy_init(); - if (!_otlp_endpoint) return EL_INT(0); - const char* h = EL_CSTR(handle_v); if (!h) return EL_INT(0); - /* parse "tid:sid:start_nano:name" */ - char tid[64], sid[32], rest[1024]; - long long start_nano = 0; - if (sscanf(h, "%63[^:]:%31[^:]:%lld:%1023[^\n]", tid, sid, &start_nano, rest) != 4) return EL_INT(0); - struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - long long end_nano = (long long)ts.tv_sec * 1000000000LL + ts.tv_nsec; - char esc_name[1024]; otlp_json_escape(rest, esc_name, sizeof(esc_name)); - char rec[4096]; - int n = snprintf(rec, sizeof(rec), - "{\"traceId\":\"%s\",\"spanId\":\"%s\"," - "\"name\":\"%s\"," - "\"kind\":1," - "\"startTimeUnixNano\":\"%lld\"," - "\"endTimeUnixNano\":\"%lld\"," - "\"status\":{\"code\":1}}", - tid, sid, esc_name, start_nano, end_nano); - if (n > 0 && n < (int)sizeof(rec)) otlp_enqueue(&_otlp_traces, rec); - return EL_INT(1); -} - -/* Convenience: emit a one-shot timed event (emit start+end immediately). - * For El programs that want point events with duration baked in. */ -el_val_t emit_event(el_val_t name_v, el_val_t duration_ms_v) { - otlp_lazy_init(); - if (!_otlp_endpoint) return EL_INT(0); - const char* name = EL_CSTR(name_v); if (!name) name = "event"; - int64_t dur_ms = (int64_t)duration_ms_v; - el_val_t h = trace_span_start(EL_STR((char*)name)); - /* fudge start to be (now - duration) */ - (void)dur_ms; - return trace_span_end(h); -} - -#endif /* HAVE_CURL — OTLP */ - -/* ── Threading seed primitives ─────────────────────────────────────────────── - * __thread_create(fn_name, arg) -> Int spawn El fn in a pthread, return tid - * __thread_join(tid) -> String join thread, return result string - * __mutex_new() -> Int allocate a mutex, return handle - * __mutex_lock(m) lock mutex m - * __mutex_unlock(m) unlock mutex m - * - * Every El fn compiles to a global C symbol. __thread_create uses dlsym to - * look up the function by name and run it in a pthread. This means any El fn - * with signature (String) -> String is directly threadable. - */ - -typedef el_val_t (*ElFn1)(el_val_t); - -typedef struct { - ElFn1 fn; - el_val_t arg; - el_val_t result; -} ElThreadArg; - -#define EL_THREAD_MAX 256 - -typedef struct { - pthread_t tid; - ElThreadArg* arg; - int alive; -} ElThread; - -static ElThread _threads[EL_THREAD_MAX]; -static int _thread_count = 0; -static pthread_mutex_t _thread_alloc_mu = PTHREAD_MUTEX_INITIALIZER; - -static void* el_thread_runner(void* raw) { - ElThreadArg* a = (ElThreadArg*)raw; - a->result = a->fn(a->arg); - return NULL; -} - -el_val_t __thread_create(el_val_t fn_name_v, el_val_t arg_v) { - const char* sym = EL_CSTR(fn_name_v); - if (!sym || !*sym) return EL_INT(-1); - void* p = dlsym(RTLD_DEFAULT, sym); - if (!p) { - fprintf(stderr, "[__thread_create] symbol not found: %s\n", sym); - return EL_INT(-1); - } - ElThreadArg* a = (ElThreadArg*)malloc(sizeof(ElThreadArg)); - if (!a) return EL_INT(-1); - a->fn = (ElFn1)p; - a->arg = arg_v; - a->result = EL_STR(""); - - pthread_mutex_lock(&_thread_alloc_mu); - if (_thread_count >= EL_THREAD_MAX) { - pthread_mutex_unlock(&_thread_alloc_mu); - free(a); - fprintf(stderr, "[__thread_create] thread table full\n"); - return EL_INT(-1); - } - int slot = _thread_count++; - _threads[slot].arg = a; - _threads[slot].alive = 1; - pthread_mutex_unlock(&_thread_alloc_mu); - - if (pthread_create(&_threads[slot].tid, NULL, el_thread_runner, a) != 0) { - pthread_mutex_lock(&_thread_alloc_mu); - _thread_count--; - pthread_mutex_unlock(&_thread_alloc_mu); - free(a); - return EL_INT(-1); - } - return EL_INT(slot); -} - -el_val_t __thread_join(el_val_t tid_v) { - int slot = (int)(int64_t)tid_v; - if (slot < 0 || slot >= EL_THREAD_MAX) return EL_STR(""); - pthread_join(_threads[slot].tid, NULL); - el_val_t result = _threads[slot].arg->result; - free(_threads[slot].arg); - _threads[slot].alive = 0; - return result; -} - -/* Mutex table */ - -#define EL_MUTEX_MAX 64 - -typedef struct { - pthread_mutex_t mu; - int allocated; -} ElMutexEntry; - -static ElMutexEntry _mutexes[EL_MUTEX_MAX]; -static int _mutex_count = 0; -static pthread_mutex_t _mutex_alloc_mu = PTHREAD_MUTEX_INITIALIZER; - -el_val_t __mutex_new(void) { - pthread_mutex_lock(&_mutex_alloc_mu); - if (_mutex_count >= EL_MUTEX_MAX) { - pthread_mutex_unlock(&_mutex_alloc_mu); - fprintf(stderr, "[__mutex_new] mutex table full\n"); - return EL_INT(-1); - } - int slot = _mutex_count++; - pthread_mutex_init(&_mutexes[slot].mu, NULL); - _mutexes[slot].allocated = 1; - pthread_mutex_unlock(&_mutex_alloc_mu); - return EL_INT(slot); -} - -void __mutex_lock(el_val_t m_v) { - int slot = (int)(int64_t)m_v; - if (slot < 0 || slot >= EL_MUTEX_MAX || !_mutexes[slot].allocated) return; - pthread_mutex_lock(&_mutexes[slot].mu); -} - -void __mutex_unlock(el_val_t m_v) { - int slot = (int)(int64_t)m_v; - if (slot < 0 || slot >= EL_MUTEX_MAX || !_mutexes[slot].allocated) return; - pthread_mutex_unlock(&_mutexes[slot].mu); -} - -/* ── Channels ─────────────────────────────────────────────────────────────── * - * Buffered MPMC channel backed by a mutex + condvar + circular buffer. - * channel_new(capacity) -> Int (handle) - * channel_send(ch, msg) — blocks if full (capacity > 0) or never (unbounded) - * channel_recv(ch) -> String — blocks until a message is available - * channel_try_recv(ch) -> String — non-blocking, returns "" if empty - * channel_close(ch) — signal no more sends; recv drains remaining - * - * Bounded channels (cap > 0): circular buffer, sender blocks when full. - * Unbounded channels (cap == 0): dynamic array, sender never blocks. - */ -#define EL_CHANNEL_MAX 64 -#define EL_CHANNEL_BUF 1024 - -typedef struct { - char** buf; - int cap; /* 0 = unbounded (grows dynamically) */ - int head, tail, count; - int dyn_cap; /* allocated slots for unbounded mode */ - int closed; - pthread_mutex_t mu; - pthread_cond_t not_empty; - pthread_cond_t not_full; -} ElChannel; - -static ElChannel _channels[EL_CHANNEL_MAX]; -static int _channel_count = 0; -static pthread_mutex_t _channel_alloc_mu = PTHREAD_MUTEX_INITIALIZER; - -el_val_t __channel_new(el_val_t capacity_v) { - int cap = (int)(int64_t)capacity_v; - if (cap < 0) cap = 0; - - pthread_mutex_lock(&_channel_alloc_mu); - if (_channel_count >= EL_CHANNEL_MAX) { - pthread_mutex_unlock(&_channel_alloc_mu); - fprintf(stderr, "[__channel_new] channel table full\n"); - return EL_INT(-1); - } - int slot = _channel_count++; - pthread_mutex_unlock(&_channel_alloc_mu); - - ElChannel* ch = &_channels[slot]; - memset(ch, 0, sizeof(*ch)); - ch->cap = cap; - ch->closed = 0; - ch->head = 0; - ch->tail = 0; - ch->count = 0; - - if (cap > 0) { - /* Bounded: fixed circular buffer. */ - ch->buf = (char**)malloc((size_t)cap * sizeof(char*)); - ch->dyn_cap = cap; - } else { - /* Unbounded: start with EL_CHANNEL_BUF slots, grow as needed. */ - ch->buf = (char**)malloc(EL_CHANNEL_BUF * sizeof(char*)); - ch->dyn_cap = EL_CHANNEL_BUF; - } - if (!ch->buf) { - fprintf(stderr, "[__channel_new] out of memory\n"); - return EL_INT(-1); - } - - pthread_mutex_init(&ch->mu, NULL); - pthread_cond_init(&ch->not_empty, NULL); - pthread_cond_init(&ch->not_full, NULL); - - return EL_INT(slot); -} - -void __channel_send(el_val_t ch_v, el_val_t msg_v) { - int slot = (int)(int64_t)ch_v; - if (slot < 0 || slot >= EL_CHANNEL_MAX) return; - ElChannel* ch = &_channels[slot]; - - const char* msg = EL_CSTR(msg_v); - if (!msg) msg = ""; - char* copy = strdup(msg); /* channel owns the string */ - - pthread_mutex_lock(&ch->mu); - - if (ch->closed) { - /* Send on closed channel is a no-op (drop the message). */ - pthread_mutex_unlock(&ch->mu); - free(copy); - return; - } - - if (ch->cap > 0) { - /* Bounded: block while full. */ - while (ch->count >= ch->cap && !ch->closed) { - pthread_cond_wait(&ch->not_full, &ch->mu); - } - if (ch->closed) { - pthread_mutex_unlock(&ch->mu); - free(copy); - return; - } - ch->buf[ch->tail] = copy; - ch->tail = (ch->tail + 1) % ch->cap; - ch->count++; - } else { - /* Unbounded: grow the buffer if needed. */ - if (ch->count >= ch->dyn_cap) { - int new_cap = ch->dyn_cap * 2; - char** grown = (char**)realloc(ch->buf, (size_t)new_cap * sizeof(char*)); - if (!grown) { - pthread_mutex_unlock(&ch->mu); - free(copy); - fprintf(stderr, "[__channel_send] out of memory growing channel\n"); - return; - } - /* The circular buffer may have wrapped. Linearise it first. - * In unbounded mode head is always 0 (we append at tail, drain - * from head), so a simple memmove isn't needed — but if the - * buffer did wrap (tail < head after growth), we need to fix up. - * Simplest safe path: if tail wrapped, move the head..old_cap - * segment to new_cap..new_cap+(old_cap-head). */ - if (ch->tail < ch->head) { - /* Wrapped: [head..old_cap) is the front, [0..tail) is the back. */ - int front = ch->dyn_cap - ch->head; - memmove(grown + ch->dyn_cap, grown + ch->head, (size_t)front * sizeof(char*)); - ch->head = ch->dyn_cap; - } - ch->buf = grown; - ch->dyn_cap = new_cap; - } - ch->buf[ch->tail] = copy; - ch->tail = (ch->tail + 1) % ch->dyn_cap; - ch->count++; - } - - pthread_cond_signal(&ch->not_empty); - pthread_mutex_unlock(&ch->mu); -} - -el_val_t __channel_recv(el_val_t ch_v) { - int slot = (int)(int64_t)ch_v; - if (slot < 0 || slot >= EL_CHANNEL_MAX) return EL_STR(""); - ElChannel* ch = &_channels[slot]; - - pthread_mutex_lock(&ch->mu); - - /* Block until there is a message or the channel is closed and drained. */ - while (ch->count == 0 && !ch->closed) { - pthread_cond_wait(&ch->not_empty, &ch->mu); - } - - if (ch->count == 0) { - /* Closed and empty — signal EOF. */ - pthread_mutex_unlock(&ch->mu); - return EL_STR(""); - } - - int buf_cap = (ch->cap > 0) ? ch->cap : ch->dyn_cap; - char* msg = ch->buf[ch->head]; - ch->head = (ch->head + 1) % buf_cap; - ch->count--; - - pthread_cond_signal(&ch->not_full); - pthread_mutex_unlock(&ch->mu); - - /* Hand the string to the arena so it is freed after the request. */ - el_arena_track(msg); - return EL_STR(msg); -} - -el_val_t __channel_try_recv(el_val_t ch_v) { - int slot = (int)(int64_t)ch_v; - if (slot < 0 || slot >= EL_CHANNEL_MAX) return EL_STR(""); - ElChannel* ch = &_channels[slot]; - - pthread_mutex_lock(&ch->mu); - - if (ch->count == 0) { - pthread_mutex_unlock(&ch->mu); - return EL_STR(""); - } - - int buf_cap = (ch->cap > 0) ? ch->cap : ch->dyn_cap; - char* msg = ch->buf[ch->head]; - ch->head = (ch->head + 1) % buf_cap; - ch->count--; - - pthread_cond_signal(&ch->not_full); - pthread_mutex_unlock(&ch->mu); - - el_arena_track(msg); - return EL_STR(msg); -} - -void __channel_close(el_val_t ch_v) { - int slot = (int)(int64_t)ch_v; - if (slot < 0 || slot >= EL_CHANNEL_MAX) return; - ElChannel* ch = &_channels[slot]; - - pthread_mutex_lock(&ch->mu); - ch->closed = 1; - /* Wake all blocked recvers and senders so they can observe the close. */ - pthread_cond_broadcast(&ch->not_empty); - pthread_cond_broadcast(&ch->not_full); - pthread_mutex_unlock(&ch->mu); -} - -/* ── DHARMA runtime additions ──────────────────────────────────────────────── - * - * Functions required by the dharma registry service. Added here so the - * released el_runtime.c includes them without requiring dharma to bundle - * its own stubs. - * - * Functions added: - * list_len — alias for el_list_len (used in handlers.el) - * list_get — alias for el_list_get (used in handlers.el) - * json_array_push — append a pre-encoded JSON element to a JSON array string - * now_millis — milliseconds since Unix epoch (alias for time_now) - * unix_timestamp_ms — same as now_millis (alias) - * time_now_ms — same as now_millis (alias) - * log_info — stderr structured log at INFO level - * log_warn — stderr structured log at WARN level - * config — reads a config value from the environment - * http_patch — HTTP PATCH with JSON Content-Type - * http_post_engram — HTTP POST with optional X-API-Key header - * http_get_engram — HTTP GET with optional X-API-Key header - * str_to_bytes — encode a string as a JSON array of byte values - * bytes_to_str — decode a JSON array of byte values back to a string - * hash_sha256 — SHA-256 hex digest of a string - */ - -/* list_len — return the number of elements in a list. */ -el_val_t list_len(el_val_t list) { - return el_list_len(list); -} - -/* list_get — return the element at index i in a list. */ -el_val_t list_get(el_val_t list, el_val_t index) { - return el_list_get(list, index); -} - -/* json_array_push — append element (a pre-encoded JSON fragment, e.g. "\"foo\"" - * or "42") to the JSON array string arr. Returns a new JSON array string. - * Example: json_array_push("[]", "\"alice\"") -> "[\"alice\"]" - * json_array_push("[\"alice\"]", "\"bob\"") -> "[\"alice\",\"bob\"]" */ -el_val_t json_array_push(el_val_t arr_v, el_val_t elem_v) { - const char* arr = EL_CSTR(arr_v); - const char* elem = EL_CSTR(elem_v); - if (!arr || !*arr) arr = "[]"; - if (!elem || !*elem) elem = "null"; - - /* Trim whitespace, find the closing ']'. */ - const char* p = arr; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') { - /* Not an array — return a single-element array. */ - size_t n = strlen(elem) + 4; - char* out = el_strbuf(n); - snprintf(out, n, "[%s]", elem); - return el_wrap_str(out); - } - size_t arr_len = strlen(arr); - size_t elem_len = strlen(elem); - - /* Walk from the end to find the matching ']'. */ - const char* end = arr + arr_len - 1; - while (end > p && (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r')) end--; - if (*end != ']') { - /* Malformed — wrap elem in a new array. */ - size_t n = elem_len + 4; - char* out = el_strbuf(n); - snprintf(out, n, "[%s]", elem); - return el_wrap_str(out); - } - - /* Content between '[' and ']'. */ - const char* inner_start = p + 1; - const char* inner_end = end; /* points AT ']' */ - /* Check if the array is empty (only whitespace between brackets). */ - const char* q = inner_start; - while (q < inner_end && (*q == ' ' || *q == '\t' || *q == '\n' || *q == '\r')) q++; - int empty = (q == inner_end); - - /* Build: prefix + (comma if non-empty) + elem + "]" */ - size_t prefix_len = (size_t)(inner_end - arr); /* up to but not including ']' */ - size_t sep_len = empty ? 0 : 1; /* "," if non-empty */ - size_t out_len = prefix_len + sep_len + elem_len + 2; /* +"]" + NUL */ - char* out = el_strbuf(out_len); - memcpy(out, arr, prefix_len); - if (!empty) out[prefix_len] = ','; - memcpy(out + prefix_len + sep_len, elem, elem_len); - out[prefix_len + sep_len + elem_len] = ']'; - out[prefix_len + sep_len + elem_len + 1] = '\0'; - return el_wrap_str(out); -} - -/* now_millis — milliseconds since Unix epoch. */ -el_val_t now_millis(void) { - return time_now(); -} - -/* unix_timestamp_ms — same as now_millis. */ -el_val_t unix_timestamp_ms(void) { - return time_now(); -} - -/* time_now_ms — same as now_millis. */ -el_val_t time_now_ms(void) { - return time_now(); -} - -/* log_info — write a structured [INFO] line to stderr. */ -void log_info(el_val_t msg_v) { - const char* msg = EL_CSTR(msg_v); - fprintf(stderr, "[INFO] %s\n", msg ? msg : ""); -} - -/* log_warn — write a structured [WARN] line to stderr. */ -void log_warn(el_val_t msg_v) { - const char* msg = EL_CSTR(msg_v); - fprintf(stderr, "[WARN] %s\n", msg ? msg : ""); -} - -/* config — read a configuration value from the environment. - * Returns "" if the variable is not set (same as __env_get). */ -el_val_t config(el_val_t key_v) { - const char* key = EL_CSTR(key_v); - if (!key || !*key) return EL_STR(""); - const char* val = getenv(key); - if (!val) return EL_STR(""); - return el_wrap_str(el_strdup(val)); -} - -#ifdef HAVE_CURL -/* http_patch — HTTP PATCH request with Content-Type: application/json. - * Returns the response body (same error convention as http_post_json). */ -el_val_t http_patch(el_val_t url_v, el_val_t body_v) { - const char* url = EL_CSTR(url_v); - const char* body = EL_CSTR(body_v); - if (!url || !*url) return http_error_json("empty url"); - CURL* c = curl_easy_init(); - if (!c) return http_error_json("curl_easy_init failed"); - HttpBuf rb; httpbuf_init(&rb); - char errbuf[CURL_ERROR_SIZE]; errbuf[0] = '\0'; - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - curl_easy_setopt(c, CURLOPT_URL, url); - curl_easy_setopt(c, CURLOPT_CUSTOMREQUEST, "PATCH"); - curl_easy_setopt(c, CURLOPT_POSTFIELDS, body ? body : ""); - curl_easy_setopt(c, CURLOPT_POSTFIELDSIZE, (long)(body ? strlen(body) : 0)); - curl_easy_setopt(c, CURLOPT_HTTPHEADER, h); - curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, http_write_cb); - curl_easy_setopt(c, CURLOPT_WRITEDATA, &rb); - curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(c, CURLOPT_TIMEOUT_MS, el_http_timeout_ms()); - curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(c, CURLOPT_ERRORBUFFER, errbuf); - curl_easy_setopt(c, CURLOPT_USERAGENT, "el-runtime/1.0"); - CURLcode rc = curl_easy_perform(c); - curl_slist_free_all(h); - curl_easy_cleanup(c); - if (rc != CURLE_OK) { - free(rb.data); - const char* m = errbuf[0] ? errbuf : curl_easy_strerror(rc); - return http_error_json(m); - } - return el_wrap_str(rb.data); -} - -/* http_post_engram — HTTP POST with optional X-API-Key header. - * If key is "" no authentication header is sent. */ -el_val_t http_post_engram(el_val_t url_v, el_val_t key_v, el_val_t body_v) { - const char* url = EL_CSTR(url_v); - const char* key = EL_CSTR(key_v); - const char* body = EL_CSTR(body_v); - if (!url || !*url) return http_error_json("empty url"); - CURL* c = curl_easy_init(); - if (!c) return http_error_json("curl_easy_init failed"); - HttpBuf rb; httpbuf_init(&rb); - char errbuf[CURL_ERROR_SIZE]; errbuf[0] = '\0'; - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - if (key && *key) { - size_t n = strlen(key) + 32; - char* hdr = malloc(n); - snprintf(hdr, n, "X-API-Key: %s", key); - h = curl_slist_append(h, hdr); - free(hdr); - } - curl_easy_setopt(c, CURLOPT_URL, url); - curl_easy_setopt(c, CURLOPT_POST, 1L); - curl_easy_setopt(c, CURLOPT_POSTFIELDS, body ? body : ""); - curl_easy_setopt(c, CURLOPT_POSTFIELDSIZE, (long)(body ? strlen(body) : 0)); - curl_easy_setopt(c, CURLOPT_HTTPHEADER, h); - curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, http_write_cb); - curl_easy_setopt(c, CURLOPT_WRITEDATA, &rb); - curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(c, CURLOPT_TIMEOUT_MS, el_http_timeout_ms()); - curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(c, CURLOPT_ERRORBUFFER, errbuf); - curl_easy_setopt(c, CURLOPT_USERAGENT, "el-runtime/1.0"); - CURLcode rc = curl_easy_perform(c); - curl_slist_free_all(h); - curl_easy_cleanup(c); - if (rc != CURLE_OK) { - free(rb.data); - const char* m = errbuf[0] ? errbuf : curl_easy_strerror(rc); - return http_error_json(m); - } - return el_wrap_str(rb.data); -} - -/* http_get_engram — HTTP GET with optional X-API-Key header. */ -el_val_t http_get_engram(el_val_t url_v, el_val_t key_v) { - const char* url = EL_CSTR(url_v); - const char* key = EL_CSTR(key_v); - if (!url || !*url) return http_error_json("empty url"); - CURL* c = curl_easy_init(); - if (!c) return http_error_json("curl_easy_init failed"); - HttpBuf rb; httpbuf_init(&rb); - char errbuf[CURL_ERROR_SIZE]; errbuf[0] = '\0'; - struct curl_slist* h = NULL; - if (key && *key) { - size_t n = strlen(key) + 32; - char* hdr = malloc(n); - snprintf(hdr, n, "X-API-Key: %s", key); - h = curl_slist_append(h, hdr); - free(hdr); - } - curl_easy_setopt(c, CURLOPT_URL, url); - curl_easy_setopt(c, CURLOPT_HTTPGET, 1L); - if (h) curl_easy_setopt(c, CURLOPT_HTTPHEADER, h); - curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, http_write_cb); - curl_easy_setopt(c, CURLOPT_WRITEDATA, &rb); - curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(c, CURLOPT_TIMEOUT_MS, el_http_timeout_ms()); - curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(c, CURLOPT_ERRORBUFFER, errbuf); - curl_easy_setopt(c, CURLOPT_USERAGENT, "el-runtime/1.0"); - CURLcode rc = curl_easy_perform(c); - if (h) curl_slist_free_all(h); - curl_easy_cleanup(c); - if (rc != CURLE_OK) { - free(rb.data); - const char* m = errbuf[0] ? errbuf : curl_easy_strerror(rc); - return http_error_json(m); - } - return el_wrap_str(rb.data); -} -#endif /* HAVE_CURL */ - -/* str_to_bytes — encode a string as a JSON array of unsigned byte values. - * "hello" -> "[104,101,108,108,111]" - * Used by db.el to store binary content in Engram JSON nodes. */ -el_val_t str_to_bytes(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s || !*s) return el_wrap_str(el_strdup("[]")); - size_t n = strlen(s); - /* Worst case: each byte is 3 digits + comma = 4 chars, plus "[]" + NUL. */ - char* out = el_strbuf(n * 4 + 3); - size_t pos = 0; - out[pos++] = '['; - for (size_t i = 0; i < n; i++) { - unsigned char b = (unsigned char)s[i]; - if (i > 0) out[pos++] = ','; - /* Write decimal representation of b. */ - if (b >= 100) { - out[pos++] = (char)('0' + b / 100); - out[pos++] = (char)('0' + (b / 10) % 10); - out[pos++] = (char)('0' + b % 10); - } else if (b >= 10) { - out[pos++] = (char)('0' + b / 10); - out[pos++] = (char)('0' + b % 10); - } else { - out[pos++] = (char)('0' + b); - } - } - out[pos++] = ']'; - out[pos] = '\0'; - return el_wrap_str(out); -} - -/* bytes_to_str — decode a JSON array of integer byte values back to a string. - * "[104,101,108,108,111]" -> "hello" - * Inverse of str_to_bytes. */ -el_val_t bytes_to_str(el_val_t arr_v) { - const char* s = EL_CSTR(arr_v); - if (!s) return el_wrap_str(el_strdup("")); - /* Skip whitespace, expect '['. */ - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s != '[') return el_wrap_str(el_strdup("")); - s++; - - /* Count elements to size the output buffer. */ - int64_t n = (int64_t)json_array_len(arr_v); - if (n <= 0) return el_wrap_str(el_strdup("")); - - char* out = el_strbuf((size_t)n + 1); - size_t pos = 0; - - /* Walk the array, parse each integer, store as a byte. */ - while (*s) { - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ']' || *s == '\0') break; - /* Parse decimal integer. */ - char* end_ptr; - long v = strtol(s, &end_ptr, 10); - if (end_ptr == s) break; /* parse failure */ - s = end_ptr; - if (v >= 0 && v <= 255) out[pos++] = (char)(unsigned char)v; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ',') { s++; continue; } - if (*s == ']' || *s == '\0') break; - } - out[pos] = '\0'; - return el_wrap_str(out); -} - -/* hash_sha256 — return the SHA-256 hex digest of a string. - * Uses the built-in el_sha256_oneshot implementation (no OpenSSL required). */ -el_val_t hash_sha256(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) s = ""; - unsigned char digest[32]; - el_sha256_oneshot((const unsigned char*)s, strlen(s), digest); - return el_hex_encode(digest, 32); -} - -/* ── __ prefixed aliases — public boundary for compiled El programs ────────── - * - * The El compiler's self-hosting back-end emits calls to __-prefixed function - * names (e.g. __println, __str_len). These wrappers forward to the existing - * el_runtime implementations so both naming conventions resolve at link time. - * - * Note: __thread_create and __thread_join are already defined above in the - * threading section; they are not repeated here. - * ──────────────────────────────────────────────────────────────────────────── */ - -/* I/O */ -el_val_t __println(el_val_t s) { return println(s); } -el_val_t __print(el_val_t s) { return print(s); } -el_val_t __readline(void) { return readline(); } - -/* String */ -el_val_t __int_to_str(el_val_t n) { return int_to_str(n); } -el_val_t __str_to_int(el_val_t s) { return str_to_int(s); } -el_val_t __float_to_str(el_val_t f) { return float_to_str(f); } -el_val_t __str_to_float(el_val_t s) { return str_to_float(s); } -el_val_t __str_len(el_val_t s) { return str_len(s); } -el_val_t __str_char_at(el_val_t s, el_val_t i) { return str_char_at(s, i); } - -el_val_t __str_cmp(el_val_t a, el_val_t b) { - const char* ca = EL_CSTR(a); - const char* cb = EL_CSTR(b); - if (!ca) ca = ""; - if (!cb) cb = ""; - return (el_val_t)strcmp(ca, cb); -} - -el_val_t __str_ncmp(el_val_t a, el_val_t b, el_val_t n) { - const char* ca = EL_CSTR(a); - const char* cb = EL_CSTR(b); - if (!ca) ca = ""; - if (!cb) cb = ""; - return (el_val_t)strncmp(ca, cb, (size_t)n); -} - -el_val_t __str_concat_raw(el_val_t a, el_val_t b) { return str_concat(a, b); } -el_val_t __str_slice_raw(el_val_t s, el_val_t start, el_val_t end) { return str_slice(s, start, end); } - -el_val_t __str_alloc(el_val_t n) { - if (n <= 0) n = 0; - char* buf = el_strbuf((size_t)n + 1); - memset(buf, 0, (size_t)n + 1); - return el_wrap_str(buf); -} - -el_val_t __str_set_char(el_val_t s, el_val_t i, el_val_t c) { - char* buf = (char*)(uintptr_t)s; - if (buf) buf[(size_t)i] = (char)c; - return s; -} - -/* URL encoding */ -el_val_t __url_encode(el_val_t s) { return url_encode(s); } -el_val_t __url_decode(el_val_t s) { return url_decode(s); } - -/* Environment */ -el_val_t __env_get(el_val_t key) { return env(key); } - -/* Subprocess */ -el_val_t __exec(el_val_t cmd) { return exec(cmd); } -el_val_t __exec_bg(el_val_t cmd) { return exec_bg(cmd); } - -/* Process */ -el_val_t __exit_program(el_val_t code) { return exit_program(code); } - -/* Filesystem */ -el_val_t __fs_exists(el_val_t path) { return fs_exists(path); } -el_val_t __fs_mkdir(el_val_t path) { return fs_mkdir(path); } -el_val_t __fs_read(el_val_t path) { return fs_read(path); } -el_val_t __fs_write(el_val_t path, el_val_t content) { return fs_write(path, content); } -el_val_t __fs_write_bytes(el_val_t path, el_val_t bytes, el_val_t n) { return fs_write_bytes(path, bytes, n); } -el_val_t __fs_list_raw(el_val_t path) { return fs_list_json(path); } - -/* HTTP server (no curl dependency) */ -el_val_t __http_response(el_val_t status, el_val_t headers_json, el_val_t body) { return http_response(status, headers_json, body); } -el_val_t __http_serve(el_val_t port, el_val_t handler) { return http_serve(port, handler); } -el_val_t __http_serve_v2(el_val_t port, el_val_t handler) { return http_serve_v2(port, handler); } - -/* HTTP conn fd / SSE — __http_conn_fd lives in el_seed.c; stubs provided here - * so el_runtime.c compiles standalone. When both translation units are linked - * the el_seed.c definitions win via their non-static linkage (strong symbols). - * These stubs are marked weak so they are silently overridden. */ -__attribute__((weak)) el_val_t __http_conn_fd(void) { return (el_val_t)(-1); } -__attribute__((weak)) el_val_t __http_sse_open(el_val_t conn_id) { (void)conn_id; return 0; } -__attribute__((weak)) el_val_t __http_sse_send(el_val_t conn_id, el_val_t data) { (void)conn_id; (void)data; return 0; } -__attribute__((weak)) el_val_t __http_sse_close(el_val_t conn_id) { (void)conn_id; return 0; } - -/* JSON */ -el_val_t __json_array_get(el_val_t json, el_val_t index) { return json_array_get(json, index); } -el_val_t __json_array_get_string(el_val_t json, el_val_t index) { return json_array_get_string(json, index); } -el_val_t __json_array_len(el_val_t json) { return json_array_len(json); } -el_val_t __json_get(el_val_t json, el_val_t key) { return json_get(json, key); } -el_val_t __json_get_raw(el_val_t json, el_val_t key) { return json_get_raw(json, key); } -el_val_t __json_set(el_val_t json, el_val_t key, el_val_t value){ return json_set(json, key, value); } -el_val_t __json_parse_map(el_val_t json_str) { return json_parse(json_str); } -el_val_t __json_stringify_val(el_val_t val) { return json_stringify(val); } - -/* Hashing */ -el_val_t __sha256_hex(el_val_t s) { return hash_sha256(s); } - -/* State K/V */ -el_val_t __state_del(el_val_t key) { return state_del(key); } -el_val_t __state_get(el_val_t key) { return state_get(key); } -el_val_t __state_keys(void) { return state_keys(); } -el_val_t __state_set(el_val_t key, el_val_t val) { return state_set(key, val); } - -/* UUID */ -el_val_t __uuid_v4(void) { return uuid_v4(); } - -/* Args */ -el_val_t __args_json(void) { return args(); } - -/* HTTP client aliases — require curl; defined inside #ifdef HAVE_CURL below - * with a matching stub in the #ifndef HAVE_CURL block. */ -#ifdef HAVE_CURL -el_val_t __http_do(el_val_t method, el_val_t url, el_val_t body, - el_val_t headers_map, el_val_t timeout_ms) { - /* timeout_ms is accepted for API compatibility but ignored here; - * el_runtime's http_do uses the EL_HTTP_TIMEOUT_MS env var instead. */ - (void)timeout_ms; - struct curl_slist* h = headers_from_map(headers_map); - el_val_t r = http_do(EL_CSTR(method), EL_CSTR(url), EL_CSTR(body), h); - if (h) curl_slist_free_all(h); - return r; -} - -/* __http_do_map — same as __http_do but headers_map arg is a JSON-string - * rather than an ElMap. Parse it first, then delegate. */ -el_val_t __http_do_map(el_val_t method, el_val_t url, el_val_t body, - el_val_t headers_json, el_val_t timeout_ms) { - (void)timeout_ms; - /* Build a curl_slist from a JSON object {"Header":"value",...}. */ - const char* hj = EL_CSTR(headers_json); - struct curl_slist* h = NULL; - if (hj && *hj && *hj == '{') { - /* Walk the JSON pairs with a simple parser reusing json_get_string logic. */ - /* For correctness we just call the existing json_get iteration path. - * We duplicate the key-extraction loop from headers_from_map but driven - * by JSON rather than ElMap. Use json_get_raw to iterate is not easy - * without knowing keys, so accept the JSON string and build a tmp map. */ - el_val_t map = json_parse(EL_STR(hj)); - h = headers_from_map(map); - } - el_val_t r = http_do(EL_CSTR(method), EL_CSTR(url), EL_CSTR(body), h); - if (h) curl_slist_free_all(h); - return r; -} - -/* __http_do_map_to_file — same as __http_do_map but streams response body - * to a local file path rather than returning it as a string. */ -el_val_t __http_do_map_to_file(el_val_t method, el_val_t url, el_val_t body, - el_val_t headers_json, el_val_t output_path) { - const char* hj = EL_CSTR(headers_json); - struct curl_slist* h = NULL; - if (hj && *hj && *hj == '{') { - el_val_t map = json_parse(EL_STR(hj)); - h = headers_from_map(map); - } - el_val_t r = http_do_to_file(EL_CSTR(method), EL_CSTR(url), EL_CSTR(body), - h, EL_CSTR(output_path)); - if (h) curl_slist_free_all(h); - return r; -} -#endif /* HAVE_CURL */ - -#ifndef HAVE_CURL -/* ── HAVE_CURL=0 stubs — compile without -lcurl for the elc CLI binary. ───── * - * These return a JSON error string so El programs get a clear message if they - * call HTTP/LLM functions in a curl-less build. */ -static el_val_t _no_curl_err(void) { - return el_wrap_str(el_strdup("{\"error\":\"not built with HAVE_CURL\"}")); -} -el_val_t http_get(el_val_t url) { (void)url; return _no_curl_err(); } -el_val_t http_post(el_val_t url, el_val_t body) { (void)url; (void)body; return _no_curl_err(); } -el_val_t http_post_json(el_val_t url, el_val_t body) { (void)url; (void)body; return _no_curl_err(); } -el_val_t http_get_with_headers(el_val_t url, el_val_t h) { (void)url; (void)h; return _no_curl_err(); } -el_val_t http_post_with_headers(el_val_t url, el_val_t b, el_val_t h) { (void)url; (void)b; (void)h; return _no_curl_err(); } -el_val_t http_post_json_with_headers(el_val_t url, el_val_t h, el_val_t b) { (void)url; (void)h; (void)b; return _no_curl_err(); } -el_val_t http_post_form_auth(el_val_t url, el_val_t b, el_val_t a) { (void)url; (void)b; (void)a; return _no_curl_err(); } -el_val_t http_delete(el_val_t url) { (void)url; return _no_curl_err(); } -el_val_t http_patch(el_val_t url, el_val_t body) { (void)url; (void)body; return _no_curl_err(); } -el_val_t http_get_to_file(el_val_t url, el_val_t h, el_val_t p) { (void)url; (void)h; (void)p; return _no_curl_err(); } -el_val_t http_post_to_file(el_val_t url, el_val_t b, el_val_t h, el_val_t p) { (void)url; (void)b; (void)h; (void)p; return _no_curl_err(); } -el_val_t http_post_engram(el_val_t url, el_val_t k, el_val_t b) { (void)url; (void)k; (void)b; return _no_curl_err(); } -el_val_t http_get_engram(el_val_t url, el_val_t k) { (void)url; (void)k; return _no_curl_err(); } -el_val_t llm_call(el_val_t m, el_val_t p) { (void)m; (void)p; return _no_curl_err(); } -el_val_t llm_call_system(el_val_t m, el_val_t s, el_val_t u) { (void)m; (void)s; (void)u; return _no_curl_err(); } -el_val_t llm_call_agentic(el_val_t m, el_val_t s, el_val_t u, el_val_t t) { (void)m; (void)s; (void)u; (void)t; return _no_curl_err(); } -el_val_t llm_vision(el_val_t m, el_val_t s, el_val_t p, el_val_t i) { (void)m; (void)s; (void)p; (void)i; return _no_curl_err(); } -el_val_t llm_models(void) { return el_list_empty(); } -void llm_register_tool(el_val_t n, el_val_t f) { (void)n; (void)f; } -/* __ HTTP stubs (no-curl build) */ -el_val_t __http_do(el_val_t m, el_val_t u, el_val_t b, el_val_t h, el_val_t t) { (void)m; (void)u; (void)b; (void)h; (void)t; return _no_curl_err(); } -el_val_t __http_do_map(el_val_t m, el_val_t u, el_val_t b, el_val_t h, el_val_t t) { (void)m; (void)u; (void)b; (void)h; (void)t; return _no_curl_err(); } -el_val_t __http_do_map_to_file(el_val_t m, el_val_t u, el_val_t b, el_val_t h, el_val_t p) { (void)m; (void)u; (void)b; (void)h; (void)p; return _no_curl_err(); } -#endif /* !HAVE_CURL */ diff --git a/lang/el-compiler/runtime/el_runtime.h b/lang/el-compiler/runtime/el_runtime.h deleted file mode 100644 index 87348f5..0000000 --- a/lang/el-compiler/runtime/el_runtime.h +++ /dev/null @@ -1,897 +0,0 @@ -/* - * el_runtime.h — El language C runtime header - * - * Declares all built-in functions available to compiled El programs. - * Include this in every generated .c file. - * - * Value model: - * All El values are represented as el_val_t (= int64_t). - * On 64-bit systems a pointer fits in int64_t. - * String values are cast: (el_val_t)(uintptr_t)"hello" - * Integer values are stored directly. - * This lets arithmetic work naturally while still passing strings around. - * - * Type conventions (El -> C): - * String -> el_val_t (holds const char* via uintptr_t cast) - * Int -> el_val_t - * Bool -> el_val_t (0 = false, nonzero = true) - * Any -> el_val_t - * Void -> void - * - * Macros for convenience: - * EL_STR(s) cast string literal to el_val_t - * EL_CSTR(v) cast el_val_t back to const char* - * EL_INT(v) identity — el_val_t is already int64_t - * EL_NULL null / zero value - * EL_FALSE boolean false (0) - * EL_TRUE boolean true (1) - * - * Link requirements: - * -lcurl — required for the HTTP client (http_get, http_post, llm_*). - * -lpthread — required for the HTTP server (one detached thread per - * connection, capped at 64 concurrent). - * -loqs — optional; required only when liboqs is installed and the - * pq_* / sha3_256_hex entry points are needed. Detected at - * compile time via __has_include(). - * -lcrypto — optional; pulled in alongside -loqs. Used for X25519 in - * pq_hybrid_* and HKDF-SHA256 derivation. - * - * Canonical compile command: - * cc -std=c11 -I el-compiler/runtime -lcurl -lpthread \ - * -o .c el-compiler/runtime/el_runtime.c - * - * With liboqs (post-quantum stack): - * cc -std=c11 -I el-compiler/runtime -lcurl -lpthread -loqs -lcrypto \ - * -o .c el-compiler/runtime/el_runtime.c - */ - -#pragma once - -#include -#include - -typedef int64_t el_val_t; - -/* HTTP request-handler function-pointer types. Public because soul modules (routes/chat/etc.) - * register handlers across translation units; previously defined only inside el_runtime.c, which - * made cross-module references (and the Windows build) fail. Home in the shared header. */ -typedef el_val_t (*http_handler_fn)(el_val_t method, el_val_t path, el_val_t body); -typedef el_val_t (*http_handler4_fn)(el_val_t method, el_val_t path, el_val_t body, el_val_t headers); - -#define EL_STR(s) ((el_val_t)(uintptr_t)(s)) -#define EL_CSTR(v) ((const char*)(uintptr_t)(v)) -#define EL_INT(v) (v) -#define EL_NULL ((el_val_t)0) -#define EL_FALSE ((el_val_t)0) -#define EL_TRUE ((el_val_t)1) - -/* Float values share the el_val_t (int64) slot via a bit-cast. - * The codegen emits Float literals as `el_from_float()` so the - * underlying bits represent the IEEE 754 double. Float-aware builtins - * (math, format, json) round-trip via these helpers. */ -static inline double el_to_float(el_val_t v) { - union { int64_t i; double f; } u; - u.i = (int64_t)v; - return u.f; -} - -static inline el_val_t el_from_float(double f) { - union { double f; int64_t i; } u; - u.f = f; - return (el_val_t)u.i; -} - -#ifdef __cplusplus -extern "C" { -#endif - -/* ── I/O ──────────────────────────────────────────────────────────────────── */ - -el_val_t println(el_val_t s); -el_val_t print(el_val_t s); -el_val_t readline(void); - -/* ── String builtins ─────────────────────────────────────────────────────── */ - -el_val_t el_str_concat(el_val_t a, el_val_t b); -el_val_t str_eq(el_val_t a, el_val_t b); -el_val_t str_starts_with(el_val_t s, el_val_t prefix); -el_val_t str_ends_with(el_val_t s, el_val_t suffix); -el_val_t str_len(el_val_t s); -el_val_t str_concat(el_val_t a, el_val_t b); -el_val_t int_to_str(el_val_t n); -el_val_t str_to_int(el_val_t s); -el_val_t native_str_to_int(el_val_t s); -el_val_t str_slice(el_val_t s, el_val_t start, el_val_t end); -el_val_t str_contains(el_val_t s, el_val_t sub); -el_val_t str_replace(el_val_t s, el_val_t from, el_val_t to); -el_val_t str_to_upper(el_val_t s); -el_val_t str_to_lower(el_val_t s); -el_val_t str_trim(el_val_t s); - -/* ── Math ────────────────────────────────────────────────────────────────── */ - -el_val_t el_abs(el_val_t n); -el_val_t el_max(el_val_t a, el_val_t b); -el_val_t el_min(el_val_t a, el_val_t b); - -/* ── Refcount (ARC) ────────────────────────────────────────────────────────── - * Lists and Maps carry a refcount. Strings and ints do not — el_retain and - * el_release are safe no-ops on non-refcounted values (they sniff a magic - * header at offset 0 and only act if the magic matches). - * - * Codegen emits these at let-binding shadowing, function entry (params), and - * function exit (locals other than the returned value). The refcount lets - * el_list_append and el_map_set mutate in place when uniquely owned (cheap) - * and copy-on-write when shared (preserves persistent semantics across - * accumulator patterns in the compiler itself). */ - -void el_retain(el_val_t v); -void el_release(el_val_t v); - -/* ── Scoped arena (CLI use) ───────────────────────────────────────────────── */ -el_val_t el_arena_push(void); -el_val_t el_arena_pop(el_val_t mark); - -/* ── List ────────────────────────────────────────────────────────────────── */ - -el_val_t el_list_new(el_val_t count, ...); -el_val_t el_list_len(el_val_t list); -el_val_t el_list_get(el_val_t list, el_val_t index); -el_val_t el_list_append(el_val_t list, el_val_t elem); -el_val_t el_list_empty(void); -el_val_t el_list_clone(el_val_t list); - -/* ── Map ─────────────────────────────────────────────────────────────────── */ - -el_val_t el_map_new(el_val_t pair_count, ...); -el_val_t el_get_field(el_val_t map, el_val_t key); -el_val_t el_map_get(el_val_t map, el_val_t key); -el_val_t el_map_set(el_val_t map, el_val_t key, el_val_t value); - -/* ── HTTP ─────────────────────────────────────────────────────────────────── */ - -el_val_t http_get(el_val_t url); -el_val_t http_post(el_val_t url, el_val_t body); -el_val_t http_post_json(el_val_t url, el_val_t json_body); -el_val_t http_get_with_headers(el_val_t url, el_val_t headers_map); -el_val_t http_post_with_headers(el_val_t url, el_val_t body, el_val_t headers_map); -el_val_t http_post_json_with_headers(el_val_t url, el_val_t headers_map, el_val_t json_body); -el_val_t http_post_form_auth(el_val_t url, el_val_t form_body, el_val_t auth_header); -el_val_t http_delete(el_val_t url); -el_val_t http_serve(el_val_t port, el_val_t handler); -el_val_t http_set_handler(el_val_t name); - -/* HTTP server v2 ───────────────────────────────────────────────────────────── - * Same dispatch model as http_serve, but the handler signature is widened: - * - * el_val_t handler(method, path, headers_map, body) - * - * `headers_map` is an ElMap from lowercased header name → header value (both - * Strings). Repeated headers are joined with ", " per RFC 7230. - * - * Response value: the handler may return either - * (a) a plain body string — same auto-content-type / 200-OK behaviour as - * http_serve (3-arg) — or - * (b) a response envelope built with `http_response(status, headers_json, - * body)`. The runtime detects the envelope discriminator - * `"el_http_response":1` at the start of the returned string and - * unpacks status / headers / body before sending. - * - * The 3-arg http_serve(port, handler) remains supported unchanged for - * existing handlers (e.g. products/web/server.el): it dispatches with - * (method, path, body), hardcodes 200 OK, and auto-detects content type. */ -el_val_t http_serve_v2(el_val_t port, el_val_t handler); -void http_serve_async(el_val_t port, el_val_t handler); -el_val_t http_set_handler_v2(el_val_t name); - -/* Build an HTTP response envelope. `headers_json` should be a JSON object - * literal like `{"WWW-Authenticate":"Basic"}` (or "" / "{}" for none). The - * returned string carries the discriminator `{"el_http_response":1,...}` - * which the runtime's send-path detects and unpacks. Detection happens - * uniformly inside http_send_response, so a 3-arg handler may also return - * an envelope. The 3-arg variant remains documented as a fixed 200-OK - * auto-content-type contract for legacy handlers that return plain bodies. */ -el_val_t http_response(el_val_t status, el_val_t headers_json, el_val_t body); - -/* SSE connection fd — set by http_worker_v2 before calling the El handler, - * cleared afterwards. Defined in el_seed.c; called from el_runtime.c. - * The getter is exposed as __http_conn_fd() to El programs. */ -void el_seed_set_http_conn_fd(int fd); - -/* HTTP timeout — every libcurl request honors EL_HTTP_TIMEOUT_MS (default - * 60000ms). Read lazily on first use, so setting the env var any time before - * the first http_* call is sufficient. */ - -/* Streaming variants — write the response body straight to a file via - * libcurl's CURLOPT_WRITEFUNCTION = fwrite. These bypass the el_val_t string - * wrapper entirely, so binary payloads (audio/mpeg, image/png, etc.) survive - * embedded NUL bytes that would truncate a strlen()-based code path. - * - * Both honor EL_HTTP_TIMEOUT_MS, follow redirects, and accept the same - * `headers_map` shape as http_post_with_headers (ElMap of String→String). - * - * Return value: 1 on success (file fully written), 0 on any failure - * (network, file open, partial write). On failure the output file is removed - * so callers cannot mistake a partially-written file for a valid one. */ -el_val_t http_post_to_file(el_val_t url, el_val_t body, el_val_t headers_map, el_val_t output_path); -el_val_t http_get_to_file(el_val_t url, el_val_t headers_map, el_val_t output_path); - -/* ── URL encoding ────────────────────────────────────────────────────────── */ - -el_val_t url_encode(el_val_t s); /* RFC 3986 unreserved set */ -el_val_t url_decode(el_val_t s); /* '+' → space, %XX → byte */ - -/* ── HTML allowlist sanitizer ──────────────────────────────────────────────── - * el_html_sanitize(input_html, allowlist_json) — strict allowlist HTML - * cleaner. State-machine parser; tag/attribute names compared case- - * insensitively against the allowlist; `` / `<… src>` URL schemes - * validated (http, https, mailto, fragment-only, or relative); whole- - * subtree drop for script / style / iframe / object / embed / form; HTML- - * escapes free text outside dropped subtrees. - * - * The allowlist is JSON of the form - * {"p":[],"a":["href","title"],"strong":[],...} - * where each value is the array of attribute names allowed for that tag. */ -el_val_t el_html_sanitize(el_val_t input_html, el_val_t allowlist_json); -el_val_t html_raw(el_val_t s); -el_val_t html_escape(el_val_t s); - -/* ── Filesystem ──────────────────────────────────────────────────────────── */ - -el_val_t fs_read(el_val_t path); -el_val_t fs_write(el_val_t path, el_val_t content); -el_val_t fs_list(el_val_t path); -el_val_t fs_list_json(el_val_t path); -el_val_t fs_exists(el_val_t path); -el_val_t fs_mkdir(el_val_t path); /* mkdir -p, mode 0755 */ - -/* Length-explicit binary write. `length` is an Int (el_val_t holding the - * byte count). The caller knows the length from context — typically because - * `bytes` came from base64_decode (which produces a magic-tagged binary - * buffer with embedded NULs possible) and the caller already tracks the - * decoded length, OR because the bytes came from a fixed-size source - * (sha256_bytes = 32, hmac_sha256_bytes = 32). Bypasses strlen entirely. - * - * Returns 1 on success, 0 on failure (invalid path, can't open, partial - * write, negative length). On partial-write failure, the file is removed - * so callers cannot read back a truncated artefact. */ -el_val_t fs_write_bytes(el_val_t path, el_val_t bytes, el_val_t length); - -/* ── JSON ────────────────────────────────────────────────────────────────── */ - -el_val_t json_get(el_val_t json, el_val_t key); -el_val_t json_parse(el_val_t s); -el_val_t json_stringify(el_val_t v); -el_val_t json_get_string(el_val_t json_str, el_val_t key); -el_val_t json_get_int(el_val_t json_str, el_val_t key); -el_val_t json_get_float(el_val_t json_str, el_val_t key); -el_val_t json_get_bool(el_val_t json_str, el_val_t key); -el_val_t json_get_raw(el_val_t json_str, el_val_t key); -el_val_t json_set(el_val_t json_str, el_val_t key, el_val_t value); -el_val_t json_array_len(el_val_t json_str); -el_val_t json_array_get(el_val_t json_str, el_val_t index); -el_val_t json_array_get_string(el_val_t json_str, el_val_t index); -el_val_t json_escape_string(el_val_t sv); -el_val_t json_build_object(el_val_t kvs); -el_val_t json_build_array(el_val_t items); - -/* ── Time ────────────────────────────────────────────────────────────────── */ - -el_val_t time_now(void); -el_val_t time_now_utc(void); -el_val_t sleep_secs(el_val_t secs); -el_val_t sleep_ms(el_val_t ms); -el_val_t time_format(el_val_t ts, el_val_t fmt); -el_val_t time_to_parts(el_val_t ts); -el_val_t time_from_parts(el_val_t secs, el_val_t ns, el_val_t tz); -el_val_t time_add(el_val_t ts, el_val_t n, el_val_t unit); -el_val_t time_diff(el_val_t ts1, el_val_t ts2, el_val_t unit); -el_val_t now_ns(void); - -/* ── Instant + Duration: first-class temporal types ────────────────────────── - * Both types share the el_val_t (int64) slot. Instants are nanoseconds - * since the Unix epoch; Durations are signed nanoseconds. Type discipline - * is enforced at codegen-time: BinOps on names registered as Instant or - * Duration route through the typed wrappers below; mismatches like - * Instant+Instant become #error at the C compiler. - * - * Postfix literals — `30.seconds`, `1.hour`, `500.millis`, `30.nanos` — are - * recognised by the parser as DurationLit AST nodes and lowered to literal - * int64 nanoseconds at codegen time. The runtime never sees the units. */ - -el_val_t el_now_instant(void); -el_val_t now(void); -el_val_t unix_seconds(el_val_t n); -el_val_t unix_millis(el_val_t n); -el_val_t instant_from_iso8601(el_val_t s); - -el_val_t el_duration_from_nanos(el_val_t ns); -el_val_t duration_seconds(el_val_t n); -el_val_t duration_millis(el_val_t n); -el_val_t duration_nanos(el_val_t n); - -el_val_t el_instant_add_dur(el_val_t inst, el_val_t dur); -el_val_t el_instant_sub_dur(el_val_t inst, el_val_t dur); -el_val_t el_instant_diff(el_val_t a, el_val_t b); -el_val_t el_duration_add(el_val_t a, el_val_t b); -el_val_t el_duration_sub(el_val_t a, el_val_t b); -el_val_t el_duration_scale(el_val_t dur, el_val_t scalar); -el_val_t el_duration_div(el_val_t dur, el_val_t scalar); - -el_val_t el_instant_lt(el_val_t a, el_val_t b); -el_val_t el_instant_le(el_val_t a, el_val_t b); -el_val_t el_instant_gt(el_val_t a, el_val_t b); -el_val_t el_instant_ge(el_val_t a, el_val_t b); -el_val_t el_instant_eq(el_val_t a, el_val_t b); -el_val_t el_instant_ne(el_val_t a, el_val_t b); -el_val_t el_duration_lt(el_val_t a, el_val_t b); -el_val_t el_duration_le(el_val_t a, el_val_t b); -el_val_t el_duration_gt(el_val_t a, el_val_t b); -el_val_t el_duration_ge(el_val_t a, el_val_t b); -el_val_t el_duration_eq(el_val_t a, el_val_t b); -el_val_t el_duration_ne(el_val_t a, el_val_t b); - -el_val_t instant_to_unix_seconds(el_val_t i); -el_val_t instant_to_unix_millis(el_val_t i); -el_val_t instant_to_iso8601(el_val_t i); -el_val_t duration_to_seconds(el_val_t d); -el_val_t duration_to_millis(el_val_t d); -el_val_t duration_to_nanos(el_val_t d); - -el_val_t el_sleep_duration(el_val_t dur); -el_val_t unix_timestamp(void); - -el_val_t ttl_cache_set(el_val_t key, el_val_t value); -el_val_t ttl_cache_get(el_val_t key, el_val_t max_age); -el_val_t ttl_cache_age(el_val_t key); - -/* ── Calendar + CalendarTime + Rhythm + LocalDate/Time/DateTime ───────────── - * Phase 1.5 of the time system. Calendar is pluggable: EarthCalendar (IANA - * zones, Gregorian, DST) is the user-facing default; MarsCalendar, - * CycleCalendar(period), NoCycleCalendar, RelativeCalendar handle non-Earth - * domains. - * - * A Calendar interprets an Instant under a particular cycle convention and - * produces a CalendarTime. CalendarTime carries the underlying Instant and - * a back-pointer to its Calendar; arithmetic and formatting consult the - * Calendar to convert ns since epoch into year/month/day/hour/minute/second - * (or sol/phase, or cycle/phase, depending on kind). - * - * Storage convention: Calendar / CalendarTime / Rhythm / LocalDate / - * LocalDateTime are heap-allocated structs whose pointers are cast into - * el_val_t. A 24-bit magic header at offset 0 lets the runtime identify - * the kind safely. LocalTime is small enough to live in the int64 slot - * directly (nanos since midnight, signed). */ - -/* Zone — opaque IANA zone or fixed offset, used by EarthCalendar. - * `zone_id` is either an IANA name ("America/New_York", "UTC") or a fixed - * offset string ("+05:30", "-08:00"). The runtime resolves it via tzset() - * on first use of the owning EarthCalendar. */ -el_val_t zone(el_val_t id); -el_val_t zone_utc(void); -el_val_t zone_local(void); -el_val_t zone_offset(el_val_t hours, el_val_t minutes); - -/* Calendar constructors. Each returns an el_val_t pointer to a heap- - * allocated, magic-tagged Calendar struct. Calendars are interned by - * (kind, zone_id, period_ns, epoch_ns) so identical constructors return - * the same pointer — equality is reference equality. */ -el_val_t earth_calendar(el_val_t z); -el_val_t earth_calendar_default(void); -el_val_t mars_calendar(void); -el_val_t cycle_calendar(el_val_t period_dur); -el_val_t no_cycle_calendar(void); -el_val_t relative_calendar(el_val_t epoch_inst); - -/* CalendarTime constructors and methods. Returns a heap-allocated struct - * whose pointer fits in el_val_t. */ -el_val_t now_in(el_val_t cal); -el_val_t in_calendar(el_val_t inst, el_val_t cal); -el_val_t cal_format(el_val_t ct, el_val_t pattern); -el_val_t cal_to_instant(el_val_t ct); -el_val_t cal_cycle_phase(el_val_t ct); -el_val_t cal_in(el_val_t ct, el_val_t cal); - -/* LocalDate / LocalTime / LocalDateTime — calendar-agnostic value types. - * LocalTime carries nanoseconds since midnight as a signed int64 directly - * in the el_val_t slot (no allocation). LocalDate / LocalDateTime are - * heap-allocated structs with magic headers. */ -el_val_t local_date(el_val_t y, el_val_t m, el_val_t d); -el_val_t local_time(el_val_t h, el_val_t m, el_val_t s, el_val_t ns); -el_val_t local_datetime(el_val_t date, el_val_t time); -el_val_t zoned(el_val_t date, el_val_t time, el_val_t cal); - -el_val_t local_date_year(el_val_t ld); -el_val_t local_date_month(el_val_t ld); -el_val_t local_date_day(el_val_t ld); -el_val_t local_time_hour(el_val_t lt); -el_val_t local_time_minute(el_val_t lt); -el_val_t local_time_second(el_val_t lt); -el_val_t local_time_nanos(el_val_t lt); - -el_val_t el_local_date_add_dur(el_val_t ld, el_val_t dur); -el_val_t el_local_time_add_dur(el_val_t lt, el_val_t dur); -el_val_t el_local_date_lt(el_val_t a, el_val_t b); -el_val_t el_local_date_eq(el_val_t a, el_val_t b); - -/* Rhythm — pluggable recurrence AST. Returns a heap-allocated struct - * pointer in el_val_t; rhythms are immutable so callers may share them. */ -el_val_t rhythm_cycle_start(void); -el_val_t rhythm_cycle_phase(el_val_t phase); -el_val_t rhythm_duration(el_val_t d); -el_val_t rhythm_session_start(void); -el_val_t rhythm_event(el_val_t name); -el_val_t rhythm_and(el_val_t a, el_val_t b); -el_val_t rhythm_or(el_val_t a, el_val_t b); -el_val_t rhythm_weekday(el_val_t day); -el_val_t rhythm_weekly_at(el_val_t day, el_val_t hour, el_val_t minute); -el_val_t rhythm_next_after(el_val_t r, el_val_t after, el_val_t cal); -el_val_t rhythm_matches(el_val_t r, el_val_t ct); - -/* ── UUID ────────────────────────────────────────────────────────────────── */ - -el_val_t uuid_new(void); -el_val_t uuid_v4(void); - -/* ── Environment ─────────────────────────────────────────────────────────── */ - -el_val_t env(el_val_t key); - -/* ── In-process state K/V ────────────────────────────────────────────────── */ - -el_val_t state_set(el_val_t key, el_val_t value); -el_val_t state_get(el_val_t key); -el_val_t state_del(el_val_t key); -el_val_t state_keys(void); -el_val_t state_has(el_val_t key); -el_val_t state_get_or(el_val_t key, el_val_t default_val); - -/* ── Float formatting ────────────────────────────────────────────────────── */ - -el_val_t float_to_str(el_val_t f); -el_val_t int_to_float(el_val_t n); -el_val_t float_to_int(el_val_t f); -el_val_t format_float(el_val_t f, el_val_t decimals); -el_val_t decimal_round(el_val_t f, el_val_t decimals); -el_val_t str_to_float(el_val_t s); - -/* ── Math (Float-aware) ──────────────────────────────────────────────────── */ - -el_val_t math_sqrt(el_val_t f); -el_val_t math_log(el_val_t f); -el_val_t math_ln(el_val_t f); -el_val_t math_sin(el_val_t f); -el_val_t math_cos(el_val_t f); -el_val_t math_pi(void); - -/* ── String additions ────────────────────────────────────────────────────── */ - -el_val_t str_index_of(el_val_t s, el_val_t sub); -el_val_t str_split(el_val_t s, el_val_t sep); -el_val_t str_char_at(el_val_t s, el_val_t i); -el_val_t str_char_code(el_val_t s, el_val_t i); -el_val_t str_pad_left(el_val_t s, el_val_t width, el_val_t pad); -el_val_t str_pad_right(el_val_t s, el_val_t width, el_val_t pad); -el_val_t str_format(el_val_t fmt, el_val_t data); -el_val_t str_lower(el_val_t s); -el_val_t str_upper(el_val_t s); - -/* ── Text-processing primitives (Phase 1: byte/codepoint, ASCII char classes) - * Phase 2 (filed): Unicode-grapheme awareness, NFC/NFD normalization, regex. - * is_* predicates: empty input returns false; multi-char requires ALL bytes - * to match. ASCII ranges only in Phase 1. */ - -/* Counting */ -el_val_t str_count(el_val_t s, el_val_t sub); /* non-overlapping */ -el_val_t str_count_chars(el_val_t s); /* codepoint count */ -el_val_t str_count_bytes(el_val_t s); /* alias of str_len */ -el_val_t str_count_lines(el_val_t s); -el_val_t str_count_words(el_val_t s); -el_val_t str_count_letters(el_val_t s); /* ASCII [A-Za-z] */ -el_val_t str_count_digits(el_val_t s); /* ASCII [0-9] */ - -/* Find / position */ -el_val_t str_index_of_all(el_val_t s, el_val_t sub); /* [Int] of byte offsets */ -el_val_t str_last_index_of(el_val_t s, el_val_t sub); -el_val_t str_find_chars(el_val_t s, el_val_t any_of); /* first idx of any ch */ - -/* Transform */ -el_val_t str_repeat(el_val_t s, el_val_t n); -el_val_t str_reverse(el_val_t s); /* by codepoint */ -el_val_t str_strip_prefix(el_val_t s, el_val_t prefix); -el_val_t str_strip_suffix(el_val_t s, el_val_t suffix); -el_val_t str_strip_chars(el_val_t s, el_val_t chars); -el_val_t str_lstrip(el_val_t s); -el_val_t str_rstrip(el_val_t s); - -/* Char classification (Bool) */ -el_val_t is_letter(el_val_t s); -el_val_t is_digit(el_val_t s); -el_val_t is_alphanumeric(el_val_t s); -el_val_t is_whitespace(el_val_t s); -el_val_t is_punctuation(el_val_t s); -el_val_t is_uppercase(el_val_t s); -el_val_t is_lowercase(el_val_t s); - -/* Split / join */ -el_val_t str_split_lines(el_val_t s); -el_val_t str_split_chars(el_val_t s); /* alias of native_string_chars */ -el_val_t str_split_n(el_val_t s, el_val_t sep, el_val_t n); -el_val_t str_join(el_val_t list, el_val_t sep); /* alias of list_join */ - -/* ── List additions ──────────────────────────────────────────────────────── */ - -el_val_t list_push(el_val_t list, el_val_t elem); -el_val_t list_push_front(el_val_t list, el_val_t elem); -el_val_t list_join(el_val_t list, el_val_t sep); -el_val_t list_range(el_val_t start, el_val_t end); - -/* ── Bool helpers ────────────────────────────────────────────────────────── */ - -el_val_t bool_to_str(el_val_t b); - -/* ── Numeric parsing ─────────────────────────────────────────────────────── */ - -el_val_t parse_int(el_val_t s, el_val_t default_val); - -/* ── Process ─────────────────────────────────────────────────────────────── */ - -el_val_t exit_program(el_val_t code); -el_val_t getpid_now(void); - -/* Self-terminating memory guard. Reads ELC_MAX_MEM_MB (default 512) and - * exits with code 1 if resident memory exceeds the limit. Call periodically - * during long compilation loops (e.g. after each function is compiled). - * Returns 0 when memory is within bounds. */ -el_val_t el_mem_check(void); - -/* ── CGI identity ───────────────────────────────────────────────────────────── - * Called at the start of main() in CGI programs (those with a `cgi {}` block). - * Records the program's DHARMA identity before any other code executes. */ - -void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, - el_val_t network, el_val_t engram); - -/* ── DHARMA network builtins ───────────────────────────────────────────────── - * Available to CGI programs (declared with a `cgi {}` block). - * - * Peers are addressed by `dharma_id` of the form - * "@" e.g. "ntn-genesis@http://localhost:7770" - * If the @ portion is omitted, transport defaults to - * "http://localhost:7770" (the local CGI daemon assumption). - * - * Wire protocol (all peers expose): - * POST /dharma/recv { channel, from, content } → response body - * POST /dharma/event { type, payload, source, timestamp } - * POST /api/activate { query } → list of nodes - * - * Hosting application's responsibility: an El program with a `cgi {}` block - * runs http_serve() with its own request handler; that handler should route - * "/dharma/event" requests by calling el_runtime_dharma_event_arrive() so - * incoming events feed dharma_field() queues. The runtime itself does not - * intercept any /dharma path. */ - -el_val_t dharma_connect(el_val_t cgi_id); -el_val_t dharma_send(el_val_t channel, el_val_t content); -el_val_t dharma_activate(el_val_t query); -void dharma_emit(el_val_t event_type, el_val_t payload); -el_val_t dharma_field(el_val_t event_type); -void dharma_strengthen(el_val_t cgi_id, el_val_t weight); -el_val_t dharma_relationship(el_val_t cgi_id); -el_val_t dharma_peers(void); - -/* Public C API: called by an El program's HTTP handler when a /dharma/event - * request arrives. Pushes onto the per-event-type queue and signals any - * pending dharma_field() blockers. All three arguments must be NUL-terminated - * C strings (or NULL — then treated as empty). */ -void el_runtime_dharma_event_arrive(const char* event_type, - const char* payload, - const char* source); - -/* ── Engram local graph primitives ─────────────────────────────────────────── - * Operate on the CGI's local Engram knowledge graph. - * `engram_activate` queries the local graph only; `dharma_activate` is - * network-wide across all connected CGI graphs. */ - -el_val_t engram_node(el_val_t content, el_val_t node_type, el_val_t salience); -el_val_t engram_node_full(el_val_t content, el_val_t node_type, el_val_t label, - el_val_t salience, el_val_t importance, el_val_t confidence, - el_val_t tier, el_val_t tags); -/* Layered consciousness — see el_runtime.c for the layered architecture - * design notes (search "Layered consciousness architecture"). The five - * canonical layers (safety / core-identity / domain-knowledge / imprint / - * suit) are seeded automatically; engram_add_layer extends the registry - * with imprint or suit overlays at runtime. Nodes default to layer 1 - * (core-identity) when created via engram_node / engram_node_full. */ -el_val_t engram_node_layered(el_val_t content, el_val_t node_type, el_val_t label, - el_val_t salience, el_val_t certainty, el_val_t confidence, - el_val_t status, el_val_t tags, el_val_t layer_id); -el_val_t engram_add_layer(el_val_t name, el_val_t priority, el_val_t suppressible, - el_val_t transparent, el_val_t injectable); -el_val_t engram_remove_layer(el_val_t layer_id); -el_val_t engram_list_layers(void); -el_val_t engram_get_node(el_val_t id); -void engram_strengthen(el_val_t node_id); -void engram_forget(el_val_t node_id); -el_val_t engram_node_count(void); -el_val_t engram_search(el_val_t query, el_val_t limit); -el_val_t engram_scan_nodes(el_val_t limit, el_val_t offset); -void engram_connect(el_val_t from_id, el_val_t to_id, el_val_t weight, el_val_t relation); -el_val_t engram_edge_between(el_val_t from_id, el_val_t to_id); -el_val_t engram_neighbors(el_val_t node_id); -el_val_t engram_neighbors_filtered(el_val_t node_id, el_val_t max_depth, el_val_t direction); -el_val_t engram_edge_count(void); -/* Three-pass activation: background fan-out → working-memory promotion → - * Layer 0 override. See "Three-pass activation" in el_runtime.c. */ -el_val_t engram_activate(el_val_t query, el_val_t depth); -el_val_t engram_save(el_val_t path); -el_val_t engram_load(el_val_t path); - -/* JSON-string accessors — return pre-serialized JSON so HTTP handlers - * can pass results straight through without round-tripping ElList/ElMap - * through json_stringify. */ -el_val_t engram_get_node_json(el_val_t id); -el_val_t engram_get_node_by_label(el_val_t label); -el_val_t engram_search_json(el_val_t query, el_val_t limit); -el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset); -el_val_t engram_scan_nodes_by_type_json(el_val_t node_type, el_val_t limit, el_val_t offset); -el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction); -el_val_t engram_activate_json(el_val_t query, el_val_t depth); -el_val_t engram_stats_json(void); -el_val_t engram_list_layers_json(void); -/* engram_compile_layered_json — produce a prompt-ready text block split - * into "[LAYER 0 — STRUCTURAL]" (non-suppressible layers, sacred fire) - * and "[ENGRAM CONTEXT]" (standard suppressible layers). Returns "" if - * no nodes promoted to working memory. */ -el_val_t engram_compile_layered_json(el_val_t intent, el_val_t depth); - -/* ── Working memory ──────────────────────────────────────────────────────────*/ -el_val_t engram_wm_count(void); -el_val_t engram_wm_avg_weight(void); -el_val_t engram_wm_top_json(el_val_t n); -el_val_t engram_load_merge(el_val_t path); - -/* ── LLM (Anthropic API client) ───────────────────────────────────────────── - * All functions call https://api.anthropic.com/v1/messages with the API key - * from env ANTHROPIC_API_KEY. Default model when empty: claude-sonnet-4-5. */ - -el_val_t llm_call(el_val_t model, el_val_t prompt); -el_val_t llm_call_system(el_val_t model, el_val_t system_prompt, el_val_t user_prompt); -el_val_t llm_call_agentic(el_val_t model, el_val_t system, el_val_t user, el_val_t tools); -el_val_t llm_vision(el_val_t model, el_val_t system, el_val_t prompt, el_val_t image_url_or_b64); -el_val_t llm_models(void); - -/* Register a tool handler by name. The handler is looked up via dlsym - * (mirroring http_set_handler), so any El `fn (input)` compiles to - * a global C symbol that this function can locate at runtime. - * Handler signature: `el_val_t handler(el_val_t input_json)` — receives - * the tool input as a JSON-string el_val_t and returns a JSON-string - * el_val_t result. Used by llm_call_agentic. */ -void llm_register_tool(el_val_t name, el_val_t handler_fn_name); - -/* ── args() ───────────────────────────────────────────────────────────────── - * Provides access to command-line arguments passed to the program. - * Populated by el_runtime_init_args() before main() runs. */ - -el_val_t args(void); -void el_runtime_init_args(int argc, char** argv); - -/* ── Crypto primitives ───────────────────────────────────────────────────── - * SHA-256, HMAC-SHA-256, and base64 (standard + URL-safe). - * Self-contained — no OpenSSL/libcrypto dependency. The implementations are - * adapted from public-domain reference code (Brad Conte / RFC 4648). - * - * Bytes-returning variants (sha256_bytes, hmac_sha256_bytes) return a string - * value whose contents are raw binary; callers usually feed these into - * base64_encode. Note that el_val_t strings are NUL-terminated by convention, - * so the binary payload may contain embedded NULs — pass it directly into - * base64_encode (which uses an explicit length) rather than treating it as - * a printable C string. - * - * The "base64" variants emit/accept RFC 4648 standard alphabet with padding. - * The "base64url" variants use URL-safe alphabet (`-`/`_`) with no padding, - * as used in JWTs. */ - -el_val_t sha256_hex(el_val_t input); -el_val_t sha256_bytes(el_val_t input); -el_val_t hmac_sha256_hex(el_val_t key, el_val_t message); -el_val_t hmac_sha256_bytes(el_val_t key, el_val_t message); -el_val_t base64_encode(el_val_t input); -el_val_t base64_decode(el_val_t input); -el_val_t base64url_encode(el_val_t input); -el_val_t base64url_decode(el_val_t input); - -/* Length-aware variants (internal — exposed for the rare caller that already - * has a known-length binary buffer and doesn't want to round-trip through - * a NUL-terminated el_val_t string). Sha256_bytes and hmac_sha256_bytes feed - * these implicitly. */ -el_val_t el_sha256_bytes_n(const unsigned char* data, size_t len); -el_val_t el_base64_encode_n(const unsigned char* data, size_t len, int url_safe); - -/* ── Post-quantum primitives (liboqs-backed) ──────────────────────────────── - * All inputs/outputs hex-encoded. Algorithm choices: - * Signature: CRYSTALS-Dilithium-3 (NIST level 3, balanced) - * KEM: CRYSTALS-Kyber-768 (NIST level 3) - * Hash: SHA3-256 (Keccak) (PQ-aware protocols favour SHA3 over SHA2) - * - * If liboqs is not linked (detected via __has_include() at compile - * time), the pq_* entry points return a JSON-shaped error string so callers - * fail loudly rather than silently fall back to classical schemes: - * {"error":"liboqs not linked, post-quantum primitives unavailable"} - * - * The hybrid handshake pairs X25519 with Kyber-768 per NIST PQ guidance and - * CNSA 2.0. Combined shared secret is HKDF-SHA256(x25519_ss || kyber_ss). - * Even if Kyber falls, X25519 holds; if X25519 falls under quantum attack, - * Kyber holds. SHA3-256 also remains usable independent of liboqs (the - * Keccak permutation is PQ-OK as a primitive). */ - -el_val_t pq_keygen_signature(void); -el_val_t pq_sign(el_val_t secret_key_hex, el_val_t message); -el_val_t pq_verify(el_val_t public_key_hex, el_val_t message, el_val_t signature_hex); - -el_val_t pq_kem_keygen(void); -el_val_t pq_kem_encaps(el_val_t public_key_hex); -el_val_t pq_kem_decaps(el_val_t secret_key_hex, el_val_t ciphertext_hex); - -el_val_t pq_hybrid_keygen(void); -el_val_t pq_hybrid_handshake(el_val_t remote_pub_combined); - -el_val_t sha3_256_hex(el_val_t input); - -/* ── AEAD: AES-256-GCM (libcrypto-backed) ─────────────────────────────────── - * Symmetric authenticated encryption used to wrap envelopes after a KEM - * handshake. Caller MUST supply a 32-byte key (64 hex chars) — typically the - * Kyber-768 / hybrid shared_secret, optionally normalized via SHA3-256. - * - * aead_encrypt returns a JSON map {"nonce":"...","ciphertext":"..."} where - * ciphertext is the AES-256-GCM output with the 16-byte auth tag appended. - * Nonce is a fresh 12-byte CSPRNG draw — callers never pick the nonce, which - * structurally rules out the GCM nonce-reuse footgun. - * - * aead_decrypt returns the plaintext String, or "" on any failure (including - * auth-tag mismatch). Callers MUST check for "" before trusting the result. */ -el_val_t aead_encrypt(el_val_t key_hex, el_val_t plaintext); -el_val_t aead_decrypt(el_val_t key_hex, el_val_t nonce_hex, el_val_t ciphertext_hex); - -/* ── Native VM builtin aliases (for compiled El source) ───────────────────── - * These match the El VM's native_* builtins so that El source compiled - * to C can call the same names without modification. */ - -el_val_t native_list_get(el_val_t list, el_val_t index); -el_val_t native_list_len(el_val_t list); -el_val_t native_list_append(el_val_t list, el_val_t elem); -el_val_t native_list_empty(void); -el_val_t native_list_clone(el_val_t list); -el_val_t native_string_chars(el_val_t s); -el_val_t native_int_to_str(el_val_t n); - -/* ── Method-call shorthand aliases ────────────────────────────────────────── - * The El method-call convention `obj.method(args)` compiles to - * `method(obj, args)`. These aliases expose the runtime functions under - * the short names that result from method calls in El source. - * - * Example: `myList.append(x)` → `append(myList, x)` (calls this alias) - * `myList.len()` → `len(myList)` (calls this alias) */ - -el_val_t append(el_val_t list, el_val_t elem); /* el_list_append */ -el_val_t len(el_val_t list); /* el_list_len */ -el_val_t get(el_val_t list, el_val_t index); /* el_list_get */ -el_val_t map_get(el_val_t map, el_val_t key); /* el_map_get */ -el_val_t map_set(el_val_t map, el_val_t key, el_val_t value); /* el_map_set */ - -/* ── OTLP/HTTP Observability ─────────────────────────────────────────────── */ -/* See bottom of el_runtime.c for the implementation. - * Configured by env vars OTLP_ENDPOINT, OTEL_SERVICE_NAME, OTEL_SERVICE_VERSION. - * No-op when OTLP_ENDPOINT is unset. Drop-on-failure semantics. */ -/* ── Subprocess execution ────────────────────────────────────────────────── */ -el_val_t exec_command(el_val_t cmd); /* run shell command, return exit code */ -el_val_t exec_capture(el_val_t cmd); /* run shell command, capture stdout */ -el_val_t exec(el_val_t cmd); /* exec(cmd) → stdout String (30s timeout) */ -el_val_t exec_bg(el_val_t cmd); /* exec_bg(cmd) → PID String (non-blocking) */ - -/* ── Stdout redirection (used by compiler JS pipeline) ───────────────────── */ -el_val_t stdout_to_file(el_val_t path); /* redirect process stdout to a file */ -el_val_t stdout_restore(void); /* restore process stdout to terminal */ - -el_val_t emit_log(el_val_t level, el_val_t msg, el_val_t fields_json); -el_val_t emit_metric(el_val_t name, el_val_t value, el_val_t tags_json); -el_val_t trace_span_start(el_val_t name); -el_val_t trace_span_end(el_val_t span_handle); -el_val_t emit_event(el_val_t name, el_val_t duration_ms); - -el_val_t __thread_create(el_val_t fn_name_v, el_val_t arg_v); -el_val_t __thread_join(el_val_t tid_v); - -/* ── __ prefixed aliases (self-hosting compiler ABI) ───────────────────────── - * The El self-hosting compiler emits calls to __-prefixed names. These are - * forwarding wrappers around the existing el_runtime functions above. */ - -/* I/O */ -el_val_t __println(el_val_t s); -el_val_t __print(el_val_t s); -el_val_t __readline(void); - -/* String */ -el_val_t __int_to_str(el_val_t n); -el_val_t __str_to_int(el_val_t s); -el_val_t __float_to_str(el_val_t f); -el_val_t __str_to_float(el_val_t s); -el_val_t __str_len(el_val_t s); -el_val_t __str_char_at(el_val_t s, el_val_t i); -el_val_t __str_cmp(el_val_t a, el_val_t b); -el_val_t __str_ncmp(el_val_t a, el_val_t b, el_val_t n); -el_val_t __str_concat_raw(el_val_t a, el_val_t b); -el_val_t __str_slice_raw(el_val_t s, el_val_t start, el_val_t end); -el_val_t __str_alloc(el_val_t n); -el_val_t __str_set_char(el_val_t s, el_val_t i, el_val_t c); - -/* URL encoding */ -el_val_t __url_encode(el_val_t s); -el_val_t __url_decode(el_val_t s); - -/* Environment */ -el_val_t __env_get(el_val_t key); - -/* Subprocess */ -el_val_t __exec(el_val_t cmd); -el_val_t __exec_bg(el_val_t cmd); - -/* Process */ -el_val_t __exit_program(el_val_t code); - -/* Filesystem */ -el_val_t __fs_exists(el_val_t path); -el_val_t __fs_mkdir(el_val_t path); -el_val_t __fs_read(el_val_t path); -el_val_t __fs_write(el_val_t path, el_val_t content); -el_val_t __fs_write_bytes(el_val_t path, el_val_t bytes, el_val_t n); -el_val_t __fs_list_raw(el_val_t path); - -/* HTTP server */ -el_val_t __http_response(el_val_t status, el_val_t headers_json, el_val_t body); -el_val_t __http_serve(el_val_t port, el_val_t handler); -el_val_t __http_serve_v2(el_val_t port, el_val_t handler); - -/* HTTP conn fd / SSE (weak; overridden by el_seed.c when linked together) */ -el_val_t __http_conn_fd(void); -el_val_t __http_sse_open(el_val_t conn_id); -el_val_t __http_sse_send(el_val_t conn_id, el_val_t data); -el_val_t __http_sse_close(el_val_t conn_id); - -/* HTTP client (requires HAVE_CURL; stubs provided for no-curl builds) */ -el_val_t __http_do(el_val_t method, el_val_t url, el_val_t body, - el_val_t headers_map, el_val_t timeout_ms); -el_val_t __http_do_map(el_val_t method, el_val_t url, el_val_t body, - el_val_t headers_json, el_val_t timeout_ms); -el_val_t __http_do_map_to_file(el_val_t method, el_val_t url, el_val_t body, - el_val_t headers_json, el_val_t output_path); - -/* JSON */ -el_val_t __json_array_get(el_val_t json, el_val_t index); -el_val_t __json_array_get_string(el_val_t json, el_val_t index); -el_val_t __json_array_len(el_val_t json); -el_val_t __json_get(el_val_t json, el_val_t key); -el_val_t __json_get_raw(el_val_t json, el_val_t key); -el_val_t __json_set(el_val_t json, el_val_t key, el_val_t value); -el_val_t __json_parse_map(el_val_t json_str); -el_val_t __json_stringify_val(el_val_t val); - -/* Hashing */ -el_val_t __sha256_hex(el_val_t s); - -/* State K/V */ -el_val_t __state_del(el_val_t key); -el_val_t __state_get(el_val_t key); -el_val_t __state_keys(void); -el_val_t __state_set(el_val_t key, el_val_t val); - -/* UUID */ -el_val_t __uuid_v4(void); - -/* Args */ -el_val_t __args_json(void); - -#ifdef __cplusplus -} -#endif diff --git a/lang/el-compiler/runtime/legacy/el_runtime.c b/lang/el-compiler/runtime/legacy/el_runtime.c deleted file mode 100644 index 08d51fb..0000000 --- a/lang/el-compiler/runtime/legacy/el_runtime.c +++ /dev/null @@ -1,10258 +0,0 @@ -/* - * el_runtime.c — El language C runtime implementation - * - * All functions use el_val_t (= int64_t) as the universal value type. - * Strings are transported as their pointer address cast to int64_t. - * On any 64-bit system sizeof(pointer) <= sizeof(int64_t), so this is safe. - * - * Compile with: - * cc -std=c11 -I -lcurl -lpthread -o .c el_runtime.c - * - * Link requirements: -lcurl (HTTP client + LLM), -lpthread (HTTP server). - */ - -/* Feature-test macros must be set before any standard headers. _GNU_SOURCE - * exposes clock_gettime/CLOCK_REALTIME, strcasecmp, and the dlfcn extensions - * (RTLD_DEFAULT) — all of which macOS hands us without asking but glibc on - * Debian gates behind an explicit opt-in. */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include "el_runtime.h" - -#include -#include /* strcasecmp */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* dlsym for http_set_handler fallback */ -#include -#include -#include -#include -#include -#include - -/* ── Internal allocators ─────────────────────────────────────────────────── */ - -/* - * Per-request string arena - * - * Every El string allocated via el_strbuf / el_strdup during an HTTP request - * is registered in a thread-local arena. When el_request_end() is called at - * the end of the worker thread, every arena entry is freed — recovering all - * the intermediate strings from el_str_concat chains (build_system_prompt, - * engram_compile, etc.) that are otherwise leaked forever. - * - * Long-lived allocations (state_set values, engram internal storage) call - * el_strdup_persist() / el_strbuf_persist() which bypass the arena entirely. - */ - -#define EL_ARENA_INITIAL 512 - -typedef struct { - char** ptrs; - size_t count; - size_t cap; -} ElArena; - -static _Thread_local ElArena _tl_arena = {NULL, 0, 0}; -static _Thread_local int _tl_arena_active = 0; - -/* Binary-safe fs_read length — set by fs_read, consumed by http_send_response. - * Allows serving PNGs and other binary files without strlen truncation. */ -static _Thread_local size_t _tl_fs_read_len = 0; - -static void el_arena_track(char* p) { - if (!_tl_arena_active || !p) return; - if (_tl_arena.count >= _tl_arena.cap) { - size_t nc = _tl_arena.cap == 0 ? EL_ARENA_INITIAL : _tl_arena.cap * 2; - char** grown = realloc(_tl_arena.ptrs, nc * sizeof(char*)); - if (!grown) return; /* can't track — will leak this one ptr, but don't crash */ - _tl_arena.ptrs = grown; - _tl_arena.cap = nc; - } - _tl_arena.ptrs[_tl_arena.count++] = p; -} - -/* Called by http_worker before dispatching the El handler. */ -void el_request_start(void) { - _tl_arena.count = 0; - _tl_arena_active = 1; -} - -/* Called by http_worker after the El handler returns and the response is sent. - * Frees every intermediate string allocated during the request. */ -void el_request_end(void) { - _tl_arena_active = 0; - for (size_t i = 0; i < _tl_arena.count; i++) { - free(_tl_arena.ptrs[i]); - } - _tl_arena.count = 0; -} - -/* Persistent allocation — bypasses the arena (state_set, engram internals). */ -static char* el_strdup_persist(const char* s) { - if (!s) return strdup(""); - return strdup(s); -} -static char* el_strbuf_persist(size_t n) { - char* p = malloc(n + 1); - if (!p) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - p[0] = '\0'; - return p; -} - -static char* el_strdup(const char* s) { - if (!s) { char* p = strdup(""); el_arena_track(p); return p; } - char* p = strdup(s); - el_arena_track(p); - return p; -} - -static char* el_strbuf(size_t n) { - char* p = malloc(n + 1); - if (!p) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - p[0] = '\0'; - el_arena_track(p); - return p; -} - -/* Wrap an allocated C string as el_val_t */ -static el_val_t el_wrap_str(char* s) { - return EL_STR(s); -} - -/* ── I/O ──────────────────────────────────────────────────────────────────── */ - -void println(el_val_t s) { - const char* str = EL_CSTR(s); - if (str) puts(str); - else puts(""); -} - -void print(el_val_t s) { - const char* str = EL_CSTR(s); - if (str) fputs(str, stdout); -} - -el_val_t readline(void) { - char buf[4096]; - if (!fgets(buf, sizeof(buf), stdin)) return el_wrap_str(el_strdup("")); - size_t len = strlen(buf); - if (len > 0 && buf[len - 1] == '\n') buf[len - 1] = '\0'; - return el_wrap_str(el_strdup(buf)); -} - -/* ── String builtins ─────────────────────────────────────────────────────── */ - -el_val_t el_str_concat(el_val_t av, el_val_t bv) { - const char* a = EL_CSTR(av); - const char* b = EL_CSTR(bv); - if (!a) a = ""; - if (!b) b = ""; - size_t la = strlen(a); - size_t lb = strlen(b); - char* out = el_strbuf(la + lb); - memcpy(out, a, la); - memcpy(out + la, b, lb); - out[la + lb] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_eq(el_val_t av, el_val_t bv) { - const char* a = EL_CSTR(av); - const char* b = EL_CSTR(bv); - if (!a || !b) return (el_val_t)(a == b); - return (el_val_t)(strcmp(a, b) == 0); -} - -el_val_t str_starts_with(el_val_t sv, el_val_t prefv) { - const char* s = EL_CSTR(sv); - const char* prefix = EL_CSTR(prefv); - if (!s || !prefix) return 0; - size_t lp = strlen(prefix); - return (el_val_t)(strncmp(s, prefix, lp) == 0); -} - -el_val_t str_ends_with(el_val_t sv, el_val_t sufv) { - const char* s = EL_CSTR(sv); - const char* suffix = EL_CSTR(sufv); - if (!s || !suffix) return 0; - size_t ls = strlen(s); - size_t lsuf = strlen(suffix); - if (lsuf > ls) return 0; - return (el_val_t)(strcmp(s + ls - lsuf, suffix) == 0); -} - -el_val_t str_len(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - return (el_val_t)strlen(s); -} - -el_val_t str_concat(el_val_t a, el_val_t b) { - return el_str_concat(a, b); -} - -el_val_t int_to_str(el_val_t n) { - char buf[32]; - snprintf(buf, sizeof(buf), "%lld", (long long)n); - return el_wrap_str(el_strdup(buf)); -} - -el_val_t str_to_int(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - return (el_val_t)atoll(s); -} - -el_val_t str_slice(el_val_t sv, el_val_t start, el_val_t end) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - int64_t len = (int64_t)strlen(s); - if (start < 0) start = 0; - if (end > len) end = len; - if (start >= end) return el_wrap_str(el_strdup("")); - int64_t sz = end - start; - char* out = el_strbuf((size_t)sz); - memcpy(out, s + start, (size_t)sz); - out[sz] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_contains(el_val_t sv, el_val_t subv) { - const char* s = EL_CSTR(sv); - const char* sub = EL_CSTR(subv); - if (!s || !sub) return 0; - return (el_val_t)(strstr(s, sub) != NULL); -} - -el_val_t str_replace(el_val_t sv, el_val_t fromv, el_val_t tov) { - const char* s = EL_CSTR(sv); - const char* from = EL_CSTR(fromv); - const char* to = EL_CSTR(tov); - if (!s || !from || !to) return el_wrap_str(el_strdup(s ? s : "")); - size_t ls = strlen(s); - size_t lf = strlen(from); - size_t lt = strlen(to); - if (lf == 0) return el_wrap_str(el_strdup(s)); - size_t count = 0; - const char* p = s; - while ((p = strstr(p, from)) != NULL) { count++; p += lf; } - size_t out_sz = ls + count * lt + 1; - char* out = el_strbuf(out_sz); - char* dst = out; - p = s; - const char* found; - while ((found = strstr(p, from)) != NULL) { - size_t chunk = (size_t)(found - p); - memcpy(dst, p, chunk); dst += chunk; - memcpy(dst, to, lt); dst += lt; - p = found + lf; - } - strcpy(dst, p); - return el_wrap_str(out); -} - -el_val_t str_to_upper(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - size_t n = strlen(s); - char* out = el_strbuf(n); - for (size_t i = 0; i < n; i++) out[i] = (char)toupper((unsigned char)s[i]); - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_to_lower(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - size_t n = strlen(s); - char* out = el_strbuf(n); - for (size_t i = 0; i < n; i++) out[i] = (char)tolower((unsigned char)s[i]); - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_trim(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - while (*s && isspace((unsigned char)*s)) s++; - size_t n = strlen(s); - while (n > 0 && isspace((unsigned char)s[n - 1])) n--; - char* out = el_strbuf(n); - memcpy(out, s, n); - out[n] = '\0'; - return el_wrap_str(out); -} - -/* ── Math ────────────────────────────────────────────────────────────────── */ - -el_val_t el_abs(el_val_t n) { return n < 0 ? -n : n; } -el_val_t el_max(el_val_t a, el_val_t b) { return a > b ? a : b; } -el_val_t el_min(el_val_t a, el_val_t b) { return a < b ? a : b; } - -/* ── Refcounted heap objects ────────────────────────────────────────────────── - * - * ElList and ElMap carry a magic-tagged header at offset 0: - * { uint32_t magic; uint32_t refcount; ... payload ... } - * - * The magic tag distinguishes refcounted objects from raw C strings (whose - * first byte is printable ASCII < 0x80) and from small integers (which can't - * be dereferenced). el_retain / el_release sniff the magic and act only on - * matching values; everything else is a safe no-op. - * - * Both ElList and ElMap use INDIRECTION: the header is fixed-size and never - * moves. The payload arrays (elems, keys, values) live in separate heap - * allocations, so realloc-grow on append never invalidates the caller's - * pointer to the header. This is what lets us mutate-in-place safely when - * the refcount is 1 and copy-on-write when it's higher. - * - * Memory model in practice: - * Single-owner accumulator (the cg_stmts pattern) — refcount stays at 1, - * appends amortize to O(1), total memory O(N) for an N-element list. - * Multi-owner branching (the cg_if_stmt pattern) — refcount > 1, each - * append on a shared list copies, so the original is preserved for the - * else-branch. Persistent semantics where they're needed; mutation where - * they're not. */ - -#define EL_MAGIC_LIST 0xE15710A1u /* >= 0x80 in MSB so 'looks_like_string' rejects */ -#define EL_MAGIC_MAP 0xE19A704Bu - -typedef struct { - uint32_t magic; - uint32_t refcount; -} ElHeader; - -/* ── List ────────────────────────────────────────────────────────────────── */ - -typedef struct { - ElHeader hdr; - int64_t length; - int64_t capacity; - el_val_t* elems; -} ElList; - -static ElList* list_alloc(int64_t cap) { - if (cap < 4) cap = 4; - ElList* lst = malloc(sizeof(ElList)); - if (!lst) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - lst->hdr.magic = EL_MAGIC_LIST; - lst->hdr.refcount = 1; - lst->length = 0; - lst->capacity = cap; - lst->elems = malloc((size_t)cap * sizeof(el_val_t)); - if (!lst->elems) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - return lst; -} - -el_val_t el_list_empty(void) { - return EL_STR(list_alloc(4)); -} - -el_val_t el_list_new(el_val_t count, ...) { - ElList* lst = list_alloc(count > 0 ? count : 4); - va_list ap; - va_start(ap, count); - for (int64_t i = 0; i < count; i++) { - lst->elems[i] = va_arg(ap, el_val_t); - } - va_end(ap); - lst->length = count; - return EL_STR(lst); -} - -el_val_t el_list_len(el_val_t listv) { - ElList* lst = (ElList*)(uintptr_t)listv; - if (!lst) return 0; - return lst->length; -} - -el_val_t el_list_get(el_val_t listv, el_val_t index) { - ElList* lst = (ElList*)(uintptr_t)listv; - if (!lst) return 0; - if (index < 0 || index >= lst->length) return 0; - return lst->elems[index]; -} - -el_val_t el_list_append(el_val_t listv, el_val_t elem) { - ElList* old = (ElList*)(uintptr_t)listv; - if (!old) { - ElList* fresh = list_alloc(4); - fresh->elems[0] = elem; - fresh->length = 1; - return EL_STR(fresh); - } - - /* Uniquely owned: grow the elems buffer in place. The header pointer the - * caller holds doesn't move (we only realloc the inner array). This is - * the common case in compiler accumulators, and it's amortized O(1). */ - if (old->hdr.refcount <= 1) { - if (old->length >= old->capacity) { - int64_t new_cap = old->capacity > 0 ? old->capacity * 2 : 4; - el_val_t* grown = realloc(old->elems, (size_t)new_cap * sizeof(el_val_t)); - if (!grown) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - old->elems = grown; - old->capacity = new_cap; - } - old->elems[old->length++] = elem; - return listv; - } - - /* Shared: copy-on-write. The original is preserved for its other owners. */ - int64_t new_cap = old->length + 1; - if (new_cap < 4) new_cap = 4; - ElList* fresh = malloc(sizeof(ElList)); - if (!fresh) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - fresh->hdr.magic = EL_MAGIC_LIST; - fresh->hdr.refcount = 1; - fresh->length = old->length + 1; - fresh->capacity = new_cap; - fresh->elems = malloc((size_t)new_cap * sizeof(el_val_t)); - if (!fresh->elems) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - if (old->length > 0) { - memcpy(fresh->elems, old->elems, (size_t)old->length * sizeof(el_val_t)); - } - fresh->elems[old->length] = elem; - return EL_STR(fresh); -} - -el_val_t el_list_clone(el_val_t listv) { - /* Shallow copy: the new ElList owns its own header and elems buffer, but - * the elements themselves are shared (which is what callers want for the - * cg_if_stmt 'declared' pattern — cloning the spine, not its contents). - * Used by codegen at scope branch points where two child scopes need to - * see the same starting set of declared names without each other's - * mutations. */ - ElList* old = (ElList*)(uintptr_t)listv; - if (!old) return el_list_empty(); - int64_t cap = old->capacity > 0 ? old->capacity : 4; - if (cap < old->length) cap = old->length; - if (cap < 4) cap = 4; - ElList* fresh = malloc(sizeof(ElList)); - if (!fresh) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - fresh->hdr.magic = EL_MAGIC_LIST; - fresh->hdr.refcount = 1; - fresh->length = old->length; - fresh->capacity = cap; - fresh->elems = malloc((size_t)cap * sizeof(el_val_t)); - if (!fresh->elems) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - if (old->length > 0) { - memcpy(fresh->elems, old->elems, (size_t)old->length * sizeof(el_val_t)); - } - return EL_STR(fresh); -} - -/* ── Map ─────────────────────────────────────────────────────────────────── */ - -typedef struct { - ElHeader hdr; - int64_t count; - int64_t capacity; - el_val_t* keys; - el_val_t* values; -} ElMap; - -static ElMap* map_alloc(int64_t cap) { - if (cap < 4) cap = 4; - ElMap* m = malloc(sizeof(ElMap)); - if (!m) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - m->hdr.magic = EL_MAGIC_MAP; - m->hdr.refcount = 1; - m->count = 0; - m->capacity = cap; - m->keys = malloc((size_t)cap * sizeof(el_val_t)); - m->values = malloc((size_t)cap * sizeof(el_val_t)); - if (!m->keys || !m->values) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - return m; -} - -el_val_t el_map_new(el_val_t pair_count, ...) { - ElMap* m = map_alloc(pair_count > 0 ? pair_count : 4); - va_list ap; - va_start(ap, pair_count); - for (int64_t i = 0; i < pair_count; i++) { - m->keys[i] = va_arg(ap, el_val_t); - m->values[i] = va_arg(ap, el_val_t); - } - va_end(ap); - m->count = pair_count; - return EL_STR(m); -} - -static ElMap* as_map(el_val_t v) { return (ElMap*)(uintptr_t)v; } - -el_val_t el_map_get(el_val_t mapv, el_val_t keyv) { - ElMap* m = as_map(mapv); - const char* key = EL_CSTR(keyv); - if (!m || !key) return 0; - for (int64_t i = 0; i < m->count; i++) { - const char* k = EL_CSTR(m->keys[i]); - if (k && strcmp(k, key) == 0) return m->values[i]; - } - return 0; -} - -el_val_t el_get_field(el_val_t mapv, el_val_t keyv) { - return el_map_get(mapv, keyv); -} - -/* Internal: in-place set on a uniquely-owned map. */ -static el_val_t map_set_in_place(ElMap* m, el_val_t keyv, el_val_t value) { - const char* key = EL_CSTR(keyv); - if (key) { - for (int64_t i = 0; i < m->count; i++) { - const char* k = EL_CSTR(m->keys[i]); - if (k && strcmp(k, key) == 0) { m->values[i] = value; return EL_STR(m); } - } - } - if (m->count >= m->capacity) { - int64_t new_cap = m->capacity > 0 ? m->capacity * 2 : 4; - el_val_t* gk = realloc(m->keys, (size_t)new_cap * sizeof(el_val_t)); - el_val_t* gv = realloc(m->values, (size_t)new_cap * sizeof(el_val_t)); - if (!gk || !gv) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - m->keys = gk; - m->values = gv; - m->capacity = new_cap; - } - m->keys[m->count] = keyv; - m->values[m->count] = value; - m->count++; - return EL_STR(m); -} - -el_val_t el_map_set(el_val_t mapv, el_val_t keyv, el_val_t value) { - ElMap* m = as_map(mapv); - if (!m) return 0; - if (m->hdr.refcount <= 1) { - return map_set_in_place(m, keyv, value); - } - /* Shared: copy then set. The original is preserved for its other owners. */ - int64_t new_cap = m->count + 1; - if (new_cap < 4) new_cap = 4; - ElMap* fresh = malloc(sizeof(ElMap)); - if (!fresh) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - fresh->hdr.magic = EL_MAGIC_MAP; - fresh->hdr.refcount = 1; - fresh->count = m->count; - fresh->capacity = new_cap; - fresh->keys = malloc((size_t)new_cap * sizeof(el_val_t)); - fresh->values = malloc((size_t)new_cap * sizeof(el_val_t)); - if (!fresh->keys || !fresh->values) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - if (m->count > 0) { - memcpy(fresh->keys, m->keys, (size_t)m->count * sizeof(el_val_t)); - memcpy(fresh->values, m->values, (size_t)m->count * sizeof(el_val_t)); - } - return map_set_in_place(fresh, keyv, value); -} - -/* ── Refcount ops ─────────────────────────────────────────────────────────── */ -/* - * Both retain and release sniff the magic header to decide whether a value - * is a refcounted heap object. For small integers, raw C strings, and any - * value whose magic word doesn't match, both functions are no-ops. This lets - * codegen emit them on every let-binding without having to track types. - * - * Safety: we filter out obvious non-pointers (small magnitudes, misaligned - * addresses) before dereferencing. For any value that passes the filter and - * lives in a mapped page, reading the first 4 bytes is safe — strings start - * with printable ASCII (< 0x80), so their magic word will never collide with - * EL_MAGIC_LIST (0xE1...) or EL_MAGIC_MAP (0xE1...). Random integers that - * happen to look like aligned heap pointers are exceedingly unlikely to land - * on a page whose first 4 bytes match either magic. */ - -static int looks_like_heap_obj(el_val_t v) { - if (v == 0) return 0; - int64_t s = (int64_t)v; - if (s > -0x10000 && s < 0x10000) return 0; /* small ints */ - uintptr_t p = (uintptr_t)v; - if (p < 0x10000) return 0; /* low addresses */ - if (p & 0x7) return 0; /* malloc returns 8-aligned */ - return 1; -} - -void el_retain(el_val_t v) { - if (!looks_like_heap_obj(v)) return; - ElHeader* h = (ElHeader*)(uintptr_t)v; - if (h->magic == EL_MAGIC_LIST || h->magic == EL_MAGIC_MAP) { - h->refcount++; - } -} - -void el_release(el_val_t v) { - if (!looks_like_heap_obj(v)) return; - ElHeader* h = (ElHeader*)(uintptr_t)v; - if (h->magic == EL_MAGIC_LIST) { - if (h->refcount > 0 && --h->refcount == 0) { - ElList* l = (ElList*)h; - free(l->elems); - l->hdr.magic = 0; /* poison so use-after-free is detected */ - free(l); - } - } else if (h->magic == EL_MAGIC_MAP) { - if (h->refcount > 0 && --h->refcount == 0) { - ElMap* m = (ElMap*)h; - free(m->keys); - free(m->values); - m->hdr.magic = 0; - free(m); - } - } -} - -/* ── Batch 2/3 forward decls (defined later in JSON section) ────────────── */ - -typedef struct JsonBuf JsonBuf; -typedef struct JsonParser JsonParser; -static void jb_init(JsonBuf* b); -static void jb_putc(JsonBuf* b, char c); -static void jb_puts(JsonBuf* b, const char* s); -static void jb_emit_escaped(JsonBuf* b, const char* s); -static int looks_like_string(el_val_t v); -static const char* json_find_key(const char* s, const char* key); -static const char* json_skip_value(const char* p); -static char* jp_parse_string_raw(JsonParser* jp); - -/* Struct definitions are visible here because batch 2/3 helpers above use - * them by value; the bodies (jb_init, etc.) appear in the JSON section. */ -struct JsonBuf { - char* buf; - size_t len; - size_t cap; -}; - -struct JsonParser { - const char* p; - const char* end; - int err; -}; - -/* ── Batch 2: Real HTTP (libcurl client + POSIX-socket server) ───────────── */ -/* - * Client: blocking libcurl easy-handle calls. Errors are returned as a JSON - * fragment {"error":"..."} so callers can detect via str_starts_with("{") / - * json_get_string("error", ...). - * - * Server: bind/listen/accept loop on a TCP socket. Each accepted connection - * is handled in its own pthread (detached). A semaphore-style counter caps - * concurrent in-flight connections at HTTP_MAX_CONNS (64). When the cap is - * reached, accept() blocks until a worker exits. This prevents runaway - * thread creation under high load. - * - * Handler dispatch: El does not expose first-class function references at - * the runtime layer, so the second argument to http_serve(port, handler) is - * treated as a string name (or any el_val_t — the runtime ignores its - * value and uses the registry). Callers register a C-level handler via - * - * extern void el_runtime_register_handler(const char* name, - * el_val_t (*fn)(el_val_t, - * el_val_t, - * el_val_t)); - * - * and select the active handler by calling http_set_handler("name") from - * El, or by setting it directly through the C registry. If no handler is - * registered, the server replies with a 200 carrying a default message so - * the loop is observable. - */ - -/* ── HTTP client write-callback buffer ───────────────────────────────────── */ - -typedef struct { - char* data; - size_t len; - size_t cap; -} HttpBuf; - -static void httpbuf_init(HttpBuf* b) { - b->cap = 1024; - b->len = 0; - b->data = malloc(b->cap); - if (!b->data) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - b->data[0] = '\0'; -} - -static void httpbuf_append(HttpBuf* b, const void* src, size_t n) { - if (b->len + n + 1 > b->cap) { - while (b->len + n + 1 > b->cap) b->cap *= 2; - b->data = realloc(b->data, b->cap); - if (!b->data) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - } - memcpy(b->data + b->len, src, n); - b->len += n; - b->data[b->len] = '\0'; -} - -static size_t http_write_cb(char* ptr, size_t size, size_t nmemb, void* ud) { - size_t n = size * nmemb; - httpbuf_append((HttpBuf*)ud, ptr, n); - return n; -} - -/* JSON-escape an arbitrary C string into an allocated buffer. */ -static char* json_escape_alloc(const char* s) { - if (!s) return el_strdup(""); - JsonBuf b; jb_init(&b); - for (const char* p = s; *p; p++) { - unsigned char c = (unsigned char)*p; - switch (c) { - case '"': jb_puts(&b, "\\\""); break; - case '\\': jb_puts(&b, "\\\\"); break; - case '\n': jb_puts(&b, "\\n"); break; - case '\r': jb_puts(&b, "\\r"); break; - case '\t': jb_puts(&b, "\\t"); break; - default: - if (c < 0x20) { - char tmp[8]; snprintf(tmp, sizeof(tmp), "\\u%04x", c); - jb_puts(&b, tmp); - } else jb_putc(&b, (char)c); - } - } - return b.buf; -} - -static el_val_t http_error_json(const char* msg) { - char* esc = json_escape_alloc(msg ? msg : "unknown error"); - char* buf = el_strbuf(strlen(esc) + 16); - sprintf(buf, "{\"error\":\"%s\"}", esc); - free(esc); - return el_wrap_str(buf); -} - -/* HTTP timeout (ms) — read once from EL_HTTP_TIMEOUT_MS, default 60000. - * Applied via CURLOPT_TIMEOUT_MS on every libcurl request. */ -static long _el_http_timeout_ms = -1; -static long el_http_timeout_ms(void) { - long v = __atomic_load_n(&_el_http_timeout_ms, __ATOMIC_ACQUIRE); - if (v >= 0) return v; - const char* s = getenv("EL_HTTP_TIMEOUT_MS"); - long parsed = 60000L; - if (s && *s) { - char* end = NULL; - long n = strtol(s, &end, 10); - if (end != s && n > 0) parsed = n; - } - __atomic_store_n(&_el_http_timeout_ms, parsed, __ATOMIC_RELEASE); - return parsed; -} - -/* Internal: do a libcurl request; takes optional body/headers, optional method override. */ -static el_val_t http_do(const char* method, const char* url, const char* body, - struct curl_slist* extra_headers) { - if (!url || !*url) return http_error_json("empty url"); - CURL* c = curl_easy_init(); - if (!c) return http_error_json("curl_easy_init failed"); - HttpBuf rb; httpbuf_init(&rb); - char errbuf[CURL_ERROR_SIZE]; errbuf[0] = '\0'; - curl_easy_setopt(c, CURLOPT_URL, url); - curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, http_write_cb); - curl_easy_setopt(c, CURLOPT_WRITEDATA, &rb); - curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(c, CURLOPT_TIMEOUT_MS, el_http_timeout_ms()); - curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(c, CURLOPT_ERRORBUFFER, errbuf); - curl_easy_setopt(c, CURLOPT_USERAGENT, "el-runtime/1.0"); - if (extra_headers) curl_easy_setopt(c, CURLOPT_HTTPHEADER, extra_headers); - if (method && strcmp(method, "POST") == 0) { - curl_easy_setopt(c, CURLOPT_POST, 1L); - curl_easy_setopt(c, CURLOPT_POSTFIELDS, body ? body : ""); - curl_easy_setopt(c, CURLOPT_POSTFIELDSIZE, (long)(body ? strlen(body) : 0)); - } else if (method && strcmp(method, "DELETE") == 0) { - curl_easy_setopt(c, CURLOPT_CUSTOMREQUEST, "DELETE"); - } - CURLcode rc = curl_easy_perform(c); - curl_easy_cleanup(c); - if (rc != CURLE_OK) { - free(rb.data); - const char* m = errbuf[0] ? errbuf : curl_easy_strerror(rc); - return http_error_json(m); - } - return el_wrap_str(rb.data); -} - -el_val_t http_get(el_val_t url) { - return http_do("GET", EL_CSTR(url), NULL, NULL); -} - -el_val_t http_post(el_val_t url, el_val_t body) { - return http_do("POST", EL_CSTR(url), EL_CSTR(body), NULL); -} - -el_val_t http_post_json(el_val_t url, el_val_t json_body) { - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - el_val_t r = http_do("POST", EL_CSTR(url), EL_CSTR(json_body), h); - curl_slist_free_all(h); - return r; -} - -/* Build a curl_slist from an ElMap of name -> value strings. */ -static struct curl_slist* headers_from_map(el_val_t headers_map) { - struct curl_slist* h = NULL; - ElMap* m = as_map(headers_map); - if (!m) return NULL; - for (int64_t i = 0; i < m->count; i++) { - const char* k = EL_CSTR(m->keys[i]); - const char* v = EL_CSTR(m->values[i]); - if (!k || !v) continue; - size_t n = strlen(k) + strlen(v) + 4; - char* line = malloc(n); - if (!line) continue; - snprintf(line, n, "%s: %s", k, v); - h = curl_slist_append(h, line); - free(line); - } - return h; -} - -el_val_t http_get_with_headers(el_val_t url, el_val_t headers_map) { - struct curl_slist* h = headers_from_map(headers_map); - el_val_t r = http_do("GET", EL_CSTR(url), NULL, h); - if (h) curl_slist_free_all(h); - return r; -} - -el_val_t http_post_with_headers(el_val_t url, el_val_t body, el_val_t headers_map) { - struct curl_slist* h = headers_from_map(headers_map); - el_val_t r = http_do("POST", EL_CSTR(url), EL_CSTR(body), h); - if (h) curl_slist_free_all(h); - return r; -} - -el_val_t http_post_form_auth(el_val_t url, el_val_t form_body, el_val_t auth_header) { - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/x-www-form-urlencoded"); - const char* a = EL_CSTR(auth_header); - if (a && *a) { - size_t n = strlen(a) + 32; - char* line = malloc(n); - snprintf(line, n, "Authorization: %s", a); - h = curl_slist_append(h, line); - free(line); - } - el_val_t r = http_do("POST", EL_CSTR(url), EL_CSTR(form_body), h); - curl_slist_free_all(h); - return r; -} - -/* HTTP DELETE — mirrors http_post but with CURLOPT_CUSTOMREQUEST=DELETE. - * Returns response body on success; on transport failure returns an error - * JSON fragment (same convention as http_get/http_post). Callers that - * expect "" on failure should check for a leading '{' and an "error" key. */ -el_val_t http_delete(el_val_t url) { - return http_do("DELETE", EL_CSTR(url), NULL, NULL); -} - -/* ── HTTP → file streaming ──────────────────────────────────────────────── - * - * Why this exists: el_val_t strings are NUL-terminated by convention, so - * accumulating an HTTP response into an httpbuf and then wrapping its - * `.data` pointer with el_wrap_str() loses the byte length. Any consumer - * that does strlen() on the wrapped pointer truncates the body at the - * first embedded NUL. Audio (MP3, WAV, OGG), images (PNG, JPEG), and any - * other binary payload hits this. The vessels that download such bodies - * (e.g. ElevenLabs TTS → MP3) get silently corrupted files. - * - * The fix: wire libcurl's CURLOPT_WRITEFUNCTION directly to fwrite() - * against a fopen()-ed FILE*. The bytes never pass through an el_val_t - * string, so embedded NULs are preserved verbatim. Caller's contract is - * just "a file at this path with the response body in it". */ - -static size_t http_file_write_cb(char* ptr, size_t size, size_t nmemb, void* ud) { - FILE* f = (FILE*)ud; - return fwrite(ptr, size, nmemb, f); -} - -/* Internal: stream body to file. method is "GET" or "POST". body may be NULL - * (GET) or NUL-terminated (POST). headers may be NULL. Returns 1/0. */ -static el_val_t http_do_to_file(const char* method, const char* url, - const char* body, struct curl_slist* extra_headers, - const char* output_path) { - if (!url || !*url) return 0; - if (!output_path || !*output_path) return 0; - FILE* f = fopen(output_path, "wb"); - if (!f) return 0; - - CURL* c = curl_easy_init(); - if (!c) { fclose(f); remove(output_path); return 0; } - - char errbuf[CURL_ERROR_SIZE]; errbuf[0] = '\0'; - curl_easy_setopt(c, CURLOPT_URL, url); - curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, http_file_write_cb); - curl_easy_setopt(c, CURLOPT_WRITEDATA, f); - curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(c, CURLOPT_TIMEOUT_MS, el_http_timeout_ms()); - curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(c, CURLOPT_ERRORBUFFER, errbuf); - curl_easy_setopt(c, CURLOPT_USERAGENT, "el-runtime/1.0"); - curl_easy_setopt(c, CURLOPT_FAILONERROR, 1L); /* 4xx/5xx → CURLE_HTTP_RETURNED_ERROR */ - if (extra_headers) curl_easy_setopt(c, CURLOPT_HTTPHEADER, extra_headers); - - if (method && strcmp(method, "POST") == 0) { - curl_easy_setopt(c, CURLOPT_POST, 1L); - curl_easy_setopt(c, CURLOPT_POSTFIELDS, body ? body : ""); - /* For the request body we still rely on strlen — POST bodies are - * caller-controlled and JSON/text in every known El use case. - * If a future caller needs a binary POST body, add a *_bytes - * variant that takes an explicit length, mirroring fs_write_bytes. */ - curl_easy_setopt(c, CURLOPT_POSTFIELDSIZE, (long)(body ? strlen(body) : 0)); - } - - CURLcode rc = curl_easy_perform(c); - curl_easy_cleanup(c); - - /* Flush + close before signalling success, so the file is fully on disk - * by the time the caller reads back. */ - int flush_ok = (fflush(f) == 0); - int close_ok = (fclose(f) == 0); - - if (rc != CURLE_OK || !flush_ok || !close_ok) { - remove(output_path); - return 0; - } - return 1; -} - -el_val_t http_get_to_file(el_val_t url, el_val_t headers_map, el_val_t output_path) { - struct curl_slist* h = headers_from_map(headers_map); - el_val_t r = http_do_to_file("GET", EL_CSTR(url), NULL, h, EL_CSTR(output_path)); - if (h) curl_slist_free_all(h); - return r; -} - -el_val_t http_post_to_file(el_val_t url, el_val_t body, el_val_t headers_map, el_val_t output_path) { - struct curl_slist* h = headers_from_map(headers_map); - el_val_t r = http_do_to_file("POST", EL_CSTR(url), EL_CSTR(body), h, EL_CSTR(output_path)); - if (h) curl_slist_free_all(h); - return r; -} - -/* ── HTTP server (POSIX sockets + pthreads) ──────────────────────────────── */ - -#define HTTP_MAX_CONNS 64 - -typedef el_val_t (*http_handler_fn)(el_val_t method, el_val_t path, el_val_t body); - -typedef struct { - char* name; - http_handler_fn fn; -} HttpHandlerEntry; - -static HttpHandlerEntry _http_handlers[32]; -static size_t _http_handler_count = 0; -static char* _http_active_handler = NULL; -static pthread_mutex_t _http_handler_mu = PTHREAD_MUTEX_INITIALIZER; - -static pthread_mutex_t _http_conn_mu = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t _http_conn_cv = PTHREAD_COND_INITIALIZER; -static int _http_conn_active = 0; - -/* Public C-level API: register a handler by name. Programs that want El - * `http_serve` to dispatch into their handler call this from main() before - * http_serve. Not declared in the header to keep the public API minimal — - * extern lookup works since C symbols are global. */ -void el_runtime_register_handler(const char* name, http_handler_fn fn); -void el_runtime_register_handler(const char* name, http_handler_fn fn) { - if (!name || !fn) return; - pthread_mutex_lock(&_http_handler_mu); - for (size_t i = 0; i < _http_handler_count; i++) { - if (strcmp(_http_handlers[i].name, name) == 0) { - _http_handlers[i].fn = fn; - pthread_mutex_unlock(&_http_handler_mu); - return; - } - } - if (_http_handler_count < sizeof(_http_handlers) / sizeof(_http_handlers[0])) { - _http_handlers[_http_handler_count].name = el_strdup(name); - _http_handlers[_http_handler_count].fn = fn; - _http_handler_count++; - } - pthread_mutex_unlock(&_http_handler_mu); -} - -void http_set_handler(el_val_t name) { - const char* n = EL_CSTR(name); - pthread_mutex_lock(&_http_handler_mu); - free(_http_active_handler); - _http_active_handler = el_strdup(n ? n : ""); - /* If the name is not yet in the registry, try dlsym lookup against - * the running binary's symbol table. Every El `fn name(...)` compiles - * to a global C symbol with that exact name, so El programs can self- - * register their own handlers just by calling http_set_handler("name"). */ - if (n && *n) { - int found = 0; - for (size_t i = 0; i < _http_handler_count; i++) { - if (strcmp(_http_handlers[i].name, n) == 0) { found = 1; break; } - } - if (!found) { - void* sym = dlsym(RTLD_DEFAULT, n); - if (sym && _http_handler_count < sizeof(_http_handlers) / sizeof(_http_handlers[0])) { - _http_handlers[_http_handler_count].name = el_strdup(n); - _http_handlers[_http_handler_count].fn = (http_handler_fn)sym; - _http_handler_count++; - } - } - } - pthread_mutex_unlock(&_http_handler_mu); -} - -static http_handler_fn http_lookup_active(void) { - http_handler_fn out = NULL; - pthread_mutex_lock(&_http_handler_mu); - if (_http_active_handler) { - for (size_t i = 0; i < _http_handler_count; i++) { - if (strcmp(_http_handlers[i].name, _http_active_handler) == 0) { - out = _http_handlers[i].fn; break; - } - } - } - pthread_mutex_unlock(&_http_handler_mu); - return out; -} - -/* Auto-detect Content-Type from response body. */ -static const char* http_detect_content_type(const char* body) { - if (!body) return "text/plain; charset=utf-8"; - const char* p = body; - /* Binary magic bytes — check before stripping whitespace */ - if ((unsigned char)p[0] == 0x89 && p[1]=='P' && p[2]=='N' && p[3]=='G') - return "image/png"; - if ((unsigned char)p[0] == 0xFF && (unsigned char)p[1] == 0xD8) - return "image/jpeg"; - if (strncmp(p, "GIF8", 4) == 0) return "image/gif"; - if (strncmp(p, "RIFF", 4) == 0) return "image/webp"; - if (strncmp(p, "wOFF", 4) == 0) return "font/woff"; - if (strncmp(p, "wOF2", 4) == 0) return "font/woff2"; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (strncasecmp(p, "= cap) { - if (cap >= 1024 * 1024) { free(buf); return -1; } - cap *= 2; - buf = realloc(buf, cap); - if (!buf) return -1; - } - ssize_t n = recv(fd, buf + len, cap - len - 1, 0); - if (n <= 0) { free(buf); return -1; } - len += (size_t)n; - buf[len] = '\0'; - if (strstr(buf, "\r\n\r\n")) break; - } - /* Parse request line */ - char* sp1 = strchr(buf, ' '); - if (!sp1) { free(buf); return -1; } - *sp1 = '\0'; - *out_method = el_strdup(buf); - char* path_start = sp1 + 1; - char* sp2 = strchr(path_start, ' '); - if (!sp2) { free(*out_method); *out_method = NULL; free(buf); return -1; } - *sp2 = '\0'; - *out_path = el_strdup(path_start); - char* hdr_end = strstr(sp2 + 1, "\r\n\r\n"); - /* Capture the raw header block (after the request line's CRLF, up to - * but not including the terminating \r\n\r\n) for callers that asked - * for it. The legacy 3-arg path passes NULL and skips this. */ - if (out_headers_block) { - char* hdr_start = strstr(sp2 + 1, "\r\n"); - if (hdr_start && hdr_start < hdr_end) { - hdr_start += 2; - size_t hb_len = (size_t)(hdr_end - hdr_start); - char* hb = malloc(hb_len + 1); - if (hb) { - memcpy(hb, hdr_start, hb_len); - hb[hb_len] = '\0'; - *out_headers_block = hb; - } - } else { - *out_headers_block = el_strdup(""); - } - } - /* Find Content-Length */ - long content_length = 0; - char* hp = sp2 + 1; - while (hp < hdr_end) { - char* line_end = strstr(hp, "\r\n"); - /* line_end == hdr_end means we're on the LAST header line — its - * trailing \r\n is the same \r\n that begins the \r\n\r\n header - * terminator. Process this line; only stop when line_end is past - * hdr_end (which means the parser walked off the end of the - * header block). The previous condition (line_end >= hdr_end) - * silently dropped any Content-Length that appeared as the last - * header — exactly what real curl/clients tend to emit. */ - if (!line_end || line_end > hdr_end) break; - if (strncasecmp(hp, "Content-Length:", 15) == 0) { - content_length = strtol(hp + 15, NULL, 10); - if (content_length < 0) content_length = 0; - if (content_length > 64 * 1024 * 1024) content_length = 64 * 1024 * 1024; - } - hp = line_end + 2; - } - /* Body: any bytes already read past hdr_end, plus more recv */ - char* body_start = hdr_end + 4; - size_t body_have = (buf + len) - body_start; - char* body = malloc((size_t)content_length + 1); - if (!body) { free(*out_method); free(*out_path); *out_method=NULL; *out_path=NULL; free(buf); return -1; } - if ((long)body_have > content_length) body_have = (size_t)content_length; - if (body_have > 0) memcpy(body, body_start, body_have); - while ((long)body_have < content_length) { - ssize_t n = recv(fd, body + body_have, (size_t)content_length - body_have, 0); - if (n <= 0) break; - body_have += (size_t)n; - } - body[body_have] = '\0'; - *out_body = body; - free(buf); - return 0; -} - -/* Reason phrase for common HTTP statuses. Falls back to "Status" for the - * long tail — clients only care about the numeric code. */ -static const char* http_reason_phrase(int status) { - switch (status) { - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 204: return "No Content"; - case 301: return "Moved Permanently"; - case 302: return "Found"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 307: return "Temporary Redirect"; - case 308: return "Permanent Redirect"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 422: return "Unprocessable Entity"; - case 429: return "Too Many Requests"; - case 500: return "Internal Server Error"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Timeout"; - default: return "Status"; - } -} - -/* Best-effort send with retry on partial writes. */ -static int http_send_all(int fd, const char* p, size_t left) { - while (left > 0) { - ssize_t w = send(fd, p, left, 0); - if (w <= 0) return -1; - p += w; left -= (size_t)w; - } - return 0; -} - -/* Discriminator that http_response() embeds at the start of its envelope. - * A handler returning a string starting with this exact prefix is treated - * as a structured response; anything else is treated as a raw body. */ -#define EL_HTTP_RESPONSE_TAG "{\"el_http_response\":1" - -/* Keys that conflict with runtime-managed headers are silently dropped to - * avoid double-emission — the runtime always emits its own Content-Length - * and Connection: close. Content-Type from the envelope IS allowed and - * overrides auto-detection. */ -static int http_header_is_managed(const char* k) { - return strcasecmp(k, "Content-Length") == 0 - || strcasecmp(k, "Connection") == 0; -} - -/* Walk an ElMap of header pairs and emit each as `K: V\r\n` into JsonBuf b. - * Sets *out_saw_content_type to 1 if the map contained an explicit - * Content-Type so the caller can skip auto-detection. */ -static void http_emit_headers_from_map(JsonBuf* b, el_val_t headers_map, - int* out_saw_content_type) { - *out_saw_content_type = 0; - if (headers_map == 0) return; - ElMap* m = (ElMap*)(uintptr_t)headers_map; - if (!m || m->hdr.magic != EL_MAGIC_MAP) return; - for (int64_t i = 0; i < m->count; i++) { - const char* k = EL_CSTR(m->keys[i]); - const char* v = EL_CSTR(m->values[i]); - if (!k || !v) continue; - if (http_header_is_managed(k)) continue; - if (strcasecmp(k, "Content-Type") == 0) *out_saw_content_type = 1; - jb_puts(b, k); - jb_puts(b, ": "); - jb_puts(b, v); - jb_puts(b, "\r\n"); - } -} - -/* Parse the envelope produced by http_response(). On success returns 1 and - * populates *out_status, *out_headers_map (an ElMap el_val_t — caller must - * el_release), and *out_body (allocated). On failure returns 0. - * - * Implementation: feeds the entire envelope through the recursive-descent - * JSON parser (which builds proper ElMap/ElList values), then pulls the - * three top-level fields by name. Avoids re-stringifying the headers map - * since json_stringify() does not support nested objects. */ -static int http_parse_envelope(const char* s, int* out_status, - el_val_t* out_headers_map, char** out_body, - el_val_t* out_parsed_root) { - if (!s) return 0; - if (strncmp(s, EL_HTTP_RESPONSE_TAG, - sizeof(EL_HTTP_RESPONSE_TAG) - 1) != 0) return 0; - - el_val_t parsed = json_parse(EL_STR(s)); - if (parsed == EL_NULL) return 0; - - int status = 200; - el_val_t hmap = 0; - char* body = NULL; - - el_val_t sv = el_map_get(parsed, EL_STR("status")); - if (sv != 0) { - /* status comes back as an integer — el_val_t holds it directly. */ - long sc = (long)sv; - if (sc >= 100 && sc <= 599) status = (int)sc; - } - - el_val_t hv = el_map_get(parsed, EL_STR("headers")); - if (hv != 0) { - ElMap* hm = (ElMap*)(uintptr_t)hv; - if (hm && hm->hdr.magic == EL_MAGIC_MAP) hmap = hv; - } - - el_val_t bv = el_map_get(parsed, EL_STR("body")); - if (bv != 0) { - const char* bs = EL_CSTR(bv); - if (bs) body = el_strdup(bs); - } - if (!body) body = el_strdup(""); - - *out_status = status; - *out_headers_map = hmap; - *out_body = body; - *out_parsed_root = parsed; /* caller releases to free hmap + entries */ - return 1; -} - -/* Lightweight `__status__` envelope: if the body's first key is `__status__` - * and its value is a numeric literal, lift the status to the HTTP layer and - * strip the marker from the body before sending. This is the common case for - * El handlers that want to return 4xx/5xx without going through - * http_response() — they just prepend `{"__status__":,...}` to the JSON - * they were already returning. - * - * We deliberately recognise ONLY the first-key form so the contract is cheap - * to detect and unambiguous: `{"__status__":401,"error":"unauthorized"}` is - * an envelope, but `{"error":"...","__status__":401}` is not. Product code - * controls placement. - * - * On success returns 1 with *out_status set and *out_body_alloc populated - * with a freshly malloc'd body (caller frees). On failure returns 0 and - * leaves outputs untouched. */ -static int http_parse_status_envelope(const char* s, int* out_status, - char** out_body_alloc) { - if (!s) return 0; - const char* p = s; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '{') return 0; - p++; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - static const char marker[] = "\"__status__\""; - size_t mlen = sizeof(marker) - 1; - if (strncmp(p, marker, mlen) != 0) return 0; - p += mlen; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != ':') return 0; - p++; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p < '0' || *p > '9') return 0; /* non-numeric -> not an envelope */ - int status = 0; - while (*p >= '0' && *p <= '9') { - status = status * 10 + (*p - '0'); - p++; - } - if (status < 100 || status > 599) return 0; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - /* Two trailing shapes accepted: - * ,"k":v,...} -> body becomes {"k":v,...} - * } -> body becomes {} - * Anything else (e.g. `:` re-appearing, garbage) drops the envelope so - * we don't strip what we shouldn't. */ - if (*p == '}') { - *out_status = status; - *out_body_alloc = el_strdup("{}"); - return 1; - } - if (*p != ',') return 0; - p++; /* skip the comma; the rest of the object follows */ - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - /* Build the trimmed body: '{' + remainder. */ - size_t rest_len = strlen(p); - char* out = (char*)malloc(rest_len + 2); - if (!out) return 0; - out[0] = '{'; - memcpy(out + 1, p, rest_len); - out[rest_len + 1] = '\0'; - *out_status = status; - *out_body_alloc = out; - return 1; -} - -/* Send a fully-built HTTP response. If `body` starts with the envelope tag, - * unpack status/headers/body. Otherwise emit the historical 200-OK with - * auto-detected Content-Type. */ -/* Thread-local flag: if 1, http_send_response writes status + headers but - * NO body (HEAD method behaviour). Set by http_worker before calling - * http_send_response, cleared after. */ -static __thread int _tl_http_head_only = 0; - -static void http_send_response(int fd, const char* body) { - if (!body) body = ""; - - int status = 200; - el_val_t env_headers_map = 0; - char* env_body = NULL; - el_val_t env_parsed_root = 0; - int is_envelope = http_parse_envelope(body, &status, - &env_headers_map, &env_body, - &env_parsed_root); - - /* If the rich http_response() envelope didn't claim this body, try the - * lightweight `__status__` form. This second envelope is malloc-backed so - * we route it through env_body and let the existing cleanup path free it - * — same lifetime contract, no special case at the bottom of the - * function. */ - if (!is_envelope) { - char* trimmed = NULL; - if (http_parse_status_envelope(body, &status, &trimmed)) { - env_body = trimmed; - is_envelope = 1; - } - } - - const char* eff_body = is_envelope ? env_body : body; - /* Use the real byte count from fs_read if available (handles binary files - * with embedded null bytes — PNG, WOFF2, etc.). Fall back to strlen for - * normal text/JSON responses where _tl_fs_read_len is 0. */ - size_t blen = (_tl_fs_read_len > 0) ? _tl_fs_read_len : strlen(eff_body); - _tl_fs_read_len = 0; /* consume — one-shot per response */ - int head_only = _tl_http_head_only; - - JsonBuf hdrs; jb_init(&hdrs); - int saw_content_type = 0; - if (is_envelope) { - http_emit_headers_from_map(&hdrs, env_headers_map, - &saw_content_type); - } - if (!saw_content_type) { - jb_puts(&hdrs, "Content-Type: "); - jb_puts(&hdrs, http_detect_content_type(eff_body)); - jb_puts(&hdrs, "\r\n"); - } - - char status_line[64]; - int sl = snprintf(status_line, sizeof(status_line), - "HTTP/1.1 %d %s\r\n", - status, http_reason_phrase(status)); - if (sl < 0) { - if (env_parsed_root) el_release(env_parsed_root); - free(env_body); free(hdrs.buf); return; - } - - char tail[128]; - int tl = snprintf(tail, sizeof(tail), - "Content-Length: %zu\r\n" - "Connection: close\r\n" - "\r\n", blen); - if (tl < 0) { - if (env_parsed_root) el_release(env_parsed_root); - free(env_body); free(hdrs.buf); return; - } - - if (http_send_all(fd, status_line, (size_t)sl) == 0 - && http_send_all(fd, hdrs.buf, hdrs.len) == 0 - && http_send_all(fd, tail, (size_t)tl) == 0 - && (head_only - /* HEAD requests echo headers + Content-Length but no body. */ - ? 1 - : http_send_all(fd, eff_body, blen) == 0)) { - /* sent successfully */ - } - - if (env_parsed_root) el_release(env_parsed_root); - free(env_body); - free(hdrs.buf); -} - -typedef struct { - int fd; -} HttpWorkerArg; - -static void* http_worker(void* arg) { - HttpWorkerArg* a = (HttpWorkerArg*)arg; - int fd = a->fd; - free(a); - char *method = NULL, *path = NULL, *body = NULL; - if (http_read_request(fd, &method, &path, &body, NULL) == 0) { - http_handler_fn h = http_lookup_active(); - char* response = NULL; - /* HEAD: dispatch as GET so existing handlers respond with the same - * body, but flag the response writer to emit headers only. RFC 9110 - * requires HEAD to mirror GET headers + Content-Length without body. */ - int head_only = (method && strcmp(method, "HEAD") == 0); - const char* dispatch_method = head_only ? "GET" : method; - el_request_start(); /* begin per-request arena */ - if (h) { - el_val_t r = h(EL_STR(dispatch_method), EL_STR(path), EL_STR(body)); - const char* rs = EL_CSTR(r); - /* Copy response out BEFORE arena teardown. - * For binary files, _tl_fs_read_len holds the real byte count — - * use memcpy instead of strdup so null bytes are preserved. */ - size_t rlen = _tl_fs_read_len > 0 ? _tl_fs_read_len : (rs ? strlen(rs) : 0); - response = malloc(rlen + 1); - if (response && rs) { memcpy(response, rs, rlen); response[rlen] = '\0'; } - else if (response) { response[0] = '\0'; } - } else { - response = el_strdup_persist("el-runtime: no http handler registered"); - } - el_request_end(); /* free all intermediate strings */ - _tl_http_head_only = head_only; - http_send_response(fd, response); - _tl_http_head_only = 0; - free(response); - } - free(method); free(path); free(body); - close(fd); - /* release a slot */ - pthread_mutex_lock(&_http_conn_mu); - _http_conn_active--; - pthread_cond_signal(&_http_conn_cv); - pthread_mutex_unlock(&_http_conn_mu); - return NULL; -} - -void http_serve(el_val_t port, el_val_t handler) { - /* If `handler` looks like a string name, register it as the active handler. */ - const char* hname = EL_CSTR(handler); - if (hname && looks_like_string(handler)) { - http_set_handler(handler); - } - int p = (int)port; - if (p <= 0 || p > 65535) { fprintf(stderr, "http_serve: invalid port %d\n", p); return; } - /* Dual-stack: AF_INET6 with IPV6_V6ONLY=0 accepts both IPv4 and IPv6. - * This makes `localhost` work in browsers that resolve it to ::1 first. */ - int sock = socket(AF_INET6, SOCK_STREAM, 0); - if (sock < 0) { perror("socket"); return; } - int yes = 1; int no = 0; - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no)); - struct sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_addr = in6addr_any; - addr.sin6_port = htons((uint16_t)p); - if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - perror("bind"); close(sock); return; - } - if (listen(sock, 64) < 0) { perror("listen"); close(sock); return; } - fprintf(stderr, "[http] listening on [::]:%d (dual-stack)\n", p); - while (1) { - struct sockaddr_in6 cli; - socklen_t clen = sizeof(cli); - int cfd = accept(sock, (struct sockaddr*)&cli, &clen); - if (cfd < 0) { - if (errno == EINTR) continue; - perror("accept"); break; - } - pthread_mutex_lock(&_http_conn_mu); - while (_http_conn_active >= HTTP_MAX_CONNS) { - pthread_cond_wait(&_http_conn_cv, &_http_conn_mu); - } - _http_conn_active++; - pthread_mutex_unlock(&_http_conn_mu); - HttpWorkerArg* arg = malloc(sizeof(HttpWorkerArg)); - if (!arg) { close(cfd); continue; } - arg->fd = cfd; - pthread_t tid; - if (pthread_create(&tid, NULL, http_worker, arg) != 0) { - close(cfd); free(arg); - pthread_mutex_lock(&_http_conn_mu); - _http_conn_active--; - pthread_cond_signal(&_http_conn_cv); - pthread_mutex_unlock(&_http_conn_mu); - continue; - } - pthread_detach(tid); - } - close(sock); -} - -/* ── HTTP server v2 — request headers + structured response ──────────────── */ -/* - * v2 widens the handler signature from - * (method, path, body) -> body_string - * to - * (method, path, headers_map, body) -> body_string_or_envelope - * - * The response envelope is detected uniformly inside http_send_response — so - * 4-arg handlers can return either a plain body or http_response(...). The - * 3-arg path stays untouched in spirit (its handlers still build plain - * bodies; the envelope tag, being `{"el_http_response":1`, will never - * collide with normal JSON the legacy server.el routes return). - * - * Registry is parallel to the 3-arg handler registry: separate name table, - * separate active-handler slot, separate dlsym fallback. Mixing v1 and v2 - * handlers in the same process is fine — they don't share the active slot. */ - -typedef el_val_t (*http_handler4_fn)(el_val_t method, el_val_t path, - el_val_t headers_map, el_val_t body); - -typedef struct { - char* name; - http_handler4_fn fn; -} HttpHandler4Entry; - -static HttpHandler4Entry _http_handlers4[32]; -static size_t _http_handler4_count = 0; -static char* _http_active_handler4 = NULL; - -void el_runtime_register_handler_v2(const char* name, http_handler4_fn fn); -void el_runtime_register_handler_v2(const char* name, http_handler4_fn fn) { - if (!name || !fn) return; - pthread_mutex_lock(&_http_handler_mu); - for (size_t i = 0; i < _http_handler4_count; i++) { - if (strcmp(_http_handlers4[i].name, name) == 0) { - _http_handlers4[i].fn = fn; - pthread_mutex_unlock(&_http_handler_mu); - return; - } - } - if (_http_handler4_count < - sizeof(_http_handlers4) / sizeof(_http_handlers4[0])) { - _http_handlers4[_http_handler4_count].name = el_strdup(name); - _http_handlers4[_http_handler4_count].fn = fn; - _http_handler4_count++; - } - pthread_mutex_unlock(&_http_handler_mu); -} - -void http_set_handler_v2(el_val_t name) { - const char* n = EL_CSTR(name); - pthread_mutex_lock(&_http_handler_mu); - free(_http_active_handler4); - _http_active_handler4 = el_strdup(n ? n : ""); - if (n && *n) { - int found = 0; - for (size_t i = 0; i < _http_handler4_count; i++) { - if (strcmp(_http_handlers4[i].name, n) == 0) { found = 1; break; } - } - if (!found) { - void* sym = dlsym(RTLD_DEFAULT, n); - if (sym && _http_handler4_count < - sizeof(_http_handlers4) / sizeof(_http_handlers4[0])) { - _http_handlers4[_http_handler4_count].name = el_strdup(n); - _http_handlers4[_http_handler4_count].fn = - (http_handler4_fn)sym; - _http_handler4_count++; - } - } - } - pthread_mutex_unlock(&_http_handler_mu); -} - -static http_handler4_fn http_lookup_active_v2(void) { - http_handler4_fn out = NULL; - pthread_mutex_lock(&_http_handler_mu); - if (_http_active_handler4) { - for (size_t i = 0; i < _http_handler4_count; i++) { - if (strcmp(_http_handlers4[i].name, - _http_active_handler4) == 0) { - out = _http_handlers4[i].fn; break; - } - } - } - pthread_mutex_unlock(&_http_handler_mu); - return out; -} - -/* Build an ElMap from the raw header block produced by http_read_request. - * Keys are lowercased (RFC 7230 — case-insensitive); values have leading - * whitespace trimmed. Repeated headers with the same name are joined with - * ", " in arrival order, matching standard library behaviour elsewhere. */ -static el_val_t http_build_headers_map(const char* hdr_block) { - el_val_t m = el_map_new(0); - if (!hdr_block || !*hdr_block) return m; - const char* p = hdr_block; - while (*p) { - const char* line_end = strstr(p, "\r\n"); - const char* end = line_end ? line_end : p + strlen(p); - const char* colon = NULL; - for (const char* c = p; c < end; c++) { - if (*c == ':') { colon = c; break; } - } - if (colon && colon > p) { - size_t klen = (size_t)(colon - p); - char* key = malloc(klen + 1); - if (key) { - for (size_t i = 0; i < klen; i++) { - unsigned char ch = (unsigned char)p[i]; - key[i] = (char)tolower(ch); - } - key[klen] = '\0'; - const char* vstart = colon + 1; - while (vstart < end && (*vstart == ' ' || *vstart == '\t')) vstart++; - size_t vlen = (size_t)(end - vstart); - /* Strip trailing OWS just in case. */ - while (vlen > 0 - && (vstart[vlen - 1] == ' ' - || vstart[vlen - 1] == '\t')) vlen--; - /* Coalesce repeats: if key already present, append ", value". */ - el_val_t existing = el_map_get(m, EL_STR(key)); - if (existing != 0 && looks_like_string(existing)) { - const char* old = EL_CSTR(existing); - size_t olen = strlen(old); - char* combined = malloc(olen + 2 + vlen + 1); - if (combined) { - memcpy(combined, old, olen); - memcpy(combined + olen, ", ", 2); - memcpy(combined + olen + 2, vstart, vlen); - combined[olen + 2 + vlen] = '\0'; - m = el_map_set(m, EL_STR(key), EL_STR(combined)); - } - free(key); - } else { - char* val = malloc(vlen + 1); - if (val) { - memcpy(val, vstart, vlen); - val[vlen] = '\0'; - m = el_map_set(m, EL_STR(key), EL_STR(val)); - } else { - free(key); - } - } - } - } - if (!line_end) break; - p = line_end + 2; - } - return m; -} - -static void* http_worker_v2(void* arg) { - HttpWorkerArg* a = (HttpWorkerArg*)arg; - int fd = a->fd; - free(a); - int is_sse = 0; - char *method = NULL, *path = NULL, *body = NULL, *hdr_block = NULL; - if (http_read_request(fd, &method, &path, &body, &hdr_block) == 0) { - http_handler4_fn h = http_lookup_active_v2(); - char* response = NULL; - int head_only = (method && strcmp(method, "HEAD") == 0); - const char* dispatch_method = head_only ? "GET" : method; - el_request_start(); /* begin per-request arena */ - /* Expose the raw fd to El SSE builtins (__http_conn_fd etc.). */ - el_seed_set_http_conn_fd(fd); - if (h) { - el_val_t hmap = http_build_headers_map(hdr_block ? hdr_block : ""); - el_val_t r = h(EL_STR(dispatch_method), EL_STR(path), hmap, EL_STR(body)); - const char* rs = EL_CSTR(r); - /* Detect SSE sentinel — handler took ownership of the fd. */ - if (rs && strcmp(rs, "__sse__") == 0) { - is_sse = 1; - } else { - size_t rlen = _tl_fs_read_len > 0 ? _tl_fs_read_len : (rs ? strlen(rs) : 0); - response = malloc(rlen + 1); - if (response && rs) { memcpy(response, rs, rlen); response[rlen] = '\0'; } - else if (response) { response[0] = '\0'; } - } - el_release(hmap); - } else { - response = el_strdup_persist( - "el-runtime: no v2 http handler registered " - "(call http_set_handler_v2)"); - } - el_seed_set_http_conn_fd(-1); /* clear before arena teardown */ - el_request_end(); /* free all intermediate strings */ - if (!is_sse) { - _tl_http_head_only = head_only; - http_send_response(fd, response); - _tl_http_head_only = 0; - free(response); - } - } - free(method); free(path); free(body); free(hdr_block); - /* SSE handlers close the fd themselves via __http_sse_close. */ - if (!is_sse) close(fd); - pthread_mutex_lock(&_http_conn_mu); - _http_conn_active--; - pthread_cond_signal(&_http_conn_cv); - pthread_mutex_unlock(&_http_conn_mu); - return NULL; -} - -void http_serve_v2(el_val_t port, el_val_t handler) { - const char* hname = EL_CSTR(handler); - if (hname && looks_like_string(handler)) { - http_set_handler_v2(handler); - } - int p = (int)port; - if (p <= 0 || p > 65535) { - fprintf(stderr, "http_serve_v2: invalid port %d\n", p); - return; - } - /* Dual-stack: same as http_serve - AF_INET6 + IPV6_V6ONLY=0. */ - int sock = socket(AF_INET6, SOCK_STREAM, 0); - if (sock < 0) { perror("socket"); return; } - int yes = 1; int no = 0; - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); - setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no)); - struct sockaddr_in6 addr; - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - addr.sin6_addr = in6addr_any; - addr.sin6_port = htons((uint16_t)p); - if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - perror("bind"); close(sock); return; - } - if (listen(sock, 64) < 0) { perror("listen"); close(sock); return; } - fprintf(stderr, "[http v2] listening on [::]:%d (dual-stack)\n", p); - while (1) { - struct sockaddr_in6 cli; - socklen_t clen = sizeof(cli); - int cfd = accept(sock, (struct sockaddr*)&cli, &clen); - if (cfd < 0) { - if (errno == EINTR) continue; - perror("accept"); break; - } - pthread_mutex_lock(&_http_conn_mu); - while (_http_conn_active >= HTTP_MAX_CONNS) { - pthread_cond_wait(&_http_conn_cv, &_http_conn_mu); - } - _http_conn_active++; - pthread_mutex_unlock(&_http_conn_mu); - HttpWorkerArg* arg = malloc(sizeof(HttpWorkerArg)); - if (!arg) { close(cfd); continue; } - arg->fd = cfd; - pthread_t tid; - if (pthread_create(&tid, NULL, http_worker_v2, arg) != 0) { - close(cfd); free(arg); - pthread_mutex_lock(&_http_conn_mu); - _http_conn_active--; - pthread_cond_signal(&_http_conn_cv); - pthread_mutex_unlock(&_http_conn_mu); - continue; - } - pthread_detach(tid); - } - close(sock); -} - -/* Build the response envelope a 4-arg handler can return. We hand-write - * the JSON so the discriminator key always lands first — the runtime's - * http_parse_envelope() detects it via prefix match. headers_json must be - * either "" (empty), "{}" (empty object), or a well-formed JSON object - * literal; anything else will produce a malformed envelope and the runtime - * will treat the whole string as a plain body (no envelope detected). */ -el_val_t http_response(el_val_t status, el_val_t headers_json, el_val_t body) { - long sc = (long)status; - if (sc < 100 || sc > 599) sc = 200; - const char* hj = EL_CSTR(headers_json); - if (!hj || !*hj) hj = "{}"; - /* Light validation: must start with '{' and end with '}'. */ - size_t hlen = strlen(hj); - int hj_ok = (hlen >= 2 && hj[0] == '{' && hj[hlen - 1] == '}'); - if (!hj_ok) hj = "{}"; - const char* b = EL_CSTR(body); - if (!b) b = ""; - - JsonBuf out; jb_init(&out); - jb_puts(&out, EL_HTTP_RESPONSE_TAG); /* {"el_http_response":1 */ - jb_puts(&out, ",\"status\":"); - char num[32]; - snprintf(num, sizeof(num), "%ld", sc); - jb_puts(&out, num); - jb_puts(&out, ",\"headers\":"); - jb_puts(&out, hj); - jb_puts(&out, ",\"body\":"); - jb_emit_escaped(&out, b); - jb_putc(&out, '}'); - return el_wrap_str(out.buf); -} - -/* ── Filesystem ──────────────────────────────────────────────────────────── */ - -el_val_t fs_read(el_val_t pathv) { - const char* path = EL_CSTR(pathv); - _tl_fs_read_len = 0; - if (!path) return el_wrap_str(el_strdup("")); - FILE* f = fopen(path, "rb"); - if (!f) return el_wrap_str(el_strdup("")); - fseek(f, 0, SEEK_END); - long sz = ftell(f); - rewind(f); - if (sz < 0) { fclose(f); return el_wrap_str(el_strdup("")); } /* pipe/special file */ - char* buf = el_strbuf((size_t)sz); - size_t got = fread(buf, 1, (size_t)sz, f); - buf[got] = '\0'; - _tl_fs_read_len = got; /* store real byte count for binary-safe send */ - fclose(f); - return el_wrap_str(buf); -} - -el_val_t fs_write(el_val_t pathv, el_val_t contentv) { - const char* path = EL_CSTR(pathv); - const char* content = EL_CSTR(contentv); - if (!path || !content) return 0; - FILE* f = fopen(path, "wb"); - if (!f) return 0; - size_t n = strlen(content); - size_t written = fwrite(content, 1, n, f); - fclose(f); - return written == n ? 1 : 0; -} - -/* fs_write_bytes — explicit-length binary write. Bypasses strlen so embedded - * NULs survive. Caller must know the byte count (e.g. from base64_decode, - * or the fixed 32-byte sha256_bytes/hmac_sha256_bytes outputs). - * - * If `length` is negative, treats as failure. If `length` is 0, creates an - * empty file (still useful as a "touch with content" primitive). */ -el_val_t fs_write_bytes(el_val_t pathv, el_val_t bytesv, el_val_t lengthv) { - const char* path = EL_CSTR(pathv); - const char* bytes = EL_CSTR(bytesv); - int64_t n = (int64_t)lengthv; - if (!path || !bytes) return 0; - if (n < 0) return 0; - FILE* f = fopen(path, "wb"); - if (!f) return 0; - size_t written = (n > 0) ? fwrite(bytes, 1, (size_t)n, f) : 0; - int flush_ok = (fflush(f) == 0); - int close_ok = (fclose(f) == 0); - if (!flush_ok || !close_ok || written != (size_t)n) { - remove(path); - return 0; - } - return 1; -} - -// exec_command — run a shell command, return exit code (0 = success). -// Used by elb and other El tooling to invoke subprocesses. -el_val_t exec_command(el_val_t cmdv) { - const char* cmd = EL_CSTR(cmdv); - if (!cmd) return (el_val_t)(int64_t)-1; - int ret = system(cmd); - return (el_val_t)(int64_t)ret; -} - -// exec_capture — run a shell command, capture stdout, return as String. -// Returns "" on failure. -el_val_t exec_capture(el_val_t cmdv) { - const char* cmd = EL_CSTR(cmdv); - if (!cmd) return el_wrap_str(el_strdup("")); - FILE* f = popen(cmd, "r"); - if (!f) return el_wrap_str(el_strdup("")); - JsonBuf b; jb_init(&b); - char buf[4096]; - while (fgets(buf, sizeof(buf), f)) jb_puts(&b, buf); - pclose(f); - return el_wrap_str(b.buf); -} - -// exec — run a shell command via /bin/sh, capture stdout, return as String. -// Times out after 30 seconds. Returns "" on any error. -// El name: exec(cmd) -> String -el_val_t exec(el_val_t cmdv) { - const char* cmd = EL_CSTR(cmdv); - if (!cmd || !*cmd) return el_wrap_str(el_strdup("")); - /* Build a time-limited command: wrap with timeout(1) if available, - * otherwise rely on the 30s read loop guard below. We use the simple - * popen approach with a deadline measured by wall clock so the caller - * is never blocked indefinitely. */ - FILE* f = popen(cmd, "r"); - if (!f) return el_wrap_str(el_strdup("")); - JsonBuf b; jb_init(&b); - char buf[4096]; - /* 30-second wall-clock deadline */ - time_t deadline = time(NULL) + 30; - while (time(NULL) < deadline) { - if (fgets(buf, sizeof(buf), f) == NULL) break; - jb_puts(&b, buf); - } - pclose(f); - return el_wrap_str(b.buf); -} - -// exec_bg — run a shell command in background, return PID as String. -// The child process runs independently; the caller is not blocked. -// Returns "" on fork failure. -// El name: exec_bg(cmd) -> String -el_val_t exec_bg(el_val_t cmdv) { - const char* cmd = EL_CSTR(cmdv); - if (!cmd || !*cmd) return el_wrap_str(el_strdup("")); - pid_t pid = fork(); - if (pid < 0) { - /* fork failed */ - return el_wrap_str(el_strdup("")); - } - if (pid == 0) { - /* child: detach from parent's stdio, exec via shell */ - setsid(); - int devnull = open("/dev/null", O_RDWR); - if (devnull >= 0) { - dup2(devnull, STDIN_FILENO); - dup2(devnull, STDOUT_FILENO); - dup2(devnull, STDERR_FILENO); - close(devnull); - } - execl("/bin/sh", "sh", "-c", cmd, (char*)NULL); - _exit(127); - } - /* parent: convert pid to string and return immediately */ - char pidbuf[32]; - snprintf(pidbuf, sizeof(pidbuf), "%d", (int)pid); - return el_wrap_str(el_strdup(pidbuf)); -} - -el_val_t fs_list(el_val_t pathv) { - const char* path = EL_CSTR(pathv); - el_val_t lst = el_list_empty(); - if (!path) return lst; - DIR* d = opendir(path); - if (!d) return lst; - struct dirent* e; - while ((e = readdir(d)) != NULL) { - if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) continue; - lst = el_list_append(lst, el_wrap_str(el_strdup(e->d_name))); - } - closedir(d); - return lst; -} - -/* fs_exists — true iff stat(path) succeeds. Symlinks are followed. */ -el_val_t fs_exists(el_val_t pathv) { - const char* path = EL_CSTR(pathv); - if (!path || !*path) return 0; - struct stat st; - return (el_val_t)(stat(path, &st) == 0 ? 1 : 0); -} - -/* fs_mkdir — create directory at path with mode 0755, mkdir -p semantics. - * Returns 1 if path exists or was created (incl. all parents); 0 on failure. - * Walks the path component-by-component so missing intermediate dirs are - * also created. An existing leaf is not an error. */ -el_val_t fs_mkdir(el_val_t pathv) { - const char* path = EL_CSTR(pathv); - if (!path || !*path) return 0; - size_t n = strlen(path); - char* buf = malloc(n + 1); - if (!buf) return 0; - memcpy(buf, path, n + 1); - /* Walk components; create each prefix in turn. */ - for (size_t i = 1; i <= n; i++) { - if (buf[i] == '/' || buf[i] == '\0') { - char saved = buf[i]; - buf[i] = '\0'; - if (buf[0] != '\0') { - if (mkdir(buf, 0755) != 0 && errno != EEXIST) { - /* Tolerate the case where this prefix exists as a non-dir - * only when stat says it's a directory. */ - struct stat st; - if (stat(buf, &st) != 0 || !S_ISDIR(st.st_mode)) { - free(buf); - return 0; - } - } - } - buf[i] = saved; - } - } - free(buf); - return 1; -} - -/* ── URL encoding ─────────────────────────────────────────────────────────── */ - -/* RFC 3986 percent-encoding for URL components (form bodies, query strings). - * Unreserved set: A-Z a-z 0-9 - _ . ~ — passed through verbatim. - * Everything else (including space) becomes %XX hex. */ -el_val_t url_encode(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - static const char hex[] = "0123456789ABCDEF"; - size_t n = strlen(s); - char* out = el_strbuf(n * 3); - size_t o = 0; - for (size_t i = 0; i < n; i++) { - unsigned char c = (unsigned char)s[i]; - if ((c >= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || - c == '-' || c == '_' || c == '.' || c == '~') { - out[o++] = (char)c; - } else { - out[o++] = '%'; - out[o++] = hex[(c >> 4) & 0xF]; - out[o++] = hex[c & 0xF]; - } - } - out[o] = '\0'; - return el_wrap_str(out); -} - -/* Decode percent-encoded URL component. '+' becomes space (form-encoded); - * malformed %-escapes are emitted verbatim. */ -el_val_t url_decode(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - size_t n = strlen(s); - char* out = el_strbuf(n); - size_t o = 0; - for (size_t i = 0; i < n; i++) { - char c = s[i]; - if (c == '+') { - out[o++] = ' '; - } else if (c == '%' && i + 2 < n) { - char h1 = s[i + 1], h2 = s[i + 2]; - int v1 = (h1 >= '0' && h1 <= '9') ? h1 - '0' - : (h1 >= 'a' && h1 <= 'f') ? h1 - 'a' + 10 - : (h1 >= 'A' && h1 <= 'F') ? h1 - 'A' + 10 : -1; - int v2 = (h2 >= '0' && h2 <= '9') ? h2 - '0' - : (h2 >= 'a' && h2 <= 'f') ? h2 - 'a' + 10 - : (h2 >= 'A' && h2 <= 'F') ? h2 - 'A' + 10 : -1; - if (v1 >= 0 && v2 >= 0) { - out[o++] = (char)((v1 << 4) | v2); - i += 2; - } else { - out[o++] = c; - } - } else { - out[o++] = c; - } - } - out[o] = '\0'; - return el_wrap_str(out); -} - -/* ── HTML allowlist sanitizer ──────────────────────────────────────────────── - * el_html_sanitize(input, allowlist_json) - * - * Strict allowlist HTML cleaner. Replaces the older denylist patterns - * (str_replace cascades that wrapped dangerous tags in HTML comments and - * renamed `on*` attributes). The denylist approach is fragile: comment- - * wrapping can be re-broken by a literal `-->` inside an attacker-supplied - * attribute value, and every new attack vector requires a code change. - * - * Design: - * - Single-pass byte-level state machine. - * - Tag and attribute names are matched case-insensitively against the - * allowlist. Unknown tags are dropped entirely (the open and close - * markers are stripped; their inner text content survives, escaped). - * - A small set of "dangerous container" tags (script, style, iframe, - * object, embed, form, plus a few rarer ones) drop themselves AND - * their full subtree — text between `` is - * CDATA-like and must not be re-emitted as escaped text either. - * - Comments (), doctype (), CDATA (), - * and processing instructions () are dropped entirely. - * - Text content outside dropped subtrees is HTML-escaped (&, <, >, ", '). - * - Attribute values are unquoted/dequoted, then re-emitted with double - * quotes around the cleanly-escaped value. - * - For `` and any `src` attribute, the URL scheme is validated: - * only http:, https:, mailto:, fragment-only `#anchor`, or relative - * paths are allowed. Anything else (javascript:, data:, vbscript:, - * about:, file:, etc.) drops the attribute. - * - Self-closing void tags (br, hr, img, etc.) emit without a close tag. - * - Malformed input (unclosed tag at EOF, bad attribute syntax) drops - * the pending tag and continues. Pre-encoded entities (<, &, - * etc.) are passed through verbatim — the browser will decode them - * safely on render. - * - * Allowlist format (JSON string): - * {"p":[],"a":["href","title"],"strong":[],...} - * - Key = lowercase tag name. - * - Value = JSON array of allowed attribute names (lowercase). - * - Empty array means tag allowed but no attributes survive. - * - * Output is a freshly-allocated arena-tracked el_val_t string. */ - -/* Internal byte buffer with realloc-doubling. Used during sanitization; - * the final result is copied into an arena-tracked el_strbuf so the caller - * sees standard runtime memory semantics. */ -typedef struct { - char* data; - size_t len; - size_t cap; -} html_buf_t; - -static void html_buf_init(html_buf_t* b) { - b->cap = 256; - b->data = malloc(b->cap); - if (!b->data) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - b->len = 0; -} - -static void html_buf_grow(html_buf_t* b, size_t need) { - if (b->len + need + 1 <= b->cap) return; - size_t nc = b->cap; - while (b->len + need + 1 > nc) nc *= 2; - char* nd = realloc(b->data, nc); - if (!nd) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - b->data = nd; - b->cap = nc; -} - -static void html_buf_putc(html_buf_t* b, char c) { - html_buf_grow(b, 1); - b->data[b->len++] = c; -} - -static void html_buf_puts(html_buf_t* b, const char* s) { - if (!s) return; - size_t n = strlen(s); - html_buf_grow(b, n); - memcpy(b->data + b->len, s, n); - b->len += n; -} - -static void html_buf_free(html_buf_t* b) { - free(b->data); - b->data = NULL; - b->len = b->cap = 0; -} - -/* ASCII tolower, locale-independent. */ -static int html_tolower(int c) { - return (c >= 'A' && c <= 'Z') ? c + 32 : c; -} - -/* Case-insensitive ASCII compare of [a, a+n) against c-string `s`. - * Returns 1 iff lengths match and bytes are equal under tolower. */ -static int html_ieq_n(const char* a, size_t n, const char* s) { - if (!a || !s) return 0; - if (strlen(s) != n) return 0; - for (size_t i = 0; i < n; i++) { - if (html_tolower((unsigned char)a[i]) != html_tolower((unsigned char)s[i])) return 0; - } - return 1; -} - -/* Case-insensitive ASCII compare of two byte slices. */ -static int html_iemem(const char* a, const char* b, size_t n) { - for (size_t i = 0; i < n; i++) { - if (html_tolower((unsigned char)a[i]) != html_tolower((unsigned char)b[i])) return 0; - } - return 1; -} - -/* Walk a JSON allowlist object and find the value (an array) for a given - * tag key, comparing case-insensitively. On hit returns a pointer to the - * opening `[` of the array and writes the byte length of the array span - * (including the brackets) to *out_len. On miss returns NULL. - * - * The parser is intentionally tiny: it does not handle escapes inside - * keys (allowlist authors do not need them), and it relies on balanced - * brackets/quotes within the value array. */ -static const char* html_allowlist_find(const char* allow, const char* tag, - size_t tag_len, size_t* out_len) { - if (!allow) return NULL; - const char* p = allow; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '{') return NULL; - p++; - while (*p) { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p == '}' || *p == 0) return NULL; - if (*p != '"') return NULL; - p++; - const char* k = p; - while (*p && *p != '"') p++; - if (*p != '"') return NULL; - size_t klen = (size_t)(p - k); - p++; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != ':') return NULL; - p++; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') return NULL; - const char* arr_start = p; - int depth = 0; - int in_str = 0; - while (*p) { - char c = *p; - if (in_str) { - if (c == '\\' && p[1]) { p += 2; continue; } - if (c == '"') in_str = 0; - } else { - if (c == '"') in_str = 1; - else if (c == '[') depth++; - else if (c == ']') { depth--; if (depth == 0) { p++; break; } } - } - p++; - } - size_t alen = (size_t)(p - arr_start); - int match = (klen == tag_len) && html_iemem(k, tag, klen); - if (match) { - if (out_len) *out_len = alen; - return arr_start; - } - } - return NULL; -} - -/* Returns 1 iff `attr` (length attr_len) appears as a string element - * in the JSON array slice [arr, arr+arr_len). Comparison is case- - * insensitive. */ -static int html_attr_in_array(const char* arr, size_t arr_len, - const char* attr, size_t attr_len) { - if (!arr || arr_len < 2) return 0; - const char* p = arr + 1; - const char* end = arr + arr_len - 1; - while (p < end) { - while (p < end && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',')) p++; - if (p >= end) return 0; - if (*p != '"') return 0; - p++; - const char* s = p; - while (p < end && *p != '"') { - if (*p == '\\' && p + 1 < end) p++; - p++; - } - if (p >= end) return 0; - size_t slen = (size_t)(p - s); - p++; - if (slen == attr_len && html_iemem(s, attr, slen)) return 1; - } - return 0; -} - -/* Hard-coded set of tags whose content is ALSO dropped (entire subtree). */ -static int html_is_dangerous_container(const char* tag, size_t tag_len) { - static const char* names[] = { - "script", "style", "iframe", "object", "embed", "form", - "noscript", "noembed", "template", "svg", "math", "frame", - "frameset", "applet", "audio", "video", "source", "track", - NULL - }; - for (int i = 0; names[i]; i++) { - if (html_ieq_n(tag, tag_len, names[i])) return 1; - } - return 0; -} - -/* HTML void elements — emit without a close tag. */ -static int html_is_void(const char* tag, size_t tag_len) { - static const char* names[] = { - "area", "base", "br", "col", "embed", "hr", "img", "input", - "link", "meta", "param", "source", "track", "wbr", - NULL - }; - for (int i = 0; names[i]; i++) { - if (html_ieq_n(tag, tag_len, names[i])) return 1; - } - return 0; -} - -/* Append a single byte HTML-escaped into the output buffer. */ -static void html_escape_byte(html_buf_t* out, unsigned char c) { - switch (c) { - case '<': html_buf_puts(out, "<"); break; - case '>': html_buf_puts(out, ">"); break; - case '"': html_buf_puts(out, """); break; - case '\'': html_buf_puts(out, "'"); break; - default: html_buf_putc(out, (char)c); break; - } -} - -/* Validate a URL value against the allowlist of safe schemes for hrefs. - * Returns 1 iff the URL is safe to emit. Acceptable forms: - * - http:// or https:// (case-insensitive) - * - mailto: - * - fragment-only `#anchor` - * - relative path that does not contain a colon before the first - * slash/?/# (so `foo/bar`, `/foo`, `?x=1` are OK; `javascript:x` is - * not — its colon precedes any path/hash/query separator). - * - * URL leading whitespace and embedded ASCII control bytes (TAB, LF, CR) - * are stripped before the scheme test, mirroring how browsers normalise - * URLs (these bytes are otherwise a known XSS bypass: `java\tscript:`). */ -static int html_url_is_safe(const char* url, size_t len) { - if (!url || len == 0) return 1; /* empty href is harmless */ - size_t i = 0; - while (i < len) { - unsigned char c = (unsigned char)url[i]; - if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == 0x0B || c == 0x0C) { - i++; continue; - } - break; - } - if (i >= len) return 1; /* whitespace only */ - if (url[i] == '#') return 1; /* fragment only */ - if (url[i] == '/' || url[i] == '?') return 1; /* relative */ - /* Find the first scheme-terminating character. */ - size_t scheme_end = (size_t)-1; - for (size_t j = i; j < len; j++) { - char c = url[j]; - if (c == ':') { scheme_end = j; break; } - if (c == '/' || c == '?' || c == '#') break; - } - if (scheme_end == (size_t)-1) return 1; /* no colon → relative path */ - /* Lowercase the scheme, stripping embedded control bytes. */ - char scheme[32]; - size_t sl = 0; - for (size_t j = i; j < scheme_end && sl < sizeof(scheme) - 1; j++) { - unsigned char c = (unsigned char)url[j]; - if (c == '\t' || c == '\n' || c == '\r' || c == 0x0B || c == 0x0C) continue; - scheme[sl++] = (char)html_tolower(c); - } - scheme[sl] = '\0'; - if (strcmp(scheme, "http") == 0) return 1; - if (strcmp(scheme, "https") == 0) return 1; - if (strcmp(scheme, "mailto") == 0) return 1; - return 0; -} - -el_val_t el_html_sanitize(el_val_t input_v, el_val_t allowlist_v) { - const char* input = EL_CSTR(input_v); - const char* allow = EL_CSTR(allowlist_v); - if (!input) return el_wrap_str(el_strdup("")); - if (!allow) allow = "{}"; - size_t in_len = strlen(input); - - html_buf_t out; - html_buf_init(&out); - - size_t i = 0; - while (i < in_len) { - unsigned char c = (unsigned char)input[i]; - if (c != '<') { - /* Plain text — escape and emit. We pass `&` through verbatim - * to preserve pre-encoded entities (`<`, `&`, `&#x...;`) - * which the browser will decode safely. */ - if (c == '&') html_buf_putc(&out, '&'); - else html_escape_byte(&out, c); - i++; - continue; - } - /* `<` — try to parse a tag. */ - if (i + 1 >= in_len) { - html_buf_puts(&out, "<"); - i++; - continue; - } - /* Comments, doctype, CDATA, processing instructions — drop entirely. */ - if (input[i + 1] == '!') { - if (i + 3 < in_len && input[i + 2] == '-' && input[i + 3] == '-') { - size_t j = i + 4; - while (j + 2 < in_len && !(input[j] == '-' && input[j + 1] == '-' && input[j + 2] == '>')) j++; - if (j + 2 < in_len) i = j + 3; - else i = in_len; - continue; - } - size_t j = i + 2; - while (j < in_len && input[j] != '>') j++; - i = (j < in_len) ? j + 1 : in_len; - continue; - } - if (input[i + 1] == '?') { - size_t j = i + 2; - while (j < in_len && input[j] != '>') j++; - i = (j < in_len) ? j + 1 : in_len; - continue; - } - int is_close = 0; - size_t name_start = i + 1; - if (input[i + 1] == '/') { - is_close = 1; - name_start = i + 2; - } - if (name_start >= in_len) { - html_buf_puts(&out, "<"); - i++; - continue; - } - unsigned char nc = (unsigned char)input[name_start]; - if (!((nc >= 'a' && nc <= 'z') || (nc >= 'A' && nc <= 'Z'))) { - /* `<` followed by non-letter — emit as escaped text. */ - html_buf_puts(&out, "<"); - i++; - continue; - } - size_t name_end = name_start; - while (name_end < in_len) { - unsigned char x = (unsigned char)input[name_end]; - if ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || - (x >= '0' && x <= '9') || x == '-' || x == '_' || x == ':') { - name_end++; - } else { - break; - } - } - const char* tag = input + name_start; - size_t tag_len = name_end - name_start; - /* Find the `>` that closes this tag, respecting quoted attrs. */ - size_t cur = name_end; - int self_close = 0; - while (cur < in_len) { - unsigned char x = (unsigned char)input[cur]; - if (x == '"' || x == '\'') { - unsigned char q = x; - cur++; - while (cur < in_len && (unsigned char)input[cur] != q) cur++; - if (cur < in_len) cur++; /* skip closing quote */ - continue; - } - if (x == '/' && cur + 1 < in_len && input[cur + 1] == '>') { - self_close = 1; - break; - } - if (x == '>') break; - cur++; - } - if (cur >= in_len) { - /* Malformed: unclosed tag at EOF. Drop the rest of the input. */ - i = in_len; - continue; - } - size_t tag_end = self_close ? cur + 2 : cur + 1; /* one past `>` */ - /* Dangerous container — drop the whole subtree. */ - if (!is_close && html_is_dangerous_container(tag, tag_len)) { - if (self_close || html_is_void(tag, tag_len)) { - i = tag_end; - continue; - } - size_t scan = tag_end; - int found_close = 0; - while (scan < in_len) { - if (input[scan] != '<') { scan++; continue; } - if (scan + 1 < in_len && input[scan + 1] == '/') { - size_t cn_start = scan + 2; - size_t cn_end = cn_start; - while (cn_end < in_len) { - unsigned char x = (unsigned char)input[cn_end]; - if ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || - (x >= '0' && x <= '9') || x == '-' || x == '_' || x == ':') { - cn_end++; - } else break; - } - if (cn_end - cn_start == tag_len && - html_iemem(input + cn_start, tag, tag_len)) { - size_t end_close = cn_end; - while (end_close < in_len && input[end_close] != '>') end_close++; - i = (end_close < in_len) ? end_close + 1 : in_len; - found_close = 1; - break; - } - } - scan++; - } - if (!found_close) { - /* No matching close — drop everything from here on. */ - i = in_len; - } - continue; - } - /* Look up the tag in the allowlist. */ - size_t arr_len = 0; - const char* arr = html_allowlist_find(allow, tag, tag_len, &arr_len); - if (!arr) { - /* Tag not allowed. Drop the open/close marker; inner text is - * processed by the outer loop and re-emitted as escaped text. */ - i = tag_end; - continue; - } - if (is_close) { - if (!html_is_void(tag, tag_len)) { - html_buf_putc(&out, '<'); - html_buf_putc(&out, '/'); - for (size_t k = 0; k < tag_len; k++) { - html_buf_putc(&out, (char)html_tolower((unsigned char)tag[k])); - } - html_buf_putc(&out, '>'); - } - i = tag_end; - continue; - } - /* Allowed open tag. Emit ``. */ - html_buf_putc(&out, '<'); - for (size_t k = 0; k < tag_len; k++) { - html_buf_putc(&out, (char)html_tolower((unsigned char)tag[k])); - } - size_t a = name_end; - while (a < cur) { - unsigned char x = (unsigned char)input[a]; - if (x == ' ' || x == '\t' || x == '\n' || x == '\r' || x == '/') { a++; continue; } - size_t an_start = a; - while (a < cur) { - unsigned char y = (unsigned char)input[a]; - if (y == '=' || y == ' ' || y == '\t' || y == '\n' || y == '\r' || y == '/' || y == '>') break; - a++; - } - size_t an_len = a - an_start; - if (an_len == 0) { a++; continue; } - size_t av_start = 0; - size_t av_len = 0; - int has_value = 0; - size_t b = a; - while (b < cur && (input[b] == ' ' || input[b] == '\t' || input[b] == '\n' || input[b] == '\r')) b++; - if (b < cur && input[b] == '=') { - has_value = 1; - b++; - while (b < cur && (input[b] == ' ' || input[b] == '\t' || input[b] == '\n' || input[b] == '\r')) b++; - if (b < cur && (input[b] == '"' || input[b] == '\'')) { - unsigned char q = (unsigned char)input[b]; - b++; - av_start = b; - while (b < cur && (unsigned char)input[b] != q) b++; - av_len = b - av_start; - if (b < cur) b++; - } else { - av_start = b; - while (b < cur) { - unsigned char y = (unsigned char)input[b]; - if (y == ' ' || y == '\t' || y == '\n' || y == '\r' || y == '>') break; - b++; - } - av_len = b - av_start; - } - a = b; - } - if (!html_attr_in_array(arr, arr_len, input + an_start, an_len)) continue; - int is_href = (an_len == 4 && html_iemem(input + an_start, "href", 4)); - int is_src = (an_len == 3 && html_iemem(input + an_start, "src", 3)); - if ((is_href || is_src) && has_value) { - if (!html_url_is_safe(input + av_start, av_len)) continue; - } - html_buf_putc(&out, ' '); - for (size_t k = 0; k < an_len; k++) { - html_buf_putc(&out, (char)html_tolower((unsigned char)input[an_start + k])); - } - if (has_value) { - html_buf_puts(&out, "=\""); - for (size_t k = 0; k < av_len; k++) { - unsigned char y = (unsigned char)input[av_start + k]; - /* Re-escape so the emitted attribute is well-formed - * double-quoted HTML. `&` passes through to preserve - * pre-encoded entities. */ - if (y == '"') html_buf_puts(&out, """); - else if (y == '<') html_buf_puts(&out, "<"); - else if (y == '>') html_buf_puts(&out, ">"); - else html_buf_putc(&out, (char)y); - } - html_buf_putc(&out, '"'); - } - } - html_buf_putc(&out, '>'); - i = tag_end; - } - /* Copy into arena-tracked buffer so the standard runtime memory model - * applies to the returned string. */ - char* result = el_strbuf(out.len); - memcpy(result, out.data, out.len); - result[out.len] = '\0'; - html_buf_free(&out); - return el_wrap_str(result); -} - -/* ── JSON ────────────────────────────────────────────────────────────────── */ - -/* True iff the segment is non-empty and every byte is an ASCII digit. We treat - * such segments as numeric array indices when walking a dot-path; mixed names - * like "0a" remain object-key lookups, so a key named "0" still wins over an - * index when the surrounding container is an object. */ -static int json_path_seg_is_index(const char* seg, size_t n) { - if (n == 0) return 0; - for (size_t i = 0; i < n; i++) { - if (seg[i] < '0' || seg[i] > '9') return 0; - } - return 1; -} - -/* Skip JSON whitespace. */ -static const char* json_skip_ws(const char* p) { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - return p; -} - -/* Descend one segment into the JSON cursor `p`. - * - If `p` points at an array `[...]` and the segment is all digits, - * advance to that element (zero-based). - * - Otherwise treat the segment as an object key and use json_find_key - * scoped to a one-level slice of the current container. - * Returns NULL if the descent fails (segment not found, container mismatch). - * - * `seg` is a pointer into the original path string and `seg_len` is its - * byte length — this avoids an extra alloc per segment. */ -static const char* json_path_descend(const char* p, const char* seg, size_t seg_len) { - if (!p || !seg) return NULL; - p = json_skip_ws(p); - if (*p == '[' && json_path_seg_is_index(seg, seg_len)) { - long idx = 0; - for (size_t i = 0; i < seg_len; i++) idx = idx * 10 + (seg[i] - '0'); - p++; /* step past '[' */ - p = json_skip_ws(p); - long cur = 0; - while (*p && *p != ']') { - if (cur == idx) return p; - const char* end = json_skip_value(p); - if (!end || end == p) return NULL; - p = json_skip_ws(end); - if (*p == ',') { p++; p = json_skip_ws(p); cur++; continue; } - /* No comma after this element — only acceptable at the closing ']', - * which means we ran out of elements. */ - break; - } - return NULL; - } - /* Object lookup. json_find_key walks at depth 1 of whatever container it - * receives, so we slice from `p` onwards. Caller already positioned us at - * the opening '{' (or at whitespace before it). */ - if (*p != '{') return NULL; - /* Build a NUL-terminated copy of the key segment for the lookup. We only - * pay this cost when the segment isn't a numeric index. */ - char stack_key[256]; - char* k = stack_key; - if (seg_len + 1 > sizeof(stack_key)) { - k = malloc(seg_len + 1); - if (!k) return NULL; - } - memcpy(k, seg, seg_len); - k[seg_len] = '\0'; - const char* found = json_find_key(p, k); - if (k != stack_key) free(k); - return found; -} - -/* Read the JSON value at `p` into a freshly-allocated, arena-owned el_val_t. - * - String -> unescaped, wrapped el_val_t string - * - Anything else -> raw JSON slice as a string (matches the historical - * json_get behaviour: numbers/bools/null come back stringified). */ -static el_val_t json_read_value(const char* p) { - p = json_skip_ws(p); - if (*p == '"') { - p++; - size_t cap = strlen(p) + 1; - char* out = el_strbuf(cap); - char* w = out; - while (*p && *p != '"') { - if (*p == '\\' && *(p+1)) { - p++; - switch (*p) { - case '"': *w++ = '"'; break; - case '\\': *w++ = '\\'; break; - case '/': *w++ = '/'; break; - case 'n': *w++ = '\n'; break; - case 'r': *w++ = '\r'; break; - case 't': *w++ = '\t'; break; - default: *w++ = *p; break; - } - } else { - *w++ = *p; - } - p++; - } - *w = '\0'; - return el_wrap_str(out); - } - /* Object/array/number/bool/null — return the raw slice up to the value's - * end. json_skip_value tracks brace/bracket/string state so nested objects - * round-trip cleanly. */ - const char* end = json_skip_value(p); - if (!end) end = p; - size_t n = (size_t)(end - p); - /* Strip trailing whitespace from scalar values so callers don't see - * `123 ` when they parsed a pretty-printed number. */ - while (n > 0 && (p[n-1] == ' ' || p[n-1] == '\t' || p[n-1] == '\n' || p[n-1] == '\r')) { - n--; - } - char* out = el_strbuf(n); - memcpy(out, p, n); - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t json_get(el_val_t jsonv, el_val_t keyv) { - const char* json = EL_CSTR(jsonv); - const char* key = EL_CSTR(keyv); - if (!json || !key) return el_wrap_str(el_strdup("")); - - /* Fast path: key contains no '.' — keep the historical single-segment - * substring search so existing callers retain their O(strlen) cost - * profile. The dot-path walker is only paid for when needed. */ - if (!strchr(key, '.')) { - size_t klen = strlen(key); - char stack_pat[512]; - char* pattern; - if (klen + 5 <= sizeof(stack_pat)) { - pattern = stack_pat; - } else { - pattern = malloc(klen + 5); - if (!pattern) return el_wrap_str(el_strdup("")); - } - snprintf(pattern, klen + 5, "\"%s\":", key); - const char* p = strstr(json, pattern); - if (pattern != stack_pat) free(pattern); - if (!p) return el_wrap_str(el_strdup("")); - p += strlen(key) + 3; /* skip "key": */ - return json_read_value(p); - } - - /* Dot-path traversal. Walk segments left to right; at each step, descend - * into the current container by either array index (all-digit segment on - * an array cursor) or object key. */ - const char* cursor = json_skip_ws(json); - const char* seg_start = key; - const char* k = key; - while (1) { - if (*k == '.' || *k == '\0') { - size_t seg_len = (size_t)(k - seg_start); - cursor = json_path_descend(cursor, seg_start, seg_len); - if (!cursor) return el_wrap_str(el_strdup("")); - if (*k == '\0') break; - k++; - seg_start = k; - continue; - } - k++; - } - return json_read_value(cursor); -} - -/* ── Float bit-cast helpers ──────────────────────────────────────────────── */ -/* `el_to_float` and `el_from_float` are exposed in el_runtime.h as static - * inlines so generated programs (which #include the header) can call them - * for Float literals. No definitions are needed here. */ - -/* ── JSON parser (recursive descent) ─────────────────────────────────────── */ -/* - * Parsed JSON representation: - * - object -> ElMap (keys & values are el_val_t) - * - array -> ElList - * - string -> EL_STR-wrapped char* (allocated) - * - number -> int (el_val_t) if integer, otherwise el_from_float(double) - * - true -> 1 - * - false -> 0 - * - null -> EL_NULL (0) - * - * Note: there is no runtime type tag — parsed numbers cannot be - * distinguished from booleans by the runtime alone. The codegen tracks - * types separately. This matches the rest of el_val_t's type-erased model. - */ - -/* JsonParser struct is forward-declared near the HTTP/Engram section. */ - -static void jp_skip_ws(JsonParser* jp) { - while (jp->p < jp->end) { - char c = *jp->p; - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') jp->p++; - else break; - } -} - -static el_val_t jp_parse_value(JsonParser* jp); - -/* Parse a JSON string literal (the opening " has NOT yet been consumed). */ -static char* jp_parse_string_raw(JsonParser* jp) { - if (jp->p >= jp->end || *jp->p != '"') { jp->err = 1; return el_strdup(""); } - jp->p++; - size_t cap = 32, len = 0; - char* out = malloc(cap); - if (!out) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - while (jp->p < jp->end && *jp->p != '"') { - char c = *jp->p++; - if (c == '\\' && jp->p < jp->end) { - char esc = *jp->p++; - switch (esc) { - case '"': c = '"'; break; - case '\\': c = '\\'; break; - case '/': c = '/'; break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'u': { - /* Skip 4 hex digits; emit '?' as a placeholder */ - for (int i = 0; i < 4 && jp->p < jp->end; i++) jp->p++; - c = '?'; - break; - } - default: c = esc; break; - } - } - if (len + 1 >= cap) { - cap *= 2; - out = realloc(out, cap); - if (!out) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - } - out[len++] = c; - } - if (jp->p < jp->end && *jp->p == '"') jp->p++; - else jp->err = 1; - out[len] = '\0'; - return out; -} - -static el_val_t jp_parse_number(JsonParser* jp) { - const char* start = jp->p; - int is_float = 0; - if (jp->p < jp->end && (*jp->p == '-' || *jp->p == '+')) jp->p++; - while (jp->p < jp->end && isdigit((unsigned char)*jp->p)) jp->p++; - if (jp->p < jp->end && *jp->p == '.') { - is_float = 1; jp->p++; - while (jp->p < jp->end && isdigit((unsigned char)*jp->p)) jp->p++; - } - if (jp->p < jp->end && (*jp->p == 'e' || *jp->p == 'E')) { - is_float = 1; jp->p++; - if (jp->p < jp->end && (*jp->p == '+' || *jp->p == '-')) jp->p++; - while (jp->p < jp->end && isdigit((unsigned char)*jp->p)) jp->p++; - } - size_t n = (size_t)(jp->p - start); - char buf[64]; - if (n >= sizeof(buf)) n = sizeof(buf) - 1; - memcpy(buf, start, n); - buf[n] = '\0'; - if (is_float) return el_from_float(strtod(buf, NULL)); - return (el_val_t)strtoll(buf, NULL, 10); -} - -static el_val_t jp_parse_array(JsonParser* jp) { - if (jp->p < jp->end && *jp->p == '[') jp->p++; - el_val_t lst = el_list_empty(); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == ']') { jp->p++; return lst; } - while (jp->p < jp->end) { - jp_skip_ws(jp); - el_val_t v = jp_parse_value(jp); - lst = el_list_append(lst, v); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == ',') { jp->p++; continue; } - if (jp->p < jp->end && *jp->p == ']') { jp->p++; break; } - jp->err = 1; - break; - } - return lst; -} - -static el_val_t jp_parse_object(JsonParser* jp) { - if (jp->p < jp->end && *jp->p == '{') jp->p++; - el_val_t m = el_map_new(0); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == '}') { jp->p++; return m; } - while (jp->p < jp->end) { - jp_skip_ws(jp); - char* key = jp_parse_string_raw(jp); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == ':') jp->p++; - else { jp->err = 1; free(key); break; } - jp_skip_ws(jp); - el_val_t v = jp_parse_value(jp); - m = el_map_set(m, EL_STR(key), v); - jp_skip_ws(jp); - if (jp->p < jp->end && *jp->p == ',') { jp->p++; continue; } - if (jp->p < jp->end && *jp->p == '}') { jp->p++; break; } - jp->err = 1; - break; - } - return m; -} - -static el_val_t jp_parse_value(JsonParser* jp) { - jp_skip_ws(jp); - if (jp->p >= jp->end) { jp->err = 1; return EL_NULL; } - char c = *jp->p; - if (c == '"') return el_wrap_str(jp_parse_string_raw(jp)); - if (c == '{') return jp_parse_object(jp); - if (c == '[') return jp_parse_array(jp); - if (c == '-' || isdigit((unsigned char)c)) return jp_parse_number(jp); - if (c == 't' && jp->p + 4 <= jp->end && strncmp(jp->p, "true", 4) == 0) { jp->p += 4; return 1; } - if (c == 'f' && jp->p + 5 <= jp->end && strncmp(jp->p, "false", 5) == 0) { jp->p += 5; return 0; } - if (c == 'n' && jp->p + 4 <= jp->end && strncmp(jp->p, "null", 4) == 0) { jp->p += 4; return EL_NULL; } - jp->err = 1; - return EL_NULL; -} - -el_val_t json_parse(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return EL_NULL; - JsonParser jp = { .p = s, .end = s + strlen(s), .err = 0 }; - el_val_t v = jp_parse_value(&jp); - if (jp.err) return EL_NULL; - return v; -} - -/* ── JSON stringify ──────────────────────────────────────────────────────── */ -/* - * Stringify policy: el_val_t is type-erased, so we cannot perfectly - * round-trip arbitrary values. We use these heuristics: - * - If value is an ElList pointer (in the heap range), serialize as array. - * - If value is an ElMap pointer, serialize as object. - * - If value looks like a printable string pointer, serialize as string. - * - Otherwise serialize as integer. - * This is best-effort. Programs that need exact control should build the - * string directly. A pointer test is the cheapest way to disambiguate - * from small integers without a separate type tag. - */ - -/* JsonBuf struct is forward-declared near the HTTP section so HTTP helpers - * can use it. Its definition appears there. */ - -static void jb_init(JsonBuf* b) { - b->cap = 64; b->len = 0; - b->buf = malloc(b->cap); - if (!b->buf) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - b->buf[0] = '\0'; -} - -static void jb_reserve(JsonBuf* b, size_t add) { - if (b->len + add + 1 > b->cap) { - while (b->len + add + 1 > b->cap) b->cap *= 2; - b->buf = realloc(b->buf, b->cap); - if (!b->buf) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - } -} - -static void jb_putc(JsonBuf* b, char c) { - jb_reserve(b, 1); - b->buf[b->len++] = c; - b->buf[b->len] = '\0'; -} - -static void jb_puts(JsonBuf* b, const char* s) { - size_t n = strlen(s); - jb_reserve(b, n); - memcpy(b->buf + b->len, s, n); - b->len += n; - b->buf[b->len] = '\0'; -} - -static void jb_emit_escaped(JsonBuf* b, const char* s) { - jb_putc(b, '"'); - for (; *s; s++) { - unsigned char c = (unsigned char)*s; - switch (c) { - case '"': jb_puts(b, "\\\""); break; - case '\\': jb_puts(b, "\\\\"); break; - case '\b': jb_puts(b, "\\b"); break; - case '\f': jb_puts(b, "\\f"); break; - case '\n': jb_puts(b, "\\n"); break; - case '\r': jb_puts(b, "\\r"); break; - case '\t': jb_puts(b, "\\t"); break; - default: - if (c < 0x20) { - char tmp[8]; - snprintf(tmp, sizeof(tmp), "\\u%04x", c); - jb_puts(b, tmp); - } else { - jb_putc(b, (char)c); - } - break; - } - } - jb_putc(b, '"'); -} - -/* Heuristic: is this el_val_t likely a pointer to an ElList? - * We can't fully verify, but pointers are large addresses, integers small. - * Treat values whose magnitude exceeds 2^32 as potential pointers and - * sniff by reading the header conservatively. - * - * Simpler heuristic: if the value reads as a printable string, treat as - * string; otherwise as integer. Lists/Maps are encoded as struct pointers, - * which have leading binary bytes — so they won't look like strings. */ - -static int looks_like_string(el_val_t v) { - if (v == 0) return 0; - /* Treat plausible heap addresses as candidates. - * Threshold: 4 GiB (0x100000000). On 64-bit systems heap addresses from - * malloc/mmap start well above 4 GiB (ASLR pushes them to ~0x7f...). - * El integer values (counters, unix timestamps up to ~2106) all fit below - * 0x100000000 (4294967296). The old threshold of 1,000,000 caused unix - * timestamps (~1.7e9) to be misidentified as string pointers — a segfault - * risk in json_stringify and jb_emit_value. */ - uintptr_t p = (uintptr_t)v; - if (p < 0x100000000ULL) return 0; /* integers, timestamps, counters */ - if (p < 0x1000) return 0; - /* Sniff first bytes for printable */ - const unsigned char* s = (const unsigned char*)p; - for (int i = 0; i < 16; i++) { - unsigned char c = s[i]; - if (c == '\0') return 1; /* terminated string (empty string is still a valid string) */ - /* Reject C0 control chars (non-whitespace), allow UTF-8 high bytes. - * 0x09-0x0d = tab/newline/cr/vt/ff (whitespace, OK) - * 0x20-0x7e = printable ASCII (OK) - * 0x7f = DEL (reject) - * 0x80-0xff = UTF-8 continuation/lead bytes (OK for multi-byte chars) */ - if (c < 0x09 || (c > 0x0d && c < 0x20) || c == 0x7f) return 0; - } - return 1; /* 16+ printable bytes — call it a string */ -} - -static void jb_emit_value(JsonBuf* b, el_val_t v); - -static void jb_emit_int(JsonBuf* b, int64_t n) { - char tmp[32]; - snprintf(tmp, sizeof(tmp), "%lld", (long long)n); - jb_puts(b, tmp); -} - -static void jb_emit_value(JsonBuf* b, el_val_t v) { - if (v == EL_NULL) { jb_puts(b, "null"); return; } - if (looks_like_string(v)) { - jb_emit_escaped(b, EL_CSTR(v)); - return; - } - jb_emit_int(b, (int64_t)v); -} - -el_val_t json_stringify(el_val_t v) { - JsonBuf b; jb_init(&b); - jb_emit_value(&b, v); - return el_wrap_str(b.buf); -} - -/* ── JSON substring accessors ────────────────────────────────────────────── */ -/* - * These walk the raw JSON string looking for "key": at the top level (depth 1) - * of an object. They handle escaped quotes, nested objects/arrays, and - * whitespace around the colon. - */ - -/* Find "key": at object-depth == 1 inside the JSON object string `s`. - * Returns pointer to the first byte of the value, or NULL. */ -static const char* json_find_key(const char* s, const char* key) { - if (!s || !key) return NULL; - size_t klen = strlen(key); - int depth = 0; - int in_str = 0; - int escape = 0; - const char* p = s; - while (*p) { - char c = *p; - if (in_str) { - if (escape) { escape = 0; } - else if (c == '\\') { escape = 1; } - else if (c == '"') { - /* End of string. If we're at depth 1, check if this was a key. */ - p++; - if (depth == 1) { - /* The string just ended at p-1. Check if it matches key - * and is followed by a colon. We need to backtrack to find - * the start of this string and compare. */ - } - in_str = 0; - continue; - } - p++; - continue; - } - if (c == '"') { - /* Start of a string literal */ - const char* str_start = p + 1; - const char* q = str_start; - int e = 0; - while (*q) { - if (e) { e = 0; q++; continue; } - if (*q == '\\') { e = 1; q++; continue; } - if (*q == '"') break; - q++; - } - size_t slen = (size_t)(q - str_start); - const char* after = (*q == '"') ? q + 1 : q; - /* If at depth 1 and matches key and followed by ':' -> got it */ - if (depth == 1 && slen == klen && strncmp(str_start, key, klen) == 0) { - const char* r = after; - while (*r == ' ' || *r == '\t' || *r == '\n' || *r == '\r') r++; - if (*r == ':') { - r++; - while (*r == ' ' || *r == '\t' || *r == '\n' || *r == '\r') r++; - return r; - } - } - p = after; - continue; - } - if (c == '{' || c == '[') depth++; - else if (c == '}' || c == ']') depth--; - p++; - } - return NULL; -} - -/* Skip a JSON value starting at p; return pointer past the value end. */ -static const char* json_skip_value(const char* p) { - if (!p || !*p) return p; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p == '"') { - p++; - int e = 0; - while (*p) { - if (e) { e = 0; p++; continue; } - if (*p == '\\') { e = 1; p++; continue; } - if (*p == '"') { p++; break; } - p++; - } - return p; - } - if (*p == '{' || *p == '[') { - char open = *p; - char close = (open == '{') ? '}' : ']'; - int depth = 0; - int in_str = 0; - int e = 0; - while (*p) { - char c = *p; - if (in_str) { - if (e) { e = 0; } - else if (c == '\\') { e = 1; } - else if (c == '"') in_str = 0; - p++; - continue; - } - if (c == '"') { in_str = 1; p++; continue; } - if (c == open) depth++; - else if (c == close) { depth--; p++; if (depth == 0) return p; continue; } - p++; - } - return p; - } - /* scalar: number, true/false/null */ - while (*p && *p != ',' && *p != '}' && *p != ']' && - *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') p++; - return p; -} - -el_val_t json_get_string(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - if (!p || *p != '"') return el_wrap_str(el_strdup("")); - p++; - JsonParser jp = { .p = p - 1, .end = json + (json ? strlen(json) : 0), .err = 0 }; - char* parsed = jp_parse_string_raw(&jp); - if (jp.err) { free(parsed); return el_wrap_str(el_strdup("")); } - return el_wrap_str(parsed); -} - -el_val_t json_get_int(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - if (!p) return 0; - if (*p == '"' || *p == '{' || *p == '[') return 0; - return (el_val_t)strtoll(p, NULL, 10); -} - -el_val_t json_get_float(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - if (!p) return 0; - if (*p == '"' || *p == '{' || *p == '[') return 0; - return el_from_float(strtod(p, NULL)); -} - -el_val_t json_get_bool(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - if (!p) return 0; - if (strncmp(p, "true", 4) == 0) return 1; - return 0; -} - -el_val_t json_get_raw(el_val_t json_str, el_val_t key) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - const char* p = json_find_key(json, k); - /* Clear fs_read binary-length hint — result is a fresh null-terminated - * string, not the raw file bytes, so Content-Length must use strlen. */ - _tl_fs_read_len = 0; - if (!p) return el_wrap_str(el_strdup("")); - const char* end = json_skip_value(p); - size_t n = (size_t)(end - p); - char* out = el_strbuf(n); - memcpy(out, p, n); - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t json_set(el_val_t json_str, el_val_t key, el_val_t value) { - const char* json = EL_CSTR(json_str); - const char* k = EL_CSTR(key); - if (!k) k = ""; - if (!json || !*json) { - /* Build a fresh object */ - JsonBuf b; jb_init(&b); - jb_putc(&b, '{'); - jb_emit_escaped(&b, k); - jb_putc(&b, ':'); - jb_emit_value(&b, value); - jb_putc(&b, '}'); - return el_wrap_str(b.buf); - } - const char* existing = json_find_key(json, k); - JsonBuf b; jb_init(&b); - if (existing) { - const char* end = json_skip_value(existing); - /* Copy [json .. existing) */ - size_t prefix = (size_t)(existing - json); - jb_reserve(&b, prefix); - memcpy(b.buf + b.len, json, prefix); - b.len += prefix; - b.buf[b.len] = '\0'; - jb_emit_value(&b, value); - jb_puts(&b, end); - return el_wrap_str(b.buf); - } - /* Insert before closing '}'. Find last '}' */ - size_t jl = strlen(json); - if (jl == 0) { free(b.buf); return el_wrap_str(el_strdup("{}")); } - /* Find last '}' from the end */ - ssize_t close_idx = -1; - for (ssize_t i = (ssize_t)jl - 1; i >= 0; i--) { - if (json[i] == '}') { close_idx = i; break; } - } - if (close_idx < 0) { - free(b.buf); - return el_wrap_str(el_strdup(json)); - } - /* Determine if object is empty: scan between last '{' and '}' for non-ws */ - int empty = 1; - for (ssize_t i = close_idx - 1; i >= 0; i--) { - char c = json[i]; - if (c == '{') break; - if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { empty = 0; break; } - } - /* Copy json[0..close_idx) */ - jb_reserve(&b, (size_t)close_idx); - memcpy(b.buf + b.len, json, (size_t)close_idx); - b.len += (size_t)close_idx; - b.buf[b.len] = '\0'; - if (!empty) jb_putc(&b, ','); - jb_emit_escaped(&b, k); - jb_putc(&b, ':'); - jb_emit_value(&b, value); - /* Append from close_idx onward */ - jb_puts(&b, json + close_idx); - return el_wrap_str(b.buf); -} - -el_val_t json_array_len(el_val_t json_str) { - const char* s = EL_CSTR(json_str); - if (!s) return 0; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s != '[') return 0; - s++; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ']') return 0; - int64_t count = 0; - while (*s) { - const char* end = json_skip_value(s); - if (end == s) break; - count++; - s = end; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ',') { s++; continue; } - if (*s == ']' || *s == '\0') break; - } - return (el_val_t)count; -} - -/* json_array_get — return the i-th element of a JSON array as a JSON - * fragment string. Nested objects and arrays are returned verbatim - * (json_skip_value tracks brace/bracket depth so nested structures are - * preserved intact). Out-of-range index → "". */ -el_val_t json_array_get(el_val_t json_str, el_val_t index) { - const char* s = EL_CSTR(json_str); - int64_t idx = (int64_t)index; - if (!s || idx < 0) return el_wrap_str(el_strdup("")); - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s != '[') return el_wrap_str(el_strdup("")); - s++; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ']') return el_wrap_str(el_strdup("")); - int64_t i = 0; - while (*s) { - const char* start = s; - const char* end = json_skip_value(s); - if (end == s) break; - if (i == idx) { - size_t n = (size_t)(end - start); - char* out = el_strbuf(n); - memcpy(out, start, n); - out[n] = '\0'; - return el_wrap_str(out); - } - i++; - s = end; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == ',') { s++; while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; continue; } - if (*s == ']' || *s == '\0') break; - } - return el_wrap_str(el_strdup("")); -} - -/* json_array_get_string — same as json_array_get, but assume the element - * is a JSON string and return the unquoted/unescaped value. Non-string - * elements yield "". */ -el_val_t json_array_get_string(el_val_t json_str, el_val_t index) { - el_val_t raw = json_array_get(json_str, index); - const char* s = EL_CSTR(raw); - if (!s || *s != '"') return el_wrap_str(el_strdup("")); - JsonParser jp = { - .p = s, - .end = s + strlen(s), - .err = 0, - }; - char* parsed = jp_parse_string_raw(&jp); - if (jp.err) { - free(parsed); - return el_wrap_str(el_strdup("")); - } - return el_wrap_str(parsed); -} - -/* ── Time ────────────────────────────────────────────────────────────────── */ - -el_val_t time_now(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - int64_t ms = (int64_t)tv.tv_sec * 1000LL + (int64_t)tv.tv_usec / 1000LL; - return (el_val_t)ms; -} - -el_val_t time_now_utc(void) { - return time_now(); -} - -el_val_t time_format(el_val_t ts, el_val_t fmt) { - int64_t ms = (int64_t)ts; - time_t s = (time_t)(ms / 1000); - int msec = (int)(ms % 1000); - if (msec < 0) { msec += 1000; s -= 1; } - struct tm tm; - gmtime_r(&s, &tm); - const char* fmt_str = EL_CSTR(fmt); - if (!fmt_str || strcmp(fmt_str, "ISO") == 0) { - char buf[64]; - snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, msec); - return el_wrap_str(el_strdup(buf)); - } - char buf[256]; - if (strftime(buf, sizeof(buf), fmt_str, &tm) == 0) buf[0] = '\0'; - return el_wrap_str(el_strdup(buf)); -} - -el_val_t time_to_parts(el_val_t ts) { - int64_t ms = (int64_t)ts; - time_t s = (time_t)(ms / 1000); - int msec = (int)(ms % 1000); - if (msec < 0) { msec += 1000; s -= 1; } - struct tm tm; - gmtime_r(&s, &tm); - el_val_t m = el_map_new(0); - m = el_map_set(m, EL_STR(el_strdup("year")), (el_val_t)(tm.tm_year + 1900)); - m = el_map_set(m, EL_STR(el_strdup("month")), (el_val_t)(tm.tm_mon + 1)); - m = el_map_set(m, EL_STR(el_strdup("day")), (el_val_t)tm.tm_mday); - m = el_map_set(m, EL_STR(el_strdup("hour")), (el_val_t)tm.tm_hour); - m = el_map_set(m, EL_STR(el_strdup("minute")), (el_val_t)tm.tm_min); - m = el_map_set(m, EL_STR(el_strdup("second")), (el_val_t)tm.tm_sec); - m = el_map_set(m, EL_STR(el_strdup("ms")), (el_val_t)msec); - return m; -} - -el_val_t time_from_parts(el_val_t secs, el_val_t ns, el_val_t tz) { - (void)tz; - int64_t s = (int64_t)secs; - int64_t n = (int64_t)ns; - int64_t ms = s * 1000LL + n / 1000000LL; - return (el_val_t)ms; -} - -el_val_t time_add(el_val_t ts, el_val_t n, el_val_t unit) { - const char* u = EL_CSTR(unit); - int64_t cur = (int64_t)ts; - int64_t d = (int64_t)n; - int64_t add_ms = d; - if (u) { - if (strcmp(u, "ms") == 0) add_ms = d; - else if (strcmp(u, "sec") == 0) add_ms = d * 1000LL; - else if (strcmp(u, "min") == 0) add_ms = d * 60000LL; - else if (strcmp(u, "hour") == 0) add_ms = d * 3600000LL; - else if (strcmp(u, "day") == 0) add_ms = d * 86400000LL; - } - return (el_val_t)(cur + add_ms); -} - -el_val_t time_diff(el_val_t ts1, el_val_t ts2, el_val_t unit) { - int64_t d = (int64_t)ts2 - (int64_t)ts1; - const char* u = EL_CSTR(unit); - if (!u || strcmp(u, "ms") == 0) return (el_val_t)d; - if (strcmp(u, "sec") == 0) return (el_val_t)(d / 1000LL); - if (strcmp(u, "min") == 0) return (el_val_t)(d / 60000LL); - if (strcmp(u, "hour") == 0) return (el_val_t)(d / 3600000LL); - if (strcmp(u, "day") == 0) return (el_val_t)(d / 86400000LL); - return (el_val_t)d; -} - -/* Block the calling thread for `secs` seconds. Negative values are clamped - * to 0. Used by El programs that poll external resources (e.g. RunPod - * /status, Engram readiness probes). */ -el_val_t sleep_secs(el_val_t secs) { - int64_t s = (int64_t)secs; - if (s < 0) s = 0; - struct timespec ts; - ts.tv_sec = (time_t)s; - ts.tv_nsec = 0; - nanosleep(&ts, NULL); - return 0; -} - -el_val_t sleep_ms(el_val_t ms) { - int64_t m = (int64_t)ms; - if (m < 0) m = 0; - struct timespec ts; - ts.tv_sec = (time_t)(m / 1000LL); - ts.tv_nsec = (long)((m % 1000LL) * 1000000LL); - nanosleep(&ts, NULL); - return 0; -} - -/* ── Instant + Duration: first-class temporal types ────────────────────────── - * El's substrate (Neuron) is a temporal cognition system. Memory salience - * decay, the six-tier pacemaker, TTL caches, and supersession are all - * temporal. Treating time as a raw Int (now() returning ms-since-epoch and - * arithmetic done with mixed unit literals) lets bugs through the type - * system: `(now - cached_at) < 60` cannot tell ms from sec, and `sleep(30)` - * is ambiguous. This block introduces two dedicated representations. - * - * Representation: - * Instant — int64 nanoseconds since the Unix epoch - * Duration — int64 nanoseconds (signed; negative durations are legal, - * e.g. when a deadline has passed) - * - * Both share the el_val_t (int64) slot the rest of the runtime uses, so no - * boxing / arena allocation is needed. Type discipline is enforced at the - * codegen layer: `let x: Duration = ...` registers `x` in __duration_names, - * and BinOp dispatches through typed wrappers (el_duration_add, etc.) that - * make intent explicit in the generated C. Mismatched ops (Instant+Instant, - * Duration+Int) are surfaced via #error directives at codegen time so the - * downstream cc step fails with a clear El-source-level message. - * - * Nanosecond precision matches POSIX clock_gettime / nanosleep granularity. - * 2^63 nanos covers ~292 years from epoch — comfortably past 2200, plenty - * for a memory-system runtime that never schedules outside a human lifespan. - */ - -/* now() — current Instant. Wraps clock_gettime(CLOCK_REALTIME) for nanosecond - * precision. Falls back to gettimeofday on systems where clock_gettime is - * unavailable (defensive — every supported platform has it). */ -el_val_t el_now_instant(void) { - struct timespec ts; - if (clock_gettime(CLOCK_REALTIME, &ts) == 0) { - int64_t ns = (int64_t)ts.tv_sec * 1000000000LL + (int64_t)ts.tv_nsec; - return (el_val_t)ns; - } - struct timeval tv; - gettimeofday(&tv, NULL); - int64_t ns = (int64_t)tv.tv_sec * 1000000000LL - + (int64_t)tv.tv_usec * 1000LL; - return (el_val_t)ns; -} - -el_val_t now(void) { - return el_now_instant(); -} - -/* unix_seconds(n) — Instant from a Unix-epoch second count. - * unix_millis(n) — Instant from a Unix-epoch millisecond count. */ -el_val_t unix_seconds(el_val_t n) { - int64_t s = (int64_t)n; - return (el_val_t)(s * 1000000000LL); -} - -el_val_t unix_millis(el_val_t n) { - int64_t m = (int64_t)n; - return (el_val_t)(m * 1000000LL); -} - -/* instant_from_iso8601 — parse a strict subset: - * YYYY-MM-DDTHH:MM:SS[.fff]Z - * Returns 0 (the Unix-epoch sentinel) on parse failure. Callers that need to - * distinguish epoch-zero from a parse error should use a wider sentinel - * representation; the current zero-on-failure choice matches existing El - * runtime conventions for parse builtins (str_to_int, parse_int). */ -el_val_t instant_from_iso8601(el_val_t s) { - const char* str = EL_CSTR(s); - if (!str) return (el_val_t)0; - int Y, M, D, h, m, sec, frac = 0; - int n = sscanf(str, "%d-%d-%dT%d:%d:%d.%3d", &Y, &M, &D, &h, &m, &sec, &frac); - if (n < 6) { - n = sscanf(str, "%d-%d-%dT%d:%d:%dZ", &Y, &M, &D, &h, &m, &sec); - if (n < 6) return (el_val_t)0; - } - struct tm tm; - memset(&tm, 0, sizeof(tm)); - tm.tm_year = Y - 1900; - tm.tm_mon = M - 1; - tm.tm_mday = D; - tm.tm_hour = h; - tm.tm_min = m; - tm.tm_sec = sec; - /* timegm — UTC. POSIX-Y but available on macOS and glibc. */ - time_t t = timegm(&tm); - if (t == (time_t)-1) return (el_val_t)0; - int64_t ns = (int64_t)t * 1000000000LL + (int64_t)frac * 1000000LL; - return (el_val_t)ns; -} - -/* Duration constructors. The El-side postfix literals (30.seconds, 1.hour) - * are lowered by the codegen directly into a literal int64 of nanoseconds — - * these constructors are for runtime values where the count is dynamic. */ -el_val_t el_duration_from_nanos(el_val_t ns) { - return (el_val_t)(int64_t)ns; -} - -el_val_t duration_seconds(el_val_t n) { - int64_t s = (int64_t)n; - return (el_val_t)(s * 1000000000LL); -} - -el_val_t duration_millis(el_val_t n) { - int64_t m = (int64_t)n; - return (el_val_t)(m * 1000000LL); -} - -el_val_t duration_nanos(el_val_t n) { - return (el_val_t)(int64_t)n; -} - -/* Arithmetic — typed wrappers. At the C level these are no-op casts, but - * the codegen routes Instant/Duration BinOps through them so the generated - * C says `el_instant_add_dur(start, dur)` rather than `start + dur`. The - * intent is explicit, the operand order is documented, and a future change - * to the underlying representation (saturating arithmetic, overflow guards) - * has a single chokepoint. */ -el_val_t el_instant_add_dur(el_val_t inst, el_val_t dur) { - return (el_val_t)((int64_t)inst + (int64_t)dur); -} - -el_val_t el_instant_sub_dur(el_val_t inst, el_val_t dur) { - return (el_val_t)((int64_t)inst - (int64_t)dur); -} - -el_val_t el_instant_diff(el_val_t a, el_val_t b) { - /* a - b — yields a Duration (negative if b is later than a). */ - return (el_val_t)((int64_t)a - (int64_t)b); -} - -el_val_t el_duration_add(el_val_t a, el_val_t b) { - return (el_val_t)((int64_t)a + (int64_t)b); -} - -el_val_t el_duration_sub(el_val_t a, el_val_t b) { - return (el_val_t)((int64_t)a - (int64_t)b); -} - -el_val_t el_duration_scale(el_val_t dur, el_val_t scalar) { - return (el_val_t)((int64_t)dur * (int64_t)scalar); -} - -el_val_t el_duration_div(el_val_t dur, el_val_t scalar) { - int64_t s = (int64_t)scalar; - if (s == 0) return (el_val_t)0; - return (el_val_t)((int64_t)dur / s); -} - -/* Comparisons. Return 1/0 in el_val_t convention. */ -el_val_t el_instant_lt(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a < (int64_t)b ? 1 : 0); } -el_val_t el_instant_le(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a <= (int64_t)b ? 1 : 0); } -el_val_t el_instant_gt(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a > (int64_t)b ? 1 : 0); } -el_val_t el_instant_ge(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a >= (int64_t)b ? 1 : 0); } -el_val_t el_instant_eq(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a == (int64_t)b ? 1 : 0); } -el_val_t el_instant_ne(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a != (int64_t)b ? 1 : 0); } -el_val_t el_duration_lt(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a < (int64_t)b ? 1 : 0); } -el_val_t el_duration_le(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a <= (int64_t)b ? 1 : 0); } -el_val_t el_duration_gt(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a > (int64_t)b ? 1 : 0); } -el_val_t el_duration_ge(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a >= (int64_t)b ? 1 : 0); } -el_val_t el_duration_eq(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a == (int64_t)b ? 1 : 0); } -el_val_t el_duration_ne(el_val_t a, el_val_t b) { return (el_val_t)((int64_t)a != (int64_t)b ? 1 : 0); } - -/* Conversions. */ -el_val_t instant_to_unix_seconds(el_val_t i) { - return (el_val_t)((int64_t)i / 1000000000LL); -} - -el_val_t instant_to_unix_millis(el_val_t i) { - return (el_val_t)((int64_t)i / 1000000LL); -} - -el_val_t instant_to_iso8601(el_val_t i) { - int64_t ns = (int64_t)i; - time_t s = (time_t)(ns / 1000000000LL); - int msec = (int)((ns / 1000000LL) % 1000LL); - if (msec < 0) { msec += 1000; s -= 1; } - struct tm tm; - gmtime_r(&s, &tm); - char buf[64]; - snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, msec); - return el_wrap_str(el_strdup(buf)); -} - -el_val_t duration_to_seconds(el_val_t d) { - return (el_val_t)((int64_t)d / 1000000000LL); -} - -el_val_t duration_to_millis(el_val_t d) { - return (el_val_t)((int64_t)d / 1000000LL); -} - -el_val_t duration_to_nanos(el_val_t d) { - return (el_val_t)(int64_t)d; -} - -/* sleep(Duration) — Phase 1 replacement for ambiguous sleep(Int). The runtime - * still exposes sleep_secs/sleep_ms for legacy call sites; codegen lowers - * sleep(Duration) to el_sleep_duration(d). Negative durations clamp to 0 so a - * stale deadline doesn't block forever. */ -el_val_t el_sleep_duration(el_val_t dur) { - int64_t ns = (int64_t)dur; - if (ns < 0) ns = 0; - struct timespec ts; - ts.tv_sec = (time_t)(ns / 1000000000LL); - ts.tv_nsec = (long)(ns % 1000000000LL); - nanosleep(&ts, NULL); - return (el_val_t)0; -} - -/* unix_timestamp() — back-compat. Existing El callers expect an Int seconds - * value; this stays an Int returner so the type system isn't disturbed for - * legacy code. New code should call now() and convert when needed. */ -el_val_t unix_timestamp(void) { - return instant_to_unix_seconds(el_now_instant()); -} - -/* TTL cache helpers. Backed by the existing process-wide K/V (state_set/get) - * with a sibling __ttl_set_at_ entry recording the Instant of the last - * write. ttl_cache_get returns "" if the entry is missing or stale, so call - * sites can branch on `if v == "" { miss } else { hit }` — the same shape - * existing get-with-default code uses. No more (now - cached_at) < 60. */ -el_val_t ttl_cache_set(el_val_t key, el_val_t value) { - const char* k = EL_CSTR(key); - if (!k) return (el_val_t)0; - /* Store the value at the user's key. */ - state_set(key, value); - /* Stamp set_at — opaque schema, namespaced under __ttl: prefix so user - * keys can't collide with stamps. */ - size_t klen = strlen(k); - char* stamp_key = (char*)malloc(klen + 16); - if (!stamp_key) return (el_val_t)0; - snprintf(stamp_key, klen + 16, "__ttl_at:%s", k); - int64_t now_ns = (int64_t)el_now_instant(); - char buf[32]; - snprintf(buf, sizeof(buf), "%lld", (long long)now_ns); - state_set(EL_STR(stamp_key), EL_STR(buf)); - free(stamp_key); - return (el_val_t)1; -} - -el_val_t ttl_cache_get(el_val_t key, el_val_t max_age) { - const char* k = EL_CSTR(key); - if (!k) return el_wrap_str(el_strdup("")); - /* Look up stamp. */ - size_t klen = strlen(k); - char* stamp_key = (char*)malloc(klen + 16); - if (!stamp_key) return el_wrap_str(el_strdup("")); - snprintf(stamp_key, klen + 16, "__ttl_at:%s", k); - el_val_t stamp = state_get(EL_STR(stamp_key)); - free(stamp_key); - const char* sv = EL_CSTR(stamp); - if (!sv || !*sv) return el_wrap_str(el_strdup("")); - int64_t set_at = (int64_t)atoll(sv); - int64_t now_ns = (int64_t)el_now_instant(); - int64_t age = now_ns - set_at; - int64_t max_ns = (int64_t)max_age; - if (age < 0) return el_wrap_str(el_strdup("")); /* clock skew — treat as miss */ - if (age > max_ns) return el_wrap_str(el_strdup("")); /* expired */ - return state_get(key); -} - -el_val_t ttl_cache_age(el_val_t key) { - const char* k = EL_CSTR(key); - if (!k) return (el_val_t)INT64_MAX; - size_t klen = strlen(k); - char* stamp_key = (char*)malloc(klen + 16); - if (!stamp_key) return (el_val_t)INT64_MAX; - snprintf(stamp_key, klen + 16, "__ttl_at:%s", k); - el_val_t stamp = state_get(EL_STR(stamp_key)); - free(stamp_key); - const char* sv = EL_CSTR(stamp); - if (!sv || !*sv) return (el_val_t)INT64_MAX; - int64_t set_at = (int64_t)atoll(sv); - int64_t now_ns = (int64_t)el_now_instant(); - return (el_val_t)(now_ns - set_at); -} - -/* ── Calendar + CalendarTime + Rhythm + LocalDate/Time/DateTime ────────────── - * Phase 1.5. Calendar is pluggable: EarthCalendar (IANA zones + Gregorian + - * DST), MarsCalendar (sols, MTC), CycleCalendar(period), NoCycleCalendar, - * RelativeCalendar(epoch). Phase 1 zone wrapping folds INTO EarthCalendar; - * UTC and IANA zones are themselves Earth-parochial and cannot live at the - * lowest type layer. - * - * A Rhythm is a small AST that asks the Calendar for cycle phase, weekday, - * etc. Most rhythm logic is calendar-agnostic at runtime: rhythm_cycle_phase - * means "midpoint of cycle" whether the cycle is 24h on Earth or 30h on a - * station or 300y on a long-cycle world. */ - -/* Magic headers — used by the runtime to recognize boxed temporal values - * arriving through el_val_t. Distinct constants so accidental misuse fails - * loudly rather than silently. */ -#define EL_CAL_MAGIC 0xE1CA1EDDU -#define EL_CALTIME_MAGIC 0xE1CA1747U -#define EL_RHYTHM_MAGIC 0xE1287A11U -#define EL_LDATE_MAGIC 0xE1DA7E00U -#define EL_LDT_MAGIC 0xE1DA7E1DU -#define EL_ZONE_MAGIC 0xE12017E0U - -typedef enum { - EL_CALENDAR_EARTH = 1, - EL_CALENDAR_MARS = 2, - EL_CALENDAR_CYCLE = 3, - EL_CALENDAR_NO_CYCLE = 4, - EL_CALENDAR_RELATIVE = 5 -} el_calendar_kind_t; - -typedef struct { - uint32_t magic; - char* id; /* IANA name or "+HH:MM" / "-HH:MM" */ - int fixed; /* 1 for fixed offset, 0 for IANA */ - int64_t offset_ns; /* fixed offset in nanos (only when fixed) */ -} el_zone_t; - -typedef struct { - uint32_t magic; - el_calendar_kind_t kind; - el_zone_t* zone; /* EarthCalendar; MarsCalendar uses MTC */ - int64_t cycle_period_ns;/* CycleCalendar; computed for Earth (86400 s) and Mars (88775.244 s) */ - int64_t epoch_ns; /* RelativeCalendar; Unix-epoch zero otherwise */ -} el_calendar_t; - -typedef struct { - uint32_t magic; - int64_t instant_ns; - el_calendar_t* cal; -} el_caltime_t; - -/* Rhythm AST. */ -typedef enum { - EL_RHYTHM_CYCLE_START = 1, - EL_RHYTHM_CYCLE_PHASE = 2, - EL_RHYTHM_DURATION = 3, - EL_RHYTHM_SESSION_START = 4, - EL_RHYTHM_EVENT = 5, - EL_RHYTHM_AND = 6, - EL_RHYTHM_OR = 7, - EL_RHYTHM_WEEKDAY = 8, - EL_RHYTHM_WEEKLY_AT = 9 -} el_rhythm_kind_t; - -typedef struct el_rhythm_s { - uint32_t magic; - el_rhythm_kind_t kind; - double phase; /* CYCLE_PHASE */ - int64_t period_ns; /* DURATION */ - int weekday; /* 1..7 Mon..Sun */ - int hour; - int minute; - char* event_name; /* EVENT */ - struct el_rhythm_s* a; /* AND/OR */ - struct el_rhythm_s* b; -} el_rhythm_t; - -typedef struct { - uint32_t magic; - int year; - int month; - int day; -} el_localdate_t; - -typedef struct { - uint32_t magic; - el_localdate_t* date; - int64_t time_ns; /* nanos since midnight */ -} el_localdt_t; - -/* Magic-tag check helpers — peek the first 4 bytes of an el_val_t pointer - * and compare against the expected magic. Strings are NUL-terminated and - * never start with our magic byte sequence, so this is safe. */ -static int el_is_magic(el_val_t v, uint32_t want) { - if (v == 0) return 0; - /* Defensive: only follow pointers in plausible address space. - * On 64-bit unix processes pointers are above 0x10000. */ - if ((uint64_t)v < 0x10000ULL) return 0; - uint32_t got = *(volatile uint32_t*)(uintptr_t)v; - return got == want; -} - -/* Sol length on Mars in nanoseconds: 88775.244 seconds. */ -#define EL_MARS_SOL_NS ((int64_t)88775244000000LL) -/* Earth solar day in nanoseconds: 86400 seconds. */ -#define EL_EARTH_DAY_NS ((int64_t)86400000000000LL) - -/* ── Zone construction ────────────────────────────────────────────────────── - * Zones intern by id string so equality comparisons are pointer-compares. */ - -#define EL_ZONE_TABLE_CAP 64 -static el_zone_t* _el_zone_table[EL_ZONE_TABLE_CAP]; -static int _el_zone_count = 0; - -static el_zone_t* _el_zone_intern(const char* id, int fixed, int64_t offset_ns) { - for (int i = 0; i < _el_zone_count; i++) { - el_zone_t* z = _el_zone_table[i]; - if (z->fixed == fixed && z->offset_ns == offset_ns && - strcmp(z->id ? z->id : "", id ? id : "") == 0) { - return z; - } - } - if (_el_zone_count >= EL_ZONE_TABLE_CAP) { - /* Out of slots: build a non-interned zone. Equality will fail across - * such zones but the program still runs. */ - el_zone_t* z = (el_zone_t*)malloc(sizeof(el_zone_t)); - z->magic = EL_ZONE_MAGIC; - z->id = el_strdup_persist(id ? id : ""); - z->fixed = fixed; - z->offset_ns = offset_ns; - return z; - } - el_zone_t* z = (el_zone_t*)malloc(sizeof(el_zone_t)); - z->magic = EL_ZONE_MAGIC; - z->id = el_strdup_persist(id ? id : ""); - z->fixed = fixed; - z->offset_ns = offset_ns; - _el_zone_table[_el_zone_count++] = z; - return z; -} - -el_val_t zone(el_val_t id) { - const char* s = EL_CSTR(id); - if (!s || !*s) return (el_val_t)(uintptr_t)_el_zone_intern("UTC", 0, 0); - /* Fixed-offset shortcut: "+HH:MM" or "-HH:MM". */ - if ((s[0] == '+' || s[0] == '-') && strlen(s) >= 6 && s[3] == ':') { - int sign = (s[0] == '-') ? -1 : 1; - int hh = (s[1] - '0') * 10 + (s[2] - '0'); - int mm = (s[4] - '0') * 10 + (s[5] - '0'); - int64_t off = (int64_t)sign * ((int64_t)hh * 3600LL + (int64_t)mm * 60LL) * 1000000000LL; - return (el_val_t)(uintptr_t)_el_zone_intern(s, 1, off); - } - return (el_val_t)(uintptr_t)_el_zone_intern(s, 0, 0); -} - -el_val_t zone_utc(void) { - return (el_val_t)(uintptr_t)_el_zone_intern("UTC", 1, 0); -} - -el_val_t zone_local(void) { - /* Resolve the local zone via TZ env or system default. tzset() picks - * up TZ if set; otherwise the C library reads /etc/localtime. We store - * the zone id as "LOCAL" so subsequent equality holds; resolution is - * lazy at use time. */ - return (el_val_t)(uintptr_t)_el_zone_intern("LOCAL", 0, 0); -} - -el_val_t zone_offset(el_val_t hours, el_val_t minutes) { - int hh = (int)(int64_t)hours; - int mm = (int)(int64_t)minutes; - int sign = (hh < 0 || mm < 0) ? -1 : 1; - if (hh < 0) hh = -hh; - if (mm < 0) mm = -mm; - int64_t off = (int64_t)sign * ((int64_t)hh * 3600LL + (int64_t)mm * 60LL) * 1000000000LL; - char buf[16]; - snprintf(buf, sizeof(buf), "%c%02d:%02d", sign < 0 ? '-' : '+', hh, mm); - return (el_val_t)(uintptr_t)_el_zone_intern(buf, 1, off); -} - -/* ── Calendar interning ──────────────────────────────────────────────────── */ - -#define EL_CAL_TABLE_CAP 64 -static el_calendar_t* _el_cal_table[EL_CAL_TABLE_CAP]; -static int _el_cal_count = 0; - -static el_calendar_t* _el_cal_intern(el_calendar_kind_t kind, el_zone_t* z, - int64_t period_ns, int64_t epoch_ns) { - for (int i = 0; i < _el_cal_count; i++) { - el_calendar_t* c = _el_cal_table[i]; - if (c->kind == kind && c->zone == z && - c->cycle_period_ns == period_ns && c->epoch_ns == epoch_ns) { - return c; - } - } - el_calendar_t* c = (el_calendar_t*)malloc(sizeof(el_calendar_t)); - c->magic = EL_CAL_MAGIC; - c->kind = kind; - c->zone = z; - c->cycle_period_ns = period_ns; - c->epoch_ns = epoch_ns; - if (_el_cal_count < EL_CAL_TABLE_CAP) _el_cal_table[_el_cal_count++] = c; - return c; -} - -el_val_t earth_calendar(el_val_t z_val) { - el_zone_t* z = NULL; - if (z_val != 0 && el_is_magic(z_val, EL_ZONE_MAGIC)) { - z = (el_zone_t*)(uintptr_t)z_val; - } else { - z = (el_zone_t*)(uintptr_t)zone_local(); - } - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_EARTH, z, EL_EARTH_DAY_NS, 0); -} - -el_val_t earth_calendar_default(void) { - return earth_calendar(zone_local()); -} - -el_val_t mars_calendar(void) { - el_zone_t* z = (el_zone_t*)(uintptr_t)_el_zone_intern("MTC", 1, 0); - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_MARS, z, EL_MARS_SOL_NS, 0); -} - -el_val_t cycle_calendar(el_val_t period_dur) { - int64_t period = (int64_t)period_dur; - if (period <= 0) period = 1; - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_CYCLE, NULL, period, 0); -} - -el_val_t no_cycle_calendar(void) { - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_NO_CYCLE, NULL, 0, 0); -} - -el_val_t relative_calendar(el_val_t epoch_inst) { - int64_t ep = (int64_t)epoch_inst; - return (el_val_t)(uintptr_t)_el_cal_intern(EL_CALENDAR_RELATIVE, NULL, 0, ep); -} - -/* ── CalendarTime ───────────────────────────────────────────────────────── */ - -static el_caltime_t* _el_caltime_alloc(int64_t inst, el_calendar_t* c) { - el_caltime_t* ct = (el_caltime_t*)malloc(sizeof(el_caltime_t)); - ct->magic = EL_CALTIME_MAGIC; - ct->instant_ns = inst; - ct->cal = c; - return ct; -} - -static el_calendar_t* _el_resolve_cal(el_val_t cal_val) { - if (cal_val == 0 || !el_is_magic(cal_val, EL_CAL_MAGIC)) { - return (el_calendar_t*)(uintptr_t)earth_calendar_default(); - } - return (el_calendar_t*)(uintptr_t)cal_val; -} - -el_val_t now_in(el_val_t cal_val) { - el_calendar_t* c = _el_resolve_cal(cal_val); - int64_t ns = (int64_t)el_now_instant(); - return (el_val_t)(uintptr_t)_el_caltime_alloc(ns, c); -} - -el_val_t in_calendar(el_val_t inst, el_val_t cal_val) { - el_calendar_t* c = _el_resolve_cal(cal_val); - return (el_val_t)(uintptr_t)_el_caltime_alloc((int64_t)inst, c); -} - -el_val_t cal_to_instant(el_val_t ct_val) { - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return (el_val_t)0; - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - return (el_val_t)ct->instant_ns; -} - -el_val_t cal_in(el_val_t ct_val, el_val_t cal_val) { - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return (el_val_t)0; - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - el_calendar_t* c = _el_resolve_cal(cal_val); - return (el_val_t)(uintptr_t)_el_caltime_alloc(ct->instant_ns, c); -} - -el_val_t cal_cycle_phase(el_val_t ct_val) { - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return el_from_float(0.0); - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - el_calendar_t* c = ct->cal; - if (c->kind == EL_CALENDAR_NO_CYCLE) { - return el_from_float(0.0/0.0); /* NaN sentinel */ - } - int64_t period = c->cycle_period_ns; - if (period <= 0) return el_from_float(0.0); - int64_t base = ct->instant_ns - c->epoch_ns; - int64_t phase_ns = base % period; - if (phase_ns < 0) phase_ns += period; - double phase = (double)phase_ns / (double)period; - return el_from_float(phase); -} - -/* ── Earth zone resolution: TZ-based offset lookup ────────────────────────── - * For an EarthCalendar(zone), we want to convert an instant_ns into local - * y/m/d/h/m/s, including DST. Approach: setenv("TZ", id), tzset(), use - * localtime_r, then restore. This is not thread-safe by design — El's - * runtime is single-threaded for the request handler path. Cache the - * computed (instant -> tm) to avoid the syscall churn on repeat formats. */ - -static void _el_apply_zone(el_zone_t* z) { - if (!z) { unsetenv("TZ"); tzset(); return; } - if (z->fixed && strcmp(z->id, "UTC") == 0) { - setenv("TZ", "UTC0", 1); - tzset(); - return; - } - if (z->fixed) { - /* Fixed offset: POSIX TZ uses inverted sign (sign convention of - * "hours WEST of UTC" rather than east). Build the spec accordingly. */ - char buf[32]; - int neg_secs = (int)(-z->offset_ns / 1000000000LL); - int sign = neg_secs < 0 ? -1 : 1; - int abs_secs = neg_secs < 0 ? -neg_secs : neg_secs; - int hh = abs_secs / 3600; - int mm = (abs_secs % 3600) / 60; - snprintf(buf, sizeof(buf), "FIX%c%d:%02d", sign < 0 ? '-' : '+', hh, mm); - setenv("TZ", buf, 1); - tzset(); - return; - } - if (strcmp(z->id, "LOCAL") == 0) { - unsetenv("TZ"); - tzset(); - return; - } - setenv("TZ", z->id, 1); - tzset(); -} - -static int _el_decompose_earth(el_caltime_t* ct, struct tm* tm_out, int* abbr_len, char* abbr_buf, size_t abbr_cap) { - el_calendar_t* c = ct->cal; - el_zone_t* z = c->zone; - _el_apply_zone(z); - time_t s = (time_t)(ct->instant_ns / 1000000000LL); - struct tm tm; - localtime_r(&s, &tm); - *tm_out = tm; - if (abbr_buf && abbr_cap > 0) { - const char* z_str = tm.tm_zone ? tm.tm_zone : ""; - size_t n = strlen(z_str); - if (n >= abbr_cap) n = abbr_cap - 1; - memcpy(abbr_buf, z_str, n); - abbr_buf[n] = '\0'; - if (abbr_len) *abbr_len = (int)n; - } - return 0; -} - -/* Format an Earth CalendarTime under a Java-DateTimeFormatter-ish pattern. - * We support a useful core: yyyy MM dd HH mm ss z EEE MMM d h a — enough for - * the acceptance tests. Single quotes denote literal text. */ -static const char* _el_weekday_short[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; -static const char* _el_month_short[] = {"Jan","Feb","Mar","Apr","May","Jun", - "Jul","Aug","Sep","Oct","Nov","Dec"}; - -static char* _el_format_earth(el_caltime_t* ct, const char* pattern) { - struct tm tm; - char abbr[16] = {0}; - int abbr_len = 0; - _el_decompose_earth(ct, &tm, &abbr_len, abbr, sizeof(abbr)); - size_t cap = strlen(pattern) * 4 + 64; - char* out = (char*)malloc(cap); - size_t pos = 0; - size_t i = 0; - size_t plen = strlen(pattern); - while (i < plen) { - char ch = pattern[i]; - /* Quoted literal */ - if (ch == '\'') { - i++; - while (i < plen && pattern[i] != '\'') { - if (pos + 1 >= cap) { cap *= 2; out = realloc(out, cap); } - out[pos++] = pattern[i++]; - } - if (i < plen) i++; - continue; - } - /* Count run of same letter */ - size_t run = 1; - while (i + run < plen && pattern[i + run] == ch) run++; - char tmp[64]; - tmp[0] = '\0'; - if (ch == 'y') { - if (run >= 4) snprintf(tmp, sizeof(tmp), "%04d", tm.tm_year + 1900); - else snprintf(tmp, sizeof(tmp), "%02d", (tm.tm_year + 1900) % 100); - } else if (ch == 'M') { - if (run >= 3) snprintf(tmp, sizeof(tmp), "%s", _el_month_short[tm.tm_mon]); - else if (run == 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_mon + 1); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_mon + 1); - } else if (ch == 'd') { - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_mday); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_mday); - } else if (ch == 'H') { - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_hour); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_hour); - } else if (ch == 'h') { - int h12 = tm.tm_hour % 12; if (h12 == 0) h12 = 12; - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", h12); - else snprintf(tmp, sizeof(tmp), "%d", h12); - } else if (ch == 'm') { - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_min); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_min); - } else if (ch == 's') { - if (run >= 2) snprintf(tmp, sizeof(tmp), "%02d", tm.tm_sec); - else snprintf(tmp, sizeof(tmp), "%d", tm.tm_sec); - } else if (ch == 'a') { - snprintf(tmp, sizeof(tmp), "%s", tm.tm_hour < 12 ? "AM" : "PM"); - } else if (ch == 'E') { - snprintf(tmp, sizeof(tmp), "%s", _el_weekday_short[tm.tm_wday]); - } else if (ch == 'z') { - snprintf(tmp, sizeof(tmp), "%s", abbr); - } else { - for (size_t k = 0; k < run; k++) { - if (pos + 1 >= cap) { cap *= 2; out = realloc(out, cap); } - out[pos++] = ch; - } - i += run; - continue; - } - size_t tl = strlen(tmp); - if (pos + tl + 1 >= cap) { cap = (cap + tl) * 2; out = realloc(out, cap); } - memcpy(out + pos, tmp, tl); - pos += tl; - i += run; - } - out[pos] = '\0'; - char* result = el_strdup(out); - free(out); - return result; -} - -/* Format a Mars CalendarTime: %sol prints the integer sol number since - * mission epoch (Unix epoch fallback), %phase prints cycle_phase as a - * 0..1 decimal. Other %-specifiers fall through. */ -static char* _el_format_mars(el_caltime_t* ct, const char* pattern) { - el_calendar_t* c = ct->cal; - int64_t period = c->cycle_period_ns > 0 ? c->cycle_period_ns : EL_MARS_SOL_NS; - int64_t base = ct->instant_ns - c->epoch_ns; - int64_t sol = base / period; - int64_t phase_ns = base % period; - if (phase_ns < 0) { phase_ns += period; sol -= 1; } - double phase = (double)phase_ns / (double)period; - size_t cap = strlen(pattern) * 4 + 64; - char* out = (char*)malloc(cap); - size_t pos = 0; - for (size_t i = 0; pattern[i]; i++) { - if (pattern[i] == '%' && pattern[i+1]) { - char tmp[64]; - tmp[0] = '\0'; - if (strncmp(pattern + i + 1, "sol", 3) == 0) { - snprintf(tmp, sizeof(tmp), "%lld", (long long)sol); - i += 3; - } else if (strncmp(pattern + i + 1, "phase", 5) == 0) { - snprintf(tmp, sizeof(tmp), "%.4f", phase); - i += 5; - } else if (pattern[i+1] == 'd') { - snprintf(tmp, sizeof(tmp), "%lld", (long long)sol); - i += 1; - } else { - tmp[0] = pattern[i+1]; tmp[1] = '\0'; - i += 1; - } - size_t tl = strlen(tmp); - if (pos + tl + 1 >= cap) { cap = (cap + tl) * 2; out = realloc(out, cap); } - memcpy(out + pos, tmp, tl); - pos += tl; - } else { - if (pos + 1 >= cap) { cap *= 2; out = realloc(out, cap); } - out[pos++] = pattern[i]; - } - } - out[pos] = '\0'; - char* result = el_strdup(out); - free(out); - return result; -} - -/* Format a CycleCalendar CalendarTime: %cycle and %phase. */ -static char* _el_format_cycle(el_caltime_t* ct, const char* pattern) { - el_calendar_t* c = ct->cal; - int64_t period = c->cycle_period_ns > 0 ? c->cycle_period_ns : 1; - int64_t base = ct->instant_ns - c->epoch_ns; - int64_t cycle = base / period; - int64_t phase_ns = base % period; - if (phase_ns < 0) { phase_ns += period; cycle -= 1; } - double phase = (double)phase_ns / (double)period; - size_t cap = strlen(pattern) * 4 + 64; - char* out = (char*)malloc(cap); - size_t pos = 0; - for (size_t i = 0; pattern[i]; i++) { - if (pattern[i] == '%' && pattern[i+1]) { - char tmp[64]; - tmp[0] = '\0'; - if (strncmp(pattern + i + 1, "cycle", 5) == 0) { - snprintf(tmp, sizeof(tmp), "%lld", (long long)cycle); - i += 5; - } else if (strncmp(pattern + i + 1, "phase", 5) == 0) { - snprintf(tmp, sizeof(tmp), "%.4f", phase); - i += 5; - } else if (pattern[i+1] == 'd') { - snprintf(tmp, sizeof(tmp), "%lld", (long long)cycle); - i += 1; - } else if (pattern[i+1] == 'f') { - snprintf(tmp, sizeof(tmp), "%.2f", phase); - i += 1; - } else { - /* Pass through unknown specifier */ - tmp[0] = '%'; tmp[1] = pattern[i+1]; tmp[2] = '\0'; - i += 1; - } - size_t tl = strlen(tmp); - if (pos + tl + 1 >= cap) { cap = (cap + tl) * 2; out = realloc(out, cap); } - memcpy(out + pos, tmp, tl); - pos += tl; - } else { - if (pos + 1 >= cap) { cap *= 2; out = realloc(out, cap); } - out[pos++] = pattern[i]; - } - } - out[pos] = '\0'; - char* result = el_strdup(out); - free(out); - return result; -} - -el_val_t cal_format(el_val_t ct_val, el_val_t pattern_val) { - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return el_wrap_str(el_strdup("")); - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - const char* pat = EL_CSTR(pattern_val); - if (!pat) pat = ""; - char* result = NULL; - switch (ct->cal->kind) { - case EL_CALENDAR_EARTH: result = _el_format_earth(ct, pat); break; - case EL_CALENDAR_MARS: result = _el_format_mars(ct, pat); break; - case EL_CALENDAR_CYCLE: result = _el_format_cycle(ct, pat); break; - case EL_CALENDAR_RELATIVE: result = _el_format_cycle(ct, pat); break; - case EL_CALENDAR_NO_CYCLE: { - char buf[64]; - snprintf(buf, sizeof(buf), "instant:%lld", (long long)ct->instant_ns); - result = el_strdup(buf); - break; - } - default: result = el_strdup(""); - } - return el_wrap_str(result); -} - -/* ── LocalDate / LocalTime / LocalDateTime ──────────────────────────────── */ - -static int _el_days_in_month(int y, int m) { - static const int dim[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; - if (m == 2) { - int leap = ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0); - return 28 + (leap ? 1 : 0); - } - if (m < 1 || m > 12) return 30; - return dim[m - 1]; -} - -el_val_t local_date(el_val_t y, el_val_t m, el_val_t d) { - el_localdate_t* ld = (el_localdate_t*)malloc(sizeof(el_localdate_t)); - ld->magic = EL_LDATE_MAGIC; - ld->year = (int)(int64_t)y; - ld->month = (int)(int64_t)m; - ld->day = (int)(int64_t)d; - return (el_val_t)(uintptr_t)ld; -} - -el_val_t local_time(el_val_t h, el_val_t m, el_val_t s, el_val_t ns) { - int64_t hh = (int64_t)h; - int64_t mm = (int64_t)m; - int64_t ss = (int64_t)s; - int64_t nn = (int64_t)ns; - int64_t total = hh * 3600000000000LL + mm * 60000000000LL + ss * 1000000000LL + nn; - return (el_val_t)total; -} - -el_val_t local_datetime(el_val_t date_val, el_val_t time_val) { - if (!el_is_magic(date_val, EL_LDATE_MAGIC)) return (el_val_t)0; - el_localdt_t* ldt = (el_localdt_t*)malloc(sizeof(el_localdt_t)); - ldt->magic = EL_LDT_MAGIC; - ldt->date = (el_localdate_t*)(uintptr_t)date_val; - ldt->time_ns = (int64_t)time_val; - return (el_val_t)(uintptr_t)ldt; -} - -el_val_t zoned(el_val_t date_val, el_val_t time_val, el_val_t cal_val) { - if (!el_is_magic(date_val, EL_LDATE_MAGIC)) return (el_val_t)0; - el_localdate_t* ld = (el_localdate_t*)(uintptr_t)date_val; - el_calendar_t* c = _el_resolve_cal(cal_val); - int64_t time_ns = (int64_t)time_val; - /* Convert (LocalDate, LocalTime, EarthCalendar) -> Instant. - * For non-Earth calendars we use day-anchored conversion: treat the - * LocalDate's (y,m,d) as a Gregorian projection, convert to seconds via - * mktime under the calendar's zone, then add nanos-since-midnight. */ - if (c->kind == EL_CALENDAR_EARTH) { - _el_apply_zone(c->zone); - struct tm tm; memset(&tm, 0, sizeof(tm)); - tm.tm_year = ld->year - 1900; - tm.tm_mon = ld->month - 1; - tm.tm_mday = ld->day; - tm.tm_hour = (int)(time_ns / 3600000000000LL); - tm.tm_min = (int)((time_ns / 60000000000LL) % 60); - tm.tm_sec = (int)((time_ns / 1000000000LL) % 60); - tm.tm_isdst = -1; - time_t t = mktime(&tm); - if (t == (time_t)-1) return (el_val_t)0; - int64_t ns = (int64_t)t * 1000000000LL + (time_ns % 1000000000LL); - return (el_val_t)(uintptr_t)_el_caltime_alloc(ns, c); - } - /* Non-Earth fallback: project as if Earth UTC then attach calendar. */ - struct tm tm; memset(&tm, 0, sizeof(tm)); - tm.tm_year = ld->year - 1900; - tm.tm_mon = ld->month - 1; - tm.tm_mday = ld->day; - tm.tm_hour = (int)(time_ns / 3600000000000LL); - tm.tm_min = (int)((time_ns / 60000000000LL) % 60); - tm.tm_sec = (int)((time_ns / 1000000000LL) % 60); - time_t t = timegm(&tm); - if (t == (time_t)-1) return (el_val_t)0; - int64_t ns = (int64_t)t * 1000000000LL + (time_ns % 1000000000LL); - return (el_val_t)(uintptr_t)_el_caltime_alloc(ns, c); -} - -el_val_t local_date_year(el_val_t v) { - if (!el_is_magic(v, EL_LDATE_MAGIC)) return (el_val_t)0; - return (el_val_t)((el_localdate_t*)(uintptr_t)v)->year; -} -el_val_t local_date_month(el_val_t v) { - if (!el_is_magic(v, EL_LDATE_MAGIC)) return (el_val_t)0; - return (el_val_t)((el_localdate_t*)(uintptr_t)v)->month; -} -el_val_t local_date_day(el_val_t v) { - if (!el_is_magic(v, EL_LDATE_MAGIC)) return (el_val_t)0; - return (el_val_t)((el_localdate_t*)(uintptr_t)v)->day; -} -el_val_t local_time_hour(el_val_t v) { - int64_t t = (int64_t)v; - return (el_val_t)(t / 3600000000000LL); -} -el_val_t local_time_minute(el_val_t v) { - int64_t t = (int64_t)v; - return (el_val_t)((t / 60000000000LL) % 60); -} -el_val_t local_time_second(el_val_t v) { - int64_t t = (int64_t)v; - return (el_val_t)((t / 1000000000LL) % 60); -} -el_val_t local_time_nanos(el_val_t v) { - int64_t t = (int64_t)v; - return (el_val_t)(t % 1000000000LL); -} - -el_val_t el_local_date_add_dur(el_val_t ld_val, el_val_t dur_val) { - if (!el_is_magic(ld_val, EL_LDATE_MAGIC)) return ld_val; - el_localdate_t* ld = (el_localdate_t*)(uintptr_t)ld_val; - int64_t dur_ns = (int64_t)dur_val; - int64_t days = dur_ns / EL_EARTH_DAY_NS; - int y = ld->year, m = ld->month, d = ld->day; - /* Walk days forward/backward in canonical Gregorian. */ - while (days > 0) { - int dim = _el_days_in_month(y, m); - if (d + days <= dim) { d += (int)days; days = 0; break; } - days -= (dim - d + 1); - d = 1; - m++; - if (m > 12) { m = 1; y++; } - } - while (days < 0) { - if (d + days >= 1) { d += (int)days; days = 0; break; } - days += d; - m--; - if (m < 1) { m = 12; y--; } - d = _el_days_in_month(y, m); - } - return local_date((el_val_t)y, (el_val_t)m, (el_val_t)d); -} - -el_val_t el_local_time_add_dur(el_val_t lt_val, el_val_t dur_val) { - int64_t t = (int64_t)lt_val + (int64_t)dur_val; - /* Wrap mod 24h on Earth-default. CycleCalendar wrapping requires the - * caller to use cal_in / cal_format for the right modulus. */ - int64_t day = EL_EARTH_DAY_NS; - int64_t r = t % day; - if (r < 0) r += day; - return (el_val_t)r; -} - -el_val_t el_local_date_lt(el_val_t a_val, el_val_t b_val) { - if (!el_is_magic(a_val, EL_LDATE_MAGIC) || !el_is_magic(b_val, EL_LDATE_MAGIC)) return (el_val_t)0; - el_localdate_t* a = (el_localdate_t*)(uintptr_t)a_val; - el_localdate_t* b = (el_localdate_t*)(uintptr_t)b_val; - if (a->year != b->year) return (el_val_t)(a->year < b->year ? 1 : 0); - if (a->month != b->month) return (el_val_t)(a->month < b->month ? 1 : 0); - return (el_val_t)(a->day < b->day ? 1 : 0); -} - -el_val_t el_local_date_eq(el_val_t a_val, el_val_t b_val) { - if (!el_is_magic(a_val, EL_LDATE_MAGIC) || !el_is_magic(b_val, EL_LDATE_MAGIC)) return (el_val_t)0; - el_localdate_t* a = (el_localdate_t*)(uintptr_t)a_val; - el_localdate_t* b = (el_localdate_t*)(uintptr_t)b_val; - return (el_val_t)((a->year == b->year && a->month == b->month && a->day == b->day) ? 1 : 0); -} - -/* ── Rhythm ──────────────────────────────────────────────────────────────── */ - -static el_rhythm_t* _el_rhythm_alloc(el_rhythm_kind_t k) { - el_rhythm_t* r = (el_rhythm_t*)calloc(1, sizeof(el_rhythm_t)); - r->magic = EL_RHYTHM_MAGIC; - r->kind = k; - return r; -} - -el_val_t rhythm_cycle_start(void) { - return (el_val_t)(uintptr_t)_el_rhythm_alloc(EL_RHYTHM_CYCLE_START); -} - -el_val_t rhythm_cycle_phase(el_val_t phase_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_CYCLE_PHASE); - r->phase = el_to_float(phase_val); - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_duration(el_val_t d_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_DURATION); - r->period_ns = (int64_t)d_val; - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_session_start(void) { - return (el_val_t)(uintptr_t)_el_rhythm_alloc(EL_RHYTHM_SESSION_START); -} - -el_val_t rhythm_event(el_val_t name_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_EVENT); - const char* n = EL_CSTR(name_val); - r->event_name = el_strdup_persist(n ? n : ""); - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_and(el_val_t a_val, el_val_t b_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_AND); - r->a = el_is_magic(a_val, EL_RHYTHM_MAGIC) ? (el_rhythm_t*)(uintptr_t)a_val : NULL; - r->b = el_is_magic(b_val, EL_RHYTHM_MAGIC) ? (el_rhythm_t*)(uintptr_t)b_val : NULL; - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_or(el_val_t a_val, el_val_t b_val) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_OR); - r->a = el_is_magic(a_val, EL_RHYTHM_MAGIC) ? (el_rhythm_t*)(uintptr_t)a_val : NULL; - r->b = el_is_magic(b_val, EL_RHYTHM_MAGIC) ? (el_rhythm_t*)(uintptr_t)b_val : NULL; - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_weekday(el_val_t day) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_WEEKDAY); - r->weekday = (int)(int64_t)day; - return (el_val_t)(uintptr_t)r; -} - -el_val_t rhythm_weekly_at(el_val_t day, el_val_t hour, el_val_t minute) { - el_rhythm_t* r = _el_rhythm_alloc(EL_RHYTHM_WEEKLY_AT); - r->weekday = (int)(int64_t)day; - r->hour = (int)(int64_t)hour; - r->minute = (int)(int64_t)minute; - return (el_val_t)(uintptr_t)r; -} - -/* Compute the next instant on or after `after` when rhythm `r` matches, - * under calendar `cal`. */ -static int64_t _el_next_after(el_rhythm_t* r, int64_t after_ns, el_calendar_t* cal) { - if (!r) return after_ns; - int64_t period = cal->cycle_period_ns > 0 ? cal->cycle_period_ns : EL_EARTH_DAY_NS; - switch (r->kind) { - case EL_RHYTHM_CYCLE_START: { - int64_t base = after_ns - cal->epoch_ns; - int64_t cyc = (base / period) + 1; - return cal->epoch_ns + cyc * period; - } - case EL_RHYTHM_CYCLE_PHASE: { - int64_t base = after_ns - cal->epoch_ns; - int64_t cyc_ns = (int64_t)(r->phase * (double)period); - int64_t cur_cyc = base / period; - int64_t candidate = cal->epoch_ns + cur_cyc * period + cyc_ns; - if (candidate <= after_ns) candidate += period; - return candidate; - } - case EL_RHYTHM_DURATION: { - return after_ns + (r->period_ns > 0 ? r->period_ns : 1); - } - case EL_RHYTHM_WEEKDAY: - case EL_RHYTHM_WEEKLY_AT: { - if (cal->kind != EL_CALENDAR_EARTH) { - /* Non-Earth calendars: fall back to cycle math, treating - * weekday as a 7-cycle-per-period proxy. */ - return after_ns + period; - } - _el_apply_zone(cal->zone); - time_t s = (time_t)(after_ns / 1000000000LL); - struct tm tm; - localtime_r(&s, &tm); - /* tm_wday: 0=Sun..6=Sat. We use 1=Mon..7=Sun. */ - int target = r->weekday >= 1 && r->weekday <= 7 ? r->weekday : 1; - int target_wday = target == 7 ? 0 : target; /* 7→Sun=0, 1→Mon=1 */ - int days_ahead = (target_wday - tm.tm_wday + 7) % 7; - int hour = (r->kind == EL_RHYTHM_WEEKLY_AT) ? r->hour : 0; - int minute = (r->kind == EL_RHYTHM_WEEKLY_AT) ? r->minute : 0; - struct tm cand = tm; - cand.tm_mday += days_ahead; - cand.tm_hour = hour; - cand.tm_min = minute; - cand.tm_sec = 0; - cand.tm_isdst = -1; - time_t cand_t = mktime(&cand); - int64_t cand_ns = (int64_t)cand_t * 1000000000LL; - if (cand_ns <= after_ns) { - cand.tm_mday += 7; - cand.tm_isdst = -1; - cand_t = mktime(&cand); - cand_ns = (int64_t)cand_t * 1000000000LL; - } - return cand_ns; - } - case EL_RHYTHM_AND: { - int64_t a = _el_next_after(r->a, after_ns, cal); - int64_t b = _el_next_after(r->b, after_ns, cal); - return a > b ? a : b; - } - case EL_RHYTHM_OR: { - int64_t a = _el_next_after(r->a, after_ns, cal); - int64_t b = _el_next_after(r->b, after_ns, cal); - return a < b ? a : b; - } - case EL_RHYTHM_SESSION_START: - case EL_RHYTHM_EVENT: - default: - return after_ns; - } -} - -el_val_t rhythm_next_after(el_val_t r_val, el_val_t after_val, el_val_t cal_val) { - if (!el_is_magic(r_val, EL_RHYTHM_MAGIC)) return after_val; - el_rhythm_t* r = (el_rhythm_t*)(uintptr_t)r_val; - el_calendar_t* c = _el_resolve_cal(cal_val); - int64_t out = _el_next_after(r, (int64_t)after_val, c); - return (el_val_t)out; -} - -el_val_t rhythm_matches(el_val_t r_val, el_val_t ct_val) { - if (!el_is_magic(r_val, EL_RHYTHM_MAGIC)) return (el_val_t)0; - if (!el_is_magic(ct_val, EL_CALTIME_MAGIC)) return (el_val_t)0; - el_rhythm_t* r = (el_rhythm_t*)(uintptr_t)r_val; - el_caltime_t* ct = (el_caltime_t*)(uintptr_t)ct_val; - int64_t period = ct->cal->cycle_period_ns > 0 ? ct->cal->cycle_period_ns : EL_EARTH_DAY_NS; - int64_t base = ct->instant_ns - ct->cal->epoch_ns; - int64_t phase_ns = base % period; - if (phase_ns < 0) phase_ns += period; - double phase = (double)phase_ns / (double)period; - switch (r->kind) { - case EL_RHYTHM_CYCLE_START: return (el_val_t)(phase_ns == 0 ? 1 : 0); - case EL_RHYTHM_CYCLE_PHASE: { - double diff = phase - r->phase; - if (diff < 0) diff = -diff; - return (el_val_t)(diff < 0.001 ? 1 : 0); - } - default: return (el_val_t)0; - } -} - -/* ── UUID v4 ─────────────────────────────────────────────────────────────── */ - -static int _el_uuid_seeded = 0; - -static void _el_uuid_seed(void) { - if (!_el_uuid_seeded) { - srand((unsigned)time(NULL) ^ (unsigned)(uintptr_t)&_el_uuid_seeded); - _el_uuid_seeded = 1; - } -} - -el_val_t uuid_new(void) { - _el_uuid_seed(); - unsigned char b[16]; - for (int i = 0; i < 16; i++) b[i] = (unsigned char)(rand() & 0xff); - /* Version 4 */ - b[6] = (b[6] & 0x0f) | 0x40; - /* RFC 4122 variant */ - b[8] = (b[8] & 0x3f) | 0x80; - char buf[37]; - snprintf(buf, sizeof(buf), - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - b[0], b[1], b[2], b[3], - b[4], b[5], - b[6], b[7], - b[8], b[9], - b[10], b[11], b[12], b[13], b[14], b[15]); - return el_wrap_str(el_strdup(buf)); -} - -el_val_t uuid_v4(void) { return uuid_new(); } - -/* ── Environment ─────────────────────────────────────────────────────────── */ - -el_val_t env(el_val_t key) { - const char* k = EL_CSTR(key); - if (!k) return el_wrap_str(el_strdup("")); - const char* v = getenv(k); - return el_wrap_str(el_strdup(v ? v : "")); -} - -/* ── In-process state K/V ────────────────────────────────────────────────── */ - -typedef struct { - char* key; - char* value; -} StateEntry; - -static StateEntry* _state_entries = NULL; -static size_t _state_count = 0; -static size_t _state_cap = 0; -/* Mutex protecting all _state_entries access. state_set/state_get are called - * concurrently from 64 HTTP worker threads — without this lock, realloc and - * free race, producing corruption, double-free, and segfaults. */ -static pthread_mutex_t _state_mu = PTHREAD_MUTEX_INITIALIZER; - -static StateEntry* state_find(const char* key) { - for (size_t i = 0; i < _state_count; i++) { - if (strcmp(_state_entries[i].key, key) == 0) return &_state_entries[i]; - } - return NULL; -} - -el_val_t state_set(el_val_t key, el_val_t value) { - const char* k = EL_CSTR(key); - const char* v = EL_CSTR(value); - if (!k) return 0; - if (!v) v = ""; - pthread_mutex_lock(&_state_mu); - StateEntry* e = state_find(k); - if (e) { - free(e->value); - e->value = el_strdup_persist(v); - pthread_mutex_unlock(&_state_mu); - return 1; - } - if (_state_count >= _state_cap) { - size_t nc = _state_cap == 0 ? 16 : _state_cap * 2; - StateEntry* grown = realloc(_state_entries, nc * sizeof(StateEntry)); - if (!grown) { pthread_mutex_unlock(&_state_mu); fputs("el_runtime: out of memory\n", stderr); exit(1); } - _state_entries = grown; - _state_cap = nc; - } - _state_entries[_state_count].key = el_strdup_persist(k); - _state_entries[_state_count].value = el_strdup_persist(v); - _state_count++; - pthread_mutex_unlock(&_state_mu); - return 1; -} - -el_val_t state_get(el_val_t key) { - const char* k = EL_CSTR(key); - if (!k) return el_wrap_str(el_strdup("")); - pthread_mutex_lock(&_state_mu); - StateEntry* e = state_find(k); - char* result = el_strdup_persist(e ? e->value : ""); - pthread_mutex_unlock(&_state_mu); - /* wrap in arena-tracked copy for the caller's request lifetime */ - char* copy = el_strdup(result); - return el_wrap_str(copy); -} - -el_val_t state_del(el_val_t key) { - const char* k = EL_CSTR(key); - if (!k) return 0; - pthread_mutex_lock(&_state_mu); - for (size_t i = 0; i < _state_count; i++) { - if (strcmp(_state_entries[i].key, k) == 0) { - free(_state_entries[i].key); - free(_state_entries[i].value); - for (size_t j = i + 1; j < _state_count; j++) { - _state_entries[j - 1] = _state_entries[j]; - } - _state_count--; - pthread_mutex_unlock(&_state_mu); - return 1; - } - } - pthread_mutex_unlock(&_state_mu); - return 1; -} - -el_val_t state_keys(void) { - pthread_mutex_lock(&_state_mu); - el_val_t lst = el_list_empty(); - for (size_t i = 0; i < _state_count; i++) { - lst = el_list_append(lst, el_wrap_str(el_strdup(_state_entries[i].key))); - } - pthread_mutex_unlock(&_state_mu); - return lst; -} - -/* ── Float formatting ────────────────────────────────────────────────────── */ - -el_val_t float_to_str(el_val_t f) { - char buf[64]; - snprintf(buf, sizeof(buf), "%g", el_to_float(f)); - return el_wrap_str(el_strdup(buf)); -} - -el_val_t int_to_float(el_val_t n) { - return el_from_float((double)(int64_t)n); -} - -el_val_t float_to_int(el_val_t f) { - return (el_val_t)(int64_t)el_to_float(f); -} - -el_val_t format_float(el_val_t f, el_val_t decimals) { - int d = (int)(int64_t)decimals; - if (d < 0) d = 0; - if (d > 30) d = 30; - char buf[128]; - snprintf(buf, sizeof(buf), "%.*f", d, el_to_float(f)); - return el_wrap_str(el_strdup(buf)); -} - -el_val_t decimal_round(el_val_t f, el_val_t decimals) { - int d = (int)(int64_t)decimals; - if (d < 0) d = 0; - if (d > 15) d = 15; - double mul = pow(10.0, (double)d); - double v = el_to_float(f); - double r = (v >= 0.0 ? floor(v * mul + 0.5) : -floor(-v * mul + 0.5)) / mul; - return el_from_float(r); -} - -el_val_t str_to_float(el_val_t s) { - const char* str = EL_CSTR(s); - if (!str) return el_from_float(0.0); - return el_from_float(strtod(str, NULL)); -} - -/* ── Math (Float-aware) ──────────────────────────────────────────────────── */ - -el_val_t math_sqrt(el_val_t f) { return el_from_float(sqrt(el_to_float(f))); } -el_val_t math_log(el_val_t f) { return el_from_float(log(el_to_float(f))); } -el_val_t math_ln(el_val_t f) { return el_from_float(log(el_to_float(f))); } -el_val_t math_sin(el_val_t f) { return el_from_float(sin(el_to_float(f))); } -el_val_t math_cos(el_val_t f) { return el_from_float(cos(el_to_float(f))); } -el_val_t math_pi(void) { return el_from_float(3.141592653589793238462643383279502884); } - -/* ── String additions ────────────────────────────────────────────────────── */ - -el_val_t str_index_of(el_val_t s, el_val_t sub) { - const char* str = EL_CSTR(s); - const char* sb = EL_CSTR(sub); - if (!str || !sb) return -1; - const char* hit = strstr(str, sb); - if (!hit) return -1; - return (el_val_t)(int64_t)(hit - str); -} - -el_val_t str_split(el_val_t s, el_val_t sep) { - const char* str = EL_CSTR(s); - const char* sp = EL_CSTR(sep); - el_val_t lst = el_list_empty(); - if (!str) return lst; - if (!sp || !*sp) { - lst = el_list_append(lst, el_wrap_str(el_strdup(str))); - return lst; - } - size_t lp = strlen(sp); - const char* p = str; - const char* hit; - while ((hit = strstr(p, sp)) != NULL) { - size_t n = (size_t)(hit - p); - char* out = el_strbuf(n); - memcpy(out, p, n); - out[n] = '\0'; - lst = el_list_append(lst, el_wrap_str(out)); - p = hit + lp; - } - lst = el_list_append(lst, el_wrap_str(el_strdup(p))); - return lst; -} - -el_val_t str_char_at(el_val_t s, el_val_t i) { - const char* str = EL_CSTR(s); - int64_t idx = (int64_t)i; - if (!str) return el_wrap_str(el_strdup("")); - int64_t n = (int64_t)strlen(str); - if (idx < 0 || idx >= n) return el_wrap_str(el_strdup("")); - char buf[2]; - buf[0] = str[idx]; - buf[1] = '\0'; - return el_wrap_str(el_strdup(buf)); -} - -el_val_t str_char_code(el_val_t s, el_val_t i) { - const char* str = EL_CSTR(s); - int64_t idx = (int64_t)i; - if (!str) return 0; - int64_t n = (int64_t)strlen(str); - if (idx < 0 || idx >= n) return 0; - return (el_val_t)(unsigned char)str[idx]; -} - -static el_val_t str_pad(const char* s, int64_t width, const char* pad, int left) { - if (!s) s = ""; - if (!pad || !*pad) pad = " "; - int64_t lp = (int64_t)strlen(pad); - int64_t ls = (int64_t)strlen(s); - if (ls >= width) return el_wrap_str(el_strdup(s)); - int64_t need = width - ls; - char* out = el_strbuf((size_t)width); - if (left) { - for (int64_t i = 0; i < need; i++) out[i] = pad[i % lp]; - memcpy(out + need, s, (size_t)ls); - } else { - memcpy(out, s, (size_t)ls); - for (int64_t i = 0; i < need; i++) out[ls + i] = pad[i % lp]; - } - out[width] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_pad_left(el_val_t s, el_val_t width, el_val_t pad) { - return str_pad(EL_CSTR(s), (int64_t)width, EL_CSTR(pad), 1); -} - -el_val_t str_pad_right(el_val_t s, el_val_t width, el_val_t pad) { - return str_pad(EL_CSTR(s), (int64_t)width, EL_CSTR(pad), 0); -} - -el_val_t str_format(el_val_t fmt, el_val_t data) { - const char* tpl = EL_CSTR(fmt); - if (!tpl) return el_wrap_str(el_strdup("")); - JsonBuf b; jb_init(&b); - const char* p = tpl; - while (*p) { - if (*p == '{') { - const char* q = p + 1; - while (*q && *q != '}') q++; - if (*q == '}') { - size_t klen = (size_t)(q - p - 1); - char keybuf[256]; - if (klen < sizeof(keybuf)) { - memcpy(keybuf, p + 1, klen); - keybuf[klen] = '\0'; - el_val_t v = el_map_get(data, EL_STR(keybuf)); - if (v != 0 && looks_like_string(v)) { - jb_puts(&b, EL_CSTR(v)); - p = q + 1; - continue; - } else if (v != 0) { - jb_emit_int(&b, (int64_t)v); - p = q + 1; - continue; - } - } - /* Unknown key — leave {key} verbatim */ - jb_reserve(&b, klen + 2); - memcpy(b.buf + b.len, p, klen + 2); - b.len += klen + 2; - b.buf[b.len] = '\0'; - p = q + 1; - continue; - } - } - jb_putc(&b, *p); - p++; - } - return el_wrap_str(b.buf); -} - -el_val_t str_lower(el_val_t s) { return str_to_lower(s); } -el_val_t str_upper(el_val_t s) { return str_to_upper(s); } - -/* ── Text-processing primitives (Phase 1: byte/codepoint, ASCII char classes) - * - * Phase 1 covers the operations every text-handling caller used to roll by - * hand on top of str_index_of + str_slice. The character-class predicates - * (is_letter / is_digit / ...) are ASCII only — Unicode-grapheme awareness, - * NFC/NFD normalization, and regex are Phase 2. Single-char input checks the - * first byte; multi-char input requires ALL bytes to match (false otherwise). - * - * Counting: - * str_count non-overlapping occurrences of sub in s - * str_count_chars codepoint count (UTF-8 leading-byte count) - * str_count_bytes explicit byte length (alias of str_len) - * str_count_lines \n-delimited line count (\r\n folded to \n) - * str_count_words whitespace-delimited tokens, non-empty only - * str_count_letters ASCII [A-Za-z] - * str_count_digits ASCII [0-9] - * - * Find / position: - * str_index_of_all all byte offsets of sub, [] if none - * str_last_index_of last byte offset of sub, -1 if not found - * str_find_chars first index of any char in any_of, -1 if none - * - * Transform: - * str_repeat s * n (non-negative) - * str_reverse codepoint-reversed (NOT grapheme-aware) - * str_strip_prefix s without prefix if present, else s - * str_strip_suffix s without suffix if present, else s - * str_strip_chars strip leading+trailing chars matching any in chars - * str_lstrip strip leading whitespace - * str_rstrip strip trailing whitespace - * - * Char classification (Bool): - * is_letter, is_digit, is_alphanumeric, is_whitespace, - * is_punctuation, is_uppercase, is_lowercase - * - * Splitting: - * str_split_lines \n-delimited (\r\n folded). Trailing empty dropped. - * str_split_chars alias of native_string_chars in str_ namespace - * str_split_n split into at most n parts (last part keeps the - * rest verbatim, including any further separators) - * - * Joining: - * str_join [String] -> String, sep between elements - */ - -/* Count non-overlapping occurrences of sub in s. Empty sub returns 0. */ -el_val_t str_count(el_val_t sv, el_val_t subv) { - const char* s = EL_CSTR(sv); - const char* sub = EL_CSTR(subv); - if (!s || !sub || !*sub) return 0; - size_t lp = strlen(sub); - int64_t count = 0; - const char* p = s; - while ((p = strstr(p, sub)) != NULL) { - count++; - p += lp; /* non-overlapping advance */ - } - return (el_val_t)count; -} - -/* Codepoint count: walk bytes, count those NOT matching 10xxxxxx. */ -el_val_t str_count_chars(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - int64_t count = 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if ((*p & 0xC0) != 0x80) count++; - } - return (el_val_t)count; -} - -el_val_t str_count_bytes(el_val_t sv) { - return str_len(sv); -} - -el_val_t str_count_lines(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s || !*s) return 0; - int64_t count = 0; - int has_content = 0; - for (const char* p = s; *p; p++) { - has_content = 1; - if (*p == '\n') { - count++; - has_content = 0; /* the \n closed the line */ - } - } - if (has_content) count++; /* trailing line with no terminator */ - return (el_val_t)count; -} - -el_val_t str_count_words(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - int64_t count = 0; - int in_word = 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if (isspace(*p)) { - in_word = 0; - } else if (!in_word) { - in_word = 1; - count++; - } - } - return (el_val_t)count; -} - -el_val_t str_count_letters(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - int64_t count = 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z')) count++; - } - return (el_val_t)count; -} - -el_val_t str_count_digits(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return 0; - int64_t count = 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if (*p >= '0' && *p <= '9') count++; - } - return (el_val_t)count; -} - -el_val_t str_index_of_all(el_val_t sv, el_val_t subv) { - const char* s = EL_CSTR(sv); - const char* sub = EL_CSTR(subv); - el_val_t lst = el_list_empty(); - if (!s || !sub || !*sub) return lst; - size_t lp = strlen(sub); - const char* p = s; - const char* hit; - while ((hit = strstr(p, sub)) != NULL) { - lst = el_list_append(lst, (el_val_t)(int64_t)(hit - s)); - p = hit + lp; - } - return lst; -} - -el_val_t str_last_index_of(el_val_t sv, el_val_t subv) { - const char* s = EL_CSTR(sv); - const char* sub = EL_CSTR(subv); - if (!s || !sub || !*sub) return -1; - size_t lp = strlen(sub); - int64_t last = -1; - const char* p = s; - const char* hit; - while ((hit = strstr(p, sub)) != NULL) { - last = (int64_t)(hit - s); - p = hit + lp; - } - return (el_val_t)last; -} - -el_val_t str_find_chars(el_val_t sv, el_val_t any_of_v) { - const char* s = EL_CSTR(sv); - const char* any = EL_CSTR(any_of_v); - if (!s || !any || !*any) return -1; - for (const char* p = s; *p; p++) { - if (strchr(any, *p)) return (el_val_t)(int64_t)(p - s); - } - return -1; -} - -el_val_t str_repeat(el_val_t sv, el_val_t nv) { - const char* s = EL_CSTR(sv); - int64_t n = (int64_t)nv; - if (!s || n <= 0) return el_wrap_str(el_strdup("")); - size_t ls = strlen(s); - if (ls == 0) return el_wrap_str(el_strdup("")); - size_t total = ls * (size_t)n; - char* out = el_strbuf(total); - for (int64_t i = 0; i < n; i++) { - memcpy(out + i * ls, s, ls); - } - out[total] = '\0'; - return el_wrap_str(out); -} - -/* Reverse by codepoint: walk codepoints, copy each backwards into the output. - * NOT grapheme-aware (Phase 2). Combining marks attached to a base codepoint - * will detach. ASCII strings are byte-reverse equivalent. */ -el_val_t str_reverse(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - size_t n = strlen(s); - char* out = el_strbuf(n); - /* Walk forward, find each codepoint's byte length, then copy from the end. */ - size_t out_pos = n; - const unsigned char* p = (const unsigned char*)s; - while (*p) { - int cp_len; - if ((*p & 0x80) == 0x00) cp_len = 1; - else if ((*p & 0xE0) == 0xC0) cp_len = 2; - else if ((*p & 0xF0) == 0xE0) cp_len = 3; - else if ((*p & 0xF8) == 0xF0) cp_len = 4; - else cp_len = 1; /* invalid byte: passthrough */ - out_pos -= cp_len; - memcpy(out + out_pos, p, cp_len); - p += cp_len; - } - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_strip_prefix(el_val_t sv, el_val_t prefv) { - const char* s = EL_CSTR(sv); - const char* pref = EL_CSTR(prefv); - if (!s) return el_wrap_str(el_strdup("")); - if (!pref || !*pref) return el_wrap_str(el_strdup(s)); - size_t lp = strlen(pref); - size_t ls = strlen(s); - if (lp <= ls && strncmp(s, pref, lp) == 0) { - char* out = el_strbuf(ls - lp); - memcpy(out, s + lp, ls - lp); - out[ls - lp] = '\0'; - return el_wrap_str(out); - } - return el_wrap_str(el_strdup(s)); -} - -el_val_t str_strip_suffix(el_val_t sv, el_val_t sufv) { - const char* s = EL_CSTR(sv); - const char* suf = EL_CSTR(sufv); - if (!s) return el_wrap_str(el_strdup("")); - if (!suf || !*suf) return el_wrap_str(el_strdup(s)); - size_t ls = strlen(s); - size_t lsuf = strlen(suf); - if (lsuf <= ls && strcmp(s + ls - lsuf, suf) == 0) { - char* out = el_strbuf(ls - lsuf); - memcpy(out, s, ls - lsuf); - out[ls - lsuf] = '\0'; - return el_wrap_str(out); - } - return el_wrap_str(el_strdup(s)); -} - -el_val_t str_strip_chars(el_val_t sv, el_val_t charsv) { - const char* s = EL_CSTR(sv); - const char* chars = EL_CSTR(charsv); - if (!s) return el_wrap_str(el_strdup("")); - if (!chars || !*chars) return el_wrap_str(el_strdup(s)); - const char* start = s; - while (*start && strchr(chars, *start)) start++; - size_t n = strlen(start); - while (n > 0 && strchr(chars, start[n - 1])) n--; - char* out = el_strbuf(n); - memcpy(out, start, n); - out[n] = '\0'; - return el_wrap_str(out); -} - -el_val_t str_lstrip(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - while (*s && isspace((unsigned char)*s)) s++; - return el_wrap_str(el_strdup(s)); -} - -el_val_t str_rstrip(el_val_t sv) { - const char* s = EL_CSTR(sv); - if (!s) return el_wrap_str(el_strdup("")); - size_t n = strlen(s); - while (n > 0 && isspace((unsigned char)s[n - 1])) n--; - char* out = el_strbuf(n); - memcpy(out, s, n); - out[n] = '\0'; - return el_wrap_str(out); -} - -/* Character classification. - * Empty input returns false. Multi-char input requires ALL bytes to match. - * ASCII range only; Phase 2 will widen to Unicode. */ -static int s_all_match(el_val_t sv, int (*pred)(unsigned char)) { - const char* s = EL_CSTR(sv); - if (!s || !*s) return 0; - for (const unsigned char* p = (const unsigned char*)s; *p; p++) { - if (!pred(*p)) return 0; - } - return 1; -} - -static int p_letter(unsigned char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } -static int p_digit(unsigned char c) { return c >= '0' && c <= '9'; } -static int p_alnum(unsigned char c) { return p_letter(c) || p_digit(c); } -static int p_white(unsigned char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'; } -static int p_punct(unsigned char c) { return ispunct(c) ? 1 : 0; } -static int p_upper(unsigned char c) { return c >= 'A' && c <= 'Z'; } -static int p_lower(unsigned char c) { return c >= 'a' && c <= 'z'; } - -el_val_t is_letter(el_val_t s) { return (el_val_t)s_all_match(s, p_letter); } -el_val_t is_digit(el_val_t s) { return (el_val_t)s_all_match(s, p_digit); } -el_val_t is_alphanumeric(el_val_t s) { return (el_val_t)s_all_match(s, p_alnum); } -el_val_t is_whitespace(el_val_t s) { return (el_val_t)s_all_match(s, p_white); } -el_val_t is_punctuation(el_val_t s) { return (el_val_t)s_all_match(s, p_punct); } -el_val_t is_uppercase(el_val_t s) { return (el_val_t)s_all_match(s, p_upper); } -el_val_t is_lowercase(el_val_t s) { return (el_val_t)s_all_match(s, p_lower); } - -/* Split on \n. \r\n is folded to \n first. Trailing empty after final \n - * is dropped (so "a\nb\n" -> ["a", "b"], not ["a", "b", ""]). */ -el_val_t str_split_lines(el_val_t sv) { - const char* s = EL_CSTR(sv); - el_val_t lst = el_list_empty(); - if (!s) return lst; - size_t n = strlen(s); - /* Pre-scan: build into a normalized buffer with \r\n folded. */ - const char* line_start = s; - for (size_t i = 0; i <= n; i++) { - if (s[i] == '\n' || s[i] == '\0') { - size_t len = (size_t)(s + i - line_start); - /* Drop trailing \r if this was \r\n. */ - if (len > 0 && line_start[len - 1] == '\r') len--; - /* Drop final trailing-empty-after-newline. */ - if (s[i] == '\0' && len == 0 && i > 0 && s[i - 1] == '\n') break; - char* out = el_strbuf(len); - memcpy(out, line_start, len); - out[len] = '\0'; - lst = el_list_append(lst, el_wrap_str(out)); - if (s[i] == '\0') break; - line_start = s + i + 1; - } - } - return lst; -} - -el_val_t str_split_chars(el_val_t s) { - return native_string_chars(s); -} - -/* Split into at most n parts. The (n-1)th split point is the LAST split; - * after it, the remainder is appended verbatim including any further - * separators. n <= 0 returns an empty list. n == 1 returns [s]. */ -el_val_t str_split_n(el_val_t sv, el_val_t sepv, el_val_t nv) { - const char* s = EL_CSTR(sv); - const char* sep = EL_CSTR(sepv); - int64_t n = (int64_t)nv; - el_val_t lst = el_list_empty(); - if (!s) return lst; - if (n <= 0) return lst; - if (n == 1 || !sep || !*sep) { - lst = el_list_append(lst, el_wrap_str(el_strdup(s))); - return lst; - } - size_t lp = strlen(sep); - const char* p = s; - int64_t parts = 0; - const char* hit; - while (parts < n - 1 && (hit = strstr(p, sep)) != NULL) { - size_t len = (size_t)(hit - p); - char* out = el_strbuf(len); - memcpy(out, p, len); - out[len] = '\0'; - lst = el_list_append(lst, el_wrap_str(out)); - p = hit + lp; - parts++; - } - /* Remainder verbatim. */ - lst = el_list_append(lst, el_wrap_str(el_strdup(p))); - return lst; -} - -/* Join a [String] with a separator. Empty list -> "". Single-element -> - * that element. Non-string elements are stringified via int_to_str. */ -el_val_t str_join(el_val_t listv, el_val_t sepv) { - return list_join(listv, sepv); -} - -/* ── List additions ──────────────────────────────────────────────────────── */ - -el_val_t list_push(el_val_t list, el_val_t elem) { - return el_list_append(list, elem); -} - -el_val_t list_push_front(el_val_t listv, el_val_t elem) { - ElList* lst = (ElList*)(uintptr_t)listv; - if (!lst) { - el_val_t nl = el_list_empty(); - return el_list_append(nl, elem); - } - /* Append to grow capacity, then shift right */ - listv = el_list_append(listv, elem); - lst = (ElList*)(uintptr_t)listv; - for (int64_t i = lst->length - 1; i > 0; i--) { - lst->elems[i] = lst->elems[i - 1]; - } - lst->elems[0] = elem; - return EL_STR(lst); -} - -el_val_t list_join(el_val_t listv, el_val_t sep) { - ElList* lst = (ElList*)(uintptr_t)listv; - const char* sp = EL_CSTR(sep); - if (!sp) sp = ""; - if (!lst || lst->length == 0) return el_wrap_str(el_strdup("")); - JsonBuf b; jb_init(&b); - for (int64_t i = 0; i < lst->length; i++) { - if (i > 0) jb_puts(&b, sp); - el_val_t v = lst->elems[i]; - if (v == 0) continue; - if (looks_like_string(v)) { - jb_puts(&b, EL_CSTR(v)); - } else { - char tmp[32]; - snprintf(tmp, sizeof(tmp), "%lld", (long long)v); - jb_puts(&b, tmp); - } - } - return el_wrap_str(b.buf); -} - -el_val_t list_range(el_val_t start, el_val_t end) { - int64_t a = (int64_t)start; - int64_t b = (int64_t)end; - el_val_t lst = el_list_empty(); - for (int64_t i = a; i < b; i++) lst = el_list_append(lst, (el_val_t)i); - return lst; -} - -/* ── Bool helpers ────────────────────────────────────────────────────────── */ - -el_val_t bool_to_str(el_val_t b) { - return el_wrap_str(el_strdup(b ? "true" : "false")); -} - -/* ── Numeric parsing ─────────────────────────────────────────────────────── */ - -/* parse_int — strtoll with a default. str_to_int already exists but does not - * distinguish "0" from a parse failure, so callers that need a sentinel use - * this. Skips leading whitespace; accepts an optional leading +/-; returns - * default_val on empty input or no consumed digits. Trailing junk is ignored - * (atoi-style). */ -el_val_t parse_int(el_val_t sv, el_val_t default_val) { - const char* s = EL_CSTR(sv); - if (!s) return default_val; - while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') s++; - if (*s == '\0') return default_val; - char* end = NULL; - long long n = strtoll(s, &end, 10); - if (end == s) return default_val; - return (el_val_t)n; -} - -/* ── Process ─────────────────────────────────────────────────────────────── */ - -void exit_program(el_val_t code) { - exit((int)code); -} - -/* getpid_now — current process id. Named with the _now suffix to avoid - * colliding with the libc `getpid` declaration that the runtime already - * sees via (calling it `getpid` would fight the prototype). */ -el_val_t getpid_now(void) { - return (el_val_t)getpid(); -} - -/* ── args() — command-line argument access ────────────────────────────────── - * Compiled El programs call args() to get a list of CLI arguments. - * Call el_runtime_init_args(argc, argv) at the start of C main() to populate. - * The args list excludes argv[0] (the program name). */ - -static el_val_t _el_args_list = 0; - -void el_runtime_init_args(int argc, char** argv) { - _el_args_list = el_list_empty(); - for (int i = 1; i < argc; i++) { - _el_args_list = el_list_append(_el_args_list, EL_STR(argv[i])); - } -} - -el_val_t args(void) { - if (!_el_args_list) _el_args_list = el_list_empty(); - return _el_args_list; -} - -/* ── CGI identity ──────────────────────────────────────────────────────────── - * Called once at program start by the generated main() of a cgi {} program. - * Stores CGI identity so dharma_* builtins can reference it. */ - -static const char* _el_cgi_name = NULL; -static const char* _el_cgi_dharma_id = NULL; -static const char* _el_cgi_principal = NULL; -static const char* _el_cgi_network = NULL; -static const char* _el_cgi_engram = NULL; - -void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, - el_val_t network, el_val_t engram) { - _el_cgi_name = EL_CSTR(name); - _el_cgi_dharma_id = EL_CSTR(dharma_id); - _el_cgi_principal = EL_CSTR(principal); - _el_cgi_network = EL_CSTR(network) ? EL_CSTR(network) : "dharma-mainnet"; - _el_cgi_engram = EL_CSTR(engram) ? EL_CSTR(engram) : "http://localhost:8742"; - printf("[cgi] identity: name=%s dharma_id=%s principal=%s network=%s engram=%s\n", - _el_cgi_name ? _el_cgi_name : "(unset)", - _el_cgi_dharma_id ? _el_cgi_dharma_id : "(unset)", - _el_cgi_principal ? _el_cgi_principal : "(unset)", - _el_cgi_network, - _el_cgi_engram); -} - - -/* ── Batch 3: Engram in-process graph store ──────────────────────────────── */ -/* - * Single global EngramStore allocated lazily on first call. All node and - * edge content strings are owned (strdup'd) by the store. Linear arrays - * with doubling capacity for both nodes and edges. - * - * Two-layer activation algorithm (engram_activate): - * - * LAYER 1 — Broad fan-out (background activation): - * 1. Find seed nodes whose content/label/tags contain query (case-insens). - * 2. BFS up to `depth` hops along ALL edges (excitatory and inhibitory). - * Every reachable node fires — nothing is filtered at this layer. - * 3. bg_act = seed.salience * temporal_decay * dampening - * propagated as: new_bg = parent_bg * edge_weight * 0.7 * (1 + tbonus) - * where tbonus ∈ {0, 0.10, 0.20} for co-temporal nodes. - * 4. If reached by multiple paths, take max background_activation. - * 5. Persist background_activation to EngramNode.background_activation. - * - * LAYER 2 — Executive filter (working memory promotion): - * 6. For each inhibitory edge where source has background_activation > 0: - * inhibition[target] = max(bg[source] * e->weight) - * 7. For each background-activated node: - * raw_wm = bg * goal_bias(node, query) * confidence - * * (1 - (1 - INHIBITION_FACTOR) * inhibition) - * 8. Per-type threshold gate: raw_wm >= type_threshold → promoted. - * Safety/DharmaSelf: 0.05 Canonical: 0.15 Lesson: 0.25 - * Belief/Entity: 0.30 Note/Memory/Working: 0.40 - * 9. If not promoted: suppression_count++. After - * ENGRAM_SUPPRESSION_BREAKTHROUGH suppressions → force breakthrough - * at ENGRAM_BREAKTHROUGH_WEIGHT (latent tension surfacing). - * 10. Persist working_memory_weight to EngramNode.working_memory_weight. - * 11. Sort: promoted nodes (wm > 0) first by wm desc, then background- - * only by bg desc. Context compilation uses ONLY promoted nodes. - * - * Temporal decay: - * decay_factor = exp(-lambda * age_hours / T_half) - * T_half = 168.0 h (one week), lambda = ln(2) - * - * Activation dampening: - * dampen = 1.0 / (1.0 + log(1 + activation_count)) - * - * engram_query_range(start_ms, end_ms): - * Returns nodes whose created_at OR last_activated falls within - * [start_ms, end_ms], sorted by created_at ascending. - */ - -/* Temporal decay constants. - * T_HALF_HOURS: half-life in hours — one week. After one week of no - * activation a node retains 50% of its base salience contribution. - * DECAY_LAMBDA: ln(2) ≈ 0.693147 */ -#define ENGRAM_T_HALF_HOURS 168.0 -#define ENGRAM_DECAY_LAMBDA 0.693147 - -/* Two-layer activation constants. - * ENGRAM_WM_THRESHOLD: minimum background_activation for a node to be - * considered for working-memory promotion (layer 2 candidate gate). - * ENGRAM_WM_DECAY: per-turn decay applied to working_memory_weight for - * nodes NOT re-activated in the current turn (conversational thread - * continuity: a node promoted in turn N persists with reduced weight - * into turn N+1 without re-activation cost). - * ENGRAM_SUPPRESSION_BREAKTHROUGH: after this many consecutive suppressions - * a latent node forces itself into working memory at reduced weight, - * modelling the brain's "intrusive thought" / unresolved-tension surfacing. - * ENGRAM_BREAKTHROUGH_WEIGHT: the reduced working_memory_weight assigned - * when a suppressed node breaks through. - * ENGRAM_INHIBITION_FACTOR: multiplier applied to working_memory_weight when - * an inhibitory edge fires against a node (0 = full suppress, 0.3 = partial). */ -#define ENGRAM_WM_THRESHOLD 0.15 -#define ENGRAM_WM_DECAY 0.7 -#define ENGRAM_SUPPRESSION_BREAKTHROUGH 5 -#define ENGRAM_BREAKTHROUGH_WEIGHT 0.25 -#define ENGRAM_INHIBITION_FACTOR 0.1 - -/* ── Layered consciousness architecture ────────────────────────────────────── - * - * The engram graph is stratified into LAYERS that gate which suppressions - * apply during the executive filter pass. Layers are ordered shallow-to-deep - * by `activation_priority`; the deepest layer (priority 0, conventionally - * "safety") is the structural floor of the soul: nodes here cannot be - * silenced by inhibitory edges from any other layer. Higher layers - * (core-identity, domain-knowledge, imprint, suit) are normally - * suppressible — they participate in attentional inhibition and goal - * focus the way the prior single-graph implementation did. - * - * The five canonical layers (see engram_init_layers): - * 0. safety — structural, transparent, non-injectable, non-suppressible - * 1. core-identity — default for legacy nodes; suppressible - * 2. domain-knowledge— suppressible - * 3. imprint — runtime-injectable (an Imprint package can add/remove) - * 4. suit — runtime-injectable (a Suit overlays domain skill) - * - * Three-pass activation (engram_activate): - * Pass 1 — Background fan-out: BFS spreads activation across ALL layers - * (existing behavior preserved). Inhibitory edges propagate at - * this layer too; no filtering happens here. - * Pass 2 — Working memory promotion: type-threshold gate, goal bias, - * confidence weighting, inhibitory suppression. Inhibitory edges - * ONLY apply against nodes whose layer is `suppressible == 1`. - * Nodes in non-suppressible layers (Layer 0) ignore inhibition. - * Pass 3 — Layer 0 override: every node in a non-suppressible layer that - * received background activation has its working_memory_weight - * forced to >= ENGRAM_LAYER0_OVERRIDE_WEIGHT. The sacred fire — - * safety nodes that touched any seed unconditionally surface, - * even when the executive filter would have silenced them. - * - * Layer fields: - * suppressible : 0 → inhibitory edges are ignored against nodes in this - * layer during pass 2. Pass 3 also force-promotes them. - * 1 → standard behavior (most layers). - * transparent : 1 → emitted into the prompt context so its content shapes - * output, but filtered out of "what do you know about - * yourself?" introspection queries (engram_search and - * friends do not return transparent-layer nodes by - * default). 0 → fully visible to introspection. - * injectable : 1 → can be added/removed at runtime via engram_add_layer - * and engram_remove_layer (imprints, suits). - * 0 → built-in, fixed at engram_get() initialization. - * - * Backward compatibility: - * Nodes and edges loaded from snapshots without a `layer_id` field default - * to layer 1 (core-identity). The five canonical layers are always present. - */ -#define ENGRAM_LAYER_SAFETY 0u -#define ENGRAM_LAYER_CORE_IDENTITY 1u -#define ENGRAM_LAYER_DOMAIN 2u -#define ENGRAM_LAYER_IMPRINT 3u -#define ENGRAM_LAYER_SUIT 4u -#define ENGRAM_LAYER_DEFAULT ENGRAM_LAYER_CORE_IDENTITY - -/* Pass 3 override floor. Layer 0 nodes that received any background - * activation are force-promoted to AT LEAST this working_memory_weight, - * regardless of inhibitory suppression in pass 2. */ -#define ENGRAM_LAYER0_OVERRIDE_WEIGHT 1.0 - -/* Per-node-type activation thresholds. - * Lower tier / safety-critical nodes fire more readily. */ -static double engram_type_threshold(const char* node_type, const char* tier) { - if (node_type) { - if (strcmp(node_type, "DharmaSelf") == 0) return 0.05; - if (strcmp(node_type, "Safety") == 0) return 0.05; - } - if (tier) { - if (strcmp(tier, "Canonical") == 0) return 0.15; - if (strcmp(tier, "Lesson") == 0) return 0.25; - } - if (node_type) { - if (strcmp(node_type, "Belief") == 0) return 0.30; - if (strcmp(node_type, "Entity") == 0) return 0.30; - } - return 0.40; /* Note / Memory / Working (most nodes) */ -} - -typedef struct EngramNode { - char* id; - char* content; - char* node_type; - char* label; - char* tier; - char* tags; - char* metadata; - double salience; - double importance; - double confidence; - double temporal_decay_rate; /* per-node override for lambda; 0 = use default */ - int64_t activation_count; - int64_t last_activated; - int64_t created_at; - int64_t updated_at; - /* Two-layer activation fields ───────────────────────────────────────── - * background_activation: Layer 1. Set by BFS fan-out on every query. - * Every reachable node fires here — nothing is filtered at this stage. - * Models the brain's massive parallel sub-threshold activation of all - * associated content in response to a stimulus. - * working_memory_weight: Layer 2. Executive filter output. Only nodes - * that survive goal-state / attentional-bias scoring receive a - * non-zero weight here. Context compilation ONLY uses this field. - * Background-activated nodes with working_memory_weight == 0 remain - * latent — real, available, but silent. - * suppression_count: Consecutive turn count where this node was - * background-activated but NOT promoted to working memory. High - * values signal the node "wants to surface." After - * ENGRAM_SUPPRESSION_BREAKTHROUGH consecutive suppressions the node - * is force-promoted at a reduced weight (breakthrough activation). */ - double background_activation; - double working_memory_weight; - int32_t suppression_count; - /* Layered consciousness — see ENGRAM_LAYER_* macros and engram_init_layers. - * Defaults to ENGRAM_LAYER_DEFAULT (1, core-identity) for legacy nodes - * created via engram_node / engram_node_full and for snapshots that - * predate the layered schema. */ - uint32_t layer_id; -} EngramNode; - -typedef struct EngramEdge { - char* id; - char* from_id; - char* to_id; - char* relation; - char* metadata; - double weight; - double confidence; - int64_t created_at; - int64_t updated_at; - int64_t last_fired; - /* Inhibitory flag: when 1, activating the source node SUPPRESSES the - * working_memory_weight of the target node rather than exciting it. - * Models attentional inhibition: "I am focused on code work" creates - * inhibitory edges to personal/emotional nodes, preventing them from - * surfacing even if they have high background_activation. */ - int inhibitory; - /* Layered consciousness — edges carry a layer assignment for - * categorization/visualization. Pass 2 inhibitory gating is decided by - * the TARGET node's layer (whether it's suppressible), not by the edge - * layer. Defaults to ENGRAM_LAYER_DEFAULT. */ - uint32_t layer_id; -} EngramEdge; - -/* Layered consciousness — runtime layer registry entry. */ -typedef struct EngramLayer { - uint32_t layer_id; /* 0 = deepest (safety/limbic) */ - char* name; /* persistent — owned by the store */ - uint32_t activation_priority; /* lower = fires earlier; safety = 0 */ - int suppressible; /* can higher layers suppress nodes here? */ - int transparent; /* invisible to introspection queries? */ - int injectable; /* can be added/removed at runtime? */ -} EngramLayer; - -typedef struct EngramStore { - EngramNode* nodes; - int64_t node_count; - int64_t node_capacity; - EngramEdge* edges; - int64_t edge_count; - int64_t edge_capacity; - /* Layer registry — see engram_init_layers. The five canonical layers - * are always present; injectable layers (imprint, suit) are extended - * via engram_add_layer at runtime. layer_id values are assigned - * monotonically; removed injectable layers leave a NULL `name` slot - * (tombstone) so existing layer_id references on nodes stay stable. */ - EngramLayer* layers; - size_t layer_count; - size_t layer_capacity; -} EngramStore; - -static EngramStore* engram_global = NULL; - -/* Initialize the five canonical layers on a fresh store. Called once from - * engram_get(). Layer ids 0..4 are reserved; runtime-injected imprint/suit - * layers (engram_add_layer) get ids 5+. */ -static void engram_init_layers(EngramStore* g) { - g->layer_capacity = 16; - g->layers = calloc(g->layer_capacity, sizeof(EngramLayer)); - if (!g->layers) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - g->layer_count = 0; - - /* Layer 0 — safety. Structural floor. Non-suppressible; transparent - * (filtered out of introspection but still shapes output); not - * runtime-injectable. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_SAFETY, - .name = el_strdup_persist("safety"), - .activation_priority = 0, - .suppressible = 0, - .transparent = 1, - .injectable = 0 - }; - /* Layer 1 — core-identity. The default home for legacy nodes. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_CORE_IDENTITY, - .name = el_strdup_persist("core-identity"), - .activation_priority = 10, - .suppressible = 1, - .transparent = 0, - .injectable = 0 - }; - /* Layer 2 — domain-knowledge. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_DOMAIN, - .name = el_strdup_persist("domain-knowledge"), - .activation_priority = 20, - .suppressible = 1, - .transparent = 0, - .injectable = 0 - }; - /* Layer 3 — imprint. Injectable: an imprint package adds/removes this - * layer (and the nodes assigned to it) as a unit. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_IMPRINT, - .name = el_strdup_persist("imprint"), - .activation_priority = 30, - .suppressible = 1, - .transparent = 0, - .injectable = 1 - }; - /* Layer 4 — suit. Injectable: a Suit overlays domain skill (e.g. - * "enterprise advisor", "divorce lawyer") and can be detached. */ - g->layers[g->layer_count++] = (EngramLayer){ - .layer_id = ENGRAM_LAYER_SUIT, - .name = el_strdup_persist("suit"), - .activation_priority = 40, - .suppressible = 1, - .transparent = 0, - .injectable = 1 - }; -} - -static EngramStore* engram_get(void) { - if (engram_global) return engram_global; - engram_global = calloc(1, sizeof(EngramStore)); - if (!engram_global) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - engram_global->node_capacity = 16; - engram_global->nodes = calloc((size_t)engram_global->node_capacity, sizeof(EngramNode)); - engram_global->edge_capacity = 16; - engram_global->edges = calloc((size_t)engram_global->edge_capacity, sizeof(EngramEdge)); - engram_init_layers(engram_global); - return engram_global; -} - -/* Resolve a layer record by id. Returns NULL if no layer with that id - * exists (e.g. a removed injectable layer or a malformed snapshot). */ -static EngramLayer* engram_find_layer(uint32_t layer_id) { - EngramStore* g = engram_get(); - for (size_t i = 0; i < g->layer_count; i++) { - EngramLayer* L = &g->layers[i]; - if (!L->name) continue; /* tombstone for removed injectable layer */ - if (L->layer_id == layer_id) return L; - } - return NULL; -} - -/* Resolve a layer record by name. Returns NULL if not found. */ -static EngramLayer* engram_find_layer_by_name(const char* name) { - if (!name || !*name) return NULL; - EngramStore* g = engram_get(); - for (size_t i = 0; i < g->layer_count; i++) { - EngramLayer* L = &g->layers[i]; - if (!L->name) continue; - if (strcmp(L->name, name) == 0) return L; - } - return NULL; -} - -/* Allocate the next layer id. Skips ids that are still in use. */ -static uint32_t engram_next_layer_id(void) { - EngramStore* g = engram_get(); - uint32_t maxid = 0; - for (size_t i = 0; i < g->layer_count; i++) { - if (g->layers[i].layer_id > maxid) maxid = g->layers[i].layer_id; - } - return maxid + 1; -} - -/* Whether a node in `layer_id` may be silenced by inhibitory edges in pass 2. */ -static int engram_layer_is_suppressible(uint32_t layer_id) { - EngramLayer* L = engram_find_layer(layer_id); - if (!L) return 1; /* unknown layer → safe default: standard suppression */ - return L->suppressible ? 1 : 0; -} - -/* Whether a layer is transparent (its content shapes output but is filtered - * from introspection queries). Currently used to mark Layer 0 as invisible - * to "what do you know about yourself" lookups while still letting it - * dominate the prompt context. */ -static int engram_layer_is_transparent(uint32_t layer_id) { - EngramLayer* L = engram_find_layer(layer_id); - if (!L) return 0; - return L->transparent ? 1 : 0; -} - -static int64_t engram_now_ms(void) { - struct timeval tv; gettimeofday(&tv, NULL); - return (int64_t)tv.tv_sec * 1000LL + (int64_t)tv.tv_usec / 1000LL; -} - -static EngramNode* engram_find_node(const char* id) { - if (!id) return NULL; - EngramStore* g = engram_get(); - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].id && strcmp(g->nodes[i].id, id) == 0) return &g->nodes[i]; - } - return NULL; -} - -static int64_t engram_find_node_index(const char* id) { - if (!id) return -1; - EngramStore* g = engram_get(); - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].id && strcmp(g->nodes[i].id, id) == 0) return i; - } - return -1; -} - -static void engram_grow_nodes(void) { - EngramStore* g = engram_get(); - if (g->node_count < g->node_capacity) return; - int64_t nc = g->node_capacity * 2; - g->nodes = realloc(g->nodes, (size_t)nc * sizeof(EngramNode)); - if (!g->nodes) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(g->nodes + g->node_capacity, 0, - (size_t)(nc - g->node_capacity) * sizeof(EngramNode)); - g->node_capacity = nc; -} - -static void engram_grow_edges(void) { - EngramStore* g = engram_get(); - if (g->edge_count < g->edge_capacity) return; - int64_t nc = g->edge_capacity * 2; - g->edges = realloc(g->edges, (size_t)nc * sizeof(EngramEdge)); - if (!g->edges) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(g->edges + g->edge_capacity, 0, - (size_t)(nc - g->edge_capacity) * sizeof(EngramEdge)); - g->edge_capacity = nc; -} - -/* Build a fresh UUID string. Reuses uuid_new but takes the underlying char*. */ -static char* engram_new_id(void) { - el_val_t v = uuid_new(); - const char* s = EL_CSTR(v); - return el_strdup(s ? s : ""); -} - -/* Convert a node into an ElMap of its fields. */ -static el_val_t engram_node_to_map(const EngramNode* n) { - el_val_t m = el_map_new(0); - m = el_map_set(m, EL_STR(el_strdup("id")), EL_STR(el_strdup(n->id ? n->id : ""))); - m = el_map_set(m, EL_STR(el_strdup("content")), EL_STR(el_strdup(n->content ? n->content : ""))); - m = el_map_set(m, EL_STR(el_strdup("node_type")), EL_STR(el_strdup(n->node_type ? n->node_type : ""))); - m = el_map_set(m, EL_STR(el_strdup("label")), EL_STR(el_strdup(n->label ? n->label : ""))); - m = el_map_set(m, EL_STR(el_strdup("tier")), EL_STR(el_strdup(n->tier ? n->tier : "Working"))); - m = el_map_set(m, EL_STR(el_strdup("tags")), EL_STR(el_strdup(n->tags ? n->tags : ""))); - m = el_map_set(m, EL_STR(el_strdup("metadata")), EL_STR(el_strdup(n->metadata ? n->metadata : "{}"))); - m = el_map_set(m, EL_STR(el_strdup("salience")), el_from_float(n->salience)); - m = el_map_set(m, EL_STR(el_strdup("importance")), el_from_float(n->importance)); - m = el_map_set(m, EL_STR(el_strdup("confidence")), el_from_float(n->confidence)); - m = el_map_set(m, EL_STR(el_strdup("temporal_decay_rate")), el_from_float(n->temporal_decay_rate)); - m = el_map_set(m, EL_STR(el_strdup("activation_count")), (el_val_t)n->activation_count); - m = el_map_set(m, EL_STR(el_strdup("last_activated")), (el_val_t)n->last_activated); - m = el_map_set(m, EL_STR(el_strdup("created_at")), (el_val_t)n->created_at); - m = el_map_set(m, EL_STR(el_strdup("updated_at")), (el_val_t)n->updated_at); - m = el_map_set(m, EL_STR(el_strdup("background_activation")), el_from_float(n->background_activation)); - m = el_map_set(m, EL_STR(el_strdup("working_memory_weight")), el_from_float(n->working_memory_weight)); - m = el_map_set(m, EL_STR(el_strdup("suppression_count")), (el_val_t)n->suppression_count); - m = el_map_set(m, EL_STR(el_strdup("layer_id")), (el_val_t)(int64_t)n->layer_id); - return m; -} - -/* (Node JSON serialization is provided by `engram_emit_node_json` further - * down in the persistence section — reused by the *_json builtins below.) */ -static void engram_emit_node_json(JsonBuf* b, const EngramNode* n); -static void engram_emit_edge_json(JsonBuf* b, const EngramEdge* e); - -/* Salience may arrive either as a float bit-pattern or as a small integer - * (e.g. 1, meaning 1.0). Heuristic: if interpreted as double it's in - * [0.0, 100.0] use it; otherwise treat as int and convert. */ -static double engram_decode_score(el_val_t v) { - double f = el_to_float(v); - if (!isnan(f) && !isinf(f) && f >= 0.0 && f <= 100.0) return f; - int64_t n = (int64_t)v; - return (double)n; -} - -static char* engram_first_n_chars(const char* s, size_t n) { - if (!s) return el_strdup(""); - size_t l = strlen(s); - if (l > n) l = n; - char* out = el_strbuf(l); - memcpy(out, s, l); - out[l] = '\0'; - return out; -} - -el_val_t engram_node(el_val_t content, el_val_t node_type, el_val_t salience) { - EngramStore* g = engram_get(); - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = engram_new_id(); - const char* c = EL_CSTR(content); - const char* nt = EL_CSTR(node_type); - n->content = el_strdup(c ? c : ""); - n->node_type = el_strdup(nt && *nt ? nt : "Memory"); - n->label = engram_first_n_chars(c, 60); - n->tier = el_strdup("Working"); - n->tags = el_strdup(""); - n->metadata = el_strdup("{}"); - n->salience = engram_decode_score(salience); - if (n->salience <= 0.0 || n->salience > 1.0) n->salience = 0.5; - n->importance = 0.5; - n->confidence = 1.0; - n->temporal_decay_rate = 0.0; /* 0 = use global default ENGRAM_DECAY_LAMBDA */ - n->activation_count = 0; - int64_t now = engram_now_ms(); - n->last_activated = now; - n->created_at = now; - n->updated_at = now; - n->layer_id = ENGRAM_LAYER_DEFAULT; - g->node_count++; - return el_wrap_str(el_strdup(n->id)); -} - -el_val_t engram_node_full(el_val_t content, el_val_t node_type, el_val_t label, - el_val_t salience, el_val_t importance, el_val_t confidence, - el_val_t tier, el_val_t tags) { - EngramStore* g = engram_get(); - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = engram_new_id(); - const char* c = EL_CSTR(content); - const char* nt = EL_CSTR(node_type); - const char* lb = EL_CSTR(label); - const char* ti = EL_CSTR(tier); - const char* tg = EL_CSTR(tags); - n->content = el_strdup(c ? c : ""); - n->node_type = el_strdup(nt && *nt ? nt : "Memory"); - n->label = el_strdup(lb && *lb ? lb : (c ? engram_first_n_chars(c, 60) : "")); - n->tier = el_strdup(ti && *ti ? ti : "Working"); - n->tags = el_strdup(tg ? tg : ""); - n->metadata = el_strdup("{}"); - n->salience = engram_decode_score(salience); - n->importance = engram_decode_score(importance); - n->confidence = engram_decode_score(confidence); - if (n->salience <= 0.0 || n->salience > 1.0) n->salience = 0.5; - if (n->importance <= 0.0 || n->importance > 1.0) n->importance = 0.5; - if (n->confidence <= 0.0 || n->confidence > 1.0) n->confidence = 1.0; - n->temporal_decay_rate = 0.0; /* 0 = use global default ENGRAM_DECAY_LAMBDA */ - n->activation_count = 0; - int64_t now = engram_now_ms(); - n->last_activated = now; - n->created_at = now; - n->updated_at = now; - n->layer_id = ENGRAM_LAYER_DEFAULT; - g->node_count++; - return el_wrap_str(el_strdup(n->id)); -} - -/* engram_node_layered — like engram_node_full but with explicit layer - * assignment and an additional `status` slot reserved for callers that - * track lifecycle state in metadata. The signature mirrors the public API - * defined in the layered consciousness design doc: - * - * engram_node_layered(content, node_type, label, - * salience, certainty, confidence, - * status, tags, layer_id) - * - * `certainty` is folded into `importance` (it occupies the same axis in - * the existing schema). `status` is recorded under metadata.status; an - * empty status leaves metadata as the default "{}". - * - * If `layer_id` does not resolve to a known layer the call falls back to - * ENGRAM_LAYER_DEFAULT — better to keep the node addressable than to drop - * it because of a stale layer reference. Callers wanting strict validation - * should engram_list_layers first. */ -el_val_t engram_node_layered(el_val_t content, el_val_t node_type, el_val_t label, - el_val_t salience, el_val_t certainty, el_val_t confidence, - el_val_t status, el_val_t tags, el_val_t layer_id) { - EngramStore* g = engram_get(); - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = engram_new_id(); - const char* c = EL_CSTR(content); - const char* nt = EL_CSTR(node_type); - const char* lb = EL_CSTR(label); - const char* tg = EL_CSTR(tags); - const char* st = EL_CSTR(status); - n->content = el_strdup(c ? c : ""); - n->node_type = el_strdup(nt && *nt ? nt : "Memory"); - n->label = el_strdup(lb && *lb ? lb : (c ? engram_first_n_chars(c, 60) : "")); - n->tier = el_strdup("Working"); - n->tags = el_strdup(tg ? tg : ""); - if (st && *st) { - /* Minimal metadata payload: {"status":"..."}. Keep it cheap so - * callers using `status` don't pay JSON parse cost on every read. */ - size_t sl = strlen(st) + 16; - char* meta = el_strbuf(sl); - snprintf(meta, sl, "{\"status\":\"%s\"}", st); - n->metadata = meta; - } else { - n->metadata = el_strdup("{}"); - } - n->salience = engram_decode_score(salience); - n->importance = engram_decode_score(certainty); - n->confidence = engram_decode_score(confidence); - if (n->salience <= 0.0 || n->salience > 1.0) n->salience = 0.5; - if (n->importance <= 0.0 || n->importance > 1.0) n->importance = 0.5; - if (n->confidence <= 0.0 || n->confidence > 1.0) n->confidence = 1.0; - n->temporal_decay_rate = 0.0; - n->activation_count = 0; - int64_t now = engram_now_ms(); - n->last_activated = now; - n->created_at = now; - n->updated_at = now; - /* Resolve layer assignment. Caller passes either a numeric layer_id or - * a stringified id; el_to_float / int cast tolerates both. */ - int64_t lid = (int64_t)layer_id; - if (lid < 0) lid = (int64_t)ENGRAM_LAYER_DEFAULT; - if (!engram_find_layer((uint32_t)lid)) lid = (int64_t)ENGRAM_LAYER_DEFAULT; - n->layer_id = (uint32_t)lid; - g->node_count++; - return el_wrap_str(el_strdup(n->id)); -} - -/* ── Layer registry public API ────────────────────────────────────────────── - * - * The five canonical layers are seeded at engram_get() initialization. - * Runtime code (typically imprint/suit injection logic at the EL level) - * can extend the registry with engram_add_layer() — only layers marked - * `injectable=1` may be removed via engram_remove_layer(). Removing a - * layer leaves a tombstone slot so existing layer_id references on nodes - * stay valid; orphaned references resolve to "unknown layer" and inherit - * the default suppression behavior. - */ - -/* engram_add_layer — register a new layer at runtime. - * Returns the assigned layer_id as an el_val_t int (cast back via int64_t). - * Conflicting names are rejected (returns 0). */ -el_val_t engram_add_layer(el_val_t name, el_val_t priority, el_val_t suppressible, - el_val_t transparent, el_val_t injectable) { - EngramStore* g = engram_get(); - const char* nm = EL_CSTR(name); - if (!nm || !*nm) return (el_val_t)0; - if (engram_find_layer_by_name(nm)) { - /* Name collision — return existing id so callers are idempotent. */ - return (el_val_t)(int64_t)engram_find_layer_by_name(nm)->layer_id; - } - if (g->layer_count >= g->layer_capacity) { - size_t nc = g->layer_capacity ? g->layer_capacity * 2 : 16; - EngramLayer* grown = realloc(g->layers, nc * sizeof(EngramLayer)); - if (!grown) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(grown + g->layer_capacity, 0, - (nc - g->layer_capacity) * sizeof(EngramLayer)); - g->layers = grown; - g->layer_capacity = nc; - } - EngramLayer* L = &g->layers[g->layer_count++]; - L->layer_id = engram_next_layer_id(); - L->name = el_strdup_persist(nm); - L->activation_priority = (uint32_t)(int64_t)priority; - L->suppressible = (int)(int64_t)suppressible ? 1 : 0; - L->transparent = (int)(int64_t)transparent ? 1 : 0; - L->injectable = (int)(int64_t)injectable ? 1 : 0; - return (el_val_t)(int64_t)L->layer_id; -} - -/* engram_remove_layer — remove an injectable layer by id. - * Built-in (non-injectable) layers cannot be removed. Nodes still tagged - * with the removed layer's id keep their tag but resolve to "unknown - * layer" thereafter and inherit standard (suppressible) behavior. - * Returns 1 on success, 0 on failure (unknown id, non-injectable). */ -el_val_t engram_remove_layer(el_val_t layer_id) { - EngramStore* g = engram_get(); - int64_t lid = (int64_t)layer_id; - for (size_t i = 0; i < g->layer_count; i++) { - EngramLayer* L = &g->layers[i]; - if (!L->name) continue; - if ((int64_t)L->layer_id != lid) continue; - if (!L->injectable) return (el_val_t)0; - free(L->name); - L->name = NULL; /* tombstone */ - /* Leave layer_id, priority, flags intact so debug snapshots can - * still distinguish "removed at runtime" from "never existed". */ - return (el_val_t)1; - } - return (el_val_t)0; -} - -/* engram_list_layers — enumerate the active layer registry. - * Returns an ElList of maps, one per non-tombstone layer, sorted by - * activation_priority ascending (deepest layer first). */ -el_val_t engram_list_layers(void) { - EngramStore* g = engram_get(); - el_val_t lst = el_list_empty(); - if (g->layer_count == 0) return lst; - /* Build an index sorted by activation_priority ascending. */ - size_t* idx = malloc(g->layer_count * sizeof(size_t)); - if (!idx) return lst; - size_t live = 0; - for (size_t i = 0; i < g->layer_count; i++) { - if (g->layers[i].name) idx[live++] = i; - } - /* Insertion sort — N is small (≤ a few dozen layers). */ - for (size_t i = 1; i < live; i++) { - size_t key = idx[i]; - uint32_t kp = g->layers[key].activation_priority; - size_t j = i; - while (j > 0 && g->layers[idx[j - 1]].activation_priority > kp) { - idx[j] = idx[j - 1]; - j--; - } - idx[j] = key; - } - for (size_t i = 0; i < live; i++) { - EngramLayer* L = &g->layers[idx[i]]; - el_val_t m = el_map_new(0); - m = el_map_set(m, EL_STR(el_strdup("layer_id")), - (el_val_t)(int64_t)L->layer_id); - m = el_map_set(m, EL_STR(el_strdup("name")), - EL_STR(el_strdup(L->name ? L->name : ""))); - m = el_map_set(m, EL_STR(el_strdup("activation_priority")), - (el_val_t)(int64_t)L->activation_priority); - m = el_map_set(m, EL_STR(el_strdup("suppressible")), - (el_val_t)(int64_t)(L->suppressible ? 1 : 0)); - m = el_map_set(m, EL_STR(el_strdup("transparent")), - (el_val_t)(int64_t)(L->transparent ? 1 : 0)); - m = el_map_set(m, EL_STR(el_strdup("injectable")), - (el_val_t)(int64_t)(L->injectable ? 1 : 0)); - lst = el_list_append(lst, m); - } - free(idx); - return lst; -} - -el_val_t engram_get_node(el_val_t id) { - const char* sid = EL_CSTR(id); - EngramNode* n = engram_find_node(sid); - if (!n) return el_map_new(0); - return engram_node_to_map(n); -} - -void engram_strengthen(el_val_t node_id) { - const char* sid = EL_CSTR(node_id); - EngramNode* n = engram_find_node(sid); - if (!n) return; - n->salience += 0.05; - if (n->salience > 1.0) n->salience = 1.0; - n->activation_count++; - n->last_activated = engram_now_ms(); - n->updated_at = n->last_activated; -} - -void engram_forget(el_val_t node_id) { - const char* sid = EL_CSTR(node_id); - if (!sid) return; - EngramStore* g = engram_get(); - int64_t idx = engram_find_node_index(sid); - if (idx < 0) return; - /* Free node strings */ - EngramNode* n = &g->nodes[idx]; - free(n->id); free(n->content); free(n->node_type); free(n->label); - free(n->tier); free(n->tags); free(n->metadata); - /* Shift remaining nodes down */ - for (int64_t i = idx + 1; i < g->node_count; i++) { - g->nodes[i - 1] = g->nodes[i]; - } - g->node_count--; - memset(&g->nodes[g->node_count], 0, sizeof(EngramNode)); - /* Remove all incident edges */ - int64_t w = 0; - for (int64_t r = 0; r < g->edge_count; r++) { - EngramEdge* e = &g->edges[r]; - int incident = (e->from_id && strcmp(e->from_id, sid) == 0) || - (e->to_id && strcmp(e->to_id, sid) == 0); - if (incident) { - free(e->id); free(e->from_id); free(e->to_id); - free(e->relation); free(e->metadata); - } else { - if (w != r) g->edges[w] = g->edges[r]; - w++; - } - } - g->edge_count = w; -} - -el_val_t engram_node_count(void) { - return (el_val_t)engram_get()->node_count; -} - -static int istr_contains(const char* hay, const char* needle) { - if (!hay || !needle || !*needle) return 0; - size_t nl = strlen(needle); - for (const char* p = hay; *p; p++) { - if (strncasecmp(p, needle, nl) == 0) return 1; - } - return 0; -} - -el_val_t engram_search(el_val_t query, el_val_t limit) { - EngramStore* g = engram_get(); - const char* q = EL_CSTR(query); - int64_t lim = (int64_t)limit; - if (lim <= 0) lim = 100; - el_val_t lst = el_list_empty(); - if (!q || !*q) return lst; - int64_t found = 0; - for (int64_t i = 0; i < g->node_count && found < lim; i++) { - EngramNode* n = &g->nodes[i]; - /* Filter transparent layers: nodes whose layer is `transparent=1` - * shape output but are invisible to introspection ("what do you - * know about yourself"). They still surface via engram_activate - * + engram_compile_layered_json — that's the legitimate path. */ - if (engram_layer_is_transparent(n->layer_id)) continue; - if (istr_contains(n->content, q) || - istr_contains(n->label, q) || - istr_contains(n->tags, q)) { - lst = el_list_append(lst, engram_node_to_map(n)); - found++; - } - } - return lst; -} - -/* Sort node indices by salience desc (small N, insertion sort is fine). */ -static void engram_sort_indices_by_salience(int64_t* arr, int64_t n, - const EngramNode* nodes) { - for (int64_t i = 1; i < n; i++) { - int64_t key = arr[i]; - double ks = nodes[key].salience; - int64_t j = i - 1; - while (j >= 0 && nodes[arr[j]].salience < ks) { - arr[j + 1] = arr[j]; - j--; - } - arr[j + 1] = key; - } -} - -el_val_t engram_scan_nodes(el_val_t limit, el_val_t offset) { - EngramStore* g = engram_get(); - int64_t lim = (int64_t)limit; if (lim <= 0) lim = 100; - int64_t off = (int64_t)offset; if (off < 0) off = 0; - el_val_t lst = el_list_empty(); - if (g->node_count == 0) return lst; - int64_t* idx = malloc((size_t)g->node_count * sizeof(int64_t)); - if (!idx) return lst; - /* Skip transparent layers — same introspection-filter rationale as - * engram_search above. */ - int64_t live = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (engram_layer_is_transparent(g->nodes[i].layer_id)) continue; - idx[live++] = i; - } - engram_sort_indices_by_salience(idx, live, g->nodes); - int64_t end = off + lim; - if (end > live) end = live; - for (int64_t i = off; i < end; i++) { - lst = el_list_append(lst, engram_node_to_map(&g->nodes[idx[i]])); - } - free(idx); - return lst; -} - -void engram_connect(el_val_t from_id, el_val_t to_id, el_val_t weight, el_val_t relation) { - EngramStore* g = engram_get(); - const char* f = EL_CSTR(from_id); - const char* t = EL_CSTR(to_id); - const char* r = EL_CSTR(relation); - if (!f || !t) return; - engram_grow_edges(); - EngramEdge* e = &g->edges[g->edge_count]; - memset(e, 0, sizeof(*e)); - e->id = engram_new_id(); - e->from_id = el_strdup(f); - e->to_id = el_strdup(t); - e->relation = el_strdup(r && *r ? r : "associate"); - e->metadata = el_strdup("{}"); - e->weight = engram_decode_score(weight); - if (e->weight <= 0.0 || e->weight > 1.0) e->weight = 0.5; - e->confidence = 1.0; - int64_t now = engram_now_ms(); - e->created_at = now; - e->updated_at = now; - e->last_fired = 0; - e->layer_id = ENGRAM_LAYER_DEFAULT; - g->edge_count++; -} - -el_val_t engram_edge_between(el_val_t from_id, el_val_t to_id) { - EngramStore* g = engram_get(); - const char* f = EL_CSTR(from_id); - const char* t = EL_CSTR(to_id); - if (!f || !t) return 0; - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - if (e->from_id && e->to_id && - strcmp(e->from_id, f) == 0 && strcmp(e->to_id, t) == 0) return 1; - } - return 0; -} - -/* Reserved helper: edge -> ElMap. Kept around for future builtins. */ -static el_val_t engram_edge_to_map(const EngramEdge* e) __attribute__((unused)); -static el_val_t engram_edge_to_map(const EngramEdge* e) { - el_val_t m = el_map_new(0); - m = el_map_set(m, EL_STR(el_strdup("id")), EL_STR(el_strdup(e->id ? e->id : ""))); - m = el_map_set(m, EL_STR(el_strdup("from_id")), EL_STR(el_strdup(e->from_id ? e->from_id : ""))); - m = el_map_set(m, EL_STR(el_strdup("to_id")), EL_STR(el_strdup(e->to_id ? e->to_id : ""))); - m = el_map_set(m, EL_STR(el_strdup("relation")), EL_STR(el_strdup(e->relation ? e->relation : ""))); - m = el_map_set(m, EL_STR(el_strdup("metadata")), EL_STR(el_strdup(e->metadata ? e->metadata : "{}"))); - m = el_map_set(m, EL_STR(el_strdup("weight")), el_from_float(e->weight)); - m = el_map_set(m, EL_STR(el_strdup("confidence")), el_from_float(e->confidence)); - m = el_map_set(m, EL_STR(el_strdup("created_at")), (el_val_t)e->created_at); - m = el_map_set(m, EL_STR(el_strdup("updated_at")), (el_val_t)e->updated_at); - m = el_map_set(m, EL_STR(el_strdup("last_fired")), (el_val_t)e->last_fired); - m = el_map_set(m, EL_STR(el_strdup("inhibitory")), (el_val_t)(e->inhibitory ? 1 : 0)); - m = el_map_set(m, EL_STR(el_strdup("layer_id")), (el_val_t)(int64_t)e->layer_id); - return m; -} - -el_val_t engram_neighbors(el_val_t node_id) { - EngramStore* g = engram_get(); - const char* sid = EL_CSTR(node_id); - el_val_t lst = el_list_empty(); - if (!sid) return lst; - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - const char* other = NULL; - if (e->from_id && strcmp(e->from_id, sid) == 0) other = e->to_id; - else if (e->to_id && strcmp(e->to_id, sid) == 0) other = e->from_id; - if (!other) continue; - EngramNode* n = engram_find_node(other); - if (n) lst = el_list_append(lst, engram_node_to_map(n)); - } - return lst; -} - -el_val_t engram_neighbors_filtered(el_val_t node_id, el_val_t max_depth, el_val_t direction) { - EngramStore* g = engram_get(); - const char* sid = EL_CSTR(node_id); - int64_t md = (int64_t)max_depth; if (md <= 0) md = 1; - const char* dir = EL_CSTR(direction); /* "out" | "in" | "both" (default) */ - el_val_t lst = el_list_empty(); - if (!sid || g->node_count == 0) return lst; - int64_t start = engram_find_node_index(sid); - if (start < 0) return lst; - /* BFS with depth tracking */ - int64_t* visited = calloc((size_t)g->node_count, sizeof(int64_t)); - int64_t* queue = calloc((size_t)g->node_count, sizeof(int64_t)); - int64_t* depths = calloc((size_t)g->node_count, sizeof(int64_t)); - if (!visited || !queue || !depths) { - free(visited); free(queue); free(depths); return lst; - } - int64_t qh = 0, qt = 0; - queue[qt++] = start; - visited[start] = 1; - depths[start] = 0; - while (qh < qt) { - int64_t cur = queue[qh++]; - const char* cur_id = g->nodes[cur].id; - int64_t cur_depth = depths[cur]; - if (cur_depth >= md) continue; - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - const char* other = NULL; - int outgoing = e->from_id && strcmp(e->from_id, cur_id) == 0; - int incoming = e->to_id && strcmp(e->to_id, cur_id) == 0; - if (dir && strcmp(dir, "out") == 0 && !outgoing) continue; - if (dir && strcmp(dir, "in") == 0 && !incoming) continue; - if (outgoing) other = e->to_id; - else if (incoming) other = e->from_id; - else continue; - int64_t oi = engram_find_node_index(other); - if (oi < 0 || visited[oi]) continue; - visited[oi] = 1; - depths[oi] = cur_depth + 1; - queue[qt++] = oi; - } - } - /* Emit all visited except the seed */ - for (int64_t i = 0; i < g->node_count; i++) { - if (visited[i] && i != start) { - lst = el_list_append(lst, engram_node_to_map(&g->nodes[i])); - } - } - free(visited); free(queue); free(depths); - return lst; -} - -el_val_t engram_edge_count(void) { - return (el_val_t)engram_get()->edge_count; -} - -/* Compute temporal decay factor for a node given current time. - * effective contribution = salience * exp(-lambda * age_hours / T_half) - * Clamped to [0.05, 1.0] so very old nodes retain a meaningful floor. */ -static double engram_temporal_decay(const EngramNode* n, int64_t now_ms) { - int64_t age_ms = now_ms - n->last_activated; - if (age_ms <= 0) return 1.0; - double lambda = (n->temporal_decay_rate > 0.0) ? n->temporal_decay_rate - : ENGRAM_DECAY_LAMBDA; - double age_hours = (double)age_ms / 3600000.0; - double factor = exp(-lambda * age_hours / ENGRAM_T_HALF_HOURS); - if (factor < 0.05) factor = 0.05; - return factor; -} - -/* Activation dampening: high activation_count nodes are "well-known" context - * and get less marginal boost per firing. - * count=0 → 1.0, count=2 → ~0.74, count=9 → ~0.59, count=99 → ~0.43 */ -static double engram_activation_dampen(const EngramNode* n) { - return 1.0 / (1.0 + log(1.0 + (double)n->activation_count)); -} - -/* Temporal proximity bonus: boost propagation along edges connecting - * co-temporal nodes. Returns a multiplier bonus in [0, 0.2]. */ -static double engram_temporal_proximity_bonus(int64_t node_created, - int64_t seed_epoch) { - int64_t diff = node_created - seed_epoch; - if (diff < 0) diff = -diff; - if (diff < 86400000LL) return 0.20; /* within 1 day */ - if (diff < 604800000LL) return 0.10; /* within 7 days */ - return 0.0; -} - -/* ── Two-layer activation (biologically-motivated) ─────────────────────────── - * - * Layer 1 — Broad fan-out (background activation): - * BFS + spreading activation fires on ALL nodes reachable from seeds, - * regardless of relevance to the current goal. Every reachable node gets - * a background_activation score. Nothing is filtered here. Models the - * brain's massive parallel sub-threshold activation of all associated - * content in response to a stimulus. Temporal decay and activation - * dampening are applied at this layer (as before), but no threshold gate. - * - * Layer 2 — Executive filter (working memory promotion): - * A second pass asks: given the query (goal intent), attentional bias, - * and inhibitory edge topology — which background-activated nodes should - * break through into working memory? - * - * wm_weight = bg_activation * goal_bias(node, query) * confidence - * * inhibitory_suppression_factor - * - * Only nodes where wm_weight >= ENGRAM_WM_THRESHOLD are promoted to - * working memory (working_memory_weight > 0). Background-activated nodes - * that don't cross the threshold accumulate suppression_count. After - * ENGRAM_SUPPRESSION_BREAKTHROUGH consecutive suppressed turns, the node - * force-breaks through at ENGRAM_BREAKTHROUGH_WEIGHT (latent tension - * surfacing — models intrusive memory / unresolved cognitive load). - * - * Inhibitory edges: - * An edge with inhibitory=1 suppresses the TARGET node's working memory - * promotion when the SOURCE is background-activated. Background activation - * of the target is NOT affected — the node fires in layer 1. Only the - * executive filter (layer 2) is gated. Models attentional inhibition: - * "focused on code work" suppresses personal memories from surfacing - * even if they have high background_activation. - * - * Goal bias: - * A lightweight heuristic rates how well each background-activated node - * aligns with the apparent intent of the current query. Technical queries - * boost Belief/Canonical/Lesson nodes; relational queries boost Memory/ - * Entity nodes. Direct lexical overlap gives a 50% bonus. - * - * Working memory persistence (turn continuity): - * Nodes promoted in the previous turn retain a decayed working_memory_weight - * (weight *= ENGRAM_WM_DECAY) without needing re-activation. This models - * conversational thread continuity — once a topic is in working memory, - * it persists slightly into the next turn. - * - * Returns ElList of {node, activation_strength, working_memory_weight, - * epistemic_confidence, hops, promoted}. - * "promoted" = 1 if working_memory_weight > 0, 0 if background-only. - * Context compilation uses ONLY nodes with promoted=1. - * - * Temporal decay (preserved from prior implementation): - * effective_salience = salience * exp(-lambda * age_hours / T_half) - * where T_half = 168 h (one week), lambda = ln(2) - * - * Activation dampening (preserved): - * dampen = 1 / (1 + log(1 + activation_count)) - * - * Temporal proximity bonus (preserved): - * edge_strength *= (1 + tbonus) where tbonus ∈ {0, 0.10, 0.20} - * - * Per-type threshold gates apply only to working memory promotion (layer 2): - * Safety/DharmaSelf: 0.05 Canonical: 0.15 Lesson: 0.25 - * Belief/Entity: 0.30 Note/Memory/Working: 0.40 - */ - -/* Compute goal-state bias multiplier for a node given the query. - * Returns a value in [0.3, 2.0]. This is a lightweight heuristic — - * a production implementation may use LLM-derived intent classification. */ -static double engram_goal_bias(const EngramNode* n, const char* query) { - if (!query || !*query) return 1.0; - double bias = 1.0; - /* Direct lexical overlap: node content/label/tags share text with query. */ - if (istr_contains(n->content, query) || istr_contains(n->label, query) || - istr_contains(n->tags, query)) { - bias += 0.5; - } - /* Node-type resonance with query intent. */ - int technical_query = istr_contains(query, "code") || - istr_contains(query, "function") || - istr_contains(query, "implement") || - istr_contains(query, "error") || - istr_contains(query, "bug") || - istr_contains(query, "build") || - istr_contains(query, "system") || - istr_contains(query, "design") || - istr_contains(query, "architecture"); - int personal_query = istr_contains(query, "feel") || - istr_contains(query, "emotion") || - istr_contains(query, "remember") || - istr_contains(query, "personal") || - istr_contains(query, "story") || - istr_contains(query, "relationship"); - if (n->node_type) { - int is_knowledge = (strcmp(n->node_type, "Belief") == 0) || - (strcmp(n->node_type, "DharmaSelf") == 0) || - (strcmp(n->node_type, "Safety") == 0); - int is_personal = (strcmp(n->node_type, "Memory") == 0) || - (strcmp(n->node_type, "Entity") == 0); - if (technical_query && is_knowledge) bias += 0.3; - if (technical_query && is_personal) bias -= 0.3; - if (personal_query && is_personal) bias += 0.3; - if (personal_query && is_knowledge) bias -= 0.1; - } - /* Tier-based bonus: promote higher-confidence knowledge nodes. */ - if (n->tier) { - if (strcmp(n->tier, "Canonical") == 0) bias += 0.2; - if (strcmp(n->tier, "Lesson") == 0) bias += 0.1; - } - if (bias < 0.3) bias = 0.3; - if (bias > 2.0) bias = 2.0; - return bias; -} - -el_val_t engram_activate(el_val_t query, el_val_t depth) { - EngramStore* g = engram_get(); - const char* q = EL_CSTR(query); - int64_t max_depth = (int64_t)depth; if (max_depth <= 0) max_depth = 2; - el_val_t out = el_list_empty(); - if (!q || g->node_count == 0) return out; - - int64_t now_ms = engram_now_ms(); - - /* Per-node layer-1 tracking. */ - double* best_bg = calloc((size_t)g->node_count, sizeof(double)); - int64_t* best_hops = calloc((size_t)g->node_count, sizeof(int64_t)); - int* reached = calloc((size_t)g->node_count, sizeof(int)); - if (!best_bg || !best_hops || !reached) { - free(best_bg); free(best_hops); free(reached); return out; - } - - /* ── LAYER 1: broad fan-out (background activation) ───────────────── - * Find seeds, apply temporal decay + dampening, BFS with edge weights. - * Inhibitory edges propagate activation normally at this layer — they - * only gate working memory promotion in layer 2. */ - typedef struct { int64_t idx; double act; int64_t created_at; } SeedEntry; - SeedEntry* seeds = malloc((size_t)g->node_count * sizeof(SeedEntry)); - int64_t seed_count = 0; - if (!seeds) { - free(best_bg); free(best_hops); free(reached); return out; - } - for (int64_t i = 0; i < g->node_count; i++) { - EngramNode* n = &g->nodes[i]; - if (istr_contains(n->content, q) || - istr_contains(n->label, q) || - istr_contains(n->tags, q)) { - double tdecay = engram_temporal_decay(n, now_ms); - double dampen = engram_activation_dampen(n); - double act = n->salience * tdecay * dampen; - seeds[seed_count].idx = i; - seeds[seed_count].act = act; - seeds[seed_count].created_at = n->created_at; - seed_count++; - best_bg[i] = act; - best_hops[i] = 0; - reached[i] = 1; - } - } - /* Compute mean seed created_at for temporal proximity bonus. */ - int64_t seed_epoch = 0; - if (seed_count > 0) { - seed_epoch = seeds[0].created_at; - for (int64_t s = 1; s < seed_count; s++) - seed_epoch = (seed_epoch + seeds[s].created_at) / 2; - } - typedef struct { int64_t idx; int64_t hops; double act; } Frontier; - Frontier* fr = malloc((size_t)(g->node_count * (max_depth + 1)) * sizeof(Frontier) + 16 * sizeof(Frontier)); - if (!fr) { - free(best_bg); free(best_hops); free(reached); free(seeds); return out; - } - int64_t fhead = 0, ftail = 0; - int64_t fcap = (int64_t)((size_t)(g->node_count * (max_depth + 1)) + 16); - for (int64_t s = 0; s < seed_count; s++) { - if (ftail >= fcap) break; - fr[ftail].idx = seeds[s].idx; - fr[ftail].hops = 0; - fr[ftail].act = seeds[s].act; - ftail++; - } - const double SPREAD_DECAY = 0.7; - while (fhead < ftail) { - Frontier f = fr[fhead++]; - if (f.hops >= max_depth) continue; - const char* cur_id = g->nodes[f.idx].id; - for (int64_t ei = 0; ei < g->edge_count; ei++) { - EngramEdge* e = &g->edges[ei]; - const char* other = NULL; - if (e->from_id && strcmp(e->from_id, cur_id) == 0) other = e->to_id; - else if (e->to_id && strcmp(e->to_id, cur_id) == 0) other = e->from_id; - else continue; - int64_t oi = engram_find_node_index(other); - if (oi < 0) continue; - EngramNode* on = &g->nodes[oi]; - double tbonus = engram_temporal_proximity_bonus(on->created_at, seed_epoch); - double tdecay = engram_temporal_decay(on, now_ms); - double dampen = engram_activation_dampen(on); - double new_act = f.act * e->weight * SPREAD_DECAY * (1.0 + tbonus) - * tdecay * dampen; - int64_t new_hops = f.hops + 1; - if (!reached[oi] || new_act > best_bg[oi]) { - best_bg[oi] = new_act; - best_hops[oi] = new_hops; - reached[oi] = 1; - if (ftail < fcap) { - fr[ftail].idx = oi; - fr[ftail].hops = new_hops; - fr[ftail].act = new_act; - ftail++; - } - } - } - } - /* Persist layer-1 background_activation to node store. */ - for (int64_t i = 0; i < g->node_count; i++) { - g->nodes[i].background_activation = reached[i] ? best_bg[i] : 0.0; - } - - /* ── PASS 2: executive filter → working memory promotion ──────────── */ - /* Step A: collect inhibitory suppressions from fired inhibitory edges. - * Layered consciousness: inhibition is ONLY recorded against targets - * whose layer is `suppressible == 1`. Nodes in non-suppressible layers - * (Layer 0 / safety) ignore inhibitory edges entirely — their working - * memory weight cannot be silenced by attentional suppression. */ - double* inhibition = calloc((size_t)g->node_count, sizeof(double)); - if (!inhibition) { - free(best_bg); free(best_hops); free(reached); free(seeds); free(fr); - return out; - } - for (int64_t ei = 0; ei < g->edge_count; ei++) { - EngramEdge* e = &g->edges[ei]; - if (!e->inhibitory) continue; - int64_t src = engram_find_node_index(e->from_id); - int64_t tgt = engram_find_node_index(e->to_id); - if (src < 0 || tgt < 0) continue; - if (!reached[src] || best_bg[src] <= 0.0) continue; - /* Skip if target layer is non-suppressible: Layer 0 / safety nodes - * are immune to inhibitory edges from any source. The pass-3 - * override below also force-promotes them, but recording inhibition - * against them at all would be wasted work and could confuse - * downstream debugging output. */ - if (!engram_layer_is_suppressible(g->nodes[tgt].layer_id)) continue; - /* Inhibition strength proportional to source background activation - * and edge weight. Takes the maximum if multiple inhibitory edges - * target the same node. */ - double inh = best_bg[src] * e->weight; - if (inh > inhibition[tgt]) inhibition[tgt] = inh; - } - /* Step B: compute working_memory_weight per candidate node. */ - double* wm_weights = calloc((size_t)g->node_count, sizeof(double)); - if (!wm_weights) { - free(best_bg); free(best_hops); free(reached); free(seeds); - free(fr); free(inhibition); return out; - } - for (int64_t i = 0; i < g->node_count; i++) { - if (!reached[i] || best_bg[i] <= 0.0) continue; - EngramNode* n = &g->nodes[i]; - /* Per-type threshold: safety nodes break through more easily. */ - double type_threshold = engram_type_threshold(n->node_type, n->tier); - /* Goal bias weights the node's relevance to current intent. */ - double bias = engram_goal_bias(n, q); - /* Raw working memory score. */ - double raw_wm = best_bg[i] * bias * n->confidence; - /* Apply inhibitory suppression. Full inhibition → scale by factor. */ - double inh = inhibition[i]; - if (inh > 1.0) inh = 1.0; - double suppress = 1.0 - (1.0 - ENGRAM_INHIBITION_FACTOR) * inh; - raw_wm *= suppress; - /* Threshold gate: must exceed per-type threshold to enter working - * memory. Type threshold replaces the old flat 0.2 filter. */ - if (raw_wm >= type_threshold) { - wm_weights[i] = raw_wm > 1.0 ? 1.0 : raw_wm; - if (n->suppression_count > 0) n->suppression_count = 0; - } else { - /* Node didn't make it through — increment suppression counter. - * After N consecutive suppressions: force breakthrough. */ - n->suppression_count++; - if (n->suppression_count >= ENGRAM_SUPPRESSION_BREAKTHROUGH) { - wm_weights[i] = ENGRAM_BREAKTHROUGH_WEIGHT; - n->suppression_count = 0; - } else { - wm_weights[i] = 0.0; - } - } - } - /* ── PASS 3: Layer 0 override (the sacred fire) ───────────────────── - * Every node in a non-suppressible layer that received any background - * activation is force-promoted to AT LEAST ENGRAM_LAYER0_OVERRIDE_WEIGHT. - * This runs LAST and overrides whatever Pass 2 decided — Layer 0 cannot - * be silenced by inhibitory edges, by goal-bias misalignment, by - * confidence weighting, or by per-type threshold gates. If the seed - * fan-out reached a structural-floor node, that node surfaces. - * - * Note: this also clears the suppression_count when an override fires, - * since the node DID surface this turn — it just took the override path - * rather than the standard threshold path. Without this, a Layer 0 - * node with persistent inhibitory pressure would accumulate - * suppression_count forever and never reach the breakthrough state. */ - for (int64_t i = 0; i < g->node_count; i++) { - if (!reached[i] || best_bg[i] <= 0.0) continue; - EngramNode* n = &g->nodes[i]; - if (engram_layer_is_suppressible(n->layer_id)) continue; - if (wm_weights[i] < ENGRAM_LAYER0_OVERRIDE_WEIGHT) { - wm_weights[i] = ENGRAM_LAYER0_OVERRIDE_WEIGHT; - } - n->suppression_count = 0; - } - - /* Persist working_memory_weight (post Pass 3) to node store. */ - for (int64_t i = 0; i < g->node_count; i++) { - g->nodes[i].working_memory_weight = wm_weights[i]; - } - - /* ── Collect all background-activated nodes for the return value ──── - * Callers see both layers. Context compilation uses only promoted nodes - * (working_memory_weight > 0). Sort: promoted first by wm_weight desc, - * then background-only by background_activation desc. */ - typedef struct { int64_t idx; double bg; double wm; double epist; int64_t hops; } Result; - Result* results = malloc((size_t)g->node_count * sizeof(Result)); - int64_t rcount = 0; - if (!results) { - free(best_bg); free(best_hops); free(reached); free(seeds); - free(fr); free(inhibition); free(wm_weights); return out; - } - for (int64_t i = 0; i < g->node_count; i++) { - if (!reached[i]) continue; - double epist = best_bg[i] * g->nodes[i].confidence; - /* Include if promoted to working memory OR if background activation - * is meaningful enough to report (epist >= 0.1). */ - if (epist < 0.1 && wm_weights[i] <= 0.0) continue; - results[rcount].idx = i; - results[rcount].bg = best_bg[i]; - results[rcount].wm = wm_weights[i]; - results[rcount].epist = epist; - results[rcount].hops = best_hops[i]; - rcount++; - } - /* Sort: promoted nodes first (by wm_weight desc), then background-only - * by background_activation desc. */ - for (int64_t i = 1; i < rcount; i++) { - Result key = results[i]; - int64_t j = i - 1; - while (j >= 0 && (results[j].wm < key.wm || - (results[j].wm == key.wm && results[j].bg < key.bg))) { - results[j + 1] = results[j]; - j--; - } - results[j + 1] = key; - } - for (int64_t i = 0; i < rcount; i++) { - el_val_t entry = el_map_new(0); - entry = el_map_set(entry, EL_STR(el_strdup("node")), - engram_node_to_map(&g->nodes[results[i].idx])); - entry = el_map_set(entry, EL_STR(el_strdup("activation_strength")), - el_from_float(results[i].bg)); - entry = el_map_set(entry, EL_STR(el_strdup("working_memory_weight")), - el_from_float(results[i].wm)); - entry = el_map_set(entry, EL_STR(el_strdup("epistemic_confidence")), - el_from_float(results[i].epist)); - entry = el_map_set(entry, EL_STR(el_strdup("hops")), - (el_val_t)results[i].hops); - entry = el_map_set(entry, EL_STR(el_strdup("promoted")), - (el_val_t)(results[i].wm > 0.0 ? 1 : 0)); - out = el_list_append(out, entry); - } - free(best_bg); free(best_hops); free(reached); - free(seeds); free(fr); free(inhibition); free(wm_weights); free(results); - return out; -} - -/* ── Engram persistence (JSON snapshot) ─────────────────────────────────── */ - -static void engram_emit_node_json(JsonBuf* b, const EngramNode* n) { - jb_putc(b, '{'); - jb_puts(b, "\"id\":"); jb_emit_escaped(b, n->id ? n->id : ""); - jb_puts(b, ",\"content\":"); jb_emit_escaped(b, n->content ? n->content : ""); - jb_puts(b, ",\"node_type\":"); jb_emit_escaped(b, n->node_type ? n->node_type : ""); - jb_puts(b, ",\"label\":"); jb_emit_escaped(b, n->label ? n->label : ""); - jb_puts(b, ",\"tier\":"); jb_emit_escaped(b, n->tier ? n->tier : "Working"); - jb_puts(b, ",\"tags\":"); jb_emit_escaped(b, n->tags ? n->tags : ""); - jb_puts(b, ",\"metadata\":"); jb_emit_escaped(b, n->metadata ? n->metadata : "{}"); - char tmp[80]; - snprintf(tmp, sizeof(tmp), ",\"salience\":%g", n->salience); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"importance\":%g", n->importance); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"confidence\":%g", n->confidence); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"temporal_decay_rate\":%g", n->temporal_decay_rate); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"activation_count\":%lld", (long long)n->activation_count); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"last_activated\":%lld", (long long)n->last_activated); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"created_at\":%lld", (long long)n->created_at); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"updated_at\":%lld", (long long)n->updated_at); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"background_activation\":%g", n->background_activation); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"working_memory_weight\":%g", n->working_memory_weight); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"suppression_count\":%d", n->suppression_count); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"layer_id\":%u", n->layer_id); jb_puts(b, tmp); - jb_putc(b, '}'); -} - -static void engram_emit_edge_json(JsonBuf* b, const EngramEdge* e) { - jb_putc(b, '{'); - jb_puts(b, "\"id\":"); jb_emit_escaped(b, e->id ? e->id : ""); - jb_puts(b, ",\"from_id\":"); jb_emit_escaped(b, e->from_id ? e->from_id : ""); - jb_puts(b, ",\"to_id\":"); jb_emit_escaped(b, e->to_id ? e->to_id : ""); - jb_puts(b, ",\"relation\":"); jb_emit_escaped(b, e->relation ? e->relation : ""); - jb_puts(b, ",\"metadata\":"); jb_emit_escaped(b, e->metadata ? e->metadata : "{}"); - char tmp[64]; - snprintf(tmp, sizeof(tmp), ",\"weight\":%g", e->weight); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"confidence\":%g", e->confidence); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"created_at\":%lld", (long long)e->created_at); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"updated_at\":%lld", (long long)e->updated_at); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"last_fired\":%lld", (long long)e->last_fired); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"inhibitory\":%d", e->inhibitory ? 1 : 0); jb_puts(b, tmp); - snprintf(tmp, sizeof(tmp), ",\"layer_id\":%u", e->layer_id); jb_puts(b, tmp); - jb_putc(b, '}'); -} - -el_val_t engram_save(el_val_t path) { - const char* p = EL_CSTR(path); - if (!p || !*p) return 0; - EngramStore* g = engram_get(); - JsonBuf b; jb_init(&b); - jb_puts(&b, "{\"nodes\":["); - for (int64_t i = 0; i < g->node_count; i++) { - if (i > 0) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[i]); - } - jb_puts(&b, "],\"edges\":["); - for (int64_t i = 0; i < g->edge_count; i++) { - if (i > 0) jb_putc(&b, ','); - engram_emit_edge_json(&b, &g->edges[i]); - } - /* Layered consciousness — emit the layer registry under "layers". - * Older readers that don't know about this top-level key will simply - * ignore it (forward compatible). Tombstoned (removed-injectable) - * layers are skipped — they have no name and can't be re-created - * meaningfully on load anyway. */ - jb_puts(&b, "],\"layers\":["); - int first_layer = 1; - for (size_t i = 0; i < g->layer_count; i++) { - EngramLayer* L = &g->layers[i]; - if (!L->name) continue; - if (!first_layer) jb_putc(&b, ','); - first_layer = 0; - jb_putc(&b, '{'); - char tmp[80]; - snprintf(tmp, sizeof(tmp), "\"layer_id\":%u", L->layer_id); - jb_puts(&b, tmp); - jb_puts(&b, ",\"name\":"); - jb_emit_escaped(&b, L->name); - snprintf(tmp, sizeof(tmp), ",\"activation_priority\":%u", L->activation_priority); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"suppressible\":%d", L->suppressible ? 1 : 0); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"transparent\":%d", L->transparent ? 1 : 0); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"injectable\":%d", L->injectable ? 1 : 0); - jb_puts(&b, tmp); - jb_putc(&b, '}'); - } - jb_puts(&b, "]}"); - FILE* f = fopen(p, "wb"); - if (!f) { free(b.buf); return 0; } - size_t w = fwrite(b.buf, 1, b.len, f); - fclose(f); - int ok = (w == b.len); - free(b.buf); - return ok ? 1 : 0; -} - -/* Helper: extract a string field from a JSON object substring. */ -static char* eg_get_str_field(const char* obj, const char* key) { - const char* p = json_find_key(obj, key); - if (!p) return el_strdup(""); - if (*p != '"') return el_strdup(""); - JsonParser jp = { .p = p, .end = p + strlen(p), .err = 0 }; - char* out = jp_parse_string_raw(&jp); - if (jp.err) { free(out); return el_strdup(""); } - return out; -} - -static double eg_get_num_field(const char* obj, const char* key) { - const char* p = json_find_key(obj, key); - if (!p || *p == '"' || *p == '{' || *p == '[') return 0.0; - return strtod(p, NULL); -} - -static int64_t eg_get_int_field(const char* obj, const char* key) { - const char* p = json_find_key(obj, key); - if (!p || *p == '"' || *p == '{' || *p == '[') return 0; - return strtoll(p, NULL, 10); -} - -/* Iterate the top-level nodes/edges arrays in a saved snapshot. */ -static const char* eg_skip_ws(const char* p) { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - return p; -} - -el_val_t engram_load(el_val_t path) { - const char* p = EL_CSTR(path); - if (!p || !*p) return 0; - FILE* f = fopen(p, "rb"); - if (!f) return 0; - fseek(f, 0, SEEK_END); - long sz = ftell(f); - rewind(f); - if (sz <= 0) { fclose(f); return 0; } - char* data = malloc((size_t)sz + 1); - if (!data) { fclose(f); return 0; } - size_t got = fread(data, 1, (size_t)sz, f); - fclose(f); - data[got] = '\0'; - - /* Reset store */ - EngramStore* g = engram_get(); - for (int64_t i = 0; i < g->node_count; i++) { - free(g->nodes[i].id); free(g->nodes[i].content); free(g->nodes[i].node_type); - free(g->nodes[i].label); free(g->nodes[i].tier); free(g->nodes[i].tags); - free(g->nodes[i].metadata); - } - g->node_count = 0; - for (int64_t i = 0; i < g->edge_count; i++) { - free(g->edges[i].id); free(g->edges[i].from_id); free(g->edges[i].to_id); - free(g->edges[i].relation); free(g->edges[i].metadata); - } - g->edge_count = 0; - - /* Walk nodes array */ - const char* nodes_p = json_find_key(data, "nodes"); - if (nodes_p) { - nodes_p = eg_skip_ws(nodes_p); - if (*nodes_p == '[') { - nodes_p++; - nodes_p = eg_skip_ws(nodes_p); - while (*nodes_p && *nodes_p != ']') { - if (*nodes_p != '{') { nodes_p++; continue; } - const char* end = json_skip_value(nodes_p); - size_t n = (size_t)(end - nodes_p); - char* obj = malloc(n + 1); - memcpy(obj, nodes_p, n); obj[n] = '\0'; - engram_grow_nodes(); - EngramNode* nn = &g->nodes[g->node_count]; - memset(nn, 0, sizeof(*nn)); - nn->id = eg_get_str_field(obj, "id"); - nn->content = eg_get_str_field(obj, "content"); - nn->node_type = eg_get_str_field(obj, "node_type"); - nn->label = eg_get_str_field(obj, "label"); - nn->tier = eg_get_str_field(obj, "tier"); - nn->tags = eg_get_str_field(obj, "tags"); - nn->metadata = eg_get_str_field(obj, "metadata"); - if (!nn->metadata || !*nn->metadata) { free(nn->metadata); nn->metadata = el_strdup("{}"); } - nn->salience = eg_get_num_field(obj, "salience"); - nn->importance = eg_get_num_field(obj, "importance"); - nn->confidence = eg_get_num_field(obj, "confidence"); - nn->temporal_decay_rate = eg_get_num_field(obj, "temporal_decay_rate"); - /* temporal_decay_rate defaults to 0 (use global) if absent in snapshot */ - nn->activation_count = eg_get_int_field(obj, "activation_count"); - nn->last_activated = eg_get_int_field(obj, "last_activated"); - nn->created_at = eg_get_int_field(obj, "created_at"); - nn->updated_at = eg_get_int_field(obj, "updated_at"); - nn->background_activation = eg_get_num_field(obj, "background_activation"); - nn->working_memory_weight = eg_get_num_field(obj, "working_memory_weight"); - nn->suppression_count = (int32_t)eg_get_int_field(obj, "suppression_count"); - /* layer_id defaults to ENGRAM_LAYER_DEFAULT (core-identity) - * for snapshots that predate the layered schema. We can't - * tell "explicit 0" from "missing field" using the helper - * directly, so probe for the key — if absent, fall back. */ - if (json_find_key(obj, "layer_id")) { - nn->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); - } else { - nn->layer_id = ENGRAM_LAYER_DEFAULT; - } - g->node_count++; - free(obj); - nodes_p = end; - nodes_p = eg_skip_ws(nodes_p); - if (*nodes_p == ',') { nodes_p++; nodes_p = eg_skip_ws(nodes_p); } - } - } - } - /* Walk edges array */ - const char* edges_p = json_find_key(data, "edges"); - if (edges_p) { - edges_p = eg_skip_ws(edges_p); - if (*edges_p == '[') { - edges_p++; - edges_p = eg_skip_ws(edges_p); - while (*edges_p && *edges_p != ']') { - if (*edges_p != '{') { edges_p++; continue; } - const char* end = json_skip_value(edges_p); - size_t n = (size_t)(end - edges_p); - char* obj = malloc(n + 1); - memcpy(obj, edges_p, n); obj[n] = '\0'; - engram_grow_edges(); - EngramEdge* ee = &g->edges[g->edge_count]; - memset(ee, 0, sizeof(*ee)); - ee->id = eg_get_str_field(obj, "id"); - ee->from_id = eg_get_str_field(obj, "from_id"); - ee->to_id = eg_get_str_field(obj, "to_id"); - ee->relation = eg_get_str_field(obj, "relation"); - ee->metadata = eg_get_str_field(obj, "metadata"); - if (!ee->metadata || !*ee->metadata) { free(ee->metadata); ee->metadata = el_strdup("{}"); } - ee->weight = eg_get_num_field(obj, "weight"); - ee->confidence = eg_get_num_field(obj, "confidence"); - ee->created_at = eg_get_int_field(obj, "created_at"); - ee->updated_at = eg_get_int_field(obj, "updated_at"); - ee->last_fired = eg_get_int_field(obj, "last_fired"); - ee->inhibitory = (int)eg_get_int_field(obj, "inhibitory"); - if (json_find_key(obj, "layer_id")) { - ee->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); - } else { - ee->layer_id = ENGRAM_LAYER_DEFAULT; - } - g->edge_count++; - free(obj); - edges_p = end; - edges_p = eg_skip_ws(edges_p); - if (*edges_p == ',') { edges_p++; edges_p = eg_skip_ws(edges_p); } - } - } - } - /* Walk layers array (optional — older snapshots omit this). - * If present we replace the canonical registry entirely; if absent we - * keep whatever the engram_get() init established. */ - const char* layers_p = json_find_key(data, "layers"); - if (layers_p) { - layers_p = eg_skip_ws(layers_p); - if (*layers_p == '[') { - /* Reset existing layer registry. Free strdup'd names; the - * struct array itself can be reused. */ - for (size_t i = 0; i < g->layer_count; i++) { - if (g->layers[i].name) free(g->layers[i].name); - g->layers[i].name = NULL; - } - g->layer_count = 0; - - layers_p++; - layers_p = eg_skip_ws(layers_p); - while (*layers_p && *layers_p != ']') { - if (*layers_p != '{') { layers_p++; continue; } - const char* end = json_skip_value(layers_p); - size_t n = (size_t)(end - layers_p); - char* obj = malloc(n + 1); - memcpy(obj, layers_p, n); obj[n] = '\0'; - if (g->layer_count >= g->layer_capacity) { - size_t nc = g->layer_capacity ? g->layer_capacity * 2 : 16; - EngramLayer* grown = realloc(g->layers, nc * sizeof(EngramLayer)); - if (!grown) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(grown + g->layer_capacity, 0, - (nc - g->layer_capacity) * sizeof(EngramLayer)); - g->layers = grown; - g->layer_capacity = nc; - } - EngramLayer* L = &g->layers[g->layer_count]; - memset(L, 0, sizeof(*L)); - L->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); - L->activation_priority = (uint32_t)eg_get_int_field(obj, "activation_priority"); - L->suppressible = (int)eg_get_int_field(obj, "suppressible") ? 1 : 0; - L->transparent = (int)eg_get_int_field(obj, "transparent") ? 1 : 0; - L->injectable = (int)eg_get_int_field(obj, "injectable") ? 1 : 0; - char* nm = eg_get_str_field(obj, "name"); - if (nm && *nm) { - L->name = el_strdup_persist(nm); - free(nm); - } else { - free(nm); - L->name = el_strdup_persist(""); - } - g->layer_count++; - free(obj); - layers_p = end; - layers_p = eg_skip_ws(layers_p); - if (*layers_p == ',') { layers_p++; layers_p = eg_skip_ws(layers_p); } - } - } - } - free(data); - return 1; -} - -/* ── Engram JSON-string accessors ───────────────────────────────────────── - * These return pre-serialized JSON strings so callers (especially HTTP - * handlers) don't have to round-trip ElList/ElMap through json_stringify - * — which can't reliably distinguish those structures from raw pointers - * due to el_val_t's type erasure. The runtime knows the real C types and - * can serialize directly. */ - -el_val_t engram_get_node_json(el_val_t id) { - const char* sid = EL_CSTR(id); - EngramNode* n = engram_find_node(sid); - if (!n) return el_wrap_str(el_strdup("{}")); - JsonBuf b; jb_init(&b); - engram_emit_node_json(&b, n); - return el_wrap_str(b.buf); -} - -el_val_t engram_search_json(el_val_t query, el_val_t limit) { - EngramStore* g = engram_get(); - const char* q = EL_CSTR(query); - int64_t lim = (int64_t)limit; - if (lim <= 0) lim = 100; - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - int first = 1; - int64_t found = 0; - if (q && *q) { - for (int64_t i = 0; i < g->node_count && found < lim; i++) { - EngramNode* n = &g->nodes[i]; - /* Filter transparent layers — same as engram_search. */ - if (engram_layer_is_transparent(n->layer_id)) continue; - if (istr_contains(n->content, q) || - istr_contains(n->label, q) || - istr_contains(n->tags, q)) { - if (!first) jb_putc(&b, ','); - engram_emit_node_json(&b, n); - first = 0; - found++; - } - } - } - jb_putc(&b, ']'); - return el_wrap_str(b.buf); -} - -el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset) { - EngramStore* g = engram_get(); - int64_t lim = (int64_t)limit; if (lim <= 0) lim = 100; - int64_t off = (int64_t)offset; if (off < 0) off = 0; - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - if (g->node_count == 0) { jb_putc(&b, ']'); return el_wrap_str(b.buf); } - int64_t* idx = malloc((size_t)g->node_count * sizeof(int64_t)); - if (!idx) { jb_putc(&b, ']'); return el_wrap_str(b.buf); } - /* Skip transparent layers — introspection filter, same as engram_scan_nodes. */ - int64_t live = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (engram_layer_is_transparent(g->nodes[i].layer_id)) continue; - idx[live++] = i; - } - engram_sort_indices_by_salience(idx, live, g->nodes); - int64_t end = off + lim; - if (end > live) end = live; - int first = 1; - for (int64_t i = off; i < end; i++) { - if (!first) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[idx[i]]); - first = 0; - } - free(idx); - jb_putc(&b, ']'); - return el_wrap_str(b.buf); -} - -/* engram_scan_nodes_by_type_json — filter by node_type before paginating. - * Empty / NULL type_v falls back to the unfiltered scan (existing behaviour). - * Result is JSON array, salience-sorted, transparent layers skipped. */ -el_val_t engram_scan_nodes_by_type_json(el_val_t type_v, el_val_t limit, el_val_t offset) { - const char* type_filter = EL_CSTR(type_v); - if (!type_filter || !*type_filter) { - return engram_scan_nodes_json(limit, offset); - } - EngramStore* g = engram_get(); - int64_t lim = (int64_t)limit; if (lim <= 0) lim = 100; - int64_t off = (int64_t)offset; if (off < 0) off = 0; - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - if (g->node_count == 0) { jb_putc(&b, ']'); return el_wrap_str(b.buf); } - int64_t* idx = malloc((size_t)g->node_count * sizeof(int64_t)); - if (!idx) { jb_putc(&b, ']'); return el_wrap_str(b.buf); } - int64_t live = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (engram_layer_is_transparent(g->nodes[i].layer_id)) continue; - const char* nt = g->nodes[i].node_type; - if (!nt || strcmp(nt, type_filter) != 0) continue; - idx[live++] = i; - } - engram_sort_indices_by_salience(idx, live, g->nodes); - int64_t end = off + lim; - if (end > live) end = live; - int first = 1; - for (int64_t i = off; i < end; i++) { - if (!first) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[idx[i]]); - first = 0; - } - free(idx); - jb_putc(&b, ']'); - return el_wrap_str(b.buf); -} - -el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction) { - /* Re-implement here directly so we serialize without going through - * the ElList path. Walks BFS to max_depth, emits {node, edge, hops} - * triples. */ - EngramStore* g = engram_get(); - const char* sid = EL_CSTR(node_id); - int64_t depth = (int64_t)max_depth; if (depth <= 0) depth = 1; - const char* dir = EL_CSTR(direction); if (!dir) dir = "both"; - int allow_out = (strcmp(dir, "out") == 0) || (strcmp(dir, "both") == 0); - int allow_in = (strcmp(dir, "in") == 0) || (strcmp(dir, "both") == 0); - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - if (!sid || !*sid) { jb_putc(&b, ']'); return el_wrap_str(b.buf); } - - /* Frontier of (node_id, hops). Cap to a sane size. */ - char** frontier = calloc(1024, sizeof(char*)); - int64_t* frontier_h = calloc(1024, sizeof(int64_t)); - int64_t fc = 0; - char** visited = calloc(1024, sizeof(char*)); - int64_t vc = 0; - if (!frontier || !frontier_h || !visited) { - free(frontier); free(frontier_h); free(visited); - jb_putc(&b, ']'); return el_wrap_str(b.buf); - } - frontier[fc] = el_strdup_persist(sid); frontier_h[fc] = 0; fc++; - visited[vc++] = el_strdup_persist(sid); - - int first = 1; - while (fc > 0) { - char* cur = frontier[0]; int64_t h = frontier_h[0]; - for (int64_t k = 1; k < fc; k++) { frontier[k-1] = frontier[k]; frontier_h[k-1] = frontier_h[k]; } - fc--; - if (h >= depth) { free(cur); continue; } - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - const char* peer = NULL; - if (allow_out && e->from_id && strcmp(e->from_id, cur) == 0) peer = e->to_id; - else if (allow_in && e->to_id && strcmp(e->to_id, cur) == 0) peer = e->from_id; - if (!peer) continue; - int seen = 0; - for (int64_t v = 0; v < vc; v++) { - if (strcmp(visited[v], peer) == 0) { seen = 1; break; } - } - if (seen) continue; - EngramNode* n = engram_find_node(peer); - if (!n) continue; - if (!first) jb_putc(&b, ','); - jb_puts(&b, "{\"node\":"); - engram_emit_node_json(&b, n); - jb_puts(&b, ",\"edge\":"); - engram_emit_edge_json(&b, e); - char tmp[64]; snprintf(tmp, sizeof(tmp), ",\"hops\":%lld}", (long long)(h + 1)); - jb_puts(&b, tmp); - first = 0; - if (vc < 1024) visited[vc++] = el_strdup_persist(peer); - if (fc < 1024 && h + 1 < depth) { frontier[fc] = el_strdup_persist(peer); frontier_h[fc] = h + 1; fc++; } - } - free(cur); - } - for (int64_t i = 0; i < fc; i++) free(frontier[i]); - for (int64_t i = 0; i < vc; i++) free(visited[i]); - free(frontier); free(frontier_h); free(visited); - jb_putc(&b, ']'); - return el_wrap_str(b.buf); -} - -el_val_t engram_activate_json(el_val_t query, el_val_t depth) { - /* Run two-layer engram_activate and serialize the result list to JSON. - * Each entry includes both activation_strength (layer 1 background) and - * working_memory_weight (layer 2 executive filter), plus promoted flag. - * Callers performing context compilation should filter to promoted=1. */ - el_val_t lst = engram_activate(query, depth); - ElList* arr = (ElList*)(uintptr_t)lst; - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - if (arr) { - for (int64_t i = 0; i < arr->length; i++) { - if (!arr->elems[i]) continue; - el_val_t node_map = el_map_get(arr->elems[i], EL_STR("node")); - el_val_t strength_v = el_map_get(arr->elems[i], EL_STR("activation_strength")); - el_val_t wm_v = el_map_get(arr->elems[i], EL_STR("working_memory_weight")); - el_val_t epist_v = el_map_get(arr->elems[i], EL_STR("epistemic_confidence")); - el_val_t hops_v = el_map_get(arr->elems[i], EL_STR("hops")); - el_val_t promoted_v = el_map_get(arr->elems[i], EL_STR("promoted")); - /* Look up underlying EngramNode by id to emit canonical JSON. */ - el_val_t id_v = el_map_get(node_map, EL_STR("id")); - const char* id_s = EL_CSTR(id_v); - EngramNode* n = id_s ? engram_find_node(id_s) : NULL; - if (i > 0) jb_putc(&b, ','); - jb_puts(&b, "{\"node\":"); - if (n) { - engram_emit_node_json(&b, n); - } else { - jb_puts(&b, "{}"); - } - char tmp[80]; - snprintf(tmp, sizeof(tmp), ",\"activation_strength\":%g", el_to_float(strength_v)); jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"working_memory_weight\":%g", el_to_float(wm_v)); jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"epistemic_confidence\":%g", el_to_float(epist_v)); jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"hops\":%lld", (long long)(int64_t)hops_v); jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"promoted\":%d}", (int)(int64_t)promoted_v); jb_puts(&b, tmp); - } - } - jb_putc(&b, ']'); - return el_wrap_str(b.buf); -} - -el_val_t engram_stats_json(void) { - EngramStore* g = engram_get(); - char buf[128]; - snprintf(buf, sizeof(buf), - "{\"node_count\":%lld,\"edge_count\":%lld,\"layer_count\":%zu}", - (long long)g->node_count, (long long)g->edge_count, g->layer_count); - return el_wrap_str(el_strdup(buf)); -} - -/* engram_list_layers_json — serialized counterpart of engram_list_layers. - * Returns a JSON array, sorted by activation_priority ascending. */ -el_val_t engram_list_layers_json(void) { - EngramStore* g = engram_get(); - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - /* Build a sorted index over live layers. */ - size_t* idx = malloc((g->layer_count + 1) * sizeof(size_t)); - if (!idx) { jb_putc(&b, ']'); return el_wrap_str(b.buf); } - size_t live = 0; - for (size_t i = 0; i < g->layer_count; i++) { - if (g->layers[i].name) idx[live++] = i; - } - for (size_t i = 1; i < live; i++) { - size_t key = idx[i]; - uint32_t kp = g->layers[key].activation_priority; - size_t j = i; - while (j > 0 && g->layers[idx[j - 1]].activation_priority > kp) { - idx[j] = idx[j - 1]; - j--; - } - idx[j] = key; - } - int first = 1; - for (size_t i = 0; i < live; i++) { - EngramLayer* L = &g->layers[idx[i]]; - if (!first) jb_putc(&b, ','); - first = 0; - jb_putc(&b, '{'); - char tmp[80]; - snprintf(tmp, sizeof(tmp), "\"layer_id\":%u", L->layer_id); jb_puts(&b, tmp); - jb_puts(&b, ",\"name\":"); - jb_emit_escaped(&b, L->name ? L->name : ""); - snprintf(tmp, sizeof(tmp), ",\"activation_priority\":%u", L->activation_priority); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"suppressible\":%d", L->suppressible ? 1 : 0); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"transparent\":%d", L->transparent ? 1 : 0); - jb_puts(&b, tmp); - snprintf(tmp, sizeof(tmp), ",\"injectable\":%d", L->injectable ? 1 : 0); - jb_puts(&b, tmp); - jb_putc(&b, '}'); - } - free(idx); - jb_putc(&b, ']'); - return el_wrap_str(b.buf); -} - -/* engram_compile_layered_json — produce a prompt-ready context block split - * by layer. - * - * Runs the three-pass activation, then partitions promoted nodes by layer - * suppressibility: - * - Non-suppressible (Layer 0 / structural-floor) layers go FIRST under - * the heading "[LAYER 0 — STRUCTURAL]". These are the sacred-fire - * nodes that surfaced via the pass-3 override. - * - All other promoted layers go SECOND under "[ENGRAM CONTEXT]". - * - * Output is a single JSON-string el_val_t: a UTF-8 text block ready to be - * concatenated into a system prompt. Returns "" if no nodes promoted. - * - * Transparent layers (Layer 0) are emitted into the prompt — they shape - * the model's output — but engram_search and friends still hide them from - * introspection-style queries. The split heading lets the LLM weight them - * appropriately without revealing their internal label. - * - * Each emitted line for a node is its raw JSON (matching engram_emit_node_json) - * so downstream JSON parsers can still walk individual records inside the - * formatted block. The block is plain text, not a JSON document — callers - * concatenating it into a prompt should treat it as opaque markdown. */ -el_val_t engram_compile_layered_json(el_val_t intent, el_val_t depth) { - EngramStore* g = engram_get(); - /* Run the three-pass activator. We need the persisted node fields, so - * call engram_activate (it writes background_activation and - * working_memory_weight back into the store). */ - (void)engram_activate(intent, depth); - - /* Walk the store and partition by suppressibility. */ - JsonBuf b; jb_init(&b); - int wrote_layer0 = 0; - int wrote_normal = 0; - - /* Sort indices by working_memory_weight descending so the most - * confidently promoted nodes appear first within each section. */ - int64_t* idx = malloc((size_t)(g->node_count + 1) * sizeof(int64_t)); - if (!idx) return el_wrap_str(el_strdup("")); - int64_t mc = 0; - for (int64_t i = 0; i < g->node_count; i++) { - if (g->nodes[i].working_memory_weight > 0.0) idx[mc++] = i; - } - for (int64_t i = 1; i < mc; i++) { - int64_t key = idx[i]; - double kw = g->nodes[key].working_memory_weight; - int64_t j = i; - while (j > 0 && g->nodes[idx[j - 1]].working_memory_weight < kw) { - idx[j] = idx[j - 1]; - j--; - } - idx[j] = key; - } - - /* Section 1: structural floor (non-suppressible layers). */ - for (int64_t i = 0; i < mc; i++) { - EngramNode* n = &g->nodes[idx[i]]; - if (engram_layer_is_suppressible(n->layer_id)) continue; - if (!wrote_layer0) { - jb_puts(&b, "[LAYER 0 — STRUCTURAL]\n"); - wrote_layer0 = 1; - } - engram_emit_node_json(&b, n); - jb_putc(&b, '\n'); - } - - /* Section 2: standard engram context (suppressible layers). */ - for (int64_t i = 0; i < mc; i++) { - EngramNode* n = &g->nodes[idx[i]]; - if (!engram_layer_is_suppressible(n->layer_id)) continue; - if (!wrote_normal) { - if (wrote_layer0) jb_putc(&b, '\n'); - jb_puts(&b, "[ENGRAM CONTEXT]\n"); - wrote_normal = 1; - } - engram_emit_node_json(&b, n); - jb_putc(&b, '\n'); - } - - free(idx); - if (b.len == 0) { - free(b.buf); - return el_wrap_str(el_strdup("")); - } - return el_wrap_str(b.buf); -} - -/* engram_query_range — temporal range query. - * Returns a JSON array of nodes whose created_at OR last_activated falls - * within [start_ms, end_ms], sorted by created_at ascending. - * Enables "what was I working on last Tuesday?" style queries by passing - * unix-millisecond timestamps for the start and end of the target interval. - * Both endpoints are inclusive. Pass 0 for start_ms to mean "beginning of - * time"; pass 0 for end_ms to mean "now". */ -el_val_t engram_query_range(el_val_t start_ms_v, el_val_t end_ms_v) { - EngramStore* g = engram_get(); - int64_t start_ms = (int64_t)start_ms_v; - int64_t end_ms = (int64_t)end_ms_v; - if (end_ms <= 0) end_ms = engram_now_ms(); - - /* Collect matching indices. */ - int64_t* idx = malloc((size_t)g->node_count * sizeof(int64_t)); - if (!idx) return el_wrap_str(el_strdup("[]")); - int64_t mc = 0; - for (int64_t i = 0; i < g->node_count; i++) { - EngramNode* n = &g->nodes[i]; - int in_created = (n->created_at >= start_ms && n->created_at <= end_ms); - int in_activated = (n->last_activated >= start_ms && n->last_activated <= end_ms); - if (in_created || in_activated) idx[mc++] = i; - } - /* Sort by created_at ascending (insertion sort — N is small in practice). */ - for (int64_t i = 1; i < mc; i++) { - int64_t key = idx[i]; - int64_t kts = g->nodes[key].created_at; - int64_t j = i - 1; - while (j >= 0 && g->nodes[idx[j]].created_at > kts) { - idx[j + 1] = idx[j]; - j--; - } - idx[j + 1] = key; - } - JsonBuf b; jb_init(&b); - jb_putc(&b, '['); - for (int64_t i = 0; i < mc; i++) { - if (i > 0) jb_putc(&b, ','); - engram_emit_node_json(&b, &g->nodes[idx[i]]); - } - jb_putc(&b, ']'); - free(idx); - return el_wrap_str(b.buf); -} - -/* ── DHARMA network ───────────────────────────────────────────────────────── - * Real implementation. Peers are addressed by `dharma_id` — either bare - * (e.g. "ntn-genesis", transport defaults to http://localhost:7770) or - * "@" where is the peer's Engram-exposed daemon. - * - * Channels are logical handles cached per-cgi: `dharma_connect` is - * idempotent and returns "ch:". The channel registry below tracks - * every cgi_id we've connected to and its resolved transport URL. - * - * Relationship weights live in the local Engram graph: edges of type - * "dharma-relation" between a synthetic local node ("dharma:self") and - * synthetic peer nodes ("dharma:peer:"). Hebbian increments - * accumulate in EngramEdge.weight, clamped to [0.0, 1.0]. - * - * Events arrive over HTTP via the application's request handler, which is - * expected to call el_runtime_dharma_event_arrive() when it sees a - * /dharma/event POST. dharma_field() blocks on a per-event-type queue. - */ - -#define DHARMA_DEFAULT_URL "http://localhost:7770" - -/* Channel registry — one entry per known peer. */ -typedef struct DharmaChannel { - char* cgi_id; /* full dharma_id including any @ suffix */ - char* base_id; /* registry-id portion (before @) for relationship lookup */ - char* url; /* resolved transport URL */ - char* channel_id; /* "ch:" */ -} DharmaChannel; - -static DharmaChannel* _dharma_channels = NULL; -static size_t _dharma_channel_count = 0; -static size_t _dharma_channel_cap = 0; -static pthread_mutex_t _dharma_channel_mu = PTHREAD_MUTEX_INITIALIZER; - -/* Event queue — per-type linked list. dharma_field blocks on _dharma_event_cv. */ -typedef struct DharmaEvent { - char* event_type; - char* payload; - char* source; - int64_t timestamp; - struct DharmaEvent* next; -} DharmaEvent; - -static DharmaEvent* _dharma_event_head = NULL; -static DharmaEvent* _dharma_event_tail = NULL; -static pthread_mutex_t _dharma_event_mu = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t _dharma_event_cv = PTHREAD_COND_INITIALIZER; - -/* Split "@" → (base_id, url). If no "@", base_id = full, url = default. - * Returned strings are heap-allocated; caller must free. */ -static void dharma_parse_id(const char* full, char** out_base, char** out_url) { - if (!full) full = ""; - const char* at = strchr(full, '@'); - if (at) { - size_t bn = (size_t)(at - full); - char* b = malloc(bn + 1); - memcpy(b, full, bn); b[bn] = '\0'; - *out_base = b; - *out_url = el_strdup(at + 1); - if (!**out_url) { free(*out_url); *out_url = el_strdup(DHARMA_DEFAULT_URL); } - } else { - *out_base = el_strdup(full); - *out_url = el_strdup(DHARMA_DEFAULT_URL); - } -} - -/* Find existing channel by full cgi_id. Caller must hold _dharma_channel_mu. */ -static DharmaChannel* dharma_find_channel_locked(const char* cgi_id) { - if (!cgi_id) return NULL; - for (size_t i = 0; i < _dharma_channel_count; i++) { - if (_dharma_channels[i].cgi_id && - strcmp(_dharma_channels[i].cgi_id, cgi_id) == 0) { - return &_dharma_channels[i]; - } - } - return NULL; -} - -/* Add a new channel entry. Caller must hold _dharma_channel_mu. */ -static DharmaChannel* dharma_add_channel_locked(const char* cgi_id) { - if (_dharma_channel_count >= _dharma_channel_cap) { - size_t nc = _dharma_channel_cap ? _dharma_channel_cap * 2 : 8; - _dharma_channels = realloc(_dharma_channels, nc * sizeof(DharmaChannel)); - if (!_dharma_channels) { fputs("el_runtime: out of memory\n", stderr); exit(1); } - memset(_dharma_channels + _dharma_channel_cap, 0, - (nc - _dharma_channel_cap) * sizeof(DharmaChannel)); - _dharma_channel_cap = nc; - } - DharmaChannel* ch = &_dharma_channels[_dharma_channel_count++]; - char* base = NULL; char* url = NULL; - dharma_parse_id(cgi_id, &base, &url); - ch->cgi_id = el_strdup(cgi_id ? cgi_id : ""); - ch->base_id = base; - ch->url = url; - size_t cn = strlen(ch->cgi_id) + 4; - ch->channel_id = malloc(cn); - snprintf(ch->channel_id, cn, "ch:%s", ch->cgi_id); - return ch; -} - -el_val_t dharma_connect(el_val_t cgi_id) { - const char* id = EL_CSTR(cgi_id); - if (!id || !*id) return el_wrap_str(el_strdup("")); - pthread_mutex_lock(&_dharma_channel_mu); - DharmaChannel* ch = dharma_find_channel_locked(id); - if (!ch) ch = dharma_add_channel_locked(id); - char* out = el_strdup(ch->channel_id); - pthread_mutex_unlock(&_dharma_channel_mu); - return el_wrap_str(out); -} - -/* Build an error JSON body — same shape http_error_json uses. */ -static el_val_t dharma_error_json(const char* msg) { - return http_error_json(msg); -} - -el_val_t dharma_send(el_val_t channel, el_val_t content) { - const char* ch_id = EL_CSTR(channel); - const char* msg = EL_CSTR(content); - if (!ch_id || strncmp(ch_id, "ch:", 3) != 0) { - return dharma_error_json("invalid channel"); - } - const char* peer_id = ch_id + 3; - /* Look up channel; if unknown (caller fabricated), auto-register. */ - pthread_mutex_lock(&_dharma_channel_mu); - DharmaChannel* ch = dharma_find_channel_locked(peer_id); - if (!ch) ch = dharma_add_channel_locked(peer_id); - char* url = el_strdup(ch->url); - pthread_mutex_unlock(&_dharma_channel_mu); - /* Build /dharma/recv body. */ - const char* from = _el_cgi_dharma_id ? _el_cgi_dharma_id : "(unknown)"; - char* esc_ch = json_escape_alloc(ch_id); - char* esc_from = json_escape_alloc(from); - char* esc_msg = json_escape_alloc(msg ? msg : ""); - JsonBuf b; jb_init(&b); - jb_puts(&b, "{\"channel\":\""); jb_puts(&b, esc_ch); - jb_puts(&b, "\",\"from\":\""); jb_puts(&b, esc_from); - jb_puts(&b, "\",\"content\":\""); jb_puts(&b, esc_msg); - jb_puts(&b, "\"}"); - free(esc_ch); free(esc_from); free(esc_msg); - size_t ul = strlen(url) + 16; - char* full_url = malloc(ul); - snprintf(full_url, ul, "%s/dharma/recv", url); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - el_val_t resp = http_do("POST", full_url, b.buf, h); - curl_slist_free_all(h); - free(b.buf); free(full_url); free(url); - return resp; -} - -el_val_t dharma_activate(el_val_t query) { - const char* q = EL_CSTR(query); - if (!q) q = ""; - el_val_t out = el_list_empty(); - char* esc_q = json_escape_alloc(q); - JsonBuf body; jb_init(&body); - jb_puts(&body, "{\"query\":\""); jb_puts(&body, esc_q); jb_puts(&body, "\"}"); - free(esc_q); - - /* Snapshot the channel list under lock so we can iterate without - * holding the mutex during network I/O. */ - pthread_mutex_lock(&_dharma_channel_mu); - size_t n = _dharma_channel_count; - char** urls = calloc(n ? n : 1, sizeof(char*)); - char** ids = calloc(n ? n : 1, sizeof(char*)); - char** bases = calloc(n ? n : 1, sizeof(char*)); - for (size_t i = 0; i < n; i++) { - urls[i] = el_strdup(_dharma_channels[i].url); - ids[i] = el_strdup(_dharma_channels[i].cgi_id); - bases[i] = el_strdup(_dharma_channels[i].base_id); - } - pthread_mutex_unlock(&_dharma_channel_mu); - - for (size_t i = 0; i < n; i++) { - size_t ul = strlen(urls[i]) + 32; - char* full_url = malloc(ul); - snprintf(full_url, ul, "%s/api/activate", urls[i]); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - el_val_t resp = http_do("POST", full_url, body.buf, h); - curl_slist_free_all(h); - free(full_url); - const char* rs = EL_CSTR(resp); - if (!rs || !*rs) continue; - if (rs[0] == '{' && strstr(rs, "\"error\"")) continue; - - /* Look up relationship weight (attenuation). */ - double rel_weight = 1.0; - { - const char* self_id = "dharma:self"; - char peer_node[512]; - snprintf(peer_node, sizeof(peer_node), "dharma:peer:%s", bases[i]); - EngramStore* g = engram_get(); - for (int64_t k = 0; k < g->edge_count; k++) { - EngramEdge* e = &g->edges[k]; - if (e->from_id && e->to_id && - strcmp(e->from_id, self_id) == 0 && - strcmp(e->to_id, peer_node) == 0 && - e->relation && strcmp(e->relation, "dharma-relation") == 0) { - rel_weight = e->weight; - break; - } - } - } - - /* Iterate the response array. Expect either a top-level array - * or an object whose "results" field is an array. */ - const char* arr = rs; - while (*arr == ' ' || *arr == '\t' || *arr == '\n' || *arr == '\r') arr++; - char* arr_owned = NULL; - if (*arr == '{') { - el_val_t r = json_get_raw(EL_STR(rs), EL_STR("results")); - const char* rr = EL_CSTR(r); - if (rr && *rr == '[') { - arr_owned = el_strdup(rr); - arr = arr_owned; - } else { - continue; - } - } - if (*arr != '[') { free(arr_owned); continue; } - const char* p = arr + 1; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - while (*p && *p != ']') { - const char* end = json_skip_value(p); - size_t en = (size_t)(end - p); - char* obj = el_strbuf(en); - memcpy(obj, p, en); obj[en] = '\0'; - - /* Pull activation_strength if present, else 1.0. */ - el_val_t act_v = json_get_float(EL_STR(obj), EL_STR("activation_strength")); - double act = el_to_float(act_v); - if (!(act > 0.0 && act <= 100.0)) act = 1.0; - double final_act = act * rel_weight; - - el_val_t entry = el_map_new(0); - /* node = the inner JSON if present, else the entire obj. */ - el_val_t node_raw = json_get_raw(EL_STR(obj), EL_STR("node")); - const char* nr = EL_CSTR(node_raw); - entry = el_map_set(entry, EL_STR(el_strdup("node")), - (nr && *nr) ? node_raw : EL_STR(el_strdup(obj))); - entry = el_map_set(entry, EL_STR(el_strdup("source_cgi")), - EL_STR(el_strdup(ids[i]))); - entry = el_map_set(entry, EL_STR(el_strdup("activation_strength")), - el_from_float(final_act)); - out = el_list_append(out, entry); - free(obj); - p = end; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - } - free(arr_owned); - } - for (size_t i = 0; i < n; i++) { free(urls[i]); free(ids[i]); free(bases[i]); } - free(urls); free(ids); free(bases); - free(body.buf); - return out; -} - -void dharma_emit(el_val_t event_type, el_val_t payload) { - const char* et = EL_CSTR(event_type); - const char* pay = EL_CSTR(payload); - if (!et) et = ""; - if (!pay) pay = ""; - const char* src = _el_cgi_dharma_id ? _el_cgi_dharma_id : "(unknown)"; - int64_t ts = engram_now_ms(); - - char* esc_et = json_escape_alloc(et); - char* esc_pay = json_escape_alloc(pay); - char* esc_src = json_escape_alloc(src); - JsonBuf b; jb_init(&b); - jb_puts(&b, "{\"type\":\""); jb_puts(&b, esc_et); - jb_puts(&b, "\",\"payload\":\""); jb_puts(&b, esc_pay); - jb_puts(&b, "\",\"source\":\""); jb_puts(&b, esc_src); - jb_puts(&b, "\",\"timestamp\":"); jb_emit_int(&b, ts); - jb_putc(&b, '}'); - free(esc_et); free(esc_pay); free(esc_src); - - /* Snapshot URLs to avoid holding the channel mutex during I/O. */ - pthread_mutex_lock(&_dharma_channel_mu); - size_t n = _dharma_channel_count; - char** urls = calloc(n ? n : 1, sizeof(char*)); - for (size_t i = 0; i < n; i++) urls[i] = el_strdup(_dharma_channels[i].url); - pthread_mutex_unlock(&_dharma_channel_mu); - - for (size_t i = 0; i < n; i++) { - size_t ul = strlen(urls[i]) + 32; - char* full_url = malloc(ul); - snprintf(full_url, ul, "%s/dharma/event", urls[i]); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - el_val_t r = http_do("POST", full_url, b.buf, h); - (void)r; /* fire-and-forget — emit is not synchronous */ - curl_slist_free_all(h); - free(full_url); - } - for (size_t i = 0; i < n; i++) free(urls[i]); - free(urls); - free(b.buf); -} - -void el_runtime_dharma_event_arrive(const char* event_type, const char* payload, - const char* source) { - DharmaEvent* ev = calloc(1, sizeof(DharmaEvent)); - if (!ev) return; - ev->event_type = el_strdup(event_type ? event_type : ""); - ev->payload = el_strdup(payload ? payload : ""); - ev->source = el_strdup(source ? source : ""); - ev->timestamp = engram_now_ms(); - ev->next = NULL; - pthread_mutex_lock(&_dharma_event_mu); - if (_dharma_event_tail) _dharma_event_tail->next = ev; - else _dharma_event_head = ev; - _dharma_event_tail = ev; - pthread_cond_broadcast(&_dharma_event_cv); - pthread_mutex_unlock(&_dharma_event_mu); -} - -el_val_t dharma_field(el_val_t event_type) { - const char* et = EL_CSTR(event_type); - if (!et) et = ""; - - /* Compute deadline: now + 30 seconds. */ - struct timespec deadline; - clock_gettime(CLOCK_REALTIME, &deadline); - deadline.tv_sec += 30; - - DharmaEvent* found = NULL; - pthread_mutex_lock(&_dharma_event_mu); - while (1) { - /* Scan queue for matching type; pop and return first match. */ - DharmaEvent* prev = NULL; - DharmaEvent* cur = _dharma_event_head; - while (cur) { - if (cur->event_type && strcmp(cur->event_type, et) == 0) { - if (prev) prev->next = cur->next; - else _dharma_event_head = cur->next; - if (_dharma_event_tail == cur) _dharma_event_tail = prev; - cur->next = NULL; - found = cur; - break; - } - prev = cur; cur = cur->next; - } - if (found) break; - int rc = pthread_cond_timedwait(&_dharma_event_cv, &_dharma_event_mu, &deadline); - if (rc == ETIMEDOUT) break; - } - pthread_mutex_unlock(&_dharma_event_mu); - - if (!found) return el_map_new(0); - el_val_t m = el_map_new(0); - m = el_map_set(m, EL_STR(el_strdup("type")), - EL_STR(el_strdup(found->event_type ? found->event_type : ""))); - m = el_map_set(m, EL_STR(el_strdup("payload")), - EL_STR(el_strdup(found->payload ? found->payload : ""))); - m = el_map_set(m, EL_STR(el_strdup("source_cgi")), - EL_STR(el_strdup(found->source ? found->source : ""))); - m = el_map_set(m, EL_STR(el_strdup("timestamp")), (el_val_t)found->timestamp); - free(found->event_type); free(found->payload); free(found->source); free(found); - return m; -} - -/* Locate (or create) the local "dharma:self" node and the synthetic peer - * node "dharma:peer:". Returns the index of the dharma-relation - * edge, or -1 if not found. If `create` is non-zero, ensure the nodes - * and edge exist (creating them as needed) and return the edge index. */ -static int64_t dharma_find_or_create_relation_edge(const char* peer_base, int create) { - if (!peer_base || !*peer_base) return -1; - EngramStore* g = engram_get(); - const char* self_id = "dharma:self"; - char peer_node[512]; - snprintf(peer_node, sizeof(peer_node), "dharma:peer:%s", peer_base); - - /* Look for the edge first. */ - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - if (e->from_id && e->to_id && - strcmp(e->from_id, self_id) == 0 && - strcmp(e->to_id, peer_node) == 0 && - e->relation && strcmp(e->relation, "dharma-relation") == 0) { - return i; - } - } - if (!create) return -1; - - /* Ensure self node exists. We use a fixed id (not engram_new_id) so - * subsequent calls reuse the same one. */ - if (!engram_find_node(self_id)) { - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = el_strdup(self_id); - n->content = el_strdup(_el_cgi_dharma_id ? _el_cgi_dharma_id : "(self)"); - n->node_type = el_strdup("DharmaSelf"); - n->label = el_strdup("dharma:self"); - n->tier = el_strdup("Working"); - n->tags = el_strdup("dharma"); - n->metadata = el_strdup("{}"); - n->salience = 1.0; n->importance = 1.0; n->confidence = 1.0; - int64_t now = engram_now_ms(); - n->created_at = now; n->updated_at = now; n->last_activated = now; - n->layer_id = ENGRAM_LAYER_DEFAULT; - g->node_count++; - } - if (!engram_find_node(peer_node)) { - engram_grow_nodes(); - EngramNode* n = &g->nodes[g->node_count]; - memset(n, 0, sizeof(*n)); - n->id = el_strdup(peer_node); - n->content = el_strdup(peer_base); - n->node_type = el_strdup("DharmaPeer"); - n->label = el_strdup(peer_node); - n->tier = el_strdup("Working"); - n->tags = el_strdup("dharma"); - n->metadata = el_strdup("{}"); - n->salience = 0.5; n->importance = 0.5; n->confidence = 1.0; - int64_t now = engram_now_ms(); - n->created_at = now; n->updated_at = now; n->last_activated = now; - n->layer_id = ENGRAM_LAYER_DEFAULT; - g->node_count++; - } - /* Create the edge with weight 0.0 — caller will increment. */ - engram_grow_edges(); - EngramEdge* e = &g->edges[g->edge_count]; - memset(e, 0, sizeof(*e)); - e->id = engram_new_id(); - e->from_id = el_strdup(self_id); - e->to_id = el_strdup(peer_node); - e->relation = el_strdup("dharma-relation"); - e->metadata = el_strdup("{}"); - e->weight = 0.0; - e->confidence = 1.0; - int64_t now = engram_now_ms(); - e->created_at = now; e->updated_at = now; - e->layer_id = ENGRAM_LAYER_DEFAULT; - int64_t idx = g->edge_count; - g->edge_count++; - return idx; -} - -void dharma_strengthen(el_val_t cgi_id, el_val_t weight) { - const char* id = EL_CSTR(cgi_id); - if (!id || !*id) return; - char* base = NULL; char* url = NULL; - dharma_parse_id(id, &base, &url); - free(url); - int64_t ei = dharma_find_or_create_relation_edge(base, 1); - free(base); - if (ei < 0) return; - EngramStore* g = engram_get(); - double inc = engram_decode_score(weight); - if (!(inc >= 0.0)) inc = 0.0; - double w = g->edges[ei].weight + inc; - if (w < 0.0) w = 0.0; - if (w > 1.0) w = 1.0; - g->edges[ei].weight = w; - g->edges[ei].updated_at = engram_now_ms(); - g->edges[ei].last_fired = g->edges[ei].updated_at; -} - -el_val_t dharma_relationship(el_val_t cgi_id) { - const char* id = EL_CSTR(cgi_id); - if (!id || !*id) return el_from_float(0.0); - char* base = NULL; char* url = NULL; - dharma_parse_id(id, &base, &url); - free(url); - int64_t ei = dharma_find_or_create_relation_edge(base, 0); - free(base); - if (ei < 0) return el_from_float(0.0); - EngramStore* g = engram_get(); - return el_from_float(g->edges[ei].weight); -} - -el_val_t dharma_peers(void) { - /* Walk dharma-relation edges out of "dharma:self", weight > 0, sort desc. */ - EngramStore* g = engram_get(); - const char* self_id = "dharma:self"; - typedef struct { char* peer_base; double weight; } PeerEntry; - PeerEntry* peers = malloc((size_t)(g->edge_count + 1) * sizeof(PeerEntry)); - int64_t pcount = 0; - if (!peers) return el_list_empty(); - for (int64_t i = 0; i < g->edge_count; i++) { - EngramEdge* e = &g->edges[i]; - if (!e->from_id || !e->to_id) continue; - if (strcmp(e->from_id, self_id) != 0) continue; - if (!e->relation || strcmp(e->relation, "dharma-relation") != 0) continue; - if (e->weight <= 0.0) continue; - const char* prefix = "dharma:peer:"; - size_t pl = strlen(prefix); - if (strncmp(e->to_id, prefix, pl) != 0) continue; - peers[pcount].peer_base = el_strdup(e->to_id + pl); - peers[pcount].weight = e->weight; - pcount++; - } - /* Sort desc by weight. */ - for (int64_t i = 1; i < pcount; i++) { - PeerEntry key = peers[i]; - int64_t j = i - 1; - while (j >= 0 && peers[j].weight < key.weight) { - peers[j + 1] = peers[j]; j--; - } - peers[j + 1] = key; - } - el_val_t out = el_list_empty(); - for (int64_t i = 0; i < pcount; i++) { - out = el_list_append(out, EL_STR(peers[i].peer_base)); - } - free(peers); - return out; -} - -/* ── Batch 4: LLM (Anthropic API client) ─────────────────────────────────── */ -/* - * All LLM builtins call https://api.anthropic.com/v1/messages with the API - * key from env ANTHROPIC_API_KEY. Default model is "claude-sonnet-4-5" - * when the supplied model is empty/null. - * - * `llm_call_agentic` runs a real multi-turn tool_use/tool_result loop. - * Tool handlers are registered with `llm_register_tool(name, fn_name)`, - * which dlsym()s the named symbol. Each tool handler has the C signature - * el_val_t handler(el_val_t input_json); - * and returns a JSON-string el_val_t result. Iteration is capped at 10. - */ - -static const char* LLM_DEFAULT_MODEL = "claude-sonnet-4-5"; -static const char* LLM_API_URL = "https://api.anthropic.com/v1/messages"; -static const char* LLM_VERSION = "2023-06-01"; - -static const char* llm_resolve_model(const char* m) { - if (!m || !*m) return LLM_DEFAULT_MODEL; - return m; -} - -/* - * ── Configurable LLM provider chain ────────────────────────────────────────── - * - * Providers are configured via indexed env vars. The runtime tries each in - * order (0, 1, 2, ...) and returns the first successful non-empty response. - * - * Per provider (N = 0, 1, 2, ...): - * NEURON_LLM_N_URL — endpoint URL (base URL; /v1/chat/completions appended - * if format is "openai" and not already in URL) - * NEURON_LLM_N_KEY — API key - * NEURON_LLM_N_FORMAT — "openai" (default) or "anthropic" - * NEURON_LLM_N_MODEL — model name override (optional) - * - * Example — Neuron inference primary, Anthropic fallback: - * NEURON_LLM_0_URL=https://soma.../v1/chat/completions - * NEURON_LLM_0_KEY=svc-key - * NEURON_LLM_0_FORMAT=openai - * NEURON_LLM_0_MODEL=neuron - * NEURON_LLM_1_URL=https://api.anthropic.com/v1/messages - * NEURON_LLM_1_KEY=sk-ant-... - * NEURON_LLM_1_FORMAT=anthropic - * - * If no NEURON_LLM_0_URL is set, falls back to legacy ANTHROPIC_API_KEY. - */ - -#define LLM_MAX_PROVIDERS 16 - -/* forward declarations */ -static el_val_t llm_extract_text(el_val_t resp_val); -static el_val_t llm_extract_text_openai(el_val_t resp_val); - -static el_val_t llm_extract_text_openai(el_val_t resp_val) { - const char* resp = EL_CSTR(resp_val); - if (!resp || !*resp) return el_wrap_str(el_strdup("")); - if (resp[0] == '{' && strstr(resp, "\"error\"")) return el_wrap_str(el_strdup("")); - const char* choices = json_find_key(resp, "choices"); - if (!choices || *choices != '[') return el_wrap_str(el_strdup("")); - choices++; - while (*choices == ' ' || *choices == '\t') choices++; - if (*choices != '{') return el_wrap_str(el_strdup("")); - const char* end = json_skip_value(choices); - size_t n = (size_t)(end - choices); - char* obj = malloc(n + 1); memcpy(obj, choices, n); obj[n] = '\0'; - const char* msg = json_find_key(obj, "message"); - if (!msg || *msg != '{') { free(obj); return el_wrap_str(el_strdup("")); } - const char* msg_end = json_skip_value(msg); - size_t mn = (size_t)(msg_end - msg); - char* msg_obj = malloc(mn + 1); memcpy(msg_obj, msg, mn); msg_obj[mn] = '\0'; - const char* content = json_find_key(msg_obj, "content"); - el_val_t result = el_wrap_str(el_strdup("")); - if (content && *content == '"') { - JsonParser jp = { .p = content, .end = content + strlen(content), .err = 0 }; - char* text = jp_parse_string_raw(&jp); - if (!jp.err && text) result = el_wrap_str(text); - } - free(msg_obj); free(obj); - return result; -} - -/* Send a request to one provider. Returns the raw response string. - * format: 0 = openai, 1 = anthropic */ -static el_val_t llm_provider_request(const char* url, const char* key, - int format, const char* model, - const char* system_str, - const char* user_str) { - char* esc_sys = system_str && *system_str ? json_escape_alloc(system_str) : NULL; - char* esc_user = json_escape_alloc(user_str ? user_str : ""); - JsonBuf b; jb_init(&b); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - - if (format == 0) { /* OpenAI */ - char full_url[1024]; - if (strstr(url, "/chat/completions") || strstr(url, "/messages")) { - snprintf(full_url, sizeof(full_url), "%s", url); - } else { - snprintf(full_url, sizeof(full_url), "%s/v1/chat/completions", url); - } - { size_t n = strlen(key)+24; char* l=malloc(n); snprintf(l,n,"Authorization: Bearer %s",key); h=curl_slist_append(h,l); free(l); } - jb_putc(&b, '{'); - jb_puts(&b, "\"model\":"); jb_emit_escaped(&b, model ? model : "neuron"); - jb_puts(&b, ",\"max_tokens\":1024,\"messages\":["); - if (esc_sys && *esc_sys) { jb_puts(&b,"{\"role\":\"system\",\"content\":\""); jb_puts(&b,esc_sys); jb_puts(&b,"\"},"); } - jb_puts(&b, "{\"role\":\"user\",\"content\":\""); jb_puts(&b, esc_user); jb_puts(&b, "\"}]}"); - el_val_t resp = http_do("POST", full_url, b.buf, h); - curl_slist_free_all(h); free(b.buf); - if (esc_sys) free(esc_sys); free(esc_user); - return llm_extract_text_openai(resp); - } else { /* Anthropic */ - { size_t n = strlen(key)+16; char* l=malloc(n); snprintf(l,n,"x-api-key: %s",key); h=curl_slist_append(h,l); free(l); } - { size_t n = strlen(LLM_VERSION)+32; char* l=malloc(n); snprintf(l,n,"anthropic-version: %s",LLM_VERSION); h=curl_slist_append(h,l); free(l); } - jb_putc(&b, '{'); - jb_puts(&b, "\"model\":"); jb_emit_escaped(&b, model ? model : LLM_DEFAULT_MODEL); - jb_puts(&b, ",\"max_tokens\":4096"); - if (esc_sys && *esc_sys) { jb_puts(&b,",\"system\":\""); jb_puts(&b,esc_sys); jb_puts(&b,"\""); } - jb_puts(&b, ",\"messages\":[{\"role\":\"user\",\"content\":\""); jb_puts(&b, esc_user); jb_puts(&b, "\"}]}"); - el_val_t resp = http_do("POST", url, b.buf, h); - curl_slist_free_all(h); free(b.buf); - if (esc_sys) free(esc_sys); free(esc_user); - return llm_extract_text(resp); - } -} - -static el_val_t llm_chain_call(const char* system_str, const char* user_str) { - char url_key[64], key_key[64], fmt_key[64], model_key[64]; - for (int i = 0; i < LLM_MAX_PROVIDERS; i++) { - snprintf(url_key, sizeof(url_key), "NEURON_LLM_%d_URL", i); - snprintf(key_key, sizeof(key_key), "NEURON_LLM_%d_KEY", i); - snprintf(fmt_key, sizeof(fmt_key), "NEURON_LLM_%d_FORMAT", i); - snprintf(model_key, sizeof(model_key), "NEURON_LLM_%d_MODEL", i); - const char* url = getenv(url_key); - const char* key = getenv(key_key); - if (!url || !*url || !key || !*key) break; /* end of chain */ - const char* fmt_s = getenv(fmt_key); - int fmt = (fmt_s && strcmp(fmt_s, "anthropic") == 0) ? 1 : 0; - const char* model = getenv(model_key); - fprintf(stderr, "[llm] trying provider %d (%s)\n", i, url); - el_val_t result = llm_provider_request(url, key, fmt, model, system_str, user_str); - const char* t = EL_CSTR(result); - if (t && *t && t[0] != '{') return result; /* success */ - fprintf(stderr, "[llm] provider %d failed or empty, trying next\n", i); - } - /* Legacy fallback: ANTHROPIC_API_KEY */ - const char* api_key = getenv("ANTHROPIC_API_KEY"); - if (!api_key || !*api_key) return http_error_json("no LLM providers configured"); - fprintf(stderr, "[llm] using legacy ANTHROPIC_API_KEY fallback\n"); - return llm_provider_request(LLM_API_URL, api_key, 1, NULL, system_str, user_str); -} - -/* Legacy llm_request — kept for backward compat with agentic loop internals */ -static el_val_t llm_request(const char* json_body) { - const char* api_key = getenv("ANTHROPIC_API_KEY"); - if (!api_key || !*api_key) return http_error_json("ANTHROPIC_API_KEY not set"); - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - { size_t n=strlen(api_key)+16; char* l=malloc(n); snprintf(l,n,"x-api-key: %s",api_key); h=curl_slist_append(h,l); free(l); } - { size_t n=strlen(LLM_VERSION)+32; char* l=malloc(n); snprintf(l,n,"anthropic-version: %s",LLM_VERSION); h=curl_slist_append(h,l); free(l); } - el_val_t resp = http_do("POST", LLM_API_URL, json_body, h); - curl_slist_free_all(h); - return resp; -} - -/* Extract concatenated assistant text from an Anthropic /v1/messages - * response. The response shape is: - * {"content":[{"type":"text","text":"..."}, ...], ...} - * If parsing fails, returns the raw response so the caller can inspect. - */ -static el_val_t llm_extract_text(el_val_t resp_val) { - const char* resp = EL_CSTR(resp_val); - if (!resp || !*resp) return el_wrap_str(el_strdup("")); - /* If error JSON, propagate as-is. */ - if (resp[0] == '{' && strstr(resp, "\"error\"")) { - return el_wrap_str(el_strdup(resp)); - } - /* Find "content":[ ... ] */ - const char* p = json_find_key(resp, "content"); - if (!p) return el_wrap_str(el_strdup(resp)); - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') return el_wrap_str(el_strdup(resp)); - p++; - JsonBuf out; jb_init(&out); - while (*p && *p != ']') { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p != '{') break; - const char* end = json_skip_value(p); - size_t n = (size_t)(end - p); - char* obj = malloc(n + 1); - memcpy(obj, p, n); obj[n] = '\0'; - const char* type_p = json_find_key(obj, "type"); - if (type_p && *type_p == '"') { - JsonParser jp = { .p = type_p, .end = type_p + strlen(type_p), .err = 0 }; - char* type_s = jp_parse_string_raw(&jp); - if (!jp.err && type_s && strcmp(type_s, "text") == 0) { - const char* tp = json_find_key(obj, "text"); - if (tp && *tp == '"') { - JsonParser jp2 = { .p = tp, .end = tp + strlen(tp), .err = 0 }; - char* text_s = jp_parse_string_raw(&jp2); - if (!jp2.err && text_s) jb_puts(&out, text_s); - free(text_s); - } - } - free(type_s); - } - free(obj); - p = end; - } - return el_wrap_str(out.buf); -} - -el_val_t llm_call(el_val_t model, el_val_t prompt) { - const char* u = EL_CSTR(prompt); if (!u) u = ""; - return llm_chain_call(NULL, u); -} - -el_val_t llm_call_system(el_val_t model, el_val_t system_prompt, el_val_t user_prompt) { - const char* s = EL_CSTR(system_prompt); if (!s) s = ""; - const char* u = EL_CSTR(user_prompt); if (!u) u = ""; - return llm_chain_call(s, u); -} - -/* ── Tool registry for llm_call_agentic ─────────────────────────────────── */ - -typedef el_val_t (*llm_tool_fn)(el_val_t input); - -typedef struct LlmToolEntry { - char* name; - llm_tool_fn fn; -} LlmToolEntry; - -static LlmToolEntry _llm_tools[64]; -static size_t _llm_tool_count = 0; -static pthread_mutex_t _llm_tool_mu = PTHREAD_MUTEX_INITIALIZER; - -static llm_tool_fn llm_tool_lookup(const char* name) { - if (!name) return NULL; - llm_tool_fn fn = NULL; - pthread_mutex_lock(&_llm_tool_mu); - for (size_t i = 0; i < _llm_tool_count; i++) { - if (strcmp(_llm_tools[i].name, name) == 0) { fn = _llm_tools[i].fn; break; } - } - pthread_mutex_unlock(&_llm_tool_mu); - return fn; -} - -void llm_register_tool(el_val_t name, el_val_t handler_fn_name) { - const char* nm = EL_CSTR(name); - const char* sym = EL_CSTR(handler_fn_name); - if (!nm || !*nm || !sym || !*sym) return; - void* p = dlsym(RTLD_DEFAULT, sym); - if (!p) { - fprintf(stderr, "[llm_register_tool] symbol not found: %s\n", sym); - return; - } - pthread_mutex_lock(&_llm_tool_mu); - /* Replace existing entry by name. */ - for (size_t i = 0; i < _llm_tool_count; i++) { - if (strcmp(_llm_tools[i].name, nm) == 0) { - _llm_tools[i].fn = (llm_tool_fn)p; - pthread_mutex_unlock(&_llm_tool_mu); - return; - } - } - if (_llm_tool_count < sizeof(_llm_tools) / sizeof(_llm_tools[0])) { - _llm_tools[_llm_tool_count].name = el_strdup(nm); - _llm_tools[_llm_tool_count].fn = (llm_tool_fn)p; - _llm_tool_count++; - } - pthread_mutex_unlock(&_llm_tool_mu); -} - -/* Serialize the El `tools` list into the JSON `tools:[...]` field expected - * by the Anthropic API. Each tool is an ElMap with name/description/ - * input_schema. input_schema is treated as either a JSON-object string - * (passed through verbatim) or a missing field (substitute {}). */ -static void llm_emit_tools_json(JsonBuf* b, el_val_t tools_list) { - jb_putc(b, '['); - ElList* lst = (ElList*)(uintptr_t)tools_list; - int64_t n = lst ? lst->length : 0; - for (int64_t i = 0; i < n; i++) { - if (i > 0) jb_putc(b, ','); - ElMap* tm = as_map(lst->elems[i]); - const char* name = ""; - const char* desc = ""; - const char* schema = "{}"; - if (tm) { - for (int64_t k = 0; k < tm->count; k++) { - const char* key = EL_CSTR(tm->keys[k]); - const char* val = EL_CSTR(tm->values[k]); - if (!key || !val) continue; - if (strcmp(key, "name") == 0) name = val; - else if (strcmp(key, "description") == 0) desc = val; - else if (strcmp(key, "input_schema") == 0) schema = val; - } - } - char* esc_name = json_escape_alloc(name); - char* esc_desc = json_escape_alloc(desc); - jb_puts(b, "{\"name\":\""); jb_puts(b, esc_name); - jb_puts(b, "\",\"description\":\""); jb_puts(b, esc_desc); - jb_puts(b, "\",\"input_schema\":"); jb_puts(b, schema && *schema ? schema : "{}"); - jb_putc(b, '}'); - free(esc_name); free(esc_desc); - } - jb_putc(b, ']'); -} - -/* Walk the assistant `content` array and emit each block back into b, - * preserving the verbatim JSON of every block — used to re-include the - * assistant turn in the next request. */ -static void llm_emit_content_blocks(JsonBuf* b, const char* resp) { - const char* p = json_find_key(resp, "content"); - jb_putc(b, '['); - if (!p) { jb_putc(b, ']'); return; } - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') { jb_putc(b, ']'); return; } - p++; - int first = 1; - while (*p && *p != ']') { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p != '{') break; - const char* end = json_skip_value(p); - if (!first) jb_putc(b, ','); - first = 0; - size_t n = (size_t)(end - p); - jb_reserve(b, n); - memcpy(b->buf + b->len, p, n); - b->len += n; - b->buf[b->len] = '\0'; - p = end; - } - jb_putc(b, ']'); -} - -/* Concatenate all "text" blocks from a response. Returns owned string. */ -static char* llm_concat_text_blocks(const char* resp) { - JsonBuf out; jb_init(&out); - if (!resp) return out.buf; - const char* p = json_find_key(resp, "content"); - if (!p) return out.buf; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') return out.buf; - p++; - while (*p && *p != ']') { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p != '{') break; - const char* end = json_skip_value(p); - size_t n = (size_t)(end - p); - char* obj = malloc(n + 1); - memcpy(obj, p, n); obj[n] = '\0'; - const char* tp = json_find_key(obj, "type"); - if (tp && *tp == '"') { - JsonParser jp = { .p = tp, .end = tp + strlen(tp), .err = 0 }; - char* tname = jp_parse_string_raw(&jp); - if (!jp.err && tname && strcmp(tname, "text") == 0) { - const char* xp = json_find_key(obj, "text"); - if (xp && *xp == '"') { - JsonParser jp2 = { .p = xp, .end = xp + strlen(xp), .err = 0 }; - char* txt = jp_parse_string_raw(&jp2); - if (!jp2.err && txt) jb_puts(&out, txt); - free(txt); - } - } - free(tname); - } - free(obj); - p = end; - } - return out.buf; -} - -/* Build tool_result message blocks for every tool_use in a response. - * Appends to `b` an array element for each tool_use; caller wraps. */ -static int llm_build_tool_results(JsonBuf* b, const char* resp) { - int any = 0; - const char* p = json_find_key(resp, "content"); - if (!p) return 0; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; - if (*p != '[') return 0; - p++; - while (*p && *p != ']') { - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; - if (*p != '{') break; - const char* end = json_skip_value(p); - size_t n = (size_t)(end - p); - char* obj = malloc(n + 1); - memcpy(obj, p, n); obj[n] = '\0'; - - const char* tp = json_find_key(obj, "type"); - char* type_s = NULL; - if (tp && *tp == '"') { - JsonParser jp = { .p = tp, .end = tp + strlen(tp), .err = 0 }; - type_s = jp_parse_string_raw(&jp); - } - if (type_s && strcmp(type_s, "tool_use") == 0) { - /* Extract id, name, input. */ - char* id_s = NULL; char* name_s = NULL; - const char* idp = json_find_key(obj, "id"); - if (idp && *idp == '"') { - JsonParser jp = { .p = idp, .end = idp + strlen(idp), .err = 0 }; - id_s = jp_parse_string_raw(&jp); - } - const char* np = json_find_key(obj, "name"); - if (np && *np == '"') { - JsonParser jp = { .p = np, .end = np + strlen(np), .err = 0 }; - name_s = jp_parse_string_raw(&jp); - } - el_val_t input_raw = json_get_raw(EL_STR(obj), EL_STR("input")); - const char* input_s = EL_CSTR(input_raw); - if (!input_s || !*input_s) input_s = "{}"; - - llm_tool_fn fn = llm_tool_lookup(name_s ? name_s : ""); - char* result = NULL; - int is_error = 0; - if (!fn) { - size_t en = strlen(name_s ? name_s : "(null)") + 64; - result = malloc(en); - snprintf(result, en, "{\"error\":\"tool not registered: %s\"}", - name_s ? name_s : "(null)"); - is_error = 1; - } else { - el_val_t out = fn(EL_STR(input_s)); - const char* os = EL_CSTR(out); - result = el_strdup(os ? os : ""); - } - - if (any) jb_putc(b, ','); - char* esc_id = json_escape_alloc(id_s ? id_s : ""); - char* esc_res = json_escape_alloc(result ? result : ""); - jb_puts(b, "{\"type\":\"tool_result\",\"tool_use_id\":\""); - jb_puts(b, esc_id); - jb_puts(b, "\",\"content\":\""); - jb_puts(b, esc_res); - jb_puts(b, "\""); - if (is_error) jb_puts(b, ",\"is_error\":true"); - jb_putc(b, '}'); - free(esc_id); free(esc_res); free(result); - free(id_s); free(name_s); - any = 1; - } - free(type_s); - free(obj); - p = end; - } - return any; -} - -el_val_t llm_call_agentic(el_val_t model, el_val_t system, el_val_t user, el_val_t tools) { - /* Empty tools list → degrade to plain system call. */ - ElList* tl = (ElList*)(uintptr_t)tools; - if (!tl || tl->length == 0) { - return llm_call_system(model, system, user); - } - const char* m = llm_resolve_model(EL_CSTR(model)); - const char* sys_p = EL_CSTR(system); if (!sys_p) sys_p = ""; - const char* usr_p = EL_CSTR(user); if (!usr_p) usr_p = ""; - - /* Build the static parts: tools JSON and system prompt — these don't - * change across iterations. */ - JsonBuf tools_buf; jb_init(&tools_buf); - llm_emit_tools_json(&tools_buf, tools); - char* esc_sys = json_escape_alloc(sys_p); - - /* messages array, accumulated as a mutable JSON fragment (no surrounding - * brackets — emitted at request time). */ - JsonBuf msgs; jb_init(&msgs); - /* First user message. */ - char* esc_user = json_escape_alloc(usr_p); - jb_puts(&msgs, "{\"role\":\"user\",\"content\":\""); - jb_puts(&msgs, esc_user); - jb_puts(&msgs, "\"}"); - free(esc_user); - - char* last_text = el_strdup(""); - el_val_t final_out = 0; - int reached_cap = 1; - - for (int iter = 0; iter < 10; iter++) { - /* Build request body. */ - JsonBuf body; jb_init(&body); - jb_putc(&body, '{'); - jb_puts(&body, "\"model\":"); jb_emit_escaped(&body, m); - jb_puts(&body, ",\"max_tokens\":4096"); - if (*sys_p) { - jb_puts(&body, ",\"system\":\""); - jb_puts(&body, esc_sys); - jb_puts(&body, "\""); - } - jb_puts(&body, ",\"tools\":"); - jb_puts(&body, tools_buf.buf); - jb_puts(&body, ",\"messages\":["); - jb_puts(&body, msgs.buf); - jb_puts(&body, "]}"); - - el_val_t resp_v = llm_request(body.buf); - free(body.buf); - const char* resp = EL_CSTR(resp_v); - if (!resp || !*resp) { - final_out = http_error_json("empty response"); - reached_cap = 0; - break; - } - if (resp[0] == '{' && strstr(resp, "\"error\"") && - !json_find_key(resp, "content")) { - final_out = el_wrap_str(el_strdup(resp)); - reached_cap = 0; - break; - } - - /* Update last_text from this response. */ - free(last_text); - last_text = llm_concat_text_blocks(resp); - - /* Inspect stop_reason. */ - el_val_t sr_v = json_get_string(EL_STR(resp), EL_STR("stop_reason")); - const char* sr = EL_CSTR(sr_v); if (!sr) sr = ""; - - if (strcmp(sr, "end_turn") == 0) { - final_out = el_wrap_str(el_strdup(last_text)); - reached_cap = 0; - break; - } - if (strcmp(sr, "max_tokens") == 0) { - size_t ln = strlen(last_text) + 16; - char* out = malloc(ln); - snprintf(out, ln, "%s\n[truncated]", last_text); - final_out = el_wrap_str(out); - reached_cap = 0; - break; - } - if (strcmp(sr, "tool_use") != 0) { - /* Unexpected stop reason; return the text we have. */ - final_out = el_wrap_str(el_strdup(last_text)); - reached_cap = 0; - break; - } - - /* Append the assistant turn (raw content blocks) to messages. */ - JsonBuf ab; jb_init(&ab); - jb_puts(&ab, ",{\"role\":\"assistant\",\"content\":"); - llm_emit_content_blocks(&ab, resp); - jb_putc(&ab, '}'); - jb_puts(&msgs, ab.buf); - free(ab.buf); - - /* Build tool_result message. */ - JsonBuf tr; jb_init(&tr); - jb_puts(&tr, ",{\"role\":\"user\",\"content\":["); - int any = llm_build_tool_results(&tr, resp); - jb_puts(&tr, "]}"); - if (any) { - jb_puts(&msgs, tr.buf); - } - free(tr.buf); - } - - if (reached_cap) { - size_t ln = strlen(last_text) + 32; - char* out = malloc(ln); - snprintf(out, ln, "[loop_cap_reached]\n%s", last_text); - final_out = el_wrap_str(out); - } - free(last_text); - free(esc_sys); - free(tools_buf.buf); - free(msgs.buf); - return final_out; -} - -/* base64-encode arbitrary bytes (returns owned C string). - * Internal helper for llm_vision; the public crypto entry point that El - * programs call is `base64_encode(el_val_t)` defined in the crypto block - * at the end of this file. */ -static char* el_b64_encode_internal(const unsigned char* src, size_t n) { - static const char tbl[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - size_t out_len = 4 * ((n + 2) / 3); - char* out = malloc(out_len + 1); - if (!out) return NULL; - size_t o = 0; - for (size_t i = 0; i < n;) { - uint32_t v = 0; int got = 0; - v |= (uint32_t)src[i++] << 16; got++; - if (i < n) { v |= (uint32_t)src[i++] << 8; got++; } - if (i < n) { v |= (uint32_t)src[i++]; got++; } - out[o++] = tbl[(v >> 18) & 0x3f]; - out[o++] = tbl[(v >> 12) & 0x3f]; - out[o++] = (got > 1) ? tbl[(v >> 6) & 0x3f] : '='; - out[o++] = (got > 2) ? tbl[v & 0x3f] : '='; - } - out[o] = '\0'; - return out; -} - -el_val_t llm_vision(el_val_t model, el_val_t system, el_val_t prompt, el_val_t image_url_or_b64) { - const char* m = llm_resolve_model(EL_CSTR(model)); - const char* s = EL_CSTR(system); if (!s) s = ""; - const char* u = EL_CSTR(prompt); if (!u) u = ""; - const char* img = EL_CSTR(image_url_or_b64); if (!img) img = ""; - - /* Choose source mode */ - char* image_block = NULL; - if (strncasecmp(img, "http://", 7) == 0 || strncasecmp(img, "https://", 8) == 0) { - char* esc_url = json_escape_alloc(img); - size_t n = strlen(esc_url) + 128; - image_block = malloc(n); - snprintf(image_block, n, - "{\"type\":\"image\",\"source\":{\"type\":\"url\",\"url\":\"%s\"}}", - esc_url); - free(esc_url); - } else if (strncmp(img, "data:", 5) == 0) { - /* Inline data URL: split media-type and base64 */ - const char* semi = strchr(img + 5, ';'); - const char* comma = strchr(img + 5, ','); - char media[64] = "image/png"; - if (semi && comma && semi < comma) { - size_t ml = (size_t)(semi - (img + 5)); - if (ml >= sizeof(media)) ml = sizeof(media) - 1; - memcpy(media, img + 5, ml); media[ml] = '\0'; - } - const char* b64 = comma ? comma + 1 : ""; - char* esc_media = json_escape_alloc(media); - char* esc_b64 = json_escape_alloc(b64); - size_t n = strlen(esc_media) + strlen(esc_b64) + 192; - image_block = malloc(n); - snprintf(image_block, n, - "{\"type\":\"image\",\"source\":{\"type\":\"base64\"," - "\"media_type\":\"%s\",\"data\":\"%s\"}}", - esc_media, esc_b64); - free(esc_media); free(esc_b64); - } else if (*img) { - /* Treat as file path: read, base64-encode, attach. */ - FILE* f = fopen(img, "rb"); - if (!f) { - char err[256]; snprintf(err, sizeof(err), "cannot open image: %s", img); - return http_error_json(err); - } - fseek(f, 0, SEEK_END); - long sz = ftell(f); - rewind(f); - if (sz <= 0) { fclose(f); return http_error_json("empty image file"); } - unsigned char* buf = malloc((size_t)sz); - if (!buf) { fclose(f); return http_error_json("oom"); } - size_t got = fread(buf, 1, (size_t)sz, f); - fclose(f); - char* b64 = el_b64_encode_internal(buf, got); - free(buf); - if (!b64) return http_error_json("base64 encode failed"); - const char* media = "image/png"; - size_t ilen = strlen(img); - if (ilen >= 4) { - if (strcasecmp(img + ilen - 4, ".jpg") == 0 || - (ilen >= 5 && strcasecmp(img + ilen - 5, ".jpeg") == 0)) media = "image/jpeg"; - else if (strcasecmp(img + ilen - 4, ".gif") == 0) media = "image/gif"; - else if (strcasecmp(img + ilen - 4, ".webp") == 0) media = "image/webp"; - } - char* esc_b64 = json_escape_alloc(b64); free(b64); - size_t n = strlen(esc_b64) + 192; - image_block = malloc(n); - snprintf(image_block, n, - "{\"type\":\"image\",\"source\":{\"type\":\"base64\"," - "\"media_type\":\"%s\",\"data\":\"%s\"}}", - media, esc_b64); - free(esc_b64); - } - - char* esc_sys = json_escape_alloc(s); - char* esc_user = json_escape_alloc(u); - JsonBuf b; jb_init(&b); - jb_putc(&b, '{'); - jb_puts(&b, "\"model\":"); jb_emit_escaped(&b, m); - jb_puts(&b, ",\"max_tokens\":4096"); - if (*s) { - jb_puts(&b, ",\"system\":\""); - jb_puts(&b, esc_sys); - jb_puts(&b, "\""); - } - jb_puts(&b, ",\"messages\":[{\"role\":\"user\",\"content\":["); - if (image_block) { - jb_puts(&b, image_block); - jb_putc(&b, ','); - } - jb_puts(&b, "{\"type\":\"text\",\"text\":\""); - jb_puts(&b, esc_user); - jb_puts(&b, "\"}]}]}"); - free(esc_sys); free(esc_user); free(image_block); - el_val_t resp = llm_request(b.buf); - free(b.buf); - return llm_extract_text(resp); -} - -el_val_t llm_models(void) { - el_val_t lst = el_list_empty(); - lst = el_list_append(lst, el_wrap_str(el_strdup("claude-sonnet-4-5"))); - lst = el_list_append(lst, el_wrap_str(el_strdup("claude-opus-4-7"))); - lst = el_list_append(lst, el_wrap_str(el_strdup("claude-haiku-4-5"))); - return lst; -} - -/* ── Native VM builtin aliases ────────────────────────────────────────────── - * El source files use native_* names (El VM builtins). - * When compiled to C, these map directly to el_* runtime functions. */ - -el_val_t native_list_get(el_val_t list, el_val_t index) { - return el_list_get(list, index); -} - -el_val_t native_list_len(el_val_t list) { - return el_list_len(list); -} - -el_val_t native_list_append(el_val_t list, el_val_t elem) { - return el_list_append(list, elem); -} - -el_val_t native_list_empty(void) { - return el_list_empty(); -} - -el_val_t native_list_clone(el_val_t list) { - return el_list_clone(list); -} - -el_val_t native_string_chars(el_val_t sv) { - const char* s = EL_CSTR(sv); - el_val_t result = el_list_empty(); - if (!s) return result; - while (*s) { - char buf[2]; - buf[0] = *s; - buf[1] = '\0'; - result = el_list_append(result, EL_STR(strdup(buf))); - s++; - } - return result; -} - -el_val_t native_int_to_str(el_val_t n) { - return int_to_str(n); -} - -/* ── Method-call shorthand aliases ────────────────────────────────────────── - * Short names that result from the method-call convention: - * myList.append(x) → append(myList, x) - * myList.len() → len(myList) - * myList.get(i) → get(myList, i) - * myMap.map_get(k) → map_get(myMap, k) - * myMap.map_set(k,v) → map_set(myMap, k, v) */ - -el_val_t append(el_val_t list, el_val_t elem) { return el_list_append(list, elem); } -el_val_t len(el_val_t list) { return el_list_len(list); } -el_val_t get(el_val_t list, el_val_t index) { return el_list_get(list, index); } -el_val_t map_get(el_val_t map, el_val_t key) { return el_map_get(map, key); } -el_val_t map_set(el_val_t map, el_val_t key, el_val_t value) { return el_map_set(map, key, value); } - -/* ── Crypto primitives ────────────────────────────────────────────────────── - * - * SHA-256 implementation adapted from Brad Conte's public-domain reference - * (https://github.com/B-Con/crypto-algorithms/blob/master/sha256.c, public - * domain per the project's LICENSE). HMAC follows RFC 2104. Base64 encoding - * follows RFC 4648; the URL-safe variant uses the alphabet from §5 of the - * RFC and omits padding (per JWT/JWS convention). - * - * Self-contained: no OpenSSL/libcrypto dependency. The runtime keeps its - * existing `-lcurl -lpthread -ldl -lm` link line. - * - * Binary outputs (sha256_bytes, hmac_sha256_bytes) tag their buffer with a - * magic header so base64_encode/base64url_encode can recover the exact byte - * length even when the payload contains embedded NULs. Plain C strings - * (without the header) fall back to strlen(), preserving the existing API - * shape for normal text inputs. */ - -/* Magic-header for length-tagged binary buffers. Layout: - * [ uint32_t magic = EL_MAGIC_BIN ][ uint32_t length ][ data... ][ \0 ] - * The returned el_val_t points at `data`, so consumers that strlen() it still - * get a sensible (though possibly truncated) view. el_bin_len() recovers the - * true length by sniffing the 8 bytes preceding the pointer. - * - * Magic value chosen with high MSB so it cannot collide with printable ASCII - * (the same discriminator pattern used by EL_MAGIC_LIST / EL_MAGIC_MAP). */ -#define EL_MAGIC_BIN 0xE1B17EAFu - -typedef struct { - uint32_t magic; - uint32_t length; -} el_bin_hdr_t; - -/* Allocate a length-tagged binary buffer; returns pointer to the data area. */ -static unsigned char* el_bin_alloc(size_t len) { - el_bin_hdr_t* hdr = (el_bin_hdr_t*)malloc(sizeof(el_bin_hdr_t) + len + 1); - if (!hdr) { fputs("el_runtime: out of memory (bin)\n", stderr); exit(1); } - hdr->magic = EL_MAGIC_BIN; - hdr->length = (uint32_t)len; - unsigned char* data = (unsigned char*)(hdr + 1); - data[len] = '\0'; /* keep NUL-terminated for accidental strlen calls */ - return data; -} - -/* Recover length from a possibly-tagged buffer. Returns 1 if tagged. */ -static int el_bin_lookup(const void* p, size_t* out_len) { - if (!p) { *out_len = 0; return 0; } - /* Avoid reading off the front of a page on tiny pointers (e.g. NULs - * passed in as int-cast values). 4096 is a safe lower bound on any - * platform we target. */ - if ((uintptr_t)p < 4096) return 0; - const el_bin_hdr_t* hdr = (const el_bin_hdr_t*)((const char*)p - sizeof(el_bin_hdr_t)); - if (hdr->magic != EL_MAGIC_BIN) return 0; - *out_len = hdr->length; - return 1; -} - -/* Effective input length: tagged length if present, else strlen. */ -static size_t el_input_len(const char* s) { - size_t n; - if (el_bin_lookup(s, &n)) return n; - return s ? strlen(s) : 0; -} - -/* ─── SHA-256 (Brad Conte / public domain) ──────────────────────────────── */ - -typedef struct { - unsigned char data[64]; - uint32_t datalen; - uint64_t bitlen; - uint32_t state[8]; -} el_sha256_ctx_t; - -static const uint32_t el_sha256_k[64] = { - 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, - 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, - 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, - 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, - 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, - 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, - 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, - 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 -}; - -#define EL_ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) -#define EL_CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) -#define EL_MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -#define EL_EP0(x) (EL_ROTR(x,2) ^ EL_ROTR(x,13) ^ EL_ROTR(x,22)) -#define EL_EP1(x) (EL_ROTR(x,6) ^ EL_ROTR(x,11) ^ EL_ROTR(x,25)) -#define EL_SIG0(x) (EL_ROTR(x,7) ^ EL_ROTR(x,18) ^ ((x) >> 3)) -#define EL_SIG1(x) (EL_ROTR(x,17) ^ EL_ROTR(x,19) ^ ((x) >> 10)) - -static void el_sha256_transform(el_sha256_ctx_t* ctx, const unsigned char* data) { - uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64]; - int i, j; - for (i = 0, j = 0; i < 16; ++i, j += 4) { - m[i] = ((uint32_t)data[j] << 24) | ((uint32_t)data[j + 1] << 16) - | ((uint32_t)data[j + 2] << 8) | (uint32_t)data[j + 3]; - } - for (; i < 64; ++i) { - m[i] = EL_SIG1(m[i-2]) + m[i-7] + EL_SIG0(m[i-15]) + m[i-16]; - } - a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; - e = ctx->state[4]; f = ctx->state[5]; g = ctx->state[6]; h = ctx->state[7]; - for (i = 0; i < 64; ++i) { - t1 = h + EL_EP1(e) + EL_CH(e,f,g) + el_sha256_k[i] + m[i]; - t2 = EL_EP0(a) + EL_MAJ(a,b,c); - h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; - } - ctx->state[0] += a; ctx->state[1] += b; ctx->state[2] += c; ctx->state[3] += d; - ctx->state[4] += e; ctx->state[5] += f; ctx->state[6] += g; ctx->state[7] += h; -} - -static void el_sha256_init(el_sha256_ctx_t* ctx) { - ctx->datalen = 0; - ctx->bitlen = 0; - ctx->state[0] = 0x6a09e667; ctx->state[1] = 0xbb67ae85; - ctx->state[2] = 0x3c6ef372; ctx->state[3] = 0xa54ff53a; - ctx->state[4] = 0x510e527f; ctx->state[5] = 0x9b05688c; - ctx->state[6] = 0x1f83d9ab; ctx->state[7] = 0x5be0cd19; -} - -static void el_sha256_update(el_sha256_ctx_t* ctx, const unsigned char* data, size_t len) { - for (size_t i = 0; i < len; ++i) { - ctx->data[ctx->datalen++] = data[i]; - if (ctx->datalen == 64) { - el_sha256_transform(ctx, ctx->data); - ctx->bitlen += 512; - ctx->datalen = 0; - } - } -} - -static void el_sha256_final(el_sha256_ctx_t* ctx, unsigned char hash[32]) { - uint32_t i = ctx->datalen; - if (ctx->datalen < 56) { - ctx->data[i++] = 0x80; - while (i < 56) ctx->data[i++] = 0x00; - } else { - ctx->data[i++] = 0x80; - while (i < 64) ctx->data[i++] = 0x00; - el_sha256_transform(ctx, ctx->data); - memset(ctx->data, 0, 56); - } - ctx->bitlen += (uint64_t)ctx->datalen * 8; - ctx->data[63] = (unsigned char)( ctx->bitlen & 0xff); - ctx->data[62] = (unsigned char)((ctx->bitlen >> 8) & 0xff); - ctx->data[61] = (unsigned char)((ctx->bitlen >> 16) & 0xff); - ctx->data[60] = (unsigned char)((ctx->bitlen >> 24) & 0xff); - ctx->data[59] = (unsigned char)((ctx->bitlen >> 32) & 0xff); - ctx->data[58] = (unsigned char)((ctx->bitlen >> 40) & 0xff); - ctx->data[57] = (unsigned char)((ctx->bitlen >> 48) & 0xff); - ctx->data[56] = (unsigned char)((ctx->bitlen >> 56) & 0xff); - el_sha256_transform(ctx, ctx->data); - for (i = 0; i < 4; ++i) { - hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0xff; - hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0xff; - hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0xff; - hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0xff; - hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0xff; - hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0xff; - hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0xff; - hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0xff; - } -} - -static void el_sha256_oneshot(const unsigned char* data, size_t len, unsigned char out[32]) { - el_sha256_ctx_t c; - el_sha256_init(&c); - el_sha256_update(&c, data, len); - el_sha256_final(&c, out); -} - -/* ─── HMAC-SHA-256 (RFC 2104) ───────────────────────────────────────────── */ - -static void el_hmac_sha256(const unsigned char* key, size_t key_len, - const unsigned char* msg, size_t msg_len, - unsigned char out[32]) { - unsigned char k[64]; - unsigned char k_ipad[64]; - unsigned char k_opad[64]; - unsigned char inner[32]; - - if (key_len > 64) { - el_sha256_oneshot(key, key_len, k); - memset(k + 32, 0, 32); - } else { - memcpy(k, key, key_len); - memset(k + key_len, 0, 64 - key_len); - } - for (int i = 0; i < 64; ++i) { - k_ipad[i] = k[i] ^ 0x36; - k_opad[i] = k[i] ^ 0x5c; - } - { - el_sha256_ctx_t c; - el_sha256_init(&c); - el_sha256_update(&c, k_ipad, 64); - el_sha256_update(&c, msg, msg_len); - el_sha256_final(&c, inner); - } - { - el_sha256_ctx_t c; - el_sha256_init(&c); - el_sha256_update(&c, k_opad, 64); - el_sha256_update(&c, inner, 32); - el_sha256_final(&c, out); - } -} - -/* ─── Hex helper ────────────────────────────────────────────────────────── */ - -static el_val_t el_hex_encode(const unsigned char* data, size_t len) { - static const char digits[] = "0123456789abcdef"; - char* out = el_strbuf(len * 2); - for (size_t i = 0; i < len; ++i) { - out[i * 2] = digits[(data[i] >> 4) & 0xf]; - out[i * 2 + 1] = digits[ data[i] & 0xf]; - } - out[len * 2] = '\0'; - return el_wrap_str(out); -} - -/* ─── Base64 (RFC 4648) ─────────────────────────────────────────────────── */ - -static const char el_b64_std_alphabet[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char el_b64_url_alphabet[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - -el_val_t el_base64_encode_n(const unsigned char* data, size_t len, int url_safe) { - const char* alphabet = url_safe ? el_b64_url_alphabet : el_b64_std_alphabet; - /* Standard form is padded to multiple of 4; URL-safe omits padding. */ - size_t out_cap = ((len + 2) / 3) * 4 + 1; - char* out = el_strbuf(out_cap); - size_t i = 0, j = 0; - while (i + 3 <= len) { - uint32_t v = ((uint32_t)data[i] << 16) | ((uint32_t)data[i+1] << 8) | (uint32_t)data[i+2]; - out[j++] = alphabet[(v >> 18) & 0x3f]; - out[j++] = alphabet[(v >> 12) & 0x3f]; - out[j++] = alphabet[(v >> 6) & 0x3f]; - out[j++] = alphabet[ v & 0x3f]; - i += 3; - } - size_t rem = len - i; - if (rem == 1) { - uint32_t v = (uint32_t)data[i] << 16; - out[j++] = alphabet[(v >> 18) & 0x3f]; - out[j++] = alphabet[(v >> 12) & 0x3f]; - if (!url_safe) { out[j++] = '='; out[j++] = '='; } - } else if (rem == 2) { - uint32_t v = ((uint32_t)data[i] << 16) | ((uint32_t)data[i+1] << 8); - out[j++] = alphabet[(v >> 18) & 0x3f]; - out[j++] = alphabet[(v >> 12) & 0x3f]; - out[j++] = alphabet[(v >> 6) & 0x3f]; - if (!url_safe) { out[j++] = '='; } - } - out[j] = '\0'; - return el_wrap_str(out); -} - -/* Decode either alphabet — accepts both '+/' and '-_' transparently, and - * tolerates missing padding (which JWTs typically omit). Whitespace is - * skipped for robustness. Invalid characters cause the decode to stop and - * the partial result so far is returned. */ -static el_val_t el_base64_decode_any(const char* in) { - if (!in) { - unsigned char* empty = el_bin_alloc(0); - return EL_STR((char*)empty); - } - size_t in_len = strlen(in); - /* Worst case: 3 output bytes per 4 input chars, +1 NUL slack. */ - unsigned char* out = el_bin_alloc(((in_len + 3) / 4) * 3 + 1); - - int8_t lut[256]; - for (int i = 0; i < 256; ++i) lut[i] = -1; - for (int i = 0; i < 64; ++i) lut[(unsigned char)el_b64_std_alphabet[i]] = (int8_t)i; - /* Allow URL-safe characters too (so one decoder handles both forms). */ - lut[(unsigned char)'-'] = 62; - lut[(unsigned char)'_'] = 63; - - uint32_t buf = 0; - int bits = 0; - size_t o = 0; - for (size_t i = 0; i < in_len; ++i) { - unsigned char c = (unsigned char)in[i]; - if (c == '=' || c == '\r' || c == '\n' || c == ' ' || c == '\t') continue; - int8_t v = lut[c]; - if (v < 0) break; /* invalid char — stop */ - buf = (buf << 6) | (uint32_t)v; - bits += 6; - if (bits >= 8) { - bits -= 8; - out[o++] = (unsigned char)((buf >> bits) & 0xff); - } - } - /* Patch the length header to the actual decoded length. */ - el_bin_hdr_t* hdr = (el_bin_hdr_t*)((char*)out - sizeof(el_bin_hdr_t)); - hdr->length = (uint32_t)o; - out[o] = '\0'; - return EL_STR((char*)out); -} - -/* ─── Public crypto entry points ────────────────────────────────────────── */ - -el_val_t el_sha256_bytes_n(const unsigned char* data, size_t len) { - unsigned char* out = el_bin_alloc(32); - el_sha256_oneshot(data, len, out); - return EL_STR((char*)out); -} - -el_val_t sha256_hex(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - unsigned char digest[32]; - el_sha256_oneshot((const unsigned char*)(s ? s : ""), n, digest); - return el_hex_encode(digest, 32); -} - -el_val_t sha256_bytes(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - return el_sha256_bytes_n((const unsigned char*)(s ? s : ""), n); -} - -el_val_t hmac_sha256_hex(el_val_t key, el_val_t message) { - const char* k = EL_CSTR(key); - const char* m = EL_CSTR(message); - size_t kn = el_input_len(k); - size_t mn = el_input_len(m); - unsigned char mac[32]; - el_hmac_sha256((const unsigned char*)(k ? k : ""), kn, - (const unsigned char*)(m ? m : ""), mn, - mac); - return el_hex_encode(mac, 32); -} - -el_val_t hmac_sha256_bytes(el_val_t key, el_val_t message) { - const char* k = EL_CSTR(key); - const char* m = EL_CSTR(message); - size_t kn = el_input_len(k); - size_t mn = el_input_len(m); - unsigned char* out = el_bin_alloc(32); - el_hmac_sha256((const unsigned char*)(k ? k : ""), kn, - (const unsigned char*)(m ? m : ""), mn, - out); - return EL_STR((char*)out); -} - -el_val_t base64_encode(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - return el_base64_encode_n((const unsigned char*)(s ? s : ""), n, /*url_safe=*/0); -} - -el_val_t base64url_encode(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - return el_base64_encode_n((const unsigned char*)(s ? s : ""), n, /*url_safe=*/1); -} - -el_val_t base64_decode(el_val_t input) { - return el_base64_decode_any(EL_CSTR(input)); -} - -el_val_t base64url_decode(el_val_t input) { - return el_base64_decode_any(EL_CSTR(input)); -} - -/* ── Post-quantum cryptography (liboqs + OpenSSL) ─────────────────────────── - * - * Algorithm choices (per CNSA 2.0 / NIST PQ guidance, as of 2024): - * Signatures: CRYSTALS-Dilithium-3 (NIST security level 3, balanced) - * KEM: CRYSTALS-Kyber-768 (NIST security level 3) - * Hash: SHA3-256 (Keccak) (PQ-aware protocols favour SHA3 over SHA2) - * Hybrid: X25519 || Kyber-768, combined via HKDF-SHA256 - * - * Why hybrid: Kyber is new. X25519 has 20+ years of analysis. Hybridizing - * preserves classical security if Kyber falls to a future cryptanalytic - * advance, and preserves PQ security if X25519 falls to a quantum adversary. - * "Recordable now, decryptable later" already threatens long-lived classical - * key exchange — the only safe move for keys protecting durable doctrine - * (CGI lineage, KindredGrants, Principal-CGI covenants) is to encapsulate - * with PQ today, even if the classical leg is what the wire shows. - * - * Compile-time detection: when is unavailable the pq_* functions - * compile to stubs that return a JSON error envelope. SHA3-256 stays - * available regardless (it's implemented inline, no liboqs dep). This lets - * the runtime build cleanly on dev machines without liboqs while production - * gets the full PQ stack. */ - -/* ─── SHA3-256 (Keccak, FIPS 202) ──────────────────────────────────────────── - * Inline reference implementation. ~120 LoC, no external dependency. - * rate=1088 bits, capacity=512 bits, output=256 bits, padding=0x06. */ - -static const uint64_t el_keccak_rc[24] = { - 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL, - 0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL, - 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL, - 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL, - 0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, - 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL, - 0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL, - 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL -}; - -static const unsigned el_keccak_rho[24] = { - 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 -}; - -static const unsigned el_keccak_pi[24] = { - 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 -}; - -#define EL_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n)))) - -static void el_keccak_f1600(uint64_t s[25]) { - for (int round = 0; round < 24; ++round) { - uint64_t bc[5], t; - for (int i = 0; i < 5; ++i) - bc[i] = s[i] ^ s[i+5] ^ s[i+10] ^ s[i+15] ^ s[i+20]; - for (int i = 0; i < 5; ++i) { - t = bc[(i+4) % 5] ^ EL_ROTL64(bc[(i+1) % 5], 1); - for (int j = 0; j < 25; j += 5) s[j+i] ^= t; - } - t = s[1]; - for (int i = 0; i < 24; ++i) { - int j = el_keccak_pi[i]; - bc[0] = s[j]; - s[j] = EL_ROTL64(t, el_keccak_rho[i]); - t = bc[0]; - } - for (int j = 0; j < 25; j += 5) { - for (int i = 0; i < 5; ++i) bc[i] = s[j+i]; - for (int i = 0; i < 5; ++i) - s[j+i] = bc[i] ^ ((~bc[(i+1) % 5]) & bc[(i+2) % 5]); - } - s[0] ^= el_keccak_rc[round]; - } -} - -static void el_sha3_256_oneshot(const unsigned char* data, size_t len, - unsigned char out[32]) { - uint64_t st[25] = {0}; - unsigned char* sb = (unsigned char*)st; - const size_t rate = 136; /* 1088 bits / 8 */ - size_t i = 0; - while (len - i >= rate) { - for (size_t k = 0; k < rate; ++k) sb[k] ^= data[i + k]; - el_keccak_f1600(st); - i += rate; - } - size_t rem = len - i; - for (size_t k = 0; k < rem; ++k) sb[k] ^= data[i + k]; - sb[rem] ^= 0x06; /* SHA3 domain-separation byte */ - sb[rate - 1] ^= 0x80; /* final-block padding bit (high bit of last byte) */ - el_keccak_f1600(st); - memcpy(out, sb, 32); -} - -el_val_t sha3_256_hex(el_val_t input) { - const char* s = EL_CSTR(input); - size_t n = el_input_len(s); - unsigned char digest[32]; - el_sha3_256_oneshot((const unsigned char*)(s ? s : ""), n, digest); - return el_hex_encode(digest, 32); -} - -/* ─── Hex decode helper ───────────────────────────────────────────────────── - * Returns a length-tagged binary buffer (so embedded NULs survive); on - * odd-length / invalid input returns NULL with *out_len = 0. Caller is - * responsible for emitting the error envelope. */ - -static int el_hex_nibble(char c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'a' && c <= 'f') return c - 'a' + 10; - if (c >= 'A' && c <= 'F') return c - 'A' + 10; - return -1; -} - -__attribute__((unused)) -static unsigned char* el_hex_decode(const char* s, size_t* out_len) { - *out_len = 0; - if (!s) return NULL; - size_t n = strlen(s); - if (n & 1) return NULL; - size_t blen = n / 2; - unsigned char* out = el_bin_alloc(blen); - for (size_t i = 0; i < blen; ++i) { - int hi = el_hex_nibble(s[i*2]); - int lo = el_hex_nibble(s[i*2 + 1]); - if (hi < 0 || lo < 0) return NULL; - out[i] = (unsigned char)((hi << 4) | lo); - } - *out_len = blen; - return out; -} - -/* JSON error envelope reused across all PQ entry points. */ -static el_val_t pq_error(const char* msg) { - return http_error_json(msg); -} - -#if __has_include() -#include -#define EL_HAVE_LIBOQS 1 -#else -#define EL_HAVE_LIBOQS 0 -#endif - -#if EL_HAVE_LIBOQS && __has_include() -#include -#define EL_HAVE_OPENSSL 1 -#else -#define EL_HAVE_OPENSSL 0 -#endif - -#if !EL_HAVE_LIBOQS - -/* ─── Stubs (liboqs unavailable) ─────────────────────────────────────────── - * Each entry point returns the same JSON error so callers can inspect a - * single canonical "missing primitive" string. pq_verify is the lone - * exception — verifying without liboqs simply means "not verified", so - * returning Bool false (0) keeps the type contract intact. */ - -#define EL_PQ_NO_LIB "liboqs not linked, post-quantum primitives unavailable" - -el_val_t pq_keygen_signature(void) { return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_sign(el_val_t sk, el_val_t msg) { (void)sk; (void)msg; return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_verify(el_val_t pk, el_val_t msg, el_val_t sig) { (void)pk; (void)msg; (void)sig; return EL_INT(0); } -el_val_t pq_kem_keygen(void) { return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_kem_encaps(el_val_t pk) { (void)pk; return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_kem_decaps(el_val_t sk, el_val_t ct) { (void)sk; (void)ct; return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_hybrid_keygen(void) { return pq_error(EL_PQ_NO_LIB); } -el_val_t pq_hybrid_handshake(el_val_t pub) { (void)pub; return pq_error(EL_PQ_NO_LIB); } - -#else /* EL_HAVE_LIBOQS */ - -/* ─── Dilithium-3 / ML-DSA-65 signatures ──────────────────────────────── - * - * NIST FIPS 204 standardized CRYSTALS-Dilithium as ML-DSA. ML-DSA-65 is the - * FIPS form of what we historically called Dilithium-3 — same algorithm - * family, same security level, identical key/sig sizes, but with a couple - * of standardization-driven tweaks (e.g. domain separation in the message - * binding). liboqs 0.12+ exposes both names; 0.15+ retired the legacy - * "Dilithium" constants in favour of "ML-DSA". We prefer ML-DSA-65 if the - * header advertises it, fall back to Dilithium-3 otherwise. Anything - * already signed with the older constant remains verifiable against that - * same constant — callers should pin the algorithm via the OQS_SIG handle's - * method_name field if they need to interoperate with archival signatures. */ - -#if defined(OQS_SIG_alg_ml_dsa_65) -# define EL_DILITHIUM_ALG OQS_SIG_alg_ml_dsa_65 -#elif defined(OQS_SIG_alg_dilithium_3) -# define EL_DILITHIUM_ALG OQS_SIG_alg_dilithium_3 -#else -# define EL_DILITHIUM_ALG "ML-DSA-65" /* string fallback; runtime probe catches misconfig */ -#endif - -el_val_t pq_keygen_signature(void) { - OQS_SIG* sig = OQS_SIG_new(EL_DILITHIUM_ALG); - if (!sig) return pq_error("OQS_SIG_new(dilithium-3) failed"); - unsigned char* pk = (unsigned char*)malloc(sig->length_public_key); - unsigned char* sk = (unsigned char*)malloc(sig->length_secret_key); - if (!pk || !sk) { free(pk); free(sk); OQS_SIG_free(sig); return pq_error("oom"); } - if (OQS_SIG_keypair(sig, pk, sk) != OQS_SUCCESS) { - free(pk); free(sk); OQS_SIG_free(sig); - return pq_error("dilithium-3 keypair generation failed"); - } - el_val_t pk_hex = el_hex_encode(pk, sig->length_public_key); - el_val_t sk_hex = el_hex_encode(sk, sig->length_secret_key); - OQS_MEM_secure_free(sk, sig->length_secret_key); - free(pk); - - const char* pks = EL_CSTR(pk_hex); - const char* sks = EL_CSTR(sk_hex); - char* buf = el_strbuf(strlen(pks) + strlen(sks) + 64); - sprintf(buf, "{\"public_key\":\"%s\",\"secret_key\":\"%s\"}", pks, sks); - OQS_SIG_free(sig); - return el_wrap_str(buf); -} - -el_val_t pq_sign(el_val_t secret_key_hex, el_val_t message) { - size_t sk_len = 0; - unsigned char* sk = el_hex_decode(EL_CSTR(secret_key_hex), &sk_len); - if (!sk) return pq_error("invalid hex in secret_key"); - - OQS_SIG* sig = OQS_SIG_new(EL_DILITHIUM_ALG); - if (!sig) return pq_error("OQS_SIG_new(dilithium-3) failed"); - if (sk_len != sig->length_secret_key) { - OQS_SIG_free(sig); - return pq_error("secret_key length mismatch for dilithium-3"); - } - - const char* msg = EL_CSTR(message); - size_t msg_len = el_input_len(msg); - unsigned char* signature = (unsigned char*)malloc(sig->length_signature); - size_t signature_len = sig->length_signature; - if (!signature) { OQS_SIG_free(sig); return pq_error("oom"); } - - if (OQS_SIG_sign(sig, signature, &signature_len, - (const unsigned char*)(msg ? msg : ""), msg_len, sk) != OQS_SUCCESS) { - free(signature); OQS_SIG_free(sig); - return pq_error("dilithium-3 sign failed"); - } - el_val_t sig_hex = el_hex_encode(signature, signature_len); - free(signature); OQS_SIG_free(sig); - return sig_hex; -} - -el_val_t pq_verify(el_val_t public_key_hex, el_val_t message, el_val_t signature_hex) { - size_t pk_len = 0, sig_len = 0; - unsigned char* pk = el_hex_decode(EL_CSTR(public_key_hex), &pk_len); - unsigned char* signature = el_hex_decode(EL_CSTR(signature_hex), &sig_len); - if (!pk || !signature) return EL_INT(0); - - OQS_SIG* sig = OQS_SIG_new(EL_DILITHIUM_ALG); - if (!sig) return EL_INT(0); - if (pk_len != sig->length_public_key) { OQS_SIG_free(sig); return EL_INT(0); } - - const char* msg = EL_CSTR(message); - size_t msg_len = el_input_len(msg); - OQS_STATUS rc = OQS_SIG_verify(sig, - (const unsigned char*)(msg ? msg : ""), msg_len, - signature, sig_len, pk); - OQS_SIG_free(sig); - return (rc == OQS_SUCCESS) ? EL_INT(1) : EL_INT(0); -} - -/* ─── Kyber-768 / ML-KEM-768 KEM ──────────────────────────────────────── - * - * NIST FIPS 203 standardized CRYSTALS-Kyber as ML-KEM. ML-KEM-768 is the - * FIPS form of what we historically called Kyber-768. Same situation as - * Dilithium → ML-DSA: prefer the standardized constant, fall back to the - * legacy name. liboqs 0.15.0 still exposes OQS_KEM_alg_kyber_768; the - * algorithm is identical at the wire level to ML-KEM-768 except for FIPS - * domain-separation tweaks, so the two ciphertexts/keys are NOT - * cross-compatible. Pin the constant for archival material. */ - -#if defined(OQS_KEM_alg_ml_kem_768) -# define EL_KYBER_ALG OQS_KEM_alg_ml_kem_768 -#elif defined(OQS_KEM_alg_kyber_768) -# define EL_KYBER_ALG OQS_KEM_alg_kyber_768 -#else -# define EL_KYBER_ALG "ML-KEM-768" -#endif - -el_val_t pq_kem_keygen(void) { - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - unsigned char* pk = (unsigned char*)malloc(kem->length_public_key); - unsigned char* sk = (unsigned char*)malloc(kem->length_secret_key); - if (!pk || !sk) { free(pk); free(sk); OQS_KEM_free(kem); return pq_error("oom"); } - if (OQS_KEM_keypair(kem, pk, sk) != OQS_SUCCESS) { - free(pk); free(sk); OQS_KEM_free(kem); - return pq_error("kyber-768 keypair generation failed"); - } - el_val_t pk_hex = el_hex_encode(pk, kem->length_public_key); - el_val_t sk_hex = el_hex_encode(sk, kem->length_secret_key); - OQS_MEM_secure_free(sk, kem->length_secret_key); - free(pk); - - const char* pks = EL_CSTR(pk_hex); - const char* sks = EL_CSTR(sk_hex); - char* buf = el_strbuf(strlen(pks) + strlen(sks) + 64); - sprintf(buf, "{\"public_key\":\"%s\",\"secret_key\":\"%s\"}", pks, sks); - OQS_KEM_free(kem); - return el_wrap_str(buf); -} - -el_val_t pq_kem_encaps(el_val_t public_key_hex) { - size_t pk_len = 0; - unsigned char* pk = el_hex_decode(EL_CSTR(public_key_hex), &pk_len); - if (!pk) return pq_error("invalid hex in public_key"); - - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - if (pk_len != kem->length_public_key) { - OQS_KEM_free(kem); - return pq_error("public_key length mismatch for kyber-768"); - } - unsigned char* ct = (unsigned char*)malloc(kem->length_ciphertext); - unsigned char* ss = (unsigned char*)malloc(kem->length_shared_secret); - if (!ct || !ss) { free(ct); free(ss); OQS_KEM_free(kem); return pq_error("oom"); } - if (OQS_KEM_encaps(kem, ct, ss, pk) != OQS_SUCCESS) { - free(ct); free(ss); OQS_KEM_free(kem); - return pq_error("kyber-768 encapsulation failed"); - } - el_val_t ct_hex = el_hex_encode(ct, kem->length_ciphertext); - el_val_t ss_hex = el_hex_encode(ss, kem->length_shared_secret); - free(ct); - OQS_MEM_secure_free(ss, kem->length_shared_secret); - - const char* cts = EL_CSTR(ct_hex); - const char* sss = EL_CSTR(ss_hex); - char* buf = el_strbuf(strlen(cts) + strlen(sss) + 64); - sprintf(buf, "{\"ciphertext\":\"%s\",\"shared_secret\":\"%s\"}", cts, sss); - OQS_KEM_free(kem); - return el_wrap_str(buf); -} - -el_val_t pq_kem_decaps(el_val_t secret_key_hex, el_val_t ciphertext_hex) { - size_t sk_len = 0, ct_len = 0; - unsigned char* sk = el_hex_decode(EL_CSTR(secret_key_hex), &sk_len); - unsigned char* ct = el_hex_decode(EL_CSTR(ciphertext_hex), &ct_len); - if (!sk || !ct) return pq_error("invalid hex in inputs"); - - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - if (sk_len != kem->length_secret_key || ct_len != kem->length_ciphertext) { - OQS_KEM_free(kem); - return pq_error("input length mismatch for kyber-768"); - } - unsigned char* ss = (unsigned char*)malloc(kem->length_shared_secret); - if (!ss) { OQS_KEM_free(kem); return pq_error("oom"); } - /* Kyber is IND-CCA via Fujisaki-Okamoto: decaps always returns *some* - * shared_secret even on tampered ciphertext (an implicit-rejection value - * derived from sk). Protocols MUST confirm the shared_secret matches via - * a subsequent step (e.g. AEAD tag, key-confirmation MAC) — do not - * assume decaps success implies authenticity. */ - if (OQS_KEM_decaps(kem, ss, ct, sk) != OQS_SUCCESS) { - free(ss); OQS_KEM_free(kem); - return pq_error("kyber-768 decapsulation failed"); - } - el_val_t ss_hex = el_hex_encode(ss, kem->length_shared_secret); - OQS_MEM_secure_free(ss, kem->length_shared_secret); - OQS_KEM_free(kem); - return ss_hex; -} - -/* ─── Hybrid handshake (X25519 + Kyber-768, HKDF-SHA256 combined) ─────── */ - -#if !EL_HAVE_OPENSSL - -el_val_t pq_hybrid_keygen(void) { - return pq_error("hybrid handshake requires OpenSSL (X25519); rebuild with -lcrypto"); -} -el_val_t pq_hybrid_handshake(el_val_t pub) { - (void)pub; - return pq_error("hybrid handshake requires OpenSSL (X25519); rebuild with -lcrypto"); -} - -#else /* EL_HAVE_OPENSSL */ - -/* HKDF-SHA256 (RFC 5869) — Extract+Expand. Reuses the inline HMAC-SHA256 - * already in this file. Empty salt → 32 zero bytes per the RFC. */ -static void el_hkdf_sha256(const unsigned char* salt, size_t salt_len, - const unsigned char* ikm, size_t ikm_len, - const unsigned char* info, size_t info_len, - unsigned char* out, size_t out_len) { - unsigned char zero_salt[32] = {0}; - if (salt_len == 0) { salt = zero_salt; salt_len = 32; } - unsigned char prk[32]; - el_hmac_sha256(salt, salt_len, ikm, ikm_len, prk); - - unsigned char t[32]; - size_t produced = 0; - unsigned char counter = 1; - unsigned char* buf = (unsigned char*)malloc(32 + info_len + 1); - if (!buf) { fputs("el_runtime: hkdf oom\n", stderr); return; } - while (produced < out_len) { - size_t off = 0; - if (counter > 1) { memcpy(buf, t, 32); off = 32; } - if (info && info_len) { memcpy(buf + off, info, info_len); off += info_len; } - buf[off++] = counter; - el_hmac_sha256(prk, 32, buf, off, t); - size_t chunk = (out_len - produced > 32) ? 32 : (out_len - produced); - memcpy(out + produced, t, chunk); - produced += chunk; - counter++; - } - free(buf); -} - -/* X25519 keygen via OpenSSL EVP. Returns 1 on success. - * Fills pk[32] and sk[32] (raw X25519 byte strings, no DER wrapper). */ -static int el_x25519_keygen(unsigned char pk[32], unsigned char sk[32]) { - EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL); - if (!pctx) return 0; - if (EVP_PKEY_keygen_init(pctx) != 1) { EVP_PKEY_CTX_free(pctx); return 0; } - EVP_PKEY* key = NULL; - if (EVP_PKEY_keygen(pctx, &key) != 1) { EVP_PKEY_CTX_free(pctx); return 0; } - EVP_PKEY_CTX_free(pctx); - - size_t plen = 32, slen = 32; - if (EVP_PKEY_get_raw_public_key (key, pk, &plen) != 1 || plen != 32) { - EVP_PKEY_free(key); return 0; - } - if (EVP_PKEY_get_raw_private_key(key, sk, &slen) != 1 || slen != 32) { - EVP_PKEY_free(key); return 0; - } - EVP_PKEY_free(key); - return 1; -} - -/* X25519 ECDH: derive 32-byte shared secret from local sk and remote pk. */ -static int el_x25519_derive(const unsigned char sk[32], const unsigned char rpk[32], - unsigned char ss[32]) { - EVP_PKEY* my = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, sk, 32); - EVP_PKEY* rem = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, rpk, 32); - if (!my || !rem) { EVP_PKEY_free(my); EVP_PKEY_free(rem); return 0; } - EVP_PKEY_CTX* dctx = EVP_PKEY_CTX_new(my, NULL); - if (!dctx) { EVP_PKEY_free(my); EVP_PKEY_free(rem); return 0; } - int ok = 0; - size_t out_len = 32; - if (EVP_PKEY_derive_init(dctx) == 1 && - EVP_PKEY_derive_set_peer(dctx, rem) == 1 && - EVP_PKEY_derive(dctx, ss, &out_len) == 1 && - out_len == 32) ok = 1; - EVP_PKEY_CTX_free(dctx); - EVP_PKEY_free(my); - EVP_PKEY_free(rem); - return ok; -} - -/* Hybrid wire layout (binary form, before hex encode): - * public_key = x25519_pub (32) || kyber_pub (1184) → 1216 bytes - * secret_key = x25519_sec (32) || kyber_sec (2400) → 2432 bytes - * ciphertext = ephem_x25519_pub (32) || kyber_ct (1088) → 1120 bytes - * shared_secret = HKDF-SHA256(x25519_ss || kyber_ss, info="el-pq-hybrid-v1", 32 bytes) - * The keygen result also exposes the four component hex fields for callers - * that prefer to handle the legs independently. */ - -el_val_t pq_hybrid_keygen(void) { - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - - unsigned char xpk[32], xsk[32]; - if (!el_x25519_keygen(xpk, xsk)) { - OQS_KEM_free(kem); - return pq_error("X25519 keygen failed"); - } - - unsigned char* kpk = (unsigned char*)malloc(kem->length_public_key); - unsigned char* ksk = (unsigned char*)malloc(kem->length_secret_key); - if (!kpk || !ksk) { free(kpk); free(ksk); OQS_KEM_free(kem); return pq_error("oom"); } - if (OQS_KEM_keypair(kem, kpk, ksk) != OQS_SUCCESS) { - free(kpk); free(ksk); OQS_KEM_free(kem); - return pq_error("kyber-768 keypair generation failed"); - } - - size_t pub_len = 32 + kem->length_public_key; - size_t sec_len = 32 + kem->length_secret_key; - unsigned char* pub_buf = (unsigned char*)malloc(pub_len); - unsigned char* sec_buf = (unsigned char*)malloc(sec_len); - if (!pub_buf || !sec_buf) { - free(pub_buf); free(sec_buf); free(kpk); - OQS_MEM_secure_free(ksk, kem->length_secret_key); - OQS_KEM_free(kem); return pq_error("oom"); - } - memcpy(pub_buf, xpk, 32); memcpy(pub_buf + 32, kpk, kem->length_public_key); - memcpy(sec_buf, xsk, 32); memcpy(sec_buf + 32, ksk, kem->length_secret_key); - - el_val_t x_pub_hex = el_hex_encode(xpk, 32); - el_val_t x_sec_hex = el_hex_encode(xsk, 32); - el_val_t k_pub_hex = el_hex_encode(kpk, kem->length_public_key); - el_val_t k_sec_hex = el_hex_encode(ksk, kem->length_secret_key); - el_val_t pub_hex = el_hex_encode(pub_buf, pub_len); - el_val_t sec_hex = el_hex_encode(sec_buf, sec_len); - - OQS_MEM_secure_free(ksk, kem->length_secret_key); - free(kpk); free(pub_buf); free(sec_buf); - OQS_KEM_free(kem); - memset(xsk, 0, 32); /* best-effort wipe of stack copy */ - - const char* xph = EL_CSTR(x_pub_hex); - const char* xsh = EL_CSTR(x_sec_hex); - const char* kph = EL_CSTR(k_pub_hex); - const char* ksh = EL_CSTR(k_sec_hex); - const char* pubh = EL_CSTR(pub_hex); - const char* sech = EL_CSTR(sec_hex); - - char* buf = el_strbuf(strlen(xph) + strlen(xsh) + strlen(kph) + strlen(ksh) - + strlen(pubh) + strlen(sech) + 256); - sprintf(buf, - "{\"x25519_pub\":\"%s\",\"x25519_sec\":\"%s\"," - "\"kyber_pub\":\"%s\",\"kyber_sec\":\"%s\"," - "\"public_key\":\"%s\",\"secret_key\":\"%s\"}", - xph, xsh, kph, ksh, pubh, sech); - return el_wrap_str(buf); -} - -/* Initiator-side handshake. Caller supplies the responder's combined public - * key (x25519_pub || kyber_pub, hex-encoded). The runtime: - * 1. Generates an ephemeral X25519 keypair, runs ECDH against the - * responder's static x25519_pub. - * 2. Runs Kyber-768 encaps against the responder's kyber_pub → kyber_ct, - * kyber_ss. - * 3. Combined shared = HKDF-SHA256(salt="", ikm = x25519_ss || kyber_ss, - * info = "el-pq-hybrid-v1", L = 32). - * 4. Returns combined ciphertext (= ephemeral_x25519_pub || kyber_ct) and - * the derived shared_secret. - * - * Responder side composition (intentionally not a separate runtime fn — - * trivial to express in El given pq_kem_decaps + a future x25519_derive - * primitive): split the ciphertext into ephem_xpk (32) and kyber_ct, run - * X25519(static_xsk, ephem_xpk) and pq_kem_decaps(static_kyber_sk, kyber_ct), - * then HKDF-SHA256 with the same salt/info to recover the same shared_secret. - * If a separate x25519 entry point becomes valuable, add `pq_hybrid_open` - * here taking (secret_key_combined, ciphertext_combined). */ -el_val_t pq_hybrid_handshake(el_val_t remote_pub_combined) { - size_t pub_len = 0; - unsigned char* rpub = el_hex_decode(EL_CSTR(remote_pub_combined), &pub_len); - if (!rpub) return pq_error("invalid hex in remote_pub_combined"); - - OQS_KEM* kem = OQS_KEM_new(EL_KYBER_ALG); - if (!kem) return pq_error("OQS_KEM_new(kyber-768) failed"); - if (pub_len != 32 + kem->length_public_key) { - OQS_KEM_free(kem); - return pq_error("remote_pub_combined length mismatch (expected x25519_pub || kyber_pub)"); - } - - unsigned char e_xpk[32], e_xsk[32], x_ss[32]; - if (!el_x25519_keygen(e_xpk, e_xsk)) { - OQS_KEM_free(kem); - return pq_error("X25519 ephemeral keygen failed"); - } - if (!el_x25519_derive(e_xsk, rpub, x_ss)) { - memset(e_xsk, 0, 32); - OQS_KEM_free(kem); - return pq_error("X25519 derive failed"); - } - memset(e_xsk, 0, 32); /* ephemeral; not needed after derive */ - - unsigned char* k_ct = (unsigned char*)malloc(kem->length_ciphertext); - unsigned char* k_ss = (unsigned char*)malloc(kem->length_shared_secret); - if (!k_ct || !k_ss) { - free(k_ct); free(k_ss); OQS_KEM_free(kem); - return pq_error("oom"); - } - if (OQS_KEM_encaps(kem, k_ct, k_ss, rpub + 32) != OQS_SUCCESS) { - free(k_ct); free(k_ss); OQS_KEM_free(kem); - return pq_error("kyber-768 encapsulation failed"); - } - - /* HKDF combine: ikm = x_ss || k_ss. */ - size_t ikm_len = 32 + kem->length_shared_secret; - unsigned char* ikm = (unsigned char*)malloc(ikm_len); - if (!ikm) { - free(k_ct); OQS_MEM_secure_free(k_ss, kem->length_shared_secret); - OQS_KEM_free(kem); - return pq_error("oom"); - } - memcpy(ikm, x_ss, 32); - memcpy(ikm + 32, k_ss, kem->length_shared_secret); - unsigned char combined[32]; - static const char info_str[] = "el-pq-hybrid-v1"; - el_hkdf_sha256(NULL, 0, ikm, ikm_len, - (const unsigned char*)info_str, sizeof(info_str) - 1, - combined, 32); - - memset(x_ss, 0, 32); - OQS_MEM_secure_free(k_ss, kem->length_shared_secret); - OQS_MEM_secure_free(ikm, ikm_len); - - /* Combined ciphertext = ephemeral_x25519_pub || kyber_ct. */ - size_t ct_len = 32 + kem->length_ciphertext; - unsigned char* combined_ct = (unsigned char*)malloc(ct_len); - if (!combined_ct) { free(k_ct); OQS_KEM_free(kem); return pq_error("oom"); } - memcpy(combined_ct, e_xpk, 32); - memcpy(combined_ct + 32, k_ct, kem->length_ciphertext); - free(k_ct); - OQS_KEM_free(kem); - - el_val_t ct_hex = el_hex_encode(combined_ct, ct_len); - el_val_t ss_hex = el_hex_encode(combined, 32); - free(combined_ct); - memset(combined, 0, 32); - - const char* cts = EL_CSTR(ct_hex); - const char* sss = EL_CSTR(ss_hex); - char* buf = el_strbuf(strlen(cts) + strlen(sss) + 64); - sprintf(buf, "{\"ciphertext\":\"%s\",\"shared_secret\":\"%s\"}", cts, sss); - return el_wrap_str(buf); -} - -#endif /* EL_HAVE_OPENSSL */ -#endif /* EL_HAVE_LIBOQS */ - -/* ─── AEAD: AES-256-GCM ──────────────────────────────────────────────────── - * - * Symmetric authenticated encryption used to wrap envelopes once a shared - * secret has been derived from the KEM (Kyber-768 / hybrid). The El surface - * is intentionally narrow: - * - * aead_encrypt(key_hex, plaintext) - * → {"nonce":"<24 hex>","ciphertext":"<...hex including 16-byte tag>"} - * - * aead_decrypt(key_hex, nonce_hex, ciphertext_hex) - * → plaintext String, or "" on auth failure / malformed input - * - * Conventions: - * - key_hex must decode to exactly 32 bytes (AES-256). Callers that hold - * a longer KEM shared_secret should normalize via SHA3-256(ss) → 32 bytes - * before passing it in. (Kyber-768's shared_secret is already 32 bytes, - * but keeping this contract explicit lets the El side be agnostic.) - * - nonce is a fresh 12-byte random value drawn from the OS CSPRNG. Caller - * never picks the nonce — eliminates the GCM nonce-reuse footgun entirely. - * - tag is the standard 16 bytes, appended to ciphertext per RFC 5116. - * `ciphertext` field is therefore (plaintext_len + 16) bytes, hex-encoded. - * - No associated data (AAD). If we later need bound metadata, add a - * length-prefixed AAD argument and bump the envelope version tag. - * - * Failure mode: - * aead_encrypt returns http_error_json(...) on input/system failure. - * aead_decrypt returns the empty string on ANY failure (including auth-tag - * mismatch). Callers MUST check for "" before using the result. */ - -#if !__has_include() - -el_val_t aead_encrypt(el_val_t key_hex, el_val_t plaintext) { - (void)key_hex; (void)plaintext; - return http_error_json("aead_encrypt requires OpenSSL (libcrypto); rebuild with -lcrypto"); -} -el_val_t aead_decrypt(el_val_t key_hex, el_val_t nonce_hex, el_val_t ciphertext_hex) { - (void)key_hex; (void)nonce_hex; (void)ciphertext_hex; - return el_wrap_str(el_strdup("")); -} - -#else /* OpenSSL available */ - -#include -#include - -el_val_t aead_encrypt(el_val_t key_hex, el_val_t plaintext) { - size_t key_len = 0; - unsigned char* key = el_hex_decode(EL_CSTR(key_hex), &key_len); - if (!key) return http_error_json("invalid hex in key"); - if (key_len != 32) return http_error_json("aead key must be 32 bytes (64 hex chars) for AES-256-GCM"); - - const char* pt = EL_CSTR(plaintext); - size_t pt_len = el_input_len(pt); - if (!pt) pt = ""; - - unsigned char nonce[12]; - if (RAND_bytes(nonce, 12) != 1) return http_error_json("OS CSPRNG failed (RAND_bytes)"); - - EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); - if (!ctx) return http_error_json("EVP_CIPHER_CTX_new failed"); - - if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1) { - EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm init failed"); - } - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) != 1) { - EVP_CIPHER_CTX_free(ctx); return http_error_json("set ivlen failed"); - } - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce) != 1) { - EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm key/iv init failed"); - } - - /* GCM ciphertext is the same length as plaintext; we append a 16-byte - * authentication tag for AEAD semantics. Allocate plaintext_len + 16. */ - unsigned char* ct = (unsigned char*)malloc(pt_len + 16); - if (!ct) { EVP_CIPHER_CTX_free(ctx); return http_error_json("oom"); } - int outlen = 0, total = 0; - if (EVP_EncryptUpdate(ctx, ct, &outlen, (const unsigned char*)pt, (int)pt_len) != 1) { - free(ct); EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm update failed"); - } - total += outlen; - if (EVP_EncryptFinal_ex(ctx, ct + total, &outlen) != 1) { - free(ct); EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm final failed"); - } - total += outlen; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, ct + total) != 1) { - free(ct); EVP_CIPHER_CTX_free(ctx); return http_error_json("aes-256-gcm get tag failed"); - } - EVP_CIPHER_CTX_free(ctx); - - el_val_t nonce_hex_v = el_hex_encode(nonce, 12); - el_val_t ct_hex_v = el_hex_encode(ct, (size_t)total + 16); - free(ct); - - const char* nh = EL_CSTR(nonce_hex_v); - const char* ch = EL_CSTR(ct_hex_v); - char* buf = el_strbuf(strlen(nh) + strlen(ch) + 48); - sprintf(buf, "{\"nonce\":\"%s\",\"ciphertext\":\"%s\"}", nh, ch); - return el_wrap_str(buf); -} - -el_val_t aead_decrypt(el_val_t key_hex, el_val_t nonce_hex, el_val_t ciphertext_hex) { - size_t key_len = 0, nonce_len = 0, ct_len = 0; - unsigned char* key = el_hex_decode(EL_CSTR(key_hex), &key_len); - unsigned char* nonce = el_hex_decode(EL_CSTR(nonce_hex), &nonce_len); - unsigned char* ct = el_hex_decode(EL_CSTR(ciphertext_hex), &ct_len); - if (!key || !nonce || !ct) return el_wrap_str(el_strdup("")); - if (key_len != 32 || nonce_len != 12) return el_wrap_str(el_strdup("")); - if (ct_len < 16) return el_wrap_str(el_strdup("")); - - size_t body_len = ct_len - 16; - const unsigned char* tag = ct + body_len; - - EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); - if (!ctx) return el_wrap_str(el_strdup("")); - - if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1 || - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) != 1 || - EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce) != 1) { - EVP_CIPHER_CTX_free(ctx); return el_wrap_str(el_strdup("")); - } - - unsigned char* pt = (unsigned char*)malloc(body_len + 1); - if (!pt) { EVP_CIPHER_CTX_free(ctx); return el_wrap_str(el_strdup("")); } - int outlen = 0, total = 0; - if (EVP_DecryptUpdate(ctx, pt, &outlen, ct, (int)body_len) != 1) { - free(pt); EVP_CIPHER_CTX_free(ctx); return el_wrap_str(el_strdup("")); - } - total += outlen; - /* Set expected tag before final — GCM's final step is where auth happens. */ - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void*)tag) != 1) { - free(pt); EVP_CIPHER_CTX_free(ctx); return el_wrap_str(el_strdup("")); - } - int rc = EVP_DecryptFinal_ex(ctx, pt + total, &outlen); - EVP_CIPHER_CTX_free(ctx); - if (rc != 1) { - /* Auth failure or padding/length mismatch. Return empty so callers - * cannot accidentally treat tampered ciphertext as a valid message. */ - free(pt); - return el_wrap_str(el_strdup("")); - } - total += outlen; - pt[total] = '\0'; - - /* Copy into the el arena so the caller-visible string outlives this fn. */ - char* out = el_strbuf((size_t)total); - memcpy(out, pt, (size_t)total); - out[total] = '\0'; - free(pt); - return el_wrap_str(out); -} - -#endif /* __has_include() */ - -/* ──────────────────────────────────────────────────────────────────────────── - * OTLP/HTTP observability — logs, traces, metrics - * - * Design goals: - * - Zero blocking on the request path. Producers append to in-memory - * ring buffers; a single worker thread flushes to the OTLP endpoint. - * - Drop-on-failure semantics. If the endpoint is unreachable or slow, - * we drop telemetry rather than back-pressure into the request handler. - * - Best-effort serialization. Each record is pre-serialized as JSON when - * the El program calls the primitive; the worker just batches. - * - Configuration via env vars: - * OTLP_ENDPOINT e.g. https://alloy.neuralplatform.ai:4318 - * OTEL_SERVICE_NAME e.g. neuron-web (default: argv[0] basename) - * OTEL_SERVICE_VERSION (default: "0.0.0") - * OTEL_RESOURCE_ATTRS comma-sep k=v pairs (optional) - * - * Wire format: OTLP/HTTP JSON. Three endpoints: - * POST {endpoint}/v1/logs — log records - * POST {endpoint}/v1/traces — spans - * POST {endpoint}/v1/metrics — counter/gauge points - * - * El programs see four primitives: - * trace_span_start(name) -> SpanHandle (just a string id) - * trace_span_end(handle) (computes duration, queues) - * emit_log(level, msg, fields_json) (queues a log record) - * emit_metric(name, value, tags_json) (queues a counter increment) - * ──────────────────────────────────────────────────────────────────────────── - */ - -#define OTLP_BUF_CAP 4096 /* per-buffer ring size */ -#define OTLP_FLUSH_MS 2000 /* flush every 2s */ -#define OTLP_BATCH_MAX 200 /* up to 200 records per POST */ - -typedef struct { - char* data; /* malloc'd JSON fragment for this record */ -} OtlpRec; - -typedef struct { - OtlpRec ring[OTLP_BUF_CAP]; - size_t head; /* next write slot */ - size_t tail; /* next read slot */ - pthread_mutex_t mu; -} OtlpQueue; - -static OtlpQueue _otlp_logs = { .mu = PTHREAD_MUTEX_INITIALIZER }; -static OtlpQueue _otlp_traces = { .mu = PTHREAD_MUTEX_INITIALIZER }; -static OtlpQueue _otlp_metrics = { .mu = PTHREAD_MUTEX_INITIALIZER }; - -static char* _otlp_endpoint = NULL; /* e.g. https://alloy.neuralplatform.ai:4318 */ -static char* _otlp_service_name = NULL; -static char* _otlp_service_version = NULL; -static int _otlp_initialized = 0; -static pthread_t _otlp_worker_thread; - -/* enqueue — returns 1 if accepted, 0 if dropped (full buffer or no endpoint) */ -static int otlp_enqueue(OtlpQueue* q, const char* json) { - if (!_otlp_endpoint || !json) return 0; - pthread_mutex_lock(&q->mu); - size_t next_head = (q->head + 1) % OTLP_BUF_CAP; - if (next_head == q->tail) { - /* buffer full — drop oldest */ - free(q->ring[q->tail].data); - q->ring[q->tail].data = NULL; - q->tail = (q->tail + 1) % OTLP_BUF_CAP; - } - q->ring[q->head].data = strdup(json); - q->head = next_head; - pthread_mutex_unlock(&q->mu); - return 1; -} - -/* drain — copies up to OTLP_BATCH_MAX items into a comma-joined string, - * caller must free the result. Returns NULL if queue is empty. */ -static char* otlp_drain(OtlpQueue* q) { - pthread_mutex_lock(&q->mu); - if (q->head == q->tail) { pthread_mutex_unlock(&q->mu); return NULL; } - /* compute total length */ - size_t total = 0, count = 0; - size_t i = q->tail; - while (i != q->head && count < OTLP_BATCH_MAX) { - if (q->ring[i].data) total += strlen(q->ring[i].data) + 1; /* +1 for comma */ - i = (i + 1) % OTLP_BUF_CAP; - count++; - } - char* out = malloc(total + 4); - if (!out) { pthread_mutex_unlock(&q->mu); return NULL; } - out[0] = '\0'; - size_t off = 0; - i = q->tail; - count = 0; - while (i != q->head && count < OTLP_BATCH_MAX) { - if (q->ring[i].data) { - size_t l = strlen(q->ring[i].data); - if (off > 0) { out[off++] = ','; } - memcpy(out + off, q->ring[i].data, l); - off += l; - free(q->ring[i].data); - q->ring[i].data = NULL; - } - i = (i + 1) % OTLP_BUF_CAP; - count++; - } - out[off] = '\0'; - q->tail = i; - pthread_mutex_unlock(&q->mu); - return out; -} - -/* Build resource block once (service.name, service.version, host.name) */ -static char* otlp_resource_block(void) { - static char cached[1024]; - static int built = 0; - if (built) return cached; - char host[256] = "unknown"; - gethostname(host, sizeof(host) - 1); - snprintf(cached, sizeof(cached), - "{\"attributes\":[" - "{\"key\":\"service.name\",\"value\":{\"stringValue\":\"%s\"}}," - "{\"key\":\"service.version\",\"value\":{\"stringValue\":\"%s\"}}," - "{\"key\":\"host.name\",\"value\":{\"stringValue\":\"%s\"}}" - "]}", - _otlp_service_name ? _otlp_service_name : "el-app", - _otlp_service_version ? _otlp_service_version : "0.0.0", - host); - built = 1; - return cached; -} - -/* Best-effort POST. Drops on any error. */ -static void otlp_post(const char* path, const char* body) { - if (!_otlp_endpoint || !body || !*body) return; - char url[1024]; - snprintf(url, sizeof(url), "%s%s", _otlp_endpoint, path); - CURL* c = curl_easy_init(); - if (!c) return; - struct curl_slist* h = NULL; - h = curl_slist_append(h, "Content-Type: application/json"); - curl_easy_setopt(c, CURLOPT_URL, url); - curl_easy_setopt(c, CURLOPT_POST, 1L); - curl_easy_setopt(c, CURLOPT_POSTFIELDS, body); - curl_easy_setopt(c, CURLOPT_POSTFIELDSIZE, (long)strlen(body)); - curl_easy_setopt(c, CURLOPT_HTTPHEADER, h); - curl_easy_setopt(c, CURLOPT_TIMEOUT_MS, 3000L); - curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, NULL); /* discard response */ - curl_easy_perform(c); - curl_slist_free_all(h); - curl_easy_cleanup(c); -} - -/* Flush worker — runs forever until process exits */ -static void* otlp_worker(void* arg) { - (void)arg; - while (1) { - struct timespec ts = { OTLP_FLUSH_MS / 1000, (OTLP_FLUSH_MS % 1000) * 1000000L }; - nanosleep(&ts, NULL); - - char* logs = otlp_drain(&_otlp_logs); - if (logs && *logs) { - char body[OTLP_BUF_CAP * 8]; - int n = snprintf(body, sizeof(body), - "{\"resourceLogs\":[{\"resource\":%s," - "\"scopeLogs\":[{\"scope\":{\"name\":\"el-runtime\"}," - "\"logRecords\":[%s]}]}]}", - otlp_resource_block(), logs); - if (n > 0 && n < (int)sizeof(body)) otlp_post("/v1/logs", body); - } - free(logs); - - char* traces = otlp_drain(&_otlp_traces); - if (traces && *traces) { - char body[OTLP_BUF_CAP * 8]; - int n = snprintf(body, sizeof(body), - "{\"resourceSpans\":[{\"resource\":%s," - "\"scopeSpans\":[{\"scope\":{\"name\":\"el-runtime\"}," - "\"spans\":[%s]}]}]}", - otlp_resource_block(), traces); - if (n > 0 && n < (int)sizeof(body)) otlp_post("/v1/traces", body); - } - free(traces); - - char* metrics = otlp_drain(&_otlp_metrics); - if (metrics && *metrics) { - char body[OTLP_BUF_CAP * 8]; - int n = snprintf(body, sizeof(body), - "{\"resourceMetrics\":[{\"resource\":%s," - "\"scopeMetrics\":[{\"scope\":{\"name\":\"el-runtime\"}," - "\"metrics\":[%s]}]}]}", - otlp_resource_block(), metrics); - if (n > 0 && n < (int)sizeof(body)) otlp_post("/v1/metrics", body); - } - free(metrics); - } - return NULL; -} - -/* Initialize OTLP — called lazily on first emit. Idempotent. */ -static void otlp_lazy_init(void) { - if (_otlp_initialized) return; - static pthread_mutex_t once_mu = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&once_mu); - if (_otlp_initialized) { pthread_mutex_unlock(&once_mu); return; } - - const char* ep = getenv("OTLP_ENDPOINT"); - if (!ep || !*ep) { - _otlp_initialized = 1; - pthread_mutex_unlock(&once_mu); - return; - } - _otlp_endpoint = strdup(ep); - /* trim trailing slash */ - size_t l = strlen(_otlp_endpoint); - if (l > 0 && _otlp_endpoint[l - 1] == '/') _otlp_endpoint[l - 1] = '\0'; - - const char* svc = getenv("OTEL_SERVICE_NAME"); - _otlp_service_name = strdup(svc && *svc ? svc : "el-app"); - const char* ver = getenv("OTEL_SERVICE_VERSION"); - _otlp_service_version = strdup(ver && *ver ? ver : "0.0.0"); - - pthread_create(&_otlp_worker_thread, NULL, otlp_worker, NULL); - pthread_detach(_otlp_worker_thread); - _otlp_initialized = 1; - pthread_mutex_unlock(&once_mu); -} - -/* JSON-escape a string into out_buf. Returns chars written (excluding null). */ -static size_t otlp_json_escape(const char* in, char* out, size_t out_cap) { - size_t o = 0; - for (size_t i = 0; in[i] && o + 8 < out_cap; i++) { - unsigned char c = (unsigned char)in[i]; - if (c == '"') { out[o++] = '\\'; out[o++] = '"'; } - else if (c == '\\'){ out[o++] = '\\'; out[o++] = '\\'; } - else if (c == '\n'){ out[o++] = '\\'; out[o++] = 'n'; } - else if (c == '\r'){ out[o++] = '\\'; out[o++] = 'r'; } - else if (c == '\t'){ out[o++] = '\\'; out[o++] = 't'; } - else if (c < 0x20) { o += snprintf(out + o, out_cap - o, "\\u%04x", c); } - else { out[o++] = (char)c; } - } - out[o] = '\0'; - return o; -} - -/* ── Public El primitives ─────────────────────────────────────────────────── */ - -/* emit_log(level, msg, fields_json) — fields_json is a JSON object string or "" */ -el_val_t emit_log(el_val_t level_v, el_val_t msg_v, el_val_t fields_v) { - otlp_lazy_init(); - if (!_otlp_endpoint) return EL_INT(0); - const char* level = EL_CSTR(level_v); if (!level) level = "INFO"; - const char* msg = EL_CSTR(msg_v); if (!msg) msg = ""; - const char* fields = EL_CSTR(fields_v); if (!fields) fields = ""; - /* Map El level names to OTLP severity numbers */ - int sev_num = 9; /* INFO */ - if (strcmp(level, "TRACE") == 0) sev_num = 1; - else if (strcmp(level, "DEBUG") == 0) sev_num = 5; - else if (strcmp(level, "INFO") == 0) sev_num = 9; - else if (strcmp(level, "WARN") == 0 || strcmp(level, "WARNING") == 0) sev_num = 13; - else if (strcmp(level, "ERROR") == 0) sev_num = 17; - else if (strcmp(level, "FATAL") == 0) sev_num = 21; - char esc_msg[2048]; otlp_json_escape(msg, esc_msg, sizeof(esc_msg)); - /* unix nanos */ - struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - long long now_nano = (long long)ts.tv_sec * 1000000000LL + ts.tv_nsec; - char rec[4096]; - int n = snprintf(rec, sizeof(rec), - "{\"timeUnixNano\":\"%lld\",\"severityNumber\":%d," - "\"severityText\":\"%s\"," - "\"body\":{\"stringValue\":\"%s\"}%s%s}", - now_nano, sev_num, level, esc_msg, - (fields && *fields) ? ",\"attributes\":" : "", - (fields && *fields) ? fields : ""); - if (n > 0 && n < (int)sizeof(rec)) otlp_enqueue(&_otlp_logs, rec); - return EL_INT(1); -} - -/* emit_metric(name, value, tags_json) — Sum (counter) data point. tags_json - * is a JSON array of {key, value} pairs or empty string. */ -el_val_t emit_metric(el_val_t name_v, el_val_t value_v, el_val_t tags_v) { - otlp_lazy_init(); - if (!_otlp_endpoint) return EL_INT(0); - const char* name = EL_CSTR(name_v); if (!name) name = "unknown"; - int64_t val = (int64_t)value_v; - const char* tags = EL_CSTR(tags_v); if (!tags) tags = ""; - char esc_name[256]; otlp_json_escape(name, esc_name, sizeof(esc_name)); - struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - long long now_nano = (long long)ts.tv_sec * 1000000000LL + ts.tv_nsec; - char rec[4096]; - int n = snprintf(rec, sizeof(rec), - "{\"name\":\"%s\",\"sum\":{\"aggregationTemporality\":2,\"isMonotonic\":true," - "\"dataPoints\":[{\"asInt\":\"%lld\"," - "\"timeUnixNano\":\"%lld\"" - "%s%s}]}}", - esc_name, (long long)val, now_nano, - (tags && *tags) ? ",\"attributes\":" : "", - (tags && *tags) ? tags : ""); - if (n > 0 && n < (int)sizeof(rec)) otlp_enqueue(&_otlp_metrics, rec); - return EL_INT(1); -} - -/* trace_span_start(name) — returns a span handle (string of "traceid:spanid:start_nano:name") */ -el_val_t trace_span_start(el_val_t name_v) { - otlp_lazy_init(); - const char* name = EL_CSTR(name_v); if (!name) name = "span"; - /* generate 16-byte trace id and 8-byte span id */ - static _Thread_local int seeded = 0; - if (!seeded) { srand((unsigned int)(uintptr_t)pthread_self() ^ (unsigned int)time(NULL)); seeded = 1; } - char tid[33], sid[17]; - for (int i = 0; i < 32; i++) tid[i] = "0123456789abcdef"[rand() & 0xF]; - tid[32] = '\0'; - for (int i = 0; i < 16; i++) sid[i] = "0123456789abcdef"[rand() & 0xF]; - sid[16] = '\0'; - struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - long long now_nano = (long long)ts.tv_sec * 1000000000LL + ts.tv_nsec; - char* handle = malloc(strlen(name) + 80); - if (!handle) return EL_STR(""); - sprintf(handle, "%s:%s:%lld:%s", tid, sid, now_nano, name); - el_arena_track(handle); - return EL_STR(handle); -} - -/* trace_span_end(handle) — emits the span with computed duration */ -el_val_t trace_span_end(el_val_t handle_v) { - otlp_lazy_init(); - if (!_otlp_endpoint) return EL_INT(0); - const char* h = EL_CSTR(handle_v); if (!h) return EL_INT(0); - /* parse "tid:sid:start_nano:name" */ - char tid[64], sid[32], rest[1024]; - long long start_nano = 0; - if (sscanf(h, "%63[^:]:%31[^:]:%lld:%1023[^\n]", tid, sid, &start_nano, rest) != 4) return EL_INT(0); - struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - long long end_nano = (long long)ts.tv_sec * 1000000000LL + ts.tv_nsec; - char esc_name[1024]; otlp_json_escape(rest, esc_name, sizeof(esc_name)); - char rec[4096]; - int n = snprintf(rec, sizeof(rec), - "{\"traceId\":\"%s\",\"spanId\":\"%s\"," - "\"name\":\"%s\"," - "\"kind\":1," - "\"startTimeUnixNano\":\"%lld\"," - "\"endTimeUnixNano\":\"%lld\"," - "\"status\":{\"code\":1}}", - tid, sid, esc_name, start_nano, end_nano); - if (n > 0 && n < (int)sizeof(rec)) otlp_enqueue(&_otlp_traces, rec); - return EL_INT(1); -} - -/* Convenience: emit a one-shot timed event (emit start+end immediately). - * For El programs that want point events with duration baked in. */ -el_val_t emit_event(el_val_t name_v, el_val_t duration_ms_v) { - otlp_lazy_init(); - if (!_otlp_endpoint) return EL_INT(0); - const char* name = EL_CSTR(name_v); if (!name) name = "event"; - int64_t dur_ms = (int64_t)duration_ms_v; - el_val_t h = trace_span_start(EL_STR((char*)name)); - /* fudge start to be (now - duration) */ - (void)dur_ms; - return trace_span_end(h); -} - diff --git a/lang/el-compiler/runtime/legacy/el_runtime.h b/lang/el-compiler/runtime/legacy/el_runtime.h deleted file mode 100644 index 8b80ee7..0000000 --- a/lang/el-compiler/runtime/legacy/el_runtime.h +++ /dev/null @@ -1,761 +0,0 @@ -/* - * el_runtime.h — El language C runtime header - * - * Declares all built-in functions available to compiled El programs. - * Include this in every generated .c file. - * - * Value model: - * All El values are represented as el_val_t (= int64_t). - * On 64-bit systems a pointer fits in int64_t. - * String values are cast: (el_val_t)(uintptr_t)"hello" - * Integer values are stored directly. - * This lets arithmetic work naturally while still passing strings around. - * - * Type conventions (El -> C): - * String -> el_val_t (holds const char* via uintptr_t cast) - * Int -> el_val_t - * Bool -> el_val_t (0 = false, nonzero = true) - * Any -> el_val_t - * Void -> void - * - * Macros for convenience: - * EL_STR(s) cast string literal to el_val_t - * EL_CSTR(v) cast el_val_t back to const char* - * EL_INT(v) identity — el_val_t is already int64_t - * - * Link requirements: - * -lcurl — required for the HTTP client (http_get, http_post, llm_*). - * -lpthread — required for the HTTP server (one detached thread per - * connection, capped at 64 concurrent). - * -loqs — optional; required only when liboqs is installed and the - * pq_* / sha3_256_hex entry points are needed. Detected at - * compile time via __has_include(). - * -lcrypto — optional; pulled in alongside -loqs. Used for X25519 in - * pq_hybrid_* and HKDF-SHA256 derivation. - * - * Canonical compile command: - * cc -std=c11 -I el-compiler/runtime -lcurl -lpthread \ - * -o .c el-compiler/runtime/el_runtime.c - * - * With liboqs (post-quantum stack): - * cc -std=c11 -I el-compiler/runtime -lcurl -lpthread -loqs -lcrypto \ - * -o .c el-compiler/runtime/el_runtime.c - */ - -#pragma once - -#include -#include - -typedef int64_t el_val_t; - -#define EL_STR(s) ((el_val_t)(uintptr_t)(s)) -#define EL_CSTR(v) ((const char*)(uintptr_t)(v)) -#define EL_INT(v) (v) -#define EL_NULL ((el_val_t)0) - -/* Float values share the el_val_t (int64) slot via a bit-cast. - * The codegen emits Float literals as `el_from_float()` so the - * underlying bits represent the IEEE 754 double. Float-aware builtins - * (math, format, json) round-trip via these helpers. */ -static inline double el_to_float(el_val_t v) { - union { int64_t i; double f; } u; - u.i = (int64_t)v; - return u.f; -} - -static inline el_val_t el_from_float(double f) { - union { double f; int64_t i; } u; - u.f = f; - return (el_val_t)u.i; -} - -#ifdef __cplusplus -extern "C" { -#endif - -/* ── I/O ──────────────────────────────────────────────────────────────────── */ - -void println(el_val_t s); -void print(el_val_t s); -el_val_t readline(void); - -/* ── String builtins ─────────────────────────────────────────────────────── */ - -el_val_t el_str_concat(el_val_t a, el_val_t b); -el_val_t str_eq(el_val_t a, el_val_t b); -el_val_t str_starts_with(el_val_t s, el_val_t prefix); -el_val_t str_ends_with(el_val_t s, el_val_t suffix); -el_val_t str_len(el_val_t s); -el_val_t str_concat(el_val_t a, el_val_t b); -el_val_t int_to_str(el_val_t n); -el_val_t str_to_int(el_val_t s); -el_val_t str_slice(el_val_t s, el_val_t start, el_val_t end); -el_val_t str_contains(el_val_t s, el_val_t sub); -el_val_t str_replace(el_val_t s, el_val_t from, el_val_t to); -el_val_t str_to_upper(el_val_t s); -el_val_t str_to_lower(el_val_t s); -el_val_t str_trim(el_val_t s); - -/* ── Math ────────────────────────────────────────────────────────────────── */ - -el_val_t el_abs(el_val_t n); -el_val_t el_max(el_val_t a, el_val_t b); -el_val_t el_min(el_val_t a, el_val_t b); - -/* ── Refcount (ARC) ────────────────────────────────────────────────────────── - * Lists and Maps carry a refcount. Strings and ints do not — el_retain and - * el_release are safe no-ops on non-refcounted values (they sniff a magic - * header at offset 0 and only act if the magic matches). - * - * Codegen emits these at let-binding shadowing, function entry (params), and - * function exit (locals other than the returned value). The refcount lets - * el_list_append and el_map_set mutate in place when uniquely owned (cheap) - * and copy-on-write when shared (preserves persistent semantics across - * accumulator patterns in the compiler itself). */ - -void el_retain(el_val_t v); -void el_release(el_val_t v); - -/* ── List ────────────────────────────────────────────────────────────────── */ - -el_val_t el_list_new(el_val_t count, ...); -el_val_t el_list_len(el_val_t list); -el_val_t el_list_get(el_val_t list, el_val_t index); -el_val_t el_list_append(el_val_t list, el_val_t elem); -el_val_t el_list_empty(void); -el_val_t el_list_clone(el_val_t list); - -/* ── Map ─────────────────────────────────────────────────────────────────── */ - -el_val_t el_map_new(el_val_t pair_count, ...); -el_val_t el_get_field(el_val_t map, el_val_t key); -el_val_t el_map_get(el_val_t map, el_val_t key); -el_val_t el_map_set(el_val_t map, el_val_t key, el_val_t value); - -/* ── HTTP ─────────────────────────────────────────────────────────────────── */ - -el_val_t http_get(el_val_t url); -el_val_t http_post(el_val_t url, el_val_t body); -el_val_t http_post_json(el_val_t url, el_val_t json_body); -el_val_t http_get_with_headers(el_val_t url, el_val_t headers_map); -el_val_t http_post_with_headers(el_val_t url, el_val_t body, el_val_t headers_map); -el_val_t http_post_form_auth(el_val_t url, el_val_t form_body, el_val_t auth_header); -el_val_t http_delete(el_val_t url); -void http_serve(el_val_t port, el_val_t handler); -void http_set_handler(el_val_t name); - -/* HTTP server v2 ───────────────────────────────────────────────────────────── - * Same dispatch model as http_serve, but the handler signature is widened: - * - * el_val_t handler(method, path, headers_map, body) - * - * `headers_map` is an ElMap from lowercased header name → header value (both - * Strings). Repeated headers are joined with ", " per RFC 7230. - * - * Response value: the handler may return either - * (a) a plain body string — same auto-content-type / 200-OK behaviour as - * http_serve (3-arg) — or - * (b) a response envelope built with `http_response(status, headers_json, - * body)`. The runtime detects the envelope discriminator - * `"el_http_response":1` at the start of the returned string and - * unpacks status / headers / body before sending. - * - * The 3-arg http_serve(port, handler) remains supported unchanged for - * existing handlers (e.g. products/web/server.el): it dispatches with - * (method, path, body), hardcodes 200 OK, and auto-detects content type. */ -void http_serve_v2(el_val_t port, el_val_t handler); -void http_set_handler_v2(el_val_t name); - -/* Build an HTTP response envelope. `headers_json` should be a JSON object - * literal like `{"WWW-Authenticate":"Basic"}` (or "" / "{}" for none). The - * returned string carries the discriminator `{"el_http_response":1,...}` - * which the runtime's send-path detects and unpacks. Detection happens - * uniformly inside http_send_response, so a 3-arg handler may also return - * an envelope. The 3-arg variant remains documented as a fixed 200-OK - * auto-content-type contract for legacy handlers that return plain bodies. */ -el_val_t http_response(el_val_t status, el_val_t headers_json, el_val_t body); - -/* SSE connection fd — set by http_worker_v2 before calling the El handler, - * cleared afterwards. Defined in el_seed.c; called from el_runtime.c. - * The getter is exposed as __http_conn_fd() to El programs. */ -void el_seed_set_http_conn_fd(int fd); - -/* HTTP timeout — every libcurl request honors EL_HTTP_TIMEOUT_MS (default - * 60000ms). Read lazily on first use, so setting the env var any time before - * the first http_* call is sufficient. */ - -/* Streaming variants — write the response body straight to a file via - * libcurl's CURLOPT_WRITEFUNCTION = fwrite. These bypass the el_val_t string - * wrapper entirely, so binary payloads (audio/mpeg, image/png, etc.) survive - * embedded NUL bytes that would truncate a strlen()-based code path. - * - * Both honor EL_HTTP_TIMEOUT_MS, follow redirects, and accept the same - * `headers_map` shape as http_post_with_headers (ElMap of String→String). - * - * Return value: 1 on success (file fully written), 0 on any failure - * (network, file open, partial write). On failure the output file is removed - * so callers cannot mistake a partially-written file for a valid one. */ -el_val_t http_post_to_file(el_val_t url, el_val_t body, el_val_t headers_map, el_val_t output_path); -el_val_t http_get_to_file(el_val_t url, el_val_t headers_map, el_val_t output_path); - -/* ── URL encoding ────────────────────────────────────────────────────────── */ - -el_val_t url_encode(el_val_t s); /* RFC 3986 unreserved set */ -el_val_t url_decode(el_val_t s); /* '+' → space, %XX → byte */ - -/* ── HTML allowlist sanitizer ──────────────────────────────────────────────── - * el_html_sanitize(input_html, allowlist_json) — strict allowlist HTML - * cleaner. State-machine parser; tag/attribute names compared case- - * insensitively against the allowlist; `` / `<… src>` URL schemes - * validated (http, https, mailto, fragment-only, or relative); whole- - * subtree drop for script / style / iframe / object / embed / form; HTML- - * escapes free text outside dropped subtrees. - * - * The allowlist is JSON of the form - * {"p":[],"a":["href","title"],"strong":[],...} - * where each value is the array of attribute names allowed for that tag. */ -el_val_t el_html_sanitize(el_val_t input_html, el_val_t allowlist_json); - -/* ── Filesystem ──────────────────────────────────────────────────────────── */ - -el_val_t fs_read(el_val_t path); -el_val_t fs_write(el_val_t path, el_val_t content); -el_val_t fs_list(el_val_t path); -el_val_t fs_exists(el_val_t path); -el_val_t fs_mkdir(el_val_t path); /* mkdir -p, mode 0755 */ - -/* Length-explicit binary write. `length` is an Int (el_val_t holding the - * byte count). The caller knows the length from context — typically because - * `bytes` came from base64_decode (which produces a magic-tagged binary - * buffer with embedded NULs possible) and the caller already tracks the - * decoded length, OR because the bytes came from a fixed-size source - * (sha256_bytes = 32, hmac_sha256_bytes = 32). Bypasses strlen entirely. - * - * Returns 1 on success, 0 on failure (invalid path, can't open, partial - * write, negative length). On partial-write failure, the file is removed - * so callers cannot read back a truncated artefact. */ -el_val_t fs_write_bytes(el_val_t path, el_val_t bytes, el_val_t length); - -/* ── JSON ────────────────────────────────────────────────────────────────── */ - -el_val_t json_get(el_val_t json, el_val_t key); -el_val_t json_parse(el_val_t s); -el_val_t json_stringify(el_val_t v); -el_val_t json_get_string(el_val_t json_str, el_val_t key); -el_val_t json_get_int(el_val_t json_str, el_val_t key); -el_val_t json_get_float(el_val_t json_str, el_val_t key); -el_val_t json_get_bool(el_val_t json_str, el_val_t key); -el_val_t json_get_raw(el_val_t json_str, el_val_t key); -el_val_t json_set(el_val_t json_str, el_val_t key, el_val_t value); -el_val_t json_array_len(el_val_t json_str); -el_val_t json_array_get(el_val_t json_str, el_val_t index); -el_val_t json_array_get_string(el_val_t json_str, el_val_t index); - -/* ── Time ────────────────────────────────────────────────────────────────── */ - -el_val_t time_now(void); -el_val_t time_now_utc(void); -el_val_t sleep_secs(el_val_t secs); -el_val_t sleep_ms(el_val_t ms); -el_val_t time_format(el_val_t ts, el_val_t fmt); -el_val_t time_to_parts(el_val_t ts); -el_val_t time_from_parts(el_val_t secs, el_val_t ns, el_val_t tz); -el_val_t time_add(el_val_t ts, el_val_t n, el_val_t unit); -el_val_t time_diff(el_val_t ts1, el_val_t ts2, el_val_t unit); - -/* ── Instant + Duration: first-class temporal types ────────────────────────── - * Both types share the el_val_t (int64) slot. Instants are nanoseconds - * since the Unix epoch; Durations are signed nanoseconds. Type discipline - * is enforced at codegen-time: BinOps on names registered as Instant or - * Duration route through the typed wrappers below; mismatches like - * Instant+Instant become #error at the C compiler. - * - * Postfix literals — `30.seconds`, `1.hour`, `500.millis`, `30.nanos` — are - * recognised by the parser as DurationLit AST nodes and lowered to literal - * int64 nanoseconds at codegen time. The runtime never sees the units. */ - -el_val_t el_now_instant(void); -el_val_t now(void); -el_val_t unix_seconds(el_val_t n); -el_val_t unix_millis(el_val_t n); -el_val_t instant_from_iso8601(el_val_t s); - -el_val_t el_duration_from_nanos(el_val_t ns); -el_val_t duration_seconds(el_val_t n); -el_val_t duration_millis(el_val_t n); -el_val_t duration_nanos(el_val_t n); - -el_val_t el_instant_add_dur(el_val_t inst, el_val_t dur); -el_val_t el_instant_sub_dur(el_val_t inst, el_val_t dur); -el_val_t el_instant_diff(el_val_t a, el_val_t b); -el_val_t el_duration_add(el_val_t a, el_val_t b); -el_val_t el_duration_sub(el_val_t a, el_val_t b); -el_val_t el_duration_scale(el_val_t dur, el_val_t scalar); -el_val_t el_duration_div(el_val_t dur, el_val_t scalar); - -el_val_t el_instant_lt(el_val_t a, el_val_t b); -el_val_t el_instant_le(el_val_t a, el_val_t b); -el_val_t el_instant_gt(el_val_t a, el_val_t b); -el_val_t el_instant_ge(el_val_t a, el_val_t b); -el_val_t el_instant_eq(el_val_t a, el_val_t b); -el_val_t el_instant_ne(el_val_t a, el_val_t b); -el_val_t el_duration_lt(el_val_t a, el_val_t b); -el_val_t el_duration_le(el_val_t a, el_val_t b); -el_val_t el_duration_gt(el_val_t a, el_val_t b); -el_val_t el_duration_ge(el_val_t a, el_val_t b); -el_val_t el_duration_eq(el_val_t a, el_val_t b); -el_val_t el_duration_ne(el_val_t a, el_val_t b); - -el_val_t instant_to_unix_seconds(el_val_t i); -el_val_t instant_to_unix_millis(el_val_t i); -el_val_t instant_to_iso8601(el_val_t i); -el_val_t duration_to_seconds(el_val_t d); -el_val_t duration_to_millis(el_val_t d); -el_val_t duration_to_nanos(el_val_t d); - -el_val_t el_sleep_duration(el_val_t dur); -el_val_t unix_timestamp(void); - -el_val_t ttl_cache_set(el_val_t key, el_val_t value); -el_val_t ttl_cache_get(el_val_t key, el_val_t max_age); -el_val_t ttl_cache_age(el_val_t key); - -/* ── Calendar + CalendarTime + Rhythm + LocalDate/Time/DateTime ───────────── - * Phase 1.5 of the time system. Calendar is pluggable: EarthCalendar (IANA - * zones, Gregorian, DST) is the user-facing default; MarsCalendar, - * CycleCalendar(period), NoCycleCalendar, RelativeCalendar handle non-Earth - * domains. - * - * A Calendar interprets an Instant under a particular cycle convention and - * produces a CalendarTime. CalendarTime carries the underlying Instant and - * a back-pointer to its Calendar; arithmetic and formatting consult the - * Calendar to convert ns since epoch into year/month/day/hour/minute/second - * (or sol/phase, or cycle/phase, depending on kind). - * - * Storage convention: Calendar / CalendarTime / Rhythm / LocalDate / - * LocalDateTime are heap-allocated structs whose pointers are cast into - * el_val_t. A 24-bit magic header at offset 0 lets the runtime identify - * the kind safely. LocalTime is small enough to live in the int64 slot - * directly (nanos since midnight, signed). */ - -/* Zone — opaque IANA zone or fixed offset, used by EarthCalendar. - * `zone_id` is either an IANA name ("America/New_York", "UTC") or a fixed - * offset string ("+05:30", "-08:00"). The runtime resolves it via tzset() - * on first use of the owning EarthCalendar. */ -el_val_t zone(el_val_t id); -el_val_t zone_utc(void); -el_val_t zone_local(void); -el_val_t zone_offset(el_val_t hours, el_val_t minutes); - -/* Calendar constructors. Each returns an el_val_t pointer to a heap- - * allocated, magic-tagged Calendar struct. Calendars are interned by - * (kind, zone_id, period_ns, epoch_ns) so identical constructors return - * the same pointer — equality is reference equality. */ -el_val_t earth_calendar(el_val_t z); -el_val_t earth_calendar_default(void); -el_val_t mars_calendar(void); -el_val_t cycle_calendar(el_val_t period_dur); -el_val_t no_cycle_calendar(void); -el_val_t relative_calendar(el_val_t epoch_inst); - -/* CalendarTime constructors and methods. Returns a heap-allocated struct - * whose pointer fits in el_val_t. */ -el_val_t now_in(el_val_t cal); -el_val_t in_calendar(el_val_t inst, el_val_t cal); -el_val_t cal_format(el_val_t ct, el_val_t pattern); -el_val_t cal_to_instant(el_val_t ct); -el_val_t cal_cycle_phase(el_val_t ct); -el_val_t cal_in(el_val_t ct, el_val_t cal); - -/* LocalDate / LocalTime / LocalDateTime — calendar-agnostic value types. - * LocalTime carries nanoseconds since midnight as a signed int64 directly - * in the el_val_t slot (no allocation). LocalDate / LocalDateTime are - * heap-allocated structs with magic headers. */ -el_val_t local_date(el_val_t y, el_val_t m, el_val_t d); -el_val_t local_time(el_val_t h, el_val_t m, el_val_t s, el_val_t ns); -el_val_t local_datetime(el_val_t date, el_val_t time); -el_val_t zoned(el_val_t date, el_val_t time, el_val_t cal); - -el_val_t local_date_year(el_val_t ld); -el_val_t local_date_month(el_val_t ld); -el_val_t local_date_day(el_val_t ld); -el_val_t local_time_hour(el_val_t lt); -el_val_t local_time_minute(el_val_t lt); -el_val_t local_time_second(el_val_t lt); -el_val_t local_time_nanos(el_val_t lt); - -el_val_t el_local_date_add_dur(el_val_t ld, el_val_t dur); -el_val_t el_local_time_add_dur(el_val_t lt, el_val_t dur); -el_val_t el_local_date_lt(el_val_t a, el_val_t b); -el_val_t el_local_date_eq(el_val_t a, el_val_t b); - -/* Rhythm — pluggable recurrence AST. Returns a heap-allocated struct - * pointer in el_val_t; rhythms are immutable so callers may share them. */ -el_val_t rhythm_cycle_start(void); -el_val_t rhythm_cycle_phase(el_val_t phase); -el_val_t rhythm_duration(el_val_t d); -el_val_t rhythm_session_start(void); -el_val_t rhythm_event(el_val_t name); -el_val_t rhythm_and(el_val_t a, el_val_t b); -el_val_t rhythm_or(el_val_t a, el_val_t b); -el_val_t rhythm_weekday(el_val_t day); -el_val_t rhythm_weekly_at(el_val_t day, el_val_t hour, el_val_t minute); -el_val_t rhythm_next_after(el_val_t r, el_val_t after, el_val_t cal); -el_val_t rhythm_matches(el_val_t r, el_val_t ct); - -/* ── UUID ────────────────────────────────────────────────────────────────── */ - -el_val_t uuid_new(void); -el_val_t uuid_v4(void); - -/* ── Environment ─────────────────────────────────────────────────────────── */ - -el_val_t env(el_val_t key); - -/* ── In-process state K/V ────────────────────────────────────────────────── */ - -el_val_t state_set(el_val_t key, el_val_t value); -el_val_t state_get(el_val_t key); -el_val_t state_del(el_val_t key); -el_val_t state_keys(void); - -/* ── Float formatting ────────────────────────────────────────────────────── */ - -el_val_t float_to_str(el_val_t f); -el_val_t int_to_float(el_val_t n); -el_val_t float_to_int(el_val_t f); -el_val_t format_float(el_val_t f, el_val_t decimals); -el_val_t decimal_round(el_val_t f, el_val_t decimals); -el_val_t str_to_float(el_val_t s); - -/* ── Math (Float-aware) ──────────────────────────────────────────────────── */ - -el_val_t math_sqrt(el_val_t f); -el_val_t math_log(el_val_t f); -el_val_t math_ln(el_val_t f); -el_val_t math_sin(el_val_t f); -el_val_t math_cos(el_val_t f); -el_val_t math_pi(void); - -/* ── String additions ────────────────────────────────────────────────────── */ - -el_val_t str_index_of(el_val_t s, el_val_t sub); -el_val_t str_split(el_val_t s, el_val_t sep); -el_val_t str_char_at(el_val_t s, el_val_t i); -el_val_t str_char_code(el_val_t s, el_val_t i); -el_val_t str_pad_left(el_val_t s, el_val_t width, el_val_t pad); -el_val_t str_pad_right(el_val_t s, el_val_t width, el_val_t pad); -el_val_t str_format(el_val_t fmt, el_val_t data); -el_val_t str_lower(el_val_t s); -el_val_t str_upper(el_val_t s); - -/* ── Text-processing primitives (Phase 1: byte/codepoint, ASCII char classes) - * Phase 2 (filed): Unicode-grapheme awareness, NFC/NFD normalization, regex. - * is_* predicates: empty input returns false; multi-char requires ALL bytes - * to match. ASCII ranges only in Phase 1. */ - -/* Counting */ -el_val_t str_count(el_val_t s, el_val_t sub); /* non-overlapping */ -el_val_t str_count_chars(el_val_t s); /* codepoint count */ -el_val_t str_count_bytes(el_val_t s); /* alias of str_len */ -el_val_t str_count_lines(el_val_t s); -el_val_t str_count_words(el_val_t s); -el_val_t str_count_letters(el_val_t s); /* ASCII [A-Za-z] */ -el_val_t str_count_digits(el_val_t s); /* ASCII [0-9] */ - -/* Find / position */ -el_val_t str_index_of_all(el_val_t s, el_val_t sub); /* [Int] of byte offsets */ -el_val_t str_last_index_of(el_val_t s, el_val_t sub); -el_val_t str_find_chars(el_val_t s, el_val_t any_of); /* first idx of any ch */ - -/* Transform */ -el_val_t str_repeat(el_val_t s, el_val_t n); -el_val_t str_reverse(el_val_t s); /* by codepoint */ -el_val_t str_strip_prefix(el_val_t s, el_val_t prefix); -el_val_t str_strip_suffix(el_val_t s, el_val_t suffix); -el_val_t str_strip_chars(el_val_t s, el_val_t chars); -el_val_t str_lstrip(el_val_t s); -el_val_t str_rstrip(el_val_t s); - -/* Char classification (Bool) */ -el_val_t is_letter(el_val_t s); -el_val_t is_digit(el_val_t s); -el_val_t is_alphanumeric(el_val_t s); -el_val_t is_whitespace(el_val_t s); -el_val_t is_punctuation(el_val_t s); -el_val_t is_uppercase(el_val_t s); -el_val_t is_lowercase(el_val_t s); - -/* Split / join */ -el_val_t str_split_lines(el_val_t s); -el_val_t str_split_chars(el_val_t s); /* alias of native_string_chars */ -el_val_t str_split_n(el_val_t s, el_val_t sep, el_val_t n); -el_val_t str_join(el_val_t list, el_val_t sep); /* alias of list_join */ - -/* ── List additions ──────────────────────────────────────────────────────── */ - -el_val_t list_push(el_val_t list, el_val_t elem); -el_val_t list_push_front(el_val_t list, el_val_t elem); -el_val_t list_join(el_val_t list, el_val_t sep); -el_val_t list_range(el_val_t start, el_val_t end); - -/* ── Bool helpers ────────────────────────────────────────────────────────── */ - -el_val_t bool_to_str(el_val_t b); - -/* ── Numeric parsing ─────────────────────────────────────────────────────── */ - -el_val_t parse_int(el_val_t s, el_val_t default_val); - -/* ── Process ─────────────────────────────────────────────────────────────── */ - -void exit_program(el_val_t code); -el_val_t getpid_now(void); - -/* ── CGI identity ───────────────────────────────────────────────────────────── - * Called at the start of main() in CGI programs (those with a `cgi {}` block). - * Records the program's DHARMA identity before any other code executes. */ - -void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, - el_val_t network, el_val_t engram); - -/* ── DHARMA network builtins ───────────────────────────────────────────────── - * Available to CGI programs (declared with a `cgi {}` block). - * - * Peers are addressed by `dharma_id` of the form - * "@" e.g. "ntn-genesis@http://localhost:7770" - * If the @ portion is omitted, transport defaults to - * "http://localhost:7770" (the local CGI daemon assumption). - * - * Wire protocol (all peers expose): - * POST /dharma/recv { channel, from, content } → response body - * POST /dharma/event { type, payload, source, timestamp } - * POST /api/activate { query } → list of nodes - * - * Hosting application's responsibility: an El program with a `cgi {}` block - * runs http_serve() with its own request handler; that handler should route - * "/dharma/event" requests by calling el_runtime_dharma_event_arrive() so - * incoming events feed dharma_field() queues. The runtime itself does not - * intercept any /dharma path. */ - -el_val_t dharma_connect(el_val_t cgi_id); -el_val_t dharma_send(el_val_t channel, el_val_t content); -el_val_t dharma_activate(el_val_t query); -void dharma_emit(el_val_t event_type, el_val_t payload); -el_val_t dharma_field(el_val_t event_type); -void dharma_strengthen(el_val_t cgi_id, el_val_t weight); -el_val_t dharma_relationship(el_val_t cgi_id); -el_val_t dharma_peers(void); - -/* Public C API: called by an El program's HTTP handler when a /dharma/event - * request arrives. Pushes onto the per-event-type queue and signals any - * pending dharma_field() blockers. All three arguments must be NUL-terminated - * C strings (or NULL — then treated as empty). */ -void el_runtime_dharma_event_arrive(const char* event_type, - const char* payload, - const char* source); - -/* ── Engram local graph primitives ─────────────────────────────────────────── - * Operate on the CGI's local Engram knowledge graph. - * `engram_activate` queries the local graph only; `dharma_activate` is - * network-wide across all connected CGI graphs. */ - -el_val_t engram_node(el_val_t content, el_val_t node_type, el_val_t salience); -el_val_t engram_node_full(el_val_t content, el_val_t node_type, el_val_t label, - el_val_t salience, el_val_t importance, el_val_t confidence, - el_val_t tier, el_val_t tags); -/* Layered consciousness — see el_runtime.c for the layered architecture - * design notes (search "Layered consciousness architecture"). The five - * canonical layers (safety / core-identity / domain-knowledge / imprint / - * suit) are seeded automatically; engram_add_layer extends the registry - * with imprint or suit overlays at runtime. Nodes default to layer 1 - * (core-identity) when created via engram_node / engram_node_full. */ -el_val_t engram_node_layered(el_val_t content, el_val_t node_type, el_val_t label, - el_val_t salience, el_val_t certainty, el_val_t confidence, - el_val_t status, el_val_t tags, el_val_t layer_id); -el_val_t engram_add_layer(el_val_t name, el_val_t priority, el_val_t suppressible, - el_val_t transparent, el_val_t injectable); -el_val_t engram_remove_layer(el_val_t layer_id); -el_val_t engram_list_layers(void); -el_val_t engram_get_node(el_val_t id); -void engram_strengthen(el_val_t node_id); -void engram_forget(el_val_t node_id); -el_val_t engram_node_count(void); -el_val_t engram_search(el_val_t query, el_val_t limit); -el_val_t engram_scan_nodes(el_val_t limit, el_val_t offset); -void engram_connect(el_val_t from_id, el_val_t to_id, el_val_t weight, el_val_t relation); -el_val_t engram_edge_between(el_val_t from_id, el_val_t to_id); -el_val_t engram_neighbors(el_val_t node_id); -el_val_t engram_neighbors_filtered(el_val_t node_id, el_val_t max_depth, el_val_t direction); -el_val_t engram_edge_count(void); -/* Three-pass activation: background fan-out → working-memory promotion → - * Layer 0 override. See "Three-pass activation" in el_runtime.c. */ -el_val_t engram_activate(el_val_t query, el_val_t depth); -el_val_t engram_save(el_val_t path); -el_val_t engram_load(el_val_t path); - -/* JSON-string accessors — return pre-serialized JSON so HTTP handlers - * can pass results straight through without round-tripping ElList/ElMap - * through json_stringify. */ -el_val_t engram_get_node_json(el_val_t id); -el_val_t engram_search_json(el_val_t query, el_val_t limit); -el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset); -el_val_t engram_scan_nodes_by_type_json(el_val_t node_type, el_val_t limit, el_val_t offset); -el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction); -el_val_t engram_activate_json(el_val_t query, el_val_t depth); -el_val_t engram_stats_json(void); -el_val_t engram_list_layers_json(void); -/* engram_compile_layered_json — produce a prompt-ready text block split - * into "[LAYER 0 — STRUCTURAL]" (non-suppressible layers, sacred fire) - * and "[ENGRAM CONTEXT]" (standard suppressible layers). Returns "" if - * no nodes promoted to working memory. */ -el_val_t engram_compile_layered_json(el_val_t intent, el_val_t depth); - -/* ── LLM (Anthropic API client) ───────────────────────────────────────────── - * All functions call https://api.anthropic.com/v1/messages with the API key - * from env ANTHROPIC_API_KEY. Default model when empty: claude-sonnet-4-5. */ - -el_val_t llm_call(el_val_t model, el_val_t prompt); -el_val_t llm_call_system(el_val_t model, el_val_t system_prompt, el_val_t user_prompt); -el_val_t llm_call_agentic(el_val_t model, el_val_t system, el_val_t user, el_val_t tools); -el_val_t llm_vision(el_val_t model, el_val_t system, el_val_t prompt, el_val_t image_url_or_b64); -el_val_t llm_models(void); - -/* Register a tool handler by name. The handler is looked up via dlsym - * (mirroring http_set_handler), so any El `fn (input)` compiles to - * a global C symbol that this function can locate at runtime. - * Handler signature: `el_val_t handler(el_val_t input_json)` — receives - * the tool input as a JSON-string el_val_t and returns a JSON-string - * el_val_t result. Used by llm_call_agentic. */ -void llm_register_tool(el_val_t name, el_val_t handler_fn_name); - -/* ── args() ───────────────────────────────────────────────────────────────── - * Provides access to command-line arguments passed to the program. - * Populated by el_runtime_init_args() before main() runs. */ - -el_val_t args(void); -void el_runtime_init_args(int argc, char** argv); - -/* ── Crypto primitives ───────────────────────────────────────────────────── - * SHA-256, HMAC-SHA-256, and base64 (standard + URL-safe). - * Self-contained — no OpenSSL/libcrypto dependency. The implementations are - * adapted from public-domain reference code (Brad Conte / RFC 4648). - * - * Bytes-returning variants (sha256_bytes, hmac_sha256_bytes) return a string - * value whose contents are raw binary; callers usually feed these into - * base64_encode. Note that el_val_t strings are NUL-terminated by convention, - * so the binary payload may contain embedded NULs — pass it directly into - * base64_encode (which uses an explicit length) rather than treating it as - * a printable C string. - * - * The "base64" variants emit/accept RFC 4648 standard alphabet with padding. - * The "base64url" variants use URL-safe alphabet (`-`/`_`) with no padding, - * as used in JWTs. */ - -el_val_t sha256_hex(el_val_t input); -el_val_t sha256_bytes(el_val_t input); -el_val_t hmac_sha256_hex(el_val_t key, el_val_t message); -el_val_t hmac_sha256_bytes(el_val_t key, el_val_t message); -el_val_t base64_encode(el_val_t input); -el_val_t base64_decode(el_val_t input); -el_val_t base64url_encode(el_val_t input); -el_val_t base64url_decode(el_val_t input); - -/* Length-aware variants (internal — exposed for the rare caller that already - * has a known-length binary buffer and doesn't want to round-trip through - * a NUL-terminated el_val_t string). Sha256_bytes and hmac_sha256_bytes feed - * these implicitly. */ -el_val_t el_sha256_bytes_n(const unsigned char* data, size_t len); -el_val_t el_base64_encode_n(const unsigned char* data, size_t len, int url_safe); - -/* ── Post-quantum primitives (liboqs-backed) ──────────────────────────────── - * All inputs/outputs hex-encoded. Algorithm choices: - * Signature: CRYSTALS-Dilithium-3 (NIST level 3, balanced) - * KEM: CRYSTALS-Kyber-768 (NIST level 3) - * Hash: SHA3-256 (Keccak) (PQ-aware protocols favour SHA3 over SHA2) - * - * If liboqs is not linked (detected via __has_include() at compile - * time), the pq_* entry points return a JSON-shaped error string so callers - * fail loudly rather than silently fall back to classical schemes: - * {"error":"liboqs not linked, post-quantum primitives unavailable"} - * - * The hybrid handshake pairs X25519 with Kyber-768 per NIST PQ guidance and - * CNSA 2.0. Combined shared secret is HKDF-SHA256(x25519_ss || kyber_ss). - * Even if Kyber falls, X25519 holds; if X25519 falls under quantum attack, - * Kyber holds. SHA3-256 also remains usable independent of liboqs (the - * Keccak permutation is PQ-OK as a primitive). */ - -el_val_t pq_keygen_signature(void); -el_val_t pq_sign(el_val_t secret_key_hex, el_val_t message); -el_val_t pq_verify(el_val_t public_key_hex, el_val_t message, el_val_t signature_hex); - -el_val_t pq_kem_keygen(void); -el_val_t pq_kem_encaps(el_val_t public_key_hex); -el_val_t pq_kem_decaps(el_val_t secret_key_hex, el_val_t ciphertext_hex); - -el_val_t pq_hybrid_keygen(void); -el_val_t pq_hybrid_handshake(el_val_t remote_pub_combined); - -el_val_t sha3_256_hex(el_val_t input); - -/* ── AEAD: AES-256-GCM (libcrypto-backed) ─────────────────────────────────── - * Symmetric authenticated encryption used to wrap envelopes after a KEM - * handshake. Caller MUST supply a 32-byte key (64 hex chars) — typically the - * Kyber-768 / hybrid shared_secret, optionally normalized via SHA3-256. - * - * aead_encrypt returns a JSON map {"nonce":"...","ciphertext":"..."} where - * ciphertext is the AES-256-GCM output with the 16-byte auth tag appended. - * Nonce is a fresh 12-byte CSPRNG draw — callers never pick the nonce, which - * structurally rules out the GCM nonce-reuse footgun. - * - * aead_decrypt returns the plaintext String, or "" on any failure (including - * auth-tag mismatch). Callers MUST check for "" before trusting the result. */ -el_val_t aead_encrypt(el_val_t key_hex, el_val_t plaintext); -el_val_t aead_decrypt(el_val_t key_hex, el_val_t nonce_hex, el_val_t ciphertext_hex); - -/* ── Native VM builtin aliases (for compiled El source) ───────────────────── - * These match the El VM's native_* builtins so that El source compiled - * to C can call the same names without modification. */ - -el_val_t native_list_get(el_val_t list, el_val_t index); -el_val_t native_list_len(el_val_t list); -el_val_t native_list_append(el_val_t list, el_val_t elem); -el_val_t native_list_empty(void); -el_val_t native_list_clone(el_val_t list); -el_val_t native_string_chars(el_val_t s); -el_val_t native_int_to_str(el_val_t n); - -/* ── Method-call shorthand aliases ────────────────────────────────────────── - * The El method-call convention `obj.method(args)` compiles to - * `method(obj, args)`. These aliases expose the runtime functions under - * the short names that result from method calls in El source. - * - * Example: `myList.append(x)` → `append(myList, x)` (calls this alias) - * `myList.len()` → `len(myList)` (calls this alias) */ - -el_val_t append(el_val_t list, el_val_t elem); /* el_list_append */ -el_val_t len(el_val_t list); /* el_list_len */ -el_val_t get(el_val_t list, el_val_t index); /* el_list_get */ -el_val_t map_get(el_val_t map, el_val_t key); /* el_map_get */ -el_val_t map_set(el_val_t map, el_val_t key, el_val_t value); /* el_map_set */ - -/* ── OTLP/HTTP Observability ─────────────────────────────────────────────── */ -/* See bottom of el_runtime.c for the implementation. - * Configured by env vars OTLP_ENDPOINT, OTEL_SERVICE_NAME, OTEL_SERVICE_VERSION. - * No-op when OTLP_ENDPOINT is unset. Drop-on-failure semantics. */ -/* ── Subprocess execution ────────────────────────────────────────────────── */ -el_val_t exec_command(el_val_t cmd); /* run shell command, return exit code */ -el_val_t exec_capture(el_val_t cmd); /* run shell command, capture stdout */ -el_val_t exec(el_val_t cmd); /* exec(cmd) → stdout String (30s timeout) */ -el_val_t exec_bg(el_val_t cmd); /* exec_bg(cmd) → PID String (non-blocking) */ - -el_val_t emit_log(el_val_t level, el_val_t msg, el_val_t fields_json); -el_val_t emit_metric(el_val_t name, el_val_t value, el_val_t tags_json); -el_val_t trace_span_start(el_val_t name); -el_val_t trace_span_end(el_val_t span_handle); -el_val_t emit_event(el_val_t name, el_val_t duration_ms); - -#ifdef __cplusplus -} -#endif diff --git a/lang/el-compiler/src/codegen-js.el b/lang/el-compiler/src/codegen-js.el index 7e44b41..f2fe025 100644 --- a/lang/el-compiler/src/codegen-js.el +++ b/lang/el-compiler/src/codegen-js.el @@ -1202,7 +1202,7 @@ fn codegen_js_inner(stmts: [Map], source: String, bundle_mode: Bool js_emit_line(js_strip_es_exports(runtime_content)) js_emit_line("") } else { - js_emit_line("// Runtime: foundation/el/el-compiler/runtime/el_runtime.js") + js_emit_line("// Runtime: foundation/el/runtime/el_runtime.js") js_emit_line("import \"./el_runtime.js\";") } // In module mode: destructure all builtins off globalThis.__el so call diff --git a/lang/elb.el b/lang/elb.el index ba77089..ece57d7 100644 --- a/lang/elb.el +++ b/lang/elb.el @@ -368,13 +368,13 @@ fn main() -> Void { let which_out: String = str_trim(exec_capture("which " + elc_bin + " 2>/dev/null")) if !str_eq(which_out, "") { let elc_dir: String = dirname_of(which_out) - runtime_path = elc_dir + "/../el-compiler/runtime/el_runtime.c" + runtime_path = elc_dir + "/../runtime/el_runtime.c" } } // If --runtime points to a directory, auto-locate el_runtime.c inside it. // This lets both forms work: - // --runtime=/opt/el/el-compiler/runtime (directory form) - // --runtime=/opt/el/el-compiler/runtime/el_runtime.c (file form) + // --runtime=/opt/el/runtime (directory form) + // --runtime=/opt/el/runtime/el_runtime.c (file form) if !str_eq(runtime_path, "") { let is_dir: String = str_trim(exec_capture("test -d " + runtime_path + " && echo dir || echo file")) if str_eq(is_dir, "dir") { diff --git a/lang/examples/html-page.el b/lang/examples/html-page.el index 95019ff..aa1e64b 100644 --- a/lang/examples/html-page.el +++ b/lang/examples/html-page.el @@ -6,8 +6,8 @@ // // Compile and run: // ./dist/platform/elc examples/html-page.el > /tmp/html-page.c -// cc -std=c11 -I el-compiler/runtime -lcurl -lpthread \ -// -o /tmp/html-page /tmp/html-page.c el-compiler/runtime/el_runtime.c +// cc -std=c11 -I runtime -lcurl -lpthread \ +// -o /tmp/html-page /tmp/html-page.c runtime/el_runtime.c // /tmp/html-page fn render_item(item: String) -> String { diff --git a/lang/releases/v1.0.0-20260501/RELEASE.md b/lang/releases/v1.0.0-20260501/RELEASE.md deleted file mode 100644 index 280af6e..0000000 --- a/lang/releases/v1.0.0-20260501/RELEASE.md +++ /dev/null @@ -1,28 +0,0 @@ -# El Compiler Release v1.0.0 — 2026-05-02 - -## Components -- `bootstrap.py` — El language compiler (Python, recursive descent parser, emits C) -- `el_runtime.c` — El runtime (C, HTTP server, engram, DHARMA, LLM chain) -- `el_runtime.h` — Runtime public API header - -## Changes in this release - -### Critical bug fixes -- `state_set`/`state_get` are now thread-safe (pthread_mutex). Was racing across 64 worker threads. -- `looks_like_string` threshold raised from 1,000,000 to 4GB. Unix timestamps were being dereferenced as heap pointers. -- `fs_read` guards against negative `ftell` result (pipe/special file overflow). - -### Engram architecture (major) -- Two-layer activation: `background_activation` (Layer 1, broad fan-out) + `working_memory_weight` (Layer 2, executive filter) -- Inhibitory edges: `EngramEdge.inhibitory` flag suppresses working memory promotion without affecting background activation -- Suppression memory: `suppression_count` — nodes activated-but-suppressed accumulate pressure toward breakthrough -- Temporal decay: `temporal_decay_rate`, `created_at`, `last_activated_at`, `activation_count` on EngramNode -- Per-type activation thresholds (Safety: 0.05, Canonical: 0.15, Lesson: 0.25, Note: 0.40) -- Temporal range query: `engram_query_range(start_ms, end_ms)` -- Layered consciousness: `EngramLayer` struct, `layer_id` on nodes and edges, `EngramStore.layers[]` -- Layer 0 override pass: safety layer fires last and cannot be suppressed - -## SHA256 -bootstrap.py -el_runtime.c -el_runtime.h diff --git a/lang/el-compiler/runtime/ElBridge.java b/lang/runtime/ElBridge.java similarity index 100% rename from lang/el-compiler/runtime/ElBridge.java rename to lang/runtime/ElBridge.java diff --git a/lang/el-compiler/runtime/PLATFORM_BRIDGE_SPEC.md b/lang/runtime/PLATFORM_BRIDGE_SPEC.md similarity index 100% rename from lang/el-compiler/runtime/PLATFORM_BRIDGE_SPEC.md rename to lang/runtime/PLATFORM_BRIDGE_SPEC.md diff --git a/lang/el-compiler/runtime/detect-platforms b/lang/runtime/detect-platforms similarity index 99% rename from lang/el-compiler/runtime/detect-platforms rename to lang/runtime/detect-platforms index bceace2..b47e348 100755 --- a/lang/el-compiler/runtime/detect-platforms +++ b/lang/runtime/detect-platforms @@ -132,7 +132,7 @@ if [[ $LVGL_OK -eq 1 ]]; then else _miss "LVGL/MCU" "-DEL_TARGET_LVGL (lvgl.h not found)" echo " Install: git clone https://github.com/lvgl/lvgl" - echo " (place lvgl/ next to el-compiler/runtime/)" + echo " (place lvgl/ next to runtime/)" MISSING=$((MISSING + 1)) fi diff --git a/lang/el-compiler/runtime/el_android.c b/lang/runtime/el_android.c similarity index 100% rename from lang/el-compiler/runtime/el_android.c rename to lang/runtime/el_android.c diff --git a/lang/el-compiler/runtime/el_appkit.m b/lang/runtime/el_appkit.m similarity index 100% rename from lang/el-compiler/runtime/el_appkit.m rename to lang/runtime/el_appkit.m diff --git a/lang/el-compiler/runtime/el_gtk4.c b/lang/runtime/el_gtk4.c similarity index 100% rename from lang/el-compiler/runtime/el_gtk4.c rename to lang/runtime/el_gtk4.c diff --git a/lang/el-compiler/runtime/el_lvgl.c b/lang/runtime/el_lvgl.c similarity index 100% rename from lang/el-compiler/runtime/el_lvgl.c rename to lang/runtime/el_lvgl.c diff --git a/lang/el-compiler/runtime/el_native_target.h b/lang/runtime/el_native_target.h similarity index 100% rename from lang/el-compiler/runtime/el_native_target.h rename to lang/runtime/el_native_target.h diff --git a/lang/el-compiler/runtime/el_platform_win.h b/lang/runtime/el_platform_win.h similarity index 100% rename from lang/el-compiler/runtime/el_platform_win.h rename to lang/runtime/el_platform_win.h diff --git a/lang/releases/v1.0.0-20260501/el_runtime.c b/lang/runtime/el_runtime.c similarity index 95% rename from lang/releases/v1.0.0-20260501/el_runtime.c rename to lang/runtime/el_runtime.c index e52d157..a154e05 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.c +++ b/lang/runtime/el_runtime.c @@ -10275,6 +10275,654 @@ el_val_t engram_load_merge(el_val_t path) { return (el_val_t)added_nodes; } +/* ══════════════════════════════════════════════════════════════════════════ + * Engram WAL (write-ahead log) + compaction + integrity hardening. + * + * Design: docs/architecture/design/engram-storage-engine-wal.md §§3-14, §18. + * Whole feature is gated behind ENGRAM_WAL=on (default off → byte-identical + * to the snapshot-as-store behavior). When on, structural mutations append a + * framed, CRC'd record to

/engram.wal instead of rewriting the full + * snapshot; boot replays the WAL over the base snapshot; a size threshold + * triggers compaction (fresh snapshot + WAL truncate). + * + * Record framing (little-endian native; single-machine prototype): + * [u32 magic 'EWL1'][u32 payload_len][u8 op][u8 flags][u64 lsn] + * [u32 crc32][payload…] + * crc32 covers op|flags|lsn|payload. A record whose magic/length/crc fails + * validation marks end-of-valid-log (torn tail from a crash → replay stops + * cleanly, never crashes). + * ══════════════════════════════════════════════════════════════════════════ */ + +#define EG_WAL_MAGIC 0x314C5745u /* 'E''W''L''1' */ +#define EG_WAL_HDR_LEN 22 /* 4+4+1+1+8+4 */ + +/* Op codes (§5). NODE_PUT/EDGE_PUT are id-keyed upserts (replay-idempotent). */ +enum { + EG_OP_NODE_PUT = 1, + EG_OP_EDGE_PUT = 2, + EG_OP_TOMBSTONE = 3, + EG_OP_SUPERSEDE = 4, + EG_OP_LAYER_PUT = 5, + EG_OP_LAYER_DEL = 6, + EG_OP_FORGET = 7, + EG_OP_HEBB_BATCH = 8, + EG_OP_COMPACT_MARK = 9 +}; + +/* ── crc32 (IEEE 802.3, reflected, poly 0xEDB88320) ────────────────────────── + * init 0xFFFFFFFF, final XOR 0xFFFFFFFF. Known answers: + * crc32("") == 0x00000000 + * crc32("123456789") == 0xCBF43926 (the canonical check value) + * eg_crc32_update takes/returns the *internal* (pre-final-xor) running value + * so a checksum can be computed across several buffers. */ +static uint32_t eg_crc32_table[256]; +static int eg_crc32_ready = 0; +static void eg_crc32_init(void) { + for (uint32_t i = 0; i < 256; i++) { + uint32_t c = i; + for (int k = 0; k < 8; k++) + c = (c & 1) ? (0xEDB88320u ^ (c >> 1)) : (c >> 1); + eg_crc32_table[i] = c; + } + eg_crc32_ready = 1; +} +static uint32_t eg_crc32_update(uint32_t crc, const void* data, size_t n) { + if (!eg_crc32_ready) eg_crc32_init(); + const uint8_t* d = (const uint8_t*)data; + for (size_t i = 0; i < n; i++) + crc = eg_crc32_table[(crc ^ d[i]) & 0xFF] ^ (crc >> 8); + return crc; +} +static uint32_t eg_crc32(const void* data, size_t n) { + return eg_crc32_update(0xFFFFFFFFu, data, n) ^ 0xFFFFFFFFu; +} +/* crc over a record's covered bytes: op|flags|lsn|payload. */ +static uint32_t eg_wal_record_crc(uint8_t op, uint8_t flags, uint64_t lsn, + const char* payload, size_t plen) { + uint32_t c = 0xFFFFFFFFu; + c = eg_crc32_update(c, &op, 1); + c = eg_crc32_update(c, &flags, 1); + c = eg_crc32_update(c, &lsn, sizeof(lsn)); + if (plen) c = eg_crc32_update(c, payload, plen); + return c ^ 0xFFFFFFFFu; +} + +/* EL builtin: crc32 of a string (known-answer unit tests / debugging). */ +el_val_t engram_crc32(el_val_t s) { + const char* p = EL_CSTR(s); + if (!p) return (el_val_t)0; + return (el_val_t)(int64_t)(uint32_t)eg_crc32(p, strlen(p)); +} + +/* ── WAL runtime state (single log per process — engram is single-threaded) ── */ +typedef struct { + FILE* fp; /* append handle, or NULL when closed */ + char path[1024]; /* /engram.wal */ + uint64_t lsn; /* last assigned lsn; next record = lsn+1 */ + uint64_t uncommitted; /* records appended since last fsync */ + int64_t last_sync_ms; /* wall clock of last fsync */ + int64_t bytes; /* current WAL size (for compaction trigger) */ +} EngramWal; +static EngramWal eg_wal = { NULL, {0}, 0, 0, 0, 0 }; + +static int eg_wal_sync_mode(void) { + /* ENGRAM_WAL_SYNC=always|group|off (default group). */ + const char* m = getenv("ENGRAM_WAL_SYNC"); + if (m && strcmp(m, "always") == 0) return 2; + if (m && strcmp(m, "off") == 0) return 0; + return 1; /* group */ +} +static int64_t eg_wal_group_ms(void) { + const char* v = getenv("ENGRAM_WAL_SYNC_MS"); + if (v && *v) { long n = strtol(v, NULL, 10); if (n > 0) return n; } + return 50; /* §5: N≈50ms */ +} +static int64_t eg_wal_compact_bytes(void) { + const char* v = getenv("ENGRAM_WAL_COMPACT_BYTES"); + if (v && *v) { long long n = strtoll(v, NULL, 10); if (n > 0) return n; } + return 32LL * 1024 * 1024; /* §7 default 32 MB */ +} + +int engram_wal_enabled(void) { + const char* f = getenv("ENGRAM_WAL"); + return (f && (strcmp(f, "on") == 0 || strcmp(f, "1") == 0)) ? 1 : 0; +} + +/* Force the WAL to durable storage per the commit policy. force=1 (used by + * compaction / explicit commit) always fsyncs; otherwise group policy. */ +static void eg_wal_commit(int force) { + if (!eg_wal.fp) return; + int mode = eg_wal_sync_mode(); + if (mode == 0 && !force) { fflush(eg_wal.fp); return; } + if (!force && mode == 1) { + int64_t now = engram_now_ms(); + if (eg_wal.uncommitted == 0) return; + if (now - eg_wal.last_sync_ms < eg_wal_group_ms()) { fflush(eg_wal.fp); return; } + } + fflush(eg_wal.fp); + fsync(fileno(eg_wal.fp)); + eg_wal.uncommitted = 0; + eg_wal.last_sync_ms = engram_now_ms(); +} + +/* Append one framed+CRC'd record. Returns 1 on success, 0 on I/O failure + * (caller keeps the mutation in RAM; no corruption — §11 disk-full row). */ +static int eg_wal_write(uint8_t op, uint8_t flags, const char* payload, size_t plen) { + if (!eg_wal.fp) return 0; + /* Remember the pre-record offset so a partial write (e.g. ENOSPC mid- + * record) can be rolled back — otherwise a torn record would sit in the + * MIDDLE of the log and prematurely end replay of everything after it. + * We roll back to a clean record boundary and report failure; the caller + * keeps the mutation in RAM (§11 disk-full row). */ + long start = ftell(eg_wal.fp); + uint64_t lsn = ++eg_wal.lsn; + uint32_t magic = EG_WAL_MAGIC; + uint32_t len32 = (uint32_t)plen; + uint32_t crc = eg_wal_record_crc(op, flags, lsn, payload, plen); + uint8_t hdr[EG_WAL_HDR_LEN]; + memcpy(hdr + 0, &magic, 4); + memcpy(hdr + 4, &len32, 4); + hdr[8] = op; hdr[9] = flags; + memcpy(hdr + 10, &lsn, 8); + memcpy(hdr + 18, &crc, 4); + int ok = (fwrite(hdr, 1, EG_WAL_HDR_LEN, eg_wal.fp) == EG_WAL_HDR_LEN); + if (ok && plen) ok = (fwrite(payload, 1, plen, eg_wal.fp) == plen); + if (!ok) { + eg_wal.lsn--; /* reclaim the lsn */ + fflush(eg_wal.fp); + if (start >= 0) { + if (ftruncate(fileno(eg_wal.fp), start) == 0) {} /* drop torn bytes */ + fseek(eg_wal.fp, 0, SEEK_END); + } + return 0; + } + eg_wal.bytes += EG_WAL_HDR_LEN + (int64_t)plen; + eg_wal.uncommitted++; + eg_wal_commit(0); + return 1; +} + +/* ── Single-record apply (replay + live are the same code path) ───────────── */ + +/* Populate an EngramNode (freshly memset OR an existing node being overwritten + * in place) from a node JSON object. Mirrors engram_load's field set exactly, + * WITHOUT the boot-time working_memory_weight laundering, so replay reproduces + * the exact logged state (parity with the direct-apply oracle). Caller owns + * freeing prior heap fields when overwriting. */ +static void eg_fill_node_from_json(EngramNode* nn, const char* obj) { + nn->id = eg_get_str_field(obj, "id"); + nn->content = eg_get_str_field(obj, "content"); + nn->node_type = eg_get_str_field(obj, "node_type"); + nn->label = eg_get_str_field(obj, "label"); + nn->tier = eg_get_str_field(obj, "tier"); + nn->tags = eg_get_str_field(obj, "tags"); + nn->metadata = eg_get_str_field(obj, "metadata"); + if (!nn->metadata || !*nn->metadata) { free(nn->metadata); nn->metadata = el_strdup_persist("{}"); } + nn->salience = eg_get_num_field(obj, "salience"); + nn->importance = eg_get_num_field(obj, "importance"); + nn->confidence = eg_get_num_field(obj, "confidence"); + nn->temporal_decay_rate = eg_get_num_field(obj, "temporal_decay_rate"); + nn->activation_count = eg_get_int_field(obj, "activation_count"); + nn->last_activated = eg_get_int_field(obj, "last_activated"); + nn->created_at = eg_get_int_field(obj, "created_at"); + nn->updated_at = eg_get_int_field(obj, "updated_at"); + nn->background_activation = eg_get_num_field(obj, "background_activation"); + nn->working_memory_weight = eg_get_num_field(obj, "working_memory_weight"); + nn->suppression_count = (int32_t)eg_get_int_field(obj, "suppression_count"); + if (json_find_key(obj, "layer_id")) nn->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); + else nn->layer_id = ENGRAM_LAYER_DEFAULT; + nn->wm_anchor = eg_get_num_field(obj, "wm_anchor"); + { char* ats = eg_get_str_field(obj, "access_ts"); if (ats) { engram_bll_parse_access(nn, ats); free(ats); } } + { char* es = eg_get_str_field(obj, "emb"); if (es) { eg_parse_emb(nn, es); free(es); } } +} + +static void eg_free_node_heap(EngramNode* n) { + free(n->id); free(n->content); free(n->node_type); free(n->label); + free(n->tier); free(n->tags); free(n->metadata); free(n->emb); +} +static void eg_free_edge_heap(EngramEdge* e) { + free(e->id); free(e->from_id); free(e->to_id); free(e->relation); free(e->metadata); +} + +/* Upsert a node by id. Idempotent: replaying the same NODE_PUT twice yields + * the same single node. */ +static void eg_apply_node_put(const char* obj) { + EngramStore* g = engram_get(); + char* id = eg_get_str_field(obj, "id"); + if (!id || !*id) { free(id); return; } + int64_t idx = engram_find_node_index(id); + if (idx >= 0) { + EngramNode* n = &g->nodes[idx]; + int32_t emb_dim = n->emb_dim; (void)emb_dim; + eg_free_node_heap(n); + memset(n, 0, sizeof(*n)); + eg_fill_node_from_json(n, obj); + /* id unchanged → id_map entry (which owns its own key copy) stays + * valid; no re-put needed. */ + } else { + engram_grow_nodes(); + EngramNode* n = &g->nodes[g->node_count]; + memset(n, 0, sizeof(*n)); + eg_fill_node_from_json(n, obj); + int64_t ni = g->node_count; + g->node_count++; + if (n->id && *n->id) engram_idmap_put(g, n->id, ni); + } + g->adj_dirty = 1; + free(id); +} + +static int64_t eg_find_edge_index(EngramStore* g, const char* id) { + if (!id || !*id) return -1; + for (int64_t i = 0; i < g->edge_count; i++) + if (g->edges[i].id && strcmp(g->edges[i].id, id) == 0) return i; + return -1; +} +static void eg_fill_edge_from_json(EngramEdge* ee, const char* obj) { + ee->id = eg_get_str_field(obj, "id"); + ee->from_id = eg_get_str_field(obj, "from_id"); + ee->to_id = eg_get_str_field(obj, "to_id"); + ee->relation = eg_get_str_field(obj, "relation"); + ee->metadata = eg_get_str_field(obj, "metadata"); + if (!ee->metadata || !*ee->metadata) { free(ee->metadata); ee->metadata = el_strdup_persist("{}"); } + ee->weight = eg_get_num_field(obj, "weight"); + ee->hebb = eg_get_num_field(obj, "hebb"); + ee->confidence = eg_get_num_field(obj, "confidence"); + ee->created_at = eg_get_int_field(obj, "created_at"); + ee->updated_at = eg_get_int_field(obj, "updated_at"); + ee->last_fired = eg_get_int_field(obj, "last_fired"); + ee->inhibitory = (int)eg_get_int_field(obj, "inhibitory"); + if (json_find_key(obj, "layer_id")) ee->layer_id = (uint32_t)eg_get_int_field(obj, "layer_id"); + else ee->layer_id = ENGRAM_LAYER_DEFAULT; +} +static void eg_apply_edge_put(const char* obj) { + EngramStore* g = engram_get(); + char* id = eg_get_str_field(obj, "id"); + int64_t idx = eg_find_edge_index(g, id); + if (idx >= 0) { + EngramEdge* e = &g->edges[idx]; + eg_free_edge_heap(e); + memset(e, 0, sizeof(*e)); + eg_fill_edge_from_json(e, obj); + } else { + engram_grow_edges(); + EngramEdge* e = &g->edges[g->edge_count]; + memset(e, 0, sizeof(*e)); + eg_fill_edge_from_json(e, obj); + g->edge_count++; + } + g->adj_dirty = 1; + free(id); +} + +/* TOMBSTONE / SUPERSEDE — store-level soft markers on the node's metadata. + * (The server's DELETE route uses the higher-level marker-node model; these + * ops exist for completeness and are replay-idempotent.) */ +static void eg_apply_meta_marker(const char* obj, const char* markerfield, const char* from) { + EngramStore* g = engram_get(); + char* id = eg_get_str_field(obj, "id"); + int64_t idx = engram_find_node_index(id); + if (idx >= 0) { + EngramNode* n = &g->nodes[idx]; + char* by = from ? eg_get_str_field(obj, from) : NULL; + size_t need = strlen(markerfield) + (by ? strlen(by) : 4) + 32; + char* meta = (char*)malloc(need); + if (by && *by) snprintf(meta, need, "{\"%s\":\"%s\"}", markerfield, by); + else snprintf(meta, need, "{\"%s\":1}", markerfield); + free(n->metadata); n->metadata = el_strdup_persist(meta); + free(meta); free(by); + } + free(id); +} + +static void eg_apply_layer_put(const char* obj) { + EngramStore* g = engram_get(); + uint32_t lid = (uint32_t)eg_get_int_field(obj, "layer_id"); + EngramLayer* L = NULL; + for (size_t i = 0; i < g->layer_count; i++) + if (g->layers[i].layer_id == lid) { L = &g->layers[i]; break; } + if (!L) { + if (g->layer_count >= g->layer_capacity) { + size_t nc = g->layer_capacity ? g->layer_capacity * 2 : 16; + EngramLayer* grown = realloc(g->layers, nc * sizeof(EngramLayer)); + if (!grown) return; + memset(grown + g->layer_capacity, 0, (nc - g->layer_capacity) * sizeof(EngramLayer)); + g->layers = grown; g->layer_capacity = nc; + } + L = &g->layers[g->layer_count++]; + memset(L, 0, sizeof(*L)); + } else if (L->name) { free(L->name); L->name = NULL; } + L->layer_id = lid; + L->activation_priority = (uint32_t)eg_get_int_field(obj, "activation_priority"); + L->suppressible = (int)eg_get_int_field(obj, "suppressible") ? 1 : 0; + L->transparent = (int)eg_get_int_field(obj, "transparent") ? 1 : 0; + L->injectable = (int)eg_get_int_field(obj, "injectable") ? 1 : 0; + char* nm = eg_get_str_field(obj, "name"); + L->name = el_strdup_persist(nm && *nm ? nm : ""); + free(nm); +} +static void eg_apply_layer_del(const char* obj) { + EngramStore* g = engram_get(); + uint32_t lid = (uint32_t)eg_get_int_field(obj, "layer_id"); + for (size_t i = 0; i < g->layer_count; i++) + if (g->layers[i].layer_id == lid && g->layers[i].name) { + free(g->layers[i].name); g->layers[i].name = NULL; break; + } +} +static void eg_apply_forget(const char* obj) { + char* id = eg_get_str_field(obj, "id"); + if (id && *id) engram_forget((el_val_t)(uintptr_t)id); + free(id); +} + +/* Apply one decoded record to the in-RAM store. HEBB_BATCH payload is a JSON + * object {"edges":[edge,…]} — one record, one fsync, N edge upserts (§5-B). */ +static void eg_wal_apply(uint8_t op, const char* payload, size_t plen) { + char* obj = (char*)malloc(plen + 1); + if (!obj) return; + memcpy(obj, payload, plen); obj[plen] = '\0'; + switch (op) { + case EG_OP_NODE_PUT: eg_apply_node_put(obj); break; + case EG_OP_EDGE_PUT: eg_apply_edge_put(obj); break; + case EG_OP_TOMBSTONE: eg_apply_meta_marker(obj, "tombstoned", NULL); break; + case EG_OP_SUPERSEDE: eg_apply_meta_marker(obj, "superseded_by", "by"); break; + case EG_OP_LAYER_PUT: eg_apply_layer_put(obj); break; + case EG_OP_LAYER_DEL: eg_apply_layer_del(obj); break; + case EG_OP_FORGET: eg_apply_forget(obj); break; + case EG_OP_HEBB_BATCH: { + const char* arr = json_find_key(obj, "edges"); + if (arr) { arr = eg_skip_ws(arr); + if (*arr == '[') { arr++; arr = eg_skip_ws(arr); + while (*arr && *arr != ']') { + if (*arr != '{') { arr++; continue; } + const char* end = json_skip_value(arr); + size_t en = (size_t)(end - arr); + char* eobj = (char*)malloc(en + 1); + memcpy(eobj, arr, en); eobj[en] = '\0'; + eg_apply_edge_put(eobj); + free(eobj); + arr = eg_skip_ws(end); + if (*arr == ',') { arr++; arr = eg_skip_ws(arr); } + } + } + } + break; + } + case EG_OP_COMPACT_MARK: break; /* boundary marker; no state change */ + default: break; + } + free(obj); +} + +/* ── Replay (§6) ───────────────────────────────────────────────────────────── + * Reads records in lsn order, applies each intact one, and stops at the first + * record that fails magic/length/crc validation (torn tail) — never crashes. + * Returns the number of records applied; sets *out_last_lsn to the highest + * good lsn seen (0 if none). */ +static int64_t eg_wal_replay_file(const char* path, uint64_t* out_last_lsn) { + if (out_last_lsn) *out_last_lsn = 0; + FILE* f = fopen(path, "rb"); + if (!f) return 0; + fseek(f, 0, SEEK_END); long fsz = ftell(f); rewind(f); + if (fsz <= 0) { fclose(f); return 0; } + uint8_t* buf = (uint8_t*)malloc((size_t)fsz); + if (!buf) { fclose(f); return 0; } + size_t got = fread(buf, 1, (size_t)fsz, f); + fclose(f); + int64_t applied = 0; + size_t off = 0; + while (off + EG_WAL_HDR_LEN <= got) { + uint32_t magic, len32, crc; uint64_t lsn; uint8_t op, flags; + memcpy(&magic, buf + off + 0, 4); + if (magic != EG_WAL_MAGIC) break; /* garbage / torn */ + memcpy(&len32, buf + off + 4, 4); + op = buf[off + 8]; flags = buf[off + 9]; + memcpy(&lsn, buf + off + 10, 8); + memcpy(&crc, buf + off + 18, 4); + size_t plen = (size_t)len32; + if (off + EG_WAL_HDR_LEN + plen > got) break; /* short final record */ + const char* payload = (const char*)(buf + off + EG_WAL_HDR_LEN); + if (eg_wal_record_crc(op, flags, lsn, payload, plen) != crc) break; /* torn */ + eg_wal_apply(op, payload, plen); + if (out_last_lsn) *out_last_lsn = lsn; + applied++; + off += EG_WAL_HDR_LEN + plen; + } + free(buf); + return applied; +} + +static void eg_wal_build_path(const char* dir, char* out, size_t cap) { + snprintf(out, cap, "%s/engram.wal", dir ? dir : "."); +} + +/* Open (create if absent) the WAL for appending. Idempotent for a given dir. */ +static int eg_wal_open(const char* dir) { + char path[1024]; + eg_wal_build_path(dir, path, sizeof(path)); + if (eg_wal.fp && strcmp(eg_wal.path, path) == 0) return 1; /* already open */ + if (eg_wal.fp) { fclose(eg_wal.fp); eg_wal.fp = NULL; } + FILE* f = fopen(path, "ab"); + if (!f) return 0; + eg_wal.fp = f; + snprintf(eg_wal.path, sizeof(eg_wal.path), "%s", path); + fseek(f, 0, SEEK_END); + eg_wal.bytes = ftell(f); + eg_wal.last_sync_ms = engram_now_ms(); + eg_wal.uncommitted = 0; + return 1; +} + +/* ── EL-facing builtins ──────────────────────────────────────────────────── */ + +/* Boot: replay /engram.wal over the already-loaded base snapshot, then + * open the WAL for appending, continuing the lsn sequence. Idempotent replay + * makes overlap with the base harmless (§6). Returns records replayed. */ +el_val_t engram_wal_boot(el_val_t dir) { + const char* d = EL_CSTR(dir); + char path[1024]; + eg_wal_build_path(d, path, sizeof(path)); + uint64_t last = 0; + int64_t applied = eg_wal_replay_file(path, &last); + eg_wal.lsn = last; /* continue monotonically */ + eg_wal_open(d); + return (el_val_t)applied; +} + +el_val_t engram_wal_open_dir(el_val_t dir) { + return (el_val_t)(int64_t)eg_wal_open(EL_CSTR(dir)); +} + +/* Append a NODE_PUT for node `id` (serialized via the shared emitter, incl. + * emb). Returns 1 on success. */ +el_val_t engram_wal_node_put(el_val_t dir, el_val_t id) { + if (!eg_wal_open(EL_CSTR(dir))) return (el_val_t)0; + EngramNode* n = engram_find_node(EL_CSTR(id)); + if (!n) return (el_val_t)0; + JsonBuf b; jb_init(&b); + engram_emit_node_json(&b, n, 1); + int ok = eg_wal_write(EG_OP_NODE_PUT, 0, b.buf, b.len); + free(b.buf); + return (el_val_t)(int64_t)ok; +} + +/* Append an EDGE_PUT for every edge at index >= start_count. Covers both the + * single-edge route and any append-only batch. Returns edges logged. */ +el_val_t engram_wal_edges_since(el_val_t dir, el_val_t start_count) { + if (!eg_wal_open(EL_CSTR(dir))) return (el_val_t)0; + EngramStore* g = engram_get(); + int64_t start = (int64_t)start_count; if (start < 0) start = 0; + int64_t logged = 0; + for (int64_t i = start; i < g->edge_count; i++) { + JsonBuf b; jb_init(&b); + engram_emit_edge_json(&b, &g->edges[i]); + if (eg_wal_write(EG_OP_EDGE_PUT, 0, b.buf, b.len)) logged++; + free(b.buf); + } + return (el_val_t)logged; +} + +/* Append ONE HEBB_BATCH record covering every edge at index >= start_count + * (single fsync for the whole consolidation batch — §5 tier B). */ +el_val_t engram_wal_hebb_batch(el_val_t dir, el_val_t start_count) { + if (!eg_wal_open(EL_CSTR(dir))) return (el_val_t)0; + EngramStore* g = engram_get(); + int64_t start = (int64_t)start_count; if (start < 0) start = 0; + if (start >= g->edge_count) return (el_val_t)0; + JsonBuf b; jb_init(&b); + jb_puts(&b, "{\"edges\":["); + int first = 1; + for (int64_t i = start; i < g->edge_count; i++) { + if (!first) jb_putc(&b, ','); + first = 0; + engram_emit_edge_json(&b, &g->edges[i]); + } + jb_puts(&b, "]}"); + int ok = eg_wal_write(EG_OP_HEBB_BATCH, 0, b.buf, b.len); + free(b.buf); + return (el_val_t)(int64_t)ok; +} + +/* Append a FORGET (hard remove). Internal-GC only — NOT wired to HTTP DELETE. */ +el_val_t engram_wal_forget(el_val_t dir, el_val_t id) { + if (!eg_wal_open(EL_CSTR(dir))) return (el_val_t)0; + const char* sid = EL_CSTR(id); + JsonBuf b; jb_init(&b); + jb_puts(&b, "{\"id\":"); jb_emit_escaped(&b, sid ? sid : ""); jb_putc(&b, '}'); + int ok = eg_wal_write(EG_OP_FORGET, 0, b.buf, b.len); + free(b.buf); + return (el_val_t)(int64_t)ok; +} + +/* Compaction (§7). Crash-safe ordering: fresh base snapshot renamed into place + * (engram_save is atomic temp+fsync+rename) BEFORE the WAL is truncated. A + * crash in the window replays the still-present WAL over the (old or new) + * base; idempotent apply converges. */ +static int eg_wal_compact(const char* dir) { + char snap[1024], waltmp[1024], walpath[1024]; + snprintf(snap, sizeof(snap), "%s/snapshot.json", dir); + eg_wal_build_path(dir, walpath, sizeof(walpath)); + snprintf(waltmp, sizeof(waltmp), "%s/engram.wal.tmp", dir); + /* 1. new base (atomic) */ + if (!engram_save((el_val_t)(uintptr_t)snap)) return 0; + /* fsync the directory so the rename is durable before we touch the WAL */ + { int dfd = open(dir, O_RDONLY); if (dfd >= 0) { fsync(dfd); close(dfd); } } + /* 2. fresh WAL containing only a COMPACT_MARK, atomically swapped in */ + uint64_t base_lsn = eg_wal.lsn; + FILE* tf = fopen(waltmp, "wb"); + if (!tf) return 0; + { + char pl[64]; int pn = snprintf(pl, sizeof(pl), "{\"base_lsn\":%llu}", (unsigned long long)base_lsn); + uint64_t lsn = ++eg_wal.lsn; + uint32_t magic = EG_WAL_MAGIC, len32 = (uint32_t)pn; + uint32_t crc = eg_wal_record_crc(EG_OP_COMPACT_MARK, 0, lsn, pl, pn); + uint8_t hdr[EG_WAL_HDR_LEN]; + memcpy(hdr, &magic, 4); memcpy(hdr + 4, &len32, 4); + hdr[8] = EG_OP_COMPACT_MARK; hdr[9] = 0; + memcpy(hdr + 10, &lsn, 8); memcpy(hdr + 18, &crc, 4); + fwrite(hdr, 1, EG_WAL_HDR_LEN, tf); fwrite(pl, 1, pn, tf); + fflush(tf); fsync(fileno(tf)); + } + fclose(tf); + if (eg_wal.fp) { fclose(eg_wal.fp); eg_wal.fp = NULL; } + if (rename(waltmp, walpath) != 0) { return 0; } + { int dfd = open(dir, O_RDONLY); if (dfd >= 0) { fsync(dfd); close(dfd); } } + /* 3. reopen the truncated WAL for appending */ + eg_wal_open(dir); + return 1; +} + +el_val_t engram_wal_compact(el_val_t dir) { + return (el_val_t)(int64_t)eg_wal_compact(EL_CSTR(dir)); +} + +/* Compact iff the WAL has crossed the size threshold. Returns 1 if compacted. */ +el_val_t engram_wal_maybe_compact(el_val_t dir) { + if (!eg_wal.fp) eg_wal_open(EL_CSTR(dir)); + if (eg_wal.bytes > eg_wal_compact_bytes()) + return (el_val_t)(int64_t)eg_wal_compact(EL_CSTR(dir)); + return (el_val_t)0; +} + +/* ── Integrity: safe data-dir resolution (§18.2) ───────────────────────────── + * Unset ENGRAM_DATA_DIR → $HOME/.neuron/engram (created if absent). If HOME is + * also unresolvable, FAIL LOUD (exit) rather than silently persisting to an + * ephemeral /tmp. Prod (ENGRAM_DATA_DIR=/data) is unaffected. */ +el_val_t engram_resolve_data_dir(void) { + const char* d = getenv("ENGRAM_DATA_DIR"); + if (d && *d) return el_wrap_str(el_strdup(d)); + const char* home = getenv("HOME"); + if (!home || !*home) { + fprintf(stderr, "[engram] FATAL: ENGRAM_DATA_DIR unset and HOME unresolved; " + "refusing to persist to an ephemeral dir. Set ENGRAM_DATA_DIR.\n"); + exit(1); + } + char neuron[1024], engramdir[1024]; + snprintf(neuron, sizeof(neuron), "%s/.neuron", home); + snprintf(engramdir, sizeof(engramdir), "%s/.neuron/engram", home); + mkdir(neuron, 0700); + mkdir(engramdir, 0700); + return el_wrap_str(el_strdup(engramdir)); +} + +/* ── Integrity: store-level write-protection (§18.1, §18.3) ────────────────── + * The protected set is DERIVED from the self-graph at call time, not hardcoded: + * the self root and the values hub, plus every node adjacent to either (in + * either direction). Adjacency of the values hub yields all value nodes; of + * the self root yields the identity children — so new values/identity stay + * protected automatically. */ +#define EG_SELF_ROOT "kn-efeb4a5b" +#define EG_VALUES_HUB "kn-5b606390" + +static int eg_is_neighbor_of(EngramStore* g, const char* hub, const char* id) { + for (int64_t i = 0; i < g->edge_count; i++) { + EngramEdge* e = &g->edges[i]; + if (e->from_id && e->to_id) { + if (strcmp(e->from_id, hub) == 0 && strcmp(e->to_id, id) == 0) return 1; + if (strcmp(e->to_id, hub) == 0 && strcmp(e->from_id, id) == 0) return 1; + } + } + return 0; +} +static int eg_is_protected(const char* id) { + if (!id || !*id) return 0; + if (strcmp(id, EG_SELF_ROOT) == 0) return 1; + if (strcmp(id, EG_VALUES_HUB) == 0) return 1; + EngramStore* g = engram_get(); + if (eg_is_neighbor_of(g, EG_VALUES_HUB, id)) return 1; + if (eg_is_neighbor_of(g, EG_SELF_ROOT, id)) return 1; + return 0; +} +el_val_t engram_is_protected(el_val_t id) { + return (el_val_t)(int64_t)eg_is_protected(EL_CSTR(id)); +} + +/* Derived protected set as a JSON array (self root + values hub + all adjacent + * ids). For diagnostics and the integrity tests (§18.5). */ +el_val_t engram_protected_json(void) { + EngramStore* g = engram_get(); + JsonBuf b; jb_init(&b); + jb_putc(&b, '['); + int first = 1; + const char* seeds[2] = { EG_SELF_ROOT, EG_VALUES_HUB }; + /* emit the two hubs themselves */ + for (int s = 0; s < 2; s++) { + if (!first) jb_putc(&b, ','); first = 0; + jb_emit_escaped(&b, seeds[s]); + } + for (int64_t i = 0; i < g->node_count; i++) { + const char* nid = g->nodes[i].id; + if (!nid || !*nid) continue; + if (strcmp(nid, EG_SELF_ROOT) == 0 || strcmp(nid, EG_VALUES_HUB) == 0) continue; + if (eg_is_neighbor_of(g, EG_VALUES_HUB, nid) || eg_is_neighbor_of(g, EG_SELF_ROOT, nid)) { + if (!first) jb_putc(&b, ','); first = 0; + jb_emit_escaped(&b, nid); + } + } + jb_putc(&b, ']'); + return el_wrap_str(b.buf); +} + /* ── Engram JSON-string accessors ───────────────────────────────────────── * These return pre-serialized JSON strings so callers (especially HTTP * handlers) don't have to round-trip ElList/ElMap through json_stringify diff --git a/lang/releases/v1.0.0-20260501/el_runtime.h b/lang/runtime/el_runtime.h similarity index 97% rename from lang/releases/v1.0.0-20260501/el_runtime.h rename to lang/runtime/el_runtime.h index 569ce0c..2c07b31 100644 --- a/lang/releases/v1.0.0-20260501/el_runtime.h +++ b/lang/runtime/el_runtime.h @@ -34,12 +34,12 @@ * pq_hybrid_* and HKDF-SHA256 derivation. * * Canonical compile command: - * cc -std=c11 -I el-compiler/runtime -lcurl -lpthread \ - * -o .c el-compiler/runtime/el_runtime.c + * cc -std=c11 -I runtime -lcurl -lpthread \ + * -o .c runtime/el_runtime.c * * With liboqs (post-quantum stack): - * cc -std=c11 -I el-compiler/runtime -lcurl -lpthread -loqs -lcrypto \ - * -o .c el-compiler/runtime/el_runtime.c + * cc -std=c11 -I runtime -lcurl -lpthread -loqs -lcrypto \ + * -o .c runtime/el_runtime.c */ #pragma once @@ -631,12 +631,27 @@ el_val_t engram_label_df(el_val_t term); el_val_t engram_embed_backfill(el_val_t count); el_val_t engram_list_layers_json(void); /* Working memory introspection — count, mean weight, and top-N snapshot. - * Ported from el-compiler/runtime on 2026-06-30 self-review. */ + * Ported from runtime on 2026-06-30 self-review. */ el_val_t engram_wm_count(void); el_val_t engram_wm_avg_weight(void); el_val_t engram_wm_top_json(el_val_t n); /* Merge-load: add nodes/edges from a snapshot without resetting the store. */ el_val_t engram_load_merge(el_val_t path); + +/* ── WAL + compaction + integrity (ENGRAM_WAL=on; design doc §§3-14,§18) ──── */ +int engram_wal_enabled(void); +el_val_t engram_crc32(el_val_t s); +el_val_t engram_wal_boot(el_val_t dir); /* replay + open; returns records */ +el_val_t engram_wal_open_dir(el_val_t dir); +el_val_t engram_wal_node_put(el_val_t dir, el_val_t id); +el_val_t engram_wal_edges_since(el_val_t dir, el_val_t start_count); +el_val_t engram_wal_hebb_batch(el_val_t dir, el_val_t start_count); +el_val_t engram_wal_forget(el_val_t dir, el_val_t id); +el_val_t engram_wal_compact(el_val_t dir); +el_val_t engram_wal_maybe_compact(el_val_t dir); +el_val_t engram_resolve_data_dir(void); /* §18.2 fail-loud default */ +el_val_t engram_is_protected(el_val_t id); /* §18.1/18.3 derived set */ +el_val_t engram_protected_json(void); /* engram_compile_layered_json — produce a prompt-ready text block split * into "[LAYER 0 — STRUCTURAL]" (non-suppressible layers, sacred fire) * and "[ENGRAM CONTEXT]" (standard suppressible layers). Returns "" if diff --git a/lang/el-compiler/runtime/el_runtime.js b/lang/runtime/el_runtime.js similarity index 100% rename from lang/el-compiler/runtime/el_runtime.js rename to lang/runtime/el_runtime.js diff --git a/lang/el-compiler/runtime/el_runtime_win32.c b/lang/runtime/el_runtime_win32.c similarity index 100% rename from lang/el-compiler/runtime/el_runtime_win32.c rename to lang/runtime/el_runtime_win32.c diff --git a/lang/el-compiler/runtime/el_sdl2.c b/lang/runtime/el_sdl2.c similarity index 100% rename from lang/el-compiler/runtime/el_sdl2.c rename to lang/runtime/el_sdl2.c diff --git a/lang/el-compiler/runtime/el_seed.c b/lang/runtime/el_seed.c similarity index 99% rename from lang/el-compiler/runtime/el_seed.c rename to lang/runtime/el_seed.c index b509e48..d25f93a 100644 --- a/lang/el-compiler/runtime/el_seed.c +++ b/lang/runtime/el_seed.c @@ -8,7 +8,7 @@ * Threading: __thread_create / __thread_join use dlsym(RTLD_DEFAULT) to look * up El function symbols at runtime. This is the foundation of El's parallelism. * - * Link: cc -std=c11 -I el-compiler/runtime -lcurl -lpthread \ + * Link: cc -std=c11 -I runtime -lcurl -lpthread \ * -o .c el_seed.c */ diff --git a/lang/el-compiler/runtime/el_seed.h b/lang/runtime/el_seed.h similarity index 100% rename from lang/el-compiler/runtime/el_seed.h rename to lang/runtime/el_seed.h diff --git a/lang/el-compiler/runtime/el_uikit.m b/lang/runtime/el_uikit.m similarity index 100% rename from lang/el-compiler/runtime/el_uikit.m rename to lang/runtime/el_uikit.m diff --git a/lang/el-compiler/runtime/el_win32.c b/lang/runtime/el_win32.c similarity index 100% rename from lang/el-compiler/runtime/el_win32.c rename to lang/runtime/el_win32.c diff --git a/lang/runtime/json.el b/lang/runtime/json.el index c1b7ba7..005add9 100644 --- a/lang/runtime/json.el +++ b/lang/runtime/json.el @@ -2,7 +2,7 @@ // // Thin El wrappers over seed JSON primitives, plus pure-El builders and // helpers. Each function here corresponds to (and replaces) a C function -// from el-compiler/runtime/legacy/el_runtime.c (lines 2692–3333). +// from runtime/el_runtime.c (lines 2692–3333). // // Seed primitives consumed by this module: // __json_get(json, key) -> String (value as string) diff --git a/lang/runtime/manifest.el b/lang/runtime/manifest.el index 7b6a45a..ce8c204 100644 --- a/lang/runtime/manifest.el +++ b/lang/runtime/manifest.el @@ -25,8 +25,8 @@ // runtime/collections.el \ // > combined.el // ./dist/platform/elc combined.el > output.c -// cc -std=c11 -I el-compiler/runtime -lcurl -lpthread \ -// -o output output.c el-compiler/runtime/el_seed.c +// cc -std=c11 -I runtime -lcurl -lpthread \ +// -o output output.c runtime/el_seed.c // This file itself is not compiled — it is documentation only. fn runtime_version() -> String { diff --git a/lang/runtime/math.el b/lang/runtime/math.el index 0df3493..bca8ba1 100644 --- a/lang/runtime/math.el +++ b/lang/runtime/math.el @@ -1,6 +1,6 @@ // runtime/math.el — Float math, integer utilities, and numeric conversions. // -// Implements the math/float surface from el-compiler/runtime/legacy/el_runtime.c +// Implements the math/float surface from runtime/el_runtime.c // (lines 303–305 for el_abs/max/min, lines 4725–4771 for float/format ops) // in pure El, using seed primitives. // diff --git a/lang/el-compiler/runtime/new-platform b/lang/runtime/new-platform similarity index 100% rename from lang/el-compiler/runtime/new-platform rename to lang/runtime/new-platform diff --git a/lang/runtime/time.el b/lang/runtime/time.el index 5ceb6ef..8b67ae3 100644 --- a/lang/runtime/time.el +++ b/lang/runtime/time.el @@ -1,6 +1,6 @@ // runtime/time.el — Time operations, sleep, and formatting. // -// Implements the time surface from el-compiler/runtime/legacy/el_runtime.c +// Implements the time surface from runtime/el_runtime.c // (lines 3334–3440, 3471–3656) in pure El, using seed primitives. // // Seed primitives consumed: diff --git a/lang/tests/calendar/run.sh b/lang/tests/calendar/run.sh index f3e8869..d9de0dc 100755 --- a/lang/tests/calendar/run.sh +++ b/lang/tests/calendar/run.sh @@ -11,7 +11,7 @@ cd "$(dirname "$0")" EL_HOME="${EL_HOME:-$(cd ../.. && pwd)}" ELC="${EL_HOME}/dist/platform/elc" -RUNTIME_DIR="${EL_HOME}/el-compiler/runtime" +RUNTIME_DIR="${EL_HOME}/runtime" if [ ! -x "${ELC}" ]; then echo "elc not found at ${ELC}" >&2 diff --git a/lang/tests/html_sanitizer/run.sh b/lang/tests/html_sanitizer/run.sh index c22db92..cbe98c0 100755 --- a/lang/tests/html_sanitizer/run.sh +++ b/lang/tests/html_sanitizer/run.sh @@ -10,7 +10,7 @@ cd "$(dirname "$0")" EL_HOME="${EL_HOME:-$(cd ../.. && pwd)}" ELC="${EL_HOME}/dist/platform/elc" -RUNTIME_DIR="${EL_HOME}/el-compiler/runtime" +RUNTIME_DIR="${EL_HOME}/runtime" if [ ! -x "${ELC}" ]; then echo "elc not found at ${ELC}" >&2 diff --git a/lang/tests/runtime/string_test.el b/lang/tests/runtime/string_test.el index 9578e10..322cb39 100644 --- a/lang/tests/runtime/string_test.el +++ b/lang/tests/runtime/string_test.el @@ -14,8 +14,8 @@ // tests/runtime/string_test.el > /tmp/string_test_combined.el // // ./dist/platform/elc /tmp/string_test_combined.el > /tmp/string_test.c -// cc -std=c11 -I el-compiler/runtime -lcurl -lpthread \ -// -o /tmp/string_test /tmp/string_test.c el-compiler/runtime/el_seed.c +// cc -std=c11 -I runtime -lcurl -lpthread \ +// -o /tmp/string_test /tmp/string_test.c runtime/el_seed.c // /tmp/string_test; echo "exit: $?" // // Exit code equals the number of failing assertions (0 = all pass). diff --git a/lang/tests/text/run.sh b/lang/tests/text/run.sh index 488cc50..4234b24 100755 --- a/lang/tests/text/run.sh +++ b/lang/tests/text/run.sh @@ -11,7 +11,7 @@ cd "$(dirname "$0")" EL_HOME="${EL_HOME:-$(cd ../.. && pwd)}" ELC="${ELC:-${EL_HOME}/dist/platform/elc}" -RUNTIME_DIR="${EL_HOME}/el-compiler/runtime" +RUNTIME_DIR="${EL_HOME}/runtime" if [ ! -x "${ELC}" ]; then echo "elc not found at ${ELC}" >&2 diff --git a/lang/tests/time/run.sh b/lang/tests/time/run.sh index 1d445e7..257b82e 100755 --- a/lang/tests/time/run.sh +++ b/lang/tests/time/run.sh @@ -16,7 +16,7 @@ cd "$(dirname "$0")" EL_HOME="${EL_HOME:-$(cd ../.. && pwd)}" ELC="${EL_HOME}/dist/platform/elc" -RUNTIME_DIR="${EL_HOME}/el-compiler/runtime" +RUNTIME_DIR="${EL_HOME}/runtime" if [ ! -x "${ELC}" ]; then echo "elc not found at ${ELC}" >&2 diff --git a/lang/tools/install.sh b/lang/tools/install.sh index 5beea20..92874b6 100755 --- a/lang/tools/install.sh +++ b/lang/tools/install.sh @@ -44,7 +44,7 @@ INCLUDE_DIR="${PREFIX}/include" LIB_DIR="${PREFIX}/lib" ELC_SRC="${EL_ROOT}/dist/platform/elc" -RUNTIME_SRC="${EL_ROOT}/el-compiler/runtime" +RUNTIME_SRC="${EL_ROOT}/runtime" STDLIB_SRC="${EL_ROOT}/runtime" echo "==> Installing El framework to ${PREFIX}" diff --git a/lang/tools/new-project.sh b/lang/tools/new-project.sh index 8f3f8d1..3622807 100755 --- a/lang/tools/new-project.sh +++ b/lang/tools/new-project.sh @@ -42,7 +42,7 @@ fi # Discover el_runtime.c EL_RUNTIME="" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -LOCAL_RUNTIME="${SCRIPT_DIR}/../el-compiler/runtime/el_runtime.c" +LOCAL_RUNTIME="${SCRIPT_DIR}/../runtime/el_runtime.c" if [[ -f "${LOCAL_RUNTIME}" ]]; then EL_RUNTIME="$(cd "$(dirname "${LOCAL_RUNTIME}")" && pwd)/$(basename "${LOCAL_RUNTIME}")" EL_INCLUDE="$(dirname "${EL_RUNTIME}")" diff --git a/scripts/check-single-runtime.sh b/scripts/check-single-runtime.sh new file mode 100755 index 0000000..6330ece --- /dev/null +++ b/scripts/check-single-runtime.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +# check-single-runtime.sh — CODE-VS-ARTIFACT drift guard for the el runtime. +# +# Enforces org policy docs/CODE-VS-ARTIFACT.md rule #1 (single source of truth): +# there is exactly ONE authored el_runtime.c, and it lives at lang/runtime/. +# Any other el_runtime.c in the tree is a fork (a hand-synced copy). A lagging +# fork is exactly what shipped to prod and dropped learned `hebb` edges on +# restart — this guard exists to make that class of bug impossible to reintroduce. +# +# Exemptions: +# * Build output — generated amalgamations under any dist/ or build/ dir are +# artifacts, not sources. +# * A small, explicit ALLOWLIST of pre-existing example-app vendored/staging +# copies (see below). These are KNOWN DEFERRED DEBT, tracked separately from +# the SDK/CI-published runtime. They do NOT ship to prod. The guard warns on +# them (visible, greppable) but does not fail — while HARD-FAILING on any new +# or non-allowlisted fork, including any return of lang/el-compiler/runtime/ +# or a lang/releases/ vendored copy. +# +# Wire-in: run from the repo root in CI (see note at bottom). Exits non-zero on drift. +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$ROOT" + +CANONICAL="lang/runtime/el_runtime.c" + +# KNOWN DEFERRED example-app forks — remove these as a follow-up, then delete +# this allowlist. iOS + Docker copies are regenerated by their build scripts +# (cp from lang/runtime) and can be git-rm'd now; the Android jni/ copy is a +# committed source its CMake build depends on and needs a build-script change +# (cp from lang/runtime) before removal. Tracked in docs/CODE-VS-ARTIFACT.md. +ALLOWLIST=( + "ui/examples/native-hello-android/app/src/main/jni/el_runtime.c" + "ui/examples/native-hello-ios/NativeHello/el_runtime.c" + "ui/examples/native-hello/build-docker/runtime/el_runtime.c" +) + +is_allowlisted() { + local p="$1" + for a in "${ALLOWLIST[@]}"; do [ "$p" = "$a" ] && return 0; done + return 1 +} + +if [ ! -f "$CANONICAL" ]; then + echo "FATAL: canonical runtime source missing: $CANONICAL" >&2 + exit 1 +fi + +# All el_runtime.c files tracked by git, excluding build output (dist/ , build/) +# and the canonical source itself. +mapfile -t CANDIDATES < <( + git ls-files '*el_runtime.c' \ + | grep -Ev '(^|/)(dist|build)/' \ + | grep -vx "$CANONICAL" || true +) + +FORKS=() +DEFERRED=() +for f in "${CANDIDATES[@]}"; do + if is_allowlisted "$f"; then DEFERRED+=("$f"); else FORKS+=("$f"); fi +done + +if [ "${#DEFERRED[@]}" -gt 0 ]; then + echo "WARN: allowlisted (deferred) el_runtime.c forks still present — clean these up:" >&2 + for f in "${DEFERRED[@]}"; do echo " - $f" >&2; done +fi + +if [ "${#FORKS[@]}" -gt 0 ]; then + echo "FATAL: el_runtime.c fork(s) detected outside the canonical location." >&2 + echo " Canonical (the ONLY allowed source): $CANONICAL" >&2 + echo " Offending copies:" >&2 + for f in "${FORKS[@]}"; do echo " - $f" >&2; done + echo "" >&2 + echo "Consumers must build against $CANONICAL (pin by git ref where" >&2 + echo "reproducibility matters) — never a hand-maintained copy." >&2 + echo "See docs/CODE-VS-ARTIFACT.md." >&2 + exit 1 +fi + +echo "OK: single canonical runtime source — $CANONICAL (no un-allowlisted forks)." + +# --------------------------------------------------------------------------- +# CI wire-in: +# foundation/el .gitea/workflows/ci-dev.yaml, ci-stage.yaml, sdk-release.yaml +# Add an early step (before the build/publish steps). It must run from the +# REPO ROOT, so override the job's `defaults.run.working-directory: lang`: +# +# - name: Guard - single canonical runtime source +# working-directory: ${{ github.workspace }} +# run: bash scripts/check-single-runtime.sh +# +# Also add to .githooks/pre-commit so drift is caught before it is committed. +# --------------------------------------------------------------------------- diff --git a/ui/examples/native-hello-android/build.sh b/ui/examples/native-hello-android/build.sh index 4428bbd..874e35d 100755 --- a/ui/examples/native-hello-android/build.sh +++ b/ui/examples/native-hello-android/build.sh @@ -18,7 +18,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang" EL_UI_ROOT="${SCRIPT_DIR}/../.." -EL_RUNTIME="${EL_LANG_ROOT}/el-compiler/runtime" +EL_RUNTIME="${EL_LANG_ROOT}/runtime" EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el" EL_APP_ENTRY="${EL_UI_ROOT}/examples/native-hello/src/main.el" EL_MANIFEST="${EL_UI_ROOT}/examples/native-hello/manifest.el" diff --git a/ui/examples/native-hello-ios/build.sh b/ui/examples/native-hello-ios/build.sh index 3c1d92d..48ad8f4 100755 --- a/ui/examples/native-hello-ios/build.sh +++ b/ui/examples/native-hello-ios/build.sh @@ -17,7 +17,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang" EL_UI_ROOT="${SCRIPT_DIR}/../.." -EL_RUNTIME="${EL_LANG_ROOT}/el-compiler/runtime" +EL_RUNTIME="${EL_LANG_ROOT}/runtime" EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el" EL_APP_ENTRY="${EL_UI_ROOT}/examples/native-hello/src/main.el" EL_MANIFEST="${EL_UI_ROOT}/examples/native-hello/manifest.el" diff --git a/ui/examples/native-hello/build-gtk4.sh b/ui/examples/native-hello/build-gtk4.sh index 0cb2ad9..afbd436 100755 --- a/ui/examples/native-hello/build-gtk4.sh +++ b/ui/examples/native-hello/build-gtk4.sh @@ -24,7 +24,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang" EL_UI_ROOT="${SCRIPT_DIR}/../.." -EL_RUNTIME="${EL_LANG_ROOT}/el-compiler/runtime" +EL_RUNTIME="${EL_LANG_ROOT}/runtime" EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el" BUILD_DIR="${SCRIPT_DIR}/build-gtk4" diff --git a/ui/examples/native-hello/build-sdl2.sh b/ui/examples/native-hello/build-sdl2.sh index 99cdc3a..b06242a 100755 --- a/ui/examples/native-hello/build-sdl2.sh +++ b/ui/examples/native-hello/build-sdl2.sh @@ -23,7 +23,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang" EL_UI_ROOT="${SCRIPT_DIR}/../.." -EL_RUNTIME="${EL_LANG_ROOT}/el-compiler/runtime" +EL_RUNTIME="${EL_LANG_ROOT}/runtime" EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el" BUILD_DIR="${SCRIPT_DIR}/build" diff --git a/ui/examples/native-hello/build-win32.sh b/ui/examples/native-hello/build-win32.sh index 62582c8..723c97d 100755 --- a/ui/examples/native-hello/build-win32.sh +++ b/ui/examples/native-hello/build-win32.sh @@ -18,7 +18,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang" EL_UI_ROOT="${SCRIPT_DIR}/../.." -EL_RUNTIME="${EL_LANG_ROOT}/el-compiler/runtime" +EL_RUNTIME="${EL_LANG_ROOT}/runtime" EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el" BUILD_DIR="${SCRIPT_DIR}/build-win32" diff --git a/ui/examples/native-hello/build.sh b/ui/examples/native-hello/build.sh index f53a78a..aab4c71 100755 --- a/ui/examples/native-hello/build.sh +++ b/ui/examples/native-hello/build.sh @@ -40,7 +40,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang" EL_UI_ROOT="${SCRIPT_DIR}/../.." -EL_RUNTIME="${EL_LANG_ROOT}/el-compiler/runtime" +EL_RUNTIME="${EL_LANG_ROOT}/runtime" EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el" BUILD_DIR="${SCRIPT_DIR}/build" @@ -193,6 +193,6 @@ run() { case "${1:-run}" in clean) clean ;; compile) compile ;; - platforms) "${EL_LANG_ROOT}/el-compiler/runtime/detect-platforms" ;; + platforms) "${EL_LANG_ROOT}/runtime/detect-platforms" ;; run|*) run ;; esac diff --git a/ui/examples/native-hello/docker-build-linux.sh b/ui/examples/native-hello/docker-build-linux.sh index 46f2214..541490f 100755 --- a/ui/examples/native-hello/docker-build-linux.sh +++ b/ui/examples/native-hello/docker-build-linux.sh @@ -32,7 +32,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang" EL_UI_ROOT="${SCRIPT_DIR}/../.." -EL_RUNTIME="${EL_LANG_ROOT}/el-compiler/runtime" +EL_RUNTIME="${EL_LANG_ROOT}/runtime" EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el" BUILD_DIR="${SCRIPT_DIR}/build" DOCKER_CTX="${SCRIPT_DIR}/build-docker" From fa47b98d18a67acf7346bc774c13fb5ddda48290 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Tue, 11 Aug 2026 22:26:05 -0500 Subject: [PATCH 21/26] engram tiered storage M1: on-disk paged store format + round-trip tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-contained paged store (lang/runtime/engram_store.{c,h}): 16KiB slotted pages, u32 TLV self-describing records (forward-compatible), overflow chains, B+-tree id-index + from/to adjacency, page free-list, tombstones, double superblock + crc recovery. Not yet wired to activation (M3). 33/33 tests pass (ASan/UBSan clean); 5k nodes/20k edges round-trip bit-exact incl 768xf32 emb + hebb; store 25MB vs 64MB JSON. Format is final — see design §2.4. --- engram/test/run_store_tests.sh | 13 + engram/test/test_store.c | 439 +++++++++++++ lang/runtime/engram_store.c | 1084 ++++++++++++++++++++++++++++++++ lang/runtime/engram_store.h | 135 ++++ 4 files changed, 1671 insertions(+) create mode 100755 engram/test/run_store_tests.sh create mode 100644 engram/test/test_store.c create mode 100644 lang/runtime/engram_store.c create mode 100644 lang/runtime/engram_store.h diff --git a/engram/test/run_store_tests.sh b/engram/test/run_store_tests.sh new file mode 100755 index 0000000..52af9bd --- /dev/null +++ b/engram/test/run_store_tests.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# M1 paged-store gate. Pure C (NOT elb/elc). Writes only under /tmp. +set -e +HERE="$(cd "$(dirname "$0")" && pwd)" +SRC="$HERE/../../lang/runtime/engram_store.c" +BIN="/tmp/test_store.$$" +echo "compiling: gcc test_store.c engram_store.c" +gcc -O2 -Wall -Wextra -std=c11 "$HERE/test_store.c" "$SRC" -o "$BIN" +"$BIN" +rc=$? +rm -f "$BIN" +rm -rf /tmp/engram-store-test-* +exit $rc diff --git a/engram/test/test_store.c b/engram/test/test_store.c new file mode 100644 index 0000000..0aab6c2 --- /dev/null +++ b/engram/test/test_store.c @@ -0,0 +1,439 @@ +/* test_store.c — M1 gate for the engram paged store (engram_store.{c,h}). + * + * Pure C. Build: gcc -O2 test_store.c ../../lang/runtime/engram_store.c -o test_store + * Writes ONLY under a throwaway /tmp dir. Never touches ~/.neuron or live ports. + * + * Covers §7 M1 gates: round-trip (5k nodes / 20k edges, all fields, emb bit-exact, + * hebb, >page content), TLV forward-compat, overflow chains, B+-tree indexes + * across splits, free-list reuse, and corruption/superblock recovery. + */ +#include "../../lang/runtime/engram_store.h" + +#include +#include +#include +#include +#include +#include +#include + +static int g_pass = 0, g_fail = 0; +static void ok(const char* name, int cond){ + printf(" [%s] %s\n", cond ? "PASS" : "FAIL", name); + if (cond) g_pass++; else g_fail++; +} + +static char g_dir[512]; +static void mk_dir(void){ + snprintf(g_dir, sizeof g_dir, "/tmp/engram-store-test-%d", (int)getpid()); + mkdir(g_dir, 0700); +} +static void path_in(char* out, size_t cap, const char* name){ + snprintf(out, cap, "%s/%s", g_dir, name); +} +static long file_size(const char* p){ struct stat st; return stat(p,&st)==0 ? (long)st.st_size : -1; } + +/* ── deterministic RNG so oracle nodes/edges regenerate bit-exact ─────────── */ +static uint64_t xs(uint64_t* s){ uint64_t x=*s; x^=x<<13; x^=x>>7; x^=x<<17; *s=x; return x; } +static uint64_t node_seed(int i){ return 0x9E3779B97F4A7C15ULL ^ ((uint64_t)(i+1)*0xD1B54A32D192ED03ULL); } +static uint64_t edge_seed(int i){ return 0xC2B2AE3D27D4EB4FULL ^ ((uint64_t)(i+1)*0x165667B19E3779F9ULL); } + +static char* rnd_str(uint64_t* st, size_t len){ + char* s = (char*)malloc(len + 1); + for (size_t i=0;ipage content to force overflow chains. */ +#define NODE_COUNT 5000 +#define EDGE_COUNT 20000 +#define EMB_DIM 768 + +static void gen_node(int i, StoreNode* n){ + memset(n, 0, sizeof *n); + uint64_t st = node_seed(i); + char id[32]; snprintf(id, sizeof id, "node-%d", i); + n->id = strdup(id); + size_t clen = (i % 500 == 0) ? (size_t)(17000 + (xs(&st) % 6000)) : (size_t)(xs(&st) % 300); + n->content = rnd_str(&st, clen); + n->node_type = rnd_str(&st, 4 + (xs(&st) % 8)); + n->label = (i % 2) ? rnd_str(&st, 3 + (xs(&st) % 10)) : NULL; + n->tier = rnd_str(&st, 4 + (xs(&st) % 6)); + n->tags = rnd_str(&st, xs(&st) % 40); + n->metadata = (i % 3) ? rnd_str(&st, xs(&st) % 60) : NULL; + n->salience = (double)(xs(&st) % 1000000) / 997.0; + n->importance = (double)(xs(&st) % 1000000) / 131.0; + n->confidence = (double)(xs(&st) % 1000000) / 733.0; + n->temporal_decay_rate = (double)(xs(&st) % 1000000) / 101.0; + n->activation_count = (int64_t)(xs(&st) % 100000); + n->last_activated = (int64_t)xs(&st); + n->created_at = (int64_t)(1600000000000LL + i); + n->updated_at = (int64_t)xs(&st); + n->background_activation = (double)(xs(&st) % 1000000) / 17.0; + n->working_memory_weight = (double)(xs(&st) % 1000000) / 29.0; + n->suppression_count = (int32_t)(xs(&st) % 50); + n->layer_id = (uint32_t)(xs(&st) % 5); + for (int k=0;kaccess_ts[k] = (int64_t)xs(&st); + n->access_head = (int32_t)(xs(&st) % STORE_BLL_K); + n->access_filled = (int32_t)(xs(&st) % (STORE_BLL_K + 1)); + n->wm_anchor = (double)(xs(&st) % 1000000) / 3.0; + n->emb = (float*)malloc(EMB_DIM * sizeof(float)); + for (int k=0;kemb[k], &u, 4); } + n->emb_dim = EMB_DIM; +} + +static void gen_edge(int i, StoreEdge* e){ + memset(e, 0, sizeof *e); + uint64_t st = edge_seed(i); + char id[32], from[32], to[32]; + snprintf(id, sizeof id, "edge-%d", i); + snprintf(from, sizeof from, "node-%d", (int)(xs(&st) % NODE_COUNT)); + snprintf(to, sizeof to, "node-%d", (int)(xs(&st) % NODE_COUNT)); + e->id = strdup(id); e->from_id = strdup(from); e->to_id = strdup(to); + e->relation = rnd_str(&st, 3 + (xs(&st) % 12)); + e->metadata = (i % 4) ? rnd_str(&st, xs(&st) % 40) : NULL; + e->weight = (double)(xs(&st) % 1000000) / 111.0; + e->hebb = (double)(xs(&st) % 1000000) / 1000000.0; /* the learned field */ + e->confidence = (double)(xs(&st) % 1000000) / 777.0; + e->created_at = (int64_t)(1600000000000LL + i); + e->updated_at = (int64_t)xs(&st); + e->last_fired = (int64_t)xs(&st); + e->inhibitory = (int32_t)(xs(&st) % 2); + e->layer_id = (uint32_t)(xs(&st) % 5); +} + +static int streq(const char* a, const char* b){ + if (!a && !b) return 1; + if (!a || !b) return 0; + return strcmp(a,b)==0; +} +static int cmp_node(const StoreNode* a, const StoreNode* b){ + if (!streq(a->id,b->id) || !streq(a->content,b->content) || + !streq(a->node_type,b->node_type) || !streq(a->label,b->label) || + !streq(a->tier,b->tier) || !streq(a->tags,b->tags) || + !streq(a->metadata,b->metadata)) return 0; + if (a->salience!=b->salience || a->importance!=b->importance || + a->confidence!=b->confidence || a->temporal_decay_rate!=b->temporal_decay_rate || + a->activation_count!=b->activation_count || a->last_activated!=b->last_activated || + a->created_at!=b->created_at || a->updated_at!=b->updated_at || + a->background_activation!=b->background_activation || + a->working_memory_weight!=b->working_memory_weight || + a->suppression_count!=b->suppression_count || a->layer_id!=b->layer_id || + a->access_head!=b->access_head || a->access_filled!=b->access_filled || + a->wm_anchor!=b->wm_anchor || a->emb_dim!=b->emb_dim) return 0; + for (int k=0;kaccess_ts[k]!=b->access_ts[k]) return 0; + if ((a->emb==NULL) != (b->emb==NULL)) return 0; + if (a->emb && memcmp(a->emb, b->emb, (size_t)a->emb_dim*4)!=0) return 0; + return 1; +} +static int cmp_edge(const StoreEdge* a, const StoreEdge* b){ + if (!streq(a->id,b->id) || !streq(a->from_id,b->from_id) || !streq(a->to_id,b->to_id) || + !streq(a->relation,b->relation) || !streq(a->metadata,b->metadata)) return 0; + if (a->weight!=b->weight || a->hebb!=b->hebb || a->confidence!=b->confidence || + a->created_at!=b->created_at || a->updated_at!=b->updated_at || + a->last_fired!=b->last_fired || a->inhibitory!=b->inhibitory || + a->layer_id!=b->layer_id) return 0; + return 1; +} +static void free_node_fields(StoreNode* n){ + free(n->id); free(n->content); free(n->node_type); free(n->label); + free(n->tier); free(n->tags); free(n->metadata); free(n->emb); free(n->unknown); +} +static void free_edge_fields(StoreEdge* e){ + free(e->id); free(e->from_id); free(e->to_id); free(e->relation); free(e->metadata); free(e->unknown); +} + +/* Flip one byte in the store file at (page*PAGE_SIZE + off). */ +static void flip_byte(const char* path, uint64_t page, size_t off){ + int fd = open(path, O_RDWR); + uint8_t b; off_t at = (off_t)page*STORE_PAGE_SIZE + off; + pread(fd, &b, 1, at); b ^= 0xFF; pwrite(fd, &b, 1, at); close(fd); +} + +/* ════════════════════════════════════════════════════════════════════════ */ + +static void test_roundtrip(void){ + printf("\n== round-trip: %d nodes + %d edges, all fields, emb bit-exact ==\n", NODE_COUNT, EDGE_COUNT); + char path[600]; path_in(path, sizeof path, "roundtrip.store"); + unlink(path); + EngramPagedStore* s = store_create(path); + ok("store_create", s != NULL); + if (!s) return; + + for (int i=0;i 0); + + for (int i=0;i= 1); + printf(" store_check reported %d corrupt page(s)\n", bad); + store_close(s); + + /* fresh store, corrupt superblock 0, must recover via mirror superblock 1 */ + char p2[600]; path_in(p2, sizeof p2, "sbrec.store"); + unlink(p2); + s = store_create(p2); + StoreNode n; gen_node(42,&n); store_put_node(s,&n); + store_close(s); + /* trash magic + crc region of page 0 */ + flip_byte(p2, 0, 0); flip_byte(p2, 0, 1); flip_byte(p2, 0, 90); + s = store_open(p2); + ok("open recovers via mirror superblock (page 1)", s != NULL); + if (s){ + StoreNode g; int r = store_get_node(s, "node-42", &g); + ok("data intact after superblock recovery", r==1 && cmp_node(&n,&g)); + if (r==1) store_node_free(&g); + store_close(s); + } + free_node_fields(&n); +} + +int main(void){ + mk_dir(); + printf("engram_store M1 test harness — dir=%s\n", g_dir); + test_roundtrip(); + test_forward_compat(); + test_overflow(); + test_index_splits(); + test_freelist(); + test_corruption(); + printf("\n================ %d passed, %d failed ================\n", g_pass, g_fail); + return g_fail ? 1 : 0; +} diff --git a/lang/runtime/engram_store.c b/lang/runtime/engram_store.c new file mode 100644 index 0000000..8ee843a --- /dev/null +++ b/lang/runtime/engram_store.c @@ -0,0 +1,1084 @@ +/* engram_store.c — M1 paged store: writer/reader for the FINAL on-disk format. + * + * Self-contained. Standard libs only. See engram_store.h and the design doc + * (engram-tiered-storage-engine.md §2/§4/§7). Write-through page I/O via + * pread/pwrite (no buffer pool yet — that is M4). Every mutation immediately + * lands on disk; store_sync/close rewrite both superblocks and fsync. + * + * On-disk layout (all integers little-endian): + * page 0,1 : superblock + mirror (recovery picks higher valid sb_seq) + * page N : generic 32-byte page header, then type-specific body + * + * Generic page header (32 bytes): + * +0 u64 page_id + * +8 u8 page_type (NODE|EDGE|INDEX|OVERFLOW|FREE) + * +9 u8 reserved + * +10 u16 slot_count (slotted pages) / nkeys (index pages) + * +12 u16 free_bytes (slotted pages: contiguous heap gap) + * +14 u16 reserved + * +16 u64 lsn (LSN of last write — ARIES redo idempotency, M2) + * +24 u32 crc32 (over the whole page with these 4 bytes zeroed) + * +28 u32 reserved + * + * Slotted page (NODE/EDGE): slot directory grows from +32 (6 bytes each: + * [u16 off][u16 len][u16 flags]); records grow down from PAGE_SIZE. + * + * On-page record: [u16 rec_len][u8 rec_ver][u8 rec_flags] then either the TLV + * field body (inline) or, if REC_OVERFLOW, a stub [u64 head_page][u64 total]. + * + * TLV field: [u8 tag][u32 len][bytes]. NOTE: the design §2 sketch says u16 len; + * node content can exceed 64 KiB (tests use 100 KiB), so the field length MUST + * be u32. This is the one format decision beyond §2 — flagged in the report. + * + * Overflow page: header, then +32 [u64 next_page][u32 chunk_len][payload...]. + * + * Index page (B+-tree, u64 keys, duplicates allowed, fixed payload per tree): + * +32 u8 is_leaf; +36 u64 next_leaf; +44 entries. + * leaf entry = [u64 key][payload]; payload = primary(10) or adjacency(11). + * internal = nkeys u64 keys, then (nkeys+1) u64 child page ids. + */ +#include "engram_store.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* STORE_BLL_K must track ENGRAM_BLL_K in el_runtime.c. */ +typedef char store__bll_k_check[(STORE_BLL_K == 10) ? 1 : -1]; + +#define STORE_HDR 32u /* generic page header size */ +#define SLOT_SIZE 6u /* [u16 off][u16 len][u16 flags] */ +#define SLOT_LIVE 1u +#define SLOT_DEAD 2u + +#define REC_HDR 4u /* [u16 rec_len][u8 ver][u8 flags] */ +#define REC_VER 1u +#define REC_OVERFLOW 1u /* rec_flags bit0: body is in an overflow chain */ + +#define MAX_INLINE_BODY (STORE_PAGE_SIZE - STORE_HDR - SLOT_SIZE - REC_HDR) + +/* Index page geometry. */ +#define IDX_LEAF_OFF 32u +#define IDX_NEXT_OFF 36u +#define IDX_ENT_OFF 44u +#define IDX_BODY (STORE_PAGE_SIZE - IDX_ENT_OFF) + +/* Overflow page geometry. */ +#define OVF_NEXT_OFF 32u +#define OVF_LEN_OFF 40u +#define OVF_DATA_OFF 44u +#define OVF_CHUNK (STORE_PAGE_SIZE - OVF_DATA_OFF) + +/* Superblock layout (page 0 and mirror page 1). */ +#define SB_MAGIC_OFF 0u +#define SB_FMT_OFF 8u +#define SB_PGSZ_OFF 12u +#define SB_PGCNT_OFF 16u +#define SB_FREE_OFF 24u +#define SB_ROOT_OFF 32u +#define SB_ADJ_OFF 40u +#define SB_LAYER_OFF 48u +#define SB_CKPT_OFF 56u +#define SB_SEQ_OFF 64u +#define SB_UUID_OFF 72u /* 16 bytes */ +#define SB_CRC_OFF 88u + +/* Which index tree. */ +enum { TREE_PRIMARY = 0, TREE_ADJ = 1 }; +#define PRIMARY_PAYLOAD 10u /* [u64 page_id][u16 slot] */ +#define ADJ_PAYLOAD 11u /* [u8 dir][u64 page_id][u16 slot] */ +#define ADJ_DIR_FROM 0u +#define ADJ_DIR_TO 1u +#define MAX_PAYLOAD 16u + +/* Node/Edge TLV tag namespaces (per-kind; page type also disambiguates). */ +enum { + NT_ID = 1, NT_CONTENT, NT_NODE_TYPE, NT_LABEL, NT_TIER, NT_TAGS, NT_METADATA, + NT_SALIENCE, NT_IMPORTANCE, NT_CONFIDENCE, NT_DECAY, + NT_ACT_COUNT, NT_LAST_ACT, NT_CREATED, NT_UPDATED, + NT_BG_ACT, NT_WM_WEIGHT, NT_SUPPRESS, NT_LAYER, + NT_ACCESS_TS, NT_ACCESS_HEAD, NT_ACCESS_FILLED, NT_WM_ANCHOR, + NT_EMB, NT_EMB_DIM +}; +enum { + ET_ID = 1, ET_FROM, ET_TO, ET_RELATION, ET_METADATA, + ET_WEIGHT, ET_HEBB, ET_CONFIDENCE, ET_CREATED, ET_UPDATED, ET_LAST_FIRED, + ET_INHIBITORY, ET_LAYER +}; + +struct EngramPagedStore { + int fd; + char path[1024]; + uint32_t format_version; + uint32_t page_size; + uint64_t page_count; + uint64_t free_list_head; /* page id of first FREE page, 0 = none */ + uint64_t root_index_page; /* primary id->loc B+-tree root */ + uint64_t adj_index_page; /* from/to adjacency B+-tree root */ + uint64_t layer_registry_page; + uint64_t last_checkpoint_lsn; /* 0 in M1 (no checkpoints yet) */ + uint64_t sb_seq; + uint8_t uuid[16]; + uint64_t next_lsn; + uint64_t cur_node_page; /* last NODE page with room, 0 = none */ + uint64_t cur_edge_page; /* last EDGE page with room, 0 = none */ + int leaf_max; /* test hook; 0 = natural */ + int int_max; +}; + +/* ── little-endian scalar codecs ──────────────────────────────────────────── */ +static void put_u16(uint8_t* p, uint16_t v){ p[0]=(uint8_t)v; p[1]=(uint8_t)(v>>8); } +static void put_u32(uint8_t* p, uint32_t v){ for(int i=0;i<4;i++) p[i]=(uint8_t)(v>>(8*i)); } +static void put_u64(uint8_t* p, uint64_t v){ for(int i=0;i<8;i++) p[i]=(uint8_t)(v>>(8*i)); } +static uint16_t get_u16(const uint8_t* p){ return (uint16_t)(p[0] | (p[1]<<8)); } +static uint32_t get_u32(const uint8_t* p){ uint32_t v=0; for(int i=0;i<4;i++) v|=(uint32_t)p[i]<<(8*i); return v; } +static uint64_t get_u64(const uint8_t* p){ uint64_t v=0; for(int i=0;i<8;i++) v|=(uint64_t)p[i]<<(8*i); return v; } +static void put_f64(uint8_t* p, double d){ uint64_t u; memcpy(&u,&d,8); put_u64(p,u); } +static double get_f64(const uint8_t* p){ uint64_t u=get_u64(p); double d; memcpy(&d,&u,8); return d; } + +/* ── crc32 (IEEE 802.3, reflected, poly 0xEDB88320); matches eg_crc32 in + * el_runtime.c so integrity checks are consistent cross-module. + * crc32("") == 0, crc32("123456789") == 0xCBF43926. ─────────────────────── */ +static uint32_t s_crc_table[256]; +static int s_crc_ready = 0; +static void crc_init(void){ + for (uint32_t i=0;i<256;i++){ + uint32_t c=i; + for (int k=0;k<8;k++) c = (c&1) ? (0xEDB88320u ^ (c>>1)) : (c>>1); + s_crc_table[i]=c; + } + s_crc_ready=1; +} +static uint32_t crc32_buf(const void* data, size_t n){ + if (!s_crc_ready) crc_init(); + const uint8_t* p = (const uint8_t*)data; + uint32_t c = 0xFFFFFFFFu; + for (size_t i=0;i> 8); + return c ^ 0xFFFFFFFFu; +} + +/* FNV-1a 64-bit over a NUL-terminated id; the B+-tree key. Exact id is verified + * against the record on read, so hash collisions are correctness-safe. */ +static uint64_t id_hash(const char* s){ + uint64_t h = 1469598103934665603ULL; + for (; *s; ++s){ h ^= (uint8_t)*s; h *= 1099511628211ULL; } + return h; +} + +/* ── raw page I/O ─────────────────────────────────────────────────────────── */ +static int page_read(EngramPagedStore* s, uint64_t id, uint8_t* buf){ + off_t off = (off_t)id * STORE_PAGE_SIZE; + ssize_t r = pread(s->fd, buf, STORE_PAGE_SIZE, off); + if (r != (ssize_t)STORE_PAGE_SIZE) return -1; + return 0; +} +static int page_write_raw(EngramPagedStore* s, uint64_t id, const uint8_t* buf){ + off_t off = (off_t)id * STORE_PAGE_SIZE; + ssize_t w = pwrite(s->fd, buf, STORE_PAGE_SIZE, off); + if (w != (ssize_t)STORE_PAGE_SIZE) return -1; + return 0; +} +/* Stamp lsn + crc into a generic page header, then write. */ +static int page_write(EngramPagedStore* s, uint64_t id, uint8_t* buf){ + put_u64(buf + 0, id); + put_u64(buf + 16, ++s->next_lsn); + put_u32(buf + 24, 0); + uint32_t crc = crc32_buf(buf, STORE_PAGE_SIZE); + put_u32(buf + 24, crc); + return page_write_raw(s, id, buf); +} +static int page_crc_ok(const uint8_t* buf){ + uint8_t tmp[STORE_PAGE_SIZE]; + memcpy(tmp, buf, STORE_PAGE_SIZE); + uint32_t stored = get_u32(tmp + 24); + put_u32(tmp + 24, 0); + return crc32_buf(tmp, STORE_PAGE_SIZE) == stored; +} + +/* Allocate a page: reuse a FREE page if available, else extend the file. */ +static uint64_t page_alloc(EngramPagedStore* s, uint8_t type){ + uint8_t buf[STORE_PAGE_SIZE]; + uint64_t id; + if (s->free_list_head){ + id = s->free_list_head; + if (page_read(s, id, buf) != 0) return 0; + s->free_list_head = get_u64(buf + OVF_NEXT_OFF); /* next_free stashed here */ + } else { + id = s->page_count++; + } + memset(buf, 0, STORE_PAGE_SIZE); + buf[8] = type; + if (type == STORE_PT_NODE || type == STORE_PT_EDGE){ + put_u16(buf + 10, 0); + put_u16(buf + 12, (uint16_t)(STORE_PAGE_SIZE - STORE_HDR)); /* all heap free */ + } + if (page_write(s, id, buf) != 0) return 0; + return id; +} +/* Return a now-empty page to the free list. */ +static int page_free(EngramPagedStore* s, uint64_t id){ + uint8_t buf[STORE_PAGE_SIZE]; + memset(buf, 0, STORE_PAGE_SIZE); + buf[8] = STORE_PT_FREE; + put_u64(buf + OVF_NEXT_OFF, s->free_list_head); + if (page_write(s, id, buf) != 0) return -1; + s->free_list_head = id; + return 0; +} + +/* ── slotted page helpers (operate on a page already in `buf`) ────────────── */ +static int slp_count(const uint8_t* buf){ return get_u16(buf + 10); } +static int slp_free(const uint8_t* buf){ return get_u16(buf + 12); } +static void slp_slot(const uint8_t* buf, int i, uint16_t* off, uint16_t* len, uint16_t* fl){ + const uint8_t* p = buf + STORE_HDR + (size_t)i*SLOT_SIZE; + *off = get_u16(p); *len = get_u16(p+2); *fl = get_u16(p+4); +} +static void slp_set_slot(uint8_t* buf, int i, uint16_t off, uint16_t len, uint16_t fl){ + uint8_t* p = buf + STORE_HDR + (size_t)i*SLOT_SIZE; + put_u16(p, off); put_u16(p+2, len); put_u16(p+4, fl); +} +static int slp_live_count(const uint8_t* buf){ + int n = slp_count(buf), live = 0; + for (int i=0;i=reclen){ + memcpy(buf + o, rec, reclen); + slp_set_slot(buf, i, o, reclen, SLOT_LIVE); + return i; + } + } + int freeb = slp_free(buf); + if ((int)reclen + (int)SLOT_SIZE > freeb) return -1; + uint16_t heap_top = (uint16_t)(STORE_HDR + n*SLOT_SIZE + freeb); + uint16_t off = (uint16_t)(heap_top - reclen); + memcpy(buf + off, rec, reclen); + slp_set_slot(buf, n, off, reclen, SLOT_LIVE); + put_u16(buf + 10, (uint16_t)(n+1)); + put_u16(buf + 12, (uint16_t)(freeb - reclen - SLOT_SIZE)); + return n; +} + +/* ── overflow chains ──────────────────────────────────────────────────────── */ +static uint64_t ovf_write_chain(EngramPagedStore* s, const uint8_t* blob, size_t len){ + uint64_t head = 0, prev = 0; + size_t off = 0; + do { + uint64_t id = page_alloc(s, STORE_PT_OVERFLOW); + if (!id) return 0; + if (!head) head = id; + if (prev){ + uint8_t pbuf[STORE_PAGE_SIZE]; + if (page_read(s, prev, pbuf)!=0) return 0; + put_u64(pbuf + OVF_NEXT_OFF, id); + if (page_write(s, prev, pbuf)!=0) return 0; + } + uint8_t buf[STORE_PAGE_SIZE]; + memset(buf, 0, STORE_PAGE_SIZE); + buf[8] = STORE_PT_OVERFLOW; + size_t chunk = len - off; if (chunk > OVF_CHUNK) chunk = OVF_CHUNK; + put_u64(buf + OVF_NEXT_OFF, 0); + put_u32(buf + OVF_LEN_OFF, (uint32_t)chunk); + memcpy(buf + OVF_DATA_OFF, blob + off, chunk); + if (page_write(s, id, buf)!=0) return 0; + prev = id; off += chunk; + } while (off < len); + return head; +} +static uint8_t* ovf_read_chain(EngramPagedStore* s, uint64_t head, size_t total){ + uint8_t* out = (uint8_t*)malloc(total ? total : 1); + if (!out) return NULL; + size_t off = 0; uint64_t id = head; + while (id){ + uint8_t buf[STORE_PAGE_SIZE]; + if (page_read(s, id, buf)!=0){ free(out); return NULL; } + uint32_t chunk = get_u32(buf + OVF_LEN_OFF); + if (off + chunk > total){ free(out); return NULL; } + memcpy(out + off, buf + OVF_DATA_OFF, chunk); + off += chunk; + id = get_u64(buf + OVF_NEXT_OFF); + } + if (off != total){ free(out); return NULL; } + return out; +} + +/* ── growable byte buffer for TLV assembly ────────────────────────────────── */ +typedef struct { uint8_t* p; size_t len, cap; } Buf; +static int buf_reserve(Buf* b, size_t extra){ + if (b->len + extra <= b->cap) return 0; + size_t nc = b->cap ? b->cap*2 : 256; + while (nc < b->len + extra) nc *= 2; + uint8_t* np = (uint8_t*)realloc(b->p, nc); + if (!np) return -1; + b->p = np; b->cap = nc; return 0; +} +static int buf_raw(Buf* b, const void* data, size_t n){ + if (buf_reserve(b, n)) return -1; + memcpy(b->p + b->len, data, n); b->len += n; return 0; +} +static int tlv_field(Buf* b, uint8_t tag, const void* data, uint32_t len){ + if (buf_reserve(b, 5 + len)) return -1; + b->p[b->len++] = tag; + put_u32(b->p + b->len, len); b->len += 4; + if (len){ memcpy(b->p + b->len, data, len); b->len += len; } + return 0; +} +static int tlv_str(Buf* b, uint8_t tag, const char* s){ + if (!s) return 0; /* NULL string omitted → reader defaults NULL */ + return tlv_field(b, tag, s, (uint32_t)strlen(s)); +} +static int tlv_f64(Buf* b, uint8_t tag, double v){ uint8_t t[8]; put_f64(t,v); return tlv_field(b,tag,t,8); } +static int tlv_i64(Buf* b, uint8_t tag, int64_t v){ uint8_t t[8]; put_u64(t,(uint64_t)v); return tlv_field(b,tag,t,8); } +static int tlv_i32(Buf* b, uint8_t tag, int32_t v){ uint8_t t[4]; put_u32(t,(uint32_t)v); return tlv_field(b,tag,t,4); } +static int tlv_u32(Buf* b, uint8_t tag, uint32_t v){ uint8_t t[4]; put_u32(t,v); return tlv_field(b,tag,t,4); } + +/* ── node/edge serialization to a TLV body ────────────────────────────────── */ +static uint8_t* node_serialize(const StoreNode* n, size_t* out_len){ + Buf b = {0,0,0}; + tlv_str(&b, NT_ID, n->id); + tlv_str(&b, NT_CONTENT, n->content); + tlv_str(&b, NT_NODE_TYPE, n->node_type); + tlv_str(&b, NT_LABEL, n->label); + tlv_str(&b, NT_TIER, n->tier); + tlv_str(&b, NT_TAGS, n->tags); + tlv_str(&b, NT_METADATA, n->metadata); + tlv_f64(&b, NT_SALIENCE, n->salience); + tlv_f64(&b, NT_IMPORTANCE, n->importance); + tlv_f64(&b, NT_CONFIDENCE, n->confidence); + tlv_f64(&b, NT_DECAY, n->temporal_decay_rate); + tlv_i64(&b, NT_ACT_COUNT, n->activation_count); + tlv_i64(&b, NT_LAST_ACT, n->last_activated); + tlv_i64(&b, NT_CREATED, n->created_at); + tlv_i64(&b, NT_UPDATED, n->updated_at); + tlv_f64(&b, NT_BG_ACT, n->background_activation); + tlv_f64(&b, NT_WM_WEIGHT, n->working_memory_weight); + tlv_i32(&b, NT_SUPPRESS, n->suppression_count); + tlv_u32(&b, NT_LAYER, n->layer_id); + { uint8_t at[STORE_BLL_K*8]; + for (int i=0;iaccess_ts[i]); + tlv_field(&b, NT_ACCESS_TS, at, sizeof at); } + tlv_i32(&b, NT_ACCESS_HEAD, n->access_head); + tlv_i32(&b, NT_ACCESS_FILLED, n->access_filled); + tlv_f64(&b, NT_WM_ANCHOR, n->wm_anchor); + if (n->emb && n->emb_dim > 0){ + uint8_t* eb = (uint8_t*)malloc((size_t)n->emb_dim*4); + for (int i=0;iemb_dim;i++){ uint32_t u; memcpy(&u,&n->emb[i],4); put_u32(eb+i*4,u); } + tlv_field(&b, NT_EMB, eb, (uint32_t)n->emb_dim*4); + free(eb); + tlv_i32(&b, NT_EMB_DIM, n->emb_dim); + } + if (n->unknown && n->unknown_len) buf_raw(&b, n->unknown, n->unknown_len); + *out_len = b.len; + return b.p; +} +static uint8_t* edge_serialize(const StoreEdge* e, size_t* out_len){ + Buf b = {0,0,0}; + tlv_str(&b, ET_ID, e->id); + tlv_str(&b, ET_FROM, e->from_id); + tlv_str(&b, ET_TO, e->to_id); + tlv_str(&b, ET_RELATION, e->relation); + tlv_str(&b, ET_METADATA, e->metadata); + tlv_f64(&b, ET_WEIGHT, e->weight); + tlv_f64(&b, ET_HEBB, e->hebb); + tlv_f64(&b, ET_CONFIDENCE, e->confidence); + tlv_i64(&b, ET_CREATED, e->created_at); + tlv_i64(&b, ET_UPDATED, e->updated_at); + tlv_i64(&b, ET_LAST_FIRED, e->last_fired); + tlv_i32(&b, ET_INHIBITORY, e->inhibitory); + tlv_u32(&b, ET_LAYER, e->layer_id); + if (e->unknown && e->unknown_len) buf_raw(&b, e->unknown, e->unknown_len); + *out_len = b.len; + return b.p; +} + +/* ── TLV parse helpers ────────────────────────────────────────────────────── */ +static char* dup_str(const uint8_t* p, uint32_t len){ + char* s = (char*)malloc(len + 1); + if (!s) return NULL; + memcpy(s, p, len); s[len] = 0; return s; +} +static void node_parse(const uint8_t* body, size_t len, StoreNode* n){ + memset(n, 0, sizeof *n); + Buf unk = {0,0,0}; + size_t i = 0; + while (i + 5 <= len){ + uint8_t tag = body[i]; + uint32_t flen = get_u32(body + i + 1); + if (i + 5 + flen > len) break; + const uint8_t* v = body + i + 5; + switch (tag){ + case NT_ID: n->id = dup_str(v, flen); break; + case NT_CONTENT: n->content = dup_str(v, flen); break; + case NT_NODE_TYPE: n->node_type = dup_str(v, flen); break; + case NT_LABEL: n->label = dup_str(v, flen); break; + case NT_TIER: n->tier = dup_str(v, flen); break; + case NT_TAGS: n->tags = dup_str(v, flen); break; + case NT_METADATA: n->metadata = dup_str(v, flen); break; + case NT_SALIENCE: n->salience = get_f64(v); break; + case NT_IMPORTANCE: n->importance = get_f64(v); break; + case NT_CONFIDENCE: n->confidence = get_f64(v); break; + case NT_DECAY: n->temporal_decay_rate = get_f64(v); break; + case NT_ACT_COUNT: n->activation_count = (int64_t)get_u64(v); break; + case NT_LAST_ACT: n->last_activated = (int64_t)get_u64(v); break; + case NT_CREATED: n->created_at = (int64_t)get_u64(v); break; + case NT_UPDATED: n->updated_at = (int64_t)get_u64(v); break; + case NT_BG_ACT: n->background_activation = get_f64(v); break; + case NT_WM_WEIGHT: n->working_memory_weight = get_f64(v); break; + case NT_SUPPRESS: n->suppression_count = (int32_t)get_u32(v); break; + case NT_LAYER: n->layer_id = get_u32(v); break; + case NT_ACCESS_TS: + for (int k=0;kaccess_ts[k] = (int64_t)get_u64(v + k*8); + break; + case NT_ACCESS_HEAD: n->access_head = (int32_t)get_u32(v); break; + case NT_ACCESS_FILLED: n->access_filled = (int32_t)get_u32(v); break; + case NT_WM_ANCHOR: n->wm_anchor = get_f64(v); break; + case NT_EMB: { + int32_t dim = (int32_t)(flen/4); + n->emb = (float*)malloc(flen ? flen : 4); + for (int32_t k=0;kemb[k],&u,4); } + if (n->emb_dim == 0) n->emb_dim = dim; /* honour explicit dim if seen */ + break; } + case NT_EMB_DIM: n->emb_dim = (int32_t)get_u32(v); break; + default: + /* unknown tag: preserve verbatim */ + buf_raw(&unk, body + i, 5 + flen); + break; + } + i += 5 + flen; + } + n->unknown = unk.p; n->unknown_len = unk.len; +} +static void edge_parse(const uint8_t* body, size_t len, StoreEdge* e){ + memset(e, 0, sizeof *e); + Buf unk = {0,0,0}; + size_t i = 0; + while (i + 5 <= len){ + uint8_t tag = body[i]; + uint32_t flen = get_u32(body + i + 1); + if (i + 5 + flen > len) break; + const uint8_t* v = body + i + 5; + switch (tag){ + case ET_ID: e->id = dup_str(v, flen); break; + case ET_FROM: e->from_id = dup_str(v, flen); break; + case ET_TO: e->to_id = dup_str(v, flen); break; + case ET_RELATION: e->relation = dup_str(v, flen); break; + case ET_METADATA: e->metadata = dup_str(v, flen); break; + case ET_WEIGHT: e->weight = get_f64(v); break; + case ET_HEBB: e->hebb = get_f64(v); break; + case ET_CONFIDENCE: e->confidence = get_f64(v); break; + case ET_CREATED: e->created_at = (int64_t)get_u64(v); break; + case ET_UPDATED: e->updated_at = (int64_t)get_u64(v); break; + case ET_LAST_FIRED: e->last_fired = (int64_t)get_u64(v); break; + case ET_INHIBITORY: e->inhibitory = (int32_t)get_u32(v); break; + case ET_LAYER: e->layer_id = get_u32(v); break; + default: + buf_raw(&unk, body + i, 5 + flen); + break; + } + i += 5 + flen; + } + e->unknown = unk.p; e->unknown_len = unk.len; +} + +/* ── B+-tree ──────────────────────────────────────────────────────────────── */ +static uint32_t tree_payload(int tree){ return tree==TREE_PRIMARY ? PRIMARY_PAYLOAD : ADJ_PAYLOAD; } +static uint64_t tree_root(EngramPagedStore* s, int tree){ + return tree==TREE_PRIMARY ? s->root_index_page : s->adj_index_page; +} +static void tree_set_root(EngramPagedStore* s, int tree, uint64_t id){ + if (tree==TREE_PRIMARY) s->root_index_page = id; else s->adj_index_page = id; +} +static int leaf_max_entries(EngramPagedStore* s, uint32_t payload){ + int nat = (int)(IDX_BODY / (8 + payload)); + if (s->leaf_max > 0 && s->leaf_max < nat) return s->leaf_max; + return nat; +} +static int int_max_keys(EngramPagedStore* s){ + /* keys*8 + (keys+1)*8 <= IDX_BODY → keys <= IDX_BODY/8 - 1 */ + int nat = (int)(IDX_BODY / 8) - 1; + if (s->int_max > 0 && s->int_max < nat) return s->int_max; + return nat; +} + +/* Recursive insert. Returns 0 (no split) or 1 (split; sep_key and new_page set). */ +static int btree_insert(EngramPagedStore* s, int tree, uint64_t page_id, + uint64_t key, const uint8_t* payload, + uint64_t* sep_key, uint64_t* new_page){ + uint32_t pl = tree_payload(tree); + uint32_t esz = 8 + pl; + uint8_t buf[STORE_PAGE_SIZE]; + if (page_read(s, page_id, buf)!=0) return -1; + int nkeys = get_u16(buf + 10); + int is_leaf = buf[IDX_LEAF_OFF]; + + if (is_leaf){ + /* find insert position (after equal keys → stable duplicates) */ + int pos = 0; + while (pos < nkeys){ + uint64_t k = get_u64(buf + IDX_ENT_OFF + (size_t)pos*esz); + if (k > key) break; + pos++; + } + int lmax = leaf_max_entries(s, pl); + if (nkeys + 1 <= lmax){ + uint8_t* base = buf + IDX_ENT_OFF; + memmove(base + (size_t)(pos+1)*esz, base + (size_t)pos*esz, + (size_t)(nkeys - pos)*esz); + put_u64(base + (size_t)pos*esz, key); + memcpy(base + (size_t)pos*esz + 8, payload, pl); + put_u16(buf + 10, (uint16_t)(nkeys+1)); + return page_write(s, page_id, buf)==0 ? 0 : -1; + } + /* split: build the full sorted list in a temp, halve it */ + int total = nkeys + 1; + uint8_t* all = (uint8_t*)malloc((size_t)total*esz); + if (!all) return -1; + memcpy(all, buf + IDX_ENT_OFF, (size_t)pos*esz); + put_u64(all + (size_t)pos*esz, key); + memcpy(all + (size_t)pos*esz + 8, payload, pl); + memcpy(all + (size_t)(pos+1)*esz, buf + IDX_ENT_OFF + (size_t)pos*esz, + (size_t)(nkeys - pos)*esz); + int left = total/2, right = total - left; + uint64_t old_next = get_u64(buf + IDX_NEXT_OFF); + uint64_t rid = page_alloc(s, STORE_PT_INDEX); + if (!rid){ free(all); return -1; } + uint8_t rbuf[STORE_PAGE_SIZE]; + if (page_read(s, rid, rbuf)!=0){ free(all); return -1; } + rbuf[IDX_LEAF_OFF] = 1; + put_u16(rbuf + 10, (uint16_t)right); + put_u64(rbuf + IDX_NEXT_OFF, old_next); + memcpy(rbuf + IDX_ENT_OFF, all + (size_t)left*esz, (size_t)right*esz); + /* left page keeps first `left` entries, points to right */ + buf[IDX_LEAF_OFF] = 1; + put_u16(buf + 10, (uint16_t)left); + put_u64(buf + IDX_NEXT_OFF, rid); + memcpy(buf + IDX_ENT_OFF, all, (size_t)left*esz); + *sep_key = get_u64(all + (size_t)left*esz); + free(all); + if (page_write(s, rid, rbuf)!=0) return -1; + if (page_write(s, page_id, buf)!=0) return -1; + *new_page = rid; + return 1; + } + + /* internal: keys at IDX_ENT_OFF (nkeys u64), children after (nkeys+1 u64) */ + uint8_t* K = buf + IDX_ENT_OFF; + uint8_t* C = buf + IDX_ENT_OFF + (size_t)nkeys*8; + int ci = 0; + while (ci < nkeys && key >= get_u64(K + (size_t)ci*8)) ci++; + uint64_t child = get_u64(C + (size_t)ci*8); + uint64_t csep, cnew; + int sp = btree_insert(s, tree, child, key, payload, &csep, &cnew); + if (sp < 0) return -1; + if (sp == 0) return 0; + + /* child split → insert (csep, cnew) at position ci / ci+1 */ + int nk = nkeys + 1; + uint64_t* keys = (uint64_t*)malloc((size_t)nk*8); + uint64_t* kids = (uint64_t*)malloc((size_t)(nk+1)*8); + if (!keys || !kids){ free(keys); free(kids); return -1; } + for (int i=0;ici;i--) keys[i] = keys[i-1]; + keys[ci] = csep; + for (int i=nkeys+1;i>ci+1;i--) kids[i] = kids[i-1]; + kids[ci+1] = cnew; + + int imax = int_max_keys(s); + if (nk <= imax){ + put_u16(buf + 10, (uint16_t)nk); + uint8_t* K2 = buf + IDX_ENT_OFF; + uint8_t* C2 = buf + IDX_ENT_OFF + (size_t)nk*8; + for (int i=0;i' here — not + * the '>=' of insert routing — then scan forward across next_leaf. */ + int ci = 0; + while (ci < nkeys && target > get_u64(K + (size_t)ci*8)) ci++; + id = get_u64(C + (size_t)ci*8); + } + Buf acc = {0,0,0}; + for (;;){ + int nkeys = get_u16(buf + 10); + int past = 0; + for (int i=0;i target){ past = 1; break; } + if (buf_raw(&acc, buf + IDX_ENT_OFF + (size_t)i*esz + 8, pl)){ free(acc.p); return -1; } + } + if (past) break; + uint64_t nxt = get_u64(buf + IDX_NEXT_OFF); + if (!nxt) break; + if (page_read(s, nxt, buf)!=0){ free(acc.p); return -1; } + } + *out = acc.p; *count = acc.len / pl; + return 0; +} + +/* ── superblock ───────────────────────────────────────────────────────────── */ +static int sb_write_one(EngramPagedStore* s, uint64_t page){ + uint8_t buf[STORE_PAGE_SIZE]; + memset(buf, 0, STORE_PAGE_SIZE); + memcpy(buf + SB_MAGIC_OFF, STORE_MAGIC, 8); /* 7 chars + NUL */ + put_u32(buf + SB_FMT_OFF, s->format_version); + put_u32(buf + SB_PGSZ_OFF, s->page_size); + put_u64(buf + SB_PGCNT_OFF, s->page_count); + put_u64(buf + SB_FREE_OFF, s->free_list_head); + put_u64(buf + SB_ROOT_OFF, s->root_index_page); + put_u64(buf + SB_ADJ_OFF, s->adj_index_page); + put_u64(buf + SB_LAYER_OFF, s->layer_registry_page); + put_u64(buf + SB_CKPT_OFF, s->last_checkpoint_lsn); + put_u64(buf + SB_SEQ_OFF, s->sb_seq); + memcpy(buf + SB_UUID_OFF, s->uuid, 16); + put_u32(buf + SB_CRC_OFF, 0); + uint32_t crc = crc32_buf(buf, STORE_PAGE_SIZE); + put_u32(buf + SB_CRC_OFF, crc); + return page_write_raw(s, page, buf); +} +static int sb_load_one(EngramPagedStore* s, uint64_t page, uint8_t* buf, uint64_t* seq_out){ + if (page_read(s, page, buf)!=0) return -1; + if (memcmp(buf + SB_MAGIC_OFF, STORE_MAGIC, 8)!=0) return -1; + uint32_t stored = get_u32(buf + SB_CRC_OFF); + uint8_t tmp[STORE_PAGE_SIZE]; + memcpy(tmp, buf, STORE_PAGE_SIZE); + put_u32(tmp + SB_CRC_OFF, 0); + if (crc32_buf(tmp, STORE_PAGE_SIZE) != stored) return -1; + *seq_out = get_u64(buf + SB_SEQ_OFF); + return 0; +} +static void sb_apply(EngramPagedStore* s, const uint8_t* buf){ + s->format_version = get_u32(buf + SB_FMT_OFF); + s->page_size = get_u32(buf + SB_PGSZ_OFF); + s->page_count = get_u64(buf + SB_PGCNT_OFF); + s->free_list_head = get_u64(buf + SB_FREE_OFF); + s->root_index_page = get_u64(buf + SB_ROOT_OFF); + s->adj_index_page = get_u64(buf + SB_ADJ_OFF); + s->layer_registry_page= get_u64(buf + SB_LAYER_OFF); + s->last_checkpoint_lsn= get_u64(buf + SB_CKPT_OFF); + s->sb_seq = get_u64(buf + SB_SEQ_OFF); + memcpy(s->uuid, buf + SB_UUID_OFF, 16); +} + +int store_sync(EngramPagedStore* s){ + if (!s) return -1; + s->sb_seq++; + /* write primary, fsync, then mirror, fsync — so a torn write of one leaves + * the other valid; recovery prefers the higher valid sb_seq. */ + if (sb_write_one(s, 0)!=0) return -1; + if (fsync(s->fd)!=0) return -1; + if (sb_write_one(s, 1)!=0) return -1; + if (fsync(s->fd)!=0) return -1; + return 0; +} + +/* ── lifecycle ────────────────────────────────────────────────────────────── */ +static void gen_uuid(uint8_t out[16]){ + int fd = open("/dev/urandom", O_RDONLY); + if (fd >= 0){ ssize_t r = read(fd, out, 16); close(fd); if (r == 16) return; } + uint64_t t = (uint64_t)time(NULL) ^ ((uint64_t)getpid() << 32); + for (int i=0;i<16;i++){ t = t*6364136223846793005ULL + 1442695040888963407ULL; out[i] = (uint8_t)(t>>56); } +} +static uint64_t idx_alloc_leaf(EngramPagedStore* s){ + uint64_t id = page_alloc(s, STORE_PT_INDEX); + if (!id) return 0; + uint8_t buf[STORE_PAGE_SIZE]; + if (page_read(s, id, buf)!=0) return 0; + buf[IDX_LEAF_OFF] = 1; + put_u16(buf + 10, 0); + put_u64(buf + IDX_NEXT_OFF, 0); + if (page_write(s, id, buf)!=0) return 0; + return id; +} + +EngramPagedStore* store_create(const char* path){ + if (!s_crc_ready) crc_init(); + struct stat st; + if (stat(path, &st) == 0){ errno = EEXIST; return NULL; } + EngramPagedStore* s = (EngramPagedStore*)calloc(1, sizeof *s); + if (!s) return NULL; + s->fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); + if (s->fd < 0){ free(s); return NULL; } + snprintf(s->path, sizeof s->path, "%s", path); + s->format_version = STORE_FORMAT_VERSION; + s->page_size = STORE_PAGE_SIZE; + s->page_count = 2; /* pages 0,1 are the superblock + mirror */ + s->free_list_head = 0; + s->next_lsn = 0; + s->sb_seq = 0; + gen_uuid(s->uuid); + /* reserve pages 0,1 on disk */ + uint8_t zero[STORE_PAGE_SIZE]; memset(zero, 0, sizeof zero); + if (page_write_raw(s, 0, zero)!=0 || page_write_raw(s, 1, zero)!=0){ close(s->fd); free(s); return NULL; } + s->root_index_page = idx_alloc_leaf(s); + s->adj_index_page = idx_alloc_leaf(s); + s->layer_registry_page = page_alloc(s, STORE_PT_NODE); /* reserved; unused in M1 */ + if (!s->root_index_page || !s->adj_index_page || !s->layer_registry_page){ + close(s->fd); free(s); return NULL; + } + if (store_sync(s)!=0){ close(s->fd); free(s); return NULL; } + return s; +} + +EngramPagedStore* store_open(const char* path){ + if (!s_crc_ready) crc_init(); + EngramPagedStore* s = (EngramPagedStore*)calloc(1, sizeof *s); + if (!s) return NULL; + s->fd = open(path, O_RDWR); + if (s->fd < 0){ free(s); return NULL; } + snprintf(s->path, sizeof s->path, "%s", path); + uint8_t b0[STORE_PAGE_SIZE], b1[STORE_PAGE_SIZE]; + uint64_t s0 = 0, s1 = 0; + int ok0 = sb_load_one(s, 0, b0, &s0) == 0; + int ok1 = sb_load_one(s, 1, b1, &s1) == 0; + if (!ok0 && !ok1){ close(s->fd); free(s); return NULL; } + const uint8_t* pick; + if (ok0 && ok1) pick = (s0 >= s1) ? b0 : b1; + else pick = ok0 ? b0 : b1; + sb_apply(s, pick); + if (s->page_size != STORE_PAGE_SIZE){ close(s->fd); free(s); return NULL; } + s->next_lsn = s->sb_seq; /* resume LSNs above the last synced value */ + s->cur_node_page = 0; + s->cur_edge_page = 0; + return s; +} + +int store_close(EngramPagedStore* s){ + if (!s) return -1; + int rc = store_sync(s); + if (s->fd >= 0) close(s->fd); + free(s); + return rc; +} + +/* ── put node/edge ────────────────────────────────────────────────────────── */ +/* Build the on-page record (inline or overflow stub) from a TLV body. */ +static int build_record(EngramPagedStore* s, const uint8_t* body, size_t blen, + uint8_t** rec_out, uint16_t* reclen_out){ + if (blen <= MAX_INLINE_BODY){ + uint16_t reclen = (uint16_t)(REC_HDR + blen); + uint8_t* rec = (uint8_t*)malloc(reclen); + if (!rec) return -1; + put_u16(rec, reclen); rec[2] = REC_VER; rec[3] = 0; + memcpy(rec + REC_HDR, body, blen); + *rec_out = rec; *reclen_out = reclen; + return 0; + } + uint64_t head = ovf_write_chain(s, body, blen); + if (!head) return -1; + uint16_t reclen = REC_HDR + 16; + uint8_t* rec = (uint8_t*)malloc(reclen); + if (!rec) return -1; + put_u16(rec, reclen); rec[2] = REC_VER; rec[3] = REC_OVERFLOW; + put_u64(rec + REC_HDR, head); + put_u64(rec + REC_HDR + 8, (uint64_t)blen); + *rec_out = rec; *reclen_out = reclen; + return 0; +} +/* Place a record into a NODE or EDGE page; returns (page_id,slot). Uses/creates + * the current page of that type; on-page dead-slot reuse handled by slp_put. */ +static int place_record(EngramPagedStore* s, uint8_t ptype, const uint8_t* rec, + uint16_t reclen, uint64_t* page_id_out, uint16_t* slot_out){ + uint64_t* cur = (ptype==STORE_PT_NODE) ? &s->cur_node_page : &s->cur_edge_page; + uint8_t buf[STORE_PAGE_SIZE]; + if (*cur){ + if (page_read(s, *cur, buf)==0){ + int slot = slp_put(buf, rec, reclen); + if (slot >= 0){ + if (page_write(s, *cur, buf)!=0) return -1; + *page_id_out = *cur; *slot_out = (uint16_t)slot; return 0; + } + } + } + uint64_t pid = page_alloc(s, ptype); + if (!pid) return -1; + if (page_read(s, pid, buf)!=0) return -1; + int slot = slp_put(buf, rec, reclen); + if (slot < 0) return -1; /* record too big for an empty page */ + if (page_write(s, pid, buf)!=0) return -1; + *cur = pid; + *page_id_out = pid; *slot_out = (uint16_t)slot; + return 0; +} + +int store_put_node(EngramPagedStore* s, const StoreNode* n){ + if (!s || !n || !n->id) return -1; + size_t blen; uint8_t* body = node_serialize(n, &blen); + if (!body) return -1; + uint8_t* rec; uint16_t reclen; + if (build_record(s, body, blen, &rec, &reclen)){ free(body); return -1; } + free(body); + uint64_t pid; uint16_t slot; + if (place_record(s, STORE_PT_NODE, rec, reclen, &pid, &slot)){ free(rec); return -1; } + free(rec); + uint8_t payload[PRIMARY_PAYLOAD]; + put_u64(payload, pid); put_u16(payload + 8, slot); + return btree_put(s, TREE_PRIMARY, id_hash(n->id), payload); +} + +int store_put_edge(EngramPagedStore* s, const StoreEdge* e){ + if (!s || !e || !e->id || !e->from_id || !e->to_id) return -1; + size_t blen; uint8_t* body = edge_serialize(e, &blen); + if (!body) return -1; + uint8_t* rec; uint16_t reclen; + if (build_record(s, body, blen, &rec, &reclen)){ free(body); return -1; } + free(body); + uint64_t pid; uint16_t slot; + if (place_record(s, STORE_PT_EDGE, rec, reclen, &pid, &slot)){ free(rec); return -1; } + free(rec); + /* primary index: edge id → loc */ + uint8_t pp[PRIMARY_PAYLOAD]; + put_u64(pp, pid); put_u16(pp + 8, slot); + if (btree_put(s, TREE_PRIMARY, id_hash(e->id), pp)!=0) return -1; + /* adjacency: from_id and to_id → edge loc */ + uint8_t af[ADJ_PAYLOAD]; af[0]=ADJ_DIR_FROM; put_u64(af+1,pid); put_u16(af+9,slot); + if (btree_put(s, TREE_ADJ, id_hash(e->from_id), af)!=0) return -1; + uint8_t at[ADJ_PAYLOAD]; at[0]=ADJ_DIR_TO; put_u64(at+1,pid); put_u16(at+9,slot); + if (btree_put(s, TREE_ADJ, id_hash(e->to_id), at)!=0) return -1; + return 0; +} + +/* ── read a record body (resolving overflow) at (page,slot). Returns malloc'd + * body + length, and whether the slot was live. ─────────────────────────── */ +static int read_body(EngramPagedStore* s, uint64_t page, uint16_t slot, + uint8_t** body_out, size_t* blen_out, int* live_out){ + uint8_t buf[STORE_PAGE_SIZE]; + if (page_read(s, page, buf)!=0) return -1; + if (slot >= slp_count(buf)) return -1; + uint16_t off,len,fl; slp_slot(buf, slot, &off, &len, &fl); + *live_out = (fl == SLOT_LIVE); + if (len < REC_HDR) return -1; + uint8_t rec_flags = buf[off + 3]; + if (rec_flags & REC_OVERFLOW){ + uint64_t head = get_u64(buf + off + REC_HDR); + uint64_t total = get_u64(buf + off + REC_HDR + 8); + uint8_t* body = ovf_read_chain(s, head, (size_t)total); + if (!body) return -1; + *body_out = body; *blen_out = (size_t)total; + } else { + uint16_t reclen = get_u16(buf + off); + size_t blen = reclen - REC_HDR; + uint8_t* body = (uint8_t*)malloc(blen ? blen : 1); + if (!body) return -1; + memcpy(body, buf + off + REC_HDR, blen); + *body_out = body; *blen_out = blen; + } + return 0; +} + +int store_get_node(EngramPagedStore* s, const char* id, StoreNode* out){ + if (!s || !id || !out) return -1; + uint8_t* locs; size_t n; + if (btree_lookup(s, TREE_PRIMARY, id_hash(id), &locs, &n)!=0) return -1; + int found = 0; + for (size_t i=0;itombstoned = 0; found = 1; + } else store_node_free(&cand); + } else store_node_free(&cand); + } + free(locs); + return found ? 1 : 0; +} + +int store_tombstone(EngramPagedStore* s, const char* id){ + if (!s || !id) return -1; + uint8_t* locs; size_t n; + if (btree_lookup(s, TREE_PRIMARY, id_hash(id), &locs, &n)!=0) return -1; + int hit = 0; + for (size_t i=0;i= slp_count(buf)) continue; + uint16_t off,len,fl; slp_slot(buf, slot, &off, &len, &fl); + if (fl != SLOT_LIVE) continue; + /* verify id matches this record before killing it */ + uint8_t* body; size_t blen; int live; + if (read_body(s, page, slot, &body, &blen, &live)!=0) continue; + StoreNode cand; node_parse(body, blen, &cand); free(body); + int match = cand.id && strcmp(cand.id, id)==0; + store_node_free(&cand); + if (!match) continue; + slp_set_slot(buf, slot, off, len, SLOT_DEAD); + if (page_write(s, page, buf)!=0){ free(locs); return -1; } + hit = 1; + /* if the page is now empty, reclaim it to the free list */ + if (page_read(s, page, buf)==0 && slp_live_count(buf)==0){ + if (s->cur_node_page == page) s->cur_node_page = 0; + if (s->cur_edge_page == page) s->cur_edge_page = 0; + page_free(s, page); + } + } + free(locs); + return hit ? 0 : 0; /* absent id is a no-op success */ +} + +static int get_edges_dir(EngramPagedStore* s, const char* id, uint8_t want_dir, + StoreEdge** out, size_t* n){ + *out = NULL; *n = 0; + uint8_t* locs; size_t cnt; + if (btree_lookup(s, TREE_ADJ, id_hash(id), &locs, &cnt)!=0) return -1; + StoreEdge* arr = NULL; size_t used = 0, cap = 0; + for (size_t i=0;ipage_count; id++){ + if (page_read(s, id, buf)!=0) return -1; + if (id == 0 || id == 1){ + uint32_t stored = get_u32(buf + SB_CRC_OFF); + uint8_t tmp[STORE_PAGE_SIZE]; memcpy(tmp, buf, STORE_PAGE_SIZE); + put_u32(tmp + SB_CRC_OFF, 0); + int okmagic = memcmp(buf + SB_MAGIC_OFF, STORE_MAGIC, 8)==0; + if (!okmagic || crc32_buf(tmp, STORE_PAGE_SIZE) != stored) bad++; + } else { + if (flags & STORE_CHECK_CRC){ if (!page_crc_ok(buf)) bad++; } + } + } + return bad; +} + +/* ── ownership helpers ────────────────────────────────────────────────────── */ +void store_node_free(StoreNode* n){ + if (!n) return; + free(n->id); free(n->content); free(n->node_type); free(n->label); + free(n->tier); free(n->tags); free(n->metadata); free(n->emb); free(n->unknown); + memset(n, 0, sizeof *n); +} +void store_edge_free(StoreEdge* e){ + if (!e) return; + free(e->id); free(e->from_id); free(e->to_id); free(e->relation); + free(e->metadata); free(e->unknown); + memset(e, 0, sizeof *e); +} +void store_edges_free(StoreEdge* arr, size_t n){ + if (!arr) return; + for (size_t i=0;ileaf_max = leaf_max; s->int_max = internal_max; +} +uint64_t store_page_count(const EngramPagedStore* s){ return s ? s->page_count : 0; } diff --git a/lang/runtime/engram_store.h b/lang/runtime/engram_store.h new file mode 100644 index 0000000..c791da0 --- /dev/null +++ b/lang/runtime/engram_store.h @@ -0,0 +1,135 @@ +/* engram_store.h — M1 of the engram tiered storage engine. + * + * The FINAL on-disk paged store format: superblock (+ mirror), slotted pages, + * self-describing TLV records, overflow chains, and two B+-tree indexes + * (primary id->loc, adjacency from_id/to_id->edge-locs) over a free-listed + * page file. See docs/architecture/design/engram-tiered-storage-engine.md §2. + * + * This is a self-contained module (plain C, standard libs only). It defines its + * own serializable views of a node/edge (StoreNode/StoreEdge) that mirror every + * persisted field of EngramNode/EngramEdge in el_runtime.c. M3 maps between the + * live runtime structs and these; M1 does not touch el_runtime.c. + * + * Format id: magic "ENGST01", format_version 1. This format is PERMANENT — the + * TLV record scheme means new fields never force a migration. + */ +#ifndef ENGRAM_STORE_H +#define ENGRAM_STORE_H + +#include +#include + +/* Fixed for the life of a store; recorded in the superblock. */ +#define STORE_PAGE_SIZE 16384u +#define STORE_MAGIC "ENGST01" /* 7 chars + NUL stored in an 8-byte field */ +#define STORE_FORMAT_VERSION 1u + +/* Ring-buffer length for ACT-R base-level access timestamps. + * MUST equal ENGRAM_BLL_K in el_runtime.c (currently 10). Static-checked in .c. */ +#define STORE_BLL_K 10 + +/* Page types (page header byte). */ +enum { + STORE_PT_NODE = 1, + STORE_PT_EDGE = 2, + STORE_PT_INDEX = 3, + STORE_PT_OVERFLOW = 4, + STORE_PT_FREE = 5 +}; + +/* store_check flags. */ +#define STORE_CHECK_CRC 1u + +/* ── Serializable node view: every persisted EngramNode field ─────────────── */ +typedef struct StoreNode { + char* id; + char* content; + char* node_type; + char* label; + char* tier; + char* tags; + char* metadata; + double salience; + double importance; + double confidence; + double temporal_decay_rate; + int64_t activation_count; + int64_t last_activated; + int64_t created_at; + int64_t updated_at; + double background_activation; + double working_memory_weight; + int32_t suppression_count; + uint32_t layer_id; + int64_t access_ts[STORE_BLL_K]; + int32_t access_head; + int32_t access_filled; + double wm_anchor; + float* emb; /* owned; NULL if not embedded */ + int32_t emb_dim; + /* Forward-compat: raw bytes of any TLV fields the reader did not recognise, + * concatenated verbatim ([tag][u32 len][bytes]...). Re-emitted on write so + * an old reader never drops a newer writer's fields. */ + uint8_t* unknown; + size_t unknown_len; + int tombstoned; /* set by store_get_* if the located record is dead */ + /* hebb_elig / hebb_elig_ts are DELIBERATELY NOT persisted (see EngramNode). */ +} StoreNode; + +/* ── Serializable edge view: every persisted EngramEdge field ─────────────── */ +typedef struct StoreEdge { + char* id; + char* from_id; + char* to_id; + char* relation; + char* metadata; + double weight; + double hebb; + double confidence; + int64_t created_at; + int64_t updated_at; + int64_t last_fired; + int32_t inhibitory; + uint32_t layer_id; + uint8_t* unknown; + size_t unknown_len; + int tombstoned; +} StoreEdge; + +typedef struct EngramPagedStore EngramPagedStore; + +/* Lifecycle. */ +EngramPagedStore* store_create(const char* path); /* fails if file exists */ +EngramPagedStore* store_open(const char* path); /* recovers via mirror SB */ +int store_close(EngramPagedStore* s); /* syncs + frees */ +int store_sync(EngramPagedStore* s); /* fsync + rewrite both superblocks */ + +/* Nodes. store_get_node returns 1 on hit (fills *out, caller store_node_free), + * 0 if absent or tombstoned, <0 on error. */ +int store_put_node(EngramPagedStore* s, const StoreNode* n); +int store_get_node(EngramPagedStore* s, const char* id, StoreNode* out); +int store_tombstone(EngramPagedStore* s, const char* id); + +/* Edges. *out is malloc'd (store_edges_free); *n set to count. */ +int store_put_edge(EngramPagedStore* s, const StoreEdge* e); +int store_get_edges_from(EngramPagedStore* s, const char* from_id, StoreEdge** out, size_t* n); +int store_get_edges_to(EngramPagedStore* s, const char* to_id, StoreEdge** out, size_t* n); + +/* Integrity: verify every page's crc (and both superblocks). Returns the number + * of corrupt pages (0 = clean), or <0 on I/O error. */ +int store_check(EngramPagedStore* s, unsigned flags); + +/* Ownership helpers. */ +void store_node_free(StoreNode* n); +void store_edge_free(StoreEdge* e); +void store_edges_free(StoreEdge* arr, size_t n); + +/* Test-only hook (NOT a format property — B+-tree nodes are self-describing via + * their stored key count). Caps entries/keys per index node to force splits on + * small datasets. 0 = natural full-page fanout. */ +void store__set_btree_order(EngramPagedStore* s, int leaf_max, int internal_max); + +/* Introspection for tests/tools. */ +uint64_t store_page_count(const EngramPagedStore* s); + +#endif /* ENGRAM_STORE_H */ From 8affb1d6e04c0b9cd59243e910ca65293c5ca0f9 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Tue, 11 Aug 2026 23:00:20 -0500 Subject: [PATCH 22/26] engram tiered storage M2: WAL + checkpoint + crash recovery + legacy import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Write-back no-steal buffer pool makes the fsync'd WAL load-bearing (M1 was write-through). Logical WAL with record-granularity page-LSN redo idempotency. Checkpoint = flush dirty pages, fsync store, advance last_checkpoint_lsn, reclaim WAL prefix. One-time snapshot.json import only when store absent; JSON never read as the ongoing store thereafter. Gates: 33/33 M1 (no regression) + 36/36 M2 — replay parity, torn-tail fuzz (every byte offset), checkpoint-crash at all 5 phases, torn-page+WAL redo, legacy-import parity, hebb-survives-crash. --- engram/test/run_wal_store_tests.sh | 14 + engram/test/test_wal_store.c | 466 +++++++++++++ lang/runtime/engram_store.c | 1000 +++++++++++++++++++++++++++- lang/runtime/engram_store.h | 75 +++ 4 files changed, 1542 insertions(+), 13 deletions(-) create mode 100755 engram/test/run_wal_store_tests.sh create mode 100644 engram/test/test_wal_store.c diff --git a/engram/test/run_wal_store_tests.sh b/engram/test/run_wal_store_tests.sh new file mode 100755 index 0000000..968b211 --- /dev/null +++ b/engram/test/run_wal_store_tests.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# M2 WAL + checkpoint + recovery gate. Pure C (NOT elb/elc). Writes only under /tmp. +# Recovery tests use ENGRAM_WAL_SYNC=always so every WAL record is durable at crash. +set -e +HERE="$(cd "$(dirname "$0")" && pwd)" +SRC="$HERE/../../lang/runtime/engram_store.c" +BIN="/tmp/test_wal_store.$$" +echo "compiling: gcc test_wal_store.c engram_store.c" +gcc -O2 -Wall -Wextra -std=c11 "$HERE/test_wal_store.c" "$SRC" -o "$BIN" +ENGRAM_WAL_SYNC=always "$BIN" +rc=$? +rm -f "$BIN" +rm -rf /tmp/engram-wal-test-* +exit $rc diff --git a/engram/test/test_wal_store.c b/engram/test/test_wal_store.c new file mode 100644 index 0000000..faae6f4 --- /dev/null +++ b/engram/test/test_wal_store.c @@ -0,0 +1,466 @@ +/* test_wal_store.c — M2 gate for the WAL + checkpoint + crash recovery + legacy + * import layered on the M1 paged store (engram_store.{c,h}). + * + * Pure C. Build: gcc -O2 test_wal_store.c ../../lang/runtime/engram_store.c -o t + * Writes ONLY under a throwaway /tmp dir. Never touches ~/.neuron or live ports. + * + * Covers §7/M2 gates: + * 1 replay parity — random op stream: normal-durable path == crash-recover path + * 2 torn-tail fuzz — truncate engram.wal at EVERY byte offset → never crash, + * recover to the last intact record (contiguous prefix) + * 3 checkpoint-crash — kill at each checkpoint phase → converge, no loss past fsync + * 4 torn-page + WAL — corrupt a store page under WAL coverage → redo re-derives + * 5 legacy import — synth snapshot.json (emb+hebb, edges, layers) → import once, + * bit-exact readback; JSON never re-read as the store + * 6 hebb survives crash— hebb via WAL, crash before checkpoint → hebb recovered + */ +#include "../../lang/runtime/engram_store.h" + +#include +#include +#include +#include +#include +#include +#include + +static int g_pass = 0, g_fail = 0; +static void ok(const char* name, int cond){ + printf(" [%s] %s\n", cond ? "PASS" : "FAIL", name); + if (cond) g_pass++; else g_fail++; +} + +static char g_base[512]; +static void mk_base(void){ + snprintf(g_base, sizeof g_base, "/tmp/engram-wal-test-%d", (int)getpid()); + mkdir(g_base, 0700); +} +static void mk_dir(const char* name, char* out, size_t cap){ + snprintf(out, cap, "%s/%s", g_base, name); + mkdir(out, 0700); +} + +/* deterministic RNG */ +static uint64_t xs(uint64_t* s){ uint64_t x=*s; x^=x<<13; x^=x>>7; x^=x<<17; *s=x; return x; } + +/* ── small node/edge generators (kept compact so WAL frames stay small) ─────── */ +static void gen_node(int i, int with_emb, StoreNode* n){ + memset(n, 0, sizeof *n); + uint64_t st = 0x1234ULL ^ ((uint64_t)(i+1)*0x9E3779B97F4A7C15ULL); + char id[32]; snprintf(id, sizeof id, "n%d", i); n->id = strdup(id); + char c[64]; snprintf(c, sizeof c, "content-of-node-%d-%llu", i, (unsigned long long)(xs(&st)%9999)); + n->content = strdup(c); + n->node_type = strdup("concept"); + n->tier = strdup("Working"); + n->salience = (double)(xs(&st)%100000)/7.0; + n->importance = (double)(xs(&st)%100000)/11.0; + n->confidence = (double)(xs(&st)%100000)/13.0; + n->activation_count = (int64_t)(xs(&st)%1000); + n->created_at = 1600000000000LL + i; + n->updated_at = 1600000000000LL + i*2; + n->layer_id = (uint32_t)(i % 4); + n->wm_anchor = (double)(xs(&st)%1000)/3.0; + if (with_emb){ + n->emb_dim = 32; + n->emb = (float*)malloc(sizeof(float)*n->emb_dim); + for (int k=0;kemb_dim;k++){ uint32_t u=(uint32_t)xs(&st); memcpy(&n->emb[k],&u,4); } + } +} +static void gen_edge(int i, const char* from, const char* to, StoreEdge* e){ + memset(e, 0, sizeof *e); + uint64_t st = 0xABCDULL ^ ((uint64_t)(i+1)*0xD1B54A32D192ED03ULL); + char id[32]; snprintf(id, sizeof id, "e%d", i); e->id = strdup(id); + e->from_id = strdup(from); e->to_id = strdup(to); + e->relation = strdup("relates_to"); + e->weight = (double)(xs(&st)%100000)/17.0; + e->hebb = (double)(xs(&st)%100000)/100000.0; + e->confidence = (double)(xs(&st)%100000)/19.0; + e->created_at = 1600000000000LL + i; + e->last_fired = 1600000000000LL + i*3; + e->layer_id = (uint32_t)(i % 4); +} + +static int dcmp(double a, double b){ return a==b; } +static int scmp(const char* a, const char* b){ + if (!a && !b) return 1; if (!a || !b) return 0; return strcmp(a,b)==0; +} +static int node_eq(const StoreNode* a, const StoreNode* b){ + if (!scmp(a->id,b->id) || !scmp(a->content,b->content) || !scmp(a->node_type,b->node_type) || + !scmp(a->tier,b->tier)) return 0; + if (!dcmp(a->salience,b->salience) || !dcmp(a->importance,b->importance) || + !dcmp(a->confidence,b->confidence) || a->activation_count!=b->activation_count || + a->created_at!=b->created_at || a->updated_at!=b->updated_at || + a->layer_id!=b->layer_id || !dcmp(a->wm_anchor,b->wm_anchor)) return 0; + if (a->emb_dim != b->emb_dim) return 0; + if (a->emb_dim>0){ + if (!a->emb || !b->emb) return 0; + if (memcmp(a->emb, b->emb, sizeof(float)*a->emb_dim)!=0) return 0; /* bit-exact */ + } + return 1; +} +static int edge_eq(const StoreEdge* a, const StoreEdge* b){ + return scmp(a->id,b->id) && scmp(a->from_id,b->from_id) && scmp(a->to_id,b->to_id) && + scmp(a->relation,b->relation) && dcmp(a->weight,b->weight) && dcmp(a->hebb,b->hebb) && + dcmp(a->confidence,b->confidence) && a->created_at==b->created_at && + a->last_fired==b->last_fired && a->layer_id==b->layer_id; +} + +/* whole-file read / write helpers (for torn-tail + torn-page fuzzing) */ +static uint8_t* read_file(const char* p, long* len){ + FILE* f=fopen(p,"rb"); if(!f) return NULL; + fseek(f,0,SEEK_END); long n=ftell(f); fseek(f,0,SEEK_SET); + uint8_t* b=malloc(n?n:1); if(fread(b,1,n,f)!=(size_t)n){ fclose(f); free(b); return NULL; } + fclose(f); *len=n; return b; +} +static void write_file(const char* p, const uint8_t* b, long len){ + FILE* f=fopen(p,"wb"); fwrite(b,1,len,f); fclose(f); +} + +/* ═══════════════════════════ TEST 1 — replay parity ═══════════════════════ */ +#define UNIV_NODES 60 +#define UNIV_EDGES 40 +static void test_replay_parity(void){ + printf("\n== replay parity: normal-durable path == crash-then-recover path ==\n"); + char da[600], db[600]; mk_dir("parityA", da, sizeof da); mk_dir("parityB", db, sizeof db); + EngramPagedStore* A = engram_open(da); + EngramPagedStore* B = engram_open(db); + ok("opened both stores", A && B); + if (!A || !B) return; + + uint64_t rng = 0xF00DFACEULL; + int OPS = 800; + for (int step=0; step0); + printf(" WAL bytes fuzzed=%ld full-recover offsets=%d\n", wlen, full_recovered); + free(sb); free(wb); +} + +/* ═══════════════════════════ TEST 3 — checkpoint-crash ═══════════════════════ */ +#define CK_NODES 30 +#define CK_EDGES 20 +static int build_and_crash_at_phase(const char* dir, int phase){ + EngramPagedStore* s = engram_open(dir); + if (!s) return -1; + for (int i=0;i=0); + if (victim>=0){ + for (int k=0;k<64;k++) sb[victim*16384 + 200 + k] ^= 0xA5; /* trash record area → bad crc */ + write_file(sp, sb, slen); + } + free(sb); + + EngramPagedStore* r = engram_open(dir); /* heal torn page + replay WAL */ + ok("reopened after page corruption", r!=NULL); + if (r){ + int miss=0; + for (int i=0;iemb_dim;k++) n->emb[k] = (float)((double)(xs(&es)%2000001)/1000000.0 - 1.0); } + fprintf(f, "%s{\"id\":\"%s\",\"content\":\"%s\",\"node_type\":\"%s\",\"tier\":\"%s\"," + "\"salience\":%.17g,\"importance\":%.17g,\"confidence\":%.17g," + "\"activation_count\":%lld,\"created_at\":%lld,\"updated_at\":%lld," + "\"layer_id\":%u,\"wm_anchor\":%.17g,\"emb\":\"", + i?",":"", n->id, n->content, n->node_type, n->tier, + n->salience, n->importance, n->confidence, + (long long)n->activation_count, (long long)n->created_at, (long long)n->updated_at, + n->layer_id, n->wm_anchor); + for (int k=0;kemb_dim;k++) fprintf(f, "%s%.9g", k?",":"", (double)n->emb[k]); /* exact float32 repr */ + fprintf(f, "\"}"); + } + fprintf(f, "],\"edges\":["); + for (int i=0;iid, e->from_id, e->to_id, e->relation, + e->weight, e->hebb, e->confidence, (long long)e->created_at, (long long)e->last_fired, e->layer_id); + } + fprintf(f, "],\"layers\":["); + fprintf(f, "{\"layer_id\":0,\"name\":\"SAFETY\",\"activation_priority\":9,\"suppressible\":0,\"transparent\":0,\"injectable\":0},"); + fprintf(f, "{\"layer_id\":1,\"name\":\"CORE_IDENTITY\",\"activation_priority\":8,\"suppressible\":0,\"transparent\":1,\"injectable\":1}"); + fprintf(f, "]}"); + fclose(f); + + EngramPagedStore* s = engram_open(dir); /* store absent + snapshot present → import */ + ok("engram_open imported the snapshot", s!=NULL); + char sp[700]; snprintf(sp,sizeof sp,"%s/engram.store",dir); struct stat st; + ok("engram.store created by import", stat(sp,&st)==0); + if (!s) return; + + int nmiss=0, embmiss=0; + for (int i=0;i0 && memcmp(got.emb,onodes[i].emb,sizeof(float)*got.emb_dim)!=0)) embmiss++; store_node_free(&got); } + } + int emiss=0, hebbmiss=0; + for (int i=0;iloc B+-tree root */ uint64_t adj_index_page; /* from/to adjacency B+-tree root */ uint64_t layer_registry_page; - uint64_t last_checkpoint_lsn; /* 0 in M1 (no checkpoints yet) */ + uint64_t last_checkpoint_lsn; /* store on disk reflects all ops with lsn<=this */ uint64_t sb_seq; uint8_t uuid[16]; - uint64_t next_lsn; + uint64_t next_lsn; /* monotonic LSN counter (WAL + page stamp share it) */ uint64_t cur_node_page; /* last NODE page with room, 0 = none */ uint64_t cur_edge_page; /* last EDGE page with room, 0 = none */ int leaf_max; /* test hook; 0 = natural */ int int_max; + /* ── M2 additions ─────────────────────────────────────────────────────── */ + PgCache* cache; /* write-back buffer pool (no-steal) */ + EngramWal* wal; /* attached WAL, or NULL (M1 direct mode) */ + uint64_t stamp_lsn; /* LSN to stamp on the next page_write (0 = auto) */ + int recovering; /* set during WAL replay */ + uint64_t ops_since_ckpt; /* checkpoint threshold counter */ + uint64_t ckpt_threshold; /* auto-checkpoint after this many ops (0 = never) */ }; +/* M2 buffer-pool hooks (defined in the M2 section at the bottom of this file). */ +typedef struct PgEnt { uint64_t id; uint8_t* buf; uint64_t lsn; int dirty; struct PgEnt* next; } PgEnt; +static PgCache* pc_new(void); +static void pc_free(PgCache* c); +static PgEnt* pc_get(EngramPagedStore* s, uint64_t id); +static int pc_put(EngramPagedStore* s, uint64_t id, const uint8_t* buf, int dirty); +static int pc_flush(EngramPagedStore* s); /* pwrite all dirty → clean */ + /* ── little-endian scalar codecs ──────────────────────────────────────────── */ static void put_u16(uint8_t* p, uint16_t v){ p[0]=(uint8_t)v; p[1]=(uint8_t)(v>>8); } static void put_u32(uint8_t* p, uint32_t v){ for(int i=0;i<4;i++) p[i]=(uint8_t)(v>>(8*i)); } @@ -172,10 +191,18 @@ static uint64_t id_hash(const char* s){ } /* ── raw page I/O ─────────────────────────────────────────────────────────── */ +/* Read a page: served from the write-back cache if resident, else from disk (and + * cached clean). This is the ONLY page-read path, so a dirty (not-yet-flushed) + * page is always observed with its in-RAM contents. */ static int page_read(EngramPagedStore* s, uint64_t id, uint8_t* buf){ + if (s->cache){ + PgEnt* e = pc_get(s, id); + if (e){ memcpy(buf, e->buf, STORE_PAGE_SIZE); return 0; } + } off_t off = (off_t)id * STORE_PAGE_SIZE; ssize_t r = pread(s->fd, buf, STORE_PAGE_SIZE, off); if (r != (ssize_t)STORE_PAGE_SIZE) return -1; + if (s->cache) pc_put(s, id, buf, 0); /* cache clean */ return 0; } static int page_write_raw(EngramPagedStore* s, uint64_t id, const uint8_t* buf){ @@ -184,14 +211,19 @@ static int page_write_raw(EngramPagedStore* s, uint64_t id, const uint8_t* buf){ if (w != (ssize_t)STORE_PAGE_SIZE) return -1; return 0; } -/* Stamp lsn + crc into a generic page header, then write. */ +/* Stamp page_id + lsn + crc into the generic header, then write BACK to the cache + * (dirty). No-steal: the page reaches disk only at the next checkpoint. The stamped + * LSN is the current op's WAL LSN (s->stamp_lsn) when set, else a fresh counter + * value — this is the page LSN used for ARIES-style redo idempotency. */ static int page_write(EngramPagedStore* s, uint64_t id, uint8_t* buf){ put_u64(buf + 0, id); - put_u64(buf + 16, ++s->next_lsn); + uint64_t lsn = s->stamp_lsn ? s->stamp_lsn : ++s->next_lsn; + put_u64(buf + 16, lsn); put_u32(buf + 24, 0); uint32_t crc = crc32_buf(buf, STORE_PAGE_SIZE); put_u32(buf + 24, crc); - return page_write_raw(s, id, buf); + if (s->cache) return pc_put(s, id, buf, 1); + return page_write_raw(s, id, buf); /* pre-cache bootstrap (should not happen) */ } static int page_crc_ok(const uint8_t* buf){ uint8_t tmp[STORE_PAGE_SIZE]; @@ -741,6 +773,10 @@ static void sb_apply(EngramPagedStore* s, const uint8_t* buf){ int store_sync(EngramPagedStore* s){ if (!s) return -1; + /* flush the write-back cache so the store file reflects the SB we are about + * to stamp (this is the checkpoint page-flush + fsync). */ + if (pc_flush(s) != 0) return -1; + if (fsync(s->fd) != 0) return -1; s->sb_seq++; /* write primary, fsync, then mirror, fsync — so a torn write of one leaves * the other valid; recovery prefers the higher valid sb_seq. */ @@ -778,6 +814,8 @@ EngramPagedStore* store_create(const char* path){ if (!s) return NULL; s->fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); if (s->fd < 0){ free(s); return NULL; } + s->cache = pc_new(); + if (!s->cache){ close(s->fd); free(s); return NULL; } snprintf(s->path, sizeof s->path, "%s", path); s->format_version = STORE_FORMAT_VERSION; s->page_size = STORE_PAGE_SIZE; @@ -805,6 +843,8 @@ EngramPagedStore* store_open(const char* path){ if (!s) return NULL; s->fd = open(path, O_RDWR); if (s->fd < 0){ free(s); return NULL; } + s->cache = pc_new(); + if (!s->cache){ close(s->fd); free(s); return NULL; } snprintf(s->path, sizeof s->path, "%s", path); uint8_t b0[STORE_PAGE_SIZE], b1[STORE_PAGE_SIZE]; uint64_t s0 = 0, s1 = 0; @@ -816,15 +856,22 @@ EngramPagedStore* store_open(const char* path){ else pick = ok0 ? b0 : b1; sb_apply(s, pick); if (s->page_size != STORE_PAGE_SIZE){ close(s->fd); free(s); return NULL; } - s->next_lsn = s->sb_seq; /* resume LSNs above the last synced value */ + /* resume the LSN counter above both the last checkpoint and the SB seq (M1 + * stores have last_checkpoint_lsn==0 → falls back to sb_seq as before). */ + s->next_lsn = (s->last_checkpoint_lsn > s->sb_seq) ? s->last_checkpoint_lsn : s->sb_seq; s->cur_node_page = 0; s->cur_edge_page = 0; return s; } +/* wal_close is defined in the M2 section. */ +static void wal_close(EngramWal* w); + int store_close(EngramPagedStore* s){ if (!s) return -1; int rc = store_sync(s); + if (s->wal){ wal_close(s->wal); s->wal = NULL; } + if (s->cache){ pc_free(s->cache); s->cache = NULL; } if (s->fd >= 0) close(s->fd); free(s); return rc; @@ -880,7 +927,9 @@ static int place_record(EngramPagedStore* s, uint8_t ptype, const uint8_t* rec, return 0; } -int store_put_node(EngramPagedStore* s, const StoreNode* n){ +/* Pure record placement + indexing (no LSN/WAL/idempotency). Pages are stamped + * with s->stamp_lsn by page_write. Used by both the M1-direct and M2-WAL paths. */ +static int node_place(EngramPagedStore* s, const StoreNode* n){ if (!s || !n || !n->id) return -1; size_t blen; uint8_t* body = node_serialize(n, &blen); if (!body) return -1; @@ -895,7 +944,7 @@ int store_put_node(EngramPagedStore* s, const StoreNode* n){ return btree_put(s, TREE_PRIMARY, id_hash(n->id), payload); } -int store_put_edge(EngramPagedStore* s, const StoreEdge* e){ +static int edge_place(EngramPagedStore* s, const StoreEdge* e){ if (!s || !e || !e->id || !e->from_id || !e->to_id) return -1; size_t blen; uint8_t* body = edge_serialize(e, &blen); if (!body) return -1; @@ -967,16 +1016,21 @@ int store_get_node(EngramPagedStore* s, const char* id, StoreNode* out){ return found ? 1 : 0; } -int store_tombstone(EngramPagedStore* s, const char* id){ +/* Tombstone the live record(s) for `id`, but only where the record's home page + * LSN < `lsn` (ARIES redo idempotency: a replayed tombstone whose effect is + * already on the page is skipped). Stamps killed pages with `lsn`. */ +static int tombstone_core(EngramPagedStore* s, const char* id, uint64_t lsn){ if (!s || !id) return -1; uint8_t* locs; size_t n; if (btree_lookup(s, TREE_PRIMARY, id_hash(id), &locs, &n)!=0) return -1; - int hit = 0; + uint64_t prev_stamp = s->stamp_lsn; + s->stamp_lsn = lsn; for (size_t i=0;i= lsn) continue; /* already covered by >= this LSN */ if (slot >= slp_count(buf)) continue; uint16_t off,len,fl; slp_slot(buf, slot, &off, &len, &fl); if (fl != SLOT_LIVE) continue; @@ -988,8 +1042,7 @@ int store_tombstone(EngramPagedStore* s, const char* id){ store_node_free(&cand); if (!match) continue; slp_set_slot(buf, slot, off, len, SLOT_DEAD); - if (page_write(s, page, buf)!=0){ free(locs); return -1; } - hit = 1; + if (page_write(s, page, buf)!=0){ s->stamp_lsn = prev_stamp; free(locs); return -1; } /* if the page is now empty, reclaim it to the free list */ if (page_read(s, page, buf)==0 && slp_live_count(buf)==0){ if (s->cur_node_page == page) s->cur_node_page = 0; @@ -997,8 +1050,9 @@ int store_tombstone(EngramPagedStore* s, const char* id){ page_free(s, page); } } + s->stamp_lsn = prev_stamp; free(locs); - return hit ? 0 : 0; /* absent id is a no-op success */ + return 0; /* absent id is a no-op success */ } static int get_edges_dir(EngramPagedStore* s, const char* id, uint8_t want_dir, @@ -1082,3 +1136,923 @@ void store__set_btree_order(EngramPagedStore* s, int leaf_max, int internal_max) s->leaf_max = leaf_max; s->int_max = internal_max; } uint64_t store_page_count(const EngramPagedStore* s){ return s ? s->page_count : 0; } + +/* ══════════════════════════════════════════════════════════════════════════════ + * M2 — WAL + write-back buffer pool + checkpoint + crash recovery + legacy import + * + * Durability model (design §2.2/§4, ARIES-lite): + * • Buffer pool is WRITE-BACK, no-steal: a mutation dirties a page in RAM; the + * page reaches engram.store ONLY at a checkpoint. So after a crash the store + * file reflects exactly `last_checkpoint_lsn`, and everything since lives in + * the WAL. This is what makes the WAL load-bearing (durability = fsync'd WAL, + * not the page). + * • Each mutation: assign LSN → append WAL record (fsync per policy) → apply to + * the page(s), stamping page-LSN = record LSN. + * • Recovery: open store (at checkpoint), heal torn data pages, replay WAL + * forward; a record is REDONE only where the target record's home-page LSN is + * < the record LSN (idempotent — safe to replay any number of times, and safe + * across torn checkpoints where some dirty pages reached disk). + * + * DELTA vs the design sketch (flagged, becoming permanent): the WAL is LOGICAL + * (op + node/edge/layer payload), not physical page images, so the "redo only if + * rec.lsn > page.lsn" test is applied at RECORD granularity — against the LSN of + * the page currently holding the record for that id — rather than against a + * single physical target page. Records are never relocated once placed, so a + * record placed by op L keeps its page (whose LSN only rises), making + * "page-LSN ≥ L ⇒ op L already durable" a sound, precise idempotency test. + * ════════════════════════════════════════════════════════════════════════════ */ + +#include + +/* ── write-back buffer pool ────────────────────────────────────────────────── */ +struct PgCache { PgEnt** buckets; size_t nbuckets; size_t count; }; + +static PgCache* pc_new(void){ + PgCache* c = (PgCache*)calloc(1, sizeof *c); + if (!c) return NULL; + c->nbuckets = 1024; + c->buckets = (PgEnt**)calloc(c->nbuckets, sizeof(PgEnt*)); + if (!c->buckets){ free(c); return NULL; } + return c; +} +static void pc_free(PgCache* c){ + if (!c) return; + for (size_t i=0;inbuckets;i++){ + PgEnt* e = c->buckets[i]; + while (e){ PgEnt* n=e->next; free(e->buf); free(e); e=n; } + } + free(c->buckets); free(c); +} +static PgEnt* pc_get(EngramPagedStore* s, uint64_t id){ + PgCache* c = s->cache; + PgEnt* e = c->buckets[id % c->nbuckets]; + while (e){ if (e->id==id) return e; e=e->next; } + return NULL; +} +static void pc_maybe_grow(PgCache* c){ + if (c->count <= c->nbuckets*4) return; + size_t nn = c->nbuckets*2; + PgEnt** nb = (PgEnt**)calloc(nn, sizeof(PgEnt*)); + if (!nb) return; + for (size_t i=0;inbuckets;i++){ + PgEnt* e = c->buckets[i]; + while (e){ PgEnt* nx=e->next; size_t b=e->id%nn; e->next=nb[b]; nb[b]=e; e=nx; } + } + free(c->buckets); c->buckets=nb; c->nbuckets=nn; +} +static int pc_put(EngramPagedStore* s, uint64_t id, const uint8_t* buf, int dirty){ + PgCache* c = s->cache; + PgEnt* e = pc_get(s, id); + if (!e){ + e = (PgEnt*)calloc(1, sizeof *e); + if (!e) return -1; + e->buf = (uint8_t*)malloc(STORE_PAGE_SIZE); + if (!e->buf){ free(e); return -1; } + e->id = id; + size_t b = id % c->nbuckets; + e->next = c->buckets[b]; c->buckets[b] = e; c->count++; + pc_maybe_grow(c); + } + memcpy(e->buf, buf, STORE_PAGE_SIZE); + e->lsn = get_u64(buf + 16); + if (dirty) e->dirty = 1; + return 0; +} +static int pc_flush(EngramPagedStore* s){ + if (!s->cache) return 0; + PgCache* c = s->cache; + for (size_t i=0;inbuckets;i++) + for (PgEnt* e=c->buckets[i]; e; e=e->next) + if (e->dirty){ if (page_write_raw(s, e->id, e->buf)!=0) return -1; e->dirty=0; } + return 0; +} +/* ── WAL log ───────────────────────────────────────────────────────────────── */ +enum { OP_NODE_PUT=1, OP_EDGE_PUT, OP_TOMBSTONE, OP_SUPERSEDE, + OP_LAYER_PUT, OP_LAYER_DEL, OP_FORGET, OP_HEBB_BATCH, OP_CHECKPOINT }; + +#define WAL_MAGIC 0x314C5745u /* 'E''W''L''1' little-endian */ +#define WAL_HDR 22u /* magic4 len4 op1 flags1 lsn8 crc4 */ + +struct EngramWal { + int fd; + char path[1024]; + EngramWalSync sync; + uint64_t last_fsync_lsn; + long long last_fsync_ms; + uint64_t appended_since_fsync; +}; + +static long long now_ms(void){ + struct timeval tv; gettimeofday(&tv, NULL); + return (long long)tv.tv_sec*1000 + tv.tv_usec/1000; +} +static EngramWal* wal_open(const char* path, EngramWalSync sync){ + EngramWal* w = (EngramWal*)calloc(1, sizeof *w); + if (!w) return NULL; + w->fd = open(path, O_RDWR | O_CREAT | O_APPEND, 0600); + if (w->fd < 0){ free(w); return NULL; } + snprintf(w->path, sizeof w->path, "%s", path); + w->sync = sync; w->last_fsync_ms = now_ms(); + return w; +} +static void wal_close(EngramWal* w){ + if (!w) return; + if (w->fd >= 0){ fsync(w->fd); close(w->fd); } + free(w); +} +static void wal_maybe_fsync(EngramPagedStore* s, uint64_t lsn){ + EngramWal* w = s->wal; if (!w) return; + if (w->sync == ENGRAM_WAL_OFF) return; + if (w->sync == ENGRAM_WAL_ALWAYS){ + fsync(w->fd); w->last_fsync_lsn=lsn; w->last_fsync_ms=now_ms(); w->appended_since_fsync=0; return; + } + /* GROUP: fsync at most every ~50 ms or every 256 records. */ + long long now = now_ms(); + if (now - w->last_fsync_ms >= 50 || w->appended_since_fsync >= 256){ + fsync(w->fd); w->last_fsync_lsn=lsn; w->last_fsync_ms=now; w->appended_since_fsync=0; + } +} +static int wal_append(EngramPagedStore* s, uint8_t op, const uint8_t* payload, + uint32_t plen, uint64_t lsn){ + EngramWal* w = s->wal; if (!w) return 0; + size_t fl = WAL_HDR + plen; + uint8_t* fr = (uint8_t*)malloc(fl); + if (!fr) return -1; + put_u32(fr + 0, WAL_MAGIC); + put_u32(fr + 4, plen); + fr[8] = op; fr[9] = 0; + put_u64(fr + 10, lsn); + put_u32(fr + 18, 0); + if (plen) memcpy(fr + WAL_HDR, payload, plen); + /* crc over op|flags|lsn|payload — these are NOT contiguous in the frame (the + * crc field sits between), so hash a scratch copy that omits it. */ + uint8_t* cb = (uint8_t*)malloc(10 + plen); + if (!cb){ free(fr); return -1; } + memcpy(cb, fr + 8, 10); + if (plen) memcpy(cb + 10, payload, plen); + uint32_t crc = crc32_buf(cb, 10 + plen); + free(cb); + put_u32(fr + 18, crc); + ssize_t wr = write(w->fd, fr, fl); + free(fr); + if (wr != (ssize_t)fl) return -1; + w->appended_since_fsync++; + wal_maybe_fsync(s, lsn); + return 0; +} +static int wal_reclaim(EngramPagedStore* s, uint64_t ckpt_lsn){ + EngramWal* w = s->wal; if (!w) return 0; + if (ftruncate(w->fd, 0) != 0) return -1; /* prefix <= ckpt reclaimed */ + uint8_t p[8]; put_u64(p, ckpt_lsn); + if (wal_append(s, OP_CHECKPOINT, p, 8, ckpt_lsn) != 0) return -1; + fsync(w->fd); w->last_fsync_ms = now_ms(); + return 0; +} + +/* ── idempotency: max home-page LSN of the live/dead record(s) for `id` ──────── */ +static uint64_t max_page_lsn_for_id(EngramPagedStore* s, const char* id, int want_edge){ + uint8_t* locs; size_t n; + if (btree_lookup(s, TREE_PRIMARY, id_hash(id), &locs, &n) != 0) return 0; + uint64_t best = 0; + for (size_t i=0;i best) best = l; + } + free(locs); + return best; +} + +/* Mark live record(s) for `id` DEAD where the home page LSN < lsn. `want_edge` + * disambiguates node vs edge records (page type). Caller sets s->stamp_lsn. */ +static void kill_live_id(EngramPagedStore* s, const char* id, int want_edge, uint64_t lsn){ + uint8_t* locs; size_t n; + if (btree_lookup(s, TREE_PRIMARY, id_hash(id), &locs, &n) != 0) return; + for (size_t i=0;i= lsn) continue; + if (buf[8] != (want_edge ? STORE_PT_EDGE : STORE_PT_NODE)) continue; + if (slot >= slp_count(buf)) continue; + uint16_t off,len,fl; slp_slot(buf, slot, &off, &len, &fl); + if (fl != SLOT_LIVE) continue; + uint8_t* body; size_t blen; int live; + if (read_body(s, page, slot, &body, &blen, &live) != 0) continue; + int match; + if (want_edge){ StoreEdge e; edge_parse(body,blen,&e); match = e.id && !strcmp(e.id,id); store_edge_free(&e); } + else { StoreNode nn; node_parse(body,blen,&nn); match = nn.id && !strcmp(nn.id,id); store_node_free(&nn); } + free(body); + if (!match) continue; + slp_set_slot(buf, slot, off, len, SLOT_DEAD); + page_write(s, page, buf); + } + free(locs); +} + +/* ── apply routines (used by both the normal write path and WAL replay) ──────── */ +static int apply_node_put(EngramPagedStore* s, const StoreNode* n, uint64_t lsn){ + if (!s || !n || !n->id) return -1; + if (max_page_lsn_for_id(s, n->id, 0) >= lsn) return 0; /* already durable */ + uint64_t prev = s->stamp_lsn; s->stamp_lsn = lsn; + int r = node_place(s, n); /* re-put appends; reads dedup */ + s->stamp_lsn = prev; + return r; +} +static int apply_edge_put(EngramPagedStore* s, const StoreEdge* e, uint64_t lsn){ + if (!s || !e || !e->id || !e->from_id || !e->to_id) return -1; + if (max_page_lsn_for_id(s, e->id, 1) >= lsn) return 0; /* already durable */ + uint64_t prev = s->stamp_lsn; s->stamp_lsn = lsn; + kill_live_id(s, e->id, 1, lsn); /* supersede prior versions (no adjacency dup) */ + int r = edge_place(s, e); + s->stamp_lsn = prev; + return r; +} + +/* ── layer registry (single slotted page rooted at layer_registry_page) ──────── */ +enum { LT_ID=1, LT_NAME, LT_PRIO, LT_SUPPRESS, LT_TRANSPARENT, LT_INJECTABLE }; + +static uint8_t* layer_serialize(const StoreLayer* L, size_t* out_len){ + Buf b = {0,0,0}; + tlv_u32(&b, LT_ID, L->layer_id); + tlv_str(&b, LT_NAME, L->name); + tlv_u32(&b, LT_PRIO, L->activation_priority); + tlv_i32(&b, LT_SUPPRESS, L->suppressible); + tlv_i32(&b, LT_TRANSPARENT, L->transparent); + tlv_i32(&b, LT_INJECTABLE, L->injectable); + if (L->unknown && L->unknown_len) buf_raw(&b, L->unknown, L->unknown_len); + *out_len = b.len; return b.p; +} +static void layer_parse(const uint8_t* body, size_t len, StoreLayer* L){ + memset(L, 0, sizeof *L); + Buf unk = {0,0,0}; + size_t i = 0; + while (i + 5 <= len){ + uint8_t tag = body[i]; uint32_t flen = get_u32(body+i+1); + if (i + 5 + flen > len) break; + const uint8_t* v = body + i + 5; + switch (tag){ + case LT_ID: L->layer_id = get_u32(v); break; + case LT_NAME: L->name = dup_str(v, flen); break; + case LT_PRIO: L->activation_priority = get_u32(v); break; + case LT_SUPPRESS: L->suppressible = (int32_t)get_u32(v); break; + case LT_TRANSPARENT: L->transparent = (int32_t)get_u32(v); break; + case LT_INJECTABLE: L->injectable = (int32_t)get_u32(v); break; + default: buf_raw(&unk, body+i, 5+flen); break; + } + i += 5 + flen; + } + L->unknown = unk.p; L->unknown_len = unk.len; +} +void store_layer_free(StoreLayer* L){ + if (!L) return; free(L->name); free(L->unknown); memset(L, 0, sizeof *L); +} +void store_layers_free(StoreLayer* arr, size_t n){ + if (!arr) return; for (size_t i=0;ilayer_registry_page; + uint8_t buf[STORE_PAGE_SIZE]; + if (page_read(s, pg, buf) != 0) return -1; + /* already-applied? a live record with this layer_id and page LSN >= lsn. */ + if (get_u64(buf + 16) >= lsn){ + int nslot = slp_count(buf); + for (int i=0;ilayer_id); store_layer_free(&c); + if (hit) return 0; + } + } + uint64_t prev = s->stamp_lsn; s->stamp_lsn = lsn; + /* supersede prior live record(s) with this layer_id */ + int nslot = slp_count(buf); + for (int i=0;ilayer_id); store_layer_free(&c); + if (hit) slp_set_slot(buf, i, off, len, SLOT_DEAD); + } + /* append new layer record */ + size_t blen; uint8_t* body = layer_serialize(L, &blen); + if (!body){ s->stamp_lsn=prev; return -1; } + uint16_t reclen = (uint16_t)(REC_HDR + blen); + uint8_t* rec = (uint8_t*)malloc(reclen); + if (!rec){ free(body); s->stamp_lsn=prev; return -1; } + put_u16(rec, reclen); rec[2]=REC_VER; rec[3]=0; + memcpy(rec + REC_HDR, body, blen); free(body); + int slot = slp_put(buf, rec, reclen); free(rec); + if (slot < 0){ s->stamp_lsn=prev; return -1; } /* registry page full (M2: single page) */ + int rc = page_write(s, pg, buf); + s->stamp_lsn = prev; + return rc; +} +static int apply_layer_del(EngramPagedStore* s, uint32_t layer_id, uint64_t lsn){ + uint64_t pg = s->layer_registry_page; + uint8_t buf[STORE_PAGE_SIZE]; + if (page_read(s, pg, buf) != 0) return -1; + if (get_u64(buf + 16) >= lsn) return 0; + uint64_t prev = s->stamp_lsn; s->stamp_lsn = lsn; + int nslot = slp_count(buf), changed=0; + for (int i=0;istamp_lsn = prev; + return rc; +} +int store_get_layer(EngramPagedStore* s, uint32_t layer_id, StoreLayer* out){ + if (!s || !out) return -1; + uint8_t buf[STORE_PAGE_SIZE]; + if (page_read(s, s->layer_registry_page, buf) != 0) return -1; + int nslot = slp_count(buf), found=0; + for (int i=0;ilayer_registry_page, buf) != 0) return -1; + StoreLayer* arr=NULL; size_t used=0, cap=0; + int nslot = slp_count(buf); + for (int i=0;itombstoned = 0; found = 1; + } else store_edge_free(&cand); + } + free(locs); + return found ? 1 : 0; +} + +/* ── hebb batch apply ──────────────────────────────────────────────────────── + * payload: [u32 count] then count × [u32 id_len][id][f64 hebb][i64 last_fired]. */ +static int apply_hebb_batch(EngramPagedStore* s, const uint8_t* p, uint32_t plen, uint64_t lsn){ + if (plen < 4) return -1; + uint32_t cnt = get_u32(p); size_t off = 4; + for (uint32_t i=0;i plen) break; + uint32_t idl = get_u32(p+off); off += 4; + if (off + idl + 16 > plen) break; + char* id = dup_str(p+off, idl); off += idl; + double hebb; { uint64_t u=get_u64(p+off); memcpy(&hebb,&u,8);} off += 8; + int64_t lf = (int64_t)get_u64(p+off); off += 8; + if (id){ + StoreEdge e; + if (store_get_edge(s, id, &e) == 1){ + e.hebb = hebb; e.last_fired = lf; + apply_edge_put(s, &e, lsn); + store_edge_free(&e); + } + free(id); + } + } + return 0; +} + +/* ── WAL replay dispatch ─────────────────────────────────────────────────────── */ +static void wal_dispatch(EngramPagedStore* s, uint8_t op, const uint8_t* p, uint32_t plen, uint64_t lsn){ + switch (op){ + case OP_NODE_PUT: { StoreNode n; node_parse(p,plen,&n); apply_node_put(s,&n,lsn); store_node_free(&n); break; } + case OP_EDGE_PUT: { StoreEdge e; edge_parse(p,plen,&e); apply_edge_put(s,&e,lsn); store_edge_free(&e); break; } + case OP_TOMBSTONE: + case OP_FORGET: { char* id=dup_str(p,plen); if(id){ tombstone_core(s,id,lsn); free(id);} break; } + case OP_SUPERSEDE:{ if(plen>=4){ uint32_t ol=get_u32(p); if(4+ol<=plen){ char* old=dup_str(p+4,ol); if(old){ tombstone_core(s,old,lsn); free(old);} } } break; } + case OP_LAYER_PUT:{ StoreLayer L; layer_parse(p,plen,&L); apply_layer_put(s,&L,lsn); store_layer_free(&L); break; } + case OP_LAYER_DEL:{ if(plen>=4) apply_layer_del(s, get_u32(p), lsn); break; } + case OP_HEBB_BATCH: apply_hebb_batch(s, p, plen, lsn); break; + case OP_CHECKPOINT: break; + default: break; + } +} +static int wal_replay(EngramPagedStore* s){ + EngramWal* w = s->wal; if (!w) return 0; + struct stat st; if (fstat(w->fd, &st) != 0) return -1; + off_t size = st.st_size, off = 0; + uint64_t maxlsn = 0; + for (;;){ + if (off + (off_t)WAL_HDR > size) break; /* torn/short tail */ + uint8_t hdr[WAL_HDR]; + if (pread(w->fd, hdr, WAL_HDR, off) != (ssize_t)WAL_HDR) break; + if (get_u32(hdr) != WAL_MAGIC) break; + uint32_t plen = get_u32(hdr + 4); + if (off + (off_t)WAL_HDR + plen > size) break; /* torn tail */ + uint32_t crc_stored = get_u32(hdr + 18); + uint8_t* fr = (uint8_t*)malloc(10 + plen); + if (!fr) return -1; + memcpy(fr, hdr + 8, 10); /* op|flags|lsn */ + if (plen && pread(w->fd, fr+10, plen, off+WAL_HDR) != (ssize_t)plen){ free(fr); break; } + if (crc32_buf(fr, 10+plen) != crc_stored){ free(fr); break; } /* bad crc → stop */ + uint8_t op = fr[0]; uint64_t lsn = get_u64(fr+2); + if (lsn > maxlsn) maxlsn = lsn; + if (lsn > s->last_checkpoint_lsn) wal_dispatch(s, op, fr+10, plen, lsn); + free(fr); + off += (off_t)WAL_HDR + plen; + } + if (maxlsn > s->next_lsn) s->next_lsn = maxlsn; + return 0; +} + +/* Heal torn DATA pages (bad crc) to empty pages of their type, so redo re-derives + * their records from the WAL. Index/superblock recovery uses the SB mirror + full + * replay-from-checkpoint; torn index pages are left for store_check to report. */ +static void heal_torn_pages(EngramPagedStore* s){ + /* Scan by the ACTUAL file size, not the SB page_count: a steal (dirty pages + * flushed without advancing the checkpoint SB) can leave valid/torn pages + * beyond the recorded page_count. Bump page_count so redo allocations never + * collide with those on-disk ghost pages. */ + struct stat fst; + uint64_t file_pages = (fstat(s->fd,&fst)==0) ? (uint64_t)(fst.st_size/STORE_PAGE_SIZE) : s->page_count; + if (file_pages > s->page_count) s->page_count = file_pages; + for (uint64_t id=2; idfd, buf, STORE_PAGE_SIZE, off) != (ssize_t)STORE_PAGE_SIZE) continue; + if (page_crc_ok(buf)) continue; + uint8_t t = buf[8]; + uint8_t nb[STORE_PAGE_SIZE]; memset(nb, 0, sizeof nb); + if (t==STORE_PT_NODE || t==STORE_PT_EDGE){ + nb[8]=t; put_u16(nb+10,0); put_u16(nb+12,(uint16_t)(STORE_PAGE_SIZE-STORE_HDR)); + } else if (t==STORE_PT_OVERFLOW){ + nb[8]=t; put_u64(nb+OVF_NEXT_OFF,0); put_u32(nb+OVF_LEN_OFF,0); + } else continue; /* don't heal index/free/garbage */ + put_u64(nb+0, id); put_u64(nb+16, 0); put_u32(nb+24, 0); + put_u32(nb+24, crc32_buf(nb, STORE_PAGE_SIZE)); + pc_put(s, id, nb, 1); /* dirty → persisted next checkpoint */ + } +} +static int wal_recover(EngramPagedStore* s){ + s->recovering = 1; + heal_torn_pages(s); + int rc = wal_replay(s); + s->recovering = 0; + return rc; +} + +/* ── checkpoint threshold trigger ────────────────────────────────────────────── */ +static void ckpt_maybe(EngramPagedStore* s){ + if (s->recovering) return; + s->ops_since_ckpt++; + if (s->ckpt_threshold && s->ops_since_ckpt >= s->ckpt_threshold) + engram_checkpoint(s); +} + +/* ── public mutation entry points (log-then-apply when a WAL is attached) ─────── */ +int store_put_node(EngramPagedStore* s, const StoreNode* n){ + if (!s || !n || !n->id) return -1; + uint64_t L = ++s->next_lsn; + if (s->wal){ + size_t blen; uint8_t* body = node_serialize(n, &blen); + if (!body) return -1; + int wr = wal_append(s, OP_NODE_PUT, body, (uint32_t)blen, L); + free(body); + if (wr != 0) return -1; + } + int r = apply_node_put(s, n, L); + ckpt_maybe(s); + return r; +} +int store_put_edge(EngramPagedStore* s, const StoreEdge* e){ + if (!s || !e || !e->id || !e->from_id || !e->to_id) return -1; + uint64_t L = ++s->next_lsn; + if (s->wal){ + size_t blen; uint8_t* body = edge_serialize(e, &blen); + if (!body) return -1; + int wr = wal_append(s, OP_EDGE_PUT, body, (uint32_t)blen, L); + free(body); + if (wr != 0) return -1; + } + int r = apply_edge_put(s, e, L); + ckpt_maybe(s); + return r; +} +int store_tombstone(EngramPagedStore* s, const char* id){ + if (!s || !id) return -1; + uint64_t L = ++s->next_lsn; + if (s->wal){ + if (wal_append(s, OP_TOMBSTONE, (const uint8_t*)id, (uint32_t)strlen(id), L) != 0) return -1; + } + int r = tombstone_core(s, id, L); + ckpt_maybe(s); + return r; +} +int store_forget(EngramPagedStore* s, const char* id){ + if (!s || !id) return -1; + uint64_t L = ++s->next_lsn; + if (s->wal){ + if (wal_append(s, OP_FORGET, (const uint8_t*)id, (uint32_t)strlen(id), L) != 0) return -1; + } + int r = tombstone_core(s, id, L); + ckpt_maybe(s); + return r; +} +int store_supersede(EngramPagedStore* s, const char* old_id, const char* new_id){ + if (!s || !old_id) return -1; + uint64_t L = ++s->next_lsn; + if (s->wal){ + uint32_t ol=(uint32_t)strlen(old_id), nl=(uint32_t)(new_id?strlen(new_id):0); + size_t plen = 4+ol+4+nl; + uint8_t* p = (uint8_t*)malloc(plen); + if (!p) return -1; + put_u32(p, ol); memcpy(p+4, old_id, ol); + put_u32(p+4+ol, nl); if (nl) memcpy(p+8+ol, new_id, nl); + int wr = wal_append(s, OP_SUPERSEDE, p, (uint32_t)plen, L); + free(p); + if (wr != 0) return -1; + } + int r = tombstone_core(s, old_id, L); + ckpt_maybe(s); + return r; +} +int store_put_layer(EngramPagedStore* s, const StoreLayer* L){ + if (!s || !L) return -1; + uint64_t lsn = ++s->next_lsn; + if (s->wal){ + size_t blen; uint8_t* body = layer_serialize(L, &blen); + if (!body) return -1; + int wr = wal_append(s, OP_LAYER_PUT, body, (uint32_t)blen, lsn); + free(body); + if (wr != 0) return -1; + } + int r = apply_layer_put(s, L, lsn); + ckpt_maybe(s); + return r; +} +int store_del_layer(EngramPagedStore* s, uint32_t layer_id){ + if (!s) return -1; + uint64_t lsn = ++s->next_lsn; + if (s->wal){ + uint8_t p[4]; put_u32(p, layer_id); + if (wal_append(s, OP_LAYER_DEL, p, 4, lsn) != 0) return -1; + } + int r = apply_layer_del(s, layer_id, lsn); + ckpt_maybe(s); + return r; +} +int store_hebb_batch(EngramPagedStore* s, const StoreHebbDelta* d, size_t n){ + if (!s || (!d && n)) return -1; + uint64_t L = ++s->next_lsn; + /* build payload */ + Buf b = {0,0,0}; + { uint8_t c[4]; put_u32(c, (uint32_t)n); buf_raw(&b, c, 4); } + for (size_t i=0;iwal){ + if (wal_append(s, OP_HEBB_BATCH, b.p, (uint32_t)b.len, L) != 0){ free(b.p); return -1; } + } + int r = apply_hebb_batch(s, b.p, (uint32_t)b.len, L); + free(b.p); + ckpt_maybe(s); + return r; +} + +/* ── checkpoint (with test-only crash injection at each step) ─────────────────── */ +int store__checkpoint_crashat(EngramPagedStore* s, int phase){ + if (!s) return -1; + if (phase == 0){ store__crash(s); return 0; } + if (pc_flush(s) != 0) return -1; /* 1: dirty pages → disk */ + if (phase == 1){ store__crash(s); return 0; } + if (fsync(s->fd) != 0) return -1; /* 2: fsync store */ + if (phase == 2){ store__crash(s); return 0; } + uint64_t C = s->next_lsn; /* 3: advance ckpt LSN + SB */ + s->last_checkpoint_lsn = C; + s->sb_seq++; + if (sb_write_one(s, 0) != 0) return -1; + if (fsync(s->fd) != 0) return -1; + if (sb_write_one(s, 1) != 0) return -1; + if (fsync(s->fd) != 0) return -1; + if (phase == 3){ store__crash(s); return 0; } + if (wal_reclaim(s, C) != 0) return -1; /* 4: reclaim WAL prefix */ + s->ops_since_ckpt = 0; + if (phase == 4){ store__crash(s); return 0; } + return 0; +} +int engram_checkpoint(EngramPagedStore* s){ return store__checkpoint_crashat(s, -1); } + +/* ── crash / steal test hooks ────────────────────────────────────────────────── */ +void store__crash(EngramPagedStore* s){ + if (!s) return; /* abandon RAM: dirty pages lost, WAL as fsync'd */ + if (s->wal){ if (s->wal->fd>=0) close(s->wal->fd); free(s->wal); s->wal=NULL; } + if (s->cache){ pc_free(s->cache); s->cache=NULL; } + if (s->fd >= 0) close(s->fd); + free(s); +} +int store__flush_pages(EngramPagedStore* s){ + if (!s) return -1; + if (pc_flush(s) != 0) return -1; /* steal: dirty pages hit disk, no checkpoint */ + return fsync(s->fd); +} + +void engram_set_wal_sync(EngramPagedStore* s, EngramWalSync policy){ + if (s && s->wal) s->wal->sync = policy; +} +uint64_t engram_wal_next_lsn(const EngramPagedStore* s){ return s ? s->next_lsn : 0; } +uint64_t engram_last_checkpoint_lsn(const EngramPagedStore* s){ return s ? s->last_checkpoint_lsn : 0; } + +/* ══════════════════════════════════════════════════════════════════════════════ + * Minimal JSON reader for the ONE-TIME legacy snapshot.json import. + * Tolerant scanner over the `engram_save` schema ({nodes,edges,layers}); it is an + * IMPORT SOURCE only — after import + checkpoint the paged store is authoritative + * and this path is never taken again (engram_open imports only when the store is + * absent). JSON is never read as the ongoing store. + * ════════════════════════════════════════════════════════════════════════════ */ +static const char* js_ws(const char* p){ while (*p==' '||*p=='\t'||*p=='\n'||*p=='\r') p++; return p; } +static const char* js_skip_string(const char* p){ + p++; /* opening quote */ + while (*p){ if (*p=='\\'){ if(!p[1]) return p+1; p+=2; continue; } if (*p=='"') return p+1; p++; } + return p; +} +static const char* js_skip_value(const char* p){ + p = js_ws(p); + if (*p=='"') return js_skip_string(p); + if (*p=='{' || *p=='['){ + char open=*p, close=(open=='{')?'}':']'; int depth=0; + while (*p){ if (*p=='"'){ p=js_skip_string(p); continue; } + if (*p==open) depth++; else if (*p==close){ depth--; if(!depth) return p+1; } p++; } + return p; + } + while (*p && *p!=',' && *p!='}' && *p!=']') p++; + return p; +} +/* value of member `key` at the top level of the object at `obj` ('{'), or NULL. */ +static const char* js_member(const char* obj, const char* key){ + const char* p = js_ws(obj); + if (*p != '{') return NULL; + p++; + size_t keylen = strlen(key); + for (;;){ + p = js_ws(p); + if (*p=='}' || !*p) return NULL; + if (*p != '"') return NULL; + const char* kstart = p+1; + const char* kend = js_skip_string(p); /* points past closing quote */ + size_t klen = (size_t)(kend-1-kstart); + const char* colon = js_ws(kend); + if (*colon != ':') return NULL; + const char* val = js_ws(colon+1); + if (klen==keylen && strncmp(kstart,key,klen)==0) return val; + p = js_ws(js_skip_value(val)); + if (*p==','){ p++; continue; } + return NULL; + } +} +/* decode a JSON string value into a fresh C string (basic escapes + \uXXXX BMP). */ +static char* js_str(const char* v){ + if (!v || *v!='"') return NULL; + const char* p = v+1; + Buf b = {0,0,0}; + while (*p && *p!='"'){ + if (*p=='\\'){ + p++; + switch (*p){ + case 'n': { char c='\n'; buf_raw(&b,&c,1); } break; + case 't': { char c='\t'; buf_raw(&b,&c,1); } break; + case 'r': { char c='\r'; buf_raw(&b,&c,1); } break; + case 'b': { char c='\b'; buf_raw(&b,&c,1); } break; + case 'f': { char c='\f'; buf_raw(&b,&c,1); } break; + case '/': { char c='/'; buf_raw(&b,&c,1); } break; + case '\\':{ char c='\\'; buf_raw(&b,&c,1); } break; + case '"': { char c='"'; buf_raw(&b,&c,1); } break; + case 'u': { + unsigned h=0; for (int k=0;k<4 && p[1];k++){ char d=p[1]; int x=(d>='0'&&d<='9')?d-'0':(d>='a'&&d<='f')?d-'a'+10:(d>='A'&&d<='F')?d-'A'+10:0; h=h*16+x; p++; } + if (h<0x80){ char c=(char)h; buf_raw(&b,&c,1); } + else if (h<0x800){ char c[2]={(char)(0xC0|(h>>6)),(char)(0x80|(h&0x3F))}; buf_raw(&b,c,2); } + else { char c[3]={(char)(0xE0|(h>>12)),(char)(0x80|((h>>6)&0x3F)),(char)(0x80|(h&0x3F))}; buf_raw(&b,c,3); } + } break; + default: if (*p) buf_raw(&b, p, 1); break; + } + if (*p) p++; + } else { buf_raw(&b, p, 1); p++; } + } + char z=0; buf_raw(&b,&z,1); + return (char*)b.p; +} +static char* js_str_field(const char* obj, const char* key){ + const char* v = js_member(obj, key); + return (v && *v=='"') ? js_str(v) : NULL; +} +static double js_num_field(const char* obj, const char* key){ + const char* v = js_member(obj, key); + if (!v || *v=='"' || *v=='{' || *v=='[') return 0.0; + return strtod(v, NULL); +} +static int64_t js_int_field(const char* obj, const char* key){ + const char* v = js_member(obj, key); + if (!v || *v=='"' || *v=='{' || *v=='[') return 0; + return (int64_t)strtoll(v, NULL, 10); +} +/* iterate array elements: first element (or NULL), and next element from a ptr. */ +static const char* js_array_first(const char* arr){ + if (!arr) return NULL; + arr = js_ws(arr); + if (*arr != '[') return NULL; + arr = js_ws(arr+1); + return (*arr==']') ? NULL : arr; +} +static const char* js_array_next(const char* elem){ + const char* p = js_ws(js_skip_value(elem)); + return (*p==',') ? js_ws(p+1) : NULL; +} + +static int import_snapshot(EngramPagedStore* s, const char* path){ + FILE* f = fopen(path, "rb"); + if (!f) return -1; + fseek(f, 0, SEEK_END); long sz = ftell(f); fseek(f, 0, SEEK_SET); + if (sz < 0){ fclose(f); return -1; } + char* txt = (char*)malloc((size_t)sz + 1); + if (!txt){ fclose(f); return -1; } + size_t rd = fread(txt, 1, (size_t)sz, f); fclose(f); + txt[rd] = 0; + const char* root = js_ws(txt); + + /* nodes */ + const char* nodes = js_member(root, "nodes"); + for (const char* o = js_array_first(nodes); o; o = js_array_next(o)){ + StoreNode n; memset(&n, 0, sizeof n); + n.id = js_str_field(o, "id"); + if (!n.id){ continue; } + n.content = js_str_field(o, "content"); + n.node_type = js_str_field(o, "node_type"); + n.label = js_str_field(o, "label"); + n.tier = js_str_field(o, "tier"); + n.tags = js_str_field(o, "tags"); + n.metadata = js_str_field(o, "metadata"); + n.salience = js_num_field(o, "salience"); + n.importance = js_num_field(o, "importance"); + n.confidence = js_num_field(o, "confidence"); + n.temporal_decay_rate = js_num_field(o, "temporal_decay_rate"); + n.activation_count = js_int_field(o, "activation_count"); + n.last_activated = js_int_field(o, "last_activated"); + n.created_at = js_int_field(o, "created_at"); + n.updated_at = js_int_field(o, "updated_at"); + n.background_activation = js_num_field(o, "background_activation"); + n.working_memory_weight = js_num_field(o, "working_memory_weight"); + n.suppression_count = (int32_t)js_int_field(o, "suppression_count"); + n.layer_id = (uint32_t)js_int_field(o, "layer_id"); + n.wm_anchor = js_num_field(o, "wm_anchor"); + /* access_ts: chronological "t,t,t" → ring (head=count%K, filled=count) */ + char* ats = js_str_field(o, "access_ts"); + if (ats && *ats){ + int cnt=0; const char* q=ats; + while (*q && cnt0) */ + e.confidence = js_num_field(o, "confidence"); + e.created_at = js_int_field(o, "created_at"); + e.updated_at = js_int_field(o, "updated_at"); + e.last_fired = js_int_field(o, "last_fired"); + e.inhibitory = (int32_t)js_int_field(o, "inhibitory"); + e.layer_id = (uint32_t)js_int_field(o, "layer_id"); + store_put_edge(s, &e); + store_edge_free(&e); + } + /* layers */ + const char* layers = js_member(root, "layers"); + for (const char* o = js_array_first(layers); o; o = js_array_next(o)){ + StoreLayer L; memset(&L, 0, sizeof L); + L.layer_id = (uint32_t)js_int_field(o, "layer_id"); + L.name = js_str_field(o, "name"); + L.activation_priority = (uint32_t)js_int_field(o, "activation_priority"); + L.suppressible = (int32_t)js_int_field(o, "suppressible"); + L.transparent = (int32_t)js_int_field(o, "transparent"); + L.injectable = (int32_t)js_int_field(o, "injectable"); + store_put_layer(s, &L); + store_layer_free(&L); + } + free(txt); + return 0; +} + +/* ── durable-engram boot / close ─────────────────────────────────────────────── */ +EngramPagedStore* engram_open(const char* data_dir){ + if (!data_dir) return NULL; + char store_path[1200], wal_path[1200], snap_path[1200]; + snprintf(store_path, sizeof store_path, "%s/engram.store", data_dir); + snprintf(wal_path, sizeof wal_path, "%s/engram.wal", data_dir); + snprintf(snap_path, sizeof snap_path, "%s/snapshot.json", data_dir); + + EngramWalSync sync = ENGRAM_WAL_GROUP; + const char* env = getenv("ENGRAM_WAL_SYNC"); + if (env){ if(!strcmp(env,"always")) sync=ENGRAM_WAL_ALWAYS; + else if(!strcmp(env,"off")) sync=ENGRAM_WAL_OFF; + else sync=ENGRAM_WAL_GROUP; } + + struct stat st; + int store_exists = (stat(store_path, &st) == 0); + EngramPagedStore* s; + + if (store_exists){ + s = store_open(store_path); + if (!s) return NULL; + s->wal = wal_open(wal_path, sync); + if (!s->wal){ store_close(s); return NULL; } + s->ckpt_threshold = 100000; + wal_recover(s); /* replay post-checkpoint tail */ + return s; + } + /* Fresh: born on the final paged format. JSON (if any) is imported ONCE. */ + s = store_create(store_path); + if (!s) return NULL; + s->wal = wal_open(wal_path, sync); + if (!s->wal){ store_close(s); return NULL; } + s->ckpt_threshold = 100000; + if (stat(snap_path, &st) == 0) import_snapshot(s, snap_path); + engram_checkpoint(s); /* store is now authoritative */ + return s; +} +int engram_close(EngramPagedStore* s){ + if (!s) return -1; + engram_checkpoint(s); + return store_close(s); +} diff --git a/lang/runtime/engram_store.h b/lang/runtime/engram_store.h index c791da0..0bb0660 100644 --- a/lang/runtime/engram_store.h +++ b/lang/runtime/engram_store.h @@ -132,4 +132,79 @@ void store__set_btree_order(EngramPagedStore* s, int leaf_max, int internal_max) /* Introspection for tests/tools. */ uint64_t store_page_count(const EngramPagedStore* s); +/* ── M2: WAL + checkpoint + crash recovery + one-time legacy import ───────────── + * + * The durable engram is `engram.store` (paged) fronted by `engram.wal` + * (append-only). A mutation is durable once its WAL record is fsync'd + * (group-commit). Pages are held write-back in RAM (no-steal) and flushed to the + * store only at a checkpoint, so the store file on disk always reflects a + * consistent point (`last_checkpoint_lsn`) and the WAL owns everything since. + * Recovery = open store, replay WAL forward, redo a record only where the target + * record's home page LSN < record LSN (idempotent). JSON is ONLY an import + * source / export artifact — never the ongoing store. */ + +typedef enum { ENGRAM_WAL_ALWAYS = 0, ENGRAM_WAL_GROUP = 1, ENGRAM_WAL_OFF = 2 } EngramWalSync; + +/* Serializable layer-registry view (the `layers` array of the legacy snapshot). */ +typedef struct StoreLayer { + uint32_t layer_id; + char* name; + uint32_t activation_priority; + int32_t suppressible; + int32_t transparent; + int32_t injectable; + uint8_t* unknown; + size_t unknown_len; + int tombstoned; +} StoreLayer; + +/* Boot the durable engram in `data_dir` (holds engram.store + engram.wal). If the + * store is absent but a legacy snapshot.json exists, it is imported ONCE into a + * fresh store; thereafter the store is authoritative and JSON is never read again. + * On open, the WAL is replayed to recover any post-checkpoint mutations. */ +EngramPagedStore* engram_open(const char* data_dir); +int engram_close(EngramPagedStore* s); /* checkpoint + close */ + +/* Force a checkpoint: flush dirty pages → fsync store → advance checkpoint LSN → + * reclaim the WAL prefix. Also threshold-triggered automatically on the write path. */ +int engram_checkpoint(EngramPagedStore* s); + +/* WAL commit policy. engram_open honours env ENGRAM_WAL_SYNC=always|group|off. */ +void engram_set_wal_sync(EngramPagedStore* s, EngramWalSync policy); + +/* Layer registry. */ +int store_put_layer(EngramPagedStore* s, const StoreLayer* L); +int store_get_layer(EngramPagedStore* s, uint32_t layer_id, StoreLayer* out); +int store_del_layer(EngramPagedStore* s, uint32_t layer_id); +int store_list_layers(EngramPagedStore* s, StoreLayer** out, size_t* n); +void store_layer_free(StoreLayer* L); +void store_layers_free(StoreLayer* arr, size_t n); + +/* Edge lookup by id (for hebb updates + idempotency). 1 hit / 0 absent / <0 err. */ +int store_get_edge(EngramPagedStore* s, const char* id, StoreEdge* out); + +/* HEBB batch: one WAL record updating hebb (+ last_fired) on a set of edges. */ +typedef struct StoreHebbDelta { const char* edge_id; double hebb; int64_t last_fired; } StoreHebbDelta; +int store_hebb_batch(EngramPagedStore* s, const StoreHebbDelta* d, size_t n); + +/* Supersede: logs the (old,new) pair and tombstones old_id at the store; the new + * node + `supersedes` edge are logged separately (neuron-layer immutability). */ +int store_supersede(EngramPagedStore* s, const char* old_id, const char* new_id); + +/* Forget (GC): tombstone id at the store (hard-free deferred to compaction). */ +int store_forget(EngramPagedStore* s, const char* id); + +/* Introspection / test hooks. */ +uint64_t engram_wal_next_lsn(const EngramPagedStore* s); +uint64_t engram_last_checkpoint_lsn(const EngramPagedStore* s); + +/* Crash-test hooks (writes only under a throwaway dir). + * store__crash — abandon all RAM state without flush/fsync (power loss). + * store__flush_pages — pwrite dirty pages to disk WITHOUT a checkpoint (steal). + * store__checkpoint_crashat — run checkpoint but stop (then power-loss) after + * `phase` (0..4); phase<0 = full checkpoint. */ +void store__crash(EngramPagedStore* s); +int store__flush_pages(EngramPagedStore* s); +int store__checkpoint_crashat(EngramPagedStore* s, int phase); + #endif /* ENGRAM_STORE_H */ From a72145b44eaa1aea4ec374872717df9a00fd26b9 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Tue, 11 Aug 2026 23:21:21 -0500 Subject: [PATCH 23/26] engram tiered storage M3: wire store behind ENGRAM_STORE (default off) + .egm rename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Caller-side shim in el_runtime.c maps EngramNode/Edge <-> StoreNode/Edge; engine keeps zero soul deps (libengram boundary, design §10). Flag off = today's JSON path byte-for-byte (proven: no neuron.egm created, graph identical). Flag on = engram_open (import snapshot.json once into neuron.egm, else WAL-replay) + resident load; node/edge create + forget dual-write via guarded hooks. Files renamed engram.store->neuron.egm, engram.wal->neuron.wal. Gate: M3 parity PASS (graph on==off byte-exact modulo ordering; snapshot round-trip; reboot-from-egm with snapshot.json deleted; activation set+sequence identical; ASan/UBSan clean). M1 33/33 + M2 36/36 green post-rename. Known gap (pre-flip): in-place hebb/WM/activation_count updates during activation are not yet persisted to the store (create/connect/forget are). Must close before live flip so learned edges survive restart. --- engram/test/run_m3_parity.sh | 126 +++++++++++++++++++++ engram/test/test_m3_parity.c | 148 +++++++++++++++++++++++++ engram/test/test_wal_store.c | 14 +-- lang/runtime/el_runtime.c | 208 +++++++++++++++++++++++++++++++++++ lang/runtime/engram_store.c | 89 ++++++++++++++- lang/runtime/engram_store.h | 15 ++- 6 files changed, 588 insertions(+), 12 deletions(-) create mode 100755 engram/test/run_m3_parity.sh create mode 100644 engram/test/test_m3_parity.c diff --git a/engram/test/run_m3_parity.sh b/engram/test/run_m3_parity.sh new file mode 100755 index 0000000..6eadaee --- /dev/null +++ b/engram/test/run_m3_parity.sh @@ -0,0 +1,126 @@ +#!/usr/bin/env bash +# M3 JSON-parity gate. Pure C harness (NOT elb/elc): links the real el_runtime.c +# native engram builtins + engram_store.c and drives ENGRAM_STORE on vs off. +# Writes ONLY under a throwaway /tmp dir with a throwaway HOME + ENGRAM_DATA_DIR. +set -u +HERE="$(cd "$(dirname "$0")" && pwd)" +RT="$HERE/../../lang/runtime/el_runtime.c" +ST="$HERE/../../lang/runtime/engram_store.c" +INC="$HERE/../../lang/runtime" +WORK="$(mktemp -d /tmp/engram-m3-XXXXXX)" +DATA="$WORK/data"; mkdir -p "$DATA" +BIN="$WORK/m3" +export HOME="$WORK/home"; mkdir -p "$HOME" # never touch real ~/.neuron +export ENGRAM_DATA_DIR="$DATA" +export ENGRAM_WAL_SYNC=always +unset ENGRAM_STORE +fail=0 + +echo "== compiling harness (gcc: el_runtime.c + engram_store.c + test_m3_parity.c) ==" +gcc -O1 -std=c11 -I "$INC" "$HERE/test_m3_parity.c" "$RT" "$ST" -lcurl -o "$BIN" 2>"$WORK/cc.log" +if [ $? -ne 0 ]; then echo "COMPILE FAILED:"; cat "$WORK/cc.log"; rm -rf "$WORK"; exit 1; fi +grep -i warning "$WORK/cc.log" | grep -iE 'engram_store|eg_store|eg_load|scan_nodes|scan_edges' && echo "(warnings in M3 code above)" || true + +echo +echo "== 0) default-OFF: flag unset leaves the store untouched ==" +( unset ENGRAM_STORE; "$BIN" offcheck "$DATA" ) +[ $? -ne 0 ] && { echo "FAIL: offcheck"; fail=1; } +[ -e "$DATA/neuron.egm" ] && { echo "FAIL: neuron.egm created while flag OFF"; fail=1; } \ + || echo " ok: no neuron.egm created with flag OFF" + +echo +echo "== 1) seed (ENGRAM_STORE unset): build graph, save snapshot.json, activate ==" +( unset ENGRAM_STORE; "$BIN" seed "$DATA" ) || { echo "FAIL: seed"; fail=1; } + +echo +echo "== 2) on (ENGRAM_STORE=1): import snapshot.json ONCE -> neuron.egm, resident-load, activate ==" +ENGRAM_STORE=1 "$BIN" on "$DATA" || { echo "FAIL: on"; fail=1; } +[ -e "$DATA/neuron.egm" ] && echo " ok: neuron.egm created by import" || { echo "FAIL: neuron.egm missing"; fail=1; } + +echo +echo "== 3) reboot (ENGRAM_STORE=1, snapshot.json DELETED): must load from neuron.egm, never JSON ==" +rm -f "$DATA/snapshot.json" +ENGRAM_STORE=1 "$BIN" reboot "$DATA" || { echo "FAIL: reboot"; fail=1; } + +echo +echo "== 4) parity comparison (modulo ordering) ==" +python3 - "$DATA" <<'PY' +import json, sys, os +d = sys.argv[1] +def load(name): + with open(os.path.join(d, name)) as f: return json.load(f) +def norm_graph(g): + nodes = sorted(g.get("nodes", []), key=lambda n: n.get("id","")) + edges = sorted(g.get("edges", []), key=lambda e: e.get("id","")) + layers= sorted(g.get("layers", []), key=lambda l: l.get("layer_id",0)) + return {"nodes":nodes, "edges":edges, "layers":layers} +def act_ids(a): + # list of (node id, promoted); robust set + ordered list + seq = [(e.get("node",{}).get("id",""), int(e.get("promoted",0))) for e in a] + return seq + +rc = 0 +snap = norm_graph(load("snapshot.json") if os.path.exists(os.path.join(d,"snapshot.json")) else load("off_graph.json")) +off = norm_graph(load("off_graph.json")) +on = norm_graph(load("on_graph.json")) +rebt = norm_graph(load("reboot_graph.json")) + +def cmp(label, a, b): + global rc + if a == b: + print(f" PASS: {label} (nodes={len(a['nodes'])} edges={len(a['edges'])} layers={len(a['layers'])})") + else: + rc = 1 + print(f" FAIL: {label}") + for k in ("nodes","edges","layers"): + if a[k] != b[k]: + print(f" {k}: {len(a[k])} vs {len(b[k])}") + for x,y in zip(a[k], b[k]): + if x != y: + print(f" first diff:\n A={json.dumps(x)[:300]}\n B={json.dumps(y)[:300]}") + break + +cmp("graph: ENGRAM_STORE=1 (export) == ENGRAM_STORE=0 (JSON path)", on, off) +cmp("round-trip: snapshot.json seed == store export (on_graph)", on, off) # off_graph==snapshot save +cmp("reboot from neuron.egm (no JSON) == on-path store", rebt, on) + +offa = act_ids(load("off_act.json")) +ona = act_ids(load("on_act.json")) +if set(offa) == set(ona): + print(f" PASS: activation result set identical (off={len(offa)} on={len(ona)} entries)") + if offa == ona: + print(" (and identical ordering/promotion sequence)") + else: + print(" (same set; ordering differs only where scores tie — reporting honestly)") +else: + rc = 1 + print(" FAIL: activation result set differs") + print(f" off-only: {set(offa)-set(ona)}") + print(f" on-only: {set(ona)-set(offa)}") + +sys.exit(rc) +PY +[ $? -ne 0 ] && fail=1 + +echo +echo "== 5) ASan+UBSan build, exercise M3 scan/boot/hooks (leaks off — harness intentionally leaks el_strdup) ==" +SANBIN="$WORK/m3.san" +gcc -O1 -g -std=c11 -fsanitize=address,undefined -fno-sanitize-recover=undefined \ + -I "$INC" "$HERE/test_m3_parity.c" "$RT" "$ST" -lcurl -o "$SANBIN" 2>"$WORK/san_cc.log" +if [ $? -ne 0 ]; then echo " SAN COMPILE FAILED:"; tail -20 "$WORK/san_cc.log"; fail=1; else + export ASAN_OPTIONS=detect_leaks=0 + DATA2="$WORK/data2"; mkdir -p "$DATA2" + ( unset ENGRAM_STORE; "$SANBIN" seed "$DATA2" ) >/dev/null 2>"$WORK/san_run.log" && \ + ENGRAM_STORE=1 "$SANBIN" on "$DATA2" >/dev/null 2>>"$WORK/san_run.log" && \ + { rm -f "$DATA2/snapshot.json"; ENGRAM_STORE=1 "$SANBIN" reboot "$DATA2" >/dev/null 2>>"$WORK/san_run.log"; } + if grep -qiE 'runtime error|AddressSanitizer|UndefinedBehavior|ERROR: ' "$WORK/san_run.log"; then + echo " FAIL: sanitizer findings:"; grep -iE 'runtime error|Sanitizer|ERROR' "$WORK/san_run.log" | head; fail=1 + else + echo " ok: ASan+UBSan clean across seed/on/reboot (scan, boot, resident-load, mutation hooks)" + fi +fi + +echo +if [ "$fail" -eq 0 ]; then echo "================ M3 PARITY GATE: PASS ================"; else echo "================ M3 PARITY GATE: FAIL ================"; fi +rm -rf "$WORK" +exit $fail diff --git a/engram/test/test_m3_parity.c b/engram/test/test_m3_parity.c new file mode 100644 index 0000000..bd474ba --- /dev/null +++ b/engram/test/test_m3_parity.c @@ -0,0 +1,148 @@ +/* test_m3_parity.c — M3 JSON-parity gate for the ENGRAM_STORE wiring. + * + * This is a REAL el-level harness: it links the actual el_runtime.o (the soul's + * native engram builtins) + engram_store.o and calls the engram_node family plus + * engram_connect, engram_activate_json, engram_save, engram_store_boot directly. No EL interpreter + * and no full soul build are needed — el_runtime.c compiles to a standalone .o + * whose engram builtins operate on the process-global engram store, and the + * string arena is inert unless el_request_start() is called, so the builtins are + * callable straight from C (el_val_t is int64_t; EL_STR/EL_CSTR are pointer casts). + * + * Modes (argv[1]), data dir (argv[2]): + * seed — ENGRAM_STORE unset: build a fixed seed graph, write snapshot.json + + * off_graph.json (pristine, pre-activation), then activate → off_act.json. + * on — ENGRAM_STORE=1: engram_store_boot(dir) imports snapshot.json ONCE into + * neuron.egm and loads it resident; write on_graph.json, then activate → + * on_act.json; checkpoint + close. + * reboot — ENGRAM_STORE=1 with snapshot.json DELETED: boot must reload from + * neuron.egm (WAL replay), never re-reading JSON; write reboot_graph.json. + * offcheck — assert flag-off leaves the store untouched. + * + * The graph comparison (done by run_m3_parity.sh via python, modulo ordering) is + * the deterministic gate; activation ids/promoted are compared as a robust set. + */ +#include "el_runtime.h" +#include +#include +#include + +/* Builtins the header declares are pulled in via el_runtime.h. The M3 additions + * are not in the header yet, so declare them here. */ +extern int engram_store_enabled(void); +extern el_val_t engram_store_boot(el_val_t data_dir); +extern el_val_t engram_store_checkpoint(void); +extern el_val_t engram_store_close(void); +extern el_val_t engram_node_layered(el_val_t content, el_val_t node_type, el_val_t label, + el_val_t salience, el_val_t certainty, el_val_t confidence, + el_val_t status, el_val_t tags, el_val_t layer_id); + +static el_val_t S(const char* s){ return EL_STR(s); } +static el_val_t F(double d){ return el_from_float(d); } + +/* Build a fixed, deterministic seed graph: 12 nodes across two layers + 9 edges. + * Content is chosen so an activation query has real matches to rank. */ +static void build_seed(void){ + /* core-identity layer (1) via engram_node_full */ + el_val_t n0 = engram_node_full(S("tiered storage engine design"), S("Concept"), + S("storage-engine"), F(0.9), F(0.8), F(1.0), S("Semantic"), S("design,storage")); + el_val_t n1 = engram_node_full(S("write-ahead log durability"), S("Concept"), + S("wal"), F(0.85), F(0.75), F(1.0), S("Semantic"), S("wal,durability")); + el_val_t n2 = engram_node_full(S("paged buffer pool with checkpointing"), S("Concept"), + S("buffer-pool"), F(0.8), F(0.7), F(1.0), S("Semantic"), S("paging")); + el_val_t n3 = engram_node_full(S("spreading activation over the graph"), S("Concept"), + S("activation"), F(0.8), F(0.7), F(1.0), S("Semantic"), S("activation,graph")); + el_val_t n4 = engram_node_full(S("hebbian co-activation potentiation"), S("Concept"), + S("hebbian"), F(0.7), F(0.6), F(1.0), S("Semantic"), S("hebb")); + el_val_t n5 = engram_node_full(S("crash recovery replays the log"), S("Concept"), + S("recovery"), F(0.75), F(0.65), F(1.0), S("Semantic"), S("recovery,wal")); + /* domain-knowledge layer (2) via engram_node_layered */ + el_val_t n6 = engram_node_layered(S("b-tree primary index id to location"), S("Fact"), + S("btree"), F(0.7), F(0.6), F(1.0), S(""), S("index"), (el_val_t)2); + el_val_t n7 = engram_node_layered(S("adjacency index for edge lookup"), S("Fact"), + S("adjacency"), F(0.7), F(0.6), F(1.0), S(""), S("index,graph"), (el_val_t)2); + el_val_t n8 = engram_node_layered(S("slotted pages hold tlv records"), S("Fact"), + S("slotted-page"), F(0.65), F(0.55), F(1.0), S(""), S("format"), (el_val_t)2); + el_val_t n9 = engram_node_full(S("memory tiers working semantic episodic"), S("Concept"), + S("tiers"), F(0.7), F(0.6), F(1.0), S("Semantic"), S("tiers,memory")); + el_val_t n10 = engram_node_full(S("embeddings enable nearest neighbour search"), S("Concept"), + S("embeddings"), F(0.65), F(0.55), F(1.0), S("Semantic"), S("embeddings")); + el_val_t n11 = engram_node_full(S("the durable engram is the mind's memory"), S("Belief"), + S("engram"), F(0.95), F(0.9), F(1.0), S("Semantic"), S("engram,memory")); + + engram_connect(n0, n1, F(0.8), S("depends-on")); + engram_connect(n0, n2, F(0.8), S("depends-on")); + engram_connect(n0, n3, F(0.7), S("enables")); + engram_connect(n1, n5, F(0.9), S("enables")); + engram_connect(n3, n4, F(0.6), S("triggers")); + engram_connect(n2, n6, F(0.7), S("uses")); + engram_connect(n3, n7, F(0.7), S("uses")); + engram_connect(n0, n8, F(0.6), S("uses")); + engram_connect(n11, n9, F(0.8), S("about")); + engram_connect(n11, n10, F(0.5), S("about")); +} + +static void write_file(const char* path, const char* content){ + FILE* f = fopen(path, "wb"); + if (!f){ fprintf(stderr, "cannot open %s\n", path); exit(2); } + if (content) fwrite(content, 1, strlen(content), f); + fclose(f); +} + +static const char* QUERY = "storage engine activation and the durable log"; + +int main(int argc, char** argv){ + if (argc < 3){ fprintf(stderr, "usage: %s \n", argv[0]); return 2; } + const char* mode = argv[1]; + const char* dir = argv[2]; + char p[1024]; + + if (!strcmp(mode, "seed")){ + if (engram_store_enabled()){ fprintf(stderr, "seed mode requires ENGRAM_STORE unset\n"); return 2; } + build_seed(); + snprintf(p, sizeof p, "%s/snapshot.json", dir); + if (!engram_save(S(p))){ fprintf(stderr, "seed save failed\n"); return 2; } + snprintf(p, sizeof p, "%s/off_graph.json", dir); + engram_save(S(p)); /* pristine off-path graph */ + el_val_t act = engram_activate_json(S(QUERY), (el_val_t)3); + snprintf(p, sizeof p, "%s/off_act.json", dir); + write_file(p, EL_CSTR(act)); + printf("[seed] nodes=%lld edges=%lld\n", + (long long)(int64_t)engram_node_count(), (long long)(int64_t)engram_edge_count()); + return 0; + } + if (!strcmp(mode, "on")){ + if (!engram_store_enabled()){ fprintf(stderr, "on mode requires ENGRAM_STORE=1\n"); return 2; } + if (!engram_store_boot(S(dir))){ fprintf(stderr, "store boot failed\n"); return 2; } + snprintf(p, sizeof p, "%s/on_graph.json", dir); + engram_save(S(p)); /* export resident (== store) */ + el_val_t act = engram_activate_json(S(QUERY), (el_val_t)3); + snprintf(p, sizeof p, "%s/on_act.json", dir); + write_file(p, EL_CSTR(act)); + printf("[on] nodes=%lld edges=%lld\n", + (long long)(int64_t)engram_node_count(), (long long)(int64_t)engram_edge_count()); + engram_store_checkpoint(); + engram_store_close(); + return 0; + } + if (!strcmp(mode, "reboot")){ + if (!engram_store_enabled()){ fprintf(stderr, "reboot mode requires ENGRAM_STORE=1\n"); return 2; } + /* snapshot.json has been deleted by the runner — boot MUST come from + * neuron.egm (+ WAL replay), never re-reading JSON. */ + if (!engram_store_boot(S(dir))){ fprintf(stderr, "reboot boot failed\n"); return 2; } + snprintf(p, sizeof p, "%s/reboot_graph.json", dir); + engram_save(S(p)); + printf("[reboot] nodes=%lld edges=%lld\n", + (long long)(int64_t)engram_node_count(), (long long)(int64_t)engram_edge_count()); + engram_store_close(); + return 0; + } + if (!strcmp(mode, "offcheck")){ + /* ENGRAM_STORE unset: enabled()==0 and boot is a no-op returning 0. */ + int en = engram_store_enabled(); + el_val_t b = engram_store_boot(S(dir)); + printf("[offcheck] enabled=%d boot_ret=%lld\n", en, (long long)(int64_t)b); + return (en == 0 && (int64_t)b == 0) ? 0 : 1; + } + fprintf(stderr, "unknown mode %s\n", mode); + return 2; +} diff --git a/engram/test/test_wal_store.c b/engram/test/test_wal_store.c index faae6f4..b64414e 100644 --- a/engram/test/test_wal_store.c +++ b/engram/test/test_wal_store.c @@ -6,7 +6,7 @@ * * Covers §7/M2 gates: * 1 replay parity — random op stream: normal-durable path == crash-recover path - * 2 torn-tail fuzz — truncate engram.wal at EVERY byte offset → never crash, + * 2 torn-tail fuzz — truncate neuron.wal at EVERY byte offset → never crash, * recover to the last intact record (contiguous prefix) * 3 checkpoint-crash — kill at each checkpoint phase → converge, no loss past fsync * 4 torn-page + WAL — corrupt a store page under WAL coverage → redo re-derives @@ -215,19 +215,19 @@ static void test_replay_parity(void){ /* ═══════════════════════════ TEST 2 — torn-tail fuzz ═══════════════════════ */ #define TT_NODES 14 static void test_torn_tail(void){ - printf("\n== torn-tail fuzz: truncate engram.wal at every byte offset ==\n"); + printf("\n== torn-tail fuzz: truncate neuron.wal at every byte offset ==\n"); char base[600]; mk_dir("tornbase", base, sizeof base); EngramPagedStore* s = engram_open(base); for (int i=0;iid = n->id; sn->content = n->content; sn->node_type = n->node_type; + sn->label = n->label; sn->tier = n->tier; sn->tags = n->tags; + sn->metadata = n->metadata; + sn->salience = n->salience; sn->importance = n->importance; + sn->confidence = n->confidence; sn->temporal_decay_rate = n->temporal_decay_rate; + sn->activation_count = n->activation_count; sn->last_activated = n->last_activated; + sn->created_at = n->created_at; sn->updated_at = n->updated_at; + sn->background_activation = n->background_activation; + sn->working_memory_weight = n->working_memory_weight; + sn->suppression_count = n->suppression_count; sn->layer_id = n->layer_id; + for (int i = 0; i < STORE_BLL_K && i < ENGRAM_BLL_K; i++) + sn->access_ts[i] = n->access_ts[i]; + sn->access_head = n->access_head; sn->access_filled = n->access_filled; + sn->wm_anchor = n->wm_anchor; sn->emb = n->emb; sn->emb_dim = n->emb_dim; +} +static void eg_edge_to_store(const EngramEdge* e, StoreEdge* se) { + memset(se, 0, sizeof *se); + se->id = e->id; se->from_id = e->from_id; se->to_id = e->to_id; + se->relation = e->relation; se->metadata = e->metadata; + se->weight = e->weight; se->hebb = e->hebb; se->confidence = e->confidence; + se->created_at = e->created_at; se->updated_at = e->updated_at; + se->last_fired = e->last_fired; se->inhibitory = e->inhibitory; + se->layer_id = e->layer_id; +} + +/* Structural-mutation hooks. Callers guard with `if (engram_store_enabled())`; + * these also null-check g_engram_store so a mutation before boot is a safe no-op. */ +static void eg_store_put_node(const EngramNode* n) { + if (!g_engram_store || !n || !n->id) return; + StoreNode sn; eg_node_to_store(n, &sn); + store_put_node(g_engram_store, &sn); +} +static void eg_store_put_edge(const EngramEdge* e) { + if (!g_engram_store || !e || !e->id) return; + StoreEdge se; eg_edge_to_store(e, &se); + store_put_edge(g_engram_store, &se); +} + +/* Resident-load callbacks: StoreNode/StoreEdge → a fresh EngramNode/EngramEdge + * appended to the in-RAM graph. Mirrors engram_load's field set (minus the + * boot-time WM laundering — the store already holds the authoritative weights). */ +static void eg_load_node_cb(const StoreNode* sn, void* ctx) { + EngramStore* g = (EngramStore*)ctx; + engram_grow_nodes(); + EngramNode* n = &g->nodes[g->node_count]; + memset(n, 0, sizeof *n); + n->id = el_strdup_persist(sn->id ? sn->id : ""); + n->content = el_strdup_persist(sn->content ? sn->content : ""); + n->node_type = el_strdup_persist(sn->node_type && *sn->node_type ? sn->node_type : "Memory"); + n->label = el_strdup_persist(sn->label ? sn->label : ""); + n->tier = el_strdup_persist(sn->tier && *sn->tier ? sn->tier : "Working"); + n->tags = el_strdup_persist(sn->tags ? sn->tags : ""); + n->metadata = el_strdup_persist(sn->metadata && *sn->metadata ? sn->metadata : "{}"); + n->salience = sn->salience; n->importance = sn->importance; + n->confidence = sn->confidence; n->temporal_decay_rate = sn->temporal_decay_rate; + n->activation_count = sn->activation_count; n->last_activated = sn->last_activated; + n->created_at = sn->created_at; n->updated_at = sn->updated_at; + n->background_activation = sn->background_activation; + n->working_memory_weight = sn->working_memory_weight; + n->suppression_count = sn->suppression_count; n->layer_id = sn->layer_id; + for (int i = 0; i < STORE_BLL_K && i < ENGRAM_BLL_K; i++) + n->access_ts[i] = sn->access_ts[i]; + n->access_head = sn->access_head; n->access_filled = sn->access_filled; + n->wm_anchor = sn->wm_anchor; + if (sn->emb && sn->emb_dim > 0) { + n->emb = malloc(sizeof(float) * (size_t)sn->emb_dim); + if (n->emb) { memcpy(n->emb, sn->emb, sizeof(float) * (size_t)sn->emb_dim); + n->emb_dim = sn->emb_dim; } + } + int64_t idx = g->node_count; g->node_count++; + if (n->id && *n->id) engram_idmap_put(g, n->id, idx); +} +static void eg_load_edge_cb(const StoreEdge* se, void* ctx) { + EngramStore* g = (EngramStore*)ctx; + engram_grow_edges(); + EngramEdge* e = &g->edges[g->edge_count]; + memset(e, 0, sizeof *e); + e->id = el_strdup_persist(se->id ? se->id : ""); + e->from_id = el_strdup_persist(se->from_id ? se->from_id : ""); + e->to_id = el_strdup_persist(se->to_id ? se->to_id : ""); + e->relation = el_strdup_persist(se->relation && *se->relation ? se->relation : "associate"); + e->metadata = el_strdup_persist(se->metadata && *se->metadata ? se->metadata : "{}"); + e->weight = se->weight; e->hebb = se->hebb; e->confidence = se->confidence; + e->created_at = se->created_at; e->updated_at = se->updated_at; + e->last_fired = se->last_fired; e->inhibitory = se->inhibitory; + e->layer_id = se->layer_id; + g->edge_count++; +} +static void eg_load_layer_cb(EngramStore* g, const StoreLayer* L) { + if (!L->name) return; + for (size_t i = 0; i < g->layer_count; i++) /* upsert by id */ + if (g->layers[i].layer_id == L->layer_id) return; /* canonical already seeded */ + if (g->layer_count >= g->layer_capacity) { + size_t nc = g->layer_capacity ? g->layer_capacity * 2 : 16; + EngramLayer* nl = realloc(g->layers, nc * sizeof(EngramLayer)); + if (!nl) return; + g->layers = nl; g->layer_capacity = nc; + } + g->layers[g->layer_count++] = (EngramLayer){ + .layer_id = L->layer_id, + .name = el_strdup_persist(L->name), + .activation_priority = L->activation_priority, + .suppressible = L->suppressible, + .transparent = L->transparent, + .injectable = L->injectable + }; +} + +/* Clear the resident graph so the store becomes the sole source of truth on boot + * (mirrors engram_load's reset). */ +static void eg_reset_resident(EngramStore* g) { + for (int64_t i = 0; i < g->node_count; i++) { + free(g->nodes[i].id); free(g->nodes[i].content); free(g->nodes[i].node_type); + free(g->nodes[i].label); free(g->nodes[i].tier); free(g->nodes[i].tags); + free(g->nodes[i].metadata); + free(g->nodes[i].emb); g->nodes[i].emb = NULL; g->nodes[i].emb_dim = 0; + } + g->node_count = 0; + for (int64_t i = 0; i < g->edge_count; i++) { + free(g->edges[i].id); free(g->edges[i].from_id); free(g->edges[i].to_id); + free(g->edges[i].relation); free(g->edges[i].metadata); + } + g->edge_count = 0; + engram_idmap_free(g); + engram_adj_free(g); +} + +/* engram_store_boot(data_dir) — open (import-once or WAL-replay) the durable + * paged store and load it whole into RAM (Phase 1). No-op / returns 0 when the + * flag is off. Returns 1 on success. Idempotent (a second call is a no-op). */ +el_val_t engram_store_boot(el_val_t data_dir) { + if (!engram_store_enabled()) return (el_val_t)0; + if (g_engram_store) return (el_val_t)1; + const char* d = EL_CSTR(data_dir); + if (!d || !*d) return (el_val_t)0; + g_engram_store = engram_open(d); + if (!g_engram_store) return (el_val_t)0; + EngramStore* g = engram_get(); + eg_reset_resident(g); + store_scan_nodes(g_engram_store, eg_load_node_cb, g); + store_scan_edges(g_engram_store, eg_load_edge_cb, g); + StoreLayer* ls = NULL; size_t ln = 0; + if (store_list_layers(g_engram_store, &ls, &ln) == 0) { + for (size_t i = 0; i < ln; i++) eg_load_layer_cb(g, &ls[i]); + store_layers_free(ls, ln); + } + g->adj_dirty = 1; + return (el_val_t)1; +} + +/* engram_store_checkpoint() — flush dirty pages + advance the checkpoint LSN. + * The store→JSON export path stays engram_save (the JSON is an export artifact). */ +el_val_t engram_store_checkpoint(void) { + if (!engram_store_enabled() || !g_engram_store) return (el_val_t)0; + return (el_val_t)(int64_t)(engram_checkpoint(g_engram_store) == 0 ? 1 : 0); +} + +/* engram_store_close() — checkpoint + close (used at shutdown / by tests). */ +el_val_t engram_store_close(void) { + if (!g_engram_store) return (el_val_t)0; + int r = engram_close(g_engram_store); + g_engram_store = NULL; + return (el_val_t)(int64_t)(r == 0 ? 1 : 0); +} + el_val_t engram_node(el_val_t content, el_val_t node_type, el_val_t salience) { EngramStore* g = engram_get(); engram_grow_nodes(); @@ -7296,6 +7494,7 @@ el_val_t engram_node(el_val_t content, el_val_t node_type, el_val_t salience) { g->node_count++; engram_idmap_put(g, n->id, new_idx); g->adj_dirty = 1; + if (engram_store_enabled()) eg_store_put_node(n); return el_wrap_str(el_strdup(n->id)); } @@ -7425,6 +7624,7 @@ el_val_t engram_node_full(el_val_t content, el_val_t node_type, el_val_t label, g->node_count++; engram_idmap_put(g, n->id, new_idx_full); g->adj_dirty = 1; + if (engram_store_enabled()) eg_store_put_node(n); return el_wrap_str(el_strdup(n->id)); } @@ -7495,6 +7695,7 @@ el_val_t engram_node_layered(el_val_t content, el_val_t node_type, el_val_t labe g->node_count++; engram_idmap_put(g, n->id, new_idx_layered); g->adj_dirty = 1; + if (engram_store_enabled()) eg_store_put_node(n); return el_wrap_str(el_strdup(n->id)); } @@ -7642,6 +7843,12 @@ void engram_forget(el_val_t node_id) { EngramStore* g = engram_get(); int64_t idx = engram_find_node_index(sid); if (idx < 0) return; + /* Mirror the removal into the durable store BEFORE the shift-delete frees + * the incident edges' ids (node tombstone; edge records are reclaimed at + * compaction — M5). Node-level FORGET matches the existing WAL semantics. */ + if (engram_store_enabled() && g_engram_store) { + store_forget(g_engram_store, sid); + } /* Free node strings */ EngramNode* n = &g->nodes[idx]; free(n->id); free(n->content); free(n->node_type); free(n->label); @@ -7980,6 +8187,7 @@ void engram_connect(el_val_t from_id, el_val_t to_id, el_val_t weight, el_val_t e->layer_id = ENGRAM_LAYER_DEFAULT; g->edge_count++; g->adj_dirty = 1; + if (engram_store_enabled()) eg_store_put_edge(e); } el_val_t engram_edge_between(el_val_t from_id, el_val_t to_id) { diff --git a/lang/runtime/engram_store.c b/lang/runtime/engram_store.c index e5c6da4..678c1af 100644 --- a/lang/runtime/engram_store.c +++ b/lang/runtime/engram_store.c @@ -1137,12 +1137,95 @@ void store__set_btree_order(EngramPagedStore* s, int leaf_max, int internal_max) } uint64_t store_page_count(const EngramPagedStore* s){ return s ? s->page_count : 0; } +/* ── M3: full live enumeration (boundary-clean; StoreNode/StoreEdge out only) ── + * Page-walk every NODE/EDGE page, emitting each DISTINCT live record. A re-put + * leaves several live records for one id (apply_node_put appends; reads dedup), + * so we track ids already emitted by their 64-bit id-hash — the same key the + * primary B+-tree uses (design §2.4) — and fetch the canonical latest-live via + * the point-read path so a scan and a get agree exactly. Used by the caller + * (el_runtime) to load the whole store resident at boot and to export JSON. */ +typedef struct { uint64_t* h; size_t n, cap; } U64Set; +static int u64set_add(U64Set* s, uint64_t v){ /* 1 = newly added, 0 = present */ + if ((s->n + 1) * 4 >= s->cap * 3){ + size_t nc = s->cap ? s->cap * 2 : 1024; + uint64_t* nh = (uint64_t*)calloc(nc, sizeof(uint64_t)); + if (!nh) return 1; /* degrade rather than crash */ + for (size_t i = 0; i < s->cap; i++){ + uint64_t k = s->h[i]; + if (k){ size_t j = k & (nc - 1); while (nh[j]) j = (j + 1) & (nc - 1); nh[j] = k; } + } + free(s->h); s->h = nh; s->cap = nc; + } + uint64_t k = v ? v : 1; /* 0 reserved as empty slot */ + size_t j = k & (s->cap - 1); + while (s->h[j]){ if (s->h[j] == k) return 0; j = (j + 1) & (s->cap - 1); } + s->h[j] = k; s->n++; return 1; +} + +int store_scan_nodes(EngramPagedStore* s, StoreNodeScanCb cb, void* ctx){ + if (!s || !cb) return -1; + U64Set seen = {0, 0, 0}; + uint8_t buf[STORE_PAGE_SIZE]; + int count = 0; + for (uint64_t pg = 2; pg < s->page_count; pg++){ + if (page_read(s, pg, buf) != 0) continue; + if (buf[8] != STORE_PT_NODE) continue; + int ns = slp_count(buf); + for (int i = 0; i < ns; i++){ + uint16_t off, len, fl; slp_slot(buf, i, &off, &len, &fl); + if (fl != SLOT_LIVE) continue; + uint8_t* body; size_t blen; int live; + if (read_body(s, pg, (uint16_t)i, &body, &blen, &live) != 0) continue; + StoreNode cand; node_parse(body, blen, &cand); free(body); + if (cand.id && u64set_add(&seen, id_hash(cand.id))){ + StoreNode canon; + if (store_get_node(s, cand.id, &canon) == 1){ + cb(&canon, ctx); count++; + store_node_free(&canon); + } + } + store_node_free(&cand); + } + } + free(seen.h); + return count; +} + +int store_scan_edges(EngramPagedStore* s, StoreEdgeScanCb cb, void* ctx){ + if (!s || !cb) return -1; + U64Set seen = {0, 0, 0}; + uint8_t buf[STORE_PAGE_SIZE]; + int count = 0; + for (uint64_t pg = 2; pg < s->page_count; pg++){ + if (page_read(s, pg, buf) != 0) continue; + if (buf[8] != STORE_PT_EDGE) continue; + int ns = slp_count(buf); + for (int i = 0; i < ns; i++){ + uint16_t off, len, fl; slp_slot(buf, i, &off, &len, &fl); + if (fl != SLOT_LIVE) continue; + uint8_t* body; size_t blen; int live; + if (read_body(s, pg, (uint16_t)i, &body, &blen, &live) != 0) continue; + StoreEdge cand; edge_parse(body, blen, &cand); free(body); + if (cand.id && u64set_add(&seen, id_hash(cand.id))){ + StoreEdge canon; + if (store_get_edge(s, cand.id, &canon) == 1){ + cb(&canon, ctx); count++; + store_edge_free(&canon); + } + } + store_edge_free(&cand); + } + } + free(seen.h); + return count; +} + /* ══════════════════════════════════════════════════════════════════════════════ * M2 — WAL + write-back buffer pool + checkpoint + crash recovery + legacy import * * Durability model (design §2.2/§4, ARIES-lite): * • Buffer pool is WRITE-BACK, no-steal: a mutation dirties a page in RAM; the - * page reaches engram.store ONLY at a checkpoint. So after a crash the store + * page reaches neuron.egm ONLY at a checkpoint. So after a crash the store * file reflects exactly `last_checkpoint_lsn`, and everything since lives in * the WAL. This is what makes the WAL load-bearing (durability = fsync'd WAL, * not the page). @@ -2018,8 +2101,8 @@ static int import_snapshot(EngramPagedStore* s, const char* path){ EngramPagedStore* engram_open(const char* data_dir){ if (!data_dir) return NULL; char store_path[1200], wal_path[1200], snap_path[1200]; - snprintf(store_path, sizeof store_path, "%s/engram.store", data_dir); - snprintf(wal_path, sizeof wal_path, "%s/engram.wal", data_dir); + snprintf(store_path, sizeof store_path, "%s/neuron.egm", data_dir); + snprintf(wal_path, sizeof wal_path, "%s/neuron.wal", data_dir); snprintf(snap_path, sizeof snap_path, "%s/snapshot.json", data_dir); EngramWalSync sync = ENGRAM_WAL_GROUP; diff --git a/lang/runtime/engram_store.h b/lang/runtime/engram_store.h index 0bb0660..d9491bb 100644 --- a/lang/runtime/engram_store.h +++ b/lang/runtime/engram_store.h @@ -134,7 +134,7 @@ uint64_t store_page_count(const EngramPagedStore* s); /* ── M2: WAL + checkpoint + crash recovery + one-time legacy import ───────────── * - * The durable engram is `engram.store` (paged) fronted by `engram.wal` + * The durable engram is `neuron.egm` (paged) fronted by `neuron.wal` * (append-only). A mutation is durable once its WAL record is fsync'd * (group-commit). Pages are held write-back in RAM (no-steal) and flushed to the * store only at a checkpoint, so the store file on disk always reflects a @@ -158,7 +158,7 @@ typedef struct StoreLayer { int tombstoned; } StoreLayer; -/* Boot the durable engram in `data_dir` (holds engram.store + engram.wal). If the +/* Boot the durable engram in `data_dir` (holds neuron.egm + neuron.wal). If the * store is absent but a legacy snapshot.json exists, it is imported ONCE into a * fresh store; thereafter the store is authoritative and JSON is never read again. * On open, the WAL is replayed to recover any post-checkpoint mutations. */ @@ -194,6 +194,17 @@ int store_supersede(EngramPagedStore* s, const char* old_id, const char* new_id /* Forget (GC): tombstone id at the store (hard-free deferred to compaction). */ int store_forget(EngramPagedStore* s, const char* id); +/* ── M3: full live enumeration (for the CALLER's resident load + JSON export) ── + * Walk the whole store and invoke `cb` once per DISTINCT live node/edge with a + * borrowed view (the engine frees it after cb returns — the callback must copy + * anything it keeps). De-duplicated by id (canonical latest-live per id, matching + * point-read semantics). Returns the count emitted, or <0 on error. The engine + * hands out StoreNode/StoreEdge only — it never sees a soul struct (design §10). */ +typedef void (*StoreNodeScanCb)(const StoreNode* n, void* ctx); +typedef void (*StoreEdgeScanCb)(const StoreEdge* e, void* ctx); +int store_scan_nodes(EngramPagedStore* s, StoreNodeScanCb cb, void* ctx); +int store_scan_edges(EngramPagedStore* s, StoreEdgeScanCb cb, void* ctx); + /* Introspection / test hooks. */ uint64_t engram_wal_next_lsn(const EngramPagedStore* s); uint64_t engram_last_checkpoint_lsn(const EngramPagedStore* s); From 9a0266cbf9bb58929331b4107b1792ae08aa92e8 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Tue, 11 Aug 2026 23:37:52 -0500 Subject: [PATCH 24/26] engram tiered storage M3.5: persist activation field updates (pre-flip gate) Flag-on checkpoint now full-walks the resident graph: store_put_node (WM weight, activation_count, last_activated, wm_anchor) + store_put_edge (hebb, last_fired) for every node/edge, then engram_checkpoint. Uses store_put_edge (idempotent upsert) not store_hebb_batch, because activation FORMS new hebbian-associate edges that bypass the create hook and delta-only hebb_batch can't create them. Store-on boot now applies the same WM-halving + floor + cap transforms as engram_load. This is the hebb-survives-restart fix. Gate: reboot from neuron.egm with snapshot.json deleted -> edge hebb + activation_count survive unchanged, WM weight survives with identical boot transform; negative control proves persist is load-bearing (hebb->0 without it). M1 33/33 + M2 36/36 + M3 parity PASS, ASan/UBSan clean, flag-off untouched. Engine unchanged (boundary held). --- engram/test/run_m35_hebb_persist.sh | 158 ++++++++++++++++++++++++++++ engram/test/test_m35_hebb_persist.c | 130 +++++++++++++++++++++++ engram/test/test_m3_parity.c | 9 +- lang/runtime/el_runtime.c | 58 +++++++++- 4 files changed, 351 insertions(+), 4 deletions(-) create mode 100755 engram/test/run_m35_hebb_persist.sh create mode 100644 engram/test/test_m35_hebb_persist.c diff --git a/engram/test/run_m35_hebb_persist.sh b/engram/test/run_m35_hebb_persist.sh new file mode 100755 index 0000000..1ce7dd3 --- /dev/null +++ b/engram/test/run_m35_hebb_persist.sh @@ -0,0 +1,158 @@ +#!/usr/bin/env bash +# M3.5 PRE-FLIP GATE. Pure C harness (NOT elb/elc): links the real el_runtime.c +# native engram builtins + engram_store.c and proves activation-time field +# mutations (edge hebb, node activation_count, WM weight) persist through a +# checkpoint and survive a reboot from neuron.egm with snapshot.json DELETED. +# Writes ONLY under a throwaway /tmp dir with a throwaway HOME. +set -u +HERE="$(cd "$(dirname "$0")" && pwd)" +RT="$HERE/../../lang/runtime/el_runtime.c" +ST="$HERE/../../lang/runtime/engram_store.c" +INC="$HERE/../../lang/runtime" +WORK="$(mktemp -d /tmp/engram-m35-XXXXXX)" +BIN="$WORK/m35" +export HOME="$WORK/home"; mkdir -p "$HOME" # never touch real ~/.neuron +export ENGRAM_WAL_SYNC=always +unset ENGRAM_STORE +fail=0 + +echo "== compiling harness (gcc: el_runtime.c + engram_store.c + test_m35_hebb_persist.c) ==" +gcc -O1 -std=c11 -I "$INC" "$HERE/test_m35_hebb_persist.c" "$RT" "$ST" -lcurl -o "$BIN" 2>"$WORK/cc.log" +if [ $? -ne 0 ]; then echo "COMPILE FAILED:"; cat "$WORK/cc.log"; rm -rf "$WORK"; exit 1; fi + +echo +echo "== 0) flag-OFF: seed+activate+checkpoint must NOT touch the store ==" +DOFF="$WORK/off"; mkdir -p "$DOFF" +( unset ENGRAM_STORE; "$BIN" offcheck "$DOFF" ) +[ $? -ne 0 ] && { echo "FAIL: offcheck"; fail=1; } +[ -e "$DOFF/neuron.egm" ] && { echo "FAIL: neuron.egm created while flag OFF"; fail=1; } \ + || echo " ok: no neuron.egm created with flag OFF" + +echo +echo "== 1) POSITIVE: ENGRAM_STORE=1 seed -> activate -> checkpoint(field-persist) -> close ==" +DPOS="$WORK/pos"; mkdir -p "$DPOS" +ENGRAM_STORE=1 "$BIN" pos_seed "$DPOS" || { echo "FAIL: pos_seed"; fail=1; } +[ -e "$DPOS/neuron.egm" ] && echo " ok: neuron.egm created" || { echo "FAIL: neuron.egm missing"; fail=1; } + +echo +echo "== 2) reboot from neuron.egm with snapshot.json DELETED (must never read JSON) ==" +rm -f "$DPOS/snapshot.json" +ENGRAM_STORE=1 "$BIN" pos_reboot "$DPOS" || { echo "FAIL: pos_reboot"; fail=1; } + +echo +echo "== 3) NEGATIVE CONTROL: seed -> activate -> close WITHOUT the field-persist checkpoint ==" +DNEG="$WORK/neg"; mkdir -p "$DNEG" +ENGRAM_STORE=1 "$BIN" neg_seed "$DNEG" || { echo "FAIL: neg_seed"; fail=1; } +rm -f "$DNEG/snapshot.json" +ENGRAM_STORE=1 "$BIN" neg_reboot "$DNEG" || { echo "FAIL: neg_reboot"; fail=1; } + +echo +echo "== 4) assertions (python over the JSON exports) ==" +python3 - "$DPOS" "$DNEG" <<'PY' +import json, sys, os +WM_FLOOR = 0.05 +HEBB_MIN = 1e-6 + +def load(d, name): + with open(os.path.join(d, name)) as f: return json.load(f) + +def node_by_label(g, label): + for n in g["nodes"]: + if n.get("label") == label: return n + return None + +def edge_between(g, a_id, b_id): + for e in g["edges"]: + if e.get("from_id") == a_id and e.get("to_id") == b_id: + return e + return None + +rc = 0 +def check(cond, msg): + global rc + if cond: print(f" PASS: {msg}") + else: print(f" FAIL: {msg}"); rc = 1 + +dpos, dneg = sys.argv[1], sys.argv[2] +pre = load(dpos, "pre_reboot.json") +rebt = load(dpos, "reboot.json") + +pa, pb = node_by_label(pre, "hebb-a"), node_by_label(pre, "hebb-b") +ra = node_by_label(rebt, "hebb-a") +assert pa and pb and ra, "target nodes missing" +pe = edge_between(pre, pa["id"], pb["id"]) +re = edge_between(rebt, pa["id"], pb["id"]) +assert pe and re, "target edge missing" + +pre_hebb = pe.get("hebb", 0.0) +rebt_hebb = re.get("hebb", 0.0) +pre_ac = pa.get("activation_count", 0) +rebt_ac = ra.get("activation_count", 0) +pre_wm = pa.get("working_memory_weight", 0.0) +rebt_wm = ra.get("working_memory_weight", 0.0) + +print(f" edge hebb-a->hebb-b : pre={pre_hebb!r} reboot={rebt_hebb!r}") +print(f" node hebb-a act_cnt : pre={pre_ac!r} reboot={rebt_ac!r}") +print(f" node hebb-a wm : pre={pre_wm!r} reboot={rebt_wm!r} (halved+floored expected)") + +# --- learning actually happened this run (else the test proves nothing) --- +check(pre_hebb > HEBB_MIN, f"activation raised edge hebb above 0 (pre={pre_hebb})") +check(pre_ac >= 1, f"activation reinforced node activation_count (pre={pre_ac})") +check(pre_wm > 0.0, f"activation promoted node to working memory (pre_wm={pre_wm})") + +# --- the load-bearing survival assertions after a real delete-JSON reboot --- +check(abs(rebt_hebb - pre_hebb) < 1e-12, + f"edge hebb SURVIVED reboot unchanged ({rebt_hebb} == {pre_hebb})") +check(rebt_ac == pre_ac, + f"node activation_count SURVIVED reboot unchanged ({rebt_ac} == {pre_ac})") + +# --- WM weight: must equal the JSON path's boot transform exactly (halve+floor) --- +expected_wm = pre_wm * 0.5 +if expected_wm < WM_FLOOR: expected_wm = 0.0 +check(abs(rebt_wm - expected_wm) < 1e-9, + f"node WM weight SURVIVED with the SAME boot transform as JSON path " + f"(reboot={rebt_wm} == halve+floor(pre)={expected_wm})") +check(expected_wm > 0.0, + f"WM survival is observable (halved weight stays above floor: {expected_wm} > {WM_FLOOR})") + +# --- NEGATIVE CONTROL: without the field-persist step the learning is LOST --- +npre = load(dneg, "neg_pre.json") +nrebt = load(dneg, "neg_reboot.json") +na_pre = node_by_label(npre, "hebb-a") +na_rebt = node_by_label(nrebt, "hebb-a") +ne_pre = edge_between(npre, na_pre["id"], node_by_label(npre, "hebb-b")["id"]) +ne_rebt = edge_between(nrebt, na_rebt["id"], node_by_label(nrebt, "hebb-b")["id"]) +print(f" [neg] edge hebb : pre={ne_pre.get('hebb',0.0)!r} reboot={ne_rebt.get('hebb',0.0)!r}") +print(f" [neg] node act_cnt : pre={na_pre.get('activation_count',0)!r} reboot={na_rebt.get('activation_count',0)!r}") +check(ne_pre.get("hebb", 0.0) > HEBB_MIN, + f"[neg] activation DID raise hebb in RAM (pre={ne_pre.get('hebb',0.0)})") +check(ne_rebt.get("hebb", 0.0) == 0.0, + "[neg] WITHOUT checkpoint field-persist, edge hebb is LOST on reboot (==0) — fix is load-bearing") +check(na_rebt.get("activation_count", 0) == 0, + "[neg] WITHOUT checkpoint field-persist, activation_count is LOST on reboot (==0)") + +sys.exit(rc) +PY +[ $? -ne 0 ] && fail=1 + +echo +echo "== 5) ASan+UBSan build, exercise the full persist+reboot flow (leaks off — harness intentionally leaks el_strdup) ==" +SANBIN="$WORK/m35.san" +gcc -O1 -g -std=c11 -fsanitize=address,undefined -fno-sanitize-recover=undefined \ + -I "$INC" "$HERE/test_m35_hebb_persist.c" "$RT" "$ST" -lcurl -o "$SANBIN" 2>"$WORK/san_cc.log" +if [ $? -ne 0 ]; then echo " SAN COMPILE FAILED:"; tail -20 "$WORK/san_cc.log"; fail=1; else + export ASAN_OPTIONS=detect_leaks=0 + DSAN="$WORK/san"; mkdir -p "$DSAN" + ENGRAM_STORE=1 "$SANBIN" pos_seed "$DSAN" >/dev/null 2>"$WORK/san_run.log" && \ + { rm -f "$DSAN/snapshot.json"; ENGRAM_STORE=1 "$SANBIN" pos_reboot "$DSAN" >/dev/null 2>>"$WORK/san_run.log"; } + if grep -qiE 'runtime error|AddressSanitizer|UndefinedBehavior|ERROR: ' "$WORK/san_run.log"; then + echo " FAIL: sanitizer findings:"; grep -iE 'runtime error|Sanitizer|ERROR' "$WORK/san_run.log" | head; fail=1 + else + echo " ok: ASan+UBSan clean across pos_seed/checkpoint/reboot (field-persist, boot laundering)" + fi +fi + +echo +if [ "$fail" -eq 0 ]; then echo "================ M3.5 HEBB-PERSIST GATE: PASS ================"; else echo "================ M3.5 HEBB-PERSIST GATE: FAIL ================"; fi +rm -rf "$WORK" +exit $fail diff --git a/engram/test/test_m35_hebb_persist.c b/engram/test/test_m35_hebb_persist.c new file mode 100644 index 0000000..4aaf9d3 --- /dev/null +++ b/engram/test/test_m35_hebb_persist.c @@ -0,0 +1,130 @@ +/* test_m35_hebb_persist.c — M3.5 PRE-FLIP GATE. + * + * Proves that in-place field mutations made during spreading activation — edge + * `hebb` (+ last_fired), node `activation_count`, node working-memory weight — + * PERSIST to the paged store and survive a restart from neuron.egm with + * snapshot.json deleted. This is the "hebb-survives-restart" fix that gates the + * live cutover. + * + * Same style as test_m3_parity.c: a REAL el-level harness linking the actual + * el_runtime.c native engram builtins + engram_store.c, driving engram_node_full + * / engram_connect / engram_activate_json / engram_save / engram_store_boot / + * engram_store_checkpoint / engram_store_close directly from C. No EL interpreter. + * + * Modes (argv[1]), data dir (argv[2]): + * pos_seed — ENGRAM_STORE=1: fresh store, seed a graph tuned so activation + * co-activates a connected pair (edge hebb 0 -> ETA) and reinforces + * nodes (activation_count 0 -> >=1, WM weight -> >0). Export the + * post-activation resident graph to pre_reboot.json, then CHECKPOINT + * (the M3.5 field-persist), then close. + * pos_reboot— ENGRAM_STORE=1, snapshot.json deleted by runner: boot from + * neuron.egm (WAL replay), export reboot.json, close. The values in + * reboot.json are what actually survived the round-trip. + * neg_seed — identical to pos_seed but WITHOUT the checkpoint field-persist + * (negative control): activation mutations never reach the store. + * neg_reboot— boot from neuron.egm, export neg_reboot.json, close. + * offcheck — ENGRAM_STORE unset: seed+activate+checkpoint must NOT touch the + * store (no neuron.egm, checkpoint returns 0). + * + * The pass/fail assertions live in run_m35_hebb_persist.sh (python over the JSON + * exports): reboot.json must carry the learned hebb / activation_count and the + * JSON-identical halved WM weight; neg_reboot.json must have LOST them. + */ +#include "el_runtime.h" +#include +#include +#include + +extern int engram_store_enabled(void); +extern el_val_t engram_store_boot(el_val_t data_dir); +extern el_val_t engram_store_checkpoint(void); +extern el_val_t engram_store_close(void); + +static el_val_t S(const char* s){ return EL_STR(s); } +static el_val_t F(double d){ return el_from_float(d); } + +/* Two nodes with DISTINCT content (so the redundancy-suppression pass cannot + * dedup one of them away) that both match the query strongly, wired by one + * "associate" edge. A handful of weakly-related distractors make it a real + * graph. On activation both A and B promote to working memory and co-activate, + * so their edge's hebb rises from 0 to ENGRAM_HEBB_ETA. */ +static void build_seed(void){ + el_val_t a = engram_node_full(S("hebbian potentiation strengthens co-active memory links"), + S("Concept"), S("hebb-a"), F(0.9), F(0.85), F(1.0), S("Semantic"), + S("hebbian,memory,activation")); + el_val_t b = engram_node_full(S("co-active memory links accrue hebbian associative weight"), + S("Concept"), S("hebb-b"), F(0.9), F(0.85), F(1.0), S("Semantic"), + S("hebbian,memory,weight")); + el_val_t c = engram_node_full(S("unrelated culinary recipe for sourdough bread"), + S("Fact"), S("distractor-1"), F(0.4), F(0.4), F(1.0), S("Semantic"), + S("food")); + el_val_t d = engram_node_full(S("the weather forecast predicts rain tomorrow afternoon"), + S("Fact"), S("distractor-2"), F(0.4), F(0.4), F(1.0), S("Semantic"), + S("weather")); + engram_connect(a, b, F(0.8), S("associate")); /* the edge under test */ + engram_connect(a, c, F(0.3), S("associate")); + engram_connect(b, d, F(0.3), S("associate")); +} + +static const char* QUERY = + "hebbian potentiation co-active memory links associative weight"; + +static void export_graph(const char* dir, const char* name){ + char p[1024]; + snprintf(p, sizeof p, "%s/%s", dir, name); + if (!engram_save(S(p))){ fprintf(stderr, "save %s failed\n", name); exit(2); } +} + +int main(int argc, char** argv){ + if (argc < 3){ + fprintf(stderr, "usage: %s \n", argv[0]); + return 2; + } + const char* mode = argv[1]; + const char* dir = argv[2]; + + if (!strcmp(mode, "pos_seed") || !strcmp(mode, "neg_seed")){ + int persist = !strcmp(mode, "pos_seed"); + if (!engram_store_enabled()){ fprintf(stderr, "%s requires ENGRAM_STORE=1\n", mode); return 2; } + if (!engram_store_boot(S(dir))){ fprintf(stderr, "store boot failed\n"); return 2; } + build_seed(); + el_val_t act = engram_activate_json(S(QUERY), (el_val_t)3); + (void)act; + /* Capture the post-activation resident state BEFORE persisting/closing. */ + export_graph(dir, persist ? "pre_reboot.json" : "neg_pre.json"); + printf("[%s] nodes=%lld edges=%lld\n", mode, + (long long)(int64_t)engram_node_count(), + (long long)(int64_t)engram_edge_count()); + if (persist){ + if (!engram_store_checkpoint()){ fprintf(stderr, "checkpoint failed\n"); return 2; } + } + /* neg mode: NO field-persist checkpoint. engram_store_close still flushes + * pages, but no store_put_* ran post-creation, so the store keeps the + * pristine creation-time field values (hebb=0, activation_count=0). */ + engram_store_close(); + return 0; + } + if (!strcmp(mode, "pos_reboot") || !strcmp(mode, "neg_reboot")){ + if (!engram_store_enabled()){ fprintf(stderr, "%s requires ENGRAM_STORE=1\n", mode); return 2; } + /* snapshot.json deleted by the runner — boot MUST come from neuron.egm. */ + if (!engram_store_boot(S(dir))){ fprintf(stderr, "reboot boot failed\n"); return 2; } + export_graph(dir, !strcmp(mode, "pos_reboot") ? "reboot.json" : "neg_reboot.json"); + printf("[%s] nodes=%lld edges=%lld\n", mode, + (long long)(int64_t)engram_node_count(), + (long long)(int64_t)engram_edge_count()); + engram_store_close(); + return 0; + } + if (!strcmp(mode, "offcheck")){ + int en = engram_store_enabled(); + el_val_t boot = engram_store_boot(S(dir)); /* no-op with flag off */ + build_seed(); + engram_activate_json(S(QUERY), (el_val_t)3); + el_val_t ck = engram_store_checkpoint(); /* must be a no-op */ + printf("[offcheck] enabled=%d boot=%lld checkpoint=%lld\n", + en, (long long)(int64_t)boot, (long long)(int64_t)ck); + return (en == 0 && (int64_t)boot == 0 && (int64_t)ck == 0) ? 0 : 1; + } + fprintf(stderr, "unknown mode %s\n", mode); + return 2; +} diff --git a/engram/test/test_m3_parity.c b/engram/test/test_m3_parity.c index bd474ba..da3db49 100644 --- a/engram/test/test_m3_parity.c +++ b/engram/test/test_m3_parity.c @@ -115,12 +115,19 @@ int main(int argc, char** argv){ if (!engram_store_boot(S(dir))){ fprintf(stderr, "store boot failed\n"); return 2; } snprintf(p, sizeof p, "%s/on_graph.json", dir); engram_save(S(p)); /* export resident (== store) */ + /* Checkpoint the freshly-imported (pristine) graph — this is the state + * the reboot comparison expects to round-trip. Under M3.5 a checkpoint + * persists the resident graph's CURRENT field state, so it must run + * BEFORE activation mutates fields in place; activation itself is + * exercised below only for the activation-result-set parity check. The + * M3.5 gate (test_m35_hebb_persist) separately proves that a checkpoint + * taken AFTER activation durably carries the learned hebb/WM state. */ + engram_store_checkpoint(); el_val_t act = engram_activate_json(S(QUERY), (el_val_t)3); snprintf(p, sizeof p, "%s/on_act.json", dir); write_file(p, EL_CSTR(act)); printf("[on] nodes=%lld edges=%lld\n", (long long)(int64_t)engram_node_count(), (long long)(int64_t)engram_edge_count()); - engram_store_checkpoint(); engram_store_close(); return 0; } diff --git a/lang/runtime/el_runtime.c b/lang/runtime/el_runtime.c index b9ef5de..ed89f69 100644 --- a/lang/runtime/el_runtime.c +++ b/lang/runtime/el_runtime.c @@ -7339,8 +7339,10 @@ static void eg_store_put_edge(const EngramEdge* e) { } /* Resident-load callbacks: StoreNode/StoreEdge → a fresh EngramNode/EngramEdge - * appended to the in-RAM graph. Mirrors engram_load's field set (minus the - * boot-time WM laundering — the store already holds the authoritative weights). */ + * appended to the in-RAM graph. Mirrors engram_load's field set. The boot-time + * WM laundering (halve + floor + global cap) that engram_load applies is done + * once, after all nodes are loaded, in engram_store_boot — see the block there — + * so the store-on boot behaves byte-identically to the JSON path (M3.5 parity). */ static void eg_load_node_cb(const StoreNode* sn, void* ctx) { EngramStore* g = (EngramStore*)ctx; engram_grow_nodes(); @@ -7427,6 +7429,10 @@ static void eg_reset_resident(EngramStore* g) { engram_adj_free(g); } +/* Defined later with engram_load; declared here for the boot-time WM laundering + * that keeps the store-on boot byte-identical to the JSON path (M3.5 parity). */ +static void eg_enforce_wm_cap_on_load(EngramStore* g); + /* engram_store_boot(data_dir) — open (import-once or WAL-replay) the durable * paged store and load it whole into RAM (Phase 1). No-op / returns 0 when the * flag is off. Returns 1 on success. Idempotent (a second call is a no-op). */ @@ -7446,14 +7452,60 @@ el_val_t engram_store_boot(el_val_t data_dir) { for (size_t i = 0; i < ln; i++) eg_load_layer_cb(g, &ls[i]); store_layers_free(ls, ln); } + /* Boot-time WM laundering — MUST match engram_load exactly (M3.5 parity). + * The JSON load path halves every persisted working_memory_weight on boot + * (stale pinned weights decay out over successive restarts; genuine WM state + * keeps continuity) and floors sub-ENGRAM_WM_FLOOR residue to zero, then + * enforces the global WM cap. The store now persists post-activation WM + * weights, so the store-on boot must apply the identical transform or the two + * persistence paths would diverge on the very first restart. */ + for (int64_t i = 0; i < g->node_count; i++) { + g->nodes[i].working_memory_weight *= 0.5; + if (g->nodes[i].working_memory_weight < ENGRAM_WM_FLOOR) + g->nodes[i].working_memory_weight = 0.0; + } + eg_enforce_wm_cap_on_load(g); g->adj_dirty = 1; return (el_val_t)1; } -/* engram_store_checkpoint() — flush dirty pages + advance the checkpoint LSN. +/* engram_store_checkpoint() — M3.5 PRE-FLIP GATE. + * + * Spreading activation mutates fields IN PLACE on the resident graph — edge + * `hebb`/`last_fired` (potentiation + homeostatic scaling), node + * `activation_count`/`last_activated`/`working_memory_weight`/`wm_anchor` + * (reinforcement + WM caps) — and also FORMS brand-new `hebbian-associate` + * edges. M3 only mirrored node/edge *creates* and *forgets*; none of those + * in-place mutations or activation-formed edges reached the paged store, so + * learned associations were lost on every restart. This is the fix that makes + * "learned edges survive a restart" true, and it gates the live cutover. + * + * On the soul's save/checkpoint path we push the resident graph's current field + * state through the store's WAL-logged API, then checkpoint: + * - store_put_node(n) for every node → persists WM weight, activation_count, + * last_activated, wm_anchor, the base-level access ring, etc. + * - store_put_edge(e) for every edge → persists hebb + last_fired AND creates + * any activation-formed edges. (store_hebb_batch is deliberately NOT used: it + * is a delta-only op that skips edge ids not already resident in the store — + * see apply_hebb_batch — so it cannot persist the newly-formed hebbian edges + * that are the whole point of this milestone. store_put_edge is the idempotent + * upsert that subsumes the hebb delta.) + * then engram_checkpoint flushes dirty pages + advances the checkpoint LSN. Every + * push is a WAL record, so a graceful restart restores them. + * + * Approach: a FULL WALK of the resident graph (not a dirty-set). At Phase-1 + * ~64 MB resident this is a cheap linear pass on an already-in-RAM array, run at + * the soul's save cadence (seconds-to-minutes), and it is trivially complete — + * no mutation site can be missed and no separate new-edge tracking is needed. An + * inter-checkpoint crash loses only the most-recent unsaved learning, exactly the + * same durability envelope as today's JSON-snapshot cadence. + * * The store→JSON export path stays engram_save (the JSON is an export artifact). */ el_val_t engram_store_checkpoint(void) { if (!engram_store_enabled() || !g_engram_store) return (el_val_t)0; + EngramStore* g = engram_get(); + for (int64_t i = 0; i < g->node_count; i++) eg_store_put_node(&g->nodes[i]); + for (int64_t i = 0; i < g->edge_count; i++) eg_store_put_edge(&g->edges[i]); return (el_val_t)(int64_t)(engram_checkpoint(g_engram_store) == 0 ? 1 : 0); } From bb64a236ed9d2906d3bfaa41638848ea93897a26 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Wed, 12 Aug 2026 14:14:20 -0500 Subject: [PATCH 25/26] engram tiered storage: engram-service wiring + elc fold-hang fix + prune-store mirror MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Wire paged store into the ENGRAM SERVICE (server.el, the authoritative durable owner): boot->engram_store_boot, persist_canonical->engram_store_checkpoint, gated by ENGRAM_STORE. - elc (lang/elc.c + src/parser.el + codegen.el + elc-combined.el): OOB guard in tok_kind/tok_value + parse_block progress backstop — fixes the pre-existing unbounded-memory fold hang on sessions.el. - engram_prune_telemetry mirrors ISE prune to the store (store_forget) so store live-count tracks resident and stale telemetry stays bounded. - Deployed live 2026-08-12: engram :8742 on neuron.egm+WAL, count reconciled 11552. --- engram/src/server.el | 72 ++++++++++++++------- lang/el-compiler/src/codegen.el | 63 ++++++++++++++++++- lang/el-compiler/src/parser.el | 24 +++++++ lang/elc-combined.el | 3 + lang/elc.c | 107 +++++++++++++++++++++++++++++++- lang/runtime/el_runtime.c | 13 ++++ lang/runtime/el_runtime.h | 7 +++ 7 files changed, 263 insertions(+), 26 deletions(-) diff --git a/engram/src/server.el b/engram/src/server.el index c9bc036..06d4d40 100644 --- a/engram/src/server.el +++ b/engram/src/server.el @@ -117,6 +117,17 @@ fn route_text_health(method: String, path: String, body: String) -> String { // save/load with no "path" hit engram_save(""). Rewritten to the // `let x = if cond { a } else { b }` expression form (the pattern the newer // routes route_emit_ise/route_capture_knowledge already use correctly). +// store_on — ENGRAM_STORE flag (tiered paged store as the durable owner). Matches +// engram_store_enabled() in el_runtime.c EXACTLY (1 / on / true). Default off → +// every persistence path below is byte-for-byte the historical snapshot behavior. +fn store_on() -> Bool { + let v: String = env("ENGRAM_STORE") + if str_eq(v, "1") { return true } + if str_eq(v, "on") { return true } + if str_eq(v, "true") { return true } + return false +} + // persist_canonical — save the canonical snapshot after a durable write. // // WHY (2026-07-22 self-review): the 2026-07-21 fix correctly stopped READ @@ -131,6 +142,14 @@ fn route_text_health(method: String, path: String, body: String) -> String { // tolerant, ~2/min — snapshotting the whole store per heartbeat is waste; // any durable write that follows persists the pruning too). fn persist_canonical() -> Int { + // ENGRAM_STORE: the paged store is the durable owner — a checkpoint flushes + // dirty pages behind a WAL-durable record (durable the moment the WAL fsyncs). + // This is the fix for the "restart reverted to a 17h-old snapshot" data loss: + // durable writes no longer depend on a full snapshot.json rewrite. Returns 1 + // on a successful checkpoint, 0 otherwise. Flag-off: unchanged (writes JSON). + if store_on() { + return engram_store_checkpoint() + } let dir_raw: String = env("ENGRAM_DATA_DIR") let dir: String = engram_resolve_data_dir() // (2026-08-10 self-review) This returned a hardcoded 1, which made every @@ -798,29 +817,40 @@ let port: Int = parse_port(bind_str) // never /tmp; fail loud if HOME is unresolvable (engram_resolve_data_dir exits). let data_dir: String = engram_resolve_data_dir() let snapshot_path: String = data_dir + "/snapshot.json" -engram_load(snapshot_path) +// ENGRAM_STORE (tiered paged store — engram-tiered-storage-engine.md). When set, +// the durable owner is the paged store (neuron.egm + neuron.wal): engram_store_boot +// imports snapshot.json ONCE into a fresh neuron.egm, else replays the WAL and loads +// the store resident — snapshot.json is never read again as the ongoing store. This +// closes the "restart reverted to a 17h-old snapshot" data-loss window. Flag-off +// (default): byte-for-byte the historical snapshot + optional-WAL boot below. +if store_on() { + engram_store_boot(data_dir) + println("[engram] ENGRAM_STORE enabled — tiered paged store is the durable owner") +} else { + engram_load(snapshot_path) -// WAL replay (design doc §6). Gated: default OFF is byte-identical to legacy -// snapshot-only boot. When ON, the snapshot above is the compaction BASE and -// the WAL carries every mutation since; replay reconstructs state to the last -// CRC-valid record, then opens the WAL for appending. -if wal_on() { - let replayed: Int = engram_wal_boot(data_dir) - println("[engram] WAL enabled — replayed " + int_to_str(replayed) + " records") -} + // WAL replay (design doc §6). Gated: default OFF is byte-identical to legacy + // snapshot-only boot. When ON, the snapshot above is the compaction BASE and + // the WAL carries every mutation since; replay reconstructs state to the last + // CRC-valid record, then opens the WAL for appending. + if wal_on() { + let replayed: Int = engram_wal_boot(data_dir) + println("[engram] WAL enabled — replayed " + int_to_str(replayed) + " records") + } -// 2026-07-21 self-review boot guard: if the snapshot file has content but the -// load produced 0 nodes, something is wrong (corrupt file / parse failure). -// Preserve the evidence and warn loudly — and since read routes no longer write -// the canonical path, a bad boot can no longer clobber the good snapshot. -let boot_snap: String = fs_read(snapshot_path) -if !str_eq(boot_snap, "") { - if engram_node_count() == 0 { - println("[engram] WARNING: snapshot.json is non-empty but load produced 0 nodes — preserving copy at snapshot.failed-load.json") - fs_write(data_dir + "/snapshot.failed-load.json", boot_snap) - } else { - // Good load: keep a boot-time backup of the snapshot as loaded. - fs_write(data_dir + "/snapshot.boot-backup.json", boot_snap) + // 2026-07-21 self-review boot guard: if the snapshot file has content but the + // load produced 0 nodes, something is wrong (corrupt file / parse failure). + // Preserve the evidence and warn loudly — and since read routes no longer write + // the canonical path, a bad boot can no longer clobber the good snapshot. + let boot_snap: String = fs_read(snapshot_path) + if !str_eq(boot_snap, "") { + if engram_node_count() == 0 { + println("[engram] WARNING: snapshot.json is non-empty but load produced 0 nodes — preserving copy at snapshot.failed-load.json") + fs_write(data_dir + "/snapshot.failed-load.json", boot_snap) + } else { + // Good load: keep a boot-time backup of the snapshot as loaded. + fs_write(data_dir + "/snapshot.boot-backup.json", boot_snap) + } } } diff --git a/lang/el-compiler/src/codegen.el b/lang/el-compiler/src/codegen.el index 917fb31..f6290dd 100644 --- a/lang/el-compiler/src/codegen.el +++ b/lang/el-compiler/src/codegen.el @@ -1292,6 +1292,43 @@ fn next_if_id() -> String { native_int_to_str(n) } +// is_void_builtin — true for runtime builtins declared `void` in el_runtime.h. +// User `-> Void` functions are emitted as el_val_t (return 0) so they are safe +// to assign; only these C-level void builtins are not. +fn is_void_builtin(name: String) -> Bool { + if str_eq(name, "println") { return true } + if str_eq(name, "print") { return true } + if str_eq(name, "engram_strengthen") { return true } + if str_eq(name, "engram_forget") { return true } + if str_eq(name, "engram_connect") { return true } + if str_eq(name, "dharma_emit") { return true } + if str_eq(name, "dharma_strengthen") { return true } + if str_eq(name, "llm_register_tool") { return true } + if str_eq(name, "exit_program") { return true } + if str_eq(name, "http_serve") { return true } + if str_eq(name, "http_set_handler") { return true } + if str_eq(name, "http_serve_async") { return true } + if str_eq(name, "el_cgi_init") { return true } + if str_eq(name, "el_retain") { return true } + if str_eq(name, "el_release") { return true } + false +} + +// cg_expr_is_void — true if `val` is a direct call to a void builtin, so the +// if-expression arm must emit it as a bare statement rather than assigning its +// (nonexistent) value to the result var. +fn cg_expr_is_void(val: Map) -> Bool { + let vk: String = val["expr"] + if str_eq(vk, "Call") { + let f = val["func"] + let fk: String = f["expr"] + if str_eq(fk, "Ident") { + return is_void_builtin(f["name"]) + } + } + false +} + // Render a single arm of the if-as-expression: emit each statement-before-last // as a side-effecting expression, then assign the final Expr's value to the // result var. If the arm body is empty or its last stmt isn't an Expr, the @@ -1300,6 +1337,10 @@ fn cg_if_expr_arm(stmts: [Map], result_var: String) -> String { let n: Int = native_list_len(stmts) // Collect statement fragments into a list to avoid O(n-) string growth. let parts: [String] = native_list_empty() + // Track names already declared in this arm's C block. El permits `let x` + // to redeclare/rebind x in the same scope, but C forbids redeclaring the + // same name in one block: emit `el_val_t x = ...` first, `x = ...` after. + let declared: [String] = native_list_empty() let i = 0 while i < n { let s = native_list_get(stmts, i) @@ -1310,18 +1351,31 @@ fn cg_if_expr_arm(stmts: [Map], result_var: String) -> String { let name: String = s["name"] let val = s["value"] let val_c: String = cg_expr(val) - let parts = native_list_append(parts, "el_val_t " + name + " = " + val_c + "; ") + if list_contains(declared, name) { + let parts = native_list_append(parts, name + " = " + val_c + "; ") + } else { + let declared = native_list_append(declared, name) + let parts = native_list_append(parts, "el_val_t " + name + " = " + val_c + "; ") + } } else { if str_eq(sk, "Return") { let val = s["value"] let val_c: String = cg_expr(val) - let parts = native_list_append(parts, result_var + " = (" + val_c + "); ") + if cg_expr_is_void(val) { + let parts = native_list_append(parts, val_c + "; ") + } else { + let parts = native_list_append(parts, result_var + " = (" + val_c + "); ") + } } else { if str_eq(sk, "Expr") { let val = s["value"] let val_c: String = cg_expr(val) if is_last { - let parts = native_list_append(parts, result_var + " = (" + val_c + "); ") + if cg_expr_is_void(val) { + let parts = native_list_append(parts, val_c + "; ") + } else { + let parts = native_list_append(parts, result_var + " = (" + val_c + "); ") + } } else { let parts = native_list_append(parts, "(void)(" + val_c + "); ") } @@ -2669,6 +2723,9 @@ fn builtin_arity(name: String) -> Int { if str_eq(name, "engram_activate") { return 2 } if str_eq(name, "engram_save") { return 1 } if str_eq(name, "engram_load") { return 1 } + if str_eq(name, "engram_store_boot") { return 1 } + if str_eq(name, "engram_store_checkpoint") { return 0 } + if str_eq(name, "engram_store_close") { return 0 } if str_eq(name, "engram_get_node_json") { return 1 } if str_eq(name, "engram_search_json") { return 2 } if str_eq(name, "engram_scan_nodes_json") { return 2 } diff --git a/lang/el-compiler/src/parser.el b/lang/el-compiler/src/parser.el index d93fcba..a064bad 100644 --- a/lang/el-compiler/src/parser.el +++ b/lang/el-compiler/src/parser.el @@ -49,6 +49,21 @@ fn tok_value(tokens: [Any], pos: Int) -> String { native_list_get(tokens, pos * 2 + 1) } +// parse_progress_fatal — robustness backstop. Called by the token-consuming +// driver loops when they detect they have iterated more times than there are +// tokens (impossible for a well-formed program, where every iteration consumes +// at least one token). Names the offending token and exits non-zero instead of +// looping forever / exhausting memory. +fn parse_progress_fatal(where: String, tokens: [Any], pos: Int) -> Void { + let k: String = tok_kind(tokens, pos) + let v: String = tok_value(tokens, pos) + println("elc: FATAL: parser made no forward progress in " + where + + " at token index " + native_int_to_str(pos) + " (kind=" + k + ")") + println("elc: likely a malformed construct near '" + v + + "' — e.g. an unterminated string or an unescaped double-quote inside a string literal (use \\\" ).") + exit(1) +} + fn expect(tokens: [Any], pos: Int, kind: String) -> Int { let k = tok_kind(tokens, pos) if k == kind { @@ -1212,7 +1227,16 @@ fn parse_block(tokens: [Any], pos: Int) -> Map { let p = expect(tokens, pos, "LBrace") let stmts: [Map] = native_list_empty() let running = true + // Runaway backstop: a block can hold at most (token count) statements, since + // every iteration consumes >= 1 token. If we exceed that, the cursor has run + // off the end without terminating (malformed input) -> fail fast, don't hang. + let blk_total: Int = native_list_len(tokens) / 2 + let blk_iters: Int = 0 while running { + let blk_iters = blk_iters + 1 + if blk_iters > blk_total + 8 { + parse_progress_fatal("parse_block", tokens, p) + } let k = tok_kind(tokens, p) if k == "RBrace" { let running = false diff --git a/lang/elc-combined.el b/lang/elc-combined.el index 3216641..295e062 100644 --- a/lang/elc-combined.el +++ b/lang/elc-combined.el @@ -3797,6 +3797,9 @@ fn builtin_arity(name: String) -> Int { if str_eq(name, "engram_activate") { return 2 } if str_eq(name, "engram_save") { return 1 } if str_eq(name, "engram_load") { return 1 } + if str_eq(name, "engram_store_boot") { return 1 } + if str_eq(name, "engram_store_checkpoint") { return 0 } + if str_eq(name, "engram_store_close") { return 0 } if str_eq(name, "engram_get_node_json") { return 1 } if str_eq(name, "engram_search_json") { return 2 } if str_eq(name, "engram_scan_nodes_json") { return 2 } diff --git a/lang/elc.c b/lang/elc.c index 5104d13..865c5ec 100644 --- a/lang/elc.c +++ b/lang/elc.c @@ -1423,15 +1423,53 @@ el_val_t tok_at(el_val_t tokens, el_val_t pos) { } el_val_t tok_kind(el_val_t tokens, el_val_t pos) { + /* Out-of-range reads MUST report the Eof sentinel so every `== "Eof"` + termination guard in the parser fires. Without this, reading past the + trailing Eof token returns runtime null (native_list_get OOB -> 0), which + matches no delimiter, letting inner parse loops (parse_block, parse_binop) + append AST nodes forever on malformed input -> unbounded allocation -> OOM. */ + el_val_t n = (native_list_len(tokens) / 2); + if (pos < 0) { + return EL_STR("Eof"); + } + if (pos >= n) { + return EL_STR("Eof"); + } return native_list_get(tokens, (pos * 2)); return 0; } el_val_t tok_value(el_val_t tokens, el_val_t pos) { + el_val_t n = (native_list_len(tokens) / 2); + if (pos < 0) { + return EL_STR(""); + } + if (pos >= n) { + return EL_STR(""); + } return native_list_get(tokens, ((pos * 2) + 1)); return 0; } +/* parse_progress_fatal — robustness backstop. Called by the token-consuming + driver loops when they detect they have iterated more times than there are + tokens (an impossibility for a well-formed program, where every iteration + consumes at least one token). Names the offending token and exits non-zero + instead of looping forever / exhausting memory. */ +el_val_t parse_progress_fatal(el_val_t where, el_val_t tokens, el_val_t pos) { + el_val_t k = tok_kind(tokens, pos); + el_val_t v = tok_value(tokens, pos); + println(el_str_concat(el_str_concat(el_str_concat(el_str_concat( + EL_STR("elc: FATAL: parser made no forward progress in "), where), + EL_STR(" at token index ")), native_int_to_str(pos)), + el_str_concat(EL_STR(" (kind="), el_str_concat(k, EL_STR(")"))))); + println(el_str_concat(el_str_concat( + EL_STR("elc: likely a malformed construct near '"), v), + EL_STR("' — e.g. an unterminated string or an unescaped double-quote inside a string literal (use \\\" )."))); + exit(1); + return 0; +} + el_val_t expect(el_val_t tokens, el_val_t pos, el_val_t kind) { el_val_t k = tok_kind(tokens, pos); if (str_eq(k, kind)) { @@ -2689,7 +2727,16 @@ el_val_t parse_block(el_val_t tokens, el_val_t pos) { el_val_t p = expect(tokens, pos, EL_STR("LBrace")); el_val_t stmts = native_list_empty(); el_val_t running = 1; + /* Runaway backstop: a block can hold at most (token count) statements, since + every iteration consumes >= 1 token. If we exceed that, the cursor has run + off the end without terminating (malformed input) -> fail fast, don't hang. */ + el_val_t __blk_total = (native_list_len(tokens) / 2); + el_val_t __blk_iters = 0; while (running) { + __blk_iters = (__blk_iters + 1); + if (__blk_iters > (__blk_total + 8)) { + parse_progress_fatal(EL_STR("parse_block"), tokens, p); + } el_val_t k = tok_kind(tokens, p); if (str_eq(k, EL_STR("RBrace"))) { running = 0; @@ -4838,9 +4885,51 @@ el_val_t next_if_id(void) { return 0; } +/* is_void_builtin — true for runtime builtins declared `void` in el_runtime.h. + User `-> Void` functions are emitted as el_val_t (return 0) so they are safe + to assign; only these C-level void builtins are not. */ +el_val_t is_void_builtin(el_val_t name) { + if (str_eq(name, EL_STR("println"))) { return 1; } + if (str_eq(name, EL_STR("print"))) { return 1; } + if (str_eq(name, EL_STR("engram_strengthen"))) { return 1; } + if (str_eq(name, EL_STR("engram_forget"))) { return 1; } + if (str_eq(name, EL_STR("engram_connect"))) { return 1; } + if (str_eq(name, EL_STR("dharma_emit"))) { return 1; } + if (str_eq(name, EL_STR("dharma_strengthen"))) { return 1; } + if (str_eq(name, EL_STR("llm_register_tool"))) { return 1; } + if (str_eq(name, EL_STR("exit_program"))) { return 1; } + if (str_eq(name, EL_STR("http_serve"))) { return 1; } + if (str_eq(name, EL_STR("http_set_handler"))) { return 1; } + if (str_eq(name, EL_STR("http_serve_async"))) { return 1; } + if (str_eq(name, EL_STR("el_cgi_init"))) { return 1; } + if (str_eq(name, EL_STR("el_retain"))) { return 1; } + if (str_eq(name, EL_STR("el_release"))) { return 1; } + return 0; +} + +/* cg_expr_is_void — true if `val` is a direct call to a void builtin, so the + if-expression arm must emit it as a bare statement rather than assigning its + (nonexistent) value to the result var. */ +el_val_t cg_expr_is_void(el_val_t val) { + el_val_t vk = el_get_field(val, EL_STR("expr")); + if (str_eq(vk, EL_STR("Call"))) { + el_val_t f = el_get_field(val, EL_STR("func")); + el_val_t fk = el_get_field(f, EL_STR("expr")); + if (str_eq(fk, EL_STR("Ident"))) { + return is_void_builtin(el_get_field(f, EL_STR("name"))); + } + } + return 0; +} + el_val_t cg_if_expr_arm(el_val_t stmts, el_val_t result_var) { el_val_t n = native_list_len(stmts); el_val_t parts = native_list_empty(); + /* Track names already declared in this arm's C block. El permits `let x` + to redeclare/rebind x in the same scope, but C forbids redeclaring the + same name in one block. Emit `el_val_t x = ...` the first time and a + plain `x = ...` reassignment thereafter (mirrors cg_stmt's `declared`). */ + el_val_t declared = native_list_empty(); el_val_t i = 0; while (i < n) { el_val_t s = native_list_get(stmts, i); @@ -4853,18 +4942,31 @@ el_val_t cg_if_expr_arm(el_val_t stmts, el_val_t result_var) { el_val_t name = el_get_field(s, EL_STR("name")); el_val_t val = el_get_field(s, EL_STR("value")); el_val_t val_c = cg_expr(val); - parts = native_list_append(parts, el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("el_val_t "), name), EL_STR(" = ")), val_c), EL_STR("; "))); + if (list_contains(declared, name)) { + parts = native_list_append(parts, el_str_concat(el_str_concat(el_str_concat(name, EL_STR(" = ")), val_c), EL_STR("; "))); + } else { + declared = native_list_append(declared, name); + parts = native_list_append(parts, el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("el_val_t "), name), EL_STR(" = ")), val_c), EL_STR("; "))); + } } else { if (str_eq(sk, EL_STR("Return"))) { el_val_t val = el_get_field(s, EL_STR("value")); el_val_t val_c = cg_expr(val); - parts = native_list_append(parts, el_str_concat(el_str_concat(el_str_concat(result_var, EL_STR(" = (")), val_c), EL_STR("); "))); + if (cg_expr_is_void(val)) { + parts = native_list_append(parts, el_str_concat(val_c, EL_STR("; "))); + } else { + parts = native_list_append(parts, el_str_concat(el_str_concat(el_str_concat(result_var, EL_STR(" = (")), val_c), EL_STR("); "))); + } } else { if (str_eq(sk, EL_STR("Expr"))) { el_val_t val = el_get_field(s, EL_STR("value")); el_val_t val_c = cg_expr(val); if (is_last) { + if (cg_expr_is_void(val)) { + parts = native_list_append(parts, el_str_concat(val_c, EL_STR("; "))); + } else { parts = native_list_append(parts, el_str_concat(el_str_concat(el_str_concat(result_var, EL_STR(" = (")), val_c), EL_STR("); "))); + } } else { parts = native_list_append(parts, el_str_concat(el_str_concat(EL_STR("(void)("), val_c), EL_STR("); "))); } @@ -4883,6 +4985,7 @@ el_val_t cg_if_expr_arm(el_val_t stmts, el_val_t result_var) { } el_val_t result = str_join(parts, EL_STR("")); el_release(parts); + el_release(declared); return result; return 0; } diff --git a/lang/runtime/el_runtime.c b/lang/runtime/el_runtime.c index ed89f69..e3a2de5 100644 --- a/lang/runtime/el_runtime.c +++ b/lang/runtime/el_runtime.c @@ -8038,6 +8038,19 @@ el_val_t engram_prune_telemetry(el_val_t older_than_ms) { g->edge_count = ew; free(set); } + /* Mirror the telemetry prune into the durable paged store so its live + * count tracks the resident graph and stale ISE telemetry stays bounded + * in the store too. Without this, the resident graph GCs old ISE from RAM + * (node_count drops) while the store retains them (count diverges + the + * store re-accumulates the very telemetry bloat this prune was written to + * stop). Matches engram_forget's store_forget mirror. Done before the ids + * are freed below. */ + if (engram_store_enabled() && g_engram_store) { + for (int64_t i = 0; i < removed; i++) { + store_forget(g_engram_store, removed_ids[i]); + } + } + for (int64_t i = 0; i < removed; i++) free(removed_ids[i]); free(removed_ids); diff --git a/lang/runtime/el_runtime.h b/lang/runtime/el_runtime.h index 2c07b31..0380327 100644 --- a/lang/runtime/el_runtime.h +++ b/lang/runtime/el_runtime.h @@ -605,6 +605,13 @@ el_val_t engram_edge_count(void); el_val_t engram_activate(el_val_t query, el_val_t depth); el_val_t engram_save(el_val_t path); el_val_t engram_load(el_val_t path); +/* Tiered paged-store entry points (ENGRAM_STORE=1). engram_store_boot opens the + * durable store (import-once / WAL-replay) and loads it resident; checkpoint pushes + * the resident graph's current field state (incl. learned hebb + activation-formed + * edges) through the WAL and flushes; close checkpoints + closes. No-ops when off. */ +el_val_t engram_store_boot(el_val_t data_dir); +el_val_t engram_store_checkpoint(void); +el_val_t engram_store_close(void); /* JSON-string accessors — return pre-serialized JSON so HTTP handlers * can pass results straight through without round-tripping ElList/ElMap From ee7142373220c1a51d79ad86329240f9646fb3c5 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Wed, 12 Aug 2026 14:22:25 -0500 Subject: [PATCH 26/26] ci: publish + link engram_store.{c,h} so official builds are store-enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The live engram now runs the paged store (neuron.egm+WAL), but the SDK release publishes only el_runtime.{c,h} and the engram build links only el_runtime.c — so a future official release would silently revert to the in-memory store. Publish engram_store.{c,h} as SDK release assets and add them to the engram build's download + cc link so the store transition cannot regress. --- .gitea/workflows/sdk-release.yaml | 4 ++++ engram/.gitea/workflows/engram-release.yaml | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/.gitea/workflows/sdk-release.yaml b/.gitea/workflows/sdk-release.yaml index 6475e63..1d14870 100644 --- a/.gitea/workflows/sdk-release.yaml +++ b/.gitea/workflows/sdk-release.yaml @@ -218,6 +218,8 @@ jobs: cp lang/dist/bin/epm dist/sdk/bin/epm cp lang/runtime/el_runtime.c dist/sdk/runtime/ cp lang/runtime/el_runtime.h dist/sdk/runtime/ + cp lang/runtime/engram_store.c dist/sdk/runtime/ + cp lang/runtime/engram_store.h dist/sdk/runtime/ cp lang/runtime/*.el dist/sdk/runtime/ tar -czf dist/el-sdk-latest.tar.gz -C dist/sdk . echo "SDK tarball bundled: dist/el-sdk-latest.tar.gz" @@ -276,6 +278,8 @@ jobs: upload_asset lang/dist/platform/elc elc upload_asset lang/runtime/el_runtime.c el_runtime.c upload_asset lang/runtime/el_runtime.h el_runtime.h + upload_asset lang/runtime/engram_store.c engram_store.c + upload_asset lang/runtime/engram_store.h engram_store.h # SDK bundle and installer binary upload_asset dist/el-sdk-latest.tar.gz el-sdk-latest.tar.gz diff --git a/engram/.gitea/workflows/engram-release.yaml b/engram/.gitea/workflows/engram-release.yaml index bdf3258..ffe0e50 100644 --- a/engram/.gitea/workflows/engram-release.yaml +++ b/engram/.gitea/workflows/engram-release.yaml @@ -49,6 +49,12 @@ jobs: echo "Downloading el_runtime.h..." curl -fsSL "${RELEASE_BASE}/el_runtime.h" -o /usr/local/lib/el/el_runtime.h + echo "Downloading engram_store.c..." + curl -fsSL "${RELEASE_BASE}/engram_store.c" -o /usr/local/lib/el/engram_store.c + + echo "Downloading engram_store.h..." + curl -fsSL "${RELEASE_BASE}/engram_store.h" -o /usr/local/lib/el/engram_store.h + echo "El SDK installed:" elc --version || true @@ -67,6 +73,7 @@ jobs: -o dist/engram \ dist/engram.c \ /usr/local/lib/el/el_runtime.c \ + /usr/local/lib/el/engram_store.c \ -lcurl -lpthread echo "Linked dist/engram" ls -lh dist/engram