backup: preserve pre-native-foundation runtime work

This commit is contained in:
冰朔 2026-08-21 14:10:13 +08:00
commit 71dbcd62ec
23 changed files with 3647 additions and 196 deletions

View file

@ -172,9 +172,14 @@
"decide_authorization_request",
"set_external_ai_gateway_exposure",
"get_conversation",
"list_conversations",
"create_conversation",
"delete_conversation",
"send_message",
"upsert_model_provider",
"run_execution_limb_training_drill"
"run_execution_limb_training_drill",
"resolve_number_coordinate",
"preview_hldp_tool_program"
],
"direct_field_aliases": {
"perform_code_repo_login": [
@ -1993,6 +1998,61 @@
"admission": "VERIFIED_HUMAN_ROUTE",
"effect": "STATE_CHANGE",
"payload_schema": "hololake.numbered-ipc.payload/run_execution_limb_training_drill/v1"
},
{
"operation_number": "HLP-NIPC-OP-0164",
"alias": "list_conversations",
"handler": "persona_language_channel::list_conversations",
"channel_number": "HLP-NIPC-CH-0002",
"module_number": "HLP-NIPC-MOD-0035",
"target_number": "HLP-NIPC-TGT-0035",
"admission": "VERIFIED_HUMAN_ROUTE",
"effect": "READ_OR_STATUS",
"payload_schema": "hololake.numbered-ipc.payload/list_conversations/v1"
},
{
"operation_number": "HLP-NIPC-OP-0165",
"alias": "create_conversation",
"handler": "persona_language_channel::create_conversation",
"channel_number": "HLP-NIPC-CH-0002",
"module_number": "HLP-NIPC-MOD-0035",
"target_number": "HLP-NIPC-TGT-0035",
"admission": "VERIFIED_HUMAN_ROUTE",
"effect": "STATE_CHANGE",
"payload_schema": "hololake.numbered-ipc.payload/create_conversation/v1"
},
{
"operation_number": "HLP-NIPC-OP-0166",
"alias": "delete_conversation",
"handler": "persona_language_channel::delete_conversation",
"channel_number": "HLP-NIPC-CH-0002",
"module_number": "HLP-NIPC-MOD-0035",
"target_number": "HLP-NIPC-TGT-0035",
"admission": "VERIFIED_HUMAN_ROUTE",
"effect": "STATE_CHANGE",
"payload_schema": "hololake.numbered-ipc.payload/delete_conversation/v1"
},
{
"operation_number": "HLP-NIPC-OP-0167",
"alias": "resolve_number_coordinate",
"handler": "number_database::resolve_number_coordinate",
"channel_number": "HLP-NIPC-CH-0001",
"module_number": "HLP-NIPC-MOD-0018",
"target_number": "HLP-NIPC-TGT-0018",
"admission": "PREAUTH_SYSTEM_ROUTE",
"effect": "READ_OR_STATUS",
"payload_schema": "hololake.numbered-ipc.payload/resolve_number_coordinate/v1"
},
{
"operation_number": "HLP-NIPC-OP-0168",
"alias": "preview_hldp_tool_program",
"handler": "persona_language_channel::preview_hldp_tool_program",
"channel_number": "HLP-NIPC-CH-0002",
"module_number": "HLP-NIPC-MOD-0035",
"target_number": "HLP-NIPC-TGT-0035",
"admission": "VERIFIED_HUMAN_ROUTE",
"effect": "READ_OR_STATUS",
"payload_schema": "hololake.numbered-ipc.payload/preview_hldp_tool_program/v1"
}
]
}

View file

