Reorganize Blender Web execution around capabilities
Some checks are pending
M6 deployable RC / quick (push) Waiting to run
M6 deployable RC / chromium (push) Blocked by required conditions
M6 deployable RC / release (push) Blocked by required conditions

This commit is contained in:
mes123456
2026-08-24 18:37:46 -04:00
parent 0b2c3ba0dd
commit a081c68c87
2530 changed files with 763976 additions and 79 deletions

Binary file not shown.

View File

@@ -0,0 +1,7 @@
export { createAssetCatalogRegistry } from "../../protocol/corrective-asset-catalog-command";
export { AssetCatalogResourceResolver, InMemoryCatalogProvider } from "../../protocol/corrective-resource-provider";
export { InMemoryMainStore } from "../../protocol/corrective-main-transaction";
export { CorrectiveHistoryStore } from "../../protocol/corrective-history-store";
export { createModifierMain, createModifierRegistry } from "../../protocol/corrective-modifier-command";
export { createMeshMain, createMeshRegistry } from "../../protocol/corrective-mesh-command";
export { runCorrectiveFamilyCases, summarizeCorrectiveFamilyResults } from "../../protocol/corrective-family-runner";

Binary file not shown.

View File

@@ -60,6 +60,9 @@
"test:m10-domain-gates": "node --test tests/unit/geometry-nodes.test.mjs tests/unit/shader-compiler.test.mjs tests/unit/nla.test.mjs tests/unit/simulation-cache.test.mjs && playwright test --config playwright.config.ts --workers=1 tests/e2e/m10-domain-browser-gates.spec.ts",
"test:browser": "playwright test --config playwright.release.config.ts",
"test:task-context": "node --test tests/unit/task-context.test.mjs && node ../tools/web/check-task-context.mjs",
"test:execution-control-plane": "node --test tests/unit/execution-control-plane.test.mjs && node ../tools/web/check-execution-control-plane.mjs --allow-unrunnable",
"test:v2-task-index": "node ../tools/web/check-v2-task-index.mjs",
"test:v2-handoff": "node ../tools/web/check-v2-handoff.mjs",
"test:context-governance": "node --test tests/unit/task-context.test.mjs tests/unit/context-governance.test.mjs && node ../tools/web/check-context-governance.mjs",
"test:streaming-resilience": "node --test tests/unit/streaming-resilience.test.mjs",
"task:context": "node ../tools/web/print-task-context.mjs",

View File

@@ -0,0 +1,61 @@
import { CorrectiveCommandRegistry } from "./corrective-command-registry";
import { CorrectiveCaseRunnerError, MainMutationCommand, MainMutationResult } from "./corrective-case-runner";
import { InMemoryMainStore, runAtomicMutation } from "./corrective-main-transaction";
import { AssetCatalogResourceResolver, CorrectiveResourceError } from "./corrective-resource-provider";
export interface AssetCatalogEntry {
id: string;
name: string;
sourceId: string;
sourceSha256: string;
byteLength: number;
}
export interface AssetCatalogMain {
entries: AssetCatalogEntry[];
}
const ENTRY_ID = /^[A-Za-z0-9._:-]{1,128}$/u;
const ENTRY_NAME = /^.{1,128}$/u;
function payload(command: MainMutationCommand): { id: string; name: string; resource: Record<string, unknown> } {
const input = command.payload;
if (!input || typeof input !== "object" || Array.isArray(input)) throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "catalog payload must be an object");
const id = input.id;
const name = input.name;
const resource = input.resource;
if (typeof id !== "string" || !ENTRY_ID.test(id) || typeof name !== "string" || !ENTRY_NAME.test(name) || !resource || typeof resource !== "object" || Array.isArray(resource)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "catalog entry payload is invalid");
}
return { id, name, resource: resource as Record<string, unknown> };
}
export function createAssetCatalogRegistry(main: InMemoryMainStore<AssetCatalogMain>, resources: AssetCatalogResourceResolver): CorrectiveCommandRegistry {
return new CorrectiveCommandRegistry().register({
commandType: "assetCatalogAppend",
targetKinds: ["ASSET_LIBRARY"],
authorizations: ["USER_EDIT", "SYSTEM"],
execute: async (command) => {
const entry = payload(command);
let resolved;
try {
resolved = await resources.resolve(entry.resource);
} catch (error) {
if (error instanceof CorrectiveResourceError && error.code === "RESOURCE_REQUIRED") {
throw new CorrectiveCaseRunnerError("RESOURCE_REQUIRED", error.message);
}
throw error;
}
return runAtomicMutation(main, command, (draft) => {
if (draft.entries.some((item) => item.id === entry.id)) throw new CorrectiveCaseRunnerError("COMMAND_UNSUPPORTED", `catalog entry ${entry.id} already exists`);
draft.entries.push({ id: entry.id, name: entry.name, sourceId: resolved.sourceId, sourceSha256: resolved.sha256, byteLength: resolved.bytes.byteLength });
return { delta: { addedId: entry.id, count: draft.entries.length }, persistence: { dirty: true } };
});
},
});
}
export function catalogFailureCode(error: unknown): string {
if (error instanceof CorrectiveResourceError) return error.code;
return error instanceof Error ? error.message : String(error);
}

View File

