Files
tutti/tools/scripts/check-renderer-feature-boundaries.test.mjs
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

198 lines
7.6 KiB
JavaScript

import assert from "node:assert/strict";
import { mkdtemp, mkdir, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { spawnSync } from "node:child_process";
import test from "node:test";
const scriptPath = resolve(
dirname(fileURLToPath(import.meta.url)),
"check-renderer-feature-boundaries.mjs"
);
const rendererRoot = "apps/desktop/src/renderer/src";
test("allows a feature to import its own services/internal implementation", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-launcher/services/internal/secret.ts":
"export const secret = 1;\n",
"features/workspace-launcher/ui/WorkspaceLauncher.tsx":
'import { secret } from "../services/internal/secret";\nconsole.log(secret);\n'
});
const result = runBoundaryCheck(workspaceRoot);
assert.equal(result.status, 0, result.stderr || result.stdout);
assert.match(result.stdout, /renderer feature boundary check passed/);
});
test("rejects workspace workbench UI imports of its services/internal implementation", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-workbench/services/internal/workspaceLaunchpadModel.ts":
"export const model = 1;\n",
"features/workspace-workbench/ui/WorkspaceLaunchpadOverlay.tsx":
'import { model } from "../services/internal/workspaceLaunchpadModel";\nconsole.log(model);\n'
});
const result = runBoundaryCheck(workspaceRoot);
assert.notEqual(result.status, 0);
assert.match(result.stderr, /workspace-workbench-ui-internal-import/);
assert.match(result.stderr, /services\/internal/);
});
test("allows workspace workbench UI imports of public services", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-workbench/services/workspaceLaunchpadModel.ts":
"export const model = 1;\n",
"features/workspace-workbench/ui/WorkspaceLaunchpadOverlay.tsx":
'import { model } from "../services/workspaceLaunchpadModel";\nconsole.log(model);\n'
});
const result = runBoundaryCheck(workspaceRoot);
assert.equal(result.status, 0, result.stderr || result.stdout);
assert.match(result.stdout, /renderer feature boundary check passed/);
});
test("rejects cross-feature imports of services/internal implementation", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-launcher/services/internal/secret.ts":
"export const secret = 1;\n",
"features/workspace-overview/ui/WorkspaceOverview.tsx":
'import { secret } from "@renderer/features/workspace-launcher/services/internal/secret";\nconsole.log(secret);\n'
});
const result = runBoundaryCheck(workspaceRoot);
assert.notEqual(result.status, 0);
assert.match(result.stderr, /feature-internal-import/);
assert.match(result.stderr, /workspace-launcher\/services\/internal/);
});
test("rejects app-level relative imports of feature services/internal implementation", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-launcher/services/internal/secret.ts":
"export const secret = 1;\n",
"app/windows/dashboard/DashboardWindow.tsx":
'import { secret } from "../../../features/workspace-launcher/services/internal/secret";\nconsole.log(secret);\n'
});
const result = runBoundaryCheck(workspaceRoot);
assert.notEqual(result.status, 0);
assert.match(result.stderr, /feature-internal-import/);
});
test("allows window containers to read the preload API composition root", async () => {
const workspaceRoot = await createFixtureWorkspace({
"app/windows/dashboard/createDashboardWindowContainer.ts":
"registerDashboardServices(registry, window.tutti);\n"
});
const result = runBoundaryCheck(workspaceRoot);
assert.equal(result.status, 0, result.stderr || result.stdout);
assert.match(result.stdout, /renderer feature boundary check passed/);
});
test("rejects feature UI direct access to the preload API", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/app-update/ui/AppUpdateStatus.tsx":
"void window.tutti.update.getState();\n"
});
const result = runBoundaryCheck(workspaceRoot);
assert.notEqual(result.status, 0);
assert.match(result.stderr, /renderer-window-tutti-access/);
});
test("rejects feature service direct access to the preload API", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-launcher/services/internal/workspaceLauncherService.ts":
'void window.tutti.host.workspace.showWorkspace("workspace");\n'
});
const result = runBoundaryCheck(workspaceRoot);
assert.notEqual(result.status, 0);
assert.match(result.stderr, /renderer-window-tutti-access/);
});
test("rejects private Maps in workspace launch coordinators", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-workbench/services/workspaceExampleLaunchCoordinator.ts":
"const handlersByWorkspaceId = new Map<string, () => void>();\n"
});
const result = runBoundaryCheck(workspaceRoot);
assert.notEqual(result.status, 0);
assert.match(result.stderr, /workspace-launch-coordinator-private-map/);
assert.match(result.stderr, /WorkspaceScopedRegistrationRegistry/);
});
test("rejects private Maps in the workspace message center coordinator", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-workbench/services/workspaceMessageCenterCoordinator.ts":
"const handlersByWorkspaceId = new Map<string, () => void>();\n"
});
const result = runBoundaryCheck(workspaceRoot);
assert.notEqual(result.status, 0);
assert.match(result.stderr, /workspace-launch-coordinator-private-map/);
});
test("allows workspace launch coordinators to use the shared registration registry", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-workbench/services/internal/workspaceScopedRegistrationRegistry.ts":
"export class WorkspaceScopedRegistrationRegistry<T> {}\n",
"features/workspace-workbench/services/workspaceExampleLaunchCoordinator.ts":
'import { WorkspaceScopedRegistrationRegistry } from "./internal/workspaceScopedRegistrationRegistry";\nconst handlers = new WorkspaceScopedRegistrationRegistry<() => void>();\n'
});
const result = runBoundaryCheck(workspaceRoot);
assert.equal(result.status, 0, result.stderr || result.stdout);
assert.match(result.stdout, /renderer feature boundary check passed/);
});
test("allows non-launch coordinator Maps outside the Shell registration rule", async () => {
const workspaceRoot = await createFixtureWorkspace({
"features/workspace-workbench/services/workspaceAgentGuiOpenSessionCoordinator.ts":
"const refCountsByWorkspaceId = new Map<string, number>();\n"
});
const result = runBoundaryCheck(workspaceRoot);
assert.equal(result.status, 0, result.stderr || result.stdout);
});
async function createFixtureWorkspace(files) {
const workspaceRoot = await mkdtemp(
join(tmpdir(), "tutti-renderer-boundaries-")
);
for (const [path, content] of Object.entries(files)) {
const absolutePath = join(workspaceRoot, rendererRoot, path);
await mkdir(dirname(absolutePath), { recursive: true });
await writeFile(absolutePath, content, "utf8");
}
return workspaceRoot;
}
function runBoundaryCheck(workspaceRoot) {
return spawnSync(process.execPath, [scriptPath], {
cwd: workspaceRoot,
encoding: "utf8",
env: {
...process.env,
TUTTI_WORKSPACE_ROOT: workspaceRoot,
TUTTI_RENDERER_ROOT: rendererRoot
}
});
}