@pixel-point/toolcraft 0.0.16 → 0.0.18
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.
- package/package.json +1 -1
- package/src/generate-performance-iteration-execution.test.mjs +2 -2
- package/src/generate-test-demand-only-lifecycle.mjs +14 -3
- package/src/generate-test-dependency-sandbox.mjs +42 -5
- package/src/generate-test-doc-assertions.mjs +109 -69
- package/src/generate-test-doc-assertions.test.mjs +65 -0
- package/src/generate-test-doc-policy-assertions.mjs +92 -0
- package/src/generate-test-file-assertions.mjs +36 -118
- package/src/generate-test-output-assertions.mjs +95 -0
- package/src/generate-test-package-assertions.mjs +6 -0
- package/src/generate-test-performance-boundary-assertions.mjs +45 -0
- package/src/generate-test-product-fixture.mjs +1 -0
- package/src/generate-test-product-fixture.test.mjs +18 -0
- package/src/generate-test-product-iteration.mjs +1 -0
- package/src/generate-test-product-iteration.test.mjs +18 -0
- package/src/generate-test-runtime-boundary-assertions.mjs +158 -0
- package/src/generate-test-standalone-assertions.mjs +10 -0
- package/src/generate-test-standalone-delivery-stages.mjs +14 -6
- package/src/generate.test.mjs +14 -0
- package/templates/runtime/contracts/component-contracts.choices.test.ts +59 -12
- package/templates/runtime/contracts/component-contracts.choices.ts +58 -12
- package/templates/runtime/contracts/component-contracts.inputs.test.ts +6 -6
- package/templates/runtime/contracts/component-contracts.inputs.ts +6 -6
- package/templates/runtime/contracts/component-contracts.media-custom.test.ts +8 -2
- package/templates/runtime/contracts/component-contracts.media-custom.ts +8 -2
- package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +21 -6
- package/templates/runtime/contracts/component-contracts.runtime-labels.test.ts +7 -1
- package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +4 -1
- package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +4 -1
- package/templates/runtime/contracts/component-contracts.runtime.ts +15 -10
- package/templates/runtime/contracts/component-contracts.test.ts +2 -0
- package/templates/runtime/contracts/decision-contracts.test.ts +43 -4
- package/templates/runtime/contracts/decision-contracts.ts +10 -10
- package/templates/runtime/contracts/performance-verification-policy.test.ts +59 -6
- package/templates/runtime/contracts/performance-verification-policy.ts +5 -2
- package/templates/runtime/export/artifact-download.test.ts +71 -0
- package/templates/runtime/export/artifact-download.ts +80 -0
- package/templates/runtime/export/artifact-export-request.ts +23 -0
- package/templates/runtime/export/artifact-export-settings.test.ts +75 -0
- package/templates/runtime/export/artifact-export-settings.ts +96 -0
- package/templates/runtime/export/artifact-frame-renderer.test.ts +107 -0
- package/templates/runtime/export/artifact-frame-renderer.ts +96 -0
- package/templates/runtime/export/artifact-frame-state.test.ts +54 -0
- package/templates/runtime/export/artifact-frame-state.ts +44 -0
- package/templates/runtime/export/artifact-scene-frame.test.ts +84 -0
- package/templates/runtime/export/artifact-scene-frame.ts +118 -0
- package/templates/runtime/export/export-background.ts +46 -0
- package/templates/runtime/export/export-error.ts +43 -0
- package/templates/runtime/export/export.test.ts +49 -226
- package/templates/runtime/export/image-artifact-export.test.ts +111 -0
- package/templates/runtime/export/image-artifact-export.ts +145 -0
- package/templates/runtime/export/index.ts +44 -3
- package/templates/runtime/export/product-export-renderer.test.ts +77 -0
- package/templates/runtime/export/product-export-renderer.ts +63 -0
- package/templates/runtime/export/video-artifact-export.test.ts +166 -0
- package/templates/runtime/export/video-artifact-export.ts +164 -0
- package/templates/runtime/export/video-encoding-backend.ts +124 -0
- package/templates/runtime/export/video-encoding-policy.test.ts +68 -0
- package/templates/runtime/export/video-encoding-policy.ts +86 -0
- package/templates/runtime/export/video-frame-schedule.test.ts +58 -0
- package/templates/runtime/export/video-frame-schedule.ts +42 -0
- package/templates/runtime/index.ts +3 -0
- package/templates/runtime/model-import/model-import-limits.ts +15 -4
- package/templates/runtime/react/app-shell/runtime-public-api-runtime.test.tsx +291 -0
- package/templates/runtime/react/app-shell/runtime-public-api-test-support.ts +21 -0
- package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +15 -304
- package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +41 -27
- package/templates/runtime/react/app-shell/toolcraft-app.tsx +39 -11
- package/templates/runtime/react/app-shell/toolcraft-source-asset-context.test.tsx +16 -57
- package/templates/runtime/react/app-shell/toolcraft-source-asset-context.tsx +75 -434
- package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.test.ts +194 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.ts +227 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-provider-ownership.test.tsx +243 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-test-support.ts +51 -0
- package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.test.ts +138 -0
- package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.ts +378 -0
- package/templates/runtime/react/canvas/canvas-shell-rendering.test.tsx +76 -0
- package/templates/runtime/react/canvas/canvas-shell-test-utils.tsx +13 -1
- package/templates/runtime/react/canvas/canvas-shell.tsx +16 -1
- package/templates/runtime/react/canvas/product-scene-surface.test.tsx +195 -0
- package/templates/runtime/react/canvas/product-scene-surface.tsx +155 -0
- package/templates/runtime/react/canvas/runtime-scene-export.ts +1 -1
- package/templates/runtime/react/controls-panel/__tests__/control-conditions.test.ts +61 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.collection-actions.test.tsx +89 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.control-visibility.test.tsx +40 -19
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +7 -12
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +18 -84
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-collection.test.tsx +62 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.source-color-bank.test.tsx +67 -0
- package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +43 -87
- package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +68 -0
- package/templates/runtime/react/controls-panel/conditions/control-conditions.ts +32 -119
- package/templates/runtime/react/controls-panel/layout/controls-panel-control-group.tsx +5 -2
- package/templates/runtime/react/controls-panel/layout/controls-panel-layout.tsx +10 -8
- package/templates/runtime/react/controls-panel/layout/controls-panel-section.tsx +3 -3
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.test.tsx +63 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-item-fields.tsx +138 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-items.tsx +104 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-collection-renderer.tsx +115 -236
- package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.test.tsx +95 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-file-drop-item-controls.tsx +82 -0
- package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.test.tsx +73 -1
- package/templates/runtime/react/controls-panel/renderers/controls-panel-media-renderer.tsx +50 -1
- package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.test.ts +1 -1
- package/templates/runtime/react/controls-panel/renderers/controls-panel-renderer-registry.ts +2 -1
- package/templates/runtime/react/controls-panel/values/controls-panel-collection-values.ts +38 -6
- package/templates/runtime/react/controls-panel/values/controls-panel-value-labels.ts +1 -0
- package/templates/runtime/react/index.ts +4 -0
- package/templates/runtime/react/model-rendering/model-export.ts +1 -1
- package/templates/runtime/react/orientation-gizmo/orientation-gizmo-selection.ts +5 -5
- package/templates/runtime/react/orientation-gizmo/use-toolcraft-orientation-control-selection.ts +2 -2
- package/templates/runtime/react/panel-host/panel-host-runtime-placement.test.tsx +30 -0
- package/templates/runtime/react/panel-host/panel-host.tsx +4 -0
- package/templates/runtime/scene/scene-bounds.test.ts +23 -0
- package/templates/runtime/scene/scene-bounds.ts +32 -19
- package/templates/runtime/schema/app-capabilities.test.ts +4 -0
- package/templates/runtime/schema/canvas-render-scale.ts +62 -0
- package/templates/runtime/schema/collection-item-controls.ts +29 -0
- package/templates/runtime/schema/control-applicability.test.ts +127 -0
- package/templates/runtime/schema/control-applicability.ts +433 -0
- package/templates/runtime/schema/control-schema-normalization.ts +177 -11
- package/templates/runtime/schema/controls-panel-actions.ts +2 -2
- package/templates/runtime/schema/controls-panel-section-id.test.ts +1 -1
- package/templates/runtime/schema/controls-panel-section-layout.ts +14 -9
- package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +62 -3
- package/templates/runtime/schema/define-toolcraft.collection-actions-item-controls.test.ts +127 -0
- package/templates/runtime/schema/define-toolcraft.control-sections.test.ts +10 -4
- package/templates/runtime/schema/define-toolcraft.file-drop-item-controls.test.ts +98 -0
- package/templates/runtime/schema/define-toolcraft.file-drop-normalization.test.ts +27 -0
- package/templates/runtime/schema/define-toolcraft.segmented-control-fit.test.ts +20 -2
- package/templates/runtime/schema/define-toolcraft.setup-background.test.ts +1 -1
- package/templates/runtime/schema/define-toolcraft.setup-canvas.test.ts +16 -3
- package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +71 -3
- package/templates/runtime/schema/define-toolcraft.source-collection.test.ts +79 -0
- package/templates/runtime/schema/define-toolcraft.ts +1 -1
- package/templates/runtime/schema/runtime-setup-section.ts +24 -5
- package/templates/runtime/schema/schema-resolvers.ts +0 -56
- package/templates/runtime/schema/types.ts +72 -17
- package/templates/runtime/state/canvas-background-state.ts +6 -0
- package/templates/runtime/testing/performance-render-plan-integration.test.ts +64 -0
- package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +18 -1
- package/templates/starter/AGENTS.md +18 -15
- package/templates/starter/NOTICE.md +6 -0
- package/templates/starter/docs/toolcraft/README.md +2 -1
- package/templates/starter/docs/toolcraft/acceptance-testing.md +23 -35
- package/templates/starter/docs/toolcraft/agent-worklog.md +18 -3
- package/templates/starter/docs/toolcraft/assembly-workflow.md +13 -5
- package/templates/starter/docs/toolcraft/component-rules.md +8 -6
- package/templates/starter/docs/toolcraft/core/control-selection.md +9 -3
- package/templates/starter/docs/toolcraft/core/layout.md +7 -7
- package/templates/starter/docs/toolcraft/core/media-upload.md +4 -2
- package/templates/starter/docs/toolcraft/core/performance.md +14 -3
- package/templates/starter/docs/toolcraft/core/runtime-boundary.md +16 -3
- package/templates/starter/docs/toolcraft/core/setup-export.md +49 -19
- package/templates/starter/docs/toolcraft/core/timeline-animation.md +4 -4
- package/templates/starter/docs/toolcraft/custom-controls.md +6 -4
- package/templates/starter/docs/toolcraft/decision-contract.md +3 -1
- package/templates/starter/docs/toolcraft/performance.md +20 -6
- package/templates/starter/docs/toolcraft/renderer-technique.md +5 -1
- package/templates/starter/docs/toolcraft/schema-reference.md +23 -25
- package/templates/starter/docs/toolcraft/workflow.md +7 -2
- package/templates/starter/e2e/app-browser-control-applicability-requirements.spec.ts +163 -0
- package/templates/starter/e2e/app-browser-control-coverage.spec.ts +33 -0
- package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +50 -3
- package/templates/starter/e2e/app-browser-orientation-evidence.spec.ts +174 -21
- package/templates/starter/e2e/app-browser-render-scale-evidence.spec.ts +60 -6
- package/templates/starter/e2e/app-browser-render-scale-requirements.spec.ts +77 -1
- package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +8 -0
- package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +35 -0
- package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +5 -34
- package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +61 -16
- package/templates/starter/e2e/app-browser-shell.spec.ts +13 -5
- package/templates/starter/e2e/app-performance-path-adapters.ts +8 -1
- package/templates/starter/e2e/app-performance.spec.ts +16 -9
- package/templates/starter/e2e/{browser-conditional-output-evidence-helpers.ts → browser-background-output-evidence.ts} +0 -68
- package/templates/starter/e2e/browser-control-applicability-evidence.ts +114 -0
- package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +29 -341
- package/templates/starter/e2e/browser-infinity-canvas-unavailable-image-evidence.ts +370 -0
- package/templates/starter/e2e/browser-media-export-evidence.spec.ts +77 -0
- package/templates/starter/e2e/browser-media-export-evidence.ts +208 -0
- package/templates/starter/e2e/browser-orientation-gizmo-evidence-helpers.ts +4 -0
- package/templates/starter/e2e/browser-orientation-gizmo-live-preconditions.ts +86 -0
- package/templates/starter/e2e/browser-render-scale-evidence.ts +37 -29
- package/templates/starter/e2e/browser-runtime-applicability-requirements.ts +84 -0
- package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +13 -3
- package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +72 -35
- package/templates/starter/e2e/browser-semantic-evidence-test-helpers.ts +25 -0
- package/templates/starter/e2e/browser-standard-timeline-evidence.ts +106 -0
- package/templates/starter/e2e/decoded-pixel-observation.spec.ts +74 -0
- package/templates/starter/e2e/decoded-pixel-observation.ts +227 -0
- package/templates/starter/e2e/export-artifact-helpers.ts +206 -25
- package/templates/starter/e2e/image-artifact-inspection.spec.ts +41 -0
- package/templates/starter/e2e/image-artifact-inspection.ts +99 -0
- package/templates/starter/e2e/performance-canvas-helpers.ts +22 -21
- package/templates/starter/e2e/performance-canvas-quality-guard.spec.ts +312 -0
- package/templates/starter/e2e/performance-canvas-quality-guard.ts +196 -0
- package/templates/starter/e2e/performance-canvas-quality-observer.ts +351 -0
- package/templates/starter/e2e/performance-control-layout-helpers.ts +2 -2
- package/templates/starter/e2e/performance-path-adapter-contract.ts +4 -4
- package/templates/starter/e2e/performance-path-helpers.spec.ts +203 -70
- package/templates/starter/e2e/performance-path-helpers.ts +210 -91
- package/templates/starter/e2e/performance-pipeline-evidence-continuity.spec.ts +76 -0
- package/templates/starter/e2e/performance-pipeline-evidence-test-fixtures.ts +11 -2
- package/templates/starter/e2e/performance-pipeline-invariants.ts +47 -4
- package/templates/starter/e2e/performance-render-scale-runner.spec.ts +140 -38
- package/templates/starter/e2e/video-artifact-inspection.spec.ts +64 -0
- package/templates/starter/e2e/video-artifact-inspection.ts +281 -0
- package/templates/starter/gitignore +1 -0
- package/templates/starter/package.json +1 -0
- package/templates/starter/scripts/check-toolcraft-docs.mjs +17 -0
- package/templates/starter/scripts/toolcraft-contract-manifest.json +1 -0
- package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +60 -0
- package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +7 -2
- package/templates/starter/scripts/toolcraft-delivery-plan.mjs +7 -3
- package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +95 -103
- package/templates/starter/scripts/toolcraft-product-boundary-module-policy.mjs +101 -0
- package/templates/starter/scripts/toolcraft-product-boundary.mjs +12 -0
- package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +0 -26
- package/templates/starter/scripts/toolcraft-product-control-bindings.mjs +182 -0
- package/templates/starter/scripts/toolcraft-product-control-boundary.mjs +146 -0
- package/templates/starter/scripts/toolcraft-product-control-boundary.test.mjs +186 -0
- package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +85 -20
- package/templates/starter/scripts/toolcraft-product-evidence-import-policy.mjs +43 -0
- package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +157 -0
- package/templates/starter/scripts/toolcraft-product-export-boundary.test.mjs +196 -0
- package/templates/starter/scripts/toolcraft-typescript-analysis.d.mts +73 -0
- package/templates/starter/scripts/toolcraft-typescript-source-evidence-structure.test.mjs +20 -0
- package/templates/starter/scripts/toolcraft-typescript-source-evidence.mjs +1 -0
- package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade-test-helpers.mjs +318 -0
- package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +157 -206
- package/templates/starter/scripts/toolcraft-verification-inventory.mjs +1 -0
- package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +51 -0
- package/templates/starter/scripts/toolcraft-vite-env-activation.test.mjs +128 -59
- package/templates/starter/src/app/acceptance/artifact-export-intent.ts +130 -0
- package/templates/starter/src/app/acceptance/conditions.ts +1 -1
- package/templates/starter/src/app/acceptance/control-acceptance-context.ts +2 -2
- package/templates/starter/src/app/acceptance/control-acceptance-coverage.ts +6 -20
- package/templates/starter/src/app/acceptance/control-acceptance-kind-rules.ts +24 -5
- package/templates/starter/src/app/acceptance/control-acceptance-policy.ts +2 -13
- package/templates/starter/src/app/acceptance/control-applicability-cases.test.ts +321 -0
- package/templates/starter/src/app/acceptance/control-applicability-cases.ts +290 -0
- package/templates/starter/src/app/acceptance/control-applicability.ts +332 -0
- package/templates/starter/src/app/acceptance/control-layout-dependency-rules.ts +20 -9
- package/templates/starter/src/app/acceptance/control-layout-entity-rules.ts +4 -6
- package/templates/starter/src/app/acceptance/control-layout-model.ts +4 -4
- package/templates/starter/src/app/acceptance/control-layout-section-rules.ts +3 -10
- package/templates/starter/src/app/acceptance/control-parts.ts +8 -0
- package/templates/starter/src/app/acceptance/control-section-entity-cohesion.test.ts +215 -0
- package/templates/starter/src/app/acceptance/control-section-entity-cohesion.ts +132 -0
- package/templates/starter/src/app/acceptance/control-section-inventory.test.ts +87 -0
- package/templates/starter/src/app/acceptance/control-section-inventory.ts +74 -44
- package/templates/starter/src/app/acceptance/custom-controls.ts +11 -3
- package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +113 -0
- package/templates/starter/src/app/acceptance/inline-layout.ts +64 -9
- package/templates/starter/src/app/acceptance/media-upload.ts +5 -1
- package/templates/starter/src/app/acceptance/orientation-gizmo.ts +18 -11
- package/templates/starter/src/app/acceptance/output-background-rules.ts +2 -2
- package/templates/starter/src/app/acceptance/output-export-layout-rules.ts +18 -10
- package/templates/starter/src/app/acceptance/output-export-model.ts +54 -11
- package/templates/starter/src/app/acceptance/output-export.ts +35 -12
- package/templates/starter/src/app/acceptance/output-video-export-rules.ts +99 -0
- package/templates/starter/src/app/acceptance/types.ts +30 -8
- package/templates/starter/src/app/acceptance/validate-coverage.ts +20 -2
- package/templates/starter/src/app/starter-acceptance.artifact-export-intent.test.ts +239 -0
- package/templates/starter/src/app/starter-acceptance.background-export.test.ts +33 -0
- package/templates/starter/src/app/starter-acceptance.canvas-sizing.test.ts +16 -1
- package/templates/starter/src/app/starter-acceptance.compound-part-coverage.test.ts +65 -0
- package/templates/starter/src/app/starter-acceptance.contract-fixtures.test.ts +41 -0
- package/templates/starter/src/app/starter-acceptance.contract-fixtures.ts +112 -16
- package/templates/starter/src/app/starter-acceptance.control-applicability.test.ts +224 -0
- package/templates/starter/src/app/starter-acceptance.control-order.test.ts +58 -3
- package/templates/starter/src/app/starter-acceptance.control-state.test.ts +0 -111
- package/templates/starter/src/app/starter-acceptance.custom-control-collections.test.ts +3 -1
- package/templates/starter/src/app/starter-acceptance.custom-control-valid.test.ts +1 -1
- package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +131 -0
- package/templates/starter/src/app/starter-acceptance.export-test-utils.ts +22 -0
- package/templates/starter/src/app/{starter-acceptance.image-video-export-settings.test.ts → starter-acceptance.image-export-settings.test.ts} +37 -9
- package/templates/starter/src/app/starter-acceptance.interaction-ownership.test.ts +12 -0
- package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +14 -4
- package/templates/starter/src/app/starter-acceptance.media-upload.fixtures.ts +11 -1
- package/templates/starter/src/app/starter-acceptance.media-upload.test.ts +28 -0
- package/templates/starter/src/app/starter-acceptance.output-export-intent.test.ts +384 -0
- package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +46 -1
- package/templates/starter/src/app/starter-acceptance.product-output-export.test.ts +112 -105
- package/templates/starter/src/app/starter-acceptance.product-readiness.test.ts +12 -0
- package/templates/starter/src/app/starter-acceptance.section-cohesion.test.ts +1 -1
- package/templates/starter/src/app/starter-acceptance.section-dependencies.test.ts +35 -24
- package/templates/starter/src/app/starter-acceptance.section-size.test.ts +72 -0
- package/templates/starter/src/app/starter-acceptance.ts +13 -2
- package/templates/starter/src/app/starter-acceptance.video-export-settings.test.ts +336 -0
- package/templates/starter/src/app/starter-acceptance.view-interaction.test.ts +8 -0
- package/templates/starter/src/app/starter-performance-test-utils.ts +103 -0
- package/templates/starter/src/app/starter-performance.gates.test.ts +231 -278
- package/templates/starter/src/app/starter-performance.lifecycle.test.ts +261 -0
- package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +4 -2
- package/templates/starter/src/routes/index.tsx +2 -0
- package/templates/ui/components/composites/tabs.tsx +2 -2
- package/templates/ui/components/controls/collection-actions/collection-item-groups.test.tsx +38 -0
- package/templates/ui/components/controls/collection-actions/collection-item-groups.tsx +36 -0
- package/templates/ui/components/controls/collection-actions/index.ts +2 -0
- package/templates/ui/components/controls/file-drop/file-drop-collection-control.tsx +137 -0
- package/templates/ui/components/controls/file-drop/file-drop-control.test.tsx +189 -0
- package/templates/ui/components/controls/file-drop/file-drop-control.tsx +81 -88
- package/templates/ui/components/controls/file-drop/file-drop-presentation.tsx +131 -9
- package/templates/ui/components/controls/file-drop/file-drop-types.ts +36 -22
- package/templates/ui/components/controls/file-drop/index.ts +1 -0
- package/templates/ui/components/controls/index.ts +3 -0
- package/templates/ui/components/controls/range-slider/range-slider-control.tsx +1 -1
- package/templates/ui/components/controls/range-slider/range-slider-value.test.ts +14 -0
- package/templates/ui/components/controls/range-slider/range-slider-value.ts +3 -2
- package/templates/runtime/export/export.ts +0 -166
- package/templates/starter/src/app/acceptance/condition-exclusivity.test.ts +0 -60
- package/templates/starter/src/app/acceptance/condition-exclusivity.ts +0 -221
|
@@ -27,6 +27,10 @@ Do not write renderer code before the envelope, `rendererTechnique`, pipeline, a
|
|
|
27
27
|
- Prefer retained resources and stable cache keys. Source-bound resources live outside React render, survive unrelated interactions according to pass lifecycle, and release during cleanup.
|
|
28
28
|
- Separate layers when they have different semantics, invalidation, lifecycle, interaction, or export treatment. A costly layer does not force unrelated output into the same renderer.
|
|
29
29
|
- Preserve selected quality, product boundaries, backing resolution, and source fidelity. A renderer is not accepted by silently reducing them.
|
|
30
|
+
- In infinite mode, custom Canvas 2D, WebGL, and WebGPU previews use `useToolcraftProductSceneFrame()` as their backing and coordinate frame. Do not keep rendering into dormant finite `canvas.size`, derive another bounds wrapper, or measure DOM geometry; runtime already positions the product scene surface from `sceneBoundsProvider`.
|
|
31
|
+
- A preview-only environment that must stay fixed to the complete Infinity
|
|
32
|
+
viewport uses `infiniteCanvasContent`, not the bounded product renderer. Keep
|
|
33
|
+
that layer pointer-transparent and exclude it from scene bounds and export.
|
|
30
34
|
|
|
31
35
|
When assessment requires a benchmark, declare `kernelBenchmarkDecisions`, implement only the named executable candidates in `e2e/app-kernel-benchmarks.ts`, and let protected `pnpm verify:kernel` measure them at the exact combined workload vector. Candidate outputs must be deterministic and equal at full quality. Do not author timing values or add speculative benchmark metadata when generic assessment resolves the choice.
|
|
32
36
|
|
|
@@ -110,7 +114,7 @@ The `mount*` and error functions above stand for product renderer integration on
|
|
|
110
114
|
|
|
111
115
|
The presentation lease is keyed by canonical document reference and shares immutable geometry/material/texture GPU resources across preview and export while cloning only scene roots. Replacement, delete/reset, failed creation, release, and provider unmount dispose ownership deterministically. The original uploaded folder/ZIP remains immutable durable source; display fit and camera pose live outside the leased root.
|
|
112
116
|
|
|
113
|
-
The runtime presents structurally valid analyzing or repairing geometry at `0.4` opacity and committed clean/fixed geometry at `1`. Export is always `1`.
|
|
117
|
+
The runtime presents structurally valid analyzing or repairing geometry at `0.4` opacity and committed clean/fixed geometry at `1`. Export is always `1`. Runtime image/video export composites visible committed model layers before awaiting the product's shared `ToolcraftAppComposition.exportRenderer` frame. Runtime owns the presentation binding, pose, scene frame, dimensions, pixel ratio, encoding, and download; product code does not call model compositors or construct a parallel export host.
|
|
114
118
|
|
|
115
119
|
When `viewInteraction.mode` is `orbit`, schema `orientationGizmo`, direct model drag, preview rendering, hit testing, reset/history, and export share every declared orientation pose target. The product renderer supplies geometry-aware `hitTest`; Toolcraft owns gesture scheduling and history through `useToolcraftModelOrbitInteraction`.
|
|
116
120
|
|
|
@@ -42,16 +42,16 @@ Custom product output declares bounds on the composition:
|
|
|
42
42
|
```tsx
|
|
43
43
|
export const appComposition: ToolcraftAppComposition = {
|
|
44
44
|
canvasContent: <ProductCanvas />,
|
|
45
|
-
sceneBoundsProvider: ({ state
|
|
46
|
-
getVisibleProductSceneRect(state
|
|
45
|
+
sceneBoundsProvider: ({ state }) => [
|
|
46
|
+
getVisibleProductSceneRect(state),
|
|
47
47
|
],
|
|
48
48
|
schema: appSchema,
|
|
49
49
|
};
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
The provider returns world-space `{ x, y, width, height }` rectangles. Runtime unions them
|
|
52
|
+
The provider returns world-space `{ x, y, width, height }` rectangles for one exact state. Runtime uses their union for the live infinite product scene, unions them with visible image/model frames for export, and calls the provider for every scheduled video state before forming one stable envelope. Canvas 2D, WebGL, and WebGPU product output calls `useToolcraftProductSceneFrame()` inside `canvasContent` for active backing size and world-to-local translation. Product code does not read DOM bounds, author a time-range envelope, or reuse dormant finite size in infinite mode.
|
|
53
53
|
|
|
54
|
-
Use `canvas.renderScale: true` only for non-vector raster previews such as Canvas 2D, WebGL, or WebGPU. Do not enable it for DOM/SVG/vector-native previews. Enabling it requires one browser runtime acceptance row targeting `canvas.renderScale` with `renderScaleCoverage.kind: "selected-backing-pixels"` and exact sorted states `["interaction", "steady"]`, plus `"playback"` when timeline is enabled. The fixed `canvas-render-scale-backing` recipe proves actual backing pixels rather than timing.
|
|
54
|
+
Use `canvas.renderScale: true` or `canvas.renderScale: { step }` only for non-vector raster previews such as Canvas 2D, WebGL, or WebGPU. For this field, product code may customize only the slider step; authored schema cannot set `enabled`, `min`, `defaultValue`, or `max`. Runtime resolves enabled render scale to `{ enabled: true, min: 1, defaultValue: 2, max: 2, step }`, using `0.25` when no step is authored. A custom step must be finite, between `0.01` and `1`, and evenly partition the canonical `1..2` range so `2` remains reachable; invalid input fails fast. Do not enable it for DOM/SVG/vector-native previews. Enabling it requires one browser runtime acceptance row targeting `canvas.renderScale` with `renderScaleCoverage.kind: "selected-backing-pixels"` and exact sorted states `["interaction", "steady"]`, plus `"playback"` when timeline is enabled. The fixed `canvas-render-scale-backing` recipe proves actual backing pixels rather than timing.
|
|
55
55
|
|
|
56
56
|
## Media Defaults
|
|
57
57
|
|
|
@@ -89,7 +89,7 @@ media: {
|
|
|
89
89
|
|
|
90
90
|
`sourceTarget` must match a compatible `fileDrop` control target. Runtime shows the asset as an attached file, users can remove it, and Reset restores it. Model defaults require `assetKind: "model"`, a root `fileName`, and complete local `sourceFiles`; each source uses a serializable `dataUrl` plus its bundle-relative `path`. Runtime restores default models through the same validation, analysis, repair, repository, and rendering pipeline as a user upload. Persisted empty media remains empty until Reset and must not silently resurrect defaults.
|
|
91
91
|
|
|
92
|
-
For a multi-item `fileDrop`, `recommendedMaxItems` is advisory. `hardMaxItems`, when present, must be a finite nonnegative safe integer and is enforced before decode or storage allocation. Additive imports count current assets with the same `sourceTarget` plus the incoming logical batch; replacement imports count only the incoming batch.
|
|
92
|
+
For a multi-item `fileDrop`, `recommendedMaxItems` is advisory. `hardMaxItems`, when present, must be a finite nonnegative safe integer and is enforced before decode or storage allocation. Additive imports count current assets with the same `sourceTarget` plus the incoming logical batch; replacement imports count only the incoming batch. A `fileDrop` with `assetKind: "file"`, `multiple: true`, and `variant: "collection-actions"` may declare `itemControls`; each entry uses a supported built-in collection item control and declares `defaultValue`. Attached files render these controls directly beneath their upload row, values persist at the parent target as records keyed by `mediaId`, and file bytes remain runtime-owned media.
|
|
93
93
|
|
|
94
94
|
## Model FileDrop
|
|
95
95
|
|
|
@@ -158,9 +158,9 @@ Common control fields:
|
|
|
158
158
|
| `defaultValue` | Initial value and reset value. |
|
|
159
159
|
| `label` | Short UI label, `false`, or omitted. |
|
|
160
160
|
| `description` | Product-specific help text only when it adds meaning beyond the label. |
|
|
161
|
-
| `
|
|
161
|
+
| `applicability` | Required product claim: `{ mode: "always" }` or `{ mode: "conditional", all: [...] }`. Hidden values are preserved. |
|
|
162
162
|
| `orderRole` | Makes section order testable. |
|
|
163
|
-
| `semanticGroup` | Language-independent product sub-entity/workflow grouping, required on every control in sections
|
|
163
|
+
| `semanticGroup` | Language-independent product sub-entity/workflow grouping, required on every control in sections with eight to ten controls. |
|
|
164
164
|
| `sliderValueKind` | `slider` intent: `"continuous"` or `"discrete"`. |
|
|
165
165
|
| `textValueKind` | `text`/`code` intent: `"single-line"`, `"multiline"`, or `"structured"`. |
|
|
166
166
|
| `curveIntent` | `curves` composition: `"single-value-map"` or `"color-channels"`. |
|
|
@@ -170,11 +170,9 @@ Common control fields:
|
|
|
170
170
|
| `keyframeable` | Timeline/keyframe capability override when structurally needed. |
|
|
171
171
|
| `variant` | Component-specific variant. |
|
|
172
172
|
|
|
173
|
-
|
|
173
|
+
Every authored product control declares `applicability`: use `{ mode: "always" }` only when it affects its accepted outcome in every finite sibling-selector branch, or `{ mode: "conditional", all: [...] }` when every predicate must match. Inactive controls are absent while values remain preserved. Do not use `disabled`, `disabledWhen`, or inert visible controls for availability. Legacy control `visibleWhen` remains readable only at the low-level compatibility boundary; product acceptance rejects it and omitted applicability. Section `visibleWhen` remains a separate legacy section-layout feature.
|
|
174
174
|
|
|
175
|
-
Conditions support `equals`, `notEquals`, `oneOf`, `notOneOf`, `greaterThan`, `greaterThanOrEqual`, `lessThan`, and `lessThanOrEqual`.
|
|
176
|
-
|
|
177
|
-
Reserved runtime targets include `runtime.settingsTransfer`, `canvas.infinity`, `canvas.aspectRatio`, `canvas.size.width`, `canvas.size.height`, `canvas.renderScale`, and `panels.timeline.extended`. Product sections must not declare those controls.
|
|
175
|
+
Conditions support `equals`, `notEquals`, `oneOf`, `notOneOf`, `greaterThan`, `greaterThanOrEqual`, `lessThan`, and `lessThanOrEqual`. Reserved runtime targets include `runtime.settingsTransfer`, `canvas.infinity`, `canvas.aspectRatio`, `canvas.size.width`, `canvas.size.height`, `canvas.renderScale`, and `panels.timeline.extended`; product sections must not declare them.
|
|
178
176
|
|
|
179
177
|
## Built-In Control Types
|
|
180
178
|
|
|
@@ -194,6 +192,7 @@ Reserved runtime targets include `runtime.settingsTransfer`, `canvas.infinity`,
|
|
|
194
192
|
| `checkbox` | `Checkbox` |
|
|
195
193
|
| `actions` | `Actions` |
|
|
196
194
|
| `collectionActions` | `CollectionActions` |
|
|
195
|
+
| `sourceCollection` | `ControlsPanelCollectionItems` |
|
|
197
196
|
| `panelActions` | `PanelActions` |
|
|
198
197
|
| `colorOpacity` | `ColorOpacity` |
|
|
199
198
|
| `palette` | `Palette` |
|
|
@@ -210,7 +209,7 @@ Reserved runtime targets include `runtime.settingsTransfer`, `canvas.infinity`,
|
|
|
210
209
|
| `settingsTransfer` | `SettingsTransfer` |
|
|
211
210
|
[//]: # (toolcraft-contract:built-in-control-table:end)
|
|
212
211
|
|
|
213
|
-
Use `component-rules.md` for component-specific fit, labels, variants, units, parser behavior, and exceptions. Use `core/control-selection.md` before deciding a custom control is needed.
|
|
212
|
+
Use `component-rules.md` for component-specific fit, labels, variants, units, parser behavior, and exceptions. `sourceCollection` renders a supported built-in `itemControl` for a source-owned array without add/remove UI; `collectionActions` owns user cardinality and its limits. Use `itemControl` for one homogeneous repeated value. For one logical repeated entity made from two or more built-in fields, use `itemControls`; for example, `{ type: "collectionActions", target: "surface.layers", defaultValue: [{ strength: 0.4, invert: false }], itemControls: { strength: { type: "slider", defaultValue: 0.5 }, invert: { type: "switch", defaultValue: false } } }`. Every field requires `defaultValue`; `itemControl` and `itemDefaultValue` are invalid competing template sources. `+` appends the complete defaults, `−` removes the final record, edits preserve sibling/product keys, and runtime places a line only between compound records without `Item N` headings. Standalone color `itemControl` remains a divider-free two-column grid. Use `core/control-selection.md` before deciding a custom control is needed.
|
|
214
213
|
|
|
215
214
|
`orientationGizmo` uses a non-degenerate `{ position: [x, y, z], up: [x, y, z] }` default, `label: false`, and `keyframeable: false`. Declare one target for the active/selected model and keep it beside at least one visible product control in the semantic model/view section; runtime renders the handle on the canvas rather than in the controls panel. Multiple declarations require statically provable mutually exclusive combined section/control visibility conditions, because runtime permits at most one active orientation handle.
|
|
216
215
|
|
|
@@ -221,6 +220,7 @@ before schema controls or renderer code:
|
|
|
221
220
|
|
|
222
221
|
```ts
|
|
223
222
|
export const starterProductReadiness: ToolcraftProductReadiness = {
|
|
223
|
+
exportIntent: { image: { mode: "toolcraft-default" }, video: { mode: "not-requested" } },
|
|
224
224
|
interactionOwnership: [],
|
|
225
225
|
mode: "product",
|
|
226
226
|
productName: "Model Studio",
|
|
@@ -290,22 +290,22 @@ exactly match schema `orientationGizmo` targets.
|
|
|
290
290
|
## Control Section Inventory
|
|
291
291
|
|
|
292
292
|
Before writing `panels.controls.sections`, export `starterControlSectionInventory` beside `starterAcceptance`:
|
|
293
|
-
|
|
294
293
|
```ts
|
|
295
294
|
export const starterControlSectionInventory = [
|
|
296
295
|
{
|
|
297
296
|
entity: "Text block",
|
|
298
|
-
|
|
299
|
-
|
|
297
|
+
entityId: "text-block",
|
|
298
|
+
groupingReason: "These controls edit the text content, typography, and visible text fill together.",
|
|
299
|
+
id: "text",
|
|
300
300
|
targets: ["text.content", "text.font"],
|
|
301
301
|
title: "Text",
|
|
302
302
|
},
|
|
303
303
|
] as const;
|
|
304
304
|
```
|
|
305
305
|
|
|
306
|
-
Every product control target appears exactly once in the inventory. Runtime `Setup`, sticky footer `Export`, settings transfer, and runtime canvas sizing targets do not need entries.
|
|
307
|
-
|
|
308
|
-
|
|
306
|
+
- Every product control target appears exactly once in the inventory. Runtime-owned `Setup`, sticky footer `Export`, settings transfer, and runtime canvas sizing targets do not need entries. The product targets authored in the standard `Background` source section remain in its `Background` inventory entry after runtime relocates those controls into `Setup`. Stable `entityId` is the primary grouping authority; target namespaces are only secondary diagnostics.
|
|
307
|
+
- Keep one logical entity in one section through ten controls. One to seven controls is the normal size; sections with eight to ten controls require `semanticGroup` on every control. Controls editing one tightly scoped product sub-entity share the same group, and this fact may not be inferred from English labels.
|
|
308
|
+
- When one entity has more than ten controls, split it into balanced workflow sections containing two to ten controls. Every split section keeps the same `entityId` and `entity`, declares a unique `workflowStage`, and provides a concrete `splitReason`. Do not create a one-control tail.
|
|
309
309
|
|
|
310
310
|
## Transfer Metadata
|
|
311
311
|
|
|
@@ -313,19 +313,17 @@ Reference and motion metadata lives in `starterTransferMode`.
|
|
|
313
313
|
|
|
314
314
|
Use `transferMode: "reference-runtime-clone"` when porting an existing app unless the user explicitly asks for redesign. Reference clones declare `referenceStudy`, `referenceFeatureInventory`, and acceptance mapping; detailed evidence requirements live in `core/reference-study.md`.
|
|
315
315
|
|
|
316
|
+
Every product readiness declaration includes required `exportIntent`. Its resolved image/video capabilities must correspond exactly to schema actions and settings sections. Use `core/setup-export.md` for the authoritative modes, evidence requirements, and decision sequence.
|
|
317
|
+
|
|
316
318
|
Video references declare `videoReferenceStudy` before implementation. Animated products declare `animationIntent`, and playback/keyframe timeline apps declare a proven loop duration when known. Detailed animation rules live in `core/timeline-animation.md`.
|
|
317
319
|
|
|
318
320
|
## Export And Actions
|
|
319
321
|
|
|
320
|
-
Product apps expose delivery through sticky `panelActions`, not canvas UI or ordinary body controls.
|
|
321
|
-
|
|
322
|
-
Every app with `Export PNG` includes `Image Export` controls with `export.image.format` and `export.image.resolution`. Apps with `Export Video` also include `Video Export` controls with `export.video.format` and `export.video.resolution`.
|
|
322
|
+
Product apps expose enabled artifact delivery through sticky `panelActions`, not canvas UI or ordinary body controls. `productReadiness.exportIntent` is required: image export defaults on and is absent only with explicit removal evidence; video export exists only with explicit user-request evidence. Animation, playback, keyframes, and timeline presence never change that intent.
|
|
323
323
|
|
|
324
|
-
|
|
324
|
+
Every app with `Export PNG` includes `Image Export` controls with `export.image.format` and `export.image.resolution`. Apps with `Export Video` include `Video Export` controls with `export.video.format` and `export.video.resolution`. Image-only, image-plus-video, video-only, and explicit no-export layouts must match `core/setup-export.md` exactly.
|
|
325
325
|
|
|
326
|
-
- `
|
|
327
|
-
- `shouldIncludeToolcraftPreviewBackground(state)`
|
|
328
|
-
- `getToolcraftVideoExportSize({ resolution, state })`
|
|
326
|
+
Use the standard runtime path: declare typed `export-image`/`export-video` panel actions and their settings, provide one `ToolcraftAppComposition.exportRenderer` when product code contributes pixels, and draw one deterministic frame from the supplied state/time in scene coordinates. Call `shouldIncludeToolcraftPreviewBackground(state)` only for bounded live preview; runtime owns artifact composition, sizing, encoding, download, progress, and errors.
|
|
329
327
|
|
|
330
328
|
Detailed Setup, Background, Image Export, Video Export, sticky action, icon, and progress rules live in `core/setup-export.md`.
|
|
331
329
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<!-- toolcraft-performance-lifecycle: first-delivery=functional; later-delivery=functional-targeted; complaint=one-authority-targeted-performance-iteration; full-audit=explicit-only -->
|
|
4
4
|
<!-- toolcraft-performance-iteration: authority=exact-request-evidence+canonical-path-ids; fixture=reachable-development; after-pass=return-app-to-user+stop -->
|
|
5
5
|
<!-- toolcraft-performance-full-authority: automatic=forbidden; recommendation=two-compatible-iterations-or-broad-unlocalizable-problem; command=pnpm verify:perf; authority=explicit-user-request-or-accepted-offer -->
|
|
6
|
+
<!-- toolcraft-performance-routing: localized=agent-targeted; ambiguous=one-user-facing-choice; broad=offer-targeted-or-full; full=explicit-only -->
|
|
6
7
|
|
|
7
8
|
This file is the app-local routing layer for Toolcraft work. It does not replace the detailed contracts; it tells an agent which contract to read and which verification path to use before editing.
|
|
8
9
|
|
|
@@ -65,7 +66,7 @@ For product app work, update `docs/toolcraft/agent-worklog.md` before reporting
|
|
|
65
66
|
- state/output mapping from controls, commands, timeline, layers, media, or renderer to the visible product;
|
|
66
67
|
- one bare-delivery verification narrative;
|
|
67
68
|
- risks or follow-ups.
|
|
68
|
-
- for
|
|
69
|
+
- for localized performance work, or a post-clarification targeted choice, an exact request quote and the canonical affected performance path IDs; classifier output establishes complaint authority only, and unresolved localization records neither performance-iteration intent nor canonical path authority regardless of classifier result.
|
|
69
70
|
- updated high-level decisions for renderer, view interaction, interaction ownership, timeline, layers, controls, export, and performance when those choices change.
|
|
70
71
|
|
|
71
72
|
If the folder is still the neutral starter, do not invent product decisions. Once it becomes a product, switch the worklog to product mode and keep it concrete.
|
|
@@ -102,9 +103,13 @@ Use the smallest focused unit and browser checks while implementation is changin
|
|
|
102
103
|
|
|
103
104
|
1. **First product delivery:** bare `pnpm verify:delivery` proves complete product contracts, performs one production build, runs full functional acceptance, and runs no measured performance.
|
|
104
105
|
2. **Later functional-targeted delivery:** bare `pnpm verify:delivery` compares the immediate previous and current semantic functional proof models. It selects exact changed acceptance contracts, their direct owners and domains, and tests reached through the affected product-unit dependency graph.
|
|
105
|
-
3. **
|
|
106
|
+
3. **Localized or clarified targeted work:** only a localized complaint or a post-clarification targeted choice records domain authority in the worklog—an exact request quote plus canonical affected path IDs—and runs one bare `pnpm verify:delivery`. It executes one targeted iteration against the reachable development fixture, returns the verified app, and waits for user evaluation. Classifier output alone never localizes a path; unresolved localization creates neither performance-iteration intent nor canonical path authority, whether classification returned high-confidence `performance-iteration` or `needs-agent-judgment`.
|
|
106
107
|
4. **Full audit:** only an explicit operator request or accepted offer authorizes `pnpm verify:perf`. It performs one fresh build and the complete maximum-fixture performance matrix without advancing the delivery anchor.
|
|
107
108
|
|
|
109
|
+
Performance authority and localization are separate decisions. Classifier output establishes complaint authority only and never path localization. A localized complaint lets the agent select the affected canonical paths and run one targeted iteration without asking the user. For an ambiguous complaint, ask one user-facing question that names the visible operation and offers targeted diagnosis or a complete performance review; never ask the user to choose internal path IDs, and record no performance-iteration intent or canonical path authority before the answer. For a broad or honestly unlocalizable problem, the agent may recommend the complete performance review in that single targeted/full choice, but the user still chooses. A direct request for the complete performance review runs `pnpm verify:perf` without another clarification.
|
|
110
|
+
|
|
111
|
+
Store agent-produced browser diagnostics under `.toolcraft/browser-artifacts/`. Browser integrations may instead use their external tool-owned storage; diagnostic files never belong in product source.
|
|
112
|
+
|
|
108
113
|
The unchanged `sourceHash` fast path does not collect the catalog, dependency graph, or functional proof model and does not execute proof. For a changed source, the current catalog, input roles, ownership inventory, and semantic model are collected once and remain the immutable basis for that delivery plan. `workflow-observation.md` is a post-delivery summary, not execution authority, so it stays outside this hash; `agent-worklog.md` remains included.
|
|
109
114
|
|
|
110
115
|
After two consecutive compatible targeted iterations, offer the slower full audit if the user remains unsatisfied. A complaint, filename, or touched subsystem never authorizes it. Canonical classification details, failure behavior, and evidence wording live in `core/performance.md` and `performance.md`.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
import { defineToolcraft } from "@repo/toolcraft-runtime";
|
|
3
|
+
|
|
4
|
+
import { deriveToolcraftBrowserRuntimeRequirements } from "./browser-runtime-evidence-requirements";
|
|
5
|
+
|
|
6
|
+
const inventory = [
|
|
7
|
+
{
|
|
8
|
+
entity: "Feature",
|
|
9
|
+
entityId: "feature",
|
|
10
|
+
groupingReason: "Mode and amount describe one feature.",
|
|
11
|
+
id: "feature",
|
|
12
|
+
targets: ["feature.mode", "feature.amount"],
|
|
13
|
+
title: "Feature",
|
|
14
|
+
},
|
|
15
|
+
] as const;
|
|
16
|
+
|
|
17
|
+
test("conditional controls derive case-specific visibility and outcome evidence", () => {
|
|
18
|
+
const schema = defineToolcraft({
|
|
19
|
+
canvas: { enabled: true },
|
|
20
|
+
panels: {
|
|
21
|
+
controls: {
|
|
22
|
+
sections: [
|
|
23
|
+
{
|
|
24
|
+
controls: {
|
|
25
|
+
amount: {
|
|
26
|
+
applicability: {
|
|
27
|
+
all: [{ equals: "advanced", target: "feature.mode" }],
|
|
28
|
+
mode: "conditional",
|
|
29
|
+
},
|
|
30
|
+
defaultValue: 1,
|
|
31
|
+
target: "feature.amount",
|
|
32
|
+
type: "slider",
|
|
33
|
+
},
|
|
34
|
+
mode: {
|
|
35
|
+
applicability: { mode: "always" },
|
|
36
|
+
defaultValue: "simple",
|
|
37
|
+
options: [
|
|
38
|
+
{ label: "Simple", value: "simple" },
|
|
39
|
+
{ label: "Advanced", value: "advanced" },
|
|
40
|
+
],
|
|
41
|
+
target: "feature.mode",
|
|
42
|
+
type: "segmented",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
id: "feature",
|
|
46
|
+
title: "Feature",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
title: "Controls",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
const requirements = deriveToolcraftBrowserRuntimeRequirements(
|
|
54
|
+
[
|
|
55
|
+
{
|
|
56
|
+
browser: true,
|
|
57
|
+
browserTestName: "browser: conditional amount",
|
|
58
|
+
evidence: "product-output",
|
|
59
|
+
id: "feature.amount",
|
|
60
|
+
kind: "control",
|
|
61
|
+
target: "feature.amount",
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
schema,
|
|
65
|
+
inventory,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(requirements.map(({ evidenceType }) => evidenceType)).toEqual(
|
|
69
|
+
expect.arrayContaining([
|
|
70
|
+
"control-applicability-hidden",
|
|
71
|
+
"control-applicability-visible",
|
|
72
|
+
"product-observable-change",
|
|
73
|
+
]),
|
|
74
|
+
);
|
|
75
|
+
expect(
|
|
76
|
+
requirements.some(
|
|
77
|
+
(requirement) => requirement.requirementId === "feature.amount",
|
|
78
|
+
),
|
|
79
|
+
).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("finite siblings expand outcomes even when always-applicability omits the selector", () => {
|
|
83
|
+
const schema = defineToolcraft({
|
|
84
|
+
canvas: { enabled: true },
|
|
85
|
+
panels: {
|
|
86
|
+
controls: {
|
|
87
|
+
sections: [
|
|
88
|
+
{
|
|
89
|
+
controls: {
|
|
90
|
+
amount: {
|
|
91
|
+
applicability: { mode: "always" },
|
|
92
|
+
defaultValue: 1,
|
|
93
|
+
target: "feature.amount",
|
|
94
|
+
type: "slider",
|
|
95
|
+
},
|
|
96
|
+
mode: {
|
|
97
|
+
applicability: { mode: "always" },
|
|
98
|
+
defaultValue: "simple",
|
|
99
|
+
options: [
|
|
100
|
+
{ label: "Simple", value: "simple" },
|
|
101
|
+
{ label: "Advanced", value: "advanced" },
|
|
102
|
+
],
|
|
103
|
+
target: "feature.mode",
|
|
104
|
+
type: "segmented",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
id: "feature",
|
|
108
|
+
title: "Feature",
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
title: "Controls",
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
const acceptance = {
|
|
116
|
+
browser: true,
|
|
117
|
+
browserTestName: "browser: feature amount",
|
|
118
|
+
evidence: "product-output" as const,
|
|
119
|
+
id: "feature.amount",
|
|
120
|
+
kind: "control" as const,
|
|
121
|
+
target: "feature.amount",
|
|
122
|
+
};
|
|
123
|
+
const requirements = deriveToolcraftBrowserRuntimeRequirements(
|
|
124
|
+
[acceptance],
|
|
125
|
+
schema,
|
|
126
|
+
inventory,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
expect(requirements).toHaveLength(4);
|
|
130
|
+
expect(
|
|
131
|
+
requirements.filter(
|
|
132
|
+
({ evidenceType }) => evidenceType === "control-applicability-visible",
|
|
133
|
+
),
|
|
134
|
+
).toHaveLength(2);
|
|
135
|
+
expect(
|
|
136
|
+
requirements.filter(
|
|
137
|
+
({ evidenceType }) => evidenceType === "product-observable-change",
|
|
138
|
+
),
|
|
139
|
+
).toHaveLength(2);
|
|
140
|
+
expect(
|
|
141
|
+
requirements.every(({ requirementId }) =>
|
|
142
|
+
requirementId.includes("#applicability:feature.mode="),
|
|
143
|
+
),
|
|
144
|
+
).toBe(true);
|
|
145
|
+
|
|
146
|
+
expect(() =>
|
|
147
|
+
deriveToolcraftBrowserRuntimeRequirements(
|
|
148
|
+
[
|
|
149
|
+
{
|
|
150
|
+
...acceptance,
|
|
151
|
+
renderScaleCoverage: {
|
|
152
|
+
kind: "selected-backing-pixels",
|
|
153
|
+
states: [],
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
schema,
|
|
158
|
+
inventory,
|
|
159
|
+
),
|
|
160
|
+
).toThrow(
|
|
161
|
+
"Visible applicability case for feature.amount has no product outcome requirement",
|
|
162
|
+
);
|
|
163
|
+
});
|
|
@@ -1,10 +1,43 @@
|
|
|
1
1
|
import { expect, test } from "@playwright/test";
|
|
2
2
|
import { expectToolcraftExportedArtifact } from "./browser-acceptance-outcome-helpers";
|
|
3
3
|
import {
|
|
4
|
+
expectToolcraftDiscreteSliderMarkers,
|
|
4
5
|
expectToolcraftSegmentedControlCellsPreservePadding,
|
|
5
6
|
getToolcraftFieldByLabel,
|
|
6
7
|
} from "./performance-helpers";
|
|
7
8
|
|
|
9
|
+
test("discrete slider layout accepts one interior marker and rejects none", async ({
|
|
10
|
+
page,
|
|
11
|
+
}) => {
|
|
12
|
+
await page.setContent(`
|
|
13
|
+
<div data-slot="toolcraft-runtime-app">
|
|
14
|
+
<div data-toolcraft-control-target="canvas.renderScale">
|
|
15
|
+
<div data-slot="field" style="display:block;width:200px;height:24px;">
|
|
16
|
+
<div data-slot="slider" data-variant="discrete" style="display:block;width:200px;height:24px;">
|
|
17
|
+
<span data-slot="slider-marker" style="display:block;width:1px;height:6px;"></span>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
`);
|
|
23
|
+
|
|
24
|
+
await expectToolcraftDiscreteSliderMarkers(page, "canvas.renderScale");
|
|
25
|
+
|
|
26
|
+
await page.setContent(`
|
|
27
|
+
<div data-slot="toolcraft-runtime-app">
|
|
28
|
+
<div data-toolcraft-control-target="canvas.renderScale">
|
|
29
|
+
<div data-slot="field" style="display:block;width:200px;height:24px;">
|
|
30
|
+
<div data-slot="slider" data-variant="discrete" style="display:block;width:200px;height:24px;"></div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
`);
|
|
35
|
+
|
|
36
|
+
await expect(
|
|
37
|
+
expectToolcraftDiscreteSliderMarkers(page, "canvas.renderScale"),
|
|
38
|
+
).rejects.toThrow(/at least one interior marker/);
|
|
39
|
+
});
|
|
40
|
+
|
|
8
41
|
test("segmented layout helper catches paddingless or colliding cells", async ({ page }) => {
|
|
9
42
|
await page.setContent(`
|
|
10
43
|
<div data-slot="field">FX Preset
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { test } from "@playwright/test";
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
expectInfiniteCanvasObservation,
|
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
expectToolcraftInfinityCanvasVideoExportEvidence,
|
|
7
7
|
observeInfinityCanvas,
|
|
8
8
|
} from "./browser-infinity-canvas-evidence";
|
|
9
|
+
import {
|
|
10
|
+
readToolcraftCanvasViewport,
|
|
11
|
+
zoomToolcraftCanvasViewport,
|
|
12
|
+
} from "./performance-canvas-helpers";
|
|
9
13
|
|
|
10
14
|
test("toolcraft Infinity canvas observation reads runtime-owned geometry", async ({
|
|
11
15
|
page,
|
|
@@ -13,17 +17,60 @@ test("toolcraft Infinity canvas observation reads runtime-owned geometry", async
|
|
|
13
17
|
await page.setContent(`
|
|
14
18
|
<div data-toolcraft-canvas-world data-toolcraft-canvas-offset-x="12" data-toolcraft-canvas-offset-y="-8">
|
|
15
19
|
<div data-toolcraft-canvas-mode="infinite" style="overflow: visible">
|
|
16
|
-
<div data-scene style="position:absolute;left
|
|
20
|
+
<div data-scene style="position:absolute;left:1px;top:2px;width:3px;height:4px"></div>
|
|
21
|
+
<div
|
|
22
|
+
data-toolcraft-product-scene
|
|
23
|
+
data-toolcraft-product-scene-status="ready"
|
|
24
|
+
style="position:absolute;left:-320px;top:-200px;width:640px;height:400px"
|
|
25
|
+
></div>
|
|
17
26
|
</div>
|
|
18
27
|
</div>
|
|
19
28
|
`);
|
|
20
29
|
|
|
21
30
|
expectInfiniteCanvasObservation(
|
|
22
|
-
await observeInfinityCanvas(page
|
|
31
|
+
await observeInfinityCanvas(page),
|
|
23
32
|
{ height: 400, width: 640, x: -320, y: -200 },
|
|
24
33
|
);
|
|
25
34
|
});
|
|
26
35
|
|
|
36
|
+
test("toolcraft canvas viewport observation reads the runtime world transform", async ({
|
|
37
|
+
page,
|
|
38
|
+
}) => {
|
|
39
|
+
await page.setContent(`
|
|
40
|
+
<div
|
|
41
|
+
data-toolcraft-canvas-world
|
|
42
|
+
data-toolcraft-canvas-offset-x="96"
|
|
43
|
+
data-toolcraft-canvas-offset-y="-64"
|
|
44
|
+
data-toolcraft-canvas-zoom="125"
|
|
45
|
+
></div>
|
|
46
|
+
`);
|
|
47
|
+
|
|
48
|
+
await expect(readToolcraftCanvasViewport(page)).resolves.toEqual({
|
|
49
|
+
offsetX: 96,
|
|
50
|
+
offsetY: -64,
|
|
51
|
+
zoom: 125,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("toolcraft canvas zoom helper performs only the requested direction", async ({
|
|
56
|
+
page,
|
|
57
|
+
}) => {
|
|
58
|
+
await page.setContent(`
|
|
59
|
+
<button aria-label="Zoom in" onclick="document.body.dataset.zoomIn = String(Number(document.body.dataset.zoomIn ?? 0) + 1)"></button>
|
|
60
|
+
<button aria-label="Zoom out" onclick="document.body.dataset.zoomOut = String(Number(document.body.dataset.zoomOut ?? 0) + 1)"></button>
|
|
61
|
+
`);
|
|
62
|
+
|
|
63
|
+
await zoomToolcraftCanvasViewport(page, {
|
|
64
|
+
direction: "in",
|
|
65
|
+
repetitions: 2,
|
|
66
|
+
});
|
|
67
|
+
await expect(page.locator("body")).toHaveAttribute("data-zoom-in", "2");
|
|
68
|
+
await expect(page.locator("body")).not.toHaveAttribute("data-zoom-out");
|
|
69
|
+
|
|
70
|
+
await zoomToolcraftCanvasViewport(page, { direction: "out" });
|
|
71
|
+
await expect(page.locator("body")).toHaveAttribute("data-zoom-out", "1");
|
|
72
|
+
});
|
|
73
|
+
|
|
27
74
|
test("toolcraft Infinity canvas video evidence compares decoded envelopes", async () => {
|
|
28
75
|
await expectToolcraftInfinityCanvasVideoExportEvidence(
|
|
29
76
|
{
|