arcane-os 0.3.0 → 0.3.2

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 (153) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +86 -117
  3. package/bin/arcane-test.mjs +170 -46
  4. package/browser-runtime/ai/browser-speech-artifacts.mjs +887 -909
  5. package/browser-runtime/ai/browser-speech-providers.mjs +96 -152
  6. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +627 -819
  7. package/browser-runtime/ai/browser-wasm.mjs +24 -35
  8. package/browser-runtime/ai/browser-wllama-runtime.mjs +64 -316
  9. package/browser-runtime/ai/model-controller.mjs +584 -181
  10. package/browser-runtime/ai/speech-worker-client.mjs +8 -146
  11. package/browser-runtime/ai/speech-worker-runtime.mjs +643 -363
  12. package/browser-runtime/dom-event-instrumentation.mjs +55 -147
  13. package/browser-runtime/event-manager.mjs +239 -624
  14. package/package.json +5 -6
  15. package/runtime/arcane/components/app-bar.html +3 -15
  16. package/runtime/arcane/components/assistant-panel.html +10 -10
  17. package/runtime/arcane/components/calculator.html +1 -1
  18. package/runtime/arcane/components/chat.html +1359 -135
  19. package/runtime/arcane/components/conversation-view.html +2 -2
  20. package/runtime/arcane/components/document-inspector.html +11 -17
  21. package/runtime/arcane/components/file-manager.html +13 -56
  22. package/runtime/arcane/components/markdown-document.html +82 -281
  23. package/runtime/arcane/components/markdown-editor.html +7 -10
  24. package/runtime/arcane/components/media-embed.html +6 -6
  25. package/runtime/arcane/components/screen-capture.html +4 -4
  26. package/runtime/arcane/components/source-explanation.html +2 -2
  27. package/runtime/arcane/components/speech.html +112 -68
  28. package/runtime/arcane/components/terminal-workspace.html +4 -4
  29. package/runtime/arcane/components/theme-editor.html +1 -1
  30. package/runtime/arcane/components/unified-inbox.html +2 -2
  31. package/runtime/arcane/components/voice-transcription.html +31 -21
  32. package/runtime/arcane/entities/Calculation.js +2 -3
  33. package/runtime/arcane/entities/Chat.js +228 -43
  34. package/runtime/arcane/entities/Preference.js +3 -5
  35. package/runtime/arcane/entities/Weather.js +5 -5
  36. package/runtime/arcane/modules/AI.js +1050 -427
  37. package/runtime/arcane/modules/AIProviderRuntime.js +658 -363
  38. package/runtime/arcane/modules/AIResponseLength.js +9 -19
  39. package/runtime/arcane/modules/AIRuntimeState.js +109 -72
  40. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +45 -32
  41. package/runtime/arcane/modules/BrowserTestSuite.js +78 -122
  42. package/runtime/arcane/modules/CalculatorEngine.js +9 -9
  43. package/runtime/arcane/modules/CommunicationAppController.js +3 -7
  44. package/runtime/arcane/modules/ComponentContracts.js +30 -32
  45. package/runtime/arcane/modules/ConfiguredAIChatSession.js +281 -230
  46. package/runtime/arcane/modules/ConversationActionItems.js +26 -59
  47. package/runtime/arcane/modules/ConversationClosingReport.js +34 -61
  48. package/runtime/arcane/modules/ConversationTimebox.js +27 -15
  49. package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +152 -344
  50. package/runtime/arcane/modules/DocumentLexicalSearch.js +25 -91
  51. package/runtime/arcane/modules/HTMLImport.js +54 -1
  52. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +40 -203
  53. package/runtime/arcane/modules/LocalAIReadiness.js +40 -60
  54. package/runtime/arcane/modules/LocalAIReadinessController.js +15 -13
  55. package/runtime/arcane/modules/MD.js +1 -45
  56. package/runtime/arcane/modules/Mail.js +51 -103
  57. package/runtime/arcane/modules/MailOutbox.mjs +95 -193
  58. package/runtime/arcane/modules/MailTransport.mjs +36 -57
  59. package/runtime/arcane/modules/ModelDefinition.js +22 -106
  60. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +39 -101
  61. package/runtime/arcane/modules/PersistentAIChatSession.js +281 -18
  62. package/runtime/arcane/modules/PreferenceStore.js +102 -30
  63. package/runtime/arcane/modules/RiskSignalAnalyzer.js +8 -9
  64. package/runtime/arcane/modules/ScopedOPFSCache.js +7 -42
  65. package/runtime/arcane/modules/ScreenCapture.js +175 -128
  66. package/runtime/arcane/modules/SpeechPlayback.js +46 -149
  67. package/runtime/arcane/modules/StaticDocumentCatalog.js +173 -407
  68. package/runtime/arcane/modules/ToolCallRouter.js +25 -12
  69. package/runtime/arcane/modules/YouTubeMedia.js +6 -5
  70. package/schemas/arcane-app-bundle.schema.json +13 -78
  71. package/schemas/arcane-app.schema.json +9 -25
  72. package/schemas/arcane-lock.schema.json +18 -151
  73. package/schemas/arcane-package.schema.json +2 -16
  74. package/schemas/native-build-plan.schema.json +119 -122
  75. package/src/app-descriptor.mjs +75 -132
  76. package/src/application-tests.mjs +200 -0
  77. package/src/cli/main.mjs +27 -46
  78. package/src/constants.mjs +3 -4
  79. package/src/dev-server.mjs +30 -324
  80. package/src/doctor.mjs +92 -154
  81. package/src/dom-event-instrumentation.mjs +55 -147
  82. package/src/errors.mjs +2 -3
  83. package/src/event-manager.mjs +239 -624
  84. package/src/event-queue.mjs +3 -3
  85. package/src/import-map.mjs +273 -1028
  86. package/src/index.mjs +14 -16
  87. package/src/installed-sdk-runtime.mjs +40 -62
  88. package/src/integrated-provider-loader.mjs +53 -382
  89. package/src/mail-api.mjs +0 -2
  90. package/src/mail-server.mjs +224 -580
  91. package/src/mail.mjs +4 -10
  92. package/src/native-plan.mjs +163 -598
  93. package/src/native-provider-loader.mjs +104 -1063
  94. package/src/packager/core.mjs +485 -3229
  95. package/src/process.mjs +5 -10
  96. package/src/release-bundle.mjs +292 -2405
  97. package/src/runtime.mjs +76 -396
  98. package/src/scaffold.mjs +30 -80
  99. package/src/sdk-browser-runtime.mjs +70 -626
  100. package/src/source-server.mjs +588 -0
  101. package/src/targets/index.mjs +78 -188
  102. package/src/templates/workspace-template.mjs +19 -135
  103. package/src/testing-loader.mjs +164 -0
  104. package/src/testing.mjs +1 -1
  105. package/src/toolchain.mjs +131 -544
  106. package/src/update-check.mjs +26 -64
  107. package/src/workspace-operation-lock.mjs +139 -430
  108. package/src/workspace-runtime.mjs +112 -779
  109. package/src/workspace.mjs +40 -302
  110. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +0 -218
  111. package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +0 -203
  112. package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +0 -80
  113. package/browser-runtime/ai/internal/sha256.mjs +0 -166
  114. package/docs/architecture.md +0 -344
  115. package/docs/compatibility.md +0 -36
  116. package/docs/event-manager.md +0 -294
  117. package/docs/platform-targets.md +0 -108
  118. package/docs/publishing.md +0 -201
  119. package/docs/reference/README.md +0 -187
  120. package/docs/reference/ai/browser-speech-package-authority.json +0 -835
  121. package/docs/reference/ai/browser-speech.md +0 -1252
  122. package/docs/reference/ai/browser-wasm.md +0 -530
  123. package/docs/reference/arcane-ollama.md +0 -288
  124. package/docs/reference/availability-and-normalization.md +0 -183
  125. package/docs/reference/behavioral-testing.md +0 -133
  126. package/docs/reference/cli.md +0 -779
  127. package/docs/reference/core/README.md +0 -62
  128. package/docs/reference/core/arcane-ai-contracts.md +0 -907
  129. package/docs/reference/core/arcane-api.md +0 -601
  130. package/docs/reference/core/arcane-entities.md +0 -65
  131. package/docs/reference/core/arcane-events.md +0 -134
  132. package/docs/reference/core/ollama-module.md +0 -181
  133. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +0 -1909
  134. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +0 -1057
  135. package/docs/reference/core/reference/arcane-api/core-and-events.md +0 -320
  136. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +0 -610
  137. package/docs/reference/core/reference/arcane-api/namespaces.md +0 -1157
  138. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +0 -1423
  139. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +0 -315
  140. package/docs/reference/event-manager.md +0 -1511
  141. package/docs/reference/inventory/package-api.json +0 -3284
  142. package/docs/reference/inventory/runtime-components.json +0 -1011
  143. package/docs/reference/inventory/runtime-entities.json +0 -26
  144. package/docs/reference/inventory/runtime-modules.json +0 -1431
  145. package/docs/reference/mail.md +0 -316
  146. package/docs/reference/protocols.md +0 -677
  147. package/docs/reference/runtime-components.md +0 -1366
  148. package/docs/reference/runtime-entities.md +0 -303
  149. package/docs/reference/runtime-modules.md +0 -2960
  150. package/docs/reference/sdk-api.md +0 -6694
  151. package/docs/roadmap.md +0 -79
  152. package/docs/work-amplification.md +0 -129
  153. package/runtime/ARCANE_RUNTIME_RELEASE.json +0 -826
