@pixel-point/toolcraft 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/package.json +6 -1
- package/src/cli.mjs +226 -17
- package/src/cli.test.mjs +127 -2
- package/templates/runtime/contracts/component-contracts.test.ts +28 -7
- package/templates/runtime/contracts/component-contracts.ts +14 -7
- package/templates/runtime/contracts/decision-contracts.ts +1 -1
- package/templates/runtime/export/export.test.ts +65 -0
- package/templates/runtime/export/export.ts +54 -1
- package/templates/runtime/react/controls-panel.test.tsx +54 -6
- package/templates/runtime/react/controls-panel.tsx +216 -0
- package/templates/runtime/react/settings-transfer.test.ts +6 -0
- package/templates/runtime/react/settings-transfer.ts +28 -2
- package/templates/runtime/schema/canvas-aspect-ratio-presets.ts +50 -0
- package/templates/runtime/schema/define-toolcraft.test.ts +45 -1
- package/templates/runtime/schema/define-toolcraft.ts +60 -2
- package/templates/runtime/schema/keyframe-capability.test.ts +7 -0
- package/templates/runtime/schema/keyframe-capability.ts +2 -2
- package/templates/runtime/schema/runtime-targets.ts +5 -0
- package/templates/runtime/state/create-template-state.test.ts +6 -0
- package/templates/runtime/state/reducer.test.ts +55 -0
- package/templates/runtime/state/reducer.ts +214 -9
- package/templates/starter/AGENTS.md +5 -3
- package/templates/starter/docs/toolcraft/acceptance-testing.md +3 -1
- package/templates/starter/docs/toolcraft/assembly-workflow.md +10 -3
- package/templates/starter/docs/toolcraft/component-rules.md +12 -5
- package/templates/starter/docs/toolcraft/schema-reference.md +45 -7
- package/templates/starter/scripts/check-ai-skills.mjs +39 -4
- package/templates/starter/src/app/starter-acceptance.test.ts +623 -21
- package/templates/starter/src/app/starter-acceptance.ts +290 -3
- package/templates/ui/components/control-layout/index.tsx +4 -4
- package/templates/ui/components/controls/font-picker/font-picker-control.tsx +1 -1
- package/toolcraft-skills/brainstorming/SKILL.md +28 -0
- package/toolcraft-skills/browser/SKILL.md +25 -0
- package/toolcraft-skills/figma/SKILL.md +24 -0
- package/toolcraft-skills/figma-implement-design/SKILL.md +24 -0
- package/toolcraft-skills/systematic-debugging/SKILL.md +24 -0
- package/toolcraft-skills/writing-plans/SKILL.md +26 -0
|
@@ -766,7 +766,7 @@ function getToggleControlLabelError(
|
|
|
766
766
|
normalizeToolcraftSemanticText(label) ===
|
|
767
767
|
normalizeToolcraftSemanticText(sectionTitle)
|
|
768
768
|
) {
|
|
769
|
-
return `toggle label "${label}" duplicates section title "${sectionTitle}". Use
|
|
769
|
+
return `toggle label "${label}" duplicates section title "${sectionTitle}". Use a shorter contextual label such as "Include" or rename the toggle to a more specific setting.`;
|
|
770
770
|
}
|
|
771
771
|
|
|
772
772
|
return undefined;
|
|
@@ -893,6 +893,15 @@ function actionLooksLikePngExport(action: ToolcraftActionSchema | string): boole
|
|
|
893
893
|
);
|
|
894
894
|
}
|
|
895
895
|
|
|
896
|
+
function actionLooksLikeVideoExport(action: ToolcraftActionSchema | string): boolean {
|
|
897
|
+
const text = getActionSearchText(action).replace(/([a-z])([A-Z])/g, "$1 $2");
|
|
898
|
+
|
|
899
|
+
return (
|
|
900
|
+
(/\b(export|download)\b/i.test(text) && /\b(video|mp4|webm|mov)\b/i.test(text)) ||
|
|
901
|
+
/\bexport\.video\b/i.test(text)
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
|
|
896
905
|
function schemaHasPngExportPanelAction(schema: ResolvedToolcraftAppSchema): boolean {
|
|
897
906
|
return (schema.panels.controls?.sections ?? []).some((section) =>
|
|
898
907
|
Object.values(section.controls).some(
|
|
@@ -903,6 +912,57 @@ function schemaHasPngExportPanelAction(schema: ResolvedToolcraftAppSchema): bool
|
|
|
903
912
|
);
|
|
904
913
|
}
|
|
905
914
|
|
|
915
|
+
function schemaHasVideoExportPanelAction(schema: ResolvedToolcraftAppSchema): boolean {
|
|
916
|
+
return (schema.panels.controls?.sections ?? []).some((section) =>
|
|
917
|
+
Object.values(section.controls).some(
|
|
918
|
+
(control) =>
|
|
919
|
+
control.type === "panelActions" &&
|
|
920
|
+
getControlActions(control).some(actionLooksLikeVideoExport),
|
|
921
|
+
),
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
function getFirstPanelActionsSectionIndex(schema: ResolvedToolcraftAppSchema): number {
|
|
926
|
+
return (schema.panels.controls?.sections ?? []).findIndex((section) =>
|
|
927
|
+
Object.values(section.controls).some((control) => control.type === "panelActions"),
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
function getSchemaControlsSectionByTitle(
|
|
932
|
+
schema: ResolvedToolcraftAppSchema,
|
|
933
|
+
title: string,
|
|
934
|
+
): NonNullable<ResolvedToolcraftAppSchema["panels"]["controls"]>["sections"][number] | undefined {
|
|
935
|
+
const normalizedTitle = normalizeToolcraftSemanticText(title);
|
|
936
|
+
|
|
937
|
+
return (schema.panels.controls?.sections ?? []).find(
|
|
938
|
+
(section) => normalizeToolcraftSemanticText(section.title) === normalizedTitle,
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
function getSchemaControlsSectionIndexByTitle(
|
|
943
|
+
schema: ResolvedToolcraftAppSchema,
|
|
944
|
+
title: string,
|
|
945
|
+
): number {
|
|
946
|
+
const normalizedTitle = normalizeToolcraftSemanticText(title);
|
|
947
|
+
|
|
948
|
+
return (schema.panels.controls?.sections ?? []).findIndex(
|
|
949
|
+
(section) => normalizeToolcraftSemanticText(section.title) === normalizedTitle,
|
|
950
|
+
);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
function getSectionControlEntryByTarget(
|
|
954
|
+
section:
|
|
955
|
+
| NonNullable<ResolvedToolcraftAppSchema["panels"]["controls"]>["sections"][number]
|
|
956
|
+
| undefined,
|
|
957
|
+
target: string,
|
|
958
|
+
): readonly [string, ToolcraftControlSchema] | undefined {
|
|
959
|
+
if (!section) {
|
|
960
|
+
return undefined;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
return Object.entries(section.controls).find(([, control]) => control.target === target);
|
|
964
|
+
}
|
|
965
|
+
|
|
906
966
|
function schemaHasOutputBackgroundColorControl(
|
|
907
967
|
controls: readonly ToolcraftVisibleControl[],
|
|
908
968
|
): boolean {
|
|
@@ -942,6 +1002,49 @@ function isOutputBackgroundToggleControl(visibleControl: ToolcraftVisibleControl
|
|
|
942
1002
|
);
|
|
943
1003
|
}
|
|
944
1004
|
|
|
1005
|
+
function getOutputBackgroundColorEntry(
|
|
1006
|
+
section:
|
|
1007
|
+
| NonNullable<ResolvedToolcraftAppSchema["panels"]["controls"]>["sections"][number]
|
|
1008
|
+
| undefined,
|
|
1009
|
+
): readonly [string, ToolcraftControlSchema] | undefined {
|
|
1010
|
+
if (!section) {
|
|
1011
|
+
return undefined;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
return Object.entries(section.controls).find(([controlId, control]) => {
|
|
1015
|
+
if (control.type !== "color") {
|
|
1016
|
+
return false;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
return /\b(background|backdrop|scene|canvas)\b/i.test(
|
|
1020
|
+
[section.title, controlId, control.target, getControlLabelText(control)]
|
|
1021
|
+
.join(" ")
|
|
1022
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2"),
|
|
1023
|
+
);
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
function sectionHasEqualWidthOutputBackgroundRow(
|
|
1028
|
+
section:
|
|
1029
|
+
| NonNullable<ResolvedToolcraftAppSchema["panels"]["controls"]>["sections"][number]
|
|
1030
|
+
| undefined,
|
|
1031
|
+
toggleControlId: string | undefined,
|
|
1032
|
+
colorControlId: string | undefined,
|
|
1033
|
+
): boolean {
|
|
1034
|
+
if (!section || !toggleControlId || !colorControlId) {
|
|
1035
|
+
return false;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
return (section.layoutGroups ?? []).some(
|
|
1039
|
+
(layoutGroup) =>
|
|
1040
|
+
layoutGroup.layout === "inline" &&
|
|
1041
|
+
layoutGroup.columns === 2 &&
|
|
1042
|
+
layoutGroup.controls.length === 2 &&
|
|
1043
|
+
layoutGroup.controls[0] === toggleControlId &&
|
|
1044
|
+
layoutGroup.controls[1] === colorControlId,
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
945
1048
|
const SEGMENTED_CONTROL_MAX_OPTIONS = 4;
|
|
946
1049
|
const SEGMENTED_CONTROL_MAX_OPTION_LABEL_LENGTH = 9;
|
|
947
1050
|
const SEGMENTED_CONTROL_MAX_TOTAL_LABEL_LENGTH = 24;
|
|
@@ -1823,7 +1926,7 @@ export function validateToolcraftAcceptanceCoverage(
|
|
|
1823
1926
|
|
|
1824
1927
|
if (unsafeBooleanLabels.length > 0) {
|
|
1825
1928
|
errors.push(
|
|
1826
|
-
`${sectionLabel} layoutGroups inline row "${layoutGroup.controls.join(", ")}" includes toggle label ${unsafeBooleanLabels.map(([controlId, control]) => `${controlId} "${getInlineSwitchLabelText(controlId, control)}"`).join(", ")} that is too long for a compact toggle-plus-parameter row. Keep the toggle label short,
|
|
1929
|
+
`${sectionLabel} layoutGroups inline row "${layoutGroup.controls.join(", ")}" includes toggle label ${unsafeBooleanLabels.map(([controlId, control]) => `${controlId} "${getInlineSwitchLabelText(controlId, control)}"`).join(", ")} that is too long for a compact toggle-plus-parameter row. Keep the toggle label short, such as "Include" inside Background, or stack the controls.`,
|
|
1827
1930
|
);
|
|
1828
1931
|
}
|
|
1829
1932
|
}
|
|
@@ -1861,15 +1964,199 @@ export function validateToolcraftAcceptanceCoverage(
|
|
|
1861
1964
|
}
|
|
1862
1965
|
|
|
1863
1966
|
if (schemaHasPngExportPanelAction(schema)) {
|
|
1967
|
+
const backgroundSection = getSchemaControlsSectionByTitle(schema, "Background");
|
|
1968
|
+
const backgroundSectionIndex = getSchemaControlsSectionIndexByTitle(schema, "Background");
|
|
1969
|
+
const panelActionsSectionIndex = getFirstPanelActionsSectionIndex(schema);
|
|
1970
|
+
const imageExportSectionIndex = getSchemaControlsSectionIndexByTitle(schema, "Image Export");
|
|
1971
|
+
const videoExportSectionIndex = getSchemaControlsSectionIndexByTitle(schema, "Video Export");
|
|
1972
|
+
const hasVideoExportAction = schemaHasVideoExportPanelAction(schema);
|
|
1973
|
+
const expectedOutputSettingsIndex =
|
|
1974
|
+
imageExportSectionIndex >= 0 ? imageExportSectionIndex : videoExportSectionIndex;
|
|
1975
|
+
const finalExportSettingsIndex = hasVideoExportAction
|
|
1976
|
+
? videoExportSectionIndex
|
|
1977
|
+
: imageExportSectionIndex;
|
|
1978
|
+
const includeBackgroundEntry = getSectionControlEntryByTarget(
|
|
1979
|
+
backgroundSection,
|
|
1980
|
+
"export.includeBackground",
|
|
1981
|
+
);
|
|
1982
|
+
const backgroundColorEntry = getOutputBackgroundColorEntry(backgroundSection);
|
|
1983
|
+
const imageExportSection = getSchemaControlsSectionByTitle(schema, "Image Export");
|
|
1984
|
+
const imageFormatEntry = getSectionControlEntryByTarget(
|
|
1985
|
+
imageExportSection,
|
|
1986
|
+
"export.image.format",
|
|
1987
|
+
);
|
|
1988
|
+
const imageResolutionEntry = getSectionControlEntryByTarget(
|
|
1989
|
+
imageExportSection,
|
|
1990
|
+
"export.image.resolution",
|
|
1991
|
+
);
|
|
1992
|
+
const imageFormatControl = imageFormatEntry?.[1];
|
|
1993
|
+
const imageResolutionControl = imageResolutionEntry?.[1];
|
|
1994
|
+
const imageFormatOptionValues =
|
|
1995
|
+
imageFormatControl?.options?.map((option) => option.value.toLowerCase()) ?? [];
|
|
1996
|
+
const imageResolutionOptionValues =
|
|
1997
|
+
imageResolutionControl?.options?.map((option) => option.value.toLowerCase()) ?? [];
|
|
1998
|
+
|
|
1999
|
+
if (!backgroundSection) {
|
|
2000
|
+
errors.push(
|
|
2001
|
+
'Product apps with Export PNG must expose a separate controls section titled "Background" directly before the first export settings section.',
|
|
2002
|
+
);
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
if (
|
|
2006
|
+
backgroundSectionIndex >= 0 &&
|
|
2007
|
+
expectedOutputSettingsIndex >= 0 &&
|
|
2008
|
+
backgroundSectionIndex !== expectedOutputSettingsIndex - 1
|
|
2009
|
+
) {
|
|
2010
|
+
errors.push(
|
|
2011
|
+
'The "Background" controls section must sit directly before the first export settings section: Image Export when PNG export exists, otherwise Video Export.',
|
|
2012
|
+
);
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
if (
|
|
2016
|
+
finalExportSettingsIndex >= 0 &&
|
|
2017
|
+
panelActionsSectionIndex >= 0 &&
|
|
2018
|
+
finalExportSettingsIndex !== panelActionsSectionIndex - 1
|
|
2019
|
+
) {
|
|
2020
|
+
errors.push(
|
|
2021
|
+
'Export settings must sit directly above sticky footer actions: Image Export for still apps, or Video Export after Image Export for animated apps.',
|
|
2022
|
+
);
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
if (
|
|
2026
|
+
hasVideoExportAction &&
|
|
2027
|
+
imageExportSectionIndex >= 0 &&
|
|
2028
|
+
videoExportSectionIndex >= 0 &&
|
|
2029
|
+
imageExportSectionIndex !== videoExportSectionIndex - 1
|
|
2030
|
+
) {
|
|
2031
|
+
errors.push(
|
|
2032
|
+
'Animated apps with both Export PNG and Export Video must place Image Export immediately before Video Export.',
|
|
2033
|
+
);
|
|
2034
|
+
}
|
|
2035
|
+
|
|
1864
2036
|
if (!schemaHasOutputBackgroundColorControl(controls)) {
|
|
1865
2037
|
errors.push(
|
|
1866
2038
|
"Product apps with Export PNG must expose a user-facing background color control such as appearance.background or scene.background. Preview, PNG export, and video export must read that runtime value instead of hardcoding the product background.",
|
|
1867
2039
|
);
|
|
1868
2040
|
}
|
|
1869
2041
|
|
|
2042
|
+
if (!backgroundColorEntry) {
|
|
2043
|
+
errors.push(
|
|
2044
|
+
'The "Background" section must contain the renderer-owned background color control, such as appearance.background or scene.background.',
|
|
2045
|
+
);
|
|
2046
|
+
} else {
|
|
2047
|
+
const [, backgroundColorControl] = backgroundColorEntry;
|
|
2048
|
+
|
|
2049
|
+
if (backgroundColorControl.label !== false) {
|
|
2050
|
+
errors.push(
|
|
2051
|
+
'The background color control inside the required "Background" section must use label false; the section title already supplies the visible context.',
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
|
|
1870
2056
|
if (!schemaHasOutputBackgroundToggleControl(controls)) {
|
|
1871
2057
|
errors.push(
|
|
1872
|
-
|
|
2058
|
+
'Product apps with Export PNG must expose export.includeBackground inside the required "Background" section as a Switch labeled "Include". PNG export must pass that runtime value to createToolcraftPngExportCanvas includeBackground; video export keeps the background.',
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
if (!includeBackgroundEntry) {
|
|
2063
|
+
errors.push(
|
|
2064
|
+
'The "Background" section must contain export.includeBackground as the Include switch.',
|
|
2065
|
+
);
|
|
2066
|
+
} else {
|
|
2067
|
+
const [, includeBackgroundControl] = includeBackgroundEntry;
|
|
2068
|
+
|
|
2069
|
+
if (includeBackgroundControl.type !== "switch") {
|
|
2070
|
+
errors.push('export.includeBackground must be a Switch control labeled "Include".');
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
if (getControlLabelText(includeBackgroundControl) !== "Include") {
|
|
2074
|
+
errors.push(
|
|
2075
|
+
'export.includeBackground must use the short visible label "Include"; the Background section title already supplies the rest of the context.',
|
|
2076
|
+
);
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
if (
|
|
2081
|
+
!sectionHasEqualWidthOutputBackgroundRow(
|
|
2082
|
+
backgroundSection,
|
|
2083
|
+
includeBackgroundEntry?.[0],
|
|
2084
|
+
backgroundColorEntry?.[0],
|
|
2085
|
+
)
|
|
2086
|
+
) {
|
|
2087
|
+
errors.push(
|
|
2088
|
+
'The "Background" section must render export.includeBackground and the background color in one two-column inline layoutGroup, with Include on the left and the unlabeled background color on the right.',
|
|
2089
|
+
);
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
if (!imageExportSection) {
|
|
2093
|
+
errors.push(
|
|
2094
|
+
'Apps with Export PNG must expose image export settings in a separate controls section titled "Image Export" directly above sticky footer export actions or directly before "Video Export" when video export also exists.',
|
|
2095
|
+
);
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
if (!imageFormatControl) {
|
|
2099
|
+
errors.push(
|
|
2100
|
+
'The separate "Image Export" section must include a format control with target "export.image.format".',
|
|
2101
|
+
);
|
|
2102
|
+
} else {
|
|
2103
|
+
if (imageFormatControl.type !== "select") {
|
|
2104
|
+
errors.push(
|
|
2105
|
+
'Image Export format must be a Select control so it matches the Video Export settings structure.',
|
|
2106
|
+
);
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
if (!imageFormatOptionValues.includes("png") || !imageFormatOptionValues.includes("jpg")) {
|
|
2110
|
+
errors.push('Image Export format options must include "png" and "jpg".');
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
if (imageFormatControl.defaultValue !== "png") {
|
|
2114
|
+
errors.push('Image Export format must default to "png".');
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
if (!imageResolutionControl) {
|
|
2119
|
+
errors.push(
|
|
2120
|
+
'The separate "Image Export" section must include a resolution control with target "export.image.resolution".',
|
|
2121
|
+
);
|
|
2122
|
+
} else {
|
|
2123
|
+
if (imageResolutionControl.type !== "select") {
|
|
2124
|
+
errors.push(
|
|
2125
|
+
'Image Export resolution must be a Select control so it matches the Video Export settings structure.',
|
|
2126
|
+
);
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
if (
|
|
2130
|
+
!imageResolutionOptionValues.includes("2k") ||
|
|
2131
|
+
!imageResolutionOptionValues.includes("4k") ||
|
|
2132
|
+
!imageResolutionOptionValues.includes("8k")
|
|
2133
|
+
) {
|
|
2134
|
+
errors.push(
|
|
2135
|
+
'Image Export resolution options must include "2k", "4k", and "8k".',
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2139
|
+
if (imageResolutionControl.defaultValue !== "4k") {
|
|
2140
|
+
errors.push('Image Export resolution must default to "4k".');
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
const imageFormatControlId = imageFormatEntry?.[0];
|
|
2145
|
+
const imageResolutionControlId = imageResolutionEntry?.[0];
|
|
2146
|
+
const imageExportHasInlinePair =
|
|
2147
|
+
imageExportSection === undefined ||
|
|
2148
|
+
imageFormatControlId === undefined ||
|
|
2149
|
+
imageResolutionControlId === undefined
|
|
2150
|
+
? false
|
|
2151
|
+
: sectionHasInlineLayoutGroupForPair(
|
|
2152
|
+
imageExportSection,
|
|
2153
|
+
imageFormatControlId,
|
|
2154
|
+
imageResolutionControlId,
|
|
2155
|
+
);
|
|
2156
|
+
|
|
2157
|
+
if (!imageExportHasInlinePair) {
|
|
2158
|
+
errors.push(
|
|
2159
|
+
"Image Export format and resolution must render as one compact two-column inline row, matching Video Export settings.",
|
|
1873
2160
|
);
|
|
1874
2161
|
}
|
|
1875
2162
|
}
|
|
@@ -80,10 +80,10 @@ export function ControlInlineGroup({
|
|
|
80
80
|
columns?: number;
|
|
81
81
|
kind?: "default" | "slider" | "toggleParameter";
|
|
82
82
|
}): React.JSX.Element {
|
|
83
|
-
const gridTemplateColumns =
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
const gridTemplateColumns = `repeat(${Math.max(
|
|
84
|
+
1,
|
|
85
|
+
Math.floor(columns),
|
|
86
|
+
)}, minmax(0, 1fr))`;
|
|
87
87
|
|
|
88
88
|
return (
|
|
89
89
|
<div
|
|
@@ -127,7 +127,7 @@ const textCaseOptions: Array<{
|
|
|
127
127
|
label: string;
|
|
128
128
|
value: FontPickerTextCasePreset;
|
|
129
129
|
}> = [
|
|
130
|
-
{ label: "
|
|
130
|
+
{ label: "As typed", value: "original" },
|
|
131
131
|
{ label: "Uppercase", value: "uppercase" },
|
|
132
132
|
{ label: "Lowercase", value: "lowercase" },
|
|
133
133
|
{ label: "Capitalize", value: "capitalize" },
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brainstorming
|
|
3
|
+
description: Use before creating Toolcraft app features, changing behavior, or assembling app specs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Toolcraft Brainstorming
|
|
7
|
+
|
|
8
|
+
Use this skill before changing a Toolcraft generated app spec, behavior, controls,
|
|
9
|
+
canvas output, panels, export behavior, renderer technique, timeline, layers, or
|
|
10
|
+
media flow.
|
|
11
|
+
|
|
12
|
+
## Process
|
|
13
|
+
|
|
14
|
+
1. Read the generated app `AGENTS.md` and relevant `docs/toolcraft/*` contract
|
|
15
|
+
files first.
|
|
16
|
+
2. Identify the product goal, visible output, editable entities, required
|
|
17
|
+
controls, export behavior, and verification tier.
|
|
18
|
+
3. Make a Control Section Inventory grouped by product entity or workflow stage,
|
|
19
|
+
not by UI component type.
|
|
20
|
+
4. Decide whether layers, timeline, persistence, settings transfer, custom
|
|
21
|
+
controls, or a custom renderer are actually required.
|
|
22
|
+
5. Record decisions in `docs/toolcraft/agent-worklog.md`.
|
|
23
|
+
|
|
24
|
+
## Toolcraft Rule
|
|
25
|
+
|
|
26
|
+
The local Toolcraft app contract is the source of truth. Do not ask the user to
|
|
27
|
+
confirm decisions already covered by the prompt, `AGENTS.md`, or local
|
|
28
|
+
Toolcraft docs. Continue when the product behavior is clear.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: browser
|
|
3
|
+
description: Use to verify Toolcraft generated apps in a real local browser after implementation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Toolcraft Browser Verification
|
|
7
|
+
|
|
8
|
+
Use this skill after implementing generated app behavior that affects visible UI,
|
|
9
|
+
canvas output, export behavior, upload/media flow, panels, controls, timeline,
|
|
10
|
+
layers, or viewport interactions.
|
|
11
|
+
|
|
12
|
+
## Process
|
|
13
|
+
|
|
14
|
+
1. Run the app with `pnpm dev`.
|
|
15
|
+
2. Open the local URL in a real browser.
|
|
16
|
+
3. Verify the product output, canvas backing, controls, panel actions, upload or
|
|
17
|
+
export flow, responsive layout, and any timeline or layer behavior touched by
|
|
18
|
+
the change.
|
|
19
|
+
4. For final delivery, run the generated app verification commands required by
|
|
20
|
+
`AGENTS.md`.
|
|
21
|
+
|
|
22
|
+
## Toolcraft Rule
|
|
23
|
+
|
|
24
|
+
Browser verification is part of the Toolcraft contract. A typecheck or build
|
|
25
|
+
alone is not enough for visible app behavior.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: figma
|
|
3
|
+
description: Use when a Toolcraft task includes a Figma URL, node ID, or design-to-code requirement.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Toolcraft Figma Workflow
|
|
7
|
+
|
|
8
|
+
Use this skill when the user provides a Figma URL, node ID, or asks to implement
|
|
9
|
+
or match a Figma design.
|
|
10
|
+
|
|
11
|
+
## Process
|
|
12
|
+
|
|
13
|
+
1. Inspect the Figma file through the available Figma MCP or design context
|
|
14
|
+
tooling.
|
|
15
|
+
2. Read actual nodes, layers, components, variables, styles, assets, and layout
|
|
16
|
+
structure.
|
|
17
|
+
3. Translate the design into Toolcraft schema controls, product renderer output,
|
|
18
|
+
canvas sizing, export behavior, and verification coverage.
|
|
19
|
+
4. Use screenshots only for final visual QA, not as the source of truth.
|
|
20
|
+
|
|
21
|
+
## Toolcraft Rule
|
|
22
|
+
|
|
23
|
+
Do not implement a Figma task from a screenshot or by eye when Figma context is
|
|
24
|
+
available. The Figma structure is the reference.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: figma-implement-design
|
|
3
|
+
description: Use to translate inspected Figma structure into a production-ready Toolcraft generated app.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Toolcraft Figma Implementation
|
|
7
|
+
|
|
8
|
+
Use this skill after Figma context has been inspected and the task is to build or
|
|
9
|
+
update a Toolcraft generated app from that design.
|
|
10
|
+
|
|
11
|
+
## Process
|
|
12
|
+
|
|
13
|
+
1. Map Figma sections, components, and visual entities to product output and
|
|
14
|
+
schema controls.
|
|
15
|
+
2. Use built-in Toolcraft controls before custom controls.
|
|
16
|
+
3. Keep app UI out of `canvasContent`; render product output there only.
|
|
17
|
+
4. Preserve the Toolcraft runtime canvas backing.
|
|
18
|
+
5. Add acceptance, browser, and performance coverage for every visible product
|
|
19
|
+
entity.
|
|
20
|
+
|
|
21
|
+
## Toolcraft Rule
|
|
22
|
+
|
|
23
|
+
Build through `defineToolcraft` and `ToolcraftApp`. Do not recreate Toolcraft
|
|
24
|
+
panels, toolbar, controls, canvas, layers, or timeline by hand.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: systematic-debugging
|
|
3
|
+
description: Use before fixing broken Toolcraft controls, tests, builds, visual mismatches, exports, or runtime regressions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Toolcraft Systematic Debugging
|
|
7
|
+
|
|
8
|
+
Use this skill before fixing any Toolcraft generated app failure.
|
|
9
|
+
|
|
10
|
+
## Process
|
|
11
|
+
|
|
12
|
+
1. Reproduce the failure with the smallest command or browser action.
|
|
13
|
+
2. Read the full error, stack trace, failing assertion, or visual mismatch.
|
|
14
|
+
3. Identify whether the root cause is app schema, app renderer, acceptance data,
|
|
15
|
+
browser test setup, copied runtime source, dependencies, or generated docs.
|
|
16
|
+
4. Compare the failure against the local Toolcraft docs and existing passing
|
|
17
|
+
patterns in the generated app.
|
|
18
|
+
5. Make one targeted fix and rerun the relevant verification.
|
|
19
|
+
|
|
20
|
+
## Toolcraft Rule
|
|
21
|
+
|
|
22
|
+
Fix source behavior in the monorepo runtime or starter when the generated
|
|
23
|
+
template is wrong. Do not patch copied `src/toolcraft` files inside one generated
|
|
24
|
+
app unless the user explicitly wants a local fork.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: writing-plans
|
|
3
|
+
description: Use before Toolcraft code changes once the product behavior or approved spec is clear.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Toolcraft Writing Plans
|
|
7
|
+
|
|
8
|
+
Use this skill before editing generated app code from a clear Toolcraft spec or
|
|
9
|
+
user request.
|
|
10
|
+
|
|
11
|
+
## Plan Content
|
|
12
|
+
|
|
13
|
+
Write a concise implementation plan that names:
|
|
14
|
+
|
|
15
|
+
1. Files to change under `src/app`, `src/routes`, docs, tests, or scripts.
|
|
16
|
+
2. Schema controls, sections, panel actions, renderer output, timeline, layers,
|
|
17
|
+
persistence, settings transfer, and export paths affected by the work.
|
|
18
|
+
3. Acceptance, browser, and performance coverage required by the selected
|
|
19
|
+
verification tier.
|
|
20
|
+
4. Commands to run before completion.
|
|
21
|
+
|
|
22
|
+
## Toolcraft Rule
|
|
23
|
+
|
|
24
|
+
Keep implementation plans focused on app behavior and verification. Do not move
|
|
25
|
+
runtime behavior into route-local state, do not patch copied `src/toolcraft`
|
|
26
|
+
internals for one app, and do not replace built-in Toolcraft surfaces.
|