@patterkit/runtime 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -33,6 +33,21 @@ version number always means the same runtime behaviour. This package is versione
33
33
 
34
34
  ## [Unreleased]
35
35
 
36
+ ## [0.13.0] - 2026-09-05
37
+
38
+ ### Changed
39
+
40
+ - **A `writable: false` host declaration is the STORY's promise, and only the story's: the game
41
+ writes it.** `Engine.setProperty` / `Flow.setProperty` are the game's surfaces, so they now write a
42
+ read-only `@world` property whether it is self-backed or bound to a resolver; an effect that writes
43
+ one is refused exactly as before, with the same sentence. Until now the runtime refused every
44
+ caller alike, so a game could not advance its own clock through the engine and a Patterplay
45
+ coverage driver on such a property killed the run - which is how both this project and the
46
+ Storylet Engine found it, on the same day, in different content
47
+ (from-storylets/host-writes-to-read-only-world). The rule now lives in the shared kernel
48
+ (`@wildwinter/scoperegistry` ^0.6.0, an explicit host authority on `set`), so both products mean
49
+ the same thing by the flag.
50
+
36
51
  ## [0.12.1] - 2026-09-04
37
52
 
38
53
  ### Changed
package/dist/index.cjs CHANGED
@@ -536,10 +536,16 @@ var Engine = class _Engine {
536
536
  const { scope, name } = this.splitShared(ref);
537
537
  return this.host.shared.get(scope, name);
538
538
  }
539
- /** Write a shared (`@patter` / foreign) property by ref. `@scene` refs are rejected (flow-level). */
539
+ /** Write a shared (`@patter` / foreign) property by ref. `@scene` refs are rejected (flow-level).
540
+ *
541
+ * This is the GAME's surface, so it writes with host authority: a host-scope declaration's
542
+ * `writable: false` is the story's promise not to write the value, never a lock on the game that
543
+ * owns it. The story's own writes come through `Flow.runEffects`, which never claims it. (Ruled
544
+ * across the family 2026-09-05, after a Storylets venue clock and this project's coverage driver
545
+ * were each refused the one property they existed to move.) */
540
546
  setProperty(ref, value) {
541
547
  const { scope, name } = this.splitShared(ref);
542
- this.host.shared.set(scope, name, value);
548
+ this.host.shared.set(scope, name, value, { host: true });
543
549
  }
544
550
  /** The shared `@patter` properties, for a live state inspector: each with its ref, type, current
545
551
  * value, declared default (for reset), and enum options. Mirrors the Unity / Godot ports. */
@@ -1006,8 +1012,15 @@ var Flow = class {
1006
1012
  if (scope === "scene") return this.sceneResolver.get(name);
1007
1013
  return this.host.shared.get(scope, name);
1008
1014
  }
1009
- /** Write a property by ref (routed by scope, then by the property's `shared` flag). */
1015
+ /** Write a property by ref (routed by scope, then by the property's `shared` flag). The GAME's
1016
+ * surface: it writes with host authority, so a `writable: false` host declaration does not refuse
1017
+ * it (see `Engine.setProperty`). The story's writes go through `writeProperty` instead. */
1010
1018
  setProperty(ref, value) {
1019
+ this.writeProperty(ref, value, true);
1020
+ }
1021
+ /** The write itself. `host` says WHO is writing, which is the only thing `writable: false` cares
1022
+ * about: the story is refused, the game is not. */
1023
+ writeProperty(ref, value, host) {
1011
1024
  const { scope, name } = this.splitRef(ref);
1012
1025
  if (scope === "patter") {
1013
1026
  this.patterResolver.set(name, value);
@@ -1015,7 +1028,7 @@ var Flow = class {
1015
1028
  if (this.currentSceneId === null) throw new Error(`'${ref}': the flow has not entered a scene yet`);
1016
1029
  this.sceneResolver.set(name, value);
1017
1030
  } else {
1018
- this.host.shared.set(scope, name, value);
1031
+ this.host.shared.set(scope, name, value, host ? { host: true } : void 0);
1019
1032
  }
1020
1033
  }
1021
1034
  // -- Save / restore (engine-driven) --------------------------------------
@@ -1359,7 +1372,7 @@ var Flow = class {
1359
1372
  for (const e of effects ?? []) {
1360
1373
  const value = this.evalExpr(e.value);
1361
1374
  const prev = this.host.logEnabled ? this.getProperty(e.target) : void 0;
1362
- this.setProperty(e.target, value);
1375
+ this.writeProperty(e.target, value, false);
1363
1376
  this.emit({ type: "write", target: e.target, value, ...prev !== void 0 ? { prev } : {} });
1364
1377
  }
1365
1378
  }