genex-desktop / tests
AGENTS.md810 starsChanged 25 days agoMITView on GitHub
Root rules and the L0–L5 loop are in AGENTS.md; the authoritative scope and layer catalog are in verification. node --test on Node 24, which strips TypeScript types, so tests and sources use erasable syntax only (no enum, namespace or parameter properties). npm test -- <files> runs named files without building the affected graph. Bare npm test runs all non-rig files with two workers, then all rig files serially, including after non-rig failures. conformance/ holds behavior suites, property/ holds fast-check suites…
In this repository33 other files it gives its agents.
- AGENTS.mdAGENTS.md
- src/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- src/CLAUDE.mdCLAUDE.md
- tests/CLAUDE.mdCLAUDE.md
- add-event-typeSkill
- add-ipc-channelSkill
- add-plugin-toolSkill
- better-colorsSkill
- better-layoutSkill
- better-typographySkill
- better-uiSkill
- better-writingSkill
- breakSkill
- harness-incident-fixSkill
- run-area-testsSkill
- variantSkill
- verify-ui-via-dev-controlSkill
- wire-artSkill
- add-event-typeSkill
- add-ipc-channelSkill
- add-plugin-toolSkill
- better-colorsSkill
- better-layoutSkill
- better-typographySkill
- better-uiSkill
- better-writingSkill
- breakSkill
- harness-incident-fixSkill
- run-area-testsSkill
- variantSkill
- verify-ui-via-dev-controlSkill
- wire-artSkill
The file
Files
Tests
Root rules and the L0–L5 loop are in AGENTS.md; the authoritative scope and layer catalog are in verification.
Runner
node --test on Node 24, which strips TypeScript types, so tests and sources use erasable syntax
only (no enum, namespace or parameter properties). npm test -- <files> runs named files
without building the affected graph. Bare npm test runs all non-rig files with two workers,
then all rig files serially, including after non-rig failures. conformance/ holds behavior suites, property/
holds fast-check suites with fixed seeds, e2e/ holds Electron runners.
scripts/test.mjs, scripts/affected-tests.mjs and the Windows suite (scripts/test-windows.mjs)
preload helpers/leftover-children.ts into every test file's process: a file that still has a
child process running after its own after hooks fails by name, instead of never exiting and
holding a runner slot. Stop what a test starts:
a core's stop() (or core-lite's close()), a ProcessSandbox's dispose(). On Linux,
sandbox-runtime's socat bridges run until the last sandbox is disposed. Node runs a file's root
after hooks once the tests registered so far have ended, so the check also waits for tests a
file registers after a top-level await (it follows node:test's node.test trace).
Each batch also runs with TMPDIR, TMP and TEMP set to a folder of its own (/tmp/gt-<pid>-…
off Windows, or in the inherited temp folder where /tmp is not writable), removed when the batch
ends, so what a test leaves in the temp folder does not pile up. A file run directly with
node --test puts its tmpDirs in a gt-<pid>-… folder of its own the same way. A run killed
before its cleanup leaves its folder: each batch first removes every gt- folder whose owner
process is gone, or that sat unchanged for a day (scripts/test-tmp.mjs).
CI partitions literal test groups with direct callbacks. Ordinary groups stay whole; the large
harness incidents suite is split into direct test subtrees, with each test's runtime descendants
and per-case hooks intact. It may not gain once-only parent hooks or dynamic direct registration.
Seed groups stay whole; their short seed upgrade root uses its direct case names to avoid matching
other roots with the same prefix. Unsupported or ambiguous shapes fail planning instead of losing coverage.
A test that runs the compiler spawns packageBin('typescript', 'tsc') from
scripts/package-bin.ts (TypeScript 7), not a node_modules path; one that builds a program
through the JS API imports @typescript/typescript6.
Helpers (helpers/)
core-lite.ts: a realStudioCoreafterinit()without the harness or engines. Its folders are real paths: the development containment check refuses a games root reached through a link (macOS/var→/private/var), so a test passing its owngamesRoothands it arealpath.resources.ts: the read-only resources folder a core needs. Import it, notstudio-rig.ts, when you only need resources: anything that reaches the rig runs in the serial rig group.sharedResources()assembles one read-only tree per test process for rig/core-lite defaults;makeResources()always creates a fresh mutable tree, including compiler-off fixtures.studio-rig.ts: the full rig with the harness loop; slow and sequential (L3).ctx-recorder.ts: a fake harnessctxthat recordsctx.callsequences (conformance/loop-sequences.test.ts). Like the real host it refuses an unknown method (UnknownMethod) and path-bearing paramsHARNESS_PARAM_SCHEMASrejects (InvalidParams).fake-studio-api.ts: a renderer-sideStudioApifake.conformance/renderer-state.test.tsdrives the Zustand stores throughcreateStudiowith it, with no DOM.fake-ollama.ts,scripted-claude.ts,scripted-codex.ts: scripted engines, no network.fake-anthropic.ts: enough of Anthropic's Messages API for the real Claude Code CLI to run one scripted worker command (ANTHROPIC_BASE_URL, a dummy OAuth token, nothing billed).fake-openai-responses.ts: the same for the real Codex CLI over OpenAI's Responses API (a custom model provider, no sign-in), a command that may ask to run outside the sandbox, and a one-shot answer (startFakeAnswer, an Auto check's verdict).fake-xai-responses.ts: the same for the real Grok Build CLI over xAI's (Grok's session service stood in for, signed in with a made-up token in a test's own home).snapshot-fixtures.ts: dirty, untracked and nested user repositories.unreal-moment-bus.ts: a fake of Genex's hook bus that plans each moment from a plugin manifest;unreal-editor-stand-in.ts: the editor the Unreal plugin's queue talks to;unreal-fake-engine.ts: a small fake Unreal (the Blank template and Epic's three plugin templates) and the Unreal plugin's backend on it in an open game, launches and host calls recorded, a game link kept as the host keeps it, and stand-in programs for a plugin's build, tests and package.godot-fake-engine.ts: a fake Mac with Godot apps where the test puts them, a runner that records each Godot job and answers with Godot's recorded words (fixtures/godot-cli/), and the Godot plugin's backend on both in an open game, its host calls recorded; and a fake Windows PC (fakeWindows,godotWindowsFixture) whose host plays the sandbox jobs and the pinned Godot.unity-editor-stand-in.ts: a Unity project folder, the descriptor Unity's Pipeline package keeps in it while an editor has it open, and a stand-in for that editor's HTTP server (scripted answers, every request recorded, a clock onlysleepmoves) as the Unity plugin'sPipelineDeps; a Mac's folders with editors installed as Unity Hub lays them out (macEnv,fakeEditor), a process table whose signals a test decides (processTable,editorRow), and a call's binding as the host hands it to the plugin's backend (pluginContext).unity-backend.ts: the Unity plugin's backend on all of those in a game folder (backendOn: its tools bycall, its panel's actions byact), with launches recorded and an opened editor started as a process with its descriptor.loop-host.ts: a fake host for the one Loop (runDirectoron a project of any kind, a web game's too): a real git repository as the game folder, the moments a plugin manifest hooks onunreal-moment-bus.ts, and the lead's scripted turns, the pool's workers and the reviewer as three kinds of delegation, on the test's clock;dispatch()starts the run through the run's start instead, on the wall clock.observe-windows.ts: fake preview windows for a plugin'sobservewith astillor aclip(Live and the pooled windows, each logging what it was asked, over a page the test scripts), a real core over them (observeHost) and budgets on a clock the test holds (heldClock).play-viewer-rig.ts: Play's viewer over recording fakes (the game's view, the bar's layer, the gallery, comments, the coin client, the sign-in, the browser) on a clock the test moves, every call inlog;sheet()is the purchase sheet as last drawn.project-fixtures.ts: the synthetic project folders infixtures/projects/(copyProjectcopies one into a test's folder and adds the files its engine writes while it runs), reads of a listed game's facts, a fake harnessctxwhosegame.*calls reach acoreLite, and a plugin registry with the toy engine plugin (fixtures/toy-engine-plugin/) installed.roblox-helper.ts: stand-ins for the Roblox plugin's helper link: Roblox Studio as StudioMCP lists it (each Studio with the helper's session marker), a clock the test moves by hand, and the Genex helper over an in-memory connection or a real WebSocket.roblox-mac.ts: a fake Mac for the Roblox plugin's backend (Studio's app a stand-in; home, storage and games real temporary folders; Studio's running, answering and open places set by the test) andhostFor, Genex's side of a plugin call in one game, keeping links as the host does.roblox-models.ts: small synthetic glTF models for the Roblox plugin's asset gate (a GLB writer, a cube made of grids, a real grey PNG of any size) and the builders offixtures/roblox-models/, each model failing the gate for one reason;writeModelFixtureswrites them again.engines.ts: the Unreal plugin's and the toy engine'senginedeclarations, read from their manifests, and a catalog of both (whatPluginRegistry.engines()answers), for linking games.plugin-author.ts: the Genex plugin's plugin-author skill read as an agent reads it (genex__skill, page by page) and its example plugin written into a project where the skill says.worker-chat.ts: a game chat with a run started in it, fake engines (two delegated, one local) that record each request, a copy of the game in that run's folder and the chat's permission rows, for worker seats and their questions (worker-seats,worker-questions,chat-workers), agent jobs through ajobSpawnthe test gives it (job-tools), andapp_lookthrough the stub port and a recordingscreenAccess(app-look-tool). Its waits are on what happened (untilSeen,nextCard), never on a clock.worker-pool-host.ts: a fake host for the seed's worker pool (real git in a temporary game and its copies, worker sessions the test ends, every record the pool appends), forworker-poolandworker-events.isolated-import.ts: imports a module in a worker thread of its own and answers with its exports' types or the error that stopped it linking. Node never frees a linked module, so a test that loads a whole harness from one fresh workspace after another (seed-upgrade) links each in a worker; otherwise every copy stays in the file's heap and a CI runner's heap runs out.git.ts,tmp.ts: temporary repositories and directories with cleanup. A test removes its own temporary folder withremoveTree(or leaves it totmpDir), not a barerm: on Windows a sandboxed test file's srt-win entries re-propagate through all of%TEMP%and hold each folder open while they do, and a bare removal then fails withEBUSY.removeTreewaits such a hold out.seed-upgrade-fixture.ts: a per-process initialized snapshot for immutable vintage inputs; each upgrade case gets independent physical workspace and manifest copies and unique import paths.claude-rules.ts: whether Claude Code would deny a path by an absolute rule, matched as CLI 2.1.281 does (node-ignore, case-blind) for the shapesclaude-permissions.tswrites.leftover-children.ts: the runners' per-file check for child processes left running (above).pe-image.ts: minimal Windows PE images naming the DLLs a test gives (import and delay-load tables, a machine type), for the package's Visual C++ runtime checks.failure-codes.ts: the analytics failure-code suites' hostile inputs (words, paths, Node codes and ids that must never reach an event property, thrown values that must read as no code) andcrossed, a failure carried across IPC as the app carries it (main'shandle, then the preload).processes.ts:running(pid), whether a process still runs. A test that proves a stop left nothing behind asks it, notprocess.kill(pid, 0), which also finds a process that exited but is not reaped yet.
Characterization so far: the api() keys and StudioCore surface (core-surface, rpc-surface),
the seed contracts the app keeps its own copy of (seed-contracts), spike snapshot/worktree
sequences (loop-sequences), snapshots of a user's own repository (snapshots), which loop runs a
run and the one Loop's calls, events, graph and journal on an Unreal game (loop-survival), the one Loop on a project of any kind (one-loop), which
Loop a run gets (one-loop-dispatch), a whole Loop through the real studio on a plugin's project
and on a folder with no plugin (one-loop-projects, L3), and the ten use cases of any project
(project-use-cases; a test marked todo names the phase that turns it green, and a marked test
whose body passes prints ✔ … # phase N: under --test-reporter=spec: that phase removes its
mark). Not yet: autopilot, gauntlet and facet-loop sequences, and golden studio:dev snapshots of
the app-basics, chat-history and run-controls fixtures; until then those paths rely on the rig
suites and the source gates in the allowlisted tests.
Fixtures (fixtures/)
harness-ok/ is a minimal harness, games/ holds code-shape samples, projects/ holds the
kinds of project Genex opens, toy-engine-plugin/ holds a made-up engine's plugin,
asset-previews/ holds format samples, transcripts/ holds recorded provider streams,
kept-seed/ holds Loop modules of an earlier seed as an agent may have kept them (.txt, so
nothing checks them as this tree's code). Keep fixtures small and synthetic.
Electron runners (e2e/)
run-*.mjs runners need a logged-in macOS GUI session and take 2–12 minutes. Run one with
npm run test:ui -- <name> (for example build-smoke, shapes-e2e, studio-ui); most need
npm run build first. They use disposable fixture profiles. run-provider-live.mjs,
run-bonsai-live.mjs and run-clean-provider-profiles.mjs touch live providers or accounts:
run them only with explicit permission. Evidence goes to .studio-dev/evidence/.
Windows suite
tests/windows-suite.json is the Windows CI's required suite
(verification). When a test file is meaningful on
Windows and passes there, add it, sorted; windows-suite.test.ts refuses missing, duplicate,
unsorted and rig entries. A file that changes the whole machine (a reservation of the sandbox's
proxy ports) is listed in RUN_ALONE in scripts/test-windows.mjs, which runs it after the rest,
one at a time. A POSIX-only case skips on win32 with its reason; don't drop the
file from the list for it. The informational fast-group report (a Windows dispatch with
backlog) lists the files still to fix and the clean ones ready to add.
Machine-dependent tests
Tests that read local projects or open the network are skipped unless opted in:
STUDIO_LOCAL_FIXTURES=1 for local projects, STUDIO_NETWORK_TESTS=1 for real network and
local Ollama probes (on Windows also Local Blender's and Godot's real downloads and sandboxed
jobs, blender-windows-live.test.ts and godot-windows-live.test.ts, and a Play game's reach to
Genex's API, windows-game-live.test.ts), STUDIO_GODOT_LIVE=1 for the Godot plugin against this Mac's own Godot
(godot-live.test.ts), STUDIO_CLAUDE_CLI_TESTS=1 for the real Claude Code CLI against
fake-anthropic.ts (claude-studio-shell-cli.test.ts, claude-tool-loading.test.ts, claude-steer-cli.test.ts),
STUDIO_CODEX_CLI_TESTS=1 for the real Codex CLI against fake-openai-responses.ts
(codex-sandbox-cli.test.ts), STUDIO_GROK_CLI_TESTS=1 for the real Grok Build CLI in the real
sandbox against fake-xai-responses.ts (grok-cli-live.test.ts; STUDIO_GROK_BIN names one, which
must sit outside ~/.grok: the test's sandbox denies the person's own Grok home). Never make a default test depend on this machine. STUDIO_RIG_UNSANDBOXED=1
runs rigs without the process sandbox, for a container where it cannot start (no user
namespaces); containment cases prove nothing there, and CI keeps the sandbox.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