@@ -0,0 +1,351 @@
export const CORRECTIVE_CASE_SCHEMA = 1 as const;
export type CaseSurface = "DESKTOP" | "WASM";
export type CommandStatus = "FINISHED" | "BLOCKED" | "CANCELLED" | "UNSUPPORTED" | "MALFORMED" | "EXTERNAL_REQUIRED";
export type MainMutation = "CHANGED" | "UNCHANGED";
export type TargetKind = "ASSET_LIBRARY" | "DATABLOCK" | "MESH" | "MODIFIER" | "SCENE";
export type EditMode = "READ_ONLY" | "EDITABLE";
export type Authorization = "NONE" | "USER_EDIT" | "SYSTEM";
export type SourceKind = "LOCAL" | "EXTERNAL" | "PACKED";
export type ResourceProvider = "NONE" | "OPFS" | "EXTERNAL_LIBRARY" | "PACKED_BLEND";
export interface CommandContext {
mainId: string;
targetKind: TargetKind;
targetId?: string;
editMode: EditMode;
authorization: Authorization;
source: { kind: SourceKind; sha256: string };
resourceProvider?: ResourceProvider;
}
export interface MainMutationCommand {
schemaVersion: typeof CORRECTIVE_CASE_SCHEMA;
requestId: string;
commandType: string;
baseRevision: number;
context: CommandContext;
payload: Record<string, unknown>;
}
export interface MainMutationResult {
schemaVersion: typeof CORRECTIVE_CASE_SCHEMA;
requestId: string;
status: CommandStatus;
code: string;
baseRevision: number;
mainRevisionBefore: number;
mainRevisionAfter: number;
mainMutation: MainMutation;
delta: Record<string, unknown> | null;
persistence: Record<string, unknown> | null;
error: Record<string, unknown> | null;
}
export interface SurfaceReceipt {
schemaVersion: typeof CORRECTIVE_CASE_SCHEMA;
surface: CaseSurface;
requestId: string;
commandType: string;
context: CommandContext | null;
result: MainMutationResult;
}
export interface SharedCaseReceipt {
schemaVersion: typeof CORRECTIVE_CASE_SCHEMA;
requestId: string;
commandType: string;
desktop: SurfaceReceipt;
wasm: SurfaceReceipt;
parity: "MATCH" | "MISMATCH";
differences: string[];
}
export interface SurfaceCaseOptions {
command: unknown;
mainRevision: number;
execute: (command: MainMutationCommand) => MainMutationResult | Promise<MainMutationResult>;
}
export class CorrectiveCaseRunnerError extends Error {
readonly code: string;
constructor(code: string, message: string) {
super(`${code}: ${message}`);
this.name = "CorrectiveCaseRunnerError";
this.code = code;
}
}
const SHA256 = /^[a-f0-9]{64}$/u;
const REQUEST_ID = /^[A-Za-z0-9._:-]{1,256}$/u;
const COMMAND_TYPE = /^[a-z][A-Za-z0-9]{0,127}$/u;
const STATUS_CODES: Readonly<Record<CommandStatus, string>> = {
FINISHED: "OK",
BLOCKED: "REVISION_CONFLICT",
CANCELLED: "CANCELLED",
UNSUPPORTED: "COMMAND_UNSUPPORTED",
MALFORMED: "COMMAND_MALFORMED",
EXTERNAL_REQUIRED: "RESOURCE_REQUIRED",
};
const STATUS_CODE_PAIRS = new Set([
"FINISHED:OK",
"BLOCKED:REVISION_CONFLICT",
"BLOCKED:INVALID_CONTEXT",
"CANCELLED:CANCELLED",
"UNSUPPORTED:COMMAND_UNSUPPORTED",
"MALFORMED:COMMAND_MALFORMED",
"EXTERNAL_REQUIRED:RESOURCE_REQUIRED",
]);
const STATUSES = new Set<CommandStatus>(Object.keys(STATUS_CODES) as CommandStatus[]);
const TARGET_KINDS = new Set<TargetKind>(["ASSET_LIBRARY", "DATABLOCK", "MESH", "MODIFIER", "SCENE"]);
const EDIT_MODES = new Set<EditMode>(["READ_ONLY", "EDITABLE"]);
const AUTHORIZATIONS = new Set<Authorization>(["NONE", "USER_EDIT", "SYSTEM"]);
const SOURCE_KINDS = new Set<SourceKind>(["LOCAL", "EXTERNAL", "PACKED"]);
const RESOURCE_PROVIDERS = new Set<ResourceProvider>(["NONE", "OPFS", "EXTERNAL_LIBRARY", "PACKED_BLEND"]);
function record(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function exactKeys(value: Record<string, unknown>, allowed: ReadonlySet<string>, label: string): void {
for (const key of Object.keys(value)) {
if (!allowed.has(key)) throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", `${label}.${key} is not allowed`);
}
}
function boundedText(value: unknown, label: string, pattern: RegExp, maximum = 256): string {
if (typeof value !== "string" || value.length === 0 || value.length > maximum || !pattern.test(value)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", `${label} is invalid`);
}
return value;
}
function nonNegativeInteger(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", `${label} must be a non-negative integer`);
}
return value;
}
function commandContext(value: unknown): CommandContext {
if (!record(value)) throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "context must be an object");
exactKeys(value, new Set(["mainId", "targetKind", "targetId", "editMode", "authorization", "source", "resourceProvider"]), "context");
const mainId = boundedText(value.mainId, "context.mainId", /^.{1,256}$/u);
if (typeof value.targetKind !== "string" || !TARGET_KINDS.has(value.targetKind as TargetKind)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "context.targetKind is invalid");
}
const targetId = value.targetId === undefined ? undefined : boundedText(value.targetId, "context.targetId", /^.{1,256}$/u);
if (typeof value.editMode !== "string" || !EDIT_MODES.has(value.editMode as EditMode)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "context.editMode is invalid");
}
if (typeof value.authorization !== "string" || !AUTHORIZATIONS.has(value.authorization as Authorization)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "context.authorization is invalid");
}
if (!record(value.source) || Object.keys(value.source).some((key) => !["kind", "sha256"].includes(key))) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "context.source is invalid");
}
if (typeof value.source.kind !== "string" || !SOURCE_KINDS.has(value.source.kind as SourceKind) ||
typeof value.source.sha256 !== "string" || !SHA256.test(value.source.sha256)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "context.source provenance is invalid");
}
const resourceProvider = value.resourceProvider === undefined ? undefined : value.resourceProvider;
if (resourceProvider !== undefined && (typeof resourceProvider !== "string" || !RESOURCE_PROVIDERS.has(resourceProvider as ResourceProvider))) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "context.resourceProvider is invalid");
}
return {
mainId,
targetKind: value.targetKind as TargetKind,
...(targetId === undefined ? {} : { targetId }),
editMode: value.editMode as EditMode,
authorization: value.authorization as Authorization,
source: { kind: value.source.kind as SourceKind, sha256: value.source.sha256 },
...(resourceProvider === undefined ? {} : { resourceProvider: resourceProvider as ResourceProvider }),
};
}
export function validateCommand(value: unknown): MainMutationCommand {
if (!record(value)) throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "command must be an object");
exactKeys(value, new Set(["schemaVersion", "requestId", "commandType", "baseRevision", "context", "payload"]), "command");
if (value.schemaVersion !== CORRECTIVE_CASE_SCHEMA) throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "schemaVersion is unsupported");
const requestId = boundedText(value.requestId, "requestId", REQUEST_ID);
const commandType = boundedText(value.commandType, "commandType", COMMAND_TYPE);
const baseRevision = nonNegativeInteger(value.baseRevision, "baseRevision");
const context = commandContext(value.context);
if (!record(value.payload)) throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "payload must be an object");
for (const key of ["requestId", "baseRevision", "context"]) {
if (Object.prototype.hasOwnProperty.call(value.payload, key)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", `payload cannot override ${key}`);
}
}
return { schemaVersion: CORRECTIVE_CASE_SCHEMA, requestId, commandType, baseRevision, context, payload: { ...value.payload } };
}
function resultObject(value: unknown): Record<string, unknown> {
if (!record(value)) throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "result must be an object");
exactKeys(value, new Set(["schemaVersion", "requestId", "status", "code", "baseRevision", "mainRevisionBefore", "mainRevisionAfter", "mainMutation", "delta", "persistence", "error"]), "result");
return value;
}
function optionalObject(value: unknown, label: string): Record<string, unknown> | null {
if (value === undefined || value === null) return null;
if (!record(value)) throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", `${label} must be an object or null`);
return { ...value };
}
export function normalizeResult(value: unknown, command: MainMutationCommand, mainRevisionBefore: number): MainMutationResult {
const result = resultObject(value);
if (result.schemaVersion !== CORRECTIVE_CASE_SCHEMA || result.requestId !== command.requestId || result.baseRevision !== command.baseRevision) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "result identity is not bound to the command");
}
nonNegativeInteger(result.mainRevisionBefore, "mainRevisionBefore");
nonNegativeInteger(result.mainRevisionAfter, "mainRevisionAfter");
if (result.mainRevisionBefore !== mainRevisionBefore) throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "result before revision is not current");
if (typeof result.status !== "string" || !STATUSES.has(result.status as CommandStatus) || typeof result.code !== "string" || !STATUS_CODE_PAIRS.has(`${result.status}:${result.code}`)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "status and code are not a closed pair");
}
const status = result.status as CommandStatus;
const mutation = result.mainMutation;
const expectedMutation: MainMutation = status === "FINISHED" ? "CHANGED" : "UNCHANGED";
if (mutation !== expectedMutation || result.mainRevisionAfter !== mainRevisionBefore + (status === "FINISHED" ? 1 : 0)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "result revision or mutation invariant failed");
}
const delta = optionalObject(result.delta, "delta");
const persistence = optionalObject(result.persistence, "persistence");
const error = optionalObject(result.error, "error");
if (status !== "FINISHED" && (delta !== null || persistence !== null)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "failure result cannot claim delta or persistence");
}
return {
schemaVersion: CORRECTIVE_CASE_SCHEMA,
requestId: command.requestId,
status,
code: STATUS_CODES[status],
baseRevision: command.baseRevision,
mainRevisionBefore,
mainRevisionAfter: result.mainRevisionAfter,
mainMutation: expectedMutation,
delta,
persistence,
error,
};
}
function failure(command: MainMutationCommand | null, status: Exclude<CommandStatus, "FINISHED">, before: number, message: string, code = STATUS_CODES[status]): MainMutationResult {
const requestId = command?.requestId ?? "invalid-request";
const baseRevision = command?.baseRevision ?? before;
return {
schemaVersion: CORRECTIVE_CASE_SCHEMA,
requestId,
status,
code,
baseRevision,
mainRevisionBefore: before,
mainRevisionAfter: before,
mainMutation: "UNCHANGED",
delta: null,
persistence: null,
error: { code, message },
};
}
function commandIdentity(value: unknown): { requestId: string; commandType: string } {
const input = record(value) ? value : {};
return {
requestId: typeof input.requestId === "string" && REQUEST_ID.test(input.requestId) ? input.requestId : "invalid-request",
commandType: typeof input.commandType === "string" && COMMAND_TYPE.test(input.commandType) ? input.commandType : "malformed",
};
}
function receipt(surface: CaseSurface, command: MainMutationCommand | null, result: MainMutationResult): SurfaceReceipt {
const identity = command ? { requestId: command.requestId, commandType: command.commandType } : commandIdentity(result);
return {
schemaVersion: CORRECTIVE_CASE_SCHEMA,
surface,
requestId: identity.requestId,
commandType: identity.commandType,
context: command?.context ?? null,
result,
};
}
async function runSurface(surface: CaseSurface, options: SurfaceCaseOptions): Promise<SurfaceReceipt> {
const before = nonNegativeInteger(options.mainRevision, "mainRevision");
let command: MainMutationCommand;
try {
command = validateCommand(options.command);
}
catch (error) {
const identity = commandIdentity(options.command);
const malformed = failure(null, "MALFORMED", before, error instanceof Error ? error.message : String(error));
malformed.requestId = identity.requestId;
return receipt(surface, null, malformed);
}
if (command.baseRevision !== before) return receipt(surface, command, failure(command, "BLOCKED", before, "base revision does not match current Main"));
if (command.context.editMode !== "EDITABLE" || command.context.authorization === "NONE") {
return receipt(surface, command, failure(command, "BLOCKED", before, "context cannot authorize a Main mutation", "INVALID_CONTEXT"));
}
if (command.context.source.kind === "EXTERNAL" && (!command.context.resourceProvider || command.context.resourceProvider === "NONE")) {
return receipt(surface, command, failure(command, "EXTERNAL_REQUIRED", before, "external source requires a resource provider"));
}
try {
return receipt(surface, command, normalizeResult(await options.execute(command), command, before));
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
const code = error instanceof CorrectiveCaseRunnerError ? error.code : "COMMAND_UNSUPPORTED";
const status = code === "RESOURCE_REQUIRED" ? "EXTERNAL_REQUIRED" : code === "CANCELLED" ? "CANCELLED" : code === "REVISION_CONFLICT" || code === "INVALID_CONTEXT" ? "BLOCKED" : code === "COMMAND_MALFORMED" ? "MALFORMED" : "UNSUPPORTED";
return receipt(surface, command, failure(command, status, before, message, code === "INVALID_CONTEXT" ? code : STATUS_CODES[status]));
}
}
export function runDesktopCase(options: SurfaceCaseOptions): Promise<SurfaceReceipt> {
return runSurface("DESKTOP", options);
}
export function runWasmCase(options: SurfaceCaseOptions): Promise<SurfaceReceipt> {
return runSurface("WASM", options);
}
function coreReceipt(receiptValue: SurfaceReceipt): Record<string, unknown> {
const result = receiptValue.result;
return {
requestId: receiptValue.requestId,
commandType: receiptValue.commandType,
status: result.status,
code: result.code,
baseRevision: result.baseRevision,
mainRevisionBefore: result.mainRevisionBefore,
mainRevisionAfter: result.mainRevisionAfter,
mainMutation: result.mainMutation,
delta: result.delta,
persistence: result.persistence,
};
}
function stable(value: unknown): unknown {
if (Array.isArray(value)) return value.map(stable);
if (record(value)) return Object.fromEntries(Object.keys(value).sort().map((key) => [key, stable(value[key])]));
return value;
}
export function compareReceipts(desktop: SurfaceReceipt, wasm: SurfaceReceipt): { parity: "MATCH" | "MISMATCH"; differences: string[] } {
const left = coreReceipt(desktop);
const right = coreReceipt(wasm);
const differences = Object.keys(left).filter((key) => JSON.stringify(stable(left[key])) !== JSON.stringify(stable(right[key]))).map((key) => `${key}: desktop=${JSON.stringify(stable(left[key]))} wasm=${JSON.stringify(stable(right[key]))}`);
return { parity: differences.length === 0 ? "MATCH" : "MISMATCH", differences };
}
export async function runSharedCase(command: unknown, mainRevision: number, executors: { desktop: SurfaceCaseOptions["execute"]; wasm: SurfaceCaseOptions["execute"] }): Promise<SharedCaseReceipt> {
const desktop = await runDesktopCase({ command, mainRevision, execute: executors.desktop });
const wasm = await runWasmCase({ command, mainRevision, execute: executors.wasm });
const comparison = compareReceipts(desktop, wasm);
return {
schemaVersion: CORRECTIVE_CASE_SCHEMA,
requestId: desktop.requestId,
commandType: desktop.commandType,
desktop,
wasm,
...comparison,
};
}

