@pixel-point/toolcraft 0.0.16 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/package.json +1 -1
  2. package/src/generate-performance-iteration-execution.test.mjs +2 -2
  3. package/src/generate-test-demand-only-lifecycle.mjs +14 -3
  4. package/src/generate-test-dependency-sandbox.mjs +42 -5
  5. package/src/generate-test-doc-assertions.mjs +68 -18
  6. package/src/generate-test-doc-assertions.test.mjs +22 -0
  7. package/src/generate-test-file-assertions.mjs +43 -76
  8. package/src/generate-test-output-assertions.mjs +95 -0
  9. package/src/generate-test-package-assertions.mjs +6 -0
  10. package/src/generate-test-performance-boundary-assertions.mjs +45 -0
  11. package/src/generate-test-product-fixture.mjs +1 -0
  12. package/src/generate-test-product-fixture.test.mjs +18 -0
  13. package/src/generate-test-product-iteration.mjs +1 -0
  14. package/src/generate-test-product-iteration.test.mjs +1 -0
  15. package/src/generate-test-standalone-delivery-stages.mjs +14 -6
  16. package/src/generate.test.mjs +14 -0
  17. package/templates/runtime/contracts/component-contracts.choices.test.ts +12 -9
  18. package/templates/runtime/contracts/component-contracts.choices.ts +10 -9
  19. package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +17 -2
  20. package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +1 -1
  21. package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +1 -1
  22. package/templates/runtime/contracts/component-contracts.runtime.ts +3 -2
  23. package/templates/runtime/contracts/decision-contracts.test.ts +25 -4
  24. package/templates/runtime/contracts/decision-contracts.ts +3 -3
  25. package/templates/runtime/contracts/performance-verification-policy.test.ts +59 -6
  26. package/templates/runtime/contracts/performance-verification-policy.ts +5 -2
  27. package/templates/runtime/export/artifact-download.test.ts +71 -0
  28. package/templates/runtime/export/artifact-download.ts +80 -0
  29. package/templates/runtime/export/artifact-export-request.ts +23 -0
  30. package/templates/runtime/export/artifact-export-settings.test.ts +75 -0
  31. package/templates/runtime/export/artifact-export-settings.ts +96 -0
  32. package/templates/runtime/export/artifact-frame-renderer.test.ts +107 -0
  33. package/templates/runtime/export/artifact-frame-renderer.ts +96 -0
  34. package/templates/runtime/export/artifact-frame-state.test.ts +54 -0
  35. package/templates/runtime/export/artifact-frame-state.ts +44 -0
  36. package/templates/runtime/export/artifact-scene-frame.test.ts +84 -0
  37. package/templates/runtime/export/artifact-scene-frame.ts +118 -0
  38. package/templates/runtime/export/export-background.ts +65 -0
  39. package/templates/runtime/export/export-error.ts +43 -0
  40. package/templates/runtime/export/export.test.ts +6 -186
  41. package/templates/runtime/export/image-artifact-export.test.ts +111 -0
  42. package/templates/runtime/export/image-artifact-export.ts +145 -0
  43. package/templates/runtime/export/index.ts +14 -1
  44. package/templates/runtime/export/product-export-renderer.test.ts +77 -0
  45. package/templates/runtime/export/product-export-renderer.ts +63 -0
  46. package/templates/runtime/export/video-artifact-export.test.ts +166 -0
  47. package/templates/runtime/export/video-artifact-export.ts +164 -0
  48. package/templates/runtime/export/video-encoding-backend.ts +124 -0
  49. package/templates/runtime/export/video-encoding-policy.test.ts +68 -0
  50. package/templates/runtime/export/video-encoding-policy.ts +86 -0
  51. package/templates/runtime/export/video-frame-schedule.test.ts +58 -0
  52. package/templates/runtime/export/video-frame-schedule.ts +42 -0
  53. package/templates/runtime/index.ts +1 -0
  54. package/templates/runtime/react/app-shell/runtime-public-api-runtime.test.tsx +291 -0
  55. package/templates/runtime/react/app-shell/runtime-public-api-test-support.ts +21 -0
  56. package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +4 -303
  57. package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +12 -27
  58. package/templates/runtime/react/app-shell/toolcraft-app.tsx +22 -4
  59. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.test.tsx +16 -57
  60. package/templates/runtime/react/app-shell/toolcraft-source-asset-context.tsx +75 -434
  61. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.test.ts +194 -0
  62. package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.ts +227 -0
  63. package/templates/runtime/react/app-shell/toolcraft-source-asset-provider-ownership.test.tsx +243 -0
  64. package/templates/runtime/react/app-shell/toolcraft-source-asset-test-support.ts +51 -0
  65. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.test.ts +138 -0
  66. package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.ts +378 -0
  67. package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +7 -12
  68. package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +17 -83
  69. package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +42 -84
  70. package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +62 -0
  71. package/templates/runtime/react/panel-host/panel-host-runtime-placement.test.tsx +30 -0
  72. package/templates/runtime/react/panel-host/panel-host.tsx +4 -0
  73. package/templates/runtime/scene/scene-bounds.ts +1 -2
  74. package/templates/runtime/schema/canvas-render-scale.ts +62 -0
  75. package/templates/runtime/schema/controls-panel-section-id.test.ts +1 -1
  76. package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +3 -3
  77. package/templates/runtime/schema/define-toolcraft.setup-background.test.ts +1 -1
  78. package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +71 -3
  79. package/templates/runtime/schema/define-toolcraft.ts +1 -1
  80. package/templates/runtime/schema/schema-resolvers.ts +0 -56
  81. package/templates/runtime/schema/types.ts +4 -4
  82. package/templates/runtime/state/canvas-background-state.ts +6 -0
  83. package/templates/runtime/testing/performance-render-plan-integration.test.ts +64 -0
  84. package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +18 -1
  85. package/templates/starter/AGENTS.md +8 -7
  86. package/templates/starter/NOTICE.md +6 -0
  87. package/templates/starter/docs/toolcraft/README.md +2 -1
  88. package/templates/starter/docs/toolcraft/acceptance-testing.md +8 -6
  89. package/templates/starter/docs/toolcraft/agent-worklog.md +3 -3
  90. package/templates/starter/docs/toolcraft/assembly-workflow.md +4 -3
  91. package/templates/starter/docs/toolcraft/core/media-upload.md +2 -2
  92. package/templates/starter/docs/toolcraft/core/performance.md +14 -3
  93. package/templates/starter/docs/toolcraft/core/runtime-boundary.md +3 -1
  94. package/templates/starter/docs/toolcraft/core/setup-export.md +16 -12
  95. package/templates/starter/docs/toolcraft/core/timeline-animation.md +4 -4
  96. package/templates/starter/docs/toolcraft/performance.md +20 -6
  97. package/templates/starter/docs/toolcraft/renderer-technique.md +1 -1
  98. package/templates/starter/docs/toolcraft/schema-reference.md +2 -6
  99. package/templates/starter/docs/toolcraft/workflow.md +7 -2
  100. package/templates/starter/e2e/app-browser-control-coverage.spec.ts +33 -0
  101. package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +43 -1
  102. package/templates/starter/e2e/app-browser-render-scale-evidence.spec.ts +60 -6
  103. package/templates/starter/e2e/app-browser-render-scale-requirements.spec.ts +77 -1
  104. package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +8 -0
  105. package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +35 -0
  106. package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +4 -1
  107. package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +0 -1
  108. package/templates/starter/e2e/app-browser-shell.spec.ts +13 -5
  109. package/templates/starter/e2e/app-performance-path-adapters.ts +8 -1
  110. package/templates/starter/e2e/app-performance.spec.ts +16 -9
  111. package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +9 -330
  112. package/templates/starter/e2e/browser-infinity-canvas-unavailable-image-evidence.ts +370 -0
  113. package/templates/starter/e2e/browser-media-export-evidence.spec.ts +77 -0
  114. package/templates/starter/e2e/browser-media-export-evidence.ts +208 -0
  115. package/templates/starter/e2e/browser-render-scale-evidence.ts +37 -29
  116. package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +4 -1
  117. package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +43 -9
  118. package/templates/starter/e2e/browser-standard-timeline-evidence.ts +106 -0
  119. package/templates/starter/e2e/decoded-pixel-observation.spec.ts +74 -0
  120. package/templates/starter/e2e/decoded-pixel-observation.ts +227 -0
  121. package/templates/starter/e2e/export-artifact-helpers.ts +206 -25
  122. package/templates/starter/e2e/image-artifact-inspection.spec.ts +41 -0
  123. package/templates/starter/e2e/image-artifact-inspection.ts +99 -0
  124. package/templates/starter/e2e/performance-canvas-helpers.ts +22 -21
  125. package/templates/starter/e2e/performance-canvas-quality-guard.spec.ts +312 -0
  126. package/templates/starter/e2e/performance-canvas-quality-guard.ts +196 -0
  127. package/templates/starter/e2e/performance-canvas-quality-observer.ts +351 -0
  128. package/templates/starter/e2e/performance-control-layout-helpers.ts +2 -2
  129. package/templates/starter/e2e/performance-path-adapter-contract.ts +4 -4
  130. package/templates/starter/e2e/performance-path-helpers.spec.ts +203 -70
  131. package/templates/starter/e2e/performance-path-helpers.ts +210 -91
  132. package/templates/starter/e2e/performance-pipeline-evidence-continuity.spec.ts +76 -0
  133. package/templates/starter/e2e/performance-pipeline-evidence-test-fixtures.ts +11 -2
  134. package/templates/starter/e2e/performance-pipeline-invariants.ts +47 -4
  135. package/templates/starter/e2e/performance-render-scale-runner.spec.ts +140 -38
  136. package/templates/starter/e2e/video-artifact-inspection.spec.ts +64 -0
  137. package/templates/starter/e2e/video-artifact-inspection.ts +281 -0
  138. package/templates/starter/gitignore +1 -0
  139. package/templates/starter/package.json +1 -0
  140. package/templates/starter/scripts/check-toolcraft-docs.mjs +17 -0
  141. package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +60 -0
  142. package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +7 -2
  143. package/templates/starter/scripts/toolcraft-delivery-plan.mjs +7 -3
  144. package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +24 -2
  145. package/templates/starter/scripts/toolcraft-product-boundary.mjs +12 -0
  146. package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +46 -0
  147. package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +85 -20
  148. package/templates/starter/scripts/toolcraft-product-evidence-import-policy.mjs +43 -0
  149. package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +168 -0
  150. package/templates/starter/scripts/toolcraft-typescript-analysis.d.mts +73 -0
  151. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade-test-helpers.mjs +318 -0
  152. package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +155 -206
  153. package/templates/starter/scripts/toolcraft-verification-inventory.mjs +1 -0
  154. package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +51 -0
  155. package/templates/starter/scripts/toolcraft-vite-env-activation.test.mjs +128 -59
  156. package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +113 -0
  157. package/templates/starter/src/app/acceptance/output-background-rules.ts +1 -1
  158. package/templates/starter/src/app/acceptance/output-export.ts +13 -2
  159. package/templates/starter/src/app/acceptance/types.ts +7 -0
  160. package/templates/starter/src/app/acceptance/validate-coverage.ts +2 -1
  161. package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +131 -0
  162. package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +14 -4
  163. package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +42 -1
  164. package/templates/starter/src/app/starter-acceptance.ts +2 -0
  165. package/templates/starter/src/app/starter-performance-test-utils.ts +103 -0
  166. package/templates/starter/src/app/starter-performance.gates.test.ts +231 -278
  167. package/templates/starter/src/app/starter-performance.lifecycle.test.ts +261 -0
  168. package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +2 -0
  169. package/templates/starter/src/routes/index.tsx +1 -0
  170. package/templates/runtime/export/export.ts +0 -166
