arcane-os 0.1.0-dev.5

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 (248) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/COMMERCIAL-LICENSE.md +13 -0
  3. package/LICENSE +661 -0
  4. package/NOTICE +70 -0
  5. package/README.md +448 -0
  6. package/bin/arcane-test.mjs +741 -0
  7. package/bin/arcane.mjs +5 -0
  8. package/docs/architecture.md +234 -0
  9. package/docs/compatibility.md +36 -0
  10. package/docs/event-manager.md +166 -0
  11. package/docs/platform-targets.md +108 -0
  12. package/docs/publishing.md +203 -0
  13. package/docs/reference/README.md +117 -0
  14. package/docs/reference/arcane-ollama.md +288 -0
  15. package/docs/reference/availability-and-normalization.md +123 -0
  16. package/docs/reference/behavioral-testing.md +86 -0
  17. package/docs/reference/cli.md +569 -0
  18. package/docs/reference/core/README.md +62 -0
  19. package/docs/reference/core/arcane-ai-contracts.md +873 -0
  20. package/docs/reference/core/arcane-api.md +601 -0
  21. package/docs/reference/core/arcane-entities.md +65 -0
  22. package/docs/reference/core/arcane-events.md +134 -0
  23. package/docs/reference/core/ollama-module.md +181 -0
  24. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
  25. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
  26. package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
  27. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
  28. package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
  29. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
  30. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
  31. package/docs/reference/event-manager.md +957 -0
  32. package/docs/reference/inventory/package-api.json +2632 -0
  33. package/docs/reference/inventory/runtime-components.json +934 -0
  34. package/docs/reference/inventory/runtime-entities.json +26 -0
  35. package/docs/reference/inventory/runtime-modules.json +1249 -0
  36. package/docs/reference/protocols.md +242 -0
  37. package/docs/reference/runtime-components.md +1098 -0
  38. package/docs/reference/runtime-entities.md +303 -0
  39. package/docs/reference/runtime-modules.md +2010 -0
  40. package/docs/reference/sdk-api.md +4901 -0
  41. package/docs/roadmap.md +79 -0
  42. package/docs/work-amplification.md +124 -0
  43. package/node_modules/event-pubsub/CHANGELOG.md +55 -0
  44. package/node_modules/event-pubsub/MIGRATION.md +70 -0
  45. package/node_modules/event-pubsub/README.md +363 -0
  46. package/node_modules/event-pubsub/SECURITY.md +37 -0
  47. package/node_modules/event-pubsub/index.js +141 -0
  48. package/node_modules/event-pubsub/licence +21 -0
  49. package/node_modules/event-pubsub/package.json +59 -0
  50. package/node_modules/strong-type/README.md +408 -0
  51. package/node_modules/strong-type/assets/strong-type-header.png +0 -0
  52. package/node_modules/strong-type/index.js +1151 -0
  53. package/node_modules/strong-type/licence +21 -0
  54. package/node_modules/strong-type/node.js +125 -0
  55. package/node_modules/strong-type/package.json +61 -0
  56. package/package.json +95 -0
  57. package/runtime/ARCANE_RUNTIME_RELEASE.json +791 -0
  58. package/runtime/arcane/components/app-bar.html +468 -0
  59. package/runtime/arcane/components/assistant-panel.html +715 -0
  60. package/runtime/arcane/components/calculator.html +8 -0
  61. package/runtime/arcane/components/chart.html +655 -0
  62. package/runtime/arcane/components/chat.html +1225 -0
  63. package/runtime/arcane/components/conversation-view.html +13 -0
  64. package/runtime/arcane/components/dashboard-config.html +341 -0
  65. package/runtime/arcane/components/data-maintenance.html +112 -0
  66. package/runtime/arcane/components/data-view.html +92 -0
  67. package/runtime/arcane/components/directory-picker.html +197 -0
  68. package/runtime/arcane/components/document-inspector.html +252 -0
  69. package/runtime/arcane/components/file-drop.html +264 -0
  70. package/runtime/arcane/components/file-inspector.html +293 -0
  71. package/runtime/arcane/components/file-manager.html +1715 -0
  72. package/runtime/arcane/components/header.html +142 -0
  73. package/runtime/arcane/components/integration-settings.html +14 -0
  74. package/runtime/arcane/components/local-ai-status.html +360 -0
  75. package/runtime/arcane/components/markdown-document.html +1048 -0
  76. package/runtime/arcane/components/markdown-editor.html +360 -0
  77. package/runtime/arcane/components/media-embed.html +8 -0
  78. package/runtime/arcane/components/modal.html +402 -0
  79. package/runtime/arcane/components/output-panel.html +259 -0
  80. package/runtime/arcane/components/preferences-form.html +135 -0
  81. package/runtime/arcane/components/record-timeline.html +105 -0
  82. package/runtime/arcane/components/relationship-board.html +116 -0
  83. package/runtime/arcane/components/screen-capture.html +8 -0
  84. package/runtime/arcane/components/source-code-viewer.html +441 -0
  85. package/runtime/arcane/components/source-explanation.html +124 -0
  86. package/runtime/arcane/components/speech.html +365 -0
  87. package/runtime/arcane/components/summary-strip.html +177 -0
  88. package/runtime/arcane/components/table.html +77 -0
  89. package/runtime/arcane/components/task-progress.html +282 -0
  90. package/runtime/arcane/components/terminal-workspace.html +65 -0
  91. package/runtime/arcane/components/theme-editor.html +41 -0
  92. package/runtime/arcane/components/theme-switcher.html +46 -0
  93. package/runtime/arcane/components/unified-inbox.html +20 -0
  94. package/runtime/arcane/components/voice-transcription.html +476 -0
  95. package/runtime/arcane/components/weather-widget.html +8 -0
  96. package/runtime/arcane/components/web-navigator.html +239 -0
  97. package/runtime/arcane/css/communications.css +1 -0
  98. package/runtime/arcane/css/dashboard-config.css +45 -0
  99. package/runtime/arcane/css/document-site.css +981 -0
  100. package/runtime/arcane/css/layout.css +438 -0
  101. package/runtime/arcane/css/primitives.css +321 -0
  102. package/runtime/arcane/css/theme.css +112 -0
  103. package/runtime/arcane/css/utility-workspace.css +1 -0
  104. package/runtime/arcane/entities/ApiModelRecord.js +20 -0
  105. package/runtime/arcane/entities/Calculation.js +13 -0
  106. package/runtime/arcane/entities/Chat.js +581 -0
  107. package/runtime/arcane/entities/CommunicationMessage.js +29 -0
  108. package/runtime/arcane/entities/CommunicationThread.js +21 -0
  109. package/runtime/arcane/entities/Document.js +10 -0
  110. package/runtime/arcane/entities/File.js +143 -0
  111. package/runtime/arcane/entities/Image.js +135 -0
  112. package/runtime/arcane/entities/IntentEnvelope.js +834 -0
  113. package/runtime/arcane/entities/Preference.js +83 -0
  114. package/runtime/arcane/entities/TWiNPolicyDecision.js +1092 -0
  115. package/runtime/arcane/entities/TerminalSession.js +46 -0
  116. package/runtime/arcane/entities/Theme.js +107 -0
  117. package/runtime/arcane/entities/User.js +1046 -0
  118. package/runtime/arcane/entities/Weather.js +23 -0
  119. package/runtime/arcane/img/arcane-os-everywhere.png +0 -0
  120. package/runtime/arcane/img/arrow-left.png +0 -0
  121. package/runtime/arcane/img/arrow-right.png +0 -0
  122. package/runtime/arcane/img/doc.svg +5 -0
  123. package/runtime/arcane/img/folder.svg +4 -0
  124. package/runtime/arcane/img/image.svg +5 -0
  125. package/runtime/arcane/img/refresh.png +0 -0
  126. package/runtime/arcane/img/send.svg +9 -0
  127. package/runtime/arcane/img/trash.svg +5 -0
  128. package/runtime/arcane/img/upload.svg +5 -0
  129. package/runtime/arcane/modules/AI.js +2048 -0
  130. package/runtime/arcane/modules/AIPreferenceRuntime.js +32 -0
  131. package/runtime/arcane/modules/AIPreferenceTuple.js +92 -0
  132. package/runtime/arcane/modules/AIResponseLength.js +42 -0
  133. package/runtime/arcane/modules/AIResponseURLPolicy.js +626 -0
  134. package/runtime/arcane/modules/AnsiText.js +53 -0
  135. package/runtime/arcane/modules/ApiModelDatabase.js +25 -0
  136. package/runtime/arcane/modules/AppDataScope.js +245 -0
  137. package/runtime/arcane/modules/AppearancePreferences.js +28 -0
  138. package/runtime/arcane/modules/ArcaneCommunicationBridge.js +22 -0
  139. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +135 -0
  140. package/runtime/arcane/modules/ArcaneNetworkPolicy.js +255 -0
  141. package/runtime/arcane/modules/AsyncBoundary.js +161 -0
  142. package/runtime/arcane/modules/BrowserTestSuite.js +326 -0
  143. package/runtime/arcane/modules/CalculatorEngine.js +20 -0
  144. package/runtime/arcane/modules/CaseEvidenceIndexer.js +134 -0
  145. package/runtime/arcane/modules/ChartLibrary.js +35 -0
  146. package/runtime/arcane/modules/ChatRecords.js +13 -0
  147. package/runtime/arcane/modules/CommunicationAppController.js +43 -0
  148. package/runtime/arcane/modules/CommunicationHub.js +16 -0
  149. package/runtime/arcane/modules/CommunicationPreferences.js +13 -0
  150. package/runtime/arcane/modules/CommunicationProviderRegistry.js +16 -0
  151. package/runtime/arcane/modules/ComponentContracts.js +586 -0
  152. package/runtime/arcane/modules/ConfiguredAIChatSession.js +288 -0
  153. package/runtime/arcane/modules/ConversationActionItems.js +488 -0
  154. package/runtime/arcane/modules/ConversationClosingReport.js +274 -0
  155. package/runtime/arcane/modules/ConversationTimebox.js +527 -0
  156. package/runtime/arcane/modules/CoreLocalModelCatalog.js +255 -0
  157. package/runtime/arcane/modules/DBLS.js +171 -0
  158. package/runtime/arcane/modules/DBOPFS.js +1154 -0
  159. package/runtime/arcane/modules/DBOPFSWorker.js +116 -0
  160. package/runtime/arcane/modules/DataMaintenance.js +91 -0
  161. package/runtime/arcane/modules/DevelopmentWorkspace.js +74 -0
  162. package/runtime/arcane/modules/DirectoryPicker.js +109 -0
  163. package/runtime/arcane/modules/DocumentNavigation.js +223 -0
  164. package/runtime/arcane/modules/Errors.js +1025 -0
  165. package/runtime/arcane/modules/GifEncoder.js +29 -0
  166. package/runtime/arcane/modules/HTMLImport.js +114 -0
  167. package/runtime/arcane/modules/InMemoryCommunicationProvider.js +14 -0
  168. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +275 -0
  169. package/runtime/arcane/modules/LocalAIReadiness.js +870 -0
  170. package/runtime/arcane/modules/LocalAIReadinessController.js +156 -0
  171. package/runtime/arcane/modules/MD.js +111 -0
  172. package/runtime/arcane/modules/Mail.js +352 -0
  173. package/runtime/arcane/modules/MailTransport.mjs +180 -0
  174. package/runtime/arcane/modules/Marked.min.js +71 -0
  175. package/runtime/arcane/modules/MemoryRecords.js +44 -0
  176. package/runtime/arcane/modules/MessageAdvisory.js +38 -0
  177. package/runtime/arcane/modules/ModelDefinition.js +189 -0
  178. package/runtime/arcane/modules/Ollama.js +74 -0
  179. package/runtime/arcane/modules/OllamaModelIdentifier.js +21 -0
  180. package/runtime/arcane/modules/OllamaSettings.js +24 -0
  181. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +14 -0
  182. package/runtime/arcane/modules/PreferenceStore.js +109 -0
  183. package/runtime/arcane/modules/QRCode.min.js +1 -0
  184. package/runtime/arcane/modules/Questionnaire.js +61 -0
  185. package/runtime/arcane/modules/RecordLinkIndex.js +24 -0
  186. package/runtime/arcane/modules/RecordPassageIndex.js +222 -0
  187. package/runtime/arcane/modules/RecordReviewStore.js +94 -0
  188. package/runtime/arcane/modules/RevocableProjectionLedger.js +1623 -0
  189. package/runtime/arcane/modules/RiskSignalAnalyzer.js +37 -0
  190. package/runtime/arcane/modules/ScamRiskPolicy.js +62 -0
  191. package/runtime/arcane/modules/ScopedOPFSCache.js +183 -0
  192. package/runtime/arcane/modules/ScreenCapture.js +20 -0
  193. package/runtime/arcane/modules/SpeechPlayback.js +581 -0
  194. package/runtime/arcane/modules/StaticDocumentCatalog.js +1248 -0
  195. package/runtime/arcane/modules/SystemAppearance.js +20 -0
  196. package/runtime/arcane/modules/SystemPlatformPresentation.js +51 -0
  197. package/runtime/arcane/modules/SystemToolRegistry.js +28 -0
  198. package/runtime/arcane/modules/TerminalClient.js +52 -0
  199. package/runtime/arcane/modules/TerminalCommandRegistry.js +50 -0
  200. package/runtime/arcane/modules/ThemeBootstrap.js +26 -0
  201. package/runtime/arcane/modules/ThemeManager.js +131 -0
  202. package/runtime/arcane/modules/TimeGuard.js +149 -0
  203. package/runtime/arcane/modules/ToolCallRouter.js +83 -0
  204. package/runtime/arcane/modules/WaitForComponent.js +102 -0
  205. package/runtime/arcane/modules/YouTubeMedia.js +16 -0
  206. package/runtime/arcane/modules/uPlot.LICENSE.txt +21 -0
  207. package/runtime/arcane/modules/uPlot.iife.min.js +2 -0
  208. package/runtime/arcane/modules/uPlot.min.css +1 -0
  209. package/runtime/arcane/security/arcane-network-policy.json +6 -0
  210. package/runtime/strong-type/index.js +352 -0
  211. package/runtime/strong-type/licence +21 -0
  212. package/runtime/strong-type/package.json +45 -0
  213. package/schemas/arcane-app-bundle.schema.json +125 -0
  214. package/schemas/arcane-app.schema.json +329 -0
  215. package/schemas/arcane-lock.schema.json +86 -0
  216. package/schemas/arcane-package.schema.json +224 -0
  217. package/schemas/cli-event.schema.json +122 -0
  218. package/schemas/event-stack.schema.json +152 -0
  219. package/schemas/native-build-plan.schema.json +176 -0
  220. package/schemas/target-adapter.schema.json +117 -0
  221. package/src/app-descriptor.mjs +500 -0
  222. package/src/cli/main.mjs +561 -0
  223. package/src/constants.mjs +31 -0
  224. package/src/dev-server.mjs +718 -0
  225. package/src/doctor.mjs +315 -0
  226. package/src/dom-event-instrumentation.mjs +594 -0
  227. package/src/errors.mjs +75 -0
  228. package/src/event-manager.mjs +1342 -0
  229. package/src/event-queue.mjs +138 -0
  230. package/src/events.mjs +219 -0
  231. package/src/index.mjs +177 -0
  232. package/src/integrated-provider-loader.mjs +432 -0
  233. package/src/native-plan.mjs +698 -0
  234. package/src/native-provider-loader.mjs +1126 -0
  235. package/src/packager/core.mjs +2691 -0
  236. package/src/process.mjs +353 -0
  237. package/src/release-bundle.mjs +2523 -0
  238. package/src/repository.mjs +90 -0
  239. package/src/runtime.mjs +452 -0
  240. package/src/scaffold.mjs +380 -0
  241. package/src/targets/index.mjs +436 -0
  242. package/src/templates/assets/app-icon.png +0 -0
  243. package/src/templates/workspace-template.mjs +388 -0
  244. package/src/testing-loader.mjs +9 -0
  245. package/src/testing.mjs +427 -0
  246. package/src/toolchain.mjs +1335 -0
  247. package/src/update-check.mjs +307 -0
  248. package/src/workspace.mjs +449 -0
