Repository navigation
EN Contribute CI
Français · Type: reference + troubleshooting · Audience: contributor · Context: engine repository · Status: ready · Applies from: 4.5.0
What GitHub Actions runs on the engine repository, why a job ran or said "not needed by the plan", and what to do when
one is red. The workflows are in .github/workflows/; the plan that decides what a
pull request runs is tools/ci-plan.ts. Which test suite runs in which job is
Which tests run when.
| Workflow | Starts on | Does | Gates |
|---|---|---|---|
ci |
a pull request; a push to main; a v* tag; by hand (pages-only) |
the three tiers below, then Pages on main
|
the pull request (pr-gate); a release (the tag's run) |
candidate |
by hand on main for a SHA (gh workflow run candidate --ref main -f sha=<full sha>); a pull request labelled full-ci (information only) |
every heavy family on one exact SHA, then candidate-gate, which writes and attests candidate-manifest.json
|
a tag must name one green run of it (Releasing) |
release |
the completion of ci on a v* tag |
the mutation sets, release-check:ci, the release made from the candidate's files, ship verify; then docs-publish (4.5.0) |
publication |
nightly |
every day at 03:17 UTC; by hand | npm names, the heavy suite, the connectors' fuzz (a minute each), the abstraction corpus (500 seeds, four shards), every mutation set from scratch, the Bridge's loads on SQLite and Postgres, the proof matrix, cross-runtime with 500 Remix seeds, the worker in a container | nothing directly; a red night is a bug to fix before the next release |
prove |
every Monday at 04:00 UTC; by hand (game, rooms) |
prove:game, the committed playtests (--strict), and the bench on a 100-room generated game (uploaded as bench) |
never a gate |
mutation |
by hand: gh workflow run mutation --ref main -f set=<set> -f ref=<branch or SHA> [-f file=<path>]
|
one mutation set, measured on a runner, its report kept as an artifact | nothing |
qualify |
a pull request or a push to main touching ops/, scripts/ops-qualify*, scripts/pack.mjs, bridge/, package.json or the lockfile; by hand |
npm run ops:qualify: the Bridge's qualification profile on Docker |
the profile does not rot between candidates |
docs-publish |
called by release after ship verify; by hand (revision, rollback, promote, preview) |
the wiki and the publication record (4.5.0) | publication of the documentation |
feature since 4.1.9
The fast tier, on every change. plan reads the diff; check and coverage run beside it:
-
check: on a pull request,changes -- --check(the fragment, Conventions) andfield:carry -- --check-range(no carried pass changes its trust root); thenquality(format, lint, knip, both TypeScript configurations, content lint),docs:truth, ffmpeg,build:game(the sample game's gates, the bundle,verify:dist, the spoiler check, the asset audit),weight -- --release,quality:baseline -- --check --dist,prove:game,audit:depswhenpackage.jsonor the lockfile moved, then the two-entry build (game and Studio demo) that the e2e rows play, kept as thedistartifact; onmainit also assembles Pages'/docs/from the released documentation archives. -
coverage: the unit suite once, under V8 coverage (test:coverage), then the coverage ratchet: a warning on a pull request, a failure onmainand on a tag (The coverage ratchet).
The second tier, what the change can break. Each job needs plan (most also check) and reads its gate in the
plan: it runs its real work, or one step that says "not needed by the plan" and succeeds.
| Job | Gate | Runs |
|---|---|---|
node-24 |
node24 |
the unit suite on Node 24 |
windows |
windows |
the doctor, the type checks, the unit suite without the files that assume POSIX, build:game, the production server answering |
e2e (six rows) |
e2e |
the production build played by touch: Chromium full, WebKit generic, Chromium and WebKit at the keyboard, Chromium in French, Chromium with the Canvas painter; with weight, music, visual, perf, Studio, accessibility and PWA steps on some rows |
pwa-firefox |
pwaFirefox |
the PWA scenario in Firefox (install, update, interrupted update, reinstall, offline) |
reference (Chromium, WebKit) |
reference |
the reference chapter built, proved, played at the keyboard, in French, against its visual references, at 30 fps or more with the CPU slowed 4×; and the heroes example |
second-game |
secondGame |
a game made by npm run new-game, through every gate the sample passes |
fresh-install |
freshInstall |
the engine packed, a game created outside the repository, installed, built and played |
external-consumer (Ubuntu, macOS, Windows) |
freshInstall |
the archives installed outside the repository on three systems |
upgrade |
upgrade |
a game of the previous release moved to this engine, its old save played to the end |
reality-xcheck, connectors, bridge-postgres, reality (Chromium, WebKit) |
reality |
Biscuit's samples in JavaScript and Rust, the connectors against a real Bridge with their fuzz, the Bridge on Postgres 16, the signals game end to end |
studio-hosted |
studioHosted |
the Studio Server on Postgres and S3 (SeaweedFS) with a real Keycloak, then the hosted Studio in Chromium and Firefox |
cross-runtime |
none (every change) | the same canonical text, speedrun proofs and Remix worlds in Node, Chromium, WebKit and Firefox |
The third tier, off the pull request path: the mutation sets on a pull request labelled full-ci, the nightly,
the candidate and the release.
pr-gate reads every job's result: each must be success; the mutation jobs may be skipped where they do not
run. It is the one check that sums a pull request up.
pages, on main only, after a green pr-gate: deploys the game, the Studio demo and /docs/ to GitHub Pages.
feature since 4.1.9
# in the engine repository, on your branch
npm run ci:plan # against origin/main
npm run ci:plan -- --base=<ref>
npm run ci:plan -- --files=src/engine/dom/room.ts,games/demo/rooms/garden.tsIt prints, on stderr, one line per changed file with the rule that matched and the gates it opened, then the plan;
on stdout, one line of JSON ({"auditDeps":…,"node24":…,…,"all":…,"docs":…,"docsPages":[…],"pagesOnly":…}), which
the plan job writes to its output. The first rule that matches a path wins, and a change runs the union of what its
files ask:
| A change to | Opens |
|---|---|
.github/workflows/ci.yml, tools/ci-plan.ts, package.json, the lockfile, a shared configuration (tsconfig*.json, vite.config.ts, vitest*.ts, biome.json, knip.json, requirements.txt, .nvmrc, .gitattributes), the app shell, tools/vite/
|
everything |
docs/, changes/, wiki/, any .md, LICENSE*, .claude/, .cursor/, clevercloud/, another .github/ file |
the fast tier only |
| the Reality runtime |
reality, e2e, node24, windows
|
| the painters, the music director |
e2e, reference, node24, windows
|
the PWA and the storage (boot.ts, dom/update, offline, save-store, storage) |
e2e, pwaFirefox, upgrade, node24, windows
|
any other file of src/engine/ (the core) |
everything |
src/studio/ |
e2e, studioHosted, node24, windows
|
bridge/ |
reality, freshInstall, node24, windows (and studioHosted for its SQL layer) |
games/demo/ |
e2e, reference, node24, windows
|
games/reference/, games/heroes/
|
reference, node24
|
games/_template/, cli/, scripts/{pack,fresh-install,external-consumer,new-game}.mjs
|
secondGame, freshInstall, upgrade, node24, windows
|
studio-server/ |
the authoring gates and studioHosted
|
other tools/ and scripts/
|
the authoring gates (node24, windows, secondGame, freshInstall, upgrade, reference) |
tests/ |
node24, windows
|
| a path no rule knows | everything |
A git error runs everything too: the plan never decides that it does not need to be checked. docs is true when
the change touches the documentation, its generators, or a file a wiki page rests on (a sources glob of
wiki/manifest.json); docsPages names those pages, to reread. It opens no job: the fast tier runs the doc tests on
every change.
On main, on a tag and on a pull request labelled full-ci, the plan is --all: every gate opens. The label also
starts the mutation jobs of ci and a candidate run for information. Add the label, then push (the label applies to
the next run).
Applies from 4.5.0 · feature since 4.5.0
docs-publish ends by gh workflow run ci.yml --ref main -f pages-only=true. The plan is then --pages-only: no
gate opens, and check, coverage and cross-runtime skip everything but the Pages build, /docs/ and the upload.
A dispatched run cancels no running run: it waits. GitHub keeps one pending run per concurrency group whatever
cancel-in-progress says, so a dispatch queued while a push's run on main is pending replaces it (that commit is
then deployed by the dispatch without its own checks), and a later push replaces a pending dispatch.
Limit ·
pages-fail-closedIf/docs/cannot be assembled from the released archives (a network failure, an archive refused), thecheckjob fails onmainand Pages is not deployed: never a site without/docs/nor with an unchecked one. A rerun of the job is the recovery.
-
Read the plan's summary in the
planjob (or runnpm run ci:planlocally): it says why each job ran.
-
Reproduce locally, in the engine repository, with the job's own command:
Red job Run locally checkthe failing step: npm run quality,npm run docs:truth,npm run build:game,npm run quality:baseline -- --check --dist(afternpm run build:web),npm run prove:game,npm run changes -- --checkcoveragenpm run test:coverage(a test, or a floor ofvite.config.tsnot met)node-24npm run test:nodeunder Node 24e2e,reference,second-gamenpm run build:game,npm run preview -- --port 5173 &, then the row'snpm run e2e -- http://127.0.0.1:5173/ --game demo --prod …(E2E_BROWSER=webkitfor a WebKit row)fresh-install,external-consumer,upgradenpm run fresh-install,npm run external-consumer,npm run upgrade-check -- --from=previousmutation (<set>)npm run test:mutation:core -- --set=<set>(Mutation testing)A failed e2e row uploads its screenshots as an artifact: read them first.
- Check the known flakes below before rerunning. A rerun of a red job that is not a known flake hides a bug.
- Fix, push, read
pr-gateagain.
| Symptom | Where | What is done | Since |
|---|---|---|---|
WebKit's Context is stopped (or Cache API operation failed: Context is stopped) after every check passed |
e2e:pwa and e2e on WebKit, during the teardown |
Reported as a warning ("reported, not counted"), only on WebKit, only in that exact form and only after every check passed; any other browser error still fails. Seen on #111, #118 (13 Oct 2026) and #139 (18 Oct 2026) | 4.1.20 (e2e:pwa), 4.2.1 (e2e) |
The Firefox pass of e2e:studio-hosted timed out at step 6d (Prepare assets) |
studio-hosted |
A real bug (a late status poll overwrote the panel), fixed in 4.3.0 (#210). If it comes back, it is a regression, not a flake | fixed in 4.3.0 |
apt-get update hangs for many minutes on the runner's Ubuntu mirror |
every job that installs ffmpeg |
scripts/ci-ffmpeg.sh: apt bounded to four minutes an attempt, then a static ffmpeg from GitHub's CDN (BtbN/FFmpeg-Builds); release.yml carries the same logic inline. Install steps have 20 minutes. Seen on 7 Oct 2026 |
4.1.15 |
toomanyrequests pulling an image from Docker Hub |
bridge-postgres, mutation, the nightly and the candidate's services |
Images pulled from mirror.gcr.io at the same digest. Seen on two jobs on 9 Oct 2026 |
4.1.18 |
npm ci or pip install fails on a network error |
any job | Every install step is tried three times, 15 s apart | — |
| WebKit cannot navigate offline under Playwright |
e2e:pwa WebKit, reality WebKit |
--allow-skip: that step reports "skipped", never counted as a proof; a person checks Safari offline before each release (Field passes) |
3.1.1 |
Limit ·
windows-not-requiredThewindowsjob runs the unit suite without the files that assume POSIX; it is not a required check of the ruleset until the maintainer adds it.
-
npm run ci:plan, thefull-cilabel,pr-gate, thepages-onlyinput. - Which tests run when, Before a pull request, Releasing, Mutation testing.
Generated publication · publication générée — current documentation · documentation courante: quest'n'click 4.4.0 r1, documentation revision · révision de la documentation 8dc717c69acb62c4742b69c54a7e7dfb620f75d8.
Earlier versions and permalinks · versions précédentes et liens permanents: https://wanoo.github.io/quest-n-click/docs/
An edit made in this wiki is overwritten at the next publication · une modification faite dans ce wiki est écrasée à la publication suivante.
Edit the source · Modifier la source · Report an error · Signaler une erreur
Index (6)
Start (6)
Play (9)
Install (17)
- Requirements
- Install from the release archive
- Install from npm, once published
- Install from the repository to work on the engine
- doctor: checking your machine
- Image toolchain
- Audio toolchain: ffmpeg, fluidsynth, Furnace, uv
- Upgrade
- Upgrade notes: 4.4
- Upgrade notes: 4.3
- Upgrade notes: 4.2
- Upgrade notes: 4.1
- Upgrade notes: v3
- Upgrade notes: v2 to v3
- Coming from web-scumm
- Package reference
- Install troubleshooting
Create a game (55)
- Your first game
- Layout of a created project and of the engine repository
- The working loop
- Content principles and the identity contract
- Rooms
- Geometry: placement, walk zones, masks, layers, camera
- Something is visible but unreachable
- Reactions
- Game commands
- Conditions
- Flags, variables and events: which to use
- Custom code
- Characters
- Items and inventory
- World map
- Dialogues
- Scripts and events
- Moving characters: patrols and walks
- Exits
- Chapters and objectives
- State and saves: persistent or temporary, renaming an id, migrations
- Staging: wide rooms and animations
- The stage: lights, particles, floors
- Skin and fonts
- Title and credits
- Heroes: several characters and hero choice
- Built-in minigames
- A custom minigame
- Translations
- Music in stems
- Sound effects
- Voices: per language and per hero
- Images: prompts, cutting sheets, transparency, scale
- Asset provenance
- The storyboard, source of truth
- Puzzle design
- Classic mechanics
- Review pages
- DSL reference
- Checking your game
- What the solver proves
- Solver options
- Playtests
- Remix
- Speedrun for authors
- The sealed ending
- Production template
- Example games
- Working with an AI
- Build and release a game
- Publish on GitHub Pages
- The static game on Clever Cloud
- Other static hosts
- Sub-path, cache and service worker, incomplete deploys, going back
- Testing on a phone over the LAN
Local Studio (24)
- The local Studio: overview and launch
- Edit a room
- Placement and stage
- Preview, apply, undo
- Storyboard
- Assets and cutting
- Check: validator, solver, critical path, heat, health, coverage
- Before and after captures
- Semantic diff
- Play and replay a session
- Rule explainer
- Language and objectives
- Voices and the heroes × languages matrix
- Map
- Notes
- Remix in the Studio
- Music
- The Assistant: bring your own key
- Demo mode and studio-apply
- Local and LAN security
- Studio API
- Local MCP: setting up each client
- MCP tools
- Studio troubleshooting
Team Studio (21)
- What runs where
- Concepts: revision, transaction, span, lease, preview, build
- Starting as an invited dev
- Working together day to day
- Roles and actions: the full matrix
- Invitations
- Managing members
- Write refused on the hosted Studio: stale base revision (409)
- Write refused on the hosted Studio: span locked (423)
- Recovering after a lost lease, a disconnection or a stale preview
- Comments
- Map and semantic diff
- Publishing builds
- Remote MCP
- The game in Git
- Upgrading the engine of a hosted game
- Hosted assets
- The server's command line
- Health and metrics routes
- Trying it locally with compose.yml
- Known limits
Clever Cloud (23)
- Clever Cloud: overview, cost and prerequisites
- Apps and add-ons
- Domains and TLS
- Keycloak
- Generic OIDC and GitLab
- Configuration
- First deployment
- Backups
- RPO and RTO
- Restore the Studio on a fresh installation
- Redeploys
- Upgrading the server and checking state after a migration
- Limits of going back
- Monitoring
- Security
- Rotating keys
- Recovering admin access
- Changing domain or OIDC provider
- Worker, PostgreSQL or Cellar down
- Exporting the game and leaving the installation
- Retention
- Clever Cloud troubleshooting
- Costs and teardown
Reality Bridge and connectors (16)
- The Reality Bridge: what it is
- Quick start
- Guarantees
- Install and run the Bridge
- Backup and restore
- Several tenants
- Signals and the manifest
- The Bridge's command line
- Connectors overview
- Email connector
- Telnet connector
- SSH connector
- Open Badges connector
- The connector SDK
- Security: Biscuit and signatures
- Bridge and connector troubleshooting
Contribute (25)
- Welcome
- Developer setup
- The dev loop
- Before a pull request
- Conventions
- Writing documentation
- Architecture
- Code tour
- Import boundaries
- Which tests run when
- Mutation testing
- The coverage ratchet
- The quality baseline
- CI explained
- Field passes
- Benchmarks
- Releasing
- npm packages
- Decisions and ADRs
- Governance
- Bot pull requests
- Contributing with AI agents
- Security policy
- Code of conduct
- Licences and credits