@proophboard/exploration-runtime 0.0.0-stage → 0.1.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.
Files changed (66) hide show
  1. package/dist/index.d.ts +68 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +61 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/lib/connectionRules.d.ts +39 -0
  6. package/dist/lib/connectionRules.d.ts.map +1 -0
  7. package/dist/lib/connectionRules.js +475 -0
  8. package/dist/lib/connectionRules.js.map +1 -0
  9. package/dist/lib/toClassName.d.ts +42 -0
  10. package/dist/lib/toClassName.d.ts.map +1 -0
  11. package/dist/lib/toClassName.js +81 -0
  12. package/dist/lib/toClassName.js.map +1 -0
  13. package/dist/playFunction/ambientTypes.d.ts +30 -0
  14. package/dist/playFunction/ambientTypes.d.ts.map +1 -0
  15. package/dist/playFunction/ambientTypes.js +174 -0
  16. package/dist/playFunction/ambientTypes.js.map +1 -0
  17. package/dist/playFunction/cascadeBudget.d.ts +53 -0
  18. package/dist/playFunction/cascadeBudget.d.ts.map +1 -0
  19. package/dist/playFunction/cascadeBudget.js +74 -0
  20. package/dist/playFunction/cascadeBudget.js.map +1 -0
  21. package/dist/playFunction/clock.d.ts +58 -0
  22. package/dist/playFunction/clock.d.ts.map +1 -0
  23. package/dist/playFunction/clock.js +104 -0
  24. package/dist/playFunction/clock.js.map +1 -0
  25. package/dist/playFunction/modelTypes.d.ts +74 -0
  26. package/dist/playFunction/modelTypes.d.ts.map +1 -0
  27. package/dist/playFunction/modelTypes.js +345 -0
  28. package/dist/playFunction/modelTypes.js.map +1 -0
  29. package/dist/playFunction/playLog.d.ts +29 -0
  30. package/dist/playFunction/playLog.d.ts.map +1 -0
  31. package/dist/playFunction/playLog.js +64 -0
  32. package/dist/playFunction/playLog.js.map +1 -0
  33. package/dist/playFunction/playType.d.ts +52 -0
  34. package/dist/playFunction/playType.d.ts.map +1 -0
  35. package/dist/playFunction/playType.js +94 -0
  36. package/dist/playFunction/playType.js.map +1 -0
  37. package/dist/playFunction/runtimeFold.d.ts +51 -0
  38. package/dist/playFunction/runtimeFold.d.ts.map +1 -0
  39. package/dist/playFunction/runtimeFold.js +620 -0
  40. package/dist/playFunction/runtimeFold.js.map +1 -0
  41. package/dist/playFunction/runtimeSteps.d.ts +45 -0
  42. package/dist/playFunction/runtimeSteps.d.ts.map +1 -0
  43. package/dist/playFunction/runtimeSteps.js +112 -0
  44. package/dist/playFunction/runtimeSteps.js.map +1 -0
  45. package/dist/playFunction/sandbox.d.ts +52 -0
  46. package/dist/playFunction/sandbox.d.ts.map +1 -0
  47. package/dist/playFunction/sandbox.js +91 -0
  48. package/dist/playFunction/sandbox.js.map +1 -0
  49. package/dist/playFunction/scenarioRunner.d.ts +49 -0
  50. package/dist/playFunction/scenarioRunner.d.ts.map +1 -0
  51. package/dist/playFunction/scenarioRunner.js +331 -0
  52. package/dist/playFunction/scenarioRunner.js.map +1 -0
  53. package/dist/playFunction/transpile.d.ts +33 -0
  54. package/dist/playFunction/transpile.d.ts.map +1 -0
  55. package/dist/playFunction/transpile.js +71 -0
  56. package/dist/playFunction/transpile.js.map +1 -0
  57. package/dist/types/eventModel.d.ts +79 -0
  58. package/dist/types/eventModel.d.ts.map +1 -0
  59. package/dist/types/eventModel.js +12 -0
  60. package/dist/types/eventModel.js.map +1 -0
  61. package/dist/types/exploration.d.ts +143 -0
  62. package/dist/types/exploration.d.ts.map +1 -0
  63. package/dist/types/exploration.js +28 -0
  64. package/dist/types/exploration.js.map +1 -0
  65. package/package.json +48 -4
  66. package/README.md +0 -3
