2026-08-12 01:08:56 +08:00
|
|
|
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',
|
2026-08-12 01:52:30 +08:00
|
|
|
sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.4',
|
2026-08-12 01:08:56 +08:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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',
|
2026-08-12 01:52:30 +08:00
|
|
|
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 },
|
|
|
|
|
}],
|
2026-08-12 01:08:56 +08:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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')
|
|
|
|
|
})
|
|
|
|
|
})
|