@pixel-point/toolcraft 0.0.8 → 0.0.11
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/README.md +42 -9
- package/package.json +1 -1
- package/src/generate.mjs +42 -5
- package/src/generate.test.mjs +40 -0
- package/src/package-json.mjs +15 -0
- package/src/package-json.test.mjs +14 -1
- package/templates/runtime/contracts/component-contracts.test.ts +251 -47
- package/templates/runtime/contracts/component-contracts.ts +130 -57
- package/templates/runtime/contracts/decision-contracts.test.ts +38 -1
- package/templates/runtime/contracts/decision-contracts.ts +22 -9
- package/templates/runtime/export/export.test.ts +63 -0
- package/templates/runtime/export/export.ts +55 -0
- package/templates/runtime/index.ts +1 -0
- package/templates/runtime/react/canvas-shell.test.tsx +58 -4
- package/templates/runtime/react/canvas-shell.tsx +31 -9
- package/templates/runtime/react/controls-panel.test.tsx +916 -108
- package/templates/runtime/react/controls-panel.tsx +136 -30
- package/templates/runtime/react/runtime-public-api.test.tsx +1 -1
- package/templates/runtime/react/settings-transfer.test.ts +4 -0
- package/templates/runtime/react/settings-transfer.ts +6 -1
- package/templates/runtime/react/timeline-panel.test.tsx +14 -0
- package/templates/runtime/react/timeline-panel.tsx +44 -7
- package/templates/runtime/react/toolcraft-app.integration.test.tsx +9 -1
- package/templates/runtime/react/toolcraft-app.test.tsx +112 -3
- package/templates/runtime/react/toolcraft-app.tsx +56 -37
- package/templates/runtime/schema/define-toolcraft.test.ts +266 -170
- package/templates/runtime/schema/define-toolcraft.ts +140 -246
- package/templates/runtime/schema/runtime-targets.ts +21 -0
- package/templates/runtime/schema/types.ts +44 -0
- package/templates/runtime/state/create-template-state.test.ts +156 -0
- package/templates/runtime/state/create-template-state.ts +38 -8
- package/templates/runtime/state/media-defaults.ts +105 -0
- package/templates/runtime/state/persistence.test.ts +58 -0
- package/templates/runtime/state/persistence.ts +105 -1
- package/templates/runtime/state/reducer.test.ts +280 -4
- package/templates/runtime/state/reducer.ts +195 -9
- package/templates/runtime/state/timeline-loop.test.ts +71 -0
- package/templates/runtime/state/timeline-loop.ts +35 -0
- package/templates/runtime/state/types.ts +27 -0
- package/templates/runtime/testing/performance.test.ts +810 -21
- package/templates/runtime/testing/performance.ts +823 -53
- package/templates/starter/AGENTS.md +24 -18
- package/templates/starter/docs/toolcraft/README.md +8 -4
- package/templates/starter/docs/toolcraft/acceptance-testing.md +43 -10
- package/templates/starter/docs/toolcraft/agent-worklog.md +1 -0
- package/templates/starter/docs/toolcraft/assembly-workflow.md +55 -20
- package/templates/starter/docs/toolcraft/component-rules.md +75 -42
- package/templates/starter/docs/toolcraft/decision-contract.md +2 -0
- package/templates/starter/docs/toolcraft/performance.md +37 -11
- package/templates/starter/docs/toolcraft/schema-reference.md +171 -41
- package/templates/starter/docs/toolcraft/workflow.md +5 -2
- package/templates/starter/e2e/app-browser-acceptance.spec.ts +3 -3
- package/templates/starter/e2e/app-performance.spec.ts +55 -2
- package/templates/starter/e2e/performance-helpers.ts +45 -0
- package/templates/starter/gitignore +1 -0
- package/templates/starter/index.html +1 -0
- package/templates/starter/package.json +3 -0
- package/templates/starter/playwright.config.ts +1 -1
- package/templates/starter/scripts/check-toolcraft-docs.mjs +1 -0
- package/templates/starter/scripts/run-vite-on-free-port.mjs +114 -13
- package/templates/starter/scripts/toolcraft-port.mjs +280 -0
- package/templates/starter/scripts/toolcraft-port.test.mjs +207 -1
- package/templates/starter/src/app/starter-acceptance.test.ts +3412 -479
- package/templates/starter/src/app/starter-acceptance.ts +1453 -97
- package/templates/starter/src/app/starter-performance.test.ts +111 -7
- package/templates/starter/src/app/starter-performance.ts +5 -0
- package/templates/starter/src/app/starter-schema.test.ts +32 -7
- package/templates/starter/src/app/starter-schema.ts +6 -2
- package/templates/starter/vite.config.ts +58 -2
- package/templates/ui/components/control-layout/index.tsx +8 -3
- package/templates/ui/components/controls/actions/actions-control.tsx +56 -5
- package/templates/ui/components/controls/code-textarea/code-textarea-control.tsx +7 -3
- package/templates/ui/components/controls/color/index.ts +4 -1
- package/templates/ui/components/controls/color/palette-control.tsx +34 -4
- package/templates/ui/components/controls/color/style-guide-color-picker-logic.ts +7 -2
- package/templates/ui/components/controls/color/style-guide-color-picker.tsx +2 -2
- package/templates/ui/components/controls/file-drop/file-drop-control.tsx +186 -14
- package/templates/ui/components/controls/file-drop/index.ts +6 -1
- package/templates/ui/components/controls/index.ts +4 -0
- package/templates/ui/components/controls/range-input/range-input-control.tsx +12 -4
- package/templates/ui/components/controls/range-slider/range-slider-value.ts +3 -1
- package/templates/ui/components/controls/select/select-control.tsx +8 -25
- package/templates/ui/components/controls/slider/slider-value.ts +0 -1
- package/templates/ui/components/controls/text-input/text-input-control.tsx +4 -1
- package/templates/ui/components/controls/vector/index.ts +1 -0
- package/templates/ui/components/controls/vector/vector-control.tsx +109 -12
- package/templates/ui/components/panel/panel-actions.tsx +1 -1
- package/templates/ui/components/panel/panel-section.tsx +29 -5
|
@@ -14,22 +14,23 @@ Then follow `workflow.md` to choose the required contract docs and verification
|
|
|
14
14
|
|
|
15
15
|
1. Build through `defineToolcraft` and `ToolcraftApp`.
|
|
16
16
|
2. Keep app state in Toolcraft runtime schema and commands.
|
|
17
|
-
3. Keep product output in `canvasContent`; never render app UI there.
|
|
17
|
+
3. Keep product output in `canvasContent`; never render app UI there. If upload/import is part of the source-material flow, do not invent canvas placeholder artwork, CTA copy, helper text, fake sample output, or preset source designs before real content exists.
|
|
18
18
|
4. Use built-in Toolcraft controls before custom controls.
|
|
19
19
|
5. Do not hand-compose runtime surfaces or render built-in control components directly in app code; use `ToolcraftApp`, schema controls, `canvasContent`, `controlRenderers`, `onPanelAction`, and runtime commands.
|
|
20
|
-
6. Before writing controls, make
|
|
20
|
+
6. Before writing controls, make and export `starterControlSectionInventory`: each product controls section declares its title, product entity or workflow stage, targets, and grouping reason. Group by product meaning, not UI component type.
|
|
21
21
|
7. Keep control `label` short but semantically sufficient with the nearest visible section/group context, and put product-specific behavior help in schema `description`; runtime renders the label help tooltip only when that description adds meaning beyond the label.
|
|
22
|
-
8. Enable layers and timeline only when product behavior requires them, then test the real UI.
|
|
22
|
+
8. Enable layers and timeline only when product behavior requires them, then test the real UI. Product animation loops are seamless forward-only by default: first and last frames stitch, direction does not reverse, and mirror/yoyo/ping-pong behavior requires explicit user intent.
|
|
23
23
|
9. Animated preview renderers suspend or coalesce non-essential animation work during canvas drag, pan, pinch, zoom, and radar/center interactions, then resume without changing user playback state.
|
|
24
24
|
10. If a Figma URL is provided, inspect the Figma file through MCP and rebuild from its structure; never implement from a screenshot or by eye.
|
|
25
|
-
11.
|
|
26
|
-
12.
|
|
27
|
-
13.
|
|
28
|
-
14.
|
|
29
|
-
15.
|
|
30
|
-
16.
|
|
31
|
-
17.
|
|
32
|
-
18.
|
|
25
|
+
11. If a video, GIF, screen recording, contact sheet, or extracted-frame sequence is provided as a reference, write a Video Reference Study before implementation: storyboard frames, frame-to-frame transition analysis, behavior decomposition, and acceptance mapping. Do not implement video references from a single screenshot or high-level summary.
|
|
26
|
+
12. Choose an explicit persistence policy; use schema `persistence` for user-edited app settings that should survive reload, and test real reload restoration when localStorage is enabled.
|
|
27
|
+
13. Generated apps keep a controls panel so runtime `Setup` is visible from the first run; product sections are added after it. Runtime `Setup` is the first visible headerless controls block, is not collapsible, and always contains `Export Settings` and `Import Settings`; never implement settings import/export through `panelActions` or route-local file inputs, and never gate this block by app complexity. Visible `Aspect ratio`, `Canvas width`, and `Canvas height` controls are owned by `editable-output` canvas sizing and merge into the same Setup block after settings transfer. App-authored sections must not declare runtime Setup targets such as `runtime.settingsTransfer`, `canvas.aspectRatio`, `canvas.size.width`, `canvas.size.height`, `canvas.renderScale`, or `panels.timeline.extended`; those controls never suppress the mandatory runtime Setup controls. Runtime aspect presets apply canonical canvas sizes, with `16:9` equal to `1920x1080`; manual Canvas width/height edits keep the typed dimension, keep the other dimension unchanged, switch Aspect ratio to Custom, and show the reduced current ratio in custom ratio inputs; when no explicit product size is provided, the runtime default canvas size is also `1920x1080`. Product-output, exportable, shader, procedural, and reference-clone apps use `editable-output`; uploaded background/source images inside product canvases also use `editable-output`, keep the current canvas size, and render as cover/crop inside the current canvas bounds. Fixed/reference/base dimensions are initial `canvas.size` values, not reasons to hide `Aspect ratio`, `Canvas width`, or `Canvas height`. Non-vector raster, Canvas 2D, WebGL, and WebGPU previews set `canvas.renderScale: true`; Setup then appends `Resolution scale` after canvas sizing so backing pixels can increase up to scale 2 without changing CSS/output size. Performance fixes must preserve the selected render scale and keep canvas preview responsive to sliders/high-frequency controls at that scale; diagnose the bottleneck before reducing quality. Do not pass budgets by silently downsampling, stretching a lower-resolution backing canvas, blurring output, or clamping `canvas.renderScale` below the user's chosen value. When `panels.timeline` is enabled, runtime appends a `Timeline` switch as the last Setup control; off shows compact Play-only transport, on shows the extended timeline with scrubber, duration, loop, and keyframe UI, and the switch never changes product values, playback, keyframes, export, or Reset controls. When `panels.timeline` is omitted, the Timeline switch must not appear.
|
|
28
|
+
14. Product apps expose a required `Background` section directly before export settings. It contains a Switch labeled `Include` and a background color control with `label: false` in one equal-width inline row; PNG export wires those runtime values into the standard export helper, live preview uses `shouldIncludeToolcraftPreviewBackground(state)` so Include can hide the product background, and video export keeps the background. Every app with `Export PNG` exposes `Image Export` with `export.image.format` and `export.image.resolution` as two `select` controls in one compact two-column inline row, and passes the selected resolution to `createToolcraftPngExportCanvas({ resolution })` so 2K/4K/8K change actual PNG dimensions. Animated apps with video export enable the top Toolcraft timeline and place `Image Export` immediately before `Video Export`.
|
|
29
|
+
15. Keep `docs/toolcraft/agent-worklog.md` current with a decision trail, product decisions, explicit reference inputs, evidence, verification, and risks. Reference-runtime-clone apps also declare `referenceStudy` plus `referenceFeatureInventory` so every inspected reference feature has feature-level behavior evidence and maps to Toolcraft implementation and acceptance coverage.
|
|
30
|
+
16. Prove every visible entity through acceptance, browser, and performance coverage.
|
|
31
|
+
17. Workload performance scenarios must declare `stressFixture` for the tested control value; browser perf tests must use `getToolcraftPerformanceStressValue(appPerformance, scenarioId)` so heavy-case tests cannot use toy values. When the tested control is not itself the whole heavy source, declare `workloadFixture` and apply it first with `getToolcraftPerformanceWorkloadValue` or `applyToolcraftPerformanceWorkloadFixture`; this is the app baseline such as large media, long text, many items, or high render scale, and it must be paired with the measured `stressFixture`. Numeric maximums, density, item counts, canvas/media size, and combined heavy states declare `loadProfile` with `hardLimit`, `smoothTarget`, and `smoothTargetRatio`; try the hard limit first, and lower the guaranteed smooth target only in 10 percent steps with failed-measurement and optimization evidence. Ranges above `smoothTarget` are experimental, not silently guaranteed. Media import and image-processing workloads use `kind: "media"` fixtures at least `1920x1080`-equivalent, and heavy pixel/media Canvas 2D must evaluate WebGL/WebGPU with measured evidence before staying on CPU.
|
|
32
|
+
18. Custom renderer apps declare a Render Pipeline Inventory in typed `rendererPipeline`: render passes, cache keys, execution location, preview/export quality, and interaction invalidation.
|
|
33
|
+
19. Classify every implementation pass with a verification tier before editing. Use targeted checks for incremental edits and the full final gate only for final delivery, exports, or architecture/runtime/template changes.
|
|
33
34
|
|
|
34
35
|
## Starter Baseline
|
|
35
36
|
|
|
@@ -84,6 +85,7 @@ These ids mirror `TOOLCRAFT_DECISION_CONTRACT` in `@/toolcraft/runtime`. Keep th
|
|
|
84
85
|
- `output-export-required`
|
|
85
86
|
- `controls-layout-heuristics`
|
|
86
87
|
- `renderer-technique-inventory`
|
|
88
|
+
- `video-reference-analysis`
|
|
87
89
|
- `reference-clone-source-of-truth`
|
|
88
90
|
- `acceptance-product-observable`
|
|
89
91
|
- `performance-coverage-levels`
|
|
@@ -99,7 +101,7 @@ These ids mirror `TOOLCRAFT_DECISION_CONTRACT` in `@/toolcraft/runtime`. Keep th
|
|
|
99
101
|
- Use `renderDefaultCanvasMedia={false}` when a custom renderer replaces the default media preview.
|
|
100
102
|
- Use `ToolcraftApp onPanelAction` for sticky footer product actions such as Generate, Apply, Export, Copy, or Download.
|
|
101
103
|
- Keep final app behavior in the schema and runtime command bus, not in isolated local control state.
|
|
102
|
-
- For animated products, write an Animation Intent Inventory before coding: use top playback timeline for product transport, keyframes timeline for editable property animation, and no timeline only for explicitly autonomous decorative output.
|
|
104
|
+
- For animated products, write an Animation Intent Inventory before coding: use top playback timeline for product transport, keyframes timeline for editable property animation, and no timeline only for explicitly autonomous decorative output with no video export. Any app with `Export Video` must enable the top Toolcraft timeline.
|
|
103
105
|
- For keyframes timeline apps, renderers read keyframed settings through Toolcraft evaluated-value helpers/hooks. Do not parse timeline `valueLabel` strings or read raw `state.values` for keyframed targets.
|
|
104
106
|
- Use schema `defaultValue` for every resettable control.
|
|
105
107
|
- Route editor-owned actions through runtime commands such as `controls.reset`, `media.import`, `media.delete`, `canvas.center`, `history.undo`, and `history.redo`.
|
|
@@ -112,7 +114,7 @@ AI must work on this app through the required workflow skills when the environme
|
|
|
112
114
|
- Before editing code from an approved spec, use `writing-plans` to produce a deterministic implementation plan focused on app files, tests, build, and browser verification.
|
|
113
115
|
- Before fixing any broken control, failed test, build failure, visual mismatch, export issue, or runtime regression, use `systematic-debugging` to find the root cause first.
|
|
114
116
|
- When the prompt includes a Figma URL, use Figma MCP/design context before implementation. Read the actual node, layer, component, variable, and asset structure; screenshots are only for final visual QA, not the source of truth.
|
|
115
|
-
- After implementation, use the `browser` workflow or equivalent local browser verification to test the running app, not only typecheck/build output. The default browser gate is `pnpm test:browser`; `pnpm test:browser:perf` is reserved for full performance checkpoints.
|
|
117
|
+
- After implementation, use the `browser` workflow or equivalent local browser verification to test the running app, not only typecheck/build output. The default browser gate is `pnpm test:browser`; it excludes `browser perf:` budget scenarios and leaves the performance audit disabled unless the perf checkpoint runner sets `TOOLCRAFT_PERF_CHECK=1`. `pnpm test:browser:perf` is reserved for full performance checkpoints.
|
|
116
118
|
- Run `pnpm ai:check` before app generation or major changes.
|
|
117
119
|
- If a required skill is missing and the environment supports skill installation, install it before implementation and restart or refresh the session if the skill list does not update.
|
|
118
120
|
- If skill installation is not available, stop before implementation and tell the user exactly which required skills are missing.
|
|
@@ -141,16 +143,18 @@ Choose the tier by blast radius, not by line count. If uncertain, move one tier
|
|
|
141
143
|
| Tier 1 — local control presentation | One control or panel visual state changes: spacing, hover, focus, disabled, marker visibility, label fit, or component variant display. Runtime state shape and product renderer are unchanged. | Targeted unit/component test plus one focused browser check for the affected control or panel. |
|
|
142
144
|
| Tier 2 — schema/product behavior | Controls, sections, defaults, persistence, panel actions, export actions, acceptance rows, or product behavior mapping changes. | `pnpm verify:quick` plus relevant browser acceptance. Run perf only when the changed control affects renderer workload or responsiveness. |
|
|
143
145
|
| Tier 3 — renderer/canvas/runtime feature | Custom renderer, animation loop, canvas sizing, upload/media, timeline, layers, toolbar, export bytes, WebGL/Canvas/SVG output, zoom, radar, history, heavy control behavior changes, or a post-generation iteration that touches renderer workload or viewport stability. | `pnpm verify:quick`, targeted browser acceptance, and targeted performance scenarios only for touched workload/viewport/export paths. |
|
|
144
|
-
| Tier 4 — final delivery/template architecture | Fresh generated app completion, folder export, commit-ready delivery, dependency changes, runtime/template/contract/CLI changes, broad refactors, or major post-generation iterations that rewrite renderer, canvas, animation, timeline/keyframes, layers, media, export, or control mapping. | Fresh folders run `pnpm install` once, then `pnpm verify:final`;
|
|
146
|
+
| Tier 4 — final delivery/template architecture | Fresh generated app completion, folder export, commit-ready delivery, dependency changes, runtime/template/contract/CLI changes, broad refactors, or major post-generation iterations that rewrite renderer, canvas, animation, timeline/keyframes, layers, media, export, or control mapping. | Fresh folders run `pnpm install` once, then `pnpm verify:final`; for the first working product version also run and pass a browser performance checkpoint with the current AI agent's controlled browser when available, using `pnpm verify:perf` only as the Playwright fallback for CI/non-agent runs or agents without a browser, then start `pnpm dev` to provide the local URL. |
|
|
145
147
|
|
|
146
148
|
Do not rerun `pnpm install` after every edit. Run it after fresh export, dependency changes, lockfile changes, or a missing package error.
|
|
147
149
|
|
|
148
150
|
Do not run the full browser performance suite for Tier 0-2 edits.
|
|
149
151
|
|
|
150
|
-
Run a full performance checkpoint
|
|
152
|
+
Run a full performance checkpoint only when the first working version of an app exists, or when the user explicitly asks to optimize performance, fix lag, remove jank, speed up animation, stabilize drag/zoom, or otherwise complains about performance. Prefer the current AI agent's controlled browser. Use `pnpm verify:perf` only when no agent-controlled browser is available or when running CI/non-agent automation.
|
|
151
153
|
|
|
152
154
|
Feature loops after the first working version do not run the full performance suite by default. Renderer, canvas, animation, export, timeline, layers, `canvas.renderScale`, bug fixes, and performance-sensitive controls still need targeted functional/browser checks first, plus targeted performance scenarios only when they directly exercise the touched workload/viewport/export path. Record any skipped full performance run and reason in the verification note or worklog.
|
|
153
155
|
|
|
156
|
+
The first working product app version is not complete until `pnpm verify:final` and the required browser performance checkpoint have passed and the worklog records the runner as `agent-browser` or `playwright-fallback`. Do not report final delivery when required checks are failed, incomplete, pending, blocked, or listed as skipped. After the first working version, a skipped full performance run is valid only when the worklog explicitly says the full performance checkpoint is not required for a post-first-working non-performance edit.
|
|
157
|
+
|
|
154
158
|
## Required Checks
|
|
155
159
|
|
|
156
160
|
For final delivery, run:
|
|
@@ -160,11 +164,13 @@ pnpm verify:final
|
|
|
160
164
|
pnpm dev
|
|
161
165
|
```
|
|
162
166
|
|
|
167
|
+
For the first working product delivery, run the browser performance checkpoint after `pnpm verify:final` and before `pnpm dev`: use the agent-controlled browser when available, otherwise run `pnpm verify:perf` as the Playwright fallback.
|
|
168
|
+
|
|
163
169
|
Use `pnpm install` before this final gate when the folder is fresh or dependencies changed.
|
|
164
170
|
|
|
165
|
-
`pnpm test` must include `node scripts/check-toolcraft-docs.mjs`, `node scripts/check-toolcraft-integrity.mjs`, and app tests. `pnpm verify:ui` / `pnpm test:browser` must run against the real app UI and product output. `pnpm verify:perf` / `pnpm test:browser:perf` remains available for the two full-performance triggers and must run the performance browser suite sequentially so budgets are measured without parallel e2e noise.
|
|
171
|
+
`pnpm test` must include `node scripts/check-toolcraft-docs.mjs`, `node scripts/check-toolcraft-integrity.mjs`, and app tests. `pnpm verify:ui` / `pnpm test:browser` must run against the real app UI and product output but must not run `browser perf:` budget scenarios or the performance audit. `pnpm verify:perf` / `pnpm test:browser:perf` remains available as the Playwright fallback for the two full-performance triggers and must run the performance audit plus browser budget suite sequentially so budgets are measured without parallel e2e noise.
|
|
166
172
|
|
|
167
|
-
Do not stop or kill existing local servers to free a port. `pnpm dev`, `pnpm preview`, and browser verification prefer port `3002`, but automatically move to the next free port
|
|
173
|
+
Do not stop or kill existing local servers to free a port during a first start. `pnpm dev`, `pnpm preview`, and browser verification prefer port `3002`, but automatically move to the next free port only while assigning this app's first saved port. After a saved port exists, normal `pnpm dev` / `pnpm preview` uses that same port; if that port is already serving this app, report that existing URL instead of starting a duplicate. Use `TOOLCRAFT_PORT`, `TOOLCRAFT_DEV_PORT`, or `TOOLCRAFT_TEST_PORT` only to change the preferred starting port before a saved port exists. A dev/preview launch is successful only after the selected port serves this app's Toolcraft server identity endpoint plus the `toolcraft-app-title` marker from `index.html`; never report a URL just because some server is listening there. When deliberately restarting this app server, use `pnpm dev:restart` or `pnpm preview:restart`; restart mode reuses the previously saved app port, stops the listener on that exact port if it is still running, force-stops it if it does not release the port, starts on the same port again, and verifies the identity before saving/reporting the port.
|
|
168
174
|
|
|
169
175
|
## App Completion Bar
|
|
170
176
|
|
|
@@ -180,7 +186,7 @@ The app is complete only when:
|
|
|
180
186
|
- PNG export uses the required `Background` section with `Include` plus unlabeled background color runtime controls, live preview hides product background when Include is off, and video keeps background;
|
|
181
187
|
- every PNG export includes `Image Export` format/resolution `select` controls, and passes `export.image.resolution` into `createToolcraftPngExportCanvas`;
|
|
182
188
|
- animated products with both PNG and video export place `Image Export` immediately before `Video Export`;
|
|
183
|
-
-
|
|
189
|
+
- export paths use the standard export helpers: PNG uses selected image resolution or retina fallback, while video uses current canvas/output size or the selected 4K target;
|
|
184
190
|
- layers are absent for single-layer apps and fully working when enabled;
|
|
185
191
|
- timeline is absent, playback, keyframes, or custom reference timeline according to product behavior;
|
|
186
192
|
- performance checks cover workload and responsiveness for all relevant controls;
|
|
@@ -27,16 +27,20 @@ Every implementation pass must choose a verification tier before editing. Use th
|
|
|
27
27
|
| Tier 1 | One control or panel visual state | targeted test + focused browser check |
|
|
28
28
|
| Tier 2 | Schema, defaults, persistence, actions, product mapping | `pnpm verify:quick` + relevant browser acceptance |
|
|
29
29
|
| Tier 3 | Renderer, canvas, timeline, layers, upload, export, zoom, heavy controls, or a touched performance-sensitive path | `pnpm verify:quick` + targeted browser checks, plus targeted perf scenarios only for the touched path |
|
|
30
|
-
| Tier 4 | Final delivery, fresh export, runtime/template/contract changes, broad renderer/product rewrites | `pnpm verify:final`;
|
|
30
|
+
| Tier 4 | Final delivery, fresh export, runtime/template/contract changes, broad renderer/product rewrites | `pnpm verify:final`; for the first working product version also run and pass a browser performance checkpoint with the agent-controlled browser when available, using `pnpm verify:perf` only as fallback |
|
|
31
31
|
|
|
32
|
-
Run the full
|
|
32
|
+
Run the full performance checkpoint only when the first working app version exists, or when the user explicitly asks to optimize performance, fix lag, remove jank, speed up animation, stabilize drag/zoom, or otherwise complains about performance. Prefer the current AI agent's controlled browser. Use `pnpm verify:perf` only when no agent browser is available or in CI/non-agent automation.
|
|
33
|
+
|
|
34
|
+
Performance fixtures use `loadProfile` for reasoned workload ceilings: test the product hard limit first, and only lower the guaranteed `smoothTarget` in 10 percent steps with failed-measurement and optimization evidence. Ranges above the smooth target must be treated as experimental, not silently guaranteed.
|
|
35
|
+
|
|
36
|
+
The first working product app version is not complete until `pnpm verify:final` and the required browser performance checkpoint have passed and the worklog records the runner as `agent-browser` or `playwright-fallback`. Do not report final delivery when required checks are failed, incomplete, pending, blocked, or listed as skipped. After the first working version, a skipped full performance run is valid only when the worklog explicitly says the full performance checkpoint is not required for a post-first-working non-performance edit.
|
|
33
37
|
|
|
34
38
|
Fresh folders or dependency changes need `pnpm install` before verification. Final delivery still starts the local app after the gate:
|
|
35
39
|
|
|
36
40
|
```bash
|
|
37
41
|
pnpm verify:final
|
|
38
|
-
pnpm verify:perf #
|
|
42
|
+
pnpm verify:perf # Playwright fallback when no agent browser is available or in CI/non-agent automation
|
|
39
43
|
pnpm dev
|
|
40
44
|
```
|
|
41
45
|
|
|
42
|
-
Do not kill existing local servers to free `3002
|
|
46
|
+
Do not kill existing local servers to free `3002` during a first start. Dev, preview, and browser verification prefer `3002`, then move to the next free port only while assigning this app's first saved port. After that, normal dev/preview starts use the saved port; if that port is already serving this app, report the existing URL instead of creating a second server. A launch is successful only after the selected port serves this app's Toolcraft server identity endpoint plus the `toolcraft-app-title` marker from `index.html`; never trust a port only because some server responds there. When restarting the same app server, use `pnpm dev:restart` or `pnpm preview:restart`; restart mode reuses the saved app port and stops only the listener on that exact port before starting again, forcing it only when the soft stop does not release the port, then verifies the identity before saving/reporting the port.
|
|
@@ -14,7 +14,7 @@ Every visible product entity must prove it works. A control is not accepted beca
|
|
|
14
14
|
- `e2e/app-performance.spec.ts`
|
|
15
15
|
- `e2e/product-observable-helpers.ts`
|
|
16
16
|
|
|
17
|
-
`pnpm verify:final` must pass before final delivery. Incremental edits use the verification tier classifier from `assembly-workflow.md`: run targeted browser acceptance for the changed entity, and add full
|
|
17
|
+
`pnpm verify:final` must pass before final delivery. Incremental edits use the verification tier classifier from `assembly-workflow.md`: run targeted browser acceptance for the changed entity, and add a full browser performance checkpoint for the first working product version or an explicit performance complaint. Prefer the current AI agent's controlled browser; use `pnpm verify:perf` only as the Playwright fallback when no agent browser is available or in CI/non-agent automation.
|
|
18
18
|
|
|
19
19
|
A full performance checkpoint is triggered only by the first working app version, or by a user request to optimize performance, fix lag, remove jank, speed up animation, stabilize drag/zoom, or otherwise investigate poor performance.
|
|
20
20
|
|
|
@@ -32,7 +32,7 @@ Product readiness also requires product surface: controls, layers, timeline, `ca
|
|
|
32
32
|
|
|
33
33
|
Product apps must update `docs/toolcraft/agent-worklog.md` before final delivery. The file records why the app chose its renderer, timeline mode, layer policy, control grouping, export behavior, and performance strategy.
|
|
34
34
|
|
|
35
|
-
The worklog must declare `Mode: product`. Every `Decision Trail` iteration must include `Request:`, `Task type:`, `User-visible result:`, `Source/reference checked:`, `Docs/contracts read:`, `Contract rules applied:`, `Decision:`, `Alternatives rejected:`, `State/output mapping:`, `Files changed:`, `Verification:`, `Skipped checks:`, and `Risks:`. `State/output mapping:` names how controls, commands, timeline, layers, media, or renderer state reaches the visible product or export. Each decision section (`Renderer`, `Timeline`, `Layers`, `Controls`, `Export`, `Performance`) must include `Decision:`, `Reason:`, and `Evidence:` entries. `Evidence` should name files, reference behavior, contract rules, browser checks, performance checks, or exact commands. `Verification` must list concrete checks such as `pnpm verify:quick`, `pnpm verify:perf
|
|
35
|
+
The worklog must declare `Mode: product`. Every `Decision Trail` iteration must include `Request:`, `Task type:`, `User-visible result:`, `Source/reference checked:`, `Reference inputs:`, `Docs/contracts read:`, `Contract rules applied:`, `Decision:`, `Alternatives rejected:`, `State/output mapping:`, `Files changed:`, `Verification:`, `Skipped checks:`, and `Risks:`. `Reference inputs:` is the explicit inventory of prompt/reference assets for that pass: write `None` only when there were no external references, otherwise list the source apps, URLs, screenshots, videos, GIFs, screen recordings, contact sheets, extracted-frame folders, or media files used. `State/output mapping:` names how controls, commands, timeline, layers, media, or renderer state reaches the visible product or export. Each decision section (`Renderer`, `Timeline`, `Layers`, `Controls`, `Export`, `Performance`) must include `Decision:`, `Reason:`, and `Evidence:` entries. `Evidence` should name files, reference behavior, contract rules, browser checks, performance checks, or exact commands. `Performance` evidence must name the hard limit, smooth target, smooth target ratio, failed higher measurements, and attempted optimizations whenever a load profile lowers the smooth target below the hard limit. `Verification` must list concrete checks such as `pnpm verify:quick`, browser tests, the agent-browser performance checkpoint, or `pnpm verify:perf` as the Playwright fallback. First working product delivery must record `pnpm verify:final` and the browser performance checkpoint as passed, including runner `agent-browser` or `playwright-fallback`; fallback evidence must state why no agent browser was available or why the run was CI/non-agent automation. Failed, incomplete, pending, blocked, or skipped required checks make the app incomplete unless the full performance checkpoint is explicitly not required for a post-first-working non-performance edit. `Risks` must include either `Risk:` entries or `None:` with a reason.
|
|
36
36
|
|
|
37
37
|
The acceptance gate fails if the worklog is missing, still says `Mode: starter`, or lacks concrete decision evidence.
|
|
38
38
|
|
|
@@ -51,14 +51,19 @@ Each row should name:
|
|
|
51
51
|
- expected product-level observable;
|
|
52
52
|
- evidence type;
|
|
53
53
|
- exact `automatedTestName`;
|
|
54
|
-
- exact `browserTestName
|
|
54
|
+
- exact `browserTestName`, the stable browser check name used by the agent-browser evidence and fallback Playwright test.
|
|
55
55
|
- `controlPartCoverage` when the control is compound.
|
|
56
|
-
- `canvasSizingCoverage: "fixed-output-size"`
|
|
56
|
+
- `canvasSizingCoverage: "fixed-output-size"` only for non-product/internal `fixed-output` fixtures.
|
|
57
|
+
- `canvasSizingCoverage: "intrinsic-media-size"` only for explicit media-viewer/source-native upload apps where imported media natural dimensions intentionally own `canvas.size`.
|
|
57
58
|
- `persistenceCoverage: "reload"` when schema `persistence.storage` is `"localStorage"`.
|
|
58
59
|
|
|
59
60
|
The test gate rejects rows without matching automated and browser test names.
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
Slider and range slider rows must prove live behavior. Browser tests should drag the real thumb and assert the runtime value and product-level canvas observable update during the drag, not only after pointer release, blur, an Apply action, or a final commit. Performance-sensitive sliders still need this live acceptance; jank is handled through renderer optimization and targeted performance coverage, not by making the slider deferred by default.
|
|
63
|
+
|
|
64
|
+
`fixed-output` canvas sizing must be deliberate and is not valid for generated product/output apps with export actions. A default, reference, or fixed-format size from the prompt should use `editable-output`, which keeps the runtime Aspect ratio, Canvas width, and Canvas height controls.
|
|
65
|
+
|
|
66
|
+
`intrinsic-media` upload sizing must also be deliberate. Uploaded background/source images inside product canvases use `editable-output`, keep the current canvas size after upload, keep Setup canvas controls visible, and render cover/crop inside the current canvas bounds. Browser acceptance must upload an image with a different aspect ratio and prove the current canvas size remains unchanged while the image covers/crops the canvas.
|
|
62
67
|
|
|
63
68
|
When localStorage persistence is enabled, add a runtime acceptance row that proves reload behavior. The browser test must change a real user-facing setting, wait for persistence to write, call a real page reload, and verify the restored control value or product output. Importing a settings JSON file is not persistence coverage.
|
|
64
69
|
|
|
@@ -84,6 +89,8 @@ Required parts:
|
|
|
84
89
|
|
|
85
90
|
Testing only one sub-control is not enough. For example, a `gradient` test that changes only a stop color must fail if the app also renders Gradient type, Angle, Position, or Opacity controls.
|
|
86
91
|
|
|
92
|
+
Palette acceptance must also prove live behavior: selecting a family or shade updates runtime state immediately, before delayed persistence or commit timers settle, and the next canvas/product interaction uses that selected token.
|
|
93
|
+
|
|
87
94
|
For `curves`, the acceptance row must match the intended variant. Semantic one-dimensional curves such as acceleration, bend, easing, response, depth, mask, opacity, threshold, or remap curves must set `variant: "single"` and prove `curves.points`; RGB active-channel coverage is reserved for color-correction or channel-specific curves.
|
|
88
95
|
|
|
89
96
|
For `fontPicker`, product output evidence must come from actual rendered/exported product text after changing the font, weight, size, letter spacing, line height, text case, color, and opacity. Runtime value changes, selected labels, or popup font previews are preflight checks, not final acceptance.
|
|
@@ -107,7 +114,7 @@ High-confidence wrong-substitution cases:
|
|
|
107
114
|
- segmented choices that clip instead of falling back to `select`;
|
|
108
115
|
- custom controls recreating built-ins.
|
|
109
116
|
|
|
110
|
-
`fileDrop` media-lifecycle rows must prove upload/import, clear/remove, thumbnail reorder for `multiple: true`, and global or section reset. A test that only clicks the clear button is not enough because Reset controls must also
|
|
117
|
+
`fileDrop` media-lifecycle rows must prove upload/import, clear/remove, image rotate/flip, thumbnail reorder for `multiple: true`, and global or section reset. A test that only clicks the clear button is not enough because Reset controls must also restore `media.defaultAssets` for predefined attached files or remove uploaded source material when no default exists. Product preview/export must consume runtime media order and `mediaAssets[].transform`.
|
|
111
118
|
|
|
112
119
|
Rows that use custom controls must include `customControlCoverage` and typed `builtInFitCheck`.
|
|
113
120
|
|
|
@@ -148,11 +155,11 @@ Every app with `Export PNG` must exercise the separate `Image Export` section: c
|
|
|
148
155
|
|
|
149
156
|
Async Export, Download, Copy, Generate, or Apply acceptance must prove the sticky footer top accent indicator is visible while the returned `onPanelAction` Promise is pending, advances when `reportProgress(0..1)` is called, and hides after it settles. Video export acceptance must prove frame-based progress updates during render/encode instead of only toggling a pending state.
|
|
150
157
|
|
|
151
|
-
Animated app acceptance must also exercise the separate `Video Export` section: choose at least two `export.video.format` values, choose at least two `export.video.resolution` values, verify unsupported MIME/container choices fall back safely, and assert exported video bytes, dimensions, MIME/container, and duration match runtime timeline state. The duration assertion must load the exported blob as a video, wait for metadata, and compare `video.duration` with the edited timeline duration; `blobSize > 0`, `blobType`, WebM parser fallback, or assigning the expected duration when metadata is missing are not enough.
|
|
158
|
+
Animated app acceptance must also exercise the separate `Video Export` section: choose at least two `export.video.format` values, choose at least two `export.video.resolution` values, verify unsupported MIME/container choices fall back safely, and assert exported video bytes, dimensions, MIME/container, and duration match runtime timeline state. `current` video export must use the current canvas/output size with even encoder-safe rounding. `4k` video export must use `getToolcraftVideoExportSize`, fit inside 3840x2160, preserve aspect ratio, and produce even dimensions; do not accept PNG-style 4096px long-edge video sizing. Recorder/encoder errors must reject instead of resolving corrupt blobs. The duration assertion must load the exported blob as a video, wait for metadata, and compare `video.duration` with the edited timeline duration; `blobSize > 0`, `blobType`, WebM parser fallback, or assigning the expected duration when metadata is missing are not enough.
|
|
152
159
|
|
|
153
160
|
Footer action acceptance must not include Reset. Reset is already available in the controls panel header and uses schema `defaultValue`; duplicating it in sticky `panelActions` fails acceptance.
|
|
154
161
|
|
|
155
|
-
Local `actions` acceptance must click every visible action and prove the nearby entity changed through runtime state or product output. A section-level `Randomize palette` must change palette output, `Normalize weights` must change weights/output, and `Clear selection` must clear only the scoped selection. Do not accept a test that only proves the button rendered.
|
|
162
|
+
Local `actions` acceptance must click every visible action and prove the nearby entity changed through runtime state or product output. A section-level `Randomize palette` must change palette output, `Normalize weights` must change weights/output, and `Clear selection` must clear only the scoped selection. Do not accept a test that only proves the button rendered. A single-button `actions` control fails validation when the control label duplicates the button label; the label must add concise context. Visual acceptance rejects side-label actions; labels sit above a two-column button grid where each button cell is 50% width.
|
|
156
163
|
|
|
157
164
|
`collectionActions` acceptance must click plus and minus in the real panel, prove the runtime target array length changes, prove `minItems` prevents invalid removal, prove `recommendedMaxItems` is not a hidden hard limit, and prove preview/export consumes the changed item list.
|
|
158
165
|
|
|
@@ -186,11 +193,37 @@ Acceptance rows with `product-output`, `rendered-pixels`, or `timeline-output` e
|
|
|
186
193
|
|
|
187
194
|
Animated viewport tests must also prove that canvas drag, pan, pinch, zoom, and radar/center interactions suspend or coalesce non-essential animation preview work without changing the user's play/pause state. After the interaction, the renderer must resume from the correct timeline or autonomous time and keep canvas zoom/offset stable.
|
|
188
195
|
|
|
196
|
+
## Video References
|
|
197
|
+
|
|
198
|
+
When a video, GIF, screen recording, contact sheet, or extracted-frame sequence is used as a reference, acceptance is driven by `starterTransferMode.videoReferenceStudy`.
|
|
199
|
+
|
|
200
|
+
- `storyboard` records timecoded frames with visible state and behavior observations;
|
|
201
|
+
- `transitionAnalysis` records frame-to-frame deltas, not only isolated frame descriptions;
|
|
202
|
+
- `behaviorDecomposition` states which observed behaviors must be copied;
|
|
203
|
+
- `acceptanceMapping` maps each observed video behavior to a real acceptance row;
|
|
204
|
+
- mapped acceptance rows must be automated, browser-backed, and observable in product output, timeline output, export output, or a real command side effect;
|
|
205
|
+
- `agent-worklog.md` records Video Reference Study evidence when `Reference inputs`, `Source/reference checked`, or `Source reviewed` cites video, GIF, screen recording, contact sheet, or extracted frames.
|
|
206
|
+
|
|
207
|
+
Do not accept a video reference implementation proved only by a single screenshot, a visual summary, generic canvas hashes, or static style checks.
|
|
208
|
+
|
|
209
|
+
## Reference Clone
|
|
210
|
+
|
|
211
|
+
Reference clone coverage is driven by `starterTransferMode.referenceFeatureInventory`.
|
|
212
|
+
|
|
213
|
+
- `starterTransferMode.referenceStudy` records source inspection plus original/reference behavior checked by running the original or restoring it locally when possible;
|
|
214
|
+
- list every user-visible and output-affecting reference feature before implementation;
|
|
215
|
+
- include source evidence, feature-level behavior evidence from the reference study, reference behavior, Toolcraft mapping, status, and one `acceptanceId` for each item;
|
|
216
|
+
- map every `referenceCoverage` and `referenceTimelineCoverage` acceptance row from the inventory;
|
|
217
|
+
- cover canvas sizing, control mapping, renderer loop/state, pause/resume, restart, export/copy, media lifecycle, persistence/randomization/reset, and custom reference timeline behavior when those exist in the reference;
|
|
218
|
+
- mark behavior as `intentionally-changed` only with explicit user approval or redesign/change-request evidence.
|
|
219
|
+
|
|
220
|
+
Do not treat a few generic checks as a complete reference transfer. The acceptance set must prove that the reference functionality inventory was implemented, not merely that the app renders.
|
|
221
|
+
|
|
189
222
|
## Timeline And Layers
|
|
190
223
|
|
|
191
224
|
When animation controls exist without `panels.timeline`, acceptance validation requires `starterTransferMode.animationIntent.mode = "autonomous"`. That intent must explain why the animation is decorative/self-running and must cover no user-facing transport, no play/pause, no scrub, no duration control, no loop control, and no export-at-time.
|
|
192
225
|
|
|
193
|
-
Playback timeline coverage must prove play/pause, scrub, duration, loop, restart when exposed, non-looping Play at the end restarts from 0, and export/copy at selected time when relevant. Duration coverage must edit the real `Edit timeline duration` control, prove the playback range changes, and prove the renderer maps one full product animation cycle to `state.timeline.durationSeconds`. Tests should compare visible or exported output at 0, midpoint, and
|
|
226
|
+
Playback timeline coverage must prove play/pause, scrub, duration, loop, restart when exposed, non-looping Play at the end restarts from 0, and export/copy at selected time when relevant. Timeline animation intent must match the enabled timeline mode and declare `loopDuration` with source, seconds, and evidence; `panels.timeline.defaultDurationSeconds` must match that value. Reference clones using `referenceTimeline.mode: "toolcraft-playback"` or `"toolcraft-keyframes"` must declare the same proof on `referenceTimeline.loopDuration`. Duration coverage must edit the real `Edit timeline duration` control, prove the playback range changes, and prove the renderer maps one full product animation cycle to `state.timeline.durationSeconds`. Loop coverage must prove a seamless forward-only product loop: motion advances in one direction, mirror/yoyo/ping-pong/reverse fallbacks are absent unless explicitly requested, first and last frames stitch without a visible jump, and the same seam holds after changing timeline duration. Tests should compare visible or exported output at 0, midpoint, end minus epsilon, and the wrapped first frame after changing the timeline duration. Prefer `getToolcraftTimelineLoopTime` or `getToolcraftTimelineLoopProgress` in the renderer so this phase math is shared. Do not accept a renderer that uses a separate fixed local duration while the timeline displays another duration, and do not accept a renderer effect that watches `state.timeline.durationSeconds` only to dispatch `timeline.setDuration` back to a computed local value.
|
|
194
227
|
|
|
195
228
|
Keyframe timeline coverage must prove diamond creation, expanded rows, keyframe updates on control change, scrub/playback evaluation, and product output changes for every inferred keyframe-capable control. Tests must prove renderers consume typed evaluated values from the Toolcraft keyframe evaluator; checking `valueLabel`, row count, or source strings is not enough.
|
|
196
229
|
|
|
@@ -212,6 +245,6 @@ Performance browser tests must assert budgets through `expectToolcraftScenarioPe
|
|
|
212
245
|
|
|
213
246
|
## Fixtures
|
|
214
247
|
|
|
215
|
-
Use fixtures that make each behavior visible. For example, background character-size controls need visible background characters, transparency needs alpha-sensitive pixels, selected-layer controls need multiple layers, timeline controls need deterministic playback or keyframe fixtures, and mode-specific controls need fixtures for every mode branch. Conditional coverage must prove visible controls,
|
|
248
|
+
Use fixtures that make each behavior visible. For example, background character-size controls need visible background characters, transparency needs alpha-sensitive pixels, selected-layer controls need multiple layers, timeline controls need deterministic playback or keyframe fixtures, and mode-specific controls need fixtures for every mode branch. Conditional coverage must prove visible controls, inactive controls hidden with `visibleWhen`, preserved values after switching away and back, and renderer output for the active branch. Count-controlled control banks must test both the low-count UI state and the expanded-count UI state; the test fails if inactive controls remain visible while the renderer ignores them.
|
|
216
249
|
|
|
217
250
|
Generic hash differences are not enough for semantic controls. If a control promises a direction, test that direction.
|
|
@@ -16,7 +16,7 @@ import { defineToolcraft } from "@/toolcraft/runtime";
|
|
|
16
16
|
import { ToolcraftApp } from "@/toolcraft/runtime/react";
|
|
17
17
|
|
|
18
18
|
const appSchema = defineToolcraft({
|
|
19
|
-
canvas: { enabled: true, sizing: { mode: "
|
|
19
|
+
canvas: { enabled: true, sizing: { mode: "editable-output" }, upload: true },
|
|
20
20
|
panels: {},
|
|
21
21
|
toolbar: { history: true, radar: true, theme: true, zoom: true },
|
|
22
22
|
});
|
|
@@ -28,7 +28,7 @@ export function AppHome() {
|
|
|
28
28
|
|
|
29
29
|
Routes must render `ToolcraftApp` directly. Do not compose `ToolcraftRoot`, `CanvasShell`, `ControlsPanel`, `LayersPanel`, `TimelinePanel`, or `ToolbarPanel` by hand in product routes. If a runtime surface has a performance or behavior issue, fix the shared runtime contract instead of replacing the surface with app-level UI.
|
|
30
30
|
|
|
31
|
-
App-specific source may use only runtime extension points: schema controls, `canvasContent` for product output, `controlRenderers` for true custom controls, `onPanelAction` for sticky footer actions, and runtime commands/hooks. Do not render built-in control components such as `SliderControl`, `SelectControl`, `ColorControl`, `GradientControl`, `FontPickerControl`, `FileDropControl`, or `PanelActionsControl` directly in app code. Declare them in schema so layout, reset, history,
|
|
31
|
+
App-specific source may use only runtime extension points: schema controls, `canvasContent` for product output, `controlRenderers` for true custom controls, `onPanelAction` for sticky footer actions, and runtime commands/hooks. Do not render built-in control components such as `SliderControl`, `SelectControl`, `ColorControl`, `GradientControl`, `FontPickerControl`, `FileDropControl`, or `PanelActionsControl` directly in app code. Declare them in schema so layout, reset, history, visibility, keyframes, labels, and tests stay runtime-owned.
|
|
32
32
|
|
|
33
33
|
Read `appSchema.assembly` before adding custom JSX. It lists enabled surfaces, capabilities, commands, and runtime assumptions.
|
|
34
34
|
|
|
@@ -51,22 +51,24 @@ Do not leave `mode: "starter"` in a renamed product folder or after adding produ
|
|
|
51
51
|
|
|
52
52
|
## Control Sections
|
|
53
53
|
|
|
54
|
-
Before writing the schema, make
|
|
54
|
+
Before writing the schema, make and export `starterControlSectionInventory`. Each product controls section needs a product entity or workflow stage, included targets, and a reason for grouping. Do not group by control type. The exported inventory must match the schema targets exactly; if one target entity is intentionally split across sections, every split section needs `workflowStage` and `splitReason`.
|
|
55
55
|
|
|
56
56
|
Bad section titles: `Controls`, `Settings`, `Options`, `Sliders`, `Inputs`, `Buttons`, `Color`, `Colors`.
|
|
57
57
|
|
|
58
58
|
Good section titles name the thing being edited: `Background`, `Object`, `Square 1 (Right)`, `Token Pattern`, `Motion`, `Tone Mapping`, `Export`.
|
|
59
59
|
|
|
60
|
-
Every app-authored controls-panel body section must have a short meaningful visible title. Runtime-created
|
|
60
|
+
Every app-authored controls-panel body section must have a short meaningful visible title. Runtime-created `Setup` renders as the first visible headerless controls block with no title, reset action, collapse button, or collapsed state; sticky footer action sections use the technical title `Export` but render without a visible heading.
|
|
61
61
|
|
|
62
62
|
Every visible section title renders through the standard 36px collapsible header row with vertically centered text and the runtime collapse icon. Do not hand-build section headers in generated apps.
|
|
63
63
|
|
|
64
64
|
Section expand/collapse uses the standard runtime height/opacity animation. Do not replace it with instant custom section visibility.
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
Runtime `Setup` and ordinary controls-panel body sections use 8px top spacing and 24px bottom spacing for their control content. Sticky footer action sections keep their dedicated spacing.
|
|
67
67
|
|
|
68
68
|
If a color, slider, input, or selector edits the same entity as nearby controls, keep it in that entity section. Split only when the product has a real workflow split and cover that decision in acceptance.
|
|
69
69
|
|
|
70
|
+
When a selector controls branch visibility through `visibleWhen`, treat both the selector and its branch controls as one dependency group if they share the same target entity or selected branch. Keep the selector and its gated branch controls in the same section; do not create a separate section that merely mirrors one selector option unless that branch is a genuinely separate product entity with its own workflow evidence. Do not use `disabledWhen` for product branches.
|
|
71
|
+
|
|
70
72
|
Before choosing the concrete control type for each target, check `component-rules.md` and `schema-reference.md`. Built-in compound controls must stay compound: for example, typography with font choice, weight, size, color/opacity, and text rhythm uses `fontPicker`, not a plain `select` plus separate inputs/sliders. The product renderer and acceptance rows must cover every semantic value part of the chosen component.
|
|
71
73
|
|
|
72
74
|
For custom renderers, write the Renderer Technique Decision Matrix and Render Pipeline Inventory before code. The implementation plan must map every performance-sensitive control to the pass it invalidates.
|
|
@@ -84,10 +86,24 @@ Required flow:
|
|
|
84
86
|
|
|
85
87
|
Do not implement a Figma design by eye from an image, screenshot, exported PNG, or rough visual memory. If the Figma URL is not node-specific, inspect the file/page metadata and choose the relevant node only when it is unambiguous; otherwise ask for a node-specific link.
|
|
86
88
|
|
|
89
|
+
## Video References
|
|
90
|
+
|
|
91
|
+
When the prompt provides a video, GIF, screen recording, contact sheet, or extracted-frame sequence as a reference, study it as behavior before implementation. This applies to new Toolcraft apps and reference-runtime-clone work.
|
|
92
|
+
|
|
93
|
+
Write a Video Reference Study before coding. Record the inspected source, extraction method, timecoded storyboard frames, visible state in each frame, behavior inferred from each frame, frame-to-frame transition analysis, behavior decomposition, and acceptance mapping. The transition analysis must explain what changes between frames: which entities move, which anchors or state persist, what releases or retargets, what input or timeline state drives the change, and which behavior should be copied.
|
|
94
|
+
|
|
95
|
+
Do not implement a video reference from a single screenshot, a generic visual summary, or a few static style observations. If the video cannot be opened or frames cannot be extracted, stop and record the blocker instead of guessing the temporal behavior.
|
|
96
|
+
|
|
97
|
+
Declare `starterTransferMode.videoReferenceStudy` when the app uses a video reference. Each `acceptanceMapping` item must point to a real acceptance row that proves the copied behavior with automated and browser coverage. `docs/toolcraft/agent-worklog.md` must include the Video Reference Study evidence when `Reference inputs`, `Source/reference checked`, or `Source reviewed` cites a video, GIF, screen recording, contact sheet, or extracted frames.
|
|
98
|
+
|
|
87
99
|
## Product Output
|
|
88
100
|
|
|
89
101
|
Use `canvasContent` only for product output: WebGL, Canvas 2D, SVG, DOM product text, shader previews, generated previews, export previews, or product editing handles.
|
|
90
102
|
|
|
103
|
+
If upload/import is part of the source-material flow, do not invent a design on the canvas before real content exists. The pre-content canvas stays neutral and runtime-backed; upload affordance belongs in `fileDrop`, not in canvas CTA text, helper copy, fake sample output, decorative placeholders, or agent-made source presets. A default procedural/reference source is allowed only when the prompt or reference explicitly defines it, and the worklog must record that evidence. If the default source is a file, image, or background image, declare it in `media.defaultAssets` with the matching `fileDrop` `sourceTarget`; it must render as an attached file that users can remove and Reset can restore.
|
|
104
|
+
|
|
105
|
+
If the uploaded image is background/source material inside the product canvas, keep the current `canvas.size` and render the image as cover/crop inside those bounds. Do not switch to `intrinsic-media`, do not resize the canvas to the image, and do not hide `Setup` canvas controls. Reserve `intrinsic-media` for explicitly justified media-viewer/source-native products with acceptance coverage.
|
|
106
|
+
|
|
91
107
|
```tsx
|
|
92
108
|
<ToolcraftApp
|
|
93
109
|
canvasContent={<ProductRenderer />}
|
|
@@ -115,15 +131,30 @@ Preserve the reference runtime as source of truth:
|
|
|
115
131
|
- canvas sizing and media lifecycle;
|
|
116
132
|
- control-to-renderer mapping.
|
|
117
133
|
|
|
134
|
+
Before implementation, create `starterTransferMode.referenceFeatureInventory` from the inspected reference source/runtime/UI. Include every user-visible and output-affecting behavior: controls, modes, generated objects, renderer state, media import lifecycle, canvas sizing, layers/selection, timeline/transport, export/copy, persistence, randomization, and reset behavior when present.
|
|
135
|
+
|
|
136
|
+
Each inventory item must name the reference feature, cite source evidence, cite feature-level behavior evidence from the original/restored/source-only reference study, describe the original behavior, describe the Toolcraft mapping, and point to an `acceptanceId` that proves the behavior. If behavior is intentionally changed or omitted, mark it `status: "intentionally-changed"` and cite explicit user approval or redesign/change-request evidence.
|
|
137
|
+
|
|
138
|
+
Do not rely on the user to find missing reference functionality after delivery. The port is incomplete until the inventory and acceptance coverage prove the reference functionality was reviewed and transferred.
|
|
139
|
+
|
|
118
140
|
Toolcraft still owns the shell: schema, controls, canvas, panels, toolbar, file upload, sticky footer actions, and `canvasContent`.
|
|
119
141
|
|
|
120
142
|
Do not iframe the reference, replace the route with copied original UI, or rebuild the app as a different shell.
|
|
121
143
|
|
|
144
|
+
Reference study is required before implementation. Declare `starterTransferMode.referenceStudy` and record:
|
|
145
|
+
|
|
146
|
+
- where the reference lives;
|
|
147
|
+
- which source/runtime files, routes, assets, and handlers were inspected;
|
|
148
|
+
- how the original was run or restored locally in the Toolcraft environment;
|
|
149
|
+
- which runtime/browser behaviors were checked.
|
|
150
|
+
|
|
151
|
+
Use `status: "ran-original"` when the original can run as-is. Use `status: "restored-local"` when you need to reconstruct enough of the reference inside the current environment to observe behavior. Use `status: "source-inspection-only"` only when running or restoring is blocked; include the concrete blocker and compensate with stronger source evidence and acceptance coverage.
|
|
152
|
+
|
|
122
153
|
## Animation Intent
|
|
123
154
|
|
|
124
155
|
Before adding animation controls, write an Animation Intent Inventory. Classify the animation as playback timeline, keyframes timeline, custom reference timeline, or autonomous decorative output.
|
|
125
156
|
|
|
126
|
-
If the
|
|
157
|
+
If the product output is animated, use the top playback timeline by default. Use no timeline only when the motion is non-product autonomous decoration with no user-facing play/pause, scrub, duration, loop, restart, progress, export-at-time behavior, product animation, or video export. In that case, declare `starterTransferMode.animationIntent.mode = "autonomous"` and list the absent transport behavior in `behaviorCoverage`. When the loop period is known or product-derived, set `panels.timeline.defaultDurationSeconds` to that period and record the same value in `starterTransferMode.animationIntent.loopDuration` with source and evidence. Reference clones that use `referenceTimeline.mode: "toolcraft-playback"` or `"toolcraft-keyframes"` record the same proof in `starterTransferMode.referenceTimeline.loopDuration`. Runtime/template fallback 8s is not evidence. Product loops are seamless forward-only cycles by default: the first and last frames stitch, direction does not reverse, and mirror/yoyo/ping-pong behavior needs explicit user intent. Use `getToolcraftTimelineLoopTime` or `getToolcraftTimelineLoopProgress` in playback renderers instead of local wall-clock or fixed-duration phase math.
|
|
127
158
|
|
|
128
159
|
Do not replace `TimelinePanel` with an app-level playback, transport, or timeline panel to work around performance. Playback/keyframe timeline UI is runtime-owned. Custom timeline UI is allowed only when a reference app has non-Toolcraft timeline behavior and `starterTransferMode.referenceTimeline.mode` is `"custom-reference-timeline"` with browser-backed `referenceTimelineCoverage`.
|
|
129
160
|
|
|
@@ -131,7 +162,7 @@ Animated preview renderers must prioritize viewport interactions. During canvas
|
|
|
131
162
|
|
|
132
163
|
## Canvas Sizing And Background
|
|
133
164
|
|
|
134
|
-
A base/default size in the prompt is the initial output size. It does not remove user-facing size controls.
|
|
165
|
+
A base/default, reference, or fixed-format size in the prompt is the initial output size. It does not remove user-facing size controls. Product-output, exportable, shader, procedural, and reference-clone apps use `editable-output`; keep fixed dimensions as editable `canvas.size` defaults instead of switching to `fixed-output`.
|
|
135
166
|
|
|
136
167
|
Every product app exposes output background controls:
|
|
137
168
|
|
|
@@ -146,15 +177,17 @@ Every product app needs output delivery in sticky footer `panelActions`. Still-o
|
|
|
146
177
|
|
|
147
178
|
Async product actions such as Export, Download, Copy, Generate, or Apply must return the real Promise from `ToolcraftApp onPanelAction`. The controls panel uses that Promise to show the sticky footer top accent indicator while the operation is pending. Use the `reportProgress(0..1)` callback from `onPanelAction` for determinate progress; video export reports frame-based render/encode progress, and PNG export reports phase progress for render, blob, and handoff when those phases are asynchronous. Do not fire-and-forget long export work from `onPanelAction`, and do not add custom loading strips or canvas UI for export progress.
|
|
148
179
|
|
|
149
|
-
|
|
180
|
+
Generated apps keep a controls panel so runtime `Setup` is visible from the first run. Settings import/export is mandatory runtime `Setup` behavior there; do not put Import Settings or Export Settings in sticky footer `panelActions`; runtime inserts them in the first visible headerless `Setup` controls block.
|
|
150
181
|
|
|
151
|
-
If the app also uses `editable-output` canvas sizing,
|
|
182
|
+
If the app also uses `editable-output` canvas sizing, `Setup` contains `Export Settings`, `Import Settings`, `Aspect ratio`, `Canvas width`, `Canvas height`, optional `Resolution scale`, and optional `Timeline` in that order. Do not split the canvas size fields and settings-transfer actions into app-authored sections, and do not declare runtime Setup targets in product sections.
|
|
152
183
|
|
|
153
|
-
For non-vector raster, Canvas 2D, WebGL, or WebGPU previews, set `canvas.renderScale: true`. Runtime appends `Resolution scale` to
|
|
184
|
+
For non-vector raster, Canvas 2D, WebGL, or WebGPU previews, set `canvas.renderScale: true`. Runtime appends `Resolution scale` to `Setup`. The slider changes backing resolution from `1` to `2` without changing visible canvas size; DOM/SVG/vector-native previews should not use it.
|
|
154
185
|
|
|
155
|
-
|
|
186
|
+
When `panels.timeline` is enabled, runtime appends a `Timeline` switch as the final Setup control. This is panel UI state only: off shows compact Play-only transport, on shows the extended timeline with scrubber, duration, loop, and keyframe UI. Switching it does not pause playback, remove keyframes, change export, or write product values. If `panels.timeline` is omitted, the Timeline switch must not appear.
|
|
156
187
|
|
|
157
|
-
|
|
188
|
+
If a controls panel shows only `Export Settings` and `Import Settings` in the first runtime section, check the canvas sizing decision. Product-output apps need `editable-output`; only intrinsic media and non-product/internal fixed fixtures should omit visible canvas size inputs. Adding app-authored Canvas width/height controls elsewhere is not an alternative.
|
|
189
|
+
|
|
190
|
+
For user-edited settings that should survive reload, use schema `persistence` with a stable app-specific key. When localStorage persistence is enabled, acceptance must prove a user setting restores after a real browser reload. Include `"media"` only when runtime media state itself should survive reload, such as predefined attached files that can be removed, reordered, or transformed. Do not use settings import/export as a workaround for broken persistence.
|
|
158
191
|
|
|
159
192
|
Every app with `Export PNG` must include a separate `Image Export` controls section with:
|
|
160
193
|
|
|
@@ -163,16 +196,16 @@ Every app with `Export PNG` must include a separate `Image Export` controls sect
|
|
|
163
196
|
|
|
164
197
|
`Image Export` `Format` and `Resolution` are one compact workflow pair: render them in a two-column inline row by default. For still-output apps, place `Image Export` directly above sticky footer export buttons. For animated apps with both image and video export, place `Image Export` immediately before `Video Export`.
|
|
165
198
|
|
|
166
|
-
Animated apps with `Export Video` must include a separate `Video Export` controls section with at least:
|
|
199
|
+
Animated apps with `Export Video` must enable the top Toolcraft timeline and include a separate `Video Export` controls section with at least:
|
|
167
200
|
|
|
168
201
|
- `export.video.format` as `select`, defaulting to `mp4`, with `mp4` and `webm` baseline options;
|
|
169
202
|
- `export.video.resolution` as `select`, defaulting to `current`, with options such as `current` and `4k`.
|
|
170
203
|
|
|
171
204
|
Place `Video Export` as the final authored controls section directly above sticky footer export buttons. Treat `Format` and `Resolution` as a compact semantic pair and put them in one two-column inline row by default. Use vertical rows only when the compact row would clip labels or selected values, and record that fallback reason in the worklog.
|
|
172
205
|
|
|
173
|
-
Use standard export helpers. `createToolcraftPngExportCanvas` accepts `includeBackground` for runtime PNG transparency and `resolution` for image-export output size. `shouldIncludeToolcraftPreviewBackground(state)` controls live preview product-background visibility. Pass the selected `export.image.resolution` into the PNG helper so 2K/4K/8K produce actual 2048/4096/8192px long-edge PNGs. Do not rely on static `export.png.background` alone when the UI exposes background controls. Video export keeps background and
|
|
206
|
+
Use standard export helpers. `createToolcraftPngExportCanvas` accepts `includeBackground` for runtime PNG transparency and `resolution` for image-export output size. `shouldIncludeToolcraftPreviewBackground(state)` controls live preview product-background visibility. Pass the selected `export.image.resolution` into the PNG helper so 2K/4K/8K produce actual 2048/4096/8192px long-edge PNGs. Do not rely on static `export.png.background` alone when the UI exposes background controls. Video export keeps background and uses `getToolcraftVideoExportSize` for `current` and `4k` dimensions.
|
|
174
207
|
|
|
175
|
-
Video export must choose the actual MIME/container with `MediaRecorder.isTypeSupported(...)` or an explicit encoder/transcoder capability check. `MOV` and `ProRes` are allowed only when the app provides a custom encoder/transcoder and proves it with acceptance plus performance coverage. Treat `4K` as an export resolution target, not a hardcoded canvas lock. Offline rendered-frame export must encode or mux frame timestamps from runtime timeline time; real-time `canvas.captureStream()` plus `MediaRecorder` records wall-clock export time and is not enough when renderer work can be slower than playback. Browser acceptance must load the exported blob as a video, wait for metadata, and compare `video.duration` with the edited timeline duration; `blobSize > 0`, `blobType`, parser fallback, or assigning the expected duration in `catch` is not enough.
|
|
208
|
+
Video export must choose the actual MIME/container with `MediaRecorder.isTypeSupported(...)` or an explicit encoder/transcoder capability check. `MOV` and `ProRes` are allowed only when the app provides a custom encoder/transcoder and proves it with acceptance plus performance coverage. Treat `4K` as an export resolution target, not a hardcoded canvas lock and not PNG-style 4096px long-edge sizing. `getToolcraftVideoExportSize` keeps `current` at the current canvas/output size with even encoder-safe rounding, and keeps `4k` encoder-safe by fitting inside 3840x2160, preserving aspect ratio, and returning even dimensions. Set recording canvas dimensions before `captureStream`, `MediaRecorder`, `VideoEncoder`, or equivalent setup, and reject recorder/encoder errors instead of returning corrupt blobs. Offline rendered-frame export must encode or mux frame timestamps from runtime timeline time; real-time `canvas.captureStream()` plus `MediaRecorder` records wall-clock export time and is not enough when renderer work can be slower than playback. Browser acceptance must load the exported blob as a video, wait for metadata, and compare `video.duration` with the edited timeline duration; `blobSize > 0`, `blobType`, parser fallback, or assigning the expected duration in `catch` is not enough.
|
|
176
209
|
|
|
177
210
|
## Verification Tiers
|
|
178
211
|
|
|
@@ -193,18 +226,20 @@ Use these tiers:
|
|
|
193
226
|
| Tier 1 — local control presentation | One control or panel visual state changes: spacing, hover, focus, disabled, marker visibility, label fit, or component variant display. Runtime state shape and product renderer are unchanged. | Targeted unit/component test plus one focused browser check for the affected control or panel. |
|
|
194
227
|
| Tier 2 — schema/product behavior | Controls, sections, defaults, persistence, panel actions, export actions, acceptance rows, or product behavior mapping changes. | `pnpm verify:quick` plus relevant browser acceptance. Run perf only when the changed control affects renderer workload or responsiveness. |
|
|
195
228
|
| Tier 3 — renderer/canvas/runtime feature | Custom renderer, animation loop, canvas sizing, upload/media, timeline, layers, toolbar, export bytes, WebGL/Canvas/SVG output, zoom, radar, history, heavy control behavior changes, or a post-generation iteration that touches renderer workload or viewport stability. | `pnpm verify:quick`, targeted browser acceptance, and targeted performance scenarios only for touched workload/viewport/export paths. |
|
|
196
|
-
| Tier 4 — final delivery/template architecture | Fresh generated app completion, folder export, commit-ready delivery, dependency changes, runtime/template/contract/CLI changes, broad refactors, or major post-generation iterations that rewrite renderer, canvas, animation, timeline/keyframes, layers, media, export, or control mapping. | Fresh folders run `pnpm install` once, then `pnpm verify:final`;
|
|
229
|
+
| Tier 4 — final delivery/template architecture | Fresh generated app completion, folder export, commit-ready delivery, dependency changes, runtime/template/contract/CLI changes, broad refactors, or major post-generation iterations that rewrite renderer, canvas, animation, timeline/keyframes, layers, media, export, or control mapping. | Fresh folders run `pnpm install` once, then `pnpm verify:final`; for the first working product version also run and pass a browser performance checkpoint with the current AI agent's controlled browser when available, using `pnpm verify:perf` only as fallback, then start `pnpm dev` to provide the local URL. |
|
|
197
230
|
|
|
198
231
|
Choose the tier by blast radius, not by line count. If uncertain, move one tier higher, not automatically to Tier 4.
|
|
199
232
|
|
|
200
233
|
Do not rerun `pnpm install` after every edit. Run it after fresh export, dependency changes, lockfile changes, or a missing package error.
|
|
201
234
|
|
|
202
|
-
Use `pnpm verify:ui` when a tier calls for the browser acceptance suite without the performance suite. Use a focused named Playwright test
|
|
235
|
+
Use `pnpm verify:ui` when a tier calls for the browser acceptance suite without the performance suite. Use the agent-controlled browser for focused checks when available; use a focused named Playwright test only as fallback when no agent browser is available or the relevant CI/non-agent check is already known.
|
|
203
236
|
|
|
204
|
-
Run a full performance checkpoint
|
|
237
|
+
Run a full performance checkpoint only when the first working version of the app exists, or when the user explicitly asks to optimize performance, fix lag, remove jank, speed up animation, stabilize drag/zoom, or otherwise complains about performance. Prefer the agent-controlled browser; use `pnpm verify:perf` only as the Playwright fallback.
|
|
205
238
|
|
|
206
239
|
Feature loops after the first working version do not run the full performance suite by default. Renderer, canvas, animation, export, timeline, layers, `canvas.renderScale`, bug fixes, and performance-sensitive controls still need targeted functional/browser checks first, plus targeted performance scenarios only when they directly exercise the touched path. Record any skipped full performance run and reason in the worklog.
|
|
207
240
|
|
|
241
|
+
The app is not complete when required checks are failed, incomplete, pending, blocked, or listed as skipped. First working product delivery must record `pnpm verify:final` and the browser performance checkpoint as passed in the worklog, including runner `agent-browser` or `playwright-fallback`. After the first working version, skipping the full performance suite is valid only when the worklog explicitly says the full performance checkpoint is not required for a post-first-working non-performance edit.
|
|
242
|
+
|
|
208
243
|
For final delivery, run:
|
|
209
244
|
|
|
210
245
|
```bash
|
|
@@ -212,6 +247,6 @@ pnpm verify:final
|
|
|
212
247
|
pnpm dev
|
|
213
248
|
```
|
|
214
249
|
|
|
215
|
-
Browser verification must use the real Toolcraft shell plus renderer output. `pnpm verify:final` runs the full static, build, and browser functional gate.
|
|
250
|
+
Browser verification must use the real Toolcraft shell plus renderer output. `pnpm verify:final` runs the full static, build, and browser functional gate. The browser performance checkpoint is intentionally separate and only runs for the two full-performance triggers; `pnpm verify:perf` is the Playwright fallback command for that checkpoint. `pnpm dev` is intentionally separate because it keeps the local server running.
|
|
216
251
|
|
|
217
|
-
Do not stop existing local servers to free `3002
|
|
252
|
+
Do not stop existing local servers to free `3002` during a first start. `pnpm dev`, `pnpm preview`, and browser verification prefer `3002`, then automatically use the next free port only while assigning the app's first saved port. After that, normal dev/preview starts use the saved port; if that port already serves the same app, report the existing URL instead of creating a second server. A launch is valid only after the selected port serves the current app root through the Toolcraft server identity endpoint and the app title marker from `index.html`; a random listener on that port is not enough. When restarting an app server you already started, use `pnpm dev:restart` or `pnpm preview:restart`; restart mode reuses the previously saved app port, stops the listener on that exact port if needed, force-stops it if the port is still occupied, starts on the same port again, and verifies the same app identity before saving/reporting the port.
|