@pixel-point/toolcraft 0.0.13 → 0.0.14

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixel-point/toolcraft",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
5
  "type": "module",
6
6
  "bin": {
@@ -166,6 +166,14 @@ describe("generateToolcraft", () => {
166
166
  assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/renderer-technique.md")));
167
167
  assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/custom-controls.md")));
168
168
  assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/component-rules.md")));
169
+ assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/core/runtime-boundary.md")));
170
+ assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/core/setup-export.md")));
171
+ assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/core/control-selection.md")));
172
+ assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/core/layout.md")));
173
+ assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/core/media-upload.md")));
174
+ assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/core/timeline-animation.md")));
175
+ assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/core/performance.md")));
176
+ assert.ok(await fs.stat(path.join(targetDir, "docs/toolcraft/core/reference-study.md")));
169
177
  assert.ok(await fs.stat(path.join(targetDir, "src/toolcraft/.toolcraft-manifest.json")));
170
178
 
171
179
  const appPerformanceSource = await fs.readFile(
@@ -224,6 +232,15 @@ describe("generateToolcraft", () => {
224
232
  const licenseSource = await fs.readFile(path.join(targetDir, "LICENSE.md"), "utf8");
225
233
  const noticeSource = await fs.readFile(path.join(targetDir, "NOTICE.md"), "utf8");
226
234
  const localDocPaths = [
235
+ "workflow.md",
236
+ "core/runtime-boundary.md",
237
+ "core/setup-export.md",
238
+ "core/control-selection.md",
239
+ "core/layout.md",
240
+ "core/media-upload.md",
241
+ "core/timeline-animation.md",
242
+ "core/performance.md",
243
+ "core/reference-study.md",
227
244
  "assembly-workflow.md",
228
245
  "decision-contract.md",
229
246
  "schema-reference.md",
@@ -282,17 +299,43 @@ describe("generateToolcraft", () => {
282
299
  path.join(targetDir, "docs/toolcraft/component-rules.md"),
283
300
  "utf8",
284
301
  );
302
+ const coreControlSelectionSource = await fs.readFile(
303
+ path.join(targetDir, "docs/toolcraft/core/control-selection.md"),
304
+ "utf8",
305
+ );
306
+ const coreLayoutSource = await fs.readFile(
307
+ path.join(targetDir, "docs/toolcraft/core/layout.md"),
308
+ "utf8",
309
+ );
310
+ const coreMediaUploadSource = await fs.readFile(
311
+ path.join(targetDir, "docs/toolcraft/core/media-upload.md"),
312
+ "utf8",
313
+ );
314
+ const coreRuntimeBoundarySource = await fs.readFile(
315
+ path.join(targetDir, "docs/toolcraft/core/runtime-boundary.md"),
316
+ "utf8",
317
+ );
318
+ const coreSetupExportSource = await fs.readFile(
319
+ path.join(targetDir, "docs/toolcraft/core/setup-export.md"),
320
+ "utf8",
321
+ );
322
+ const coreTimelineSource = await fs.readFile(
323
+ path.join(targetDir, "docs/toolcraft/core/timeline-animation.md"),
324
+ "utf8",
325
+ );
285
326
  assert.match(componentRulesSource, /Slider `step` means numeric snapping only/);
286
327
  assert.match(componentRulesSource, /variant: "discrete"/);
287
328
  assert.match(componentRulesSource, /Keep large or precision stepped ranges visually continuous/);
288
329
  assert.match(componentRulesSource, /Segmented Controls/);
289
- assert.match(componentRulesSource, /Never generate a section titled `Color` or `Colors`/);
290
- assert.match(componentRulesSource, /Use `fileDrop` for source material uploads/);
330
+ assert.match(coreLayoutSource, /Bad titles: `Controls`, `Settings`, `Options`, `Sliders`, `Inputs`, `Buttons`, `Color`, `Colors`/);
331
+ assert.match(coreMediaUploadSource, /Use `fileDrop` for source material uploads/);
332
+ assert.match(coreControlSelectionSource, /Use `fileDrop` for source material uploads/);
333
+ assert.match(coreRuntimeBoundarySource, /appSchema\.assembly/);
291
334
  assert.match(componentRulesSource, /Do not show Layers for a single-layer app/);
292
- assert.match(componentRulesSource, /Use playback timeline/);
293
- assert.match(componentRulesSource, /Still-output product apps include one primary `Export PNG` action/);
294
- assert.match(componentRulesSource, /Animated product apps include `Export Video`/);
295
- assert.match(componentRulesSource, /Copy never replaces export/);
335
+ assert.match(coreTimelineSource, /Any app with `Export Video` must enable the top Toolcraft timeline/);
336
+ assert.match(coreSetupExportSource, /Still products expose `Export PNG`/);
337
+ assert.match(coreSetupExportSource, /Animated products expose `Export Video` plus `Export PNG`/);
338
+ assert.match(coreSetupExportSource, /Clipboard copy is optional and never replaces export/);
296
339
 
297
340
  const assemblyDocsSource = await fs.readFile(
298
341
  path.join(targetDir, "docs/toolcraft/assembly-workflow.md"),
@@ -24,11 +24,11 @@ Then follow `workflow.md` to choose the required contract docs and verification
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
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
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`.
27
+ 13. Generated apps follow the mandatory runtime Setup, canvas sizing, render scale, Timeline switch, Background, Image Export, Video Export, and sticky action rules in `docs/toolcraft/core/setup-export.md`. Do not duplicate or reinterpret those controls in app-authored sections.
28
+ 14. Media uploads, image/file mode, source images, multi-upload sorting, default assets, and image transform actions follow `docs/toolcraft/core/media-upload.md`.
29
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
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.
31
+ 17. Performance workload, render scale, live slider responsiveness, GPU evaluation, and optimization evidence rules live in `docs/toolcraft/core/performance.md` plus `docs/toolcraft/performance.md`.
32
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
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.
34
34
 
@@ -47,6 +47,7 @@ This project includes Toolcraft source code governed by the Toolcraft Designer L
47
47
  Use this `AGENTS.md` as the entry contract. Use local docs for detail; the app must remain buildable without the website.
48
48
 
49
49
  - `docs/toolcraft/workflow.md` — required preflight, task routing, worklog gate, and verification routing.
50
+ - `docs/toolcraft/core/runtime-boundary.md`, `docs/toolcraft/core/setup-export.md`, `docs/toolcraft/core/control-selection.md`, `docs/toolcraft/core/layout.md`, `docs/toolcraft/core/media-upload.md`, `docs/toolcraft/core/timeline-animation.md`, `docs/toolcraft/core/performance.md`, `docs/toolcraft/core/reference-study.md` — focused core modules routed by `workflow.md`.
50
51
  - `docs/toolcraft/assembly-workflow.md` — runtime assembly, canvas output, and reference clone path.
51
52
  - `docs/toolcraft/decision-contract.md` — rule ids, levels, and enforcement expectations.
52
53
  - `docs/toolcraft/schema-reference.md` — schema authoring rules for `src/app/app-schema.ts`.
@@ -6,6 +6,21 @@ Use `../../AGENTS.md` as the entry contract, then read `workflow.md` before plan
6
6
 
7
7
  The starter app itself is intentionally neutral. It should show the Toolcraft canvas/upload/toolbar baseline only until the product schema is authored. Demo controls, prompt inputs, layers, and timeline belong in tests/docs or in a real generated product that needs them.
8
8
 
9
+ ## Core modules
10
+
11
+ `workflow.md` routes agents to these focused modules. Read every module listed for the task type; each module is intended to be small enough to read fully without relying on truncated terminal output.
12
+
13
+ - `core/runtime-boundary.md` — Toolcraft shell, allowed extension points, canvas boundary, and generated-app source boundary.
14
+ - `core/setup-export.md` — required Setup, canvas sizing, render scale, Timeline switch, Background, Image Export, Video Export, and sticky export actions.
15
+ - `core/control-selection.md` — built-in control fit, exact owners, compound controls, actions, collection actions, vector ownership, and custom control gate.
16
+ - `core/layout.md` — sections, dependency cohesion, headers, reset, spacing, dividers, labels, inline rows, actions layout, colors, select, and segmented fit.
17
+ - `core/media-upload.md` — file/image upload, multi-upload, sorting, transform actions, canvas source images, default assets, and source material behavior.
18
+ - `core/timeline-animation.md` — animation intent, timeline requirement, compact/extended timeline, seamless forward loops, duration changes, keyframes, and video timing.
19
+ - `core/performance.md` — verification triggers, workload fixtures, media/pixel workloads, render scale, live slider responsiveness, renderer pipeline inventory, and optimization evidence.
20
+ - `core/reference-study.md` — reference-runtime clone, feature inventory, reference study, Figma source, video references, acceptance mapping, and worklog evidence.
21
+
22
+ The broad docs below remain compatibility and topic references. They do not replace `workflow.md` routing or the `core/*` modules.
23
+
9
24
  1. `workflow.md` — required preflight, task routing, worklog gate, and verification routing.
10
25
  2. `assembly-workflow.md` — how the app must be assembled.
11
26
  3. `decision-contract.md` — hard rules, defaults, heuristics, and escape hatches.
@@ -1,5 +1,7 @@
1
1
  # Acceptance Testing
2
2
 
3
+ > Reading route: start with `workflow.md`. Core generated-app rules live in `core/*`; this file is a focused acceptance reference for the topic below.
4
+
3
5
  Every visible product entity must prove it works. A control is not accepted because it renders; it is accepted only when tests prove user interaction changes runtime state and the final product output, command side effect, timeline frame, layer result, media lifecycle, or canvas viewport.
4
6
 
5
7
  ## Required Files
@@ -1,5 +1,7 @@
1
1
  # Assembly Workflow
2
2
 
3
+ > Reading route: start with `workflow.md`. Core generated-app rules live in `core/*`; this file is the focused runtime assembly path.
4
+
3
5
  Build the app from the local Toolcraft runtime copy. Do not recreate controls, panels, toolbar, canvas behavior, timeline, layers, or app chrome by hand.
4
6
 
5
7
  Use:
@@ -9,6 +11,8 @@ Use:
9
11
  - `@/toolcraft/runtime/styles.css` for runtime styles.
10
12
  - `@/toolcraft/ui` for visual components.
11
13
 
14
+ ## Runtime Path
15
+
12
16
  Declare the product with `defineToolcraft`. Render through `ToolcraftApp`.
13
17
 
14
18
  ```tsx
@@ -26,15 +30,23 @@ export function AppHome() {
26
30
  }
27
31
  ```
28
32
 
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.
33
+ Routes must render `ToolcraftApp` directly. Do not compose `ToolcraftRoot`, `CanvasShell`, `ControlsPanel`, `LayersPanel`, `TimelinePanel`, or `ToolbarPanel` by hand. If a runtime surface has a performance or behavior issue, fix the shared runtime instead of replacing the surface locally.
34
+
35
+ Allowed app extension points:
30
36
 
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.
37
+ | Extension point | Use for |
38
+ | --- | --- |
39
+ | Schema controls | Built-in controls, targets, defaults, visibility, panel actions. |
40
+ | `canvasContent` | Product output only. |
41
+ | `controlRenderers` | True custom controls only after the built-in fit check. |
42
+ | `onPanelAction` | Sticky footer product actions. |
43
+ | Runtime commands/hooks | History, media, canvas, timeline, layers, and controlled app behavior. |
32
44
 
33
- Read `appSchema.assembly` before adding custom JSX. It lists enabled surfaces, capabilities, commands, and runtime assumptions.
45
+ Do not render built-in controls 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.
34
46
 
35
- Toolbar history owns undo/redo buttons and keyboard shortcuts. When `toolbar.history` is enabled, the runtime handles `Cmd/Ctrl+Z`, `Cmd/Ctrl+Shift+Z`, and `Ctrl+Y`, while ignoring shortcuts inside inputs, textareas, selects, and editable value labels. Do not add route-local undo/redo keyboard listeners.
47
+ ## Product Readiness
36
48
 
37
- The starter baseline is deliberately neutral. It must not include demo controls, prompt fields, timeline, or layers until the product behavior requires them. Use tests and docs fixtures to exercise component coverage; do not expose those fixtures in the starting product schema.
49
+ The starter baseline is neutral: canvas/upload/toolbar shell only. Do not include demo controls, prompt fields, timeline, or layers until product behavior requires them.
38
50
 
39
51
  Once the folder is a real product, switch `src/app/app-acceptance.ts` from neutral readiness to:
40
52
 
@@ -47,169 +59,45 @@ export const appProductReadiness = {
47
59
  } as const;
48
60
  ```
49
61
 
50
- Do not leave `mode: "starter"` in a renamed product folder or after adding product controls, `canvasContent`, timeline, layers, or acceptance rows.
51
-
52
- ## Control Sections
53
-
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
-
56
- Bad section titles: `Controls`, `Settings`, `Options`, `Sliders`, `Inputs`, `Buttons`, `Color`, `Colors`.
57
-
58
- Good section titles name the thing being edited: `Background`, `Object`, `Square 1 (Right)`, `Token Pattern`, `Motion`, `Tone Mapping`, `Export`.
59
-
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
-
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
-
64
- Section expand/collapse uses the standard runtime height/opacity animation. Do not replace it with instant custom section visibility.
65
-
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
-
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
-
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
-
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.
73
-
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.
75
-
76
- ## Figma Source
77
-
78
- When the prompt provides a Figma URL, treat the Figma file as the design source of truth.
62
+ ## Controls
79
63
 
80
- Required flow:
64
+ Before writing product sections, export `starterControlSectionInventory`. Each product section declares its title, targets, product entity or workflow stage, and grouping reason.
81
65
 
82
- - Use Figma MCP/design context before implementation.
83
- - Inspect the target node, layer tree, component instances, variants, text nodes, variables, styles, and assets.
84
- - Recreate the design from the Figma structure and Toolcraft runtime/component contracts.
85
- - Use screenshots only for final visual QA after reading the file structure.
66
+ Use `core/layout.md` for section grouping, dependency cohesion, headers, reset, collapse, spacing, dividers, labels, and inline rows. Use `core/control-selection.md` and `component-rules.md` before choosing concrete controls. Built-in compound controls stay compound; extend the kit instead of splitting owned fields into neighboring controls.
86
67
 
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.
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
-
99
- ## Product Output
68
+ ## Canvas And Product Output
100
69
 
101
70
  Use `canvasContent` only for product output: WebGL, Canvas 2D, SVG, DOM product text, shader previews, generated previews, export previews, or product editing handles.
102
71
 
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
-
107
- ```tsx
108
- <ToolcraftApp
109
- canvasContent={<ProductRenderer />}
110
- renderDefaultCanvasMedia={false}
111
- schema={appSchema}
112
- />
113
- ```
114
-
115
72
  `canvasContent` must not contain app UI: buttons, forms, CTAs, upload prompts, helper text, settings, menus, labels, placeholder copy, or empty-state instructions.
116
73
 
117
- Product text rendered as DOM must be marked with `data-toolcraft-product-output` or `data-toolcraft-product-text`. Product editing handles must be textless overlays, write to runtime state, and stay out of export/copy output.
118
-
119
- Preserve the runtime canvas surface. Product renderers may draw their own output background, but must not hide, replace, or make the Toolcraft canvas backing transparent.
120
-
121
- ## Reference Runtime Clone
122
-
123
- When porting an existing app, use `transferMode: "reference-runtime-clone"` unless the user explicitly asks for redesign.
124
-
125
- Preserve the reference runtime as source of truth:
126
-
127
- - animation loop and time ownership;
128
- - refs and mutable renderer state;
129
- - particles, objects, connections, spawn cadence, and lifetime rules;
130
- - pause/resume, restart, progress, export, and copy semantics;
131
- - canvas sizing and media lifecycle;
132
- - control-to-renderer mapping.
74
+ If upload/import is part of the source-material flow, use `fileDrop` and keep the pre-content canvas neutral. Do not invent canvas placeholder artwork, source CTAs, fake sample output, or hidden preset files. Use `media.defaultAssets` when the prompt or reference actually provides default files.
133
75
 
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.
76
+ Use `core/runtime-boundary.md` for shell boundaries, `core/media-upload.md` for upload behavior, and `core/setup-export.md` for editable output size, background, and export sections.
135
77
 
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.
78
+ ## Reference And Design Sources
137
79
 
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.
80
+ If a Figma URL is provided, use Figma MCP/design context before implementation and rebuild from file structure, not from a screenshot.
139
81
 
140
- Toolcraft still owns the shell: schema, controls, canvas, panels, toolbar, file upload, sticky footer actions, and `canvasContent`.
82
+ If a video, GIF, screen recording, contact sheet, or extracted-frame sequence is provided, write a Video Reference Study before implementation.
141
83
 
142
- Do not iframe the reference, replace the route with copied original UI, or rebuild the app as a different shell.
84
+ When porting an existing app, use `transferMode: "reference-runtime-clone"` unless the user explicitly asks for redesign. Declare `referenceStudy` plus `referenceFeatureInventory`, then prove each inspected reference feature with acceptance coverage. Use `core/reference-study.md` for the detailed reference, Figma, and video study rules.
143
85
 
144
- Reference study is required before implementation. Declare `starterTransferMode.referenceStudy` and record:
86
+ ## Timeline And Animation
145
87
 
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.
88
+ Before adding animation controls, write an Animation Intent Inventory. Product animation, keyframes, playback, and video export use the top Toolcraft timeline. Autonomous no-timeline animation is allowed only for non-product decorative motion with no user-facing transport and no video export.
150
89
 
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.
90
+ Use `core/timeline-animation.md` for timeline mode, compact/extended timeline, seamless forward loops, duration changes, keyframes, viewport interaction performance, and video export timing.
152
91
 
153
- ## Animation Intent
92
+ ## Renderer Work
154
93
 
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.
94
+ For custom renderers, write the Renderer Technique Decision Matrix and Render Pipeline Inventory before code. The implementation plan maps every performance-sensitive control to the render pass it invalidates.
156
95
 
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.
158
-
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`.
160
-
161
- Animated preview renderers must prioritize viewport interactions. During canvas drag, pan, pinch, zoom, and radar/center, suspend or coalesce non-essential animation work, then resume from the correct timeline or autonomous time without changing the user's play/pause state.
162
-
163
- ## Canvas Sizing And Background
164
-
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`.
166
-
167
- Every product app exposes output background controls:
168
-
169
- - `appearance.background` or `scene.background` as a schema `color` control;
170
- - `export.includeBackground` as a `switch`, `checkbox`, `select`, or `segmented` control.
171
-
172
- Preview, PNG export, and video export read the background color runtime value. PNG export passes the include-background runtime value to the export helper. Live preview calls `shouldIncludeToolcraftPreviewBackground(state)` and hides only the product-rendered background when Include is off; the Toolcraft canvas backing stays visible. Video output keeps the background.
173
-
174
- Keep those controls together in one required `Background` section directly before the first export settings section. With PNG export that first settings section is `Image Export`; with video-only export it is `Video Export`. Use an equal-width inline row with `export.includeBackground` on the left and the background color parameter on the right; each control occupies half the row. The switch label is `Include`; the color control uses `label: false` because the section title already supplies the background context.
175
-
176
- Every product app needs output delivery in sticky footer `panelActions`. Still-output apps expose `Export PNG`. Animated apps expose `Export Video` and `Export PNG`. Clipboard copy is optional and never replaces export. If an odd number of footer actions leaves one action alone in the final row, that final action spans the full row.
177
-
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.
179
-
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.
181
-
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.
183
-
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.
185
-
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.
187
-
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.
191
-
192
- Every app with `Export PNG` must include a separate `Image Export` controls section with:
193
-
194
- - `export.image.format` as `select`, defaulting to `png`, with `png` and `jpg` baseline options;
195
- - `export.image.resolution` as `select`, defaulting to `4k`, with `2k`, `4k`, and `8k` baseline options.
196
-
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`.
198
-
199
- Animated apps with `Export Video` must enable the top Toolcraft timeline and include a separate `Video Export` controls section with at least:
200
-
201
- - `export.video.format` as `select`, defaulting to `mp4`, with `mp4` and `webm` baseline options;
202
- - `export.video.resolution` as `select`, defaulting to `current`, with options such as `current` and `4k`.
203
-
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.
205
-
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.
207
-
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.
96
+ Use `renderer-technique.md` and `core/performance.md` for renderer strategy, cache keys, workload fixtures, render scale, and optimization evidence.
209
97
 
210
98
  ## Verification Tiers
211
99
 
212
- Before every edit, classify the change by blast radius and write the planned checks in the implementation note or plan:
100
+ Before every edit, classify blast radius and record the planned checks:
213
101
 
214
102
  ```md
215
103
  Verification tier: Tier N
@@ -218,27 +106,7 @@ Run: <commands and browser checks>
218
106
  Skip: <checks not needed for this pass and why>
219
107
  ```
220
108
 
221
- Use these tiers:
222
-
223
- | Tier | Use When | Required Checks |
224
- | --- | --- | --- |
225
- | Tier 0 — docs/copy | Documentation, comments, copy, labels, or titles change without schema targets, values, runtime behavior, renderer output, or layout mechanics. | Targeted docs/typecheck or targeted app test. Browser is not required unless visual text fitting is the risk. |
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. |
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. |
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. |
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. |
230
-
231
- Choose the tier by blast radius, not by line count. If uncertain, move one tier higher, not automatically to Tier 4.
232
-
233
- Do not rerun `pnpm install` after every edit. Run it after fresh export, dependency changes, lockfile changes, or a missing package error.
234
-
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.
236
-
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.
238
-
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.
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.
109
+ Use `pnpm verify:ui` when browser acceptance is required without the performance suite. Run `pnpm verify:final` for first working product delivery, folder export, runtime/template/contract/CLI changes, broad refactors, and final gates. Full performance checkpoints run only for the first working product version or explicit performance complaints; otherwise run targeted performance checks only for touched paths.
242
110
 
243
111
  For final delivery, run:
244
112
 
@@ -246,7 +114,3 @@ For final delivery, run:
246
114
  pnpm verify:final
247
115
  pnpm dev
248
116
  ```
249
-
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 default `pnpm test:browser` / `pnpm verify:ui` gate excludes every Playwright test whose name contains `browser perf:`, including performance audit and budget scenarios. 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.
251
-
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.