Important Fixes, New mechanics, and many more
Some checks failed
CI / validate (push) Failing after 9m21s

This commit is contained in:
2026-08-15 17:37:57 +05:00
parent 1774496cf9
commit 438e5af0ad
56 changed files with 5090 additions and 119 deletions

View File

@@ -0,0 +1,56 @@
import { describe, expect, it } from 'vitest'
import type { Character, PlayerIntent, RoundPlan } from '@dng/shared'
import { buildActionSequence, 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,
abilities: { str: 10, dex: 10, con: 10, int: 10, wis: 10, cha: 10 },
hp: 10, maxHp: 10, defense: 10, proficiency: 2, inventory: [], statuses: [], persona: {},
})
const intent = (id: string, characterId: string, createdAt: string): PlayerIntent => ({
id, roundId: 'round', memberId: id, characterId, action: `Action ${id}`, ready: true, createdAt, updatedAt: createdAt,
})
describe('round orchestration', () => {
it('keeps a minimal context and orders humans before AI/delegated heroes', () => {
const context = buildRoundContext({
scene: 'Current scene', storySummary: 'Story so far',
recentRounds: [1, 2, 3].map(number => ({ number, narration: `Round ${number}` })),
intents: [intent('late', 'human', '2026-01-01T00:00:02.000Z'), intent('early', 'human', '2026-01-01T00:00:01.000Z')],
characters: [character('human', 'human'), character('companion', 'ai'), character('stand-in', 'delegated')],
memories: Array.from({ length: 10 }, (_, index) => ({ summary: `Memory ${index}`, importance: (index % 5) + 1 })),
})
const plan: RoundPlan = { checks: [], proposedEvents: [], relevantMemoryQueries: [], aiActions: [
{ characterId: 'stand-in', action: 'Covers the retreat' },
{ characterId: 'human', action: 'Illegally overrides the player' },
{ characterId: 'companion', action: 'Scouts ahead' },
] }
const validated = validateAndOrderRoundPlan(plan, context)
expect(context.recentRounds.map(round => round.number)).toEqual([2, 3])
expect(context.memories).toHaveLength(8)
expect(validated.aiActions.map(action => action.characterId)).toEqual(['companion', 'stand-in'])
expect(buildActionSequence(context, validated).map(action => action.phase)).toEqual(['human', 'human', 'ai', 'ai'])
})
it('rejects mechanical references outside the active campaign', () => {
const context = buildRoundContext({ scene: 'Scene', recentRounds: [], intents: [], characters: [character('hero', 'human')], memories: [] })
expect(() => validateAndOrderRoundPlan({
checks: [{ actorId: 'outsider', kind: 'ability', mode: 'normal', reason: 'Invalid' }],
aiActions: [], proposedEvents: [], relevantMemoryQueries: [],
}, context)).toThrow('Unknown check actor outsider')
})
it('schedules durable story summaries every third completed round', () => {
expect([1, 2, 3, 4, 5, 6].filter(shouldUpdateStorySummary)).toEqual([3, 6])
})
it('drops model-authored memory labels that PostgreSQL cannot cast to uuid[]', () => {
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'])
})
})