makepad/apps/wm/ci.splash
Admin 036fa2fd86 apps, examples: the window manager on Android and Windows, the phone layouts, the task manager, director, mail and the rest; Flow, the asset UI and VJ move to Stage
App and example changes, with the apps that moved to the Stage repository (apps/vj, apps/asset-ui) removed here.

Covers work 6f1e44649..2b1a41df4 for apps examples:

- wm: the Android super-app compiles tiles on the phone against the host engine
- cargo-makepad: the super-app APK is packed by `android dyn-pack`, in Rust
- widgets, storybook: the widget catalogue app, some eighty new widgets, a theme store with mixable style sheets, and the rule that a press belongs to
- wm, widgets: the style tween starts with all eight weights, and the new style sheet takes the last number instead of macOS's
- platform: the Android desk swipes at 120 Hz — offscreen render passes and framebuffers cached, SVG meshes kept, font families that complete
- flow: the flow-ui app and the flowgraph canvas return to the workspace, with staged progress in libs/flow
- app_main!: only ship the fonts an app declares (#1247)
- platform, widgets, wm: every Vulkan pass renders through a negative-height viewport again, so a Wayland or X11 window stands upright, and no capture
- calendar: its own colour contrast is named explicitly, now that the theme store exports one under the same name through the widgets glob
- platform, wm, director: a hosted app's software frame arrives as a top-left texture and the window manager and the director carry no flip term at al
- wm: the desktop style menu lists each style once
- cef, video, platform: what Stage's browser needs from the shared layers
- platform, wm: work builds again on iOS, tvOS and wasm, and the window manager is warning-free on Windows
- ci: tools/ci, a Splash runtime that watches a branch and runs every ci.splash it finds
- ci: the terminal gets its pty helper, director is a desktop tool, and a refused input is asked again
- apps: what the CI box found
- Remove Flow, asset and VJ applications moved into Stage
- ci: a quiet header, a build that visibly moves, and scripts that leave the machine alone
- tests: the workspace suite, run as a whole for the first time, passes outside the example UI tests
- examples: the UI tests pass, for the reasons they failed
- tests: the last three failures of the CI box's night
- tools: makepad-screen is makepad-agents, and its binary is `agents`
- tests: the three binaries over ten seconds in release come under it
- wm: the shell menu says what it did, and the CI waits for that
- mail: the phone layout lines up
- clock: the phone layout fits both orientations
- calendar, reminders, calculator, sheets: the phone layouts fit their space
- platform, widgets, wm: a touch that is taken away is cancelled, never released
- weather, notes, finance, photos, route: the phone layouts tidy up
- files: the phone layout tidies up
- wm: the phone shell's surfaces match the app and the grid
- wm on Android: every app is its own process
- clock: a cancelled release neither opens an alarm nor switches tab
- platform, wm: hosted apps ask the WM for what they cannot do themselves
- wm on Android: apps build on the phone
- wm on Android: app transitions and gestures feel like the phone's
- android: rotated Vulkan windows stop rebuilding their swapchain every frame, and hosted children get touch
- android: hosted children hand frames over with GPU fences and draw only when they have work
- wm on Android: gestures and surfaces settle like the phone's
- widgets: touch lists scroll with Android's physics
- wm on Android: the shell follows the Pixel launcher's motion
- wm on Android: Recents shows the apps over a receding home, and the home screen switches looks
- wm on Android: the look switcher stays put, the iOS dock shows its icons, background apps follow a look change
- task, cargo-makepad, widgets, audio: the task manager chooses its columns, graphs every process' network and disk traffic and installs itself as a D
- files: the tile view's three projections are toolbar buttons
- mail: the local view takes a theme-derived palette and line icons, search pages share records
- director: agent lanes form a tree and Grok joins the usage bar
- widgets, draw: skeuomorphic surfaces light each other through an optional relief buffer
- widgets, platform: a texture can light the relief buffer, menus take colour chips, and a style reload recompiles changed shader functions
- platform, widgets, audio_route, ai: window crossfades and whole-frame presents, caption controls that click, themed menus, a stereo-pair audio tap,
- builder: the Builder TUI matches the new terminal design, Windows executables carry app icons, and every app has one
- files: the Files app deletes nothing and never overwrites
- director: coding agents ask before acting unless you choose otherwise
- sheets, score, git, home: saves cannot cut a file short or overwrite another one, and checkouts cannot write outside the repository
- widgets, builder: the big widget families are features, all on by default, and the Builder takes none of them
- ai: Claude Desktop drives any app with the F10 panel
- wm: starts on Windows
- wm: children open no console windows on Windows
- wm: the whole deck out of a Builder's source, compiled only when the person opens an app
- ai: Connect hands the .mcpb to Claude Desktop itself
- wm: the clock and calendar know the date on Windows
- wm: opening an app rebuilds it when its binary is out of date; warm instances never build
- civil-time: one local wall clock for every app, and it knows the zone on Windows
- platform + wm: a hosted child redraws at its tile's new size
- calendar: the Calendars sheet is an opaque panel, and the wide layout does not float one over its sidebar
- platform: an app's package dir, icons and bundle name rebuild only that app
- build: the AI stack, csg, Scope and Source Library join the one workspace
- ai chat: the chat's backends are the CLI, MCP and cloud providers; the local model is the `localai` feature
- apps: every app that hosts the chat has a `localai` feature for the local model, off unless the app's own job runs one
- widgets: every widget family is a crate of its own under widgets/families, and makepad-widgets links, re-exports and registers the ones its features
- aichat, widgets: the chat reads the design feedback through the tweaker's hook, so linking the chat no longer needs the tweaker
- apps, examples, libs: each crate builds only the widget families it uses, and the design overlay is each app's own default feature
- ai chat: a build without local AI starts on the first provider that answers here, not on "No model"
- repo: no third-party comic archive, generated models or sample asset in the tree
- remove big example media files
- wm: in a Makepad Builder installation apps build through the Builder, however wm was started

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 20:10:58 +02:00

83 lines
6.3 KiB
Text

// CI smoke test for the window manager. Run by tools/ci, which finds every
// `ci.splash` in the checkout and runs it with the `ci` module in scope.
//
// The rule: this script decides every input. The vision model never chooses
// what to send; `ci.accept(image, text)` hands it one grab and one acceptance
// text, and it answers YES or NO with its reasons. Keep it basic: does the
// WM come up, switch to macOS, and launch a terminal and a browser.
use mod.std.*
use mod.ci;
// Said in every acceptance: hidden test instances draw this on every grab.
let FRAME = "This is a screenshot of one application window taken from a Mac. A thin bright red frame runs around the very edge of the picture; it is the test harness's marker and is not part of the application. Ignore it. "
let VERDICT = " Write one short bullet line for each numbered point saying what you see. Then write the verdict as the last line, in exactly this form: VERDICT: YES or VERDICT: NO"
ci.step("check other platforms", fn(){
ci.check_targets({packages: ["makepad-wm"] targets: ci.host.targets})
})
// The WM starts its apps through cargo. Building them first makes that
// launch instant, so the waits below measure the app, not the compiler.
ci.step("build the apps the desk will open", fn(){
ci.build({package: "makepad-terminal" binary: "terminal"})
// The terminal starts its shell through this helper, next to it.
ci.build({package: "makepad-agents" binary: "agents"})
ci.build({package: "makepad-browser" binary: "browser"})
})
let wm = ci.launch({package: "makepad-wm" binary: "wm" cwd: "."})
ci.step("desktop is up", fn(){
ci.sleep(3.0)
wm.no_errors()
let start = wm.grab("start")
ci.accept(start, FRAME + "The application is a desktop window manager: it draws a whole desktop inside its own window. A desktop is being shown when ALL of these are true: 1. The picture is not blank: it is not a single flat colour edge to edge. 2. There is a bar or panel along the top edge or the bottom edge, running most of the width, that contains small icons or text. 3. There is a large background region, a wallpaper or a flat desktop colour, taking most of the remaining area." + VERDICT)
ci.accept(start, FRAME + "Some failures paint text over the whole window: a red or black panel with words such as panic, error, thread, unwrap, failed, backtrace, or a long block of monospace text filling the screen. 1. Name the largest block of text you can see and where it is. 2. Say whether any of those words appear in it. YES means the window shows NO error panel and NO error words. NO means an error panel or those words are visible." + VERDICT)
})
ci.step("switch to the macOS style", fn(){
wm.key("Space", {cmd: true})
wm.type_text("macos")
wm.key("ReturnKey")
wm.wait_log("desktop style macos applied", 15.0)
// The log line lands while the menu is still up and the desktop is
// still tweening: settle before looking.
ci.sleep(2.5)
let mac = wm.grab("macos")
ci.accept(mac, FRAME + "The application is a desktop window manager that can imitate several desktop styles. A macOS-style desktop has these features: 1. A thin menu bar across the very top of the picture, light or dark, with small text or a small mark at its left end and small status icons such as wifi, sound and battery at its right end; a clock may sit in the middle or at the right. 2. A dock: a single row of many colourful square app icons with rounded corners along the bottom edge, sitting on a translucent rounded shelf that is wider than it is tall. 3. It does NOT have a Windows-style taskbar with a Start button at the bottom-left. YES means points 1, 2 and 3 are all satisfied." + VERDICT)
ci.accept(mac, FRAME + "Look only at the top edge of this macOS-style desktop. Describe in three bullet lines: the strip's height compared to the picture, what is at its left end, and what is at its right end. YES means a thin bar runs across the full top edge with something at both ends. NO means no such bar." + VERDICT)
ci.accept(mac, FRAME + "Look only at the bottom quarter of this macOS-style desktop. Describe in two bullet lines: whether there is a single row of app icons, and whether that row sits on a rounded shelf or panel near the bottom edge. The row may be short and centred or long and nearly as wide as the picture; both are fine. YES means a row of at least four icons on a shelf near the bottom edge. NO otherwise." + VERDICT)
})
ci.step("launch the terminal", fn(){
wm.key("Space", {cmd: true})
wm.type_text("terminal")
wm.key("ReturnKey")
// The menu says what Return did; a launcher that lost the keys or
// picked nothing fails here, by name, not at the frame wait below.
wm.wait_log("shell menu activate apps.terminal", 20.0)
// "launched" fires at spawn; the window is a compile placeholder until
// the app draws. The WM says when it has: wait for that line.
wm.wait_log("terminal client * first frame", 180.0)
ci.sleep(2.0)
let shot = wm.grab("terminal")
ci.accept(shot, FRAME + "It shows a desktop with app windows on it. A terminal window is a rectangular window whose content area is mostly one dark or one light flat colour with lines of monospace text starting at the left edge, usually with a prompt symbol such as $ or % or > on the last line, and a title bar above it. 1. For each window you can see, say its rough position and what its content looks like. 2. Say whether at least one of them is a terminal as described. YES means at least one terminal window is open." + VERDICT)
})
ci.step("launch the browser", fn(){
wm.key("Space", {cmd: true})
wm.type_text("browser")
wm.key("ReturnKey")
wm.wait_log("shell menu activate apps.browser", 20.0)
wm.wait_log("browser client * first frame", 240.0)
ci.sleep(4.0)
let shot = wm.grab("browser")
ci.accept(shot, FRAME + "It shows a desktop with app windows on it. A web browser window has an address bar, a wide rounded text field near its top containing a web address or a search field, possibly a row of tabs above it, and a web page below it with headings, paragraphs, images or a search box. 1. For each window you can see, say its rough position and whether it has an address bar near its top. 2. Say whether at least one of them is a web browser as described. YES means at least one browser window is open." + VERDICT)
})
wm.no_errors()
wm.quit()
nil