clone

a browser grid puzzle game where you push words around to rewrite the rules of each level

main
miau-is-true / openspec / changes / archive / 2026-09-24-add-rules-compatibility-revision / design.md
design.md 4.0K source

Context

The current loader validates manifest.engine as the data/schema version and defaults an omitted value to MOD_SCHEMA_VERSION. It has no equivalent field for behavioral semantics. W6 changes precedence, transform reading order, and contact order while preserving the existing manifest shape, so an old pack needs an explicit compatibility signal.

Decisions

A monotonic integer revision

The host exports one current rules revision, CURRENT_RULES_VERSION = 2. Revision 2 means the post-W6 contract: PUSH precedence over STOP, defeat before win, X IS X self-blocking, reading-order transform conflicts, one-link transform chains per turn, and complete AND noun reading. Future semantic changes bump the integer. This field is deliberately separate from manifest.engine, which continues to describe the validated data API.

manifest.rules is a positive integer no greater than the current revision. Non-integers, zero, negative values, and other types are validation errors. A value greater than 2 is rejected as an unsupported future rules revision; the loader must fail before it registers any part of the pack.

Missing means legacy revision one

An omitted manifest.rules is interpreted as revision 1, the pre-W6 rules contract. Normalization materializes the effective revision so local imports, shared decoding, CommonJS export, catalog records, pack-service preview views, and cloned or persisted views agree. Every projection boundary, including manifestFromView() and createPackView(), must carry rules forward instead of rebuilding a manifest that drops it. The engine still runs the current rules implementation; this revision is a compatibility declaration and does not select an alternate simulator.

First-party packs that are authored for the current runtime declare rules: 2 explicitly. Imported packs without the field stay usable and receive the legacy note below.

One transient pack-level warning

For an effective revision below the host revision, diagnostics returns one bounded warning with the pack identity and source detail. Its player message is exactly:

This pack was made for older rules; some proofs may play differently.

The warning is nonfatal and appears in both local CommonJS and data-only shared previews. It uses the existing warning envelope, with word: 'RULES', levelId: null, levelTitle: null, and sentence: null; detail identifies manifest.rules, the effective revision, and the current revision. It is emitted once per preview, not once per proof, and does not count authored levels as separate warnings. The warning is recomputed on preview and is never copied into normalized authored data, catalog records, snapshots, exports, or shared payloads.

Keep preview and installation atomic

Validation happens before catalog registration. An unsupported future revision returns the normal structured pack error and leaves the catalog unchanged. A known older revision returns errors: [], installs normally when selected, and retains the effective revision in the pack's normalized manifest.

Risks and mitigations

  • Existing packs omit the field. Treating absence as revision one preserves loading while making the semantic mismatch visible.
  • A warning can be mistaken for a compatibility mode. The message and docs say the current rules run; no legacy simulator is introduced.
  • Local and shared paths can drift. Run the same fixtures through loadMod, decodeSharedPack, and pack-service previews, then compare warning envelopes and normalized manifests.
  • First-party world packs may be edited by their owners. Ask each owner to add rules: 2 rather than mutating team-owned pack files in this change.

Non-goals

  • Reimplementing pre-W6 rules or adding a rules-version switch to the engine.
  • Changing manifest.engine, share envelope version, feature negotiation, or warning thresholds for long proof titles.
  • Changing puzzle content, solver search semantics, or presentation copy beyond the one compatibility note.