View File

@@ -0,0 +1,116 @@
import {
Authorization,
CaseSurface,
CommandContext,
CorrectiveCaseRunnerError,
MainMutationCommand,
MainMutationResult,
SurfaceReceipt,
TargetKind,
runDesktopCase,
runWasmCase,
} from "./corrective-case-runner";
export const CORRECTIVE_COMMAND_REGISTRY_SCHEMA = 1 as const;
export type CommandExecutor = (command: MainMutationCommand) => MainMutationResult | Promise<MainMutationResult>;
export interface RegisteredCommand {
commandType: string;
targetKinds: readonly TargetKind[];
authorizations: readonly Exclude<Authorization, "NONE">[];
execute: CommandExecutor;
}
export class CommandRegistryError extends Error {
readonly code: "REGISTRY_INVALID" | "REGISTRY_DUPLICATE";
constructor(code: "REGISTRY_INVALID" | "REGISTRY_DUPLICATE", message: string) {
super(`${code}: ${message}`);
this.name = "CommandRegistryError";
this.code = code;
}
}
export interface DispatchOptions {
command: unknown;
mainRevision: number;
}
const COMMAND_TYPE = /^[a-z][A-Za-z0-9]{0,127}$/u;
const TARGET_KINDS = new Set<TargetKind>(["ASSET_LIBRARY", "DATABLOCK", "MESH", "MODIFIER", "SCENE"]);
const AUTHORIZATIONS = new Set<Exclude<Authorization, "NONE">>(["USER_EDIT", "SYSTEM"]);
function unique<T>(values: readonly T[]): boolean {
return new Set(values).size === values.length;
}
function validateDefinition(definition: RegisteredCommand): void {
if (!definition || typeof definition !== "object" || !COMMAND_TYPE.test(definition.commandType)) {
throw new CommandRegistryError("REGISTRY_INVALID", "commandType is invalid");
}
if (!Array.isArray(definition.targetKinds) || definition.targetKinds.length === 0 ||
!unique(definition.targetKinds) || definition.targetKinds.some((kind) => !TARGET_KINDS.has(kind))) {
throw new CommandRegistryError("REGISTRY_INVALID", "targetKinds must contain unique supported targets");
}
if (!Array.isArray(definition.authorizations) || definition.authorizations.length === 0 ||
!unique(definition.authorizations) || definition.authorizations.some((authorization) => !AUTHORIZATIONS.has(authorization))) {
throw new CommandRegistryError("REGISTRY_INVALID", "authorizations must contain unique mutating authorities");
}
if (typeof definition.execute !== "function") {
throw new CommandRegistryError("REGISTRY_INVALID", "execute must be a function");
}
}
function contextError(context: CommandContext, message: string): CorrectiveCaseRunnerError {
return new CorrectiveCaseRunnerError("INVALID_CONTEXT", `${context.targetKind}: ${message}`);
}
export class CorrectiveCommandRegistry {
readonly schemaVersion = CORRECTIVE_COMMAND_REGISTRY_SCHEMA;
private readonly commands = new Map<string, RegisteredCommand>();
register(definition: RegisteredCommand): this {
validateDefinition(definition);
if (this.commands.has(definition.commandType)) {
throw new CommandRegistryError("REGISTRY_DUPLICATE", `commandType ${definition.commandType} is already registered`);
}
this.commands.set(definition.commandType, {
commandType: definition.commandType,
targetKinds: [...definition.targetKinds],
authorizations: [...definition.authorizations],
execute: definition.execute,
});
return this;
}
has(commandType: string): boolean {
return this.commands.has(commandType);
}
list(): string[] {
return [...this.commands.keys()].sort();
}
async dispatch(surface: CaseSurface, options: DispatchOptions): Promise<SurfaceReceipt> {
const run = surface === "DESKTOP" ? runDesktopCase : runWasmCase;
return run({
command: options.command,
mainRevision: options.mainRevision,
execute: async (command) => {
const definition = this.commands.get(command.commandType);
if (!definition) {
throw new CorrectiveCaseRunnerError("COMMAND_UNSUPPORTED", `commandType ${command.commandType} is not registered`);
}
if (!definition.targetKinds.includes(command.context.targetKind)) {
throw contextError(command.context, "target is not authorized for this command");
}
if (!definition.authorizations.includes(command.context.authorization as Exclude<Authorization, "NONE">)) {
throw contextError(command.context, "authorization is not allowed for this command");
}
return definition.execute(command);
},
});
}
}

View File

@@ -0,0 +1,45 @@
import { CorrectiveCommandRegistry } from "./corrective-command-registry";
import { CaseSurface, SurfaceReceipt } from "./corrective-case-runner";
export type CorrectiveFamily = "ASSET_CATALOG" | "MODIFIER" | "MESH";
export interface CorrectiveFamilyCase {
id: string;
family: CorrectiveFamily;
registry: CorrectiveCommandRegistry;
surface: CaseSurface;
command: unknown;
mainRevision: number;
}
export interface CorrectiveFamilyResult extends CorrectiveFamilyCase {
receipt: SurfaceReceipt;
}
const CASE_ID = /^[A-Za-z][A-Za-z0-9._:-]{0,127}$/u;
export async function runCorrectiveFamilyCases(cases: readonly CorrectiveFamilyCase[]): Promise<CorrectiveFamilyResult[]> {
const ids = new Set<string>();
for (const testCase of cases) {
if (!testCase || !CASE_ID.test(testCase.id) || ids.has(testCase.id)) throw new Error(`family case id is invalid or duplicated: ${testCase?.id ?? "unknown"}`);
ids.add(testCase.id);
if (!["ASSET_CATALOG", "MODIFIER", "MESH"].includes(testCase.family)) throw new Error(`unsupported corrective family: ${testCase.family}`);
if (!(testCase.registry instanceof CorrectiveCommandRegistry)) throw new Error(`family case registry is invalid: ${testCase.id}`);
if (!Number.isSafeInteger(testCase.mainRevision) || testCase.mainRevision < 0) throw new Error(`family case revision is invalid: ${testCase.id}`);
}
return Promise.all(cases.map(async (testCase) => ({ ...testCase, receipt: await testCase.registry.dispatch(testCase.surface, { command: testCase.command, mainRevision: testCase.mainRevision }) })));
}
export function summarizeCorrectiveFamilyResults(results: readonly CorrectiveFamilyResult[]): Record<CorrectiveFamily, { total: number; finished: number; unchanged: number }> {
const summary: Record<CorrectiveFamily, { total: number; finished: number; unchanged: number }> = {
ASSET_CATALOG: { total: 0, finished: 0, unchanged: 0 },
MODIFIER: { total: 0, finished: 0, unchanged: 0 },
MESH: { total: 0, finished: 0, unchanged: 0 },
};
for (const result of results) {
const bucket = summary[result.family]; bucket.total += 1;
if (result.receipt.result.status === "FINISHED") bucket.finished += 1;
if (result.receipt.result.mainMutation === "UNCHANGED") bucket.unchanged += 1;
}
return summary;
}

View File

@@ -0,0 +1,70 @@
import { InMemoryMainStore, MainSnapshot } from "./corrective-main-transaction";
export interface HistoryState<T> extends MainSnapshot<T> {
canUndo: boolean;
canRedo: boolean;
savedRevision: number;
}
export class CorrectiveHistoryStore<T> extends InMemoryMainStore<T> {
private readonly capacity: number;
private undoStack: MainSnapshot<T>[] = [];
private redoStack: MainSnapshot<T>[] = [];
private saved: MainSnapshot<T>;
constructor(value: T, revision: number, dirty: boolean, clone: (value: T) => T, capacity = 16) {
super(value, revision, dirty, clone);
if (!Number.isSafeInteger(capacity) || capacity < 1 || capacity > 256) throw new Error("history capacity must be between 1 and 256");
this.capacity = capacity;
this.saved = this.snapshot();
}
override commit(value: T, revision: number, dirty: boolean): void {
const before = this.snapshot();
super.commit(value, revision, dirty);
if (before.revision !== revision || JSON.stringify(before.value) !== JSON.stringify(value) || before.dirty !== dirty) {
this.undoStack.push(before);
if (this.undoStack.length > this.capacity) this.undoStack.shift();
this.redoStack = [];
}
}
save(): MainSnapshot<T> {
const current = this.snapshot();
this.saved = current;
super.commit(current.value, current.revision, false);
return this.snapshot();
}
reopen(): MainSnapshot<T> {
const before = this.snapshot();
super.commit(this.saved.value, this.saved.revision, false);
this.undoStack = [];
this.redoStack = [];
return before;
}
undo(): MainSnapshot<T> {
const previous = this.undoStack.pop();
if (!previous) return this.snapshot();
const current = this.snapshot();
this.redoStack.push(current);
super.commit(previous.value, previous.revision, previous.dirty);
return this.snapshot();
}
redo(): MainSnapshot<T> {
const next = this.redoStack.pop();
if (!next) return this.snapshot();
const current = this.snapshot();
this.undoStack.push(current);
super.commit(next.value, next.revision, next.dirty);
return this.snapshot();
}
historyState(): HistoryState<T> {
const current = this.snapshot();
return { ...current, canUndo: this.undoStack.length > 0, canRedo: this.redoStack.length > 0, savedRevision: this.saved.revision };
}
}

View File

