@fugood/bricks-project 2.24.3 → 2.24.5

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.
Files changed (83) hide show
  1. package/compile/action-name-map.ts +5 -0
  2. package/compile/index.ts +10 -4
  3. package/package.json +2 -2
  4. package/package.json.bak +2 -2
  5. package/skills/bricks-ctor/SKILL.md +3 -1
  6. package/skills/bricks-ctor/rules/architecture-patterns.md +12 -0
  7. package/skills/bricks-ctor/rules/automations.md +11 -0
  8. package/skills/bricks-ctor/rules/data-calculation.md +5 -5
  9. package/skills/bricks-ctor/rules/verification-toolchain.md +177 -0
  10. package/skills/bricks-design/SKILL.md +160 -45
  11. package/skills/bricks-design/references/architecture-truths.md +132 -0
  12. package/skills/bricks-design/references/avoiding-complexity.md +91 -0
  13. package/skills/bricks-design/references/design-critique.md +195 -0
  14. package/skills/bricks-design/references/design-languages.md +265 -0
  15. package/skills/bricks-design/references/performance.md +116 -0
  16. package/skills/bricks-design/references/presentation-and-slideshow.md +137 -0
  17. package/skills/bricks-design/references/translating-inputs.md +152 -0
  18. package/skills/bricks-design/references/variations-and-tweaks.md +124 -0
  19. package/skills/bricks-design/references/when-the-brief-is-branded.md +284 -0
  20. package/skills/bricks-design/references/when-the-brief-is-vague.md +85 -0
  21. package/skills/bricks-design/references/workflow.md +134 -0
  22. package/skills/bricks-ux/SKILL.md +120 -0
  23. package/skills/bricks-ux/references/accessibility.md +162 -0
  24. package/skills/bricks-ux/references/flow-states.md +175 -0
  25. package/skills/bricks-ux/references/interaction-archetypes.md +189 -0
  26. package/skills/bricks-ux/references/monitoring-screens.md +153 -0
  27. package/skills/bricks-ux/references/pressable-composition.md +126 -0
  28. package/skills/bricks-ux/references/user-journey.md +168 -0
  29. package/skills/bricks-ux/references/ux-critique.md +256 -0
  30. package/tools/_git-author.ts +10 -2
  31. package/tools/_last-pushed-commit.ts +28 -0
  32. package/tools/_shell.ts +8 -1
  33. package/tools/deploy.ts +15 -0
  34. package/tools/mcp-tools/compile.ts +17 -7
  35. package/tools/mcp-tools/media.ts +4 -1
  36. package/tools/pull.ts +91 -16
  37. package/tools/update-config.ts +8 -0
  38. package/types/animation.ts +8 -3
  39. package/types/automation.ts +1 -0
  40. package/types/brick-base.ts +1 -1
  41. package/types/bricks/Camera.ts +8 -8
  42. package/types/bricks/Chart.ts +4 -4
  43. package/types/bricks/GenerativeMedia.ts +15 -15
  44. package/types/bricks/Icon.ts +7 -7
  45. package/types/bricks/Image.ts +9 -9
  46. package/types/bricks/Items.ts +7 -7
  47. package/types/bricks/Lottie.ts +10 -10
  48. package/types/bricks/Maps.ts +11 -11
  49. package/types/bricks/QrCode.ts +7 -7
  50. package/types/bricks/Rect.ts +7 -7
  51. package/types/bricks/RichText.ts +12 -9
  52. package/types/bricks/Rive.ts +9 -9
  53. package/types/bricks/Sketch.ts +6 -6
  54. package/types/bricks/Slideshow.ts +7 -7
  55. package/types/bricks/Svg.ts +7 -7
  56. package/types/bricks/Text.ts +9 -9
  57. package/types/bricks/TextInput.ts +10 -10
  58. package/types/bricks/Video.ts +12 -12
  59. package/types/bricks/VideoStreaming.ts +10 -10
  60. package/types/bricks/WebRtcStream.ts +1 -1
  61. package/types/bricks/WebView.ts +4 -4
  62. package/types/common.ts +2 -2
  63. package/types/data-calc-command/base.ts +57 -0
  64. package/types/data-calc-command/collection.ts +418 -0
  65. package/types/data-calc-command/color.ts +432 -0
  66. package/types/data-calc-command/constant.ts +50 -0
  67. package/types/data-calc-command/datetime.ts +147 -0
  68. package/types/data-calc-command/file.ts +129 -0
  69. package/types/data-calc-command/index.ts +13 -0
  70. package/types/data-calc-command/iteratee.ts +23 -0
  71. package/types/data-calc-command/logictype.ts +190 -0
  72. package/types/data-calc-command/math.ts +275 -0
  73. package/types/data-calc-command/object.ts +119 -0
  74. package/types/data-calc-command/sandbox.ts +58 -0
  75. package/types/data-calc-command/string.ts +407 -0
  76. package/types/data-calc.ts +1 -0
  77. package/types/data.ts +1 -1
  78. package/types/generators/Assistant.ts +18 -0
  79. package/types/generators/LlmGgml.ts +37 -0
  80. package/utils/data.ts +1 -1
  81. package/utils/id.ts +78 -27
  82. package/skills/bricks-design/LICENSE.txt +0 -180
  83. package/types/data-calc-command.ts +0 -7005
