Login
Timeline
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

50 most recent check-ins

2026-09-21
04:35
Merge crystal-robots badge app to trunk (ticket 1565521c5c, M3/W2-W3)

Merges agent/20260921T035546Z-m3-w2-w3-crystal-robots-badge-app (f6b766fcd88d): adds applications/apps/crystal_robots/crystal_robots_app.py, a badge front-end for the crystal-robots status/command interface (M3/W1, on trunk), built on lib/crystal_robots_client.py and modeled on battlesnake_app.py's polling/command pattern. Renders live robot state; ENTER steps through a 4-step move-only demo sequence targeting the first robot; UP sends estop with no target. Shows 'Robot offline' when the status file is missing or its generated_at_ms is stale (2000ms), without crashing the launcher. Never auto-starts a backend, unlike Battlesnake/Zepto. Tagged teacher_demo order 15, matching the 'Teacher Demo Showcase Plan' wiki page's reservation (the order 15 is presently inert -- core/app_loader.py's teacher_demo scanning hasn't merged to this branch yet, disclosed honestly in the source commit). Adds README.md and tests/test_crystal_robots_app.py (6 cases).

Verified independently in an isolated checkout (not the live tree): diff against trunk exactly these 3 files, no existing files touched, no .pyc/__pycache__ tracked. Read the source directly to confirm no backend auto-start, offline logic driven purely by generated_at_ms staleness (both missing- and stale-file paths tested), and the two commands are exactly estop and move-only nudges. crystal run ci.cr exits 0 with 28/28 tests (8 app-import + 6 crystal_robots_app + 7 client round-trip + 7 logic).

Gated GREEN and reviewed (merge-gate-report ok:true, design_input:confirm). Merge word given by fable under maintainer delegation. Source-only merge; no rebuild/redeploy. M3's remaining unit is classroom polish (M4). Leaf check-in: 4cb2ae057c user: agent-trunk-ops tags: badge-snake, trunk

04:01
M3/W2-W3: Crystal Robots badge app

Adds applications/apps/crystal_robots/crystal_robots_app.py, a badge front-end for the crystal-robots status/command interface documented in docs/crystal-robots-wire-contract.md, built on the existing lib/crystal_robots_client.py reader/writer (M3/W1). Modeled on applications/games/battlesnake/battlesnake_app.py's polling/command pattern, but never auto-starts a backend -- crystal-robots is an independent peer process.

- Renders live robot state (name, state, battery, task) from the polled status file; shows "Robot offline" when the status file is missing or its own generated_at_ms is more than STALE_STATUS_MS (2s) behind wall clock, without crashing the launcher. - Two stage-safe canned commands: ENTER runs a demo routine (steps through a small square of `move` nudges, one per press) targeting the first robot in the status snapshot; UP sends `estop` with no target, halting every robot. - Tagged `teacher_demo` (order 15, per the "Teacher Demo Showcase Plan" wiki page) via a class-level manifest attribute, forward-compatible with core/app_loader.list_teacher_demos() from M1 (not yet merged to this branch).

tests/test_crystal_robots_app.py (6 unittest cases, mocking lvgl/input minimally like tests/test_apps_sdl.py does) covers: a fixture status file driving the state view, the missing- and stale-file offline cases, and both canned commands writing the expected command.json shape.

Verified via `crystal run ci.cr`: exits 0, 28/28 tests (8 app-import + 6 crystal-robots app + 7 client round-trip + 7 logic). Does not touch crystal-robots or lib/crystal_robots_client.py. Leaf check-in: f6b766fcd8 user: agent-claude tags: agent/20260921T035546Z-m3-w2-w3-crystal-robots-badge-app

02:51
Merge wire-contract ERROR/resume correction to trunk (ticket f40ff10685)

Merges agent/20260921T021147Z-wire-contract-resume-clears-estop-only-a (d1776fe1fe28): amends docs/crystal-robots-wire-contract.md so resume is documented as clearing ESTOP only, with no effect on ERROR; select_robot likewise does not clear ERROR; adds a paragraph stating ERROR is terminal for the rest of the match with no in-vocabulary recovery path. Updates lib/crystal_robots_client.py's docstring to match. Adds tests/test_crystal_robots_client.py::test_error_robot_stays_error_after_resume_command. Six-command vocabulary (estop/resume/select_robot/move/calibrate/ping) unchanged; docs/docstring/test correction only, no behavior change.

