diff --git a/content/demo/scenarios/talking-room.json b/content/demo/scenarios/talking-room.json new file mode 100644 index 0000000..f916e5c --- /dev/null +++ b/content/demo/scenarios/talking-room.json @@ -0,0 +1,148 @@ +{ + "id": "talking-room", + "name": "Talking Room", + "description": "A scientific experiment where two memory-wiped subjects are placed in a featureless white room to observe their interaction.", + "startTime": "2026-07-09T08:00:00.000Z", + "world": { + "attributes": [ + { + "name": "experiment_codename", + "value": "Project Tabula Rasa (Phase 3)", + "visibility": "PRIVATE", + "allowedEntities": [] + }, + { + "name": "observation_status", + "value": "Active monitoring. Audio and visual feeds online.", + "visibility": "PRIVATE", + "allowedEntities": [] + }, + { + "name": "ambient_sound", + "value": "A low, barely audible electrical hum.", + "visibility": "PUBLIC" + } + ] + }, + "locations": [ + { + "id": "white-room", + "parentId": null, + "attributes": [ + { + "name": "description", + "value": "A pristine, featureless room with white walls, ceiling, and floor. There are no visible doors, windows, seams, or vents.", + "visibility": "PUBLIC" + }, + { + "name": "lighting", + "value": "Bright, uniform illumination casting no shadows.", + "visibility": "PUBLIC" + } + ], + "connections": [] + } + ], + "entities": [ + { + "id": "subject-alpha", + "locationId": "white-room", + "attributes": [ + { + "name": "name", + "value": "Subject Alpha", + "visibility": "PUBLIC" + }, + { + "name": "appearance", + "value": "A tall human with short dark hair and alert eyes, standing near the center of the room.", + "visibility": "PUBLIC" + }, + { + "name": "clothing", + "value": "A clean, sterile grey jumpsuit with 'Alpha' embroidered in black lettering on the chest pocket.", + "visibility": "PUBLIC" + }, + { + "name": "knowledge", + "value": "I woke up here. I know my name is Alpha. I know I agreed to participate in a paid scientific experiment, but my memories of who I was or my life before this room are gone.", + "visibility": "PRIVATE", + "allowedEntities": ["subject-alpha"] + }, + { + "name": "neural_erasure_dose", + "value": "150mg Compound-TR9", + "visibility": "PRIVATE", + "allowedEntities": [] + } + ], + "aliases": { + "subject-beta": "the person in the Beta jumpsuit" + }, + "initialMemories": [ + { + "id": "alpha-wake", + "timestamp": "2026-07-09T07:58:00.000Z", + "locationId": "white-room", + "intent": { + "type": "action", + "originalText": "I woke up on the floor. I stood up and looked around the white room, realizing my memories were wiped.", + "description": "wake up on the cold floor and stand up", + "actorId": "subject-alpha", + "targetIds": [] + } + } + ] + }, + { + "id": "subject-beta", + "locationId": "white-room", + "attributes": [ + { + "name": "name", + "value": "Subject Beta", + "visibility": "PUBLIC" + }, + { + "name": "appearance", + "value": "A medium-build human with long blonde hair tied back, sitting with their back pressed against the white wall.", + "visibility": "PUBLIC" + }, + { + "name": "clothing", + "value": "A clean, sterile grey jumpsuit with 'Beta' embroidered in black lettering on the chest pocket.", + "visibility": "PUBLIC" + }, + { + "name": "knowledge", + "value": "I remember my name is Beta. I remember signing up for a paid research study. My past memories have been completely erased. I am disoriented.", + "visibility": "PRIVATE", + "allowedEntities": ["subject-beta"] + }, + { + "name": "neural_erasure_dose", + "value": "150mg Compound-TR9", + "visibility": "PRIVATE", + "allowedEntities": [] + } + ], + "aliases": { + "subject-alpha": "the person in the Alpha jumpsuit" + }, + "initialMemories": [ + { + "id": "beta-wake", + "timestamp": "2026-07-09T07:58:30.000Z", + "locationId": "white-room", + "intent": { + "type": "action", + "originalText": "I opened my eyes, sitting against the wall. I rubbed my temples, trying to remember how I got here.", + "description": "wake up sitting against the wall and rub temples", + "actorId": "subject-beta", + "targetIds": [] + } + } + ] + } + ] +} diff --git a/content/scenario-core/tests/talking-room.test.ts b/content/scenario-core/tests/talking-room.test.ts new file mode 100644 index 0000000..9cb1237 --- /dev/null +++ b/content/scenario-core/tests/talking-room.test.ts @@ -0,0 +1,88 @@ +import { describe, test, expect } from "vitest"; +import Database from "better-sqlite3"; +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; +import { SQLiteRepository } from "@omnia/core"; +import { Location } from "@omnia/spatial"; +import { BufferRepository } from "@omnia/memory"; +import { ScenarioLoader, ScenarioSchema } from "../src/index.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const SCENARIO_PATH = path.resolve(__dirname, "../../demo/scenarios/talking-room.json"); + +describe("Talking Room Demo Scenario Test (Tier 1)", () => { + test("talking-room.json exists, parses, and loads correctly into database", async () => { + // 1. Verify file exists + expect(fs.existsSync(SCENARIO_PATH)).toBe(true); + + // 2. Read and parse JSON + const rawJson = fs.readFileSync(SCENARIO_PATH, "utf-8"); + const scenarioJson = JSON.parse(rawJson); + const parsed = ScenarioSchema.safeParse(scenarioJson); + expect(parsed.success).toBe(true); + + // 3. Setup SQLite and loader + const db = new Database(":memory:"); + const coreRepo = new SQLiteRepository(db); + const bufferRepo = new BufferRepository(db); + const loader = new ScenarioLoader(coreRepo, bufferRepo); + + const worldInstanceId = "run-talking-room-1"; + await loader.initializeWorld(scenarioJson, worldInstanceId); + + // 4. Assert WorldState + const world = coreRepo.loadWorldState(worldInstanceId); + expect(world).not.toBeNull(); + expect(world!.attributes.get("name")?.getValue()).toBe("Talking Room"); + expect(world!.attributes.get("experiment_codename")?.getValue()).toBe("Project Tabula Rasa (Phase 3)"); + expect(world!.attributes.get("experiment_codename")?.visibility).toBe("PRIVATE"); + expect(world!.attributes.get("experiment_codename")?.getAllowedEntities()).toHaveLength(0); // System only! + + // 5. Assert location + const locations = coreRepo.listLocations(worldInstanceId, (id, parentId) => new Location(id, parentId)); + expect(locations).toHaveLength(1); + expect(locations[0].id).toBe("white-room"); + expect(locations[0].attributes.get("description")?.getValue()).toContain("A pristine, featureless room"); + + // 6. Assert entities and their private attributes / allowedEntities + const alpha = world!.getEntity("subject-alpha"); + expect(alpha).toBeDefined(); + expect(alpha!.locationId).toBe("white-room"); + expect(alpha!.attributes.get("name")?.getValue()).toBe("Subject Alpha"); + + // Check private knowledge attribute visibility + const alphaKnowledge = alpha!.attributes.get("knowledge")!; + expect(alphaKnowledge.visibility).toBe("PRIVATE"); + expect(alphaKnowledge.hasAccess("subject-alpha")).toBe(true); + expect(alphaKnowledge.hasAccess("subject-beta")).toBe(false); + + // Check system-only attribute (neural_erasure_dose) + const alphaDose = alpha!.attributes.get("neural_erasure_dose")!; + expect(alphaDose.visibility).toBe("PRIVATE"); + expect(alphaDose.hasAccess("subject-alpha")).toBe(false); + expect(alphaDose.hasAccess("subject-beta")).toBe(false); + + // Check subjective aliases + expect(alpha!.aliases.get("subject-beta")).toBe("the person in the Beta jumpsuit"); + + const beta = world!.getEntity("subject-beta"); + expect(beta).toBeDefined(); + expect(beta!.locationId).toBe("white-room"); + expect(beta!.aliases.get("subject-alpha")).toBe("the person in the Alpha jumpsuit"); + + // 7. Assert initial pre-seeded memories + const alphaMemories = bufferRepo.listForOwner("subject-alpha"); + expect(alphaMemories).toHaveLength(1); + expect(alphaMemories[0].id).toBe("alpha-wake"); + expect(alphaMemories[0].intent.description).toBe("wake up on the cold floor and stand up"); + + const betaMemories = bufferRepo.listForOwner("subject-beta"); + expect(betaMemories).toHaveLength(1); + expect(betaMemories[0].id).toBe("beta-wake"); + expect(betaMemories[0].intent.description).toBe("wake up sitting against the wall and rub temples"); + + db.close(); + }); +});