@@ -1,1511 +0,0 @@
1
- # EventManager and time-travel diagnostics
2
-
3
- `arcaneEvents` gives Arcane SDK publishers one canonical synchronous event
4
- authority per JavaScript realm. `EventManager` remains the constructor for an
5
- isolated strict pub/sub bus and optional bounded diagnostic timeline. Use source
6
- handles for SDK semantic events; use isolated managers for local diagnostics,
7
- DOM capture, export, and review.
8
-
9
- The API is capability-first:
10
-
11
- - ordinary pub/sub works in Node and browser JavaScript;
12
- - duplicate module URLs reuse the same branded `globalThis.arcaneEvents` value;
13
- - canonical occurrences expose only deeply frozen privacy-admitted public detail;
14
- - rich compatibility detail remains local to source listeners and DOM projection;
15
- - recording creates immutable, normalized `arcane-event-stack/1` records;
16
- - browser DOM capture is opt-in and privacy-preserving by default;
17
- - review playback is safe by default; live event redispatch is explicitly effectful;
18
- - no event stack is uploaded, persisted, bridged to Core, or sent to a cloud service
19
- automatically.
20
-
21
- All 32 JavaScript exports are available from both `arcane-os` and
22
- `arcane-os/event-manager`. The bindings are identical, so choose the focused
23
- subpath when event instrumentation is the only SDK capability you need. Node
24
- can resolve either package entrypoint. The generated browser map intentionally
25
- exposes only the focused `arcane-os/event-manager` entry, not the Node package
26
- root.
27
-
28
- ## Quick start
29
-
30
- ```javascript
31
- import {
32
- arcaneEvents,
33
- createArcaneEventSource,
34
- createEventManager,
35
- projectArcaneDOMEvent,
36
- PLAYBACK_RECORD_EVENT
37
- } from 'arcane-os/event-manager';
38
-
39
- const events=createArcaneEventSource(editorController,{
40
- source:'app.editor',
41
- eventTypes:['document.save.completed']
42
- });
43
-
44
- const unsubscribe=arcaneEvents.subscribe('document.save.completed',occurrence=>{
45
- console.info('Saved',occurrence.detail.documentId);
46
- });
47
-
48
- const publication=events.dispatch(
49
- 'document.save.completed',
50
- Object.freeze({documentId:'example',document:liveDocument}),
51
- {operationId:'save-42',publicDetail:{documentId:'example'}}
52
- );
53
- projectArcaneDOMEvent(editorElement,publication.occurrence);
54
- unsubscribe();
55
-
56
- const diagnostics=createEventManager({timeTravel:true});
57
- const stack=diagnostics.exportStack();
58
- diagnostics.on(PLAYBACK_RECORD_EVENT,record=>console.info(record.type));
59
- await diagnostics.playback({stack,mode:'review',speed:0});
60
- ```
61
-
62
- Recording is disabled by default. Keep isolated diagnostic sessions bounded,
63
- export intentionally, then call `clearHistory()`.
64
-
65
- ## Availability and normalization
66
-
67
- | Capability | Node | Browser renderer | Native/Core host | Remote or cloud | Normalization |
68
- | --- | --- | --- | --- | --- | --- |
69
- | Canonical per-realm authority and source occurrences | Yes | Yes, per window or worker realm | Only when the SDK module runs in that JavaScript realm | No automatic transport | `arcane-event-authority/1`, `arcane-event-source/1`, and `arcane-event-occurrence/1` |
70
- | Pub/sub, semantic instrumentation, parse/export, seek, playback | Yes | Yes, through a bundler or the managed Arcane import map | Only when the SDK module runs in that JavaScript host | No automatic transport | Same synchronous API; optional immutable JSON-like snapshots |
71
- | DOM selectors and target descriptions | With DOM-like values or a test shim | Yes | No native UI observation | No | Stable diagnostic descriptors |
72
- | DOM interaction and mutation capture | No native DOM | Yes | No | No | DOM activity becomes semantic event-stack records |
73
- | Event-stack schema | Yes | Yes | Data contract only | Can be transported explicitly by the developer | `arcane-event-stack/1` |
74
-
75
- In an external or physical-v1 integrated workspace, the managed browser map
76
- resolves `arcane-os/event-manager` to
77
- `./arcane/sdk/event-manager.mjs` and its private bare dependency
78
- `event-pubsub` to
79
- `./arcane/sdk/dependencies/event-pubsub/index.js`. The canonical
80
- integrated-legacy workspace retains its older physical routes instead. The
81
- hash-pinned Arcane browser runtime does not inject this SDK-authored module into
82
- Shell, Provisioner, Core, or built-in apps. There is no transparent fallback to
83
- the Node package root, `arcane/1`, HTTP, WebSocket, Ollama, or a cloud event
84
- service.
85
-
86
- ## Export summary
87
-
88
- | Export | Kind | Primary capability |
89
- | --- | --- | --- |
90
- | `ARCANE_EVENT_STACK_PROTOCOL` | String constant | Identify the durable stack format |
91
- | `ARCANE_EVENT_AUTHORITY_PROTOCOL` | String constant | Identify singleton authority compatibility |
92
- | `ARCANE_EVENT_OCCURRENCE_PROTOCOL` | String constant | Identify canonical occurrences |
93
- | `ARCANE_EVENT_SOURCE_PROTOCOL` | String constant | Identify source handles |
94
- | `ARCANE_EVENT_AUTHORITY_BRAND` | Global symbol | Inspect the authority brand descriptor |
95
- | `ARCANE_EVENT_AUTHORITY_KIND` | String constant | Identify an authority descriptor |
96
- | `ARCANE_EVENT_SOURCE_KIND` | String constant | Identify a source descriptor |
97
- | `ARCANE_EVENT_LISTENER_ERROR_EVENT` | String constant | Observe privacy-safe listener failures |
98
- | `ARCANE_EVENT_SOURCE_DISPOSED_EVENT` | String constant | Observe a source's final occurrence |
99
- | `ARCANE_EVENT_ERROR_CODES` | Frozen object | Match stable authority error codes |
100
- | `TIME_TRAVEL_SEEK_EVENT` | String constant | Observe review-cursor movement |
101
- | `PLAYBACK_STARTED_EVENT` | String constant | Observe playback startup |
102
- | `PLAYBACK_RECORD_EVENT` | String constant | Receive safe review records |
103
- | `PLAYBACK_COMPLETED_EVENT` | String constant | Observe successful completion |
104
- | `PLAYBACK_CANCELLED_EVENT` | String constant | Observe cancellation |
105
- | `PLAYBACK_FAILED_EVENT` | String constant | Observe playback failure |
106
- | `TIME_TRAVEL_OVERFLOW_EVENT` | String constant | Identify the terminal retention marker |
107
- | `DOM_INTERACTION_EVENT` | String constant | Identify normalized DOM interactions |
108
- | `DOM_MUTATION_EVENT` | String constant | Identify normalized DOM mutations |
109
- | `DOM_OBSERVATION_STARTED_EVENT` | String constant | Identify DOM-capture startup |
110
- | `DOM_OBSERVATION_STOPPED_EVENT` | String constant | Identify DOM-capture shutdown |
111
- | `DEFAULT_DOM_EVENT_TYPES` | Frozen string array | Use Arcane's default DOM capture set |
112
- | `domSelector()` | Function | Build a diagnostic DOM locator |
113
- | `describeDOMTarget()` | Function | Normalize a DOM event target |
114
- | `createDOMInstrumentation()` | Function | Attach interaction and mutation capture |
115
- | `parseEventStack()` | Function | Strictly import and freeze a stack |
116
- | `EventManager` | Class | Create an isolated bus and timeline |
117
- | `createEventManager()` | Function | Create an `EventManager` |
118
- | `arcaneEvents` | Branded `EventManager` authority | Observe canonical SDK events in this realm |
119
- | `createArcaneEventSource()` | Function | Register one declared semantic source per owner |
120
- | `projectArcaneDOMEvent()` | Function | Project one occurrence to one `CustomEvent` |
121
- | `isArcaneEventOccurrence()` | Function | Recognize authority-created occurrences and views |
122
-
123
- ## `EventManager`
124
-
125
- ### Overview
126
-
127
- Creates an isolated synchronous `event-pubsub` bus. Time-travel recording,
128
- snapshot capture, retention, DOM observation, import/export, cursor movement, and
129
- playback are layered around that bus.
130
-
131
- ### Constructor
132
-
133
- ```javascript
134
- new EventManager({
135
- timeTravel=false,
136
- dom=null,
137
- captureStacks=false,
138
- redactSensitive=true,
139
- maxEvents=10_000,
140
- maxSnapshotDepth=50,
141
- maxSnapshotEntries=1_000,
142
- maxSnapshotStringLength=10_000,
143
- clock=()=>new Date(),
144
- now=performance.now-or-Date.now,
145
- sessionId=randomUUID-or-local-id
146
- }={})
147
- ```
148
-
149
- `dom` may be a root directly or an options object containing `root`. Source and
150
- error stacks are omitted unless `captureStacks` is true. Redaction, depth, entry,
151
- string, and retention bounds are applied before records enter history.
152
- `maxSnapshotStringLength` defaults to 10,000 and must be a safe integer of at
153
- least 64; the other numeric retention limits must be positive safe integers.
154
-
155
- ### Properties
156
-
157
- | Property | Value |
158
- | --- | --- |
159
- | `list` | Underlying subscriber registry from `event-pubsub` |
160
- | `sessionId` | Current non-empty session identifier, at most 256 characters |
161
- | `timeTravelEnabled` | Whether new string-typed events are being recorded |
162
- | `replaying` | Whether playback is active |
163
- | `cursor` | Current sequence selected or delivered; `0` means before the first event |
164
- | `eventCount` | Retained record count, including an overflow marker |
165
- | `maxEvents` | Configured ordinary-record limit |
166
- | `overflowed` | Whether retention ended with an overflow marker |
167
- | `history` | Frozen array copy of immutable records |
168
- | `domInstrumentation` | Attached DOM controller or `null` |
169
-
170
- ### Methods
171
-
172
- #### `on(type, handler, once=false)`
173
-
174
- Registers a synchronous handler and returns the manager.
175
-
176
- #### `once(type, handler)`
177
-
178
- Registers a synchronous one-shot handler and returns the manager.
179
-
180
- #### `off(type='*', handler='*')`
181
-
182
- Removes matching subscriptions and returns the manager.
183
-
184
- #### `reset()`
185
-
186
- Clears subscriptions and returns the manager. It does not clear recorded history.
187
-
188
- #### `emit(type, ...payload)`
189
-
190
- Synchronously delivers arbitrary payload arguments. String event types are
191
- recorded while time travel is enabled. Non-string types are delivered without a
192
- record. Subscriber exceptions are recorded as a failed dispatch and rethrown.
193
- Subscriber promises are not awaited.
194
-
195
- ```javascript
196
- events.on('ready',(documentId,revision)=>console.info(documentId,revision));
197
- events.emit('ready','document-7',3);
198
- ```
199
-
200
- #### `instrument(type, payload, metadata={})`
201
-
202
- Delivers one semantic payload and records optional `source`, `category`,
203
- `correlationId`, and `causationId` metadata.
204
-
205
- ```javascript
206
- events.instrument('sync.completed',{count:12},{
207
- source:'app:library',
208
- category:'operation',
209
- correlationId:'sync-9'
210
- });
211
- ```
212
-
213
- #### `forward(event, metadata={})`
214
-
215
- Requires a non-array object with a string `type`, then instruments that object as
216
- the event's single payload. SDK operation queues use this shape to mirror their
217
- already-normalized events through `arcaneEvents` once.
218
-
219
- #### `enableTimeTravel({dom}={})`
220
-
221
- Enables recording and optionally attaches DOM capture. An overflowed manager must
222
- be cleared before it can be enabled again.
223
-
224
- #### `disableTimeTravel()`
225
-
226
- Stops attached DOM capture, records its stopped lifecycle boundary, disables
227
- recording, and returns the manager.
228
-
229
- #### `attachDOM(root=globalThis.document, options={})`
230
-
231
- Stops and replaces the current DOM controller. The new controller starts
232
- immediately when recording is enabled. Returns the controller.
233
-
234
- Attaching at the exact retention limit causes the DOM-start event to trigger the
235
- normal terminal overflow path. In that case the returned controller is inactive,
236
- `timeTravelEnabled` is false, `overflowed` is true, and the final retained record
237
- is the overflow marker. No stopped lifecycle record is appended after it.
238
-
239
- #### `detachDOM()`
240
-
241
- Stops DOM capture, clears the controller, and returns the manager.
242
-
243
- #### `clearHistory({newSession=true}={})`
244
-
245
- Clears history, sequence, cursor, and overflow state. By default it creates a new
246
- session identifier; pass `newSession:false` to retain the existing identifier.
247
- History cannot be cleared during synchronous dispatch or playback.
248
-
249
- #### `getEventStack({fromSequence=1, toSequence=Number.MAX_SAFE_INTEGER, type=null}={})`
250
-
251
- Returns a frozen array of records within the inclusive sequence range, optionally
252
- restricted to one exact event type.
253
-
254
- #### `exportStack({space=2}={})`
255
-
256
- Returns a JSON document with the current session and retained history. `space`
257
- must be a safe integer from 0 through 10. Export does not write a file, persist,
258
- upload, or transmit anything.
259
-
260
- #### `seek(sequence)`
261
-
262
- Moves the review cursor to `0` or an existing sequence, emits
263
- `TIME_TRAVEL_SEEK_EVENT`, and returns the selected record or `null` for zero.
264
- Seeking never rewrites DOM, storage, native state, processes, or network state.
265
-
266
- #### `playback(options={})`
267
-
268
- ```javascript
269
- await events.playback({
270
- stack:null,
271
- fromSequence:1,
272
- toSequence:Number.MAX_SAFE_INTEGER,
273
- speed:0,
274
- mode:'review',
275
- signal,
276
- onRecord
277
- });
278
- ```
279
-
280
- Only one playback may run at a time. `stack:null` uses current history; a string
281
- or object is passed through `parseEventStack()`. Recording is suppressed during
282
- playback.
283
-
284
- | Mode | Behavior | Safety |
285
- | --- | --- | --- |
286
- | `review` | Emits every immutable record as `PLAYBACK_RECORD_EVENT` | Default; intended for debugger and timeline UIs |
287
- | `events` | Redispatches `record.type` with the normalized payload arguments | Effectful; use only in an isolated harness |
288
- | `none` | Emits no per-record bus event; only invokes `onRecord` | Useful for controlled analysis |
289
-
290
- `speed:0` delivers immediately. A positive speed preserves recorded monotonic
291
- delays, divided by the multiplier. `onRecord(record)` may be async and is awaited.
292
- An `AbortSignal` cancels waiting or delivery; playback emits exactly one terminal
293
- completed, cancelled, or failed lifecycle event, rejects on cancellation/failure,
294
- and restores `replaying` in all cases.
295
-
296
- ### Availability and normalization
297
-
298
- The class is host-neutral JavaScript in Node and browser module graphs. DOM capture
299
- requires a browser-compatible root. Event values are delivered to live subscribers
300
- unchanged; only the optional historical copy is normalized.
301
-
302
- ### Example
303
-
304
- ```javascript
305
- import {EventManager} from 'arcane-os/event-manager';
306
-
307
- const events=new EventManager({timeTravel:true,maxEvents:500});
308
- events.emit('workspace.opened',{workspaceId:'local-demo'});
309
- console.info(events.history[0].status); // "completed"
310
- events.clearHistory();
311
- ```
312
-
313
- ## `createEventManager()`
314
-
315
- ### Overview
316
-
317
- Convenience factory equivalent to `new EventManager(options)`.
318
-
319
- ### Signature
320
-
321
- ```javascript
322
- createEventManager(options)
323
- ```
324
-
325
- ### Availability and normalization
326
-
327
- Node and browser JavaScript; identical behavior to the constructor.
328
-
329
- ### Example
330
-
331
- ```javascript
332
- import {createEventManager} from 'arcane-os/event-manager';
333
- const events=createEventManager({timeTravel:true,maxEvents:1_000});
334
- ```
335
-
336
- ## `arcaneEvents`
337
-
338
- ### Overview
339
-
340
- The SDK's canonical per-realm event authority. Module evaluation first inspects
341
- the own descriptor of `globalThis.arcaneEvents`. If absent, it constructs,
342
- brands, and installs one authority as a non-enumerable, non-writable,
343
- non-configurable data property. A duplicate module URL validates and reuses that
344
- exact object without constructing a transient second bus. Accessor collisions,
345
- unbranded values, malformed descriptors, incompatible protocols, and incomplete
346
- APIs fail closed with stable `ARCANE_EVENT_AUTHORITY_*` codes.
347
-
348
- ### Value
349
-
350
- ```javascript
351
- globalThis.arcaneEvents === arcaneEvents
352
- arcaneEvents.protocol === 'arcane-event-authority/1'
353
- arcaneEvents[ARCANE_EVENT_AUTHORITY_BRAND] === 'arcane-event-authority/1'
354
- ```
355
-
356
- ### Availability and normalization
357
-
358
- Exactly one authority per JavaScript realm. A window, worker, frame, Node realm,
359
- or process has its own boundary. Nothing automatically transports occurrences
360
- to another realm, Core, a native host, or a remote service.
361
-
362
- `subscribe(type,handler,{once=false,signal}={})` observes one exact canonical
363
- event type. `handler` is a function or EventListener object and receives the
364
- canonical occurrence as its sole argument. The returned idempotent unsubscribe
365
- has `unsubscribe.dispose === unsubscribe`. An already-aborted signal installs
366
- nothing; later abort marks the listener inactive synchronously and removes it
367
- without corrupting an in-progress dispatch. `'*'` is not a canonical subscription
368
- type.
369
-
370
- `createSource(owner,{source,eventTypes,onListenerError?})` is the authority
371
- method used by the exported
372
- `createArcaneEventSource(owner,{source,eventTypes,onListenerError?})` wrapper.
373
- Both return the same frozen singleton-backed source handle; neither constructs
374
- an EventManager, EventTarget, or component-local bus.
375
-
376
- `addEventListener()` and `removeEventListener()` expose EventTarget-shaped
377
- canonical registration, including function/EventListener-object callbacks,
378
- type/listener/capture deduplication, `once`, and `signal`. They return
379
- `undefined`. Authority-level `dispatchEvent()` is a deprecated admission adapter
380
- for older `aiRuntimeEvents` callers. It accepts an Event-like value with a valid
381
- type and data `detail`, creates one new occurrence from source
382
- `event-target-compatibility`, preserves preexisting and observer cancellation,
383
- and never uses raw `EventManager.emit()` as a parallel path.
384
-
385
- The inherited `on`, `once`, `off`, `reset`, `emit`, `instrument`, and `forward`
386
- surface is retained for legacy direct diagnostics. Its registrations are
387
- separate: source dispatch does not re-emit raw compatibility detail to legacy
388
- listeners, and legacy `off()`/`reset()` cannot remove canonical or source-owned
389
- registrations. New SDK publishers use `createArcaneEventSource()`.
390
-
391
- ### Example
392
-
393
- ```javascript
394
- import {arcaneEvents} from 'arcane-os/event-manager';
395
-
396
- const unsubscribe=arcaneEvents.subscribe('sdk.operation.completed',occurrence=>{
397
- console.info(occurrence.occurrenceId,occurrence.detail);
398
- });
399
- unsubscribe();
400
- ```
401
-
402
- ## `createArcaneEventSource()`
403
-
404
- ### Overview
405
-
406
- Registers one active semantic source for a non-null object or function owner.
407
- The options object has only `source`, `eventTypes`, and optional
408
- `onListenerError`. Source and event names are trimmed lowercase identifiers of
409
- at most 128 characters matching
410
- `^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$`. `eventTypes` contains 1 through 256 unique
411
- declared types. A second active source for the same owner fails closed.
412
-
413
- ### Signature and result
414
-
415
- ```text
416
- createArcaneEventSource(owner, options)
417
- ```
418
-
419
- ```javascript
420
- const source=createArcaneEventSource(owner,{
421
- source:'sdk.document-store',
422
- eventTypes:['document.saved'],
423
- onListenerError(error,errorOccurrence){
424
- reportOwnerLocalFailure(error,errorOccurrence?.occurrenceId??null);
425
- }
426
- });
427
- ```
428
-
429
- The returned handle and its descriptor are frozen. The descriptor identifies
430
- `arcane-event-source/1`, the stable source name, an authority-sequenced opaque
431
- `arcane-source-<base36>` instance id, and the declared event types plus the final
432
- `arcane.event.source.disposed` event. IDs are unique only during one authority's
433
- lifetime in one realm.
434
-
435
- The authority descriptor is exactly
436
- `{kind:'arcane-event-authority',protocol:'arcane-event-authority/1',realm:'current'}`.
437
- The source descriptor is exactly
438
- `{kind:'arcane-event-source',protocol:'arcane-event-source/1',source,instanceId,
439
- eventTypes}`; `eventTypes` is frozen and includes the declared types followed by
440
- `arcane.event.source.disposed`.
441
-
442
- ### Dispatch
443
-
444
- ```javascript
445
- const {occurrence,accepted}=source.dispatch(
446
- 'document.saved',
447
- Object.freeze({document:liveDocument,documentId:'document-7'}),
448
- {
449
- operationId:'save-42',
450
- publicDetail:{documentId:'document-7'},
451
- cancelable:true
452
- }
453
- );
454
- ```
455
-
456
- `dispatch()` is synchronous. Exact canonical subscribers run first in
457
- registration order, followed by this source's exact `on()`/EventListener
458
- registrations in registration order. Source listeners receive one frozen
459
- EventTarget-compatible view whose `detail` is the locally held compatibility
460
- detail, whose `target` and `currentTarget` are the source owner, and whose
461
- cancellation state is shared with the occurrence. Function listeners also
462
- receive that owner as `this`. The public
463
- occurrence contains:
464
-
465
- ```javascript
466
- {
467
- protocol:'arcane-event-occurrence/1',
468
- occurrenceId:'arcane-event-<base36>',
469
- type,
470
- source,
471
- instanceId,
472
- operationId, // string or null
473
- detail, // defensive, privacy-admitted, deeply frozen snapshot
474
- cancelable,
475
- get defaultPrevented(),
476
- preventDefault()
477
- }
478
- ```
479
-
480
- The frozen result is `{occurrence,accepted:!occurrence.defaultPrevented}`.
481
- Cancellation does not roll back domain work automatically. All active listeners
482
- run even when one prevents default or throws. Listener exceptions create one
483
- nonrecursive, privacy-safe `arcane.event.listener.error` occurrence and are
484
- reported through `reportError` or `console.error`; committed source dispatch does
485
- not throw because an observer failed. `onListenerError(error,errorOccurrence)`
486
- is invoked synchronously only at the source-owner boundary after canonical error
487
- publication and platform reporting. Its second argument is the canonical
488
- listener-error occurrence, or `null` only if that secondary publication could
489
- not be constructed. If the callback throws, its failure is reported directly
490
- without another listener-error occurrence. The listener-error public detail is
491
- exactly `{code:'ARCANE_EVENT_LISTENER_CALLBACK_FAILED',reason:'listener-threw',
492
- eventType,occurrenceId,source,instanceId,operationId}`.
493
-
494
- Canonical publication never awaits a listener return value and exposes no
495
- Promise-returning publication API. Domain promises and `createEventQueue()` own
496
- asynchronous work, ordered callback backpressure, and async failure. Synchronous
497
- source generation, occurrence creation, sticky state commits, subscription
498
- installation, and cancellation admission stay on the authority call stack.
499
-
500
- `on(type,handler,{once=false,signal}={})` and `subscribe()` on the source are
501
- aliases returning an idempotent disposable unsubscribe. `once()` is the
502
- one-delivery form. `addEventListener()`/`removeEventListener()` use EventTarget
503
- deduplication, ignore null or non-listener callbacks, and return `undefined`.
504
- The stricter `on()`/`subscribe()` APIs reject invalid handlers.
505
- `dispatchEvent(event)` is a compatibility
506
- adapter that accepts only a declared type, preserves cancellation, and publishes
507
- a new canonical occurrence rather than the raw input.
508
-
509
- `dispose()` is idempotent: the first call publishes the final noncancelable
510
- `arcane.event.source.disposed` occurrence, removes source-owned registrations,
511
- and returns `true`; reentrant or later calls return `false`. Dispatch or new
512
- registration after disposal fails with `ARCANE_EVENT_SOURCE_DISPOSED`. The owner
513
- may register a new source after disposal. Its compatibility detail is
514
- `{source,instanceId,reason:'source-disposed'}` and its public detail is
515
- `{reason:'source-disposed'}`. `destroy()` aliases `dispose()`.
516
-
517
- Already-frozen compatibility detail retains its identity. Other rich
518
- compatibility detail is shallow-copied and frozen when it is a plain record or
519
- array; host objects such as DOM nodes, `File`, or `Error` remain local and are
520
- not recursively frozen. Compatibility detail never enters canonical
521
- EventPubSub/time-travel payloads. Only privacy-admitted `publicDetail` enters the
522
- occurrence and optional diagnostics.
523
-
524
- ### Availability and normalization
525
-
526
- **Node and browser/bundler, within the current JavaScript realm.** This wrapper
527
- reuses `globalThis.arcaneEvents`; it creates no second bus or asynchronous work
528
- owner. Admission, publication, cancellation, and teardown remain synchronous.
529
-
530
- ### Example
531
-
532
- ```javascript
533
- import {createArcaneEventSource} from 'arcane-os/event-manager';
534
-
535
- const source=createArcaneEventSource({}, {
536
- source:'sdk.example',
537
- eventTypes:['sdk.example.completed']
538
- });
539
- source.dispatch('sdk.example.completed',{}, {publicDetail:{status:'completed'}});
540
- source.dispose();
541
- ```
542
-
543
- ## `projectArcaneDOMEvent()`
544
-
545
- ### Overview
546
-
547
- Projects one authority-created occurrence to one `CustomEvent`. This is a
548
- one-way compatibility boundary; DOM dispatch never republishes into
549
- `arcaneEvents`.
550
-
551
- ### Signature and result
552
-
553
- ```text
554
- projectArcaneDOMEvent(target, occurrence, options)
555
- ```
556
-
557
- ```javascript
558
- projectArcaneDOMEvent(target,occurrence,{
559
- type=occurrence.type,
560
- bubbles=false,
561
- composed=false,
562
- cancelable=occurrence.cancelable
563
- }={})
564
- ```
565
-
566
- The authority retrieves the centrally held compatibility detail, creates a
567
- frozen outer projection detail, and additively supplies `occurrenceId`, `source`,
568
- `arcaneSource`, `instanceId`, and `operationId`. `arcaneSource` is always the
569
- canonical emitter identity. A caller-owned compatibility `source` value is
570
- preserved; when absent, `source` is added as an alias of `arcaneSource`. A
571
- conflicting caller-owned reserved metadata value fails
572
- with `ARCANE_EVENT_DOM_DETAIL_COLLISION`. If the occurrence is already canceled,
573
- the function skips DOM dispatch and returns `false`. Otherwise it dispatches
574
- exactly one event, propagates DOM cancellation to a cancelable occurrence, and
575
- returns the combined acceptance result.
576
-
577
- ### Availability and normalization
578
-
579
- **Browser DOM or a DOM-compatible host with `CustomEvent` and
580
- `dispatchEvent`.** Only an occurrence created by this realm's authority is
581
- accepted. Projection is synchronous and one-way and creates no listener state.
582
-
583
- ### Example
584
-
585
- ```javascript
586
- import {projectArcaneDOMEvent} from 'arcane-os/event-manager';
587
-
588
- projectArcaneDOMEvent(button,publication.occurrence,{bubbles:true});
589
- ```
590
-
591
- ## `isArcaneEventOccurrence()`
592
-
593
- ### Overview
594
-
595
- Returns `true` only for a canonical occurrence or source compatibility view
596
- created by the current realm's authority. It does not authenticate hostile
597
- same-realm code; the brand and protocol are compatibility boundaries.
598
-
599
- ### Signature and result
600
-
601
- ```text
602
- isArcaneEventOccurrence(value)
603
- ```
604
-
605
- Returns a boolean; a structurally similar foreign value returns `false`.
606
-
607
- ### Availability and normalization
608
-
609
- **Node and browser/bundler, within the current JavaScript realm.** Recognition
610
- is synchronous and identity-based, with no parsing, cloning, or transport.
611
-
612
- ### Example
613
-
614
- ```javascript
615
- import {isArcaneEventOccurrence} from 'arcane-os/event-manager';
616
-
617
- console.log(isArcaneEventOccurrence(publication.occurrence));
618
- ```
619
-
620
- ## `ARCANE_EVENT_AUTHORITY_BRAND`
621
-
622
- ### Overview
623
-
624
- Global registry symbol that brands the one compatible authority in a realm.
625
-
626
- ### Value and import
627
-
628
- ```text
629
- const ARCANE_EVENT_AUTHORITY_BRAND
630
- ```
631
-
632
- Its exact value is `Symbol.for('arcane-os.arcane-events-authority')`.
633
-
634
- ### Availability and normalization
635
-
636
- **Node and browser/bundler.** The brand property is an immutable,
637
- non-enumerable compatibility marker, not cross-realm transport or authenticity.
638
-
639
- ### Example
640
-
641
- ```javascript
642
- import {ARCANE_EVENT_AUTHORITY_BRAND,arcaneEvents} from 'arcane-os/event-manager';
643
- console.log(arcaneEvents[ARCANE_EVENT_AUTHORITY_BRAND]);
644
- ```
645
-
646
- ## `ARCANE_EVENT_AUTHORITY_KIND`
647
-
648
- ### Overview
649
-
650
- Stable kind discriminator for the frozen authority descriptor.
651
-
652
- ### Value and import
653
-
654
- ```text
655
- const ARCANE_EVENT_AUTHORITY_KIND
656
- ```
657
-
658
- Its exact value is `arcane-event-authority`.
659
-
660
- ### Availability and normalization
661
-
662
- **Node and browser/bundler.** Reading it creates no authority or listener.
663
-
664
- ### Example
665
-
666
- ```javascript
667
- import {ARCANE_EVENT_AUTHORITY_KIND,arcaneEvents} from 'arcane-os/event-manager';
668
- console.log(arcaneEvents.descriptor.kind===ARCANE_EVENT_AUTHORITY_KIND);
669
- ```
670
-
671
- ## `ARCANE_EVENT_AUTHORITY_PROTOCOL`
672
-
673
- ### Overview
674
-
675
- Stable protocol discriminator for compatible per-realm authorities.
676
-
677
- ### Value and import
678
-
679
- ```text
680
- const ARCANE_EVENT_AUTHORITY_PROTOCOL
681
- ```
682
-
683
- Its exact value is `arcane-event-authority/1`.
684
-
685
- ### Availability and normalization
686
-
687
- **Node and browser/bundler.** An incompatible installed protocol fails closed
688
- and is never replaced or wrapped.
689
-
690
- ### Example
691
-
692
- ```javascript
693
- import {ARCANE_EVENT_AUTHORITY_PROTOCOL,arcaneEvents} from 'arcane-os/event-manager';
694
- console.log(arcaneEvents.protocol===ARCANE_EVENT_AUTHORITY_PROTOCOL);
695
- ```
696
-
697
- ## `ARCANE_EVENT_ERROR_CODES`
698
-
699
- ### Overview
700
-
701
- Frozen registry of every stable event-authority failure code.
702
-
703
- ### Value and import
704
-
705
- ```text
706
- const ARCANE_EVENT_ERROR_CODES
707
- ```
708
-
709
- Every key maps to its identical string value; thrown authority failures expose
710
- the matching value as `error.code`.
711
-
712
- ### Availability and normalization
713
-
714
- **Node and browser/bundler.** The registry has no mutable registration surface
715
- or vague fallback code.
716
-
717
- ### Example
718
-
719
- ```javascript
720
- import {ARCANE_EVENT_ERROR_CODES} from 'arcane-os/event-manager';
721
- console.log(ARCANE_EVENT_ERROR_CODES.ARCANE_EVENT_SOURCE_DISPOSED);
722
- ```
723
-
724
- ## `ARCANE_EVENT_LISTENER_ERROR_EVENT`
725
-
726
- ### Overview
727
-
728
- Canonical observational event emitted when an event listener throws.
729
-
730
- ### Value and import
731
-
732
- ```text
733
- const ARCANE_EVENT_LISTENER_ERROR_EVENT
734
- ```
735
-
736
- Its exact value is `arcane.event.listener.error`.
737
-
738
- ### Availability and normalization
739
-
740
- **Node and browser/bundler.** Its frozen public detail carries the exact failure
741
- code and source occurrence identifiers, never the raw error. Its shape is
742
- exactly `{code:'ARCANE_EVENT_LISTENER_CALLBACK_FAILED',reason:'listener-threw',
743
- eventType,occurrenceId,source,instanceId,operationId}`. Publication is
744
- synchronous and nonrecursive.
745
-
746
- ### Example
747
-
748
- ```javascript
749
- import {ARCANE_EVENT_LISTENER_ERROR_EVENT,arcaneEvents} from 'arcane-os/event-manager';
750
- const unsubscribe=arcaneEvents.subscribe(ARCANE_EVENT_LISTENER_ERROR_EVENT,console.log);
751
- ```
752
-
753
- ## `ARCANE_EVENT_OCCURRENCE_PROTOCOL`
754
-
755
- ### Overview
756
-
757
- Stable protocol discriminator for immutable canonical occurrences.
758
-
759
- ### Value and import
760
-
761
- ```text
762
- const ARCANE_EVENT_OCCURRENCE_PROTOCOL
763
- ```
764
-
765
- Its exact value is `arcane-event-occurrence/1`.
766
-
767
- ### Availability and normalization
768
-
769
- **Node and browser/bundler.** Occurrences are realm-owned identity values with
770
- deeply frozen public detail and synchronous cancellation state.
771
-
772
- ### Example
773
-
774
- ```javascript
775
- import {ARCANE_EVENT_OCCURRENCE_PROTOCOL} from 'arcane-os/event-manager';
776
- console.log(publication.occurrence.protocol===ARCANE_EVENT_OCCURRENCE_PROTOCOL);
777
- ```
778
-
779
- ## `ARCANE_EVENT_SOURCE_DISPOSED_EVENT`
780
-
781
- ### Overview
782
-
783
- Final noncancelable occurrence published during a source's first disposal.
784
-
785
- ### Value and import
786
-
787
- ```text
788
- const ARCANE_EVENT_SOURCE_DISPOSED_EVENT
789
- ```
790
-
791
- Its exact value is `arcane.event.source.disposed`.
792
-
793
- ### Availability and normalization
794
-
795
- **Node and browser/bundler.** Public detail is exactly
796
- `{reason:'source-disposed'}`. Delivery precedes source-listener cleanup;
797
- reentrant or later disposal publishes nothing and returns `false`.
798
-
799
- ### Example
800
-
801
- ```javascript
802
- import {ARCANE_EVENT_SOURCE_DISPOSED_EVENT} from 'arcane-os/event-manager';
803
- source.once(ARCANE_EVENT_SOURCE_DISPOSED_EVENT,console.log);
804
- source.dispose();
805
- ```
806
-
807
- ## `ARCANE_EVENT_SOURCE_KIND`
808
-
809
- ### Overview
810
-
811
- Stable kind discriminator for frozen source descriptors.
812
-
813
- ### Value and import
814
-
815
- ```text
816
- const ARCANE_EVENT_SOURCE_KIND
817
- ```
818
-
819
- Its exact value is `arcane-event-source`.
820
-
821
- ### Availability and normalization
822
-
823
- **Node and browser/bundler.** Reading it does not register or dispose a source.
824
-
825
- ### Example
826
-
827
- ```javascript
828
- import {ARCANE_EVENT_SOURCE_KIND} from 'arcane-os/event-manager';
829
- console.log(source.descriptor.kind===ARCANE_EVENT_SOURCE_KIND);
830
- ```
831
-
832
- ## `ARCANE_EVENT_SOURCE_PROTOCOL`
833
-
834
- ### Overview
835
-
836
- Stable protocol discriminator for frozen source handles and descriptors.
837
-
838
- ### Value and import
839
-
840
- ```text
841
- const ARCANE_EVENT_SOURCE_PROTOCOL
842
- ```
843
-
844
- Its exact value is `arcane-event-source/1`.
845
-
846
- ### Availability and normalization
847
-
848
- **Node and browser/bundler.** One handle belongs to one active owner in one
849
- realm and declares every publishable type before use.
850
-
851
- ### Example
852
-
853
- ```javascript
854
- import {ARCANE_EVENT_SOURCE_PROTOCOL} from 'arcane-os/event-manager';
855
- console.log(source.protocol===ARCANE_EVENT_SOURCE_PROTOCOL);
856
- ```
857
-
858
- ## `parseEventStack()`
859
-
860
- ### Overview
861
-
862
- Strictly imports a JSON string or data object, rejects ambiguous or malformed
863
- structures, returns null-prototype normalized data objects, and deeply freezes the
864
- result. Validation includes exact document/record keys, canonical timestamps,
865
- session and record identity, status-dependent completion fields, bounded nested
866
- values, increasing sequences, causal parent consistency, and overflow placement.
867
-
868
- ### Signature
869
-
870
- ```javascript
871
- parseEventStack(source, {
872
- maxEvents=10_000,
873
- maxSnapshotDepth=50,
874
- maxSnapshotEntries=1_000,
875
- maxSnapshotStringLength=10_000
876
- }={})
877
- ```
878
-
879
- All import limits must be positive safe integers, except that
880
- `maxSnapshotStringLength` has the additional minimum of 64. A valid overflowed
881
- stack may contain `maxEvents + 1` records only when its final record is the sole
882
- overflow marker.
883
-
884
- The parser binds every imported record to its enclosing document: protocol and
885
- session must match, ids must equal `${sessionId}:${sequence}`, sequences and timing
886
- must be valid, status must agree with completion/error fields, and parent,
887
- depth, and causation data must form a valid earlier-record relationship. Unknown
888
- keys, missing keys, sparse arrays, forged identities, incomplete records, and
889
- nonterminal or forged overflow markers are rejected instead of repaired.
890
-
891
- ### Availability and normalization
892
-
893
- Pure host-neutral JavaScript. It performs no I/O and does not revive tagged values
894
- into executable JavaScript types.
895
-
896
- ### Example
897
-
898
- ```javascript
899
- import {parseEventStack} from 'arcane-os/event-manager';
900
-
901
- const document=parseEventStack(receivedText,{maxEvents:2_000});
902
- for(const record of document.events)console.info(record.sequence,record.type);
903
- ```
904
-
905
- ## `createDOMInstrumentation()`
906
-
907
- ### Overview
908
-
909
- Creates a frozen, opt-in browser controller that records capture-phase DOM
910
- interactions and `MutationObserver` changes through an event manager. It observes
911
- the supplied root and, by default, open shadow roots already present or later
912
- inserted.
913
-
914
- ### Signature
915
-
916
- ```javascript
917
- createDOMInstrumentation({
918
- eventManager,
919
- root=globalThis.document,
920
- eventTypes=DEFAULT_DOM_EVENT_TYPES,
921
- MutationObserver=globalThis.MutationObserver,
922
- captureEventDetails=false,
923
- captureInputValues=false,
924
- captureNodeMarkup=false,
925
- captureMutations=true,
926
- maxValueLength=10_000,
927
- maxSerializedNodeLength=100_000,
928
- observeOpenShadowRoots=true
929
- }={})
930
- ```
931
-
932
- The returned controller exposes `root`, `start()`, `stop({emitLifecycle=true}={})`,
933
- `active`, and `observedRootCount`. Start and stop are idempotent. Startup rolls
934
- back partially attached listeners on failure; shutdown retries listener/observer
935
- cleanup and surfaces any remaining failure.
936
-
937
- ### Privacy
938
-
939
- Input values, detailed text-entry fields, and inserted/removed node markup are all
940
- off by default. Password controls, password autocomplete fields, and any element
941
- under `data-arcane-private` remain redacted even when optional capture is enabled.
942
- Sensitive attributes and URLs are redacted. Document URLs are represented only as
943
- `[REDACTED URL]`; event strings and node content are bounded.
944
-
945
- DOM capture is not complete application-state capture. It cannot observe closed
946
- shadow roots, cross-origin frames, CSSOM/canvas rendering, most property-only
947
- writes, native/kernel actions, external content, or activity before startup.
948
-
949
- ### Availability and normalization
950
-
951
- Browser/DOM renderer only, or a compatible test shim. Records use the same
952
- host-neutral event-stack format as semantic events.
953
-
954
- ### Example
955
-
956
- ```javascript
957
- import {createEventManager} from 'arcane-os/event-manager';
958
-
959
- const events=createEventManager({timeTravel:true,maxEvents:2_000});
960
- const dom=events.attachDOM(document,{
961
- captureEventDetails:false,
962
- captureInputValues:false,
963
- captureNodeMarkup:false
964
- });
965
-
966
- // Exercise a bounded scenario.
967
- dom.stop();
968
- const text=events.exportStack();
969
- events.clearHistory();
970
- ```
971
-
972
- ## `domSelector()`
973
-
974
- ### Overview
975
-
976
- Builds a diagnostic selector from ids, `data-arcane-id`, `data-testid`, tag names,
977
- and sibling positions. `:document` and `:shadow-root` identify roots; ` >>> ` marks
978
- an open-shadow boundary and is not a standard `querySelector()` combinator.
979
-
980
- ### Signature
981
-
982
- ```javascript
983
- domSelector(target, root)
984
- ```
985
-
986
- ### Availability and normalization
987
-
988
- Browser DOM or DOM-like test values. Returns a string or `null`.
989
-
990
- ### Example
991
-
992
- ```javascript
993
- import {domSelector} from 'arcane-os/event-manager';
994
- console.info(domSelector(button,document));
995
- ```
996
-
997
- ## `describeDOMTarget()`
998
-
999
- ### Overview
1000
-
1001
- Returns a frozen descriptor for a document, shadow root, text node, element,
1002
- global object, or generic event target. Element descriptors include selector, tag,
1003
- id, role, name, type, and private-state metadata.
1004
-
1005
- ### Signature
1006
-
1007
- ```javascript
1008
- describeDOMTarget(target, root)
1009
- ```
1010
-
1011
- ### Availability and normalization
1012
-
1013
- Browser DOM or DOM-like test values. Returns a frozen descriptor or `null`.
1014
-
1015
- ### Example
1016
-
1017
- ```javascript
1018
- import {describeDOMTarget} from 'arcane-os/event-manager';
1019
- console.info(describeDOMTarget(document.activeElement,document));
1020
- ```
1021
-
1022
- ## `DEFAULT_DOM_EVENT_TYPES`
1023
-
1024
- ### Overview
1025
-
1026
- A frozen array of 44 keyboard, composition, pointer, mouse, touch, form, focus,
1027
- clipboard, drag, selection, scroll, and wheel event names used by default DOM
1028
- instrumentation.
1029
-
1030
- ### Value
1031
-
1032
- ```javascript
1033
- const DEFAULT_DOM_EVENT_TYPES = Object.freeze([/* 44 event names */])
1034
- ```
1035
-
1036
- ### Availability and normalization
1037
-
1038
- Importable in Node and browsers; operational only with DOM event targets.
1039
-
1040
- ### Example
1041
-
1042
- ```javascript
1043
- import {DEFAULT_DOM_EVENT_TYPES} from 'arcane-os/event-manager';
1044
- const eventTypes=DEFAULT_DOM_EVENT_TYPES.filter(type=>type!=='pointermove');
1045
- ```
1046
-
1047
- ## `ARCANE_EVENT_STACK_PROTOCOL`
1048
-
1049
- ### Overview
1050
-
1051
- Identifies the immutable event-stack JSON contract.
1052
-
1053
- ### Value
1054
-
1055
- ```javascript
1056
- ARCANE_EVENT_STACK_PROTOCOL === 'arcane-event-stack/1'
1057
- ```
1058
-
1059
- ### Availability and normalization
1060
-
1061
- All JavaScript hosts; exact string, never negotiated or silently upgraded.
1062
-
1063
- ### Example
1064
-
1065
- ```javascript
1066
- if(document.protocol!==ARCANE_EVENT_STACK_PROTOCOL)throw new Error('Unsupported stack');
1067
- ```
1068
-
1069
- ## `TIME_TRAVEL_SEEK_EVENT`
1070
-
1071
- ### Overview
1072
-
1073
- Names the cursor event. Its payload is `{sessionId,sequence,record}`. The event is
1074
- delivered synchronously but is not added to the diagnostic history.
1075
-
1076
- ### Value
1077
-
1078
- ```javascript
1079
- TIME_TRAVEL_SEEK_EVENT === 'arcane.time-travel.seek'
1080
- ```
1081
-
1082
- ### Availability and normalization
1083
-
1084
- Node and browser event managers; normalized payload, no state restoration.
1085
-
1086
- ### Example
1087
-
1088
- ```javascript
1089
- events.on(TIME_TRAVEL_SEEK_EVENT,({sequence})=>timeline.select(sequence));
1090
- events.seek(0);
1091
- ```
1092
-
1093
- ## `PLAYBACK_STARTED_EVENT`
1094
-
1095
- ### Overview
1096
-
1097
- Names the lifecycle event emitted with
1098
- `{sessionId,count,fromSequence,toSequence,speed,mode}` before playback delivery.
1099
-
1100
- ### Value
1101
-
1102
- ```javascript
1103
- PLAYBACK_STARTED_EVENT === 'arcane.time-travel.playback.started'
1104
- ```
1105
-
1106
- ### Availability and normalization
1107
-
1108
- Node and browser event managers; synchronous lifecycle notification.
1109
-
1110
- ### Example
1111
-
1112
- ```javascript
1113
- events.on(PLAYBACK_STARTED_EVENT,({count})=>console.info(`Reviewing ${count}`));
1114
- ```
1115
-
1116
- ## `PLAYBACK_RECORD_EVENT`
1117
-
1118
- ### Overview
1119
-
1120
- Names the per-record event used by safe `mode:'review'` playback. Its only payload
1121
- is the immutable record.
1122
-
1123
- ### Value
1124
-
1125
- ```javascript
1126
- PLAYBACK_RECORD_EVENT === 'arcane.time-travel.playback.record'
1127
- ```
1128
-
1129
- ### Availability and normalization
1130
-
1131
- Node and browser event managers; the payload remains a normalized record.
1132
-
1133
- ### Example
1134
-
1135
- ```javascript
1136
- events.on(PLAYBACK_RECORD_EVENT,record=>timeline.append(record));
1137
- await events.playback({mode:'review'});
1138
- ```
1139
-
1140
- ## `PLAYBACK_COMPLETED_EVENT`
1141
-
1142
- ### Overview
1143
-
1144
- Names the successful terminal event. Payload:
1145
- `{sessionId,delivered,cursor,completed:true}`.
1146
-
1147
- ### Value
1148
-
1149
- ```javascript
1150
- PLAYBACK_COMPLETED_EVENT === 'arcane.time-travel.playback.completed'
1151
- ```
1152
-
1153
- ### Availability and normalization
1154
-
1155
- Node and browser event managers; immutable result payload.
1156
-
1157
- ### Example
1158
-
1159
- ```javascript
1160
- events.once(PLAYBACK_COMPLETED_EVENT,result=>console.info(result.delivered));
1161
- ```
1162
-
1163
- ## `PLAYBACK_CANCELLED_EVENT`
1164
-
1165
- ### Overview
1166
-
1167
- Names the cancelled terminal event. Payload:
1168
- `{sessionId,delivered,cursor,completed:false,error}`. Playback still rejects with
1169
- the original cancellation reason.
1170
-
1171
- ### Value
1172
-
1173
- ```javascript
1174
- PLAYBACK_CANCELLED_EVENT === 'arcane.time-travel.playback.cancelled'
1175
- ```
1176
-
1177
- ### Availability and normalization
1178
-
1179
- Node and browser event managers; immutable error snapshot in the event payload.
1180
-
1181
- ### Example
1182
-
1183
- ```javascript
1184
- events.once(PLAYBACK_CANCELLED_EVENT,({delivered})=>console.info(delivered));
1185
- controller.abort('review closed');
1186
- ```
1187
-
1188
- ## `PLAYBACK_FAILED_EVENT`
1189
-
1190
- ### Overview
1191
-
1192
- Names the failed terminal event. It uses the same failed result shape as
1193
- cancelled playback, and the original failure rejects `playback()`.
1194
-
1195
- ### Value
1196
-
1197
- ```javascript
1198
- PLAYBACK_FAILED_EVENT === 'arcane.time-travel.playback.failed'
1199
- ```
1200
-
1201
- ### Availability and normalization
1202
-
1203
- Node and browser event managers; immutable error snapshot in the event payload.
1204
-
1205
- ### Example
1206
-
1207
- ```javascript
1208
- events.once(PLAYBACK_FAILED_EVENT,({error})=>console.error(error.message));
1209
- ```
1210
-
1211
- ## `TIME_TRAVEL_OVERFLOW_EVENT`
1212
-
1213
- ### Overview
1214
-
1215
- Identifies the final retention marker added when another recordable string event
1216
- arrives after `maxEvents` ordinary records have been retained. The marker has
1217
- `source:'event-manager'`, `category:'overflow'`, no parent, completed status, and
1218
- payload `[{maxEvents,retainedEvents}]`.
1219
-
1220
- The marker becomes record `maxEvents + 1`; recording is disabled, DOM observation
1221
- is stopped without adding another lifecycle record, and the triggering application
1222
- event is still delivered live but is not recorded. The marker is written to
1223
- history; it is not separately emitted to live subscribers at overflow time.
1224
- Exactly `maxEvents` ordinary records plus this one terminal marker are retained.
1225
- `enableTimeTravel()` rejects until `clearHistory()` removes the marker and resets
1226
- the overflow state.
1227
-
1228
- ### Value
1229
-
1230
- ```javascript
1231
- TIME_TRAVEL_OVERFLOW_EVENT === 'arcane.time-travel.overflow'
1232
- ```
1233
-
1234
- ### Availability and normalization
1235
-
1236
- Node and browser event managers; deterministic terminal record in
1237
- `arcane-event-stack/1`.
1238
-
1239
- ### Example
1240
-
1241
- ```javascript
1242
- if(events.overflowed){
1243
- persistLocallyForReview(events.exportStack());
1244
- events.clearHistory();
1245
- events.enableTimeTravel();
1246
- }
1247
- ```
1248
-
1249
- ## `DOM_INTERACTION_EVENT`
1250
-
1251
- ### Overview
1252
-
1253
- Identifies captured DOM interactions. Payload includes the DOM event type,
1254
- normalized target and composed path, event flags, bounded/redacted optional
1255
- details, and an optional captured value.
1256
-
1257
- ### Value
1258
-
1259
- ```javascript
1260
- DOM_INTERACTION_EVENT === 'arcane.dom.interaction'
1261
- ```
1262
-
1263
- ### Availability and normalization
1264
-
1265
- Produced only by browser/DOM instrumentation; stored as a host-neutral record.
1266
-
1267
- ### Example
1268
-
1269
- ```javascript
1270
- const clicks=events.getEventStack({type:DOM_INTERACTION_EVENT});
1271
- ```
1272
-
1273
- ## `DOM_MUTATION_EVENT`
1274
-
1275
- ### Overview
1276
-
1277
- Identifies normalized attribute, character-data, and child-list mutations. A
1278
- mutation captured immediately after an interaction may carry that interaction's
1279
- record id as its causation id.
1280
-
1281
- ### Value
1282
-
1283
- ```javascript
1284
- DOM_MUTATION_EVENT === 'arcane.dom.mutation'
1285
- ```
1286
-
1287
- ### Availability and normalization
1288
-
1289
- Produced only by browser `MutationObserver`; stored as a host-neutral record.
1290
-
1291
- ### Example
1292
-
1293
- ```javascript
1294
- for(const record of events.getEventStack({type:DOM_MUTATION_EVENT})){
1295
- console.info(record.payload[0].mutationType);
1296
- }
1297
- ```
1298
-
1299
- ## `DOM_OBSERVATION_STARTED_EVENT`
1300
-
1301
- ### Overview
1302
-
1303
- Identifies successful DOM capture startup. Payload describes the redacted root,
1304
- event types, and capture flags.
1305
-
1306
- ### Value
1307
-
1308
- ```javascript
1309
- DOM_OBSERVATION_STARTED_EVENT === 'arcane.dom.observation.started'
1310
- ```
1311
-
1312
- ### Availability and normalization
1313
-
1314
- Browser/DOM instrumentation lifecycle record.
1315
-
1316
- ### Example
1317
-
1318
- ```javascript
1319
- events.once(DOM_OBSERVATION_STARTED_EVENT,details=>console.info(details.eventTypes.length));
1320
- ```
1321
-
1322
- ## `DOM_OBSERVATION_STOPPED_EVENT`
1323
-
1324
- ### Overview
1325
-
1326
- Identifies normal DOM capture shutdown. Payload is `{root}`. Overflow cleanup uses
1327
- `emitLifecycle:false`, so the overflow marker remains the final retained record.
1328
-
1329
- ### Value
1330
-
1331
- ```javascript
1332
- DOM_OBSERVATION_STOPPED_EVENT === 'arcane.dom.observation.stopped'
1333
- ```
1334
-
1335
- ### Availability and normalization
1336
-
1337
- Browser/DOM instrumentation lifecycle record.
1338
-
1339
- ### Example
1340
-
1341
- ```javascript
1342
- events.once(DOM_OBSERVATION_STOPPED_EVENT,()=>console.info('DOM capture stopped'));
1343
- events.disableTimeTravel();
1344
- ```
1345
-
1346
- ## Event-stack document and record shapes
1347
-
1348
- `exportStack()` and `parseEventStack()` use this document shape:
1349
-
1350
- ```javascript
1351
- {
1352
- protocol:'arcane-event-stack/1',
1353
- sessionId:'diagnostic-session',
1354
- createdAt:'2026-08-24T03:00:00.000Z',
1355
- events:[/* immutable records */]
1356
- }
1357
- ```
1358
-
1359
- Every record has exactly these fields:
1360
-
1361
- ```javascript
1362
- {
1363
- protocol,
1364
- sessionId,
1365
- id, // `${sessionId}:${sequence}`
1366
- sequence, // positive, strictly increasing safe integer
1367
- timestamp, // canonical UTC ISO timestamp
1368
- monotonicMs, // finite, non-negative number
1369
- type,
1370
- source,
1371
- category, // string or null
1372
- correlationId, // string or null
1373
- causationId, // string or null
1374
- parentSequence, // positive sequence or null
1375
- depth, // nested synchronous dispatch depth
1376
- stack, // bounded string or null
1377
- payload, // normalized array of delivered arguments
1378
- metadata, // normalized object
1379
- status, // 'dispatching', 'completed', or 'failed'
1380
- completedAt, // canonical timestamp or null
1381
- durationMs, // non-negative number or null
1382
- error // normalized error or null
1383
- }
1384
- ```
1385
-
1386
- Nested synchronous dispatch records its parent sequence and depth and derives a
1387
- causation id when one is not supplied. A record initially appears as `dispatching`
1388
- and is replaced with a completed or failed immutable record when synchronous
1389
- delivery finishes.
1390
-
1391
- Snapshot normalization never evaluates accessor properties, including own
1392
- properties that attempt to shadow the built-in behavior of dates, regular
1393
- expressions, errors, maps, sets, typed arrays, data views, or functions. It
1394
- preserves cycles as `$ref`, applies tagged forms for non-finite numbers, bigint,
1395
- symbols, functions, dates, regular expressions, errors, maps, sets, typed arrays,
1396
- array buffers, truncation, unreadable values, and capture failures, and returns
1397
- null-prototype objects. BigInt decimal text is bounded by
1398
- `maxSnapshotStringLength`, just like other generated strings.
1399
-
1400
- The minimum 64-character budget is sufficient for the SDK's generated tags and
1401
- bookkeeping. When bounded property names collide, later names use an
1402
- `$arcaneCollision:<index>` key; omitted object entries use `$arcaneTruncated`, and
1403
- bounded collections use their corresponding truncation metadata. These special,
1404
- collision, and truncation forms round-trip through `exportStack()` and
1405
- `parseEventStack()` under the same limits. Tagged values are evidence, not
1406
- executable values, and are not revived by playback.
1407
-
1408
- Safe capture is subordinate to live delivery. Snapshot accessors are represented
1409
- as unreadable rather than invoked, and a proxy trap, invalid special value, or
1410
- other snapshot failure becomes a bounded `snapshot-failed` value when possible.
1411
- If diagnostic capture itself cannot construct a record, the live synchronous
1412
- event is still delivered. A subscriber failure remains authoritative and is
1413
- re-thrown after the SDK makes a best effort to finalize its failed record.
1414
-
1415
- With the defaults `redactSensitive:true` and `captureStacks:false`, source and
1416
- error stacks are suppressed; credential-like keys and the private event fields
1417
- `key`, `data`, and `detail` become `[REDACTED]`; and URL-like strings using
1418
- `blob:`, `data:`, `file:`, `ftp:`, `ftps:`, `http:`, `https:`, `ws:`, or `wss:`
1419
- become `[REDACTED URL]`. Redaction happens before history or export. Disabling it
1420
- is an explicit diagnostic-risk decision, not a transport requirement.
1421
-
1422
- <details>
1423
- <summary>Protocol and schema details</summary>
1424
-
1425
- The durable protocol is exactly `arcane-event-stack/1`. It is independent of the
1426
- Core `arcane/1` host protocol and the CLI event-stream protocol. Import the schema
1427
- from `arcane-os/schemas/event-stack.json`; it uses JSON Schema draft 2020-12.
1428
-
1429
- ```javascript
1430
- import schema from 'arcane-os/schemas/event-stack.json' with {type:'json'};
1431
- ```
1432
-
1433
- Protocol versions are not negotiated or normalized automatically. A remote tool
1434
- must explicitly transport the JSON, preserve it as untrusted input, and call
1435
- `parseEventStack()` under suitable bounds before use. Playback does not resend
1436
- native RPC, repeat provisioning, synthesize trusted browser input, or restore a
1437
- kernel/application snapshot.
1438
-
1439
- </details>
1440
-
1441
- ## Errors and recovery
1442
-
1443
- | Operation | Error | Recovery |
1444
- | --- | --- | --- |
1445
- | `globalThis.arcaneEvents` is an accessor | `ARCANE_EVENT_AUTHORITY_ACCESSOR_COLLISION` | Remove the incompatible realm bootstrap before importing the SDK |
1446
- | Authority value is unbranded | `ARCANE_EVENT_AUTHORITY_VALUE_COLLISION` | Install no competing global value |
1447
- | Global, brand, or protocol descriptor flags differ | `ARCANE_EVENT_AUTHORITY_DESCRIPTOR_MISMATCH` | Use the exact non-enumerable/non-writable/non-configurable authority and brand contract |
1448
- | Authority brand/protocol differs | `ARCANE_EVENT_AUTHORITY_PROTOCOL_MISMATCH` | Load a compatible SDK authority protocol |
1449
- | Required authority method is absent, non-callable, or an accessor | `ARCANE_EVENT_AUTHORITY_API_MISMATCH` | Remove the incompatible authority; accessors are never evaluated for admission |
1450
- | Authority cannot be installed | `ARCANE_EVENT_AUTHORITY_INSTALL_FAILED` | Make the realm global extensible before first import |
1451
- | Source owner/options/name/event types/callback invalid | `ARCANE_EVENT_SOURCE_INVALID` | Use one owner, exact data options, valid names, and 1–256 unique declared types |
1452
- | Owner already has an active source | `ARCANE_EVENT_SOURCE_ALREADY_REGISTERED` | Reuse or dispose the current handle |
1453
- | Source is disposing or disposed | `ARCANE_EVENT_SOURCE_DISPOSED` | Stop publishing or create a new source after disposal completes |
1454
- | Source publishes/listens to an undeclared type | `ARCANE_EVENT_SOURCE_EVENT_TYPE_UNDECLARED` | Add the exact type to `eventTypes` before source creation |
1455
- | Occurrence/options invalid | `ARCANE_EVENT_OCCURRENCE_INVALID` | Use the authority-created occurrence and documented dispatch options |
1456
- | Realm occurrence sequence exhausted | `ARCANE_EVENT_OCCURRENCE_SEQUENCE_EXHAUSTED` | Start a new JavaScript realm |
1457
- | Realm source sequence exhausted | `ARCANE_EVENT_SOURCE_SEQUENCE_EXHAUSTED` | Start a new JavaScript realm |
1458
- | Compatibility detail cannot be safely admitted | `ARCANE_EVENT_COMPATIBILITY_DETAIL_INVALID` | Use a host object directly or a plain/array value with data properties only |
1459
- | Canonical listener throws | `ARCANE_EVENT_LISTENER_CALLBACK_FAILED` in a listener-error occurrence | Fix the observer; committed domain dispatch remains successful |
1460
- | Subscription type invalid | `ARCANE_EVENT_SUBSCRIPTION_TYPE_INVALID` | Use a nonempty trimmed name matching the authority event-name grammar; canonical wildcard subscription is not admitted |
1461
- | Subscription handler invalid | `ARCANE_EVENT_SUBSCRIPTION_HANDLER_INVALID` | Use a function or EventListener object |
1462
- | Subscription options invalid | `ARCANE_EVENT_SUBSCRIPTION_OPTIONS_INVALID` | Use a data-only `{once?,signal?}` record with a boolean `once` value |
1463
- | Subscription signal invalid | `ARCANE_EVENT_SUBSCRIPTION_SIGNAL_INVALID` | Pass an AbortSignal-compatible value or omit `signal` |
1464
- | EventTarget adapter input lacks a valid type or data detail | `ARCANE_EVENT_DISPATCH_EVENT_INVALID` | Pass an Event or an Event-like data object; do not use accessors |
1465
- | DOM target invalid | `ARCANE_EVENT_DOM_TARGET_INVALID` | Supply a target with `dispatchEvent` in a realm with `CustomEvent` support |
1466
- | DOM options invalid | `ARCANE_EVENT_DOM_OPTIONS_INVALID` | Use only `type`, `bubbles`, `composed`, and `cancelable`, with boolean flags |
1467
- | DOM detail conflicts with authority identifiers | `ARCANE_EVENT_DOM_DETAIL_COLLISION` | Remove conflicting `occurrenceId`, `arcaneSource`, `instanceId`, or `operationId` fields; compatibility `source` is preserved |
1468
- | Constructor flags, clocks, or session id invalid | `TypeError` | Correct types; keep session id non-empty and at most 256 characters |
1469
- | Constructor/import retention or snapshot limits invalid | `RangeError` | Use positive safe integers and keep `maxSnapshotStringLength` at least 64 |
1470
- | Clock returns invalid timestamp or monotonic value | `TypeError` | Supply a valid UTC-compatible clock and finite non-negative monotonic clock |
1471
- | Metadata is not an object; forwarded event is invalid | `TypeError` | Pass an object and a string event type |
1472
- | Subscriber throws | Original error is rethrown | Treat synchronous handlers as part of the publisher's failure boundary |
1473
- | History overflows | No exception in normal overflow; recording disables | Export, `clearHistory()`, then enable a new bounded session |
1474
- | Re-enable before clearing overflow | `Error` | Clear history first |
1475
- | Clear during dispatch/playback | `Error` | Wait for the active operation to finish |
1476
- | Stack JSON/shape/order/identity/timing/causality/overflow invalid | `TypeError` | Reject unknown, incomplete, or forged input; do not partially use it |
1477
- | Import exceeds configured bounds | `RangeError` or invalid-stack `TypeError` | Raise explicit bounds only for a trusted operational need |
1478
- | Stack range or playback mode/callback invalid | `TypeError` | Correct the options |
1479
- | Export indentation, seek position, or playback speed invalid | `RangeError` | Use documented ranges |
1480
- | Playback already active | `Error` | Await or cancel the current playback |
1481
- | Playback aborts or a callback/subscriber fails | Promise rejects after terminal lifecycle event | Handle rejection and inspect the immutable terminal error snapshot |
1482
- | DOM manager/root/options invalid or MutationObserver unavailable | `TypeError`/`RangeError` | Correct capability/options or set `captureMutations:false` |
1483
-
1484
- ## Behavioral tests
1485
-
1486
- The executable contract is covered by:
1487
-
1488
- - `test/event-manager.test.mjs`: synchronous bus compatibility, causal recording,
1489
- pollution-safe and accessor-safe snapshots, safe capture failures, redaction and
1490
- stack-suppression defaults, minimum-budget BigInt/collision/truncation round
1491
- trips, strict forged-import rejection, cursor behavior, review and event
1492
- playback, cancellation, bounded overflow, attach-at-limit cleanup, recovery,
1493
- central queue mirroring, singleton descriptor/collision admission, duplicate
1494
- module reuse, source order/privacy/lifecycle, dispatch-safe unsubscribe,
1495
- EventTarget adapters, one-way DOM projection, and observational listener
1496
- failures;
1497
- - `test/dom-event-instrumentation.test.mjs`: browser interaction/mutation capture,
1498
- open-shadow observation, privacy defaults, lifecycle, and cleanup;
1499
- - `test/contracts.test.mjs`: published schema and package-export stability;
1500
- - `test/reference-completeness.test.mjs`: public export and MDN-reference coverage.
1501
-
1502
- The overflow tests assert the boundary itself: exactly `maxEvents` ordinary
1503
- records, one final terminal marker, uninterrupted live delivery, inactive DOM
1504
- capture without a trailing stopped marker, blocked re-enable until clear, and a
1505
- strictly importable bounded export.
1506
-
1507
- Run the behavioral suite through the repository's normal gate:
1508
-
1509
- ```shell
1510
- npm run check
1511
- ```