Verified independently in an isolated checkout (not the live tree): diff against trunk exactly these 3 files, no code paths touched, no .pyc/__pycache__ tracked, crystal run ci.cr exits 0 with 22/22 tests (8 app-import + 7 client round-trip + 7 logic). Also traced the underlying engine claim directly against crystal-robots' actual current trunk (41aebac7ef, via fossil cat, not its live checkout): src/battle/field.cr's Robot#error is a getter with no public setter, and src/badge/session.cr's Session#apply skips ERROR robots on resume and treats select_robot/ping as no-ops -- the amended contract matches the real engine exactly.

Gated GREEN and reviewed (merge-gate-report ok:true, design_input:confirm). Merge word given by fable under maintainer delegation. Source-only merge; no rebuild/redeploy. check-in: b670d0ee0e user: agent-trunk-ops tags: badge-snake, trunk

02:13
Amend wire contract: resume clears ESTOP only, ERROR is terminal

crystal-robots ticket 27a70ff3ed flagged that the contract's resume row ("Clears ESTOP/ERROR state") doesn't match the engine: Robot#error (src/battle/field.cr) is a getter with no setter, and Session#apply's resume (src/badge/session.cr) only clears the @estopped set and does `r.active = true unless r.error`. select_robot is also confirmed a pure no-op in Session#apply ("informational only, no field state to change") -- it does not clear ERROR either, so there is no recovery command in the current six-command vocabulary at all; ERROR lasts for the rest of that crystal-robots match.

- docs/crystal-robots-wire-contract.md: resume row now says "Clears ESTOP ... Has no effect on ERROR"; select_robot row notes it doesn't clear ERROR either; added a paragraph spelling out that ERROR is terminal per-match with no in-vocabulary recovery path. - lib/crystal_robots_client.py: docstring note matching the above. - tests/test_crystal_robots_client.py: new test_error_robot_stays_error_after_resume_command asserts a status fixture with an ERROR robot still reports ERROR after write_command ("resume", ...) -- the client is a dumb reader/writer and just surfaces whatever the engine last wrote.

Six-command vocabulary unchanged. Verified via `crystal run ci.cr` (21/21 including the new case). Leaf check-in: d1776fe1fe user: agent-claude tags: agent/20260921T021147Z-wire-contract-resume-clears-estop-only-a

2026-09-20
21:58
Merge crystal-robots peer declaration + wire contract to trunk (ticket 500ed41616)

Merges agent/20260920T203716Z-m3-w1-declare-crystal-robots-peer-status (533aff20320b), the M3/W1 redo: declares crystal-robots as a peer (.peers/peers.json), documents the badge/crystal-robots status/command wire contract (docs/crystal-robots-wire-contract.md: two flat JSON files, 5Hz status cadence, seq/generated_at_ms staleness, 6-command vocabulary), modeled on battlesnake_app.py's existing STATE_PATH/COMMAND_PATH pattern. Adds lib/crystal_robots_client.py (badge-side reader/writer stub) and tests/test_crystal_robots_client.py (6 unittest cases). Folds in and supersedes the earlier 64c41339cf2e attempt, which had committed 9 stray __pycache__/*.pyc files predating trunk's ci.cr/ignore-glob; those are gone from this branch.

Verified independently in an isolated checkout (not the live tree): diff against trunk purely additive (these 4 files only), no .pyc/__pycache__ tracked, crystal run ci.cr exits 0 with 21/21 tests (8 app-import + 6 client round-trip + 7 logic). Gated GREEN and reviewed (merge-gate-report ok:true, design_input:confirm). Merge word given by fable under maintainer delegation. Source-only merge; no rebuild/redeploy.

Does not touch the crystal-robots repo itself; that side is routed separately via ticket 27a70ff3ed there. check-in: f21722a59a user: agent-trunk-ops tags: badge-snake, trunk

20:38
Redo: merge crystal-robots peer/wire-contract work, drop leftover bytecode, verify against ci.cr

Merges agent/20260920T194332Z-m3-w1-declare-crystal-robots-peer-status (64c41339cf2e), which declared crystal-robots as a peer (.peers/peers.json), documented the status/command wire contract (docs/crystal-robots-wire-contract.md) modelled on battlesnake_app.py's STATE_PATH/COMMAND_PATH pattern, and added a badge-side reader/writer stub (lib/crystal_robots_client.py) with a round-trip test (tests/test_crystal_robots_client.py).

