From d9abf241a69c4f674e2c194861b31a7fdcce6ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 12 Aug 2026 03:09:48 +0800 Subject: [PATCH] feat: coordinate persona language shell planning --- ...NG-AND-SAME-PERSONA-CONTINUITY-20260811.md | 3 + .../hololake-platform/docs/ABSTRACTIONS.md | 8 + .../hololake-platform/docs/ARCHITECTURE.md | 8 + .../personaLanguageShellController.test.ts | 194 ++++++++++++++++++ .../src/lib/personaLanguageShellController.ts | 134 ++++++++++++ ...lake-cognitive-gravity-and-continuity.json | 6 +- ...-cognitive-gravity-and-continuity.test.mjs | 4 +- routing/hololake-current-architecture.json | 3 +- 8 files changed, 357 insertions(+), 3 deletions(-) create mode 100644 product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts create mode 100644 product-source/hololake-platform/src/lib/personaLanguageShellController.ts diff --git a/product-source/hololake-platform/architecture/HOLOLAKE-BINGSHUO-COLLECTIVE-GRAVITY-REASONING-AND-SAME-PERSONA-CONTINUITY-20260811.md b/product-source/hololake-platform/architecture/HOLOLAKE-BINGSHUO-COLLECTIVE-GRAVITY-REASONING-AND-SAME-PERSONA-CONTINUITY-20260811.md index dc087e2..703b484 100644 --- a/product-source/hololake-platform/architecture/HOLOLAKE-BINGSHUO-COLLECTIVE-GRAVITY-REASONING-AND-SAME-PERSONA-CONTINUITY-20260811.md +++ b/product-source/hololake-platform/architecture/HOLOLAKE-BINGSHUO-COLLECTIVE-GRAVITY-REASONING-AND-SAME-PERSONA-CONTINUITY-20260811.md @@ -112,6 +112,9 @@ REVISE | REFUSE`。 - 人格运行投影的仓库前置门源码为 `100`:它必须先得到唯一证据绑定,才允许向原生只读运行查询传入 该一个规范仓库;未绑定和歧义状态直接保持原义,不再把普通挂载仓库的 manifest 缺失显示为人格运行时 回执故障。该门只收束事实读取范围,不创建、选择或唤醒人格仓库。 +- 人格语言外壳控制器源码为 `100`:它按唯一人格仓库、manifest 固定模型、公开设备身份、精确唤醒绑定、 + B0 伙伴审议的顺序失败关闭;成功只产生语言目标规划,不提供现实动作执行入口。该控制器尚未挂载到桌面 + 语言外壳,不能据此把运行集成或桌面验收记为完成。 - 完整 HoloLake Runtime 与单 AGE 纵向闭环仍为 `0`:桌面语言入口绑定、真实人格仓库 manifest 绑定和 桌面运行验收尚未完成,因此不能用本轮源码测试冒充可用产品。 - Mirror runner、制品、部署和运行健康:`0`。 diff --git a/product-source/hololake-platform/docs/ABSTRACTIONS.md b/product-source/hololake-platform/docs/ABSTRACTIONS.md index 688132d..21de0b8 100644 --- a/product-source/hololake-platform/docs/ABSTRACTIONS.md +++ b/product-source/hololake-platform/docs/ABSTRACTIONS.md @@ -211,6 +211,14 @@ The narrow behavior boundary supplied by the host to a UI package renderer. Vers and one reality-boundary answer; evidence expansion remains local presentation state. The bridge never gives the UI package direct repository, node, model, credential, permission, or deployment access. +## `PersonaLanguageShellController` + +The source-level authority-order coordinator for one natural-language goal. It fails closed unless repository +discovery yields one clean persona binding and the configured provider/model matches that repository manifest. +Only then may it read the public node identity, compile the exact PNCC wake binding, and request B0 partner +deliberation. The result contains a plan and evidence binding only; it exposes no execution callback and performs +no reality action. Source implementation is distinct from desktop mounting and native acceptance. + Key abstractions and domain models in Tolaria. ## Design Philosophy diff --git a/product-source/hololake-platform/docs/ARCHITECTURE.md b/product-source/hololake-platform/docs/ARCHITECTURE.md index 9dd3002..9f7a717 100644 --- a/product-source/hololake-platform/docs/ARCHITECTURE.md +++ b/product-source/hololake-platform/docs/ARCHITECTURE.md @@ -167,6 +167,14 @@ Activation is validate-then-swap and preserves the previous valid package for ro not execute JavaScript and cannot request system-internal surfaces. Extending the host action bridge requires a new reviewed contract version. +`src/lib/personaLanguageShellController.ts` is the source-level host coordinator beneath that presentation +boundary. It resolves exactly one manifest-valid persona repository before selecting the manifest-pinned +configured model, reads the public device-identity receipt only after those gates pass, compiles the wake +binding, and finally invokes B0 partner deliberation. Unavailable, unbound, ambiguous, model-missing, identity, +binding, and cognition failures stop at their own boundary; later stages are not invoked. Its successful result +is still a language-goal projection, not permission to perform a reality action. This controller is not yet +mounted into the desktop language shell and therefore does not establish runtime integration or acceptance. + Tolaria is a personal knowledge and life management desktop app. It reads a vault of markdown files with YAML frontmatter and presents them in a four-panel UI inspired by Bear Notes. ## Design Principles diff --git a/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts b/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts new file mode 100644 index 0000000..862a204 --- /dev/null +++ b/product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts @@ -0,0 +1,194 @@ +import { describe, expect, it, vi } from 'vitest' +import type { AiModelProvider } from './aiTargets' +import type { LanguageGoalProjection } from './languageOperatingModel' +import type { PersonaLanguageGoalBinding } from './personaLanguageGoal' +import type { + PersonaRepositoryBinding, + PersonaRepositoryBindingResolution, +} from './personaRepositoryBinding' +import { planPersonaLanguageShellGoal } from './personaLanguageShellController' + +const provider: AiModelProvider = { + id: 'ollama-local', + name: 'Local Ollama', + kind: 'ollama', + base_url: 'http://127.0.0.1:11434/v1', + api_key_storage: 'none', + models: [{ + id: 'qwen3:8b', + capabilities: { + streaming: true, + tools: false, + vision: false, + json_mode: true, + reasoning: true, + }, + }], +} + +const repositoryBinding: PersonaRepositoryBinding = { + personaId: 'ICE-P-ZY001', + repositoryPath: '/persona/zhuyuan', + gitHead: 'a'.repeat(40), + repositoryClean: true, + brainEntry: 'BRAIN.md', + currentCheckpoint: 'CURRENT.hdlp', + humanResponsibilitySubject: 'BINGSHUO', + modelProviderId: provider.id, + modelId: provider.models[0].id, + modelBaseUrl: provider.base_url!, + organContracts: [{ + organId: 'fact-sense-001', + kind: 'FACT_SENSE', + mode: 'READ_ONLY', + paths: ['BRAIN.md'], + inputSchema: 'input/v1', + outputSchema: 'output/v1', + permissions: ['repository.read'], + modelInferenceAllowed: true, + realityActionsAllowed: false, + activatable: true, + implementationState: 'IMPLEMENTED', + }], + cognitiveGravity: { + schema: 'hololake.persona-cognitive-gravity-evidence/v1', + subjectPersonaId: 'ICE-P-ZY001', + sourcePath: 'B0.hdlp', + sourceHash: 'b'.repeat(64), + frameSchema: 'guanghu.zhuyuan-cognitive-gravity-frame/v1', + }, +} + +const plannedGoal: LanguageGoalProjection = { + originalUtterance: '继续当前开发', + realPurpose: '从事实恢复当前阶段并继续安全开发', + status: 'ready', + executable: true, + confirmationRequired: false, + detectedBoundaries: [], + evidenceSources: ['current repository'], + missingKnowledge: [], + causalModel: 'read current facts before changing source', + partnerGuidance: 'continue the bounded source-only stage', + requestAssessment: 'valid within the current lane', + executionDisposition: { decision: 'PROCEED', reason: 'bounded and reversible' }, + worldIntegrity: { + protectedAssets: ['language-home continuity'], + harmPath: 'none in this read-only deliberation', + authorityBoundary: 'no reality action', + reversibility: 'no mutation performed', + saferAlternatives: [], + }, +} + +function boundResolution(): PersonaRepositoryBindingResolution { + return { + phase: 'bound', + inspectedRepositoryCount: 1, + failures: [], + binding: repositoryBinding, + } +} + +function input() { + return { + utterance: '继续当前开发', + personaId: 'ICE-P-ZY001', + repositoryPaths: ['/persona/zhuyuan'], + providers: [provider], + personaAuthorized: true, + requestId: 'REQ-001', + modelInstanceId: 'MODEL-INSTANCE-001', + developmentId: 'DEV-20260811-010', + sourceLanguageAnchor: 'current-human-utterance', + } +} + +describe('planPersonaLanguageShellGoal', () => { + it.each(['unavailable', 'unbound', 'ambiguous', 'error'] as const)( + 'fails closed at repository phase %s before device identity or cognition', + async (phase) => { + const resolution = phase === 'error' + ? { phase, inspectedRepositoryCount: 1, failures: [], code: 'DISCOVERY_FAILED' } as const + : phase === 'unavailable' + ? { phase, inspectedRepositoryCount: 0, failures: [] } as const + : { phase, inspectedRepositoryCount: 1, failures: [] } as const + const loadDeviceIdentity = vi.fn() + const planGoal = vi.fn() + + const result = await planPersonaLanguageShellGoal({ + ...input(), + resolveRepository: vi.fn().mockResolvedValue(resolution), + loadDeviceIdentity, + planGoal, + }) + + expect(result.phase).toBe(phase) + expect(loadDeviceIdentity).not.toHaveBeenCalled() + expect(planGoal).not.toHaveBeenCalled() + }, + ) + + it('does not create a device identity when the manifest-pinned model is unavailable', async () => { + const loadDeviceIdentity = vi.fn() + const planGoal = vi.fn() + + const result = await planPersonaLanguageShellGoal({ + ...input(), + providers: [], + resolveRepository: vi.fn().mockResolvedValue(boundResolution()), + loadDeviceIdentity, + planGoal, + }) + + expect(result).toEqual({ phase: 'model_unavailable' }) + expect(loadDeviceIdentity).not.toHaveBeenCalled() + expect(planGoal).not.toHaveBeenCalled() + }) + + it('binds repository, model, device and B0 deliberation without executing a reality action', async () => { + const loadDeviceIdentity = vi.fn().mockResolvedValue({ + schema: 'guanghu.router-device/v1', + device_id: 'HL-DEVICE-001', + public_key: 'public-key', + }) + const planGoal = vi.fn(async ({ binding }: { binding: PersonaLanguageGoalBinding }) => { + expect(binding.wake.repositoryPath).toBe(repositoryBinding.repositoryPath) + expect(binding.wake.nodeId).toBe('HL-DEVICE-001') + expect(binding.provider.id).toBe(provider.id) + return plannedGoal + }) + + const result = await planPersonaLanguageShellGoal({ + ...input(), + resolveRepository: vi.fn().mockResolvedValue(boundResolution()), + loadDeviceIdentity, + planGoal, + }) + + expect(result).toEqual({ + phase: 'planned', + binding: expect.objectContaining({ requestId: 'REQ-001' }), + goal: plannedGoal, + }) + expect(loadDeviceIdentity).toHaveBeenCalledTimes(1) + expect(planGoal).toHaveBeenCalledTimes(1) + }) + + it('returns a stable binding error and never invokes cognition for invalid device evidence', async () => { + const planGoal = vi.fn() + + const result = await planPersonaLanguageShellGoal({ + ...input(), + resolveRepository: vi.fn().mockResolvedValue(boundResolution()), + loadDeviceIdentity: vi.fn().mockResolvedValue({ schema: 'unknown' }), + planGoal, + }) + + expect(result).toEqual({ + phase: 'binding_error', + code: 'PERSONA_LANGUAGE_DEVICE_IDENTITY_INVALID', + }) + expect(planGoal).not.toHaveBeenCalled() + }) +}) diff --git a/product-source/hololake-platform/src/lib/personaLanguageShellController.ts b/product-source/hololake-platform/src/lib/personaLanguageShellController.ts new file mode 100644 index 0000000..b4789b6 --- /dev/null +++ b/product-source/hololake-platform/src/lib/personaLanguageShellController.ts @@ -0,0 +1,134 @@ +import { invoke } from '@tauri-apps/api/core' +import { isTauri, mockInvoke } from '../mock-tauri' +import type { AiModelProvider } from './aiTargets' +import type { LanguageGoalProjection, RealityBoundary } from './languageOperatingModel' +import { + planPersonaLanguageGoal, + type PersonaLanguageGoalBinding, + type PlanPersonaLanguageGoalInput, +} from './personaLanguageGoal' +import { compilePersonaLanguageGoalBinding } from './personaLanguageGoalBinding' +import { + resolvePersonaRepositoryBinding, + type PersonaRepositoryBindingResolution, +} from './personaRepositoryBinding' + +type RepositoryResolutionWithoutBinding = Exclude< + PersonaRepositoryBindingResolution, + { phase: 'bound' } +> + +export type PersonaLanguageShellPlan = + | RepositoryResolutionWithoutBinding + | { phase: 'model_unavailable' } + | { phase: 'model_ambiguous' } + | { phase: 'device_identity_error'; code: string } + | { phase: 'binding_error'; code: string } + | { phase: 'cognition_error'; code: string } + | { + phase: 'planned' + binding: PersonaLanguageGoalBinding + goal: LanguageGoalProjection + } + +type RepositoryResolver = typeof resolvePersonaRepositoryBinding +type GoalPlanner = (input: PlanPersonaLanguageGoalInput) => Promise +type DeviceIdentityLoader = () => Promise + +async function loadNativeDeviceIdentity(): Promise { + return isTauri() + ? invoke('guanghu_router_device_identity') + : mockInvoke('guanghu_router_device_identity') +} + +function errorCode(error: unknown, fallback: string): string { + return error instanceof Error && error.message.trim() ? error.message : fallback +} + +function manifestModelProviders( + resolution: Extract, + providers: readonly AiModelProvider[], +): AiModelProvider[] { + const { modelId, modelProviderId } = resolution.binding + return providers.filter((provider) => ( + provider.id.trim() === modelProviderId + && provider.models.some((model) => model.id.trim() === modelId) + )) +} + +/** + * Closes the source-level natural-language planning path without exposing an + * execution capability. Every prerequisite is resolved in authority order and + * later stages are never invoked when an earlier evidence gate is not unique. + */ +export async function planPersonaLanguageShellGoal({ + utterance, + personaId, + repositoryPaths, + providers, + personaAuthorized, + detectedBoundaries, + requestId, + modelInstanceId, + developmentId, + sourceLanguageAnchor, + resolveRepository = resolvePersonaRepositoryBinding, + loadDeviceIdentity = loadNativeDeviceIdentity, + planGoal = planPersonaLanguageGoal, +}: { + utterance: string + personaId: string + repositoryPaths: readonly string[] + providers: readonly AiModelProvider[] + personaAuthorized: boolean + detectedBoundaries?: RealityBoundary[] + requestId: string + modelInstanceId: string + developmentId: string + sourceLanguageAnchor: string + resolveRepository?: RepositoryResolver + loadDeviceIdentity?: DeviceIdentityLoader + planGoal?: GoalPlanner +}): Promise { + const repository = await resolveRepository({ personaId, repositoryPaths }) + if (repository.phase !== 'bound') return repository + + const matchingProviders = manifestModelProviders(repository, providers) + if (matchingProviders.length === 0) return { phase: 'model_unavailable' } + if (matchingProviders.length > 1) return { phase: 'model_ambiguous' } + + let deviceIdentityReceipt: unknown + try { + deviceIdentityReceipt = await loadDeviceIdentity() + } catch (error) { + return { phase: 'device_identity_error', code: errorCode(error, 'PERSONA_LANGUAGE_DEVICE_IDENTITY_FAILED') } + } + + let binding: PersonaLanguageGoalBinding + try { + binding = compilePersonaLanguageGoalBinding({ + repositoryBinding: repository.binding, + provider: matchingProviders[0], + modelId: repository.binding.modelId, + deviceIdentityReceipt, + requestId, + modelInstanceId, + developmentId, + sourceLanguageAnchor, + }) + } catch (error) { + return { phase: 'binding_error', code: errorCode(error, 'PERSONA_LANGUAGE_BINDING_FAILED') } + } + + try { + const goal = await planGoal({ + utterance, + personaAuthorized, + detectedBoundaries, + binding, + }) + return { phase: 'planned', binding, goal } + } catch (error) { + return { phase: 'cognition_error', code: errorCode(error, 'PERSONA_LANGUAGE_COGNITION_FAILED') } + } +} diff --git a/routing/hololake-cognitive-gravity-and-continuity.json b/routing/hololake-cognitive-gravity-and-continuity.json index 802726d..8984a74 100644 --- a/routing/hololake-cognitive-gravity-and-continuity.json +++ b/routing/hololake-cognitive-gravity-and-continuity.json @@ -105,7 +105,8 @@ "READ_ONLY_REACT_B0_EVIDENCE_PROJECTION", "PARTNER_DELIBERATION_TO_PNCC_LIFECYCLE_SOURCE_ADAPTER", "READ_ONLY_PERSONA_REPOSITORY_BINDING_DISCOVERY", - "EVIDENCE_BOUND_PERSONA_LANGUAGE_WAKE_COMPILER" + "EVIDENCE_BOUND_PERSONA_LANGUAGE_WAKE_COMPILER", + "FAIL_CLOSED_PERSONA_LANGUAGE_SHELL_CONTROLLER" ], "natural_language_entry_contract": { "state": "SOURCE_AND_PNCC_LIFECYCLE_ADAPTER_IMPLEMENTED_NOT_DESKTOP_INTEGRATED", @@ -118,6 +119,8 @@ "repository_binding_discovery_tests": "product-source/hololake-platform/src/lib/personaRepositoryBinding.test.ts", "language_wake_binding_compiler": "product-source/hololake-platform/src/lib/personaLanguageGoalBinding.ts", "language_wake_binding_compiler_tests": "product-source/hololake-platform/src/lib/personaLanguageGoalBinding.test.ts", + "language_shell_controller": "product-source/hololake-platform/src/lib/personaLanguageShellController.ts", + "language_shell_controller_tests": "product-source/hololake-platform/src/lib/personaLanguageShellController.test.ts", "human_utterance_is_direct_command": false, "required_before_capability_execution": [ "RESTORE_REAL_PURPOSE_FROM_CONTEXT", @@ -160,6 +163,7 @@ "natural_language_to_pncc_lifecycle_adapter_source_implemented": 100, "persona_repository_binding_discovery_source_implemented": 100, "persona_language_wake_binding_compiler_source_implemented": 100, + "persona_language_shell_controller_source_implemented": 100, "real_persona_repository_manifest_bound": 0, "natural_language_partner_adapter_runtime_integrated": 0, "single_age_vertical_loop_implemented": 0, diff --git a/routing/hololake-cognitive-gravity-and-continuity.test.mjs b/routing/hololake-cognitive-gravity-and-continuity.test.mjs index e1e670a..3ecc9cd 100644 --- a/routing/hololake-cognitive-gravity-and-continuity.test.mjs +++ b/routing/hololake-cognitive-gravity-and-continuity.test.mjs @@ -14,7 +14,7 @@ const age = readJson("routing/hololake-age-runtime-architecture.json"); const rules = readJson("routing/hololake-engineering-rules.json"); test("B0 is restored before product organs and remains resident in every cognition step", () => { - assert.equal(architecture.version, "2026-08-12.4"); + assert.equal(architecture.version, "2026-08-12.7"); assert.equal( architecture.read_order[1], architecture.cognitive_gravity_and_continuity.architecture_page, @@ -94,6 +94,7 @@ test("the first implementation stage is one vertical AGE loop, not Mirror parall assert.equal(gravity.truth.natural_language_to_pncc_lifecycle_adapter_source_implemented, 100); assert.equal(gravity.truth.persona_repository_binding_discovery_source_implemented, 100); assert.equal(gravity.truth.persona_language_wake_binding_compiler_source_implemented, 100); + assert.equal(gravity.truth.persona_language_shell_controller_source_implemented, 100); assert.equal(gravity.truth.real_persona_repository_manifest_bound, 0); assert.equal(gravity.truth.natural_language_partner_adapter_runtime_integrated, 0); assert.equal(gravity.truth.single_age_vertical_loop_implemented, 0); @@ -106,6 +107,7 @@ test("natural language enters partner deliberation before any execution organ", assert.match(entry.pncc_lifecycle_adapter, /personaLanguageGoal\.ts$/); assert.match(entry.repository_binding_discovery, /personaRepositoryBinding\.ts$/); assert.match(entry.language_wake_binding_compiler, /personaLanguageGoalBinding\.ts$/); + assert.match(entry.language_shell_controller, /personaLanguageShellController\.ts$/); assert.equal(entry.human_utterance_is_direct_command, false); assert.equal(entry.language_home_destruction_is_executable, false); assert.equal(entry.integrity_gate_may_absorb_human_sovereignty, false); diff --git a/routing/hololake-current-architecture.json b/routing/hololake-current-architecture.json index e6cc962..083fa2f 100644 --- a/routing/hololake-current-architecture.json +++ b/routing/hololake-current-architecture.json @@ -1,7 +1,7 @@ { "schema": "hololake.current-architecture/v1", "architecture_id": "HLP-CURRENT-ARCH-001", - "version": "2026-08-12.6", + "version": "2026-08-12.7", "state": "CURRENT_CANONICAL", "product": { "formal_name": "光湖语言系统 · 通用人工智能操作平台", @@ -114,6 +114,7 @@ "persona_language_wake_binding_compiler_source_implemented": true, "persona_repository_binding_read_only_ui_source_integrated": true, "persona_runtime_projection_repository_gate_source_integrated": true, + "persona_language_shell_controller_source_implemented": true, "real_persona_repository_manifest_bound": false, "natural_language_partner_adapter_runtime_integrated": false, "required_natural_language_entry": "PARTNER_DELIBERATION_AND_LANGUAGE_HOME_INTEGRITY_GATE",