@@ -0,0 +1,957 @@
1
+ # EventManager and time-travel diagnostics
2
+
3
+ `EventManager` gives Arcane applications one synchronous event bus and an optional,
4
+ bounded diagnostic timeline. Use it to observe SDK operation events, add semantic
5
+ application events, capture browser interactions, export evidence, and review a
6
+ recording without implying that Arcane has restored live state.
7
+
8
+ The API is capability-first:
9
+
10
+ - ordinary pub/sub works in Node and browser JavaScript;
11
+ - recording creates immutable, normalized `arcane-event-stack/1` records;
12
+ - browser DOM capture is opt-in and privacy-preserving by default;
13
+ - review playback is safe by default; live event redispatch is explicitly effectful;
14
+ - no event stack is uploaded, persisted, bridged to Core, or sent to a cloud service
15
+ automatically.
16
+
17
+ All 20 JavaScript exports are available from both `arcane-os` and
18
+ `arcane-os/event-manager`. The bindings are identical, so choose the focused
19
+ subpath when event instrumentation is the only SDK capability you need.
20
+
21
+ ## Quick start
22
+
23
+ ```javascript
24
+ import {
25
+ arcaneEvents,
26
+ PLAYBACK_RECORD_EVENT
27
+ } from 'arcane-os/event-manager';
28
+
29
+ arcaneEvents.on('document.save.completed',event=>{
30
+ console.info('Saved',event.documentId);
31
+ });
32
+
33
+ arcaneEvents.enableTimeTravel();
34
+ try{
35
+ arcaneEvents.instrument(
36
+ 'document.save.completed',
37
+ {documentId:'example'},
38
+ {source:'app:editor',category:'operation',correlationId:'save-42'}
39
+ );
40
+ }finally{
41
+ arcaneEvents.disableTimeTravel();
42
+ }
43
+
44
+ const stack=arcaneEvents.exportStack();
45
+ arcaneEvents.on(PLAYBACK_RECORD_EVENT,record=>console.info(record.type));
46
+ await arcaneEvents.playback({stack,mode:'review',speed:0});
47
+ ```
48
+
49
+ Recording is disabled on `arcaneEvents` by default. Keep diagnostic sessions
50
+ bounded, export intentionally, then call `clearHistory()`.
51
+
52
+ ## Availability and normalization
53
+
54
+ | Capability | Node | Browser renderer | Native/Core host | Remote or cloud | Normalization |
55
+ | --- | --- | --- | --- | --- | --- |
56
+ | Pub/sub, semantic instrumentation, parse/export, seek, playback | Yes | Yes, through a bundler or import map | Only when the SDK module runs in that JavaScript host | No automatic transport | Same synchronous API; optional immutable JSON-like snapshots |
57
+ | DOM selectors and target descriptions | With DOM-like values or a test shim | Yes | No native UI observation | No | Stable diagnostic descriptors |
58
+ | DOM interaction and mutation capture | No native DOM | Yes | No | No | DOM activity becomes semantic event-stack records |
59
+ | Event-stack schema | Yes | Yes | Data contract only | Can be transported explicitly by the developer | `arcane-event-stack/1` |
60
+
61
+ An unbundled browser must serve and map `arcane-os` and `event-pubsub`. The
62
+ hash-pinned Arcane browser runtime does not automatically inject this SDK-authored
63
+ module into Shell, Provisioner, Core, or built-in apps. There is no transparent
64
+ fallback to `arcane/1`, HTTP, WebSocket, Ollama, or a cloud event service.
65
+
66
+ ## Export summary
67
+
68
+ | Export | Kind | Primary capability |
69
+ | --- | --- | --- |
70
+ | `ARCANE_EVENT_STACK_PROTOCOL` | String constant | Identify the durable stack format |
71
+ | `TIME_TRAVEL_SEEK_EVENT` | String constant | Observe review-cursor movement |
72
+ | `PLAYBACK_STARTED_EVENT` | String constant | Observe playback startup |
73
+ | `PLAYBACK_RECORD_EVENT` | String constant | Receive safe review records |
74
+ | `PLAYBACK_COMPLETED_EVENT` | String constant | Observe successful completion |
75
+ | `PLAYBACK_CANCELLED_EVENT` | String constant | Observe cancellation |
76
+ | `PLAYBACK_FAILED_EVENT` | String constant | Observe playback failure |
77
+ | `TIME_TRAVEL_OVERFLOW_EVENT` | String constant | Identify the terminal retention marker |
78
+ | `DOM_INTERACTION_EVENT` | String constant | Identify normalized DOM interactions |
79
+ | `DOM_MUTATION_EVENT` | String constant | Identify normalized DOM mutations |
80
+ | `DOM_OBSERVATION_STARTED_EVENT` | String constant | Identify DOM-capture startup |
81
+ | `DOM_OBSERVATION_STOPPED_EVENT` | String constant | Identify DOM-capture shutdown |
82
+ | `DEFAULT_DOM_EVENT_TYPES` | Frozen string array | Use Arcane's default DOM capture set |
83
+ | `domSelector()` | Function | Build a diagnostic DOM locator |
84
+ | `describeDOMTarget()` | Function | Normalize a DOM event target |
85
+ | `createDOMInstrumentation()` | Function | Attach interaction and mutation capture |
86
+ | `parseEventStack()` | Function | Strictly import and freeze a stack |
87
+ | `EventManager` | Class | Create an isolated bus and timeline |
88
+ | `createEventManager()` | Function | Create an `EventManager` |
89
+ | `arcaneEvents` | `EventManager` singleton | Observe shared SDK events |
90
+
91
+ ## `EventManager`
92
+
93
+ ### Overview
94
+
95
+ Creates an isolated synchronous `event-pubsub` bus. Time-travel recording,
96
+ snapshot capture, retention, DOM observation, import/export, cursor movement, and
97
+ playback are layered around that bus.
98
+
99
+ ### Constructor
100
+
101
+ ```javascript
102
+ new EventManager({
103
+ timeTravel=false,
104
+ dom=null,
105
+ captureStacks=false,
106
+ redactSensitive=true,
107
+ maxEvents=10_000,
108
+ maxSnapshotDepth=50,
109
+ maxSnapshotEntries=1_000,
110
+ maxSnapshotStringLength=10_000,
111
+ clock=()=>new Date(),
112
+ now=performance.now-or-Date.now,
113
+ sessionId=randomUUID-or-local-id
114
+ }={})
115
+ ```
116
+
117
+ `dom` may be a root directly or an options object containing `root`. Source and
118
+ error stacks are omitted unless `captureStacks` is true. Redaction, depth, entry,
119
+ string, and retention bounds are applied before records enter history.
120
+ `maxSnapshotStringLength` defaults to 10,000 and must be a safe integer of at
121
+ least 64; the other numeric retention limits must be positive safe integers.
122
+
123
+ ### Properties
124
+
125
+ | Property | Value |
126
+ | --- | --- |
127
+ | `list` | Underlying subscriber registry from `event-pubsub` |
128
+ | `sessionId` | Current non-empty session identifier, at most 256 characters |
129
+ | `timeTravelEnabled` | Whether new string-typed events are being recorded |
130
+ | `replaying` | Whether playback is active |
131
+ | `cursor` | Current sequence selected or delivered; `0` means before the first event |
132
+ | `eventCount` | Retained record count, including an overflow marker |
133
+ | `maxEvents` | Configured ordinary-record limit |
134
+ | `overflowed` | Whether retention ended with an overflow marker |
135
+ | `history` | Frozen array copy of immutable records |
136
+ | `domInstrumentation` | Attached DOM controller or `null` |
137
+
138
+ ### Methods
139
+
140
+ #### `on(type, handler, once=false)`
141
+
142
+ Registers a synchronous handler and returns the manager.
143
+
144
+ #### `once(type, handler)`
145
+
146
+ Registers a synchronous one-shot handler and returns the manager.
147
+
148
+ #### `off(type='*', handler='*')`
149
+
150
+ Removes matching subscriptions and returns the manager.
151
+
152
+ #### `reset()`
153
+
154
+ Clears subscriptions and returns the manager. It does not clear recorded history.
155
+
156
+ #### `emit(type, ...payload)`
157
+
158
+ Synchronously delivers arbitrary payload arguments. String event types are
159
+ recorded while time travel is enabled. Non-string types are delivered without a
160
+ record. Subscriber exceptions are recorded as a failed dispatch and rethrown.
161
+ Subscriber promises are not awaited.
162
+
163
+ ```javascript
164
+ events.on('ready',(documentId,revision)=>console.info(documentId,revision));
165
+ events.emit('ready','document-7',3);
166
+ ```
167
+
168
+ #### `instrument(type, payload, metadata={})`
169
+
170
+ Delivers one semantic payload and records optional `source`, `category`,
171
+ `correlationId`, and `causationId` metadata.
172
+
173
+ ```javascript
174
+ events.instrument('sync.completed',{count:12},{
175
+ source:'app:library',
176
+ category:'operation',
177
+ correlationId:'sync-9'
178
+ });
179
+ ```
180
+
181
+ #### `forward(event, metadata={})`
182
+
183
+ Requires a non-array object with a string `type`, then instruments that object as
184
+ the event's single payload. SDK operation queues use this shape to mirror their
185
+ already-normalized events through `arcaneEvents` once.
186
+
187
+ #### `enableTimeTravel({dom}={})`
188
+
189
+ Enables recording and optionally attaches DOM capture. An overflowed manager must
190
+ be cleared before it can be enabled again.
191
+
192
+ #### `disableTimeTravel()`
193
+
194
+ Stops attached DOM capture, records its stopped lifecycle boundary, disables
195
+ recording, and returns the manager.
196
+
197
+ #### `attachDOM(root=globalThis.document, options={})`
198
+
199
+ Stops and replaces the current DOM controller. The new controller starts
200
+ immediately when recording is enabled. Returns the controller.
201
+
202
+ Attaching at the exact retention limit causes the DOM-start event to trigger the
203
+ normal terminal overflow path. In that case the returned controller is inactive,
204
+ `timeTravelEnabled` is false, `overflowed` is true, and the final retained record
205
+ is the overflow marker. No stopped lifecycle record is appended after it.
206
+
207
+ #### `detachDOM()`
208
+
209
+ Stops DOM capture, clears the controller, and returns the manager.
210
+
211
+ #### `clearHistory({newSession=true}={})`
212
+
213
+ Clears history, sequence, cursor, and overflow state. By default it creates a new
214
+ session identifier; pass `newSession:false` to retain the existing identifier.
215
+ History cannot be cleared during synchronous dispatch or playback.
216
+
217
+ #### `getEventStack({fromSequence=1, toSequence=Number.MAX_SAFE_INTEGER, type=null}={})`
218
+
219
+ Returns a frozen array of records within the inclusive sequence range, optionally
220
+ restricted to one exact event type.
221
+
222
+ #### `exportStack({space=2}={})`
223
+
224
+ Returns a JSON document with the current session and retained history. `space`
225
+ must be a safe integer from 0 through 10. Export does not write a file, persist,
226
+ upload, or transmit anything.
227
+
228
+ #### `seek(sequence)`
229
+
230
+ Moves the review cursor to `0` or an existing sequence, emits
231
+ `TIME_TRAVEL_SEEK_EVENT`, and returns the selected record or `null` for zero.
232
+ Seeking never rewrites DOM, storage, native state, processes, or network state.
233
+
234
+ #### `playback(options={})`
235
+
236
+ ```javascript
237
+ await events.playback({
238
+ stack=null,
239
+ fromSequence=1,
240
+ toSequence=Number.MAX_SAFE_INTEGER,
241
+ speed=0,
242
+ mode='review',
243
+ signal,
244
+ onRecord
245
+ });
246
+ ```
247
+
248
+ Only one playback may run at a time. `stack:null` uses current history; a string
249
+ or object is passed through `parseEventStack()`. Recording is suppressed during
250
+ playback.
251
+
252
+ | Mode | Behavior | Safety |
253
+ | --- | --- | --- |
254
+ | `review` | Emits every immutable record as `PLAYBACK_RECORD_EVENT` | Default; intended for debugger and timeline UIs |
255
+ | `events` | Redispatches `record.type` with the normalized payload arguments | Effectful; use only in an isolated harness |
256
+ | `none` | Emits no per-record bus event; only invokes `onRecord` | Useful for controlled analysis |
257
+
258
+ `speed:0` delivers immediately. A positive speed preserves recorded monotonic
259
+ delays, divided by the multiplier. `onRecord(record)` may be async and is awaited.
260
+ An `AbortSignal` cancels waiting or delivery; playback emits exactly one terminal
261
+ completed, cancelled, or failed lifecycle event, rejects on cancellation/failure,
262
+ and restores `replaying` in all cases.
263
+
264
+ ### Availability and normalization
265
+
266
+ The class is host-neutral JavaScript in Node and browser module graphs. DOM capture
267
+ requires a browser-compatible root. Event values are delivered to live subscribers
268
+ unchanged; only the optional historical copy is normalized.
269
+
270
+ ### Example
271
+
272
+ ```javascript
273
+ import {EventManager} from 'arcane-os/event-manager';
274
+
275
+ const events=new EventManager({timeTravel:true,maxEvents:500});
276
+ events.emit('workspace.opened',{workspaceId:'local-demo'});
277
+ console.info(events.history[0].status); // "completed"
278
+ events.clearHistory();
279
+ ```
280
+
281
+ ## `createEventManager()`
282
+
283
+ ### Overview
284
+
285
+ Convenience factory equivalent to `new EventManager(options)`.
286
+
287
+ ### Signature
288
+
289
+ ```javascript
290
+ createEventManager(options)
291
+ ```
292
+
293
+ ### Availability and normalization
294
+
295
+ Node and browser JavaScript; identical behavior to the constructor.
296
+
297
+ ### Example
298
+
299
+ ```javascript
300
+ import {createEventManager} from 'arcane-os/event-manager';
301
+ const events=createEventManager({timeTravel:true,maxEvents:1_000});
302
+ ```
303
+
304
+ ## `arcaneEvents`
305
+
306
+ ### Overview
307
+
308
+ The SDK-wide `EventManager` singleton. Recording is off by default. SDK operation
309
+ queues forward each normalized event object through this manager before their
310
+ awaited callback; nested queues deduplicate the same object identity.
311
+
312
+ ### Value
313
+
314
+ ```javascript
315
+ const arcaneEvents = new EventManager()
316
+ ```
317
+
318
+ ### Availability and normalization
319
+
320
+ One singleton per resolved SDK module graph in Node or a browser bundle. It is not
321
+ a cross-process, cross-frame, Core, native, or cloud singleton.
322
+
323
+ ### Example
324
+
325
+ ```javascript
326
+ import {arcaneEvents} from 'arcane-os';
327
+ arcaneEvents.on('sdk.operation.completed',event=>console.info(event));
328
+ ```
329
+
330
+ ## `parseEventStack()`
331
+
332
+ ### Overview
333
+
334
+ Strictly imports a JSON string or data object, rejects ambiguous or malformed
335
+ structures, returns null-prototype normalized data objects, and deeply freezes the
336
+ result. Validation includes exact document/record keys, canonical timestamps,
337
+ session and record identity, status-dependent completion fields, bounded nested
338
+ values, increasing sequences, causal parent consistency, and overflow placement.
339
+
340
+ ### Signature
341
+
342
+ ```javascript
343
+ parseEventStack(source, {
344
+ maxEvents=10_000,
345
+ maxSnapshotDepth=50,
346
+ maxSnapshotEntries=1_000,
347
+ maxSnapshotStringLength=10_000
348
+ }={})
349
+ ```
350
+
351
+ All import limits must be positive safe integers, except that
352
+ `maxSnapshotStringLength` has the additional minimum of 64. A valid overflowed
353
+ stack may contain `maxEvents + 1` records only when its final record is the sole
354
+ overflow marker.
355
+
356
+ The parser binds every imported record to its enclosing document: protocol and
357
+ session must match, ids must equal `${sessionId}:${sequence}`, sequences and timing
358
+ must be valid, status must agree with completion/error fields, and parent,
359
+ depth, and causation data must form a valid earlier-record relationship. Unknown
360
+ keys, missing keys, sparse arrays, forged identities, incomplete records, and
361
+ nonterminal or forged overflow markers are rejected instead of repaired.
362
+
363
+ ### Availability and normalization
364
+
365
+ Pure host-neutral JavaScript. It performs no I/O and does not revive tagged values
366
+ into executable JavaScript types.
367
+
368
+ ### Example
369
+
370
+ ```javascript
371
+ import {parseEventStack} from 'arcane-os/event-manager';
372
+
373
+ const document=parseEventStack(receivedText,{maxEvents:2_000});
374
+ for(const record of document.events)console.info(record.sequence,record.type);
375
+ ```
376
+
377
+ ## `createDOMInstrumentation()`
378
+
379
+ ### Overview
380
+
381
+ Creates a frozen, opt-in browser controller that records capture-phase DOM
382
+ interactions and `MutationObserver` changes through an event manager. It observes
383
+ the supplied root and, by default, open shadow roots already present or later
384
+ inserted.
385
+
386
+ ### Signature
387
+
388
+ ```javascript
389
+ createDOMInstrumentation({
390
+ eventManager,
391
+ root=globalThis.document,
392
+ eventTypes=DEFAULT_DOM_EVENT_TYPES,
393
+ MutationObserver=globalThis.MutationObserver,
394
+ captureEventDetails=false,
395
+ captureInputValues=false,
396
+ captureNodeMarkup=false,
397
+ captureMutations=true,
398
+ maxValueLength=10_000,
399
+ maxSerializedNodeLength=100_000,
400
+ observeOpenShadowRoots=true
401
+ }={})
402
+ ```
403
+
404
+ The returned controller exposes `root`, `start()`, `stop({emitLifecycle=true}={})`,
405
+ `active`, and `observedRootCount`. Start and stop are idempotent. Startup rolls
406
+ back partially attached listeners on failure; shutdown retries listener/observer
407
+ cleanup and surfaces any remaining failure.
408
+
409
+ ### Privacy
410
+
411
+ Input values, detailed text-entry fields, and inserted/removed node markup are all
412
+ off by default. Password controls, password autocomplete fields, and any element
413
+ under `data-arcane-private` remain redacted even when optional capture is enabled.
414
+ Sensitive attributes and URLs are redacted. Document URLs are represented only as
415
+ `[REDACTED URL]`; event strings and node content are bounded.
416
+
417
+ DOM capture is not complete application-state capture. It cannot observe closed
418
+ shadow roots, cross-origin frames, CSSOM/canvas rendering, most property-only
419
+ writes, native/kernel actions, external content, or activity before startup.
420
+
421
+ ### Availability and normalization
422
+
423
+ Browser/DOM renderer only, or a compatible test shim. Records use the same
424
+ host-neutral event-stack format as semantic events.
425
+
426
+ ### Example
427
+
428
+ ```javascript
429
+ import {createEventManager} from 'arcane-os/event-manager';
430
+
431
+ const events=createEventManager({timeTravel:true,maxEvents:2_000});
432
+ const dom=events.attachDOM(document,{
433
+ captureEventDetails:false,
434
+ captureInputValues:false,
435
+ captureNodeMarkup:false
436
+ });
437
+
438
+ // Exercise a bounded scenario.
439
+ dom.stop();
440
+ const text=events.exportStack();
441
+ events.clearHistory();
442
+ ```
443
+
444
+ ## `domSelector()`
445
+
446
+ ### Overview
447
+
448
+ Builds a diagnostic selector from ids, `data-arcane-id`, `data-testid`, tag names,
449
+ and sibling positions. `:document` and `:shadow-root` identify roots; ` >>> ` marks
450
+ an open-shadow boundary and is not a standard `querySelector()` combinator.
451
+
452
+ ### Signature
453
+
454
+ ```javascript
455
+ domSelector(target, root)
456
+ ```
457
+
458
+ ### Availability and normalization
459
+
460
+ Browser DOM or DOM-like test values. Returns a string or `null`.
461
+
462
+ ### Example
463
+
464
+ ```javascript
465
+ import {domSelector} from 'arcane-os/event-manager';
466
+ console.info(domSelector(button,document));
467
+ ```
468
+
469
+ ## `describeDOMTarget()`
470
+
471
+ ### Overview
472
+
473
+ Returns a frozen descriptor for a document, shadow root, text node, element,
474
+ global object, or generic event target. Element descriptors include selector, tag,
475
+ id, role, name, type, and private-state metadata.
476
+
477
+ ### Signature
478
+
479
+ ```javascript
480
+ describeDOMTarget(target, root)
481
+ ```
482
+
483
+ ### Availability and normalization
484
+
485
+ Browser DOM or DOM-like test values. Returns a frozen descriptor or `null`.
486
+
487
+ ### Example
488
+
489
+ ```javascript
490
+ import {describeDOMTarget} from 'arcane-os/event-manager';
491
+ console.info(describeDOMTarget(document.activeElement,document));
492
+ ```
493
+
494
+ ## `DEFAULT_DOM_EVENT_TYPES`
495
+
496
+ ### Overview
497
+
498
+ A frozen array of 44 keyboard, composition, pointer, mouse, touch, form, focus,
499
+ clipboard, drag, selection, scroll, and wheel event names used by default DOM
500
+ instrumentation.
501
+
502
+ ### Value
503
+
504
+ ```javascript
505
+ const DEFAULT_DOM_EVENT_TYPES = Object.freeze([/* 44 event names */])
506
+ ```
507
+
508
+ ### Availability and normalization
509
+
510
+ Importable in Node and browsers; operational only with DOM event targets.
511
+
512
+ ### Example
513
+
514
+ ```javascript
515
+ import {DEFAULT_DOM_EVENT_TYPES} from 'arcane-os/event-manager';
516
+ const eventTypes=DEFAULT_DOM_EVENT_TYPES.filter(type=>type!=='pointermove');
517
+ ```
518
+
519
+ ## `ARCANE_EVENT_STACK_PROTOCOL`
520
+
521
+ ### Overview
522
+
523
+ Identifies the immutable event-stack JSON contract.
524
+
525
+ ### Value
526
+
527
+ ```javascript
528
+ ARCANE_EVENT_STACK_PROTOCOL === 'arcane-event-stack/1'
529
+ ```
530
+
531
+ ### Availability and normalization
532
+
533
+ All JavaScript hosts; exact string, never negotiated or silently upgraded.
534
+
535
+ ### Example
536
+
537
+ ```javascript
538
+ if(document.protocol!==ARCANE_EVENT_STACK_PROTOCOL)throw new Error('Unsupported stack');
539
+ ```
540
+
541
+ ## `TIME_TRAVEL_SEEK_EVENT`
542
+
543
+ ### Overview
544
+
545
+ Names the cursor event. Its payload is `{sessionId,sequence,record}`. The event is
546
+ delivered synchronously but is not added to the diagnostic history.
547
+
548
+ ### Value
549
+
550
+ ```javascript
551
+ TIME_TRAVEL_SEEK_EVENT === 'arcane.time-travel.seek'
552
+ ```
553
+
554
+ ### Availability and normalization
555
+
556
+ Node and browser event managers; normalized payload, no state restoration.
557
+
558
+ ### Example
559
+
560
+ ```javascript
561
+ events.on(TIME_TRAVEL_SEEK_EVENT,({sequence})=>timeline.select(sequence));
562
+ events.seek(0);
563
+ ```
564
+
565
+ ## `PLAYBACK_STARTED_EVENT`
566
+
567
+ ### Overview
568
+
569
+ Names the lifecycle event emitted with
570
+ `{sessionId,count,fromSequence,toSequence,speed,mode}` before playback delivery.
571
+
572
+ ### Value
573
+
574
+ ```javascript
575
+ PLAYBACK_STARTED_EVENT === 'arcane.time-travel.playback.started'
576
+ ```
577
+
578
+ ### Availability and normalization
579
+
580
+ Node and browser event managers; synchronous lifecycle notification.
581
+
582
+ ### Example
583
+
584
+ ```javascript
585
+ events.on(PLAYBACK_STARTED_EVENT,({count})=>console.info(`Reviewing ${count}`));
586
+ ```
587
+
588
+ ## `PLAYBACK_RECORD_EVENT`
589
+
590
+ ### Overview
591
+
592
+ Names the per-record event used by safe `mode:'review'` playback. Its only payload
593
+ is the immutable record.
594
+
595
+ ### Value
596
+
597
+ ```javascript
598
+ PLAYBACK_RECORD_EVENT === 'arcane.time-travel.playback.record'
599
+ ```
600
+
601
+ ### Availability and normalization
602
+
603
+ Node and browser event managers; the payload remains a normalized record.
604
+
605
+ ### Example
606
+
607
+ ```javascript
608
+ events.on(PLAYBACK_RECORD_EVENT,record=>timeline.append(record));
609
+ await events.playback({mode:'review'});
610
+ ```
611
+
612
+ ## `PLAYBACK_COMPLETED_EVENT`
613
+
614
+ ### Overview
615
+
616
+ Names the successful terminal event. Payload:
617
+ `{sessionId,delivered,cursor,completed:true}`.
618
+
619
+ ### Value
620
+
621
+ ```javascript
622
+ PLAYBACK_COMPLETED_EVENT === 'arcane.time-travel.playback.completed'
623
+ ```
624
+
625
+ ### Availability and normalization
626
+
627
+ Node and browser event managers; immutable result payload.
628
+
629
+ ### Example
630
+
631
+ ```javascript
632
+ events.once(PLAYBACK_COMPLETED_EVENT,result=>console.info(result.delivered));
633
+ ```
634
+
635
+ ## `PLAYBACK_CANCELLED_EVENT`
636
+
637
+ ### Overview
638
+
639
+ Names the cancelled terminal event. Payload:
640
+ `{sessionId,delivered,cursor,completed:false,error}`. Playback still rejects with
641
+ the original cancellation reason.
642
+
643
+ ### Value
644
+
645
+ ```javascript
646
+ PLAYBACK_CANCELLED_EVENT === 'arcane.time-travel.playback.cancelled'
647
+ ```
648
+
649
+ ### Availability and normalization
650
+
651
+ Node and browser event managers; immutable error snapshot in the event payload.
652
+
653
+ ### Example
654
+
655
+ ```javascript
656
+ events.once(PLAYBACK_CANCELLED_EVENT,({delivered})=>console.info(delivered));
657
+ controller.abort('review closed');
658
+ ```
659
+
660
+ ## `PLAYBACK_FAILED_EVENT`
661
+
662
+ ### Overview
663
+
664
+ Names the failed terminal event. It uses the same failed result shape as
665
+ cancelled playback, and the original failure rejects `playback()`.
666
+
667
+ ### Value
668
+
669
+ ```javascript
670
+ PLAYBACK_FAILED_EVENT === 'arcane.time-travel.playback.failed'
671
+ ```
672
+
673
+ ### Availability and normalization
674
+
675
+ Node and browser event managers; immutable error snapshot in the event payload.
676
+
677
+ ### Example
678
+
679
+ ```javascript
680
+ events.once(PLAYBACK_FAILED_EVENT,({error})=>console.error(error.message));
681
+ ```
682
+
683
+ ## `TIME_TRAVEL_OVERFLOW_EVENT`
684
+
685
+ ### Overview
686
+
687
+ Identifies the final retention marker added when another recordable string event
688
+ arrives after `maxEvents` ordinary records have been retained. The marker has
689
+ `source:'event-manager'`, `category:'overflow'`, no parent, completed status, and
690
+ payload `[{maxEvents,retainedEvents}]`.
691
+
692
+ The marker becomes record `maxEvents + 1`; recording is disabled, DOM observation
693
+ is stopped without adding another lifecycle record, and the triggering application
694
+ event is still delivered live but is not recorded. The marker is written to
695
+ history; it is not separately emitted to live subscribers at overflow time.
696
+ Exactly `maxEvents` ordinary records plus this one terminal marker are retained.
697
+ `enableTimeTravel()` rejects until `clearHistory()` removes the marker and resets
698
+ the overflow state.
699
+
700
+ ### Value
701
+
702
+ ```javascript
703
+ TIME_TRAVEL_OVERFLOW_EVENT === 'arcane.time-travel.overflow'
704
+ ```
705
+
706
+ ### Availability and normalization
707
+
708
+ Node and browser event managers; deterministic terminal record in
709
+ `arcane-event-stack/1`.
710
+
711
+ ### Example
712
+
713
+ ```javascript
714
+ if(events.overflowed){
715
+ persistLocallyForReview(events.exportStack());
716
+ events.clearHistory();
717
+ events.enableTimeTravel();
718
+ }
719
+ ```
720
+
721
+ ## `DOM_INTERACTION_EVENT`
722
+
723
+ ### Overview
724
+
725
+ Identifies captured DOM interactions. Payload includes the DOM event type,
726
+ normalized target and composed path, event flags, bounded/redacted optional
727
+ details, and an optional captured value.
728
+
729
+ ### Value
730
+
731
+ ```javascript
732
+ DOM_INTERACTION_EVENT === 'arcane.dom.interaction'
733
+ ```
734
+
735
+ ### Availability and normalization
736
+
737
+ Produced only by browser/DOM instrumentation; stored as a host-neutral record.
738
+
739
+ ### Example
740
+
741
+ ```javascript
742
+ const clicks=events.getEventStack({type:DOM_INTERACTION_EVENT});
743
+ ```
744
+
745
+ ## `DOM_MUTATION_EVENT`
746
+
747
+ ### Overview
748
+
749
+ Identifies normalized attribute, character-data, and child-list mutations. A
750
+ mutation captured immediately after an interaction may carry that interaction's
751
+ record id as its causation id.
752
+
753
+ ### Value
754
+
755
+ ```javascript
756
+ DOM_MUTATION_EVENT === 'arcane.dom.mutation'
757
+ ```
758
+
759
+ ### Availability and normalization
760
+
761
+ Produced only by browser `MutationObserver`; stored as a host-neutral record.
762
+
763
+ ### Example
764
+
765
+ ```javascript
766
+ for(const record of events.getEventStack({type:DOM_MUTATION_EVENT})){
767
+ console.info(record.payload[0].mutationType);
768
+ }
769
+ ```
770
+
771
+ ## `DOM_OBSERVATION_STARTED_EVENT`
772
+
773
+ ### Overview
774
+
775
+ Identifies successful DOM capture startup. Payload describes the redacted root,
776
+ event types, and capture flags.
777
+
778
+ ### Value
779
+
780
+ ```javascript
781
+ DOM_OBSERVATION_STARTED_EVENT === 'arcane.dom.observation.started'
782
+ ```
783
+
784
+ ### Availability and normalization
785
+
786
+ Browser/DOM instrumentation lifecycle record.
787
+
788
+ ### Example
789
+
790
+ ```javascript
791
+ events.once(DOM_OBSERVATION_STARTED_EVENT,details=>console.info(details.eventTypes.length));
792
+ ```
793
+
794
+ ## `DOM_OBSERVATION_STOPPED_EVENT`
795
+
796
+ ### Overview
797
+
798
+ Identifies normal DOM capture shutdown. Payload is `{root}`. Overflow cleanup uses
799
+ `emitLifecycle:false`, so the overflow marker remains the final retained record.
800
+
801
+ ### Value
802
+
803
+ ```javascript
804
+ DOM_OBSERVATION_STOPPED_EVENT === 'arcane.dom.observation.stopped'
805
+ ```
806
+
807
+ ### Availability and normalization
808
+
809
+ Browser/DOM instrumentation lifecycle record.
810
+
811
+ ### Example
812
+
813
+ ```javascript
814
+ events.once(DOM_OBSERVATION_STOPPED_EVENT,()=>console.info('DOM capture stopped'));
815
+ events.disableTimeTravel();
816
+ ```
817
+
818
+ ## Event-stack document and record shapes
819
+
820
+ `exportStack()` and `parseEventStack()` use this document shape:
821
+
822
+ ```javascript
823
+ {
824
+ protocol:'arcane-event-stack/1',
825
+ sessionId:'diagnostic-session',
826
+ createdAt:'2026-08-24T03:00:00.000Z',
827
+ events:[/* immutable records */]
828
+ }
829
+ ```
830
+
831
+ Every record has exactly these fields:
832
+
833
+ ```javascript
834
+ {
835
+ protocol,
836
+ sessionId,
837
+ id, // `${sessionId}:${sequence}`
838
+ sequence, // positive, strictly increasing safe integer
839
+ timestamp, // canonical UTC ISO timestamp
840
+ monotonicMs, // finite, non-negative number
841
+ type,
842
+ source,
843
+ category, // string or null
844
+ correlationId, // string or null
845
+ causationId, // string or null
846
+ parentSequence, // positive sequence or null
847
+ depth, // nested synchronous dispatch depth
848
+ stack, // bounded string or null
849
+ payload, // normalized array of delivered arguments
850
+ metadata, // normalized object
851
+ status, // 'dispatching', 'completed', or 'failed'
852
+ completedAt, // canonical timestamp or null
853
+ durationMs, // non-negative number or null
854
+ error // normalized error or null
855
+ }
856
+ ```
857
+
858
+ Nested synchronous dispatch records its parent sequence and depth and derives a
859
+ causation id when one is not supplied. A record initially appears as `dispatching`
860
+ and is replaced with a completed or failed immutable record when synchronous
861
+ delivery finishes.
862
+
863
+ Snapshot normalization never evaluates accessor properties, including own
864
+ properties that attempt to shadow the built-in behavior of dates, regular
865
+ expressions, errors, maps, sets, typed arrays, data views, or functions. It
866
+ preserves cycles as `$ref`, applies tagged forms for non-finite numbers, bigint,
867
+ symbols, functions, dates, regular expressions, errors, maps, sets, typed arrays,
868
+ array buffers, truncation, unreadable values, and capture failures, and returns
869
+ null-prototype objects. BigInt decimal text is bounded by
870
+ `maxSnapshotStringLength`, just like other generated strings.
871
+
872
+ The minimum 64-character budget is sufficient for the SDK's generated tags and
873
+ bookkeeping. When bounded property names collide, later names use an
874
+ `$arcaneCollision:<index>` key; omitted object entries use `$arcaneTruncated`, and
875
+ bounded collections use their corresponding truncation metadata. These special,
876
+ collision, and truncation forms round-trip through `exportStack()` and
877
+ `parseEventStack()` under the same limits. Tagged values are evidence, not
878
+ executable values, and are not revived by playback.
879
+
880
+ Safe capture is subordinate to live delivery. Snapshot accessors are represented
881
+ as unreadable rather than invoked, and a proxy trap, invalid special value, or
882
+ other snapshot failure becomes a bounded `snapshot-failed` value when possible.
883
+ If diagnostic capture itself cannot construct a record, the live synchronous
884
+ event is still delivered. A subscriber failure remains authoritative and is
885
+ re-thrown after the SDK makes a best effort to finalize its failed record.
886
+
887
+ With the defaults `redactSensitive:true` and `captureStacks:false`, source and
888
+ error stacks are suppressed; credential-like keys and the private event fields
889
+ `key`, `data`, and `detail` become `[REDACTED]`; and URL-like strings using
890
+ `blob:`, `data:`, `file:`, `ftp:`, `ftps:`, `http:`, `https:`, `ws:`, or `wss:`
891
+ become `[REDACTED URL]`. Redaction happens before history or export. Disabling it
892
+ is an explicit diagnostic-risk decision, not a transport requirement.
893
+
894
+ <details>
895
+ <summary>Protocol and schema details</summary>
896
+
897
+ The durable protocol is exactly `arcane-event-stack/1`. It is independent of the
898
+ Core `arcane/1` host protocol and the CLI event-stream protocol. Import the schema
899
+ from `arcane-os/schemas/event-stack.json`; it uses JSON Schema draft 2020-12.
900
+
901
+ ```javascript
902
+ import schema from 'arcane-os/schemas/event-stack.json' with {type:'json'};
903
+ ```
904
+
905
+ Protocol versions are not negotiated or normalized automatically. A remote tool
906
+ must explicitly transport the JSON, preserve it as untrusted input, and call
907
+ `parseEventStack()` under suitable bounds before use. Playback does not resend
908
+ native RPC, repeat provisioning, synthesize trusted browser input, or restore a
909
+ kernel/application snapshot.
910
+
911
+ </details>
912
+
913
+ ## Errors and recovery
914
+
915
+ | Operation | Error | Recovery |
916
+ | --- | --- | --- |
917
+ | Constructor flags, clocks, or session id invalid | `TypeError` | Correct types; keep session id non-empty and at most 256 characters |
918
+ | Constructor/import retention or snapshot limits invalid | `RangeError` | Use positive safe integers and keep `maxSnapshotStringLength` at least 64 |
919
+ | Clock returns invalid timestamp or monotonic value | `TypeError` | Supply a valid UTC-compatible clock and finite non-negative monotonic clock |
920
+ | Metadata is not an object; forwarded event is invalid | `TypeError` | Pass an object and a string event type |
921
+ | Subscriber throws | Original error is rethrown | Treat synchronous handlers as part of the publisher's failure boundary |
922
+ | History overflows | No exception in normal overflow; recording disables | Export, `clearHistory()`, then enable a new bounded session |
923
+ | Re-enable before clearing overflow | `Error` | Clear history first |
924
+ | Clear during dispatch/playback | `Error` | Wait for the active operation to finish |
925
+ | Stack JSON/shape/order/identity/timing/causality/overflow invalid | `TypeError` | Reject unknown, incomplete, or forged input; do not partially use it |
926
+ | Import exceeds configured bounds | `RangeError` or invalid-stack `TypeError` | Raise explicit bounds only for a trusted operational need |
927
+ | Stack range or playback mode/callback invalid | `TypeError` | Correct the options |
928
+ | Export indentation, seek position, or playback speed invalid | `RangeError` | Use documented ranges |
929
+ | Playback already active | `Error` | Await or cancel the current playback |
930
+ | Playback aborts or a callback/subscriber fails | Promise rejects after terminal lifecycle event | Handle rejection and inspect the immutable terminal error snapshot |
931
+ | DOM manager/root/options invalid or MutationObserver unavailable | `TypeError`/`RangeError` | Correct capability/options or set `captureMutations:false` |
932
+
933
+ ## Behavioral tests
934
+
935
+ The executable contract is covered by:
936
+
937
+ - `test/event-manager.test.mjs`: synchronous bus compatibility, causal recording,
938
+ pollution-safe and accessor-safe snapshots, safe capture failures, redaction and
939
+ stack-suppression defaults, minimum-budget BigInt/collision/truncation round
940
+ trips, strict forged-import rejection, cursor behavior, review and event
941
+ playback, cancellation, bounded overflow, attach-at-limit cleanup, recovery,
942
+ and central queue mirroring;
943
+ - `test/dom-event-instrumentation.test.mjs`: browser interaction/mutation capture,
944
+ open-shadow observation, privacy defaults, lifecycle, and cleanup;
945
+ - `test/contracts.test.mjs`: published schema and package-export stability;
946
+ - `test/reference-completeness.test.mjs`: public export and MDN-reference coverage.
947
+
948
+ The overflow tests assert the boundary itself: exactly `maxEvents` ordinary
949
+ records, one final terminal marker, uninterrupted live delivery, inactive DOM
950
+ capture without a trailing stopped marker, blocked re-enable until clear, and a
951
+ strictly importable bounded export.
952
+
953
+ Run the behavioral suite through the repository's normal gate:
954
+
955
+ ```shell
956
+ npm run check
957
+ ```