Repository navigation
EN Contribute Import Boundaries
Français · Type: reference · Audience: contributor · Context: engine repository · Status: ready · Applies from: 4.1.14
What each folder of src/engine/ may import, where each responsibility of the engine, the player and the solver
lives, and what is public. The source is src/engine/BOUNDARIES.md;
tests/boundaries.test.ts checks the rules on every run of the unit suite.
feature since 3.9.0
| Layer | Folder | May import | Never |
|---|---|---|---|
| Core | core/ |
itself, plain packages (zod/mini) |
the DOM, tools, dev, minigames, the Studio |
| Player |
dom/, minigames/, ending/, boot.ts
|
core, each other; tools/i18n (locales at boot); tools/replay and dev/ only through import()
|
the solver, the validator, the linter, any other tool, the Studio, tweakpane |
| Scene |
scene/ (4.1.11) |
core (the painter's specs as types only) | the DOM, tools, dev, the Studio, a painter |
| Reality |
reality/ (4.1.1) |
core, plain packages (zod/mini); WebCrypto |
the DOM, tools, dev, the Studio, the Bridge (bridge/) |
| Tools | tools/ |
core | the DOM (they run in Node, workers and tests) |
| Dev | dev/ |
anything | being imported statically by the player |
Outside src/engine/, the test also holds two rules of 4.1.1: the engine never imports the Bridge (Biscuit, keys
and the server stay out of every game), and the Bridge reaches neither the Studio, the tools, nor a game: only the
protocol it shares with the player.
Guarantee ·
core-imports-no-dom· referenced · scope self-checked by the author (AI), not reviewed The core imports none of the engine's other layers: no DOM layer (dom/), no tools, no dev code, no minigames, noending/, no Studio. A static import that breaks this fails the unit suite. The check reads the import statements of the files; it cannot see a module reached through a global or aneval.
The check does not sort packages: keeping the core's packages plain is left to review.
-
The player's first visit is held to
assetBudgets.initialJsKB(npm run verify:dist): the minigames load when one starts (minigames/meta.tskeeps what the tools read of them), the dev panel and the Studio on demand. -
A painter (
dom/render-*.ts,dom/renderer.ts,dom/frame-renderer.ts) never imports the engine, its ports or its runtime modules, not even as a type (4.1.11, D21): it is given frames and specs, and answers with intentions. -
No cycle of static imports anywhere in
src/engine(4.1.0): a module never imports itself back. Types (import type) are erased and do not count.
A new folder under src/engine/ belongs to no layer of the test until one is written for it: add it to
BOUNDARIES.md and to tests/boundaries.test.ts together.
feature since 4.1.0
Engine (core/engine.ts) is the facade: its state, its lifecycle (new game, load, checkpoint) and one forwarding
method per operation, in the same order of effects as before the split. What each operation does lives in a module of
its own, a function taking the engine as its first argument:
| Module | What it does |
|---|---|
core/session-runtime.ts |
the session: entries opened and closed, the answers recorded, digests, replay's feed |
core/event-runtime.ts |
emit: scripts waiting for the event, then the room's listeners, then the game's |
core/script-runtime.ts |
scripts: their state, one step, loops, the scheduler |
core/interactions.ts |
the rule, kind or fallback that answers an action; lines, hints, the talk loop |
core/command-runtime.ts |
exec and step: running Cmds, each through its handler in core/command-handlers.ts (4.1.5); where a command points in the room |
core/world-queries.ts |
names, kinds, visibility, prop states, targets, approach points |
core/players.ts |
several playable characters: who is where, switch, swap, transfer |
core/movement.ts |
walking, entering a room, the map and its travel, a teleport (4.1.1) |
core/reality-runtime.ts |
a signal from outside: applied at most once, the cursor, the session entry (4.1.1) |
core/engine-shared.ts |
the context of a command, the journal's entry, small helpers |
core/journal.ts |
the semantic journal (4.1.11): what happened, in ids, numbered; emitted by the core alone |
core/busy.ts |
the busy owner (4.1.11): runs in progress, the tutorial step waited for, a skip |
core/run-clock.ts |
the run clock (4.1.14, ADR 0016): logical steps and time, told by the session and the commands; it never writes the state |
core/prng.ts |
the seeded generator (4.1.14): xoshiro128**, a stream per purpose; engine.random draws from logic
|
core/run-tape.ts |
a run's links (4.1.14): each entry with its events and the clock after it, the same live and replayed |
core/journal-chunks.ts |
the run's chunks chained by SHA-256 (4.1.14), written to a ChunkStore, read back checked |
core/types/*.ts |
the content format by subject; core/types.ts re-exports every name |
The modules import Engine as a type only; tests/core-runtime.test.ts calls each directly.
feature since 4.1.0
App (dom/app.ts) is the orchestration (4.1.11): its state, the constructor, and the composition of the engine, a
Presenter (dom/presenter.ts) and the room view's renderer. The rest lives in modules called through forwarding
methods, as in the core:
| Module | What it does |
|---|---|
dom/presenter.ts |
the Presenter the engine talks to (4.1.11): the scene's calls, lines, overlays, minigames, the ending; intent(), the one door of the player's input |
dom/room.ts |
the scene model: entities, walking, the camera; it makes the SceneFrame (scene/frame.ts) and paints it |
dom/room-stage.ts |
a room's stage for the painter: conditions evaluated, images placed on the backdrop (4.1.11) |
dom/frame-renderer.ts |
a painter (DOM or Canvas) as a Renderer: whole frames, an unchanged one skipped, a changed one by its differences |
dom/shell.ts |
the shell's elements, their layout for the screen, the accessible targets (from the frame's targets) |
dom/side-fit.ts |
the phone column's fit (pure): verb and slot heights that keep the tools row on a short screen |
dom/input.ts |
verbs, the inventory bar, taps and double taps (verbFor, nearMiss), the keyboard, the action line |
dom/speech.ts |
lines with their voice, the transcript, phone calls, the choice of responses |
dom/map-view.ts |
the map and the travel animation |
dom/menus.ts |
title, pause (and the session export, through import()), save slots, restart, credits |
dom/settings.ts |
the player's preferences, their defaults and menu |
dom/update.ts |
the offline warm-ups and status, the update offered after a verified save |
dom/storage.ts |
the localStorage autosave and slots (when IndexedDB is missing) |
dom/app-shared.ts |
small helpers (element factory, tap timings, the FPS meter) |
dom/reality-ui.ts |
the world link (4.1.1): pairing, status, the client; loaded by import() only for a game with reality
|
dom/run-store.ts |
the runs' IndexedDB store (4.1.14, web-scumm-runs): chunks and heads in one transaction, local records |
dom/speedrun-ui.ts |
the speedrun mode (4.1.14): the recorder on the app's engine, its timer, records, ghost, export; loaded by import() (it reaches tools/speedrun/ the same way) |
feature since 4.1.0
tools/solve.ts re-exports what it exported before; the solver lives in tools/solve/:
| Module | What it does |
|---|---|
src/engine/tools/solve/search.ts |
solve(): the frontier, the proof workers, termination and the verdict |
src/engine/tools/solve/expansion.ts |
makeExpander: every action worth trying from a state, run on the real engine; the no-op memo |
src/engine/tools/solve/abstractions.ts |
what a state is made of (dimensions), the canonical forms (players, mobility, ownership), dominance |
src/engine/tools/solve/model.ts |
options, SearchNode, Expansion and a transition (TryRecord), with their invariants |
src/engine/tools/solve/scenarios.ts |
signals from outside in a search: closed, a scenario, adversarial (4.1.1) |
src/engine/tools/solve/report.ts |
the result, its profile, the profile as text |
src/engine/tools/solve/drive.ts |
an engine promise awaited, the guided tutorial's steps played meanwhile |
src/engine/tools/solve/explosion.ts |
the explosion profile (4.1.13): the states attributed to positions, inventories, flags, dialogues, scripts |
src/engine/tools/solve/search/compact.ts |
the store of the states seen (4.1.13, ADR 0015): by index, interned keys, parents, paths and session entries |
src/engine/tools/solve/search/checkpoint.ts |
a search written down and taken up again (4.1.13): snapshot, header, fingerprint |
src/engine/tools/solve/search/classify.ts |
the verdict of a proof over the stored states: reverse reachability, softlocks and their causes |
src/engine/tools/solve/search/dominance.ts |
dominance, symmetric items, independent sub-puzzles (4.1.13) |
src/engine/tools/solve/search/partition.ts |
the workers' shared visited table, the partition of a batch and work stealing (4.1.13) |
The path of a proof reads solve() → solveOnce() (search) → makeExpander() (expansion) → the engine's act() →
a TryRecord merged into the store and the frontier → the verdict.
No file of src/ is over 800 lines but the exceptions tests/file-size.test.ts lists with their reason, each capped
at its size: an exception never grows, and leaves the list once under the limit.
Public, and held to semantic versioning: the five entries of src/engine/api/, published as quest-n-click/content
(the types and defineGame), quest-n-click/player (boot), quest-n-click/minigames, quest-n-click/testing
(Engine, the fakes, the save envelope, solve) and quest-n-click/reality (since 4.1.1); the content format, the
save envelope and the MCP tools. They are held by tests/api-surface.json and the support policy
(Stability and support, Public API).
Internal: the modules behind the Engine and App facades (their members marked @internal), the solver's modules,
the tools' code. They may move between minor versions.
-
npm run verify:dist(the first visit's budget),tests/boundaries.test.ts,tests/file-size.test.ts,tests/api-surface.json. - Architecture, Code tour.
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