const assert = require("assert"); const fs = require("fs"); const path = require("path"); const root = path.join(__dirname, ".."); const read = (file) => fs.readFileSync(path.join(root, file), "utf8"); const interactions = read("src/web/public/lumi-interactions.js"); const request = read("src/web/public/lumi-request.js"); const pages = read("src/web/public/lumi-page.js"); const dialogs = read("src/web/public/lumi-dialog.js"); const app = read("src/web/public/app.js"); const overlay = read("src/web/public/overlay-management.js"); const overlayCss = read("src/web/public/overlay-management.css"); const overlayPreviewWindow = read("src/web/public/overlay-preview-window.js"); const overlayRoute = read("src/services/overlay-routes.js"); const layout = read("src/web/views/partials/layout-top.ejs"); const tokens = read("src/web/public/lumi-tokens.css"); const legacy = read("src/web/public/styles.css"); const navigationTemplate = read("src/web/views/admin-navigation.ejs"); const navigationClient = read("src/web/public/navigation-builder.js"); const server = read("src/web/server.js"); const themeTemplate = read("src/web/views/admin-theme.ejs"); const themeClient = read("src/web/public/theme-editor.js"); const aiTemplate = read("plugins/lumi_ai/views/settings.ejs"); const aiClient = read("plugins/lumi_ai/public/settings.js"); const aiServer = read("plugins/lumi_ai/index.js"); const commandTemplate = read("src/web/views/admin-commands.ejs"); const commandClient = read("src/web/public/command-management.js"); const policyTemplate = read("src/web/views/admin-command-policies.ejs"); const policyClient = read("src/web/public/command-policies.js"); const updateTemplate = read("src/web/views/admin-updates.ejs"); const updateClient = read("src/web/public/update-management.js"); assert(interactions.includes("window.LumiRequest.form(form)"), "settings saves must use the shared request contract"); assert(!interactions.includes("Saved. Reloading"), "ordinary settings saves must not announce an implicit reload"); assert(!interactions.includes("executePageScripts"), "soft navigation must not re-execute arbitrary page scripts"); assert(interactions.includes('a[data-lumi-soft-nav][href]'), "soft navigation must be explicit while routes migrate"); assert(interactions.includes("window.LumiEvents") && interactions.includes('window.addEventListener("beforeunload", closeEvents)'), "shared live events must release their connection before full navigation"); assert(!app.includes('new EventSource("/admin/updates/events")') || app.includes("window.LumiEvents?.subscribe"), "updates must prefer the shared event stream"); assert(request.includes('"X-Lumi-Enhanced": "1"') && request.includes("reloadRequired")); assert(request.includes('getAttribute?.("formaction")') && !request.includes("submitter?.formAction"), "enhanced requests must use authored form actions"); assert(pages.includes("controller.abort()") && pages.includes("teardown")); assert(dialogs.includes("restoreFocus") && dialogs.includes('event.key !== "Tab"') && dialogs.includes("inert")); assert(app.includes("page.inert = true") && app.includes("closeSidebar") && app.includes('event.key === "Escape"')); assert(layout.includes('id="lumi-sidebar"') && layout.includes('aria-controls="lumi-sidebar"')); assert(!overlay.includes("--overlay-settings-max-height"), "overlay height must not be calculated from viewport geometry"); assert(!overlay.includes("scrollIntoView"), "scene/source selection must not force viewport movement"); assert(!overlay.includes("window.location.reload"), "normal overlay actions must not reload the document"); assert(overlay.includes("window.clearInterval(obsStatusTimer)"), "overlay polling must be lifecycle-owned"); assert(!overlayCss.includes("--overlay-settings-max-height")); assert(/@media \(min-width: 1180px\)[\s\S]*\.overlay-settings-column\s*\{[^}]*overflow-y:\s*auto/s.test(overlayCss), "desktop overlay settings need a bounded workspace scroller"); assert(!/\.overlay-preview-panel\s*\{[^}]*overflow:\s*auto/s.test(overlayCss), "the sticky preview cannot become a nested main scroller"); assert(overlayCss.includes(".overlay-preview-panel.is-open") && overlayCss.includes("position: fixed"), "thin overlay layouts need a viewport-contained edge drawer"); assert(overlay.includes("editorRoot.inert = !open") && overlay.includes("restoreFocus"), "the preview drawer must hide closed controls and restore focus"); assert(overlay.includes("BroadcastChannel") && overlay.includes("dataset.previewPopoutUrl"), "the editor must synchronize its desktop pop-out preview"); assert(overlayPreviewWindow.includes("Math.min(previewViewport.clientWidth / width, previewViewport.clientHeight / height)"), "the pop-out must preserve the canvas aspect ratio"); assert(overlayPreviewWindow.includes("editor: true") && overlayPreviewWindow.includes("/transform") && overlayPreviewWindow.includes('type: "transform"'), "the pop-out must support synchronized transform editing"); assert(overlayRoute.includes('app.get("/admin/overlays/:id/preview-window", requireOverlayAccess(OVERLAY_CAPABILITIES.MANAGE)'), "the pop-out must remain behind overlay management access"); assert(tokens.includes("@layer reset, tokens, base, layout, components, utilities, features, overrides")); assert(!legacy.includes("fonts.googleapis.com"), "core CSS cannot depend on remote Google Fonts"); assert(!navigationTemplate.includes("