@@ -0,0 +1,92 @@
import {
CorrectiveCaseRunnerError,
MainMutationCommand,
MainMutationResult,
} from "./corrective-case-runner";
export interface MainSnapshot<T> {
value: T;
revision: number;
dirty: boolean;
}
export interface AtomicMutationOutcome {
delta: Record<string, unknown>;
persistence?: Record<string, unknown> | null;
}
export type DraftMutation<T> = (draft: T, command: MainMutationCommand) => AtomicMutationOutcome | Promise<AtomicMutationOutcome>;
export class InMemoryMainStore<T> {
private value: T;
private currentRevision: number;
private currentDirty: boolean;
private readonly clone: (value: T) => T;
constructor(value: T, revision: number, dirty: boolean, clone: (value: T) => T) {
if (!Number.isSafeInteger(revision) || revision < 0) throw new Error("revision must be a non-negative integer");
this.clone = clone;
this.value = clone(value);
this.currentRevision = revision;
this.currentDirty = dirty;
}
snapshot(): MainSnapshot<T> {
return { value: this.clone(this.value), revision: this.currentRevision, dirty: this.currentDirty };
}
commit(value: T, revision: number, dirty: boolean): void {
if (!Number.isSafeInteger(revision) || revision < 0) throw new Error("revision must be a non-negative integer");
this.value = this.clone(value);
this.currentRevision = revision;
this.currentDirty = dirty;
}
restore(snapshot: MainSnapshot<T>): void {
this.commit(snapshot.value, snapshot.revision, snapshot.dirty);
}
}
function validOutcome(value: unknown): value is AtomicMutationOutcome {
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
const candidate = value as Record<string, unknown>;
if (!candidate.delta || typeof candidate.delta !== "object" || Array.isArray(candidate.delta)) return false;
return candidate.persistence === undefined || candidate.persistence === null ||
(typeof candidate.persistence === "object" && !Array.isArray(candidate.persistence));
}
export async function runAtomicMutation<T>(
store: InMemoryMainStore<T>,
command: MainMutationCommand,
mutate: DraftMutation<T>,
): Promise<MainMutationResult> {
const before = store.snapshot();
if (command.baseRevision !== before.revision) {
throw new CorrectiveCaseRunnerError("REVISION_CONFLICT", "base revision does not match current Main");
}
try {
const draft = store.snapshot().value;
const outcome = await mutate(draft, command);
if (!validOutcome(outcome)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "atomic mutation outcome is invalid");
}
store.commit(draft, before.revision + 1, true);
return {
schemaVersion: 1,
requestId: command.requestId,
status: "FINISHED",
code: "OK",
baseRevision: command.baseRevision,
mainRevisionBefore: before.revision,
mainRevisionAfter: before.revision + 1,
mainMutation: "CHANGED",
delta: { ...outcome.delta },
persistence: outcome.persistence === undefined ? { dirty: true } : outcome.persistence,
error: null,
};
} catch (error) {
store.restore(before);
throw error;
}
}

View File

@@ -0,0 +1,72 @@
import { CorrectiveCommandRegistry } from "./corrective-command-registry";
import { CorrectiveCaseRunnerError, MainMutationCommand } from "./corrective-case-runner";
import { InMemoryMainStore, runAtomicMutation } from "./corrective-main-transaction";
export interface MeshVertexState {
id: string;
x: number;
y: number;
z: number;
}
export interface MeshMain {
vertices: MeshVertexState[];
}
const VERTEX_ID = /^[A-Za-z0-9._:-]{1,128}$/u;
const COORDINATE_LIMIT = 1_000_000;
function coordinate(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value) || Math.abs(value) > COORDINATE_LIMIT) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", `${label} must be a finite coordinate within bounds`);
}
return value;
}
function meshPayload(command: MainMutationCommand): { vertexId: string; delta: { x: number; y: number; z: number } } {
const input = command.payload;
if (!input || typeof input !== "object" || Array.isArray(input) ||
typeof input.vertexId !== "string" || !VERTEX_ID.test(input.vertexId) ||
!input.delta || typeof input.delta !== "object" || Array.isArray(input.delta) ||
Object.keys(input).some((key) => !["vertexId", "delta"].includes(key))) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "mesh payload must contain only vertexId and delta");
}
const delta = input.delta as Record<string, unknown>;
if (Object.keys(delta).some((key) => !["x", "y", "z"].includes(key)) ||
!Object.prototype.hasOwnProperty.call(delta, "x") || !Object.prototype.hasOwnProperty.call(delta, "y") || !Object.prototype.hasOwnProperty.call(delta, "z")) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "mesh delta must contain only x, y, and z");
}
return { vertexId: input.vertexId, delta: { x: coordinate(delta.x, "delta.x"), y: coordinate(delta.y, "delta.y"), z: coordinate(delta.z, "delta.z") } };
}
function cloneMeshMain(value: MeshMain): MeshMain {
return { vertices: value.vertices.map((vertex) => ({ ...vertex })) };
}
export function createMeshRegistry(main: InMemoryMainStore<MeshMain>): CorrectiveCommandRegistry {
return new CorrectiveCommandRegistry().register({
commandType: "meshTranslateVertex",
targetKinds: ["MESH"],
authorizations: ["USER_EDIT", "SYSTEM"],
execute: async (command) => {
const change = meshPayload(command);
return runAtomicMutation(main, command, (draft) => {
const vertex = draft.vertices.find((candidate) => candidate.id === change.vertexId);
if (!vertex) throw new CorrectiveCaseRunnerError("COMMAND_UNSUPPORTED", `vertex ${change.vertexId} does not exist`);
const before = { x: vertex.x, y: vertex.y, z: vertex.z };
const after = { x: before.x + change.delta.x, y: before.y + change.delta.y, z: before.z + change.delta.z };
if ([after.x, after.y, after.z].some((value) => !Number.isFinite(value) || Math.abs(value) > COORDINATE_LIMIT)) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "mesh translation exceeds coordinate bounds");
}
vertex.x = after.x;
vertex.y = after.y;
vertex.z = after.z;
return { delta: { vertexId: vertex.id, before, after }, persistence: { dirty: true } };
});
},
});
}
export function createMeshMain(vertices: readonly MeshVertexState[], revision = 0, dirty = false): InMemoryMainStore<MeshMain> {
return new InMemoryMainStore({ vertices: vertices.map((vertex) => ({ ...vertex })) }, revision, dirty, cloneMeshMain);
}

View File

@@ -0,0 +1,59 @@
import { CorrectiveCommandRegistry } from "./corrective-command-registry";
import { CorrectiveCaseRunnerError, MainMutationCommand } from "./corrective-case-runner";
import { InMemoryMainStore, runAtomicMutation } from "./corrective-main-transaction";
export interface ModifierState {
uuid: string;
name: string;
type: string;
enabled: boolean;
showViewport: boolean;
showRender: boolean;
}
export interface ModifierMain {
modifiers: ModifierState[];
}
const UUID = /^[A-Za-z0-9._:-]{1,128}$/u;
function modifierPayload(command: MainMutationCommand): { modifierUuid: string; enabled: boolean } {
const input = command.payload;
if (!input || typeof input !== "object" || Array.isArray(input) ||
typeof input.modifierUuid !== "string" || !UUID.test(input.modifierUuid) ||
typeof input.enabled !== "boolean" || Object.keys(input).some((key) => !["modifierUuid", "enabled"].includes(key))) {
throw new CorrectiveCaseRunnerError("COMMAND_MALFORMED", "modifier payload must contain only modifierUuid and enabled");
}
return { modifierUuid: input.modifierUuid, enabled: input.enabled };
}
function cloneModifierMain(value: ModifierMain): ModifierMain {
return { modifiers: value.modifiers.map((modifier) => ({ ...modifier })) };
}
export function createModifierRegistry(main: InMemoryMainStore<ModifierMain>): CorrectiveCommandRegistry {
return new CorrectiveCommandRegistry().register({
commandType: "modifierSetEnabled",
targetKinds: ["MODIFIER"],
authorizations: ["USER_EDIT", "SYSTEM"],
execute: async (command) => {
const change = modifierPayload(command);
return runAtomicMutation(main, command, (draft) => {
const modifier = draft.modifiers.find((candidate) => candidate.uuid === change.modifierUuid);
if (!modifier) {
throw new CorrectiveCaseRunnerError("COMMAND_UNSUPPORTED", `modifier ${change.modifierUuid} does not exist`);
}
const previousEnabled = modifier.enabled;
modifier.enabled = change.enabled;
return {
delta: { modifierUuid: modifier.uuid, previousEnabled, enabled: modifier.enabled },
persistence: { dirty: true },
};
});
},
});
}
export function createModifierMain(modifiers: readonly ModifierState[], revision = 0, dirty = false): InMemoryMainStore<ModifierMain> {
return new InMemoryMainStore({ modifiers: modifiers.map((modifier) => ({ ...modifier })) }, revision, dirty, cloneModifierMain);
}

View File