@@ -0,0 +1,104 @@
1
+ /**
2
+ * clock — the deterministic system clock + helpers for Exploration handlers
3
+ * (Exploration R31, R32, draft §4.5.1).
4
+ *
5
+ * Reproducibility is anchored by ONE human-meaningful system clock: a fixed base
6
+ * datetime (from scenario initial state, defaulting to run-start `now()`). All
7
+ * non-deterministic helpers read from it, never the wall clock, so the same
8
+ * scenario + model yields identical events, IDs, and timestamps on every replay.
9
+ *
10
+ * now() → the clock's CURRENT value (base + ticks/advances so far)
11
+ * today() → 'YYYY-MM-DD' derived from the same clock
12
+ * uuid() → deterministic sequence seeded from the clock + call index
13
+ * advanceClock(dur) → move the clock explicitly (opt-in, "3 days later")
14
+ *
15
+ * The clock AUTO-TICKS a small fixed amount per produced event by default (A), so
16
+ * each event's timestamp is distinct and increases with index with zero modeler
17
+ * effort; `advanceClock` (B) is the opt-in for scenarios that are *about* elapsed
18
+ * time.
19
+ *
20
+ * This module is pure/stateful-by-instance (no globals): the fold creates one
21
+ * `DeterministicClock` per replay and injects its helper surface into handlers.
22
+ */
23
+ /** Milliseconds the clock auto-advances per produced event (default tick). */
24
+ export const AUTO_TICK_MS = 1000;
25
+ /** Parse a duration like '1h', '30m', '2d', '45s', '500ms' into milliseconds. */
26
+ export function parseDuration(duration) {
27
+ if (typeof duration === 'number')
28
+ return duration;
29
+ const m = /^\s*(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)\s*$/.exec(duration);
30
+ if (!m) {
31
+ throw new Error(`advanceClock: invalid duration "${duration}" (use e.g. "30s", "15m", "2h", "3d", "500ms")`);
32
+ }
33
+ const value = parseFloat(m[1]);
34
+ const unit = m[2];
35
+ const factor = unit === 'ms' ? 1 :
36
+ unit === 's' ? 1000 :
37
+ unit === 'm' ? 60000 :
38
+ unit === 'h' ? 3600000 :
39
+ /* 'd' */ 86400000;
40
+ return Math.round(value * factor);
41
+ }
42
+ export class DeterministicClock {
43
+ /**
44
+ * @param baseISO fixed base datetime (ISO). Defaults to wall-clock now() only
45
+ * at construction — callers should pass the scenario clock for reproducibility.
46
+ */
47
+ constructor(baseISO) {
48
+ this.uuidCounter = 0;
49
+ const parsed = baseISO ? Date.parse(baseISO) : Date.now();
50
+ this.currentMs = Number.isNaN(parsed) ? Date.now() : parsed;
51
+ }
52
+ /** Current clock value as ISO string. */
53
+ now() {
54
+ return new Date(this.currentMs).toISOString();
55
+ }
56
+ /** Current clock date as 'YYYY-MM-DD'. */
57
+ today() {
58
+ return new Date(this.currentMs).toISOString().slice(0, 10);
59
+ }
60
+ /**
61
+ * Deterministic UUID (v4-shaped) seeded from the clock value + call index, so
62
+ * the Nth uuid() in a replay is always identical. NOT random.
63
+ */
64
+ uuid() {
65
+ const seed = `${this.currentMs}-${this.uuidCounter++}`;
66
+ // Deterministic 128-bit-ish hex from the seed via a simple xorshift fill.
67
+ let h = 0x811c9dc5;
68
+ const bytes = [];
69
+ for (let i = 0; i < 16; i++) {
70
+ for (let j = 0; j < seed.length; j++) {
71
+ h ^= seed.charCodeAt(j) + i * 131;
72
+ h = Math.imul(h, 0x01000193) >>> 0;
73
+ }
74
+ bytes.push(h & 0xff);
75
+ }
76
+ const hex = bytes.map((b) => b.toString(16).padStart(2, '0'));
77
+ // Shape as a v4 UUID (version/variant nibbles fixed for familiarity).
78
+ hex[6] = (parseInt(hex[6], 16) & 0x0f | 0x40).toString(16).padStart(2, '0');
79
+ hex[8] = (parseInt(hex[8], 16) & 0x3f | 0x80).toString(16).padStart(2, '0');
80
+ return (hex.slice(0, 4).join('') + '-' +
81
+ hex.slice(4, 6).join('') + '-' +
82
+ hex.slice(6, 8).join('') + '-' +
83
+ hex.slice(8, 10).join('') + '-' +
84
+ hex.slice(10, 16).join(''));
85
+ }
86
+ /** Auto-tick: advance by the default per-event amount. Called by the fold. */
87
+ tick() {
88
+ this.currentMs += AUTO_TICK_MS;
89
+ }
90
+ /** Opt-in explicit advance (R32). Exposed to handlers as advanceClock(). */
91
+ advanceClock(duration) {
92
+ this.currentMs += parseDuration(duration);
93
+ }
94
+ /** The handler-facing helper surface (bound to this instance). */
95
+ surface() {
96
+ return {
97
+ now: () => this.now(),
98
+ today: () => this.today(),
99
+ uuid: () => this.uuid(),
100
+ advanceClock: (d) => this.advanceClock(d),
101
+ };
102
+ }
103
+ }
104
+ //# sourceMappingURL=clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../../src/playFunction/clock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * modelTypes — generate a per-chapter `.d.ts` for the Play Function Monaco editor
3
+ * so authored handlers get MODEL-DERIVED autocomplete and checking, inferred from
4
+ * the current chapter (no schema parsing yet — just names/contexts/keys):
5
+ *
6
+ * • CommandName — a union of every command element name in the chapter.
7
+ * • EventName — a union of every event element name.
8
+ * • ContextName — a union of every context used by any element.
9
+ * • RuntimeState projection keys — for each Information element, a typed path
10
+ * `state.<ContextKey>.<ElementKey>` (keys via toClassName), so the editor
11
+ * autocompletes `state.TodoManagement.Todo` and stops flagging the hops.
12
+ * • Name-keyed PAYLOAD maps — for each command/event/ui/information element that
13
+ * declares a `playType`, a member in CommandPayloads/EventPayloads/UiInputs (or
14
+ * the Information projection shape). The base dts looks these up by `.name` to
15
+ * narrow `RuntimeCommand.payload` / `RuntimeEvent(Input).payload` / interact's
16
+ * `storage`; an element without a `playType` is absent from the map and falls
17
+ * back to the permissive payload (`Record<string, unknown>` / `any`).
18
+ *
19
+ * This MERGES with the static base dts (`ambientTypes.ts`) via TypeScript
20
+ * declaration merging:
21
+ * - a second `interface RuntimeState { … }` adds the known projection keys on
22
+ * top of the base's `$events` + `[context: string]: any` index signature, so
23
+ * unknown keys still resolve to `any`.
24
+ * - `CommandName` / `EventName` / `ContextName` are STRICT literal unions of the
25
+ * modeled names. The base dts wires them into `RuntimeCommand.name`,
26
+ * `RuntimeEventInput.name`, `RuntimeEvent.name` and the `.context` fields, so
27
+ * a typo'd/unknown name is flagged by the editor (the deliberate trade-off:
28
+ * catch mistakes over accepting arbitrary strings). Draw the element first,
29
+ * then its handler — authoring a new element extends the union.
30
+ *
31
+ * Pure: `buildModelDts(chapter) → string`. Registered under its own stable extra-
32
+ * lib path and refreshed whenever the chapter's command/event/information shape
33
+ * changes.
34
+ */
35
+ import type { Chapter, Element } from '../types/eventModel.js';
36
+ /** Virtual file name the model extraLib is registered under (stable for dedupe). */
37
+ export declare const MODEL_TYPES_PATH = "ts:exploration-model.d.ts";
38
+ /**
39
+ * Build the per-chapter model dts. Returns a `declare global { … } export {};`
40
+ * block that merges with the base ambient types.
41
+ */
42
+ export declare function buildModelDts(chapter: Chapter | undefined): string;
43
+ /**
44
+ * Virtual file name the PER-ELEMENT extraLib is registered under. Stable across
45
+ * element switches (the content changes; the path stays) so Monaco replaces
46
+ * rather than accumulates it.
47
+ */
48
+ export declare const PER_ELEMENT_TYPES_PATH = "ts:exploration-element.d.ts";
49
+ /**
50
+ * Build the per-element `.d.ts` for the Play Function editor. Its job is to
51
+ * declare the handlers whose parameter type depends on WHICH element is being
52
+ * edited, pinned to THAT element's declared payload so the author gets a typed
53
+ * parameter WITHOUT a `.name` guard:
54
+ *
55
+ * • interact(storage) — storage pinned to this UI element's input (UiInputs[name])
56
+ * • decide(command) — command pinned to this command element (name + payload)
57
+ * • apply(event) — event pinned to this event element (name + payload)
58
+ *
59
+ * These are declared HERE (not in the base ambient dts) so each parameter can vary
60
+ * per element without a duplicate-identifier clash. A handler authored on a command
61
+ * element gets a `decide` whose `command.payload` is exactly this command's declared
62
+ * type — it does NOT matter whether other (untyped) commands exist, because the
63
+ * parameter is the single element's type, not the `RuntimeCommand` union.
64
+ *
65
+ * The payload lookup uses the ELEMENT NAME as the key (matching CommandPayloads /
66
+ * EventPayloads / UiInputs in buildModelDts). When the element declares no
67
+ * `playType`, the name is absent from the map, so we fall back to the permissive
68
+ * `Record<string, unknown>` rather than emitting `Map["<name>"]` (which would error
69
+ * on a missing key). For element types that don't match a given handler, that
70
+ * handler's parameter falls back to the generic runtime union so the global surface
71
+ * stays complete regardless of the edited element.
72
+ */
73
+ export declare function buildPerElementDts(element: Pick<Element, 'type' | 'name' | 'playType'> | undefined): string;
74
+ //# sourceMappingURL=modelTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelTypes.d.ts","sourceRoot":"","sources":["../../src/playFunction/modelTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAG/D,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAwE5D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAwKlE;AAGD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,gCAAgC,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC,GAAG,SAAS,GAC/D,MAAM,CAoDR"}
@@ -0,0 +1,345 @@
1
+ /**
2
+ * modelTypes — generate a per-chapter `.d.ts` for the Play Function Monaco editor
3
+ * so authored handlers get MODEL-DERIVED autocomplete and checking, inferred from
4
+ * the current chapter (no schema parsing yet — just names/contexts/keys):
5
+ *
6
+ * • CommandName — a union of every command element name in the chapter.
7
+ * • EventName — a union of every event element name.
8
+ * • ContextName — a union of every context used by any element.
9
+ * • RuntimeState projection keys — for each Information element, a typed path
10
+ * `state.<ContextKey>.<ElementKey>` (keys via toClassName), so the editor
11
+ * autocompletes `state.TodoManagement.Todo` and stops flagging the hops.
12
+ * • Name-keyed PAYLOAD maps — for each command/event/ui/information element that
13
+ * declares a `playType`, a member in CommandPayloads/EventPayloads/UiInputs (or
14
+ * the Information projection shape). The base dts looks these up by `.name` to
15
+ * narrow `RuntimeCommand.payload` / `RuntimeEvent(Input).payload` / interact's
16
+ * `storage`; an element without a `playType` is absent from the map and falls
17
+ * back to the permissive payload (`Record<string, unknown>` / `any`).
18
+ *
19
+ * This MERGES with the static base dts (`ambientTypes.ts`) via TypeScript
20
+ * declaration merging:
21
+ * - a second `interface RuntimeState { … }` adds the known projection keys on
22
+ * top of the base's `$events` + `[context: string]: any` index signature, so
23
+ * unknown keys still resolve to `any`.
24
+ * - `CommandName` / `EventName` / `ContextName` are STRICT literal unions of the
25
+ * modeled names. The base dts wires them into `RuntimeCommand.name`,
26
+ * `RuntimeEventInput.name`, `RuntimeEvent.name` and the `.context` fields, so
27
+ * a typo'd/unknown name is flagged by the editor (the deliberate trade-off:
28
+ * catch mistakes over accepting arbitrary strings). Draw the element first,
29
+ * then its handler — authoring a new element extends the union.
30
+ *
31
+ * Pure: `buildModelDts(chapter) → string`. Registered under its own stable extra-
32
+ * lib path and refreshed whenever the chapter's command/event/information shape
33
+ * changes.
34
+ */
35
+ import { toClassName } from '../lib/toClassName.js';
36
+ /** Virtual file name the model extraLib is registered under (stable for dedupe). */
37
+ export const MODEL_TYPES_PATH = 'ts:exploration-model.d.ts';
38
+ /** Distinct, sorted display names of a given element type. */
39
+ function distinctNames(chapter, type) {
40
+ const set = new Set();
41
+ for (const el of chapter.elements) {
42
+ if (el.type === type && el.name.trim().length > 0)
43
+ set.add(el.name);
44
+ }
45
+ return [...set].sort();
46
+ }
47
+ /** Distinct, sorted contexts across all elements (defaulting empty → 'App'). */
48
+ function distinctContexts(chapter) {
49
+ const set = new Set();
50
+ for (const el of chapter.elements)
51
+ set.add(el.context || 'App');
52
+ return [...set].sort();
53
+ }
54
+ /**
55
+ * A STRICT string-literal union of the modeled names: `"A" | "B"`. Unknown names
56
+ * (typos, or names not yet drawn) are flagged by the editor — the deliberate
57
+ * trade-off for catching mistakes. Falls back to `string` only when there are NO
58
+ * names, so an empty/early chapter doesn't error on every annotation.
59
+ *
60
+ * (We previously used `… | (string & {})` to also accept arbitrary strings, but
61
+ * that silently allowed typos — the opposite of what authors want here. In Event
62
+ * Modeling you draw the element first, then write its handler, so an unknown name
63
+ * is almost always a typo. Author a new element to extend the union.)
64
+ */
65
+ function nameUnion(names) {
66
+ if (names.length === 0)
67
+ return 'string';
68
+ return names.map((n) => JSON.stringify(n)).join(' | ');
69
+ }
70
+ /**
71
+ * Collect `element.name → playType` for every element of `type` whose `playType`
72
+ * is a non-empty string. The display NAME is the key (it is the discriminant used
73
+ * by RuntimeCommand/RuntimeEventInput/RuntimeEvent `.name`), so a declared payload
74
+ * narrows on `.name`. Last-write-wins on duplicate names (sorted for stability).
75
+ */
76
+ function payloadsByName(chapter, type) {
77
+ const map = new Map();
78
+ for (const el of chapter.elements) {
79
+ if (el.type !== type)
80
+ continue;
81
+ const name = el.name.trim();
82
+ const expr = el.playType?.trim();
83
+ if (name.length === 0 || !expr)
84
+ continue;
85
+ map.set(name, expr);
86
+ }
87
+ return map;
88
+ }
89
+ /**
90
+ * Emit a name-keyed payload interface (`interface <Name> { "<element>": <type>; }`)
91
+ * from a display-name → type-expression map, or `null` when the map is empty (so
92
+ * callers can omit the block entirely and let the permissive fallback apply).
93
+ *
94
+ * Members are quoted display names (they contain spaces), each mapped to the
95
+ * author's verbatim `playType` expression. The interface is intentionally CLOSED
96
+ * (no index signature): the ambient wiring looks a name up and falls back to the
97
+ * permissive payload when the name is absent, so undeclared names stay permissive
98
+ * WITHOUT every map needing an `any` catch-all (which would defeat the narrowing).
99
+ */
100
+ function payloadInterface(name, byName, doc) {
101
+ if (byName.size === 0)
102
+ return null;
103
+ const members = [...byName.entries()]
104
+ .sort(([a], [b]) => a.localeCompare(b))
105
+ .map(([elName, expr]) => ` ${JSON.stringify(elName)}: ${expr};`)
106
+ .join('\n');
107
+ return ` /** ${doc} */\n interface ${name} {\n${members}\n }\n`;
108
+ }
109
+ /**
110
+ * Build the per-chapter model dts. Returns a `declare global { … } export {};`
111
+ * block that merges with the base ambient types.
112
+ */
113
+ export function buildModelDts(chapter) {
114
+ if (!chapter) {
115
+ // Minimal, still-valid aliases so references don't error on an empty editor.
116
+ return `declare global {
117
+ /** Command names in this chapter (none yet). */
118
+ type CommandName = string;
119
+ /** Event names in this chapter (none yet). */
120
+ type EventName = string;
121
+ /** Contexts in this chapter (none yet). */
122
+ type ContextName = string;
123
+ /** Declared command payloads (none yet). */
124
+ interface CommandPayloads {}
125
+ /** Declared event payloads (none yet). */
126
+ interface EventPayloads {}
127
+ /** Declared UI input shapes (none yet). */
128
+ interface UiInputs {}
129
+ /** The return shape of \`apply\` (none modeled yet — any object). */
130
+ type ProjectionPatch = Record<string, Record<string, unknown>>;
131
+ }
132
+ export {};
133
+ `;
134
+ }
135
+ const commandNames = distinctNames(chapter, 'command');
136
+ const eventNames = distinctNames(chapter, 'event');
137
+ const contexts = distinctContexts(chapter);
138
+ // Build nested projection shape grouped by context className → element className.
139
+ // Each element carries its declared `playType` (the STORED projection shape) when
140
+ // present, else null (⇒ permissive `any`/`unknown`). This single structure feeds
141
+ // both the RuntimeState augmentation and the ProjectionPatch return type.
142
+ const projByCtx = new Map();
143
+ for (const el of chapter.elements) {
144
+ if (el.type !== 'information')
145
+ continue;
146
+ const ctxKey = toClassName(el.context || 'App');
147
+ const elKey = toClassName(el.name);
148
+ if (!ctxKey || !elKey)
149
+ continue;
150
+ if (!projByCtx.has(ctxKey))
151
+ projByCtx.set(ctxKey, new Map());
152
+ const shape = el.playType?.trim();
153
+ projByCtx.get(ctxKey).set(elKey, shape && shape.length > 0 ? shape : null);
154
+ }
155
+ // Each known Information projection is typed by its declared `playType` (the
156
+ // stored shape) when the modeler provided one, else `any` so handlers can
157
+ // deep-access objects AND spread/iterate list projections (e.g. `[...state.Ctx.List]`)
158
+ // without a cast; the base index signature covers unknown keys.
159
+ const projectionMembers = [...projByCtx.entries()]
160
+ .sort(([a], [b]) => a.localeCompare(b))
161
+ .map(([ctxKey, elKeys]) => {
162
+ const members = [...elKeys.entries()]
163
+ .sort(([a], [b]) => a.localeCompare(b))
164
+ .map(([elKey, shape]) => ` /** Projection: state.${ctxKey}.${elKey} (${shape ? 'declared shape' : 'object, list, or scalar'}) */\n ${elKey}: ${shape ?? 'any'};`)
165
+ .join('\n');
166
+ return ` /** Context "${ctxKey}" projections. */\n ${ctxKey}: {\n${members}\n [element: string]: any;\n };`;
167
+ })
168
+ .join('\n');
169
+ // Namespace RuntimeState — mirrors the interface augmentation so authors can
170
+ // write `type Payload = RuntimeState.TodoManagement.Todo` in the Type editor
171
+ // (and in Function handlers). Namespace members use the same shape as the
172
+ // interface: declared `playType` when present, else `any` (permissive).
173
+ // Each context-level namespace also carries a catch-all `[element: string]: any`
174
+ // so undeclared element names resolve to `any` rather than error.
175
+ const namespaceParts = [...projByCtx.entries()]
176
+ .sort(([a], [b]) => a.localeCompare(b))
177
+ .map(([ctxKey, elKeys]) => {
178
+ const members = [...elKeys.entries()]
179
+ .sort(([a], [b]) => a.localeCompare(b))
180
+ .map(([elKey, shape]) => ` type ${elKey} = ${shape ?? 'any'};`)
181
+ .join('\n');
182
+ return ` namespace ${ctxKey} {\n${members}\n }`;
183
+ })
184
+ .join('\n');
185
+ const stateNamespace = namespaceParts
186
+ ? ` /**
187
+ * Namespace mirror of RuntimeState projections. Allows dotted-path type
188
+ * references in the Type editor: type Payload = RuntimeState.TodoManagement.Todo
189
+ */
190
+ namespace RuntimeState {
191
+ ${namespaceParts}
192
+ }
193
+ `
194
+ : '';
195
+ const stateAugment = projectionMembers
196
+ ? ` /**
197
+ * Model-derived projection keys (from this chapter's Information elements).
198
+ * Merges with the base RuntimeState: known contexts/elements autocomplete,
199
+ * unknown keys still resolve to \`any\` via the base index signature. Where an
200
+ * Information element declares a payload type, its projection is strictly typed.
201
+ */
202
+ interface RuntimeState {
203
+ ${projectionMembers}
204
+ }
205
+ ${stateNamespace}`
206
+ : '';
207
+ // ProjectionPatch — the typed return of `apply`. Shape: a PARTIAL map of known
208
+ // contexts → PARTIAL map of that context's known Information elements → patch
209
+ // VALUE. The value is the element's declared `playType` when present (so a typed
210
+ // patch is checked field-by-field), else `unknown` (object, list, or scalar — R13
211
+ // replaces lists/scalars wholesale, leaf-merges objects), so only the context/
212
+ // element KEY names are checked. Being `Partial` lets a handler write any subset;
213
+ // the absence of an inner index signature means a typo'd key is flagged by the
214
+ // excess-property check on the returned object literal. Falls back to a permissive
215
+ // map when no Information is modeled.
216
+ const patchContexts = [...projByCtx.entries()]
217
+ .sort(([a], [b]) => a.localeCompare(b))
218
+ .map(([ctxKey, elKeys]) => {
219
+ const members = [...elKeys.entries()]
220
+ .sort(([a], [b]) => a.localeCompare(b))
221
+ .map(([elKey, shape]) => ` ${elKey}?: ${shape ? `Partial<${shape}>` : 'unknown'};`)
222
+ .join('\n');
223
+ return ` ${ctxKey}?: {\n${members}\n };`;
224
+ })
225
+ .join('\n');
226
+ const projectionPatchType = patchContexts
227
+ ? ` /**
228
+ * The return shape of \`apply\`. Known contexts/elements are checked — a typo'd
229
+ * context or Information name is flagged. Every key is optional (write a subset).
230
+ */
231
+ interface ProjectionPatch {
232
+ ${patchContexts}
233
+ }
234
+ `
235
+ : ` /** The return shape of \`apply\` (no Information modeled yet — any object). */
236
+ type ProjectionPatch = Record<string, Record<string, unknown>>;
237
+ `;
238
+ // Name-keyed payload maps (display name → declared `playType`). Each is emitted
239
+ // as an interface the base ambient dts references to narrow `.payload`/`storage`
240
+ // by `.name`. An element WITHOUT a `playType` is simply absent from the map, so
241
+ // the ambient wiring's conditional lookup falls back to the permissive payload.
242
+ // We ALWAYS emit the interface (empty when nothing is declared) so the base dts
243
+ // can reference it unconditionally — an empty interface narrows nothing, which is
244
+ // exactly the permissive fallback.
245
+ const commandPayloads = payloadInterface('CommandPayloads', payloadsByName(chapter, 'command'), "Declared command payloads, keyed by command name. Narrows RuntimeCommand.payload on `.name`.")
246
+ ?? ` /** Declared command payloads (none yet). */\n interface CommandPayloads {}\n`;
247
+ const eventPayloads = payloadInterface('EventPayloads', payloadsByName(chapter, 'event'), "Declared event payloads, keyed by event name. Narrows RuntimeEvent(Input).payload on `.name`.")
248
+ ?? ` /** Declared event payloads (none yet). */\n interface EventPayloads {}\n`;
249
+ const uiInputs = payloadInterface('UiInputs', payloadsByName(chapter, 'ui'), "Declared UI input shapes, keyed by UI element name. Pins interact's `storage` per element.")
250
+ ?? ` /** Declared UI input shapes (none yet). */\n interface UiInputs {}\n`;
251
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- doc only
252
+ return `declare global {
253
+ /** Command names authored in this chapter. Unknown names are flagged (typos). */
254
+ type CommandName = ${nameUnion(commandNames)};
255
+
256
+ /** Event names authored in this chapter. Unknown names are flagged (typos). */
257
+ type EventName = ${nameUnion(eventNames)};
258
+
259
+ /** Contexts used in this chapter. Unknown contexts are flagged (typos). */
260
+ type ContextName = ${nameUnion(contexts)};
261
+
262
+ ${commandPayloads}
263
+ ${eventPayloads}
264
+ ${uiInputs}
265
+ ${projectionPatchType}
266
+ ${stateAugment}}
267
+ export {};
268
+ `;
269
+ }
270
+ /**
271
+ * Virtual file name the PER-ELEMENT extraLib is registered under. Stable across
272
+ * element switches (the content changes; the path stays) so Monaco replaces
273
+ * rather than accumulates it.
274
+ */
275
+ export const PER_ELEMENT_TYPES_PATH = 'ts:exploration-element.d.ts';
276
+ /**
277
+ * Build the per-element `.d.ts` for the Play Function editor. Its job is to
278
+ * declare the handlers whose parameter type depends on WHICH element is being
279
+ * edited, pinned to THAT element's declared payload so the author gets a typed
280
+ * parameter WITHOUT a `.name` guard:
281
+ *
282
+ * • interact(storage) — storage pinned to this UI element's input (UiInputs[name])
283
+ * • decide(command) — command pinned to this command element (name + payload)
284
+ * • apply(event) — event pinned to this event element (name + payload)
285
+ *
286
+ * These are declared HERE (not in the base ambient dts) so each parameter can vary
287
+ * per element without a duplicate-identifier clash. A handler authored on a command
288
+ * element gets a `decide` whose `command.payload` is exactly this command's declared
289
+ * type — it does NOT matter whether other (untyped) commands exist, because the
290
+ * parameter is the single element's type, not the `RuntimeCommand` union.
291
+ *
292
+ * The payload lookup uses the ELEMENT NAME as the key (matching CommandPayloads /
293
+ * EventPayloads / UiInputs in buildModelDts). When the element declares no
294
+ * `playType`, the name is absent from the map, so we fall back to the permissive
295
+ * `Record<string, unknown>` rather than emitting `Map["<name>"]` (which would error
296
+ * on a missing key). For element types that don't match a given handler, that
297
+ * handler's parameter falls back to the generic runtime union so the global surface
298
+ * stays complete regardless of the edited element.
299
+ */
300
+ export function buildPerElementDts(element) {
301
+ const name = element?.name ?? '';
302
+ const hasType = typeof element?.playType === 'string' && element.playType.trim().length > 0;
303
+ const nameLit = JSON.stringify(name);
304
+ // interact → this UI element's input shape (else permissive).
305
+ const storageType = element?.type === 'ui' && hasType ? `UiInputs[${nameLit}]` : 'Record<string, unknown>';
306
+ // decide → this command element pinned to its own name + payload (else generic union).
307
+ const commandType = element?.type === 'command'
308
+ ? `{ name: ${nameLit}; context: ContextName; payload: ${hasType ? `CommandPayloads[${nameLit}]` : 'Record<string, unknown>'} }`
309
+ : 'RuntimeCommand';
310
+ // apply → this event element pinned to its own name + payload (else generic union).
311
+ const eventType = element?.type === 'event'
312
+ ? `{ name: ${nameLit}; context: ContextName; payload: ${hasType ? `EventPayloads[${nameLit}]` : 'Record<string, unknown>'}; index: number; timestamp: string }`
313
+ : 'RuntimeEvent';
314
+ return `declare global {
315
+ /**
316
+ * The captured UI input shape for the element currently being edited. Pinned to
317
+ * this UI element's declared payload type when it has one, else permissive.
318
+ */
319
+ type ThisUiStorage = ${storageType};
320
+
321
+ /**
322
+ * This command, pinned to the edited command element's name + declared payload,
323
+ * so \`command.payload\` is typed directly — no \`.name\` guard needed.
324
+ */
325
+ type ThisCommand = ${commandType};
326
+
327
+ /**
328
+ * This event, pinned to the edited event element's name + declared payload, so
329
+ * \`event.payload\` is typed directly — no \`.name\` guard needed.
330
+ */
331
+ type ThisEvent = ${eventType};
332
+
333
+ /** UI handler: collected input + state → commands. \`storage\` is this element's input shape. */
334
+ function interact(storage: ThisUiStorage, state: RuntimeState): RuntimeCommand[];
335
+
336
+ /** Command handler: this command + state → events (or reject()). \`command\` is this element. */
337
+ function decide(command: ThisCommand, state: RuntimeState): RuntimeEventInput[];
338
+
339
+ /** Event handler: this event + state → projection patches. \`event\` is this element. */
340
+ function apply(event: ThisEvent, state: RuntimeState): ProjectionPatch;
341
+ }
342
+ export {};
343
+ `;
344
+ }
345
+ //# sourceMappingURL=modelTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelTypes.js","sourceRoot":"","sources":["../../src/playFunction/modelTypes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * playLog — permanent, colored debug logging for the Exploration Play runtime.
3
+ *
4
+ * Two sources, tagged in every message:
5
+ * [Play] — main-thread orchestration (useExplorationRuntime / the worker
6
+ * hook lifecycle: fast-path vs worker, dispatch, resolve/settle).
7
+ * [PlayWorker] — work done inside the Web Worker AND the pure fold it runs
8
+ * (handler execution per kind, emitted events, pending commands,
9
+ * errors). The fold also runs on the main thread for the sync
10
+ * fast-path; there it logs under [Play] via the `source` arg.
11
+ *
12
+ * Coloring: each handler KIND gets its own color so a flow is scannable at a
13
+ * glance. Uses `%c` CSS styling, which both the window console and the
14
+ * DedicatedWorker console support. No-ops safely if `console` is unavailable.
15
+ *
16
+ * These logs are intentionally PERMANENT (not stripped in prod) — Exploration is
17
+ * a modeling/debugging surface where seeing the handler flow is the point.
18
+ */
19
+ export type PlaySource = 'Play' | 'PlayWorker';
20
+ /** The six handler kinds plus flow/event/error channels, each with a color. */
21
+ export type PlayChannel = 'interact' | 'decide' | 'apply' | 'read' | 'react' | 'process' | 'event' | 'input' | 'pending' | 'flow' | 'error';
22
+ /**
23
+ * Log one line. `source` tags the thread, `channel` picks the color/label.
24
+ * Extra args are passed through verbatim (objects stay inspectable in devtools).
25
+ */
26
+ export declare function playLog(source: PlaySource, channel: PlayChannel, message: string, ...args: unknown[]): void;
27
+ /** Convenience factory bound to a source, so call-sites read `log('decide', …)`. */
28
+ export declare function makePlayLogger(source: PlaySource): (channel: PlayChannel, message: string, ...args: unknown[]) => void;
29
+ //# sourceMappingURL=playLog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playLog.d.ts","sourceRoot":"","sources":["../../src/playFunction/playLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,YAAY,CAAC;AAE/C,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GACnB,UAAU,GACV,QAAQ,GACR,OAAO,GACP,MAAM,GACN,OAAO,GACP,SAAS,GACT,OAAO,GACP,OAAO,GACP,SAAS,GACT,MAAM,GACN,OAAO,CAAC;AAyBZ;;;GAGG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,GAAG,IAAI,EAAE,OAAO,EAAE,GACjB,IAAI,CAcN;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,IACvC,SAAS,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,OAAO,EAAE,UAElE"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * playLog — permanent, colored debug logging for the Exploration Play runtime.
3
+ *
4
+ * Two sources, tagged in every message:
5
+ * [Play] — main-thread orchestration (useExplorationRuntime / the worker
6
+ * hook lifecycle: fast-path vs worker, dispatch, resolve/settle).
7
+ * [PlayWorker] — work done inside the Web Worker AND the pure fold it runs
8
+ * (handler execution per kind, emitted events, pending commands,
9
+ * errors). The fold also runs on the main thread for the sync
10
+ * fast-path; there it logs under [Play] via the `source` arg.
11
+ *
12
+ * Coloring: each handler KIND gets its own color so a flow is scannable at a
13
+ * glance. Uses `%c` CSS styling, which both the window console and the
14
+ * DedicatedWorker console support. No-ops safely if `console` is unavailable.
15
+ *
16
+ * These logs are intentionally PERMANENT (not stripped in prod) — Exploration is
17
+ * a modeling/debugging surface where seeing the handler flow is the point.
18
+ */
19
+ /** Per-channel label color (hex; readable on both light and dark consoles). */
20
+ const CHANNEL_COLOR = {
21
+ interact: '#8b5cf6', // violet — UI
22
+ decide: '#2563eb', // blue — command
23
+ apply: '#ea580c', // orange — event projection
24
+ read: '#16a34a', // green — information view
25
+ react: '#db2777', // pink — automation reaction
26
+ process: '#c026d3', // fuchsia — automation job
27
+ event: '#f59e0b', // amber — emitted event
28
+ input: '#0891b2', // cyan — captured UI input ($input)
29
+ pending: '#0d9488', // teal — deferred command
30
+ flow: '#64748b', // slate — orchestration
31
+ error: '#dc2626', // red — failure
32
+ };
33
+ /** Source badge background (so [Play] vs [PlayWorker] are distinguishable). */
34
+ const SOURCE_BG = {
35
+ Play: '#1e293b', // slate-800
36
+ PlayWorker: '#312e81', // indigo-900
37
+ };
38
+ const hasConsole = typeof console !== 'undefined';
39
+ /**
40
+ * Log one line. `source` tags the thread, `channel` picks the color/label.
41
+ * Extra args are passed through verbatim (objects stay inspectable in devtools).
42
+ */
43
+ export function playLog(source, channel, message, ...args) {
44
+ if (!hasConsole)
45
+ return;
46
+ const color = CHANNEL_COLOR[channel];
47
+ const srcBg = SOURCE_BG[source];
48
+ // Two styled segments: a source badge, then a colored channel label.
49
+ const prefix = `%c[${source}]%c ${channel}`;
50
+ const srcStyle = `background:${srcBg};color:#fff;padding:1px 4px;border-radius:3px;font-weight:600`;
51
+ const chStyle = `color:${color};font-weight:600`;
52
+ try {
53
+ // eslint-disable-next-line no-console
54
+ console.log(prefix, srcStyle, chStyle, message, ...args);
55
+ }
56
+ catch {
57
+ /* no-op: never let logging break the runtime */
58
+ }
59
+ }
60
+ /** Convenience factory bound to a source, so call-sites read `log('decide', …)`. */
61
+ export function makePlayLogger(source) {
62
+ return (channel, message, ...args) => playLog(source, channel, message, ...args);
63
+ }
64
+ //# sourceMappingURL=playLog.js.map