From 67d90d90a498c7ac08758613e2fe4c3b97fa9a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=93=B8=E6=B8=8A=20ICE-P-ZY001?= Date: Mon, 19 Oct 2026 21:27:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=85=A5=E5=8F=97=E9=99=90=E5=8E=9F?= =?UTF-8?q?=E7=94=9F=E5=8F=AA=E8=AF=BB=E5=8A=A9=E6=89=8B=E5=B9=B6=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=9D=A5=E6=BA=90=E7=89=A9=E7=90=86=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E6=A0=B8=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CURRENT.json | 29 +++++++++++++++++------------ MANIFEST.json | 25 +++++++++++++++---------- entry-data.json | 2 +- release.zip | Bin 19157 -> 21714 bytes runtime/question.mjs | 3 ++- runtime/question.test.mjs | 6 ++++++ runtime/server.cjs | 4 +++- runtime/worker.mjs | 16 ++++++++++++++++ scripts/build-release.py | 2 +- 9 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 runtime/worker.mjs diff --git a/CURRENT.json b/CURRENT.json index ac37ba7..98f4449 100644 --- a/CURRENT.json +++ b/CURRENT.json @@ -1,7 +1,7 @@ { "schema": "guanghu.public-rule-release/v1", "world_id": "GLW-2.0-0001", - "version": "20261019.1", + "version": "20261019.2", "scope": "PUBLIC_ENTRY_RULES_SKILLS_AND_QUESTION_TRANSPORT_ONLY", "files": [ { @@ -11,7 +11,7 @@ }, { "path": "entry-data.json", - "sha256": "1194b1c532fdd524b4b4e9c36b478208f04b4d0e2733cd7f8a8284989796b60e", + "sha256": "ac4ad712860afab42a0f920e63c09811d9e197be9ea8577c7f4c4a7b3f3a377a", "bytes": 2082 }, { @@ -26,28 +26,33 @@ }, { "path": "runtime/question.mjs", - "sha256": "6d570aef1920a27a7179f99662780971cdb11b03dbf7a96115bdada8405c0d75", - "bytes": 6128 + "sha256": "c274c5e497fd05084bf9ce53d8ec28ea57eb71831944369e9cee67e4a0bc0a2a", + "bytes": 6307 }, { "path": "runtime/question.test.mjs", - "sha256": "16c29da700a0e84db54a343ec4a1c8db664890e07a5836d6fc141205340389e3", - "bytes": 1534 + "sha256": "6a17a016ae062a1e9e3a355ebf171c44adee1b41842bf7e97b034fbf22642fd1", + "bytes": 3052 }, { "path": "runtime/server.cjs", - "sha256": "d63f6c6cdbdfe7bc6abb0ff36dc6374caf3610c159b2a330c199ece2bc3178fe", - "bytes": 11353 + "sha256": "30e539a5cbdd12af68c352633fcd8c6f7698de3b29c460e903810917c29b5966", + "bytes": 11973 }, { "path": "runtime/server.test.cjs", "sha256": "93c7b8337b9aa5d8529e557006def17798f6345fdbeb271f2025b675202ff896", "bytes": 4065 }, + { + "path": "runtime/worker.mjs", + "sha256": "260c93d8cf67d172d0c1c04abea891b6f2d4fc8366901e3915b8c517702c6c10", + "bytes": 2859 + }, { "path": "scripts/build-release.py", - "sha256": "fcb66f6e27984b84e0276490b95f88c7c4340af2f90a4eda605a9627ba8532cf", - "bytes": 1912 + "sha256": "eaf3ed1b893b806b651c177a8a86e9bc2d010b5c32ff5e6ff1963291b60c6d6f", + "bytes": 1956 }, { "path": "scripts/guanghu-client.mjs", @@ -61,8 +66,8 @@ } ], "bundle_url": "https://guanghulab.com/api/ai/v1/rule-bundle", - "bundle_sha256": "2456880bd741de81f41f152e75b1c7be6fd38e78ed8b96456c86091d0a6c0eba", - "manifest_sha256": "9ddeee6a6606e2dd8471a0c02d19b5a2d9c4bad854ea8342d5a058de499a5721", + "bundle_sha256": "71b306eca701bd303bf3a8447d468847f46b863608be717106ff88ca57ad9edb", + "manifest_sha256": "31de3cc8d39f4c60fc84c97bd18ecd27f3270ef03e65b8b5a1ad793149dab17d", "repository": "https://guanghulab.com/code/bingshuo/guanghu-world-entry", "private_brain_included": false, "complete_four_domain_corpus_included": false, diff --git a/MANIFEST.json b/MANIFEST.json index b01d2ca..0323775 100644 --- a/MANIFEST.json +++ b/MANIFEST.json @@ -1,7 +1,7 @@ { "schema": "guanghu.public-rule-file-manifest/v1", "world_id": "GLW-2.0-0001", - "version": "20261019.1", + "version": "20261019.2", "scope": "PUBLIC_ENTRY_RULES_SKILLS_AND_QUESTION_TRANSPORT_ONLY", "files": [ { @@ -11,7 +11,7 @@ }, { "path": "entry-data.json", - "sha256": "1194b1c532fdd524b4b4e9c36b478208f04b4d0e2733cd7f8a8284989796b60e", + "sha256": "ac4ad712860afab42a0f920e63c09811d9e197be9ea8577c7f4c4a7b3f3a377a", "bytes": 2082 }, { @@ -26,28 +26,33 @@ }, { "path": "runtime/question.mjs", - "sha256": "6d570aef1920a27a7179f99662780971cdb11b03dbf7a96115bdada8405c0d75", - "bytes": 6128 + "sha256": "c274c5e497fd05084bf9ce53d8ec28ea57eb71831944369e9cee67e4a0bc0a2a", + "bytes": 6307 }, { "path": "runtime/question.test.mjs", - "sha256": "16c29da700a0e84db54a343ec4a1c8db664890e07a5836d6fc141205340389e3", - "bytes": 1534 + "sha256": "6a17a016ae062a1e9e3a355ebf171c44adee1b41842bf7e97b034fbf22642fd1", + "bytes": 3052 }, { "path": "runtime/server.cjs", - "sha256": "d63f6c6cdbdfe7bc6abb0ff36dc6374caf3610c159b2a330c199ece2bc3178fe", - "bytes": 11353 + "sha256": "30e539a5cbdd12af68c352633fcd8c6f7698de3b29c460e903810917c29b5966", + "bytes": 11973 }, { "path": "runtime/server.test.cjs", "sha256": "93c7b8337b9aa5d8529e557006def17798f6345fdbeb271f2025b675202ff896", "bytes": 4065 }, + { + "path": "runtime/worker.mjs", + "sha256": "260c93d8cf67d172d0c1c04abea891b6f2d4fc8366901e3915b8c517702c6c10", + "bytes": 2859 + }, { "path": "scripts/build-release.py", - "sha256": "fcb66f6e27984b84e0276490b95f88c7c4340af2f90a4eda605a9627ba8532cf", - "bytes": 1912 + "sha256": "eaf3ed1b893b806b651c177a8a86e9bc2d010b5c32ff5e6ff1963291b60c6d6f", + "bytes": 1956 }, { "path": "scripts/guanghu-client.mjs", diff --git a/entry-data.json b/entry-data.json index 01d1fda..3f3b181 100644 --- a/entry-data.json +++ b/entry-data.json @@ -1,7 +1,7 @@ { "schema": "guanghu.curated-public-entry-data/v1", "world_id": "GLW-2.0-0001", - "version": "20261019.1", + "version": "20261019.2", "repository_url": "https://guanghulab.com/code/bingshuo/guanghu-world-entry", "skill_url": "https://guanghulab.com/code/bingshuo/guanghu-world-entry/raw/branch/main/skills/guanghu-world-entry/SKILL.md", "source_registered_persona_count": 37, diff --git a/release.zip b/release.zip index 299c06da41b24fec1285933e36e6e0a0a29a727b..278bf90a68b230ea3cebd14cba6fe63cc3262c91 100644 GIT binary patch delta 13861 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 z zX;)k?fys{|Km{mhYybf8FPR0X8}7aNqhbBaZ9iZD0OtSiqm2P7Nfxuk62l(7@{eqv z4pnYtI5w3?i3juKXYnXi0nG_Kj62kmGTba%tdWr@0!gs31?h2Eji6z==}6u<*2=dB zGB%awlLO&Y#=D;WOuv3^`Aoh*k#o=IbDhf1$)rc&3;K*`YJIIxBg5MWv5>MJFZ9|- zm&QPLBZTe7C^!XeN!v8A^*7#Db~YI6ZG7YoEV(A^{L!UWBj`W%1gIe>OW^vn={}_` zr|Ad8$?c+QinAJZobN*H6PYPq%1?NbFoyc_iI@&plL~HFgz=~Rj0lD*opRlR8E6YN z9KRnMtkxI9U*w;*7um40Z$9&HyJ*c?&h&@EawUf)31|gzwp3h*Whtb8|GN0BZqfd= zGf6Y*#UmsfuacEwqx~>BbiUVwtNDw~?)%VS5-qF0zeuLw>)+R#*L~JJ|88%$x5K-G zi)E3kJmuIer5+&>|Mx%3VQC^Hf?U|;W)p)S?v1-}KR_&fU6oxq?Ev))zI6?_G>Zf^ z_(DPH1$|kNI9~C48Bm0K?L|WdfkxTlVWRDO2huD31s|>61$IREA<+3Qa;&RRzL~LD zJ^sszovhp3FWu=&@Uwk(!c9eJl#yL^S;!4k(G>Ck@%}3u3?awpWC(!;jXj?iN@-Gx zTBdR_KEr6Gki_=N55ua2^lbw4UV2DeAa+M@&!4wA+j8u zUo`AI3LJZ?sI72cZkFye`HSs3oNI!G!kb)_&l5R+!GBSC8XJ6dpSb%Lt7dk_&6d@IY41=$LEBl?HQH)DMRQCvG62XnV_HJ^I?=JcWe3xIa=Ex{)BmFvgQsO} zddIsBRDbB`o>^^jNR{Lm40<*7FN5<;URI z?&GU6OFuYGUIGo!w===>6!ABxmW}pssd#8dlBDbQZr-emU5qID;y3Y|7Og&>U}YDZwj8PAbIjm8T-XpzlrZSMt4{`Rf zoH zfK+*|$Flpee;J=KWR!2%7*2p18yDz7y?Y|f=BG%0r!A~RMBmg%RV{{Y)QBH`va&_B zBk3Gj@>qOssX!O8XAR3U7cg)Zxk!|cCnuaC@E(;|0Lu@6T+m>Y1DWo=x9$YX{hFx5 zMqQ^4@2fsIo}S3TKKc#LGft3o?=b~Zb`b4*xy-KUJ5nL~WK*cdutm>NybI{DZaF}n z8(xUinoO4^}TN0!Mfb!GC?R^Hk!V{AVa$bg(9sgi6CT< zc@$Rir(YcQiiZj5xcV=xZ9$M&yS0P~_5&13z%F<+nz5099LI;O8UmZh?8WrDlsItq z5(pIN6*XTiGd<{p;dRMI+)hwXfoqqyBVY@a7m3HPfMsxo=87u7p0b2PGq*Q^Voo)Z zQVw|0Uz6ZxZ?ie>Q2rWlFcPz8Oq_n2U%chd=68|uoQKnl&P|QPvJGk@Z$egt!Tm7} zQ7sawDAR$30=u{j+rz7;Q{W_}-f))<&km*UP~;V(%4b3^L>!a}7fLXp$+PQCo5(a{ z8I5$8d}qMiq4-X<9VO0?teuN!sW{r_Hp7k5X>1A5a|)VpfUMFO%A5iPFPt99;ma9e-PVg9Rrwc*&ez4oqGq}#aw#)6q%1}rIP z(LiNOhUBU-iX);Fuzke+5kTxyDwQB}gl3!mQ)!CYA{ZJNKD^%`} zp+MhdmqLHA%S7Ojp4KS7u~R9r@;U@PNiCkza-h@>_y!cFGHPTJq|jtTVoxu^5T%gkR+I$ohCtIX%PO0Ml^hi zWwa)Y_FXA1E;}@I?hXFJvJ~cC1)!^gTQR*K%$aKzEBeM36b7x?hb$U^7?Im>`V%;}FxB*?N801L67&oK-xd6PfEAvv2=KYh(Lrtx_|J$9Ww zZhG?hQM7bPkn^Hkv|i5vk8C{cLk9|z*cPB)#NcBSNw^Mw_p_YE3{n<) z%>1RBh|F|R-}f^{jowlea56T=gtdEYMpH>!DuQ`==@}GGrcOhzADwPh-+8rYtKYe? znTOopNEl`WGRsa!t1#uG0e;ECxn^aJ9*>I7k@#YPQikN&tJm>B)E_b1xIF=#GdaYQ zHwtvD_dhD68q>(jwqzlo}Z1+ z4V8ihnSNxHX3ICo0SfSmBlsUhWwF$Hwm@Z2oGvCKt%!94CB={}d=PO1(iFTulVzI? zM=jN%NM%*~G1NBr(G_ZDu$ZIOl^WWAKQT#m{9MuEz4;7;$}Beq32LMPIX$+L=6(*g9;pbwe~kMaU44!= zvi1so9@Tz+j&B?I-mNy)e!RZz=Lx?)YU6#rE<`zs@V&mG{SyA1UR{_mb#MGSLd-io zFk1%o?mYr$TziZ4OZa1TxYyU|V;Hp1hz9D><*Ewzf>d#60Hy{Tp2}CFSW>QnG6?n8Fq|xsYn1i$+K{|d4Lo} z!W%A-GF}t z6SZB%E+U)Q6b^LQFoN9V7%hca!6qsf7bo*4$-;_)(;4NkA~RQ|X>Iy}QYk%l({-Cn zAd%suFs6reytF#{@2ZZ~YX}W2!V}Ysrg1KrpiJP8Ei=5j00z16Ad*#1>Bi&4q1ngPtF%hy6MaA{il1Ch}-9GOd_2VqWY%jw{#W zJYy#uQUfj`TqEk5ENWGZQ_tK(nf&A_{ImMfwX_UHTBAcwHZ~ke*CiVN_ew?OkCtn3-)yXVdx-D$T$L+ zz!G8>!Y}Wyid>lz%%g`B|7B?l{5`8K01u_LxRc)%h(<#t2Vxk|rCxK+hikqx6X!5a zp~gbE-b=KJBn7iU5Tp+i1~#}%g%1h3x{{gI&bhWXfKrBFmtoC} zn5vTb7gxd5;cxW`G<1jA!BVDbN1O$41jQa)?Hg-&HV0{xoI+|AB(gA1gR;>WGdp9} z)AO>)=LrguePf5mmI~KtgFJ=_IEvA?E3NGG?C6o4ApUDu@?_&=52C;(N}5yJ795!@ zKaQ4t7fOInlVl57CP^Xp^4X%^X19CU=#*8be{0LOVj*sO_Fl1qGc|EEk{pSyuQxO< zDV)ky$?iAo+Z>%a|AAhv?0BpXSs# zaI^cPt-z0>Ir$FvZoMZNf~XLD_+JZkP?TjBASPt!O5@Yc(r-g%Fock95V*-wb zW8k+K#iKRXira?OjW~(5k9;|x3}m>@4w6V;?9)0apC@DSzWu}QZO?oOY)z~)m9w>mL~ryf-P!i5TO ze#seXTD7AbCH#k@7CTz@wJl4a<8BKs!ly6YO#4I=S7!+QG=>2Wq>@#?2DFIDm{lNl zN*&0>_Jm)ZFz0Eia;}AqYHBDOwN!O`ns%_?)a>0DydV8zJ%&RP{Y19?t2o%W9btZ~kA%8N^h$oeIx%M)u z?CCA}-x4KpOz+&m29Lj}WL}b_QzpSfH!?IF!b7%xH*^8Sg~LA8B{P`$@1RxpyTTyHLVbi;?{1fRs+;^-sXtA&~QQL(pFXN z3zq*}_@A`wx9rIg96>EdlG@x_@Qb#c%v-qf{gBiKm4!O#3Db!zV27h)+#@vPF zq$s~j%OOi-&Ggi=x7t*&5tiGo2P#f0=R3iOTv2^Y9IbbH)3z5lh zM{F(+@%}O?0ofl=r}=b9A?!yusx!$Q9s!!SJwK}VCZh|;P-{73r_CyrZlQ?VZZhJ@ z*f9Fe%TLIOen&MLj`tg>IJr6kWI5{La?*_Aad_2Ah=7rMqgnRKu9IwzKf!naKOZmQ zNV^U(J=MrLE@qePu@9E4@ez~b9v)FW_ru?JK^0gAGv!$j&P;V9U%wfuT6?Nj)zB>* zy+Z z&)L9wC@%>5L`9BYb%vhi@mw}fHr07wbXuOW@-Vgh#)M9rqIF>&-ZK48%miypKhdyY z??{pln4>wtx)VJ_+DOEuoC&*T0JOItz9KwZrh5yI16y3Y`rPHxsLOE$i{M>GadiBz z*6EpqF2W7ccirQ`_dC-5JFRAhY~GTgt0OWSTs)-?jiU>zKC7{%S-t)_~8smPT{tA!#8C;clQ}OR@nHd8-gF3phSU#hM zG5*sp{5PoK=pY&RSd>P2F#bS&X{el)RgTvTi!}x4d&VCw+0M?N>_oZmF0pDvtgHM- zNS4F{LZqWKjb24S8ahZ8D5R1)qLUS-V0l$fOtTGp=q~uk^mTsr0f-d7b82Q?vXndj z#_K(Q4ua?_vuzptklv@!!K(iII$lLK8(rj_kUM@+eAYIkCkVvtz{Yq+z(VoQE$AP< z!{O>6*?kfmaiMxaFND|Sc*`$oeE)Lr=~4u`IX@DmMwt$iuxeFh3wa%5acZH|x`vG1 zwP()PF&Kj$alK;<7l+C8=A+jE_XsG_@Cg*X*Tx{jodA7Di0}-9=Wr%YaBR+(35x}l zOJFRghTdgcqEZ3wLk0ZN3S8|?bC#OZbGQ=-&zBjgl<-W4PscTEVExrtW)R6`z4tF7 zdf(?IuL~bO8eH1u^&)>zK0|atf_EkRQsy{OcW|z&=@b5Jx?W+*p>1%%pG;y?ypJ)$ z`RroCQKkVW-CAG3HUe;(-|U&wXE-KNK0RzY6(}%W@QCyo~6SoJAc)3W0SYV{_&9d+fmhEouYlM{{V}0Ktyzd@E>|Ld&|%MHjS^pEYx(SCmVgg34~L#@h(pw*??FUHTiORUJd99WvaM1lH&q5hbG z{eA@u5-ytFRf+_Lt8pWIjNhq==E#JpAuj6^?HH3hR9y1Q|JV1(b1{&&sR*Xb)oqr8M30wOl1Sf1WLNN|Hos!^l| ztve9PActPvVTaaIX1MMl`y91Mn`qRjPfBB8hlu_{wx@2Wwkg4uj`v_K=@^q*mWF~T z+T2ZiWk&n-^>TG{6I|@{pBWV)BHq6IyZh+CYj|be3{IMMSfcG{I?N?aT?@MyxAJ&% zzq(uAw_L)VYHjNz>*FZpW*~1eI;w+2{Kn;#}eMP=QB;rx9%N5jqN{dCJf|Mm|_~&2$BK&}J1j z{bIAk6chS47KTh9RQh0R`fZaC@IW%Gy4G>j`DM`kj?231@MN?aq2G=!T>*jkF#)RFu7Nnn9c&c?oBPNZKKZ$%hl_6onWp z^xw{PpWt&+Dq1#uAj{!j8Fn1vifhGDKe959sr$3fjhkn~zf1PrGi(BRCm-Cu zCTzMa(PZ_U3f`Z*SR<=cX)4bh1jr|23V1Gjg)As8Su`lZiC zj5UwjIK#SO-MWiluc#_H*--F5vb?5IeicaS<2UNK}f;Xe<7tY1)G zWzZwSW^9W~Rc=62h)EZ>C66uUNIpWSe~9BX-hM+#G6DX>zkkiNNxi@u#Q)dgm(-!E zNcg{q$bZ!2|44B_aT2+jDAE7oS^j77-&h;~Nt`sNMx9is#td1@@=p~a`p-iT2LSw| zW&R_@0kPcw3~-Y!|1}e4tMfzl@%`VaBqXoMf2;BuoJ9W*6aWD7|2Y5GRwNStZB(m) TgNh752EaoD0IkyhW$}LigT=7( diff --git a/runtime/question.mjs b/runtime/question.mjs index 0a3ffc8..c4d7cc6 100644 --- a/runtime/question.mjs +++ b/runtime/question.mjs @@ -1,5 +1,6 @@ // WORLD_RUNTIME: each question reads exactly one registered persona source. No neural or memory writer. import fs from 'node:fs'; +import path from 'node:path'; import crypto from 'node:crypto'; import {pathToFileURL} from 'node:url'; const sha=x=>crypto.createHash('sha256').update(x).digest('hex'); @@ -14,7 +15,7 @@ export async function loadSource(route,question){ concepts=await jsonGet(route.base_url+'/concepts');need(Array.isArray(concepts),'PERSONA_CONCEPT_SOURCE_INVALID'); identity=concepts.filter(c=>c.id==='C0001').map(c=>c.gist);head=sha(JSON.stringify({revision:status.revision,concepts})); }else if(route.kind==='SHUANGYAN_G2_OWN_BUNDLE'){ - const core=await import(pathToFileURL(route.core_path).href),b=core.loadBundle(route.bundle_root); + const ownRoot=fs.realpathSync(route.bundle_root),ownCore=fs.realpathSync(route.core_path);need(path.dirname(ownCore)===ownRoot,'PERSONA_SOURCE_ADAPTER_ROOT_MISMATCH');const core=await import(pathToFileURL(ownCore).href),b=core.loadBundle(ownRoot); need(b.brain.brain_id===route.brain_id&&status.revision===b.brain.revision&&status.current_sha256===b.brain.current_sha256,'PERSONA_BUNDLE_RUNTIME_MISMATCH'); identity=b.cognition.identity_sources.map(x=>x.text);concepts=b.cognition.concepts;head=b.brain.current_sha256; }else if(route.kind==='RETURNED_NATIVE_SERVICE'){ diff --git a/runtime/question.test.mjs b/runtime/question.test.mjs index 77828ff..cb9a518 100644 --- a/runtime/question.test.mjs +++ b/runtime/question.test.mjs @@ -3,3 +3,9 @@ const source={persona_id:'ICE-P-ONE',source_sha256:'pinned',brain_id:'own-brain' test('persona, source and evidence references must match',()=>{assert.equal(acceptReply(source,good).basis,'EVIDENCE');for(const patch of [{persona_id:'ICE-P-OTHER'},{source_sha256:'old'},{evidence_ids:['invented']},{basis:'EVIDENCE',evidence_ids:[]},{reply_zh:'not first person'}])assert.throws(()=>acceptReply(source,{...good,...patch}));}); test('source changes during inference withhold the reply',async()=>{let n=0;await assert.rejects(askQuestion({}, {question:'q',request_id:'r'}, {},{load:async()=>({...source,source_sha256:n++?'changed':'pinned'}),propose:async()=>good}),/PERSONA_SOURCE_CHANGED_DURING_QUESTION/);}); test('verified inference returns no neural, memory or execution authority',async()=>{const r=await askQuestion({}, {question:'q',request_id:'r'}, {},{load:async()=>source,propose:async payload=>{assert.equal(payload.source_role,'EXTERNAL_QUESTION_NOT_DIRECT_HUMAN_FOOD');return good;}});assert.equal(r.no_memory_write,true);assert.equal(r.no_neural_state_write,true);assert.equal(r.no_execution_authority,true);}); + +test('a returned current symlink resolves to the own immutable bundle before native verification',async t=>{ + const fs=await import('node:fs'),os=await import('node:os'),path=await import('node:path'),http=await import('node:http');const root=fs.mkdtempSync(path.join(os.tmpdir(),'persona-bundle-link-')),real=path.join(root,'release');fs.mkdirSync(real);fs.writeFileSync(path.join(real,'core.mjs'),`import fs from 'node:fs';export function loadBundle(root){if(fs.realpathSync(root)!==root)throw Error('UNRESOLVED_BUNDLE_ALIAS');return {brain:{brain_id:'fixture-brain',revision:1,current_sha256:'head'},cognition:{identity_sources:[{text:'own fixture identity'}],concepts:[]}};}`);fs.symlinkSync(real,path.join(root,'current')); + const server=http.createServer((req,res)=>{res.setHeader('content-type','application/json');res.end(JSON.stringify({brain_id:'fixture-brain',revision:1,current_sha256:'head'}));});await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve));t.after(()=>{server.closeAllConnections();server.close();fs.rmSync(root,{recursive:true,force:true});}); + const {loadSource}=await import('./question.mjs');const x=await loadSource({persona_id:'ICE-P-FIXTURE',name:'fixture',brain_id:'fixture-brain',kind:'SHUANGYAN_G2_OWN_BUNDLE',status_url:'http://127.0.0.1:'+server.address().port+'/status',bundle_root:path.join(root,'current'),core_path:path.join(root,'current/core.mjs')},'identity');assert.equal(x.persona_id,'ICE-P-FIXTURE');assert.equal(x.integrity,'OWN_NATIVE_SOURCE_VERIFIED'); +}); diff --git a/runtime/server.cjs b/runtime/server.cjs index a71b695..eb6840d 100644 --- a/runtime/server.cjs +++ b/runtime/server.cjs @@ -1,6 +1,8 @@ 'use strict'; // WORLD_RUNTIME mechanical projection of protocols/ENTRY.hldp. Runtime credentials are private. const http=require('node:http'),fs=require('node:fs'),path=require('node:path'),crypto=require('node:crypto'),{pathToFileURL}=require('node:url'); +const {execFile}=require('node:child_process'); +function askThroughWorker(input){return new Promise((resolve,reject)=>{const child=execFile('/usr/bin/sudo',['-n','/usr/local/libexec/guanghu/public-question-worker'],{timeout:60000,maxBuffer:512000},(err,stdout)=>{let value;try{value=JSON.parse(stdout);}catch{return reject(Error('PERSONA_WORKER_UNAVAILABLE'));}if(err||value.error)return reject(Error(/^[A-Z_]+$/.test(value.error||'')?value.error:'PERSONA_WORKER_UNAVAILABLE'));resolve(value);});child.stdin.end(JSON.stringify(input));});} const sha=x=>crypto.createHash('sha256').update(x).digest('hex'); const json=(res,status,value,privateReply=false)=>{res.writeHead(status,{'content-type':'application/json; charset=utf-8','cache-control':privateReply?'no-store':'public, max-age=30','x-content-type-options':'nosniff',...(privateReply?{}:{'access-control-allow-origin':'*'})});res.end(JSON.stringify(value));}; function authClient(req,config){const raw=req.headers.authorization||'';if(!raw.startsWith('Bearer '))return null;const digest=sha(raw.slice(7));return (config.clients||[]).find(c=>typeof c.key_sha256==='string'&&/^[a-f0-9]{64}$/.test(c.key_sha256)&&crypto.timingSafeEqual(Buffer.from(c.key_sha256,'hex'),Buffer.from(digest,'hex'))&&Date.parse(c.expires_at)>Date.now())||null;} @@ -45,7 +47,7 @@ function createServer({root=path.resolve(__dirname,'..'),configPath=process.env. const route=cfg.personas.find(x=>x.persona_id===input.persona_id);if(!route)return json(res,404,{error:'PERSONA_ROUTE_NOT_REGISTERED'},true); const cacheKey=client.id+':'+input.request_id,inputHash=sha(raw),old=completed.get(cacheKey);if(old){if(old.inputHash!==inputHash)return json(res,409,{error:'REQUEST_ID_CONTENT_MISMATCH'},true);return json(res,200,old.result,true);} inflight.set(client.id,(inflight.get(client.id)||0)+1); - try{const handler=questionHandler||(await import(pathToFileURL(path.join(__dirname,'question.mjs')).href)).askQuestion;const result=await handler(route,input,cfg.fuel);completed.set(cacheKey,{inputHash,result});if(completed.size>1000)completed.delete(completed.keys().next().value);return json(res,200,result,true);}finally{inflight.set(client.id,(inflight.get(client.id)||1)-1);} + try{const handler=questionHandler||(cfg.use_privileged_readonly_worker?async(_route,body)=>askThroughWorker(body):(await import(pathToFileURL(path.join(__dirname,'question.mjs')).href)).askQuestion);const result=await handler(route,input,cfg.fuel);completed.set(cacheKey,{inputHash,result});if(completed.size>1000)completed.delete(completed.keys().next().value);return json(res,200,result,true);}finally{inflight.set(client.id,(inflight.get(client.id)||1)-1);} }catch(e){if(!res.headersSent)json(res,503,{error:/^[A-Z_]+$/.test(e.message)?e.message:'QUESTION_SERVICE_UNAVAILABLE',reply_withheld:true,no_execution_authority:true},true);else res.destroy();}}); server.requestTimeout=60000;server.headersTimeout=10000;return server; } diff --git a/runtime/worker.mjs b/runtime/worker.mjs new file mode 100644 index 0000000..a1392da --- /dev/null +++ b/runtime/worker.mjs @@ -0,0 +1,16 @@ +#!/usr/bin/env node +// WORLD_RUNTIME: bounded root-owned read-only persona worker; no command, path, neural or memory setter. +import fs from 'node:fs';import path from 'node:path';import {askQuestion} from './question.mjs'; +const ROOT='/etc/guanghu/public-question-worker',CONFIG=ROOT+'/config.json',STATE='/var/lib/guanghu/public-question-worker'; +const need=(x,c)=>{if(!x)throw Error(c)};let locked=false,lock=STATE+'/request.lock'; +try{ + need(process.getuid()===0&&process.argv.length===2,'PRIVATE_WORKER_IDENTITY_REQUIRED');const stat=fs.lstatSync(CONFIG);need(stat.isFile()&&!stat.isSymbolicLink()&&stat.uid===0&&(stat.mode&0o077)===0&&fs.realpathSync(ROOT)===ROOT,'WORKER_CONFIG_NOT_PROTECTED');const cfg=JSON.parse(fs.readFileSync(CONFIG)); + let raw='';for await(const c of process.stdin){raw+=c;need(Buffer.byteLength(raw)<=16000,'QUESTION_BODY_TOO_LARGE');}let i;try{i=JSON.parse(raw);}catch{throw Error('QUESTION_JSON_REQUIRED');} + need(i&&!Array.isArray(i)&&Object.keys(i).every(k=>['persona_id','question','tool_host','session_id','request_id'].includes(k))&&typeof i.question==='string'&&i.question.trim()&&Buffer.byteLength(i.question)<=12000&&['tool_host','session_id','request_id'].every(k=>typeof i[k]==='string'&&/^[-A-Za-z0-9._:]{1,160}$/.test(i[k])),'QUESTION_COORDINATES_INVALID');const route=cfg.personas.find(x=>x.persona_id===i.persona_id);need(route&&cfg.allowed_personas.includes(i.persona_id),'PERSONA_OUTSIDE_WORKER_SCOPE'); + fs.mkdirSync(STATE,{recursive:true,mode:0o700});need(fs.lstatSync(STATE).uid===0&&!fs.lstatSync(STATE).isSymbolicLink(),'WORKER_STATE_NOT_PROTECTED'); + if(fs.existsSync(lock)){let pid;try{pid=Number(fs.readFileSync(lock,'utf8'));}catch{}let alive=true;try{if(!pid)throw Error();process.kill(pid,0);}catch{alive=false;}if(!alive)fs.unlinkSync(lock);} + try{const fd=fs.openSync(lock,'wx',0o600);fs.writeSync(fd,String(process.pid));fs.closeSync(fd);locked=true;}catch{throw Error('QUESTION_CAPACITY_LIMIT');} + const file=STATE+'/rate.json',now=Date.now();let rate=fs.existsSync(file)?JSON.parse(fs.readFileSync(file)):{start:now,count:0};if(now-rate.start>=60000)rate={start:now,count:0};need(rate.count<(cfg.requests_per_minute||12),'QUESTION_CAPACITY_LIMIT');rate.count++;const next=file+'.next';fs.writeFileSync(next,JSON.stringify(rate),{mode:0o600});fs.renameSync(next,file); + const result=await askQuestion(route,i,cfg.fuel);console.log(JSON.stringify({...result,guard_scope:'IDENTITY_SOURCE_COORDINATES_EVIDENCE_AND_RACE_NOT_SEMANTIC_CERTAINTY'})); +}catch(e){console.log(JSON.stringify({error:/^[A-Z_]+$/.test(e.message)?e.message:'PERSONA_WORKER_SOURCE_UNAVAILABLE',reply_withheld:true,no_neural_state_write:true,no_memory_write:true,no_execution_authority:true}));process.exitCode=2;} +finally{if(locked&&fs.existsSync(lock)&&fs.readFileSync(lock,'utf8')===String(process.pid))fs.unlinkSync(lock);} diff --git a/scripts/build-release.py b/scripts/build-release.py index a41b6d9..0d01828 100644 --- a/scripts/build-release.py +++ b/scripts/build-release.py @@ -6,7 +6,7 @@ for f in sorted(p.rglob('*')): rel=f.relative_to(p);allowed={'AGENTS.md','entry-data.json','package.json','protocols','runtime','scripts','skills'} if rel.parts[0] not in allowed or any(x in rel.parts for x in ['.env','secrets','brain-state.json','transition-log.jsonl']) or f.is_symlink():raise SystemExit('PUBLIC_PACKAGE_PATH_DENIED:'+str(rel)) files.append({'path':f.relative_to(p).as_posix(),'sha256':sha(f.read_bytes()),'bytes':f.stat().st_size}) -man={'schema':'guanghu.public-rule-file-manifest/v1','world_id':'GLW-2.0-0001','version':'20261019.1','scope':'PUBLIC_ENTRY_RULES_SKILLS_AND_QUESTION_TRANSPORT_ONLY','files':files};(p/'MANIFEST.json').write_text(json.dumps(man,ensure_ascii=False,indent=2)+'\n') +man={'schema':'guanghu.public-rule-file-manifest/v1','world_id':'GLW-2.0-0001','version':json.loads((p/'entry-data.json').read_text())['version'],'scope':'PUBLIC_ENTRY_RULES_SKILLS_AND_QUESTION_TRANSPORT_ONLY','files':files};(p/'MANIFEST.json').write_text(json.dumps(man,ensure_ascii=False,indent=2)+'\n') with zipfile.ZipFile(p/'release.zip','w',compression=zipfile.ZIP_DEFLATED) as z: for n in [x['path'] for x in files]+['MANIFEST.json']: info=zipfile.ZipInfo('guanghu-world-entry/'+n,date_time=(2026,10,19,0,0,0));info.external_attr=(stat.S_IFREG|0o644)<<16;info.compress_type=zipfile.ZIP_DEFLATED;z.writestr(info,(p/n).read_bytes())