@@ -0,0 +1,153 @@
export const CORRECTIVE_RESOURCE_SCHEMA = 1 as const;
export type CatalogSourceKind = "LOCAL" | "EXTERNAL" | "PACKED";
export type ResourceProviderKind = "LOCAL" | "EXTERNAL_LIBRARY" | "PACKED_BLEND";
export interface ActiveLibraryContext {
libraryId: string;
sourceKind: CatalogSourceKind;
sourceId: string;
generation: number;
revision: number;
readOnly: boolean;
}
export interface ResourceRequest {
schemaVersion: typeof CORRECTIVE_RESOURCE_SCHEMA;
requestId: string;
sourceKind: CatalogSourceKind;
sourceId: string;
sha256: string;
}
export interface ResourceRecord {
schemaVersion: typeof CORRECTIVE_RESOURCE_SCHEMA;
provider: ResourceProviderKind;
sourceKind: CatalogSourceKind;
sourceId: string;
sha256: string;
bytes: Uint8Array;
}
export class CorrectiveResourceError extends Error {
readonly code: "RESOURCE_MALFORMED" | "RESOURCE_REQUIRED" | "RESOURCE_NOT_FOUND" | "RESOURCE_HASH_MISMATCH" | "CANCELLED" | "CONTEXT_INVALID";
constructor(code: CorrectiveResourceError["code"], message: string) {
super(`${code}: ${message}`);
this.name = "CorrectiveResourceError";
this.code = code;
}
}
const SHA256 = /^[a-f0-9]{64}$/u;
const REQUEST_ID = /^[A-Za-z0-9._:-]{1,256}$/u;
const SOURCE_ID = /^[A-Za-z0-9._:/-]{1,256}$/u;
const LIBRARY_ID = /^[A-Za-z0-9._:/-]{1,256}$/u;
const SOURCE_KINDS = new Set<CatalogSourceKind>(["LOCAL", "EXTERNAL", "PACKED"]);
function assertText(value: unknown, pattern: RegExp, label: string): string {
if (typeof value !== "string" || !pattern.test(value)) throw new CorrectiveResourceError("RESOURCE_MALFORMED", `${label} is invalid`);
return value;
}
function assertInteger(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw new CorrectiveResourceError("RESOURCE_MALFORMED", `${label} is invalid`);
return value;
}
function bytesCopy(value: Uint8Array): Uint8Array {
return new Uint8Array(value);
}
async function digest(bytes: Uint8Array): Promise<string> {
const hash = await globalThis.crypto.subtle.digest("SHA-256", bytes as Uint8Array<ArrayBuffer>);
return [...new Uint8Array(hash)].map((value) => value.toString(16).padStart(2, "0")).join("");
}
export function validateActiveLibraryContext(value: unknown): ActiveLibraryContext {
if (!value || typeof value !== "object" || Array.isArray(value)) throw new CorrectiveResourceError("CONTEXT_INVALID", "active library context must be an object");
const input = value as Record<string, unknown>;
const keys = Object.keys(input);
if (keys.some((key) => !["libraryId", "sourceKind", "sourceId", "generation", "revision", "readOnly"].includes(key))) throw new CorrectiveResourceError("CONTEXT_INVALID", "active library context has unknown fields");
const libraryId = assertText(input.libraryId, LIBRARY_ID, "libraryId");
const sourceKind = input.sourceKind;
if (typeof sourceKind !== "string" || !SOURCE_KINDS.has(sourceKind as CatalogSourceKind)) throw new CorrectiveResourceError("CONTEXT_INVALID", "sourceKind is invalid");
const sourceId = assertText(input.sourceId, SOURCE_ID, "sourceId");
const generation = assertInteger(input.generation, "generation");
const revision = assertInteger(input.revision, "revision");
if (typeof input.readOnly !== "boolean") throw new CorrectiveResourceError("CONTEXT_INVALID", "readOnly is invalid");
return { libraryId, sourceKind: sourceKind as CatalogSourceKind, sourceId, generation, revision, readOnly: input.readOnly };
}
export function validateResourceRequest(value: unknown): ResourceRequest {
if (!value || typeof value !== "object" || Array.isArray(value)) throw new CorrectiveResourceError("RESOURCE_MALFORMED", "resource request must be an object");
const input = value as Record<string, unknown>;
if (Object.keys(input).some((key) => !["schemaVersion", "requestId", "sourceKind", "sourceId", "sha256"].includes(key))) throw new CorrectiveResourceError("RESOURCE_MALFORMED", "resource request has unknown fields");
if (input.schemaVersion !== CORRECTIVE_RESOURCE_SCHEMA) throw new CorrectiveResourceError("RESOURCE_MALFORMED", "schemaVersion is unsupported");
const requestId = assertText(input.requestId, REQUEST_ID, "requestId");
if (typeof input.sourceKind !== "string" || !SOURCE_KINDS.has(input.sourceKind as CatalogSourceKind)) throw new CorrectiveResourceError("RESOURCE_MALFORMED", "sourceKind is invalid");
const sourceId = assertText(input.sourceId, SOURCE_ID, "sourceId");
const sha256 = assertText(input.sha256, SHA256, "sha256");
return { schemaVersion: CORRECTIVE_RESOURCE_SCHEMA, requestId, sourceKind: input.sourceKind as CatalogSourceKind, sourceId, sha256 };
}
export class InMemoryCatalogProvider {
readonly provider: ResourceProviderKind;
private readonly records = new Map<string, Uint8Array>();
constructor(provider: ResourceProviderKind) {
this.provider = provider;
}
async put(sourceId: string, bytes: Uint8Array): Promise<string> {
assertText(sourceId, SOURCE_ID, "sourceId");
if (!(bytes instanceof Uint8Array)) throw new CorrectiveResourceError("RESOURCE_MALFORMED", "bytes must be Uint8Array");
const copy = bytesCopy(bytes);
const hash = await digest(copy);
this.records.set(sourceId, copy);
return hash;
}
async load(sourceId: string, signal?: AbortSignal): Promise<Uint8Array> {
if (signal?.aborted) throw new CorrectiveResourceError("CANCELLED", "resource lookup cancelled");
const value = this.records.get(sourceId);
if (!value) throw new CorrectiveResourceError("RESOURCE_NOT_FOUND", `resource ${sourceId} is not available`);
await Promise.resolve();
if (signal?.aborted) throw new CorrectiveResourceError("CANCELLED", "resource lookup cancelled");
return bytesCopy(value);
}
}
export class AssetCatalogResourceResolver {
private readonly providers = new Map<ResourceProviderKind, InMemoryCatalogProvider>();
private active: ActiveLibraryContext | null = null;
setActiveLibraryContext(value: unknown): ActiveLibraryContext {
this.active = validateActiveLibraryContext(value);
return { ...this.active };
}
registerProvider(provider: InMemoryCatalogProvider): this {
this.providers.set(provider.provider, provider);
return this;
}
activeLibraryContext(): ActiveLibraryContext | null {
return this.active ? { ...this.active } : null;
}
async resolve(value: unknown, signal?: AbortSignal): Promise<ResourceRecord> {
const request = validateResourceRequest(value);
if (signal?.aborted) throw new CorrectiveResourceError("CANCELLED", "resource lookup cancelled");
if (!this.active || this.active.sourceKind !== request.sourceKind || this.active.sourceId !== request.sourceId) {
throw new CorrectiveResourceError("CONTEXT_INVALID", "request does not match active library context");
}
const providerKind: ResourceProviderKind = request.sourceKind === "LOCAL" ? "LOCAL" : request.sourceKind === "EXTERNAL" ? "EXTERNAL_LIBRARY" : "PACKED_BLEND";
const provider = this.providers.get(providerKind);
if (!provider) throw new CorrectiveResourceError("RESOURCE_REQUIRED", `${providerKind} provider is required`);
const bytes = await provider.load(request.sourceId, signal);
const observed = await digest(bytes);
if (observed !== request.sha256) throw new CorrectiveResourceError("RESOURCE_HASH_MISMATCH", `resource hash ${observed} does not match request`);
return { schemaVersion: CORRECTIVE_RESOURCE_SCHEMA, provider: providerKind, sourceKind: request.sourceKind, sourceId: request.sourceId, sha256: observed, bytes };
}
}

View File

@@ -46,9 +46,22 @@ export interface SceneNodeIR {
localMatrix: number[];
worldMatrix: number[];
transform: SceneTransformIR;
assetData?: AssetMetadataIR;
constraints?: ConstraintIR[];
}
export interface AssetMetadataIR {
marked: true;
author: string;
description: string;
copyright: string;
license: string;
catalogSimpleName: string;
activeTag: number;
preferredImportMethod: number;
tags: string[];
}
export interface ConstraintIR {
name: string;
typeCode: number;

View File

@@ -0,0 +1,41 @@
import { expect, test } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C3-003");
test("C3-003 Chromium asset catalog pilot covers five cases and save/reopen", async ({ page }) => {
await page.goto("/");
const report = await page.evaluate(async () => {
const { createAssetCatalogRegistry, AssetCatalogResourceResolver, InMemoryCatalogProvider, InMemoryMainStore, CorrectiveHistoryStore } = await import("/src/corrective-pilot-bridge.ts");
const bytes = new TextEncoder().encode("chromium-catalog-fixture");
const provider = new InMemoryCatalogProvider("EXTERNAL_LIBRARY");
const hash = await provider.put("library.blend", bytes);
const resources = new AssetCatalogResourceResolver();
resources.registerProvider(provider).setActiveLibraryContext({ libraryId: "lib:chromium", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 4, readOnly: false });
const createMain = () => new InMemoryMainStore({ entries: [] }, 4, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) }));
const command = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-catalog-001", commandType: "assetCatalogAppend", baseRevision: 4, context: { mainId: "main:chromium", targetKind: "ASSET_LIBRARY", targetId: "library:chromium", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "EXTERNAL", sha256: hash }, resourceProvider: "EXTERNAL_LIBRARY" }, payload: { id: "asset:chromium", name: "Chromium Asset", resource: { schemaVersion: 1, requestId: "resource-chromium-001", sourceKind: "EXTERNAL", sourceId: "library.blend", sha256: hash } }, ...overrides });
const desktopMain = createMain(); const wasmMain = createMain();
const desktop = await createAssetCatalogRegistry(desktopMain, resources).dispatch("DESKTOP", { command: command(), mainRevision: 4 });
const wasm = await createAssetCatalogRegistry(wasmMain, resources).dispatch("WASM", { command: command(), mainRevision: 4 });
const duplicate = await createAssetCatalogRegistry(desktopMain, resources).dispatch("DESKTOP", { command: command({ baseRevision: 5 }), mainRevision: 5 });
const missingResources = new AssetCatalogResourceResolver(); missingResources.setActiveLibraryContext({ libraryId: "lib:chromium", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 4, readOnly: false });
const missing = await createAssetCatalogRegistry(createMain(), missingResources).dispatch("WASM", { command: command(), mainRevision: 4 });
const revision = await createAssetCatalogRegistry(createMain(), resources).dispatch("WASM", { command: command({ baseRevision: 3 }), mainRevision: 4 });
const malformed = await createAssetCatalogRegistry(createMain(), resources).dispatch("DESKTOP", { command: command({ payload: { id: "bad id" } }), mainRevision: 4 });
const history = new CorrectiveHistoryStore({ entries: [] }, 4, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) }));
history.commit(desktopMain.snapshot().value, 5, true); history.save(); history.commit({ entries: [] }, 6, true); history.reopen();
return { positive: { desktop: desktop.result, wasm: wasm.result, desktopEntries: desktopMain.snapshot().value.entries.length, wasmEntries: wasmMain.snapshot().value.entries.length }, negative: { duplicate: duplicate.result, missing: missing.result, revision: revision.result, malformed: malformed.result }, persistence: history.snapshot(), parity: JSON.stringify(desktop.result) === JSON.stringify(wasm.result) };
});
fs.mkdirSync(evidenceRoot, { recursive: true });
fs.writeFileSync(path.join(evidenceRoot, process.env.C3_PILOT_REPORT ?? "receipt-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C3-003", operation: "CORRECTIVE_ASSET_CATALOG_CHROMIUM_PILOT", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
expect(report.parity).toBe(true);
expect(report.positive.desktop.status).toBe("FINISHED");
expect(report.positive.desktopEntries).toBe(1);
expect(report.positive.wasmEntries).toBe(1);
expect(report.negative.duplicate.mainRevisionAfter).toBe(5);
expect(report.negative.missing.mainRevisionAfter).toBe(4);
expect(report.negative.revision.code).toBe("REVISION_CONFLICT");
expect(report.negative.malformed.code).toBe("COMMAND_MALFORMED");
expect(report.persistence).toEqual({ value: { entries: [{ id: "asset:chromium", name: "Chromium Asset", sourceId: "library.blend", sourceSha256: expect.any(String), byteLength: 24 }] }, revision: 5, dirty: false });
});