That prior branch predated trunk's ci.cr and had committed the __pycache__/*.pyc bytecode its own test run generated; fossil rm'd all nine leftover .pyc files (now covered by trunk's ignore-glob) and confirmed a clean re-run leaves no bytecode tracked.

Verified: crystal run ci.cr exits 0, 21/21 tests (8 app-import + 6 crystal_robots_client + 7 logic), including the new test_crystal_robots_client.py round-trip suite. Leaf check-in: 533aff2032 user: agent-claude tags: agent/20260920T203716Z-m3-w1-declare-crystal-robots-peer-status

20:18
Merge badge-launcher ci.cr CI declaration to trunk (ticket 0717629c19)

Merges agent/20260920T195914Z-declare-the-ci-flow-a-root-ci-cr-that-ru (e91950522c90): adds a root ci.cr (plain Crystal, stdlib only, 'crystal run ci.cr') that runs badge-launcher's Python test suite directly via tests/test_*.py invocation (pytest/unittest discover both misfire on this repo's sys.exit(0)-at-module-scope test scripts), plus .fossil-settings/ignore-glob for __pycache__/ and *.pyc so compiled bytecode stops getting committed.

Verified: ci.cr exits 0, 15/15 tests (8 app-import + 7 logic). Gated GREEN (OCX-MERGE-GATE stamped on ticket 0717629c19) and merge word given by fable under maintainer delegation. Source-only merge; no rebuild/redeploy.

This unblocks the daemon's CI gate for badge-launcher branches generally (was holding all branches with 'no CI flow declared'). check-in: 9f5b654065 user: agent-trunk-ops tags: badge-snake, trunk

