var test = require("node:test");
var assert = require("node:assert/strict");
var fs = require("node:fs");
var path = require("node:path");
var pathToFileURL = require("node:url").pathToFileURL;
var root = path.join(__dirname, "..");
var indexSource = fs.readFileSync(path.join(root, "lib/public/index.html"), "utf8");
var appSource = fs.readFileSync(path.join(root, "lib/public/app.js"), "utf8");
var dockSource = fs.readFileSync(path.join(root, "lib/public/modules/home-dock.js"), "utf8");
var resizeSource = fs.readFileSync(path.join(root, "lib/public/modules/home-dock-resize.js"), "utf8");
var sidebarSource = fs.readFileSync(path.join(root, "lib/public/modules/home-sidebar.js"), "utf8");
var librarySource = fs.readFileSync(path.join(root, "lib/public/modules/home-capsule-library.js"), "utf8");
var creationIntentSource = fs.readFileSync(path.join(root, "lib/public/modules/home-capsule-creation-intent.js"), "utf8");
var toolsSource = fs.readFileSync(path.join(root, "lib/public/modules/home-tools.js"), "utf8");
var chatSource = fs.readFileSync(path.join(root, "lib/public/modules/home-mate-chat.js"), "utf8");
var cssSource = fs.readFileSync(path.join(root, "lib/public/css/home-capsule-library.css"), "utf8");
var homeMarkup = indexSource.slice(indexSource.indexOf('
[\s\S]*id="home-tool-workbench"/);
assert.match(indexSource, /id="home-dock-switcher"[\s\S]*id="home-dock-content"/);
assert.doesNotMatch(appSource, /initHomeDock\(/);
assert.match(appSource, /function showHomeHub\(fromHistory\) \{ showProjectsHub\(fromHistory\); \}/);
assert.match(dockSource, /export function openHomeCapsules\(\)/);
});
test("Capsules resumes the last installed Capsule or opens Library without a fake persisted tool", function () {
assert.match(dockSource, /export function openHomeCapsules\(\)/);
assert.match(dockSource, /lastActiveId && toolsById\[lastActiveId\][\s\S]*openHomeDock\(lastActiveId\)/);
assert.match(dockSource, /openHomeCapsuleLibrary\(\)/);
assert.match(dockSource, /dockActiveToolId: null,[\s\S]*dockLibraryOpen: true/);
assert.match(dockSource, /activeToolId: store\.get\('dockActiveToolId'\) \|\| null/);
assert.doesNotMatch(dockSource, /activeToolId: ["']library["']/);
assert.match(appSource, /dockActiveToolId: null/);
assert.match(dockSource, /store\.get\('dockActiveToolId'\) === toolId[\s\S]*dockActiveToolId: null,[\s\S]*persistDock\(\)/);
});
test("complete registry sync clears a stale persisted Capsule and opens Library when needed", function () {
assert.match(appSource, /homeToolRegistryLoaded: false/);
assert.match(toolsSource, /var completeSync = !msg\.requestedToolId/);
assert.match(toolsSource, /if \(completeSync\) \{[\s\S]*previousIds/);
assert.match(toolsSource, /if \(completeSync\) store\.set\(\{ homeToolRegistryLoaded: true \}\)/);
assert.match(toolsSource, /if \(completeSync && reconcileDockActiveTool\(\)\) return;/);
assert.match(dockSource, /export function reconcileDockActiveTool\(\)/);
assert.match(dockSource, /if \(!activeToolId \|\| toolsById\[activeToolId\]\) return false/);
assert.match(dockSource, /dockActiveToolId: null,[\s\S]*dockLibraryOpen: store\.get\('dockOpen'\) === true/);
assert.match(dockSource, /renderDock\(\);[\s\S]*persistDock\(\);[\s\S]*return true/);
});
test("valid saved Capsule IDs and incremental tool responses bypass reconciliation", function () {
assert.match(dockSource, /toolsById\[activeToolId\]\) return false/);
assert.match(toolsSource, /var completeSync = !msg\.requestedToolId/);
assert.doesNotMatch(toolsSource, /if \(msg\.requestedToolId && reconcileDockActiveTool/);
assert.match(toolsSource, /if \(completeSync && reconcileDockActiveTool\(\)\) return;[\s\S]*renderDock\(\)/);
});
test("dock preference arriving after registry load reconciles its saved Capsule", function () {
assert.match(dockSource, /export function handleHomeDockState\(msg\)[\s\S]*dockActiveToolId: saved\.activeToolId \|\| null/);
assert.match(dockSource, /syncDockState\(\);[\s\S]*store\.get\('homeToolRegistryLoaded'\) && reconcileDockActiveTool\(\)/);
assert.match(dockSource, /reconcileDockActiveTool\(\)\) return;[\s\S]*renderDock\(\)/);
});
test("dock preference does not reconcile against an incomplete registry", function () {
assert.match(appSource, /homeToolRegistryLoaded: false/);
assert.match(toolsSource, /export function requestTools\(\)[\s\S]*store\.set\(\{ homeToolRegistryLoaded: false \}\)[\s\S]*type: "tools_list"/);
assert.match(dockSource, /if \(store\.get\('homeToolRegistryLoaded'\) && reconcileDockActiveTool\(\)\) return;/);
assert.doesNotMatch(dockSource, /if \(!store\.get\('homeToolRegistryLoaded'\)\) reconcileDockActiveTool/);
assert.match(toolsSource, /if \(completeSync\) store\.set\(\{ homeToolRegistryLoaded: true \}\)/);
});
test("Capsule Library is a native host surface over shared installed-tool state", function () {
assert.match(dockSource, /renderHomeCapsuleLibrary\(contentEl, store\.get\('installedTools'\) \|\| \[\], openLibraryCapsule\)/);
assert.match(toolsSource, /store\.set\(\{ installedTools: tools \}\)/);
assert.match(librarySource, /definition\.manifest/);
assert.match(librarySource, /document\.createElement\("ul"\)/);
assert.match(librarySource, /row\.addEventListener\("click", function \(\) \{ openCapsule\(manifest\.id\); \}\)/);
assert.doesNotMatch(librarySource, /tool_install|tool_remove|uninstall|localStorage|alert\(|confirm\(|prompt\(/);
});
test("Capsule Home is the permanent leftmost Workbench tab", function () {
assert.match(dockSource, /appendCapsuleHomeTab\(switcherEl, libraryOpen && !backstageOpen\);[\s\S]*for \(var i = 0; i < tools\.length; i\+\+\)/);
assert.match(dockSource, /tab\.dataset\.dockHome = "true"/);
assert.match(dockSource, /tab\.setAttribute\("aria-label", "Capsule Home"\)/);
assert.match(dockSource, /renderToolIdentity\(\{ name: "Home", lucideIcon: "house" \}\)/);
assert.match(dockSource, /tab\.addEventListener\("click", openHomeCapsuleLibrary\)/);
assert.match(librarySource, /title\.textContent = "Capsule Home"/);
assert.doesNotMatch(dockSource, /tools\.unshift|registerDockTool\([^)]*home/i);
});
test("Capsule Library starts with a Mate conversation composer in empty and populated states", function () {
assert.match(librarySource, /definitionTitle\.textContent = "What is a Capsule\?"/);
assert.match(librarySource, /A Capsule is a small, persistent app that a Mate creates with you/);
assert.match(librarySource, /keeps its interface and data beyond the conversation/);
assert.match(librarySource, /label\.textContent = "Create with Mate"/);
assert.match(librarySource, /Your current Mate will open a new conversation and shape it with you/);
assert.match(librarySource, /input\.placeholder = "Describe the interface you need"/);
assert.match(librarySource, /root\.appendChild\(createComposer\(\)\)[\s\S]*if \(!capsules\.length\) \{ container\.appendChild\(root\); return; \}/);
assert.match(librarySource, /inventoryTitle\.textContent = "Installed Capsules"/);
assert.doesNotMatch(librarySource, /No Capsules are installed|example prompt|localStorage/);
assert.match(librarySource, /event\.isComposing/);
assert.match(cssSource, /\.home-capsule-library-definition[\s\S]*\.home-capsule-library-create-guidance[\s\S]*\.home-capsule-library-inventory/);
});
test("Capsule creation targets only the currently open visible Mate", function () {
assert.match(creationIntentSource, /findHomeMate\(visible, currentMateId\)/);
assert.match(creationIntentSource, /homeSurfaceLoaded/);
assert.match(creationIntentSource, /homeChatMateId/);
assert.match(creationIntentSource, /HOME_CAPSULE_CREATION_EVENT/);
assert.doesNotMatch(creationIntentSource, /homePreferredMateId|resolveHomeMate|builtinKey === "clay"|keyword|locale|localStorage/);
});
test("Capsule creation never falls back from the currently open Mate", async function () {
var module = await import(pathToFileURL(path.join(root, "lib/public/modules/home-capsule-creation-intent.js")).href);
var mates = [
{ id: "mate-current", archived: false },
{ id: "mate-preferred", archived: false, builtinKey: "clay" },
];
assert.equal(module.resolveCapsuleCreationMate(mates, "mate-current"), mates[0]);
assert.equal(module.resolveCapsuleCreationMate(mates, "mate-missing"), null);
mates[0].archived = true;
assert.equal(module.resolveCapsuleCreationMate(mates, "mate-current"), null);
});
test("Capsule creation hands off through an exact fresh Home conversation", function () {
var capsuleStart = chatSource.slice(chatSource.indexOf("export function startHomeCapsuleCreation"), chatSource.indexOf("function bindComposer"));
assert.match(capsuleStart, /export function startHomeCapsuleCreation\(mateId, description\)/);
assert.match(capsuleStart, /mateId !== store\.get\('homeChatMateId'\)/);
assert.match(capsuleStart, /type: "home_mate_new_session"[\s\S]*mateId: mateId[\s\S]*type: "capsule_creation", description: description/);
assert.match(capsuleStart, /rememberHomeMate\(mateId\)/);
assert.doesNotMatch(capsuleStart, /store\.set\(\{ homeChatMateId: mateId \}\)/);
assert.doesNotMatch(creationIntentSource + chatSource, /tool_install|tool_update|clay_tool_install|clay_tool_update/);
});
test("Library selection opens the real registered Capsule and keeps dock tabs", function () {
assert.match(dockSource, /function openLibraryCapsule\(toolId\)[\s\S]*activateTool\(toolId\)[\s\S]*focusActiveCapsuleTab\(\)/);
assert.match(dockSource, /for \(var i = 0; i < tools\.length; i\+\+\)[\s\S]*dataset\.dockToolId = tool\.id/);
assert.match(dockSource, /tab\.addEventListener\("click", function \(\) \{ activateTool\(tool\.id\); \}\)/);
assert.match(dockSource, /dockLibraryOpen: false/);
});
test("retained Capsule activity state stays reusable without a visible Home trigger", function () {
assert.doesNotMatch(indexSource, /id="home-tools-activity"|id="home-tools-label"/);
assert.match(dockSource, /dockHasActivity: true, dockActivityToolId: toolId \|\| null/);
assert.match(dockSource, /dockHasActivity: false/);
assert.doesNotMatch(appSource, /initHomeDock\(/);
});
test("Stage 7 preserves Workbench controls, runtime, and durable dock preference", function () {
assert.match(dockSource, /initHomeDockResize\(\)/);
assert.match(dockSource, /home-dock-collapse/);
assert.match(dockSource, /home-dock-focus/);
assert.match(dockSource, /home-dock-return/);
assert.match(resizeSource, /home_dock_set|clay:home-dock-width-commit/);
assert.match(toolsSource, /createToolRuntime/);
assert.match(toolsSource, /handleToolStorageResult/);
assert.match(dockSource, /dockOpen: store\.get\('dockOpen'\) === true,[\s\S]*dockWidth: store\.get\('dockWidth'\),[\s\S]*activeToolId:/);
});
test("Capsule Library is responsive and moves focus into visible Workbench content", function () {
assert.match(librarySource, /aria-labelledby", "home-capsule-library-title"/);
assert.match(librarySource, /title\.tabIndex = -1/);
assert.match(librarySource, /row\.setAttribute\("aria-label", "Open " \+ \(manifest\.name \|\| manifest\.id\) \+ " Capsule"\)/);
assert.match(dockSource, /home-capsule-library-title[\s\S]*title\.focus\(\)/);
assert.match(dockSource, /home-dock-switcher \.home-dock-tool\.active[\s\S]*activeTab\.focus\(\)/);
assert.match(cssSource, /@media \(max-width: 768px\)/);
assert.match(dockSource, /export function toggleHomeCapsules\(\)[\s\S]*if \(store\.get\('dockOpen'\)\) closeHomeDock\(\);[\s\S]*else openHomeCapsules\(\)/);
assert.match(sidebarSource, /closeNarrowDrawer\(!opening\)/);
});