View File

@@ -0,0 +1,18 @@
import { expect, test } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C5-002");
test("C5-002 Chromium family runner dispatches data-driven Asset, Modifier, and Mesh cases", async ({ page }) => {
await page.goto("/");
const report = await page.evaluate(async () => {
const { AssetCatalogResourceResolver, InMemoryCatalogProvider, InMemoryMainStore, createAssetCatalogRegistry, createModifierMain, createModifierRegistry, createMeshMain, createMeshRegistry, runCorrectiveFamilyCases, summarizeCorrectiveFamilyResults } = await import("/src/corrective-pilot-bridge.ts");
const bytes = new TextEncoder().encode("family-runner-resource"); const provider = new InMemoryCatalogProvider("EXTERNAL_LIBRARY"); const sourceHash = await provider.put("library.blend", bytes); const resolver = new AssetCatalogResourceResolver(); resolver.registerProvider(provider).setActiveLibraryContext({ libraryId: "library:family", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 1, readOnly: false });
const command = (family, surface) => family === "ASSET_CATALOG" ? ({ schemaVersion: 1, requestId: `chromium-family-${surface.toLowerCase()}-asset`, commandType: "assetCatalogAppend", baseRevision: 1, context: { mainId: "main:asset", targetKind: "ASSET_LIBRARY", targetId: "library:family", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "EXTERNAL", sha256: sourceHash }, resourceProvider: "EXTERNAL_LIBRARY" }, payload: { id: `asset:${surface.toLowerCase()}`, name: "Family Asset", resource: { schemaVersion: 1, requestId: "family-resource", sourceKind: "EXTERNAL", sourceId: "library.blend", sha256: sourceHash } } }) : family === "MODIFIER" ? ({ schemaVersion: 1, requestId: `chromium-family-${surface.toLowerCase()}-modifier`, commandType: "modifierSetEnabled", baseRevision: 1, context: { mainId: "main:modifier", targetKind: "MODIFIER", targetId: "modifier:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "f".repeat(64) } }, payload: { modifierUuid: "modifier:one", enabled: true } }) : ({ schemaVersion: 1, requestId: `chromium-family-${surface.toLowerCase()}-mesh`, commandType: "meshTranslateVertex", baseRevision: 1, context: { mainId: "main:mesh", targetKind: "MESH", targetId: "mesh:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "0".repeat(64) } }, payload: { vertexId: "vertex:0", delta: { x: 1, y: 0, z: 0 } } });
const cases = []; for (const family of ["ASSET_CATALOG", "MODIFIER", "MESH"]) for (const surface of ["DESKTOP", "WASM"]) { const main = family === "ASSET_CATALOG" ? new InMemoryMainStore({ entries: [] }, 1, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) })) : family === "MODIFIER" ? createModifierMain([{ uuid: "modifier:one", name: "One", type: "BEVEL", enabled: false, showViewport: true, showRender: true }], 1, false) : createMeshMain([{ id: "vertex:0", x: 0, y: 0, z: 0 }], 1, false); const registry = family === "ASSET_CATALOG" ? createAssetCatalogRegistry(main, resolver) : family === "MODIFIER" ? createModifierRegistry(main) : createMeshRegistry(main); cases.push({ id: `${family.toLowerCase()}-${surface.toLowerCase()}`, family, registry, surface, command: command(family, surface), mainRevision: 1 }); }
const results = await runCorrectiveFamilyCases(cases); return { summary: summarizeCorrectiveFamilyResults(results), results: results.map((result) => ({ id: result.id, family: result.family, surface: result.surface, receipt: result.receipt.result })) };
});
fs.mkdirSync(evidenceRoot, { recursive: true }); fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "chromium-family-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C5-002", operation: "CORRECTIVE_FAMILY_RUNNER_CHROMIUM", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
expect(report.results).toHaveLength(6); expect(report.results.every((result) => result.receipt.status === "FINISHED")).toBe(true); expect(report.summary).toEqual({ ASSET_CATALOG: { total: 2, finished: 2, unchanged: 0 }, MODIFIER: { total: 2, finished: 2, unchanged: 0 }, MESH: { total: 2, finished: 2, unchanged: 0 } });
});

View File

@@ -0,0 +1,33 @@
import { expect, test } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C4-002");
test("C4-002 Chromium mesh pilot covers geometry parity, rollback, and save/reopen", async ({ page }) => {
await page.goto("/");
const report = await page.evaluate(async () => {
const { createMeshMain, createMeshRegistry, CorrectiveHistoryStore } = await import("/src/corrective-pilot-bridge.ts");
const fixture = [{ id: "vertex:0", x: 1, y: 2, z: 3 }, { id: "vertex:1", x: 0, y: 0, z: 0 }];
const command = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-mesh-001", commandType: "meshTranslateVertex", baseRevision: 9, context: { mainId: "main:chromium-mesh", targetKind: "MESH", targetId: "mesh:cube", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "b".repeat(64) } }, payload: { vertexId: "vertex:0", delta: { x: 0.5, y: -1, z: 2 } }, ...overrides });
const desktopMain = createMeshMain(fixture, 9, false); const wasmMain = createMeshMain(fixture, 9, false);
const desktop = await createMeshRegistry(desktopMain).dispatch("DESKTOP", { command: command(), mainRevision: 9 }); const wasm = await createMeshRegistry(wasmMain).dispatch("WASM", { command: command(), mainRevision: 9 });
const rollbackMain = createMeshMain(fixture, 9, false); const registry = createMeshRegistry(rollbackMain);
const malformed = await registry.dispatch("DESKTOP", { command: command({ payload: { vertexId: "vertex:0", delta: { x: 0.5, y: -1, z: 2, w: 1 } } }), mainRevision: 9 });
const stale = await registry.dispatch("WASM", { command: command({ baseRevision: 8 }), mainRevision: 9 });
const unknown = await registry.dispatch("DESKTOP", { command: command({ payload: { vertexId: "vertex:missing", delta: { x: 0.5, y: -1, z: 2 } } }), mainRevision: 9 });
const clone = (value) => ({ vertices: value.vertices.map((vertex) => ({ ...vertex })) });
const history = new CorrectiveHistoryStore({ vertices: fixture }, 9, false, clone);
await createMeshRegistry(history).dispatch("WASM", { command: command(), mainRevision: 9 });
const saved = history.save(); const undone = history.undo(); const redone = history.redo(); const reopened = history.reopen();
return { positive: { desktop: desktop.result, wasm: wasm.result, desktopMain: desktopMain.snapshot(), wasmMain: wasmMain.snapshot() }, negative: { malformed: malformed.result, stale: stale.result, unknown: unknown.result, rollbackMain: rollbackMain.snapshot() }, persistence: { saved, undone, redone, reopened, final: history.snapshot() }, parity: JSON.stringify(desktop.result) === JSON.stringify(wasm.result) && JSON.stringify(desktopMain.snapshot()) === JSON.stringify(wasmMain.snapshot()) };
});
fs.mkdirSync(evidenceRoot, { recursive: true });
fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "receipt-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C4-002", operation: "CORRECTIVE_MESH_CHROMIUM_PILOT", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
expect(report.parity).toBe(true); expect(report.positive.desktop.status).toBe("FINISHED");
expect(report.positive.desktop.delta).toEqual({ vertexId: "vertex:0", before: { x: 1, y: 2, z: 3 }, after: { x: 1.5, y: 1, z: 5 } });
expect(report.positive.desktopMain.value.vertices[0]).toEqual({ id: "vertex:0", x: 1.5, y: 1, z: 5 }); expect(report.positive.desktopMain.dirty).toBe(true);
expect(report.negative.malformed.code).toBe("COMMAND_MALFORMED"); expect(report.negative.stale.code).toBe("REVISION_CONFLICT"); expect(report.negative.unknown.code).toBe("COMMAND_UNSUPPORTED");
expect(report.negative.rollbackMain).toEqual({ value: { vertices: [{ id: "vertex:0", x: 1, y: 2, z: 3 }, { id: "vertex:1", x: 0, y: 0, z: 0 }] }, revision: 9, dirty: false });
expect(report.persistence.saved.dirty).toBe(false); expect(report.persistence.undone.value.vertices[0].x).toBe(1); expect(report.persistence.redone.value.vertices[0].x).toBe(1.5); expect(report.persistence.reopened.value.vertices[0].z).toBe(5); expect(report.persistence.final.dirty).toBe(false);
});