@@ -4,7 +4,10 @@ import { deriveToolcraftPerformancePaths } from "@repo/toolcraft-runtime";
4
4
 
5
5
  import { starterPerformance } from "../src/app/starter-performance";
6
6
  import { starterSchema } from "../src/app/starter-schema";
7
- import { appPerformancePathAdapters } from "./app-performance-path-adapters";
7
+ import {
8
+ appPerformanceCanvasBacking,
9
+ appPerformancePathAdapters,
10
+ } from "./app-performance-path-adapters";
8
11
  import {
9
12
  compileToolcraftPerformancePathAdapterMatrix,
10
13
  getToolcraftPerformancePathTestName,
@@ -25,20 +28,24 @@ test("browser perf: toolcraft environment", async ({ page }) => {
25
28
  });
26
29
 
27
30
  test("browser perf: toolcraft adapter catalog", () => {
28
- compileToolcraftPerformancePathAdapterMatrix(
29
- performancePaths,
30
- appPerformancePathAdapters,
31
- );
31
+ compileToolcraftPerformancePathAdapterMatrix({
32
+ adapters: appPerformancePathAdapters,
33
+ canvasBacking: appPerformanceCanvasBacking,
34
+ paths: performancePaths,
35
+ schema: starterSchema,
36
+ });
32
37
  });
33
38
 
34
39
  for (const path of performancePaths) {
35
40
  test(getToolcraftPerformancePathTestName(path), async ({ page }) => {
36
- const [entry] = compileToolcraftPerformancePathAdapterMatrix(
37
- [path],
38
- appPerformancePathAdapters.filter(
41
+ const [entry] = compileToolcraftPerformancePathAdapterMatrix({
42
+ adapters: appPerformancePathAdapters.filter(
39
43
  (adapter) => adapter.pathId === path.id,
40
44
  ),
41
- );
45
+ canvasBacking: appPerformanceCanvasBacking,
46
+ paths: [path],
47
+ schema: starterSchema,
48
+ });
42
49
  if (!entry) {
43
50
  throw new Error(`Missing compiled performance path "${path.id}".`);
44
51
  }
@@ -1,21 +1,15 @@
1
1
  import { expect, type Page } from "@playwright/test";
2
2
 
3
3
  import { attachToolcraftBrowserRuntimeEvidence } from "./browser-runtime-evidence";
4
- import {
5
- assertToolcraftBrowserProofSession,
6
- getToolcraftBrowserActionTarget,
7
- readToolcraftBrowserObservation,
8
- runToolcraftBrowserAction,
9
- runToolcraftBrowserValueAction,
10
- type ToolcraftBrowserAction,
11
- type ToolcraftBrowserObservation,
12
- type ToolcraftBrowserProofSession,
13
- } from "./browser-proof-session";
14
- import {
15
- assertToolcraftProducedArtifact,
16
- validateToolcraftExportArtifactInspection,
17
- type ToolcraftExportArtifactInspection,
18
- } from "./export-artifact-helpers";
4
+
5
+ export {
6
+ createToolcraftUnavailableImageResourceFixture,
7
+ expectToolcraftInfinityCanvasUnavailableImageExportEvidence,
8
+ } from "./browser-infinity-canvas-unavailable-image-evidence";
9
+ export type {
10
+ ToolcraftUnavailableImageResourceFixture,
11
+ ToolcraftUnavailableImageResourceObservation,
12
+ } from "./browser-infinity-canvas-unavailable-image-evidence";
19
13
 
20
14
  export type InfinityCanvasObservation = Readonly<{
21
15
  artboardPresent: boolean;
@@ -367,321 +361,6 @@ export async function expectToolcraftInfinityCanvasImageExportEvidence(
367
361
  });
368
362
  }
369
363
 
370
- declare const toolcraftUnavailableImageResourceFixtureBrand: unique symbol;
371
-
372
- export type ToolcraftUnavailableImageResourceObservation = Readonly<{
373
- assetId?: string;
374
- fileName?: string;
375
- lifecycle?: "ready" | "unavailable";
376
- message?: string;
377
- requestId?: string;
378
- resolverAvailable?: boolean;
379
- status: "active" | "cleaned" | "error" | "missing";
380
- }>;
381
-
382
- export type ToolcraftUnavailableImageResourceFixture = Readonly<{
383
- readonly [toolcraftUnavailableImageResourceFixtureBrand]: true;
384
- }>;
385
-
386
- type ToolcraftUnavailableImageResourceFixtureRecord = Readonly<{
387
- activate: ToolcraftBrowserAction;
388
- cleanup: ToolcraftBrowserAction;
389
- fileName: string;
390
- observe: ToolcraftBrowserObservation<ToolcraftUnavailableImageResourceObservation>;
391
- requestId: string;
392
- session: ToolcraftBrowserProofSession;
393
- target: string;
394
- }>;
395
-
396
- const unavailableImageResourceFixtureRecords = new WeakMap<
397
- object,
398
- ToolcraftUnavailableImageResourceFixtureRecord
399
- >();
400
- let unavailableImageResourceFixtureSequence = 0;
401
-
402
- function requireUnavailableImageResourceFixture(
403
- fixture: ToolcraftUnavailableImageResourceFixture,
404
- ): ToolcraftUnavailableImageResourceFixtureRecord {
405
- const record =
406
- typeof fixture === "object" && fixture !== null
407
- ? unavailableImageResourceFixtureRecords.get(fixture)
408
- : undefined;
409
- if (!record) {
410
- throw new Error(
411
- "Unavailable-image export evidence requires the protected Toolcraft unavailable-resource fixture facade.",
412
- );
413
- }
414
- return record;
415
- }
416
-
417
- function validateUnavailableImageResourceObservation(
418
- observation: ToolcraftUnavailableImageResourceObservation,
419
- expected: Readonly<{
420
- fileName: string;
421
- requestId: string;
422
- status: "active" | "cleaned";
423
- }>,
424
- ): void {
425
- if (observation.status === "error") {
426
- throw new Error(
427
- observation.message ??
428
- "The Toolcraft unavailable-resource proof fixture failed.",
429
- );
430
- }
431
- expect(
432
- observation,
433
- `Unavailable-resource proof "${expected.requestId}" must publish its exact typed state.`,
434
- ).toMatchObject(
435
- expected.status === "active"
436
- ? {
437
- fileName: expected.fileName,
438
- lifecycle: "unavailable",
439
- requestId: expected.requestId,
440
- resolverAvailable: false,
441
- status: "active",
442
- }
443
- : {
444
- fileName: expected.fileName,
445
- lifecycle: "ready",
446
- requestId: expected.requestId,
447
- resolverAvailable: true,
448
- status: "cleaned",
449
- },
450
- );
451
- expect(
452
- observation.assetId?.trim(),
453
- "Unavailable-resource proof must identify the exact affected runtime asset.",
454
- ).toBeTruthy();
455
- }
456
-
457
- export function createToolcraftUnavailableImageResourceFixture(
458
- session: ToolcraftBrowserProofSession,
459
- {
460
- fileName,
461
- sourceTarget,
462
- target,
463
- }: Readonly<{
464
- fileName: string;
465
- sourceTarget?: string;
466
- target: string;
467
- }>,
468
- ): ToolcraftUnavailableImageResourceFixture {
469
- const normalizedFileName = fileName.trim();
470
- const normalizedSourceTarget = sourceTarget?.trim();
471
- const normalizedTarget = target.trim();
472
- expect(
473
- normalizedFileName,
474
- "Unavailable-resource proof requires an exact non-empty image file name.",
475
- ).not.toBe("");
476
- expect(
477
- normalizedTarget,
478
- "Unavailable-resource proof requires an exact semantic acceptance target.",
479
- ).not.toBe("");
480
- if (sourceTarget !== undefined) {
481
- expect(
482
- normalizedSourceTarget,
483
- "Unavailable-resource proof sourceTarget must be non-empty when provided.",
484
- ).not.toBe("");
485
- }
486
-
487
- const requestId =
488
- `unavailable-image-${++unavailableImageResourceFixtureSequence}`;
489
- const request = {
490
- fileName: normalizedFileName,
491
- requestId,
492
- ...(normalizedSourceTarget
493
- ? { sourceTarget: normalizedSourceTarget }
494
- : {}),
495
- };
496
- const runRequest = (
497
- action: "activate" | "cleanup",
498
- expectedStatus: "active" | "cleaned",
499
- ) =>
500
- session.targetAction(normalizedTarget, async (page) => {
501
- await page.evaluate(
502
- ({ detail, eventName }) => {
503
- document.dispatchEvent(
504
- new CustomEvent(eventName, {
505
- detail,
506
- }),
507
- );
508
- },
509
- {
510
- detail: { ...request, action },
511
- eventName:
512
- "toolcraft.browser-proof.unavailable-resource-request",
513
- },
514
- );
515
- await expect
516
- .poll(
517
- async () => {
518
- const raw = await page
519
- .locator('[data-slot="toolcraft-runtime-app"]')
520
- .getAttribute(
521
- "data-toolcraft-unavailable-resource-evidence",
522
- );
523
- if (!raw) return "missing";
524
- const observation = JSON.parse(
525
- raw,
526
- ) as ToolcraftUnavailableImageResourceObservation;
527
- if (
528
- observation.requestId === requestId &&
529
- observation.status === "error"
530
- ) {
531
- throw new Error(
532
- observation.message ??
533
- "The Toolcraft unavailable-resource proof fixture failed.",
534
- );
535
- }
536
- return observation.requestId === requestId
537
- ? observation.status
538
- : "other-request";
539
- },
540
- {
541
- message:
542
- `Unavailable-resource proof "${requestId}" should reach ${expectedStatus}.`,
543
- },
544
- )
545
- .toBe(expectedStatus);
546
- });
547
- const activate = runRequest("activate", "active");
548
- const cleanup = runRequest("cleanup", "cleaned");
549
- const observe = session.observe((root) => {
550
- const raw = root.getAttribute(
551
- "data-toolcraft-unavailable-resource-evidence",
552
- );
553
- if (!raw) {
554
- return { status: "missing" as const };
555
- }
556
- try {
557
- return JSON.parse(
558
- raw,
559
- ) as ToolcraftUnavailableImageResourceObservation;
560
- } catch {
561
- return {
562
- message: "Unavailable-resource proof published malformed state.",
563
- status: "error" as const,
564
- };
565
- }
566
- });
567
- const fixture = Object.freeze({}) as ToolcraftUnavailableImageResourceFixture;
568
- unavailableImageResourceFixtureRecords.set(fixture, {
569
- activate,
570
- cleanup,
571
- fileName: normalizedFileName,
572
- observe,
573
- requestId,
574
- session,
575
- target: normalizedTarget,
576
- });
577
- return fixture;
578
- }
579
-
580
- export async function expectToolcraftInfinityCanvasUnavailableImageExportEvidence<
581
- TArtifact,
582
- >(
583
- fixture: ToolcraftUnavailableImageResourceFixture,
584
- produceArtifact: ToolcraftBrowserAction<"interaction", TArtifact>,
585
- inspectArtifact: (
586
- artifact: TArtifact,
587
- ) => Promise<ToolcraftExportArtifactInspection> | ToolcraftExportArtifactInspection,
588
- {
589
- expectedSize,
590
- requirementId,
591
- }: Readonly<{
592
- expectedSize: Readonly<{ height: number; width: number }>;
593
- requirementId: string;
594
- }>,
595
- ): Promise<ToolcraftExportArtifactInspection> {
596
- const record = requireUnavailableImageResourceFixture(fixture);
597
- assertToolcraftBrowserProofSession(
598
- record.observe,
599
- record.activate,
600
- record.cleanup,
601
- produceArtifact,
602
- );
603
- const exportTarget = getToolcraftBrowserActionTarget(produceArtifact)?.trim();
604
- expect(
605
- exportTarget,
606
- "Unavailable-image export evidence requires a target-scoped artifact action.",
607
- ).toBe(record.target);
608
-
609
- let activationAttempted = false;
610
- let cleanupSucceeded = false;
611
- let inspection: ToolcraftExportArtifactInspection | null = null;
612
- let outputVerified = false;
613
- try {
614
- activationAttempted = true;
615
- await runToolcraftBrowserAction(record.activate);
616
- validateUnavailableImageResourceObservation(
617
- await readToolcraftBrowserObservation(record.observe),
618
- {
619
- fileName: record.fileName,
620
- requestId: record.requestId,
621
- status: "active",
622
- },
623
- );
624
-
625
- const artifact = await runToolcraftBrowserValueAction(produceArtifact);
626
- assertToolcraftProducedArtifact(artifact, requirementId);
627
- inspection = await inspectArtifact(artifact);
628
- validateToolcraftExportArtifactInspection(inspection, requirementId);
629
- expect(
630
- inspection,
631
- `Unavailable-image export "${requirementId}" must decode to the expected visible scene bounds.`,
632
- ).toMatchObject(expectedSize);
633
- validateUnavailableImageResourceObservation(
634
- await readToolcraftBrowserObservation(record.observe),
635
- {
636
- fileName: record.fileName,
637
- requestId: record.requestId,
638
- status: "active",
639
- },
640
- );
641
- outputVerified = true;
642
- } finally {
643
- const current = activationAttempted
644
- ? await readToolcraftBrowserObservation(record.observe)
645
- : null;
646
- if (
647
- current?.requestId === record.requestId &&
648
- current.status === "active"
649
- ) {
650
- await runToolcraftBrowserAction(record.cleanup);
651
- validateUnavailableImageResourceObservation(
652
- await readToolcraftBrowserObservation(record.observe),
653
- {
654
- fileName: record.fileName,
655
- requestId: record.requestId,
656
- status: "cleaned",
657
- },
658
- );
659
- cleanupSucceeded = true;
660
- } else if (outputVerified) {
661
- throw new Error(
662
- "Unavailable-image export evidence requires the exact active fixture to remain available for deterministic cleanup.",
663
- );
664
- }
665
- }
666
-
667
- if (!cleanupSucceeded || !inspection) {
668
- throw new Error(
669
- "Unavailable-image export evidence requires successful fixture cleanup before publication.",
670
- );
671
- }
672
- await attachToolcraftBrowserRuntimeEvidence({
673
- evidenceType: "exported-artifact",
674
- requirementId,
675
- target: exportTarget,
676
- });
677
- await attachToolcraftBrowserRuntimeEvidence({
678
- evidenceType: "infinity-scene-bounds-image-export",
679
- requirementId,
680
- target: exportTarget,
681
- });
682
- return inspection;
683
- }
684
-
685
364
  export async function expectToolcraftInfinityCanvasVideoExportEvidence(
686
365
  artifacts: Readonly<{
687
366
  finite: Readonly<{