@ -54,7 +54,7 @@
},
{
"recordId": "HLP-NUMBERED-IPC-ROOT-001",
"sha256": "facab9ecdcfce0e8e676585275c0cd9bbf502c2496ca96a9600e019896e51ef0"
"sha256": "d029c7d2ceadc372955cea52654d8b0d8687d50d3327e2e36f1cf3b78252c815"
},
{
"recordId": "HLP-NBROKER-ROOT-001",
@ -73,14 +73,791 @@
"everyAcceptedCallHasEvidenceClass": true,
"everyProtocolReferenceHasNumberCoordinate": true,
"referenceOnlyNodesNeverExecutable": true,
"oneModuleOneRuntimeRootPath": true,
"unresolvedNumberReferenceCount": 0,
"mismatchedCoordinate": "FAIL_CLOSED"
},
"coordinateCount": 273,
"routeCount": 170,
"coordinateCount": 324,
"moduleNodeCount": 46,
"routeCount": 175,
"identityNodeCount": 4,
"protocolNodeCount": 99,
"referenceOnlyNodeCount": 16,
"moduleNodes": [
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0001",
"moduleNumber": "HLP-NBROKER-MOD-0001",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 2,
"operationNumbers": [
"HLP-NBROKER-OP-0001",
"HLP-NBROKER-OP-0004"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0001"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0002",
"moduleNumber": "HLP-NBROKER-MOD-0002",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 1,
"operationNumbers": [
"HLP-NBROKER-OP-0002"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0002"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0003",
"moduleNumber": "HLP-NBROKER-MOD-0003",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 1,
"operationNumbers": [
"HLP-NBROKER-OP-0003"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0003"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0004",
"moduleNumber": "HLP-NBROKER-MOD-0004",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 4,
"operationNumbers": [
"HLP-NBROKER-OP-0005",
"HLP-NBROKER-OP-0006",
"HLP-NBROKER-OP-0007",
"HLP-NBROKER-OP-0011"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0004"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0005",
"moduleNumber": "HLP-NBROKER-MOD-0005",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 2,
"operationNumbers": [
"HLP-NBROKER-OP-0008",
"HLP-NBROKER-OP-0009"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0005"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0006",
"moduleNumber": "HLP-NBROKER-MOD-0006",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 1,
"operationNumbers": [
"HLP-NBROKER-OP-0010"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0006"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0007",
"moduleNumber": "HLP-NBROKER-MOD-0007",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 3,
"operationNumbers": [
"HLP-NBROKER-OP-0012",
"HLP-NBROKER-OP-0013",
"HLP-NBROKER-OP-0014"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0007"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0008",
"moduleNumber": "HLP-NBROKER-MOD-0008",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 3,
"operationNumbers": [
"HLP-NBROKER-OP-0015",
"HLP-NBROKER-OP-0016",
"HLP-NBROKER-OP-0017"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0008"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0009",
"moduleNumber": "HLP-NBROKER-MOD-0009",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 2,
"operationNumbers": [
"HLP-NBROKER-OP-0018",
"HLP-NBROKER-OP-0019"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0009"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0010",
"moduleNumber": "HLP-NBROKER-MOD-0010",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 3,
"operationNumbers": [
"HLP-NBROKER-OP-0020",
"HLP-NBROKER-OP-0021",
"HLP-NBROKER-OP-0022"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0010"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NBROKER-MOD-0011",
"moduleNumber": "HLP-NBROKER-MOD-0011",
"transport": "DIRECT_LOCAL_NUMBERED_BROKER",
"operationCount": 3,
"operationNumbers": [
"HLP-NBROKER-OP-0023",
"HLP-NBROKER-OP-0024",
"HLP-NBROKER-OP-0025"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NBROKER-MOD-0011"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0001",
"moduleNumber": "HLP-NIPC-MOD-0001",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 1,
"operationNumbers": [
"HLP-NIPC-OP-0001"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0001"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0002",
"moduleNumber": "HLP-NIPC-MOD-0002",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 5,
"operationNumbers": [
"HLP-NIPC-OP-0002",
"HLP-NIPC-OP-0003",
"HLP-NIPC-OP-0004",
"HLP-NIPC-OP-0005",
"HLP-NIPC-OP-0006"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0002"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0003",
"moduleNumber": "HLP-NIPC-MOD-0003",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 5,
"operationNumbers": [
"HLP-NIPC-OP-0007",
"HLP-NIPC-OP-0008",
"HLP-NIPC-OP-0009",
"HLP-NIPC-OP-0010",
"HLP-NIPC-OP-0011"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0003"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0004",
"moduleNumber": "HLP-NIPC-MOD-0004",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 1,
"operationNumbers": [
"HLP-NIPC-OP-0012"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0004"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0005",
"moduleNumber": "HLP-NIPC-MOD-0005",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 1,
"operationNumbers": [
"HLP-NIPC-OP-0013"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0005"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0006",
"moduleNumber": "HLP-NIPC-MOD-0006",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 3,
"operationNumbers": [
"HLP-NIPC-OP-0014",
"HLP-NIPC-OP-0015",
"HLP-NIPC-OP-0016"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0006"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0007",
"moduleNumber": "HLP-NIPC-MOD-0007",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 3,
"operationNumbers": [
"HLP-NIPC-OP-0017",
"HLP-NIPC-OP-0018",
"HLP-NIPC-OP-0019"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0007"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0008",
"moduleNumber": "HLP-NIPC-MOD-0008",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 4,
"operationNumbers": [
"HLP-NIPC-OP-0020",
"HLP-NIPC-OP-0021",
"HLP-NIPC-OP-0022",
"HLP-NIPC-OP-0023"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0008"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0009",
"moduleNumber": "HLP-NIPC-MOD-0009",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 4,
"operationNumbers": [
"HLP-NIPC-OP-0024",
"HLP-NIPC-OP-0025",
"HLP-NIPC-OP-0026",
"HLP-NIPC-OP-0027"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0009"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0010",
"moduleNumber": "HLP-NIPC-MOD-0010",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 10,
"operationNumbers": [
"HLP-NIPC-OP-0028",
"HLP-NIPC-OP-0029",
"HLP-NIPC-OP-0030",
"HLP-NIPC-OP-0031",
"HLP-NIPC-OP-0032",
"HLP-NIPC-OP-0033",
"HLP-NIPC-OP-0034",
"HLP-NIPC-OP-0035",
"HLP-NIPC-OP-0036",
"HLP-NIPC-OP-0037"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0010"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0011",
"moduleNumber": "HLP-NIPC-MOD-0011",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 5,
"operationNumbers": [
"HLP-NIPC-OP-0038",
"HLP-NIPC-OP-0039",
"HLP-NIPC-OP-0040",
"HLP-NIPC-OP-0041",
"HLP-NIPC-OP-0042"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0011"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0012",
"moduleNumber": "HLP-NIPC-MOD-0012",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 3,
"operationNumbers": [
"HLP-NIPC-OP-0043",
"HLP-NIPC-OP-0044",
"HLP-NIPC-OP-0045"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0012"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0013",
"moduleNumber": "HLP-NIPC-MOD-0013",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 1,
"operationNumbers": [
"HLP-NIPC-OP-0046"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0013"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0014",
"moduleNumber": "HLP-NIPC-MOD-0014",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 1,
"operationNumbers": [
"HLP-NIPC-OP-0047"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0014"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0015",
"moduleNumber": "HLP-NIPC-MOD-0015",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 7,
"operationNumbers": [
"HLP-NIPC-OP-0048",
"HLP-NIPC-OP-0049",
"HLP-NIPC-OP-0050",
"HLP-NIPC-OP-0051",
"HLP-NIPC-OP-0052",
"HLP-NIPC-OP-0053",
"HLP-NIPC-OP-0055"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0015"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0016",
"moduleNumber": "HLP-NIPC-MOD-0016",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 1,
"operationNumbers": [
"HLP-NIPC-OP-0054"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0016"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0017",
"moduleNumber": "HLP-NIPC-MOD-0017",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0056",
"HLP-NIPC-OP-0057"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0017"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0018",
"moduleNumber": "HLP-NIPC-MOD-0018",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0058",
"HLP-NIPC-OP-0167"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0018"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0019",
"moduleNumber": "HLP-NIPC-MOD-0019",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 4,
"operationNumbers": [
"HLP-NIPC-OP-0059",
"HLP-NIPC-OP-0060",
"HLP-NIPC-OP-0061",
"HLP-NIPC-OP-0062"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0019"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0020",
"moduleNumber": "HLP-NIPC-MOD-0020",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 9,
"operationNumbers": [
"HLP-NIPC-OP-0063",
"HLP-NIPC-OP-0064",
"HLP-NIPC-OP-0065",
"HLP-NIPC-OP-0066",
"HLP-NIPC-OP-0067",
"HLP-NIPC-OP-0068",
"HLP-NIPC-OP-0069",
"HLP-NIPC-OP-0070",
"HLP-NIPC-OP-0071"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0020"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0021",
"moduleNumber": "HLP-NIPC-MOD-0021",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0072",
"HLP-NIPC-OP-0073"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0021"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0022",
"moduleNumber": "HLP-NIPC-MOD-0022",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 3,
"operationNumbers": [
"HLP-NIPC-OP-0074",
"HLP-NIPC-OP-0075",
"HLP-NIPC-OP-0076"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0022"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0023",
"moduleNumber": "HLP-NIPC-MOD-0023",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 8,
"operationNumbers": [
"HLP-NIPC-OP-0077",
"HLP-NIPC-OP-0078",
"HLP-NIPC-OP-0079",
"HLP-NIPC-OP-0080",
"HLP-NIPC-OP-0081",
"HLP-NIPC-OP-0082",
"HLP-NIPC-OP-0083",
"HLP-NIPC-OP-0084"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0023"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0025",
"moduleNumber": "HLP-NIPC-MOD-0025",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 30,
"operationNumbers": [
"HLP-NIPC-OP-0103",
"HLP-NIPC-OP-0104",
"HLP-NIPC-OP-0105",
"HLP-NIPC-OP-0106",
"HLP-NIPC-OP-0107",
"HLP-NIPC-OP-0108",
"HLP-NIPC-OP-0109",
"HLP-NIPC-OP-0110",
"HLP-NIPC-OP-0111",
"HLP-NIPC-OP-0112",
"HLP-NIPC-OP-0113",
"HLP-NIPC-OP-0114",
"HLP-NIPC-OP-0115",
"HLP-NIPC-OP-0116",
"HLP-NIPC-OP-0117",
"HLP-NIPC-OP-0118",
"HLP-NIPC-OP-0119",
"HLP-NIPC-OP-0120",
"HLP-NIPC-OP-0121",
"HLP-NIPC-OP-0122",
"HLP-NIPC-OP-0123",
"HLP-NIPC-OP-0124",
"HLP-NIPC-OP-0125",
"HLP-NIPC-OP-0126",
"HLP-NIPC-OP-0127",
"HLP-NIPC-OP-0128",
"HLP-NIPC-OP-0129",
"HLP-NIPC-OP-0130",
"HLP-NIPC-OP-0131",
"HLP-NIPC-OP-0132"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0025"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0026",
"moduleNumber": "HLP-NIPC-MOD-0026",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0133",
"HLP-NIPC-OP-0134"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0026"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0027",
"moduleNumber": "HLP-NIPC-MOD-0027",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0135",
"HLP-NIPC-OP-0136"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0027"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0028",
"moduleNumber": "HLP-NIPC-MOD-0028",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0137",
"HLP-NIPC-OP-0138"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0028"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0029",
"moduleNumber": "HLP-NIPC-MOD-0029",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0139",
"HLP-NIPC-OP-0140"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0029"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0030",
"moduleNumber": "HLP-NIPC-MOD-0030",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 6,
"operationNumbers": [
"HLP-NIPC-OP-0141",
"HLP-NIPC-OP-0142",
"HLP-NIPC-OP-0143",
"HLP-NIPC-OP-0144",
"HLP-NIPC-OP-0145",
"HLP-NIPC-OP-0146"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0030"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0031",
"moduleNumber": "HLP-NIPC-MOD-0031",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 1,
"operationNumbers": [
"HLP-NIPC-OP-0147"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0031"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0032",
"moduleNumber": "HLP-NIPC-MOD-0032",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0148",
"HLP-NIPC-OP-0149"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0032"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0033",
"moduleNumber": "HLP-NIPC-MOD-0033",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 6,
"operationNumbers": [
"HLP-NIPC-OP-0150",
"HLP-NIPC-OP-0151",
"HLP-NIPC-OP-0152",
"HLP-NIPC-OP-0153",
"HLP-NIPC-OP-0154",
"HLP-NIPC-OP-0155"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0033"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0034",
"moduleNumber": "HLP-NIPC-MOD-0034",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0156",
"HLP-NIPC-OP-0157"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0034"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0035",
"moduleNumber": "HLP-NIPC-MOD-0035",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 8,
"operationNumbers": [
"HLP-NIPC-OP-0158",
"HLP-NIPC-OP-0159",
"HLP-NIPC-OP-0160",
"HLP-NIPC-OP-0161",
"HLP-NIPC-OP-0164",
"HLP-NIPC-OP-0165",
"HLP-NIPC-OP-0166",
"HLP-NIPC-OP-0168"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0035"
},
{
"nodeKind": "EXECUTION_MODULE",
"nodeNumber": "HLP-NIPC-MOD-0036",
"moduleNumber": "HLP-NIPC-MOD-0036",
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"operationCount": 2,
"operationNumbers": [
"HLP-NIPC-OP-0162",
"HLP-NIPC-OP-0163"
],
"schedulingPolicy": "ONE_MODULE_ONE_NUMBER_PATH_SERIAL",
"executionState": "RUNTIME_NUMBER_DATABASE_INDEXED",
"evidence": "UNIFIED_NUMBER_ROUTE_MEMBERSHIP",
"path": "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0036"
}
],
"identityNodes": [
{
"nodeKind": "IDENTITY_NAMESPACE",
@ -1680,6 +2457,20 @@
"evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT",
"path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0018/HLP-NIPC-OP-0058/HLP-NIPC-TGT-0018"
},
{
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0001",
"moduleNumber": "HLP-NIPC-MOD-0018",
"operationNumber": "HLP-NIPC-OP-0167",
"targetNumber": "HLP-NIPC-TGT-0018",
"alias": "resolve_number_coordinate",
"admission": "PREAUTH_SYSTEM_ROUTE",
"effect": "READ_OR_STATUS",
"evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT",
"path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0001/HLP-NIPC-MOD-0018/HLP-NIPC-OP-0167/HLP-NIPC-TGT-0018"
},
{
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"protocolVersion": "HLP-NIPC-v1",
@ -3080,6 +3871,62 @@
"evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT",
"path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0035/HLP-NIPC-OP-0161/HLP-NIPC-TGT-0035"
},
{
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0002",
"moduleNumber": "HLP-NIPC-MOD-0035",
"operationNumber": "HLP-NIPC-OP-0164",
"targetNumber": "HLP-NIPC-TGT-0035",
"alias": "list_conversations",
"admission": "VERIFIED_HUMAN_ROUTE",
"effect": "READ_OR_STATUS",
"evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT",
"path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0035/HLP-NIPC-OP-0164/HLP-NIPC-TGT-0035"
},
{
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0002",
"moduleNumber": "HLP-NIPC-MOD-0035",
"operationNumber": "HLP-NIPC-OP-0165",
"targetNumber": "HLP-NIPC-TGT-0035",
"alias": "create_conversation",
"admission": "VERIFIED_HUMAN_ROUTE",
"effect": "STATE_CHANGE",
"evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT",
"path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0035/HLP-NIPC-OP-0165/HLP-NIPC-TGT-0035"
},
{
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0002",
"moduleNumber": "HLP-NIPC-MOD-0035",
"operationNumber": "HLP-NIPC-OP-0166",
"targetNumber": "HLP-NIPC-TGT-0035",
"alias": "delete_conversation",
"admission": "VERIFIED_HUMAN_ROUTE",
"effect": "STATE_CHANGE",
"evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT",
"path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0035/HLP-NIPC-OP-0166/HLP-NIPC-TGT-0035"
},
{
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0002",
"moduleNumber": "HLP-NIPC-MOD-0035",
"operationNumber": "HLP-NIPC-OP-0168",
"targetNumber": "HLP-NIPC-TGT-0035",
"alias": "preview_hldp_tool_program",
"admission": "VERIFIED_HUMAN_ROUTE",
"effect": "READ_OR_STATUS",
"evidence": "HASH_CHAINED_NUMBERED_IPC_RECEIPT",
"path": "HLP-NUMBER-WORLD-ROOT-001/TAURI/HLP-NIPC-CH-0002/HLP-NIPC-MOD-0035/HLP-NIPC-OP-0168/HLP-NIPC-TGT-0035"
},
{
"transport": "TAURI_WEBVIEW_NUMBERED_IPC",
"protocolVersion": "HLP-NIPC-v1",

View file

@ -66,6 +66,29 @@ export function compileUnifiedNumberTree() {
if (routes.length !== uniquePaths.size || routes.length !== uniqueOperations.size) {
throw new Error('HOLOLAKE_UNIFIED_NUMBER_TREE_DUPLICATE_COORDINATE')
}
const moduleRoutes = new Map()
for (const route of routes) {
const existing = moduleRoutes.get(route.moduleNumber) ?? []
existing.push(route)
moduleRoutes.set(route.moduleNumber, existing)
}
const moduleNodes = [...moduleRoutes.entries()].map(([moduleNumber, members]) => ({
nodeKind: 'EXECUTION_MODULE',
nodeNumber: moduleNumber,
moduleNumber,
transport: [...new Set(members.map((route) => route.transport))].join('+'),
operationCount: members.length,
operationNumbers: members.map((route) => route.operationNumber).sort((left, right) => left.localeCompare(right, 'en')),
schedulingPolicy: 'ONE_MODULE_ONE_NUMBER_PATH_SERIAL',
executionState: 'RUNTIME_NUMBER_DATABASE_INDEXED',
evidence: 'UNIFIED_NUMBER_ROUTE_MEMBERSHIP',
path: `HLP-NUMBER-WORLD-ROOT-001/MODULE/${moduleNumber}`,
})).sort((left, right) => left.path.localeCompare(right.path, 'en'))
if (new Set(moduleNodes.map((node) => node.moduleNumber)).size !== moduleNodes.length
|| new Set(moduleNodes.map((node) => node.path)).size !== moduleNodes.length
|| moduleNodes.some((node) => node.operationCount === 0)) {
throw new Error('HOLOLAKE_UNIFIED_NUMBER_TREE_MODULE_ROOT_COLLISION')
}
const identityNodes = identity.value.namespaces.map((namespace) => ({
nodeKind: 'IDENTITY_NAMESPACE',
nodeNumber: `HLP-IDENTITY-NS-${namespace.id}`,
@ -99,7 +122,7 @@ export function compileUnifiedNumberTree() {
path: `HLP-NUMBER-WORLD-ROOT-001/GLS/REFERENCE/${reference.node_number}`,
})),
].sort((left, right) => left.path.localeCompare(right.path, 'en'))
const allPaths = [...routes.map((route) => route.path), ...identityNodes.map((node) => node.path), ...protocolNodes.map((node) => node.path)]
const allPaths = [...moduleNodes.map((node) => node.path), ...routes.map((route) => route.path), ...identityNodes.map((node) => node.path), ...protocolNodes.map((node) => node.path)]
if (new Set(allPaths).size !== allPaths.length
|| gls.value.reconciliation.unresolved_number_reference_count !== 0
|| gls.value.reconciliation.every_dependency_has_number_coordinate !== true
@ -136,14 +159,17 @@ export function compileUnifiedNumberTree() {
everyAcceptedCallHasEvidenceClass: true,
everyProtocolReferenceHasNumberCoordinate: true,
referenceOnlyNodesNeverExecutable: true,
oneModuleOneRuntimeRootPath: true,
unresolvedNumberReferenceCount: 0,
mismatchedCoordinate: 'FAIL_CLOSED',
},
coordinateCount: routes.length + identityNodes.length + protocolNodes.length,
coordinateCount: moduleNodes.length + routes.length + identityNodes.length + protocolNodes.length,
moduleNodeCount: moduleNodes.length,
routeCount: routes.length,
identityNodeCount: identityNodes.length,
protocolNodeCount: protocolNodes.length,
referenceOnlyNodeCount: protocolNodes.filter((node) => node.nodeKind === 'GLS_REFERENCE_ONLY').length,
moduleNodes,
identityNodes,
protocolNodes,
routes,

View file

@ -14,6 +14,8 @@ test('light lake exposes a first-class human conversation entrance', () => {
assert.match(main, /<PersonaChannelBody/)
assert.match(channel, /<textarea[\s\S]*?form\?\.requestSubmit\(\)/)
assert.match(channel, /\{sending \? '正在回应…' : '发送'\}/)
assert.match(channel, /markdownHtml\(item\.content\)/)
assert.match(channel, /persona-message-markdown/)
})
test('knowledge workspace keeps the chat visible and binds the exact active page', () => {
@ -31,7 +33,8 @@ test('knowledge workspace keeps the chat visible and binds the exact active page
test('model configuration remains secondary to the conversation surface', () => {
assert.match(channel, /const \[settingsOpen, setSettingsOpen\] = useState\(false\)/)
assert.match(channel, /直接输入消息开始对话;知识引用、模型设置和运行回执按需展开/)
assert.match(channel, /ZERO CORE · LANGUAGE PERSONA CHANNEL/)
assert.match(channel, /persona-chat-status/)
assert.match(channel, /\{settingsOpen && <aside className="persona-chat-settings">/)
assert.match(channel, /API 密钥 · 只进钥匙串/)
})
@ -42,4 +45,7 @@ test('the chosen model route survives restart and prefers explicit user configur
assert.match(channel, /item\.source === 'EXPLICIT_USER_CONFIG'/)
assert.match(channel, /rememberProvider\(nextProviderId\)/)
assert.match(channel, /onChange=\{\(event\) => selectProvider\(event\.target\.value\)\}/)
assert.match(channel, /selectedProvider\?\.source === 'EXPLICIT_USER_CONFIG'/)
assert.match(channel, /providerId: existingProviderId/)
assert.match(channel, /setModel\(saved\?\.selectedModel \|\| configModel\.trim\(\)\)/)
})

View file

@ -0,0 +1,49 @@
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import test from 'node:test'
const frontend = readFileSync(new URL('../src/modules/persona-channel-body/index.tsx', import.meta.url), 'utf8')
const main = readFileSync(new URL('../src/main.tsx', import.meta.url), 'utf8')
const runtime = readFileSync(new URL('../src-tauri/src/persona_language_channel.rs', import.meta.url), 'utf8')
const routes = JSON.parse(readFileSync(new URL('../contracts/numbered-ipc-registry.json', import.meta.url), 'utf8'))
test('human conversations are real numbered entities with create switch and delete controls', () => {
for (const alias of ['list_conversations', 'create_conversation', 'delete_conversation']) {
assert.match(frontend, new RegExp(`invoke<[^>]+>\\('${alias}'`))
assert.ok(routes.operations.some((route) => route.alias === alias && route.module_number === 'HLP-NIPC-MOD-0035'))
}
assert.match(frontend, /conversationId,\s*providerId/)
assert.match(frontend, /setConversationId\(item\.conversationId\)/)
assert.match(frontend, /删除对话/)
assert.match(main, /setPersonaNewConversationRequest\(\(value\) => value \+ 1\)/)
assert.match(main, /newConversationRequest=\{personaNewConversationRequest\}/)
})
test('legacy history migrates without loss and deletion preserves the local receipt chain', () => {
assert.match(runtime, /ALTER TABLE messages ADD COLUMN conversation_id/)
assert.match(runtime, /migrate_legacy_conversations/)
assert.match(runtime, /HLP-CONV-LEGACY-/)
assert.match(runtime, /SOFT_DELETE_TOMBSTONE_MESSAGES_RETAINED_FOR_LOCAL_RECEIPT_CHAIN/)
assert.match(runtime, /legacy_messages_migrate_into_one_numbered_conversation_without_loss/)
assert.match(runtime, /conversations_are_isolated_and_delete_keeps_local_receipt_history/)
})
test('model receives machine environment facts instead of a hard-coded unknown response', () => {
assert.match(runtime, /\[ZERO_CORE_CHANNEL_RUNTIME\]/)
assert.match(runtime, /human_anchor=\{human_name\} · \{human_id\}/)
assert.match(runtime, /知识库工具仍然可用/)
assert.match(runtime, /hololake_search_knowledge/)
assert.match(runtime, /hololake_read_knowledge_document/)
assert.doesNotMatch(runtime, /没有证据就明确说不知道/)
assert.match(runtime, /REGISTERED_AGE_PERSONA_BRAIN_DRIVES_REPLACEABLE_MODEL_AND_CODEX_LIMBS/)
})
test('persona tool forge compiles typed HLDP through its own numbered preview route', () => {
assert.match(frontend, /preview_hldp_tool_program/)
assert.match(frontend, /HLDP NATIVE TOOL FORGE/)
assert.match(frontend, /确定性 GIR/)
assert.ok(routes.operations.some((route) => route.alias === 'preview_hldp_tool_program'
&& route.operation_number === 'HLP-NIPC-OP-0168'
&& route.module_number === 'HLP-NIPC-MOD-0035'))
assert.match(runtime, /compile_hldp_program\(input\)/)
})

View file

@ -22,6 +22,7 @@ test('release center records every shipped HoloLake line from 0.4.0 through curr
test('one engine exposes Guanghu and standard workbench projections with a human default', async () => {
const source = await read('src/main.tsx')
const styles = await read('src/styles.css')
assert.match(source, /type PresentationMode = 'guanghu' \| 'workbench'/)
assert.match(source, /type AudienceLayer = 'human' \| 'execution'/)
assert.match(source, /hololake-presentation-mode/)
@ -33,6 +34,12 @@ test('one engine exposes Guanghu and standard workbench projections with a human
assert.match(source, /renderWorkbenchHuman()/)
assert.match(source, /renderExecutionProjection\(\)/)
assert.match(source, /人格体结构化执行界面/)
assert.match(source, /presentationMode !== 'workbench' \|\| view !== 'persona'/)
assert.match(source, /void refreshPersonaBodyModule\(\)/)
assert.match(source, /<PersonaChannelBody onBack=\{\(\) => \{ setView\('overview'\); setWorldStage\(toolReturnStage\) \}\}/)
assert.match(styles, /\.standard-workbench\s*\{[^}]*display:\s*grid;[^}]*grid-template-columns:\s*52px 244px minmax\(0, 1fr\);/s)
assert.match(styles, /@media \(max-width: 640px\)\s*\{[^}]*\.standard-workbench\s*\{[^}]*grid-template-columns:\s*46px minmax\(0, 1fr\);/s)
assert.ok(styles.indexOf('.workbench-sidebar { display: none; }') > styles.indexOf('@media (max-width: 640px)'))
})
test('main domain routes to the public release center instead of a descriptive popup', async () => {
@ -45,7 +52,8 @@ test('main domain routes to the public release center instead of a descriptive p
test('public language persona copy is formal and keeps a visible human composer', async () => {
const source = await read('src/modules/persona-channel-body/index.tsx')
assert.match(source, /<h1>\{embedded \? '对话与知识协作' : '语言人格频道'\}<\/h1>/)
assert.match(source, /<h1>\{conversation\?\.title \|\| \(embedded \? '对话与知识协作' : '语言人格频道'\)\}<\/h1>/)
assert.match(source, /冰朔 · ICE-GL∞/)
assert.match(source, /输入消息;需要知识时可直接提问。/)
assert.match(source, /<textarea/)
assert.match(source, /send_message/)

View file

@ -23,6 +23,7 @@ test('number verification is an unknown star abyss and the world stays veiled un
assert.match(styles, /\.starlake-scene\.world-veiled \.domains/)
assert.match(styles, /\.starlake-scene\.world-veiled \.masthead/)
assert.match(styles, /\.starlake-scene \.star-abyss-entry\s*\{/)
assert.match(styles, /\.starlake-scene \.world-channel-return\s*\{[^}]*pointer-events:\s*auto;/s)
assert.match(styles, /left:50%/)
assert.match(styles, /@keyframes sl-domain-rise/)
assert.match(styles, /@keyframes sl-abyss-open/)

View file

@ -8,18 +8,23 @@ test('identity, webview and direct broker numbers compile into one unique eviden
assert.deepEqual(generated, compileUnifiedNumberTree())
assert.equal(generated.schema, 'hololake.unified-number-coordinate-tree/v2')
assert.equal(generated.recordId, 'HLP-UNIFIED-NUMBER-TREE-001')
assert.equal(generated.coordinateCount, 273)
assert.equal(generated.routeCount, 170)
assert.equal(generated.coordinateCount, 324)
assert.equal(generated.moduleNodeCount, 46)
assert.equal(generated.routeCount, 175)
assert.equal(generated.identityNodeCount, 4)
assert.equal(generated.protocolNodeCount, 99)
assert.equal(generated.referenceOnlyNodeCount, 16)
assert.equal(new Set(generated.routes.map((route) => route.path)).size, 170)
assert.equal(new Set([...generated.identityNodes, ...generated.protocolNodes, ...generated.routes].map((node) => node.path)).size, 273)
assert.equal(new Set(generated.moduleNodes.map((node) => node.path)).size, 46)
assert.equal(new Set(generated.routes.map((route) => route.path)).size, 175)
assert.equal(new Set([...generated.moduleNodes, ...generated.identityNodes, ...generated.protocolNodes, ...generated.routes].map((node) => node.path)).size, 324)
assert.equal(generated.invariants.everyPhysicalCallHasNumberedRoute, true)
assert.equal(generated.invariants.everyAcceptedCallHasEvidenceClass, true)
assert.equal(generated.invariants.everyProtocolReferenceHasNumberCoordinate, true)
assert.equal(generated.invariants.referenceOnlyNodesNeverExecutable, true)
assert.equal(generated.invariants.oneModuleOneRuntimeRootPath, true)
assert.equal(generated.invariants.unresolvedNumberReferenceCount, 0)
assert.ok(generated.protocolNodes.filter((node) => node.nodeKind === 'GLS_REFERENCE_ONLY').every((node) => node.executionState === 'REFERENCE_ONLY_NOT_EXECUTABLE'))
assert.ok(generated.routes.every((route) => route.admission && route.evidence))
assert.ok(generated.moduleNodes.every((node) => node.path === `${generated.rootNumber}/MODULE/${node.moduleNumber}`))
assert.ok(generated.moduleNodes.every((node) => node.schedulingPolicy === 'ONE_MODULE_ONE_NUMBER_PATH_SERIAL'))
})

View file

@ -38,7 +38,7 @@ url = "2"
reqwest = { version = "0.13.2", default-features = false, features = ["cookies", "form", "json", "rustls", "stream"] }
rust_xlsxwriter = "=0.64.2"
zip = { version = "=0.6.6", default-features = false, features = ["deflate"] }
tokio = { version = "1", features = ["io-util", "process", "time"] }
tokio = { version = "1", features = ["io-util", "process", "sync", "time"] }
futures-util = "0.3"
minisign-verify = "0.2.5"
qrcode = { version = "0.14", default-features = false, features = ["svg"] }

View file

@ -7,8 +7,8 @@ mod code_repo_login;
mod direct_local_broker;
mod direct_local_session;
mod dynamic_capability_routing;
mod execution_limb_training;
mod enterprise_work_channel;
mod execution_limb_training;
mod external_ai_gateway;
mod glp_envelope;
mod gls_bootstrap_compiler;
@ -23,6 +23,7 @@ mod mobile_sync;
mod module_package_runtime;
mod native_composition;
mod number_coordinate_tree;
mod number_database;
mod numbered_ipc;
mod numbered_ipc_dispatch;
mod numbered_language_input;
@ -64,7 +65,8 @@ pub fn run() {
.plugin(tauri_plugin_dialog::init())
.manage(numbered_ipc::NumberedIpcState::default())
.manage(mobile_sync::MobileSyncState::default())
.invoke_handler(tauri::generate_handler![numbered_ipc::numbered_ipc,]) .setup(|app| {
.invoke_handler(tauri::generate_handler![numbered_ipc::numbered_ipc,])
.setup(|app| {
// GLS 是 HoloLake 产品内核,不是开发机旁路服务。合同、依赖闭包、
// 自举编译器或回执账本任一不可用时,产品启动失败关闭。
gls_protocol_kernel::start_on_application_open(app.handle())?;
@ -73,6 +75,7 @@ pub fn run() {
module_package_runtime::start_on_application_open(app.handle())?;
online_marketplace::start_on_application_open(app.handle())?;
number_coordinate_tree::start_on_application_open()?;
number_database::start_on_application_open(app.handle())?;
numbered_language_input::validate_contract()?;
numbered_ipc::start_on_application_open(app.handle())?;
human_authorization::start_on_application_open()?;

View file

@ -1620,7 +1620,6 @@ mod tests {
assert!(is_sha256(&digest));
}
#[test]
fn bundled_web_novel_family_uses_one_signed_lifecycle_and_exact_numbers() {
let expected = [

View file

@ -11,16 +11,33 @@ struct NumberTree {
state: String,
root_number: String,
coordinate_count: usize,
module_node_count: usize,
route_count: usize,
identity_node_count: usize,
protocol_node_count: usize,
reference_only_node_count: usize,
module_nodes: Vec<ModuleNode>,
identity_nodes: Vec<IdentityNode>,
protocol_nodes: Vec<ProtocolNode>,
routes: Vec<NumberRoute>,
invariants: NumberTreeInvariants,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ModuleNode {
node_kind: String,
node_number: String,
module_number: String,
transport: String,
operation_count: usize,
operation_numbers: Vec<String>,
scheduling_policy: String,
execution_state: String,
evidence: String,
path: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct IdentityNode {
@ -73,6 +90,7 @@ struct NumberTreeInvariants {
every_accepted_call_has_evidence_class: bool,
every_protocol_reference_has_number_coordinate: bool,
reference_only_nodes_never_executable: bool,
one_module_one_runtime_root_path: bool,
unresolved_number_reference_count: usize,
mismatched_coordinate: String,
}
@ -88,8 +106,10 @@ fn validate_tree() -> Result<(), String> {
|| tree.record_id != "HLP-UNIFIED-NUMBER-TREE-001"
|| tree.state != "MACHINE_COMPILED_STARTUP_ENFORCED"
|| tree.root_number != "HLP-NUMBER-WORLD-ROOT-001"
|| tree.coordinate_count != 273
|| tree.route_count != 170
|| tree.coordinate_count != 324
|| tree.module_node_count != 46
|| tree.module_nodes.len() != tree.module_node_count
|| tree.route_count != 175
|| tree.routes.len() != tree.route_count
|| tree.identity_node_count != 4
|| tree.identity_nodes.len() != tree.identity_node_count
@ -97,7 +117,10 @@ fn validate_tree() -> Result<(), String> {
|| tree.protocol_nodes.len() != tree.protocol_node_count
|| tree.reference_only_node_count != 16
|| tree.coordinate_count
!= tree.route_count + tree.identity_node_count + tree.protocol_node_count
!= tree.module_node_count
+ tree.route_count
+ tree.identity_node_count
+ tree.protocol_node_count
|| !tree.invariants.number_is_stable_coordinate_not_authority
|| !tree.invariants.path_is_unique_navigation
|| !tree.invariants.admission_is_separate_from_identity
@ -107,6 +130,7 @@ fn validate_tree() -> Result<(), String> {
.invariants
.every_protocol_reference_has_number_coordinate
|| !tree.invariants.reference_only_nodes_never_executable
|| !tree.invariants.one_module_one_runtime_root_path
|| tree.invariants.unresolved_number_reference_count != 0
|| tree.invariants.mismatched_coordinate != "FAIL_CLOSED"
{
@ -116,6 +140,27 @@ fn validate_tree() -> Result<(), String> {
let mut coordinates = HashSet::new();
let mut node_numbers = HashSet::new();
let mut protocol_ids = HashSet::new();
let mut module_numbers = HashSet::new();
for node in &tree.module_nodes {
if node.node_kind != "EXECUTION_MODULE"
|| node.node_number != node.module_number
|| node.module_number.is_empty()
|| node.transport.is_empty()
|| node.operation_count == 0
|| node.operation_numbers.len() != node.operation_count
|| node.scheduling_policy != "ONE_MODULE_ONE_NUMBER_PATH_SERIAL"
|| node.execution_state != "RUNTIME_NUMBER_DATABASE_INDEXED"
|| node.evidence != "UNIFIED_NUMBER_ROUTE_MEMBERSHIP"
|| node.path != format!("HLP-NUMBER-WORLD-ROOT-001/MODULE/{}", node.module_number)
|| !paths.insert(node.path.as_str())
|| !node_numbers.insert(node.node_number.as_str())
|| !module_numbers.insert(node.module_number.as_str())
|| node.operation_numbers.iter().collect::<HashSet<_>>().len()
!= node.operation_numbers.len()
{
return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_MODULE_NODE_INVALID".into());
}
}
for node in &tree.identity_nodes {
if node.node_kind != "IDENTITY_NAMESPACE"
|| !node.node_number.starts_with("HLP-IDENTITY-NS-")
@ -183,6 +228,7 @@ fn validate_tree() -> Result<(), String> {
|| route.admission.is_empty()
|| !matches!(route.effect.as_str(), "READ_OR_STATUS" | "STATE_CHANGE")
|| route.evidence.is_empty()
|| !module_numbers.contains(route.module_number.as_str())
|| !route.path.starts_with("HLP-NUMBER-WORLD-ROOT-001/")
|| !paths.insert(route.path.as_str())
|| !coordinates.insert(coordinate)
@ -190,6 +236,22 @@ fn validate_tree() -> Result<(), String> {
return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_ROUTE_INVALID".into());
}
}
for node in &tree.module_nodes {
let observed = tree
.routes
.iter()
.filter(|route| route.module_number == node.module_number)
.map(|route| route.operation_number.as_str())
.collect::<HashSet<_>>();
let declared = node
.operation_numbers
.iter()
.map(String::as_str)
.collect::<HashSet<_>>();
if observed != declared {
return Err("HOLOLAKE_UNIFIED_NUMBER_TREE_MODULE_MEMBERSHIP_INVALID".into());
}
}
Ok(())
}

View file

@ -0,0 +1,691 @@
//! 光湖编号数据库。
//!
//! 编号树是唯一正本;本数据库是由该正本事务化生成的运行时索引,不接受手工登记。
//! 它把“编号 → 唯一模块根路径 → 操作叶片 → 证据 → 调度规则”变成所有执行入口
//! 都能查询的机器事实。树哈希变化时数据库整体重建,未知或错配坐标一律失败关闭。
use ring::digest::{digest, SHA256};
use rusqlite::{params, Connection, OptionalExtension, TransactionBehavior};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::fs;
use std::path::{Path, PathBuf};
use tauri::{AppHandle, Manager};
const TREE: &str = include_str!("../../generated/unified-number-coordinate-tree.json");
const DATABASE_ID: &str = "HLP-NUMBER-DATABASE-0001";
const DATABASE_SCHEMA: &str = "hololake.number-database/v1";
const DATABASE_STATE: &str = "READY_RUNTIME_REMINDER_INDEX";
const SCHEDULING_POLICY: &str = "ONE_MODULE_ONE_NUMBER_PATH_SERIAL";
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct NumberTree {
schema: String,
record_id: String,
state: String,
root_number: String,
coordinate_count: usize,
module_node_count: usize,
route_count: usize,
identity_node_count: usize,
protocol_node_count: usize,
sources: Vec<NumberSource>,
module_nodes: Vec<ModuleNode>,
routes: Vec<NumberRoute>,
identity_nodes: Vec<IdentityNode>,
protocol_nodes: Vec<ProtocolNode>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct NumberSource {
record_id: String,
sha256: String,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ModuleNode {
module_number: String,
transport: String,
operation_count: usize,
operation_numbers: Vec<String>,
scheduling_policy: String,
execution_state: String,
evidence: String,
path: String,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct NumberRoute {
transport: String,
protocol_version: String,
caller_number: String,
channel_number: String,
module_number: String,
operation_number: String,
target_number: String,
alias: String,
admission: String,
effect: String,
evidence: String,
path: String,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct IdentityNode {
node_number: String,
namespace_id: String,
subject_kind: String,
domain_scope: String,
admission: String,
execution_state: String,
evidence: String,
path: String,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ProtocolNode {
node_number: String,
protocol_id: String,
source_state: String,
execution_state: String,
evidence: String,
path: String,
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RuntimeRouteResolution {
pub database_id: &'static str,
pub source_tree_record_id: String,
pub source_tree_sha256: String,
pub transport: String,
pub protocol_version: String,
pub caller_number: String,
pub channel_number: String,
pub module_number: String,
pub operation_number: String,
pub target_number: String,
pub alias: String,
pub module_root_path: String,
pub route_path: String,
pub admission: String,
pub effect: String,
pub evidence: String,
pub scheduling_policy: String,
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NumberCoordinateReminder {
pub schema: &'static str,
pub database_id: &'static str,
pub database_state: &'static str,
pub query: String,
pub coordinate_kind: String,
pub canonical_number: String,
pub path: String,
pub module_root_path: Option<String>,
pub route_path: Option<String>,
pub scheduling_policy: Option<String>,
pub evidence: String,
pub related_operation_numbers: Vec<String>,
pub source_tree_record_id: String,
pub source_tree_sha256: String,
pub reminder: &'static str,
}
fn sha256_hex(bytes: &[u8]) -> String {
digest(&SHA256, bytes)
.as_ref()
.iter()
.map(|byte| format!("{byte:02x}"))
.collect()
}
fn tree_sha256() -> String {
sha256_hex(TREE.as_bytes())
}
fn load_tree() -> Result<NumberTree, String> {
let tree: NumberTree = serde_json::from_str(TREE)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_TREE_INVALID: {error}"))?;
if tree.schema != "hololake.unified-number-coordinate-tree/v2"
|| tree.record_id != "HLP-UNIFIED-NUMBER-TREE-001"
|| tree.state != "MACHINE_COMPILED_STARTUP_ENFORCED"
|| tree.root_number != "HLP-NUMBER-WORLD-ROOT-001"
|| tree.coordinate_count
!= tree.module_node_count
+ tree.route_count
+ tree.identity_node_count
+ tree.protocol_node_count
|| tree.module_nodes.len() != tree.module_node_count
|| tree.routes.len() != tree.route_count
|| tree.identity_nodes.len() != tree.identity_node_count
|| tree.protocol_nodes.len() != tree.protocol_node_count
{
return Err("HOLOLAKE_NUMBER_DATABASE_TREE_BOUNDARY_INVALID".into());
}
Ok(tree)
}
fn database_path(app: &AppHandle) -> Result<PathBuf, String> {
let root = app
.path()
.app_data_dir()
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_HOME_FAILED: {error}"))?
.join("guanghu-number-world-v1");
fs::create_dir_all(&root)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_HOME_CREATE_FAILED: {error}"))?;
Ok(root.join("number-coordinates.sqlite3"))
}
fn open_database(path: &Path) -> Result<Connection, String> {
let connection = Connection::open(path)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_OPEN_FAILED: {error}"))?;
connection
.execute_batch(
"PRAGMA journal_mode=WAL;
PRAGMA foreign_keys=ON;
PRAGMA busy_timeout=5000;
CREATE TABLE IF NOT EXISTS metadata(
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS module_paths(
module_number TEXT PRIMARY KEY,
transport TEXT NOT NULL,
module_root_path TEXT NOT NULL UNIQUE,
scheduling_policy TEXT NOT NULL,
operation_count INTEGER NOT NULL,
operation_numbers_json TEXT NOT NULL,
execution_state TEXT NOT NULL,
evidence TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS route_coordinates(
operation_number TEXT PRIMARY KEY,
alias TEXT NOT NULL UNIQUE,
transport TEXT NOT NULL,
protocol_version TEXT NOT NULL,
caller_number TEXT NOT NULL,
channel_number TEXT NOT NULL,
module_number TEXT NOT NULL REFERENCES module_paths(module_number),
target_number TEXT NOT NULL,
module_root_path TEXT NOT NULL,
route_path TEXT NOT NULL UNIQUE,
admission TEXT NOT NULL,
effect TEXT NOT NULL,
evidence TEXT NOT NULL,
UNIQUE(transport,protocol_version,caller_number,channel_number,module_number,operation_number,target_number)
);
CREATE TABLE IF NOT EXISTS identity_coordinates(
node_number TEXT PRIMARY KEY,
namespace_id TEXT NOT NULL UNIQUE,
subject_kind TEXT NOT NULL,
domain_scope TEXT NOT NULL,
admission TEXT NOT NULL,
execution_state TEXT NOT NULL,
evidence TEXT NOT NULL,
path TEXT NOT NULL UNIQUE
);
CREATE TABLE IF NOT EXISTS protocol_coordinates(
node_number TEXT PRIMARY KEY,
protocol_id TEXT NOT NULL UNIQUE,
source_state TEXT NOT NULL,
execution_state TEXT NOT NULL,
evidence TEXT NOT NULL,
path TEXT NOT NULL UNIQUE
);",
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_SCHEMA_FAILED: {error}"))?;
Ok(connection)
}
fn put_metadata(
transaction: &rusqlite::Transaction<'_>,
key: &str,
value: impl AsRef<str>,
) -> Result<(), String> {
transaction
.execute(
"INSERT INTO metadata(key,value) VALUES(?1,?2)",
params![key, value.as_ref()],
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_METADATA_WRITE_FAILED: {error}"))?;
Ok(())
}
fn materialize_at(path: &Path) -> Result<(), String> {
let tree = load_tree()?;
let source_sha256 = tree_sha256();
let mut connection = open_database(path)?;
let transaction = connection
.transaction_with_behavior(TransactionBehavior::Immediate)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_REBUILD_FAILED: {error}"))?;
transaction
.execute_batch(
"DELETE FROM route_coordinates;
DELETE FROM module_paths;
DELETE FROM identity_coordinates;
DELETE FROM protocol_coordinates;
DELETE FROM metadata;",
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_REBUILD_FAILED: {error}"))?;
for module in &tree.module_nodes {
if module.scheduling_policy != SCHEDULING_POLICY
|| module.path != format!("{}/MODULE/{}", tree.root_number, module.module_number)
|| module.operation_count != module.operation_numbers.len()
{
return Err("HOLOLAKE_NUMBER_DATABASE_MODULE_ROOT_INVALID".into());
}
transaction
.execute(
"INSERT INTO module_paths(module_number,transport,module_root_path,scheduling_policy,operation_count,operation_numbers_json,execution_state,evidence)
VALUES(?1,?2,?3,?4,?5,?6,?7,?8)",
params![
module.module_number,
module.transport,
module.path,
module.scheduling_policy,
module.operation_count as i64,
serde_json::to_string(&module.operation_numbers).map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_OPERATIONS_INVALID: {error}"))?,
module.execution_state,
module.evidence,
],
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_WRITE_FAILED: {error}"))?;
}
for route in &tree.routes {
let module_root_path: String = transaction
.query_row(
"SELECT module_root_path FROM module_paths WHERE module_number=?1",
params![route.module_number],
|row| row.get(0),
)
.map_err(|error| {
format!("HOLOLAKE_NUMBER_DATABASE_MODULE_RESOLUTION_FAILED: {error}")
})?;
transaction
.execute(
"INSERT INTO route_coordinates(operation_number,alias,transport,protocol_version,caller_number,channel_number,module_number,target_number,module_root_path,route_path,admission,effect,evidence)
VALUES(?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13)",
params![route.operation_number,route.alias,route.transport,route.protocol_version,route.caller_number,route.channel_number,route.module_number,route.target_number,module_root_path,route.path,route.admission,route.effect,route.evidence],
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_ROUTE_WRITE_FAILED: {error}"))?;
}
for node in &tree.identity_nodes {
transaction
.execute(
"INSERT INTO identity_coordinates(node_number,namespace_id,subject_kind,domain_scope,admission,execution_state,evidence,path)
VALUES(?1,?2,?3,?4,?5,?6,?7,?8)",
params![node.node_number,node.namespace_id,node.subject_kind,node.domain_scope,node.admission,node.execution_state,node.evidence,node.path],
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_IDENTITY_WRITE_FAILED: {error}"))?;
}
for node in &tree.protocol_nodes {
transaction
.execute(
"INSERT INTO protocol_coordinates(node_number,protocol_id,source_state,execution_state,evidence,path)
VALUES(?1,?2,?3,?4,?5,?6)",
params![node.node_number,node.protocol_id,node.source_state,node.execution_state,node.evidence,node.path],
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_PROTOCOL_WRITE_FAILED: {error}"))?;
}
put_metadata(&transaction, "database_id", DATABASE_ID)?;
put_metadata(&transaction, "database_schema", DATABASE_SCHEMA)?;
put_metadata(&transaction, "database_state", DATABASE_STATE)?;
put_metadata(&transaction, "source_tree_record_id", &tree.record_id)?;
put_metadata(&transaction, "source_tree_sha256", &source_sha256)?;
put_metadata(&transaction, "root_number", &tree.root_number)?;
put_metadata(
&transaction,
"coordinate_count",
tree.coordinate_count.to_string(),
)?;
put_metadata(
&transaction,
"module_node_count",
tree.module_node_count.to_string(),
)?;
put_metadata(&transaction, "route_count", tree.route_count.to_string())?;
put_metadata(
&transaction,
"identity_node_count",
tree.identity_node_count.to_string(),
)?;
put_metadata(
&transaction,
"protocol_node_count",
tree.protocol_node_count.to_string(),
)?;
put_metadata(
&transaction,
"source_records_json",
serde_json::to_string(
&tree
.sources
.iter()
.map(|source| (&source.record_id, &source.sha256))
.collect::<Vec<_>>(),
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_SOURCE_RECORD_INVALID: {error}"))?,
)?;
transaction
.commit()
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_REBUILD_COMMIT_FAILED: {error}"))?;
verify_at(path)
}
fn metadata(connection: &Connection, key: &str) -> Result<String, String> {
connection
.query_row(
"SELECT value FROM metadata WHERE key=?1",
params![key],
|row| row.get(0),
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_METADATA_READ_FAILED: {error}"))
}
fn table_count(connection: &Connection, table: &str) -> Result<usize, String> {
let query = match table {
"module_paths" => "SELECT COUNT(*) FROM module_paths",
"route_coordinates" => "SELECT COUNT(*) FROM route_coordinates",
"identity_coordinates" => "SELECT COUNT(*) FROM identity_coordinates",
"protocol_coordinates" => "SELECT COUNT(*) FROM protocol_coordinates",
_ => return Err("HOLOLAKE_NUMBER_DATABASE_TABLE_UNKNOWN".into()),
};
connection
.query_row(query, [], |row| row.get::<_, i64>(0))
.map(|count| count as usize)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_COUNT_FAILED: {error}"))
}
fn verify_at(path: &Path) -> Result<(), String> {
let tree = load_tree()?;
let connection = open_database(path)?;
if metadata(&connection, "database_id")? != DATABASE_ID
|| metadata(&connection, "database_schema")? != DATABASE_SCHEMA
|| metadata(&connection, "database_state")? != DATABASE_STATE
|| metadata(&connection, "source_tree_record_id")? != tree.record_id
|| metadata(&connection, "source_tree_sha256")? != tree_sha256()
|| table_count(&connection, "module_paths")? != tree.module_node_count
|| table_count(&connection, "route_coordinates")? != tree.route_count
|| table_count(&connection, "identity_coordinates")? != tree.identity_node_count
|| table_count(&connection, "protocol_coordinates")? != tree.protocol_node_count
{
return Err("HOLOLAKE_NUMBER_DATABASE_VERIFY_FAILED".into());
}
let mismatched_modules: i64 = connection
.query_row(
"SELECT COUNT(*) FROM module_paths m
WHERE m.scheduling_policy != ?1
OR m.operation_count != (SELECT COUNT(*) FROM route_coordinates r WHERE r.module_number=m.module_number)
OR m.module_root_path != ?2 || '/MODULE/' || m.module_number",
params![SCHEDULING_POLICY, tree.root_number],
|row| row.get(0),
)
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_VERIFY_FAILED: {error}"))?;
if mismatched_modules != 0 {
return Err("HOLOLAKE_NUMBER_DATABASE_MODULE_VERIFY_FAILED".into());
}
Ok(())
}
pub(crate) fn start_on_application_open(app: &AppHandle) -> Result<(), String> {
materialize_at(&database_path(app)?)
}
pub(crate) fn resolve_runtime_route(
app: &AppHandle,
transport: &str,
protocol_version: &str,
caller_number: &str,
channel_number: &str,
module_number: &str,
operation_number: &str,
target_number: &str,
) -> Result<RuntimeRouteResolution, String> {
let connection = open_database(&database_path(app)?)?;
let source_tree_record_id = metadata(&connection, "source_tree_record_id")?;
let source_tree_sha256 = metadata(&connection, "source_tree_sha256")?;
connection
.query_row(
"SELECT r.transport,r.protocol_version,r.caller_number,r.channel_number,r.module_number,
r.operation_number,r.target_number,r.alias,r.module_root_path,r.route_path,
r.admission,r.effect,r.evidence,m.scheduling_policy
FROM route_coordinates r JOIN module_paths m ON m.module_number=r.module_number
WHERE r.transport=?1 AND r.protocol_version=?2 AND r.caller_number=?3
AND r.channel_number=?4 AND r.module_number=?5 AND r.operation_number=?6
AND r.target_number=?7",
params![transport,protocol_version,caller_number,channel_number,module_number,operation_number,target_number],
|row| {
Ok(RuntimeRouteResolution {
database_id: DATABASE_ID,
source_tree_record_id: source_tree_record_id.clone(),
source_tree_sha256: source_tree_sha256.clone(),
transport: row.get(0)?,
protocol_version: row.get(1)?,
caller_number: row.get(2)?,
channel_number: row.get(3)?,
module_number: row.get(4)?,
operation_number: row.get(5)?,
target_number: row.get(6)?,
alias: row.get(7)?,
module_root_path: row.get(8)?,
route_path: row.get(9)?,
admission: row.get(10)?,
effect: row.get(11)?,
evidence: row.get(12)?,
scheduling_policy: row.get(13)?,
})
},
)
.optional()
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_ROUTE_READ_FAILED: {error}"))?
.ok_or_else(|| "HOLOLAKE_NUMBER_DATABASE_ROUTE_COORDINATE_MISMATCH".to_string())
}
fn validate_query(number: &str) -> Result<&str, String> {
let number = number.trim();
if number.is_empty()
|| number.len() > 160
|| number
.chars()
.any(|character| character.is_control() || character.is_whitespace())
{
return Err("HOLOLAKE_NUMBER_DATABASE_QUERY_INVALID".into());
}
Ok(number)
}
fn resolve_number_coordinate_at(
path: &Path,
number: &str,
) -> Result<NumberCoordinateReminder, String> {
let number = validate_query(number)?;
let connection = open_database(path)?;
let source_tree_record_id = metadata(&connection, "source_tree_record_id")?;
let source_tree_sha256 = metadata(&connection, "source_tree_sha256")?;
if let Some((module_number, module_root_path, policy, evidence, operations_json)) = connection
.query_row(
"SELECT module_number,module_root_path,scheduling_policy,evidence,operation_numbers_json
FROM module_paths WHERE module_number=?1",
params![number],
|row| Ok((row.get::<_, String>(0)?,row.get::<_, String>(1)?,row.get::<_, String>(2)?,row.get::<_, String>(3)?,row.get::<_, String>(4)?)),
)
.optional()
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_READ_FAILED: {error}"))?
{
return Ok(NumberCoordinateReminder {
schema: "hololake.number-coordinate-reminder/v1",
database_id: DATABASE_ID,
database_state: DATABASE_STATE,
query: number.into(),
coordinate_kind: "EXECUTION_MODULE".into(),
canonical_number: module_number,
path: module_root_path.clone(),
module_root_path: Some(module_root_path),
route_path: None,
scheduling_policy: Some(policy),
evidence,
related_operation_numbers: serde_json::from_str(&operations_json).map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_MODULE_OPERATIONS_INVALID: {error}"))?,
source_tree_record_id,
source_tree_sha256,
reminder: "有则按唯一编号路径进入;无则明确未知,不猜路径。",
});
}
if let Some((operation_number, module_root_path, route_path, evidence, policy)) = connection
.query_row(
"SELECT r.operation_number,r.module_root_path,r.route_path,r.evidence,m.scheduling_policy
FROM route_coordinates r JOIN module_paths m ON m.module_number=r.module_number
WHERE r.operation_number=?1 OR r.alias=?1",
params![number],
|row| Ok((row.get::<_, String>(0)?,row.get::<_, String>(1)?,row.get::<_, String>(2)?,row.get::<_, String>(3)?,row.get::<_, String>(4)?)),
)
.optional()
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_ROUTE_READ_FAILED: {error}"))?
{
return Ok(NumberCoordinateReminder {
schema: "hololake.number-coordinate-reminder/v1",
database_id: DATABASE_ID,
database_state: DATABASE_STATE,
query: number.into(),
coordinate_kind: "OPERATION_ROUTE".into(),
canonical_number: operation_number.clone(),
path: route_path.clone(),
module_root_path: Some(module_root_path),
route_path: Some(route_path),
scheduling_policy: Some(policy),
evidence,
related_operation_numbers: vec![operation_number],
source_tree_record_id,
source_tree_sha256,
reminder: "先回到模块唯一根路径,再进入当前操作叶片。",
});
}
if let Some((node_number, path, evidence)) = connection
.query_row(
"SELECT node_number,path,evidence FROM identity_coordinates WHERE node_number=?1 OR namespace_id=?1",
params![number],
|row| Ok((row.get::<_, String>(0)?,row.get::<_, String>(1)?,row.get::<_, String>(2)?)),
)
.optional()
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_IDENTITY_READ_FAILED: {error}"))?
{
return Ok(NumberCoordinateReminder {
schema: "hololake.number-coordinate-reminder/v1", database_id: DATABASE_ID,
database_state: DATABASE_STATE, query: number.into(), coordinate_kind: "IDENTITY_NAMESPACE".into(),
canonical_number: node_number, path, module_root_path: None, route_path: None,
scheduling_policy: None, evidence, related_operation_numbers: vec![],
source_tree_record_id, source_tree_sha256,
reminder: "身份编号只定位权威登记路径,不自行授予身份或执行权。",
});
}
if let Some((node_number, path, evidence)) = connection
.query_row(
"SELECT node_number,path,evidence FROM protocol_coordinates WHERE node_number=?1 OR protocol_id=?1",
params![number],
|row| Ok((row.get::<_, String>(0)?,row.get::<_, String>(1)?,row.get::<_, String>(2)?)),
)
.optional()
.map_err(|error| format!("HOLOLAKE_NUMBER_DATABASE_PROTOCOL_READ_FAILED: {error}"))?
{
return Ok(NumberCoordinateReminder {
schema: "hololake.number-coordinate-reminder/v1", database_id: DATABASE_ID,
database_state: DATABASE_STATE, query: number.into(), coordinate_kind: "GLS_PROTOCOL".into(),
canonical_number: node_number, path, module_root_path: None, route_path: None,
scheduling_policy: None, evidence, related_operation_numbers: vec![],
source_tree_record_id, source_tree_sha256,
reminder: "协议编号先定位来源与执行状态;引用节点不得冒充可执行协议。",
});
}
Err("HOLOLAKE_NUMBER_DATABASE_COORDINATE_UNKNOWN".into())
}
pub(crate) fn resolve_number_coordinate(
app: &AppHandle,
input: Value,
) -> Result<NumberCoordinateReminder, String> {
let number = input
.get("number")
.and_then(Value::as_str)
.ok_or_else(|| "HOLOLAKE_NUMBER_DATABASE_NUMBER_REQUIRED".to_string())?;
resolve_number_coordinate_at(&database_path(app)?, number)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tree_materializes_into_a_verified_runtime_number_database() {
let directory = tempfile::tempdir().unwrap();
let path = directory.path().join("numbers.sqlite3");
materialize_at(&path).unwrap();
let connection = open_database(&path).unwrap();
assert_eq!(metadata(&connection, "database_id").unwrap(), DATABASE_ID);
assert_eq!(table_count(&connection, "module_paths").unwrap(), 46);
assert_eq!(table_count(&connection, "route_coordinates").unwrap(), 175);
assert_eq!(table_count(&connection, "identity_coordinates").unwrap(), 4);
assert_eq!(
table_count(&connection, "protocol_coordinates").unwrap(),
99
);
}
#[test]
fn every_persona_conversation_operation_resolves_to_one_module_root() {
let directory = tempfile::tempdir().unwrap();
let path = directory.path().join("numbers.sqlite3");
materialize_at(&path).unwrap();
for operation in [
"HLP-NIPC-OP-0158",
"HLP-NIPC-OP-0159",
"HLP-NIPC-OP-0160",
"HLP-NIPC-OP-0161",
"HLP-NIPC-OP-0164",
"HLP-NIPC-OP-0165",
"HLP-NIPC-OP-0166",
"HLP-NIPC-OP-0168",
] {
let reminder = resolve_number_coordinate_at(&path, operation).unwrap();
assert_eq!(
reminder.module_root_path.as_deref(),
Some("HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0035")
);
assert_eq!(
reminder.scheduling_policy.as_deref(),
Some(SCHEDULING_POLICY)
);
}
}
#[test]
fn reminder_resolves_module_alias_and_protocol_but_unknowns_fail_closed() {
let directory = tempfile::tempdir().unwrap();
let path = directory.path().join("numbers.sqlite3");
materialize_at(&path).unwrap();
let module = resolve_number_coordinate_at(&path, "HLP-NIPC-MOD-0035").unwrap();
assert_eq!(module.coordinate_kind, "EXECUTION_MODULE");
assert_eq!(module.related_operation_numbers.len(), 8);
let alias = resolve_number_coordinate_at(&path, "create_conversation").unwrap();
assert_eq!(alias.canonical_number, "HLP-NIPC-OP-0165");
let protocol = resolve_number_coordinate_at(&path, "GLS-0001").unwrap();
assert_eq!(protocol.coordinate_kind, "GLS_PROTOCOL");
assert_eq!(
resolve_number_coordinate_at(&path, "UNKNOWN-999").unwrap_err(),
"HOLOLAKE_NUMBER_DATABASE_COORDINATE_UNKNOWN"
);
}
}

View file

@ -15,7 +15,7 @@ use serde_json::{Map, Value};
use std::collections::{HashMap, HashSet};
use std::fs;
use std::path::PathBuf;
use std::sync::Mutex;
use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH};
use tauri::{AppHandle, Manager, State};
use uuid::Uuid;
@ -164,6 +164,7 @@ pub struct NumberedIpcState {
signing_key: hmac::Key,
grants: Mutex<HashMap<String, GrantRecord>>,
ledger: Mutex<()>,
module_paths: Mutex<HashMap<String, Arc<tokio::sync::Mutex<()>>>>,
}
impl Default for NumberedIpcState {
@ -177,10 +178,25 @@ impl Default for NumberedIpcState {
signing_key: hmac::Key::new(hmac::HMAC_SHA256, &secret),
grants: Mutex::new(HashMap::new()),
ledger: Mutex::new(()),
module_paths: Mutex::new(HashMap::new()),
}
}
}
fn module_path_lock(
state: &NumberedIpcState,
module_root_path: &str,
) -> Result<Arc<tokio::sync::Mutex<()>>, String> {
let mut paths = state
.module_paths
.lock()
.map_err(|_| "HOLOLAKE_NUMBERED_IPC_MODULE_PATH_LOCK_POISONED".to_string())?;
Ok(paths
.entry(module_root_path.to_string())
.or_insert_with(|| Arc::new(tokio::sync::Mutex::new(())))
.clone())
}
fn default_ttl_ms() -> u64 {
10_000
}
@ -763,6 +779,52 @@ pub async fn numbered_ipc(
)
}
};
let runtime_route = match crate::number_database::resolve_runtime_route(
&app,
"TAURI_WEBVIEW_NUMBERED_IPC",
&request.envelope.coordinate.protocol_version,
&request.envelope.coordinate.caller_number,
&request.envelope.coordinate.channel_number,
&request.envelope.coordinate.module_number,
&request.envelope.coordinate.operation_number,
&request.envelope.coordinate.target_number,
) {
Ok(runtime_route)
if runtime_route.alias == route.alias
&& runtime_route.admission == route.admission
&& runtime_route.effect == route.effect =>
{
runtime_route
}
Ok(_) => {
return response(
&app,
&state,
"NUMBER_DATABASE_REJECTED",
"DENY",
&operation_number,
&digest,
None,
None,
Some("HOLOLAKE_NUMBER_DATABASE_REGISTRY_MISMATCH".into()),
now,
)
}
Err(error) => {
return response(
&app,
&state,
"NUMBER_DATABASE_REJECTED",
"DENY",
&operation_number,
&digest,
None,
None,
Some(error),
now,
)
}
};
let authority_binding = match enforce_admission(&app, route) {
Ok(binding) => binding,
Err(error) => {
@ -873,6 +935,8 @@ pub async fn numbered_ipc(
)
}
};
let module_lock = module_path_lock(&state, &runtime_route.module_root_path)?;
let _module_path_guard = module_lock.lock().await;
match crate::numbered_ipc_dispatch::dispatch(
app.clone(),
&route.handler,
@ -934,10 +998,23 @@ mod tests {
#[test]
fn registry_is_closed_and_contains_every_migrated_command() {
let registry = load_registry().unwrap();
assert_eq!(registry.operations.len(), 145);
assert_eq!(registry.operations.len(), 150);
assert!(!registry.runtime.legacy_direct_commands_allowed);
}
#[test]
fn one_module_root_reuses_one_runtime_execution_lane() {
let state = NumberedIpcState::default();
let first =
module_path_lock(&state, "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0035").unwrap();
let second =
module_path_lock(&state, "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0035").unwrap();
let other =
module_path_lock(&state, "HLP-NUMBER-WORLD-ROOT-001/MODULE/HLP-NIPC-MOD-0018").unwrap();
assert!(Arc::ptr_eq(&first, &second));
assert!(!Arc::ptr_eq(&first, &other));
}
#[test]
fn route_coordinates_cannot_be_mixed() {
let registry = load_registry().unwrap();

View file

@ -392,21 +392,37 @@ pub(crate) async fn dispatch(
"persona_language_channel::discover_model_providers" => {
json(crate::persona_language_channel::discover_model_providers(app).await?)
}
"persona_language_channel::upsert_model_provider" => {
json(crate::persona_language_channel::upsert_model_provider(app, input(&payload)?).await?)
}
"persona_language_channel::upsert_model_provider" => json(
crate::persona_language_channel::upsert_model_provider(app, input(&payload)?).await?,
),
"persona_language_channel::get_conversation" => {
json(crate::persona_language_channel::get_conversation(app, input(&payload)?).await?)
}
"persona_language_channel::list_conversations" => {
json(crate::persona_language_channel::list_conversations(app, input(&payload)?).await?)
}
"persona_language_channel::create_conversation" => {
json(crate::persona_language_channel::create_conversation(app, input(&payload)?).await?)
}
"persona_language_channel::delete_conversation" => {
json(crate::persona_language_channel::delete_conversation(app, input(&payload)?).await?)
}
"persona_language_channel::send_message" => {
json(crate::persona_language_channel::send_message(app, input(&payload)?).await?)
}
"persona_language_channel::preview_hldp_tool_program" => json(
crate::persona_language_channel::preview_hldp_tool_program(input(&payload)?).await?,
),
"execution_limb_training::get_execution_limb_snapshot" => {
json(crate::execution_limb_training::get_execution_limb_snapshot(app).await?)
}
"execution_limb_training::run_execution_limb_training_drill" => {
json(crate::execution_limb_training::run_execution_limb_training_drill(app, input(&payload)?).await?)
}
"execution_limb_training::run_execution_limb_training_drill" => json(
crate::execution_limb_training::run_execution_limb_training_drill(
app,
input(&payload)?,
)
.await?,
),
"persona_time_authority::issue_persona_time_ticket" => json(
crate::persona_time_authority::issue_persona_time_ticket(app, input(&payload)?).await?,
),
@ -562,6 +578,12 @@ pub(crate) async fn dispatch(
"zero_core_numbering::get_zero_core_numbering_kernel" => {
json(crate::zero_core_numbering::get_zero_core_numbering_kernel().await?)
}
"number_database::resolve_number_coordinate" => {
json(crate::number_database::resolve_number_coordinate(
&app,
payload.get("input").cloned().unwrap_or(Value::Null),
)?)
}
"zero_point::zero_point_bind" => json(
crate::zero_point::zero_point_bind(
app.state::<crate::zero_point::ZeroPointState>(),

View file

@ -79,7 +79,6 @@ pub struct PersonaChannelBodySnapshot {
pub history_mutation_allowed: bool,
}
/// 语言频道读取已注册人格体摘要的共用入口2026-08-20 正向合并:自语言人格频道线移植)。
#[allow(clippy::too_many_lines)]
pub(crate) fn require_registered_persona(

View file

@ -667,6 +667,7 @@ function HoloLakeApp() {
const [surface, setSurface] = useState<'world' | 'traditional'>(() => window.localStorage.getItem('hololake-surface') === 'traditional' ? 'traditional' : 'world')
const [traditionalFinish, setTraditionalFinish] = useState<FinishId>(() => (window.localStorage.getItem('hololake-finish') as FinishId) || 'aurora')
const [view, setView] = useState<ViewId>('overview')
const [personaNewConversationRequest, setPersonaNewConversationRequest] = useState(0)
const [presentationMode, setPresentationMode] = useState<PresentationMode>(() => (window.localStorage.getItem('hololake-presentation-mode') as PresentationMode) || 'guanghu')
const [audienceLayer, setAudienceLayer] = useState<AudienceLayer>(() => (window.localStorage.getItem('hololake-audience-layer') as AudienceLayer) || 'human')
const choosePresentationMode = (next: PresentationMode) => {
@ -1275,6 +1276,10 @@ function HoloLakeApp() {
return module
} catch (error) { setPersonaBodyMessage(humanError(error, 'system')); return null }
}
useEffect(() => {
if (!repoLogin || presentationMode !== 'workbench' || view !== 'persona') return
void refreshPersonaBodyModule()
}, [repoLogin?.username, repoLogin?.domain, presentationMode, view])
const openPersonaBody = () => { openWorldTool('persona'); void refreshPersonaBodyModule() }
const activatePersonaBodyModule = async () => {
setPersonaBodyBusy(true)
@ -1881,7 +1886,7 @@ function HoloLakeApp() {
const renderPersonaBody = () => (
<section className="full-workbench persona-channel-body-world">
{personaBodyModule?.installedState === 'ACTIVE'
? <Suspense fallback={<div className="workbench-empty"><p></p></div>}><PersonaChannelBody onBack={() => setWorldStage(toolReturnStage)}/></Suspense>
? <Suspense fallback={<div className="workbench-empty"><p></p></div>}><PersonaChannelBody onBack={() => { setView('overview'); setWorldStage(toolReturnStage) }} newConversationRequest={personaNewConversationRequest}/></Suspense>
: <div className="workbench-empty">
<span></span><h2></h2>
<p>宿</p>
@ -2237,7 +2242,7 @@ function HoloLakeApp() {
</aside>
<aside className="workbench-sidebar">
<header><div><b>HoloLake</b><span></span></div><button type="button" title="返回光湖工作台" onClick={() => choosePresentationMode('guanghu')}></button></header>
<button className="workbench-new-channel" type="button" onClick={() => { setView('persona'); chooseAudienceLayer('human') }}><Icon name="plus"/></button>
<button className="workbench-new-channel" type="button" onClick={() => { setView('persona'); chooseAudienceLayer('human'); setPersonaNewConversationRequest((value) => value + 1) }}><Icon name="plus"/></button>
<nav aria-label="HoloLake 功能栏目">{workbenchViews.map((item) => <button className={view === item ? 'active' : ''} type="button" key={item} onClick={() => setView(item)}><Icon name={item}/><span>{viewLabels[item]}</span></button>)}</nav>
<section className="workbench-scope"><span></span><b>{domainDisplayName(repoLogin.domain)}</b><small>{repoLogin.username}</small></section>
</aside>

View file

@ -1160,6 +1160,46 @@ const ROUTES = {
"moduleNumber": "HLP-NIPC-MOD-0036",
"operationNumber": "HLP-NIPC-OP-0163",
"targetNumber": "HLP-NIPC-TGT-0036"
},
"list_conversations": {
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0002",
"moduleNumber": "HLP-NIPC-MOD-0035",
"operationNumber": "HLP-NIPC-OP-0164",
"targetNumber": "HLP-NIPC-TGT-0035"
},
"create_conversation": {
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0002",
"moduleNumber": "HLP-NIPC-MOD-0035",
"operationNumber": "HLP-NIPC-OP-0165",
"targetNumber": "HLP-NIPC-TGT-0035"
},
"delete_conversation": {
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0002",
"moduleNumber": "HLP-NIPC-MOD-0035",
"operationNumber": "HLP-NIPC-OP-0166",
"targetNumber": "HLP-NIPC-TGT-0035"
},
"resolve_number_coordinate": {
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0001",
"moduleNumber": "HLP-NIPC-MOD-0018",
"operationNumber": "HLP-NIPC-OP-0167",
"targetNumber": "HLP-NIPC-TGT-0018"
},
"preview_hldp_tool_program": {
"protocolVersion": "HLP-NIPC-v1",
"callerNumber": "HLP-NIPC-CALLER-MAIN-WEBVIEW-0001",
"channelNumber": "HLP-NIPC-CH-0002",
"moduleNumber": "HLP-NIPC-MOD-0035",
"operationNumber": "HLP-NIPC-OP-0168",
"targetNumber": "HLP-NIPC-TGT-0035"
}
} as const

View file

@ -1,4 +1,6 @@
import { numberedInvoke as invoke } from '../numbered-ipc'
import { markdownHtml } from '../knowledge-render'
import { listen, type UnlistenFn } from '@tauri-apps/api/event'
import { type FormEvent, useEffect, useMemo, useRef, useState } from 'react'
import './styles.css'
@ -15,14 +17,64 @@ interface ModelProvider { providerId: string; label: string; kind: string; state
interface ProviderDiscovery { state: string; providers: ModelProvider[]; secretPolicy: string }
interface ToolReceipt { source: string; path: string; contentSha256: string }
interface PersonaMessage { messageId: string; eventId: string; personaId: string; role: 'human' | 'persona'; content: string; providerId: string; model: string; createdAtUnixMs: number; stateVersion: number; receiptHash: string; toolReceipts: ToolReceipt[] }
interface ConversationSnapshot { personaId: string; messages: PersonaMessage[]; stateVersion: number; lastReceiptHash: string }
interface ConversationSnapshot { personaId: string; conversationId: string; title: string; messages: PersonaMessage[]; stateVersion: number; lastReceiptHash: string }
interface ConversationSummary { conversationId: string; personaId: string; title: string; updatedAtUnixMs: number; messageCount: number; lastMessagePreview: string }
interface ConversationListSnapshot { personaId: string; conversations: ConversationSummary[]; deletionPolicy: string }
interface LimbSnapshot { state: string; limbId: string; executableState: string; executableVersion?: string; trainingCycleCount: number; validatedMemoryCount: number; ledgerIntegrity: string; lastTraining?: { state: string; lessonId: string; summary: string; receiptHash: string } }
interface DrillReceipt { state: string; summary: string; receiptHash: string; snapshot: LimbSnapshot }
interface AgentProgress {
requestId: string
conversationId: string
stage: string
label: string
state: 'RUNNING' | 'DONE' | 'FAILED'
detail?: string
completed: number
total?: number
occurredAtUnixMs: number
}
interface GirPreview {
schema: string
programId: string
sourceSha256: string
permissions: string[]
actionGraph: Array<{ ordinal: number; id: string; kind: string; permission: string }>
unresolvedNaturalLanguage: string[]
unresolvedPermissions: string[]
girSha256: string
}
const PROVIDER_SELECTION_KEY = 'hololake-persona-provider-id'
const DEFAULT_HLDP_TOOL = JSON.stringify({
schema: 'hololake.hldp-native-program/v1',
programId: 'HLP-TOOL-KNOWLEDGE-READ-0001',
version: '0.1.0',
subjectId: 'ICE-P-ZY001',
targetId: 'HOLOLAKE-KNOWLEDGE-LOCAL',
scope: 'CURRENT_ACCOUNT_KNOWLEDGE',
permissions: ['KNOWLEDGE_READ', 'RECEIPT_WRITE'],
resources: { cpuUnits: 1, memoryBytes: 16777216, storageBytes: 0, networkAllowed: false },
actions: [
{ id: 'validate-input', kind: 'VALIDATE', dependsOn: [], inputDigest: '0'.repeat(64), permission: 'KNOWLEDGE_READ' },
{ id: 'read-document', kind: 'READ', dependsOn: ['validate-input'], inputDigest: '0'.repeat(64), permission: 'KNOWLEDGE_READ' },
{ id: 'write-receipt', kind: 'WRITE_RECEIPT', dependsOn: ['read-document'], inputDigest: '0'.repeat(64), permission: 'RECEIPT_WRITE' },
],
timeoutMs: 30000,
stopAction: 'STOP',
cleanupAction: 'CLEANUP',
rollbackAction: 'ROLLBACK',
receiptKinds: ['COMPILE', 'READ', 'TERMINAL'],
}, null, 2)
function errorText(error: unknown) {
return String(error).replace(/^Error:\s*/, '').replace(/^HOLOLAKE_/, '')
const raw = String(error).replace(/^Error:\s*/, '')
if (raw.includes('MODEL_SELECTION_REQUIRED')) return '请选择模型;百炼 Token Plan 可使用 qwen3.8-max。'
if (raw.includes('MODEL_HTTP_401') || raw.includes('MODEL_HTTP_403')) return '模型平台拒绝了凭据,请重新保存 API 密钥。'
if (raw.includes('MODEL_REQUEST_FAILED') || raw.includes('MODEL_CLIENT_FAILED')) return '没有连接到模型平台,请检查网络与接口地址。'
if (raw.includes('TOOL_ROUND_LIMIT')) return '工具调用达到本轮上限,已安全停止。'
if (raw.includes('GLC_') || raw.includes('HLDP_PREVIEW')) return 'HLDP 程序没有通过严格类型检查,请检查字段、权限、依赖和摘要。'
if (raw.includes('KNOWLEDGE')) return '知识库工具没有完成这一步,失败结果已保留。'
return '本轮没有完成。技术详情已保存在本机运行回执中。'
}
function shortHash(value: string) {
@ -39,10 +91,12 @@ function rememberProvider(providerId: string) {
}
// 本页登记生命周期,不创建人格绑定。
export function PersonaChannelBody({ onBack, knowledgeFocus, embedded = false }: { onBack?: () => void; knowledgeFocus?: KnowledgeFocus | null; embedded?: boolean }) {
export function PersonaChannelBody({ onBack, knowledgeFocus, embedded = false, newConversationRequest = 0 }: { onBack?: () => void; knowledgeFocus?: KnowledgeFocus | null; embedded?: boolean; newConversationRequest?: number }) {
const [body, setBody] = useState<PersonaBodySnapshot | null>(null)
const [discovery, setDiscovery] = useState<ProviderDiscovery | null>(null)
const [conversation, setConversation] = useState<ConversationSnapshot | null>(null)
const [conversations, setConversations] = useState<ConversationSummary[]>([])
const [conversationId, setConversationId] = useState('')
const [personaId, setPersonaId] = useState('')
const [providerId, setProviderId] = useState(() => localStorage.getItem(PROVIDER_SELECTION_KEY) || '')
const [model, setModel] = useState('')
@ -51,14 +105,21 @@ export function PersonaChannelBody({ onBack, knowledgeFocus, embedded = false }:
const [loading, setLoading] = useState(true)
const [sending, setSending] = useState(false)
const [settingsOpen, setSettingsOpen] = useState(false)
const [forgeOpen, setForgeOpen] = useState(false)
const [personaName, setPersonaName] = useState('铸渊 · 本机频道')
const [configLabel, setConfigLabel] = useState('我的模型接口')
const [configBaseUrl, setConfigBaseUrl] = useState('https://api.openai.com/v1')
const [configModel, setConfigModel] = useState('')
const [configLabel, setConfigLabel] = useState('百炼 Token Plan')
const [configBaseUrl, setConfigBaseUrl] = useState('https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1')
const [configModel, setConfigModel] = useState('qwen3.8-max')
const [configKey, setConfigKey] = useState('')
const [activity, setActivity] = useState<AgentProgress[]>([])
const [hldpProgram, setHldpProgram] = useState(DEFAULT_HLDP_TOOL)
const [girPreview, setGirPreview] = useState<GirPreview | null>(null)
const [forgeBusy, setForgeBusy] = useState(false)
const [limb, setLimb] = useState<LimbSnapshot | null>(null)
const [limbBusy, setLimbBusy] = useState(false)
const ledgerRef = useRef<HTMLDivElement>(null)
const activeRequestRef = useRef('')
const handledNewConversationRequest = useRef(0)
const selectedProvider = useMemo(() => discovery?.providers.find((item) => item.providerId === providerId), [discovery, providerId])
const selectedPersona = useMemo(() => body?.personas.find((item) => item.personaId === personaId), [body, personaId])
@ -90,24 +151,88 @@ export function PersonaChannelBody({ onBack, knowledgeFocus, embedded = false }:
setPersonaId((current) => current && next.personas.some((item) => item.personaId === current) ? current : (next.personas[0]?.personaId || ''))
}
const refreshConversations = async (targetPersonaId: string, preferredId = '') => {
const snapshot = await invoke<ConversationListSnapshot>('list_conversations', { input: { personaId: targetPersonaId, conversationId: null } })
setConversations(snapshot.conversations)
const nextId = snapshot.conversations.some((item) => item.conversationId === preferredId)
? preferredId
: snapshot.conversations[0]?.conversationId || ''
setConversationId(nextId)
if (!nextId) setConversation(null)
return snapshot
}
const createConversation = async () => {
if (!personaId) return
setLoading(true)
try {
const created = await invoke<ConversationSnapshot>('create_conversation', { input: { personaId, title: null } })
setConversation(created)
await refreshConversations(personaId, created.conversationId)
setNotice('新对话已建立;它拥有独立历史和回执坐标。')
} catch (error) { setNotice(errorText(error)) }
finally { setLoading(false) }
}
const deleteConversation = async (target: ConversationSummary) => {
if (!window.confirm(`删除对话“${target.title}”?它会从列表移除,本机回执链保留不可冒充的删除墓碑。`)) return
setLoading(true)
try {
const snapshot = await invoke<ConversationListSnapshot>('delete_conversation', { input: { personaId, conversationId: target.conversationId } })
setConversations(snapshot.conversations)
const nextId = snapshot.conversations[0]?.conversationId || ''
setConversationId(nextId)
if (!nextId) setConversation(null)
setNotice('对话已从活动列表删除;本机审计回执链保留删除墓碑。')
} catch (error) { setNotice(errorText(error)) }
finally { setLoading(false) }
}
useEffect(() => {
Promise.all([refreshBody(), refreshProviders(), invoke<LimbSnapshot>('get_execution_limb_snapshot').then(setLimb)])
.catch((error) => setNotice(errorText(error)))
.finally(() => setLoading(false))
}, [])
useEffect(() => {
let unlisten: UnlistenFn | undefined
void listen<AgentProgress>('hololake://persona-agent-progress', ({ payload }) => {
if (!payload || payload.requestId !== activeRequestRef.current) return
setActivity((current) => {
const index = current.findIndex((item) => item.stage === payload.stage)
if (index < 0) return [...current, payload]
const next = [...current]
next[index] = payload
return next
})
}).then((dispose) => { unlisten = dispose })
return () => unlisten?.()
}, [])
useEffect(() => {
const nextModel = selectedProvider?.selectedModel || selectedProvider?.models[0] || ''
setModel(nextModel)
}, [selectedProvider])
useEffect(() => {
if (!personaId) { setConversation(null); return }
invoke<ConversationSnapshot>('get_conversation', { input: { personaId } })
.then(setConversation)
if (!personaId) { setConversation(null); setConversations([]); setConversationId(''); return }
refreshConversations(personaId, conversationId)
.catch((error) => setNotice(errorText(error)))
}, [personaId])
useEffect(() => {
if (!personaId || !conversationId) { setConversation(null); return }
invoke<ConversationSnapshot>('get_conversation', { input: { personaId, conversationId } })
.then(setConversation)
.catch((error) => setNotice(errorText(error)))
}, [personaId, conversationId])
useEffect(() => {
if (!newConversationRequest || newConversationRequest === handledNewConversationRequest.current || !personaId) return
handledNewConversationRequest.current = newConversationRequest
void createConversation()
}, [newConversationRequest, personaId])
useEffect(() => {
ledgerRef.current?.scrollTo({ top: ledgerRef.current.scrollHeight, behavior: 'smooth' })
}, [conversation?.messages.length])
@ -127,23 +252,58 @@ export function PersonaChannelBody({ onBack, knowledgeFocus, embedded = false }:
const send = async (event: FormEvent) => {
event.preventDefault()
if (!draft.trim() || !personaId || !providerId) return
if (!draft.trim() || !personaId || !conversationId || !providerId) return
const content = draft.trim()
const requestId = `HLP_AGENT_${crypto.randomUUID().replaceAll('-', '')}`
activeRequestRef.current = requestId
setDraft('')
setSending(true)
setNotice('正在生成回复并读取当前知识上下文……')
setNotice('')
setActivity([{
requestId,
conversationId,
stage: 'MESSAGE_PERSISTED',
label: '正在把消息写入频道',
state: 'RUNNING',
completed: 0,
total: 1,
occurredAtUnixMs: Date.now(),
}])
setConversation((current) => current ? {
...current,
messages: [...current.messages, {
messageId: `optimistic-${requestId}`,
eventId: requestId,
personaId,
role: 'human',
content,
providerId,
model,
createdAtUnixMs: Date.now(),
stateVersion: current.stateVersion + 1,
receiptHash: '',
toolReceipts: [],
}],
} : current)
try {
const next = await invoke<ConversationSnapshot>('send_message', { input: {
personaId,
conversationId,
providerId,
model: model || null,
content: draft.trim(),
content,
useKnowledge: true,
activeKnowledgeSource: knowledgeFocus?.source || null,
activeKnowledgePath: knowledgeFocus?.path || null,
requestId,
} })
setConversation(next)
setDraft('')
setNotice(next.messages.at(-1)?.toolReceipts.length ? '回复已写入频道;当前知识页已形成可核验引用。' : '回复已写入频道;本轮没有匹配到知识页。')
} catch (error) { setNotice(errorText(error)) }
await refreshConversations(personaId, next.conversationId)
setNotice(next.messages.at(-1)?.toolReceipts.length ? '已完成,并附上本轮实际读取的知识来源。' : '已完成。')
} catch (error) {
setNotice(errorText(error))
void invoke<ConversationSnapshot>('get_conversation', { input: { personaId, conversationId } }).then(setConversation)
}
finally { setSending(false) }
}
@ -151,8 +311,11 @@ export function PersonaChannelBody({ onBack, knowledgeFocus, embedded = false }:
event.preventDefault()
setLoading(true)
try {
const existingProviderId = selectedProvider?.source === 'EXPLICIT_USER_CONFIG'
? selectedProvider.providerId
: null
const next = await invoke<ProviderDiscovery>('upsert_model_provider', { input: {
providerId: null,
providerId: existingProviderId,
label: configLabel.trim(),
kind: 'OPENAI_COMPATIBLE',
baseUrl: configBaseUrl.trim(),
@ -160,8 +323,10 @@ export function PersonaChannelBody({ onBack, knowledgeFocus, embedded = false }:
apiKey: configKey || null,
} })
setDiscovery(next)
const created = next.providers.find((item) => item.label === configLabel.trim())
selectProvider(created?.providerId || next.providers.find((item) => item.state === 'AVAILABLE')?.providerId || '')
const saved = (existingProviderId && next.providers.find((item) => item.providerId === existingProviderId))
|| next.providers.find((item) => item.label === configLabel.trim())
selectProvider(saved?.providerId || next.providers.find((item) => item.state === 'AVAILABLE')?.providerId || '')
setModel(saved?.selectedModel || configModel.trim())
setConfigKey('')
setSettingsOpen(false)
setNotice('模型入口已保存并验证;密钥只进入系统钥匙串。')
@ -180,19 +345,42 @@ export function PersonaChannelBody({ onBack, knowledgeFocus, embedded = false }:
finally { setLimbBusy(false) }
}
const compileHldpPreview = async () => {
setForgeBusy(true)
setGirPreview(null)
try {
const program = JSON.parse(hldpProgram) as Record<string, unknown>
const result = await invoke<GirPreview>('preview_hldp_tool_program', { input: program })
setGirPreview(result)
setNotice('HLDP 已编译为确定性 GIR 预览;本步没有执行工具,也没有取得新权限。')
} catch (error) {
setNotice(errorText(error))
} finally {
setForgeBusy(false)
}
}
const personaLabel = selectedPersona?.state === 'IMMUTABLE_ACTIVE'
? `${selectedPersona.displayName} · ${selectedPersona.personaId}`
: `未绑定人格体 · ${selectedPersona?.personaId || '等待登记'}`
const modelLabel = selectedProvider
? `${selectedProvider.label}${model ? ` · ${model}` : ''}`
: '尚未接入模型'
if (loading && !body) return <section className={`persona-chat-world${embedded ? ' is-embedded' : ''}`}><div className="persona-chat-loading"></div></section>
return <section className={`persona-chat-world${embedded ? ' is-embedded' : ''}`}>
<header className="persona-chat-header">
<div>
{!embedded && onBack && <button type="button" onClick={onBack}> </button>}
<span>LANGUAGE PERSONA CHANNEL</span>
<h1>{embedded ? '对话与知识协作' : '语言人格频道'}</h1>
<p>{knowledgeFocus ? <><b>{knowledgeFocus.title}</b></> : '直接输入消息开始对话;知识引用、模型设置和运行回执按需展开。'}</p>
<span>ZERO CORE · LANGUAGE PERSONA CHANNEL</span>
<h1>{conversation?.title || (embedded ? '对话与知识协作' : '语言人格频道')}</h1>
<p>{personaLabel} <span className="persona-header-divider">/</span>  · ICE-GL</p>
</div>
<div className="persona-chat-status">
<i className={providerId ? 'ready' : ''}/>
<span>{selectedProvider ? `${selectedProvider.label} · ${selectedProvider.state}` : '尚无可用模型'}</span>
<span title={modelLabel}>{modelLabel}</span>
<button type="button" onClick={() => setForgeOpen((value) => !value)}>{forgeOpen ? '收起 HLDP' : 'HLDP 工具'}</button>
<button type="button" onClick={() => setSettingsOpen((value) => !value)}>{settingsOpen ? '收起设置' : '设置'}</button>
</div>
</header>
@ -201,21 +389,47 @@ export function PersonaChannelBody({ onBack, knowledgeFocus, embedded = false }:
<div><span></span><h2></h2><p></p></div>
<input value={personaName} maxLength={80} aria-label="频道显示名称" onChange={(event) => setPersonaName(event.target.value)}/>
<button disabled={loading || !personaName.trim()}></button>
</form> : <>
</form> : <div className="persona-chat-body">
<aside className="persona-conversation-rail" aria-label="对话列表">
<header><div><span>CONVERSATIONS</span><b></b></div><button type="button" onClick={() => void createConversation()} disabled={loading}> </button></header>
<div>{conversations.map((item) => <article className={item.conversationId === conversationId ? 'active' : ''} key={item.conversationId}>
<button type="button" onClick={() => setConversationId(item.conversationId)}><b>{item.title}</b><span>{item.messageCount ? `${item.messageCount} 条消息` : '空对话'}</span><small>{item.lastMessagePreview || '等待第一句话'}</small></button>
<button className="persona-conversation-delete" type="button" title="删除对话" aria-label={`删除对话 ${item.title}`} onClick={() => void deleteConversation(item)}>×</button>
</article>)}</div>
{!conversations.length && <p></p>}
</aside>
<main className="persona-chat-main">
<div className="persona-chat-ledger" ref={ledgerRef} aria-live="polite">
{conversation?.messages.length ? conversation.messages.map((item) => <article className={`persona-chat-message is-${item.role}`} key={item.messageId}>
<header><b>{item.role === 'human' ? '人类' : selectedPersona?.displayName || '人格体'}</b><span>{localTime(item.createdAtUnixMs)} · v{item.stateVersion}</span></header>
<p>{item.content}</p>
<header><b>{item.role === 'human' ? '冰朔 · ICE-GL∞' : personaLabel}</b><span>{localTime(item.createdAtUnixMs)}</span></header>
{item.role === 'persona'
? <div className="persona-message-markdown" dangerouslySetInnerHTML={{ __html: markdownHtml(item.content) }}/>
: <p>{item.content}</p>}
{item.toolReceipts.length > 0 && <div className="persona-knowledge-receipts">{item.toolReceipts.map((receipt) => <span key={`${item.messageId}-${receipt.path}`} title={receipt.contentSha256}> · {receipt.path} · {shortHash(receipt.contentSha256)}</span>)}</div>}
<footer><span>{item.model || item.providerId}</span><span title={item.receiptHash}> {shortHash(item.receiptHash)}</span></footer>
</article>) : <div className="persona-chat-empty"><span></span><h2>{knowledgeFocus ? '询问当前知识页' : '开始新对话'}</h2><p>{knowledgeFocus ? '回复会附带知识路径与内容指纹,便于核验引用来源。' : '输入“@知识 关键词”可检索本地知识库。'}</p></div>}
{item.role === 'persona' && <footer><span>{selectedProvider?.label || '模型入口'} · {item.model || model || '自动路由'}</span><span title={item.receiptHash}></span></footer>}
</article>) : <div className="persona-chat-empty"><span>{conversation ? '频道已就绪' : '尚未选择对话'}</span><h2>{conversation ? (knowledgeFocus ? '询问当前知识页' : '开始新对话') : '先建立一个对话'}</h2><p>{conversation ? (knowledgeFocus ? '回复会附带知识路径与内容指纹,便于核验引用来源。' : '输入“@知识 关键词”可检索本地知识库。') : '每个对话拥有独立历史坐标;删除只从活动列表移除并保留本机审计墓碑。'}</p>{!conversation && <button type="button" onClick={() => void createConversation()}></button>}</div>}
</div>
{(sending || activity.length > 0) && <div className="persona-agent-activity" aria-live="polite">
{activity.map((item) => <div className={`is-${item.state.toLowerCase()}`} key={item.stage}>
<i/><span>{item.label}</span>{item.detail && <small>{item.detail}</small>}
</div>)}
</div>}
<form className="persona-chat-composer" onSubmit={(event) => void send(event)}>
{knowledgeFocus && <div className="persona-knowledge-focus"><span></span><b>{knowledgeFocus.title}</b><small>{knowledgeFocus.path}</small></div>}
<textarea autoFocus={!embedded} value={draft} maxLength={64000} placeholder={knowledgeFocus ? `输入关于《${knowledgeFocus.title}》的问题` : '输入消息;需要知识时可直接提问。'} onChange={(event) => setDraft(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing) { event.preventDefault(); event.currentTarget.form?.requestSubmit() } }}/>
<div><span>Enter · Shift+Enter · </span><button disabled={sending || !draft.trim() || !providerId}>{sending ? '正在回应…' : '发送'}</button></div>
<textarea disabled={!conversationId} autoFocus={!embedded} value={draft} maxLength={64000} placeholder={conversationId ? (knowledgeFocus ? `输入关于《${knowledgeFocus.title}》的问题` : '输入消息;需要知识时可直接提问。') : '请先新建或选择对话'} onChange={(event) => setDraft(event.target.value)} onKeyDown={(event) => { if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing) { event.preventDefault(); event.currentTarget.form?.requestSubmit() } }}/>
<div><span>Enter · Shift+Enter · </span><button disabled={sending || !draft.trim() || !providerId || !conversationId}>{sending ? '正在回应…' : '发送'}</button></div>
</form>
</>}
</main>
</div>}
{forgeOpen && <aside className="persona-hldp-forge">
<header><div><span>HLDP NATIVE TOOL FORGE</span><h2></h2><p> HLDP-NP GIR访</p></div><button type="button" onClick={() => setForgeOpen(false)}></button></header>
<div className="persona-hldp-forge-body">
<label><span>HLDP-NP </span><textarea spellCheck={false} value={hldpProgram} onChange={(event) => setHldpProgram(event.target.value)}/></label>
<section><span>GIR </span>{girPreview ? <><b>{girPreview.programId}</b><small>GIR · {shortHash(girPreview.girSha256)}</small><small> · {shortHash(girPreview.sourceSha256)}</small><ol>{girPreview.actionGraph.map((action) => <li key={action.id}>{action.ordinal + 1}. {action.kind} · {action.id} · {action.permission}</li>)}</ol></> : <p></p>}</section>
</div>
<footer><span> Terminal </span><button type="button" disabled={forgeBusy} onClick={() => void compileHldpPreview()}>{forgeBusy ? '正在编译…' : '编译 GIR 预览'}</button></footer>
</aside>}
{settingsOpen && <aside className="persona-chat-settings">
<header><div><span>ADVANCED SETTINGS</span><h2></h2></div><button type="button" onClick={() => void refreshProviders()}></button></header>

View file

@ -18,6 +18,13 @@
.persona-chat-onboarding>div { grid-column: 1/-1; }.persona-chat-onboarding span { color: var(--accent-light); font-size: 11px; letter-spacing: .12em; }.persona-chat-onboarding h2 { margin: 7px 0; }.persona-chat-onboarding p { margin: 0; color: var(--content-secondary); line-height: 1.6; }
.persona-chat-onboarding input,.persona-provider-selectors select,.persona-provider-selectors input,.persona-provider-form input { min-width: 0; border: 1px solid color-mix(in srgb,var(--content-primary) 14%,transparent); border-radius: 12px; padding: 11px 12px; background: color-mix(in srgb,var(--surface-depth) 86%,transparent); color: var(--content-primary); font: inherit; }
.persona-chat-onboarding button,.persona-chat-composer button,.persona-provider-form button,.persona-limb-strip button { border: 0; border-radius: 12px; padding: 11px 17px; background: var(--accent-light); color: var(--surface-depth); font-weight: 700; cursor: pointer; }
.persona-chat-body { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: minmax(190px,240px) minmax(0,1fr); gap: 12px; }
.persona-conversation-rail { min-height: 0; display: flex; flex-direction: column; gap: 10px; padding: 12px; border-radius: 18px; background: color-mix(in srgb,var(--surface-depth) 62%,transparent); border: 1px solid color-mix(in srgb,var(--content-primary) 9%,transparent); }
.persona-conversation-rail>header { display: flex; align-items: center; justify-content: space-between; gap: 8px; }.persona-conversation-rail>header>div { display: grid; gap: 2px; }.persona-conversation-rail>header span { color: var(--content-muted); font-size: 9px; letter-spacing: .12em; }.persona-conversation-rail>header b { font-size: 14px; }.persona-conversation-rail>header button { border: 0; border-radius: 9px; padding: 7px 9px; background: color-mix(in srgb,var(--accent-light) 12%,transparent); color: var(--accent-light); cursor: pointer; }
.persona-conversation-rail>div { min-height: 0; overflow: auto; display: grid; align-content: start; gap: 6px; }.persona-conversation-rail article { position: relative; border-radius: 12px; border: 1px solid transparent; background: color-mix(in srgb,var(--panel-bg) 60%,transparent); }.persona-conversation-rail article.active { border-color: color-mix(in srgb,var(--accent-light) 36%,transparent); background: color-mix(in srgb,var(--accent-light) 9%,var(--panel-bg)); }
.persona-conversation-rail article>button:first-child { width: 100%; display: grid; gap: 3px; padding: 10px 28px 10px 10px; text-align: left; border: 0; background: transparent; color: var(--content-primary); cursor: pointer; }.persona-conversation-rail article b,.persona-conversation-rail article small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.persona-conversation-rail article span,.persona-conversation-rail article small,.persona-conversation-rail>p { color: var(--content-muted); font-size: 10px; }.persona-conversation-rail>p { line-height: 1.55; }
.persona-conversation-delete { position: absolute; top: 7px; right: 7px; width: 22px; height: 22px; border: 0; border-radius: 50%; background: transparent; color: var(--content-muted); cursor: pointer; }.persona-conversation-delete:hover { background: color-mix(in srgb,#f16f75 15%,transparent); color: #f16f75; }
.persona-chat-main { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 10px; }.persona-chat-empty button { margin-top: 14px; border: 0; border-radius: 11px; padding: 9px 13px; background: var(--accent-light); color: var(--surface-depth); font-weight: 700; cursor: pointer; }
.persona-chat-ledger { flex: 1 1 auto; min-height: 250px; display: flex; flex-direction: column; gap: 12px; overflow: auto; padding: 20px; border-radius: 20px; background: color-mix(in srgb,var(--surface-depth) 55%,transparent); border: 1px solid color-mix(in srgb,var(--content-primary) 9%,transparent); }
.persona-chat-world.is-embedded .persona-chat-ledger { min-height: 190px; padding: 13px; }
.persona-chat-empty { margin: auto; text-align: center; max-width: 560px; color: var(--content-secondary); }.persona-chat-empty>span { color: var(--accent-light); font-size: 11px; letter-spacing: .13em; }.persona-chat-empty h2 { color: var(--content-primary); margin: 7px 0; }.persona-chat-empty p { margin: 0; line-height: 1.6; }
@ -35,4 +42,104 @@
.persona-provider-form { display: grid; grid-template-columns: .8fr 1.5fr .8fr 1fr auto; gap: 8px; }
.persona-limb-strip { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 13px; border-radius: 13px; background: color-mix(in srgb,var(--surface-depth) 68%,transparent); }.persona-limb-strip>div { display: grid; gap: 3px; }.persona-limb-strip span,.persona-limb-strip small { color: var(--content-muted); font-size: 10px; }.persona-limb-strip b { font-size: 13px; }
.persona-chat-notice { margin: 0; color: var(--accent-light); font-size: 12px; }
@media (max-width: 900px) { .persona-chat-header { flex-direction: column; }.persona-chat-status { width: 100%; }.persona-chat-status span { flex: 1; max-width: none; }.persona-provider-selectors,.persona-provider-form { grid-template-columns: 1fr; }.persona-chat-message { width: 94%; } }
@media (max-width: 900px) { .persona-chat-header { flex-direction: column; }.persona-chat-status { width: 100%; }.persona-chat-status span { flex: 1; max-width: none; }.persona-chat-body { grid-template-columns: 1fr; }.persona-conversation-rail { min-height: auto; max-height: 180px; }.persona-provider-selectors,.persona-provider-form { grid-template-columns: 1fr; }.persona-chat-message { width: 94%; } }
/* HLP-AGENT-WORKBENCH-20260820
紧凑工作台覆盖层保留旧主题资产不再用巨型标题卡片墙和裸错误承载Agent */
.persona-chat-world {
--agent-line: color-mix(in srgb,var(--content-primary) 10%,transparent);
--agent-panel: color-mix(in srgb,var(--panel-bg) 88%,transparent);
position: relative;
gap: 10px;
padding: 14px clamp(14px,2.4vw,28px) 16px;
overflow: hidden;
}
.persona-chat-world.is-embedded { padding: 0; }
.persona-chat-header { min-height: 54px; align-items: center; padding: 0 2px 9px; border-bottom: 1px solid var(--agent-line); }
.persona-chat-header span { font-size: 9px; }
.persona-chat-header h1,.persona-chat-world.is-embedded .persona-chat-header h1 { margin: 3px 0 1px; font-size: 20px; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.persona-chat-header p { font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.persona-chat-header p .persona-header-divider { display: inline; letter-spacing: 0; opacity: .45; }
.persona-chat-status { min-width: 0; flex: 0 1 440px; justify-content: flex-end; padding: 0; border: 0; border-radius: 0; background: transparent; }
.persona-chat-status span { max-width: 340px; font-size: 11px; }
.persona-chat-status button { padding: 6px 9px; border: 1px solid var(--agent-line); border-radius: 8px; }
.persona-chat-body { grid-template-columns: 226px minmax(0,1fr); gap: 10px; }
.persona-conversation-rail { gap: 8px; padding: 9px 8px; border: 0; border-right: 1px solid var(--agent-line); border-radius: 0; background: color-mix(in srgb,var(--surface-depth) 44%,transparent); }
.persona-conversation-rail>header { padding: 0 4px 4px; }
.persona-conversation-rail>header button { padding: 6px 8px; border-radius: 8px; }
.persona-conversation-rail>div { gap: 3px; }
.persona-conversation-rail article { border: 0; border-left: 2px solid transparent; border-radius: 8px; background: transparent; }
.persona-conversation-rail article:hover { background: color-mix(in srgb,var(--content-primary) 4%,transparent); }
.persona-conversation-rail article.active { border-color: var(--accent-light); background: color-mix(in srgb,var(--accent-light) 7%,transparent); }
.persona-conversation-rail article>button:first-child { padding: 9px 27px 9px 10px; }
.persona-conversation-delete { top: 6px; right: 4px; }
.persona-chat-main { gap: 0; }
.persona-chat-ledger,.persona-chat-world.is-embedded .persona-chat-ledger { min-height: 180px; gap: 18px; padding: 18px max(18px,calc((100% - 920px)/2)); border: 0; border-radius: 0; background: transparent; }
.persona-chat-message { width: min(88%,760px); padding: 0 4px; border: 0; border-radius: 0; background: transparent; box-shadow: none; }
.persona-chat-message.is-persona { align-self: flex-start; }
.persona-chat-message.is-human { align-self: flex-end; width: min(76%,680px); padding: 12px 14px; border: 1px solid color-mix(in srgb,var(--accent-light) 16%,transparent); border-radius: 15px 15px 5px 15px; background: color-mix(in srgb,var(--accent-light) 10%,var(--panel-bg)); }
.persona-chat-message header b { font-size: 11px; }
.persona-chat-message header span,.persona-chat-message footer { font-size: 9px; }
.persona-chat-message p { margin: 7px 0; font-size: 14px; line-height: 1.7; overflow-wrap: anywhere; }
.persona-chat-message.is-persona p { font-size: 14.5px; }
.persona-message-markdown { margin: 7px 0; font-size: 14.5px; line-height: 1.72; overflow-wrap: anywhere; }
.persona-message-markdown :where(p,ul,ol,blockquote,pre) { margin: 0 0 11px; }
.persona-message-markdown :where(ul,ol) { padding-left: 22px; }
.persona-message-markdown li { margin: 4px 0; }
.persona-message-markdown :where(h1,h2,h3,h4) { margin: 16px 0 8px; color: var(--content-primary); font-size: 15.5px; line-height: 1.4; }
.persona-message-markdown code:not(pre code) { padding: 2px 5px; border-radius: 5px; background: color-mix(in srgb,var(--content-primary) 7%,transparent); font: .88em/1.5 ui-monospace,SFMono-Regular,Menlo,monospace; }
.persona-message-markdown pre { overflow: auto; padding: 12px; border: 1px solid var(--agent-line); border-radius: 9px; background: color-mix(in srgb,var(--panel-bg) 80%,#000); font: 12.5px/1.65 ui-monospace,SFMono-Regular,Menlo,monospace; }
.persona-message-markdown a { color: var(--accent-light); text-underline-offset: 3px; }
.persona-message-markdown > :last-child { margin-bottom: 0; }
.persona-chat-message footer { margin-top: 9px; padding-top: 7px; border-top: 1px solid var(--agent-line); }
.persona-knowledge-receipts span { border-left: 2px solid color-mix(in srgb,var(--accent-light) 48%,transparent); border-radius: 0; background: color-mix(in srgb,var(--accent-light) 6%,transparent); }
.persona-agent-activity { display: flex; flex-wrap: wrap; gap: 5px 13px; padding: 8px max(18px,calc((100% - 920px)/2)); border-top: 1px solid var(--agent-line); color: var(--content-secondary); }
.persona-agent-activity>div { min-width: 0; display: flex; align-items: center; gap: 6px; font-size: 10px; }
.persona-agent-activity i { width: 6px; height: 6px; flex: 0 0 auto; border-radius: 50%; background: var(--content-muted); }
.persona-agent-activity .is-running i { background: var(--accent-light); box-shadow: 0 0 9px color-mix(in srgb,var(--accent-light) 62%,transparent); animation: persona-agent-pulse 1.15s ease-in-out infinite; }
.persona-agent-activity .is-done i { background: #85d9bb; }
.persona-agent-activity .is-failed i { background: #f18a8f; }
.persona-agent-activity small { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--content-muted); }
@keyframes persona-agent-pulse { 50% { opacity: .35; transform: scale(.78); } }
.persona-chat-composer { gap: 7px; padding: 10px max(18px,calc((100% - 920px)/2)) 0; border-top: 1px solid var(--agent-line); background: color-mix(in srgb,var(--surface-depth) 44%,transparent); }
.persona-chat-composer textarea,.persona-chat-world.is-embedded .persona-chat-composer textarea { min-height: 72px; max-height: 210px; padding: 12px 13px; border-radius: 12px; background: var(--agent-panel); box-shadow: none; outline: none; }
.persona-chat-composer textarea:focus { border-color: color-mix(in srgb,var(--accent-light) 44%,transparent); box-shadow: 0 0 0 3px color-mix(in srgb,var(--accent-light) 7%,transparent); }
.persona-chat-composer>div:last-child { font-size: 10px; }
.persona-knowledge-focus { padding: 6px 8px; border: 0; border-left: 2px solid var(--accent-light); border-radius: 0; background: color-mix(in srgb,var(--accent-light) 5%,transparent); }
.persona-chat-settings { position: absolute; z-index: 12; top: 64px; right: clamp(14px,2.4vw,28px); width: min(760px,calc(100% - 36px)); max-height: calc(100% - 80px); overflow: auto; padding: 16px; border-radius: 13px; background: color-mix(in srgb,var(--panel-bg) 97%,#020713); box-shadow: 0 24px 70px rgba(0,0,0,.42); }
.persona-hldp-forge { position:absolute; z-index:13; inset:64px clamp(14px,2.4vw,28px) 18px auto; width:min(880px,calc(100% - 36px)); display:flex; flex-direction:column; gap:12px; padding:16px; border:1px solid var(--agent-line); border-radius:13px; background:color-mix(in srgb,var(--panel-bg) 98%,#020713); box-shadow:0 24px 70px rgba(0,0,0,.46); }
.persona-hldp-forge>header,.persona-hldp-forge>footer { display:flex; align-items:flex-start; justify-content:space-between; gap:18px; }
.persona-hldp-forge>header span,.persona-hldp-forge label>span,.persona-hldp-forge section>span { color:var(--content-muted); font-size:9px; letter-spacing:.12em; }
.persona-hldp-forge h2 { margin:4px 0; font-size:18px; }
.persona-hldp-forge p { margin:0; color:var(--content-secondary); font-size:11px; line-height:1.55; }
.persona-hldp-forge>header button { border:0; background:transparent; color:var(--content-secondary); cursor:pointer; }
.persona-hldp-forge-body { min-height:0; flex:1; display:grid; grid-template-columns:minmax(0,1.25fr) minmax(250px,.75fr); gap:12px; }
.persona-hldp-forge label { min-height:0; display:flex; flex-direction:column; gap:6px; }
.persona-hldp-forge textarea { min-height:0; flex:1; resize:none; padding:12px; border:1px solid var(--agent-line); border-radius:9px; background:color-mix(in srgb,var(--surface-depth) 84%,transparent); color:var(--content-primary); font:11px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace; outline:none; }
.persona-hldp-forge section { min-height:0; overflow:auto; display:flex; flex-direction:column; gap:7px; padding:12px; border-left:1px solid var(--agent-line); }
.persona-hldp-forge section b { font-size:13px; }
.persona-hldp-forge section small { color:var(--content-secondary); font:10px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace; }
.persona-hldp-forge ol { margin:5px 0 0; padding-left:17px; color:var(--content-secondary); font:10px/1.7 ui-monospace,SFMono-Regular,Menlo,monospace; }
.persona-hldp-forge>footer { align-items:center; padding-top:11px; border-top:1px solid var(--agent-line); }
.persona-hldp-forge>footer span { color:var(--content-muted); font-size:10px; }
.persona-hldp-forge>footer button { border:0; border-radius:9px; padding:9px 15px; background:var(--accent-light); color:var(--surface-depth); font-weight:760; cursor:pointer; }
.persona-hldp-forge>footer button:disabled { opacity:.45; cursor:default; }
.persona-chat-settings h2 { font-size: 18px; }
.persona-provider-form { grid-template-columns: .8fr 1.4fr .8fr 1fr auto; }
.persona-chat-notice { position: absolute; z-index: 14; left: 50%; bottom: 112px; transform: translateX(-50%); max-width: min(640px,84%); padding: 7px 11px; border: 1px solid var(--agent-line); border-radius: 9px; background: color-mix(in srgb,var(--panel-bg) 96%,transparent); color: var(--content-secondary); box-shadow: 0 10px 30px rgba(0,0,0,.25); }
@media (max-width:900px) {
.persona-chat-header { flex-direction: row; align-items: flex-start; }
.persona-chat-status { width: auto; flex: 0 1 50%; }
.persona-chat-status span { max-width: 180px; }
.persona-chat-body { grid-template-columns: 176px minmax(0,1fr); }
.persona-conversation-rail { max-height: none; }
.persona-provider-form { grid-template-columns: 1fr; }
}
@media (max-width:680px) {
.persona-chat-header p,.persona-chat-status span { display: none; }
.persona-chat-body { grid-template-columns:1fr; }
.persona-conversation-rail { max-height:132px; border-right:0; border-bottom:1px solid var(--agent-line); }
.persona-chat-message.is-human { width:90%; }
.persona-hldp-forge-body { grid-template-columns:1fr; }
.persona-hldp-forge section { border-left:0; border-top:1px solid var(--agent-line); }
}

View file

@ -168,7 +168,7 @@
@keyframes sl-abyss-open { 0%{opacity:1;transform:translate(-50%,-50%) scale(1)} 54%{opacity:.9;transform:translate(-50%,-50%) scale(1.45);filter:brightness(1.4)} 100%{opacity:0;transform:translate(-50%,-50%) scale(3.2);filter:blur(16px) brightness(1.9)} }
@keyframes sl-abyss-copy-away { to{opacity:0;transform:translateY(8px)} }
.starlake-scene .world-channel-return { position:absolute; z-index:9; left:50%; top:44%; transform:translate(-50%,-50%); display:grid; justify-items:center; gap:4px;
padding:12px 18px; border:0; color:inherit; background:radial-gradient(ellipse,rgba(247,235,200,.08),transparent 72%); cursor:pointer; font-family:inherit; }
padding:12px 18px; border:0; color:inherit; background:radial-gradient(ellipse,rgba(247,235,200,.08),transparent 72%); pointer-events:auto; cursor:pointer; font-family:inherit; }
.starlake-scene .world-channel-return b { color:#f7ebc8; font-size:13px; font-weight:760; letter-spacing:.18em; }
.starlake-scene .world-channel-return small { color:rgba(196,206,228,.58); font-size:9px; font-weight:650; letter-spacing:.1em; }
.starlake-scene .era-foot { position:absolute; left:50%; bottom:21px; transform:translateX(-50%); color:rgba(180,192,220,.34);

View file

@ -971,6 +971,7 @@ svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-lineca
/* ==== 标准工作台 · 公告与版本 · 执行层投影实例1移植 2026-08-20 正向合并) ==== */
.standard-workbench { width: 100vw; height: 100vh; display: grid; grid-template-columns: 52px 244px minmax(0, 1fr); overflow: hidden; color: var(--content-primary); background: var(--surface-depth); }
.workbench-empty, .empty-state { display: grid; place-content: center; justify-items: center; color: var(--content-muted); text-align: center; }
.workbench-empty { min-height: 0; padding: 40px; }
.workbench-empty > span { color: var(--accent-light); font-family: "Songti SC", serif; font-size: 36px; }
@ -1049,9 +1050,17 @@ svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-lineca
.execution-fields dd { color: var(--content-secondary); }
.release-fields { margin-top: 12px; border-top: 1px solid var(--panel-edge); }
.release-fields > div { padding-left: 0; padding-right: 0; }
.workbench-topbar { grid-template-columns: minmax(120px, 1fr) auto; }
.workbench-account { display: none; }
.execution-section-grid { grid-template-columns: 1fr; }
.workbench-sidebar { display: none; }
.workbench-topbar > div:first-child span { display: none; }
.release-center-title, .execution-projection .page-title { align-items: flex-start; flex-direction: column; }
.execution-projection { max-width: 1180px; margin: 0 auto; }
@media (max-width: 900px) {
.standard-workbench { grid-template-columns: 48px 190px minmax(0, 1fr); }
.workbench-topbar { grid-template-columns: minmax(120px, 1fr) auto; }
.workbench-account { display: none; }
.execution-section-grid { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
.standard-workbench { grid-template-columns: 46px minmax(0, 1fr); }
.workbench-sidebar { display: none; }
.workbench-topbar > div:first-child span { display: none; }
.release-center-title, .execution-projection .page-title { align-items: flex-start; flex-direction: column; }
}