import { describe, expect, it } from "vitest"; import { getToolcraftComponentContract } from "./component-contracts"; import { TOOLCRAFT_PERFORMANCE_VERIFICATION_POLICY, TOOLCRAFT_PERFORMANCE_VERIFICATION_POLICY_TEXT, } from "./performance-verification-policy"; describe("Toolcraft template component contracts: runtime and composition", () => { it("documents app entity acceptance as product-output verification", () => { const contract = getToolcraftComponentContract("appEntityAcceptance"); expect(contract.kind).toBe("composition"); expect(contract.stateMode).toBe("runtime-owned"); expect(contract.capabilities).toContain("product-output-verification"); expect(contract.aiUsageRules).toContain( "Every app entity introduced by the AI must have an acceptance test that proves its product responsibility.", ); expect(contract.aiUsageRules).toContain( "Every supplied video, GIF, screen-recording, contact-sheet, or extracted-frame reference must be registered as a typed referenceInputs item and preprocessed with pnpm reference:study before product code. The protected study performs a full source scan, reviews dense 12 FPS evidence, partitions reviews above 120 frames, classifies every detected event, decomposes complete contiguous phases into behaviors, and maps each behavior bidirectionally to observable acceptance and browser reference-parity coverage. A no-reference app declares referenceInputs: [] and runs no preprocessing.", ); expect(contract.aiUsageRules).toContain( "Compound control browser tests must explicitly exercise each required value part, not only one visible sub-control.", ); expect(contract.aiUsageRules).toContain( "Acceptance tests must fail when an entity is disconnected from runtime state, renderer output, export output, or command side effects.", ); expect(contract.aiUsageRules).toContain( "Built-in control values enter runtime state through one canonical codec for defaults, live edits, persistence, settings import, and keyframes.", ); expect(contract.aiUsageRules).toContain( "Selection-scoped property controls prove two distinct entities: the selected entity changes and the comparison entity remains unchanged in both selection directions.", ); expect(contract.aiUsageRules).toContain( "Do not accept typecheck, component existence, registered commands, runtime state mutation, renderer input objects, shader uniform presence, or signature strings as final proof.", ); expect(contract.aiUsageRules).toContain( "A generic canvas hash difference is not enough for workload or semantic controls; assert the intended direction of the effect.", ); expect(contract.aiUsageRules).toContain( "Component variants are accepted entities too; tests should fail if a non-default Toolcraft control variant falls back to the default variant or custom markup.", ); expect(contract.aiUsageRules).toContain( "Conditional entities require fixtures that make the condition observable.", ); expect(contract.aiUsageRules).toContain( 'Every generated product control declares applicability as mode: "always" or mode: "conditional"; omitted applicability and legacy visibleWhen are runtime compatibility only and fail starter acceptance.', ); expect(contract.aiUsageRules).toContain( "Conditional applicability combines every predicate with AND, hides controls outside mode/type/source/include/variant/count branches, and preserves their runtime values while hidden.", ); expect(contract.aiUsageRules).toContain( "A visible product control must prove its existing product outcome in every supported finite sibling-selector branch from its Control Section Inventory, including always controls and selectors omitted from its predicates.", ); expect(contract.aiUsageRules).toContain( "Do not use schema disabled: true or disabledWhen for generated product availability; runtime primitives may use disabled styling internally, but product controls outside the active branch are absent.", ); expect(contract.aiUsageRules).toContain( "Do not leave inactive conditional controls visible while making the renderer ignore them.", ); expect(contract.aiUsageRules).toContain( "Before controls or canvas interactions, declare typed interactionOwnership for every operation that could plausibly live on either surface. User request, inspected reference, or product usability selects one primary owner.", ); expect(contract.aiUsageRules).toContain( "Do not mirror one operation across canvas and panel, even with different labels, ids, styling, or custom chrome. The same target and operation capability has one surface owner.", ); expect(contract.aiUsageRules).toContain( "Allow complementary operations across surfaces when capabilities differ: canvas selection or direct manipulation may coexist with panel properties, modes, constraints, colors, collections, commands, or exact-value editing.", ); }); it("requires selected-layer properties to use the shared entity-isolation recipe", () => { const contract = getToolcraftComponentContract("layersPanel"); expect(contract.aiUsageRules).toContain( "Every selectedLayer.* control uses the shared two-entity isolation recipe in addition to selected-layer-controls coverage.", ); }); it("requires workload envelopes and render-plan assessment before renderer code", () => { const contract = getToolcraftComponentContract("performanceAcceptance"); const rules = contract.aiUsageRules.join("\n"); expect(contract.kind).toBe("composition"); expect(contract.stateMode).toBe("runtime-owned"); expect(contract.capabilities).toContain("performance-budgets"); expect(contract.capabilities).toContain("workload-control-tests"); expect(rules).toContain( TOOLCRAFT_PERFORMANCE_VERIFICATION_POLICY.functionalInitialDelivery, ); expect(rules).toContain( TOOLCRAFT_PERFORMANCE_VERIFICATION_POLICY.focusedLaterEdits, ); expect(rules).toContain( "On a proven product without new performance authority it exits before inventory, tests, build, browser work, or checkpoint writes.", ); expect(rules).toContain("performance-iteration"); expect(rules).toContain( "Only a localized complaint or a post-clarification targeted choice creates performance-iteration intent", ); expect(rules).toContain( "Classifier output establishes complaint authority only and never path localization", ); expect(rules).toContain( "Regardless of whether the classifier returned high-confidence performance-iteration or needs-agent-judgment, unresolved localization creates neither performance-iteration intent nor canonical path authority", ); expect(rules).toContain( "repetition alone never expands scope or selects the complete performance matrix", ); expect(rules).not.toContain( "One complaint maps to one exact authority-selected targeted performance iteration", ); expect(rules).not.toContain( "Direct and repeated performance complaints each start one bounded targeted iteration", ); expect(rules).toContain( "After two consecutive compatible protected performance iterations, the agent must offer a slower complete audit", ); expect(rules).toContain( "explicit acceptance of the agent's offer, authorizes the agent acting as operator to run pnpm verify:perf", ); expect(contract.aiUsageRules).toContain( "Before renderer code, inventory every reachable control, runtime-state input, and external input, and explicitly mark which ones change workload magnitude; do not infer workload from labels, target names, units, or keywords.", ); expect(contract.aiUsageRules).toContain( "Map every reachable workload role to exactly one numeric workloadEnvelope dimension with a stable id, unit, source, mapping, defaultValue, and every enforced interactiveMax or batchMax boundary.", ); expect(contract.aiUsageRules).toContain( "Treat interactiveMax and batchMax as maximum-workload boundaries, not numerical maxima. Every numeric schema source declares workloadBoundary as minimum or maximum, every declared profile boundary equals that schema endpoint, and a batch-only dimension does not invent an interactive boundary.", ); expect(contract.aiUsageRules).toContain( "Declare only boundary profiles consumed by renderer passes; a control that changes a batch-only dimension keeps targeted control-change coverage without claiming an interactiveMax.", ); expect(contract.aiUsageRules).toContain( "Discrete fixture adapters must declare an exhaustive entries domain that binds every numeric workload value to its applied product value. Schema select/segmented/tabs domains must match every option one-to-one; other finite domains require source-aligned provenance. Development is available only for a reachable combined vector at normalized pressure 0.8 within runtime tolerance; otherwise it is unavailable while maximum remains available. Generic and measured inverse checkpoints are validated against the same exhaustive domain before exact application and observation. Path-level discrete search is deterministic, lazy, and limited by the runtime-owned combination budget; cardinality overflow or an exceeded budget is a planning error, not an unavailable exact vector.", ); expect(contract.aiUsageRules).toContain( "Before renderer code, declare rendererPipeline.runtimeId plus every render pass's cost dimensions, relationship, frequency, lifecycle, execution location, quality, cache keys, and exact interaction invalidation.", ); expect(contract.aiUsageRules).toContain( "Run assessToolcraftRenderPlan before implementation. Resolve every required kernel benchmark with measured full-quality candidate evidence; do not choose renderer technology from a hardcoded product category.", ); expect(contract.aiUsageRules).toContain( "Performance iterations require an exact reachable development fixture at normalized pressure 0.8 and fail with a configuration error when it is unavailable; they never fall back to maximum. Explicit full-performance checkpoints run the complete current matrix with maximum fixtures.", ); expect(contract.aiUsageRules).toContain( "Derive performance paths from rendererPipeline interaction invalidation. Scenarios must reference the canonical pathId and exact coversTargets, and equivalent controls that invalidate the same work share one path.", ); expect(contract.aiUsageRules).toContain( "Compile development and maximum fixtures centrally from each derived path. Combined fixtures contain every path dimension, and measured inverse full-vector evidence is authored only for a custom dimension mapping or benchmark cost relationship.", ); expect(contract.aiUsageRules).toContain( "Browser performance proof must apply compiled fixture values through the real UI, observe every dimension after application, exercise the same preview or export path as the running app, and enforce the path's derived interaction profile.", ); expect(contract.aiUsageRules).toContain( TOOLCRAFT_PERFORMANCE_VERIFICATION_POLICY_TEXT, ); expect(rules).toContain( TOOLCRAFT_PERFORMANCE_VERIFICATION_POLICY.functionalChangeEvidence, ); expect(rules).toContain( TOOLCRAFT_PERFORMANCE_VERIFICATION_POLICY.renderScaleFidelity, ); expect(rules).toContain( TOOLCRAFT_PERFORMANCE_VERIFICATION_POLICY.complaintRouting, ); expect(contract.aiUsageRules).toContain( "Every export performance scenario must declare the exact panelActions actionValue, visible controlLabel, and completionEvidence it exercises; selectors, unrelated export actions, and injectable completion callbacks are not output evidence. The named browser scenario must resolve to test or it imported from @playwright/test, be statically registered at module scope or inside an executable test.describe, test.describe.serial, or test.describe.parallel suite, and directly await the matching unshadowed protected output-action helper in its root callback block without focus, skip, condition, or nesting; local test runners, uncalled or conditional test declarations, skipped/fixme suites, and runtime skip/fixme/fail annotations are invalid, and generated integrity protects the focused-test Playwright config.", ); expect(contract.aiUsageRules).toContain( "Do not create WebGL/WebGPU contexts, shader programs, textures, or requestAnimationFrame loops directly in the React render path.", ); expect(contract.aiUsageRules).toContain( "Animation loops must cancel scheduled frames during cleanup.", ); expect(rules).toMatch(/rendererTechnique/); expect(rules).toMatch(/rendererTechnique\.layers/); expect(rules).toMatch(/rendererPipeline/); expect(rules).toMatch(/sourceRepresentation/); expect(rules).toMatch(/productRepresentation/); expect(rules).toMatch(/previewRenderer/); expect(rules).toMatch(/exportRenderer/); expect(rules).not.toMatch(/1920x1080-equivalent|50_000|1_000\s+lines/); expect(rules).not.toMatch(/rendererWorkload as|stressFixture is|workloadTargets/); }); it("documents reference runtime clone mode as a tested composition contract", () => { const contract = getToolcraftComponentContract("referenceRuntimeClone"); expect(contract.kind).toBe("composition"); expect(contract.schemaType).toBe("transferMode"); expect(contract.visualComponent).toBe("canvasContent"); expect(contract.capabilities).toContain("reference-runtime-clone"); expect(contract.capabilities).toContain("reference-timeline-inventory"); expect(contract.aiUsageRules).toContain( 'Use transferMode: "reference-runtime-clone" when the user asks to port, clone, copy, or reproduce an existing app exactly.', ); expect(contract.aiUsageRules).toContain( "Preserve the reference runtime as the source of truth instead of replacing it with a new renderer or timeline model.", ); expect(contract.aiUsageRules).toContain( "Port requestAnimationFrame loops, refs, mutable particle/object state, connection state, spawn/update cadence, lifetime rules, pause/resume, export/copy, canvas sizing, and media lifecycle when the reference depends on them.", ); expect(contract.aiUsageRules).toContain( "Reference clone timeline choice is based on timeline behavior, not only on whether the reference draws a timeline-shaped UI.", ); expect(contract.aiUsageRules).toContain( "If the reference has Play/Pause, Restart from beginning, current time/progress, duration, loop, scrub, selected range, trim handles, or video export timing, write a Reference Timeline Inventory before choosing a timeline mode.", ); expect(contract.aiUsageRules).toContain( 'Use referenceTimeline.mode "toolcraft-playback" for plain transport behavior such as play/pause, restart, duration/progress, loop, scrub, or export at time.', ); expect(contract.aiUsageRules).toContain( "Reference clone specs must list every detected transport behavior explicitly, including pause-resume, restart, time-progress, export-at-time, playback, scrub, duration, loop, and keyframes when present.", ); expect(contract.aiUsageRules).toContain( 'Toolcraft reference timelines must declare referenceTimeline.loopDuration with source "reference", "user-request", or "product-derived", plus seconds and evidence; runtime/template fallback 8s is not a valid source.', ); expect(contract.aiUsageRules).toContain( "panels.timeline.defaultDurationSeconds must match referenceTimeline.loopDuration.seconds for referenceTimeline.mode toolcraft-playback/toolcraft-keyframes.", ); expect(contract.aiUsageRules).toContain( 'Do not downgrade custom reference timelines to panels.timeline mode "playback". State buttons, trim handles, selected-range playback, or range export require referenceTimeline.mode "custom-reference-timeline" and dedicated acceptance.', ); expect(contract.aiUsageRules).toContain( "Reference clone acceptance must include referenceCoverage rows for canvas sizing, control mapping, renderer state, and any renderer loop, spawn/update cadence, pause/resume, export/copy, or media lifecycle behavior in the reference.", ); expect(contract.aiUsageRules).toContain( "Motion reference assets used in a reference clone must use typed starterTransferMode.referenceInputs with nested studies backed by pnpm reference:study evidence; each study covers the fully scanned source through dense phases, classifies every detected event, maps behaviors through acceptanceId and motionReferenceCoverage, and requires browser reference-parity.", ); }); });