// Verify the agent memory vault round-trips: signed-in user tells the // Assistant a fact, then asks the Assistant to recall it. Second persona // in same tenant must NOT see the first persona's notes (isolation check // is tenant-scoped not user-scoped since the vault key is per-user). import { chromium } from "playwright"; const URL = "https://canvas.flow-master.ai/"; const args = ["--host-resolver-rules=MAP canvas.flow-master.ai 65.21.71.186", "--ignore-certificate-errors"]; const b = await chromium.launch({ headless: true, args }); async function asPersona(personaText, work) { const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } }); const p = await ctx.newPage(); await p.goto(URL, { waitUntil: "networkidle" }); await p.waitForTimeout(800); await p.locator(".persona-chip", { hasText: personaText }).click(); await p.locator(".dev-login-btn").click(); await p.waitForTimeout(2500); const enter = p.locator("button", { hasText: /Enter Mission Control/i }).first(); if (await enter.count()) { await enter.click(); await p.waitForTimeout(1200); } await p.locator(".tab", { hasText: /^\s*Assistant\s*$/ }).click(); await p.waitForTimeout(1500); const result = await work(p); await ctx.close(); return result; } async function ask(p, text) { const before = await p.locator(".agent-turn-agent .agent-turn-body").count(); await p.locator(".agent-composer textarea").fill(text); await p.locator(".agent-composer button", { hasText: /Send/i }).click(); await p.waitForFunction((n) => document.querySelectorAll(".agent-turn-agent .agent-turn-body").length > n, before, { timeout: 8000 }).catch(() => {}); await p.waitForTimeout(600); return (await p.locator(".agent-turn-agent .agent-turn-body").last().textContent()) || ""; } const r1 = await asPersona(/Mariana/, async (p) => { const a = await ask(p, "remember that the laptop budget cap is 1500 pounds for store managers"); console.log("[CEO remember]:", a.slice(0, 120)); await p.waitForTimeout(2000); const b = await ask(p, "recall about laptop budget"); console.log("[CEO recall]:", b.slice(0, 200)); return { remember: a, recall: b }; }); const r2 = await asPersona(/Aisha/, async (p) => { const a = await ask(p, "recall about laptop budget"); console.log("[HR recall]:", a.slice(0, 200)); return { recall: a }; }); console.log(); console.log("CEO remembered:", r1.remember.includes("I'll remember") ? "YES" : "NO"); console.log("CEO recalled own note:", r1.recall.includes("1500") || r1.recall.includes("laptop") ? "YES" : "NO"); console.log("HR vault isolated from CEO:", !r2.recall.includes("1500") ? "YES" : "NO (leak)"); await b.close();