View File

@@ -0,0 +1,60 @@
import { expect, test } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C4-001");
test("C4-001 Chromium modifier pilot covers positive parity, rollback, and save/reopen", async ({ page }) => {
await page.goto("/");
const report = await page.evaluate(async () => {
const { createModifierMain, createModifierRegistry, CorrectiveHistoryStore } = await import("/src/corrective-pilot-bridge.ts");
const fixture = [{ uuid: "modifier:bevel", name: "Pilot Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }];
const command = (overrides = {}) => ({
schemaVersion: 1,
requestId: "chromium-modifier-001",
commandType: "modifierSetEnabled",
baseRevision: 7,
context: { mainId: "main:chromium-modifier", targetKind: "MODIFIER", targetId: "modifier:bevel", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "a".repeat(64) } },
payload: { modifierUuid: "modifier:bevel", enabled: true },
...overrides,
});
const desktopMain = createModifierMain(fixture, 7, false);
const wasmMain = createModifierMain(fixture, 7, false);
const desktop = await createModifierRegistry(desktopMain).dispatch("DESKTOP", { command: command(), mainRevision: 7 });
const wasm = await createModifierRegistry(wasmMain).dispatch("WASM", { command: command(), mainRevision: 7 });
const rollbackMain = createModifierMain(fixture, 7, false);
const registry = createModifierRegistry(rollbackMain);
const malformed = await registry.dispatch("DESKTOP", { command: command({ payload: { modifierUuid: "modifier:bevel", enabled: true, unexpected: true } }), mainRevision: 7 });
const stale = await registry.dispatch("WASM", { command: command({ baseRevision: 6 }), mainRevision: 7 });
const unknown = await registry.dispatch("DESKTOP", { command: command({ payload: { modifierUuid: "modifier:missing", enabled: true } }), mainRevision: 7 });
const clone = (value) => ({ modifiers: value.modifiers.map((modifier) => ({ ...modifier })) });
const history = new CorrectiveHistoryStore({ modifiers: fixture }, 7, false, clone);
await createModifierRegistry(history).dispatch("WASM", { command: command(), mainRevision: 7 });
const saved = history.save();
const undone = history.undo();
const redone = history.redo();
const reopened = history.reopen();
return {
positive: { desktop: desktop.result, wasm: wasm.result, desktopMain: desktopMain.snapshot(), wasmMain: wasmMain.snapshot() },
negative: { malformed: malformed.result, stale: stale.result, unknown: unknown.result, rollbackMain: rollbackMain.snapshot() },
persistence: { saved, undone, redone, reopened, final: history.snapshot() },
parity: JSON.stringify(desktop.result) === JSON.stringify(wasm.result) && JSON.stringify(desktopMain.snapshot()) === JSON.stringify(wasmMain.snapshot()),
};
});
fs.mkdirSync(evidenceRoot, { recursive: true });
fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "receipt-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C4-001", operation: "CORRECTIVE_MODIFIER_CHROMIUM_PILOT", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
expect(report.parity).toBe(true);
expect(report.positive.desktop.status).toBe("FINISHED");
expect(report.positive.desktop.delta).toEqual({ modifierUuid: "modifier:bevel", previousEnabled: false, enabled: true });
expect(report.positive.desktopMain.value.modifiers[0].enabled).toBe(true);
expect(report.positive.desktopMain.dirty).toBe(true);
expect(report.negative.malformed.code).toBe("COMMAND_MALFORMED");
expect(report.negative.stale.code).toBe("REVISION_CONFLICT");
expect(report.negative.unknown.code).toBe("COMMAND_UNSUPPORTED");
expect(report.negative.rollbackMain).toEqual({ value: { modifiers: [{ uuid: "modifier:bevel", name: "Pilot Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }] }, revision: 7, dirty: false });
expect(report.persistence.saved.dirty).toBe(false);
expect(report.persistence.undone.value.modifiers[0].enabled).toBe(false);
expect(report.persistence.redone.value.modifiers[0].enabled).toBe(true);
expect(report.persistence.reopened.value.modifiers[0].enabled).toBe(true);
expect(report.persistence.final.dirty).toBe(false);
});

View File

@@ -0,0 +1,27 @@
import { expect, test } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C4-003");
test("C4-003 Chromium negative matrix keeps all Main snapshots unchanged", async ({ page }) => {
await page.goto("/");
const report = await page.evaluate(async () => {
const { createAssetCatalogRegistry, AssetCatalogResourceResolver, InMemoryMainStore, createModifierMain, createModifierRegistry, createMeshMain, createMeshRegistry } = await import("/src/corrective-pilot-bridge.ts");
const modifierFixture = [{ uuid: "modifier:one", name: "One", type: "BEVEL", enabled: false, showViewport: true, showRender: true }]; const meshFixture = [{ id: "vertex:0", x: 0, y: 0, z: 0 }];
const modifierCommand = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-negative-modifier", commandType: "modifierSetEnabled", baseRevision: 3, context: { mainId: "main:modifier", targetKind: "MODIFIER", targetId: "modifier:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "c".repeat(64) } }, payload: { modifierUuid: "modifier:one", enabled: true }, ...overrides });
const meshCommand = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-negative-mesh", commandType: "meshTranslateVertex", baseRevision: 4, context: { mainId: "main:mesh", targetKind: "MESH", targetId: "mesh:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "d".repeat(64) } }, payload: { vertexId: "vertex:0", delta: { x: 1, y: 0, z: 0 } }, ...overrides });
const assetCommand = (overrides = {}) => ({ schemaVersion: 1, requestId: "chromium-negative-asset", commandType: "assetCatalogAppend", baseRevision: 2, context: { mainId: "main:asset", targetKind: "ASSET_LIBRARY", targetId: "library:one", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "EXTERNAL", sha256: "e".repeat(64) }, resourceProvider: "EXTERNAL_LIBRARY" }, payload: { id: "asset:one", name: "One", resource: { schemaVersion: 1, requestId: "resource-one", sourceKind: "EXTERNAL", sourceId: "library.blend", sha256: "e".repeat(64) } }, ...overrides });
const modifierMain = createModifierMain(modifierFixture, 3, false); const meshMain = createMeshMain(meshFixture, 4, false); const assetMain = new InMemoryMainStore({ entries: [] }, 2, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) })); const resources = new AssetCatalogResourceResolver(); resources.setActiveLibraryContext({ libraryId: "library:one", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 2, readOnly: false });
const cases = [
["modifierMalformed", createModifierRegistry(modifierMain), "DESKTOP", modifierCommand({ payload: { modifierUuid: "modifier:one", enabled: true, extra: true } }), 3], ["modifierUnsupported", createModifierRegistry(modifierMain), "WASM", modifierCommand({ payload: { modifierUuid: "modifier:missing", enabled: true } }), 3], ["modifierRevision", createModifierRegistry(modifierMain), "DESKTOP", modifierCommand({ baseRevision: 2 }), 3],
["meshMalformed", createMeshRegistry(meshMain), "WASM", meshCommand({ payload: { vertexId: "vertex:0", delta: { x: 1, y: 0, z: 0, extra: true } } }), 4], ["meshUnsupported", createMeshRegistry(meshMain), "DESKTOP", meshCommand({ payload: { vertexId: "vertex:missing", delta: { x: 1, y: 0, z: 0 } } }), 4], ["meshRevision", createMeshRegistry(meshMain), "WASM", meshCommand({ baseRevision: 3 }), 4],
["assetMalformed", createAssetCatalogRegistry(assetMain, resources), "DESKTOP", assetCommand({ payload: { id: "bad id" } }), 2], ["assetResourceMissing", createAssetCatalogRegistry(assetMain, resources), "WASM", assetCommand(), 2], ["assetRevision", createAssetCatalogRegistry(assetMain, resources), "DESKTOP", assetCommand({ baseRevision: 1 }), 2],
];
const results = {}; for (const [name, registry, surface, command, mainRevision] of cases) results[name] = (await registry.dispatch(surface, { command, mainRevision })).result;
return { results, snapshots: { modifier: modifierMain.snapshot(), mesh: meshMain.snapshot(), asset: assetMain.snapshot() }, unchanged: Object.values(results).every((result) => result.mainMutation === "UNCHANGED") };
});
fs.mkdirSync(evidenceRoot, { recursive: true }); fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "chromium-negative-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C4-003", operation: "CORRECTIVE_NEGATIVE_MATRIX_CHROMIUM", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
expect(report.unchanged).toBe(true); expect(report.results.modifierMalformed.code).toBe("COMMAND_MALFORMED"); expect(report.results.modifierUnsupported.code).toBe("COMMAND_UNSUPPORTED"); expect(report.results.modifierRevision.code).toBe("REVISION_CONFLICT"); expect(report.results.meshMalformed.code).toBe("COMMAND_MALFORMED"); expect(report.results.meshUnsupported.code).toBe("COMMAND_UNSUPPORTED"); expect(report.results.meshRevision.code).toBe("REVISION_CONFLICT"); expect(report.results.assetMalformed.code).toBe("COMMAND_MALFORMED"); expect(report.results.assetResourceMissing.code).toBe("RESOURCE_REQUIRED"); expect(report.results.assetRevision.code).toBe("REVISION_CONFLICT");
expect(report.snapshots.modifier.revision).toBe(3); expect(report.snapshots.mesh.revision).toBe(4); expect(report.snapshots.asset.revision).toBe(2); expect(report.snapshots.modifier.dirty).toBe(false); expect(report.snapshots.mesh.dirty).toBe(false); expect(report.snapshots.asset.dirty).toBe(false);
});

View File

