import { beforeEach, 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 native = vi.hoisted(() => ({ invoke: vi.fn() })) vi.mock('@tauri-apps/api/core', () => ({ invoke: native.invoke })) vi.mock('../mock-tauri', () => ({ isTauri: () => false, mockInvoke: native.invoke })) 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], requestId: 'REQ-001', modelInstanceId: 'MODEL-INSTANCE-001', developmentId: 'DEV-20260811-010', sourceLanguageAnchor: 'current-human-utterance', } } describe('planPersonaLanguageShellGoal', () => { beforeEach(() => native.invoke.mockReset()) 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) expect(planGoal).toHaveBeenCalledWith(expect.objectContaining({ personaAuthorized: false })) }) it('enables persona-primary planning only after the native verifier accepts the exact receipt', async () => { const planGoal = vi.fn().mockResolvedValue(plannedGoal) const candidateReceipt = { schema: 'hololake.persona-control-authorization/v2', outcome: 'VERIFIED', authorizationId: 'AUTH-001', } native.invoke.mockResolvedValue({ status: 'VERIFIED', reason: null, sourceCommit: 'c'.repeat(40), signerId: 'GH-AIOS-AUTHORIZER-001', authorizationEnabled: true, }) await planPersonaLanguageShellGoal({ ...input(), personaControlAuthorizationReceipt: candidateReceipt, authorizationObservedAt: Date.parse('2026-08-12T04:35:00+08:00'), resolveRepository: vi.fn().mockResolvedValue(boundResolution()), loadDeviceIdentity: vi.fn().mockResolvedValue({ schema: 'guanghu.router-device/v1', device_id: 'HL-DEVICE-001', public_key: 'public-key', }), planGoal, }) expect(native.invoke).toHaveBeenCalledWith( 'verify_persona_control_authorization', { receipt: candidateReceipt, expectation: { personaId: repositoryBinding.personaId, humanResponsibilitySubject: repositoryBinding.humanResponsibilitySubject, repositoryHead: repositoryBinding.gitHead, modelInstanceId: 'MODEL-INSTANCE-001', requestId: 'REQ-001', sourceLanguageAnchor: 'current-human-utterance', observedAtMilliseconds: Date.parse('2026-08-12T04:35:00+08:00'), }, }, ) expect(planGoal).toHaveBeenCalledWith(expect.objectContaining({ personaAuthorized: true })) }) it('keeps system-direct planning for a native denial', async () => { const planGoal = vi.fn().mockResolvedValue(plannedGoal) native.invoke.mockResolvedValue({ status: 'DENIED', reason: 'NO_TRUSTED_SIGNER', sourceCommit: 'c'.repeat(40), signerId: null, authorizationEnabled: false, }) await planPersonaLanguageShellGoal({ ...input(), personaControlAuthorizationReceipt: { outcome: 'VERIFIED' }, resolveRepository: vi.fn().mockResolvedValue(boundResolution()), loadDeviceIdentity: vi.fn().mockResolvedValue({ schema: 'guanghu.router-device/v1', device_id: 'HL-DEVICE-001', public_key: 'public-key', }), planGoal, }) expect(planGoal).toHaveBeenCalledWith(expect.objectContaining({ personaAuthorized: false })) }) it('keeps system-direct planning when the native verifier is unavailable', async () => { const planGoal = vi.fn().mockResolvedValue(plannedGoal) native.invoke.mockImplementationOnce(() => { throw new Error('SOURCE_UNAVAILABLE') }) await planPersonaLanguageShellGoal({ ...input(), personaControlAuthorizationReceipt: { outcome: 'VERIFIED' }, resolveRepository: vi.fn().mockResolvedValue(boundResolution()), loadDeviceIdentity: vi.fn().mockResolvedValue({ schema: 'guanghu.router-device/v1', device_id: 'HL-DEVICE-001', public_key: 'public-key', }), planGoal, }) expect(planGoal).toHaveBeenCalledWith(expect.objectContaining({ personaAuthorized: false })) }) 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() }) })