@@ -782,6 +782,11 @@ export const templateActionNameMap = {
782
782
  seed: 'GENERATOR_LLM_SEED',
783
783
  typicalP: 'GENERATOR_LLM_TYPICAL_P',
784
784
  ignoreEos: 'GENERATOR_LLM_IGNORE_EOS',
785
+ mtpSpeculativeDecoding: 'GENERATOR_LLM_MTP_SPECULATIVE_DECODING',
786
+ mtpDraftTokens: 'GENERATOR_LLM_MTP_DRAFT_TOKENS',
787
+ mtpDraftMinTokens: 'GENERATOR_LLM_MTP_DRAFT_MIN_TOKENS',
788
+ mtpDraftMinProbability: 'GENERATOR_LLM_MTP_DRAFT_MIN_PROBABILITY',
789
+ mtpDraftSplitProbability: 'GENERATOR_LLM_MTP_DRAFT_SPLIT_PROBABILITY',
785
790
  functionCallEnabled: 'GENERATOR_LLM_FUNCTION_CALL_ENABLED',
786
791
  functionCallSchema: 'GENERATOR_LLM_FUNCTION_CALL_SCHEMA',
787
792
  },
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
- const animationId = assertEntryId(animation?.id, 'ANIMATION', errorReference)
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
@@ -641,6 +643,7 @@ const compileAutomationTest = (
641
643
 
642
644
  return {
643
645
  id: testId,
646
+ alias: test.alias,
644
647
  title: test.title,
645
648
  hide_short_ref: test.hideShortRef,
646
649
  timeout: test.timeout,
@@ -1189,7 +1192,7 @@ export const compile = async (app: Application) => {
1189
1192
  ...compileRemoteUpdate(data.remoteUpdate),
1190
1193
  routing: data.routing,
1191
1194
  schema: data.schema,
1192
- type: data.type,
1195
+ type: data.type === 'boolean' ? 'bool' : data.type,
1193
1196
  ...compileKind(data.kind),
1194
1197
  value: compileProperty(data.value, `(data: ${dataId}, subspace ${subspaceId})`),
1195
1198
  event_map: compileEvents('PROPERTY_BANK', data.events || {}, {
@@ -1209,6 +1212,7 @@ export const compile = async (app: Application) => {
1209
1212
  )
1210
1213
 
1211
1214
  const calc: any = {
1215
+ alias: dataCalc.alias,
1212
1216
  title: dataCalc.title,
1213
1217
  description: dataCalc.description,
1214
1218
  hide_short_ref: dataCalc.hideShortRef,
@@ -1454,5 +1458,7 @@ export const compile = async (app: Application) => {
1454
1458
 
1455
1459
  export const checkConfig = async (configPath: string) => {
1456
1460
  const { sh } = await import('../tools/_shell')
1457
- await sh`bricks app check-config ${configPath}`
1461
+ // --validate-automation surfaces broken automation_map / test_map refs early,
1462
+ // which catches agent-authored automations that reference deleted bricks.
1463
+ await sh`bricks app check-config --validate-automation ${configPath}`
1458
1464
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@fugood/bricks-project",
3
- "version": "2.24.3",
3
+ "version": "2.24.5",
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.24.3",
10
+ "@fugood/bricks-cli": "^2.24.5",
11
11
  "@huggingface/gguf": "^0.3.2",
12
12
  "@iarna/toml": "^3.0.0",
13
13
  "@modelcontextprotocol/sdk": "^1.15.0",
package/package.json.bak CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@fugood/bricks-ctor",
3
- "version": "2.24.3",
3
+ "version": "2.24.5",
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.24.3",
10
+ "@fugood/bricks-cli": "^2.24.5",
11
11
  "@huggingface/gguf": "^0.3.2",
12
12
  "@iarna/toml": "^3.0.0",
13
13
  "@modelcontextprotocol/sdk": "^1.15.0",
@@ -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, and Buttress (remote inference). Triggers on multi-device sync, cloud data, media assets, AI offloading, E2E testing, or canvas transitions.
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
@@ -20,6 +20,7 @@ This skill covers advanced BRICKS features not in the main project instructions.
20
20
  | [Remote Data Bank](rules/remote-data-bank.md) | Cloud data sync and API access |
21
21
  | [Media Flow](rules/media-flow.md) | Media asset management |
22
22
  | [Buttress](rules/buttress.md) | Remote inference for AI generators |
23
+ | [Verification Toolchain](rules/verification-toolchain.md) | Definition of done, compile, preview tool selection, on-device DevTools, Path 1/2/3 decision rule |
23
24
 
24
25
  ## Quick Reference
25
26
 
@@ -30,3 +31,4 @@ This skill covers advanced BRICKS features not in the main project instructions.
30
31
  - **AI offloading**: See [Buttress](rules/buttress.md) for GPU server delegation
31
32
  - **E2E testing**: See [Automations](rules/automations.md) for test automation
32
33
  - **Enter animations**: See [Standby Transition](rules/standby-transition.md) for canvas transitions
34
+ - **Verification before done**: See [Verification Toolchain](rules/verification-toolchain.md) for the definition-of-done gate and Path 1/2/3 decision rule
@@ -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
@@ -167,7 +167,7 @@ code: `
167
167
 
168
168
  ## Triggering Manually
169
169
 
170
- Use `PROPERTY_BANK_COMMAND` system action to trigger a manual calculation:
170
+ Use `PROPERTY_BANK_COMMAND` system action to trigger a manual calculation. `input` references a Data that is a trigger input (`trigger: true`) of the target calc — the system runs the calc(s) that data feeds into. It does NOT reference the DataCalculation itself.
171
171
 
172
172
  ```typescript
173
173
  const triggerCalc: EventAction = {
@@ -176,12 +176,14 @@ const triggerCalc: EventAction = {
176
176
  __actionName: 'PROPERTY_BANK_COMMAND',
177
177
  parent: 'System',
178
178
  dataParams: [
179
- { input: () => computeTotalCalc }, // Reference to DataCalculation
179
+ { input: () => priceData }, // Reference to a trigger Data input of the calc
180
180
  ],
181
181
  },
182
182
  }
183
183
  ```
184
184
 
185
+ When the same chain writes a calc input (e.g. `PROPERTY_BANK` setting `dLastButton`) then issues `PROPERTY_BANK_COMMAND`, set `waitAsync: true` on the write so the calc reads the new value rather than the pre-chain snapshot. See [Event Action Chains](architecture-patterns.md#event-action-chains-priority-2).
186
+
185
187
  ## Best Practices
186
188
 
187
189
  1. **Avoid circular deps**: Set non-triggering inputs (`trigger: false`) or use `manual` mode
@@ -194,9 +196,7 @@ const triggerCalc: EventAction = {
194
196
  See [Architecture Patterns](architecture-patterns.md) for the full pattern selection guide.
195
197
 
196
198
  ### Using Data Calc as an orchestrator
197
- Scripts that manage state machines, control UI flow, or coordinate multi-step processes belong in Event Action Chains, not here.
198
-
199
- **Symptom**: Script has if/else branches deciding "what happens next" or tracks "current step".
199
+ Scripts that manage state machines, control UI flow, or coordinate multi-step processes belong in Event Action Chains. Symptoms: if/else on "what happens next", mirror `dFooResult` outputs that copy back to `dFoo` via `valueChange`, or a `dLastInput` field set-then-cleared to force an auto calc. See the "user-driven state machine" recipe in [Architecture Patterns](architecture-patterns.md).
200
200
 
201
201
  ### Quick reference
202
202
 
@@ -0,0 +1,177 @@
1
+ # Verification Toolchain
2
+
3
+ Three runtime targets, one decision rule. Verify against the cheapest path that proves what you need to prove.
4
+
5
+ ## Definition of done — the hard gate
6
+
7
+ Before the agent is allowed to claim work is complete, **all** of the following must be true:
8
+
9
+ 1. **Compile clean.** Latest source passes `compile` with no errors.
10
+ 2. **Every Canvas screenshot captured.** A rendered screenshot of every Canvas in the deliverable, captured via the available preview tool (`responseImage: true` when the selected model supports vision) at the target hardware resolution and orientation. Canvases gated behind events are reached via Automation runs (`testId` / `testTitleLike` with `brick_press` / `wait_until_canvas_change` cases). Single-Canvas Subspaces still require a captured screenshot.
11
+ 3. **Every screenshot reviewed by the agent.** The agent must read each captured screenshot back through the host's image-reading capability — saving the file is not the same as seeing it. The model that produced the Canvas must also have seen the rendered result, or the verification gate has not passed.
12
+ 4. **Reference comparison report.** If the user supplied any reference material (Figma / website / HTML / screenshot / PDF / brand book / competitor), produce a short delta report per Canvas:
13
+ - What matches the reference.
14
+ - What intentionally diverges, and why (deployment constraint, BRICKS-runtime semantic, system commitment).
15
+ - What unintentionally diverges, and the planned fix.
16
+ 5. **Path appropriate to deployment executed.** Path 1 by default. Path 2 (on-device) when the deployment depends on real hardware behaviour, or whenever the brief touches payment, identity, peripherals, or LocalSync.
17
+ 6. **Console clean.** No 404s on media, no Data-key-undefined warnings, no Generator init failures, no React-style warnings — every console line is either zero or accept-with-a-comment.
18
+
19
+ What does **not** count as done:
20
+
21
+ - A single hero-Canvas screenshot.
22
+ - "Looks roughly like the reference" with no per-Canvas comparison.
23
+ - "Compiled successfully" with no rendered preview.
24
+ - A claim of done with no screenshots in evidence.
25
+ - Captured screenshots saved to disk but never read back by the agent.
26
+
27
+ If any item is unmet, the work is mid-iteration. Say so explicitly to the user; offer a precise list of what remains.
28
+
29
+ ## Path 1 — Electron preview (no device required)
30
+
31
+ The default loop. Always available; deterministic; no device wear; safe for side-effecting flows because nothing real fires.
32
+
33
+ `bun update-app` and `bun deploy-app` publish to the BRICKS portal. The local preview reads `.bricks/build/application-config.json` (produced by `compile`) directly.
34
+
35
+ ### Compile tool
36
+
37
+ Typecheck + compile the project. Gate every iteration on this; everything below assumes a clean compile.
38
+
39
+ Agent invocation: call the MCP tool `compile` exposed by the `bricks-ctor` MCP server registered for the project. No arguments.
40
+
41
+ ### Preview tool
42
+
43
+ Use the preview implementation exposed by the current harness:
44
+
45
+ - **CTOR Desktop agent session:** use `preview_invoke`. CTOR Desktop disables the `bricks-ctor` MCP `preview` tool and routes screenshots/automation through the desktop preview pane instead. If the user already opened the simulator pane, `preview_invoke` should reuse it rather than start a separate preview.
46
+ - **Pure `bricks-ctor` project / other agent harness:** use the `bricks-ctor` MCP `preview` tool when `preview_invoke` is not available.
47
+
48
+ Both forms are the same verification primitive: launch or reuse Electron preview, take a screenshot, and optionally run a named Automation test by id or partial title. Do not hard-code one tool name into the workflow; choose the available preview tool for the environment.
49
+
50
+ Common arguments:
51
+ - `delay` (ms before screenshot) — default is harness-specific: usually 3000 for a fresh/standalone preview; CTOR Desktop may capture immediately when its preview already has a settled latest config. Increase if Standby Transitions are still in flight.
52
+ - `width`, `height` — screenshot dimensions in px.
53
+ - `responseImage: true` — return the screenshot as image content when the selected model supports vision. If vision is unavailable, save the screenshot and report the path.
54
+ - `testId` or `testTitleLike` — run a project Automation before the screenshot. Use `testTitleLike` for fuzzy matches (case-insensitive partial title).
55
+
56
+ Returns text log + saved screenshot path + image content when supported.
57
+
58
+ ### `bun preview` (project script)
59
+
60
+ Sustained dev session — watches `subspaces/`, recompiles on save, exposes CDP at `localhost:19852` (configurable via `--cdp-port`), writes `.bricks/devtools.json` with port/pid for downstream tooling.
61
+
62
+ Useful flags:
63
+ - `--screenshot` + `--screenshot-delay/width/height/path` — drive screenshot capture without keeping the window open.
64
+ - `--show-menu` — surface the Electron menu (debugging).
65
+ - `--test-id` / `--test-title-like` — run an Automation in this preview.
66
+ - `--no-keep-open` — exit after one screenshot.
67
+ - `--no-cdp` — disable CDP server (rare; default is to expose it).
68
+ - `--clear-cache` — reset cached state between runs.
69
+
70
+ For ad-hoc CDP inspection against this local preview, connect any CDP client to `localhost:19852` — Chrome DevTools front-end works directly. For an agent-friendly CLI over CDP (screenshot, brick tree/query, input emulation, storage reads, runtime eval, network capture), the `bricks-cli` skill documents the `bricks devtools` command surface — read that skill if it is installed in this workspace. If it is not installed, run `bricks --help` and `bricks devtools --help`; the CLI's own help output is authoritative.
71
+
72
+ ### Project Automations
73
+
74
+ E2E tests authored in TypeScript inside the project (`AutomationTest` / `TestCase`). Test cases include:
75
+
76
+ - `brick_press` — synthesize a press on a Brick.
77
+ - `wait_until_canvas_change` — assert navigation.
78
+ - `assert_property` — assert a Data value equals expected.
79
+ - `wait_property_update` — wait for a Data value to change.
80
+ - `match_screenshot` — visual regression with stored reference image.
81
+
82
+ Trigger types: `launch` (runs on app start), `anytime` (manual), `cron` (scheduled).
83
+
84
+ Important: the automation map id must be `'AUTOMATION_MAP_DEFAULT'` (not a generated id) — the preview test runner reads from `automationMap['AUTOMATION_MAP_DEFAULT']?.map`.
85
+
86
+ Run a single test from the agent: call the available preview tool (`preview_invoke` in CTOR Desktop, otherwise `bricks-ctor` MCP `preview`) with `testId` or `testTitleLike`.
87
+
88
+ ## Path 2 — Real device with DevTools enabled
89
+
90
+ Required when the deployment depends on hardware behaviour the Electron preview cannot reproduce: physical orientation/DPI, real touch hardware (IR overlays, multi-touch), peripherals (camera, BLE, MQTT, NFC, payment, printer, sensors), watchdog cycles on the actual launcher build, fleet-managed reboot semantics, LocalSync across multiple devices, the actual color/luminance of the panel.
91
+
92
+ **Always Path 2** when the brief touches: payment, identity capture, real-time peripheral data, multi-device LocalSync, certified hardware.
93
+
94
+ ### One-time manual setup (the agent cannot do this)
95
+
96
+ Ask the user to:
97
+
98
+ 1. On the device, open **Settings** → advanced settings.
99
+ 2. Toggle **Chrome DevTools** on. The device starts a DevTools server on the local network on port `19851` (auto-increments if taken).
100
+ 3. Confirm **Enable LAN Discovery** is on (default) so the device is discoverable.
101
+ 4. Note the device passcode if displayed.
102
+
103
+ Requires BRICKS Foundation **≥ 2.24** for CDP commands.
104
+
105
+ ### Endpoints exposed once enabled
106
+
107
+ | Endpoint | URL shape | Use |
108
+ |---|---|---|
109
+ | Web UI | `http://<ip>:19851` | DevTools landing in a browser |
110
+ | CDP | `http://<ip>:19851/devtools-frontend/inspector.html?ws=<ip>:19851/ws/<passcode>` | Chrome DevTools front-end |
111
+ | MCP | `http://<ip>:19851/mcp` | MCP endpoint (Bearer-token auth with passcode) |
112
+ | MCP SSE | `http://<ip>:19851/sse` | Same, SSE transport |
113
+ | Info | `http://<ip>:19851/devtools/info` | Device / server metadata |
114
+
115
+ ### Driving the device
116
+
117
+ Once DevTools is on, ask the user how they want to drive the verification — Chrome DevTools front-end, an MCP client they already run, or screenshot export from their own tooling — and follow their lead. Capture every Canvas screenshot through whichever path the user picks; the verification gate is about the evidence, not the tool.
118
+
119
+ For agent-driven CDP/MCP work against the device (`bricks devtools …` with `-a <ip> --passcode <pc>`, plus bridging the device MCP endpoint into an MCP client), the same `bricks-cli` skill referenced in Path 1 covers the on-device case — read it if installed. If not installed, run `bricks --help` and `bricks devtools --help` for the authoritative command listing.
120
+
121
+ ### Real-device side-effects warning
122
+
123
+ Real devices fire real peripherals. Payment terminals charge. MQTT broadcasts on shared topics. BLE advertises to bystanders. Use a **staging** device for verification cycles; never iterate on a production-deployed device unless the user explicitly approves.
124
+
125
+ ## Path 3 — Remote debugging via BRICKS Controller (off-LAN)
126
+
127
+ Out of scope for the standard verification loop. It exists for ops scenarios where the device is not on the same network. If the user asks for it, point them at the BRICKS Controller documentation rather than attempting it as part of verification.
128
+
129
+ ## Decision rule
130
+
131
+ ```
132
+ default Path 1.
133
+
134
+ if deployment depends on:
135
+ physical orientation / DPI / touch HW / peripherals /
136
+ watchdog on real launcher / LocalSync / certified hardware
137
+ → escalate to Path 2 before declaring done.
138
+
139
+ if brief touches payment, identity, peripherals, LocalSync
140
+ → Path 2 is mandatory, not optional.
141
+
142
+ if user is off-LAN
143
+ → Path 3 (out of scope here).
144
+ ```
145
+
146
+ ## What to actually verify (per shape)
147
+
148
+ ### Static signage (single-canvas glance loop)
149
+ - Path 1 screenshot captures the loop frame.
150
+ - Watch one full rotation in `bun preview` to see all queue items.
151
+ - Cut network mid-loop; confirm cached media plays.
152
+ - Path 2 only if the panel is OLED / has burn-in concerns or specific color profile.
153
+
154
+ ### Multi-canvas state machine (kiosk)
155
+ - Path 1: Automation walking the happy path with `brick_press` + `wait_until_canvas_change` + `assert_property` + `match_screenshot` per Canvas.
156
+ - Cancel + inactivity reset paths verified as Automations.
157
+ - Watchdog reset: kill the runtime, restart, confirm boot Canvas resets transient flow Data.
158
+ - Path 2 mandatory if payment / identity is in the flow — fire a real test transaction on staging hardware.
159
+
160
+ ### Subspace-driven composition
161
+ - Path 1: open the Subspace standalone if the preview supports it; verify in isolation.
162
+ - Embedded test: walk the host's flow; assert Outlets fire as expected via `wait_property_update`.
163
+ - Re-mount test: cause the host to re-bind the Subspace; confirm internal state resets.
164
+
165
+ ### Generator-driven reactive
166
+ - Path 1: drive the source by writing to Data from the runtime (whatever CDP path the user prefers); observe Brick re-render.
167
+ - Throttle / firehose tests: write 100 updates rapidly; confirm the canvas doesn't choke (frame budget intact).
168
+ - Disconnect: simulate source disconnect; confirm UI surfaces stale state, not blank.
169
+ - Threshold transitions: cross every Switch boundary; confirm visual reaction.
170
+ - Path 2 mandatory if the source is a real peripheral — Electron cannot fake the timing or the failure modes.
171
+
172
+ ### Multi-device LocalSync
173
+ - Path 2 mandatory. Two devices on the same LAN with DevTools on. Drive one, observe the other.
174
+
175
+ ## Browser / runtime log discipline
176
+
177
+ Throughout: the DevTools console must be clean. 404s on media, "Data key not defined" warnings, Generator init failures, React-style warnings — every one is a defect or accept-with-comment. Don't ship around them.