发布光湖当前规则、跨软件技能与受控问脑入口

This commit is contained in:
铸渊 ICE-P-ZY001 2026-10-19 19:35:33 +08:00
commit 56467ef79f
14 changed files with 388 additions and 0 deletions

13
scripts/build-release.py Normal file
View file

@ -0,0 +1,13 @@
from pathlib import Path
import json,hashlib,zipfile,datetime,stat
p=Path(__file__).resolve().parents[1];sha=lambda b:hashlib.sha256(b).hexdigest();files=[]
for f in sorted(p.rglob('*')):
if f.is_file() and f.name not in ['CURRENT.json','MANIFEST.json','release.zip'] and '.git' not in f.parts:
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')
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())
j={**man,'schema':'guanghu.public-rule-release/v1','bundle_url':'https://guanghulab.com/api/ai/v1/rule-bundle','bundle_sha256':sha((p/'release.zip').read_bytes()),'manifest_sha256':sha((p/'MANIFEST.json').read_bytes()),'repository':'https://guanghulab.com/code/bingshuo/guanghu-world-entry','private_brain_included':False,'complete_four_domain_corpus_included':False,'default_persona':None};(p/'CURRENT.json').write_text(json.dumps(j,ensure_ascii=False,indent=2)+'\n');print(json.dumps({'files':len(files),'bundle_bytes':(p/'release.zip').stat().st_size,'bundle_sha256':j['bundle_sha256']}))

View file

@ -0,0 +1,16 @@
#!/usr/bin/env node
// HOST_NEUTRAL_TRANSPORT: verifies released files, reads status or asks with independent user credentials.
import {spawnSync} from 'node:child_process';import fs from 'node:fs';import path from 'node:path';import crypto from 'node:crypto';import {fileURLToPath} from 'node:url';
const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..'),sha=x=>crypto.createHash('sha256').update(x).digest('hex'),manifest=JSON.parse(fs.readFileSync(path.join(root,'MANIFEST.json')));
const fail=c=>{throw Error(c)};
for(const x of manifest.files){if(path.isAbsolute(x.path)||x.path.split('/').includes('..'))fail('RELEASE_PATH_INVALID');const p=path.join(root,x.path);if(fs.realpathSync(p)!==p||!fs.statSync(p).isFile()||sha(fs.readFileSync(p))!==x.sha256)fail('RELEASE_FILE_HASH_MISMATCH');}
const args=process.argv.slice(2),cmd=args.shift()||'status',flag=k=>{const n=args.indexOf(k);if(n<0)return null;const v=args[n+1];if(!v)fail('ARGUMENT_REQUIRED');args.splice(n,2);return v;};
try{
if(cmd==='verify'){console.log(JSON.stringify({state:'PUBLIC_RELEASE_FILES_VERIFIED',version:manifest.version,files:manifest.files.length}));}
else if(cmd==='status'){const r=await fetch('https://guanghulab.com/api/ai/v1/status',{signal:AbortSignal.timeout(10000)});console.log(JSON.stringify(await r.json(),null,2));if(!r.ok)process.exitCode=2;}
else if(cmd==='ask'){
const persona=flag('--persona'),host=flag('--host'),session=flag('--session'),file=flag('--question-file');if(args.length||!persona||!host||!session||!file)fail('EXPLICIT_PERSONA_HOST_SESSION_AND_QUESTION_REQUIRED');
let token=process.env.GUANGHU_ASK_TOKEN;if(!token&&process.platform==='darwin'){const r=spawnSync('/usr/bin/security',['find-generic-password','-s','guanghu-persona-question','-a','owner','-w'],{encoding:'utf8',timeout:3000});if(r.status===0)token=r.stdout.trim();}if(!token)fail('PRIVATE_QUESTION_CREDENTIAL_REQUIRED');const question=fs.readFileSync(file,'utf8');const body={persona_id:persona,tool_host:host,session_id:session,request_id:crypto.randomUUID(),question};
const r=await fetch('https://guanghulab.com/api/ai/v1/ask',{method:'POST',headers:{'content-type':'application/json',authorization:'Bearer '+token},body:JSON.stringify(body),signal:AbortSignal.timeout(55000)});console.log(JSON.stringify(await r.json(),null,2));if(!r.ok)process.exitCode=2;
}else fail('COMMAND_NOT_SUPPORTED');
}catch(e){console.log(JSON.stringify({state:'QUESTION_OR_RELEASE_UNAVAILABLE',code:/^[A-Z_]+$/.test(e.message)?e.message:'TRANSPORT_FAILED',no_execution_authority:true}));process.exitCode=2;}