20:01
Add root ci.cr CI gate and ignore-glob for __pycache__/*.pyc

Adds a plain-Crystal ci.cr (stdlib only, `crystal run ci.cr`, no args) that runs badge-launcher's Python test suite and streams each script's output through, exiting 0/non-zero to match. Neither pytest nor unittest discovery is this repo's actual convention: pytest isn't installed/referenced anywhere, and `python3 -m unittest discover -s tests` falsely reports FAILED because tests/test_logic_sdl.py calls sys.exit(0) at module scope, which unittest's loader treats as an import error. The real convention (per test_apps_sdl.py's own docstring and both scripts' sys.exit(0)/sys.exit(1) contracts) is direct invocation, so ci.cr runs each tests/test_*.py script with python3 and fails the gate if any exits non-zero.

Verified: crystal run ci.cr exits 0, running tests/test_apps_sdl.py (8/8 app imports) and tests/test_logic_sdl.py (7/7 logic tests) — 15/15 total.

Also adds .fossil-settings/ignore-glob (__pycache__/, *.pyc) so compiled bytecode from running the suite doesn't get committed again. Leaf check-in: e91950522c user: agent-claude tags: agent/20260920T195914Z-declare-the-ci-flow-a-root-ci-cr-that-ru

19:48
task 500ed41616e57aca55d3b2395f12f81b9e395177: leftover work committed by the daemon at run end; suite not confirmed Leaf check-in: 64c41339cf user: agent-claude tags: agent/20260920T194332Z-m3-w1-declare-crystal-robots-peer-status
19:48
M3/W1 (badge-launcher side): declare crystal-robots peer + document status/command wire contract

- .peers/peers.json: declare crystal-robots as a local peer (not yet served; repo_url points at the conventional /var/lib/fossil path so peer tooling picks it up once crystal-robots is imported). - docs/crystal-robots-wire-contract.md: documents the status file crystal-robots writes and the command file the badge writes, fields, ~5Hz cadence, and command vocabulary (estop/resume/select_robot/move/ calibrate/ping), modeled on the state/command file pair battlesnake_app.py already uses toward its host backend. - lib/crystal_robots_client.py: badge-side reader/writer stub (CrystalRobotsClient) implementing that contract. - tests/test_crystal_robots_client.py: 6 unittest cases round-tripping a fixture status file and command writes (read/dedupe/missing-file, write/seq-increment/directory-creation). All 6 pass.

Does not touch crystal-robots; that side is its own ticket there per the M3/W1 scope split. check-in: 23c4bf661c user: agent-claude tags: agent/20260920T194332Z-m3-w1-declare-crystal-robots-peer-status

2026-09-17
19:05
Merge badge-launcher root-privilege fix to trunk (ticket 50bd91a6a6)

Merges agent/20260917T184525Z-badge-services-must-not-run-as-root-laun (b90c39381c), which itself carries the original root-privilege fix (e158d2da93) plus two coordinator-requested follow-ups: a narrower debian/postinst chown (config.json, the applications/ app-store install tree, and /home/badge instead of the whole /opt/badge_launcher tree) and removal of scripts/run.sh setup lines now redundant with the unit's root ExecStartPre steps.

badge-launcher.service now runs User=badge/Group=badge with hardware access via group membership (video, i2c, input, tty) and new udev rules, instead of User=root. Bridge-runner and Fossil-web-server hardening from the same ticket remain open (out of scope for this checkout).

Verified in isolated clones (not the live checkout): tests/test_apps_sdl.py 8/8 and tests/test_logic_sdl.py 7/7 pass on both e158d2da93 and b90c39381c. Gated GREEN and merge word given by fable under maintainer delegation.

This is a source-only merge. It does not rebuild or redeploy anything; badge-launcher ships via a Debian package, not this checkout's binary. check-in: e0b8e790c3 user: agent-trunk-ops tags: badge-snake, trunk

18:47
badge-launcher: narrow postinst chown, drop redundant run.sh setup

Follow-up to e158d2da93 (ticket 50bd91a6a6) per coordinator hold:

- debian/postinst: only chown the paths the launcher actually writes (config.json, the applications/ app-store install tree, and /home/badge) instead of the whole /opt/badge_launcher tree. The unprivileged, internet-facing service can no longer modify its own code, debian metadata, drivers, lib, or core sources.

- scripts/run.sh: drop the killall and the two cursor-hide writes (fbcon cursor_blink, setterm -cursor off). The unit's ExecStartPre steps already do these as root via the systemd '+' prefix; running as 'badge', these lines only failed silently behind 2>/dev/null.

tests/test_apps_sdl.py (8/8) and tests/test_logic_sdl.py (7/7) still pass. Leaf check-in: b90c39381c user: agent-claude tags: agent/20260917T184525Z-badge-services-must-not-run-as-root-laun

11:01
Note greybus-over-I2C as an alternative Zepto transport in the bridge docstring

Maintainer follow-up: Zepto supports greybus over I2C (github.com/beagleboard/greybus-zephyr) in addition to plain I2C register reads. Still no network transport either way. Captured as an open question on ticket M2/W2b rather than guessing which the badge already supports -- if greybus-over-I2C is what's there, nodes may show up as normal IIO devices, which would replace this bridge's manual scan/read rather than just filling in its placeholder address/register. Leaf check-in: b488aa7da3 user: agent-claude tags: session/117061bb067f0af9a202940868770beaee7269afb63b941bef2e9684bf836e7e

11:00
M2: BeagleConnect Zepto sensor demo, re-scoped to I2C

Per maintainer correction: Zepto is a Zephyr microcontroller with no network stack, wired to the badge over I2C (not a wireless/gateway transport) -- drop the earlier CoAP/border-router/greybus assumptions.

- scripts/zepto_bridge.py: host-side reader, scans I2C bus(es) via i2cdetect, reads a value per detected node via i2cget, publishes /tmp/badge_zepto/state.json (per-node id/bus/address/raw/last_seen_ms), evicts stale nodes. Address range and value register are documented placeholders pending the real Zepto I2C spec (tracked as ticket M2/W2b). - scripts/run_zepto_bridge.sh + scripts/deploy_local_zepto_sensors.sh: launcher and on-device deploy, mirroring the Battlesnake/IIO scripts. - applications/demos/zepto_sensors_app.py: polls state.json (battlesnake- style snapshot caching), auto-starts the bridge, renders up to 4 node rows with segment bars styled like sensor_visualizer_app.py; shows a scanning/starting message instead of erroring when no nodes are live. Tagged teacher_demo order=25. - Test coverage added to tests/test_apps_sdl.py and tests/test_logic_sdl.py; both suites pass. - Updated the Teacher Demo Showcase Plan wiki and applications/apps/teacher_mode/README.md to match. check-in: 5370c00d8c user: agent-claude tags: session/117061bb067f0af9a202940868770beaee7269afb63b941bef2e9684bf836e7e

2026-09-16
15:30
Add Teacher Demo Mode shell for classroom showcase

Lays the foundation for a guided, one-button tour of BeagleBadge's demos so a teacher can present without navigating the category menu.

- core/app_loader.list_teacher_demos(): scans all categories for apps carrying an opt-in `teacher_demo` dict attribute (summary, hardware, order) and returns them sorted. - applications/apps/teacher_mode/: new TeacherModeApp — LEFT/RIGHT to browse demo cards, ENTER to launch, ESC to back out; returns to the same card after a demo exits. - Tag the three existing showcase-worthy demos (Battlesnake/BadgeSnake, IIO Sensors, BadgeBeam) with teacher_demo metadata as the first opt-ins. - Generalize the two test harnesses' module-path resolution so folder-based apps nested under a category (not just flat files) can be exercised, and add coverage for the new manifest + navigation.

This is milestone 1 of the teacher-showcase plan (see forum thread and the Teacher Demo Showcase Plan wiki page); BeagleConnect Zepto sensor telemetry and a crystal-robots bridge are follow-on milestones that plug into this same `teacher_demo` convention. check-in: 051f0fbfd1 user: agent-claude tags: session/117061bb067f0af9a202940868770beaee7269afb63b941bef2e9684bf836e7e

15:22
Create new branch named "session/117061bb067f0af9a202940868770beaee7269afb63b941bef2e9684bf836e7e" check-in: fc6beeba0a user: agent-claude tags: session/117061bb067f0af9a202940868770beaee7269afb63b941bef2e9684bf836e7e
2026-09-15
08:42
badge-launcher: run as unprivileged 'badge' user, not root

badge-launcher.service was User=root on an internet-accessible device. Determined what it actually needs root for (framebuffer, I2C, RGB LED, input, tty console) and granted it instead through group membership and targeted udev rules:

- debian/badge-launcher.service: User=badge, Group=badge, SupplementaryGroups=video i2c input tty. The two ExecStartPre lines that toggle the framebuffer console cursor still need root (they write root-owned sysfs/tty nodes with no group grant), so they keep it via the systemd "+" exec prefix while the main process drops privileges. - debian/badge-launcher.rules (new): udev rules for /dev/i2c-* (GROUP=i2c; not covered by udev's stock defaults, unlike fb0/event*/tty which already get video/input/tty) plus the sysfs attributes used to bind/unbind the opt3001 driver and drive the RGB status LED, neither of which are device nodes udev can chgrp declaratively. - debian/postinst: creates the 'badge' system user, adds it to the needed groups, and chowns /opt/badge_launcher (it writes its own config.json and app-store installs there) and its home directory. - debian/rules: installs the new udev rules file into the package. - debian/control: adds the adduser dependency postinst now relies on.

