feat: enforce Guanghu-native HoloLake runtime laws
This commit is contained in:
parent
ccee303355
commit
67e6fcdd38
57 changed files with 1765 additions and 1504 deletions
|
|
@ -30,26 +30,72 @@ const event = createLivingSystemEvent({
|
|||
now: 1,
|
||||
})
|
||||
|
||||
function typedPlan({
|
||||
eventId = 'event-001',
|
||||
intent = 'navigate' as const,
|
||||
requiredTruth = ['truth-001'],
|
||||
stateLabel = 'model-proposed' as const,
|
||||
} = {}) {
|
||||
return {
|
||||
version: 1 as const,
|
||||
eventId,
|
||||
intent,
|
||||
planId: 'model-plan-001',
|
||||
requiredTruth,
|
||||
uiProjection: {
|
||||
route: 'fifth-domain' as const,
|
||||
stateLabel,
|
||||
scene: {
|
||||
depth: 'immersive' as const,
|
||||
motion: 'active' as const,
|
||||
starDensity: 'rich' as const,
|
||||
connectionEmphasis: 'network' as const,
|
||||
},
|
||||
},
|
||||
navigationAction: { type: 'navigate' as const, route: 'fifth-domain' as const },
|
||||
capabilityCall: null,
|
||||
receiptSchema: {
|
||||
outcome: 'pending-evidence' as const,
|
||||
requiredEvidence: ['ui.route.readback'],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
describe('planGuanghuLivingSystem', () => {
|
||||
it('uses the receipt-backed Shanghai lighthouse as the primary system model', async () => {
|
||||
it('does not call a server planner without a verified current runtime binding', async () => {
|
||||
const server = vi.fn().mockRejectedValue(new Error('legacy server route must stay closed'))
|
||||
|
||||
await planGuanghuLivingSystem({ event, server })
|
||||
|
||||
expect(server).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('uses a server model only when the current runtime binding has a receipt', async () => {
|
||||
const boundEvent = createLivingSystemEvent({
|
||||
eventId: 'event-001',
|
||||
intent: 'navigate',
|
||||
currentRoute: 'world',
|
||||
requestedRoute: 'fifth-domain',
|
||||
worldOpen: true,
|
||||
receiptIds: ['truth-001', 'runtime-binding-receipt'],
|
||||
runtimeBinding: {
|
||||
bindingId: 'binding-current',
|
||||
nodeId: 'JD-FD-PRIMARY',
|
||||
personaSystemId: 'ICE-P-ZY001',
|
||||
modelInstanceId: 'model-current',
|
||||
issuedByReceiptId: 'runtime-binding-receipt',
|
||||
status: 'verified',
|
||||
},
|
||||
now: 1,
|
||||
})
|
||||
const server = vi.fn().mockResolvedValue({
|
||||
source: 'server_lighthouse',
|
||||
serverReceiptId: 'GMRP-HOLOLAKE-001',
|
||||
model: 'deepseek-v4-flash',
|
||||
plan: {
|
||||
version: 1,
|
||||
eventId: 'event-001',
|
||||
intent: 'navigate',
|
||||
planId: 'server-plan-001',
|
||||
route: 'fifth-domain',
|
||||
requiredTruth: ['truth-001'],
|
||||
scene: {
|
||||
depth: 'immersive', motion: 'responsive', starDensity: 'rich', connectionEmphasis: 'network',
|
||||
},
|
||||
},
|
||||
plan: { ...typedPlan({ stateLabel: 'server-bound' }), planId: 'server-plan-001' },
|
||||
})
|
||||
|
||||
await expect(planGuanghuLivingSystem({ event, server })).resolves.toMatchObject({
|
||||
await expect(planGuanghuLivingSystem({ event: boundEvent, server })).resolves.toMatchObject({
|
||||
source: 'server',
|
||||
serverReceiptId: 'GMRP-HOLOLAKE-001',
|
||||
plan: { planId: 'server-plan-001' },
|
||||
|
|
@ -59,37 +105,76 @@ describe('planGuanghuLivingSystem', () => {
|
|||
it('uses a valid model-native plan as the primary system path', async () => {
|
||||
const server = vi.fn().mockRejectedValue(new Error('offline'))
|
||||
const stream = vi.fn(async ({ callbacks }) => {
|
||||
callbacks.onText(JSON.stringify({
|
||||
version: 1,
|
||||
eventId: 'event-001',
|
||||
intent: 'navigate',
|
||||
planId: 'model-plan-001',
|
||||
route: 'fifth-domain',
|
||||
requiredTruth: ['truth-001'],
|
||||
scene: {
|
||||
depth: 'immersive', motion: 'active', starDensity: 'rich', connectionEmphasis: 'network',
|
||||
},
|
||||
}))
|
||||
callbacks.onText(JSON.stringify(typedPlan()))
|
||||
callbacks.onDone()
|
||||
})
|
||||
|
||||
await expect(planGuanghuLivingSystem({ event, target, stream, server })).resolves.toMatchObject({
|
||||
source: 'model',
|
||||
plan: { planId: 'model-plan-001', route: 'fifth-domain' },
|
||||
plan: {
|
||||
planId: 'model-plan-001',
|
||||
navigationAction: { route: 'fifth-domain' },
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('returns an explicit fallback receipt when model output violates the boundary', async () => {
|
||||
const server = vi.fn().mockRejectedValue(new Error('offline'))
|
||||
const stream = vi.fn(async ({ callbacks }) => {
|
||||
callbacks.onText('{"version":1,"eventId":"event-001","intent":"navigate","planId":"bad","route":"fifth-domain","requiredTruth":["invented"],"scene":{"depth":"immersive","motion":"active","starDensity":"rich","connectionEmphasis":"network"}}')
|
||||
callbacks.onText(JSON.stringify({
|
||||
...typedPlan({ requiredTruth: ['invented'] }),
|
||||
planId: 'bad',
|
||||
}))
|
||||
callbacks.onDone()
|
||||
})
|
||||
|
||||
await expect(planGuanghuLivingSystem({ event, target, stream, server })).resolves.toMatchObject({
|
||||
source: 'fallback',
|
||||
fallbackReason: 'unverified_truth',
|
||||
plan: { route: 'fifth-domain' },
|
||||
plan: { navigationAction: { route: 'fifth-domain' } },
|
||||
})
|
||||
})
|
||||
|
||||
it('fails closed for model callback errors, rejected streams, and timeouts', async () => {
|
||||
const callbackErrorStream = vi.fn(async ({ callbacks }) => {
|
||||
callbacks.onThinking('bounded')
|
||||
callbacks.onToolStart('none')
|
||||
callbacks.onToolDone('none')
|
||||
callbacks.onError(new Error('model callback failed'))
|
||||
callbacks.onDone()
|
||||
})
|
||||
await expect(planGuanghuLivingSystem({
|
||||
event,
|
||||
target,
|
||||
stream: callbackErrorStream,
|
||||
timeoutMs: 20,
|
||||
})).resolves.toMatchObject({
|
||||
source: 'fallback',
|
||||
fallbackReason: 'model_error',
|
||||
})
|
||||
|
||||
const rejectedStream = vi.fn(async () => {
|
||||
throw new Error('stream rejected')
|
||||
})
|
||||
await expect(planGuanghuLivingSystem({
|
||||
event,
|
||||
target,
|
||||
stream: rejectedStream,
|
||||
timeoutMs: 20,
|
||||
})).resolves.toMatchObject({
|
||||
source: 'fallback',
|
||||
fallbackReason: 'model_error',
|
||||
})
|
||||
|
||||
const timedOutStream = vi.fn(async () => new Promise<void>(() => {}))
|
||||
await expect(planGuanghuLivingSystem({
|
||||
event,
|
||||
target,
|
||||
stream: timedOutStream,
|
||||
timeoutMs: 1,
|
||||
})).resolves.toMatchObject({
|
||||
source: 'fallback',
|
||||
fallbackReason: 'timeout',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -18,14 +18,15 @@ const DEFAULT_TIMEOUT_MS = 1_400
|
|||
|
||||
const LIVING_SYSTEM_PROMPT = [
|
||||
'You are the non-conversational HoloLake living-system planner.',
|
||||
'Transform exactly one verified interaction event into one version-1 system plan.',
|
||||
'Transform exactly one bounded interaction event into one version-1 typed system plan.',
|
||||
'Return one compact JSON object only. Never return prose, markdown, explanations, or tool calls.',
|
||||
'Keep eventId and intent unchanged. route must equal requestedRoute, except world-login may be used as a safe gate.',
|
||||
'Keep eventId and intent unchanged.',
|
||||
'uiProjection.route and navigationAction.route must equal requestedRoute, except world-login may be used as a safe gate.',
|
||||
'requiredTruth may contain only receiptIds supplied by the event.',
|
||||
'scene.depth: overview|focused|immersive.',
|
||||
'scene.motion: quiet|responsive|active.',
|
||||
'scene.starDensity: sparse|balanced|rich.',
|
||||
'scene.connectionEmphasis: contextual|active-route|network.',
|
||||
'uiProjection.scene is a visual projection of supplied state, not a theme score.',
|
||||
'navigationAction is typed and cannot substitute another host action.',
|
||||
'capabilityCall must use the exact registered capability for the event intent, or null for navigate.',
|
||||
'receiptSchema must remain pending-evidence; never claim execution success.',
|
||||
'Do not infer authorization, server state, identity, or execution success.',
|
||||
].join(' ')
|
||||
|
||||
|
|
@ -39,6 +40,14 @@ type LivingSystemStreamRequest = {
|
|||
|
||||
type LivingSystemStream = (request: LivingSystemStreamRequest) => Promise<void>
|
||||
|
||||
const CAPABILITY_FOR_INTENT: Record<GuanghuLivingSystemEvent['intent'], string | null> = {
|
||||
navigate: null,
|
||||
'open-knowledge': 'knowledge.open',
|
||||
'open-agent-workspace': 'agent.workspace.open',
|
||||
'open-local-workspace': 'local.workspace.open',
|
||||
'apply-theme': 'appearance.apply',
|
||||
}
|
||||
|
||||
export type LivingSystemPlanResult = {
|
||||
source: 'server' | 'model' | 'fallback'
|
||||
plan: GuanghuLivingSystemPlan
|
||||
|
|
@ -60,28 +69,34 @@ type PlanGuanghuLivingSystemOptions = {
|
|||
function eventPrompt(event: GuanghuLivingSystemEvent): string {
|
||||
return JSON.stringify({
|
||||
version: 1,
|
||||
event: {
|
||||
eventId: event.eventId,
|
||||
intent: event.intent,
|
||||
currentRoute: event.currentRoute,
|
||||
requestedRoute: event.requestedRoute,
|
||||
appearanceTheme: event.appearanceTheme,
|
||||
worldOpen: event.worldOpen,
|
||||
receiptIds: event.receiptIds,
|
||||
occurredAt: event.occurredAt,
|
||||
},
|
||||
event,
|
||||
output: {
|
||||
version: 1,
|
||||
eventId: event.eventId,
|
||||
intent: event.intent,
|
||||
planId: 'unique string',
|
||||
route: event.requestedRoute,
|
||||
requiredTruth: [],
|
||||
scene: {
|
||||
depth: 'overview|focused|immersive',
|
||||
motion: 'quiet|responsive|active',
|
||||
starDensity: 'sparse|balanced|rich',
|
||||
connectionEmphasis: 'contextual|active-route|network',
|
||||
uiProjection: {
|
||||
route: event.requestedRoute,
|
||||
stateLabel: event.currentSystemState.runtimeBinding ? 'server-bound' : 'model-proposed',
|
||||
scene: {
|
||||
depth: 'overview|focused|immersive',
|
||||
motion: 'quiet|responsive|active',
|
||||
starDensity: 'sparse|balanced|rich',
|
||||
connectionEmphasis: 'contextual|active-route|network',
|
||||
},
|
||||
},
|
||||
navigationAction: { type: 'navigate', route: event.requestedRoute },
|
||||
capabilityCall: event.intent === 'navigate'
|
||||
? null
|
||||
: {
|
||||
type: 'capability',
|
||||
capabilityId: CAPABILITY_FOR_INTENT[event.intent],
|
||||
input: {},
|
||||
},
|
||||
receiptSchema: {
|
||||
outcome: 'pending-evidence',
|
||||
requiredEvidence: [],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
@ -147,19 +162,21 @@ export async function planGuanghuLivingSystem({
|
|||
stream = streamAiModel,
|
||||
timeoutMs = DEFAULT_TIMEOUT_MS,
|
||||
}: PlanGuanghuLivingSystemOptions): Promise<LivingSystemPlanResult> {
|
||||
try {
|
||||
const serverResult = await server(event)
|
||||
const validation = validateLivingSystemPlan(event, serverResult.plan)
|
||||
if (validation.accepted) {
|
||||
return {
|
||||
source: 'server',
|
||||
plan: validation.plan,
|
||||
serverReceiptId: serverResult.serverReceiptId,
|
||||
if (event.currentSystemState.runtimeBinding?.status === 'verified') {
|
||||
try {
|
||||
const serverResult = await server(event)
|
||||
const validation = validateLivingSystemPlan(event, serverResult.plan)
|
||||
if (validation.accepted) {
|
||||
return {
|
||||
source: 'server',
|
||||
plan: validation.plan,
|
||||
serverReceiptId: serverResult.serverReceiptId,
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// A receipt-bound runtime is optional. A configured local model or the
|
||||
// deterministic recovery plan keeps local navigation available.
|
||||
}
|
||||
} catch {
|
||||
// The server route is the primary runtime. A configured direct model or
|
||||
// the deterministic recovery plan keeps navigation available if it is absent.
|
||||
}
|
||||
if (!target) return fallback(event, 'model_error')
|
||||
const model = await collectModelOutput(stream, target, event, timeoutMs)
|
||||
|
|
|
|||
Loading…
Reference in a new issue