@fugood/bricks-project 2.25.0-beta.4 → 2.25.0-beta.40
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/compile/action-name-map.ts +63 -0
- package/compile/index.ts +208 -19
- package/package.json +4 -3
- package/package.json.bak +4 -3
- package/skills/bricks-ctor/SKILL.md +21 -17
- package/skills/bricks-ctor/{rules → references}/animation.md +3 -2
- package/skills/bricks-ctor/{rules → references}/architecture-patterns.md +12 -0
- package/skills/bricks-ctor/{rules → references}/automations.md +11 -0
- package/skills/bricks-ctor/references/buttress.md +245 -0
- package/skills/bricks-ctor/{rules → references}/data-calculation.md +5 -5
- package/skills/bricks-ctor/references/simulator.md +115 -0
- package/skills/bricks-ctor/references/verification-toolchain.md +179 -0
- package/skills/bricks-design/SKILL.md +160 -45
- package/skills/bricks-design/references/architecture-truths.md +132 -0
- package/skills/bricks-design/references/avoiding-complexity.md +91 -0
- package/skills/bricks-design/references/design-critique.md +195 -0
- package/skills/bricks-design/references/design-languages.md +265 -0
- package/skills/bricks-design/references/performance.md +116 -0
- package/skills/bricks-design/references/presentation-and-slideshow.md +137 -0
- package/skills/bricks-design/references/translating-inputs.md +152 -0
- package/skills/bricks-design/references/variations-and-tweaks.md +124 -0
- package/skills/bricks-design/references/when-the-brief-is-branded.md +284 -0
- package/skills/bricks-design/references/when-the-brief-is-vague.md +85 -0
- package/skills/bricks-design/references/workflow.md +134 -0
- package/skills/bricks-ux/SKILL.md +120 -0
- package/skills/bricks-ux/references/accessibility.md +162 -0
- package/skills/bricks-ux/references/flow-states.md +175 -0
- package/skills/bricks-ux/references/interaction-archetypes.md +189 -0
- package/skills/bricks-ux/references/monitoring-screens.md +153 -0
- package/skills/bricks-ux/references/pressable-composition.md +126 -0
- package/skills/bricks-ux/references/user-journey.md +168 -0
- package/skills/bricks-ux/references/ux-critique.md +256 -0
- package/tools/_git-author.ts +10 -2
- package/tools/_last-pushed-commit.ts +28 -0
- package/tools/_shell.ts +8 -1
- package/tools/deploy.ts +15 -0
- package/tools/mcp-tools/compile.ts +19 -9
- package/tools/mcp-tools/media.ts +4 -1
- package/tools/pull.ts +91 -16
- package/tools/push-config.ts +118 -0
- package/tools/{preview-main.mjs → simulator-main.mjs} +207 -12
- package/tools/simulator-preload.cjs +16 -0
- package/tools/{preview.ts → simulator.ts} +4 -4
- package/types/{animation.ts → animation.d.ts} +24 -8
- package/types/{automation.ts → automation.d.ts} +16 -20
- package/types/{brick-base.ts → brick-base.d.ts} +1 -1
- package/types/bricks/{Camera.ts → Camera.d.ts} +8 -8
- package/types/bricks/{Chart.ts → Chart.d.ts} +4 -4
- package/types/bricks/{GenerativeMedia.ts → GenerativeMedia.d.ts} +15 -15
- package/types/bricks/{Icon.ts → Icon.d.ts} +7 -7
- package/types/bricks/{Image.ts → Image.d.ts} +21 -9
- package/types/bricks/{Items.ts → Items.d.ts} +7 -7
- package/types/bricks/{Lottie.ts → Lottie.d.ts} +10 -10
- package/types/bricks/{Maps.ts → Maps.d.ts} +11 -11
- package/types/bricks/{QrCode.ts → QrCode.d.ts} +7 -7
- package/types/bricks/{Rect.ts → Rect.d.ts} +7 -7
- package/types/bricks/{RichText.ts → RichText.d.ts} +12 -9
- package/types/bricks/{Rive.ts → Rive.d.ts} +9 -9
- package/types/bricks/Scene3D.d.ts +596 -0
- package/types/bricks/{Sketch.ts → Sketch.d.ts} +6 -6
- package/types/bricks/{Slideshow.ts → Slideshow.d.ts} +7 -7
- package/types/bricks/{Svg.ts → Svg.d.ts} +7 -7
- package/types/bricks/{Text.ts → Text.d.ts} +9 -9
- package/types/bricks/{TextInput.ts → TextInput.d.ts} +10 -10
- package/types/bricks/{Video.ts → Video.d.ts} +12 -12
- package/types/bricks/{VideoStreaming.ts → VideoStreaming.d.ts} +10 -10
- package/types/bricks/{WebRtcStream.ts → WebRtcStream.d.ts} +1 -1
- package/types/bricks/{WebView.ts → WebView.d.ts} +4 -4
- package/types/bricks/{index.ts → index.d.ts} +1 -0
- package/types/{common.ts → common.d.ts} +3 -6
- package/types/data-calc-command/base.d.ts +57 -0
- package/types/data-calc-command/collection.d.ts +418 -0
- package/types/data-calc-command/color.d.ts +432 -0
- package/types/data-calc-command/constant.d.ts +50 -0
- package/types/data-calc-command/datetime.d.ts +147 -0
- package/types/data-calc-command/file.d.ts +129 -0
- package/types/data-calc-command/index.d.ts +13 -0
- package/types/data-calc-command/iteratee.d.ts +23 -0
- package/types/data-calc-command/logictype.d.ts +190 -0
- package/types/data-calc-command/math.d.ts +275 -0
- package/types/data-calc-command/object.d.ts +119 -0
- package/types/data-calc-command/sandbox.d.ts +58 -0
- package/types/data-calc-command/string.d.ts +407 -0
- package/types/{data-calc.ts → data-calc.d.ts} +1 -0
- package/types/{data.ts → data.d.ts} +4 -2
- package/types/generators/{Assistant.ts → Assistant.d.ts} +19 -0
- package/types/generators/{LlmGgml.ts → LlmGgml.d.ts} +43 -1
- package/types/generators/{LlmMlx.ts → LlmMlx.d.ts} +1 -0
- package/types/generators/{RerankerGgml.ts → RerankerGgml.d.ts} +5 -1
- package/types/generators/{SoundRecorder.ts → SoundRecorder.d.ts} +10 -1
- package/types/generators/{SpeechToTextGgml.ts → SpeechToTextGgml.d.ts} +6 -1
- package/types/generators/{SttAppleBuiltin.ts → SttAppleBuiltin.d.ts} +27 -4
- package/types/generators/{ThermalPrinter.ts → ThermalPrinter.d.ts} +9 -7
- package/types/generators/{VadGgml.ts → VadGgml.d.ts} +12 -2
- package/types/{subspace.ts → subspace.d.ts} +1 -1
- package/utils/data.ts +2 -2
- package/utils/event-props.ts +17 -0
- package/utils/id.ts +78 -27
- package/skills/bricks-ctor/rules/buttress.md +0 -156
- package/skills/bricks-design/LICENSE.txt +0 -180
- package/types/data-calc-command.ts +0 -7005
- /package/skills/bricks-ctor/{rules → references}/local-sync.md +0 -0
- /package/skills/bricks-ctor/{rules → references}/media-flow.md +0 -0
- /package/skills/bricks-ctor/{rules → references}/remote-data-bank.md +0 -0
- /package/skills/bricks-ctor/{rules → references}/standby-transition.md +0 -0
- /package/types/{canvas.ts → canvas.d.ts} +0 -0
- /package/types/{data-calc-script.ts → data-calc-script.d.ts} +0 -0
- /package/types/generators/{AlarmClock.ts → AlarmClock.d.ts} +0 -0
- /package/types/generators/{BleCentral.ts → BleCentral.d.ts} +0 -0
- /package/types/generators/{BlePeripheral.ts → BlePeripheral.d.ts} +0 -0
- /package/types/generators/{CanvasMap.ts → CanvasMap.d.ts} +0 -0
- /package/types/generators/{CastlesPay.ts → CastlesPay.d.ts} +0 -0
- /package/types/generators/{DataBank.ts → DataBank.d.ts} +0 -0
- /package/types/generators/{File.ts → File.d.ts} +0 -0
- /package/types/generators/{GraphQl.ts → GraphQl.d.ts} +0 -0
- /package/types/generators/{Http.ts → Http.d.ts} +0 -0
- /package/types/generators/{HttpServer.ts → HttpServer.d.ts} +0 -0
- /package/types/generators/{Information.ts → Information.d.ts} +0 -0
- /package/types/generators/{Intent.ts → Intent.d.ts} +0 -0
- /package/types/generators/{Iterator.ts → Iterator.d.ts} +0 -0
- /package/types/generators/{Keyboard.ts → Keyboard.d.ts} +0 -0
- /package/types/generators/{LlmAnthropicCompat.ts → LlmAnthropicCompat.d.ts} +0 -0
- /package/types/generators/{LlmAppleBuiltin.ts → LlmAppleBuiltin.d.ts} +0 -0
- /package/types/generators/{LlmMediaTekNeuroPilot.ts → LlmMediaTekNeuroPilot.d.ts} +0 -0
- /package/types/generators/{LlmOnnx.ts → LlmOnnx.d.ts} +0 -0
- /package/types/generators/{LlmOpenAiCompat.ts → LlmOpenAiCompat.d.ts} +0 -0
- /package/types/generators/{LlmQualcommAiEngine.ts → LlmQualcommAiEngine.d.ts} +0 -0
- /package/types/generators/{Mcp.ts → Mcp.d.ts} +0 -0
- /package/types/generators/{McpServer.ts → McpServer.d.ts} +0 -0
- /package/types/generators/{MediaFlow.ts → MediaFlow.d.ts} +0 -0
- /package/types/generators/{MqttBroker.ts → MqttBroker.d.ts} +0 -0
- /package/types/generators/{MqttClient.ts → MqttClient.d.ts} +0 -0
- /package/types/generators/{Question.ts → Question.d.ts} +0 -0
- /package/types/generators/{RealtimeTranscription.ts → RealtimeTranscription.d.ts} +0 -0
- /package/types/generators/{SerialPort.ts → SerialPort.d.ts} +0 -0
- /package/types/generators/{SoundPlayer.ts → SoundPlayer.d.ts} +0 -0
- /package/types/generators/{SpeechToTextOnnx.ts → SpeechToTextOnnx.d.ts} +0 -0
- /package/types/generators/{SpeechToTextPlatform.ts → SpeechToTextPlatform.d.ts} +0 -0
- /package/types/generators/{SqLite.ts → SqLite.d.ts} +0 -0
- /package/types/generators/{Step.ts → Step.d.ts} +0 -0
- /package/types/generators/{Tcp.ts → Tcp.d.ts} +0 -0
- /package/types/generators/{TcpServer.ts → TcpServer.d.ts} +0 -0
- /package/types/generators/{TextToSpeechAppleBuiltin.ts → TextToSpeechAppleBuiltin.d.ts} +0 -0
- /package/types/generators/{TextToSpeechGgml.ts → TextToSpeechGgml.d.ts} +0 -0
- /package/types/generators/{TextToSpeechOnnx.ts → TextToSpeechOnnx.d.ts} +0 -0
- /package/types/generators/{TextToSpeechOpenAiLike.ts → TextToSpeechOpenAiLike.d.ts} +0 -0
- /package/types/generators/{Tick.ts → Tick.d.ts} +0 -0
- /package/types/generators/{Udp.ts → Udp.d.ts} +0 -0
- /package/types/generators/{VadOnnx.ts → VadOnnx.d.ts} +0 -0
- /package/types/generators/{VadTraditional.ts → VadTraditional.d.ts} +0 -0
- /package/types/generators/{VectorStore.ts → VectorStore.d.ts} +0 -0
- /package/types/generators/{Watchdog.ts → Watchdog.d.ts} +0 -0
- /package/types/generators/{WebCrawler.ts → WebCrawler.d.ts} +0 -0
- /package/types/generators/{WebRtc.ts → WebRtc.d.ts} +0 -0
- /package/types/generators/{WebSocket.ts → WebSocket.d.ts} +0 -0
- /package/types/generators/{index.ts → index.d.ts} +0 -0
- /package/types/{index.ts → index.d.ts} +0 -0
- /package/types/{switch.ts → switch.d.ts} +0 -0
- /package/types/{system.ts → system.d.ts} +0 -0
|
@@ -350,6 +350,62 @@ export const templateActionNameMap = {
|
|
|
350
350
|
strokeWidth: 'BRICK_SKETCH_STROKE_WIDTH',
|
|
351
351
|
},
|
|
352
352
|
},
|
|
353
|
+
BRICK_SCENE_3D: {
|
|
354
|
+
BRICK_SCENE_3D_ADD_OBJECT: {
|
|
355
|
+
objectId: 'BRICK_SCENE_3D_OBJECT_ID',
|
|
356
|
+
objectType: 'BRICK_SCENE_3D_OBJECT_TYPE',
|
|
357
|
+
objectUrl: 'BRICK_SCENE_3D_OBJECT_URL',
|
|
358
|
+
objectMd5: 'BRICK_SCENE_3D_OBJECT_MD5',
|
|
359
|
+
objectPosition: 'BRICK_SCENE_3D_OBJECT_POSITION',
|
|
360
|
+
objectRotation: 'BRICK_SCENE_3D_OBJECT_ROTATION',
|
|
361
|
+
objectScale: 'BRICK_SCENE_3D_OBJECT_SCALE',
|
|
362
|
+
objectColor: 'BRICK_SCENE_3D_OBJECT_COLOR',
|
|
363
|
+
},
|
|
364
|
+
BRICK_SCENE_3D_REMOVE_OBJECT: {
|
|
365
|
+
objectId: 'BRICK_SCENE_3D_OBJECT_ID',
|
|
366
|
+
},
|
|
367
|
+
BRICK_SCENE_3D_UPDATE_OBJECT: {
|
|
368
|
+
objectId: 'BRICK_SCENE_3D_OBJECT_ID',
|
|
369
|
+
objectPosition: 'BRICK_SCENE_3D_OBJECT_POSITION',
|
|
370
|
+
objectRotation: 'BRICK_SCENE_3D_OBJECT_ROTATION',
|
|
371
|
+
objectScale: 'BRICK_SCENE_3D_OBJECT_SCALE',
|
|
372
|
+
objectVisible: 'BRICK_SCENE_3D_OBJECT_VISIBLE',
|
|
373
|
+
objectColor: 'BRICK_SCENE_3D_OBJECT_COLOR',
|
|
374
|
+
},
|
|
375
|
+
BRICK_SCENE_3D_SET_CAMERA: {
|
|
376
|
+
cameraPosition: 'BRICK_SCENE_3D_CAMERA_POSITION',
|
|
377
|
+
cameraTarget: 'BRICK_SCENE_3D_CAMERA_TARGET',
|
|
378
|
+
cameraFov: 'BRICK_SCENE_3D_CAMERA_FOV',
|
|
379
|
+
cameraAnimateMs: 'BRICK_SCENE_3D_CAMERA_ANIMATE_MS',
|
|
380
|
+
},
|
|
381
|
+
BRICK_SCENE_3D_LOOK_AT: {
|
|
382
|
+
objectId: 'BRICK_SCENE_3D_OBJECT_ID',
|
|
383
|
+
},
|
|
384
|
+
BRICK_SCENE_3D_PLAY_ANIMATION: {
|
|
385
|
+
objectId: 'BRICK_SCENE_3D_OBJECT_ID',
|
|
386
|
+
animationName: 'BRICK_SCENE_3D_ANIMATION_NAME',
|
|
387
|
+
animationLoop: 'BRICK_SCENE_3D_ANIMATION_LOOP',
|
|
388
|
+
animationSpeed: 'BRICK_SCENE_3D_ANIMATION_SPEED',
|
|
389
|
+
},
|
|
390
|
+
BRICK_SCENE_3D_STOP_ANIMATION: {
|
|
391
|
+
objectId: 'BRICK_SCENE_3D_OBJECT_ID',
|
|
392
|
+
animationName: 'BRICK_SCENE_3D_ANIMATION_NAME',
|
|
393
|
+
},
|
|
394
|
+
BRICK_SCENE_3D_SET_BACKGROUND: {
|
|
395
|
+
backgroundColor: 'BRICK_SCENE_3D_BACKGROUND_COLOR',
|
|
396
|
+
backgroundHdrUrl: 'BRICK_SCENE_3D_BACKGROUND_HDR_URL',
|
|
397
|
+
backgroundMd5: 'BRICK_SCENE_3D_BACKGROUND_MD5',
|
|
398
|
+
},
|
|
399
|
+
BRICK_SCENE_3D_SET_CONTROLS: {
|
|
400
|
+
controlsEnabled: 'BRICK_SCENE_3D_CONTROLS_ENABLED',
|
|
401
|
+
controlsAutoRotate: 'BRICK_SCENE_3D_CONTROLS_AUTO_ROTATE',
|
|
402
|
+
controlsAutoRotateSpeed: 'BRICK_SCENE_3D_CONTROLS_AUTO_ROTATE_SPEED',
|
|
403
|
+
},
|
|
404
|
+
BRICK_SCENE_3D_SCREENSHOT: {
|
|
405
|
+
screenshotFormat: 'BRICK_SCENE_3D_SCREENSHOT_FORMAT',
|
|
406
|
+
screenshotQuality: 'BRICK_SCENE_3D_SCREENSHOT_QUALITY',
|
|
407
|
+
},
|
|
408
|
+
},
|
|
353
409
|
|
|
354
410
|
GENERATOR_FILE: {
|
|
355
411
|
GENERATOR_FILE_READ_CONTENT: {
|
|
@@ -782,6 +838,11 @@ export const templateActionNameMap = {
|
|
|
782
838
|
seed: 'GENERATOR_LLM_SEED',
|
|
783
839
|
typicalP: 'GENERATOR_LLM_TYPICAL_P',
|
|
784
840
|
ignoreEos: 'GENERATOR_LLM_IGNORE_EOS',
|
|
841
|
+
mtpSpeculativeDecoding: 'GENERATOR_LLM_MTP_SPECULATIVE_DECODING',
|
|
842
|
+
mtpDraftTokens: 'GENERATOR_LLM_MTP_DRAFT_TOKENS',
|
|
843
|
+
mtpDraftMinTokens: 'GENERATOR_LLM_MTP_DRAFT_MIN_TOKENS',
|
|
844
|
+
mtpDraftMinProbability: 'GENERATOR_LLM_MTP_DRAFT_MIN_PROBABILITY',
|
|
845
|
+
mtpDraftSplitProbability: 'GENERATOR_LLM_MTP_DRAFT_SPLIT_PROBABILITY',
|
|
785
846
|
functionCallEnabled: 'GENERATOR_LLM_FUNCTION_CALL_ENABLED',
|
|
786
847
|
functionCallSchema: 'GENERATOR_LLM_FUNCTION_CALL_SCHEMA',
|
|
787
848
|
},
|
|
@@ -894,10 +955,12 @@ export const templateActionNameMap = {
|
|
|
894
955
|
GENERATOR_APPLE_STT_TRANSCRIBE_FILE: {
|
|
895
956
|
fileUrl: 'GENERATOR_APPLE_STT_FILE_URL',
|
|
896
957
|
language: 'GENERATOR_APPLE_STT_LANGUAGE',
|
|
958
|
+
contextualStrings: 'GENERATOR_APPLE_STT_CONTEXTUAL_STRINGS',
|
|
897
959
|
},
|
|
898
960
|
GENERATOR_APPLE_STT_TRANSCRIBE_DATA: {
|
|
899
961
|
data: 'GENERATOR_APPLE_STT_DATA',
|
|
900
962
|
language: 'GENERATOR_APPLE_STT_LANGUAGE',
|
|
963
|
+
contextualStrings: 'GENERATOR_APPLE_STT_CONTEXTUAL_STRINGS',
|
|
901
964
|
},
|
|
902
965
|
},
|
|
903
966
|
GENERATOR_APPLE_TTS: {
|
package/compile/index.ts
CHANGED
|
@@ -154,11 +154,13 @@ const basicAnimationEvents = ['show', 'standby', 'breatheStart']
|
|
|
154
154
|
|
|
155
155
|
const compileAnimations = (
|
|
156
156
|
templateKey: string,
|
|
157
|
-
animations: { [key: string]: Animation },
|
|
157
|
+
animations: { [key: string]: Animation | (() => Animation) },
|
|
158
158
|
errorReference: string,
|
|
159
159
|
) =>
|
|
160
160
|
Object.entries(animations).reduce((acc, [key, animation]) => {
|
|
161
|
-
|
|
161
|
+
// Animation events accept either a direct Animation or a getter; unwrap.
|
|
162
|
+
const resolved = typeof animation === 'function' ? animation() : animation
|
|
163
|
+
const animationId = assertEntryId(resolved?.id, 'ANIMATION', errorReference)
|
|
162
164
|
acc[convertEventKey(basicAnimationEvents.includes(key) ? 'BRICK' : templateKey, key)] =
|
|
163
165
|
`ANIMATION#${animationId}`
|
|
164
166
|
return acc
|
|
@@ -301,6 +303,162 @@ const animationTypeMap = {
|
|
|
301
303
|
AnimationTimingConfig: 'timing',
|
|
302
304
|
AnimationSpringConfig: 'spring',
|
|
303
305
|
AnimationDecayConfig: 'decay',
|
|
306
|
+
} as const
|
|
307
|
+
|
|
308
|
+
type CompiledAnimationType = (typeof animationTypeMap)[keyof typeof animationTypeMap]
|
|
309
|
+
type WarningMetadata = Record<string, unknown>
|
|
310
|
+
|
|
311
|
+
const animationProperties = new Set([
|
|
312
|
+
'transform.translateX',
|
|
313
|
+
'transform.translateY',
|
|
314
|
+
'transform.scale',
|
|
315
|
+
'transform.scaleX',
|
|
316
|
+
'transform.scaleY',
|
|
317
|
+
'transform.rotate',
|
|
318
|
+
'transform.rotateX',
|
|
319
|
+
'transform.rotateY',
|
|
320
|
+
'opacity',
|
|
321
|
+
])
|
|
322
|
+
|
|
323
|
+
const animationComposeTypes = new Set(['parallel', 'sequence'])
|
|
324
|
+
const springConfigFamilies = [
|
|
325
|
+
['stiffness', 'damping', 'mass'],
|
|
326
|
+
['tension', 'friction'],
|
|
327
|
+
['bounciness', 'speed'],
|
|
328
|
+
]
|
|
329
|
+
const springConfigFamilyKeys = new Set(springConfigFamilies.flat())
|
|
330
|
+
|
|
331
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
332
|
+
Boolean(value) && typeof value === 'object' && !Array.isArray(value)
|
|
333
|
+
|
|
334
|
+
const hasDefinedConfigValue = (config: Record<string, unknown>, key: string) =>
|
|
335
|
+
config[key] !== undefined
|
|
336
|
+
|
|
337
|
+
const assertConfigValue = (
|
|
338
|
+
config: Record<string, unknown>,
|
|
339
|
+
key: string,
|
|
340
|
+
errorReference: string,
|
|
341
|
+
) => {
|
|
342
|
+
if (!hasDefinedConfigValue(config, key)) {
|
|
343
|
+
throw new Error(`Invalid animation config ${errorReference}: missing "${key}"`)
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const assertAnimationProperty = (property: unknown, errorReference: string) => {
|
|
348
|
+
if (typeof property !== 'string' || !animationProperties.has(property)) {
|
|
349
|
+
throw new Error(
|
|
350
|
+
`Invalid animation property${errorReference ? ` ${errorReference}` : ''}: ${String(
|
|
351
|
+
property,
|
|
352
|
+
)}`,
|
|
353
|
+
)
|
|
354
|
+
}
|
|
355
|
+
return property
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const getAnimationType = (config: unknown, errorReference: string): CompiledAnimationType => {
|
|
359
|
+
if (!isRecord(config)) {
|
|
360
|
+
throw new Error(`Invalid animation config ${errorReference}: config must be an object`)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const animationType = animationTypeMap[config.__type as keyof typeof animationTypeMap]
|
|
364
|
+
if (!animationType) {
|
|
365
|
+
throw new Error(`Invalid animation config type ${errorReference}: ${String(config.__type)}`)
|
|
366
|
+
}
|
|
367
|
+
return animationType
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const assertAnimationComposeType = (composeType: unknown, errorReference: string) => {
|
|
371
|
+
if (typeof composeType !== 'string' || !animationComposeTypes.has(composeType)) {
|
|
372
|
+
throw new Error(`Invalid animation compose type ${errorReference}: ${String(composeType)}`)
|
|
373
|
+
}
|
|
374
|
+
return composeType
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const pickDefinedConfigValues = (config: Record<string, unknown>, keys: string[]) =>
|
|
378
|
+
keys.reduce((acc, key) => {
|
|
379
|
+
if (hasDefinedConfigValue(config, key)) acc[key] = config[key]
|
|
380
|
+
return acc
|
|
381
|
+
}, {})
|
|
382
|
+
|
|
383
|
+
const getDefinedConfigKeys = (config: Record<string, unknown>, keys: string[]) =>
|
|
384
|
+
keys.filter((key) => hasDefinedConfigValue(config, key))
|
|
385
|
+
|
|
386
|
+
const formatWarningMetadata = (metadata: WarningMetadata = {}) =>
|
|
387
|
+
Object.entries(metadata)
|
|
388
|
+
.filter(([, value]) => value !== undefined && value !== null && value !== '')
|
|
389
|
+
.map(([key, value]) => `${key}: ${String(value)}`)
|
|
390
|
+
.join(', ')
|
|
391
|
+
|
|
392
|
+
const formatWarningReference = (metadata?: WarningMetadata) => {
|
|
393
|
+
const metadataText = formatWarningMetadata(metadata)
|
|
394
|
+
return metadataText ? ` [${metadataText}]` : ''
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const normalizeSpringConfig = (
|
|
398
|
+
config: Record<string, unknown>,
|
|
399
|
+
errorReference: string,
|
|
400
|
+
warningMetadata?: WarningMetadata,
|
|
401
|
+
): Record<string, unknown> => {
|
|
402
|
+
assertConfigValue(config, 'toValue', errorReference)
|
|
403
|
+
|
|
404
|
+
const usedFamilies = springConfigFamilies.filter((keys) =>
|
|
405
|
+
keys.some((key) => hasDefinedConfigValue(config, key)),
|
|
406
|
+
)
|
|
407
|
+
if (usedFamilies.length <= 1) return config
|
|
408
|
+
|
|
409
|
+
const configWithoutSpringFamily = Object.entries(config).reduce((acc, [key, value]) => {
|
|
410
|
+
if (!springConfigFamilyKeys.has(key)) acc[key] = value
|
|
411
|
+
return acc
|
|
412
|
+
}, {})
|
|
413
|
+
|
|
414
|
+
// Match runtime normalization: physical spring values are most explicit,
|
|
415
|
+
// otherwise preserve BRICKS' historical tension/friction controls.
|
|
416
|
+
const resolvedFamily =
|
|
417
|
+
usedFamilies.find((keys) => keys.includes('stiffness')) ||
|
|
418
|
+
usedFamilies.find((keys) => keys.includes('tension')) ||
|
|
419
|
+
usedFamilies[0]
|
|
420
|
+
const resolvedFamilyKeys = getDefinedConfigKeys(config, resolvedFamily)
|
|
421
|
+
const droppedFamilyKeys = usedFamilies
|
|
422
|
+
.filter((keys) => keys !== resolvedFamily)
|
|
423
|
+
.flatMap((keys) => getDefinedConfigKeys(config, keys))
|
|
424
|
+
|
|
425
|
+
console.warn(
|
|
426
|
+
`[Warning] Resolved animation spring config${formatWarningReference(
|
|
427
|
+
warningMetadata,
|
|
428
|
+
)}: using ${resolvedFamilyKeys.join('/')}, dropping ${droppedFamilyKeys.join('/')}`,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
return {
|
|
432
|
+
...configWithoutSpringFamily,
|
|
433
|
+
...pickDefinedConfigValues(config, resolvedFamily),
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const compileAnimationConfig = (
|
|
438
|
+
animationType: CompiledAnimationType,
|
|
439
|
+
config: unknown,
|
|
440
|
+
errorReference: string,
|
|
441
|
+
warningMetadata?: WarningMetadata,
|
|
442
|
+
) => {
|
|
443
|
+
if (!isRecord(config)) {
|
|
444
|
+
throw new Error(`Invalid animation config ${errorReference}: config must be an object`)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const compiledConfig = compileProperty(omit(config, '__type'), errorReference)
|
|
448
|
+
|
|
449
|
+
if (!isRecord(compiledConfig)) {
|
|
450
|
+
throw new Error(`Invalid animation config ${errorReference}: config must compile to an object`)
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (animationType === 'timing') {
|
|
454
|
+
assertConfigValue(compiledConfig, 'toValue', errorReference)
|
|
455
|
+
} else if (animationType === 'spring') {
|
|
456
|
+
return normalizeSpringConfig(compiledConfig, errorReference, warningMetadata)
|
|
457
|
+
} else if (animationType === 'decay') {
|
|
458
|
+
assertConfigValue(compiledConfig, 'velocity', errorReference)
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return compiledConfig
|
|
304
462
|
}
|
|
305
463
|
|
|
306
464
|
const compileFrame = (frame: Canvas['items'][number]['frame']) => ({
|
|
@@ -327,6 +485,8 @@ const preloadTypes = [
|
|
|
327
485
|
'ggml-model-asset',
|
|
328
486
|
'gguf-model-asset',
|
|
329
487
|
'binary-asset',
|
|
488
|
+
'mlx-model-asset',
|
|
489
|
+
'scene3d-objects',
|
|
330
490
|
]
|
|
331
491
|
|
|
332
492
|
const compileKind = (kind: Data['kind']) => {
|
|
@@ -353,9 +513,10 @@ const compileKind = (kind: Data['kind']) => {
|
|
|
353
513
|
}
|
|
354
514
|
|
|
355
515
|
const compileRemoteUpdate = (remoteUpdate: Data['remoteUpdate']) => {
|
|
356
|
-
if (!remoteUpdate) return {}
|
|
357
|
-
if (remoteUpdate.type === 'auto') return { enable_remote_update: true }
|
|
516
|
+
if (!remoteUpdate) return { bank_type: 'none' }
|
|
517
|
+
if (remoteUpdate.type === 'auto') return { bank_type: 'create', enable_remote_update: true }
|
|
358
518
|
return {
|
|
519
|
+
bank_type: remoteUpdate.type === 'device-specific' ? 'create-device-specific' : 'global',
|
|
359
520
|
enable_remote_update: true,
|
|
360
521
|
...(remoteUpdate.type === 'device-specific' ? { use_remote_id_prefix: true } : {}),
|
|
361
522
|
...(remoteUpdate.type === 'global-data' ? { global_remote_update_prop: remoteUpdate.id } : {}),
|
|
@@ -485,6 +646,7 @@ const compileAutomationTest = (
|
|
|
485
646
|
|
|
486
647
|
return {
|
|
487
648
|
id: testId,
|
|
649
|
+
alias: test.alias,
|
|
488
650
|
title: test.title,
|
|
489
651
|
hide_short_ref: test.hideShortRef,
|
|
490
652
|
timeout: test.timeout,
|
|
@@ -629,39 +791,63 @@ export const compile = async (app: Application) => {
|
|
|
629
791
|
`(animation index: ${animationIndex}, subspace: ${subspaceId})`,
|
|
630
792
|
)
|
|
631
793
|
|
|
632
|
-
|
|
794
|
+
const animationTypename = animation.__typename
|
|
795
|
+
if (animationTypename === 'Animation') {
|
|
633
796
|
const animationDef = animation as AnimationDef
|
|
797
|
+
const animationErrorReference = `(animation: ${animationId}, subspace ${subspaceId})`
|
|
798
|
+
const animationWarningMetadata = {
|
|
799
|
+
animationIndex,
|
|
800
|
+
animationTitle: animationDef.title,
|
|
801
|
+
animationAlias: animationDef.alias,
|
|
802
|
+
animationProperty: animationDef.property,
|
|
803
|
+
subspaceIndex,
|
|
804
|
+
subspaceTitle: subspace.title,
|
|
805
|
+
}
|
|
806
|
+
const animationType = getAnimationType(animationDef.config, animationErrorReference)
|
|
634
807
|
map[animationId] = {
|
|
635
808
|
alias: animationDef.alias,
|
|
636
809
|
title: animationDef.title,
|
|
637
810
|
description: animationDef.description,
|
|
638
811
|
hide_short_ref: animationDef.hideShortRef,
|
|
639
812
|
animationRunType: animationDef.runType,
|
|
640
|
-
property: animationDef.property,
|
|
641
|
-
type:
|
|
642
|
-
config:
|
|
643
|
-
|
|
644
|
-
|
|
813
|
+
property: assertAnimationProperty(animationDef.property, animationErrorReference),
|
|
814
|
+
type: animationType,
|
|
815
|
+
config: compileAnimationConfig(
|
|
816
|
+
animationType,
|
|
817
|
+
animationDef.config,
|
|
818
|
+
animationErrorReference,
|
|
819
|
+
animationWarningMetadata,
|
|
645
820
|
),
|
|
646
821
|
}
|
|
647
|
-
} else if (
|
|
822
|
+
} else if (animationTypename === 'AnimationCompose') {
|
|
648
823
|
const animationDef = animation as AnimationComposeDef
|
|
824
|
+
const animationErrorReference = `(animation: ${animationId}, subspace ${subspaceId})`
|
|
649
825
|
map[animationId] = {
|
|
650
826
|
alias: animationDef.alias,
|
|
651
827
|
title: animationDef.title,
|
|
652
828
|
description: animationDef.description,
|
|
653
829
|
hide_short_ref: animationDef.hideShortRef,
|
|
654
830
|
animationRunType: animationDef.runType,
|
|
655
|
-
compose_type:
|
|
831
|
+
compose_type: assertAnimationComposeType(
|
|
832
|
+
animationDef.composeType,
|
|
833
|
+
animationErrorReference,
|
|
834
|
+
),
|
|
656
835
|
item_list: animationDef.items.map((item, index) => {
|
|
657
836
|
const innerAnimation = item()
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
)
|
|
662
|
-
|
|
837
|
+
const innerAnimationId = assertEntryId(
|
|
838
|
+
innerAnimation?.id,
|
|
839
|
+
'ANIMATION',
|
|
840
|
+
`(animation item index: ${index}, animation: ${animationId}, subspace ${subspaceId})`,
|
|
841
|
+
)
|
|
842
|
+
return { animation_id: innerAnimationId }
|
|
663
843
|
}),
|
|
664
844
|
}
|
|
845
|
+
} else {
|
|
846
|
+
throw new Error(
|
|
847
|
+
`Invalid animation typename (animation: ${animationId}, subspace ${subspaceId}): ${String(
|
|
848
|
+
animationTypename,
|
|
849
|
+
)}`,
|
|
850
|
+
)
|
|
665
851
|
}
|
|
666
852
|
return map
|
|
667
853
|
}, {}),
|
|
@@ -1009,7 +1195,7 @@ export const compile = async (app: Application) => {
|
|
|
1009
1195
|
...compileRemoteUpdate(data.remoteUpdate),
|
|
1010
1196
|
routing: data.routing,
|
|
1011
1197
|
schema: data.schema,
|
|
1012
|
-
type: data.type,
|
|
1198
|
+
type: data.type === 'boolean' ? 'bool' : data.type,
|
|
1013
1199
|
...compileKind(data.kind),
|
|
1014
1200
|
value: compileProperty(data.value, `(data: ${dataId}, subspace ${subspaceId})`),
|
|
1015
1201
|
event_map: compileEvents('PROPERTY_BANK', data.events || {}, {
|
|
@@ -1029,6 +1215,7 @@ export const compile = async (app: Application) => {
|
|
|
1029
1215
|
)
|
|
1030
1216
|
|
|
1031
1217
|
const calc: any = {
|
|
1218
|
+
alias: dataCalc.alias,
|
|
1032
1219
|
title: dataCalc.title,
|
|
1033
1220
|
description: dataCalc.description,
|
|
1034
1221
|
hide_short_ref: dataCalc.hideShortRef,
|
|
@@ -1274,5 +1461,7 @@ export const compile = async (app: Application) => {
|
|
|
1274
1461
|
|
|
1275
1462
|
export const checkConfig = async (configPath: string) => {
|
|
1276
1463
|
const { sh } = await import('../tools/_shell')
|
|
1277
|
-
|
|
1464
|
+
// --validate-automation surfaces broken automation_map / test_map refs early,
|
|
1465
|
+
// which catches agent-authored automations that reference deleted bricks.
|
|
1466
|
+
await sh`bricks app check-config --validate-automation ${configPath}`
|
|
1278
1467
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fugood/bricks-project",
|
|
3
|
-
"version": "2.25.0-beta.
|
|
3
|
+
"version": "2.25.0-beta.40",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"typecheck": "tsc --noEmit",
|
|
7
7
|
"build": "bun scripts/build.js"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@fugood/bricks-cli": "^2.25.0-beta.
|
|
10
|
+
"@fugood/bricks-cli": "^2.25.0-beta.40",
|
|
11
11
|
"@huggingface/gguf": "^0.3.2",
|
|
12
12
|
"@iarna/toml": "^3.0.0",
|
|
13
13
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
@@ -24,5 +24,6 @@
|
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"oxfmt": "^0.36.0"
|
|
27
|
-
}
|
|
27
|
+
},
|
|
28
|
+
"gitHead": "4ad8588eed6f0161b0aa66d863a36e6c623c4a83"
|
|
28
29
|
}
|
package/package.json.bak
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fugood/bricks-ctor",
|
|
3
|
-
"version": "2.25.0-beta.
|
|
3
|
+
"version": "2.25.0-beta.40",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"typecheck": "tsc --noEmit",
|
|
7
7
|
"build": "bun scripts/build.js"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@fugood/bricks-cli": "^2.25.0-beta.
|
|
10
|
+
"@fugood/bricks-cli": "^2.25.0-beta.40",
|
|
11
11
|
"@huggingface/gguf": "^0.3.2",
|
|
12
12
|
"@iarna/toml": "^3.0.0",
|
|
13
13
|
"@modelcontextprotocol/sdk": "^1.15.0",
|
|
@@ -24,5 +24,6 @@
|
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"oxfmt": "^0.36.0"
|
|
27
|
-
}
|
|
27
|
+
},
|
|
28
|
+
"gitHead": "4ad8588eed6f0161b0aa66d863a36e6c623c4a83"
|
|
28
29
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bricks-ctor
|
|
3
|
-
description: Advanced BRICKS configuration knowledge. Covers Standby Transition, Automations (E2E testing), Data Calculation (JS sandbox libraries), Local Sync, Remote Data Bank, Media Flow,
|
|
3
|
+
description: Advanced BRICKS configuration knowledge. Covers Standby Transition, Automations (E2E testing), Data Calculation (JS sandbox libraries), Local Sync, Remote Data Bank, Media Flow, Buttress (remote inference), and the verification toolchain (compile, harness-specific preview tool, on-device DevTools, definition-of-done gate). Triggers on multi-device sync, cloud data, media assets, AI offloading, E2E testing, canvas transitions, or verifying project work before declaring done.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# BRICKS Ctor - Advanced Features
|
|
@@ -11,22 +11,26 @@ This skill covers advanced BRICKS features not in the main project instructions.
|
|
|
11
11
|
|
|
12
12
|
| Rule | Description |
|
|
13
13
|
|------|-------------|
|
|
14
|
-
| [Architecture Patterns](
|
|
15
|
-
| [Animation](
|
|
16
|
-
| [Standby Transition](
|
|
17
|
-
| [Automations](
|
|
18
|
-
| [Data Calculation](
|
|
19
|
-
| [Local Sync](
|
|
20
|
-
| [Remote Data Bank](
|
|
21
|
-
| [Media Flow](
|
|
22
|
-
| [Buttress](
|
|
14
|
+
| [Architecture Patterns](references/architecture-patterns.md) | **Read first** — decompose flows and select patterns |
|
|
15
|
+
| [Animation](references/animation.md) | Animation system for brick transforms and opacity |
|
|
16
|
+
| [Standby Transition](references/standby-transition.md) | Canvas enter/exit animations |
|
|
17
|
+
| [Automations](references/automations.md) | E2E testing and scheduled tasks |
|
|
18
|
+
| [Data Calculation](references/data-calculation.md) | JS sandbox libraries (25+ available) |
|
|
19
|
+
| [Local Sync](references/local-sync.md) | LAN device synchronization |
|
|
20
|
+
| [Remote Data Bank](references/remote-data-bank.md) | Cloud data sync and API access |
|
|
21
|
+
| [Media Flow](references/media-flow.md) | Media asset management |
|
|
22
|
+
| [Buttress](references/buttress.md) | Remote inference for AI generators |
|
|
23
|
+
| [Verification Toolchain](references/verification-toolchain.md) | Definition of done, compile, preview tool selection, on-device DevTools, Path 1/2/3 decision rule |
|
|
24
|
+
| [Simulator](references/simulator.md) | Path 1 fidelity — Simulator feature support, fallbacks (Camera/LLM/STT/Vector Store, Buttress disabled), when a green run is enough vs. Path 2 |
|
|
23
25
|
|
|
24
26
|
## Quick Reference
|
|
25
27
|
|
|
26
|
-
- **Complex flows**: See [Architecture Patterns](
|
|
27
|
-
- **Multi-device**: See [Local Sync](
|
|
28
|
-
- **Cloud data**: See [Remote Data Bank](
|
|
29
|
-
- **Media assets**: See [Media Flow](
|
|
30
|
-
- **AI offloading**: See [Buttress](
|
|
31
|
-
- **E2E testing**: See [Automations](
|
|
32
|
-
- **Enter animations**: See [Standby Transition](
|
|
28
|
+
- **Complex flows**: See [Architecture Patterns](references/architecture-patterns.md) for decomposing multi-step workflows
|
|
29
|
+
- **Multi-device**: See [Local Sync](references/local-sync.md) for LAN coordination
|
|
30
|
+
- **Cloud data**: See [Remote Data Bank](references/remote-data-bank.md) for sync and API access
|
|
31
|
+
- **Media assets**: See [Media Flow](references/media-flow.md) for centralized asset management
|
|
32
|
+
- **AI offloading**: See [Buttress](references/buttress.md) for GPU server delegation
|
|
33
|
+
- **E2E testing**: See [Automations](references/automations.md) for test automation
|
|
34
|
+
- **Enter animations**: See [Standby Transition](references/standby-transition.md) for canvas transitions
|
|
35
|
+
- **Verification before done**: See [Verification Toolchain](references/verification-toolchain.md) for the definition-of-done gate and Path 1/2/3 decision rule
|
|
36
|
+
- **Simulator fidelity**: See [Simulator](references/simulator.md) for what the Simulator fakes (Camera, AI generators, Buttress) and when to escalate to a real device
|
|
@@ -41,12 +41,13 @@ const bounce: AnimationDef = {
|
|
|
41
41
|
toValue: 1,
|
|
42
42
|
friction: 7,
|
|
43
43
|
tension: 40,
|
|
44
|
-
speed: 12,
|
|
45
|
-
bounciness: 8,
|
|
46
44
|
},
|
|
47
45
|
}
|
|
48
46
|
```
|
|
49
47
|
|
|
48
|
+
Use one spring parameter family per config: `tension/friction`, `speed/bounciness`, or
|
|
49
|
+
`stiffness/damping/mass`.
|
|
50
|
+
|
|
50
51
|
### Decay Animation
|
|
51
52
|
Velocity-based deceleration animation.
|
|
52
53
|
|
|
@@ -26,6 +26,8 @@ The primary way to orchestrate multi-step flows. A single event can contain an a
|
|
|
26
26
|
- Use `dataParams` + `mapping` to pass event data downstream
|
|
27
27
|
- This is the "glue" that wires generators, state, and UI together
|
|
28
28
|
|
|
29
|
+
Sequential `PROPERTY_BANK` / `PROPERTY_BANK_EXPRESSION` actions in one chain read the data values that existed when the chain started. If a later action needs to read what an earlier action wrote, set `waitAsync: true` on the earlier action.
|
|
30
|
+
|
|
29
31
|
### System Actions (Priority 3)
|
|
30
32
|
Built-in commands for direct state and UI changes.
|
|
31
33
|
- **PROPERTY_BANK**: set data value
|
|
@@ -67,3 +69,13 @@ Only actual data derivation maps to Data Calculation:
|
|
|
67
69
|
|
|
68
70
|
### Step 4: Wire with Event Action Chains
|
|
69
71
|
Connect the pieces through events on generators and bricks.
|
|
72
|
+
|
|
73
|
+
## Recipe: user-driven state machine (calculator, form wizard, picker)
|
|
74
|
+
|
|
75
|
+
A brief like "state vars X, Y, Z; button A updates X from X+Y; button B resets" is a state machine. The shape:
|
|
76
|
+
|
|
77
|
+
- Each state variable is its own `Data` entity. Displays read it via `linkData(() => data.dFoo)`.
|
|
78
|
+
- Each button's `onPress` is an Event Action Chain. For every state var that changes, append one `PROPERTY_BANK_EXPRESSION` whose `expression` reads the current state and returns the new value.
|
|
79
|
+
- Use `Data Calculation` only for reusable pure derivations referenced as inputs to those expressions.
|
|
80
|
+
|
|
81
|
+
A 10-button calculator with 4 state vars is ~10 small chains of 1–4 inline expressions. If you find yourself writing a single auto-mode `DataCalculationScript` that consumes all state vars and emits all-new state through mirror `dFooResult` data — or pinging a `dLastInput` field to force an auto calc to re-run — the chain shape was the right answer.
|
|
@@ -118,6 +118,16 @@ const testLoginFlow: AutomationTest = {
|
|
|
118
118
|
| `match_screenshot` | `[name, threshold?, maxRetry?]` | Screenshot compare |
|
|
119
119
|
| `delay` | `[subspace?, property?, defaultValue?]` | Delay execution |
|
|
120
120
|
|
|
121
|
+
In project TypeScript source, pass entity getters for BRICKS entities:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
run: ['brick_press', () => mainSubspace, () => bricks.bSubmitButton]
|
|
125
|
+
run: ['wait_until_canvas_change', () => mainSubspace, () => canvases.cDone, 5000]
|
|
126
|
+
run: ['assert_property', () => mainSubspace, () => data.dStep, 'done']
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The compiler resolves these getters to the current generated IDs.
|
|
130
|
+
|
|
121
131
|
### execute_action Params
|
|
122
132
|
|
|
123
133
|
The `params` object in `execute_action` uses **runtime event property keys** from `event-props.ts`, NOT the action config `input` names from type definitions.
|
|
@@ -208,6 +218,7 @@ Automations work with Modules. Use Manual Run in Preview mode for module testing
|
|
|
208
218
|
|
|
209
219
|
- **Automation map key**: Always use `'AUTOMATION_MAP_DEFAULT'` as the automation map ID (not `makeId()`). The preview test runner reads from `automationMap['AUTOMATION_MAP_DEFAULT']?.map`.
|
|
210
220
|
- **Valid makeId types**: Use `'test'` for AutomationTest, `'test_case'` for TestCase, `'test_var'` for TestVariable. Do NOT use `'automation_test'` or `'automation_test_map'`.
|
|
221
|
+
- **Entity references in run arrays**: Use getter references (`() => subspace`, `() => bricks.bButton`, `() => data.dValue`) in TypeScript source so compile resolves fresh IDs.
|
|
211
222
|
- **handler in execute_action**: Pass the entity's `.id` string (e.g., `bricks.bInput.id`), not a getter function.
|
|
212
223
|
|
|
213
224
|
## Best Practices
|