Repository navigation
EN Install Upgrade Notes V2 To V3
Français · Reference · Published, reviewed by a person · Applies from: 3.0.0
These are the notes written for 3.0.0, when v3 broke the authoring contract once (authoring schema 2 to 3). They are kept, unchanged, for a game still on authoring schema 2: a game written before 3.0.0, or a 4.1.x game that never opted in. They do not describe a step of a current upgrade.
- Today the automatic part is one command. In a created project,
npx quest-n-click migratesees schema 2 and runsids --write --map(step 2 below) for you; in the engine repository it isGAME=<id> npm run migrate. The three lines ofgame.ts(step 2) stay yours. Upgrade gives the whole procedure. - A game on a hosted Studio is upgraded by its owner through the engine upgrade (
POST /api/engine/migrate), see Upgrading the engine of a hosted game. - The commands below are written as they were in 3.0.0, for a game inside the engine repository (
GAME=<id>). Some have changed since:npm run buildno longer runs the pixel tests (4.1.6), the namesweb-scummbecamequest-n-click(4.2.5, removed in 4.3.0). The later notes say when: 4.1, 4.2, 4.3.
The original introduction:
v3 deliberately breaks the authoring contract once so saves can become durable afterwards. Migrate on a branch, keep a representative v2 save, and do not change prose or reorder content until the ids below have been assigned.
Audience, context, and the statuses of what this page rests on
Audience: author · Context: created project
On the last v2 commit, export saves at important checkpoints and keep one complete session. Record:
GAME=<id> npm run validate
GAME=<id> npm run solve
GAME=<id> npm testDo not commit private game material or exported player saves to this public repository.
Add schemaVersion: 3 to defineGame({...}). compileGame clones and normalises the source; the compiled v3 value is
frozen, so integrations must not rely on engine.game === source or mutate it after construction.
Let the tool write the ids, then review them:
npm run ids # dry run: what would be written, what must be done by hand
npm run ids -- --write --map # writes the ids into rooms/*.ts, rules.ts, game.ts; renames locales/*.json keys;
# writes ids.migration.json (renameSeen / renameCounter) and ids.paths.jsonIt names things after their content (house.open-pantry, house.grandma.where-is-the-key,
house.open-pantry.once, clock.wait), uniquely across the game, deterministically. What it needs on every room
and game Rule, TalkTopic, Choice, EventRule, once / nth / cycle / random block: an id; on every
script: one stepIds entry per top-level command. Lists built by code (a spread, a .map(...)) are skipped and
reported with the id the engine expects: add it in the generator. Then the three lines by hand in game.ts:
schemaVersion: 3, saveVersion + 1, migrations: [idsMigration] with import idsMigration from './ids.migration.json'. npm run validate refuses a v3 game with a missing or duplicate id; npm run ids can run
again at any time (it never renames twice). Generated exit rules receive deterministic ids automatically.
The browser stores a web-scumm-save envelope with schema 3 in IndexedDB. The first v3 run imports the legacy
<game>.save localStorage autosave once and removes it only after a verified write. Manual slots (saves.slots) live
in the same database, as envelopes, verified the same way; the v2 <game>.slot.<n> entries are imported once too. A
file imported from the save menu also lands in the first free slot.
Increase saveVersion for a state change and supply one Migration per integer step. Besides v2 fields, v3 supports:
migrations: [{
from: 2,
renameCounter: { 'house:on3.0': 'pantry.first_open' },
renameSeen: { 'topic.house/grandma[0]': 'topic.grandma.ask_key' },
renameScript: { old_clock: 'clock' },
renameScriptStep: { clock: { 'step.1': 'chime' } },
renamePlayer: { kid: 'laverne' },
renameCharacter: { old_grandma: 'grandma' },
dropCounter: ['temporary_gag'],
dropSeen: ['removed_choice'],
dropScript: ['removed_patrol'],
}],Map positional v2 counter/topic/script keys only when the old content and its meaning are known. There is no universal safe conversion after content has already been reordered or translated. An unmapped stale optional reference is pruned with a player-visible warning; malformed JSON, a foreign game, a missing current room or an unknown active player is rejected without replacing the current session.
In v3 the translation paths name things by id (room:house/on.house.open-pantry.do[1], talk.grandma.<id>.topic,
.choice.<id>.text, events.<id>.do); npm run ids -- --write renamed the existing tables (ids.paths.json holds
the map). Run npm run i18n -- extract --lang <xx> for every shipped language. v3 also extracts verb labels/join words and the
text paths declared by each minigame's textParams. Then run npm run i18n -- status and translate every new entry.
Custom minigames should declare required and textParams so validation and translation tools understand their
parameters. Asset ids keep the existing sheet/cell convention and are discovered by the asset tools.
-
npm run devandnpm run studioare loopback-only. - Use
dev:lan/studio:lanfor a phone and open the printed token URL. -
npm testis the Node suite;npm run test:assetsis the Python-backed asset suite. -
npm run buildrequires validation and a winning witness, but not an unbounded state-space proof. -
npm run prove:gameproves global and chapter state graphs and fails on softlocks or truncation. -
npm run release-checkincludes prerequisites, build, exhaustive proof and dependency audit.
Do not enable a partial-order reduction in proof mode until equivalence with the reference exploration is demonstrated for the relevant game class.
GAME=<id> npm run doctor
GAME=<id> npm run build
GAME=<id> npm run prove:game
GAME=<id> npm run e2e -- http://127.0.0.1:5173/ --prodLoad every representative v2 save and verify its room, active player, inventories, persistent choices and script step.
Reorder one rule, topic, choice and script step in a test fixture; the same v3 save must retain its meaning. Finally,
test the production PWA online, offline in a room never visited (npm run e2e:pwa does it), and through an update.
The whole game is cached after the first visit unless the game says offline: 'nearby' (decision D5).
What migrates on its own. The v2 autosave is imported into IndexedDB on the first v3 launch and verified before
the old key goes. A save that names something the content no longer has is pruned with one toast (ui.saveAdjusted),
never refused. Without an id, a once / nth / cycle / random block keeps its positional v2 key, so v2 counters
survive. The solver's witness is unchanged (the private reference game: 59 actions, 355 states, 0.3 s on both).
| v2 | v3 |
|---|---|
npm run dev listens on the network |
npm run dev listens on 127.0.0.1; npm run dev:lan / studio:lan print a one-session token URL for the phone |
npm test runs everything |
npm test = Node tests; npm run test:assets = the Python-backed image tests; npm run check = tsc + Node tests |
npm run build = tsc + tests + vite |
npm run build = check + test:assets + verify:game (validate, solve, --chapters, i18n status) + vite + spoilers + asset audit |
| — |
npm run prove:game = --prove and --prove --chapters, the exhaustive softlock gate, run by release-check, never by build
|
npm run audit |
npm run audit (assets, private names) + npm run audit:deps (npm audit, production deps) |
| — |
npm run doctor, npm run e2e:smoke, npm run e2e:pwa, npm run release-check
|
Solver exit codes. 0 solved and no broken invariant; 1 unsolved, softlocks, errors or a broken invariant;
2 truncated. --json gains status, mode, softlocks, assumptions; the human output gains one line after the
verdict (Witness status: / Proof status:), everything else is unchanged.
| Where | Field | Used by |
|---|---|---|
a rule in on (room or game) |
id |
saves, the puzzle graph, the solver's heatmap (rule:<id>) |
a choice option |
id |
once choices in saves, translations, voice files |
| a talk topic | id |
seen topics in saves, translations |
a listener in events
|
id |
once listeners in saves |
once / nth / cycle / random
|
id |
their counters in saves (v2 key still read, deprecated) |
| a script |
stepIds, one per command of do
|
a save resumes at the named step after a reorder |
New ui keys (English defaults when absent): saveFailed, saveAdjusted, updateAvailable, updateNow, advance, offlineStatus, offlineComplete, offlineRetry (3.1.1: the pause menu's offline row)
(3.1, the "tap to continue" marker for screen readers), shareSession (3.1, the playtest row of the pause menu).
Generated publication · publication générée — current documentation · documentation courante: quest'n'click 4.5.3 r1, documentation revision · révision de la documentation b061c4ae6fbeb0be47a11ba8a442ba7e23ecb0a1.
Latest documentation · dernière documentation: https://quest-n-click.cleverapps.io/docs · https://quest-n-click.cleverapps.io/fr/docs; earlier versions · versions précédentes: each release's quest-n-click-docs-<version>.tar.gz · l'archive quest-n-click-docs-<version>.tar.gz de chaque release, https://github.com/Quest-n-Click/quest-n-click/releases
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 (18)
- Requirements
- Install from the release archive
- Install from npm
- 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.5
- 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