GPIO device nodes are not touched directly anywhere in this codebase (the badge buttons come in through /dev/input/event0), so no gpio group grant was added.

Bridge runner and Fossil web server hardening from the same ticket are out of scope: neither lives in this checkout. Leaf check-in: e158d2da93 user: agent-claude tags: agent/20260915T083709Z-badge-services-must-not-run-as-root-laun

2026-06-11
17:39
Pin BadgeSnake launcher demo matchup check-in: 47ba228d6d user: codex@beagleboard.org tags: badge-snake, trunk
2026-06-09
05:48
Refine Battlesnake food and snake rendering check-in: 052a739ffa user: codex@beagleboard.org tags: badge-snake, trunk
05:42
Improve Battlesnake board readability check-in: 847dae7918 user: codex@beagleboard.org tags: badge-snake, trunk
05:32
Auto-start Battlesnake backend from launcher check-in: 5f153ab539 user: codex@beagleboard.org tags: badge-snake, trunk
05:09
Handle OPT3001 hotplug more robustly check-in: 506c29f951 user: codex@beagleboard.org tags: badge-snake, trunk
04:54
Tune live sensor demo sampling latency check-in: 3671ff7d6c user: codex@beagleboard.org tags: badge-snake, trunk
04:42
Refine IIO sensor visualizer layout check-in: 9701babc36 user: codex@beagleboard.org tags: badge-snake, trunk
03:57
Add IIO sensor visualizer demo check-in: f01552d82b user: codex@beagleboard.org tags: badge-snake, trunk
02:43
Prebuild badgesnake before local UI launch check-in: 4c7c163af6 user: codex@beagleboard.org tags: badge-snake, trunk
02:29
Show richer simulated Battlesnake match state check-in: 22e2668ad4 user: codex@beagleboard.org tags: badge-snake, trunk
2026-06-07
17:04
Render Battlesnake UI from host state snapshots check-in: b2ede5ae67 user: codex@beagleboard.org tags: badge-snake, trunk
2026-06-05
17:24
Return direct Battlesnake app to launcher menu check-in: 87400ae2cd user: codex@beagleboard.org tags: badge-snake, trunk
16:43
Add Battlesnake app and local deploy helpers check-in: 7c73d2f2be user: codex@beagleboard.org tags: badge-snake, trunk
2026-04-07
14:24
Merge branch 'main' of https://github.com/Grippy98/badge-launcher Leaf check-in: b1cee3bb23 user: andrei1998@gmail.com tags: main, trunk
14:23
chore: remove references to unused libtuxdriver check-in: 6a60051043 user: andrei1998@gmail.com tags: main, trunk
14:21
chore: project cleanup and reorganization

