Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
- run: bun run check
- run: bun run desktop test:rust
- run: bun run desktop build
- run: bun run desktop test:macos

linux-web:
name: Linux distribution + WASM preview
Expand Down
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ to one of them:
pocket-desktop. It owns windows, application presentation and themes.
PocketJS owns package isolation, scheduling and native composition.
macOS and Linux are native targets; the browser is an interactive preview.
The macOS product keeps the desktop and headless window chrome, with Files,
Devices and Minesweeper as built-in apps, without the external demo catalog. Its read-only USB
discovery and bundle launcher live in `shells/desktop/macos`; native rendering remains in PocketJS.

Each shell owns its sources, manifests, scripts, tests, assets and documentation.
Root scripts provide setup and command routing. They share one runtime
Expand Down
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ shell owns its interface and input model.
| --- | --- | --- |
| Nintendo 3DS | Self-rendered tiling windows on the top screen; chords and touch controls on the lower screen | [shells/3ds](shells/3ds/README.md) |
| iPod touch 4 | An Omarchy companion that mirrors and controls a desktop over USB or Wi-Fi | [shells/ipod](shells/ipod/README.md) |
| Desktop OS | Windows, application launching and Classic 98, XP and Aqua themes on macOS and Linux, with a browser preview | [shells/desktop](shells/desktop/README.md) |
| Desktop OS | Desktop with Classic 98, XP and Aqua themes; macOS ships Files, Devices and Minesweeper, Linux and browser include the demo catalog | [shells/desktop](shells/desktop/README.md) |

The former **pocket-desktop** project is now the desktop OS shell in this
repository. Its application code, assets, tests, native build scripts, browser
Expand Down Expand Up @@ -61,7 +61,8 @@ bun run check:3ds # or check:ipod / check:desktop
bun run desktop macos # build and launch on macOS
bun run desktop linux # build and launch on Linux
bun run desktop web # interactive browser preview
bun run desktop build # macOS release build without launching
bun run desktop build # build the standalone Pocket Shell.app
bun run desktop test:macos # verify the built Mac bundle and USB companion
bun run desktop package:linux # relocatable Linux distribution
bun run desktop test:web # browser interaction smoke test
bun run desktop build:site
Expand All @@ -71,6 +72,16 @@ bun run desktop test:site
Desktop outputs are in `shells/desktop/dist/`. Use `bun run desktop --help`
to list its commands, including captures, benchmarks and the text companion.

On macOS, open `shells/desktop/dist/Pocket Shell.app` or drag it into
Applications. It opens an Aqua desktop with Files, Devices and Minesweeper
windows. Each app has a desktop icon and a Dock entry. Files browses the
Mac filesystem, launches Native Apps through macOS, and opens Pocket Apps as
Shell windows. Cards, Motions and Stats are included. A local OpenStrike checkout
can supply the packaged Pocket3D game. Devices lists connected PSPs and iPod
touch 4 devices over USB.
Discovery does not require Bun, Homebrew, an existing device bridge or this
checkout once the app has been built.

