@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 +1 -1
- package/src/generate.test.mjs +49 -6
- package/templates/starter/AGENTS.md +4 -3
- package/templates/starter/docs/toolcraft/README.md +15 -0
- package/templates/starter/docs/toolcraft/acceptance-testing.md +2 -0
- package/templates/starter/docs/toolcraft/assembly-workflow.md +35 -171
- package/templates/starter/docs/toolcraft/component-rules.md +12 -188
- package/templates/starter/docs/toolcraft/core/control-selection.md +93 -0
- package/templates/starter/docs/toolcraft/core/layout.md +104 -0
- package/templates/starter/docs/toolcraft/core/media-upload.md +85 -0
- package/templates/starter/docs/toolcraft/core/performance.md +83 -0
- package/templates/starter/docs/toolcraft/core/reference-study.md +115 -0
- package/templates/starter/docs/toolcraft/core/runtime-boundary.md +53 -0
- package/templates/starter/docs/toolcraft/core/setup-export.md +86 -0
- package/templates/starter/docs/toolcraft/core/timeline-animation.md +67 -0
- package/templates/starter/docs/toolcraft/custom-controls.md +2 -0
- package/templates/starter/docs/toolcraft/performance.md +2 -0
- package/templates/starter/docs/toolcraft/renderer-technique.md +2 -0
- package/templates/starter/docs/toolcraft/schema-reference.md +117 -367
- package/templates/starter/docs/toolcraft/workflow.md +12 -10
- package/templates/starter/scripts/check-toolcraft-docs.mjs +28 -6
- package/templates/starter/src/app/starter-acceptance.test.ts +9 -8
package/package.json
CHANGED
package/src/generate.test.mjs
CHANGED
|
@@ -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(
|
|
290
|
-
assert.match(
|
|
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(
|
|
293
|
-
assert.match(
|
|
294
|
-
assert.match(
|
|
295
|
-
assert.match(
|
|
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
|
|
28
|
-
14.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47
|
+
## Product Readiness
|
|
36
48
|
|
|
37
|
-
The starter baseline is
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
78
|
+
## Reference And Design Sources
|
|
137
79
|
|
|
138
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
86
|
+
## Timeline And Animation
|
|
145
87
|
|
|
146
|
-
|
|
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 `
|
|
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
|
-
##
|
|
92
|
+
## Renderer Work
|
|
154
93
|
|
|
155
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|