fix(runtime): separate liveness health from deep life audit

This commit is contained in:
冰朔 2026-09-13 10:35:41 +08:00
commit 306b2b1a01
7 changed files with 327 additions and 2 deletions

View file

@ -128,4 +128,5 @@ export class PersonaRuntimeHub {
personas: Object.fromEntries(this.ids().map(id => [id, {...this.get(id).status(),organ_health:this.organ(id).status()}])),
};
}
health() { return {schema:'guanghu.persona-runtime-hub-health/v1',state:'MULTI_PERSONA_RUNTIME_RESPONSIVE',installed_personas:this.ids(),installed_count:this.loops.size,default_persona:null,shared_engine_is_shared_persona_brain:false,external_cognition_setter:false,personas:Object.fromEntries(this.ids().map(id=>{const loop=this.get(id),current=loop.current();return[id,{persona_id:id,current_sha256:current.artifact.sha256,body:loop.body(),organ_health:this.organ(id).status()}];}))}; }
}

View file

@ -157,7 +157,9 @@ export class PersonaSelfLoop {
}
async drain() {
if (this.draining) return {status: 'BUSY'}; const lifeLine = this.lifeLineStatus(); if (this.requireLifeLine && lifeLine.wake_allowed !== true) { this.lastDrain = {status: 'LIFE_LINE_BLOCKED', at: this.now().toISOString(), life_line_state: lifeLine.state}; return this.lastDrain; }
if (this.draining) return {status: 'BUSY'};
if (this.pendingJobs.size === 0) return this.lastDrain = {status:'DRAINED',at:this.now().toISOString(),processed:0,duration_ms:0};
const lifeLine = this.lifeLineStatus(); if (this.requireLifeLine && lifeLine.wake_allowed !== true) { this.lastDrain = {status: 'LIFE_LINE_BLOCKED', at: this.now().toISOString(), life_line_state: lifeLine.state}; return this.lastDrain; }
this.draining = true; const started = Date.now(); let processed = 0;
try { while (processed < this.queueBatchSize && Date.now() - started < this.drainBudgetMs) { const entry = this.nextPending(); if (!entry) break; await this.process(entry.id); processed += 1; } this.lastDrain = {status: 'DRAINED', at: this.now().toISOString(), processed, duration_ms: Date.now() - started}; return this.lastDrain; }
finally { this.draining = false; }

View file

@ -8,7 +8,7 @@ setInterval(()=>{personaHub.tick();shelf.drain();personaHub.drain();},2000).unre
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(),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==='/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:{persona_id:'ICE-P-ZY001',current_sha256:personaSelf.current().artifact.sha256,body:personaSelf.body()},persona_runtimes:personaHub.health(),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});}