feat(memory): implement stability stage
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { Character, PlayerIntent, RoundPlan } from '@dng/shared'
|
||||
import { buildActionSequence, buildRoundContext, sanitizeRoundMemory, shouldUpdateStorySummary, validateAndOrderRoundPlan } from './orchestration'
|
||||
import { buildActionSequence, buildRetrievalText, buildRoundContext, sanitizeRoundMemory, shouldUpdateStorySummary, validateAndOrderRoundPlan } from './orchestration'
|
||||
|
||||
const character = (id: string, controller: Character['controller']): Character => ({
|
||||
id, controller, name: id, concept: 'A campaign hero', userId: controller === 'human' ? 'user' : null,
|
||||
@@ -61,11 +61,44 @@ describe('round orchestration', () => {
|
||||
})
|
||||
|
||||
it('drops model-authored memory labels that PostgreSQL cannot cast to uuid[]', () => {
|
||||
const knownId = '9ea0ef06-34bf-4cf3-8f2f-af1a65180d0e'
|
||||
expect(sanitizeRoundMemory({
|
||||
summary: 'The party learned who controls the gate.',
|
||||
importance: 4,
|
||||
tags: ['gate'],
|
||||
entityIds: ['the-gatekeeper', '9ea0ef06-34bf-4cf3-8f2f-af1a65180d0e', '9ea0ef06-34bf-4cf3-8f2f-af1a65180d0e'],
|
||||
})?.entityIds).toEqual(['9ea0ef06-34bf-4cf3-8f2f-af1a65180d0e'])
|
||||
entityIds: ['the-gatekeeper', knownId, knownId, '8ea0ef06-34bf-4cf3-8f2f-af1a65180d0e'],
|
||||
}, new Set([knownId]))?.entityIds).toEqual([knownId])
|
||||
})
|
||||
|
||||
it('builds a bounded retrieval query from only current-round context', () => {
|
||||
const text = buildRetrievalText({
|
||||
scene: 'The sealed moon gate is humming.',
|
||||
intents: [intent('ready', 'hero', '2026-01-01T00:00:00.000Z'), { ...intent('draft', 'hero', '2026-01-01T00:00:01.000Z'), ready: false }],
|
||||
characters: [character('hero', 'human')],
|
||||
})
|
||||
expect(text).toContain('sealed moon gate')
|
||||
expect(text).toContain('Action ready')
|
||||
expect(text).not.toContain('Action draft')
|
||||
})
|
||||
|
||||
it('accepts typed relationship, quest, and scene projections only for known entities', () => {
|
||||
const questId = '11111111-1111-4111-8111-111111111111'
|
||||
const locationId = '22222222-2222-4222-8222-222222222222'
|
||||
const context = buildRoundContext({
|
||||
scene: 'Scene', recentRounds: [], intents: [], characters: [character('hero', 'human')], memories: [],
|
||||
entities: [
|
||||
{ id: questId, kind: 'quest', name: 'Open the gate', summary: 'Find the key.', tags: ['gate'] },
|
||||
{ id: locationId, kind: 'location', name: 'Moon Gate', summary: 'A sealed arch.', tags: ['gate'] },
|
||||
],
|
||||
})
|
||||
const validated = validateAndOrderRoundPlan({
|
||||
checks: [], aiActions: [], relevantMemoryQueries: [],
|
||||
proposedEvents: [
|
||||
{ type: 'relationship', actorId: 'hero', targetId: questId, value: 3, item: null, damageType: null, description: 'The hero becomes invested.' },
|
||||
{ type: 'quest', actorId: 'hero', targetId: questId, value: null, item: 'active', damageType: null, description: 'The gate must be opened.' },
|
||||
{ type: 'narrative', actorId: null, targetId: locationId, value: null, item: 'scene', damageType: null, description: 'The party reaches the Moon Gate.' },
|
||||
],
|
||||
}, context)
|
||||
expect(validated.proposedEvents).toHaveLength(3)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user