```sh
bun run guest # bundle the 3DS guest for the simulator
bun run 3ds # full console binary in dist/3ds
Expand Down
6 changes: 5 additions & 1 deletion docs/ASSETS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

Commit the definitions needed to build a shell, the inputs that cannot be
recreated from this checkout, and selected documentation and test fixtures.
Build intermediates and individual validation runs stay ignored.
Expensive offline icon bakes are retained as reviewed product inputs so normal
builds do not depend on Blender. Build intermediates and individual validation
runs stay ignored.

| Files | Role and retention |
| --- | --- |
| Desktop `gen-icons.ts` | Original pixel grids and vector definitions; retained as source. Its 100 SVG outputs in `src/system-ui/icons/` are ignored and regenerated before builds. |
| Desktop `assets/icons/render.py`, `objects.py`, `pixel-icons.py` and 135 PNG bakes | Original Blender scenes and pixel-grid recipes for applications, filesystem places and device classes across Aqua, XP and Classic 98, with shipping icons at 16/32/64 px. Cycles models, materials, cameras and lights are recreated by the recipe; normal builds copy these offline bakes into the ignored icon directory at 1×/2× density. Theme selection variants are derived into the ignored output directory during normal builds. `scripts/aqua-controls.ts` also generates supersampled Aqua button faces there; no additional baked button inputs are tracked. Editable `.blend` files and full-size renders stay in `.pocket-build/validation/blender-icons/`. |
| Desktop `gen-assets.ts`, W95FA OTF and its OFL notice | Font recipe and original input; retained. The ten 1×/2× `.bin` atlases in `src/system-ui/fonts/` are ignored. Inter comes from the pinned PocketJS submodule. |
| Desktop `assets/macos/AppIcon.icns` | Original SHERU macOS icon, reused unchanged for the Pocket Shell app bundle. Provenance and digest are in the desktop third-party notices. The `.app` itself stays in ignored `dist/`. |
| 3DS `src/wall/*.png` and `images.json` | The three texture inputs the guest uses. The preparation script needs external Omarchy originals and macOS `sips`; deleting the only bundled inputs would break a clean build. |
| iPod `src/fonts/SymbolsNerdFont-subset.otf` and its license | Shipped font input. The complete Nerd Font used to make this subset is not stored here. |
| iPod `src/menu.ts` | Versioned Omarchy menu snapshot. Regeneration reads an external machine or JSONC file; ordinary builds must not depend on a live Omarchy installation. The source version and digest are in its header. |
Expand Down
9 changes: 8 additions & 1 deletion scripts/check-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,22 @@ const goldens = new Set(TAPES.flatMap((tape) => tape.capture.flatMap((frame) =>
)));
const sourceInputs = new Set([
"shells/desktop/assets/fonts/W95FA.otf",
"shells/desktop/assets/macos/AppIcon.icns",
"shells/ipod/src/fonts/SymbolsNerdFont-subset.otf",
]);
// Reviewed offline theme artwork consumed by the desktop icon generator.
for (const prefix of ["", "xp-", "classic-"]) {
for (const name of ["files", "devices", "handheld", "media-player", "disk", "home", "desktop-place", "documents-place", "downloads", "native-apps", "pocket-apps", "document-file", "trash", "openstrike", "mines"]) {
for (const size of [16, 32, 64]) sourceInputs.add(`shells/desktop/assets/icons/${prefix}${name}-${size}.png`);
}
}
const wallpapers = JSON.parse(readFileSync(resolve(ROOT, "shells/3ds/src/images.json"), "utf8"));
for (const key of Object.keys(wallpapers)) sourceInputs.add(`shells/3ds/src/${key}`);

for (const path of [...goldens, ...sourceInputs]) {
if (!tracked.includes(path)) failures.push(`missing committed input or golden: ${path}`);
}
const mediaExtensions = new Set([".svg", ".png", ".gif", ".bin", ".otf", ".ttf", ".jpg", ".jpeg", ".webp", ".wasm", ".pak", ".pocket"]);
const mediaExtensions = new Set([".svg", ".png", ".gif", ".bin", ".otf", ".ttf", ".jpg", ".jpeg", ".webp", ".icns", ".wasm", ".pak", ".pocket"]);
for (const path of tracked.filter((path) => mediaExtensions.has(extname(path)))) {
if (!referenced.has(path) && !goldens.has(path) && !sourceInputs.has(path)) {
failures.push(`asset has no document, test or declared source consumer: ${path}`);
Expand Down
10 changes: 4 additions & 6 deletions shells/3ds/test/sim.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// test/sim.test.ts — Pocket Shell's render layer in the
// headless sim: the same button tape the Azahar golden runs, with the dock
// taps replaced by store calls (the sim has no touch screen; a detached core
// node stands in for the 3DS bottom screen's host root). What this proves is
// taps replaced by store calls. The sim owns the bottom screen's auxiliary
// host root. What this proves is
// that every chord, layout toggle and workspace switch reconciles the two
// Solid trees without a renderer error, in milliseconds rather than an
// emulator boot.

import { describe, expect, test } from "bun:test";
import { NODE_TYPE } from "../../../vendor/pocketjs/contracts/spec/spec.ts";
import { bootWorld } from "../../../vendor/pocketjs/hosts/sim/sim.ts";
import { SHELL_TAPE } from "../film/tape.ts";
import type { ShellStore } from "../src/store.ts";

const spec = SHELL_TAPE;

async function boot(): Promise<{ world: Awaited<ReturnType<typeof bootWorld>>; store: ShellStore }> {
const world = await bootWorld("pocketshell-main", 60, undefined, (ops) => {
const createNode = ops.createNode as (type: number) => number;
ops.__auxiliarySurface = { root: createNode(NODE_TYPE.view), w: 320, h: 240 };
const world = await bootWorld("pocketshell-main", 60, undefined, undefined, {
width: 400, height: 240, auxiliary: [320, 240],
});
const store = (globalThis as { __pocketShell?: ShellStore }).__pocketShell;
if (!store) throw new Error("the bundle did not publish __pocketShell");
Expand Down
Loading