Skip to content

Commit f5aa82c

Browse files
committed
merge: origin/dev (with 047 dashboard kill) into cloud/issues-048-merge
Brings in the full dashboard refactor (PR #2239): - DashboardManager is now cloud-internal (no external mini app) - SYSTEM_DASHBOARD_PACKAGE_NAME removed, replaced by OS_PACKAGE_NAME - Model-aware display profiles (G1, G2, Z100, Nex) - Stacked layout for narrow displays (Z100/Mach1) - Header column alignment fix (worst-case token measurement) - DEPRECATED_APPS blocklist for old dashboard app - Weather at 50% display midpoint Also fixed: - China deploy: Dockerfile.livekit → Dockerfile.porter (file didn't exist) - China deploy: removed SYSTEM_DASHBOARD_PACKAGE_NAME env var - docker-compose.porter.local.yml: same Dockerfile fix All 5 packages build clean (bun run ci).
2 parents 7101767 + eb97614 commit f5aa82c

40 files changed

+3852
-1617
lines changed

.github/workflows/china-deployment-dev.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ jobs:
3535
value: "production"
3636
- name: PORT
3737
value: "80"
38-
- name: SYSTEM_DASHBOARD_PACKAGE_NAME
39-
value: "system.augmentos.dashboard"
4038
- name: CLOUD_VERSION
4139
value: "2.1.2"
4240
- name: ADMIN_EMAILS
@@ -154,7 +152,7 @@ jobs:
154152
acr-vpc-domain: "mentra-acr-cnsz-a-registry-vpc.cn-shenzhen.cr.aliyuncs.com"
155153
acr-public-domain: "mentra-acr-cnsz-a-registry.cn-shenzhen.cr.aliyuncs.com"
156154
docker-context: "./cloud"
157-
dockerfile: "./cloud/docker/Dockerfile.livekit"
155+
dockerfile: "./cloud/docker/Dockerfile.porter"
158156
image-tag: ${{ steps.vars.outputs.sha_short }}
159157
min-instances: 1
160158
max-instances: 2

.github/workflows/porter-debug.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,7 @@ on:
44
workflow_dispatch: # Manual trigger fallback
55
push:
66
branches:
7-
- cloud/issues-048
87
- cloud/issues-048-merge
9-
- cloud/issues-044
10-
- new-context-soniox
11-
- cloud/044-ci-build-audit
12-
- hotfix/cloud-observability
13-
- hotfix/crash-diagnostics
14-
- cloud/062-mongodb-audit
15-
- hotfix/graceful-shutdown
16-
- hotfix/remove-forced-gc-add-livez
178
paths:
189
- "cloud/**"
1910
- ".github/workflows/porter-debug.yml"

cloud/.architecture/dashboard.md

Lines changed: 531 additions & 0 deletions
Large diffs are not rendered by default.

cloud/bun.lock

Lines changed: 324 additions & 439 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cloud/docker-compose.porter.local.yml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ services:
33
image: augmentos-cloud:porter
44
build:
55
context: .
6-
dockerfile: ./docker/Dockerfile.livekit
6+
dockerfile: ./docker/Dockerfile.porter
77
command: ./start.sh
88
environment:
99
HOST: 0.0.0.0
@@ -19,15 +19,7 @@ services:
1919
- "8002:80" # Cloud (Bun)
2020
- "8080:8080" # Go bridge
2121
healthcheck:
22-
test:
23-
[
24-
"CMD",
25-
"wget",
26-
"--no-verbose",
27-
"--tries=1",
28-
"--spider",
29-
"http://localhost:80/health",
30-
]
22+
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:80/health"]
3123
interval: 30s
3224
timeout: 5s
3325
retries: 3

cloud/issues/039-sdk-v3-api-surface/v2-v3-api-map.md

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,14 +260,56 @@ Timezone is resolved from: user setting (`userTimezone`) → GPS-derived timezon
260260

261261
`session.display` integrates with `@mentra/display-utils` automatically. The session knows the device profile (G1, Nex, etc.) — developers don't need to manually create toolkits or pick profiles.
262262

263+
### Two-layer wrapping model
264+
265+
Text wrapping in MentraOS happens at two independent layers with different responsibilities:
266+
267+
**Layer 1 — SDK (`session.display.showText`)**: formats for readability.
268+
269+
- Default break mode: **`"word"`** — wraps at word boundaries, hyphenates only when a single word exceeds the line width
270+
- This is what developers expect. `showText("This is a long sentence")` produces readable word-wrapped output
271+
- Developer can override with `{ breakMode: "character" }` for dense data / maximum utilisation
272+
273+
**Layer 2 — Mobile `DisplayProcessor`**: safety net for physical fit.
274+
275+
- Default break mode: **`"character-no-hyphen"`** — breaks mid-character without hyphen only when a line is too wide
276+
- Purpose: ensure text physically fits on the display without changing the developer's intended formatting
277+
- Preserves explicit `\n` breaks and pre-formatted structure
278+
- When the SDK wraps first (layer 1), layer 2 becomes a no-op — lines already fit
279+
280+
**Why the defaults differ:**
281+
282+
The `DisplayProcessor`'s `"character-no-hyphen"` is intentionally conservative — it runs on every display event regardless of where it came from (SDK apps, system services, old clients). Changing it to `"word"` would re-flow text that a developer deliberately structured, potentially breaking their layout.
283+
284+
The SDK's `"word"` default is correct for the common developer case: `showText("raw unformatted string")`. The developer is handing the SDK a raw string and expecting it to handle line breaks sensibly.
285+
286+
If a developer pre-formats their text with explicit `\n` breaks and passes it as `string[]` (array), the SDK sends it as-is — skipping layer 1 wrapping entirely — and layer 2 just ensures no line overflows.
287+
288+
```
289+
Developer calls showText("Some long sentence...")
290+
→ SDK: word-wrap → ["Some long", "sentence..."] ← readable
291+
→ Mobile: character-no-hyphen safety net → no-op ← already fits
292+
293+
Developer calls showText(["Pre-formatted", "lines"])
294+
→ SDK: sends as-is (array skips wrapping)
295+
→ Mobile: character-no-hyphen safety net → no-op ← already fits
296+
297+
Developer calls showText(dense_data, {breakMode: "character"})
298+
→ SDK: character-wrap → maximum utilisation
299+
→ Mobile: safety net → no-op
300+
```
301+
263302
### showText accepts `string | string[]`
264303

265304
```typescript
266-
// Simple string — auto-wraps for current device
305+
// Simple string — SDK word-wraps for current device
267306
session.display.showText("Very long text that will be wrapped automatically")
268307

269-
// Pre-wrapped array — sends as-is
308+
// Pre-wrapped array — sends as-is, skips SDK wrapping
270309
session.display.showText(["Line 1", "Line 2", "Line 3"])
310+
311+
// Explicit break mode override
312+
session.display.showText(denseData, {breakMode: "character"})
271313
```
272314

273315
### wrap() — pure formatting, returns string[]
@@ -287,7 +329,8 @@ session.display.showText(lines.slice(-3)) // show last 3 lines only
287329
// Options:
288330
session.display.wrap(text, {maxLines: 5}) // cap at 5 lines
289331
session.display.wrap(text, {maxLines: 1}) // single line (truncate)
290-
session.display.wrap(text, {breakMode: "word"}) // word-break
332+
session.display.wrap(text, {breakMode: "word"}) // explicit word-break (default)
333+
session.display.wrap(text, {breakMode: "character"}) // max utilisation
291334
session.display.wrap(text, {width: 0.5}) // 50% of screen width
292335
```
293336

@@ -314,6 +357,17 @@ session.display.showText(scroll.getViewport().lines)
314357

315358
`@mentra/display-utils` stays as a standalone package (cloud and mobile use it directly). `session.display` wraps it with session context so SDK developers don't need to import it or pick profiles manually.
316359

360+
**`display-utils` break modes reference:**
361+
362+
| Mode | Behaviour | Use when |
363+
| ----------------------- | ------------------------------------------------------ | --------------------------------------------------------------- |
364+
| `"word"` | Wrap at word boundaries, hyphenate only if word > line | Default for `session.display.showText` — readable output |
365+
| `"character"` | Break mid-word with hyphen | Maximum utilisation, dense data |
366+
| `"character-no-hyphen"` | Break mid-word, no hyphen | Mobile `DisplayProcessor` safety net — preserves dev formatting |
367+
| `"strict-word"` | Word boundaries only, long words overflow | Rare — when overflow is preferable to breaking a word |
368+
369+
**Note on `ColumnComposer` overflow bug**: there is a known off-by-one pixel issue in `ColumnComposer.mergeColumns()` where `Math.ceil` on space padding can push the right column start past `rightColumnStartPx`, causing the right column to overflow by up to 5px and the last character to wrap onto the next line's left position. Fix tracked in `cloud/issues/047-dashboard-refactor/`. The new system dashboard layout avoids `DoubleTextWall` entirely; the fix is still needed for third-party apps using `showDoubleText`.
370+
317371
---
318372

319373
## 4. Transcription

0 commit comments

Comments
 (0)