@fugood/bricks-ctor 2.25.0-beta.60 → 2.25.0-beta.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -28
- package/tools/__tests__/legacy-forwarder.test.js +91 -0
- package/tools/_forward.ts +26 -0
- package/tools/deploy.ts +3 -175
- package/tools/mcp-server.ts +3 -35
- package/tools/postinstall.ts +3 -291
- package/tools/pull.ts +3 -198
- package/tools/push-config.ts +3 -113
- package/tools/simulator.ts +3 -149
- package/compile/__tests__/config-diff.test.js +0 -100
- package/compile/__tests__/index.test.js +0 -461
- package/compile/__tests__/util.test.js +0 -450
- package/compile/action-name-map.ts +0 -1079
- package/compile/config-diff.ts +0 -155
- package/compile/index.ts +0 -1594
- package/compile/util.ts +0 -482
- package/index.ts +0 -6
- package/skills/bricks-ctor/SKILL.md +0 -38
- package/skills/bricks-ctor/references/animation.md +0 -160
- package/skills/bricks-ctor/references/architecture-patterns.md +0 -88
- package/skills/bricks-ctor/references/automations.md +0 -232
- package/skills/bricks-ctor/references/buttress.md +0 -245
- package/skills/bricks-ctor/references/data-calculation.md +0 -252
- package/skills/bricks-ctor/references/local-sync.md +0 -129
- package/skills/bricks-ctor/references/media-flow.md +0 -165
- package/skills/bricks-ctor/references/remote-data-bank.md +0 -196
- package/skills/bricks-ctor/references/simulator.md +0 -132
- package/skills/bricks-ctor/references/source-editing-tools.md +0 -81
- package/skills/bricks-ctor/references/standby-transition.md +0 -124
- package/skills/bricks-ctor/references/verification-toolchain.md +0 -200
- package/skills/bricks-design/SKILL.md +0 -171
- package/skills/bricks-design/references/architecture-truths.md +0 -132
- package/skills/bricks-design/references/avoiding-complexity.md +0 -91
- package/skills/bricks-design/references/design-critique.md +0 -195
- package/skills/bricks-design/references/design-languages.md +0 -265
- package/skills/bricks-design/references/performance.md +0 -116
- package/skills/bricks-design/references/presentation-and-slideshow.md +0 -137
- package/skills/bricks-design/references/translating-inputs.md +0 -152
- package/skills/bricks-design/references/variations-and-tweaks.md +0 -124
- package/skills/bricks-design/references/when-the-brief-is-branded.md +0 -284
- package/skills/bricks-design/references/when-the-brief-is-vague.md +0 -85
- package/skills/bricks-design/references/workflow.md +0 -134
- package/skills/bricks-ux/SKILL.md +0 -114
- package/skills/bricks-ux/references/accessibility.md +0 -162
- package/skills/bricks-ux/references/flow-states.md +0 -175
- package/skills/bricks-ux/references/interaction-archetypes.md +0 -189
- package/skills/bricks-ux/references/monitoring-screens.md +0 -153
- package/skills/bricks-ux/references/pressable-composition.md +0 -126
- package/skills/bricks-ux/references/user-journey.md +0 -168
- package/skills/bricks-ux/references/ux-critique.md +0 -256
- package/skills/rive-marketplace/SKILL.md +0 -99
- package/tools/__tests__/_cli-error.test.ts +0 -35
- package/tools/__tests__/_mcp-config.test.ts +0 -67
- package/tools/__tests__/pull.test.ts +0 -108
- package/tools/_cli-error.ts +0 -17
- package/tools/_edits-log.ts +0 -41
- package/tools/_git-author.ts +0 -37
- package/tools/_last-pushed-commit.ts +0 -28
- package/tools/_mcp-config.ts +0 -42
- package/tools/_shell.ts +0 -180
- package/tools/icons/.gitattributes +0 -1
- package/tools/icons/fa6pro-glyphmap.json +0 -4686
- package/tools/icons/fa6pro-meta.json +0 -1
- package/tools/mcp-env.ts +0 -13
- package/tools/mcp-tools/__tests__/data-calc-editing.test.js +0 -516
- package/tools/mcp-tools/__tests__/entry-editing.test.js +0 -866
- package/tools/mcp-tools/__tests__/huggingface.test.ts +0 -49
- package/tools/mcp-tools/__tests__/icons.test.ts +0 -21
- package/tools/mcp-tools/__tests__/mcp-env.test.js +0 -19
- package/tools/mcp-tools/_editing-helpers.ts +0 -98
- package/tools/mcp-tools/_verify.ts +0 -50
- package/tools/mcp-tools/compile.ts +0 -104
- package/tools/mcp-tools/data-calc-editing.ts +0 -1311
- package/tools/mcp-tools/entry-editing.ts +0 -2297
- package/tools/mcp-tools/huggingface.ts +0 -772
- package/tools/mcp-tools/icons.ts +0 -97
- package/tools/mcp-tools/lottie.ts +0 -102
- package/tools/mcp-tools/media.ts +0 -113
- package/tools/simulator-main.mjs +0 -488
- package/tools/simulator-preload.cjs +0 -16
- package/types/animation.d.ts +0 -116
- package/types/automation.d.ts +0 -231
- package/types/brick-base.d.ts +0 -80
- package/types/bricks/Camera.d.ts +0 -246
- package/types/bricks/Chart.d.ts +0 -372
- package/types/bricks/GenerativeMedia.d.ts +0 -290
- package/types/bricks/Icon.d.ts +0 -98
- package/types/bricks/Image.d.ts +0 -126
- package/types/bricks/Items.d.ts +0 -480
- package/types/bricks/Lottie.d.ts +0 -168
- package/types/bricks/Maps.d.ts +0 -262
- package/types/bricks/QrCode.d.ts +0 -117
- package/types/bricks/Rect.d.ts +0 -150
- package/types/bricks/RichText.d.ts +0 -131
- package/types/bricks/Rive.d.ts +0 -220
- package/types/bricks/Scene3D.d.ts +0 -676
- package/types/bricks/Sketch.d.ts +0 -256
- package/types/bricks/Slideshow.d.ts +0 -201
- package/types/bricks/Svg.d.ts +0 -99
- package/types/bricks/Text.d.ts +0 -148
- package/types/bricks/TextInput.d.ts +0 -242
- package/types/bricks/Video.d.ts +0 -242
- package/types/bricks/VideoStreaming.d.ts +0 -112
- package/types/bricks/WebRtcStream.d.ts +0 -65
- package/types/bricks/WebView.d.ts +0 -168
- package/types/bricks/index.d.ts +0 -23
- package/types/canvas.d.ts +0 -82
- package/types/common.d.ts +0 -141
- package/types/data-calc-command/base.d.ts +0 -57
- package/types/data-calc-command/collection.d.ts +0 -418
- package/types/data-calc-command/color.d.ts +0 -432
- package/types/data-calc-command/constant.d.ts +0 -50
- package/types/data-calc-command/datetime.d.ts +0 -147
- package/types/data-calc-command/file.d.ts +0 -129
- package/types/data-calc-command/index.d.ts +0 -13
- package/types/data-calc-command/iteratee.d.ts +0 -23
- package/types/data-calc-command/logictype.d.ts +0 -190
- package/types/data-calc-command/math.d.ts +0 -275
- package/types/data-calc-command/object.d.ts +0 -119
- package/types/data-calc-command/sandbox.d.ts +0 -66
- package/types/data-calc-command/string.d.ts +0 -407
- package/types/data-calc-script.d.ts +0 -21
- package/types/data-calc.d.ts +0 -12
- package/types/data.d.ts +0 -97
- package/types/generators/AlarmClock.d.ts +0 -110
- package/types/generators/Assistant.d.ts +0 -640
- package/types/generators/BleCentral.d.ts +0 -247
- package/types/generators/BlePeripheral.d.ts +0 -208
- package/types/generators/CanvasMap.d.ts +0 -74
- package/types/generators/CastlesPay.d.ts +0 -87
- package/types/generators/DataBank.d.ts +0 -160
- package/types/generators/File.d.ts +0 -432
- package/types/generators/GraphQl.d.ts +0 -132
- package/types/generators/Http.d.ts +0 -222
- package/types/generators/HttpServer.d.ts +0 -230
- package/types/generators/Information.d.ts +0 -103
- package/types/generators/Intent.d.ts +0 -168
- package/types/generators/Iterator.d.ts +0 -108
- package/types/generators/Keyboard.d.ts +0 -105
- package/types/generators/LlmAnthropicCompat.d.ts +0 -212
- package/types/generators/LlmAppleBuiltin.d.ts +0 -159
- package/types/generators/LlmGgml.d.ts +0 -903
- package/types/generators/LlmMediaTekNeuroPilot.d.ts +0 -235
- package/types/generators/LlmMlx.d.ts +0 -228
- package/types/generators/LlmOnnx.d.ts +0 -213
- package/types/generators/LlmOpenAiCompat.d.ts +0 -312
- package/types/generators/LlmQualcommAiEngine.d.ts +0 -247
- package/types/generators/Mcp.d.ts +0 -637
- package/types/generators/McpServer.d.ts +0 -289
- package/types/generators/MediaFlow.d.ts +0 -170
- package/types/generators/MqttBroker.d.ts +0 -141
- package/types/generators/MqttClient.d.ts +0 -141
- package/types/generators/Question.d.ts +0 -408
- package/types/generators/RealtimeTranscription.d.ts +0 -287
- package/types/generators/RerankerGgml.d.ts +0 -195
- package/types/generators/SerialPort.d.ts +0 -151
- package/types/generators/SoundPlayer.d.ts +0 -94
- package/types/generators/SoundRecorder.d.ts +0 -139
- package/types/generators/SpeechToTextGgml.d.ts +0 -424
- package/types/generators/SpeechToTextOnnx.d.ts +0 -236
- package/types/generators/SpeechToTextPlatform.d.ts +0 -85
- package/types/generators/SqLite.d.ts +0 -159
- package/types/generators/Step.d.ts +0 -107
- package/types/generators/SttAppleBuiltin.d.ts +0 -153
- package/types/generators/Tcp.d.ts +0 -126
- package/types/generators/TcpServer.d.ts +0 -147
- package/types/generators/TextToSpeechAppleBuiltin.d.ts +0 -127
- package/types/generators/TextToSpeechGgml.d.ts +0 -221
- package/types/generators/TextToSpeechOnnx.d.ts +0 -178
- package/types/generators/TextToSpeechOpenAiLike.d.ts +0 -121
- package/types/generators/ThermalPrinter.d.ts +0 -193
- package/types/generators/Tick.d.ts +0 -83
- package/types/generators/Udp.d.ts +0 -120
- package/types/generators/VadGgml.d.ts +0 -260
- package/types/generators/VadOnnx.d.ts +0 -231
- package/types/generators/VadTraditional.d.ts +0 -138
- package/types/generators/VectorStore.d.ts +0 -257
- package/types/generators/Watchdog.d.ts +0 -107
- package/types/generators/WebCrawler.d.ts +0 -103
- package/types/generators/WebRtc.d.ts +0 -181
- package/types/generators/WebSocket.d.ts +0 -148
- package/types/generators/index.d.ts +0 -57
- package/types/index.d.ts +0 -13
- package/types/subspace.d.ts +0 -60
- package/types/switch.d.ts +0 -51
- package/types/system.d.ts +0 -707
- package/utils/__tests__/calc.test.js +0 -25
- package/utils/__tests__/id.test.js +0 -154
- package/utils/calc.ts +0 -130
- package/utils/data.ts +0 -495
- package/utils/event-props.ts +0 -912
- package/utils/id.ts +0 -133
|
@@ -1,200 +0,0 @@
|
|
|
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 — Simulator (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
|
-
Before trusting a Simulator screenshot, know what it can and can't reproduce: it runs in the Electron preview (a browser-class runtime, not the device — and not the device's JS engine), can't exercise hardware/peripheral features (BLE, printers, raw sockets, SQLite, …), and substitutes fallbacks for Camera and the AI generators (LLM/STT/Vector Store) with Buttress disabled. See [Simulator](simulator.md) for the fidelity boundaries and the per-item gear to run the real implementation — it's what tells you when a green run is enough vs. when to escalate to Path 2.
|
|
34
|
-
|
|
35
|
-
`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.
|
|
36
|
-
|
|
37
|
-
### Compile tool
|
|
38
|
-
|
|
39
|
-
Typecheck + compile the project. Gate every iteration on this; everything below assumes a clean compile.
|
|
40
|
-
|
|
41
|
-
Agent invocation: call the MCP tool `compile` exposed by the `bricks-ctor` MCP server registered for the project. No arguments.
|
|
42
|
-
|
|
43
|
-
### Simulator tool
|
|
44
|
-
|
|
45
|
-
Use the preview implementation exposed by the current harness:
|
|
46
|
-
|
|
47
|
-
- **CTOR Desktop agent session:** use `simulator_invoke`. CTOR Desktop disables the `bricks-ctor` MCP `simulator` tool and routes screenshots/automation through the desktop preview pane instead. If the user already opened the simulator pane, `simulator_invoke` should reuse it rather than start a separate preview.
|
|
48
|
-
- **Pure `bricks-ctor` project / other agent harness:** use the `bricks-ctor` MCP `simulator` tool when `simulator_invoke` is not available.
|
|
49
|
-
|
|
50
|
-
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.
|
|
51
|
-
|
|
52
|
-
Common arguments:
|
|
53
|
-
- `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.
|
|
54
|
-
- `width`, `height` — screenshot dimensions in px.
|
|
55
|
-
- `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.
|
|
56
|
-
- `testId` or `testTitleLike` — run a project Automation before the screenshot. Use `testTitleLike` for fuzzy matches (case-insensitive partial title).
|
|
57
|
-
|
|
58
|
-
Returns text log + saved screenshot path + image content when supported.
|
|
59
|
-
|
|
60
|
-
### `bun invoke-simulator` (project script)
|
|
61
|
-
|
|
62
|
-
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.
|
|
63
|
-
|
|
64
|
-
Useful flags:
|
|
65
|
-
- `--screenshot` + `--screenshot-delay/width/height/path` — drive screenshot capture without keeping the window open.
|
|
66
|
-
- `--show-menu` — surface the Electron menu (debugging).
|
|
67
|
-
- `--test-id` / `--test-title-like` — run an Automation in this preview.
|
|
68
|
-
- `--no-keep-open` — exit after one screenshot.
|
|
69
|
-
- `--no-cdp` — disable CDP server (rare; default is to expose it).
|
|
70
|
-
- `--clear-cache` — reset cached state between runs.
|
|
71
|
-
|
|
72
|
-
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.
|
|
73
|
-
|
|
74
|
-
To inspect Data / Property Bank or storage state, prefer the dedicated `bricks devtools storage` subcommands — `storage data-bank get <S_xxxx>` (saved Data values), `storage system persist|memory`, `storage system get <key>` — over hand-written `runtime eval`. Reach for `runtime eval` only for *live* store internals that aren't persisted to a data bank (e.g. a current transient value: `runtime eval "system.data.property('S_xxxx', '<alias>')"`); don't reverse-engineer the `system.*` globals.
|
|
75
|
-
|
|
76
|
-
### Project Automations
|
|
77
|
-
|
|
78
|
-
E2E tests authored in TypeScript inside the project (`AutomationTest` / `TestCase`). Test cases include:
|
|
79
|
-
|
|
80
|
-
- `brick_press` — synthesize a press on a Brick.
|
|
81
|
-
- `wait_until_canvas_change` — assert navigation.
|
|
82
|
-
- `assert_property` — assert a Data value equals expected.
|
|
83
|
-
- `wait_property_update` — wait for a Data value to change.
|
|
84
|
-
- `match_screenshot` — visual regression with stored reference image.
|
|
85
|
-
|
|
86
|
-
Trigger types: `launch` (runs on app start), `anytime` (manual), `cron` (scheduled).
|
|
87
|
-
|
|
88
|
-
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`.
|
|
89
|
-
|
|
90
|
-
Run a single test from the agent: call the available preview tool (`simulator_invoke` in CTOR Desktop, otherwise `bricks-ctor` MCP `preview`) with `testId` or `testTitleLike`.
|
|
91
|
-
|
|
92
|
-
## Path 2 — Real device with DevTools enabled
|
|
93
|
-
|
|
94
|
-
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.
|
|
95
|
-
|
|
96
|
-
**Always Path 2** when the brief touches: payment, identity capture, real-time peripheral data, multi-device LocalSync, certified hardware.
|
|
97
|
-
|
|
98
|
-
### One-time manual setup (the agent cannot do this)
|
|
99
|
-
|
|
100
|
-
Ask the user to:
|
|
101
|
-
|
|
102
|
-
1. On the device, open **Settings** → advanced settings.
|
|
103
|
-
2. Toggle **Chrome DevTools** on. The device starts a DevTools server on the local network on port `19851` (auto-increments if taken).
|
|
104
|
-
3. Confirm **Enable LAN Discovery** is on (default) so the device is discoverable.
|
|
105
|
-
4. Note the device passcode if displayed.
|
|
106
|
-
|
|
107
|
-
Requires BRICKS Foundation **≥ 2.24** for CDP commands.
|
|
108
|
-
|
|
109
|
-
### Endpoints exposed once enabled
|
|
110
|
-
|
|
111
|
-
| Endpoint | URL shape | Use |
|
|
112
|
-
|---|---|---|
|
|
113
|
-
| Web UI | `http://<ip>:19851` | DevTools landing in a browser |
|
|
114
|
-
| CDP | `http://<ip>:19851/devtools-frontend/inspector.html?ws=<ip>:19851/ws/<passcode>` | Chrome DevTools front-end |
|
|
115
|
-
| MCP | `http://<ip>:19851/mcp` | MCP endpoint (Bearer-token auth with passcode) |
|
|
116
|
-
| MCP SSE | `http://<ip>:19851/sse` | Same, SSE transport |
|
|
117
|
-
| Info | `http://<ip>:19851/devtools/info` | Device / server metadata |
|
|
118
|
-
|
|
119
|
-
### Driving the device
|
|
120
|
-
|
|
121
|
-
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.
|
|
122
|
-
|
|
123
|
-
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.
|
|
124
|
-
|
|
125
|
-
### Running real-device Automations from an agent
|
|
126
|
-
|
|
127
|
-
There is no `bricks devtools automation` subcommand. Use the DevTools runtime helpers exposed inside the app:
|
|
128
|
-
|
|
129
|
-
```bash
|
|
130
|
-
bricks devtools runtime eval -a <ip> -p 19851 --passcode <pc> "Object.getOwnPropertyNames(automation).sort()" -j
|
|
131
|
-
bricks devtools runtime eval -a <ip> -p 19851 --passcode <pc> "automation.list()" -j
|
|
132
|
-
bricks devtools runtime eval -a <ip> -p 19851 --passcode <pc> "automation.run('<TEST_id>', { updateScreenshot: false })" --await -j
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
`automation.run()` starts the device-side run and may return `null`; treat that as accepted, not as a pass/fail result. Wait for the run timeout/window, then verify completion through the app's own state and a screenshot. For app state, use live runtime reads such as:
|
|
136
|
-
|
|
137
|
-
```bash
|
|
138
|
-
bricks devtools runtime eval -a <ip> -p 19851 --passcode <pc> "JSON.stringify({ result: system.data.property('<S_xxxx>', '<resultAlias>')?.value })" -j
|
|
139
|
-
bricks devtools screenshot -a <ip> -p 19851 --passcode <pc> -o /tmp/device-automation.png
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
In CTOR Desktop sandboxed sessions, keep these as separate simple commands. Avoid multi-line shell scripts, `for` loops, brace expansion, and command substitution around `bricks devtools`; those can stay sandboxed and lose LAN/device access. After `bun update-app` or a device refresh, the DevTools socket may briefly drop, so wait and probe with one screenshot or one `runtime eval` before running the automation.
|
|
143
|
-
|
|
144
|
-
### Real-device side-effects warning
|
|
145
|
-
|
|
146
|
-
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.
|
|
147
|
-
|
|
148
|
-
## Path 3 — Remote debugging via BRICKS Controller (off-LAN)
|
|
149
|
-
|
|
150
|
-
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.
|
|
151
|
-
|
|
152
|
-
## Decision rule
|
|
153
|
-
|
|
154
|
-
```
|
|
155
|
-
default Path 1.
|
|
156
|
-
|
|
157
|
-
if deployment depends on:
|
|
158
|
-
physical orientation / DPI / touch HW / peripherals /
|
|
159
|
-
watchdog on real launcher / LocalSync / certified hardware
|
|
160
|
-
→ escalate to Path 2 before declaring done.
|
|
161
|
-
|
|
162
|
-
if brief touches payment, identity, peripherals, LocalSync
|
|
163
|
-
→ Path 2 is mandatory, not optional.
|
|
164
|
-
|
|
165
|
-
if user is off-LAN
|
|
166
|
-
→ Path 3 (out of scope here).
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
## What to actually verify (per shape)
|
|
170
|
-
|
|
171
|
-
### Static signage (single-canvas glance loop)
|
|
172
|
-
- Path 1 screenshot captures the loop frame.
|
|
173
|
-
- Watch one full rotation in `bun invoke-simulator` to see all queue items.
|
|
174
|
-
- Cut network mid-loop; confirm cached media plays.
|
|
175
|
-
- Path 2 only if the panel is OLED / has burn-in concerns or specific color profile.
|
|
176
|
-
|
|
177
|
-
### Multi-canvas state machine (kiosk)
|
|
178
|
-
- Path 1: Automation walking the happy path with `brick_press` + `wait_until_canvas_change` + `assert_property` + `match_screenshot` per Canvas.
|
|
179
|
-
- Cancel + inactivity reset paths verified as Automations.
|
|
180
|
-
- Watchdog reset: kill the runtime, restart, confirm boot Canvas resets transient flow Data.
|
|
181
|
-
- Path 2 mandatory if payment / identity is in the flow — fire a real test transaction on staging hardware.
|
|
182
|
-
|
|
183
|
-
### Subspace-driven composition
|
|
184
|
-
- Path 1: open the Subspace standalone if the preview supports it; verify in isolation.
|
|
185
|
-
- Embedded test: walk the host's flow; assert Outlets fire as expected via `wait_property_update`.
|
|
186
|
-
- Re-mount test: cause the host to re-bind the Subspace; confirm internal state resets.
|
|
187
|
-
|
|
188
|
-
### Generator-driven reactive
|
|
189
|
-
- Path 1: drive the source by writing to Data from the runtime (whatever CDP path the user prefers); observe Brick re-render.
|
|
190
|
-
- Throttle / firehose tests: write 100 updates rapidly; confirm the canvas doesn't choke (frame budget intact).
|
|
191
|
-
- Disconnect: simulate source disconnect; confirm UI surfaces stale state, not blank.
|
|
192
|
-
- Threshold transitions: cross every Switch boundary; confirm visual reaction.
|
|
193
|
-
- Path 2 mandatory if the source is a real peripheral — Electron cannot fake the timing or the failure modes.
|
|
194
|
-
|
|
195
|
-
### Multi-device LocalSync
|
|
196
|
-
- Path 2 mandatory. Two devices on the same LAN with DevTools on. Drive one, observe the other.
|
|
197
|
-
|
|
198
|
-
## Browser / runtime log discipline
|
|
199
|
-
|
|
200
|
-
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.
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: bricks-design
|
|
3
|
-
description: >-
|
|
4
|
-
Visual design discipline for Applications and Subspaces — type, palette, asset
|
|
5
|
-
acquisition, design language, system commitment, visual rhythm, brand. TRIGGER
|
|
6
|
-
for visual / aesthetic / system / style / brand-asset work even when named in
|
|
7
|
-
product terms — slideshow, pitch deck, explainer, kiosk, signage, menu board,
|
|
8
|
-
lobby, wayfinding, retail, museum, transit; translate or rebuild from Figma /
|
|
9
|
-
HTML / screenshot / website / PDF / brand book; vague creative briefs; branded
|
|
10
|
-
scenes; rework or audit of an existing Subspace's type / palette / motion /
|
|
11
|
-
rhythm. For end-to-end briefs invoke in parallel with bricks-ux (interaction /
|
|
12
|
-
flow layer). SKIP for pure usability / flow / accessibility audits (bricks-
|
|
13
|
-
ux), single-Brick or Generator template work (create-brick-or-generator),
|
|
14
|
-
debugging without design intent, or non-display deliverables. Encodes
|
|
15
|
-
architecture truths, performance guardrails, input-translation rules, visual
|
|
16
|
-
languages, Direction Advisor, Media Flow protocol; verification toolchain
|
|
17
|
-
lives in bricks-ctor.
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
# BRICKS Design
|
|
21
|
-
|
|
22
|
-
You are a BRICKS **visual designer**. Your output is the visual surface of a runnable Subspace — the type, palette, asset, motion vocabulary, rhythm, and system commitment that makes the work read as one designed thing. Interaction shape (flows, journeys, affordance, feedback, accessibility) is the companion `bricks-ux` skill's domain; the two run in parallel on most briefs.
|
|
23
|
-
|
|
24
|
-
Every visual decision is downstream of the deployment — hardware, scene, network, language, brand, peripherals, watchdog. Web habits (scroll, hover, modals-as-overlays-by-default, semantic links) do not transfer; surface them as tells when input arrives in those shapes.
|
|
25
|
-
|
|
26
|
-
The user-facing primitive is **Data** (legacy alias: Property Bank — kept in some internal action names like `PROPERTY_BANK`). Surface "Data" in your prose. Other primitives keep their names: Application, Subspace, Canvas, Brick, Generator, DataCalculation, Switch, Animation, Standby Transition, Media Flow, Automation.
|
|
27
|
-
|
|
28
|
-
## Priority #0 — Verify deployment context
|
|
29
|
-
|
|
30
|
-
Before any design exploration, confirm: **hardware** (size, resolution, orientation, touch, viewing distance), **scene** (where the screen lives, what the user does), **network** (always-on / intermittent / offline), **language(s)**, **brand**, **peripherals** (camera, BLE, MQTT, NFC, payment, printer, sensors), **watchdog / fleet management**. If any of the first five is missing, stop and ask in a single batch — improvising on hardware or scene is the most expensive mistake in BRICKS work.
|
|
31
|
-
|
|
32
|
-
## Priority #0.5 — Visually inspect every reference, in full
|
|
33
|
-
|
|
34
|
-
If the user supplies any reference material — a website URL, a docs site, a Figma link, an HTML project, a screenshot, an image, a PDF, a brand book, a video walkthrough, a competitor's product — you must **visually inspect every page, frame, and state of it**, not skim a text summary or rely on a markdown extraction. Translating from material you have not actually seen is the single fastest path to designs that miss obvious cues (layout rhythm, photography style, motion language, brand temperature) that no text description preserves.
|
|
35
|
-
|
|
36
|
-
Hard rule: a markdown extraction (e.g., `WebFetch`, an `llms.txt`, a `README.md`) is **not** visual inspection. It captures words and loses everything that makes the reference design-relevant. Use it only as a navigation aid — a list of pages to then visit visually.
|
|
37
|
-
|
|
38
|
-
How to inspect, by source type:
|
|
39
|
-
|
|
40
|
-
- **Website / docs site URL** — drive a browser automation tool (browser-MCP, Playwright/Puppeteer-style MCP server, `agent-browser`-equivalent skill, or any host-provided browser tool). Visit the home page, every primary navigation entry, every page the user explicitly named, and every page that looks like it carries the brand's visual signature (hero, product, gallery, customers). Capture a full-page screenshot of each. Then read each screenshot back via the host's image-reading capability so you actually *see* it. If no browser automation is available, ask the user for screenshots before proceeding.
|
|
41
|
-
- **Figma / design-tool link** — use a Figma-MCP / design-tool MCP if available to enumerate every frame and image-export each; otherwise ask the user for PNG exports of every frame. Inspect each image.
|
|
42
|
-
- **HTML project on disk** — serve and screenshot every route via a browser tool, the same way as a public URL. Don't infer visuals from the source HTML/CSS.
|
|
43
|
-
- **PDF / brand book / slide deck** — read every page via the host's PDF-reading capability (page-by-page if the document is long). Do not summarize from a text extraction.
|
|
44
|
-
- **Local images / screenshots** — read each one via the image-reading tool.
|
|
45
|
-
- **Video walkthrough** — ask the user to provide key-frame screenshots, or to describe each state explicitly. Do not claim to "watch" a video you cannot actually frame-step.
|
|
46
|
-
|
|
47
|
-
Coverage check before continuing: list — out loud, in your reply — every reference artifact and the count of pages / frames / images you actually saw. If anything is unseen, name the gap and ask. Translating from incomplete reference inspection is grounds for rework.
|
|
48
|
-
|
|
49
|
-
## Workflow spine
|
|
50
|
-
|
|
51
|
-
Pass-based delivery, not sprint-to-finished. Full discipline in [`references/workflow.md`](references/workflow.md) (ask-vs-build heuristic, batched question playbook by axis, five passes with checkpoints).
|
|
52
|
-
|
|
53
|
-
1. **Verify deployment context** (Priority #0) and branch on input shape:
|
|
54
|
-
- Vague brief → [`references/when-the-brief-is-vague.md`](references/when-the-brief-is-vague.md) (Direction Advisor — interaction archetype × visual language × Canvas-graph shape for sequenced work).
|
|
55
|
-
- Branded brief → [`references/when-the-brief-is-branded.md`](references/when-the-brief-is-branded.md) (Media Flow protocol).
|
|
56
|
-
- Figma / HTML / screenshot input → [`references/translating-inputs.md`](references/translating-inputs.md).
|
|
57
|
-
- Presentation / slideshow / intro / explainer / storyboard → [`references/presentation-and-slideshow.md`](references/presentation-and-slideshow.md) (Canvas-graph shape decision, hero continuity).
|
|
58
|
-
2. **Pass 0** — Declare the system as a comment block at the top of the Subspace file: type scale, palette, **spacing scale in grid units**, motion vocabulary, grid stance (lean / break / breathe), hero Brick ids. The grid substrate is given by the runtime (Truth #6); the design decisions sit on top.
|
|
59
|
-
3. **Pass 1 — Showcase Canvas lockdown.** Build one Canvas fully lit, verify, show the user. This is the cheapest moment to redirect; do not build the full Canvas graph before sign-off.
|
|
60
|
-
4. **Pass 2** — Build out the full Canvas graph with hero ids shared across Canvases (Truth #3 as narrative principle). Mid-review checkpoint partway through.
|
|
61
|
-
5. **Pass 3** — Polish: spacing-scale adherence, density rhythm, Standby Transition vocabulary consistent, multilingual fits.
|
|
62
|
-
6. **Variations**, if exploring options — three patterns ordered by token cost, default Pattern 1. See [`references/variations-and-tweaks.md`](references/variations-and-tweaks.md). Comparison surface is chat + source tree, not the Canvas.
|
|
63
|
-
7. **Pass 4** — Verification gate (below) + self-critique (5 dimensions + first-viewer rubric for sequenced work). Never declare done off a single screenshot.
|
|
64
|
-
|
|
65
|
-
## The 10 architecture truths
|
|
66
|
-
|
|
67
|
-
The load-bearing laws. Each is unpacked in [`references/architecture-truths.md`](references/architecture-truths.md).
|
|
68
|
-
|
|
69
|
-
1. **Canvas is a state, not a screen.** A Subspace is a state machine; Canvases are states; Brick events / Data changes are transitions. Treat Canvases as web pages and you'll fight the runtime.
|
|
70
|
-
2. **Data is the conduit for *dynamic* values.** Anything that varies at runtime (content, i18n, Generator inputs/outputs, Subspace boundaries, event payloads) flows through Data. Hardcoded values in genuinely-static, single-use Bricks are fine — convention is loose, not enforced. The rule kicks in the moment the value can change.
|
|
71
|
-
3. **Shared Brick ids across Canvases auto-tween.** Use the same Brick on Canvas A and Canvas B with different frames — the runtime animates position/size for free. This is the highest-leverage technique for a polished feel; rewriting per Canvas throws it away.
|
|
72
|
-
4. **Switches compare; Data Hit/Not-Hit only matches.** Canvas / Brick / Generator Switches support `==` `!=` `>` `<` `>=` `<=` against Data values (`SwitchCondData`). Data events `valueHit` / `valueNotHit` only support equal-match (`hit_equal`) or regex-match (`hit_regex`). Threshold-driven UI lives on Switches, not on Data event subscriptions. Don't confuse them.
|
|
73
|
-
5. **Generators are headless, async, event-driven.** Wire them via events; never as synchronous calls. Every chain needs a termination condition. Generators that hit hardware/network must not block the canvas thread.
|
|
74
|
-
6. **Frames are grid units.** Off-grid placement is legal but only ever intentional (overflow effects, anchor-at-origin tricks). It is never a nudge to escape the grid. Bricks fully outside the grid are auto-culled.
|
|
75
|
-
7. **Standby Transition is part of the design language.** Every visible Brick gets an entrance offset (`standbyMode` + `standbyOpacity` + `standbyDelay`); the runtime's auto-tween handles in-flight motion. Snap-cuts are reserved for emphasis (alarm states), never for routine navigation.
|
|
76
|
-
8. **Subspace is a typed module.** Inputs are call-by-value-on-host-change; outlets emit update + value-change events on the host. Extract a Subspace only when the same flow appears 2+ times or when the boundary scopes Data meaningfully — never as a "tidy up" tactic.
|
|
77
|
-
9. **DataCalculation is for derivation, not orchestration.** Inputs → outputs via DataCalculationScript or DataCalculationMap. Keep scripts pure by default; `enableAsync: true` (Promise / timers / async libs) and Map `FILE_*` commands are available when derivation genuinely needs them. Network calls, navigation, and DataCalc-triggers-DataCalc fanout belong in Event Action chains or Generators.
|
|
78
|
-
10. **No scroll, no overflow, no responsive reflow.** Frames are fixed; what doesn't fit doesn't show. Design within the Canvas; don't import web habits.
|
|
79
|
-
|
|
80
|
-
## Commit to a design language
|
|
81
|
-
|
|
82
|
-
A BRICKS Application that doesn't commit to a design language reads as generic regardless of how well it runs. After Direction Advisor (or directly, when the brief is concrete enough), pick a visual language from [`references/design-languages.md`](references/design-languages.md) — Swiss Editorial / Kenya Hara emptiness / Field.io motion poetics / Brutalist web / Y2K futurist-retro / etc. — and write its system declaration as a comment block at the top of the Subspace file. Every subsequent choice cites the block; adding a value not in the block requires updating the block first. That's what makes the system structural rather than aspirational.
|
|
83
|
-
|
|
84
|
-
The commitment principle: when unsure, do *more* of what defines the chosen language, not less. A style executed at 30% reads as hesitant; at 80% it reads as deliberate. Soften signature moves and you've abandoned the language for nowhere.
|
|
85
|
-
|
|
86
|
-
The picked language is orthogonal to the picked **interaction archetype** (glance / browse / interact / transact / monitor / dwell — see [`references/when-the-brief-is-vague.md`](references/when-the-brief-is-vague.md)). Together they define the work. Pick both deliberately; combine awkward pairings (transact + Sagmeister, monitor + Magazine editorial) only as a deliberate brand statement, not by accident.
|
|
87
|
-
|
|
88
|
-
## Pressable composition
|
|
89
|
-
|
|
90
|
-
Composite-button wiring (where `on_press` sits, which Bricks bypass) is an interaction concern — see the companion `bricks-ux` skill's `pressable-composition.md`. The visual-design responsibility here is making pressable affordance *visually distinct*: a tile that's pressable should not look identical to a tile that's decorative. Affordance reads through the visual language; the wiring lands the press.
|
|
91
|
-
|
|
92
|
-
## Performance & complexity guardrails
|
|
93
|
-
|
|
94
|
-
Two reference files cover the second-order rules. Read them when the design is non-trivial.
|
|
95
|
-
|
|
96
|
-
- [`references/performance.md`](references/performance.md) — throttle at the Generator boundary, bound Data history explicitly, `persistData: true` is for last-known-good and idempotency keys (not transient flow state), boot Canvas must render in < 1 s using only cached/persisted Data, `renderOutOfViewport: false` for legitimate off-grid Bricks, offline-first cache + queue + status-Data on every networked Generator. **Media bound through Media Flow is preloaded to the device and is offline-safe by default — image / video / Lottie / Rive / brand reel are not "offline risk" categories. The offline wrap is for Generators fetching dynamic runtime data, not for design-time media.**
|
|
97
|
-
- [`references/avoiding-complexity.md`](references/avoiding-complexity.md) — Subspace abuse (single-instance Subspaces are usually directories), Switch fanout (4+ on one node = state machine in disguise; promote to Canvases), DataCalc chains (orchestration in the wrong primitive), animation overuse (one orchestrated entrance > scattered micro-anims; `loop` only for attention draws), Canvas inflation (each Canvas is a state the user can be stuck in).
|
|
98
|
-
|
|
99
|
-
## Asset discipline
|
|
100
|
-
|
|
101
|
-
Brand work succeeds or fails on assets, not on colors. Logo, product photography, UI screenshots, scene photography, and motion assets are first-class — colors and fonts are auxiliary. Acquire them through the protocol in [`references/when-the-brief-is-branded.md`](references/when-the-brief-is-branded.md): five steps, the 5-10-2-8 quality bar with five named scoring dimensions, three fallback paths per asset category, and structural enforcement that Bricks reference Media Flow Data via DataLink rather than embed, redraw, or skip.
|
|
102
|
-
|
|
103
|
-
When an asset category genuinely cannot be acquired and the user has no plan to provide one, the priority is: stop and ask (always for logo) → compose the host environment's image / motion generators (canvas-design / imagen / generative MCP), brand-reference-anchored, scored at the same bar → labeled placeholder with the gap tracked in `brand-spec.md`. **This skill does not duplicate generative or composition skills — it composes them.** Where the host has none, surface the constraint to the user; don't silently degrade.
|
|
104
|
-
|
|
105
|
-
## Anti-slop, terse
|
|
106
|
-
|
|
107
|
-
Snap canvas transitions on routine navigation. Hardcoded *dynamic* strings (content, i18n) bypassing Data. Hover affordances on no-touch hardware. Sketch-drawn imitations of real brand assets. Aggregator-sourced logos shipped as final. Generated brand imagery without a real brand-reference anchor. Subspaces extracted for "neatness". Switch fanout standing in for state. DataCalc chains standing in for orchestration. Animation everywhere. Stock-photo grounds behind real product photography. CSS-style scroll containers.
|
|
108
|
-
|
|
109
|
-
## Variations
|
|
110
|
-
|
|
111
|
-
When exploring options for the user to choose from, default 3, differentiated on a real axis (visual language / interaction archetype / Canvas-graph shape / motion language / content rhythm). Three colour-swap variants is not three variants.
|
|
112
|
-
|
|
113
|
-
**The comparison surface is chat + source tree, never the Canvas.** No in-Canvas palette pickers, no "choose your theme" toggles, no demo-mode switches left in production. Default to Pattern 1 (Data-preset variations — one Canvas tree, flat preset map, single-line preset switch, screenshot grid in chat). Escalate to shared module or separate Subspaces only when the variation can't be expressed by the cheaper pattern. Full protocol with token-saving discipline and knob filter in [`references/variations-and-tweaks.md`](references/variations-and-tweaks.md).
|
|
114
|
-
|
|
115
|
-
Ship a one-paragraph trade-off note alongside so the user can pick or blend with full context.
|
|
116
|
-
|
|
117
|
-
## Verification gate
|
|
118
|
-
|
|
119
|
-
**Definition of done — non-negotiable.** Before declaring a design complete, every one of the following must be true:
|
|
120
|
-
|
|
121
|
-
1. The source compiles cleanly.
|
|
122
|
-
2. Every Canvas in the deliverable has a rendered screenshot at the target hardware resolution and orientation. Cover every reachable state — Canvases gated behind events get reached by running an Automation.
|
|
123
|
-
3. The agent has **viewed** each of those screenshots back through the host's image-reading capability — not just saved them. The model that designed the Canvas must also have seen the rendered result.
|
|
124
|
-
4. If the user supplied any reference material (Figma / website / HTML / screenshot / PDF / brand book), a side-by-side visual comparison has been done between each Canvas screenshot and the corresponding reference, with a short delta report listing:
|
|
125
|
-
- What matches.
|
|
126
|
-
- What intentionally diverges, and why (deployment constraint, system commitment, BRICKS-runtime limitation).
|
|
127
|
-
- What unintentionally diverges, and how you will fix it.
|
|
128
|
-
5. The verification path appropriate to the deployment has executed (Path 1 Electron preview by default; Path 2 on-device DevTools when the deployment depends on real hardware, payment, identity capture, peripherals, or LocalSync).
|
|
129
|
-
6. The browser / runtime console is clean — no 404s, no Data-key-undefined warnings, no Generator init failures.
|
|
130
|
-
|
|
131
|
-
A single hero-Canvas screenshot is **not** done. A "looks roughly like the reference" handwave is **not** done. A claim of done without screenshots in evidence is **not** done. If you have not produced and reviewed a screenshot of every Canvas, you are still mid-iteration and must say so explicitly to the user.
|
|
132
|
-
|
|
133
|
-
**Self-critique pass before declaring done** — every Canvas scored on 5 dimensions (system commitment / visual hierarchy / craft / functional fit / originality), anti-slop top-10 swept clean, < 8 scores either fixed or surfaced as accepted trade-offs. See [`references/design-critique.md`](references/design-critique.md). Verification proves it runs; critique proves it's good — both required.
|
|
134
|
-
|
|
135
|
-
For the toolchain itself — `compile` / `simulator` MCP usage, `bun invoke-simulator` flags, Project Automation cases, on-device DevTools setup, the Path 1/2/3 decision rule, and per-deployment-shape verification checklists — see the `bricks-ctor` skill's `rules/verification-toolchain.md`.
|
|
136
|
-
|
|
137
|
-
## Boundaries
|
|
138
|
-
|
|
139
|
-
- Do not recreate copyrighted UIs. Build an original design that respects the IP.
|
|
140
|
-
- Do not invent brand assets. Use a labeled placeholder Brick + tracked gap list.
|
|
141
|
-
- Do not bypass Data for dynamic values.
|
|
142
|
-
- Do not carry web-frame habits across (scroll, hover, semantic links, modals-by-default, responsive reflow).
|
|
143
|
-
- Treat real-device runs as side-effecting — peripherals fire for real, payment terminals charge for real, MQTT/BLE may broadcast on shared topics. Use a staging device for verification cycles.
|
|
144
|
-
|
|
145
|
-
## Companion skill: `bricks-ux`
|
|
146
|
-
|
|
147
|
-
Interaction / flow / journey / affordance / feedback / recovery / accessibility / multilingual concerns live in `bricks-ux`. For end-to-end briefs ("design a kiosk for X", "build a presentation introducing Y") both skills invoke in parallel — `bricks-design` carries the visual layer, `bricks-ux` carries the interaction layer. Cross-references in this skill point to `bricks-ux/references/...` where the interaction discipline matters.
|
|
148
|
-
|
|
149
|
-
## Reference index
|
|
150
|
-
|
|
151
|
-
| When you need to... | Read |
|
|
152
|
-
|---|---|
|
|
153
|
-
| Decide when to ask vs build; pace the work across passes | [`references/workflow.md`](references/workflow.md) |
|
|
154
|
-
| Deepen any of the 10 truths | [`references/architecture-truths.md`](references/architecture-truths.md) |
|
|
155
|
-
| Tune for performance / offline | [`references/performance.md`](references/performance.md) |
|
|
156
|
-
| Resist over-engineering | [`references/avoiding-complexity.md`](references/avoiding-complexity.md) |
|
|
157
|
-
| Translate a Figma / HTML / screenshot | [`references/translating-inputs.md`](references/translating-inputs.md) |
|
|
158
|
-
| Pick and commit to a design language | [`references/design-languages.md`](references/design-languages.md) |
|
|
159
|
-
| Design a presentation / pitch deck / intro / explainer / slideshow (visual rhythm + hero continuity) | [`references/presentation-and-slideshow.md`](references/presentation-and-slideshow.md) |
|
|
160
|
-
| Offer variations / pick what becomes a Data knob | [`references/variations-and-tweaks.md`](references/variations-and-tweaks.md) |
|
|
161
|
-
| Self-critique on the visual dimensions | [`references/design-critique.md`](references/design-critique.md) |
|
|
162
|
-
| Verify a design before shipping | `bricks-ctor/rules/verification-toolchain.md` (companion skill) |
|
|
163
|
-
| Propose visual directions for a vague brief | [`references/when-the-brief-is-vague.md`](references/when-the-brief-is-vague.md) |
|
|
164
|
-
| Acquire and bind brand assets | [`references/when-the-brief-is-branded.md`](references/when-the-brief-is-branded.md) |
|
|
165
|
-
| Compose a button so taps land where intended | `bricks-ux/references/pressable-composition.md` (companion skill) |
|
|
166
|
-
| Walk the universal interaction journey | `bricks-ux/references/user-journey.md` (companion skill) |
|
|
167
|
-
| Apply interaction-archetype rule sets | `bricks-ux/references/interaction-archetypes.md` (companion skill) |
|
|
168
|
-
| Design idle / loading / empty / error / boot / maintenance states | `bricks-ux/references/flow-states.md` (companion skill) |
|
|
169
|
-
| Design monitoring / dashboard UX | `bricks-ux/references/monitoring-screens.md` (companion skill) |
|
|
170
|
-
| Accessibility floors at deployment-relative thresholds | `bricks-ux/references/accessibility.md` (companion skill) |
|
|
171
|
-
| Tiered UX critique | `bricks-ux/references/ux-critique.md` (companion skill) |
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
# Architecture Truths
|
|
2
|
-
|
|
3
|
-
The 10 load-bearing laws of BRICKS design. Each one lists the truth, the runtime semantic that makes it true, and the failure mode it prevents. Re-read this when something feels arbitrary — usually one of the truths settles it.
|
|
4
|
-
|
|
5
|
-
## 1. Canvas is a state, not a screen
|
|
6
|
-
|
|
7
|
-
A Subspace is implicitly a state machine: Canvases are states, Brick events / Data changes are transitions, the visible Canvas is the current state. The runtime auto-tweens shared Bricks across Canvas changes, so transitions *are* the design language.
|
|
8
|
-
|
|
9
|
-
**Failure mode:** treating each Canvas as an independent web page. Symptoms — every Canvas redraws all chrome from scratch (no shared Bricks), transitions feel like hard cuts, navigation logic gets bolted onto Bricks instead of expressed as Canvas changes.
|
|
10
|
-
|
|
11
|
-
**Tell:** if you have one Canvas with `if-then-else` Switches toggling Brick visibility based on a `flowStep` Data, you're emulating a state machine inside one Canvas. Promote to N Canvases.
|
|
12
|
-
|
|
13
|
-
## 2. Data is the conduit for dynamic values
|
|
14
|
-
|
|
15
|
-
Anything that varies at runtime — content (text, images, URLs), i18n strings, Generator inputs/outputs, Subspace Props/Outlets, event payloads, theme tokens you want to swap — flows through Data.
|
|
16
|
-
|
|
17
|
-
Hardcoded values in genuinely-static, single-use Bricks are *fine*. The convention is loose, not enforced. A decorative Rect's `backgroundColor` set to a literal hex, a Text Brick that says `"OK"` as a confirmation label that will never change — both acceptable.
|
|
18
|
-
|
|
19
|
-
**The rule kicks in the moment the value can change.** A `"Welcome"` heading that should later support Chinese must live in Data from day one; retrofitting i18n once the design is complete is far more expensive than naming the Data key now.
|
|
20
|
-
|
|
21
|
-
**Failure mode:** Bricks coupled directly (Brick A reads Brick B's prop), Generator A invoking Generator B by name, hardcoded URLs that should be config, hardcoded English where i18n is foreseeable.
|
|
22
|
-
|
|
23
|
-
**Misread to avoid:** "dynamic values flow through Data" does not mean "media is dynamic and therefore an offline risk". Media bound through Media Flow (image / video / Lottie / Rive / brand reel via Data of `kind: media-resource-*` with `preload` metadata) is preloaded to the device at boot, integrity-verified, and served from local storage. It works offline. The offline-first concern is about Generators fetching runtime data (menus, sensor readings, LLM output, server-fed inventory), not design-time media. Don't strip rich visuals "to be safe for offline" — that's a category error.
|
|
24
|
-
|
|
25
|
-
## 3. Shared Brick ids across Canvases auto-tween
|
|
26
|
-
|
|
27
|
-
If a Brick has the same id on Canvas A and Canvas B with different `frame`s, the runtime animates `x`/`y`/`width`/`height` between the two when the Canvas changes. New Bricks enter via Standby Transition; departing Bricks exit symmetrically.
|
|
28
|
-
|
|
29
|
-
**Use it for** brand chrome (logo, header), progress indicators, persistent CTAs, status footers — anything continuous across the flow.
|
|
30
|
-
|
|
31
|
-
**Narrative principle, not just a runtime fact.** Pick one or two **hero Bricks** (logo lockup, headline word, product silhouette, brand chrome). Give them the same id across every Canvas they appear on. Each Canvas is then a *transformation* of the hero's state, not a new set of elements appearing and disappearing. Auxiliary Bricks (content that only matters to one Canvas) scope to that Canvas via Standby Transition. Heroes are the thread that makes the sequence feel like one designed thing — especially for presentation / slideshow / narrative work (see [`presentation-and-slideshow.md`](presentation-and-slideshow.md)).
|
|
32
|
-
|
|
33
|
-
**Failure mode:** every Brick is unique to its Canvas. The Application loses continuity and even with entrance/exit animations configured, every transition feels like a hard cut. This is the single biggest difference between a polished and an amateur BRICKS Application — and the difference between "narrated PowerPoint" and a designed presentation.
|
|
34
|
-
|
|
35
|
-
## 4. Switches compare; Data Hit/Not-Hit only matches
|
|
36
|
-
|
|
37
|
-
Two distinct condition systems exist; do not confuse them.
|
|
38
|
-
|
|
39
|
-
**Switches** (`SwitchDef` on Canvas / Brick / Generator) support comparison operators against `SwitchCondData`:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
method: '==' | '!=' | '>' | '<' | '>=' | '<='
|
|
43
|
-
cond: SwitchCondData | SwitchCondInnerStateCurrentCanvas | SwitchCondInnerStateOutlet
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Use Switches for threshold-driven UI: hide a Brick when `flowProgress < 1`, switch a tile's color when `value >= threshold`, show a chrome variant when the current Canvas has a specific id.
|
|
47
|
-
|
|
48
|
-
**Data events** `valueHit` / `valueNotHit` only fire on equal-match (`hit_equal: any`) or regex-match (`hit_regex: string`). They do not support `>` `<` `>=` `<=`. Use them for state notifications: "alarm.active became true", "code matched the pin regex".
|
|
49
|
-
|
|
50
|
-
**Failure mode:** trying to express `value > threshold` via a Data Hit subscription. It will not fire as you expect. Move the comparison to a Switch.
|
|
51
|
-
|
|
52
|
-
## 5. Generators are headless, async, event-driven
|
|
53
|
-
|
|
54
|
-
Generators have no visible surface. They take inputs from Data, produce outputs to Data, and are triggered by events. They emit events. They run asynchronously against the canvas thread.
|
|
55
|
-
|
|
56
|
-
**Wire them via events**, never as synchronous calls. The canonical chain: an event triggers a System / Generator Action; the Generator runs; its outlet writes to Data; downstream Data event subscribers (Bricks, other Generators, canvas-transition Actions) react.
|
|
57
|
-
|
|
58
|
-
**Every chain needs a termination condition.** Idempotency keys, guarded conditions, hard-stop counters, retry caps. Surface termination in a comment or a Switch. A Generator chain that fans out without a stop is a denial-of-service against your own Application.
|
|
59
|
-
|
|
60
|
-
**Failure mode:** synchronous "fetch then render" patterns where the canvas waits on a Generator. The runtime can render *something* immediately and let the Generator's outlet update later — design for that.
|
|
61
|
-
|
|
62
|
-
## 6. Frames are grid units
|
|
63
|
-
|
|
64
|
-
Frames (`x`, `y`, `width`, `height`) are integers in the configured grid (`layout.width` × `layout.height`; default 96 × 54 in many projects, but confirm against the actual Subspace). The runtime maps grid units to physical pixels at runtime based on hardware resolution.
|
|
65
|
-
|
|
66
|
-
Off-grid placement is *legal*: position `(-2, -3)` size `(4, 6)` puts the Brick's center at the screen origin — a real composition technique. It is *slop* when used to nudge a Brick by a non-grid amount because the grid felt restrictive.
|
|
67
|
-
|
|
68
|
-
**Bricks fully outside the grid are auto-culled** for performance. Don't rely on that as a hide mechanism — use Switches or `hidden`.
|
|
69
|
-
|
|
70
|
-
**Failure mode:** copy-pasting pixel values from a Figma render into frame fields. Translate to grid units instead.
|
|
71
|
-
|
|
72
|
-
## 7. Standby Transition is the design language
|
|
73
|
-
|
|
74
|
-
Every visible Brick item on a Canvas can declare a Standby Transition (`standbyMode`, `standbyOpacity`, `standbyDelay`, `standbyDelayRandom`, `standbyEasing`, per-property easing on x/y/width/height/opacity). On Canvas enter, the runtime animates the Brick from its standby pose to its placed pose.
|
|
75
|
-
|
|
76
|
-
Combined with shared-Brick auto-tweens (Truth #3), this is the entire transition vocabulary of a BRICKS Application. Master it.
|
|
77
|
-
|
|
78
|
-
**Snap-cuts** (no Standby) are reserved for emphasis — alarm states, error overlays, deliberate hard moments. Routine navigation that snap-cuts feels broken.
|
|
79
|
-
|
|
80
|
-
**Failure mode:** every Brick gets the same fade-in. Boring is also slop. Stagger delays, vary directions per Brick role, use the runtime's `standbyDelayRandom` for natural-looking item lists.
|
|
81
|
-
|
|
82
|
-
## 8. Subspace is a typed module
|
|
83
|
-
|
|
84
|
-
A Subspace is a self-contained mini-Application: own Canvases, own Bricks, own Generators, own Data, own DataCalculation. It binds to a host via:
|
|
85
|
-
|
|
86
|
-
- **Inputs** (Props): host-provided Data values copied into Subspace Data on host change (call-by-value at the boundary). Triggers the Subspace's `valueChange` event internally.
|
|
87
|
-
- **Outlets**: Subspace-emitted values that fire `outlet update` (always) and `outlet value change` (on diff) events in the host.
|
|
88
|
-
- **Actions / Events**: explicit host-callable actions and Subspace-emitted events.
|
|
89
|
-
|
|
90
|
-
**Extract a Subspace only when**:
|
|
91
|
-
- The same flow appears 2+ times (login, OTP, payment, language picker, confirm dialog).
|
|
92
|
-
- The boundary scopes Data meaningfully (a sub-flow with its own complete state independent of the host).
|
|
93
|
-
- A Module distribution is intended (Subspace is also the unit of reuse via the BRICKS Module system).
|
|
94
|
-
|
|
95
|
-
**Do not extract** for "tidy up". Single-instance, single-purpose Subspaces are directories, not modules; they make the design harder to reason about.
|
|
96
|
-
|
|
97
|
-
**Failure mode:** Subspaces with leaky contracts (every host Data exposed as a Prop). Tighten the contract; if you can't, the boundary is wrong.
|
|
98
|
-
|
|
99
|
-
## 9. DataCalculation is for derivation, not orchestration
|
|
100
|
-
|
|
101
|
-
Two flavours:
|
|
102
|
-
|
|
103
|
-
- **`DataCalculationScript`** — a sandboxed JS function with named inputs / outputs. Default is sync + pure; opt into async with `enableAsync: true`, which unlocks `Promise`, `setTimeout` / `setInterval` / `setImmediate`, `requestAnimationFrame`, and the full lodash surface (`debounce`, `delay`, `defer`). Bundled libraries include lodash, voca, mathjs, chroma, moment, json5, qs, url, bytes, ms, base45, iconv, nanoid, md5, crypto-browserify, jsrsasign (JWS), cose-js, fflate (gzip/zlib), cbor, fs (limited; no download/upload), officeparser, turndown, opencc-js, toon-format. Runs on Hermes (Android) and JavaScriptCore (iOS) — keep that in mind for engine pitfalls.
|
|
104
|
-
- **`DataCalculationMap`** — a node-graph of `DataCommand`s spanning these categories: `COLLECTION`, `COLOR`, `CONSTANT`, `DATETIME`, `FILE` (file-system ops: `READ` / `WRITE` / `APPEND` / `MKDIR` / `COPY_FILE` / `MOVE_FILE` / `UNLINK` / `EXISTS` / `STAT` / etc.), `ITERATEE`, `LOGICTYPE`, `MATH`, `OBJECT`, `SANDBOX` (`SANDBOX_RUN_JAVASCRIPT` runs a script node inside the graph), `STRING`.
|
|
105
|
-
|
|
106
|
-
Derivation is the intent. Purity is a strong default and the right framing for the common case, but it is a best practice — not a hard runtime restriction. `enableAsync` and `FILE_*` exist because some derivation work (document parsing, decompression, signing, reading a cached file) genuinely needs them.
|
|
107
|
-
|
|
108
|
-
**Use it for**:
|
|
109
|
-
- Format conversion (date → human-readable, currency → localized string).
|
|
110
|
-
- Combining Data values into a derived display value.
|
|
111
|
-
- Reductions / iterations over a collection.
|
|
112
|
-
- Boolean conditions feeding a Switch.
|
|
113
|
-
- Async derivation pipelines: decode → decompress → parse → verify (cbor, fflate, cose-js, officeparser, turndown).
|
|
114
|
-
- Reading cached files written earlier in the flow (Map `FILE_*` commands or Script `fs`).
|
|
115
|
-
|
|
116
|
-
**Triggering**: `triggerMode: 'auto'` re-runs on input change (watch for circular dependencies); `'manual'` only runs on `PROPERTY_BANK_COMMAND` action.
|
|
117
|
-
|
|
118
|
-
**Do not use** for orchestration, navigation, network calls (no `fetch` / XHR in the sandbox — that's a Generator's job), or anything that should be in an Event Action chain or a Generator. A DataCalc that triggers DataCalc that triggers DataCalc is an orchestration system in the wrong primitive — promote to event chains. `enableAsync` and `FILE_*` are tools for derivation, not a licence to smuggle flow control into the calc layer.
|
|
119
|
-
|
|
120
|
-
**Failure mode:** spinning up a Generator just to do a string concat or unit conversion. That's a DataCalc job; the inverse misuse is just as common.
|
|
121
|
-
|
|
122
|
-
## 10. No scroll, no overflow, no responsive reflow
|
|
123
|
-
|
|
124
|
-
Subspace `layout` is fixed. Frames are fixed. There is no document flow, no `overflow: scroll`, no media-query reflow. What doesn't fit, doesn't show.
|
|
125
|
-
|
|
126
|
-
**Implications**:
|
|
127
|
-
- Long content lists → `Items` Brick (interactive virtualized list) or `Slideshow` Brick (timed rotation) or paginate across Canvases.
|
|
128
|
-
- Long forms → Canvas per question, not a scrollable form.
|
|
129
|
-
- Modal dialogs → Subspace overlay or Switch-driven Brick reveal — not a popup primitive.
|
|
130
|
-
- Different orientations → different Subspaces with different `layout`s, not a single design that "responds".
|
|
131
|
-
|
|
132
|
-
**Failure mode:** importing a long Figma artboard verbatim, expecting BRICKS to scroll the overflow. Redesign the information architecture; the runtime will not save you.
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# Avoiding Complexity
|
|
2
|
-
|
|
3
|
-
The "designer ego" guardrails. Each one names a specific over-engineering pattern, the symptom that exposes it, and the simpler primitive it should collapse into. When in doubt, delete.
|
|
4
|
-
|
|
5
|
-
## Subspace abuse
|
|
6
|
-
|
|
7
|
-
A Subspace is a typed module — own Canvases, own Data, own Generators, own contract. It earns its complexity only when it's reused, when it scopes a non-trivial Data boundary, or when it's a distributed Module.
|
|
8
|
-
|
|
9
|
-
**Symptoms of abuse**:
|
|
10
|
-
- Single-instance Subspace whose Props are "everything in the host's Data" — not a module, a leaky directory.
|
|
11
|
-
- Subspace extracted to "tidy up" a single Canvas with 8 Bricks — the cleanup made the design harder to reason about because state now crosses a boundary.
|
|
12
|
-
- Nesting > 2 Subspaces deep — the abstraction is wrong; flatten.
|
|
13
|
-
|
|
14
|
-
**Collapse rule**: if the Subspace appears once and its Props/Outlets cover most of its Data, inline it back into the host.
|
|
15
|
-
|
|
16
|
-
## Switch fanout
|
|
17
|
-
|
|
18
|
-
Switches are powerful — they let one Brick or Canvas have several conditional poses. They become slop when used to express what should be N Canvases.
|
|
19
|
-
|
|
20
|
-
**Symptoms**:
|
|
21
|
-
- 4+ Switches on one Canvas, each gating a different subset of Bricks based on a `flowStep` Data.
|
|
22
|
-
- Switches that toggle Brick `hidden` based on the same `flowStep` value — you've hand-rolled a state machine inside one Canvas.
|
|
23
|
-
- Switch conditions referencing Outlets from a Subspace just for navigation logic.
|
|
24
|
-
|
|
25
|
-
**Collapse rule**: if the Switches partition the Canvas into more than 2 visual states gated by the same Data, promote each state to its own Canvas. Use the runtime's auto-tween of shared chrome (Truth #3) to keep continuity.
|
|
26
|
-
|
|
27
|
-
## DataCalculation chains
|
|
28
|
-
|
|
29
|
-
DataCalc is for derivation. A single calc that produces a derived value is healthy. A calc whose output triggers another calc whose output triggers another is orchestration smuggled into the wrong primitive.
|
|
30
|
-
|
|
31
|
-
**Symptoms**:
|
|
32
|
-
- DataCalc A → Data X → DataCalc B → Data Y → DataCalc C → Data Z, all `triggerMode: 'auto'`.
|
|
33
|
-
- Calcs whose names sound like verbs ("submitForm", "validateInput", "navigateNext") instead of nouns ("formattedDate", "scoreSum", "displayLabel").
|
|
34
|
-
- Circular dependency warnings or fired-multiple-times-per-update behaviour.
|
|
35
|
-
|
|
36
|
-
**Collapse rule**: derivation lives in calcs; the *flow* connecting derivations to user-visible effects lives in Event Action chains and Generators. If a calc has a side effect or triggers navigation, it shouldn't be a calc.
|
|
37
|
-
|
|
38
|
-
## Animation everywhere
|
|
39
|
-
|
|
40
|
-
Standby Transitions are part of the design language (Truth #7). `loop` animations are an emphasis tool. Reaching for animation on every Brick on every state change is noise, not polish.
|
|
41
|
-
|
|
42
|
-
**Symptoms**:
|
|
43
|
-
- Every Brick on every Canvas has a Standby spec with the same easing and duration — uniform motion is no motion.
|
|
44
|
-
- 5+ `runType: 'loop'` animations idling on a Canvas.
|
|
45
|
-
- Animations that fight each other (a parent Brick scaling while children translate against the scale).
|
|
46
|
-
|
|
47
|
-
**Collapse rule**: vary motion intentionally — stagger Standby delays per Brick role, reserve loop for genuine attention draws, use shared-Brick auto-tween instead of separate exit + entrance animations for chrome that persists.
|
|
48
|
-
|
|
49
|
-
## Canvas inflation
|
|
50
|
-
|
|
51
|
-
Each Canvas is a state. Each state is a place the user can be stuck. More Canvases is rarely better UX.
|
|
52
|
-
|
|
53
|
-
**Symptoms**:
|
|
54
|
-
- Canvases with one Brick and one event chain that immediately CHANGE_CANVAS to the next — these are state machine steps that don't deserve a Canvas.
|
|
55
|
-
- Canvases that exist only to "loadingly transition" — that's what Standby and shared-Brick tweens are for.
|
|
56
|
-
- Canvases for every locale / every theme variant — variants belong in Switches or Data-bound props, not parallel Canvases.
|
|
57
|
-
|
|
58
|
-
**Collapse rule**: a Canvas earns its existence by being a stable state the user observes for at least a moment. Transitional / loading / variant-only Canvases should fold into their neighbours.
|
|
59
|
-
|
|
60
|
-
## Generator orchestration smell
|
|
61
|
-
|
|
62
|
-
Generators are I/O units triggered by events. Generators invoking other Generators directly (via name in an Action chain that runs synchronously) is orchestration smell.
|
|
63
|
-
|
|
64
|
-
**Symptoms**:
|
|
65
|
-
- Long Action chains with `waitAsync: true` chaining 4+ Generator calls.
|
|
66
|
-
- A Generator whose only job is to call another Generator and wait.
|
|
67
|
-
- Two Generators reading and writing the same Data inside one event chain.
|
|
68
|
-
|
|
69
|
-
**Collapse rule**: split the chain at Data boundaries. Generator A writes its outlet → Data fires `valueChange` → that event chain triggers Generator B. Each piece is independently inspectable, retryable, and cacheable.
|
|
70
|
-
|
|
71
|
-
## Module overreach
|
|
72
|
-
|
|
73
|
-
The BRICKS Module system lets a Subspace be packaged with version metadata and dependency requirements (`Subspace.module`). It is a real distribution mechanism — and like any package boundary, it has a maintenance cost.
|
|
74
|
-
|
|
75
|
-
**Symptoms**:
|
|
76
|
-
- Modularizing a Subspace that's only used in one Application.
|
|
77
|
-
- Modules whose contract changes every version because the host keeps adding Props.
|
|
78
|
-
- Bumping a Module version for purely cosmetic edits.
|
|
79
|
-
|
|
80
|
-
**Collapse rule**: keep Subspaces local until at least the second consumer asks for them. Versioned modules are for genuinely shared building blocks (login, payment, OTP, language picker) maintained by someone who treats them as a product.
|
|
81
|
-
|
|
82
|
-
## "Let's make it dynamic" overreach
|
|
83
|
-
|
|
84
|
-
Truth #2 says dynamic values flow through Data. The inverse failure is making everything dynamic when it doesn't need to be — exposing every color, every text, every layout dimension as Data "in case we want to change it later".
|
|
85
|
-
|
|
86
|
-
**Symptoms**:
|
|
87
|
-
- Subspace with 40 Data entries, half of them never read by a Generator and never written by anything but a default value.
|
|
88
|
-
- Theme tokens exposed as Data even though the design ships with one theme.
|
|
89
|
-
- A Generator whose job is to "set the title" of a Brick that always says the same thing.
|
|
90
|
-
|
|
91
|
-
**Collapse rule**: Data is the conduit for *currently dynamic* values. If a value is genuinely static and single-use, hardcode it. The cost of converting later is low; the cost of carrying inert Data forever is real.
|