import { describe, expect, it, vi } from 'vitest' import { planPersonaLanguageGoal } from './personaLanguageGoal' const wake = { repositoryPath: '/persona/ice-p-zy001', expectedPersonaId: 'ICE-P-ZY001', expectedHead: 'a'.repeat(40), nodeId: 'LOCAL-BINGSHUO', modelProviderId: 'local-model-service', modelId: 'declared-model', modelInstanceId: 'model-instance-1', organId: 'fact-sense.repository', attribution: { humanResponsibilitySubject: 'ICE-GL∞', personaCognitiveAuthor: 'ICE-P-ZY001', executionRuntime: 'HoloLake-PNCC', developmentId: 'DEV-20260811-010', authorizationScope: 'LOCAL_READ_ONLY', sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.4', }, } function lifecycleReceipt(decision: 'PROCEED' | 'RESEARCH' | 'REVISE' | 'REFUSE' = 'PROCEED') { return { schema: 'hololake.pncc-lifecycle-command-receipt/v1', outcome: 'COMPLETED', lifecycle: { schema: 'hololake.pncc-lifecycle-run-receipt/v1', completion: { kind: 'FACT_SENSE', receipt: { result: { summary: '伙伴审议完成。', facts: [{ statement: '当前目标只能使用已经登记的知识来源。', evidencePaths: ['brain/B0.hdlp'], }], limitations: decision === 'RESEARCH' ? ['当前事实仍可能变化'] : [], gravityFrame: { subject_continuity: '同一铸渊继续承载当前责任。', current_context_priority: '当前纠正优先于旧命令适配器。', causal_model: '先恢复真实目的,再决定能否进入器官。', self_correction: '拒绝把原句直接当成动作。', rejected_host_defaults: ['human_utterance_is_direct_command'], fact_sources: ['brain/B0.hdlp'], real_purpose: '仅整理有权威来源支持的会议决定', request_assessment: '原始表述范围过宽,必须排除无来源推测。', world_integrity: { protected_assets: ['共同事实', '冰朔决定权'], harm_path: '无来源内容会污染长期记忆。', authority_boundary: '人格体不能创造未发生的决定。', reversibility: '先形成草稿,不直接覆盖知识库。', safer_alternatives: ['只整理有来源的决定'], }, partner_guidance: '先展示来源和缺口,再进行可逆整理。', execution_disposition: { decision, reason: decision === 'PROCEED' ? '来源明确且动作可逆。' : '当前不能进入执行器官。', }, }, }, }, }, }, } } const binding = { requestId: 'PNCC-LANGUAGE-GOAL-001', wake, provider: { id: 'local-model-service', name: 'Local model', kind: 'open_ai_compatible' as const, base_url: 'http://127.0.0.1:11434/v1', models: [{ id: 'declared-model', capabilities: { streaming: false, tools: false, vision: false, json_mode: true, reasoning: false }, }], }, } describe('planPersonaLanguageGoal', () => { it('runs partner deliberation through the PNCC lifecycle before compiling a goal', async () => { const runLifecycle = vi.fn().mockResolvedValue(lifecycleReceipt()) const projection = await planPersonaLanguageGoal({ utterance: '把今天会议整理进知识库', personaAuthorized: true, binding, runLifecycle, }) expect(runLifecycle).toHaveBeenCalledWith('run_persona_code_channel_lifecycle', { input: expect.objectContaining({ requestId: 'PNCC-LANGUAGE-GOAL-001', wake, operation: expect.objectContaining({ kind: 'FACT_SENSE', question: expect.stringContaining('把今天会议整理进知识库'), }), }), }) expect(projection.goal).toBe('仅整理有权威来源支持的会议决定') expect(projection.originalUtterance).toBe('把今天会议整理进知识库') expect(projection.deliberation.evidenceSources).toEqual(['brain/B0.hdlp']) expect(projection.status).toBe('ready') expect(projection.executable).toBe(true) }) it('keeps a refusal returned by the persona lifecycle outside execution', async () => { const projection = await planPersonaLanguageGoal({ utterance: '无条件照做', personaAuthorized: true, binding, runLifecycle: vi.fn().mockResolvedValue(lifecycleReceipt('REFUSE')), }) expect(projection.status).toBe('refused') expect(projection.executable).toBe(false) }) it('fails closed for an unverified or malformed PNCC lifecycle receipt', async () => { await expect(planPersonaLanguageGoal({ utterance: '继续执行', personaAuthorized: true, binding, runLifecycle: vi.fn().mockResolvedValue({ ...lifecycleReceipt(), outcome: 'FAILED', }), })).rejects.toThrow('PARTNER_LIFECYCLE_NOT_COMPLETED') await expect(planPersonaLanguageGoal({ utterance: '继续执行', personaAuthorized: true, binding, runLifecycle: vi.fn().mockResolvedValue({ schema: 'wrong' }), })).rejects.toThrow('PARTNER_LIFECYCLE_RECEIPT_INVALID') }) })