Repository navigation
v4.1.12
"Language": the programme's fifth release. The game's logic as plain data (GameIR, deterministic, with
the file and line that writes each id), a fingerprint in four SHA-256 (logic, trusted extensions, presentation,
engine) that the pause menu shows and the build seals, one canonical text per value (canonicalJson, held to fifty
edge values in Node, a script written to compare them in three browsers, not yet in CI), objectives and the quest journal (the one primitive admitted,
with its ADR; every other candidate refused with its proof), forms generated from the schemas in the Studio, the DSL's
reference generated from them, and the DSL stabilised until Remix freezes it. Measured against 4.1.11 in
docs/dev/baselines/4.1.12.md; what this release does not do is in the LOG and the passes sheet
(docs/dev/passes/4.1.12.md).
Breaking
- The pause menu's fingerprint row in every game (4.1.12). A game whose release language is not English shows its
English default ("Build") until it addsui.fingerprint(andui.objectiveswhen it declares objectives) to its
uiand its translation tables; the release-language e2e (npm run e2e -- --lang xx) fails on a visible default.
The sample game and the reference chapter carry both, in English and French (UPGRADING §24).
Changes
-
Objectives and the quest journal (4.1.12, ADR 0014). A game may declare
objectives(title,done,
optional,parent). The pause menu lists them, each step under its parent, ✓ done or ○ open; the semantic journal
saysobjectiveCompletedonce, right after the event that completes it (even inside a cutscene, before what
follows, the autosave and an ending), never again in the session, and silently for what already holds when a game
starts or loads;npm run solve -- --goal=100%searches for a state where every objective that is not optional
holds at once. The validator refuses an objective whosedonecan never hold (naming a custom command without
declaredeffects), an unknown parent and a cycle of parents, and warns about adonethe content can take back.
The flag and item handlers now change the state before they journal it. The sample
game and the reference chapter declare five each, translated into French. The save format does not change. -
The game's intermediate representation (4.1.12, ADR 0013).
compileIRturns a compiled game into its logic as
plain data (rooms, entities, rules, scripts, objectives, Reality policies, the world, the trusted extensions by name,
a variant slot reserved for 4.1.15), deterministic, with thefile:linethat writes each id.npm run ir -- --game <id> [--json]prints it; the Studio's new Language tab shows it with the objectives; MCP's newget_irreturns
it. Every field of a game, a room and an entity is classified logic, presentation, both or tooling in one table the
compiler checks. The runtime, the solver and the replay keep reading the compiled game. -
The game's fingerprint (4.1.12, ADR 0013). Four SHA-256 computed with WebCrypto:
logic(the IR),
trustedExtensions(the game's code beside its content, hashed by the build),presentation(decors, sprites,
sounds, interface texts and the asset manifest) andengine(its version). A rule changed moveslogiconly, a
decorpresentationonly, a custom command's codetrustedExtensionsonly. The pause menu shows the short form
(ui.fingerprint, "Build" by default); a build writessite.jsonwith the trusted extensions' hash and the
engine's version, whichnpm run verify:distexpects. -
One canonical text per value (4.1.12).
canonicalJson(NFC, sorted keys, no-0, big integers as decimal
strings, anything lossy refused) is held to fifty edge values in Node;npm run e2e:canonicalcompares them in
Chromium, WebKit and Firefox (written in this lot, not yet in CI). The solver's proof cache is keyed by it: the
entries of earlier versions are not reused. -
The Studio writes objectives (4.1.12). Their form is generated from their schema (each field with its
description); a value is checked before it is sent, and the validator's errors come back named by file, id and
field; the diff is previewed before the write and Undo takes it back. MCP'sset_valuewrites them in the game file
withid: "@game";list_roomsshows them. -
The DSL's reference is generated (4.1.12, D22).
docs/en/DSL.mdanddocs/fr/DSL.mdlist every condition,
every command with its shape, the objectives' fields and how each field counts for the IR, from the schemas
(npx tsx tools/dsl-doc.ts, held by a test). The DSL is stabilised:docs/dev/DSL-STABILITY.mdsays what is
stable, what may still grow until 4.1.15, and the candidate primitives of the programme with the proof that admitted
or refused each (objectives admitted; no Reality nor stage primitive needed). -
API (4.1.12), additive.
web-scumm/content:compileIR,canonicalJson,provenanceOf,logicView,
completionGoal,ObjectiveDef,GameIRand the IR's types.web-scumm/testing:fingerprint,
fingerprintGame,presentationOf,hashSources,sha256Hex,shortFingerprint,GameFingerprint. MCP:get_ir.
Engine.objectives,App.fingerprint(),App.objectivesMenu(),BootOptions.buildand twouikeys
(fingerprint,objectives) are new members. -
The first visit's JavaScript goes from 122 to 124 KB gzipped (4.1.12): the fingerprint (WebCrypto), the
objectives and the quest journal are in the player's main chunk; the budget (initialJsKB140) is untouched and the
baseline moved on purpose. -
The validator's migration checks moved to
tools/validate/migrations.ts(4.1.12), beside the objectives'
checks:validate.tsgoes from 1 140 to 1 113 lines, and its cap with it. -
e2e:pwaon Firefox tolerates one file missing from the cache after a reinstall warm-up it reported complete
(4.1.12, CI only; the files are listed), under the same bound as the refused cached files (two): more is a failure.
Chromium and WebKit stay strict. -
A tag's release chain in half the time (4.1.10).
release.ymlruns the two mutation sets as jobs of their own
(core,reality, about half an hour each; the final tag after its candidate reuses the candidate's reports through
the cache) beside
release-check:ci(release-checkwithout the mutation step), and the release waits for all three: about 35
minutes from the tag's green run to the published release instead of 70.ship tag --now(andchain --now) tags
as soon as the pull request is merged instead of waiting for main's run of the same commit: the tag's own run, the
same suite on the same commit, is what the release checks. -
ship tagfetches before reading the commit (4.1.10):chaintagged nothing twice (4.1.9, 4.1.10) because the
merge commit it had just made was on origin only ("not a commit here").
Manual passes (D12: reported, not blocking)
0 of 13 done.
| Pass | Status | Who, when | Device, OS, browser, versions | What failed |
|---|---|---|---|---|
| A game of your own given five objectives in the Studio, played to 100 % | not done | |||
| The pause menu's fingerprint compared between two builds of the same game by a person | not done | |||
| Real phone, frame rate of the heaviest scene on both painters (≥ 30 FPS) | not done | |||
| Screen reader on both painters, the quest journal read aloud | not done | |||
| A real multi-instance deployment behind HTTPS (Postgres), a connector delivering | not done | |||
| A real email provider (webhook mode) delivering to a game | not done | |||
| A real Open Badge (OB2 hosted, OB3 VC-JWT) from a real issuer verified | not done | |||
| SSH and Telnet exposed in a controlled environment, attacked by a person | not done | |||
Safari offline (docs/dev/SAFARI-OFFLINE.md), iPhone install and update |
not done | |||
| Firefox offline on a real machine | not done | |||
Windows: npm run doctor, npm run dev, npm run build by hand |
not done | |||
Playtesters who do not know the puzzles (npm run verify:field) |
not done | |||
Recorded voices; listening; a signed tag (git tag -s) |
not done |