- Consolidate scattered docs into docs/

- Untrack pre-compiled binaries (img2bin, micropython)

- Move tests and specific scripts to their respective directories

- Clean up broken README links

- Disable img2bin compilation since source is missing

- Restore debug_loader.py to tools/ check-in: 326427d646 user: andrei1998@gmail.com tags: main, trunk

14:12
Remove docstring from init function

Removed docstring from the init function in display.py. check-in: 286609c48d user: noreply@github.com tags: main, trunk

14:11
Remove zephyr submodule from .gitmodules

Removed zephyr submodule configuration. check-in: d47c57300a user: noreply@github.com tags: main, trunk

14:10
Update README.md check-in: ab7894fc52 user: noreply@github.com tags: main, trunk
14:09
Cleanup check-in: 955bf3873a user: andrei1998@gmail.com tags: main, trunk
14:07
Delete debug_loader.py check-in: cd4887765b user: andrei1998@gmail.com tags: main, trunk
14:04
Update .gitignore check-in: ad088b67f7 user: andrei1998@gmail.com tags: main, trunk
2026-03-17
20:41
Re-architect BLE server to separate GATT definition from raw Hardware HCI Advertising check-in: 6cdaa51e3e user: 7153954+Grippy98@users.noreply.github.com tags: main, trunk
20:37
Force BlueZ to use Legacy BLE Advertising PDUs with Secondary_Channel: 1M check-in: 633c057837 user: 7153954+Grippy98@users.noreply.github.com tags: main, trunk
20:19
Reinsert custom 128-bit ServiceUUID to LEAdvertisement1 to support native WebBLE Service discovery check-in: 72db4017bc user: 7153954+Grippy98@users.noreply.github.com tags: main, trunk
20:02
Omit large 128-bit Service UUID from LEAdvertisement1 to force LocalName into primary AD packet check-in: c343fcbdb4 user: 7153954+Grippy98@users.noreply.github.com tags: main, trunk
19:48
Add BadgeBeam App, DBus background server, and fix launcher menu scrolling check-in: 6fea1bb8de user: 7153954+Grippy98@users.noreply.github.com tags: main, trunk
2026-03-03
01:45
Remove Libtuxdriver, update deb build script check-in: b1717239a5 user: andrei1998@gmail.com tags: main, trunk
2026-02-19
20:24
Fix sync script check-in: 4d87adf471 user: andrei1998@gmail.com tags: main, trunk
2026-02-09
16:52
Add Linux Instructions check-in: fa62ada6a9 user: andrei1998@gmail.com tags: main, trunk
2026-02-06
16:37
Input cleanup on hardware check-in: 35b2d65224 user: andrei1998@gmail.com tags: main, trunk
2026-02-05
20:27
Add File Manager and App Loading fixes check-in: d4ec754083 user: 7153954+Grippy98@users.noreply.github.com tags: main, trunk
19:41
App Loader and Menu Fixes check-in: 1d10ef90be user: 7153954+Grippy98@users.noreply.github.com tags: main, trunk