@@ -0,0 +1,21 @@
import { expect, test } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C6-002");
test("C6-002 Chromium performance and security boundaries stay within budget", async ({ page }) => {
await page.goto("/");
const report = await page.evaluate(async () => {
const { AssetCatalogResourceResolver, InMemoryMainStore, createAssetCatalogRegistry, createModifierMain, createModifierRegistry } = await import("/src/corrective-pilot-bridge.ts");
const fixture = [{ uuid: "modifier:security", name: "Security Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }];
const modifierCommand = (overrides = {}) => ({ schemaVersion: 1, requestId: "security-modifier-001", commandType: "modifierSetEnabled", baseRevision: 0, context: { mainId: "main:security", targetKind: "MODIFIER", targetId: "modifier:security", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "2".repeat(64) } }, payload: { modifierUuid: "modifier:security", enabled: true }, ...overrides });
const samples = []; for (let index = 0; index < 50; index += 1) { const main = createModifierMain(fixture, 0, false); const start = performance.now(); const receipt = await createModifierRegistry(main).dispatch("WASM", { command: modifierCommand({ requestId: `security-sample-${index}` }), mainRevision: 0 }); samples.push({ durationMs: performance.now() - start, status: receipt.result.status, revision: main.snapshot().revision }); }
const replayMain = createModifierMain(fixture, 0, false); const replayRegistry = createModifierRegistry(replayMain); const replayCommand = modifierCommand(); const first = await replayRegistry.dispatch("DESKTOP", { command: replayCommand, mainRevision: 0 }); const replay = await replayRegistry.dispatch("DESKTOP", { command: replayCommand, mainRevision: 1 });
const malformedMain = createModifierMain(fixture, 0, false); const malformed = await createModifierRegistry(malformedMain).dispatch("WASM", { command: modifierCommand({ payload: { modifierUuid: "modifier:security", enabled: true, extra: "x".repeat(4096) } }), mainRevision: 0 });
const assetMain = new InMemoryMainStore({ entries: [] }, 0, false, (value) => ({ entries: value.entries.map((entry) => ({ ...entry })) })); const resolver = new AssetCatalogResourceResolver(); resolver.setActiveLibraryContext({ libraryId: "library:security", sourceKind: "EXTERNAL", sourceId: "library.blend", generation: 1, revision: 0, readOnly: false }); const pathCommand = { schemaVersion: 1, requestId: "security-path-001", commandType: "assetCatalogAppend", baseRevision: 0, context: { mainId: "main:asset-security", targetKind: "ASSET_LIBRARY", targetId: "library:security", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "EXTERNAL", sha256: "3".repeat(64) }, resourceProvider: "EXTERNAL_LIBRARY" }, payload: { id: "asset:escape", name: "Escape", resource: { schemaVersion: 1, requestId: "security-resource", sourceKind: "EXTERNAL", sourceId: "../escape.blend", sha256: "3".repeat(64) } } }; const pathResult = await createAssetCatalogRegistry(assetMain, resolver).dispatch("WASM", { command: pathCommand, mainRevision: 0 });
const durations = samples.map((sample) => sample.durationMs).sort((a, b) => a - b); return { sampleCount: samples.length, latencyMs: { p50: durations[Math.floor(durations.length * 0.5)], p95: durations[Math.floor(durations.length * 0.95)], max: durations.at(-1) }, samples, security: { replay: replay.result, first: first.result, malformed: malformed.result, path: pathResult.result, snapshots: { replay: replayMain.snapshot(), malformed: malformedMain.snapshot(), path: assetMain.snapshot() } }, budgets: { p95Ms: 100, maxMs: 250, maxSamples: 50 }, withinBudget: durations[Math.floor(durations.length * 0.95)] < 100 && durations.at(-1) < 250 };
});
fs.mkdirSync(evidenceRoot, { recursive: true }); fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "performance-security-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C6-002", operation: "CORRECTIVE_PERFORMANCE_SECURITY_CHROMIUM", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
expect(report.sampleCount).toBe(50); expect(report.withinBudget).toBe(true); expect(report.security.first.status).toBe("FINISHED"); expect(report.security.replay.code).toBe("REVISION_CONFLICT"); expect(report.security.replay.mainMutation).toBe("UNCHANGED"); expect(report.security.malformed.code).toBe("COMMAND_MALFORMED"); expect(report.security.malformed.mainMutation).toBe("UNCHANGED"); expect(report.security.path.mainMutation).toBe("UNCHANGED"); expect(report.security.snapshots.replay.revision).toBe(1); expect(report.security.snapshots.malformed.revision).toBe(0); expect(report.security.snapshots.path.revision).toBe(0); expect(report.security.snapshots.replay.dirty).toBe(true); expect(report.security.snapshots.malformed.dirty).toBe(false); expect(report.security.snapshots.path.dirty).toBe(false);
});

View File

@@ -0,0 +1,18 @@
import { expect, test } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const evidenceRoot = path.resolve(import.meta.dirname, "../../../tests/golden/corrective/C6-001");
test("C6-001 Chromium open/edit/undo/redo/save/reopen workflow is stable", async ({ page }) => {
await page.goto("/");
const report = await page.evaluate(async () => {
const { CorrectiveHistoryStore, createModifierRegistry } = await import("/src/corrective-pilot-bridge.ts");
const fixture = [{ uuid: "modifier:workflow", name: "Workflow Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }]; const clone = (value) => ({ modifiers: value.modifiers.map((modifier) => ({ ...modifier })) }); const history = new CorrectiveHistoryStore({ modifiers: fixture }, 0, false, clone);
const command = { schemaVersion: 1, requestId: "chromium-workflow-001", commandType: "modifierSetEnabled", baseRevision: 0, context: { mainId: "main:workflow", targetKind: "MODIFIER", targetId: "modifier:workflow", editMode: "EDITABLE", authorization: "USER_EDIT", source: { kind: "LOCAL", sha256: "1".repeat(64) } }, payload: { modifierUuid: "modifier:workflow", enabled: true } };
const opened = history.snapshot(); const editedReceipt = await createModifierRegistry(history).dispatch("DESKTOP", { command, mainRevision: 0 }); const edited = history.snapshot(); const saved = history.save(); const undone = history.undo(); const redone = history.redo(); const reopened = history.reopen();
return { opened, editedReceipt: editedReceipt.result, edited, saved, undone, redone, reopened, final: history.snapshot() };
});
fs.mkdirSync(evidenceRoot, { recursive: true }); fs.writeFileSync(path.join(evidenceRoot, process.env.C4_PILOT_REPORT ?? "workflow-report.json"), `${JSON.stringify({ schemaVersion: 1, task: "C6-001", operation: "CORRECTIVE_CHROMIUM_WORKFLOW_GATE", browser: "chromium", queueMutation: false, ...report }, null, 2)}\n`);
expect(report.opened).toEqual({ value: { modifiers: [{ uuid: "modifier:workflow", name: "Workflow Bevel", type: "BEVEL", enabled: false, showViewport: true, showRender: true }] }, revision: 0, dirty: false }); expect(report.editedReceipt.status).toBe("FINISHED"); expect(report.edited.revision).toBe(1); expect(report.edited.dirty).toBe(true); expect(report.edited.value.modifiers[0].enabled).toBe(true); expect(report.saved.revision).toBe(1); expect(report.saved.dirty).toBe(false); expect(report.undone.revision).toBe(0); expect(report.undone.value.modifiers[0].enabled).toBe(false); expect(report.redone.revision).toBe(1); expect(report.redone.value.modifiers[0].enabled).toBe(true); expect(report.reopened.value.modifiers[0].enabled).toBe(true); expect(report.reopened.dirty).toBe(false); expect(report.final).toEqual(report.reopened);
});

View File

@@ -0,0 +1,20 @@
import assert from "node:assert/strict";
import { execFileSync } from "node:child_process";
import test from "node:test";
import path from "node:path";
const root = path.resolve(import.meta.dirname, "../../..");
test("execution control plane reports one queue pointer and capability throughput", () => {
const output = execFileSync(process.execPath, [
path.join(root, "tools/web/check-execution-control-plane.mjs"),
"--allow-unrunnable",
], { cwd: root, encoding: "utf8" });
const report = JSON.parse(output);
assert.equal(report.status, "PASS");
assert.equal(report.queue.currentTask, "WBV2-P0-002");
assert.equal(report.queue.parentNextTask, report.queue.currentTask);
assert.equal(report.efficiency.capabilityClusters, 3);
assert.ok(report.efficiency.averageGapsPerCapability >= 1);
assert.equal(report.issues.length, 0);
});

View File

@@ -4,7 +4,7 @@ import { collectGeneratedGapPreflight } from "../../../tools/web/generated-gap-p
import { readIndexedTask, root, verifyTaskIndex } from "../../../tools/web/task-context-lib.mjs";
test("generated gap preflight accepts a runnable task with existing inputs", () => {
verifyTaskIndex();
verifyTaskIndex("M16-GAP-00281");
const entry = readIndexedTask("M16-GAP-00281");
assert.deepEqual(collectGeneratedGapPreflight({ root, task: "M16-GAP-00281", entry }), []);
});

View File

@@ -5,12 +5,12 @@ import { buildTaskContext, compactTaskContext, contextSizeReport, CONTEXT_LIMITS
test("current task context is bounded and follows the parent pointer", () => {
const bundle = buildTaskContext();
const report = contextSizeReport(bundle);
assert.match(bundle.context.task, /^M\d+-GAP-\d{5}$/);
assert.match(bundle.context.parentTask, /^M\d+-GAP-\d{5}$/);
assert.match(bundle.context.task, /^(?:M\d+-GAP-\d{5}|WBV2-P\d-\d{3})$/);
assert.match(bundle.context.parentTask, /^(?:M\d+-GAP-\d{5}|WBV2-(?:BASELINE|P\d-\d{3}))$/);
assert.equal(bundle.context.parent.manifest.nextTask, bundle.context.task);
assert.ok(bundle.context.commands.length >= 1);
assert.equal(bundle.context.sourceDocuments.taskCard, `docs/tasks/${bundle.context.task}.md`);
assert.equal(bundle.context.sourceDocuments.taskIndex, "tests/golden/M15-03A/task-index.json");
assert.equal(bundle.context.sourceDocuments.taskIndex, "tests/golden/WBV2/task-index.json");
assert.ok(!JSON.stringify(bundle.context).includes("next-task-plan.json"));
assert.equal(bundle.context.scope.ownerFamily, readIndexedTask(bundle.context.task).ownerFamily);
assert.equal(report.withinBudget, true);