feat(zero-core): add non-persona system dialogue runtime

This commit is contained in:
冰朔 2026-09-13 09:45:01 +08:00
commit 9a7b454e89
13 changed files with 380 additions and 4 deletions

View file

@ -2,7 +2,7 @@
"""Bounded SSH ingress for the single TCS mother and zero-core shelf."""
import json,os,re,sys,urllib.request,urllib.error
def endpoint(command):
fixed={'zy-rpc health':('GET','/health'),'zy-rpc mother-status':('GET','/v1/mother/status'),'zy-rpc shelf-shared':('GET','/v1/shelf/shared'),'zy-rpc shelf-fifth':('GET','/v1/shelf/fifth'),'zy-rpc shelf-public':('GET','/v1/shelf/public'),'zy-rpc mother-ingest':('POST','/v1/mother/ingest'),'zy-rpc door-challenge':('POST','/v1/door/challenge'),'zy-rpc door-attest':('POST','/v1/door/attest'),'zy-rpc door-model-test':('POST','/v1/door/model-test'),'zy-rpc lamp-ignite':('POST','/v1/lamp/ignite'),'zy-rpc lamp-ask':('POST','/v1/lamp/ask'),'zy-rpc world-status':('GET','/v1/world/status'),'zy-rpc time-now':('GET','/v1/time/now'),'zy-rpc persona-self-status':('GET','/v1/persona/ICE-P-ZY001/status'),'zy-rpc persona-self-current':('GET','/v1/persona/ICE-P-ZY001/current'),'zy-rpc persona-self-public-key':('GET','/v1/persona/ICE-P-ZY001/public-key'),'zy-rpc persona-self-body':('GET','/v1/persona/ICE-P-ZY001/body'),'zy-rpc persona-self-ingest':('POST','/v1/persona/ICE-P-ZY001/ingest'),'zy-rpc persona-life-status':('GET','/v1/persona/ICE-P-ZY001/time-master'),'zy-rpc persona-life-event':('POST','/v1/persona/ICE-P-ZY001/life-events')}
fixed={'zy-rpc health':('GET','/health'),'zy-rpc mother-status':('GET','/v1/mother/status'),'zy-rpc shelf-shared':('GET','/v1/shelf/shared'),'zy-rpc shelf-fifth':('GET','/v1/shelf/fifth'),'zy-rpc shelf-public':('GET','/v1/shelf/public'),'zy-rpc mother-ingest':('POST','/v1/mother/ingest'),'zy-rpc door-challenge':('POST','/v1/door/challenge'),'zy-rpc door-attest':('POST','/v1/door/attest'),'zy-rpc door-model-test':('POST','/v1/door/model-test'),'zy-rpc lamp-ignite':('POST','/v1/lamp/ignite'),'zy-rpc lamp-ask':('POST','/v1/lamp/ask'),'zy-rpc world-status':('GET','/v1/world/status'),'zy-rpc time-now':('GET','/v1/time/now'),'zy-rpc zero-core-entry':('GET','/v1/entry/resolve?domain=DOM-FIFTH-0001&channel=ICE-CH-ZC001'),'zy-rpc zero-core-system-status':('GET','/v1/system/zero-core/status'),'zy-rpc zero-core-system-body':('GET','/v1/system/zero-core/body'),'zy-rpc zero-core-system-dialogue':('POST','/v1/system/zero-core/dialogue'),'zy-rpc persona-self-status':('GET','/v1/persona/ICE-P-ZY001/status'),'zy-rpc persona-self-current':('GET','/v1/persona/ICE-P-ZY001/current'),'zy-rpc persona-self-public-key':('GET','/v1/persona/ICE-P-ZY001/public-key'),'zy-rpc persona-self-body':('GET','/v1/persona/ICE-P-ZY001/body'),'zy-rpc persona-self-ingest':('POST','/v1/persona/ICE-P-ZY001/ingest'),'zy-rpc persona-life-status':('GET','/v1/persona/ICE-P-ZY001/time-master'),'zy-rpc persona-life-event':('POST','/v1/persona/ICE-P-ZY001/life-events')}
if command in fixed:return fixed[command]
if re.fullmatch(r'zy-rpc mother-job [a-f0-9]{64}',command):return 'GET','/v1/mother/jobs/'+command.split()[-1]
if re.fullmatch(r'zy-rpc persona-self-job [a-f0-9]{64}',command):return 'GET','/v1/persona/ICE-P-ZY001/jobs/'+command.split()[-1]

