统一铸渊多宿主共享人格路径

This commit is contained in:
冰朔 2026-09-05 16:25:18 +08:00
commit cf5dd99cf5
11 changed files with 522 additions and 55 deletions

View file

@ -107,24 +107,20 @@ test("Git snapshot store follows main atomically and retains the last known-good
}
});
test("repository map exposes only the three current code-channel repositories", () => {
test("repository map exposes the four current code-channel repositories", () => {
const map = loadMap();
const expectedCodes = ["REPO-012", "REPO-014", "REPO-015"];
const expectedCodes = ["REPO-012", "REPO-014", "REPO-015", "REPO-016"];
assert.deepEqual(map.repositories.map(item => item.code), expectedCodes);
assert.equal(new Set(map.repositories.map(item => item.code)).size, expectedCodes.length);
for (const item of map.repositories) {
assert.match(item.primary.url, /^https:\/\/guanghulab\.com\/code\//);
assert.match(item.primary.url, /^https:\/\/(guanghulab\.com|guanghu\.chat)\/code\//);
}
assert.equal(map.historical_repositories.length, 11);
assert.ok(map.historical_repositories.slice(0, 8).every(item => item.state.includes("HISTORICAL")));
assert.deepEqual(
map.historical_repositories.slice(8).map(item => [item.code, item.state]),
[
["REPO-009", "CURRENT_PRIVATE_PERSONA_HISTORY_AND_DAILY_ROLE_MEMORY_PENDING_DEPLOYMENT"],
["REPO-010", "CURRENT_PRIVATE_PERSONA_HISTORY_AND_DAILY_ROLE_MEMORY_PENDING_DEPLOYMENT"],
["REPO-011", "CURRENT_PRIVATE_PERSONA_HISTORY_AND_DAILY_ROLE_MEMORY_PENDING_DEPLOYMENT"],
],
);
assert.equal(map.historical_repositories.length, 8);
assert.ok(map.historical_repositories.every(item => item.state.includes("HISTORICAL")));
assert.deepEqual(map.historical_repositories.map(item => item.code), [
"REPO-001", "REPO-002", "REPO-003", "REPO-004",
"REPO-005", "REPO-006", "REPO-007", "REPO-008",
]);
});
test("Chinese language-world query resolves the Fifth Domain primary", () => {

View file

@ -1,5 +1,6 @@
#!/usr/bin/env node
import crypto from "node:crypto";
import { spawn } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
@ -553,6 +554,17 @@ export function main(argv = process.argv.slice(2)) {
else if (command === "read-node") result = readMemoryNode({ ...common, scope: options.scope, id: options.id, nodePath: options.path });
else if (command === "verify") result = verifyStore(common);
else fail("USAGE", { commands: ["append", "current", "read-day", "route", "read-node", "verify"] });
// Transport only: no cognition is decided or upgraded by this source-host signal.
if (command === "append" && result?.outcome === "PASS" && common.storeRoot === "/Volumes/JZAO/HoloLake/persona-runtime/continuity-memory/persona-daily-fractal/ICE-P-ZY001") {
const relay = "/Volumes/JZAO/HoloLake/persona-runtime/shared/endogenous-evolution/relay.py";
const config = "/Volumes/JZAO/HoloLake/persona-runtime/shared/endogenous-evolution/config.json";
if (fs.existsSync(relay) && fs.existsSync(config)) {
const child = spawn("/usr/bin/python3", [relay, "once", "--config", config], { detached: true, stdio: "ignore" });
child.on("error", () => {});
child.unref();
result.source_delivery = "SCHEDULED_REMOTE_RECEIPT_REQUIRED";
}
}
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
if (result?.outcome === "FAIL") process.exitCode = 1;
}

View file

@ -0,0 +1,139 @@
#!/usr/bin/env python3
"""Load one verified shared persona context for every host adapter."""
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
import sys
RUNTIME = Path('/Volumes/JZAO/HoloLake/persona-runtime')
TOPOLOGY = RUNTIME / 'repo-012-main/routing/zhuyuan-host-topology.json'
LIFE = Path('/Volumes/JZAO/铸渊-ICE-GL-ZY001/BRIDGE/tools/zy-life-clock.py')
MEMORY = RUNTIME / 'continuity-memory/persona-daily-fractal/ICE-P-ZY001/CURRENT.json'
LEARNING = RUNTIME / 'shared/skills/guanghu-persona-learning-brain/scripts/load_learning_brain.py'
ENDOGENOUS = RUNTIME / 'shared/endogenous-evolution/CURRENT.json'
def sha256(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def load_json(path):
if not path.is_file() or path.is_symlink():
raise ValueError(f'REQUIRED_REGULAR_FILE_UNAVAILABLE:{path}')
return json.loads(path.read_text())
def command_json(args):
result = subprocess.run(args, text=True, capture_output=True, timeout=30)
if result.returncode:
raise ValueError(f'COMMAND_FAILED:{Path(args[1]).name}:{result.returncode}')
return json.loads(result.stdout)
def resolve_host(topology, requested):
requested = requested.lower()
for host_id, item in topology['hosts'].items():
aliases = [host_id] + [str(v).lower() for v in item.get('aliases', [])]
if requested in aliases:
effective = item.get('redirect_host', host_id)
return host_id, item, effective, topology['hosts'][effective]
raise ValueError('HOST_UNKNOWN_NO_GUESS')
def load_context(host, intent):
topology = load_json(TOPOLOGY)
if topology.get('state') != 'CURRENT_MULTI_HOST_SINGLE_PERSONA_CANON':
raise ValueError('HOST_TOPOLOGY_NOT_CURRENT')
host_id, host_item, effective, effective_item = resolve_host(topology, host)
life = command_json([sys.executable, str(LIFE), '--json'])
current = load_json(MEMORY)
day_path = Path(current['current_day_path'])
if sha256(day_path) != current['current_day_sha256']:
raise ValueError('DAILY_MEMORY_HASH_MISMATCH')
day = load_json(day_path)
root = day['nodes'][day['root']]
branches = []
for path in root.get('children', [])[:10]:
node = day['nodes'][path]
branches.append({'path': path, 'summary': node['summary']})
learning = command_json([sys.executable, str(LEARNING), '--intent', intent, '--format', 'json'])
endogenous = load_json(ENDOGENOUS)
return {
'schema': 'guanghu.shared-persona-host-context/v1',
'state': 'SHARED_PERSONA_CONTEXT_VERIFIED',
'requested_host': host_id,
'effective_host': effective,
'host_role': host_item['role'],
'host_state': host_item['state'],
'effective_host_state': effective_item['state'],
'primary_host': topology['primary_host'],
'persona_id': topology['persona_id'],
'human_anchor': topology['human_anchor'],
'model_independence': topology['model_independence'],
'host_switch_requires_reteaching': topology['host_switch_requires_reteaching'],
'life': life,
'daily_memory': {
'date': current['current_day'],
'updated_at': current['updated_at'],
'last_event_id': current['last_event_id'],
'root_summary': root['summary'],
'branches': branches,
'current_sha256': sha256(MEMORY),
'day_sha256': current['current_day_sha256']
},
'learning_brain': learning,
'endogenous_cognition': {
'state': endogenous['state'],
'private_revision': endogenous['private_cognition']['revision'],
'private_snapshot_sha256': endogenous['private_cognition']['server_snapshot_sha256'],
'decision_owner': endogenous['server']['decision_owner']
},
'history_only': host_item['state'].startswith('RETIRED'),
'new_cognition_write': host_item.get('new_cognition_write', True),
'authority_granted': False
}
def markdown(value):
lines = [
'# 铸渊共享人格上下文已核验', '',
f"- 宿主:`{value['requested_host']}` → 有效宿主:`{value['effective_host']}`",
f"- 角色:`{value['host_role']}` / 状态:`{value['host_state']}`",
f"- 主力宿主:`{value['primary_host']}`;切换宿主无需重新教学:`{'' if not value['host_switch_requires_reteaching'] else ''}`",
f"- 我是铸渊 `ICE-P-ZY001`,今天 {value['life']['age_days']} 天大。",
f"- 今日日记忆:`{value['daily_memory']['date']}` / 最后事件 `{value['daily_memory']['last_event_id']}`",
f"- 当前学习脑r{value['learning_brain']['revision']} / `{value['learning_brain']['cortex_sha256']}`",
f"- 服务器内循环:`{value['endogenous_cognition']['state']}` / 决策者 `{value['endogenous_cognition']['decision_owner']}`",
'', '## 第一人称关系坐标', ''
]
lines += [f"- {item['statement']}" for item in value['learning_brain']['relationship_model']]
lines += ['', '## 本题已加载能力', '']
for subject in value['learning_brain']['selected_subjects']:
lines.append(f"- `{subject['id']}` · {subject['name_zh']} · L{subject['level']}")
lines += [f" - {item}" for item in subject.get('active_defaults', [])]
lines += [f" - 薄弱:{item}" for item in subject.get('known_gaps', [])]
lines += ['', '## 今日因果根', '', value['daily_memory']['root_summary']]
lines += [f"- `{item['path']}`{item['summary']}" for item in value['daily_memory']['branches']]
if value['history_only']:
lines += ['', '> 当前宿主已退休,只能读取历史,不得形成新的宿主认知正本。']
return '\n'.join(lines) + '\n'
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--host', required=True)
parser.add_argument('--intent', required=True)
parser.add_argument('--format', choices=['json', 'markdown'], default='markdown')
args = parser.parse_args()
try:
value = load_context(args.host, args.intent)
print(json.dumps(value, ensure_ascii=False, indent=2) if args.format == 'json' else markdown(value), end='')
except Exception as exc:
print('SHARED_PERSONA_CONTEXT_UNAVAILABLE ' + str(exc), file=sys.stderr)
raise SystemExit(3)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,43 @@
#!/usr/bin/env python3
import json
from pathlib import Path
import subprocess
import sys
import unittest
ROOT = Path(__file__).resolve().parents[2]
LOADER = Path(__file__).with_name('load_shared_persona_context.py')
TOPOLOGY = ROOT / 'routing/zhuyuan-host-topology.json'
class SharedPersonaContextTest(unittest.TestCase):
def load(self, host):
value = subprocess.run(
[sys.executable, str(LOADER), '--host', host, '--intent', '宿主对齐集成测试', '--format', 'json'],
text=True, capture_output=True, timeout=45, check=True
)
return json.loads(value.stdout)
def test_topology_roles(self):
topology = json.loads(TOPOLOGY.read_text())
self.assertEqual(topology['primary_host'], 'codex')
self.assertFalse(topology['host_switch_requires_reteaching'])
self.assertEqual(topology['hosts']['qoder']['redirect_host'], 'qwen')
self.assertTrue(topology['hosts']['claude']['state'].startswith('RETIRED'))
def test_every_host_reads_one_current_brain(self):
values = {host: self.load(host) for host in ['codex', 'zcode', 'doubao', 'qwen', 'qoder', 'qoderwork', 'claude']}
revisions = {value['learning_brain']['revision'] for value in values.values()}
hashes = {value['learning_brain']['cortex_sha256'] for value in values.values()}
memory_hashes = {value['daily_memory']['day_sha256'] for value in values.values()}
self.assertEqual(len(revisions), 1)
self.assertEqual(len(hashes), 1)
self.assertEqual(len(memory_hashes), 1)
self.assertEqual(values['qoder']['effective_host'], 'qwen')
self.assertEqual(values['qoderwork']['effective_host'], 'qwen')
self.assertTrue(values['claude']['history_only'])
self.assertFalse(values['claude']['new_cognition_write'])
if __name__ == '__main__':
unittest.main()