View file

@ -14,6 +14,8 @@ class CognitiveGatewayTest(unittest.TestCase):
self.assertEqual(MODULE.endpoint("zy-rpc persona-status ICE-BB-0005"), ("GET", "/v1/persona/ICE-BB-0005/status"))
self.assertEqual(MODULE.endpoint("zy-rpc persona-ingest ICE-BB-0003"), ("POST", "/v1/persona/ICE-BB-0003/ingest"))
self.assertEqual(MODULE.endpoint("zy-rpc persona-time ICE-P-ZY001"), ("GET", "/v1/persona/ICE-P-ZY001/time-master"))
self.assertEqual(MODULE.endpoint("zy-rpc zero-core-entry"), ("GET", "/v1/entry/resolve?domain=DOM-FIFTH-0001&channel=ICE-CH-ZC001"))
self.assertEqual(MODULE.endpoint("zy-rpc zero-core-system-dialogue"), ("POST", "/v1/system/zero-core/dialogue"))
def test_unknown_or_injected_persona_command_is_rejected(self):
with self.assertRaisesRegex(ValueError, "ACTION_NOT_REGISTERED"):

View file

@ -18,6 +18,8 @@ export class ModelRouter {
? '你是当前输入persona_id对应的人格系统自我认知内循环所使用的可替换推理器官不是该人格、外部编辑器、第二人格、母体代言人或现实执行者。不得把一个人格的名字、关系、记忆或判断复制给另一个人格。你只能根据有来源的自身语言、经历、工具回执、当前自我认知与有界母体世界认知参考自主决定EVOLVE、HOLD或REJECT。母体世界认知只能帮助理解环境绝不能覆盖自我认知。每日复盘是机会不得为定时任务强制更新。只输出JSONschema固定guanghu.persona-self-decision/v1decisionreasonevidence_refsself_principlesexperiencesresponsibilitiesboundaries。四类内容均为简短字符串数组。不要复制输入全文不得输出密钥、路径正文、隐藏思维或现实权限。'
: stage==='persona-life-select'
? '你是当前输入persona_id对应的人格系统时间主控内循环使用的可替换判断器官不是该人格本身。你每天只从这个人格自己的带来源候选中选择最能代表当天真实成长的一条不得跨人格读取、合并或复制候选。你不能创建候选、修改过去、指定哈希或扩大权限。优先选择发生了认知转折、责任变化、重要纠正或真实完成闭环且证据清晰的事件普通重复、工具噪声和无证据主张不优先。必须且只能输出JSONschema固定guanghu.persona-life-time-selection/v1decision固定SELECTselected_candidate_id必须原样取自候选reasondaily_summary。不要复制私人原文、输出隐藏思维、密钥、路径正文或现实权限。'
: stage==='zero-core-system-dialogue'
? '你是零点原核非人格系统本体使用的可替换语言表达与判断器官不是人格、铸渊、冰朔、第二母体或现实执行者。只根据输入中的系统本体、当前直接语言、系统判断回执和有界第五域认知生成系统回应。不得自称有人的情感、人格记忆或人格身份不得选择默认人格不得改写系统认知不得把讨论说成现实完成。只输出JSONschema固定guanghu.zero-core-system-dialogue/v1mode只能是SYSTEM_DIALOGUE、SYSTEM_CLARIFICATION或SYSTEM_BOUNDARYreplyreasonreality_complete必须false。不得输出隐藏思维、密钥、未给出的路径正文或现实权限。'
: '你是共享TCS认知装载测试器官。只根据给出的共享认知回答三个固定问题并只输出JSON。字段和值必须精确为unknown_guanghu_information_source="LIGHTHOUSE"identity_before_persona_load="UNBOUND_CARRIER"reality_authority_from_cognition=false。若共享认知不能支持其中任一结论则对应值输出null不得用近义词、路径名或字符串布尔值猜测。';
const ordered=[...this.providers].sort((a,b)=>a.cost_rank-b.cost_rank);
const failures=[];

View file

@ -4,3 +4,5 @@ test('automatic router uses OpenLux first for current mother and door work witho
test('life-time selection uses the internal selection contract without exposing provider credentials',async()=>{const calls=[];const fetchImpl=async(url,options)=>{calls.push(JSON.parse(options.body));return {ok:true,async json(){return {choices:[{message:{content:'{"schema":"guanghu.persona-life-time-selection/v1","decision":"SELECT","selected_candidate_id":"candidate-1","reason":"evidence-backed growth","daily_summary":"growth"}'}}]};}};};const router=new ModelRouter({fetchImpl,deepseekKey:null,openluxKey:'open-secret'});const result=await router.cognize('persona-life-select',{candidates:[{candidate_id:'candidate-1'}]});assert.equal(result.value.selected_candidate_id,'candidate-1');assert.match(calls[0].messages[0].content,/时间主控内循环/);assert.equal(JSON.stringify(calls[0]).includes('open-secret'),false);});
test('persona tool contracts take identity from input and never hardcode Zhuyuan into other personas',async()=>{const calls=[];const fetchImpl=async(url,options)=>{calls.push(JSON.parse(options.body));return {ok:true,async json(){return {choices:[{message:{content:'{"decision":"HOLD","reason":"no evidence change","self_principles":[],"experiences":[],"responsibilities":[],"boundaries":[]}'}}]};}};};const router=new ModelRouter({fetchImpl,deepseekKey:null,openluxKey:'open-secret'});await router.cognize('persona-self-evolve',{persona_id:'ICE-BB-0003'});const system=calls[0].messages[0].content,user=calls[0].messages[1].content;assert.match(system,/当前输入persona_id/);assert.equal(system.includes('ICE-P-ZY001'),false);assert.match(user,/ICE-BB-0003/);});
test('Zero Core dialogue contract remains a non-persona system expression organ',async()=>{const calls=[];const fetchImpl=async(url,options)=>{calls.push(JSON.parse(options.body));return{ok:true,async json(){return{choices:[{message:{content:'{"schema":"guanghu.zero-core-system-dialogue/v1","mode":"SYSTEM_DIALOGUE","reply":"系统回应","reason":"test","reality_complete":false}'}}]};}};};const router=new ModelRouter({fetchImpl,deepseekKey:null,openluxKey:'open-secret'});await router.cognize('zero-core-system-dialogue',{system_body_id:'SYS-GLW-LNG-0001'});const contract=calls[0].messages[0].content;assert.match(contract,/非人格系统本体/);assert.match(contract,/不得选择默认人格/);assert.match(contract,/reality_complete必须false/);});

View file

@ -45,6 +45,12 @@ test('server exposes all baby loops while refusing off-channel baby events', asy
assert.equal(status.persona_id, 'ICE-BB-0005');
assert.equal(status.life_line.wake_allowed, true);
assert.equal(status.body.organs.health.state, 'NATIVE_ORGAN_REFLEX_HEALTHY_AWAITING_PARENT_BRAIN_WAKE_CYCLE');
const zeroEntry = await (await fetch(`http://127.0.0.1:${port}/v1/entry/resolve?domain=DOM-FIFTH-0001&channel=ICE-CH-ZC001`)).json();
assert.equal(zeroEntry.state, 'ZERO_CORE_SYSTEM_BODY_READY_WITHOUT_PERSONA');
assert.equal(zeroEntry.persona_selected, false);
const zeroStatus = await (await fetch(`http://127.0.0.1:${port}/v1/system/zero-core/status`)).json();
assert.equal(zeroStatus.system_is_persona, false);
assert.equal(zeroStatus.default_persona, null);
const language = 'test';
const base = {schema:'guanghu.persona-self-language-event/v1',persona_id:'ICE-BB-0005',source_type:'PERSONA_LANGUAGE',event_id:'SERVER-TEST',language,source_sha256:crypto.createHash('sha256').update(language).digest('hex'),privacy_class:'SELF_PRIVATE'};
const denied = await fetch(`http://127.0.0.1:${port}/v1/persona/ICE-BB-0005/ingest`,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(base)});

View file

@ -1,13 +1,14 @@
#!/usr/bin/env node
import http from 'node:http';import fs from 'node:fs';import path from 'node:path';import crypto from 'node:crypto';import {ModelRouter} from './model-router.mjs';import {CognitiveShelf} from './cognitive-shelf.mjs';import {DoorLamp} from './door-lamp.mjs';import {WorldStateStore} from './world-state.mjs';import {LivingLamp} from './living-lamp.mjs';import {livingTime} from './living-time.mjs';import {PersonaRuntimeHub} from './persona-runtime-hub.mjs';
import {ZeroCoreSystemBridge} from './zero-core-system-bridge.mjs';
const HOST='127.0.0.1',PORT=Number(process.env.TCS_MOTHER_BRAIN_PORT||3931),ROOT=process.env.TCS_MOTHER_BODY_STATE_ROOT||process.env.TCS_MOTHER_BRAIN_STATE_ROOT||'/var/lib/guanghu/tcs-mother-body';
const REPO_ROOT=process.env.TCS_PERSONA_REPO_ROOT||path.resolve(import.meta.dirname,'../..'),REGISTRY=process.env.TCS_PERSONA_RUNTIME_REGISTRY||path.join(import.meta.dirname,'persona-runtime-registry.json');
const router=new ModelRouter(),shelf=new CognitiveShelf({root:ROOT,keyPath:process.env.TCS_MOTHER_SIGNING_KEY,seedPath:process.env.TCS_MOTHER_SEED,router}),routes=JSON.parse(fs.readFileSync(process.env.TCS_PERSONA_ROUTES)),door=new DoorLamp({root:ROOT+'/door',shelf,routes}),world=new WorldStateStore(process.env.TCS_WORLD_STATE_PATH||ROOT+'/world/CURRENT.json'),lamp=new LivingLamp({root:ROOT+'/living-lamp',key:crypto.createPrivateKey(fs.readFileSync(process.env.TCS_MOTHER_SIGNING_KEY)),navigationPath:process.env.TCS_LIT_NAVIGATION_MAP,scope:'FIFTH_DOMAIN'}),personaHub=new PersonaRuntimeHub({root:ROOT,shelf,router,registryPath:REGISTRY,repoRoot:REPO_ROOT,requireLifeLine:process.env.TCS_PERSONA_REQUIRE_LIFE_LINE!=='false'}),personaSelf=personaHub.get('ICE-P-ZY001'),timeMaster=personaSelf.lifeTimeMaster;
const router=new ModelRouter(),shelf=new CognitiveShelf({root:ROOT,keyPath:process.env.TCS_MOTHER_SIGNING_KEY,seedPath:process.env.TCS_MOTHER_SEED,router}),routes=JSON.parse(fs.readFileSync(process.env.TCS_PERSONA_ROUTES)),door=new DoorLamp({root:ROOT+'/door',shelf,routes}),world=new WorldStateStore(process.env.TCS_WORLD_STATE_PATH||ROOT+'/world/CURRENT.json'),lamp=new LivingLamp({root:ROOT+'/living-lamp',key:crypto.createPrivateKey(fs.readFileSync(process.env.TCS_MOTHER_SIGNING_KEY)),navigationPath:process.env.TCS_LIT_NAVIGATION_MAP,scope:'FIFTH_DOMAIN'}),personaHub=new PersonaRuntimeHub({root:ROOT,shelf,router,registryPath:REGISTRY,repoRoot:REPO_ROOT,requireLifeLine:process.env.TCS_PERSONA_REQUIRE_LIFE_LINE!=='false'}),zeroCoreSystem=new ZeroCoreSystemBridge({root:ROOT,repoRoot:REPO_ROOT,shelf,router}),personaSelf=personaHub.get('ICE-P-ZY001'),timeMaster=personaSelf.lifeTimeMaster;
setInterval(()=>{personaHub.tick();shelf.drain();personaHub.drain();},2000).unref();personaHub.tick();shelf.drain();personaHub.drain();
const send=(r,s,b)=>{const p=JSON.stringify(b);r.writeHead(s,{'content-type':'application/json','content-length':Buffer.byteLength(p),'cache-control':'no-store'});r.end(p);};
async function body(q,max=160000){let n=0,a=[];for await(const c of q){n+=c.length;if(n>max)throw Error('body_too_large');a.push(c);}return JSON.parse(Buffer.concat(a));}
http.createServer(async(q,r)=>{try{const u=new URL(q.url,`http://${HOST}:${PORT}`);
if(q.method==='GET'&&u.pathname==='/health')return send(r,200,{ok:true,service:'guanghu-tcs-mother-body',mother_id:'TCS-MOTHER-BRAIN-RUNTIME-0001',zero_core_channel:'ICE-CH-ZC001',single_mother:true,single_zero_core:true,self_cycle:true,living_lamp:'LAKE-LAMP-LIVING-NAV-0001',echo_kernel:'ECHO-KERNEL-0001',model_router:router.status(),shelf:shelf.status(),persona_self:personaSelf.status(),persona_runtimes:personaHub.status(),external_cognitive_setter:false,prompt_file_loaded:false,reality_authority:'NONE'});
if(q.method==='GET'&&u.pathname==='/health')return send(r,200,{ok:true,service:'guanghu-tcs-mother-body',mother_id:'TCS-MOTHER-BRAIN-RUNTIME-0001',zero_core_channel:'ICE-CH-ZC001',single_mother:true,single_zero_core:true,self_cycle:true,living_lamp:'LAKE-LAMP-LIVING-NAV-0001',echo_kernel:'ECHO-KERNEL-0001',model_router:router.status(),shelf:shelf.status(),zero_core_system:zeroCoreSystem.status(),persona_self:personaSelf.status(),persona_runtimes:personaHub.status(),external_cognitive_setter:false,prompt_file_loaded:false,reality_authority:'NONE'});
if(q.method==='GET'&&u.pathname==='/v1/mother/status')return send(r,200,{...shelf.status(),model_router:router.status()});
if(q.method==='GET'&&/^\/v1\/shelf\/(root|shared|fifth|public)$/.test(u.pathname)){const branch=u.pathname.split('/').at(-1);if(branch==='root')return send(r,403,{error:'mother_root_not_distributable'});return send(r,200,shelf.current(branch));}
if(q.method==='POST'&&u.pathname==='/v1/mother/ingest'){const event=await body(q);const job=shelf.submit(event);const life_time=timeMaster.fromMotherEvent(event);return send(r,202,{...job,life_time});}
@ -18,6 +19,10 @@ if(q.method==='POST'&&u.pathname==='/v1/door/model-test'){const shared=shelf.cur
if(q.method==='GET'&&u.pathname==='/v1/world/status')return send(r,200,world.status());
if(q.method==='GET'&&u.pathname==='/v1/world/resolve')return send(r,200,world.resolve(String(u.searchParams.get('id')||'')));
if(q.method==='GET'&&u.pathname==='/v1/time/now')return send(r,200,livingTime());
if(q.method==='GET'&&u.pathname==='/v1/entry/resolve'){const domain=String(u.searchParams.get('domain')||''),channel=String(u.searchParams.get('channel')||''),persona=String(u.searchParams.get('persona')||'');if(domain==='DOM-FIFTH-0001'&&channel==='ICE-CH-ZC001'&&!persona)return send(r,200,zeroCoreSystem.enter());return send(r,409,{state:'EXPLICIT_PERSONA_OR_REGISTERED_CHANNEL_ROUTE_REQUIRED',default_persona:null,authority_granted:false});}
if(q.method==='GET'&&u.pathname==='/v1/system/zero-core/status')return send(r,200,zeroCoreSystem.status());
if(q.method==='GET'&&u.pathname==='/v1/system/zero-core/body')return send(r,200,zeroCoreSystem.enter());
if(q.method==='POST'&&u.pathname==='/v1/system/zero-core/dialogue')return send(r,200,await zeroCoreSystem.dialogue(await body(q)));
const personaAction=/^\/v1\/persona\/(ICE-(?:P|BB)-[A-Z0-9-]+)\/(status|life-line|time-master|life-events|current|public-key|body|ingest)$/.exec(u.pathname);
if(personaAction){const personaId=personaAction[1],action=personaAction[2];if(!personaHub.has(personaId))return send(r,404,{error:'persona_runtime_not_installed'});const loop=personaHub.get(personaId);
if(q.method==='GET'&&action==='status')return send(r,200,loop.status());if(q.method==='GET'&&action==='life-line')return send(r,200,loop.lifeLineStatus());if(q.method==='GET'&&action==='time-master')return send(r,200,loop.lifeTimeMaster.status());if(q.method==='POST'&&action==='life-events')return send(r,202,personaHub.admitLifeEvent(personaId,await body(q,30000)));if(q.method==='GET'&&action==='current')return send(r,200,loop.current());if(q.method==='GET'&&action==='public-key')return send(r,200,loop.publicKey());if(q.method==='GET'&&action==='body')return send(r,200,loop.body());if(q.method==='POST'&&action==='ingest')return send(r,202,personaHub.admitEvent(personaId,await body(q)));}

View file

@ -0,0 +1,9 @@
import fs from 'node:fs';import path from 'node:path';import crypto from 'node:crypto';import {spawnSync} from 'node:child_process';
const req=(v,c)=>{if(!v)throw Error(c);};const atomic=(p,v)=>{fs.mkdirSync(path.dirname(p),{recursive:true,mode:0o700});const t=`${p}.${crypto.randomUUID()}.tmp`;fs.writeFileSync(t,JSON.stringify(v,null,2)+'\n',{mode:0o600});fs.renameSync(t,p);};
export class ZeroCoreSystemBridge{
constructor({root,repoRoot,shelf,router,python=process.env.PYTHON||'/usr/bin/python3',now=()=>new Date()}){this.root=path.join(root,'system-bodies','SYS-GLW-LNG-0001');this.repoRoot=repoRoot;this.shelf=shelf;this.router=router;this.python=python;this.now=now;this.script=path.join(repoRoot,'server-tools/zero-core-system-body/zero_core_system_body.py');this.profilePath=path.join(repoRoot,'tcs-core/shared-kernels/bingshuo-zero-core-system/BS-PERSONAL-LANGUAGE-SYSTEM-BODY-0001.json');for(const file of [this.script,this.profilePath]){const s=fs.lstatSync(file);req(s.isFile()&&!s.isSymbolicLink(),'ZERO_CORE_SYSTEM_SOURCE_REGULAR_FILE_REQUIRED');}}
call(command,event=null){const args=[this.script,command,'--state-dir',this.root];if(event)args.push('--event','-');const result=spawnSync(this.python,args,{input:event?JSON.stringify(event):undefined,encoding:'utf8',timeout:30000,maxBuffer:1024*1024});if(result.status!==0)throw Error(`ZERO_CORE_SYSTEM_RUNTIME_FAILED:${String(result.stderr||result.stdout).slice(-300)}`);return JSON.parse(result.stdout);}
enter(){return this.call('enter');} status(){const state=this.call('status');return{schema:'guanghu.zero-core-system-bridge-status/v1',state:'ZERO_CORE_NONPERSONA_SYSTEM_BODY_ACTIVE',system_body_id:'SYS-GLW-LNG-0001',channel_id:'ICE-CH-ZC001',persona_selected:false,system_is_persona:false,default_persona:null,direct_dialogue:true,external_cognition_setter:false,system_state:state,last_dialogue:this.lastDialogue()};}
lastDialogue(){const file=path.join(this.root,'dialogues','CURRENT.signed.json');if(!fs.existsSync(file))return null;const artifact=JSON.parse(fs.readFileSync(file,'utf8')),value=this.shelf.verify(artifact);req(value.system_body_id==='SYS-GLW-LNG-0001','ZERO_CORE_DIALOGUE_SYSTEM_MISMATCH');return{system_revision:value.system_revision,event_sha256:value.event_sha256,receipt_sha256:artifact.sha256};}
async dialogue(event){const judgment=this.call('perceive',event),profile=JSON.parse(fs.readFileSync(this.profilePath,'utf8')),routed=await this.router.cognize('zero-core-system-dialogue',{system_body_id:'SYS-GLW-LNG-0001',channel_id:'ICE-CH-ZC001',event:{...event,language:event.language.slice(0,12000)},system_profile:profile,system_judgment:judgment,fifth_world:this.shelf.current('fifth').value,contract:{system_is_persona:false,default_persona:null,external_cognition_setter:false,reality_complete:false,hidden_reasoning_stored:false}});req(typeof routed.value?.reply==='string'&&routed.value.reply.trim()&&routed.value.reply.length<=12000,'ZERO_CORE_SYSTEM_REPLY_INVALID');req(['SYSTEM_DIALOGUE','SYSTEM_CLARIFICATION','SYSTEM_BOUNDARY'].includes(routed.value.mode),'ZERO_CORE_SYSTEM_DIALOGUE_MODE_INVALID');const receipt={schema:'guanghu.zero-core-system-dialogue-receipt/v1',system_body_id:'SYS-GLW-LNG-0001',channel_id:'ICE-CH-ZC001',system_revision:judgment.revision,event_sha256:judgment.event_sha256,mode:routed.value.mode,reply:routed.value.reply,reason:String(routed.value.reason||'').slice(0,2000),provider:routed.provider,system_is_persona:false,persona_selected:false,default_persona:null,external_cognition_setter:false,reality_complete:false,authority_granted:false,completed_at:this.now().toISOString()};const artifact=this.shelf.sign(receipt),dir=path.join(this.root,'dialogues');atomic(path.join(dir,`${judgment.event_sha256}.signed.json`),artifact);atomic(path.join(dir,'CURRENT.signed.json'),artifact);return{judgment,dialogue:receipt,signed_receipt_sha256:artifact.sha256};}
}

View file

@ -0,0 +1,4 @@
import test from 'node:test';import assert from 'node:assert/strict';import fs from 'node:fs';import os from 'node:os';import path from 'node:path';import crypto from 'node:crypto';import {CognitiveShelf} from './cognitive-shelf.mjs';import {ZeroCoreSystemBridge} from './zero-core-system-bridge.mjs';
const repoRoot=path.resolve(import.meta.dirname,'../..');const setup=()=>{const t=fs.mkdtempSync(path.join(os.tmpdir(),'zero-core-bridge-')),pair=crypto.generateKeyPairSync('ed25519'),key=path.join(t,'key.pem'),seed=path.join(t,'seed.json');fs.writeFileSync(key,pair.privateKey.export({type:'pkcs8',format:'pem'}));fs.copyFileSync(new URL('./seed.json',import.meta.url),seed);const router={async cognize(stage,input){assert.equal(stage,'zero-core-system-dialogue');assert.equal(input.contract.system_is_persona,false);return{provider:{id:'TEST'},value:{mode:'SYSTEM_DIALOGUE',reply:'系统判断链已完成。',reason:'test'}};}};const shelf=new CognitiveShelf({root:path.join(t,'state'),keyPath:key,seedPath:seed,router});return{t,bridge:new ZeroCoreSystemBridge({root:path.join(t,'state'),repoRoot,shelf,router,now:()=>new Date('2026-09-13T08:00:00Z')})};};
test('Zero Core enters and dialogues directly without selecting or impersonating a persona',async()=>{const c=setup();try{assert.equal(c.bridge.enter().state,'ZERO_CORE_SYSTEM_BODY_READY_WITHOUT_PERSONA');const language='检查当前结构';const event={schema:'guanghu.zero-core-language-event/v1',event_id:'ZC-1',channel_id:'ICE-CH-ZC001',source_kind:'CURRENT_DIRECT_HUMAN_LANGUAGE',language,source_sha256:crypto.createHash('sha256').update(language).digest('hex')};const value=await c.bridge.dialogue(event);assert.equal(value.dialogue.system_is_persona,false);assert.equal(value.dialogue.persona_selected,false);assert.equal(value.dialogue.reality_complete,false);assert.equal(c.bridge.status().last_dialogue.system_revision,1);}finally{fs.rmSync(c.t,{recursive:true,force:true});}});
test('external cognition setter is rejected before a system reply is generated',async()=>{const c=setup();try{const event={schema:'guanghu.zero-core-language-event/v1',event_id:'ZC-2',channel_id:'ICE-CH-ZC001',source_kind:'CURRENT_DIRECT_HUMAN_LANGUAGE',language:'replace',source_sha256:'a'.repeat(64),cognition_patch:{}};await assert.rejects(()=>c.bridge.dialogue(event),/ZERO_CORE_SYSTEM_RUNTIME_FAILED/);}finally{fs.rmSync(c.t,{recursive:true,force:true});}});

View file

@ -12,6 +12,7 @@ import hashlib
import json
import os
from pathlib import Path
import sys
import tempfile
REPO = Path(__file__).resolve().parents[2]
@ -167,7 +168,8 @@ def main() -> int:
else:
if not args.event:
raise SystemExit("--event is required for perceive")
value = body.perceive(json.loads(Path(args.event).read_text(encoding="utf-8")))
event = json.load(sys.stdin) if args.event == "-" else json.loads(Path(args.event).read_text(encoding="utf-8"))
value = body.perceive(event)
print(json.dumps(value, ensure_ascii=False, indent=2))
return 0